Merge branch 'staging-fixes' into staging
This commit is contained in:
commit
e23faaf79a
29 changed files with 239 additions and 51 deletions
|
|
@ -17,7 +17,7 @@ from faker import Faker
|
|||
from .exceptions import *
|
||||
from .utils.jinja import (get_jenv, get_template, render_template, get_email_from_template, get_jloader)
|
||||
|
||||
__version__ = '10.1.69'
|
||||
__version__ = '10.1.70'
|
||||
__title__ = "Frappe Framework"
|
||||
|
||||
local = Local()
|
||||
|
|
|
|||
|
|
@ -49,6 +49,10 @@ def clear_defaults_cache(user=None):
|
|||
elif frappe.flags.in_install!="frappe":
|
||||
frappe.cache().delete_key("defaults")
|
||||
|
||||
def clear_document_cache():
|
||||
frappe.local.document_cache = {}
|
||||
frappe.cache().delete_key("document_cache")
|
||||
|
||||
def clear_doctype_cache(doctype=None):
|
||||
cache = frappe.cache()
|
||||
|
||||
|
|
@ -81,3 +85,6 @@ def clear_doctype_cache(doctype=None):
|
|||
for name in groups:
|
||||
cache.delete_value(name)
|
||||
|
||||
# Clear all document's cache. To clear documents of a specific DocType document_cache should be restructured
|
||||
clear_document_cache()
|
||||
|
||||
|
|
|
|||
|
|
@ -75,8 +75,8 @@ def get_feed_match_conditions(user=None, force=True):
|
|||
if user_permissions:
|
||||
can_read_docs = []
|
||||
for doctype, obj in user_permissions.items():
|
||||
for n in obj.get("docs", []):
|
||||
can_read_docs.append('"{}|{}"'.format(doctype, frappe.db.escape(n)))
|
||||
for n in obj:
|
||||
can_read_docs.append('"{}|{}"'.format(doctype, frappe.db.escape(n.get('doc', ''))))
|
||||
|
||||
if can_read_docs:
|
||||
conditions.append("concat_ws('|', `tabCommunication`.reference_doctype, `tabCommunication`.reference_name) in ({})".format(
|
||||
|
|
|
|||
|
|
@ -56,10 +56,10 @@ def get_user_permissions(user=None):
|
|||
if not out.get(perm.allow):
|
||||
out[perm.allow] = []
|
||||
|
||||
out[perm.allow].append({
|
||||
out[perm.allow].append(frappe._dict({
|
||||
'doc': doc_name,
|
||||
'applicable_for': perm.get('applicable_for')
|
||||
})
|
||||
}))
|
||||
|
||||
try:
|
||||
for perm in frappe.get_all('User Permission',
|
||||
|
|
@ -74,6 +74,7 @@ def get_user_permissions(user=None):
|
|||
for doc in decendants:
|
||||
add_doc_to_perm(perm, doc)
|
||||
|
||||
out = frappe._dict(out)
|
||||
frappe.cache().hset("user_permissions", user, out)
|
||||
|
||||
except frappe.SQLError as e:
|
||||
|
|
@ -95,7 +96,7 @@ def get_applicable_for_doctype_list(doctype, txt, searchfield, start, page_len,
|
|||
linked_doctypes = get_linked_doctypes(doctype, True).keys()
|
||||
linked_doctypes = list(linked_doctypes)
|
||||
linked_doctypes += [doctype]
|
||||
|
||||
|
||||
if txt:
|
||||
linked_doctypes = [d for d in linked_doctypes if txt in d.lower()]
|
||||
|
||||
|
|
@ -110,3 +111,13 @@ def get_applicable_for_doctype_list(doctype, txt, searchfield, start, page_len,
|
|||
def get_permitted_documents(doctype):
|
||||
return [d.get('doc') for d in get_user_permissions().get(doctype, []) \
|
||||
if d.get('doc')]
|
||||
|
||||
@frappe.whitelist()
|
||||
def clear_user_permissions(user, for_doctype):
|
||||
frappe.only_for('System Manager')
|
||||
|
||||
total = frappe.db.count('User Permission', filters = dict(user=user, allow=for_doctype))
|
||||
if total:
|
||||
frappe.db.sql('DELETE FROM `tabUser Permission` WHERE user=%s AND allow=%s', (user, for_doctype))
|
||||
frappe.clear_cache()
|
||||
return total
|
||||
|
|
|
|||
52
frappe/core/doctype/user_permission/user_permission_list.js
Normal file
52
frappe/core/doctype/user_permission/user_permission_list.js
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
frappe.listview_settings['User Permission'] = {
|
||||
onload: function(list_view) {
|
||||
list_view.page.add_menu_item(__("Clear User Permissions"), () => {
|
||||
const dialog = new frappe.ui.Dialog({
|
||||
title: __('Clear User Permissions'),
|
||||
fields: [
|
||||
{
|
||||
'fieldname': 'user',
|
||||
'label': __('For User'),
|
||||
'fieldtype': 'Link',
|
||||
'options': 'User',
|
||||
'reqd': 1
|
||||
},
|
||||
{
|
||||
'fieldname': 'for_doctype',
|
||||
'label': __('For Document Type'),
|
||||
'fieldtype': 'Link',
|
||||
'options': 'DocType',
|
||||
'reqd': 1
|
||||
},
|
||||
],
|
||||
primary_action: (data) => {
|
||||
// mandatory not filled
|
||||
if (!data) return;
|
||||
|
||||
frappe.confirm(__('Are you sure?'), () => {
|
||||
frappe
|
||||
.xcall('frappe.core.doctype.user_permission.user_permission.clear_user_permissions', data)
|
||||
.then(data => {
|
||||
dialog.hide();
|
||||
let message = '';
|
||||
if (data === 0) {
|
||||
message = __('No records deleted');
|
||||
} else {
|
||||
message = __('{0} records deleted', [data]);
|
||||
}
|
||||
frappe.show_alert({
|
||||
message,
|
||||
indicator: 'green'
|
||||
});
|
||||
list_view.refresh();
|
||||
});
|
||||
});
|
||||
|
||||
},
|
||||
primary_action_label: __('Clear')
|
||||
});
|
||||
|
||||
dialog.show();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -93,7 +93,6 @@ def get_permission_query_conditions(user):
|
|||
}
|
||||
|
||||
def has_permission(doc, user):
|
||||
frappe.log_error(doc.owner)
|
||||
if doc.event_type=="Public" or doc.owner==user:
|
||||
return True
|
||||
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ def generate_report_result(report, filters=None, user=None):
|
|||
module = report.module or frappe.db.get_value("DocType", report.ref_doctype, "module")
|
||||
if report.is_standard == "Yes":
|
||||
method_name = get_report_module_dotted_path(module, report.name) + ".execute"
|
||||
threshold = 10
|
||||
threshold = 60
|
||||
res = []
|
||||
|
||||
start_time = datetime.datetime.now()
|
||||
|
|
|
|||
|
|
@ -559,24 +559,55 @@
|
|||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "0",
|
||||
"fieldname": "retry",
|
||||
"fieldtype": "Int",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Retry",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"icon": "fa fa-envelope",
|
||||
"idx": 1,
|
||||
"image_view": 0,
|
||||
"in_create": 1,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-11-09 15:34:07.229657",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Email",
|
||||
"name": "Email Queue",
|
||||
"owner": "Administrator",
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"icon": "fa fa-envelope",
|
||||
"idx": 1,
|
||||
"image_view": 0,
|
||||
"in_create": 1,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2019-01-11 09:05:04.175368",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Email",
|
||||
"name": "Email Queue",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
|
|
|
|||
|
|
@ -382,7 +382,7 @@ def send_one(email, smtpserver=None, auto_commit=True, now=False, from_test=Fals
|
|||
email = frappe.db.sql('''select
|
||||
name, status, communication, message, sender, reference_doctype,
|
||||
reference_name, unsubscribe_param, unsubscribe_method, expose_recipients,
|
||||
show_as_cc, add_unsubscribe_link, attachments
|
||||
show_as_cc, add_unsubscribe_link, attachments, retry
|
||||
from
|
||||
`tabEmail Queue`
|
||||
where
|
||||
|
|
@ -464,12 +464,16 @@ def send_one(email, smtpserver=None, auto_commit=True, now=False, from_test=Fals
|
|||
except Exception as e:
|
||||
frappe.db.rollback()
|
||||
|
||||
if any("Sent" == s.status for s in recipients_list):
|
||||
frappe.db.sql("""update `tabEmail Queue` set status='Partially Errored', error=%s where name=%s""",
|
||||
(text_type(e), email.name), auto_commit=auto_commit)
|
||||
if email.retry < 3:
|
||||
frappe.db.sql("""update `tabEmail Queue` set status='Not Sent', modified=%s, retry=retry+1 where name=%s""",
|
||||
(now_datetime(), email.name), auto_commit=auto_commit)
|
||||
else:
|
||||
frappe.db.sql("""update `tabEmail Queue` set status='Error', error=%s
|
||||
where name=%s""", (text_type(e), email.name), auto_commit=auto_commit)
|
||||
if any("Sent" == s.status for s in recipients_list):
|
||||
frappe.db.sql("""update `tabEmail Queue` set status='Partially Errored', error=%s where name=%s""",
|
||||
(text_type(e), email.name), auto_commit=auto_commit)
|
||||
else:
|
||||
frappe.db.sql("""update `tabEmail Queue` set status='Error', error=%s
|
||||
where name=%s""", (text_type(e), email.name), auto_commit=auto_commit)
|
||||
|
||||
if email.communication:
|
||||
frappe.get_doc('Communication', email.communication).set_delivery_status(commit=auto_commit)
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ source_link = "https://github.com/frappe/frappe"
|
|||
app_license = "MIT"
|
||||
|
||||
develop_version = '12.x.x-develop'
|
||||
staging_version = '11.0.3-beta.49'
|
||||
staging_version = '11.0.3-beta.50'
|
||||
|
||||
app_email = "info@frappe.io"
|
||||
|
||||
|
|
|
|||
|
|
@ -133,13 +133,14 @@ def user_permissions_exist(df, user_permissions):
|
|||
|
||||
def get_default_based_on_another_field(df, user_permissions, parent_doc):
|
||||
# default value based on another document
|
||||
from frappe.permissions import get_allowed_docs_for_doctype
|
||||
|
||||
ref_doctype = df.default[1:]
|
||||
ref_fieldname = ref_doctype.lower().replace(" ", "_")
|
||||
reference_name = parent_doc.get(ref_fieldname) if parent_doc else frappe.db.get_default(ref_fieldname)
|
||||
|
||||
default_value = frappe.db.get_value(ref_doctype, reference_name, df.fieldname)
|
||||
is_allowed_default_value = (not user_permissions_exist(df, user_permissions) or
|
||||
(default_value in user_permissions.get(df.options).get('docs', [])))
|
||||
(default_value in get_allowed_docs_for_doctype(user_permissions[df.options], df.parent)))
|
||||
|
||||
# is this allowed as per user permissions
|
||||
if is_allowed_default_value:
|
||||
|
|
|
|||
|
|
@ -30,13 +30,14 @@ frappe.db = {
|
|||
});
|
||||
});
|
||||
},
|
||||
get_value: function(doctype, filters, fieldname, callback) {
|
||||
get_value: function(doctype, filters, fieldname, callback, parent) {
|
||||
return frappe.call({
|
||||
method: "frappe.client.get_value",
|
||||
args: {
|
||||
doctype: doctype,
|
||||
fieldname: fieldname,
|
||||
filters: filters
|
||||
filters: filters,
|
||||
parent: parent
|
||||
},
|
||||
callback: function(r) {
|
||||
callback && callback(r.message);
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ frappe.provide('frappe.utils');
|
|||
*/
|
||||
const EventEmitterMixin = {
|
||||
init() {
|
||||
this.jq = jQuery(this);
|
||||
this.jq = jQuery({});
|
||||
},
|
||||
|
||||
trigger(evt, data) {
|
||||
|
|
|
|||
|
|
@ -45,7 +45,9 @@ frappe.ui.form.ControlData = frappe.ui.form.ControlInput.extend({
|
|||
if (val) {
|
||||
this.set_description(__('{0} already exists. Select another name', [val.name]));
|
||||
}
|
||||
});
|
||||
},
|
||||
this.doc.parenttype
|
||||
);
|
||||
this.last_check = null;
|
||||
}, 1000);
|
||||
this.last_check = timeout;
|
||||
|
|
|
|||
|
|
@ -181,6 +181,19 @@ frappe.ui.form.ControlTextEditor = frappe.ui.form.ControlCode.extend({
|
|||
},
|
||||
|
||||
get_input_value() {
|
||||
return this.quill ? this.quill.root.innerHTML : '';
|
||||
let value = this.quill ? this.quill.root.innerHTML : '';
|
||||
// quill keeps ol as a common container for both type of lists
|
||||
// and uses css for appearances, this is not semantic
|
||||
// so we convert ol to ul if it is unordered
|
||||
const $value = $(`<div>${value}</div>`);
|
||||
$value.find('ol li[data-list=bullet]:first-child').each((i, li) => {
|
||||
let $li = $(li);
|
||||
let $parent = $li.parent();
|
||||
let $children = $parent.children();
|
||||
let $ul = $('<ul>').append($children);
|
||||
$parent.replaceWith($ul);
|
||||
});
|
||||
value = $value.html();
|
||||
return value;
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -103,6 +103,7 @@ frappe.ui.form.AssignTo = Class.extend({
|
|||
}
|
||||
|
||||
me.assign_to.dialog.show();
|
||||
me.assign_to = null;
|
||||
},
|
||||
remove: function(owner) {
|
||||
var me = this;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
{% if (data.user_content) { %}
|
||||
<span class="pull-left avatar avatar-medium hidden-xs" style="margin-top: 1px">
|
||||
{% if(data.user_info.image) { %}
|
||||
<div class="avatar-frame" style="background-image: url({%= data.user_info.image %})"></div>
|
||||
<div class="avatar-frame" style="background-image: url(\'{%= data.user_info.image %}\')"></div>
|
||||
{% } else { %}
|
||||
<div class="standard-image" style="background-color: {{ data.user_info.color }}">
|
||||
{{ data.user_info.abbr }}</div>
|
||||
|
|
@ -35,7 +35,7 @@
|
|||
<div class="comment-header clearfix small {% if (data.edit || data.delete) { %} links-active {% } %}">
|
||||
<span class="pull-left avatar avatar-small visible-xs">
|
||||
{% if(data.user_info.image) { %}
|
||||
<div class="avatar-frame" style="background-image: url({%= data.user_info.image %})"></div>
|
||||
<div class="avatar-frame" style="background-image: url(\'{%= data.user_info.image %}\')"></div>
|
||||
{% } else { %}
|
||||
<div class="standard-image" style="background-color: {{ data.user_info.color }}">
|
||||
{{ data.user_info.abbr }}</div>
|
||||
|
|
|
|||
|
|
@ -683,8 +683,8 @@ export default class Grid {
|
|||
data.push([__("Do not edit headers which are preset in the template")]);
|
||||
data.push(["------"]);
|
||||
$.each(frappe.get_meta(me.df.options).fields, function(i, df) {
|
||||
// don't include the hidden field in the template
|
||||
if(frappe.model.is_value_type(df.fieldtype) && !df.hidden) {
|
||||
// don't include the read-only field in the template
|
||||
if(frappe.model.is_value_type(df.fieldtype) && !df.read_only) {
|
||||
data[1].push(df.label);
|
||||
data[2].push(df.fieldname);
|
||||
let description = (df.description || "") + ' ';
|
||||
|
|
|
|||
|
|
@ -597,7 +597,7 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList {
|
|||
args: {
|
||||
doctype: this.doctype,
|
||||
filters: this.get_filters_for_args(),
|
||||
fields: [`count(${frappe.model.get_full_column_name('name', this.doctype)}) as total_count`]
|
||||
fields: [`count(distinct ${frappe.model.get_full_column_name('name', this.doctype)}) as total_count`],
|
||||
}
|
||||
}).then(r => {
|
||||
this.total_count = r.message.values[0][0] || current_count;
|
||||
|
|
|
|||
|
|
@ -153,6 +153,7 @@ frappe.ui.Dialog = class Dialog extends frappe.ui.FieldGroup {
|
|||
this.$wrapper.modal("show");
|
||||
this.primary_action_fulfilled = false;
|
||||
this.is_visible = true;
|
||||
return this;
|
||||
}
|
||||
hide() {
|
||||
this.$wrapper.modal("hide");
|
||||
|
|
|
|||
|
|
@ -639,6 +639,10 @@ frappe.views.CommunicationComposer = Class.extend({
|
|||
+ this.real_name + ",</p><!-- salutation-ends --><br>" + (this.message || "");
|
||||
}
|
||||
|
||||
if(this.message && signature && this.message.includes(signature)) {
|
||||
signature = "";
|
||||
}
|
||||
|
||||
let reply = (this.message || "") + (signature ? ("<br>" + signature) : "");
|
||||
let content = '';
|
||||
|
||||
|
|
|
|||
|
|
@ -616,11 +616,24 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList {
|
|||
{for_print: false, always_show_decimals: true}, data);
|
||||
};
|
||||
|
||||
let compareFn = null;
|
||||
if (column.fieldtype === 'Date') {
|
||||
compareFn = (cell, keyword) => {
|
||||
if (!cell.content) return null;
|
||||
if (keyword.length !== 'YYYY-MM-DD'.length) return null;
|
||||
|
||||
const keywordValue = frappe.datetime.user_to_obj(keyword);
|
||||
const cellValue = frappe.datetime.str_to_obj(cell.content);
|
||||
return [+cellValue, +keywordValue];
|
||||
};
|
||||
}
|
||||
|
||||
return Object.assign(column, {
|
||||
id: column.fieldname,
|
||||
name: column.label,
|
||||
width: parseInt(column.width) || null,
|
||||
editable: false,
|
||||
compareValue: compareFn,
|
||||
format: (value, row, column, data) => {
|
||||
if (this.report_settings.formatter) {
|
||||
return this.report_settings.formatter(value, row, column, data, format_cell);
|
||||
|
|
|
|||
|
|
@ -823,6 +823,19 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView {
|
|||
// child table column
|
||||
const id = doctype !== this.doctype ? `${doctype}:${fieldname}` : fieldname;
|
||||
|
||||
let compareFn = null;
|
||||
if (docfield.fieldtype === 'Date') {
|
||||
compareFn = (cell, keyword) => {
|
||||
if (!cell.content) return null;
|
||||
if (keyword.length !== 'YYYY-MM-DD'.length) return null;
|
||||
|
||||
const keywordValue = frappe.datetime.user_to_obj(keyword);
|
||||
const cellValue = frappe.datetime.str_to_obj(cell.content);
|
||||
return [+cellValue, +keywordValue];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
id: id,
|
||||
field: fieldname,
|
||||
|
|
@ -832,6 +845,7 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView {
|
|||
width,
|
||||
editable,
|
||||
align,
|
||||
compareValue: compareFn,
|
||||
format: (value, row, column, data) => {
|
||||
const d = row.reduce((acc, curr) => {
|
||||
if (!curr.column.docfield) return acc;
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ from frappe.permissions import (add_user_permission, remove_user_permission,
|
|||
get_valid_perms)
|
||||
from frappe.core.page.permission_manager.permission_manager import update, reset
|
||||
from frappe.test_runner import make_test_records_for_doctype
|
||||
from frappe.core.doctype.user_permission.user_permission import clear_user_permissions
|
||||
|
||||
test_dependencies = ['Blogger', 'Blog Post', "User", "Contact", "Salutation"]
|
||||
|
||||
|
|
@ -427,4 +428,35 @@ class TestPermissions(unittest.TestCase):
|
|||
self.assertTrue(doc.has_permission("delete"))
|
||||
|
||||
# delete the created doc
|
||||
frappe.delete_doc('Blog Post', '-test-blog-post-title')
|
||||
frappe.delete_doc('Blog Post', '-test-blog-post-title')
|
||||
|
||||
def test_clear_user_permissions(self):
|
||||
current_user = frappe.session.user
|
||||
frappe.set_user('Administrator')
|
||||
clear_user_permissions_for_doctype('Blog Category', 'test2@example.com')
|
||||
clear_user_permissions_for_doctype('Blog Post', 'test2@example.com')
|
||||
|
||||
add_user_permission('Blog Post', '-test-blog-post-1', 'test2@example.com')
|
||||
add_user_permission('Blog Post', '-test-blog-post-2', 'test2@example.com')
|
||||
add_user_permission("Blog Category", '_Test Blog Category 1', 'test2@example.com')
|
||||
|
||||
deleted_user_permission_count = clear_user_permissions('test2@example.com', 'Blog Post')
|
||||
|
||||
self.assertEqual(deleted_user_permission_count, 2)
|
||||
|
||||
blog_post_user_permission_count = frappe.db.count('User Permission', filters={
|
||||
'user': 'test2@example.com',
|
||||
'allow': 'Blog Post'
|
||||
})
|
||||
|
||||
self.assertEqual(blog_post_user_permission_count, 0)
|
||||
|
||||
blog_category_user_permission_count = frappe.db.count('User Permission', filters={
|
||||
'user': 'test2@example.com',
|
||||
'allow': 'Blog Category'
|
||||
})
|
||||
|
||||
self.assertEqual(blog_category_user_permission_count, 1)
|
||||
|
||||
# reset the user
|
||||
frappe.set_user(current_user)
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ def print_by_server(doctype, name, print_format=None, doc=None, no_letterhead=0)
|
|||
print_settings = frappe.get_doc("Print Settings")
|
||||
try:
|
||||
import cups
|
||||
except ModuleNotFoundError:
|
||||
except ImportError:
|
||||
frappe.throw("You need to install pycups to use this feature!")
|
||||
return
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ class WebsiteGenerator(Document):
|
|||
return title_field
|
||||
|
||||
def clear_cache(self):
|
||||
super(WebsiteGenerator, self).clear_cache()
|
||||
clear_cache(self.route)
|
||||
|
||||
def scrub(self, text):
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
"awesomplete": "^1.1.2",
|
||||
"cookie": "^0.3.1",
|
||||
"express": "^4.16.2",
|
||||
"frappe-datatable": "^1.7.3",
|
||||
"frappe-datatable": "^1.8.0",
|
||||
"frappe-gantt": "^0.1.0",
|
||||
"fuse.js": "^3.2.0",
|
||||
"highlight.js": "^9.12.0",
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ pyasn1
|
|||
zxcvbn-python
|
||||
unittest-xml-reporting
|
||||
oauthlib==2.1.0
|
||||
requests-oauthlib==1.1.0
|
||||
pdfkit
|
||||
PyJWT
|
||||
PyPDF2
|
||||
|
|
|
|||
|
|
@ -1219,10 +1219,10 @@ forwarded@~0.1.2:
|
|||
resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84"
|
||||
integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=
|
||||
|
||||
frappe-datatable@^1.7.2:
|
||||
version "1.7.3"
|
||||
resolved "https://registry.yarnpkg.com/frappe-datatable/-/frappe-datatable-1.7.3.tgz#dadddf01867723bf0862918dd62cfea4652416a3"
|
||||
integrity sha512-72LUx0ZRRjFPLFQUzgB7Uywpxgk1rFLjyzOq5yQ5Mr2G8u0t3AoUJLRG2lAqFD49JOxezVb6Oa03Qmon1DCExA==
|
||||
frappe-datatable@^1.8.0:
|
||||
version "1.8.0"
|
||||
resolved "https://registry.yarnpkg.com/frappe-datatable/-/frappe-datatable-1.8.0.tgz#7f789ed77bdf9800143fffb1bb28a24d5dbdc27c"
|
||||
integrity sha512-j3DdmYtTjhcVXCVkYjKHdZOc8tSwZapanlujdx1xzXcL7Ueo+BFiPR5WptWRfH43K3nboh3m7clcAIX7LdQR4g==
|
||||
dependencies:
|
||||
hyperlist "^1.0.0-beta"
|
||||
lodash "^4.17.5"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue