refactor: track completed app setup wizards and re-run the setup wizard upon new app installation. (#32640)
This commit is contained in:
parent
2baedc18c6
commit
5c6b2b5bec
21 changed files with 301 additions and 24 deletions
|
|
@ -1931,6 +1931,18 @@ def get_active_domains():
|
|||
return get_active_domains()
|
||||
|
||||
|
||||
@request_cache
|
||||
def is_setup_complete():
|
||||
is_setup_complete = False
|
||||
if not frappe.db.table_exists("Installed Application"):
|
||||
return is_setup_complete
|
||||
|
||||
if all(frappe.get_all("Installed Application", {"has_setup_wizard": 1}, pluck="is_setup_complete")):
|
||||
is_setup_complete = True
|
||||
|
||||
return is_setup_complete
|
||||
|
||||
|
||||
@whitelist(allow_guest=True)
|
||||
def ping():
|
||||
return "pong"
|
||||
|
|
|
|||
|
|
@ -5,6 +5,11 @@ import re
|
|||
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.core.doctype.installed_applications.installed_applications import (
|
||||
get_apps_with_incomplete_dependencies,
|
||||
get_setup_wizard_completed_apps,
|
||||
get_setup_wizard_not_required_apps,
|
||||
)
|
||||
|
||||
# check if route is /app or /app/* and not /app1 or /app1/*
|
||||
DESK_APP_PATTERN = re.compile(r"^/app(/.*)?$")
|
||||
|
|
@ -15,6 +20,13 @@ def get_apps():
|
|||
apps = frappe.get_installed_apps()
|
||||
app_list = []
|
||||
for app in apps:
|
||||
if (
|
||||
app not in get_setup_wizard_completed_apps()
|
||||
and app not in get_setup_wizard_not_required_apps()
|
||||
and "System Manager" not in frappe.get_roles()
|
||||
):
|
||||
continue
|
||||
|
||||
if app == "frappe":
|
||||
continue
|
||||
app_details = frappe.get_hooks("add_to_apps_screen", app_name=app)
|
||||
|
|
@ -79,3 +91,24 @@ def set_app_as_default(app_name):
|
|||
frappe.db.set_value("User", frappe.session.user, "default_app", "")
|
||||
else:
|
||||
frappe.db.set_value("User", frappe.session.user, "default_app", app_name)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_incomplete_setup_route(current_app, app_route):
|
||||
pending_apps = get_apps_with_incomplete_dependencies(current_app)
|
||||
|
||||
if not pending_apps:
|
||||
return app_route
|
||||
|
||||
for app in pending_apps:
|
||||
if app == "frappe":
|
||||
return "app"
|
||||
|
||||
app_details = frappe.get_hooks("add_to_apps_screen", app_name=app)
|
||||
if not app_details:
|
||||
continue
|
||||
|
||||
if route := app_details[0].get("route"):
|
||||
return route
|
||||
|
||||
return app_route
|
||||
|
|
|
|||
|
|
@ -9,6 +9,10 @@ import os
|
|||
import frappe
|
||||
import frappe.defaults
|
||||
import frappe.desk.desk_page
|
||||
from frappe.core.doctype.installed_applications.installed_applications import (
|
||||
get_setup_wizard_completed_apps,
|
||||
get_setup_wizard_not_required_apps,
|
||||
)
|
||||
from frappe.core.doctype.navbar_settings.navbar_settings import get_app_logo, get_navbar_settings
|
||||
from frappe.desk.doctype.changelog_feed.changelog_feed import get_changelog_feed_items
|
||||
from frappe.desk.doctype.form_tour.form_tour import get_onboarding_ui_tours
|
||||
|
|
@ -42,6 +46,8 @@ def get_bootinfo():
|
|||
# system info
|
||||
bootinfo.sitename = frappe.local.site
|
||||
bootinfo.sysdefaults = frappe.defaults.get_defaults()
|
||||
bootinfo.sysdefaults["setup_complete"] = frappe.is_setup_complete()
|
||||
|
||||
bootinfo.server_date = frappe.utils.nowdate()
|
||||
|
||||
if frappe.session["user"] != "Guest":
|
||||
|
|
@ -114,9 +120,34 @@ def get_bootinfo():
|
|||
if sentry_dsn := get_sentry_dsn():
|
||||
bootinfo.sentry_dsn = sentry_dsn
|
||||
|
||||
bootinfo.setup_wizard_completed_apps = get_setup_wizard_completed_apps() or []
|
||||
bootinfo.setup_wizard_not_required_apps = get_setup_wizard_not_required_apps() or []
|
||||
remove_apps_with_incomplete_dependencies(bootinfo)
|
||||
|
||||
return bootinfo
|
||||
|
||||
|
||||
def remove_apps_with_incomplete_dependencies(bootinfo):
|
||||
remove_apps = []
|
||||
|
||||
for app in bootinfo.setup_wizard_not_required_apps:
|
||||
if app in bootinfo.setup_wizard_completed_apps:
|
||||
continue
|
||||
|
||||
for required_apps in frappe.get_hooks("required_apps"):
|
||||
required_apps = required_apps.split("/")
|
||||
|
||||
for required_app in required_apps:
|
||||
if app not in bootinfo.setup_wizard_not_required_apps:
|
||||
continue
|
||||
|
||||
if required_app not in bootinfo.setup_wizard_completed_apps:
|
||||
remove_apps.append(app)
|
||||
|
||||
for app in remove_apps:
|
||||
bootinfo.setup_wizard_not_required_apps.remove(app)
|
||||
|
||||
|
||||
def get_letter_heads():
|
||||
letter_heads = {}
|
||||
|
||||
|
|
@ -345,7 +376,7 @@ def add_home_page(bootinfo, docs):
|
|||
return
|
||||
home_page = frappe.db.get_default("desktop:home_page")
|
||||
|
||||
if home_page == "setup-wizard":
|
||||
if not frappe.is_setup_complete():
|
||||
bootinfo.setup_wizard_requires = frappe.get_hooks("setup_wizard_requires")
|
||||
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ class AddressTemplate(Document):
|
|||
|
||||
if not self.is_default and not self._get_previous_default():
|
||||
self.is_default = 1
|
||||
if frappe.get_system_settings("setup_complete"):
|
||||
if frappe.is_setup_complete():
|
||||
frappe.msgprint(_("Setting this Address Template as default as there is no other default"))
|
||||
|
||||
def on_update(self):
|
||||
|
|
|
|||
|
|
@ -6,10 +6,13 @@
|
|||
"field_order": [
|
||||
"app_name",
|
||||
"app_version",
|
||||
"git_branch"
|
||||
"git_branch",
|
||||
"has_setup_wizard",
|
||||
"is_setup_complete"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"columns": 2,
|
||||
"fieldname": "git_branch",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
|
|
@ -18,6 +21,7 @@
|
|||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"columns": 2,
|
||||
"fieldname": "app_name",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
|
|
@ -26,25 +30,44 @@
|
|||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"columns": 2,
|
||||
"fieldname": "app_version",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Application Version",
|
||||
"read_only": 1,
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"columns": 2,
|
||||
"default": "0",
|
||||
"fieldname": "has_setup_wizard",
|
||||
"fieldtype": "Check",
|
||||
"in_list_view": 1,
|
||||
"label": "Has Setup Wizard"
|
||||
},
|
||||
{
|
||||
"columns": 2,
|
||||
"default": "0",
|
||||
"fieldname": "is_setup_complete",
|
||||
"fieldtype": "Check",
|
||||
"in_list_view": 1,
|
||||
"label": "Is Setup Complete?"
|
||||
}
|
||||
],
|
||||
"grid_page_length": 50,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2024-03-23 16:03:27.892752",
|
||||
"modified": "2025-05-22 12:26:49.523690",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Core",
|
||||
"name": "Installed Application",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"row_format": "Dynamic",
|
||||
"sort_field": "creation",
|
||||
"sort_order": "DESC",
|
||||
"states": [],
|
||||
"track_changes": 1
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ class InstalledApplication(Document):
|
|||
app_name: DF.Data
|
||||
app_version: DF.Data
|
||||
git_branch: DF.Data
|
||||
has_setup_wizard: DF.Check
|
||||
is_setup_complete: DF.Check
|
||||
parent: DF.Data
|
||||
parentfield: DF.Data
|
||||
parenttype: DF.Data
|
||||
|
|
|
|||
|
|
@ -26,18 +26,40 @@ class InstalledApplications(Document):
|
|||
# end: auto-generated types
|
||||
|
||||
def update_versions(self):
|
||||
app_wise_setup_details = self.get_app_wise_setup_details()
|
||||
|
||||
self.delete_key("installed_applications")
|
||||
for app in frappe.utils.get_installed_apps_info():
|
||||
has_setup_wizard = 0
|
||||
if app.get("app_name") == "frappe" or frappe.get_hooks(app_name=app.get("app_name")).get(
|
||||
"setup_wizard_stages"
|
||||
):
|
||||
has_setup_wizard = 1
|
||||
|
||||
self.append(
|
||||
"installed_applications",
|
||||
{
|
||||
"app_name": app.get("app_name"),
|
||||
"app_version": app.get("version") or "UNVERSIONED",
|
||||
"git_branch": app.get("branch") or "UNVERSIONED",
|
||||
"has_setup_wizard": has_setup_wizard,
|
||||
"is_setup_complete": app_wise_setup_details.get(app.get("app_name")) or 0,
|
||||
},
|
||||
)
|
||||
|
||||
self.save()
|
||||
|
||||
def get_app_wise_setup_details(self):
|
||||
"""Get app wise setup details from the Installed Application doctype"""
|
||||
return frappe._dict(
|
||||
frappe.get_all(
|
||||
"Installed Application",
|
||||
fields=["app_name", "is_setup_complete"],
|
||||
filters={"has_setup_wizard": 1},
|
||||
as_list=True,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def update_installed_apps_order(new_order: list[str] | str):
|
||||
|
|
@ -85,3 +107,57 @@ def get_installed_app_order() -> list[str]:
|
|||
frappe.only_for("System Manager")
|
||||
|
||||
return frappe.get_installed_apps(_ensure_on_bench=True)
|
||||
|
||||
|
||||
@frappe.request_cache
|
||||
def get_setup_wizard_completed_apps():
|
||||
"""Get list of apps that have completed setup wizard"""
|
||||
return frappe.get_all(
|
||||
"Installed Application",
|
||||
filters={"has_setup_wizard": 1, "is_setup_complete": 1},
|
||||
pluck="app_name",
|
||||
)
|
||||
|
||||
|
||||
@frappe.request_cache
|
||||
def get_setup_wizard_not_required_apps():
|
||||
"""Get list of apps that do not require setup wizard"""
|
||||
return frappe.get_all(
|
||||
"Installed Application",
|
||||
filters={"has_setup_wizard": 0},
|
||||
pluck="app_name",
|
||||
)
|
||||
|
||||
|
||||
@frappe.request_cache
|
||||
def get_apps_with_incomplete_dependencies(current_app):
|
||||
"""Get apps with incomplete dependencies."""
|
||||
dependent_apps = ["frappe"]
|
||||
|
||||
if apps := frappe.get_hooks("required_apps", app_name=current_app):
|
||||
dependent_apps.extend(apps)
|
||||
|
||||
parsed_apps = []
|
||||
for apps in dependent_apps:
|
||||
apps = apps.split("/")
|
||||
parsed_apps.extend(apps)
|
||||
|
||||
pending_apps = get_setup_wizard_pending_apps(parsed_apps)
|
||||
|
||||
return pending_apps
|
||||
|
||||
|
||||
@frappe.request_cache
|
||||
def get_setup_wizard_pending_apps(apps=None):
|
||||
"""Get list of apps that have completed setup wizard"""
|
||||
|
||||
filters = {"has_setup_wizard": 1, "is_setup_complete": 0}
|
||||
if apps:
|
||||
filters["app_name"] = ["in", apps]
|
||||
|
||||
return frappe.get_all(
|
||||
"Installed Application",
|
||||
filters=filters,
|
||||
order_by="idx",
|
||||
pluck="app_name",
|
||||
)
|
||||
|
|
|
|||
|
|
@ -258,7 +258,7 @@ def set_desktop_icons(visible_list, ignore_duplicate=True):
|
|||
an icon for the doctype"""
|
||||
|
||||
# clear all custom only if setup is not complete
|
||||
if not frappe.defaults.get_defaults().get("setup_complete", 0):
|
||||
if not frappe.is_setup_complete():
|
||||
frappe.db.delete("Desktop Icon", {"standard": 0})
|
||||
|
||||
# set standard as blocked and hidden if setting first active domain
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ def get_notifications():
|
|||
"open_count_doctype": {},
|
||||
"targets": {},
|
||||
}
|
||||
if frappe.flags.in_install or not frappe.get_system_settings("setup_complete"):
|
||||
if frappe.flags.in_install or not frappe.is_setup_complete():
|
||||
return out
|
||||
|
||||
config = get_notification_config()
|
||||
|
|
|
|||
|
|
@ -63,6 +63,13 @@ frappe.pages["setup-wizard"].on_page_show = function () {
|
|||
};
|
||||
|
||||
frappe.setup.on("before_load", function () {
|
||||
if (
|
||||
frappe.boot.setup_wizard_completed_apps?.length &&
|
||||
frappe.boot.setup_wizard_completed_apps.includes("frappe")
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
// load slides
|
||||
frappe.setup.slides_settings.forEach((s) => {
|
||||
if (!(s.name === "user" && frappe.boot.developer_mode)) {
|
||||
|
|
@ -207,7 +214,12 @@ frappe.setup.SetupWizard = class SetupWizard extends frappe.ui.Slides {
|
|||
}
|
||||
setTimeout(function () {
|
||||
// Reload
|
||||
window.location.href = frappe.boot.apps_data.default_path || "/app";
|
||||
let current_route = localStorage.current_route;
|
||||
|
||||
localStorage.current_route = "";
|
||||
localStorage.current_app = "";
|
||||
|
||||
window.location.href = current_route || frappe.boot.apps_data.default_path || "/app";
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import json
|
|||
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.core.doctype.installed_applications.installed_applications import get_setup_wizard_completed_apps
|
||||
from frappe.geo.country_info import get_country_info
|
||||
from frappe.permissions import AUTOMATIC_ROLES
|
||||
from frappe.translate import send_translations, set_default_language
|
||||
|
|
@ -22,7 +23,12 @@ def get_setup_stages(args): # nosemgrep
|
|||
"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"}
|
||||
{
|
||||
"fn": update_global_settings,
|
||||
"args": args,
|
||||
"fail_msg": "Failed to update global settings",
|
||||
"app_name": "frappe",
|
||||
}
|
||||
],
|
||||
}
|
||||
]
|
||||
|
|
@ -47,18 +53,18 @@ def setup_complete(args):
|
|||
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")):
|
||||
if frappe.is_setup_complete():
|
||||
return {"status": "ok"}
|
||||
|
||||
args = parse_args(sanitize_input(args))
|
||||
stages = get_setup_stages(args)
|
||||
kwargs = parse_args(sanitize_input(args))
|
||||
stages = get_setup_stages(kwargs)
|
||||
is_background_task = frappe.conf.get("trigger_site_setup_in_background")
|
||||
|
||||
if is_background_task:
|
||||
process_setup_stages.enqueue(stages=stages, user_input=args, is_background_task=True, at_front=True)
|
||||
process_setup_stages.enqueue(stages=stages, user_input=kwargs, is_background_task=True, at_front=True)
|
||||
return {"status": "registered"}
|
||||
else:
|
||||
return process_setup_stages(stages, args)
|
||||
return process_setup_stages(stages, kwargs)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
|
|
@ -87,6 +93,8 @@ def initialize_system_settings_and_user(system_settings_data, user_data):
|
|||
def process_setup_stages(stages, user_input, is_background_task=False):
|
||||
from frappe.utils.telemetry import capture
|
||||
|
||||
setup_wizard_completed_apps = get_setup_wizard_completed_apps()
|
||||
|
||||
capture("initated_server_side", "setup")
|
||||
try:
|
||||
frappe.flags.in_setup_wizard = True
|
||||
|
|
@ -100,7 +108,18 @@ def process_setup_stages(stages, user_input, is_background_task=False):
|
|||
|
||||
for task in stage.get("tasks"):
|
||||
current_task = task
|
||||
if task.get("app_name") and task.get("app_name") in setup_wizard_completed_apps:
|
||||
continue
|
||||
|
||||
if "frappe" in setup_wizard_completed_apps:
|
||||
set_missing_values(task)
|
||||
|
||||
task.get("fn")(task.get("args"))
|
||||
|
||||
if task.get("app_name"):
|
||||
enable_setup_wizard_complete(task.get("app_name"))
|
||||
else:
|
||||
enable_setup_wizard_complete("frappe")
|
||||
except Exception:
|
||||
handle_setup_exception(user_input)
|
||||
message = current_task.get("fail_msg") if current_task else "Failed to complete setup"
|
||||
|
|
@ -123,6 +142,23 @@ def process_setup_stages(stages, user_input, is_background_task=False):
|
|||
frappe.flags.in_setup_wizard = False
|
||||
|
||||
|
||||
def set_missing_values(task):
|
||||
if task and task.get("args"):
|
||||
doc = frappe.get_doc("System Settings")
|
||||
task["args"].update(
|
||||
{
|
||||
"country": doc.country,
|
||||
"time_zone": doc.time_zone,
|
||||
"time_format": doc.time_format,
|
||||
"currency": doc.currency,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def enable_setup_wizard_complete(app_name):
|
||||
frappe.db.set_value("Installed Application", {"app_name": app_name}, "is_setup_complete", 1)
|
||||
|
||||
|
||||
def update_global_settings(args): # nosemgrep
|
||||
if args.language and args.language != "English":
|
||||
set_default_language(get_language_code(args.lang))
|
||||
|
|
@ -166,6 +202,7 @@ def get_setup_complete_hooks(args): # nosemgrep
|
|||
"fn": frappe.get_attr(method),
|
||||
"args": args,
|
||||
"fail_msg": "Failed to execute method",
|
||||
"app_name": method.split(".")[0],
|
||||
}
|
||||
],
|
||||
}
|
||||
|
|
@ -183,6 +220,9 @@ def handle_setup_exception(args): # nosemgrep
|
|||
|
||||
|
||||
def update_system_settings(args): # nosemgrep
|
||||
if not args.get("country"):
|
||||
return
|
||||
|
||||
number_format = get_country_info(args.get("country")).get("number_format", "#,###.##")
|
||||
|
||||
# replace these as float number formats, as they have 0 precision
|
||||
|
|
@ -310,8 +350,6 @@ def disable_future_access():
|
|||
# Enable onboarding after install
|
||||
frappe.db.set_single_value("System Settings", "enable_onboarding", 1)
|
||||
|
||||
frappe.db.set_single_value("System Settings", "setup_complete", 1)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def load_messages(language):
|
||||
|
|
|
|||
|
|
@ -344,6 +344,8 @@ def add_to_installed_apps(app_name, rebuild_website=True):
|
|||
if frappe.flags.in_install:
|
||||
post_install(rebuild_website)
|
||||
|
||||
frappe.get_single("Installed Applications").update_versions()
|
||||
|
||||
|
||||
def remove_from_installed_apps(app_name):
|
||||
installed_apps = frappe.get_installed_apps()
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
[pre_model_sync]
|
||||
frappe.patches.v16_0.enable_setup_complete
|
||||
frappe.patches.v15_0.remove_implicit_primary_key
|
||||
frappe.patches.v12_0.remove_deprecated_fields_from_doctype #3
|
||||
execute:frappe.utils.global_search.setup_global_search_table()
|
||||
|
|
|
|||
24
frappe/patches/v16_0/enable_setup_complete.py
Normal file
24
frappe/patches/v16_0/enable_setup_complete.py
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
import frappe
|
||||
|
||||
|
||||
def execute():
|
||||
frappe.reload_doc("core", "doctype", "installed_application")
|
||||
frappe.reload_doc("core", "doctype", "installed_applications")
|
||||
|
||||
is_setup_complete = frappe.db.get_single_value("System Settings", "setup_complete")
|
||||
for app_name in frappe.get_all("Installed Application", pluck="app_name"):
|
||||
has_setup_wizard = 0
|
||||
if app_name == "frappe":
|
||||
has_setup_wizard = 1
|
||||
elif frappe.get_hooks(app_name=app_name).get("setup_wizard_stages"):
|
||||
has_setup_wizard = 1
|
||||
|
||||
if has_setup_wizard:
|
||||
frappe.db.set_value(
|
||||
"Installed Application",
|
||||
{"app_name": app_name},
|
||||
{
|
||||
"has_setup_wizard": 1,
|
||||
"is_setup_complete": is_setup_complete,
|
||||
},
|
||||
)
|
||||
|
|
@ -380,6 +380,7 @@ frappe.Application = class Application {
|
|||
if (r.exc) {
|
||||
return;
|
||||
}
|
||||
|
||||
me.redirect_to_login();
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -129,7 +129,12 @@ frappe.router = {
|
|||
if (!frappe.app) return;
|
||||
|
||||
let sub_path = this.get_sub_path();
|
||||
if (frappe.boot.setup_complete) {
|
||||
let current_app = localStorage.current_app;
|
||||
|
||||
if (
|
||||
frappe.boot.setup_complete ||
|
||||
(current_app && frappe.boot.setup_wizard_not_required_apps?.includes(current_app))
|
||||
) {
|
||||
!frappe.re_route["setup-wizard"] && (frappe.re_route["setup-wizard"] = "app");
|
||||
} else if (!sub_path.startsWith("setup-wizard")) {
|
||||
frappe.re_route["setup-wizard"] && delete frappe.re_route["setup-wizard"];
|
||||
|
|
|
|||
|
|
@ -170,7 +170,7 @@ def get():
|
|||
bootinfo["lang"] = frappe.translate.get_user_lang()
|
||||
bootinfo["disable_async"] = frappe.conf.disable_async
|
||||
|
||||
bootinfo["setup_complete"] = cint(frappe.get_system_settings("setup_complete"))
|
||||
bootinfo["setup_complete"] = frappe.is_setup_complete()
|
||||
bootinfo["apps_data"] = {
|
||||
"apps": get_apps() or [],
|
||||
"is_desk_apps": 1 if bool(is_desk_apps(get_apps())) else 0,
|
||||
|
|
|
|||
|
|
@ -814,7 +814,7 @@ def get_site_info():
|
|||
"country": system_settings.country,
|
||||
"language": system_settings.language or "english",
|
||||
"time_zone": system_settings.time_zone,
|
||||
"setup_complete": cint(system_settings.setup_complete),
|
||||
"setup_complete": frappe.is_setup_complete(),
|
||||
"scheduler_enabled": system_settings.enable_scheduler,
|
||||
# usage
|
||||
"emails_sent": get_emails_sent_this_month(),
|
||||
|
|
|
|||
|
|
@ -45,7 +45,6 @@ def after_install():
|
|||
# only set home_page if the value doesn't exist in the db
|
||||
if not frappe.db.get_default("desktop:home_page"):
|
||||
frappe.db.set_default("desktop:home_page", "setup-wizard")
|
||||
frappe.db.set_single_value("System Settings", "setup_complete", 0)
|
||||
|
||||
# clear test log
|
||||
from frappe.tests.utils.generators import _clear_test_log
|
||||
|
|
@ -136,7 +135,7 @@ def before_tests():
|
|||
frappe.clear_cache()
|
||||
|
||||
# complete setup if missing
|
||||
if not cint(frappe.db.get_single_value("System Settings", "setup_complete")):
|
||||
if not frappe.is_setup_complete():
|
||||
complete_setup_wizard()
|
||||
|
||||
frappe.db.set_single_value("Website Settings", "disable_signup", 0)
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@ endblock -%} {%- block footer -%} {%- endblock -%} {% block content %}
|
|||
{% set appsCount = apps|length if apps|length <= 6 else 6 %}
|
||||
<div class="apps" style="grid-template-columns: repeat({{ appsCount }}, 1fr);">
|
||||
{% for app in apps %}
|
||||
<a href="{{ app.route }}" class="app-icon">
|
||||
<div class="app-logo">
|
||||
<a class="app-icon" style="cursor: pointer;">
|
||||
<div class="app-logo app-name-cls" app-name="{{ app.name }}" app-route="{{ app.route }}">
|
||||
<img src="{{ app.logo }}" />
|
||||
<div
|
||||
app-name="{{ app.name }}"
|
||||
|
|
@ -73,7 +73,25 @@ endblock -%} {%- block footer -%} {%- endblock -%} {% block content %}
|
|||
},
|
||||
});
|
||||
});
|
||||
|
||||
$(".app-name-cls").on("click", function (e) {
|
||||
localStorage.current_app = $(this).attr("app-name");
|
||||
localStorage.current_route = $(this).attr("app-route");
|
||||
|
||||
frappe.call({
|
||||
method: "frappe.apps.get_incomplete_setup_route",
|
||||
args: { current_app: localStorage.current_app, app_route:localStorage.current_route },
|
||||
callback: function (r) {
|
||||
window.location.href = r.message;
|
||||
},
|
||||
})
|
||||
|
||||
});
|
||||
|
||||
$(".logout-btn").on("click", function () {
|
||||
localStorage.current_app = "";
|
||||
localStorage.current_route = "";
|
||||
|
||||
frappe.call({
|
||||
method: "logout",
|
||||
callback: function () {
|
||||
|
|
|
|||
|
|
@ -17,6 +17,6 @@ def get_boot():
|
|||
"site_name": frappe.local.site,
|
||||
"read_only_mode": frappe.flags.read_only,
|
||||
"csrf_token": frappe.sessions.get_csrf_token(),
|
||||
"setup_complete": cint(frappe.get_system_settings("setup_complete")),
|
||||
"setup_complete": frappe.is_setup_complete(),
|
||||
}
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue