From a21ca8fb621c5b5feed779a497f5933b1235933a Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Mon, 1 Mar 2021 17:06:08 +0000 Subject: [PATCH 1/6] First version, still playing around with styling. --- .../builder/src/builderStore/store/backend.js | 1 + .../DataTable/modals/CreateEditColumn.svelte | 110 +++++++++++------- .../builder/src/constants/backend/index.js | 6 + packages/server/src/constants/index.js | 1 + .../src/db/linkedRows/LinkController.js | 41 +++++-- 5 files changed, 106 insertions(+), 53 deletions(-) diff --git a/packages/builder/src/builderStore/store/backend.js b/packages/builder/src/builderStore/store/backend.js index 0a5b9f0461..93ed27c9af 100644 --- a/packages/builder/src/builderStore/store/backend.js +++ b/packages/builder/src/builderStore/store/backend.js @@ -259,6 +259,7 @@ export const getBackendUiStore = () => { } state.draftTable.schema[field.name] = cloneDeep(field) + console.log(state.draftTable) store.actions.tables.save(state.draftTable) return state }) diff --git a/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte b/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte index ae19489575..812647d1cc 100644 --- a/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte +++ b/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte @@ -11,12 +11,13 @@ import { cloneDeep } from "lodash/fp" import { backendUiStore } from "builderStore" import { TableNames, UNEDITABLE_USER_FIELDS } from "constants" - import { FIELDS, AUTO_COLUMN_SUB_TYPES } from "constants/backend" + import { FIELDS, AUTO_COLUMN_SUB_TYPES, RelationshipTypes } from "constants/backend" import { getAutoColumnInformation, buildAutoColumn } from "builderStore/utils" import { notifier } from "builderStore/store/notifications" import ValuesList from "components/common/ValuesList.svelte" import DatePicker from "components/common/DatePicker.svelte" import ConfirmDialog from "components/common/ConfirmDialog.svelte" + import { truncate } from "lodash" const AUTO_COL = "auto" const LINK_TYPE = FIELDS.LINK.type @@ -36,16 +37,7 @@ $backendUiStore.selectedTable.primaryDisplay == null || $backendUiStore.selectedTable.primaryDisplay === field.name - let relationshipTypes = [ - { text: "Many to many (N:N)", value: "many-to-many" }, - { text: "One to many (1:N)", value: "one-to-many" }, - ] - let types = ["Many to many (N:N)", "One to many (1:N)"] - - let selectedRelationshipType = - relationshipTypes.find(type => type.value === field.relationshipType) - ?.text || "Many to many (N:N)" - + let table = $backendUiStore.selectedTable let indexes = [...($backendUiStore.selectedTable.indexes || [])] let confirmDeleteDialog let deletion @@ -57,7 +49,7 @@ $: uneditable = $backendUiStore.selectedTable?._id === TableNames.USERS && UNEDITABLE_USER_FIELDS.includes(field.name) - $: invalid = field.type === FIELDS.LINK.type && !field.tableId + $: invalid = field.type === LINK_TYPE && !field.tableId // used to select what different options can be displayed for column type $: canBeSearched = @@ -67,15 +59,9 @@ $: canBeDisplay = field.type !== LINK_TYPE && field.type !== AUTO_COL $: canBeRequired = field.type !== LINK_TYPE && !uneditable && field.type !== AUTO_COL + $: relationshipOptions = getRelationshipOptions(field) async function saveColumn() { - // Set relationship type if it's - if (field.type === "link") { - field.relationshipType = relationshipTypes.find( - type => type.text === selectedRelationshipType - ).value - } - if (field.type === AUTO_COL) { field = buildAutoColumn( $backendUiStore.draftTable.name, @@ -110,12 +96,18 @@ if (!definition) { return } - field.type = definition.type - field.constraints = definition.constraints // remove any extra fields that may not be related to this type delete field.autocolumn delete field.subtype delete field.tableId + delete field.relationshipType + // add in defaults and initial definition + field.type = definition.type + field.constraints = definition.constraints + // default relationships many to many + if (field.type === LINK_TYPE) { + field.relationshipType = RelationshipTypes.MANY_TO_MANY + } } function onChangeRequired(e) { @@ -153,6 +145,23 @@ confirmDeleteDialog.hide() deletion = false } + + function getRelationshipOptions(field) { + if (!field || !field.tableId) { + return null + } + const linkTable = tableOptions.find(table => table._id === field.tableId) + if (!linkTable) { + return null + } + const thisName = truncate(table.name, { length: 20 }), + linkName = truncate(linkTable.name, { length: 20 }) + return [ + { name: `Many ${thisName} has many ${linkName}`, value: RelationshipTypes.MANY_TO_MANY }, + { name: `One ${thisName} has many ${linkName}`, value: RelationshipTypes.ONE_TO_MANY }, + { name: `Many ${thisName} has one ${linkName}`, value: RelationshipTypes.MANY_TO_ONE }, + ] + }
@@ -231,26 +240,32 @@ label="Max Value" bind:value={field.constraints.numericality.lessThanOrEqualTo} /> {:else if field.type === 'link'} -
- -
- {#each types as type} - - - - {/each} -
-
+ {#if relationshipOptions && relationshipOptions.length > 0} +
+ +
+ {#each relationshipOptions as {value, name}} + +
+ + + +
+
+ {/each} +
+
+ {/if} diff --git a/packages/builder/src/constants/backend/index.js b/packages/builder/src/constants/backend/index.js index 22d5544753..f7bb77db3b 100644 --- a/packages/builder/src/constants/backend/index.js +++ b/packages/builder/src/constants/backend/index.js @@ -123,3 +123,9 @@ export function isAutoColumnUserRelationship(subtype) { subtype === AUTO_COLUMN_SUB_TYPES.UPDATED_BY ) } + +export const RelationshipTypes = { + MANY_TO_MANY: "many-to-many", + ONE_TO_MANY: "one-to-many", + MANY_TO_ONE: "many-to-one", +} diff --git a/packages/server/src/constants/index.js b/packages/server/src/constants/index.js index 90893730be..46fb5cb649 100644 --- a/packages/server/src/constants/index.js +++ b/packages/server/src/constants/index.js @@ -14,6 +14,7 @@ exports.FieldTypes = { exports.RelationshipTypes = { ONE_TO_MANY: "one-to-many", + MANY_TO_ONE: "many-to-one", MANY_TO_MANY: "many-to-many", } diff --git a/packages/server/src/db/linkedRows/LinkController.js b/packages/server/src/db/linkedRows/LinkController.js index 2e86592b24..433bf57ad4 100644 --- a/packages/server/src/db/linkedRows/LinkController.js +++ b/packages/server/src/db/linkedRows/LinkController.js @@ -145,6 +145,27 @@ class LinkController { return true } + /** + * Given two the field of this table, and the field of the linked table, this makes sure + * the state of relationship type is accurate on both. + */ + handleRelationshipType(field, linkedField) { + if ( + !field.relationshipType || + field.relationshipType === RelationshipTypes.MANY_TO_MANY + ) { + linkedField.relationshipType = RelationshipTypes.MANY_TO_MANY + // make sure by default all are many to many (if not specified) + field.relationshipType = RelationshipTypes.MANY_TO_MANY + } else if (field.relationshipType === RelationshipTypes.MANY_TO_ONE) { + // Ensure that the other side of the relationship is locked to one record + linkedField.relationshipType = RelationshipTypes.ONE_TO_MANY + } else if (field.relationshipType === RelationshipTypes.ONE_TO_MANY) { + linkedField.relationshipType = RelationshipTypes.MANY_TO_ONE + } + return { field, linkedField } + } + // all operations here will assume that the table // this operation is related to has linked rows /** @@ -317,34 +338,32 @@ class LinkController { } catch (err) { continue } - const linkConfig = { + const fields = this.handleRelationshipType(field, { name: field.fieldName, type: FieldTypes.LINK, // these are the props of the table that initiated the link tableId: table._id, fieldName: fieldName, - } + }) + + // update table schema after checking relationship types + schema[fieldName] = fields.field + const linkedField = fields.linkedField if (field.autocolumn) { - linkConfig.autocolumn = field.autocolumn - } - - if (field.relationshipType) { - // Ensure that the other side of the relationship is locked to one record - linkConfig.relationshipType = field.relationshipType - delete field.relationshipType + linkedField.autocolumn = field.autocolumn } // check the linked table to make sure we aren't overwriting an existing column const existingSchema = linkedTable.schema[field.fieldName] if ( existingSchema != null && - !this.areSchemasEqual(existingSchema, linkConfig) + !this.areSchemasEqual(existingSchema, linkedField) ) { throw new Error("Cannot overwrite existing column.") } // create the link field in the other table - linkedTable.schema[field.fieldName] = linkConfig + linkedTable.schema[field.fieldName] = linkedField const response = await this._db.put(linkedTable) // special case for when linking back to self, make sure rev updated if (linkedTable._id === table._id) { From 4cd6fef492171839f2d67f438acd8668b07d7171 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Mon, 1 Mar 2021 17:48:52 +0000 Subject: [PATCH 2/6] Updating the properties panel to show the component type rather than name (no point in repeating) and some final styling changes to the one to many update. --- .../backend/DataTable/modals/CreateEditColumn.svelte | 9 +++++---- .../design/PropertiesPanel/PropertiesPanel.svelte | 4 ++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte b/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte index 812647d1cc..b4a9283352 100644 --- a/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte +++ b/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte @@ -257,9 +257,9 @@ value={value} bind:group={field.relationshipType}>
- + - +
{/each} @@ -326,8 +326,9 @@ .rel-type-center { font-weight: 500; color: var(--grey-6); - margin-right: 10px; - margin-left: 10px; + margin-right: 8px; + margin-left: 8px; + padding: 1px 3px 1px 3px; background: var(--grey-3); border-radius: 2px; } diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertiesPanel.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertiesPanel.svelte index 6291917cd0..39eb2752bf 100644 --- a/packages/builder/src/components/design/PropertiesPanel/PropertiesPanel.svelte +++ b/packages/builder/src/components/design/PropertiesPanel/PropertiesPanel.svelte @@ -73,8 +73,8 @@ {categories} {selectedCategory} /> -{#if showDisplayName} -
{$selectedComponent._instanceName}
+{#if definition && definition.name} +
{definition.name}
{/if}
From 93759fa77c5387c3883822f3fcbb74b1b5c8d28c Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Mon, 1 Mar 2021 18:03:33 +0000 Subject: [PATCH 3/6] Formatting. --- .../DataTable/modals/CreateEditColumn.svelte | 35 +++++++++++++------ 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte b/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte index b4a9283352..ad1deaae2a 100644 --- a/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte +++ b/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte @@ -11,7 +11,11 @@ import { cloneDeep } from "lodash/fp" import { backendUiStore } from "builderStore" import { TableNames, UNEDITABLE_USER_FIELDS } from "constants" - import { FIELDS, AUTO_COLUMN_SUB_TYPES, RelationshipTypes } from "constants/backend" + import { + FIELDS, + AUTO_COLUMN_SUB_TYPES, + RelationshipTypes, + } from "constants/backend" import { getAutoColumnInformation, buildAutoColumn } from "builderStore/utils" import { notifier } from "builderStore/store/notifications" import ValuesList from "components/common/ValuesList.svelte" @@ -157,9 +161,18 @@ const thisName = truncate(table.name, { length: 20 }), linkName = truncate(linkTable.name, { length: 20 }) return [ - { name: `Many ${thisName} has many ${linkName}`, value: RelationshipTypes.MANY_TO_MANY }, - { name: `One ${thisName} has many ${linkName}`, value: RelationshipTypes.ONE_TO_MANY }, - { name: `Many ${thisName} has one ${linkName}`, value: RelationshipTypes.MANY_TO_ONE }, + { + name: `Many ${thisName} has many ${linkName}`, + value: RelationshipTypes.MANY_TO_MANY, + }, + { + name: `One ${thisName} has many ${linkName}`, + value: RelationshipTypes.ONE_TO_MANY, + }, + { + name: `Many ${thisName} has one ${linkName}`, + value: RelationshipTypes.MANY_TO_ONE, + }, ] } @@ -250,16 +263,16 @@
- {#each relationshipOptions as {value, name}} + {#each relationshipOptions as { value, name }} + disabled={originalName} + name="Relationship type" + {value} + bind:group={field.relationshipType}>
- + - +
{/each} From b9493db3a94038cf7b2c72d5c5bd7a1ff5aaecf4 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Mon, 1 Mar 2021 18:10:28 +0000 Subject: [PATCH 4/6] Removing console log. --- packages/builder/src/builderStore/store/backend.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/builder/src/builderStore/store/backend.js b/packages/builder/src/builderStore/store/backend.js index 93ed27c9af..0a5b9f0461 100644 --- a/packages/builder/src/builderStore/store/backend.js +++ b/packages/builder/src/builderStore/store/backend.js @@ -259,7 +259,6 @@ export const getBackendUiStore = () => { } state.draftTable.schema[field.name] = cloneDeep(field) - console.log(state.draftTable) store.actions.tables.save(state.draftTable) return state }) From 2975ed39e09182649c721c0c257c92572322143d Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Tue, 2 Mar 2021 11:10:26 +0000 Subject: [PATCH 5/6] Updating with a suggestion from Andrew kingston, adding row/rows to sentences about one->many relationships so that singular/plural english makes sense. --- .../DataTable/modals/CreateEditColumn.svelte | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte b/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte index ad1deaae2a..57ce4cb43d 100644 --- a/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte +++ b/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte @@ -158,19 +158,19 @@ if (!linkTable) { return null } - const thisName = truncate(table.name, { length: 20 }), - linkName = truncate(linkTable.name, { length: 20 }) + const thisName = truncate(table.name, { length: 15 }), + linkName = truncate(linkTable.name, { length: 15 }) return [ { - name: `Many ${thisName} has many ${linkName}`, + name: `Many ${thisName} rows has many ${linkName} rows`, value: RelationshipTypes.MANY_TO_MANY, }, { - name: `One ${thisName} has many ${linkName}`, + name: `One ${thisName} row has many ${linkName} rows`, value: RelationshipTypes.ONE_TO_MANY, }, { - name: `Many ${thisName} has one ${linkName}`, + name: `Many ${thisName} rows has one ${linkName} row`, value: RelationshipTypes.MANY_TO_ONE, }, ] @@ -339,15 +339,14 @@ .rel-type-center { font-weight: 500; color: var(--grey-6); - margin-right: 8px; - margin-left: 8px; + margin-right: 6px; + margin-left: 6px; padding: 1px 3px 1px 3px; background: var(--grey-3); border-radius: 2px; } .radio-button-labels { - display: flex; - align-items: center; + margin-top: 2px; } From 519d7b32dc882a696164c246be74b411652724e9 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Wed, 3 Mar 2021 10:41:40 +0000 Subject: [PATCH 6/6] PR comment from Marty, adding a bit more vertical breathing room around checkboxes of relationship type. --- .../backend/DataTable/modals/CreateEditColumn.svelte | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte b/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte index 57ce4cb43d..598bcdaad2 100644 --- a/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte +++ b/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte @@ -316,7 +316,7 @@ } .radio-buttons :global(> *) { - margin-top: var(--spacing-xs); + margin-top: var(--spacing-s); width: 100%; } @@ -339,8 +339,8 @@ .rel-type-center { font-weight: 500; color: var(--grey-6); - margin-right: 6px; - margin-left: 6px; + margin-right: 4px; + margin-left: 4px; padding: 1px 3px 1px 3px; background: var(--grey-3); border-radius: 2px;