@griddo/ax 10.3.9 → 10.3.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/package.json +2 -2
- package/src/__tests__/components/Gallery/GalleryPanel/GalleryDragAndDrop/GalleryDragAndDrop.test.tsx +2 -1
- package/src/api/files.tsx +10 -5
- package/src/api/images.tsx +3 -3
- package/src/api/utils.tsx +30 -1
- package/src/components/DragAndDrop/index.tsx +5 -0
- package/src/components/Fields/UrlField/index.tsx +10 -2
- package/src/components/Gallery/GalleryPanel/GalleryDragAndDrop/index.tsx +15 -10
- package/src/components/Gallery/GalleryPanel/GalleryDragAndDrop/style.tsx +11 -10
- package/src/containers/FileDrive/actions.tsx +20 -7
- package/src/containers/Gallery/actions.tsx +6 -2
- package/src/containers/Sites/actions.tsx +30 -4
- package/src/containers/Sites/reducer.tsx +1 -1
- package/src/modules/App/Routing/NavMenu/index.tsx +1 -1
- package/src/modules/Content/index.tsx +30 -3
- package/src/modules/FileDrive/FileDragAndDrop/index.tsx +56 -21
- package/src/modules/FileDrive/FileDragAndDrop/style.tsx +69 -27
- package/src/modules/FileDrive/FileModal/DetailPanel/UsageContent/Item/index.tsx +31 -0
- package/src/modules/FileDrive/FileModal/DetailPanel/UsageContent/Item/style.tsx +43 -0
- package/src/modules/FileDrive/FileModal/DetailPanel/UsageContent/ItemGroup/index.tsx +42 -0
- package/src/modules/FileDrive/FileModal/DetailPanel/UsageContent/ItemGroup/style.tsx +34 -0
- package/src/modules/FileDrive/FileModal/DetailPanel/UsageContent/index.tsx +138 -0
- package/src/modules/FileDrive/FileModal/DetailPanel/UsageContent/style.tsx +21 -0
- package/src/modules/FileDrive/FileModal/DetailPanel/index.tsx +86 -68
- package/src/modules/FileDrive/FileModal/DetailPanel/style.tsx +1 -1
- package/src/modules/FileDrive/UploadItem/index.tsx +32 -0
- package/src/modules/FileDrive/UploadItem/style.tsx +40 -0
- package/src/modules/FileDrive/index.tsx +71 -30
- package/src/types/index.tsx +18 -0
|
@@ -18,11 +18,13 @@ const FileDragAndDrop = (props: IProps) => {
|
|
|
18
18
|
inverse = false,
|
|
19
19
|
uploadError,
|
|
20
20
|
uploadFile,
|
|
21
|
+
handleMultipleUpload,
|
|
21
22
|
handleUpload,
|
|
22
23
|
replaceData,
|
|
23
24
|
replaceFile,
|
|
24
25
|
siteID,
|
|
25
26
|
isAllowedToUpload = true,
|
|
27
|
+
resetError,
|
|
26
28
|
} = props;
|
|
27
29
|
|
|
28
30
|
const validExtensions = validFormats.map((format) => `.${format}`).join(",");
|
|
@@ -32,10 +34,10 @@ const FileDragAndDrop = (props: IProps) => {
|
|
|
32
34
|
const [inDropZone, setInDropZone] = useState(false);
|
|
33
35
|
const [dropDepth, setDropDepth] = useState(0);
|
|
34
36
|
const [uploadingState, setUploadingState] = useState({ total: 0, ready: 0 });
|
|
37
|
+
const [progress, setProgress] = useState(0);
|
|
35
38
|
|
|
36
39
|
const uploading = isUploading || uploadingState.total > uploadingState.ready;
|
|
37
40
|
const success = isSuccess && uploadingState.total === uploadingState.ready;
|
|
38
|
-
const uploadPercentage = (uploadingState.ready * 100) / uploadingState.total;
|
|
39
41
|
|
|
40
42
|
const handleDragEnter = () => {
|
|
41
43
|
setDropDepth((depth) => depth + 1);
|
|
@@ -61,14 +63,29 @@ const FileDragAndDrop = (props: IProps) => {
|
|
|
61
63
|
|
|
62
64
|
const handleDrop = async (e: React.DragEvent<HTMLDivElement>) => {
|
|
63
65
|
const files = Array.from(e.dataTransfer.files);
|
|
64
|
-
|
|
65
|
-
|
|
66
|
+
if (handleMultipleUpload && files.length > 1) {
|
|
67
|
+
if (!files.every((file) => checkType(file.type))) {
|
|
68
|
+
uploadError(true, "Invalid format");
|
|
69
|
+
} else {
|
|
70
|
+
handleMultipleUpload(files);
|
|
71
|
+
}
|
|
72
|
+
} else {
|
|
73
|
+
await uploadFiles(files);
|
|
74
|
+
}
|
|
66
75
|
setDropDepth(0);
|
|
67
76
|
};
|
|
68
77
|
|
|
69
|
-
const handleFilesUpload = (e: any) => {
|
|
78
|
+
const handleFilesUpload = async (e: any) => {
|
|
70
79
|
const files: File[] = Array.from(e.currentTarget.files);
|
|
71
|
-
|
|
80
|
+
if (handleMultipleUpload && files.length > 1) {
|
|
81
|
+
if (!files.every((file) => checkType(file.type))) {
|
|
82
|
+
uploadError(true, "Invalid format");
|
|
83
|
+
} else {
|
|
84
|
+
handleMultipleUpload(files);
|
|
85
|
+
}
|
|
86
|
+
} else {
|
|
87
|
+
await uploadFiles(files);
|
|
88
|
+
}
|
|
72
89
|
};
|
|
73
90
|
|
|
74
91
|
const uploadFiles = async (files: File[]) => {
|
|
@@ -82,27 +99,29 @@ const FileDragAndDrop = (props: IProps) => {
|
|
|
82
99
|
|
|
83
100
|
let result: IFile[] = [];
|
|
84
101
|
if (replaceData) {
|
|
85
|
-
const fileUploaded =
|
|
102
|
+
const fileUploaded =
|
|
103
|
+
files[0] && (await replaceFile(files[0], replaceData.fileID, replaceData.keepURL, siteID, setProgress));
|
|
86
104
|
if (fileUploaded) {
|
|
87
105
|
result.push(fileUploaded);
|
|
106
|
+
setUploadingState((state) => ({ total: state.total, ready: state.ready + 1 }));
|
|
88
107
|
}
|
|
89
108
|
} else {
|
|
90
109
|
while (files.length) {
|
|
91
110
|
const file = files.shift();
|
|
92
|
-
const fileUploaded = file && (await uploadFile(file, folderID, siteID || "global"));
|
|
111
|
+
const fileUploaded = file && (await uploadFile(file, folderID, siteID || "global", setProgress));
|
|
93
112
|
if (fileUploaded) {
|
|
94
113
|
result.push(fileUploaded);
|
|
114
|
+
setUploadingState((state) => ({ total: state.total, ready: state.ready + 1 }));
|
|
95
115
|
}
|
|
96
|
-
setUploadingState((state) => ({ total: state.total, ready: state.ready + 1 }));
|
|
97
116
|
}
|
|
98
117
|
}
|
|
99
118
|
|
|
100
|
-
if (result) {
|
|
119
|
+
if (result.length) {
|
|
101
120
|
setInDropZone(false);
|
|
102
121
|
setUploadingState({ total: 0, ready: 0 });
|
|
103
122
|
setTimeout(() => {
|
|
104
123
|
handleUpload(result);
|
|
105
|
-
}, 3000)
|
|
124
|
+
}, 3000);
|
|
106
125
|
}
|
|
107
126
|
} catch (error) {
|
|
108
127
|
console.log(error);
|
|
@@ -111,6 +130,8 @@ const FileDragAndDrop = (props: IProps) => {
|
|
|
111
130
|
|
|
112
131
|
const handleTryAgain = () => {
|
|
113
132
|
setInDropZone(false);
|
|
133
|
+
setUploadingState({ total: 0, ready: 0 });
|
|
134
|
+
resetError();
|
|
114
135
|
};
|
|
115
136
|
|
|
116
137
|
const handleFileClick = () => {
|
|
@@ -149,9 +170,9 @@ const FileDragAndDrop = (props: IProps) => {
|
|
|
149
170
|
<S.DragSubtitle>Valid formats: {validFormats.join(", ")}. Max. size: 50MB</S.DragSubtitle>
|
|
150
171
|
</S.DragStatus>
|
|
151
172
|
<S.DragOverStatus onDragEnter={handleDragEnter} onDragLeave={handleDragLeave}>
|
|
152
|
-
<S.
|
|
153
|
-
<Icon name="
|
|
154
|
-
</S.
|
|
173
|
+
<S.DropIcon>
|
|
174
|
+
<Icon name="page" size="48" />
|
|
175
|
+
</S.DropIcon>
|
|
155
176
|
<S.DragTitle>Drop your file</S.DragTitle>
|
|
156
177
|
<S.DragSubtitle>Valid formats: {validFormats.join(", ")}. Max. size: 50MB</S.DragSubtitle>
|
|
157
178
|
</S.DragOverStatus>
|
|
@@ -189,17 +210,17 @@ const FileDragAndDrop = (props: IProps) => {
|
|
|
189
210
|
<S.StatusWrapper>
|
|
190
211
|
<S.UploadingStatus>
|
|
191
212
|
<S.DragIcon>
|
|
192
|
-
<Icon name="
|
|
213
|
+
<Icon name="page" size="48" />
|
|
193
214
|
</S.DragIcon>
|
|
194
215
|
<S.ProgressBar>
|
|
195
|
-
<ProgressBar percentage={
|
|
216
|
+
<ProgressBar percentage={progress} inverse={inverse} />
|
|
196
217
|
</S.ProgressBar>
|
|
197
218
|
<S.DragTitle>Uploading...</S.DragTitle>
|
|
198
219
|
</S.UploadingStatus>
|
|
199
220
|
<S.SuccessStatus>
|
|
200
|
-
<S.
|
|
221
|
+
<S.SuccessIcon>
|
|
201
222
|
<Icon name="success" size="48" />
|
|
202
|
-
</S.
|
|
223
|
+
</S.SuccessIcon>
|
|
203
224
|
<S.DragTitle>File loaded!</S.DragTitle>
|
|
204
225
|
</S.SuccessStatus>
|
|
205
226
|
<S.ErrorStatus>
|
|
@@ -228,11 +249,24 @@ interface IProps {
|
|
|
228
249
|
inverse?: boolean;
|
|
229
250
|
siteID: number | "global";
|
|
230
251
|
isAllowedToUpload?: boolean;
|
|
231
|
-
uploadError: (error: boolean, msg?: string) => Promise<void>;
|
|
232
|
-
uploadFile: (docFiles: File | File[], folderID: number | null, siteID: number | "global") => Promise<IFile | null>;
|
|
233
|
-
handleUpload: (result: IFile[]) => void;
|
|
234
252
|
replaceData?: { fileID: number; keepURL: boolean };
|
|
235
|
-
|
|
253
|
+
handleUpload: (result: IFile[]) => void;
|
|
254
|
+
handleMultipleUpload?: (files: File[]) => void;
|
|
255
|
+
uploadError: (error: boolean, msg?: string) => Promise<void>;
|
|
256
|
+
uploadFile: (
|
|
257
|
+
docFiles: File | File[],
|
|
258
|
+
folderID: number | null,
|
|
259
|
+
siteID: number | "global",
|
|
260
|
+
setProgress?: (progress: number) => void
|
|
261
|
+
) => Promise<IFile | null>;
|
|
262
|
+
replaceFile: (
|
|
263
|
+
docFile: File,
|
|
264
|
+
fileID: number,
|
|
265
|
+
keepUrl: boolean,
|
|
266
|
+
siteID: number | "global",
|
|
267
|
+
setProgress?: (progress: number) => void
|
|
268
|
+
) => Promise<IFile | null>;
|
|
269
|
+
resetError: () => void;
|
|
236
270
|
}
|
|
237
271
|
|
|
238
272
|
const mapStateToProps = (state: IRootState) => ({
|
|
@@ -246,6 +280,7 @@ const mapDispatchToProps = {
|
|
|
246
280
|
uploadError: fileDriveActions.uploadError,
|
|
247
281
|
uploadFile: fileDriveActions.uploadFile,
|
|
248
282
|
replaceFile: fileDriveActions.replaceFile,
|
|
283
|
+
resetError: fileDriveActions.resetError,
|
|
249
284
|
};
|
|
250
285
|
|
|
251
286
|
export default connect(mapStateToProps, mapDispatchToProps)(memo(FileDragAndDrop));
|
|
@@ -2,7 +2,7 @@ import React from "react";
|
|
|
2
2
|
import styled from "styled-components";
|
|
3
3
|
import Button from "@ax/components/Button";
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
const Wrapper = styled.div<{ inverse: boolean }>`
|
|
6
6
|
background-color: ${(p) => (p.inverse ? p.theme.color.overlay : p.theme.color.uiBarBackground)};
|
|
7
7
|
position: relative;
|
|
8
8
|
transition: opacity 0.1s;
|
|
@@ -11,7 +11,7 @@ export const Wrapper = styled.div<{ inverse: boolean }>`
|
|
|
11
11
|
padding: ${(p) => p.theme.spacing.m};
|
|
12
12
|
`;
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
const StatusWrapper = styled.div`
|
|
15
15
|
position: absolute;
|
|
16
16
|
top: 50%;
|
|
17
17
|
left: 50%;
|
|
@@ -19,69 +19,89 @@ export const StatusWrapper = styled.div`
|
|
|
19
19
|
text-align: center;
|
|
20
20
|
`;
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
const DragStatus = styled.div`
|
|
23
23
|
transition: opacity 0.1s;
|
|
24
24
|
`;
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
const DragTitle = styled.div`
|
|
27
27
|
${(p) => p.theme.textStyle.fieldLabel};
|
|
28
28
|
margin-bottom: ${(p) => p.theme.spacing.xxs};
|
|
29
29
|
`;
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
const DragSubtitle = styled.div`
|
|
32
32
|
${(p) => p.theme.textStyle.uiXS};
|
|
33
33
|
margin-bottom: ${(p) => p.theme.spacing.xxs};
|
|
34
34
|
`;
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
const DragIcon = styled.div`
|
|
37
37
|
height: ${(p) => p.theme.spacing.l};
|
|
38
38
|
margin-bottom: ${(p) => p.theme.spacing.s};
|
|
39
39
|
`;
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
${
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}
|
|
41
|
+
const DropIcon = styled.div`
|
|
42
|
+
height: ${(p) => p.theme.spacing.l};
|
|
43
|
+
margin-bottom: ${(p) => p.theme.spacing.s};
|
|
44
|
+
svg {
|
|
45
|
+
path {
|
|
46
|
+
fill: ${(p) => p.theme.color.interactiveInverse};
|
|
48
47
|
}
|
|
49
48
|
}
|
|
50
49
|
`;
|
|
51
50
|
|
|
52
|
-
|
|
51
|
+
const SuccessIcon = styled.div`
|
|
52
|
+
height: ${(p) => p.theme.spacing.l};
|
|
53
|
+
margin-bottom: ${(p) => p.theme.spacing.s};
|
|
54
|
+
svg {
|
|
55
|
+
path {
|
|
56
|
+
fill: ${(p) => p.theme.color.online};
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
`;
|
|
60
|
+
|
|
61
|
+
const UploadingStatus = styled.div`
|
|
53
62
|
transition: opacity 0.1s;
|
|
54
63
|
`;
|
|
55
64
|
|
|
56
|
-
|
|
65
|
+
const SuccessStatus = styled.div`
|
|
57
66
|
transition: opacity 0.1s;
|
|
58
|
-
${DragIcon
|
|
67
|
+
${DragIcon} {
|
|
59
68
|
svg {
|
|
60
69
|
path {
|
|
61
70
|
fill: ${(p) => p.theme.color.online};
|
|
62
71
|
}
|
|
63
72
|
}
|
|
64
73
|
}
|
|
65
|
-
${DragTitle
|
|
74
|
+
${DragTitle} {
|
|
66
75
|
color: ${(p) => p.theme.color.textHighEmphasis};
|
|
67
76
|
}
|
|
68
77
|
`;
|
|
69
78
|
|
|
70
|
-
|
|
79
|
+
const ErrorStatus = styled.div`
|
|
71
80
|
transition: opacity 0.1s;
|
|
72
|
-
${DragIcon
|
|
81
|
+
${DragIcon} {
|
|
73
82
|
svg {
|
|
74
83
|
path {
|
|
75
84
|
fill: ${(p) => p.theme.color.error};
|
|
76
85
|
}
|
|
77
86
|
}
|
|
78
87
|
}
|
|
79
|
-
${DragTitle
|
|
88
|
+
${DragTitle} {
|
|
80
89
|
color: ${(p) => p.theme.color.textHighEmphasis};
|
|
81
90
|
}
|
|
82
91
|
`;
|
|
83
92
|
|
|
84
|
-
|
|
93
|
+
const DragOverStatus = styled.div`
|
|
94
|
+
transition: opacity 0.1s;
|
|
95
|
+
${DragIcon} {
|
|
96
|
+
svg {
|
|
97
|
+
path {
|
|
98
|
+
fill: #ffffff;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
`;
|
|
103
|
+
|
|
104
|
+
const DragAndDropWrapper = styled.div<{
|
|
85
105
|
inDropZone: boolean;
|
|
86
106
|
uploading: boolean;
|
|
87
107
|
success: boolean;
|
|
@@ -127,7 +147,7 @@ export const DragAndDropWrapper = styled.div<{
|
|
|
127
147
|
}
|
|
128
148
|
`;
|
|
129
149
|
|
|
130
|
-
|
|
150
|
+
const UploadingWrapper = styled.div<{
|
|
131
151
|
inDropZone: boolean;
|
|
132
152
|
uploading: boolean;
|
|
133
153
|
success: boolean;
|
|
@@ -172,22 +192,22 @@ export const UploadingWrapper = styled.div<{
|
|
|
172
192
|
}
|
|
173
193
|
`;
|
|
174
194
|
|
|
175
|
-
|
|
195
|
+
const ErrorMsg = styled.div`
|
|
176
196
|
${(p) => p.theme.textStyle.uiXS};
|
|
177
197
|
color: ${(p) => p.theme.color.textMediumEmphasis};
|
|
178
198
|
margin-top: ${(p) => p.theme.spacing.xxs};
|
|
179
199
|
`;
|
|
180
200
|
|
|
181
|
-
|
|
201
|
+
const StyledButton = styled((props) => <Button {...props} />)`
|
|
182
202
|
margin-top: ${(p) => p.theme.spacing.s};
|
|
183
203
|
`;
|
|
184
204
|
|
|
185
|
-
|
|
205
|
+
const FilesInput = styled.input<{ ref: any }>`
|
|
186
206
|
display: none;
|
|
187
207
|
`;
|
|
188
208
|
|
|
189
209
|
const _Button: any = React.forwardRef((props: any, ref?: React.Ref<HTMLDivElement>) => <Button {...props} />);
|
|
190
|
-
|
|
210
|
+
const FilesButton = styled(_Button)`
|
|
191
211
|
margin-top: ${(p) => p.theme.spacing.xs};
|
|
192
212
|
margin-bottom: ${(p) => p.theme.spacing.xs};
|
|
193
213
|
|
|
@@ -206,6 +226,28 @@ export const FilesButton = styled(_Button)`
|
|
|
206
226
|
}
|
|
207
227
|
`;
|
|
208
228
|
|
|
209
|
-
|
|
229
|
+
const ProgressBar = styled.div`
|
|
210
230
|
margin-bottom: ${(p) => p.theme.spacing.xs};
|
|
211
231
|
`;
|
|
232
|
+
|
|
233
|
+
export {
|
|
234
|
+
Wrapper,
|
|
235
|
+
StatusWrapper,
|
|
236
|
+
DragStatus,
|
|
237
|
+
DragTitle,
|
|
238
|
+
DragSubtitle,
|
|
239
|
+
DragIcon,
|
|
240
|
+
DropIcon,
|
|
241
|
+
SuccessIcon,
|
|
242
|
+
UploadingStatus,
|
|
243
|
+
SuccessStatus,
|
|
244
|
+
ErrorStatus,
|
|
245
|
+
DragOverStatus,
|
|
246
|
+
DragAndDropWrapper,
|
|
247
|
+
UploadingWrapper,
|
|
248
|
+
ErrorMsg,
|
|
249
|
+
StyledButton,
|
|
250
|
+
FilesInput,
|
|
251
|
+
FilesButton,
|
|
252
|
+
ProgressBar,
|
|
253
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { getFormattedDateWithTimezone } from "@ax/helpers";
|
|
3
|
+
|
|
4
|
+
import * as S from "./style";
|
|
5
|
+
|
|
6
|
+
const Item = (props: IItemProps): JSX.Element => {
|
|
7
|
+
const { title, type, date, onClick } = props;
|
|
8
|
+
|
|
9
|
+
const pageType = type || "Page";
|
|
10
|
+
|
|
11
|
+
return (
|
|
12
|
+
<S.ListItem onClick={onClick}>
|
|
13
|
+
<S.Content>
|
|
14
|
+
<S.Header>
|
|
15
|
+
<S.Type>{pageType}</S.Type>
|
|
16
|
+
<S.Date>{getFormattedDateWithTimezone(date, "d MMM Y")}</S.Date>
|
|
17
|
+
</S.Header>
|
|
18
|
+
<S.Title>{title}</S.Title>
|
|
19
|
+
</S.Content>
|
|
20
|
+
</S.ListItem>
|
|
21
|
+
);
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
interface IItemProps {
|
|
25
|
+
title: string;
|
|
26
|
+
type?: string;
|
|
27
|
+
date: Date;
|
|
28
|
+
onClick: () => void;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export default Item;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import styled from "styled-components";
|
|
2
|
+
|
|
3
|
+
const ListItem = styled.li`
|
|
4
|
+
display: flex;
|
|
5
|
+
width: 100%;
|
|
6
|
+
padding: ${(p) => p.theme.spacing.s};
|
|
7
|
+
background-color: ${(p) => p.theme.color.uiBarBackground};
|
|
8
|
+
border: 1px solid ${(p) => p.theme.color.uiLine};
|
|
9
|
+
border-radius: ${(p) => p.theme.radii.s};
|
|
10
|
+
margin-bottom: ${(p) => p.theme.spacing.xs};
|
|
11
|
+
:hover {
|
|
12
|
+
background-color: ${(p) => p.theme.color.overlayHoverPrimary};
|
|
13
|
+
cursor: pointer;
|
|
14
|
+
}
|
|
15
|
+
`;
|
|
16
|
+
|
|
17
|
+
const Title = styled.div`
|
|
18
|
+
${(p) => p.theme.textStyle.fieldContent}
|
|
19
|
+
color: ${(p) => p.theme.colors.textHighEmphasis};
|
|
20
|
+
`;
|
|
21
|
+
|
|
22
|
+
const Header = styled.div`
|
|
23
|
+
display: flex;
|
|
24
|
+
margin-bottom: ${(p) => p.theme.spacing.xxs};
|
|
25
|
+
`;
|
|
26
|
+
|
|
27
|
+
const Type = styled.div`
|
|
28
|
+
${(p) => p.theme.textStyle.headingXXS};
|
|
29
|
+
color: ${(p) => p.theme.colors.textLowEmphasis};
|
|
30
|
+
`;
|
|
31
|
+
|
|
32
|
+
const Date = styled.div`
|
|
33
|
+
${(p) => p.theme.textStyle.uiXS};
|
|
34
|
+
color: ${(p) => p.theme.colors.textLowEmphasis};
|
|
35
|
+
margin-left: auto;
|
|
36
|
+
`;
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
const Content = styled.div`
|
|
40
|
+
width: 100%;
|
|
41
|
+
`;
|
|
42
|
+
|
|
43
|
+
export { ListItem, Title, Header, Type, Date, Content };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import React, { useState } from "react";
|
|
2
|
+
import { IFileUseItem } from "@ax/types";
|
|
3
|
+
import Item from "../Item";
|
|
4
|
+
|
|
5
|
+
import * as S from "./style";
|
|
6
|
+
|
|
7
|
+
const ItemGroup = (props: IItemGroupProps): React.ReactElement => {
|
|
8
|
+
const { title, items, onClick } = props;
|
|
9
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
10
|
+
|
|
11
|
+
const handleClick = () => setIsOpen(!isOpen);
|
|
12
|
+
|
|
13
|
+
return (
|
|
14
|
+
<S.Wrapper>
|
|
15
|
+
<S.Label onClick={handleClick} isOpen={isOpen}>
|
|
16
|
+
{title}
|
|
17
|
+
</S.Label>
|
|
18
|
+
<S.Content isOpen={isOpen}>
|
|
19
|
+
{items.map((item: any) => {
|
|
20
|
+
const handleClick = () => onClick(item);
|
|
21
|
+
return (
|
|
22
|
+
<Item
|
|
23
|
+
title={item.title}
|
|
24
|
+
date={item.published}
|
|
25
|
+
type={item.structuredDataId || "Page"}
|
|
26
|
+
key={item.id}
|
|
27
|
+
onClick={handleClick}
|
|
28
|
+
/>
|
|
29
|
+
);
|
|
30
|
+
})}
|
|
31
|
+
</S.Content>
|
|
32
|
+
</S.Wrapper>
|
|
33
|
+
);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
interface IItemGroupProps {
|
|
37
|
+
title: string;
|
|
38
|
+
items: IFileUseItem[];
|
|
39
|
+
onClick(item: IFileUseItem): void;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export default ItemGroup;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import styled from "styled-components";
|
|
2
|
+
|
|
3
|
+
const Wrapper = styled.div`
|
|
4
|
+
margin: ${(p) => `${p.theme.spacing.m} 0 ${p.theme.spacing.m} 0`};
|
|
5
|
+
`;
|
|
6
|
+
|
|
7
|
+
const Label = styled.div<{ isOpen: boolean }>`
|
|
8
|
+
position: relative;
|
|
9
|
+
${(p) => p.theme.textStyle.headingXXS};
|
|
10
|
+
color: ${(p) => p.theme.colors.textMediumEmphasis};
|
|
11
|
+
padding-bottom: ${(p) => p.theme.spacing.xs};
|
|
12
|
+
margin-bottom: ${(p) => p.theme.spacing.xs};
|
|
13
|
+
cursor: pointer;
|
|
14
|
+
:after {
|
|
15
|
+
position: absolute;
|
|
16
|
+
right: 10px;
|
|
17
|
+
top: ${(p) => (p.isOpen ? `10px` : `6px`)};
|
|
18
|
+
content: "";
|
|
19
|
+
border: solid ${(p) => p.theme.color.interactive01};
|
|
20
|
+
border-width: 0 2px 2px 0;
|
|
21
|
+
display: inline-block;
|
|
22
|
+
padding: 3px;
|
|
23
|
+
transform: ${(p) => (p.isOpen ? `rotate(-135deg)` : `rotate(45deg)`)};
|
|
24
|
+
}
|
|
25
|
+
`;
|
|
26
|
+
|
|
27
|
+
const Content = styled.div<{ isOpen: boolean }>`
|
|
28
|
+
overflow-y: ${(p) => (p.isOpen ? "visible" : "hidden")};
|
|
29
|
+
max-height: ${(p) => (p.isOpen ? `auto` : 0)};
|
|
30
|
+
transition: all 0.5s ease-in-out;
|
|
31
|
+
border-bottom: 1px solid ${(p) => p.theme.color.uiLine};
|
|
32
|
+
`;
|
|
33
|
+
|
|
34
|
+
export { Wrapper, Label, Content };
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { connect } from "react-redux";
|
|
3
|
+
import { appActions } from "@ax/containers/App";
|
|
4
|
+
import { pageEditorActions } from "@ax/containers/PageEditor";
|
|
5
|
+
import { sitesActions } from "@ax/containers/Sites";
|
|
6
|
+
import { structuredDataActions } from "@ax/containers/StructuredData";
|
|
7
|
+
import { ISetCurrentPageIDAction } from "@ax/containers/PageEditor/interfaces";
|
|
8
|
+
import { IFile, IFileUseItem, IFileUsePages, IRootState } from "@ax/types";
|
|
9
|
+
import Item from "./Item";
|
|
10
|
+
import ItemGroup from "./ItemGroup";
|
|
11
|
+
|
|
12
|
+
import * as S from "./style";
|
|
13
|
+
|
|
14
|
+
const UsageContent = (props: IProps) => {
|
|
15
|
+
const {
|
|
16
|
+
file,
|
|
17
|
+
currentSiteID,
|
|
18
|
+
selectedTab,
|
|
19
|
+
setHistoryPush,
|
|
20
|
+
setCurrentPageID,
|
|
21
|
+
getSite,
|
|
22
|
+
setCurrentDataID,
|
|
23
|
+
setSelectedStructuredData,
|
|
24
|
+
} = props;
|
|
25
|
+
const {
|
|
26
|
+
contentInUse: { pages, simpleStructuredData, globalPages },
|
|
27
|
+
} = file;
|
|
28
|
+
|
|
29
|
+
const isSiteView = !!currentSiteID;
|
|
30
|
+
|
|
31
|
+
const getPageList = () => {
|
|
32
|
+
if (isSiteView && selectedTab !== "global") {
|
|
33
|
+
const pageItems = pages[0] ? pages[0].pages : [];
|
|
34
|
+
return pageItems.map((item: IFileUseItem) => {
|
|
35
|
+
const handleClick = () => {
|
|
36
|
+
setCurrentPageID(item.id);
|
|
37
|
+
setHistoryPush("pages/editor", true);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
return <Item title={item.title} date={item.published} key={item.id} onClick={handleClick} />;
|
|
41
|
+
});
|
|
42
|
+
} else {
|
|
43
|
+
return pages.map((item: IFileUsePages) => {
|
|
44
|
+
const handleClick = async (page: IFileUseItem) => {
|
|
45
|
+
await getSite(item.siteId);
|
|
46
|
+
setCurrentPageID(page.id);
|
|
47
|
+
setHistoryPush("/sites/pages/editor", true);
|
|
48
|
+
};
|
|
49
|
+
return <ItemGroup title={item.siteName} items={item.pages} onClick={handleClick} />;
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const getGlobalPageList = () => {
|
|
55
|
+
if (globalPages.length === 0) {
|
|
56
|
+
return <></>;
|
|
57
|
+
} else {
|
|
58
|
+
const handleClick = (item: IFileUseItem) => {
|
|
59
|
+
setCurrentPageID(item.id);
|
|
60
|
+
const path = isSiteView ? "/data/pages/editor" : "data/pages/editor";
|
|
61
|
+
setHistoryPush(path, true);
|
|
62
|
+
};
|
|
63
|
+
return <ItemGroup title="Global Pages" items={globalPages} onClick={handleClick} />;
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const getStructuredDataList = () => {
|
|
68
|
+
if (simpleStructuredData.length === 0) {
|
|
69
|
+
return <></>;
|
|
70
|
+
}
|
|
71
|
+
if (isSiteView && selectedTab !== "global") {
|
|
72
|
+
return simpleStructuredData.map((item: IFileUseItem) => {
|
|
73
|
+
const handleClick = () => {
|
|
74
|
+
item.structuredDataId && setSelectedStructuredData(item.structuredDataId, "site");
|
|
75
|
+
setCurrentDataID(item.id);
|
|
76
|
+
setHistoryPush(`data/${item.structuredDataId}/editor`, true);
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
return (
|
|
80
|
+
<Item
|
|
81
|
+
title={item.title}
|
|
82
|
+
date={item.published}
|
|
83
|
+
key={item.id}
|
|
84
|
+
type={item.structuredDataId}
|
|
85
|
+
onClick={handleClick}
|
|
86
|
+
/>
|
|
87
|
+
);
|
|
88
|
+
});
|
|
89
|
+
} else {
|
|
90
|
+
const handleClick = (item: IFileUseItem) => {
|
|
91
|
+
item.structuredDataId && setSelectedStructuredData(item.structuredDataId, "global");
|
|
92
|
+
setCurrentDataID(item.id);
|
|
93
|
+
setHistoryPush(`/data/${item.structuredDataId}/editor`, true);
|
|
94
|
+
};
|
|
95
|
+
return <ItemGroup title="Global Simple Content" items={simpleStructuredData} onClick={handleClick} />;
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
return (
|
|
100
|
+
<S.Content>
|
|
101
|
+
<S.Note>
|
|
102
|
+
Only documents <strong>selected from the File field</strong> are counted. Documents added via a URL are not
|
|
103
|
+
displayed in this list.
|
|
104
|
+
</S.Note>
|
|
105
|
+
<S.ListWrapper>
|
|
106
|
+
{getPageList()}
|
|
107
|
+
{getGlobalPageList()}
|
|
108
|
+
{getStructuredDataList()}
|
|
109
|
+
</S.ListWrapper>
|
|
110
|
+
</S.Content>
|
|
111
|
+
);
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
interface IProps {
|
|
115
|
+
file: IFile;
|
|
116
|
+
currentSiteID: number | null;
|
|
117
|
+
selectedTab: "local" | "global";
|
|
118
|
+
setHistoryPush(page: string, isEditor: boolean): Promise<void>;
|
|
119
|
+
setCurrentPageID(currentPageID: number | null): ISetCurrentPageIDAction;
|
|
120
|
+
getSite(siteID: number): Promise<void>;
|
|
121
|
+
setCurrentDataID(id: number | null): void;
|
|
122
|
+
setSelectedStructuredData(id: string, scope: string): void;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const mapDispatchToProps = {
|
|
126
|
+
setHistoryPush: appActions.setHistoryPush,
|
|
127
|
+
setCurrentPageID: pageEditorActions.setCurrentPageID,
|
|
128
|
+
getSite: sitesActions.getSite,
|
|
129
|
+
setCurrentDataID: structuredDataActions.setCurrentDataID,
|
|
130
|
+
setSelectedStructuredData: structuredDataActions.setSelectedStructuredData,
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
const mapStateToProps = (state: IRootState) => ({
|
|
134
|
+
currentSiteID: state.sites.currentSiteInfo && state.sites.currentSiteInfo.id,
|
|
135
|
+
selectedTab: state.fileDrive.selectedTab,
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
export default connect(mapStateToProps, mapDispatchToProps)(UsageContent);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import styled from "styled-components";
|
|
2
|
+
|
|
3
|
+
const Content = styled.div`
|
|
4
|
+
padding: ${(p) => p.theme.spacing.s};
|
|
5
|
+
overflow: auto;
|
|
6
|
+
height: 100%;
|
|
7
|
+
`;
|
|
8
|
+
|
|
9
|
+
const Note = styled.div`
|
|
10
|
+
${(p) => p.theme.textStyle.uiXS};
|
|
11
|
+
color: ${(p) => p.theme.color.textMediumEmphasis};
|
|
12
|
+
background-color: ${(p) => p.theme.color.uiBackground03};
|
|
13
|
+
padding: ${(p) => p.theme.spacing.s};
|
|
14
|
+
border-radius: ${(p) => p.theme.radii.s};
|
|
15
|
+
`;
|
|
16
|
+
|
|
17
|
+
const ListWrapper = styled.div`
|
|
18
|
+
margin-top: ${(p) => p.theme.spacing.xs};
|
|
19
|
+
`;
|
|
20
|
+
|
|
21
|
+
export { Content, Note, ListWrapper };
|