From 4339bf1d3c36c1c0bf31fd227d159be964060330 Mon Sep 17 00:00:00 2001 From: Naveen Kumar Date: Tue, 24 Dec 2024 13:29:06 +0530 Subject: [PATCH 01/11] fix, handling use case when duplicate step name is allowed --- .../AutomationBuilder/FlowChart/FlowItemHeader.svelte | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/FlowItemHeader.svelte b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/FlowItemHeader.svelte index 0aa43f8e04..523f00b351 100644 --- a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/FlowItemHeader.svelte +++ b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/FlowItemHeader.svelte @@ -22,7 +22,7 @@ const dispatch = createEventDispatcher() $: blockRefs = $selectedAutomation?.blockRefs || {} - $: stepNames = automation?.definition.stepNames + $: stepNames = automation?.definition.stepNames || {} $: allSteps = automation?.definition.steps || [] $: automationName = itemName || stepNames?.[block.id] || block?.name || "" $: automationNameError = getAutomationNameError(automationName) @@ -64,7 +64,7 @@ const getAutomationNameError = name => { const duplicateError = "This name already exists, please enter a unique name" - if (stepNames && editing) { + if (editing) { for (const [key, value] of Object.entries(stepNames)) { if (name !== block.name && name === value && key !== block.id) { return duplicateError From f5ebc6b2497bbbbddf5d592209f78e1060fde9e6 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 24 Dec 2024 13:41:17 +0100 Subject: [PATCH 02/11] Type validation --- .../src/components/grid/stores/index.ts | 5 +++- .../stores/{validation.js => validation.ts} | 29 +++++++++++++------ 2 files changed, 24 insertions(+), 10 deletions(-) rename packages/frontend-core/src/components/grid/stores/{validation.js => validation.ts} (69%) diff --git a/packages/frontend-core/src/components/grid/stores/index.ts b/packages/frontend-core/src/components/grid/stores/index.ts index f2b6c973b9..90e89cbf4c 100644 --- a/packages/frontend-core/src/components/grid/stores/index.ts +++ b/packages/frontend-core/src/components/grid/stores/index.ts @@ -60,7 +60,8 @@ export type Store = BaseStore & Table.Store & ViewV2.Store & NonPlus.Store & - Datasource.Store & { + Datasource.Store & + Validation.Store & { // TODO while typing the rest of stores fetch: Writable filter: Writable @@ -76,6 +77,8 @@ export type Store = BaseStore & dispatch: (event: string, data: any) => any notifications: Writable schemaOverrides: Writable + focusedCellId: Writable + previousFocusedRowId: Writable } export const attachStores = (context: Store): Store => { diff --git a/packages/frontend-core/src/components/grid/stores/validation.js b/packages/frontend-core/src/components/grid/stores/validation.ts similarity index 69% rename from packages/frontend-core/src/components/grid/stores/validation.js rename to packages/frontend-core/src/components/grid/stores/validation.ts index 93e67e1d31..32bb1cf978 100644 --- a/packages/frontend-core/src/components/grid/stores/validation.js +++ b/packages/frontend-core/src/components/grid/stores/validation.ts @@ -1,10 +1,21 @@ -import { writable, get, derived } from "svelte/store" +import { writable, get, derived, Writable, Readable } from "svelte/store" +import { Store as StoreContext } from "." import { parseCellID } from "../lib/utils" +interface ValidationStore { + validation: Writable> +} + +interface DerivedValidationStore { + validationRowLookupMap: Readable> +} + +export type Store = ValidationStore & DerivedValidationStore + // Normally we would break out actions into the explicit "createActions" // function, but for validation all these actions are pure so can go into // "createStores" instead to make dependency ordering simpler -export const createStores = () => { +export const createStores = (): ValidationStore => { const validation = writable({}) return { @@ -12,12 +23,12 @@ export const createStores = () => { } } -export const deriveStores = context => { +export const deriveStores = (context: StoreContext): DerivedValidationStore => { const { validation } = context // Derive which rows have errors so that we can use that info later const validationRowLookupMap = derived(validation, $validation => { - let map = {} + const map: Record = {} Object.entries($validation).forEach(([key, error]) => { // Extract row ID from all errored cell IDs if (error) { @@ -36,10 +47,10 @@ export const deriveStores = context => { } } -export const createActions = context => { +export const createActions = (context: StoreContext) => { const { validation, focusedCellId, validationRowLookupMap } = context - const setError = (cellId, error) => { + const setError = (cellId: string | undefined, error: string) => { if (!cellId) { return } @@ -49,11 +60,11 @@ export const createActions = context => { })) } - const rowHasErrors = rowId => { + const rowHasErrors = (rowId: string) => { return get(validationRowLookupMap)[rowId]?.length > 0 } - const focusFirstRowError = rowId => { + const focusFirstRowError = (rowId: string) => { const errorCells = get(validationRowLookupMap)[rowId] const cellId = errorCells?.[0] if (cellId) { @@ -73,7 +84,7 @@ export const createActions = context => { } } -export const initialise = context => { +export const initialise = (context: StoreContext) => { const { validation, previousFocusedRowId, validationRowLookupMap } = context // Remove validation errors when changing rows From ad21b2e1fd10bd9c1ae8e5beeb22e5496a24b0c9 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 24 Dec 2024 13:54:16 +0100 Subject: [PATCH 03/11] Type user store --- .../src/components/grid/stores/index.ts | 3 +- .../grid/stores/{users.js => users.ts} | 37 +++++++++++++++---- packages/types/src/ui/stores/grid/index.ts | 1 + packages/types/src/ui/stores/grid/user.ts | 6 +++ 4 files changed, 38 insertions(+), 9 deletions(-) rename packages/frontend-core/src/components/grid/stores/{users.js => users.ts} (61%) create mode 100644 packages/types/src/ui/stores/grid/user.ts diff --git a/packages/frontend-core/src/components/grid/stores/index.ts b/packages/frontend-core/src/components/grid/stores/index.ts index 90e89cbf4c..8ecbc0e19c 100644 --- a/packages/frontend-core/src/components/grid/stores/index.ts +++ b/packages/frontend-core/src/components/grid/stores/index.ts @@ -61,7 +61,8 @@ export type Store = BaseStore & ViewV2.Store & NonPlus.Store & Datasource.Store & - Validation.Store & { + Validation.Store & + Users.Store & { // TODO while typing the rest of stores fetch: Writable filter: Writable diff --git a/packages/frontend-core/src/components/grid/stores/users.js b/packages/frontend-core/src/components/grid/stores/users.ts similarity index 61% rename from packages/frontend-core/src/components/grid/stores/users.js rename to packages/frontend-core/src/components/grid/stores/users.ts index 64c1e27835..f8824f8329 100644 --- a/packages/frontend-core/src/components/grid/stores/users.js +++ b/packages/frontend-core/src/components/grid/stores/users.ts @@ -1,8 +1,29 @@ -import { writable, get, derived } from "svelte/store" +import { writable, get, derived, Writable, Readable } from "svelte/store" import { helpers } from "@budibase/shared-core" +import { Store as StoreContext } from "." +import { UIUser } from "@budibase/types" -export const createStores = () => { - const users = writable([]) +interface UsersStore { + users: Writable +} + +interface DerivedUsersStore { + userCellMap: Readable> +} + +interface ActionUserStore { + users: UsersStore["users"] & { + actions: { + updateUser: (user: UIUser) => void + removeUser: (sessionId: string) => void + } + } +} + +export type Store = UsersStore & DerivedUsersStore + +export const createStores = (): UsersStore => { + const users = writable([]) const enrichedUsers = derived(users, $users => { return $users.map(user => ({ @@ -20,7 +41,7 @@ export const createStores = () => { } } -export const deriveStores = context => { +export const deriveStores = (context: StoreContext): DerivedUsersStore => { const { users, focusedCellId } = context // Generate a lookup map of cell ID to the user that has it selected, to make @@ -28,7 +49,7 @@ export const deriveStores = context => { const userCellMap = derived( [users, focusedCellId], ([$users, $focusedCellId]) => { - let map = {} + let map: Record = {} $users.forEach(user => { const cellId = user.gridMetadata?.focusedCellId if (cellId && cellId !== $focusedCellId) { @@ -44,10 +65,10 @@ export const deriveStores = context => { } } -export const createActions = context => { +export const createActions = (context: StoreContext): ActionUserStore => { const { users } = context - const updateUser = user => { + const updateUser = (user: UIUser) => { const $users = get(users) if (!$users.some(x => x.sessionId === user.sessionId)) { users.set([...$users, user]) @@ -60,7 +81,7 @@ export const createActions = context => { } } - const removeUser = sessionId => { + const removeUser = (sessionId: string) => { users.update(state => { return state.filter(x => x.sessionId !== sessionId) }) diff --git a/packages/types/src/ui/stores/grid/index.ts b/packages/types/src/ui/stores/grid/index.ts index bcd7e3267d..b6a152ed73 100644 --- a/packages/types/src/ui/stores/grid/index.ts +++ b/packages/types/src/ui/stores/grid/index.ts @@ -2,3 +2,4 @@ export * from "./columns" export * from "./datasource" export * from "./table" export * from "./view" +export * from "./user" diff --git a/packages/types/src/ui/stores/grid/user.ts b/packages/types/src/ui/stores/grid/user.ts new file mode 100644 index 0000000000..b6eb529805 --- /dev/null +++ b/packages/types/src/ui/stores/grid/user.ts @@ -0,0 +1,6 @@ +import { User } from "@budibase/types" + +export interface UIUser extends User { + sessionId: string + gridMetadata?: { focusedCellId?: string } +} From 9d5e7b14a7ac5abfd76ead22bd470c2e4348e248 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 24 Dec 2024 14:07:14 +0100 Subject: [PATCH 04/11] Type menu store --- .../src/components/grid/stores/index.ts | 8 +++++- .../grid/stores/{menu.js => menu.ts} | 26 +++++++++++++++---- 2 files changed, 28 insertions(+), 6 deletions(-) rename packages/frontend-core/src/components/grid/stores/{menu.js => menu.ts} (77%) diff --git a/packages/frontend-core/src/components/grid/stores/index.ts b/packages/frontend-core/src/components/grid/stores/index.ts index 8ecbc0e19c..d0413cb80a 100644 --- a/packages/frontend-core/src/components/grid/stores/index.ts +++ b/packages/frontend-core/src/components/grid/stores/index.ts @@ -62,7 +62,8 @@ export type Store = BaseStore & NonPlus.Store & Datasource.Store & Validation.Store & - Users.Store & { + Users.Store & + Menu.Store & { // TODO while typing the rest of stores fetch: Writable filter: Writable @@ -80,6 +81,11 @@ export type Store = BaseStore & schemaOverrides: Writable focusedCellId: Writable previousFocusedRowId: Writable + gridID: string + selectedRows: Writable + selectedRowCount: Writable + selectedCellMap: Writable + selectedCellCount: Writable } export const attachStores = (context: Store): Store => { diff --git a/packages/frontend-core/src/components/grid/stores/menu.js b/packages/frontend-core/src/components/grid/stores/menu.ts similarity index 77% rename from packages/frontend-core/src/components/grid/stores/menu.js rename to packages/frontend-core/src/components/grid/stores/menu.ts index 22bf26fff5..27e41c412b 100644 --- a/packages/frontend-core/src/components/grid/stores/menu.js +++ b/packages/frontend-core/src/components/grid/stores/menu.ts @@ -1,8 +1,24 @@ -import { writable, get } from "svelte/store" +import { writable, get, Writable } from "svelte/store" + +import { Store as StoreContext } from "." import { parseCellID } from "../lib/utils" +interface MenuStoreData { + left: number + top: number + visible: boolean + multiRowMode: boolean + multiCellMode: boolean +} + +interface MenuStore { + menu: Writable +} + +export type Store = MenuStore + export const createStores = () => { - const menu = writable({ + const menu = writable({ left: 0, top: 0, visible: false, @@ -14,7 +30,7 @@ export const createStores = () => { } } -export const createActions = context => { +export const createActions = (context: StoreContext) => { const { menu, focusedCellId, @@ -25,7 +41,7 @@ export const createActions = context => { selectedCellCount, } = context - const open = (cellId, e) => { + const open = (cellId: string, e: MouseEvent) => { e.preventDefault() e.stopPropagation() @@ -37,7 +53,7 @@ export const createActions = context => { } // Compute bounds of cell relative to outer data node - const targetBounds = e.target.getBoundingClientRect() + const targetBounds = (e.target as HTMLElement).getBoundingClientRect() const dataBounds = dataNode.getBoundingClientRect() // Check if there are multiple rows selected, and if this is one of them From 342503700a563cd12364c477d84d88f78e050803 Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Mon, 30 Dec 2024 09:06:12 +0000 Subject: [PATCH 05/11] convert more stores to ts --- .../src/stores/builder/{app.js => app.ts} | 73 ++++++++++++++++--- 1 file changed, 62 insertions(+), 11 deletions(-) rename packages/builder/src/stores/builder/{app.js => app.ts} (55%) diff --git a/packages/builder/src/stores/builder/app.js b/packages/builder/src/stores/builder/app.ts similarity index 55% rename from packages/builder/src/stores/builder/app.js rename to packages/builder/src/stores/builder/app.ts index 3b9e4e0b3c..f98e79eff1 100644 --- a/packages/builder/src/stores/builder/app.js +++ b/packages/builder/src/stores/builder/app.ts @@ -1,7 +1,54 @@ import { API } from "api" import { BudiStore } from "../BudiStore" +import { + App, + AppFeatures, + AppIcon, + AutomationSettings, + Plugin, +} from "@budibase/types" -export const INITIAL_APP_META_STATE = { +interface ClientFeatures { + spectrumThemes: boolean + intelligentLoading: boolean + deviceAwareness: boolean + state: boolean + rowSelection: boolean + customThemes: boolean + devicePreview: boolean + messagePassing: boolean + continueIfAction: boolean + showNotificationAction: boolean + sidePanel: boolean +} + +interface TypeSupportPresets { + [key: string]: any +} + +interface AppMetaState { + appId: string + name: string + url: string + libraries: string[] + clientFeatures: ClientFeatures + typeSupportPresets: TypeSupportPresets + features: AppFeatures + clientLibPath: string + hasLock: boolean + appInstance: { _id: string } | null + initialised: boolean + hasAppPackage: boolean + usedPlugins: Plugin[] | null + automations: AutomationSettings + routes: { [key: string]: any } + version?: string + revertableVersion?: string + upgradableVersion?: string + icon?: AppIcon +} + +export const INITIAL_APP_META_STATE: AppMetaState = { appId: "", name: "", url: "", @@ -34,23 +81,27 @@ export const INITIAL_APP_META_STATE = { routes: {}, } -export class AppMetaStore extends BudiStore { +export class AppMetaStore extends BudiStore { constructor() { super(INITIAL_APP_META_STATE) } - reset() { + reset(): void { this.store.set({ ...INITIAL_APP_META_STATE }) } - syncAppPackage(pkg) { + syncAppPackage(pkg: { + application: App + clientLibPath: string + hasLock: boolean + }): void { const { application: app, clientLibPath, hasLock } = pkg this.update(state => ({ ...state, name: app.name, appId: app.appId, - url: app.url, + url: app.url || "", hasLock, clientLibPath, libraries: app.componentLibraries, @@ -58,8 +109,8 @@ export class AppMetaStore extends BudiStore { appInstance: app.instance, revertableVersion: app.revertableVersion, upgradableVersion: app.upgradableVersion, - usedPlugins: app.usedPlugins, - icon: app.icon || {}, + usedPlugins: app.usedPlugins || null, + icon: app.icon, features: { ...INITIAL_APP_META_STATE.features, ...app.features, @@ -70,7 +121,7 @@ export class AppMetaStore extends BudiStore { })) } - syncClientFeatures(features) { + syncClientFeatures(features: Partial): void { this.update(state => ({ ...state, clientFeatures: { @@ -80,14 +131,14 @@ export class AppMetaStore extends BudiStore { })) } - syncClientTypeSupportPresets(typeSupportPresets) { + syncClientTypeSupportPresets(typeSupportPresets: TypeSupportPresets): void { this.update(state => ({ ...state, typeSupportPresets, })) } - async syncAppRoutes() { + async syncAppRoutes(): Promise { const resp = await API.fetchAppRoutes() this.update(state => ({ ...state, @@ -96,7 +147,7 @@ export class AppMetaStore extends BudiStore { } // Returned from socket - syncMetadata(metadata) { + syncMetadata(metadata: { name: string; url: string; icon?: AppIcon }): void { const { name, url, icon } = metadata this.update(state => ({ ...state, From 6e6c25e15e988dc9d574158aeaf5e3e1dba45676 Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Mon, 30 Dec 2024 09:08:51 +0000 Subject: [PATCH 06/11] migrate builder.js to ts --- .../stores/builder/{builder.js => builder.ts} | 62 ++++++++++++------- 1 file changed, 40 insertions(+), 22 deletions(-) rename packages/builder/src/stores/builder/{builder.js => builder.ts} (67%) diff --git a/packages/builder/src/stores/builder/builder.js b/packages/builder/src/stores/builder/builder.ts similarity index 67% rename from packages/builder/src/stores/builder/builder.js rename to packages/builder/src/stores/builder/builder.ts index 9b5a847680..472abe7c66 100644 --- a/packages/builder/src/stores/builder/builder.js +++ b/packages/builder/src/stores/builder/builder.ts @@ -3,8 +3,25 @@ import { createBuilderWebsocket } from "./websocket.js" import { BuilderSocketEvent } from "@budibase/shared-core" import { BudiStore } from "../BudiStore.js" import { TOUR_KEYS } from "components/portal/onboarding/tours.js" +import { App } from "@budibase/types" -export const INITIAL_BUILDER_STATE = { +interface BuilderState { + previousTopNavPath: Record + highlightedSetting: { + key: string + type: "info" | string + } | null + propertyFocus: string | null + builderSidePanel: boolean + onboarding: boolean + tourNodes: Record | null + tourKey: string | null + tourStepKey: string | null + hoveredComponentId: string | null + websocket?: ReturnType +} + +export const INITIAL_BUILDER_STATE: BuilderState = { previousTopNavPath: {}, highlightedSetting: null, propertyFocus: null, @@ -16,7 +33,9 @@ export const INITIAL_BUILDER_STATE = { hoveredComponentId: null, } -export class BuilderStore extends BudiStore { +export class BuilderStore extends BudiStore { + websocket?: ReturnType + constructor() { super({ ...INITIAL_BUILDER_STATE }) @@ -32,11 +51,9 @@ export class BuilderStore extends BudiStore { this.registerTourNode = this.registerTourNode.bind(this) this.destroyTourNode = this.destroyTourNode.bind(this) this.startBuilderOnboarding = this.startBuilderOnboarding.bind(this) - - this.websocket } - init(app) { + init(app: App): void { if (!app?.appId) { console.error("BuilderStore: No appId supplied for websocket") return @@ -46,45 +63,46 @@ export class BuilderStore extends BudiStore { } } - refresh() { - this.store.set(this.store.get()) + refresh(): void { + const currentState = get(this.store) + this.store.set(currentState) } - reset() { + reset(): void { this.store.set({ ...INITIAL_BUILDER_STATE }) this.websocket?.disconnect() - this.websocket = null + this.websocket = undefined } - highlightSetting(key, type) { + highlightSetting(key?: string, type?: string): void { this.update(state => ({ ...state, highlightedSetting: key ? { key, type: type || "info" } : null, })) } - propertyFocus(key) { + propertyFocus(key: string | null): void { this.update(state => ({ ...state, propertyFocus: key, })) } - showBuilderSidePanel() { + showBuilderSidePanel(): void { this.update(state => ({ ...state, builderSidePanel: true, })) } - hideBuilderSidePanel() { + hideBuilderSidePanel(): void { this.update(state => ({ ...state, builderSidePanel: false, })) } - setPreviousTopNavPath(route, url) { + setPreviousTopNavPath(route: string, url: string): void { this.update(state => ({ ...state, previousTopNavPath: { @@ -94,13 +112,13 @@ export class BuilderStore extends BudiStore { })) } - selectResource(id) { - this.websocket.emit(BuilderSocketEvent.SelectResource, { + selectResource(id: string): void { + this.websocket?.emit(BuilderSocketEvent.SelectResource, { resourceId: id, }) } - registerTourNode(tourStepKey, node) { + registerTourNode(tourStepKey: string, node: HTMLElement): void { this.update(state => { const update = { ...state, @@ -113,7 +131,7 @@ export class BuilderStore extends BudiStore { }) } - destroyTourNode(tourStepKey) { + destroyTourNode(tourStepKey: string): void { const store = get(this.store) if (store.tourNodes?.[tourStepKey]) { const nodes = { ...store.tourNodes } @@ -125,7 +143,7 @@ export class BuilderStore extends BudiStore { } } - startBuilderOnboarding() { + startBuilderOnboarding(): void { this.update(state => ({ ...state, onboarding: true, @@ -133,19 +151,19 @@ export class BuilderStore extends BudiStore { })) } - endBuilderOnboarding() { + endBuilderOnboarding(): void { this.update(state => ({ ...state, onboarding: false, })) } - setTour(tourKey) { + setTour(tourKey?: string | null): void { this.update(state => ({ ...state, tourStepKey: null, tourNodes: null, - tourKey: tourKey, + tourKey: tourKey || null, })) } } From a94adced72589e1f66249b6afb9d0416613bd674 Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Mon, 30 Dec 2024 09:27:22 +0000 Subject: [PATCH 07/11] contextmenu and deployment --- .../builder/src/stores/builder/contextMenu.js | 28 ----------- .../builder/src/stores/builder/contextMenu.ts | 46 +++++++++++++++++++ .../{deployments.js => deployments.ts} | 7 +-- 3 files changed, 50 insertions(+), 31 deletions(-) delete mode 100644 packages/builder/src/stores/builder/contextMenu.js create mode 100644 packages/builder/src/stores/builder/contextMenu.ts rename packages/builder/src/stores/builder/{deployments.js => deployments.ts} (62%) diff --git a/packages/builder/src/stores/builder/contextMenu.js b/packages/builder/src/stores/builder/contextMenu.js deleted file mode 100644 index 2b8808570e..0000000000 --- a/packages/builder/src/stores/builder/contextMenu.js +++ /dev/null @@ -1,28 +0,0 @@ -import { writable } from "svelte/store" - -export const INITIAL_CONTEXT_MENU_STATE = { - id: null, - items: [], - position: { x: 0, y: 0 }, - visible: false, -} - -export function createViewsStore() { - const store = writable({ ...INITIAL_CONTEXT_MENU_STATE }) - - const open = (id, items, position) => { - store.set({ id, items, position, visible: true }) - } - - const close = () => { - store.set({ ...INITIAL_CONTEXT_MENU_STATE }) - } - - return { - subscribe: store.subscribe, - open, - close, - } -} - -export const contextMenuStore = createViewsStore() diff --git a/packages/builder/src/stores/builder/contextMenu.ts b/packages/builder/src/stores/builder/contextMenu.ts new file mode 100644 index 0000000000..dc205c7fea --- /dev/null +++ b/packages/builder/src/stores/builder/contextMenu.ts @@ -0,0 +1,46 @@ +import { writable } from "svelte/store" + +interface Position { + x: number + y: number +} + +interface MenuItem { + label: string + icon?: string + action: () => void +} + +interface ContextMenuState { + id: string | null + items: MenuItem[] + position: Position + visible: boolean +} + +export const INITIAL_CONTEXT_MENU_STATE: ContextMenuState = { + id: null, + items: [], + position: { x: 0, y: 0 }, + visible: false, +} + +export function createViewsStore() { + const store = writable({ ...INITIAL_CONTEXT_MENU_STATE }) + + const open = (id: string, items: MenuItem[], position: Position): void => { + store.set({ id, items, position, visible: true }) + } + + const close = (): void => { + store.set({ ...INITIAL_CONTEXT_MENU_STATE }) + } + + return { + subscribe: store.subscribe, + open, + close, + } +} + +export const contextMenuStore = createViewsStore() diff --git a/packages/builder/src/stores/builder/deployments.js b/packages/builder/src/stores/builder/deployments.ts similarity index 62% rename from packages/builder/src/stores/builder/deployments.js rename to packages/builder/src/stores/builder/deployments.ts index dafdb1dabc..130e52bc91 100644 --- a/packages/builder/src/stores/builder/deployments.js +++ b/packages/builder/src/stores/builder/deployments.ts @@ -1,11 +1,12 @@ -import { writable } from "svelte/store" +import { writable, type Writable } from "svelte/store" import { API } from "api" import { notifications } from "@budibase/bbui" +import { DeploymentProgressResponse } from "@budibase/types" export const createDeploymentStore = () => { - let store = writable([]) + let store: Writable = writable([]) - const load = async () => { + const load = async (): Promise => { try { store.set(await API.getAppDeployments()) } catch (err) { From 5c3922219fa132aefd004bc7dd214559237e80d0 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 24 Dec 2024 13:41:17 +0100 Subject: [PATCH 08/11] Type validation --- .../src/components/grid/stores/index.ts | 5 +++- .../stores/{validation.js => validation.ts} | 29 +++++++++++++------ 2 files changed, 24 insertions(+), 10 deletions(-) rename packages/frontend-core/src/components/grid/stores/{validation.js => validation.ts} (69%) diff --git a/packages/frontend-core/src/components/grid/stores/index.ts b/packages/frontend-core/src/components/grid/stores/index.ts index f2b6c973b9..90e89cbf4c 100644 --- a/packages/frontend-core/src/components/grid/stores/index.ts +++ b/packages/frontend-core/src/components/grid/stores/index.ts @@ -60,7 +60,8 @@ export type Store = BaseStore & Table.Store & ViewV2.Store & NonPlus.Store & - Datasource.Store & { + Datasource.Store & + Validation.Store & { // TODO while typing the rest of stores fetch: Writable filter: Writable @@ -76,6 +77,8 @@ export type Store = BaseStore & dispatch: (event: string, data: any) => any notifications: Writable schemaOverrides: Writable + focusedCellId: Writable + previousFocusedRowId: Writable } export const attachStores = (context: Store): Store => { diff --git a/packages/frontend-core/src/components/grid/stores/validation.js b/packages/frontend-core/src/components/grid/stores/validation.ts similarity index 69% rename from packages/frontend-core/src/components/grid/stores/validation.js rename to packages/frontend-core/src/components/grid/stores/validation.ts index 93e67e1d31..32bb1cf978 100644 --- a/packages/frontend-core/src/components/grid/stores/validation.js +++ b/packages/frontend-core/src/components/grid/stores/validation.ts @@ -1,10 +1,21 @@ -import { writable, get, derived } from "svelte/store" +import { writable, get, derived, Writable, Readable } from "svelte/store" +import { Store as StoreContext } from "." import { parseCellID } from "../lib/utils" +interface ValidationStore { + validation: Writable> +} + +interface DerivedValidationStore { + validationRowLookupMap: Readable> +} + +export type Store = ValidationStore & DerivedValidationStore + // Normally we would break out actions into the explicit "createActions" // function, but for validation all these actions are pure so can go into // "createStores" instead to make dependency ordering simpler -export const createStores = () => { +export const createStores = (): ValidationStore => { const validation = writable({}) return { @@ -12,12 +23,12 @@ export const createStores = () => { } } -export const deriveStores = context => { +export const deriveStores = (context: StoreContext): DerivedValidationStore => { const { validation } = context // Derive which rows have errors so that we can use that info later const validationRowLookupMap = derived(validation, $validation => { - let map = {} + const map: Record = {} Object.entries($validation).forEach(([key, error]) => { // Extract row ID from all errored cell IDs if (error) { @@ -36,10 +47,10 @@ export const deriveStores = context => { } } -export const createActions = context => { +export const createActions = (context: StoreContext) => { const { validation, focusedCellId, validationRowLookupMap } = context - const setError = (cellId, error) => { + const setError = (cellId: string | undefined, error: string) => { if (!cellId) { return } @@ -49,11 +60,11 @@ export const createActions = context => { })) } - const rowHasErrors = rowId => { + const rowHasErrors = (rowId: string) => { return get(validationRowLookupMap)[rowId]?.length > 0 } - const focusFirstRowError = rowId => { + const focusFirstRowError = (rowId: string) => { const errorCells = get(validationRowLookupMap)[rowId] const cellId = errorCells?.[0] if (cellId) { @@ -73,7 +84,7 @@ export const createActions = context => { } } -export const initialise = context => { +export const initialise = (context: StoreContext) => { const { validation, previousFocusedRowId, validationRowLookupMap } = context // Remove validation errors when changing rows From c30c68c289e324d3c111ba60753b07db8013e388 Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Mon, 30 Dec 2024 12:16:02 +0000 Subject: [PATCH 09/11] socket expects undefined instead of null --- packages/builder/src/stores/builder/builder.ts | 5 +++-- packages/builder/src/stores/builder/tests/builder.test.js | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/builder/src/stores/builder/builder.ts b/packages/builder/src/stores/builder/builder.ts index 472abe7c66..00f6c5fce7 100644 --- a/packages/builder/src/stores/builder/builder.ts +++ b/packages/builder/src/stores/builder/builder.ts @@ -1,5 +1,6 @@ import { get } from "svelte/store" import { createBuilderWebsocket } from "./websocket.js" +import { Socket } from "socket.io-client" import { BuilderSocketEvent } from "@budibase/shared-core" import { BudiStore } from "../BudiStore.js" import { TOUR_KEYS } from "components/portal/onboarding/tours.js" @@ -18,7 +19,7 @@ interface BuilderState { tourKey: string | null tourStepKey: string | null hoveredComponentId: string | null - websocket?: ReturnType + websocket?: Socket } export const INITIAL_BUILDER_STATE: BuilderState = { @@ -34,7 +35,7 @@ export const INITIAL_BUILDER_STATE: BuilderState = { } export class BuilderStore extends BudiStore { - websocket?: ReturnType + websocket?: Socket constructor() { super({ ...INITIAL_BUILDER_STATE }) diff --git a/packages/builder/src/stores/builder/tests/builder.test.js b/packages/builder/src/stores/builder/tests/builder.test.js index e6f52689aa..f3c42dae72 100644 --- a/packages/builder/src/stores/builder/tests/builder.test.js +++ b/packages/builder/src/stores/builder/tests/builder.test.js @@ -65,7 +65,7 @@ describe("Builder store", () => { ctx.test.builderStore.reset() expect(disconnected).toBe(true) expect(ctx.test.store).toStrictEqual(INITIAL_BUILDER_STATE) - expect(ctx.test.builderStore.websocket).toBeNull() + expect(ctx.test.builderStore.websocket).toBeUndefined() }) it("Attempt to emit a resource select event to the websocket on select", ctx => { From 430431203b0f469c28a7bf198d9827a9345502f6 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Mon, 30 Dec 2024 14:25:23 +0100 Subject: [PATCH 10/11] Typed enriched users --- .../src/components/grid/stores/users.ts | 17 +++++++++-------- packages/types/src/ui/stores/grid/user.ts | 5 +++++ 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/packages/frontend-core/src/components/grid/stores/users.ts b/packages/frontend-core/src/components/grid/stores/users.ts index f8824f8329..dcac940088 100644 --- a/packages/frontend-core/src/components/grid/stores/users.ts +++ b/packages/frontend-core/src/components/grid/stores/users.ts @@ -1,7 +1,7 @@ import { writable, get, derived, Writable, Readable } from "svelte/store" import { helpers } from "@budibase/shared-core" import { Store as StoreContext } from "." -import { UIUser } from "@budibase/types" +import { UIEnrichedUser, UIUser } from "@budibase/types" interface UsersStore { users: Writable @@ -12,21 +12,22 @@ interface DerivedUsersStore { } interface ActionUserStore { - users: UsersStore["users"] & { - actions: { - updateUser: (user: UIUser) => void - removeUser: (sessionId: string) => void + users: UsersStore["users"] & + Readable & { + actions: { + updateUser: (user: UIUser) => void + removeUser: (sessionId: string) => void + } } - } } -export type Store = UsersStore & DerivedUsersStore +export type Store = DerivedUsersStore & ActionUserStore export const createStores = (): UsersStore => { const users = writable([]) const enrichedUsers = derived(users, $users => { - return $users.map(user => ({ + return $users.map(user => ({ ...user, color: helpers.getUserColor(user), label: helpers.getUserLabel(user), diff --git a/packages/types/src/ui/stores/grid/user.ts b/packages/types/src/ui/stores/grid/user.ts index b6eb529805..225c232d3d 100644 --- a/packages/types/src/ui/stores/grid/user.ts +++ b/packages/types/src/ui/stores/grid/user.ts @@ -4,3 +4,8 @@ export interface UIUser extends User { sessionId: string gridMetadata?: { focusedCellId?: string } } + +export interface UIEnrichedUser extends UIUser { + color: string + label: string +} From cca22fe8644a8106cfbb579d8fa51fb8e1037eda Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Mon, 30 Dec 2024 14:49:36 +0100 Subject: [PATCH 11/11] Move type --- packages/frontend-core/src/components/grid/stores/users.ts | 7 ++++++- packages/types/src/ui/stores/grid/user.ts | 5 ----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/frontend-core/src/components/grid/stores/users.ts b/packages/frontend-core/src/components/grid/stores/users.ts index dcac940088..b3dffbcb1b 100644 --- a/packages/frontend-core/src/components/grid/stores/users.ts +++ b/packages/frontend-core/src/components/grid/stores/users.ts @@ -1,7 +1,12 @@ import { writable, get, derived, Writable, Readable } from "svelte/store" import { helpers } from "@budibase/shared-core" import { Store as StoreContext } from "." -import { UIEnrichedUser, UIUser } from "@budibase/types" +import { UIUser } from "@budibase/types" + +interface UIEnrichedUser extends UIUser { + color: string + label: string +} interface UsersStore { users: Writable diff --git a/packages/types/src/ui/stores/grid/user.ts b/packages/types/src/ui/stores/grid/user.ts index 225c232d3d..b6eb529805 100644 --- a/packages/types/src/ui/stores/grid/user.ts +++ b/packages/types/src/ui/stores/grid/user.ts @@ -4,8 +4,3 @@ export interface UIUser extends User { sessionId: string gridMetadata?: { focusedCellId?: string } } - -export interface UIEnrichedUser extends UIUser { - color: string - label: string -}