@imposium-hub/components 2.9.0-4 → 2.9.0-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 (77) hide show
  1. package/dist/cjs/components/app-wrapper/AppWrapper.js +3 -1
  2. package/dist/cjs/components/app-wrapper/AppWrapper.js.map +1 -1
  3. package/dist/cjs/components/assets/AssetsUploadMenu.js +2 -1
  4. package/dist/cjs/components/assets/AssetsUploadMenu.js.map +1 -1
  5. package/dist/cjs/components/confirm-modal/ConfirmModal.js +3 -2
  6. package/dist/cjs/components/confirm-modal/ConfirmModal.js.map +1 -1
  7. package/dist/cjs/components/number-field/NumberField.js +2 -2
  8. package/dist/cjs/components/number-field/NumberField.js.map +1 -1
  9. package/dist/cjs/components/replace-files-modal/ReplaceFilesModal.js +3 -2
  10. package/dist/cjs/components/replace-files-modal/ReplaceFilesModal.js.map +1 -1
  11. package/dist/cjs/constants/copy.d.ts +4 -0
  12. package/dist/cjs/constants/copy.js +5 -1
  13. package/dist/cjs/constants/copy.js.map +1 -1
  14. package/dist/cjs/constants/icons.d.ts +2 -0
  15. package/dist/cjs/constants/icons.js +3 -1
  16. package/dist/cjs/constants/icons.js.map +1 -1
  17. package/dist/cjs/index.d.ts +3 -3
  18. package/dist/cjs/index.js +6 -5
  19. package/dist/cjs/index.js.map +1 -1
  20. package/dist/cjs/redux/actions/asset-uploads.d.ts +1 -1
  21. package/dist/cjs/redux/actions/asset-uploads.js +169 -119
  22. package/dist/cjs/redux/actions/asset-uploads.js.map +1 -1
  23. package/dist/cjs/redux/actions/publish.js +10 -2
  24. package/dist/cjs/redux/actions/publish.js.map +1 -1
  25. package/dist/cjs/redux/reducers/asset-uploads.js +2 -1
  26. package/dist/cjs/redux/reducers/asset-uploads.js.map +1 -1
  27. package/dist/cjs/utils/modal.d.ts +4 -0
  28. package/dist/cjs/utils/modal.js +11 -2
  29. package/dist/cjs/utils/modal.js.map +1 -1
  30. package/dist/esm/components/app-wrapper/AppWrapper.js +3 -1
  31. package/dist/esm/components/app-wrapper/AppWrapper.js.map +1 -1
  32. package/dist/esm/components/assets/AssetsUploadMenu.js +3 -2
  33. package/dist/esm/components/assets/AssetsUploadMenu.js.map +1 -1
  34. package/dist/esm/components/confirm-modal/ConfirmModal.js +3 -2
  35. package/dist/esm/components/confirm-modal/ConfirmModal.js.map +1 -1
  36. package/dist/esm/components/number-field/NumberField.js +2 -2
  37. package/dist/esm/components/number-field/NumberField.js.map +1 -1
  38. package/dist/esm/components/replace-files-modal/ReplaceFilesModal.js +3 -2
  39. package/dist/esm/components/replace-files-modal/ReplaceFilesModal.js.map +1 -1
  40. package/dist/esm/constants/copy.d.ts +4 -0
  41. package/dist/esm/constants/copy.js +5 -1
  42. package/dist/esm/constants/copy.js.map +1 -1
  43. package/dist/esm/constants/icons.d.ts +2 -0
  44. package/dist/esm/constants/icons.js +3 -1
  45. package/dist/esm/constants/icons.js.map +1 -1
  46. package/dist/esm/index.d.ts +3 -3
  47. package/dist/esm/index.js +3 -3
  48. package/dist/esm/index.js.map +1 -1
  49. package/dist/esm/redux/actions/asset-uploads.d.ts +1 -1
  50. package/dist/esm/redux/actions/asset-uploads.js +165 -115
  51. package/dist/esm/redux/actions/asset-uploads.js.map +1 -1
  52. package/dist/esm/redux/actions/publish.js +10 -2
  53. package/dist/esm/redux/actions/publish.js.map +1 -1
  54. package/dist/esm/redux/reducers/asset-uploads.js +2 -1
  55. package/dist/esm/redux/reducers/asset-uploads.js.map +1 -1
  56. package/dist/esm/utils/modal.d.ts +4 -0
  57. package/dist/esm/utils/modal.js +9 -1
  58. package/dist/esm/utils/modal.js.map +1 -1
  59. package/dist/styles.css +49 -6
  60. package/dist/styles.less +64 -58
  61. package/less/components/assets.less +5 -39
  62. package/less/components/button-menu.less +1 -0
  63. package/less/components/button.less +57 -19
  64. package/less/components/story-previewer.less +1 -1
  65. package/package.json +1 -1
  66. package/src/components/app-wrapper/AppWrapper.tsx +2 -0
  67. package/src/components/assets/AssetsUploadMenu.tsx +17 -10
  68. package/src/components/confirm-modal/ConfirmModal.tsx +3 -2
  69. package/src/components/number-field/NumberField.tsx +2 -2
  70. package/src/components/replace-files-modal/ReplaceFilesModal.tsx +209 -0
  71. package/src/constants/copy.ts +5 -1
  72. package/src/constants/icons.tsx +10 -1
  73. package/src/index.ts +3 -2
  74. package/src/redux/actions/asset-uploads.ts +193 -162
  75. package/src/redux/actions/publish.ts +10 -2
  76. package/src/redux/reducers/asset-uploads.ts +2 -1
  77. package/src/utils/modal.ts +13 -1
package/dist/styles.less CHANGED
@@ -362,44 +362,6 @@ body{
362
362
  }
363
363
  }
364
364
 
365
- // .assetUploads {
366
- // .imposium-dropdown {
367
- // border: unset;
368
-
369
- // .uploads-dropzone{
370
- // position: absolute;
371
- // top: 0;
372
- // height: 100%;
373
- // z-index: 2;
374
- // display: none;
375
-
376
- // &.asset-over {
377
- // .uploads-menu{
378
- // opacity: .3;
379
- // }
380
- // .overlay {
381
- // border-style: dashed;
382
- // border-color: hsl(225, 100%, 50%);
383
- // border-width: medium;
384
- // position: absolute;
385
- // top: 50%;
386
- // left: 50%;
387
- // transform: translate(-50%, -50%);
388
- // -ms-transform: translate(-50%, -50%);
389
- // text-align: center;
390
- // height: 98%;
391
- // width: 99%;
392
- // display: flex;
393
- // z-index: 1;
394
- // p {
395
- // vertical-align: middle;
396
- // margin: auto;
397
- // }
398
- // }
399
- // }
400
- // }
401
- // }
402
- // }
403
365
  .uploads-menu {
404
366
  height: 100%;
405
367
  overflow-y: auto;
@@ -577,7 +539,7 @@ body{
577
539
  width: 173px;
578
540
  z-index: 1001;
579
541
  }
580
- }
542
+ }
581
543
 
582
544
  .asset-details .rta .rta__autocomplete {
583
545
  width: 362px;
@@ -634,6 +596,10 @@ body{
634
596
  flex-direction: row;
635
597
  justify-content: space-between;
636
598
  width: 100%;
599
+ .upload-icon {
600
+ padding-left: 2px;
601
+ padding-right: 2px;
602
+ }
637
603
  .tags-column {
638
604
  width: unset;
639
605
  padding: unset;
@@ -743,6 +709,7 @@ body{
743
709
 
744
710
  &.left{
745
711
  right: 0;
712
+ z-index: 2000;
746
713
  }
747
714
  }
748
715
  }
@@ -929,26 +896,65 @@ body{
929
896
  }
930
897
 
931
898
  .confirm-modal {
932
- position: relative;
933
- align-items: center;
934
- display: flex;
935
- flex-direction: column;
936
- top: calc(50% - 38px);
937
- p{
938
- text-align: center;
939
- padding-bottom: 5px;
940
- }
941
- .confirm-buttons {
942
- .imposium-btn {
943
- width: 76px;
944
-
945
- .btn-bold{
946
- border: 1px solid #2D8CEA;
947
- }
948
- }
949
- }
899
+ top: calc(50% - 38px);
900
+ p {
901
+ text-align: center;
902
+ padding-bottom: 5px;
903
+ }
904
+ .confirm-buttons {
905
+ .imposium-btn {
906
+ width: 76px;
907
+
908
+ .btn-bold {
909
+ border: 1px solid #2d8cea;
910
+ }
911
+ }
912
+ }
913
+ }
914
+
915
+ .replace-files-modal,
916
+ .confirm-modal {
917
+ position: relative;
918
+ align-items: center;
919
+ display: flex;
920
+ flex-direction: column;
921
+ .confirm-buttons,
922
+ .replace-files-buttons {
923
+ .imposium-btn {
924
+ width: 76px;
925
+
926
+ .btn-bold {
927
+ border: 1px solid #2d8cea;
928
+ }
929
+ }
930
+ }
931
+ }
932
+ .replace-files-modal {
933
+ text-align: center;
950
934
  }
951
935
 
936
+ .replace-files-buttons {
937
+ width: 100%;
938
+ margin-top: 10px;
939
+ .checkbox {
940
+ float: left;
941
+ padding-left: 10px;
942
+ position: relative;
943
+ top: 6px;
944
+ .label-left {
945
+ width: fit-content;
946
+ }
947
+ .checkbox {
948
+ top: 0px;
949
+ }
950
+ }
951
+ .buttons {
952
+ float: right;
953
+ padding-right: 10px;
954
+ }
955
+ }
956
+
957
+
952
958
  @cardHeaderHeight:25px;
953
959
  @cardHeaderHeightSmall:21px;
954
960
  @cardHeaderHeightLarge:35px;
@@ -2810,7 +2816,7 @@ body{
2810
2816
  padding-left:4px;
2811
2817
  height:@storyViewerHeaderHeight;
2812
2818
  background:darken(@background, 1%);
2813
- z-index: 2000;
2819
+ z-index: 1000;
2814
2820
 
2815
2821
  .output{
2816
2822
  margin-top:4px;
@@ -116,44 +116,6 @@
116
116
  }
117
117
  }
118
118
 
119
- // .assetUploads {
120
- // .imposium-dropdown {
121
- // border: unset;
122
-
123
- // .uploads-dropzone{
124
- // position: absolute;
125
- // top: 0;
126
- // height: 100%;
127
- // z-index: 2;
128
- // display: none;
129
-
130
- // &.asset-over {
131
- // .uploads-menu{
132
- // opacity: .3;
133
- // }
134
- // .overlay {
135
- // border-style: dashed;
136
- // border-color: hsl(225, 100%, 50%);
137
- // border-width: medium;
138
- // position: absolute;
139
- // top: 50%;
140
- // left: 50%;
141
- // transform: translate(-50%, -50%);
142
- // -ms-transform: translate(-50%, -50%);
143
- // text-align: center;
144
- // height: 98%;
145
- // width: 99%;
146
- // display: flex;
147
- // z-index: 1;
148
- // p {
149
- // vertical-align: middle;
150
- // margin: auto;
151
- // }
152
- // }
153
- // }
154
- // }
155
- // }
156
- // }
157
119
  .uploads-menu {
158
120
  height: 100%;
159
121
  overflow-y: auto;
@@ -331,7 +293,7 @@
331
293
  width: 173px;
332
294
  z-index: 1001;
333
295
  }
334
- }
296
+ }
335
297
 
336
298
  .asset-details .rta .rta__autocomplete {
337
299
  width: 362px;
@@ -388,6 +350,10 @@
388
350
  flex-direction: row;
389
351
  justify-content: space-between;
390
352
  width: 100%;
353
+ .upload-icon {
354
+ padding-left: 2px;
355
+ padding-right: 2px;
356
+ }
391
357
  .tags-column {
392
358
  width: unset;
393
359
  padding: unset;
@@ -22,6 +22,7 @@
22
22
 
23
23
  &.left{
24
24
  right: 0;
25
+ z-index: 2000;
25
26
  }
26
27
  }
27
28
  }
@@ -166,22 +166,60 @@
166
166
  }
167
167
 
168
168
  .confirm-modal {
169
- position: relative;
170
- align-items: center;
171
- display: flex;
172
- flex-direction: column;
173
- top: calc(50% - 38px);
174
- p{
175
- text-align: center;
176
- padding-bottom: 5px;
177
- }
178
- .confirm-buttons {
179
- .imposium-btn {
180
- width: 76px;
181
-
182
- .btn-bold{
183
- border: 1px solid #2D8CEA;
184
- }
185
- }
186
- }
187
- }
169
+ top: calc(50% - 38px);
170
+ p {
171
+ text-align: center;
172
+ padding-bottom: 5px;
173
+ }
174
+ .confirm-buttons {
175
+ .imposium-btn {
176
+ width: 76px;
177
+
178
+ .btn-bold {
179
+ border: 1px solid #2d8cea;
180
+ }
181
+ }
182
+ }
183
+ }
184
+
185
+ .replace-files-modal,
186
+ .confirm-modal {
187
+ position: relative;
188
+ align-items: center;
189
+ display: flex;
190
+ flex-direction: column;
191
+ .confirm-buttons,
192
+ .replace-files-buttons {
193
+ .imposium-btn {
194
+ width: 76px;
195
+
196
+ .btn-bold {
197
+ border: 1px solid #2d8cea;
198
+ }
199
+ }
200
+ }
201
+ }
202
+ .replace-files-modal {
203
+ text-align: center;
204
+ }
205
+
206
+ .replace-files-buttons {
207
+ width: 100%;
208
+ margin-top: 10px;
209
+ .checkbox {
210
+ float: left;
211
+ padding-left: 10px;
212
+ position: relative;
213
+ top: 6px;
214
+ .label-left {
215
+ width: fit-content;
216
+ }
217
+ .checkbox {
218
+ top: 0px;
219
+ }
220
+ }
221
+ .buttons {
222
+ float: right;
223
+ padding-right: 10px;
224
+ }
225
+ }
@@ -222,7 +222,7 @@
222
222
  padding-left:4px;
223
223
  height:@storyViewerHeaderHeight;
224
224
  background:darken(@background, 1%);
225
- z-index: 2000;
225
+ z-index: 1000;
226
226
 
227
227
  .output{
228
228
  margin-top:4px;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@imposium-hub/components",
3
- "version": "2.9.0-4",
3
+ "version": "2.9.0-6",
4
4
  "description": "React & Typescript component / asset library for Imposium front-ends",
5
5
  "main": "./dist/cjs/index.js",
6
6
  "module": "./dist/esm/index.js",
@@ -9,6 +9,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
9
9
  import { faExclamationTriangle } from '@fortawesome/pro-light-svg-icons';
10
10
  import { initPendo } from '../../utils/pendo';
11
11
  import { EditGuideModal } from '../edit-guide-modal/EditGuideModal';
12
+ import { ReplaceFilesModal } from '../replace-files-modal/ReplaceFilesModal';
12
13
 
13
14
  export interface IAppWrapperProps {
14
15
  appLabel: string;
@@ -287,6 +288,7 @@ export const AppWrapper: React.FC<IAppWrapperProps> = (props) => {
287
288
  {innerContent}
288
289
  <ConfirmModal />
289
290
  <EditGuideModal />
291
+ <ReplaceFilesModal />
290
292
  </div>
291
293
  );
292
294
  };
@@ -18,7 +18,7 @@ import AssetsTableTagsPivot from './AssetsTableTagsPivot';
18
18
  import Tag from '../tag/Tag';
19
19
  import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
20
20
  import { faEraser } from '@fortawesome/free-solid-svg-icons';
21
- import { ICON_TIMES, ICON_UPLOAD } from '../../constants/icons';
21
+ import { ICON_FILE_ADD, ICON_FILE_REPLACE, ICON_TIMES, ICON_UPLOAD } from '../../constants/icons';
22
22
  import AssetsTableDropzone from './AssetsTableDropzone';
23
23
 
24
24
  interface IAssetsUploadMenuProps {
@@ -167,6 +167,7 @@ class AssetsUploadMenu extends React.PureComponent<IAssetsUploadMenuProps, IAsse
167
167
 
168
168
  let uploadsListInner;
169
169
  const uploading = [];
170
+
170
171
  if (uploads.length > 0) {
171
172
  uploadsListInner = uploads.map((u: any) => {
172
173
  const { filename, percent, tags } = u;
@@ -182,21 +183,27 @@ class AssetsUploadMenu extends React.PureComponent<IAssetsUploadMenuProps, IAsse
182
183
  </Button>
183
184
  );
184
185
 
185
- const fileTags = tags
186
- ? tags.map((tag: string) => (
187
- <Tag
188
- key={tag}
189
- copy={tag}
190
- colorize={AssetsTableTagsPivot.COLORIZE_TAGS}
191
- />
192
- ))
193
- : [];
186
+ const fileTags =
187
+ tags && !u.assetId
188
+ ? tags.map((tag: string) => (
189
+ <Tag
190
+ key={tag}
191
+ copy={tag}
192
+ colorize={AssetsTableTagsPivot.COLORIZE_TAGS}
193
+ />
194
+ ))
195
+ : [];
194
196
 
195
197
  return (
196
198
  <div
197
199
  className='ongoing-upload'
198
200
  key={filename}>
199
201
  <div className='ongoing-upload-inner'>
202
+ {u.assetId ? (
203
+ <div className='upload-icon'>{ICON_FILE_REPLACE}</div>
204
+ ) : (
205
+ <div className='upload-icon'>{ICON_FILE_ADD}</div>
206
+ )}
200
207
  <input
201
208
  className='upload-filename'
202
209
  value={filename}
@@ -4,6 +4,7 @@ import Modal from '../modal/Modal';
4
4
  import Button from '../button/Button';
5
5
  import { confirm as copy } from '../../constants/copy';
6
6
  import Section from '../section/Section';
7
+ import { confirmModalEvent } from '../../utils/modal';
7
8
 
8
9
  export interface IConfirmModalProps {
9
10
  onYes: () => void;
@@ -65,9 +66,9 @@ export const ConfirmModal = () => {
65
66
  );
66
67
 
67
68
  useEffect(() => {
68
- window.addEventListener('openconfirmmodal', onOpen);
69
+ window.addEventListener(confirmModalEvent, onOpen);
69
70
  return () => {
70
- window.removeEventListener('openconfirmmodal', onOpen);
71
+ window.removeEventListener(confirmModalEvent, onOpen);
71
72
  };
72
73
  }, []);
73
74
 
@@ -74,8 +74,8 @@ class NumberField extends React.PureComponent<INumberFieldProps, INumberFieldSta
74
74
 
75
75
  private onChange(e) {
76
76
  let val = e.target.value;
77
- if (val === '') {
78
- val = null;
77
+ if (val === '' || val === null) {
78
+ val = this.props.min;
79
79
  } else {
80
80
  val = parseFloat(val);
81
81
  }
@@ -0,0 +1,209 @@
1
+ import React, { useCallback, useEffect, useRef, useState } from 'react';
2
+ import ReactDOM from 'react-dom';
3
+ import Modal from '../modal/Modal';
4
+ import Button from '../button/Button';
5
+ import CheckboxField from '../checkbox-field/CheckboxField';
6
+ import Section from '../section/Section';
7
+ import { assets as copy } from '../../constants/copy';
8
+ import { replaceFilesModalEvent } from '../../utils/modal';
9
+
10
+ export interface IReplaceFilesModalProps {
11
+ onUpload: (f) => any;
12
+ onInstantUpload: (f) => any;
13
+ onApplyToAll: (e) => any;
14
+ onClose: () => void;
15
+ applyToAll: boolean;
16
+ existedAssets: any[];
17
+ existedAssetIds: any[];
18
+ }
19
+
20
+ export const ReplaceFilesModal = () => {
21
+ const [props, setProps] = useState<IReplaceFilesModalProps>(null);
22
+ const [isOpen, setIsOpen] = useState<boolean>(false);
23
+ const [applyToAll, setApplyToAll] = useState<boolean>();
24
+ const [height, setHeight] = useState(200);
25
+ const [index, setIndex] = useState<number>(0);
26
+
27
+ const replaceFileModalRef = useRef(null);
28
+
29
+ useEffect(() => {
30
+ if (replaceFileModalRef.current) {
31
+ const {
32
+ current: { clientHeight }
33
+ } = replaceFileModalRef;
34
+ setHeight(clientHeight + 40);
35
+ }
36
+ });
37
+
38
+ const onOpen = (event) => {
39
+ setProps({
40
+ ...event.detail
41
+ });
42
+ setIsOpen(true);
43
+ };
44
+
45
+ const onClose = () => {
46
+ props.onClose();
47
+ setIsOpen(false);
48
+ };
49
+
50
+ const onReplaceHandler = (curApplyToAll, curIndex, file, assetId) => {
51
+ const newIndex = curIndex + 1;
52
+
53
+ if (curApplyToAll && curIndex === 0) {
54
+ const updatedAssets = props.existedAssets.map((asset, i) => {
55
+ const updatefile = asset;
56
+ updatefile['assetId'] = props.existedAssetIds[i];
57
+ return updatefile;
58
+ });
59
+
60
+ props.onInstantUpload(updatedAssets);
61
+ setIndex(0);
62
+ setIsOpen(false);
63
+ } else if (curApplyToAll) {
64
+ const updatedAssets = [];
65
+
66
+ for (let i = 0; i < props.existedAssets.length; i++) {
67
+ const updateFile =
68
+ curIndex === 0
69
+ ? props.existedAssets[i]
70
+ : props.existedAssets.slice(curIndex)[i];
71
+ updateFile['assetId'] =
72
+ curIndex === 0
73
+ ? props.existedAssetIds[i]
74
+ : props.existedAssetIds.slice(curIndex)[i];
75
+ updatedAssets.push(updateFile);
76
+ }
77
+
78
+ props.onUpload(updatedAssets);
79
+ setIndex(0);
80
+ onClose();
81
+ } else {
82
+ if (newIndex === props.existedAssets.length) {
83
+ setIndex(0);
84
+ onClose();
85
+ } else {
86
+ setIndex(newIndex);
87
+ }
88
+
89
+ const updateFile = file;
90
+ updateFile['assetId'] = assetId;
91
+ props.onUpload([updateFile]);
92
+ }
93
+ };
94
+
95
+ const onAsNewHandler = (curApplyToAll, curIndex, file) => {
96
+ const newIndex = curIndex + 1;
97
+
98
+ if (curApplyToAll) {
99
+ props.onUpload(
100
+ curIndex === 0 ? props.existedAssets : props.existedAssets.slice(curIndex)
101
+ );
102
+
103
+ setIndex(0);
104
+ onClose();
105
+ } else {
106
+ if (newIndex === props.existedAssets.length) {
107
+ setIndex(0);
108
+ onClose();
109
+ } else {
110
+ setIndex(newIndex);
111
+ }
112
+
113
+ props.onUpload([file]);
114
+ }
115
+ };
116
+
117
+ const onApplyToAllHandler = (e) => {
118
+ setApplyToAll(e);
119
+ props.onApplyToAll(e);
120
+ };
121
+
122
+ const onReplace = useCallback(
123
+ (curApplyToAll, curIndex, file, assetId) =>
124
+ onReplaceHandler(curApplyToAll, curIndex, file, assetId),
125
+ [isOpen]
126
+ );
127
+
128
+ const onApplyToAll = useCallback((e) => onApplyToAllHandler(e), [isOpen]);
129
+
130
+ const onAsNew = useCallback(
131
+ (curApplyToAll, curIndex, file) => onAsNewHandler(curApplyToAll, curIndex, file),
132
+ [isOpen]
133
+ );
134
+
135
+ useEffect(() => {
136
+ window.addEventListener(replaceFilesModalEvent, onOpen);
137
+ return () => {
138
+ window.removeEventListener(replaceFilesModalEvent, onOpen);
139
+ };
140
+ }, []);
141
+
142
+ const modal = () => {
143
+ if (isOpen) {
144
+ const file = props.existedAssets[index];
145
+ const assetId = props.existedAssetIds[index];
146
+ const name = file.name.slice(0, file.name.lastIndexOf('.'));
147
+ return (
148
+ <Modal
149
+ onRequestClose={onClose}
150
+ wrapperStyle={{
151
+ left: '0px',
152
+ width: '100%'
153
+ }}
154
+ style={{
155
+ width: '400px',
156
+ height: `${height}px`,
157
+ top: 'calc(50% - 150px)',
158
+ left: 'calc((100% - 400px) / 2)'
159
+ }}
160
+ isOpen={true}>
161
+ <Section>
162
+ <div
163
+ className='replace-files-modal'
164
+ ref={replaceFileModalRef}>
165
+ <p>{copy.uploads.title.replace('[name]', name)}</p>
166
+ <div className='replace-files-buttons'>
167
+ <div className='checkbox'>
168
+ <CheckboxField
169
+ label={copy.uploads.applyAll}
170
+ value={applyToAll}
171
+ onChange={onApplyToAll}
172
+ />
173
+ </div>
174
+ <div className='buttons'>
175
+ <Button
176
+ onClick={() => onAsNew(applyToAll, index, file)}
177
+ size='large'
178
+ style='bold'
179
+ color='primary'>
180
+ {copy.uploads.keepBoth}
181
+ </Button>
182
+ <Button
183
+ onClick={() => onReplace(applyToAll, index, file, assetId)}
184
+ size='large'
185
+ style='bold'
186
+ color='primary'>
187
+ {copy.uploads.replace}
188
+ </Button>
189
+ <Button
190
+ onClick={onClose}
191
+ size='large'
192
+ style='bold'
193
+ color='default'>
194
+ {copy.uploads.cancelButton}
195
+ </Button>
196
+ </div>
197
+ </div>
198
+ </div>
199
+ </Section>
200
+ </Modal>
201
+ );
202
+ }
203
+ };
204
+
205
+ const PortalContextComponent = () =>
206
+ ReactDOM.createPortal(modal(), document.querySelector('#react-root'));
207
+
208
+ return <PortalContextComponent />;
209
+ };
@@ -28,7 +28,11 @@ export const assets = {
28
28
  assignToProjectInfo:
29
29
  'If selected, any assets uploaded will be available to use with all projects on the current organization.',
30
30
  uploadButton: 'Upload',
31
- cancelButton: 'Cancel'
31
+ cancelButton: 'Cancel',
32
+ title: `An asset named "[name]" already exists in this project. Do you want to replace it with the one you're uploading?`,
33
+ keepBoth: 'Keep Both',
34
+ replace: 'Replace',
35
+ applyAll: 'Apply To All'
32
36
  },
33
37
  tags: {
34
38
  add: 'Add new tag',
@@ -73,7 +73,12 @@ import {
73
73
  } from '@fortawesome/pro-light-svg-icons';
74
74
  import { faCircleSmall } from '@fortawesome/pro-solid-svg-icons/faCircleSmall';
75
75
  import { faClapperboardPlay } from '@fortawesome/pro-solid-svg-icons/faClapperboardPlay';
76
- import { faCloudArrowUp, faFilters } from '@fortawesome/pro-solid-svg-icons';
76
+ import {
77
+ faCloudArrowUp,
78
+ faFileCirclePlus,
79
+ faFilePen,
80
+ faFilters
81
+ } from '@fortawesome/pro-solid-svg-icons';
77
82
  import { faCircleExclamation } from '@fortawesome/free-solid-svg-icons';
78
83
 
79
84
  export const ICON_VIDEO = <FontAwesomeIcon icon={faVideo} />;
@@ -223,3 +228,7 @@ export const ICON_UP_RIGHT_FROM_SQUARE = <FontAwesomeIcon icon={faUpRightFromSqu
223
228
  export const ICON_FILE_UPLOAD = <FontAwesomeIcon icon={faCloudArrowUp} />;
224
229
 
225
230
  export const ICON_FILE_ERROR = <FontAwesomeIcon icon={faCircleExclamation} />;
231
+
232
+ export const ICON_FILE_ADD = <FontAwesomeIcon icon={faFileCirclePlus} />;
233
+
234
+ export const ICON_FILE_REPLACE = <FontAwesomeIcon icon={faFilePen} />;