Merge branch 'new-design-ui' of github.com:Budibase/budibase into new-design-ui

This commit is contained in:
Martin McKeaveney 2022-06-13 21:01:08 +01:00
commit b077903991
41 changed files with 328 additions and 216 deletions

View File

@ -1,5 +1,5 @@
{ {
"version": "1.0.192-alpha.5", "version": "1.0.192-alpha.6",
"npmClient": "yarn", "npmClient": "yarn",
"packages": [ "packages": [
"packages/*" "packages/*"

View File

@ -1,6 +1,6 @@
{ {
"name": "@budibase/backend-core", "name": "@budibase/backend-core",
"version": "1.0.192-alpha.5", "version": "1.0.192-alpha.6",
"description": "Budibase backend core libraries used in server and worker", "description": "Budibase backend core libraries used in server and worker",
"main": "src/index.js", "main": "src/index.js",
"author": "Budibase", "author": "Budibase",

View File

@ -1,7 +1,7 @@
{ {
"name": "@budibase/bbui", "name": "@budibase/bbui",
"description": "A UI solution used in the different Budibase projects.", "description": "A UI solution used in the different Budibase projects.",
"version": "1.0.192-alpha.5", "version": "1.0.192-alpha.6",
"license": "MPL-2.0", "license": "MPL-2.0",
"svelte": "src/index.js", "svelte": "src/index.js",
"module": "dist/bbui.es.js", "module": "dist/bbui.es.js",
@ -38,7 +38,7 @@
], ],
"dependencies": { "dependencies": {
"@adobe/spectrum-css-workflow-icons": "^1.2.1", "@adobe/spectrum-css-workflow-icons": "^1.2.1",
"@budibase/string-templates": "^1.0.192-alpha.5", "@budibase/string-templates": "^1.0.192-alpha.6",
"@spectrum-css/actionbutton": "^1.0.1", "@spectrum-css/actionbutton": "^1.0.1",
"@spectrum-css/actiongroup": "^1.0.1", "@spectrum-css/actiongroup": "^1.0.1",
"@spectrum-css/avatar": "^3.0.2", "@spectrum-css/avatar": "^3.0.2",

View File

@ -83,4 +83,7 @@
:global([dir="ltr"] .spectrum-ActionButton .spectrum-Icon) { :global([dir="ltr"] .spectrum-ActionButton .spectrum-Icon) {
margin-left: 0; margin-left: 0;
} }
.is-selected {
background: var(--spectrum-global-color-gray-300);
}
</style> </style>

View File

@ -41,7 +41,6 @@
.active :global(svg) { .active :global(svg) {
color: white; color: white;
} }
.icon-side-nav-item:hover,
.active { .active {
background: var(--spectrum-global-color-gray-300); background: var(--spectrum-global-color-gray-300);
} }

View File

@ -1,4 +1,5 @@
import filterTests from "../support/filterTests" import filterTests from "../support/filterTests"
const interact = require('../support/interact')
filterTests(['smoke', 'all'], () => { filterTests(['smoke', 'all'], () => {
context("Create a automation", () => { context("Create a automation", () => {
@ -11,51 +12,51 @@ filterTests(['smoke', 'all'], () => {
cy.createTestTableWithData() cy.createTestTableWithData()
cy.wait(2000) cy.wait(2000)
cy.contains("Automate").click() cy.contains("Automate").click()
cy.get(".add-button .spectrum-Icon").click() cy.get(interact.ADD_BUTTON_SPECTRUM).click()
cy.get(".modal-inner-wrapper").within(() => { cy.get(interact.MODAL_INNER_WRAPPER).within(() => {
cy.get("input").type("Add Row") cy.get("input").type("Add Row")
cy.contains("Row Created").click({ force: true }) cy.contains("Row Created").click({ force: true })
cy.wait(500) cy.wait(500)
cy.get(".spectrum-Button--cta").click() cy.get(interact.SPECTRUM_BUTTON_CTA).click()
}) })
// Setup trigger // Setup trigger
cy.get(".spectrum-Picker-label").click() cy.get(interact.SPECTRUM_PICKER_LABEL).click()
cy.wait(500) cy.wait(500)
cy.contains("dog").click() cy.contains("dog").click()
cy.wait(2000) cy.wait(2000)
// Create action // Create action
cy.get('[aria-label="AddCircle"]').eq(1).click() cy.get('[aria-label="AddCircle"]').eq(1).click()
cy.get(".modal-inner-wrapper").within(() => { cy.get(interact.MODAL_INNER_WRAPPER).within(() => {
cy.wait(1000) cy.wait(1000)
cy.contains("Create Row").trigger('mouseover').click().click() cy.contains("Create Row").trigger('mouseover').click().click()
cy.get(".spectrum-Button--cta").click() cy.get(interact.SPECTRUM_BUTTON_CTA).click()
}) })
cy.get(".spectrum-Picker-label").eq(1).click() cy.get(interact.SPECTRUM_PICKER_LABEL).eq(1).click()
cy.contains("dog").click() cy.contains("dog").click()
cy.get(".spectrum-Textfield-input") cy.get(interact.SPECTRUM_TEXTFIELD_INPUT)
.first() .first()
.type("{{ trigger.row.name }}", { parseSpecialCharSequences: false }) .type("{{ trigger.row.name }}", { parseSpecialCharSequences: false })
cy.get(".spectrum-Textfield-input") cy.get(interact.SPECTRUM_TEXTFIELD_INPUT)
.eq(1) .eq(1)
.type("11") .type("11")
cy.contains("Finish and test automation").click() cy.contains("Finish and test automation").click()
cy.get(".modal-inner-wrapper").within(() => { cy.get(interact.MODAL_INNER_WRAPPER).within(() => {
cy.wait(1000) cy.wait(1000)
cy.get(".spectrum-Picker-label").click() cy.get(interact.SPECTRUM_PICKER_LABEL).click()
cy.contains("dog").click() cy.contains("dog").click()
cy.wait(1000) cy.wait(1000)
cy.get(".spectrum-Textfield-input") cy.get(interact.SPECTRUM_TEXTFIELD_INPUT)
.first() .first()
.type("automationGoodboy") .type("automationGoodboy")
cy.get(".spectrum-Textfield-input") cy.get(interact.SPECTRUM_TEXTFIELD_INPUT)
.eq(1) .eq(1)
.type("11") .type("11")
cy.get(".spectrum-Textfield-input") cy.get(interact.SPECTRUM_TEXTFIELD_INPUT)
.eq(2) .eq(2)
.type("123456") .type("123456")
cy.get(".spectrum-Textfield-input") cy.get(interact.SPECTRUM_TEXTFIELD_INPUT)
.eq(3) .eq(3)
.type("123456") .type("123456")
cy.contains("Test").click() cy.contains("Test").click()

View File

@ -1,4 +1,5 @@
import filterTests from "../support/filterTests" import filterTests from "../support/filterTests"
const interact = require('../support/interact')
filterTests(["smoke", "all"], () => { filterTests(["smoke", "all"], () => {
context("Create a Table", () => { context("Create a Table", () => {
@ -11,7 +12,7 @@ filterTests(["smoke", "all"], () => {
cy.createTable("dog") cy.createTable("dog")
cy.wait(1000) cy.wait(1000)
// Check if Table exists // Check if Table exists
cy.get(".table-title h1").should("have.text", "dog") cy.get(interact.TABLE_TITLE_H1).should("have.text", "dog")
}) })
it("adds a new column to the table", () => { it("adds a new column to the table", () => {
@ -25,13 +26,13 @@ filterTests(["smoke", "all"], () => {
}) })
it("updates a column on the table", () => { it("updates a column on the table", () => {
cy.get(".title").click() cy.get(interact.TABLE_TITLE).click()
cy.get(".spectrum-Table-editIcon > use").click() cy.get(interact.SPECTRUM_TABLE_EDIT).click()
cy.get(".modal-inner-wrapper").within(() => { cy.get(interact.MODAL_INNER_WRAPPER).within(() => {
cy.get("input").eq(0).type("updated", { force: true }) cy.get("input").eq(0).type("updated", { force: true })
// Unset table display column // Unset table display column
cy.get(".spectrum-Switch-input").eq(1).click() cy.get(interact.SPECTRUM_SWITCH_INPUT).eq(1).click()
cy.contains("Save Column").click() cy.contains("Save Column").click()
}) })
cy.contains("nameupdated ").should("contain", "nameupdated") cy.contains("nameupdated ").should("contain", "nameupdated")
@ -40,16 +41,16 @@ filterTests(["smoke", "all"], () => {
it("edits a row", () => { it("edits a row", () => {
cy.contains("button", "Edit").click({ force: true }) cy.contains("button", "Edit").click({ force: true })
cy.wait(1000) cy.wait(1000)
cy.get(".spectrum-Modal input").clear() cy.get(interact.SPECTRUM_MODAL_INPUT).clear()
cy.get(".spectrum-Modal input").type("Updated") cy.get(interact.SPECTRUM_MODAL_INPUT).type("Updated")
cy.contains("Save").click() cy.contains("Save").click()
cy.contains("Updated").should("have.text", "Updated") cy.contains("Updated").should("have.text", "Updated")
}) })
it("deletes a row", () => { it("deletes a row", () => {
cy.get(".spectrum-Checkbox-input").check({ force: true }) cy.get(interact.SPECTRUM_CHECKBOX_INPUT).check({ force: true })
cy.contains("Delete 1 row(s)").click() cy.contains("Delete 1 row(s)").click()
cy.get(".spectrum-Modal").contains("Delete").click() cy.get(interact.SPECTRUM_MODAL).contains("Delete").click()
cy.contains("RoverUpdated").should("not.exist") cy.contains("RoverUpdated").should("not.exist")
}) })
@ -63,50 +64,50 @@ filterTests(["smoke", "all"], () => {
} }
cy.reload() cy.reload()
cy.wait(2000) cy.wait(2000)
cy.get(".spectrum-Pagination").within(() => { cy.get(interact.SPECTRUM_PAGINATION).within(() => {
cy.get(".spectrum-ActionButton").eq(1).click() cy.get(interact.SPECTRUM_ACTION_BUTTON).eq(1).click()
}) })
cy.get(".spectrum-Pagination").within(() => { cy.get(interact.SPECTRUM_PAGINATION).within(() => {
cy.get(".spectrum-Body--secondary").contains("Page 2") cy.get(interact.SPECTRUM_BODY_SECOND).contains("Page 2")
}) })
}) })
xit("Deletes rows and checks pagination", () => { xit("Deletes rows and checks pagination", () => {
// Delete rows, removing second page from table // Delete rows, removing second page from table
cy.get(".spectrum-Checkbox-input").check({ force: true }) cy.get(interact.SPECTRUM_CHECKBOX_INPUT).check({ force: true })
cy.get(".popovers").within(() => { cy.get(interact.POPOVERS).within(() => {
cy.get(".spectrum-Button").click({ force: true }) cy.get(interact.SPECTRUM_BUTTON).click({ force: true })
}) })
cy.get(".spectrum-Dialog-grid").contains("Delete").click({ force: true }) cy.get(interact.SPECTRUM_DIALOG_GRID).contains("Delete").click({ force: true })
cy.wait(1000) cy.wait(1000)
// Confirm table only has one page // Confirm table only has one page
cy.get(".spectrum-Pagination").within(() => { cy.get(interact.SPECTRUM_PAGINATION).within(() => {
cy.get(".spectrum-ActionButton").eq(1).should("not.be.enabled") cy.get(interact.SPECTRUM_ACTION_BUTTON).eq(1).should("not.be.enabled")
}) })
}) })
} }
it("deletes a column", () => { it("deletes a column", () => {
const columnName = "nameupdated" const columnName = "nameupdated"
cy.get(".title").click() cy.get(interact.TABLE_TITLE).click()
cy.get(".spectrum-Table-editIcon > use").click() cy.get(interact.SPECTRUM_TABLE_EDIT).click()
cy.contains("Delete").click() cy.contains("Delete").click()
cy.get('[data-cy="delete-column-confirm"]').type(columnName) cy.get(interact.DELETE_COLUMN_CONFIRM).type(columnName)
cy.contains("Delete Column").click() cy.contains("Delete Column").click()
cy.contains("nameupdated").should("not.exist") cy.contains("nameupdated").should("not.exist")
}) })
it("deletes a table", () => { it("deletes a table", () => {
cy.get(".nav-item") cy.get(interact.NAV_ITEM)
.contains("dog") .contains("dog")
.parents(".nav-item") .parents(interact.NAV_ITEM)
.first() .first()
.within(() => { .within(() => {
cy.get(".actions .spectrum-Icon").click({ force: true }) cy.get(interact.ACTION_SPECTRUM_ICON).click({ force: true })
}) })
cy.get(".spectrum-Menu > :nth-child(2)").click() cy.get(interact.SPECTRUM_MENU_CHILD2).click()
cy.get('[data-cy="delete-table-confirm"]').type("dog") cy.get(interact.DELETE_TABLE_CONFIRM).type("dog")
cy.contains("Delete Table").click() cy.contains("Delete Table").click()
cy.contains("dog").should("not.exist") cy.contains("dog").should("not.exist")
}) })

View File

@ -1,4 +1,5 @@
import filterTests from "../support/filterTests" import filterTests from "../support/filterTests"
const interact = require('../support/interact')
filterTests(["smoke", "all"], () => { filterTests(["smoke", "all"], () => {
context("Create a User and Assign Roles", () => { context("Create a User and Assign Roles", () => {
@ -12,7 +13,7 @@ filterTests(["smoke", "all"], () => {
cy.visit(`${Cypress.config().baseUrl}/builder`) cy.visit(`${Cypress.config().baseUrl}/builder`)
cy.wait(1000) cy.wait(1000)
cy.createUser("bbuser@test.com") cy.createUser("bbuser@test.com")
cy.get(".spectrum-Table").should("contain", "bbuser") cy.get(interact.SPECTRUM_TABLE).should("contain", "bbuser")
}) })
it("should confirm there is No Access for a New User", () => { it("should confirm there is No Access for a New User", () => {
@ -20,9 +21,9 @@ filterTests(["smoke", "all"], () => {
cy.contains("bbuser").click() cy.contains("bbuser").click()
cy.wait(500) cy.wait(500)
// Get No Access table - Confirm it has apps in it // Get No Access table - Confirm it has apps in it
cy.get(".spectrum-Table").eq(1).should("not.contain", "No rows found") cy.get(interact.SPECTRUM_TABLE).eq(1).should("not.contain", "No rows found")
// Get Configure Roles table - Confirm it has no apps // Get Configure Roles table - Confirm it has no apps
cy.get(".spectrum-Table").eq(0).contains("No rows found") cy.get(interact.SPECTRUM_TABLE).eq(0).contains("No rows found")
}) })
if (Cypress.env("TEST_ENV")) { if (Cypress.env("TEST_ENV")) {
@ -40,7 +41,7 @@ filterTests(["smoke", "all"], () => {
} else { } else {
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(interact.CREATE_APP_BUTTON).click({ force: true })
cy.createAppFromScratch(name) cy.createAppFromScratch(name)
} }
} }
@ -49,35 +50,35 @@ filterTests(["smoke", "all"], () => {
// Navigate back to the user // Navigate back to the user
cy.visit(`${Cypress.config().baseUrl}/builder`) cy.visit(`${Cypress.config().baseUrl}/builder`)
cy.wait(500) cy.wait(500)
cy.get(".spectrum-SideNav").contains("Users").click() cy.get(interact.SPECTRUM_SIDENAV).contains("Users").click()
cy.wait(500) cy.wait(500)
cy.get(".spectrum-Table").contains("bbuser").click() cy.get(interact.SPECTRUM_TABLE).contains("bbuser").click()
cy.wait(1000) cy.wait(1000)
for (let i = 0; i < 3; i++) { for (let i = 0; i < 3; i++) {
cy.get(".spectrum-Table", { timeout: 3000}) cy.get(interact.SPECTRUM_TABLE, { timeout: 3000})
.eq(1) .eq(1)
.find(".spectrum-Table-row") .find(interact.SPECTRUM_TABLE_ROW)
.eq(0) .eq(0)
.find(".spectrum-Table-cell") .find(interact.SPECTRUM_TABLE_CELL)
.eq(0) .eq(0)
.click() .click()
cy.wait(500) cy.wait(500)
cy.get(".spectrum-Dialog-grid") cy.get(interact.SPECTRUM_DIALOG_GRID)
.contains("Choose an option") .contains("Choose an option")
.click() .click()
.then(() => { .then(() => {
cy.wait(1000) cy.wait(1000)
if (i == 0) { if (i == 0) {
cy.get(".spectrum-Menu").contains("Admin").click({ force: true }) cy.get(interact.SPECTRUM_MENU).contains("Admin").click({ force: true })
} }
else if (i == 1) { else if (i == 1) {
cy.get(".spectrum-Menu").contains("Power").click({ force: true }) cy.get(interact.SPECTRUM_MENU).contains("Power").click({ force: true })
} }
else if (i == 2) { else if (i == 2) {
cy.get(".spectrum-Menu").contains("Basic").click({ force: true }) cy.get(interact.SPECTRUM_MENU).contains("Basic").click({ force: true })
} }
cy.wait(1000) cy.wait(1000)
cy.get(".spectrum-Button") cy.get(interact.SPECTRUM_BUTTON)
.contains("Update role") .contains("Update role")
.click({ force: true }) .click({ force: true })
}) })
@ -85,7 +86,7 @@ filterTests(["smoke", "all"], () => {
} }
// Confirm roles exist within Configure roles table // Confirm roles exist within Configure roles table
cy.wait(2000) cy.wait(2000)
cy.get(".spectrum-Table") cy.get(interact.SPECTRUM_TABLE)
.eq(0) .eq(0)
.within(assginedRoles => { .within(assginedRoles => {
expect(assginedRoles).to.contain("Admin") expect(assginedRoles).to.contain("Admin")
@ -96,60 +97,60 @@ filterTests(["smoke", "all"], () => {
it("should unassign role types", () => { it("should unassign role types", () => {
// Set each app within Configure roles table to 'No Access' // Set each app within Configure roles table to 'No Access'
cy.get(".spectrum-Table") cy.get(interact.SPECTRUM_TABLE)
.eq(0) .eq(0)
.find(".spectrum-Table-row") .find(interact.SPECTRUM_TABLE_ROW)
.its("length") .its("length")
.then(len => { .then(len => {
for (let i = 0; i < len; i++) { for (let i = 0; i < len; i++) {
cy.get(".spectrum-Table") cy.get(interact.SPECTRUM_TABLE)
.eq(0) .eq(0)
.find(".spectrum-Table-row") .find(interact.SPECTRUM_TABLE_ROW)
.eq(0) .eq(0)
.find(".spectrum-Table-cell") .find(interact.SPECTRUM_TABLE_CELL)
.eq(0) .eq(0)
.click() .click()
.then(() => { .then(() => {
cy.get(".spectrum-Picker").eq(1).click({ force: true }) cy.get(interact.SPECTRUM_PICKER).eq(1).click({ force: true })
cy.wait(500) cy.wait(500)
cy.get(".spectrum-Popover").contains("No Access").click() cy.get(interact.SPECTRUM_POPOVER).contains("No Access").click()
}) })
cy.get(".spectrum-Button") cy.get(interact.SPECTRUM_BUTTON)
.contains("Update role") .contains("Update role")
.click({ force: true }) .click({ force: true })
cy.wait(1000) cy.wait(1000)
} }
}) })
// Confirm Configure roles table no longer has any apps in it // Confirm Configure roles table no longer has any apps in it
cy.get(".spectrum-Table").eq(0).contains("No rows found") cy.get(interact.SPECTRUM_TABLE).eq(0).contains("No rows found")
}) })
} }
it("should enable Developer access", () => { it("should enable Developer access", () => {
// Enable Developer access // Enable Developer access
cy.get(".field") cy.get(interact.FIELD)
.eq(4) .eq(4)
.within(() => { .within(() => {
cy.get(".spectrum-Switch-input").click({ force: true }) cy.get(interact.SPECTRUM_SWITCH_INPUT).click({ force: true })
}) })
// No Access table should now be empty // No Access table should now be empty
cy.get(".container") cy.get(interact.CONTAINER)
.contains("No Access") .contains("No Access")
.parent() .parent()
.within(() => { .within(() => {
cy.get(".spectrum-Table").contains("No rows found") cy.get(interact.SPECTRUM_TABLE).contains("No rows found")
}) })
// Each app within Configure roles should have Admin access // Each app within Configure roles should have Admin access
cy.get(".spectrum-Table") cy.get(interact.SPECTRUM_TABLE)
.eq(0) .eq(0)
.find(".spectrum-Table-row") .find(interact.SPECTRUM_TABLE_ROW)
.its("length") .its("length")
.then(len => { .then(len => {
for (let i = 0; i < len; i++) { for (let i = 0; i < len; i++) {
cy.get(".spectrum-Table") cy.get(interact.SPECTRUM_TABLE)
.eq(0) .eq(0)
.find(".spectrum-Table-row") .find(interact.SPECTRUM_TABLE_ROW)
.eq(i) .eq(i)
.contains("Admin") .contains("Admin")
cy.wait(500) cy.wait(500)
@ -169,26 +170,26 @@ filterTests(["smoke", "all"], () => {
.contains("Configure roles") .contains("Configure roles")
.parent() .parent()
.within(() => { .within(() => {
cy.get(".spectrum-Table").contains("No rows found") cy.get(interact.SPECTRUM_TABLE).contains("No rows found")
}) })
}) })
it("should delete a user", () => { it("should delete a user", () => {
// Click Delete user button // Click Delete user button
cy.get(".spectrum-Button") cy.get(interact.SPECTRUM_BUTTON)
.contains("Delete user") .contains("Delete user")
.click({ force: true }) .click({ force: true })
.then(() => { .then(() => {
// Confirm deletion within modal // Confirm deletion within modal
cy.wait(500) cy.wait(500)
cy.get(".spectrum-Dialog-grid").within(() => { cy.get(interact.SPECTRUM_DIALOG_GRID).within(() => {
cy.get(".spectrum-Button") cy.get(interact.SPECTRUM_BUTTON)
.contains("Delete user") .contains("Delete user")
.click({ force: true }) .click({ force: true })
cy.wait(4000) cy.wait(4000)
}) })
}) })
cy.get(".spectrum-Table").should("not.have.text", "bbuser") cy.get(interact.SPECTRUM_TABLE).should("not.have.text", "bbuser")
}) })
}) })
}) })

View File

@ -62,3 +62,45 @@ export const GLOBESTRIKE = "svg[aria-label=GlobeStrike]"
export const GLOBE = "svg[aria-label=Globe]" export const GLOBE = "svg[aria-label=Globe]"
export const UNPUBLISH_MODAL = "[data-cy=unpublish-modal]" export const UNPUBLISH_MODAL = "[data-cy=unpublish-modal]"
export const CONFIRM_WRAP_BUTTON = ".confirm-wrap button" export const CONFIRM_WRAP_BUTTON = ".confirm-wrap button"
//changeAppiconAndColour
export const APP_ROW_ACTION = ".app-row-actions-icon"
export const SPECTRUM_MENU = ".spectrum-Menu"
export const ICON_ITEM = ".icon-item"
export const FILL = ".fill"
export const COLOURSS = ".colors"
export const AREA_LABEL = "[aria-label]"
export const TITLE = ".title"
export const GRID = ".grid"
export const COLOUR = ".color"
//createAutomation
export const ADD_BUTTON_SPECTRUM = ".add-button .spectrum-Icon"
export const MODAL_INNER_WRAPPER = ".modal-inner-wrapper"
export const SPECTRUM_BUTTON_CTA = ".spectrum-Button--cta"
export const SPECTRUM_TEXTFIELD_INPUT = ".spectrum-Textfield-input"
//createTable
export const TABLE_TITLE_H1 = ".table-title h1"
export const TABLE_TITLE = ".title"
export const SPECTRUM_TABLE_EDIT = ".spectrum-Table-editIcon > use"
export const SPECTRUM_SWITCH_INPUT = ".spectrum-Switch-input"
export const SPECTRUM_CHECKBOX_INPUT = ".spectrum-Checkbox-input"
export const SPECTRUM_PAGINATION = ".spectrum-Pagination"
export const SPECTRUM_ACTION_BUTTON = ".spectrum-ActionButton"
export const SPECTRUM_BODY_SECOND = ".spectrum-Body--secondary"
export const POPOVERS = ".popovers"
export const SPECTRUM_DIALOG_GRID = ".spectrum-Dialog-grid"
export const DELETE_COLUMN_CONFIRM = '[data-cy="delete-column-confirm"]'
export const NAV_ITEM = ".nav-item"
export const ACTION_SPECTRUM_ICON = ".actions .spectrum-Icon"
export const SPECTRUM_MENU_CHILD2 = ".spectrum-Menu > :nth-child(2)"
export const DELETE_TABLE_CONFIRM = '[data-cy="delete-table-confirm"]'
//createUSerAndRoles
export const SPECTRUM_TABLE = ".spectrum-Table"
export const SPECTRUM_SIDENAV = ".spectrum-SideNav"
export const SPECTRUM_TABLE_ROW = ".spectrum-Table-row"
export const SPECTRUM_TABLE_CELL = ".spectrum-Table-cell"
export const FIELD = ".field"
export const CONTAINER = ".container"

View File

@ -1,6 +1,6 @@
{ {
"name": "@budibase/builder", "name": "@budibase/builder",
"version": "1.0.192-alpha.5", "version": "1.0.192-alpha.6",
"license": "GPL-3.0", "license": "GPL-3.0",
"private": true, "private": true,
"scripts": { "scripts": {
@ -69,10 +69,10 @@
} }
}, },
"dependencies": { "dependencies": {
"@budibase/bbui": "^1.0.192-alpha.5", "@budibase/bbui": "^1.0.192-alpha.6",
"@budibase/client": "^1.0.192-alpha.5", "@budibase/client": "^1.0.192-alpha.6",
"@budibase/frontend-core": "^1.0.192-alpha.5", "@budibase/frontend-core": "^1.0.192-alpha.6",
"@budibase/string-templates": "^1.0.192-alpha.5", "@budibase/string-templates": "^1.0.192-alpha.6",
"@sentry/browser": "5.19.1", "@sentry/browser": "5.19.1",
"@spectrum-css/page": "^3.0.1", "@spectrum-css/page": "^3.0.1",
"@spectrum-css/vars": "^3.0.1", "@spectrum-css/vars": "^3.0.1",

View File

@ -10,8 +10,9 @@
{#each options as option} {#each options as option}
<ActionButton <ActionButton
icon={option.barIcon} icon={option.barIcon}
quiet={option.value !== value} quiet
on:click={() => onChange(option.value)} on:click={() => onChange(option.value)}
selected={option.value === value}
/> />
{/each} {/each}
</ActionGroup> </ActionGroup>

View File

@ -5,15 +5,16 @@
export let value export let value
export let error export let error
export let placeholder = null
</script> </script>
<Select <Select
bind:value bind:value
on:change on:change
options={$roles} options={$roles}
placeholder={null}
getOptionLabel={role => role.name} getOptionLabel={role => role.name}
getOptionValue={role => role._id} getOptionValue={role => role._id}
getOptionColour={role => RoleUtils.getRoleColour(role._id)} getOptionColour={role => RoleUtils.getRoleColour(role._id)}
{placeholder}
{error} {error}
/> />

View File

@ -2,7 +2,7 @@
import { Layout } from "@budibase/bbui" import { Layout } from "@budibase/bbui"
</script> </script>
<!-- routify:options index=5 --> <!-- routify:options index=4 -->
<Layout gap="S" justifyItems="center"> <Layout gap="S" justifyItems="center">
<slot /> <slot />
</Layout> </Layout>

View File

@ -18,7 +18,7 @@
} }
</script> </script>
<!-- routify:options index=2 --> <!-- routify:options index=1 -->
<div class="root"> <div class="root">
<div class="nav"> <div class="nav">
<Tabs {selected} on:select={selectFirstDatasource}> <Tabs {selected} on:select={selectFirstDatasource}>

View File

@ -12,7 +12,7 @@
urlParam: "screenId", urlParam: "screenId",
stateKey: "selectedScreenId", stateKey: "selectedScreenId",
validate: id => $store.screens.some(screen => screen._id === id), validate: id => $store.screens.some(screen => screen._id === id),
fallbackUrl: "../../", fallbackUrl: "../../design",
store, store,
routify, routify,
}) })

View File

@ -43,7 +43,8 @@
extraButtonText="View details" extraButtonText="View details"
extraButtonAction={() => {}} extraButtonAction={() => {}}
> >
Custom layouts are being deprecated. They will be removed on [date]. Custom layouts are being deprecated. They will be removed in a future
release.
</Banner> </Banner>
<Body size="S"> <Body size="S">
You can save the content of this layout by pressing the button below. You can save the content of this layout by pressing the button below.

View File

@ -11,6 +11,7 @@
import { dndzone } from "svelte-dnd-action" import { dndzone } from "svelte-dnd-action"
import { generate } from "shortid" import { generate } from "shortid"
import { store } from "builderStore" import { store } from "builderStore"
import RoleSelect from "components/design/settings/controls/RoleSelect.svelte"
export let links = [] export let links = []
@ -75,6 +76,7 @@
placeholder="URL" placeholder="URL"
options={urlOptions} options={urlOptions}
/> />
<RoleSelect bind:value={link.roleId} placeholder="Minimum role" />
<Icon <Icon
name="Close" name="Close"
hoverable hoverable
@ -95,7 +97,7 @@
<style> <style>
.container { .container {
width: 100%; width: 100%;
max-width: 600px; max-width: 800px;
margin: 0 auto; margin: 0 auto;
} }
.links { .links {

View File

@ -1,5 +1,4 @@
<script> <script>
import { goto } from "@roxi/routify"
import { store } from "builderStore" import { store } from "builderStore"
import ConfirmDialog from "components/common/ConfirmDialog.svelte" import ConfirmDialog from "components/common/ConfirmDialog.svelte"
import { import {
@ -66,7 +65,6 @@
const deleteScreen = async () => { const deleteScreen = async () => {
try { try {
await store.actions.screens.delete(screen) await store.actions.screens.delete(screen)
$goto("../")
notifications.success("Deleted screen successfully.") notifications.success("Deleted screen successfully.")
} catch (err) { } catch (err) {
notifications.error("Error deleting screen") notifications.error("Error deleting screen")

View File

@ -45,6 +45,12 @@
placeholder={null} placeholder={null}
getOptionLabel={role => role.name} getOptionLabel={role => role.name}
getOptionValue={role => role._id} getOptionValue={role => role._id}
getOptionColour={role => {
if (role?._id === "all") {
return null
}
return RoleUtils.getRoleColour(role._id)
}}
options={[{ name: "All screens", _id: "all" }, ...$roles]} options={[{ name: "All screens", _id: "all" }, ...$roles]}
/> />
</Layout> </Layout>

View File

@ -0,0 +1,2 @@
<!-- routify:options index=2 -->
<slot />

View File

@ -1,4 +1,4 @@
<script> <script>
import { redirect } from "@roxi/routify" import { redirect } from "@roxi/routify"
$redirect("./design") $redirect("./data")
</script> </script>

View File

@ -1,2 +0,0 @@
<!-- routify:options index=4 -->
<slot />

View File

@ -1,6 +0,0 @@
Settings
<!-- {#if $admin.cloud && $auth.user.account}
<UpgradeModal />
{/if}
<VersionModal /> -->

View File

@ -1,6 +1,6 @@
{ {
"name": "@budibase/cli", "name": "@budibase/cli",
"version": "1.0.192-alpha.5", "version": "1.0.192-alpha.6",
"description": "Budibase CLI, for developers, self hosting and migrations.", "description": "Budibase CLI, for developers, self hosting and migrations.",
"main": "src/index.js", "main": "src/index.js",
"bin": { "bin": {

View File

@ -1,6 +1,6 @@
{ {
"name": "@budibase/client", "name": "@budibase/client",
"version": "1.0.192-alpha.5", "version": "1.0.192-alpha.6",
"license": "MPL-2.0", "license": "MPL-2.0",
"module": "dist/budibase-client.js", "module": "dist/budibase-client.js",
"main": "dist/budibase-client.js", "main": "dist/budibase-client.js",
@ -19,9 +19,9 @@
"dev:builder": "rollup -cw" "dev:builder": "rollup -cw"
}, },
"dependencies": { "dependencies": {
"@budibase/bbui": "^1.0.192-alpha.5", "@budibase/bbui": "^1.0.192-alpha.6",
"@budibase/frontend-core": "^1.0.192-alpha.5", "@budibase/frontend-core": "^1.0.192-alpha.6",
"@budibase/string-templates": "^1.0.192-alpha.5", "@budibase/string-templates": "^1.0.192-alpha.6",
"@spectrum-css/button": "^3.0.3", "@spectrum-css/button": "^3.0.3",
"@spectrum-css/card": "^3.0.3", "@spectrum-css/card": "^3.0.3",
"@spectrum-css/divider": "^1.0.3", "@spectrum-css/divider": "^1.0.3",

View File

@ -23,9 +23,9 @@ export const API = createAPIClient({
} }
// Add role header // Add role header
const role = get(devToolsStore).role const devToolsState = get(devToolsStore)
if (role) { if (devToolsState.enabled && devToolsState.role) {
headers["x-budibase-role"] = role headers["x-budibase-role"] = devToolsState.role
} }
}, },
@ -34,7 +34,11 @@ export const API = createAPIClient({
// Or we could check error.status and redirect to login on a 403 etc. // Or we could check error.status and redirect to login on a 403 etc.
onError: error => { onError: error => {
const { status, method, url, message, handled } = error || {} const { status, method, url, message, handled } = error || {}
const ignoreErrorUrls = ["bbtel", "/api/global/self"] const ignoreErrorUrls = [
"bbtel",
"/api/global/self",
"/api/tables/ta_users",
]
// Log any errors that we haven't manually handled // Log any errors that we haven't manually handled
if (!handled) { if (!handled) {

View File

@ -42,10 +42,7 @@
let permissionError = false let permissionError = false
// Determine if we should show devtools or not // Determine if we should show devtools or not
$: isDevPreview = $: showDevTools = $devToolsStore.enabled && !$routeStore.queryParams?.peek
$appStore.isDevApp &&
!$builderStore.inBuilder &&
!$routeStore.queryParams?.peek
// Handle no matching route // Handle no matching route
$: { $: {
@ -59,6 +56,7 @@
$screenStore.screens, $screenStore.screens,
$devToolsStore.role $devToolsStore.role
) )
permissionError = false
routeStore.actions.navigate(route) routeStore.actions.navigate(route)
} else { } else {
// No screens likely means the user has no permissions to view this app // No screens likely means the user has no permissions to view this app
@ -120,41 +118,57 @@
dir="ltr" dir="ltr"
class="spectrum spectrum--medium {$themeStore.theme}" class="spectrum spectrum--medium {$themeStore.theme}"
> >
{#if permissionError} <DeviceBindingsProvider>
<div class="error">
<Layout justifyItems="center" gap="S">
{@html ErrorSVG}
<Heading size="L">You don't have permission to use this app</Heading>
<Body size="S">Ask your administrator to grant you access</Body>
</Layout>
</div>
{:else if $screenStore.activeLayout}
<UserBindingsProvider> <UserBindingsProvider>
<DeviceBindingsProvider> <StateBindingsProvider>
<StateBindingsProvider> <RowSelectionProvider>
<RowSelectionProvider> <!-- Settings bar can be rendered outside of device preview -->
<!-- Settings bar can be rendered outside of device preview --> <!-- Key block needs to be outside the if statement or it breaks -->
<!-- Key block needs to be outside the if statement or it breaks --> {#key $builderStore.selectedComponentId}
{#key $builderStore.selectedComponentId} {#if $builderStore.inBuilder}
{#if $builderStore.inBuilder} <SettingsBar />
<SettingsBar /> {/if}
{/key}
<!-- Clip boundary for selection indicators -->
<div
id="clip-root"
class:preview={$builderStore.inBuilder}
class:tablet-preview={$builderStore.previewDevice === "tablet"}
class:mobile-preview={$builderStore.previewDevice === "mobile"}
>
<!-- Actual app -->
<div id="app-root">
{#if showDevTools}
<DevToolsHeader />
{/if} {/if}
{/key}
<!-- Clip boundary for selection indicators --> <div id="app-body">
<div {#if permissionError}
id="clip-root" <div class="error">
class:preview={$builderStore.inBuilder} <Layout justifyItems="center" gap="S">
class:tablet-preview={$builderStore.previewDevice === "tablet"} {@html ErrorSVG}
class:mobile-preview={$builderStore.previewDevice === "mobile"} <Heading size="L">
> You don't have permission to use this app
<!-- Actual app --> </Heading>
<div id="app-root"> <Body size="S">
{#if isDevPreview} Ask your administrator to grant you access
<DevToolsHeader /> </Body>
{/if} </Layout>
</div>
<div id="app-body"> {:else if !$screenStore.activeLayout}
<div class="error">
<Layout justifyItems="center" gap="S">
{@html ErrorSVG}
<Heading size="L">
Something went wrong rendering your app
</Heading>
<Body size="S">
Get in touch with support if this issue persists
</Body>
</Layout>
</div>
{:else}
<CustomThemeWrapper> <CustomThemeWrapper>
{#key $screenStore.activeLayout._id} {#key $screenStore.activeLayout._id}
<Component <Component
@ -178,29 +192,29 @@
<ConfirmationDisplay /> <ConfirmationDisplay />
<PeekScreenDisplay /> <PeekScreenDisplay />
</CustomThemeWrapper> </CustomThemeWrapper>
{/if}
{#if isDevPreview} {#if showDevTools}
<DevTools /> <DevTools />
{/if} {/if}
</div>
</div> </div>
<!-- Preview and dev tools utilities -->
{#if $appStore.isDevApp}
<SelectionIndicator />
{/if}
{#if $builderStore.inBuilder || $devToolsStore.allowSelection}
<HoverIndicator />
{/if}
{#if $builderStore.inBuilder}
<DNDHandler />
{/if}
</div> </div>
</RowSelectionProvider>
</StateBindingsProvider> <!-- Preview and dev tools utilities -->
</DeviceBindingsProvider> {#if $appStore.isDevApp}
<SelectionIndicator />
{/if}
{#if $builderStore.inBuilder || $devToolsStore.allowSelection}
<HoverIndicator />
{/if}
{#if $builderStore.inBuilder}
<DNDHandler />
{/if}
</div>
</RowSelectionProvider>
</StateBindingsProvider>
</UserBindingsProvider> </UserBindingsProvider>
{/if} </DeviceBindingsProvider>
</div> </div>
<KeyboardManager /> <KeyboardManager />
{/if} {/if}
@ -249,7 +263,6 @@
} }
.error { .error {
position: absolute;
width: 100%; width: 100%;
height: 100%; height: 100%;
display: grid; display: grid;
@ -258,23 +271,19 @@
text-align: center; text-align: center;
padding: 20px; padding: 20px;
} }
.error :global(svg) { .error :global(svg) {
fill: var(--spectrum-global-color-gray-500); fill: var(--spectrum-global-color-gray-500);
width: 80px; width: 80px;
height: 80px; height: 80px;
} }
.error :global(h1), .error :global(h1),
.error :global(p) { .error :global(p) {
color: var(--spectrum-global-color-gray-800); color: var(--spectrum-global-color-gray-800);
} }
.error :global(p) { .error :global(p) {
font-style: italic; font-style: italic;
margin-top: -0.5em; margin-top: -0.5em;
} }
.error :global(h1) { .error :global(h1) {
font-weight: 400; font-weight: 400;
} }
@ -284,12 +293,10 @@
#clip-root.preview { #clip-root.preview {
padding: 2px; padding: 2px;
} }
#clip-root.tablet-preview { #clip-root.tablet-preview {
width: calc(1024px + 6px); width: calc(1024px + 6px);
height: calc(768px + 6px); height: calc(768px + 6px);
} }
#clip-root.mobile-preview { #clip-root.mobile-preview {
width: calc(390px + 6px); width: calc(390px + 6px);
height: calc(844px + 6px); height: calc(844px + 6px);

View File

@ -2,10 +2,12 @@
import { getContext, setContext } from "svelte" import { getContext, setContext } from "svelte"
import { writable } from "svelte/store" import { writable } from "svelte/store"
import { Heading, Icon } from "@budibase/bbui" import { Heading, Icon } from "@budibase/bbui"
import { FieldTypes } from "../../constants" import { FieldTypes } from "constants"
import active from "svelte-spa-router/active" import active from "svelte-spa-router/active"
import { RoleUtils } from "@budibase/frontend-core"
const { routeStore, styleable, linkable, builderStore } = getContext("sdk") const sdk = getContext("sdk")
const { routeStore, styleable, linkable, builderStore, currentRole } = sdk
const component = getContext("component") const component = getContext("component")
const context = getContext("context") const context = getContext("context")
@ -50,7 +52,7 @@
}) })
setContext("layout", store) setContext("layout", store)
$: validLinks = links?.filter(link => link.text && link.url) || [] $: validLinks = getValidLinks(links, $currentRole)
$: typeClass = NavigationClasses[navigation] || NavigationClasses.None $: typeClass = NavigationClasses[navigation] || NavigationClasses.None
$: navWidthClass = WidthClasses[navWidth || width] || WidthClasses.Large $: navWidthClass = WidthClasses[navWidth || width] || WidthClasses.Large
$: pageWidthClass = WidthClasses[pageWidth || width] || WidthClasses.Large $: pageWidthClass = WidthClasses[pageWidth || width] || WidthClasses.Large
@ -79,6 +81,17 @@
} }
} }
const getValidLinks = (allLinks, role) => {
// Strip links missing required info
let validLinks = (allLinks || []).filter(link => link.text && link.url)
// Filter to only links allowed by the current role
const priority = RoleUtils.getRolePriority(role)
return validLinks.filter(link => {
return !link.roleId || RoleUtils.getRolePriority(link.roleId) <= priority
})
}
const isInternal = url => { const isInternal = url => {
return url.startsWith("/") return url.startsWith("/")
} }

View File

@ -21,11 +21,11 @@
} }
onMount(() => { onMount(() => {
resizeObserver.observe(document.getElementById("app-root")) resizeObserver.observe(document.getElementById("spectrum-root"))
}) })
onDestroy(() => { onDestroy(() => {
resizeObserver.unobserve(document.getElementById("app-root")) resizeObserver.unobserve(document.getElementById("spectrum-root"))
}) })
</script> </script>

View File

@ -1,6 +1,6 @@
<script> <script>
import Provider from "./Provider.svelte" import Provider from "./Provider.svelte"
import { authStore, devToolsStore } from "stores" import { authStore, currentRole } from "stores"
import { ActionTypes } from "constants" import { ActionTypes } from "constants"
import { Constants } from "@budibase/frontend-core" import { Constants } from "@budibase/frontend-core"
@ -17,10 +17,6 @@
] ]
</script> </script>
<Provider <Provider key="user" data={{ ...$authStore, roleId: $currentRole }} {actions}>
key="user"
data={{ ...$authStore, roleId: $devToolsStore.role || $authStore?.roleId }}
{actions}
>
<slot /> <slot />
</Provider> </Provider>

View File

@ -1,6 +1,7 @@
import ClientApp from "./components/ClientApp.svelte" import ClientApp from "./components/ClientApp.svelte"
import { builderStore, appStore } from "./stores" import { builderStore, appStore, devToolsStore } from "./stores"
import loadSpectrumIcons from "@budibase/bbui/spectrum-icons-rollup.js" import loadSpectrumIcons from "@budibase/bbui/spectrum-icons-rollup.js"
import { get } from "svelte/store"
// Initialise spectrum icons // Initialise spectrum icons
loadSpectrumIcons() loadSpectrumIcons()
@ -23,7 +24,12 @@ const loadBudibase = () => {
// Set app ID - this window flag is set by both the preview and the real // Set app ID - this window flag is set by both the preview and the real
// server rendered app HTML // server rendered app HTML
appStore.actions.setAppID(window["##BUDIBASE_APP_ID##"]) appStore.actions.setAppId(window["##BUDIBASE_APP_ID##"])
// Enable dev tools or not. We need to be using a dev app and not inside
// the builder preview to enable them.
const enableDevTools = !get(builderStore).inBuilder && get(appStore).isDevApp
devToolsStore.actions.setEnabled(enableDevTools)
// Create app if one hasn't been created yet // Create app if one hasn't been created yet
if (!app) { if (!app) {

View File

@ -8,6 +8,7 @@ import {
uploadStore, uploadStore,
rowSelectionStore, rowSelectionStore,
componentStore, componentStore,
currentRole,
} from "stores" } from "stores"
import { styleable } from "utils/styleable" import { styleable } from "utils/styleable"
import { linkable } from "utils/linkable" import { linkable } from "utils/linkable"
@ -26,6 +27,7 @@ export default {
builderStore, builderStore,
uploadStore, uploadStore,
componentStore, componentStore,
currentRole,
styleable, styleable,
linkable, linkable,
getAction, getAction,

View File

@ -1,5 +1,5 @@
import { API } from "api" import { API } from "api"
import { get, writable } from "svelte/store" import { get, writable, derived } from "svelte/store"
const initialState = { const initialState = {
appId: null, appId: null,
@ -9,6 +9,12 @@ const initialState = {
const createAppStore = () => { const createAppStore = () => {
const store = writable(initialState) const store = writable(initialState)
const derivedStore = derived(store, $store => {
return {
...$store,
isDevApp: $store.appId?.startsWith("app_dev"),
}
})
// Fetches the app definition including screens, layouts and theme // Fetches the app definition including screens, layouts and theme
const fetchAppDefinition = async () => { const fetchAppDefinition = async () => {
@ -22,7 +28,6 @@ const createAppStore = () => {
...initialState, ...initialState,
...appDefinition, ...appDefinition,
appId: appDefinition?.application?.appId, appId: appDefinition?.application?.appId,
isDevApp: appId.startsWith("app_dev"),
}) })
} catch (error) { } catch (error) {
store.set(initialState) store.set(initialState)
@ -30,7 +35,7 @@ const createAppStore = () => {
} }
// Sets the initial app ID // Sets the initial app ID
const setAppID = id => { const setAppId = id => {
store.update(state => { store.update(state => {
if (state) { if (state) {
state.appId = id state.appId = id
@ -42,8 +47,8 @@ const createAppStore = () => {
} }
return { return {
subscribe: store.subscribe, subscribe: derivedStore.subscribe,
actions: { setAppID, fetchAppDefinition }, actions: { setAppId, fetchAppDefinition },
} }
} }

View File

@ -1,23 +1,29 @@
import { get } from "svelte/store"
import { createLocalStorageStore } from "@budibase/frontend-core" import { createLocalStorageStore } from "@budibase/frontend-core"
import { appStore } from "./app"
import { initialise } from "./initialise" import { initialise } from "./initialise"
import { authStore } from "./auth" import { authStore } from "./auth"
import { API } from "../api"
const initialState = { const initialState = {
enabled: false,
visible: false, visible: false,
allowSelection: false, allowSelection: false,
role: null, role: null,
} }
const createDevToolStore = () => { const createDevToolStore = () => {
const localStorageKey = `${get(appStore).appId}.devTools` const store = createLocalStorageStore("bb-devtools", initialState)
const store = createLocalStorageStore(localStorageKey, initialState)
const setEnabled = enabled => {
store.update(state => ({
...state,
enabled,
}))
}
const setVisible = visible => { const setVisible = visible => {
store.update(state => ({ store.update(state => ({
...state, ...state,
visible: visible, visible,
})) }))
} }
@ -33,14 +39,14 @@ const createDevToolStore = () => {
...state, ...state,
role: role === "self" ? null : role, role: role === "self" ? null : role,
})) }))
// location.reload() API.invalidateCache()
await authStore.actions.fetchUser() await authStore.actions.fetchUser()
await initialise() await initialise()
} }
return { return {
subscribe: store.subscribe, subscribe: store.subscribe,
actions: { setVisible, setAllowSelection, changeRole }, actions: { setEnabled, setVisible, setAllowSelection, changeRole },
} }
} }

View File

@ -1,3 +1,7 @@
import { derived } from "svelte/store"
import { devToolsStore } from "./devTools.js"
import { authStore } from "./auth.js"
export { authStore } from "./auth" export { authStore } from "./auth"
export { appStore } from "./app" export { appStore } from "./app"
export { notificationStore } from "./notification" export { notificationStore } from "./notification"
@ -13,8 +17,17 @@ export { devToolsStore } from "./devTools"
export { componentStore } from "./components" export { componentStore } from "./components"
export { uploadStore } from "./uploads.js" export { uploadStore } from "./uploads.js"
export { rowSelectionStore } from "./rowSelection.js" export { rowSelectionStore } from "./rowSelection.js"
// Context stores are layered and duplicated, so it is not a singleton // Context stores are layered and duplicated, so it is not a singleton
export { createContextStore } from "./context" export { createContextStore } from "./context"
// Initialises an app by loading screens and routes // Initialises an app by loading screens and routes
export { initialise } from "./initialise" export { initialise } from "./initialise"
// Derive the current role of the logged-in user
export const currentRole = derived(
[devToolsStore, authStore],
([$devToolsStore, $authStore]) => {
return ($devToolsStore.enabled && $devToolsStore.role) || $authStore?.roleId
}
)

View File

@ -1,12 +1,12 @@
{ {
"name": "@budibase/frontend-core", "name": "@budibase/frontend-core",
"version": "1.0.192-alpha.5", "version": "1.0.192-alpha.6",
"description": "Budibase frontend core libraries used in builder and client", "description": "Budibase frontend core libraries used in builder and client",
"author": "Budibase", "author": "Budibase",
"license": "MPL-2.0", "license": "MPL-2.0",
"svelte": "src/index.js", "svelte": "src/index.js",
"dependencies": { "dependencies": {
"@budibase/bbui": "^1.0.192-alpha.5", "@budibase/bbui": "^1.0.192-alpha.6",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"svelte": "^3.46.2" "svelte": "^3.46.2"
} }

View File

@ -57,6 +57,7 @@ export const createAPIClient = config => {
...defaultAPIClientConfig, ...defaultAPIClientConfig,
...config, ...config,
} }
let cache = {}
// Generates an error object from an API response // Generates an error object from an API response
const makeErrorFromResponse = async (response, method) => { const makeErrorFromResponse = async (response, method) => {
@ -139,6 +140,7 @@ export const createAPIClient = config => {
credentials: "same-origin", credentials: "same-origin",
}) })
} catch (error) { } catch (error) {
delete cache[url]
throw makeError("Failed to send request", { url, method }) throw makeError("Failed to send request", { url, method })
} }
@ -151,9 +153,11 @@ export const createAPIClient = config => {
return await response.json() return await response.json()
} }
} catch (error) { } catch (error) {
delete cache[url]
return null return null
} }
} else { } else {
delete cache[url]
throw await makeErrorFromResponse(response, method) throw await makeErrorFromResponse(response, method)
} }
} }
@ -161,7 +165,6 @@ export const createAPIClient = config => {
// Performs an API call to the server and caches the response. // Performs an API call to the server and caches the response.
// Future invocation for this URL will return the cached result instead of // Future invocation for this URL will return the cached result instead of
// hitting the server again. // hitting the server again.
let cache = {}
const makeCachedApiCall = async params => { const makeCachedApiCall = async params => {
const identifier = params.url const identifier = params.url
if (!identifier) { if (!identifier) {
@ -206,6 +209,9 @@ export const createAPIClient = config => {
error: message => { error: message => {
throw makeError(message) throw makeError(message)
}, },
invalidateCache: () => {
cache = {}
},
} }
// Attach all endpoints // Attach all endpoints

View File

@ -1,7 +1,7 @@
{ {
"name": "@budibase/server", "name": "@budibase/server",
"email": "hi@budibase.com", "email": "hi@budibase.com",
"version": "1.0.192-alpha.5", "version": "1.0.192-alpha.6",
"description": "Budibase Web Server", "description": "Budibase Web Server",
"main": "src/index.ts", "main": "src/index.ts",
"repository": { "repository": {
@ -70,10 +70,10 @@
"license": "GPL-3.0", "license": "GPL-3.0",
"dependencies": { "dependencies": {
"@apidevtools/swagger-parser": "^10.0.3", "@apidevtools/swagger-parser": "^10.0.3",
"@budibase/backend-core": "^1.0.192-alpha.5", "@budibase/backend-core": "^1.0.192-alpha.6",
"@budibase/client": "^1.0.192-alpha.5", "@budibase/client": "^1.0.192-alpha.6",
"@budibase/pro": "1.0.192-alpha.5", "@budibase/pro": "1.0.192-alpha.6",
"@budibase/string-templates": "^1.0.192-alpha.5", "@budibase/string-templates": "^1.0.192-alpha.6",
"@bull-board/api": "^3.7.0", "@bull-board/api": "^3.7.0",
"@bull-board/koa": "^3.7.0", "@bull-board/koa": "^3.7.0",
"@elastic/elasticsearch": "7.10.0", "@elastic/elasticsearch": "7.10.0",

View File

@ -74,6 +74,10 @@ module.exports = async (ctx, next) => {
try { try {
await getRole(roleHeader) await getRole(roleHeader)
roleId = roleHeader roleId = roleHeader
// Delete admin and builder flags so that the specified role is honoured
delete ctx.user.builder
delete ctx.user.admin
} catch (error) { } catch (error) {
// Swallow error and do nothing // Swallow error and do nothing
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "@budibase/string-templates", "name": "@budibase/string-templates",
"version": "1.0.192-alpha.5", "version": "1.0.192-alpha.6",
"description": "Handlebars wrapper for Budibase templating.", "description": "Handlebars wrapper for Budibase templating.",
"main": "src/index.cjs", "main": "src/index.cjs",
"module": "dist/bundle.mjs", "module": "dist/bundle.mjs",

View File

@ -1,7 +1,7 @@
{ {
"name": "@budibase/worker", "name": "@budibase/worker",
"email": "hi@budibase.com", "email": "hi@budibase.com",
"version": "1.0.192-alpha.5", "version": "1.0.192-alpha.6",
"description": "Budibase background service", "description": "Budibase background service",
"main": "src/index.ts", "main": "src/index.ts",
"repository": { "repository": {
@ -32,9 +32,9 @@
"author": "Budibase", "author": "Budibase",
"license": "GPL-3.0", "license": "GPL-3.0",
"dependencies": { "dependencies": {
"@budibase/backend-core": "^1.0.192-alpha.5", "@budibase/backend-core": "^1.0.192-alpha.6",
"@budibase/pro": "1.0.192-alpha.5", "@budibase/pro": "1.0.192-alpha.6",
"@budibase/string-templates": "^1.0.192-alpha.5", "@budibase/string-templates": "^1.0.192-alpha.6",
"@koa/router": "^8.0.0", "@koa/router": "^8.0.0",
"@sentry/node": "6.17.7", "@sentry/node": "6.17.7",
"@techpass/passport-openidconnect": "^0.3.0", "@techpass/passport-openidconnect": "^0.3.0",