Ver a proveniência

Setup stages (#4618)

* setup complete stages

* [setup] better setup-in-progress card

* restructure setup exception flow

* use setup_stages hook

* Add message for non-dev mode, fail instead of error

* message to not include commits in app setup stages
version-14
Prateeksha Singh há 7 anos
committed by Nabin Hait
ascendente
cometimento
d5ad0ff2e8
4 ficheiros alterados com 207 adições e 187 eliminações
  1. +92
    -54
      frappe/desk/page/setup_wizard/setup_wizard.js
  2. +108
    -41
      frappe/desk/page/setup_wizard/setup_wizard.py
  3. +3
    -46
      frappe/public/css/page.css
  4. +4
    -46
      frappe/public/less/page.less

+ 92
- 54
frappe/desk/page/setup_wizard/setup_wizard.js Ver ficheiro

@@ -182,39 +182,72 @@ frappe.setup.SetupWizard = class SetupWizard extends frappe.ui.Slides {
}

action_on_complete() {
var me = this;
if (!this.current_slide.set_values()) return;
this.update_values();
this.show_working_state();
this.disable_keyboard_nav();
this.listen_for_setup_stages();

return frappe.call({
method: "frappe.desk.page.setup_wizard.setup_wizard.setup_complete",
args: {args: this.values},
callback: function() {
me.show_setup_complete_state();
if(frappe.setup.welcome_page) {
localStorage.setItem("session_last_route", frappe.setup.welcome_page);
callback: (r) => {
if(r.message.status === 'ok') {
this.post_setup_success();
} else if(r.message.fail !== undefined) {
this.abort_setup(r.message.fail);
}
setTimeout(function() {
// Reload
window.location.href = '';
}, 2000);
setTimeout(()=> {
$('body').removeClass('setup-state');
}, 20000);
},
error: function() {
var d = frappe.msgprint(__("There were errors."));
d.custom_onhide = function() {
$(me.parent).find('.page-card-container').remove();
$('body').removeClass('setup-state');
me.container.show();
frappe.set_route(me.page_name, me.slides.length - 1);
};
}
error: this.abort_setup.bind(this, "Error in setup", true)
});
}

post_setup_success() {
this.set_setup_complete_message(__("Setup Complete"), __("Refreshing..."));
if(frappe.setup.welcome_page) {
localStorage.setItem("session_last_route", frappe.setup.welcome_page);
}
setTimeout(function() {
// Reload
window.location.href = '';
}, 2000);
}

abort_setup(fail_msg, error=false) {
this.$working_state.find('.state-icon-container').html('');
fail_msg = fail_msg ? fail_msg : __("Failed to complete setup");

if(error && !frappe.boot.developer_mode) {
frappe.msgprint(`Don't worry. It's not you, it's us. We've
received the issue details and will get back to you on the solution.
Please feel free to contact us on support@erpnext.com in the meantime.`);
}

this.update_setup_message('Could not start up: ' + fail_msg);

this.$working_state.find('.title').html('Setup failed');

this.$abort_btn.show();
}

listen_for_setup_stages() {
frappe.realtime.on("setup_task", (data) => {
// console.log('data', data);
if(data.stage_status) {
// .html('Process '+ data.progress[0] + ' of ' + data.progress[1] + ': ' + data.stage_status);
this.update_setup_message(data.stage_status);
this.set_setup_load_percent((data.progress[0]+1)/data.progress[1] * 100);
}
if(data.fail_msg) {
this.abort_setup(data.fail_msg);
}
})
}

update_setup_message(message) {
this.$working_state.find('.setup-message').html(message);
}

get_setup_slides_filtered_by_domain() {
var filtered_slides = [];
frappe.setup.slides.forEach(function(slide) {
@@ -233,51 +266,56 @@ frappe.setup.SetupWizard = class SetupWizard extends frappe.ui.Slides {

show_working_state() {
this.container.hide();
$('body').addClass('setup-state');
frappe.set_route(this.page_name);

this.working_state_message = this.get_message(
__("Setting Up"),
__("Sit tight while your system is being setup. This may take a few moments."),
true
).appendTo(this.parent);
this.$working_state = this.get_message(
__("Setting up your system"),
__("Starting Frappé ...")).appendTo(this.parent);
this.attach_abort_button();

this.current_id = this.slides.length;
this.current_slide = null;
this.completed_state_message = this.get_message(
__("Setup Complete"),
__("Refreshing...")
);
}

show_setup_complete_state() {
this.working_state_message.hide();
this.completed_state_message.appendTo(this.parent);
attach_abort_button() {
this.$abort_btn = $(`<button class='btn btn-default btn-xs text-muted'
style="margin-bottom: 30px;">${__('Retry')}</button>`);
this.$working_state.find('.content').append(this.$abort_btn);

this.$abort_btn.on('click', () => {
$(this.parent).find('.setup-in-progress').remove();
this.container.show();
frappe.set_route(this.page_name, this.slides.length - 1);
});

this.$abort_btn.hide();
}

get_message(title, message="", loading=false) {
const loading_html = loading
? '<div style="width:100%;height:100%" class="lds-rolling state-icon"><div></div></div>'
: `<div style="width:100%;height:100%" class="state-icon">
<i class="fa fa-check-circle text-success"
style="font-size: 64px; margin-top: -8px;"></i>
</div>`;

return $(`<div class="page-card-container" data-state="setup">
<div class="page-card">
<div class="page-card-head">
${loading
? `<span class="indicator orange">${title}</span>`
: `<span class="indicator green">${title}</span>`
}
</div>
<p>${message}</p>
<div class="state-icon-container">
${loading_html}
</div>
get_message(title, message="") {
const loading_html = `<div class="progress-chart" style ="width: 150px;">
<div class="progress" style="margin-top: 70px; margin-bottom: 0px">
<div class="progress-bar" style="width: 2%; background-color: #5e64ff;"></div>
</div>
</div>`;

return $(`<div class="slides-wrapper setup-wizard-slide setup-in-progress">
<div class="content text-center">
<p class="title lead">${title}</p>
<div class="state-icon-container">${loading_html}</div>
<p class="setup-message text-muted" style="margin: 30px 0px;">${message}</p>
</div>
</div>`);
}

set_setup_complete_message(title, message) {
this.$working_state.find('.title').html(title);
this.$working_state.find('.setup-message').html(message);
}

set_setup_load_percent(percent) {
this.$working_state.find('.progress-bar').css({"width": percent + "%"});
}
};

frappe.setup.SetupWizardSlide = class SetupWizardSlide extends frappe.ui.Slide {


+ 108
- 41
frappe/desk/page/setup_wizard/setup_wizard.py Ver ficheiro

@@ -13,50 +13,117 @@ from werkzeug.useragents import UserAgent
from . import install_fixtures
from six import string_types

def get_setup_stages(args):

# App setup stage functions should not include frappe.db.commit
# That is done by frappe after successful completion of all stages
stages = [
{
'status': 'Updating global settings',
'fail_msg': 'Failed to update global settings',
'tasks': [
{
'fn': update_global_settings,
'args': args,
'fail_msg': 'Failed to update global settings'
}
]
}
]

stages += get_stages_hooks(args) + get_setup_complete_hooks(args)

stages.append({
# post executing hooks
'status': 'Wrapping up',
'fail_msg': 'Failed to complete setup',
'tasks': [
{
'fn': run_post_setup_complete,
'args': args,
'fail_msg': 'Failed to complete setup'
}
]
})

return stages

@frappe.whitelist()
def setup_complete(args):
"""Calls hooks for `setup_wizard_complete`, sets home page as `desktop`
and clears cache. If wizard breaks, calls `setup_wizard_exception` hook"""

# Setup complete: do not throw an exception, let the user continue to desk
if cint(frappe.db.get_single_value('System Settings', 'setup_complete')):
# do not throw an exception if setup is already complete
# let the user continue to desk
return
#frappe.throw(_('Setup already complete'))

args = process_args(args)
args = parse_args(args)

try:
if args.language and args.language != "english":
set_default_language(get_language_code(args.language))
stages = get_setup_stages(args)

frappe.clear_cache()

# update system settings
update_system_settings(args)
update_user_name(args)

for method in frappe.get_hooks("setup_wizard_complete"):
frappe.get_attr(method)(args)
try:
current_task = None
for idx, stage in enumerate(stages):
frappe.publish_realtime('setup_task', {"progress": [idx, len(stages)],
"stage_status": stage.get('status')}, user=frappe.session.user)

for task in stage.get('tasks'):
current_task = task
task.get('fn')(task.get('args'))

except Exception:
handle_setup_exception(args)
return {'status': 'fail', 'fail': current_task.get('fail_msg')}
else:
run_setup_success(args)
return {'status': 'ok'}

disable_future_access()
def update_global_settings(args):
if args.language and args.language != "english":
set_default_language(get_language_code(args.lang))
frappe.clear_cache()

frappe.db.commit()
frappe.clear_cache()
except:
frappe.db.rollback()
if args:
traceback = frappe.get_traceback()
for hook in frappe.get_hooks("setup_wizard_exception"):
frappe.get_attr(hook)(traceback, args)
update_system_settings(args)
update_user_name(args)

raise
def run_post_setup_complete(args):
disable_future_access()
frappe.db.commit()
frappe.clear_cache()

else:
for hook in frappe.get_hooks("setup_wizard_success"):
frappe.get_attr(hook)(args)
install_fixtures.install()
def run_setup_success(args):
for hook in frappe.get_hooks("setup_wizard_success"):
frappe.get_attr(hook)(args)
install_fixtures.install()

def get_stages_hooks(args):
stages = []
for method in frappe.get_hooks("setup_wizard_stages"):
stages += frappe.get_attr(method)(args)
return stages

def get_setup_complete_hooks(args):
stages = []
for method in frappe.get_hooks("setup_wizard_complete"):
stages.append({
'status': 'Executing method',
'fail_msg': 'Failed to execute method',
'tasks': [
{
'fn': frappe.get_attr(method),
'args': args,
'fail_msg': 'Failed to execute method'
}
]
})
return stages

def handle_setup_exception(args):
frappe.db.rollback()
if args:
traceback = frappe.get_traceback()
for hook in frappe.get_hooks("setup_wizard_exception"):
frappe.get_attr(hook)(traceback, args)

def update_system_settings(args):
number_format = get_country_info(args.get("country")).get("number_format", "#,###.##")
@@ -126,7 +193,7 @@ def update_user_name(args):
if args.get('name'):
add_all_roles_to(args.get("name"))

def process_args(args):
def parse_args(args):
if not args:
args = frappe.local.form_dict
if isinstance(args, string_types):
@@ -234,14 +301,6 @@ def email_setup_wizard_exception(traceback, args):
user_agent = frappe._dict()

message = """
#### Basic Information

- **Site:** {site}
- **User:** {user}
- **Browser:** {user_agent.platform} {user_agent.browser} version: {user_agent.version} language: {user_agent.language}
- **Browser Languages**: `{accept_languages}`

---

#### Traceback

@@ -257,7 +316,16 @@ def email_setup_wizard_exception(traceback, args):

#### Request Headers

<pre>{headers}</pre>""".format(
<pre>{headers}</pre>

---

#### Basic Information

- **Site:** {site}
- **User:** {user}
- **Browser:** {user_agent.platform} {user_agent.browser} version: {user_agent.version} language: {user_agent.language}
- **Browser Languages**: `{accept_languages}`""".format(
site=frappe.local.site,
traceback=traceback,
args="\n".join(pretty_args),
@@ -268,14 +336,13 @@ def email_setup_wizard_exception(traceback, args):

frappe.sendmail(recipients=frappe.local.conf.setup_wizard_exception_email,
sender=frappe.session.user,
subject="Exception in Setup Wizard - {}".format(frappe.local.site),
subject="Setup failed: {}".format(frappe.local.site),
message=message,
delayed=False)

def get_language_code(lang):
return frappe.db.get_value('Language', {'language_name':lang})


def enable_twofactor_all_roles():
all_role = frappe.get_doc('Role',{'role_name':'All'})
all_role.two_factor_auth = True


+ 3
- 46
frappe/public/css/page.css Ver ficheiro

@@ -279,6 +279,9 @@ select.input-sm {
opacity: 1;
cursor: pointer;
}
.setup-wizard-slide .progress-bar {
background-color: #5e64ff;
}
.page-card-container {
padding: 70px;
}
@@ -312,49 +315,3 @@ select.input-sm {
justify-content: center;
align-items: center;
}
@keyframes lds-rolling {
0% {
-webkit-transform: translate(-50%, -50%) rotate(0deg);
transform: translate(-50%, -50%) rotate(0deg);
}
100% {
-webkit-transform: translate(-50%, -50%) rotate(360deg);
transform: translate(-50%, -50%) rotate(360deg);
}
}
@-webkit-keyframes lds-rolling {
0% {
-webkit-transform: translate(-50%, -50%) rotate(0deg);
transform: translate(-50%, -50%) rotate(0deg);
}
100% {
-webkit-transform: translate(-50%, -50%) rotate(360deg);
transform: translate(-50%, -50%) rotate(360deg);
}
}
.lds-rolling {
-webkit-transform: translate(-100px, -100px) scale(1) translate(100px, 100px);
transform: translate(-100px, -100px) scale(1) translate(100px, 100px);
}
.lds-rolling div {
position: absolute;
width: 60px;
height: 60px;
border: 3px solid #d1d8dd;
border-top-color: transparent;
border-radius: 50%;
-webkit-animation: lds-rolling 1s linear infinite;
animation: lds-rolling 1s linear infinite;
top: 50px;
left: 50px;
}
.lds-rolling div:after {
position: absolute;
width: 60px;
height: 60px;
border: 3px solid #d1d8dd;
border-top-color: transparent;
border-radius: 50%;
-webkit-transform: rotate(90deg);
transform: rotate(90deg);
}

+ 4
- 46
frappe/public/less/page.less Ver ficheiro

@@ -335,6 +335,10 @@ select.input-sm {
cursor: pointer;
}
}

.progress-bar {
background-color: #5e64ff;
}
}

.page-card-container {
@@ -376,50 +380,4 @@ select.input-sm {
align-items: center;
}

@keyframes lds-rolling {
0% {
-webkit-transform: translate(-50%, -50%) rotate(0deg);
transform: translate(-50%, -50%) rotate(0deg);
}
100% {
-webkit-transform: translate(-50%, -50%) rotate(360deg);
transform: translate(-50%, -50%) rotate(360deg);
}
}
@-webkit-keyframes lds-rolling {
0% {
-webkit-transform: translate(-50%, -50%) rotate(0deg);
transform: translate(-50%, -50%) rotate(0deg);
}
100% {
-webkit-transform: translate(-50%, -50%) rotate(360deg);
transform: translate(-50%, -50%) rotate(360deg);
}
}

.lds-rolling {
-webkit-transform: translate(-100px, -100px) scale(1) translate(100px, 100px);
transform: translate(-100px, -100px) scale(1) translate(100px, 100px);
div {
position: absolute;
width: 60px;
height: 60px;
border: 3px solid #d1d8dd;
border-top-color: transparent;
border-radius: 50%;
-webkit-animation: lds-rolling 1s linear infinite;
animation: lds-rolling 1s linear infinite;
top: 50px;
left: 50px;
&:after {
position: absolute;
width: 60px;
height: 60px;
border: 3px solid #d1d8dd;
border-top-color: transparent;
border-radius: 50%;
-webkit-transform: rotate(90deg);
transform: rotate(90deg);
}
}
}

Carregando…
Cancelar
Guardar