diff --git a/ks_dashboard_ninja/models/ks_dashboard_ninja.py b/ks_dashboard_ninja/models/ks_dashboard_ninja.py index e99881f..84621c1 100644 --- a/ks_dashboard_ninja/models/ks_dashboard_ninja.py +++ b/ks_dashboard_ninja/models/ks_dashboard_ninja.py @@ -109,6 +109,11 @@ class KsDashboardNinjaBoard(models.Model): ks_ai_explain_dash = fields.Boolean(default=False); is_bookmarked = fields.Boolean(default=False) + ks_is_home_dashboard = fields.Boolean( + string=_("设为登录首页"), + default=False, + help=_("勾选后,「组访问」中所有组的成员登录后都会进入本工作台"), + ) def _default_dashboard_image(self): return image_data_uri(encodebytes(file_open('ks_dashboard_ninja/static/images/dashboardOverview/defaultDashboard.png', 'rb').read())) @@ -149,6 +154,11 @@ class KsDashboardNinjaBoard(models.Model): 'web_icon': 'ks_dashboard_ninja,static/description/iconi.png' if not record.ks_dashboard_top_menu_id else False, }) + # Sync group-level home dashboard setting on creation + if record.ks_is_home_dashboard and record.ks_dashboard_group_access: + users = self.env['res.users'].search([('groups_id', 'in', record.ks_dashboard_group_access.ids)]) + users.write({'action_id': record.ks_dashboard_client_action_id.id}) + if record.ks_dashboard_default_template and record.ks_dashboard_default_template.ks_item_count: ks_gridstack_config = {} template_data = json.loads(record.ks_dashboard_default_template.ks_gridstack_config) @@ -172,6 +182,15 @@ class KsDashboardNinjaBoard(models.Model): def write(self, vals): + # Remember old values so we can cleanly update group-level home pages. + old_home_values = { + rec.id: { + 'group_ids': rec.ks_dashboard_group_access.ids, + 'is_home': rec.ks_is_home_dashboard, + } + for rec in self + } + if vals.get('ks_date_filter_selection', False) and vals.get('ks_date_filter_selection') != 'l_custom': vals.update({ 'ks_dashboard_start_date': False, @@ -179,16 +198,17 @@ class KsDashboardNinjaBoard(models.Model): }) record = super(KsDashboardNinjaBoard, self).write(vals) + default_board = self.env.ref('ks_dashboard_ninja.ks_my_default_dashboard_board', raise_if_not_found=False) + default_board_id = default_board.id if default_board else False for rec in self: if 'ks_dashboard_menu_name' in vals: - if self.env.ref('ks_dashboard_ninja.ks_my_default_dashboard_board') and self.env.ref( - 'ks_dashboard_ninja.ks_my_default_dashboard_board').sudo().id == rec.id: + if default_board_id and default_board_id == rec.id: if self.env.ref('ks_dashboard_ninja.board_menu_root', False): self.env.ref('ks_dashboard_ninja.board_menu_root').sudo().name = vals['ks_dashboard_menu_name'] else: rec.ks_dashboard_menu_id.sudo().name = vals['ks_dashboard_menu_name'] if 'ks_dashboard_group_access' in vals: - if self.env.ref('ks_dashboard_ninja.ks_my_default_dashboard_board').id == rec.id: + if default_board_id and default_board_id == rec.id: if self.env.ref('ks_dashboard_ninja.board_menu_root', False): self.env.ref('ks_dashboard_ninja.board_menu_root').groups_id = vals['ks_dashboard_group_access'] else: @@ -211,10 +231,37 @@ class KsDashboardNinjaBoard(models.Model): if 'name' in vals: rec.ks_dashboard_client_action_id.sudo().name = vals['name'] + # Sync group-level home dashboard setting + if 'ks_is_home_dashboard' in vals or 'ks_dashboard_group_access' in vals: + client_action_id = rec.ks_dashboard_client_action_id.id + if client_action_id: + old = old_home_values[rec.id] + new_group_ids = rec.ks_dashboard_group_access.ids + if rec.ks_is_home_dashboard: + # Remove users that are no longer in the allowed groups + removed_groups = list(set(old['group_ids']) - set(new_group_ids)) + if removed_groups: + removed_users = self.env['res.users'].search([ + ('groups_id', 'in', removed_groups), + ('action_id', '=', client_action_id), + ]) + removed_users.write({'action_id': False}) + # Set home page for all current group members + users = self.env['res.users'].search([('groups_id', 'in', new_group_ids)]) + users.write({'action_id': client_action_id}) + elif old['is_home']: + # Home page option was disabled: clear old group members + old_users = self.env['res.users'].search([ + ('groups_id', 'in', old['group_ids']), + ('action_id', '=', client_action_id), + ]) + old_users.write({'action_id': False}) + return record def unlink(self): - if self.env.ref('ks_dashboard_ninja.ks_my_default_dashboard_board').id in self.ids: + default_board = self.env.ref('ks_dashboard_ninja.ks_my_default_dashboard_board', raise_if_not_found=False) + if default_board and default_board.id in self.ids: raise ValidationError(_("Default Dashboard can't be deleted.")) else: for rec in self: diff --git a/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja_new.js b/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja_new.js index b3cfcfb..f16d465 100644 --- a/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja_new.js +++ b/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja_new.js @@ -275,7 +275,8 @@ export class KsDashboardNinja extends Component { if(!document.body.classList.contains('ks_body_class')) dnNavBarAddClasses(); - if(this.env.services.menu.getCurrentApp()?.xmlid !== "ks_dashboard_ninja.board_menu_root") + const currentApp = this.env.services.menu.getCurrentApp(); + if (currentApp && currentApp.xmlid !== "ks_dashboard_ninja.board_menu_root") this.env.services.menu.reload() @@ -2032,6 +2033,21 @@ const ks_dn_webclient ={ var self = this; // const sup = await this.super(...args); const sup = await super.loadRouterState(...args); + // When the home action loads as a client action (no menu app is active + // by default), Odoo's menu service still thinks "no app selected" and + // a subsequent router update may call _loadDefaultApp() -> selectMenu + // on the apps root, flashing the user back to the apps page. + // Anchor the menu to board_menu_root whenever we have a current + // controller but no active menu app. + const currentApp = this.menuService.getCurrentApp(); + if (!currentApp && this.actionService.currentController) { + const dashboardMenu = this.menuService.getAll().find( + (m) => m.xmlid === "ks_dashboard_ninja.board_menu_root" + ); + if (dashboardMenu) { + this.menuService.setCurrentMenu(dashboardMenu); + } + } const ks_reload_menu = async (id) => { this.menuService.reload().then(() => { self.menuService.selectMenu(id); @@ -2040,5 +2056,13 @@ const ks_dn_webclient ={ this.actionService.ksDnReloadMenu = ks_reload_menu; return sup; }, + // Prevent Odoo's default fallback ("no action => apps page") from kicking + // in when an action (e.g. our home client action) is already loaded. + _loadDefaultApp() { + if (this.actionService.currentController) { + return; + } + return super._loadDefaultApp(); + }, }; patch(WebClient.prototype, ks_dn_webclient) \ No newline at end of file diff --git a/ks_dashboard_ninja/views/ks_dashboard_ninja_view.xml b/ks_dashboard_ninja/views/ks_dashboard_ninja_view.xml index 230901c..b7a3cca 100644 --- a/ks_dashboard_ninja/views/ks_dashboard_ninja_view.xml +++ b/ks_dashboard_ninja/views/ks_dashboard_ninja_view.xml @@ -7,6 +7,11 @@
+
+ + +