Update buttons for views

This commit is contained in:
Andrew Kingston 2024-08-20 08:24:23 +01:00
parent 38bd64cebd
commit 54f9507e53
No known key found for this signature in database
19 changed files with 95 additions and 200 deletions

View File

@ -34,7 +34,7 @@
"dist" "dist"
], ],
"dependencies": { "dependencies": {
"@adobe/spectrum-css-workflow-icons": "1.2.1", "@adobe/spectrum-css-workflow-icons": "3.0.0",
"@budibase/shared-core": "0.0.0", "@budibase/shared-core": "0.0.0",
"@budibase/string-templates": "0.0.0", "@budibase/string-templates": "0.0.0",
"@spectrum-css/accordion": "3.0.24", "@spectrum-css/accordion": "3.0.24",

View File

@ -1,44 +0,0 @@
<script>
import { API } from "api"
import Table from "./Table.svelte"
import { tables } from "stores/builder"
import { notifications } from "@budibase/bbui"
export let tableId
export let rowId
export let fieldName
let row
let title
$: data = row?.[fieldName] ?? []
$: linkedTableId = data?.length ? data[0].tableId : null
$: linkedTable = $tables.list.find(table => table._id === linkedTableId)
$: schema = linkedTable?.schema
$: table = $tables.list.find(table => table._id === tableId)
$: fetchData(tableId, rowId)
$: {
let rowLabel = row?.[table?.primaryDisplay]
if (rowLabel) {
title = `${rowLabel} - ${fieldName}`
} else {
title = fieldName
}
}
async function fetchData(tableId, rowId) {
try {
row = await API.fetchRelationshipData({
tableId,
rowId,
})
} catch (error) {
row = null
notifications.error("Error fetching relationship data")
}
}
</script>
{#if row && row._id === rowId}
<Table {title} {schema} {data} />
{/if}

View File

@ -1,39 +0,0 @@
<script>
import { viewsV2 } from "stores/builder"
import { admin, licensing } from "stores/portal"
import { Grid } from "@budibase/frontend-core"
import { API } from "api"
import GridCreateEditRowModal from "components/backend/DataTable/modals/grid/GridCreateEditRowModal.svelte"
import GridFilterButton from "components/backend/DataTable/buttons/grid/GridFilterButton.svelte"
import GridManageAccessButton from "components/backend/DataTable/buttons/grid/GridManageAccessButton.svelte"
$: id = $viewsV2.selected?.id
$: datasource = {
type: "viewV2",
id,
tableId: $viewsV2.selected?.tableId,
}
const handleGridViewUpdate = async e => {
viewsV2.replaceView(id, e.detail)
}
</script>
<Grid
{API}
{datasource}
allowAddRows
allowDeleteRows
showAvatars={false}
on:updatedatasource={handleGridViewUpdate}
isCloud={$admin.cloud}
allowViewReadonlyColumns={$licensing.isViewReadonlyColumnsEnabled}
>
<svelte:fragment slot="filter">
<GridFilterButton />
</svelte:fragment>
<svelte:fragment slot="controls">
<GridCreateEditRowModal />
<GridManageAccessButton />
</svelte:fragment>
</Grid>

View File

@ -1,9 +1,9 @@
<script> <script>
import { getContext } from "svelte" import { getContext } from "svelte"
import { ActionButton, Popover, Icon, notifications } from "@budibase/bbui" import { ActionButton, Popover, Icon, notifications } from "@budibase/bbui"
import { getColumnIcon } from "../lib/utils" import ToggleActionButtonGroup from "components/common/ToggleActionButtonGroup.svelte"
import ToggleActionButtonGroup from "./ToggleActionButtonGroup.svelte"
import { helpers } from "@budibase/shared-core" import { helpers } from "@budibase/shared-core"
import { SchemaUtils } from "@budibase/frontend-core"
export let allowViewReadonlyColumns = false export let allowViewReadonlyColumns = false
@ -110,7 +110,7 @@
<div class="columns"> <div class="columns">
{#each displayColumns as column} {#each displayColumns as column}
<div class="column"> <div class="column">
<Icon size="S" name={getColumnIcon(column)} /> <Icon size="S" name={SchemaUtils.getColumnIcon(column)} />
<div class="column-label" title={column.label}> <div class="column-label" title={column.label}>
{column.label} {column.label}
</div> </div>

View File

@ -1,34 +1,34 @@
<script> <script>
import { getContext } from "svelte" import { getContext } from "svelte"
import { ActionButton, Popover, Label } from "@budibase/bbui" import { ActionButton, Popover, Label } from "@budibase/bbui"
import {
DefaultColumnWidth,
LargeRowHeight,
MediumRowHeight,
SmallRowHeight,
} from "../lib/constants"
const { columns, rowHeight, definition, fixedRowHeight, datasource } = const {
getContext("grid") Constants,
columns,
rowHeight,
definition,
fixedRowHeight,
datasource,
} = getContext("grid")
// Some constants for column width options // Some constants for column width options
const smallColSize = 120 const smallColSize = 120
const mediumColSize = DefaultColumnWidth const mediumColSize = Constants.DefaultColumnWidth
const largeColSize = DefaultColumnWidth * 1.5 const largeColSize = Constants.DefaultColumnWidth * 1.5
// Row height sizes // Row height sizes
const rowSizeOptions = [ const rowSizeOptions = [
{ {
label: "Small", label: "Small",
size: SmallRowHeight, size: Constants.SmallRowHeight,
}, },
{ {
label: "Medium", label: "Medium",
size: MediumRowHeight, size: Constants.MediumRowHeight,
}, },
{ {
label: "Large", label: "Large",
size: LargeRowHeight, size: Constants.LargeRowHeight,
}, },
] ]
@ -66,7 +66,6 @@
} }
</script> </script>
#
<div bind:this={anchor}> <div bind:this={anchor}>
<ActionButton <ActionButton
icon="MoveUpDown" icon="MoveUpDown"

View File

@ -9,7 +9,7 @@
export let options export let options
</script> </script>
<div class="permissionPicker"> <div>
{#each options as option} {#each options as option}
<AbsTooltip text={option.tooltip} type={TooltipType.Info}> <AbsTooltip text={option.tooltip} type={TooltipType.Info}>
<ActionButton <ActionButton
@ -26,15 +26,14 @@
</div> </div>
<style> <style>
.permissionPicker { div {
display: flex; display: flex;
gap: var(--spacing-xs); gap: var(--spacing-xs);
} }
div :global(.spectrum-Icon) {
.permissionPicker :global(.spectrum-Icon) {
width: 14px; width: 14px;
} }
.permissionPicker :global(.spectrum-ActionButton) { div :global(.spectrum-ActionButton) {
width: 28px; width: 28px;
height: 28px; height: 28px;
} }

View File

@ -1,5 +1,45 @@
<script> <script>
import ViewV2DataTable from "components/backend/DataTable/ViewV2DataTable.svelte" import { viewsV2 } from "stores/builder"
import { admin, licensing } from "stores/portal"
import { Grid } from "@budibase/frontend-core"
import { API } from "api"
import GridCreateEditRowModal from "components/backend/DataTable/modals/grid/GridCreateEditRowModal.svelte"
import GridFilterButton from "components/backend/DataTable/buttons/grid/GridFilterButton.svelte"
import GridManageAccessButton from "components/backend/DataTable/buttons/grid/GridManageAccessButton.svelte"
import GridSortButton from "components/backend/DataTable/buttons/grid/GridSortButton.svelte"
import GridColumnsSettingButton from "components/backend/DataTable/buttons/grid/GridColumnsSettingButton.svelte"
import GridSizeButton from "components/backend/DataTable/buttons/grid/GridSizeButton.svelte"
import GridCreateAutomationButton from "components/backend/DataTable/buttons/grid/GridCreateAutomationButton.svelte"
$: id = $viewsV2.selected?.id
$: datasource = {
type: "viewV2",
id,
tableId: $viewsV2.selected?.tableId,
}
const handleGridViewUpdate = async e => {
viewsV2.replaceView(id, e.detail)
}
</script> </script>
<ViewV2DataTable /> <Grid
{API}
{datasource}
allowAddRows
allowDeleteRows
showAvatars={false}
on:updatedatasource={handleGridViewUpdate}
isCloud={$admin.cloud}
allowViewReadonlyColumns={$licensing.isViewReadonlyColumnsEnabled}
>
<svelte:fragment slot="controls">
<GridFilterButton />
<GridSortButton />
<GridColumnsSettingButton />
<GridManageAccessButton />
<GridSizeButton />
<GridCreateAutomationButton />
</svelte:fragment>
<GridCreateEditRowModal />
</Grid>

View File

@ -1,10 +0,0 @@
<script>
import { params } from "@roxi/routify"
import RelationshipDataTable from "components/backend/DataTable/RelationshipDataTable.svelte"
</script>
<RelationshipDataTable
tableId={$params.tableId}
rowId={$params.rowId}
fieldName={decodeURI($params.field)}
/>

View File

@ -1,7 +0,0 @@
<script>
import { redirect } from "@roxi/routify"
$redirect("../../")
</script>
<!-- routify:options index=false -->

View File

@ -1,7 +0,0 @@
<script>
import { redirect } from "@roxi/routify"
$redirect("../")
</script>
<!-- routify:options index=false -->

View File

@ -1,24 +0,0 @@
<script>
import { viewsV2, builderStore } from "stores/builder"
import { syncURLToState } from "helpers/urlStateSync"
import * as routify from "@roxi/routify"
import { onDestroy } from "svelte"
$: id = $viewsV2.selectedViewId
$: builderStore.selectResource(id)
const stopSyncing = syncURLToState({
urlParam: "viewId",
stateKey: "selectedViewId",
validate: id => $viewsV2.list?.some(view => view.id === id),
update: viewsV2.select,
fallbackUrl: "../../",
store: viewsV2,
routify,
decode: decodeURIComponent,
})
onDestroy(stopSyncing)
</script>
<slot />

View File

@ -1,5 +0,0 @@
<script>
import ViewV2DataTable from "components/backend/DataTable/ViewV2DataTable.svelte"
</script>
<ViewV2DataTable />

View File

@ -1,5 +0,0 @@
<script>
import { redirect } from "@roxi/routify"
$redirect("../")
</script>

View File

@ -3,7 +3,7 @@
import { canBeDisplayColumn, canBeSortColumn } from "@budibase/shared-core" import { canBeDisplayColumn, canBeSortColumn } from "@budibase/shared-core"
import { Icon, Menu, MenuItem, Modal } from "@budibase/bbui" import { Icon, Menu, MenuItem, Modal } from "@budibase/bbui"
import GridCell from "./GridCell.svelte" import GridCell from "./GridCell.svelte"
import { getColumnIcon } from "../lib/utils" import { getColumnIcon } from "../../../utils/schema"
import MigrationModal from "../controls/MigrationModal.svelte" import MigrationModal from "../controls/MigrationModal.svelte"
import { debounce } from "../../../utils/utils" import { debounce } from "../../../utils/utils"
import { FieldType, FormulaType } from "@budibase/types" import { FieldType, FormulaType } from "@budibase/types"

View File

@ -21,15 +21,7 @@
import KeyboardManager from "../overlays/KeyboardManager.svelte" import KeyboardManager from "../overlays/KeyboardManager.svelte"
import NewRow from "./NewRow.svelte" import NewRow from "./NewRow.svelte"
import { createGridWebsocket } from "../lib/websocket" import { createGridWebsocket } from "../lib/websocket"
import { import * as Constants from "../lib/constants"
MaxCellRenderOverflow,
GutterWidth,
DefaultRowHeight,
VPadding,
SmallRowHeight,
ControlsHeight,
ScrollBarSize,
} from "../lib/constants"
export let API = null export let API = null
export let datasource = null export let datasource = null
@ -64,6 +56,7 @@
// Build up context // Build up context
let context = { let context = {
API: API || createAPIClient(), API: API || createAPIClient(),
Constants,
gridID, gridID,
props, props,
} }
@ -112,8 +105,13 @@
// Derive min height and make available in context // Derive min height and make available in context
const minHeight = derived(rowHeight, $height => { const minHeight = derived(rowHeight, $height => {
const heightForControls = $$slots.controls ? ControlsHeight : 0 const heightForControls = $$slots.controls ? Constants.ControlsHeight : 0
return VPadding + SmallRowHeight + $height + heightForControls return (
Constants.VPadding +
Constants.SmallRowHeight +
$height +
heightForControls
)
}) })
context = { ...context, minHeight } context = { ...context, minHeight }
@ -141,7 +139,7 @@
class:quiet class:quiet
on:mouseenter={() => gridFocused.set(true)} on:mouseenter={() => gridFocused.set(true)}
on:mouseleave={() => gridFocused.set(false)} on:mouseleave={() => gridFocused.set(false)}
style="--row-height:{$rowHeight}px; --default-row-height:{DefaultRowHeight}px; --gutter-width:{GutterWidth}px; --max-cell-render-overflow:{MaxCellRenderOverflow}px; --content-lines:{$contentLines}; --min-height:{$minHeight}px; --controls-height:{ControlsHeight}px; --scroll-bar-size:{ScrollBarSize}px;" style="--row-height:{$rowHeight}px; --default-row-height:{Constants.DefaultRowHeight}px; --gutter-width:{Constants.GutterWidth}px; --max-cell-render-overflow:{Constants.MaxCellRenderOverflow}px; --content-lines:{$contentLines}; --min-height:{$minHeight}px; --controls-height:{Constants.ControlsHeight}px; --scroll-bar-size:{Constants.ScrollBarSize}px;"
> >
{#if $$slots.controls} {#if $$slots.controls}
<div class="controls"> <div class="controls">

View File

@ -1,6 +1,3 @@
import { helpers } from "@budibase/shared-core"
import { TypeIconMap } from "../../../constants"
// We can't use "-" as a separator as this can be present in the ID // We can't use "-" as a separator as this can be present in the ID
// or column name, so we use something very unusual to avoid this problem // or column name, so we use something very unusual to avoid this problem
const JOINING_CHARACTER = "‽‽" const JOINING_CHARACTER = "‽‽"
@ -18,24 +15,6 @@ export const getCellID = (rowId, fieldName) => {
return `${rowId}${JOINING_CHARACTER}${fieldName}` return `${rowId}${JOINING_CHARACTER}${fieldName}`
} }
export const getColumnIcon = column => {
if (column.schema.autocolumn) {
return "MagicWand"
}
if (helpers.schema.isDeprecatedSingleUserColumn(column.schema)) {
return "User"
}
const { type, subtype } = column.schema
const result =
typeof TypeIconMap[type] === "object" && subtype
? TypeIconMap[type][subtype]
: TypeIconMap[type]
return result || "Text"
}
export const parseEventLocation = e => { export const parseEventLocation = e => {
return { return {
x: e.clientX ?? e.touches?.[0]?.clientX, x: e.clientX ?? e.touches?.[0]?.clientX,

View File

@ -5,6 +5,7 @@ export * as RoleUtils from "./roles"
export * as Utils from "./utils" export * as Utils from "./utils"
export * as RowUtils from "./rows" export * as RowUtils from "./rows"
export * as search from "./searchFields" export * as search from "./searchFields"
export * as SchemaUtils from "./schema"
export { memo, derivedMemo } from "./memo" export { memo, derivedMemo } from "./memo"
export { createWebsocket } from "./websocket" export { createWebsocket } from "./websocket"
export * from "./download" export * from "./download"

View File

@ -0,0 +1,20 @@
import { helpers } from "@budibase/shared-core"
import { TypeIconMap } from "../constants"
export const getColumnIcon = column => {
if (column.schema.autocolumn) {
return "MagicWand"
}
if (helpers.schema.isDeprecatedSingleUserColumn(column.schema)) {
return "User"
}
const { type, subtype } = column.schema
const result =
typeof TypeIconMap[type] === "object" && subtype
? TypeIconMap[type][subtype]
: TypeIconMap[type]
return result || "Text"
}