@vonaffenfels/contentful-teasermanager 1.0.31 → 1.0.33

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.31",
3
+ "version": "1.0.33",
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.31",
99
+ "@vonaffenfels/slate-editor": "^1.0.33",
100
100
  "webpack": "5.88.2"
101
101
  },
102
- "gitHead": "007715e3b949cf0368e7b4d70626d2931c7b7829",
102
+ "gitHead": "a5d858b33c49e6a1a53f90951749159b06452db5",
103
103
  "publishConfig": {
104
104
  "access": "public"
105
105
  }
@@ -8,7 +8,6 @@ const Entry = ({sdk}) => {
8
8
  const [locale, setLocale] = useState(sdk.locales.default);
9
9
  const [portal, setPortal] = useState();
10
10
  const portalField = sdk?.entry?.fields?.portal;
11
- const [reloadTrigger, setReloadTrigger] = useState(0);
12
11
 
13
12
  portalField?.onValueChanged(() => {
14
13
  if (portalField.getValue() !== portal) {
@@ -27,7 +26,7 @@ const Entry = ({sdk}) => {
27
26
  }, []);
28
27
 
29
28
  const onSlotClick = (slotId, currentDate) => {
30
- sdk.dialogs.selectSingleEntry({contentTypes: ["article"]}).then(async (entry) => {
29
+ return sdk.dialogs.selectSingleEntry({contentTypes: ["article"]}).then(async (entry) => {
31
30
  if (!entry) {
32
31
  return;
33
32
  }
@@ -46,7 +45,7 @@ const Entry = ({sdk}) => {
46
45
  "date": currentDate,
47
46
  }),
48
47
  });
49
- setReloadTrigger((current) => current + 1);
48
+ return entry;
50
49
  } catch (e) {
51
50
  console.error(e);
52
51
  alert("Fehler beim speichern!");
@@ -69,7 +68,6 @@ const Entry = ({sdk}) => {
69
68
  "date": currentDate,
70
69
  }),
71
70
  });
72
- setReloadTrigger((current) => current + 1);
73
71
  } catch (e) {
74
72
  console.error(e);
75
73
  alert("Fehler beim speichern!");
@@ -115,8 +113,7 @@ const Entry = ({sdk}) => {
115
113
  loadSlotStateForPage={loadSlotStateForPage}
116
114
  removeSlotData={removeSlotData}
117
115
  loadTimelineStateForPage={loadTimelineStateForPage}
118
- onSlotClick={onSlotClick}
119
- reloadTrigger={reloadTrigger}/>;
116
+ onSlotClick={onSlotClick}/>;
120
117
  };
121
118
 
122
119
  export default Entry;
@@ -83,4 +83,7 @@
83
83
  .timeline:after {
84
84
  background: white;
85
85
  }
86
+ .timeline-dot-changed {
87
+ background-color: #ffffff;
88
+ }
86
89
  }
@@ -8,16 +8,16 @@ import componentLoader from "@vonaffenfels/slate-editor/componentLoader";
8
8
  import {Timeline} from "./Teasermanager/Timeline";
9
9
  import styles from "./Teasermanager.module.css";
10
10
  import {runLoaders} from "../lib/runLoaders";
11
+ import classNames from "classnames";
11
12
 
12
13
  export const Teasermanager = ({
13
14
  entryId,
14
15
  loadSlotStateForPage = () => console.error("missing loadSlotStateForPage"),
15
16
  loadTimelineStateForPage = () => console.error("missing loadTimelineStateForPage"),
16
- onSlotClick = () => console.error("missing onSlotClick"),
17
- removeSlotData = () => console.error("missing removeSlotData"),
17
+ onSlotClick = async () => console.error("missing onSlotClick"),
18
+ removeSlotData = async () => console.error("missing removeSlotData"),
18
19
  contentFieldName = "content",
19
20
  locale = "de",
20
- reloadTrigger = 0,
21
21
  }) => {
22
22
  const contentfulClient = getContentfulClient();
23
23
  const [entry, setEntry] = useState(null);
@@ -26,6 +26,7 @@ export const Teasermanager = ({
26
26
  const [loadedContent, setLoadedContent] = useState(null);
27
27
  const [currentDate, _setCurrentDate] = useState(null);
28
28
  const [currentSlotState, setCurrentSlotState] = useState(null);
29
+ const currentLoadingOperation = useRef(0);
29
30
 
30
31
  const setCurrentDate = (date) => {
31
32
  if (date) {
@@ -35,6 +36,38 @@ export const Teasermanager = ({
35
36
  _setCurrentDate(date);
36
37
  }
37
38
 
39
+ const reloadAllData = async () => {
40
+ let loadingId = ++currentLoadingOperation.current;
41
+ if (!currentDate) {
42
+ return;
43
+ }
44
+
45
+ const contentValue = entry?.fields?.[contentFieldName]?.[locale];
46
+ const portalValue = entry?.fields?.portal?.[locale];
47
+
48
+ if (!contentValue) {
49
+ setLoading("initial");
50
+ setLoadedContent(null);
51
+ return;
52
+ }
53
+
54
+ console.log(`Teasermanager :: LOADING DATA`);
55
+ if (loading !== "initial") {
56
+ setLoading(true);
57
+ }
58
+
59
+ const content = await runLoaders(contentValue, portalValue, entry?.sys?.id, currentDate);
60
+
61
+ // only apply the LAST update
62
+ if (currentLoadingOperation.current === loadingId) {
63
+ updateSlotStateData();
64
+
65
+ console.log(`Teasermanager :: LOADED DATA`);
66
+ setLoadedContent(content);
67
+ setLoading(false);
68
+ }
69
+ }
70
+
38
71
  const initSlot = (node) => {
39
72
  const existingManagementNode = node.querySelector(`.__teasermanager_management_node`);
40
73
  if (existingManagementNode) {
@@ -67,7 +100,13 @@ export const Teasermanager = ({
67
100
  </svg>
68
101
  `;
69
102
  managementRemoveButtonNode.addEventListener("click", (e) => {
70
- removeSlotData(slotId, currentDate);
103
+ removeSlotData(slotId, currentDate).then(() => {
104
+ managementNode.classList.add(styles.loading);
105
+ reloadAllData().then(() => {
106
+ // DONT remove, in case multiple loading operations are running we want the state to stay loading :)
107
+ //managementNode.classList.remove(styles.loading);
108
+ });
109
+ });
71
110
  e.preventDefault();
72
111
  e.stopPropagation();
73
112
  return false;
@@ -83,9 +122,17 @@ export const Teasermanager = ({
83
122
  }
84
123
 
85
124
  managementNode.appendChild(managementLabelNode);
86
-
87
125
  managementNode.addEventListener("click", (e) => {
88
- onSlotClick(slotId, currentDate);
126
+ onSlotClick(slotId, currentDate).then((entry) => {
127
+ if (!entry) {
128
+ return; // nothing changed, no need to reload!
129
+ }
130
+ managementNode.classList.add(styles.loading);
131
+ reloadAllData().then(() => {
132
+ // DONT remove, in case multiple loading operations are running we want the state to stay loading :)
133
+ //managementNode.classList.remove(styles.loading);
134
+ });
135
+ });
89
136
  e.preventDefault();
90
137
  e.stopPropagation();
91
138
  return false;
@@ -101,6 +148,7 @@ export const Teasermanager = ({
101
148
  // update all slots
102
149
  const slots = wrapperRef.current.querySelectorAll(`*[data-teasermanager-slot]`);
103
150
  slots.forEach(initSlot);
151
+ console.log(`Teasermanager :: UPDATE ALL SLOTS`);
104
152
  } else {
105
153
  // update only if the change was not a management node
106
154
  const isValidUpdate = mutationList?.find(mutation => {
@@ -149,7 +197,7 @@ export const Teasermanager = ({
149
197
  return () => {
150
198
  observer.disconnect();
151
199
  };
152
- }, [wrapperRef, currentDate, currentSlotState]);
200
+ }, [wrapperRef, currentDate, currentSlotState, onSlotClick, removeSlotData, reloadAllData]);
153
201
 
154
202
  const updateSlotStateData = async () => {
155
203
  try {
@@ -162,37 +210,13 @@ export const Teasermanager = ({
162
210
  }
163
211
  }
164
212
 
165
- const reloadAllData = async () => {
166
- if (loading === true || !currentDate) {
167
- return;
168
- }
169
-
170
- const contentValue = entry?.fields?.[contentFieldName]?.[locale];
171
- const portalValue = entry?.fields?.portal?.[locale];
172
-
173
- if (!contentValue) {
174
- setLoading(false);
175
- setLoadedContent(null);
176
- return;
177
- }
178
-
179
- console.log(`Teasermanager :: LOADING DATA`);
180
- setLoading(true);
181
- runLoaders(contentValue, portalValue, entry?.sys?.id, currentDate).then(content => {
182
- setLoadedContent(content);
183
- setLoading(false);
184
- });
185
-
186
- updateSlotStateData();
187
- }
188
-
189
213
  useEffect(() => {
190
214
  updateSlots();
191
215
  }, [currentSlotState]);
192
216
 
193
217
  useEffect(() => {
194
218
  reloadAllData();
195
- }, [contentFieldName, locale, entry, reloadTrigger, currentDate]);
219
+ }, [contentFieldName, locale, entry, currentDate]);
196
220
 
197
221
  return <div className="flex w-full flex-col">
198
222
  <div className="w-full">
@@ -201,11 +225,8 @@ export const Teasermanager = ({
201
225
  setCurrentDate={setCurrentDate}
202
226
  loadTimelineStateForPage={loadTimelineStateForPage}/>
203
227
  </div>
204
- <div className={styles.wrapper} ref={wrapperRef}>
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>}
208
- {!!loadedContent && !loading &&
228
+ <div className={classNames(styles.wrapper, {[styles.loading]: loading === "initial"})} ref={wrapperRef}>
229
+ {!!loadedContent && loading !== "initial" &&
209
230
  <Renderer
210
231
  value={loadedContent}
211
232
  storybookComponentLoader={componentLoader}
@@ -32,13 +32,53 @@
32
32
  cursor: pointer;
33
33
  }
34
34
 
35
+ .loading {
36
+ animation: pulse 3s ease-in-out infinite;
37
+ }
38
+
39
+ .loading:after {
40
+ content: '';
41
+ position: absolute;
42
+ top: 50%;
43
+ left: 50%;
44
+ margin-top: -50px;
45
+ margin-left: -50px;
46
+ width: 100px;
47
+ height: 100px;
48
+ border-radius: 999999px;
49
+ border: 10px dotted white;
50
+ filter: drop-shadow(2px 4px 6px black);
51
+ animation: loading 3s linear infinite;
52
+ }
53
+
54
+ @keyframes loading {
55
+ 0% {
56
+ transform: rotate(0deg);
57
+ }
58
+ 100% {
59
+ transform: rotate(360deg);
60
+ }
61
+ }
62
+
63
+ @keyframes pulse {
64
+ from {
65
+ opacity: 1;
66
+ }
67
+ 50% {
68
+ opacity: 0.3;
69
+ }
70
+ to {
71
+ opacity: 1;
72
+ }
73
+ }
74
+
35
75
  @media (prefers-color-scheme: dark) {
36
76
  .management {
37
77
  outline: 2px dashed white;
38
78
  }
39
79
  }
40
80
 
41
- .management:hover {
81
+ .management:hover {
42
82
  background-color: rgba(255, 255, 255, 0.9);
43
83
  }
44
84
 
@@ -54,10 +94,11 @@
54
94
  }
55
95
 
56
96
  .changed {
57
- background-color: rgba(172, 255, 156, 0.9);
97
+ background-color: rgba(172, 255, 156, 0.4);
58
98
  }
99
+
59
100
  .changed:hover {
60
- background-color: rgba(97, 255, 68, 0.9);
101
+ background-color: rgba(97, 255, 68, 0.6);
61
102
  }
62
103
 
63
104
  .changed-border {