Merge branch 'master' into BUDI-8986/validate-datasource-setting-on-components
This commit is contained in:
commit
d0516f807a
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"$schema": "node_modules/lerna/schemas/lerna-schema.json",
|
||||
"version": "3.3.0",
|
||||
"version": "3.3.1",
|
||||
"npmClient": "yarn",
|
||||
"concurrency": 20,
|
||||
"command": {
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
const processModals = () => {
|
||||
const defaultCacheFn = key => {
|
||||
temporalStore.actions.setExpiring(key, {}, oneDayInSeconds)
|
||||
temporalStore.setExpiring(key, {}, oneDayInSeconds)
|
||||
}
|
||||
|
||||
const dismissableModals = [
|
||||
|
@ -50,7 +50,7 @@
|
|||
},
|
||||
]
|
||||
return dismissableModals.filter(modal => {
|
||||
return !temporalStore.actions.getExpiring(modal.key) && modal.criteria()
|
||||
return !temporalStore.getExpiring(modal.key) && modal.criteria()
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ import { BANNER_TYPES } from "@budibase/bbui"
|
|||
const oneDayInSeconds = 86400
|
||||
|
||||
const defaultCacheFn = key => {
|
||||
temporalStore.actions.setExpiring(key, {}, oneDayInSeconds)
|
||||
temporalStore.setExpiring(key, {}, oneDayInSeconds)
|
||||
}
|
||||
|
||||
const upgradeAction = key => {
|
||||
|
@ -148,7 +148,7 @@ export const getBanners = () => {
|
|||
buildUsersAboveLimitBanner(ExpiringKeys.LICENSING_USERS_ABOVE_LIMIT_BANNER),
|
||||
].filter(licensingBanner => {
|
||||
return (
|
||||
!temporalStore.actions.getExpiring(licensingBanner.key) &&
|
||||
!temporalStore.getExpiring(licensingBanner.key) &&
|
||||
licensingBanner.criteria()
|
||||
)
|
||||
})
|
||||
|
|
|
@ -11,7 +11,7 @@ export const datasourceSelect = {
|
|||
},
|
||||
viewV2: (view, datasources) => {
|
||||
const datasource = datasources
|
||||
.filter(f => f.entities)
|
||||
?.filter(f => f.entities)
|
||||
.flatMap(d => d.entities)
|
||||
.find(ds => ds._id === view.tableId)
|
||||
return {
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
$: useAccountPortal = cloud && !$admin.disableAccountPortal
|
||||
|
||||
navigation.actions.init($redirect)
|
||||
navigation.init($redirect)
|
||||
|
||||
const validateTenantId = async () => {
|
||||
const host = window.location.host
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { it, expect, describe, beforeEach, vi } from "vitest"
|
||||
import { createAdminStore } from "./admin"
|
||||
import { AdminStore } from "./admin"
|
||||
import { writable, get } from "svelte/store"
|
||||
import { API } from "@/api"
|
||||
import { auth } from "@/stores/portal"
|
||||
|
@ -46,16 +46,7 @@ describe("admin store", () => {
|
|||
ctx.writableReturn = { update: vi.fn(), subscribe: vi.fn() }
|
||||
writable.mockReturnValue(ctx.writableReturn)
|
||||
|
||||
ctx.returnedStore = createAdminStore()
|
||||
})
|
||||
|
||||
it("returns the created store", ctx => {
|
||||
expect(ctx.returnedStore).toEqual({
|
||||
subscribe: expect.toBe(ctx.writableReturn.subscribe),
|
||||
init: expect.toBeFunc(),
|
||||
unload: expect.toBeFunc(),
|
||||
getChecklist: expect.toBeFunc(),
|
||||
})
|
||||
ctx.returnedStore = new AdminStore()
|
||||
})
|
||||
|
||||
describe("init method", () => {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { writable, get } from "svelte/store"
|
||||
import { get } from "svelte/store"
|
||||
import { API } from "@/api"
|
||||
import { auth } from "@/stores/portal"
|
||||
import { banner } from "@budibase/bbui"
|
||||
|
@ -7,42 +7,44 @@ import {
|
|||
GetEnvironmentResponse,
|
||||
SystemStatusResponse,
|
||||
} from "@budibase/types"
|
||||
import { BudiStore } from "../BudiStore"
|
||||
|
||||
interface PortalAdminStore extends GetEnvironmentResponse {
|
||||
interface AdminState extends GetEnvironmentResponse {
|
||||
loaded: boolean
|
||||
checklist?: ConfigChecklistResponse
|
||||
status?: SystemStatusResponse
|
||||
}
|
||||
|
||||
export function createAdminStore() {
|
||||
const admin = writable<PortalAdminStore>({
|
||||
loaded: false,
|
||||
multiTenancy: false,
|
||||
cloud: false,
|
||||
isDev: false,
|
||||
disableAccountPortal: false,
|
||||
offlineMode: false,
|
||||
maintenance: [],
|
||||
})
|
||||
export class AdminStore extends BudiStore<AdminState> {
|
||||
constructor() {
|
||||
super({
|
||||
loaded: false,
|
||||
multiTenancy: false,
|
||||
cloud: false,
|
||||
isDev: false,
|
||||
disableAccountPortal: false,
|
||||
offlineMode: false,
|
||||
maintenance: [],
|
||||
})
|
||||
}
|
||||
|
||||
async function init() {
|
||||
await getChecklist()
|
||||
await getEnvironment()
|
||||
async init() {
|
||||
await this.getChecklist()
|
||||
await this.getEnvironment()
|
||||
// enable system status checks in the cloud
|
||||
if (get(admin).cloud) {
|
||||
await getSystemStatus()
|
||||
checkStatus()
|
||||
if (get(this.store).cloud) {
|
||||
await this.getSystemStatus()
|
||||
this.checkStatus()
|
||||
}
|
||||
|
||||
admin.update(store => {
|
||||
this.update(store => {
|
||||
store.loaded = true
|
||||
return store
|
||||
})
|
||||
}
|
||||
|
||||
async function getEnvironment() {
|
||||
async getEnvironment() {
|
||||
const environment = await API.getEnvironment()
|
||||
admin.update(store => {
|
||||
this.update(store => {
|
||||
store.multiTenancy = environment.multiTenancy
|
||||
store.cloud = environment.cloud
|
||||
store.disableAccountPortal = environment.disableAccountPortal
|
||||
|
@ -56,43 +58,36 @@ export function createAdminStore() {
|
|||
})
|
||||
}
|
||||
|
||||
const checkStatus = async () => {
|
||||
const health = get(admin)?.status?.health
|
||||
async checkStatus() {
|
||||
const health = get(this.store).status?.health
|
||||
if (!health?.passing) {
|
||||
await banner.showStatus()
|
||||
}
|
||||
}
|
||||
|
||||
async function getSystemStatus() {
|
||||
async getSystemStatus() {
|
||||
const status = await API.getSystemStatus()
|
||||
admin.update(store => {
|
||||
this.update(store => {
|
||||
store.status = status
|
||||
return store
|
||||
})
|
||||
}
|
||||
|
||||
async function getChecklist() {
|
||||
async getChecklist() {
|
||||
const tenantId = get(auth).tenantId
|
||||
const checklist = await API.getChecklist(tenantId)
|
||||
admin.update(store => {
|
||||
this.update(store => {
|
||||
store.checklist = checklist
|
||||
return store
|
||||
})
|
||||
}
|
||||
|
||||
function unload() {
|
||||
admin.update(store => {
|
||||
unload() {
|
||||
this.update(store => {
|
||||
store.loaded = false
|
||||
return store
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
subscribe: admin.subscribe,
|
||||
init,
|
||||
unload,
|
||||
getChecklist,
|
||||
}
|
||||
}
|
||||
|
||||
export const admin = createAdminStore()
|
||||
export const admin = new AdminStore()
|
||||
|
|
|
@ -13,7 +13,7 @@ interface PortalAuditLogsStore {
|
|||
logs?: SearchAuditLogsResponse
|
||||
}
|
||||
|
||||
export class AuditLogsStore extends BudiStore<PortalAuditLogsStore> {
|
||||
class AuditLogsStore extends BudiStore<PortalAuditLogsStore> {
|
||||
constructor() {
|
||||
super({})
|
||||
}
|
||||
|
|
|
@ -1,38 +1,31 @@
|
|||
import { writable } from "svelte/store"
|
||||
import { BudiStore } from "../BudiStore"
|
||||
|
||||
type GotoFuncType = (path: string) => void
|
||||
|
||||
interface PortalNavigationStore {
|
||||
interface NavigationState {
|
||||
initialisated: boolean
|
||||
goto: GotoFuncType
|
||||
}
|
||||
|
||||
export function createNavigationStore() {
|
||||
const store = writable<PortalNavigationStore>({
|
||||
initialisated: false,
|
||||
goto: undefined as any,
|
||||
})
|
||||
const { set, subscribe } = store
|
||||
class NavigationStore extends BudiStore<NavigationState> {
|
||||
constructor() {
|
||||
super({
|
||||
initialisated: false,
|
||||
goto: undefined as any,
|
||||
})
|
||||
}
|
||||
|
||||
const init = (gotoFunc: GotoFuncType) => {
|
||||
init(gotoFunc: GotoFuncType) {
|
||||
if (typeof gotoFunc !== "function") {
|
||||
throw new Error(
|
||||
`gotoFunc must be a function, found a "${typeof gotoFunc}" instead`
|
||||
)
|
||||
}
|
||||
|
||||
set({
|
||||
this.set({
|
||||
initialisated: true,
|
||||
goto: gotoFunc,
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
subscribe,
|
||||
actions: {
|
||||
init,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export const navigation = createNavigationStore()
|
||||
export const navigation = new NavigationStore()
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
import { writable } from "svelte/store"
|
||||
import { API } from "@/api"
|
||||
|
||||
export function templatesStore() {
|
||||
const { subscribe, set } = writable([])
|
||||
|
||||
return {
|
||||
subscribe,
|
||||
load: async () => {
|
||||
const templates = await API.getAppTemplates()
|
||||
set(templates)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export const templates = templatesStore()
|
|
@ -0,0 +1,16 @@
|
|||
import { API } from "@/api"
|
||||
import { BudiStore } from "../BudiStore"
|
||||
import { TemplateMetadata } from "@budibase/types"
|
||||
|
||||
class TemplateStore extends BudiStore<TemplateMetadata[]> {
|
||||
constructor() {
|
||||
super([])
|
||||
}
|
||||
|
||||
async load() {
|
||||
const templates = await API.getAppTemplates()
|
||||
this.set(templates)
|
||||
}
|
||||
}
|
||||
|
||||
export const templates = new TemplateStore()
|
|
@ -1,45 +0,0 @@
|
|||
import { createLocalStorageStore } from "@budibase/frontend-core"
|
||||
import { get } from "svelte/store"
|
||||
|
||||
export const createTemporalStore = () => {
|
||||
const initialValue = {}
|
||||
|
||||
const localStorageKey = `bb-temporal`
|
||||
const store = createLocalStorageStore(localStorageKey, initialValue)
|
||||
|
||||
const setExpiring = (key, data, duration) => {
|
||||
const updated = {
|
||||
...data,
|
||||
expiry: Date.now() + duration * 1000,
|
||||
}
|
||||
|
||||
store.update(state => ({
|
||||
...state,
|
||||
[key]: updated,
|
||||
}))
|
||||
}
|
||||
|
||||
const getExpiring = key => {
|
||||
const entry = get(store)[key]
|
||||
if (!entry) {
|
||||
return
|
||||
}
|
||||
const currentExpiry = entry.expiry
|
||||
if (currentExpiry < Date.now()) {
|
||||
store.update(state => {
|
||||
delete state[key]
|
||||
return state
|
||||
})
|
||||
return null
|
||||
} else {
|
||||
return entry
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
subscribe: store.subscribe,
|
||||
actions: { setExpiring, getExpiring },
|
||||
}
|
||||
}
|
||||
|
||||
export const temporalStore = createTemporalStore()
|
|
@ -0,0 +1,53 @@
|
|||
import { get } from "svelte/store"
|
||||
import { BudiStore, PersistenceType } from "../BudiStore"
|
||||
|
||||
type TemporalItem = Record<string, any> & { expiry: number }
|
||||
type TemporalState = Record<string, TemporalItem>
|
||||
|
||||
class TemporalStore extends BudiStore<TemporalState> {
|
||||
constructor() {
|
||||
super(
|
||||
{},
|
||||
{
|
||||
persistence: {
|
||||
key: "bb-temporal",
|
||||
type: PersistenceType.LOCAL,
|
||||
},
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
setExpiring = (
|
||||
key: string,
|
||||
data: Record<string, any>,
|
||||
durationSeconds: number
|
||||
) => {
|
||||
const updated: TemporalItem = {
|
||||
...data,
|
||||
expiry: Date.now() + durationSeconds * 1000,
|
||||
}
|
||||
this.update(state => ({
|
||||
...state,
|
||||
[key]: updated,
|
||||
}))
|
||||
}
|
||||
|
||||
getExpiring(key: string) {
|
||||
const entry = get(this.store)[key]
|
||||
if (!entry) {
|
||||
return null
|
||||
}
|
||||
const currentExpiry = entry.expiry
|
||||
if (currentExpiry < Date.now()) {
|
||||
this.update(state => {
|
||||
delete state[key]
|
||||
return state
|
||||
})
|
||||
return null
|
||||
} else {
|
||||
return entry
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const temporalStore = new TemporalStore()
|
|
@ -1,37 +0,0 @@
|
|||
import { createLocalStorageStore } from "@budibase/frontend-core"
|
||||
import { derived } from "svelte/store"
|
||||
import {
|
||||
DefaultBuilderTheme,
|
||||
ensureValidTheme,
|
||||
getThemeClassNames,
|
||||
ThemeOptions,
|
||||
ThemeClassPrefix,
|
||||
} from "@budibase/shared-core"
|
||||
|
||||
export const getThemeStore = () => {
|
||||
const themeElement = document.documentElement
|
||||
const initialValue = {
|
||||
theme: DefaultBuilderTheme,
|
||||
}
|
||||
const store = createLocalStorageStore("bb-theme", initialValue)
|
||||
const derivedStore = derived(store, $store => ({
|
||||
...$store,
|
||||
theme: ensureValidTheme($store.theme, DefaultBuilderTheme),
|
||||
}))
|
||||
|
||||
// Update theme class when store changes
|
||||
derivedStore.subscribe(({ theme }) => {
|
||||
const classNames = getThemeClassNames(theme).split(" ")
|
||||
ThemeOptions.forEach(option => {
|
||||
const className = `${ThemeClassPrefix}${option.id}`
|
||||
themeElement.classList.toggle(className, classNames.includes(className))
|
||||
})
|
||||
})
|
||||
|
||||
return {
|
||||
...store,
|
||||
subscribe: derivedStore.subscribe,
|
||||
}
|
||||
}
|
||||
|
||||
export const themeStore = getThemeStore()
|
|
@ -0,0 +1,45 @@
|
|||
import { derived, Writable } from "svelte/store"
|
||||
import {
|
||||
DefaultBuilderTheme,
|
||||
ensureValidTheme,
|
||||
getThemeClassNames,
|
||||
ThemeOptions,
|
||||
ThemeClassPrefix,
|
||||
} from "@budibase/shared-core"
|
||||
import { Theme } from "@budibase/types"
|
||||
import { DerivedBudiStore, PersistenceType } from "../BudiStore"
|
||||
|
||||
interface ThemeState {
|
||||
theme: Theme
|
||||
}
|
||||
|
||||
class ThemeStore extends DerivedBudiStore<ThemeState, ThemeState> {
|
||||
constructor() {
|
||||
const makeDerivedStore = (store: Writable<ThemeState>) => {
|
||||
return derived(store, $store => ({
|
||||
...$store,
|
||||
theme: ensureValidTheme($store.theme, DefaultBuilderTheme),
|
||||
}))
|
||||
}
|
||||
super({ theme: DefaultBuilderTheme }, makeDerivedStore, {
|
||||
persistence: {
|
||||
key: "bb-theme",
|
||||
type: PersistenceType.LOCAL,
|
||||
},
|
||||
})
|
||||
|
||||
// Update theme class when store changes
|
||||
this.subscribe(({ theme }) => {
|
||||
const classNames = getThemeClassNames(theme).split(" ")
|
||||
ThemeOptions.forEach(option => {
|
||||
const className = `${ThemeClassPrefix}${option.id}`
|
||||
document.documentElement.classList.toggle(
|
||||
className,
|
||||
classNames.includes(className)
|
||||
)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export const themeStore = new ThemeStore()
|
Loading…
Reference in New Issue