@asaleh37/ui-base 1.2.17 → 1.2.18
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 +105 -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,49 @@ const TemplateGrid: React.FC<TemplateGridProps> = (props) => {
|
|
|
558
581
|
}
|
|
559
582
|
}
|
|
560
583
|
}
|
|
584
|
+
if (props?.attachment) {
|
|
585
|
+
actions?.push(
|
|
586
|
+
<GridActionsCellItem
|
|
587
|
+
icon={
|
|
588
|
+
<Tooltip title={"Attachments"}>
|
|
589
|
+
<FontAwesomeIcon icon={"paperclip"} />
|
|
590
|
+
</Tooltip>
|
|
591
|
+
}
|
|
592
|
+
label={"Attachments"}
|
|
593
|
+
className="textPrimary"
|
|
594
|
+
color="inherit"
|
|
595
|
+
onClick={() => {
|
|
596
|
+
setSelectedRecord(record);
|
|
597
|
+
if (props?.attachment?.enableAttachFn) {
|
|
598
|
+
setAttachmentPanelEnabledForRecord(
|
|
599
|
+
props.attachment.enableAttachFn(record)
|
|
600
|
+
);
|
|
601
|
+
} else {
|
|
602
|
+
setAttachmentPanelEnabledForRecord(true);
|
|
603
|
+
}
|
|
604
|
+
setAttachmentWindowState(true);
|
|
605
|
+
}}
|
|
606
|
+
/>
|
|
607
|
+
);
|
|
608
|
+
}
|
|
609
|
+
if (props?.workFlowDocumentCode) {
|
|
610
|
+
actions?.push(
|
|
611
|
+
<GridActionsCellItem
|
|
612
|
+
icon={
|
|
613
|
+
<Tooltip title={"Approvals"}>
|
|
614
|
+
<FontAwesomeIcon icon={"stamp"} />
|
|
615
|
+
</Tooltip>
|
|
616
|
+
}
|
|
617
|
+
label={"Approvals"}
|
|
618
|
+
className="textPrimary"
|
|
619
|
+
color="inherit"
|
|
620
|
+
onClick={() => {
|
|
621
|
+
setSelectedRecord(record);
|
|
622
|
+
setWorkFlowWindowState(true);
|
|
623
|
+
}}
|
|
624
|
+
/>
|
|
625
|
+
);
|
|
626
|
+
}
|
|
561
627
|
if (props?.rowActions) {
|
|
562
628
|
for (const rowAction of props.rowActions) {
|
|
563
629
|
if (
|
|
@@ -590,7 +656,9 @@ const TemplateGrid: React.FC<TemplateGridProps> = (props) => {
|
|
|
590
656
|
width:
|
|
591
657
|
(props?.rowActions ? props.rowActions.length * 30 : 0) +
|
|
592
658
|
(props?.editAction && props?.editAction?.isEnabled ? 30 : 0) +
|
|
593
|
-
(props?.deleteAction && props?.deleteAction?.isEnabled ? 30 : 0)
|
|
659
|
+
(props?.deleteAction && props?.deleteAction?.isEnabled ? 30 : 0) +
|
|
660
|
+
(props?.attachment ? 30 : 0) +
|
|
661
|
+
(props?.workFlowDocumentCode ? 30 : 0),
|
|
594
662
|
getActions: getActionColumnActions,
|
|
595
663
|
};
|
|
596
664
|
|
|
@@ -614,6 +682,10 @@ const TemplateGrid: React.FC<TemplateGridProps> = (props) => {
|
|
|
614
682
|
adjustGridColumns();
|
|
615
683
|
}, []);
|
|
616
684
|
|
|
685
|
+
useEffect(() => {
|
|
686
|
+
props.apiActions.reloadData(props?.gridLoadParametersValues);
|
|
687
|
+
}, [session.UserInfo?.currentOrganization]);
|
|
688
|
+
|
|
617
689
|
useEffect(() => {
|
|
618
690
|
adjustGridColumns();
|
|
619
691
|
}, [themeDirection, props.formElements]);
|
|
@@ -698,6 +770,8 @@ const TemplateGrid: React.FC<TemplateGridProps> = (props) => {
|
|
|
698
770
|
/>
|
|
699
771
|
) : (
|
|
700
772
|
<TemplateForm
|
|
773
|
+
keyColumnName={props.keyColumnName}
|
|
774
|
+
attachment={props.attachment}
|
|
701
775
|
formLoadCallBk={props.formLoadCallBk}
|
|
702
776
|
recordIdToEdit={
|
|
703
777
|
recordToEdit ? recordToEdit[keyColumnName] : undefined
|
|
@@ -818,7 +892,34 @@ const TemplateGrid: React.FC<TemplateGridProps> = (props) => {
|
|
|
818
892
|
) : (
|
|
819
893
|
<></>
|
|
820
894
|
)}
|
|
821
|
-
|
|
895
|
+
{props?.attachment ? (
|
|
896
|
+
<AttachmentWindow>
|
|
897
|
+
<AttachmentPanel
|
|
898
|
+
attachmentCode={props.attachment.attachmentCode}
|
|
899
|
+
refKey={selectedRecord[props?.keyColumnName || "id"]}
|
|
900
|
+
enableAttachment={attachmentPanelEnabledForRecord}
|
|
901
|
+
/>
|
|
902
|
+
</AttachmentWindow>
|
|
903
|
+
) : (
|
|
904
|
+
<></>
|
|
905
|
+
)}
|
|
906
|
+
{props?.workFlowDocumentCode ? (
|
|
907
|
+
<WorkFlowWindow>
|
|
908
|
+
<WorkflowDocumentPanel
|
|
909
|
+
workFlowDocumentCode={props.workFlowDocumentCode}
|
|
910
|
+
refDocumentId={selectedRecord[props?.keyColumnName || "id"]}
|
|
911
|
+
postActionCallBk={() => {
|
|
912
|
+
setWorkFlowWindowState(false);
|
|
913
|
+
props.apiActions.reloadData(props.gridLoadParametersValues);
|
|
914
|
+
}}
|
|
915
|
+
cancelActionCallBk={() => {
|
|
916
|
+
setWorkFlowWindowState(false);
|
|
917
|
+
}}
|
|
918
|
+
/>
|
|
919
|
+
</WorkFlowWindow>
|
|
920
|
+
) : (
|
|
921
|
+
<></>
|
|
922
|
+
)}
|
|
822
923
|
<DataGridPremium
|
|
823
924
|
{...props?.muiProps}
|
|
824
925
|
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;
|