diff options
author | Liang Yi <[email protected]> | 2022-03-16 14:26:15 +0800 |
---|---|---|
committer | GitHub <[email protected]> | 2022-03-16 14:26:15 +0800 |
commit | 50a252fdd7e5652d344e9f1eb82ff755d55fe8a5 (patch) | |
tree | 204a1fd629f29e1be7e987820b3f829f4c54377d /frontend/src/components/MassEditor.tsx | |
parent | f81972b291b73f5771c40359f18d6470b23e2650 (diff) | |
download | bazarr-50a252fdd7e5652d344e9f1eb82ff755d55fe8a5.tar.gz bazarr-50a252fdd7e5652d344e9f1eb82ff755d55fe8a5.zip |
Frontend improvement and cleanup (#1690)
* Replace Create-React-App with Vite.js
* Update React-Router to v6
* Cleanup unused codes
Diffstat (limited to 'frontend/src/components/MassEditor.tsx')
-rw-r--r-- | frontend/src/components/MassEditor.tsx | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/frontend/src/components/MassEditor.tsx b/frontend/src/components/MassEditor.tsx new file mode 100644 index 000000000..9a6fdb0e3 --- /dev/null +++ b/frontend/src/components/MassEditor.tsx @@ -0,0 +1,121 @@ +import { useIsAnyMutationRunning, useLanguageProfiles } from "@/apis/hooks"; +import { GetItemId } from "@/utilities"; +import { faCheck, faUndo } from "@fortawesome/free-solid-svg-icons"; +import { uniqBy } from "lodash"; +import { useCallback, useMemo, useState } from "react"; +import { Container, Dropdown, Row } from "react-bootstrap"; +import { UseMutationResult } from "react-query"; +import { useNavigate } from "react-router-dom"; +import { Column, useRowSelect } from "react-table"; +import { ContentHeader, SimpleTable } from "."; +import { useCustomSelection } from "./tables/plugins"; + +interface MassEditorProps<T extends Item.Base = Item.Base> { + columns: Column<T>[]; + data: T[]; + mutation: UseMutationResult<void, unknown, FormType.ModifyItem>; +} + +function MassEditor<T extends Item.Base>(props: MassEditorProps<T>) { + const { columns, data: raw, mutation } = props; + + const [selections, setSelections] = useState<T[]>([]); + const [dirties, setDirties] = useState<T[]>([]); + const hasTask = useIsAnyMutationRunning(); + const { data: profiles } = useLanguageProfiles(); + + const navigate = useNavigate(); + + const onEnded = useCallback(() => navigate(".."), [navigate]); + + const data = useMemo( + () => uniqBy([...dirties, ...(raw ?? [])], GetItemId), + [dirties, raw] + ); + + const profileOptions = useMemo(() => { + const items: JSX.Element[] = []; + if (profiles) { + items.push( + <Dropdown.Item key="clear-profile">Clear Profile</Dropdown.Item> + ); + items.push(<Dropdown.Divider key="dropdown-divider"></Dropdown.Divider>); + items.push( + ...profiles.map((v) => ( + <Dropdown.Item key={v.profileId} eventKey={v.profileId.toString()}> + {v.name} + </Dropdown.Item> + )) + ); + } + + return items; + }, [profiles]); + + const { mutateAsync } = mutation; + + const save = useCallback(() => { + const form: FormType.ModifyItem = { + id: [], + profileid: [], + }; + dirties.forEach((v) => { + const id = GetItemId(v); + if (id) { + form.id.push(id); + form.profileid.push(v.profileId); + } + }); + return mutateAsync(form); + }, [dirties, mutateAsync]); + + const setProfiles = useCallback( + (key: Nullable<string>) => { + const id = key ? parseInt(key) : null; + + const newItems = selections.map((v) => ({ ...v, profileId: id })); + + setDirties((dirty) => { + return uniqBy([...newItems, ...dirty], GetItemId); + }); + }, + [selections] + ); + return ( + <Container fluid> + <ContentHeader scroll={false}> + <ContentHeader.Group pos="start"> + <Dropdown onSelect={setProfiles}> + <Dropdown.Toggle disabled={selections.length === 0} variant="light"> + Change Profile + </Dropdown.Toggle> + <Dropdown.Menu>{profileOptions}</Dropdown.Menu> + </Dropdown> + </ContentHeader.Group> + <ContentHeader.Group pos="end"> + <ContentHeader.Button icon={faUndo} onClick={onEnded}> + Cancel + </ContentHeader.Button> + <ContentHeader.AsyncButton + icon={faCheck} + disabled={dirties.length === 0 || hasTask} + promise={save} + onSuccess={onEnded} + > + Save + </ContentHeader.AsyncButton> + </ContentHeader.Group> + </ContentHeader> + <Row> + <SimpleTable + columns={columns} + data={data} + onSelect={setSelections} + plugins={[useRowSelect, useCustomSelection]} + ></SimpleTable> + </Row> + </Container> + ); +} + +export default MassEditor; |