You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
103 lines
3.0 KiB
103 lines
3.0 KiB
3 years ago
|
import { useIsAnyMutationRunning, useLanguageProfiles } from "@/apis/hooks";
|
||
2 years ago
|
import { SimpleTable, Toolbox } from "@/components";
|
||
|
import { Selector } from "@/components/inputs";
|
||
|
import { useCustomSelection } from "@/components/tables/plugins";
|
||
|
import { GetItemId, useSelectorOptions } from "@/utilities";
|
||
3 years ago
|
import { faCheck, faUndo } from "@fortawesome/free-solid-svg-icons";
|
||
2 years ago
|
import { Container } from "@mantine/core";
|
||
3 years ago
|
import { uniqBy } from "lodash";
|
||
|
import { useCallback, useMemo, useState } from "react";
|
||
|
import { UseMutationResult } from "react-query";
|
||
|
import { useNavigate } from "react-router-dom";
|
||
|
import { Column, useRowSelect } from "react-table";
|
||
|
|
||
|
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]
|
||
|
);
|
||
|
|
||
2 years ago
|
const profileOptions = useSelectorOptions(profiles ?? [], (v) => v.name);
|
||
3 years ago
|
|
||
|
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(
|
||
2 years ago
|
(profile: Language.Profile | null) => {
|
||
|
const id = profile?.profileId ?? null;
|
||
3 years ago
|
const newItems = selections.map((v) => ({ ...v, profileId: id }));
|
||
|
|
||
|
setDirties((dirty) => {
|
||
|
return uniqBy([...newItems, ...dirty], GetItemId);
|
||
|
});
|
||
|
},
|
||
|
[selections]
|
||
|
);
|
||
|
return (
|
||
2 years ago
|
<Container fluid px={0}>
|
||
|
<Toolbox>
|
||
|
<div>
|
||
|
<Selector
|
||
|
placeholder="Change Profile"
|
||
|
{...profileOptions}
|
||
|
disabled={selections.length === 0}
|
||
|
onChange={setProfiles}
|
||
|
></Selector>
|
||
|
</div>
|
||
|
<div>
|
||
|
<Toolbox.Button icon={faUndo} onClick={onEnded}>
|
||
3 years ago
|
Cancel
|
||
2 years ago
|
</Toolbox.Button>
|
||
|
<Toolbox.MutateButton
|
||
3 years ago
|
icon={faCheck}
|
||
|
disabled={dirties.length === 0 || hasTask}
|
||
|
promise={save}
|
||
|
onSuccess={onEnded}
|
||
|
>
|
||
|
Save
|
||
2 years ago
|
</Toolbox.MutateButton>
|
||
|
</div>
|
||
|
</Toolbox>
|
||
|
<SimpleTable
|
||
|
columns={columns}
|
||
|
data={data}
|
||
|
onSelect={setSelections}
|
||
|
plugins={[useRowSelect, useCustomSelection]}
|
||
|
></SimpleTable>
|
||
3 years ago
|
</Container>
|
||
|
);
|
||
|
}
|
||
|
|
||
|
export default MassEditor;
|