@asaleh37/ui-base 1.2.17 → 1.2.19
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/.env.development +1 -1
- package/dist/index.d.ts +27 -5
- package/dist/index.js +5 -5
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +5 -5
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/public/no_image.png +0 -0
- package/src/components/administration/admin/OrganizationApplicationModuleGrid.tsx +10 -34
- package/src/components/administration/admin/OrganizationGrid.tsx +4 -87
- package/src/components/administration/admin/OrganizationRankGrid.tsx +34 -16
- package/src/components/administration/admin/OrganizationUnitGrid.tsx +34 -30
- package/src/components/administration/admin/OrganizationUnitTypeGrid.tsx +3 -16
- package/src/components/administration/admin/PersonGrid.tsx +38 -1
- package/src/components/administration/admin/RoleAuthoritiesForm.tsx +2 -4
- package/src/components/administration/admin/SystemApplicationAuthorityGrid.tsx +2 -18
- package/src/components/administration/admin/SystemApplicationGrid.tsx +5 -83
- package/src/components/administration/admin/SystemApplicationModuleGrid.tsx +2 -15
- package/src/components/administration/admin/SystemApplicationRoleGrid.tsx +1 -15
- package/src/components/administration/dev/AttachmentConfigGrid.tsx +213 -0
- package/src/components/administration/dev/AttachmentGrid.tsx +172 -0
- package/src/components/administration/dev/LookupGrid.tsx +1 -12
- package/src/components/common/Home.tsx +24 -22
- package/src/components/templates/DataEntryTemplates/DataEntryTypes.ts +13 -1
- package/src/components/templates/DataEntryTemplates/DataEntryUtil.ts +6 -0
- package/src/components/templates/DataEntryTemplates/TemplateDataForm/FormElementField.tsx +1 -3
- package/src/components/templates/DataEntryTemplates/TemplateDataForm/FormFields/SystemLookupCombobox.tsx +1 -1
- package/src/components/templates/DataEntryTemplates/TemplateDataForm/TemplateForm.tsx +100 -8
- package/src/components/templates/DataEntryTemplates/TemplateDataGrid/TemplateGrid.tsx +113 -4
- package/src/components/templates/attachment/AttachmentCard.tsx +126 -0
- package/src/components/templates/attachment/AttachmentImageViewer.tsx +44 -0
- package/src/components/templates/attachment/AttachmentPanel.tsx +269 -0
- package/src/components/templates/workflow/WorkflowDocumentPanel.tsx +4 -4
- package/src/hooks/UseSession.tsx +20 -2
- package/src/hooks/useAxios.tsx +71 -11
- package/src/hooks/useLookupGridColumn.tsx +2 -2
- package/src/layout/MainContent.tsx +49 -46
- package/src/layout/TopBar.tsx +6 -1
- package/src/locales/arabic/devLocalsAr.json +13 -1
- package/src/locales/english/devLocalsEn.json +13 -1
- package/src/main.tsx +3 -3
- package/src/navigationItems/Administration/adminNavigationItems.tsx +77 -3
- package/src/redux/features/administration/AdministrationStoresMetaData.ts +14 -6
- package/src/routes/administration/adminRoutes.tsx +21 -0
- package/src/routes/administration/devRoutes.tsx +24 -0
- package/public/icons/LICENSE.md +0 -5
- package/public/icons/arrow-clockwise.svg +0 -4
- package/public/icons/arrow-counterclockwise.svg +0 -4
- package/public/icons/journal-text.svg +0 -5
- package/public/icons/justify.svg +0 -3
- package/public/icons/text-center.svg +0 -3
- package/public/icons/text-left.svg +0 -3
- package/public/icons/text-paragraph.svg +0 -3
- package/public/icons/text-right.svg +0 -3
- package/public/icons/type-bold.svg +0 -3
- package/public/icons/type-italic.svg +0 -3
- package/public/icons/type-strikethrough.svg +0 -3
- package/public/icons/type-underline.svg +0 -3
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { attachment } from "./../attachment/AttachmentCard";
|
|
1
2
|
import { IconProp } from "@fortawesome/fontawesome-svg-core";
|
|
2
3
|
import {
|
|
3
4
|
DataGridPremiumProps,
|
|
@@ -96,7 +97,14 @@ export type TemplateGridColDef = GridColDef & {
|
|
|
96
97
|
valueField?: string;
|
|
97
98
|
};
|
|
98
99
|
|
|
100
|
+
export type TemplateGridAttachmentProps = {
|
|
101
|
+
attachmentCode: string;
|
|
102
|
+
enableAttachFn?: (record: any) => boolean;
|
|
103
|
+
};
|
|
104
|
+
|
|
99
105
|
export type TemplateGridProps = {
|
|
106
|
+
workFlowDocumentCode?: string;
|
|
107
|
+
attachment?: TemplateGridAttachmentProps;
|
|
100
108
|
formElements: Array<FormElementProps>;
|
|
101
109
|
gridStateKey?: string;
|
|
102
110
|
data: Array<any>;
|
|
@@ -178,7 +186,8 @@ export type RecordFieldProps = {
|
|
|
178
186
|
| "combobox"
|
|
179
187
|
| "checkbox"
|
|
180
188
|
| "html"
|
|
181
|
-
| "lookup"
|
|
189
|
+
| "lookup"
|
|
190
|
+
| "custom";
|
|
182
191
|
lookupType?: string;
|
|
183
192
|
required?: boolean;
|
|
184
193
|
disabled?: boolean;
|
|
@@ -259,6 +268,9 @@ export type FormActionProps = {
|
|
|
259
268
|
};
|
|
260
269
|
|
|
261
270
|
export type TemplateFormProps = {
|
|
271
|
+
workFlowDocumentCode?: string;
|
|
272
|
+
attachment?: TemplateGridAttachmentProps;
|
|
273
|
+
keyColumnName?: any;
|
|
262
274
|
elements: Array<FormElementProps>;
|
|
263
275
|
findByIdParamName?: string;
|
|
264
276
|
recordIdToEdit?: any;
|
|
@@ -164,6 +164,12 @@ export const constructGridColumnsFromFields: (
|
|
|
164
164
|
minWidth: 200,
|
|
165
165
|
});
|
|
166
166
|
columns.push(column);
|
|
167
|
+
} else {
|
|
168
|
+
const column: TemplateGridColDef = {
|
|
169
|
+
field: tableField.fieldName,
|
|
170
|
+
...tableField?.gridProps?.muiProps,
|
|
171
|
+
};
|
|
172
|
+
columns.push(column);
|
|
167
173
|
}
|
|
168
174
|
}
|
|
169
175
|
return columns;
|
|
@@ -22,7 +22,7 @@ const SystemLookupCombobox: React.FC<SystemLookupListProps> = (props) => {
|
|
|
22
22
|
|
|
23
23
|
const loadLookupOptions = async () => {
|
|
24
24
|
await handleGetRequest({
|
|
25
|
-
endPointURI: "api/v1/
|
|
25
|
+
endPointURI: "api/v1/public/system/lookup",
|
|
26
26
|
showMask: true,
|
|
27
27
|
parameters: { lookupType: props.lookupType },
|
|
28
28
|
successCallBkFn: (response: any) => {
|
|
@@ -4,7 +4,7 @@ import * as z from "zod";
|
|
|
4
4
|
import { useForm } from "react-hook-form";
|
|
5
5
|
import { zodResolver } from "@hookform/resolvers/zod";
|
|
6
6
|
import { useParams } from "react-router-dom";
|
|
7
|
-
import { Button, Grid2 } from "@mui/material";
|
|
7
|
+
import { Button, Grid2, Icon, IconButton, Tooltip } from "@mui/material";
|
|
8
8
|
import { toast } from "react-toastify";
|
|
9
9
|
import FormElementGroup from "./FormElementGroup";
|
|
10
10
|
import FormElementField from "./FormElementField";
|
|
@@ -17,10 +17,33 @@ import {
|
|
|
17
17
|
} from "../DataEntryTypes";
|
|
18
18
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|
19
19
|
import { useTranslation } from "react-i18next";
|
|
20
|
+
import { useWindow } from "../../../../hooks";
|
|
21
|
+
import AttachmentPanel from "../../attachment/AttachmentPanel";
|
|
22
|
+
import WorkflowDocumentPanel from "../../workflow/WorkflowDocumentPanel";
|
|
20
23
|
|
|
21
24
|
const TemplateForm: React.FC<TemplateFormProps> = (
|
|
22
25
|
props: TemplateFormProps
|
|
23
26
|
) => {
|
|
27
|
+
const { Window: AttachmentWindow, setWindowState: setAttachmentWindowState } =
|
|
28
|
+
useWindow({
|
|
29
|
+
windowTitle: "Attachments",
|
|
30
|
+
windowIcon: "paperclip",
|
|
31
|
+
width: "fit-content",
|
|
32
|
+
height: "fit-content",
|
|
33
|
+
minHeight: 500,
|
|
34
|
+
minWidth: 400,
|
|
35
|
+
});
|
|
36
|
+
const { Window: WorkflowWindow, setWindowState: setWorkflowWindowState } =
|
|
37
|
+
useWindow({
|
|
38
|
+
windowTitle: "Approvals",
|
|
39
|
+
windowIcon: "stamp",
|
|
40
|
+
width: "fit-content",
|
|
41
|
+
height: "fit-content",
|
|
42
|
+
minHeight: 500,
|
|
43
|
+
minWidth: 400,
|
|
44
|
+
});
|
|
45
|
+
const [attachmentPanelEnabledForRecord, setAttachmentPanelEnabledForRecord] =
|
|
46
|
+
useState<boolean>(true);
|
|
24
47
|
const { t } = useTranslation();
|
|
25
48
|
const fields = getAllFields(props.elements);
|
|
26
49
|
const initiallyHiddenFields = [];
|
|
@@ -141,8 +164,47 @@ const TemplateForm: React.FC<TemplateFormProps> = (
|
|
|
141
164
|
loadRecord();
|
|
142
165
|
}, [props?.recordIdToEdit]);
|
|
143
166
|
|
|
167
|
+
useEffect(() => {
|
|
168
|
+
if (props?.attachment && props?.attachment?.enableAttachFn) {
|
|
169
|
+
setAttachmentPanelEnabledForRecord(
|
|
170
|
+
props.attachment.enableAttachFn(formValues)
|
|
171
|
+
);
|
|
172
|
+
} else {
|
|
173
|
+
setAttachmentPanelEnabledForRecord(true);
|
|
174
|
+
}
|
|
175
|
+
}, [formValues]);
|
|
176
|
+
|
|
144
177
|
return (
|
|
145
178
|
<>
|
|
179
|
+
{props?.attachment ? (
|
|
180
|
+
<AttachmentWindow>
|
|
181
|
+
<AttachmentPanel
|
|
182
|
+
attachmentCode={props.attachment.attachmentCode}
|
|
183
|
+
refKey={formValues[props?.keyColumnName || "id"]}
|
|
184
|
+
enableAttachment={attachmentPanelEnabledForRecord}
|
|
185
|
+
/>
|
|
186
|
+
</AttachmentWindow>
|
|
187
|
+
) : (
|
|
188
|
+
<></>
|
|
189
|
+
)}
|
|
190
|
+
{props?.workFlowDocumentCode ? (
|
|
191
|
+
<WorkflowWindow>
|
|
192
|
+
<WorkflowDocumentPanel
|
|
193
|
+
workFlowDocumentCode={props.workFlowDocumentCode}
|
|
194
|
+
refDocumentId={formValues[props?.keyColumnName || "id"]}
|
|
195
|
+
postActionCallBk={() => {
|
|
196
|
+
setWorkflowWindowState(false);
|
|
197
|
+
loadRecord();
|
|
198
|
+
}}
|
|
199
|
+
cancelActionCallBk={() => {
|
|
200
|
+
setWorkflowWindowState(false);
|
|
201
|
+
}}
|
|
202
|
+
/>
|
|
203
|
+
</WorkflowWindow>
|
|
204
|
+
) : (
|
|
205
|
+
<></>
|
|
206
|
+
)}
|
|
207
|
+
|
|
146
208
|
<Box
|
|
147
209
|
sx={{
|
|
148
210
|
display: "flex",
|
|
@@ -218,14 +280,44 @@ const TemplateForm: React.FC<TemplateFormProps> = (
|
|
|
218
280
|
justifyContent: "flex-start",
|
|
219
281
|
}}
|
|
220
282
|
>
|
|
283
|
+
{formValues[props?.keyColumnName || "id"] ? (
|
|
284
|
+
props?.attachment ? (
|
|
285
|
+
<Tooltip title="Attachments">
|
|
286
|
+
<IconButton
|
|
287
|
+
onClick={() => {
|
|
288
|
+
setAttachmentWindowState(true);
|
|
289
|
+
}}
|
|
290
|
+
>
|
|
291
|
+
<FontAwesomeIcon icon="paperclip" />
|
|
292
|
+
</IconButton>
|
|
293
|
+
</Tooltip>
|
|
294
|
+
) : null
|
|
295
|
+
) : null}
|
|
296
|
+
{formValues[props?.keyColumnName || "id"] ? (
|
|
297
|
+
props?.workFlowDocumentCode ? (
|
|
298
|
+
<Tooltip title="Approvals">
|
|
299
|
+
<IconButton
|
|
300
|
+
onClick={() => {
|
|
301
|
+
setWorkflowWindowState(true);
|
|
302
|
+
}}
|
|
303
|
+
>
|
|
304
|
+
<FontAwesomeIcon icon="stamp" />
|
|
305
|
+
</IconButton>
|
|
306
|
+
</Tooltip>
|
|
307
|
+
) : null
|
|
308
|
+
) : null}
|
|
221
309
|
{props?.actions ? (
|
|
222
|
-
props
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
310
|
+
formValues[props?.keyColumnName || "id"] ? (
|
|
311
|
+
props.actions.map((action: RecordAction) => {
|
|
312
|
+
if (action?.formActionProps?.enabled === true) {
|
|
313
|
+
return <FormAction {...action} record={formValues} />;
|
|
314
|
+
} else {
|
|
315
|
+
return <></>;
|
|
316
|
+
}
|
|
317
|
+
})
|
|
318
|
+
) : (
|
|
319
|
+
<></>
|
|
320
|
+
)
|
|
229
321
|
) : (
|
|
230
322
|
<></>
|
|
231
323
|
)}
|
|
@@ -47,6 +47,8 @@ import { useWindow } from "../../../../hooks/UseWindow";
|
|
|
47
47
|
import { useAxios } from "../../../../hooks";
|
|
48
48
|
import useLookupGridColumn from "../../../../hooks/useLookupGridColumn";
|
|
49
49
|
import { ContinuousColorLegend } from "@mui/x-charts";
|
|
50
|
+
import AttachmentPanel from "../../attachment/AttachmentPanel";
|
|
51
|
+
import WorkflowDocumentPanel from "../../workflow/WorkflowDocumentPanel";
|
|
50
52
|
let currentNewRecordIndex = -1;
|
|
51
53
|
|
|
52
54
|
interface GridState {
|
|
@@ -78,12 +80,33 @@ const saveGridState = (gridStateKey: string, statePart: GridState) => {
|
|
|
78
80
|
const PIN_FIXED_COLUMNS = ["__check__", "actions"];
|
|
79
81
|
|
|
80
82
|
const TemplateGrid: React.FC<TemplateGridProps> = (props) => {
|
|
83
|
+
const { t } = useTranslation();
|
|
81
84
|
const AppLayout = useSelector((state: any) => state.AppLayout);
|
|
85
|
+
const [selectedRecord, setSelectedRecord] = useState<any>({});
|
|
86
|
+
const [attachmentPanelEnabledForRecord, setAttachmentPanelEnabledForRecord] =
|
|
87
|
+
useState<boolean>(true);
|
|
82
88
|
const { getLookupOptions } = useLookupGridColumn();
|
|
89
|
+
const { Window: AttachmentWindow, setWindowState: setAttachmentWindowState } =
|
|
90
|
+
useWindow({
|
|
91
|
+
windowTitle: t(props.gridTitle) + " Attachments",
|
|
92
|
+
windowIcon: "paperclip",
|
|
93
|
+
width: "fit-content",
|
|
94
|
+
height: "fit-content",
|
|
95
|
+
minHeight: 500,
|
|
96
|
+
minWidth: 400,
|
|
97
|
+
});
|
|
98
|
+
const { Window: WorkFlowWindow, setWindowState: setWorkFlowWindowState } =
|
|
99
|
+
useWindow({
|
|
100
|
+
windowTitle: t(props.gridTitle) + " Attachments",
|
|
101
|
+
windowIcon: "paperclip",
|
|
102
|
+
width: "fit-content",
|
|
103
|
+
height: "fit-content",
|
|
104
|
+
minHeight: 500,
|
|
105
|
+
minWidth: 400,
|
|
106
|
+
});
|
|
83
107
|
const [generatedColumns, setGeneratedColumns] = useState<
|
|
84
108
|
Array<TemplateGridColDef>
|
|
85
109
|
>([]);
|
|
86
|
-
const { t } = useTranslation();
|
|
87
110
|
const fields = getAllFields(props.formElements);
|
|
88
111
|
const hiddenFields = [];
|
|
89
112
|
const savedState = React.useMemo<GridState>(
|
|
@@ -174,7 +197,7 @@ const TemplateGrid: React.FC<TemplateGridProps> = (props) => {
|
|
|
174
197
|
gridColumn.options = await getLookupOptions(gridColumn.lookupType);
|
|
175
198
|
gridColumn.valueField = "lookupValue";
|
|
176
199
|
}
|
|
177
|
-
}
|
|
200
|
+
}
|
|
178
201
|
setGeneratedColumns(gridColumns);
|
|
179
202
|
};
|
|
180
203
|
const [rowSelectionModel, setRowSelectionModel] =
|
|
@@ -558,6 +581,57 @@ const TemplateGrid: React.FC<TemplateGridProps> = (props) => {
|
|
|
558
581
|
}
|
|
559
582
|
}
|
|
560
583
|
}
|
|
584
|
+
if (
|
|
585
|
+
record[props?.keyColumnName || "id"] &&
|
|
586
|
+
record[props?.keyColumnName || "id"] > 0 &&
|
|
587
|
+
props?.attachment
|
|
588
|
+
) {
|
|
589
|
+
actions?.push(
|
|
590
|
+
<GridActionsCellItem
|
|
591
|
+
icon={
|
|
592
|
+
<Tooltip title={"Attachments"}>
|
|
593
|
+
<FontAwesomeIcon icon={"paperclip"} />
|
|
594
|
+
</Tooltip>
|
|
595
|
+
}
|
|
596
|
+
label={"Attachments"}
|
|
597
|
+
className="textPrimary"
|
|
598
|
+
color="inherit"
|
|
599
|
+
onClick={() => {
|
|
600
|
+
setSelectedRecord(record);
|
|
601
|
+
if (props?.attachment?.enableAttachFn) {
|
|
602
|
+
setAttachmentPanelEnabledForRecord(
|
|
603
|
+
props.attachment.enableAttachFn(record)
|
|
604
|
+
);
|
|
605
|
+
} else {
|
|
606
|
+
setAttachmentPanelEnabledForRecord(true);
|
|
607
|
+
}
|
|
608
|
+
setAttachmentWindowState(true);
|
|
609
|
+
}}
|
|
610
|
+
/>
|
|
611
|
+
);
|
|
612
|
+
}
|
|
613
|
+
if (
|
|
614
|
+
record[props?.keyColumnName || "id"] &&
|
|
615
|
+
record[props?.keyColumnName || "id"] > 0 &&
|
|
616
|
+
props?.workFlowDocumentCode
|
|
617
|
+
) {
|
|
618
|
+
actions?.push(
|
|
619
|
+
<GridActionsCellItem
|
|
620
|
+
icon={
|
|
621
|
+
<Tooltip title={"Approvals"}>
|
|
622
|
+
<FontAwesomeIcon icon={"stamp"} />
|
|
623
|
+
</Tooltip>
|
|
624
|
+
}
|
|
625
|
+
label={"Approvals"}
|
|
626
|
+
className="textPrimary"
|
|
627
|
+
color="inherit"
|
|
628
|
+
onClick={() => {
|
|
629
|
+
setSelectedRecord(record);
|
|
630
|
+
setWorkFlowWindowState(true);
|
|
631
|
+
}}
|
|
632
|
+
/>
|
|
633
|
+
);
|
|
634
|
+
}
|
|
561
635
|
if (props?.rowActions) {
|
|
562
636
|
for (const rowAction of props.rowActions) {
|
|
563
637
|
if (
|
|
@@ -590,7 +664,9 @@ const TemplateGrid: React.FC<TemplateGridProps> = (props) => {
|
|
|
590
664
|
width:
|
|
591
665
|
(props?.rowActions ? props.rowActions.length * 30 : 0) +
|
|
592
666
|
(props?.editAction && props?.editAction?.isEnabled ? 30 : 0) +
|
|
593
|
-
(props?.deleteAction && props?.deleteAction?.isEnabled ? 30 : 0)
|
|
667
|
+
(props?.deleteAction && props?.deleteAction?.isEnabled ? 30 : 0) +
|
|
668
|
+
(props?.attachment ? 30 : 0) +
|
|
669
|
+
(props?.workFlowDocumentCode ? 30 : 0),
|
|
594
670
|
getActions: getActionColumnActions,
|
|
595
671
|
};
|
|
596
672
|
|
|
@@ -614,6 +690,10 @@ const TemplateGrid: React.FC<TemplateGridProps> = (props) => {
|
|
|
614
690
|
adjustGridColumns();
|
|
615
691
|
}, []);
|
|
616
692
|
|
|
693
|
+
useEffect(() => {
|
|
694
|
+
props.apiActions.reloadData(props?.gridLoadParametersValues);
|
|
695
|
+
}, [session.UserInfo?.currentOrganization]);
|
|
696
|
+
|
|
617
697
|
useEffect(() => {
|
|
618
698
|
adjustGridColumns();
|
|
619
699
|
}, [themeDirection, props.formElements]);
|
|
@@ -698,6 +778,8 @@ const TemplateGrid: React.FC<TemplateGridProps> = (props) => {
|
|
|
698
778
|
/>
|
|
699
779
|
) : (
|
|
700
780
|
<TemplateForm
|
|
781
|
+
keyColumnName={props.keyColumnName}
|
|
782
|
+
attachment={props.attachment}
|
|
701
783
|
formLoadCallBk={props.formLoadCallBk}
|
|
702
784
|
recordIdToEdit={
|
|
703
785
|
recordToEdit ? recordToEdit[keyColumnName] : undefined
|
|
@@ -818,7 +900,34 @@ const TemplateGrid: React.FC<TemplateGridProps> = (props) => {
|
|
|
818
900
|
) : (
|
|
819
901
|
<></>
|
|
820
902
|
)}
|
|
821
|
-
|
|
903
|
+
{props?.attachment ? (
|
|
904
|
+
<AttachmentWindow>
|
|
905
|
+
<AttachmentPanel
|
|
906
|
+
attachmentCode={props.attachment.attachmentCode}
|
|
907
|
+
refKey={selectedRecord[props?.keyColumnName || "id"]}
|
|
908
|
+
enableAttachment={attachmentPanelEnabledForRecord}
|
|
909
|
+
/>
|
|
910
|
+
</AttachmentWindow>
|
|
911
|
+
) : (
|
|
912
|
+
<></>
|
|
913
|
+
)}
|
|
914
|
+
{props?.workFlowDocumentCode ? (
|
|
915
|
+
<WorkFlowWindow>
|
|
916
|
+
<WorkflowDocumentPanel
|
|
917
|
+
workFlowDocumentCode={props.workFlowDocumentCode}
|
|
918
|
+
refDocumentId={selectedRecord[props?.keyColumnName || "id"]}
|
|
919
|
+
postActionCallBk={() => {
|
|
920
|
+
setWorkFlowWindowState(false);
|
|
921
|
+
props.apiActions.reloadData(props.gridLoadParametersValues);
|
|
922
|
+
}}
|
|
923
|
+
cancelActionCallBk={() => {
|
|
924
|
+
setWorkFlowWindowState(false);
|
|
925
|
+
}}
|
|
926
|
+
/>
|
|
927
|
+
</WorkFlowWindow>
|
|
928
|
+
) : (
|
|
929
|
+
<></>
|
|
930
|
+
)}
|
|
822
931
|
<DataGridPremium
|
|
823
932
|
{...props?.muiProps}
|
|
824
933
|
slots={{ toolbar: TemplateGridTopBar }}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import Card from "@mui/material/Card";
|
|
2
|
+
import CardActions from "@mui/material/CardActions";
|
|
3
|
+
import CardContent from "@mui/material/CardContent";
|
|
4
|
+
import CardMedia from "@mui/material/CardMedia";
|
|
5
|
+
import Button from "@mui/material/Button";
|
|
6
|
+
import Typography from "@mui/material/Typography";
|
|
7
|
+
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|
8
|
+
import { IconButton, Tooltip } from "@mui/material";
|
|
9
|
+
import { useAxios, useConfirmationWindow } from "../../../hooks";
|
|
10
|
+
import AttachmentImageViewer from "./AttachmentImageViewer";
|
|
11
|
+
|
|
12
|
+
export type attachment = {
|
|
13
|
+
attachmentCode: string;
|
|
14
|
+
setAttachmentConfig: (props: any) => void;
|
|
15
|
+
id: number;
|
|
16
|
+
attachmentConfigId: number;
|
|
17
|
+
attachmentSize: number;
|
|
18
|
+
category: string;
|
|
19
|
+
docType: string;
|
|
20
|
+
fileName: string;
|
|
21
|
+
refKey: string;
|
|
22
|
+
remark: string;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const AttachmentCard: React.FC<attachment> = (props) => {
|
|
26
|
+
const { handleGetRequest, handleDeleteRequest } = useAxios();
|
|
27
|
+
|
|
28
|
+
const handleDelete = async () => {
|
|
29
|
+
await handleDeleteRequest({
|
|
30
|
+
endPointURI: "api/v1/attachment/archive",
|
|
31
|
+
parameters: {
|
|
32
|
+
attachmentCode: props.attachmentCode,
|
|
33
|
+
refKey: props.refKey,
|
|
34
|
+
attachmentId: props.id,
|
|
35
|
+
},
|
|
36
|
+
successCallBkFn: (response) => {
|
|
37
|
+
props.setAttachmentConfig(response.data);
|
|
38
|
+
},
|
|
39
|
+
showMask: true,
|
|
40
|
+
});
|
|
41
|
+
};
|
|
42
|
+
const { ConfirmationWindow, setOpen } = useConfirmationWindow({
|
|
43
|
+
title: "Confirmation",
|
|
44
|
+
body: "Are you sure you want to delete this attachment?",
|
|
45
|
+
onConfirmationCallBk: () => {
|
|
46
|
+
handleDelete();
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
const handleDownload = async () => {
|
|
51
|
+
await handleGetRequest({
|
|
52
|
+
endPointURI: "api/v1/attachment/download",
|
|
53
|
+
parameters: {
|
|
54
|
+
attachmentId: props.id,
|
|
55
|
+
},
|
|
56
|
+
showMask: true,
|
|
57
|
+
responseType: "blob",
|
|
58
|
+
successCallBkFn: (response) => {
|
|
59
|
+
const url = window.URL.createObjectURL(new Blob([response.data]));
|
|
60
|
+
const link = document.createElement("a");
|
|
61
|
+
link.href = url;
|
|
62
|
+
link.setAttribute("download", props.fileName);
|
|
63
|
+
document.body.appendChild(link);
|
|
64
|
+
link.click();
|
|
65
|
+
link.remove();
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
return (
|
|
71
|
+
<>
|
|
72
|
+
<ConfirmationWindow />
|
|
73
|
+
<Card sx={{ width: 300, border: "0.5px solid gray" }}>
|
|
74
|
+
<CardMedia
|
|
75
|
+
sx={{
|
|
76
|
+
height: 140,
|
|
77
|
+
width: 300,
|
|
78
|
+
display: "flex",
|
|
79
|
+
alignItems: "center",
|
|
80
|
+
justifyContent: "center",
|
|
81
|
+
}}
|
|
82
|
+
>
|
|
83
|
+
{props?.docType.toLocaleLowerCase().includes("image") ? (
|
|
84
|
+
<AttachmentImageViewer attachmentId={props.id} />
|
|
85
|
+
) : (
|
|
86
|
+
<FontAwesomeIcon icon="file" size="3x" />
|
|
87
|
+
)}
|
|
88
|
+
</CardMedia>
|
|
89
|
+
<CardContent>
|
|
90
|
+
<Typography gutterBottom variant="h6" component="div">
|
|
91
|
+
{props.fileName}
|
|
92
|
+
</Typography>
|
|
93
|
+
<Typography variant="body2" sx={{ color: "text.secondary" }}>
|
|
94
|
+
{`File Size: ${props?.attachmentSize || "unknown"} kb`}
|
|
95
|
+
</Typography>
|
|
96
|
+
<Typography variant="body2" sx={{ color: "text.secondary" }}>
|
|
97
|
+
{`File Type: ${props?.category || "NA"}`}
|
|
98
|
+
</Typography>
|
|
99
|
+
<Typography variant="body2" sx={{ color: "text.secondary" }}>
|
|
100
|
+
{props.remark}
|
|
101
|
+
</Typography>
|
|
102
|
+
</CardContent>
|
|
103
|
+
<CardActions>
|
|
104
|
+
<IconButton
|
|
105
|
+
size="small"
|
|
106
|
+
onClick={() => {
|
|
107
|
+
setOpen(true);
|
|
108
|
+
}}
|
|
109
|
+
>
|
|
110
|
+
<Tooltip title="Delete Attachment">
|
|
111
|
+
<FontAwesomeIcon icon="trash" />
|
|
112
|
+
</Tooltip>
|
|
113
|
+
</IconButton>
|
|
114
|
+
<div style={{ flex: 1 }}></div>
|
|
115
|
+
<IconButton size="small" onClick={handleDownload}>
|
|
116
|
+
<Tooltip title="Download Attachment">
|
|
117
|
+
<FontAwesomeIcon icon="download" />
|
|
118
|
+
</Tooltip>
|
|
119
|
+
</IconButton>
|
|
120
|
+
</CardActions>
|
|
121
|
+
</Card>
|
|
122
|
+
</>
|
|
123
|
+
);
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
export default AttachmentCard;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
2
|
+
import { useSelector } from "react-redux";
|
|
3
|
+
import { Avatar } from "@mui/material";
|
|
4
|
+
|
|
5
|
+
type AttachmentImageViewerProps = {
|
|
6
|
+
attachmentId?: number;
|
|
7
|
+
attachmentCode?: string;
|
|
8
|
+
refKey?: string;
|
|
9
|
+
category?: string;
|
|
10
|
+
showAsAvatar?: boolean;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const AttachmentImageViewer: React.FC<AttachmentImageViewerProps> = (props) => {
|
|
14
|
+
const apiBaseUrl = useSelector(
|
|
15
|
+
(state: any) => state.AppInfo.value.apiBaseUrl
|
|
16
|
+
);
|
|
17
|
+
let imagePath = apiBaseUrl + "/api/v1/attachment/";
|
|
18
|
+
if (props?.attachmentId) {
|
|
19
|
+
imagePath += "download?attachmentId=" + props.attachmentId;
|
|
20
|
+
} else {
|
|
21
|
+
imagePath += `downloadImage?attachmentCode=${props.attachmentCode}&refKey=${props.refKey}`;
|
|
22
|
+
if (props?.category) {
|
|
23
|
+
imagePath += `&category=${props.category}`;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
const [imgSrc, setImgSrc] = useState(imagePath);
|
|
27
|
+
return props?.showAsAvatar ? (
|
|
28
|
+
<Avatar src={imgSrc} />
|
|
29
|
+
) : (
|
|
30
|
+
<img
|
|
31
|
+
src={imgSrc}
|
|
32
|
+
alt="image"
|
|
33
|
+
onError={() => setImgSrc("/no_image.png")}
|
|
34
|
+
style={{
|
|
35
|
+
width: "100%",
|
|
36
|
+
height: "100%",
|
|
37
|
+
objectFit: "cover",
|
|
38
|
+
display: "block",
|
|
39
|
+
}}
|
|
40
|
+
/>
|
|
41
|
+
);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export default AttachmentImageViewer;
|