@retikolo/drag-drop-content-types-strapi 2.0.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.
- package/README.md +77 -0
- package/dist/_chunks/Settings-BUJ6OWyE.js +3632 -0
- package/dist/_chunks/Settings-Cx22s5Bk.mjs +3615 -0
- package/dist/_chunks/en-I3-CH3Sy.js +31 -0
- package/dist/_chunks/en-bxpER_P-.mjs +31 -0
- package/dist/_chunks/fr-C8Qw4iPZ.js +4 -0
- package/dist/_chunks/fr-hkSxFuzl.mjs +4 -0
- package/dist/_chunks/index-CxWC49Ye.mjs +477 -0
- package/dist/_chunks/index-D5Ne-GrP.js +478 -0
- package/dist/admin/index.js +3 -0
- package/dist/admin/index.mjs +4 -0
- package/dist/admin/src/components/Initializer.d.ts +5 -0
- package/dist/admin/src/components/PluginIcon.d.ts +2 -0
- package/dist/admin/src/components/SettingsTextField.d.ts +14 -0
- package/dist/admin/src/components/SettingsToggleField.d.ts +13 -0
- package/dist/admin/src/components/SortModal/CustomItem.d.ts +12 -0
- package/dist/admin/src/components/SortModal/SortMenu.d.ts +3 -0
- package/dist/admin/src/components/SortModal/SortableList.d.ts +3 -0
- package/dist/admin/src/components/SortModal/SortableListItem.d.ts +7 -0
- package/dist/admin/src/components/SortModal/index.d.ts +2 -0
- package/dist/admin/src/components/SortModal/utils.d.ts +2 -0
- package/dist/admin/src/components/TooltipIconButton.d.ts +11 -0
- package/dist/admin/src/index.d.ts +13 -0
- package/dist/admin/src/pages/App.d.ts +2 -0
- package/dist/admin/src/pages/HomePage.d.ts +2 -0
- package/dist/admin/src/pages/Settings.d.ts +2 -0
- package/dist/admin/src/permissions.d.ts +7 -0
- package/dist/admin/src/pluginId.d.ts +1 -0
- package/dist/admin/src/utils/getTranslation.d.ts +2 -0
- package/dist/admin/src/utils/strapi.d.ts +13 -0
- package/dist/admin/src/utils/useQueryParams.d.ts +7 -0
- package/dist/server/index.js +266 -0
- package/dist/server/index.mjs +267 -0
- package/dist/server/src/bootstrap.d.ts +5 -0
- package/dist/server/src/config/index.d.ts +5 -0
- package/dist/server/src/content-types/index.d.ts +2 -0
- package/dist/server/src/controllers/dragdrop.d.ts +9 -0
- package/dist/server/src/controllers/index.d.ts +16 -0
- package/dist/server/src/controllers/settings.d.ts +8 -0
- package/dist/server/src/destroy.d.ts +5 -0
- package/dist/server/src/index.d.ts +79 -0
- package/dist/server/src/middlewares/index.d.ts +2 -0
- package/dist/server/src/policies/index.d.ts +2 -0
- package/dist/server/src/register.d.ts +5 -0
- package/dist/server/src/routes/dragdrop.d.ts +13 -0
- package/dist/server/src/routes/index.d.ts +26 -0
- package/dist/server/src/routes/settings.d.ts +12 -0
- package/dist/server/src/services/dragdrop.d.ts +21 -0
- package/dist/server/src/services/index.d.ts +21 -0
- package/dist/server/src/services/settings.d.ts +8 -0
- package/package.json +98 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const en = {
|
|
4
|
+
"plugin.name": "Drag Drop Content Type",
|
|
5
|
+
"plugin.configuration": "Configuration",
|
|
6
|
+
"plugin.settings.errors.required": "Required field",
|
|
7
|
+
"plugin.settings.buttons.save": "Save",
|
|
8
|
+
"plugin.settings.buttons.off": "Off",
|
|
9
|
+
"plugin.settings.buttons.on": "On",
|
|
10
|
+
"plugin.settings.title": "Drag Drop Content Type Config",
|
|
11
|
+
"plugin.settings.subtitle": "Manage field values for drag-droppable entries",
|
|
12
|
+
"plugin.settings.updated": "Settings successfully updated",
|
|
13
|
+
"plugin.settings.field-names": "Field Names",
|
|
14
|
+
"plugin.settings.triggerWebhooks.label": "Trigger Webhooks",
|
|
15
|
+
"plugin.settings.triggerWebhooks.hint": "If enabled, the 'entry.update' webhook will be triggered when entries are reordered",
|
|
16
|
+
"plugin.settings.triggerWebhooks.tooltip": "Enable to trigger webhooks when entries are reordered",
|
|
17
|
+
"plugin.settings.rank.label": "Rank Field Name",
|
|
18
|
+
"plugin.settings.rank.hint": "You must create a Number Field with this label and type integer in the Content-Type Builder",
|
|
19
|
+
"plugin.settings.rank.tooltip": "Field which is used for ordering content-type entries",
|
|
20
|
+
"plugin.settings.rank.placeholder": "Rank",
|
|
21
|
+
"plugin.settings.title.label": "Title Field Name",
|
|
22
|
+
"plugin.settings.title.hint": "Select or create a Short Text Field with this label in the Content-Type Builder. Leave blank to use content-type entry title",
|
|
23
|
+
"plugin.settings.title.tooltip": "Field that will show up in the drag drop menu",
|
|
24
|
+
"plugin.settings.title.placeholder": "Title",
|
|
25
|
+
"plugin.settings.subtitle.label": "Subitle Field Name",
|
|
26
|
+
"plugin.settings.subtitle.hint": "Optionally select a second subtitle field to show up attached to the title in the drag drop menu. Leave blank to not show a subtitle.",
|
|
27
|
+
"plugin.settings.subtitle.tooltip": "Field that will show up in the drag drop menu attached to title",
|
|
28
|
+
"plugin.settings.subtitle.placeholder": "Subtitle",
|
|
29
|
+
"plugin.settings.sortableList.showMore": "Show more"
|
|
30
|
+
};
|
|
31
|
+
exports.default = en;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
const en = {
|
|
2
|
+
"plugin.name": "Drag Drop Content Type",
|
|
3
|
+
"plugin.configuration": "Configuration",
|
|
4
|
+
"plugin.settings.errors.required": "Required field",
|
|
5
|
+
"plugin.settings.buttons.save": "Save",
|
|
6
|
+
"plugin.settings.buttons.off": "Off",
|
|
7
|
+
"plugin.settings.buttons.on": "On",
|
|
8
|
+
"plugin.settings.title": "Drag Drop Content Type Config",
|
|
9
|
+
"plugin.settings.subtitle": "Manage field values for drag-droppable entries",
|
|
10
|
+
"plugin.settings.updated": "Settings successfully updated",
|
|
11
|
+
"plugin.settings.field-names": "Field Names",
|
|
12
|
+
"plugin.settings.triggerWebhooks.label": "Trigger Webhooks",
|
|
13
|
+
"plugin.settings.triggerWebhooks.hint": "If enabled, the 'entry.update' webhook will be triggered when entries are reordered",
|
|
14
|
+
"plugin.settings.triggerWebhooks.tooltip": "Enable to trigger webhooks when entries are reordered",
|
|
15
|
+
"plugin.settings.rank.label": "Rank Field Name",
|
|
16
|
+
"plugin.settings.rank.hint": "You must create a Number Field with this label and type integer in the Content-Type Builder",
|
|
17
|
+
"plugin.settings.rank.tooltip": "Field which is used for ordering content-type entries",
|
|
18
|
+
"plugin.settings.rank.placeholder": "Rank",
|
|
19
|
+
"plugin.settings.title.label": "Title Field Name",
|
|
20
|
+
"plugin.settings.title.hint": "Select or create a Short Text Field with this label in the Content-Type Builder. Leave blank to use content-type entry title",
|
|
21
|
+
"plugin.settings.title.tooltip": "Field that will show up in the drag drop menu",
|
|
22
|
+
"plugin.settings.title.placeholder": "Title",
|
|
23
|
+
"plugin.settings.subtitle.label": "Subitle Field Name",
|
|
24
|
+
"plugin.settings.subtitle.hint": "Optionally select a second subtitle field to show up attached to the title in the drag drop menu. Leave blank to not show a subtitle.",
|
|
25
|
+
"plugin.settings.subtitle.tooltip": "Field that will show up in the drag drop menu attached to title",
|
|
26
|
+
"plugin.settings.subtitle.placeholder": "Subtitle",
|
|
27
|
+
"plugin.settings.sortableList.showMore": "Show more"
|
|
28
|
+
};
|
|
29
|
+
export {
|
|
30
|
+
en as default
|
|
31
|
+
};
|
|
@@ -0,0 +1,477 @@
|
|
|
1
|
+
import React__default, { useRef, useEffect, useState, forwardRef } from "react";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { arrayMoveImmutable } from "array-move";
|
|
4
|
+
import { useFetchClient, useNotification, useAPIErrorHandler } from "@strapi/strapi/admin";
|
|
5
|
+
import { Box, Grid, Typography, Divider, Button, Popover, IconButton } from "@strapi/design-system";
|
|
6
|
+
import { Drag } from "@strapi/icons";
|
|
7
|
+
import { useIntl } from "react-intl";
|
|
8
|
+
import { useSensors, useSensor, PointerSensor, TouchSensor, DndContext, closestCenter } from "@dnd-kit/core";
|
|
9
|
+
import { useSortable, SortableContext, arrayMove } from "@dnd-kit/sortable";
|
|
10
|
+
import { CSS } from "@dnd-kit/utilities";
|
|
11
|
+
const __variableDynamicImportRuntimeHelper = (glob, path, segs) => {
|
|
12
|
+
const v = glob[path];
|
|
13
|
+
if (v) {
|
|
14
|
+
return typeof v === "function" ? v() : Promise.resolve(v);
|
|
15
|
+
}
|
|
16
|
+
return new Promise((_, reject) => {
|
|
17
|
+
(typeof queueMicrotask === "function" ? queueMicrotask : setTimeout)(
|
|
18
|
+
reject.bind(
|
|
19
|
+
null,
|
|
20
|
+
new Error(
|
|
21
|
+
"Unknown variable dynamic import: " + path + (path.split("/").length !== segs ? ". Note that variables only represent file names one level deep." : "")
|
|
22
|
+
)
|
|
23
|
+
)
|
|
24
|
+
);
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
const PLUGIN_ID = "drag-drop-content-types";
|
|
28
|
+
const Initializer = ({ setPlugin }) => {
|
|
29
|
+
const ref = useRef(setPlugin);
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
ref.current(PLUGIN_ID);
|
|
32
|
+
}, []);
|
|
33
|
+
return null;
|
|
34
|
+
};
|
|
35
|
+
function useQueryParams() {
|
|
36
|
+
const [params, setParams] = useState(null);
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
const q = new Proxy(new URLSearchParams(window.location.search), {
|
|
39
|
+
get: (queryParams, prop) => queryParams.get(prop.toString())
|
|
40
|
+
});
|
|
41
|
+
setParams(q);
|
|
42
|
+
}, [window.location.search]);
|
|
43
|
+
return { queryParams: params };
|
|
44
|
+
}
|
|
45
|
+
const getTranslation = (id) => `${PLUGIN_ID}.${id}`;
|
|
46
|
+
const CustomItem = forwardRef(
|
|
47
|
+
({ item, isOpacityEnabled, isDragging, style, ...props }, ref) => {
|
|
48
|
+
const styles = {
|
|
49
|
+
opacity: isOpacityEnabled ? "0.4" : "1",
|
|
50
|
+
cursor: isDragging ? "grabbing" : "grab",
|
|
51
|
+
lineHeight: "0.5",
|
|
52
|
+
transform: isDragging ? "scale(1.05)" : "scale(1)",
|
|
53
|
+
...style
|
|
54
|
+
};
|
|
55
|
+
const ellipsis = (str, num = str.length, ellipsisStr = "...") => str.length >= num ? str.slice(0, num >= ellipsisStr.length ? num - ellipsisStr.length : num) + ellipsisStr : str;
|
|
56
|
+
item.title = ellipsis(item.title ?? "", 30);
|
|
57
|
+
item.subtitle = ellipsis(item.subtitle ?? "", 30);
|
|
58
|
+
return /* @__PURE__ */ jsx("div", { ref, style: styles, ...props, children: /* @__PURE__ */ jsx(
|
|
59
|
+
Box,
|
|
60
|
+
{
|
|
61
|
+
style: { zIndex: 10, cursor: "all-scroll", userSelect: "none" },
|
|
62
|
+
background: "neutral0",
|
|
63
|
+
hasRadius: true,
|
|
64
|
+
shadow: "filterShadow",
|
|
65
|
+
padding: 2,
|
|
66
|
+
children: /* @__PURE__ */ jsxs(Grid.Root, { gap: 1, children: [
|
|
67
|
+
/* @__PURE__ */ jsx(Grid.Item, { col: 2, s: 12, children: /* @__PURE__ */ jsx(Drag, {}) }),
|
|
68
|
+
/* @__PURE__ */ jsx(Grid.Item, { col: 10, s: 12, children: /* @__PURE__ */ jsxs(Typography, { children: [
|
|
69
|
+
item.title,
|
|
70
|
+
item.subtitle
|
|
71
|
+
] }) })
|
|
72
|
+
] })
|
|
73
|
+
}
|
|
74
|
+
) });
|
|
75
|
+
}
|
|
76
|
+
);
|
|
77
|
+
const SortableListItem = ({ item, ...props }) => {
|
|
78
|
+
const { attributes, isDragging, listeners, setNodeRef, transform, transition } = useSortable({
|
|
79
|
+
id: item.id
|
|
80
|
+
});
|
|
81
|
+
const styles = {
|
|
82
|
+
transform: CSS.Transform.toString(transform),
|
|
83
|
+
transition: transition || void 0
|
|
84
|
+
};
|
|
85
|
+
return /* @__PURE__ */ jsx(
|
|
86
|
+
CustomItem,
|
|
87
|
+
{
|
|
88
|
+
item,
|
|
89
|
+
ref: setNodeRef,
|
|
90
|
+
style: styles,
|
|
91
|
+
isOpacityEnabled: isDragging,
|
|
92
|
+
...props,
|
|
93
|
+
...attributes,
|
|
94
|
+
...listeners
|
|
95
|
+
}
|
|
96
|
+
);
|
|
97
|
+
};
|
|
98
|
+
function getSubtitle(entry, subTitleField, titleField) {
|
|
99
|
+
try {
|
|
100
|
+
if (subTitleField && entry[subTitleField]) {
|
|
101
|
+
if (entry[subTitleField].constructor.name == "Array") {
|
|
102
|
+
if (entry[subTitleField].length > 0)
|
|
103
|
+
return ` - ${entry[subTitleField][0][titleField]}`;
|
|
104
|
+
} else if (typeof entry[subTitleField] === "object") {
|
|
105
|
+
return ` - ${entry[subTitleField][titleField]}`;
|
|
106
|
+
} else {
|
|
107
|
+
return ` - ${entry[subTitleField]}`;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return "";
|
|
111
|
+
} catch (e) {
|
|
112
|
+
console.log("Unsupported subtitle field value.", e);
|
|
113
|
+
return "";
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
function getTitle(entry, titleField, mainField) {
|
|
117
|
+
const title = entry[titleField] ? entry[titleField] : entry[mainField];
|
|
118
|
+
return title?.toString();
|
|
119
|
+
}
|
|
120
|
+
const SortableList = ({ data, onShowMore, hasMore, settings, onSortEnd }) => {
|
|
121
|
+
const { formatMessage } = useIntl();
|
|
122
|
+
let { title, subtitle, mainField } = settings;
|
|
123
|
+
subtitle = subtitle ?? "";
|
|
124
|
+
mainField = mainField ?? "";
|
|
125
|
+
const convertDataItem = (pageEntry) => {
|
|
126
|
+
return {
|
|
127
|
+
...pageEntry,
|
|
128
|
+
title: getTitle(pageEntry, title, mainField),
|
|
129
|
+
subtitle: getSubtitle(pageEntry, subtitle, title)
|
|
130
|
+
};
|
|
131
|
+
};
|
|
132
|
+
const defaultItems = data.map((x) => convertDataItem(x));
|
|
133
|
+
const [items, setItems] = useState(defaultItems);
|
|
134
|
+
if (items.length !== defaultItems.length)
|
|
135
|
+
setItems(defaultItems);
|
|
136
|
+
const [activeItem, setActiveItem] = useState();
|
|
137
|
+
const sensors = useSensors(useSensor(PointerSensor), useSensor(TouchSensor));
|
|
138
|
+
const handleDragStart = (event) => {
|
|
139
|
+
const { active } = event;
|
|
140
|
+
setActiveItem(items.find((item) => item.id === active.id));
|
|
141
|
+
};
|
|
142
|
+
const handleDragEnd = (event) => {
|
|
143
|
+
const { active, over } = event;
|
|
144
|
+
if (!over) return;
|
|
145
|
+
const activeItem2 = items.find((item) => item.id === active.id);
|
|
146
|
+
const overItem = items.find((item) => item.id === over.id);
|
|
147
|
+
if (!activeItem2 || !overItem) {
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
const activeIndex = items.findIndex((item) => item.id === active.id);
|
|
151
|
+
const overIndex = items.findIndex((item) => item.id === over.id);
|
|
152
|
+
if (activeIndex !== overIndex) {
|
|
153
|
+
setItems((prev) => arrayMove(prev, activeIndex, overIndex));
|
|
154
|
+
}
|
|
155
|
+
setActiveItem(void 0);
|
|
156
|
+
onSortEnd({ oldIndex: activeIndex, newIndex: overIndex });
|
|
157
|
+
};
|
|
158
|
+
const handleDragCancel = () => {
|
|
159
|
+
setActiveItem(void 0);
|
|
160
|
+
};
|
|
161
|
+
return /* @__PURE__ */ jsxs("div", { style: { maxWidth: "280px" }, children: [
|
|
162
|
+
/* @__PURE__ */ jsx(
|
|
163
|
+
DndContext,
|
|
164
|
+
{
|
|
165
|
+
sensors,
|
|
166
|
+
collisionDetection: closestCenter,
|
|
167
|
+
onDragStart: handleDragStart,
|
|
168
|
+
onDragEnd: handleDragEnd,
|
|
169
|
+
onDragCancel: handleDragCancel,
|
|
170
|
+
children: /* @__PURE__ */ jsx(SortableContext, { items, children: items.map((item) => /* @__PURE__ */ jsx(SortableListItem, { item }, item.id)) })
|
|
171
|
+
}
|
|
172
|
+
),
|
|
173
|
+
/* @__PURE__ */ jsx(Divider, { margin: 0 }),
|
|
174
|
+
/* @__PURE__ */ jsx(Box, { padding: 1, children: /* @__PURE__ */ jsx(Button, { size: "S", disabled: hasMore ? true : false, onClick: onShowMore, children: formatMessage({ id: getTranslation("plugin.settings.sortableList.showMore") }) }) })
|
|
175
|
+
] });
|
|
176
|
+
};
|
|
177
|
+
const SortMenu = ({ status, data, onSortEnd, onShowMore, hasMore, settings, onClose }) => {
|
|
178
|
+
const [visible, setVisible] = useState(false);
|
|
179
|
+
const buttonRef = React__default.useRef(null);
|
|
180
|
+
const togglePortal = React__default.useCallback(() => {
|
|
181
|
+
setVisible((prev) => !prev);
|
|
182
|
+
}, []);
|
|
183
|
+
const handleClose = React__default.useCallback((event) => {
|
|
184
|
+
if (event?.target?.id !== "drag-drop-content-type-plugin--sort-menu-button") {
|
|
185
|
+
setVisible(false);
|
|
186
|
+
if (onClose) {
|
|
187
|
+
onClose();
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}, [onClose]);
|
|
191
|
+
return /* @__PURE__ */ jsx(React__default.Fragment, { children: /* @__PURE__ */ jsxs(Popover.Root, { children: [
|
|
192
|
+
/* @__PURE__ */ jsx(Popover.Trigger, { children: /* @__PURE__ */ jsx(
|
|
193
|
+
IconButton,
|
|
194
|
+
{
|
|
195
|
+
id: "drag-drop-content-type-plugin--sort-menu-button",
|
|
196
|
+
ref: buttonRef,
|
|
197
|
+
variant: "secondary",
|
|
198
|
+
disabled: status === "success" ? false : true,
|
|
199
|
+
withTooltip: false,
|
|
200
|
+
onClick: togglePortal,
|
|
201
|
+
label: "Sort",
|
|
202
|
+
children: /* @__PURE__ */ jsx(Drag, {})
|
|
203
|
+
}
|
|
204
|
+
) }),
|
|
205
|
+
/* @__PURE__ */ jsx(
|
|
206
|
+
Popover.Content,
|
|
207
|
+
{
|
|
208
|
+
onEscapeKeyDown: handleClose,
|
|
209
|
+
onPointerDownOutside: handleClose,
|
|
210
|
+
children: /* @__PURE__ */ jsx(
|
|
211
|
+
SortableList,
|
|
212
|
+
{
|
|
213
|
+
data,
|
|
214
|
+
onShowMore,
|
|
215
|
+
onSortEnd,
|
|
216
|
+
hasMore,
|
|
217
|
+
settings
|
|
218
|
+
}
|
|
219
|
+
)
|
|
220
|
+
}
|
|
221
|
+
)
|
|
222
|
+
] }) });
|
|
223
|
+
};
|
|
224
|
+
const SortModal = () => {
|
|
225
|
+
const { get, post, put } = useFetchClient();
|
|
226
|
+
const [data, setData] = useState([]);
|
|
227
|
+
const [pagination, setPagination] = useState();
|
|
228
|
+
const [status, setStatus] = useState("loading");
|
|
229
|
+
const [mainField, setMainField] = useState("id");
|
|
230
|
+
const [uid, setUid] = useState(null);
|
|
231
|
+
const [settings, setSettings] = useState({
|
|
232
|
+
rank: "",
|
|
233
|
+
title: "",
|
|
234
|
+
subtitle: "",
|
|
235
|
+
mainField: null
|
|
236
|
+
});
|
|
237
|
+
const [noEntriesFromNextPage, setNoEntriesFromNextPage] = useState(0);
|
|
238
|
+
const [hasSorted, setHasSorted] = useState(false);
|
|
239
|
+
const { queryParams } = useQueryParams();
|
|
240
|
+
const { toggleNotification } = useNotification();
|
|
241
|
+
const { formatAPIError } = useAPIErrorHandler();
|
|
242
|
+
const paths = window.location.pathname.split("/");
|
|
243
|
+
const contentTypePath = paths[paths.length - 1];
|
|
244
|
+
const params = queryParams;
|
|
245
|
+
const pageSize = parseInt(params?.pageSize) ?? 0;
|
|
246
|
+
const currentPage = parseInt(params?.page) ?? 0;
|
|
247
|
+
const locale = params?.["plugins[i18n][locale]"];
|
|
248
|
+
const listIncrementSize = pageSize ? pageSize / 2 : 1;
|
|
249
|
+
const hasMore = noEntriesFromNextPage ? noEntriesFromNextPage + listIncrementSize >= data?.length - 1 : false;
|
|
250
|
+
const fetchContentTypeConfig = async () => {
|
|
251
|
+
try {
|
|
252
|
+
const { data: data2 } = await get(
|
|
253
|
+
`/content-manager/content-types/${contentTypePath}/configuration`
|
|
254
|
+
);
|
|
255
|
+
const settings2 = data2.data.contentType?.settings;
|
|
256
|
+
setMainField(settings2.mainField);
|
|
257
|
+
setUid(data2.data.contentType?.uid);
|
|
258
|
+
setNoEntriesFromNextPage(settings2.pageSize / 2);
|
|
259
|
+
} catch (e) {
|
|
260
|
+
console.log(e);
|
|
261
|
+
}
|
|
262
|
+
};
|
|
263
|
+
const fetchSettings = async () => {
|
|
264
|
+
try {
|
|
265
|
+
const { data: data2 } = await get(`/drag-drop-content-types/settings`);
|
|
266
|
+
let fetchedSettings = {
|
|
267
|
+
rank: data2.body.rank,
|
|
268
|
+
title: data2.body.title?.length > 0 ? data2.body.title : mainField,
|
|
269
|
+
subtitle: data2.body.subtitle?.length > 0 ? data2.body.subtitle : null,
|
|
270
|
+
mainField
|
|
271
|
+
};
|
|
272
|
+
setSettings(fetchedSettings);
|
|
273
|
+
} catch (e) {
|
|
274
|
+
console.log(e);
|
|
275
|
+
}
|
|
276
|
+
};
|
|
277
|
+
const getPageEntries = async () => {
|
|
278
|
+
if (pageSize) {
|
|
279
|
+
const sortIndexParam = {
|
|
280
|
+
contentType: contentTypePath,
|
|
281
|
+
rankFieldName: settings.rank,
|
|
282
|
+
start: Math.max(
|
|
283
|
+
0,
|
|
284
|
+
(currentPage - 1) * pageSize - noEntriesFromNextPage
|
|
285
|
+
),
|
|
286
|
+
limit: currentPage === 1 ? pageSize + noEntriesFromNextPage : pageSize + 2 * noEntriesFromNextPage,
|
|
287
|
+
locale
|
|
288
|
+
};
|
|
289
|
+
const results = await post(`/drag-drop-content-types/sort-index`, sortIndexParam);
|
|
290
|
+
return results;
|
|
291
|
+
}
|
|
292
|
+
};
|
|
293
|
+
const initializeContentType = async () => {
|
|
294
|
+
try {
|
|
295
|
+
if (settings?.rank) {
|
|
296
|
+
const entries = await getPageEntries();
|
|
297
|
+
if (entries?.data?.length) {
|
|
298
|
+
const firstEntry = entries.data[0];
|
|
299
|
+
const firstEntryRank = firstEntry[settings.rank];
|
|
300
|
+
if (entries.data?.length > 0 && firstEntryRank && !!firstEntryRank.toString()) {
|
|
301
|
+
setStatus("success");
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
} catch (e) {
|
|
306
|
+
console.log("Could not initialize content type", e);
|
|
307
|
+
setStatus("error");
|
|
308
|
+
}
|
|
309
|
+
};
|
|
310
|
+
const fetchContentType = async () => {
|
|
311
|
+
try {
|
|
312
|
+
const entries = await getPageEntries();
|
|
313
|
+
if (entries?.data?.length) {
|
|
314
|
+
setStatus("success");
|
|
315
|
+
setData(entries.data);
|
|
316
|
+
const { data: data2 } = await get(
|
|
317
|
+
`/content-manager/collection-types/${contentTypePath}?sort=${settings.rank}:asc&page=${currentPage}&pageSize=${pageSize}&locale=${locale}`
|
|
318
|
+
);
|
|
319
|
+
setPagination(data2.pagination);
|
|
320
|
+
}
|
|
321
|
+
} catch (e) {
|
|
322
|
+
console.log("Could not fetch content type", e);
|
|
323
|
+
setStatus("error");
|
|
324
|
+
}
|
|
325
|
+
};
|
|
326
|
+
const updateContentType = async (item) => {
|
|
327
|
+
const { oldIndex, newIndex } = item;
|
|
328
|
+
try {
|
|
329
|
+
const sortedList = arrayMoveImmutable(data, oldIndex, newIndex);
|
|
330
|
+
const rankUpdates = [];
|
|
331
|
+
let rankHasChanged = false;
|
|
332
|
+
for (let i = 0; i < sortedList.length; i++) {
|
|
333
|
+
if (sortedList[i].id != data[i].id) {
|
|
334
|
+
const newRank = pageSize * (currentPage - 1) + i || 0;
|
|
335
|
+
const update = {
|
|
336
|
+
id: sortedList[i].id,
|
|
337
|
+
rank: newRank
|
|
338
|
+
};
|
|
339
|
+
rankUpdates.push(update);
|
|
340
|
+
rankHasChanged = true;
|
|
341
|
+
} else if (rankHasChanged) {
|
|
342
|
+
break;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
await put("/drag-drop-content-types/batch-update", {
|
|
346
|
+
contentType: contentTypePath,
|
|
347
|
+
updates: rankUpdates
|
|
348
|
+
});
|
|
349
|
+
let sortedListViewEntries = currentPage == 1 ? sortedList.slice(0, pageSize) : sortedList.length < pageSize ? sortedList.slice(noEntriesFromNextPage, sortedList.length) : sortedList.slice(
|
|
350
|
+
noEntriesFromNextPage,
|
|
351
|
+
pageSize + noEntriesFromNextPage
|
|
352
|
+
);
|
|
353
|
+
setData(sortedList);
|
|
354
|
+
setStatus("success");
|
|
355
|
+
afterUpdate(sortedListViewEntries, pagination);
|
|
356
|
+
} catch (e) {
|
|
357
|
+
console.log("Could not update content type:", e);
|
|
358
|
+
toggleNotification({
|
|
359
|
+
type: "warning",
|
|
360
|
+
message: formatAPIError(e)
|
|
361
|
+
});
|
|
362
|
+
setStatus("error");
|
|
363
|
+
}
|
|
364
|
+
};
|
|
365
|
+
const afterUpdate = (newData, pagination2) => {
|
|
366
|
+
setHasSorted(true);
|
|
367
|
+
};
|
|
368
|
+
const handleModalClose = () => {
|
|
369
|
+
if (hasSorted) {
|
|
370
|
+
window.location.reload();
|
|
371
|
+
}
|
|
372
|
+
};
|
|
373
|
+
const showMoreHandler = () => {
|
|
374
|
+
setNoEntriesFromNextPage(noEntriesFromNextPage + listIncrementSize);
|
|
375
|
+
};
|
|
376
|
+
useEffect(() => {
|
|
377
|
+
fetchContentTypeConfig();
|
|
378
|
+
}, []);
|
|
379
|
+
useEffect(() => {
|
|
380
|
+
fetchSettings();
|
|
381
|
+
}, [mainField]);
|
|
382
|
+
useEffect(() => {
|
|
383
|
+
if (settings?.rank) {
|
|
384
|
+
initializeContentType();
|
|
385
|
+
}
|
|
386
|
+
}, [settings]);
|
|
387
|
+
useEffect(() => {
|
|
388
|
+
if (settings?.rank && pageSize && currentPage) {
|
|
389
|
+
fetchContentType();
|
|
390
|
+
}
|
|
391
|
+
}, [noEntriesFromNextPage, locale, pageSize, currentPage, settings]);
|
|
392
|
+
return (
|
|
393
|
+
// <CheckPermissions permissions={pluginPermissions.main}>
|
|
394
|
+
/* @__PURE__ */ jsx(
|
|
395
|
+
SortMenu,
|
|
396
|
+
{
|
|
397
|
+
data,
|
|
398
|
+
status,
|
|
399
|
+
onOpen: fetchContentType,
|
|
400
|
+
onSortEnd: updateContentType,
|
|
401
|
+
onShowMore: showMoreHandler,
|
|
402
|
+
onClose: handleModalClose,
|
|
403
|
+
hasMore,
|
|
404
|
+
settings
|
|
405
|
+
}
|
|
406
|
+
)
|
|
407
|
+
);
|
|
408
|
+
};
|
|
409
|
+
const pluginPermissions = {
|
|
410
|
+
main: [{ action: "plugin::drag-drop-content-types.read", subject: null }]
|
|
411
|
+
};
|
|
412
|
+
const prefixPluginTranslations = (trad, pluginId) => {
|
|
413
|
+
return Object.keys(trad).reduce((acc, current) => {
|
|
414
|
+
acc[`${pluginId}.${current}`] = trad[current];
|
|
415
|
+
return acc;
|
|
416
|
+
}, {});
|
|
417
|
+
};
|
|
418
|
+
const index = {
|
|
419
|
+
register(app) {
|
|
420
|
+
app.createSettingSection(
|
|
421
|
+
{
|
|
422
|
+
id: PLUGIN_ID,
|
|
423
|
+
intlLabel: {
|
|
424
|
+
id: `${PLUGIN_ID}.plugin.name`,
|
|
425
|
+
defaultMessage: "Drag Drop Content Types"
|
|
426
|
+
},
|
|
427
|
+
permissions: pluginPermissions.main
|
|
428
|
+
},
|
|
429
|
+
[
|
|
430
|
+
{
|
|
431
|
+
intlLabel: {
|
|
432
|
+
id: `${PLUGIN_ID}.plugin.configuration`,
|
|
433
|
+
defaultMessage: "Configuration"
|
|
434
|
+
},
|
|
435
|
+
id: "settings",
|
|
436
|
+
to: `${PLUGIN_ID}`,
|
|
437
|
+
Component: () => import("./Settings-Cx22s5Bk.mjs")
|
|
438
|
+
}
|
|
439
|
+
]
|
|
440
|
+
);
|
|
441
|
+
app.registerPlugin({
|
|
442
|
+
id: PLUGIN_ID,
|
|
443
|
+
initializer: Initializer,
|
|
444
|
+
isReady: false,
|
|
445
|
+
name: PLUGIN_ID
|
|
446
|
+
});
|
|
447
|
+
},
|
|
448
|
+
bootstrap(app) {
|
|
449
|
+
app.getPlugin("content-manager").injectComponent("listView", "actions", {
|
|
450
|
+
name: "sort-component",
|
|
451
|
+
Component: SortModal
|
|
452
|
+
});
|
|
453
|
+
},
|
|
454
|
+
async registerTrads(app) {
|
|
455
|
+
const { locales } = app;
|
|
456
|
+
const importedTranslations = await Promise.all(
|
|
457
|
+
locales.map((locale) => {
|
|
458
|
+
return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/en.json": () => import("./en-bxpER_P-.mjs"), "./translations/fr.json": () => import("./fr-hkSxFuzl.mjs") }), `./translations/${locale}.json`, 3).then(({ default: data }) => {
|
|
459
|
+
return {
|
|
460
|
+
data: prefixPluginTranslations(data, PLUGIN_ID),
|
|
461
|
+
locale
|
|
462
|
+
};
|
|
463
|
+
}).catch(() => {
|
|
464
|
+
return {
|
|
465
|
+
data: {},
|
|
466
|
+
locale
|
|
467
|
+
};
|
|
468
|
+
});
|
|
469
|
+
})
|
|
470
|
+
);
|
|
471
|
+
return importedTranslations;
|
|
472
|
+
}
|
|
473
|
+
};
|
|
474
|
+
export {
|
|
475
|
+
getTranslation as g,
|
|
476
|
+
index as i
|
|
477
|
+
};
|