@griddo/ax 10.2.25 → 10.3.0

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 (94) hide show
  1. package/package.json +2 -2
  2. package/public/img/icons/excel.png +0 -0
  3. package/public/img/icons/pdf.png +0 -0
  4. package/public/img/icons/word.png +0 -0
  5. package/public/img/icons/zip.png +0 -0
  6. package/src/GlobalStore.tsx +3 -0
  7. package/src/__mocks__/store/GenericStore.ts +3 -0
  8. package/src/__tests__/components/Fields/FileField/FileField.test.tsx +34 -8
  9. package/src/__tests__/components/Gallery/GalleryPanel/GalleryDragAndDrop/GalleryDragAndDrop.test.tsx +1 -1
  10. package/src/api/files.tsx +171 -1
  11. package/src/api/users.tsx +5 -2
  12. package/src/components/ActionMenu/index.tsx +5 -13
  13. package/src/components/BackFolder/index.tsx +28 -0
  14. package/src/components/BackFolder/style.tsx +33 -0
  15. package/src/components/BulkSelectionOptions/index.tsx +4 -8
  16. package/src/components/Button/index.tsx +8 -3
  17. package/src/components/Button/style.tsx +5 -3
  18. package/src/components/ElementsTooltip/index.tsx +22 -7
  19. package/src/components/ElementsTooltip/style.tsx +2 -2
  20. package/src/components/Fields/FileField/index.tsx +7 -7
  21. package/src/components/Fields/TextField/index.tsx +3 -0
  22. package/src/components/FileGallery/FolderItem/index.tsx +39 -0
  23. package/src/components/FileGallery/FolderItem/style.tsx +31 -0
  24. package/src/components/FileGallery/GalleryPanel/DetailPanel/index.tsx +164 -0
  25. package/src/components/FileGallery/GalleryPanel/DetailPanel/style.tsx +113 -0
  26. package/src/components/FileGallery/GalleryPanel/index.tsx +42 -0
  27. package/src/components/FileGallery/GalleryPanel/style.tsx +7 -0
  28. package/src/components/FileGallery/GridItem/index.tsx +47 -0
  29. package/src/components/FileGallery/GridItem/style.tsx +51 -0
  30. package/src/components/FileGallery/index.tsx +304 -0
  31. package/src/components/FileGallery/style.tsx +173 -0
  32. package/src/components/FileGallery/utils.tsx +19 -0
  33. package/src/components/Gallery/GalleryPanel/GalleryDragAndDrop/index.tsx +4 -6
  34. package/src/components/Icon/components/Back.js +10 -0
  35. package/src/components/Icon/components/ClosePanel.js +12 -0
  36. package/src/components/Icon/components/NewFolder.js +10 -0
  37. package/src/components/Icon/components/OpenPanel.js +12 -0
  38. package/src/components/Icon/svgs/Back.svg +3 -0
  39. package/src/components/Icon/svgs/Close_panel.svg +3 -0
  40. package/src/components/Icon/svgs/New-folder.svg +3 -0
  41. package/src/components/Icon/svgs/Open_panel.svg +3 -0
  42. package/src/components/Modal/index.tsx +7 -5
  43. package/src/components/Modal/style.tsx +6 -6
  44. package/src/components/ProgressBar/index.tsx +3 -2
  45. package/src/components/ProgressBar/style.tsx +5 -3
  46. package/src/components/TableList/index.tsx +3 -2
  47. package/src/components/TableList/style.tsx +4 -0
  48. package/src/components/Toast/style.tsx +2 -2
  49. package/src/components/index.tsx +4 -0
  50. package/src/containers/FileDrive/actions.tsx +386 -0
  51. package/src/containers/FileDrive/constants.tsx +24 -0
  52. package/src/containers/FileDrive/index.tsx +7 -0
  53. package/src/containers/FileDrive/interfaces.tsx +59 -0
  54. package/src/containers/FileDrive/reducer.tsx +57 -0
  55. package/src/containers/FileDrive/utils.tsx +37 -0
  56. package/src/containers/Gallery/actions.tsx +1 -1
  57. package/src/containers/Gallery/interfaces.tsx +1 -1
  58. package/src/helpers/index.tsx +2 -0
  59. package/src/helpers/objects.tsx +6 -0
  60. package/src/modules/FileDrive/Breadcrumb/index.tsx +42 -0
  61. package/src/modules/FileDrive/Breadcrumb/style.tsx +18 -0
  62. package/src/modules/FileDrive/BulkGridHeader/GridHeader/index.tsx +37 -0
  63. package/src/modules/FileDrive/BulkGridHeader/GridHeader/style.tsx +19 -0
  64. package/src/modules/FileDrive/BulkGridHeader/index.tsx +35 -0
  65. package/src/modules/FileDrive/BulkGridHeader/style.tsx +17 -0
  66. package/src/modules/FileDrive/BulkListHeader/TableHeader/index.tsx +42 -0
  67. package/src/modules/FileDrive/BulkListHeader/TableHeader/style.tsx +53 -0
  68. package/src/modules/FileDrive/BulkListHeader/index.tsx +35 -0
  69. package/src/modules/FileDrive/BulkListHeader/style.tsx +17 -0
  70. package/src/modules/FileDrive/FileDragAndDrop/index.tsx +249 -0
  71. package/src/{components/Fields/FileField → modules/FileDrive}/FileDragAndDrop/style.tsx +50 -9
  72. package/src/modules/FileDrive/FileModal/DetailPanel/index.tsx +170 -0
  73. package/src/modules/FileDrive/FileModal/DetailPanel/style.tsx +81 -0
  74. package/src/modules/FileDrive/FileModal/index.tsx +129 -0
  75. package/src/modules/FileDrive/FileModal/style.tsx +112 -0
  76. package/src/modules/FileDrive/FolderItem/index.tsx +180 -0
  77. package/src/modules/FileDrive/FolderItem/style.tsx +39 -0
  78. package/src/modules/FileDrive/FolderTree/index.tsx +108 -0
  79. package/src/modules/FileDrive/FolderTree/style.tsx +69 -0
  80. package/src/modules/FileDrive/FolderTree/utils.tsx +91 -0
  81. package/src/modules/FileDrive/GridItem/index.tsx +167 -0
  82. package/src/modules/FileDrive/GridItem/style.tsx +76 -0
  83. package/src/modules/FileDrive/ListItem/index.tsx +180 -0
  84. package/src/modules/FileDrive/ListItem/style.tsx +88 -0
  85. package/src/modules/FileDrive/atoms.tsx +173 -0
  86. package/src/modules/FileDrive/helpers.tsx +19 -0
  87. package/src/modules/FileDrive/index.tsx +670 -0
  88. package/src/modules/FileDrive/style.tsx +145 -0
  89. package/src/modules/Sites/SitesList/index.tsx +0 -3
  90. package/src/routes/multisite.tsx +9 -0
  91. package/src/routes/site.tsx +9 -0
  92. package/src/types/index.tsx +63 -0
  93. package/src/components/Fields/FileField/FileDragAndDrop/index.tsx +0 -188
  94. package/src/components/Fields/FileField/store.tsx +0 -61
@@ -1,15 +1,14 @@
1
1
  import React from "react";
2
2
 
3
3
  import { useModal } from "@ax/hooks";
4
+ import { ISite } from "@ax/types";
4
5
  import { formatBytes, getFormattedDateWithTimezone } from "@ax/helpers";
5
- import { Icon, Modal, TextField } from "@ax/components";
6
- import FileDragAndDrop from "./FileDragAndDrop";
7
- import { MAX_SIZE } from "./store";
6
+ import { Icon, Modal, TextField, FileGallery } from "@ax/components";
8
7
 
9
8
  import * as S from "./style";
10
9
 
11
10
  const FileField = (props: IFileFieldProps): JSX.Element => {
12
- const { disabled, value, onChange } = props;
11
+ const { disabled, value, site, onChange } = props;
13
12
 
14
13
  const { isOpen, toggleModal } = useModal(false);
15
14
 
@@ -88,7 +87,7 @@ const FileField = (props: IFileFieldProps): JSX.Element => {
88
87
  <Icon name="File" size="24" />
89
88
  </S.IconWrapper>
90
89
  </S.Field>
91
- <S.HelpText>Valid formats: {validFormats.join(", ")}. Max. size: {MAX_SIZE}MB</S.HelpText>
90
+ <S.HelpText>Valid formats: {validFormats.join(", ")}. Max. size: 50MB</S.HelpText>
92
91
  </>
93
92
  )}
94
93
  {value && (
@@ -100,8 +99,8 @@ const FileField = (props: IFileFieldProps): JSX.Element => {
100
99
  <S.StyledActionMenu icon="more" options={menuOptions} tooltip="Actions" />
101
100
  </S.Component>
102
101
  )}
103
- <Modal isOpen={isOpen} hide={toggleModal} size="M" title="Select file">
104
- {isOpen && <FileDragAndDrop validFormats={validFormats} addFile={addFile} />}
102
+ <Modal isOpen={isOpen} hide={toggleModal} size="XL" title="Select file">
103
+ {isOpen && <FileGallery validFormats={validFormats} addFile={addFile} toggleModal={toggleModal} site={site} />}
105
104
  </Modal>
106
105
  </>
107
106
  );
@@ -111,6 +110,7 @@ export interface IFileFieldProps {
111
110
  value: any;
112
111
  onChange: (value: any) => void;
113
112
  disabled?: boolean;
113
+ site: ISite | null;
114
114
  }
115
115
 
116
116
  export default FileField;
@@ -16,6 +16,7 @@ const TextField = (props: ITextFieldProps): JSX.Element => {
16
16
  className,
17
17
  onChange,
18
18
  onBlur,
19
+ onKeyDown,
19
20
  inputType = "text",
20
21
  disabled,
21
22
  iconPosition = "out",
@@ -89,6 +90,7 @@ const TextField = (props: ITextFieldProps): JSX.Element => {
89
90
  name={name}
90
91
  onChange={handleOnChange}
91
92
  onBlur={handleOnBlur}
93
+ onKeyDown={onKeyDown}
92
94
  placeholder={placeholder}
93
95
  autoComplete={autoComplete}
94
96
  error={error}
@@ -128,6 +130,7 @@ interface ITextFieldProps {
128
130
  onClickIcon?: () => void;
129
131
  className?: string;
130
132
  onBlur?: (value: string) => void;
133
+ onKeyDown?: () => void;
131
134
  disabled?: boolean;
132
135
  iconPosition?: string;
133
136
  prefix?: string;
@@ -0,0 +1,39 @@
1
+ import React from "react";
2
+
3
+ import { IFolder } from "@ax/types";
4
+ import { Icon, Tooltip } from "@ax/components";
5
+ import { trimText } from "@ax/helpers";
6
+
7
+ import * as S from "./style";
8
+
9
+ const FolderItem = (props: IProps) => {
10
+ const { folder, onClick } = props;
11
+ const { id, folderName } = folder;
12
+
13
+ const handleClick = () => onClick(id);
14
+
15
+ const FolderTitle = () =>
16
+ folderName.length > 15 ? (
17
+ <Tooltip content={folderName}>
18
+ <S.Title>{trimText(folderName, 15)}</S.Title>
19
+ </Tooltip>
20
+ ) : (
21
+ <S.Title>{folderName}</S.Title>
22
+ );
23
+
24
+ return (
25
+ <S.Wrapper onClick={handleClick}>
26
+ <S.IconWrapper>
27
+ <Icon name="project" size="24" />
28
+ </S.IconWrapper>
29
+ <FolderTitle />
30
+ </S.Wrapper>
31
+ );
32
+ };
33
+
34
+ interface IProps {
35
+ folder: IFolder;
36
+ onClick(folderID: number): void;
37
+ }
38
+
39
+ export default FolderItem;
@@ -0,0 +1,31 @@
1
+ import styled from "styled-components";
2
+
3
+ const Wrapper = styled.div`
4
+ position: relative;
5
+ background-color: ${(p) => p.theme.color.uiBackground02};
6
+ border: ${(p) => `1px solid ${p.theme.color.uiLine}`};
7
+ border-radius: ${p => p.theme.radii.s};
8
+ display: flex;
9
+ align-items: center;
10
+ min-width: 165px;
11
+ max-width: 180px;
12
+ height: 40px;
13
+ cursor: pointer;
14
+ &:hover {
15
+ background-color: ${(p) => p.theme.color.overlayHoverPrimary};
16
+ }
17
+ `;
18
+
19
+ const IconWrapper = styled.div`
20
+ width: 24px;
21
+ height: 24px;
22
+ margin-left: ${(p) => p.theme.spacing.m};
23
+ `;
24
+
25
+ const Title = styled.div`
26
+ ${(p) => p.theme.textStyle.uiS};
27
+ color: ${(p) => p.theme.colors.textHighEmphasis};
28
+ margin-left: ${(p) => p.theme.spacing.xs};
29
+ `;
30
+
31
+ export { Wrapper, IconWrapper, Title };
@@ -0,0 +1,164 @@
1
+ import React, { memo, useEffect, useState } from "react";
2
+ import { connect } from "react-redux";
3
+ import { IRootState, IFile } from "@ax/types";
4
+ import { Button, FieldsBehavior, IconAction } from "@ax/components";
5
+ import { formatBytes, getFormattedDateWithTimezone } from "@ax/helpers";
6
+ import { fileDriveActions } from "@ax/containers/FileDrive";
7
+ import { getFileIcon } from "../../utils";
8
+
9
+ import * as S from "./style";
10
+
11
+ const GalleryDetailPanel = (props: IProps) => {
12
+ const { selectedFile, isSaving, isAllowedToEdit, setFile, updateFile } = props;
13
+ const { title, alt, tags, fileName, uploadDate, fileType, sizeBytes } = selectedFile || {};
14
+
15
+ const initState: IFormState = { title: title || "", alt: alt || "", tags: tags || [] };
16
+ const [form, setForm] = useState(initState);
17
+
18
+ useEffect(() => {
19
+ setForm(initState);
20
+ }, [selectedFile]);
21
+
22
+ const updateFormField = (field: string, value: string) => setForm((state) => ({ ...state, [field]: value }));
23
+
24
+ const handleTitle = (newValue: string) => updateFormField("title", newValue);
25
+
26
+ const handleAlt = (newValue: string) => updateFormField("alt", newValue);
27
+
28
+ const handleTags = (newValue: string) => updateFormField("tags", newValue);
29
+
30
+ const handleSave = async () =>
31
+ selectedFile && (await updateFile(selectedFile.id, form, selectedFile?.site || "global", false));
32
+
33
+ const handleSaveAndAdd = async () => {
34
+ selectedFile && (await updateFile(selectedFile.id, form, selectedFile?.site || "global", false));
35
+ setFile(form);
36
+ };
37
+
38
+ const handleAdd = () => setFile(form);
39
+
40
+ const handleOpenUrl = () => {
41
+ if (selectedFile) {
42
+ const win = window.open(selectedFile.url, "_blank");
43
+ if (win) {
44
+ win.focus();
45
+ }
46
+ }
47
+ };
48
+
49
+ const handleCopyUrl = () => selectedFile && navigator.clipboard.writeText(selectedFile.url);
50
+
51
+ const iconUrl = fileType ? `/img/icons/${getFileIcon(fileType)}` : "";
52
+
53
+ return (
54
+ <S.DetailPanelWrapper>
55
+ <S.PanelForm>
56
+ <S.InfoWrapper>
57
+ <S.IconWrapper>
58
+ <img src={iconUrl} alt={`${fileType} Icon`} />
59
+ </S.IconWrapper>
60
+ <S.Name>{fileName}</S.Name>
61
+ <S.InfoRow>
62
+ <strong>Uploaded:</strong> {uploadDate && getFormattedDateWithTimezone(uploadDate, "d MMM Y")}
63
+ </S.InfoRow>
64
+ <S.InfoRow>
65
+ <strong>Type:</strong> {fileType}
66
+ </S.InfoRow>
67
+ <S.InfoRow>
68
+ <strong>Size:</strong> {sizeBytes && formatBytes(sizeBytes)}
69
+ </S.InfoRow>
70
+ <S.ButtonsWrapper>
71
+ <Button type="button" onClick={handleCopyUrl} buttonStyle="line">
72
+ Copy URL
73
+ </Button>
74
+ <IconAction icon="OpenOutside" size="m" onClick={handleOpenUrl} />
75
+ </S.ButtonsWrapper>
76
+ </S.InfoWrapper>
77
+ <S.FormWrapper>
78
+ {isAllowedToEdit ? (
79
+ <>
80
+ <FieldsBehavior
81
+ title="Title"
82
+ name="title"
83
+ value={form.title}
84
+ fieldType="TextField"
85
+ onChange={handleTitle}
86
+ />
87
+ <FieldsBehavior
88
+ title="Alternative text"
89
+ name="alt"
90
+ value={form.alt}
91
+ fieldType="TextField"
92
+ onChange={handleAlt}
93
+ />
94
+ </>
95
+ ) : (
96
+ <>
97
+ <S.Label>Title</S.Label>
98
+ <S.FieldText>{form.title}</S.FieldText>
99
+ <S.Label>Alternative text</S.Label>
100
+ <S.FieldText>{form.alt}</S.FieldText>
101
+ </>
102
+ )}
103
+ <FieldsBehavior
104
+ title="Tags"
105
+ value={form.tags}
106
+ fieldType="TagsField"
107
+ onChange={handleTags}
108
+ disabled={!isAllowedToEdit}
109
+ />
110
+ </S.FormWrapper>
111
+ </S.PanelForm>
112
+ <S.PanelActions>
113
+ {isAllowedToEdit ? (
114
+ <>
115
+ <Button type="button" buttonStyle="line" onClick={handleSave} disabled={isSaving}>
116
+ {isSaving ? `Saving` : `Save`}
117
+ </Button>
118
+ <Button type="button" onClick={handleSaveAndAdd} disabled={isSaving}>
119
+ {isSaving ? `Saving` : `Save & Add`}
120
+ </Button>
121
+ </>
122
+ ) : (
123
+ <Button type="button" onClick={handleAdd}>
124
+ Add file
125
+ </Button>
126
+ )}
127
+ </S.PanelActions>
128
+ </S.DetailPanelWrapper>
129
+ );
130
+ };
131
+
132
+ export interface IDetailPanelProps {
133
+ setFile: (fileData: any) => void;
134
+ selectedFile: IFile | null;
135
+ isSaving: boolean;
136
+ isAllowedToEdit: boolean;
137
+ }
138
+
139
+ interface IFormState {
140
+ alt: string;
141
+ title: string;
142
+ tags: string[];
143
+ }
144
+
145
+ const mapStateToProps = (state: IRootState) => ({
146
+ isSaving: state.app.isSaving,
147
+ });
148
+
149
+ export interface IDispatchProps {
150
+ updateFile(
151
+ fileID: number,
152
+ data: { title: string; alt: string; tags: string[] },
153
+ siteID: number | "global",
154
+ loading: boolean
155
+ ): Promise<boolean>;
156
+ }
157
+
158
+ const mapDispatchToProps = {
159
+ updateFile: fileDriveActions.updateFile,
160
+ };
161
+
162
+ type IProps = IDetailPanelProps & IDispatchProps;
163
+
164
+ export default connect(mapStateToProps, mapDispatchToProps)(memo(GalleryDetailPanel));
@@ -0,0 +1,113 @@
1
+ import styled from "styled-components";
2
+
3
+ const DetailPanelWrapper = styled.div`
4
+ position: relative;
5
+ opacity: ${(p) => (p.hidden ? "0" : "1")};
6
+ transition: opacity 0.1s;
7
+ height: 100%;
8
+ width: 100%;
9
+ `;
10
+
11
+ const PanelActions = styled.div`
12
+ position: absolute;
13
+ bottom: 0;
14
+ left: 0;
15
+ right: 0;
16
+ display: flex;
17
+ justify-content: flex-end;
18
+ background-color: ${(p) => p.theme.color.uiBarBackground};
19
+ padding: ${(p) => p.theme.spacing.s} ${(p) => p.theme.spacing.m};
20
+ border-top: 1px solid ${(p) => p.theme.color.uiLine};
21
+ button:not(:first-child) {
22
+ margin-left: ${(p) => p.theme.spacing.s};
23
+ }
24
+ `;
25
+
26
+ const PanelForm = styled.div`
27
+ position: relative;
28
+ width: 100%;
29
+ height: calc(${(p) => p.theme.spacing.xl} * 8);
30
+ overflow: auto;
31
+ `;
32
+
33
+ const InfoRow = styled.div`
34
+ ${(p) => p.theme.textStyle.uiM};
35
+ color: ${(p) => p.theme.color.textMediumEmphasis};
36
+ margin-bottom: ${(p) => p.theme.spacing.xxs};
37
+ `;
38
+
39
+ const InfoWrapper = styled.div`
40
+ padding: ${(p) => `${p.theme.spacing.s} ${p.theme.spacing.s} ${p.theme.spacing.m} ${p.theme.spacing.s}`};
41
+ border-bottom: 1px solid ${(p) => p.theme.color.uiLine};
42
+ strong {
43
+ font-weight: 600;
44
+ }
45
+ `;
46
+
47
+ const ButtonsWrapper = styled.div`
48
+ display: flex;
49
+ margin-top: ${(p) => p.theme.spacing.s};
50
+ align-items: center;
51
+
52
+ button:first-child {
53
+ margin-right: ${(p) => p.theme.spacing.xs};
54
+ }
55
+ `;
56
+
57
+ const Name = styled.div`
58
+ ${(p) => p.theme.textStyle.uiL};
59
+ color: ${(p) => p.theme.color.textHighEmphasis};
60
+ margin-bottom: ${(p) => p.theme.spacing.xxs};
61
+ overflow-wrap: break-word;
62
+ `;
63
+
64
+ const FormWrapper = styled.div`
65
+ padding: ${(p) => `${p.theme.spacing.s} ${p.theme.spacing.s} 0 ${p.theme.spacing.s}`};
66
+ `;
67
+
68
+ const Url = styled.div`
69
+ display: flex;
70
+ ${(p) => p.theme.textStyle.fieldContent};
71
+ color: ${(p) => p.theme.color.textMediumEmphasis};
72
+ background-color: ${(p) => p.theme.color.uiBackground03};
73
+ border-radius: 4px;
74
+ width: 100%;
75
+ height: ${(p) => p.theme.spacing.l};
76
+ padding: 0 ${(p) => p.theme.spacing.s};
77
+ margin-bottom: ${(p) => p.theme.spacing.m};
78
+ overflow: hidden;
79
+ white-space: nowrap;
80
+ `;
81
+
82
+ const IconWrapper = styled.div`
83
+ width: 42px;
84
+ height: 40px;
85
+ margin-bottom: ${(p) => p.theme.spacing.xs};
86
+ `;
87
+
88
+ const Label = styled.div`
89
+ ${(p) => p.theme.textStyle.fieldLabel};
90
+ color: ${(p) => p.theme.colors.textMediumEmphasis};
91
+ margin-bottom: ${(p) => p.theme.spacing.xxs};
92
+ `;
93
+
94
+ const FieldText = styled.div`
95
+ ${(p) => p.theme.textStyle.uiM};
96
+ color: ${(p) => p.theme.colors.textHighEmphasis};
97
+ margin-bottom: ${(p) => p.theme.spacing.s};
98
+ `;
99
+
100
+ export {
101
+ DetailPanelWrapper,
102
+ PanelActions,
103
+ PanelForm,
104
+ InfoRow,
105
+ InfoWrapper,
106
+ ButtonsWrapper,
107
+ Name,
108
+ FormWrapper,
109
+ Url,
110
+ IconWrapper,
111
+ Label,
112
+ FieldText,
113
+ };
@@ -0,0 +1,42 @@
1
+ import React, { memo } from "react";
2
+
3
+ import { IFile } from "@ax/types";
4
+
5
+ import DetailPanel from "./DetailPanel";
6
+ import FileDragAndDrop from "@ax/modules/FileDrive/FileDragAndDrop";
7
+
8
+ import * as S from "./style";
9
+
10
+ const GalleryPanel = (props: IGalleryPanelProps) => {
11
+ const { selectedFile, validFormats, setFile, scope, currentFolderID, isAllowedToAdd, isAllowedToEdit, handleUpload } =
12
+ props;
13
+
14
+ return (
15
+ <S.GalleryPanel>
16
+ {!selectedFile ? (
17
+ <FileDragAndDrop
18
+ validFormats={validFormats}
19
+ folderID={currentFolderID}
20
+ handleUpload={handleUpload}
21
+ siteID={scope}
22
+ isAllowedToUpload={isAllowedToAdd}
23
+ />
24
+ ) : (
25
+ <DetailPanel selectedFile={selectedFile} setFile={setFile} isAllowedToEdit={isAllowedToEdit} />
26
+ )}
27
+ </S.GalleryPanel>
28
+ );
29
+ };
30
+
31
+ export interface IGalleryPanelProps {
32
+ selectedFile: IFile | null;
33
+ validFormats: string[];
34
+ setFile: (fileData: any) => void;
35
+ scope: number | "global";
36
+ currentFolderID: number | null;
37
+ handleUpload: (file: IFile[]) => void;
38
+ isAllowedToEdit: boolean;
39
+ isAllowedToAdd: boolean;
40
+ }
41
+
42
+ export default memo(GalleryPanel);
@@ -0,0 +1,7 @@
1
+ import styled from "styled-components";
2
+
3
+ export const GalleryPanel = styled.div`
4
+ background-color: ${p => p.theme.color.uiBarBackground};
5
+ width: ${p => `calc(${p.theme.spacing.xl} * 5)`};
6
+ flex-shrink: 0;
7
+ `;
@@ -0,0 +1,47 @@
1
+ import React from "react";
2
+ import { IFile } from "@ax/types";
3
+ import { getFormattedDateWithTimezone, trimText } from "@ax/helpers";
4
+ import { Tooltip } from "@ax/components";
5
+ import { getFileIcon } from "../utils";
6
+
7
+ import * as S from "./style";
8
+
9
+ const GridItem = (props: IProps) => {
10
+ const { file, onClick, isSelected } = props;
11
+ const { fileName, fileType, uploadDate } = file;
12
+
13
+ const handleClick = () => onClick(file);
14
+
15
+ const iconUrl = `/img/icons/${getFileIcon(fileType)}`;
16
+
17
+ const FileTitle = () =>
18
+ fileName.length > 30 ? (
19
+ <Tooltip content={fileName}>
20
+ <S.Name>{trimText(fileName, 30)}</S.Name>
21
+ </Tooltip>
22
+ ) : (
23
+ <S.Name>{fileName}</S.Name>
24
+ );
25
+
26
+ return (
27
+ <S.Wrapper onClick={handleClick} isSelected={isSelected}>
28
+ <S.Header>
29
+ <S.IconWrapper>
30
+ <img src={iconUrl} alt={`${fileType} Icon`} />
31
+ </S.IconWrapper>
32
+ </S.Header>
33
+ <FileTitle />
34
+ <S.Info>
35
+ <S.Tag>{getFormattedDateWithTimezone(uploadDate, "d MMM Y")}</S.Tag>
36
+ </S.Info>
37
+ </S.Wrapper>
38
+ );
39
+ };
40
+
41
+ interface IProps {
42
+ file: IFile;
43
+ onClick(file: IFile): void;
44
+ isSelected: boolean;
45
+ }
46
+
47
+ export default GridItem;
@@ -0,0 +1,51 @@
1
+ import styled from "styled-components";
2
+
3
+ const Wrapper = styled.div<{ isSelected: boolean }>`
4
+ position: relative;
5
+ background-color: ${(p) => p.theme.color.uiBackground02};
6
+ border: ${(p) => p.isSelected ? `2px solid ${p.theme.color.interactive01}` : `1px solid ${p.theme.color.uiLine}`};
7
+ border-radius: ${p => p.theme.radii.s};
8
+ display: flex;
9
+ flex-direction: column;
10
+ padding: ${(p) => p.theme.spacing.s};
11
+ min-width: 165px;
12
+ max-width: 170px;
13
+ height: 144px;
14
+ cursor: pointer;
15
+ &:hover {
16
+ background-color: ${(p) => p.theme.color.overlayHoverPrimary};
17
+ }
18
+ `;
19
+
20
+ const Header = styled.div`
21
+ display: flex;
22
+ margin-bottom: ${(p) => p.theme.spacing.xs};
23
+ `;
24
+
25
+ const IconWrapper = styled.div`
26
+ width: 42px;
27
+ height: 40px;
28
+ `;
29
+
30
+ const Name = styled.div`
31
+ ${(p) => p.theme.textStyle.uiS};
32
+ color: ${(p) => p.theme.colors.textHighEmphasis};
33
+ margin-bottom: ${(p) => p.theme.spacing.xxs};
34
+ word-break: break-word;
35
+ `;
36
+
37
+ const Info = styled.div`
38
+ display: flex;
39
+ margin-top: auto;
40
+ `;
41
+
42
+ const Tag = styled.div`
43
+ ${(p) => p.theme.textStyle.uiXS};
44
+ border: ${(p) => `1px solid ${p.theme.color.uiLine}`};
45
+ border-radius: 20px;
46
+ color: ${(p) => p.theme.colors.textMediumEmphasis};
47
+ padding: 2px 8px;
48
+ margin-right: ${(p) => p.theme.spacing.xxs};
49
+ `;
50
+
51
+ export { Wrapper, Header, Name, Info, IconWrapper, Tag };