Merge branch 'develop' into timeline-missing-comments

This commit is contained in:
Suraj Shetty 2021-09-06 22:57:59 +05:30 committed by GitHub
commit 92fceb88d5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 207 additions and 68 deletions

View file

@ -121,6 +121,7 @@ jobs:
ORCHESTRATOR_URL: http://test-orchestrator.frappe.io
- name: Upload coverage data
if: ${{ steps.check-build.outputs.build == 'strawberry' }}
uses: codecov/codecov-action@v2
with:
name: MariaDB

View file

@ -124,6 +124,7 @@ jobs:
ORCHESTRATOR_URL: http://test-orchestrator.frappe.io
- name: Upload coverage data
if: ${{ steps.check-build.outputs.build == 'strawberry' }}
uses: codecov/codecov-action@v2
with:
name: Postgres

View file

@ -69,13 +69,11 @@ def make_tree_args(**kwarg):
doctype = kwarg['doctype']
parent_field = 'parent_' + doctype.lower().replace(' ', '_')
name_field = kwarg.get('name_field', doctype.lower().replace(' ', '_') + '_name')
if kwarg['is_root'] == 'false': kwarg['is_root'] = False
if kwarg['is_root'] == 'true': kwarg['is_root'] = True
kwarg.update({
name_field: kwarg[name_field],
parent_field: kwarg.get("parent") or kwarg.get(parent_field)
})

View file

@ -131,7 +131,7 @@ frappe.ui.form.Control = class BaseControl {
if (!this.doc.__islocal) {
new frappe.views.TranslationManager({
'df': this.df,
'source_text': value,
'source_text': this.value,
'target_language': this.doc.language,
'doc': this.doc
});

View file

@ -104,8 +104,10 @@ frappe.ui.form.ControlComment = class ControlComment extends frappe.ui.form.Cont
return [
['bold', 'italic', 'underline'],
['blockquote', 'code-block'],
[{ 'direction': "rtl" }],
['link', 'image'],
[{ 'list': 'ordered' }, { 'list': 'bullet' }],
[{ 'align': [] }],
['clean']
];
}

View file

@ -164,8 +164,11 @@ frappe.ui.form.ControlTextEditor = class ControlTextEditor extends frappe.ui.for
['bold', 'italic', 'underline', 'clean'],
[{ 'color': [] }, { 'background': [] }],
['blockquote', 'code-block'],
// Adding Direction tool to give the user the ability to change text direction.
[{ 'direction': "rtl" }],
['link', 'image'],
[{ 'list': 'ordered' }, { 'list': 'bullet' }, { 'list': 'check' }],
[{ 'align': [] }],
[{ 'indent': '-1'}, { 'indent': '+1' }],
[{'table': [
'insert-table',

View file

@ -1152,6 +1152,10 @@ frappe.ui.form.Form = class FrappeForm {
return btn;
}
change_custom_button_type(label, group, type) {
this.page.change_inner_button_type(label, group, type);
}
clear_custom_buttons() {
this.page.clear_inner_toolbar();
this.page.clear_user_actions();

View file

@ -4,7 +4,7 @@ export default class BulkOperations {
this.doctype = doctype;
}
print(docs) {
print (docs) {
const print_settings = frappe.model.get_doc(':Print Settings', 'Print Settings');
const allow_print_for_draft = cint(print_settings.allow_print_for_draft);
const is_submittable = frappe.model.is_submittable(this.doctype);
@ -27,31 +27,38 @@ export default class BulkOperations {
if (valid_docs.length > 0) {
const dialog = new frappe.ui.Dialog({
title: __('Print Documents'),
fields: [{
'fieldtype': 'Check',
'label': __('With Letterhead'),
'fieldname': 'with_letterhead'
},
{
'fieldtype': 'Select',
'label': __('Print Format'),
'fieldname': 'print_sel',
options: frappe.meta.get_print_formats(this.doctype)
}]
fields: [
{
'fieldtype': 'Select',
'label': __('Letter Head'),
'fieldname': 'letter_sel',
'default': __('No Letterhead'),
options: this.get_letterhead_options()
},
{
'fieldtype': 'Select',
'label': __('Print Format'),
'fieldname': 'print_sel',
options: frappe.meta.get_print_formats(this.doctype)
}
]
});
dialog.set_primary_action(__('Print'), args => {
if (!args) return;
const default_print_format = frappe.get_meta(this.doctype).default_print_format;
const with_letterhead = args.with_letterhead ? 1 : 0;
const with_letterhead = args.letter_sel == __("No Letterhead") ? 0 : 1;
const print_format = args.print_sel ? args.print_sel : default_print_format;
const json_string = JSON.stringify(valid_docs);
const letterhead = args.letter_sel;
const w = window.open('/api/method/frappe.utils.print_format.download_multi_pdf?' +
'doctype=' + encodeURIComponent(this.doctype) +
'&name=' + encodeURIComponent(json_string) +
'&format=' + encodeURIComponent(print_format) +
'&no_letterhead=' + (with_letterhead ? '0' : '1'));
'&no_letterhead=' + (with_letterhead ? '0' : '1') +
'&letterhead=' + encodeURIComponent(letterhead)
);
if (!w) {
frappe.msgprint(__('Please enable pop-ups'));
return;
@ -64,7 +71,28 @@ export default class BulkOperations {
}
}
delete(docnames, done = null) {
get_letterhead_options () {
const letterhead_options = [__("No Letterhead")];
frappe.call({
method: "frappe.client.get_list",
args: {
doctype: 'Letter Head',
fields: ['name', 'is_default'],
limit: 0
},
async: false,
callback (r) {
if (r.message) {
r.message.forEach(letterhead => {
letterhead_options.push(letterhead.name);
});
}
}
});
return letterhead_options;
}
delete (docnames, done = null) {
frappe
.call({
method: 'frappe.desk.reportview.delete_items',
@ -88,7 +116,7 @@ export default class BulkOperations {
});
}
assign(docnames, done) {
assign (docnames, done) {
if (docnames.length > 0) {
const assign_to = new frappe.ui.form.AssignToDialog({
obj: this,
@ -106,7 +134,7 @@ export default class BulkOperations {
}
}
apply_assignment_rule(docnames, done) {
apply_assignment_rule (docnames, done) {
if (docnames.length > 0) {
frappe.call('frappe.automation.doctype.assignment_rule.assignment_rule.bulk_apply', {
doctype: this.doctype,
@ -115,7 +143,7 @@ export default class BulkOperations {
}
}
submit_or_cancel(docnames, action='submit', done=null) {
submit_or_cancel (docnames, action = 'submit', done = null) {
action = action.toLowerCase();
frappe
.call({
@ -140,7 +168,7 @@ export default class BulkOperations {
});
}
edit(docnames, field_mappings, done) {
edit (docnames, field_mappings, done) {
let field_options = Object.keys(field_mappings).sort();
const status_regex = /status/i;
@ -198,16 +226,16 @@ export default class BulkOperations {
if (default_field) set_value_field(dialog); // to set `Value` df based on default `Field`
function set_value_field(dialogObj) {
function set_value_field (dialogObj) {
const new_df = Object.assign({},
field_mappings[dialogObj.get_value('field')]);
/* if the field label has status in it and
if it has select fieldtype with no default value then
set a default value from the available option. */
if(new_df.label.match(status_regex) &&
if (new_df.label.match(status_regex) &&
new_df.fieldtype === 'Select' && !new_df.default) {
let options = [];
if(typeof new_df.options==="string") {
if (typeof new_df.options === "string") {
options = new_df.options.split("\n");
}
//set second option as default if first option is an empty string
@ -223,8 +251,7 @@ export default class BulkOperations {
dialog.show();
}
add_tags(docnames, done) {
add_tags (docnames, done) {
const dialog = new frappe.ui.Dialog({
title: __('Add Tags'),
fields: [
@ -233,7 +260,7 @@ export default class BulkOperations {
fieldname: 'tags',
label: __("Tags"),
reqd: true,
get_data: function(txt) {
get_data: function (txt) {
return frappe.db.get_link_options("Tag", txt);
}
},
@ -262,7 +289,7 @@ export default class BulkOperations {
dialog.show();
}
export(doctype, docnames) {
export (doctype, docnames) {
frappe.require('data_import_tools.bundle.js', () => {
const data_exporter = new frappe.data_import.DataExporter(doctype, 'Insert New Records');
data_exporter.dialog.set_value('export_records', 'by_filter');

View file

@ -618,6 +618,23 @@ frappe.ui.Page = class Page {
}
}
change_inner_button_type(label, group, type) {
let btn;
if (group) {
var $group = this.get_inner_group_button(__(group));
if ($group.length) {
btn = $group.find(`.dropdown-item[data-label="${encodeURIComponent(label)}"]`);
}
} else {
btn = this.inner_toolbar.find(`button[data-label="${encodeURIComponent(label)}"]`);
}
if (btn) {
btn.removeClass().addClass(`btn btn-${type} ellipsis`);
}
}
add_inner_message(message) {
let $message = $(`<span class='inner-page-message text-muted small'>${message}</div>`);
this.inner_toolbar.find('.inner-page-message').remove();

View file

@ -155,7 +155,7 @@ frappe.views.Workspace = class Workspace {
});
// Scroll sidebar to selected page if it is not in viewport.
!frappe.dom.is_element_in_viewport(this.sidebar.find('.selected'))
!frappe.dom.is_element_in_viewport(this.sidebar.find('.selected'))
&& this.sidebar.find('.selected')[0].scrollIntoView();
}
@ -185,7 +185,7 @@ frappe.views.Workspace = class Workspace {
}
append_item(item, container) {
let is_current_page = frappe.router.slug(item.title) == frappe.router.slug(this.get_page_to_show().name)
let is_current_page = frappe.router.slug(item.title) == frappe.router.slug(this.get_page_to_show().name)
&& item.public == this.get_page_to_show().public;
if (is_current_page) {
item.selected = true;
@ -253,11 +253,13 @@ frappe.views.Workspace = class Workspace {
if (!this.page_data || Object.keys(this.page_data).length === 0) return;
return frappe.dashboard_utils.get_dashboard_settings().then(settings => {
let chart_config = settings.chart_config ? JSON.parse(settings.chart_config) : {};
if (this.page_data.charts && this.page_data.charts.items) {
this.page_data.charts.items.map(chart => {
chart.chart_settings = chart_config[chart.chart_name] || {};
});
if (settings) {
let chart_config = settings.chart_config ? JSON.parse(settings.chart_config) : {};
if (this.page_data.charts && this.page_data.charts.items) {
this.page_data.charts.items.map(chart => {
chart.chart_settings = chart_config[chart.chart_name] || {};
});
}
}
});
});
@ -560,7 +562,7 @@ frappe.views.Workspace = class Workspace {
fieldname: 'is_public',
depends_on: `eval:${this.has_access}`,
onchange: function() {
d.set_df_property('parent', 'options',
d.set_df_property('parent', 'options',
this.get_value() ? me.public_parent_pages : me.private_parent_pages);
}
},
@ -704,9 +706,9 @@ frappe.views.Workspace = class Workspace {
}
});
let blocks = outputData.blocks.filter(
item => item.type != 'card' ||
(item.data.card_name !== 'Custom Documents' &&
let blocks = outputData.blocks.filter(
item => item.type != 'card' ||
(item.data.card_name !== 'Custom Documents' &&
item.data.card_name !== 'Custom Reports')
);
@ -752,4 +754,4 @@ frappe.views.Workspace = class Workspace {
this.setup_pages();
this.undo.readOnly = true;
}
};
};

View file

@ -17,10 +17,10 @@ body {
}
.standard-sidebar-section {
margin-top: var(--margin-xl);
margin-bottom: var(--margin-xl);
&:first-of-type {
margin-top: var(--margin-sm);
&:last-of-type {
margin-bottom: var(--margin-sm);
}
}
}
@ -143,7 +143,7 @@ body {
font-weight: 500;
line-height: 1.3em;
color: var(--heading-color);
svg {
flex: none;
margin-right: 6px;
@ -863,7 +863,7 @@ body {
.drag-handle {
display: inline-block;
}
.delete-page {
display: inline-block;
margin-right: 8px;
@ -888,44 +888,44 @@ body {
.codex-editor {
min-height: 630px;
.codex-editor__redactor{
display: flex;
flex-wrap: wrap;
flex-direction: row;
margin: 0px -7px;
padding-bottom: 20px !important;
.ce-block{
width: 100%;
padding-left: 0;
padding-right: 0;
&.ce-block--selected {
.ce-block__content {
background-color: inherit;
}
}
.ce-block__content {
max-width: 100%;
height: 100%;
padding: 7px;
&> div {
height: 100%;
}
.tune-btn > * {
pointer-events: none;
}
.ce-header {
padding: 0 !important;
margin-bottom: 0 !important;
flex: 1;
}
.widget{
&.header {
display: flex;
@ -938,11 +938,11 @@ body {
background-color: var(--control-bg);
color: var(--text-muted);
}
&:focus {
outline: none;
}
&.new-widget {
align-items: inherit;
}
@ -959,7 +959,7 @@ body {
gap: 5px;
background-color: var(--card-bg);
padding-left: 5px;
.drag-handle {
cursor: all-scroll;
cursor: -webkit-grabbing;
@ -969,22 +969,22 @@ body {
}
}
}
svg {
fill: none;
}
.ce-toolbar {
svg {
fill: currentColor;
}
.icon {
stroke: none;
width: fit-content;
height: fit-content;
}
.ce-settings {
width: fit-content;
@ -1011,18 +1011,18 @@ body {
border-radius: 0 4px 4px 0;z-index: 0;
}
}
.ce-toolbar__settings-btn {
display: none;
}
}
.ce-inline-tool, .ce-inline-toolbar__dropdown {
.icon {
fill: currentColor;
}
}
@media (min-width: 1199px) {
.ce-toolbar__content {
max-width: 930px;
@ -1033,14 +1033,14 @@ body {
max-width: 760px;
}
}
@media (max-width: 1199px) {
.ce-block.col-4 {
flex: 0 0 50%;
max-width: 50%;
}
}
@media (max-width: 750px) {
.ce-block.col-4 {
flex: 0 0 100%;
@ -1053,6 +1053,6 @@ body {
max-width: 100%;
}
}
}
}

View file

@ -0,0 +1,67 @@
import unittest
import frappe
from frappe.www.list import get_list_context
class TestWebsite(unittest.TestCase):
def test_get_context_hook_of_webform(self):
create_custom_doctype()
create_webform()
# check context for apps without any hook
context_list = get_list_context("", "Custom Doctype", "test-webform")
self.assertFalse(context_list)
# create a hook to get webform_context
set_webform_hook(
"webform_list_context",
"frappe.www._test._test_webform.webform_list_context",
)
# check context for apps with hook
context_list = get_list_context("", "Custom Doctype", "test-webform")
self.assertTrue(context_list)
def create_custom_doctype():
frappe.get_doc(
{
"doctype": "DocType",
"name": "Custom Doctype",
"module": "Core",
"custom": 1,
"fields": [{"label": "Title", "fieldname": "title", "fieldtype": "Data"}],
}
).insert(ignore_if_duplicate=True)
def create_webform():
frappe.get_doc(
{
"doctype": "Web Form",
"module": "Core",
"title": "Test Webform",
"route": "test-webform",
"doc_type": "Custom Doctype",
"web_form_fields": [
{
"doctype": "Web Form Field",
"fieldname": "title",
"fieldtype": "Data",
"label": "Title",
}
],
}
).insert(ignore_if_duplicate=True)
def set_webform_hook(key, value):
from frappe import hooks
# reset hooks
for hook in "webform_list_context":
if hasattr(hooks, hook):
delattr(hooks, hook)
setattr(hooks, key, value)
frappe.cache().delete_key("app_hooks")

View file

@ -821,6 +821,9 @@ def update_translations_for_source(source=None, translation_dict=None):
translation_dict = json.loads(translation_dict)
if is_html(source):
source = strip_html_tags(source)
# for existing records
translation_records = frappe.db.get_values('Translation', {
'source_text': source

View file

@ -0,0 +1,6 @@
def webform_list_context(module):
return {"get_list": get_webform_context_list}
def get_webform_context_list():
pass

View file

@ -161,6 +161,14 @@ def get_list_context(context, doctype, web_form_name=None):
module = load_doctype_module(doctype)
list_context = update_context_from_module(module, list_context)
# get context for custom webform
if meta.custom and web_form_name:
webform_list_contexts = frappe.get_hooks('webform_list_context')
if webform_list_contexts:
out = frappe._dict(frappe.get_attr(webform_list_contexts[0])(meta.module) or {})
if out:
list_context = out
# get context from web form module
if web_form_name:
web_form = frappe.get_doc('Web Form', web_form_name)