diff --git a/cypress/fixtures/flows/dashboard-layouts.json b/cypress/fixtures/flows/dashboard-layouts.json new file mode 100644 index 000000000..45b6f6173 --- /dev/null +++ b/cypress/fixtures/flows/dashboard-layouts.json @@ -0,0 +1,184 @@ +[ + { + "id": "dashboard-ui-base", + "type": "ui-base", + "name": "UI Name", + "path": "/dashboard", + "includeClientData": true, + "acceptsClientConfig": [ + "ui-notification", + "ui-control" + ] + }, + { + "id": "dashboard-ui-page-grid", + "type": "ui-page", + "name": "Layout: Grid", + "ui": "dashboard-ui-base", + "path": "/grid", + "icon": "", + "layout": "grid", + "theme": "dashboard-ui-theme", + "order": 2, + "className": "", + "visible": "true", + "disabled": false + }, + { + "id": "dashboard-ui-page-fixed", + "type": "ui-page", + "name": "Layout: Fixed", + "ui": "dashboard-ui-base", + "path": "/fixed", + "icon": "", + "layout": "flex", + "theme": "dashboard-ui-theme", + "order": 1, + "className": "", + "visible": "true", + "disabled": false + }, + { + "id": "dashboard-ui-page-notebook", + "type": "ui-page", + "name": "Layout: Notebook", + "ui": "dashboard-ui-base", + "path": "/notebook", + "icon": "", + "layout": "notebook", + "theme": "dashboard-ui-theme", + "order": 1, + "className": "", + "visible": "true", + "disabled": false + }, + { + "id": "dashboard-ui-theme", + "type": "ui-theme", + "name": "Theme Name", + "colors": { + "surface": "#ffffff", + "primary": "#0094ce", + "bgPage": "#eeeeee", + "groupBg": "#ffffff", + "groupOutline": "#cccccc" + } + }, + { + "id": "dashboard-ui-group-grid1", + "type": "ui-group", + "name": "Order 1", + "page": "dashboard-ui-page-grid", + "width": "6", + "height": "1", + "order": 1, + "showTitle": true, + "className": "", + "visible": "true", + "disabled": "false" + }, + { + "id": "dashboard-ui-group-grid2", + "type": "ui-group", + "name": "Order 2", + "page": "dashboard-ui-page-grid", + "width": "6", + "height": "1", + "order": 2, + "showTitle": true, + "className": "", + "visible": "true", + "disabled": "false" + }, + { + "id": "dashboard-ui-group-grid3", + "type": "ui-group", + "name": "Order 3", + "page": "dashboard-ui-page-grid", + "width": "6", + "height": "1", + "order": 3, + "showTitle": true, + "className": "", + "visible": "true", + "disabled": "false" + }, + { + "id": "dashboard-ui-group-fixed1", + "type": "ui-group", + "name": "Order 1", + "page": "dashboard-ui-page-fixed", + "width": "6", + "height": "1", + "order": 1, + "showTitle": true, + "className": "", + "visible": "true", + "disabled": "false" + }, + { + "id": "dashboard-ui-group-fixed2", + "type": "ui-group", + "name": "Order 2", + "page": "dashboard-ui-page-fixed", + "width": "6", + "height": "1", + "order": 2, + "showTitle": true, + "className": "", + "visible": "true", + "disabled": "false" + }, + { + "id": "dashboard-ui-group-fixed3", + "type": "ui-group", + "name": "Order 3", + "page": "dashboard-ui-page-fixed", + "width": "6", + "height": "1", + "order": 3, + "showTitle": true, + "className": "", + "visible": "true", + "disabled": "false" + }, + { + "id": "dashboard-ui-group-notebook1", + "type": "ui-group", + "name": "Order 1", + "page": "dashboard-ui-page-notebook", + "width": "6", + "height": "1", + "order": 1, + "showTitle": true, + "className": "", + "visible": "true", + "disabled": "false" + }, + { + "id": "dashboard-ui-group-notebook3", + "type": "ui-group", + "name": "Order 3", + "page": "dashboard-ui-page-notebook", + "width": "6", + "height": "1", + "order": 3, + "showTitle": true, + "className": "", + "visible": "true", + "disabled": "false" + }, + { + "id": "dashboard-ui-group-notebook2", + "type": "ui-group", + "name": "Order 2", + "page": "dashboard-ui-page-notebook", + "width": "6", + "height": "1", + "order": 2, + "showTitle": true, + "className": "", + "visible": "true", + "disabled": "false" + } +] \ No newline at end of file diff --git a/cypress/tests/layouts.spec.js b/cypress/tests/layouts.spec.js new file mode 100644 index 000000000..a327c33d5 --- /dev/null +++ b/cypress/tests/layouts.spec.js @@ -0,0 +1,41 @@ +// test admin rights & access in FlowForge + +describe('Node-RED Dashboard 2.0 - Layout: Grid', () => { + beforeEach(() => { + cy.deployFixture('dashboard-layouts') + cy.visit('/dashboard/grid') + }) + + it('should render groups in the correct order', () => { + cy.get('.nrdb-ui-group').should('have.length', 3) + cy.get('.nrdb-ui-group').eq(0).should('have.text', 'Order 1') + cy.get('.nrdb-ui-group').eq(1).should('have.text', 'Order 2') + cy.get('.nrdb-ui-group').eq(2).should('have.text', 'Order 3') + }) +}) +describe('Node-RED Dashboard 2.0 - Layout: Fixed', () => { + beforeEach(() => { + cy.deployFixture('dashboard-layouts') + cy.visit('/dashboard/fixed') + }) + + it('should render groups in the correct order', () => { + cy.get('.nrdb-ui-group').should('have.length', 3) + cy.get('.nrdb-ui-group').eq(0).should('have.text', 'Order 1') + cy.get('.nrdb-ui-group').eq(1).should('have.text', 'Order 2') + cy.get('.nrdb-ui-group').eq(2).should('have.text', 'Order 3') + }) +}) +describe('Node-RED Dashboard 2.0 - Layout: Notebook', () => { + beforeEach(() => { + cy.deployFixture('dashboard-layouts') + cy.visit('/dashboard/notebook') + }) + + it('should render groups in the correct order', () => { + cy.get('.nrdb-ui-group').should('have.length', 3) + cy.get('.nrdb-ui-group').eq(0).should('have.text', 'Order 1') + cy.get('.nrdb-ui-group').eq(1).should('have.text', 'Order 2') + cy.get('.nrdb-ui-group').eq(2).should('have.text', 'Order 3') + }) +}) diff --git a/nodes/config/ui_base.html b/nodes/config/ui_base.html index 57deee8d0..efef6a551 100644 --- a/nodes/config/ui_base.html +++ b/nodes/config/ui_base.html @@ -903,6 +903,9 @@ * @param {DashboardItemLookup} widgetsByGroup - The lookup of widgets by group */ function addGroupOrderingList (pageId, container, groups, widgetsByGroup) { + // sort groups by order + groups.sort((a, b) => a.order - b.order) + // ordered list of groups to live within a container (e.g. page list item) const groupsOL = $('
    ', { class: 'nrdb2-sb-group-list' }).appendTo(container).editableList({ sortable: '.nrdb2-sb-groups-list-header', @@ -936,6 +939,11 @@ titleRow.click(titleToggle(group.id, widgetsList, chevron)) addWidgetToList(group.id, widgetsList, widgets) + + const events = [] + updateItemOrder(groupsOL.editableList('items'), events) + // add our changes to NR history and trigger whether or not we need to redeploy + recordEvents(events) }, sortItems: function (items) { // track any changes diff --git a/ui/src/layouts/Flex.vue b/ui/src/layouts/Flex.vue index f7de7b99f..e96273b86 100644 --- a/ui/src/layouts/Flex.vue +++ b/ui/src/layouts/Flex.vue @@ -65,6 +65,9 @@ export default { } return true }) + .sort((a, b) => { + return a.order - b.order + }) return groups }, pageWidgets: function () { diff --git a/ui/src/layouts/Grid.vue b/ui/src/layouts/Grid.vue index 363ab8fba..1aa5065a4 100644 --- a/ui/src/layouts/Grid.vue +++ b/ui/src/layouts/Grid.vue @@ -68,6 +68,9 @@ export default { } return true }) + .sort((a, b) => { + return a.order - b.order + }) return groups }, pageWidgets: function () { diff --git a/ui/src/layouts/Notebook.vue b/ui/src/layouts/Notebook.vue index 1af66fc1d..15875500b 100644 --- a/ui/src/layouts/Notebook.vue +++ b/ui/src/layouts/Notebook.vue @@ -64,6 +64,9 @@ export default { } return true }) + .sort((a, b) => { + return a.order - b.order + }) return groups }, pageWidgets: function () {