diff --git a/lerna.json b/lerna.json index 106084980f..c6a99591de 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "0.1.16", + "version": "0.1.17", "npmClient": "yarn", "packages": [ "packages/*" diff --git a/package.json b/package.json index b3ce4265a6..148924b6d3 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "build": "lerna run build", "initialise": "lerna run initialise", "publishdev": "lerna run publishdev", - "publishnpm": "yarn build && lerna publish", + "publishnpm": "yarn build && lerna publish --force-publish", "clean": "lerna clean", "dev": "node ./scripts/symlinkDev.js && lerna run --parallel --stream dev:builder", "test": "lerna run test", diff --git a/packages/builder/cypress/integration/createComponents.spec.js b/packages/builder/cypress/integration/createComponents.spec.js index d6c471b74f..2e247f7110 100644 --- a/packages/builder/cypress/integration/createComponents.spec.js +++ b/packages/builder/cypress/integration/createComponents.spec.js @@ -5,7 +5,7 @@ xcontext('Create Components', () => { cy.visit('localhost:4001/_builder') // https://on.cypress.io/type cy.createApp('Model App', 'Model App Description') - cy.createModel('dog', 'name', 'age') + cy.createTable('dog', 'name', 'age') cy.addRecord('bob', '15') }) diff --git a/packages/builder/cypress/integration/createModel.spec.js b/packages/builder/cypress/integration/createModel.spec.js deleted file mode 100644 index 06b2420331..0000000000 --- a/packages/builder/cypress/integration/createModel.spec.js +++ /dev/null @@ -1,22 +0,0 @@ -xcontext('Create a Model', () => { - - before(() => { - cy.visit('localhost:4001/_builder') - // https://on.cypress.io/type - cy.createApp('Model App', 'Model App Description') - }) - - // https://on.cypress.io/interacting-with-elements - it('should create a new model', () => { - - cy.createModel('dog', 'name', 'age') - - // Check if model exists - cy.get('.title').should('have.text', 'dog') - }) - it('should add a record', () => { - cy.addRecord('bob', '15') - - cy.contains('bob').should('have.text', 'bob') - }) -}) diff --git a/packages/builder/cypress/integration/createTable.spec.js b/packages/builder/cypress/integration/createTable.spec.js new file mode 100644 index 0000000000..c744eb7e4f --- /dev/null +++ b/packages/builder/cypress/integration/createTable.spec.js @@ -0,0 +1,70 @@ +context('Create a Table', () => { + before(() => { + cy.visit('localhost:4001/_builder') + cy.createApp('Table App', 'Table App Description') + }) + + it('should create a new Table', () => { + cy.createTable('dog') + + // Check if Table exists + cy.get('.title').should('have.text', 'dog') + }) + + it('adds a new column to the table', () => { + cy.addColumn('dog', 'name', 'Plain Text') + + cy.contains('name').should("be.visible") + }) + + it('creates a record in the table', () => { + cy.addRecord(["Rover"]) + + cy.contains('Rover').should("be.visible") + }) + + it('updates a column on the table', () => { + cy.contains("name").click() + cy.get("[data-cy='edit-column-header']").click() + + cy.get("[placeholder=Name]").type("updated") + cy.get("select").select("Plain Text") + + cy.contains("Save Column").click() + + cy.contains('nameupdated').should('have.text', 'nameupdated ') + }) + + it('edits a record', () => { + cy.get("tbody .ri-more-line").click() + cy.get("[data-cy=edit-row]").click() + cy.get(".actions input").type("updatedRecord") + cy.contains("Save").click() + + cy.contains('updatedRecord').should('have.text', 'updatedRecord') + }) + + it('deletes a record', () => { + cy.get("tbody .ri-more-line").click() + cy.get("[data-cy=delete-row]").click() + cy.get(".modal-actions").contains("Delete").click() + + cy.contains('updatedRecord').should('not.exist') + }) + + it('deletes a column', () => { + cy.contains("name").click() + cy.get("[data-cy='delete-column-header']").click() + + cy.contains('nameupdated').should('not.exist') + }) + + it('deletes a table', () => { + cy.contains("div", "dog").get(".ri-more-line").click() + cy.get("[data-cy=delete-table]").click() + cy.get(".modal-actions").contains("Delete").click() + + cy.contains('dog').should('not.exist') + }) + +}) diff --git a/packages/builder/cypress/integration/createWorkflow.spec.js b/packages/builder/cypress/integration/createWorkflow.spec.js index ed14ce1487..f341bf86b1 100644 --- a/packages/builder/cypress/integration/createWorkflow.spec.js +++ b/packages/builder/cypress/integration/createWorkflow.spec.js @@ -9,7 +9,7 @@ xcontext('Create a workflow', () => { // https://on.cypress.io/interacting-with-elements it('should create a workflow', () => { - cy.createModel('dog', 'name', 'age') + cy.createTable('dog', 'name', 'age') cy.contains('workflow').click() cy.contains('Create New Workflow').click() diff --git a/packages/builder/cypress/support/commands.js b/packages/builder/cypress/support/commands.js index abd44d7061..40ffb0f489 100644 --- a/packages/builder/cypress/support/commands.js +++ b/packages/builder/cypress/support/commands.js @@ -57,29 +57,37 @@ Cypress.Commands.add("createApp", name => { }) }) -Cypress.Commands.add("createModel", modelName => { +Cypress.Commands.add("createTable", tableName => { // Enter model name cy.contains("Create New Table").click() - cy.get("[data-cy=table-name-input]").type(modelName) + cy.get("[placeholder='Table Name']").type(tableName) // Add 'name' field - cy.contains("Add").click() - cy.contains("Plain Text").click() - - // Add 'age' field - cy.contains("Add").click() - cy.contains("Number").click() - cy.contains("Save").click() - - cy.contains(modelName).click() + cy.contains(tableName).should("be.visible") }) -Cypress.Commands.add("addRecord", (firstField, secondField) => { - cy.contains("Create New Record").click() +Cypress.Commands.add("addColumn", (tableName, columnName, type) => { + // Select Table + cy.contains(tableName).click() + cy.contains("Create New Column").click() - cy.get("[data-cy='Plain Text-input']").type(firstField) - cy.get("[data-cy=Number-input]").type(secondField) + cy.get("[placeholder=Name]").type(columnName) + cy.get("select").select(type) + + cy.contains("Save Column") + + cy.contains("Save").click() +}) + +Cypress.Commands.add("addRecord", values => { + cy.contains("Create New Row").click() + + for (let i = 0; i < values.length; i++) { + cy.get("input") + .eq(i) + .type(values[i]) + } // Save cy.contains("Save").click() diff --git a/packages/builder/package.json b/packages/builder/package.json index 7ebbe81617..206df9d326 100644 --- a/packages/builder/package.json +++ b/packages/builder/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/builder", - "version": "0.1.16", + "version": "0.1.17", "license": "AGPL-3.0", "private": true, "scripts": { @@ -58,7 +58,7 @@ }, "dependencies": { "@budibase/bbui": "^1.23.1", - "@budibase/client": "^0.1.1", + "@budibase/client": "^0.1.17", "@budibase/colorpicker": "^1.0.1", "@nx-js/compiler-util": "^2.0.0", "@sentry/browser": "5.19.1", @@ -68,6 +68,7 @@ "d3-selection": "^1.4.1", "date-fns": "^1.29.0", "deepmerge": "^4.2.2", + "fast-sort": "^2.2.0", "feather-icons": "^4.21.0", "flatpickr": "^4.5.7", "lodash": "^4.17.13", @@ -98,6 +99,7 @@ "cypress-terminal-report": "^1.4.1", "eslint-plugin-cypress": "^2.11.1", "http-proxy-middleware": "^0.19.1", + "identity-obj-proxy": "^3.0.0", "jest": "^26.2.2", "ncp": "^2.0.0", "npm-run-all": "^4.1.5", diff --git a/packages/builder/src/builderStore/store/backend.js b/packages/builder/src/builderStore/store/backend.js index 393371ce85..28272d9893 100644 --- a/packages/builder/src/builderStore/store/backend.js +++ b/packages/builder/src/builderStore/store/backend.js @@ -61,10 +61,9 @@ export const getBackendUiStore = () => { state.draftModel = cloneDeep(model) state.selectedField = "" state.selectedView = `all_${model._id}` - state.tabs.SETUP_PANEL = "SETUP" return state }), - save: async ({ model }) => { + save: async model => { const updatedModel = cloneDeep(model) // update any renamed schema keys to reflect their names @@ -83,20 +82,35 @@ export const getBackendUiStore = () => { const savedModel = await response.json() await store.actions.models.fetch() store.actions.models.select(savedModel) + return savedModel }, - addField: field => { + delete: async model => { + await api.delete(`/api/models/${model._id}/${model._rev}`) store.update(state => { - if (!state.draftModel.schema) { - state.draftModel.schema = {} - } + state.models = state.models.filter( + existing => existing._id !== model._id + ) + state.selectedModel = state.models[0] || {} + return state + }) + }, + saveField: ({ originalName, field }) => { + store.update(state => { + // delete the original if renaming + delete state.draftModel.schema[originalName] state.draftModel.schema = { ...state.draftModel.schema, [field.name]: cloneDeep(field), } - state.selectedField = field.name - state.tabs.NAVIGATION_PANEL = "NAVIGATE" - + store.actions.models.save(state.draftModel) + return state + }) + }, + deleteField: field => { + store.update(state => { + delete state.draftModel.schema[field.name] + store.actions.models.save(state.draftModel) return state }) }, diff --git a/packages/builder/src/components/database/ModelDataTable/ModelDataTable.svelte b/packages/builder/src/components/database/ModelDataTable/ModelDataTable.svelte index bbd9d6d4a3..c7efd29253 100644 --- a/packages/builder/src/components/database/ModelDataTable/ModelDataTable.svelte +++ b/packages/builder/src/components/database/ModelDataTable/ModelDataTable.svelte @@ -1,38 +1,19 @@ - -
Edit | -Name | -Type | -- |
---|---|---|---|
- editField(meta)} /> - | -
- {key}
- |
- {meta.type} | -- deleteField(meta)} /> - | -
Before you can view your table, you need to set it up.
-Blocks are pre-made fields and help you build your table quicker.
-Blocks are pre-made fields and help you build your table quicker.
-Blocks are pre-made fields and help you build your table quicker.
-