@@ -1,22 +1,25 @@
frappe.provide("frappe.wiz");
frappe.provide("frappe.wiz .events");
frappe.provide("frappe.setup .events");
frappe.wiz = {
frappe.setup = {
slides: [],
events: {},
data: {},
utils: {},
remove_app_slides: [],
on: function(event, fn) {
if(!frappe.wiz.events[event]) {
frappe.wiz .events[event] = [];
if(!frappe.setup .events[event]) {
frappe.setup .events[event] = [];
}
frappe.wiz .events[event].push(fn);
frappe.setup .events[event].push(fn);
},
add_slide: function(slide) {
frappe.wiz .slides.push(slide);
frappe.setup .slides.push(slide);
},
run_event: function(event) {
$.each(frappe.wiz .events[event] || [], function(i, fn) {
$.each(frappe.setup .events[event] || [], function(i, fn) {
fn();
});
}
@@ -25,21 +28,21 @@ frappe.wiz = {
frappe.pages['setup-wizard'].on_page_load = function(wrapper) {
// setup page ui
$(".navbar:first").toggle(false);
$("body").css({"padding-top":"30px"});
var requires = ["/assets/frappe/css/animate.min.css"].concat(frappe.boot.setup_wizard_requires || []);
frappe.require(requires, function() {
frappe.wiz.run_event("before_load");
frappe.setup.run_event("before_load");
var wizard_settings = {
page_name: "setup-wizard",
parent: wrapper,
slides: frappe.wiz .slides,
slides: frappe.setup .slides,
title: __("Welcome")
}
frappe.wizard = new frappe.wiz .Wizard(wizard_settings);
frappe.wiz .run_event("after_load");
frappe.wizard = new frappe.setup .Wizard(wizard_settings);
frappe.setup .run_event("after_load");
// frappe.wizard.values = test_values_edu;
@@ -56,7 +59,7 @@ frappe.pages['setup-wizard'].on_page_show = function(wrapper) {
}
}
frappe.wiz .Wizard = Class.extend({
frappe.setup .Wizard = Class.extend({
init: function(opts) {
$.extend(this, opts);
this.make();
@@ -75,6 +78,7 @@ frappe.wiz.Wizard = Class.extend({
</div>', {html:html}))
},
show_working: function() {
$('header').find('.setup-wizard-brand').hide();
this.hide_current_slide();
frappe.set_route(this.page_name);
this.current_slide = {"$wrapper": this.get_message(this.working_html()).appendTo(this.parent)};
@@ -96,7 +100,7 @@ frappe.wiz.Wizard = Class.extend({
this.update_values();
if(!this.slide_dict[id]) {
this.slide_dict[id] = new frappe.wiz .WizardSlide($.extend(this.slides[id], {wiz:this, id:id}));
this.slide_dict[id] = new frappe.setup .WizardSlide($.extend(this.slides[id], {wiz:this, id:id}));
this.slide_dict[id].make();
}
@@ -147,8 +151,8 @@ frappe.wiz.Wizard = Class.extend({
args: {args: this.values},
callback: function(r) {
me.show_complete();
if(frappe.wiz .welcome_page) {
localStorage.setItem("session_last_route", frappe.wiz .welcome_page);
if(frappe.setup .welcome_page) {
localStorage.setItem("session_last_route", frappe.setup .welcome_page);
}
setTimeout(function() {
window.location = "/desk";
@@ -181,26 +185,27 @@ frappe.wiz.Wizard = Class.extend({
this.update_values();
frappe.wiz .slides = [];
frappe.wiz .run_event("before_load");
frappe.setup .slides = [];
frappe.setup .run_event("before_load");
// remove slides listed in remove_app_slides
var new_slides = [];
frappe.wiz .slides.forEach(function(slide) {
if(frappe.wiz .domain) {
frappe.setup .slides.forEach(function(slide) {
if(frappe.setup .domain) {
var domains = slide.domains;
if (domains.indexOf('all') !== -1 ||
domains.indexOf(frappe.wiz .domain.toLowerCase()) !== -1) {
domains.indexOf(frappe.setup .domain.toLowerCase()) !== -1) {
new_slides.push(slide);
}
} else {
new_slides.push(slide);
}
})
frappe.wiz.slides = new_slides;
this.slides = frappe.wiz.slides;
frappe.wiz.run_event("after_load");
frappe.setup.slides = new_slides;
this.slides = frappe.setup.slides;
frappe.setup.run_event("after_load");
// re-render all slides
this.slide_dict = {};
@@ -213,7 +218,7 @@ frappe.wiz.Wizard = Class.extend({
}
});
frappe.wiz .WizardSlide = Class.extend({
frappe.setup .WizardSlide = Class.extend({
init: function(opts) {
$.extend(this, opts);
this.$wrapper = $('<div class="slide-wrapper hidden"></div>')
@@ -224,6 +229,17 @@ frappe.wiz.WizardSlide = Class.extend({
var me = this;
if(this.$body) this.$body.remove();
var fields = JSON.parse(JSON.stringify(this.fields));
if(this.add_more) {
this.count = 1;
fields = fields.map(field => {
if(field.fieldname) field.fieldname += '_1';
if(field.label) field.label += ' 1';
return field;
});
}
if(this.before_load) {
this.before_load(this);
}
@@ -234,7 +250,6 @@ frappe.wiz.WizardSlide = Class.extend({
main_title:__(this.wiz.title),
step: this.id + 1,
name: this.name,
css_class: this.css_class || "",
slides_count: this.wiz.slides.length
})).appendTo(this.$wrapper);
@@ -242,7 +257,7 @@ frappe.wiz.WizardSlide = Class.extend({
if(this.fields) {
this.form = new frappe.ui.FieldGroup({
fields: this. fields,
fields: fields,
body: this.body,
no_submit_on_enter: true
});
@@ -251,18 +266,33 @@ frappe.wiz.WizardSlide = Class.extend({
$(this.body).html(this.html);
}
this.set_reqd_fields();
this.set_init_values();
this.make_prev_next_buttons();
if(this.add_more) this.bind_more_button();
var $primary_btn = this.$next ? this.$next : this.$complete;
this.bind_fields_to_next($primary_btn);
if(this.onload) {
this.onload(this);
}
this.reset_next($primary_btn);
this.focus_first_input();
},
set_reqd_fields: function() {
var dict = this.form.fields_dict;
this.reqd_fields = [];
Object.keys(dict).map(key => {
if(dict[key].df.reqd) {
this.reqd_fields.push(dict[key]);
}
});
},
set_init_values: function() {
var me = this;
// set values from frappe.wiz.values
// set values from frappe.setup .values
if(frappe.wizard.values && this.fields) {
this.fields.forEach(function(f) {
var value = frappe.wizard.values[f.fieldname];
@@ -284,6 +314,23 @@ frappe.wiz.WizardSlide = Class.extend({
return true;
},
bind_more_button: function() {
this.$more = this.$body.find('.more-btn');
this.$more.removeClass('hide')
.on('click', () => {
this.count++;
var fields = JSON.parse(JSON.stringify(this.fields));
this.form.add_fields(fields.map(field => {
if(field.fieldname) field.fieldname += '_' + this.count;
if(field.label) field.label += ' ' + this.count;
return field;
}));
if(this.count === this.max_count) {
this.$more.addClass('hide');
}
});
},
make_prev_next_buttons: function() {
var me = this;
@@ -311,7 +358,7 @@ frappe.wiz.WizardSlide = Class.extend({
.click(this.next_or_complete.bind(this));
}
//setup mousefree navigation
// setup mousefree navigation
this.$body.on('keypress', function(e) {
if(e.which === 13) {
var $target = $(e.target);
@@ -326,6 +373,14 @@ frappe.wiz.WizardSlide = Class.extend({
}
});
},
bind_fields_to_next: function($primary_btn) {
var me = this;
this.reqd_fields.map((field) => {
field.$wrapper.on('change input', () => {
me.reset_next($primary_btn);
});
});
},
next_or_complete: function() {
if(this.set_values()) {
if(this.id+1 < this.wiz.slides.length) {
@@ -335,6 +390,17 @@ frappe.wiz.WizardSlide = Class.extend({
}
}
},
reset_next: function($primary_btn) {
var empty_fields = this.reqd_fields.filter((field) => {
return !field.get_value();
})
if(empty_fields.length) {
$primary_btn.addClass('disabled');
} else {
$primary_btn.removeClass('disabled');
}
},
focus_first_input: function() {
setTimeout(function() {
this.$body.find('.form-control').first().focus();
@@ -360,233 +426,302 @@ frappe.wiz.WizardSlide = Class.extend({
},
});
function load_frappe_slides() {
// language selection
frappe.wiz.welcome = {
var frappe_slides = [
{
// Welcome (language) slide
name: "welcome",
domains: ["all"],
title: __("Welcome "),
title: __("Hello! "),
icon: "fa fa-world",
help: __("Let's prepare the system for first use."),
fields: [
{ fieldname: "language", label: __("Select Your Language"), reqd:1,
fieldtype: "Select", "default": "english" },
{ fieldname: "language", label: __("Your Language"),
fieldtype: "Select", "default": "English" }
],
onload: function(slide) {
if (!frappe.wiz.welcome.data ) {
frappe.wiz.welcome.load_language s(slide);
if (frappe.setup.data.lang ) {
this.setup_field s(slide);
} else {
frappe.wiz.welcome.setup_fields(slide );
utils.load_languages(slide, this.setup_fields );
}
},
css_class: "single-column",
load_languages: function(slide) {
frappe.call({
method: "frappe.desk.page.setup_wizard.setup_wizard.load_languages",
freeze: true,
callback: function(r) {
frappe.wiz.welcome.data = r.message;
frappe.wiz.welcome.setup_fields(slide);
var language_field = slide.get_field("language");
language_field.set_input(frappe.wiz.welcome.data.default_language || "english");
if (!frappe.wiz._from_load_messages) {
language_field.$input.trigger("change");
}
delete frappe.wiz._from_load_messages;
moment.locale("en");
}
});
},
setup_fields: function(slide) {
var select = slide.get_field("language");
select.df.options = frappe.wiz.welcome.data.languages;
select.refresh();
frappe.wiz.welcome.bind_events(slide);
utils.setup_language_field(slide);
utils.bind_language_events(slide);
},
bind_events: function(slide) {
slide.get_input("language").unbind("change").on("change", function() {
var lang = $(this).val() || "english";
frappe._messages = {};
frappe.call({
method: "frappe.desk.page.setup_wizard.setup_wizard.load_messages",
freeze: true,
args: {
language: lang
},
callback: function(r) {
frappe.wiz._from_load_messages = true;
frappe.wizard.refresh_slides();
}
});
});
}
},
// region selection
frappe.wiz.region = {
{
// Region slide
name: 'region',
domains: ["all"],
title: __("Region"),
title: __("Select Your Region"),
icon: "fa fa-flag",
help: __("Select your Country, Time Zone and Currency"),
fields: [
{ fieldname: "country", label: __("Country"), reqd:1,
{ fieldname: "country", label: __("Your Country"), reqd:1,
fieldtype: "Select" },
{ fieldtype: "Section Break" },
{ fieldname: "timezone", label: __("Time Zone"), reqd:1,
fieldtype: "Select" },
{ fieldtype: "Column Break" },
{ fieldname: "currency", label: __("Currency"), reqd:1,
fieldtype: "Select" },
fieldtype: "Select" }
],
onload: function(slide) {
var _setup = function() {
frappe.wiz.region.setup_fields(slide);
frappe.wiz.region.bind_events(slide);
};
if(frappe.wiz.regional_data) {
_setup();
if(frappe.setup.data.regional_data) {
this.setup_fields(slide);
} else {
frappe.call({
method:"frappe.geo.country_info.get_country_timezone_info",
callback: function(data) {
frappe.wiz.regional_data = data.message;
_setup();
}
});
utils.load_regional_data(slide, this.setup_fields);
}
},
css_class: "single-column",
setup_fields: function(slide) {
var data = frappe.wiz.regional_data;
utils.setup_region_fields(slide);
utils.bind_region_events(slide);
}
},
slide.get_input("country").empty()
.add_options([""].concat(Object.keys(data.country_info).sort()));
{
// Profile slide
name: 'user',
domains: ["all"],
title: __("The First User: You"),
icon: "fa fa-user",
fields: [
{ "fieldtype":"Attach Image", "fieldname":"attach_user_image",
label: __("Attach Your Picture"), is_private: 0},
{ "fieldname": "full_name", "label": __("Full Name"), "fieldtype": "Data",
reqd:1},
{ "fieldname": "email", "label": __("Email Address") + ' <i>(' + __("Will be your login ID") + ')</i>',
"fieldtype": "Data", reqd:1, "options":"Email"},
{ "fieldname": "password", "label": __("Password"), "fieldtype": "Password", reqd:1 }
],
help: __('The first user will become the System Manager (you can change this later).'),
onload: function(slide) {
if(frappe.session.user!=="Administrator") {
// remove password field
delete slide.form.fields_dict.password;
slide.form.fields_dict.email.$wrapper.toggle(false);
if(frappe.boot.user.first_name || frappe.boot.user.last_name) {
slide.form.fields_dict.full_name.set_input(
[frappe.boot.user.first_name, frappe.boot.user.last_name].join(' ').trim());
}
slide.get_input("currency").empty()
.add_options(frappe.utils.unique([""].concat($.map(data.country_info,
function(opts, country) { return opts.currency; }))).sort());
var user_image = frappe.get_cookie("user_image");
var $attach_user_image = slide.form.fields_dict.attach_user_image.$wrapper;
slide.get_input("timezone").empty()
.add_options([""].concat(data.all_timezones));
if(user_image) {
$attach_user_image.find(".missing-image").toggle(false);
$attach_user_image.find("img").attr("src", decodeURIComponent(user_image)).toggle(true);
}
delete slide.form.fields_dict.email;
// set values if present
if(frappe.wizard.values.country) {
slide.get_field("country").set_input(frappe.wizard.values.country);
} else if (data.default_country) {
slide.get_field("country").set_input(data.default_country);
} else {
utils.load_user_details(slide, this.setup_fields);
}
},
if(frappe.wizard.values.currency) {
slide.get_field("currency").set_input(frappe.wizard.values.currency);
setup_fields: function(slide) {
if(frappe.setup.data.full_name) {
slide.form.fields_dict.full_name.set_input(frappe.setup.data.full_name);
}
if(frappe.wizard.values.timezone) {
slide.get_field("timezone").set_input(frappe.wizard.values.timezone);
if(frappe.setup.data.email) {
let email = frappe.setup.data.email;
slide.form.fields_dict.email.set_input(email);
if (frappe.get_gravatar(email, 200)) {
var $attach_user_image = slide.form.fields_dict.attach_user_image.$wrapper;
$attach_user_image.find(".missing-image").toggle(false);
$attach_user_image.find("img").attr("src", frappe.get_gravatar(email, 200));
$attach_user_image.find(".img-container").toggle(true);
}
}
},
},
];
bind_events: function(slide) {
slide.get_input("country").on("change", function() {
var country = slide.get_input("country").val();
var $timezone = slide.get_input("timezone");
var data = frappe.wiz.regional_data;
var utils = {
load_languages: function(slide, callback) {
frappe.call({
method: "frappe.desk.page.setup_wizard.setup_wizard.load_languages",
freeze: true,
callback: function(r) {
frappe.setup.data.lang = r.message;
callback(slide);
$timezone.empty();
var language_field = slide.get_field("language" );
// add country specific timezones first
if(country) {
var timezone_list = data.country_info[country].timezones || [];
$timezone.add_options(timezone_list.sort());
slide.get_field("currency").set_input(data.country_info[country].currency);
slide.get_field("currency").$input.trigger("change");
language_field.set_input(frappe.setup.data.default_language || "English");
if (!frappe.setup._from_load_messages) {
language_field.$input.trigger("change");
}
delete frappe.setup._from_load_messages;
moment.locale("en");
}
});
},
load_regional_data: function(slide, callback) {
frappe.call({
method:"frappe.geo.country_info.get_country_timezone_info",
callback: function(data) {
frappe.setup.data.regional_data = data.message;
callback(slide);
}
});
},
// add all timezones at the end, so that user has the option to change it to any timezone
$timezone.add_options([""].concat(data.all_timezones));
load_user_details: function(slide, callback) {
frappe.call({
method: "frappe.desk.page.setup_wizard.setup_wizard.load_user_details",
freeze: true,
callback: function(r) {
frappe.setup.data.full_name = r.message.full_name;
frappe.setup.data.email = r.message.email;
callback(slide);
}
})
},
slide.get_field("timezone").set_input($timezone.val());
setup_language_field: function(slide) {
var language_field = slide.get_field("language");
language_field.df.options = frappe.setup.data.lang.languages;
language_field.refresh();
},
// temporarily set date format
frappe.boot.sysdefaults.date_format = (data.country_info[country].date_format
|| "dd-mm-yyyy");
});
setup_region_fields: function(slide) {
/*
Set a slide's country, timezone and currency fields
*/
var data = frappe.setup.data.regional_data;
slide.get_input("currency").on("change", function() {
var currency = slide.get_input("currency").val();
if (!currency) return;
frappe.model.with_doc("Currency", currency, function() {
frappe.provide("locals.:Currency." + currency);
var currency_doc = frappe.model.get_doc("Currency", currency);
var number_format = currency_doc.number_format;
if (number_format==="#.###") {
number_format = "#.###,##";
} else if (number_format==="#,###") {
number_format = "#,###.##"
}
frappe.boot.sysdefaults.number_format = number_format;
locals[":Currency"][currency] = $.extend({}, currency_doc );
});
} );
var country_field = slide.get_field('country');
slide.get_input("country").empty()
.add_options([""].concat(Object.keys(data.country_info).sort()));
slide.get_input("currency").empty()
.add_options(frappe.utils.unique([""].concat($.map(data.country_info,
function(opts, country) { return opts.currency; }))).sort());
slide.get_input("timezone").empty()
.add_options([""].concat(data.all_timezones));
// set values if present
if(frappe.wizard.values.country) {
country_field.set_input(frappe.wizard.values.country );
} else if (data.default_country) {
country_field.set_input(data.default_country );
}
},
if(frappe.wizard.values.currency) {
slide.get_field("currency").set_input(frappe.wizard.values.currency);
}
frappe.wiz.user = {
domains: ["all"],
title: __("The First User: You"),
icon: "fa fa-user",
fields: [
{"fieldname": "full_name", "label": __("Full Name"), "fieldtype": "Data",
reqd:1},
{"fieldname": "email", "label": __("Email Address"), "fieldtype": "Data",
reqd:1, "description": __("Login id"), "options":"Email"},
{"fieldname": "password", "label": __("Password"), "fieldtype": "Password",
reqd:1},
{fieldtype:"Attach Image", fieldname:"attach_user",
label: __("Attach Your Picture"), is_private: 0},
],
help: __('The first user will become the System Manager (you can change this later).'),
onload: function(slide) {
if(frappe.session.user!=="Administrator") {
slide.form.fields_dict.password.$wrapper.toggle(false);
slide.form.fields_dict.email.$wrapper.toggle(false);
if(frappe.boot.user.first_name || frappe.boot.user.last_name) {
slide.form.fields_dict.full_name.set_input(
[frappe.boot.user.first_name, frappe.boot.user.last_name].join(' ').trim());
if(frappe.wizard.values.timezone) {
slide.get_field("timezone").set_input(frappe.wizard.values.timezone);
}
country_field.df.description = 'fetching country...';
country_field.set_description();
// get location from IP (unreliable)
frappe.call({
method:"frappe.desk.page.setup_wizard.setup_wizard.load_country",
callback: function(r) {
if(r.message) {
slide.get_field("country").set_input(r.message);
slide.get_input("country").trigger('change');
}
country_field.df.description = '';
country_field.set_description();
}
});
},
var user_image = frappe.get_cookie("user_image");
if(user_image) {
var $attach_user = slide.form.fields_dict.attach_user.$wrapper;
$attach_user.find(".missing-image").toggle(false);
$attach_user.find("img").attr("src", decodeURIComponent(user_image)).toggle(true);
bind_language_events: function(slide) {
slide.get_input("language").unbind("change").on("change", function() {
var lang = $(this).val() || "English";
frappe._messages = {};
frappe.call({
method: "frappe.desk.page.setup_wizard.setup_wizard.load_messages",
freeze: true,
args: {
language: lang
},
callback: function(r) {
frappe.setup._from_load_messages = true;
frappe.wizard.refresh_slides();
}
});
});
},
delete slide.form.fields_dict.email;
delete slide.form.fields_dict.password;
bind_region_events: function(slide) {
/*
Bind a slide's country, timezone and currency fields
*/
slide.get_input("country").on("change", function() {
var country = slide.get_input("country").val();
var $timezone = slide.get_input("timezone");
var data = frappe.setup.data.regional_data;
$timezone.empty();
// add country specific timezones first
if(country) {
var timezone_list = data.country_info[country].timezones || [];
$timezone.add_options(timezone_list.sort());
slide.get_field("currency").set_input(data.country_info[country].currency);
slide.get_field("currency").$input.trigger("change");
}
},
css_class: "single-column"
};
// add all timezones at the end, so that user has the option to change it to any timezone
$timezone.add_options([""].concat(data.all_timezones));
slide.get_field("timezone").set_input($timezone.val());
// temporarily set date format
frappe.boot.sysdefaults.date_format = (data.country_info[country].date_format
|| "dd-mm-yyyy");
});
slide.get_input("currency").on("change", function() {
var currency = slide.get_input("currency").val();
if (!currency) return;
frappe.model.with_doc("Currency", currency, function() {
frappe.provide("locals.:Currency." + currency);
var currency_doc = frappe.model.get_doc("Currency", currency);
var number_format = currency_doc.number_format;
if (number_format==="#.###") {
number_format = "#.###,##";
} else if (number_format==="#,###") {
number_format = "#,###.##"
}
frappe.boot.sysdefaults.number_format = number_format;
locals[":Currency"][currency] = $.extend({}, currency_doc);
});
});
},
}
frappe.wiz.on("before_load", function() {
load_frappe_slides();
frappe.setup.on("before_load", function() {
// load slides
frappe_slides.map(frappe.setup.add_slide);
// add welcome slide
frappe.wiz.add_slide(frappe.wiz.welcome);
frappe.wiz.add_slide(frappe.wiz.region);
frappe.wiz.add_slide(frappe.wiz.user);
// set header image
let $icon = $('header .setup-wizard-brand');
if($icon.length === 0) {
$('header').append(`<div class="setup-wizard-brand"">
<img src="/assets/frappe/images/frappe-bird-grey.svg"
class="brand-icon frappe-icon" style="width:36px;"></div>`);
}
});