@griddo/ax 10.3.3 → 10.3.5
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/api/files.tsx +20 -4
- package/src/api/utils.tsx +4 -2
- package/src/components/Fields/FileField/index.tsx +1 -1
- package/src/components/FileGallery/index.tsx +101 -70
- package/src/components/FileGallery/style.tsx +19 -3
- package/src/components/Icon/components/Download.js +7 -0
- package/src/components/Icon/svgs/Download.svg +3 -0
- package/src/components/SearchField/index.tsx +17 -1
- package/src/components/SearchField/style.tsx +4 -1
- package/src/components/Tag/index.tsx +12 -2
- package/src/components/Tag/style.tsx +19 -9
- package/src/containers/FileDrive/actions.tsx +26 -0
- package/src/containers/Sites/actions.tsx +26 -13
- package/src/hooks/index.tsx +2 -0
- package/src/hooks/resize.ts +57 -0
- package/src/modules/Content/PageItem/index.tsx +1 -0
- package/src/modules/Content/index.tsx +23 -6
- package/src/modules/FileDrive/BulkListHeader/TableHeader/index.tsx +3 -1
- package/src/modules/FileDrive/BulkListHeader/TableHeader/style.tsx +16 -2
- package/src/modules/FileDrive/BulkListHeader/index.tsx +9 -2
- package/src/modules/FileDrive/FileDragAndDrop/index.tsx +4 -2
- package/src/modules/FileDrive/FileFilters/SortBy/index.tsx +60 -0
- package/src/modules/FileDrive/FileFilters/SortBy/style.tsx +31 -0
- package/src/modules/FileDrive/FileFilters/Type/index.tsx +77 -0
- package/src/modules/FileDrive/FileFilters/Type/style.tsx +39 -0
- package/src/modules/FileDrive/FileFilters/Usage/index.tsx +66 -0
- package/src/modules/FileDrive/FileFilters/Usage/style.tsx +30 -0
- package/src/modules/FileDrive/FileModal/DetailPanel/index.tsx +26 -7
- package/src/modules/FileDrive/FileModal/index.tsx +81 -15
- package/src/modules/FileDrive/GridItem/index.tsx +24 -5
- package/src/modules/FileDrive/GridItem/style.tsx +9 -4
- package/src/modules/FileDrive/ListItem/index.tsx +22 -4
- package/src/modules/FileDrive/ListItem/style.tsx +7 -1
- package/src/modules/FileDrive/atoms.tsx +27 -4
- package/src/modules/FileDrive/helpers.tsx +17 -17
- package/src/modules/FileDrive/hooks.tsx +77 -0
- package/src/modules/FileDrive/index.tsx +145 -23
- package/src/modules/FileDrive/style.tsx +40 -6
- package/src/modules/FileDrive/utils.tsx +19 -0
- package/src/modules/StructuredData/StructuredDataList/GlobalPageItem/index.tsx +1 -1
- package/src/types/index.tsx +2 -3
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@griddo/ax",
|
|
3
3
|
"description": "Griddo Author Experience",
|
|
4
|
-
"version": "10.3.
|
|
4
|
+
"version": "10.3.5",
|
|
5
5
|
"authors": [
|
|
6
6
|
"Álvaro Sánchez' <alvaro.sanches@secuoyas.com>",
|
|
7
7
|
"Carlos Torres <carlos.torres@secuoyas.com>",
|
|
@@ -230,5 +230,5 @@
|
|
|
230
230
|
"publishConfig": {
|
|
231
231
|
"access": "public"
|
|
232
232
|
},
|
|
233
|
-
"gitHead": "
|
|
233
|
+
"gitHead": "0608fd5d1b2149a0dbfbaad156b3a46727a3e673"
|
|
234
234
|
}
|
package/src/api/files.tsx
CHANGED
|
@@ -64,6 +64,12 @@ const SERVICES: { [key: string]: IServiceConfig } = {
|
|
|
64
64
|
endpoint: ["/files/", "/replace"],
|
|
65
65
|
method: "PUT",
|
|
66
66
|
},
|
|
67
|
+
DOWNLOAD_FILES: {
|
|
68
|
+
...template,
|
|
69
|
+
endpoint: "/files/download/",
|
|
70
|
+
method: "POST",
|
|
71
|
+
responseType: "blob",
|
|
72
|
+
},
|
|
67
73
|
};
|
|
68
74
|
|
|
69
75
|
const uploadFile = async (data: FormData) => {
|
|
@@ -76,17 +82,16 @@ const getFolderContent = async (params: IGetFolderParams) => {
|
|
|
76
82
|
endpoint: [prefix, suffix],
|
|
77
83
|
} = SERVICES.GET_FOLDER_CONTENT;
|
|
78
84
|
|
|
79
|
-
const { siteID, folderID, search,
|
|
85
|
+
const { siteID, folderID, search, query: filters = "" } = params;
|
|
80
86
|
|
|
81
87
|
const data = {
|
|
82
88
|
...(folderID && { folder: folderID }),
|
|
83
89
|
...(search && { search }),
|
|
84
|
-
...(order && { order }),
|
|
85
|
-
...(filter && { filterType: filter }),
|
|
86
90
|
};
|
|
87
91
|
|
|
88
92
|
const queryParams = encodeData(data);
|
|
89
|
-
const
|
|
93
|
+
const queryFilters = queryParams.length ? `${queryParams}&${filters}` : filters;
|
|
94
|
+
const query = queryFilters.length ? `?${queryFilters}` : "";
|
|
90
95
|
|
|
91
96
|
SERVICES.GET_FOLDER_CONTENT.dynamicUrl = `${host}${prefix}${siteID}${suffix}${query}`;
|
|
92
97
|
|
|
@@ -170,6 +175,16 @@ const replaceFile = async (data: FormData, fileID: number, keepUrl: boolean) =>
|
|
|
170
175
|
return sendRequest(SERVICES.REPLACE_FILE, data as any);
|
|
171
176
|
};
|
|
172
177
|
|
|
178
|
+
const downloadFiles = async (fileID: number | number[], zip: boolean) => {
|
|
179
|
+
const { host, endpoint } = SERVICES.DOWNLOAD_FILES;
|
|
180
|
+
|
|
181
|
+
const query = zip ? "?zip=on" : "";
|
|
182
|
+
|
|
183
|
+
SERVICES.DOWNLOAD_FILES.dynamicUrl = `${host}${endpoint}${fileID}${query}`;
|
|
184
|
+
|
|
185
|
+
return sendRequest(SERVICES.DOWNLOAD_FILES);
|
|
186
|
+
};
|
|
187
|
+
|
|
173
188
|
export default {
|
|
174
189
|
uploadFile,
|
|
175
190
|
getFolderContent,
|
|
@@ -183,4 +198,5 @@ export default {
|
|
|
183
198
|
moveFile,
|
|
184
199
|
moveFilesBulk,
|
|
185
200
|
replaceFile,
|
|
201
|
+
downloadFiles,
|
|
186
202
|
};
|
package/src/api/utils.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import axios, { AxiosRequestConfig, AxiosResponse, Method } from "axios";
|
|
1
|
+
import axios, { AxiosRequestConfig, AxiosResponse, Method, ResponseType } from "axios";
|
|
2
2
|
import { SET_ERROR } from "./../containers/App/constants";
|
|
3
3
|
|
|
4
4
|
export interface IServiceConfig {
|
|
@@ -8,6 +8,7 @@ export interface IServiceConfig {
|
|
|
8
8
|
headers: { "Content-type": string; accept: string; site?: number | null; lang?: number };
|
|
9
9
|
hasToken: boolean;
|
|
10
10
|
dynamicUrl?: string;
|
|
11
|
+
responseType?: ResponseType;
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
const getToken = (): Record<string, unknown> | null => {
|
|
@@ -43,7 +44,7 @@ const getHeaders = (headers: Record<string, unknown>, hasToken: boolean): Record
|
|
|
43
44
|
};
|
|
44
45
|
|
|
45
46
|
const wrapConfig = (serviceConfig: IServiceConfig): AxiosRequestConfig => {
|
|
46
|
-
const { host, endpoint, method, headers: configHeaders, hasToken, dynamicUrl } = serviceConfig;
|
|
47
|
+
const { host, endpoint, method, headers: configHeaders, hasToken, dynamicUrl, responseType } = serviceConfig;
|
|
47
48
|
|
|
48
49
|
const headers = getHeaders(configHeaders, hasToken);
|
|
49
50
|
|
|
@@ -51,6 +52,7 @@ const wrapConfig = (serviceConfig: IServiceConfig): AxiosRequestConfig => {
|
|
|
51
52
|
url: dynamicUrl ? dynamicUrl : `${host}${endpoint}`,
|
|
52
53
|
method,
|
|
53
54
|
headers,
|
|
55
|
+
responseType,
|
|
54
56
|
};
|
|
55
57
|
};
|
|
56
58
|
|
|
@@ -12,7 +12,7 @@ const FileField = (props: IFileFieldProps): JSX.Element => {
|
|
|
12
12
|
|
|
13
13
|
const { isOpen, toggleModal } = useModal(false);
|
|
14
14
|
|
|
15
|
-
const validFormats = ["pdf", "doc", "docx", "xls", "xlsx", "zip"];
|
|
15
|
+
const validFormats = ["pdf", "doc", "docx", "xls", "xlsx", "zip", "csv"];
|
|
16
16
|
|
|
17
17
|
const handleClick = () => {
|
|
18
18
|
if (!disabled) {
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
BackFolder,
|
|
15
15
|
} from "@ax/components";
|
|
16
16
|
import { fileDriveActions } from "@ax/containers/FileDrive";
|
|
17
|
-
import { usePermission } from "@ax/hooks";
|
|
17
|
+
import { usePermission, useResizable } from "@ax/hooks";
|
|
18
18
|
|
|
19
19
|
import GalleryPanel from "./GalleryPanel";
|
|
20
20
|
import GridItem from "./GridItem";
|
|
@@ -25,6 +25,10 @@ import * as S from "./style";
|
|
|
25
25
|
// refactor
|
|
26
26
|
import Breadcrumb from "@ax/modules/FileDrive/Breadcrumb";
|
|
27
27
|
import FolderTree from "@ax/modules/FileDrive/FolderTree";
|
|
28
|
+
import Type from "@ax/modules/FileDrive/FileFilters/Type";
|
|
29
|
+
import SortBy from "@ax/modules/FileDrive/FileFilters/SortBy";
|
|
30
|
+
import { useFilterQuery, useSortedListStatus } from "@ax/modules/FileDrive/hooks";
|
|
31
|
+
import { getSortedListStatus } from "@ax/modules/FileDrive/utils";
|
|
28
32
|
|
|
29
33
|
const FileGallery = (props: IProps): JSX.Element => {
|
|
30
34
|
const {
|
|
@@ -57,6 +61,11 @@ const FileGallery = (props: IProps): JSX.Element => {
|
|
|
57
61
|
|
|
58
62
|
const galleryRef = useRef<HTMLDivElement>(null);
|
|
59
63
|
|
|
64
|
+
const [ref] = useResizable();
|
|
65
|
+
|
|
66
|
+
const { setFiltersSelection, setFilterQuery, filterValues } = useFilterQuery();
|
|
67
|
+
const { sortedListStatus, setSortedListStatus } = useSortedListStatus();
|
|
68
|
+
const [currentFilterQuery, setCurrentFilterQuery] = useState("");
|
|
60
69
|
const [searchQuery, setSearchQuery] = useState<string>("");
|
|
61
70
|
const isSearching = searchQuery.length > 0;
|
|
62
71
|
|
|
@@ -95,10 +104,11 @@ const FileGallery = (props: IProps): JSX.Element => {
|
|
|
95
104
|
folderID: currentFolderID,
|
|
96
105
|
search: searchQuery,
|
|
97
106
|
loading: false,
|
|
107
|
+
query: currentFilterQuery,
|
|
98
108
|
};
|
|
99
109
|
|
|
100
110
|
return params;
|
|
101
|
-
}, [currentFolderID, searchQuery, selectedTab]);
|
|
111
|
+
}, [currentFolderID, searchQuery, selectedTab, currentFilterQuery]);
|
|
102
112
|
|
|
103
113
|
useLayoutEffect(() => {
|
|
104
114
|
return () => {
|
|
@@ -158,6 +168,21 @@ const FileGallery = (props: IProps): JSX.Element => {
|
|
|
158
168
|
await getFolderContent(params);
|
|
159
169
|
};
|
|
160
170
|
|
|
171
|
+
const sortItems = async (orderPointer: string, isAscending: boolean) => {
|
|
172
|
+
const sortedState = getSortedListStatus(orderPointer, isAscending);
|
|
173
|
+
setSortedListStatus(sortedState);
|
|
174
|
+
|
|
175
|
+
const filtersSelection = setFiltersSelection("order", orderPointer, isAscending);
|
|
176
|
+
const filterQuery = setFilterQuery(filtersSelection);
|
|
177
|
+
setCurrentFilterQuery(filterQuery);
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
const filterItems = async (filterPointer: string, filtersSelected: string) => {
|
|
181
|
+
const filtersSelection = setFiltersSelection(filterPointer, filtersSelected);
|
|
182
|
+
const filterQuery = setFilterQuery(filtersSelection);
|
|
183
|
+
setCurrentFilterQuery(filterQuery);
|
|
184
|
+
};
|
|
185
|
+
|
|
161
186
|
const foldersIcon = isPanelOpen ? <Icon name="closePanel" size="24" /> : <Icon name="openPanel" size="24" />;
|
|
162
187
|
|
|
163
188
|
const emptySearchStateProps = {
|
|
@@ -173,87 +198,93 @@ const FileGallery = (props: IProps): JSX.Element => {
|
|
|
173
198
|
|
|
174
199
|
return (
|
|
175
200
|
<S.Wrapper data-testid="file-gallery-wrapper">
|
|
176
|
-
<S.FolderPanel isOpen={isPanelOpen}>
|
|
201
|
+
<S.FolderPanel isOpen={isPanelOpen} ref={ref}>
|
|
177
202
|
<S.FolderPanelContent>
|
|
178
|
-
<FolderTree folderID={currentFolderID || 0} onClick={updateCurrentFolder} title="Folders"
|
|
203
|
+
<FolderTree folderID={currentFolderID || 0} onClick={updateCurrentFolder} title="Folders" />
|
|
179
204
|
</S.FolderPanelContent>
|
|
205
|
+
<S.ResizeHandle className="resizer" />
|
|
180
206
|
</S.FolderPanel>
|
|
181
207
|
<S.ContentWrapper>
|
|
182
|
-
|
|
208
|
+
{!!tabs.length && (
|
|
209
|
+
<S.Header>
|
|
183
210
|
{!!tabs.length && (
|
|
184
211
|
<S.TabsWrapper>
|
|
185
212
|
<Tabs tabs={tabs} active={selectedTab} setSelectedTab={handleSelectedTab} noMargins />
|
|
186
213
|
</S.TabsWrapper>
|
|
187
214
|
)}
|
|
188
|
-
<S.Filters
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
</S.
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
<S.FoldersIconWrapper onClick={togglePanel}>
|
|
216
|
-
<Tooltip content="Open folder panel">{foldersIcon}</Tooltip>
|
|
217
|
-
</S.FoldersIconWrapper>
|
|
218
|
-
</S.SectionTitle>
|
|
219
|
-
</S.SectionHeader>
|
|
220
|
-
<S.FoldersWrapper>
|
|
221
|
-
{!isRoot && !isSearching && <BackFolder onClick={handleBackClick} size="S" />}
|
|
222
|
-
<S.FoldersGrid>
|
|
223
|
-
{folders.map((folder: IFolder) => (
|
|
224
|
-
<FolderItem folder={folder} onClick={updateCurrentFolder} key={folder.folderName} />
|
|
225
|
-
))}
|
|
226
|
-
</S.FoldersGrid>
|
|
227
|
-
</S.FoldersWrapper>
|
|
228
|
-
</S.SectionWrapper>
|
|
229
|
-
)}
|
|
215
|
+
<S.Filters>
|
|
216
|
+
<Type filterItems={filterItems} value={filterValues["filterType"]} />
|
|
217
|
+
<SortBy sortItems={sortItems} sortedState={sortedListStatus} />
|
|
218
|
+
</S.Filters>
|
|
219
|
+
</S.Header>
|
|
220
|
+
)}
|
|
221
|
+
<S.Search>
|
|
222
|
+
<SearchField onChange={setSearchQuery} placeholder="Type file’s name, title, or #tag" autoFocus={false} />
|
|
223
|
+
</S.Search>
|
|
224
|
+
<S.GalleryWrapper ref={galleryRef}>
|
|
225
|
+
{isGlobalTab && isSiteView && (
|
|
226
|
+
<S.NotificationWrapper>
|
|
227
|
+
<Notification
|
|
228
|
+
type="info"
|
|
229
|
+
text="This is a global Library. All the changes you make will be applied to all the sites."
|
|
230
|
+
/>
|
|
231
|
+
</S.NotificationWrapper>
|
|
232
|
+
)}
|
|
233
|
+
<ErrorToast size="l" />
|
|
234
|
+
{isLoading ? (
|
|
235
|
+
<S.LoadingWrapper>
|
|
236
|
+
<Loader name="circle" />
|
|
237
|
+
</S.LoadingWrapper>
|
|
238
|
+
) : (
|
|
239
|
+
<>
|
|
240
|
+
{!isRoot && !isSearching && <Breadcrumb breadcrumb={breadcrumb} onClick={updateCurrentFolder} />}
|
|
241
|
+
{(hasFolders || (!isRoot && !isSearching)) && (
|
|
230
242
|
<S.SectionWrapper>
|
|
231
243
|
<S.SectionHeader>
|
|
232
|
-
<S.SectionTitle>
|
|
244
|
+
<S.SectionTitle>
|
|
245
|
+
<div>Folders</div>
|
|
246
|
+
<S.FoldersIconWrapper onClick={togglePanel}>
|
|
247
|
+
<Tooltip content="Open folder panel">{foldersIcon}</Tooltip>
|
|
248
|
+
</S.FoldersIconWrapper>
|
|
249
|
+
</S.SectionTitle>
|
|
233
250
|
</S.SectionHeader>
|
|
234
|
-
|
|
235
|
-
<S
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
) : (
|
|
243
|
-
<S.Grid>
|
|
244
|
-
{items &&
|
|
245
|
-
items.map((item: IFile) => {
|
|
246
|
-
const isSelected = item.id === selectedFile?.id;
|
|
247
|
-
return (
|
|
248
|
-
<GridItem file={item} onClick={handleClick} key={item.fileName} isSelected={isSelected} />
|
|
249
|
-
);
|
|
250
|
-
})}
|
|
251
|
-
</S.Grid>
|
|
252
|
-
)}
|
|
251
|
+
<S.FoldersWrapper>
|
|
252
|
+
{!isRoot && !isSearching && <BackFolder onClick={handleBackClick} size="S" />}
|
|
253
|
+
<S.FoldersGrid>
|
|
254
|
+
{folders.map((folder: IFolder) => (
|
|
255
|
+
<FolderItem folder={folder} onClick={updateCurrentFolder} key={folder.folderName} />
|
|
256
|
+
))}
|
|
257
|
+
</S.FoldersGrid>
|
|
258
|
+
</S.FoldersWrapper>
|
|
253
259
|
</S.SectionWrapper>
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
260
|
+
)}
|
|
261
|
+
<S.SectionWrapper>
|
|
262
|
+
<S.SectionHeader>
|
|
263
|
+
<S.SectionTitle>Documents</S.SectionTitle>
|
|
264
|
+
</S.SectionHeader>
|
|
265
|
+
{!items.length ? (
|
|
266
|
+
<S.EmptyWrapper>
|
|
267
|
+
{isSearching ? (
|
|
268
|
+
<EmptyState {...emptySearchStateProps} />
|
|
269
|
+
) : (
|
|
270
|
+
<EmptyState {...emptyFolderStateProps} />
|
|
271
|
+
)}
|
|
272
|
+
</S.EmptyWrapper>
|
|
273
|
+
) : (
|
|
274
|
+
<S.Grid>
|
|
275
|
+
{items &&
|
|
276
|
+
items.map((item: IFile) => {
|
|
277
|
+
const isSelected = item.id === selectedFile?.id;
|
|
278
|
+
return (
|
|
279
|
+
<GridItem file={item} onClick={handleClick} key={item.fileName} isSelected={isSelected} />
|
|
280
|
+
);
|
|
281
|
+
})}
|
|
282
|
+
</S.Grid>
|
|
283
|
+
)}
|
|
284
|
+
</S.SectionWrapper>
|
|
285
|
+
</>
|
|
286
|
+
)}
|
|
287
|
+
</S.GalleryWrapper>
|
|
257
288
|
</S.ContentWrapper>
|
|
258
289
|
<GalleryPanel
|
|
259
290
|
selectedFile={selectedFile}
|
|
@@ -7,11 +7,13 @@ const Wrapper = styled.div`
|
|
|
7
7
|
`;
|
|
8
8
|
|
|
9
9
|
const FolderPanel = styled.div<{ isOpen: boolean }>`
|
|
10
|
+
position: relative;
|
|
10
11
|
background-color: ${(p) => p.theme.color.uiBackground02};
|
|
11
12
|
border-right: ${(p) => `1px solid ${p.theme.color.uiLine}`};
|
|
12
13
|
width: ${(p) => (p.isOpen ? "192px" : "0")};
|
|
14
|
+
min-width: ${(p) => (p.isOpen ? "192px" : "0")};
|
|
15
|
+
max-width: ${(p) => (p.isOpen ? "370px" : "0")};
|
|
13
16
|
overflow: hidden;
|
|
14
|
-
transition: width 0.8s ease-out;
|
|
15
17
|
flex-shrink: 0;
|
|
16
18
|
`;
|
|
17
19
|
|
|
@@ -55,7 +57,7 @@ const Filters = styled.div`
|
|
|
55
57
|
|
|
56
58
|
& > * {
|
|
57
59
|
&:not(:last-child) {
|
|
58
|
-
margin-right: ${(p) => p.theme.spacing.
|
|
60
|
+
margin-right: ${(p) => p.theme.spacing.m};
|
|
59
61
|
}
|
|
60
62
|
}
|
|
61
63
|
`;
|
|
@@ -150,6 +152,19 @@ const FoldersIconWrapper = styled.div`
|
|
|
150
152
|
cursor: pointer;
|
|
151
153
|
`;
|
|
152
154
|
|
|
155
|
+
const ResizeHandle = styled.div`
|
|
156
|
+
position: absolute;
|
|
157
|
+
width: 2px;
|
|
158
|
+
right: 0;
|
|
159
|
+
top: 0;
|
|
160
|
+
bottom: 0;
|
|
161
|
+
cursor: col-resize;
|
|
162
|
+
|
|
163
|
+
&:hover {
|
|
164
|
+
background-color: ${(p) => p.theme.color.interactive01};
|
|
165
|
+
}
|
|
166
|
+
`;
|
|
167
|
+
|
|
153
168
|
export {
|
|
154
169
|
Wrapper,
|
|
155
170
|
FolderPanel,
|
|
@@ -169,5 +184,6 @@ export {
|
|
|
169
184
|
SectionTitle,
|
|
170
185
|
FoldersGrid,
|
|
171
186
|
FoldersWrapper,
|
|
172
|
-
FoldersIconWrapper
|
|
187
|
+
FoldersIconWrapper,
|
|
188
|
+
ResizeHandle,
|
|
173
189
|
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
const SvgDownload = (props) => (
|
|
3
|
+
<svg xmlns="http://www.w3.org/2000/svg" width={24} height={24} fill="none" {...props}>
|
|
4
|
+
<path fill="#5057FF" fillRule="evenodd" d="M15 9h4l-7 7-7-7h4V3h6v6ZM5 20v-2h14v2H5Z" clipRule="evenodd" />
|
|
5
|
+
</svg>
|
|
6
|
+
);
|
|
7
|
+
export default SvgDownload;
|
|
@@ -16,12 +16,27 @@ const SearchField = (props: ISearchFieldProps): JSX.Element => {
|
|
|
16
16
|
small,
|
|
17
17
|
autoFocus = true,
|
|
18
18
|
size = "M",
|
|
19
|
+
value,
|
|
19
20
|
} = props;
|
|
20
21
|
|
|
21
22
|
const [isOpen, setIsOpen] = useState(false);
|
|
22
|
-
const [inputValue, setInputValue] = useState("");
|
|
23
|
+
const [inputValue, setInputValue] = useState(value || "");
|
|
23
24
|
const [selectValue, setSelectValue] = useState<string>("");
|
|
24
25
|
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
if (inputValue.length === 0) {
|
|
28
|
+
setIsOpen(false);
|
|
29
|
+
}
|
|
30
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
31
|
+
}, [inputValue]);
|
|
32
|
+
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
if (value !== inputValue) {
|
|
35
|
+
setInputValue(value || "");
|
|
36
|
+
}
|
|
37
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
38
|
+
}, [value]);
|
|
39
|
+
|
|
25
40
|
const toggleField = () => setIsOpen(!isOpen);
|
|
26
41
|
|
|
27
42
|
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
@@ -123,6 +138,7 @@ export interface ISearchFieldProps {
|
|
|
123
138
|
small?: boolean;
|
|
124
139
|
autoFocus?: boolean;
|
|
125
140
|
size?: "M" | "S" | "XS";
|
|
141
|
+
value?: string;
|
|
126
142
|
}
|
|
127
143
|
|
|
128
144
|
export default SearchField;
|
|
@@ -17,6 +17,9 @@ const FieldWrapper = styled.div<{ closeOnInactive: boolean; disabled: boolean }>
|
|
|
17
17
|
border-width: ${(p) => (p.closeOnInactive ? "0 0 1px" : "1px")};
|
|
18
18
|
border-style: solid;
|
|
19
19
|
border-radius: ${(p) => (p.closeOnInactive ? 0 : p.theme.radii.s)};
|
|
20
|
+
&:focus-within {
|
|
21
|
+
border-color: ${(p) => (p.disabled ? p.theme.color.interactiveDisabled : p.theme.color.interactive01)};
|
|
22
|
+
}
|
|
20
23
|
`;
|
|
21
24
|
|
|
22
25
|
const Input = styled.input<{
|
|
@@ -32,13 +35,13 @@ const Input = styled.input<{
|
|
|
32
35
|
height: ${(p) => (p.inputSize === "XS" ? "40px" : p.theme.spacing.l)};
|
|
33
36
|
padding-left: ${(p) => p.theme.spacing.xs};
|
|
34
37
|
border: none;
|
|
38
|
+
border-radius: ${(p) => (p.closeOnInactive ? 0 : p.theme.radii.s)};
|
|
35
39
|
width: ${(p) =>
|
|
36
40
|
p.small || p.inputSize !== "M" ? `calc(${p.theme.spacing.xl} * 2)` : `calc(${p.theme.spacing.xl} * 4)`};
|
|
37
41
|
|
|
38
42
|
&:active,
|
|
39
43
|
&:focus {
|
|
40
44
|
outline: none;
|
|
41
|
-
border-color: ${(p) => (p.disabled ? p.theme.color.interactiveDisabled : p.theme.color.interactive01)};
|
|
42
45
|
}
|
|
43
46
|
`;
|
|
44
47
|
|
|
@@ -4,7 +4,7 @@ import { Icon } from "@ax/components";
|
|
|
4
4
|
import * as S from "./style";
|
|
5
5
|
|
|
6
6
|
const Tag = (props: ITagProps): JSX.Element => {
|
|
7
|
-
const { type, text, color, onDeleteAction } = props;
|
|
7
|
+
const { type, text, color, icon, onDeleteAction } = props;
|
|
8
8
|
|
|
9
9
|
const handleClick = () => {
|
|
10
10
|
if (onDeleteAction) {
|
|
@@ -27,7 +27,16 @@ const Tag = (props: ITagProps): JSX.Element => {
|
|
|
27
27
|
</S.TagStatus>
|
|
28
28
|
);
|
|
29
29
|
case "square":
|
|
30
|
-
return
|
|
30
|
+
return (
|
|
31
|
+
<S.TagSquare color={color} data-testid="tag-square">
|
|
32
|
+
{icon && (
|
|
33
|
+
<S.IconTag>
|
|
34
|
+
<Icon name={icon} size="16" />
|
|
35
|
+
</S.IconTag>
|
|
36
|
+
)}
|
|
37
|
+
<div>{text}</div>
|
|
38
|
+
</S.TagSquare>
|
|
39
|
+
);
|
|
31
40
|
default:
|
|
32
41
|
return (
|
|
33
42
|
<S.TagFixed color={color} data-testid="tag-fixed">
|
|
@@ -44,6 +53,7 @@ export interface ITagProps {
|
|
|
44
53
|
type?: "status" | "fixed" | "interactive" | "square" | undefined;
|
|
45
54
|
text: string;
|
|
46
55
|
color?: string;
|
|
56
|
+
icon?: string;
|
|
47
57
|
onDeleteAction?: () => void;
|
|
48
58
|
}
|
|
49
59
|
|
|
@@ -14,12 +14,12 @@ export const TagStatus = styled.div`
|
|
|
14
14
|
|
|
15
15
|
export const TagSquare = styled.div<{ color: string | undefined }>`
|
|
16
16
|
${(p) => p.theme.textStyle.uiXS};
|
|
17
|
+
display: flex;
|
|
17
18
|
background-color: ${(p) => (p.color ? p.color : p.theme.colors.uiBackground01)};
|
|
18
19
|
box-sizing: border-box;
|
|
19
20
|
border-radius: ${(p) => p.theme.radii.xs};
|
|
20
21
|
color: ${(p) => (p.color ? p.theme.color.textMediumEmphasisInverse : p.theme.color.textMediumEmphasis)};
|
|
21
22
|
white-space: nowrap;
|
|
22
|
-
display: inline-block;
|
|
23
23
|
padding: 3px 8px;
|
|
24
24
|
text-transform: capitalize;
|
|
25
25
|
`;
|
|
@@ -34,26 +34,36 @@ export const Bullet = styled.span<{ color: string | undefined }>`
|
|
|
34
34
|
`;
|
|
35
35
|
|
|
36
36
|
export const TagFixed = styled.div<{ color: string | undefined }>`
|
|
37
|
-
${(p) => p.theme.textStyle
|
|
38
|
-
background-color: ${(p) => (p.color ? p.color : p.theme.color
|
|
39
|
-
border-radius: ${(p) => p.theme.spacing
|
|
37
|
+
${(p) => p.theme.textStyle.uiS};
|
|
38
|
+
background-color: ${(p) => (p.color ? p.color : p.theme.color.interactive02)};
|
|
39
|
+
border-radius: ${(p) => p.theme.spacing.s};
|
|
40
40
|
box-sizing: border-box;
|
|
41
|
-
color: ${(p) => p.theme.color
|
|
41
|
+
color: ${(p) => p.theme.color.textMediumEmphasis};
|
|
42
42
|
display: inline-block;
|
|
43
43
|
padding: 3px 8px;
|
|
44
|
-
margin-right: ${(p) => p.theme.spacing
|
|
45
|
-
margin-bottom: ${(p) => p.theme.spacing
|
|
44
|
+
margin-right: ${(p) => p.theme.spacing.xxs};
|
|
45
|
+
margin-bottom: ${(p) => p.theme.spacing.xxs};
|
|
46
46
|
`;
|
|
47
47
|
|
|
48
48
|
export const Title = styled.div``;
|
|
49
49
|
|
|
50
50
|
export const IconWrapper = styled.div`
|
|
51
51
|
height: 16px;
|
|
52
|
-
margin-left: ${(p) => p.theme.spacing
|
|
52
|
+
margin-left: ${(p) => p.theme.spacing.xxs};
|
|
53
53
|
cursor: pointer;
|
|
54
54
|
svg {
|
|
55
55
|
path {
|
|
56
|
-
fill: ${(p) => p.theme.color
|
|
56
|
+
fill: ${(p) => p.theme.color.textMediumEmphasis};
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
`;
|
|
60
|
+
|
|
61
|
+
export const IconTag = styled.div`
|
|
62
|
+
height: 16px;
|
|
63
|
+
margin-right: ${(p) => p.theme.spacing.xs};
|
|
64
|
+
svg {
|
|
65
|
+
path {
|
|
66
|
+
fill: ${(p) => p.theme.color.textMediumEmphasis};
|
|
57
67
|
}
|
|
58
68
|
}
|
|
59
69
|
`;
|
|
@@ -367,6 +367,31 @@ function replaceFile(
|
|
|
367
367
|
};
|
|
368
368
|
}
|
|
369
369
|
|
|
370
|
+
function downloadFiles(fileID: number | number[], zip: boolean, fileName?: string): (dispatch: Dispatch) => Promise<void> {
|
|
371
|
+
return async (dispatch) => {
|
|
372
|
+
try {
|
|
373
|
+
const responseActions = {
|
|
374
|
+
handleSuccess: (response: any) => {
|
|
375
|
+
const url = window.URL.createObjectURL(new Blob([response]));
|
|
376
|
+
const a = document.createElement('a');
|
|
377
|
+
a.href = url;
|
|
378
|
+
a.download = fileName ? fileName : "download.zip"
|
|
379
|
+
document.body.appendChild(a);
|
|
380
|
+
a.click();
|
|
381
|
+
window.URL.revokeObjectURL(url);
|
|
382
|
+
},
|
|
383
|
+
handleError: (response: any) => appActions.handleError(response)(dispatch),
|
|
384
|
+
};
|
|
385
|
+
|
|
386
|
+
const callback = async () => files.downloadFiles(fileID, zip);
|
|
387
|
+
|
|
388
|
+
await handleRequest(callback, responseActions, [])(dispatch);
|
|
389
|
+
} catch (e) {
|
|
390
|
+
console.log(e);
|
|
391
|
+
}
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
|
|
370
395
|
export {
|
|
371
396
|
getFolderContent,
|
|
372
397
|
updateCurrentFolder,
|
|
@@ -383,4 +408,5 @@ export {
|
|
|
383
408
|
updateDisplayMode,
|
|
384
409
|
updateTab,
|
|
385
410
|
replaceFile,
|
|
411
|
+
downloadFiles,
|
|
386
412
|
};
|
|
@@ -279,7 +279,6 @@ function setSiteInfo(currentSiteInfo: ISite): (dispatch: any, getState: any) =>
|
|
|
279
279
|
}
|
|
280
280
|
|
|
281
281
|
getUserCurrentPermissions()(dispatch, getState);
|
|
282
|
-
|
|
283
282
|
} catch (e) {
|
|
284
283
|
console.log(e); // FIXME: capturar errores
|
|
285
284
|
}
|
|
@@ -456,8 +455,8 @@ function resetSiteValues(siteID: number): (dispatch: Dispatch) => void {
|
|
|
456
455
|
dispatch(setCurrentSitePages([]));
|
|
457
456
|
dispatch(setTotalItems(0));
|
|
458
457
|
getAnalytics(siteID)(dispatch);
|
|
459
|
-
}
|
|
460
|
-
}
|
|
458
|
+
};
|
|
459
|
+
}
|
|
461
460
|
|
|
462
461
|
function saveCurrentSiteInfo(): (dispatch: Dispatch, getState: any) => Promise<void> {
|
|
463
462
|
return async (dispatch, getState) => {
|
|
@@ -584,13 +583,6 @@ function deleteAndRemoveFromSiteBulk(
|
|
|
584
583
|
|
|
585
584
|
let responseErrorPages: any = { data: { code: null, message: null } };
|
|
586
585
|
|
|
587
|
-
const responsePageActions = {
|
|
588
|
-
handleSuccess: () => true,
|
|
589
|
-
handleError: (response: any) => {
|
|
590
|
-
responseErrorPages = response;
|
|
591
|
-
},
|
|
592
|
-
};
|
|
593
|
-
|
|
594
586
|
const getMessageErrors = () => {
|
|
595
587
|
const {
|
|
596
588
|
data: { message },
|
|
@@ -601,6 +593,14 @@ function deleteAndRemoveFromSiteBulk(
|
|
|
601
593
|
appActions.handleError(responseErrorPages, isMultiple, msg)(dispatch);
|
|
602
594
|
};
|
|
603
595
|
|
|
596
|
+
const responsePageActions = {
|
|
597
|
+
handleSuccess: () => true,
|
|
598
|
+
handleError: (response: any) => {
|
|
599
|
+
responseErrorPages = response;
|
|
600
|
+
getMessageErrors();
|
|
601
|
+
},
|
|
602
|
+
};
|
|
603
|
+
|
|
604
604
|
const responseGlobalPageActions = {
|
|
605
605
|
handleSuccess: () => {
|
|
606
606
|
if (responseErrorPages.data.message?.length > 0) {
|
|
@@ -624,10 +624,23 @@ function deleteAndRemoveFromSiteBulk(
|
|
|
624
624
|
const callbackPages = async () => pages.bulkDelete(pageIds);
|
|
625
625
|
const callbackGlobalPages = async () => sites.removePageBulk(currentSiteInfo.id, globalPageIds);
|
|
626
626
|
|
|
627
|
-
|
|
628
|
-
|
|
627
|
+
let errors = 0;
|
|
628
|
+
|
|
629
|
+
if (pageIds.length > 0) {
|
|
630
|
+
const result = await handleRequest(callbackPages, responsePageActions, [])(dispatch);
|
|
631
|
+
if (!result) {
|
|
632
|
+
errors = errors + 1;
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
if (globalPageIds.length > 0) {
|
|
637
|
+
const result = await handleRequest(callbackGlobalPages, responseGlobalPageActions, [])(dispatch);
|
|
638
|
+
if (!result) {
|
|
639
|
+
errors = errors + 1;
|
|
640
|
+
}
|
|
641
|
+
}
|
|
629
642
|
|
|
630
|
-
return
|
|
643
|
+
return errors > 0 ? false : true;
|
|
631
644
|
} catch (e) {
|
|
632
645
|
console.log(e);
|
|
633
646
|
return false;
|