From 042f98bcc5cc5886e0d0e5ce19483fb760b58cf8 Mon Sep 17 00:00:00 2001 From: Shariq Ansari <30859809+shariquerik@users.noreply.github.com> Date: Fri, 22 Apr 2022 18:00:44 +0530 Subject: [PATCH] fix: Workspace Miscellaneous fixes (#16578) --- cypress/integration/workspace.js | 113 ++++++++++++++++-- frappe/desk/doctype/workspace/workspace.py | 29 ++++- frappe/public/js/frappe/form/toolbar.js | 2 +- .../js/frappe/views/workspace/blocks/block.js | 2 +- .../js/frappe/views/workspace/blocks/card.js | 2 +- .../js/frappe/views/workspace/blocks/chart.js | 2 +- .../views/workspace/blocks/onboarding.js | 2 +- .../frappe/views/workspace/blocks/shortcut.js | 2 +- .../public/js/frappe/widgets/widget_dialog.js | 45 +++---- 9 files changed, 159 insertions(+), 40 deletions(-) diff --git a/cypress/integration/workspace.js b/cypress/integration/workspace.js index fbff451305..a12d86b3d6 100644 --- a/cypress/integration/workspace.js +++ b/cypress/integration/workspace.js @@ -2,7 +2,6 @@ context('Workspace 2.0', () => { before(() => { cy.visit('/login'); cy.login(); - cy.visit('/app/website'); }); it('Navigate to page from sidebar', () => { @@ -13,6 +12,11 @@ context('Workspace 2.0', () => { }); it('Create Private Page', () => { + cy.intercept({ + method: 'POST', + url: 'api/method/frappe.desk.doctype.workspace.workspace.new_page' + }).as('new_page'); + cy.get('.codex-editor__redactor .ce-block'); cy.get('.custom-actions button[data-label="Create%20Workspace"]').click(); cy.fill_field('title', 'Test Private Page', 'Data'); @@ -27,12 +31,100 @@ context('Workspace 2.0', () => { cy.wait(300); cy.get('.sidebar-item-container[item-name="Test Private Page"]').should('have.attr', 'item-public', '0'); - cy.wait(500); + cy.wait('@new_page'); + }); + + it('Create Child Page', () => { + cy.intercept({ + method: 'POST', + url: 'api/method/frappe.desk.doctype.workspace.workspace.new_page' + }).as('new_page'); + + cy.get('.codex-editor__redactor .ce-block'); + cy.get('.custom-actions button[data-label="Create%20Workspace"]').click(); + cy.fill_field('title', 'Test Child Page', 'Data'); + cy.fill_field('parent', 'Test Private Page', 'Select'); + cy.fill_field('icon', 'edit', 'Icon'); + cy.get_open_dialog().find('.modal-header').click(); + cy.get_open_dialog().find('.btn-primary').click(); + + // check if sidebar item is added in pubic section + cy.get('.sidebar-item-container[item-name="Test Child Page"]').should('have.attr', 'item-public', '0'); + + cy.get('.standard-actions .btn-primary[data-label="Save"]').click(); + cy.wait(300); + cy.get('.sidebar-item-container[item-name="Test Child Page"]').should('have.attr', 'item-public', '0'); + + cy.wait('@new_page'); + }); + + it('Duplicate Page', () => { + cy.intercept({ + method: 'POST', + url: 'api/method/frappe.desk.doctype.workspace.workspace.duplicate_page' + }).as('page_duplicated'); + cy.get('.codex-editor__redactor .ce-block'); cy.get('.standard-actions .btn-secondary[data-label=Edit]').click(); + + cy.get('.sidebar-item-container[item-name="Test Private Page"]').as('sidebar-item'); + + cy.get('@sidebar-item').find('.standard-sidebar-item').first().click(); + cy.get('@sidebar-item').find('.dropdown-btn').first().click(); + cy.get('@sidebar-item').find('.dropdown-list .dropdown-item').contains('Duplicate').first().click({force: true}); + + cy.get_open_dialog().fill_field('title', 'Duplicate Page', 'Data'); + cy.click_modal_primary_button('Duplicate'); + + cy.wait('@page_duplicated'); + }); + + it('Drag Sidebar Item', () => { + cy.intercept({ + method: 'POST', + url: 'api/method/frappe.desk.doctype.workspace.workspace.sort_pages' + }).as('page_sorted'); + + cy.get('.sidebar-item-container[item-name="Duplicate Page"]').as('sidebar-item'); + + cy.get('@sidebar-item').find('.standard-sidebar-item').first().click(); + cy.get('@sidebar-item').find('.drag-handle').first().move({ deltaX: 0, deltaY: 100 }); + + cy.get('.sidebar-item-container[item-name="Build"]').as('sidebar-item'); + + cy.get('@sidebar-item').find('.standard-sidebar-item').first().click(); + cy.get('@sidebar-item').find('.drag-handle').first().move({ deltaX: 0, deltaY: 100 }); + + cy.wait('@page_sorted'); + }); + + it('Edit Page Detail', () => { + cy.intercept({ + method: 'POST', + url: 'api/method/frappe.desk.doctype.workspace.workspace.update_page' + }).as('page_updated'); + + cy.get('.sidebar-item-container[item-name="Test Private Page"]').as('sidebar-item'); + + cy.get('@sidebar-item').find('.standard-sidebar-item').first().click(); + cy.get('@sidebar-item').find('.dropdown-btn').first().click(); + cy.get('@sidebar-item').find('.dropdown-list .dropdown-item').contains('Edit').first().click({force: true}); + + cy.get_open_dialog().fill_field('title', ' 1', 'Data'); + cy.get_open_dialog().find('input[data-fieldname="is_public"]').check(); + cy.click_modal_primary_button('Update'); + + cy.get('.standard-sidebar-section:first .sidebar-item-container[item-name="Test Private Page"]').should('not.exist'); + cy.get('.standard-sidebar-section:last .sidebar-item-container[item-name="Test Private Page 1"]').should('exist'); + + cy.wait('@page_updated'); }); it('Add New Block', () => { + cy.get('.sidebar-item-container[item-name="Duplicate Page"]').as('sidebar-item'); + + cy.get('@sidebar-item').find('.standard-sidebar-item').first().click(); + cy.get('.ce-block').click().type('{enter}'); cy.get('.block-list-container .block-list-item').contains('Heading').click(); cy.get(":focus").type('Header'); @@ -70,19 +162,24 @@ context('Workspace 2.0', () => { cy.get('.standard-actions .btn-primary[data-label="Save"]').click(); }); - it('Delete Private Page', () => { + it('Delete Duplicate Page', () => { + cy.intercept({ + method: 'POST', + url: 'api/method/frappe.desk.doctype.workspace.workspace.delete_page' + }).as('page_deleted'); + cy.get('.codex-editor__redactor .ce-block'); cy.get('.standard-actions .btn-secondary[data-label=Edit]').click(); - cy.get('.sidebar-item-container[item-name="Test Private Page"]') + cy.get('.sidebar-item-container[item-name="Duplicate Page"]') .find('.sidebar-item-control .setting-btn').click(); - cy.get('.sidebar-item-container[item-name="Test Private Page"]') + cy.get('.sidebar-item-container[item-name="Duplicate Page"]') .find('.dropdown-item[title="Delete Workspace"]').click({force: true}); cy.wait(300); cy.get('.modal-footer > .standard-actions > .btn-modal-primary:visible').first().click(); - cy.get('.standard-actions .btn-primary[data-label="Save"]').click(); - cy.get('.codex-editor__redactor .ce-block'); - cy.get('.sidebar-item-container[item-name="Test Private Page"]').should('not.exist'); + cy.get('.sidebar-item-container[item-name="Duplicate Page"]').should('not.exist'); + + cy.wait('@page_deleted'); }); }); \ No newline at end of file diff --git a/frappe/desk/doctype/workspace/workspace.py b/frappe/desk/doctype/workspace/workspace.py index a2dbcbfbe2..284fecbe31 100644 --- a/frappe/desk/doctype/workspace/workspace.py +++ b/frappe/desk/doctype/workspace/workspace.py @@ -80,7 +80,14 @@ class Workspace(Document): # remove duplicate before adding for idx, link in enumerate(self.links): - if link.label == card.get("label") and link.type == "Card Break": + if link.get("label") == card.get("label") and link.get("type") == "Card Break": + # count and set number of links for the card if link_count is 0 + if link.link_count == 0: + for count, card_link in enumerate(self.links[idx + 1 :]): + if card_link.get("type") == "Card Break": + break + link.link_count = count + 1 + del self.links[idx : idx + link.link_count + 1] self.append( @@ -199,21 +206,31 @@ def update_page(name, title, icon, parent, public): doc.sequence_id = frappe.db.count("Workspace", {"public": public}, cache=True) doc.public = public doc.for_user = "" if public else doc.for_user or frappe.session.user - doc.label = "{0}-{1}".format(title, doc.for_user) if doc.for_user else title + doc.label = new_name = "{0}-{1}".format(title, doc.for_user) if doc.for_user else title doc.save(ignore_permissions=True) - if name != doc.label: - rename_doc("Workspace", name, doc.label, force=True, ignore_permissions=True) + if name != new_name: + rename_doc("Workspace", name, new_name, force=True, ignore_permissions=True) # update new name and public in child pages if child_docs: for child in child_docs: child_doc = frappe.get_doc("Workspace", child.name) child_doc.parent_page = doc.title - child_doc.public = doc.public + if child_doc.public != public: + child_doc.public = public + child_doc.for_user = "" if public else child_doc.for_user or frappe.session.user + child_doc.label = new_child_name = ( + "{0}-{1}".format(child_doc.title, child_doc.for_user) + if child_doc.for_user + else child_doc.title + ) child_doc.save(ignore_permissions=True) - return {"name": doc.title, "public": doc.public, "label": doc.label} + if child.name != new_child_name: + rename_doc("Workspace", child.name, new_child_name, force=True, ignore_permissions=True) + + return {"name": title, "public": public, "label": new_name} @frappe.whitelist() diff --git a/frappe/public/js/frappe/form/toolbar.js b/frappe/public/js/frappe/form/toolbar.js index e55eb9fdeb..6841640341 100644 --- a/frappe/public/js/frappe/form/toolbar.js +++ b/frappe/public/js/frappe/form/toolbar.js @@ -323,7 +323,7 @@ frappe.ui.form.Toolbar = class Toolbar { } // New - if(p[CREATE] && !this.frm.meta.issingle) { + if (p[CREATE] && !this.frm.meta.issingle && !this.frm.meta.in_create) { this.page.add_menu_item(__("New {0}", [__(me.frm.doctype)]), function() { frappe.new_doc(me.frm.doctype, true); }, true, { diff --git a/frappe/public/js/frappe/views/workspace/blocks/block.js b/frappe/public/js/frappe/views/workspace/blocks/block.js index 9605d30c81..1df6b707fe 100644 --- a/frappe/public/js/frappe/views/workspace/blocks/block.js +++ b/frappe/public/js/frappe/views/workspace/blocks/block.js @@ -7,7 +7,7 @@ export default class Block { make(block, block_name, widget_type = block) { let block_data = this.config.page_data[block+'s'].items.find(obj => { - return frappe.utils.unescape_html(obj.label) == frappe.utils.unescape_html(block_name); + return frappe.utils.unescape_html(obj.label) == frappe.utils.unescape_html(__(block_name)); }); if (!block_data) return false; this.wrapper.innerHTML = ''; diff --git a/frappe/public/js/frappe/views/workspace/blocks/card.js b/frappe/public/js/frappe/views/workspace/blocks/card.js index 9ce6ce8b4d..4b46b12890 100644 --- a/frappe/public/js/frappe/views/workspace/blocks/card.js +++ b/frappe/public/js/frappe/views/workspace/blocks/card.js @@ -31,7 +31,7 @@ export default class Card extends Block { this.new('card', 'links'); if (this.data && this.data.card_name) { - let has_data = this.make('card', __(this.data.card_name), 'links'); + let has_data = this.make('card', this.data.card_name, 'links'); if (!has_data) return; } diff --git a/frappe/public/js/frappe/views/workspace/blocks/chart.js b/frappe/public/js/frappe/views/workspace/blocks/chart.js index ccef1fa15f..cb688f48ed 100644 --- a/frappe/public/js/frappe/views/workspace/blocks/chart.js +++ b/frappe/public/js/frappe/views/workspace/blocks/chart.js @@ -32,7 +32,7 @@ export default class Chart extends Block { this.new('chart'); if (this.data && this.data.chart_name) { - let has_data = this.make('chart', __(this.data.chart_name)); + let has_data = this.make('chart', this.data.chart_name); if (!has_data) return; } diff --git a/frappe/public/js/frappe/views/workspace/blocks/onboarding.js b/frappe/public/js/frappe/views/workspace/blocks/onboarding.js index c0ba529853..c76141996f 100644 --- a/frappe/public/js/frappe/views/workspace/blocks/onboarding.js +++ b/frappe/public/js/frappe/views/workspace/blocks/onboarding.js @@ -73,7 +73,7 @@ export default class Onboarding extends Block { make(block, block_name) { let block_data = this.config.page_data['onboardings'].items.find(obj => { - return obj.label == block_name; + return obj.label == __(block_name); }); if (!block_data) return false; this.wrapper.innerHTML = ''; diff --git a/frappe/public/js/frappe/views/workspace/blocks/shortcut.js b/frappe/public/js/frappe/views/workspace/blocks/shortcut.js index 2be5da0d4b..ef9bfa8cf9 100644 --- a/frappe/public/js/frappe/views/workspace/blocks/shortcut.js +++ b/frappe/public/js/frappe/views/workspace/blocks/shortcut.js @@ -51,7 +51,7 @@ export default class Shortcut extends Block { this.new('shortcut'); if (this.data && this.data.shortcut_name) { - let has_data = this.make('shortcut', __(this.data.shortcut_name)); + let has_data = this.make('shortcut', this.data.shortcut_name); if (!has_data) return; } diff --git a/frappe/public/js/frappe/widgets/widget_dialog.js b/frappe/public/js/frappe/widgets/widget_dialog.js index d1ba75227b..bba29ffaf9 100644 --- a/frappe/public/js/frappe/widgets/widget_dialog.js +++ b/frappe/public/js/frappe/widgets/widget_dialog.js @@ -228,30 +228,35 @@ class CardDialog extends WidgetDialog { } process_data(data) { - data.links.map((item, idx) => { - let message = ''; - let row = idx+1; + let message = ''; - if (!item.link_type) { - message = "Following fields have missing values:

"; + frappe.throw({ + message: __(message), + title: __("Missing Values Required"), + indicator: 'orange' + }); + } data.label = data.label ? data.label : data.chart_name; return data;