@vonaffenfels/contentful-teasermanager 1.2.32 → 1.2.41
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/.babelrc +19 -19
- package/dist/TestStory.js +94 -0
- package/dist/TestStory2.js +94 -0
- package/dist/TestStory3.js +94 -0
- package/dist/index.html +12 -0
- package/dist/index.js +120203 -0
- package/jest.config.js +8 -8
- package/package.json +3 -3
- package/postcss.config.js +6 -6
- package/src/components/Contentful/ConfigScreen.js +154 -154
- package/src/components/Contentful/Dialog/LogicEditor.js +602 -602
- package/src/components/Contentful/Dialog/NewestArticles.js +198 -198
- package/src/components/Contentful/Dialog.js +87 -87
- package/src/components/Contentful/EntryEditor.js +196 -196
- package/src/components/Contentful/Page.js +9 -9
- package/src/components/NoAccess.js +12 -12
- package/src/components/Teasermanager/Timeline.js +179 -179
- package/src/components/Teasermanager/Timeline.module.css +89 -89
- package/src/components/Teasermanager.js +269 -269
- package/src/components/Teasermanager.module.css +137 -137
- package/src/dev.js +5 -5
- package/src/hooks/useDebounce.js +20 -20
- package/src/hooks/useOnScreen.js +23 -23
- package/src/icons/remove.svg +7 -7
- package/src/index.html +11 -11
- package/src/index.js +51 -51
- package/src/lib/contentfulClient.js +12 -12
- package/src/lib/runLoaders.js +46 -46
- package/src/queryFromLogic.test.js +148 -148
- package/src/scss/index.scss +11 -11
- package/src/utils/germanTimezoneOffset.js +35 -35
- package/src/utils/germanTimezoneOffset.test.js +51 -51
- package/tailwind.config.js +5 -5
- package/webpack.config.dev.js +25 -25
- package/webpack.config.js +174 -174
|
@@ -1,269 +1,269 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
useEffect, useRef, useState,
|
|
3
|
-
} from "react";
|
|
4
|
-
|
|
5
|
-
import {getContentfulClient} from "../lib/contentfulClient";
|
|
6
|
-
import Renderer from "@vonaffenfels/slate-editor/dist/Renderer";
|
|
7
|
-
import componentLoader from "@vonaffenfels/slate-editor/componentLoader";
|
|
8
|
-
import {Timeline} from "./Teasermanager/Timeline";
|
|
9
|
-
import styles from "./Teasermanager.module.css";
|
|
10
|
-
import {runLoaders} from "../lib/runLoaders";
|
|
11
|
-
import classNames from "classnames";
|
|
12
|
-
|
|
13
|
-
export const Teasermanager = ({
|
|
14
|
-
entryId,
|
|
15
|
-
loadSlotStateForPage = () => console.error("missing loadSlotStateForPage"),
|
|
16
|
-
loadTimelineStateForPage = () => console.error("missing loadTimelineStateForPage"),
|
|
17
|
-
onSlotClick = async () => console.error("missing onSlotClick"),
|
|
18
|
-
onSlotClickLogic = async () => console.error("missing onSlotClickLogic"),
|
|
19
|
-
removeSlotData = async () => console.error("missing removeSlotData"),
|
|
20
|
-
contentFieldName = "content",
|
|
21
|
-
locale = "de",
|
|
22
|
-
}) => {
|
|
23
|
-
const contentfulClient = getContentfulClient();
|
|
24
|
-
const [entry, setEntry] = useState(null);
|
|
25
|
-
const wrapperRef = useRef(null);
|
|
26
|
-
const [loading, setLoading] = useState("initial");
|
|
27
|
-
const [loadedContent, setLoadedContent] = useState(null);
|
|
28
|
-
const [currentDate, _setCurrentDate] = useState(null);
|
|
29
|
-
const [currentSlotState, setCurrentSlotState] = useState(null);
|
|
30
|
-
const [currentSlotLogicState, setCurrentSlotLogicState] = useState(null);
|
|
31
|
-
const currentLoadingOperation = useRef(0);
|
|
32
|
-
|
|
33
|
-
const setCurrentDate = (date) => {
|
|
34
|
-
if (date) {
|
|
35
|
-
date.setSeconds(0);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
_setCurrentDate(date);
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
const reloadAllData = async () => {
|
|
42
|
-
let loadingId = ++currentLoadingOperation.current;
|
|
43
|
-
if (!currentDate) {
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const contentValue = entry?.fields?.[contentFieldName]?.[locale];
|
|
48
|
-
const portalValue = entry?.fields?.portal?.[locale];
|
|
49
|
-
|
|
50
|
-
if (!contentValue) {
|
|
51
|
-
setLoading("initial");
|
|
52
|
-
setLoadedContent(null);
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
console.log(`Teasermanager :: LOADING DATA`);
|
|
57
|
-
if (loading !== "initial") {
|
|
58
|
-
setLoading(true);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const content = await runLoaders(
|
|
62
|
-
contentValue, portalValue, entry?.sys?.id, currentDate,
|
|
63
|
-
);
|
|
64
|
-
|
|
65
|
-
// only apply the LAST update
|
|
66
|
-
if (currentLoadingOperation.current === loadingId) {
|
|
67
|
-
updateSlotStateData();
|
|
68
|
-
|
|
69
|
-
console.log(`Teasermanager :: LOADED DATA`);
|
|
70
|
-
setLoadedContent(content);
|
|
71
|
-
setLoading(false);
|
|
72
|
-
}
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
const initSlot = (node) => {
|
|
76
|
-
const existingManagementNode = node.querySelector(`.__teasermanager_management_node`);
|
|
77
|
-
if (existingManagementNode) {
|
|
78
|
-
node.removeChild(existingManagementNode);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
const slotId = node.dataset.teasermanagerSlot;
|
|
82
|
-
const managementNode = document.createElement("div");
|
|
83
|
-
managementNode.classList.add(styles.management);
|
|
84
|
-
|
|
85
|
-
const managementLabelNode = document.createElement("div");
|
|
86
|
-
managementLabelNode.classList.add(styles.label);
|
|
87
|
-
const managementLabelNodeLogic = document.createElement("div");
|
|
88
|
-
managementLabelNodeLogic.classList.add(styles.labelLogic);
|
|
89
|
-
|
|
90
|
-
if (currentSlotState?.[slotId]) {
|
|
91
|
-
managementNode.classList.add(styles.changedBorder);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
if (currentSlotLogicState?.[slotId]) {
|
|
95
|
-
managementNode.classList.add(styles.logicBorder);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
if (currentSlotState?.[slotId] && currentSlotState?.[slotId] !== "RESET") {
|
|
99
|
-
managementNode.classList.add(styles.changed);
|
|
100
|
-
|
|
101
|
-
managementLabelNode.innerHTML = `Artikel wechseln`;
|
|
102
|
-
const managementRemoveButtonNode = document.createElement("div");
|
|
103
|
-
managementRemoveButtonNode.classList.add(styles.removeButton);
|
|
104
|
-
managementRemoveButtonNode.title = `Artikel entfernen`;
|
|
105
|
-
managementRemoveButtonNode.innerHTML = `
|
|
106
|
-
<svg height="800px" width="800px" version="1.1" style="width: 20px; height: 20px;" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 496.158 496.158" xml:space="preserve">
|
|
107
|
-
<path style="fill:#E04F5F;" d="M0,248.085C0,111.063,111.069,0.003,248.075,0.003c137.013,0,248.083,111.061,248.083,248.082
|
|
108
|
-
\tc0,137.002-111.07,248.07-248.083,248.07C111.069,496.155,0,385.087,0,248.085z"/>
|
|
109
|
-
<path style="fill:#FFFFFF;" d="M383.546,206.286H112.612c-3.976,0-7.199,3.225-7.199,7.2v69.187c0,3.976,3.224,7.199,7.199,7.199
|
|
110
|
-
\th270.934c3.976,0,7.199-3.224,7.199-7.199v-69.187C390.745,209.511,387.521,206.286,383.546,206.286z"/>
|
|
111
|
-
</svg>
|
|
112
|
-
`;
|
|
113
|
-
managementRemoveButtonNode.addEventListener("click", (e) => {
|
|
114
|
-
removeSlotData(slotId, currentDate).then(() => {
|
|
115
|
-
managementNode.classList.add(styles.loading);
|
|
116
|
-
reloadAllData().then(() => {
|
|
117
|
-
// DONT remove, in case multiple loading operations are running we want the state to stay loading :)
|
|
118
|
-
// managementNode.classList.remove(styles.loading);
|
|
119
|
-
});
|
|
120
|
-
});
|
|
121
|
-
e.preventDefault();
|
|
122
|
-
e.stopPropagation();
|
|
123
|
-
return false;
|
|
124
|
-
});
|
|
125
|
-
managementNode.appendChild(managementRemoveButtonNode);
|
|
126
|
-
} else {
|
|
127
|
-
managementLabelNode.innerHTML = `Artikel festlegen`;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
if (currentSlotLogicState?.[slotId]) {
|
|
131
|
-
managementLabelNodeLogic.innerHTML = `Logik bearbeiten`;
|
|
132
|
-
} else {
|
|
133
|
-
managementLabelNodeLogic.innerHTML = `Logik festlegen`;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
managementNode.appendChild(managementLabelNode);
|
|
137
|
-
managementNode.appendChild(managementLabelNodeLogic);
|
|
138
|
-
managementLabelNode.addEventListener("click", (e) => {
|
|
139
|
-
onSlotClick(slotId, currentDate).then((entry) => {
|
|
140
|
-
if (!entry) {
|
|
141
|
-
return; // nothing changed, no need to reload!
|
|
142
|
-
}
|
|
143
|
-
managementNode.classList.add(styles.loading);
|
|
144
|
-
reloadAllData().then(() => {
|
|
145
|
-
// DONT remove, in case multiple loading operations are running we want the state to stay loading :)
|
|
146
|
-
// managementNode.classList.remove(styles.loading);
|
|
147
|
-
});
|
|
148
|
-
});
|
|
149
|
-
e.preventDefault();
|
|
150
|
-
e.stopPropagation();
|
|
151
|
-
return false;
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
managementLabelNodeLogic.addEventListener("click", (e) => {
|
|
155
|
-
onSlotClickLogic(slotId, currentDate).then(() => {
|
|
156
|
-
managementNode.classList.add(styles.loading);
|
|
157
|
-
reloadAllData().then(() => {
|
|
158
|
-
// DONT remove, in case multiple loading operations are running we want the state to stay loading :)
|
|
159
|
-
// managementNode.classList.remove(styles.loading);
|
|
160
|
-
});
|
|
161
|
-
});
|
|
162
|
-
e.preventDefault();
|
|
163
|
-
e.stopPropagation();
|
|
164
|
-
return false;
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
managementNode.classList.add("__teasermanager_management_node");
|
|
169
|
-
node.appendChild(managementNode);
|
|
170
|
-
};
|
|
171
|
-
|
|
172
|
-
const updateSlots = (mutationList) => {
|
|
173
|
-
if (!mutationList) {
|
|
174
|
-
// update all slots
|
|
175
|
-
const slots = wrapperRef.current.querySelectorAll(`*[data-teasermanager-slot]`);
|
|
176
|
-
slots.forEach(initSlot);
|
|
177
|
-
console.log(`Teasermanager :: UPDATE ALL SLOTS`);
|
|
178
|
-
} else {
|
|
179
|
-
// update only if the change was not a management node
|
|
180
|
-
const isValidUpdate = mutationList?.find(mutation => {
|
|
181
|
-
if (mutation.type === "childList") {
|
|
182
|
-
const removedNonManagementNode = [...mutation.removedNodes]?.find(node => !node.classList.contains("__teasermanager_management_node"));
|
|
183
|
-
const addedNonManagementNode = [...mutation.addedNodes]?.find(node => !node.classList.contains("__teasermanager_management_node"));
|
|
184
|
-
|
|
185
|
-
if (!removedNonManagementNode && !addedNonManagementNode) {
|
|
186
|
-
return false;
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
return true;
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
if (isValidUpdate) {
|
|
194
|
-
updateSlots();
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
};
|
|
198
|
-
|
|
199
|
-
useEffect(() => {
|
|
200
|
-
if (!entryId || entry) {
|
|
201
|
-
setEntry(null);
|
|
202
|
-
return;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
contentfulClient.getEntry(entryId).then((loadedEntry, b) => {
|
|
206
|
-
setEntry(loadedEntry);
|
|
207
|
-
});
|
|
208
|
-
}, [entryId]);
|
|
209
|
-
|
|
210
|
-
useEffect(() => {
|
|
211
|
-
if (!wrapperRef.current) {
|
|
212
|
-
return;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
const observer = new MutationObserver(updateSlots);
|
|
216
|
-
observer.observe(wrapperRef.current, {
|
|
217
|
-
attributes: false,
|
|
218
|
-
childList: true,
|
|
219
|
-
subtree: true,
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
return () => {
|
|
223
|
-
observer.disconnect();
|
|
224
|
-
};
|
|
225
|
-
}, [wrapperRef, currentDate, currentSlotState, onSlotClick, removeSlotData, reloadAllData]);
|
|
226
|
-
|
|
227
|
-
const updateSlotStateData = async () => {
|
|
228
|
-
try {
|
|
229
|
-
if (!currentDate) {
|
|
230
|
-
return;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
const {
|
|
234
|
-
data,
|
|
235
|
-
logicData,
|
|
236
|
-
} = await loadSlotStateForPage(currentDate);
|
|
237
|
-
|
|
238
|
-
setCurrentSlotState(data);
|
|
239
|
-
setCurrentSlotLogicState(logicData);
|
|
240
|
-
} catch (e) {
|
|
241
|
-
console.error(e);
|
|
242
|
-
}
|
|
243
|
-
};
|
|
244
|
-
|
|
245
|
-
useEffect(() => {
|
|
246
|
-
updateSlots();
|
|
247
|
-
}, [currentSlotState]);
|
|
248
|
-
|
|
249
|
-
useEffect(() => {
|
|
250
|
-
reloadAllData();
|
|
251
|
-
}, [contentFieldName, locale, entry, currentDate]);
|
|
252
|
-
|
|
253
|
-
return <div className="flex w-full flex-col">
|
|
254
|
-
<div className="w-full">
|
|
255
|
-
<Timeline
|
|
256
|
-
currentDate={currentDate}
|
|
257
|
-
setCurrentDate={setCurrentDate}
|
|
258
|
-
loadTimelineStateForPage={loadTimelineStateForPage}/>
|
|
259
|
-
</div>
|
|
260
|
-
<div className={classNames(styles.wrapper, {[styles.loading]: loading === "initial"})} ref={wrapperRef}>
|
|
261
|
-
{!!loadedContent && loading !== "initial" &&
|
|
262
|
-
<Renderer
|
|
263
|
-
value={loadedContent}
|
|
264
|
-
storybookComponentLoader={componentLoader}
|
|
265
|
-
/>
|
|
266
|
-
}
|
|
267
|
-
</div>
|
|
268
|
-
</div>;
|
|
269
|
-
};
|
|
1
|
+
import React, {
|
|
2
|
+
useEffect, useRef, useState,
|
|
3
|
+
} from "react";
|
|
4
|
+
|
|
5
|
+
import {getContentfulClient} from "../lib/contentfulClient";
|
|
6
|
+
import Renderer from "@vonaffenfels/slate-editor/dist/Renderer";
|
|
7
|
+
import componentLoader from "@vonaffenfels/slate-editor/componentLoader";
|
|
8
|
+
import {Timeline} from "./Teasermanager/Timeline";
|
|
9
|
+
import styles from "./Teasermanager.module.css";
|
|
10
|
+
import {runLoaders} from "../lib/runLoaders";
|
|
11
|
+
import classNames from "classnames";
|
|
12
|
+
|
|
13
|
+
export const Teasermanager = ({
|
|
14
|
+
entryId,
|
|
15
|
+
loadSlotStateForPage = () => console.error("missing loadSlotStateForPage"),
|
|
16
|
+
loadTimelineStateForPage = () => console.error("missing loadTimelineStateForPage"),
|
|
17
|
+
onSlotClick = async () => console.error("missing onSlotClick"),
|
|
18
|
+
onSlotClickLogic = async () => console.error("missing onSlotClickLogic"),
|
|
19
|
+
removeSlotData = async () => console.error("missing removeSlotData"),
|
|
20
|
+
contentFieldName = "content",
|
|
21
|
+
locale = "de",
|
|
22
|
+
}) => {
|
|
23
|
+
const contentfulClient = getContentfulClient();
|
|
24
|
+
const [entry, setEntry] = useState(null);
|
|
25
|
+
const wrapperRef = useRef(null);
|
|
26
|
+
const [loading, setLoading] = useState("initial");
|
|
27
|
+
const [loadedContent, setLoadedContent] = useState(null);
|
|
28
|
+
const [currentDate, _setCurrentDate] = useState(null);
|
|
29
|
+
const [currentSlotState, setCurrentSlotState] = useState(null);
|
|
30
|
+
const [currentSlotLogicState, setCurrentSlotLogicState] = useState(null);
|
|
31
|
+
const currentLoadingOperation = useRef(0);
|
|
32
|
+
|
|
33
|
+
const setCurrentDate = (date) => {
|
|
34
|
+
if (date) {
|
|
35
|
+
date.setSeconds(0);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
_setCurrentDate(date);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const reloadAllData = async () => {
|
|
42
|
+
let loadingId = ++currentLoadingOperation.current;
|
|
43
|
+
if (!currentDate) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const contentValue = entry?.fields?.[contentFieldName]?.[locale];
|
|
48
|
+
const portalValue = entry?.fields?.portal?.[locale];
|
|
49
|
+
|
|
50
|
+
if (!contentValue) {
|
|
51
|
+
setLoading("initial");
|
|
52
|
+
setLoadedContent(null);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
console.log(`Teasermanager :: LOADING DATA`);
|
|
57
|
+
if (loading !== "initial") {
|
|
58
|
+
setLoading(true);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const content = await runLoaders(
|
|
62
|
+
contentValue, portalValue, entry?.sys?.id, currentDate,
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
// only apply the LAST update
|
|
66
|
+
if (currentLoadingOperation.current === loadingId) {
|
|
67
|
+
updateSlotStateData();
|
|
68
|
+
|
|
69
|
+
console.log(`Teasermanager :: LOADED DATA`);
|
|
70
|
+
setLoadedContent(content);
|
|
71
|
+
setLoading(false);
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const initSlot = (node) => {
|
|
76
|
+
const existingManagementNode = node.querySelector(`.__teasermanager_management_node`);
|
|
77
|
+
if (existingManagementNode) {
|
|
78
|
+
node.removeChild(existingManagementNode);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const slotId = node.dataset.teasermanagerSlot;
|
|
82
|
+
const managementNode = document.createElement("div");
|
|
83
|
+
managementNode.classList.add(styles.management);
|
|
84
|
+
|
|
85
|
+
const managementLabelNode = document.createElement("div");
|
|
86
|
+
managementLabelNode.classList.add(styles.label);
|
|
87
|
+
const managementLabelNodeLogic = document.createElement("div");
|
|
88
|
+
managementLabelNodeLogic.classList.add(styles.labelLogic);
|
|
89
|
+
|
|
90
|
+
if (currentSlotState?.[slotId]) {
|
|
91
|
+
managementNode.classList.add(styles.changedBorder);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (currentSlotLogicState?.[slotId]) {
|
|
95
|
+
managementNode.classList.add(styles.logicBorder);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (currentSlotState?.[slotId] && currentSlotState?.[slotId] !== "RESET") {
|
|
99
|
+
managementNode.classList.add(styles.changed);
|
|
100
|
+
|
|
101
|
+
managementLabelNode.innerHTML = `Artikel wechseln`;
|
|
102
|
+
const managementRemoveButtonNode = document.createElement("div");
|
|
103
|
+
managementRemoveButtonNode.classList.add(styles.removeButton);
|
|
104
|
+
managementRemoveButtonNode.title = `Artikel entfernen`;
|
|
105
|
+
managementRemoveButtonNode.innerHTML = `
|
|
106
|
+
<svg height="800px" width="800px" version="1.1" style="width: 20px; height: 20px;" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 496.158 496.158" xml:space="preserve">
|
|
107
|
+
<path style="fill:#E04F5F;" d="M0,248.085C0,111.063,111.069,0.003,248.075,0.003c137.013,0,248.083,111.061,248.083,248.082
|
|
108
|
+
\tc0,137.002-111.07,248.07-248.083,248.07C111.069,496.155,0,385.087,0,248.085z"/>
|
|
109
|
+
<path style="fill:#FFFFFF;" d="M383.546,206.286H112.612c-3.976,0-7.199,3.225-7.199,7.2v69.187c0,3.976,3.224,7.199,7.199,7.199
|
|
110
|
+
\th270.934c3.976,0,7.199-3.224,7.199-7.199v-69.187C390.745,209.511,387.521,206.286,383.546,206.286z"/>
|
|
111
|
+
</svg>
|
|
112
|
+
`;
|
|
113
|
+
managementRemoveButtonNode.addEventListener("click", (e) => {
|
|
114
|
+
removeSlotData(slotId, currentDate).then(() => {
|
|
115
|
+
managementNode.classList.add(styles.loading);
|
|
116
|
+
reloadAllData().then(() => {
|
|
117
|
+
// DONT remove, in case multiple loading operations are running we want the state to stay loading :)
|
|
118
|
+
// managementNode.classList.remove(styles.loading);
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
e.preventDefault();
|
|
122
|
+
e.stopPropagation();
|
|
123
|
+
return false;
|
|
124
|
+
});
|
|
125
|
+
managementNode.appendChild(managementRemoveButtonNode);
|
|
126
|
+
} else {
|
|
127
|
+
managementLabelNode.innerHTML = `Artikel festlegen`;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (currentSlotLogicState?.[slotId]) {
|
|
131
|
+
managementLabelNodeLogic.innerHTML = `Logik bearbeiten`;
|
|
132
|
+
} else {
|
|
133
|
+
managementLabelNodeLogic.innerHTML = `Logik festlegen`;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
managementNode.appendChild(managementLabelNode);
|
|
137
|
+
managementNode.appendChild(managementLabelNodeLogic);
|
|
138
|
+
managementLabelNode.addEventListener("click", (e) => {
|
|
139
|
+
onSlotClick(slotId, currentDate).then((entry) => {
|
|
140
|
+
if (!entry) {
|
|
141
|
+
return; // nothing changed, no need to reload!
|
|
142
|
+
}
|
|
143
|
+
managementNode.classList.add(styles.loading);
|
|
144
|
+
reloadAllData().then(() => {
|
|
145
|
+
// DONT remove, in case multiple loading operations are running we want the state to stay loading :)
|
|
146
|
+
// managementNode.classList.remove(styles.loading);
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
e.preventDefault();
|
|
150
|
+
e.stopPropagation();
|
|
151
|
+
return false;
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
managementLabelNodeLogic.addEventListener("click", (e) => {
|
|
155
|
+
onSlotClickLogic(slotId, currentDate).then(() => {
|
|
156
|
+
managementNode.classList.add(styles.loading);
|
|
157
|
+
reloadAllData().then(() => {
|
|
158
|
+
// DONT remove, in case multiple loading operations are running we want the state to stay loading :)
|
|
159
|
+
// managementNode.classList.remove(styles.loading);
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
e.preventDefault();
|
|
163
|
+
e.stopPropagation();
|
|
164
|
+
return false;
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
managementNode.classList.add("__teasermanager_management_node");
|
|
169
|
+
node.appendChild(managementNode);
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
const updateSlots = (mutationList) => {
|
|
173
|
+
if (!mutationList) {
|
|
174
|
+
// update all slots
|
|
175
|
+
const slots = wrapperRef.current.querySelectorAll(`*[data-teasermanager-slot]`);
|
|
176
|
+
slots.forEach(initSlot);
|
|
177
|
+
console.log(`Teasermanager :: UPDATE ALL SLOTS`);
|
|
178
|
+
} else {
|
|
179
|
+
// update only if the change was not a management node
|
|
180
|
+
const isValidUpdate = mutationList?.find(mutation => {
|
|
181
|
+
if (mutation.type === "childList") {
|
|
182
|
+
const removedNonManagementNode = [...mutation.removedNodes]?.find(node => !node.classList.contains("__teasermanager_management_node"));
|
|
183
|
+
const addedNonManagementNode = [...mutation.addedNodes]?.find(node => !node.classList.contains("__teasermanager_management_node"));
|
|
184
|
+
|
|
185
|
+
if (!removedNonManagementNode && !addedNonManagementNode) {
|
|
186
|
+
return false;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return true;
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
if (isValidUpdate) {
|
|
194
|
+
updateSlots();
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
useEffect(() => {
|
|
200
|
+
if (!entryId || entry) {
|
|
201
|
+
setEntry(null);
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
contentfulClient.getEntry(entryId).then((loadedEntry, b) => {
|
|
206
|
+
setEntry(loadedEntry);
|
|
207
|
+
});
|
|
208
|
+
}, [entryId]);
|
|
209
|
+
|
|
210
|
+
useEffect(() => {
|
|
211
|
+
if (!wrapperRef.current) {
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const observer = new MutationObserver(updateSlots);
|
|
216
|
+
observer.observe(wrapperRef.current, {
|
|
217
|
+
attributes: false,
|
|
218
|
+
childList: true,
|
|
219
|
+
subtree: true,
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
return () => {
|
|
223
|
+
observer.disconnect();
|
|
224
|
+
};
|
|
225
|
+
}, [wrapperRef, currentDate, currentSlotState, onSlotClick, removeSlotData, reloadAllData]);
|
|
226
|
+
|
|
227
|
+
const updateSlotStateData = async () => {
|
|
228
|
+
try {
|
|
229
|
+
if (!currentDate) {
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
const {
|
|
234
|
+
data,
|
|
235
|
+
logicData,
|
|
236
|
+
} = await loadSlotStateForPage(currentDate);
|
|
237
|
+
|
|
238
|
+
setCurrentSlotState(data);
|
|
239
|
+
setCurrentSlotLogicState(logicData);
|
|
240
|
+
} catch (e) {
|
|
241
|
+
console.error(e);
|
|
242
|
+
}
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
useEffect(() => {
|
|
246
|
+
updateSlots();
|
|
247
|
+
}, [currentSlotState]);
|
|
248
|
+
|
|
249
|
+
useEffect(() => {
|
|
250
|
+
reloadAllData();
|
|
251
|
+
}, [contentFieldName, locale, entry, currentDate]);
|
|
252
|
+
|
|
253
|
+
return <div className="flex w-full flex-col">
|
|
254
|
+
<div className="w-full">
|
|
255
|
+
<Timeline
|
|
256
|
+
currentDate={currentDate}
|
|
257
|
+
setCurrentDate={setCurrentDate}
|
|
258
|
+
loadTimelineStateForPage={loadTimelineStateForPage}/>
|
|
259
|
+
</div>
|
|
260
|
+
<div className={classNames(styles.wrapper, {[styles.loading]: loading === "initial"})} ref={wrapperRef}>
|
|
261
|
+
{!!loadedContent && loading !== "initial" &&
|
|
262
|
+
<Renderer
|
|
263
|
+
value={loadedContent}
|
|
264
|
+
storybookComponentLoader={componentLoader}
|
|
265
|
+
/>
|
|
266
|
+
}
|
|
267
|
+
</div>
|
|
268
|
+
</div>;
|
|
269
|
+
};
|