@vonaffenfels/contentful-teasermanager 1.2.3 → 1.2.5

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",
3
+ "version": "1.2.5",
4
4
  "main": "dist/index.js",
5
5
  "scripts": {
6
6
  "prepublish": "yarn run build",
@@ -66,6 +66,7 @@
66
66
  "@contentful/forma-36-tokens": "^0.10.1",
67
67
  "@dnd-kit/core": "^6.3.1",
68
68
  "@svgr/webpack": "^5.5.0",
69
+ "@tanstack/react-query": "^4",
69
70
  "babel-loader": "^8.2.2",
70
71
  "classnames": "^2.3.2",
71
72
  "clean-webpack-plugin": "^3.0.0",
@@ -101,7 +102,7 @@
101
102
  "contentful-resolve-response": "^1.9.2",
102
103
  "webpack": "5.88.2"
103
104
  },
104
- "gitHead": "89b263e6c6a0b3a1bb39eeb63abf8a8c00207416",
105
+ "gitHead": "357c8624f8aa9008ed7dde920ef7508b12f45dd4",
105
106
  "publishConfig": {
106
107
  "access": "public"
107
108
  }
@@ -18,7 +18,8 @@ import useDebounce from "../../../hooks/useDebounce";
18
18
  import {getContentfulClient} from "../../../lib/contentfulClient";
19
19
  import {PlusIcon} from "@contentful/f36-icons";
20
20
  import {CSS} from "@dnd-kit/utilities";
21
-
21
+ import {queryFromLogic} from "../../../queryFromLogic";
22
+ import {useQuery} from "@tanstack/react-query";
22
23
  export const LogicEditor = (props) => {
23
24
  const [selectedTags, setSelectedTags] = useState([]);
24
25
 
@@ -65,6 +66,43 @@ const LogicEditorInner = ({
65
66
  const [addTimepoint, setAddTimepoint] = useState(7);
66
67
  const debouncedSearch = useDebounce(searchQuery, 500);
67
68
  const [selectedTimepoints, setSelectedTimepoints] = useState([]);
69
+ const {
70
+ portal,
71
+ locale = "de",
72
+ } = sdk.parameters.invocation;
73
+
74
+ const {data: articles} = useQuery({
75
+ enabled: !!selectedTags.length && !!portal && !!contentfulClient,
76
+ queryKey: ["articles", selectedTags, portal],
77
+ queryFn: async () => {
78
+ const query = queryFromLogic({
79
+ tags: selectedTags,
80
+ portal,
81
+ });
82
+
83
+ try {
84
+ const result = await contentfulClient.getEntries({
85
+ content_type: "article",
86
+ locale: "de",
87
+ order: "-fields.date",
88
+ limit: 10,
89
+ ...query,
90
+ select: [
91
+ "fields.title",
92
+ "fields.slug",
93
+ "fields.date",
94
+ "sys.id",
95
+ ].join(","),
96
+ });
97
+
98
+ return result;
99
+ } catch (e) {
100
+ console.error(e);
101
+ return {items: []};
102
+ }
103
+ },
104
+ });
105
+
68
106
  useEffect(() => {
69
107
  if (logicData?.timepoints) {
70
108
  setSelectedTimepoints(logicData?.timepoints);
@@ -83,11 +121,6 @@ const LogicEditorInner = ({
83
121
  node: andNode,
84
122
  } = useDroppable({id: "and"});
85
123
 
86
- const {
87
- portal,
88
- locale = "de",
89
- } = sdk.parameters.invocation;
90
-
91
124
  useEffect(() => {
92
125
  setLoading(true);
93
126
  const params = {
@@ -196,8 +229,8 @@ const LogicEditorInner = ({
196
229
  </div>
197
230
  <div className="flex w-full flex-row items-center gap-2" style={{minHeight: 36}}>
198
231
  <SectionHeading style={{marginBottom: 0}}>Gewählte Kategorien & Tags:</SectionHeading>
199
- <div className="grid grid-cols-2 gap-4">
200
- <div className="flex flex-col gap-2">
232
+ <div className="grid w-full grid-cols-4 gap-4">
233
+ <div className="flex w-full flex-col gap-2">
201
234
  <div>
202
235
  <SectionHeading style={{marginBottom: 0}}>Oder</SectionHeading>
203
236
  </div>
@@ -222,7 +255,7 @@ const LogicEditorInner = ({
222
255
  })}
223
256
  </div>
224
257
  </div>
225
- <div className="flex flex-col gap-2">
258
+ <div className="flex w-full flex-col gap-2">
226
259
  <SectionHeading style={{marginBottom: 0}}>Und</SectionHeading>
227
260
  <div
228
261
  ref={setAndNodeRef}
@@ -246,6 +279,39 @@ const LogicEditorInner = ({
246
279
  })}
247
280
  </div>
248
281
  </div>
282
+ <div className="col-span-2 flex w-full flex-col gap-4">
283
+ <div>
284
+ <SectionHeading style={{marginBottom: 0}}>Artikel</SectionHeading>
285
+ </div>
286
+ <div className="flex flex-col gap-4">
287
+ <table className="w-full max-w-full table-auto gap-4 text-left">
288
+ <thead>
289
+ <tr>
290
+ <th>Datum</th>
291
+ <th className="pl-4">Titel</th>
292
+ </tr>
293
+ </thead>
294
+ <tbody>
295
+ {articles?.items?.map((article) => {
296
+ return <tr key={article.sys.id}>
297
+ <td className="whitespace-nowrap">
298
+ {new Date(article.fields.date.de).toLocaleString("de-DE", {
299
+ hour: "2-digit",
300
+ minute: "2-digit",
301
+ day: "2-digit",
302
+ month: "2-digit",
303
+ year: "numeric",
304
+ })}
305
+ </td>
306
+ <td className="truncate whitespace-nowrap pl-4">
307
+ {article.fields.title.de}
308
+ </td>
309
+ </tr>;
310
+ })}
311
+ </tbody>
312
+ </table>
313
+ </div>
314
+ </div>
249
315
  </div>
250
316
  </div>
251
317
  <div className="flex w-full flex-row gap-2">
@@ -2,8 +2,12 @@ import React, {
2
2
  useEffect, useState,
3
3
  } from 'react';
4
4
  import {NewestArticles} from "./Dialog/NewestArticles";
5
- import {NoAccess} from "../NoAccess";
6
5
  import {LogicEditor} from './Dialog/LogicEditor';
6
+ import {
7
+ QueryClient, QueryClientProvider,
8
+ } from "@tanstack/react-query";
9
+
10
+ const queryClient = new QueryClient();
7
11
 
8
12
  const Dialog = ({
9
13
  sdk,
@@ -60,21 +64,23 @@ const Dialog = ({
60
64
  backgroundColor: "#FFFFFF",
61
65
  minHeight: "100vh",
62
66
  }}>
63
- {sdk.parameters.invocation.isLogicEditor ?
64
- <LogicEditor
65
- sdk={sdk}
66
- onSave={onSave}
67
- logicData={logicData}
68
- portals={portals}
69
- /> :
70
- <NewestArticles
71
- sdk={sdk}
72
- onEntryClick={selectEntry}
73
- slotState={slotState}
74
- getArticleThumbnailUrl={getArticleThumbnailUrl}
75
- portals={portals}
76
- />
77
- }
67
+ <QueryClientProvider client={queryClient}>
68
+ {sdk.parameters.invocation.isLogicEditor ?
69
+ <LogicEditor
70
+ sdk={sdk}
71
+ onSave={onSave}
72
+ logicData={logicData}
73
+ portals={portals}
74
+ /> :
75
+ <NewestArticles
76
+ sdk={sdk}
77
+ onEntryClick={selectEntry}
78
+ slotState={slotState}
79
+ getArticleThumbnailUrl={getArticleThumbnailUrl}
80
+ portals={portals}
81
+ />
82
+ }
83
+ </QueryClientProvider>
78
84
  </div>;
79
85
  };
80
86
 
@@ -0,0 +1,29 @@
1
+ export const queryFromLogic = (logic) => {
2
+ const orTags = logic.tags.filter(v => v.type === "or").map(v => v.id);
3
+ const andTags = logic.tags.filter(v => v.type === "and").map(v => v.id);
4
+ const timeZoneOffsetInHours = new Date().getTimezoneOffset() / 60;
5
+ const differenceToGermanTime = timeZoneOffsetInHours + 2;
6
+ const hours = [...(logic.timepoints || [])].map(v => parseInt(v)).sort((a, b) => a - b);
7
+ let nearestPassedTime = hours.find(v => v <= new Date().getUTCHours() + differenceToGermanTime);
8
+ const logicQuery = {"fields.portal": logic.portal};
9
+
10
+ if (!nearestPassedTime) {
11
+ nearestPassedTime = hours.at(0) || 0;
12
+ }
13
+
14
+ if (orTags.length) {
15
+ logicQuery["fields.tags.sys.id[in]"] = orTags.join(",");
16
+ }
17
+
18
+ if (andTags.length) {
19
+ logicQuery["fields.tags.sys.id[all]"] = andTags.join(",");
20
+ }
21
+
22
+ if (nearestPassedTime && hours.length) {
23
+ logicQuery["fields.date[lte]"] = new Date(new Date().setHours(
24
+ nearestPassedTime + differenceToGermanTime, 0, 0, 0,
25
+ ));
26
+ }
27
+
28
+ return logicQuery;
29
+ };
@@ -5,7 +5,7 @@ let config = require("./webpack.config")({
5
5
  });
6
6
 
7
7
 
8
- config.entry = {index: './src/dev.js'};
8
+ config.entry.index = './src/dev.js';
9
9
 
10
10
  config.mode = "development";
11
11
  config.watch = true;