diff --git a/packages/bbui/src/Button/Button.svelte b/packages/bbui/src/Button/Button.svelte index a3d2df069a..e8f6b4500e 100644 --- a/packages/bbui/src/Button/Button.svelte +++ b/packages/bbui/src/Button/Button.svelte @@ -13,6 +13,7 @@ export let icon = undefined export let active = false export let tooltip = undefined + export let dataCy let showTooltip = false @@ -27,6 +28,7 @@ class:active class="spectrum-Button spectrum-Button--size{size.toUpperCase()}" {disabled} + data-cy={dataCy} on:click|preventDefault on:mouseover={() => (showTooltip = true)} on:focus={() => (showTooltip = true)} diff --git a/packages/bbui/src/Modal/ModalContent.svelte b/packages/bbui/src/Modal/ModalContent.svelte index 9043fb748f..89c10bb625 100644 --- a/packages/bbui/src/Modal/ModalContent.svelte +++ b/packages/bbui/src/Modal/ModalContent.svelte @@ -5,6 +5,7 @@ import Divider from "../Divider/Divider.svelte" import Icon from "../Icon/Icon.svelte" import Context from "../context" + import ProgressCircle from "../ProgressCircle/ProgressCircle.svelte" export let title = undefined export let size = "S" @@ -102,15 +103,22 @@ {/if} {#if showConfirmButton} - + + + {/if} {/if} @@ -169,4 +177,8 @@ .spectrum-Dialog-buttonGroup { padding-left: 0; } + + .confirm-wrap :global(.spectrum-Button-label) { + display: contents; + } diff --git a/packages/builder/cypress/integration/changeAppIconAndColour.spec.js b/packages/builder/cypress/integration/changeAppIconAndColour.spec.js index 92d03a102d..bd532aa3fb 100644 --- a/packages/builder/cypress/integration/changeAppIconAndColour.spec.js +++ b/packages/builder/cypress/integration/changeAppIconAndColour.spec.js @@ -5,10 +5,14 @@ filterTests(['all'], () => { before(() => { cy.login() }) + + after(() => { + cy.deleteAllApps() + }) it("should change the icon and colour for an application", () => { // Search for test application - cy.searchForApplication("Cypress Tests") + cy.applicationInAppTable("Cypress Tests") cy.get(".appTable") .within(() => { cy.get(".spectrum-Icon").eq(1).click() diff --git a/packages/builder/cypress/integration/createApp.spec.js b/packages/builder/cypress/integration/createApp.spec.js index 273683aec8..9507f88be9 100644 --- a/packages/builder/cypress/integration/createApp.spec.js +++ b/packages/builder/cypress/integration/createApp.spec.js @@ -2,11 +2,146 @@ import filterTests from '../support/filterTests' filterTests(['smoke', 'all'], () => { context("Create an Application", () => { - it("should create a new application", () => { + + beforeEach(() => { cy.login() - cy.createTestApp() - cy.visit(`${Cypress.config().baseUrl}/builder`) - cy.contains("Cypress Tests").should("exist") }) + + it("should show the new user UI/UX", () => { + cy.visit(`${Cypress.config().baseUrl}/builder`) + cy.get(`[data-cy="create-app-btn"]`).contains('Start from scratch').should("exist") + cy.get(`[data-cy="import-app-btn"]`).should("exist") + + cy.get(".template-category-filters").should("exist") + cy.get(".template-categories").should("exist") + + cy.get(".appTable").should("not.exist") + }) + + it("should provide filterable templates", () => { + cy.visit(`${Cypress.config().baseUrl}/builder`) + cy.wait(500) + + cy.get(".template-category-filters").should("exist") + cy.get(".template-categories").should("exist") + + cy.get(".template-category").its('length').should('be.gt', 1) + cy.get(".template-category-filters .spectrum-ActionButton").its('length').should('be.gt', 2) + + cy.get(".template-category-filters .spectrum-ActionButton").eq(1).click() + cy.get(".template-category").should('have.length', 1) + + cy.get(".template-category-filters .spectrum-ActionButton").eq(0).click() + cy.get(".template-category").its('length').should('be.gt', 1) + }) + + it("should enforce a valid url before submission", () => { + cy.visit(`${Cypress.config().baseUrl}/builder`) + cy.wait(500) + + const appName = "A New App" + + cy.get(`[data-cy="create-app-btn"]`).contains('Start from scratch').click({force: true}) + cy.get(".spectrum-Modal").within(() => { + + //Auto fill + cy.get("input").eq(0).type(appName).should("have.value", appName).blur() + cy.get("input").eq(1).should("have.value", "/a-new-app") + cy.get(".spectrum-ButtonGroup").contains("Create app").should('not.be.disabled') + + //Empty the app url - disabled create + cy.get("input").eq(1).clear().blur() + cy.get(".spectrum-ButtonGroup").contains("Create app").should('be.disabled') + + //Invalid url + cy.get("input").eq(1).type("/new app-url").blur() + cy.get(".spectrum-ButtonGroup").contains("Create app").should('be.disabled') + + //Specifically alter the url + cy.get("input").eq(1).clear() + cy.get("input").eq(1).type("another-app-name").blur() + cy.get("input").eq(1).should("have.value", "/another-app-name") + cy.get("input").eq(0).should("have.value", appName) + cy.get(".spectrum-ButtonGroup").contains("Create app").should('not.be.disabled') + + }) + }) + + it("should create the first application from scratch", () => { + const appName = "Cypress Tests" + cy.deleteApp(appName) + cy.createApp(appName, "This app is used for Cypress testing.") + + cy.visit(`${Cypress.config().baseUrl}/builder`) + cy.wait(1000) + + cy.applicationInAppTable(appName) + cy.deleteApp(appName) + }) + + it("should generate the first application from a template", () => { + cy.visit(`${Cypress.config().baseUrl}/builder`) + cy.wait(500) + + cy.get(".template-category-filters").should("exist") + cy.get(".template-categories").should("exist") + + //### Select nth template and choose to create? + cy.get('.template-category').eq(0).within(() => { + const card = cy.get('.template-card').eq(0).should("exist"); + const cardOverlay = card.get('.template-thumbnail-action-overlay').should("exist") + cardOverlay.invoke("show") + cardOverlay.get("button").contains("Use template").should("exist").click({force: true}) + }) + + //### CMD Create app from theme card + cy.get(".spectrum-Modal").should('be.visible') + + const templateName = cy.get(".spectrum-Modal .template-thumbnail-text") + templateName.invoke('text') + .then(templateNameText => { + const templateNameParsed = "/"+templateNameText.toLowerCase().replace(/\s+/g, "-") + cy.get(".spectrum-Modal input").eq(0).should("have.value", templateNameText) + cy.get(".spectrum-Modal input").eq(1).should("have.value", templateNameParsed) + + cy.get(".spectrum-Modal .spectrum-ButtonGroup").contains("Create app").click() + cy.wait(5000) + + cy.visit(`${Cypress.config().baseUrl}/builder`) + cy.wait(1000) + + cy.applicationInAppTable(templateNameText) + cy.deleteAllApps() + }); + + }) + + it("should display a second application and app filtering", () => { + const appName = "Cypress Tests" + cy.deleteApp(appName) + cy.createApp(appName, "This app is used for Cypress testing.") + + cy.visit(`${Cypress.config().baseUrl}/builder`) + cy.wait(500) + + const secondAppName = "Second App Demo" + cy.deleteApp(secondAppName) + + cy.get(`[data-cy="create-app-btn"]`).contains('Create new app').click({force: true}) + cy.wait(500) + cy.url().should('include', '/builder/portal/apps/create') + + cy.createAppFromScratch(secondAppName) + + cy.visit(`${Cypress.config().baseUrl}/builder`) + cy.wait(500) + + //Both applications should exist and be searchable + cy.searchForApplication(appName) + cy.searchForApplication(secondAppName) + + cy.deleteAllApps() + }) + }) }) diff --git a/packages/builder/cypress/integration/createTable.spec.js b/packages/builder/cypress/integration/createTable.spec.js index 81b7c2f045..df6ca5c7ca 100644 --- a/packages/builder/cypress/integration/createTable.spec.js +++ b/packages/builder/cypress/integration/createTable.spec.js @@ -7,6 +7,10 @@ filterTests(["smoke", "all"], () => { cy.createTestApp() }) + after(() => { + cy.deleteAllApps() + }) + it("should create a new Table", () => { cy.createTable("dog") cy.wait(1000) diff --git a/packages/builder/cypress/integration/createUserAndRoles.spec.js b/packages/builder/cypress/integration/createUserAndRoles.spec.js index ce6d370187..7cb3bda93b 100644 --- a/packages/builder/cypress/integration/createUserAndRoles.spec.js +++ b/packages/builder/cypress/integration/createUserAndRoles.spec.js @@ -4,9 +4,14 @@ filterTests(["smoke", "all"], () => { context("Create a User and Assign Roles", () => { before(() => { cy.login() + cy.visit(`${Cypress.config().baseUrl}/builder`) + cy.wait(500) + cy.createAppFromScratch("Initial App") }) it("should create a user", () => { + cy.visit(`${Cypress.config().baseUrl}/builder`) + cy.wait(1000) cy.createUser("bbuser@test.com") cy.get(".spectrum-Table").should("contain", "bbuser") }) @@ -30,7 +35,14 @@ filterTests(["smoke", "all"], () => { for (let i = 1; i < 3; i++) { const uuid = () => Cypress._.random(0, 1e6) const name = uuid() - cy.createApp(name) + if(i < 1){ + cy.createApp(name) + } else { + cy.visit(`${Cypress.config().baseUrl}/builder`) + cy.wait(500) + cy.get(`[data-cy="create-app-btn"]`).click({ force: true }) + cy.createAppFromScratch(name) + } } } }) diff --git a/packages/builder/cypress/integration/createView.spec.js b/packages/builder/cypress/integration/createView.spec.js index 6b06cde0bc..ad21d6afa7 100644 --- a/packages/builder/cypress/integration/createView.spec.js +++ b/packages/builder/cypress/integration/createView.spec.js @@ -4,6 +4,8 @@ filterTests(['smoke', 'all'], () => { context("Create a View", () => { before(() => { cy.login() + cy.deleteAllApps() + cy.createTestApp() cy.createTable("data") cy.addColumn("data", "group", "Text") diff --git a/packages/builder/cypress/integration/datasources/rest.spec.js b/packages/builder/cypress/integration/datasources/rest.spec.js index a15487c01b..7216a13847 100644 --- a/packages/builder/cypress/integration/datasources/rest.spec.js +++ b/packages/builder/cypress/integration/datasources/rest.spec.js @@ -4,6 +4,7 @@ filterTests(["smoke", "all"], () => { context("REST Datasource Testing", () => { before(() => { cy.login() + cy.deleteAllApps() cy.createTestApp() }) diff --git a/packages/builder/cypress/integration/queryLevelTransformers.spec.js b/packages/builder/cypress/integration/queryLevelTransformers.spec.js index e96a6dba29..86aea8eafb 100644 --- a/packages/builder/cypress/integration/queryLevelTransformers.spec.js +++ b/packages/builder/cypress/integration/queryLevelTransformers.spec.js @@ -4,7 +4,7 @@ filterTests(["smoke", "all"], () => { context("Query Level Transformers", () => { before(() => { cy.login() - cy.deleteApp("Cypress Tests") + cy.deleteAllApps() cy.createApp("Cypress Tests") }) diff --git a/packages/builder/cypress/integration/renameAnApplication.spec.js b/packages/builder/cypress/integration/renameAnApplication.spec.js index 48e829fa03..258479b628 100644 --- a/packages/builder/cypress/integration/renameAnApplication.spec.js +++ b/packages/builder/cypress/integration/renameAnApplication.spec.js @@ -1,133 +1,133 @@ import filterTests from "../support/filterTests" filterTests(['all'], () => { - context("Rename an App", () => { - beforeEach(() => { - cy.login() - cy.createTestApp() - }) + context("Rename an App", () => { + beforeEach(() => { + cy.login() + cy.createTestApp() + }) it("should rename an unpublished application", () => { - const appName = "Cypress Tests" - const appRename = "Cypress Renamed" - // Rename app, Search for app, Confirm name was changed - cy.get(".home-logo").click() - renameApp(appName, appRename) - cy.reload() - cy.wait(1000) - cy.searchForApplication(appRename) - cy.get(".appTable").find(".title").should("have.length", 1) - // Set app name back to Cypress Tests - cy.reload() - cy.wait(1000) - renameApp(appRename, appName) + const appName = "Cypress Tests" + const appRename = "Cypress Renamed" + // Rename app, Search for app, Confirm name was changed + cy.get(".home-logo").click() + renameApp(appName, appRename) + cy.reload() + cy.wait(1000) + cy.get(".appTable").find(".title").should("have.length", 1) + cy.applicationInAppTable(appRename) + // Set app name back to Cypress Tests + cy.reload() + cy.wait(1000) + renameApp(appRename, appName) }) - + xit("Should rename a published application", () => { - // It is not possible to rename a published application - const appName = "Cypress Tests" - const appRename = "Cypress Renamed" - // Publish the app - cy.get(".toprightnav") - cy.get(".spectrum-Button").contains("Publish").click({force: true}) - cy.get(".spectrum-Dialog-grid") - .within(() => { - // Click publish again within the modal - cy.get(".spectrum-Button").contains("Publish").click({force: true}) - }) - // Rename app, Search for app, Confirm name was changed - cy.get(".home-logo").click() - renameApp(appName, appRename, true) - cy.searchForApplication(appRename) - cy.get(".appTable").find(".wrapper").should("have.length", 1) + // It is not possible to rename a published application + const appName = "Cypress Tests" + const appRename = "Cypress Renamed" + // Publish the app + cy.get(".toprightnav") + cy.get(".spectrum-Button").contains("Publish").click({ force: true }) + cy.get(".spectrum-Dialog-grid") + .within(() => { + // Click publish again within the modal + cy.get(".spectrum-Button").contains("Publish").click({ force: true }) + }) + // Rename app, Search for app, Confirm name was changed + cy.get(".home-logo").click() + renameApp(appName, appRename, true) + cy.get(".appTable").find(".wrapper").should("have.length", 1) + cy.applicationInAppTable(appRename) }) it("Should try to rename an application to have no name", () => { - const appName = "Cypress Tests" - cy.get(".home-logo").click() - renameApp(appName, " ", false, true) - cy.wait(500) - // Close modal and confirm name has not been changed - cy.get(".spectrum-Dialog-grid").contains("Cancel").click() - cy.reload() - cy.wait(1000) - cy.searchForApplication(appName) - cy.get(".appTable").find(".title").should("have.length", 1) + const appName = "Cypress Tests" + cy.get(".home-logo").click() + renameApp(appName, " ", false, true) + cy.wait(500) + // Close modal and confirm name has not been changed + cy.get(".spectrum-Dialog-grid").contains("Cancel").click() + cy.reload() + cy.wait(1000) + cy.applicationInAppTable(appName) + cy.get(".appTable").find(".title").should("have.length", 1) }) xit("Should create two applications with the same name", () => { - // It is not possible to have applications with the same name - const appName = "Cypress Tests" - cy.visit(`${Cypress.config().baseUrl}/builder`) - cy.wait(500) - cy.get(".spectrum-Button").contains("Create app").click({force: true}) - cy.contains(/Start from scratch/).click() - cy.get(".spectrum-Modal") + // It is not possible to have applications with the same name + const appName = "Cypress Tests" + cy.visit(`${Cypress.config().baseUrl}/builder`) + cy.wait(500) + cy.get(".spectrum-Button").contains("Create app").click({ force: true }) + cy.contains(/Start from scratch/).click() + cy.get(".spectrum-Modal") .within(() => { - cy.get("input").eq(0).type(appName) - cy.get(".spectrum-ButtonGroup").contains("Create app").click({force: true}) - cy.get(".error").should("have.text", "Another app with the same name already exists") + cy.get("input").eq(0).type(appName) + cy.get(".spectrum-ButtonGroup").contains("Create app").click({ force: true }) + cy.get(".error").should("have.text", "Another app with the same name already exists") }) }) it("should validate application names", () => { - // App name must be letters, numbers and spaces only - // This test checks numbers and special characters specifically - const appName = "Cypress Tests" - const numberName = 12345 - const specialCharName = "£$%^" - cy.get(".home-logo").click() - renameApp(appName, numberName) - cy.reload() - cy.wait(1000) - cy.searchForApplication(numberName) - cy.get(".appTable").find(".title").should("have.length", 1) - cy.reload() - cy.wait(1000) - renameApp(numberName, specialCharName) - cy.get(".error").should("have.text", "App name must be letters, numbers and spaces only") - // Set app name back to Cypress Tests - cy.reload() - cy.wait(1000) - renameApp(numberName, appName) + // App name must be letters, numbers and spaces only + // This test checks numbers and special characters specifically + const appName = "Cypress Tests" + const numberName = 12345 + const specialCharName = "£$%^" + cy.get(".home-logo").click() + renameApp(appName, numberName) + cy.reload() + cy.wait(1000) + cy.applicationInAppTable(numberName) + cy.get(".appTable").find(".title").should("have.length", 1) + cy.reload() + cy.wait(1000) + renameApp(numberName, specialCharName) + cy.get(".error").should("have.text", "App name must be letters, numbers and spaces only") + // Set app name back to Cypress Tests + cy.reload() + cy.wait(1000) + renameApp(numberName, appName) }) - - const renameApp = (originalName, changedName, published, noName) => { - cy.searchForApplication(originalName) - cy.request(`${Cypress.config().baseUrl}/api/applications?status=all`) + + const renameApp = (originalName, changedName, published, noName) => { + cy.applicationInAppTable(originalName) + cy.request(`${Cypress.config().baseUrl}/api/applications?status=all`) .its("body") .then(val => { - if (val.length > 0) { - cy.get(".appTable") - .within(() => { - cy.get(".spectrum-Icon").eq(1).click() - }) - // Check for when an app is published - if (published == true){ - // Should not have Edit as option, will unpublish app - cy.should("not.have.value", "Edit") - cy.get(".spectrum-Menu").contains("Unpublish").click() - cy.get(".spectrum-Dialog-grid").contains("Unpublish app").click() - cy.get(".appTable > :nth-child(5) > :nth-child(2) > .spectrum-Icon").click() + if (val.length > 0) { + cy.get(".appTable") + .within(() => { + cy.get(".spectrum-Icon").eq(1).click() + }) + // Check for when an app is published + if (published == true) { + // Should not have Edit as option, will unpublish app + cy.should("not.have.value", "Edit") + cy.get(".spectrum-Menu").contains("Unpublish").click() + cy.get(".spectrum-Dialog-grid").contains("Unpublish app").click() + cy.get(".appTable > :nth-child(5) > :nth-child(2) > .spectrum-Icon").click() + } + cy.contains("Edit").click() + cy.get(".spectrum-Modal") + .within(() => { + if (noName == true) { + cy.get("input").clear() + cy.get(".spectrum-Dialog-grid").click() + .contains("App name must be letters, numbers and spaces only") + return cy } - cy.contains("Edit").click() - cy.get(".spectrum-Modal") - .within(() => { - if (noName == true){ - cy.get("input").clear() - cy.get(".spectrum-Dialog-grid").click() - .contains("App name must be letters, numbers and spaces only") - return cy - } - cy.get("input").clear() - cy.get("input").eq(0).type(changedName).should("have.value", changedName).blur() - cy.get(".spectrum-ButtonGroup").contains("Save").click({force: true}) - cy.wait(500) - }) - } + cy.get("input").clear() + cy.get("input").eq(0).type(changedName).should("have.value", changedName).blur() + cy.get(".spectrum-ButtonGroup").contains("Save").click({ force: true }) + cy.wait(500) + }) + } }) } - }) + }) }) diff --git a/packages/builder/cypress/support/commands.js b/packages/builder/cypress/support/commands.js index 699cf1fbf0..c45978e026 100644 --- a/packages/builder/cypress/support/commands.js +++ b/packages/builder/cypress/support/commands.js @@ -35,7 +35,9 @@ Cypress.Commands.add("login", () => { Cypress.Commands.add("createApp", name => { cy.visit(`${Cypress.config().baseUrl}/builder`) cy.wait(500) - cy.get(".spectrum-Button").contains("Create app").click({ force: true }) + + cy.get(`[data-cy="create-app-btn"]`).click({ force: true }) + cy.get(".spectrum-Modal").within(() => { cy.get("input").eq(0).type(name).should("have.value", name).blur() cy.get(".spectrum-ButtonGroup").contains("Create app").click() @@ -51,10 +53,23 @@ Cypress.Commands.add("deleteApp", name => { .its("body") .then(val => { if (val.length > 0) { - cy.searchForApplication(name) - cy.get(".appTable").within(() => { - cy.get(".spectrum-Icon").eq(1).click() + const appId = val.reduce((acc, app) => { + if (name === app.name) { + acc = app.appId + } + return acc + }, "") + + if (appId == "") { + return + } + + const appIdParsed = appId.split("_").pop() + const actionEleId = `[data-cy=row_actions_${appIdParsed}]` + cy.get(actionEleId).within(() => { + cy.get(".spectrum-Icon").eq(0).click() }) + cy.get(".spectrum-Menu").then($menu => { if ($menu.text().includes("Unpublish")) { cy.get(".spectrum-Menu").contains("Unpublish").click() @@ -80,22 +95,18 @@ Cypress.Commands.add("deleteAllApps", () => { .its("body") .then(val => { for (let i = 0; i < val.length; i++) { - cy.get(".spectrum-Heading") - .eq(1) - .then(app => { - const name = app.text() - cy.get(".title") - .children() - .within(() => { - cy.get(".spectrum-Icon").eq(0).click() - }) - cy.get(".spectrum-Menu").contains("Delete").click() - cy.get(".spectrum-Dialog-grid").within(() => { - cy.get("input").type(name) - cy.get(".spectrum-Button--warning").click() - }) - cy.reload() - }) + const appIdParsed = val[i].appId.split("_").pop() + const actionEleId = `[data-cy=row_actions_${appIdParsed}]` + cy.get(actionEleId).within(() => { + cy.get(".spectrum-Icon").eq(0).click() + }) + + cy.get(".spectrum-Menu").contains("Delete").click() + cy.get(".spectrum-Dialog-grid").within(() => { + cy.get("input").type(val[i].name) + cy.get(".spectrum-Button--warning").click() + }) + cy.reload() } }) }) @@ -190,9 +201,11 @@ Cypress.Commands.add("addRowMultiValue", values => { Cypress.Commands.add("createUser", email => { // quick hacky recorded way to create a user cy.contains("Users").click() - cy.get(".spectrum-Button--primary").click() + cy.get(`[data-cy="add-user"]`).click() cy.get(".spectrum-Picker-label").click() cy.get(".spectrum-Menu-item:nth-child(2) > .spectrum-Menu-itemLabel").click() + + //Onboarding type selector cy.get( ":nth-child(2) > .spectrum-Form-itemField > .spectrum-Textfield > .spectrum-Textfield-input" ) @@ -312,16 +325,37 @@ Cypress.Commands.add("addCustomSourceOptions", totalOptions => { }) }) +//Filters visible with 1 or more Cypress.Commands.add("searchForApplication", appName => { cy.wait(1000) // Searches for the app cy.get(".filter").then(() => { cy.get(".spectrum-Textfield").within(() => { + cy.get("input").eq(0).clear() cy.get("input").eq(0).type(appName) }) }) // Confirms app exists after search - cy.get(".appTable").contains(appName) + cy.applicationInAppTable(appName) +}) + +//Assumes there are no others +Cypress.Commands.add("applicationInAppTable", appName => { + cy.get(".appTable").within(() => { + cy.get(".title").contains(appName).should("exist") + }) +}) + +Cypress.Commands.add("createAppFromScratch", appName => { + cy.get(`[data-cy="create-app-btn"]`) + .contains("Start from scratch") + .click({ force: true }) + cy.get(".spectrum-Modal").within(() => { + cy.get("input").eq(0).type(appName).should("have.value", appName).blur() + cy.get(".spectrum-ButtonGroup").contains("Create app").click() + cy.wait(10000) + }) + cy.createTable("Cypress Tests", true) }) Cypress.Commands.add("selectExternalDatasource", datasourceName => { diff --git a/packages/builder/src/components/common/TemplateCard.svelte b/packages/builder/src/components/common/TemplateCard.svelte new file mode 100644 index 0000000000..1271f6aa24 --- /dev/null +++ b/packages/builder/src/components/common/TemplateCard.svelte @@ -0,0 +1,125 @@ + + +
+
+ {name} +
+ + + +
+
+ +
+
+
+
{name}
+
+
+ + diff --git a/packages/builder/src/components/common/TemplateDisplay.svelte b/packages/builder/src/components/common/TemplateDisplay.svelte new file mode 100644 index 0000000000..c96bff8d5e --- /dev/null +++ b/packages/builder/src/components/common/TemplateDisplay.svelte @@ -0,0 +1,152 @@ + + +
+ + Templates +
+ + { + selectedTemplateCategory = null + }} + > + All + + {#each templateCategories as templateCategoryKey} + { + selectedTemplateCategory = templateCategoryKey + }} + > + {templateCategoryKey} + + {/each} + +
+
+
+ +
+ + {#each filteredTemplateCategories as templateCategoryKey} +
+ {templateCategoryKey} +
+ {#each filteredTemplates[templateCategoryKey] as templateEntry} + + + + Details + + + {/each} +
+
+ {/each} +
+
+ + + + + + diff --git a/packages/builder/src/components/start/AppRow.svelte b/packages/builder/src/components/start/AppRow.svelte index bda7356a88..d6dc4e1800 100644 --- a/packages/builder/src/components/start/AppRow.svelte +++ b/packages/builder/src/components/start/AppRow.svelte @@ -61,7 +61,7 @@ {#if app.deployed}Published{:else}Unpublished{/if} -
+
+ + +
+
+ + {createAppTitle} + + {welcomeBody} + + + +
+ + +
+
+
+ + + + {#if loaded && $templates?.length} + + {/if} + + + + + + + + diff --git a/packages/builder/src/pages/builder/portal/apps/index.svelte b/packages/builder/src/pages/builder/portal/apps/index.svelte index b05aa1b659..b024afa1c7 100644 --- a/packages/builder/src/pages/builder/portal/apps/index.svelte +++ b/packages/builder/src/pages/builder/portal/apps/index.svelte @@ -11,8 +11,9 @@ notifications, Body, Search, - Icon, + Divider, } from "@budibase/bbui" + import TemplateDisplay from "components/common/TemplateDisplay.svelte" import Spinner from "components/common/Spinner.svelte" import CreateAppModal from "components/start/CreateAppModal.svelte" import UpdateAppModal from "components/start/UpdateAppModal.svelte" @@ -45,6 +46,21 @@ let appName = "" let creatingFromTemplate = false + const resolveWelcomeMessage = (auth, apps) => { + const userWelcome = auth?.user?.firstName + ? `Welcome ${auth?.user?.firstName}!` + : "Welcome back!" + return apps?.length ? userWelcome : "Let's create your first app!" + } + $: welcomeHeader = resolveWelcomeMessage($auth, $apps) + $: welcomeBody = $apps?.length + ? "Manage your apps and get a head start with templates" + : "Start from scratch or get a head start with one of our templates" + + $: createAppButtonText = $apps?.length + ? "Create new app" + : "Start from scratch" + $: enrichedApps = enrichApps($apps, $auth.user, sortBy) $: filteredApps = enrichedApps.filter(app => app?.name?.toLowerCase().includes(searchTerm.toLowerCase()) @@ -79,9 +95,13 @@ } const initiateAppCreation = () => { - template = null - creationModal.show() - creatingApp = true + if ($apps?.length) { + $goto("/builder/portal/apps/create") + } else { + template = null + creationModal.show() + creatingApp = true + } } const initiateAppsExport = () => { @@ -268,148 +288,120 @@ -
- - Welcome to Budibase - - Manage your apps and get a head start with templates - - + {#if loaded} +
+
+ + {welcomeHeader} + + {welcomeBody} + + -
- {#if cloud} - - {/if} - - -
-
- - - Quick start templates -
- {#each $templates as item} -
{ - template = item - creationModal.show() - creatingApp = true - }} - class="template-card" - > - + + {#if $apps?.length > 0} + + {/if} + {#if !$apps?.length} + + {/if} +
+
+
+ + + +
+ +
+ + {#if !$apps?.length && $templates?.length} + + {/if} + + {#if enrichedApps.length} + +
+ My apps + {#if enrichedApps.length > 1} +
+ {#if cloud} + + {/if} +
+ - +
+ {#each filteredApps as app (app.appId)} + + {/each}
-
- -
- {#each filteredApps as app (app.appId)} - - {/each} -
- - {/if} - - {#if !enrichedApps.length && !creatingApp && loaded} -
-
-
- - logo -
- Create a business app in minutes! -
- -
-
-
-
+ + {/if} {/if} {#if creatingFromTemplate}
+

Creating your Budibase app from your selected template...

@@ -459,6 +451,15 @@ diff --git a/packages/builder/src/pages/builder/portal/apps/templates.svelte b/packages/builder/src/pages/builder/portal/apps/templates.svelte new file mode 100644 index 0000000000..93b4a6d257 --- /dev/null +++ b/packages/builder/src/pages/builder/portal/apps/templates.svelte @@ -0,0 +1,43 @@ + + + + + + + + {#if loaded && $templates?.length} + + {/if} + + diff --git a/packages/builder/src/pages/builder/portal/manage/users/index.svelte b/packages/builder/src/pages/builder/portal/manage/users/index.svelte index 1160cc109b..bfbe520b2f 100644 --- a/packages/builder/src/pages/builder/portal/manage/users/index.svelte +++ b/packages/builder/src/pages/builder/portal/manage/users/index.svelte @@ -71,7 +71,9 @@ Users - +