mirror of https://github.com/Budibase/budibase.git
committed by
GitHub
9 changed files with 612 additions and 191 deletions
@ -1,51 +1,103 @@ |
|||
import filterTests from "../support/filterTests" |
|||
|
|||
filterTests(['smoke', 'all'], () => { |
|||
context("Auto Screens UI", () => { |
|||
before(() => { |
|||
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') |
|||
}) |
|||
} |
|||
context("Auto Screens UI", () => { |
|||
before(() => { |
|||
cy.login() |
|||
}) |
|||
|
|||
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') |
|||
}) |
|||
} |
|||
}) |
|||
}) |
|||
|
|||
@ -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