@vonaffenfels/contentful-teasermanager 1.0.28 → 1.0.30

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.0.28",
3
+ "version": "1.0.30",
4
4
  "scripts": {
5
5
  "prepublish": "yarn run build",
6
6
  "dev": "yarn run start",
@@ -96,10 +96,10 @@
96
96
  "webpack-dev-server": "^4.0.0-beta.2"
97
97
  },
98
98
  "dependencies": {
99
- "@vonaffenfels/slate-editor": "^1.0.28",
99
+ "@vonaffenfels/slate-editor": "^1.0.30",
100
100
  "webpack": "5.88.2"
101
101
  },
102
- "gitHead": "fe5a1e14e437b67a1aa58fa6781b9ae134914750",
102
+ "gitHead": "fe88a0b3ce82331fa3d7193a4cd62b8e2c8ecfb9",
103
103
  "publishConfig": {
104
104
  "access": "public"
105
105
  }
@@ -54,12 +54,69 @@ const Entry = ({sdk}) => {
54
54
  });
55
55
  };
56
56
 
57
+ const removeSlotData = async (slotId, currentDate) => {
58
+ console.log(`Removing slot data for page ${sdk.entry.getSys().id} with portal ${portal} for slot ${slotId} and date ${currentDate}`);
59
+
60
+ try {
61
+ const apiRoot = sdk.parameters.instance.apiRoot;
62
+ const response = await fetch(`${apiRoot}/api/saveStateForSlot`, {
63
+ method: "POST",
64
+ body: JSON.stringify({
65
+ "project": portal,
66
+ "slot": slotId,
67
+ "page": sdk.entry.getSys().id,
68
+ "entry": "RESET",
69
+ "date": currentDate,
70
+ }),
71
+ });
72
+ setReloadTrigger((current) => current + 1);
73
+ } catch (e) {
74
+ console.error(e);
75
+ alert("Fehler beim speichern!");
76
+ }
77
+ }
78
+
79
+ const loadSlotStateForPage = async (date) => {
80
+ try {
81
+ const apiRoot = sdk.parameters.instance.apiRoot;
82
+ const teasermanagerUrl = `${apiRoot}/api/findStateForPage?project=${portal}&page=${sdk.entry.getSys().id}&date=${date}`;
83
+ const response = await fetch(teasermanagerUrl).then(res => res.json());
84
+
85
+ if (response?.message) {
86
+ console.error(response.message);
87
+ }
88
+
89
+ return response?.data || {};
90
+ } catch (e) {
91
+ console.error(e);
92
+ }
93
+ }
94
+
95
+ const loadTimelineStateForPage = async (fromDate, toDate) => {
96
+ try {
97
+ const apiRoot = sdk.parameters.instance.apiRoot;
98
+ const teasermanagerUrl = `${apiRoot}/api/getTimelineStateForPage?project=${portal}&page=${sdk.entry.getSys().id}&fromDate=${fromDate}&toDate=${toDate}`;
99
+ const response = await fetch(teasermanagerUrl).then(res => res.json());
100
+
101
+ if (response?.message) {
102
+ console.error(response.message);
103
+ }
104
+
105
+ return response?.data || {};
106
+ } catch (e) {
107
+ console.error(e);
108
+ }
109
+ }
110
+
57
111
  return <Teasermanager
58
112
  entryId={sdk.entry.getSys().id}
59
113
  locale={locale}
60
114
  contentFieldName={contentField}
115
+ loadSlotStateForPage={loadSlotStateForPage}
116
+ removeSlotData={removeSlotData}
117
+ loadTimelineStateForPage={loadTimelineStateForPage}
61
118
  onSlotClick={onSlotClick}
62
119
  reloadTrigger={reloadTrigger}/>;
63
120
  };
64
121
 
65
- export default Entry;
122
+ export default Entry;
@@ -9,15 +9,20 @@ import classNames from "classnames";
9
9
  export const Timeline = ({
10
10
  currentDate,
11
11
  setCurrentDate,
12
+ loadTimelineStateForPage,
12
13
  }) => {
14
+ const [timelineState, setTimelineState] = useState(null);
15
+
13
16
  const stepsInRange = (24 * 60) / 15 + 1; // must be uneven so we have a center ;)
14
17
 
15
18
  useEffect(() => {
16
- const currentDate = new Date();
17
- currentDate.setMinutes((Math.round(currentDate.getMinutes() / 15) * 15) % 60);
19
+ if (!currentDate) {
20
+ const defaultCurrentDate = new Date();
21
+ defaultCurrentDate.setMinutes((Math.round(defaultCurrentDate.getMinutes() / 15) * 15) % 60);
18
22
 
19
- setCurrentDate(currentDate);
20
- }, []);
23
+ setCurrentDate(defaultCurrentDate);
24
+ }
25
+ }, [currentDate]);
21
26
 
22
27
  const leftDate = currentDate && subtract(currentDate, {minutes: stepsInRange / 2 * 15});
23
28
  if (leftDate) {
@@ -31,6 +36,10 @@ export const Timeline = ({
31
36
 
32
37
  let newDate = new Date(e.target.value);
33
38
 
39
+ if (format(currentDate, "yyyy-MM-dd") === format(newDate, "yyyy-MM-dd")) {
40
+ return; // nothing changed
41
+ }
42
+
34
43
  newDate.setHours(currentDate.getHours(), currentDate.getMinutes());
35
44
 
36
45
  setCurrentDate(newDate);
@@ -45,9 +54,17 @@ export const Timeline = ({
45
54
 
46
55
  switch (type) {
47
56
  case "hour":
57
+ if (newDate.getHours() === e.target.value) {
58
+ return; // nothing changed
59
+ }
60
+
48
61
  newDate.setHours(e.target.value);
49
62
  break;
50
63
  case "minute":
64
+ if (newDate.getMinutes() === e.target.value) {
65
+ return; // nothing changed
66
+ }
67
+
51
68
  newDate.setMinutes(e.target.value);
52
69
  break;
53
70
  }
@@ -55,30 +72,57 @@ export const Timeline = ({
55
72
  setCurrentDate(newDate);
56
73
  };
57
74
 
75
+
76
+ useEffect(() => {
77
+ if (!currentDate) {
78
+ return;
79
+ }
80
+
81
+ const leftDate = subtract(currentDate, {minutes: stepsInRange / 2 * 15});
82
+ leftDate.setMinutes((Math.round(currentDate.getMinutes() / 15) * 15) % 60);
83
+ leftDate.setSeconds(0);
84
+
85
+ const rightDate = new Date();
86
+ rightDate.setTime(leftDate.getTime() + (15 * 60 * 1000 * stepsInRange));
87
+
88
+ loadTimelineStateForPage(leftDate, rightDate).then(setTimelineState);
89
+ }, [currentDate])
90
+
58
91
  return <div className="flex w-full">
59
92
  <div className={styles.wrapper}>
60
93
  <div className="w-full h-auto text-center py-2">
61
94
  {!!currentDate && (
62
95
  <>
63
- <input type="date" value={format(currentDate, "yyyy-MM-dd")} onChange={handleDateChange} className="mr-2 w-auto" />
64
- <TimeSelect className="inline w-auto" currentDate={currentDate} onChange={handleTimeChange} />
96
+ <input
97
+ type="date"
98
+ value={format(currentDate, "yyyy-MM-dd")}
99
+ onChange={handleDateChange}
100
+ className="mr-2 w-auto"/>
101
+ <TimeSelect className="inline w-auto" currentDate={currentDate} onChange={handleTimeChange}/>
65
102
  </>
66
103
  )}
67
104
  </div>
68
105
  <div className={styles.timeline}>
69
106
  {!!leftDate && Array(stepsInRange).fill(0).map((_, index) => {
70
107
  const dotDate = new Date(leftDate.getTime() + (15 * 60 * 1000 * (index + 1)));
108
+ const stateChanged = timelineState?.[format(dotDate, "dd.MM.yyyy HH:mm")] || 0;
71
109
 
72
110
  return <div
73
111
  key={index}
74
- className={classNames(styles.timelineDot, {[styles.timelineDotActive]: dotDate.getTime() === currentDate.getTime()})}
112
+ className={classNames(styles.timelineDot, {
113
+ [styles.timelineDotActive]: dotDate.getTime() === currentDate.getTime(),
114
+ [styles.timelineDotChanged]: timelineState?.[format(dotDate, "dd.MM.yyyy HH:mm")],
115
+ })}
75
116
  onClick={e => {
76
117
  e.preventDefault();
77
118
  setCurrentDate(dotDate);
78
119
  return false;
79
- }}>
80
- <div className={classNames(styles.timelineDotLabel, {[styles.timelineDotLabelPermanent]: dotDate.getHours() % 6 === 0 && dotDate.getMinutes() === 0})}>
120
+ }}
121
+ >
122
+ <div
123
+ className={classNames(styles.timelineDotLabel, {[styles.timelineDotLabelPermanent]: dotDate.getHours() % 6 === 0 && dotDate.getMinutes() === 0})}>
81
124
  {leftDate && format(dotDate, "dd.MM.yyyy HH:mm")}
125
+ {!!stateChanged && ` (${stateChanged})`}
82
126
  </div>
83
127
  </div>;
84
128
  })}
@@ -96,7 +140,10 @@ const TimeSelect = ({
96
140
  let options = [];
97
141
 
98
142
  for (let i = 1; i <= 24; i++) {
99
- options.push(<option key={`hour-option-${i}`} value={i} style={{padding: "8px"}}>{i < 10 ? `0${i}` : i}</option>);
143
+ options.push(<option
144
+ key={`hour-option-${i}`}
145
+ value={i}
146
+ style={{padding: "8px"}}>{i < 10 ? `0${i}` : i}</option>);
100
147
  }
101
148
 
102
149
  return options;
@@ -106,7 +153,10 @@ const TimeSelect = ({
106
153
  let options = [];
107
154
 
108
155
  for (let i = 0; i <= 60; i += 15) {
109
- options.push(<option key={`minute-option-${i}`} value={i} style={{padding: "8px"}}>{i < 10 ? `0${i}` : i}</option>);
156
+ options.push(<option
157
+ key={`minute-option-${i}`}
158
+ value={i}
159
+ style={{padding: "8px"}}>{i < 10 ? `0${i}` : i}</option>);
110
160
  }
111
161
 
112
162
  return options;
@@ -120,7 +170,7 @@ const TimeSelect = ({
120
170
  <select value={format(currentDate, "m")} onChange={e => onChange(e, "minute")} className="mr-1 w-auto">
121
171
  {renderMinuteSelectOptions()}
122
172
  </select>
123
- Uhr
173
+ <span className="dark:text-white">Uhr</span>
124
174
  </div>
125
175
  );
126
176
  };
@@ -7,6 +7,7 @@
7
7
  }
8
8
 
9
9
  .timeline {
10
+ position: relative;
10
11
  height: auto;
11
12
  padding: 30px 0 12px 0;
12
13
  width: 100%;
@@ -15,24 +16,52 @@
15
16
  font-size: 1em;
16
17
  justify-content: space-between;
17
18
  }
19
+ .timeline:after {
20
+ content: "";
21
+ display: block;
22
+ background: black;
23
+ width: 100%;
24
+ height: 2px;
25
+ position: absolute;
26
+ z-index: 0;
27
+ bottom: 16px;
28
+ left: 0px;
29
+ }
30
+
31
+ .timeline:hover .timeline-dot-label {
32
+ opacity: 0.2;
33
+ }
18
34
 
19
35
  .timeline-dot {
20
36
  display: block;
21
- width: 10px;
22
- height: 10px;
23
- background-color: #004f73;
37
+ width: 12px;
38
+ height: 12px;
24
39
  border-radius: 9999px;
25
- cursor: pointer;
26
40
  position: relative;
41
+ z-index: 1;
27
42
  }
28
43
 
29
- .timeline-dot:hover .timeline-dot-label {
44
+ .timeline .timeline-dot:hover .timeline-dot-label {
30
45
  display: block;
46
+ opacity: 1;
31
47
  z-index: 100;
32
48
  }
33
49
 
34
50
  .timeline-dot-active {
35
- outline: 2px solid red;
51
+ outline: 2px solid green;
52
+ cursor: pointer;
53
+ background-color: green;
54
+ }
55
+
56
+ .timeline-dot-changed {
57
+ outline: 2px solid blue;
58
+ cursor: pointer;
59
+ background-color: #004f73;
60
+ }
61
+
62
+ .timeline-dot-active.timeline-dot-changed {
63
+ outline: 2px solid green;
64
+ background-color: #004f73;
36
65
  }
37
66
 
38
67
  .timeline-dot-label.timeline-dot-label-permanent {
@@ -48,4 +77,10 @@
48
77
  left: -100px;
49
78
  width: 200px;
50
79
  text-align: center;
80
+ }
81
+
82
+ @media(prefers-color-scheme: dark) {
83
+ .timeline:after {
84
+ background: white;
85
+ }
51
86
  }
@@ -11,7 +11,10 @@ import {runLoaders} from "../lib/runLoaders";
11
11
 
12
12
  export const Teasermanager = ({
13
13
  entryId,
14
+ loadSlotStateForPage = () => console.error("missing loadSlotStateForPage"),
15
+ loadTimelineStateForPage = () => console.error("missing loadTimelineStateForPage"),
14
16
  onSlotClick = () => console.error("missing onSlotClick"),
17
+ removeSlotData = () => console.error("missing removeSlotData"),
15
18
  contentFieldName = "content",
16
19
  locale = "de",
17
20
  reloadTrigger = 0,
@@ -19,41 +22,109 @@ export const Teasermanager = ({
19
22
  const contentfulClient = getContentfulClient();
20
23
  const [entry, setEntry] = useState(null);
21
24
  const wrapperRef = useRef(null);
22
- const [loading, setLoading] = useState(true);
25
+ const [loading, setLoading] = useState("initial");
23
26
  const [loadedContent, setLoadedContent] = useState(null);
24
- const [currentDate, setCurrentDate] = useState(null);
27
+ const [currentDate, _setCurrentDate] = useState(null);
28
+ const [currentSlotState, setCurrentSlotState] = useState(null);
25
29
 
26
- const initSlot = (node) => {
27
- if (node.dataset.__teasermanager_slot_initialized) {
28
- return;
30
+ const setCurrentDate = (date) => {
31
+ if (date) {
32
+ date.setSeconds(0);
29
33
  }
30
34
 
31
- node.dataset.__teasermanager_slot_initialized = true;
35
+ _setCurrentDate(date);
36
+ }
32
37
 
38
+ const initSlot = (node) => {
39
+ const existingManagementNode = node.querySelector(`.__teasermanager_management_node`);
40
+ if (existingManagementNode) {
41
+ node.removeChild(existingManagementNode);
42
+ }
43
+
44
+ const slotId = node.dataset.teasermanagerSlot;
33
45
  const managementNode = document.createElement("div");
34
46
  managementNode.classList.add(styles.management);
35
47
 
36
48
  const managementLabelNode = document.createElement("div");
37
49
  managementLabelNode.classList.add(styles.label);
38
- managementLabelNode.innerHTML = `Klicken um den Artikel zu wechseln`;
50
+ if (currentSlotState?.[slotId]) {
51
+ managementNode.classList.add(styles.changedBorder);
52
+ }
53
+
54
+ if (currentSlotState?.[slotId] && currentSlotState?.[slotId] !== "RESET") {
55
+ managementNode.classList.add(styles.changed);
56
+
57
+ managementLabelNode.innerHTML = `Klicken um den Artikel zu wechseln`;
58
+ const managementRemoveButtonNode = document.createElement("div");
59
+ managementRemoveButtonNode.classList.add(styles.removeButton);
60
+ managementRemoveButtonNode.title = `Artikel entfernen`;
61
+ managementRemoveButtonNode.innerHTML = `
62
+ <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">
63
+ <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
64
+ \tc0,137.002-111.07,248.07-248.083,248.07C111.069,496.155,0,385.087,0,248.085z"/>
65
+ <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
66
+ \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"/>
67
+ </svg>
68
+ `;
69
+ managementRemoveButtonNode.addEventListener("click", (e) => {
70
+ removeSlotData(slotId, currentDate);
71
+ e.preventDefault();
72
+ e.stopPropagation();
73
+ return false;
74
+ });
75
+ managementNode.appendChild(managementRemoveButtonNode);
76
+ } else {
77
+ if (currentSlotState?.[slotId] === "RESET") {
78
+ managementLabelNode.innerHTML = `Hier wurde ein bereits verslotteter Artikel wieder entfernt<br />Klicken um einen neuen Artikel festzulegen`;
79
+ } else {
80
+ managementLabelNode.innerHTML = `Klicken um den Artikel festzulegen`;
81
+ }
82
+
83
+ }
39
84
 
40
85
  managementNode.appendChild(managementLabelNode);
41
86
 
42
87
  managementNode.addEventListener("click", (e) => {
43
- const slotId = node.dataset.teasermanagerSlot;
44
88
  onSlotClick(slotId, currentDate);
89
+ e.preventDefault();
90
+ e.stopPropagation();
91
+ return false;
45
92
  });
46
93
 
94
+ managementNode.classList.add("__teasermanager_management_node");
47
95
  node.appendChild(managementNode);
48
96
  };
49
97
 
50
98
  const updateSlots = (mutationList) => {
51
- const slots = wrapperRef.current.querySelectorAll(`*[data-teasermanager-slot]`);
52
- slots.forEach(initSlot);
99
+
100
+ if (!mutationList) {
101
+ // update all slots
102
+ const slots = wrapperRef.current.querySelectorAll(`*[data-teasermanager-slot]`);
103
+ slots.forEach(initSlot);
104
+ } else {
105
+ // update only if the change was not a management node
106
+ const isValidUpdate = mutationList?.find(mutation => {
107
+ if (mutation.type === "childList") {
108
+ const removedNonManagementNode = [...mutation.removedNodes]?.find(node => !node.classList.contains("__teasermanager_management_node"));
109
+ const addedNonManagementNode = [...mutation.addedNodes]?.find(node => !node.classList.contains("__teasermanager_management_node"));
110
+
111
+ if (!removedNonManagementNode && !addedNonManagementNode) {
112
+ return false;
113
+ }
114
+ }
115
+
116
+ return true;
117
+ })
118
+
119
+ if (isValidUpdate) {
120
+ updateSlots();
121
+ }
122
+ }
123
+
53
124
  };
54
125
 
55
126
  useEffect(() => {
56
- if (!entryId && entry) {
127
+ if (!entryId || entry) {
57
128
  setEntry(null);
58
129
  return;
59
130
  }
@@ -61,7 +132,7 @@ export const Teasermanager = ({
61
132
  contentfulClient.getEntry(entryId).then((loadedEntry, b) => {
62
133
  setEntry(loadedEntry);
63
134
  });
64
- }, []);
135
+ }, [entryId]);
65
136
 
66
137
  useEffect(() => {
67
138
  if (!wrapperRef.current) {
@@ -78,30 +149,62 @@ export const Teasermanager = ({
78
149
  return () => {
79
150
  observer.disconnect();
80
151
  };
81
- }, [wrapperRef, currentDate]);
152
+ }, [wrapperRef, currentDate, currentSlotState]);
153
+
154
+ const updateSlotStateData = async () => {
155
+ try {
156
+ if (!currentDate) {
157
+ return;
158
+ }
159
+ setCurrentSlotState(await loadSlotStateForPage(currentDate))
160
+ } catch (e) {
161
+ console.error(e);
162
+ }
163
+ }
164
+
165
+ const reloadAllData = async () => {
166
+ if (loading === true || !currentDate) {
167
+ return;
168
+ }
82
169
 
83
- useEffect(() => {
84
170
  const contentValue = entry?.fields?.[contentFieldName]?.[locale];
85
171
  const portalValue = entry?.fields?.portal?.[locale];
86
172
 
87
173
  if (!contentValue) {
88
174
  setLoading(false);
89
- return setLoadedContent(null);
175
+ setLoadedContent(null);
176
+ return;
90
177
  }
91
178
 
179
+ console.log(`Teasermanager :: LOADING DATA`);
92
180
  setLoading(true);
93
- runLoaders(contentValue, portalValue, entry?.sys?.id).then(content => {
181
+ runLoaders(contentValue, portalValue, entry?.sys?.id, currentDate).then(content => {
94
182
  setLoadedContent(content);
95
183
  setLoading(false);
96
184
  });
97
- }, [contentFieldName, locale, entry, reloadTrigger]);
185
+
186
+ updateSlotStateData();
187
+ }
188
+
189
+ useEffect(() => {
190
+ updateSlots();
191
+ }, [currentSlotState]);
192
+
193
+ useEffect(() => {
194
+ reloadAllData();
195
+ }, [contentFieldName, locale, entry, reloadTrigger, currentDate]);
98
196
 
99
197
  return <div className="flex w-full flex-col">
100
198
  <div className="w-full">
101
- <Timeline currentDate={currentDate} setCurrentDate={setCurrentDate}/>
199
+ <Timeline
200
+ currentDate={currentDate}
201
+ setCurrentDate={setCurrentDate}
202
+ loadTimelineStateForPage={loadTimelineStateForPage}/>
102
203
  </div>
103
204
  <div className={styles.wrapper} ref={wrapperRef}>
104
- {loading && <div>Lade Inhalte...</div>}
205
+ {loading &&
206
+ <div className="dark:text-white w-full font-base text-2xl p-8 h-full text-center align-middle">Lade
207
+ Inhalte...</div>}
105
208
  {!!loadedContent && !loading &&
106
209
  <Renderer
107
210
  value={loadedContent}
@@ -5,8 +5,8 @@
5
5
  .management {
6
6
  font-family: Arial, Helvetica, sans-serif;
7
7
 
8
- background-color: rgba(255, 255, 255, 0.4);
9
- border: 1px dashed black;
8
+ background-color: rgba(255, 255, 255, 0.2);
9
+ outline: 2px dashed black;
10
10
  color: black;
11
11
  text-align: center;
12
12
  vertical-align: middle;
@@ -23,16 +23,43 @@
23
23
  padding: 2em;
24
24
  }
25
25
 
26
+ .remove-button {
27
+ display: flex;
28
+ padding: 0.5em;
29
+ position: absolute;
30
+ top: 0;
31
+ right: 0;
32
+ cursor: pointer;
33
+ }
34
+
35
+ @media (prefers-color-scheme: dark) {
36
+ .management {
37
+ outline: 2px dashed white;
38
+ }
39
+ }
40
+
26
41
  .management:hover {
27
42
  background-color: rgba(255, 255, 255, 0.9);
28
43
  }
29
44
 
30
45
  .label {
31
46
  visibility: hidden;
47
+ width: 100%;
32
48
  font-weight: bold;
49
+ text-align: center;
33
50
  }
34
51
 
35
52
  .management:hover .label {
36
53
  visibility: visible;
37
54
  }
38
55
 
56
+ .changed {
57
+ background-color: rgba(172, 255, 156, 0.9);
58
+ }
59
+ .changed:hover {
60
+ background-color: rgba(97, 255, 68, 0.9);
61
+ }
62
+
63
+ .changed-border {
64
+ outline-color: green;
65
+ }
@@ -0,0 +1,8 @@
1
+
2
+ <svg height="0px" width="800px" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
3
+ viewBox="0 0 496.158 496.158" xml:space="preserve">
4
+ <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
5
+ c0,137.002-111.07,248.07-248.083,248.07C111.069,496.155,0,385.087,0,248.085z"/>
6
+ <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
7
+ h270.934c3.976,0,7.199-3.224,7.199-7.199v-69.187C390.745,209.511,387.521,206.286,383.546,206.286z"/>
8
+ </svg>
@@ -1,11 +1,11 @@
1
- export const runLoaders = async (value, portal, contextId) => {
1
+ export const runLoaders = async (value, portal, contextId, currentDate) => {
2
2
  if (!Array.isArray(value)) {
3
3
  return value;
4
4
  }
5
5
 
6
6
  const newValue = await Promise.all(value.map(async (item) => {
7
7
  try {
8
- return await runLoader(item, portal, contextId)
8
+ return await runLoader(item, portal, contextId, currentDate)
9
9
  } catch (e) {
10
10
  console.error(e);
11
11
  return item;
@@ -15,7 +15,7 @@ export const runLoaders = async (value, portal, contextId) => {
15
15
  return newValue;
16
16
  }
17
17
 
18
- const runLoader = async (item, portal, contextId) => {
18
+ const runLoader = async (item, portal, contextId, currentDate = new Date()) => {
19
19
 
20
20
  if (!item?.block) {
21
21
  return item;
@@ -23,7 +23,13 @@ const runLoader = async (item, portal, contextId) => {
23
23
  try {
24
24
  const response = await fetch(`/api/loader/?portal=${portal}&block=${item.block}`, {
25
25
  method: "POST",
26
- body: JSON.stringify({variables: item.attributes, context: {activeContent: {sys: {id: contextId}}}}),
26
+ body: JSON.stringify({
27
+ variables: {
28
+ ...(item.attributes || {}),
29
+ teasermanagerDate: currentDate,
30
+ },
31
+ context: {activeContent: {sys: {id: contextId}}},
32
+ }),
27
33
  }).then(res => res.json());
28
34
 
29
35
  return {