Rewrite most of the screen creation code to account for views and clean up mess
This commit is contained in:
parent
71c092be1e
commit
09ad3e73ae
|
@ -1,10 +1,10 @@
|
||||||
import rowListScreen from "./rowListScreen"
|
import rowListScreen from "./rowListScreen"
|
||||||
import createFromScratchScreen from "./createFromScratchScreen"
|
import createFromScratchScreen from "./createFromScratchScreen"
|
||||||
|
|
||||||
const allTemplates = tables => [...rowListScreen(tables)]
|
const allTemplates = datasources => [...rowListScreen(datasources)]
|
||||||
|
|
||||||
// Allows us to apply common behaviour to all create() functions
|
// Allows us to apply common behaviour to all create() functions
|
||||||
const createTemplateOverride = (frontendState, template) => () => {
|
const createTemplateOverride = template => () => {
|
||||||
const screen = template.create()
|
const screen = template.create()
|
||||||
screen.name = screen.props._id
|
screen.name = screen.props._id
|
||||||
screen.routing.route = screen.routing.route.toLowerCase()
|
screen.routing.route = screen.routing.route.toLowerCase()
|
||||||
|
@ -12,14 +12,13 @@ const createTemplateOverride = (frontendState, template) => () => {
|
||||||
return screen
|
return screen
|
||||||
}
|
}
|
||||||
|
|
||||||
export default (frontendState, tables) => {
|
export default datasources => {
|
||||||
const enrichTemplate = template => ({
|
const enrichTemplate = template => ({
|
||||||
...template,
|
...template,
|
||||||
create: createTemplateOverride(frontendState, template),
|
create: createTemplateOverride(template),
|
||||||
})
|
})
|
||||||
|
|
||||||
const fromScratch = enrichTemplate(createFromScratchScreen)
|
const fromScratch = enrichTemplate(createFromScratchScreen)
|
||||||
const tableTemplates = allTemplates(tables).map(enrichTemplate)
|
const tableTemplates = allTemplates(datasources).map(enrichTemplate)
|
||||||
return [
|
return [
|
||||||
fromScratch,
|
fromScratch,
|
||||||
...tableTemplates.sort((templateA, templateB) => {
|
...tableTemplates.sort((templateA, templateB) => {
|
||||||
|
|
|
@ -2,31 +2,26 @@ import sanitizeUrl from "./utils/sanitizeUrl"
|
||||||
import { Screen } from "./utils/Screen"
|
import { Screen } from "./utils/Screen"
|
||||||
import { Component } from "./utils/Component"
|
import { Component } from "./utils/Component"
|
||||||
|
|
||||||
export default function (tables) {
|
export default function (datasources) {
|
||||||
return tables.map(table => {
|
return datasources.map(datasource => {
|
||||||
return {
|
return {
|
||||||
name: `${table.name} - List`,
|
name: `${datasource.name} - List`,
|
||||||
create: () => createScreen(table),
|
create: () => createScreen(datasource),
|
||||||
id: ROW_LIST_TEMPLATE,
|
id: ROW_LIST_TEMPLATE,
|
||||||
table: table._id,
|
resourceId: datasource.resourceId,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ROW_LIST_TEMPLATE = "ROW_LIST_TEMPLATE"
|
export const ROW_LIST_TEMPLATE = "ROW_LIST_TEMPLATE"
|
||||||
export const rowListUrl = table => sanitizeUrl(`/${table.name}`)
|
export const rowListUrl = datasource => sanitizeUrl(`/${datasource.name}`)
|
||||||
|
|
||||||
const generateTableBlock = table => {
|
const generateTableBlock = datasource => {
|
||||||
const tableBlock = new Component("@budibase/standard-components/tableblock")
|
const tableBlock = new Component("@budibase/standard-components/tableblock")
|
||||||
tableBlock
|
tableBlock
|
||||||
.customProps({
|
.customProps({
|
||||||
title: table.name,
|
title: datasource.name,
|
||||||
dataSource: {
|
dataSource: datasource,
|
||||||
label: table.name,
|
|
||||||
name: table._id,
|
|
||||||
tableId: table._id,
|
|
||||||
type: "table",
|
|
||||||
},
|
|
||||||
sortOrder: "Ascending",
|
sortOrder: "Ascending",
|
||||||
size: "spectrum--medium",
|
size: "spectrum--medium",
|
||||||
paginate: true,
|
paginate: true,
|
||||||
|
@ -36,14 +31,14 @@ const generateTableBlock = table => {
|
||||||
titleButtonText: "Create row",
|
titleButtonText: "Create row",
|
||||||
titleButtonClickBehaviour: "new",
|
titleButtonClickBehaviour: "new",
|
||||||
})
|
})
|
||||||
.instanceName(`${table.name} - Table block`)
|
.instanceName(`${datasource.name} - Table block`)
|
||||||
return tableBlock
|
return tableBlock
|
||||||
}
|
}
|
||||||
|
|
||||||
const createScreen = table => {
|
const createScreen = datasource => {
|
||||||
return new Screen()
|
return new Screen()
|
||||||
.route(rowListUrl(table))
|
.route(rowListUrl(datasource))
|
||||||
.instanceName(`${table.name} - List`)
|
.instanceName(`${datasource.name} - List`)
|
||||||
.addChild(generateTableBlock(table))
|
.addChild(generateTableBlock(datasource))
|
||||||
.json()
|
.json()
|
||||||
}
|
}
|
||||||
|
|
|
@ -179,7 +179,7 @@
|
||||||
<Modal bind:this={datasourceModal}>
|
<Modal bind:this={datasourceModal}>
|
||||||
<DatasourceModal
|
<DatasourceModal
|
||||||
onConfirm={confirmScreenDatasources}
|
onConfirm={confirmScreenDatasources}
|
||||||
initalScreens={!selectedTemplates ? [] : [...selectedTemplates]}
|
initialScreens={!selectedTemplates ? [] : [...selectedTemplates]}
|
||||||
/>
|
/>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
|
|
|
@ -1,41 +1,30 @@
|
||||||
<script>
|
<script>
|
||||||
import { store } from "builderStore"
|
import { ModalContent, Layout, notifications, Body } from "@budibase/bbui"
|
||||||
import {
|
import { datasources } from "stores/backend"
|
||||||
ModalContent,
|
|
||||||
Layout,
|
|
||||||
notifications,
|
|
||||||
Icon,
|
|
||||||
Body,
|
|
||||||
} from "@budibase/bbui"
|
|
||||||
import { tables, datasources } from "stores/backend"
|
|
||||||
import getTemplates from "builderStore/store/screenTemplates"
|
|
||||||
import ICONS from "components/backend/DatasourceNavigator/icons"
|
import ICONS from "components/backend/DatasourceNavigator/icons"
|
||||||
import { IntegrationNames } from "constants"
|
import { IntegrationNames } from "constants"
|
||||||
import { onMount } from "svelte"
|
import { onMount } from "svelte"
|
||||||
|
import rowListScreen from "builderStore/store/screenTemplates/rowListScreen"
|
||||||
|
import DatasourceTemplateRow from "./DatasourceTemplateRow.svelte"
|
||||||
|
|
||||||
export let onCancel
|
export let onCancel
|
||||||
export let onConfirm
|
export let onConfirm
|
||||||
export let initalScreens = []
|
export let initialScreens = []
|
||||||
|
|
||||||
let selectedScreens = [...initalScreens]
|
let selectedScreens = [...initialScreens]
|
||||||
|
|
||||||
const toggleScreenSelection = (table, datasource) => {
|
$: filteredSources = $datasources.list?.filter(datasource => {
|
||||||
if (selectedScreens.find(s => s.table === table._id)) {
|
return datasource.source !== IntegrationNames.REST && datasource["entities"]
|
||||||
|
})
|
||||||
|
|
||||||
|
const toggleSelection = datasource => {
|
||||||
|
const { resourceId } = datasource
|
||||||
|
if (selectedScreens.find(s => s.resourceId === resourceId)) {
|
||||||
selectedScreens = selectedScreens.filter(
|
selectedScreens = selectedScreens.filter(
|
||||||
screen => screen.table !== table._id
|
screen => screen.resourceId !== resourceId
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
let partialTemplates = getTemplates($store, $tables.list).reduce(
|
selectedScreens = [...selectedScreens, rowListScreen([datasource])[0]]
|
||||||
(acc, template) => {
|
|
||||||
if (template.table === table._id) {
|
|
||||||
template.datasource = datasource.name
|
|
||||||
acc.push(template)
|
|
||||||
}
|
|
||||||
return acc
|
|
||||||
},
|
|
||||||
[]
|
|
||||||
)
|
|
||||||
selectedScreens = [...partialTemplates, ...selectedScreens]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,18 +34,6 @@
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
$: filteredSources = Array.isArray($datasources.list)
|
|
||||||
? $datasources.list.reduce((acc, datasource) => {
|
|
||||||
if (
|
|
||||||
datasource.source !== IntegrationNames.REST &&
|
|
||||||
datasource["entities"]
|
|
||||||
) {
|
|
||||||
acc.push(datasource)
|
|
||||||
}
|
|
||||||
return acc
|
|
||||||
}, [])
|
|
||||||
: []
|
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
try {
|
try {
|
||||||
await datasources.fetch()
|
await datasources.fetch()
|
||||||
|
@ -81,6 +58,9 @@
|
||||||
</Body>
|
</Body>
|
||||||
<Layout noPadding gap="S">
|
<Layout noPadding gap="S">
|
||||||
{#each filteredSources as datasource}
|
{#each filteredSources as datasource}
|
||||||
|
{@const entities = Array.isArray(datasource.entities)
|
||||||
|
? datasource.entities
|
||||||
|
: Object.values(datasource.entities || {})}
|
||||||
<div class="data-source-wrap">
|
<div class="data-source-wrap">
|
||||||
<div class="data-source-header">
|
<div class="data-source-header">
|
||||||
<svelte:component
|
<svelte:component
|
||||||
|
@ -90,64 +70,49 @@
|
||||||
/>
|
/>
|
||||||
<div class="data-source-name">{datasource.name}</div>
|
<div class="data-source-name">{datasource.name}</div>
|
||||||
</div>
|
</div>
|
||||||
{#if Array.isArray(datasource.entities)}
|
<!-- List all tables -->
|
||||||
{#each datasource.entities.filter(table => table._id !== "ta_users") as table}
|
{#each entities.filter(table => table._id !== "ta_users") as table}
|
||||||
<div
|
{@const views = Object.values(table.views || {})}
|
||||||
class="data-source-entry"
|
{@const datasource = {
|
||||||
class:selected={selectedScreens.find(
|
...table,
|
||||||
x => x.table === table._id
|
// Legacy properties
|
||||||
)}
|
tableId: table._id,
|
||||||
on:click={() => toggleScreenSelection(table, datasource)}
|
label: table.name,
|
||||||
>
|
// New consistent properties
|
||||||
<svg
|
resourceId: table._id,
|
||||||
width="16px"
|
name: table.name,
|
||||||
height="16px"
|
type: "table",
|
||||||
class="spectrum-Icon"
|
}}
|
||||||
style="color: white"
|
{@const selected = selectedScreens.find(
|
||||||
focusable="false"
|
x => x.resourceId === datasource.resourceId
|
||||||
>
|
)}
|
||||||
<use xlink:href="#spectrum-icon-18-Table" />
|
<DatasourceTemplateRow
|
||||||
</svg>
|
on:click={() => toggleSelection(datasource)}
|
||||||
{table.name}
|
{selected}
|
||||||
{#if selectedScreens.find(x => x.table === table._id)}
|
{datasource}
|
||||||
<span class="data-source-check">
|
/>
|
||||||
<Icon size="S" name="CheckmarkCircle" />
|
|
||||||
</span>
|
<!-- List all views inside this table -->
|
||||||
{/if}
|
{#each views as view}
|
||||||
</div>
|
{@const datasource = {
|
||||||
|
...view,
|
||||||
|
// Legacy properties
|
||||||
|
label: view.name,
|
||||||
|
// New consistent properties
|
||||||
|
resourceId: view.id,
|
||||||
|
name: view.name,
|
||||||
|
type: "viewV2",
|
||||||
|
}}
|
||||||
|
{@const selected = selectedScreens.find(
|
||||||
|
x => x.resourceId === datasource.resourceId
|
||||||
|
)}
|
||||||
|
<DatasourceTemplateRow
|
||||||
|
on:click={() => toggleSelection(datasource)}
|
||||||
|
{selected}
|
||||||
|
{datasource}
|
||||||
|
/>
|
||||||
{/each}
|
{/each}
|
||||||
{/if}
|
{/each}
|
||||||
{#if datasource["entities"] && !Array.isArray(datasource.entities)}
|
|
||||||
{#each Object.keys(datasource.entities).filter(table => table._id !== "ta_users") as table_key}
|
|
||||||
<div
|
|
||||||
class="data-source-entry"
|
|
||||||
class:selected={selectedScreens.find(
|
|
||||||
x => x.table === datasource.entities[table_key]._id
|
|
||||||
)}
|
|
||||||
on:click={() =>
|
|
||||||
toggleScreenSelection(
|
|
||||||
datasource.entities[table_key],
|
|
||||||
datasource
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
width="16px"
|
|
||||||
height="16px"
|
|
||||||
class="spectrum-Icon"
|
|
||||||
style="color: white"
|
|
||||||
focusable="false"
|
|
||||||
>
|
|
||||||
<use xlink:href="#spectrum-icon-18-Table" />
|
|
||||||
</svg>
|
|
||||||
{datasource.entities[table_key].name}
|
|
||||||
{#if selectedScreens.find(x => x.table === datasource.entities[table_key]._id)}
|
|
||||||
<span class="data-source-check">
|
|
||||||
<Icon size="S" name="CheckmarkCircle" />
|
|
||||||
</span>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
{/each}
|
|
||||||
{/if}
|
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
</Layout>
|
</Layout>
|
||||||
|
@ -160,42 +125,10 @@
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-gap: var(--spacing-s);
|
grid-gap: var(--spacing-s);
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-source-header {
|
.data-source-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: var(--spacing-m);
|
gap: var(--spacing-m);
|
||||||
padding-bottom: var(--spacing-xs);
|
padding-bottom: var(--spacing-xs);
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-source-entry {
|
|
||||||
cursor: pointer;
|
|
||||||
grid-gap: var(--spectrum-alias-grid-margin-xsmall);
|
|
||||||
padding: var(--spectrum-alias-item-padding-s);
|
|
||||||
background: var(--spectrum-alias-background-color-secondary);
|
|
||||||
transition: 0.3s all;
|
|
||||||
border: 1px solid var(--spectrum-global-color-gray-300);
|
|
||||||
border-radius: 4px;
|
|
||||||
border-width: 1px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.data-source-entry:hover,
|
|
||||||
.selected {
|
|
||||||
background: var(--spectrum-alias-background-color-tertiary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.data-source-entry .data-source-check {
|
|
||||||
margin-left: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.data-source-entry :global(.spectrum-Icon) {
|
|
||||||
min-width: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.data-source-entry .data-source-check :global(.spectrum-Icon) {
|
|
||||||
color: var(--spectrum-global-color-green-600);
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
<script>
|
||||||
|
import { Icon } from "@budibase/bbui"
|
||||||
|
export let datasource
|
||||||
|
export let selected = false
|
||||||
|
|
||||||
|
$: icon = datasource.type === "viewV2" ? "Remove" : "Table"
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="data-source-entry" class:selected on:click>
|
||||||
|
<Icon name={icon} color="var(--spectrum-global-color-gray-600)" />
|
||||||
|
{datasource.name}
|
||||||
|
{#if selected}
|
||||||
|
<span class="data-source-check">
|
||||||
|
<Icon size="S" name="CheckmarkCircle" />
|
||||||
|
</span>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.data-source-entry {
|
||||||
|
cursor: pointer;
|
||||||
|
grid-gap: 12px;
|
||||||
|
padding: var(--spectrum-alias-item-padding-s);
|
||||||
|
background: var(--spectrum-alias-background-color-secondary);
|
||||||
|
transition: 0.3s all;
|
||||||
|
border: 1px solid var(--spectrum-global-color-gray-300);
|
||||||
|
border-radius: 4px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.data-source-entry:hover,
|
||||||
|
.selected {
|
||||||
|
background: var(--spectrum-alias-background-color-tertiary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.data-source-check {
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
.data-source-check :global(.spectrum-Icon) {
|
||||||
|
color: var(--spectrum-global-color-green-600);
|
||||||
|
}
|
||||||
|
</style>
|
Loading…
Reference in New Issue