@pega/react-sdk-overrides 0.25.4 → 0.25.6

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 (39) hide show
  1. package/lib/designSystemExtension/Banner/Banner.tsx +5 -2
  2. package/lib/designSystemExtension/CaseSummaryFields/CaseSummaryFields.tsx +1 -1
  3. package/lib/designSystemExtension/RichTextEditor/RichTextEditor.tsx +5 -2
  4. package/lib/designSystemExtension/WssQuickCreate/WssQuickCreate.css +6 -13
  5. package/lib/designSystemExtension/WssQuickCreate/WssQuickCreate.tsx +12 -1
  6. package/lib/field/Group/Group.tsx +3 -1
  7. package/lib/field/Location/Location.css +4 -0
  8. package/lib/field/Location/Location.tsx +2 -0
  9. package/lib/field/RadioButtons/RadioButtons.tsx +1 -1
  10. package/lib/field/RichText/RichText.css +79 -0
  11. package/lib/field/RichText/RichText.tsx +2 -0
  12. package/lib/field/SelectableCard/SelectableCard.tsx +3 -3
  13. package/lib/field/SelectableCard/utils.tsx +0 -4
  14. package/lib/field/SemanticLink/SemanticLink.tsx +1 -1
  15. package/lib/field/UserReference/UserReference.tsx +1 -1
  16. package/lib/helpers/attachmentShared.ts +6 -0
  17. package/lib/helpers/formatters/Currency.ts +9 -4
  18. package/lib/helpers/object-utils.ts +10 -0
  19. package/lib/infra/Assignment/Assignment.tsx +31 -24
  20. package/lib/infra/Containers/ModalViewContainer/ModalViewContainer.tsx +2 -1
  21. package/lib/infra/MultiStep/MultiStep.css +44 -66
  22. package/lib/infra/MultiStep/MultiStep.tsx +25 -51
  23. package/lib/infra/View/View.tsx +2 -1
  24. package/lib/template/AppShell/AppShell.tsx +10 -7
  25. package/lib/template/CaseSummary/CaseSummary.tsx +26 -38
  26. package/lib/template/CaseView/CaseView.tsx +20 -15
  27. package/lib/template/DefaultPage/DefaultPage.tsx +21 -1
  28. package/lib/template/ListView/ListView.tsx +152 -157
  29. package/lib/template/SelfServiceCaseView/SelfServiceCaseView.tsx +143 -1
  30. package/lib/template/SingleReferenceReadOnly/SingleReferenceReadOnly.tsx +9 -1
  31. package/lib/template/WssNavBar/WssNavBar.tsx +3 -3
  32. package/lib/template/utils.tsx +58 -0
  33. package/lib/widget/Attachment/Attachment.tsx +284 -210
  34. package/lib/widget/Attachment/Attachment.types.ts +96 -0
  35. package/lib/widget/Attachment/AttachmentUtils.ts +316 -0
  36. package/lib/widget/FileUtility/FileUtility/FileUtility.tsx +25 -16
  37. package/lib/widget/ToDo/ToDo.tsx +2 -6
  38. package/package.json +1 -1
  39. package/lib/helpers/attachmentHelpers.ts +0 -97
@@ -0,0 +1,96 @@
1
+ import type { ReactElement, Ref } from 'react';
2
+
3
+ export interface ResponseProps {
4
+ ID: string;
5
+ extension: string;
6
+ createDateTime?: Date | string | number;
7
+ createUser?: string;
8
+ name: string;
9
+ }
10
+
11
+ export interface AttachmentActions {
12
+ rel: string;
13
+ href: string;
14
+ title: string;
15
+ type: string;
16
+ }
17
+
18
+ export interface AttachmentLinks {
19
+ delete: AttachmentActions;
20
+ download: AttachmentActions;
21
+ edit: AttachmentActions;
22
+ }
23
+ export interface FileObject extends File {
24
+ icon?: string;
25
+ ID: string;
26
+ fileName: string;
27
+ category: string;
28
+ responseType: string;
29
+ fileType: string;
30
+ mimeType: string;
31
+ extension: string;
32
+ thumbnail?: string;
33
+ nameWithExt: string;
34
+ inProgress?: boolean;
35
+ progress?: number;
36
+ handle: string;
37
+ label: string;
38
+ delete?: boolean;
39
+ error?: boolean;
40
+ description: string;
41
+
42
+ props: {
43
+ icon?: string;
44
+
45
+ ref?: Ref<HTMLDivElement>;
46
+ id: string;
47
+ error?: string;
48
+ format?: string;
49
+ name: string;
50
+ thumbnail?: string;
51
+ onPreview?: () => void;
52
+ onDelete?: () => void;
53
+ onOpen?: () => void;
54
+ onEdit?: () => void;
55
+ onCancel?: () => void;
56
+ };
57
+ responseProps: ResponseProps;
58
+ value?: {
59
+ filename: string;
60
+ ID: string;
61
+ thumbnail: string;
62
+ };
63
+ categoryName: string;
64
+ createTime: string;
65
+ createdBy: string;
66
+ createdByName: string;
67
+ links: AttachmentLinks;
68
+ name: string;
69
+ meta?: ReactElement;
70
+ }
71
+
72
+ export interface ReduxAttachments {
73
+ ID?: string;
74
+ pzInsKey?: string;
75
+ FileName: string;
76
+ Category: string;
77
+ MimeType?: string;
78
+ FileExtension: string;
79
+ error: string | null;
80
+ localAttachment: boolean;
81
+ thumbnail?: string;
82
+ fileIndex?: number;
83
+ instruction?: string;
84
+ }
85
+
86
+ export interface PageInstructionOptions {
87
+ allowMultiple: boolean;
88
+ isMultiAttachmentInInlineEditTable: boolean;
89
+ attachmentCount: number;
90
+ insertPageInstruction: boolean;
91
+ deletePageInstruction: boolean;
92
+ deleteIndex: number;
93
+ insertRedux: boolean;
94
+ isOldAttachment: boolean;
95
+ deleteRedux: boolean;
96
+ }
@@ -0,0 +1,316 @@
1
+ import { useCallback, useRef } from 'react';
2
+ import download from 'downloadjs';
3
+ import equal from 'fast-deep-equal';
4
+
5
+ import type { FileObject, PageInstructionOptions, ReduxAttachments } from './Attachment.types';
6
+
7
+ export const isContentBinary = (headers: Record<string, string>) => {
8
+ return headers && headers['content-transfer-encoding'] === 'binary';
9
+ };
10
+
11
+ export const isContentBase64 = (headers: Record<string, string>) => {
12
+ return headers && headers['content-transfer-encoding'] === 'base64';
13
+ };
14
+
15
+ export const validateFileExtension = (fileObj: Record<string, string>, allowedExtensions: string) => {
16
+ if (!allowedExtensions) {
17
+ return true;
18
+ }
19
+ const allowedExtensionList = allowedExtensions
20
+ .toLowerCase()
21
+ .split(',')
22
+ .map(item => item.replaceAll('.', '').trim());
23
+ const extension = fileObj.name.split('.').pop()?.toLowerCase() || '';
24
+ return allowedExtensionList.includes(extension);
25
+ };
26
+
27
+ export const fileDownload = (data: string | Blob, fileName: string, ext: string | null, headers: Record<string, string>) => {
28
+ const name = ext ? `${fileName}.${ext}` : fileName;
29
+ // Temp fix: downloading EMAIl type attachment as html file
30
+ if (ext === 'html') {
31
+ download(isContentBase64(headers) ? atob(data as string) : data, name, 'text/html');
32
+ } else if (isContentBinary(headers)) {
33
+ download(data, name);
34
+ } else {
35
+ download(atob(data as string), name);
36
+ }
37
+ };
38
+
39
+ export const getIconFromFileType = (fileType: string) => {
40
+ let icon = 'document-doc';
41
+ if (!fileType) return icon;
42
+ if (fileType.startsWith('audio')) {
43
+ icon = 'audio';
44
+ } else if (fileType.startsWith('video')) {
45
+ icon = 'video';
46
+ } else if (fileType.startsWith('image')) {
47
+ icon = 'picture';
48
+ } else if (fileType.includes('pdf')) {
49
+ icon = 'document-pdf';
50
+ } else {
51
+ const [, subtype] = fileType.split('/');
52
+ const foundMatch = (sources: string[]) => {
53
+ return sources.some(key => subtype.includes(key));
54
+ };
55
+
56
+ if (foundMatch(['excel', 'spreadsheet'])) {
57
+ icon = 'document-xls';
58
+ } else if (foundMatch(['zip', 'compressed', 'gzip', 'rar', 'tar'])) {
59
+ icon = 'document-compress';
60
+ }
61
+ }
62
+
63
+ return icon;
64
+ };
65
+
66
+ export const fileDownloadVar = (content: { data: string; headers: Record<string, string> }, type: string, name: string, extension: string) => {
67
+ if (type === 'FILE' || type === undefined) {
68
+ fileDownload(content.data, name, extension, content.headers);
69
+ } else if (type === 'URL') {
70
+ let { data } = content;
71
+ if (!/^(http|https):\/\//.test(data)) {
72
+ data = `//${data}`;
73
+ }
74
+ window.open(content.data, '_blank');
75
+ } else if (type === 'EMAIL') {
76
+ // Temp Fix: for EMAIL type attachment
77
+ fileDownload(content.data, name, 'html', content.headers);
78
+ }
79
+ };
80
+
81
+ export const getMappedValue = (value: string): string => {
82
+ return PCore.getEnvironmentInfo().getKeyMapping(value) ?? value;
83
+ };
84
+
85
+ const generateInstructions = (
86
+ files: FileObject[],
87
+ pConn: typeof PConnect,
88
+ attachmentsInModal: ReduxAttachments[] | Pick<ReduxAttachments, 'instruction' | 'fileIndex'>[],
89
+ options: {
90
+ allowMultiple: boolean;
91
+ isMultiAttachmentInInlineEditTable: boolean;
92
+ attachmentCount: number;
93
+ insertPageInstruction: boolean;
94
+ deletePageInstruction: boolean;
95
+ deleteIndex: number;
96
+ }
97
+ ) => {
98
+ const { allowMultiple, isMultiAttachmentInInlineEditTable, attachmentCount, insertPageInstruction, deletePageInstruction, deleteIndex } = options;
99
+ const transformedAttachments: ReduxAttachments[] = [];
100
+ let valueRef = pConn.getStateProps().value;
101
+ valueRef = valueRef?.indexOf('.') === 0 ? valueRef.substring(1) : valueRef;
102
+ const uniqueKey = getMappedValue('pzInsKey');
103
+ files.forEach((file, index) => {
104
+ const filename = file.value?.filename || file.props?.name || '';
105
+ const payload = {
106
+ [uniqueKey]: file.value?.ID || file.props?.id,
107
+ FileName: filename,
108
+ Category: '',
109
+ // MimeType: getMimeTypeFromFile(filename),
110
+ FileExtension: filename.split('.').pop() ?? filename,
111
+ error: file.props?.error || null,
112
+ localAttachment: true,
113
+ thumbnail: file.value?.thumbnail
114
+ };
115
+ transformedAttachments.push(payload);
116
+ if (payload.error) {
117
+ return; // Don't process page instructions for error files, skip current iteration
118
+ }
119
+ if (allowMultiple) {
120
+ if (isMultiAttachmentInInlineEditTable) {
121
+ if (insertPageInstruction) {
122
+ attachmentsInModal.push({ ...payload, instruction: 'insert' } as any);
123
+ } else if (deletePageInstruction) {
124
+ (attachmentsInModal as Pick<ReduxAttachments, 'instruction' | 'fileIndex'>[]).push({
125
+ instruction: 'delete',
126
+ fileIndex: deleteIndex
127
+ });
128
+ }
129
+ } else if (insertPageInstruction) {
130
+ pConn.getListActions().insert({ ID: payload[uniqueKey] }, attachmentCount + index, undefined, {
131
+ skipStateUpdate: true
132
+ });
133
+ } else if (deletePageInstruction) {
134
+ pConn.getListActions().deleteEntry(deleteIndex, undefined, { skipStateUpdate: true });
135
+ }
136
+ } else if (insertPageInstruction) {
137
+ pConn.getListActions().replacePage(`.${valueRef}`, { ID: payload[uniqueKey] }, { skipStateUpdate: true });
138
+ } else if (deletePageInstruction) {
139
+ pConn.getListActions().deletePage(`.${valueRef}`, { skipStateUpdate: true });
140
+ }
141
+ });
142
+ return transformedAttachments;
143
+ };
144
+
145
+ export const updateReduxState = (
146
+ transformedAttachments: ReduxAttachments[],
147
+ pConn: typeof PConnect,
148
+ valueRef: string,
149
+ options: PageInstructionOptions
150
+ ) => {
151
+ const { allowMultiple, isOldAttachment, insertRedux, deleteRedux } = options;
152
+ let deleteIndex = -1;
153
+
154
+ if (allowMultiple || isOldAttachment) {
155
+ transformedAttachments.forEach(attachment => {
156
+ const key = isOldAttachment ? `${valueRef}.pxResults` : valueRef;
157
+ const existingAttachments: ReduxAttachments[] = PCore.getStoreValue(`.${key}`, pConn.getPageReference(), pConn.getContextName()) || [];
158
+
159
+ if (insertRedux) {
160
+ const actionPayLoad = {
161
+ type: 'LIST_ACTION',
162
+ payload: {
163
+ instruction: 'INSERT',
164
+ context: pConn.getContextName(),
165
+ referenceList: `${pConn.getPageReference()}.${key}`,
166
+ listIndex: existingAttachments.length,
167
+ content: attachment
168
+ }
169
+ };
170
+ PCore.getStore()?.dispatch(actionPayLoad);
171
+ } else if (deleteRedux) {
172
+ const uniqueKey = getMappedValue('pzInsKey');
173
+ deleteIndex = existingAttachments.findIndex(
174
+ existingAttachment =>
175
+ existingAttachment[uniqueKey as keyof ReduxAttachments] === transformedAttachments[0][uniqueKey as keyof ReduxAttachments]
176
+ );
177
+ const actionPayLoad = {
178
+ type: 'LIST_ACTION',
179
+ payload: {
180
+ instruction: 'DELETE',
181
+ context: pConn.getContextName(),
182
+ referenceList: `${pConn.getPageReference()}.${key}`,
183
+ listIndex: deleteIndex
184
+ }
185
+ };
186
+ PCore.getStore()?.dispatch(actionPayLoad);
187
+ }
188
+ });
189
+ } else if (insertRedux) {
190
+ const actionPayLoad = {
191
+ type: 'LIST_ACTION',
192
+ payload: {
193
+ instruction: 'REPLACE',
194
+ context: pConn.getContextName(),
195
+ referenceList: `${pConn.getPageReference()}.${valueRef}`,
196
+ content: transformedAttachments[0]
197
+ }
198
+ };
199
+ PCore.getStore()?.dispatch(actionPayLoad);
200
+ } else if (deleteRedux) {
201
+ const actionPayLoad = {
202
+ type: 'LIST_ACTION',
203
+ payload: {
204
+ instruction: 'DELETEPAGE',
205
+ context: pConn.getContextName(),
206
+ referenceList: `${pConn.getPageReference()}.${valueRef}`
207
+ }
208
+ };
209
+ PCore.getStore()?.dispatch(actionPayLoad);
210
+ }
211
+ };
212
+
213
+ export const insertAttachments = (
214
+ files: FileObject[],
215
+ pConn: typeof PConnect,
216
+ attachmentsInModal: ReduxAttachments[],
217
+ options: PageInstructionOptions
218
+ ) => {
219
+ const { isMultiAttachmentInInlineEditTable } = options;
220
+ let valueRef = pConn.getStateProps().value;
221
+ valueRef = valueRef?.indexOf('.') === 0 ? valueRef.substring(1) : valueRef;
222
+ const transformedAttachments = generateInstructions(files, pConn, attachmentsInModal, {
223
+ ...options,
224
+ insertPageInstruction: true
225
+ });
226
+
227
+ if (isMultiAttachmentInInlineEditTable) {
228
+ return; // For attachments within modal, redux update is not necessary yet, as modal isn't submitted at this stage
229
+ }
230
+ updateReduxState(transformedAttachments, pConn, valueRef, { ...options, insertRedux: true });
231
+ };
232
+
233
+ export const deleteAttachments = (
234
+ files: FileObject[],
235
+ pConn: typeof PConnect,
236
+ attachmentsInModal: Pick<ReduxAttachments, 'instruction' | 'fileIndex'>[],
237
+ options: PageInstructionOptions
238
+ ) => {
239
+ const { isMultiAttachmentInInlineEditTable } = options;
240
+ let valueRef = pConn.getStateProps().value;
241
+ valueRef = valueRef?.indexOf('.') === 0 ? valueRef.substring(1) : valueRef;
242
+ const transformedAttachments = generateInstructions(files, pConn, attachmentsInModal, {
243
+ ...options,
244
+ deletePageInstruction: true
245
+ });
246
+
247
+ if (isMultiAttachmentInInlineEditTable) {
248
+ return; // For attachments within modal, redux update is not necessary yet, as modal isn't submitted at this stage
249
+ }
250
+ updateReduxState(transformedAttachments, pConn, valueRef, { ...options, deleteRedux: true });
251
+ };
252
+
253
+ export const clearFieldErrorMessages = (pConn: typeof PConnect) => {
254
+ const fieldName = pConn.getStateProps().value;
255
+ PCore.getMessageManager().clearMessages({
256
+ type: PCore.getConstants().MESSAGES.MESSAGES_TYPE_ERROR,
257
+ property: fieldName,
258
+ pageReference: pConn.getPageReference(),
259
+ context: pConn.getContextName()
260
+ });
261
+ };
262
+
263
+ export const useFileDownload = (context: string) => {
264
+ return useCallback(
265
+ ({
266
+ ID,
267
+ name,
268
+ extension,
269
+ type,
270
+ category,
271
+ responseType
272
+ }: {
273
+ ID: string;
274
+ name: string;
275
+ extension: string;
276
+ type: string;
277
+ category: string;
278
+ responseType: string;
279
+ }) => {
280
+ if (category !== 'pxDocument') {
281
+ (
282
+ PCore.getAttachmentUtils().downloadAttachment(ID, context, responseType) as Promise<{
283
+ data: string;
284
+ headers: Record<string, string>;
285
+ }>
286
+ )
287
+ .then(content => {
288
+ fileDownloadVar(content, type, name, extension);
289
+ })
290
+
291
+ .catch(console.error);
292
+ } else {
293
+ (
294
+ PCore.getAttachmentUtils().downloadDocument(ID, context) as Promise<{
295
+ data: string;
296
+ headers: Record<string, string>;
297
+ }>
298
+ )
299
+ .then(content => {
300
+ fileDownloadVar(content, type, name, extension);
301
+ })
302
+
303
+ .catch(console.error);
304
+ }
305
+ },
306
+ [context]
307
+ );
308
+ };
309
+
310
+ export const useDeepMemo = (memoFn, key) => {
311
+ const ref: any = useRef();
312
+ if (!ref.current || !equal(key, ref.current.key)) {
313
+ ref.current = { key, value: memoFn() };
314
+ }
315
+ return ref.current.value;
316
+ };
@@ -7,15 +7,17 @@ import download from 'downloadjs';
7
7
  // import SummaryList from '../../SummaryList';
8
8
  // import ActionButtonsForFileUtil from '../ActionButtonsForFileUtil';
9
9
  import './FileUtility.css';
10
- import { IconButton, Menu, MenuItem, Button, CircularProgress, Card } from '@mui/material';
10
+ import { IconButton, Menu, MenuItem, Button, CircularProgress, Card, debounce } from '@mui/material';
11
11
  import MoreVertIcon from '@mui/icons-material/MoreVert';
12
12
 
13
- import { validateMaxSize } from '@pega/react-sdk-components/lib/components/helpers/attachmentHelpers';
13
+ import { validateMaxSize } from '@pega/react-sdk-components/lib/components/helpers/attachmentShared';
14
+ import { getResolvedConstantValue } from '@pega/react-sdk-components/lib/components/helpers/object-utils';
14
15
  import { getComponentFromMap } from '@pega/react-sdk-components/lib/bridge/helpers/sdk_component_map';
15
16
  import type { PConnProps } from '@pega/react-sdk-components/lib/types/PConnProps';
16
17
 
17
18
  interface FileUtilityProps extends PConnProps {
18
19
  // If any, enter additional props that only exist on this component
20
+ caseId?: string;
19
21
  }
20
22
 
21
23
  export default function FileUtility(props: FileUtilityProps) {
@@ -23,8 +25,9 @@ export default function FileUtility(props: FileUtilityProps) {
23
25
  const SummaryList = getComponentFromMap('SummaryList');
24
26
  const ActionButtonsForFileUtil = getComponentFromMap('ActionButtonsForFileUtil');
25
27
 
26
- const { getPConnect } = props;
28
+ const { getPConnect, caseId } = props;
27
29
  const thePConn = getPConnect();
30
+ const caseID = caseId ?? getResolvedConstantValue(thePConn, PCore.getConstants().CASE_INFO.CASE_INFO_ID);
28
31
  const required = true;
29
32
  const listTemp = {
30
33
  data: [],
@@ -210,7 +213,6 @@ export default function FileUtility(props: FileUtilityProps) {
210
213
 
211
214
  const getAttachments = () => {
212
215
  const attachmentUtils = PCore.getAttachmentUtils();
213
- const caseID = thePConn.getValue(PCore.getConstants().CASE_INFO.CASE_INFO_ID, ''); // 2nd arg empty string until typedef marked correctly
214
216
 
215
217
  if (caseID && caseID !== '') {
216
218
  const attPromise = attachmentUtils.getCaseAttachments(caseID, thePConn.getContextName());
@@ -245,25 +247,32 @@ export default function FileUtility(props: FileUtilityProps) {
245
247
  }
246
248
  };
247
249
 
250
+ const debouncedGetAttachments = debounce(getAttachments, 1000);
251
+
248
252
  useEffect(() => {
249
- getAttachments();
253
+ debouncedGetAttachments();
250
254
  }, []);
251
255
 
252
256
  useEffect(() => {
253
- PCore.getPubSubUtils().subscribe(
254
- (PCore.getEvents().getCaseEvent() as any).CASE_ATTACHMENTS_UPDATED_FROM_CASEVIEW,
255
- getAttachments,
256
- 'caseAttachmentsUpdateFromCaseview'
257
- );
258
-
259
- return () => {
260
- PCore.getPubSubUtils().unsubscribe(
261
- (PCore.getEvents().getCaseEvent() as any).CASE_ATTACHMENTS_UPDATED_FROM_CASEVIEW,
262
- 'caseAttachmentsUpdateFromCaseview'
263
- );
257
+ const attachSubObject = {
258
+ matcher: 'ATTACHMENTS',
259
+ criteria: {
260
+ ID: caseID
261
+ }
262
+ };
263
+ const attachSubId = PCore.getMessagingServiceManager().subscribe(attachSubObject, debouncedGetAttachments, getPConnect().getContextName());
264
+
265
+ return function cleanup() {
266
+ PCore.getMessagingServiceManager().unsubscribe(attachSubId);
264
267
  };
265
268
  }, []);
266
269
 
270
+ useEffect(() => {
271
+ thePConn.registerAdditionalProps({
272
+ lastRefreshTime: `@P ${PCore.getConstants().SUMMARY_OF_ATTACHMENTS_LAST_REFRESH_TIME}`
273
+ });
274
+ }, [thePConn]);
275
+
267
276
  function setNewFiles(arFiles) {
268
277
  let index = 0;
269
278
  for (const file of arFiles) {
@@ -82,19 +82,15 @@ function getID(assignment: any) {
82
82
 
83
83
  const useStyles = makeStyles(theme => ({
84
84
  root: {
85
- marginTop: theme.spacing(1),
86
85
  marginBottom: theme.spacing(1),
87
86
  paddingBottom: theme.spacing(1),
88
- borderLeft: '6px solid',
89
- borderLeftColor: theme.palette.primary.light
87
+ borderRadius: 16
90
88
  },
91
89
  avatar: {
92
90
  backgroundColor: theme.palette.primary.light,
93
91
  color: theme.palette.getContrastText(theme.palette.primary.light)
94
92
  },
95
93
  todoWrapper: {
96
- borderLeft: '6px solid',
97
- borderLeftColor: theme.palette.primary.light,
98
94
  padding: theme.spacing(1),
99
95
  margin: theme.spacing(1)
100
96
  },
@@ -307,7 +303,7 @@ export default function ToDo(props: ToDoProps) {
307
303
  </Avatar>
308
304
  <div style={{ display: 'block' }}>
309
305
  <Typography variant='h6'>{assignment?.name}</Typography>
310
- {`${localizedVal('Task in', localeCategory)} ${renderTaskId(type, getPConnect, showTodoList, assignment)} \u2022 ${localizedVal(
306
+ {`${localizedVal('Task in', localeCategory)} ${getID(assignment)} \u2022 ${localizedVal(
311
307
  'Urgency',
312
308
  localeCategory
313
309
  )} ${getPriority(assignment)}`}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pega/react-sdk-overrides",
3
- "version": "0.25.4",
3
+ "version": "0.25.6",
4
4
  "description": "React SDK - Code for overriding components",
5
5
  "_filesComment": "During packing, npm ignores everything NOT in the files list",
6
6
  "files": [
@@ -1,97 +0,0 @@
1
- import { useCallback } from 'react';
2
- import download from 'downloadjs';
3
-
4
- export const isContentBinary = headers => {
5
- return headers && headers['content-transfer-encoding'] === 'binary';
6
- };
7
-
8
- export const isContentBase64 = headers => {
9
- return headers && headers['content-transfer-encoding'] === 'base64';
10
- };
11
-
12
- export const fileDownload = (data, fileName, ext, headers) => {
13
- const name = ext ? `${fileName}.${ext}` : fileName;
14
- // Temp fix: downloading EMAIl type attachment as html file
15
- if (ext === 'html') {
16
- download(isContentBase64(headers) ? atob(data) : data, name, 'text/html');
17
- } else if (isContentBinary(headers)) {
18
- download(data, name);
19
- } else {
20
- download(atob(data), name);
21
- }
22
- };
23
-
24
- export const fileDownloadVar = (content, type, name, extension) => {
25
- if (type === 'FILE' || type === undefined) {
26
- fileDownload(content.data, name, extension, content.headers);
27
- } else if (type === 'URL') {
28
- let { data } = content;
29
- if (!/^(http|https):\/\//.test(data)) {
30
- data = `//${data}`;
31
- }
32
- window.open(content.data, '_blank');
33
- } else if (type === 'EMAIL') {
34
- // Temp Fix: for EMAIL type attachment
35
- fileDownload(content.data, name, 'html', content.headers);
36
- }
37
- };
38
-
39
- export const useFileDownload = context => {
40
- return useCallback(
41
- ({ ID, name, extension, type, category, responseType }) => {
42
- if (category !== 'pxDocument') {
43
- PCore.getAttachmentUtils()
44
- .downloadAttachment(ID, context, responseType)
45
- .then(content => {
46
- fileDownloadVar(content, type, name, extension);
47
- })
48
-
49
- .catch(console.error);
50
- } else {
51
- PCore.getAttachmentUtils()
52
- // @ts-expect-error
53
- .downloadDocument(ID, context, responseType)
54
- .then(content => {
55
- fileDownloadVar(content, type, name, extension);
56
- })
57
-
58
- .catch(console.error);
59
- }
60
- },
61
- [context]
62
- );
63
- };
64
-
65
- export const getIconFromFileType = (fileType): string => {
66
- let icon = 'document-doc';
67
- if (!fileType) return icon;
68
- if (fileType.startsWith('audio')) {
69
- icon = 'audio';
70
- } else if (fileType.startsWith('video')) {
71
- icon = 'video';
72
- } else if (fileType.startsWith('image')) {
73
- icon = 'picture';
74
- } else if (fileType.includes('pdf')) {
75
- icon = 'document-pdf';
76
- } else {
77
- const [, subtype] = fileType.split('/');
78
- const foundMatch = sources => {
79
- return sources.some(key => subtype.includes(key));
80
- };
81
-
82
- if (foundMatch(['excel', 'spreadsheet'])) {
83
- icon = 'document-xls';
84
- } else if (foundMatch(['zip', 'compressed', 'gzip', 'rar', 'tar'])) {
85
- icon = 'document-compress';
86
- }
87
- }
88
-
89
- return icon;
90
- };
91
-
92
- export const validateMaxSize = (fileObj: any, maxSizeInMB: string): boolean => {
93
- const fileSize = (fileObj.size / 1048576).toFixed(2);
94
- return parseFloat(fileSize) < parseFloat(maxSizeInMB);
95
- };
96
-
97
- export const isFileUploadedToServer = file => file.responseProps && !file.responseProps.ID?.includes('temp');