@olenbetong/synergi-react 2.2.3 → 2.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/es/components/FilePond.d.ts +8 -5
- package/es/components/FilePond.js +47 -20
- package/es/elements/ElementDamage/DamageFormButtons.d.ts +9 -0
- package/es/elements/ElementDamage/DamageFormButtons.js +7 -0
- package/es/elements/ElementDamage/DescriptionInput.d.ts +14 -0
- package/es/elements/ElementDamage/DescriptionInput.js +44 -0
- package/es/elements/{ElementDamageForm/DuplicateDamage/DuplicateElementDamageDialog.d.ts → ElementDamage/DuplicateDamage/DublicateElementDamageDialog.d.ts} +4 -3
- package/es/elements/ElementDamage/DuplicateDamage/DublicateElementDamageDialog.js +12 -0
- package/es/elements/ElementDamage/DuplicateDamage/index.d.ts +36 -0
- package/es/elements/ElementDamage/DuplicateDamage/index.js +40 -0
- package/es/elements/ElementDamage/ElementNumberTextField.d.ts +10 -0
- package/es/elements/ElementDamage/ElementNumberTextField.js +18 -0
- package/es/elements/ElementDamage/HiddenDamageFields.d.ts +6 -0
- package/es/elements/ElementDamage/HiddenDamageFields.js +4 -0
- package/es/elements/ElementDamage/RegisterFix.d.ts +14 -0
- package/es/elements/ElementDamage/RegisterFix.js +45 -0
- package/es/elements/ElementDamage/SubmitButtons.d.ts +20 -0
- package/es/elements/ElementDamage/SubmitButtons.js +7 -0
- package/es/elements/ElementDamage/TransportElementSelect.d.ts +7 -0
- package/es/elements/ElementDamage/TransportElementSelect.js +16 -0
- package/es/elements/ElementLookup.d.ts +20 -0
- package/es/elements/ElementLookup.js +30 -0
- package/es/elements/{AddElementDialog → ElementLookupDialog}/Manual/ManualForm.js +4 -2
- package/es/elements/{AddElementDialog → ElementLookupDialog}/getElement.d.ts +1 -0
- package/es/elements/{AddElementDialog → ElementLookupDialog}/getElement.js +1 -0
- package/es/elements/{AddElementDialog → ElementLookupDialog}/index.d.ts +5 -5
- package/es/elements/{AddElementDialog → ElementLookupDialog}/index.js +4 -1
- package/es/elements/ProjectSelect.js +9 -2
- package/es/elements/data/dsDamages.d.ts +1 -1
- package/es/elements/data/dsDamages.js +2 -2
- package/es/elements/data/dsElements.d.ts +2 -0
- package/es/elements/data/dsElements.js +11 -1
- package/es/elements/data/dsTransportElements.d.ts +10 -0
- package/es/elements/data/dsTransportElements.js +57 -0
- package/es/elements/data/index.d.ts +5 -1
- package/es/elements/data/index.js +5 -1
- package/es/elements/data/procDeleteAttachment.d.ts +2 -0
- package/es/elements/data/procDeleteAttachment.js +18 -0
- package/es/elements/data/procDeleteDamage.d.ts +2 -0
- package/es/elements/data/procDeleteDamage.js +18 -0
- package/es/elements/data/procRemoveDamageFix.d.ts +2 -0
- package/es/elements/data/procRemoveDamageFix.js +18 -0
- package/es/elements/data/procRestoreAttachments.d.ts +2 -0
- package/es/elements/data/procRestoreAttachments.js +18 -0
- package/es/elements/index.d.ts +8 -2
- package/es/elements/index.js +8 -2
- package/es/index.d.ts +1 -1
- package/es/index.js +1 -1
- package/package.json +4 -4
- package/src/components/FilePond.tsx +73 -26
- package/src/elements/ElementDamage/DamageFormButtons.tsx +35 -0
- package/src/elements/ElementDamage/DescriptionInput.tsx +111 -0
- package/src/elements/{ElementDamageForm/DuplicateDamage/DuplicateElementDamageDialog.tsx → ElementDamage/DuplicateDamage/DublicateElementDamageDialog.tsx} +24 -9
- package/src/elements/ElementDamage/DuplicateDamage/index.tsx +105 -0
- package/src/elements/ElementDamage/ElementNumberTextField.tsx +41 -0
- package/src/elements/ElementDamage/HiddenDamageFields.tsx +13 -0
- package/src/elements/ElementDamage/RegisterFix.tsx +100 -0
- package/src/elements/ElementDamage/SubmitButtons.tsx +40 -0
- package/src/elements/ElementDamage/TransportElementSelect.tsx +52 -0
- package/src/elements/ElementLookup.tsx +90 -0
- package/src/elements/{AddElementDialog → ElementLookupDialog}/Manual/ManualForm.tsx +5 -2
- package/src/elements/{AddElementDialog → ElementLookupDialog}/getElement.ts +2 -0
- package/src/elements/{AddElementDialog → ElementLookupDialog}/index.tsx +9 -5
- package/src/elements/ProjectSelect.tsx +13 -3
- package/src/elements/data/dsDamages.ts +3 -3
- package/src/elements/data/dsElements.ts +13 -1
- package/src/elements/data/dsTransportElements.ts +68 -0
- package/src/elements/data/index.ts +5 -1
- package/src/elements/data/procDeleteAttachment.ts +19 -0
- package/src/elements/data/procDeleteDamage.ts +19 -0
- package/src/elements/data/procRemoveDamageFix.ts +19 -0
- package/src/elements/data/procRestoreAttachments.ts +19 -0
- package/src/elements/index.ts +8 -3
- package/src/index.ts +1 -1
- package/es/elements/ElementDamageForm/DamageFormFields.d.ts +0 -12
- package/es/elements/ElementDamageForm/DamageFormFields.js +0 -39
- package/es/elements/ElementDamageForm/DuplicateDamage/DuplicateElementDamageDialog.js +0 -11
- package/es/elements/ElementDamageForm/index.d.ts +0 -13
- package/es/elements/ElementDamageForm/index.js +0 -219
- package/src/elements/ElementDamageForm/DamageFormFields.tsx +0 -149
- package/src/elements/ElementDamageForm/index.tsx +0 -397
- /package/es/elements/{ElementDamageForm → ElementDamage}/DuplicateDamage/DesktopView.d.ts +0 -0
- /package/es/elements/{ElementDamageForm → ElementDamage}/DuplicateDamage/DesktopView.js +0 -0
- /package/es/elements/{ElementDamageForm → ElementDamage}/DuplicateDamage/PhoneView.d.ts +0 -0
- /package/es/elements/{ElementDamageForm → ElementDamage}/DuplicateDamage/PhoneView.js +0 -0
- /package/es/elements/{ElementDamageForm → ElementDamage}/index.css +0 -0
- /package/es/elements/{AddElementDialog → ElementLookupDialog}/BarcodeScanner/DeadIcon.d.ts +0 -0
- /package/es/elements/{AddElementDialog → ElementLookupDialog}/BarcodeScanner/DeadIcon.js +0 -0
- /package/es/elements/{AddElementDialog → ElementLookupDialog}/BarcodeScanner/Error.d.ts +0 -0
- /package/es/elements/{AddElementDialog → ElementLookupDialog}/BarcodeScanner/Error.js +0 -0
- /package/es/elements/{AddElementDialog → ElementLookupDialog}/BarcodeScanner/index.d.ts +0 -0
- /package/es/elements/{AddElementDialog → ElementLookupDialog}/BarcodeScanner/index.js +0 -0
- /package/es/elements/{AddElementDialog → ElementLookupDialog}/BarcodeScanner/useScanner.d.ts +0 -0
- /package/es/elements/{AddElementDialog → ElementLookupDialog}/BarcodeScanner/useScanner.js +0 -0
- /package/es/elements/{AddElementDialog → ElementLookupDialog}/HIDScanner/index.css +0 -0
- /package/es/elements/{AddElementDialog → ElementLookupDialog}/HIDScanner/index.d.ts +0 -0
- /package/es/elements/{AddElementDialog → ElementLookupDialog}/HIDScanner/index.js +0 -0
- /package/es/elements/{AddElementDialog → ElementLookupDialog}/HIDScanner/useHIDScanner.d.ts +0 -0
- /package/es/elements/{AddElementDialog → ElementLookupDialog}/HIDScanner/useHIDScanner.js +0 -0
- /package/es/elements/{AddElementDialog → ElementLookupDialog}/Manual/ManualForm.d.ts +0 -0
- /package/es/elements/{AddElementDialog → ElementLookupDialog}/utils/Giai.d.ts +0 -0
- /package/es/elements/{AddElementDialog → ElementLookupDialog}/utils/Giai.js +0 -0
- /package/es/elements/{AddElementDialog → ElementLookupDialog}/utils/beep.d.ts +0 -0
- /package/es/elements/{AddElementDialog → ElementLookupDialog}/utils/beep.js +0 -0
- /package/src/elements/{ElementDamageForm → ElementDamage}/DuplicateDamage/DesktopView.tsx +0 -0
- /package/src/elements/{ElementDamageForm → ElementDamage}/DuplicateDamage/PhoneView.tsx +0 -0
- /package/src/elements/{ElementDamageForm → ElementDamage}/index.css +0 -0
- /package/src/elements/{AddElementDialog → ElementLookupDialog}/BarcodeScanner/DeadIcon.tsx +0 -0
- /package/src/elements/{AddElementDialog → ElementLookupDialog}/BarcodeScanner/Error.tsx +0 -0
- /package/src/elements/{AddElementDialog → ElementLookupDialog}/BarcodeScanner/index.tsx +0 -0
- /package/src/elements/{AddElementDialog → ElementLookupDialog}/BarcodeScanner/useScanner.ts +0 -0
- /package/src/elements/{AddElementDialog → ElementLookupDialog}/HIDScanner/index.css +0 -0
- /package/src/elements/{AddElementDialog → ElementLookupDialog}/HIDScanner/index.tsx +0 -0
- /package/src/elements/{AddElementDialog → ElementLookupDialog}/HIDScanner/useHIDScanner.ts +0 -0
- /package/src/elements/{AddElementDialog → ElementLookupDialog}/utils/Giai.ts +0 -0
- /package/src/elements/{AddElementDialog → ElementLookupDialog}/utils/beep.ts +0 -0
|
@@ -8,10 +8,11 @@ export { registerPlugin, FileStatus };
|
|
|
8
8
|
type FilePondProps<T extends Record<string, unknown>> = React.HTMLProps<HTMLInputElement> & {
|
|
9
9
|
dataObject: DataObject<T>;
|
|
10
10
|
fields: Partial<T>;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
onError: () => void;
|
|
11
|
+
onUploadStart: () => void;
|
|
12
|
+
onFileUploaded: (error: FilePondErrorDescription | null, file: FilePondFile) => void;
|
|
13
|
+
onFinishedUploads: () => void;
|
|
14
|
+
onError: (error: string) => void;
|
|
15
|
+
onFileRemoved?: (primKey: string) => void;
|
|
15
16
|
/**
|
|
16
17
|
* If the file should be uploaded to a blob field, set the field name here
|
|
17
18
|
*/
|
|
@@ -28,6 +29,8 @@ type FilePondProps<T extends Record<string, unknown>> = React.HTMLProps<HTMLInpu
|
|
|
28
29
|
* Options to pass to FilePond
|
|
29
30
|
*/
|
|
30
31
|
filePondOptions?: Partial<FilePondOptions>;
|
|
32
|
+
attachmentPrimKeys?: string[];
|
|
33
|
+
whereClause?: string;
|
|
31
34
|
};
|
|
32
35
|
type FileStoreDataObjectRecord = {
|
|
33
36
|
PrimKey: string;
|
|
@@ -38,4 +41,4 @@ type FileStoreDataObjectRecord = {
|
|
|
38
41
|
Damage: boolean;
|
|
39
42
|
DamageID: number | null;
|
|
40
43
|
};
|
|
41
|
-
export declare function FilePond<T extends FileStoreDataObjectRecord>({ dataObject, fields,
|
|
44
|
+
export declare function FilePond<T extends FileStoreDataObjectRecord>({ dataObject, fields, onUploadStart, onFileUploaded, onFinishedUploads, onFileRemoved, onError, fieldName, filePondOptions, primKey, attachmentPrimKeys, whereClause, inputRef: inputRefProp, ...props }: FilePondProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import "filepond-plugin-file-poster/dist/filepond-plugin-file-poster.css";
|
|
3
3
|
import "filepond-plugin-image-preview/dist/filepond-plugin-image-preview.css";
|
|
4
4
|
import "filepond/dist/filepond.css";
|
|
5
5
|
import { getLocalizedString } from "@olenbetong/appframe-core";
|
|
6
|
-
import { useData } from "@olenbetong/appframe-react";
|
|
6
|
+
import { useData, useFetchData } from "@olenbetong/appframe-react";
|
|
7
7
|
import { create, FileStatus, registerPlugin, } from "filepond";
|
|
8
8
|
import FilePondPluginImageExifOrientation from "filepond-plugin-image-exif-orientation";
|
|
9
9
|
import FilePondPluginImagePreview from "filepond-plugin-image-preview";
|
|
10
10
|
import FilePondPluginImageResize from "filepond-plugin-image-resize";
|
|
11
11
|
import FilePondPluginImageTransform from "filepond-plugin-image-transform";
|
|
12
|
-
import { useEffect, useRef } from "react";
|
|
12
|
+
import { useEffect, useMemo, useRef } from "react";
|
|
13
13
|
export { registerPlugin, FileStatus };
|
|
14
14
|
registerPlugin(FilePondPluginImageExifOrientation, FilePondPluginImageResize, FilePondPluginImagePreview, FilePondPluginImageTransform);
|
|
15
15
|
let isMostLikelyMobile = navigator.userAgent.match(/Android/i) ||
|
|
@@ -57,10 +57,26 @@ const labels = {
|
|
|
57
57
|
imageValidateSizeLabelExpectedMinResolution: getLocalizedString("Minimum resolution is {minResolution}"),
|
|
58
58
|
imageValidateSizeLabelExpectedMaxResolution: getLocalizedString("Maximum resolution is {maxResolution}"),
|
|
59
59
|
};
|
|
60
|
-
|
|
60
|
+
function getFileUrl(dataObject, fieldName, primKey, action = "upload") {
|
|
61
|
+
let url = action === "upload"
|
|
62
|
+
? dataObject.dataHandler.getUploadUrl()
|
|
63
|
+
: dataObject.dataHandler.getFileStoreURL(primKey ?? "", fieldName ?? "");
|
|
64
|
+
if (action === "upload") {
|
|
65
|
+
url += "/";
|
|
66
|
+
}
|
|
67
|
+
return url?.replaceAll("//", "/") ?? "";
|
|
68
|
+
}
|
|
69
|
+
export function FilePond({ dataObject, fields, onUploadStart, onFileUploaded, onFinishedUploads, onFileRemoved, onError, fieldName, filePondOptions, primKey, attachmentPrimKeys, whereClause, inputRef: inputRefProp, ...props }) {
|
|
61
70
|
let inputRef = useRef(null);
|
|
62
71
|
let pondRef = useRef(null);
|
|
63
|
-
let
|
|
72
|
+
let filesData = useData(dataObject);
|
|
73
|
+
let { data: filesFetched } = useFetchData(dataObject, whereClause ?? "1=2");
|
|
74
|
+
let files = useMemo(() => {
|
|
75
|
+
if (whereClause) {
|
|
76
|
+
return filesFetched;
|
|
77
|
+
}
|
|
78
|
+
return filesData;
|
|
79
|
+
}, [whereClause, filesFetched, filesData]);
|
|
64
80
|
let clearFilesRef = useRef(false);
|
|
65
81
|
useEffect(() => {
|
|
66
82
|
return () => {
|
|
@@ -82,6 +98,7 @@ export function FilePond({ dataObject, fields, onFileStart, onFileProcessed, onF
|
|
|
82
98
|
PrimKey: source,
|
|
83
99
|
});
|
|
84
100
|
if (result) {
|
|
101
|
+
onFileRemoved?.(source);
|
|
85
102
|
load();
|
|
86
103
|
}
|
|
87
104
|
else {
|
|
@@ -95,10 +112,6 @@ export function FilePond({ dataObject, fields, onFileStart, onFileProcessed, onF
|
|
|
95
112
|
"Failed to delete file on server but no error was returned.");
|
|
96
113
|
}
|
|
97
114
|
}
|
|
98
|
-
let uploadUrl = dataObject.dataHandler.getUploadUrl({ fieldName, primKey });
|
|
99
|
-
if (!uploadUrl) {
|
|
100
|
-
throw new Error("DataHandler does not support file uploads.");
|
|
101
|
-
}
|
|
102
115
|
let options = {
|
|
103
116
|
allowMultiple: Boolean(props.multiple),
|
|
104
117
|
allowImageResize: true,
|
|
@@ -107,21 +120,34 @@ export function FilePond({ dataObject, fields, onFileStart, onFileProcessed, onF
|
|
|
107
120
|
imageResizeTargetHeight: 2400,
|
|
108
121
|
imageResizeUpscale: false,
|
|
109
122
|
...labels,
|
|
110
|
-
onaddfilestart: () =>
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
123
|
+
onaddfilestart: (file) => {
|
|
124
|
+
if (file.status !== 5 && file.status !== 6 && file.status !== 10) {
|
|
125
|
+
onUploadStart();
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
onprocessfile: (error, file) => {
|
|
129
|
+
onFileUploaded(error, file);
|
|
130
|
+
let refFiles = pondRef.current?.getFiles();
|
|
131
|
+
let found = refFiles?.find((file) => file.status !== 2 && file.status !== 5 && file.status !== 6 && file.status !== 10);
|
|
132
|
+
if (found === undefined) {
|
|
133
|
+
onFinishedUploads();
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
onprocessfiles: () => onFinishedUploads(),
|
|
137
|
+
onerror: (error) => onError(error.body),
|
|
138
|
+
beforeRemoveFile: () => {
|
|
115
139
|
if (confirm(getLocalizedString("Are you sure you want to remove this file?"))) {
|
|
116
140
|
return true;
|
|
117
141
|
}
|
|
118
142
|
return false;
|
|
119
143
|
},
|
|
120
144
|
server: {
|
|
145
|
+
load: getFileUrl(dataObject, fieldName, primKey, "view"),
|
|
146
|
+
restore: getFileUrl(dataObject, fieldName, primKey, "view"),
|
|
121
147
|
revert: removeUploadedFile,
|
|
122
148
|
remove: removeUploadedFile,
|
|
123
149
|
process: {
|
|
124
|
-
url:
|
|
150
|
+
url: getFileUrl(dataObject, fieldName),
|
|
125
151
|
ondata: (formData) => {
|
|
126
152
|
let masterChildCriteria = dataObject.getParameter("masterChildCriteria");
|
|
127
153
|
let allFields = { ...masterChildCriteria, ...fields };
|
|
@@ -148,13 +174,14 @@ export function FilePond({ dataObject, fields, onFileStart, onFileProcessed, onF
|
|
|
148
174
|
props.multiple,
|
|
149
175
|
fields,
|
|
150
176
|
fieldName,
|
|
177
|
+
primKey,
|
|
151
178
|
inputRefProp,
|
|
152
179
|
filePondOptions,
|
|
153
180
|
onError,
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
181
|
+
onFileUploaded,
|
|
182
|
+
onUploadStart,
|
|
183
|
+
onFinishedUploads,
|
|
184
|
+
onFileRemoved,
|
|
158
185
|
]);
|
|
159
186
|
useEffect(() => {
|
|
160
187
|
if (pondRef.current) {
|
|
@@ -174,5 +201,5 @@ export function FilePond({ dataObject, fields, onFileStart, onFileProcessed, onF
|
|
|
174
201
|
clearFilesRef.current = false;
|
|
175
202
|
};
|
|
176
203
|
}, [files]);
|
|
177
|
-
return (
|
|
204
|
+
return (_jsxs("div", { className: "filepond--wrapper", children: [attachmentPrimKeys && _jsx("input", { type: "hidden", name: "AttachmentPrimkeys", value: attachmentPrimKeys }), _jsx("input", { type: "file", ...props, name: "File", ref: inputRefProp ?? inputRef })] }));
|
|
178
205
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
type DamageFormButtonsProps = {
|
|
2
|
+
isEdit: boolean;
|
|
3
|
+
loading: boolean;
|
|
4
|
+
uploadingFile: boolean;
|
|
5
|
+
handleDelete: () => void;
|
|
6
|
+
handleCancel: () => void;
|
|
7
|
+
};
|
|
8
|
+
export declare function DamageFormButtonsProps({ isEdit, loading, uploadingFile, handleDelete, handleCancel, }: DamageFormButtonsProps): import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import Add from "@mui/icons-material/Add";
|
|
3
|
+
import { Button } from "@mui/material";
|
|
4
|
+
import { getLocalizedString } from "@olenbetong/appframe-core";
|
|
5
|
+
export function DamageFormButtonsProps({ isEdit, loading, uploadingFile, handleDelete, handleCancel, }) {
|
|
6
|
+
return (_jsxs(_Fragment, { children: [isEdit && _jsx(Button, { onClick: handleDelete, children: getLocalizedString("Delete") }), _jsx(Button, { onClick: handleCancel, children: getLocalizedString("Cancel") }), _jsx(Button, { loading: loading || uploadingFile, loadingPosition: "start", startIcon: _jsx(Add, {}), type: "submit", variant: "contained", children: isEdit ? getLocalizedString("Save changes") : getLocalizedString("Register damage") })] }));
|
|
7
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type DescriptionInputType = {
|
|
2
|
+
Description?: string | null;
|
|
3
|
+
Cause?: string | null;
|
|
4
|
+
Action?: string | null;
|
|
5
|
+
Date?: Date;
|
|
6
|
+
};
|
|
7
|
+
type DescriptionInputProps = {
|
|
8
|
+
value?: DescriptionInputType | null;
|
|
9
|
+
defaultValue?: DescriptionInputType | null;
|
|
10
|
+
onCopyPrevDamage?: (value: DescriptionInputType) => void;
|
|
11
|
+
onChange?: (value: DescriptionInputType) => void;
|
|
12
|
+
};
|
|
13
|
+
export declare function DescriptionInput({ value, defaultValue, onCopyPrevDamage, onChange }: DescriptionInputProps): import("react/jsx-runtime").JSX.Element;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Autocomplete, Button, TextField } from "@mui/material";
|
|
3
|
+
import { getLocalizedString } from "@olenbetong/appframe-core";
|
|
4
|
+
import { useEffect, useRef, useState } from "react";
|
|
5
|
+
export function DescriptionInput({ value, defaultValue, onCopyPrevDamage, onChange }) {
|
|
6
|
+
let initializedRef = useRef(false);
|
|
7
|
+
let [input, setInput] = useState(defaultValue ?? null);
|
|
8
|
+
let inputValue = value === undefined ? input : value;
|
|
9
|
+
// biome-ignore lint: intentionally skipping "value" dependency as this should never run when "value" changes
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
if (initializedRef.current) {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
if (value === undefined && defaultValue) {
|
|
15
|
+
setInput(defaultValue);
|
|
16
|
+
initializedRef.current = true;
|
|
17
|
+
}
|
|
18
|
+
}, [defaultValue]);
|
|
19
|
+
function handleCopyPrevDamage() {
|
|
20
|
+
let description = localStorage.getItem("ElementDamage_Description") ?? "";
|
|
21
|
+
let cause = localStorage.getItem("ElementDamage_Cause") ?? "";
|
|
22
|
+
let action = localStorage.getItem("ElementDamage_Action") ?? "";
|
|
23
|
+
onCopyPrevDamage?.({
|
|
24
|
+
Description: description,
|
|
25
|
+
Cause: cause,
|
|
26
|
+
Action: action,
|
|
27
|
+
});
|
|
28
|
+
setInput({
|
|
29
|
+
...inputValue,
|
|
30
|
+
Description: description,
|
|
31
|
+
Cause: cause,
|
|
32
|
+
Action: action,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
function handleOnChange(value) {
|
|
36
|
+
onChange?.(value);
|
|
37
|
+
setInput(value);
|
|
38
|
+
}
|
|
39
|
+
return (_jsxs(_Fragment, { children: [_jsx(TextField, { name: "Date", type: "date", value: (inputValue?.Date ?? new Date()).toISOString().split("T")[0], onChange: (event) => handleOnChange({ ...inputValue, Date: new Date(event.target.value) }), id: "NewElementDamage_Date", label: getLocalizedString("Date"), fullWidth: true, required: true, slotProps: { inputLabel: { shrink: true } } }), _jsx(Button, { variant: "contained", onClick: handleCopyPrevDamage, children: getLocalizedString("Copy previous damage") }), _jsx(Autocomplete, { value: inputValue?.Description ?? "", onChange: (_event, value) => handleOnChange({ ...inputValue, Description: value ?? "" }), options: [
|
|
40
|
+
getLocalizedString("Tear in element"),
|
|
41
|
+
getLocalizedString("Damage around lifting anchor"),
|
|
42
|
+
getLocalizedString("Damage on underside"),
|
|
43
|
+
], freeSolo: true, renderInput: (params) => (_jsx(TextField, { name: "Description", required: true, ...params, label: getLocalizedString("Description") })) }), _jsx(TextField, { name: "Cause", id: "NewElementDamage_Cause", value: inputValue?.Cause ?? "", onChange: (event) => handleOnChange({ ...inputValue, Cause: event.currentTarget.value }), label: getLocalizedString("Cause"), fullWidth: true }), _jsx(TextField, { name: "Action", id: "NewElementDamage_Action", value: inputValue?.Action ?? "", onChange: (event) => handleOnChange({ ...inputValue, Action: event.currentTarget.value }), label: getLocalizedString("Action"), fullWidth: true })] }));
|
|
44
|
+
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type { DamagesRecord } from "../../data";
|
|
2
2
|
type DuplicateElementDamageDialogProps = {
|
|
3
3
|
open: boolean;
|
|
4
|
-
onClose: (
|
|
4
|
+
onClose: () => void;
|
|
5
5
|
record: DamagesRecord[];
|
|
6
|
-
|
|
6
|
+
onRegisterAnyway: () => void;
|
|
7
|
+
loading: boolean;
|
|
7
8
|
};
|
|
8
|
-
export declare function DuplicateElementDamageDialog({ open, onClose, record,
|
|
9
|
+
export declare function DuplicateElementDamageDialog({ open, onClose, record, onRegisterAnyway, loading, }: DuplicateElementDamageDialogProps): import("react/jsx-runtime").JSX.Element;
|
|
9
10
|
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import Add from "@mui/icons-material/Add";
|
|
3
|
+
import { Button, Dialog, DialogActions, DialogContent, DialogTitle, Grid, useMediaQuery } from "@mui/material";
|
|
4
|
+
import { getLocalizedString } from "@olenbetong/appframe-core";
|
|
5
|
+
import { theme } from "@olenbetong/appframe-mui";
|
|
6
|
+
import { ElementDamagesHeader, ElementDamagesItem } from "./DesktopView";
|
|
7
|
+
import { DuplicatePhoneViewItem } from "./PhoneView";
|
|
8
|
+
export function DuplicateElementDamageDialog({ open, onClose, record, onRegisterAnyway, loading, }) {
|
|
9
|
+
let matches = useMediaQuery(theme.breakpoints.up("lg"));
|
|
10
|
+
let backgroundColor = "#e9ebee";
|
|
11
|
+
return (_jsxs(Dialog, { open: open, onClose: onClose, fullWidth: true, fullScreen: !matches, children: [_jsx(DialogTitle, { sx: { backgroundColor: backgroundColor }, children: getLocalizedString("This element has one or more unfixed registered damage") }), _jsx(DialogContent, { sx: { backgroundColor: backgroundColor }, children: _jsx(Grid, { container: true, children: matches ? (_jsxs(_Fragment, { children: [_jsx(ElementDamagesHeader, {}), record.map((record) => (_jsx(ElementDamagesItem, { record: record }, record.PrimKey)))] })) : (_jsx("div", { className: "flow", style: { width: "100%" }, children: record.map((record) => (_jsx(DuplicatePhoneViewItem, { record: record }, record.PrimKey))) })) }) }), _jsxs(DialogActions, { sx: { backgroundColor: backgroundColor }, children: [_jsx(Button, { onClick: onClose, children: getLocalizedString("Cancel") }), _jsx(Button, { startIcon: _jsx(Add, {}), variant: "contained", type: "submit", onClick: onRegisterAnyway, loading: loading, loadingPosition: "start", children: getLocalizedString("Register damage anyway") })] })] }));
|
|
12
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { type DamagesRecord } from "../../data";
|
|
2
|
+
import type { Element } from "../../ElementLookup";
|
|
3
|
+
export { DuplicateElementDamageDialog } from "./DublicateElementDamageDialog";
|
|
4
|
+
export type DuplicateElementDamageHandle = {
|
|
5
|
+
onClose: () => void;
|
|
6
|
+
checkDuplicate: () => Promise<DamagesRecord[] | null>;
|
|
7
|
+
record: DamagesRecord[];
|
|
8
|
+
};
|
|
9
|
+
type DuplicateElementDamageProps = {
|
|
10
|
+
element: Element | null;
|
|
11
|
+
/**
|
|
12
|
+
* External control of dialog visibility
|
|
13
|
+
*/
|
|
14
|
+
open?: boolean;
|
|
15
|
+
onOpenChange?: (value: boolean) => void;
|
|
16
|
+
/**
|
|
17
|
+
* Skip duplicate checking (used in edit mode)
|
|
18
|
+
*/
|
|
19
|
+
disableCheck?: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Loading state for submit button
|
|
22
|
+
*/
|
|
23
|
+
loading?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Called when duplicate or duplicates are found
|
|
26
|
+
* @param record Array with all of the duplicate damages
|
|
27
|
+
* @returns void
|
|
28
|
+
*/
|
|
29
|
+
onDuplicateFound?: (record: DamagesRecord[]) => void;
|
|
30
|
+
/**
|
|
31
|
+
* Called when user presses register anyway in dialog
|
|
32
|
+
* @returns void
|
|
33
|
+
*/
|
|
34
|
+
onRegisterAnyway?: () => void;
|
|
35
|
+
};
|
|
36
|
+
export declare const DuplicateElementDamage: import("react").ForwardRefExoticComponent<DuplicateElementDamageProps & import("react").RefAttributes<DuplicateElementDamageHandle>>;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useDataWithFilter } from "@olenbetong/appframe-react";
|
|
3
|
+
import { forwardRef, useImperativeHandle, useMemo, useState } from "react";
|
|
4
|
+
import { dsDamagesDuplicateCheck } from "../../data";
|
|
5
|
+
import { DuplicateElementDamageDialog } from "./DublicateElementDamageDialog";
|
|
6
|
+
export { DuplicateElementDamageDialog } from "./DublicateElementDamageDialog";
|
|
7
|
+
export const DuplicateElementDamage = forwardRef(function DuplicateElementDamage({ element, open: controlledOpen, onOpenChange, disableCheck = false, loading = false, onRegisterAnyway, }, ref) {
|
|
8
|
+
let [record, setRecord] = useState([]);
|
|
9
|
+
let [uncontrolledOpen, setUncontrolledOpen] = useState(false);
|
|
10
|
+
let open = controlledOpen === undefined ? uncontrolledOpen : controlledOpen;
|
|
11
|
+
let whereClause = useMemo(() => {
|
|
12
|
+
if (!element) {
|
|
13
|
+
return "1=0";
|
|
14
|
+
}
|
|
15
|
+
return `Domain = '${element.Domain}' AND ElementID = '${element.ElementID}' AND ProjectID = '${element.ProjectID}'`;
|
|
16
|
+
}, [element]);
|
|
17
|
+
let duplicateRecord = useDataWithFilter(dsDamagesDuplicateCheck, whereClause, "whereClause");
|
|
18
|
+
async function runDuplicateCheck() {
|
|
19
|
+
// If we are editing a record, we don't need to check for duplicates
|
|
20
|
+
if (disableCheck) {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
if (duplicateRecord.length > 0) {
|
|
24
|
+
setRecord(duplicateRecord);
|
|
25
|
+
setUncontrolledOpen(true);
|
|
26
|
+
return duplicateRecord;
|
|
27
|
+
}
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
function handleOpenChange(value) {
|
|
31
|
+
setUncontrolledOpen(value);
|
|
32
|
+
onOpenChange?.(value);
|
|
33
|
+
}
|
|
34
|
+
useImperativeHandle(ref, () => ({
|
|
35
|
+
onClose: () => setUncontrolledOpen(false),
|
|
36
|
+
checkDuplicate: () => runDuplicateCheck(),
|
|
37
|
+
record: record,
|
|
38
|
+
}));
|
|
39
|
+
return (_jsx(DuplicateElementDamageDialog, { open: open, onClose: () => handleOpenChange(false), record: record, onRegisterAnyway: onRegisterAnyway ?? (() => { }), loading: loading ?? false }));
|
|
40
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type SxProps, type Theme } from "@mui/material";
|
|
2
|
+
type ElementNumberTextFieldProps = {
|
|
3
|
+
value?: string | null;
|
|
4
|
+
defaultValue?: string | null;
|
|
5
|
+
onChange?: (value: string) => void;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
sx?: SxProps<Theme>;
|
|
8
|
+
};
|
|
9
|
+
export declare function ElementNumberTextField({ value, defaultValue, onChange, disabled, sx }: ElementNumberTextFieldProps): import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { TextField } from "@mui/material";
|
|
3
|
+
import { getLocalizedString } from "@olenbetong/appframe-core";
|
|
4
|
+
import { useEffect, useState } from "react";
|
|
5
|
+
export function ElementNumberTextField({ value, defaultValue, onChange, disabled, sx }) {
|
|
6
|
+
let [elementNumber, setElementNumber] = useState(defaultValue ?? "");
|
|
7
|
+
let elementNumberValue = value === undefined ? elementNumber : value;
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
if (value === undefined && defaultValue) {
|
|
10
|
+
setElementNumber(defaultValue);
|
|
11
|
+
}
|
|
12
|
+
}, [defaultValue, value]);
|
|
13
|
+
function handleChange(value) {
|
|
14
|
+
onChange?.(value);
|
|
15
|
+
setElementNumber(value);
|
|
16
|
+
}
|
|
17
|
+
return (_jsx(TextField, { name: "ElementNumber", id: "NewElementDamage_ElementNr", value: elementNumberValue, onChange: (event) => handleChange(event.currentTarget.value), label: getLocalizedString("Element number"), fullWidth: true, autoComplete: "off", disabled: disabled ?? false, sx: { ...sx } }));
|
|
18
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
export function HiddenDamageFields({ primKey, ID }) {
|
|
3
|
+
return (_jsxs(_Fragment, { children: [_jsx("input", { type: "hidden", name: "PrimKey", value: primKey }), _jsx("input", { type: "hidden", name: "ID", value: ID })] }));
|
|
4
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
type RegisterFixType = {
|
|
2
|
+
ID: number;
|
|
3
|
+
RegisteredFixFullName: string | null;
|
|
4
|
+
RegisteredFix: Date | null;
|
|
5
|
+
RegisteredFixBy: string | null;
|
|
6
|
+
};
|
|
7
|
+
type RegisterFixProps = {
|
|
8
|
+
value?: RegisterFixType | null;
|
|
9
|
+
defaultValue?: RegisterFixType | null;
|
|
10
|
+
onFix?: (ID: number) => void;
|
|
11
|
+
edit?: boolean;
|
|
12
|
+
};
|
|
13
|
+
export declare function RegisterFix({ value, defaultValue, onFix, edit }: RegisterFixProps): import("react/jsx-runtime").JSX.Element;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import CheckIcon from "@mui/icons-material/Check";
|
|
3
|
+
import { Button, Checkbox, FormControlLabel, Typography } from "@mui/material";
|
|
4
|
+
import { getLocalizedString, localize } from "@olenbetong/appframe-core";
|
|
5
|
+
import { useEffect, useRef, useState } from "react";
|
|
6
|
+
import { procApproveDamage } from "../data";
|
|
7
|
+
const formatter = new Intl.DateTimeFormat(af.userSession.culture, {
|
|
8
|
+
day: "numeric",
|
|
9
|
+
month: "long",
|
|
10
|
+
year: "numeric",
|
|
11
|
+
hour: "2-digit",
|
|
12
|
+
minute: "2-digit",
|
|
13
|
+
timeZone: "UTC",
|
|
14
|
+
});
|
|
15
|
+
export function RegisterFix({ value, defaultValue, onFix, edit }) {
|
|
16
|
+
let [loading, setLoading] = useState(false);
|
|
17
|
+
let initializedRef = useRef(false);
|
|
18
|
+
let [fix, setFix] = useState(defaultValue ?? null);
|
|
19
|
+
let fixValue = value === undefined ? fix : value;
|
|
20
|
+
// biome-ignore lint: intentionally skipping "value" dependency as this should never run when "value" changes
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
if (initializedRef.current) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
if (value === undefined && defaultValue) {
|
|
26
|
+
setFix(defaultValue);
|
|
27
|
+
initializedRef.current = true;
|
|
28
|
+
}
|
|
29
|
+
}, [defaultValue]);
|
|
30
|
+
async function handleRegisterFix() {
|
|
31
|
+
try {
|
|
32
|
+
if (confirm(getLocalizedString("Are you sure you want to register a fix for this damage?"))) {
|
|
33
|
+
setLoading(true);
|
|
34
|
+
let record = (await procApproveDamage.execute({ ID: fixValue?.ID }));
|
|
35
|
+
setFix({ ...record.Table[0] });
|
|
36
|
+
setLoading(false);
|
|
37
|
+
onFix?.(fixValue?.ID ?? -1);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
alert(error.message);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return (_jsxs(_Fragment, { children: [edit ? (_jsx(Button, { loading: loading, loadingPosition: "end", endIcon: _jsx(CheckIcon, {}), onClick: handleRegisterFix, disabled: !!fixValue?.RegisteredFix, variant: "contained", children: getLocalizedString("Register fix") })) : (_jsx(FormControlLabel, { control: _jsx(Checkbox, {}), label: getLocalizedString("Register fixed"), name: "RegisteredFix", id: "NewElementDamage_RegisteredFix" })), fixValue?.RegisteredFix && (_jsx(Typography, { mb: 1.5, color: "text.secondary", children: localize `Registered fix by ${fixValue.RegisteredFixFullName ?? fixValue.RegisteredFixBy} on the ${formatter.format(fixValue.RegisteredFix)}` }))] }));
|
|
45
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type SxProps, type Theme } from "@mui/material";
|
|
2
|
+
type SubmitButtonsProps = {
|
|
3
|
+
/**
|
|
4
|
+
* Whether the form is in edit mode. If true, delete button is visible and submit button's text changes.
|
|
5
|
+
*/
|
|
6
|
+
edit?: boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Set loading state for submit button
|
|
9
|
+
*/
|
|
10
|
+
loading?: boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Custom styles for Box wrapper around buttons
|
|
13
|
+
*/
|
|
14
|
+
sx?: SxProps<Theme>;
|
|
15
|
+
onDelete?: () => void;
|
|
16
|
+
onCancel?: () => void;
|
|
17
|
+
onSubmit?: () => void;
|
|
18
|
+
};
|
|
19
|
+
export declare function SubmitButtons({ edit, loading, onDelete, onCancel, onSubmit, sx }: SubmitButtonsProps): import("react/jsx-runtime").JSX.Element;
|
|
20
|
+
export {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import Add from "@mui/icons-material/Add";
|
|
3
|
+
import { Box, Button } from "@mui/material";
|
|
4
|
+
import { getLocalizedString } from "@olenbetong/appframe-core";
|
|
5
|
+
export function SubmitButtons({ edit, loading, onDelete, onCancel, onSubmit, sx }) {
|
|
6
|
+
return (_jsxs(Box, { sx: { display: "flex", flexWrap: "wrap", gap: 2, justifyContent: "flex-end", ...sx }, children: [edit && _jsx(Button, { onClick: onDelete, children: getLocalizedString("Delete") }), _jsx(Button, { onClick: onCancel, children: getLocalizedString("Cancel") }), _jsx(Button, { loading: loading, loadingPosition: "start", startIcon: _jsx(Add, {}), type: "submit", variant: "contained", onClick: onSubmit, children: edit ? getLocalizedString("Save changes") : getLocalizedString("Register damage") })] }));
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { TransportElementsRecord } from "../data/dsTransportElements.js";
|
|
2
|
+
type TransportElementSelectProps = {
|
|
3
|
+
elements: TransportElementsRecord[];
|
|
4
|
+
onSelect: (element: TransportElementsRecord) => void;
|
|
5
|
+
};
|
|
6
|
+
export declare function TransportElementSelect({ elements, onSelect }: TransportElementSelectProps): import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import DropDownArrowIcon from "@mui/icons-material/KeyboardArrowDown";
|
|
3
|
+
import { Button, ListItemText, Menu, MenuItem } from "@mui/material";
|
|
4
|
+
import { getLocalizedString } from "@olenbetong/appframe-core";
|
|
5
|
+
import { useState } from "react";
|
|
6
|
+
export function TransportElementSelect({ elements, onSelect }) {
|
|
7
|
+
let [anchorEl, setAnchorEl] = useState(null);
|
|
8
|
+
let open = !!anchorEl;
|
|
9
|
+
let [selected, setSelected] = useState(null);
|
|
10
|
+
function handleChange(element) {
|
|
11
|
+
setAnchorEl(null);
|
|
12
|
+
onSelect(element);
|
|
13
|
+
setSelected(element);
|
|
14
|
+
}
|
|
15
|
+
return (_jsxs(_Fragment, { children: [_jsx(Button, { id: "select_element", variant: "contained", endIcon: _jsx(DropDownArrowIcon, { style: { transform: open ? "rotate(180deg)" : "rotate(0deg)", transition: "transform 0.2s" } }), sx: { width: "165px" }, "aria-controls": open ? "basic-menu" : undefined, "aria-haspopup": "true", "aria-expanded": open ? "true" : undefined, onClick: (event) => setAnchorEl(event.currentTarget), children: selected ? `${selected.ElementID} - ${selected.Name}` : getLocalizedString("Select element") }), _jsx(Menu, { id: "menu_element", anchorEl: anchorEl, open: open, onClose: () => setAnchorEl(null), children: elements.map((element) => (_jsx(MenuItem, { onClick: () => handleChange(element), children: _jsxs(ListItemText, { children: [element.ElementID, " - ", element.Name] }) }, element.PrimKey))) })] }));
|
|
16
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type RefObject } from "react";
|
|
2
|
+
export type Element = {
|
|
3
|
+
Domain: string;
|
|
4
|
+
PrimKey: string;
|
|
5
|
+
ProjectID: string;
|
|
6
|
+
ProjectName: string;
|
|
7
|
+
ElementID: string | null;
|
|
8
|
+
};
|
|
9
|
+
export type ElementLookupHandle = {
|
|
10
|
+
openDialog: () => void;
|
|
11
|
+
closeDialog: () => void;
|
|
12
|
+
};
|
|
13
|
+
export type ElementLookupProps = {
|
|
14
|
+
value?: Element | null;
|
|
15
|
+
defaultValue?: Element | null;
|
|
16
|
+
ref?: RefObject<ElementLookupHandle | null>;
|
|
17
|
+
openLookupDialogIcon?: boolean;
|
|
18
|
+
onChange?: (value: Element | null) => void;
|
|
19
|
+
};
|
|
20
|
+
export declare function ElementLookup({ value, defaultValue, ref, openLookupDialogIcon, onChange }: ElementLookupProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import SearchIcon from "@mui/icons-material/Search";
|
|
3
|
+
import { IconButton, TextField } from "@mui/material";
|
|
4
|
+
import { getLocalizedString } from "@olenbetong/appframe-core";
|
|
5
|
+
import { useEffect, useImperativeHandle, useState } from "react";
|
|
6
|
+
import { ElementLookupDialog } from "./ElementLookupDialog";
|
|
7
|
+
export function ElementLookup({ value, defaultValue, ref, openLookupDialogIcon, onChange }) {
|
|
8
|
+
let [openElementLookupDialog, setOpenElementLookupDialog] = useState(false);
|
|
9
|
+
let [element, setElement] = useState(defaultValue ?? null);
|
|
10
|
+
let elementValue = value === undefined ? element : value;
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
if (value === undefined && defaultValue) {
|
|
13
|
+
setElement(defaultValue);
|
|
14
|
+
}
|
|
15
|
+
}, [defaultValue, value]);
|
|
16
|
+
useImperativeHandle(ref, () => ({
|
|
17
|
+
openDialog: () => setOpenElementLookupDialog(true),
|
|
18
|
+
closeDialog: () => setOpenElementLookupDialog(false),
|
|
19
|
+
}));
|
|
20
|
+
async function handleAddElement(addElement) {
|
|
21
|
+
onChange?.(addElement.element);
|
|
22
|
+
setElement(addElement.element);
|
|
23
|
+
}
|
|
24
|
+
return (_jsxs(_Fragment, { children: [_jsx(ElementLookupDialog, { open: openElementLookupDialog, mode: "single", onClose: () => setOpenElementLookupDialog(false), onAdd: handleAddElement }), _jsx("input", { type: "hidden", name: "ProjectID", value: elementValue?.ProjectID ?? "" }), _jsx("input", { type: "hidden", name: "ElementRef", value: elementValue?.PrimKey ?? "" }), _jsx(TextField, { id: "NewElementDamge_Project", value: elementValue ? `${elementValue.ProjectID}: ${elementValue.ProjectName}` : "", label: getLocalizedString("Project"), fullWidth: true, required: true, autoComplete: "off", slotProps: { htmlInput: { readOnly: true } } }), _jsx(TextField, { name: "ElementID", id: "NewElementDamage_ElementID", value: elementValue ? elementValue.ElementID : "", label: getLocalizedString("Element ID"), fullWidth: true, autoComplete: "off", slotProps: {
|
|
25
|
+
htmlInput: { readOnly: true },
|
|
26
|
+
input: {
|
|
27
|
+
endAdornment: openLookupDialogIcon ? (_jsx(IconButton, { onClick: () => setOpenElementLookupDialog(true), children: _jsx(SearchIcon, {}) })) : undefined,
|
|
28
|
+
},
|
|
29
|
+
} })] }));
|
|
30
|
+
}
|
|
@@ -2,12 +2,13 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import Add from "@mui/icons-material/Add";
|
|
3
3
|
import { Alert, Button, TextField } from "@mui/material";
|
|
4
4
|
import { getLocalizedString } from "@olenbetong/appframe-core";
|
|
5
|
-
import { useRef, useState } from "react";
|
|
5
|
+
import { useId, useRef, useState } from "react";
|
|
6
6
|
import { ProjectSelect } from "../../ProjectSelect";
|
|
7
7
|
import { getElement } from "../getElement";
|
|
8
8
|
const isElementsOnly = /^([a-z]{2,4}[\s]*[0-9]{4,8}[\s,]*)+$/i;
|
|
9
9
|
const matchElements = /([a-z]{2,4}[\s]*[0-9]{4,8})/gi;
|
|
10
10
|
export function AddElementManualForm({ onAdd, mode, defaultProject }) {
|
|
11
|
+
let id = useId();
|
|
11
12
|
let buttonRef = useRef(null);
|
|
12
13
|
let [working, setWorking] = useState(false);
|
|
13
14
|
let [elementId, setElementId] = useState("");
|
|
@@ -15,6 +16,7 @@ export function AddElementManualForm({ onAdd, mode, defaultProject }) {
|
|
|
15
16
|
async function handleSubmit(evt) {
|
|
16
17
|
try {
|
|
17
18
|
evt.preventDefault();
|
|
19
|
+
evt.stopPropagation();
|
|
18
20
|
let formData = new FormData(evt.target);
|
|
19
21
|
let elements = formData.get("ElementID");
|
|
20
22
|
let domain = formData.get("Domain");
|
|
@@ -42,5 +44,5 @@ export function AddElementManualForm({ onAdd, mode, defaultProject }) {
|
|
|
42
44
|
alert(error.message);
|
|
43
45
|
}
|
|
44
46
|
}
|
|
45
|
-
return (_jsxs("form", { onSubmit: handleSubmit, method: "post", children: [_jsx(Alert, { severity: "warning", sx: { mb: 2 }, children: getLocalizedString("Manually entering elements is a major source of errors. Only use this as a last resort. If the camera or scanner is not working, please contact the IT department.") }), _jsx(ProjectSelect, { onChange: (project) => (project ? setProject(project) : setProject(null)), value: project, id: "AddElement_Project" }), _jsx(TextField, { variant: "filled", fullWidth: true, autoComplete: "off", margin: "normal", name: "ElementID", id: "AddElement_ElementID", label: getLocalizedString("Element ID"), value: elementId, onChange: (evt) => setElementId(evt.target.value) }), _jsx(Button, { ref: buttonRef, color: "primary", variant: "contained", size: "large", type: "submit", disabled: !isElementsOnly.test(elementId) || working, loading: working, loadingPosition: "end", endIcon: _jsx(Add, {}), children: getLocalizedString("Add") })] }));
|
|
47
|
+
return (_jsxs("form", { id: id, onSubmit: handleSubmit, method: "post", children: [_jsx(Alert, { severity: "warning", sx: { mb: 2 }, children: getLocalizedString("Manually entering elements is a major source of errors. Only use this as a last resort. If the camera or scanner is not working, please contact the IT department.") }), _jsx(ProjectSelect, { onChange: (project) => (project ? setProject(project) : setProject(null)), value: project, id: "AddElement_Project" }), _jsx(TextField, { variant: "filled", fullWidth: true, autoComplete: "off", margin: "normal", name: "ElementID", id: "AddElement_ElementID", label: getLocalizedString("Element ID"), value: elementId, onChange: (evt) => setElementId(evt.target.value) }), _jsx(Button, { form: id, ref: buttonRef, color: "primary", variant: "contained", size: "large", type: "submit", disabled: !isElementsOnly.test(elementId) || working, loading: working, loadingPosition: "end", endIcon: _jsx(Add, {}), children: getLocalizedString("Add") })] }));
|
|
46
48
|
}
|
|
@@ -6,6 +6,7 @@ const elementsDataHandler = new DataProviderHandlerAPI({
|
|
|
6
6
|
fields: [
|
|
7
7
|
{ name: "PrimKey", type: "string" },
|
|
8
8
|
{ name: "Created", type: "datetime" },
|
|
9
|
+
{ name: "Domain", type: "string" },
|
|
9
10
|
{ name: "ProjectID", type: "string" },
|
|
10
11
|
{ name: "ProjectName", type: "string" },
|
|
11
12
|
{ name: "ProjectDomain", type: "string" },
|