@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.
Files changed (116) hide show
  1. package/es/components/FilePond.d.ts +8 -5
  2. package/es/components/FilePond.js +47 -20
  3. package/es/elements/ElementDamage/DamageFormButtons.d.ts +9 -0
  4. package/es/elements/ElementDamage/DamageFormButtons.js +7 -0
  5. package/es/elements/ElementDamage/DescriptionInput.d.ts +14 -0
  6. package/es/elements/ElementDamage/DescriptionInput.js +44 -0
  7. package/es/elements/{ElementDamageForm/DuplicateDamage/DuplicateElementDamageDialog.d.ts → ElementDamage/DuplicateDamage/DublicateElementDamageDialog.d.ts} +4 -3
  8. package/es/elements/ElementDamage/DuplicateDamage/DublicateElementDamageDialog.js +12 -0
  9. package/es/elements/ElementDamage/DuplicateDamage/index.d.ts +36 -0
  10. package/es/elements/ElementDamage/DuplicateDamage/index.js +40 -0
  11. package/es/elements/ElementDamage/ElementNumberTextField.d.ts +10 -0
  12. package/es/elements/ElementDamage/ElementNumberTextField.js +18 -0
  13. package/es/elements/ElementDamage/HiddenDamageFields.d.ts +6 -0
  14. package/es/elements/ElementDamage/HiddenDamageFields.js +4 -0
  15. package/es/elements/ElementDamage/RegisterFix.d.ts +14 -0
  16. package/es/elements/ElementDamage/RegisterFix.js +45 -0
  17. package/es/elements/ElementDamage/SubmitButtons.d.ts +20 -0
  18. package/es/elements/ElementDamage/SubmitButtons.js +7 -0
  19. package/es/elements/ElementDamage/TransportElementSelect.d.ts +7 -0
  20. package/es/elements/ElementDamage/TransportElementSelect.js +16 -0
  21. package/es/elements/ElementLookup.d.ts +20 -0
  22. package/es/elements/ElementLookup.js +30 -0
  23. package/es/elements/{AddElementDialog → ElementLookupDialog}/Manual/ManualForm.js +4 -2
  24. package/es/elements/{AddElementDialog → ElementLookupDialog}/getElement.d.ts +1 -0
  25. package/es/elements/{AddElementDialog → ElementLookupDialog}/getElement.js +1 -0
  26. package/es/elements/{AddElementDialog → ElementLookupDialog}/index.d.ts +5 -5
  27. package/es/elements/{AddElementDialog → ElementLookupDialog}/index.js +4 -1
  28. package/es/elements/ProjectSelect.js +9 -2
  29. package/es/elements/data/dsDamages.d.ts +1 -1
  30. package/es/elements/data/dsDamages.js +2 -2
  31. package/es/elements/data/dsElements.d.ts +2 -0
  32. package/es/elements/data/dsElements.js +11 -1
  33. package/es/elements/data/dsTransportElements.d.ts +10 -0
  34. package/es/elements/data/dsTransportElements.js +57 -0
  35. package/es/elements/data/index.d.ts +5 -1
  36. package/es/elements/data/index.js +5 -1
  37. package/es/elements/data/procDeleteAttachment.d.ts +2 -0
  38. package/es/elements/data/procDeleteAttachment.js +18 -0
  39. package/es/elements/data/procDeleteDamage.d.ts +2 -0
  40. package/es/elements/data/procDeleteDamage.js +18 -0
  41. package/es/elements/data/procRemoveDamageFix.d.ts +2 -0
  42. package/es/elements/data/procRemoveDamageFix.js +18 -0
  43. package/es/elements/data/procRestoreAttachments.d.ts +2 -0
  44. package/es/elements/data/procRestoreAttachments.js +18 -0
  45. package/es/elements/index.d.ts +8 -2
  46. package/es/elements/index.js +8 -2
  47. package/es/index.d.ts +1 -1
  48. package/es/index.js +1 -1
  49. package/package.json +4 -4
  50. package/src/components/FilePond.tsx +73 -26
  51. package/src/elements/ElementDamage/DamageFormButtons.tsx +35 -0
  52. package/src/elements/ElementDamage/DescriptionInput.tsx +111 -0
  53. package/src/elements/{ElementDamageForm/DuplicateDamage/DuplicateElementDamageDialog.tsx → ElementDamage/DuplicateDamage/DublicateElementDamageDialog.tsx} +24 -9
  54. package/src/elements/ElementDamage/DuplicateDamage/index.tsx +105 -0
  55. package/src/elements/ElementDamage/ElementNumberTextField.tsx +41 -0
  56. package/src/elements/ElementDamage/HiddenDamageFields.tsx +13 -0
  57. package/src/elements/ElementDamage/RegisterFix.tsx +100 -0
  58. package/src/elements/ElementDamage/SubmitButtons.tsx +40 -0
  59. package/src/elements/ElementDamage/TransportElementSelect.tsx +52 -0
  60. package/src/elements/ElementLookup.tsx +90 -0
  61. package/src/elements/{AddElementDialog → ElementLookupDialog}/Manual/ManualForm.tsx +5 -2
  62. package/src/elements/{AddElementDialog → ElementLookupDialog}/getElement.ts +2 -0
  63. package/src/elements/{AddElementDialog → ElementLookupDialog}/index.tsx +9 -5
  64. package/src/elements/ProjectSelect.tsx +13 -3
  65. package/src/elements/data/dsDamages.ts +3 -3
  66. package/src/elements/data/dsElements.ts +13 -1
  67. package/src/elements/data/dsTransportElements.ts +68 -0
  68. package/src/elements/data/index.ts +5 -1
  69. package/src/elements/data/procDeleteAttachment.ts +19 -0
  70. package/src/elements/data/procDeleteDamage.ts +19 -0
  71. package/src/elements/data/procRemoveDamageFix.ts +19 -0
  72. package/src/elements/data/procRestoreAttachments.ts +19 -0
  73. package/src/elements/index.ts +8 -3
  74. package/src/index.ts +1 -1
  75. package/es/elements/ElementDamageForm/DamageFormFields.d.ts +0 -12
  76. package/es/elements/ElementDamageForm/DamageFormFields.js +0 -39
  77. package/es/elements/ElementDamageForm/DuplicateDamage/DuplicateElementDamageDialog.js +0 -11
  78. package/es/elements/ElementDamageForm/index.d.ts +0 -13
  79. package/es/elements/ElementDamageForm/index.js +0 -219
  80. package/src/elements/ElementDamageForm/DamageFormFields.tsx +0 -149
  81. package/src/elements/ElementDamageForm/index.tsx +0 -397
  82. /package/es/elements/{ElementDamageForm → ElementDamage}/DuplicateDamage/DesktopView.d.ts +0 -0
  83. /package/es/elements/{ElementDamageForm → ElementDamage}/DuplicateDamage/DesktopView.js +0 -0
  84. /package/es/elements/{ElementDamageForm → ElementDamage}/DuplicateDamage/PhoneView.d.ts +0 -0
  85. /package/es/elements/{ElementDamageForm → ElementDamage}/DuplicateDamage/PhoneView.js +0 -0
  86. /package/es/elements/{ElementDamageForm → ElementDamage}/index.css +0 -0
  87. /package/es/elements/{AddElementDialog → ElementLookupDialog}/BarcodeScanner/DeadIcon.d.ts +0 -0
  88. /package/es/elements/{AddElementDialog → ElementLookupDialog}/BarcodeScanner/DeadIcon.js +0 -0
  89. /package/es/elements/{AddElementDialog → ElementLookupDialog}/BarcodeScanner/Error.d.ts +0 -0
  90. /package/es/elements/{AddElementDialog → ElementLookupDialog}/BarcodeScanner/Error.js +0 -0
  91. /package/es/elements/{AddElementDialog → ElementLookupDialog}/BarcodeScanner/index.d.ts +0 -0
  92. /package/es/elements/{AddElementDialog → ElementLookupDialog}/BarcodeScanner/index.js +0 -0
  93. /package/es/elements/{AddElementDialog → ElementLookupDialog}/BarcodeScanner/useScanner.d.ts +0 -0
  94. /package/es/elements/{AddElementDialog → ElementLookupDialog}/BarcodeScanner/useScanner.js +0 -0
  95. /package/es/elements/{AddElementDialog → ElementLookupDialog}/HIDScanner/index.css +0 -0
  96. /package/es/elements/{AddElementDialog → ElementLookupDialog}/HIDScanner/index.d.ts +0 -0
  97. /package/es/elements/{AddElementDialog → ElementLookupDialog}/HIDScanner/index.js +0 -0
  98. /package/es/elements/{AddElementDialog → ElementLookupDialog}/HIDScanner/useHIDScanner.d.ts +0 -0
  99. /package/es/elements/{AddElementDialog → ElementLookupDialog}/HIDScanner/useHIDScanner.js +0 -0
  100. /package/es/elements/{AddElementDialog → ElementLookupDialog}/Manual/ManualForm.d.ts +0 -0
  101. /package/es/elements/{AddElementDialog → ElementLookupDialog}/utils/Giai.d.ts +0 -0
  102. /package/es/elements/{AddElementDialog → ElementLookupDialog}/utils/Giai.js +0 -0
  103. /package/es/elements/{AddElementDialog → ElementLookupDialog}/utils/beep.d.ts +0 -0
  104. /package/es/elements/{AddElementDialog → ElementLookupDialog}/utils/beep.js +0 -0
  105. /package/src/elements/{ElementDamageForm → ElementDamage}/DuplicateDamage/DesktopView.tsx +0 -0
  106. /package/src/elements/{ElementDamageForm → ElementDamage}/DuplicateDamage/PhoneView.tsx +0 -0
  107. /package/src/elements/{ElementDamageForm → ElementDamage}/index.css +0 -0
  108. /package/src/elements/{AddElementDialog → ElementLookupDialog}/BarcodeScanner/DeadIcon.tsx +0 -0
  109. /package/src/elements/{AddElementDialog → ElementLookupDialog}/BarcodeScanner/Error.tsx +0 -0
  110. /package/src/elements/{AddElementDialog → ElementLookupDialog}/BarcodeScanner/index.tsx +0 -0
  111. /package/src/elements/{AddElementDialog → ElementLookupDialog}/BarcodeScanner/useScanner.ts +0 -0
  112. /package/src/elements/{AddElementDialog → ElementLookupDialog}/HIDScanner/index.css +0 -0
  113. /package/src/elements/{AddElementDialog → ElementLookupDialog}/HIDScanner/index.tsx +0 -0
  114. /package/src/elements/{AddElementDialog → ElementLookupDialog}/HIDScanner/useHIDScanner.ts +0 -0
  115. /package/src/elements/{AddElementDialog → ElementLookupDialog}/utils/Giai.ts +0 -0
  116. /package/src/elements/{AddElementDialog → ElementLookupDialog}/utils/beep.ts +0 -0
@@ -5,20 +5,20 @@ export type AddElement = {
5
5
  scanTime?: number;
6
6
  };
7
7
  type InitialTabProps = "camera" | "scanner" | "manual";
8
- export type AddElementDialogSharedProps = {
8
+ export type ElementLookupDialogSharedProps = {
9
9
  open: boolean;
10
10
  onClose: () => void;
11
11
  initialTab?: InitialTabProps | null;
12
12
  useSearch?: boolean;
13
13
  };
14
- export type AddElementDialogSingleModeProps = AddElementDialogSharedProps & {
14
+ export type ElementLookupDialogSingleModeProps = ElementLookupDialogSharedProps & {
15
15
  mode: "single" | "search";
16
16
  onAdd: (element: AddElement) => Promise<void>;
17
17
  };
18
- export type AddElementDialogMultiModeProps = AddElementDialogSharedProps & {
18
+ export type ElementLookupDialogMultiModeProps = ElementLookupDialogSharedProps & {
19
19
  mode: "multi";
20
20
  onAdd: (element: AddElement[]) => Promise<void>;
21
21
  };
22
- export type AddElementDialogProps = AddElementDialogSingleModeProps | AddElementDialogMultiModeProps;
23
- export declare function AddElementDialog(props: AddElementDialogProps): import("react/jsx-runtime").JSX.Element;
22
+ export type ElementLookupDialogProps = ElementLookupDialogSingleModeProps | ElementLookupDialogMultiModeProps;
23
+ export declare function ElementLookupDialog(props: ElementLookupDialogProps): import("react/jsx-runtime").JSX.Element;
24
24
  export {};
@@ -15,7 +15,7 @@ import { AddElementHIDScanner } from "./HIDScanner";
15
15
  import { AddElementManualForm } from "./Manual/ManualForm";
16
16
  import { useBeeper } from "./utils/beep";
17
17
  import Giai from "./utils/Giai";
18
- export function AddElementDialog(props) {
18
+ export function ElementLookupDialog(props) {
19
19
  let { open, onClose, initialTab } = props;
20
20
  let [tab, setTab] = useState("camera");
21
21
  let [elements, setElements] = useState([]);
@@ -67,6 +67,9 @@ export function AddElementDialog(props) {
67
67
  alert(error.message);
68
68
  }
69
69
  }
70
+ if (tab === "manual" && props.mode === "search") {
71
+ tab = "camera";
72
+ }
70
73
  return (_jsx(ResponsiveDialog, { open: open, onClose: onClose, slotProps: {
71
74
  paper: { sx: { overflow: "hidden" } },
72
75
  }, children: _jsxs(Box, { display: "flex", flexDirection: "column", maxHeight: "100%", overflow: "hidden", flexGrow: 1, children: [_jsxs(Tabs, { value: tab, onChange: (_, newTab) => setTab(newTab), variant: "fullWidth", sx: { flexShrink: 0 }, children: [props.mode !== "search" && _jsx(Tab, { icon: _jsx(Edit, {}), label: getLocalizedString("Manual"), value: "manual" }), _jsx(Tab, { icon: _jsx(TapAndPlay, {}), label: getLocalizedString("Scanner"), value: "scanner" }), _jsx(Tab, { icon: _jsx(QrCodeScanner, {}), label: getLocalizedString("Camera"), value: "camera" })] }), tab === "camera" && (_jsx(Box, { flexBasis: "12rem", flexGrow: 1, flexShrink: 2, children: _jsx(BarcodeScanner, { onRead: (element) => handleElementAdd(element, "camera-barcode") }) })), tab === "manual" && (_jsx(Box, { p: 2, children: _jsx(AddElementManualForm, { onAdd: (element) => handleElementAdd(element, "manual") }) })), tab === "scanner" && (_jsx(Box, { flexBasis: "12rem", flexGrow: 1, flexShrink: 2, children: _jsx(AddElementHIDScanner, { onScan: (element) => handleElementAdd(element, element.startsWith(Giai.BARCODE_PREFIX) ? "hid-barcode" : "hid-rfid") }) })), _jsxs(Box, { flex: "3 1 14rem", overflow: "auto", children: [props.mode === "multi" && (_jsx(Alert, { icon: false, severity: "info", sx: { justifyContent: "center", py: 0, position: "sticky", top: 0, zIndex: 1 }, slotProps: {
@@ -2,7 +2,7 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
2
2
  import { Autocomplete, ListItem, ListItemText, TextField } from "@mui/material";
3
3
  import { getLocalizedString } from "@olenbetong/appframe-core";
4
4
  import { useDataWithFilter, useDebounce } from "@olenbetong/appframe-react";
5
- import { useMemo, useState } from "react";
5
+ import { useMemo, useRef, useState } from "react";
6
6
  import { dsProjects } from "./data/dsProjects";
7
7
  import { dsReportProjects } from "./data/dsReportProjects";
8
8
  export function ProjectSelect({ className, disabled, id, names, onChange, readOnly, required, defaultValue, value, label, sx, report, }) {
@@ -10,7 +10,9 @@ export function ProjectSelect({ className, disabled, id, names, onChange, readOn
10
10
  let [query, setQuery] = useState("");
11
11
  let search = useDebounce(query);
12
12
  let projects = useDataWithFilter(report ? dsReportProjects : dsProjects, search ? `[SearchColumn] LIKE '%${search}%'` : "");
13
+ let highlightRef = useRef(null);
13
14
  function handleSelect(value) {
15
+ highlightRef.current = null;
14
16
  if (!disabled && !readOnly) {
15
17
  if (onChange) {
16
18
  onChange(value);
@@ -28,7 +30,12 @@ export function ProjectSelect({ className, disabled, id, names, onChange, readOn
28
30
  });
29
31
  return new Set([...nameCount.entries()].filter(([, count]) => count > 1).map(([name]) => name));
30
32
  }, [projects]);
31
- return (_jsxs(_Fragment, { children: [_jsx(Autocomplete, { sx: sx, autoHighlight: true, className: className, options: projects, disabled: disabled, getOptionLabel: (option) => option?.ProjectID !== undefined ? `${option.ProjectID}: ${option.ProjectName}` : "", isOptionEqualToValue: (option, value) => option.Domain === value.Domain && option.ProjectID === value.ProjectID, clearOnEscape: true, onChange: (_, value) => handleSelect(value), onClose: () => setQuery(""), value: value !== undefined ? value : selected, renderInput: (params) => (_jsx(TextField, { ...params, label: label ? label : getLocalizedString("Project ID"), id: id ?? "ProjectLookup", fullWidth: true, inputProps: { readOnly, ...params.inputProps }, autoComplete: "off", variant: "filled", required: required, onChange: (evt) => setQuery(evt.target.value), value: query })), renderOption: (props, option) => {
33
+ return (_jsxs(_Fragment, { children: [_jsx(Autocomplete, { sx: sx, autoHighlight: true, autoSelect: true, clearOnEscape: true, className: className, options: projects, disabled: disabled, getOptionLabel: (option) => option?.ProjectID !== undefined ? `${option.ProjectID}: ${option.ProjectName}` : "", isOptionEqualToValue: (option, value) => option.Domain === value.Domain && option.ProjectID === value.ProjectID, onChange: (_, value) => handleSelect(value), onClose: () => setQuery(""), value: value !== undefined ? value : selected, renderInput: (params) => (_jsx(TextField, { ...params, label: label ? label : getLocalizedString("Project ID"), id: id ?? "ProjectLookup", fullWidth: true, slotProps: {
34
+ htmlInput: {
35
+ readOnly,
36
+ ...params.inputProps,
37
+ },
38
+ }, autoComplete: "off", variant: "filled", required: required, onChange: (evt) => setQuery(evt.target.value), value: query })), renderOption: (props, option) => {
32
39
  let isDuplicated = option.ProjectName && duplicatedNames.has(option.ProjectName);
33
40
  return (_jsx(ListItem, { ...props, children: _jsx(ListItemText, { primary: isDuplicated ? `${option.ProjectName} (${option.Domain})` : option.ProjectName, secondary: option.ProjectID }) }));
34
41
  } }), _jsx("input", { name: names?.domain ?? "Domain", type: "hidden", value: current?.Domain ?? "" }), _jsx("input", { name: names?.name ?? "ProjectName", type: "hidden", value: current?.ProjectName ?? "" }), _jsx("input", { name: names?.projectId ?? "ProjectID", type: "hidden", value: current?.ProjectID ?? "" })] }));
@@ -17,8 +17,8 @@ export type DamagesRecord = {
17
17
  Action: string | null;
18
18
  RegisteredFix: Date | null;
19
19
  RegisteredFixBy: string | null;
20
+ RegisteredFixFullName: string | null;
20
21
  Cause: string | null;
21
- FullName: string | null;
22
22
  SearchColumn: string;
23
23
  ElementRef: string | null;
24
24
  };
@@ -100,12 +100,12 @@ export const dsDamages = generateApiDataObject({
100
100
  nullable: true,
101
101
  },
102
102
  {
103
- name: "Cause",
103
+ name: "RegisteredFixFullName",
104
104
  type: "string",
105
105
  nullable: true,
106
106
  },
107
107
  {
108
- name: "FullName",
108
+ name: "Cause",
109
109
  type: "string",
110
110
  nullable: true,
111
111
  },
@@ -1,6 +1,8 @@
1
1
  export type ElementsRecord = {
2
2
  PrimKey: string;
3
3
  ProjectID: string;
4
+ ProjectName: string;
4
5
  ElementID: string | null;
6
+ Name: string | null;
5
7
  };
6
8
  export declare const dsElements: import("@olenbetong/appframe-data").DataObject<ElementsRecord>;
@@ -4,7 +4,7 @@ af resources generate aviw_Production_Elements_All \
4
4
  --id dsElements \
5
5
  --types \
6
6
  --max-records 100 \
7
- --fields PrimKey,ProjectID,ElementID
7
+ --fields PrimKey,ProjectID,ElementID,ProjectName,Name
8
8
  */
9
9
  import { generateApiDataObject } from "@olenbetong/appframe-data";
10
10
  export const dsElements = generateApiDataObject({
@@ -25,11 +25,21 @@ export const dsElements = generateApiDataObject({
25
25
  type: "string",
26
26
  nullable: false,
27
27
  },
28
+ {
29
+ name: "ProjectName",
30
+ type: "string",
31
+ nullable: false,
32
+ },
28
33
  {
29
34
  name: "ElementID",
30
35
  type: "string",
31
36
  nullable: true,
32
37
  },
38
+ {
39
+ name: "Name",
40
+ type: "string",
41
+ nullable: true,
42
+ },
33
43
  ],
34
44
  parameters: {
35
45
  maxRecords: 100,
@@ -0,0 +1,10 @@
1
+ export type TransportElementsRecord = {
2
+ PrimKey: string;
3
+ DeliveryTicketID: number;
4
+ Domain: string;
5
+ ProjectID: string;
6
+ ProjectName: string;
7
+ ElementID: string | null;
8
+ Name: string | null;
9
+ };
10
+ export declare const dsTransportElements: import("@olenbetong/appframe-data").DataObject<TransportElementsRecord>;
@@ -0,0 +1,57 @@
1
+ /*
2
+ auto-generated by CLI:
3
+ af resources generate aviw_Fleet_DeliveryTickets_Elements \
4
+ --id dsTransportElements \
5
+ --types \
6
+ --max-records 100 \
7
+ --fields PrimKey,DeliveryTicketID,ProjectID,ProjectName,ElementID,Name,Domain
8
+ */
9
+ import { generateApiDataObject } from "@olenbetong/appframe-data";
10
+ export const dsTransportElements = generateApiDataObject({
11
+ resource: "aviw_Fleet_DeliveryTickets_Elements",
12
+ id: "dsTransportElements",
13
+ allowUpdate: false,
14
+ allowInsert: false,
15
+ allowDelete: false,
16
+ dynamicLoading: false,
17
+ fields: [
18
+ {
19
+ name: "PrimKey",
20
+ type: "string",
21
+ nullable: false,
22
+ },
23
+ {
24
+ name: "DeliveryTicketID",
25
+ type: "number",
26
+ nullable: false,
27
+ },
28
+ {
29
+ name: "Domain",
30
+ type: "string",
31
+ nullable: false,
32
+ },
33
+ {
34
+ name: "ProjectID",
35
+ type: "string",
36
+ nullable: false,
37
+ },
38
+ {
39
+ name: "ProjectName",
40
+ type: "string",
41
+ nullable: false,
42
+ },
43
+ {
44
+ name: "ElementID",
45
+ type: "string",
46
+ nullable: true,
47
+ },
48
+ {
49
+ name: "Name",
50
+ type: "string",
51
+ nullable: true,
52
+ },
53
+ ],
54
+ parameters: {
55
+ maxRecords: 100,
56
+ },
57
+ });
@@ -3,5 +3,9 @@ export * from "./dsCurrentAttachment.js";
3
3
  export * from "./dsDamages.js";
4
4
  export * from "./dsDamagesDuplicateCheck.js";
5
5
  export * from "./dsElements.js";
6
- export * from "./procApproveDamage.js";
7
6
  export * from "./dsProjects.js";
7
+ export * from "./procApproveDamage.js";
8
+ export * from "./procDeleteAttachment.js";
9
+ export * from "./procDeleteDamage.js";
10
+ export * from "./procRemoveDamageFix.js";
11
+ export * from "./procRestoreAttachments.js";
@@ -3,5 +3,9 @@ export * from "./dsCurrentAttachment.js";
3
3
  export * from "./dsDamages.js";
4
4
  export * from "./dsDamagesDuplicateCheck.js";
5
5
  export * from "./dsElements.js";
6
- export * from "./procApproveDamage.js";
7
6
  export * from "./dsProjects.js";
7
+ export * from "./procApproveDamage.js";
8
+ export * from "./procDeleteAttachment.js";
9
+ export * from "./procDeleteDamage.js";
10
+ export * from "./procRemoveDamageFix.js";
11
+ export * from "./procRestoreAttachments.js";
@@ -0,0 +1,2 @@
1
+ import { ProcedureAPI } from "@olenbetong/appframe-data";
2
+ export declare const procDeleteAttachment: ProcedureAPI<unknown, unknown>;
@@ -0,0 +1,18 @@
1
+ /*
2
+ auto-generated by CLI:
3
+ af resources generate astp_Production_ElementsDamages_DeleteAttachments \
4
+ --id procDeleteAttachment
5
+ */
6
+ import { ProcedureAPI } from "@olenbetong/appframe-data";
7
+ export const procDeleteAttachment = new ProcedureAPI({
8
+ procedureId: "astp_Production_ElementsDamages_DeleteAttachments",
9
+ parameters: [
10
+ {
11
+ name: "PrimKeyList",
12
+ type: "string",
13
+ hasDefault: false,
14
+ required: false,
15
+ },
16
+ ],
17
+ timeout: 30000,
18
+ });
@@ -0,0 +1,2 @@
1
+ import { ProcedureAPI } from "@olenbetong/appframe-data";
2
+ export declare const procDeleteDamage: ProcedureAPI<unknown, unknown>;
@@ -0,0 +1,18 @@
1
+ /*
2
+ auto-generated by CLI:
3
+ af resources generate astp_Production_ElementsDamages_Delete \
4
+ --id procDeleteDamage
5
+ */
6
+ import { ProcedureAPI } from "@olenbetong/appframe-data";
7
+ export const procDeleteDamage = new ProcedureAPI({
8
+ procedureId: "astp_Production_ElementsDamages_Delete",
9
+ parameters: [
10
+ {
11
+ name: "ID",
12
+ type: "number",
13
+ hasDefault: false,
14
+ required: false,
15
+ },
16
+ ],
17
+ timeout: 30000,
18
+ });
@@ -0,0 +1,2 @@
1
+ import { ProcedureAPI } from "@olenbetong/appframe-data";
2
+ export declare const procRemoveDamageFix: ProcedureAPI<unknown, unknown>;
@@ -0,0 +1,18 @@
1
+ /*
2
+ auto-generated by CLI:
3
+ af resources generate astp_Production_ElementsDamages_RemoveFix \
4
+ --id procRemoveDamageFix
5
+ */
6
+ import { ProcedureAPI } from "@olenbetong/appframe-data";
7
+ export const procRemoveDamageFix = new ProcedureAPI({
8
+ procedureId: "astp_Production_ElementsDamages_RemoveFix",
9
+ parameters: [
10
+ {
11
+ name: "ID",
12
+ type: "number",
13
+ hasDefault: false,
14
+ required: false,
15
+ },
16
+ ],
17
+ timeout: 30000,
18
+ });
@@ -0,0 +1,2 @@
1
+ import { ProcedureAPI } from "@olenbetong/appframe-data";
2
+ export declare const procRestoreAttachments: ProcedureAPI<unknown, unknown>;
@@ -0,0 +1,18 @@
1
+ /*
2
+ auto-generated by CLI:
3
+ af resources generate astp_Production_ElementsDamages_RestoreAttachments \
4
+ --id procRestoreAttachments
5
+ */
6
+ import { ProcedureAPI } from "@olenbetong/appframe-data";
7
+ export const procRestoreAttachments = new ProcedureAPI({
8
+ procedureId: "astp_Production_ElementsDamages_RestoreAttachments",
9
+ parameters: [
10
+ {
11
+ name: "PrimKeyList",
12
+ type: "string",
13
+ hasDefault: false,
14
+ required: false,
15
+ },
16
+ ],
17
+ timeout: 30000,
18
+ });
@@ -1,3 +1,9 @@
1
1
  export * from "./data/index.js";
2
- export * from "./AddElementDialog/index.js";
3
- export * from "./ElementDamageForm/index.js";
2
+ export * from "./ElementDamage/DescriptionInput.js";
3
+ export * from "./ElementDamage/DuplicateDamage/index.js";
4
+ export * from "./ElementDamage/ElementNumberTextField.js";
5
+ export * from "./ElementDamage/HiddenDamageFields.js";
6
+ export * from "./ElementDamage/RegisterFix.js";
7
+ export * from "./ElementDamage/SubmitButtons.js";
8
+ export * from "./ElementLookup.js";
9
+ export * from "./ElementLookupDialog/index.js";
@@ -1,3 +1,9 @@
1
1
  export * from "./data/index.js";
2
- export * from "./AddElementDialog/index.js";
3
- export * from "./ElementDamageForm/index.js";
2
+ export * from "./ElementDamage/DescriptionInput.js";
3
+ export * from "./ElementDamage/DuplicateDamage/index.js";
4
+ export * from "./ElementDamage/ElementNumberTextField.js";
5
+ export * from "./ElementDamage/HiddenDamageFields.js";
6
+ export * from "./ElementDamage/RegisterFix.js";
7
+ export * from "./ElementDamage/SubmitButtons.js";
8
+ export * from "./ElementLookup.js";
9
+ export * from "./ElementLookupDialog/index.js";
package/es/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export { Checkbox, type CheckboxProps } from "./components/Checkbox/index.js";
2
2
  export { CardColumn, CardDetail, CardLabel, CardStep, CardStepList, ColorCard } from "./components/ColorCard/index.js";
3
3
  export { DateNavigator } from "./components/DateNavigator/index.js";
4
+ export * from "./components/FilePond.js";
4
5
  export { Card, LinkedList, LinkedListItem } from "./components/LinkedCardList/index.js";
5
6
  export { BannerImage as PageBannerImage, type BannerImageProps, PageBanner, type PageBannerProps, Tab as PageBannerTab, TabList as PageBannerTabList, type TabListProps as PageBannerTabListProps, type TabProps as PageBannerTabProps, Title as PageBannerTitle, type TitleProps as PageBannerTitleProps, } from "./components/PageBanner/index.js";
6
7
  export { Portal } from "./components/Portal/index.js";
@@ -9,5 +10,4 @@ export { Sidebar, type SidebarProps } from "./components/Sidebar/index.js";
9
10
  export { Spinner, type SpinnerProps } from "./components/Spinner/index.js";
10
11
  export { SplitContainer, type SplitContainerProps } from "./components/SplitContainer/index.js";
11
12
  export { ValueToggleGroup, type ValueToggleGroupProps } from "./components/ValueToggleGroup/index.js";
12
- export { ElementDamageForm } from "./elements/ElementDamageForm/index.js";
13
13
  export { useTranslation } from "./useTranslation/index.js";
package/es/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  export { Checkbox } from "./components/Checkbox/index.js";
2
2
  export { CardColumn, CardDetail, CardLabel, CardStep, CardStepList, ColorCard } from "./components/ColorCard/index.js";
3
3
  export { DateNavigator } from "./components/DateNavigator/index.js";
4
+ export * from "./components/FilePond.js";
4
5
  export { Card, LinkedList, LinkedListItem } from "./components/LinkedCardList/index.js";
5
6
  export { BannerImage as PageBannerImage, PageBanner, Tab as PageBannerTab, TabList as PageBannerTabList, Title as PageBannerTitle, } from "./components/PageBanner/index.js";
6
7
  export { Portal } from "./components/Portal/index.js";
@@ -9,5 +10,4 @@ export { Sidebar } from "./components/Sidebar/index.js";
9
10
  export { Spinner } from "./components/Spinner/index.js";
10
11
  export { SplitContainer } from "./components/SplitContainer/index.js";
11
12
  export { ValueToggleGroup } from "./components/ValueToggleGroup/index.js";
12
- export { ElementDamageForm } from "./elements/ElementDamageForm/index.js";
13
13
  export { useTranslation } from "./useTranslation/index.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@olenbetong/synergi-react",
3
- "version": "2.2.3",
3
+ "version": "2.3.1",
4
4
  "description": "Standalone React component for SynergiWeb and Partner Portal",
5
5
  "type": "module",
6
6
  "exports": {
@@ -9,8 +9,8 @@
9
9
  "import": "./es/index.js"
10
10
  },
11
11
  "./elements": {
12
- "types": "./es/features/elements/index.d.ts",
13
- "import": "./es/features/elements/index.js"
12
+ "types": "./es/elements/index.d.ts",
13
+ "import": "./es/elements/index.js"
14
14
  }
15
15
  },
16
16
  "files": [
@@ -38,7 +38,7 @@
38
38
  "filepond-plugin-image-transform": "^3.8.7",
39
39
  "localforage": "^1.10.0",
40
40
  "mitt": "^3.0.1",
41
- "@olenbetong/appframe-core": "2.11.9"
41
+ "@olenbetong/appframe-core": "2.11.10"
42
42
  },
43
43
  "repository": {
44
44
  "type": "git",
@@ -4,7 +4,7 @@ import "filepond/dist/filepond.css";
4
4
 
5
5
  import { getLocalizedString } from "@olenbetong/appframe-core";
6
6
  import type { DataObject } from "@olenbetong/appframe-data";
7
- import { useData } from "@olenbetong/appframe-react";
7
+ import { useData, useFetchData } from "@olenbetong/appframe-react";
8
8
 
9
9
  import {
10
10
  create,
@@ -20,7 +20,7 @@ import FilePondPluginImageExifOrientation from "filepond-plugin-image-exif-orien
20
20
  import FilePondPluginImagePreview from "filepond-plugin-image-preview";
21
21
  import FilePondPluginImageResize from "filepond-plugin-image-resize";
22
22
  import FilePondPluginImageTransform from "filepond-plugin-image-transform";
23
- import { type RefObject, useEffect, useRef } from "react";
23
+ import { type RefObject, useEffect, useMemo, useRef } from "react";
24
24
 
25
25
  export { registerPlugin, FileStatus };
26
26
 
@@ -82,10 +82,11 @@ const labels = {
82
82
  type FilePondProps<T extends Record<string, unknown>> = React.HTMLProps<HTMLInputElement> & {
83
83
  dataObject: DataObject<T>;
84
84
  fields: Partial<T>;
85
- onFileStart: () => void;
86
- onFileProcessed: (error: FilePondErrorDescription | null, file: FilePondFile) => void;
87
- onFilesProcessed: () => void;
88
- onError: () => void;
85
+ onUploadStart: () => void;
86
+ onFileUploaded: (error: FilePondErrorDescription | null, file: FilePondFile) => void;
87
+ onFinishedUploads: () => void;
88
+ onError: (error: string) => void;
89
+ onFileRemoved?: (primKey: string) => void;
89
90
  /**
90
91
  * If the file should be uploaded to a blob field, set the field name here
91
92
  */
@@ -102,8 +103,28 @@ type FilePondProps<T extends Record<string, unknown>> = React.HTMLProps<HTMLInpu
102
103
  * Options to pass to FilePond
103
104
  */
104
105
  filePondOptions?: Partial<FilePondOptions>;
106
+ attachmentPrimKeys?: string[];
107
+ whereClause?: string;
105
108
  };
106
109
 
110
+ function getFileUrl<T extends Record<string, unknown>>(
111
+ dataObject: DataObject<T>,
112
+ fieldName?: string,
113
+ primKey?: string,
114
+ action = "upload",
115
+ ) {
116
+ let url =
117
+ action === "upload"
118
+ ? dataObject.dataHandler.getUploadUrl()
119
+ : dataObject.dataHandler.getFileStoreURL(primKey ?? "", fieldName ?? "");
120
+
121
+ if (action === "upload") {
122
+ url += "/";
123
+ }
124
+
125
+ return url?.replaceAll("//", "/") ?? "";
126
+ }
127
+
107
128
  type FileStoreDataObjectRecord = {
108
129
  PrimKey: string;
109
130
  FileName: string | null;
@@ -117,19 +138,29 @@ type FileStoreDataObjectRecord = {
117
138
  export function FilePond<T extends FileStoreDataObjectRecord>({
118
139
  dataObject,
119
140
  fields,
120
- onFileStart,
121
- onFileProcessed,
122
- onFilesProcessed,
141
+ onUploadStart,
142
+ onFileUploaded,
143
+ onFinishedUploads,
144
+ onFileRemoved,
123
145
  onError,
124
146
  fieldName,
125
147
  filePondOptions,
126
148
  primKey,
149
+ attachmentPrimKeys,
150
+ whereClause,
127
151
  inputRef: inputRefProp,
128
152
  ...props
129
153
  }: FilePondProps<T>) {
130
154
  let inputRef = useRef<HTMLInputElement>(null);
131
155
  let pondRef = useRef<FilePondInstance | null>(null);
132
- let files = useData(dataObject);
156
+ let filesData = useData(dataObject);
157
+ let { data: filesFetched } = useFetchData(dataObject, whereClause ?? "1=2");
158
+ let files = useMemo(() => {
159
+ if (whereClause) {
160
+ return filesFetched;
161
+ }
162
+ return filesData;
163
+ }, [whereClause, filesFetched, filesData]);
133
164
  let clearFilesRef = useRef(false);
134
165
 
135
166
  useEffect(() => {
@@ -154,6 +185,7 @@ export function FilePond<T extends FileStoreDataObjectRecord>({
154
185
  } as Partial<T>);
155
186
 
156
187
  if (result) {
188
+ onFileRemoved?.(source);
157
189
  load();
158
190
  } else {
159
191
  error("Failed to delete file on server. Delete request returned false");
@@ -168,12 +200,6 @@ export function FilePond<T extends FileStoreDataObjectRecord>({
168
200
  }
169
201
  }
170
202
 
171
- let uploadUrl = dataObject.dataHandler.getUploadUrl({ fieldName, primKey });
172
-
173
- if (!uploadUrl) {
174
- throw new Error("DataHandler does not support file uploads.");
175
- }
176
-
177
203
  let options: FilePondOptions = {
178
204
  allowMultiple: Boolean(props.multiple),
179
205
  allowImageResize: true,
@@ -182,11 +208,26 @@ export function FilePond<T extends FileStoreDataObjectRecord>({
182
208
  imageResizeTargetHeight: 2400,
183
209
  imageResizeUpscale: false,
184
210
  ...labels,
185
- onaddfilestart: () => onFileStart(),
186
- onprocessfile: (error, file) => onFileProcessed(error, file),
187
- onprocessfiles: () => onFilesProcessed(),
188
- onerror: () => onError(),
189
- beforeRemoveFile: (_file) => {
211
+ onaddfilestart: (file) => {
212
+ if (file.status !== 5 && file.status !== 6 && file.status !== 10) {
213
+ onUploadStart();
214
+ }
215
+ },
216
+ onprocessfile: (error, file) => {
217
+ onFileUploaded(error, file);
218
+
219
+ let refFiles = pondRef.current?.getFiles();
220
+ let found = refFiles?.find(
221
+ (file) => file.status !== 2 && file.status !== 5 && file.status !== 6 && file.status !== 10,
222
+ );
223
+
224
+ if (found === undefined) {
225
+ onFinishedUploads();
226
+ }
227
+ },
228
+ onprocessfiles: () => onFinishedUploads(),
229
+ onerror: (error) => onError(error.body),
230
+ beforeRemoveFile: () => {
190
231
  if (confirm(getLocalizedString("Are you sure you want to remove this file?"))) {
191
232
  return true;
192
233
  }
@@ -194,11 +235,14 @@ export function FilePond<T extends FileStoreDataObjectRecord>({
194
235
  return false;
195
236
  },
196
237
  server: {
238
+ load: getFileUrl(dataObject, fieldName, primKey, "view"),
239
+ restore: getFileUrl(dataObject, fieldName, primKey, "view"),
240
+
197
241
  revert: removeUploadedFile,
198
242
  remove: removeUploadedFile,
199
243
 
200
244
  process: {
201
- url: uploadUrl,
245
+ url: getFileUrl(dataObject, fieldName),
202
246
  ondata: (formData) => {
203
247
  let masterChildCriteria = dataObject.getParameter("masterChildCriteria");
204
248
  let allFields = { ...masterChildCriteria, ...fields };
@@ -227,13 +271,14 @@ export function FilePond<T extends FileStoreDataObjectRecord>({
227
271
  props.multiple,
228
272
  fields,
229
273
  fieldName,
274
+ primKey,
230
275
  inputRefProp,
231
276
  filePondOptions,
232
277
  onError,
233
- onFileProcessed,
234
- onFileStart,
235
- onFilesProcessed,
236
- primKey,
278
+ onFileUploaded,
279
+ onUploadStart,
280
+ onFinishedUploads,
281
+ onFileRemoved,
237
282
  ]);
238
283
 
239
284
  useEffect(() => {
@@ -259,6 +304,8 @@ export function FilePond<T extends FileStoreDataObjectRecord>({
259
304
 
260
305
  return (
261
306
  <div className="filepond--wrapper">
307
+ {attachmentPrimKeys && <input type="hidden" name="AttachmentPrimkeys" value={attachmentPrimKeys} />}
308
+
262
309
  <input type="file" {...props} name="File" ref={inputRefProp ?? inputRef} />
263
310
  </div>
264
311
  );
@@ -0,0 +1,35 @@
1
+ import Add from "@mui/icons-material/Add";
2
+ import { Button } from "@mui/material";
3
+ import { getLocalizedString } from "@olenbetong/appframe-core";
4
+
5
+ type DamageFormButtonsProps = {
6
+ isEdit: boolean;
7
+ loading: boolean;
8
+ uploadingFile: boolean;
9
+ handleDelete: () => void;
10
+ handleCancel: () => void;
11
+ };
12
+
13
+ export function DamageFormButtonsProps({
14
+ isEdit,
15
+ loading,
16
+ uploadingFile,
17
+ handleDelete,
18
+ handleCancel,
19
+ }: DamageFormButtonsProps) {
20
+ return (
21
+ <>
22
+ {isEdit && <Button onClick={handleDelete}>{getLocalizedString("Delete")}</Button>}
23
+ <Button onClick={handleCancel}>{getLocalizedString("Cancel")}</Button>
24
+ <Button
25
+ loading={loading || uploadingFile}
26
+ loadingPosition="start"
27
+ startIcon={<Add />}
28
+ type="submit"
29
+ variant="contained"
30
+ >
31
+ {isEdit ? getLocalizedString("Save changes") : getLocalizedString("Register damage")}
32
+ </Button>
33
+ </>
34
+ );
35
+ }