276 lines
8.3 KiB
TypeScript
276 lines
8.3 KiB
TypeScript
import Joi from "joi";
|
|
import React, { useEffect } from "react";
|
|
import { Navigate, useParams } from "react-router-dom";
|
|
import { toast } from "react-toastify";
|
|
import { useTranslation } from "react-i18next";
|
|
import { Namespaces } from "../../../i18n/i18n";
|
|
import { InputType } from "../../../components/common/Input";
|
|
import { GeneralIdRef, MakeGeneralIdRef } from "../../../utils/GeneralIdRef";
|
|
import glossariesService, {
|
|
CustomFieldValue,
|
|
Glossary,
|
|
SystemGlossaries,
|
|
} from "./services/glossaryService";
|
|
import { CustomField } from "../customfields/services/customFieldsService";
|
|
import Loading from "../../../components/common/Loading";
|
|
import {
|
|
renderError,
|
|
renderButton,
|
|
renderInput,
|
|
renderCustomFields,
|
|
renderCustomFieldsEditor,
|
|
} from "../../../components/common/formHelpers";
|
|
import { useFormWithGuard } from "../../../components/common/useFormRouter";
|
|
|
|
interface GlossariesDetailsProps {
|
|
editMode?: boolean;
|
|
}
|
|
|
|
const GlossariesDetails: React.FC<GlossariesDetailsProps> = ({
|
|
editMode = false,
|
|
}) => {
|
|
const { glossaryId } = useParams<{ glossaryId: string }>();
|
|
const { t } = useTranslation(Namespaces.Common);
|
|
|
|
const labelName = t("Name");
|
|
const labelChildCustomFieldDefinition = t("CustomFieldForChildEntries");
|
|
|
|
const labelApply = t("Save");
|
|
const labelSave = t("SaveAndClose");
|
|
|
|
const form = useFormWithGuard({
|
|
loaded: false,
|
|
data: {
|
|
id: undefined,
|
|
guid: undefined,
|
|
name: "",
|
|
parent: undefined,
|
|
childCustomFieldDefinition: [],
|
|
},
|
|
errors: {},
|
|
redirect: "",
|
|
});
|
|
|
|
form.schema = {
|
|
id: Joi.optional(),
|
|
guid: Joi.optional(),
|
|
name: Joi.string().required().max(450).label(labelName),
|
|
parent: Joi.optional(),
|
|
childCustomFieldDefinition: Joi.optional().label(
|
|
labelChildCustomFieldDefinition,
|
|
),
|
|
};
|
|
|
|
useEffect(() => {
|
|
const loadData = async () => {
|
|
const newData = { ...form.state.data };
|
|
|
|
if (editMode) {
|
|
const generalIdRef = MakeGeneralIdRef(BigInt(glossaryId!));
|
|
try {
|
|
const loadedData =
|
|
await glossariesService.getGlossaryItem(generalIdRef);
|
|
if (loadedData) {
|
|
newData.name = loadedData.name;
|
|
newData.parent = loadedData.parent;
|
|
newData.id = loadedData.id;
|
|
newData.guid = loadedData.guid;
|
|
newData.childCustomFieldDefinition =
|
|
loadedData.childCustomFieldDefinition ?? [];
|
|
|
|
const parentGlossary = newData.parent as Glossary | undefined;
|
|
|
|
form.setCustomFieldValues(
|
|
newData,
|
|
loadedData.customFieldValues,
|
|
parentGlossary?.childCustomFieldDefinition ?? [],
|
|
);
|
|
}
|
|
} catch (ex: any) {
|
|
form.handleGeneralError(ex);
|
|
}
|
|
} else {
|
|
const generalIdRef = MakeGeneralIdRef(BigInt(glossaryId!));
|
|
try {
|
|
const loadedData =
|
|
await glossariesService.getGlossaryItem(generalIdRef);
|
|
if (loadedData) {
|
|
newData.parent = loadedData;
|
|
}
|
|
} catch (ex: any) {
|
|
form.handleGeneralError(ex);
|
|
}
|
|
}
|
|
|
|
form.setState({
|
|
loaded: true,
|
|
data: newData,
|
|
customFields: (newData.parent as Glossary | undefined)
|
|
?.childCustomFieldDefinition,
|
|
});
|
|
};
|
|
|
|
loadData();
|
|
}, [glossaryId, editMode]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
|
|
const handleAdd = (customfield: CustomField) => {
|
|
const newData = { ...form.state.data };
|
|
const childDefs =
|
|
(newData.childCustomFieldDefinition as CustomField[]) ?? [];
|
|
childDefs.push(customfield);
|
|
newData.childCustomFieldDefinition = childDefs;
|
|
|
|
form.setState({ data: newData });
|
|
};
|
|
|
|
const handleDelete = (fieldToDelete: CustomField) => {
|
|
const newData = { ...form.state.data };
|
|
|
|
if (fieldToDelete) {
|
|
const childDefs =
|
|
(newData.childCustomFieldDefinition as CustomField[]) ?? [];
|
|
newData.childCustomFieldDefinition = childDefs.filter(
|
|
(x) => x !== fieldToDelete,
|
|
);
|
|
}
|
|
|
|
form.setState({ data: newData });
|
|
};
|
|
|
|
const doSubmit = async (buttonName: string) => {
|
|
try {
|
|
const { id, guid, name, parent, childCustomFieldDefinition } =
|
|
form.state.data;
|
|
const nameStr = typeof name === "string" ? name : "";
|
|
const parentGlossary = parent as Glossary | undefined;
|
|
const childDefs = (childCustomFieldDefinition as CustomField[]) ?? [];
|
|
const idValue = typeof id === "bigint" ? id : undefined;
|
|
const guidValue = typeof guid === "string" ? guid : undefined;
|
|
|
|
const customfieldValues = form.CustomFieldValues();
|
|
|
|
if (editMode) {
|
|
const generalIdRef = MakeGeneralIdRef(idValue, guidValue);
|
|
|
|
const response = await glossariesService.putGlossaryItem(
|
|
generalIdRef,
|
|
parentGlossary
|
|
? MakeGeneralIdRef(parentGlossary.id, parentGlossary.guid)
|
|
: undefined,
|
|
nameStr,
|
|
childDefs,
|
|
customfieldValues,
|
|
);
|
|
if (response) {
|
|
toast.info(t("GlossaryItemEdited"));
|
|
}
|
|
} else {
|
|
const generalIdRef = parentGlossary
|
|
? MakeGeneralIdRef(parentGlossary.id, parentGlossary.guid)
|
|
: SystemGlossaries;
|
|
const response = await glossariesService.postGlossaryItem(
|
|
generalIdRef,
|
|
nameStr,
|
|
childDefs,
|
|
customfieldValues,
|
|
);
|
|
if (response) {
|
|
toast.info(t("NewGlossaryItemAdded"));
|
|
}
|
|
}
|
|
|
|
const navigateId = parentGlossary ? parentGlossary.id.toString() : "";
|
|
if (buttonName === "save")
|
|
form.setState({ redirect: "/glossaries/" + navigateId });
|
|
form.markAsSaved();
|
|
} catch (ex: any) {
|
|
form.handleGeneralError(ex);
|
|
}
|
|
};
|
|
|
|
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
|
|
form.handleSubmit(e, doSubmit);
|
|
};
|
|
|
|
const { loaded, redirect, data } = form.state;
|
|
if (redirect) return <Navigate to={redirect} />;
|
|
|
|
let mode = t("Add");
|
|
if (editMode) mode = t("Edit");
|
|
|
|
const parentGlossary = data.parent as Glossary | undefined;
|
|
const handleCustomFieldChange = (
|
|
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
|
|
) => {
|
|
if (e.target instanceof HTMLTextAreaElement) {
|
|
form.handleTextAreaChange(e as React.ChangeEvent<HTMLTextAreaElement>);
|
|
} else {
|
|
form.handleCustomFieldChange(e as React.ChangeEvent<HTMLInputElement>);
|
|
}
|
|
};
|
|
const getCustomFieldType = (
|
|
field: CustomFieldValue,
|
|
customFields: CustomField[],
|
|
) => {
|
|
return form.getCustomFieldType(field as any, customFields);
|
|
};
|
|
const handleCustomFieldPickerChange = (
|
|
name: string,
|
|
value: GeneralIdRef | CustomFieldValue[],
|
|
) => {
|
|
if (Array.isArray(value)) {
|
|
form.handleGlossaryPickerChange(name, value);
|
|
} else {
|
|
form.handlePickerChange(name, value as GeneralIdRef);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<Loading loaded={loaded}>
|
|
<h1>
|
|
{mode} {t("GlossaryItem")}
|
|
</h1>
|
|
<form onSubmit={handleSubmit}>
|
|
{renderError("_general", form.state.errors)}
|
|
{renderInput(
|
|
"name",
|
|
labelName,
|
|
form.state.data,
|
|
form.state.errors,
|
|
InputType.text,
|
|
false,
|
|
"",
|
|
"",
|
|
0,
|
|
true,
|
|
undefined,
|
|
form.handleChange,
|
|
)}
|
|
{renderCustomFields(
|
|
parentGlossary?.childCustomFieldDefinition,
|
|
form.state.data,
|
|
form.state.errors,
|
|
handleCustomFieldChange,
|
|
handleCustomFieldPickerChange,
|
|
getCustomFieldType,
|
|
)}
|
|
<hr />
|
|
{renderCustomFieldsEditor(
|
|
"childCustomFieldDefinition",
|
|
labelChildCustomFieldDefinition,
|
|
form.state.data,
|
|
form.state.errors,
|
|
(data.childCustomFieldDefinition as CustomField[]) ?? [],
|
|
handleAdd,
|
|
handleDelete,
|
|
)}
|
|
<br />
|
|
{editMode && renderButton(labelApply, form.state.errors, "apply")}
|
|
{renderButton(labelSave, form.state.errors, "save")}
|
|
</form>
|
|
</Loading>
|
|
);
|
|
};
|
|
|
|
export default GlossariesDetails;
|