Add view CRUD and table editing via new UI
This commit is contained in:
parent
fa80d99139
commit
d313968eaa
|
@ -9,7 +9,6 @@
|
||||||
import GridAddColumnModal from "components/backend/DataTable/modals/grid/GridCreateColumnModal.svelte"
|
import GridAddColumnModal from "components/backend/DataTable/modals/grid/GridCreateColumnModal.svelte"
|
||||||
import GridCreateEditRowModal from "components/backend/DataTable/modals/grid/GridCreateEditRowModal.svelte"
|
import GridCreateEditRowModal from "components/backend/DataTable/modals/grid/GridCreateEditRowModal.svelte"
|
||||||
import GridEditUserModal from "components/backend/DataTable/modals/grid/GridEditUserModal.svelte"
|
import GridEditUserModal from "components/backend/DataTable/modals/grid/GridEditUserModal.svelte"
|
||||||
import GridCreateViewButton from "components/backend/DataTable/buttons/grid/GridCreateViewButton.svelte"
|
|
||||||
import GridImportButton from "components/backend/DataTable/buttons/grid/GridImportButton.svelte"
|
import GridImportButton from "components/backend/DataTable/buttons/grid/GridImportButton.svelte"
|
||||||
import GridExportButton from "components/backend/DataTable/buttons/grid/GridExportButton.svelte"
|
import GridExportButton from "components/backend/DataTable/buttons/grid/GridExportButton.svelte"
|
||||||
import GridFilterButton from "components/backend/DataTable/buttons/grid/GridFilterButton.svelte"
|
import GridFilterButton from "components/backend/DataTable/buttons/grid/GridFilterButton.svelte"
|
||||||
|
@ -77,9 +76,6 @@
|
||||||
<GridFilterButton />
|
<GridFilterButton />
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
<svelte:fragment slot="controls">
|
<svelte:fragment slot="controls">
|
||||||
{#if !isUsersTable}
|
|
||||||
<GridCreateViewButton />
|
|
||||||
{/if}
|
|
||||||
<GridManageAccessButton />
|
<GridManageAccessButton />
|
||||||
{#if !isUsersTable}
|
{#if !isUsersTable}
|
||||||
<GridCreateAutomationButton />
|
<GridCreateAutomationButton />
|
||||||
|
|
|
@ -39,9 +39,7 @@
|
||||||
|
|
||||||
const selectTable = tableId => {
|
const selectTable = tableId => {
|
||||||
tables.select(tableId)
|
tables.select(tableId)
|
||||||
if (!$isActive("./table/:tableId")) {
|
$goto(`./table/${tableId}`)
|
||||||
$goto(`./table/${tableId}`)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function openNode(datasource) {
|
function openNode(datasource) {
|
||||||
|
|
|
@ -1,14 +1,11 @@
|
||||||
<script>
|
<script>
|
||||||
import TableNavItem from "./TableNavItem/TableNavItem.svelte"
|
import TableNavItem from "./TableNavItem/TableNavItem.svelte"
|
||||||
|
import { alphabetical } from "./utils"
|
||||||
|
|
||||||
export let tables
|
export let tables
|
||||||
export let selectTable
|
export let selectTable
|
||||||
|
|
||||||
$: sortedTables = tables.sort(alphabetical)
|
$: sortedTables = tables.sort(alphabetical)
|
||||||
|
|
||||||
const alphabetical = (a, b) => {
|
|
||||||
return a.name?.toLowerCase() > b.name?.toLowerCase() ? 1 : -1
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="hierarchy-items-container">
|
<div class="hierarchy-items-container">
|
||||||
|
|
|
@ -66,3 +66,7 @@ export const parseFile = e => {
|
||||||
reader.readAsText(file)
|
reader.readAsText(file)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const alphabetical = (a, b) => {
|
||||||
|
return a.name?.toLowerCase() > b.name?.toLowerCase() ? 1 : -1
|
||||||
|
}
|
||||||
|
|
|
@ -1,16 +1,21 @@
|
||||||
<script>
|
<script>
|
||||||
import { getContext } from "svelte"
|
import { Modal, Input, notifications, ModalContent } from "@budibase/bbui"
|
||||||
import { Input, notifications, ModalContent } from "@budibase/bbui"
|
|
||||||
import { goto } from "@roxi/routify"
|
import { goto } from "@roxi/routify"
|
||||||
import { viewsV2 } from "stores/builder"
|
import { viewsV2 } from "stores/builder"
|
||||||
|
|
||||||
const { filter, sort, definition } = getContext("grid")
|
export let table
|
||||||
|
|
||||||
let name
|
let name
|
||||||
|
let modal
|
||||||
|
|
||||||
$: views = Object.keys($definition?.views || {}).map(x => x.toLowerCase())
|
$: views = Object.keys(table?.views || {}).map(x => x.toLowerCase())
|
||||||
$: nameExists = views.includes(name?.trim().toLowerCase())
|
$: nameExists = views.includes(name?.trim().toLowerCase())
|
||||||
|
|
||||||
|
export const show = () => {
|
||||||
|
name = null
|
||||||
|
modal?.show()
|
||||||
|
}
|
||||||
|
|
||||||
const enrichSchema = schema => {
|
const enrichSchema = schema => {
|
||||||
// We need to sure that "visible" is set to true for any fields which have
|
// We need to sure that "visible" is set to true for any fields which have
|
||||||
// not yet been saved with grid metadata attached
|
// not yet been saved with grid metadata attached
|
||||||
|
@ -28,33 +33,30 @@
|
||||||
try {
|
try {
|
||||||
const newView = await viewsV2.create({
|
const newView = await viewsV2.create({
|
||||||
name,
|
name,
|
||||||
tableId: $definition._id,
|
tableId: table._id,
|
||||||
query: $filter,
|
schema: enrichSchema(table.schema),
|
||||||
sort: {
|
primaryDisplay: table.primaryDisplay,
|
||||||
field: $sort.column,
|
|
||||||
order: $sort.order,
|
|
||||||
},
|
|
||||||
schema: enrichSchema($definition.schema),
|
|
||||||
primaryDisplay: $definition.primaryDisplay,
|
|
||||||
})
|
})
|
||||||
notifications.success(`View ${name} created`)
|
notifications.success(`View ${name} created`)
|
||||||
$goto(`../../view/v2/${newView.id}`)
|
$goto(`./${newView.id}`)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
notifications.error("Error creating view")
|
notifications.error("Error creating view")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<ModalContent
|
<Modal bind:this={modal}>
|
||||||
title="Create view"
|
<ModalContent
|
||||||
confirmText="Create view"
|
title="Create view"
|
||||||
onConfirm={saveView}
|
confirmText="Create view"
|
||||||
disabled={nameExists}
|
onConfirm={saveView}
|
||||||
>
|
disabled={nameExists}
|
||||||
<Input
|
>
|
||||||
label="View name"
|
<Input
|
||||||
thin
|
label="View name"
|
||||||
bind:value={name}
|
thin
|
||||||
error={nameExists ? "A view already exists with that name" : null}
|
bind:value={name}
|
||||||
/>
|
error={nameExists ? "A view already exists with that name" : null}
|
||||||
</ModalContent>
|
/>
|
||||||
|
</ModalContent>
|
||||||
|
</Modal>
|
|
@ -6,7 +6,7 @@
|
||||||
contextMenuStore,
|
contextMenuStore,
|
||||||
} from "stores/builder"
|
} from "stores/builder"
|
||||||
import IntegrationIcon from "components/backend/DatasourceNavigator/IntegrationIcon.svelte"
|
import IntegrationIcon from "components/backend/DatasourceNavigator/IntegrationIcon.svelte"
|
||||||
import { Icon } from "@budibase/bbui"
|
import { Icon, Button } from "@budibase/bbui"
|
||||||
import { params, url } from "@roxi/routify"
|
import { params, url } from "@roxi/routify"
|
||||||
import EditViewModal from "./EditViewModal.svelte"
|
import EditViewModal from "./EditViewModal.svelte"
|
||||||
import DeleteViewModal from "./DeleteViewModal.svelte"
|
import DeleteViewModal from "./DeleteViewModal.svelte"
|
||||||
|
@ -16,8 +16,11 @@
|
||||||
import { tick } from "svelte"
|
import { tick } from "svelte"
|
||||||
import { DB_TYPE_EXTERNAL } from "constants/backend"
|
import { DB_TYPE_EXTERNAL } from "constants/backend"
|
||||||
import { TableNames } from "constants"
|
import { TableNames } from "constants"
|
||||||
|
import { alphabetical } from "components/backend/TableNavigator/utils"
|
||||||
|
import CreateViewModal from "./CreateViewModal.svelte"
|
||||||
|
|
||||||
// Editing table
|
// Editing table
|
||||||
|
let createViewModal
|
||||||
let editTableModal
|
let editTableModal
|
||||||
let deleteTableModal
|
let deleteTableModal
|
||||||
|
|
||||||
|
@ -101,10 +104,6 @@
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const alphabetical = (a, b) => {
|
|
||||||
return a.name < b.name ? -1 : 1
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="view-nav-bar">
|
<div class="view-nav-bar">
|
||||||
|
@ -126,7 +125,13 @@
|
||||||
<UserAvatars size="XS" users={tableSelectedBy} />
|
<UserAvatars size="XS" users={tableSelectedBy} />
|
||||||
{/if}
|
{/if}
|
||||||
{#if tableEditable}
|
{#if tableEditable}
|
||||||
<Icon on:click={openTableContextMenu} s hoverable name="MoreSmallList" />
|
<Icon
|
||||||
|
on:click={openTableContextMenu}
|
||||||
|
hoverable
|
||||||
|
name="MoreSmallList"
|
||||||
|
color="var(--spectrum-global-color-gray-600)"
|
||||||
|
hoverColor="var(--spectrum-global-color-gray-900)"
|
||||||
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
</a>
|
</a>
|
||||||
{#each views as view (view.id)}
|
{#each views as view (view.id)}
|
||||||
|
@ -145,15 +150,33 @@
|
||||||
{/if}
|
{/if}
|
||||||
<Icon
|
<Icon
|
||||||
on:click={e => openViewContextMenu(e, view)}
|
on:click={e => openViewContextMenu(e, view)}
|
||||||
s
|
|
||||||
hoverable
|
hoverable
|
||||||
name="MoreSmallList"
|
name="MoreSmallList"
|
||||||
|
color="var(--spectrum-global-color-gray-600)"
|
||||||
|
hoverColor="var(--spectrum-global-color-gray-900)"
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
{/each}
|
{/each}
|
||||||
|
{#if !views.length && tableEditable}
|
||||||
|
<Button cta on:click={createViewModal?.show}>Create a view</Button>
|
||||||
|
<span>
|
||||||
|
To create subsets of data, control access and more, create a view.
|
||||||
|
</span>
|
||||||
|
{/if}
|
||||||
|
{#if views.length}
|
||||||
|
<Icon
|
||||||
|
name="Add"
|
||||||
|
size="L"
|
||||||
|
hoverable
|
||||||
|
color="var(--spectrum-global-color-gray-600)"
|
||||||
|
hoverColor="var(--spectrum-global-color-gray-900)"
|
||||||
|
on:click={createViewModal?.show}
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if table}
|
{#if table && tableEditable}
|
||||||
|
<CreateViewModal {table} bind:this={createViewModal} />
|
||||||
<EditTableModal {table} bind:this={editTableModal} />
|
<EditTableModal {table} bind:this={editTableModal} />
|
||||||
<DeleteTableModal {table} bind:this={deleteTableModal} />
|
<DeleteTableModal {table} bind:this={deleteTableModal} />
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -183,7 +206,7 @@
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: var(--spacing-m);
|
gap: var(--spacing-m);
|
||||||
transition: background 130ms ease-out, color 130ms ease-out;
|
transition: background 130ms ease-out, color 130ms ease-out;
|
||||||
color: var(--spectrum-global-color-gray-700);
|
color: var(--spectrum-global-color-gray-600);
|
||||||
}
|
}
|
||||||
.title {
|
.title {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
|
|
Loading…
Reference in New Issue