diff --git a/.eslintrc b/.eslintrc index e79571f556..eef33ec8a0 100644 --- a/.eslintrc +++ b/.eslintrc @@ -5,7 +5,7 @@ "es6": true }, "parserOptions": { - "ecmaVersion": 8, + "ecmaVersion": 9, "sourceType": "module" }, "extends": "eslint:recommended", diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml deleted file mode 100644 index 26801ebbe8..0000000000 --- a/.github/workflows/backport.yml +++ /dev/null @@ -1,16 +0,0 @@ -name: Backport -on: - pull_request: - types: - - closed - - labeled - -jobs: - backport: - runs-on: ubuntu-18.04 - name: Backport - steps: - - name: Backport - uses: tibdex/backport@v1 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} 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 41d1765684..6569b2fb20 100644 --- a/frappe/core/desk_page/settings/settings.json +++ b/frappe/core/desk_page/settings/settings.json @@ -1,37 +1,37 @@ { "cards": [ { - "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" + "hidden": 0, + "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]" }, { - "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" + "hidden": 0, + "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]" }, { - "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" + "hidden": 0, + "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]" }, { - "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" + "hidden": 0, + "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]" }, { - "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" + "hidden": 0, + "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]" }, { - "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" + "hidden": 0, + "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 +42,29 @@ "idx": 0, "is_standard": 1, "label": "Settings", - "modified": "2020-03-12 16:30:43.510434", + "modified": "2020-04-01 11:24:40.636747", "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" } 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/core/doctype/user/user.py b/frappe/core/doctype/user/user.py index ddad3a91fb..7837c90d2b 100644 --- a/frappe/core/doctype/user/user.py +++ b/frappe/core/doctype/user/user.py @@ -205,7 +205,7 @@ class User(Document): _update_password(user=self.name, pwd=new_password, logout_all_sessions=self.logout_all_sessions) - if not self.flags.no_welcome_mail and self.send_welcome_email: + if not self.flags.no_welcome_mail and cint(self.send_welcome_email): self.send_welcome_mail_to_user() self.flags.email_sent = 1 if frappe.session.user != 'Guest': @@ -577,7 +577,7 @@ def update_password(new_password, logout_all_sessions=0, key=None, old_password= return redirect_url if redirect_url else "/" @frappe.whitelist(allow_guest=True) -def test_password_strength(new_password, key=None, old_password=None, user_data=[]): +def test_password_strength(new_password, key=None, old_password=None, user_data=None): from frappe.utils.password_strength import test_password_strength as _test_password_strength password_policy = frappe.db.get_value("System Settings", None, diff --git a/frappe/core/page/dashboard/dashboard.js b/frappe/core/page/dashboard/dashboard.js index 88bfba9e84..ad65b05894 100644 --- a/frappe/core/page/dashboard/dashboard.js +++ b/frappe/core/page/dashboard/dashboard.js @@ -97,7 +97,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/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/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/desk/desktop.py b/frappe/desk/desktop.py index 1cb03355c6..26bc8c96b3 100644 --- a/frappe/desk/desktop.py +++ b/frappe/desk/desktop.py @@ -4,24 +4,34 @@ from __future__ import unicode_literals import frappe -import json -from frappe import _, DoesNotExistError +from json import loads, dumps +from frappe import _, DoesNotExistError, ValidationError, _dict from frappe.boot import get_allowed_pages, get_allowed_reports from six import string_types -from frappe.cache_manager import build_domain_restriced_doctype_cache, build_domain_restriced_page_cache, build_table_count_cache +from frappe.cache_manager import ( + build_domain_restriced_doctype_cache, + build_domain_restriced_page_cache, + build_table_count_cache +) class Workspace: def __init__(self, page_name): self.page_name = page_name - - def build_cache(self): - self.doc = frappe.get_doc("Desk Page", self.page_name) - self.get_pages_to_extend() + self.extended_cards = [] + self.extended_charts = [] + self.extended_shortcuts = [] user = frappe.get_user() user.build_permissions() - self.user = user + user_doc = frappe.get_doc('User', frappe.session.user) + self.blocked_modules = user_doc.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() @@ -29,16 +39,27 @@ class Workspace: 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, - 'restrict_to_domain': ['in', frappe.get_active_domains()] + 'restrict_to_domain': ['in', frappe.get_active_domains()], + 'for_user': '', + 'module': ['not in', self.blocked_modules] }) 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 @@ -61,17 +82,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.shortcuts_label), 'items': self.get_shortcuts() } @@ -105,18 +126,21 @@ class Workspace: item["count"] = count + # Translate label + item["label"] = _(item.label) if item.label else _(item.name) + return item new_data = [] 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 for item in links: - item = frappe._dict(item) + item = _dict(item) # Condition: based on country if item.country and item.country != default_country: @@ -125,15 +149,15 @@ 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): + if isinstance(section, _dict): new_section = section.copy() else: new_section = section.as_dict().copy() new_section["links"] = new_items - new_section["label"] = section.title + new_section["label"] = _(new_section["label"]) new_data.append(new_section) return new_data @@ -147,7 +171,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 @@ -167,21 +192,23 @@ class Workspace: for item in shortcuts: new_item = item.as_dict().copy() - 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] - 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 + else: + new_item['ref_doctype'] = report.get('ref_doctype') + + # Translate label + new_item["label"] = _(item.label) if item.label else _(item.link_to) items.append(new_item) return items @frappe.whitelist() +@frappe.read_only() def get_desktop_page(page): """Applies permissions, customizations and returns the configruration for a page on desk. @@ -192,9 +219,8 @@ def get_desktop_page(page): Returns: dict: dictionary of cards, charts and shortcuts to be displayed on website """ - wspace = Workspace(page) try: - wspace.build_cache() + wspace = Workspace(page) wspace.build_workspace() return { 'charts': wspace.charts, @@ -213,9 +239,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': False + 'extends_another_page': 0, + 'is_standard': 1, + 'for_user': '', + 'module': ['not in', blocked_modules] } if not frappe.local.conf.developer_mode: @@ -228,8 +259,10 @@ 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')) sidebar_items[page["category"]].append(page) return sidebar_items @@ -242,8 +275,8 @@ def get_table_with_counts(): def get_custom_reports_and_doctypes(module): return [ - frappe._dict({ - "title": "Custom", + _dict({ + "label": "Custom", "links": get_custom_doctype_list(module) + get_custom_report_list(module) }) ] @@ -280,104 +313,111 @@ def get_custom_report_list(module): return out -def make_them_pages(): - """Helper function to make pages +def get_custom_workspace_for_user(page): + """Get custom page from desk_page if exists or create one + + Args: + page (stirng): Page name + + Returns: + Object: Document object """ - 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]) + 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]) + doc = frappe.new_doc("Desk Page") + doc.extends = page + doc.for_user = frappe.session.user + return doc -def make_them_cards(page_name, from_module=None, to_module=None, icon=None): - from frappe.desk.moduleview import get +@frappe.whitelist() +def save_customization(page, config): + """Save customizations as a separate doctype in Desk page per user - if not from_module: - from_module = page_name + Args: + page (string): Name of the page to be edited + config (dict): Dictionary config of al widgets - if not to_module: - to_module = page_name + Returns: + Boolean: Customization saving status + """ + original_page = frappe.get_doc("Desk Page", page) + page_doc = get_custom_workspace_for_user(page) + + # Update field values + page_doc.update({ + "charts_label": original_page.charts_label, + "cards_label": original_page.cards_label, + "shortcuts_label": original_page.shortcuts_label, + "icon": original_page.icon, + "module": original_page.module, + "developer_mode_only": original_page.developer_mode_only, + "category": original_page.category + }) + + config = _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") + + # Set label + page_doc.label = page + '-' + frappe.session.user try: - modules = get(from_module)['data'] - except: - return + if page_doc.is_new(): + page_doc.insert(ignore_permissions=True) + else: + page_doc.save(ignore_permissions=True) + except (ValidationError, TypeError) as e: + # Create a json string to log + json_config = dumps(config, sort_keys=True, indent=4) - # 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)) - else: - page = frappe.new_doc("Desk Page") - page.label = page_name - page.cards = [] - page.icon = icon - print("--- New Page: {0}".format(page.name)) + # Error log body + log = \ + """ + page: {0} + config: {1} + exception: {2} + """.format(page, json_config, e) + frappe.log_error(log, _("Could not save customization")) + return False - # Guess Which Module - if not to_module and frappe.db.exists("Module Def", page_name): - page.module = page_name + return True - if to_module: - page.module = to_module - elif frappe.db.exists("Module Def", page_name): - page.module = page_name - for data in modules: - # Create a New Card Child Doc - card = frappe.new_doc("Desk Card") +def prepare_widget(config, doctype, parentfield): + """Create widget child table entries with parent details - # Data clean up - for item in data['items']: - try: - del item['count'] - del item['incomplete_dependencies'] - except KeyError: - pass + Args: + config (dict): Dictionary containing widget config + doctype (string): Doctype name of the child table + parentfield (string): Parent field for the child table - # 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) + Returns: + TYPE: List of Document objects + """ + 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) - # Set Parent attributes - card.parent = page.name - card.parenttype = page.doctype - card.parentfield = "cards" + # New Doc + doc = frappe.new_doc(doctype) + doc.update(wid_config) - # Add cards to page doc - print("------- Adding Card: {0}".format(card.title)) - page.cards.append(card) + # Manually Set IDX + doc.idx = idx + 1 - # End it all - page.save() - frappe.db.commit() - return \ No newline at end of file + # Set Parent Field + doc.parentfield = parentfield + + prepare_widget_list.append(doc) + return prepare_widget_list diff --git a/frappe/desk/doctype/desk_card/desk_card.json b/frappe/desk/doctype/desk_card/desk_card.json index 4ccffd4f58..dbcb4b0d5c 100644 --- a/frappe/desk/doctype/desk_card/desk_card.json +++ b/frappe/desk/doctype/desk_card/desk_card.json @@ -2,11 +2,12 @@ "actions": [], "creation": "2020-01-29 14:45:54.383089", "doctype": "DocType", + "editable_grid": 1, "engine": "InnoDB", "field_order": [ - "title", + "label", "column_break_2", - "icon", + "hidden", "section_break_3", "links" ], @@ -18,13 +19,6 @@ "options": "JSON", "reqd": 1 }, - { - "fieldname": "title", - "fieldtype": "Data", - "in_list_view": 1, - "label": "Title", - "reqd": 1 - }, { "fieldname": "section_break_3", "fieldtype": "Section Break" @@ -34,14 +28,23 @@ "fieldtype": "Column Break" }, { - "fieldname": "icon", + "default": "0", + "fieldname": "hidden", + "fieldtype": "Check", + "in_list_view": 1, + "label": "Hidden" + }, + { + "fieldname": "label", "fieldtype": "Data", - "label": "Icon" + "in_list_view": 1, + "label": "Label", + "reqd": 1 } ], "istable": 1, "links": [], - "modified": "2020-02-03 12:40:42.595122", + "modified": "2020-03-31 14:38:06.303847", "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_page/desk_page.js b/frappe/desk/doctype/desk_page/desk_page.js index 7af3e0e98c..3087a5f5b8 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_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", diff --git a/frappe/desk/doctype/desk_shortcut/desk_shortcut.json b/frappe/desk/doctype/desk_shortcut/desk_shortcut.json index 6b57f250a9..9f8990732a 100644 --- a/frappe/desk/doctype/desk_shortcut/desk_shortcut.json +++ b/frappe/desk/doctype/desk_shortcut/desk_shortcut.json @@ -6,11 +6,11 @@ "engine": "InnoDB", "field_order": [ "type", - "icon", + "label", "column_break_4", "link_to", + "icon", "restrict_to_domain", - "is_query_report", "section_break_5", "stats_filter", "column_break_3", @@ -51,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" @@ -61,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" @@ -77,15 +72,22 @@ "fieldtype": "Column Break" }, { + "depends_on": "eval:frappe.boot.developer_mode", "fieldname": "restrict_to_domain", "fieldtype": "Link", "label": "Restrict to Domain", "options": "Domain" + }, + { + "fieldname": "label", + "fieldtype": "Data", + "label": "Label", + "reqd": 1 } ], "istable": 1, "links": [], - "modified": "2020-03-11 13:09:00.180528", + "modified": "2020-04-07 19:04:23.645198", "modified_by": "Administrator", "module": "Desk", "name": "Desk Shortcut", diff --git a/frappe/email/doctype/newsletter/newsletter.py b/frappe/email/doctype/newsletter/newsletter.py index 2d40ffd800..2469569892 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")) @@ -71,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: @@ -82,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 = [] @@ -268,6 +269,6 @@ def send_scheduled_email(): scheduled_newsletter = frappe.get_all('Newsletter', filters = { 'schedule_send': ('<=', now_datetime()), 'email_sent': 0 - }, fields = ['name']) + }, fields = ['name'], ignore_ifnull=True) for newsletter in scheduled_newsletter: - send_newsletter(newsletter.name) \ No newline at end of file + send_newsletter(newsletter.name) 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/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/grid_row.js b/frappe/public/js/frappe/form/grid_row.js index 0e36e671cc..31d62dc445 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, true, 15); this.refresh(); if(cur_frm) cur_frm.cur_grid = null; this.wrapper.removeClass("grid-row-open"); diff --git a/frappe/public/js/frappe/form/grid_row_form.js b/frappe/public/js/frappe/form/grid_row_form.js index 73f0856c08..f93640936f 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/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/public/js/frappe/list/list_sidebar_group_by.js b/frappe/public/js/frappe/list/list_sidebar_group_by.js index bd37b71ae4..7aa62dcb5f 100644 --- a/frappe/public/js/frappe/list/list_sidebar_group_by.js +++ b/frappe/public/js/frappe/list/list_sidebar_group_by.js @@ -53,15 +53,18 @@ 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); - fieldtype = frappe.meta.get_docfield(this.doctype, fieldname).fieldtype; + let docfield = frappe.meta.get_docfield(this.doctype, fieldname); + if (!docfield) { + return; + } + fieldtype = docfield.fieldtype; } return `