forked from tsai/budibase
committed by
GitHub
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 disable the autogenerated screen options if no sources are available", () => { |
||||
it("should generate internal table screens", () => { |
cy.createApp("First Test App", false) |
||||
// Create autogenerated screens from the internal table
|
|
||||
cy.createAutogeneratedScreens(["Cypress Tests"]) |
cy.closeModal(); |
||||
// Confirm screens have been auto generated
|
|
||||
cy.get(".nav-items-container").contains("cypress-tests").click({ force: true }) |
cy.contains("Design").click() |
||||
cy.get(".nav-items-container").should('contain', 'cypress-tests/:id') |
cy.get("[aria-label=AddCircle]").click() |
||||
.and('contain', 'cypress-tests/new/row') |
cy.get(".spectrum-Modal").within(() => { |
||||
}) |
cy.get(".item.disabled").contains("Autogenerated screens") |
||||
|
cy.get(".confirm-wrap .spectrum-Button").should('be.disabled') |
||||
it("should generate multiple internal table screens at once", () => { |
}) |
||||
// Create a second internal table
|
|
||||
const initialTable = "Cypress Tests" |
cy.deleteAllApps() |
||||
const secondTable = "Table Two" |
}); |
||||
cy.createTable(secondTable) |
|
||||
// Create autogenerated screens from the internal tables
|
it("should not display incompatible sources", () => { |
||||
cy.createAutogeneratedScreens([initialTable, secondTable]) |
cy.createApp("Test App") |
||||
// Confirm screens have been auto generated
|
|
||||
cy.get(".nav-items-container").contains("cypress-tests").click({ force: true }) |
cy.selectExternalDatasource("REST") |
||||
// Previously generated tables are suffixed with numbers - as expected
|
cy.selectExternalDatasource("S3") |
||||
cy.get(".nav-items-container").should('contain', 'cypress-tests-2/:id') |
cy.get(".spectrum-Modal").within(() => { |
||||
.and('contain', 'cypress-tests-2/new/row') |
cy.get(".spectrum-Button").contains("Save and continue to query").click({ force : true }) |
||||
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') |
cy.navigateToAutogeneratedModal() |
||||
}) |
|
||||
|
cy.get('.data-source-entry').should('have.length', 1) |
||||
if (Cypress.env("TEST_ENV")) { |
cy.get('.data-source-entry') |
||||
it("should generate data source screens", () => { |
|
||||
// Using MySQL data source for testing this
|
cy.deleteAllApps() |
||||
const datasource = "MySQL" |
}); |
||||
// Select & configure MySQL data source
|
|
||||
cy.selectExternalDatasource(datasource) |
it("should generate internal table screens", () => { |
||||
cy.addDatasourceConfig(datasource) |
cy.createTestApp() |
||||
// Create autogenerated screens from a MySQL table - MySQL contains books table
|
// Create Autogenerated screens from the internal table
|
||||
cy.createAutogeneratedScreens(["books"]) |
cy.createDatasourceScreen(["Cypress Tests"]) |
||||
cy.get(".nav-items-container").contains("books").click() |
// Confirm screens have been auto generated
|
||||
cy.get(".nav-items-container").should('contain', 'books/:id') |
cy.get(".nav-items-container").contains("cypress-tests").click({ force: true }) |
||||
.and('contain', 'books/new/row') |
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') |
||||
|
}) |
||||
|
} |
||||
|
}) |
||||
}) |
}) |
||||
|
|||||
@ -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> |
||||
Loading…
Reference in new issue