From 7be2d6896e564c73be857bd7c910349e62b9b523 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Tue, 4 Jul 2023 08:58:14 +0100 Subject: [PATCH] Add indicators to show selected state in data section --- packages/builder/src/builderStore/index.js | 13 +++++ .../src/builderStore/store/frontend.js | 8 +++ .../DatasourceNavigator.svelte | 4 ++ .../TableNavigator/TableNavigator.svelte | 3 + .../src/components/common/NavItem.svelte | 57 ++++++++++++++++++- .../app/[application]/data/_layout.svelte | 6 ++ .../datasource/[datasourceId]/_layout.svelte | 4 ++ .../data/datasource/bb_internal/index.svelte | 2 + .../index.svelte | 3 + .../data/query/[queryId]/_layout.svelte | 4 ++ .../data/table/[tableId]/_layout.svelte | 4 ++ .../data/view/[viewName]/_layout.svelte | 4 ++ packages/server/src/websockets/builder.ts | 7 ++- packages/shared-core/src/constants.ts | 1 + 14 files changed, 117 insertions(+), 3 deletions(-) diff --git a/packages/builder/src/builderStore/index.js b/packages/builder/src/builderStore/index.js index 9dca6a64e6..1022f917d0 100644 --- a/packages/builder/src/builderStore/index.js +++ b/packages/builder/src/builderStore/index.js @@ -118,3 +118,16 @@ export const selectedAutomation = derived(automationStore, $automationStore => { x => x._id === $automationStore.selectedAutomationId ) }) + +// Derive map of resource IDs to other users. +// We only ever care about a single user in each resource, so if multiple users +// share the same datasource we can just overwrite them. +export const userSelectedResourceMap = derived(userStore, $userStore => { + let map = {} + $userStore.forEach(user => { + if (user.selectedResourceId) { + map[user.selectedResourceId] = user + } + }) + return map +}) diff --git a/packages/builder/src/builderStore/store/frontend.js b/packages/builder/src/builderStore/store/frontend.js index 4af3be4673..a3e499e336 100644 --- a/packages/builder/src/builderStore/store/frontend.js +++ b/packages/builder/src/builderStore/store/frontend.js @@ -38,6 +38,7 @@ import { import { makePropSafe as safe } from "@budibase/string-templates" import { getComponentFieldOptions } from "helpers/formFields" import { createBuilderWebsocket } from "builderStore/websocket" +import { BuilderSocketEvent } from "@budibase/shared-core" const INITIAL_FRONTEND_STATE = { initialised: false, @@ -1394,6 +1395,13 @@ export const getFrontendStore = () => { }) }, }, + websocket: { + selectResource: id => { + websocket.emit(BuilderSocketEvent.SelectResource, { + resourceId: id, + }) + }, + }, } return store diff --git a/packages/builder/src/components/backend/DatasourceNavigator/DatasourceNavigator.svelte b/packages/builder/src/components/backend/DatasourceNavigator/DatasourceNavigator.svelte index e2dd1b4cc3..c34afce783 100644 --- a/packages/builder/src/components/backend/DatasourceNavigator/DatasourceNavigator.svelte +++ b/packages/builder/src/components/backend/DatasourceNavigator/DatasourceNavigator.svelte @@ -13,6 +13,7 @@ } from "helpers/data/utils" import IntegrationIcon from "./IntegrationIcon.svelte" import { TableNames } from "constants" + import { userSelectedResourceMap } from "builderStore" let openDataSources = [] @@ -166,6 +167,7 @@ selected={$isActive("./table/:tableId") && $tables.selected?._id === TableNames.USERS} on:click={() => selectTable(TableNames.USERS)} + selectedBy={$userSelectedResourceMap[TableNames.USERS]} /> {#each enrichedDataSources as datasource, idx} selectDatasource(datasource)} on:iconClick={() => toggleNode(datasource)} + selectedBy={$userSelectedResourceMap[datasource._id]} >
$goto(`./query/${query._id}`)} + selectedBy={$userSelectedResourceMap[query._id]} > diff --git a/packages/builder/src/components/backend/TableNavigator/TableNavigator.svelte b/packages/builder/src/components/backend/TableNavigator/TableNavigator.svelte index a7e5764865..d9def682dc 100644 --- a/packages/builder/src/components/backend/TableNavigator/TableNavigator.svelte +++ b/packages/builder/src/components/backend/TableNavigator/TableNavigator.svelte @@ -5,6 +5,7 @@ import EditViewPopover from "./popovers/EditViewPopover.svelte" import NavItem from "components/common/NavItem.svelte" import { goto, isActive } from "@roxi/routify" + import { userSelectedResourceMap } from "builderStore" const alphabetical = (a, b) => a.name?.toLowerCase() > b.name?.toLowerCase() ? 1 : -1 @@ -30,6 +31,7 @@ selected={$isActive("./table/:tableId") && $tables.selected?._id === table._id} on:click={() => selectTable(table._id)} + selectedBy={$userSelectedResourceMap[table._id]} > {#if table._id !== TableNames.USERS} @@ -42,6 +44,7 @@ text={viewName} selected={$isActive("./view") && $views.selected?.name === viewName} on:click={() => $goto(`./view/${encodeURIComponent(viewName)}`)} + selectedBy={$userSelectedResourceMap[viewName]} > import { Icon } from "@budibase/bbui" import { createEventDispatcher, getContext } from "svelte" + import { helpers } from "@budibase/shared-core" + import { UserAvatar } from "@budibase/frontend-core" export let icon export let withArrow = false @@ -18,12 +20,15 @@ export let rightAlignIcon = false export let id export let showTooltip = false + export let selectedBy = null const scrollApi = getContext("scroll") const dispatch = createEventDispatcher() let contentRef + $: selected && contentRef && scrollToView() + $: style = getStyle(indentLevel, selectedBy) const onClick = () => { scrollToView() @@ -42,6 +47,14 @@ const bounds = contentRef.getBoundingClientRect() scrollApi.scrollTo(bounds) } + + const getStyle = (indentLevel, selectedBy) => { + let style = `padding-left:calc(${indentLevel * 14}px);` + if (selectedBy) { + style += `--selected-by-color:${helpers.getUserColor(selectedBy)};` + } + return style + }
{/if}
+ {#if selectedBy} +
{helpers.getUserLabel(selectedBy)}
+ {/if} + + + + +