Sfoglia il codice sorgente

Merge branch 'develop' into duplicate-listview-records

version-14
Shariq Ansari 3 anni fa
committed by GitHub
parent
commit
ec1443323a
Non sono state trovate chiavi note per questa firma nel database ID Chiave GPG: 4AEE18F83AFDEB23
23 ha cambiato i file con 923 aggiunte e 860 eliminazioni
  1. +2
    -0
      .github/helper/documentation.py
  2. +699
    -685
      frappe/core/doctype/doctype/doctype.json
  3. +0
    -0
      frappe/core/doctype/doctype_state/__init__.py
  4. +50
    -0
      frappe/core/doctype/doctype_state/doctype_state.json
  5. +8
    -0
      frappe/core/doctype/doctype_state/doctype_state.py
  6. +16
    -0
      frappe/custom/doctype/customize_form/customize_form.js
  7. +19
    -1
      frappe/custom/doctype/customize_form/customize_form.json
  8. +8
    -2
      frappe/custom/doctype/customize_form/customize_form.py
  9. +3
    -2
      frappe/custom/doctype/property_setter/property_setter.json
  10. +47
    -147
      frappe/desk/doctype/kanban_board_column/kanban_board_column.json
  11. +1
    -1
      frappe/model/base_document.py
  12. +11
    -3
      frappe/model/meta.py
  13. +1
    -1
      frappe/model/sync.py
  14. +7
    -5
      frappe/modules/import_file.py
  15. +1
    -0
      frappe/patches.txt
  16. +22
    -0
      frappe/patches/v14_0/update_color_names_in_kanban_board_column.py
  17. +1
    -1
      frappe/public/js/frappe/list/list_view.js
  18. +10
    -0
      frappe/public/js/frappe/model/indicator.js
  19. +7
    -8
      frappe/public/js/frappe/views/kanban/kanban_board.js
  20. +1
    -0
      frappe/public/js/frappe/widgets/widget_dialog.js
  21. +1
    -1
      frappe/public/scss/common/global.scss
  22. +7
    -3
      frappe/public/scss/common/indicator.scss
  23. +1
    -0
      frappe/utils/install.py

+ 2
- 0
.github/helper/documentation.py Vedi File

@@ -24,6 +24,8 @@ def docs_link_exists(body):
parts = parsed_url.path.split('/')
if len(parts) == 5 and parts[1] == "frappe" and parts[2] in docs_repos:
return True
if parsed_url.netloc in ["docs.erpnext.com", "frappeframework.com"]:
return True


if __name__ == "__main__":


+ 699
- 685
frappe/core/doctype/doctype/doctype.json
File diff soppresso perché troppo grande
Vedi File


+ 0
- 0
frappe/core/doctype/doctype_state/__init__.py Vedi File


+ 50
- 0
frappe/core/doctype/doctype_state/doctype_state.json Vedi File

@@ -0,0 +1,50 @@
{
"actions": [],
"creation": "2021-08-23 17:21:28.345841",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"title",
"color",
"custom"
],
"fields": [
{
"fieldname": "title",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Title",
"reqd": 1
},
{
"default": "Blue",
"fieldname": "color",
"fieldtype": "Select",
"in_list_view": 1,
"label": "Color",
"options": "Blue\nCyan\nGray\nGreen\nLight Blue\nOrange\nPink\nPurple\nRed\nYellow",
"reqd": 1
},
{
"default": "0",
"fieldname": "custom",
"fieldtype": "Check",
"hidden": 1,
"label": "Custom"
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2021-12-14 14:14:55.716378",
"modified_by": "Administrator",
"module": "Core",
"name": "DocType State",
"owner": "Administrator",
"permissions": [],
"sort_field": "modified",
"sort_order": "DESC",
"states": [],
"track_changes": 1
}

+ 8
- 0
frappe/core/doctype/doctype_state/doctype_state.py Vedi File

@@ -0,0 +1,8 @@
# Copyright (c) 2021, Frappe Technologies and contributors
# For license information, please see license.txt

# import frappe
from frappe.model.document import Document

class DocTypeState(Document):
pass

+ 16
- 0
frappe/custom/doctype/customize_form/customize_form.js Vedi File

@@ -114,6 +114,7 @@ frappe.ui.form.on("Customize Form", {
frm.page.clear_icons();

if (frm.doc.doc_type) {
frm.page.set_title(__('Customize Form - {0}', [frm.doc.doc_type]));
frappe.customize_form.set_primary_action(frm);

frm.add_custom_button(
@@ -276,6 +277,21 @@ frappe.ui.form.on("DocType Action", {
}
});

// can't delete standard states
frappe.ui.form.on("DocType State", {
before_states_remove: function(frm, doctype, name) {
let row = frappe.get_doc(doctype, name);
if (!(row.custom || row.__islocal)) {
frappe.msgprint(__("Cannot delete standard document state."));
throw "cannot delete standard document state";
}
},
states_add: function(frm, cdt, cdn) {
let f = frappe.model.get_doc(cdt, cdn);
f.custom = 1;
}
});

frappe.customize_form.set_primary_action = function(frm) {
frm.page.set_primary_action(__("Update"), function() {
if (frm.doc.doc_type) {


+ 19
- 1
frappe/custom/doctype/customize_form/customize_form.json Vedi File

@@ -41,6 +41,8 @@
"actions",
"document_links_section",
"links",
"document_states_section",
"states",
"section_break_8",
"sort_field",
"column_break_10",
@@ -280,6 +282,20 @@
"fieldname": "autoname",
"fieldtype": "Data",
"label": "Auto Name"
},
{
"collapsible": 1,
"collapsible_depends_on": "states",
"depends_on": "doc_type",
"fieldname": "document_states_section",
"fieldtype": "Section Break",
"label": "Document States"
},
{
"fieldname": "states",
"fieldtype": "Table",
"label": "States",
"options": "DocType State"
}
],
"hide_toolbar": 1,
@@ -288,10 +304,11 @@
"index_web_pages_for_search": 1,
"issingle": 1,
"links": [],
"modified": "2021-06-21 19:01:06.920663",
"modified": "2021-12-14 16:45:04.308690",
"modified_by": "Administrator",
"module": "Custom",
"name": "Customize Form",
"naming_rule": "Expression (old style)",
"owner": "Administrator",
"permissions": [
{
@@ -308,5 +325,6 @@
"search_fields": "doc_type",
"sort_field": "modified",
"sort_order": "DESC",
"states": [],
"track_changes": 1
}

+ 8
- 2
frappe/custom/doctype/customize_form/customize_form.py Vedi File

@@ -72,7 +72,7 @@ class CustomizeForm(Document):
new_d[prop] = d.get(prop)
self.append("fields", new_d)

for fieldname in ('links', 'actions'):
for fieldname in ('links', 'actions', 'states'):
for d in meta.get(fieldname):
self.append(fieldname, d)

@@ -258,7 +258,8 @@ class CustomizeForm(Document):
'''
for doctype, fieldname, field_map in (
('DocType Link', 'links', doctype_link_properties),
('DocType Action', 'actions', doctype_action_properties)
('DocType Action', 'actions', doctype_action_properties),
('DocType State', 'states', doctype_state_properties),
):
has_custom = False
items = []
@@ -568,6 +569,11 @@ doctype_action_properties = {
'hidden': 'Check'
}

doctype_state_properties = {
'title': 'Data',
'color': 'Select'
}


ALLOWED_FIELDTYPE_CHANGE = (
('Currency', 'Float', 'Percent'),


+ 3
- 2
frappe/custom/doctype/property_setter/property_setter.json Vedi File

@@ -37,7 +37,7 @@
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Applied On",
"options": "\nDocField\nDocType\nDocType Link\nDocType Action",
"options": "\nDocField\nDocType\nDocType Link\nDocType Action\nDocType State",
"read_only_depends_on": "eval:!doc.__islocal",
"reqd": 1
},
@@ -109,7 +109,7 @@
"idx": 1,
"index_web_pages_for_search": 1,
"links": [],
"modified": "2021-09-04 12:46:17.860769",
"modified": "2021-12-14 14:15:41.929071",
"modified_by": "Administrator",
"module": "Custom",
"name": "Property Setter",
@@ -141,5 +141,6 @@
"search_fields": "doc_type,property",
"sort_field": "modified",
"sort_order": "DESC",
"states": [],
"track_changes": 1
}

+ 47
- 147
frappe/desk/doctype/kanban_board_column/kanban_board_column.json Vedi File

@@ -1,155 +1,55 @@
{
"allow_copy": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
"creation": "2016-10-19 12:26:42.569185",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "",
"editable_grid": 1,
"engine": "InnoDB",
"actions": [],
"creation": "2016-10-19 12:26:42.569185",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"column_name",
"status",
"indicator",
"order"
],
"fields": [
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_name",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Column 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": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
"fieldname": "column_name",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Column Name"
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "Active",
"fieldname": "status",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Status",
"length": 0,
"no_copy": 0,
"options": "Active\nArchived",
"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
},
"default": "Active",
"fieldname": "status",
"fieldtype": "Select",
"in_list_view": 1,
"label": "Status",
"options": "Active\nArchived"
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "darkgrey",
"fieldname": "indicator",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Indicator",
"length": 0,
"no_copy": 0,
"options": "blue\norange\nred\ngreen\ndarkgrey\npurple\nyellow\nlightblue",
"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
},
"default": "Gray",
"fieldname": "indicator",
"fieldtype": "Select",
"in_list_view": 1,
"label": "Indicator",
"options": "Blue\nCyan\nGray\nGreen\nLight Blue\nOrange\nPink\nPurple\nRed\nRed\nYellow"
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "order",
"fieldtype": "Code",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Order",
"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
"fieldname": "order",
"fieldtype": "Code",
"label": "Order"
}
],
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,

"is_submittable": 0,
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2017-01-17 15:23:43.520379",
"modified_by": "Administrator",
"module": "Desk",
"name": "Kanban Board Column",
"name_case": "",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
"read_only": 0,
"read_only_onload": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1,
"track_seen": 0
],
"istable": 1,
"links": [],
"modified": "2021-12-14 13:13:38.804259",
"modified_by": "Administrator",
"module": "Desk",
"name": "Kanban Board Column",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
"sort_field": "modified",
"sort_order": "DESC",
"states": [],
"track_changes": 1
}

+ 1
- 1
frappe/model/base_document.py Vedi File

@@ -338,7 +338,7 @@ class BaseDocument(object):
return self.meta.get_field(fieldname).options
except AttributeError:
if self.doctype == 'DocType':
return dict(links='DocType Link', actions='DocType Action').get(fieldname)
return dict(links='DocType Link', actions='DocType Action', states='DocType State').get(fieldname)
raise

def get_parentfield_of_doctype(self, doctype):


+ 11
- 3
frappe/model/meta.py Vedi File

@@ -66,7 +66,7 @@ def load_doctype_from_file(doctype):
class Meta(Document):
_metaclass = True
default_fields = list(default_fields)[1:]
special_doctypes = ("DocField", "DocPerm", "DocType", "Module Def", 'DocType Action', 'DocType Link')
special_doctypes = ("DocField", "DocPerm", "DocType", "Module Def", 'DocType Action', 'DocType Link', 'DocType State')

def __init__(self, doctype):
self._fields = {}
@@ -184,7 +184,8 @@ class Meta(Document):
"fields": "DocField",
"permissions": "DocPerm",
"actions": "DocType Action",
'links': 'DocType Link'
"links": "DocType Link",
"states": "DocType State",
}.get(fieldname)

def get_field(self, fieldname):
@@ -343,8 +344,14 @@ class Meta(Document):
d.set(ps.property, cast(ps.property_type, ps.value))
break

elif ps.doctype_or_field=='DocType State':
for d in self.states:
if d.name == ps.row_name:
d.set(ps.property, cast(ps.property_type, ps.value))
break

def add_custom_links_and_actions(self):
for doctype, fieldname in (('DocType Link', 'links'), ('DocType Action', 'actions')):
for doctype, fieldname in (('DocType Link', 'links'), ('DocType Action', 'actions'), ('DocType State', 'states')):
# ignore_ddl because the `custom` column was added later via a patch
for d in frappe.get_all(doctype, fields='*', filters=dict(parent=self.name, custom=1), ignore_ddl=True):
self.append(fieldname, d)
@@ -571,6 +578,7 @@ DOCTYPE_TABLE_FIELDS = [
frappe._dict({"fieldname": "permissions", "options": "DocPerm"}),
frappe._dict({"fieldname": "actions", "options": "DocType Action"}),
frappe._dict({"fieldname": "links", "options": "DocType Link"}),
frappe._dict({"fieldname": "states", "options": "DocType State"}),
]

#######


+ 1
- 1
frappe/model/sync.py Vedi File

@@ -30,7 +30,7 @@ def sync_for(app_name, force=0, reset_permissions=False):

FRAPPE_PATH = frappe.get_app_path("frappe")

for core_module in ["docfield", "docperm", "doctype_action", "doctype_link", "role", "has_role", "doctype"]:
for core_module in ["docfield", "docperm", "doctype_action", "doctype_link", "doctype_state", "role", "has_role", "doctype"]:
files.append(os.path.join(FRAPPE_PATH, "core", "doctype", core_module, f"{core_module}.json"))

for custom_module in ["custom_field", "property_setter"]:


+ 7
- 5
frappe/modules/import_file.py Vedi File

@@ -8,7 +8,7 @@ import frappe
from frappe.model.base_document import get_controller
from frappe.modules import get_module_path, scrub_dt_dn
from frappe.query_builder import DocType
from frappe.utils import get_datetime_str, now
from frappe.utils import get_datetime, now


def caclulate_hash(path: str) -> str:
@@ -109,7 +109,9 @@ def import_file_by_path(path: str,force: bool = False,data_import: bool = False,

# modified timestamp in db, none if doctype's first import
db_modified_timestamp = frappe.db.get_value(doc["doctype"], doc["name"], "modified")
is_db_timestamp_latest = db_modified_timestamp and doc.get("modified") <= get_datetime_str(db_modified_timestamp)
is_db_timestamp_latest = db_modified_timestamp and (
get_datetime(doc.get("modified")) <= get_datetime(db_modified_timestamp)
)

if not force or db_modified_timestamp:
try:
@@ -120,11 +122,11 @@ def import_file_by_path(path: str,force: bool = False,data_import: bool = False,

# if hash exists and is equal no need to update
if stored_hash and stored_hash == calculated_hash:
return False
continue

# if hash doesn't exist, check if db timestamp is same as json timestamp, add hash if from doctype
if is_db_timestamp_latest and doc["doctype"] != "DocType":
return False
continue

import_doc(
docdict=doc,
@@ -161,7 +163,7 @@ def import_file_by_path(path: str,force: bool = False,data_import: bool = False,
def is_timestamp_changed(doc):
# check if timestamps match
db_modified = frappe.db.get_value(doc["doctype"], doc["name"], "modified")
return not (db_modified and doc.get("modified") == get_datetime_str(db_modified))
return not (db_modified and get_datetime(doc.get("modified")) == get_datetime(db_modified))


def read_doc_from_file(path):


+ 1
- 0
frappe/patches.txt Vedi File

@@ -187,3 +187,4 @@ frappe.patches.v14_0.copy_mail_data #08.03.21
frappe.patches.v14_0.update_workspace2 # 20.09.2021
frappe.patches.v14_0.update_github_endpoints #08-11-2021
frappe.patches.v14_0.remove_db_aggregation
frappe.patches.v14_0.update_color_names_in_kanban_board_column

+ 22
- 0
frappe/patches/v14_0/update_color_names_in_kanban_board_column.py Vedi File

@@ -0,0 +1,22 @@
# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors
# MIT License. See license.txt

from __future__ import unicode_literals
import frappe

def execute():
frappe.reload_doc("desk", "doctype", "kanban_board_column")
indicator_map = {
'blue': 'Blue',
'orange': 'Orange',
'red': 'Red',
'green': 'Green',
'darkgrey': 'Gray',
'gray': 'Gray',
'purple': 'Purple',
'yellow': 'Yellow',
'lightblue': 'Light Blue',
}
for d in frappe.db.get_all('Kanban Board Column', fields=['name', 'indicator']):
color_name = indicator_map.get(d.indicator, 'Gray')
frappe.db.set_value('Kanban Board Column', d.name, 'indicator', color_name)

+ 1
- 1
frappe/public/js/frappe/list/list_view.js Vedi File

@@ -312,7 +312,7 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList {
let $check_all_checkbox = this.$checkbox_actions.find(".list-check-all");

if ($check_all_checkbox.prop("checked") && target && !target.prop("checked")) {
$check_all_checkbox.prop("checked", false);
$check_all_checkbox.prop("checked", false);
}

$check_all_checkbox.prop("checked", this.$checks.length === this.data.length);


+ 10
- 0
frappe/public/js/frappe/model/indicator.js Vedi File

@@ -10,6 +10,8 @@ frappe.has_indicator = function(doctype) {
} else if(frappe.meta.has_field(doctype, 'enabled')
|| frappe.meta.has_field(doctype, 'disabled')) {
return true;
} else if (frappe.meta.has_field(doctype, 'status') && frappe.get_meta(doctype).states.length) {
return true;
}
return false;
}
@@ -21,6 +23,7 @@ frappe.get_indicator = function(doc, doctype) {

if(!doctype) doctype = doc.doctype;

let meta = frappe.get_meta(doctype);
var workflow = frappe.workflow.workflows[doctype];
var without_workflow = workflow ? workflow['override_status'] : true;

@@ -61,6 +64,13 @@ frappe.get_indicator = function(doc, doctype) {
return [__("Cancelled"), "red", "docstatus,=,2"];
}

// based on document state
if (doc.status && meta && meta.states && meta.states.find(d => d.title === doc.status)) {
let state = meta.states.find(d => d.title === doc.status);
let color_class = frappe.scrub(state.color, '-');
return [__(doc.status), color_class, "status,=," + doc.status];
}

if(settings.get_indicator) {
var indicator = settings.get_indicator(doc);
if(indicator) return indicator;


+ 7
- 8
frappe/public/js/frappe/views/kanban/kanban_board.js Vedi File

@@ -467,7 +467,7 @@ frappe.provide("frappe.views");
'kanban_column', {
title: column.title,
doctype: store.getState().doctype,
indicator: column.indicator
indicator: frappe.scrub(column.indicator, '-')
})).appendTo(wrapper);
self.$kanban_cards = self.$kanban_column.find('.kanban-cards');
}
@@ -581,13 +581,12 @@ frappe.provide("frappe.views");
}
});
get_column_indicators(function(indicators) {
var html = '<li class="button-group">';
html += indicators.reduce(function(prev, curr) {
return prev + '<div \
data-action="indicator" data-indicator="'+curr+'"\
class="btn btn-default btn-xs indicator-pill ' + curr + '"></div>';
}, "");
html += '</li>';
let html = `<li class="button-group">${
indicators.map(indicator => {
let classname = frappe.scrub(indicator, '-');
return `<div data-action="indicator" data-indicator="${indicator}" class="btn btn-default btn-xs indicator-pill ${classname}"></div>`
}).join('')
}</li>`;
self.$kanban_column.find(".column-options .dropdown-menu")
.append(html);
});


+ 1
- 0
frappe/public/js/frappe/widgets/widget_dialog.js Vedi File

@@ -352,6 +352,7 @@ class ShortcutDialog extends WidgetDialog {
label: __("Color"),
options: ["Grey", "Green", "Red", "Orange", "Pink", "Yellow", "Blue", "Cyan"],
default: "Grey",
input_class: "color-select",
onchange: () => {
let color = this.dialog.fields_dict.color.value.toLowerCase();
let $select = this.dialog.fields_dict.color.$input;


+ 1
- 1
frappe/public/scss/common/global.scss Vedi File

@@ -119,7 +119,7 @@ input[type="checkbox"] {
}

.frappe-control[data-fieldtype="Select"].frappe-control[data-fieldname="color"] {
select {
.color-select {
padding-left: 40px;
}



+ 7
- 3
frappe/public/scss/common/indicator.scss Vedi File

@@ -163,9 +163,13 @@
@include indicator-pill-color('purple');
}

.indicator-pill.lightblue,
.indicator-pill-right.lightblue,
.indicator-pill-round.lightblue {
.indicator.light-blue {
@include indicator-color('light-blue');
}

.indicator-pill.light-blue,
.indicator-pill-right.light-blue,
.indicator-pill-round.light-blue {
@include indicator-pill-color('light-blue');
}



+ 1
- 0
frappe/utils/install.py Vedi File

@@ -9,6 +9,7 @@ def before_install():
frappe.reload_doc("core", "doctype", "docperm")
frappe.reload_doc("core", "doctype", "doctype_action")
frappe.reload_doc("core", "doctype", "doctype_link")
frappe.reload_doc("core", "doctype", "doctype_state")
frappe.reload_doc("desk", "doctype", "form_tour_step")
frappe.reload_doc("desk", "doctype", "form_tour")
frappe.reload_doc("core", "doctype", "doctype")


Caricamento…
Annulla
Salva