Refactored the screen wizard to separate out the role selection. Design and layout updates to address feedback
This commit is contained in:
parent
e0ebd08cf6
commit
d601ec47f4
|
@ -288,7 +288,7 @@ Cypress.Commands.add("createScreen", (screenName, route, accessLevelLabel) => {
|
|||
cy.get("[aria-label=AddCircle]").click()
|
||||
cy.get(".spectrum-Modal").within(() => {
|
||||
cy.get(".item").contains("Blank").click()
|
||||
cy.get(".spectrum-Button").contains("Add screens").click({ force: true })
|
||||
cy.get(".spectrum-Button").contains("Continue").click({ force: true })
|
||||
cy.wait(500)
|
||||
})
|
||||
cy.get(".spectrum-Dialog-grid").within(() => {
|
||||
|
@ -311,7 +311,7 @@ Cypress.Commands.add("navigateToAutogeneratedModal", () => {
|
|||
cy.get("[aria-label=AddCircle]").click()
|
||||
cy.get(".spectrum-Modal").within(() => {
|
||||
cy.get(".item").contains("Autogenerated Screens").click()
|
||||
cy.get(".spectrum-Button").contains("Add screens").click({ force: true })
|
||||
cy.get(".spectrum-Button").contains("Continue").click({ force: true })
|
||||
cy.wait(500)
|
||||
})
|
||||
})
|
||||
|
|
|
@ -1,24 +1,17 @@
|
|||
<script>
|
||||
import { store, selectedAccessRole } from "builderStore"
|
||||
import {
|
||||
ModalContent,
|
||||
Layout,
|
||||
Select,
|
||||
Divider,
|
||||
notifications,
|
||||
} from "@budibase/bbui"
|
||||
import { tables, datasources, roles } from "stores/backend"
|
||||
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 analytics, { Events } from "analytics"
|
||||
import { onMount } from "svelte"
|
||||
|
||||
export let onCancel
|
||||
export let onConfirm
|
||||
export let initalScreens = []
|
||||
|
||||
let selectedScreens = []
|
||||
let screenAccessRole = $selectedAccessRole + ""
|
||||
let selectedScreens = [...initalScreens]
|
||||
|
||||
const toggleScreenSelection = (table, datasource) => {
|
||||
if (selectedScreens.find(s => s.table === table.name)) {
|
||||
|
@ -43,7 +36,6 @@
|
|||
const confirmDatasourceSelection = async () => {
|
||||
await onConfirm({
|
||||
templates: selectedScreens,
|
||||
screenAccessRole,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -77,93 +69,94 @@
|
|||
disabled={!selectedScreens.length}
|
||||
size="L"
|
||||
>
|
||||
<Layout noPadding gap="XS">
|
||||
<Layout noPadding gap="S">
|
||||
{#each filteredSources as datasource}
|
||||
<div class="data-source-header">
|
||||
<div class="datasource-icon">
|
||||
<svelte:component
|
||||
this={ICONS[datasource.source]}
|
||||
height="24"
|
||||
width="24"
|
||||
/>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="text">{datasource.name}</div>
|
||||
<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>
|
||||
{#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}
|
||||
</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}
|
||||
</div>
|
||||
{/each}
|
||||
{/if}
|
||||
{/each}
|
||||
<div>
|
||||
<Divider size="S" />
|
||||
</div>
|
||||
<Select
|
||||
bind:value={screenAccessRole}
|
||||
on:change={() => {
|
||||
analytics.captureEvent(Events.SCREEN.CREATE_ROLE_UPDATED, {
|
||||
screenAccessRole,
|
||||
})
|
||||
}}
|
||||
label="Screen access"
|
||||
getOptionLabel={role => role.name}
|
||||
getOptionValue={role => role._id}
|
||||
getOptionColor={role => role.color}
|
||||
options={$roles}
|
||||
/>
|
||||
</Layout>
|
||||
</ModalContent>
|
||||
|
||||
<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-header .content {
|
||||
padding: var(--spectrum-alias-item-padding-l);
|
||||
}
|
||||
|
||||
.data-source-entry {
|
||||
cursor: pointer;
|
||||
grid-gap: var(--spectrum-alias-grid-margin-xsmall);
|
||||
|
@ -172,7 +165,6 @@
|
|||
transition: 0.3s all;
|
||||
border: 1px solid var(--spectrum-global-color-gray-300);
|
||||
border-radius: 4px;
|
||||
box-sizing: border-box;
|
||||
border-width: 1px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
@ -182,4 +174,22 @@
|
|||
.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,6 +1,6 @@
|
|||
<script>
|
||||
import { tables } from "stores/backend"
|
||||
import { ModalContent, Body, Layout, Icon } from "@budibase/bbui"
|
||||
import { ModalContent, Body, Layout, Icon, Heading } from "@budibase/bbui"
|
||||
|
||||
export let onConfirm
|
||||
export let onCancel
|
||||
|
@ -18,14 +18,13 @@
|
|||
<div>
|
||||
<ModalContent
|
||||
title="Add screens"
|
||||
confirmText="Add screens"
|
||||
confirmText="Continue"
|
||||
cancelText="Cancel"
|
||||
onConfirm={confirmScreenSelection}
|
||||
{onCancel}
|
||||
disabled={!selectedScreenMode}
|
||||
size="L"
|
||||
>
|
||||
<Body size="S">Add a blank screen</Body>
|
||||
<Layout noPadding gap="S">
|
||||
<div
|
||||
class="screen-type item"
|
||||
|
@ -36,7 +35,10 @@
|
|||
>
|
||||
<div data-cy="blank-screen" class="content screen-type-wrap">
|
||||
<Icon name="WebPage" />
|
||||
<span class="text">Blank</span>
|
||||
<div class="screen-type-text">
|
||||
<Heading size="XS">Blank screen</Heading>
|
||||
<Body size="S">Add a blank screen</Body>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
style="color: var(--spectrum-global-color-green-600); float: right"
|
||||
|
@ -49,11 +51,6 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<Body size="S">
|
||||
Add autogenerated screens with CRUD functionality to get a working app
|
||||
quickly! (Requires a data source)
|
||||
</Body>
|
||||
|
||||
<div
|
||||
class="screen-type item"
|
||||
class:selected={selectedScreenMode == autoCreateModeKey}
|
||||
|
@ -65,7 +62,13 @@
|
|||
>
|
||||
<div data-cy="autogenerated-screens" class="content screen-type-wrap">
|
||||
<Icon name="WebPages" />
|
||||
<span class="text">Autogenerated Screens</span>
|
||||
<div class="screen-type-text">
|
||||
<Heading size="XS">Autogenerated Screens</Heading>
|
||||
<Body size="S">
|
||||
Add autogenerated screens with CRUD functionality to get a working
|
||||
app quickly! (Requires a data source)
|
||||
</Body>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
style="color: var(--spectrum-global-color-green-600); float: right"
|
||||
|
@ -100,12 +103,6 @@
|
|||
.content {
|
||||
letter-spacing: 0px;
|
||||
}
|
||||
.text {
|
||||
font-weight: 600;
|
||||
margin-left: var(--spacing-m);
|
||||
font-size: 14px;
|
||||
text-transform: capitalize;
|
||||
}
|
||||
.item {
|
||||
cursor: pointer;
|
||||
grid-gap: var(--spectrum-alias-grid-margin-xsmall);
|
||||
|
@ -114,15 +111,22 @@
|
|||
transition: 0.3s all;
|
||||
border: 1px solid var(--spectrum-global-color-gray-300);
|
||||
border-radius: 4px;
|
||||
box-sizing: border-box;
|
||||
border-width: 1px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
height: 60px;
|
||||
}
|
||||
.item:hover,
|
||||
.selected {
|
||||
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>
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
<script>
|
||||
import { ModalContent, Input, Select } from "@budibase/bbui"
|
||||
import { ModalContent, Input } from "@budibase/bbui"
|
||||
import sanitizeUrl from "builderStore/store/screenTemplates/utils/sanitizeUrl"
|
||||
import { selectedAccessRole, allScreens } from "builderStore"
|
||||
import { get } from "svelte/store"
|
||||
import { roles } from "stores/backend"
|
||||
import analytics, { Events } from "analytics"
|
||||
|
||||
export let onConfirm
|
||||
export let onCancel
|
||||
|
@ -40,7 +38,6 @@
|
|||
const confirmScreenDetails = async () => {
|
||||
await onConfirm({
|
||||
screenUrl,
|
||||
screenAccessRole,
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
@ -55,22 +52,9 @@
|
|||
disabled={!screenAccessRole || !screenUrl || routeError || !touched}
|
||||
>
|
||||
<Input
|
||||
label="URL"
|
||||
label="Enter a URL for the new screen"
|
||||
error={routeError}
|
||||
bind:value={screenUrl}
|
||||
on:change={routeChanged}
|
||||
/>
|
||||
<Select
|
||||
bind:value={screenAccessRole}
|
||||
on:change={() => {
|
||||
analytics.captureEvent(Events.SCREEN.CREATE_ROLE_UPDATED, {
|
||||
screenAccessRole,
|
||||
})
|
||||
}}
|
||||
label="Screen access"
|
||||
getOptionLabel={role => role.name}
|
||||
getOptionValue={role => role._id}
|
||||
getOptionColor={role => role.color}
|
||||
options={$roles}
|
||||
/>
|
||||
</ModalContent>
|
||||
|
|
|
@ -3,12 +3,12 @@
|
|||
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 { Modal, notifications } from "@budibase/bbui"
|
||||
import { Modal, ModalContent, Select, notifications } from "@budibase/bbui"
|
||||
import { store, selectedAccessRole } from "builderStore"
|
||||
import analytics, { Events } from "analytics"
|
||||
import { get } from "svelte/store"
|
||||
import getTemplates from "builderStore/store/screenTemplates"
|
||||
import { tables } from "stores/backend"
|
||||
import { tables, roles } from "stores/backend"
|
||||
|
||||
let pendingScreen
|
||||
|
||||
|
@ -16,11 +16,22 @@
|
|||
let newScreenModal
|
||||
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
|
||||
export const showModal = () => {
|
||||
newScreenModal.show()
|
||||
selectedTemplates = null
|
||||
blankScreenUrl = null
|
||||
screenMode = null
|
||||
|
||||
newScreenModal.show()
|
||||
// Reset state when showing modal again
|
||||
pendingScreen = null
|
||||
}
|
||||
|
@ -102,6 +113,8 @@
|
|||
|
||||
// Handler for NewScreenModal
|
||||
const confirmScreenSelection = async mode => {
|
||||
screenMode = mode
|
||||
|
||||
if (mode == "autoCreate") {
|
||||
datasourceModal.show()
|
||||
} else {
|
||||
|
@ -114,12 +127,18 @@
|
|||
}
|
||||
}
|
||||
|
||||
// Handler for DatasourceModal
|
||||
const confirmScreenDatasources = async ({ templates, screenAccessRole }) => {
|
||||
// Handler for DatasourceModal confirmation, move to screen access select
|
||||
const confirmScreenDatasources = async ({ templates }) => {
|
||||
selectedTemplates = templates
|
||||
screenAccessRoleModal.show()
|
||||
}
|
||||
|
||||
// Handler for Datasource Screen Creation
|
||||
const completeDatasourceScreenCreation = async () => {
|
||||
// // Handle template selection
|
||||
if (templates?.length > 1) {
|
||||
if (selectedTemplates?.length > 1) {
|
||||
// Autoscreens, so create immediately
|
||||
const screens = templates.map(template => {
|
||||
const screens = selectedTemplates.map(template => {
|
||||
let screenTemplate = template.create()
|
||||
screenTemplate.datasource = template.datasource
|
||||
return screenTemplate
|
||||
|
@ -128,14 +147,42 @@
|
|||
}
|
||||
}
|
||||
|
||||
// Handler for ScreenDetailsModal
|
||||
const confirmScreenDetails = async ({ screenUrl, screenAccessRole }) => {
|
||||
const confirmScreenBlank = async ({ screenUrl }) => {
|
||||
blankScreenUrl = screenUrl
|
||||
screenAccessRoleModal.show()
|
||||
}
|
||||
|
||||
// Submit request for a blank screen
|
||||
const confirmBlankScreenCreation = async ({
|
||||
screenUrl,
|
||||
screenAccessRole,
|
||||
}) => {
|
||||
if (!pendingScreen) {
|
||||
return
|
||||
}
|
||||
pendingScreen.routing.route = screenUrl
|
||||
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") {
|
||||
newScreenModal.show()
|
||||
} else {
|
||||
datasourceModal.show()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<Modal bind:this={newScreenModal}>
|
||||
|
@ -146,12 +193,39 @@
|
|||
<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 bind:this={screenDetailsModal}>
|
||||
<ScreenDetailsModal
|
||||
onConfirm={confirmScreenDetails}
|
||||
onConfirm={confirmScreenBlank}
|
||||
onCancel={() => newScreenModal.show()}
|
||||
initialUrl={blankScreenUrl}
|
||||
/>
|
||||
</Modal>
|
||||
|
|
Loading…
Reference in New Issue