@raclettejs/core 0.1.36 → 0.1.38

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.
Files changed (39) hide show
  1. package/CHANGELOG.md +32 -7
  2. package/dist/cli.js +1 -1
  3. package/dist/cli.js.map +2 -2
  4. package/package.json +2 -2
  5. package/services/backend/src/corePlugins/raclette__core/backend/datatypes/composition/composition.schema.ts +10 -4
  6. package/services/backend/src/corePlugins/raclette__core/backend/datatypes/interactionLink/interactionLink.schema.ts +4 -1
  7. package/services/backend/src/shared/schemas/core/CompositionCreate.schema.ts +4 -0
  8. package/services/backend/src/shared/schemas/core/InteractionLinkCreate.schema.ts +4 -0
  9. package/services/backend/src/shared/types/core/CompositionCreate.types.ts +1 -0
  10. package/services/backend/src/shared/types/core/InteractionLinkCreate.types.ts +1 -0
  11. package/services/frontend/src/core/lib/scheduleTask.ts +35 -0
  12. package/services/frontend/src/core/store/index.ts +5 -1
  13. package/services/frontend/src/core/store/reducers/compositionSlots/reducers.ts +1 -5
  14. package/services/frontend/src/core/store/reducers/data/reducers.ts +101 -65
  15. package/services/frontend/src/core/store/reducers/metaReducer.ts +23 -0
  16. package/services/frontend/src/core/store/reducers/notifications/reducers.ts +39 -47
  17. package/services/frontend/src/core/store/reducers/queries/effects.ts +55 -2
  18. package/services/frontend/src/core/store/reducers/queries/reducers.ts +60 -62
  19. package/services/frontend/src/core/store/reducers/queriesCache/effects.ts +105 -0
  20. package/services/frontend/src/core/store/reducers/queriesCache/index.ts +2 -1
  21. package/services/frontend/src/core/store/reducers/queriesCache/queryCacheHelper.ts +79 -9
  22. package/services/frontend/src/core/store/reducers/queriesCache/reducers.ts +95 -100
  23. package/services/frontend/src/orchestrator/components/CompositionLoadingState.vue +28 -0
  24. package/services/frontend/src/orchestrator/components/composition/CompositionOverlay.vue +5 -7
  25. package/services/frontend/src/orchestrator/components/composition/WidgetsLayoutLoader.vue +171 -39
  26. package/services/frontend/src/orchestrator/components/dataTable/BaseDataTable.vue +336 -56
  27. package/services/frontend/src/orchestrator/components/dataTable/BaseDataTableConfirmDeleteBtn.vue +27 -0
  28. package/services/frontend/src/orchestrator/components/dataTable/BaseDataTableFilterDrawerShell.vue +72 -0
  29. package/services/frontend/src/orchestrator/components/index.ts +4 -0
  30. package/services/frontend/src/orchestrator/composables/index.ts +1 -0
  31. package/services/frontend/src/orchestrator/composables/useBaseDataTableDeleteConfirm.ts +23 -0
  32. package/services/frontend/src/orchestrator/composables/useVueWriteOperationHelper.ts +16 -4
  33. package/services/frontend/src/orchestrator/composables/useWidgetLifecycle.ts +53 -23
  34. package/services/frontend/src/orchestrator/constants/widgetSlotType.ts +4 -0
  35. package/services/frontend/src/orchestrator/i18n/de-DE.json +7 -1
  36. package/services/frontend/src/orchestrator/i18n/en-EU.json +7 -1
  37. package/services/frontend/src/orchestrator/i18n/sk.json +7 -1
  38. package/services/frontend/src/orchestrator/router/routerHooks/afterEach.ts +15 -9
  39. package/services/frontend/src/orchestrator/types/DataApi.ts +2 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@raclettejs/core",
3
- "version": "0.1.36",
3
+ "version": "0.1.38",
4
4
  "description": "racletteJS core package",
5
5
  "repository": "https://gitlab.com/raclettejs/core",
6
6
  "author": "Pacifico Digital Explorations GmbH <info@raclettejs.com>",
@@ -83,7 +83,7 @@
83
83
  "@emnapi/core": "1.9.2",
84
84
  "@emnapi/runtime": "1.9.2",
85
85
  "@eslint/js": "9.35.0",
86
- "@raclettejs/types": "0.1.36",
86
+ "@raclettejs/types": "0.1.38",
87
87
  "@types/fs-extra": "11.0.4",
88
88
  "@types/js-yaml": "4.0.9",
89
89
  "@types/node": "25.5.0",
@@ -66,10 +66,16 @@ export const compositionSchema = Type.Object(
66
66
  /**
67
67
  * Composition Create Schema - For POST operations
68
68
  */
69
- export const compositionCreateSchema = Type.Object(baseCompositionSchema, {
70
- $id: "#composition/create",
71
- title: "core/composition-create",
72
- })
69
+ export const compositionCreateSchema = Type.Object(
70
+ {
71
+ _id: Type.Optional(Type.String({ format: "uuid" })),
72
+ ...baseCompositionSchema,
73
+ },
74
+ {
75
+ $id: "#composition/create",
76
+ title: "core/composition-create",
77
+ },
78
+ )
73
79
 
74
80
  /**
75
81
  * Composition Update Schema - For PATCH operations
@@ -53,7 +53,10 @@ export const interactionLinkSchema = Type.Object(
53
53
  * InteractionLink Create Schema - For POST operations
54
54
  */
55
55
  export const interactionLinkCreateSchema = Type.Object(
56
- baseInteractionLinkSchema,
56
+ {
57
+ _id: Type.Optional(Type.String({ format: "uuid" })),
58
+ ...baseInteractionLinkSchema,
59
+ },
57
60
  {
58
61
  $id: "#interactionLink/create",
59
62
  title: "core/interactionLink-create",
@@ -20,6 +20,10 @@ export const CompositionCreateSchema = {
20
20
  "widgetsLayout",
21
21
  ],
22
22
  properties: {
23
+ _id: {
24
+ format: "uuid",
25
+ type: "string",
26
+ },
23
27
  title: {
24
28
  minLength: 1,
25
29
  maxLength: 200,
@@ -19,6 +19,10 @@ export const InteractionLinkCreateSchema = {
19
19
  "tags",
20
20
  ],
21
21
  properties: {
22
+ _id: {
23
+ format: "uuid",
24
+ type: "string",
25
+ },
22
26
  composition: {
23
27
  type: "string",
24
28
  },
@@ -7,6 +7,7 @@
7
7
  */
8
8
 
9
9
  export type CompositionCreate = {
10
+ _id?: string
10
11
  title: string
11
12
  description?: string
12
13
  tags: string[]
@@ -7,6 +7,7 @@
7
7
  */
8
8
 
9
9
  export type InteractionLinkCreate = {
10
+ _id?: string
10
11
  composition: string
11
12
  slotType: string
12
13
  triggers: {
@@ -0,0 +1,35 @@
1
+ type IdleDeadline = {
2
+ didTimeout: boolean
3
+ timeRemaining: () => number
4
+ }
5
+
6
+ /**
7
+ * Run work after the next paint so timer handlers stay lightweight.
8
+ */
9
+ export function scheduleAfterPaint(callback: () => void): void {
10
+ if (typeof requestAnimationFrame === "function") {
11
+ requestAnimationFrame(() => {
12
+ requestAnimationFrame(callback)
13
+ })
14
+ return
15
+ }
16
+
17
+ setTimeout(callback, 0)
18
+ }
19
+
20
+ /**
21
+ * Run non-urgent work during idle time (falls back to a macrotask).
22
+ */
23
+ export function scheduleIdleWork(
24
+ callback: () => void,
25
+ options?: { timeout?: number },
26
+ ): void {
27
+ const timeout = options?.timeout ?? 2000
28
+
29
+ if (typeof requestIdleCallback === "function") {
30
+ requestIdleCallback((_deadline: IdleDeadline) => callback(), { timeout })
31
+ return
32
+ }
33
+
34
+ setTimeout(callback, 0)
35
+ }
@@ -41,7 +41,10 @@ import {
41
41
  } from "./reducers/compositions"
42
42
  import backendReducers from "./reducers/backend"
43
43
  import { queriesEffects, queriesReducers } from "./reducers/queries"
44
- import { queriesCacheReducers } from "./reducers/queriesCache"
44
+ import {
45
+ queriesCacheEffects,
46
+ queriesCacheReducers,
47
+ } from "./reducers/queriesCache"
45
48
  import log from "@racletteCore/lib/logger"
46
49
  import type { RacletteStore, StoreHelperGetState } from "@racletteCore"
47
50
 
@@ -179,6 +182,7 @@ const registerStoreEffects = (store) => {
179
182
  compositionsEffects(store).forEach((effect) => effects.push(effect))
180
183
  interactionLinksEffects(store).forEach((effect) => effects.push(effect))
181
184
  queriesEffects(store).forEach((effect) => effects.push(effect))
185
+ queriesCacheEffects(store).forEach((effect) => effects.push(effect))
182
186
 
183
187
  effects.forEach((effect) => store.effect(effect))
184
188
  }
@@ -30,10 +30,6 @@ const compositionsSet = (state, action) => {
30
30
  }
31
31
 
32
32
  /* update page */
33
- const compositionsUpdate = (state, action) => {
34
- console.warn("Implement: compositionsUpdate()")
35
-
36
- return state
37
- }
33
+ const compositionsUpdate = (state, action) => state
38
34
 
39
35
  export { addCompositionSlot, compositionsUpdate, projectInit, compositionsSet }
@@ -8,14 +8,14 @@ import {
8
8
  handleParentChildCountChange,
9
9
  handleDataIdPrefixing,
10
10
  } from "@racletteCore/lib/dataHelper"
11
- import { mergeDeepRight, clone, difference } from "ramda"
11
+ import { mergeDeepRight, clone, difference, equals } from "ramda"
12
12
  import { v4 as uuidv4 } from "uuid"
13
13
  import * as dbItems from "./dbItems/index"
14
14
 
15
15
  const addDataToDataStore = (state, action, remote = false) => {
16
16
  const { result, actionIdentifier } = action.payload
17
17
  const { actionId, cacheKey } = actionIdentifier
18
- const newState = structuredClone(state)
18
+ const newState = { ...state }
19
19
 
20
20
  result.forEach((_item) => {
21
21
  const item = structuredClone(_item)
@@ -28,20 +28,25 @@ const addDataToDataStore = (state, action, remote = false) => {
28
28
  )
29
29
  if (!state[item._id] || remote) {
30
30
  // if the item is completely new to the cache, or from a remote query we'll just add it
31
- return (newState[item._id] = item)
31
+ newState[item._id] = item
32
+ return
32
33
  }
33
- if (state[item._id]) {
34
- if (!item._updatedAt && !state[item._id]._updatedAt) {
35
- newState[item._id] = item
36
- }
37
- if (
38
- item._updatedAt &&
39
- state[item._id]._updatedAt &&
40
- new Date(item._updatedAt) > new Date(state[item._id]._updatedAt)
41
- ) {
42
- newState[item._id] = item
43
- }
44
- newState[item._id].__requestedFor = item.__requestedFor
34
+ const existing = state[item._id]
35
+ if (!item._updatedAt && !existing._updatedAt) {
36
+ newState[item._id] = item
37
+ return
38
+ }
39
+ if (
40
+ item._updatedAt &&
41
+ existing._updatedAt &&
42
+ new Date(item._updatedAt) > new Date(existing._updatedAt)
43
+ ) {
44
+ newState[item._id] = item
45
+ return
46
+ }
47
+ newState[item._id] = {
48
+ ...existing,
49
+ __requestedFor: item.__requestedFor,
45
50
  }
46
51
  })
47
52
 
@@ -59,11 +64,7 @@ const addDataToDataStore = (state, action, remote = false) => {
59
64
  */
60
65
  const applyItemTemplate = (item, type) => {
61
66
  // TODO add dynamic plugin datatype schema retrieval here
62
- let itemTemplate = dbItems[type]
63
- if (!itemTemplate) {
64
- console.warn(`no dbItem template for ${type} found`)
65
- }
66
- itemTemplate = dbItems.defaultItem(type, item)
67
+ const itemTemplate = dbItems.defaultItem(type, item)
67
68
 
68
69
  return itemTemplate
69
70
  }
@@ -118,26 +119,23 @@ const handleRequestActionIdRegistry = (
118
119
  * we currently have in our dataStore.
119
120
  * */
120
121
  const updateDataCache = (oldCache, newItems) => {
121
- const newCache = structuredClone(oldCache)
122
+ const newCache = { ...oldCache }
122
123
 
123
124
  newItems.forEach((item) => {
124
125
  const oldItem = oldCache[item._id]
125
126
 
126
127
  // Tickets will just get updated if they have already been in the data Store due to a query
127
- if (oldItem) {
128
- newCache[item._id] = item
129
- }
130
- // apply the requestAction registry handler
131
- if (newCache[item._id]) {
132
- newCache[item._id].__requestedFor = handleRequestActionIdRegistry(
133
- newCache[item._id],
134
- oldItem,
135
- )
136
- }
137
- // we will always delete the offline flag as this function will only be called by the dataRead which retrieves synced backend items
138
- if (newCache[item._id]) {
139
- delete newCache[item._id]._offline
128
+ if (!oldItem) {
129
+ return
140
130
  }
131
+
132
+ const updatedItem = { ...item }
133
+ updatedItem.__requestedFor = handleRequestActionIdRegistry(
134
+ updatedItem,
135
+ oldItem,
136
+ )
137
+ delete updatedItem._offline
138
+ newCache[item._id] = updatedItem
141
139
  })
142
140
 
143
141
  return newCache
@@ -197,8 +195,6 @@ const dataRead = (state, action) => {
197
195
  return state
198
196
  }
199
197
  if (!Array.isArray(payload)) {
200
- console.error("data push needs to be an array!")
201
-
202
198
  return state
203
199
  }
204
200
 
@@ -324,10 +320,7 @@ const dataUpdate = (state, action) => {
324
320
  } else {
325
321
  item._source = mergeDeepRight(item._source, payload)
326
322
  }
327
- if (
328
- payload.tags &&
329
- clone(payload.tags) !== clone(oldItem._source.tags || [])
330
- ) {
323
+ if (payload.tags && !equals(payload.tags, oldItem._source.tags || [])) {
331
324
  // we have a change in tags, so let's find out what happened and change the childCount values for the tags accordingly
332
325
  const tagsAdded = difference(payload.tags, oldItem._source.tags || [])
333
326
  const tagsRemoved = difference(oldItem._source.tags || [], payload.tags)
@@ -438,33 +431,76 @@ const dataDelete = (state, action) => {
438
431
  * @param {String} action.actionId - The Id of the query which requested the items
439
432
  * @returns {Object} - Returns the new state after removing the data from the cache.
440
433
  */
434
+ const removeRequestedForFromItem = (dataItems, uuid, actionId) => {
435
+ if (!dataItems[uuid]) {
436
+ return
437
+ }
438
+ if (!dataItems[uuid].__requestedFor) {
439
+ delete dataItems[uuid]
440
+ return
441
+ }
442
+ if (dataItems[uuid].__requestedFor[actionId]) {
443
+ delete dataItems[uuid].__requestedFor[actionId]
444
+ }
445
+ if (!Object.keys(dataItems[uuid].__requestedFor).length) {
446
+ delete dataItems[uuid]
447
+ }
448
+ }
449
+
441
450
  const deleteFromCache = (state, action) => {
442
451
  const { payload, actionId } = action
443
- const dataItems = clone(state)
444
452
 
445
- if (actionId) {
446
- const iterateItems =
447
- payload?.uuids && payload?.uuids?.length
448
- ? payload?.uuids
449
- : Object.keys(dataItems)
450
- if (iterateItems.length) {
451
- iterateItems.forEach((uuid) => {
452
- if (!dataItems[uuid]) {
453
- return
454
- }
455
- if (!dataItems[uuid].__requestedFor) {
456
- delete dataItems[uuid]
457
- }
458
- // remove the indicator that this item was requested for the query in deletion process
459
- if (dataItems[uuid].__requestedFor[actionId]) {
460
- delete dataItems[uuid].__requestedFor[actionId]
461
- }
462
- // if item has no other requesters (i.e also not the global requestor) we can delete the item from the store as it is not needed anymore
463
- if (!Object.keys(dataItems[uuid].__requestedFor).length) {
464
- delete dataItems[uuid]
465
- }
466
- })
453
+ if (!actionId) {
454
+ return state
455
+ }
456
+
457
+ const uuids = payload?.uuids?.length ? payload.uuids : null
458
+
459
+ if (uuids) {
460
+ const needsUpdate = uuids.some((uuid) => {
461
+ const item = state[uuid]
462
+ if (!item) {
463
+ return false
464
+ }
465
+ if (!item.__requestedFor) {
466
+ return true
467
+ }
468
+ return Boolean(item.__requestedFor[actionId])
469
+ })
470
+
471
+ if (!needsUpdate) {
472
+ return state
467
473
  }
474
+
475
+ const dataItems = { ...state }
476
+ uuids.forEach((uuid) => {
477
+ if (!dataItems[uuid]) {
478
+ return
479
+ }
480
+ if (!dataItems[uuid].__requestedFor) {
481
+ delete dataItems[uuid]
482
+ return
483
+ }
484
+ if (!dataItems[uuid].__requestedFor[actionId]) {
485
+ return
486
+ }
487
+ const updatedItem = clone(dataItems[uuid])
488
+ delete updatedItem.__requestedFor[actionId]
489
+ if (!Object.keys(updatedItem.__requestedFor).length) {
490
+ delete dataItems[uuid]
491
+ } else {
492
+ dataItems[uuid] = updatedItem
493
+ }
494
+ })
495
+ return dataItems
496
+ }
497
+
498
+ const dataItems = clone(state)
499
+ const iterateItems = Object.keys(dataItems)
500
+ if (iterateItems.length) {
501
+ iterateItems.forEach((uuid) => {
502
+ removeRequestedForFromItem(dataItems, uuid, actionId)
503
+ })
468
504
  }
469
505
 
470
506
  return dataItems
@@ -493,13 +529,13 @@ const dataMove = (state, action) => {
493
529
  }
494
530
 
495
531
  if (!item) {
496
- console.error("item moved which is not in dataStore!")
532
+ return state
497
533
  }
498
534
  if (!item._meta) {
499
535
  item._meta = {}
500
536
  }
501
537
  if (!item?._meta?.path) {
502
- console.error("item has no path!")
538
+ return state
503
539
  }
504
540
  const updateObj = {}
505
541
 
@@ -37,6 +37,29 @@ interface ActionResult {
37
37
  deleted: any[]
38
38
  resolved: any[]
39
39
  }
40
+ dataCacheCleanup?: {
41
+ actionId: string
42
+ uuids: string[]
43
+ }
44
+ queryDeleted?: {
45
+ actionId: string
46
+ query: Record<string, unknown>
47
+ }
48
+ cacheEviction?: {
49
+ cacheKey: string
50
+ uuids: string[]
51
+ }
52
+ cacheGraceEviction?: {
53
+ cacheKey: string
54
+ actionId: string
55
+ }
56
+ cacheGraceCancel?: {
57
+ cacheKey: string
58
+ }
59
+ cacheRemoveCancelled?: {
60
+ cacheKey: string
61
+ childCount: number
62
+ }
40
63
  }
41
64
  const decorateAction = (reducer) => (state, action) => {
42
65
  action.storeLookup = {
@@ -3,17 +3,18 @@
3
3
  */
4
4
  import { applicationState } from "../../state"
5
5
  import { clone, mergeDeepRight } from "ramda"
6
- import { $store } from "@racletteCore"
6
+
7
7
  /**
8
8
  * add notifcation
9
9
  */
10
10
  const notificationsAdd = (state, action) => {
11
11
  const items = clone(state.items)
12
12
  const notificationTime = new Date()
13
- const notificationEntry = action.payload
14
-
15
- notificationEntry.time = notificationTime
16
- notificationEntry.state = "unread"
13
+ const notificationEntry = {
14
+ ...action.payload,
15
+ time: notificationTime,
16
+ state: "unread",
17
+ }
17
18
  // as we just want updates pushed to the notification que per item and editor each 5min
18
19
  const notificationTimeThreshold = 1000 * 60 * 5
19
20
  const notificationKeyTime = new Date(
@@ -47,16 +48,11 @@ const notificationsMarkAllAsSeen = (state, action) => {
47
48
  item.state = "seen"
48
49
  }
49
50
  })
50
- $store.dispatch({
51
- type: "notifications/update",
52
- payload: {
53
- unreadCount: 0,
54
- },
55
- })
56
51
 
57
52
  return {
58
53
  ...state,
59
54
  items,
55
+ unreadCount: 0,
60
56
  }
61
57
  }
62
58
 
@@ -71,16 +67,11 @@ const notificationsMarkAllAsRead = (state, action) => {
71
67
  item.state = "read"
72
68
  }
73
69
  })
74
- $store.dispatch({
75
- type: "notifications/update",
76
- payload: {
77
- unreadCount: 0,
78
- },
79
- })
80
70
 
81
71
  return {
82
72
  ...state,
83
73
  items,
74
+ unreadCount: 0,
84
75
  }
85
76
  }
86
77
 
@@ -88,23 +79,20 @@ const notificationsMarkAllAsRead = (state, action) => {
88
79
  * mark notification as read
89
80
  */
90
81
  const notificationsMarkAsRead = (state, action) => {
91
- const items = clone(state.items)
82
+ const queKey = action.payload.queKey
83
+ const item = state.items[queKey]
92
84
 
93
- if (items[action.payload.queKey].state !== "read") {
94
- items[action.payload.queKey].state = "read"
95
- if (state.unreadCount > 0) {
96
- $store.dispatch({
97
- type: "notifications/update",
98
- payload: {
99
- unreadCount: state.unreadCount - 1,
100
- },
101
- })
102
- }
85
+ if (!item || item.state === "read") {
86
+ return state
103
87
  }
104
88
 
105
89
  return {
106
90
  ...state,
107
- items: items,
91
+ items: {
92
+ ...state.items,
93
+ [queKey]: { ...item, state: "read" },
94
+ },
95
+ unreadCount: state.unreadCount > 0 ? state.unreadCount - 1 : state.unreadCount,
108
96
  }
109
97
  }
110
98
 
@@ -112,21 +100,20 @@ const notificationsMarkAsRead = (state, action) => {
112
100
  * mark notifcation as unread
113
101
  */
114
102
  const notificationsMarkUnread = (state, action) => {
115
- const items = clone(state.items)
103
+ const queKey = action.payload.queKey
104
+ const item = state.items[queKey]
116
105
 
117
- if (items[action.payload.queKey].state !== "unread") {
118
- items[action.payload.queKey].state = "unread"
119
- $store.dispatch({
120
- type: "notifications/update",
121
- payload: {
122
- unreadCount: state.unreadCount + 1,
123
- },
124
- })
106
+ if (!item || item.state === "unread") {
107
+ return state
125
108
  }
126
109
 
127
110
  return {
128
111
  ...state,
129
- items: items,
112
+ items: {
113
+ ...state.items,
114
+ [queKey]: { ...item, state: "unread" },
115
+ },
116
+ unreadCount: state.unreadCount + 1,
130
117
  }
131
118
  }
132
119
 
@@ -135,15 +122,20 @@ const notificationsMarkUnread = (state, action) => {
135
122
  */
136
123
  const notificationsToggle = (state, action) => {
137
124
  if (action.payload.toggled === false && state.toggled === true) {
138
- $store.dispatch({
139
- type: "notifications/update",
140
- payload: {
141
- unreadCount: 0,
142
- },
143
- })
144
- $store.dispatch({
145
- type: "notifications/markAllAsSeen",
125
+ const items = clone(state.items)
126
+
127
+ Object.values(items).forEach((item) => {
128
+ if (item.state !== "read") {
129
+ item.state = "seen"
130
+ }
146
131
  })
132
+
133
+ return {
134
+ ...state,
135
+ ...action.payload,
136
+ items,
137
+ unreadCount: 0,
138
+ }
147
139
  }
148
140
 
149
141
  return {
@@ -1,7 +1,23 @@
1
1
  import { tap, distinctUntilChanged, ignoreElements } from "rxjs/operators"
2
2
  import { actions$, ofType } from "mini-rx-store"
3
3
  import { getData } from "@racletteCore/lib/data/dataApi"
4
- import log from "@racletteCore/lib/logger"
4
+ import { scheduleIdleWork } from "@racletteCore/lib/scheduleTask"
5
+ import { $eventbus } from "@racletteCore/main"
6
+
7
+ const dispatchDataCacheCleanup = (store, cleanup) => {
8
+ if (!cleanup?.uuids?.length || !cleanup?.actionId) {
9
+ return
10
+ }
11
+
12
+ scheduleIdleWork(() => {
13
+ store.dispatch({
14
+ type: "data/deleteFromCache",
15
+ payload: { uuids: cleanup.uuids },
16
+ actionId: cleanup.actionId,
17
+ })
18
+ })
19
+ }
20
+
5
21
  const queriesEffects = (store) => {
6
22
  const queriesAddExecute = actions$.pipe(
7
23
  ofType("queries/add/execute"),
@@ -22,6 +38,7 @@ const queriesEffects = (store) => {
22
38
  ),
23
39
  ignoreElements(),
24
40
  )
41
+
25
42
  const queriesExecute = actions$.pipe(
26
43
  ofType("queries/execute"),
27
44
  distinctUntilChanged((prev, curr) => !store.hasChanges(prev, curr)),
@@ -35,6 +52,7 @@ const queriesEffects = (store) => {
35
52
  }),
36
53
  ignoreElements(),
37
54
  )
55
+
38
56
  const queryiesSetCacheKey = actions$.pipe(
39
57
  ofType("queries/setCacheKey"),
40
58
  distinctUntilChanged((prev, curr) => !store.hasChanges(prev, curr)),
@@ -54,7 +72,42 @@ const queriesEffects = (store) => {
54
72
  }),
55
73
  ignoreElements(),
56
74
  )
57
- return [queriesAddExecute, queriesExecute, queryiesSetCacheKey]
75
+
76
+ const queriesUpdateItemsCleanup = actions$.pipe(
77
+ ofType("queries/updateItems"),
78
+ distinctUntilChanged((prev, curr) => !store.hasChanges(prev, curr)),
79
+
80
+ tap((action) => {
81
+ dispatchDataCacheCleanup(store, action.actionResult?.dataCacheCleanup)
82
+ }),
83
+ ignoreElements(),
84
+ )
85
+
86
+ const queriesRemoveSideEffects = actions$.pipe(
87
+ ofType("queries/remove"),
88
+ distinctUntilChanged((prev, curr) => !store.hasChanges(prev, curr)),
89
+
90
+ tap((action) => {
91
+ dispatchDataCacheCleanup(store, action.actionResult?.dataCacheCleanup)
92
+
93
+ const deleted = action.actionResult?.queryDeleted as
94
+ | { actionId: string; query: Record<string, unknown> }
95
+ | undefined
96
+
97
+ if (deleted?.actionId) {
98
+ $eventbus.emit("query_deleted_" + deleted.actionId, deleted.query)
99
+ }
100
+ }),
101
+ ignoreElements(),
102
+ )
103
+
104
+ return [
105
+ queriesAddExecute,
106
+ queriesExecute,
107
+ queryiesSetCacheKey,
108
+ queriesUpdateItemsCleanup,
109
+ queriesRemoveSideEffects,
110
+ ]
58
111
  }
59
112
 
60
113
  export default queriesEffects