Merge branch 'develop' into rpay-webhook-verification
This commit is contained in:
commit
4e1ad550ec
55 changed files with 1303 additions and 663 deletions
22
.travis.yml
22
.travis.yml
|
|
@ -25,6 +25,7 @@ cache:
|
|||
# https://docs.cypress.io/guides/guides/continuous-integration.html#Caching
|
||||
- ~/.cache
|
||||
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- name: "Python 3.7 MariaDB"
|
||||
|
|
@ -46,7 +47,26 @@ matrix:
|
|||
script: bench --site test_site run-ui-tests frappe --headless
|
||||
|
||||
before_install:
|
||||
# install wkhtmltopdf
|
||||
# do we really want to run travis?
|
||||
- |
|
||||
ONLY_DOCS_CHANGES=$(git diff --name-only $TRAVIS_COMMIT_RANGE | grep -qvE '\.(md|png|jpg|jpeg)$|^.github|LICENSE' ; echo $?)
|
||||
ONLY_JS_CHANGES=$(git diff --name-only $TRAVIS_COMMIT_RANGE | grep -qvE '\.js$' ; echo $?)
|
||||
ONLY_PY_CHANGES=$(git diff --name-only $TRAVIS_COMMIT_RANGE | grep -qvE '\.py$' ; echo $?)
|
||||
|
||||
if [[ $ONLY_DOCS_CHANGES == "1" ]]; then
|
||||
echo "Only docs were updated, stopping build process.";
|
||||
exit;
|
||||
fi
|
||||
if [[ $ONLY_JS_CHANGES == "1" && $TYPE == "server" ]]; then
|
||||
echo "Only JavaScript code was updated; Stopping Python build process.";
|
||||
exit;
|
||||
fi
|
||||
if [[ $ONLY_PY_CHANGES == "1" && $TYPE == "ui" ]]; then
|
||||
echo "Only Python code was updated, stopping Cypress build process.";
|
||||
exit;
|
||||
fi
|
||||
|
||||
# install wkhtmltopdf
|
||||
- wget -O /tmp/wkhtmltox.tar.xz https://github.com/frappe/wkhtmltopdf/raw/master/wkhtmltox-0.12.3_linux-generic-amd64.tar.xz
|
||||
- tar -xf /tmp/wkhtmltox.tar.xz -C /tmp
|
||||
- sudo mv /tmp/wkhtmltox/bin/wkhtmltopdf /usr/local/bin/wkhtmltopdf
|
||||
|
|
|
|||
45
cypress/integration/control_duration.js
Normal file
45
cypress/integration/control_duration.js
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
context('Control Duration', () => {
|
||||
before(() => {
|
||||
cy.login();
|
||||
cy.visit('/desk#workspace/Website');
|
||||
});
|
||||
|
||||
function get_dialog_with_duration(show_days=1, show_seconds=1) {
|
||||
return cy.dialog({
|
||||
title: 'Duration',
|
||||
fields: [{
|
||||
'fieldname': 'duration',
|
||||
'fieldtype': 'Duration',
|
||||
'show_seconds': show_days,
|
||||
'show_days': show_seconds
|
||||
}]
|
||||
});
|
||||
}
|
||||
|
||||
it('should set duration', () => {
|
||||
get_dialog_with_duration().as('dialog');
|
||||
cy.get('.frappe-control[data-fieldname=duration] input')
|
||||
.first()
|
||||
.click();
|
||||
cy.get('.duration-input[data-duration=days]')
|
||||
.type(45, {force: true})
|
||||
.blur({force: true});
|
||||
cy.get('.duration-input[data-duration=minutes]')
|
||||
.type(30)
|
||||
.blur({force: true});
|
||||
cy.get('.frappe-control[data-fieldname=duration] input').first().should('have.value', '45d 30m');
|
||||
cy.get('.frappe-control[data-fieldname=duration] input').first().blur();
|
||||
cy.get('.duration-picker').should('not.be.visible');
|
||||
cy.get('@dialog').then(dialog => {
|
||||
let value = dialog.get_value('duration');
|
||||
expect(value).to.equal(3889800);
|
||||
});
|
||||
});
|
||||
|
||||
it('should hide days or seconds according to duration options', () => {
|
||||
get_dialog_with_duration(0, 0).as('dialog');
|
||||
cy.get('.frappe-control[data-fieldname=duration] input').first().click();
|
||||
cy.get('.duration-input[data-duration=days]').should('not.be.visible');
|
||||
cy.get('.duration-input[data-duration=seconds]').should('not.be.visible');
|
||||
});
|
||||
});
|
||||
|
|
@ -19,6 +19,7 @@ from frappe.email.inbox import get_email_accounts
|
|||
from frappe.social.doctype.energy_point_settings.energy_point_settings import is_energy_point_enabled
|
||||
from frappe.website.doctype.web_page_view.web_page_view import is_tracking_enabled
|
||||
from frappe.social.doctype.energy_point_log.energy_point_log import get_energy_points
|
||||
from frappe.model.base_document import get_controller
|
||||
from frappe.social.doctype.post.post import frequently_visited_links
|
||||
|
||||
def get_bootinfo():
|
||||
|
|
@ -106,6 +107,7 @@ def load_desktop_data(bootinfo):
|
|||
from frappe.desk.desktop import get_desk_sidebar_items
|
||||
bootinfo.allowed_modules = get_modules_from_all_apps_for_user()
|
||||
bootinfo.allowed_workspaces = get_desk_sidebar_items(True)
|
||||
bootinfo.module_page_map = get_controller("Desk Page").get_module_page_map()
|
||||
bootinfo.dashboards = frappe.get_all("Dashboard")
|
||||
|
||||
def get_allowed_pages(cache=False):
|
||||
|
|
|
|||
|
|
@ -43,14 +43,16 @@ def new_site(site, mariadb_root_username=None, mariadb_root_password=None, admin
|
|||
_new_site(db_name, site, mariadb_root_username=mariadb_root_username,
|
||||
mariadb_root_password=mariadb_root_password, admin_password=admin_password,
|
||||
verbose=verbose, install_apps=install_app, source_sql=source_sql, force=force,
|
||||
no_mariadb_socket=no_mariadb_socket, db_password=db_password, db_type=db_type, db_host=db_host, db_port=db_port)
|
||||
no_mariadb_socket=no_mariadb_socket, db_password=db_password, db_type=db_type, db_host=db_host,
|
||||
db_port=db_port, new_site=True)
|
||||
|
||||
if len(frappe.utils.get_sites()) == 1:
|
||||
use(site)
|
||||
|
||||
def _new_site(db_name, site, mariadb_root_username=None, mariadb_root_password=None,
|
||||
admin_password=None, verbose=False, install_apps=None, source_sql=None, force=False,
|
||||
no_mariadb_socket=False, reinstall=False, db_password=None, db_type=None, db_host=None, db_port=None):
|
||||
no_mariadb_socket=False, reinstall=False, db_password=None, db_type=None, db_host=None,
|
||||
db_port=None, new_site=False):
|
||||
"""Install a new Frappe site"""
|
||||
|
||||
if not force and os.path.exists(site):
|
||||
|
|
@ -79,7 +81,10 @@ def _new_site(db_name, site, mariadb_root_username=None, mariadb_root_password=N
|
|||
make_site_dirs()
|
||||
|
||||
installing = touch_file(get_site_path('locks', 'installing.lock'))
|
||||
atexit.register(_new_site_cleanup, site, mariadb_root_username, mariadb_root_password)
|
||||
|
||||
if new_site:
|
||||
# run cleanup only if new-site is called
|
||||
atexit.register(_new_site_cleanup, site, mariadb_root_username, mariadb_root_password)
|
||||
|
||||
install_db(root_login=mariadb_root_username, root_password=mariadb_root_password, db_name=db_name,
|
||||
admin_password=admin_password, verbose=verbose, source_sql=source_sql, force=force, reinstall=reinstall,
|
||||
|
|
@ -97,7 +102,10 @@ def _new_site(db_name, site, mariadb_root_username=None, mariadb_root_password=N
|
|||
print("*** Scheduler is", scheduler_status, "***")
|
||||
|
||||
def _new_site_cleanup(site, mariadb_root_username, mariadb_root_password):
|
||||
installing = get_site_path('locks', 'installing.lock')
|
||||
try:
|
||||
installing = get_site_path('locks', 'installing.lock')
|
||||
except AttributeError:
|
||||
installing = os.path.join(site, 'locks', 'installing.lock')
|
||||
|
||||
if installing and os.path.exists(installing):
|
||||
if mariadb_root_password:
|
||||
|
|
|
|||
|
|
@ -2,20 +2,21 @@
|
|||
# MIT License. See license.txt
|
||||
|
||||
from __future__ import unicode_literals, absolute_import
|
||||
from collections import Counter
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils import validate_email_address, get_fullname, strip_html, cstr
|
||||
from frappe.core.doctype.communication.email import (validate_email,
|
||||
notify, _notify, update_parent_mins_to_first_response)
|
||||
from frappe.utils import validate_email_address, strip_html, cstr, time_diff_in_seconds
|
||||
from frappe.core.doctype.communication.email import validate_email, notify, _notify
|
||||
from frappe.core.utils import get_parent_doc
|
||||
from frappe.utils.bot import BotReply
|
||||
from frappe.utils import parse_addr
|
||||
from frappe.core.doctype.comment.comment import update_comment_in_doc
|
||||
from email.utils import parseaddr
|
||||
from six.moves.urllib.parse import unquote
|
||||
from collections import Counter
|
||||
from frappe.utils.user import is_system_user
|
||||
from frappe.contacts.doctype.contact.contact import get_contact_name
|
||||
from frappe.automation.doctype.assignment_rule.assignment_rule import apply as apply_assignment_rule
|
||||
|
||||
exclude_from_linked_with = True
|
||||
|
||||
|
|
@ -119,7 +120,7 @@ class Communication(Document):
|
|||
update_comment_in_doc(self)
|
||||
|
||||
if self.comment_type != 'Updated':
|
||||
update_parent_mins_to_first_response(self)
|
||||
update_parent_document_on_communication(self)
|
||||
self.bot_reply()
|
||||
|
||||
def on_trash(self):
|
||||
|
|
@ -258,7 +259,12 @@ class Communication(Document):
|
|||
|
||||
# Timeline Links
|
||||
def set_timeline_links(self):
|
||||
contacts = get_contacts([self.sender, self.recipients, self.cc, self.bcc])
|
||||
contacts = []
|
||||
if (self.email_account and frappe.db.get_value("Email Account", self.email_account, "create_contact")) or \
|
||||
frappe.flags.in_test:
|
||||
|
||||
contacts = get_contacts([self.sender, self.recipients, self.cc, self.bcc])
|
||||
|
||||
for contact_name in contacts:
|
||||
self.add_link('Contact', contact_name)
|
||||
|
||||
|
|
@ -423,3 +429,39 @@ def get_email_without_link(email):
|
|||
email_host = email.split("@")[1]
|
||||
|
||||
return "{0}@{1}".format(email_id, email_host)
|
||||
|
||||
def update_parent_document_on_communication(doc):
|
||||
"""Update mins_to_first_communication of parent document based on who is replying."""
|
||||
|
||||
parent = get_parent_doc(doc)
|
||||
if not parent:
|
||||
return
|
||||
|
||||
# update parent mins_to_first_communication only if we create the Email communication
|
||||
# ignore in case of only Comment is added
|
||||
if doc.communication_type == "Comment":
|
||||
return
|
||||
|
||||
status_field = parent.meta.get_field("status")
|
||||
if status_field:
|
||||
options = (status_field.options or '').splitlines()
|
||||
|
||||
# if status has a "Replied" option, then update the status for received communication
|
||||
if ('Replied' in options) and doc.sent_or_received=="Received":
|
||||
parent.db_set("status", "Open")
|
||||
apply_assignment_rule(parent)
|
||||
else:
|
||||
# update the modified date for document
|
||||
parent.update_modified()
|
||||
|
||||
update_mins_to_first_communication(parent, doc)
|
||||
parent.run_method('notify_communication', doc)
|
||||
parent.notify_update()
|
||||
|
||||
def update_mins_to_first_communication(parent, communication):
|
||||
if parent.meta.has_field('mins_to_first_response') and not parent.get('mins_to_first_response'):
|
||||
if is_system_user(communication.sender):
|
||||
first_responded_on = communication.creation
|
||||
if parent.meta.has_field('first_responded_on') and communication.sent_or_received == "Sent":
|
||||
parent.db_set('first_responded_on', first_responded_on)
|
||||
parent.db_set('mins_to_first_response', round(time_diff_in_seconds(first_responded_on, parent.creation) / 60), 2)
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import json
|
|||
from email.utils import formataddr
|
||||
from frappe.core.utils import get_parent_doc
|
||||
from frappe.utils import (get_url, get_formatted_email, cint,
|
||||
validate_email_address, split_emails, time_diff_in_seconds, parse_addr, get_datetime)
|
||||
validate_email_address, split_emails, parse_addr, get_datetime)
|
||||
from frappe.email.email_body import get_message_id
|
||||
import frappe.email.smtp
|
||||
import time
|
||||
|
|
@ -172,33 +172,6 @@ def _notify(doc, print_html=None, print_format=None, attachments=None,
|
|||
print_letterhead=frappe.flags.print_letterhead
|
||||
)
|
||||
|
||||
def update_parent_mins_to_first_response(doc):
|
||||
"""Update mins_to_first_communication of parent document based on who is replying."""
|
||||
|
||||
parent = get_parent_doc(doc)
|
||||
if not parent:
|
||||
return
|
||||
|
||||
# update parent mins_to_first_communication only if we create the Email communication
|
||||
# ignore in case of only Comment is added
|
||||
if doc.communication_type == "Comment":
|
||||
return
|
||||
|
||||
status_field = parent.meta.get_field("status")
|
||||
if status_field:
|
||||
options = (status_field.options or '').splitlines()
|
||||
|
||||
# if status has a "Replied" option, then update the status for received communication
|
||||
if ('Replied' in options) and doc.sent_or_received=="Received":
|
||||
parent.db_set("status", "Open")
|
||||
else:
|
||||
# update the modified date for document
|
||||
parent.update_modified()
|
||||
|
||||
update_mins_to_first_communication(parent, doc)
|
||||
parent.run_method('notify_communication', doc)
|
||||
parent.notify_update()
|
||||
|
||||
def get_recipients_cc_and_bcc(doc, recipients, cc, bcc, fetched_from_email_account=False):
|
||||
doc.all_email_addresses = []
|
||||
doc.sent_email_addresses = []
|
||||
|
|
@ -499,15 +472,6 @@ def sendmail(communication_name, print_html=None, print_format=None, attachments
|
|||
traceback = frappe.log_error("frappe.core.doctype.communication.email.sendmail")
|
||||
raise
|
||||
|
||||
def update_mins_to_first_communication(parent, communication):
|
||||
if parent.meta.has_field('mins_to_first_response') and not parent.get('mins_to_first_response'):
|
||||
if frappe.db.get_all('User', filters={'email': communication.sender,
|
||||
'user_type': 'System User', 'enabled': 1}, limit=1):
|
||||
first_responded_on = communication.creation
|
||||
if parent.meta.has_field('first_responded_on') and communication.sent_or_received == "Sent":
|
||||
parent.db_set('first_responded_on', first_responded_on)
|
||||
parent.db_set('mins_to_first_response', round(time_diff_in_seconds(first_responded_on, parent.creation) / 60), 2)
|
||||
|
||||
@frappe.whitelist(allow_guest=True)
|
||||
def mark_email_as_seen(name=None):
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -202,6 +202,8 @@ class TestCommunication(unittest.TestCase):
|
|||
self.assertIn(("Note", note.name), doc_links)
|
||||
|
||||
def create_email_account():
|
||||
frappe.delete_doc_if_exists("Email Account", "_Test Comm Account 1")
|
||||
|
||||
frappe.flags.mute_emails = False
|
||||
frappe.flags.sent_mail = None
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@
|
|||
"fieldname",
|
||||
"precision",
|
||||
"length",
|
||||
"show_days",
|
||||
"show_seconds",
|
||||
"reqd",
|
||||
"search_index",
|
||||
"in_list_view",
|
||||
|
|
@ -87,7 +89,7 @@
|
|||
"label": "Type",
|
||||
"oldfieldname": "fieldtype",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "Attach\nAttach Image\nBarcode\nButton\nCheck\nCode\nColor\nColumn Break\nCurrency\nData\nDate\nDatetime\nDynamic Link\nFloat\nFold\nGeolocation\nHeading\nHTML\nHTML Editor\nImage\nInt\nLink\nLong Text\nMarkdown Editor\nPassword\nPercent\nRead Only\nRating\nSection Break\nSelect\nSmall Text\nTable\nTable MultiSelect\nText\nText Editor\nTime\nSignature",
|
||||
"options": "Attach\nAttach Image\nBarcode\nButton\nCheck\nCode\nColor\nColumn Break\nCurrency\nData\nDate\nDatetime\nDuration\nDynamic Link\nFloat\nFold\nGeolocation\nHeading\nHTML\nHTML Editor\nImage\nInt\nLink\nLong Text\nMarkdown Editor\nPassword\nPercent\nRead Only\nRating\nSection Break\nSelect\nSmall Text\nTable\nTable MultiSelect\nText\nText Editor\nTime\nSignature",
|
||||
"reqd": 1,
|
||||
"search_index": 1
|
||||
},
|
||||
|
|
@ -450,6 +452,20 @@
|
|||
"fieldname": "column_break_38",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"default": "1",
|
||||
"depends_on": "eval:doc.fieldtype === \"Duration\";",
|
||||
"fieldname": "show_days",
|
||||
"fieldtype": "Check",
|
||||
"label": "Show Days"
|
||||
},
|
||||
{
|
||||
"default": "1",
|
||||
"depends_on": "eval:doc.fieldtype === \"Duration\";",
|
||||
"fieldname": "show_seconds",
|
||||
"fieldtype": "Check",
|
||||
"label": "Show Seconds"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"depends_on": "eval:doc.fieldtype=='Section Break'",
|
||||
|
|
@ -461,7 +477,7 @@
|
|||
"idx": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2020-04-27 11:38:21.223185",
|
||||
"modified": "2020-05-15 09:06:25.224411",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Core",
|
||||
"name": "DocField",
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@
|
|||
"column_break_6",
|
||||
"fieldtype",
|
||||
"precision",
|
||||
"show_seconds",
|
||||
"show_days",
|
||||
"options",
|
||||
"fetch_from",
|
||||
"fetch_if_empty",
|
||||
|
|
@ -56,368 +58,386 @@
|
|||
],
|
||||
"fields": [
|
||||
{
|
||||
"bold": 1,
|
||||
"fieldname": "dt",
|
||||
"fieldtype": "Link",
|
||||
"in_filter": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Document",
|
||||
"oldfieldname": "dt",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "DocType",
|
||||
"reqd": 1,
|
||||
"search_index": 1
|
||||
"bold": 1,
|
||||
"fieldname": "dt",
|
||||
"fieldtype": "Link",
|
||||
"in_filter": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Document",
|
||||
"oldfieldname": "dt",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "DocType",
|
||||
"reqd": 1,
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"bold": 1,
|
||||
"fieldname": "label",
|
||||
"fieldtype": "Data",
|
||||
"in_filter": 1,
|
||||
"label": "Label",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "label",
|
||||
"oldfieldtype": "Data"
|
||||
"bold": 1,
|
||||
"fieldname": "label",
|
||||
"fieldtype": "Data",
|
||||
"in_filter": 1,
|
||||
"label": "Label",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "label",
|
||||
"oldfieldtype": "Data"
|
||||
},
|
||||
{
|
||||
"fieldname": "label_help",
|
||||
"fieldtype": "HTML",
|
||||
"label": "Label Help",
|
||||
"oldfieldtype": "HTML"
|
||||
"fieldname": "label_help",
|
||||
"fieldtype": "HTML",
|
||||
"label": "Label Help",
|
||||
"oldfieldtype": "HTML"
|
||||
},
|
||||
{
|
||||
"fieldname": "fieldname",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Fieldname",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "fieldname",
|
||||
"oldfieldtype": "Data",
|
||||
"read_only": 1
|
||||
"fieldname": "fieldname",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Fieldname",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "fieldname",
|
||||
"oldfieldtype": "Data",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"description": "Select the label after which you want to insert new field.",
|
||||
"fieldname": "insert_after",
|
||||
"fieldtype": "Select",
|
||||
"label": "Insert After",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "insert_after",
|
||||
"oldfieldtype": "Select"
|
||||
"description": "Select the label after which you want to insert new field.",
|
||||
"fieldname": "insert_after",
|
||||
"fieldtype": "Select",
|
||||
"label": "Insert After",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "insert_after",
|
||||
"oldfieldtype": "Select"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_6",
|
||||
"fieldtype": "Column Break"
|
||||
"fieldname": "column_break_6",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"bold": 1,
|
||||
"default": "Data",
|
||||
"fieldname": "fieldtype",
|
||||
"fieldtype": "Select",
|
||||
"in_filter": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Field Type",
|
||||
"oldfieldname": "fieldtype",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "Attach\nAttach Image\nBarcode\nButton\nCheck\nCode\nColor\nColumn Break\nCurrency\nData\nDate\nDatetime\nDynamic Link\nFloat\nGeolocation\nHTML\nImage\nInt\nLink\nLong Text\nMarkdown Editor\nPassword\nPercent\nRating\nRead Only\nSection Break\nSelect\nSmall Text\nTable\nTable MultiSelect\nText\nText Editor\nTime\nSignature",
|
||||
"reqd": 1
|
||||
"bold": 1,
|
||||
"default": "Data",
|
||||
"fieldname": "fieldtype",
|
||||
"fieldtype": "Select",
|
||||
"in_filter": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Field Type",
|
||||
"oldfieldname": "fieldtype",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "Attach\nAttach Image\nBarcode\nButton\nCheck\nCode\nColor\nColumn Break\nCurrency\nData\nDate\nDatetime\nDuration\nDynamic Link\nFloat\nGeolocation\nHTML\nImage\nInt\nLink\nLong Text\nMarkdown Editor\nPassword\nPercent\nRating\nRead Only\nSection Break\nSelect\nSmall Text\nTable\nTable MultiSelect\nText\nText Editor\nTime\nSignature",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:in_list([\"Float\", \"Currency\", \"Percent\"], doc.fieldtype)",
|
||||
"description": "Set non-standard precision for a Float or Currency field",
|
||||
"fieldname": "precision",
|
||||
"fieldtype": "Select",
|
||||
"label": "Precision",
|
||||
"options": "\n0\n1\n2\n3\n4\n5\n6\n7\n8\n9"
|
||||
"depends_on": "eval:in_list([\"Float\", \"Currency\", \"Percent\"], doc.fieldtype)",
|
||||
"description": "Set non-standard precision for a Float or Currency field",
|
||||
"fieldname": "precision",
|
||||
"fieldtype": "Select",
|
||||
"label": "Precision",
|
||||
"options": "\n0\n1\n2\n3\n4\n5\n6\n7\n8\n9"
|
||||
},
|
||||
{
|
||||
"fieldname": "options",
|
||||
"fieldtype": "Small Text",
|
||||
"in_list_view": 1,
|
||||
"label": "Options",
|
||||
"oldfieldname": "options",
|
||||
"oldfieldtype": "Text"
|
||||
"fieldname": "options",
|
||||
"fieldtype": "Small Text",
|
||||
"in_list_view": 1,
|
||||
"label": "Options",
|
||||
"oldfieldname": "options",
|
||||
"oldfieldtype": "Text"
|
||||
},
|
||||
{
|
||||
"fieldname": "fetch_from",
|
||||
"fieldtype": "Small Text",
|
||||
"label": "Fetch From"
|
||||
"fieldname": "fetch_from",
|
||||
"fieldtype": "Small Text",
|
||||
"label": "Fetch From"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"description": "If checked, this field will be not overwritten based on Fetch From if a value already exists.",
|
||||
"fieldname": "fetch_if_empty",
|
||||
"fieldtype": "Check",
|
||||
"label": "Fetch If Empty"
|
||||
"default": "0",
|
||||
"description": "If checked, this field will be not overwritten based on Fetch From if a value already exists.",
|
||||
"fieldname": "fetch_if_empty",
|
||||
"fieldtype": "Check",
|
||||
"label": "Fetch If Empty"
|
||||
},
|
||||
{
|
||||
"fieldname": "options_help",
|
||||
"fieldtype": "HTML",
|
||||
"label": "Options Help",
|
||||
"oldfieldtype": "HTML"
|
||||
"fieldname": "options_help",
|
||||
"fieldtype": "HTML",
|
||||
"label": "Options Help",
|
||||
"oldfieldtype": "HTML"
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break_11",
|
||||
"fieldtype": "Section Break"
|
||||
"fieldname": "section_break_11",
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"depends_on": "eval:doc.fieldtype==\"Section Break\"",
|
||||
"fieldname": "collapsible",
|
||||
"fieldtype": "Check",
|
||||
"label": "Collapsible"
|
||||
"default": "0",
|
||||
"depends_on": "eval:doc.fieldtype==\"Section Break\"",
|
||||
"fieldname": "collapsible",
|
||||
"fieldtype": "Check",
|
||||
"label": "Collapsible"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.fieldtype==\"Section Break\"",
|
||||
"fieldname": "collapsible_depends_on",
|
||||
"fieldtype": "Code",
|
||||
"label": "Collapsible Depends On"
|
||||
"depends_on": "eval:doc.fieldtype==\"Section Break\"",
|
||||
"fieldname": "collapsible_depends_on",
|
||||
"fieldtype": "Code",
|
||||
"label": "Collapsible Depends On"
|
||||
},
|
||||
{
|
||||
"fieldname": "default",
|
||||
"fieldtype": "Text",
|
||||
"label": "Default Value",
|
||||
"oldfieldname": "default",
|
||||
"oldfieldtype": "Text"
|
||||
"fieldname": "default",
|
||||
"fieldtype": "Text",
|
||||
"label": "Default Value",
|
||||
"oldfieldname": "default",
|
||||
"oldfieldtype": "Text"
|
||||
},
|
||||
{
|
||||
"fieldname": "depends_on",
|
||||
"fieldtype": "Code",
|
||||
"label": "Depends On",
|
||||
"length": 255
|
||||
"fieldname": "depends_on",
|
||||
"fieldtype": "Code",
|
||||
"label": "Depends On",
|
||||
"length": 255
|
||||
},
|
||||
{
|
||||
"fieldname": "description",
|
||||
"fieldtype": "Text",
|
||||
"label": "Field Description",
|
||||
"oldfieldname": "description",
|
||||
"oldfieldtype": "Text",
|
||||
"print_width": "300px",
|
||||
"width": "300px"
|
||||
"fieldname": "description",
|
||||
"fieldtype": "Text",
|
||||
"label": "Field Description",
|
||||
"oldfieldname": "description",
|
||||
"oldfieldtype": "Text",
|
||||
"print_width": "300px",
|
||||
"width": "300px"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "permlevel",
|
||||
"fieldtype": "Int",
|
||||
"label": "Permission Level",
|
||||
"oldfieldname": "permlevel",
|
||||
"oldfieldtype": "Int"
|
||||
"default": "0",
|
||||
"fieldname": "permlevel",
|
||||
"fieldtype": "Int",
|
||||
"label": "Permission Level",
|
||||
"oldfieldname": "permlevel",
|
||||
"oldfieldtype": "Int"
|
||||
},
|
||||
{
|
||||
"fieldname": "width",
|
||||
"fieldtype": "Data",
|
||||
"label": "Width",
|
||||
"oldfieldname": "width",
|
||||
"oldfieldtype": "Data"
|
||||
"fieldname": "width",
|
||||
"fieldtype": "Data",
|
||||
"label": "Width",
|
||||
"oldfieldname": "width",
|
||||
"oldfieldtype": "Data"
|
||||
},
|
||||
{
|
||||
"description": "Number of columns for a field in a List View or a Grid (Total Columns should be less than 11)",
|
||||
"fieldname": "columns",
|
||||
"fieldtype": "Int",
|
||||
"label": "Columns"
|
||||
"description": "Number of columns for a field in a List View or a Grid (Total Columns should be less than 11)",
|
||||
"fieldname": "columns",
|
||||
"fieldtype": "Int",
|
||||
"label": "Columns"
|
||||
},
|
||||
{
|
||||
"fieldname": "properties",
|
||||
"fieldtype": "Column Break",
|
||||
"oldfieldtype": "Column Break",
|
||||
"print_width": "50%",
|
||||
"width": "50%"
|
||||
"fieldname": "properties",
|
||||
"fieldtype": "Column Break",
|
||||
"oldfieldtype": "Column Break",
|
||||
"print_width": "50%",
|
||||
"width": "50%"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "reqd",
|
||||
"fieldtype": "Check",
|
||||
"in_list_view": 1,
|
||||
"label": "Is Mandatory Field",
|
||||
"oldfieldname": "reqd",
|
||||
"oldfieldtype": "Check"
|
||||
"default": "0",
|
||||
"fieldname": "reqd",
|
||||
"fieldtype": "Check",
|
||||
"in_list_view": 1,
|
||||
"label": "Is Mandatory Field",
|
||||
"oldfieldname": "reqd",
|
||||
"oldfieldtype": "Check"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "unique",
|
||||
"fieldtype": "Check",
|
||||
"label": "Unique"
|
||||
"default": "0",
|
||||
"fieldname": "unique",
|
||||
"fieldtype": "Check",
|
||||
"label": "Unique"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "read_only",
|
||||
"fieldtype": "Check",
|
||||
"label": "Read Only"
|
||||
"default": "0",
|
||||
"fieldname": "read_only",
|
||||
"fieldtype": "Check",
|
||||
"label": "Read Only"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"depends_on": "eval:doc.fieldtype===\"Link\"",
|
||||
"fieldname": "ignore_user_permissions",
|
||||
"fieldtype": "Check",
|
||||
"label": "Ignore User Permissions"
|
||||
"default": "0",
|
||||
"depends_on": "eval:doc.fieldtype===\"Link\"",
|
||||
"fieldname": "ignore_user_permissions",
|
||||
"fieldtype": "Check",
|
||||
"label": "Ignore User Permissions"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "hidden",
|
||||
"fieldtype": "Check",
|
||||
"label": "Hidden"
|
||||
"default": "0",
|
||||
"fieldname": "hidden",
|
||||
"fieldtype": "Check",
|
||||
"label": "Hidden"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "print_hide",
|
||||
"fieldtype": "Check",
|
||||
"label": "Print Hide",
|
||||
"oldfieldname": "print_hide",
|
||||
"oldfieldtype": "Check"
|
||||
"default": "0",
|
||||
"fieldname": "print_hide",
|
||||
"fieldtype": "Check",
|
||||
"label": "Print Hide",
|
||||
"oldfieldname": "print_hide",
|
||||
"oldfieldtype": "Check"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"depends_on": "eval:[\"Int\", \"Float\", \"Currency\", \"Percent\"].indexOf(doc.fieldtype)!==-1",
|
||||
"fieldname": "print_hide_if_no_value",
|
||||
"fieldtype": "Check",
|
||||
"label": "Print Hide If No Value"
|
||||
"default": "0",
|
||||
"depends_on": "eval:[\"Int\", \"Float\", \"Currency\", \"Percent\"].indexOf(doc.fieldtype)!==-1",
|
||||
"fieldname": "print_hide_if_no_value",
|
||||
"fieldtype": "Check",
|
||||
"label": "Print Hide If No Value"
|
||||
},
|
||||
{
|
||||
"fieldname": "print_width",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
"label": "Print Width",
|
||||
"no_copy": 1,
|
||||
"print_hide": 1
|
||||
"fieldname": "print_width",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
"label": "Print Width",
|
||||
"no_copy": 1,
|
||||
"print_hide": 1
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "no_copy",
|
||||
"fieldtype": "Check",
|
||||
"label": "No Copy",
|
||||
"oldfieldname": "no_copy",
|
||||
"oldfieldtype": "Check"
|
||||
"default": "0",
|
||||
"fieldname": "no_copy",
|
||||
"fieldtype": "Check",
|
||||
"label": "No Copy",
|
||||
"oldfieldname": "no_copy",
|
||||
"oldfieldtype": "Check"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "allow_on_submit",
|
||||
"fieldtype": "Check",
|
||||
"label": "Allow on Submit",
|
||||
"oldfieldname": "allow_on_submit",
|
||||
"oldfieldtype": "Check"
|
||||
"default": "0",
|
||||
"fieldname": "allow_on_submit",
|
||||
"fieldtype": "Check",
|
||||
"label": "Allow on Submit",
|
||||
"oldfieldname": "allow_on_submit",
|
||||
"oldfieldtype": "Check"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "in_list_view",
|
||||
"fieldtype": "Check",
|
||||
"label": "In List View"
|
||||
"default": "0",
|
||||
"fieldname": "in_list_view",
|
||||
"fieldtype": "Check",
|
||||
"label": "In List View"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "in_standard_filter",
|
||||
"fieldtype": "Check",
|
||||
"label": "In Standard Filter"
|
||||
"default": "0",
|
||||
"fieldname": "in_standard_filter",
|
||||
"fieldtype": "Check",
|
||||
"label": "In Standard Filter"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"depends_on": "eval:([\"Data\", \"Select\", \"Table\", \"Text\", \"Text Editor\", \"Link\", \"Small Text\", \"Long Text\", \"Read Only\", \"Heading\", \"Dynamic Link\"].indexOf(doc.fieldtype) !== -1)",
|
||||
"fieldname": "in_global_search",
|
||||
"fieldtype": "Check",
|
||||
"label": "In Global Search"
|
||||
"default": "0",
|
||||
"depends_on": "eval:([\"Data\", \"Select\", \"Table\", \"Text\", \"Text Editor\", \"Link\", \"Small Text\", \"Long Text\", \"Read Only\", \"Heading\", \"Dynamic Link\"].indexOf(doc.fieldtype) !== -1)",
|
||||
"fieldname": "in_global_search",
|
||||
"fieldtype": "Check",
|
||||
"label": "In Global Search"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "bold",
|
||||
"fieldtype": "Check",
|
||||
"label": "Bold"
|
||||
"default": "0",
|
||||
"fieldname": "bold",
|
||||
"fieldtype": "Check",
|
||||
"label": "Bold"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "report_hide",
|
||||
"fieldtype": "Check",
|
||||
"label": "Report Hide",
|
||||
"oldfieldname": "report_hide",
|
||||
"oldfieldtype": "Check"
|
||||
"default": "0",
|
||||
"fieldname": "report_hide",
|
||||
"fieldtype": "Check",
|
||||
"label": "Report Hide",
|
||||
"oldfieldname": "report_hide",
|
||||
"oldfieldtype": "Check"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "search_index",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 1,
|
||||
"label": "Index",
|
||||
"no_copy": 1,
|
||||
"print_hide": 1
|
||||
"default": "0",
|
||||
"fieldname": "search_index",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 1,
|
||||
"label": "Index",
|
||||
"no_copy": 1,
|
||||
"print_hide": 1
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"description": "Don't HTML Encode HTML tags like <script> or just characters like < or >, as they could be intentionally used in this field",
|
||||
"fieldname": "ignore_xss_filter",
|
||||
"fieldtype": "Check",
|
||||
"label": "Ignore XSS Filter"
|
||||
"default": "0",
|
||||
"description": "Don't HTML Encode HTML tags like <script> or just characters like < or >, as they could be intentionally used in this field",
|
||||
"fieldname": "ignore_xss_filter",
|
||||
"fieldtype": "Check",
|
||||
"label": "Ignore XSS Filter"
|
||||
},
|
||||
{
|
||||
"default": "1",
|
||||
"depends_on": "eval:['Data', 'Select', 'Text', 'Small Text', 'Text Editor'].includes(doc.fieldtype)",
|
||||
"fieldname": "translatable",
|
||||
"fieldtype": "Check",
|
||||
"label": "Translatable"
|
||||
"default": "1",
|
||||
"depends_on": "eval:['Data', 'Select', 'Text', 'Small Text', 'Text Editor'].includes(doc.fieldtype)",
|
||||
"fieldname": "translatable",
|
||||
"fieldtype": "Check",
|
||||
"label": "Translatable"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:in_list(['Data', 'Link', 'Dynamic Link', 'Password', 'Select', 'Read Only', 'Attach', 'Attach Image', 'Int'], doc.fieldtype)",
|
||||
"fieldname": "length",
|
||||
"fieldtype": "Int",
|
||||
"label": "Length"
|
||||
"depends_on": "eval:in_list(['Data', 'Link', 'Dynamic Link', 'Password', 'Select', 'Read Only', 'Attach', 'Attach Image', 'Int'], doc.fieldtype)",
|
||||
"fieldname": "length",
|
||||
"fieldtype": "Int",
|
||||
"label": "Length"
|
||||
},
|
||||
{
|
||||
"fieldname": "mandatory_depends_on",
|
||||
"fieldtype": "Code",
|
||||
"label": "Mandatory Depends On",
|
||||
"length": 255
|
||||
"fieldname": "mandatory_depends_on",
|
||||
"fieldtype": "Code",
|
||||
"label": "Mandatory Depends On",
|
||||
"length": 255
|
||||
},
|
||||
{
|
||||
"fieldname": "read_only_depends_on",
|
||||
"fieldtype": "Code",
|
||||
"label": "Read Only Depends On",
|
||||
"length": 255
|
||||
"fieldname": "read_only_depends_on",
|
||||
"fieldtype": "Code",
|
||||
"label": "Read Only Depends On",
|
||||
"length": 255
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "allow_in_quick_entry",
|
||||
"fieldtype": "Check",
|
||||
"label": "Allow in Quick Entry"
|
||||
"default": "0",
|
||||
"fieldname": "allow_in_quick_entry",
|
||||
"fieldtype": "Check",
|
||||
"label": "Allow in Quick Entry"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "in_preview",
|
||||
"fieldtype": "Check",
|
||||
"label": "In Preview"
|
||||
"default": "0",
|
||||
"fieldname": "in_preview",
|
||||
"fieldtype": "Check",
|
||||
"label": "In Preview"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"depends_on": "eval:doc.fieldtype=='Section Break'",
|
||||
"fieldname": "hide_border",
|
||||
"fieldtype": "Check",
|
||||
"label": "Hide Border"
|
||||
"default": "1",
|
||||
"depends_on": "eval:doc.fieldtype === \"Duration\";",
|
||||
"fieldname": "show_seconds",
|
||||
"fieldtype": "Check",
|
||||
"label": "Show Seconds",
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"default": "1",
|
||||
"depends_on": "eval:doc.fieldtype === \"Duration\";",
|
||||
"fieldname": "show_days",
|
||||
"fieldtype": "Check",
|
||||
"label": "Show Days",
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"depends_on": "eval:doc.fieldtype=='Section Break'",
|
||||
"fieldname": "hide_border",
|
||||
"fieldtype": "Check",
|
||||
"label": "Hide Border"
|
||||
}
|
||||
],
|
||||
"icon": "fa fa-glass",
|
||||
"idx": 1,
|
||||
"links": [],
|
||||
"modified": "2020-04-27 11:40:48.325481",
|
||||
"modified": "2020-05-15 23:43:00.123572",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Custom",
|
||||
"name": "Custom Field",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Administrator",
|
||||
"share": 1,
|
||||
"write": 1
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Administrator",
|
||||
"share": 1,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"share": 1,
|
||||
"write": 1
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"share": 1,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"search_fields": "dt,label,fieldtype,options",
|
||||
|
|
|
|||
|
|
@ -46,6 +46,9 @@ class CustomField(Document):
|
|||
if not self.fieldname:
|
||||
frappe.throw(_("Fieldname not set for Custom Field"))
|
||||
|
||||
if self.fieldname in fieldnames:
|
||||
frappe.throw(_("A field with the name '{}' already exists in doctype {}.").format(self.fieldname, self.dt))
|
||||
|
||||
if self.get('translatable', 0) and not supports_translation(self.fieldtype):
|
||||
self.translatable = 0
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@
|
|||
"label",
|
||||
"fieldtype",
|
||||
"fieldname",
|
||||
"show_seconds",
|
||||
"show_days",
|
||||
"reqd",
|
||||
"unique",
|
||||
"in_list_view",
|
||||
|
|
@ -58,350 +60,368 @@
|
|||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "label_and_type",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Label and Type"
|
||||
"fieldname": "label_and_type",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Label and Type"
|
||||
},
|
||||
{
|
||||
"fieldname": "label",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Label",
|
||||
"oldfieldname": "label",
|
||||
"oldfieldtype": "Data",
|
||||
"search_index": 1
|
||||
"fieldname": "label",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Label",
|
||||
"oldfieldname": "label",
|
||||
"oldfieldtype": "Data",
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"default": "Data",
|
||||
"fieldname": "fieldtype",
|
||||
"fieldtype": "Select",
|
||||
"in_list_view": 1,
|
||||
"label": "Type",
|
||||
"oldfieldname": "fieldtype",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "Attach\nAttach Image\nBarcode\nButton\nCheck\nCode\nColor\nColumn Break\nCurrency\nData\nDate\nDatetime\nDynamic Link\nFloat\nFold\nGeolocation\nHeading\nHTML\nHTML Editor\nImage\nInt\nLink\nLong Text\nMarkdown Editor\nPassword\nPercent\nRating\nRead Only\nSection Break\nSelect\nSignature\nSmall Text\nTable\nTable MultiSelect\nText\nText Editor\nTime",
|
||||
"reqd": 1,
|
||||
"search_index": 1
|
||||
"default": "Data",
|
||||
"fieldname": "fieldtype",
|
||||
"fieldtype": "Select",
|
||||
"in_list_view": 1,
|
||||
"label": "Type",
|
||||
"oldfieldname": "fieldtype",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "Attach\nAttach Image\nBarcode\nButton\nCheck\nCode\nColor\nColumn Break\nCurrency\nData\nDate\nDatetime\nDuration\nDynamic Link\nFloat\nFold\nGeolocation\nHeading\nHTML\nHTML Editor\nImage\nInt\nLink\nLong Text\nMarkdown Editor\nPassword\nPercent\nRating\nRead Only\nSection Break\nSelect\nSignature\nSmall Text\nTable\nTable MultiSelect\nText\nText Editor\nTime",
|
||||
"reqd": 1,
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "fieldname",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Name",
|
||||
"oldfieldname": "fieldname",
|
||||
"oldfieldtype": "Data",
|
||||
"read_only": 1,
|
||||
"search_index": 1
|
||||
"fieldname": "fieldname",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Name",
|
||||
"oldfieldname": "fieldname",
|
||||
"oldfieldtype": "Data",
|
||||
"read_only": 1,
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"depends_on": "eval:!in_list([\"Section Break\", \"Column Break\", \"Button\", \"HTML\"], doc.fieldtype)",
|
||||
"fieldname": "reqd",
|
||||
"fieldtype": "Check",
|
||||
"label": "Mandatory",
|
||||
"oldfieldname": "reqd",
|
||||
"oldfieldtype": "Check",
|
||||
"print_width": "50px",
|
||||
"width": "50px"
|
||||
"default": "0",
|
||||
"depends_on": "eval:!in_list([\"Section Break\", \"Column Break\", \"Button\", \"HTML\"], doc.fieldtype)",
|
||||
"fieldname": "reqd",
|
||||
"fieldtype": "Check",
|
||||
"label": "Mandatory",
|
||||
"oldfieldname": "reqd",
|
||||
"oldfieldtype": "Check",
|
||||
"print_width": "50px",
|
||||
"width": "50px"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "unique",
|
||||
"fieldtype": "Check",
|
||||
"label": "Unique"
|
||||
"default": "0",
|
||||
"fieldname": "unique",
|
||||
"fieldtype": "Check",
|
||||
"label": "Unique"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "in_list_view",
|
||||
"fieldtype": "Check",
|
||||
"label": "In List View"
|
||||
"default": "0",
|
||||
"fieldname": "in_list_view",
|
||||
"fieldtype": "Check",
|
||||
"label": "In List View"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "in_standard_filter",
|
||||
"fieldtype": "Check",
|
||||
"label": "In Standard Filter"
|
||||
"default": "0",
|
||||
"fieldname": "in_standard_filter",
|
||||
"fieldtype": "Check",
|
||||
"label": "In Standard Filter"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"depends_on": "eval:([\"Data\", \"Select\", \"Table\", \"Text\", \"Text Editor\", \"Link\", \"Small Text\", \"Long Text\", \"Read Only\", \"Heading\", \"Dynamic Link\"].indexOf(doc.fieldtype) !== -1)",
|
||||
"fieldname": "in_global_search",
|
||||
"fieldtype": "Check",
|
||||
"label": "In Global Search"
|
||||
"default": "0",
|
||||
"depends_on": "eval:([\"Data\", \"Select\", \"Table\", \"Text\", \"Text Editor\", \"Link\", \"Small Text\", \"Long Text\", \"Read Only\", \"Heading\", \"Dynamic Link\"].indexOf(doc.fieldtype) !== -1)",
|
||||
"fieldname": "in_global_search",
|
||||
"fieldtype": "Check",
|
||||
"label": "In Global Search"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "bold",
|
||||
"fieldtype": "Check",
|
||||
"label": "Bold"
|
||||
"default": "0",
|
||||
"fieldname": "bold",
|
||||
"fieldtype": "Check",
|
||||
"label": "Bold"
|
||||
},
|
||||
{
|
||||
"default": "1",
|
||||
"depends_on": "eval:['Data', 'Select', 'Text', 'Small Text', 'Text Editor'].includes(doc.fieldtype)",
|
||||
"fieldname": "translatable",
|
||||
"fieldtype": "Check",
|
||||
"label": "Translatable"
|
||||
"default": "1",
|
||||
"depends_on": "eval:['Data', 'Select', 'Text', 'Small Text', 'Text Editor'].includes(doc.fieldtype)",
|
||||
"fieldname": "translatable",
|
||||
"fieldtype": "Check",
|
||||
"label": "Translatable"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_7",
|
||||
"fieldtype": "Column Break"
|
||||
"fieldname": "column_break_7",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:in_list([\"Float\", \"Currency\", \"Percent\"], doc.fieldtype)",
|
||||
"description": "Set non-standard precision for a Float or Currency field",
|
||||
"fieldname": "precision",
|
||||
"fieldtype": "Select",
|
||||
"label": "Precision",
|
||||
"options": "\n0\n1\n2\n3\n4\n5\n6\n7\n8\n9"
|
||||
"depends_on": "eval:in_list([\"Float\", \"Currency\", \"Percent\"], doc.fieldtype)",
|
||||
"description": "Set non-standard precision for a Float or Currency field",
|
||||
"fieldname": "precision",
|
||||
"fieldtype": "Select",
|
||||
"label": "Precision",
|
||||
"options": "\n0\n1\n2\n3\n4\n5\n6\n7\n8\n9"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:in_list(['Data', 'Link', 'Dynamic Link', 'Password', 'Select', 'Read Only', 'Attach', 'Attach Image'], doc.fieldtype)",
|
||||
"fieldname": "length",
|
||||
"fieldtype": "Int",
|
||||
"label": "Length"
|
||||
"depends_on": "eval:in_list(['Data', 'Link', 'Dynamic Link', 'Password', 'Select', 'Read Only', 'Attach', 'Attach Image'], doc.fieldtype)",
|
||||
"fieldname": "length",
|
||||
"fieldtype": "Int",
|
||||
"label": "Length"
|
||||
},
|
||||
{
|
||||
"description": "For Links, enter the DocType as range.\nFor Select, enter list of Options, each on a new line.",
|
||||
"fieldname": "options",
|
||||
"fieldtype": "Small Text",
|
||||
"in_list_view": 1,
|
||||
"label": "Options",
|
||||
"oldfieldname": "options",
|
||||
"oldfieldtype": "Text"
|
||||
"description": "For Links, enter the DocType as range.\nFor Select, enter list of Options, each on a new line.",
|
||||
"fieldname": "options",
|
||||
"fieldtype": "Small Text",
|
||||
"in_list_view": 1,
|
||||
"label": "Options",
|
||||
"oldfieldname": "options",
|
||||
"oldfieldtype": "Text"
|
||||
},
|
||||
{
|
||||
"fieldname": "fetch_from",
|
||||
"fieldtype": "Small Text",
|
||||
"label": "Fetch From"
|
||||
"fieldname": "fetch_from",
|
||||
"fieldtype": "Small Text",
|
||||
"label": "Fetch From"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"description": "If checked, this field will be not overwritten based on Fetch From if a value already exists.",
|
||||
"fieldname": "fetch_if_empty",
|
||||
"fieldtype": "Check",
|
||||
"label": "Fetch If Empty"
|
||||
"default": "0",
|
||||
"description": "If checked, this field will be not overwritten based on Fetch From if a value already exists.",
|
||||
"fieldname": "fetch_if_empty",
|
||||
"fieldtype": "Check",
|
||||
"label": "Fetch If Empty"
|
||||
},
|
||||
{
|
||||
"fieldname": "permissions",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Permissions"
|
||||
"fieldname": "permissions",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Permissions"
|
||||
},
|
||||
{
|
||||
"description": "This field will appear only if the fieldname defined here has value OR the rules are true (examples): \nmyfield\neval:doc.myfield=='My Value'\neval:doc.age>18",
|
||||
"fieldname": "depends_on",
|
||||
"fieldtype": "Code",
|
||||
"label": "Depends On",
|
||||
"oldfieldname": "depends_on",
|
||||
"oldfieldtype": "Data",
|
||||
"options": "JS"
|
||||
"description": "This field will appear only if the fieldname defined here has value OR the rules are true (examples): \nmyfield\neval:doc.myfield=='My Value'\neval:doc.age>18",
|
||||
"fieldname": "depends_on",
|
||||
"fieldtype": "Code",
|
||||
"label": "Depends On",
|
||||
"oldfieldname": "depends_on",
|
||||
"oldfieldtype": "Data",
|
||||
"options": "JS"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "permlevel",
|
||||
"fieldtype": "Int",
|
||||
"in_list_view": 1,
|
||||
"label": "Perm Level",
|
||||
"oldfieldname": "permlevel",
|
||||
"oldfieldtype": "Int"
|
||||
"default": "0",
|
||||
"fieldname": "permlevel",
|
||||
"fieldtype": "Int",
|
||||
"in_list_view": 1,
|
||||
"label": "Perm Level",
|
||||
"oldfieldname": "permlevel",
|
||||
"oldfieldtype": "Int"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "hidden",
|
||||
"fieldtype": "Check",
|
||||
"label": "Hidden",
|
||||
"oldfieldname": "hidden",
|
||||
"oldfieldtype": "Check",
|
||||
"print_width": "50px",
|
||||
"width": "50px"
|
||||
"default": "0",
|
||||
"fieldname": "hidden",
|
||||
"fieldtype": "Check",
|
||||
"label": "Hidden",
|
||||
"oldfieldname": "hidden",
|
||||
"oldfieldtype": "Check",
|
||||
"print_width": "50px",
|
||||
"width": "50px"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "read_only",
|
||||
"fieldtype": "Check",
|
||||
"label": "Read Only"
|
||||
"default": "0",
|
||||
"fieldname": "read_only",
|
||||
"fieldtype": "Check",
|
||||
"label": "Read Only"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"depends_on": "eval:doc.fieldtype==\"Section Break\"",
|
||||
"fieldname": "collapsible",
|
||||
"fieldtype": "Check",
|
||||
"label": "Collapsible"
|
||||
"default": "0",
|
||||
"depends_on": "eval:doc.fieldtype==\"Section Break\"",
|
||||
"fieldname": "collapsible",
|
||||
"fieldtype": "Check",
|
||||
"label": "Collapsible"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"depends_on": "eval: doc.fieldtype == \"Table\"",
|
||||
"fieldname": "allow_bulk_edit",
|
||||
"fieldtype": "Check",
|
||||
"label": "Allow Bulk Edit"
|
||||
"default": "0",
|
||||
"depends_on": "eval: doc.fieldtype == \"Table\"",
|
||||
"fieldname": "allow_bulk_edit",
|
||||
"fieldtype": "Check",
|
||||
"label": "Allow Bulk Edit"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.fieldtype==\"Section Break\"",
|
||||
"fieldname": "collapsible_depends_on",
|
||||
"fieldtype": "Code",
|
||||
"label": "Collapsible Depends On",
|
||||
"options": "JS"
|
||||
"depends_on": "eval:doc.fieldtype==\"Section Break\"",
|
||||
"fieldname": "collapsible_depends_on",
|
||||
"fieldtype": "Code",
|
||||
"label": "Collapsible Depends On",
|
||||
"options": "JS"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_14",
|
||||
"fieldtype": "Column Break"
|
||||
"fieldname": "column_break_14",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "ignore_user_permissions",
|
||||
"fieldtype": "Check",
|
||||
"label": "Ignore User Permissions"
|
||||
"default": "0",
|
||||
"fieldname": "ignore_user_permissions",
|
||||
"fieldtype": "Check",
|
||||
"label": "Ignore User Permissions"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "allow_on_submit",
|
||||
"fieldtype": "Check",
|
||||
"label": "Allow on Submit",
|
||||
"oldfieldname": "allow_on_submit",
|
||||
"oldfieldtype": "Check"
|
||||
"default": "0",
|
||||
"fieldname": "allow_on_submit",
|
||||
"fieldtype": "Check",
|
||||
"label": "Allow on Submit",
|
||||
"oldfieldname": "allow_on_submit",
|
||||
"oldfieldtype": "Check"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "report_hide",
|
||||
"fieldtype": "Check",
|
||||
"label": "Report Hide",
|
||||
"oldfieldname": "report_hide",
|
||||
"oldfieldtype": "Check"
|
||||
"default": "0",
|
||||
"fieldname": "report_hide",
|
||||
"fieldtype": "Check",
|
||||
"label": "Report Hide",
|
||||
"oldfieldname": "report_hide",
|
||||
"oldfieldtype": "Check"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"depends_on": "eval:(doc.fieldtype == 'Link')",
|
||||
"fieldname": "remember_last_selected_value",
|
||||
"fieldtype": "Check",
|
||||
"label": "Remember Last Selected Value"
|
||||
"default": "0",
|
||||
"depends_on": "eval:(doc.fieldtype == 'Link')",
|
||||
"fieldname": "remember_last_selected_value",
|
||||
"fieldtype": "Check",
|
||||
"label": "Remember Last Selected Value"
|
||||
},
|
||||
{
|
||||
"fieldname": "display",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Display"
|
||||
"fieldname": "display",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Display"
|
||||
},
|
||||
{
|
||||
"fieldname": "default",
|
||||
"fieldtype": "Text",
|
||||
"label": "Default",
|
||||
"oldfieldname": "default",
|
||||
"oldfieldtype": "Text"
|
||||
"fieldname": "default",
|
||||
"fieldtype": "Text",
|
||||
"label": "Default",
|
||||
"oldfieldname": "default",
|
||||
"oldfieldtype": "Text"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "in_filter",
|
||||
"fieldtype": "Check",
|
||||
"label": "In Filter",
|
||||
"oldfieldname": "in_filter",
|
||||
"oldfieldtype": "Check",
|
||||
"print_width": "50px",
|
||||
"width": "50px"
|
||||
"default": "0",
|
||||
"fieldname": "in_filter",
|
||||
"fieldtype": "Check",
|
||||
"label": "In Filter",
|
||||
"oldfieldname": "in_filter",
|
||||
"oldfieldtype": "Check",
|
||||
"print_width": "50px",
|
||||
"width": "50px"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_21",
|
||||
"fieldtype": "Column Break"
|
||||
"fieldname": "column_break_21",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "description",
|
||||
"fieldtype": "Text",
|
||||
"label": "Description",
|
||||
"oldfieldname": "description",
|
||||
"oldfieldtype": "Text",
|
||||
"print_width": "300px",
|
||||
"width": "300px"
|
||||
"fieldname": "description",
|
||||
"fieldtype": "Text",
|
||||
"label": "Description",
|
||||
"oldfieldname": "description",
|
||||
"oldfieldtype": "Text",
|
||||
"print_width": "300px",
|
||||
"width": "300px"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "print_hide",
|
||||
"fieldtype": "Check",
|
||||
"label": "Print Hide",
|
||||
"oldfieldname": "print_hide",
|
||||
"oldfieldtype": "Check"
|
||||
"default": "0",
|
||||
"fieldname": "print_hide",
|
||||
"fieldtype": "Check",
|
||||
"label": "Print Hide",
|
||||
"oldfieldname": "print_hide",
|
||||
"oldfieldtype": "Check"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"depends_on": "eval:[\"Int\", \"Float\", \"Currency\", \"Percent\"].indexOf(doc.fieldtype)!==-1",
|
||||
"fieldname": "print_hide_if_no_value",
|
||||
"fieldtype": "Check",
|
||||
"label": "Print Hide If No Value"
|
||||
"default": "0",
|
||||
"depends_on": "eval:[\"Int\", \"Float\", \"Currency\", \"Percent\"].indexOf(doc.fieldtype)!==-1",
|
||||
"fieldname": "print_hide_if_no_value",
|
||||
"fieldtype": "Check",
|
||||
"label": "Print Hide If No Value"
|
||||
},
|
||||
{
|
||||
"description": "Print Width of the field, if the field is a column in a table",
|
||||
"fieldname": "print_width",
|
||||
"fieldtype": "Data",
|
||||
"label": "Print Width",
|
||||
"print_width": "50px",
|
||||
"width": "50px"
|
||||
"description": "Print Width of the field, if the field is a column in a table",
|
||||
"fieldname": "print_width",
|
||||
"fieldtype": "Data",
|
||||
"label": "Print Width",
|
||||
"print_width": "50px",
|
||||
"width": "50px"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:cur_frm.doc.istable",
|
||||
"description": "Number of columns for a field in a Grid (Total Columns in a grid should be less than 11)",
|
||||
"fieldname": "columns",
|
||||
"fieldtype": "Int",
|
||||
"label": "Columns"
|
||||
"depends_on": "eval:cur_frm.doc.istable",
|
||||
"description": "Number of columns for a field in a Grid (Total Columns in a grid should be less than 11)",
|
||||
"fieldname": "columns",
|
||||
"fieldtype": "Int",
|
||||
"label": "Columns"
|
||||
},
|
||||
{
|
||||
"fieldname": "width",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Width",
|
||||
"oldfieldname": "width",
|
||||
"oldfieldtype": "Data",
|
||||
"print_width": "50px",
|
||||
"width": "50px"
|
||||
"fieldname": "width",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Width",
|
||||
"oldfieldname": "width",
|
||||
"oldfieldtype": "Data",
|
||||
"print_width": "50px",
|
||||
"width": "50px"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "is_custom_field",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 1,
|
||||
"label": "Is Custom Field",
|
||||
"read_only": 1
|
||||
"default": "0",
|
||||
"fieldname": "is_custom_field",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 1,
|
||||
"label": "Is Custom Field",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "allow_in_quick_entry",
|
||||
"fieldtype": "Check",
|
||||
"label": "Allow in Quick Entry"
|
||||
"default": "0",
|
||||
"fieldname": "allow_in_quick_entry",
|
||||
"fieldtype": "Check",
|
||||
"label": "Allow in Quick Entry"
|
||||
},
|
||||
{
|
||||
"fieldname": "property_depends_on_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Property Depends On"
|
||||
"fieldname": "property_depends_on_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Property Depends On"
|
||||
},
|
||||
{
|
||||
"fieldname": "mandatory_depends_on",
|
||||
"fieldtype": "Code",
|
||||
"label": "Mandatory Depends On",
|
||||
"options": "JS"
|
||||
"fieldname": "mandatory_depends_on",
|
||||
"fieldtype": "Code",
|
||||
"label": "Mandatory Depends On",
|
||||
"options": "JS"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_33",
|
||||
"fieldtype": "Column Break"
|
||||
"fieldname": "column_break_33",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "read_only_depends_on",
|
||||
"fieldtype": "Code",
|
||||
"label": "Read Only Depends On",
|
||||
"options": "JS"
|
||||
"fieldname": "read_only_depends_on",
|
||||
"fieldtype": "Code",
|
||||
"label": "Read Only Depends On",
|
||||
"options": "JS"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "in_preview",
|
||||
"fieldtype": "Check",
|
||||
"label": "In Preview"
|
||||
"default": "0",
|
||||
"fieldname": "in_preview",
|
||||
"fieldtype": "Check",
|
||||
"label": "In Preview"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"depends_on": "eval:doc.fieldtype=='Section Break'",
|
||||
"fieldname": "hide_border",
|
||||
"fieldtype": "Check",
|
||||
"label": "Hide Border"
|
||||
"default": "1",
|
||||
"depends_on": "eval:doc.fieldtype === \"Duration\";",
|
||||
"fieldname": "show_seconds",
|
||||
"fieldtype": "Check",
|
||||
"label": "Show Seconds",
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"default": "1",
|
||||
"depends_on": "eval:doc.fieldtype === \"Duration\";",
|
||||
"fieldname": "show_days",
|
||||
"fieldtype": "Check",
|
||||
"label": "Show Days",
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"depends_on": "eval:doc.fieldtype=='Section Break'",
|
||||
"fieldname": "hide_border",
|
||||
"fieldtype": "Check",
|
||||
"label": "Hide Border"
|
||||
}
|
||||
],
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2020-04-27 11:39:26.389300",
|
||||
"modified": "2020-05-15 23:45:46.810869",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Custom",
|
||||
"name": "Customize Form Field",
|
||||
|
|
|
|||
|
|
@ -55,7 +55,8 @@ class MariaDBDatabase(Database):
|
|||
'Signature': ('longtext', ''),
|
||||
'Color': ('varchar', self.VARCHAR_LEN),
|
||||
'Barcode': ('longtext', ''),
|
||||
'Geolocation': ('longtext', '')
|
||||
'Geolocation': ('longtext', ''),
|
||||
'Duration': ('decimal', '18,6')
|
||||
}
|
||||
|
||||
def get_connection(self):
|
||||
|
|
|
|||
|
|
@ -60,7 +60,8 @@ class PostgresDatabase(Database):
|
|||
'Signature': ('text', ''),
|
||||
'Color': ('varchar', self.VARCHAR_LEN),
|
||||
'Barcode': ('text', ''),
|
||||
'Geolocation': ('text', '')
|
||||
'Geolocation': ('text', ''),
|
||||
'Duration': ('decimal', '18,6')
|
||||
}
|
||||
|
||||
def get_connection(self):
|
||||
|
|
|
|||
|
|
@ -251,6 +251,7 @@ frappe.ui.form.on('Dashboard Chart', {
|
|||
render_filters_table: function(frm) {
|
||||
frm.set_df_property("filters_section", "hidden", 0);
|
||||
let is_document_type = frm.doc.chart_type!== 'Report' && frm.doc.chart_type!=='Custom';
|
||||
let is_dynamic_filter = f => ['Date', 'DateRange'].includes(f.fieldtype) && f.default;
|
||||
|
||||
let wrapper = $(frm.get_field('filters_json').wrapper).empty();
|
||||
let table = $(`<table class="table table-bordered" style="cursor:pointer; margin:0px;">
|
||||
|
|
@ -268,6 +269,18 @@ frappe.ui.form.on('Dashboard Chart', {
|
|||
let filters = JSON.parse(frm.doc.filters_json || '[]');
|
||||
var filters_set = false;
|
||||
|
||||
// Set dynamic filters for reports
|
||||
if (frm.doc.chart_type == 'Report') {
|
||||
let set_filters = false;
|
||||
frm.chart_filters.forEach(f => {
|
||||
if (is_dynamic_filter(f)) {
|
||||
filters[f.fieldname] = f.default;
|
||||
set_filters = true;
|
||||
}
|
||||
});
|
||||
set_filters && frm.set_value('filters_json', JSON.stringify(filters));
|
||||
}
|
||||
|
||||
let fields;
|
||||
if (is_document_type) {
|
||||
fields = [
|
||||
|
|
@ -292,6 +305,7 @@ frappe.ui.form.on('Dashboard Chart', {
|
|||
}
|
||||
} else if (frm.chart_filters.length) {
|
||||
fields = frm.chart_filters.filter(f => f.fieldname);
|
||||
|
||||
fields.map( f => {
|
||||
if (filters[f.fieldname]) {
|
||||
let condition = '=';
|
||||
|
|
@ -318,7 +332,7 @@ frappe.ui.form.on('Dashboard Chart', {
|
|||
|
||||
let dialog = new frappe.ui.Dialog({
|
||||
title: __('Set Filters'),
|
||||
fields: fields,
|
||||
fields: fields.filter(f => !is_dynamic_filter(f)),
|
||||
primary_action: function() {
|
||||
let values = this.get_values();
|
||||
if (values) {
|
||||
|
|
@ -351,8 +365,15 @@ frappe.ui.form.on('Dashboard Chart', {
|
|||
}
|
||||
|
||||
dialog.show();
|
||||
//Set query report object so that it can be used while fetching filter values in the report
|
||||
frappe.query_report = new frappe.views.QueryReport({'filters': dialog.fields_list});
|
||||
|
||||
if (frm.doc.chart_type == 'Report') {
|
||||
//Set query report object so that it can be used while fetching filter values in the report
|
||||
frappe.query_report = new frappe.views.QueryReport({'filters': dialog.fields_list});
|
||||
frappe.query_reports[frm.doc.report_name]
|
||||
&& frappe.query_reports[frm.doc.report_name].onload
|
||||
&& frappe.query_reports[frm.doc.report_name].onload(frappe.query_report);
|
||||
}
|
||||
|
||||
dialog.set_values(filters);
|
||||
});
|
||||
},
|
||||
|
|
|
|||
|
|
@ -20,6 +20,17 @@ class DeskPage(Document):
|
|||
if frappe.conf.developer_mode and self.is_standard:
|
||||
export_to_files(record_list=[['Desk Page', self.name]], record_module=self.module)
|
||||
|
||||
@staticmethod
|
||||
def get_module_page_map():
|
||||
filters = {
|
||||
'extends_another_page': 0,
|
||||
'for_user': '',
|
||||
}
|
||||
|
||||
pages = frappe.get_all("Desk Page", fields=["name", "module"], filters=filters, as_list=1)
|
||||
|
||||
return { page[1]: page[0] for page in pages }
|
||||
|
||||
def disable_saving_as_standard():
|
||||
return frappe.flags.in_install or \
|
||||
frappe.flags.in_patch or \
|
||||
|
|
|
|||
|
|
@ -110,7 +110,11 @@ class UserProfile {
|
|||
|
||||
|
||||
render_line_chart() {
|
||||
this.line_chart_filters = [['Energy Point Log', 'user', '=', this.user_id, false]];
|
||||
this.line_chart_filters = [
|
||||
['Energy Point Log', 'user', '=', this.user_id, false],
|
||||
['Energy Point Log', 'type', '!=', 'Review', false]
|
||||
];
|
||||
|
||||
this.line_chart_config = {
|
||||
timespan: 'Last Month',
|
||||
time_interval: 'Daily',
|
||||
|
|
@ -186,7 +190,10 @@ class UserProfile {
|
|||
options: ['All', 'Auto', 'Criticism', 'Appreciation', 'Revert'],
|
||||
action: (selected_item) => {
|
||||
if (selected_item === 'All') {
|
||||
if (this.line_chart_filters.length > 1) this.line_chart_filters.pop();
|
||||
this.line_chart_filters = [
|
||||
['Energy Point Log', 'user', '=', this.user_id, false],
|
||||
['Energy Point Log', 'type', '!=', 'Review', false]
|
||||
];
|
||||
} else {
|
||||
this.line_chart_filters[1] = ['Energy Point Log', 'type', '=', selected_item, false];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
"default_incoming",
|
||||
"email_sync_option",
|
||||
"initial_sync_count",
|
||||
"create_contact",
|
||||
"section_break_12",
|
||||
"enable_automatic_linking",
|
||||
"section_break_13",
|
||||
|
|
@ -114,9 +115,9 @@
|
|||
"depends_on": "eval:!doc.service",
|
||||
"fieldname": "domain",
|
||||
"fieldtype": "Link",
|
||||
"label": "Domain",
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 1,
|
||||
"label": "Domain",
|
||||
"options": "Email Domain"
|
||||
},
|
||||
{
|
||||
|
|
@ -408,11 +409,17 @@
|
|||
"fieldname": "use_ssl_for_outgoing",
|
||||
"fieldtype": "Check",
|
||||
"label": "Use SSL for Outgoing"
|
||||
},
|
||||
{
|
||||
"default": "1",
|
||||
"fieldname": "create_contact",
|
||||
"fieldtype": "Check",
|
||||
"label": "Create Contacts from Incoming Emails"
|
||||
}
|
||||
],
|
||||
"icon": "fa fa-inbox",
|
||||
"links": [],
|
||||
"modified": "2020-04-06 19:20:50.491146",
|
||||
"modified": "2020-05-11 15:18:43.931499",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Email",
|
||||
"name": "Email Account",
|
||||
|
|
@ -427,11 +434,11 @@
|
|||
"write": 1
|
||||
},
|
||||
{
|
||||
"read": 1,
|
||||
"role": "Inbox User"
|
||||
"read": 1,
|
||||
"role": "Inbox User"
|
||||
}
|
||||
],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ def backup_to_dropbox(upload_db_backup=True):
|
|||
dropbox_settings['access_token'] = access_token['oauth2_token']
|
||||
set_dropbox_access_token(access_token['oauth2_token'])
|
||||
|
||||
dropbox_client = dropbox.Dropbox(dropbox_settings['access_token'])
|
||||
dropbox_client = dropbox.Dropbox(dropbox_settings['access_token'], timeout=None)
|
||||
|
||||
if upload_db_backup:
|
||||
if frappe.flags.create_new_backup:
|
||||
|
|
|
|||
|
|
@ -147,11 +147,14 @@ def sync_contacts_from_google_contacts(g_contact):
|
|||
results = []
|
||||
contacts_updated = 0
|
||||
|
||||
sync_token = account.get_password(fieldname="next_sync_token", raise_exception=False) or None
|
||||
contacts = frappe._dict()
|
||||
|
||||
while True:
|
||||
try:
|
||||
sync_token = account.get_password(fieldname="next_sync_token", raise_exception=False) or None
|
||||
contacts = google_contacts.people().connections().list(resourceName='people/me',syncToken=sync_token,
|
||||
personFields="names,emailAddresses,organizations,phoneNumbers").execute()
|
||||
contacts = google_contacts.people().connections().list(resourceName='people/me', pageToken=contacts.get("nextPageToken"),
|
||||
syncToken=sync_token, pageSize=2000, requestSyncToken=True, personFields="names,emailAddresses,organizations,phoneNumbers").execute()
|
||||
|
||||
except HttpError as err:
|
||||
frappe.throw(_("Google Contacts - Could not sync contacts from Google Contacts {0}, error code {1}.").format(account.name, err.resp.status))
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,8 @@ data_fieldtypes = (
|
|||
'Signature',
|
||||
'Color',
|
||||
'Barcode',
|
||||
'Geolocation'
|
||||
'Geolocation',
|
||||
'Duration'
|
||||
)
|
||||
|
||||
no_value_fields = ('Section Break', 'Column Break', 'HTML', 'Table', 'Table MultiSelect', 'Button', 'Image',
|
||||
|
|
|
|||
|
|
@ -693,7 +693,7 @@ class BaseDocument(object):
|
|||
df = self.meta.get_field(fieldname)
|
||||
sanitized_value = value
|
||||
|
||||
if df and df.get("fieldtype") in ("Data", "Code", "Small Text") and df.get("options")=="Email":
|
||||
if df and df.get("fieldtype") in ("Data", "Code", "Small Text", "Text") and df.get("options")=="Email":
|
||||
sanitized_value = sanitize_email(value)
|
||||
|
||||
elif df and (df.get("ignore_xss_filter")
|
||||
|
|
|
|||
|
|
@ -283,3 +283,6 @@ frappe.patches.v13_0.remove_tailwind_from_page_builder
|
|||
frappe.patches.v13_0.rename_onboarding
|
||||
frappe.patches.v13_0.email_unsubscribe
|
||||
execute:frappe.delete_doc("Web Template", "Section with Left Image", force=1)
|
||||
execute:frappe.delete_doc("DocType", "Onboarding Slide")
|
||||
execute:frappe.delete_doc("DocType", "Onboarding Slide Field")
|
||||
execute:frappe.delete_doc("DocType", "Onboarding Slide Help Link")
|
||||
|
|
@ -38,6 +38,7 @@ import './table_multiselect';
|
|||
import './multiselect_pills';
|
||||
import './multiselect_list';
|
||||
import './rating';
|
||||
import './duration';
|
||||
|
||||
frappe.ui.form.make_control = function (opts) {
|
||||
var control_class_name = "Control" + opts.df.fieldtype.replace(/ /g, "");
|
||||
|
|
|
|||
152
frappe/public/js/frappe/form/controls/duration.js
Normal file
152
frappe/public/js/frappe/form/controls/duration.js
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
frappe.ui.form.ControlDuration = frappe.ui.form.ControlData.extend({
|
||||
make_input: function() {
|
||||
this._super();
|
||||
this.make_picker();
|
||||
},
|
||||
|
||||
make_picker: function() {
|
||||
this.inputs = [];
|
||||
this.set_duration_options();
|
||||
this.$picker = $(
|
||||
`<div class="duration-picker">
|
||||
<div class="picker-row row"></div>
|
||||
</div>`
|
||||
);
|
||||
this.$wrapper.append(this.$picker);
|
||||
this.build_numeric_input("days", !this.duration_options.show_days);
|
||||
this.build_numeric_input("hours", false);
|
||||
this.build_numeric_input("minutes", false);
|
||||
this.build_numeric_input("seconds", !this.duration_options.show_seconds);
|
||||
this.set_duration_picker_value(this.value);
|
||||
this.$picker.hide();
|
||||
this.bind_events();
|
||||
this.refresh();
|
||||
},
|
||||
|
||||
build_numeric_input: function(label, hidden, max) {
|
||||
let $duration_input = $(`
|
||||
<input class="input-sm duration-input" data-duration="${label}" type="number" min="0" value="0">
|
||||
`);
|
||||
|
||||
let $input = $(`<div class="row duration-row"></div>`).prepend($duration_input);
|
||||
|
||||
if (max) {
|
||||
$duration_input.attr("max", max);
|
||||
}
|
||||
|
||||
this.inputs[label] = $duration_input;
|
||||
|
||||
let $control = $(`
|
||||
<div class="col duration-col">
|
||||
<div class="row duration-row duration-label">${__(label)}</div>
|
||||
</div>`
|
||||
);
|
||||
|
||||
if (hidden) {
|
||||
$control.addClass("hidden");
|
||||
}
|
||||
$control.prepend($input);
|
||||
$control.appendTo(this.$picker.find(".picker-row"));
|
||||
},
|
||||
|
||||
set_duration_options() {
|
||||
this.duration_options = frappe.utils.get_duration_options(this.df);
|
||||
},
|
||||
|
||||
set_duration_picker_value: function(value) {
|
||||
let total_duration = frappe.utils.seconds_to_duration(value, this.duration_options);
|
||||
|
||||
if (this.$picker) {
|
||||
Object.keys(total_duration).forEach(duration => {
|
||||
this.inputs[duration].prop("value", total_duration[duration]);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
bind_events: function() {
|
||||
// flag to handle the display property of the picker
|
||||
let clicked = false;
|
||||
|
||||
this.$wrapper.find(".duration-input").mousedown(() => {
|
||||
// input in individual duration boxes
|
||||
clicked = true;
|
||||
});
|
||||
|
||||
this.$picker.on("change", ".duration-input", () => {
|
||||
// duration changed in individual boxes
|
||||
clicked = false;
|
||||
let duration = this.get_duration();
|
||||
let value = frappe.utils.duration_to_seconds(
|
||||
duration.days,
|
||||
duration.hours,
|
||||
duration.minutes,
|
||||
duration.seconds
|
||||
);
|
||||
this.set_value(value);
|
||||
this.set_focus();
|
||||
});
|
||||
|
||||
this.$input.on("focus", () => {
|
||||
this.$picker.show();
|
||||
let is_picker_set = this.is_duration_picker_set(this.inputs);
|
||||
if (!is_picker_set) {
|
||||
this.set_duration_picker_value(this.value);
|
||||
}
|
||||
});
|
||||
|
||||
this.$input.on("blur", () => {
|
||||
// input in duration boxes, don't close the picker
|
||||
if (clicked) {
|
||||
clicked = false;
|
||||
} else {
|
||||
// blur event was not due to duration inputs
|
||||
this.$picker.hide();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
get_value() {
|
||||
return cint(this.value);
|
||||
},
|
||||
|
||||
refresh_input: function() {
|
||||
this._super();
|
||||
this.set_duration_options();
|
||||
this.set_duration_picker_value(this.value);
|
||||
},
|
||||
|
||||
format_for_input: function(value) {
|
||||
return frappe.utils.get_formatted_duration(value, this.duration_options);
|
||||
},
|
||||
|
||||
get_duration() {
|
||||
// returns an object of days, hours, minutes and seconds from the inputs array
|
||||
let total_duration = {
|
||||
minutes: 0,
|
||||
hours: 0,
|
||||
days: 0,
|
||||
seconds: 0
|
||||
};
|
||||
if (this.inputs) {
|
||||
total_duration.minutes = parseInt(this.inputs.minutes.val());
|
||||
total_duration.hours = parseInt(this.inputs.hours.val());
|
||||
if (this.duration_options.show_days) {
|
||||
total_duration.days = parseInt(this.inputs.days.val());
|
||||
}
|
||||
if (this.duration_options.show_seconds) {
|
||||
total_duration.seconds = parseInt(this.inputs.seconds.val());
|
||||
}
|
||||
}
|
||||
return total_duration;
|
||||
},
|
||||
|
||||
is_duration_picker_set(inputs) {
|
||||
let is_set = false;
|
||||
Object.values(inputs).forEach(duration => {
|
||||
if (duration.prop("value") != 0) {
|
||||
is_set = true;
|
||||
}
|
||||
});
|
||||
return is_set;
|
||||
}
|
||||
});
|
||||
|
|
@ -589,7 +589,6 @@ frappe.ui.form.Timeline = class Timeline {
|
|||
out.push(me.get_version_comment(version, message));
|
||||
}
|
||||
} else {
|
||||
p = p.map(frappe.utils.escape_html);
|
||||
const df = frappe.meta.get_docfield(me.frm.doctype, p[0], me.frm.docname);
|
||||
if (df && !df.hidden) {
|
||||
const field_display_status = frappe.perm.get_field_display_status(df, null,
|
||||
|
|
@ -597,8 +596,8 @@ frappe.ui.form.Timeline = class Timeline {
|
|||
if (field_display_status === 'Read' || field_display_status === 'Write') {
|
||||
parts.push(__('{0} from {1} to {2}', [
|
||||
__(df.label),
|
||||
(frappe.ellipsis(frappe.utils.html2text(p[1]), 40) || '""').bold(),
|
||||
(frappe.ellipsis(frappe.utils.html2text(p[2]), 40) || '""').bold()
|
||||
me.format_content_for_timeline(p[1]),
|
||||
me.format_content_for_timeline(p[2])
|
||||
]));
|
||||
}
|
||||
}
|
||||
|
|
@ -608,9 +607,9 @@ frappe.ui.form.Timeline = class Timeline {
|
|||
if (parts.length) {
|
||||
let message;
|
||||
if (updater_reference_link) {
|
||||
message = __("changed value of {0} {1}", [parts.join(', ').bold(), updater_reference_link]);
|
||||
message = __("changed value of {0} {1}", [parts.join(', '), updater_reference_link]);
|
||||
} else {
|
||||
message = __("changed value of {0}", [parts.join(', ').bold()]);
|
||||
message = __("changed value of {0}", [parts.join(', ')]);
|
||||
}
|
||||
out.push(me.get_version_comment(version, message));
|
||||
}
|
||||
|
|
@ -618,23 +617,23 @@ frappe.ui.form.Timeline = class Timeline {
|
|||
|
||||
// value changed in table field
|
||||
if (data.row_changed && data.row_changed.length) {
|
||||
var parts = [], count = 0;
|
||||
let parts = [];
|
||||
data.row_changed.every(function(row) {
|
||||
row[3].every(function(p) {
|
||||
var df = me.frm.fields_dict[row[0]] &&
|
||||
frappe.meta.get_docfield(me.frm.fields_dict[row[0]].grid.doctype,
|
||||
p[0], me.frm.docname);
|
||||
|
||||
if(df && !df.hidden) {
|
||||
if (df && !df.hidden) {
|
||||
var field_display_status = frappe.perm.get_field_display_status(df,
|
||||
null, me.frm.perm);
|
||||
|
||||
if(field_display_status === 'Read' || field_display_status === 'Write') {
|
||||
if (field_display_status === 'Read' || field_display_status === 'Write') {
|
||||
parts.push(__('{0} from {1} to {2} in row #{3}', [
|
||||
frappe.meta.get_label(me.frm.fields_dict[row[0]].grid.doctype,
|
||||
p[0]),
|
||||
(frappe.ellipsis(p[1], 40) || '""').bold(),
|
||||
(frappe.ellipsis(p[2], 40) || '""').bold(),
|
||||
me.format_content_for_timeline(p[1]),
|
||||
me.format_content_for_timeline(p[2]),
|
||||
row[1]
|
||||
]));
|
||||
}
|
||||
|
|
@ -657,20 +656,22 @@ frappe.ui.form.Timeline = class Timeline {
|
|||
// rows added / removed
|
||||
// __('added'), __('removed') # for translation, don't remove
|
||||
['added', 'removed'].forEach(function(key) {
|
||||
if(data[key] && data[key].length) {
|
||||
parts = (data[key] || []).map(function(p) {
|
||||
if (data[key] && data[key].length) {
|
||||
let parts = (data[key] || []).map(function(p) {
|
||||
var df = frappe.meta.get_docfield(me.frm.doctype, p[0], me.frm.docname);
|
||||
if(df && !df.hidden) {
|
||||
if (df && !df.hidden) {
|
||||
var field_display_status = frappe.perm.get_field_display_status(df, null,
|
||||
me.frm.perm);
|
||||
|
||||
if(field_display_status === 'Read' || field_display_status === 'Write') {
|
||||
if (field_display_status === 'Read' || field_display_status === 'Write') {
|
||||
return frappe.meta.get_label(me.frm.doctype, p[0])
|
||||
}
|
||||
}
|
||||
});
|
||||
parts = parts.filter(function(p) { return p; });
|
||||
if(parts.length) {
|
||||
parts = parts.filter(function(p) {
|
||||
return p;
|
||||
});
|
||||
if (parts.length) {
|
||||
out.push(me.get_version_comment(version, __("{0} rows for {1}",
|
||||
[__(key), parts.join(', ')])));
|
||||
}
|
||||
|
|
@ -717,6 +718,17 @@ frappe.ui.form.Timeline = class Timeline {
|
|||
|
||||
}
|
||||
|
||||
format_content_for_timeline(content) {
|
||||
// text to HTML
|
||||
// limits content to 40 characters
|
||||
// escapes HTML
|
||||
// and makes it bold
|
||||
content = frappe.utils.html2text(content);
|
||||
content = frappe.ellipsis(content, 40) || '""';
|
||||
content = frappe.utils.escape_html(content);
|
||||
return content.bold();
|
||||
}
|
||||
|
||||
delete_comment(name) {
|
||||
var me = this;
|
||||
|
||||
|
|
|
|||
|
|
@ -650,13 +650,14 @@ frappe.ui.form.Form = class FrappeForm {
|
|||
frappe.utils.play_sound("submit");
|
||||
callback && callback();
|
||||
me.script_manager.trigger("on_submit")
|
||||
.then(() => resolve(me));
|
||||
if (frappe.route_hooks.after_submit) {
|
||||
let route_callback = frappe.route_hooks.after_submit;
|
||||
delete frappe.route_hooks.after_submit;
|
||||
|
||||
route_callback(me);
|
||||
}
|
||||
.then(() => resolve(me))
|
||||
.then(() => {
|
||||
if (frappe.route_hooks.after_submit) {
|
||||
let route_callback = frappe.route_hooks.after_submit;
|
||||
delete frappe.route_hooks.after_submit;
|
||||
route_callback(me);
|
||||
}
|
||||
});
|
||||
}
|
||||
}, btn, () => me.handle_save_fail(btn, on_error), resolve);
|
||||
});
|
||||
|
|
@ -1586,7 +1587,7 @@ frappe.ui.form.Form = class FrappeForm {
|
|||
let steps = frappe.tour[this.doctype].map(step => {
|
||||
let field = this.get_docfield(step.fieldname);
|
||||
return {
|
||||
element: `.frappe-control[title='${step.fieldname}']`,
|
||||
element: `.frappe-control[data-fieldname='${step.fieldname}']`,
|
||||
popover: {
|
||||
title: step.title || field.label,
|
||||
description: step.description
|
||||
|
|
|
|||
|
|
@ -142,10 +142,7 @@ frappe.form.formatters = {
|
|||
},
|
||||
DateRange: function(value) {
|
||||
if($.isArray(value)) {
|
||||
return __("{0} to {1}", [
|
||||
frappe.datetime.str_to_user(value[0]),
|
||||
frappe.datetime.str_to_user(value[1])
|
||||
]);
|
||||
return __("{0} to {1}", [frappe.datetime.str_to_user(value[0]), frappe.datetime.str_to_user(value[1])]);
|
||||
} else {
|
||||
return value || "";
|
||||
}
|
||||
|
|
@ -188,6 +185,14 @@ frappe.form.formatters = {
|
|||
|
||||
return value || "";
|
||||
},
|
||||
Duration: function(value, docfield) {
|
||||
if (value) {
|
||||
let duration_options = frappe.utils.get_duration_options(docfield);
|
||||
value = frappe.utils.get_formatted_duration(value, duration_options);
|
||||
}
|
||||
|
||||
return value || "";
|
||||
},
|
||||
LikedBy: function(value) {
|
||||
var html = "";
|
||||
$.each(JSON.parse(value || "[]"), function(i, v) {
|
||||
|
|
|
|||
|
|
@ -16,12 +16,22 @@ frappe.ui.form.get_event_handler_list = function(doctype, fieldname) {
|
|||
frappe.ui.form.on = frappe.ui.form.on_change = function(doctype, fieldname, handler) {
|
||||
var add_handler = function(fieldname, handler) {
|
||||
var handler_list = frappe.ui.form.get_event_handler_list(doctype, fieldname);
|
||||
handler_list.push(handler);
|
||||
|
||||
let _handler = (...args) => {
|
||||
try {
|
||||
handler(...args);
|
||||
} catch (error) {
|
||||
console.error(handler);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
handler_list.push(_handler);
|
||||
|
||||
// add last handler to events so it can be called as
|
||||
// frm.events.handler(frm)
|
||||
if(cur_frm && cur_frm.doctype===doctype) {
|
||||
cur_frm.events[fieldname] = handler;
|
||||
cur_frm.events[fieldname] = _handler;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -103,7 +103,11 @@ frappe.views.ListGroupBy = class ListGroupBy {
|
|||
this.render_dropdown_items(field_count_list, fieldtype, dropdown);
|
||||
frappe.utils.setup_search(dropdown, '.group-by-item', '.group-by-value', 'data-name');
|
||||
} else {
|
||||
dropdown.find('.group-by-loading').html(`${__("No filters found")}`);
|
||||
dropdown.html(
|
||||
`<div class="list-loading text-center group-by-empty text-muted">
|
||||
${__("No filters found")}
|
||||
</div>`
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -161,8 +161,7 @@ $.extend(frappe.meta, {
|
|||
|
||||
if(!out) {
|
||||
// eslint-disable-next-line
|
||||
console.log(__('Warning: Unable to find {0} in any table related to {1}', [
|
||||
key, __(doctype)]));
|
||||
console.log(__('Warning: Unable to find {0} in any table related to {1}', [key, __(doctype)]));
|
||||
}
|
||||
}
|
||||
return out;
|
||||
|
|
@ -266,5 +265,5 @@ $.extend(frappe.meta, {
|
|||
precision = cint(frappe.defaults.get_default("float_precision")) || 3;
|
||||
}
|
||||
return precision;
|
||||
},
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -200,6 +200,12 @@ frappe.ui.FilterList = Class.extend({
|
|||
value = {0:"Draft", 1:"Submitted", 2:"Cancelled"}[value] || value;
|
||||
} else if(field.df.original_type==="Check") {
|
||||
value = {0:"No", 1:"Yes"}[cint(value)];
|
||||
} else if (field.df.original_type === "Duration") {
|
||||
let duration_options = {
|
||||
show_days: field.df.show_days,
|
||||
show_seconds: field.df.show_seconds
|
||||
};
|
||||
value = frappe.utils.get_formatted_duration(value, duration_options);
|
||||
}
|
||||
|
||||
value = frappe.format(value, field.df, {only_value: 1});
|
||||
|
|
|
|||
|
|
@ -803,6 +803,70 @@ Object.assign(frappe.utils, {
|
|||
name: M[0],
|
||||
version: M[1],
|
||||
};
|
||||
},
|
||||
|
||||
get_formatted_duration(value, duration_options) {
|
||||
let duration = '';
|
||||
if (value) {
|
||||
let total_duration = frappe.utils.seconds_to_duration(value, duration_options);
|
||||
|
||||
if (total_duration.days) {
|
||||
duration += total_duration.days + __('d', null, 'Days (Field: Duration)');
|
||||
}
|
||||
if (total_duration.hours) {
|
||||
duration += (duration.length ? " " : "");
|
||||
duration += total_duration.hours + __('h', null, 'Hours (Field: Duration)');
|
||||
}
|
||||
if (total_duration.minutes) {
|
||||
duration += (duration.length ? " " : "");
|
||||
duration += total_duration.minutes + __('m', null, 'Minutes (Field: Duration)');
|
||||
}
|
||||
if (total_duration.seconds) {
|
||||
duration += (duration.length ? " " : "");
|
||||
duration += total_duration.seconds + __('s', null, 'Seconds (Field: Duration)');
|
||||
}
|
||||
}
|
||||
return duration;
|
||||
},
|
||||
|
||||
seconds_to_duration(value, duration_options) {
|
||||
let secs = value;
|
||||
let total_duration = {
|
||||
days: Math.floor(secs / (3600 * 24)),
|
||||
hours: Math.floor(secs % (3600 * 24) / 3600),
|
||||
minutes: Math.floor(secs % 3600 / 60),
|
||||
seconds: Math.floor(secs % 60)
|
||||
};
|
||||
if (!duration_options.show_days) {
|
||||
total_duration.hours = Math.floor(secs / 3600);
|
||||
total_duration.days = 0;
|
||||
}
|
||||
return total_duration;
|
||||
},
|
||||
|
||||
duration_to_seconds(days=0, hours=0, minutes=0, seconds=0) {
|
||||
let value = 0;
|
||||
if (days) {
|
||||
value += days * 24 * 60 * 60;
|
||||
}
|
||||
if (hours) {
|
||||
value += hours * 60 * 60;
|
||||
}
|
||||
if (minutes) {
|
||||
value += minutes * 60;
|
||||
}
|
||||
if (seconds) {
|
||||
value += seconds;
|
||||
}
|
||||
return value;
|
||||
},
|
||||
|
||||
get_duration_options: function(docfield) {
|
||||
let duration_options = {
|
||||
show_days: docfield.show_days,
|
||||
show_seconds: docfield.show_seconds
|
||||
};
|
||||
return duration_options;
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -934,4 +998,4 @@ String.prototype.plural = function(revert) {
|
|||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -89,16 +89,21 @@ frappe.breadcrumbs = {
|
|||
breadcrumbs.module = frappe.breadcrumbs.module_map[breadcrumbs.module];
|
||||
}
|
||||
|
||||
if(frappe.get_module(breadcrumbs.module)) {
|
||||
let current_module = breadcrumbs.module
|
||||
// Check if a desk page exists
|
||||
if (frappe.boot.module_page_map[breadcrumbs.module]) {
|
||||
breadcrumbs.module = frappe.boot.module_page_map[breadcrumbs.module];
|
||||
}
|
||||
|
||||
if(frappe.get_module(current_module)) {
|
||||
// if module access exists
|
||||
var module_info = frappe.get_module(breadcrumbs.module),
|
||||
var module_info = frappe.get_module(current_module),
|
||||
icon = module_info && module_info.icon,
|
||||
label = module_info ? module_info.label : breadcrumbs.module;
|
||||
|
||||
|
||||
if(module_info && !module_info.blocked && frappe.visible_modules.includes(module_info.module_name)) {
|
||||
$(repl('<li><a href="#workspace/%(module)s">%(label)s</a></li>',
|
||||
{ module: breadcrumbs.module, label: __(label) }))
|
||||
{ module: breadcrumbs.module, label: __(breadcrumbs.module) }))
|
||||
.appendTo($breadcrumbs);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -97,7 +97,6 @@ export default class ChartWidget extends Widget {
|
|||
this.chart_settings = {};
|
||||
}
|
||||
this.setup_container();
|
||||
this.prepare_chart_object();
|
||||
if (!this.in_customize_mode) {
|
||||
this.action_area.empty();
|
||||
this.prepare_chart_actions();
|
||||
|
|
@ -110,7 +109,10 @@ export default class ChartWidget extends Widget {
|
|||
this.render_time_series_filters();
|
||||
}
|
||||
}
|
||||
this.fetch_and_update_chart();
|
||||
frappe.run_serially([
|
||||
() => this.prepare_chart_object(),
|
||||
() => this.fetch_and_update_chart(),
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -412,6 +414,8 @@ export default class ChartWidget extends Widget {
|
|||
dialog.show();
|
||||
//Set query report object so that it can be used while fetching filter values in the report
|
||||
frappe.query_report = new frappe.views.QueryReport({'filters': dialog.fields_list});
|
||||
frappe.query_reports[this.chart_doc.report_name].onload
|
||||
&& frappe.query_reports[this.chart_doc.report_name].onload(frappe.query_report);
|
||||
dialog.set_values(this.filters);
|
||||
}
|
||||
|
||||
|
|
@ -577,7 +581,7 @@ export default class ChartWidget extends Widget {
|
|||
colors.push(field.color);
|
||||
});
|
||||
} else if (["Line", "Bar"].includes(this.chart_doc.type)) {
|
||||
colors = [this.chart_doc.color || "light-blue"];
|
||||
colors = [this.chart_doc.color || []];
|
||||
} else if (this.chart_doc.type == "Heatmap") {
|
||||
colors = [];
|
||||
}
|
||||
|
|
@ -623,13 +627,41 @@ export default class ChartWidget extends Widget {
|
|||
}
|
||||
|
||||
prepare_chart_object() {
|
||||
let saved_filters = this.chart_settings.filters || null;
|
||||
this.filters =
|
||||
saved_filters || this.filters || JSON.parse(this.chart_doc.filters_json || "[]");
|
||||
|
||||
if (this.chart_doc.type == 'Heatmap' && !this.chart_doc.heatmap_year) {
|
||||
this.chart_doc.heatmap_year = frappe.dashboard_utils.get_year(frappe.datetime.now_date());
|
||||
}
|
||||
|
||||
return this.set_chart_filters();
|
||||
}
|
||||
|
||||
set_chart_filters() {
|
||||
let user_saved_filters = this.chart_settings.filters || null;
|
||||
let chart_saved_filters = JSON.parse(this.chart_doc.filters_json || "null");
|
||||
|
||||
if (this.chart_doc.chart_type == 'Report') {
|
||||
return frappe.dashboard_utils
|
||||
.get_filters_for_chart_type(this.chart_doc).then(filters => {
|
||||
chart_saved_filters = this.update_default_date_filters(filters, chart_saved_filters);
|
||||
this.filters =
|
||||
user_saved_filters || this.filters || chart_saved_filters;
|
||||
});
|
||||
} else {
|
||||
this.filters =
|
||||
user_saved_filters || this.filters || chart_saved_filters;
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
update_default_date_filters(report_filters, chart_filters) {
|
||||
report_filters.map(f => {
|
||||
if (['Date', 'DateRange'].includes(f.fieldtype) && f.default) {
|
||||
if (f.reqd || chart_filters[f.fieldname]) {
|
||||
chart_filters[f.fieldname] = f.default;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return chart_filters;
|
||||
}
|
||||
|
||||
get_settings() {
|
||||
|
|
|
|||
|
|
@ -29,9 +29,13 @@ export default class ShortcutWidget extends Widget {
|
|||
name: this.link_to,
|
||||
type: this.type,
|
||||
is_query_report: this.is_query_report,
|
||||
doctype: this.ref_doctype
|
||||
doctype: this.ref_doctype,
|
||||
});
|
||||
|
||||
let filters = this.get_doctype_filter();
|
||||
if (this.type == "DocType" && filters) {
|
||||
frappe.route_options = filters;
|
||||
}
|
||||
frappe.set_route(route);
|
||||
});
|
||||
}
|
||||
|
|
@ -40,16 +44,26 @@ export default class ShortcutWidget extends Widget {
|
|||
if (this.in_customize_mode) return;
|
||||
|
||||
this.widget.addClass("shortcut-widget-box");
|
||||
const get_filter = new Function(`return ${this.stats_filter}`);
|
||||
if (this.type == "DocType" && this.stats_filter) {
|
||||
|
||||
let filters = this.get_doctype_filter();
|
||||
if (this.type == "DocType" && filters) {
|
||||
frappe.db
|
||||
.count(this.link_to, {
|
||||
filters: get_filter(),
|
||||
filters: filters,
|
||||
})
|
||||
.then((count) => this.set_count(count));
|
||||
}
|
||||
}
|
||||
|
||||
get_doctype_filter() {
|
||||
let count_filter = new Function(`return ${this.stats_filter}`)();
|
||||
if (count_filter) {
|
||||
return count_filter;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
set_title() {
|
||||
if (this.icon) {
|
||||
this.title_field[0].innerHTML = `<div>
|
||||
|
|
@ -82,4 +96,4 @@ export default class ShortcutWidget extends Widget {
|
|||
|
||||
buttons.appendTo(this.action_area);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -241,11 +241,14 @@ class ShortcutDialog extends WidgetDialog {
|
|||
|
||||
if (this.dialog.get_value("type") == "DocType" && this.filter_group) {
|
||||
let filters = this.filter_group.get_filters();
|
||||
filters.forEach((arr) => {
|
||||
stats_filter[arr[1]] = [arr[2], arr[3]];
|
||||
});
|
||||
|
||||
data.stats_filter = JSON.stringify(stats_filter);
|
||||
if (filters.length) {
|
||||
filters.forEach((arr) => {
|
||||
stats_filter[arr[1]] = [arr[2], arr[3]];
|
||||
});
|
||||
|
||||
data.stats_filter = JSON.stringify(stats_filter);
|
||||
}
|
||||
}
|
||||
|
||||
data.label = data.label
|
||||
|
|
|
|||
|
|
@ -165,3 +165,76 @@
|
|||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* duration control */
|
||||
|
||||
.duration-picker {
|
||||
position: absolute;
|
||||
z-index: 999;
|
||||
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,.15);
|
||||
background: #fff;
|
||||
border: 1px solid @border-color;
|
||||
padding-top: 10px;
|
||||
padding-left: 5px;
|
||||
|
||||
&:after,
|
||||
&:before {
|
||||
border: solid transparent;
|
||||
content: " ";
|
||||
height: 0;
|
||||
width: 0;
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
bottom: 100%;
|
||||
left: 30px;
|
||||
}
|
||||
&:after {
|
||||
border-color: rgba(255, 255, 255, 0);
|
||||
border-bottom-color: #fff;
|
||||
border-width: 8px;
|
||||
margin-left: -8px;
|
||||
}
|
||||
&:before {
|
||||
border-color: rgba(221, 221, 221, 0);
|
||||
border-bottom-color: @border-color;
|
||||
border-width: 9px;
|
||||
margin-left: -9px;
|
||||
}
|
||||
|
||||
.row .col {
|
||||
// for fixing layout in child table
|
||||
padding-left: 0px !important;
|
||||
padding-right: 0px !important;
|
||||
}
|
||||
|
||||
.duration-row {
|
||||
margin: 7px;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.duration-col {
|
||||
margin-left: 2px;
|
||||
}
|
||||
|
||||
.duration-input {
|
||||
width: 60px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.25) !important;
|
||||
}
|
||||
|
||||
.duration-input:focus {
|
||||
outline: None;
|
||||
}
|
||||
|
||||
.duration-label {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.picker-row {
|
||||
display: flex;
|
||||
margin-left: 5px;
|
||||
margin-bottom: 3px;
|
||||
margin-right: 12px;
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
margin-top: 20px;
|
||||
|
||||
.desk-sidebar {
|
||||
width: 24rem;
|
||||
width: 20rem;
|
||||
display: block;
|
||||
position: fixed;
|
||||
z-index: 1;
|
||||
|
|
@ -69,7 +69,7 @@
|
|||
}
|
||||
|
||||
.desk-body {
|
||||
padding-left: calc(24rem + 15px);
|
||||
padding-left: 20rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
.dt-scrollable {
|
||||
max-height: calc(100vh - 250px);
|
||||
min-height: 100px;
|
||||
scrollbar-width: thin;
|
||||
}
|
||||
|
||||
table td.dt-cell {
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ def clear_sessions(user=None, keep_current=False, device=None, force=False):
|
|||
|
||||
:param user: user name (default: current user)
|
||||
:param keep_current: keep current session (default: false)
|
||||
:param device: delete sessions of this device (default: desktop)
|
||||
:param device: delete sessions of this device (default: desktop, mobile)
|
||||
:param force: triggered by the user (default false)
|
||||
'''
|
||||
|
||||
|
|
@ -49,13 +49,16 @@ def get_sessions_to_clear(user=None, keep_current=False, device=None):
|
|||
|
||||
:param user: user name (default: current user)
|
||||
:param keep_current: keep current session (default: false)
|
||||
:param device: delete sessions of this device (default: desktop)
|
||||
:param device: delete sessions of this device (default: desktop, mobile)
|
||||
'''
|
||||
if not user:
|
||||
user = frappe.session.user
|
||||
|
||||
if not device:
|
||||
device = frappe.session.data.device or "desktop"
|
||||
device = ("desktop", "mobile")
|
||||
|
||||
if not isinstance(device, (tuple, list)):
|
||||
device = (device,)
|
||||
|
||||
offset = 0
|
||||
if user == frappe.session.user:
|
||||
|
|
@ -68,12 +71,12 @@ def get_sessions_to_clear(user=None, keep_current=False, device=None):
|
|||
|
||||
return frappe.db.sql_list("""
|
||||
SELECT `sid` FROM `tabSessions`
|
||||
WHERE user=%s
|
||||
AND device=%s
|
||||
WHERE user=%(user)s
|
||||
AND device in %(device)s
|
||||
{condition}
|
||||
ORDER BY `lastupdate` DESC
|
||||
LIMIT 100 OFFSET {offset}""".format(condition=condition, offset=offset),
|
||||
(user, device))
|
||||
{"user": user, "device": device})
|
||||
|
||||
def delete_session(sid=None, user=None, reason="Session Expired"):
|
||||
from frappe.core.doctype.activity_log.feed import logout_feed
|
||||
|
|
|
|||
|
|
@ -145,6 +145,11 @@ table.no-border, table.no-border td {
|
|||
margin: 3px 0px 3px;
|
||||
}
|
||||
|
||||
.print-format table td pre {
|
||||
white-space: normal;
|
||||
word-break: normal;
|
||||
}
|
||||
|
||||
table td div {
|
||||
{% if not print_settings.allow_page_break_inside_tables %}
|
||||
/* needed to avoid partial cutting of text between page break in wkhtmltopdf */
|
||||
|
|
|
|||
|
|
@ -119,21 +119,19 @@ def get_dict(fortype, name=None):
|
|||
messages += frappe.db.sql("select 'Role:', name from tabRole")
|
||||
messages += frappe.db.sql("select 'Module:', name from `tabModule Def`")
|
||||
|
||||
|
||||
message_dict = make_dict_from_messages(messages)
|
||||
message_dict.update(get_dict_from_hooks(fortype, name))
|
||||
|
||||
# remove untranslated
|
||||
message_dict = {k:v for k, v in iteritems(message_dict) if k!=v}
|
||||
|
||||
if fortype=="boot":
|
||||
message_dict.update(get_user_translations(frappe.local.lang))
|
||||
|
||||
translation_assets[asset_key] = message_dict
|
||||
|
||||
cache.hset("translation_assets", frappe.local.lang, translation_assets, shared=True)
|
||||
|
||||
return translation_assets[asset_key]
|
||||
translation_map = translation_assets[asset_key]
|
||||
if fortype == "boot":
|
||||
translation_map.update(get_user_translations(frappe.local.lang))
|
||||
|
||||
return translation_map
|
||||
|
||||
|
||||
def get_dict_from_hooks(fortype, name):
|
||||
translated_dict = {}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,9 @@ import frappe
|
|||
from frappe import _, conf
|
||||
from frappe.utils import cstr, get_url, now_datetime
|
||||
|
||||
_verbose = False
|
||||
# backup variable for backwards compatibility
|
||||
verbose = False
|
||||
_verbose = verbose
|
||||
|
||||
|
||||
class BackupGenerator:
|
||||
|
|
|
|||
|
|
@ -89,10 +89,14 @@ def sync_dashboards(app=None):
|
|||
config = get_config(app_name, module_name)
|
||||
if config:
|
||||
frappe.flags.in_import = True
|
||||
make_records(config.charts, "Dashboard Chart")
|
||||
make_records(config.number_cards, "Number Card")
|
||||
make_records(config.dashboards, "Dashboard")
|
||||
frappe.flags.in_import = False
|
||||
try:
|
||||
make_records(config.charts, "Dashboard Chart")
|
||||
make_records(config.number_cards, "Number Card")
|
||||
make_records(config.dashboards, "Dashboard")
|
||||
except Exception as e:
|
||||
frappe.log_error(e, _("Dashboard Import Error"))
|
||||
finally:
|
||||
frappe.flags.in_import = False
|
||||
|
||||
def make_records(config, doctype):
|
||||
if not config:
|
||||
|
|
|
|||
|
|
@ -323,6 +323,34 @@ def format_datetime(datetime_string, format_string=None):
|
|||
formatted_datetime = datetime.strftime('%Y-%m-%d %H:%M:%S')
|
||||
return formatted_datetime
|
||||
|
||||
def format_duration(seconds, show_days=True):
|
||||
total_duration = {
|
||||
'days': math.floor(seconds / (3600 * 24)),
|
||||
'hours': math.floor(seconds % (3600 * 24) / 3600),
|
||||
'minutes': math.floor(seconds % 3600 / 60),
|
||||
'seconds': math.floor(seconds % 60)
|
||||
}
|
||||
|
||||
if not show_days:
|
||||
total_duration['hours'] = math.floor(seconds / 3600)
|
||||
total_duration['days'] = 0
|
||||
|
||||
duration = ''
|
||||
if total_duration:
|
||||
if total_duration.get('days'):
|
||||
duration += str(total_duration.get('days')) + 'd'
|
||||
if total_duration.get('hours'):
|
||||
duration += ' ' if len(duration) else ''
|
||||
duration += str(total_duration.get('hours')) + 'h'
|
||||
if total_duration.get('minutes'):
|
||||
duration += ' ' if len(duration) else ''
|
||||
duration += str(total_duration.get('minutes')) + 'm'
|
||||
if total_duration.get('seconds'):
|
||||
duration += ' ' if len(duration) else ''
|
||||
duration += str(total_duration.get('seconds')) + 's'
|
||||
|
||||
return duration
|
||||
|
||||
def get_weekdays():
|
||||
return ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
import datetime
|
||||
from frappe.utils import formatdate, fmt_money, flt, cstr, cint, format_datetime, format_time
|
||||
from frappe.utils import formatdate, fmt_money, flt, cstr, cint, format_datetime, format_time, format_duration
|
||||
from frappe.model.meta import get_field_currency, get_field_precision
|
||||
import re
|
||||
from six import string_types
|
||||
|
|
@ -90,4 +90,8 @@ def format_value(value, df=None, doc=None, currency=None, translated=False):
|
|||
values = [v.get(link_field.fieldname, 'asdf') for v in value]
|
||||
return ', '.join(values)
|
||||
|
||||
elif df.get("fieldtype") == "Duration":
|
||||
show_days = df.show_days
|
||||
return format_duration(value, show_days)
|
||||
|
||||
return value
|
||||
|
|
|
|||
|
|
@ -38,10 +38,11 @@
|
|||
"docstatus": 0,
|
||||
"doctype": "Desk Page",
|
||||
"extends_another_page": 0,
|
||||
"hide_custom": 0,
|
||||
"idx": 0,
|
||||
"is_standard": 1,
|
||||
"label": "Website",
|
||||
"modified": "2020-05-05 18:17:13.232473",
|
||||
"modified": "2020-05-28 13:53:10.736212",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Website",
|
||||
"name": "Website",
|
||||
|
|
@ -51,7 +52,7 @@
|
|||
"pin_to_top": 0,
|
||||
"shortcuts": [
|
||||
{
|
||||
"color": "",
|
||||
"color": "#cef6d1",
|
||||
"format": "{} Published",
|
||||
"label": "Blog Post",
|
||||
"link_to": "Blog Post",
|
||||
|
|
@ -59,6 +60,7 @@
|
|||
"type": "DocType"
|
||||
},
|
||||
{
|
||||
"color": "#cef6d1",
|
||||
"format": "{} Active",
|
||||
"label": "Blogger",
|
||||
"link_to": "Blogger",
|
||||
|
|
@ -66,8 +68,11 @@
|
|||
"type": "DocType"
|
||||
},
|
||||
{
|
||||
"color": "#cef6d1",
|
||||
"format": "{} Published",
|
||||
"label": "Web Page",
|
||||
"link_to": "Web Page",
|
||||
"stats_filter": "{ \"published\": 1 }",
|
||||
"type": "DocType"
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"actions": [],
|
||||
"creation": "2014-09-01 14:14:14.292173",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
|
|
@ -34,7 +35,7 @@
|
|||
"fieldtype": "Select",
|
||||
"in_list_view": 1,
|
||||
"label": "Fieldtype",
|
||||
"options": "Attach\nAttach Image\nCheck\nCurrency\nData\nDate\nDatetime\nFloat\nHTML\nInt\nLink\nRating\nSelect\nSmall Text\nText\nText Editor\nTable\nSection Break\nColumn Break"
|
||||
"options": "Attach\nAttach Image\nCheck\nCurrency\nData\nDate\nDatetime\nDuration\nFloat\nHTML\nInt\nLink\nRating\nSelect\nSmall Text\nText\nText Editor\nTable\nSection Break\nColumn Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "label",
|
||||
|
|
@ -119,7 +120,8 @@
|
|||
}
|
||||
],
|
||||
"istable": 1,
|
||||
"modified": "2019-06-07 12:17:10.547133",
|
||||
"links": [],
|
||||
"modified": "2020-05-13 13:35:08.454427",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Website",
|
||||
"name": "Web Form Field",
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
"documentation_url": "https://docs.erpnext.com/docs/user/manual/en/website",
|
||||
"idx": 0,
|
||||
"is_complete": 0,
|
||||
"modified": "2020-05-13 12:32:35.269025",
|
||||
"modified": "2020-05-28 13:51:57.535269",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Website",
|
||||
"name": "Website",
|
||||
|
|
|
|||
|
|
@ -8,10 +8,12 @@
|
|||
"is_mandatory": 0,
|
||||
"is_single": 0,
|
||||
"is_skipped": 0,
|
||||
"modified": "2020-04-30 19:06:10.750976",
|
||||
"modified": "2020-05-28 13:51:53.157256",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Add Blog Category",
|
||||
"owner": "Administrator",
|
||||
"reference_document": "Blog Category",
|
||||
"title": "Add Blog Category"
|
||||
"show_full_form": 0,
|
||||
"title": "Add Blog Category",
|
||||
"validate_action": 0
|
||||
}
|
||||
|
|
@ -13,5 +13,7 @@
|
|||
"name": "Create Blogger",
|
||||
"owner": "Administrator",
|
||||
"reference_document": "Blogger",
|
||||
"title": "Create Blogger"
|
||||
"show_full_form": 0,
|
||||
"title": "Create Blogger",
|
||||
"validate_action": 0
|
||||
}
|
||||
|
|
@ -14,6 +14,8 @@
|
|||
"name": "Enable Website Tracking",
|
||||
"owner": "Administrator",
|
||||
"reference_document": "Website Settings",
|
||||
"show_full_form": 0,
|
||||
"title": "Enable Website Tracking",
|
||||
"validate_action": 0,
|
||||
"value_to_validate": "1"
|
||||
}
|
||||
|
|
@ -8,10 +8,12 @@
|
|||
"is_mandatory": 1,
|
||||
"is_single": 0,
|
||||
"is_skipped": 0,
|
||||
"modified": "2020-04-30 19:06:10.578218",
|
||||
"modified": "2020-05-28 13:51:51.485924",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Introduction to Website",
|
||||
"owner": "Administrator",
|
||||
"show_full_form": 0,
|
||||
"title": "Introduction to Website",
|
||||
"validate_action": 0,
|
||||
"video_url": "https://www.youtube.com/watch?v=lyW6mfFBSNw"
|
||||
}
|
||||
|
|
@ -8,10 +8,12 @@
|
|||
"is_mandatory": 0,
|
||||
"is_single": 0,
|
||||
"is_skipped": 0,
|
||||
"modified": "2020-05-13 12:32:15.966570",
|
||||
"modified": "2020-05-28 13:51:54.264456",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Web Page Tour",
|
||||
"owner": "Administrator",
|
||||
"reference_document": "Web Page",
|
||||
"title": "Learn about Web Pages"
|
||||
"show_full_form": 0,
|
||||
"title": "Learn about Web Pages",
|
||||
"validate_action": 0
|
||||
}
|
||||
|
|
@ -7,9 +7,9 @@
|
|||
"custom_overrides": "",
|
||||
"docstatus": 0,
|
||||
"doctype": "Website Theme",
|
||||
"font_properties": "wght:400;500;600;700;800",
|
||||
"idx": 28,
|
||||
"modified": "2020-05-19 00:33:58.011046",
|
||||
"font_properties": "400,500,600,700,800",
|
||||
"idx": 26,
|
||||
"modified": "2020-05-20 14:47:12.938879",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Website",
|
||||
"name": "Standard",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue