From 236d4851e40ba7e5f1a0eb2ee265d427e6a9f496 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Mon, 23 Mar 2020 12:35:52 +0530 Subject: [PATCH 001/115] refactor: better customization options --- frappe/core/page/dashboard/dashboard.js | 8 ++++++- .../public/js/frappe/views/desktop/desktop.js | 24 ++++++++++++++++--- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/frappe/core/page/dashboard/dashboard.js b/frappe/core/page/dashboard/dashboard.js index 511aac7010..69e14f65e8 100644 --- a/frappe/core/page/dashboard/dashboard.js +++ b/frappe/core/page/dashboard/dashboard.js @@ -92,7 +92,13 @@ class Dashboard { container: this.container, type: "chart", columns: 2, - allow_sorting: false, + options: { + allow_sorting: false, + allow_create: false, + allow_delete: false, + allow_hiding: false, + allow_edit: false, + } widgets: this.charts, }); }); diff --git a/frappe/public/js/frappe/views/desktop/desktop.js b/frappe/public/js/frappe/views/desktop/desktop.js index 54a25c3771..c74443bcee 100644 --- a/frappe/public/js/frappe/views/desktop/desktop.js +++ b/frappe/public/js/frappe/views/desktop/desktop.js @@ -229,7 +229,13 @@ class DesktopPage { container: this.page, type: "chart", columns: 1, - allow_sorting: false, + options: { + allow_sorting: false, + allow_create: this.allow_customization, + allow_delete: this.allow_customization, + allow_hiding: false, + allow_edit: this.allow_customization, + }, widgets: this.data.charts.items }); } @@ -240,7 +246,13 @@ class DesktopPage { container: this.page, type: "bookmark", columns: 3, - allow_sorting: this.allow_customization && frappe.is_mobile(), + options: { + allow_sorting: this.allow_customization && frappe.is_mobile(), + allow_create: this.allow_customization, + allow_delete: this.allow_customization, + allow_hiding: false, + allow_edit: this.allow_customization, + }, widgets: this.data.shortcuts.items }); } @@ -251,7 +263,13 @@ class DesktopPage { container: this.page, type: "links", columns: 3, - allow_sorting: this.allow_customization && frappe.is_mobile(), + options: { + allow_sorting: this.allow_customization && frappe.is_mobile(), + allow_create: false, + allow_delete: false, + allow_hiding: this.allow_customization, + allow_edit: false, + }, widgets: this.data.cards.items }); From b71d8eb754211263b16b42b80560f2dccaf85619 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Mon, 23 Mar 2020 12:36:45 +0530 Subject: [PATCH 002/115] feat: added customization link --- .../public/js/frappe/views/desktop/desktop.js | 17 +++++++++++++ frappe/public/less/desktop.less | 24 +++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/frappe/public/js/frappe/views/desktop/desktop.js b/frappe/public/js/frappe/views/desktop/desktop.js index c74443bcee..d052d20b39 100644 --- a/frappe/public/js/frappe/views/desktop/desktop.js +++ b/frappe/public/js/frappe/views/desktop/desktop.js @@ -152,6 +152,16 @@ class DesktopPage { this.page.hide(); } + make_customization_link() { + this.customize_link = $(`
Customize Workspace
`); + this.customize_link.on('click', () => { + this.customize(); + }) + + this.customize_link.appendTo(this.page); + this.page.addClass('allow-customization'); + } + make() { this.make_page(); this.get_data().then(res => { @@ -164,6 +174,7 @@ class DesktopPage { } this.allow_customization = this.data.allow_customization || false; + this.allow_customization && this.make_customization_link(); !this.sections["onboarding"] && this.data.charts.items.length && @@ -223,6 +234,12 @@ class DesktopPage { }); } + customize() { + Object.keys(this.sections).forEach(section => { + this.sections[section].customize(); + }) + } + make_charts() { this.sections["charts"] = new frappe.widget.WidgetGroup({ title: this.data.charts.label || `${this.page_name} Dashboard`, diff --git a/frappe/public/less/desktop.less b/frappe/public/less/desktop.less index 9df4addf61..14d19aae88 100644 --- a/frappe/public/less/desktop.less +++ b/frappe/public/less/desktop.less @@ -76,6 +76,20 @@ position: relative; min-height: 1px; padding-right: 15px; + + .desk-page.allow-customization { + .customize-page { + text-align: right; + margin-top: 7px; + color: @text-muted; + cursor: pointer; + z-index: 99; + } + + .widget-group:nth-child(2) { + margin-top: -25px; + } + } } @media (max-width: 768px) { @@ -220,6 +234,16 @@ border-color: @disabled-background } + &.new-widget { + min-height: 65px; + background-color: @disabled-background; + color: @text-muted; + display: flex; + align-content: center; + justify-content: center; + cursor: pointer; + } + // Overrides for each widgets &.dashboard-widget-box { padding: 10px 15px !important; From e27e81e7ed3951dbb8a9efcb4b48533747cae901 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Mon, 23 Mar 2020 12:37:34 +0530 Subject: [PATCH 003/115] feat: added new widget class --- frappe/public/js/frappe/widgets/new_widget.js | 45 +++++++++++++++++ .../public/js/frappe/widgets/widget_group.js | 50 ++++++++++++------- 2 files changed, 76 insertions(+), 19 deletions(-) create mode 100644 frappe/public/js/frappe/widgets/new_widget.js diff --git a/frappe/public/js/frappe/widgets/new_widget.js b/frappe/public/js/frappe/widgets/new_widget.js new file mode 100644 index 0000000000..47af5c03fa --- /dev/null +++ b/frappe/public/js/frappe/widgets/new_widget.js @@ -0,0 +1,45 @@ +export default class NewWidget { + constructor(opts) { + Object.assign(this, opts); + this.make(); + window.wid = this; + } + + refresh() { + // + } + + customize() { + return + } + + make() { + this.make_widget(); + this.widget.appendTo(this.container); + this.setup_events(); + } + + make_widget() { + this.widget = $(`
+ + New +
`); + this.body = this.widget + this.set_body(); + } + + delete() { + this.widget.remove(); + } + + set_actions() { + // + } + + set_body() { + // + } + + setup_events() { + // + } +} \ No newline at end of file diff --git a/frappe/public/js/frappe/widgets/widget_group.js b/frappe/public/js/frappe/widgets/widget_group.js index 36fb2c9efc..18a9e3f88d 100644 --- a/frappe/public/js/frappe/widgets/widget_group.js +++ b/frappe/public/js/frappe/widgets/widget_group.js @@ -3,6 +3,7 @@ import BaseWidget from "../widgets/base_widget"; import ShortcutWidget from "../widgets/shortcut_widget"; import LinksWidget from "../widgets/links_widget"; import OnboardingWidget from "../widgets/onboarding_widget"; +import NewWidget from "../widgets/new_widget"; frappe.provide('frappe.widget') @@ -11,26 +12,15 @@ const widget_factory = { base: BaseWidget, bookmark: ShortcutWidget, links: LinksWidget, - onboarding: OnboardingWidget + onboarding: OnboardingWidget, + new: NewWidget }; export default class WidgetGroup { constructor(opts) { Object.assign(this, opts); - // opts = { - // title: "CRM Dashboard", - // container: $(''), - // widgets: [ - // {type: "dashboard", width: "Full", options: {}}. - // {type: "dashboard", width: "Full", options: {}} - // ], - // allow_delete: true, - // allow_create: true, - // allow_rearrange: true, - // hide_edit_option: false, - // collapsible: false - // } - window.wid_area = this; + this.widgets_list = []; + this.widgets_dict = {}; this.make(); } @@ -42,7 +32,7 @@ export default class WidgetGroup { refresh() { this.title && this.set_title(this.title); this.widgets && this.make_widgets(); - this.allow_sorting && this.setup_sortable(); + this.options.allow_sorting && this.setup_sortable(); } make_container() { @@ -70,13 +60,35 @@ export default class WidgetGroup { const widget_class = widget_factory[this.type]; this.widgets.forEach(widget => { - new widget_class({ + let widget_object = new widget_class({ ...widget, - container: this.body - }) + container: this.body, + on_delete: (name) => this.on_delete(name) + }); + this.widgets_list.push(widget_object); + this.widgets_dict[widget.name] = widget_object; }); } + customize() { + const options = { + delete: this.options.allow_delete, + sort: this.options.allow_sorting + } + + this.widgets_list.forEach(wid => { + wid.customize(options); + }) + + this.options.allow_create && new NewWidget({ + container: this.body + }) + } + + on_delete(name) { + this.widgets_list = this.widgets_list.filter(wid => name != wid.name) + } + setup_sortable() { const container = this.body[0]; this.sortable = new Sortable(container, { From 040af6844f1d16d524ce59c62a372e67cbf6cbd1 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Mon, 23 Mar 2020 13:07:33 +0530 Subject: [PATCH 004/115] feat: remove customize override for chart widget --- frappe/public/js/frappe/widgets/chart_widget.js | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/frappe/public/js/frappe/widgets/chart_widget.js b/frappe/public/js/frappe/widgets/chart_widget.js index 3388890776..bb8e412fa7 100644 --- a/frappe/public/js/frappe/widgets/chart_widget.js +++ b/frappe/public/js/frappe/widgets/chart_widget.js @@ -13,10 +13,6 @@ export default class ChartWidget extends Widget { this.make_chart(); } - customize() { - this.setup_customize_actions(); - } - set_body() { this.widget.addClass("dashboard-widget-box"); if (this.width == "Full") { @@ -79,13 +75,6 @@ export default class ChartWidget extends Widget { }); } - setup_customize_actions() { - this.action_area.empty(); - const buttons = $(` - `); - buttons.appendTo(this.action_area); - } - render_time_series_filters() { let filters = [ { From 3f30dbec053751d136ede3dbf0225e60698c56af Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Mon, 23 Mar 2020 15:41:48 +0530 Subject: [PATCH 005/115] feat: enable customize mode --- .../public/js/frappe/views/desktop/desktop.js | 32 ++++++++++++++++--- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/frappe/public/js/frappe/views/desktop/desktop.js b/frappe/public/js/frappe/views/desktop/desktop.js index d052d20b39..a51654f91b 100644 --- a/frappe/public/js/frappe/views/desktop/desktop.js +++ b/frappe/public/js/frappe/views/desktop/desktop.js @@ -141,6 +141,7 @@ class DesktopPage { this.page_name = page_name; this.sections = {}; this.allow_customization = false; + this.in_customize_mode = false; this.make(); } @@ -153,12 +154,27 @@ class DesktopPage { } make_customization_link() { - this.customize_link = $(`
Customize Workspace
`); + this.customize_link = $(`
Customize Workspace
`); + this.customize_link.appendTo(this.page); this.customize_link.on('click', () => { this.customize(); }) - this.customize_link.appendTo(this.page); + this.save_or_discard_link = $(`
+ Save / Discard +
`).hide(); + + this.save_or_discard_link.appendTo(this.page); + this.save_or_discard_link.find(".save-customization").on("click", () => { + console.log("Save Customization"); + }); + + this.save_or_discard_link.find(".discard-customization").on("click", () => { + this.in_customize_mode = false; + this.container.empty(); + this.make(); + }) + this.page.addClass('allow-customization'); } @@ -235,9 +251,17 @@ class DesktopPage { } customize() { + if (this.in_customize_mode) { + return + } + + this.customize_link.hide(); + this.save_or_discard_link.show(); + Object.keys(this.sections).forEach(section => { this.sections[section].customize(); }) + this.in_customize_mode = true; } make_charts() { @@ -264,7 +288,7 @@ class DesktopPage { type: "bookmark", columns: 3, options: { - allow_sorting: this.allow_customization && frappe.is_mobile(), + allow_sorting: this.allow_customization && !frappe.is_mobile(), allow_create: this.allow_customization, allow_delete: this.allow_customization, allow_hiding: false, @@ -281,7 +305,7 @@ class DesktopPage { type: "links", columns: 3, options: { - allow_sorting: this.allow_customization && frappe.is_mobile(), + allow_sorting: this.allow_customization && !frappe.is_mobile(), allow_create: false, allow_delete: false, allow_hiding: this.allow_customization, From c9eb03dce7de1f2cd22ae4d9a9c7707fcc0a2ef5 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Mon, 23 Mar 2020 15:42:13 +0530 Subject: [PATCH 006/115] feat: setup customize API for base widget --- .../public/js/frappe/widgets/base_widget.js | 58 +++++- .../public/js/frappe/widgets/widget_group.js | 23 ++- frappe/public/less/desktop.less | 180 ++++++++++++++++-- 3 files changed, 228 insertions(+), 33 deletions(-) diff --git a/frappe/public/js/frappe/widgets/base_widget.js b/frappe/public/js/frappe/widgets/base_widget.js index 7461f2ddc0..4064c34d01 100644 --- a/frappe/public/js/frappe/widgets/base_widget.js +++ b/frappe/public/js/frappe/widgets/base_widget.js @@ -10,14 +10,35 @@ export default class Widget { this.set_body(); } - customize() { + customize(options) { + this.action_area.empty(); + options.allow_delete && + this.add_custom_button( + '', + () => this.delete() + ); + options.allow_sorting && + this.add_custom_button( + '', + null, + "drag-handle" + ); + options.allow_hiding && + this.add_custom_button( + '', + () => this.hide() + ); + options.allow_edit && + this.add_custom_button( + '', + () => this.edit() + ); } make() { this.make_widget(); this.widget.appendTo(this.container); - this.setup_events(); } make_widget() { @@ -46,6 +67,33 @@ export default class Widget { this.title_field[0].innerHTML = this.label || this.name; } + add_custom_button(html, action, class_name = "") { + let button = $( + `` + ); + action && button.on("click", () => action()); + button.appendTo(this.action_area); + } + + delete() { + this.widget.addClass("zoomOutDelete"); + // wait for animation + setTimeout(() => { + this.widget.remove(); + this.on_delete && this.on_delete(this.name); + }, 300); + } + + edit() { + this.on_edit && this.on_edit(this.name); + } + + hide() { + this.body.css("opacity", 0.5); + this.title_field.css("opacity", 0.5); + this.footer.css("opacity", 0.5); + } + set_actions() { // } @@ -53,8 +101,4 @@ export default class Widget { set_body() { // } - - setup_events() { - // - } -} \ No newline at end of file +} diff --git a/frappe/public/js/frappe/widgets/widget_group.js b/frappe/public/js/frappe/widgets/widget_group.js index 18a9e3f88d..a34b1dc450 100644 --- a/frappe/public/js/frappe/widgets/widget_group.js +++ b/frappe/public/js/frappe/widgets/widget_group.js @@ -32,7 +32,6 @@ export default class WidgetGroup { refresh() { this.title && this.set_title(this.title); this.widgets && this.make_widgets(); - this.options.allow_sorting && this.setup_sortable(); } make_container() { @@ -63,7 +62,10 @@ export default class WidgetGroup { let widget_object = new widget_class({ ...widget, container: this.body, - on_delete: (name) => this.on_delete(name) + options: { + ...this.options, + on_delete: (name) => this.on_delete(name) + } }); this.widgets_list.push(widget_object); this.widgets_dict[widget.name] = widget_object; @@ -71,18 +73,16 @@ export default class WidgetGroup { } customize() { - const options = { - delete: this.options.allow_delete, - sort: this.options.allow_sorting - } - this.widgets_list.forEach(wid => { - wid.customize(options); + wid.customize(this.options); }) this.options.allow_create && new NewWidget({ - container: this.body + container: this.body, + type: this.type }) + + this.options.allow_sorting && this.setup_sortable(); } on_delete(name) { @@ -93,11 +93,10 @@ export default class WidgetGroup { const container = this.body[0]; this.sortable = new Sortable(container, { animation: 150, + handle: ".drag-handle", onEnd: () => { console.log("Sorting") - }, - // onChoose: (evt) => this.sortable_config.on_choose(evt, container), - // onStart: (evt) => this.sortable_config.on_start(evt, container) + }, // onStart: (evt) => this.sortable_config.on_start(evt, container) }); } } diff --git a/frappe/public/less/desktop.less b/frappe/public/less/desktop.less index 14d19aae88..7d7643ec3e 100644 --- a/frappe/public/less/desktop.less +++ b/frappe/public/less/desktop.less @@ -78,15 +78,23 @@ padding-right: 15px; .desk-page.allow-customization { - .customize-page { + .customize-options { text-align: right; margin-top: 7px; color: @text-muted; - cursor: pointer; z-index: 99; + + .save-customization { + cursor: pointer; + color: @text-color; + } + + .discard-customization { + cursor: pointer; + } } - .widget-group:nth-child(2) { + .widget-group:nth-child(3) { margin-top: -25px; } } @@ -104,6 +112,9 @@ .widget-group { margin-bottom: 25px; + // -webkit-animation-name: slideInUp; + // animation-name: slideInUp; + // animation-duration: 0.4s; .widget-group-head { display: flex; @@ -215,6 +226,17 @@ margin-left: 5px; } + .drag-handle { + cursor: all-scroll; + cursor: -webkit-grabbing; + + &:active { + cursor: grabbing; + cursor: -moz-grabbing; + cursor: -webkit-grabbing; + } + } + .dashboard-date-field { .clearfix, .help-box { @@ -381,23 +403,153 @@ border-radius: 10px; } -.pill-green { - background: #71b92c; - // color: #000; +@-webkit-keyframes smallBounce { + from, + 20%, + 53%, + 80%, + to { + -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + + 40%, + 43% { + -webkit-animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06); + animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06); + -webkit-transform: translate3d(0, -12px, 0); + transform: translate3d(0, -12px, 0); + } + + 70% { + -webkit-animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06); + animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06); + -webkit-transform: translate3d(0, -6px, 0); + transform: translate3d(0, -6px, 0); + } + + 90% { + -webkit-transform: translate3d(0, -4px, 0); + transform: translate3d(0, -4px, 0); + } } -.pill-red { - background: @red; +@keyframes smallBounce { + from, + 20%, + 53%, + 80%, + to { + -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + + 40%, + 43% { + -webkit-animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06); + animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06); + -webkit-transform: translate3d(0, -12px, 0); + transform: translate3d(0, -12px, 0); + } + + 70% { + -webkit-animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06); + animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06); + -webkit-transform: translate3d(0, -6px, 0); + transform: translate3d(0, -6px, 0); + } + + 90% { + -webkit-transform: translate3d(0, -4px, 0); + transform: translate3d(0, -4px, 0); + } } -.pill-blue { - background: @blue; +.small-bounce { + -webkit-animation-name: smallBounce; + animation-name: smallBounce; + -webkit-transform-origin: center bottom; + transform-origin: center bottom; + animation-duration: 1s; } -.pill-yellow { - background: @yellow; +@-webkit-keyframes slideInUp { + from { + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + visibility: visible; + } + + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } } -.pill-orange { - background: @orange; +@keyframes slideInUp { + from { + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + visibility: visible; + } + + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +.slide-in-up { + -webkit-animation-name: slideInUp; + animation-name: slideInUp; + animation-duration: 1s; +} + + +@-webkit-keyframes pulse { + from { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } + + 50% { + -webkit-transform: scale3d(1.05, 1.05, 1.05); + transform: scale3d(1.05, 1.05, 1.05); + } + + to { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } +} + +@keyframes pulse { + from { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } + + 50% { + -webkit-transform: scale3d(1.05, 1.05, 1.05); + transform: scale3d(1.05, 1.05, 1.05); + } + + to { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } +} + +.zoomOutDelete { + // -webkit-animation-name: zoomOut; + // animation-name: zoomOut; + // animation-duration: 1s; + transition: opacity 0.2s, visibility 0.2s, transform 0.2s; + transform: scale3d(0.5, 0.5, 0.5); + opacity: 0; + visibility: hidden; } \ No newline at end of file From 44d6c87335276b53db1f78d3834f74a29b7c85de Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Thu, 26 Mar 2020 13:51:03 +0530 Subject: [PATCH 007/115] feat: widget config API for saving customizations --- .../public/js/frappe/widgets/widget_group.js | 35 ++++++++++++++++--- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/frappe/public/js/frappe/widgets/widget_group.js b/frappe/public/js/frappe/widgets/widget_group.js index a34b1dc450..249dabf008 100644 --- a/frappe/public/js/frappe/widgets/widget_group.js +++ b/frappe/public/js/frappe/widgets/widget_group.js @@ -21,6 +21,7 @@ export default class WidgetGroup { Object.assign(this, opts); this.widgets_list = []; this.widgets_dict = {}; + this.widget_order = []; this.make(); } @@ -86,7 +87,19 @@ export default class WidgetGroup { } on_delete(name) { - this.widgets_list = this.widgets_list.filter(wid => name != wid.name) + this.widgets_list = this.widgets_list.filter(wid => name != wid.name); + delete this.widgets_dict[name]; + this.update_widget_order(); + } + + update_widget_order() { + this.widget_order = []; + this.body.children().each((index, element) => { + let name = element.dataset.widgetName; + if (name) { + this.widget_order.push(name); + } + }) } setup_sortable() { @@ -94,11 +107,25 @@ export default class WidgetGroup { this.sortable = new Sortable(container, { animation: 150, handle: ".drag-handle", - onEnd: () => { - console.log("Sorting") - }, // onStart: (evt) => this.sortable_config.on_start(evt, container) + onEnd: () => this.update_widget_order(), }); } + + get_widget_config() { + this.update_widget_order(); + let prepared_dict = {}; + + this.widgets_list.forEach(wid => { + let config = wid.get_config() + let name = config.docname ? config.docname : config.name + prepared_dict[name] = config + }); + + return { + order: this.widget_order, + widgets: prepared_dict + } + } } frappe.widget.WidgetGroup = WidgetGroup; \ No newline at end of file From b1720604bdf23780bf283846eaff72e996f8aa80 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Thu, 26 Mar 2020 13:51:50 +0530 Subject: [PATCH 008/115] refactor: save widget name as data attribute --- frappe/public/js/frappe/widgets/base_widget.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/frappe/public/js/frappe/widgets/base_widget.js b/frappe/public/js/frappe/widgets/base_widget.js index 4064c34d01..dea800e452 100644 --- a/frappe/public/js/frappe/widgets/base_widget.js +++ b/frappe/public/js/frappe/widgets/base_widget.js @@ -42,7 +42,9 @@ export default class Widget { } make_widget() { - this.widget = $(`
+ this.widget = $(`
From fb303febe683f9a81bb74566a107a2cbac90c900 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Thu, 26 Mar 2020 13:52:22 +0530 Subject: [PATCH 009/115] feat: get_config api to save customizations --- frappe/public/js/frappe/widgets/base_widget.js | 8 ++++++++ frappe/public/js/frappe/widgets/chart_widget.js | 9 +++++++++ frappe/public/js/frappe/widgets/links_widget.js | 10 ++++++++++ frappe/public/js/frappe/widgets/shortcut_widget.js | 14 ++++++++++++++ 4 files changed, 41 insertions(+) diff --git a/frappe/public/js/frappe/widgets/base_widget.js b/frappe/public/js/frappe/widgets/base_widget.js index dea800e452..3e28d664da 100644 --- a/frappe/public/js/frappe/widgets/base_widget.js +++ b/frappe/public/js/frappe/widgets/base_widget.js @@ -10,6 +10,14 @@ export default class Widget { this.set_body(); } + get_config() { + return { + name: this.name, + docname: this.docname, + label: this.label, + } + } + customize(options) { this.action_area.empty(); diff --git a/frappe/public/js/frappe/widgets/chart_widget.js b/frappe/public/js/frappe/widgets/chart_widget.js index bb8e412fa7..18951689c9 100644 --- a/frappe/public/js/frappe/widgets/chart_widget.js +++ b/frappe/public/js/frappe/widgets/chart_widget.js @@ -9,6 +9,15 @@ export default class ChartWidget extends Widget { this.height = 240; } + get_config() { + return { + name: this.name, + docname: this.docname, + chart_name: this.chart_name, + label: this.label, + } + } + refresh() { this.make_chart(); } diff --git a/frappe/public/js/frappe/widgets/links_widget.js b/frappe/public/js/frappe/widgets/links_widget.js index e8012b03d8..951f386e19 100644 --- a/frappe/public/js/frappe/widgets/links_widget.js +++ b/frappe/public/js/frappe/widgets/links_widget.js @@ -10,6 +10,16 @@ export default class LinksWidget extends Widget { // } + get_config() { + return { + name: this.name, + docname: this.docname, + links: JSON.stringify(this.links), + label: this.label, + title: this.title, + } + } + set_body() { this.options = {}; this.options.links = this.links; diff --git a/frappe/public/js/frappe/widgets/shortcut_widget.js b/frappe/public/js/frappe/widgets/shortcut_widget.js index 81ab4f05e4..ad3ad05fdf 100644 --- a/frappe/public/js/frappe/widgets/shortcut_widget.js +++ b/frappe/public/js/frappe/widgets/shortcut_widget.js @@ -18,6 +18,20 @@ export default class ShortcutWidget extends Widget { // } + get_config() { + return { + name: this.name, + docname: this.docname, + icon: this.icon, + label: this.label, + format: this.format, + link_to: this.link_to, + restrict_to_domain: this.restrict_to_domain, + stats_filter: this.stats_filter, + type: this.type + } + } + setup_events() { this.widget.click(() => { let route = generate_route(this) From 3ae487544b239f8b4b194ecde787984291ea5822 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Thu, 26 Mar 2020 13:53:05 +0530 Subject: [PATCH 010/115] feat: customization handlers for widgets --- .../public/js/frappe/widgets/base_widget.js | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/frappe/public/js/frappe/widgets/base_widget.js b/frappe/public/js/frappe/widgets/base_widget.js index 3e28d664da..17e0d7d218 100644 --- a/frappe/public/js/frappe/widgets/base_widget.js +++ b/frappe/public/js/frappe/widgets/base_widget.js @@ -35,7 +35,7 @@ export default class Widget { options.allow_hiding && this.add_custom_button( '', - () => this.hide() + () => this.hide_or_show() ); options.allow_edit && this.add_custom_button( @@ -90,7 +90,8 @@ export default class Widget { // wait for animation setTimeout(() => { this.widget.remove(); - this.on_delete && this.on_delete(this.name); + this.options.on_delete + && this.options.on_delete(this.name); }, 300); } @@ -98,10 +99,18 @@ export default class Widget { this.on_edit && this.on_edit(this.name); } - hide() { - this.body.css("opacity", 0.5); - this.title_field.css("opacity", 0.5); - this.footer.css("opacity", 0.5); + hide_or_show() { + if (!this.hidden) { + this.body.css("opacity", 0.5); + this.title_field.css("opacity", 0.5); + this.footer.css("opacity", 0.5); + this.hidden = true; + } else { + this.body.css("opacity", 1); + this.title_field.css("opacity", 1); + this.footer.css("opacity", 1); + this.hidden = false; + } } set_actions() { From faeb7a6c3377725bc5565e2c5871021971c7232e Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Thu, 26 Mar 2020 13:53:43 +0530 Subject: [PATCH 011/115] feat: allow saving customizations --- .../public/js/frappe/views/desktop/desktop.js | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/frappe/public/js/frappe/views/desktop/desktop.js b/frappe/public/js/frappe/views/desktop/desktop.js index a51654f91b..0b51f07975 100644 --- a/frappe/public/js/frappe/views/desktop/desktop.js +++ b/frappe/public/js/frappe/views/desktop/desktop.js @@ -165,9 +165,7 @@ class DesktopPage {
`).hide(); this.save_or_discard_link.appendTo(this.page); - this.save_or_discard_link.find(".save-customization").on("click", () => { - console.log("Save Customization"); - }); + this.save_or_discard_link.find(".save-customization").on("click", () => this.save_customization()); this.save_or_discard_link.find(".discard-customization").on("click", () => { this.in_customize_mode = false; @@ -264,6 +262,19 @@ class DesktopPage { this.in_customize_mode = true; } + save_customization() { + const config = {}; + + if (this.sections.charts) config.charts = this.sections.charts.get_widget_config(); + if (this.sections.shortcuts) config.shortcuts = this.sections.shortcuts.get_widget_config(); + if (this.sections.cards) config.cards = this.sections.cards.get_widget_config(); + + return frappe.call('frappe.desk.desktop.save_customization', { + page: this.page_name, + config: config + }) + } + make_charts() { this.sections["charts"] = new frappe.widget.WidgetGroup({ title: this.data.charts.label || `${this.page_name} Dashboard`, @@ -275,7 +286,7 @@ class DesktopPage { allow_create: this.allow_customization, allow_delete: this.allow_customization, allow_hiding: false, - allow_edit: this.allow_customization, + allow_edit: false, }, widgets: this.data.charts.items }); @@ -292,7 +303,7 @@ class DesktopPage { allow_create: this.allow_customization, allow_delete: this.allow_customization, allow_hiding: false, - allow_edit: this.allow_customization, + allow_edit: false, }, widgets: this.data.shortcuts.items }); @@ -308,7 +319,7 @@ class DesktopPage { allow_sorting: this.allow_customization && !frappe.is_mobile(), allow_create: false, allow_delete: false, - allow_hiding: this.allow_customization, + allow_hiding: false, allow_edit: false, }, widgets: this.data.cards.items From d1ea9f9044a3a9656d66f411eda740e7fdd4911a Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Thu, 26 Mar 2020 13:54:16 +0530 Subject: [PATCH 012/115] feat: API to save customization and override default page for user --- frappe/desk/desktop.py | 193 +++++++++---------- frappe/desk/doctype/desk_page/desk_page.json | 26 ++- 2 files changed, 110 insertions(+), 109 deletions(-) diff --git a/frappe/desk/desktop.py b/frappe/desk/desktop.py index ef84114745..10f8db5b83 100644 --- a/frappe/desk/desktop.py +++ b/frappe/desk/desktop.py @@ -4,7 +4,7 @@ from __future__ import unicode_literals import frappe -import json +from json import loads, dumps from frappe import _, DoesNotExistError from frappe.boot import get_allowed_pages, get_allowed_reports from six import string_types @@ -13,10 +13,24 @@ from frappe.cache_manager import build_domain_restriced_doctype_cache, build_dom class Workspace: def __init__(self, page_name): self.page_name = page_name + self.extended_cards = [] + self.extended_charts = [] + self.extended_shortcuts = [] - def build_cache(self): - self.doc = frappe.get_doc("Desk Page", self.page_name) - self.get_pages_to_extend() + def get_page_for_user(self): + filters = { + 'extends': self.page_name, + 'for_user': frappe.session.user + } + pages = frappe.get_list("Desk Page", filters=filters) + if pages: + return frappe.get_doc("Desk Page", pages[0]) + else: + self.get_pages_to_extend() + return frappe.get_doc("Desk Page", self.page_name) + + def init(self): + self.doc = self.get_page_for_user() user = frappe.get_user() user.build_permissions() @@ -32,13 +46,11 @@ class Workspace: def get_pages_to_extend(self): pages = frappe.get_all("Desk Page", filters={ "extends": self.page_name, - 'restrict_to_domain': ['in', frappe.get_active_domains()] + 'restrict_to_domain': ['in', frappe.get_active_domains()], + 'for_user': '' }) pages = [frappe.get_doc("Desk Page", page['name']) for page in pages] - self.extended_cards = [] - self.extended_charts = [] - self.extended_shortcuts = [] for page in pages: self.extended_cards = self.extended_cards + page.cards @@ -111,7 +123,7 @@ class Workspace: for section in cards: new_items = [] if isinstance(section.links, string_types): - links = json.loads(section.links) + links = loads(section.links) else: links = section.links @@ -134,6 +146,7 @@ class Workspace: new_section = section.as_dict().copy() new_section["links"] = new_items new_section["label"] = section.title + new_section["docname"] = section.name new_data.append(new_section) return new_data @@ -147,6 +160,7 @@ class Workspace: for chart in charts: chart.label = chart.label if chart.label else chart.chart_name + chart.docname = chart.name all_charts.append(chart) return all_charts @@ -166,6 +180,7 @@ class Workspace: for item in shortcuts: new_item = item.as_dict().copy() + new_item['docname'] = item.name new_item['name'] = _(item.link_to) if self.is_item_allowed(item.link_to, item.type) and _in_active_domains(item): if item.type == "Page": @@ -193,7 +208,7 @@ def get_desktop_page(page): """ wspace = Workspace(page) try: - wspace.build_cache() + wspace.init() wspace.build_workspace() return { 'charts': wspace.charts, @@ -205,7 +220,7 @@ def get_desktop_page(page): except DoesNotExistError: if frappe.message_log: frappe.message_log.pop() - return None + return Nonee @frappe.whitelist() def get_desk_sidebar_items(): @@ -214,7 +229,9 @@ def get_desk_sidebar_items(): # don't get domain restricted pages filters = { 'restrict_to_domain': ['in', frappe.get_active_domains()], - 'extends_another_page': False + 'extends_another_page': 0, + 'is_standard': 1, + 'for_user': '' } if not frappe.local.conf.developer_mode: @@ -279,104 +296,72 @@ def get_custom_report_list(module): return out -def make_them_pages(): - """Helper function to make pages - """ - pages = [ - ('Desk', 'frappe', 'octicon octicon-calendar'), - ('Settings', 'frappe', 'octicon octicon-settings'), - ('Users and Permissions', 'frappe', 'octicon octicon-settings'), - ('Customization', 'frappe', 'octicon octicon-settings'), - ('Integrations', 'frappe', 'octicon octicon-globe'), - ('Core', 'frappe', 'octicon octicon-circuit-board'), - ('Website', 'frappe', 'octicon octicon-globe'), - ('Getting Started', 'erpnext', 'fa fa-check-square-o'), - ('Accounts', 'erpnext', 'octicon octicon-repo'), - ('Selling', 'erpnext', 'octicon octicon-tag'), - ('Buying', 'erpnext', 'octicon octicon-briefcase'), - ('Stock', 'erpnext', 'octicon octicon-package'), - ('Assets', 'erpnext', 'octicon octicon-database'), - ('Projects', 'erpnext', 'octicon octicon-rocket'), - ('CRM', 'erpnext', 'octicon octicon-broadcast'), - ('Support', 'erpnext', 'fa fa-check-square-o'), - ('HR', 'erpnext', 'octicon octicon-organization'), - ('Quality Management', 'erpnext', 'fa fa-check-square-o'), - ('Manufacturing', 'erpnext', 'octicon octicon-tools'), - ('Retail', 'erpnext', 'octicon octicon-credit-card'), - ('Education', 'erpnext', 'octicon octicon-mortar-board'), - ('Healthcare', 'erpnext', 'fa fa-heartbeat'), - ('Agriculture', 'erpnext', 'octicon octicon-globe'), - ('Non Profit', 'erpnext', 'octicon octicon-heart'), - ('Help', 'erpnext', 'octicon octicon-device-camera-video') - ] - - for page in pages: - print("Processing Page: {0}".format(page[0])) - make_them_cards(page[0], page[2]) - - -def make_them_cards(page_name, from_module=None, to_module=None, icon=None): - from frappe.desk.moduleview import get - - if not from_module: - from_module = page_name - - if not to_module: - to_module = page_name - - try: - modules = get(from_module)['data'] - except: - return - - # Find or make page doc - if frappe.db.exists("Desk Page", page_name): - page = frappe.get_doc("Desk Page", page_name) - print("--- Got Page: {0}".format(page.name)) +def get_custom_workspace_for_user(page): + filters = { + 'extends': page, + 'for_user': frappe.session.user + } + pages = frappe.get_list("Desk Page", filters=filters) + if pages: + return frappe.get_doc("Desk Page", pages[0]) else: - page = frappe.new_doc("Desk Page") - page.label = page_name - page.cards = [] - page.icon = icon - print("--- New Page: {0}".format(page.name)) + doc = frappe.new_doc("Desk Page") + doc.extends = page + doc.for_user = frappe.session.user + return doc - # Guess Which Module - if not to_module and frappe.db.exists("Module Def", page_name): - page.module = page_name - if to_module: - page.module = to_module - elif frappe.db.exists("Module Def", page_name): - page.module = page_name +@frappe.whitelist() +def save_customization(page, config): + original_page = frappe.get_doc("Desk Page", page) + page_doc = get_custom_workspace_for_user(page) - for data in modules: - # Create a New Card Child Doc - card = frappe.new_doc("Desk Card") + # Update field values + page_doc.charts_label = original_page.charts_label + page_doc.cards_label = original_page.cards_label + page_doc.shortcuts_label = original_page.shortcuts_label + page_doc.charts_label = original_page.charts_label + page_doc.icon = original_page.icon + page_doc.module = original_page.module + page_doc.developer_mode_only = original_page.developer_mode_only + page_doc.category = original_page.category - # Data clean up - for item in data['items']: - try: - del item['count'] - del item['incomplete_dependencies'] - except KeyError: - pass - # Set Child doc values - card.title = data['label'] - card.icon = data.get('icon') - # Pretty dump JSON - card.links = json.dumps(data['items'], indent=4, sort_keys=True) + config = frappe._dict(loads(config)) - # Set Parent attributes - card.parent = page.name - card.parenttype = page.doctype - card.parentfield = "cards" + page_doc.charts = prepare_widget(config.charts, "Desk Chart", "charts") + page_doc.shortcuts = prepare_widget(config.shortcuts, "Desk Shortcut", "shortcuts") + page_doc.cards = prepare_widget(config.cards, "Desk Card", "cards") - # Add cards to page doc - print("------- Adding Card: {0}".format(card.title)) - page.cards.append(card) + # Set label + page_doc.label = page + '-' + frappe.session.user - # End it all - page.save() - frappe.db.commit() - return \ No newline at end of file + if page_doc.is_new(): + page_doc.insert() + else: + page_doc.save() + +def prepare_widget(config, doctype, parentfield): + if not config: + return + order = config.get('order') + widgets = config.get('widgets') + prepare_widget_list = [] + for idx, name in enumerate(order): + wid_config = widgets[name].copy() + # Some cleanup + wid_config.pop("name", None) + wid_config.pop("docname", None) + + # New Doc + doc = frappe.new_doc(doctype) + doc.update(wid_config) + + # Manually Set IDX + doc.idx = idx + 1 + + # Set Parent Field + doc.parentfield = parentfield + + prepare_widget_list.append(doc) + return prepare_widget_list diff --git a/frappe/desk/doctype/desk_page/desk_page.json b/frappe/desk/doctype/desk_page/desk_page.json index 6bc33d1326..7e6baf221b 100644 --- a/frappe/desk/doctype/desk_page/desk_page.json +++ b/frappe/desk/doctype/desk_page/desk_page.json @@ -9,6 +9,7 @@ "field_order": [ "label", "extends", + "for_user", "module", "category", "restrict_to_domain", @@ -36,7 +37,6 @@ "fieldname": "label", "fieldtype": "Data", "label": "Name", - "length": 22, "unique": 1 }, { @@ -52,6 +52,7 @@ "options": "Desk Chart" }, { + "depends_on": "eval:!doc.extends_another_page || !doc.is_standard", "fieldname": "shortcuts", "fieldtype": "Table", "label": "Shortcuts", @@ -136,16 +137,19 @@ "search_index": 1 }, { + "depends_on": "eval:!doc.extends_another_page || !doc.is_standard", "fieldname": "charts_label", "fieldtype": "Data", "label": "Label" }, { + "depends_on": "eval:!doc.extends_another_page || !doc.is_standard", "fieldname": "shortcuts_label", "fieldtype": "Data", "label": "Label" }, { + "depends_on": "eval:!doc.extends_another_page || !doc.is_standard", "fieldname": "cards_label", "fieldtype": "Data", "label": "Label" @@ -166,24 +170,36 @@ "default": "0", "fieldname": "is_standard", "fieldtype": "Check", - "label": "Is Standard" + "in_list_view": 1, + "in_standard_filter": 1, + "label": "Is Standard", + "search_index": 1 }, { "default": "0", "fieldname": "extends_another_page", "fieldtype": "Check", - "label": "Extends Another Page" + "label": "Extends Another Page", + "search_index": 1 }, { "depends_on": "eval:doc.extends_another_page == 1", "fieldname": "extends", "fieldtype": "Link", + "in_standard_filter": 1, "label": "Extends", - "options": "Desk Page" + "options": "Desk Page", + "search_index": 1 + }, + { + "fieldname": "for_user", + "fieldtype": "Data", + "label": "For User", + "read_only": 1 } ], "links": [], - "modified": "2020-03-12 16:38:16.206732", + "modified": "2020-03-26 12:35:41.981432", "modified_by": "Administrator", "module": "Desk", "name": "Desk Page", From 3a57996b9afc932bbcaa0c569b74a545b7ebdf19 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Thu, 26 Mar 2020 14:53:15 +0530 Subject: [PATCH 013/115] feat: make get_desktop_page readonly --- frappe/desk/desktop.py | 1 + 1 file changed, 1 insertion(+) diff --git a/frappe/desk/desktop.py b/frappe/desk/desktop.py index 10f8db5b83..ae1ed35d70 100644 --- a/frappe/desk/desktop.py +++ b/frappe/desk/desktop.py @@ -196,6 +196,7 @@ class Workspace: return items @frappe.whitelist() +@frappe.read_only() def get_desktop_page(page): """Applies permissions, customizations and returns the configruration for a page on desk. From 5917677251c77e355ed6d0b8e0c4d16ce4f0e6b9 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Thu, 26 Mar 2020 14:53:33 +0530 Subject: [PATCH 014/115] refactor: rename bookmark to shortcut --- frappe/public/js/frappe/views/desktop/desktop.js | 2 +- frappe/public/js/frappe/widgets/widget_group.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frappe/public/js/frappe/views/desktop/desktop.js b/frappe/public/js/frappe/views/desktop/desktop.js index 0b51f07975..f00c053594 100644 --- a/frappe/public/js/frappe/views/desktop/desktop.js +++ b/frappe/public/js/frappe/views/desktop/desktop.js @@ -296,7 +296,7 @@ class DesktopPage { this.sections["shortcuts"] = new frappe.widget.WidgetGroup({ title: this.data.shortcuts.label || `Your Shortcuts`, container: this.page, - type: "bookmark", + type: "shortcut", columns: 3, options: { allow_sorting: this.allow_customization && !frappe.is_mobile(), diff --git a/frappe/public/js/frappe/widgets/widget_group.js b/frappe/public/js/frappe/widgets/widget_group.js index 249dabf008..c61d6d6747 100644 --- a/frappe/public/js/frappe/widgets/widget_group.js +++ b/frappe/public/js/frappe/widgets/widget_group.js @@ -10,7 +10,7 @@ frappe.provide('frappe.widget') const widget_factory = { chart: ChartWidget, base: BaseWidget, - bookmark: ShortcutWidget, + shortcut: ShortcutWidget, links: LinksWidget, onboarding: OnboardingWidget, new: NewWidget From 744cedcfcf0cb298dfcb85a8377a05e541867812 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Thu, 26 Mar 2020 14:54:04 +0530 Subject: [PATCH 015/115] chore: cleanup --- frappe/public/js/frappe/widgets/onboarding_widget.js | 1 - 1 file changed, 1 deletion(-) diff --git a/frappe/public/js/frappe/widgets/onboarding_widget.js b/frappe/public/js/frappe/widgets/onboarding_widget.js index ea9428972e..736af01cc5 100644 --- a/frappe/public/js/frappe/widgets/onboarding_widget.js +++ b/frappe/public/js/frappe/widgets/onboarding_widget.js @@ -3,7 +3,6 @@ import Widget from "./base_widget.js"; export default class OnboardingWidget extends Widget { constructor(opts) { super(opts); - window.onb = this; } refresh() { } From b4ebaa662bc0c8fca1a4222bc003f00dc1065cc7 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Thu, 26 Mar 2020 14:54:16 +0530 Subject: [PATCH 016/115] feat: create new widget dialog from child table meta --- frappe/public/js/frappe/widgets/new_widget.js | 53 +++++++++++++++---- .../public/js/frappe/widgets/widget_group.js | 42 +++++++++------ 2 files changed, 69 insertions(+), 26 deletions(-) diff --git a/frappe/public/js/frappe/widgets/new_widget.js b/frappe/public/js/frappe/widgets/new_widget.js index 47af5c03fa..18cd8fdd56 100644 --- a/frappe/public/js/frappe/widgets/new_widget.js +++ b/frappe/public/js/frappe/widgets/new_widget.js @@ -1,8 +1,12 @@ +const WIDGET_DOCTYPE_MAP = { + chart: "Desk Chart", + shortcut: "Desk Shortcut", +} + export default class NewWidget { constructor(opts) { Object.assign(this, opts); this.make(); - window.wid = this; } refresh() { @@ -19,27 +23,54 @@ export default class NewWidget { this.setup_events(); } + get_title() { + return __(`New ${frappe.utils.to_title_case(this.type)}`) + } + make_widget() { this.widget = $(`
- + New + + ${this.get_title()}
`); this.body = this.widget - this.set_body(); + } + + setup_events() { + this.widget.on('click', () => this.open_dialog()) } delete() { this.widget.remove(); } - set_actions() { - // - } + open_dialog() { + let doctype = WIDGET_DOCTYPE_MAP[this.type] - set_body() { - // - } + if (!doctype) { + console.log(`Could not find ${this.type}`) + } - setup_events() { - // + frappe.model.with_doctype(doctype, () => { + let new_dialog = new frappe.ui.Dialog({ + title: this.get_title(), + fields: frappe.get_meta(doctype).fields, + primary_action: (data) => { + if (this.type == 'chart' && !data.label) { + data.label = data.chart_name; + } + + if (this.type == 'shortcut') { + data.label = data.link_to; + } + + data.docname = frappe.utils.get_random(20); + + new_dialog.hide(); + this.on_create(data); + }, + primary_action_label: __("Add"), + }); + + new_dialog.show() + }); } } \ No newline at end of file diff --git a/frappe/public/js/frappe/widgets/widget_group.js b/frappe/public/js/frappe/widgets/widget_group.js index c61d6d6747..debef4f0e1 100644 --- a/frappe/public/js/frappe/widgets/widget_group.js +++ b/frappe/public/js/frappe/widgets/widget_group.js @@ -57,20 +57,25 @@ export default class WidgetGroup { make_widgets() { this.body.empty() + this.widgets.forEach(widget => { + this.add_widget(widget) + }); + } + + add_widget(widget) { const widget_class = widget_factory[this.type]; - this.widgets.forEach(widget => { - let widget_object = new widget_class({ - ...widget, - container: this.body, - options: { - ...this.options, - on_delete: (name) => this.on_delete(name) - } - }); - this.widgets_list.push(widget_object); - this.widgets_dict[widget.name] = widget_object; + let widget_object = new widget_class({ + ...widget, + container: this.body, + options: { + ...this.options, + on_delete: (name) => this.on_delete(name) + } }); + + this.widgets_list.push(widget_object); + this.widgets_dict[widget.name] = widget_object; } customize() { @@ -78,10 +83,17 @@ export default class WidgetGroup { wid.customize(this.options); }) - this.options.allow_create && new NewWidget({ - container: this.body, - type: this.type - }) + if (this.options.allow_create) { + this.new_widget = new NewWidget({ + container: this.body, + type: this.type, + on_create: (config) => { + this.new_widget.delete(); + this.add_widget(config); + this.customize(); + } + }) + } this.options.allow_sorting && this.setup_sortable(); } From 55a790cd63b27ce8b6d15abcd81f521a878dd44c Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Fri, 27 Mar 2020 12:12:01 +0530 Subject: [PATCH 017/115] feat: added check for hidden --- frappe/desk/doctype/desk_card/desk_card.json | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/frappe/desk/doctype/desk_card/desk_card.json b/frappe/desk/doctype/desk_card/desk_card.json index 4ccffd4f58..522911e804 100644 --- a/frappe/desk/doctype/desk_card/desk_card.json +++ b/frappe/desk/doctype/desk_card/desk_card.json @@ -5,8 +5,9 @@ "engine": "InnoDB", "field_order": [ "title", - "column_break_2", "icon", + "column_break_2", + "hidden", "section_break_3", "links" ], @@ -37,11 +38,17 @@ "fieldname": "icon", "fieldtype": "Data", "label": "Icon" + }, + { + "default": "0", + "fieldname": "hidden", + "fieldtype": "Check", + "label": "Hidden" } ], "istable": 1, "links": [], - "modified": "2020-02-03 12:40:42.595122", + "modified": "2020-03-27 12:05:00.545808", "modified_by": "Administrator", "module": "Desk", "name": "Desk Card", From 4585bbba006bd8a3e406bd11d08e4ca2fe812f44 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Fri, 27 Mar 2020 12:14:33 +0530 Subject: [PATCH 018/115] feat: reload desktop after save --- .../public/js/frappe/views/desktop/desktop.js | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/frappe/public/js/frappe/views/desktop/desktop.js b/frappe/public/js/frappe/views/desktop/desktop.js index f00c053594..1d4cdbf83d 100644 --- a/frappe/public/js/frappe/views/desktop/desktop.js +++ b/frappe/public/js/frappe/views/desktop/desktop.js @@ -142,6 +142,7 @@ class DesktopPage { this.sections = {}; this.allow_customization = false; this.in_customize_mode = false; + this.container.empty(); this.make(); } @@ -153,6 +154,12 @@ class DesktopPage { this.page.hide(); } + reload() { + this.in_customize_mode = false; + this.container.empty(); + this.make(); + } + make_customization_link() { this.customize_link = $(`
Customize Workspace
`); this.customize_link.appendTo(this.page); @@ -167,11 +174,7 @@ class DesktopPage { this.save_or_discard_link.appendTo(this.page); this.save_or_discard_link.find(".save-customization").on("click", () => this.save_customization()); - this.save_or_discard_link.find(".discard-customization").on("click", () => { - this.in_customize_mode = false; - this.container.empty(); - this.make(); - }) + this.save_or_discard_link.find(".discard-customization").on("click", () => this.reload()) this.page.addClass('allow-customization'); } @@ -269,9 +272,11 @@ class DesktopPage { if (this.sections.shortcuts) config.shortcuts = this.sections.shortcuts.get_widget_config(); if (this.sections.cards) config.cards = this.sections.cards.get_widget_config(); - return frappe.call('frappe.desk.desktop.save_customization', { + frappe.call('frappe.desk.desktop.save_customization', { page: this.page_name, config: config + }).then(res => { + this.reload(); }) } @@ -319,7 +324,7 @@ class DesktopPage { allow_sorting: this.allow_customization && !frappe.is_mobile(), allow_create: false, allow_delete: false, - allow_hiding: false, + allow_hiding: this.allow_customization, allow_edit: false, }, widgets: this.data.cards.items From 6b4a070ab39f4a086500dd9671e89719c39d22e6 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Fri, 27 Mar 2020 12:14:59 +0530 Subject: [PATCH 019/115] feat: allow hiding of link cards --- frappe/public/js/frappe/widgets/base_widget.js | 15 +++++++++++++-- frappe/public/js/frappe/widgets/links_widget.js | 1 + 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/frappe/public/js/frappe/widgets/base_widget.js b/frappe/public/js/frappe/widgets/base_widget.js index 17e0d7d218..c45bd3b5b9 100644 --- a/frappe/public/js/frappe/widgets/base_widget.js +++ b/frappe/public/js/frappe/widgets/base_widget.js @@ -26,17 +26,28 @@ export default class Widget { '', () => this.delete() ); + options.allow_sorting && this.add_custom_button( '', null, "drag-handle" ); - options.allow_hiding && + + if (options.allow_hiding) { + if (this.hidden) { + this.widget.removeClass('hidden') + this.body.css("opacity", 0.5); + this.title_field.css("opacity", 0.5); + this.footer.css("opacity", 0.5); + } + this.add_custom_button( '', () => this.hide_or_show() ); + } + options.allow_edit && this.add_custom_button( '', @@ -50,7 +61,7 @@ export default class Widget { } make_widget() { - this.widget = $(`
diff --git a/frappe/public/js/frappe/widgets/links_widget.js b/frappe/public/js/frappe/widgets/links_widget.js index 951f386e19..760fc0fd97 100644 --- a/frappe/public/js/frappe/widgets/links_widget.js +++ b/frappe/public/js/frappe/widgets/links_widget.js @@ -17,6 +17,7 @@ export default class LinksWidget extends Widget { links: JSON.stringify(this.links), label: this.label, title: this.title, + hidden: this.hidden, } } From c205eab1e85d9ead23c403df4f9d144fb5c2cbf0 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Fri, 27 Mar 2020 12:29:42 +0530 Subject: [PATCH 020/115] chore: formatting --- .../public/js/frappe/widgets/base_widget.js | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/frappe/public/js/frappe/widgets/base_widget.js b/frappe/public/js/frappe/widgets/base_widget.js index c45bd3b5b9..8ea5a66648 100644 --- a/frappe/public/js/frappe/widgets/base_widget.js +++ b/frappe/public/js/frappe/widgets/base_widget.js @@ -14,8 +14,8 @@ export default class Widget { return { name: this.name, docname: this.docname, - label: this.label, - } + label: this.label + }; } customize(options) { @@ -36,7 +36,7 @@ export default class Widget { if (options.allow_hiding) { if (this.hidden) { - this.widget.removeClass('hidden') + this.widget.removeClass("hidden"); this.body.css("opacity", 0.5); this.title_field.css("opacity", 0.5); this.footer.css("opacity", 0.5); @@ -44,7 +44,12 @@ export default class Widget { this.add_custom_button( '', - () => this.hide_or_show() + () => this.hide_or_show(), + "show-or-hide-button" + ); + + this.show_or_hide_button = this.action_area.find( + ".show-or-hide-button" ); } @@ -61,9 +66,9 @@ export default class Widget { } make_widget() { - this.widget = $(`
+ this.widget = $(`
@@ -101,8 +106,7 @@ export default class Widget { // wait for animation setTimeout(() => { this.widget.remove(); - this.options.on_delete - && this.options.on_delete(this.name); + this.options.on_delete && this.options.on_delete(this.name); }, 300); } From 3246715afa98cb8f845a1a6bf61dab63e60f730b Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Fri, 27 Mar 2020 12:29:54 +0530 Subject: [PATCH 021/115] feat: toggle button icon on show or hide --- frappe/public/js/frappe/widgets/base_widget.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/frappe/public/js/frappe/widgets/base_widget.js b/frappe/public/js/frappe/widgets/base_widget.js index 8ea5a66648..693cc24519 100644 --- a/frappe/public/js/frappe/widgets/base_widget.js +++ b/frappe/public/js/frappe/widgets/base_widget.js @@ -119,11 +119,19 @@ export default class Widget { this.body.css("opacity", 0.5); this.title_field.css("opacity", 0.5); this.footer.css("opacity", 0.5); + this.show_or_hide_button.empty(); + $(``).appendTo( + this.show_or_hide_button + ); this.hidden = true; } else { this.body.css("opacity", 1); this.title_field.css("opacity", 1); this.footer.css("opacity", 1); + this.show_or_hide_button.empty(); + $(``).appendTo( + this.show_or_hide_button + ); this.hidden = false; } } From 70127a058412d2d608025dd4333c626f37f3d49e Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Fri, 27 Mar 2020 12:33:15 +0530 Subject: [PATCH 022/115] feat: allow users to save customizations --- frappe/desk/desktop.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frappe/desk/desktop.py b/frappe/desk/desktop.py index ae1ed35d70..9954d593d7 100644 --- a/frappe/desk/desktop.py +++ b/frappe/desk/desktop.py @@ -338,9 +338,9 @@ def save_customization(page, config): page_doc.label = page + '-' + frappe.session.user if page_doc.is_new(): - page_doc.insert() + page_doc.insert(ignore_permissions=True) else: - page_doc.save() + page_doc.save(ignore_permissions=True) def prepare_widget(config, doctype, parentfield): if not config: From 102e871e6a988ddc960aecf4237351efcff1b0b8 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Fri, 27 Mar 2020 12:59:02 +0530 Subject: [PATCH 023/115] feat: allow adding widgets to empty groups --- .../public/js/frappe/views/desktop/desktop.js | 19 ++++++++++++++++--- .../public/js/frappe/widgets/widget_group.js | 6 ++---- frappe/public/less/desktop.less | 4 ---- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/frappe/public/js/frappe/views/desktop/desktop.js b/frappe/public/js/frappe/views/desktop/desktop.js index 1d4cdbf83d..2a23d8d8a4 100644 --- a/frappe/public/js/frappe/views/desktop/desktop.js +++ b/frappe/public/js/frappe/views/desktop/desktop.js @@ -144,6 +144,7 @@ class DesktopPage { this.in_customize_mode = false; this.container.empty(); this.make(); + window.page = this; } show() { @@ -194,10 +195,14 @@ class DesktopPage { this.allow_customization && this.make_customization_link(); !this.sections["onboarding"] && - this.data.charts.items.length && + this.data.charts.items && this.make_charts(); - this.data.shortcuts.items.length && this.make_shortcuts(); - this.data.cards.items.length && this.make_cards(); + this.data.shortcuts.items && this.make_shortcuts(); + this.data.cards.items && this.make_cards(); + if (this.allow_customization) { + // Move the widget group up to align with labels if customization is allowed + $('.desk-page .widget-group:visible:first').css('margin-top', '-25px'); + } }); } @@ -256,6 +261,11 @@ class DesktopPage { return } + // It may be possible the chart area is hidden since it has no widgets + // So the margin-top: -25px would be applied to the shortcut group + // We need to remove this as the chart group will be visible during customization + $('.desk-page .widget-group:visible:first').css('margin-top', '0px'); + this.customize_link.hide(); this.save_or_discard_link.show(); @@ -263,6 +273,9 @@ class DesktopPage { this.sections[section].customize(); }) this.in_customize_mode = true; + + // Move the widget group up to align with labels if customization is allowed + $('.desk-page .widget-group:visible:first').css('margin-top', '-25px'); } save_customization() { diff --git a/frappe/public/js/frappe/widgets/widget_group.js b/frappe/public/js/frappe/widgets/widget_group.js index debef4f0e1..28e47018df 100644 --- a/frappe/public/js/frappe/widgets/widget_group.js +++ b/frappe/public/js/frappe/widgets/widget_group.js @@ -27,10 +27,6 @@ export default class WidgetGroup { make() { this.make_container(); - this.refresh(); - } - - refresh() { this.title && this.set_title(this.title); this.widgets && this.make_widgets(); } @@ -48,6 +44,7 @@ export default class WidgetGroup { this.title_area = widget_area.find(".widget-group-title"); this.control_area = widget_area.find(".widget-group-control"); this.body = widget_area.find(".widget-group-body"); + !this.widgets.length && this.widget_area.hide(); widget_area.appendTo(this.container); } @@ -79,6 +76,7 @@ export default class WidgetGroup { } customize() { + this.widget_area.show(); this.widgets_list.forEach(wid => { wid.customize(this.options); }) diff --git a/frappe/public/less/desktop.less b/frappe/public/less/desktop.less index 7d7643ec3e..4699f94ccf 100644 --- a/frappe/public/less/desktop.less +++ b/frappe/public/less/desktop.less @@ -93,10 +93,6 @@ cursor: pointer; } } - - .widget-group:nth-child(3) { - margin-top: -25px; - } } } From d8b2b62b76ac37c8e03dccd92b18f3deab679281 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Fri, 27 Mar 2020 13:41:02 +0530 Subject: [PATCH 024/115] refactor: logic for toggling show hide button --- frappe/public/js/frappe/widgets/base_widget.js | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/frappe/public/js/frappe/widgets/base_widget.js b/frappe/public/js/frappe/widgets/base_widget.js index 693cc24519..7528a5a82a 100644 --- a/frappe/public/js/frappe/widgets/base_widget.js +++ b/frappe/public/js/frappe/widgets/base_widget.js @@ -41,9 +41,9 @@ export default class Widget { this.title_field.css("opacity", 0.5); this.footer.css("opacity", 0.5); } - + const classname = this.hidden ? 'fa fa-eye' : 'fa fa-eye-slash'; this.add_custom_button( - '', + ``, () => this.hide_or_show(), "show-or-hide-button" ); @@ -119,21 +119,19 @@ export default class Widget { this.body.css("opacity", 0.5); this.title_field.css("opacity", 0.5); this.footer.css("opacity", 0.5); - this.show_or_hide_button.empty(); - $(``).appendTo( - this.show_or_hide_button - ); this.hidden = true; } else { this.body.css("opacity", 1); this.title_field.css("opacity", 1); this.footer.css("opacity", 1); - this.show_or_hide_button.empty(); - $(``).appendTo( - this.show_or_hide_button - ); this.hidden = false; } + this.show_or_hide_button.empty(); + + const classname = this.hidden ? 'fa fa-eye' : 'fa fa-eye-slash'; + $(``).appendTo( + this.show_or_hide_button + ); } set_actions() { From 2e68fabe85b3e015fe276a599882838962d1ee31 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Fri, 27 Mar 2020 15:31:51 +0530 Subject: [PATCH 025/115] fix: call setup events after rendering --- frappe/public/js/frappe/widgets/base_widget.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/frappe/public/js/frappe/widgets/base_widget.js b/frappe/public/js/frappe/widgets/base_widget.js index 7528a5a82a..0ecb5a1de3 100644 --- a/frappe/public/js/frappe/widgets/base_widget.js +++ b/frappe/public/js/frappe/widgets/base_widget.js @@ -87,6 +87,7 @@ export default class Widget { this.set_title(); this.set_actions(); this.set_body(); + this.setup_events(); } set_title() { @@ -134,6 +135,10 @@ export default class Widget { ); } + setup_events() { + // + } + set_actions() { // } From e5dacb6e1a9693b44d7626413061c2dc565c60a2 Mon Sep 17 00:00:00 2001 From: prssanna Date: Mon, 30 Mar 2020 18:33:58 +0530 Subject: [PATCH 026/115] fix: add scroll to grid form --- frappe/public/less/form_grid.less | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/frappe/public/less/form_grid.less b/frappe/public/less/form_grid.less index 28f08635ba..ed457a9ce8 100644 --- a/frappe/public/less/form_grid.less +++ b/frappe/public/less/form_grid.less @@ -262,6 +262,11 @@ border-bottom: 1px solid @border-color; } +.grid-form-body { + max-height: 75vh; + overflow-y: auto; +} + .grid-header-toolbar { display: flow-root; } From 8f4a958b3d82561018759feb1b812f1c9b550e0a Mon Sep 17 00:00:00 2001 From: prssanna Date: Mon, 30 Mar 2020 18:34:46 +0530 Subject: [PATCH 027/115] fix: scroll back to row in case body is scrolled --- frappe/public/js/frappe/form/grid_row.js | 1 + 1 file changed, 1 insertion(+) diff --git a/frappe/public/js/frappe/form/grid_row.js b/frappe/public/js/frappe/form/grid_row.js index 0e36e671cc..7f6039a2a2 100644 --- a/frappe/public/js/frappe/form/grid_row.js +++ b/frappe/public/js/frappe/form/grid_row.js @@ -550,6 +550,7 @@ export default class GridRow { hide_form() { frappe.dom.unfreeze(); this.row.toggle(true); + frappe.utils.scroll_to(this.row); this.refresh(); if(cur_frm) cur_frm.cur_grid = null; this.wrapper.removeClass("grid-row-open"); From bf92c8a4040ba698fdaa0fd35fca8979dd2490f9 Mon Sep 17 00:00:00 2001 From: prssanna Date: Mon, 30 Mar 2020 19:08:24 +0530 Subject: [PATCH 028/115] refactor: add element_to_be_scrolled as parameter to frappe.utils.scroll_to --- frappe/public/js/frappe/form/grid_row_form.js | 1 + frappe/public/js/frappe/utils/utils.js | 14 ++++++++------ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/frappe/public/js/frappe/form/grid_row_form.js b/frappe/public/js/frappe/form/grid_row_form.js index 73f0856c08..47da96f4d7 100644 --- a/frappe/public/js/frappe/form/grid_row_form.js +++ b/frappe/public/js/frappe/form/grid_row_form.js @@ -9,6 +9,7 @@ export default class GridRowForm { var me = this; this.make_form(); this.form_area.empty(); + frappe.utils.scroll_to(0, false, 0, this.wrapper.find('.grid-form-body')) this.layout = new frappe.ui.form.Layout({ fields: this.row.docfields, diff --git a/frappe/public/js/frappe/utils/utils.js b/frappe/public/js/frappe/utils/utils.js index 278c80897e..dd2db371a1 100644 --- a/frappe/public/js/frappe/utils/utils.js +++ b/frappe/public/js/frappe/utils/utils.js @@ -122,9 +122,11 @@ Object.assign(frappe.utils, {

'); return content.html(); }, - scroll_to: function(element, animate, additional_offset) { + scroll_to: function(element, animate, additional_offset, element_to_be_scrolled) { + element_to_be_scrolled = element_to_be_scrolled || $("html, body"); + var y = 0; - if(element && typeof element==='number') { + if (element && typeof element==="number") { y = element; } else if(element) { var header_offset = $(".navbar").height() + $(".page-head").height(); @@ -136,14 +138,14 @@ Object.assign(frappe.utils, { } // already there - if(y==$('html, body').scrollTop()) { + if (y == element_to_be_scrolled.scrollTop()) { return; } - if (animate!==false) { - $("html, body").animate({ scrollTop: y }); + if (animate !== false) { + element_to_be_scrolled.animate({ scrollTop: y }); } else { - $(window).scrollTop(y); + element_to_be_scrolled.scrollTop(y); } }, From 10d2931a19215ae57d3b00e12f50952003f2ffc4 Mon Sep 17 00:00:00 2001 From: prssanna Date: Mon, 30 Mar 2020 19:08:47 +0530 Subject: [PATCH 029/115] fix: add offset --- frappe/public/js/frappe/form/grid_row.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/public/js/frappe/form/grid_row.js b/frappe/public/js/frappe/form/grid_row.js index 7f6039a2a2..8cb7d7d664 100644 --- a/frappe/public/js/frappe/form/grid_row.js +++ b/frappe/public/js/frappe/form/grid_row.js @@ -550,7 +550,7 @@ export default class GridRow { hide_form() { frappe.dom.unfreeze(); this.row.toggle(true); - frappe.utils.scroll_to(this.row); + frappe.utils.scroll_to(this.row, false, 15); this.refresh(); if(cur_frm) cur_frm.cur_grid = null; this.wrapper.removeClass("grid-row-open"); From 5fac84d613bb9ea17c70efe6a19f21cae29b126f Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Tue, 31 Mar 2020 13:31:03 +0530 Subject: [PATCH 030/115] feat: enable edit API for widgets --- .../public/js/frappe/views/desktop/desktop.js | 6 +-- .../public/js/frappe/widgets/base_widget.js | 39 ++++++++++++++++--- .../public/js/frappe/widgets/chart_widget.js | 1 + .../public/js/frappe/widgets/links_widget.js | 4 -- .../js/frappe/widgets/shortcut_widget.js | 4 -- 5 files changed, 37 insertions(+), 17 deletions(-) diff --git a/frappe/public/js/frappe/views/desktop/desktop.js b/frappe/public/js/frappe/views/desktop/desktop.js index 2a23d8d8a4..66c7ec8043 100644 --- a/frappe/public/js/frappe/views/desktop/desktop.js +++ b/frappe/public/js/frappe/views/desktop/desktop.js @@ -300,11 +300,11 @@ class DesktopPage { type: "chart", columns: 1, options: { - allow_sorting: false, + allow_sorting: this.allow_customization && !frappe.is_mobile(), allow_create: this.allow_customization, allow_delete: this.allow_customization, allow_hiding: false, - allow_edit: false, + allow_edit: true, }, widgets: this.data.charts.items }); @@ -321,7 +321,7 @@ class DesktopPage { allow_create: this.allow_customization, allow_delete: this.allow_customization, allow_hiding: false, - allow_edit: false, + allow_edit: true, }, widgets: this.data.shortcuts.items }); diff --git a/frappe/public/js/frappe/widgets/base_widget.js b/frappe/public/js/frappe/widgets/base_widget.js index 0ecb5a1de3..eaad7b75d5 100644 --- a/frappe/public/js/frappe/widgets/base_widget.js +++ b/frappe/public/js/frappe/widgets/base_widget.js @@ -8,6 +8,7 @@ export default class Widget { this.set_title(); this.set_actions(); this.set_body(); + this.setup_events(); } get_config() { @@ -84,10 +85,7 @@ export default class Widget { this.action_area = this.widget.find(".widget-control"); this.head = this.widget.find(".widget-head"); this.footer = this.widget.find(".widget-footer"); - this.set_title(); - this.set_actions(); - this.set_body(); - this.setup_events(); + this.refresh(); } set_title() { @@ -98,7 +96,10 @@ export default class Widget { let button = $( `` ); - action && button.on("click", () => action()); + button.click(event => { + event.stopPropagation(); + action && action(); + }); button.appendTo(this.action_area); } @@ -112,7 +113,33 @@ export default class Widget { } edit() { - this.on_edit && this.on_edit(this.name); + frappe.model.with_doctype(this.doctype, () => { + let new_dialog = new frappe.ui.Dialog({ + title: __("Edit"), + fields: frappe.get_meta(this.doctype).fields, + primary_action: (data) => { + if (this.doctype == 'Desk Chart' && !data.label) { + data.label = data.chart_name; + } + + if (this.doctype == 'Desk Shortcut') { + data.label = data.link_to; + } + + new_dialog.hide(); + console.log("DATA", data) + Object.assign(this, data); + this.set_title(); + this.set_actions(); + this.set_body(); + this.setup_events(); + }, + primary_action_label: __("Save"), + }); + + new_dialog.show(); + new_dialog.set_values(this.get_config()); + }); } hide_or_show() { diff --git a/frappe/public/js/frappe/widgets/chart_widget.js b/frappe/public/js/frappe/widgets/chart_widget.js index 18951689c9..382b0df746 100644 --- a/frappe/public/js/frappe/widgets/chart_widget.js +++ b/frappe/public/js/frappe/widgets/chart_widget.js @@ -19,6 +19,7 @@ export default class ChartWidget extends Widget { } refresh() { + super.refresh(); this.make_chart(); } diff --git a/frappe/public/js/frappe/widgets/links_widget.js b/frappe/public/js/frappe/widgets/links_widget.js index 760fc0fd97..dc2dc9e7f8 100644 --- a/frappe/public/js/frappe/widgets/links_widget.js +++ b/frappe/public/js/frappe/widgets/links_widget.js @@ -6,10 +6,6 @@ export default class LinksWidget extends Widget { super(opts); } - refresh() { - // - } - get_config() { return { name: this.name, diff --git a/frappe/public/js/frappe/widgets/shortcut_widget.js b/frappe/public/js/frappe/widgets/shortcut_widget.js index ad3ad05fdf..3b4aee668d 100644 --- a/frappe/public/js/frappe/widgets/shortcut_widget.js +++ b/frappe/public/js/frappe/widgets/shortcut_widget.js @@ -14,10 +14,6 @@ export default class ShortcutWidget extends Widget { super(opts); } - refresh() { - // - } - get_config() { return { name: this.name, From 481e292e416414ca6b330eecc8ba328c7e04d2bc Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Tue, 31 Mar 2020 13:31:23 +0530 Subject: [PATCH 031/115] refactor: use console.warn --- frappe/public/js/frappe/widgets/new_widget.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/public/js/frappe/widgets/new_widget.js b/frappe/public/js/frappe/widgets/new_widget.js index 18cd8fdd56..2c2ae1466d 100644 --- a/frappe/public/js/frappe/widgets/new_widget.js +++ b/frappe/public/js/frappe/widgets/new_widget.js @@ -46,7 +46,7 @@ export default class NewWidget { let doctype = WIDGET_DOCTYPE_MAP[this.type] if (!doctype) { - console.log(`Could not find ${this.type}`) + console.warn(`Could not find ${this.type}`) } frappe.model.with_doctype(doctype, () => { From a1259b4ada47cd452597d79743023d5c69c2d43a Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Tue, 31 Mar 2020 13:43:02 +0530 Subject: [PATCH 032/115] feat: use label field across widgets --- frappe/desk/doctype/desk_card/desk_card.json | 19 ++++++++++--------- .../desk/doctype/desk_chart/desk_chart.json | 2 +- .../doctype/desk_shortcut/desk_shortcut.json | 8 +++++++- .../public/js/frappe/widgets/base_widget.js | 2 +- 4 files changed, 19 insertions(+), 12 deletions(-) diff --git a/frappe/desk/doctype/desk_card/desk_card.json b/frappe/desk/doctype/desk_card/desk_card.json index 522911e804..8877ccd2bd 100644 --- a/frappe/desk/doctype/desk_card/desk_card.json +++ b/frappe/desk/doctype/desk_card/desk_card.json @@ -4,7 +4,7 @@ "doctype": "DocType", "engine": "InnoDB", "field_order": [ - "title", + "label", "icon", "column_break_2", "hidden", @@ -15,17 +15,11 @@ { "fieldname": "links", "fieldtype": "Code", + "in_list_view": 1, "label": "Links", "options": "JSON", "reqd": 1 }, - { - "fieldname": "title", - "fieldtype": "Data", - "in_list_view": 1, - "label": "Title", - "reqd": 1 - }, { "fieldname": "section_break_3", "fieldtype": "Section Break" @@ -44,11 +38,18 @@ "fieldname": "hidden", "fieldtype": "Check", "label": "Hidden" + }, + { + "fieldname": "label", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Label", + "reqd": 1 } ], "istable": 1, "links": [], - "modified": "2020-03-27 12:05:00.545808", + "modified": "2020-03-31 13:40:14.993872", "modified_by": "Administrator", "module": "Desk", "name": "Desk Card", diff --git a/frappe/desk/doctype/desk_chart/desk_chart.json b/frappe/desk/doctype/desk_chart/desk_chart.json index c3c9231353..09deefd59d 100644 --- a/frappe/desk/doctype/desk_chart/desk_chart.json +++ b/frappe/desk/doctype/desk_chart/desk_chart.json @@ -26,7 +26,7 @@ ], "istable": 1, "links": [], - "modified": "2020-03-20 10:04:13.992228", + "modified": "2020-03-31 13:33:13.128804", "modified_by": "Administrator", "module": "Desk", "name": "Desk Chart", diff --git a/frappe/desk/doctype/desk_shortcut/desk_shortcut.json b/frappe/desk/doctype/desk_shortcut/desk_shortcut.json index 6b57f250a9..9d2469f7fb 100644 --- a/frappe/desk/doctype/desk_shortcut/desk_shortcut.json +++ b/frappe/desk/doctype/desk_shortcut/desk_shortcut.json @@ -9,6 +9,7 @@ "icon", "column_break_4", "link_to", + "label", "restrict_to_domain", "is_query_report", "section_break_5", @@ -81,11 +82,16 @@ "fieldtype": "Link", "label": "Restrict to Domain", "options": "Domain" + }, + { + "fieldname": "label", + "fieldtype": "Data", + "label": "Label" } ], "istable": 1, "links": [], - "modified": "2020-03-11 13:09:00.180528", + "modified": "2020-03-31 13:41:49.802777", "modified_by": "Administrator", "module": "Desk", "name": "Desk Shortcut", diff --git a/frappe/public/js/frappe/widgets/base_widget.js b/frappe/public/js/frappe/widgets/base_widget.js index eaad7b75d5..4ac464c22e 100644 --- a/frappe/public/js/frappe/widgets/base_widget.js +++ b/frappe/public/js/frappe/widgets/base_widget.js @@ -89,7 +89,7 @@ export default class Widget { } set_title() { - this.title_field[0].innerHTML = this.label || this.name; + this.title_field[0].innerHTML = this.label; } add_custom_button(html, action, class_name = "") { From ed3e2a9a3926405b6a956a7b7fcd431919d884eb Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Tue, 31 Mar 2020 13:50:23 +0530 Subject: [PATCH 033/115] feat: get rid of docname hack --- frappe/desk/desktop.py | 6 ------ frappe/public/js/frappe/widgets/base_widget.js | 9 ++------- frappe/public/js/frappe/widgets/chart_widget.js | 1 - frappe/public/js/frappe/widgets/links_widget.js | 2 -- frappe/public/js/frappe/widgets/shortcut_widget.js | 8 ++++++-- 5 files changed, 8 insertions(+), 18 deletions(-) diff --git a/frappe/desk/desktop.py b/frappe/desk/desktop.py index 9954d593d7..39369599c2 100644 --- a/frappe/desk/desktop.py +++ b/frappe/desk/desktop.py @@ -145,8 +145,6 @@ class Workspace: else: new_section = section.as_dict().copy() new_section["links"] = new_items - new_section["label"] = section.title - new_section["docname"] = section.name new_data.append(new_section) return new_data @@ -160,7 +158,6 @@ class Workspace: for chart in charts: chart.label = chart.label if chart.label else chart.chart_name - chart.docname = chart.name all_charts.append(chart) return all_charts @@ -180,8 +177,6 @@ class Workspace: for item in shortcuts: new_item = item.as_dict().copy() - new_item['docname'] = item.name - new_item['name'] = _(item.link_to) if self.is_item_allowed(item.link_to, item.type) and _in_active_domains(item): if item.type == "Page": page = self.allowed_pages[item.link_to] @@ -352,7 +347,6 @@ def prepare_widget(config, doctype, parentfield): wid_config = widgets[name].copy() # Some cleanup wid_config.pop("name", None) - wid_config.pop("docname", None) # New Doc doc = frappe.new_doc(doctype) diff --git a/frappe/public/js/frappe/widgets/base_widget.js b/frappe/public/js/frappe/widgets/base_widget.js index 4ac464c22e..759c49feb2 100644 --- a/frappe/public/js/frappe/widgets/base_widget.js +++ b/frappe/public/js/frappe/widgets/base_widget.js @@ -14,7 +14,6 @@ export default class Widget { get_config() { return { name: this.name, - docname: this.docname, label: this.label }; } @@ -69,7 +68,7 @@ export default class Widget { make_widget() { this.widget = $(`
+ }" data-widget-name=${this.name}>
@@ -127,12 +126,8 @@ export default class Widget { } new_dialog.hide(); - console.log("DATA", data) Object.assign(this, data); - this.set_title(); - this.set_actions(); - this.set_body(); - this.setup_events(); + this.refresh(); }, primary_action_label: __("Save"), }); diff --git a/frappe/public/js/frappe/widgets/chart_widget.js b/frappe/public/js/frappe/widgets/chart_widget.js index 382b0df746..e5cc879974 100644 --- a/frappe/public/js/frappe/widgets/chart_widget.js +++ b/frappe/public/js/frappe/widgets/chart_widget.js @@ -12,7 +12,6 @@ export default class ChartWidget extends Widget { get_config() { return { name: this.name, - docname: this.docname, chart_name: this.chart_name, label: this.label, } diff --git a/frappe/public/js/frappe/widgets/links_widget.js b/frappe/public/js/frappe/widgets/links_widget.js index dc2dc9e7f8..b93b592117 100644 --- a/frappe/public/js/frappe/widgets/links_widget.js +++ b/frappe/public/js/frappe/widgets/links_widget.js @@ -9,10 +9,8 @@ export default class LinksWidget extends Widget { get_config() { return { name: this.name, - docname: this.docname, links: JSON.stringify(this.links), label: this.label, - title: this.title, hidden: this.hidden, } } diff --git a/frappe/public/js/frappe/widgets/shortcut_widget.js b/frappe/public/js/frappe/widgets/shortcut_widget.js index 3b4aee668d..ed5cbf5e5a 100644 --- a/frappe/public/js/frappe/widgets/shortcut_widget.js +++ b/frappe/public/js/frappe/widgets/shortcut_widget.js @@ -17,7 +17,6 @@ export default class ShortcutWidget extends Widget { get_config() { return { name: this.name, - docname: this.docname, icon: this.icon, label: this.label, format: this.format, @@ -30,7 +29,12 @@ export default class ShortcutWidget extends Widget { setup_events() { this.widget.click(() => { - let route = generate_route(this) + let route = generate_route({ + route: this.route, + name: this.link_to, + type: this.type + }) + frappe.set_route(route) }) } From fe0bc6feff9ea93e08e429cc47d140eea52c8ba7 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Tue, 31 Mar 2020 14:08:13 +0530 Subject: [PATCH 034/115] feat: move settings to modules section --- frappe/core/desk_page/settings/settings.json | 41 ++++++++++++-------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/frappe/core/desk_page/settings/settings.json b/frappe/core/desk_page/settings/settings.json index 41d1765684..ac8310454d 100644 --- a/frappe/core/desk_page/settings/settings.json +++ b/frappe/core/desk_page/settings/settings.json @@ -1,37 +1,43 @@ { "cards": [ { + "hidden": 0, "icon": "fa fa-th", - "links": "[\n {\n \"description\": \"Import Data from CSV / Excel files.\",\n \"icon\": \"octicon octicon-cloud-upload\",\n \"label\": \"Import Data\",\n \"name\": \"Data Import\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Export Data in CSV / Excel format.\",\n \"icon\": \"octicon octicon-cloud-upload\",\n \"label\": \"Export Data\",\n \"name\": \"Data Export\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Update many values at one time.\",\n \"hide_count\": true,\n \"label\": \"Bulk Update\",\n \"name\": \"Bulk Update\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"List of backups available for download\",\n \"icon\": \"fa fa-download\",\n \"label\": \"Download Backups\",\n \"name\": \"backups\",\n \"type\": \"page\"\n },\n {\n \"description\": \"Restore or permanently delete a document.\",\n \"label\": \"Deleted Documents\",\n \"name\": \"Deleted Document\",\n \"type\": \"doctype\"\n }\n]", - "title": "Data" + "label": "Data", + "links": "[\n {\n \"description\": \"Import Data from CSV / Excel files.\",\n \"icon\": \"octicon octicon-cloud-upload\",\n \"label\": \"Import Data\",\n \"name\": \"Data Import\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Export Data in CSV / Excel format.\",\n \"icon\": \"octicon octicon-cloud-upload\",\n \"label\": \"Export Data\",\n \"name\": \"Data Export\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Update many values at one time.\",\n \"hide_count\": true,\n \"label\": \"Bulk Update\",\n \"name\": \"Bulk Update\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"List of backups available for download\",\n \"icon\": \"fa fa-download\",\n \"label\": \"Download Backups\",\n \"name\": \"backups\",\n \"type\": \"page\"\n },\n {\n \"description\": \"Restore or permanently delete a document.\",\n \"label\": \"Deleted Documents\",\n \"name\": \"Deleted Document\",\n \"type\": \"doctype\"\n }\n]" }, { + "hidden": 0, "icon": "fa fa-envelope", - "links": "[\n {\n \"description\": \"Add / Manage Email Accounts.\",\n \"label\": \"Email Account\",\n \"name\": \"Email Account\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Add / Manage Email Domains.\",\n \"label\": \"Email Domain\",\n \"name\": \"Email Domain\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Setup Notifications based on various criteria.\",\n \"label\": \"Notification\",\n \"name\": \"Notification\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Email Templates for common queries.\",\n \"label\": \"Email Template\",\n \"name\": \"Email Template\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Setup Reports to be emailed at regular intervals\",\n \"label\": \"Auto Email Report\",\n \"name\": \"Auto Email Report\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Create and manage newsletter\",\n \"label\": \"Newsletter\",\n \"name\": \"Newsletter\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Configure notifications for mentions, assignments, energy points and more.\",\n \"label\": \"Notification Settings\",\n \"name\": \"Notification Settings\",\n \"route\": \"Form/Notification Settings/Administrator\",\n \"type\": \"doctype\"\n }\n]", - "title": "Email / Notifications" + "label": "Email / Notifications", + "links": "[\n {\n \"description\": \"Add / Manage Email Accounts.\",\n \"label\": \"Email Account\",\n \"name\": \"Email Account\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Add / Manage Email Domains.\",\n \"label\": \"Email Domain\",\n \"name\": \"Email Domain\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Setup Notifications based on various criteria.\",\n \"label\": \"Notification\",\n \"name\": \"Notification\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Email Templates for common queries.\",\n \"label\": \"Email Template\",\n \"name\": \"Email Template\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Setup Reports to be emailed at regular intervals\",\n \"label\": \"Auto Email Report\",\n \"name\": \"Auto Email Report\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Create and manage newsletter\",\n \"label\": \"Newsletter\",\n \"name\": \"Newsletter\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Configure notifications for mentions, assignments, energy points and more.\",\n \"label\": \"Notification Settings\",\n \"name\": \"Notification Settings\",\n \"route\": \"Form/Notification Settings/Administrator\",\n \"type\": \"doctype\"\n }\n]" }, { + "hidden": 0, "icon": "fa fa-globe", - "links": "[\n {\n \"description\": \"Setup of top navigation bar, footer and logo.\",\n \"label\": \"Website Settings\",\n \"name\": \"Website Settings\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"List of themes for Website.\",\n \"label\": \"Website Theme\",\n \"name\": \"Website Theme\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Javascript to append to the head section of the page.\",\n \"label\": \"Website Script\",\n \"name\": \"Website Script\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Settings for About Us Page.\",\n \"label\": \"About Us Settings\",\n \"name\": \"About Us Settings\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Settings for Contact Us Page.\",\n \"label\": \"Contact Us Settings\",\n \"name\": \"Contact Us Settings\",\n \"type\": \"doctype\"\n }\n]", - "title": "Website" + "label": "Website", + "links": "[\n {\n \"description\": \"Setup of top navigation bar, footer and logo.\",\n \"label\": \"Website Settings\",\n \"name\": \"Website Settings\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"List of themes for Website.\",\n \"label\": \"Website Theme\",\n \"name\": \"Website Theme\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Javascript to append to the head section of the page.\",\n \"label\": \"Website Script\",\n \"name\": \"Website Script\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Settings for About Us Page.\",\n \"label\": \"About Us Settings\",\n \"name\": \"About Us Settings\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Settings for Contact Us Page.\",\n \"label\": \"Contact Us Settings\",\n \"name\": \"Contact Us Settings\",\n \"type\": \"doctype\"\n }\n]" }, { + "hidden": 0, "icon": "fa fa-wrench", - "links": "[\n {\n \"description\": \"Language, Date and Time settings\",\n \"hide_count\": true,\n \"label\": \"System Settings\",\n \"name\": \"System Settings\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Log of error on automated events (scheduler).\",\n \"label\": \"Error Log\",\n \"name\": \"Error Log\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Log of error during requests.\",\n \"label\": \"Error Snapshot\",\n \"name\": \"Error Snapshot\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Enable / Disable Domains\",\n \"hide_count\": true,\n \"label\": \"Domain Settings\",\n \"name\": \"Domain Settings\",\n \"type\": \"doctype\"\n }\n]", - "title": "Core" + "label": "Core", + "links": "[\n {\n \"description\": \"Language, Date and Time settings\",\n \"hide_count\": true,\n \"label\": \"System Settings\",\n \"name\": \"System Settings\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Log of error on automated events (scheduler).\",\n \"label\": \"Error Log\",\n \"name\": \"Error Log\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Log of error during requests.\",\n \"label\": \"Error Snapshot\",\n \"name\": \"Error Snapshot\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Enable / Disable Domains\",\n \"hide_count\": true,\n \"label\": \"Domain Settings\",\n \"name\": \"Domain Settings\",\n \"type\": \"doctype\"\n }\n]" }, { + "hidden": 0, "icon": "fa fa-print", - "links": "[\n {\n \"description\": \"Drag and Drop tool to build and customize Print Formats.\",\n \"label\": \"Print Format Builder\",\n \"name\": \"print-format-builder\",\n \"type\": \"page\"\n },\n {\n \"description\": \"Set default format, page size, print style etc.\",\n \"label\": \"Print Settings\",\n \"name\": \"Print Settings\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Customized HTML Templates for printing transactions.\",\n \"label\": \"Print Format\",\n \"name\": \"Print Format\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Stylesheets for Print Formats\",\n \"label\": \"Print Style\",\n \"name\": \"Print Style\",\n \"type\": \"doctype\"\n }\n]", - "title": "Printing" + "label": "Printing", + "links": "[\n {\n \"description\": \"Drag and Drop tool to build and customize Print Formats.\",\n \"label\": \"Print Format Builder\",\n \"name\": \"print-format-builder\",\n \"type\": \"page\"\n },\n {\n \"description\": \"Set default format, page size, print style etc.\",\n \"label\": \"Print Settings\",\n \"name\": \"Print Settings\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Customized HTML Templates for printing transactions.\",\n \"label\": \"Print Format\",\n \"name\": \"Print Format\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Stylesheets for Print Formats\",\n \"label\": \"Print Style\",\n \"name\": \"Print Style\",\n \"type\": \"doctype\"\n }\n]" }, { + "hidden": 0, "icon": "fa fa-random", - "links": "[\n {\n \"description\": \"Define workflows for forms.\",\n \"label\": \"Workflow\",\n \"name\": \"Workflow\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"States for workflow (e.g. Draft, Approved, Cancelled).\",\n \"label\": \"Workflow State\",\n \"name\": \"Workflow State\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Actions for workflow (e.g. Approve, Cancel).\",\n \"label\": \"Workflow Action\",\n \"name\": \"Workflow Action\",\n \"type\": \"doctype\"\n }\n]", - "title": "Workflow" + "label": "Workflow", + "links": "[\n {\n \"description\": \"Define workflows for forms.\",\n \"label\": \"Workflow\",\n \"name\": \"Workflow\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"States for workflow (e.g. Draft, Approved, Cancelled).\",\n \"label\": \"Workflow State\",\n \"name\": \"Workflow State\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Actions for workflow (e.g. Approve, Cancel).\",\n \"label\": \"Workflow Action\",\n \"name\": \"Workflow Action\",\n \"type\": \"doctype\"\n }\n]" } ], - "category": "Administration", + "category": "Modules", "charts": [], "creation": "2020-03-02 15:09:40.527211", "developer_mode_only": 0, @@ -42,29 +48,32 @@ "idx": 0, "is_standard": 1, "label": "Settings", - "modified": "2020-03-12 16:30:43.510434", + "modified": "2020-03-31 13:56:46.807568", "modified_by": "Administrator", "module": "Core", "name": "Settings", "owner": "Administrator", - "pin_to_bottom": 0, - "pin_to_top": 1, + "pin_to_bottom": 1, + "pin_to_top": 0, "shortcuts": [ { "icon": "octicon octicon-settings", "is_query_report": 0, + "label": "System Settings", "link_to": "System Settings", "type": "DocType" }, { "icon": "fa fa-print", "is_query_report": 0, + "label": "Print Settings", "link_to": "Print Settings", "type": "DocType" }, { "icon": "fa fa-globe", "is_query_report": 0, + "label": "Website Settings", "link_to": "Website Settings", "type": "DocType" } From e8434806ec6041ca0357e18df09844e01597ce31 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Tue, 31 Mar 2020 14:30:30 +0530 Subject: [PATCH 035/115] feat: removed unused fields from widget docs --- frappe/desk/doctype/desk_card/desk_card.json | 8 +------ frappe/desk/doctype/desk_page/desk_page.js | 24 +++++++++++-------- .../doctype/desk_shortcut/desk_shortcut.json | 20 +++++++--------- 3 files changed, 23 insertions(+), 29 deletions(-) diff --git a/frappe/desk/doctype/desk_card/desk_card.json b/frappe/desk/doctype/desk_card/desk_card.json index 8877ccd2bd..775681b4e2 100644 --- a/frappe/desk/doctype/desk_card/desk_card.json +++ b/frappe/desk/doctype/desk_card/desk_card.json @@ -5,7 +5,6 @@ "engine": "InnoDB", "field_order": [ "label", - "icon", "column_break_2", "hidden", "section_break_3", @@ -28,11 +27,6 @@ "fieldname": "column_break_2", "fieldtype": "Column Break" }, - { - "fieldname": "icon", - "fieldtype": "Data", - "label": "Icon" - }, { "default": "0", "fieldname": "hidden", @@ -49,7 +43,7 @@ ], "istable": 1, "links": [], - "modified": "2020-03-31 13:40:14.993872", + "modified": "2020-03-31 14:30:06.122112", "modified_by": "Administrator", "module": "Desk", "name": "Desk Card", diff --git a/frappe/desk/doctype/desk_page/desk_page.js b/frappe/desk/doctype/desk_page/desk_page.js index 7af3e0e98c..67def55521 100644 --- a/frappe/desk/doctype/desk_page/desk_page.js +++ b/frappe/desk/doctype/desk_page/desk_page.js @@ -2,17 +2,21 @@ // For license information, please see license.txt frappe.ui.form.on('Desk Page', { - refresh: function(frm) { + setup: function(frm) { frm.get_field("is_standard").toggle(frappe.boot.developer_mode); frm.get_field("extends_another_page").toggle(frappe.boot.developer_mode); - if (!frappe.boot.developer_mode) { - frm.set_read_only(); - frm.fields - .filter(field => field.has_input) - .forEach(field => { - frm.set_df_property(field.df.fieldname, "read_only", "1"); - }); - frm.disable_save(); + if (!frappe.boot.developer_mode || frm.doc.for_user) { + frm.trigger('disable_form') } + }, + + disable_form: function(frm) { + frm.set_read_only(); + frm.fields + .filter(field => field.has_input) + .forEach(field => { + frm.set_df_property(field.df.fieldname, "read_only", "1"); + }); + frm.disable_save(); } -}); +}); \ No newline at end of file diff --git a/frappe/desk/doctype/desk_shortcut/desk_shortcut.json b/frappe/desk/doctype/desk_shortcut/desk_shortcut.json index 9d2469f7fb..d008a94834 100644 --- a/frappe/desk/doctype/desk_shortcut/desk_shortcut.json +++ b/frappe/desk/doctype/desk_shortcut/desk_shortcut.json @@ -6,12 +6,11 @@ "engine": "InnoDB", "field_order": [ "type", - "icon", - "column_break_4", "link_to", + "column_break_4", "label", + "icon", "restrict_to_domain", - "is_query_report", "section_break_5", "stats_filter", "column_break_3", @@ -52,6 +51,7 @@ "label": "Format" }, { + "depends_on": "eval:doc.type == \"DocType\" && frappe.boot.developer_mode", "fieldname": "section_break_5", "fieldtype": "Section Break", "label": "Count Filter" @@ -62,13 +62,7 @@ "label": "Color" }, { - "default": "0", - "depends_on": "eval:doc.type === \"Report\"", - "fieldname": "is_query_report", - "fieldtype": "Check", - "label": "Is Query Report" - }, - { + "depends_on": "eval:frappe.boot.developer_mode", "fieldname": "icon", "fieldtype": "Data", "label": "Icon" @@ -78,6 +72,7 @@ "fieldtype": "Column Break" }, { + "depends_on": "eval:frappe.boot.developer_mode", "fieldname": "restrict_to_domain", "fieldtype": "Link", "label": "Restrict to Domain", @@ -86,12 +81,13 @@ { "fieldname": "label", "fieldtype": "Data", - "label": "Label" + "label": "Label", + "reqd": 1 } ], "istable": 1, "links": [], - "modified": "2020-03-31 13:41:49.802777", + "modified": "2020-03-31 14:29:37.021121", "modified_by": "Administrator", "module": "Desk", "name": "Desk Shortcut", From 50492786313e26b5a17e6eb17aa972302e4f81f9 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Tue, 31 Mar 2020 14:38:21 +0530 Subject: [PATCH 036/115] feat: cleanup --- frappe/desk/desktop.py | 19 ++++++++++--------- frappe/desk/doctype/desk_card/desk_card.json | 5 +++-- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/frappe/desk/desktop.py b/frappe/desk/desktop.py index 39369599c2..13e0dbf7b4 100644 --- a/frappe/desk/desktop.py +++ b/frappe/desk/desktop.py @@ -313,15 +313,16 @@ def save_customization(page, config): page_doc = get_custom_workspace_for_user(page) # Update field values - page_doc.charts_label = original_page.charts_label - page_doc.cards_label = original_page.cards_label - page_doc.shortcuts_label = original_page.shortcuts_label - page_doc.charts_label = original_page.charts_label - page_doc.icon = original_page.icon - page_doc.module = original_page.module - page_doc.developer_mode_only = original_page.developer_mode_only - page_doc.category = original_page.category - + page_doc.update({ + "charts_label": original_page.charts_label, + "cards_label": original_page.cards_label, + "shortcuts_label": original_page.shortcuts_label, + "charts_label": original_page.charts_label, + "icon": original_page.icon, + "module": original_page.module, + "developer_mode_only": original_page.developer_mode_only, + "category": original_page.category + }) config = frappe._dict(loads(config)) diff --git a/frappe/desk/doctype/desk_card/desk_card.json b/frappe/desk/doctype/desk_card/desk_card.json index 775681b4e2..dbcb4b0d5c 100644 --- a/frappe/desk/doctype/desk_card/desk_card.json +++ b/frappe/desk/doctype/desk_card/desk_card.json @@ -2,6 +2,7 @@ "actions": [], "creation": "2020-01-29 14:45:54.383089", "doctype": "DocType", + "editable_grid": 1, "engine": "InnoDB", "field_order": [ "label", @@ -14,7 +15,6 @@ { "fieldname": "links", "fieldtype": "Code", - "in_list_view": 1, "label": "Links", "options": "JSON", "reqd": 1 @@ -31,6 +31,7 @@ "default": "0", "fieldname": "hidden", "fieldtype": "Check", + "in_list_view": 1, "label": "Hidden" }, { @@ -43,7 +44,7 @@ ], "istable": 1, "links": [], - "modified": "2020-03-31 14:30:06.122112", + "modified": "2020-03-31 14:38:06.303847", "modified_by": "Administrator", "module": "Desk", "name": "Desk Card", From 0027781cb058b199d27f92bfd426942f189825cc Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Tue, 31 Mar 2020 14:39:25 +0530 Subject: [PATCH 037/115] fix: label for custom card --- frappe/desk/desktop.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/desk/desktop.py b/frappe/desk/desktop.py index 13e0dbf7b4..d2049faeb5 100644 --- a/frappe/desk/desktop.py +++ b/frappe/desk/desktop.py @@ -255,7 +255,7 @@ def get_table_with_counts(): def get_custom_reports_and_doctypes(module): return [ frappe._dict({ - "title": "Custom", + "label": "Custom", "links": get_custom_doctype_list(module) + get_custom_report_list(module) }) ] From 626f41078878cffc092dd99022fceb19994bf5f9 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Tue, 31 Mar 2020 15:02:06 +0530 Subject: [PATCH 038/115] fix: custom links card bug --- frappe/public/js/frappe/widgets/base_widget.js | 2 +- frappe/public/js/frappe/widgets/new_widget.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/frappe/public/js/frappe/widgets/base_widget.js b/frappe/public/js/frappe/widgets/base_widget.js index 759c49feb2..992be13438 100644 --- a/frappe/public/js/frappe/widgets/base_widget.js +++ b/frappe/public/js/frappe/widgets/base_widget.js @@ -68,7 +68,7 @@ export default class Widget { make_widget() { this.widget = $(`
+ }" data-widget-name=${this.name ? this.name : ''}>
diff --git a/frappe/public/js/frappe/widgets/new_widget.js b/frappe/public/js/frappe/widgets/new_widget.js index 2c2ae1466d..d0dabe6678 100644 --- a/frappe/public/js/frappe/widgets/new_widget.js +++ b/frappe/public/js/frappe/widgets/new_widget.js @@ -58,11 +58,11 @@ export default class NewWidget { data.label = data.chart_name; } - if (this.type == 'shortcut') { + if (this.type == 'shortcut' && !data.label) { data.label = data.link_to; } - data.docname = frappe.utils.get_random(20); + data.name = `${this.type}-${this.label}-${frappe.utils.get_random(20)}`; new_dialog.hide(); this.on_create(data); From 34f2a0ada13d3e542d6e19540d7fe1d5aa63437d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2020 09:38:12 +0000 Subject: [PATCH 039/115] chore(deps): bump bleach from 3.1.2 to 3.1.4 Bumps [bleach](https://github.com/mozilla/bleach) from 3.1.2 to 3.1.4. - [Release notes](https://github.com/mozilla/bleach/releases) - [Changelog](https://github.com/mozilla/bleach/blob/master/CHANGES) - [Commits](https://github.com/mozilla/bleach/compare/v3.1.2...v3.1.4) Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 55a4910056..bcf3760cd8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ Babel==2.6.0 beautifulsoup4==4.8.2 bleach-whitelist==0.0.10 -bleach==3.1.2 +bleach==3.1.4 boto3==1.10.18 braintree==3.57.1 chardet==3.0.4 From 01326a3d20d26fc939ab68ff3cd8f1c4e55e2e5b Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Tue, 31 Mar 2020 16:01:04 +0530 Subject: [PATCH 040/115] feat: added toggleFullwidth event to body --- frappe/public/js/frappe/ui/toolbar/toolbar.js | 1 + 1 file changed, 1 insertion(+) diff --git a/frappe/public/js/frappe/ui/toolbar/toolbar.js b/frappe/public/js/frappe/ui/toolbar/toolbar.js index eed36615fc..e774550a69 100644 --- a/frappe/public/js/frappe/ui/toolbar/toolbar.js +++ b/frappe/public/js/frappe/ui/toolbar/toolbar.js @@ -203,6 +203,7 @@ $.extend(frappe.ui.toolbar, { fullwidth = !fullwidth; localStorage.container_fullwidth = fullwidth; frappe.ui.toolbar.set_fullwidth_if_enabled(); + $(document.body).trigger('toggleFullWidth'); }, set_fullwidth_if_enabled() { let fullwidth = JSON.parse(localStorage.container_fullwidth || 'false'); From b1d7e8fb05bc46ce7de5d9f56aafff1abe6abdc2 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Tue, 31 Mar 2020 16:01:33 +0530 Subject: [PATCH 041/115] refactor: clean up --- .../public/js/frappe/views/desktop/desktop.js | 83 +++++-------------- 1 file changed, 23 insertions(+), 60 deletions(-) diff --git a/frappe/public/js/frappe/views/desktop/desktop.js b/frappe/public/js/frappe/views/desktop/desktop.js index 66c7ec8043..2ae65ed1a4 100644 --- a/frappe/public/js/frappe/views/desktop/desktop.js +++ b/frappe/public/js/frappe/views/desktop/desktop.js @@ -1,7 +1,6 @@ export default class Desktop { constructor({ wrapper }) { this.wrapper = wrapper; - window.desk = this; this.pages = {}; this.sidebar_items = {}; this.sidebar_categories = [ @@ -131,8 +130,6 @@ export default class Desktop { this.pages[page] = $page; return $page; } - - setup_events() {} } class DesktopPage { @@ -141,10 +138,7 @@ class DesktopPage { this.page_name = page_name; this.sections = {}; this.allow_customization = false; - this.in_customize_mode = false; - this.container.empty(); - this.make(); - window.page = this; + this.reload(); } show() { @@ -159,6 +153,7 @@ class DesktopPage { this.in_customize_mode = false; this.container.empty(); this.make(); + this.setup_events(); } make_customization_link() { @@ -181,7 +176,9 @@ class DesktopPage { } make() { - this.make_page(); + this.page = $(`
`); + this.page.appendTo(this.container); + this.get_data().then(res => { this.data = res.message; // this.make_onboarding(); @@ -191,26 +188,24 @@ class DesktopPage { return; } - this.allow_customization = this.data.allow_customization || false; - this.allow_customization && this.make_customization_link(); - - !this.sections["onboarding"] && - this.data.charts.items && - this.make_charts(); - this.data.shortcuts.items && this.make_shortcuts(); - this.data.cards.items && this.make_cards(); - if (this.allow_customization) { - // Move the widget group up to align with labels if customization is allowed - $('.desk-page .widget-group:visible:first').css('margin-top', '-25px'); - } + this.refresh(); }); } - make_page() { - this.page = $( - `
` - ); - this.page.appendTo(this.container); + refresh() { + this.page.empty(); + this.allow_customization = this.data.allow_customization || false; + this.allow_customization && this.make_customization_link(); + + !this.sections["onboarding"] && + this.data.charts.items && + this.make_charts(); + this.data.shortcuts.items && this.make_shortcuts(); + this.data.cards.items && this.make_cards(); + if (this.allow_customization) { + // Move the widget group up to align with labels if customization is allowed + $('.desk-page .widget-group:visible:first').css('margin-top', '-25px'); + } } get_data() { @@ -219,41 +214,8 @@ class DesktopPage { }); } - make_onboarding() { - this.sections["onboarding"] = new frappe.widget.WidgetGroup({ - title: `Getting Started`, - container: this.page, - type: "onboarding", - columns: 1, - widgets: [ - { - label: "Unlock Great Customer Experience", - subtitle: "Just a few steps, and you’re good to go.", - steps: [ - { - label: "Configure Lead Sources", - completed: true - }, - { - label: "Add Your Leads", - completed: false - }, - { - label: "Create Your First Opportunity", - completed: false - }, - { - label: "Onboard your Sales Team", - completed: false - }, - { - label: "Assign Territories", - completed: false - } - ] - } - ] - }); + setup_events() { + $(document.body).on('toggleFullWidth', () => this.refresh()); } customize() { @@ -289,6 +251,7 @@ class DesktopPage { page: this.page_name, config: config }).then(res => { + frappe.msgprint(__("Customizations Saved Successfully")) this.reload(); }) } From 15f80cc4b078d901c4f52c9340bad2c181277da1 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Tue, 31 Mar 2020 16:16:57 +0530 Subject: [PATCH 042/115] feat: set max count for widget group --- frappe/public/js/frappe/views/desktop/desktop.js | 1 + frappe/public/js/frappe/widgets/widget_group.js | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/frappe/public/js/frappe/views/desktop/desktop.js b/frappe/public/js/frappe/views/desktop/desktop.js index 2ae65ed1a4..c8c99295e2 100644 --- a/frappe/public/js/frappe/views/desktop/desktop.js +++ b/frappe/public/js/frappe/views/desktop/desktop.js @@ -268,6 +268,7 @@ class DesktopPage { allow_delete: this.allow_customization, allow_hiding: false, allow_edit: true, + max_widget_count: 2, }, widgets: this.data.charts.items }); diff --git a/frappe/public/js/frappe/widgets/widget_group.js b/frappe/public/js/frappe/widgets/widget_group.js index 28e47018df..7acb9b63de 100644 --- a/frappe/public/js/frappe/widgets/widget_group.js +++ b/frappe/public/js/frappe/widgets/widget_group.js @@ -81,7 +81,11 @@ export default class WidgetGroup { wid.customize(this.options); }) - if (this.options.allow_create) { + const max = this.options + ? this.options.max_widget_count || Number.POSITIVE_INFINITY + : Number.POSITIVE_INFINITY; + + if (this.options.allow_create && this.widgets_list.length < max) { this.new_widget = new NewWidget({ container: this.body, type: this.type, From 27963b774839e975913c7da0badd971f847d8553 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Tue, 31 Mar 2020 16:18:31 +0530 Subject: [PATCH 043/115] feat: add in_customize_mode flag --- frappe/public/js/frappe/widgets/base_widget.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/frappe/public/js/frappe/widgets/base_widget.js b/frappe/public/js/frappe/widgets/base_widget.js index 992be13438..93093de84f 100644 --- a/frappe/public/js/frappe/widgets/base_widget.js +++ b/frappe/public/js/frappe/widgets/base_widget.js @@ -19,6 +19,7 @@ export default class Widget { } customize(options) { + this.in_customize_mode = true; this.action_area.empty(); options.allow_delete && @@ -58,9 +59,11 @@ export default class Widget { '', () => this.edit() ); + } make() { + this.in_customize_mode = false; this.make_widget(); this.widget.appendTo(this.container); } From 01245091453589c80d49dade4da4c2194458ea26 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Tue, 31 Mar 2020 16:18:44 +0530 Subject: [PATCH 044/115] fix: actions not visible on adding widget bug --- .../public/js/frappe/widgets/chart_widget.js | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/frappe/public/js/frappe/widgets/chart_widget.js b/frappe/public/js/frappe/widgets/chart_widget.js index e5cc879974..2dd87e9a50 100644 --- a/frappe/public/js/frappe/widgets/chart_widget.js +++ b/frappe/public/js/frappe/widgets/chart_widget.js @@ -18,7 +18,8 @@ export default class ChartWidget extends Widget { } refresh() { - super.refresh(); + this.set_title(); + this.set_body(); this.make_chart(); } @@ -69,17 +70,18 @@ export default class ChartWidget extends Widget { this.get_settings().then(() => { this.setup_container(); this.prepare_chart_object(); - this.action_area.empty(); - this.prepare_chart_actions(); - this.setup_filter_button(); + if (!this.in_customize_mode) { + this.action_area.empty(); + this.prepare_chart_actions(); + this.setup_filter_button(); - if ( - this.chart_doc.timeseries && - this.chart_doc.chart_type !== "Custom" - ) { - this.render_time_series_filters(); + if ( + this.chart_doc.timeseries && + this.chart_doc.chart_type !== "Custom" + ) { + this.render_time_series_filters(); + } } - this.fetch_and_update_chart(); }); } From 249de2c7d142bd7db984a32559335788bb0a0767 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Tue, 31 Mar 2020 16:32:19 +0530 Subject: [PATCH 045/115] fix: chart edit bug --- frappe/public/js/frappe/widgets/chart_widget.js | 1 + 1 file changed, 1 insertion(+) diff --git a/frappe/public/js/frappe/widgets/chart_widget.js b/frappe/public/js/frappe/widgets/chart_widget.js index 2dd87e9a50..2aa7209d0d 100644 --- a/frappe/public/js/frappe/widgets/chart_widget.js +++ b/frappe/public/js/frappe/widgets/chart_widget.js @@ -18,6 +18,7 @@ export default class ChartWidget extends Widget { } refresh() { + delete this.dashboard_chart; this.set_title(); this.set_body(); this.make_chart(); From 0af7c90cce8e21794282cc209f4af72c946bb8c9 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Wed, 1 Apr 2020 10:49:17 +0530 Subject: [PATCH 046/115] fix: fix typo --- frappe/desk/desktop.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/desk/desktop.py b/frappe/desk/desktop.py index d2049faeb5..a639400670 100644 --- a/frappe/desk/desktop.py +++ b/frappe/desk/desktop.py @@ -216,7 +216,7 @@ def get_desktop_page(page): except DoesNotExistError: if frappe.message_log: frappe.message_log.pop() - return Nonee + return None @frappe.whitelist() def get_desk_sidebar_items(): From c67ecbc6ba28c27a10155ee8be7c87eda400ecb7 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Wed, 1 Apr 2020 11:25:15 +0530 Subject: [PATCH 047/115] feat: update desk pages --- frappe/automation/desk_page/tools/tools.json | 34 ++++++++-------- frappe/core/desk_page/settings/settings.json | 11 +----- frappe/core/desk_page/users/users.json | 28 ++++++------- .../customization/customization.json | 24 ++++++------ .../desk_page/integrations/integrations.json | 28 +++++++------ frappe/website/desk_page/website/website.json | 39 ++++++++++--------- 6 files changed, 83 insertions(+), 81 deletions(-) diff --git a/frappe/automation/desk_page/tools/tools.json b/frappe/automation/desk_page/tools/tools.json index 3cfaa0bd97..235498724d 100644 --- a/frappe/automation/desk_page/tools/tools.json +++ b/frappe/automation/desk_page/tools/tools.json @@ -1,22 +1,24 @@ { "cards": [ { - "icon": "octicon octicon-briefcase", - "links": "[\n {\n \"description\": \"Documents assigned to you and by you.\",\n \"label\": \"To Do\",\n \"name\": \"ToDo\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Event and other calendars.\",\n \"label\": \"Calendar\",\n \"link\": \"List/Event/Calendar\",\n \"name\": \"Event\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Private and public Notes.\",\n \"label\": \"Note\",\n \"name\": \"Note\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Files\",\n \"name\": \"File\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Activity log of all users.\",\n \"label\": \"Activity\",\n \"name\": \"activity\",\n \"type\": \"page\"\n }\n]", - "title": "Tools" + "hidden": 0, + "label": "Tools", + "links": "[\n {\n \"description\": \"Documents assigned to you and by you.\",\n \"label\": \"To Do\",\n \"name\": \"ToDo\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Event and other calendars.\",\n \"label\": \"Calendar\",\n \"link\": \"List/Event/Calendar\",\n \"name\": \"Event\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Private and public Notes.\",\n \"label\": \"Note\",\n \"name\": \"Note\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Files\",\n \"name\": \"File\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Activity log of all users.\",\n \"label\": \"Activity\",\n \"name\": \"activity\",\n \"type\": \"page\"\n }\n]" }, { - "links": "[\n {\n \"description\": \"Newsletters to contacts, leads.\",\n \"label\": \"Newsletter\",\n \"name\": \"Newsletter\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Email Group List\",\n \"label\": \"Email Group\",\n \"name\": \"Email Group\",\n \"type\": \"doctype\"\n }\n]", - "title": "Email" + "hidden": 0, + "label": "Email", + "links": "[\n {\n \"description\": \"Newsletters to contacts, leads.\",\n \"label\": \"Newsletter\",\n \"name\": \"Newsletter\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Email Group List\",\n \"label\": \"Email Group\",\n \"name\": \"Email Group\",\n \"type\": \"doctype\"\n }\n]" }, { - "icon": "fa fa-cog", - "links": "[\n {\n \"type\": \"doctype\",\n \"name\": \"Assignment Rule\",\n \"description\": \"Set up rules for user assignments.\",\n \"label\": \"Assignment Rule\"\n },\n {\n \"type\": \"doctype\",\n \"name\": \"Milestone\",\n \"description\": \"Tracks milestones on the lifecycle of a document if it undergoes multiple stages.\",\n \"label\": \"Milestone\"\n },\n {\n \"type\": \"doctype\",\n \"name\": \"Auto Repeat\",\n \"description\": \"Automatically generates recurring documents.\",\n \"label\": \"Auto Repeat\"\n }\n]", - "title": "Automation" + "hidden": 0, + "label": "Automation", + "links": "[\n {\n \"type\": \"doctype\",\n \"name\": \"Assignment Rule\",\n \"description\": \"Set up rules for user assignments.\",\n \"label\": \"Assignment Rule\"\n },\n {\n \"type\": \"doctype\",\n \"name\": \"Milestone\",\n \"description\": \"Tracks milestones on the lifecycle of a document if it undergoes multiple stages.\",\n \"label\": \"Milestone\"\n },\n {\n \"type\": \"doctype\",\n \"name\": \"Auto Repeat\",\n \"description\": \"Automatically generates recurring documents.\",\n \"label\": \"Auto Repeat\"\n }\n]" }, { - "links": "[\n {\n \"type\": \"doctype\",\n \"name\": \"Event Producer\",\n \"description\": \"The site you want to subscribe to for consuming events.\",\n \"label\": \"Event Producer\"\n },\n {\n \"type\": \"doctype\",\n \"name\": \"Event Consumer\",\n \"description\": \"The site which is consuming your events.\",\n \"label\": \"Event Consumer\"\n },\n {\n \"type\": \"doctype\",\n \"name\": \"Event Update Log\",\n \"description\": \"Maintains a Log of all inserts, updates and deletions on Event Producer site for documents that have consumers.\",\n \"label\": \"Event Update Log\"\n },\n {\n \"type\": \"doctype\",\n \"name\": \"Event Sync Log\",\n \"description\": \"Maintains a log of every event consumed along with the status of the sync and a Resync button in case sync fails.\",\n \"label\": \"Event Sync Log\"\n },\n {\n \"type\": \"doctype\",\n \"name\": \"Document Type Mapping\",\n \"description\": \"The mapping configuration between two doctypes.\",\n \"label\": \"Document Type Mapping\"\n }\n]", - "title": "Event Streaming" + "hidden": 0, + "label": "Event Streaming", + "links": "[\n {\n \"type\": \"doctype\",\n \"name\": \"Event Producer\",\n \"description\": \"The site you want to subscribe to for consuming events.\",\n \"label\": \"Event Producer\"\n },\n {\n \"type\": \"doctype\",\n \"name\": \"Event Consumer\",\n \"description\": \"The site which is consuming your events.\",\n \"label\": \"Event Consumer\"\n },\n {\n \"type\": \"doctype\",\n \"name\": \"Event Update Log\",\n \"description\": \"Maintains a Log of all inserts, updates and deletions on Event Producer site for documents that have consumers.\",\n \"label\": \"Event Update Log\"\n },\n {\n \"type\": \"doctype\",\n \"name\": \"Event Sync Log\",\n \"description\": \"Maintains a log of every event consumed along with the status of the sync and a Resync button in case sync fails.\",\n \"label\": \"Event Sync Log\"\n },\n {\n \"type\": \"doctype\",\n \"name\": \"Document Type Mapping\",\n \"description\": \"The mapping configuration between two doctypes.\",\n \"label\": \"Document Type Mapping\"\n }\n]" } ], "category": "Administration", @@ -30,7 +32,7 @@ "idx": 0, "is_standard": 1, "label": "Tools", - "modified": "2020-03-12 16:30:41.841895", + "modified": "2020-04-01 11:24:40.804346", "modified_by": "Administrator", "module": "Automation", "name": "Tools", @@ -39,27 +41,27 @@ "pin_to_top": 0, "shortcuts": [ { - "is_query_report": 0, + "label": "ToDo", "link_to": "ToDo", "type": "DocType" }, { - "is_query_report": 0, + "label": "Note", "link_to": "Note", "type": "DocType" }, { - "is_query_report": 0, + "label": "File", "link_to": "File", "type": "DocType" }, { - "is_query_report": 0, + "label": "Assignment Rule", "link_to": "Assignment Rule", "type": "DocType" }, { - "is_query_report": 0, + "label": "Auto Repeat", "link_to": "Auto Repeat", "type": "DocType" } diff --git a/frappe/core/desk_page/settings/settings.json b/frappe/core/desk_page/settings/settings.json index ac8310454d..6569b2fb20 100644 --- a/frappe/core/desk_page/settings/settings.json +++ b/frappe/core/desk_page/settings/settings.json @@ -2,37 +2,31 @@ "cards": [ { "hidden": 0, - "icon": "fa fa-th", "label": "Data", "links": "[\n {\n \"description\": \"Import Data from CSV / Excel files.\",\n \"icon\": \"octicon octicon-cloud-upload\",\n \"label\": \"Import Data\",\n \"name\": \"Data Import\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Export Data in CSV / Excel format.\",\n \"icon\": \"octicon octicon-cloud-upload\",\n \"label\": \"Export Data\",\n \"name\": \"Data Export\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Update many values at one time.\",\n \"hide_count\": true,\n \"label\": \"Bulk Update\",\n \"name\": \"Bulk Update\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"List of backups available for download\",\n \"icon\": \"fa fa-download\",\n \"label\": \"Download Backups\",\n \"name\": \"backups\",\n \"type\": \"page\"\n },\n {\n \"description\": \"Restore or permanently delete a document.\",\n \"label\": \"Deleted Documents\",\n \"name\": \"Deleted Document\",\n \"type\": \"doctype\"\n }\n]" }, { "hidden": 0, - "icon": "fa fa-envelope", "label": "Email / Notifications", "links": "[\n {\n \"description\": \"Add / Manage Email Accounts.\",\n \"label\": \"Email Account\",\n \"name\": \"Email Account\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Add / Manage Email Domains.\",\n \"label\": \"Email Domain\",\n \"name\": \"Email Domain\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Setup Notifications based on various criteria.\",\n \"label\": \"Notification\",\n \"name\": \"Notification\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Email Templates for common queries.\",\n \"label\": \"Email Template\",\n \"name\": \"Email Template\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Setup Reports to be emailed at regular intervals\",\n \"label\": \"Auto Email Report\",\n \"name\": \"Auto Email Report\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Create and manage newsletter\",\n \"label\": \"Newsletter\",\n \"name\": \"Newsletter\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Configure notifications for mentions, assignments, energy points and more.\",\n \"label\": \"Notification Settings\",\n \"name\": \"Notification Settings\",\n \"route\": \"Form/Notification Settings/Administrator\",\n \"type\": \"doctype\"\n }\n]" }, { "hidden": 0, - "icon": "fa fa-globe", "label": "Website", "links": "[\n {\n \"description\": \"Setup of top navigation bar, footer and logo.\",\n \"label\": \"Website Settings\",\n \"name\": \"Website Settings\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"List of themes for Website.\",\n \"label\": \"Website Theme\",\n \"name\": \"Website Theme\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Javascript to append to the head section of the page.\",\n \"label\": \"Website Script\",\n \"name\": \"Website Script\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Settings for About Us Page.\",\n \"label\": \"About Us Settings\",\n \"name\": \"About Us Settings\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Settings for Contact Us Page.\",\n \"label\": \"Contact Us Settings\",\n \"name\": \"Contact Us Settings\",\n \"type\": \"doctype\"\n }\n]" }, { "hidden": 0, - "icon": "fa fa-wrench", "label": "Core", "links": "[\n {\n \"description\": \"Language, Date and Time settings\",\n \"hide_count\": true,\n \"label\": \"System Settings\",\n \"name\": \"System Settings\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Log of error on automated events (scheduler).\",\n \"label\": \"Error Log\",\n \"name\": \"Error Log\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Log of error during requests.\",\n \"label\": \"Error Snapshot\",\n \"name\": \"Error Snapshot\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Enable / Disable Domains\",\n \"hide_count\": true,\n \"label\": \"Domain Settings\",\n \"name\": \"Domain Settings\",\n \"type\": \"doctype\"\n }\n]" }, { "hidden": 0, - "icon": "fa fa-print", "label": "Printing", "links": "[\n {\n \"description\": \"Drag and Drop tool to build and customize Print Formats.\",\n \"label\": \"Print Format Builder\",\n \"name\": \"print-format-builder\",\n \"type\": \"page\"\n },\n {\n \"description\": \"Set default format, page size, print style etc.\",\n \"label\": \"Print Settings\",\n \"name\": \"Print Settings\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Customized HTML Templates for printing transactions.\",\n \"label\": \"Print Format\",\n \"name\": \"Print Format\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Stylesheets for Print Formats\",\n \"label\": \"Print Style\",\n \"name\": \"Print Style\",\n \"type\": \"doctype\"\n }\n]" }, { "hidden": 0, - "icon": "fa fa-random", "label": "Workflow", "links": "[\n {\n \"description\": \"Define workflows for forms.\",\n \"label\": \"Workflow\",\n \"name\": \"Workflow\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"States for workflow (e.g. Draft, Approved, Cancelled).\",\n \"label\": \"Workflow State\",\n \"name\": \"Workflow State\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Actions for workflow (e.g. Approve, Cancel).\",\n \"label\": \"Workflow Action\",\n \"name\": \"Workflow Action\",\n \"type\": \"doctype\"\n }\n]" } @@ -48,7 +42,7 @@ "idx": 0, "is_standard": 1, "label": "Settings", - "modified": "2020-03-31 13:56:46.807568", + "modified": "2020-04-01 11:24:40.636747", "modified_by": "Administrator", "module": "Core", "name": "Settings", @@ -58,21 +52,18 @@ "shortcuts": [ { "icon": "octicon octicon-settings", - "is_query_report": 0, "label": "System Settings", "link_to": "System Settings", "type": "DocType" }, { "icon": "fa fa-print", - "is_query_report": 0, "label": "Print Settings", "link_to": "Print Settings", "type": "DocType" }, { "icon": "fa fa-globe", - "is_query_report": 0, "label": "Website Settings", "link_to": "Website Settings", "type": "DocType" diff --git a/frappe/core/desk_page/users/users.json b/frappe/core/desk_page/users/users.json index dc9619314e..30455b86e6 100644 --- a/frappe/core/desk_page/users/users.json +++ b/frappe/core/desk_page/users/users.json @@ -1,19 +1,19 @@ { "cards": [ { - "icon": "fa fa-group", - "links": "[\n {\n \"description\": \"System and Website Users\",\n \"label\": \"User\",\n \"name\": \"User\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"User Roles\",\n \"label\": \"Role\",\n \"name\": \"Role\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Role Profile\",\n \"label\": \"Role Profile\",\n \"name\": \"Role Profile\",\n \"type\": \"doctype\"\n }\n]", - "title": "Users" + "hidden": 0, + "label": "Users", + "links": "[\n {\n \"description\": \"System and Website Users\",\n \"label\": \"User\",\n \"name\": \"User\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"User Roles\",\n \"label\": \"Role\",\n \"name\": \"Role\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Role Profile\",\n \"label\": \"Role Profile\",\n \"name\": \"Role Profile\",\n \"type\": \"doctype\"\n }\n]" }, { - "icon": "fa fa-group", - "links": "[\n {\n \"description\": \"Activity Log by \",\n \"label\": \"Activity Log\",\n \"name\": \"Activity Log\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"View Log of all print, download and export events\",\n \"label\": \"Access Log\",\n \"name\": \"Access Log\",\n \"type\": \"doctype\"\n }\n]", - "title": "Logs" + "hidden": 0, + "label": "Logs", + "links": "[\n {\n \"description\": \"Activity Log by \",\n \"label\": \"Activity Log\",\n \"name\": \"Activity Log\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"View Log of all print, download and export events\",\n \"label\": \"Access Log\",\n \"name\": \"Access Log\",\n \"type\": \"doctype\"\n }\n]" }, { - "icon": "fa fa-lock", - "links": "[\n {\n \"description\": \"Set Permissions on Document Types and Roles\",\n \"icon\": \"fa fa-lock\",\n \"label\": \"Role Permissions Manager\",\n \"name\": \"permission-manager\",\n \"type\": \"page\"\n },\n {\n \"description\": \"Restrict user for specific document\",\n \"icon\": \"fa fa-lock\",\n \"label\": \"User Permissions\",\n \"name\": \"User Permission\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Set custom roles for page and report\",\n \"label\": \"Role Permission for Page and Report\",\n \"name\": \"Role Permission for Page and Report\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"User\"\n ],\n \"description\": \"Check which Documents are readable by a User\",\n \"doctype\": \"User\",\n \"icon\": \"fa fa-eye-open\",\n \"is_query_report\": true,\n \"label\": \"Permitted Documents For User\",\n \"name\": \"Permitted Documents For User\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"DocShare\"\n ],\n \"description\": \"Report of all document shares\",\n \"doctype\": \"DocShare\",\n \"icon\": \"fa fa-share\",\n \"label\": \"Document Share Report\",\n \"name\": \"Document Share Report\",\n \"type\": \"report\"\n }\n]", - "title": "Permissions" + "hidden": 0, + "label": "Permissions", + "links": "[\n {\n \"description\": \"Set Permissions on Document Types and Roles\",\n \"icon\": \"fa fa-lock\",\n \"label\": \"Role Permissions Manager\",\n \"name\": \"permission-manager\",\n \"type\": \"page\"\n },\n {\n \"description\": \"Restrict user for specific document\",\n \"icon\": \"fa fa-lock\",\n \"label\": \"User Permissions\",\n \"name\": \"User Permission\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Set custom roles for page and report\",\n \"label\": \"Role Permission for Page and Report\",\n \"name\": \"Role Permission for Page and Report\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"User\"\n ],\n \"description\": \"Check which Documents are readable by a User\",\n \"doctype\": \"User\",\n \"icon\": \"fa fa-eye-open\",\n \"is_query_report\": true,\n \"label\": \"Permitted Documents For User\",\n \"name\": \"Permitted Documents For User\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"DocShare\"\n ],\n \"description\": \"Report of all document shares\",\n \"doctype\": \"DocShare\",\n \"icon\": \"fa fa-share\",\n \"label\": \"Document Share Report\",\n \"name\": \"Document Share Report\",\n \"type\": \"report\"\n }\n]" } ], "category": "Administration", @@ -27,7 +27,7 @@ "idx": 0, "is_standard": 1, "label": "Users", - "modified": "2020-03-12 16:30:42.483376", + "modified": "2020-04-01 11:24:40.767676", "modified_by": "Administrator", "module": "Core", "name": "Users", @@ -36,22 +36,22 @@ "pin_to_top": 0, "shortcuts": [ { - "is_query_report": 0, + "label": "User", "link_to": "User", "type": "DocType" }, { - "is_query_report": 0, + "label": "Role", "link_to": "Role", "type": "DocType" }, { - "is_query_report": 0, + "label": "permission-manager", "link_to": "permission-manager", "type": "Page" }, { - "is_query_report": 0, + "label": "user-profile", "link_to": "user-profile", "type": "Page" } diff --git a/frappe/custom/desk_page/customization/customization.json b/frappe/custom/desk_page/customization/customization.json index dedfcaeeec..29f4cb745f 100644 --- a/frappe/custom/desk_page/customization/customization.json +++ b/frappe/custom/desk_page/customization/customization.json @@ -1,17 +1,19 @@ { "cards": [ { - "links": "[\n {\n \"label\": \"Dashboard\",\n \"name\": \"Dashboard\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Dashboard Chart\",\n \"name\": \"Dashboard Chart\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Dashboard Chart Source\",\n \"name\": \"Dashboard Chart Source\",\n \"type\": \"doctype\"\n }\n]", - "title": "Dashboards" + "hidden": 0, + "label": "Dashboards", + "links": "[\n {\n \"label\": \"Dashboard\",\n \"name\": \"Dashboard\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Dashboard Chart\",\n \"name\": \"Dashboard Chart\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Dashboard Chart Source\",\n \"name\": \"Dashboard Chart Source\",\n \"type\": \"doctype\"\n }\n]" }, { - "icon": "fa fa-glass", - "links": "[\n {\n \"description\": \"Change field properties (hide, readonly, permission etc.)\",\n \"label\": \"Customize Form\",\n \"name\": \"Customize Form\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Add fields to forms.\",\n \"label\": \"Custom Field\",\n \"name\": \"Custom Field\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Add custom javascript to forms.\",\n \"label\": \"Custom Script\",\n \"name\": \"Custom Script\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Add custom forms.\",\n \"label\": \"DocType\",\n \"name\": \"DocType\",\n \"type\": \"doctype\"\n }\n]", - "title": "Form Customization" + "hidden": 0, + "label": "Form Customization", + "links": "[\n {\n \"description\": \"Change field properties (hide, readonly, permission etc.)\",\n \"label\": \"Customize Form\",\n \"name\": \"Customize Form\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Add fields to forms.\",\n \"label\": \"Custom Field\",\n \"name\": \"Custom Field\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Add custom javascript to forms.\",\n \"label\": \"Custom Script\",\n \"name\": \"Custom Script\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Add custom forms.\",\n \"label\": \"DocType\",\n \"name\": \"DocType\",\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"description\": \"Add your own translations\",\n \"label\": \"Custom Translations\",\n \"name\": \"Translation\",\n \"type\": \"doctype\"\n }\n]", - "title": "Other" + "hidden": 0, + "label": "Other", + "links": "[\n {\n \"description\": \"Add your own translations\",\n \"label\": \"Custom Translations\",\n \"name\": \"Translation\",\n \"type\": \"doctype\"\n }\n]" } ], "category": "Administration", @@ -25,7 +27,7 @@ "idx": 0, "is_standard": 1, "label": "Customization", - "modified": "2020-03-12 16:30:42.155206", + "modified": "2020-04-01 11:24:40.787109", "modified_by": "Administrator", "module": "Custom", "name": "Customization", @@ -34,17 +36,17 @@ "pin_to_top": 0, "shortcuts": [ { - "is_query_report": 0, + "label": "Customize Form", "link_to": "Customize Form", "type": "DocType" }, { - "is_query_report": 0, + "label": "Custom Role", "link_to": "Custom Role", "type": "DocType" }, { - "is_query_report": 0, + "label": "Custom Script", "link_to": "Custom Script", "type": "DocType" } diff --git a/frappe/integrations/desk_page/integrations/integrations.json b/frappe/integrations/desk_page/integrations/integrations.json index 6ea871cd90..9201e223f8 100644 --- a/frappe/integrations/desk_page/integrations/integrations.json +++ b/frappe/integrations/desk_page/integrations/integrations.json @@ -1,25 +1,29 @@ { "cards": [ { - "links": "[\n {\n \"description\": \"Dropbox backup settings\",\n \"label\": \"Dropbox Settings\",\n \"name\": \"Dropbox Settings\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"S3 Backup Settings\",\n \"label\": \"S3 Backup Settings\",\n \"name\": \"S3 Backup Settings\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Google Drive Backup.\",\n \"label\": \"Google Drive\",\n \"name\": \"Google Drive\",\n \"type\": \"doctype\"\n }\n]", - "title": "Backup" + "hidden": 0, + "label": "Backup", + "links": "[\n {\n \"description\": \"Dropbox backup settings\",\n \"label\": \"Dropbox Settings\",\n \"name\": \"Dropbox Settings\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"S3 Backup Settings\",\n \"label\": \"S3 Backup Settings\",\n \"name\": \"S3 Backup Settings\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Google Drive Backup.\",\n \"label\": \"Google Drive\",\n \"name\": \"Google Drive\",\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"description\": \"Google API Settings.\",\n \"label\": \"Google Settings\",\n \"name\": \"Google Settings\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Google Contacts Integration.\",\n \"label\": \"Google Contacts\",\n \"name\": \"Google Contacts\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Google Calendar Integration.\",\n \"label\": \"Google Calendar\",\n \"name\": \"Google Calendar\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Google Drive Integration.\",\n \"label\": \"Google Drive\",\n \"name\": \"Google Drive\",\n \"type\": \"doctype\"\n }\n]", - "title": "Google Services" + "hidden": 0, + "label": "Google Services", + "links": "[\n {\n \"description\": \"Google API Settings.\",\n \"label\": \"Google Settings\",\n \"name\": \"Google Settings\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Google Contacts Integration.\",\n \"label\": \"Google Contacts\",\n \"name\": \"Google Contacts\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Google Calendar Integration.\",\n \"label\": \"Google Calendar\",\n \"name\": \"Google Calendar\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Google Drive Integration.\",\n \"label\": \"Google Drive\",\n \"name\": \"Google Drive\",\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"description\": \"Webhooks calling API requests into web apps\",\n \"label\": \"Webhook\",\n \"name\": \"Webhook\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Slack Webhooks for internal integration\",\n \"label\": \"Slack Webhook URL\",\n \"name\": \"Slack Webhook URL\",\n \"type\": \"doctype\"\n }\n]", - "title": "Webhook" + "hidden": 0, + "label": "Webhook", + "links": "[\n {\n \"description\": \"Webhooks calling API requests into web apps\",\n \"label\": \"Webhook\",\n \"name\": \"Webhook\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Slack Webhooks for internal integration\",\n \"label\": \"Slack Webhook URL\",\n \"name\": \"Slack Webhook URL\",\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"description\": \"Enter keys to enable login via Facebook, Google, GitHub.\",\n \"label\": \"Social Login Key\",\n \"name\": \"Social Login Key\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Ldap settings\",\n \"label\": \"LDAP Settings\",\n \"name\": \"LDAP Settings\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Register OAuth Client App\",\n \"label\": \"OAuth Client\",\n \"name\": \"OAuth Client\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Settings for OAuth Provider\",\n \"label\": \"OAuth Provider Settings\",\n \"name\": \"OAuth Provider Settings\",\n \"type\": \"doctype\"\n }\n]", - "title": "Authentication" + "hidden": 0, + "label": "Authentication", + "links": "[\n {\n \"description\": \"Enter keys to enable login via Facebook, Google, GitHub.\",\n \"label\": \"Social Login Key\",\n \"name\": \"Social Login Key\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Ldap settings\",\n \"label\": \"LDAP Settings\",\n \"name\": \"LDAP Settings\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Register OAuth Client App\",\n \"label\": \"OAuth Client\",\n \"name\": \"OAuth Client\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Settings for OAuth Provider\",\n \"label\": \"OAuth Provider Settings\",\n \"name\": \"OAuth Provider Settings\",\n \"type\": \"doctype\"\n }\n]" }, { - "icon": "fa fa-star", - "links": "[\n {\n \"description\": \"Braintree payment gateway settings\",\n \"label\": \"Braintree Settings\",\n \"name\": \"Braintree Settings\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"PayPal payment gateway settings\",\n \"label\": \"PayPal Settings\",\n \"name\": \"PayPal Settings\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Razorpay Payment gateway settings\",\n \"label\": \"Razorpay Settings\",\n \"name\": \"Razorpay Settings\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Stripe payment gateway settings\",\n \"label\": \"Stripe Settings\",\n \"name\": \"Stripe Settings\",\n \"type\": \"doctype\"\n }\n]", - "title": "Payments" + "hidden": 0, + "label": "Payments", + "links": "[\n {\n \"description\": \"Braintree payment gateway settings\",\n \"label\": \"Braintree Settings\",\n \"name\": \"Braintree Settings\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"PayPal payment gateway settings\",\n \"label\": \"PayPal Settings\",\n \"name\": \"PayPal Settings\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Razorpay Payment gateway settings\",\n \"label\": \"Razorpay Settings\",\n \"name\": \"Razorpay Settings\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Stripe payment gateway settings\",\n \"label\": \"Stripe Settings\",\n \"name\": \"Stripe Settings\",\n \"type\": \"doctype\"\n }\n]" } ], "category": "Administration", @@ -34,7 +38,7 @@ "idx": 0, "is_standard": 1, "label": "Integrations", - "modified": "2020-03-12 16:30:42.823316", + "modified": "2020-04-01 11:24:40.751651", "modified_by": "Administrator", "module": "Integrations", "name": "Integrations", diff --git a/frappe/website/desk_page/website/website.json b/frappe/website/desk_page/website/website.json index 915a9d2554..9171018523 100644 --- a/frappe/website/desk_page/website/website.json +++ b/frappe/website/desk_page/website/website.json @@ -1,26 +1,29 @@ { "cards": [ { - "icon": "fa fa-cog", - "links": "[\n {\n \"description\": \"Setup of top navigation bar, footer and logo.\",\n \"label\": \"Website Settings\",\n \"name\": \"Website Settings\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"List of themes for Website.\",\n \"label\": \"Website Theme\",\n \"name\": \"Website Theme\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Javascript to append to the head section of the page.\",\n \"label\": \"Website Script\",\n \"name\": \"Website Script\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Settings for About Us Page.\",\n \"label\": \"About Us Settings\",\n \"name\": \"About Us Settings\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Settings for Contact Us Page.\",\n \"label\": \"Contact Us Settings\",\n \"name\": \"Contact Us Settings\",\n \"type\": \"doctype\"\n }\n]", - "title": "Setup" + "hidden": 0, + "label": "Setup", + "links": "[\n {\n \"description\": \"Setup of top navigation bar, footer and logo.\",\n \"label\": \"Website Settings\",\n \"name\": \"Website Settings\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"List of themes for Website.\",\n \"label\": \"Website Theme\",\n \"name\": \"Website Theme\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Javascript to append to the head section of the page.\",\n \"label\": \"Website Script\",\n \"name\": \"Website Script\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Settings for About Us Page.\",\n \"label\": \"About Us Settings\",\n \"name\": \"About Us Settings\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Settings for Contact Us Page.\",\n \"label\": \"Contact Us Settings\",\n \"name\": \"Contact Us Settings\",\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"description\": \"Single Post (article).\",\n \"label\": \"Blog Post\",\n \"name\": \"Blog Post\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"A user who posts blogs.\",\n \"label\": \"Blogger\",\n \"name\": \"Blogger\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Categorize blog posts.\",\n \"label\": \"Blog Category\",\n \"name\": \"Blog Category\",\n \"type\": \"doctype\"\n }\n]", - "title": "Blog" + "hidden": 0, + "label": "Blog", + "links": "[\n {\n \"description\": \"Single Post (article).\",\n \"label\": \"Blog Post\",\n \"name\": \"Blog Post\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"A user who posts blogs.\",\n \"label\": \"Blogger\",\n \"name\": \"Blogger\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Categorize blog posts.\",\n \"label\": \"Blog Category\",\n \"name\": \"Blog Category\",\n \"type\": \"doctype\"\n }\n]" }, { - "icon": "fa fa-star", - "links": "[\n {\n \"description\": \"Content web page.\",\n \"label\": \"Web Page\",\n \"name\": \"Web Page\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"User editable form on Website.\",\n \"label\": \"Web Form\",\n \"name\": \"Web Form\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Website Sidebar\",\n \"name\": \"Website Sidebar\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Embed image slideshows in website pages.\",\n \"label\": \"Website Slideshow\",\n \"name\": \"Website Slideshow\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Add meta tags to your web pages\",\n \"label\": \"Website Route Meta\",\n \"name\": \"Website Route Meta\",\n \"type\": \"doctype\"\n }\n]", - "title": "Web Site" + "hidden": 0, + "label": "Web Site", + "links": "[\n {\n \"description\": \"Content web page.\",\n \"label\": \"Web Page\",\n \"name\": \"Web Page\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"User editable form on Website.\",\n \"label\": \"Web Form\",\n \"name\": \"Web Form\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Website Sidebar\",\n \"name\": \"Website Sidebar\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Embed image slideshows in website pages.\",\n \"label\": \"Website Slideshow\",\n \"name\": \"Website Slideshow\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Add meta tags to your web pages\",\n \"label\": \"Website Route Meta\",\n \"name\": \"Website Route Meta\",\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"label\": \"Portal Settings\",\n \"name\": \"Portal Settings\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n }\n]", - "title": "Portal" + "hidden": 0, + "label": "Portal", + "links": "[\n {\n \"label\": \"Portal Settings\",\n \"name\": \"Portal Settings\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n }\n]" }, { - "links": "[\n {\n \"label\": \"Help Category\",\n \"name\": \"Help Category\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Help Article\",\n \"name\": \"Help Article\",\n \"type\": \"doctype\"\n }\n]", - "title": "Knowledge Base" + "hidden": 0, + "label": "Knowledge Base", + "links": "[\n {\n \"label\": \"Help Category\",\n \"name\": \"Help Category\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Help Article\",\n \"name\": \"Help Article\",\n \"type\": \"doctype\"\n }\n]" } ], "category": "Modules", @@ -34,7 +37,7 @@ "idx": 0, "is_standard": 1, "label": "Website", - "modified": "2020-03-12 16:30:43.092622", + "modified": "2020-04-01 11:24:40.726934", "modified_by": "Administrator", "module": "Website", "name": "Website", @@ -45,30 +48,30 @@ { "color": "", "format": "{} Published", - "is_query_report": 0, + "label": "Blog Post", "link_to": "Blog Post", "stats_filter": "{\"published\":\"1\"}", "type": "DocType" }, { "format": "{} Active", - "is_query_report": 0, + "label": "Blogger", "link_to": "Blogger", "stats_filter": "{\"disabled\": 0}", "type": "DocType" }, { - "is_query_report": 0, + "label": "Web Page", "link_to": "Web Page", "type": "DocType" }, { - "is_query_report": 0, + "label": "Web Form", "link_to": "Web Form", "type": "DocType" }, { - "is_query_report": 0, + "label": "Website Settings", "link_to": "Website Settings", "type": "DocType" } From 0bd0188addf0c10d109f83bfa83a78f01fe6449c Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Thu, 2 Apr 2020 13:19:43 +0530 Subject: [PATCH 048/115] fix: new_widget shows if max count not exceeded --- .../public/js/frappe/widgets/widget_group.js | 26 +++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/frappe/public/js/frappe/widgets/widget_group.js b/frappe/public/js/frappe/widgets/widget_group.js index 7acb9b63de..41ea7fae71 100644 --- a/frappe/public/js/frappe/widgets/widget_group.js +++ b/frappe/public/js/frappe/widgets/widget_group.js @@ -73,6 +73,8 @@ export default class WidgetGroup { this.widgets_list.push(widget_object); this.widgets_dict[widget.name] = widget_object; + + return widget_object } customize() { @@ -81,29 +83,43 @@ export default class WidgetGroup { wid.customize(this.options); }) + this.options.allow_create && this.setup_new_widget(); + this.options.allow_sorting && this.setup_sortable(); + } + + setup_new_widget() { const max = this.options ? this.options.max_widget_count || Number.POSITIVE_INFINITY : Number.POSITIVE_INFINITY; - if (this.options.allow_create && this.widgets_list.length < max) { + if (this.widgets_list.length < max) { this.new_widget = new NewWidget({ container: this.body, type: this.type, on_create: (config) => { + // Remove new widget this.new_widget.delete(); - this.add_widget(config); - this.customize(); + delete this.new_widget; + + // Add new widget and customize it + let wid = this.add_widget(config); + wid.customize(this.options); + + // Put back the new widget if required + if (this.widgets_list.length < max) { + this.setup_new_widget(); + } } }) } - - this.options.allow_sorting && this.setup_sortable(); } on_delete(name) { this.widgets_list = this.widgets_list.filter(wid => name != wid.name); delete this.widgets_dict[name]; this.update_widget_order(); + + if (!this.new_widget) this.setup_new_widget(); } update_widget_order() { From 3dd2c756f13e95776c95d7788481b9d3e637da19 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Mon, 6 Apr 2020 14:00:43 +0530 Subject: [PATCH 049/115] fix: added comma --- frappe/core/page/dashboard/dashboard.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/core/page/dashboard/dashboard.js b/frappe/core/page/dashboard/dashboard.js index 69e14f65e8..30941f94c0 100644 --- a/frappe/core/page/dashboard/dashboard.js +++ b/frappe/core/page/dashboard/dashboard.js @@ -98,7 +98,7 @@ class Dashboard { allow_delete: false, allow_hiding: false, allow_edit: false, - } + }, widgets: this.charts, }); }); From 62b48aeca4306c28c45912854a10932b37c159a4 Mon Sep 17 00:00:00 2001 From: prssanna Date: Mon, 6 Apr 2020 17:52:44 +0530 Subject: [PATCH 050/115] fix: remove field if no docfield exists --- frappe/public/js/frappe/list/list_sidebar_group_by.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/frappe/public/js/frappe/list/list_sidebar_group_by.js b/frappe/public/js/frappe/list/list_sidebar_group_by.js index bd37b71ae4..f72ff33e4c 100644 --- a/frappe/public/js/frappe/list/list_sidebar_group_by.js +++ b/frappe/public/js/frappe/list/list_sidebar_group_by.js @@ -53,14 +53,17 @@ frappe.views.ListGroupBy = class ListGroupBy { render_group_by_items() { let get_item_html = (fieldname) => { - let label; - let fieldtype; + let label, fieldtype; if (fieldname === 'assigned_to') { label = __('Assigned To'); } else if (fieldname === 'owner') { label = __('Created By'); } else { label = frappe.meta.get_label(this.doctype, fieldname); + let docfield = frappe.meta.get_docfield(this.doctype, fieldname); + if (!docfield) { + return; + } fieldtype = frappe.meta.get_docfield(this.doctype, fieldname).fieldtype; } From 6199f980205e97d3978902b79743d4fc2f28bf8c Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Mon, 6 Apr 2020 18:48:42 +0530 Subject: [PATCH 051/115] feat: disable shortcut events in customize mode --- frappe/public/js/frappe/widgets/shortcut_widget.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frappe/public/js/frappe/widgets/shortcut_widget.js b/frappe/public/js/frappe/widgets/shortcut_widget.js index ed5cbf5e5a..8bedc556ac 100644 --- a/frappe/public/js/frappe/widgets/shortcut_widget.js +++ b/frappe/public/js/frappe/widgets/shortcut_widget.js @@ -29,6 +29,8 @@ export default class ShortcutWidget extends Widget { setup_events() { this.widget.click(() => { + if (this.in_customize_mode) return + let route = generate_route({ route: this.route, name: this.link_to, From 95a789763b67989f6c2dd04a8db796e7dc353ec6 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Mon, 6 Apr 2020 18:51:12 +0530 Subject: [PATCH 052/115] feat: disable link events in customize mode --- frappe/public/js/frappe/widgets/links_widget.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/frappe/public/js/frappe/widgets/links_widget.js b/frappe/public/js/frappe/widgets/links_widget.js index b93b592117..1f186aa6c2 100644 --- a/frappe/public/js/frappe/widgets/links_widget.js +++ b/frappe/public/js/frappe/widgets/links_widget.js @@ -80,21 +80,22 @@ export default class LinksWidget extends Widget { const popover = link.find(".module-link-popover"); link_label.mouseover(() => { + if (this.in_customize_mode) return popover.show(); }); link_label.mouseout(() => popover.hide()); } else { - if (link_label.hasClass("help-video-link")) { - link_label.click(event => { + link_label.click(event => { + if (this.in_customize_mode) return + + if (link_label.hasClass("help-video-link")) { let yt_id = event.target.dataset.youtubeid; frappe.help.show_video(yt_id); - }); - } else { - link_label.click(event => { + } else { let route = event.target.dataset.route; frappe.set_route(route); - }); - } + } + }); } }); } From ed9fd709adb8a9296f7d94fce6c213cf0d06bbfa Mon Sep 17 00:00:00 2001 From: "Chinmay D. Pai" Date: Mon, 6 Apr 2020 19:02:30 +0530 Subject: [PATCH 053/115] fix: update newsletter status on sending sets email_sent, schedule_send, and scheduled_to_send on newsletter being sent also switch to raw sql query to avoid default set by coalesce Signed-off-by: Chinmay D. Pai --- frappe/email/doctype/newsletter/newsletter.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/frappe/email/doctype/newsletter/newsletter.py b/frappe/email/doctype/newsletter/newsletter.py index 2d40ffd800..056f3a0b02 100755 --- a/frappe/email/doctype/newsletter/newsletter.py +++ b/frappe/email/doctype/newsletter/newsletter.py @@ -51,9 +51,6 @@ class Newsletter(WebsiteGenerator): frappe.msgprint(_("Scheduled to send to {0} recipients").format(len(self.recipients))) - frappe.db.set(self, "email_sent", 1) - frappe.db.set(self, "schedule_send", now_datetime()) - frappe.db.set(self, 'scheduled_to_send', len(self.recipients)) else: frappe.msgprint(_("Newsletter should have atleast one recipient")) @@ -217,6 +214,9 @@ def send_newsletter(newsletter): try: doc = frappe.get_doc("Newsletter", newsletter) doc.queue_all() + doc.db_set("email_sent", 1) + doc.db_set("schedule_send", now_datetime()) + doc.db_set("scheduled_to_send", len(self.recipients)) except: frappe.db.rollback() @@ -265,9 +265,10 @@ def get_newsletter_list(doctype, txt, filters, limit_start, limit_page_length=20 def send_scheduled_email(): """Send scheduled newsletter to the recipients.""" - scheduled_newsletter = frappe.get_all('Newsletter', filters = { - 'schedule_send': ('<=', now_datetime()), - 'email_sent': 0 - }, fields = ['name']) + scheduled_newsletter = frappe.db.sql(""" +SELECT name from `tabNewsletter` +WHERE schedule_send <= %s +AND email_sent = 0 +""", now_datetime(), as_dict=1) for newsletter in scheduled_newsletter: - send_newsletter(newsletter.name) \ No newline at end of file + send_newsletter(newsletter.name) From 27b193914641cbe23d416d529a97808c9dc35bdd Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Mon, 6 Apr 2020 19:20:53 +0530 Subject: [PATCH 054/115] fix: retain container on reload of page --- frappe/public/js/frappe/views/desktop/desktop.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/frappe/public/js/frappe/views/desktop/desktop.js b/frappe/public/js/frappe/views/desktop/desktop.js index c8c99295e2..3311af301f 100644 --- a/frappe/public/js/frappe/views/desktop/desktop.js +++ b/frappe/public/js/frappe/views/desktop/desktop.js @@ -105,8 +105,6 @@ export default class Desktop { } this.current_page = page; localStorage.current_desk_page = page; - frappe.set_route("workspace", page); - this.pages[page] ? this.pages[page].show() : this.make_page(page); } @@ -134,6 +132,7 @@ export default class Desktop { class DesktopPage { constructor({ container, page_name }) { + frappe.desk_page = this; this.container = container; this.page_name = page_name; this.sections = {}; @@ -142,6 +141,8 @@ class DesktopPage { } show() { + console.log("Showing ", this.page_name) + frappe.desk_page = this; this.page.show(); } @@ -151,7 +152,7 @@ class DesktopPage { reload() { this.in_customize_mode = false; - this.container.empty(); + this.page && this.page.remove(); this.make(); this.setup_events(); } From 73623547fc28405835d2e13fe38f17e5f9d7a29c Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Mon, 6 Apr 2020 19:28:20 +0530 Subject: [PATCH 055/115] feat: filter blocked modules --- frappe/desk/desktop.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/frappe/desk/desktop.py b/frappe/desk/desktop.py index a639400670..1edc2e57ec 100644 --- a/frappe/desk/desktop.py +++ b/frappe/desk/desktop.py @@ -30,15 +30,20 @@ class Workspace: return frappe.get_doc("Desk Page", self.page_name) def init(self): - self.doc = self.get_page_for_user() - user = frappe.get_user() user.build_permissions() - self.user = user + self.blocked_modules = frappe.get_doc('User', frappe.session.user).get_blocked_modules() + self.doc = self.get_page_for_user() + + if self.doc.module in self.blocked_modules: + raise frappe.PermissionError + + self.user = user self.allowed_pages = get_allowed_pages() self.allowed_reports = get_allowed_reports() + self.table_counts = get_table_with_counts() self.restricted_doctypes = build_domain_restriced_doctype_cache() self.restricted_pages = build_domain_restriced_page_cache() @@ -47,7 +52,8 @@ class Workspace: pages = frappe.get_all("Desk Page", filters={ "extends": self.page_name, 'restrict_to_domain': ['in', frappe.get_active_domains()], - 'for_user': '' + 'for_user': '', + 'module': ['not in', self.blocked_modules] }) pages = [frappe.get_doc("Desk Page", page['name']) for page in pages] @@ -223,11 +229,14 @@ def get_desk_sidebar_items(): """Get list of sidebar items for desk """ # don't get domain restricted pages + blocked_modules = frappe.get_doc('User', frappe.session.user).get_blocked_modules() + filters = { 'restrict_to_domain': ['in', frappe.get_active_domains()], 'extends_another_page': 0, 'is_standard': 1, - 'for_user': '' + 'for_user': '', + 'module': ['not in', blocked_modules] } if not frappe.local.conf.developer_mode: From a1e297ecb1754551eeece7e79ab1345b45b8ba7a Mon Sep 17 00:00:00 2001 From: "Chinmay D. Pai" Date: Mon, 6 Apr 2020 19:46:57 +0530 Subject: [PATCH 056/115] chore: fix codacy issue Signed-off-by: Chinmay D. Pai --- frappe/email/doctype/newsletter/newsletter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/email/doctype/newsletter/newsletter.py b/frappe/email/doctype/newsletter/newsletter.py index 056f3a0b02..ccb2e87264 100755 --- a/frappe/email/doctype/newsletter/newsletter.py +++ b/frappe/email/doctype/newsletter/newsletter.py @@ -216,7 +216,7 @@ def send_newsletter(newsletter): doc.queue_all() doc.db_set("email_sent", 1) doc.db_set("schedule_send", now_datetime()) - doc.db_set("scheduled_to_send", len(self.recipients)) + doc.db_set("scheduled_to_send", len(doc.recipients)) except: frappe.db.rollback() From 074be8124d90339a13cf4f4e531d070b2fd681a6 Mon Sep 17 00:00:00 2001 From: "Chinmay D. Pai" Date: Tue, 7 Apr 2020 15:47:20 +0530 Subject: [PATCH 057/115] fix: set email_sent after enqueuing newsletters Signed-off-by: Chinmay D. Pai --- frappe/email/doctype/newsletter/newsletter.py | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/frappe/email/doctype/newsletter/newsletter.py b/frappe/email/doctype/newsletter/newsletter.py index ccb2e87264..a847940448 100755 --- a/frappe/email/doctype/newsletter/newsletter.py +++ b/frappe/email/doctype/newsletter/newsletter.py @@ -68,8 +68,8 @@ class Newsletter(WebsiteGenerator): attachments = [] if self.send_attachements: - files = frappe.get_all("File", fields = ["name"], filters = {"attached_to_doctype": "Newsletter", - "attached_to_name":self.name}, order_by="creation desc") + files = frappe.get_all("File", fields=["name"], filters={"attached_to_doctype": "Newsletter", + "attached_to_name": self.name}, order_by="creation desc") for file in files: try: @@ -79,17 +79,21 @@ class Newsletter(WebsiteGenerator): except IOError: frappe.throw(_("Unable to find attachment {0}").format(file.name)) - send(recipients = self.recipients, sender = sender, - subject = self.subject, message = self.message, - reference_doctype = self.doctype, reference_name = self.name, - add_unsubscribe_link = self.send_unsubscribe_link, attachments=attachments, - unsubscribe_method = "/unsubscribe", - unsubscribe_params = {"name": self.name}, - send_priority = 0, queue_separately=True) + send(recipients=self.recipients, sender=sender, + subject=self.subject, message=self.message, + reference_doctype=self.doctype, reference_name=self.name, + add_unsubscribe_link=self.send_unsubscribe_link, attachments=attachments, + unsubscribe_method="/unsubscribe", + unsubscribe_params={"name": self.name}, + send_priority=0, queue_separately=True) if not frappe.flags.in_test: frappe.db.auto_commit_on_many_writes = False + self.db_set("email_sent", 1) + self.db_set("schedule_send", now_datetime()) + self.db_set("scheduled_to_send", len(self.recipients)) + def get_recipients(self): """Get recipients from Email Group""" recipients_list = [] From 8e0c9201a566f2276602f5cf12159b8f686cc2e0 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Tue, 7 Apr 2020 16:08:55 +0530 Subject: [PATCH 058/115] chore: remove duplicate db set --- frappe/email/doctype/newsletter/newsletter.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/frappe/email/doctype/newsletter/newsletter.py b/frappe/email/doctype/newsletter/newsletter.py index a847940448..b022655699 100755 --- a/frappe/email/doctype/newsletter/newsletter.py +++ b/frappe/email/doctype/newsletter/newsletter.py @@ -218,9 +218,6 @@ def send_newsletter(newsletter): try: doc = frappe.get_doc("Newsletter", newsletter) doc.queue_all() - doc.db_set("email_sent", 1) - doc.db_set("schedule_send", now_datetime()) - doc.db_set("scheduled_to_send", len(doc.recipients)) except: frappe.db.rollback() From 3d772709672a43a7546153f25cfb4a87b2a51e7a Mon Sep 17 00:00:00 2001 From: prssanna Date: Tue, 7 Apr 2020 18:05:17 +0530 Subject: [PATCH 059/115] fix: set animate as true --- frappe/public/js/frappe/form/grid_row.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/public/js/frappe/form/grid_row.js b/frappe/public/js/frappe/form/grid_row.js index 8cb7d7d664..31d62dc445 100644 --- a/frappe/public/js/frappe/form/grid_row.js +++ b/frappe/public/js/frappe/form/grid_row.js @@ -550,7 +550,7 @@ export default class GridRow { hide_form() { frappe.dom.unfreeze(); this.row.toggle(true); - frappe.utils.scroll_to(this.row, false, 15); + frappe.utils.scroll_to(this.row, true, 15); this.refresh(); if(cur_frm) cur_frm.cur_grid = null; this.wrapper.removeClass("grid-row-open"); From 0fdcce62a5ba3b67f9b31c4b4695ec34c1882694 Mon Sep 17 00:00:00 2001 From: prssanna Date: Tue, 7 Apr 2020 18:07:27 +0530 Subject: [PATCH 060/115] style: missing semicolon --- frappe/public/js/frappe/form/grid_row_form.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/public/js/frappe/form/grid_row_form.js b/frappe/public/js/frappe/form/grid_row_form.js index 47da96f4d7..f93640936f 100644 --- a/frappe/public/js/frappe/form/grid_row_form.js +++ b/frappe/public/js/frappe/form/grid_row_form.js @@ -9,7 +9,7 @@ export default class GridRowForm { var me = this; this.make_form(); this.form_area.empty(); - frappe.utils.scroll_to(0, false, 0, this.wrapper.find('.grid-form-body')) + frappe.utils.scroll_to(0, false, 0, this.wrapper.find('.grid-form-body')); this.layout = new frappe.ui.form.Layout({ fields: this.row.docfields, From 10a9f3111da2c9db07bf10b459547ec1c97a567e Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Tue, 7 Apr 2020 19:07:35 +0530 Subject: [PATCH 061/115] feat: remove label as mandatory field --- .../doctype/desk_shortcut/desk_shortcut.json | 6 +-- frappe/public/js/frappe/widgets/new_widget.js | 37 ++++++++++++------- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/frappe/desk/doctype/desk_shortcut/desk_shortcut.json b/frappe/desk/doctype/desk_shortcut/desk_shortcut.json index d008a94834..9f8990732a 100644 --- a/frappe/desk/doctype/desk_shortcut/desk_shortcut.json +++ b/frappe/desk/doctype/desk_shortcut/desk_shortcut.json @@ -6,9 +6,9 @@ "engine": "InnoDB", "field_order": [ "type", - "link_to", - "column_break_4", "label", + "column_break_4", + "link_to", "icon", "restrict_to_domain", "section_break_5", @@ -87,7 +87,7 @@ ], "istable": 1, "links": [], - "modified": "2020-03-31 14:29:37.021121", + "modified": "2020-04-07 19:04:23.645198", "modified_by": "Administrator", "module": "Desk", "name": "Desk Shortcut", diff --git a/frappe/public/js/frappe/widgets/new_widget.js b/frappe/public/js/frappe/widgets/new_widget.js index d0dabe6678..73ad401256 100644 --- a/frappe/public/js/frappe/widgets/new_widget.js +++ b/frappe/public/js/frappe/widgets/new_widget.js @@ -1,7 +1,7 @@ const WIDGET_DOCTYPE_MAP = { chart: "Desk Chart", shortcut: "Desk Shortcut", -} +}; export default class NewWidget { constructor(opts) { @@ -14,7 +14,7 @@ export default class NewWidget { } customize() { - return + return; } make() { @@ -24,18 +24,18 @@ export default class NewWidget { } get_title() { - return __(`New ${frappe.utils.to_title_case(this.type)}`) + return __(`New ${frappe.utils.to_title_case(this.type)}`); } make_widget() { this.widget = $(`
+ ${this.get_title()}
`); - this.body = this.widget + this.body = this.widget; } setup_events() { - this.widget.on('click', () => this.open_dialog()) + this.widget.on("click", () => this.open_dialog()); } delete() { @@ -43,26 +43,37 @@ export default class NewWidget { } open_dialog() { - let doctype = WIDGET_DOCTYPE_MAP[this.type] + let doctype = WIDGET_DOCTYPE_MAP[this.type]; if (!doctype) { - console.warn(`Could not find ${this.type}`) + console.warn(`Could not find ${this.type}`); } frappe.model.with_doctype(doctype, () => { + let fields = frappe.get_meta(doctype).fields; + + if (this.type == "shortcut") { + let fields_to_remove = ["label"]; + fields = fields.filter( + (df) => !fields_to_remove.includes(df.fieldname) + ); + } + let new_dialog = new frappe.ui.Dialog({ title: this.get_title(), - fields: frappe.get_meta(doctype).fields, + fields: fields, primary_action: (data) => { - if (this.type == 'chart' && !data.label) { + if (this.type == "chart" && !data.label) { data.label = data.chart_name; } - if (this.type == 'shortcut' && !data.label) { + if (this.type == "shortcut" && !data.label) { data.label = data.link_to; } - data.name = `${this.type}-${this.label}-${frappe.utils.get_random(20)}`; + data.name = `${this.type}-${ + this.label + }-${frappe.utils.get_random(20)}`; new_dialog.hide(); this.on_create(data); @@ -70,7 +81,7 @@ export default class NewWidget { primary_action_label: __("Add"), }); - new_dialog.show() + new_dialog.show(); }); } -} \ No newline at end of file +} From 009c2cad949421622c92737dbaac5afbc4a94ce2 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Tue, 7 Apr 2020 20:21:57 +0530 Subject: [PATCH 062/115] feat: cleanup --- frappe/public/js/frappe/views/desktop/desktop.js | 1 - 1 file changed, 1 deletion(-) diff --git a/frappe/public/js/frappe/views/desktop/desktop.js b/frappe/public/js/frappe/views/desktop/desktop.js index 3311af301f..249308a79f 100644 --- a/frappe/public/js/frappe/views/desktop/desktop.js +++ b/frappe/public/js/frappe/views/desktop/desktop.js @@ -141,7 +141,6 @@ class DesktopPage { } show() { - console.log("Showing ", this.page_name) frappe.desk_page = this; this.page.show(); } From 749f3f60216d42cf95295e0e3551ede4251cc437 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Tue, 7 Apr 2020 20:22:17 +0530 Subject: [PATCH 063/115] feat: object oriented new widget --- frappe/public/js/frappe/widgets/new_widget.js | 202 ++++++++++++++---- .../public/js/frappe/widgets/widget_group.js | 6 +- 2 files changed, 163 insertions(+), 45 deletions(-) diff --git a/frappe/public/js/frappe/widgets/new_widget.js b/frappe/public/js/frappe/widgets/new_widget.js index 73ad401256..1fd019cb73 100644 --- a/frappe/public/js/frappe/widgets/new_widget.js +++ b/frappe/public/js/frappe/widgets/new_widget.js @@ -1,18 +1,9 @@ -const WIDGET_DOCTYPE_MAP = { - chart: "Desk Chart", - shortcut: "Desk Shortcut", -}; - -export default class NewWidget { +export class NewWidget { constructor(opts) { Object.assign(this, opts); this.make(); } - refresh() { - // - } - customize() { return; } @@ -42,46 +33,173 @@ export default class NewWidget { this.widget.remove(); } + get_fields() { + // + } + + process_data(data) { + return data + } + + setup_dialog_events() { + // + } + open_dialog() { - let doctype = WIDGET_DOCTYPE_MAP[this.type]; + this.dialog = new frappe.ui.Dialog({ + title: this.get_title(), + fields: this.get_fields(), + primary_action: (data) => { + data = this.process_data(data); + this.dialog.hide(); + this.on_create(data); + }, + primary_action_label: __("Add"), + }); - if (!doctype) { - console.warn(`Could not find ${this.type}`); - } + this.setup_dialog_events(); - frappe.model.with_doctype(doctype, () => { - let fields = frappe.get_meta(doctype).fields; + this.dialog.show(); + } - if (this.type == "shortcut") { - let fields_to_remove = ["label"]; - fields = fields.filter( - (df) => !fields_to_remove.includes(df.fieldname) - ); - } + hide_field(fieldname) { + this.dialog.set_df_property(fieldname, "hidden", true); + } - let new_dialog = new frappe.ui.Dialog({ - title: this.get_title(), - fields: fields, - primary_action: (data) => { - if (this.type == "chart" && !data.label) { - data.label = data.chart_name; + show_field(fieldname) { + this.dialog.set_df_property(fieldname, "hidden", false); + } +} + +export class NewChartWidget extends NewWidget { + constructor(opts) { + super(opts); + } + + get_fields() { + return [ + { + fieldtype: "Link", + fieldname: "chart_name", + label: "Chart Name", + options: "Dashboard Chart", + reqd: 1, + }, + { + fieldtype: "Data", + fieldname: "label", + label: "Label" + }, + ]; + } + + process_data(data) { + data.label = data.chart_name; + return data + } +} + +export class NewShortcutWidget extends NewWidget { + constructor(opts) { + super(opts); + window.neww = this; + } + + get_fields() { + return [ + { + fieldtype: "Select", + fieldname: "type", + label: "Type", + reqd: 1, + options: "DocType\nReport\nPage", + onchange: () => { + if (this.dialog.get_value("type") == "DocType") { + this.dialog.fields_dict.link_to.get_query = () => { + return { filters: { "istable": false }} + } } - - if (this.type == "shortcut" && !data.label) { - data.label = data.link_to; - } - - data.name = `${this.type}-${ - this.label - }-${frappe.utils.get_random(20)}`; - - new_dialog.hide(); - this.on_create(data); }, - primary_action_label: __("Add"), - }); + }, + { + fieldtype: "Column Break", + fieldname: "column_break_4", + }, + { + fieldtype: "Dynamic Link", + fieldname: "link_to", + label: "Link To", + reqd: 1, + options: "type", + onchange: () => { + let dg = this.dialog; + if (this.dialog.get_value("type") == "DocType") { + this.show_field('count_section_break'); + this.show_field('filters_section_break'); + this.setup_filter(); + } else { + this.hide_field('count_section_break'); + this.hide_field('filters_section_break'); + } + }, + }, + { + fieldtype: "Section Break", + fieldname: "count_section_break", + label: "Count Filter", + hidden: 1, + }, + { + fieldtype: "Color", + fieldname: "color", + label: "Color", + }, + { + fieldtype: "Column Break", + fieldname: "column_break_3", + }, + { + fieldtype: "Data", + fieldname: "format", + label: "Format", + description: "For Example: {} Open", + }, + { + fieldtype: "Section Break", + fieldname: "filters_section_break", + hidden: 1, + }, + { + fieldtype: "HTML", + fieldname: "filter_area", + }, + ]; + } - new_dialog.show(); + process_data(data) { + data.label = data.link_to; + + return data + } + + setup_filter() { + if (this.filter_group) { + this.filter_group.wrapper.empty(); + delete this.filter_group; + } + this.filter_group = new frappe.ui.FilterGroup({ + parent: this.dialog.get_field('filter_area').$wrapper, + doctype: this.dialog.get_value('link_to'), + on_change: () => {}, }); } } + +export function get_new_widget_class(type) { + const widget_map = { + chart: NewChartWidget, + shortcut: NewShortcutWidget, + }; + + return widget_map[type] || NewWidget; +} diff --git a/frappe/public/js/frappe/widgets/widget_group.js b/frappe/public/js/frappe/widgets/widget_group.js index 41ea7fae71..cc57b66666 100644 --- a/frappe/public/js/frappe/widgets/widget_group.js +++ b/frappe/public/js/frappe/widgets/widget_group.js @@ -3,7 +3,7 @@ import BaseWidget from "../widgets/base_widget"; import ShortcutWidget from "../widgets/shortcut_widget"; import LinksWidget from "../widgets/links_widget"; import OnboardingWidget from "../widgets/onboarding_widget"; -import NewWidget from "../widgets/new_widget"; +import { get_new_widget_class } from "../widgets/new_widget"; frappe.provide('frappe.widget') @@ -13,7 +13,6 @@ const widget_factory = { shortcut: ShortcutWidget, links: LinksWidget, onboarding: OnboardingWidget, - new: NewWidget }; export default class WidgetGroup { @@ -93,7 +92,8 @@ export default class WidgetGroup { : Number.POSITIVE_INFINITY; if (this.widgets_list.length < max) { - this.new_widget = new NewWidget({ + const new_widget_class = get_new_widget_class(this.type) + this.new_widget = new new_widget_class({ container: this.body, type: this.type, on_create: (config) => { From 069db06b724705aa5c9677a256da6d24177d0b08 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Tue, 7 Apr 2020 21:08:13 +0530 Subject: [PATCH 064/115] chore: cleanup --- frappe/desk/desktop.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/frappe/desk/desktop.py b/frappe/desk/desktop.py index 1edc2e57ec..1f3a83735b 100644 --- a/frappe/desk/desktop.py +++ b/frappe/desk/desktop.py @@ -326,7 +326,6 @@ def save_customization(page, config): "charts_label": original_page.charts_label, "cards_label": original_page.cards_label, "shortcuts_label": original_page.shortcuts_label, - "charts_label": original_page.charts_label, "icon": original_page.icon, "module": original_page.module, "developer_mode_only": original_page.developer_mode_only, @@ -334,7 +333,6 @@ def save_customization(page, config): }) config = frappe._dict(loads(config)) - page_doc.charts = prepare_widget(config.charts, "Desk Chart", "charts") page_doc.shortcuts = prepare_widget(config.shortcuts, "Desk Shortcut", "shortcuts") page_doc.cards = prepare_widget(config.cards, "Desk Card", "cards") From 33cdd41b101448250f83f57d5c4672fbd1f7d805 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Tue, 7 Apr 2020 21:08:30 +0530 Subject: [PATCH 065/115] feat: set a random name --- frappe/public/js/frappe/widgets/new_widget.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frappe/public/js/frappe/widgets/new_widget.js b/frappe/public/js/frappe/widgets/new_widget.js index 1fd019cb73..2a4999fd0f 100644 --- a/frappe/public/js/frappe/widgets/new_widget.js +++ b/frappe/public/js/frappe/widgets/new_widget.js @@ -51,6 +51,8 @@ export class NewWidget { fields: this.get_fields(), primary_action: (data) => { data = this.process_data(data); + data.name = `${this.type}-${this.label}-${frappe.utils.get_random(20)}`; + this.dialog.hide(); this.on_create(data); }, From 4ceed892d02928112f7330f80d2352f494fe8866 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Tue, 7 Apr 2020 21:09:15 +0530 Subject: [PATCH 066/115] feat: setup new widget class for charts and shortcut --- frappe/public/js/frappe/widgets/new_widget.js | 32 ++++++++++++++++--- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/frappe/public/js/frappe/widgets/new_widget.js b/frappe/public/js/frappe/widgets/new_widget.js index 2a4999fd0f..1fbe3384ad 100644 --- a/frappe/public/js/frappe/widgets/new_widget.js +++ b/frappe/public/js/frappe/widgets/new_widget.js @@ -136,9 +136,17 @@ export class NewShortcutWidget extends NewWidget { onchange: () => { let dg = this.dialog; if (this.dialog.get_value("type") == "DocType") { - this.show_field('count_section_break'); - this.show_field('filters_section_break'); - this.setup_filter(); + let doctype = this.dialog.get_value("link_to") + frappe.db.get_value("DocType", doctype, "issingle").then(res => { + if (res.message.issingle) { + this.hide_field('count_section_break'); + this.hide_field('filters_section_break'); + } else { + this.setup_filter(doctype); + this.show_field('count_section_break'); + this.show_field('filters_section_break'); + } + }) } else { this.hide_field('count_section_break'); this.hide_field('filters_section_break'); @@ -179,21 +187,35 @@ export class NewShortcutWidget extends NewWidget { } process_data(data) { + let stats_filter = {}; + let filters = this.filter_group.get_filters(); + filters.forEach(arr => { + stats_filter[arr[1]] = [arr[2], arr[3]] + }); + + data.stats_filter = JSON.stringify(stats_filter); data.label = data.link_to; return data } - setup_filter() { + setup_filter(doctype) { if (this.filter_group) { this.filter_group.wrapper.empty(); delete this.filter_group; } + + this.filters = [] + this.filter_group = new frappe.ui.FilterGroup({ parent: this.dialog.get_field('filter_area').$wrapper, - doctype: this.dialog.get_value('link_to'), + doctype: doctype, on_change: () => {}, }); + + frappe.model.with_doctype(doctype, () => { + this.filter_group.add_filters_to_filter_group(this.filters); + }); } } From 57055b462ef10b5dc9b101e4b252ce0f5b281ca8 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Tue, 7 Apr 2020 21:09:27 +0530 Subject: [PATCH 067/115] feat: set customize mode for new widgets by default --- frappe/public/js/frappe/widgets/base_widget.js | 1 - frappe/public/js/frappe/widgets/shortcut_widget.js | 2 ++ frappe/public/js/frappe/widgets/widget_group.js | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/frappe/public/js/frappe/widgets/base_widget.js b/frappe/public/js/frappe/widgets/base_widget.js index 93093de84f..63fc49a166 100644 --- a/frappe/public/js/frappe/widgets/base_widget.js +++ b/frappe/public/js/frappe/widgets/base_widget.js @@ -63,7 +63,6 @@ export default class Widget { } make() { - this.in_customize_mode = false; this.make_widget(); this.widget.appendTo(this.container); } diff --git a/frappe/public/js/frappe/widgets/shortcut_widget.js b/frappe/public/js/frappe/widgets/shortcut_widget.js index 8bedc556ac..d96f135728 100644 --- a/frappe/public/js/frappe/widgets/shortcut_widget.js +++ b/frappe/public/js/frappe/widgets/shortcut_widget.js @@ -42,6 +42,8 @@ export default class ShortcutWidget extends Widget { } set_actions() { + if (this.in_customize_mode) return + this.widget.addClass('shortcut-widget-box'); const get_filter = new Function(`return ${this.stats_filter}`) if (this.type == "DocType" && this.stats_filter) { diff --git a/frappe/public/js/frappe/widgets/widget_group.js b/frappe/public/js/frappe/widgets/widget_group.js index cc57b66666..f121939748 100644 --- a/frappe/public/js/frappe/widgets/widget_group.js +++ b/frappe/public/js/frappe/widgets/widget_group.js @@ -101,6 +101,8 @@ export default class WidgetGroup { this.new_widget.delete(); delete this.new_widget; + config.in_customize_mode = 1; + // Add new widget and customize it let wid = this.add_widget(config); wid.customize(this.options); From 040abe2e2855a8e435fd37df1e7662737e285db3 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Wed, 8 Apr 2020 13:53:49 +0530 Subject: [PATCH 068/115] refactor: layout for new shortcut widget --- frappe/public/js/frappe/widgets/new_widget.js | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/frappe/public/js/frappe/widgets/new_widget.js b/frappe/public/js/frappe/widgets/new_widget.js index 1fbe3384ad..e85ecf1718 100644 --- a/frappe/public/js/frappe/widgets/new_widget.js +++ b/frappe/public/js/frappe/widgets/new_widget.js @@ -155,10 +155,20 @@ export class NewShortcutWidget extends NewWidget { }, { fieldtype: "Section Break", - fieldname: "count_section_break", + fieldname: "filters_section_break", label: "Count Filter", hidden: 1, }, + { + fieldtype: "HTML", + fieldname: "filter_area", + }, + { + fieldtype: "Section Break", + fieldname: "count_section_break", + label: "Count Customizations", + hidden: 1, + }, { fieldtype: "Color", fieldname: "color", @@ -174,15 +184,6 @@ export class NewShortcutWidget extends NewWidget { label: "Format", description: "For Example: {} Open", }, - { - fieldtype: "Section Break", - fieldname: "filters_section_break", - hidden: 1, - }, - { - fieldtype: "HTML", - fieldname: "filter_area", - }, ]; } From bd8c55110d999f11a74210e35bd2c1967826c66b Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Wed, 8 Apr 2020 13:54:01 +0530 Subject: [PATCH 069/115] fix: add color option to get_config --- frappe/public/js/frappe/widgets/shortcut_widget.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frappe/public/js/frappe/widgets/shortcut_widget.js b/frappe/public/js/frappe/widgets/shortcut_widget.js index d96f135728..a492aaf89b 100644 --- a/frappe/public/js/frappe/widgets/shortcut_widget.js +++ b/frappe/public/js/frappe/widgets/shortcut_widget.js @@ -21,6 +21,7 @@ export default class ShortcutWidget extends Widget { label: this.label, format: this.format, link_to: this.link_to, + color: this.color, restrict_to_domain: this.restrict_to_domain, stats_filter: this.stats_filter, type: this.type @@ -42,6 +43,7 @@ export default class ShortcutWidget extends Widget { } set_actions() { + console.log(this.in_customize_mode); if (this.in_customize_mode) return this.widget.addClass('shortcut-widget-box'); From 284c70809b2cf03314aedb960889d1561e51cb52 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Wed, 8 Apr 2020 14:20:52 +0530 Subject: [PATCH 070/115] fix: Translatable strings with trailing spaces --- .../customize_form_field.json | 4 +- .../doctype/oauth_client/oauth_client.json | 956 +++++++++--------- frappe/model/naming.py | 6 +- frappe/public/js/frappe/form/workflow.js | 26 +- .../emails/delete_data_confirmation.html | 3 +- 5 files changed, 499 insertions(+), 496 deletions(-) diff --git a/frappe/custom/doctype/customize_form_field/customize_form_field.json b/frappe/custom/doctype/customize_form_field/customize_form_field.json index 57b4cec23b..34778a76e9 100644 --- a/frappe/custom/doctype/customize_form_field/customize_form_field.json +++ b/frappe/custom/doctype/customize_form_field/customize_form_field.json @@ -358,7 +358,7 @@ "default": "0", "fieldname": "allow_in_quick_entry", "fieldtype": "Check", - "label": " Allow in Quick Entry " + "label": "Allow in Quick Entry" }, { "fieldname": "property_depends_on_section", @@ -385,7 +385,7 @@ "idx": 1, "istable": 1, "links": [], - "modified": "2020-03-16 14:53:40.619043", + "modified": "2020-04-07 14:53:40.619043", "modified_by": "Administrator", "module": "Custom", "name": "Customize Form Field", diff --git a/frappe/integrations/doctype/oauth_client/oauth_client.json b/frappe/integrations/doctype/oauth_client/oauth_client.json index 47ede6e280..d0d45c36ab 100644 --- a/frappe/integrations/doctype/oauth_client/oauth_client.json +++ b/frappe/integrations/doctype/oauth_client/oauth_client.json @@ -1,517 +1,517 @@ { - "allow_copy": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "autoname": "", - "beta": 0, - "creation": "2016-08-24 14:07:21.955052", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "Document", - "editable_grid": 1, - "engine": "InnoDB", + "allow_copy": 0, + "allow_guest_to_view": 0, + "allow_import": 0, + "allow_rename": 0, + "autoname": "", + "beta": 0, + "creation": "2016-08-24 14:07:21.955052", + "custom": 0, + "docstatus": 0, + "doctype": "DocType", + "document_type": "Document", + "editable_grid": 1, + "engine": "InnoDB", "fields": [ { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "", - "fieldname": "client_id", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "App Client ID", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "", + "fieldname": "client_id", + "fieldtype": "Data", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "App Client ID", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "app_name", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "App Name", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "app_name", + "fieldtype": "Data", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "App Name", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 1, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "user", - "fieldtype": "Link", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "User", - "length": 0, - "no_copy": 0, - "options": "User", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "user", + "fieldtype": "Link", + "hidden": 1, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "User", + "length": 0, + "no_copy": 0, + "options": "User", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "cb_1", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "cb_1", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "client_secret", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "App Client Secret", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "client_secret", + "fieldtype": "Data", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "App Client Secret", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "description": "If checked, users will not see the Confirm Access dialog.", - "fieldname": "skip_authorization", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Skip Authorization", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "description": "If checked, users will not see the Confirm Access dialog.", + "fieldname": "skip_authorization", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Skip Authorization", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "description": "", - "fieldname": "sb_1", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "description": "", + "fieldname": "sb_1", + "fieldtype": "Section Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "all openid", - "description": "A list of resources which the Client App will have access to after the user allows it.
e.g. project", - "fieldname": "scopes", - "fieldtype": "Text", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Scopes", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "all openid", + "description": "A list of resources which the Client App will have access to after the user allows it.
e.g. project", + "fieldname": "scopes", + "fieldtype": "Text", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Scopes", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 1, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "cb_3", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "cb_3", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "description": "URIs for receiving authorization code once the user allows access, as well as failure responses. Typically a REST endpoint exposed by the Client App.\n
e.g. http://hostname//api/method/frappe.www.login.login_via_facebook", - "fieldname": "redirect_uris", - "fieldtype": "Text", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Redirect URIs", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "description": "URIs for receiving authorization code once the user allows access, as well as failure responses. Typically a REST endpoint exposed by the Client App.\n
e.g. http://hostname//api/method/frappe.www.login.login_via_facebook", + "fieldname": "redirect_uris", + "fieldtype": "Text", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Redirect URIs", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "default_redirect_uri", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Default Redirect URI", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "default_redirect_uri", + "fieldtype": "Data", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Default Redirect URI", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 1, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 1, - "collapsible_depends_on": "1", - "columns": 0, - "fieldname": "sb_advanced", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": " Advanced Settings", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 1, + "collapsible_depends_on": "1", + "columns": 0, + "fieldname": "sb_advanced", + "fieldtype": "Section Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Advanced Settings", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "grant_type", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 1, - "label": "Grant Type", - "length": 0, - "no_copy": 0, - "options": "Authorization Code\nImplicit", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "grant_type", + "fieldtype": "Select", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 1, + "in_standard_filter": 1, + "label": "Grant Type", + "length": 0, + "no_copy": 0, + "options": "Authorization Code\nImplicit", + "permlevel": 0, + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "cb_2", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "cb_2", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "Code", - "fieldname": "response_type", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 1, - "label": "Response Type", - "length": 0, - "no_copy": 0, - "options": "Code\nToken", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "Code", + "fieldname": "response_type", + "fieldtype": "Select", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 1, + "in_standard_filter": 1, + "label": "Response Type", + "length": 0, + "no_copy": 0, + "options": "Code\nToken", + "permlevel": 0, + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2017-10-05 21:07:39.476360", - "modified_by": "Administrator", - "module": "Integrations", - "name": "OAuth Client", - "name_case": "", - "owner": "Administrator", + ], + "has_web_view": 0, + "hide_heading": 0, + "hide_toolbar": 0, + "idx": 0, + "image_view": 0, + "in_create": 0, + "is_submittable": 0, + "issingle": 0, + "istable": 0, + "max_attachments": 0, + "modified": "2020-04-07 21:07:39.476360", + "modified_by": "Administrator", + "module": "Integrations", + "name": "OAuth Client", + "name_case": "", + "owner": "Administrator", "permissions": [ { - "amend": 0, - "apply_user_permissions": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "System Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 0, + "amend": 0, + "apply_user_permissions": 0, + "cancel": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "if_owner": 0, + "import": 0, + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "set_user_permissions": 0, + "share": 1, + "submit": 0, "write": 1 } - ], - "quick_entry": 0, - "read_only": 0, - "read_only_onload": 0, - "show_name_in_global_search": 0, - "sort_field": "modified", - "sort_order": "DESC", - "title_field": "app_name", - "track_changes": 1, + ], + "quick_entry": 0, + "read_only": 0, + "read_only_onload": 0, + "show_name_in_global_search": 0, + "sort_field": "modified", + "sort_order": "DESC", + "title_field": "app_name", + "track_changes": 1, "track_seen": 0 } \ No newline at end of file diff --git a/frappe/model/naming.py b/frappe/model/naming.py index 78d2c462e1..ffaf84e2b3 100644 --- a/frappe/model/naming.py +++ b/frappe/model/naming.py @@ -110,7 +110,11 @@ def make_autoname(key="", doctype="", doc=""): if "#" not in key: key = key + ".#####" elif "." not in key: - frappe.throw(_("Invalid naming series (. missing)") + (_(" for {0}").format(doctype) if doctype else "")) + error_message = _("Invalid naming series (. missing)") + if doctype: + error_message = _("Invalid naming series (. missing) for {0}").format(doctype) + + frappe.throw(error_message) parts = key.split('.') n = parse_naming_series(parts, doctype, doc) diff --git a/frappe/public/js/frappe/form/workflow.js b/frappe/public/js/frappe/form/workflow.js index 4eb33a5f28..4c59e8219b 100644 --- a/frappe/public/js/frappe/form/workflow.js +++ b/frappe/public/js/frappe/form/workflow.js @@ -29,20 +29,18 @@ frappe.ui.form.States = Class.extend({ }); frappe.workflow.get_transitions(me.frm.doc).then((transitions) => { - var next_html = $.map(transitions, - function(d) { - return d.action.bold() + __(" by Role ") + d.allowed; - }).join(", ") || __("None: End of Workflow").bold(); + const next_actions = $.map(transitions, d => `${d.action.bold()} ${__("by Role")} ${d.allowed}`) + .join(", ") || __("None: End of Workflow").bold(); + + const document_editable_by = frappe.workflow.get_document_state(me.frm.doctype, state).allow_edit.bold(); + + $(d.body).html(` +

${__("Current status")}: ${state.bold()}

+

${__("Document is only editable by users with role")}: ${document_editable_by}

+

${__("Next actions")}: ${next_actions}

+

${__("{0}: Other permission rules may also apply", [__('Note').bold()])}

+ `).css({padding: '15px'}); - $(d.body).html("

"+__("Current status")+": " + state.bold() + "

" - + "

"+__("Document is only editable by users of role")+": " - + frappe.workflow.get_document_state(me.frm.doctype, - state).allow_edit.bold() + "

" - + "

"+__("Next actions")+": "+ next_html +"

" - + (me.frm.doc.__islocal ? ("
" - +__("Workflow will start after saving.")+"
") : "") - + "

"+__("Note: Other permission rules may also apply")+"

" - ).css({padding: '15px'}); d.show(); }); }, true); @@ -115,7 +113,7 @@ frappe.ui.form.States = Class.extend({ } else { this.setup_btn(added); } - + }); }, diff --git a/frappe/templates/emails/delete_data_confirmation.html b/frappe/templates/emails/delete_data_confirmation.html index e483bd59ed..126d8bcb4b 100644 --- a/frappe/templates/emails/delete_data_confirmation.html +++ b/frappe/templates/emails/delete_data_confirmation.html @@ -7,5 +7,6 @@ {{ _("Confirm Request") }}

- {{_("You can also copy-paste this ")}} {{_("Verification Link")}}{{_(" to your browser")}} + {% set verification_link = '{{ _("Verification Link") }}' %} + {{_("You can also copy-paste this {0} to your browser").format(verification_link) }}

\ No newline at end of file From a440b954d5e2465d47f698e03af13fd9b098c9e9 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Wed, 8 Apr 2020 18:18:18 +0530 Subject: [PATCH 071/115] fix: code cleanup --- frappe/public/js/frappe/widgets/shortcut_widget.js | 1 - 1 file changed, 1 deletion(-) diff --git a/frappe/public/js/frappe/widgets/shortcut_widget.js b/frappe/public/js/frappe/widgets/shortcut_widget.js index a492aaf89b..e36120ebda 100644 --- a/frappe/public/js/frappe/widgets/shortcut_widget.js +++ b/frappe/public/js/frappe/widgets/shortcut_widget.js @@ -43,7 +43,6 @@ export default class ShortcutWidget extends Widget { } set_actions() { - console.log(this.in_customize_mode); if (this.in_customize_mode) return this.widget.addClass('shortcut-widget-box'); From 7a7f7af38056fbfa3ba82a0db78ad417ad6f09bb Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Wed, 8 Apr 2020 18:18:32 +0530 Subject: [PATCH 072/115] fix: set margin after widgets are added --- frappe/public/js/frappe/views/desktop/desktop.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/frappe/public/js/frappe/views/desktop/desktop.js b/frappe/public/js/frappe/views/desktop/desktop.js index 2eb619d910..8ff7d7e167 100644 --- a/frappe/public/js/frappe/views/desktop/desktop.js +++ b/frappe/public/js/frappe/views/desktop/desktop.js @@ -200,6 +200,11 @@ class DesktopPage { let create_shortcuts_and_cards = () => { this.data.shortcuts.items.length && this.make_shortcuts(); this.data.cards.items.length && this.make_cards(); + + if (this.allow_customization) { + // Move the widget group up to align with labels if customization is allowed + $('.desk-page .widget-group:visible:first').css('margin-top', '-25px'); + } }; if (!this.sections["onboarding"] && this.data.charts.items.length) { @@ -209,11 +214,6 @@ class DesktopPage { } else { create_shortcuts_and_cards(); } - - if (this.allow_customization) { - // Move the widget group up to align with labels if customization is allowed - $('.desk-page .widget-group:visible:first').css('margin-top', '-25px'); - } } get_data() { From d0b0b68311f6586b21e81b5030d48085e8afcba6 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Wed, 8 Apr 2020 18:33:44 +0530 Subject: [PATCH 073/115] feat: separate new widget and widget dialog --- frappe/public/js/frappe/widgets/new_widget.js | 213 ++---------------- .../public/js/frappe/widgets/widget_dialog.js | 204 +++++++++++++++++ .../public/js/frappe/widgets/widget_group.js | 5 +- 3 files changed, 222 insertions(+), 200 deletions(-) create mode 100644 frappe/public/js/frappe/widgets/widget_dialog.js diff --git a/frappe/public/js/frappe/widgets/new_widget.js b/frappe/public/js/frappe/widgets/new_widget.js index e85ecf1718..d7b05869b1 100644 --- a/frappe/public/js/frappe/widgets/new_widget.js +++ b/frappe/public/js/frappe/widgets/new_widget.js @@ -1,4 +1,6 @@ -export class NewWidget { +import get_dialog_constructor from './widget_dialog.js' + +export default class NewWidget { constructor(opts) { Object.assign(this, opts); this.make(); @@ -29,202 +31,19 @@ export class NewWidget { this.widget.on("click", () => this.open_dialog()); } + open_dialog() { + const dialog_class = get_dialog_constructor(this.type) + this.dialog = new dialog_class({ + label: this.label, + type: this.type, + values: false, + on_create: this.on_create, + }) + + this.dialog.make(); + } + delete() { this.widget.remove(); } - - get_fields() { - // - } - - process_data(data) { - return data - } - - setup_dialog_events() { - // - } - - open_dialog() { - this.dialog = new frappe.ui.Dialog({ - title: this.get_title(), - fields: this.get_fields(), - primary_action: (data) => { - data = this.process_data(data); - data.name = `${this.type}-${this.label}-${frappe.utils.get_random(20)}`; - - this.dialog.hide(); - this.on_create(data); - }, - primary_action_label: __("Add"), - }); - - this.setup_dialog_events(); - - this.dialog.show(); - } - - hide_field(fieldname) { - this.dialog.set_df_property(fieldname, "hidden", true); - } - - show_field(fieldname) { - this.dialog.set_df_property(fieldname, "hidden", false); - } -} - -export class NewChartWidget extends NewWidget { - constructor(opts) { - super(opts); - } - - get_fields() { - return [ - { - fieldtype: "Link", - fieldname: "chart_name", - label: "Chart Name", - options: "Dashboard Chart", - reqd: 1, - }, - { - fieldtype: "Data", - fieldname: "label", - label: "Label" - }, - ]; - } - - process_data(data) { - data.label = data.chart_name; - return data - } -} - -export class NewShortcutWidget extends NewWidget { - constructor(opts) { - super(opts); - window.neww = this; - } - - get_fields() { - return [ - { - fieldtype: "Select", - fieldname: "type", - label: "Type", - reqd: 1, - options: "DocType\nReport\nPage", - onchange: () => { - if (this.dialog.get_value("type") == "DocType") { - this.dialog.fields_dict.link_to.get_query = () => { - return { filters: { "istable": false }} - } - } - }, - }, - { - fieldtype: "Column Break", - fieldname: "column_break_4", - }, - { - fieldtype: "Dynamic Link", - fieldname: "link_to", - label: "Link To", - reqd: 1, - options: "type", - onchange: () => { - let dg = this.dialog; - if (this.dialog.get_value("type") == "DocType") { - let doctype = this.dialog.get_value("link_to") - frappe.db.get_value("DocType", doctype, "issingle").then(res => { - if (res.message.issingle) { - this.hide_field('count_section_break'); - this.hide_field('filters_section_break'); - } else { - this.setup_filter(doctype); - this.show_field('count_section_break'); - this.show_field('filters_section_break'); - } - }) - } else { - this.hide_field('count_section_break'); - this.hide_field('filters_section_break'); - } - }, - }, - { - fieldtype: "Section Break", - fieldname: "filters_section_break", - label: "Count Filter", - hidden: 1, - }, - { - fieldtype: "HTML", - fieldname: "filter_area", - }, - { - fieldtype: "Section Break", - fieldname: "count_section_break", - label: "Count Customizations", - hidden: 1, - }, - { - fieldtype: "Color", - fieldname: "color", - label: "Color", - }, - { - fieldtype: "Column Break", - fieldname: "column_break_3", - }, - { - fieldtype: "Data", - fieldname: "format", - label: "Format", - description: "For Example: {} Open", - }, - ]; - } - - process_data(data) { - let stats_filter = {}; - let filters = this.filter_group.get_filters(); - filters.forEach(arr => { - stats_filter[arr[1]] = [arr[2], arr[3]] - }); - - data.stats_filter = JSON.stringify(stats_filter); - data.label = data.link_to; - - return data - } - - setup_filter(doctype) { - if (this.filter_group) { - this.filter_group.wrapper.empty(); - delete this.filter_group; - } - - this.filters = [] - - this.filter_group = new frappe.ui.FilterGroup({ - parent: this.dialog.get_field('filter_area').$wrapper, - doctype: doctype, - on_change: () => {}, - }); - - frappe.model.with_doctype(doctype, () => { - this.filter_group.add_filters_to_filter_group(this.filters); - }); - } -} - -export function get_new_widget_class(type) { - const widget_map = { - chart: NewChartWidget, - shortcut: NewShortcutWidget, - }; - - return widget_map[type] || NewWidget; -} +} \ No newline at end of file diff --git a/frappe/public/js/frappe/widgets/widget_dialog.js b/frappe/public/js/frappe/widgets/widget_dialog.js new file mode 100644 index 0000000000..2a4bb864a0 --- /dev/null +++ b/frappe/public/js/frappe/widgets/widget_dialog.js @@ -0,0 +1,204 @@ +class WidgetDialog { + constructor(opts) { + Object.assign(this, opts); + } + + make() { + this.dialog = new frappe.ui.Dialog({ + title: this.get_title(), + fields: this.get_fields(), + primary_action: (data) => { + data = this.process_data(data); + data.name = `${this.type}-${this.label}-${frappe.utils.get_random(20)}`; + + this.dialog.hide(); + this.on_create(data); + }, + primary_action_label: __("Add"), + }); + + this.setup_dialog_events(); + + this.dialog.show(); + } + + get_title() { + return __(`New ${frappe.utils.to_title_case(this.type)}`); + } + + get_fields() { + // + } + + process_data(data) { + return data + } + + setup_dialog_events() { + // + } + + hide_field(fieldname) { + this.dialog.set_df_property(fieldname, "hidden", true); + } + + show_field(fieldname) { + this.dialog.set_df_property(fieldname, "hidden", false); + } +} + +class ChartDialog extends WidgetDialog { + constructor(opts) { + super(opts); + } + + get_fields() { + return [ + { + fieldtype: "Link", + fieldname: "chart_name", + label: "Chart Name", + options: "Dashboard Chart", + reqd: 1, + }, + { + fieldtype: "Data", + fieldname: "label", + label: "Label" + }, + ]; + } + + process_data(data) { + data.label = data.chart_name; + return data + } +} + +class ShortcutDialog extends WidgetDialog { + constructor(opts) { + super(opts); + window.neww = this; + } + + get_fields() { + return [ + { + fieldtype: "Select", + fieldname: "type", + label: "Type", + reqd: 1, + options: "DocType\nReport\nPage", + onchange: () => { + if (this.dialog.get_value("type") == "DocType") { + this.dialog.fields_dict.link_to.get_query = () => { + return { filters: { "istable": false }} + } + } + }, + }, + { + fieldtype: "Column Break", + fieldname: "column_break_4", + }, + { + fieldtype: "Dynamic Link", + fieldname: "link_to", + label: "Link To", + reqd: 1, + options: "type", + onchange: () => { + let dg = this.dialog; + if (this.dialog.get_value("type") == "DocType") { + let doctype = this.dialog.get_value("link_to") + frappe.db.get_value("DocType", doctype, "issingle").then(res => { + if (res.message.issingle) { + this.hide_field('count_section_break'); + this.hide_field('filters_section_break'); + } else { + this.setup_filter(doctype); + this.show_field('count_section_break'); + this.show_field('filters_section_break'); + } + }) + } else { + this.hide_field('count_section_break'); + this.hide_field('filters_section_break'); + } + }, + }, + { + fieldtype: "Section Break", + fieldname: "filters_section_break", + label: "Count Filter", + hidden: 1, + }, + { + fieldtype: "HTML", + fieldname: "filter_area", + }, + { + fieldtype: "Section Break", + fieldname: "count_section_break", + label: "Count Customizations", + hidden: 1, + }, + { + fieldtype: "Color", + fieldname: "color", + label: "Color", + }, + { + fieldtype: "Column Break", + fieldname: "column_break_3", + }, + { + fieldtype: "Data", + fieldname: "format", + label: "Format", + description: "For Example: {} Open", + }, + ]; + } + + process_data(data) { + let stats_filter = {}; + let filters = this.filter_group.get_filters(); + filters.forEach(arr => { + stats_filter[arr[1]] = [arr[2], arr[3]] + }); + + data.stats_filter = JSON.stringify(stats_filter); + data.label = data.link_to; + + return data + } + + setup_filter(doctype) { + if (this.filter_group) { + this.filter_group.wrapper.empty(); + delete this.filter_group; + } + + this.filters = [] + + this.filter_group = new frappe.ui.FilterGroup({ + parent: this.dialog.get_field('filter_area').$wrapper, + doctype: doctype, + on_change: () => {}, + }); + + frappe.model.with_doctype(doctype, () => { + this.filter_group.add_filters_to_filter_group(this.filters); + }); + } +} + +export default function get_dialog_constructor(type) { + const widget_map = { + chart: ChartDialog, + shortcut: ShortcutDialog, + }; + + return widget_map[type] || WidgetDialog; +} \ No newline at end of file diff --git a/frappe/public/js/frappe/widgets/widget_group.js b/frappe/public/js/frappe/widgets/widget_group.js index f121939748..99f3a8edbd 100644 --- a/frappe/public/js/frappe/widgets/widget_group.js +++ b/frappe/public/js/frappe/widgets/widget_group.js @@ -3,7 +3,7 @@ import BaseWidget from "../widgets/base_widget"; import ShortcutWidget from "../widgets/shortcut_widget"; import LinksWidget from "../widgets/links_widget"; import OnboardingWidget from "../widgets/onboarding_widget"; -import { get_new_widget_class } from "../widgets/new_widget"; +import NewWidget from "../widgets/new_widget"; frappe.provide('frappe.widget') @@ -92,8 +92,7 @@ export default class WidgetGroup { : Number.POSITIVE_INFINITY; if (this.widgets_list.length < max) { - const new_widget_class = get_new_widget_class(this.type) - this.new_widget = new new_widget_class({ + this.new_widget = new NewWidget({ container: this.body, type: this.type, on_create: (config) => { From afe9ec3ed669e5c10c23753342b86b68f0999f9f Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Wed, 8 Apr 2020 20:12:20 +0530 Subject: [PATCH 074/115] feat: return a promise of set_values --- frappe/public/js/frappe/ui/field_group.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/frappe/public/js/frappe/ui/field_group.js b/frappe/public/js/frappe/ui/field_group.js index 9c04789544..e467e2e65e 100644 --- a/frappe/public/js/frappe/ui/field_group.js +++ b/frappe/public/js/frappe/ui/field_group.js @@ -125,11 +125,14 @@ frappe.ui.FieldGroup = frappe.ui.form.Layout.extend({ return this.set_value(key, val); }, set_values: function(dict) { + let promises = [] for(var key in dict) { if(this.fields_dict[key]) { - this.set_value(key, dict[key]); + promises.push(this.set_value(key, dict[key])); } } + + return Promise.all(promises) }, clear: function() { for(var key in this.fields_dict) { From f9686f1a8536d6ed25d4f1c0a6fb5cf10ada0cfa Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Wed, 8 Apr 2020 20:12:54 +0530 Subject: [PATCH 075/115] feat: allow editing of widgets --- .../public/js/frappe/widgets/base_widget.js | 34 ++++----- frappe/public/js/frappe/widgets/new_widget.js | 3 +- .../js/frappe/widgets/shortcut_widget.js | 10 +-- .../public/js/frappe/widgets/widget_dialog.js | 71 ++++++++++++++++--- .../public/js/frappe/widgets/widget_group.js | 1 + 5 files changed, 78 insertions(+), 41 deletions(-) diff --git a/frappe/public/js/frappe/widgets/base_widget.js b/frappe/public/js/frappe/widgets/base_widget.js index 63fc49a166..faa79da76d 100644 --- a/frappe/public/js/frappe/widgets/base_widget.js +++ b/frappe/public/js/frappe/widgets/base_widget.js @@ -1,3 +1,5 @@ +import get_dialog_constructor from './widget_dialog.js' + export default class Widget { constructor(opts) { Object.assign(this, opts); @@ -114,29 +116,21 @@ export default class Widget { } edit() { - frappe.model.with_doctype(this.doctype, () => { - let new_dialog = new frappe.ui.Dialog({ - title: __("Edit"), - fields: frappe.get_meta(this.doctype).fields, - primary_action: (data) => { - if (this.doctype == 'Desk Chart' && !data.label) { - data.label = data.chart_name; - } + const dialog_class = get_dialog_constructor(this.widget_type) - if (this.doctype == 'Desk Shortcut') { - data.label = data.link_to; - } + this.edit_dialog = new dialog_class({ + label: this.label, + type: this.widget_type, + values: this.get_config(), + primary_action: (data) => { + Object.assign(this, data); + data.name = this.name; - new_dialog.hide(); - Object.assign(this, data); - this.refresh(); - }, - primary_action_label: __("Save"), - }); + this.refresh(); + }, + }) - new_dialog.show(); - new_dialog.set_values(this.get_config()); - }); + this.edit_dialog.make(); } hide_or_show() { diff --git a/frappe/public/js/frappe/widgets/new_widget.js b/frappe/public/js/frappe/widgets/new_widget.js index d7b05869b1..d3d887bf20 100644 --- a/frappe/public/js/frappe/widgets/new_widget.js +++ b/frappe/public/js/frappe/widgets/new_widget.js @@ -33,11 +33,12 @@ export default class NewWidget { open_dialog() { const dialog_class = get_dialog_constructor(this.type) + this.dialog = new dialog_class({ label: this.label, type: this.type, values: false, - on_create: this.on_create, + primary_action: this.on_create, }) this.dialog.make(); diff --git a/frappe/public/js/frappe/widgets/shortcut_widget.js b/frappe/public/js/frappe/widgets/shortcut_widget.js index e36120ebda..16f9f32718 100644 --- a/frappe/public/js/frappe/widgets/shortcut_widget.js +++ b/frappe/public/js/frappe/widgets/shortcut_widget.js @@ -1,13 +1,5 @@ import Widget from "./base_widget.js"; import { generate_route } from "./utils"; -// import { get_luminosity, shadeColor } from "./utils"; - -String.prototype.format = function () { - var i = 0, args = arguments; - return this.replace(/{}/g, function () { - return typeof args[i] != 'undefined' ? args[i++] : ''; - }); -}; export default class ShortcutWidget extends Widget { constructor(opts) { @@ -69,7 +61,7 @@ export default class ShortcutWidget extends Widget { set_count(count) { const get_label = () => { if (this.format) { - return this.format.format(count); + return this.format.replace(/{}/g, count); } return count } diff --git a/frappe/public/js/frappe/widgets/widget_dialog.js b/frappe/public/js/frappe/widgets/widget_dialog.js index 2a4bb864a0..1fa1c08a13 100644 --- a/frappe/public/js/frappe/widgets/widget_dialog.js +++ b/frappe/public/js/frappe/widgets/widget_dialog.js @@ -4,22 +4,33 @@ class WidgetDialog { } make() { + this.make_dialog(); + this.setup_dialog_events(); + this.dialog.show(); + + if (this.values && Object.keys(this.values).length) { + this.set_default_values(); + } + } + + make_dialog() { this.dialog = new frappe.ui.Dialog({ title: this.get_title(), fields: this.get_fields(), primary_action: (data) => { data = this.process_data(data); - data.name = `${this.type}-${this.label}-${frappe.utils.get_random(20)}`; + + if (this.values && this.values.name) { + data.name = this.values.name; + } else { + data.name = `${this.type}-${this.label}-${frappe.utils.get_random(20)}`; + } this.dialog.hide(); - this.on_create(data); + this.primary_action(data); }, primary_action_label: __("Add"), }); - - this.setup_dialog_events(); - - this.dialog.show(); } get_title() { @@ -30,6 +41,10 @@ class WidgetDialog { // } + set_default_values() { + return this.dialog.set_values(this.values); + } + process_data(data) { return data } @@ -70,7 +85,12 @@ class ChartDialog extends WidgetDialog { } process_data(data) { - data.label = data.chart_name; + if (this.values && this.values.label) { + data.label = this.values.label; + } else { + data.label = data.chart_name; + } + return data } } @@ -110,9 +130,9 @@ class ShortcutDialog extends WidgetDialog { onchange: () => { let dg = this.dialog; if (this.dialog.get_value("type") == "DocType") { - let doctype = this.dialog.get_value("link_to") - frappe.db.get_value("DocType", doctype, "issingle").then(res => { - if (res.message.issingle) { + let doctype = this.dialog.get_value("link_to"); + doctype &&frappe.db.get_value("DocType", doctype, "issingle").then(res => { + if (res.message && res.message.issingle) { this.hide_field('count_section_break'); this.hide_field('filters_section_break'); } else { @@ -133,9 +153,14 @@ class ShortcutDialog extends WidgetDialog { label: "Count Filter", hidden: 1, }, + { + fieldtype: "HTML", + fieldname: "filter_area_loading", + }, { fieldtype: "HTML", fieldname: "filter_area", + hidden: 1, }, { fieldtype: "Section Break", @@ -161,6 +186,12 @@ class ShortcutDialog extends WidgetDialog { ]; } + set_default_values() { + super.set_default_values().then(() => { + this.dialog.fields_dict.link_to.df.onchange(); + }); + } + process_data(data) { let stats_filter = {}; let filters = this.filter_group.get_filters(); @@ -169,7 +200,12 @@ class ShortcutDialog extends WidgetDialog { }); data.stats_filter = JSON.stringify(stats_filter); - data.label = data.link_to; + + if (this.values && this.values.label) { + data.label = this.values.label; + } else { + data.label = data.link_to; + } return data } @@ -180,8 +216,19 @@ class ShortcutDialog extends WidgetDialog { delete this.filter_group; } + let $loading = this.dialog.get_field('filter_area_loading').$wrapper + $(`Loading Filters...`).appendTo($loading) + this.filters = [] + if (this.values && this.values.stats_filter) { + const filters_json = JSON.parse(this.values.stats_filter); + this.filters = Object.keys(filters_json).map(filter => { + let val = filters_json[filter]; + return [this.values.link_to, filter, val[0], val[1], false] + }) + } + this.filter_group = new frappe.ui.FilterGroup({ parent: this.dialog.get_field('filter_area').$wrapper, doctype: doctype, @@ -190,6 +237,8 @@ class ShortcutDialog extends WidgetDialog { frappe.model.with_doctype(doctype, () => { this.filter_group.add_filters_to_filter_group(this.filters); + this.hide_field('filter_area_loading'); + this.show_field('filter_area'); }); } } diff --git a/frappe/public/js/frappe/widgets/widget_group.js b/frappe/public/js/frappe/widgets/widget_group.js index 99f3a8edbd..b1759f3d93 100644 --- a/frappe/public/js/frappe/widgets/widget_group.js +++ b/frappe/public/js/frappe/widgets/widget_group.js @@ -63,6 +63,7 @@ export default class WidgetGroup { let widget_object = new widget_class({ ...widget, + widget_type: this.type, container: this.body, options: { ...this.options, From bf47bc8ba3fc292beeed4ae690f6654b1cec2f0b Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Wed, 8 Apr 2020 20:16:51 +0530 Subject: [PATCH 076/115] feat: custom primary action label for new widget dialog --- frappe/public/js/frappe/widgets/base_widget.js | 1 + frappe/public/js/frappe/widgets/widget_dialog.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/frappe/public/js/frappe/widgets/base_widget.js b/frappe/public/js/frappe/widgets/base_widget.js index faa79da76d..d436d07731 100644 --- a/frappe/public/js/frappe/widgets/base_widget.js +++ b/frappe/public/js/frappe/widgets/base_widget.js @@ -128,6 +128,7 @@ export default class Widget { this.refresh(); }, + primary_action_label: __("Save") }) this.edit_dialog.make(); diff --git a/frappe/public/js/frappe/widgets/widget_dialog.js b/frappe/public/js/frappe/widgets/widget_dialog.js index 1fa1c08a13..1584c59ed4 100644 --- a/frappe/public/js/frappe/widgets/widget_dialog.js +++ b/frappe/public/js/frappe/widgets/widget_dialog.js @@ -29,7 +29,7 @@ class WidgetDialog { this.dialog.hide(); this.primary_action(data); }, - primary_action_label: __("Add"), + primary_action_label: this.primary_action_label || __("Add"), }); } From 9dbaf7932a38d4e35596165bac0a73751898cb0d Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Thu, 9 Apr 2020 11:29:10 +0530 Subject: [PATCH 077/115] fix (linting): remove unused import --- frappe/desk/desktop.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/desk/desktop.py b/frappe/desk/desktop.py index 175bfa90ff..b367aea455 100644 --- a/frappe/desk/desktop.py +++ b/frappe/desk/desktop.py @@ -4,7 +4,7 @@ from __future__ import unicode_literals import frappe -from json import loads, dumps +from json import loads from frappe import _, DoesNotExistError from frappe.boot import get_allowed_pages, get_allowed_reports from six import string_types From 0b80c44796f8b91f299dde75f84b161dc12910ed Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Thu, 9 Apr 2020 11:35:42 +0530 Subject: [PATCH 078/115] style: remove unnecessary else --- frappe/desk/desktop.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/frappe/desk/desktop.py b/frappe/desk/desktop.py index b367aea455..305edc0615 100644 --- a/frappe/desk/desktop.py +++ b/frappe/desk/desktop.py @@ -25,9 +25,9 @@ class Workspace: pages = frappe.get_list("Desk Page", filters=filters) if pages: return frappe.get_doc("Desk Page", pages[0]) - else: - self.get_pages_to_extend() - return frappe.get_doc("Desk Page", self.page_name) + + self.get_pages_to_extend() + return frappe.get_doc("Desk Page", self.page_name) def init(self): user = frappe.get_user() @@ -310,11 +310,10 @@ def get_custom_workspace_for_user(page): pages = frappe.get_list("Desk Page", filters=filters) if pages: return frappe.get_doc("Desk Page", pages[0]) - else: - doc = frappe.new_doc("Desk Page") - doc.extends = page - doc.for_user = frappe.session.user - return doc + doc = frappe.new_doc("Desk Page") + doc.extends = page + doc.for_user = frappe.session.user + return doc @frappe.whitelist() From d99f68a230a6bbaad6fc4592f388a699954efab6 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Thu, 9 Apr 2020 12:01:10 +0530 Subject: [PATCH 079/115] style: load data on object initializing --- frappe/desk/desktop.py | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/frappe/desk/desktop.py b/frappe/desk/desktop.py index 305edc0615..b616c2838d 100644 --- a/frappe/desk/desktop.py +++ b/frappe/desk/desktop.py @@ -17,19 +17,6 @@ class Workspace: self.extended_charts = [] self.extended_shortcuts = [] - def get_page_for_user(self): - filters = { - 'extends': self.page_name, - 'for_user': frappe.session.user - } - pages = frappe.get_list("Desk Page", filters=filters) - if pages: - return frappe.get_doc("Desk Page", pages[0]) - - self.get_pages_to_extend() - return frappe.get_doc("Desk Page", self.page_name) - - def init(self): user = frappe.get_user() user.build_permissions() @@ -43,11 +30,22 @@ class Workspace: self.allowed_pages = get_allowed_pages() self.allowed_reports = get_allowed_reports() - self.table_counts = get_table_with_counts() self.restricted_doctypes = build_domain_restriced_doctype_cache() self.restricted_pages = build_domain_restriced_page_cache() + def get_page_for_user(self): + filters = { + 'extends': self.page_name, + 'for_user': frappe.session.user + } + pages = frappe.get_list("Desk Page", filters=filters) + if pages: + return frappe.get_doc("Desk Page", pages[0]) + + self.get_pages_to_extend() + return frappe.get_doc("Desk Page", self.page_name) + def get_pages_to_extend(self): pages = frappe.get_all("Desk Page", filters={ "extends": self.page_name, @@ -209,9 +207,8 @@ def get_desktop_page(page): Returns: dict: dictionary of cards, charts and shortcuts to be displayed on website """ - wspace = Workspace(page) try: - wspace.init() + wspace = Workspace(page) wspace.build_workspace() return { 'charts': wspace.charts, From b7270d82ea6e0b5abb3df52bbc793f11ab1f800a Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Thu, 9 Apr 2020 13:47:35 +0530 Subject: [PATCH 080/115] fix (linting): fixes from codacy --- frappe/public/js/frappe/ui/field_group.js | 4 +- .../public/js/frappe/views/desktop/desktop.js | 10 ++-- .../public/js/frappe/widgets/base_widget.js | 6 +-- .../public/js/frappe/widgets/chart_widget.js | 2 +- .../public/js/frappe/widgets/links_widget.js | 6 +-- frappe/public/js/frappe/widgets/new_widget.js | 8 +-- .../js/frappe/widgets/shortcut_widget.js | 52 +++++++++++-------- .../public/js/frappe/widgets/widget_group.js | 44 ++++++++-------- 8 files changed, 68 insertions(+), 64 deletions(-) diff --git a/frappe/public/js/frappe/ui/field_group.js b/frappe/public/js/frappe/ui/field_group.js index e467e2e65e..4d827354d8 100644 --- a/frappe/public/js/frappe/ui/field_group.js +++ b/frappe/public/js/frappe/ui/field_group.js @@ -125,14 +125,14 @@ frappe.ui.FieldGroup = frappe.ui.form.Layout.extend({ return this.set_value(key, val); }, set_values: function(dict) { - let promises = [] + let promises = []; for(var key in dict) { if(this.fields_dict[key]) { promises.push(this.set_value(key, dict[key])); } } - return Promise.all(promises) + return Promise.all(promises); }, clear: function() { for(var key in this.fields_dict) { diff --git a/frappe/public/js/frappe/views/desktop/desktop.js b/frappe/public/js/frappe/views/desktop/desktop.js index 8ff7d7e167..e0f400ed9a 100644 --- a/frappe/public/js/frappe/views/desktop/desktop.js +++ b/frappe/public/js/frappe/views/desktop/desktop.js @@ -169,9 +169,7 @@ class DesktopPage { this.save_or_discard_link.appendTo(this.page); this.save_or_discard_link.find(".save-customization").on("click", () => this.save_customization()); - - this.save_or_discard_link.find(".discard-customization").on("click", () => this.reload()) - + this.save_or_discard_link.find(".discard-customization").on("click", () => this.reload()); this.page.addClass('allow-customization'); } @@ -228,7 +226,7 @@ class DesktopPage { customize() { if (this.in_customize_mode) { - return + return; } // It may be possible the chart area is hidden since it has no widgets @@ -259,9 +257,9 @@ class DesktopPage { page: this.page_name, config: config }).then(res => { - frappe.msgprint(__("Customizations Saved Successfully")) + frappe.msgprint(__("Customizations Saved Successfully")); this.reload(); - }) + }); } make_charts() { diff --git a/frappe/public/js/frappe/widgets/base_widget.js b/frappe/public/js/frappe/widgets/base_widget.js index d436d07731..700966ecb5 100644 --- a/frappe/public/js/frappe/widgets/base_widget.js +++ b/frappe/public/js/frappe/widgets/base_widget.js @@ -1,4 +1,4 @@ -import get_dialog_constructor from './widget_dialog.js' +import get_dialog_constructor from './widget_dialog.js'; export default class Widget { constructor(opts) { @@ -116,7 +116,7 @@ export default class Widget { } edit() { - const dialog_class = get_dialog_constructor(this.widget_type) + const dialog_class = get_dialog_constructor(this.widget_type); this.edit_dialog = new dialog_class({ label: this.label, @@ -129,7 +129,7 @@ export default class Widget { this.refresh(); }, primary_action_label: __("Save") - }) + }); this.edit_dialog.make(); } diff --git a/frappe/public/js/frappe/widgets/chart_widget.js b/frappe/public/js/frappe/widgets/chart_widget.js index 2bfd701db1..6f83be39c7 100644 --- a/frappe/public/js/frappe/widgets/chart_widget.js +++ b/frappe/public/js/frappe/widgets/chart_widget.js @@ -14,7 +14,7 @@ export default class ChartWidget extends Widget { name: this.name, chart_name: this.chart_name, label: this.label, - } + }; } refresh() { diff --git a/frappe/public/js/frappe/widgets/links_widget.js b/frappe/public/js/frappe/widgets/links_widget.js index 1f186aa6c2..f7bca23c47 100644 --- a/frappe/public/js/frappe/widgets/links_widget.js +++ b/frappe/public/js/frappe/widgets/links_widget.js @@ -12,7 +12,7 @@ export default class LinksWidget extends Widget { links: JSON.stringify(this.links), label: this.label, hidden: this.hidden, - } + }; } set_body() { @@ -80,13 +80,13 @@ export default class LinksWidget extends Widget { const popover = link.find(".module-link-popover"); link_label.mouseover(() => { - if (this.in_customize_mode) return + if (this.in_customize_mode) return; popover.show(); }); link_label.mouseout(() => popover.hide()); } else { link_label.click(event => { - if (this.in_customize_mode) return + if (this.in_customize_mode) return; if (link_label.hasClass("help-video-link")) { let yt_id = event.target.dataset.youtubeid; diff --git a/frappe/public/js/frappe/widgets/new_widget.js b/frappe/public/js/frappe/widgets/new_widget.js index d3d887bf20..ffd96c87da 100644 --- a/frappe/public/js/frappe/widgets/new_widget.js +++ b/frappe/public/js/frappe/widgets/new_widget.js @@ -1,4 +1,4 @@ -import get_dialog_constructor from './widget_dialog.js' +import get_dialog_constructor from "./widget_dialog.js"; export default class NewWidget { constructor(opts) { @@ -32,14 +32,14 @@ export default class NewWidget { } open_dialog() { - const dialog_class = get_dialog_constructor(this.type) + const dialog_class = get_dialog_constructor(this.type); this.dialog = new dialog_class({ label: this.label, type: this.type, values: false, primary_action: this.on_create, - }) + }); this.dialog.make(); } @@ -47,4 +47,4 @@ export default class NewWidget { delete() { this.widget.remove(); } -} \ No newline at end of file +} diff --git a/frappe/public/js/frappe/widgets/shortcut_widget.js b/frappe/public/js/frappe/widgets/shortcut_widget.js index 16f9f32718..8df604cf97 100644 --- a/frappe/public/js/frappe/widgets/shortcut_widget.js +++ b/frappe/public/js/frappe/widgets/shortcut_widget.js @@ -16,44 +16,47 @@ export default class ShortcutWidget extends Widget { color: this.color, restrict_to_domain: this.restrict_to_domain, stats_filter: this.stats_filter, - type: this.type - } + type: this.type, + }; } setup_events() { this.widget.click(() => { - if (this.in_customize_mode) return + if (this.in_customize_mode) return; let route = generate_route({ route: this.route, name: this.link_to, - type: this.type - }) + type: this.type, + }); - frappe.set_route(route) - }) + frappe.set_route(route); + }); } set_actions() { - if (this.in_customize_mode) return + if (this.in_customize_mode) return; - this.widget.addClass('shortcut-widget-box'); - const get_filter = new Function(`return ${this.stats_filter}`) + this.widget.addClass("shortcut-widget-box"); + const get_filter = new Function(`return ${this.stats_filter}`); if (this.type == "DocType" && this.stats_filter) { - frappe.db.count(this.link_to, { - filters: get_filter() - }).then(count => this.set_count(count)) + frappe.db + .count(this.link_to, { + filters: get_filter(), + }) + .then((count) => this.set_count(count)); } } set_title() { if (this.icon) { this.title_field[0].innerHTML = `
- + ${this.label || this.name} -
` - } - else { +
`; + } else { super.set_title(); } } @@ -63,17 +66,20 @@ export default class ShortcutWidget extends Widget { if (this.format) { return this.format.replace(/{}/g, count); } - return count - } + return count; + }; this.action_area.empty(); const label = get_label(); const buttons = $(`
${label}
`); - if(this.color) { - buttons.css('background-color', this.color); - buttons.css('color', frappe.ui.color.get_contrast_color(this.color)) + if (this.color) { + buttons.css("background-color", this.color); + buttons.css( + "color", + frappe.ui.color.get_contrast_color(this.color) + ); } buttons.appendTo(this.action_area); } -} \ No newline at end of file +} diff --git a/frappe/public/js/frappe/widgets/widget_group.js b/frappe/public/js/frappe/widgets/widget_group.js index b1759f3d93..bfbdb7393b 100644 --- a/frappe/public/js/frappe/widgets/widget_group.js +++ b/frappe/public/js/frappe/widgets/widget_group.js @@ -5,7 +5,7 @@ import LinksWidget from "../widgets/links_widget"; import OnboardingWidget from "../widgets/onboarding_widget"; import NewWidget from "../widgets/new_widget"; -frappe.provide('frappe.widget') +frappe.provide("frappe.widget"); const widget_factory = { chart: ChartWidget, @@ -52,9 +52,9 @@ export default class WidgetGroup { } make_widgets() { - this.body.empty() - this.widgets.forEach(widget => { - this.add_widget(widget) + this.body.empty(); + this.widgets.forEach((widget) => { + this.add_widget(widget); }); } @@ -67,21 +67,21 @@ export default class WidgetGroup { container: this.body, options: { ...this.options, - on_delete: (name) => this.on_delete(name) - } + on_delete: (name) => this.on_delete(name), + }, }); this.widgets_list.push(widget_object); this.widgets_dict[widget.name] = widget_object; - return widget_object + return widget_object; } customize() { this.widget_area.show(); - this.widgets_list.forEach(wid => { + this.widgets_list.forEach((wid) => { wid.customize(this.options); - }) + }); this.options.allow_create && this.setup_new_widget(); this.options.allow_sorting && this.setup_sortable(); @@ -89,8 +89,8 @@ export default class WidgetGroup { setup_new_widget() { const max = this.options - ? this.options.max_widget_count || Number.POSITIVE_INFINITY - : Number.POSITIVE_INFINITY; + ? this.options.max_widget_count || Number.POSITIVE_INFINITY + : Number.POSITIVE_INFINITY; if (this.widgets_list.length < max) { this.new_widget = new NewWidget({ @@ -111,13 +111,13 @@ export default class WidgetGroup { if (this.widgets_list.length < max) { this.setup_new_widget(); } - } - }) + }, + }); } } on_delete(name) { - this.widgets_list = this.widgets_list.filter(wid => name != wid.name); + this.widgets_list = this.widgets_list.filter((wid) => name != wid.name); delete this.widgets_dict[name]; this.update_widget_order(); @@ -131,7 +131,7 @@ export default class WidgetGroup { if (name) { this.widget_order.push(name); } - }) + }); } setup_sortable() { @@ -147,17 +147,17 @@ export default class WidgetGroup { this.update_widget_order(); let prepared_dict = {}; - this.widgets_list.forEach(wid => { - let config = wid.get_config() - let name = config.docname ? config.docname : config.name - prepared_dict[name] = config + this.widgets_list.forEach((wid) => { + let config = wid.get_config(); + let name = config.docname ? config.docname : config.name; + prepared_dict[name] = config; }); return { order: this.widget_order, - widgets: prepared_dict - } + widgets: prepared_dict, + }; } } -frappe.widget.WidgetGroup = WidgetGroup; \ No newline at end of file +frappe.widget.WidgetGroup = WidgetGroup; From c85a09a739511ed8fb55a9df82b32c350ca6e0fa Mon Sep 17 00:00:00 2001 From: prssanna Date: Thu, 9 Apr 2020 19:33:04 +0530 Subject: [PATCH 081/115] fix: set method in get_settings --- frappe/public/js/frappe/widgets/chart_widget.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/frappe/public/js/frappe/widgets/chart_widget.js b/frappe/public/js/frappe/widgets/chart_widget.js index 6f83be39c7..9c03f08523 100644 --- a/frappe/public/js/frappe/widgets/chart_widget.js +++ b/frappe/public/js/frappe/widgets/chart_widget.js @@ -429,9 +429,7 @@ export default class ChartWidget extends Widget { } fetch(filters, refresh = false, args) { - let method = this.settings - ? this.settings.method - : "frappe.desk.doctype.dashboard_chart.dashboard_chart.get"; + let method = this.settings.method; if (this.chart_doc.chart_type == "Report") { args = { @@ -559,6 +557,9 @@ export default class ChartWidget extends Widget { }; return Promise.resolve(); } else { + this.settings = { + method: "frappe.desk.doctype.dashboard_chart.dashboard_chart.get" + }; return Promise.resolve(); } }); From 9fb1c7b5b0d1648e4f2cf8cb303ede41f71e3605 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Thu, 9 Apr 2020 19:47:52 +0530 Subject: [PATCH 082/115] feat: translate desk --- frappe/desk/desktop.py | 24 +++++++++++++------ .../public/js/frappe/views/desktop/desktop.js | 22 +++++++++-------- frappe/public/js/frappe/widgets/new_widget.js | 2 ++ .../public/js/frappe/widgets/widget_dialog.js | 9 ++++++- 4 files changed, 39 insertions(+), 18 deletions(-) diff --git a/frappe/desk/desktop.py b/frappe/desk/desktop.py index b616c2838d..7041704513 100644 --- a/frappe/desk/desktop.py +++ b/frappe/desk/desktop.py @@ -77,17 +77,17 @@ class Workspace: def build_workspace(self): self.cards = { - 'label': self.doc.cards_label, + 'label': _(self.doc.cards_label), 'items': self.get_cards() } self.charts = { - 'label': self.doc.charts_label, + 'label': _(self.doc.charts_label), 'items': self.get_charts() } self.shortcuts = { - 'label': self.doc.shortcuts_label, + 'label': _(self.doc.charts_label), 'items': self.get_shortcuts() } @@ -121,6 +121,9 @@ class Workspace: item["count"] = count + # Translate label + item["label"] = _(item.label) if item.label else _(item.name) + return item new_data = [] @@ -141,7 +144,7 @@ class Workspace: # Check if user is allowed to view if self.is_item_allowed(item.name, item.type): prepared_item = _prepare_item(item) - new_items.append(item) + new_items.append(prepared_item) if new_items: if isinstance(section, frappe._dict): @@ -149,6 +152,7 @@ class Workspace: else: new_section = section.as_dict().copy() new_section["links"] = new_items + new_section["label"] = _(new_section["label"]) new_data.append(new_section) return new_data @@ -162,7 +166,8 @@ class Workspace: for chart in charts: if frappe.has_permission('Dashboard Chart', doc=chart.chart_name): - chart.label = chart.label if chart.label else chart.chart_name + # Translate label + chart.label = _(chart.label) if chart.label else _(chart.chart_name) all_charts.append(chart) return all_charts @@ -185,12 +190,14 @@ class Workspace: if self.is_item_allowed(item.link_to, item.type) and _in_active_domains(item): if item.type == "Page": page = self.allowed_pages[item.link_to] - new_item['label'] = _(page.get("title", frappe.unscrub(item.link_to))) if item.type == "Report": report = self.allowed_reports.get(item.link_to, {}) if report.get("report_type") in ["Query Report", "Script Report"]: new_item['is_query_report'] = 1 + # Translate label + new_item["label"] = _(item.label) if item.label else _(item.link_to) + items.append(new_item) return items @@ -247,8 +254,11 @@ def get_desk_sidebar_items(): from collections import defaultdict sidebar_items = defaultdict(list) + # The order will be maintained while categorizing for page in pages: - # The order will be maintained while categorizing + # Translate label + page['label'] = _(page.get('name')) + print(page) sidebar_items[page["category"]].append(page) return sidebar_items diff --git a/frappe/public/js/frappe/views/desktop/desktop.js b/frappe/public/js/frappe/views/desktop/desktop.js index e0f400ed9a..742f769b79 100644 --- a/frappe/public/js/frappe/views/desktop/desktop.js +++ b/frappe/public/js/frappe/views/desktop/desktop.js @@ -44,12 +44,12 @@ export default class Desktop { this.desktop_settings = response.message; } else { frappe.throw({ - title: "Couldn't Load Desk", + title: __("Couldn't Load Desk"), message: - "Something went wrong while loading Desk. Please relaod the page. If the problem persists, contact the Administrator", + __("Something went wrong while loading Desk. Please relaod the page. If the problem persists, contact the Administrator"), indicator: "red", primary_action: { - label: "Reload", + label: __("Reload"), action: () => location.reload() } }); @@ -63,7 +63,7 @@ export default class Desktop { item.name}" class="sidebar-item ${ item.selected ? "selected" : "" }"> - ${item.name} + ${item.label || item.name}
`); }; @@ -78,8 +78,10 @@ export default class Desktop { }; const make_category_title = name => { + // DO NOT REMOVE: Comment to load translation + // __("Modules") __("Domains") __("Places") __("Administration") let $title = $( - `` + `` ); $title.appendTo(this.sidebar); }; @@ -157,14 +159,14 @@ class DesktopPage { } make_customization_link() { - this.customize_link = $(`
Customize Workspace
`); + this.customize_link = $(`
${__('Customize Workspace')}
`); this.customize_link.appendTo(this.page); this.customize_link.on('click', () => { this.customize(); }) this.save_or_discard_link = $(`
- Save / Discard + ${__('Save')} / ${__('Discard')}
`).hide(); this.save_or_discard_link.appendTo(this.page); @@ -272,7 +274,7 @@ class DesktopPage { } this.sections["charts"] = new frappe.widget.WidgetGroup({ - title: this.data.charts.label || `${this.page_name} Dashboard`, + title: this.data.charts.label || __('{} Dashboard', [__(this.page_name)]), container: this.page, type: "chart", columns: 1, @@ -291,7 +293,7 @@ class DesktopPage { make_shortcuts() { this.sections["shortcuts"] = new frappe.widget.WidgetGroup({ - title: this.data.shortcuts.label || `Your Shortcuts`, + title: this.data.shortcuts.label || __(`Your Shortcuts`), container: this.page, type: "shortcut", columns: 3, @@ -308,7 +310,7 @@ class DesktopPage { make_cards() { let cards = new frappe.widget.WidgetGroup({ - title: this.data.cards.label || `Reports & Masters`, + title: this.data.cards.label || __(`Reports & Masters`), container: this.page, type: "links", columns: 3, diff --git a/frappe/public/js/frappe/widgets/new_widget.js b/frappe/public/js/frappe/widgets/new_widget.js index ffd96c87da..787cb3a79c 100644 --- a/frappe/public/js/frappe/widgets/new_widget.js +++ b/frappe/public/js/frappe/widgets/new_widget.js @@ -17,6 +17,8 @@ export default class NewWidget { } get_title() { + // DO NOT REMOVE: Comment to load translation + // __("New Chart") __("New Shortcut") return __(`New ${frappe.utils.to_title_case(this.type)}`); } diff --git a/frappe/public/js/frappe/widgets/widget_dialog.js b/frappe/public/js/frappe/widgets/widget_dialog.js index 1584c59ed4..c04d0209f9 100644 --- a/frappe/public/js/frappe/widgets/widget_dialog.js +++ b/frappe/public/js/frappe/widgets/widget_dialog.js @@ -34,7 +34,14 @@ class WidgetDialog { } get_title() { - return __(`New ${frappe.utils.to_title_case(this.type)}`); + // DO NOT REMOVE: Comment to load translation + // __("New Chart") __("New Shortcut") __("Edit Chart") __("Edit Shortcut") + + if (this.values && Object.keys(this.values).length) { + return __(`Edit ${frappe.utils.to_title_case(this.type)}`); + } else { + return __(`Add ${frappe.utils.to_title_case(this.type)}`); + } } get_fields() { From d7dc9bf64e3ea963a64ad6f8ecff0464c910774f Mon Sep 17 00:00:00 2001 From: Suraj Shetty <13928957+surajshetty3416@users.noreply.github.com> Date: Thu, 9 Apr 2020 20:11:02 +0530 Subject: [PATCH 083/115] refactor: Remove redundant code --- frappe/public/js/frappe/list/list_sidebar_group_by.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/public/js/frappe/list/list_sidebar_group_by.js b/frappe/public/js/frappe/list/list_sidebar_group_by.js index f72ff33e4c..7aa62dcb5f 100644 --- a/frappe/public/js/frappe/list/list_sidebar_group_by.js +++ b/frappe/public/js/frappe/list/list_sidebar_group_by.js @@ -64,7 +64,7 @@ frappe.views.ListGroupBy = class ListGroupBy { if (!docfield) { return; } - fieldtype = frappe.meta.get_docfield(this.doctype, fieldname).fieldtype; + fieldtype = docfield.fieldtype; } return `