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 diff --git a/packages/frontend-core/src/components/grid/stores/index.ts b/packages/frontend-core/src/components/grid/stores/index.ts index f2b6c973b9..d0413cb80a 100644 --- a/packages/frontend-core/src/components/grid/stores/index.ts +++ b/packages/frontend-core/src/components/grid/stores/index.ts @@ -60,7 +60,10 @@ export type Store = BaseStore & Table.Store & ViewV2.Store & NonPlus.Store & - Datasource.Store & { + Datasource.Store & + Validation.Store & + Users.Store & + Menu.Store & { // TODO while typing the rest of stores fetch: Writable filter: Writable @@ -76,6 +79,13 @@ export type Store = BaseStore & dispatch: (event: string, data: any) => any notifications: Writable 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 diff --git a/packages/frontend-core/src/components/grid/stores/users.js b/packages/frontend-core/src/components/grid/stores/users.ts similarity index 56% rename from packages/frontend-core/src/components/grid/stores/users.js rename to packages/frontend-core/src/components/grid/stores/users.ts index 64c1e27835..b3dffbcb1b 100644 --- a/packages/frontend-core/src/components/grid/stores/users.js +++ b/packages/frontend-core/src/components/grid/stores/users.ts @@ -1,11 +1,38 @@ -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 UIEnrichedUser extends UIUser { + color: string + label: string +} + +interface UsersStore { + users: Writable +} + +interface DerivedUsersStore { + userCellMap: Readable> +} + +interface ActionUserStore { + users: UsersStore["users"] & + Readable & { + actions: { + updateUser: (user: UIUser) => void + removeUser: (sessionId: string) => void + } + } +} + +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), @@ -20,7 +47,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 +55,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 +71,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 +87,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/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 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 } +}