2021-03-25 14:22:43 +00:00
|
|
|
import { faTrash, faWrench } from "@fortawesome/free-solid-svg-icons";
|
2021-03-28 15:27:13 +00:00
|
|
|
import { cloneDeep } from "lodash";
|
2021-03-25 14:22:43 +00:00
|
|
|
import React, {
|
|
|
|
FunctionComponent,
|
|
|
|
useCallback,
|
|
|
|
useMemo,
|
|
|
|
useState,
|
|
|
|
} from "react";
|
|
|
|
import { Badge, Button, ButtonGroup } from "react-bootstrap";
|
|
|
|
import { Column, TableUpdater } from "react-table";
|
2021-08-14 12:59:08 +00:00
|
|
|
import { useEnabledLanguagesContext, useProfilesContext } from ".";
|
2021-03-25 14:22:43 +00:00
|
|
|
import { ActionButton, SimpleTable, useShowModal } from "../../components";
|
|
|
|
import { useSingleUpdate } from "../components";
|
|
|
|
import { languageProfileKey } from "../keys";
|
|
|
|
import Modal from "./modal";
|
|
|
|
import { anyCutoff } from "./options";
|
|
|
|
|
|
|
|
const Table: FunctionComponent = () => {
|
2021-08-14 12:59:08 +00:00
|
|
|
const originalProfiles = useProfilesContext();
|
2021-03-25 14:22:43 +00:00
|
|
|
|
2021-08-14 12:59:08 +00:00
|
|
|
const languages = useEnabledLanguagesContext();
|
2021-04-04 17:18:43 +00:00
|
|
|
|
2021-03-28 15:27:13 +00:00
|
|
|
const [profiles, setProfiles] = useState(() => cloneDeep(originalProfiles));
|
2021-03-25 14:22:43 +00:00
|
|
|
|
|
|
|
const nextProfileId = useMemo(
|
|
|
|
() =>
|
|
|
|
1 +
|
|
|
|
profiles.reduce<number>((val, prof) => Math.max(prof.profileId, val), 0),
|
|
|
|
[profiles]
|
|
|
|
);
|
|
|
|
|
|
|
|
const update = useSingleUpdate();
|
|
|
|
|
|
|
|
const showModal = useShowModal();
|
|
|
|
|
|
|
|
const submitProfiles = useCallback(
|
2021-08-14 12:59:08 +00:00
|
|
|
(list: Language.Profile[]) => {
|
2021-03-25 14:22:43 +00:00
|
|
|
update(list, languageProfileKey);
|
|
|
|
setProfiles(list);
|
|
|
|
},
|
|
|
|
[update]
|
|
|
|
);
|
|
|
|
|
|
|
|
const updateProfile = useCallback(
|
2021-08-14 12:59:08 +00:00
|
|
|
(profile: Language.Profile) => {
|
2021-03-25 14:22:43 +00:00
|
|
|
const list = [...profiles];
|
|
|
|
const idx = list.findIndex((v) => v.profileId === profile.profileId);
|
|
|
|
|
|
|
|
if (idx !== -1) {
|
|
|
|
list[idx] = profile;
|
|
|
|
} else {
|
|
|
|
list.push(profile);
|
|
|
|
}
|
|
|
|
submitProfiles(list);
|
|
|
|
},
|
|
|
|
[profiles, submitProfiles]
|
|
|
|
);
|
|
|
|
|
2021-08-14 12:59:08 +00:00
|
|
|
const updateRow = useCallback<TableUpdater<Language.Profile>>(
|
|
|
|
(row, item?: Language.Profile) => {
|
2021-03-25 14:22:43 +00:00
|
|
|
if (item) {
|
2021-03-28 15:27:13 +00:00
|
|
|
showModal("profile", cloneDeep(item));
|
2021-03-25 14:22:43 +00:00
|
|
|
} else {
|
|
|
|
const list = [...profiles];
|
|
|
|
list.splice(row.index, 1);
|
|
|
|
submitProfiles(list);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
[submitProfiles, showModal, profiles]
|
|
|
|
);
|
|
|
|
|
2021-08-14 12:59:08 +00:00
|
|
|
const columns = useMemo<Column<Language.Profile>[]>(
|
2021-03-25 14:22:43 +00:00
|
|
|
() => [
|
|
|
|
{
|
|
|
|
Header: "Name",
|
|
|
|
accessor: "name",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Header: "Languages",
|
|
|
|
accessor: "items",
|
|
|
|
Cell: (row) => {
|
|
|
|
const items = row.value;
|
|
|
|
const cutoff = row.row.original.cutoff;
|
|
|
|
return items.map((v) => {
|
|
|
|
const isCutoff = v.id === cutoff || cutoff === anyCutoff;
|
|
|
|
return (
|
|
|
|
<ItemBadge
|
|
|
|
key={v.id}
|
|
|
|
cutoff={isCutoff}
|
|
|
|
className="mx-1"
|
|
|
|
item={v}
|
|
|
|
></ItemBadge>
|
|
|
|
);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
},
|
2021-12-11 12:44:53 +00:00
|
|
|
{
|
|
|
|
Header: "Must contain",
|
|
|
|
accessor: "mustContain",
|
|
|
|
Cell: (row) => {
|
|
|
|
const items = row.value;
|
|
|
|
if (!items) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return items.map((v) => {
|
|
|
|
return (
|
|
|
|
<Badge className={"mx-1"} variant={"secondary"}>
|
|
|
|
{v}
|
|
|
|
</Badge>
|
|
|
|
);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Header: "Must not contain",
|
|
|
|
accessor: "mustNotContain",
|
|
|
|
Cell: (row) => {
|
|
|
|
const items = row.value;
|
|
|
|
if (!items) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return items.map((v) => {
|
|
|
|
return (
|
|
|
|
<Badge className={"mx-1"} variant={"secondary"}>
|
|
|
|
{v}
|
|
|
|
</Badge>
|
|
|
|
);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
},
|
2021-03-25 14:22:43 +00:00
|
|
|
{
|
|
|
|
accessor: "profileId",
|
2021-08-22 12:03:36 +00:00
|
|
|
Cell: ({ row, update }) => {
|
2021-03-25 14:22:43 +00:00
|
|
|
const profile = row.original;
|
|
|
|
|
|
|
|
return (
|
|
|
|
<ButtonGroup>
|
|
|
|
<ActionButton
|
|
|
|
icon={faWrench}
|
|
|
|
onClick={() => {
|
2021-08-22 12:03:36 +00:00
|
|
|
update && update(row, profile);
|
2021-03-25 14:22:43 +00:00
|
|
|
}}
|
|
|
|
></ActionButton>
|
|
|
|
<ActionButton
|
|
|
|
icon={faTrash}
|
2021-08-22 12:03:36 +00:00
|
|
|
onClick={() => update && update(row)}
|
2021-03-25 14:22:43 +00:00
|
|
|
></ActionButton>
|
|
|
|
</ButtonGroup>
|
|
|
|
);
|
|
|
|
},
|
|
|
|
},
|
|
|
|
],
|
|
|
|
[]
|
|
|
|
);
|
|
|
|
|
2021-04-04 17:18:43 +00:00
|
|
|
const canAdd = languages.length !== 0;
|
|
|
|
|
2021-03-25 14:22:43 +00:00
|
|
|
return (
|
|
|
|
<React.Fragment>
|
|
|
|
<SimpleTable
|
|
|
|
columns={columns}
|
|
|
|
data={profiles}
|
2021-08-22 12:03:36 +00:00
|
|
|
update={updateRow}
|
2021-03-25 14:22:43 +00:00
|
|
|
></SimpleTable>
|
|
|
|
<Button
|
|
|
|
block
|
2021-04-04 17:18:43 +00:00
|
|
|
disabled={!canAdd}
|
2021-03-25 14:22:43 +00:00
|
|
|
variant="light"
|
|
|
|
onClick={() => {
|
|
|
|
const profile = {
|
|
|
|
profileId: nextProfileId,
|
|
|
|
name: "",
|
|
|
|
items: [],
|
|
|
|
cutoff: null,
|
|
|
|
};
|
|
|
|
showModal("profile", profile);
|
|
|
|
}}
|
|
|
|
>
|
2021-04-04 17:18:43 +00:00
|
|
|
{canAdd ? "Add New Profile" : "No Enabled Languages"}
|
2021-03-25 14:22:43 +00:00
|
|
|
</Button>
|
|
|
|
<Modal update={updateProfile} modalKey="profile"></Modal>
|
|
|
|
</React.Fragment>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
interface ItemProps {
|
|
|
|
className?: string;
|
2021-08-14 12:59:08 +00:00
|
|
|
item: Language.ProfileItem;
|
2021-03-25 14:22:43 +00:00
|
|
|
cutoff: boolean;
|
|
|
|
}
|
|
|
|
|
|
|
|
const ItemBadge: FunctionComponent<ItemProps> = ({
|
|
|
|
cutoff,
|
|
|
|
item,
|
|
|
|
className,
|
|
|
|
}) => {
|
|
|
|
const text = useMemo(() => {
|
|
|
|
let result = item.language;
|
|
|
|
if (item.hi === "True") {
|
|
|
|
result += ":HI";
|
|
|
|
} else if (item.forced === "True") {
|
|
|
|
result += ":Forced";
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}, [item.hi, item.forced, item.language]);
|
|
|
|
return (
|
|
|
|
<Badge
|
|
|
|
className={className}
|
|
|
|
title={cutoff ? "Ignore others if this one is available" : undefined}
|
|
|
|
variant={cutoff ? "primary" : "secondary"}
|
|
|
|
>
|
|
|
|
{text}
|
|
|
|
</Badge>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
export default Table;
|