From 01f3851c9a17de54fb296493ed0c8345ee8c4902 Mon Sep 17 00:00:00 2001 From: Maurits Lourens Date: Mon, 6 Sep 2021 15:16:21 +0200 Subject: [PATCH 1/4] add link to checklist items for direct navigation (and lint issues) --- .../components/common/ConfigChecklist.svelte | 17 +++---- packages/builder/src/stores/portal/admin.js | 2 +- .../api/controllers/row/ExternalRequest.ts | 44 ++++++++++++++----- packages/server/src/definitions/datasource.ts | 2 +- .../src/api/controllers/global/configs.js | 24 ++++++++-- 5 files changed, 63 insertions(+), 26 deletions(-) diff --git a/packages/builder/src/components/common/ConfigChecklist.svelte b/packages/builder/src/components/common/ConfigChecklist.svelte index 83e6a41063..e3a88d709b 100644 --- a/packages/builder/src/components/common/ConfigChecklist.svelte +++ b/packages/builder/src/components/common/ConfigChecklist.svelte @@ -7,13 +7,7 @@ ProgressCircle, } from "@budibase/bbui" import { admin } from "stores/portal" - - const MESSAGES = { - apps: "Create your first app", - smtp: "Set up email", - adminUser: "Create your first user", - sso: "Set up single sign-on", - } + import { goto } from "@roxi/routify" @@ -28,9 +22,12 @@ {#each Object.keys($admin.checklist) as checklistItem, idx} -
- {idx + 1}. {MESSAGES[checklistItem]} - +
$goto($admin.checklist[checklistItem].link)} + > + {idx + 1}. {$admin.checklist[checklistItem].label} +
{/each} diff --git a/packages/builder/src/stores/portal/admin.js b/packages/builder/src/stores/portal/admin.js index 25688ac70c..28178a98eb 100644 --- a/packages/builder/src/stores/portal/admin.js +++ b/packages/builder/src/stores/portal/admin.js @@ -24,7 +24,7 @@ export function createAdminStore() { const onboardingSteps = Object.keys(json) const stepsComplete = onboardingSteps.reduce( - (score, step) => score + Number(!!json[step]), + (score, step) => (score + step.checked ? 1 : 0), 0 ) diff --git a/packages/server/src/api/controllers/row/ExternalRequest.ts b/packages/server/src/api/controllers/row/ExternalRequest.ts index 648c94bff5..b87e27c067 100644 --- a/packages/server/src/api/controllers/row/ExternalRequest.ts +++ b/packages/server/src/api/controllers/row/ExternalRequest.ts @@ -6,8 +6,16 @@ import { SearchFilters, SortJson, } from "../../../definitions/datasource" -import {Datasource, FieldSchema, Row, Table} from "../../../definitions/common" -import {breakRowIdField, generateRowIdField} from "../../../integrations/utils" +import { + Datasource, + FieldSchema, + Row, + Table, +} from "../../../definitions/common" +import { + breakRowIdField, + generateRowIdField, +} from "../../../integrations/utils" import { RelationshipTypes } from "../../../constants" interface ManyRelationship { @@ -348,7 +356,7 @@ module External { * information. */ async lookupRelations(tableId: string, row: Row) { - const related: {[key: string]: any} = {} + const related: { [key: string]: any } = {} const { tableName } = breakExternalTableId(tableId) const table = this.tables[tableName] // @ts-ignore @@ -387,7 +395,11 @@ module External { * isn't supposed to exist anymore and delete those. This is better than the usual method of delete them * all and then re-create, as theres no chance of losing data (e.g. delete succeed, but write fail). */ - async handleManyRelationships(mainTableId: string, row: Row, relationships: ManyRelationship[]) { + async handleManyRelationships( + mainTableId: string, + row: Row, + relationships: ManyRelationship[] + ) { const { appId } = this // if we're creating (in a through table) need to wipe the existing ones first const promises = [] @@ -399,8 +411,10 @@ module External { // @ts-ignore const linkPrimary = linkTable.primary[0] const rows = related[key].rows || [] - const found = rows.find((row: { [key: string]: any }) => - row[linkPrimary] === relationship.id || row[linkPrimary] === body[linkPrimary] + const found = rows.find( + (row: { [key: string]: any }) => + row[linkPrimary] === relationship.id || + row[linkPrimary] === body[linkPrimary] ) const operation = isUpdate ? DataSourceOperation.UPDATE @@ -420,13 +434,17 @@ module External { } } // finally cleanup anything that needs to be removed - for (let [colName, {isMany, rows, tableId}] of Object.entries(related)) { + for (let [colName, { isMany, rows, tableId }] of Object.entries( + related + )) { const table = this.getTable(tableId) for (let row of rows) { const filters = buildFilters(generateIdForRow(row, table), {}, table) // safety check, if there are no filters on deletion bad things happen if (Object.keys(filters).length !== 0) { - const op = isMany ? DataSourceOperation.DELETE : DataSourceOperation.UPDATE + const op = isMany + ? DataSourceOperation.DELETE + : DataSourceOperation.UPDATE const body = isMany ? null : { [colName]: null } promises.push( makeExternalQuery(this.appId, { @@ -448,7 +466,10 @@ module External { * Creating the specific list of fields that we desire, and excluding the ones that are no use to us * is more performant and has the added benefit of protecting against this scenario. */ - buildFields(table: Table, includeRelations: IncludeRelationships = IncludeRelationships.INCLUDE) { + buildFields( + table: Table, + includeRelations: IncludeRelationships = IncludeRelationships.INCLUDE + ) { function extractNonLinkFieldNames(table: Table, existing: string[] = []) { return Object.entries(table.schema) .filter( @@ -523,7 +544,10 @@ module External { // can't really use response right now const response = await makeExternalQuery(appId, json) // handle many to many relationships now if we know the ID (could be auto increment) - if (operation !== DataSourceOperation.READ && processed.manyRelationships) { + if ( + operation !== DataSourceOperation.READ && + processed.manyRelationships + ) { await this.handleManyRelationships( table._id || "", response[0], diff --git a/packages/server/src/definitions/datasource.ts b/packages/server/src/definitions/datasource.ts index a43573ecf7..48fd24e1cf 100644 --- a/packages/server/src/definitions/datasource.ts +++ b/packages/server/src/definitions/datasource.ts @@ -42,7 +42,7 @@ export enum SourceNames { export enum IncludeRelationships { INCLUDE = 1, - EXCLUDE = 0 + EXCLUDE = 0, } export interface QueryDefinition { diff --git a/packages/worker/src/api/controllers/global/configs.js b/packages/worker/src/api/controllers/global/configs.js index 1208fda485..8752545960 100644 --- a/packages/worker/src/api/controllers/global/configs.js +++ b/packages/worker/src/api/controllers/global/configs.js @@ -248,10 +248,26 @@ exports.configChecklist = async function (ctx) { const adminUser = users.rows.some(row => row.doc.admin) ctx.body = { - apps: apps.length, - smtp: !!smtpConfig, - adminUser, - sso: !!googleConfig || !!oidcConfig, + apps: { + checked: apps.length > 0, + label: "Create your first app", + link: "/builder/portal/apps", + }, + smtp: { + checked: !!smtpConfig, + label: "Set up email", + link: "/builder/portal/manage/email", + }, + adminUser: { + checked: adminUser != null, + label: "Create your first user", + link: "/builder/portal/manage/users", + }, + sso: { + checked: !!googleConfig || !!oidcConfig, + label: "Set up single sign-on", + link: "/builder/portal/manage/auth", + }, } } catch (err) { ctx.throw(err.status, err) From de96f7384adf122d48cda936f47e846690514f4f Mon Sep 17 00:00:00 2001 From: Maurits Lourens Date: Mon, 6 Sep 2021 15:49:38 +0200 Subject: [PATCH 2/4] fix unit test --- packages/worker/src/api/routes/tests/configs.spec.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/worker/src/api/routes/tests/configs.spec.js b/packages/worker/src/api/routes/tests/configs.spec.js index 10feb77b37..73c2903ced 100644 --- a/packages/worker/src/api/routes/tests/configs.spec.js +++ b/packages/worker/src/api/routes/tests/configs.spec.js @@ -4,7 +4,7 @@ const setup = require("./utilities") jest.mock("nodemailer") const nodemailer = require("nodemailer") nodemailer.createTransport.mockReturnValue({ - verify: jest.fn() + verify: jest.fn(), }) describe("/api/global/configs/checklist", () => { @@ -25,11 +25,11 @@ describe("/api/global/configs/checklist", () => { .set(config.defaultHeaders()) .expect("Content-Type", /json/) .expect(200) - + const checklist = res.body - expect(checklist.apps).toBe(0) - expect(checklist.smtp).toBe(true) - expect(checklist.adminUser).toBe(true) + expect(checklist.apps.checked).toBeFalsy() + expect(checklist.smtp.checked).toBeTruthy() + expect(checklist.adminUser.checked).toBeTruthy() }) -}) \ No newline at end of file +}) From a3065bca363fd42b12ac0d9b1251d99a0a7611c7 Mon Sep 17 00:00:00 2001 From: Maurits Lourens Date: Mon, 6 Sep 2021 17:55:19 +0200 Subject: [PATCH 3/4] fix tests --- packages/builder/src/pages/builder/_layout.svelte | 2 +- packages/builder/src/pages/builder/admin/_layout.svelte | 2 +- packages/builder/src/stores/portal/admin.js | 7 ++++++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/builder/src/pages/builder/_layout.svelte b/packages/builder/src/pages/builder/_layout.svelte index b1f6d7e733..aac5d28f52 100644 --- a/packages/builder/src/pages/builder/_layout.svelte +++ b/packages/builder/src/pages/builder/_layout.svelte @@ -6,7 +6,7 @@ let loaded = false $: multiTenancyEnabled = $admin.multiTenancy - $: hasAdminUser = !!$admin?.checklist?.adminUser + $: hasAdminUser = !!$admin?.checklist?.adminUser.checked $: tenantSet = $auth.tenantSet onMount(async () => { diff --git a/packages/builder/src/pages/builder/admin/_layout.svelte b/packages/builder/src/pages/builder/admin/_layout.svelte index 70823b9a34..602b6a6de3 100644 --- a/packages/builder/src/pages/builder/admin/_layout.svelte +++ b/packages/builder/src/pages/builder/admin/_layout.svelte @@ -6,7 +6,7 @@ let loaded = false onMount(() => { - if ($admin?.checklist?.adminUser) { + if ($admin?.checklist?.adminUser.checked) { $redirect("../") } else { loaded = true diff --git a/packages/builder/src/stores/portal/admin.js b/packages/builder/src/stores/portal/admin.js index 28178a98eb..24b8c31aab 100644 --- a/packages/builder/src/stores/portal/admin.js +++ b/packages/builder/src/stores/portal/admin.js @@ -8,7 +8,12 @@ export function createAdminStore() { multiTenancy: false, sandbox: false, onboardingProgress: 0, - checklist: { apps: 0, smtp: false, adminUser: false, sso: false }, + checklist: { + apps: { checked: false }, + smtp: { checked: false }, + adminUser: { checked: false }, + sso: { checked: false }, + }, } const admin = writable(DEFAULT_CONFIG) From 33104fb1d1c56d2299a9456ddb0b55df72affbc2 Mon Sep 17 00:00:00 2001 From: Maurits Lourens Date: Mon, 6 Sep 2021 20:23:33 +0200 Subject: [PATCH 4/4] fix test --- packages/builder/src/components/common/ConfigChecklist.svelte | 2 +- packages/builder/src/pages/builder/_layout.svelte | 3 +-- packages/worker/src/api/controllers/global/configs.js | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/builder/src/components/common/ConfigChecklist.svelte b/packages/builder/src/components/common/ConfigChecklist.svelte index e3a88d709b..7914a78b65 100644 --- a/packages/builder/src/components/common/ConfigChecklist.svelte +++ b/packages/builder/src/components/common/ConfigChecklist.svelte @@ -27,7 +27,7 @@ on:click={() => $goto($admin.checklist[checklistItem].link)} > {idx + 1}. {$admin.checklist[checklistItem].label} - +
{/each} diff --git a/packages/builder/src/pages/builder/_layout.svelte b/packages/builder/src/pages/builder/_layout.svelte index aac5d28f52..0dbabb31d2 100644 --- a/packages/builder/src/pages/builder/_layout.svelte +++ b/packages/builder/src/pages/builder/_layout.svelte @@ -6,7 +6,7 @@ let loaded = false $: multiTenancyEnabled = $admin.multiTenancy - $: hasAdminUser = !!$admin?.checklist?.adminUser.checked + $: hasAdminUser = $admin?.checklist?.adminUser.checked $: tenantSet = $auth.tenantSet onMount(async () => { @@ -26,7 +26,6 @@ $redirect("./admin") } } - // Redirect to log in at any time if the user isn't authenticated $: { if ( diff --git a/packages/worker/src/api/controllers/global/configs.js b/packages/worker/src/api/controllers/global/configs.js index 8752545960..aa83fd695f 100644 --- a/packages/worker/src/api/controllers/global/configs.js +++ b/packages/worker/src/api/controllers/global/configs.js @@ -259,7 +259,7 @@ exports.configChecklist = async function (ctx) { link: "/builder/portal/manage/email", }, adminUser: { - checked: adminUser != null, + checked: adminUser, label: "Create your first user", link: "/builder/portal/manage/users", },