@pega/react-sdk-overrides 24.2.11 → 25.1.11
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/lib/designSystemExtension/AlertBanner/AlertBanner.css +46 -0
- package/lib/designSystemExtension/AlertBanner/AlertBanner.tsx +37 -20
- package/lib/designSystemExtension/Banner/Banner.css +1 -1
- package/lib/designSystemExtension/Banner/Banner.tsx +10 -7
- package/lib/designSystemExtension/CaseSummaryFields/CaseSummaryFields.css +0 -1
- package/lib/designSystemExtension/CaseSummaryFields/CaseSummaryFields.tsx +53 -37
- package/lib/designSystemExtension/DetailsFields/DetailsFields.tsx +11 -13
- package/lib/designSystemExtension/FieldGroup/FieldGroup.tsx +8 -9
- package/lib/designSystemExtension/FieldGroupList/FieldGroupList.tsx +9 -9
- package/lib/designSystemExtension/FieldValueList/FieldValueList.tsx +7 -8
- package/lib/designSystemExtension/Operator/Operator.tsx +21 -19
- package/lib/designSystemExtension/Pulse/Pulse.tsx +1 -1
- package/lib/designSystemExtension/RichTextEditor/RichTextEditor.tsx +32 -4
- package/lib/designSystemExtension/WssQuickCreate/WssQuickCreate.css +7 -14
- package/lib/designSystemExtension/WssQuickCreate/WssQuickCreate.tsx +13 -2
- package/lib/field/AutoComplete/AutoComplete.tsx +1 -1
- package/lib/field/CancelAlert/CancelAlert.css +4 -4
- package/lib/field/CancelAlert/CancelAlert.tsx +6 -6
- package/lib/field/Checkbox/Checkbox.tsx +97 -4
- package/lib/field/Currency/Currency.tsx +3 -3
- package/lib/field/Currency/currency-utils.ts +1 -2
- package/lib/field/Date/Date.tsx +3 -7
- package/lib/field/DateTime/DateTime.tsx +3 -8
- package/lib/field/Decimal/Decimal.tsx +3 -5
- package/lib/field/Dropdown/Dropdown.tsx +5 -7
- package/lib/field/Email/Email.tsx +11 -13
- package/lib/field/Group/Group.tsx +10 -8
- package/lib/field/Integer/Integer.tsx +5 -7
- package/lib/field/Location/Location.css +4 -0
- package/lib/field/Location/Location.tsx +258 -0
- package/lib/field/Location/config-ext.json +8 -0
- package/lib/field/Location/index.tsx +1 -0
- package/lib/field/Multiselect/utils.ts +1 -1
- package/lib/field/ObjectReference/ObjectReference.tsx +235 -0
- package/lib/field/ObjectReference/index.tsx +1 -0
- package/lib/field/ObjectReference/utils.ts +111 -0
- package/lib/field/Percentage/Percentage.tsx +3 -7
- package/lib/field/Phone/Phone.tsx +7 -5
- package/lib/field/RadioButtons/RadioButtons.tsx +47 -2
- package/lib/field/RichText/RichText.css +79 -0
- package/lib/field/RichText/RichText.tsx +3 -1
- package/lib/field/ScalarList/ScalarList.tsx +2 -3
- package/lib/field/SelectableCard/SelectableCard.tsx +189 -0
- package/lib/field/SelectableCard/index.tsx +1 -0
- package/lib/field/SelectableCard/utils.tsx +223 -0
- package/lib/field/SemanticLink/SemanticLink.tsx +160 -28
- package/lib/field/SemanticLink/utils.ts +1 -1
- package/lib/field/TextArea/TextArea.tsx +5 -7
- package/lib/field/TextContent/TextContent.tsx +1 -2
- package/lib/field/TextInput/TextInput.tsx +5 -7
- package/lib/field/Time/Time.tsx +3 -7
- package/lib/field/URL/URL.tsx +5 -7
- package/lib/field/UserReference/UserReference.tsx +2 -3
- package/lib/helpers/attachmentShared.ts +6 -0
- package/lib/helpers/common-utils.ts +3 -4
- package/lib/helpers/data_page.ts +0 -1
- package/lib/helpers/field-group-utils.ts +1 -1
- package/lib/helpers/formatters/Currency.ts +9 -4
- package/lib/helpers/formatters/CurrencyMap.ts +0 -2
- package/lib/helpers/object-utils.ts +10 -0
- package/lib/helpers/simpleTableHelpers.ts +118 -6
- package/lib/helpers/utils.ts +8 -1
- package/lib/helpers/versionHelpers.ts +0 -1
- package/lib/infra/ActionButtons/ActionButtons.tsx +28 -21
- package/lib/infra/Assignment/Assignment.tsx +47 -31
- package/lib/infra/Assignment/useValidationBanner.ts +29 -0
- package/lib/infra/AssignmentCard/AssignmentCard.tsx +2 -2
- package/lib/infra/Containers/FlowContainer/FlowContainer.tsx +22 -102
- package/lib/infra/Containers/ModalViewContainer/ListViewActionButtons/ListViewActionButtons.tsx +1 -2
- package/lib/infra/Containers/ModalViewContainer/ModalViewContainer.tsx +12 -6
- package/lib/infra/Containers/ViewContainer/ViewContainer.tsx +8 -13
- package/lib/infra/Containers/container-helpers.ts +47 -1
- package/lib/infra/DashboardFilter/DashboardFilter.tsx +3 -6
- package/lib/infra/DashboardFilter/filterUtils.tsx +3 -4
- package/lib/infra/DeferLoad/DeferLoad.tsx +26 -13
- package/lib/infra/ErrorBoundary/ErrorBoundary.tsx +1 -3
- package/lib/infra/MultiStep/MultiStep.css +48 -70
- package/lib/infra/MultiStep/MultiStep.tsx +27 -53
- package/lib/infra/NavBar/NavBar.css +1 -1
- package/lib/infra/NavBar/NavBar.tsx +49 -34
- package/lib/infra/Reference/Reference.tsx +8 -4
- package/lib/infra/Region/Region.tsx +1 -1
- package/lib/infra/RootContainer/RootContainer.tsx +6 -8
- package/lib/infra/Stages/Stages.tsx +3 -4
- package/lib/infra/View/View.tsx +9 -9
- package/lib/template/AdvancedSearch/AdvancedSearch.tsx +86 -0
- package/lib/template/AdvancedSearch/SearchGroup/persistUtils.ts +52 -0
- package/lib/template/AdvancedSearch/SearchGroups/SearchGroups.tsx +244 -0
- package/lib/template/AdvancedSearch/SearchGroups/hooks.ts +37 -0
- package/lib/template/AdvancedSearch/SearchGroups/index.tsx +1 -0
- package/lib/template/AdvancedSearch/SearchGroups/utils.ts +29 -0
- package/lib/template/AdvancedSearch/TemplateContext.ts +11 -0
- package/lib/template/AdvancedSearch/config-ext.json +9 -0
- package/lib/template/AdvancedSearch/index.tsx +1 -0
- package/lib/template/AppShell/AppShell.css +1 -5
- package/lib/template/AppShell/AppShell.tsx +16 -17
- package/lib/template/BannerPage/BannerPage.tsx +2 -2
- package/lib/template/CaseSummary/CaseSummary.tsx +25 -43
- package/lib/template/CaseView/CaseView.tsx +28 -35
- package/lib/template/CaseViewActionsMenu/CaseViewActionsMenu.tsx +1 -1
- package/lib/template/Confirmation/Confirmation.tsx +2 -3
- package/lib/template/DataReference/DataReference.tsx +312 -106
- package/lib/template/DataReference/DataReferenceAdvancedSearchContext.ts +10 -0
- package/lib/template/DataReference/SearchForm.tsx +149 -0
- package/lib/template/DataReference/utils.ts +90 -0
- package/lib/template/DefaultForm/DefaultForm.tsx +3 -3
- package/lib/template/DefaultForm/utils/index.ts +1 -3
- package/lib/template/DefaultPage/DefaultPage.tsx +108 -0
- package/lib/template/DefaultPage/index.tsx +1 -0
- package/lib/template/Details/Details/Details.tsx +11 -11
- package/lib/template/Details/DetailsSubTabs/DetailsSubTabs.tsx +2 -2
- package/lib/template/Details/DetailsThreeColumn/DetailsThreeColumn.tsx +11 -11
- package/lib/template/Details/DetailsTwoColumn/DetailsTwoColumn.tsx +11 -11
- package/lib/template/Details/DynamicTabs/DynamicTabs.tsx +1 -1
- package/lib/template/FieldGroupTemplate/FieldGroupTemplate.tsx +12 -6
- package/lib/template/HierarchicalForm/HierarchicalForm.tsx +58 -0
- package/lib/template/HierarchicalForm/hooks.ts +224 -0
- package/lib/template/HierarchicalForm/index.tsx +1 -0
- package/lib/template/InlineDashboard/InlineDashboard.tsx +14 -16
- package/lib/template/InlineDashboardPage/InlineDashboardPage.tsx +2 -2
- package/lib/template/ListPage/ListPage.tsx +1 -1
- package/lib/template/ListView/ListView.tsx +342 -204
- package/lib/template/ListView/hooks.ts +1 -5
- package/lib/template/ListView/utils.ts +38 -5
- package/lib/template/MultiReferenceReadOnly/MultiReferenceReadOnly.tsx +17 -2
- package/lib/template/NarrowWide/NarrowWide/NarrowWide.tsx +5 -5
- package/lib/template/NarrowWide/NarrowWideDetails/NarrowWideDetails.tsx +11 -11
- package/lib/template/NarrowWide/NarrowWideForm/NarrowWideForm.tsx +2 -2
- package/lib/template/NarrowWide/NarrowWidePage/NarrowWidePage.tsx +2 -2
- package/lib/template/ObjectPage/index.tsx +1 -0
- package/lib/template/OneColumn/OneColumn/OneColumn.tsx +7 -7
- package/lib/template/OneColumn/OneColumnPage/OneColumnPage.tsx +1 -1
- package/lib/template/OneColumn/OneColumnTab/OneColumnTab.tsx +2 -2
- package/lib/template/PromotedFilters/PromotedFilters.tsx +1 -2
- package/lib/template/SelfServiceCaseView/SelfServiceCaseView.tsx +153 -0
- package/lib/template/SelfServiceCaseView/index.tsx +1 -0
- package/lib/template/SimpleTable/SimpleTable/SimpleTable.tsx +2 -3
- package/lib/template/SimpleTable/SimpleTableManual/SimpleTableManual.tsx +45 -34
- package/lib/template/SimpleTable/SimpleTableSelect/SimpleTableSelect.tsx +1 -1
- package/lib/template/SimpleTable/SimpleTableSelectReadonly/SimpleTableSelectReadonly.tsx +179 -0
- package/lib/template/SimpleTable/SimpleTableSelectReadonly/index.tsx +1 -0
- package/lib/template/SingleReferenceReadOnly/SingleReferenceReadOnly.tsx +10 -2
- package/lib/template/SubTabs/SubTabs.tsx +2 -2
- package/lib/template/SubTabs/tabUtils.ts +118 -1
- package/lib/template/TwoColumn/TwoColumn/TwoColumn.tsx +9 -10
- package/lib/template/TwoColumn/TwoColumnPage/TwoColumnPage.tsx +1 -1
- package/lib/template/TwoColumn/TwoColumnTab/TwoColumnTab.tsx +9 -10
- package/lib/template/WideNarrow/WideNarrow/WideNarrow.tsx +5 -5
- package/lib/template/WideNarrow/WideNarrowDetails/WideNarrowDetails.tsx +11 -11
- package/lib/template/WideNarrow/WideNarrowForm/WideNarrowForm.tsx +2 -2
- package/lib/template/WideNarrow/WideNarrowPage/WideNarrowPage.tsx +2 -2
- package/lib/template/WssNavBar/WssNavBar.css +1 -1
- package/lib/template/WssNavBar/WssNavBar.tsx +6 -6
- package/lib/template/utils.tsx +58 -0
- package/lib/widget/AppAnnouncement/AppAnnouncement.tsx +1 -1
- package/lib/widget/Attachment/Attachment.css +6 -8
- package/lib/widget/Attachment/Attachment.tsx +303 -225
- package/lib/widget/Attachment/Attachment.types.ts +96 -0
- package/lib/widget/Attachment/AttachmentUtils.ts +316 -0
- package/lib/widget/CaseHistory/CaseHistory.tsx +5 -5
- package/lib/widget/FileUtility/ActionButtonsForFileUtil/ActionButtonsForFileUtil.css +0 -14
- package/lib/widget/FileUtility/ActionButtonsForFileUtil/ActionButtonsForFileUtil.tsx +3 -3
- package/lib/widget/FileUtility/FileUtility/FileUtility.css +7 -6
- package/lib/widget/FileUtility/FileUtility/FileUtility.tsx +29 -22
- package/lib/widget/Followers/Followers.tsx +2 -4
- package/lib/widget/QuickCreate/QuickCreate.tsx +1 -2
- package/lib/widget/SummaryItem/SummaryItem.css +9 -11
- package/lib/widget/SummaryItem/SummaryItem.tsx +2 -2
- package/lib/widget/SummaryList/SummaryList.tsx +1 -1
- package/lib/widget/ToDo/ToDo.css +1 -13
- package/lib/widget/ToDo/ToDo.tsx +37 -36
- package/package.json +1 -1
- package/lib/helpers/attachmentHelpers.ts +0 -76
|
@@ -1,173 +1,192 @@
|
|
|
1
|
-
|
|
2
|
-
/* eslint-disable react/no-array-index-key */
|
|
3
|
-
/* eslint-disable no-nested-ternary */
|
|
4
|
-
import { useState, useEffect, useCallback } from 'react';
|
|
1
|
+
import { useState, useEffect, useCallback, useMemo, useRef } from 'react';
|
|
5
2
|
import { CircularProgress, IconButton, Menu, MenuItem, Button } from '@mui/material';
|
|
6
3
|
import MoreVertIcon from '@mui/icons-material/MoreVert';
|
|
7
|
-
import download from 'downloadjs';
|
|
8
4
|
|
|
9
|
-
import { buildFilePropsFromResponse, getIconFromFileType, validateMaxSize } from '@pega/react-sdk-components/lib/components/helpers/attachmentHelpers';
|
|
10
5
|
import { Utils } from '@pega/react-sdk-components/lib/components/helpers/utils';
|
|
11
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
clearFieldErrorMessages,
|
|
8
|
+
deleteAttachments,
|
|
9
|
+
getIconFromFileType,
|
|
10
|
+
getMappedValue,
|
|
11
|
+
insertAttachments,
|
|
12
|
+
useDeepMemo,
|
|
13
|
+
useFileDownload,
|
|
14
|
+
validateFileExtension
|
|
15
|
+
} from './AttachmentUtils';
|
|
16
|
+
import { validateMaxSize } from '@pega/react-sdk-components/lib/components/helpers/attachmentShared';
|
|
17
|
+
import type { PageInstructionOptions } from './Attachment.types';
|
|
18
|
+
import type { PConnFieldProps } from '@pega/react-sdk-components/lib/types/PConnProps';
|
|
12
19
|
|
|
13
20
|
import './Attachment.css';
|
|
14
21
|
|
|
15
22
|
interface AttachmentProps extends Omit<PConnFieldProps, 'value'> {
|
|
16
23
|
// If any, enter additional props that only exist on this component
|
|
17
24
|
value: any;
|
|
18
|
-
allowMultiple: string;
|
|
25
|
+
allowMultiple: boolean | string;
|
|
19
26
|
extensions: string;
|
|
27
|
+
editMode: string;
|
|
28
|
+
isTableFormatter: boolean;
|
|
20
29
|
}
|
|
21
30
|
|
|
22
|
-
const getAttachmentKey = (name = '') => (name ? `attachmentsList.${name}` : 'attachmentsList');
|
|
23
|
-
|
|
24
|
-
const getCurrentAttachmentsList = (key, context) => {
|
|
25
|
-
return PCore.getStoreValue(`.${key}`, 'context_data', context) || [];
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
const updateAttachmentState = (pConn, key, attachments) => {
|
|
29
|
-
PCore.getStateUtils().updateState(pConn.getContextName(), key, attachments, {
|
|
30
|
-
pageReference: 'context_data',
|
|
31
|
-
isArrayDeepMerge: false
|
|
32
|
-
});
|
|
33
|
-
};
|
|
34
|
-
|
|
35
31
|
export default function Attachment(props: AttachmentProps) {
|
|
36
|
-
const { value, getPConnect, label, validatemessage,
|
|
32
|
+
const { value, getPConnect, label, validatemessage, extensions, displayMode, helperText, editMode, isTableFormatter } = props;
|
|
37
33
|
/* this is a temporary fix because required is supposed to be passed as a boolean and NOT as a string */
|
|
38
|
-
let { required, disabled } = props;
|
|
39
|
-
[required, disabled] = [required, disabled].map(
|
|
34
|
+
let { required, disabled, allowMultiple } = props;
|
|
35
|
+
[required, disabled, allowMultiple] = [required, disabled, allowMultiple].map(
|
|
36
|
+
prop => prop === true || (typeof prop === 'string' && prop === 'true')
|
|
37
|
+
);
|
|
40
38
|
const pConn = getPConnect();
|
|
41
|
-
const
|
|
39
|
+
const localizationService = pConn.getLocalizationService();
|
|
40
|
+
|
|
41
|
+
const actionSequencer = useMemo(() => PCore.getActionsSequencer(), []);
|
|
42
|
+
const rawValue = pConn.getComponentConfig().value;
|
|
43
|
+
const isAttachmentAnnotationPresent = typeof rawValue === 'object' ? false : rawValue?.includes('@ATTACHMENT');
|
|
44
|
+
const { attachments, isOldAttachment } = isAttachmentAnnotationPresent ? value : PCore.getAttachmentUtils().prepareAttachmentData(value);
|
|
45
|
+
|
|
46
|
+
let valueRef = (pConn.getStateProps() as any).value;
|
|
47
|
+
valueRef = valueRef.indexOf('.') === 0 ? valueRef.substring(1) : valueRef;
|
|
48
|
+
|
|
49
|
+
pConn.setReferenceList(`.${valueRef}`);
|
|
50
|
+
|
|
51
|
+
const isMultiAttachmentInInlineEditTable = isTableFormatter && allowMultiple && editMode === 'tableRows';
|
|
52
|
+
|
|
53
|
+
const [files, setFiles] = useState<any[]>(attachments);
|
|
54
|
+
const overrideLocalState = useRef(false);
|
|
55
|
+
const attachmentCount = useRef(attachments.length);
|
|
56
|
+
const filesWithError = useRef<any[]>([]);
|
|
57
|
+
const multiAttachmentsInInlineEdit = useRef([]);
|
|
58
|
+
const thumbnailURLs = useRef<any[]>([]);
|
|
59
|
+
const contextName = pConn.getContextName();
|
|
60
|
+
const onFileDownload = useFileDownload(contextName);
|
|
61
|
+
|
|
42
62
|
const localizedVal = PCore.getLocaleUtils().getLocaleValue;
|
|
43
63
|
const localeCategory = 'CosmosFields';
|
|
44
64
|
const uploadMultipleFilesLabel = localizedVal('file_upload_text_multiple', localeCategory);
|
|
45
65
|
const uploadSingleFileLabel = localizedVal('file_upload_text_one', localeCategory);
|
|
46
|
-
let categoryName = '';
|
|
47
|
-
if (value && value.pyCategoryName) {
|
|
48
|
-
categoryName = value.pyCategoryName;
|
|
49
|
-
}
|
|
50
66
|
const deleteIcon = Utils.getImageSrc('trash', Utils.getSDKStaticConentUrl());
|
|
51
67
|
const srcImg = Utils.getImageSrc('document-doc', Utils.getSDKStaticConentUrl());
|
|
52
|
-
|
|
53
|
-
valueRef = valueRef.indexOf('.') === 0 ? valueRef.substring(1) : valueRef;
|
|
68
|
+
|
|
54
69
|
const [anchorEl, setAnchorEl] = useState(null);
|
|
55
70
|
const open = Boolean(anchorEl);
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
);
|
|
59
|
-
const [filesWithError, setFilesWithError] = useState<any[]>([]);
|
|
71
|
+
|
|
72
|
+
const fileInputRef = useRef<HTMLInputElement>(null);
|
|
60
73
|
const [toggleUploadBegin, setToggleUploadBegin] = useState(false);
|
|
61
74
|
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
isArrayDeepMerge: false
|
|
66
|
-
});
|
|
67
|
-
};
|
|
75
|
+
const deleteFile = useCallback(
|
|
76
|
+
(file, fileIndex) => {
|
|
77
|
+
setAnchorEl(null);
|
|
68
78
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
79
|
+
// reset the file input so that it will allow re-uploading the same file after deletion
|
|
80
|
+
if (fileInputRef.current) {
|
|
81
|
+
fileInputRef.current.value = ''; // Reset the input
|
|
82
|
+
}
|
|
73
83
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
const extension = fileObj.pyAttachName.split('.').pop();
|
|
81
|
-
fileDownload(content.data, fileObj.pyFileName, extension);
|
|
82
|
-
})
|
|
83
|
-
.catch(() => {});
|
|
84
|
-
};
|
|
84
|
+
if (filesWithError.current.length > 0) {
|
|
85
|
+
filesWithError.current = filesWithError.current.filter(fileWithError => fileWithError.props.id !== file.props.id);
|
|
86
|
+
if (filesWithError.current.length === 0) {
|
|
87
|
+
clearFieldErrorMessages(pConn);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
85
90
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
// If file to be deleted is the one added in previous stage i.e. for which a file instance is created in server
|
|
93
|
-
// no need to filter currentAttachmentList as we will get another entry of file in redux with delete & label
|
|
94
|
-
// eslint-disable-next-line no-unsafe-optional-chaining
|
|
95
|
-
if (value && value?.pxResults && +value?.pyCount > 0 && file.responseProps && file?.responseProps?.pzInsKey !== 'temp') {
|
|
96
|
-
const updatedAttachments = files.map(f => {
|
|
97
|
-
if (f.responseProps && f.responseProps.pzInsKey === file.responseProps.pzInsKey) {
|
|
98
|
-
return { ...f, delete: true, label: valueRef };
|
|
99
|
-
}
|
|
100
|
-
return f;
|
|
91
|
+
if (file.inProgress) {
|
|
92
|
+
// @ts-ignore - Expected 1 arguments, but got 2.ts(2554)
|
|
93
|
+
PCore.getAttachmentUtils().cancelRequest(file.props.id, contextName);
|
|
94
|
+
actionSequencer.deRegisterBlockingAction(contextName).catch(() => {});
|
|
95
|
+
setFiles(localFiles => {
|
|
96
|
+
return localFiles.filter(localFile => localFile.props.id !== file.props.id);
|
|
101
97
|
});
|
|
98
|
+
} else {
|
|
99
|
+
deleteAttachments([file], pConn, multiAttachmentsInInlineEdit.current, {
|
|
100
|
+
allowMultiple,
|
|
101
|
+
isOldAttachment,
|
|
102
|
+
isMultiAttachmentInInlineEditTable,
|
|
103
|
+
attachmentCount: attachmentCount.current,
|
|
104
|
+
deleteIndex: fileIndex
|
|
105
|
+
} as any);
|
|
106
|
+
// Filter out without deleted file and reset the file indexes
|
|
107
|
+
setFiles(localFiles => {
|
|
108
|
+
let tempLocalFiles = [...localFiles];
|
|
109
|
+
tempLocalFiles = tempLocalFiles.filter(localFile => localFile.props.id !== file.props.id);
|
|
110
|
+
tempLocalFiles.forEach(localFile => {
|
|
111
|
+
if (!localFile.props.error && !file.props.error) {
|
|
112
|
+
const updatedDeleteIndex =
|
|
113
|
+
localFile.responseProps.deleteIndex > fileIndex ? localFile.responseProps.deleteIndex - 1 : localFile.responseProps.deleteIndex;
|
|
102
114
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
);
|
|
110
|
-
attachmentsList = [...filesPostDelete, ...newlyAddedFiles];
|
|
111
|
-
return attachmentsList;
|
|
112
|
-
});
|
|
113
|
-
} // if the file being deleted is the added in this stage i.e. whose data is not yet created in server
|
|
114
|
-
else {
|
|
115
|
-
// filter newly added files in this stage, later the updated current stage files will be added to redux once files state is updated in below setFiles()
|
|
116
|
-
currentAttachmentList = currentAttachmentList.filter(f => f.label !== valueRef);
|
|
117
|
-
setFiles(current => {
|
|
118
|
-
attachmentsList = current.filter(f => f.ID !== file.ID);
|
|
119
|
-
return attachmentsList;
|
|
115
|
+
localFile.props.onDelete = () => deleteFile(localFile, updatedDeleteIndex);
|
|
116
|
+
|
|
117
|
+
localFile.responseProps.deleteIndex = updatedDeleteIndex;
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
return tempLocalFiles;
|
|
120
121
|
});
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
// @ts-ignore - 3rd parameter "responseEncoding" should be optional
|
|
124
|
-
PCore.getAttachmentUtils().cancelRequest(file.ID, pConn.getContextName());
|
|
122
|
+
if (!file.props.error) {
|
|
123
|
+
attachmentCount.current -= 1;
|
|
125
124
|
}
|
|
126
125
|
}
|
|
127
126
|
|
|
128
127
|
setToggleUploadBegin(false);
|
|
129
|
-
setFilesWithError(prevFilesWithError => {
|
|
130
|
-
return prevFilesWithError.filter(f => f.ID !== file.ID);
|
|
131
|
-
});
|
|
132
128
|
},
|
|
133
|
-
[pConn
|
|
129
|
+
[pConn]
|
|
134
130
|
);
|
|
135
131
|
|
|
136
|
-
const onUploadProgress = () => {
|
|
132
|
+
const onUploadProgress = (id, ev) => {
|
|
133
|
+
const progress = Math.floor((ev.loaded / ev.total) * 100);
|
|
134
|
+
setFiles(localFiles => [
|
|
135
|
+
...localFiles.map(localFile => {
|
|
136
|
+
if (localFile.props?.id === id) {
|
|
137
|
+
localFile.inProgress = true;
|
|
138
|
+
localFile.props.progress = progress;
|
|
139
|
+
}
|
|
140
|
+
return localFile;
|
|
141
|
+
})
|
|
142
|
+
]);
|
|
143
|
+
};
|
|
137
144
|
|
|
138
|
-
const
|
|
145
|
+
const populateErrorAndUpdateRedux = file => {
|
|
146
|
+
const fieldName = (pConn.getStateProps() as any).value;
|
|
147
|
+
// set errors to property to block submit even on errors in file upload
|
|
148
|
+
PCore.getMessageManager().addMessages({
|
|
149
|
+
messages: [
|
|
150
|
+
{
|
|
151
|
+
type: 'error',
|
|
152
|
+
message: localizationService.getLocalizedText('Error with one or more files')
|
|
153
|
+
}
|
|
154
|
+
],
|
|
155
|
+
property: fieldName,
|
|
156
|
+
pageReference: pConn.getPageReference(),
|
|
157
|
+
context: contextName
|
|
158
|
+
});
|
|
159
|
+
insertAttachments([file], pConn, multiAttachmentsInInlineEdit.current, {
|
|
160
|
+
allowMultiple,
|
|
161
|
+
isOldAttachment,
|
|
162
|
+
isMultiAttachmentInInlineEditTable,
|
|
163
|
+
attachmentCount: attachmentCount.current
|
|
164
|
+
} as any);
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
const errorHandler = (isFetchCanceled, file) => {
|
|
139
168
|
return error => {
|
|
140
169
|
if (!isFetchCanceled(error)) {
|
|
141
|
-
let uploadFailMsg =
|
|
170
|
+
let uploadFailMsg = localizationService.getLocalizedText('Something went wrong');
|
|
142
171
|
if (error.response && error.response.data && error.response.data.errorDetails) {
|
|
143
|
-
uploadFailMsg =
|
|
172
|
+
uploadFailMsg = localizationService.getLocalizedText(error.response.data.errorDetails[0].localizedValue);
|
|
144
173
|
}
|
|
174
|
+
|
|
145
175
|
setFiles(current => {
|
|
146
|
-
return current.map(
|
|
147
|
-
if (
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
messages: [
|
|
159
|
-
{
|
|
160
|
-
type: 'error',
|
|
161
|
-
message: pConn.getLocalizedValue('Error with one or more files', '', '')
|
|
162
|
-
}
|
|
163
|
-
],
|
|
164
|
-
property: fieldName,
|
|
165
|
-
pageReference: pConn.getPageReference(),
|
|
166
|
-
context
|
|
167
|
-
});
|
|
168
|
-
delete f.props.progress;
|
|
176
|
+
return current.map((localFile, index) => {
|
|
177
|
+
if (localFile.props.id === file.props.id) {
|
|
178
|
+
localFile.props.meta = uploadFailMsg;
|
|
179
|
+
localFile.props.error = true;
|
|
180
|
+
localFile.props.onDelete = () => deleteFile(localFile, index);
|
|
181
|
+
localFile.props.icon = getIconFromFileType(localFile.type);
|
|
182
|
+
localFile.props.name = localizationService.getLocalizedText('Unable to upload file');
|
|
183
|
+
localFile.inProgress = false;
|
|
184
|
+
delete localFile.props.progress;
|
|
185
|
+
filesWithError.current.push(localFile);
|
|
186
|
+
|
|
187
|
+
populateErrorAndUpdateRedux(localFile);
|
|
169
188
|
}
|
|
170
|
-
return
|
|
189
|
+
return localFile;
|
|
171
190
|
});
|
|
172
191
|
});
|
|
173
192
|
}
|
|
@@ -175,78 +194,62 @@ export default function Attachment(props: AttachmentProps) {
|
|
|
175
194
|
};
|
|
176
195
|
};
|
|
177
196
|
|
|
178
|
-
const validateFileExtension = (fileObj, allowedExtensions) => {
|
|
179
|
-
if (!allowedExtensions) {
|
|
180
|
-
return true;
|
|
181
|
-
}
|
|
182
|
-
const allowedExtensionList = allowedExtensions
|
|
183
|
-
.toLowerCase()
|
|
184
|
-
.split(',')
|
|
185
|
-
.map(item => item.replaceAll('.', '').trim());
|
|
186
|
-
const extension = fileObj.name.split('.').pop().toLowerCase();
|
|
187
|
-
return allowedExtensionList.includes(extension);
|
|
188
|
-
};
|
|
189
|
-
|
|
190
|
-
const clearFieldErrorMessages = () => {
|
|
191
|
-
const fieldName = (pConn.getStateProps() as any).value;
|
|
192
|
-
const context = pConn.getContextName();
|
|
193
|
-
PCore.getMessageManager().clearMessages({
|
|
194
|
-
type: PCore.getConstants().MESSAGES.MESSAGES_TYPE_ERROR,
|
|
195
|
-
property: fieldName,
|
|
196
|
-
pageReference: pConn.getPageReference(),
|
|
197
|
-
context
|
|
198
|
-
});
|
|
199
|
-
};
|
|
200
|
-
|
|
201
197
|
const onFileAdded = event => {
|
|
202
198
|
let addedFiles = Array.from(event.target.files);
|
|
203
|
-
addedFiles = allowMultiple
|
|
199
|
+
addedFiles = allowMultiple ? addedFiles : [addedFiles[0]];
|
|
204
200
|
const maxAttachmentSize = PCore.getEnvironmentInfo().getMaxAttachmentSize() || '5';
|
|
205
201
|
const tempFilesToBeUploaded = [
|
|
206
202
|
...addedFiles.map((f: any, index) => {
|
|
207
203
|
f.ID = `${new Date().getTime()}I${index}`;
|
|
208
|
-
f.inProgress = true;
|
|
209
204
|
f.props = {
|
|
210
205
|
type: f.type,
|
|
211
206
|
name: f.name,
|
|
207
|
+
id: f.ID,
|
|
208
|
+
format: f.name.split('.').pop(),
|
|
212
209
|
icon: getIconFromFileType(f.type),
|
|
213
|
-
onDelete: () => deleteFile(f)
|
|
210
|
+
onDelete: () => deleteFile(f, index),
|
|
211
|
+
thumbnail: window.URL.createObjectURL(f)
|
|
214
212
|
};
|
|
215
213
|
if (!validateMaxSize(f, maxAttachmentSize)) {
|
|
216
214
|
f.props.error = true;
|
|
217
|
-
f.
|
|
218
|
-
f.props.meta = pConn.getLocalizedValue(`File is too big. Max allowed size is ${maxAttachmentSize}MB.`, '', '');
|
|
215
|
+
f.props.meta = localizationService.getLocalizedText(`File is too big. Max allowed size is ${maxAttachmentSize}MB.`);
|
|
219
216
|
} else if (!validateFileExtension(f, extensions)) {
|
|
220
217
|
f.props.error = true;
|
|
221
|
-
f.
|
|
222
|
-
f.props.meta = `${pConn.getLocalizedValue('File has invalid extension. Allowed extensions are:', '', '')} ${extensions.replaceAll(
|
|
218
|
+
f.props.meta = `${localizationService.getLocalizedText('File has invalid extension. Allowed extensions are:')} ${extensions.replaceAll(
|
|
223
219
|
'.',
|
|
224
220
|
''
|
|
225
221
|
)}`;
|
|
226
222
|
}
|
|
227
223
|
if (f.props.error) {
|
|
228
224
|
const fieldName = (pConn.getStateProps() as any).value;
|
|
229
|
-
const context = pConn.getContextName();
|
|
230
225
|
PCore.getMessageManager().addMessages({
|
|
231
226
|
messages: [
|
|
232
227
|
{
|
|
233
228
|
type: 'error',
|
|
234
|
-
message:
|
|
229
|
+
message: localizationService.getLocalizedText('Error with one or more files')
|
|
235
230
|
}
|
|
236
231
|
],
|
|
237
232
|
property: fieldName,
|
|
238
233
|
pageReference: pConn.getPageReference(),
|
|
239
|
-
context
|
|
234
|
+
context: contextName
|
|
240
235
|
});
|
|
241
236
|
}
|
|
242
237
|
return f;
|
|
243
238
|
})
|
|
244
239
|
];
|
|
240
|
+
|
|
245
241
|
const tempFilesWithError = tempFilesToBeUploaded.filter(f => f.props.error);
|
|
246
242
|
if (tempFilesWithError.length > 0) {
|
|
247
|
-
|
|
243
|
+
filesWithError.current = [...filesWithError.current, ...tempFilesWithError];
|
|
244
|
+
|
|
245
|
+
insertAttachments(tempFilesWithError, pConn, multiAttachmentsInInlineEdit.current, {
|
|
246
|
+
allowMultiple,
|
|
247
|
+
isOldAttachment,
|
|
248
|
+
isMultiAttachmentInInlineEditTable,
|
|
249
|
+
attachmentCount: attachmentCount.current
|
|
250
|
+
} as PageInstructionOptions);
|
|
248
251
|
}
|
|
249
|
-
setFiles(current => (allowMultiple
|
|
252
|
+
setFiles(current => (!allowMultiple ? [...tempFilesToBeUploaded] : [...current, ...tempFilesToBeUploaded]));
|
|
250
253
|
setToggleUploadBegin(true);
|
|
251
254
|
};
|
|
252
255
|
|
|
@@ -255,106 +258,178 @@ export default function Attachment(props: AttachmentProps) {
|
|
|
255
258
|
.filter(e => {
|
|
256
259
|
const isFileUploaded = e.props && e.props.progress === 100;
|
|
257
260
|
const fileHasError = e.props && e.props.error;
|
|
258
|
-
const
|
|
259
|
-
|
|
261
|
+
const isFileUploadedInLastStep = e.responseProps && e.responseProps.ID !== 'temp';
|
|
262
|
+
const isFileUploadInProgress = e.inProgress;
|
|
263
|
+
return !isFileUploadInProgress && !isFileUploaded && !fileHasError && !isFileUploadedInLastStep;
|
|
260
264
|
})
|
|
261
|
-
.map(
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
onUploadProgress();
|
|
265
|
+
.map(file =>
|
|
266
|
+
PCore.getAttachmentUtils().uploadAttachment(
|
|
267
|
+
file,
|
|
268
|
+
ev => {
|
|
269
|
+
onUploadProgress(file.props.id, ev);
|
|
266
270
|
},
|
|
267
271
|
isFetchCanceled => {
|
|
268
|
-
return errorHandler(isFetchCanceled,
|
|
272
|
+
return errorHandler(isFetchCanceled, file);
|
|
269
273
|
},
|
|
270
|
-
|
|
274
|
+
contextName
|
|
271
275
|
)
|
|
272
276
|
);
|
|
277
|
+
|
|
278
|
+
// allow new files to be added when other files upload is still in progress
|
|
279
|
+
setToggleUploadBegin(false);
|
|
273
280
|
Promise.allSettled(filesToBeUploaded)
|
|
274
281
|
.then((fileResponses: any) => {
|
|
275
282
|
fileResponses = fileResponses.filter(fr => fr.status !== 'rejected'); // in case of deleting an in progress file, promise gets cancelled but still enters then block
|
|
276
283
|
if (fileResponses.length > 0) {
|
|
277
|
-
setFiles(
|
|
278
|
-
const tempFilesUploaded = [...
|
|
279
|
-
tempFilesUploaded.forEach(
|
|
280
|
-
|
|
284
|
+
setFiles(localFiles => {
|
|
285
|
+
const tempFilesUploaded = [...localFiles];
|
|
286
|
+
tempFilesUploaded.forEach(localFile => {
|
|
287
|
+
// if attach field has multiple files & in bw any error files are present
|
|
288
|
+
// Example : files = [properFile1, errFile, errFile, properFile2]
|
|
289
|
+
// indexes for delete & preview should be for files [properFile1, properFile2] which is [1,2]
|
|
290
|
+
const index = fileResponses.findIndex(fileResponse => fileResponse.value.clientFileID === localFile.props.id);
|
|
281
291
|
if (index >= 0) {
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
292
|
+
fileResponses[index].value.thumbnail = localFile.props.thumbnail;
|
|
293
|
+
localFile.inProgress = false;
|
|
294
|
+
localFile.ID = fileResponses[index].value.ID;
|
|
295
|
+
localFile.props.meta = localizationService.getLocalizedText('Uploaded successfully');
|
|
296
|
+
localFile.props.progress = 100;
|
|
297
|
+
localFile.handle = fileResponses[index].value.ID;
|
|
298
|
+
localFile.label = valueRef;
|
|
299
|
+
localFile.responseProps = {
|
|
300
|
+
pzInsKey: 'temp'
|
|
291
301
|
};
|
|
292
302
|
}
|
|
293
303
|
});
|
|
294
304
|
return tempFilesUploaded;
|
|
295
305
|
});
|
|
296
306
|
|
|
297
|
-
|
|
298
|
-
|
|
307
|
+
insertAttachments(fileResponses, pConn, multiAttachmentsInInlineEdit.current, {
|
|
308
|
+
allowMultiple,
|
|
309
|
+
isOldAttachment,
|
|
310
|
+
isMultiAttachmentInInlineEditTable,
|
|
311
|
+
attachmentCount: attachmentCount.current,
|
|
312
|
+
insert: true
|
|
313
|
+
} as any);
|
|
314
|
+
attachmentCount.current += fileResponses.length;
|
|
315
|
+
|
|
316
|
+
if (filesWithError.current.length === 0) {
|
|
317
|
+
clearFieldErrorMessages(pConn);
|
|
299
318
|
}
|
|
300
319
|
}
|
|
301
|
-
|
|
320
|
+
actionSequencer.deRegisterBlockingAction(contextName).catch(() => {});
|
|
302
321
|
})
|
|
303
322
|
.catch(error => {
|
|
304
|
-
// eslint-disable-next-line no-console
|
|
305
323
|
console.log(error);
|
|
306
324
|
setToggleUploadBegin(false);
|
|
307
325
|
});
|
|
308
|
-
}, [files
|
|
326
|
+
}, [files]);
|
|
309
327
|
|
|
310
328
|
useEffect(() => {
|
|
311
329
|
if (toggleUploadBegin && files.length > 0) {
|
|
312
|
-
|
|
330
|
+
actionSequencer.registerBlockingAction(contextName).then(() => {
|
|
331
|
+
uploadFiles();
|
|
332
|
+
});
|
|
313
333
|
}
|
|
314
334
|
}, [toggleUploadBegin]);
|
|
315
335
|
|
|
316
336
|
useEffect(() => {
|
|
317
|
-
if (
|
|
318
|
-
|
|
319
|
-
// block duplicate files to redux store when added 1 after another to prevent multiple duplicates being added to the case on submit
|
|
320
|
-
const tempFiles = files.filter(f => currentAttachmentList.findIndex(fr => fr.ID === f.ID) === -1 && !f.inProgress && f.responseProps);
|
|
321
|
-
|
|
322
|
-
const updatedAttList = [...currentAttachmentList, ...tempFiles];
|
|
323
|
-
updateAttachmentState(pConn, getAttachmentKey(valueRef), updatedAttList);
|
|
337
|
+
if (filesWithError.current.length === 0) {
|
|
338
|
+
clearFieldErrorMessages(pConn);
|
|
324
339
|
}
|
|
325
|
-
}, [
|
|
340
|
+
}, [filesWithError]);
|
|
341
|
+
|
|
342
|
+
const memoizedAttachments = useDeepMemo(() => {
|
|
343
|
+
return attachments;
|
|
344
|
+
}, [attachments]);
|
|
345
|
+
|
|
346
|
+
// Prepares new structure as per Cosmos component
|
|
347
|
+
const transformAttachments = () => {
|
|
348
|
+
const transformedFiles = [...attachments];
|
|
349
|
+
let deleteIndex = -1;
|
|
350
|
+
transformedFiles.forEach(attachment => {
|
|
351
|
+
attachment.props.id = attachment.responseProps.ID;
|
|
352
|
+
attachment.props.format = attachment.props.name.split('.').pop();
|
|
353
|
+
if (attachment.props.error) {
|
|
354
|
+
attachment.responseProps.deleteIndex = deleteIndex;
|
|
355
|
+
} else {
|
|
356
|
+
deleteIndex += 1;
|
|
357
|
+
attachment.responseProps.deleteIndex = deleteIndex;
|
|
358
|
+
}
|
|
359
|
+
if (attachment.props.thumbnail) {
|
|
360
|
+
thumbnailURLs.current.push(attachment.props.thumbnail);
|
|
361
|
+
}
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
return transformedFiles;
|
|
365
|
+
};
|
|
326
366
|
|
|
327
367
|
useEffect(() => {
|
|
328
|
-
|
|
329
|
-
|
|
368
|
+
const caseID = PCore.getStoreValue(`.${getMappedValue('pyID')}`, PCore.getResolvedConstantValue('caseInfo.content'), contextName);
|
|
369
|
+
if (displayMode !== 'DISPLAY_ONLY') {
|
|
370
|
+
PCore.getPubSubUtils().subscribe(
|
|
371
|
+
PCore.getConstants().PUB_SUB_EVENTS.CASE_EVENTS.ASSIGNMENT_SUBMISSION,
|
|
372
|
+
() => {
|
|
373
|
+
overrideLocalState.current = true;
|
|
374
|
+
},
|
|
375
|
+
caseID
|
|
376
|
+
);
|
|
330
377
|
}
|
|
331
|
-
}, [filesWithError]);
|
|
332
378
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
...current.map(f => {
|
|
339
|
-
return f.responseProps.pzInsKey && !f.responseProps.pzInsKey.includes('temp')
|
|
340
|
-
? {
|
|
341
|
-
...f,
|
|
342
|
-
props: {
|
|
343
|
-
...f.props,
|
|
344
|
-
onDelete: () => deleteFile(f)
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
: { ...f };
|
|
348
|
-
}),
|
|
349
|
-
...tempUploadedFiles
|
|
350
|
-
];
|
|
351
|
-
});
|
|
352
|
-
PCore.getPubSubUtils().subscribe(PCore.getConstants().PUB_SUB_EVENTS.CASE_EVENTS.ASSIGNMENT_SUBMISSION, resetAttachmentStoredState, caseID);
|
|
379
|
+
// When component mounts, only set local files state from redux.
|
|
380
|
+
const serverFiles = transformAttachments();
|
|
381
|
+
setFiles(serverFiles);
|
|
382
|
+
filesWithError.current = serverFiles.filter(file => file.props.error);
|
|
383
|
+
|
|
353
384
|
return () => {
|
|
354
|
-
|
|
385
|
+
if (displayMode !== 'DISPLAY_ONLY') {
|
|
386
|
+
PCore.getPubSubUtils().unsubscribe(PCore.getConstants().PUB_SUB_EVENTS.CASE_EVENTS.ASSIGNMENT_SUBMISSION, caseID);
|
|
387
|
+
}
|
|
355
388
|
};
|
|
356
389
|
}, []);
|
|
357
390
|
|
|
391
|
+
useEffect(() => {
|
|
392
|
+
if (overrideLocalState.current) {
|
|
393
|
+
const serverFiles = transformAttachments();
|
|
394
|
+
overrideLocalState.current = false;
|
|
395
|
+
attachmentCount.current = attachments.length;
|
|
396
|
+
filesWithError.current = [];
|
|
397
|
+
setFiles(serverFiles);
|
|
398
|
+
} else {
|
|
399
|
+
// Determine whether refresh call has overridden any error files in redux, push error files back to redux from local state to perform client side validation during assignment submit
|
|
400
|
+
const errorFiles = attachments.filter(attachment => attachment.props.error);
|
|
401
|
+
if (errorFiles.length === 0 && filesWithError.current.length > 0) {
|
|
402
|
+
// Check if local file state contains error files and push those to redux
|
|
403
|
+
const uniqueKey = getMappedValue('pzInsKey');
|
|
404
|
+
const transformedErrorFiles = filesWithError.current.map(errorFile => {
|
|
405
|
+
const filename = errorFile.props.name;
|
|
406
|
+
return {
|
|
407
|
+
[uniqueKey]: errorFile.props.id,
|
|
408
|
+
FileName: filename,
|
|
409
|
+
Category: '',
|
|
410
|
+
FileExtension: filename.split('.').pop() ?? filename,
|
|
411
|
+
error: errorFile.props.error || null
|
|
412
|
+
};
|
|
413
|
+
});
|
|
414
|
+
let key = '';
|
|
415
|
+
let updatedAttachments: any = [];
|
|
416
|
+
if (allowMultiple || isOldAttachment) {
|
|
417
|
+
key = isOldAttachment ? `${valueRef}.pxResults` : valueRef;
|
|
418
|
+
const existingAttachments = PCore.getStoreValue(`.${key}`, pConn.getPageReference(), pConn.getContextName()) || [];
|
|
419
|
+
updatedAttachments = [...existingAttachments, ...transformedErrorFiles];
|
|
420
|
+
} else {
|
|
421
|
+
key = valueRef;
|
|
422
|
+
updatedAttachments = transformedErrorFiles[0];
|
|
423
|
+
}
|
|
424
|
+
PCore.getStateUtils().updateState(pConn.getContextName(), key, updatedAttachments, {
|
|
425
|
+
pageReference: pConn.getPageReference(),
|
|
426
|
+
isArrayDeepMerge: false,
|
|
427
|
+
removePropertyFromChangedList: true
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
}, [memoizedAttachments]);
|
|
432
|
+
|
|
358
433
|
const handleClick = event => {
|
|
359
434
|
setAnchorEl(event.currentTarget);
|
|
360
435
|
};
|
|
@@ -375,13 +450,13 @@ export default function Attachment(props: AttachmentProps) {
|
|
|
375
450
|
id={valueRef}
|
|
376
451
|
name='upload-photo'
|
|
377
452
|
type='file'
|
|
378
|
-
multiple={allowMultiple
|
|
453
|
+
multiple={allowMultiple}
|
|
379
454
|
required={required}
|
|
380
455
|
disabled={disabled}
|
|
381
456
|
onChange={onFileAdded}
|
|
382
457
|
/>
|
|
383
458
|
<Button style={{ textTransform: 'none' }} variant='outlined' color='primary' component='span'>
|
|
384
|
-
{allowMultiple
|
|
459
|
+
{allowMultiple
|
|
385
460
|
? uploadMultipleFilesLabel === 'file_upload_text_multiple'
|
|
386
461
|
? 'Choose files'
|
|
387
462
|
: uploadMultipleFilesLabel
|
|
@@ -415,7 +490,7 @@ export default function Attachment(props: AttachmentProps) {
|
|
|
415
490
|
</div>
|
|
416
491
|
<div className='psdk-utility-action'>
|
|
417
492
|
{item.ID && (
|
|
418
|
-
<button type='button' className='psdk-utility-button' aria-label='Delete Attachment' onClick={() => deleteFile(item)}>
|
|
493
|
+
<button type='button' className='psdk-utility-button' aria-label='Delete Attachment' onClick={() => deleteFile(item, index)}>
|
|
419
494
|
<img className='psdk-utility-card-action-svg-icon' src={deleteIcon} />
|
|
420
495
|
</button>
|
|
421
496
|
)}
|
|
@@ -435,11 +510,14 @@ export default function Attachment(props: AttachmentProps) {
|
|
|
435
510
|
<MenuItem
|
|
436
511
|
style={{ fontSize: '14px' }}
|
|
437
512
|
key='download'
|
|
438
|
-
onClick={() =>
|
|
513
|
+
onClick={() => {
|
|
514
|
+
setAnchorEl(null);
|
|
515
|
+
onFileDownload(item.responseProps ? item.responseProps : {});
|
|
516
|
+
}}
|
|
439
517
|
>
|
|
440
518
|
Download
|
|
441
519
|
</MenuItem>
|
|
442
|
-
<MenuItem style={{ fontSize: '14px' }} key='delete' onClick={() => deleteFile(item)}>
|
|
520
|
+
<MenuItem style={{ fontSize: '14px' }} key='delete' onClick={() => deleteFile(item, index)}>
|
|
443
521
|
Delete
|
|
444
522
|
</MenuItem>
|
|
445
523
|
</Menu>
|
|
@@ -455,7 +533,7 @@ export default function Attachment(props: AttachmentProps) {
|
|
|
455
533
|
return (
|
|
456
534
|
<div className='file-upload-container'>
|
|
457
535
|
<span className={`label ${required ? 'file-label' : ''}`}>{label}</span>
|
|
458
|
-
{((files.length === 0 && allowMultiple
|
|
536
|
+
{((files.length === 0 && !allowMultiple) || allowMultiple) && <section>{content}</section>}
|
|
459
537
|
{validatemessage !== '' ? <span className='file-error'>{validatemessage}</span> : <span style={{ fontSize: '14px' }}>{helperText}</span>}
|
|
460
538
|
{files && files.length > 0 && <section>{fileDisplay}</section>}
|
|
461
539
|
</div>
|