@vonaffenfels/contentful-teasermanager 1.2.0 → 1.2.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
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vonaffenfels/contentful-teasermanager",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.2",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"prepublish": "yarn run build",
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
"classnames": "^2.3.2",
|
|
71
71
|
"clean-webpack-plugin": "^3.0.0",
|
|
72
72
|
"cloudinary": "^1.25.1",
|
|
73
|
-
"contentful-management": "^
|
|
73
|
+
"contentful-management": "^11",
|
|
74
74
|
"copy-webpack-plugin": "^8.1.1",
|
|
75
75
|
"cross-env": "^7.0.3",
|
|
76
76
|
"css-loader": "^5.2.4",
|
|
@@ -98,9 +98,10 @@
|
|
|
98
98
|
},
|
|
99
99
|
"dependencies": {
|
|
100
100
|
"@vonaffenfels/slate-editor": "^1.2.0",
|
|
101
|
+
"contentful-resolve-response": "^1.9.2",
|
|
101
102
|
"webpack": "5.88.2"
|
|
102
103
|
},
|
|
103
|
-
"gitHead": "
|
|
104
|
+
"gitHead": "1e99cab528da01b06334b55df31f21305222e6b8",
|
|
104
105
|
"publishConfig": {
|
|
105
106
|
"access": "public"
|
|
106
107
|
}
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
DndContext, useDraggable, useDroppable,
|
|
11
11
|
PointerSensor, useSensor, useSensors,
|
|
12
12
|
} from '@dnd-kit/core';
|
|
13
|
+
import contentfulResolveResponse from "contentful-resolve-response";
|
|
13
14
|
import {
|
|
14
15
|
useEffect, useState,
|
|
15
16
|
} from "react";
|
|
@@ -52,23 +53,25 @@ export const LogicEditor = (props) => {
|
|
|
52
53
|
const LogicEditorInner = ({
|
|
53
54
|
onSave = () => alert("onSave missing"),
|
|
54
55
|
sdk,
|
|
55
|
-
logicData
|
|
56
|
-
timepoints: [7, 12, 18],
|
|
57
|
-
tags: [],
|
|
58
|
-
},
|
|
56
|
+
logicData,
|
|
59
57
|
selectedTags,
|
|
60
58
|
setSelectedTags,
|
|
61
59
|
}) => {
|
|
62
60
|
const contentfulClient = getContentfulClient();
|
|
63
61
|
const [loading, setLoading] = useState(false);
|
|
64
|
-
const [
|
|
62
|
+
const [tags, setTags] = useState([]);
|
|
63
|
+
const [categories, setCategories] = useState([]);
|
|
65
64
|
const [searchQuery, setSearchQuery] = useState("");
|
|
66
65
|
const [addTimepoint, setAddTimepoint] = useState(7);
|
|
67
66
|
const debouncedSearch = useDebounce(searchQuery, 500);
|
|
68
67
|
const [selectedTimepoints, setSelectedTimepoints] = useState([]);
|
|
69
68
|
useEffect(() => {
|
|
70
|
-
|
|
71
|
-
|
|
69
|
+
if (logicData?.timepoints) {
|
|
70
|
+
setSelectedTimepoints(logicData?.timepoints);
|
|
71
|
+
} else {
|
|
72
|
+
setSelectedTimepoints([7, 12, 18]);
|
|
73
|
+
}
|
|
74
|
+
}, [logicData]);
|
|
72
75
|
const {
|
|
73
76
|
setNodeRef: setOrNodeRef,
|
|
74
77
|
isOver: isOrOver,
|
|
@@ -102,14 +105,48 @@ const LogicEditorInner = ({
|
|
|
102
105
|
"sys.id",
|
|
103
106
|
].join(","),
|
|
104
107
|
};
|
|
108
|
+
const paramsNavigation = {
|
|
109
|
+
limit: 1,
|
|
110
|
+
content_type: "navigation",
|
|
111
|
+
include: 2,
|
|
112
|
+
locale,
|
|
113
|
+
"fields.portal": portal,
|
|
114
|
+
"fields.type": "main",
|
|
115
|
+
};
|
|
105
116
|
|
|
106
117
|
if (debouncedSearch) {
|
|
107
118
|
params["fields.title[match]"] = debouncedSearch;
|
|
108
119
|
}
|
|
109
120
|
|
|
110
|
-
|
|
121
|
+
Promise.all([
|
|
122
|
+
contentfulClient.getEntries(params),
|
|
123
|
+
contentfulClient.getEntries(paramsNavigation).then(async (response) => {
|
|
124
|
+
if (!response?.items?.[0]) {
|
|
125
|
+
return [];
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const references = await sdk.cma.entry.references({entryId: response.items[0].sys.id}, {include: 7});
|
|
129
|
+
const resolved = contentfulResolveResponse(references);
|
|
130
|
+
const allCategories = {};
|
|
131
|
+
|
|
132
|
+
for (const category of resolved) {
|
|
133
|
+
if (!category?.fields?.children?.de) {
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const children = category.fields.children.de || [];
|
|
138
|
+
|
|
139
|
+
for (const child of children) {
|
|
140
|
+
getAllTagsFromCategory(child, allCategories);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return Object.values(allCategories);
|
|
145
|
+
}),
|
|
146
|
+
]).then(([tags, categories]) => {
|
|
111
147
|
setLoading(false);
|
|
112
|
-
|
|
148
|
+
setTags(tags.items);
|
|
149
|
+
setCategories(categories);
|
|
113
150
|
});
|
|
114
151
|
}, [debouncedSearch, portal, locale]);
|
|
115
152
|
|
|
@@ -117,7 +154,7 @@ const LogicEditorInner = ({
|
|
|
117
154
|
const orTags = selectedTags.filter((t) => t.type === "or");
|
|
118
155
|
|
|
119
156
|
return <div className="flex flex-col gap-2 p-4">
|
|
120
|
-
<div className="
|
|
157
|
+
<div className="z-10 flex w-full flex-col gap-4 border-b border-gray-200 bg-white py-4">
|
|
121
158
|
<div className="flex w-full flex-row items-center gap-2" style={{minHeight: 36}}>
|
|
122
159
|
<SectionHeading style={{marginBottom: 0}}>Gewählte Zeitpunkte:</SectionHeading>
|
|
123
160
|
<div className="flex flex-row items-center gap-2">
|
|
@@ -159,53 +196,55 @@ const LogicEditorInner = ({
|
|
|
159
196
|
</div>
|
|
160
197
|
<div className="flex w-full flex-row items-center gap-2" style={{minHeight: 36}}>
|
|
161
198
|
<SectionHeading style={{marginBottom: 0}}>Gewählte Kategorien & Tags:</SectionHeading>
|
|
162
|
-
<div className="grid
|
|
163
|
-
<div>
|
|
164
|
-
<
|
|
199
|
+
<div className="grid grid-cols-2 gap-4">
|
|
200
|
+
<div className="flex flex-col gap-2">
|
|
201
|
+
<div>
|
|
202
|
+
<SectionHeading style={{marginBottom: 0}}>Oder</SectionHeading>
|
|
203
|
+
</div>
|
|
204
|
+
<div
|
|
205
|
+
ref={setOrNodeRef}
|
|
206
|
+
style={{
|
|
207
|
+
minHeight: 36,
|
|
208
|
+
backgroundColor: isOrOver ? "rgba(0, 255, 0, 0.3)" : "transparent",
|
|
209
|
+
}}
|
|
210
|
+
className="flex h-full w-full flex-row flex-wrap gap-2"
|
|
211
|
+
>
|
|
212
|
+
{orTags.map((tag) => {
|
|
213
|
+
return <DraggablePill
|
|
214
|
+
key={tag.id}
|
|
215
|
+
id={tag.id}
|
|
216
|
+
variant="active"
|
|
217
|
+
label={(`${tag.label}`)}
|
|
218
|
+
onClose={() => {
|
|
219
|
+
setSelectedTags(selectedTags.filter((t) => t.id !== tag.id));
|
|
220
|
+
}}
|
|
221
|
+
/>;
|
|
222
|
+
})}
|
|
223
|
+
</div>
|
|
165
224
|
</div>
|
|
166
|
-
<div>
|
|
225
|
+
<div className="flex flex-col gap-2">
|
|
167
226
|
<SectionHeading style={{marginBottom: 0}}>Und</SectionHeading>
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
<div
|
|
190
|
-
ref={setAndNodeRef}
|
|
191
|
-
style={{
|
|
192
|
-
minHeight: 36,
|
|
193
|
-
backgroundColor: isAndOver ? "rgba(0, 255, 0, 0.3)" : "transparent",
|
|
194
|
-
}}
|
|
195
|
-
className="flex w-full flex-row flex-wrap gap-2"
|
|
196
|
-
>
|
|
197
|
-
{andTags.map((tag) => {
|
|
198
|
-
return <DraggablePill
|
|
199
|
-
key={tag.id}
|
|
200
|
-
id={tag.id}
|
|
201
|
-
testId={tag.id}
|
|
202
|
-
variant="active"
|
|
203
|
-
label={(`${tag.label}`)}
|
|
204
|
-
onClose={() => {
|
|
205
|
-
setSelectedTags(selectedTags.filter((t) => t.id !== tag.id));
|
|
206
|
-
}}
|
|
207
|
-
/>;
|
|
208
|
-
})}
|
|
227
|
+
<div
|
|
228
|
+
ref={setAndNodeRef}
|
|
229
|
+
style={{
|
|
230
|
+
minHeight: 36,
|
|
231
|
+
backgroundColor: isAndOver ? "rgba(0, 255, 0, 0.3)" : "transparent",
|
|
232
|
+
}}
|
|
233
|
+
className="flex h-full w-full flex-row flex-wrap gap-2"
|
|
234
|
+
>
|
|
235
|
+
{andTags.map((tag) => {
|
|
236
|
+
return <DraggablePill
|
|
237
|
+
key={tag.id}
|
|
238
|
+
id={tag.id}
|
|
239
|
+
testId={tag.id}
|
|
240
|
+
variant="active"
|
|
241
|
+
label={(`${tag.label}`)}
|
|
242
|
+
onClose={() => {
|
|
243
|
+
setSelectedTags(selectedTags.filter((t) => t.id !== tag.id));
|
|
244
|
+
}}
|
|
245
|
+
/>;
|
|
246
|
+
})}
|
|
247
|
+
</div>
|
|
209
248
|
</div>
|
|
210
249
|
</div>
|
|
211
250
|
</div>
|
|
@@ -217,28 +256,81 @@ const LogicEditorInner = ({
|
|
|
217
256
|
/>
|
|
218
257
|
</div>
|
|
219
258
|
</div>
|
|
220
|
-
<div className="grid grid-cols-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
<
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
259
|
+
<div className="grid grid-cols-2 gap-4 overflow-y-auto">
|
|
260
|
+
<div className="flex flex-col gap-4">
|
|
261
|
+
<div>
|
|
262
|
+
<SectionHeading style={{marginBottom: 0}}>Kategorien</SectionHeading>
|
|
263
|
+
</div>
|
|
264
|
+
<div className="grid grid-cols-3 gap-4">
|
|
265
|
+
{categories?.map((category) => {
|
|
266
|
+
return (
|
|
267
|
+
<Checkbox
|
|
268
|
+
key={category.id}
|
|
269
|
+
isChecked={selectedTags.some((t) => category.tags.some((c) => c.id === t.id) || t.id === category.id)}
|
|
270
|
+
onChange={(e) => {
|
|
271
|
+
let newTags = [...selectedTags];
|
|
272
|
+
|
|
273
|
+
if (e.target.checked) {
|
|
274
|
+
newTags.push({
|
|
275
|
+
label: category.title,
|
|
276
|
+
id: category.id,
|
|
277
|
+
type: "or",
|
|
278
|
+
});
|
|
279
|
+
for (const tag of category.tags) {
|
|
280
|
+
if (!selectedTags.find((t) => t.id === tag.id)) {
|
|
281
|
+
newTags.push({
|
|
282
|
+
label: tag.label,
|
|
283
|
+
id: tag.id,
|
|
284
|
+
type: "or",
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
} else {
|
|
289
|
+
newTags = newTags.filter((t) => t.id !== category.id);
|
|
290
|
+
|
|
291
|
+
for (const tag of category.tags) {
|
|
292
|
+
newTags = newTags.filter((t) => t.id !== tag.id);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
setSelectedTags(newTags);
|
|
297
|
+
}}
|
|
298
|
+
>
|
|
299
|
+
{category.title} ({selectedTags.filter((t) =>
|
|
300
|
+
category.tags.some((c) => c.id === t.id) || t.id === category.id).length}/{category.tags.length + 1})
|
|
301
|
+
</Checkbox>
|
|
302
|
+
);
|
|
303
|
+
})}
|
|
304
|
+
</div>
|
|
305
|
+
</div>
|
|
306
|
+
<div className="flex flex-col gap-4">
|
|
307
|
+
<div>
|
|
308
|
+
<SectionHeading style={{marginBottom: 0}}>Tags</SectionHeading>
|
|
309
|
+
</div>
|
|
310
|
+
<div className="grid grid-cols-3 gap-4">
|
|
311
|
+
{tags?.map((tag) => {
|
|
312
|
+
return (
|
|
313
|
+
<Checkbox
|
|
314
|
+
key={tag.sys.id}
|
|
315
|
+
isChecked={!!selectedTags.find((t) => t.id === tag.sys.id)}
|
|
316
|
+
onChange={(e) => {
|
|
317
|
+
if (e.target.checked) {
|
|
318
|
+
setSelectedTags([...selectedTags, {
|
|
319
|
+
label: tag.fields.title[locale],
|
|
320
|
+
id: tag.sys.id,
|
|
321
|
+
type: "or",
|
|
322
|
+
}]);
|
|
323
|
+
} else {
|
|
324
|
+
setSelectedTags(selectedTags.filter((t) => t.id !== tag.sys.id));
|
|
325
|
+
}
|
|
326
|
+
}}
|
|
327
|
+
>
|
|
328
|
+
{tag.fields.title[locale]}
|
|
329
|
+
</Checkbox>
|
|
330
|
+
);
|
|
331
|
+
})}
|
|
332
|
+
</div>
|
|
333
|
+
</div>
|
|
242
334
|
</div>
|
|
243
335
|
<div className="sticky bottom-0 flex w-full flex-row justify-between gap-2 border-t border-gray-200 bg-white py-4">
|
|
244
336
|
<Button
|
|
@@ -259,6 +351,62 @@ const LogicEditorInner = ({
|
|
|
259
351
|
</div>;
|
|
260
352
|
};
|
|
261
353
|
|
|
354
|
+
function getAllTagsFromCategory(categoryNode, allCategories = {}) {
|
|
355
|
+
if (!categoryNode || !categoryNode.fields?.children) {
|
|
356
|
+
return allCategories;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
const children = categoryNode.fields.children.de || [];
|
|
360
|
+
|
|
361
|
+
allCategories[categoryNode.sys.id] = {
|
|
362
|
+
title: categoryNode.fields.title.de,
|
|
363
|
+
tags: [],
|
|
364
|
+
id: categoryNode.sys.id,
|
|
365
|
+
};
|
|
366
|
+
|
|
367
|
+
if (categoryNode?.fields?.tags?.de) {
|
|
368
|
+
for (const tag of categoryNode.fields.tags.de) {
|
|
369
|
+
if (!tag?.fields?.title) {
|
|
370
|
+
continue;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
if (!allCategories[categoryNode.sys.id].tags.find((c) => c.id === tag.sys.id)) {
|
|
374
|
+
allCategories[categoryNode.sys.id].tags.push({
|
|
375
|
+
label: tag.fields.title.de,
|
|
376
|
+
id: tag.sys.id,
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
for (const child of children) {
|
|
383
|
+
if (!child || !child.fields) {
|
|
384
|
+
continue;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
if (child?.fields?.tags?.de) {
|
|
388
|
+
for (const tag of child.fields.tags.de) {
|
|
389
|
+
if (!allCategories[categoryNode.sys.id].tags.find((c) => c.id === tag.sys.id)) {
|
|
390
|
+
if (!tag?.fields?.title) {
|
|
391
|
+
continue;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
allCategories[categoryNode.sys.id].tags.push({
|
|
395
|
+
label: tag.fields.title.de,
|
|
396
|
+
id: tag.sys.id,
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
getAllTagsFromCategory(child, allCategories);
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
allCategories[categoryNode.sys.id].tags = [...new Set(allCategories[categoryNode.sys.id].tags)];
|
|
406
|
+
|
|
407
|
+
return allCategories;
|
|
408
|
+
}
|
|
409
|
+
|
|
262
410
|
|
|
263
411
|
function DraggablePill({
|
|
264
412
|
id, ...props
|
|
@@ -276,19 +424,21 @@ function DraggablePill({
|
|
|
276
424
|
};
|
|
277
425
|
|
|
278
426
|
return (
|
|
279
|
-
<
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
427
|
+
<div>
|
|
428
|
+
<Pill
|
|
429
|
+
dragHandleComponent={
|
|
430
|
+
<DragHandle
|
|
431
|
+
label="Reorder item"
|
|
432
|
+
variant="transparent"
|
|
433
|
+
{...attributes}
|
|
434
|
+
{...listeners}
|
|
435
|
+
/>
|
|
436
|
+
}
|
|
437
|
+
isDraggable
|
|
438
|
+
ref={setNodeRef}
|
|
439
|
+
style={style}
|
|
440
|
+
{...props}
|
|
441
|
+
/>
|
|
442
|
+
</div>
|
|
293
443
|
);
|
|
294
444
|
}
|