@griddo/ax 1.55.15 → 1.56.3
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/GlobalStore.tsx +3 -0
- package/src/components/ConfigPanel/Form/ConnectedField/PageConnectedField/index.tsx +6 -0
- package/src/components/Fields/ArrayFieldGroup/ArrayFieldInline/index.tsx +16 -12
- package/src/components/Fields/ArrayFieldGroup/ArrayFieldItem/index.tsx +17 -15
- package/src/components/Fields/ConditionalField/index.tsx +1 -3
- package/src/components/Fields/FileField/index.tsx +1 -1
- package/src/components/Fields/Wysiwyg/config.tsx +0 -1
- package/src/components/Fields/Wysiwyg/index.tsx +16 -5
- package/src/components/Gallery/GalleryPanel/DetailPanel/index.tsx +110 -99
- package/src/components/Gallery/GalleryPanel/GalleryDragAndDrop/index.tsx +75 -55
- package/src/components/Gallery/GalleryPanel/index.tsx +14 -8
- package/src/components/Gallery/index.tsx +113 -151
- package/src/components/Gallery/style.tsx +40 -10
- package/src/components/MainWrapper/AppBar/index.tsx +1 -0
- package/src/components/Toast/index.tsx +15 -9
- package/src/components/Toast/style.tsx +2 -2
- package/src/containers/Gallery/actions.tsx +171 -0
- package/src/containers/Gallery/constants.tsx +18 -0
- package/src/containers/Gallery/index.tsx +7 -0
- package/src/containers/Gallery/interfaces.tsx +41 -0
- package/src/containers/Gallery/reducer.tsx +78 -0
- package/src/containers/PageEditor/actions.tsx +15 -5
- package/src/containers/StructuredData/actions.tsx +4 -21
- package/src/forms/fields.tsx +19 -6
- package/src/guards/error/index.tsx +3 -1
- package/src/modules/Content/HeaderMenus/Live/index.tsx +6 -5
- package/src/modules/Sites/SitesList/index.tsx +1 -1
- package/src/modules/StructuredData/Form/ConnectedField/index.tsx +2 -4
- package/src/modules/StructuredData/Form/index.tsx +10 -6
- package/src/modules/StructuredData/StructuredDataList/HeaderMenus/Live/index.tsx +1 -1
- package/src/types/index.tsx +20 -0
- package/src/components/Gallery/store.tsx +0 -186
|
@@ -1,43 +1,46 @@
|
|
|
1
|
-
import React, { memo,
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
initialState,
|
|
7
|
-
setDropDepth,
|
|
8
|
-
setInDropZone,
|
|
9
|
-
setIsUploading,
|
|
10
|
-
setUploadSuccess,
|
|
11
|
-
setUploadError,
|
|
12
|
-
uploadImage,
|
|
13
|
-
} from "../../store";
|
|
1
|
+
import React, { memo, useRef, useState } from "react";
|
|
2
|
+
import { connect } from "react-redux";
|
|
3
|
+
|
|
4
|
+
import { galleryActions } from "@ax/containers/Gallery";
|
|
5
|
+
import { IGetSiteImages, IImage, IRootState } from "@ax/types";
|
|
14
6
|
import { Icon, DragAndDrop } from "@ax/components";
|
|
15
7
|
|
|
16
8
|
import * as S from "./style";
|
|
17
9
|
|
|
18
10
|
const GalleryDragAndDrop = (props: IProps) => {
|
|
19
|
-
const { isImageSelected,
|
|
20
|
-
|
|
11
|
+
const { isImageSelected,
|
|
12
|
+
validFormats,
|
|
13
|
+
site,
|
|
14
|
+
allowUpload,
|
|
15
|
+
refreshImages,
|
|
16
|
+
uploadError,
|
|
17
|
+
isUploading,
|
|
18
|
+
isSuccess,
|
|
19
|
+
isError,
|
|
20
|
+
errorMsg,
|
|
21
|
+
uploadImage,
|
|
22
|
+
selectImage,
|
|
23
|
+
} = props;
|
|
21
24
|
const validExtensions = validFormats.map((format) => `.${format}`).join(",");
|
|
22
25
|
|
|
23
|
-
const filesInputRef = useRef<
|
|
24
|
-
const filesButtonRef = useRef<
|
|
25
|
-
|
|
26
|
-
const [
|
|
26
|
+
const filesInputRef = useRef<HTMLInputElement>(null);
|
|
27
|
+
const filesButtonRef = useRef<HTMLButtonElement>(null);
|
|
28
|
+
const [inDropZone, setInDropZone] = useState(false);
|
|
29
|
+
const [dropDepth, setDropDepth] = useState(0);
|
|
27
30
|
|
|
28
31
|
const handleDragEnter = () => {
|
|
29
|
-
|
|
32
|
+
setDropDepth((depth) => depth + 1);
|
|
30
33
|
};
|
|
31
34
|
|
|
32
35
|
const handleDragLeave = () => {
|
|
33
|
-
|
|
34
|
-
if (
|
|
35
|
-
|
|
36
|
+
setDropDepth((depth) => depth - 1);
|
|
37
|
+
if (dropDepth > 1) return;
|
|
38
|
+
setInDropZone(false);
|
|
36
39
|
};
|
|
37
40
|
|
|
38
41
|
const handleDragOver = (e: React.DragEvent<HTMLDivElement>) => {
|
|
39
42
|
e.dataTransfer.dropEffect = "copy";
|
|
40
|
-
|
|
43
|
+
setInDropZone(true);
|
|
41
44
|
};
|
|
42
45
|
|
|
43
46
|
const checkType = (type: string) => {
|
|
@@ -51,7 +54,7 @@ const GalleryDragAndDrop = (props: IProps) => {
|
|
|
51
54
|
const files = Array.from(e.dataTransfer.files);
|
|
52
55
|
e.dataTransfer.clearData();
|
|
53
56
|
await handleUploadFile(files);
|
|
54
|
-
|
|
57
|
+
setDropDepth(0);
|
|
55
58
|
};
|
|
56
59
|
|
|
57
60
|
const handleFilesUpload = (e: any) => {
|
|
@@ -61,23 +64,15 @@ const GalleryDragAndDrop = (props: IProps) => {
|
|
|
61
64
|
|
|
62
65
|
const handleUploadFile = async (files: Array<any>) => {
|
|
63
66
|
if (files[0]) {
|
|
64
|
-
dispatch(setIsUploading());
|
|
65
|
-
|
|
66
67
|
if (!checkType(files[0].type)) {
|
|
67
|
-
|
|
68
|
+
uploadError("Invalid format");
|
|
68
69
|
} else {
|
|
69
70
|
try {
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
addImage(value);
|
|
75
|
-
dispatch(setInDropZone(false));
|
|
76
|
-
} else {
|
|
77
|
-
dispatch(setUploadError("Error uploading image"));
|
|
78
|
-
}
|
|
71
|
+
const newImage = await uploadImage(files[0], site);
|
|
72
|
+
setInDropZone(false);
|
|
73
|
+
await refreshImages();
|
|
74
|
+
selectImage(newImage);
|
|
79
75
|
} catch (error) {
|
|
80
|
-
dispatch(setUploadError("Error uploading image"));
|
|
81
76
|
console.log(error);
|
|
82
77
|
}
|
|
83
78
|
}
|
|
@@ -85,16 +80,14 @@ const GalleryDragAndDrop = (props: IProps) => {
|
|
|
85
80
|
};
|
|
86
81
|
|
|
87
82
|
const handleTryAgain = () => {
|
|
88
|
-
|
|
83
|
+
setInDropZone(false);
|
|
89
84
|
};
|
|
90
85
|
|
|
91
86
|
const handleFileClick = () => {
|
|
92
|
-
|
|
93
|
-
filesInputRef.current.click();
|
|
94
|
-
}
|
|
87
|
+
filesInputRef && filesInputRef.current && filesInputRef.current.click();
|
|
95
88
|
};
|
|
96
89
|
|
|
97
|
-
const errorWrapper =
|
|
90
|
+
const errorWrapper = errorMsg ? <S.ErrorMsg>{errorMsg}</S.ErrorMsg> : null;
|
|
98
91
|
|
|
99
92
|
const renderDragAndDrop = () => (
|
|
100
93
|
<DragAndDrop
|
|
@@ -135,7 +128,7 @@ const GalleryDragAndDrop = (props: IProps) => {
|
|
|
135
128
|
<S.DragIcon>
|
|
136
129
|
<Icon name="image" size="36" />
|
|
137
130
|
</S.DragIcon>
|
|
138
|
-
<S.DragTitle>Select
|
|
131
|
+
<S.DragTitle>Select an image to see details</S.DragTitle>
|
|
139
132
|
</S.StatusWrapper>
|
|
140
133
|
|
|
141
134
|
);
|
|
@@ -143,18 +136,18 @@ const GalleryDragAndDrop = (props: IProps) => {
|
|
|
143
136
|
return (
|
|
144
137
|
<S.Wrapper hidden={isImageSelected}>
|
|
145
138
|
<S.DragAndDropWrapper
|
|
146
|
-
inDropZone={
|
|
147
|
-
uploading={
|
|
148
|
-
success={
|
|
149
|
-
error={
|
|
139
|
+
inDropZone={inDropZone}
|
|
140
|
+
uploading={isUploading}
|
|
141
|
+
success={isSuccess}
|
|
142
|
+
error={isError}
|
|
150
143
|
>
|
|
151
144
|
{allowUpload ? renderDragAndDrop() : renderPlaceholder()}
|
|
152
145
|
</S.DragAndDropWrapper>
|
|
153
146
|
<S.UploadingWrapper
|
|
154
|
-
inDropZone={
|
|
155
|
-
uploading={
|
|
156
|
-
success={
|
|
157
|
-
error={
|
|
147
|
+
inDropZone={inDropZone}
|
|
148
|
+
uploading={isUploading}
|
|
149
|
+
success={isSuccess}
|
|
150
|
+
error={isError}
|
|
158
151
|
>
|
|
159
152
|
<S.StatusWrapper>
|
|
160
153
|
<S.UploadingStatus>
|
|
@@ -185,12 +178,39 @@ const GalleryDragAndDrop = (props: IProps) => {
|
|
|
185
178
|
);
|
|
186
179
|
};
|
|
187
180
|
|
|
188
|
-
interface
|
|
181
|
+
interface IGalleryDragAndDropProps {
|
|
189
182
|
isImageSelected: boolean;
|
|
190
183
|
validFormats: string[];
|
|
191
|
-
addImage: (image: IImage) => void;
|
|
192
184
|
site: number | string;
|
|
193
185
|
allowUpload: boolean;
|
|
186
|
+
refreshImages: () => Promise<void>;
|
|
187
|
+
isUploading: boolean,
|
|
188
|
+
isSuccess: boolean,
|
|
189
|
+
isError: boolean,
|
|
190
|
+
errorMsg: string;
|
|
194
191
|
}
|
|
195
192
|
|
|
196
|
-
|
|
193
|
+
const mapStateToProps = (state: IRootState) => ({
|
|
194
|
+
isUploading: state.gallery.isUploading,
|
|
195
|
+
isSuccess: state.gallery.isSuccess,
|
|
196
|
+
isError: state.gallery.isError,
|
|
197
|
+
errorMsg: state.gallery.errorMsg,
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
interface IDispatchProps {
|
|
201
|
+
getSiteImages(params: IGetSiteImages): Promise<void>;
|
|
202
|
+
selectImage(item: IImage): void;
|
|
203
|
+
uploadError: (error: string) => Promise<void>;
|
|
204
|
+
uploadImage: (imageFile: File, site: number | string) => Promise<IImage>;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
const mapDispatchToProps = {
|
|
208
|
+
getSiteImages: galleryActions.getSiteImages,
|
|
209
|
+
selectImage: galleryActions.selectImage,
|
|
210
|
+
uploadError: galleryActions.uploadError,
|
|
211
|
+
uploadImage: galleryActions.uploadImage,
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
type IProps = IGalleryDragAndDropProps & IDispatchProps;
|
|
215
|
+
|
|
216
|
+
export default connect(mapStateToProps, mapDispatchToProps)(memo(GalleryDragAndDrop));
|
|
@@ -1,24 +1,31 @@
|
|
|
1
1
|
import React, { memo } from "react";
|
|
2
|
+
|
|
2
3
|
import { IImage } from "@ax/types";
|
|
4
|
+
|
|
3
5
|
import GalleryDragAndDrop from "./GalleryDragAndDrop";
|
|
4
6
|
import DetailPanel from "./DetailPanel";
|
|
5
|
-
|
|
6
7
|
import * as S from "./style";
|
|
7
8
|
|
|
8
9
|
const GalleryPanel = (props: IGalleryPanelProps) => {
|
|
9
|
-
const { isImageSelected, imageSelected,
|
|
10
|
+
const { isImageSelected, imageSelected, validFormats, setImage, isGlobalTab, site, selectedTab, refreshImages } =
|
|
11
|
+
props;
|
|
10
12
|
const allowUpload = !isGlobalTab || !selectedTab;
|
|
11
13
|
|
|
12
14
|
return (
|
|
13
15
|
<S.GalleryPanel>
|
|
14
|
-
<GalleryDragAndDrop
|
|
16
|
+
<GalleryDragAndDrop
|
|
17
|
+
isImageSelected={isImageSelected}
|
|
18
|
+
validFormats={validFormats}
|
|
19
|
+
site={site}
|
|
20
|
+
allowUpload={allowUpload}
|
|
21
|
+
refreshImages={refreshImages}
|
|
22
|
+
/>
|
|
15
23
|
<DetailPanel
|
|
16
24
|
imageSelected={imageSelected}
|
|
17
25
|
isImageSelected={isImageSelected}
|
|
18
26
|
setImage={setImage}
|
|
19
|
-
updateImage={updateItems}
|
|
20
|
-
deleteImage={updateItems}
|
|
21
27
|
isGlobalTab={isGlobalTab}
|
|
28
|
+
refreshImages={refreshImages}
|
|
22
29
|
/>
|
|
23
30
|
</S.GalleryPanel>
|
|
24
31
|
);
|
|
@@ -28,12 +35,11 @@ interface IGalleryPanelProps {
|
|
|
28
35
|
isImageSelected: boolean;
|
|
29
36
|
imageSelected: IImage | null;
|
|
30
37
|
validFormats: string[];
|
|
31
|
-
|
|
32
|
-
setImage: () => void;
|
|
33
|
-
addImage: (image: IImage) => void;
|
|
38
|
+
setImage: (imageData: any) => void;
|
|
34
39
|
isGlobalTab: boolean;
|
|
35
40
|
site: number | string;
|
|
36
41
|
selectedTab: string;
|
|
42
|
+
refreshImages: () => Promise<void>;
|
|
37
43
|
}
|
|
38
44
|
|
|
39
45
|
export default memo(GalleryPanel);
|
|
@@ -1,36 +1,31 @@
|
|
|
1
1
|
import React, { useEffect, useState, memo, useRef } from "react";
|
|
2
|
+
import { connect } from "react-redux";
|
|
2
3
|
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { galleryActions } from "@ax/containers/Gallery";
|
|
5
|
+
import { IData, IIsLoading } from "@ax/containers/Gallery/reducer";
|
|
6
|
+
import { IGetSiteImages, IImage, IRootState, ISite } from "@ax/types";
|
|
7
|
+
import { Icon, Loader, Tabs, SearchField, EmptyState, ErrorToast, Notification } from "@ax/components";
|
|
6
8
|
|
|
7
|
-
import Orientation from "./GalleryFilters/Orientation"
|
|
8
|
-
import SortBy from "./GalleryFilters/SortBy"
|
|
9
|
+
import Orientation from "./GalleryFilters/Orientation";
|
|
10
|
+
import SortBy from "./GalleryFilters/SortBy";
|
|
9
11
|
import GalleryPanel from "./GalleryPanel";
|
|
10
12
|
import * as S from "./style";
|
|
11
13
|
import { useFilterQuery, useSortedListStatus } from "./hooks";
|
|
12
|
-
import { getSortedListStatus } from "./utils"
|
|
14
|
+
import { getSortedListStatus } from "./utils";
|
|
13
15
|
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
+
const itemsPerPage = 50;
|
|
17
|
+
const firstPage = 1;
|
|
18
|
+
|
|
19
|
+
const Gallery = (props: IProps): JSX.Element => {
|
|
20
|
+
const { data, isLoading, getSiteImages, selectImage, getImageSelected, toggleModal, site } = props;
|
|
16
21
|
|
|
17
22
|
const tabs = [];
|
|
18
23
|
if (site) tabs.unshift(...["Local", "Global"]);
|
|
19
24
|
const [selectedTab, setSelectedTab] = useState(tabs[0]);
|
|
20
25
|
const isLocalTab = selectedTab === "Local";
|
|
26
|
+
const isGlobalTab = selectedTab === "Global";
|
|
21
27
|
const galleryScope = isLocalTab ? site.id : "global";
|
|
22
28
|
|
|
23
|
-
const initialState: IGalleryState = {
|
|
24
|
-
items: [],
|
|
25
|
-
isImageSelected: false,
|
|
26
|
-
imageSelected: null,
|
|
27
|
-
page: 1,
|
|
28
|
-
isFinished: false,
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
const [data, setData] = useState(initialState);
|
|
32
|
-
const [isLoading, setIsLoading] = useState({ init: false, more: false });
|
|
33
|
-
|
|
34
29
|
const validFormats = ["jpeg", "jpg", "png", "svg"];
|
|
35
30
|
|
|
36
31
|
const galleryRef = useRef<HTMLDivElement>(null);
|
|
@@ -40,125 +35,67 @@ const Gallery = (props: IGalleryProps): JSX.Element => {
|
|
|
40
35
|
const { sortedListStatus, setSortedListStatus } = useSortedListStatus();
|
|
41
36
|
const [searchQuery, setSearchQuery] = useState<string>("");
|
|
42
37
|
const isSearching = searchQuery.length > 0;
|
|
38
|
+
const pageRef = useRef(firstPage);
|
|
43
39
|
|
|
44
40
|
const getParams = () => ({
|
|
45
41
|
site: galleryScope,
|
|
46
|
-
page: data
|
|
47
|
-
items:
|
|
42
|
+
page: data?.page,
|
|
43
|
+
items: itemsPerPage,
|
|
48
44
|
query: currentFilterQuery,
|
|
49
|
-
search: searchQuery
|
|
45
|
+
search: searchQuery,
|
|
50
46
|
});
|
|
51
47
|
|
|
48
|
+
pageRef.current = getParams().page;
|
|
49
|
+
|
|
52
50
|
useEffect(() => {
|
|
53
51
|
const params = getParams();
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
.then((result) => {
|
|
57
|
-
setData({ items: result, page: 1, isImageSelected: false, imageSelected: null, isFinished: false });
|
|
58
|
-
setIsLoading({ init: false, more: false });
|
|
59
|
-
})
|
|
60
|
-
.catch((error) => console.log(error));
|
|
61
|
-
};
|
|
62
|
-
setIsLoading({ init: true, more: false });
|
|
63
|
-
getAndSetImages();
|
|
64
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
52
|
+
getSiteImages({ ...params, page: firstPage });
|
|
53
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
65
54
|
}, [galleryScope]);
|
|
66
55
|
|
|
67
56
|
useEffect(() => {
|
|
68
57
|
const handleScroll = () => {
|
|
69
|
-
|
|
70
|
-
galleryRef.current &&
|
|
71
|
-
galleryRef.current.
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
58
|
+
const loadMore =
|
|
59
|
+
galleryRef.current &&
|
|
60
|
+
galleryRef.current.scrollHeight -
|
|
61
|
+
(galleryRef.current.scrollTop + galleryRef.current.getBoundingClientRect().height) <
|
|
62
|
+
60 &&
|
|
63
|
+
galleryRef.current.scrollTop > 0;
|
|
64
|
+
if (!loadMore) return;
|
|
75
65
|
if (!data.isFinished) {
|
|
76
|
-
|
|
66
|
+
const params = getParams();
|
|
67
|
+
getSiteImages({ ...params, page: pageRef.current + 1, more: true });
|
|
77
68
|
}
|
|
78
69
|
};
|
|
79
70
|
window.addEventListener("scroll", handleScroll, true);
|
|
80
71
|
return () => window.removeEventListener("scroll", handleScroll, true);
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
const getAndSetMoreImages = async () => {
|
|
84
|
-
const params = getParams();
|
|
85
|
-
const result = await getSiteImages({ ...params, page: params.page + 1 });
|
|
86
|
-
try {
|
|
87
|
-
setData({
|
|
88
|
-
...data,
|
|
89
|
-
items: [...data.items, ...result],
|
|
90
|
-
page: data.page + 1,
|
|
91
|
-
isFinished: result.length < ITEMS_PER_PAGE,
|
|
92
|
-
});
|
|
93
|
-
setIsLoading({ init: false, more: false });
|
|
94
|
-
} catch (error) {
|
|
95
|
-
console.log(error);
|
|
96
|
-
}
|
|
97
|
-
};
|
|
72
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
73
|
+
}, [data?.isFinished]);
|
|
98
74
|
|
|
99
|
-
const
|
|
75
|
+
const refreshImages = async (page = firstPage) => {
|
|
100
76
|
const params = getParams();
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
setIsLoading({ init: false, more: false });
|
|
105
|
-
galleryRef && galleryRef.current && galleryRef.current.scrollTo(0, 0);
|
|
106
|
-
} catch (error) {
|
|
107
|
-
console.log(error);
|
|
108
|
-
}
|
|
77
|
+
const more = page !== firstPage;
|
|
78
|
+
await getSiteImages({ ...params, page, more });
|
|
79
|
+
if (page < params.page) refreshImages(page + 1);
|
|
109
80
|
};
|
|
110
81
|
|
|
111
82
|
useEffect(() => {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
getAndSetMoreImages();
|
|
115
|
-
}, 2000);
|
|
116
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
117
|
-
}, [isLoading.more]);
|
|
118
|
-
|
|
119
|
-
useEffect(() => {
|
|
120
|
-
setIsLoading({ init: true, more: false });
|
|
121
|
-
getAndSetImages();
|
|
83
|
+
const params = getParams();
|
|
84
|
+
getSiteImages({ ...params, page: firstPage });
|
|
122
85
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
123
86
|
}, [currentFilterQuery, searchQuery]);
|
|
124
87
|
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
setData({ ...data, imageSelected: null, isImageSelected: false });
|
|
128
|
-
} else {
|
|
129
|
-
setData({ ...data, imageSelected: item, isImageSelected: true });
|
|
130
|
-
}
|
|
88
|
+
const handleClick = (item: IImage) => (e: React.MouseEvent<HTMLDivElement>) => {
|
|
89
|
+
selectImage(item);
|
|
131
90
|
};
|
|
132
91
|
|
|
133
|
-
const setImage = () => {
|
|
134
|
-
|
|
92
|
+
const setImage = (imageData: any) => {
|
|
93
|
+
const updatedImage = { ...data.imageSelected, ...imageData };
|
|
94
|
+
getImageSelected(updatedImage);
|
|
135
95
|
toggleModal();
|
|
136
96
|
};
|
|
137
97
|
|
|
138
|
-
const updateItems = () => {
|
|
139
|
-
setIsLoading({ init: true, more: false });
|
|
140
|
-
const params = getParams();
|
|
141
|
-
getSiteImages({ ...params, page: 1 })
|
|
142
|
-
.then((result) => {
|
|
143
|
-
setData({ items: result, isImageSelected: false, imageSelected: null, page: 1, isFinished: false });
|
|
144
|
-
setIsLoading({ init: false, more: false });
|
|
145
|
-
})
|
|
146
|
-
.catch((error) => console.log(error));
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
const addImage = (item: IImage) => {
|
|
150
|
-
setIsLoading({ init: true, more: false });
|
|
151
|
-
const params = getParams();
|
|
152
|
-
getSiteImages({ ...params, page: 1 })
|
|
153
|
-
.then((result) => {
|
|
154
|
-
setData({ items: result, isImageSelected: true, imageSelected: item, page: 1, isFinished: false });
|
|
155
|
-
setIsLoading({ init: false, more: false });
|
|
156
|
-
})
|
|
157
|
-
.catch((error) => console.log(error));
|
|
158
|
-
};
|
|
159
|
-
|
|
160
98
|
const sortItems = async (orderPointer: string, isAscending: boolean) => {
|
|
161
|
-
setData((data) => ({ ...data, page: 1 }));
|
|
162
99
|
const sortedState = getSortedListStatus(orderPointer, isAscending);
|
|
163
100
|
setSortedListStatus(sortedState);
|
|
164
101
|
|
|
@@ -168,7 +105,6 @@ const Gallery = (props: IGalleryProps): JSX.Element => {
|
|
|
168
105
|
};
|
|
169
106
|
|
|
170
107
|
const filterItems = async (filterPointer: string, filtersSelected: string) => {
|
|
171
|
-
setData((data) => ({ ...data, page: 1 }));
|
|
172
108
|
const filtersSelection = setFiltersSelection(filterPointer, filtersSelected);
|
|
173
109
|
const filterQuery = setFilterQuery(filtersSelection);
|
|
174
110
|
setCurrentFilterQuery(filterQuery);
|
|
@@ -178,9 +114,9 @@ const Gallery = (props: IGalleryProps): JSX.Element => {
|
|
|
178
114
|
icon: "search",
|
|
179
115
|
title: "Oh! No Results Found",
|
|
180
116
|
message: "We couldn’t find what you are looking for. Please, try another search.",
|
|
181
|
-
}
|
|
117
|
+
};
|
|
182
118
|
|
|
183
|
-
const noSearchResults = !data
|
|
119
|
+
const noSearchResults = !data?.items?.length && isSearching;
|
|
184
120
|
|
|
185
121
|
return (
|
|
186
122
|
<S.Wrapper>
|
|
@@ -195,76 +131,102 @@ const Gallery = (props: IGalleryProps): JSX.Element => {
|
|
|
195
131
|
<Orientation filterItems={filterItems} />
|
|
196
132
|
<SortBy sortItems={sortItems} sortedState={sortedListStatus} />
|
|
197
133
|
</S.Filters>
|
|
198
|
-
</
|
|
134
|
+
</S.Header>
|
|
199
135
|
<S.Search>
|
|
200
136
|
<SearchField onChange={setSearchQuery} placeholder="Type an image’s name, title, or #tag" />
|
|
201
|
-
</
|
|
137
|
+
</S.Search>
|
|
202
138
|
<S.GalleryWrapper ref={galleryRef}>
|
|
139
|
+
{isGlobalTab && (
|
|
140
|
+
<S.NotificationWrapper>
|
|
141
|
+
<Notification
|
|
142
|
+
type="info"
|
|
143
|
+
text="This is a global Library. All the changes you make will be applied to all the sites."
|
|
144
|
+
/>
|
|
145
|
+
</S.NotificationWrapper>
|
|
146
|
+
)}
|
|
147
|
+
<ErrorToast size="l" />
|
|
203
148
|
{isLoading.init ? (
|
|
204
149
|
<S.LoadingWrapper>
|
|
205
150
|
<Loader name="circle" />
|
|
206
151
|
</S.LoadingWrapper>
|
|
207
152
|
) : (
|
|
208
|
-
|
|
209
|
-
{
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
153
|
+
<>
|
|
154
|
+
{noSearchResults ? (
|
|
155
|
+
<S.EmptyWrapper>
|
|
156
|
+
<EmptyState {...emptyStateProps} />
|
|
157
|
+
</S.EmptyWrapper>
|
|
158
|
+
) : (
|
|
159
|
+
<S.Grid>
|
|
160
|
+
{data &&
|
|
161
|
+
data.items &&
|
|
162
|
+
data.items.map((item: IImage, index: number) => {
|
|
163
|
+
const isSelected = data.imageSelected ? item.id === data.imageSelected.id : false;
|
|
164
|
+
return (
|
|
165
|
+
<S.GridItem key={item.name + index} orientation={item.orientation}>
|
|
166
|
+
<S.ImageWrapper
|
|
167
|
+
onClick={handleClick(item)}
|
|
168
|
+
selected={isSelected}
|
|
169
|
+
orientation={item.orientation}
|
|
170
|
+
>
|
|
171
|
+
<img src={item.thumb} alt={item.alt} />
|
|
172
|
+
<S.IconUnchecked>
|
|
173
|
+
<Icon name="emptyCheck" size="24" />
|
|
174
|
+
</S.IconUnchecked>
|
|
175
|
+
<S.IconChecked>
|
|
176
|
+
<Icon name="success" size="24" />
|
|
177
|
+
</S.IconChecked>
|
|
178
|
+
</S.ImageWrapper>
|
|
179
|
+
</S.GridItem>
|
|
180
|
+
);
|
|
181
|
+
})}
|
|
182
|
+
</S.Grid>
|
|
183
|
+
)}
|
|
227
184
|
{isLoading.more && (
|
|
228
185
|
<S.LoaderWrapper>
|
|
229
186
|
<Loader name="dots" />
|
|
230
187
|
</S.LoaderWrapper>
|
|
231
188
|
)}
|
|
232
|
-
|
|
233
|
-
<S.EmptyWrapper>
|
|
234
|
-
<EmptyState {...emptyStateProps} />
|
|
235
|
-
</S.EmptyWrapper>)
|
|
236
|
-
}
|
|
237
|
-
</S.Grid>
|
|
189
|
+
</>
|
|
238
190
|
)}
|
|
239
191
|
</S.GalleryWrapper>
|
|
240
|
-
</
|
|
192
|
+
</S.GalleryTabs>
|
|
241
193
|
<GalleryPanel
|
|
242
|
-
isImageSelected={data
|
|
243
|
-
imageSelected={data
|
|
194
|
+
isImageSelected={data?.isImageSelected}
|
|
195
|
+
imageSelected={data?.imageSelected}
|
|
244
196
|
validFormats={validFormats}
|
|
245
|
-
addImage={addImage}
|
|
246
|
-
updateItems={updateItems}
|
|
247
197
|
setImage={setImage}
|
|
248
198
|
isGlobalTab={!isLocalTab}
|
|
249
199
|
site={galleryScope}
|
|
250
200
|
selectedTab={selectedTab}
|
|
201
|
+
refreshImages={refreshImages}
|
|
251
202
|
/>
|
|
252
203
|
</S.Wrapper>
|
|
253
204
|
);
|
|
254
205
|
};
|
|
255
206
|
|
|
256
|
-
interface IGalleryState {
|
|
257
|
-
items: IImage[];
|
|
258
|
-
isImageSelected: boolean;
|
|
259
|
-
imageSelected: IImage | null;
|
|
260
|
-
page: number;
|
|
261
|
-
isFinished: boolean;
|
|
262
|
-
}
|
|
263
|
-
|
|
264
207
|
interface IGalleryProps {
|
|
265
208
|
getImageSelected: (img: IImage | null) => void;
|
|
266
209
|
toggleModal: () => void;
|
|
267
210
|
site: ISite;
|
|
211
|
+
data: IData;
|
|
212
|
+
isLoading: IIsLoading;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const mapStateToProps = (state: IRootState) => ({
|
|
216
|
+
data: state.gallery.data,
|
|
217
|
+
isLoading: state.gallery.isLoading,
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
interface IDispatchProps {
|
|
221
|
+
getSiteImages(params: IGetSiteImages): Promise<void>;
|
|
222
|
+
selectImage(item: IImage): void;
|
|
268
223
|
}
|
|
269
224
|
|
|
270
|
-
|
|
225
|
+
const mapDispatchToProps = {
|
|
226
|
+
getSiteImages: galleryActions.getSiteImages,
|
|
227
|
+
selectImage: galleryActions.selectImage,
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
type IProps = IGalleryProps & IDispatchProps;
|
|
231
|
+
|
|
232
|
+
export default connect(mapStateToProps, mapDispatchToProps)(memo(Gallery));
|