Merge branch 'rebrand-ui' of https://github.com/frappe/frappe into rebrand-ui

This commit is contained in:
Suraj Shetty 2021-01-29 13:06:14 +05:30
commit 33da252486
14 changed files with 490 additions and 327 deletions

View file

@ -30,7 +30,7 @@ context('Form', () => {
cy.visit('/app/contact/Test Form Contact 3');
cy.get('.prev-doc').should('be.visible').click();
cy.get('.msgprint-dialog .modal-body').contains('No further records').should('be.visible');
cy.get('.btn-modal-close:visible').click();
cy.hide_dialog();
cy.get('.next-doc').click();
cy.wait(200);
cy.contains('Test Form Contact 2').should('not.exist');

View file

@ -11,8 +11,7 @@ context('List View', () => {
cy.go_to_list('ToDo');
cy.get('.list-row-container:contains("Pending") .list-row-checkbox').click({ multiple: true, force: true });
cy.get('.actions-btn-group button').contains('Actions').should('be.visible').click();
cy.wait(300);
cy.get('.dropdown-menu li:visible').should('have.length', 8).each((el, index) => {
cy.get('.dropdown-menu li:visible').should('have.length', 9).each((el, index) => {
cy.wrap(el).contains(actions[index]);
}).then((elements) => {
cy.server();

View file

@ -15,7 +15,7 @@ context('List View Settings', () => {
cy.get('.list-count').should('contain', "20 of");
cy.get('.menu-btn-group button').click();
cy.get('.dropdown-menu li').filter(':visible').contains('List Settings').click();
cy.get('.modal-dialog').should('contain', 'List Settings');
cy.get('.modal-dialog').should('contain', 'DocType Settings');
cy.get('input[data-fieldname="disable_count"]').check({ force: true });
cy.get('input[data-fieldname="disable_sidebar_stats"]').check({ force: true });

View file

@ -233,7 +233,9 @@ export default class GridRow {
</div>
`)
.appendTo($('<div class="col col-xs-1"></div>').appendTo(this.row))
.on('click', function() { me.toggle_view(); return false; });
.on('click', function() {
me.toggle_view(); return false;
});
if(this.is_too_small()) {
// narrow

View file

@ -551,7 +551,7 @@ frappe.ui.form.Layout = Class.extend({
frappe.throw(__('Invalid "depends_on" expression'));
}
} else if (expression.substr(0,3)=='fn:' && this.frm) {
} else if (expression.substr(0, 3)=='fn:' && this.frm) {
out = this.frm.script_manager.trigger(expression.substr(3), this.doctype, this.docname);
} else {
var value = doc[expression];

View file

@ -1,38 +1,50 @@
frappe.ui.get_print_settings = function (pdf, callback, letter_head, pick_columns) {
frappe.ui.get_print_settings = function(
pdf,
callback,
letter_head,
pick_columns
) {
var print_settings = locals[":Print Settings"]["Print Settings"];
var default_letter_head = locals[":Company"] && frappe.defaults.get_default('company')
? locals[":Company"][frappe.defaults.get_default('company')]["default_letter_head"]
: '';
var default_letter_head =
locals[":Company"] && frappe.defaults.get_default("company")
? locals[":Company"][frappe.defaults.get_default("company")][
"default_letter_head"
]
: "";
var columns = [{
fieldtype: "Check",
fieldname: "with_letter_head",
label: __("With Letter head")
}, {
fieldtype: "Select",
fieldname: "letter_head",
label: __("Letter Head"),
depends_on: "with_letter_head",
options: frappe.boot.letter_heads,
default: letter_head || default_letter_head
}, {
fieldtype: "Select",
fieldname: "orientation",
label: __("Orientation"),
options: [
{ "value": "Landscape", "label": __("Landscape") },
{ "value": "Portrait", "label": __("Portrait") }
],
default: "Landscape"
}];
var columns = [
{
fieldtype: "Check",
fieldname: "with_letter_head",
label: __("With Letter head")
},
{
fieldtype: "Select",
fieldname: "letter_head",
label: __("Letter Head"),
depends_on: "with_letter_head",
options: frappe.boot.letter_heads,
default: letter_head || default_letter_head
},
{
fieldtype: "Select",
fieldname: "orientation",
label: __("Orientation"),
options: [
{ value: "Landscape", label: __("Landscape") },
{ value: "Portrait", label: __("Portrait") }
],
default: "Landscape"
}
];
if (pick_columns) {
columns.push(
{
label: __("Pick Columns"),
fieldtype: "Check",
fieldname: "pick_columns",
fieldname: "pick_columns"
},
{
label: __("Select Columns"),
@ -48,18 +60,22 @@ frappe.ui.get_print_settings = function (pdf, callback, letter_head, pick_column
);
}
return frappe.prompt(columns, function (data) {
var data = $.extend(print_settings, data);
if (!data.with_letter_head) {
data.letter_head = null;
}
if (data.letter_head) {
data.letter_head = frappe.boot.letter_heads[print_settings.letter_head];
}
callback(data);
}, __("Print Settings"));
}
return frappe.prompt(
columns,
function(data) {
var data = $.extend(print_settings, data);
if (!data.with_letter_head) {
data.letter_head = null;
}
if (data.letter_head) {
data.letter_head =
frappe.boot.letter_heads[print_settings.letter_head];
}
callback(data);
},
__("Print Settings")
);
};
// qz tray connection wrapper
// - allows active and inactive connections to resolve regardless
@ -67,62 +83,87 @@ frappe.ui.get_print_settings = function (pdf, callback, letter_head, pick_column
// - if connection fails, catch the reject, fire the mimetype launcher
// - after mimetype launcher is fired, try to connect 3 more times
// - display success/fail message to user
frappe.ui.form.qz_connect = function () {
return new Promise(function (resolve, reject) {
frappe.ui.form.qz_connect = function() {
return new Promise(function(resolve, reject) {
frappe.ui.form.qz_init().then(() => {
if (qz.websocket.isActive()) { // if already active, resolve immediately
if (qz.websocket.isActive()) {
// if already active, resolve immediately
// frappe.show_alert({message: __('QZ Tray Connection Active!'), indicator: 'green'});
resolve();
} else {
// try to connect once before firing the mimetype launcher
frappe.show_alert({
message: __('Attempting Connection to QZ Tray...'),
indicator: 'blue'
message: __("Attempting Connection to QZ Tray..."),
indicator: "blue"
});
qz.websocket.connect().then(() => {
frappe.show_alert({
message: __('Connected to QZ Tray!'),
indicator: 'green'
});
resolve();
}, function retry(err) {
if (err.message === 'Unable to establish connection with QZ') {
// if a connect was not successful, launch the mimetype, try 3 more times
qz.websocket.connect().then(
() => {
frappe.show_alert({
message: __('Attempting to launch QZ Tray...'),
indicator: 'blue'
}, 14);
window.location.assign("qz:launch");
qz.websocket.connect({
retries: 3,
delay: 1
}).then(() => {
frappe.show_alert({
message: __('Connected to QZ Tray!'),
indicator: 'green'
});
resolve();
},
() => {
frappe.throw(__('Error connecting to QZ Tray Application...<br><br> You need to have QZ Tray application installed and running, to use the Raw Print feature.<br><br><a target="_blank" href="https://qz.io/download/">Click here to Download and install QZ Tray</a>.<br> <a target="_blank" href="https://erpnext.com/docs/user/manual/en/setting-up/print/raw-printing">Click here to learn more about Raw Printing</a>.'));
reject();
message: __("Connected to QZ Tray!"),
indicator: "green"
});
} else {
frappe.show_alert({
message: 'QZ Tray ' + err.toString(),
indicator: 'red'
}, 14);
reject();
resolve();
},
function retry(err) {
if (
err.message ===
"Unable to establish connection with QZ"
) {
// if a connect was not successful, launch the mimetype, try 3 more times
frappe.show_alert(
{
message: __(
"Attempting to launch QZ Tray..."
),
indicator: "blue"
},
14
);
window.location.assign("qz:launch");
qz.websocket
.connect({
retries: 3,
delay: 1
})
.then(
() => {
frappe.show_alert({
message: __(
"Connected to QZ Tray!"
),
indicator: "green"
});
resolve();
},
() => {
frappe.throw(
__(
'Error connecting to QZ Tray Application...<br><br> You need to have QZ Tray application installed and running, to use the Raw Print feature.<br><br><a target="_blank" href="https://qz.io/download/">Click here to Download and install QZ Tray</a>.<br> <a target="_blank" href="https://erpnext.com/docs/user/manual/en/setting-up/print/raw-printing">Click here to learn more about Raw Printing</a>.'
)
);
reject();
}
);
} else {
frappe.show_alert(
{
message: "QZ Tray " + err.toString(),
indicator: "red"
},
14
);
reject();
}
}
});
);
}
});
});
}
};
frappe.ui.form.qz_init = function () {
frappe.ui.form.qz_init = function() {
// Initializing qz tray library
return new Promise((resolve) => {
return new Promise(resolve => {
if (typeof qz === "object" && typeof qz.version === "string") {
// resolve immediately if already Initialized
resolve();
@ -131,11 +172,11 @@ frappe.ui.form.qz_init = function () {
"/assets/frappe/node_modules/js-sha256/build/sha256.min.js",
"/assets/frappe/node_modules/qz-tray/qz-tray.js"
];
frappe.require(qz_required_assets,() => {
frappe.require(qz_required_assets, () => {
qz.api.setPromiseType(function promise(resolver) {
return new Promise(resolver);
});
qz.api.setSha256Type(function (data) {
qz.api.setSha256Type(function(data) {
// Codacy fix
/*global sha256*/
return sha256(data);
@ -144,33 +185,39 @@ frappe.ui.form.qz_init = function () {
});
// note 'frappe.require' does not have callback on fail. Hence, any failure cannot be communicated to the user.
}
});
}
};
frappe.ui.form.qz_get_printer_list = function () {
frappe.ui.form.qz_get_printer_list = function() {
// returns the list of printers that are available to the QZ Tray
return frappe.ui.form.qz_connect().then(function () {
return qz.printers.find();
}).then((data) => {
return data;
}).catch((err) => {
frappe.ui.form.qz_fail(err);
});
}
return frappe.ui.form
.qz_connect()
.then(function() {
return qz.printers.find();
})
.then(data => {
return data;
})
.catch(err => {
frappe.ui.form.qz_fail(err);
});
};
frappe.ui.form.qz_success = function () {
frappe.ui.form.qz_success = function() {
// notify qz successful print
frappe.show_alert({
message: __('Print Sent to the printer!'),
indicator: 'green'
message: __("Print Sent to the printer!"),
indicator: "green"
});
}
};
frappe.ui.form.qz_fail = function (e) {
frappe.ui.form.qz_fail = function(e) {
// notify qz errors
frappe.show_alert({
message: __("QZ Tray Failed: ") + e.toString(),
indicator: 'red'
}, 20);
}
frappe.show_alert(
{
message: __("QZ Tray Failed: ") + e.toString(),
indicator: "red"
},
20
);
};

View file

@ -249,7 +249,7 @@ frappe.ui.form.Toolbar = class Toolbar {
}, true);
this.print_icon = this.page.add_action_icon("printer", function() {
me.frm.print_doc();
},'', __("Print"));
}, '', __("Print"));
}
}

View file

@ -1114,7 +1114,7 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList {
}
// link, let the event be handled via set_route
if ($target.is("a")) { return; }
if ($target.is("a")) return;
// clicked on the row, open form
const $row = $(e.currentTarget);

View file

@ -1,4 +1,4 @@
frappe.provide('frappe.views');
frappe.provide("frappe.views");
frappe.views.ListViewSelect = class ListViewSelect {
constructor(opts) {
@ -14,110 +14,112 @@ frappe.views.ListViewSelect = class ListViewSelect {
action,
true,
null,
this.icon_map[view] || 'list'
this.icon_map[view] || "list"
);
$el.parent().attr('data-view', view)
$el.parent().attr("data-view", view);
}
set_current_view() {
this.current_view = 'List';
this.current_view = "List";
const route = frappe.get_route();
const view_name = frappe.utils.to_title_case(route[2] || '');
const view_name = frappe.utils.to_title_case(route[2] || "");
if (route.length > 2 && frappe.views.view_modes.includes(view_name)) {
this.current_view = view_name;
if (this.current_view === 'Kanban') {
if (this.current_view === "Kanban") {
this.kanban_board = route[3];
} else if (this.current_view === 'Inbox') {
} else if (this.current_view === "Inbox") {
this.email_account = route[3];
}
}
}
set_route(view, calendar_name) {
const route = [this.slug(), 'view', view];
const route = [this.slug(), "view", view];
if (calendar_name) route.push(calendar_name);
frappe.set_route(route);
}
setup_views() {
const views = {
'List': {
List: {
condition: true,
action: () => this.set_route('list')
action: () => this.set_route("list")
},
'Report': {
Report: {
condition: true,
action: () => this.set_route('report'),
action: () => this.set_route("report"),
current_view_handler: () => {
const reports = this.get_reports();
this.setup_dropdown_in_sidebar(
'Report',
reports,
{
label: __('Report Builder'),
action: () => this.set_route('report')
}
);
}
},
'Dashboard': {
condition: true,
action: () => this.set_route('dashboard')
},
'Calendar': {
condition: frappe.views.calendar[this.doctype],
action: () => this.set_route('calendar', 'default'),
current_view_handler: () => {
this.get_calendars().then(calendars => {
this.setup_dropdown_in_sidebar(
'Calendar',
calendars,
);
this.setup_dropdown_in_sidebar("Report", reports, {
label: __("Report Builder"),
action: () => this.set_route("report")
});
}
},
'Gantt': {
condition: frappe.views.calendar[this.doctype],
action: () => this.set_route('gantt')
Dashboard: {
condition: true,
action: () => this.set_route("dashboard")
},
'Inbox': {
condition: this.doctype === "Communication" && frappe.boot.email_accounts.length,
action: () => this.set_route('inbox'),
Calendar: {
condition: frappe.views.calendar[this.doctype],
action: () => this.set_route("calendar", "default"),
current_view_handler: () => {
this.get_calendars().then(calendars => {
this.setup_dropdown_in_sidebar("Calendar", calendars);
});
}
},
Gantt: {
condition: frappe.views.calendar[this.doctype],
action: () => this.set_route("gantt")
},
Inbox: {
condition:
this.doctype === "Communication" &&
frappe.boot.email_accounts.length,
action: () => this.set_route("inbox"),
current_view_handler: () => {
const accounts = this.get_email_accounts();
let default_action;
if (has_common(frappe.user_roles, ["System Manager", "Administrator"])) {
if (
has_common(frappe.user_roles, [
"System Manager",
"Administrator"
])
) {
default_action = {
label: __('New Email Account'),
label: __("New Email Account"),
action: () => frappe.new_doc("Email Account")
}
};
}
this.setup_dropdown_in_sidebar(
'Inbox',
"Inbox",
accounts,
default_action,
default_action
);
}
},
'Image': {
Image: {
condition: this.list_view.meta.image_field,
action: () => this.set_route('image')
action: () => this.set_route("image")
},
'Tree': {
condition: frappe.treeview_settings[this.doctype] || frappe.get_meta(this.doctype).is_tree,
action: () => this.set_route('tree')
Tree: {
condition:
frappe.treeview_settings[this.doctype] ||
frappe.get_meta(this.doctype).is_tree,
action: () => this.set_route("tree")
},
'Kanban': {
Kanban: {
condition: true,
action: () => this.setup_kanban_boards(),
current_view_handler: () => {
frappe.views.KanbanView.get_kanbans(this.doctype).then((kanbans) =>
this.setup_kanban_switcher(kanbans)
frappe.views.KanbanView.get_kanbans(this.doctype).then(
kanbans => this.setup_kanban_switcher(kanbans)
);
}
},
}
}
};
frappe.views.view_modes.forEach(view => {
if (this.current_view !== view && views[view].condition) {
@ -125,71 +127,78 @@ frappe.views.ListViewSelect = class ListViewSelect {
}
if (this.current_view == view) {
views[view].current_view_handler && views[view].current_view_handler();
views[view].current_view_handler &&
views[view].current_view_handler();
}
});
}
setup_dropdown_in_sidebar(view, items, default_action) {
if (!this.sidebar) return;
const views_wrapper = this.sidebar.sidebar.find('.views-section');
views_wrapper.find('.sidebar-label').html(`${__(view)}`);
const $dropdown = views_wrapper.find('.views-dropdown');
const views_wrapper = this.sidebar.sidebar.find(".views-section");
views_wrapper.find(".sidebar-label").html(`${__(view)}`);
const $dropdown = views_wrapper.find(".views-dropdown");
let placeholder = `Select ${view}`;
let html = ``;
if (!items || !items.length) {
html = `<div class="empty-state">
${__('No {} Found', [view])}
${__("No {} Found", [view])}
</div>`;
} else {
items.map(item => {
if (item.name == this.get_page_name()) {
placeholder = item.name;
}
html += `<li><a class="dropdown-item" href="${item.route}">${item.name}</a></li>`;
html += `<li><a class="dropdown-item" href="${item.route}">${
item.name
}</a></li>`;
});
}
views_wrapper.find('.selected-view').html(placeholder);
views_wrapper.find(".selected-view").html(placeholder);
if (default_action) {
views_wrapper.find('.sidebar-action a').html(default_action.label);
views_wrapper.find('.sidebar-action a').click(() => default_action.action());
views_wrapper.find(".sidebar-action a").html(default_action.label);
views_wrapper
.find(".sidebar-action a")
.click(() => default_action.action());
}
$dropdown.html(html);
views_wrapper.removeClass('hide');
views_wrapper.removeClass("hide");
}
setup_kanban_switcher(kanbans) {
const kanban_switcher =
this.page.add_custom_button_group(
__('Select Kanban'), null, this.list_view.$filter_section
);
const kanban_switcher = this.page.add_custom_button_group(
__("Select Kanban"),
null,
this.list_view.$filter_section
);
kanbans.map(k => {
this.page.add_custom_menu_item(
kanban_switcher,
k.name,
() => this.set_route('kanban', k.name),
() => this.set_route("kanban", k.name),
false
);
});
this.page.add_custom_menu_item(
kanban_switcher,
__('Create New Kanban Board'),
__("Create New Kanban Board"),
() => frappe.views.KanbanView.show_kanban_dialog(this.doctype),
true
);
}
get_page_name() {
return frappe.utils.to_title_case(frappe.get_route().slice(-1)[0] || '')
return frappe.utils.to_title_case(
frappe.get_route().slice(-1)[0] || ""
);
}
get_reports() {
@ -197,18 +206,24 @@ frappe.views.ListViewSelect = class ListViewSelect {
let added = [];
let reports_to_add = [];
let add_reports = (reports) => {
reports.map((r) => {
let add_reports = reports => {
reports.map(r => {
if (!r.ref_doctype || r.ref_doctype == this.doctype) {
const report_type = r.report_type === 'Report Builder' ?
`/app/list/${r.ref_doctype}/report` : 'query-report';
const report_type =
r.report_type === "Report Builder"
? `/app/list/${r.ref_doctype}/report`
: "query-report";
const route = r.route || report_type + '/' + (r.title || r.name);
const route =
r.route || report_type + "/" + (r.title || r.name);
if (added.indexOf(route) === -1) {
// don't repeat
added.push(route);
reports_to_add.push({name: r.title || r.name, route: route});
reports_to_add.push({
name: r.title || r.name,
route: route
});
}
}
});
@ -220,7 +235,10 @@ frappe.views.ListViewSelect = class ListViewSelect {
}
// Sort reports alphabetically
var reports = Object.values(frappe.boot.user.all_reports).sort((a,b) => a.title.localeCompare(b.title)) || [];
var reports =
Object.values(frappe.boot.user.all_reports).sort((a, b) =>
a.title.localeCompare(b.title)
) || [];
// from specially tagged reports
add_reports(reports);
@ -229,10 +247,17 @@ frappe.views.ListViewSelect = class ListViewSelect {
}
setup_kanban_boards() {
const last_opened_kanban = frappe.model.user_settings[this.doctype]['Kanban']
&& frappe.model.user_settings[this.doctype]['Kanban'].last_kanban_board;
const last_opened_kanban =
frappe.model.user_settings[this.doctype]["Kanban"] &&
frappe.model.user_settings[this.doctype]["Kanban"]
.last_kanban_board;
if (last_opened_kanban) {
frappe.set_route('list', this.doctype, 'kanban', last_opened_kanban);
frappe.set_route(
"list",
this.doctype,
"kanban",
last_opened_kanban
);
} else {
frappe.views.KanbanView.show_kanban_dialog(this.doctype, true);
}
@ -242,35 +267,50 @@ frappe.views.ListViewSelect = class ListViewSelect {
const doctype = this.doctype;
let calendars = [];
return frappe.db.get_list('Calendar View', {
filters: {
reference_doctype: doctype
}
}).then(result => {
if (!(result && Array.isArray(result) && result.length)) return;
return frappe.db
.get_list("Calendar View", {
filters: {
reference_doctype: doctype
}
})
.then(result => {
if (!(result && Array.isArray(result) && result.length)) return;
if (frappe.views.calendar[this.doctype]) {
// has standard calendar view
calendars.push({
name: 'Default',
route: `/app/${this.slug()}/view/calendar/default`
if (frappe.views.calendar[this.doctype]) {
// has standard calendar view
calendars.push({
name: "Default",
route: `/app/${this.slug()}/view/calendar/default`
});
}
result.map(calendar => {
calendars.push({
name: calendar.name,
route: `/app/${this.slug()}/view/calendar/${
calendar.name
}`
});
});
}
result.map(calendar => {
calendars.push({name: calendar.name, route: `/app/${this.slug()}/view/calendar/${calendar.name}`});
});
return calendars;
});
return calendars;
});
}
get_email_accounts() {
let accounts_to_add = [];
let accounts = frappe.boot.email_accounts;
accounts.forEach(account => {
let email_account = (account.email_id == "All Accounts") ? "All Accounts" : account.email_account;
let email_account =
account.email_id == "All Accounts"
? "All Accounts"
: account.email_account;
let route = `/app/communication/inbox/${email_account}`;
let display_name = ["All Accounts", "Sent Mail", "Spam", "Trash"].includes(account.email_id)
let display_name = [
"All Accounts",
"Sent Mail",
"Spam",
"Trash"
].includes(account.email_id)
? __(account.email_id)
: account.email_account;
@ -286,4 +326,4 @@ frappe.views.ListViewSelect = class ListViewSelect {
slug() {
return frappe.router.slug(frappe.router.doctype_layout || this.doctype);
}
}
};

View file

@ -7,7 +7,12 @@ $.extend(frappe.model, {
new_names: {},
new_name_count: {},
get_new_doc: function(doctype, parent_doc, parentfield, with_mandatory_children) {
get_new_doc: function(
doctype,
parent_doc,
parentfield,
with_mandatory_children
) {
frappe.provide("locals." + doctype);
var doc = {
docstatus: 0,
@ -19,13 +24,13 @@ $.extend(frappe.model, {
};
frappe.model.set_default_values(doc, parent_doc);
if(parent_doc) {
if (parent_doc) {
$.extend(doc, {
parent: parent_doc.name,
parentfield: parentfield,
parenttype: parent_doc.doctype,
parenttype: parent_doc.doctype
});
if(!parent_doc[parentfield]) parent_doc[parentfield] = [];
if (!parent_doc[parentfield]) parent_doc[parentfield] = [];
doc.idx = parent_doc[parentfield].length + 1;
parent_doc[parentfield].push(doc);
} else {
@ -34,7 +39,7 @@ $.extend(frappe.model, {
frappe.model.add_to_locals(doc);
if(with_mandatory_children) {
if (with_mandatory_children) {
frappe.model.create_mandatory_children(doc);
}
@ -43,26 +48,31 @@ $.extend(frappe.model, {
}
// set the name if called from a link field
if(frappe.route_options && frappe.route_options.name_field) {
if (frappe.route_options && frappe.route_options.name_field) {
var meta = frappe.get_meta(doctype);
// set title field / name as name
if(meta.autoname && meta.autoname.indexOf("field:")!==-1) {
if (meta.autoname && meta.autoname.indexOf("field:") !== -1) {
doc[meta.autoname.substr(6)] = frappe.route_options.name_field;
} else if(meta.title_field) {
} else if (meta.title_field) {
doc[meta.title_field] = frappe.route_options.name_field;
}
delete frappe.route_options.name_field;
}
// set route options
if(frappe.route_options && !doc.parent) {
if (frappe.route_options && !doc.parent) {
$.each(frappe.route_options, function(fieldname, value) {
var df = frappe.meta.has_field(doctype, fieldname);
if(df && in_list(['Link', 'Data', 'Select', 'Dynamic Link'], df.fieldtype) && !df.no_copy) {
doc[fieldname]=value;
if (
df &&
in_list(
["Link", "Data", "Select", "Dynamic Link"],
df.fieldtype
) &&
!df.no_copy
) {
doc[fieldname] = value;
}
});
frappe.route_options = null;
@ -72,13 +82,17 @@ $.extend(frappe.model, {
},
make_new_doc_and_get_name: function(doctype, with_mandatory_children) {
return frappe.model.get_new_doc(doctype, null, null, with_mandatory_children).name;
return frappe.model.get_new_doc(
doctype,
null,
null,
with_mandatory_children
).name;
},
get_new_name: function(doctype) {
var cnt = frappe.model.new_name_count
if(!cnt[doctype])
cnt[doctype] = 0;
var cnt = frappe.model.new_name_count;
if (!cnt[doctype]) cnt[doctype] = 0;
cnt[doctype]++;
return frappe.router.slug(`new-${doctype}-${cnt[doctype]}`);
},
@ -87,22 +101,27 @@ $.extend(frappe.model, {
var doctype = doc.doctype;
var docfields = frappe.meta.get_docfields(doctype);
var updated = [];
for (var fid=0;fid<docfields.length;fid++) {
for (var fid = 0; fid < docfields.length; fid++) {
var f = docfields[fid];
if(!in_list(frappe.model.no_value_type, f.fieldtype) && doc[f.fieldname]==null) {
if (
!in_list(frappe.model.no_value_type, f.fieldtype) &&
doc[f.fieldname] == null
) {
if (f.no_default) continue;
var v = frappe.model.get_default_value(f, doc, parent_doc);
if (v) {
if(in_list(["Int", "Check"], f.fieldtype))
v = cint(v);
else if(in_list(["Currency", "Float"], f.fieldtype))
if (in_list(["Int", "Check"], f.fieldtype)) v = cint(v);
else if (in_list(["Currency", "Float"], f.fieldtype))
v = flt(v);
doc[f.fieldname] = v;
updated.push(f.fieldname);
} else if(f.fieldtype == "Select" && f.options && typeof f.options === 'string'
&& !in_list(["[Select]", "Loading..."], f.options)) {
} else if (
f.fieldtype == "Select" &&
f.options &&
typeof f.options === "string" &&
!in_list(["[Select]", "Loading..."], f.options)
) {
doc[f.fieldname] = f.options.split("\n")[0];
}
}
@ -112,11 +131,11 @@ $.extend(frappe.model, {
create_mandatory_children: function(doc) {
var meta = frappe.get_meta(doc.doctype);
if(meta && meta.istable) return;
if (meta && meta.istable) return;
// create empty rows for mandatory table fields
frappe.meta.get_docfields(doc.doctype).forEach(function(df) {
if(df.fieldtype==='Table' && df.reqd) {
if (df.fieldtype === "Table" && df.reqd) {
frappe.model.add_child(doc, df.fieldname);
}
});
@ -128,85 +147,106 @@ $.extend(frappe.model, {
let allowed_records = [];
let default_doc = null;
let value = null;
if(user_permissions) {
({allowed_records, default_doc} = frappe.perm.filter_allowed_docs_for_doctype(user_permissions[df.options], doc.doctype));
if (user_permissions) {
({
allowed_records,
default_doc
} = frappe.perm.filter_allowed_docs_for_doctype(
user_permissions[df.options],
doc.doctype
));
}
var meta = frappe.get_meta(doc.doctype);
var has_user_permissions = (df.fieldtype==="Link"
&& !$.isEmptyObject(user_permissions)
&& df.ignore_user_permissions != 1
&& allowed_records.length);
var has_user_permissions =
df.fieldtype === "Link" &&
!$.isEmptyObject(user_permissions) &&
df.ignore_user_permissions != 1 &&
allowed_records.length;
// don't set defaults for "User" link field using User Permissions!
if (df.fieldtype==="Link" && df.options!=="User") {
if (df.fieldtype === "Link" && df.options !== "User") {
// If user permission has Is Default enabled or single-user permission has found against respective doctype.
if (has_user_permissions && default_doc) {
value = default_doc;
} else {
// 2 - look in user defaults
if(!df.ignore_user_permissions) {
var user_defaults = frappe.defaults.get_user_defaults(df.options);
if (user_defaults && user_defaults.length===1) {
if (!df.ignore_user_permissions) {
var user_defaults = frappe.defaults.get_user_defaults(
df.options
);
if (user_defaults && user_defaults.length === 1) {
// Use User Permission value when only when it has a single value
user_default = user_defaults[0];
}
} else if (!user_default) {
user_default = frappe.defaults.get_user_default(
df.fieldname
);
} else if (
!user_default &&
df.remember_last_selected_value &&
frappe.boot.user.last_selected_values
) {
user_default =
frappe.boot.user.last_selected_values[df.options];
}
else if (!user_default) {
user_default = frappe.defaults.get_user_default(df.fieldname);
}
else if(!user_default && df.remember_last_selected_value && frappe.boot.user.last_selected_values) {
user_default = frappe.boot.user.last_selected_values[df.options];
}
var is_allowed_user_default = user_default &&
(!has_user_permissions || allowed_records.includes(user_default));
var is_allowed_user_default =
user_default &&
(!has_user_permissions ||
allowed_records.includes(user_default));
// is this user default also allowed as per user permissions?
if (is_allowed_user_default) {
value = user_default;
}
}
}
// 3 - look in default of docfield
if (!value || df['default']) {
const default_val = String(df['default']);
if (default_val == "__user" || default_val.toLowerCase() == "user") {
if (!value || df["default"]) {
const default_val = String(df["default"]);
if (
default_val == "__user" ||
default_val.toLowerCase() == "user"
) {
value = frappe.session.user;
} else if (default_val == "user_fullname") {
value = frappe.session.user_fullname;
} else if (default_val == "Today") {
value = frappe.datetime.get_today();
} else if ((default_val || "").toLowerCase() === "now") {
value = frappe.datetime.now_datetime();
} else if (default_val[0]===":") {
var boot_doc = frappe.model.get_default_from_boot_docs(df, doc, parent_doc);
var is_allowed_boot_doc = !has_user_permissions || allowed_records.includes(boot_doc);
} else if (default_val[0] === ":") {
var boot_doc = frappe.model.get_default_from_boot_docs(
df,
doc,
parent_doc
);
var is_allowed_boot_doc =
!has_user_permissions || allowed_records.includes(boot_doc);
if (is_allowed_boot_doc) {
value = boot_doc;
}
} else if (df.fieldname===meta.title_field) {
} else if (df.fieldname === meta.title_field) {
// ignore defaults for title field
value = "";
} else {
// is this default value is also allowed as per user permissions?
var is_allowed_default = !has_user_permissions || allowed_records.includes(df.default);
if (df.fieldtype!=="Link" || df.options==="User" || is_allowed_default) {
var is_allowed_default =
!has_user_permissions ||
allowed_records.includes(df.default);
if (
df.fieldtype !== "Link" ||
df.options === "User" ||
is_allowed_default
) {
value = df["default"];
}
}
} else if (df.fieldtype=="Time") {
} else if (df.fieldtype == "Time") {
value = frappe.datetime.now_time();
}
@ -218,14 +258,19 @@ $.extend(frappe.model, {
get_default_from_boot_docs: function(df, doc, parent_doc) {
// set default from partial docs passed during boot like ":User"
if(frappe.get_list(df["default"]).length > 0) {
var ref_fieldname = df["default"].slice(1).toLowerCase().replace(" ", "_");
var ref_value = parent_doc ?
parent_doc[ref_fieldname] :
frappe.defaults.get_user_default(ref_fieldname);
var ref_doc = ref_value ? frappe.get_doc(df["default"], ref_value) : null;
if (frappe.get_list(df["default"]).length > 0) {
var ref_fieldname = df["default"]
.slice(1)
.toLowerCase()
.replace(" ", "_");
var ref_value = parent_doc
? parent_doc[ref_fieldname]
: frappe.defaults.get_user_default(ref_fieldname);
var ref_doc = ref_value
? frappe.get_doc(df["default"], ref_value)
: null;
if(ref_doc && ref_doc[df.fieldname]) {
if (ref_doc && ref_doc[df.fieldname]) {
return ref_doc[df.fieldname];
}
}
@ -233,9 +278,10 @@ $.extend(frappe.model, {
add_child: function(parent_doc, doctype, parentfield, idx) {
// if given doc, fieldname only
if(arguments.length===2) {
if (arguments.length === 2) {
parentfield = doctype;
doctype = frappe.meta.get_field(parent_doc.doctype, parentfield).options;
doctype = frappe.meta.get_field(parent_doc.doctype, parentfield)
.options;
}
// create row doc
@ -245,9 +291,11 @@ $.extend(frappe.model, {
child.idx = idx;
// renum for fraction
if(idx !== cint(idx)) {
var sorted = parent_doc[parentfield].sort(function(a, b) { return a.idx - b.idx; });
for(var i=0, j=sorted.length; i<j; i++) {
if (idx !== cint(idx)) {
var sorted = parent_doc[parentfield].sort(function(a, b) {
return a.idx - b.idx;
});
for (var i = 0, j = sorted.length; i < j; i++) {
var d = sorted[i];
d.idx = i + 1;
}
@ -259,22 +307,38 @@ $.extend(frappe.model, {
},
copy_doc: function(doc, from_amend, parent_doc, parentfield) {
var no_copy_list = ['name','amended_from','amendment_date','cancel_reason'];
var newdoc = frappe.model.get_new_doc(doc.doctype, parent_doc, parentfield);
var no_copy_list = [
"name",
"amended_from",
"amendment_date",
"cancel_reason"
];
var newdoc = frappe.model.get_new_doc(
doc.doctype,
parent_doc,
parentfield
);
for(var key in doc) {
for (var key in doc) {
// dont copy name and blank fields
var df = frappe.meta.get_docfield(doc.doctype, key);
if (df && key.substr(0, 2) != '__'
&& !in_list(no_copy_list, key)
&& !(df && (!from_amend && cint(df.no_copy) == 1))) {
if (
df &&
key.substr(0, 2) != "__" &&
!in_list(no_copy_list, key) &&
!(df && (!from_amend && cint(df.no_copy) == 1))
) {
var value = doc[key] || [];
if (frappe.model.table_fields.includes(df.fieldtype)) {
for (var i = 0, j = value.length; i < j; i++) {
var d = value[i];
frappe.model.copy_doc(d, from_amend, newdoc, df.fieldname);
frappe.model.copy_doc(
d,
from_amend,
newdoc,
df.fieldname
);
}
} else {
newdoc[key] = doc[key];
@ -287,28 +351,31 @@ $.extend(frappe.model, {
newdoc.__islocal = 1;
newdoc.docstatus = 0;
newdoc.owner = user;
newdoc.creation = '';
newdoc.creation = "";
newdoc.modified_by = user;
newdoc.modified = '';
newdoc.modified = "";
return newdoc;
},
open_mapped_doc: function(opts) {
if (opts.frm && opts.frm.doc.__unsaved) {
frappe.throw(__("You have unsaved changes in this form. Please save before you continue."));
frappe.throw(
__(
"You have unsaved changes in this form. Please save before you continue."
)
);
} else if (!opts.source_name && opts.frm) {
opts.source_name = opts.frm.doc.name;
// Allow opening a mapped doc without a source document name
// Allow opening a mapped doc without a source document name
} else if (!opts.frm) {
opts.source_name = null;
}
return frappe.call({
type: "POST",
method: 'frappe.model.mapper.make_mapped_doc',
method: "frappe.model.mapper.make_mapped_doc",
args: {
method: opts.method,
source_name: opts.source_name,
@ -316,41 +383,45 @@ $.extend(frappe.model, {
selected_children: opts.frm ? opts.frm.get_selected() : null
},
freeze: true,
freeze_message: opts.freeze_message || '',
freeze_message: opts.freeze_message || "",
callback: function(r) {
if(!r.exc) {
if (!r.exc) {
frappe.model.sync(r.message);
if(opts.run_link_triggers) {
frappe.get_doc(r.message.doctype, r.message.name).__run_link_triggers = true;
if (opts.run_link_triggers) {
frappe.get_doc(
r.message.doctype,
r.message.name
).__run_link_triggers = true;
}
frappe.set_route("Form", r.message.doctype, r.message.name);
}
}
})
});
}
});
frappe.create_routes = {};
frappe.new_doc = function (doctype, opts, init_callback) {
if (doctype === 'File') {
frappe.new_doc = function(doctype, opts, init_callback) {
if (doctype === "File") {
new frappe.ui.FileUploader({
folder: opts ? opts.folder : 'Home'
folder: opts ? opts.folder : "Home"
});
return;
}
return new Promise(resolve => {
if(opts && $.isPlainObject(opts)) {
if (opts && $.isPlainObject(opts)) {
frappe.route_options = opts;
}
frappe.model.with_doctype(doctype, function() {
if(frappe.create_routes[doctype]) {
frappe.set_route(frappe.create_routes[doctype])
if (frappe.create_routes[doctype]) {
frappe
.set_route(frappe.create_routes[doctype])
.then(() => resolve());
} else {
frappe.ui.form.make_quick_entry(doctype, null, init_callback)
frappe.ui.form
.make_quick_entry(doctype, null, init_callback)
.then(() => resolve());
}
});
});
}
};

View file

@ -426,7 +426,7 @@ frappe.router = {
// global functions for backward compatibility
frappe.get_route = () => frappe.router.current_route;
frappe.get_route_str = () => frappe.router.current_route.join('/');
frappe.set_route = function() { return frappe.router.set_route.apply(frappe.router, arguments) };
frappe.set_route = () => frappe.router.set_route.apply(frappe.router, arguments);
frappe.get_prev_route = function() {
if (frappe.route_history && frappe.route_history.length > 1) {

View file

@ -17,7 +17,7 @@ frappe.ui.Slide = class Slide {
// Make has to be called manually, to account for on-demand use cases
make() {
if (this.before_load) { this.before_load(this); }
if (this.before_load) this.before_load(this);
this.$body = $(`<div class="slide-body">
<div class="content text-center">
@ -68,7 +68,7 @@ frappe.ui.Slide = class Slide {
this.set_reqd_fields();
if (this.onload) { this.onload(this); }
if (this.onload) this.onload(this);
this.set_reqd_fields();
}
@ -333,7 +333,7 @@ frappe.ui.Slides = class Slides {
if (slide.done) this.completed++;
}
});
if (this.on_update) { this.on_update(this.completed, this.slides.length); }
if (this.on_update) this.on_update(this.completed, this.slides.length);
if (!this.unidirectional) this.bind_progress_dots();
}

View file

@ -273,8 +273,12 @@ frappe.ui.Tree = class {
});
node.$tree_link.hover(
function() { $(this).parent().addClass('hover-active') },
function() { $(this).parent().removeClass('hover-active') },
function() {
$(this).parent().addClass('hover-active')
},
function() {
$(this).parent().removeClass('hover-active')
},
)
}

View file

@ -82,7 +82,7 @@ frappe.views.FormFactory = class FormFactory extends frappe.views.Factory {
if (r && r['403']) return; // not permitted
if (!(locals[doctype] && locals[doctype][name])) {
if (name && name.substr(0,3)==='new') {
if (name && name.substr(0, 3) === 'new') {
this.render_new_doc(doctype, name, doctype_layout);
} else {
frappe.show_not_found(route);