@raclettejs/core 0.1.10 → 0.1.12
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/CHANGELOG.md +59 -2
- package/dist/cli.js +104 -104
- package/dist/cli.js.map +7 -0
- package/dist/index.js +4 -4
- package/dist/index.js.map +7 -0
- package/package.json +32 -31
- package/services/backend/package.json +35 -45
- package/services/backend/src/core/payload/payloadTypes.ts +7 -0
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/account/routes/route.account.get.ts +1 -1
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/account/routes/route.account.getAll.ts +1 -1
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/composition/composition.model.ts +5 -0
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/composition/composition.schema.ts +1 -0
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/composition/composition.service.ts +1 -1
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/composition/routes/route.composition.get.ts +1 -1
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/composition/routes/route.composition.getAll.ts +1 -1
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/interactionLink/helpers/payload.ts +6 -2
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/interactionLink/routes/route.interactionLink.get.ts +1 -1
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/interactionLink/routes/route.interactionLink.getAll.ts +1 -1
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/project/routes/route.project.get.ts +1 -1
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/project/routes/route.project.getAll.ts +1 -1
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/tag/index.ts +2 -1
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/tag/routes/route.tag.get.ts +1 -1
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/tag/routes/route.tag.getAll.ts +6 -2
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/tag/tag.service.ts +22 -1
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/user/routes/route.user.get.ts +1 -1
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/user/routes/route.user.getAll.ts +1 -1
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/user/routes/route.user.remove.ts +3 -0
- package/services/backend/src/corePlugins/raclette__core/backend/datatypes/user/user.service.ts +1 -2
- package/services/backend/src/corePlugins/raclette__core/frontend/generated-config.ts +12 -12
- package/services/backend/src/domains/index.ts +3 -0
- package/services/backend/src/domains/system/collections.service.ts +119 -0
- package/services/backend/src/domains/system/index.ts +8 -0
- package/services/backend/src/domains/system/routes/index.ts +5 -0
- package/services/backend/src/domains/system/routes/route.collection.getAll.ts +61 -0
- package/services/backend/src/domains/system/routes/route.collection.remove.ts +93 -0
- package/services/backend/src/types/custom-fastify.d.ts +1 -0
- package/services/backend/src/utils/request.utils.ts +28 -1
- package/services/backend/yarn.lock +431 -1180
- package/services/frontend/package.json +29 -40
- package/services/frontend/src/core/constants/ApiClient.ts +6 -1
- package/services/frontend/src/core/lib/data/dataApi.ts +8 -1
- package/services/frontend/src/core/lib/data/fetchDataHandler.ts +58 -27
- package/services/frontend/src/core/lib/data/queryApi.ts +29 -8
- package/services/frontend/src/core/lib/data/responseTypeHandler.ts +27 -4
- package/services/frontend/src/core/lib/data/writeDataHandler.ts +1 -1
- package/services/frontend/src/core/lib/dataHelper.ts +8 -1
- package/services/frontend/src/core/lib/easteregg.ts +1 -1
- package/services/frontend/src/core/lib/eventEmitter.ts +1 -0
- package/services/frontend/src/core/lib/eventWhitelist.ts +11 -1
- package/services/frontend/src/core/lib/logger.ts +11 -3
- package/services/frontend/src/core/lib/userNotifier.ts +17 -17
- package/services/frontend/src/core/main.ts +3 -3
- package/services/frontend/src/core/setup/plugin-system/api/wrappers.ts +18 -1
- package/services/frontend/src/core/setup/plugin-system/registration/index.ts +1 -1
- package/services/frontend/src/core/setup/socketClient.ts +2 -2
- package/services/frontend/src/core/setup/socketEvents.ts +2 -2
- package/services/frontend/src/core/store/reducers/compositions/selectors.ts +2 -2
- package/services/frontend/src/core/store/reducers/data/index.ts +1 -1
- package/services/frontend/src/core/store/reducers/data/reducers.ts +3 -3
- package/services/frontend/src/core/store/reducers/queries/effects.ts +20 -1
- package/services/frontend/src/core/store/reducers/queries/index.ts +1 -0
- package/services/frontend/src/core/store/reducers/queries/reducers.ts +28 -1
- package/services/frontend/src/core/store/reducers/queriesCache/queryCacheHelper.ts +5 -4
- package/services/frontend/src/core/store/reducers/queriesCache/reducers.ts +4 -3
- package/services/frontend/src/core/store/state.ts +1 -1
- package/services/frontend/src/core/types/ApiClient.ts +1 -1
- package/services/frontend/src/core/types/DataApi.ts +4 -0
- package/services/frontend/src/core/types/Queries.ts +1 -0
- package/services/frontend/src/orchestrator/ProductOrchestrator.vue +19 -7
- package/services/frontend/src/orchestrator/WelcomeScreen.vue +39 -41
- package/services/frontend/src/orchestrator/assets/styles/tailwindStyles.css +3 -0
- package/services/frontend/src/orchestrator/assets/styles/themes/dark.ts +2 -2
- package/services/frontend/src/orchestrator/assets/styles/vuetifyStyles.scss +0 -1
- package/services/frontend/src/orchestrator/components/composition/CompositionOverlay.vue +11 -2
- package/services/frontend/src/orchestrator/components/composition/WidgetsLayoutLoader.vue +167 -58
- package/services/frontend/src/orchestrator/components/menu/DevIndicator.vue +122 -7
- package/services/frontend/src/orchestrator/components/menu/UserMenu.vue +38 -20
- package/services/frontend/src/orchestrator/components/snackbar/SnackStack.vue +17 -5
- package/services/frontend/src/orchestrator/composables/useCurrentComposition.ts +32 -4
- package/services/frontend/src/orchestrator/composables/usePageNavigation.ts +5 -1
- package/services/frontend/src/orchestrator/composables/usePluginApi.ts +125 -26
- package/services/frontend/src/orchestrator/composables/useRouteState.ts +0 -1
- package/services/frontend/src/orchestrator/composables/useVueQueryObservableHelper.ts +2 -0
- package/services/frontend/src/orchestrator/composables/useVueWriteOperationHelper.ts +5 -3
- package/services/frontend/src/orchestrator/composables/useWidgets/helperFunctions.ts +4 -1
- package/services/frontend/src/orchestrator/helpers/loginUserNotifications.ts +1 -1
- package/services/frontend/src/orchestrator/helpers/uiHelper.ts +1 -1
- package/services/frontend/src/orchestrator/i18n/de-DE.json +2 -1
- package/services/frontend/src/orchestrator/i18n/en-EU.json +2 -1
- package/services/frontend/src/orchestrator/i18n/sk.json +2 -1
- package/services/frontend/src/orchestrator/i18n/tl-TL.json +1 -1
- package/services/frontend/src/orchestrator/router/routeParserHelper.ts +4 -1
- package/services/frontend/src/orchestrator/router/routeStore.ts +78 -11
- package/services/frontend/tsconfig.app.json +1 -0
- package/services/frontend/yarn.lock +796 -1872
- package/yarn.lock +435 -618
|
@@ -93,10 +93,10 @@ const createRacletteApp = async (
|
|
|
93
93
|
store.dispatch({ type: "user/set", payload: user })
|
|
94
94
|
|
|
95
95
|
// does the core really need to communicate with itself via eventbus?
|
|
96
|
-
eventbus.emit("
|
|
96
|
+
eventbus.emit("socket/join/room")
|
|
97
97
|
|
|
98
98
|
return new Promise<CreateAppResponse>(async (resolve, reject) => {
|
|
99
|
-
eventbus.on("
|
|
99
|
+
eventbus.on("ui/setupProject", (spaceId: string) => {
|
|
100
100
|
resolve({
|
|
101
101
|
authenticated: true,
|
|
102
102
|
setupComplete: true,
|
|
@@ -152,7 +152,7 @@ const generateLoginCallback =
|
|
|
152
152
|
|
|
153
153
|
store.dispatch({ type: "user/set", payload: response.data.user })
|
|
154
154
|
|
|
155
|
-
eventbus.emit("
|
|
155
|
+
eventbus.emit("socket/join/room")
|
|
156
156
|
|
|
157
157
|
// Return success with token & redirect function
|
|
158
158
|
return {
|
|
@@ -27,12 +27,29 @@ export const wrapFileApi = (
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
export const wrapEventbusApi = (
|
|
30
|
+
plugin: RegisteredPlugin,
|
|
30
31
|
$eventbus: any,
|
|
31
32
|
pluginApi: Partial<PluginApi>,
|
|
32
33
|
): any => {
|
|
33
34
|
if ($eventbus && !pluginApi.$eventbus) {
|
|
34
35
|
const $pluginEventbus = new EventEmitter(false, false)
|
|
35
|
-
$pluginEventbus.global =
|
|
36
|
+
$pluginEventbus.global = {
|
|
37
|
+
on: (event: string, listener: Function) => {
|
|
38
|
+
return $eventbus.on(event, listener)
|
|
39
|
+
},
|
|
40
|
+
once: (event: string, listener: Function) => {
|
|
41
|
+
return $eventbus.once(event, listener)
|
|
42
|
+
},
|
|
43
|
+
emit: (event: string, payload: object) => {
|
|
44
|
+
return $eventbus.emit(event, {
|
|
45
|
+
sender: plugin.pluginKey,
|
|
46
|
+
data: payload,
|
|
47
|
+
})
|
|
48
|
+
},
|
|
49
|
+
isValid: (event: string) => {
|
|
50
|
+
return $eventbus.isValid(event)
|
|
51
|
+
},
|
|
52
|
+
}
|
|
36
53
|
return $pluginEventbus
|
|
37
54
|
}
|
|
38
55
|
return pluginApi
|
|
@@ -113,7 +113,7 @@ export const loadAndRegisterPlugin = async (
|
|
|
113
113
|
|
|
114
114
|
if (corePluginApi.$eventbus) {
|
|
115
115
|
currentPlugin.initEventbus = () =>
|
|
116
|
-
wrapEventbusApi(corePluginApi.$eventbus, pluginApi)
|
|
116
|
+
wrapEventbusApi(plugin, corePluginApi.$eventbus, pluginApi)
|
|
117
117
|
}
|
|
118
118
|
|
|
119
119
|
const handleOperations = handlePluginOperations(
|
|
@@ -6,7 +6,7 @@ import log from "@racletteCore/lib/logger"
|
|
|
6
6
|
import { getUserToken } from "./sessionHandler"
|
|
7
7
|
import configService from "@racletteCore/lib/configService"
|
|
8
8
|
const registerSocketClient = ($socket, $eventbus) => {
|
|
9
|
-
$eventbus.on("
|
|
9
|
+
$eventbus.on("socket/join/room", (roomId?: string) => {
|
|
10
10
|
const { requireAuthentication } = configService.getConfig()?.global ?? {
|
|
11
11
|
requireAuthentication: true,
|
|
12
12
|
}
|
|
@@ -25,7 +25,7 @@ const registerSocketClient = ($socket, $eventbus) => {
|
|
|
25
25
|
$socket.emit("join", { roomId, token })
|
|
26
26
|
})
|
|
27
27
|
|
|
28
|
-
$eventbus.on("
|
|
28
|
+
$eventbus.on("socket/leave/room", (roomId) => {
|
|
29
29
|
log.socket("emitLeave", { roomId })
|
|
30
30
|
$socket.emit("leave", roomId)
|
|
31
31
|
})
|
|
@@ -206,7 +206,7 @@ const registerSocketEvents = ($socket, $store, $eventbus) => {
|
|
|
206
206
|
})
|
|
207
207
|
await setupSpace(compositions, interactionLinks, projectConfig)
|
|
208
208
|
|
|
209
|
-
$eventbus.emit("
|
|
209
|
+
$eventbus.emit("ui/setupProject", roomId)
|
|
210
210
|
})
|
|
211
211
|
// Reset all store states which are project dependent.
|
|
212
212
|
$store.dispatch({
|
|
@@ -263,7 +263,7 @@ const registerSocketEvents = ($socket, $store, $eventbus) => {
|
|
|
263
263
|
isOwnRequest: appSessionId === $socket.appSessionId,
|
|
264
264
|
})
|
|
265
265
|
handleServerItem(payload, true, false)
|
|
266
|
-
$eventbus.emit("
|
|
266
|
+
$eventbus.emit("socket/data/update", { offline: false, body })
|
|
267
267
|
})
|
|
268
268
|
|
|
269
269
|
/**
|
|
@@ -21,8 +21,8 @@ type LocaleObject = {
|
|
|
21
21
|
// TODO: outsource to a better place
|
|
22
22
|
const getLocalizedName = (localeObject: LocaleObject) => {
|
|
23
23
|
const locale = $store.getState(["ui", "locale"])
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
const localeName =
|
|
25
|
+
localeObject[locale] || localeObject[locale.split("-")?.[0]]
|
|
26
26
|
|
|
27
27
|
if (localeName) {
|
|
28
28
|
return localeName
|
|
@@ -6,7 +6,7 @@ import reducerFromMap from "@racletteCore/lib/reducerFromMap"
|
|
|
6
6
|
const reducerMap = {
|
|
7
7
|
init: reducers.init,
|
|
8
8
|
projectInit: reducers.projectInit,
|
|
9
|
-
"data/push": reducers.
|
|
9
|
+
"data/push": reducers.dataRead,
|
|
10
10
|
"data/create": reducers.dataCreate,
|
|
11
11
|
"data/update": reducers.dataUpdate,
|
|
12
12
|
"data/deleteFromCache": reducers.deleteFromCache,
|
|
@@ -134,7 +134,7 @@ const updateDataCache = (oldCache, newItems) => {
|
|
|
134
134
|
oldItem,
|
|
135
135
|
)
|
|
136
136
|
}
|
|
137
|
-
// we will always delete the offline flag as this function will only be called by the
|
|
137
|
+
// we will always delete the offline flag as this function will only be called by the dataRead which retrieves synced backend items
|
|
138
138
|
if (newCache[item._id]) {
|
|
139
139
|
delete newCache[item._id]._offline
|
|
140
140
|
}
|
|
@@ -189,7 +189,7 @@ const dataAddFromServer = (state, action) => {
|
|
|
189
189
|
* @param {Array} action.payload - An array of items to be added to the state. Each item is an object that must contain an `_id` property.
|
|
190
190
|
* @returns {Object} - Returns the new state after pushing the data from the action payload.
|
|
191
191
|
*/
|
|
192
|
-
const
|
|
192
|
+
const dataRead = (state, action) => {
|
|
193
193
|
const { payload } = action
|
|
194
194
|
|
|
195
195
|
// early return if no data
|
|
@@ -540,7 +540,7 @@ const addRequestedFor = (state, action) => {
|
|
|
540
540
|
export {
|
|
541
541
|
init,
|
|
542
542
|
projectInit,
|
|
543
|
-
|
|
543
|
+
dataRead,
|
|
544
544
|
dataUpdate,
|
|
545
545
|
dataMove,
|
|
546
546
|
dataCreate,
|
|
@@ -34,7 +34,26 @@ const queriesEffects = (store) => {
|
|
|
34
34
|
}),
|
|
35
35
|
ignoreElements(),
|
|
36
36
|
)
|
|
37
|
-
|
|
37
|
+
const queryiesSetCacheKey = actions$.pipe(
|
|
38
|
+
ofType("queries/setCacheKey"),
|
|
39
|
+
distinctUntilChanged((prev, curr) => !store.hasChanges(prev, curr)),
|
|
40
|
+
|
|
41
|
+
tap((action) => {
|
|
42
|
+
const updatedQuery = action?.actionResult?.updated || null
|
|
43
|
+
if (updatedQuery) {
|
|
44
|
+
const { item, itemBefore } = updatedQuery
|
|
45
|
+
const { actionId } = action
|
|
46
|
+
if (itemBefore.cacheKey && itemBefore.cacheKey !== item.cacheKey) {
|
|
47
|
+
store.dispatch({
|
|
48
|
+
type: "queriesCache/remove",
|
|
49
|
+
payload: { cacheKey: itemBefore.cacheKey, actionId },
|
|
50
|
+
})
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}),
|
|
54
|
+
ignoreElements(),
|
|
55
|
+
)
|
|
56
|
+
return [queriesAddExecute, queriesExecute, queryiesSetCacheKey]
|
|
38
57
|
}
|
|
39
58
|
|
|
40
59
|
export default queriesEffects
|
|
@@ -15,6 +15,7 @@ const reducerMap = {
|
|
|
15
15
|
"queries/updateItems": reducers.updateQueryItems,
|
|
16
16
|
"queries/update": reducers.updateQuery,
|
|
17
17
|
"queries/update/loading": reducers.queriesUpdateLoading,
|
|
18
|
+
"queries/setCacheKey": reducers.queryiesSetCacheKey,
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
const queriesReducers = reducerFromMap(reducerMap)
|
|
@@ -10,6 +10,8 @@ export type Query = {
|
|
|
10
10
|
target: string
|
|
11
11
|
actionId: string
|
|
12
12
|
params: Record<string, any>
|
|
13
|
+
options: Record<string, any>
|
|
14
|
+
config: Record<string, any>
|
|
13
15
|
loading?: boolean
|
|
14
16
|
backend?: Record<string, any>
|
|
15
17
|
uuids?: Array<string>
|
|
@@ -56,6 +58,12 @@ const updateQuery = (state, action) => {
|
|
|
56
58
|
if (payload.target) {
|
|
57
59
|
query.target = payload.target
|
|
58
60
|
}
|
|
61
|
+
if (payload.options) {
|
|
62
|
+
query.options = payload.options
|
|
63
|
+
}
|
|
64
|
+
if (payload.config) {
|
|
65
|
+
query.config = payload.config
|
|
66
|
+
}
|
|
59
67
|
if (payload.pageItems) {
|
|
60
68
|
const uuids = []
|
|
61
69
|
const results = payload.pageItems || null
|
|
@@ -83,7 +91,9 @@ const updateQuery = (state, action) => {
|
|
|
83
91
|
query.params = mergeDeepRight(query.params || {}, payload.params)
|
|
84
92
|
}
|
|
85
93
|
}
|
|
86
|
-
|
|
94
|
+
if (payload.cacheKey) {
|
|
95
|
+
query.cacheKey = payload.cacheKey
|
|
96
|
+
}
|
|
87
97
|
if (payload.backend) {
|
|
88
98
|
if (payload.reset) {
|
|
89
99
|
query.backend = payload.backend
|
|
@@ -98,7 +108,19 @@ const updateQuery = (state, action) => {
|
|
|
98
108
|
|
|
99
109
|
return queries
|
|
100
110
|
}
|
|
111
|
+
const queryiesSetCacheKey = (state, action) => {
|
|
112
|
+
let queries = structuredClone(state)
|
|
113
|
+
const payload = action.payload
|
|
114
|
+
const { actionId, cacheKey } = payload
|
|
115
|
+
if (!actionId || !state[actionId]) {
|
|
116
|
+
return state
|
|
117
|
+
}
|
|
101
118
|
|
|
119
|
+
queries[actionId] = { ...queries[actionId], cacheKey }
|
|
120
|
+
action.actionResult.updated.itemBefore = state[actionId]
|
|
121
|
+
action.actionResult.updated.item = queries[actionId]
|
|
122
|
+
return queries
|
|
123
|
+
}
|
|
102
124
|
const queriesUpdateLoading = (state, action) => {
|
|
103
125
|
const payload = action.payload
|
|
104
126
|
const actionId = payload.actionId
|
|
@@ -175,11 +197,15 @@ const queriesAdd = (state, action) => {
|
|
|
175
197
|
const params: CustomStoreActionParams = payload.params || {}
|
|
176
198
|
const actionId = payload.actionId
|
|
177
199
|
const target = payload.target
|
|
200
|
+
const config = payload.config || {}
|
|
201
|
+
const options = payload.options || {}
|
|
178
202
|
|
|
179
203
|
const query: Query = {
|
|
180
204
|
target,
|
|
181
205
|
params,
|
|
182
206
|
actionId,
|
|
207
|
+
options,
|
|
208
|
+
config,
|
|
183
209
|
}
|
|
184
210
|
|
|
185
211
|
action.actionResult.added.push(query)
|
|
@@ -216,6 +242,7 @@ const queriesRemove = (state, action) => {
|
|
|
216
242
|
}
|
|
217
243
|
|
|
218
244
|
export {
|
|
245
|
+
queryiesSetCacheKey,
|
|
219
246
|
queriesExecute,
|
|
220
247
|
queriesAdd,
|
|
221
248
|
queriesRemove,
|
|
@@ -2,7 +2,7 @@ import createStableHash from "@racletteCore/lib/createStableHash"
|
|
|
2
2
|
import { $store } from "@racletteCore"
|
|
3
3
|
import log from "@racletteCore/lib/logger"
|
|
4
4
|
|
|
5
|
-
const isParentResultFresh = (cacheKey: string): boolean => {
|
|
5
|
+
const isParentResultFresh = (cacheKey: string, ttl: number = 1000): boolean => {
|
|
6
6
|
const queriesState = $store.getState("queriesCache")
|
|
7
7
|
const currentTimeStamp = new Date().getTime()
|
|
8
8
|
const parentQuery = queriesState[cacheKey]
|
|
@@ -15,16 +15,17 @@ const isParentResultFresh = (cacheKey: string): boolean => {
|
|
|
15
15
|
) {
|
|
16
16
|
log.store(
|
|
17
17
|
"queryCacheHelper",
|
|
18
|
-
`
|
|
18
|
+
`cache #${cacheKey} has not been executed yet or is still fetching`,
|
|
19
|
+
parentQuery,
|
|
19
20
|
)
|
|
20
21
|
return false
|
|
21
22
|
}
|
|
22
23
|
|
|
23
|
-
const isParentResultFresh = parentQuery.lastFetched +
|
|
24
|
+
const isParentResultFresh = parentQuery.lastFetched + ttl >= currentTimeStamp
|
|
24
25
|
|
|
25
26
|
log.store(
|
|
26
27
|
"queryCacheHelper",
|
|
27
|
-
`
|
|
28
|
+
`cache #${cacheKey} is ${isParentResultFresh ? "fresh" : "stale"} for ttl of ${ttl}ms`,
|
|
28
29
|
)
|
|
29
30
|
|
|
30
31
|
return isParentResultFresh
|
|
@@ -22,7 +22,7 @@ const getAffectedCacheQuery = (state, actionId) => {
|
|
|
22
22
|
})
|
|
23
23
|
return state[removedQueryCacheKey]
|
|
24
24
|
}
|
|
25
|
-
const getChildQueries = (cacheKey: string): Array => {
|
|
25
|
+
const getChildQueries = (cacheKey: string): Array<Record<string, object>> => {
|
|
26
26
|
const queries = $store.getState("queries")
|
|
27
27
|
const childQueries = []
|
|
28
28
|
Object.values(queries).forEach((query) => {
|
|
@@ -107,6 +107,7 @@ const cacheRemove = (state, action) => {
|
|
|
107
107
|
|
|
108
108
|
return newState
|
|
109
109
|
}
|
|
110
|
+
|
|
110
111
|
const cacheChildRemove = (state, action) => {
|
|
111
112
|
const newState = structuredClone(state)
|
|
112
113
|
const { actionId } = action.payload
|
|
@@ -118,7 +119,7 @@ const cacheChildRemove = (state, action) => {
|
|
|
118
119
|
}
|
|
119
120
|
const childQueries = getChildQueries(affectedCacheQuery.cacheKey)
|
|
120
121
|
if (childQueries.length === 1) {
|
|
121
|
-
// if the action which is currently deleted is the last one needing this cache, we will give it a
|
|
122
|
+
// if the action which is currently deleted is the last one needing this cache, we will give it a 2sek grace period before we remove the cache
|
|
122
123
|
newState[affectedCacheQuery.cacheKey].deleted = true
|
|
123
124
|
if (deleteTimeouts[affectedCacheQuery.cacheKey]) {
|
|
124
125
|
clearTimeout(deleteTimeouts[affectedCacheQuery.cacheKey])
|
|
@@ -129,7 +130,7 @@ const cacheChildRemove = (state, action) => {
|
|
|
129
130
|
type: "queriesCache/remove",
|
|
130
131
|
payload: { cacheKey: affectedCacheQuery.cacheKey, actionId },
|
|
131
132
|
})
|
|
132
|
-
},
|
|
133
|
+
}, 2000)
|
|
133
134
|
}
|
|
134
135
|
delete cacheMap[actionId]
|
|
135
136
|
return newState
|
|
@@ -155,7 +155,7 @@ const storePatterns = {
|
|
|
155
155
|
// a deeper abstractation level for widgets which are used as tools.
|
|
156
156
|
// ie. type:''add' create a folder called 'add' and create a default.vue
|
|
157
157
|
// or FACE.vue containing your add logic for a given widget
|
|
158
|
-
|
|
158
|
+
workingState: {},
|
|
159
159
|
version: "0.0.0",
|
|
160
160
|
},
|
|
161
161
|
tools: {
|
|
@@ -7,12 +7,14 @@ export type CustomStoreActionOptions = {
|
|
|
7
7
|
notify?: boolean // default true, disables notification/snackbar
|
|
8
8
|
responseType?: string // i.e stream
|
|
9
9
|
mode?: string //i.e cors for streaming
|
|
10
|
+
useCache?: boolean
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
export type CustomStoreActionsPayload = {
|
|
13
14
|
id?: String // if set this will used as the final namespace giver for the actionId, if not it will be a nanoId
|
|
14
15
|
params?: CustomStoreActionParams
|
|
15
16
|
options?: CustomStoreActionOptions
|
|
17
|
+
config?: any
|
|
16
18
|
}
|
|
17
19
|
export type QueryApiQuery = QueryState & {
|
|
18
20
|
execute: (params?: Record<string, any>) => Promise<any>
|
|
@@ -23,6 +25,8 @@ export type DataApiMethods = {
|
|
|
23
25
|
response: Object
|
|
24
26
|
isLoading: Boolean
|
|
25
27
|
execute: Function
|
|
28
|
+
clear: Function
|
|
29
|
+
remove: Function
|
|
26
30
|
}
|
|
27
31
|
export type QueryMethods = DataApiMethods & {
|
|
28
32
|
uuids: Array<string>
|
|
@@ -77,6 +77,8 @@
|
|
|
77
77
|
class="tw:overflow-y-auto! tw:pb-0"
|
|
78
78
|
:class="{ '!tw:invisible': loading }"
|
|
79
79
|
:widgets-layout="widgetsLayout"
|
|
80
|
+
slot-type="page"
|
|
81
|
+
:slot-layout="slotLayout"
|
|
80
82
|
@scroll.passive="onScroll($event)"
|
|
81
83
|
/>
|
|
82
84
|
|
|
@@ -133,11 +135,10 @@ import { useRoute } from "vue-router"
|
|
|
133
135
|
import useUiState from "./composables/useUiState"
|
|
134
136
|
import useRouteState from "./composables/useRouteState"
|
|
135
137
|
import CompositionOverlay from "./components/composition/CompositionOverlay.vue"
|
|
136
|
-
import { useTitle } from "@vueuse/core"
|
|
138
|
+
import { useTitle, useLocalStorage } from "@vueuse/core"
|
|
137
139
|
import loginUserNotifications from "./helpers/loginUserNotifications"
|
|
138
140
|
import configService from "@racletteCore/lib/configService"
|
|
139
141
|
import { isDevelopmentMode } from "@racletteCore/helpers/devMode"
|
|
140
|
-
import { useLocalStorage } from "@vueuse/core"
|
|
141
142
|
import useDragAndDrop from "./composables/useDragAndDrop"
|
|
142
143
|
import { useCurrentComposition } from "./composables"
|
|
143
144
|
import WidgetsLayoutLoader from "./components/composition/WidgetsLayoutLoader.vue"
|
|
@@ -151,7 +152,7 @@ const { loading, theme, locale, landingPage, availableInterfaces } =
|
|
|
151
152
|
useUiState()
|
|
152
153
|
useRouteState()
|
|
153
154
|
const { isDraggingOrResizingAnything } = useDragAndDrop()
|
|
154
|
-
const { widgetsLayout } = useCurrentComposition()
|
|
155
|
+
const { widgetsLayout, slotLayout } = useCurrentComposition()
|
|
155
156
|
|
|
156
157
|
const showWelcomeScreen = computed(() => {
|
|
157
158
|
const isDynamicPage = route.name === "app.space.page"
|
|
@@ -208,20 +209,31 @@ const checkImageExists = async (url: string): Promise<boolean> => {
|
|
|
208
209
|
const showScrollToTopBtn = ref(false)
|
|
209
210
|
const isDevelopment = ref(false)
|
|
210
211
|
|
|
212
|
+
const setTheme = (theme: "dark" | "light") => {
|
|
213
|
+
vuetifyTheme.change(theme)
|
|
214
|
+
|
|
215
|
+
// tailwind support
|
|
216
|
+
if (theme === "dark") {
|
|
217
|
+
document.body.classList.add("dark")
|
|
218
|
+
} else {
|
|
219
|
+
document.body.classList.remove("dark")
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
211
223
|
const onScroll = (e) =>
|
|
212
224
|
(showScrollToTopBtn.value = e.currentTarget.scrollTop > 0)
|
|
213
225
|
|
|
214
226
|
onMounted(async () => {
|
|
215
|
-
|
|
227
|
+
setTheme(theme.value)
|
|
216
228
|
vuetifyLocale.current.value = locale.value
|
|
217
|
-
isDevelopment.value = isDevelopmentMode()
|
|
229
|
+
isDevelopment.value = true || isDevelopmentMode()
|
|
218
230
|
logoExists.value = await checkImageExists(logoSrc.value)
|
|
219
231
|
// check if we have a message from checkToken to display as a snackbar
|
|
220
232
|
loginUserNotifications()
|
|
221
233
|
})
|
|
222
234
|
|
|
223
235
|
watch(theme, () => {
|
|
224
|
-
|
|
236
|
+
setTheme(theme.value)
|
|
225
237
|
})
|
|
226
238
|
|
|
227
239
|
// set vuetify locale here, the rest is done in setup/i18n
|
|
@@ -233,7 +245,7 @@ window
|
|
|
233
245
|
.addEventListener("change", (event) => {
|
|
234
246
|
const newColorScheme = event.matches ? "dark" : "light"
|
|
235
247
|
if (userTheme.value === null) {
|
|
236
|
-
|
|
248
|
+
setTheme(theme.value)
|
|
237
249
|
}
|
|
238
250
|
})
|
|
239
251
|
</script>
|
|
@@ -1,40 +1,29 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="welcome-screen">
|
|
3
|
-
<
|
|
4
|
-
|
|
5
|
-
<v-
|
|
6
|
-
<
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
<v-expansion-
|
|
11
|
-
<v-expansion-panel
|
|
12
|
-
<v-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
<
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
<
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
>
|
|
26
|
-
<v-chip
|
|
27
|
-
v-if="feature.status"
|
|
28
|
-
:color="feature.status.color"
|
|
29
|
-
size="small"
|
|
30
|
-
class="tw:mt-2"
|
|
31
|
-
>
|
|
32
|
-
<v-icon start :icon="feature.status.icon"></v-icon>
|
|
33
|
-
{{ $t(`core.welcomeScreen.${feature.status.key}`) }}
|
|
34
|
-
</v-chip>
|
|
35
|
-
</a>
|
|
3
|
+
<component :is="currentComponent" />
|
|
4
|
+
<v-row>
|
|
5
|
+
<v-col cols="12">
|
|
6
|
+
<h2 class="tw:text-2xl tw:font-semibold tw:mb-4">
|
|
7
|
+
{{ $t("core.welcomeScreen.builtInFeaturesTitle") }}
|
|
8
|
+
</h2>
|
|
9
|
+
<v-expansion-panels flat variant="accordion">
|
|
10
|
+
<v-expansion-panel v-for="feature in features" :key="feature.key">
|
|
11
|
+
<v-expansion-panel-title>
|
|
12
|
+
<v-icon :icon="feature.icon" class="tw:mr-3"></v-icon>
|
|
13
|
+
{{ $t(`core.welcomeScreen.${feature.key}Title`) }}
|
|
14
|
+
</v-expansion-panel-title>
|
|
15
|
+
<v-expansion-panel-text>
|
|
16
|
+
<div class="tw:py-2">
|
|
17
|
+
{{ $t(`core.welcomeScreen.${feature.key}Description`) }}
|
|
18
|
+
</div>
|
|
19
|
+
<template v-if="feature.status">
|
|
20
|
+
<a
|
|
21
|
+
v-if="feature.status.link"
|
|
22
|
+
target="_blank"
|
|
23
|
+
:href="feature.status.link"
|
|
24
|
+
>
|
|
36
25
|
<v-chip
|
|
37
|
-
v-
|
|
26
|
+
v-if="feature.status"
|
|
38
27
|
:color="feature.status.color"
|
|
39
28
|
size="small"
|
|
40
29
|
class="tw:mt-2"
|
|
@@ -42,13 +31,22 @@
|
|
|
42
31
|
<v-icon start :icon="feature.status.icon"></v-icon>
|
|
43
32
|
{{ $t(`core.welcomeScreen.${feature.status.key}`) }}
|
|
44
33
|
</v-chip>
|
|
45
|
-
</
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
34
|
+
</a>
|
|
35
|
+
<v-chip
|
|
36
|
+
v-else
|
|
37
|
+
:color="feature.status.color"
|
|
38
|
+
size="small"
|
|
39
|
+
class="tw:mt-2"
|
|
40
|
+
>
|
|
41
|
+
<v-icon start :icon="feature.status.icon"></v-icon>
|
|
42
|
+
{{ $t(`core.welcomeScreen.${feature.status.key}`) }}
|
|
43
|
+
</v-chip>
|
|
44
|
+
</template>
|
|
45
|
+
</v-expansion-panel-text>
|
|
46
|
+
</v-expansion-panel>
|
|
47
|
+
</v-expansion-panels>
|
|
48
|
+
</v-col>
|
|
49
|
+
</v-row>
|
|
52
50
|
</div>
|
|
53
51
|
</template>
|
|
54
52
|
|
|
@@ -11,6 +11,9 @@
|
|
|
11
11
|
/* @import "tailwindcss/preflight.css" layer(base) prefix(tw); */
|
|
12
12
|
/* @import "tailwindcss/utilities.css" layer(utilities) prefix(tw); */
|
|
13
13
|
|
|
14
|
+
/* enable dark mode via class */
|
|
15
|
+
@custom-variant dark (&:where(.dark, .dark *));
|
|
16
|
+
|
|
14
17
|
/* safelist for the resizing in the composition editor */
|
|
15
18
|
@source inline('tw:col-span-{1..12}');
|
|
16
19
|
@source inline('tw:grid-cols-{1..12}');
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
export default {
|
|
5
5
|
background: "#212121",
|
|
6
6
|
surface: "#212121",
|
|
7
|
-
primary: "#
|
|
7
|
+
primary: "#0b6487",
|
|
8
8
|
"primary-darken-1": "#1279a2",
|
|
9
9
|
"primary-darken-2": "#106689",
|
|
10
10
|
"primary-darken-3": "#0e5470",
|
|
@@ -19,7 +19,7 @@ export default {
|
|
|
19
19
|
"primary-lighten-5": "#9dd8f2",
|
|
20
20
|
"primary-lighten-6": "#c4e7f7",
|
|
21
21
|
"primary-lighten-7": "#ebf5fc",
|
|
22
|
-
secondary: "#
|
|
22
|
+
secondary: "#017f73",
|
|
23
23
|
"secondary-darken-1": "#02b7a6",
|
|
24
24
|
"secondary-darken-2": "#029487",
|
|
25
25
|
error: "#FF5252",
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<DefaultModal v-model="showModal">
|
|
3
|
-
<
|
|
3
|
+
<div class="tw:p-5 tw:h-full">
|
|
4
|
+
<WidgetsLayoutLoader
|
|
5
|
+
v-if="widgetsLayout"
|
|
6
|
+
:widgets-layout="widgetsLayout"
|
|
7
|
+
:slot-layout="slotLayout"
|
|
8
|
+
slot-type="modal"
|
|
9
|
+
/>
|
|
10
|
+
</div>
|
|
4
11
|
</DefaultModal>
|
|
5
12
|
</template>
|
|
6
13
|
|
|
@@ -11,7 +18,9 @@ import { computed } from "vue"
|
|
|
11
18
|
import useRouteState from "@racletteOrchestrator/composables/useRouteState"
|
|
12
19
|
import { DEFAULT_MODAL_SLOT_NAME } from "@racletteOrchestrator/router/routeParserHelper"
|
|
13
20
|
|
|
14
|
-
const { widgetsLayout } = useCurrentComposition(
|
|
21
|
+
const { widgetsLayout, slotLayout } = useCurrentComposition(
|
|
22
|
+
DEFAULT_MODAL_SLOT_NAME,
|
|
23
|
+
)
|
|
15
24
|
const { removeSlot } = useRouteState()
|
|
16
25
|
|
|
17
26
|
const showModal = computed({
|