Merge branch 'develop' into timeline-missing-comments
This commit is contained in:
commit
92fceb88d5
15 changed files with 207 additions and 68 deletions
1
.github/workflows/server-mariadb-tests.yml
vendored
1
.github/workflows/server-mariadb-tests.yml
vendored
|
|
@ -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
|
||||
|
|
|
|||
1
.github/workflows/server-postgres-tests.yml
vendored
1
.github/workflows/server-postgres-tests.yml
vendored
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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']
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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');
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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%;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
67
frappe/tests/test_webform.py
Normal file
67
frappe/tests/test_webform.py
Normal 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")
|
||||
|
|
@ -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
|
||||
|
|
|
|||
6
frappe/www/_test/_test_webform.py
Normal file
6
frappe/www/_test/_test_webform.py
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
def webform_list_context(module):
|
||||
return {"get_list": get_webform_context_list}
|
||||
|
||||
|
||||
def get_webform_context_list():
|
||||
pass
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue