@primershop/strapi-plugin-status-manager 0.0.16 → 0.0.18
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/dist/_chunks/HomePage-CYpSKXVE.mjs +2115 -0
- package/dist/_chunks/HomePage-D9xj2-y8.js +2115 -0
- package/dist/_chunks/index-BXToWkDF.js +227 -0
- package/dist/_chunks/index-CzxwE0pe.mjs +226 -0
- package/dist/admin/index.js +2 -11
- package/dist/admin/index.mjs +4 -6
- package/dist/server/index.js +601 -703
- package/dist/server/index.mjs +603 -702
- package/package.json +13 -14
- package/dist/admin/HomePage-Bez9ZXv-.js +0 -412
- package/dist/admin/HomePage-Dx9N0awm.mjs +0 -410
- package/dist/admin/index-BVybZ6IA.mjs +0 -280
- package/dist/admin/index-mATo7IeG.js +0 -283
|
@@ -1,410 +0,0 @@
|
|
|
1
|
-
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
-
import { Box, Typography, Flex, TextInput, Button, Dialog, SingleSelect, SingleSelectOption } from '@strapi/design-system';
|
|
3
|
-
import { useFetchClient, Layouts, Page } from '@strapi/strapi/admin';
|
|
4
|
-
import { useState, useEffect, useCallback } from 'react';
|
|
5
|
-
import { combine } from '@atlaskit/pragmatic-drag-and-drop/combine';
|
|
6
|
-
import { draggable, dropTargetForElements, monitorForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
|
|
7
|
-
import { pointerOutsideOfPreview } from '@atlaskit/pragmatic-drag-and-drop/element/pointer-outside-of-preview';
|
|
8
|
-
import { setCustomNativeDragPreview } from '@atlaskit/pragmatic-drag-and-drop/element/set-custom-native-drag-preview';
|
|
9
|
-
import { reorder } from '@atlaskit/pragmatic-drag-and-drop/reorder';
|
|
10
|
-
import { extractClosestEdge, attachClosestEdge } from '@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge';
|
|
11
|
-
import { Plus, Drag, Trash } from '@strapi/icons';
|
|
12
|
-
import { p as pluginPermissions } from './index-BVybZ6IA.mjs';
|
|
13
|
-
|
|
14
|
-
const StatusManager = ()=>{
|
|
15
|
-
const [statuses, setStatuses] = useState([]);
|
|
16
|
-
const [newStatus, setNewStatus] = useState("");
|
|
17
|
-
const [statusToDelete, setStatusToDelete] = useState(null);
|
|
18
|
-
const [replacementStatus, setReplacementStatus] = useState("");
|
|
19
|
-
const { get, post, put } = useFetchClient();
|
|
20
|
-
const [instanceId] = useState(()=>Symbol("instance-id"));
|
|
21
|
-
// Fetch statuses
|
|
22
|
-
useEffect(()=>{
|
|
23
|
-
const loadStatuses = async ()=>{
|
|
24
|
-
const { data } = await get("primershop-status-manager/statuses");
|
|
25
|
-
setStatuses(data);
|
|
26
|
-
};
|
|
27
|
-
loadStatuses();
|
|
28
|
-
}, [
|
|
29
|
-
get
|
|
30
|
-
]);
|
|
31
|
-
// Validate input (Latin characters only)
|
|
32
|
-
const validateInput = (value)=>/^[a-zA-Z\s]+$/.test(value);
|
|
33
|
-
// Add new status
|
|
34
|
-
const addStatus = async ()=>{
|
|
35
|
-
if (!newStatus || !validateInput(newStatus)) return alert("Only Latin characters allowed!");
|
|
36
|
-
try {
|
|
37
|
-
const { data } = await post("primershop-status-manager/status", {
|
|
38
|
-
name: newStatus,
|
|
39
|
-
published: false
|
|
40
|
-
});
|
|
41
|
-
setStatuses([
|
|
42
|
-
...statuses,
|
|
43
|
-
data
|
|
44
|
-
]);
|
|
45
|
-
setNewStatus("");
|
|
46
|
-
} catch (error) {
|
|
47
|
-
console.error("Error creating status:", error);
|
|
48
|
-
}
|
|
49
|
-
};
|
|
50
|
-
const reorderItem = useCallback(async ({ startIndex, indexOfTarget, closestEdgeOfTarget })=>{
|
|
51
|
-
// Calculate the final index based on the target position and edge
|
|
52
|
-
let finishIndex = indexOfTarget;
|
|
53
|
-
if (closestEdgeOfTarget === "bottom") {
|
|
54
|
-
finishIndex = indexOfTarget + 1;
|
|
55
|
-
}
|
|
56
|
-
// If moving an item down, we need to adjust for the removed item
|
|
57
|
-
if (startIndex < finishIndex) {
|
|
58
|
-
finishIndex--;
|
|
59
|
-
}
|
|
60
|
-
if (finishIndex === startIndex) {
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
const reordered = reorder({
|
|
64
|
-
list: statuses,
|
|
65
|
-
startIndex,
|
|
66
|
-
finishIndex
|
|
67
|
-
});
|
|
68
|
-
// Send new order to API
|
|
69
|
-
const orderedIds = reordered.map((status, index)=>({
|
|
70
|
-
documentId: status.documentId,
|
|
71
|
-
order: index
|
|
72
|
-
}));
|
|
73
|
-
await put("/primershop-status-manager/statuses/reorder", {
|
|
74
|
-
statuses: orderedIds
|
|
75
|
-
});
|
|
76
|
-
setStatuses(reordered);
|
|
77
|
-
}, [
|
|
78
|
-
statuses,
|
|
79
|
-
put
|
|
80
|
-
]);
|
|
81
|
-
// Setup drag and drop
|
|
82
|
-
useEffect(()=>{
|
|
83
|
-
const statusElements = document.querySelectorAll("[data-status-id]");
|
|
84
|
-
const cleanupFunctions = [];
|
|
85
|
-
statusElements.forEach((element)=>{
|
|
86
|
-
const statusId = element.getAttribute("data-status-id");
|
|
87
|
-
const index = statuses.findIndex((s)=>s.documentId === statusId);
|
|
88
|
-
const dragHandle = element.querySelector("[data-drag-handle]");
|
|
89
|
-
if (!dragHandle) return;
|
|
90
|
-
// Setup draggable
|
|
91
|
-
const draggableCleanup = draggable({
|
|
92
|
-
element: dragHandle,
|
|
93
|
-
getInitialData: ()=>({
|
|
94
|
-
statusId,
|
|
95
|
-
index,
|
|
96
|
-
instanceId
|
|
97
|
-
}),
|
|
98
|
-
onGenerateDragPreview ({ nativeSetDragImage }) {
|
|
99
|
-
setCustomNativeDragPreview({
|
|
100
|
-
nativeSetDragImage,
|
|
101
|
-
getOffset: pointerOutsideOfPreview({
|
|
102
|
-
x: "16px",
|
|
103
|
-
y: "8px"
|
|
104
|
-
}),
|
|
105
|
-
render ({ container }) {
|
|
106
|
-
const preview = document.createElement("div");
|
|
107
|
-
preview.style.padding = "8px 16px";
|
|
108
|
-
preview.style.backgroundColor = "#fff";
|
|
109
|
-
preview.style.border = "1px solid #ccc";
|
|
110
|
-
preview.style.borderRadius = "4px";
|
|
111
|
-
preview.style.boxShadow = "0 2px 4px rgba(0,0,0,0.1)";
|
|
112
|
-
const statusNameElement = element.querySelector("[data-status-name]");
|
|
113
|
-
preview.textContent = statusNameElement?.textContent || "";
|
|
114
|
-
container.appendChild(preview);
|
|
115
|
-
return ()=>container.removeChild(preview);
|
|
116
|
-
}
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
});
|
|
120
|
-
// Setup drop target
|
|
121
|
-
const dropTargetCleanup = dropTargetForElements({
|
|
122
|
-
element: element,
|
|
123
|
-
canDrop: ({ source })=>source.data.instanceId === instanceId,
|
|
124
|
-
getData ({ input }) {
|
|
125
|
-
return attachClosestEdge({
|
|
126
|
-
statusId,
|
|
127
|
-
index,
|
|
128
|
-
instanceId
|
|
129
|
-
}, {
|
|
130
|
-
element,
|
|
131
|
-
input,
|
|
132
|
-
allowedEdges: [
|
|
133
|
-
"top",
|
|
134
|
-
"bottom"
|
|
135
|
-
]
|
|
136
|
-
});
|
|
137
|
-
},
|
|
138
|
-
onDrag ({ source, self }) {
|
|
139
|
-
const isSource = source.element === dragHandle;
|
|
140
|
-
if (isSource) return;
|
|
141
|
-
const closestEdge = extractClosestEdge(self.data);
|
|
142
|
-
const sourceIndex = Number(source.data.index);
|
|
143
|
-
const isItemBeforeSource = index === sourceIndex - 1;
|
|
144
|
-
const isItemAfterSource = index === sourceIndex + 1;
|
|
145
|
-
const isDropIndicatorHidden = isItemBeforeSource && closestEdge === "bottom" || isItemAfterSource && closestEdge === "top";
|
|
146
|
-
if (isDropIndicatorHidden) return;
|
|
147
|
-
// Add visual feedback for drop target
|
|
148
|
-
element.style.background = `linear-gradient(${closestEdge === "top" ? 180 : 0}deg, rgba(136,131,214,0.4) 0%, rgba(255,255,255,0) 50%)`;
|
|
149
|
-
},
|
|
150
|
-
onDragLeave () {
|
|
151
|
-
element.style.background = "";
|
|
152
|
-
},
|
|
153
|
-
onDrop ({ source, self }) {
|
|
154
|
-
element.style.background = "";
|
|
155
|
-
const sourceData = source.data;
|
|
156
|
-
const targetData = self.data;
|
|
157
|
-
const indexOfTarget = statuses.findIndex((s)=>s.documentId === targetData.statusId);
|
|
158
|
-
if (indexOfTarget < 0) return;
|
|
159
|
-
const closestEdgeOfTarget = extractClosestEdge(targetData);
|
|
160
|
-
reorderItem({
|
|
161
|
-
startIndex: sourceData.index,
|
|
162
|
-
indexOfTarget,
|
|
163
|
-
closestEdgeOfTarget
|
|
164
|
-
});
|
|
165
|
-
}
|
|
166
|
-
});
|
|
167
|
-
// Combine cleanup functions
|
|
168
|
-
const combinedCleanup = combine(draggableCleanup, dropTargetCleanup);
|
|
169
|
-
cleanupFunctions.push(combinedCleanup);
|
|
170
|
-
});
|
|
171
|
-
// Monitor for drops
|
|
172
|
-
const monitorCleanup = monitorForElements({
|
|
173
|
-
canMonitor: ({ source })=>source.data.instanceId === instanceId,
|
|
174
|
-
onDrop ({ location, source }) {
|
|
175
|
-
const target = location.current.dropTargets[0];
|
|
176
|
-
if (!target) return;
|
|
177
|
-
const sourceData = source.data;
|
|
178
|
-
const targetData = target.data;
|
|
179
|
-
const indexOfTarget = statuses.findIndex((s)=>s.documentId === targetData.statusId);
|
|
180
|
-
if (indexOfTarget < 0) return;
|
|
181
|
-
const closestEdgeOfTarget = extractClosestEdge(targetData);
|
|
182
|
-
reorderItem({
|
|
183
|
-
startIndex: sourceData.index,
|
|
184
|
-
indexOfTarget,
|
|
185
|
-
closestEdgeOfTarget
|
|
186
|
-
});
|
|
187
|
-
}
|
|
188
|
-
});
|
|
189
|
-
// Cleanup function
|
|
190
|
-
return ()=>{
|
|
191
|
-
cleanupFunctions.forEach((cleanup)=>cleanup());
|
|
192
|
-
monitorCleanup();
|
|
193
|
-
};
|
|
194
|
-
}, [
|
|
195
|
-
statuses,
|
|
196
|
-
reorderItem,
|
|
197
|
-
instanceId
|
|
198
|
-
]);
|
|
199
|
-
// Open delete dialog
|
|
200
|
-
const confirmDelete = (status)=>{
|
|
201
|
-
setStatusToDelete(status);
|
|
202
|
-
};
|
|
203
|
-
// Delete status and replace with selected one
|
|
204
|
-
const deleteStatus = async ()=>{
|
|
205
|
-
if (!replacementStatus) return alert("Select a replacement status!");
|
|
206
|
-
const replacementStatusObj = statuses.find((s)=>s.name === replacementStatus);
|
|
207
|
-
if (!replacementStatusObj) return alert("Replacement status not found!");
|
|
208
|
-
try {
|
|
209
|
-
await put("/primershop-status-manager/statuses/delete", {
|
|
210
|
-
statusId: statusToDelete?.documentId,
|
|
211
|
-
replacementId: replacementStatusObj.documentId
|
|
212
|
-
});
|
|
213
|
-
// Remove the deleted status from the list
|
|
214
|
-
setStatuses(statuses.filter((s)=>s.documentId !== statusToDelete?.documentId));
|
|
215
|
-
setStatusToDelete(null);
|
|
216
|
-
setReplacementStatus("");
|
|
217
|
-
} catch (error) {
|
|
218
|
-
console.error("Error deleting status:", error);
|
|
219
|
-
}
|
|
220
|
-
};
|
|
221
|
-
// Toggle publish status
|
|
222
|
-
const togglePublish = async (id, published)=>{
|
|
223
|
-
try {
|
|
224
|
-
await put(`/primershop-status-manager/statuses/${id}`, {
|
|
225
|
-
published: !published
|
|
226
|
-
});
|
|
227
|
-
setStatuses(statuses.map((s)=>s.documentId === id ? {
|
|
228
|
-
...s,
|
|
229
|
-
published: !published
|
|
230
|
-
} : s));
|
|
231
|
-
} catch (error) {
|
|
232
|
-
console.error("Error toggling publish status:", error);
|
|
233
|
-
}
|
|
234
|
-
};
|
|
235
|
-
return /*#__PURE__*/ jsxs(Box, {
|
|
236
|
-
padding: 4,
|
|
237
|
-
children: [
|
|
238
|
-
/*#__PURE__*/ jsx(Typography, {
|
|
239
|
-
variant: "beta",
|
|
240
|
-
children: "Status Manager"
|
|
241
|
-
}),
|
|
242
|
-
/*#__PURE__*/ jsxs(Flex, {
|
|
243
|
-
marginTop: 4,
|
|
244
|
-
gap: 2,
|
|
245
|
-
children: [
|
|
246
|
-
/*#__PURE__*/ jsx(TextInput, {
|
|
247
|
-
placeholder: "Enter a status...",
|
|
248
|
-
value: newStatus,
|
|
249
|
-
onChange: (e)=>setNewStatus(e.target.value)
|
|
250
|
-
}),
|
|
251
|
-
/*#__PURE__*/ jsx(Button, {
|
|
252
|
-
onClick: addStatus,
|
|
253
|
-
startIcon: /*#__PURE__*/ jsx(Plus, {}),
|
|
254
|
-
children: "Add Status"
|
|
255
|
-
})
|
|
256
|
-
]
|
|
257
|
-
}),
|
|
258
|
-
/*#__PURE__*/ jsx(Box, {
|
|
259
|
-
marginTop: 4,
|
|
260
|
-
children: statuses.map((status)=>/*#__PURE__*/ jsxs(Flex, {
|
|
261
|
-
"data-status-id": status.documentId,
|
|
262
|
-
alignItems: "center",
|
|
263
|
-
gap: 2,
|
|
264
|
-
marginBottom: 2,
|
|
265
|
-
paddingBottom: 2,
|
|
266
|
-
style: {
|
|
267
|
-
borderBottom: `1px solid gray`,
|
|
268
|
-
minWidth: 300,
|
|
269
|
-
userSelect: "none",
|
|
270
|
-
touchAction: "none"
|
|
271
|
-
},
|
|
272
|
-
children: [
|
|
273
|
-
/*#__PURE__*/ jsx(Box, {
|
|
274
|
-
"data-drag-handle": true,
|
|
275
|
-
style: {
|
|
276
|
-
cursor: "grab",
|
|
277
|
-
padding: "4px",
|
|
278
|
-
display: "flex",
|
|
279
|
-
alignItems: "center"
|
|
280
|
-
},
|
|
281
|
-
children: /*#__PURE__*/ jsx(Drag, {})
|
|
282
|
-
}, `dragHandle-${status.documentId}`),
|
|
283
|
-
/*#__PURE__*/ jsx(Typography, {
|
|
284
|
-
variant: "sigma",
|
|
285
|
-
style: {
|
|
286
|
-
display: "inline-block",
|
|
287
|
-
marginRight: "auto"
|
|
288
|
-
},
|
|
289
|
-
"data-status-name": true,
|
|
290
|
-
children: status.name
|
|
291
|
-
}),
|
|
292
|
-
/*#__PURE__*/ jsx(Button, {
|
|
293
|
-
variant: status.published ? "success-light" : "secondary",
|
|
294
|
-
onClick: ()=>togglePublish(status.documentId, status.published),
|
|
295
|
-
children: status.published ? "Published" : "Unpublished"
|
|
296
|
-
}),
|
|
297
|
-
/*#__PURE__*/ jsxs(Dialog.Root, {
|
|
298
|
-
onOpenChange: ()=>confirmDelete(status),
|
|
299
|
-
children: [
|
|
300
|
-
/*#__PURE__*/ jsx(Dialog.Trigger, {
|
|
301
|
-
children: /*#__PURE__*/ jsx(Button, {
|
|
302
|
-
variant: "tertiary",
|
|
303
|
-
startIcon: /*#__PURE__*/ jsx(Trash, {}),
|
|
304
|
-
children: "Delete"
|
|
305
|
-
})
|
|
306
|
-
}),
|
|
307
|
-
/*#__PURE__*/ jsxs(Dialog.Content, {
|
|
308
|
-
children: [
|
|
309
|
-
/*#__PURE__*/ jsx(Dialog.Header, {
|
|
310
|
-
children: "Delete status"
|
|
311
|
-
}),
|
|
312
|
-
statuses.length > 1 && statusToDelete && /*#__PURE__*/ jsxs(Dialog.Body, {
|
|
313
|
-
children: [
|
|
314
|
-
/*#__PURE__*/ jsx(Typography, {
|
|
315
|
-
children: "Choose a replacement status before deleting:"
|
|
316
|
-
}),
|
|
317
|
-
/*#__PURE__*/ jsx(SingleSelect, {
|
|
318
|
-
onChange: (value)=>setReplacementStatus(value),
|
|
319
|
-
placeholder: "Select replacement",
|
|
320
|
-
children: statuses.filter((s)=>s.documentId !== statusToDelete.documentId).map((s)=>/*#__PURE__*/ jsx(SingleSelectOption, {
|
|
321
|
-
value: s.name,
|
|
322
|
-
children: s.name
|
|
323
|
-
}, `statusChoice-${s.documentId}`))
|
|
324
|
-
}),
|
|
325
|
-
replacementStatus && /*#__PURE__*/ jsxs(Typography, {
|
|
326
|
-
children: [
|
|
327
|
-
"Replacing ",
|
|
328
|
-
statusToDelete.name,
|
|
329
|
-
" with ",
|
|
330
|
-
replacementStatus
|
|
331
|
-
]
|
|
332
|
-
})
|
|
333
|
-
]
|
|
334
|
-
}),
|
|
335
|
-
/*#__PURE__*/ jsxs(Dialog.Footer, {
|
|
336
|
-
children: [
|
|
337
|
-
/*#__PURE__*/ jsx(Dialog.Cancel, {
|
|
338
|
-
children: /*#__PURE__*/ jsx(Button, {
|
|
339
|
-
fullWidth: true,
|
|
340
|
-
variant: "tertiary",
|
|
341
|
-
children: "Cancel"
|
|
342
|
-
})
|
|
343
|
-
}),
|
|
344
|
-
/*#__PURE__*/ jsx(Dialog.Action, {
|
|
345
|
-
children: /*#__PURE__*/ jsx(Button, {
|
|
346
|
-
fullWidth: true,
|
|
347
|
-
variant: "danger-light",
|
|
348
|
-
onClick: deleteStatus,
|
|
349
|
-
children: "Yes, delete"
|
|
350
|
-
})
|
|
351
|
-
})
|
|
352
|
-
]
|
|
353
|
-
})
|
|
354
|
-
]
|
|
355
|
-
})
|
|
356
|
-
]
|
|
357
|
-
})
|
|
358
|
-
]
|
|
359
|
-
}, `status-${status.documentId}`))
|
|
360
|
-
}, statuses.length)
|
|
361
|
-
]
|
|
362
|
-
});
|
|
363
|
-
};
|
|
364
|
-
|
|
365
|
-
const HomePage = ()=>{
|
|
366
|
-
return /*#__PURE__*/ jsxs(Layouts.Root, {
|
|
367
|
-
children: [
|
|
368
|
-
/*#__PURE__*/ jsx(Page.Title, {
|
|
369
|
-
children: "Status Manager"
|
|
370
|
-
}),
|
|
371
|
-
/*#__PURE__*/ jsx(Page.Main, {
|
|
372
|
-
children: /*#__PURE__*/ jsx(Page.Protect, {
|
|
373
|
-
permissions: pluginPermissions.accessStatusManager,
|
|
374
|
-
children: /*#__PURE__*/ jsx(Layouts.Content, {
|
|
375
|
-
children: /*#__PURE__*/ jsx(Box, {
|
|
376
|
-
children: /*#__PURE__*/ jsx(Flex, {
|
|
377
|
-
padding: 10,
|
|
378
|
-
gap: {
|
|
379
|
-
initial: 1,
|
|
380
|
-
medium: 4,
|
|
381
|
-
large: 8
|
|
382
|
-
},
|
|
383
|
-
direction: {
|
|
384
|
-
initial: "column",
|
|
385
|
-
medium: "row"
|
|
386
|
-
},
|
|
387
|
-
alignItems: {
|
|
388
|
-
initial: "center",
|
|
389
|
-
medium: "flex-start"
|
|
390
|
-
},
|
|
391
|
-
children: /*#__PURE__*/ jsxs(Box, {
|
|
392
|
-
padding: 1,
|
|
393
|
-
children: [
|
|
394
|
-
/*#__PURE__*/ jsx(Typography, {
|
|
395
|
-
variant: "alpha",
|
|
396
|
-
children: "Status manager"
|
|
397
|
-
}),
|
|
398
|
-
/*#__PURE__*/ jsx(StatusManager, {})
|
|
399
|
-
]
|
|
400
|
-
})
|
|
401
|
-
})
|
|
402
|
-
})
|
|
403
|
-
})
|
|
404
|
-
})
|
|
405
|
-
})
|
|
406
|
-
]
|
|
407
|
-
});
|
|
408
|
-
};
|
|
409
|
-
|
|
410
|
-
export { HomePage };
|
|
@@ -1,280 +0,0 @@
|
|
|
1
|
-
import React, { useRef, useEffect, useState, useCallback } from 'react';
|
|
2
|
-
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
3
|
-
import { CheckCircle } from '@strapi/icons';
|
|
4
|
-
import { Flex, Box, Typography, SingleSelect, SingleSelectOption } from '@strapi/design-system';
|
|
5
|
-
import { unstable_useContentManagerContext, useFetchClient, useQueryParams } from '@strapi/strapi/admin';
|
|
6
|
-
|
|
7
|
-
const PLUGIN_ID = "primershop-status-manager";
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* @type {import('react').FC<{ setPlugin: (id: string) => void }>}
|
|
11
|
-
*/ const Initializer = ({ setPlugin })=>{
|
|
12
|
-
const ref = useRef(setPlugin);
|
|
13
|
-
useEffect(()=>{
|
|
14
|
-
ref.current(PLUGIN_ID);
|
|
15
|
-
}, []);
|
|
16
|
-
return null;
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
const PluginIcon = ()=>/*#__PURE__*/ jsx(CheckCircle, {});
|
|
20
|
-
|
|
21
|
-
const ProductStatusField = ()=>{
|
|
22
|
-
const { contentType, id } = unstable_useContentManagerContext();
|
|
23
|
-
const [statuses, setStatuses] = useState([]);
|
|
24
|
-
const [currentStatus, setCurrentStatus] = useState("");
|
|
25
|
-
const [message, setMessage] = useState("");
|
|
26
|
-
const { get, put } = useFetchClient();
|
|
27
|
-
const handleStatusChange = useCallback(async (newStatus)=>{
|
|
28
|
-
if (!id) {
|
|
29
|
-
setMessage("Save the product first and then change the status");
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
try {
|
|
33
|
-
await put(`primershop-status-manager/content-status`, {
|
|
34
|
-
contentTypeUid: "api::product.product",
|
|
35
|
-
contentDocumentId: id,
|
|
36
|
-
statusId: statuses.find((status)=>status.name === newStatus)?.documentId
|
|
37
|
-
});
|
|
38
|
-
setMessage(`Status updated ${currentStatus ? `from ${currentStatus}` : ""} to ${newStatus}`);
|
|
39
|
-
setCurrentStatus(newStatus || "");
|
|
40
|
-
} catch (error) {
|
|
41
|
-
setMessage("Error updating status");
|
|
42
|
-
console.error("Error updating status:", error);
|
|
43
|
-
}
|
|
44
|
-
}, [
|
|
45
|
-
id,
|
|
46
|
-
statuses,
|
|
47
|
-
currentStatus,
|
|
48
|
-
put
|
|
49
|
-
]);
|
|
50
|
-
useEffect(()=>{
|
|
51
|
-
async function fetchCurrentStatus() {
|
|
52
|
-
try {
|
|
53
|
-
const { data: productData } = await get(`primershop-status-manager/content-status?contentDocumentId=${id}&contentTypeUid=api::product.product`);
|
|
54
|
-
const status = productData?.status;
|
|
55
|
-
if (status && status.name) return setCurrentStatus(status.name);
|
|
56
|
-
if (statuses.length) return handleStatusChange(statuses[0].name);
|
|
57
|
-
} catch (error) {
|
|
58
|
-
console.error("Error fetching product status:", error);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
if (id && !currentStatus.length) fetchCurrentStatus();
|
|
62
|
-
if (!id && statuses.length) setCurrentStatus(statuses[0].name);
|
|
63
|
-
}, [
|
|
64
|
-
id,
|
|
65
|
-
statuses,
|
|
66
|
-
get
|
|
67
|
-
]);
|
|
68
|
-
useEffect(()=>{
|
|
69
|
-
async function fetchStatuses() {
|
|
70
|
-
try {
|
|
71
|
-
const { data } = await get("primershop-status-manager/statuses");
|
|
72
|
-
setStatuses(data);
|
|
73
|
-
} catch (error) {
|
|
74
|
-
console.error("Error fetching statuses:", error);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
fetchStatuses();
|
|
78
|
-
}, [
|
|
79
|
-
get
|
|
80
|
-
]);
|
|
81
|
-
return /*#__PURE__*/ jsxs(Flex, {
|
|
82
|
-
direction: "column",
|
|
83
|
-
justifyContent: "center",
|
|
84
|
-
alignItems: "stretch",
|
|
85
|
-
width: "100%",
|
|
86
|
-
children: [
|
|
87
|
-
/*#__PURE__*/ jsx(Box, {
|
|
88
|
-
padding: 2,
|
|
89
|
-
children: /*#__PURE__*/ jsxs(Typography, {
|
|
90
|
-
variant: "sigma",
|
|
91
|
-
children: [
|
|
92
|
-
contentType?.info.displayName,
|
|
93
|
-
" status"
|
|
94
|
-
]
|
|
95
|
-
})
|
|
96
|
-
}),
|
|
97
|
-
/*#__PURE__*/ jsx(SingleSelect, {
|
|
98
|
-
placeholder: currentStatus,
|
|
99
|
-
onChange: handleStatusChange,
|
|
100
|
-
children: statuses.map((status)=>/*#__PURE__*/ jsx(SingleSelectOption, {
|
|
101
|
-
value: status.name,
|
|
102
|
-
children: status.name
|
|
103
|
-
}, status.documentId))
|
|
104
|
-
}),
|
|
105
|
-
/*#__PURE__*/ jsx(Box, {
|
|
106
|
-
padding: 2,
|
|
107
|
-
children: /*#__PURE__*/ jsx(Typography, {
|
|
108
|
-
variant: "sigma",
|
|
109
|
-
children: message
|
|
110
|
-
})
|
|
111
|
-
})
|
|
112
|
-
]
|
|
113
|
-
});
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
const StatusCell = ({ row })=>{
|
|
117
|
-
const [status, setStatus] = useState(null);
|
|
118
|
-
useEffect(()=>{
|
|
119
|
-
setStatus(row.statusField);
|
|
120
|
-
}, [
|
|
121
|
-
row
|
|
122
|
-
]);
|
|
123
|
-
if (!status) return null;
|
|
124
|
-
return /*#__PURE__*/ jsx("span", {
|
|
125
|
-
style: {
|
|
126
|
-
padding: "4px 8px",
|
|
127
|
-
borderRadius: 4,
|
|
128
|
-
background: status.published ? "#eafbe7" : "#f0f0ff",
|
|
129
|
-
color: status.published ? "#2f6846" : "#271fe0",
|
|
130
|
-
border: `1px solid ${status.published ? "#2f6846" : "#271fe0"}`,
|
|
131
|
-
fontSize: 14
|
|
132
|
-
},
|
|
133
|
-
children: status.name
|
|
134
|
-
});
|
|
135
|
-
};
|
|
136
|
-
|
|
137
|
-
const addStatusColumnHook = ({ displayedHeaders, layout })=>{
|
|
138
|
-
const statusHeader = {
|
|
139
|
-
attribute: {
|
|
140
|
-
type: "custom"
|
|
141
|
-
},
|
|
142
|
-
name: "statusLabel",
|
|
143
|
-
label: {
|
|
144
|
-
id: "primershop-status-manager.status",
|
|
145
|
-
defaultMessage: "Status"
|
|
146
|
-
},
|
|
147
|
-
searchable: false,
|
|
148
|
-
sortable: false,
|
|
149
|
-
cellFormatter: (row)=>{
|
|
150
|
-
return React.createElement(StatusCell, {
|
|
151
|
-
row
|
|
152
|
-
});
|
|
153
|
-
}
|
|
154
|
-
};
|
|
155
|
-
return {
|
|
156
|
-
displayedHeaders: [
|
|
157
|
-
...displayedHeaders,
|
|
158
|
-
statusHeader
|
|
159
|
-
],
|
|
160
|
-
layout
|
|
161
|
-
};
|
|
162
|
-
};
|
|
163
|
-
|
|
164
|
-
/**
|
|
165
|
-
* Admin permission actions for use in addMenuLink, Page.Protect, and useRBAC.
|
|
166
|
-
* Action IDs must match uids registered in server bootstrap (registerMany).
|
|
167
|
-
*/ const pluginPermissions = {
|
|
168
|
-
accessStatusManager: [
|
|
169
|
-
{
|
|
170
|
-
action: "plugin::primershop-status-manager.main",
|
|
171
|
-
subject: null
|
|
172
|
-
}
|
|
173
|
-
]
|
|
174
|
-
};
|
|
175
|
-
|
|
176
|
-
const StatusFilter = ()=>{
|
|
177
|
-
const { contentType } = unstable_useContentManagerContext();
|
|
178
|
-
const [statuses, setStatuses] = useState([]);
|
|
179
|
-
const [selected, setSelected] = useState("");
|
|
180
|
-
const { get } = useFetchClient();
|
|
181
|
-
const [{ query }, setQuery] = useQueryParams();
|
|
182
|
-
const handleStatusChange = useCallback((name)=>{
|
|
183
|
-
setQuery({
|
|
184
|
-
page: 1,
|
|
185
|
-
plugins: {
|
|
186
|
-
...query.plugins,
|
|
187
|
-
"primershop-status-manager": {
|
|
188
|
-
statusName: name.toLowerCase()
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
}, "push", true);
|
|
192
|
-
}, [
|
|
193
|
-
query.plugins,
|
|
194
|
-
setQuery
|
|
195
|
-
]);
|
|
196
|
-
useEffect(()=>{
|
|
197
|
-
const selectedStatusName = query.plugins?.["primershop-status-manager"]?.statusName;
|
|
198
|
-
if (!selectedStatusName) return;
|
|
199
|
-
const status = statuses.find((status)=>status.name.toLowerCase() === selectedStatusName);
|
|
200
|
-
if (status) {
|
|
201
|
-
setSelected(status.name);
|
|
202
|
-
}
|
|
203
|
-
}, [
|
|
204
|
-
query,
|
|
205
|
-
statuses
|
|
206
|
-
]);
|
|
207
|
-
useEffect(()=>{
|
|
208
|
-
async function fetchStatuses() {
|
|
209
|
-
try {
|
|
210
|
-
const { data } = await get("primershop-status-manager/statuses");
|
|
211
|
-
const allStatusesObject = {
|
|
212
|
-
documentId: "all",
|
|
213
|
-
name: "All"
|
|
214
|
-
};
|
|
215
|
-
setStatuses([
|
|
216
|
-
allStatusesObject,
|
|
217
|
-
...data
|
|
218
|
-
]);
|
|
219
|
-
} catch (error) {
|
|
220
|
-
console.error("Error fetching statuses:", error);
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
fetchStatuses();
|
|
224
|
-
}, [
|
|
225
|
-
get
|
|
226
|
-
]);
|
|
227
|
-
return /*#__PURE__*/ jsx(Flex, {
|
|
228
|
-
direction: "column",
|
|
229
|
-
justifyContent: "center",
|
|
230
|
-
children: /*#__PURE__*/ jsx(SingleSelect, {
|
|
231
|
-
size: "S",
|
|
232
|
-
placeholder: `${contentType?.info.displayName} status`,
|
|
233
|
-
value: selected,
|
|
234
|
-
onChange: handleStatusChange,
|
|
235
|
-
children: statuses.map((status)=>/*#__PURE__*/ jsx(SingleSelectOption, {
|
|
236
|
-
value: status.name,
|
|
237
|
-
children: status.name
|
|
238
|
-
}, status.documentId))
|
|
239
|
-
})
|
|
240
|
-
});
|
|
241
|
-
};
|
|
242
|
-
|
|
243
|
-
const plugin = {
|
|
244
|
-
register (app) {
|
|
245
|
-
app.registerPlugin({
|
|
246
|
-
id: PLUGIN_ID,
|
|
247
|
-
initializer: Initializer,
|
|
248
|
-
isReady: true,
|
|
249
|
-
name: PLUGIN_ID
|
|
250
|
-
});
|
|
251
|
-
app.addMenuLink({
|
|
252
|
-
to: `plugins/${PLUGIN_ID}`,
|
|
253
|
-
icon: PluginIcon,
|
|
254
|
-
intlLabel: {
|
|
255
|
-
id: `${PLUGIN_ID}.plugin.name`,
|
|
256
|
-
defaultMessage: "Status manager"
|
|
257
|
-
},
|
|
258
|
-
permissions: [
|
|
259
|
-
pluginPermissions.accessStatusManager[0]
|
|
260
|
-
],
|
|
261
|
-
Component: ()=>import('./HomePage-Dx9N0awm.mjs').then((module)=>({
|
|
262
|
-
default: module.HomePage
|
|
263
|
-
}))
|
|
264
|
-
});
|
|
265
|
-
},
|
|
266
|
-
bootstrap (app) {
|
|
267
|
-
app.getPlugin("content-manager").injectComponent("editView", "right-links", {
|
|
268
|
-
name: "Status",
|
|
269
|
-
Component: ProductStatusField
|
|
270
|
-
});
|
|
271
|
-
app.registerHook('Admin/CM/pages/ListView/inject-column-in-table', addStatusColumnHook);
|
|
272
|
-
const contentManager = app.getPlugin('content-manager');
|
|
273
|
-
contentManager.injectComponent('listView', 'actions', {
|
|
274
|
-
name: 'status-filter',
|
|
275
|
-
Component: StatusFilter
|
|
276
|
-
});
|
|
277
|
-
}
|
|
278
|
-
};
|
|
279
|
-
|
|
280
|
-
export { plugin as a, pluginPermissions as p };
|