Merge pull request #5266 from Budibase/feature/new-screen-addition-ui
Screen workflow updates
This commit is contained in:
commit
80853d7c09
9 changed files with 612 additions and 191 deletions
|
@ -1,51 +1,103 @@
|
||||||
import filterTests from "../support/filterTests"
|
import filterTests from "../support/filterTests"
|
||||||
|
|
||||||
filterTests(['smoke', 'all'], () => {
|
filterTests(['smoke', 'all'], () => {
|
||||||
context("Auto Screens UI", () => {
|
context("Auto Screens UI", () => {
|
||||||
before(() => {
|
before(() => {
|
||||||
cy.login()
|
cy.login()
|
||||||
cy.createTestApp()
|
|
||||||
})
|
|
||||||
|
|
||||||
it("should generate internal table screens", () => {
|
|
||||||
// Create autogenerated screens from the internal table
|
|
||||||
cy.createAutogeneratedScreens(["Cypress Tests"])
|
|
||||||
// Confirm screens have been auto generated
|
|
||||||
cy.get(".nav-items-container").contains("cypress-tests").click({ force: true })
|
|
||||||
cy.get(".nav-items-container").should('contain', 'cypress-tests/:id')
|
|
||||||
.and('contain', 'cypress-tests/new/row')
|
|
||||||
})
|
|
||||||
|
|
||||||
it("should generate multiple internal table screens at once", () => {
|
|
||||||
// Create a second internal table
|
|
||||||
const initialTable = "Cypress Tests"
|
|
||||||
const secondTable = "Table Two"
|
|
||||||
cy.createTable(secondTable)
|
|
||||||
// Create autogenerated screens from the internal tables
|
|
||||||
cy.createAutogeneratedScreens([initialTable, secondTable])
|
|
||||||
// Confirm screens have been auto generated
|
|
||||||
cy.get(".nav-items-container").contains("cypress-tests").click({ force: true })
|
|
||||||
// Previously generated tables are suffixed with numbers - as expected
|
|
||||||
cy.get(".nav-items-container").should('contain', 'cypress-tests-2/:id')
|
|
||||||
.and('contain', 'cypress-tests-2/new/row')
|
|
||||||
cy.get(".nav-items-container").contains("table-two").click()
|
|
||||||
cy.get(".nav-items-container").should('contain', 'table-two/:id')
|
|
||||||
.and('contain', 'table-two/new/row')
|
|
||||||
})
|
|
||||||
|
|
||||||
if (Cypress.env("TEST_ENV")) {
|
|
||||||
it("should generate data source screens", () => {
|
|
||||||
// Using MySQL data source for testing this
|
|
||||||
const datasource = "MySQL"
|
|
||||||
// Select & configure MySQL data source
|
|
||||||
cy.selectExternalDatasource(datasource)
|
|
||||||
cy.addDatasourceConfig(datasource)
|
|
||||||
// Create autogenerated screens from a MySQL table - MySQL contains books table
|
|
||||||
cy.createAutogeneratedScreens(["books"])
|
|
||||||
cy.get(".nav-items-container").contains("books").click()
|
|
||||||
cy.get(".nav-items-container").should('contain', 'books/:id')
|
|
||||||
.and('contain', 'books/new/row')
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("should disable the autogenerated screen options if no sources are available", () => {
|
||||||
|
cy.createApp("First Test App", false)
|
||||||
|
|
||||||
|
cy.closeModal();
|
||||||
|
|
||||||
|
cy.contains("Design").click()
|
||||||
|
cy.get("[aria-label=AddCircle]").click()
|
||||||
|
cy.get(".spectrum-Modal").within(() => {
|
||||||
|
cy.get(".item.disabled").contains("Autogenerated screens")
|
||||||
|
cy.get(".confirm-wrap .spectrum-Button").should('be.disabled')
|
||||||
|
})
|
||||||
|
|
||||||
|
cy.deleteAllApps()
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should not display incompatible sources", () => {
|
||||||
|
cy.createApp("Test App")
|
||||||
|
|
||||||
|
cy.selectExternalDatasource("REST")
|
||||||
|
cy.selectExternalDatasource("S3")
|
||||||
|
cy.get(".spectrum-Modal").within(() => {
|
||||||
|
cy.get(".spectrum-Button").contains("Save and continue to query").click({ force : true })
|
||||||
|
})
|
||||||
|
|
||||||
|
cy.navigateToAutogeneratedModal()
|
||||||
|
|
||||||
|
cy.get('.data-source-entry').should('have.length', 1)
|
||||||
|
cy.get('.data-source-entry')
|
||||||
|
|
||||||
|
cy.deleteAllApps()
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should generate internal table screens", () => {
|
||||||
|
cy.createTestApp()
|
||||||
|
// Create Autogenerated screens from the internal table
|
||||||
|
cy.createDatasourceScreen(["Cypress Tests"])
|
||||||
|
// Confirm screens have been auto generated
|
||||||
|
cy.get(".nav-items-container").contains("cypress-tests").click({ force: true })
|
||||||
|
cy.get(".nav-items-container").should('contain', 'cypress-tests/:id')
|
||||||
|
.and('contain', 'cypress-tests/new/row')
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should generate multiple internal table screens at once", () => {
|
||||||
|
// Create a second internal table
|
||||||
|
const initialTable = "Cypress Tests"
|
||||||
|
const secondTable = "Table Two"
|
||||||
|
cy.createTable(secondTable)
|
||||||
|
// Create Autogenerated screens from the internal tables
|
||||||
|
cy.createDatasourceScreen([initialTable, secondTable])
|
||||||
|
// Confirm screens have been auto generated
|
||||||
|
cy.get(".nav-items-container").contains("cypress-tests").click({ force: true })
|
||||||
|
// Previously generated tables are suffixed with numbers - as expected
|
||||||
|
cy.get(".nav-items-container").should('contain', 'cypress-tests-2/:id')
|
||||||
|
.and('contain', 'cypress-tests-2/new/row')
|
||||||
|
cy.get(".nav-items-container").contains("table-two").click()
|
||||||
|
cy.get(".nav-items-container").should('contain', 'table-two/:id')
|
||||||
|
.and('contain', 'table-two/new/row')
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should generate multiple internal table screens with the same screen access level", () => {
|
||||||
|
//The tables created in the previous step still exist
|
||||||
|
cy.createTable("Table Three")
|
||||||
|
cy.createTable("Table Four")
|
||||||
|
cy.createDatasourceScreen(["Table Three", "Table Four"], "Admin")
|
||||||
|
|
||||||
|
cy.get(".nav-items-container").contains("table-three").click()
|
||||||
|
cy.get(".nav-items-container").should('contain', 'table-three/:id')
|
||||||
|
.and('contain', 'table-three/new/row')
|
||||||
|
|
||||||
|
cy.get(".nav-items-container").contains("table-four").click()
|
||||||
|
cy.get(".nav-items-container").should('contain', 'table-four/:id')
|
||||||
|
.and('contain', 'table-four/new/row')
|
||||||
|
|
||||||
|
//The access level should now be set to admin. Previous screens should be filtered.
|
||||||
|
cy.get(".nav-items-container").contains("table-two").should('not.exist')
|
||||||
|
cy.get(".nav-items-container").contains("cypress-tests").should('not.exist')
|
||||||
|
})
|
||||||
|
|
||||||
|
if (Cypress.env("TEST_ENV")) {
|
||||||
|
it("should generate data source screens", () => {
|
||||||
|
// Using MySQL data source for testing this
|
||||||
|
const datasource = "MySQL"
|
||||||
|
// Select & configure MySQL data source
|
||||||
|
cy.selectExternalDatasource(datasource)
|
||||||
|
cy.addDatasourceConfig(datasource)
|
||||||
|
// Create Autogenerated screens from a MySQL table - MySQL contains books table
|
||||||
|
cy.createDatasourceScreen(["books"])
|
||||||
|
|
||||||
|
cy.get(".nav-items-container").contains("books").click()
|
||||||
|
cy.get(".nav-items-container").should('contain', 'books/:id')
|
||||||
|
.and('contain', 'books/new/row')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -26,7 +26,7 @@ filterTests(['smoke', 'all'], () => {
|
||||||
|
|
||||||
it("should add a URL param binding", () => {
|
it("should add a URL param binding", () => {
|
||||||
const paramName = "foo"
|
const paramName = "foo"
|
||||||
cy.createScreen("Test Param", `/test/:${paramName}`)
|
cy.createScreen(`/test/:${paramName}`)
|
||||||
cy.addComponent("Elements", "Paragraph").then(componentId => {
|
cy.addComponent("Elements", "Paragraph").then(componentId => {
|
||||||
addSettingBinding("text", `URL.${paramName}`)
|
addSettingBinding("text", `URL.${paramName}`)
|
||||||
// The builder preview pages don't have a real URL, so all we can do
|
// The builder preview pages don't have a real URL, so all we can do
|
||||||
|
|
|
@ -9,17 +9,33 @@ filterTests(["smoke", "all"], () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it("Should successfully create a screen", () => {
|
it("Should successfully create a screen", () => {
|
||||||
cy.createScreen("Test Screen", "/test")
|
cy.createScreen("/test")
|
||||||
cy.get(".nav-items-container").within(() => {
|
cy.get(".nav-items-container").within(() => {
|
||||||
cy.contains("/test").should("exist")
|
cy.contains("/test").should("exist")
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it("Should update the url", () => {
|
it("Should update the url", () => {
|
||||||
cy.createScreen("Test Screen", "test with spaces")
|
cy.createScreen("test with spaces")
|
||||||
cy.get(".nav-items-container").within(() => {
|
cy.get(".nav-items-container").within(() => {
|
||||||
cy.contains("/test-with-spaces").should("exist")
|
cy.contains("/test-with-spaces").should("exist")
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("Should create a blank screen with the selected access level", () => {
|
||||||
|
cy.createScreen("admin only", "Admin")
|
||||||
|
|
||||||
|
cy.get(".nav-items-container").within(() => {
|
||||||
|
cy.contains("/admin-only").should("exist")
|
||||||
|
})
|
||||||
|
|
||||||
|
cy.createScreen("open to all", "Public")
|
||||||
|
|
||||||
|
cy.get(".nav-items-container").within(() => {
|
||||||
|
cy.contains("/open-to-all").should("exist")
|
||||||
|
//The access level should now be set to admin. Previous screens should be filtered.
|
||||||
|
cy.get(".nav-item").contains("/test-screen").should("not.exist")
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -32,7 +32,17 @@ Cypress.Commands.add("login", () => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
Cypress.Commands.add("createApp", name => {
|
Cypress.Commands.add("closeModal", () => {
|
||||||
|
cy.get(".spectrum-Modal").within(() => {
|
||||||
|
cy.get(".close-icon").click()
|
||||||
|
cy.wait(500)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Cypress.Commands.add("createApp", (name, addDefaultTable) => {
|
||||||
|
const shouldCreateDefaultTable =
|
||||||
|
typeof addDefaultTable != "boolean" ? true : addDefaultTable
|
||||||
|
|
||||||
cy.visit(`${Cypress.config().baseUrl}/builder`)
|
cy.visit(`${Cypress.config().baseUrl}/builder`)
|
||||||
cy.wait(500)
|
cy.wait(500)
|
||||||
cy.get(`[data-cy="create-app-btn"]`).click({ force: true })
|
cy.get(`[data-cy="create-app-btn"]`).click({ force: true })
|
||||||
|
@ -51,7 +61,9 @@ Cypress.Commands.add("createApp", name => {
|
||||||
cy.get(".spectrum-ButtonGroup").contains("Create app").click()
|
cy.get(".spectrum-ButtonGroup").contains("Create app").click()
|
||||||
cy.wait(10000)
|
cy.wait(10000)
|
||||||
})
|
})
|
||||||
cy.createTable("Cypress Tests", true)
|
if (shouldCreateDefaultTable) {
|
||||||
|
cy.createTable("Cypress Tests", true)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
Cypress.Commands.add("deleteApp", name => {
|
Cypress.Commands.add("deleteApp", name => {
|
||||||
|
@ -135,7 +147,7 @@ Cypress.Commands.add("createTestApp", () => {
|
||||||
const appName = "Cypress Tests"
|
const appName = "Cypress Tests"
|
||||||
cy.deleteApp(appName)
|
cy.deleteApp(appName)
|
||||||
cy.createApp(appName, "This app is used for Cypress testing.")
|
cy.createApp(appName, "This app is used for Cypress testing.")
|
||||||
cy.createScreen("home", "home")
|
cy.createScreen("home")
|
||||||
})
|
})
|
||||||
|
|
||||||
Cypress.Commands.add("createTestTableWithData", () => {
|
Cypress.Commands.add("createTestTableWithData", () => {
|
||||||
|
@ -275,33 +287,99 @@ Cypress.Commands.add("navigateToDataSection", () => {
|
||||||
cy.contains("Data").click()
|
cy.contains("Data").click()
|
||||||
})
|
})
|
||||||
|
|
||||||
Cypress.Commands.add("createScreen", (screenName, route) => {
|
//Blank
|
||||||
|
Cypress.Commands.add("createScreen", (route, accessLevelLabel) => {
|
||||||
cy.contains("Design").click()
|
cy.contains("Design").click()
|
||||||
cy.get("[aria-label=AddCircle]").click()
|
cy.get("[aria-label=AddCircle]").click()
|
||||||
cy.get(".spectrum-Modal").within(() => {
|
cy.get(".spectrum-Modal").within(() => {
|
||||||
cy.get(".item").contains("Blank").click()
|
cy.get(".item").contains("Blank screen").click()
|
||||||
cy.get(".spectrum-Button").contains("Add screens").click({ force: true })
|
cy.get(".spectrum-Button").contains("Continue").click({ force: true })
|
||||||
cy.wait(500)
|
cy.wait(500)
|
||||||
})
|
})
|
||||||
cy.get(".spectrum-Dialog-grid").within(() => {
|
cy.get(".spectrum-Dialog-grid").within(() => {
|
||||||
cy.get(".spectrum-Form-itemField").eq(0).type(screenName)
|
cy.get(".spectrum-Form-itemField").eq(0).type(route)
|
||||||
cy.get(".spectrum-Form-itemField").eq(1).type(route)
|
|
||||||
cy.get(".spectrum-Button").contains("Continue").click({ force: true })
|
cy.get(".spectrum-Button").contains("Continue").click({ force: true })
|
||||||
cy.wait(1000)
|
cy.wait(1000)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
cy.get(".spectrum-Modal").within(() => {
|
||||||
|
if (accessLevelLabel) {
|
||||||
|
cy.get(".spectrum-Picker-label").click()
|
||||||
|
cy.wait(500)
|
||||||
|
cy.contains(accessLevelLabel).click()
|
||||||
|
}
|
||||||
|
cy.get(".spectrum-Button").contains("Done").click({ force: true })
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
Cypress.Commands.add("createAutogeneratedScreens", screenNames => {
|
Cypress.Commands.add(
|
||||||
|
"createDatasourceScreen",
|
||||||
|
(datasourceNames, accessLevelLabel) => {
|
||||||
|
cy.contains("Design").click()
|
||||||
|
cy.get("[aria-label=AddCircle]").click()
|
||||||
|
cy.get(".spectrum-Modal").within(() => {
|
||||||
|
cy.get(".item").contains("Autogenerated screens").click()
|
||||||
|
cy.get(".spectrum-Button").contains("Continue").click({ force: true })
|
||||||
|
cy.wait(500)
|
||||||
|
})
|
||||||
|
cy.get(".spectrum-Modal [data-cy='data-source-modal']").within(() => {
|
||||||
|
for (let i = 0; i < datasourceNames.length; i++) {
|
||||||
|
cy.get(".data-source-entry").contains(datasourceNames[i]).click()
|
||||||
|
//Ensure the check mark is visible
|
||||||
|
cy.get(".data-source-entry")
|
||||||
|
.contains(datasourceNames[i])
|
||||||
|
.get(".data-source-check")
|
||||||
|
.should("exist")
|
||||||
|
}
|
||||||
|
|
||||||
|
cy.get(".spectrum-Button").contains("Confirm").click({ force: true })
|
||||||
|
})
|
||||||
|
|
||||||
|
cy.get(".spectrum-Modal").within(() => {
|
||||||
|
if (accessLevelLabel) {
|
||||||
|
cy.get(".spectrum-Picker-label").click()
|
||||||
|
cy.wait(500)
|
||||||
|
cy.contains(accessLevelLabel).click()
|
||||||
|
}
|
||||||
|
cy.get(".spectrum-Button").contains("Done").click({ force: true })
|
||||||
|
})
|
||||||
|
|
||||||
|
cy.contains("Design").click()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
Cypress.Commands.add("navigateToAutogeneratedModal", () => {
|
||||||
// Screen name must already exist within data source
|
// Screen name must already exist within data source
|
||||||
cy.contains("Design").click()
|
cy.contains("Design").click()
|
||||||
cy.get("[aria-label=AddCircle]").click()
|
cy.get("[aria-label=AddCircle]").click()
|
||||||
for (let i = 0; i < screenNames.length; i++) {
|
cy.get(".spectrum-Modal").within(() => {
|
||||||
cy.get(".item").contains(screenNames[i]).click()
|
cy.get(".item").contains("Autogenerated screens").click()
|
||||||
}
|
cy.get(".spectrum-Button").contains("Continue").click({ force: true })
|
||||||
cy.get(".spectrum-Button").contains("Add screens").click({ force: true })
|
cy.wait(500)
|
||||||
cy.wait(4000)
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Cypress.Commands.add(
|
||||||
|
"createAutogeneratedScreens",
|
||||||
|
(screenNames, accessLevelLabel) => {
|
||||||
|
cy.navigateToAutogeneratedModal()
|
||||||
|
|
||||||
|
for (let i = 0; i < screenNames.length; i++) {
|
||||||
|
cy.get(".data-source-entry").contains(screenNames[i]).click()
|
||||||
|
}
|
||||||
|
|
||||||
|
cy.get(".spectrum-Modal").within(() => {
|
||||||
|
if (accessLevelLabel) {
|
||||||
|
cy.get(".spectrum-Picker-label").click()
|
||||||
|
cy.wait(500)
|
||||||
|
cy.contains(accessLevelLabel).click()
|
||||||
|
}
|
||||||
|
cy.get(".spectrum-Button").contains("Confirm").click({ force: true })
|
||||||
|
cy.wait(4000)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
Cypress.Commands.add("addRow", values => {
|
Cypress.Commands.add("addRow", values => {
|
||||||
cy.contains("Create row").click()
|
cy.contains("Create row").click()
|
||||||
cy.get(".spectrum-Modal").within(() => {
|
cy.get(".spectrum-Modal").within(() => {
|
||||||
|
|
|
@ -22,6 +22,7 @@ export const Events = {
|
||||||
},
|
},
|
||||||
SCREEN: {
|
SCREEN: {
|
||||||
CREATED: "Screen Created",
|
CREATED: "Screen Created",
|
||||||
|
CREATE_ROLE_UPDATED: "Changed Role On Screen Creation",
|
||||||
},
|
},
|
||||||
AUTOMATION: {
|
AUTOMATION: {
|
||||||
CREATED: "Automation Created",
|
CREATED: "Automation Created",
|
||||||
|
|
|
@ -0,0 +1,199 @@
|
||||||
|
<script>
|
||||||
|
import { store } from "builderStore"
|
||||||
|
import { ModalContent, Layout, notifications, Icon } from "@budibase/bbui"
|
||||||
|
import { tables, datasources } from "stores/backend"
|
||||||
|
import getTemplates from "builderStore/store/screenTemplates"
|
||||||
|
import ICONS from "../../backend/DatasourceNavigator/icons"
|
||||||
|
import { IntegrationNames } from "constants"
|
||||||
|
import { onMount } from "svelte"
|
||||||
|
|
||||||
|
export let onCancel
|
||||||
|
export let onConfirm
|
||||||
|
export let initalScreens = []
|
||||||
|
|
||||||
|
let selectedScreens = [...initalScreens]
|
||||||
|
|
||||||
|
const toggleScreenSelection = (table, datasource) => {
|
||||||
|
if (selectedScreens.find(s => s.table === table.name)) {
|
||||||
|
selectedScreens = selectedScreens.filter(
|
||||||
|
screen => screen.table !== table.name
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
let partialTemplates = getTemplates($store, $tables.list).reduce(
|
||||||
|
(acc, template) => {
|
||||||
|
if (template.table === table.name) {
|
||||||
|
template.datasource = datasource.name
|
||||||
|
acc.push(template)
|
||||||
|
}
|
||||||
|
return acc
|
||||||
|
},
|
||||||
|
[]
|
||||||
|
)
|
||||||
|
selectedScreens = [...partialTemplates, ...selectedScreens]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const confirmDatasourceSelection = async () => {
|
||||||
|
await onConfirm({
|
||||||
|
templates: selectedScreens,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
$: filteredSources = Array.isArray($datasources.list)
|
||||||
|
? $datasources.list.reduce((acc, datasource) => {
|
||||||
|
if (
|
||||||
|
datasource.source !== IntegrationNames.REST &&
|
||||||
|
datasource["entities"]
|
||||||
|
) {
|
||||||
|
acc.push(datasource)
|
||||||
|
}
|
||||||
|
return acc
|
||||||
|
}, [])
|
||||||
|
: []
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
try {
|
||||||
|
await datasources.fetch()
|
||||||
|
} catch (error) {
|
||||||
|
notifications.error("Error fetching datasources")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<span data-cy="data-source-modal">
|
||||||
|
<ModalContent
|
||||||
|
title="Create CRUD Screens"
|
||||||
|
confirmText="Confirm"
|
||||||
|
cancelText="Back"
|
||||||
|
onConfirm={confirmDatasourceSelection}
|
||||||
|
{onCancel}
|
||||||
|
disabled={!selectedScreens.length}
|
||||||
|
size="L"
|
||||||
|
>
|
||||||
|
<Layout noPadding gap="S">
|
||||||
|
{#each filteredSources as datasource}
|
||||||
|
<div class="data-source-wrap">
|
||||||
|
<div class="data-source-header">
|
||||||
|
<div class="datasource-icon">
|
||||||
|
<svelte:component
|
||||||
|
this={ICONS[datasource.source]}
|
||||||
|
height="24"
|
||||||
|
width="24"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="data-source-name">{datasource.name}</div>
|
||||||
|
</div>
|
||||||
|
{#if Array.isArray(datasource.entities)}
|
||||||
|
{#each datasource.entities.filter(table => table._id !== "ta_users") as table}
|
||||||
|
<div
|
||||||
|
class="data-source-entry"
|
||||||
|
class:selected={selectedScreens.find(
|
||||||
|
x => x.table === table.name
|
||||||
|
)}
|
||||||
|
on:click={() => toggleScreenSelection(table, datasource)}
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
width="16px"
|
||||||
|
height="16px"
|
||||||
|
class="spectrum-Icon"
|
||||||
|
style="color: white"
|
||||||
|
focusable="false"
|
||||||
|
>
|
||||||
|
<use xlink:href="#spectrum-icon-18-Table" />
|
||||||
|
</svg>
|
||||||
|
{table.name}
|
||||||
|
|
||||||
|
{#if selectedScreens.find(x => x.table === table.name)}
|
||||||
|
<span class="data-source-check">
|
||||||
|
<Icon size="S" name="CheckmarkCircle" />
|
||||||
|
</span>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
{/if}
|
||||||
|
{#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].name
|
||||||
|
)}
|
||||||
|
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].name)}
|
||||||
|
<span class="data-source-check">
|
||||||
|
<Icon size="S" name="CheckmarkCircle" />
|
||||||
|
</span>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
</Layout>
|
||||||
|
</ModalContent>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.data-source-wrap {
|
||||||
|
padding-bottom: var(--spectrum-alias-item-padding-s);
|
||||||
|
display: grid;
|
||||||
|
grid-gap: var(--spacing-xs);
|
||||||
|
}
|
||||||
|
|
||||||
|
.data-source-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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-primary);
|
||||||
|
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-name {
|
||||||
|
padding: var(--spectrum-alias-item-padding-s);
|
||||||
|
min-height: var(--spectrum-icon-size-s);
|
||||||
|
}
|
||||||
|
|
||||||
|
.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>
|
|
@ -1,117 +1,98 @@
|
||||||
<script>
|
<script>
|
||||||
import { store } from "builderStore"
|
|
||||||
import { tables } from "stores/backend"
|
import { tables } from "stores/backend"
|
||||||
import {
|
import { ModalContent, Body, Layout, Icon, Heading } from "@budibase/bbui"
|
||||||
ModalContent,
|
|
||||||
Body,
|
|
||||||
Detail,
|
|
||||||
Layout,
|
|
||||||
Icon,
|
|
||||||
ProgressCircle,
|
|
||||||
} from "@budibase/bbui"
|
|
||||||
import getTemplates from "builderStore/store/screenTemplates"
|
|
||||||
|
|
||||||
export let onConfirm
|
export let onConfirm
|
||||||
export let onCancel
|
export let onCancel
|
||||||
export let showProgressCircle = false
|
|
||||||
|
|
||||||
const blankScreen = "createFromScratch"
|
let autoCreateModeKey = "autoCreate"
|
||||||
|
let blankScreenModeKey = "blankScreen"
|
||||||
|
|
||||||
let selectedScreens = []
|
let selectedScreenMode
|
||||||
let templates = getTemplates($store, $tables.list)
|
|
||||||
|
|
||||||
$: blankSelected = selectedScreens?.length === 1
|
|
||||||
$: autoSelected = selectedScreens?.length > 0 && !blankSelected
|
|
||||||
|
|
||||||
const toggleScreenSelection = table => {
|
|
||||||
if (selectedScreens.find(s => s.table === table.name)) {
|
|
||||||
selectedScreens = selectedScreens.filter(
|
|
||||||
screen => screen.table !== table.name
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
let partialTemplates = getTemplates($store, $tables.list).filter(
|
|
||||||
template => template.table === table.name
|
|
||||||
)
|
|
||||||
selectedScreens = [...partialTemplates, ...selectedScreens]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const confirmScreenSelection = async () => {
|
const confirmScreenSelection = async () => {
|
||||||
await onConfirm(selectedScreens)
|
await onConfirm(selectedScreenMode)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<ModalContent
|
<ModalContent
|
||||||
title="Add screens"
|
title="Add screens"
|
||||||
confirmText="Add screens"
|
confirmText="Continue"
|
||||||
cancelText="Cancel"
|
cancelText="Cancel"
|
||||||
onConfirm={confirmScreenSelection}
|
onConfirm={confirmScreenSelection}
|
||||||
{onCancel}
|
{onCancel}
|
||||||
disabled={!selectedScreens.length}
|
disabled={!selectedScreenMode}
|
||||||
size="L"
|
size="L"
|
||||||
>
|
>
|
||||||
<Body size="S">
|
|
||||||
Please select the screens you would like to add to your application.
|
|
||||||
Autogenerated screens come with CRUD functionality.
|
|
||||||
</Body>
|
|
||||||
<Layout noPadding gap="S">
|
<Layout noPadding gap="S">
|
||||||
<Detail size="S">Blank screen</Detail>
|
|
||||||
<div
|
<div
|
||||||
class="item"
|
class="screen-type item"
|
||||||
class:selected={selectedScreens.find(x => x.id.includes(blankScreen))}
|
class:selected={selectedScreenMode == blankScreenModeKey}
|
||||||
on:click={() =>
|
on:click={() => {
|
||||||
toggleScreenSelection(templates.find(t => t.id === blankScreen))}
|
selectedScreenMode = blankScreenModeKey
|
||||||
class:disabled={autoSelected}
|
}}
|
||||||
>
|
>
|
||||||
<div data-cy="blank-screen" class="content">
|
<div data-cy="blank-screen" class="content screen-type-wrap">
|
||||||
<div class="text">Blank</div>
|
<Icon name="WebPage" />
|
||||||
|
<div class="screen-type-text">
|
||||||
|
<Heading size="XS">Blank screen</Heading>
|
||||||
|
<Body size="S">Add a blank screen</Body>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
style="color: var(--spectrum-global-color-green-600); float: right"
|
style="color: var(--spectrum-global-color-green-600); float: right"
|
||||||
>
|
>
|
||||||
{#if selectedScreens.find(x => x.id === blankScreen)}
|
{#if selectedScreenMode == blankScreenModeKey}
|
||||||
<div class="checkmark-spacing">
|
<div class="checkmark-spacing">
|
||||||
<Icon size="S" name="CheckmarkCircleOutline" />
|
<Icon size="S" name="CheckmarkCircle" />
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{#if $tables.list.filter(table => table._id !== "ta_users").length > 0}
|
|
||||||
<Detail size="S">Autogenerated Screens</Detail>
|
|
||||||
|
|
||||||
{#each $tables.list.filter(table => table._id !== "ta_users") as table}
|
<div
|
||||||
<div
|
class="screen-type item"
|
||||||
class:disabled={blankSelected}
|
class:selected={selectedScreenMode == autoCreateModeKey}
|
||||||
class:selected={selectedScreens.find(x => x.table === table.name)}
|
on:click={() => {
|
||||||
on:click={() => toggleScreenSelection(table)}
|
selectedScreenMode = autoCreateModeKey
|
||||||
class="item"
|
}}
|
||||||
>
|
class:disabled={!$tables.list.filter(table => table._id !== "ta_users")
|
||||||
<div class="content">
|
.length}
|
||||||
<div class="text">{table.name}</div>
|
>
|
||||||
</div>
|
<div data-cy="autogenerated-screens" class="content screen-type-wrap">
|
||||||
<div
|
<Icon name="WebPages" />
|
||||||
style="color: var(--spectrum-global-color-green-600); float: right"
|
<div class="screen-type-text">
|
||||||
>
|
<Heading size="XS">Autogenerated screens</Heading>
|
||||||
{#if selectedScreens.find(x => x.table === table.name)}
|
<Body size="S">
|
||||||
<div class="checkmark-spacing">
|
Add autogenerated screens with CRUD functionality to get a working
|
||||||
<Icon size="S" name="CheckmarkCircleOutline" />
|
app quickly! (Requires a data source)
|
||||||
</div>
|
</Body>
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
</div>
|
||||||
{/if}
|
<div
|
||||||
|
style="color: var(--spectrum-global-color-green-600); float: right"
|
||||||
|
>
|
||||||
|
{#if selectedScreenMode == autoCreateModeKey}
|
||||||
|
<div class="checkmark-spacing">
|
||||||
|
<Icon size="S" name="CheckmarkCircle" />
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</Layout>
|
</Layout>
|
||||||
<div slot="footer">
|
|
||||||
{#if showProgressCircle}
|
|
||||||
<div class="footer-progress"><ProgressCircle size="S" /></div>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
</ModalContent>
|
</ModalContent>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
.screen-type.item {
|
||||||
|
padding: var(--spectrum-alias-item-padding-xl);
|
||||||
|
}
|
||||||
|
.screen-type-wrap {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
.disabled {
|
.disabled {
|
||||||
opacity: 0.3;
|
opacity: 0.3;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
@ -119,22 +100,9 @@
|
||||||
.checkmark-spacing {
|
.checkmark-spacing {
|
||||||
margin-right: var(--spacing-m);
|
margin-right: var(--spacing-m);
|
||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
letter-spacing: 0px;
|
letter-spacing: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer-progress {
|
|
||||||
margin-top: var(--spacing-s);
|
|
||||||
}
|
|
||||||
|
|
||||||
.text {
|
|
||||||
font-weight: 600;
|
|
||||||
margin-left: var(--spacing-m);
|
|
||||||
font-size: 14px;
|
|
||||||
text-transform: capitalize;
|
|
||||||
}
|
|
||||||
|
|
||||||
.item {
|
.item {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
grid-gap: var(--spectrum-alias-grid-margin-xsmall);
|
grid-gap: var(--spectrum-alias-grid-margin-xsmall);
|
||||||
|
@ -143,16 +111,22 @@
|
||||||
transition: 0.3s all;
|
transition: 0.3s all;
|
||||||
border: 1px solid var(--spectrum-global-color-gray-300);
|
border: 1px solid var(--spectrum-global-color-gray-300);
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
box-sizing: border-box;
|
|
||||||
border-width: 1px;
|
border-width: 1px;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
height: 60px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.item:hover,
|
.item:hover,
|
||||||
.selected {
|
.selected {
|
||||||
background: var(--spectrum-alias-background-color-tertiary);
|
background: var(--spectrum-alias-background-color-tertiary);
|
||||||
}
|
}
|
||||||
|
.screen-type-wrap .screen-type-text {
|
||||||
|
padding-left: var(--spectrum-alias-item-padding-xl);
|
||||||
|
}
|
||||||
|
.screen-type-wrap :global(.spectrum-Icon) {
|
||||||
|
min-width: var(--spectrum-icon-size-m);
|
||||||
|
}
|
||||||
|
.screen-type-wrap :global(.spectrum-Heading) {
|
||||||
|
padding-bottom: var(--spectrum-alias-item-padding-s);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,18 +1,23 @@
|
||||||
<script>
|
<script>
|
||||||
import { ModalContent, Input, ProgressCircle } from "@budibase/bbui"
|
import { ModalContent, Input } from "@budibase/bbui"
|
||||||
import sanitizeUrl from "builderStore/store/screenTemplates/utils/sanitizeUrl"
|
import sanitizeUrl from "builderStore/store/screenTemplates/utils/sanitizeUrl"
|
||||||
import { selectedAccessRole, allScreens } from "builderStore"
|
import { selectedAccessRole, allScreens } from "builderStore"
|
||||||
import { get } from "svelte/store"
|
import { get } from "svelte/store"
|
||||||
|
|
||||||
export let onConfirm
|
export let onConfirm
|
||||||
export let onCancel
|
export let onCancel
|
||||||
export let showProgressCircle = false
|
|
||||||
export let screenName
|
|
||||||
export let screenUrl
|
export let screenUrl
|
||||||
export let confirmText = "Continue"
|
export let confirmText = "Continue"
|
||||||
|
|
||||||
let routeError
|
let routeError
|
||||||
let touched = false
|
let touched = false
|
||||||
|
let screenAccessRole = $selectedAccessRole + ""
|
||||||
|
|
||||||
|
const appPrefix = "/app"
|
||||||
|
|
||||||
|
$: appUrl = screenUrl
|
||||||
|
? `${window.location.origin}${appPrefix}${screenUrl}`
|
||||||
|
: `${window.location.origin}${appPrefix}`
|
||||||
|
|
||||||
const routeChanged = event => {
|
const routeChanged = event => {
|
||||||
if (!event.detail.startsWith("/")) {
|
if (!event.detail.startsWith("/")) {
|
||||||
|
@ -38,7 +43,6 @@
|
||||||
|
|
||||||
const confirmScreenDetails = async () => {
|
const confirmScreenDetails = async () => {
|
||||||
await onConfirm({
|
await onConfirm({
|
||||||
screenName,
|
|
||||||
screenUrl,
|
screenUrl,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -51,24 +55,25 @@
|
||||||
onConfirm={confirmScreenDetails}
|
onConfirm={confirmScreenDetails}
|
||||||
{onCancel}
|
{onCancel}
|
||||||
cancelText={"Back"}
|
cancelText={"Back"}
|
||||||
disabled={!screenName || !screenUrl || routeError || !touched}
|
disabled={!screenAccessRole || !screenUrl || routeError || !touched}
|
||||||
>
|
>
|
||||||
<Input label="Name" bind:value={screenName} />
|
|
||||||
<Input
|
<Input
|
||||||
label="URL"
|
label="Enter a URL for the new screen"
|
||||||
error={routeError}
|
error={routeError}
|
||||||
bind:value={screenUrl}
|
bind:value={screenUrl}
|
||||||
on:change={routeChanged}
|
on:change={routeChanged}
|
||||||
/>
|
/>
|
||||||
<div slot="footer">
|
<div class="app-server" title={appUrl}>
|
||||||
{#if showProgressCircle}
|
{appUrl}
|
||||||
<div class="footer-progress"><ProgressCircle size="S" /></div>
|
|
||||||
{/if}
|
|
||||||
</div>
|
</div>
|
||||||
</ModalContent>
|
</ModalContent>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.footer-progress {
|
.app-server {
|
||||||
margin-top: var(--spacing-s);
|
color: var(--spectrum-global-color-gray-600);
|
||||||
|
width: 320px;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,34 +1,46 @@
|
||||||
<script>
|
<script>
|
||||||
import ScreenDetailsModal from "components/design/NavigationPanel/ScreenDetailsModal.svelte"
|
import ScreenDetailsModal from "components/design/NavigationPanel/ScreenDetailsModal.svelte"
|
||||||
import NewScreenModal from "components/design/NavigationPanel/NewScreenModal.svelte"
|
import NewScreenModal from "components/design/NavigationPanel/NewScreenModal.svelte"
|
||||||
|
import DatasourceModal from "components/design/NavigationPanel/DatasourceModal.svelte"
|
||||||
import sanitizeUrl from "builderStore/store/screenTemplates/utils/sanitizeUrl"
|
import sanitizeUrl from "builderStore/store/screenTemplates/utils/sanitizeUrl"
|
||||||
import { Modal, notifications } from "@budibase/bbui"
|
import { Modal, ModalContent, Select, notifications } from "@budibase/bbui"
|
||||||
import { store, selectedAccessRole } from "builderStore"
|
import { store, selectedAccessRole } from "builderStore"
|
||||||
import analytics, { Events } from "analytics"
|
import analytics, { Events } from "analytics"
|
||||||
import { get } from "svelte/store"
|
import { get } from "svelte/store"
|
||||||
|
import getTemplates from "builderStore/store/screenTemplates"
|
||||||
|
import { tables, roles } from "stores/backend"
|
||||||
|
|
||||||
let pendingScreen
|
let pendingScreen
|
||||||
let showProgressCircle = false
|
|
||||||
|
|
||||||
// Modal refs
|
// Modal refs
|
||||||
let newScreenModal
|
let newScreenModal
|
||||||
let screenDetailsModal
|
let screenDetailsModal
|
||||||
|
let datasourceModal
|
||||||
|
let screenAccessRoleModal
|
||||||
|
|
||||||
|
// Cache variables for workflow
|
||||||
|
let screenAccessRole = $selectedAccessRole + ""
|
||||||
|
let selectedTemplates = null
|
||||||
|
let blankScreenUrl = null
|
||||||
|
|
||||||
|
let screenMode = null
|
||||||
|
|
||||||
// External handler to show the screen wizard
|
// External handler to show the screen wizard
|
||||||
export const showModal = () => {
|
export const showModal = () => {
|
||||||
newScreenModal.show()
|
selectedTemplates = null
|
||||||
|
blankScreenUrl = null
|
||||||
|
screenMode = null
|
||||||
|
|
||||||
|
newScreenModal.show()
|
||||||
// Reset state when showing modal again
|
// Reset state when showing modal again
|
||||||
pendingScreen = null
|
pendingScreen = null
|
||||||
showProgressCircle = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates an array of screens, checking and sanitising their URLs
|
// Creates an array of screens, checking and sanitising their URLs
|
||||||
const createScreens = async screens => {
|
const createScreens = async ({ screens, screenAccessRole }) => {
|
||||||
if (!screens?.length) {
|
if (!screens?.length) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
showProgressCircle = true
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
for (let screen of screens) {
|
for (let screen of screens) {
|
||||||
|
@ -46,7 +58,9 @@
|
||||||
screen.routing.route = sanitizeUrl(screen.routing.route)
|
screen.routing.route = sanitizeUrl(screen.routing.route)
|
||||||
|
|
||||||
// Use the currently selected role
|
// Use the currently selected role
|
||||||
screen.routing.roleId = get(selectedAccessRole) || "BASIC"
|
screen.routing.roleId = screenAccessRole
|
||||||
|
? screenAccessRole
|
||||||
|
: get(selectedAccessRole) || "BASIC"
|
||||||
|
|
||||||
// Create the screen
|
// Create the screen
|
||||||
await store.actions.screens.save(screen)
|
await store.actions.screens.save(screen)
|
||||||
|
@ -55,6 +69,8 @@
|
||||||
if (screen.template) {
|
if (screen.template) {
|
||||||
analytics.captureEvent(Events.SCREEN.CREATED, {
|
analytics.captureEvent(Events.SCREEN.CREATED, {
|
||||||
template: screen.template,
|
template: screen.template,
|
||||||
|
datasource: screen.datasource,
|
||||||
|
screenAccessRole,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,8 +85,6 @@
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
notifications.error("Error creating screens")
|
notifications.error("Error creating screens")
|
||||||
}
|
}
|
||||||
|
|
||||||
showProgressCircle = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks if any screens exist in the store with the given route and
|
// Checks if any screens exist in the store with the given route and
|
||||||
|
@ -98,38 +112,120 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handler for NewScreenModal
|
// Handler for NewScreenModal
|
||||||
const confirmScreenSelection = async templates => {
|
const confirmScreenSelection = async mode => {
|
||||||
// Handle template selection
|
screenMode = mode
|
||||||
if (templates?.length > 1) {
|
|
||||||
// Autoscreens, so create immediately
|
if (mode == "autoCreate") {
|
||||||
const screens = templates.map(template => template.create())
|
datasourceModal.show()
|
||||||
await createScreens(screens)
|
|
||||||
} else {
|
} else {
|
||||||
// Empty screen, so proceed to the next modal
|
let templates = getTemplates($store, $tables.list)
|
||||||
pendingScreen = templates[0].create()
|
const blankScreenTemplate = templates.find(
|
||||||
|
t => t.id === "createFromScratch"
|
||||||
|
)
|
||||||
|
pendingScreen = blankScreenTemplate.create()
|
||||||
screenDetailsModal.show()
|
screenDetailsModal.show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handler for ScreenDetailsModal
|
// Handler for DatasourceModal confirmation, move to screen access select
|
||||||
const confirmScreenDetails = async ({ screenName, screenUrl }) => {
|
const confirmScreenDatasources = async ({ templates }) => {
|
||||||
|
selectedTemplates = templates
|
||||||
|
screenAccessRoleModal.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handler for Datasource Screen Creation
|
||||||
|
const completeDatasourceScreenCreation = async () => {
|
||||||
|
// // Handle template selection
|
||||||
|
if (selectedTemplates?.length > 1) {
|
||||||
|
// Autoscreens, so create immediately
|
||||||
|
const screens = selectedTemplates.map(template => {
|
||||||
|
let screenTemplate = template.create()
|
||||||
|
screenTemplate.datasource = template.datasource
|
||||||
|
return screenTemplate
|
||||||
|
})
|
||||||
|
await createScreens({ screens, screenAccessRole })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const confirmScreenBlank = async ({ screenUrl }) => {
|
||||||
|
blankScreenUrl = screenUrl
|
||||||
|
screenAccessRoleModal.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Submit request for a blank screen
|
||||||
|
const confirmBlankScreenCreation = async ({
|
||||||
|
screenUrl,
|
||||||
|
screenAccessRole,
|
||||||
|
}) => {
|
||||||
if (!pendingScreen) {
|
if (!pendingScreen) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
pendingScreen.props._instanceName = screenName
|
|
||||||
pendingScreen.routing.route = screenUrl
|
pendingScreen.routing.route = screenUrl
|
||||||
await createScreens([pendingScreen])
|
await createScreens({ screens: [pendingScreen], screenAccessRole })
|
||||||
|
}
|
||||||
|
|
||||||
|
// Submit screen config for creation.
|
||||||
|
const confirmScreenCreation = async () => {
|
||||||
|
if (screenMode === "blankScreen") {
|
||||||
|
confirmBlankScreenCreation({
|
||||||
|
screenUrl: blankScreenUrl,
|
||||||
|
screenAccessRole,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
completeDatasourceScreenCreation()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const roleSelectBack = () => {
|
||||||
|
if (screenMode === "blankScreen") {
|
||||||
|
screenDetailsModal.show()
|
||||||
|
} else {
|
||||||
|
datasourceModal.show()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Modal bind:this={newScreenModal}>
|
<Modal bind:this={newScreenModal}>
|
||||||
<NewScreenModal onConfirm={confirmScreenSelection} {showProgressCircle} />
|
<NewScreenModal onConfirm={confirmScreenSelection} />
|
||||||
|
</Modal>
|
||||||
|
|
||||||
|
<Modal bind:this={datasourceModal}>
|
||||||
|
<DatasourceModal
|
||||||
|
onConfirm={confirmScreenDatasources}
|
||||||
|
onCancel={() => newScreenModal.show()}
|
||||||
|
initalScreens={!selectedTemplates ? [] : [...selectedTemplates]}
|
||||||
|
/>
|
||||||
|
</Modal>
|
||||||
|
|
||||||
|
<Modal bind:this={screenAccessRoleModal}>
|
||||||
|
<ModalContent
|
||||||
|
title={"Create CRUD Screens"}
|
||||||
|
confirmText={"Done"}
|
||||||
|
cancelText={"Back"}
|
||||||
|
onConfirm={confirmScreenCreation}
|
||||||
|
onCancel={roleSelectBack}
|
||||||
|
>
|
||||||
|
Select which level of access you want your screens to have
|
||||||
|
<Select
|
||||||
|
bind:value={screenAccessRole}
|
||||||
|
on:change={() => {
|
||||||
|
analytics.captureEvent(Events.SCREEN.CREATE_ROLE_UPDATED, {
|
||||||
|
screenAccessRole,
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
label="Access"
|
||||||
|
getOptionLabel={role => role.name}
|
||||||
|
getOptionValue={role => role._id}
|
||||||
|
getOptionColor={role => role.color}
|
||||||
|
options={$roles}
|
||||||
|
/>
|
||||||
|
</ModalContent>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
<Modal bind:this={screenDetailsModal}>
|
<Modal bind:this={screenDetailsModal}>
|
||||||
<ScreenDetailsModal
|
<ScreenDetailsModal
|
||||||
{showProgressCircle}
|
onConfirm={confirmScreenBlank}
|
||||||
onConfirm={confirmScreenDetails}
|
|
||||||
onCancel={() => newScreenModal.show()}
|
onCancel={() => newScreenModal.show()}
|
||||||
|
initialUrl={blankScreenUrl}
|
||||||
/>
|
/>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
Loading…
Reference in a new issue