diff --git a/frappe/desk/desktop.py b/frappe/desk/desktop.py index f2243c2e56..824e144272 100644 --- a/frappe/desk/desktop.py +++ b/frappe/desk/desktop.py @@ -157,14 +157,11 @@ class Workspace: return False def build_workspace(self): + self.number_cards = {"items": self.get_number_cards()} self.cards = {"items": self.get_links()} - self.charts = {"items": self.get_charts()} - self.shortcuts = {"items": self.get_shortcuts()} - self.onboardings = {"items": self.get_onboardings()} - self.quick_lists = {"items": self.get_quick_lists()} def _doctype_contains_a_record(self, name): @@ -204,6 +201,22 @@ class Workspace: return item + @handle_not_exist + def get_number_cards(self): + all_number_cards = [] + if frappe.has_permission("Number Card", throw=False): + number_cards = self.doc.number_cards + for number_card in number_cards: + if frappe.has_permission("Number Card", doc=number_card.number_card_name): + # Translate label + number_card.label = ( + _(number_card.label) if number_card.label else _(number_card.number_card_name) + ) + + all_number_cards.append(number_card) + + return all_number_cards + @handle_not_exist def get_links(self): cards = self.doc.get_link_groups() @@ -349,6 +362,7 @@ def get_desktop_page(page): workspace = Workspace(loads(page)) workspace.build_workspace() return { + "number_cards": workspace.number_cards, "charts": workspace.charts, "shortcuts": workspace.shortcuts, "cards": workspace.cards, @@ -476,6 +490,10 @@ def save_new_widget(doc, page, blocks, new_widgets): if loads(new_widgets): widgets = _dict(loads(new_widgets)) + if widgets.number_card: + doc.number_cards.extend( + new_widget(widgets.number_card, "Workspace Number Card", "number_cards") + ) if widgets.chart: doc.charts.extend(new_widget(widgets.chart, "Workspace Chart", "charts")) if widgets.shortcut: @@ -511,7 +529,7 @@ def save_new_widget(doc, page, blocks, new_widgets): def clean_up(original_page, blocks): page_widgets = {} - for wid in ["shortcut", "card", "chart", "quick_list"]: + for wid in ["number_card", "shortcut", "card", "chart", "quick_list"]: # get list of widget's name from blocks page_widgets[wid] = [x["data"][wid + "_name"] for x in loads(blocks) if x["type"] == wid] diff --git a/frappe/desk/doctype/number_card/number_card.py b/frappe/desk/doctype/number_card/number_card.py index d940448cb1..0783a4ab29 100644 --- a/frappe/desk/doctype/number_card/number_card.py +++ b/frappe/desk/doctype/number_card/number_card.py @@ -124,10 +124,10 @@ def get_result(doc, filters, to_date=None): ) ] - filters = frappe.parse_json(filters) - if not filters: filters = [] + elif isinstance(filters, str): + filters = frappe.parse_json(filters) if to_date: filters.append([doc.document_type, "creation", "<", to_date]) diff --git a/frappe/desk/doctype/workspace/workspace.json b/frappe/desk/doctype/workspace/workspace.json index edd5c32e99..af5f9c4184 100644 --- a/frappe/desk/doctype/workspace/workspace.json +++ b/frappe/desk/doctype/workspace/workspace.json @@ -21,6 +21,8 @@ "public", "is_hidden", "content", + "number_cards_tab", + "number_cards", "tab_break_2", "charts", "tab_break_15", @@ -181,11 +183,22 @@ "fieldname": "is_hidden", "fieldtype": "Check", "label": "Is Hidden" + }, + { + "fieldname": "number_cards_tab", + "fieldtype": "Tab Break", + "label": "Number Cards" + }, + { + "fieldname": "number_cards", + "fieldtype": "Table", + "label": "Number Cards", + "options": "Workspace Number Card" } ], "in_create": 1, "links": [], - "modified": "2023-01-07 19:37:39.512482", + "modified": "2023-02-15 01:16:56.035205", "modified_by": "Administrator", "module": "Desk", "name": "Workspace", @@ -208,4 +221,4 @@ "sort_field": "modified", "sort_order": "DESC", "states": [] -} \ No newline at end of file +} diff --git a/frappe/desk/doctype/workspace_number_card/__init__.py b/frappe/desk/doctype/workspace_number_card/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/frappe/desk/doctype/workspace_number_card/workspace_number_card.json b/frappe/desk/doctype/workspace_number_card/workspace_number_card.json new file mode 100644 index 0000000000..f9e3865d74 --- /dev/null +++ b/frappe/desk/doctype/workspace_number_card/workspace_number_card.json @@ -0,0 +1,40 @@ +{ + "actions": [], + "allow_rename": 1, + "creation": "2023-02-15 01:16:26.216201", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "number_card_name", + "label" + ], + "fields": [ + { + "fieldname": "number_card_name", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Number Card Name", + "options": "Number Card", + "reqd": 1 + }, + { + "fieldname": "label", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Label" + } + ], + "index_web_pages_for_search": 1, + "istable": 1, + "links": [], + "modified": "2023-02-15 01:16:26.216201", + "modified_by": "Administrator", + "module": "Desk", + "name": "Workspace Number Card", + "owner": "Administrator", + "permissions": [], + "sort_field": "modified", + "sort_order": "DESC", + "states": [] +} \ No newline at end of file diff --git a/frappe/desk/doctype/workspace_number_card/workspace_number_card.py b/frappe/desk/doctype/workspace_number_card/workspace_number_card.py new file mode 100644 index 0000000000..e972f3f525 --- /dev/null +++ b/frappe/desk/doctype/workspace_number_card/workspace_number_card.py @@ -0,0 +1,9 @@ +# Copyright (c) 2023, Frappe Technologies and contributors +# For license information, please see license.txt + +# import frappe +from frappe.model.document import Document + + +class WorkspaceNumberCard(Document): + pass diff --git a/frappe/public/js/frappe/views/workspace/blocks/index.js b/frappe/public/js/frappe/views/workspace/blocks/index.js index d15635fba9..afee5ab98a 100644 --- a/frappe/public/js/frappe/views/workspace/blocks/index.js +++ b/frappe/public/js/frappe/views/workspace/blocks/index.js @@ -1,6 +1,7 @@ // import blocks import Header from "./header"; import Paragraph from "./paragraph"; +import NumberCard from "./number_card"; import Card from "./card"; import Chart from "./chart"; import Shortcut from "./shortcut"; @@ -16,6 +17,7 @@ frappe.provide("frappe.workspace_block"); frappe.workspace_block.blocks = { header: Header, paragraph: Paragraph, + number_card: NumberCard, card: Card, chart: Chart, shortcut: Shortcut, diff --git a/frappe/public/js/frappe/views/workspace/blocks/number_card.js b/frappe/public/js/frappe/views/workspace/blocks/number_card.js new file mode 100644 index 0000000000..a952d7666b --- /dev/null +++ b/frappe/public/js/frappe/views/workspace/blocks/number_card.js @@ -0,0 +1,62 @@ +import Block from "./block.js"; +export default class NumberCard extends Block { + static get toolbox() { + return { + title: "Number Card", + icon: frappe.utils.icon("income", "sm"), + }; + } + + static get isReadOnlySupported() { + return true; + } + + constructor({ data, api, config, readOnly, block }) { + super({ data, api, config, readOnly, block }); + this.sections = {}; + this.col = this.data.col ? this.data.col : "4"; + this.allow_customization = !this.readOnly; + this.options = { + allow_sorting: this.allow_customization, + allow_create: this.allow_customization, + allow_delete: this.allow_customization, + allow_hiding: false, + allow_edit: true, + allow_resize: true, + }; + } + + render() { + this.wrapper = document.createElement("div"); + this.new("number_card"); + + if (this.data && this.data.number_card_name) { + let has_data = this.make("number_card", this.data.number_card_name); + if (!has_data) return; + } + + if (!this.readOnly) { + $(this.wrapper).find(".widget").addClass("number_card edit-mode"); + this.add_settings_button(); + this.add_new_block_button(); + } + + return this.wrapper; + } + + validate(savedData) { + if (!savedData.number_card_name) { + return false; + } + + return true; + } + + save() { + return { + number_card_name: this.wrapper.getAttribute("number_card_name"), + col: this.get_col(), + new: this.new_block_widget, + }; + } +} diff --git a/frappe/public/js/frappe/views/workspace/workspace.js b/frappe/public/js/frappe/views/workspace/workspace.js index 76f528dad7..fca6f35786 100644 --- a/frappe/public/js/frappe/views/workspace/workspace.js +++ b/frappe/public/js/frappe/views/workspace/workspace.js @@ -387,6 +387,7 @@ frappe.views.Workspace = class Workspace { this.editor.isReady.then(() => { this.editor.configuration.tools.chart.config.page_data = this.page_data; this.editor.configuration.tools.shortcut.config.page_data = this.page_data; + this.editor.configuration.tools.number_card.config.page_data = this.page_data; this.editor.configuration.tools.card.config.page_data = this.page_data; this.editor.configuration.tools.onboarding.config.page_data = this.page_data; this.editor.configuration.tools.quick_list.config.page_data = this.page_data; @@ -1334,9 +1335,16 @@ frappe.views.Workspace = class Workspace { page_data: this.page_data || [], }, }, + number_card: { + class: this.blocks["number_card"], + config: { + page_data: this.page_data || [], + }, + }, spacer: this.blocks["spacer"], HeaderSize: frappe.workspace_block.tunes["header_size"], }; + this.editor = new EditorJS({ data: { blocks: blocks || [], diff --git a/frappe/public/js/frappe/widgets/number_card_widget.js b/frappe/public/js/frappe/widgets/number_card_widget.js index 0874f825a6..03502cfd72 100644 --- a/frappe/public/js/frappe/widgets/number_card_widget.js +++ b/frappe/public/js/frappe/widgets/number_card_widget.js @@ -11,6 +11,7 @@ export default class NumberCardWidget extends Widget { get_config() { return { name: this.name, + number_card_name: this.number_card_name || this.name, label: this.label, color: this.color, hidden: this.hidden, @@ -31,7 +32,7 @@ export default class NumberCardWidget extends Widget { } make_card() { - frappe.model.with_doc("Number Card", this.name).then((card) => { + frappe.model.with_doc("Number Card", this.number_card_name || this.name).then((card) => { if (!card) { if (this.document_type) { frappe.run_serially([ @@ -144,7 +145,6 @@ export default class NumberCardWidget extends Widget { } render_card() { - this.prepare_actions(); this.set_title(); this.set_loading_state(); diff --git a/frappe/public/js/frappe/widgets/widget_dialog.js b/frappe/public/js/frappe/widgets/widget_dialog.js index 1696927cd8..56234071e3 100644 --- a/frappe/public/js/frappe/widgets/widget_dialog.js +++ b/frappe/public/js/frappe/widgets/widget_dialog.js @@ -643,7 +643,7 @@ class NumberCardDialog extends WidgetDialog { } data.stats_filter = this.filter_group && JSON.stringify(this.filter_group.get_filters()); data.document_type = this.document_type; - + data.label = data.label ? data.label : data.card; return data; } }