@griddo/ax 1.55.14 → 1.56.2
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
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@griddo/ax",
|
|
3
3
|
"description": "Griddo Author Experience",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.56.2",
|
|
5
5
|
"authors": [
|
|
6
6
|
"Álvaro Sánchez' <alvaro.sanches@secuoyas.com>",
|
|
7
7
|
"Carlos Torres <carlos.torres@secuoyas.com>",
|
|
@@ -233,5 +233,5 @@
|
|
|
233
233
|
"publishConfig": {
|
|
234
234
|
"access": "public"
|
|
235
235
|
},
|
|
236
|
-
"gitHead": "
|
|
236
|
+
"gitHead": "76dddc292b1037223a780b2093399c3c6e12ce02"
|
|
237
237
|
}
|
package/src/GlobalStore.tsx
CHANGED
|
@@ -16,6 +16,7 @@ import { languagesReducer, languagesInitialState } from "./containers/Settings/L
|
|
|
16
16
|
import { dataPacksReducer, dataPacksInitialState } from "./containers/Settings/DataPacks/reducer";
|
|
17
17
|
import { socialReducer, socialInitialState } from "./containers/Settings/Social/reducer";
|
|
18
18
|
import { usersReducer, usersInitialState } from "./containers/Users/reducer";
|
|
19
|
+
import { galleryReducer, galleryInitialState } from "./containers/Gallery/reducer";
|
|
19
20
|
|
|
20
21
|
import { IRootState } from "@ax/types";
|
|
21
22
|
|
|
@@ -44,6 +45,7 @@ export class GlobalStore {
|
|
|
44
45
|
dataPacks: dataPacksReducer as Reducer<any, Action<any>>,
|
|
45
46
|
social: socialReducer as Reducer<any, Action<any>>,
|
|
46
47
|
users: usersReducer as Reducer<any, Action<any>>,
|
|
48
|
+
gallery: galleryReducer as Reducer<any, Action<any>>,
|
|
47
49
|
});
|
|
48
50
|
|
|
49
51
|
const rootReducer = (state: IRootState | undefined, action: any) => {
|
|
@@ -60,6 +62,7 @@ export class GlobalStore {
|
|
|
60
62
|
dataPacks: dataPacksInitialState,
|
|
61
63
|
social: socialInitialState,
|
|
62
64
|
users: usersInitialState,
|
|
65
|
+
gallery: galleryInitialState,
|
|
63
66
|
};
|
|
64
67
|
}
|
|
65
68
|
|
|
@@ -111,6 +111,12 @@ const PageConnectedField = (props: any) => {
|
|
|
111
111
|
updateEditorContent(selectedEditorID, "metaTitle", value);
|
|
112
112
|
}
|
|
113
113
|
}
|
|
114
|
+
|
|
115
|
+
const isComponentImage = ["LinkableImage", "Image"].includes(selectedContent.component) && key === "file";
|
|
116
|
+
if (isComponentImage) {
|
|
117
|
+
updateEditorContent(selectedEditorID, "title", value.title);
|
|
118
|
+
updateEditorContent(selectedEditorID, "alt", value.alt);
|
|
119
|
+
}
|
|
114
120
|
};
|
|
115
121
|
|
|
116
122
|
if (isOverride) {
|
|
@@ -7,8 +7,21 @@ import * as S from "./style";
|
|
|
7
7
|
const ArrayFieldInline = (props: IProps): JSX.Element => {
|
|
8
8
|
const { fields, item, index, onChange, handleDelete } = props;
|
|
9
9
|
|
|
10
|
-
const deleteItem = () =>
|
|
11
|
-
|
|
10
|
+
const deleteItem = () => handleDelete(index);
|
|
11
|
+
|
|
12
|
+
const getFields = (fields: any[]): any[] => {
|
|
13
|
+
return fields.map((field: any) => {
|
|
14
|
+
const key = field.props.objKey;
|
|
15
|
+
const handleChange = (newValue: any) => onChange({ [key]: newValue });
|
|
16
|
+
|
|
17
|
+
const innerFields = field.props.innerFields ? getFields(field.props.innerFields) : undefined;
|
|
18
|
+
|
|
19
|
+
return {
|
|
20
|
+
...field,
|
|
21
|
+
props: { ...field.props, value: item[key], objKey: key, onChange: handleChange, innerFields },
|
|
22
|
+
key,
|
|
23
|
+
};
|
|
24
|
+
});
|
|
12
25
|
};
|
|
13
26
|
|
|
14
27
|
return (
|
|
@@ -17,16 +30,7 @@ const ArrayFieldInline = (props: IProps): JSX.Element => {
|
|
|
17
30
|
<S.IconWrapper>
|
|
18
31
|
<IconAction icon="delete" onClick={deleteItem} size="s" />
|
|
19
32
|
</S.IconWrapper>
|
|
20
|
-
{fields
|
|
21
|
-
const key = field.props.objKey;
|
|
22
|
-
const handleChange = (newValue: any) => onChange({ [key]: newValue });
|
|
23
|
-
|
|
24
|
-
return {
|
|
25
|
-
...field,
|
|
26
|
-
props: { ...field.props, value: item[key], objKey: key, onChange: handleChange },
|
|
27
|
-
key,
|
|
28
|
-
};
|
|
29
|
-
})}
|
|
33
|
+
{getFields(fields)}
|
|
30
34
|
</S.Content>
|
|
31
35
|
</S.Wrapper>
|
|
32
36
|
);
|
|
@@ -9,9 +9,7 @@ const ArrayFieldItem = (props: IProps): JSX.Element => {
|
|
|
9
9
|
|
|
10
10
|
const handleClick = () => setIsOpen(!isOpen);
|
|
11
11
|
|
|
12
|
-
const deleteItem = () =>
|
|
13
|
-
handleDelete(index);
|
|
14
|
-
};
|
|
12
|
+
const deleteItem = () => handleDelete(index);
|
|
15
13
|
|
|
16
14
|
const menuOptions = [
|
|
17
15
|
{
|
|
@@ -21,24 +19,28 @@ const ArrayFieldItem = (props: IProps): JSX.Element => {
|
|
|
21
19
|
},
|
|
22
20
|
];
|
|
23
21
|
|
|
22
|
+
const getFields = (fields: any[]): any[] => {
|
|
23
|
+
return fields.map((field: any) => {
|
|
24
|
+
const key = field.props.objKey;
|
|
25
|
+
const handleChange = (newValue: any) => onChange({ [key]: newValue });
|
|
26
|
+
|
|
27
|
+
const innerFields = field.props.innerFields ? getFields(field.props.innerFields) : undefined;
|
|
28
|
+
|
|
29
|
+
return {
|
|
30
|
+
...field,
|
|
31
|
+
props: { ...field.props, value: item[key], objKey: key, onChange: handleChange, innerFields },
|
|
32
|
+
key,
|
|
33
|
+
};
|
|
34
|
+
});
|
|
35
|
+
};
|
|
36
|
+
|
|
24
37
|
return (
|
|
25
38
|
<S.Wrapper isOpen={isOpen}>
|
|
26
39
|
<S.Title onClick={handleClick} isOpen={isOpen}>
|
|
27
40
|
{`${name} ${index + 1}`}
|
|
28
41
|
<S.StyledActionMenu icon="more" options={menuOptions} />
|
|
29
42
|
</S.Title>
|
|
30
|
-
<S.Content isOpen={isOpen}>
|
|
31
|
-
{fields.map((field: any) => {
|
|
32
|
-
const key = field.props.objKey;
|
|
33
|
-
const handleChange = (newValue: any) => onChange({ [key]: newValue });
|
|
34
|
-
|
|
35
|
-
return {
|
|
36
|
-
...field,
|
|
37
|
-
props: { ...field.props, value: item[key], objKey: key, onChange: handleChange },
|
|
38
|
-
key,
|
|
39
|
-
};
|
|
40
|
-
})}
|
|
41
|
-
</S.Content>
|
|
43
|
+
<S.Content isOpen={isOpen}>{getFields(fields)}</S.Content>
|
|
42
44
|
</S.Wrapper>
|
|
43
45
|
);
|
|
44
46
|
};
|
|
@@ -6,9 +6,7 @@ import * as S from "./style";
|
|
|
6
6
|
const ConditionalField = (props: IConditionalFieldProps) => {
|
|
7
7
|
const { value, options, innerFields, onChange } = props;
|
|
8
8
|
|
|
9
|
-
const handleChange = (newValue: any) =>
|
|
10
|
-
onChange(newValue);
|
|
11
|
-
};
|
|
9
|
+
const handleChange = (newValue: any) => onChange(newValue);
|
|
12
10
|
|
|
13
11
|
return (
|
|
14
12
|
<S.Wrapper>
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
+
import { connect } from "react-redux";
|
|
2
3
|
import FroalaEditor from "react-froala-wysiwyg";
|
|
3
4
|
import { decodeEntities } from "@ax/helpers";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
5
|
+
import { IImage, ISite } from "@ax/types";
|
|
6
|
+
import { galleryActions } from "@ax/containers/Gallery";
|
|
6
7
|
|
|
7
8
|
import { wysiwygConfig, buttons, buttonsFull } from "./config";
|
|
8
9
|
import "./vendors";
|
|
9
10
|
import * as S from "./style";
|
|
10
11
|
|
|
11
|
-
const Wysiwyg = (props:
|
|
12
|
-
const { value, error, onChange, placeholder, full = true, disabled, handleValidation, site } = props;
|
|
12
|
+
const Wysiwyg = (props: IProps): JSX.Element => {
|
|
13
|
+
const { value, error, onChange, placeholder, full = true, disabled, handleValidation, site, uploadImage } = props;
|
|
13
14
|
|
|
14
15
|
const imageSite = site ? site.id : "global"
|
|
15
16
|
|
|
@@ -71,4 +72,14 @@ interface IWysiwygProps {
|
|
|
71
72
|
site: ISite;
|
|
72
73
|
}
|
|
73
74
|
|
|
74
|
-
|
|
75
|
+
interface IDispatchProps {
|
|
76
|
+
uploadImage: (imageFile: File, site: number | string) => Promise<IImage>;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const mapDispatchToProps = {
|
|
80
|
+
uploadImage: galleryActions.uploadImage,
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
type IProps = IWysiwygProps & IDispatchProps;
|
|
84
|
+
|
|
85
|
+
export default connect(null, mapDispatchToProps)(Wysiwyg);
|
|
@@ -1,114 +1,106 @@
|
|
|
1
|
-
import React, { memo,
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import React, { memo, useEffect, useState } from "react";
|
|
2
|
+
import { connect } from "react-redux";
|
|
3
|
+
import { IImage, IRootState, IImageForm } from "@ax/types";
|
|
4
|
+
import { Button, CheckField, FieldsBehavior, Toast } from "@ax/components";
|
|
4
5
|
import { formatBytes, getFormattedDateWithTimezone } from "@ax/helpers";
|
|
5
|
-
import {
|
|
6
|
-
reducer,
|
|
7
|
-
initialState,
|
|
8
|
-
setInitForm,
|
|
9
|
-
setFormField,
|
|
10
|
-
saveImageData,
|
|
11
|
-
deleteImageData,
|
|
12
|
-
uploadImage,
|
|
13
|
-
} from "../../store";
|
|
14
6
|
|
|
7
|
+
import { galleryActions } from "@ax/containers/Gallery";
|
|
8
|
+
import { IIsSaving } from "@ax/containers/Gallery/reducer";
|
|
15
9
|
import * as S from "./style";
|
|
16
10
|
|
|
17
11
|
const GalleryDetailPanel = (props: IProps) => {
|
|
18
|
-
const {
|
|
12
|
+
const {
|
|
13
|
+
imageSelected,
|
|
14
|
+
isImageSelected,
|
|
15
|
+
deleteImage,
|
|
16
|
+
isGlobalTab,
|
|
17
|
+
updateImage,
|
|
18
|
+
refreshImages,
|
|
19
|
+
isSaving,
|
|
20
|
+
setImage,
|
|
21
|
+
uploadImage,
|
|
22
|
+
} = props;
|
|
23
|
+
|
|
24
|
+
const initialState: IImageForm = {
|
|
25
|
+
id: undefined,
|
|
26
|
+
alt: "",
|
|
27
|
+
title: "",
|
|
28
|
+
description: "",
|
|
29
|
+
tags: [],
|
|
30
|
+
};
|
|
19
31
|
|
|
20
|
-
const [
|
|
21
|
-
const [isSaving, setIsSaving] = useState({ save: false, saveAdd: false, delete: false });
|
|
32
|
+
const [imageForm, setImageForm] = useState(initialState);
|
|
22
33
|
const [addToGlobal, setAddToGlobal] = useState({ value: "addToGlobal", isChecked: false });
|
|
34
|
+
const [deletedToast, setDeletedToast] = useState(false);
|
|
35
|
+
|
|
36
|
+
const setInitForm = (imageSelected: IImage) => {
|
|
37
|
+
const form = {
|
|
38
|
+
id: imageSelected.id,
|
|
39
|
+
title: imageSelected.title ? imageSelected.title : "",
|
|
40
|
+
alt: imageSelected.alt ? imageSelected.alt : "",
|
|
41
|
+
description: imageSelected.description ? imageSelected.description : "",
|
|
42
|
+
tags: imageSelected.tags ? imageSelected.tags : [],
|
|
43
|
+
};
|
|
44
|
+
setImageForm(form);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const updateFormField = (field: string, value: string) => setImageForm((state) => ({ ...state, [field]: value }));
|
|
23
48
|
|
|
24
49
|
useEffect(() => {
|
|
25
|
-
if (imageSelected && imageSelected.id !==
|
|
26
|
-
|
|
27
|
-
setInitForm({
|
|
28
|
-
id: imageSelected.id,
|
|
29
|
-
title: imageSelected.title,
|
|
30
|
-
alt: imageSelected.alt,
|
|
31
|
-
description: imageSelected.description,
|
|
32
|
-
tags: imageSelected.tags,
|
|
33
|
-
})
|
|
34
|
-
);
|
|
50
|
+
if (imageSelected && imageSelected.id !== imageForm.id) {
|
|
51
|
+
setInitForm(imageSelected);
|
|
35
52
|
}
|
|
36
53
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
37
54
|
}, [imageSelected]);
|
|
38
55
|
|
|
39
|
-
const
|
|
40
|
-
|
|
56
|
+
const handleTitle = (newValue: string) => {
|
|
57
|
+
updateFormField("title", newValue);
|
|
41
58
|
};
|
|
42
59
|
|
|
43
|
-
const
|
|
44
|
-
|
|
60
|
+
const handleAlt = (newValue: string) => {
|
|
61
|
+
updateFormField("alt", newValue);
|
|
45
62
|
};
|
|
46
63
|
|
|
47
|
-
const
|
|
48
|
-
|
|
64
|
+
const handleDescription = (newValue: string) => {
|
|
65
|
+
updateFormField("description", newValue);
|
|
49
66
|
};
|
|
50
67
|
|
|
51
|
-
const
|
|
52
|
-
|
|
68
|
+
const handleTags = (newValue: string) => {
|
|
69
|
+
updateFormField("tags", newValue);
|
|
53
70
|
};
|
|
54
71
|
|
|
55
72
|
const handleSetAsGlobal = async () => {
|
|
56
73
|
const saveAsGlobal = !isGlobalTab && addToGlobal.isChecked && imageSelected?.file;
|
|
57
|
-
const image = saveAsGlobal && imageSelected && await uploadImage(imageSelected.file, "global");
|
|
58
|
-
if (image) await
|
|
74
|
+
const image = saveAsGlobal && imageSelected && (await uploadImage(imageSelected.file, "global"));
|
|
75
|
+
if (image && image.id) await updateImage(image.id, imageForm);
|
|
59
76
|
setAddToGlobal({ value: "addToGlobal", isChecked: false });
|
|
60
77
|
};
|
|
61
78
|
|
|
62
|
-
const
|
|
63
|
-
if (
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const value = await saveImageData(state.imageForm.id, state.imageForm);
|
|
68
|
-
if (value) {
|
|
69
|
-
updateImage(value);
|
|
70
|
-
}
|
|
71
|
-
setIsSaving({ ...isSaving, saveAdd: false });
|
|
72
|
-
setImage();
|
|
73
|
-
} catch (error) {
|
|
74
|
-
console.log(error);
|
|
75
|
-
}
|
|
79
|
+
const handleSave = async () => {
|
|
80
|
+
if (imageForm.id) {
|
|
81
|
+
await updateImage(imageForm.id, imageForm);
|
|
82
|
+
await handleSetAsGlobal();
|
|
83
|
+
refreshImages();
|
|
76
84
|
}
|
|
77
85
|
};
|
|
78
86
|
|
|
79
|
-
const
|
|
80
|
-
if (
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
const value = await saveImageData(state.imageForm.id, state.imageForm);
|
|
85
|
-
if (value) {
|
|
86
|
-
updateImage(value);
|
|
87
|
-
}
|
|
88
|
-
setIsSaving({ ...isSaving, save: false });
|
|
89
|
-
} catch (error) {
|
|
90
|
-
console.log(error);
|
|
91
|
-
}
|
|
87
|
+
const handleSaveAndAdd = async () => {
|
|
88
|
+
if (imageForm.id) {
|
|
89
|
+
await updateImage(imageForm.id, imageForm, true);
|
|
90
|
+
handleSetAsGlobal();
|
|
91
|
+
setImage(imageForm);
|
|
92
92
|
}
|
|
93
93
|
};
|
|
94
94
|
|
|
95
|
-
const
|
|
96
|
-
if (
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
if (value && state.imageForm.id) {
|
|
101
|
-
deleteImage(state.imageForm.id);
|
|
102
|
-
}
|
|
103
|
-
setIsSaving({ ...isSaving, delete: false });
|
|
104
|
-
})
|
|
105
|
-
.catch((error) => {
|
|
106
|
-
console.log(error);
|
|
107
|
-
});
|
|
95
|
+
const handleDelete = async () => {
|
|
96
|
+
if (imageForm.id) {
|
|
97
|
+
const deleted = await deleteImage(imageForm.id);
|
|
98
|
+
if (deleted) setDeletedToast(true);
|
|
99
|
+
refreshImages();
|
|
108
100
|
}
|
|
109
101
|
};
|
|
110
102
|
|
|
111
|
-
const
|
|
103
|
+
const handleOnClickUrl = () => {
|
|
112
104
|
if (imageSelected) {
|
|
113
105
|
const win = window.open(imageSelected.url, "_blank");
|
|
114
106
|
if (win) {
|
|
@@ -137,14 +129,14 @@ const GalleryDetailPanel = (props: IProps) => {
|
|
|
137
129
|
|
|
138
130
|
const canSetAsGlobal = !isGlobalTab && imageSelected?.file;
|
|
139
131
|
|
|
140
|
-
const
|
|
132
|
+
const renderImageForm = !imageSelected ? null : (
|
|
141
133
|
<S.PanelForm>
|
|
142
134
|
{canSetAsGlobal && <AddToGlobal />}
|
|
143
135
|
<S.DateWrapper>Uploaded: {getFormattedDateWithTimezone(imageSelected.published, "d MMM Y")}</S.DateWrapper>
|
|
144
136
|
<S.ImageName>{imageSelected.name}</S.ImageName>
|
|
145
137
|
<S.ImageInfoWrapper>
|
|
146
138
|
<S.ImageWrapper>
|
|
147
|
-
<img src={imageSelected.url} alt={
|
|
139
|
+
<img src={imageSelected.url} alt={imageForm.alt} />
|
|
148
140
|
</S.ImageWrapper>
|
|
149
141
|
<S.ImageData>
|
|
150
142
|
<S.ImageSize>{formatBytes(imageSelected.size)}</S.ImageSize>
|
|
@@ -159,42 +151,42 @@ const GalleryDetailPanel = (props: IProps) => {
|
|
|
159
151
|
fieldType="TextField"
|
|
160
152
|
readonly={true}
|
|
161
153
|
icon="openOutside"
|
|
162
|
-
onClickIcon={
|
|
154
|
+
onClickIcon={handleOnClickUrl}
|
|
163
155
|
/>
|
|
164
156
|
<FieldsBehavior
|
|
165
|
-
title="
|
|
166
|
-
name="
|
|
167
|
-
value={
|
|
157
|
+
title="Title"
|
|
158
|
+
name="title"
|
|
159
|
+
value={imageForm.title}
|
|
168
160
|
fieldType="TextField"
|
|
169
|
-
onChange={
|
|
161
|
+
onChange={handleTitle}
|
|
170
162
|
/>
|
|
171
163
|
<FieldsBehavior
|
|
172
|
-
title="
|
|
173
|
-
name="
|
|
174
|
-
value={
|
|
164
|
+
title="Alternative text"
|
|
165
|
+
name="alt"
|
|
166
|
+
value={imageForm.alt}
|
|
175
167
|
fieldType="TextField"
|
|
176
|
-
onChange={
|
|
168
|
+
onChange={handleAlt}
|
|
177
169
|
/>
|
|
178
170
|
<FieldsBehavior
|
|
179
171
|
title="Description"
|
|
180
172
|
name="description"
|
|
181
|
-
value={
|
|
173
|
+
value={imageForm.description}
|
|
182
174
|
fieldType="TextArea"
|
|
183
|
-
onChange={
|
|
175
|
+
onChange={handleDescription}
|
|
184
176
|
/>
|
|
185
|
-
<FieldsBehavior title="Tags" value={
|
|
177
|
+
<FieldsBehavior title="Tags" value={imageForm.tags} fieldType="TagField" onChange={handleTags} />
|
|
186
178
|
</S.FormWrapper>
|
|
187
179
|
</S.PanelForm>
|
|
188
180
|
);
|
|
189
181
|
|
|
190
182
|
return (
|
|
191
183
|
<S.DetailPanelWrapper hidden={!isImageSelected}>
|
|
192
|
-
{
|
|
184
|
+
{renderImageForm}
|
|
193
185
|
<S.PanelActions>
|
|
194
186
|
<Button
|
|
195
187
|
type="button"
|
|
196
188
|
buttonStyle="text"
|
|
197
|
-
onClick={
|
|
189
|
+
onClick={handleDelete}
|
|
198
190
|
disabled={isSaving.save || isSaving.saveAdd || isSaving.delete}
|
|
199
191
|
>
|
|
200
192
|
{isSaving.delete ? `Deleting` : `Delete`}
|
|
@@ -202,30 +194,49 @@ const GalleryDetailPanel = (props: IProps) => {
|
|
|
202
194
|
<Button
|
|
203
195
|
type="button"
|
|
204
196
|
buttonStyle="line"
|
|
205
|
-
onClick={
|
|
197
|
+
onClick={handleSave}
|
|
206
198
|
disabled={isSaving.save || isSaving.saveAdd || isSaving.delete}
|
|
207
199
|
>
|
|
208
200
|
{isSaving.save ? `Saving` : `Save`}
|
|
209
201
|
</Button>
|
|
210
202
|
<Button
|
|
211
203
|
type="button"
|
|
212
|
-
onClick={
|
|
204
|
+
onClick={handleSaveAndAdd}
|
|
213
205
|
disabled={isSaving.save || isSaving.saveAdd || isSaving.delete}
|
|
214
206
|
>
|
|
215
207
|
{isSaving.saveAdd ? `Saving` : `Save & Add`}
|
|
216
208
|
</Button>
|
|
217
209
|
</S.PanelActions>
|
|
210
|
+
{deletedToast && <Toast message="1 image deleted" setIsVisible={setDeletedToast} />}
|
|
218
211
|
</S.DetailPanelWrapper>
|
|
219
212
|
);
|
|
220
213
|
};
|
|
221
214
|
|
|
222
|
-
interface
|
|
223
|
-
setImage: () => void;
|
|
224
|
-
updateImage: (image: IImage) => void;
|
|
225
|
-
deleteImage: (imageID: number) => void;
|
|
215
|
+
interface IDetailPanelProps {
|
|
216
|
+
setImage: (imageData: any) => void;
|
|
226
217
|
imageSelected: IImage | null;
|
|
227
218
|
isImageSelected: boolean;
|
|
228
219
|
isGlobalTab: boolean;
|
|
220
|
+
refreshImages: () => void;
|
|
221
|
+
isSaving: IIsSaving;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const mapStateToProps = (state: IRootState) => ({
|
|
225
|
+
isSaving: state.gallery.isSaving,
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
interface IDispatchProps {
|
|
229
|
+
updateImage: (imageID: number, imageData: IImageForm, add?: boolean) => Promise<void>;
|
|
230
|
+
deleteImage: (imageID: number) => Promise<boolean>;
|
|
231
|
+
uploadImage: (imageFile: File, site: number | string) => Promise<IImage>;
|
|
229
232
|
}
|
|
230
233
|
|
|
231
|
-
|
|
234
|
+
const mapDispatchToProps = {
|
|
235
|
+
updateImage: galleryActions.updateImage,
|
|
236
|
+
deleteImage: galleryActions.deleteImage,
|
|
237
|
+
uploadImage: galleryActions.uploadImage,
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
type IProps = IDetailPanelProps & IDispatchProps;
|
|
241
|
+
|
|
242
|
+
export default connect(mapStateToProps, mapDispatchToProps)(memo(GalleryDetailPanel));
|