summaryrefslogtreecommitdiffstats
path: root/install/ui/src/freeipa/Application_controller.js
diff options
context:
space:
mode:
authorPetr Vobornik <pvoborni@redhat.com>2012-12-14 16:39:20 +0100
committerPetr Vobornik <pvoborni@redhat.com>2013-05-06 16:22:17 +0200
commit693dc560620d52dc24a0ab89e20147b10ed4f469 (patch)
treea748bc7a89f76d8ea4cdf1dc1a91895192a7ea56 /install/ui/src/freeipa/Application_controller.js
parenta4d9e19c79b60b8f7269141374b2e3b6c0d66c45 (diff)
downloadfreeipa-693dc560620d52dc24a0ab89e20147b10ed4f469.tar.gz
freeipa-693dc560620d52dc24a0ab89e20147b10ed4f469.tar.xz
freeipa-693dc560620d52dc24a0ab89e20147b10ed4f469.zip
Menu and application controller refactoring
https://fedorahosted.org/freeipa/ticket/3235 https://fedorahosted.org/freeipa/ticket/3236
Diffstat (limited to 'install/ui/src/freeipa/Application_controller.js')
-rw-r--r--install/ui/src/freeipa/Application_controller.js323
1 files changed, 323 insertions, 0 deletions
diff --git a/install/ui/src/freeipa/Application_controller.js b/install/ui/src/freeipa/Application_controller.js
new file mode 100644
index 000000000..6406e8bc4
--- /dev/null
+++ b/install/ui/src/freeipa/Application_controller.js
@@ -0,0 +1,323 @@
+/* Authors:
+ * Petr Vobornik <pvoborni@redhat.com>
+ *
+ * Copyright (C) 2012 Red Hat
+ * see file 'COPYING' for use and warranty information
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * Application controller
+ *
+ * Controls interaction between navigation, menu and facets.
+ */
+
+define(['dojo/_base/declare',
+ 'dojo/_base/lang',
+ 'dojo/_base/array',
+ 'dojo/on',
+ 'dojo/topic',
+ 'dojo/query',
+ 'dojo/dom-class',
+ './widgets/App',
+ './ipa',
+ './navigation/Menu',
+ './navigation/Router',
+ './navigation/menu_spec'
+ ],
+ function(declare, lang, array, on, topic, query, dom_class,
+ App_widget, IPA, Menu, Router, menu_spec) {
+
+ /**
+ * Main application
+ *
+ * This class serves as top level widget. It creates basic UI: controls
+ * rendering of header, footer and placeholder for facets.
+ */
+ var App = declare(null, {
+
+ app_widget: null,
+
+ router: null,
+
+ menu: null,
+
+ initialized: false,
+
+ facet_changing: false,
+
+ init: function() {
+ this.menu = new Menu();
+ this.router = new Router();
+ this.app_widget = new App_widget();
+ this.app_widget.menu_widget.set_menu(this.menu);
+ this.app_widget.container_node = query('body')[0];
+
+ on(this.app_widget.menu_widget, 'item-select', lang.hitch(this, this.on_menu_click));
+ on(this.app_widget, 'profile-click', lang.hitch(this, this.on_profile));
+ on(this.app_widget, 'logout-click', lang.hitch(this, this.on_logout));
+ on(this.menu, 'selected', lang.hitch(this, this.on_menu_select));
+
+ topic.subscribe('facet-show', lang.hitch(this, this.on_facet_show));
+ topic.subscribe('facet-change', lang.hitch(this, this.on_facet_change));
+ topic.subscribe('facet-change-canceled', lang.hitch(this, this.on_facet_canceled));
+ topic.subscribe('phase-error', lang.hitch(this, this.on_phase_error));
+ topic.subscribe('facet-state-change', lang.hitch(this, this.on_facet_state_changed));
+
+ this.app_widget.render();
+ },
+
+ /**
+ * Gets:
+ * * metadata
+ * * server configuration
+ * * user information
+ */
+ get_configuration: function(success_handler, error_handler) {
+ IPA.init({ on_success: success_handler, on_error: error_handler});
+ },
+
+ /**
+ * Deduces current application profile - administraion or self-service.
+ * Initializes profiles's menu.
+ */
+ choose_profile: function() {
+
+ // TODO: change IPA.whoami.cn[0] to something readable
+ this.update_logged_in(true, IPA.whoami.cn[0]);
+ var selfservice = this.is_selfservice();
+
+
+ this.app_widget.menu_widget.ignore_changes = true;
+
+ if (selfservice) {
+ this.menu.name = menu_spec.self_service.name;
+ this.menu.add_items(menu_spec.self_service.items);
+ } else {
+ this.menu.name = menu_spec.admin.name;
+ this.menu.add_items(menu_spec.admin.items);
+ }
+
+ this.app_widget.menu_widget.ignore_changes = false;
+ this.app_widget.menu_widget.render();
+ this.app_widget.menu_widget.select(this.menu.selected);
+
+ // now we are ready for displaying a facet
+ // cat match a facet if hash is set
+ this.router.startup();
+
+ // choose default facet if not defined by route
+ if (!this.current_facet) {
+ if (selfservice) {
+ this.on_profile();
+ } else {
+ this.router.navigate_to_entity_facet('user', 'search');
+ }
+ }
+ },
+
+ is_selfservice: function() {
+ var whoami = IPA.whoami;
+ var self_service = true;
+
+
+ if (whoami.hasOwnProperty('memberof_group') &&
+ whoami.memberof_group.indexOf('admins') !== -1) {
+ self_service = false;
+ } else if (whoami.hasOwnProperty('memberofindirect_group')&&
+ whoami.memberofindirect_group.indexOf('admins') !== -1) {
+ self_service = false;
+ } else if (whoami.hasOwnProperty('memberof_role') &&
+ whoami.memberof_role.length > 0) {
+ self_service = false;
+ } else if (whoami.hasOwnProperty('memberofindirect_role') &&
+ whoami.memberofindirect_role.length > 0) {
+ self_service = false;
+ }
+
+ IPA.is_selfservice = self_service; // quite ugly, needed for users
+
+ return self_service;
+ },
+
+ update_logged_in: function(logged_in, fullname) {
+ this.app_widget.set('logged', logged_in);
+ this.app_widget.set('fullname', fullname);
+ },
+
+ on_profile: function() {
+ this.router.navigate_to_entity_facet('user', 'details', [IPA.whoami.uid[0]]);
+ },
+
+ on_logout: function(event) {
+ IPA.logout();
+ },
+
+ on_phase_error: function(error) {
+ // FIXME: CHANGE!!!
+ window.alert('Initialization error, have a coffee and relax.');
+// var container = $('#content').empty();
+// container.append('<p>Error: '+error_thrown.name+'</p>');
+// container.append('<p>'+error_thrown.message+'</p>');
+ },
+
+ on_facet_change: function(event) {
+ //this.facet_changing = true;
+ var new_facet = event.facet;
+ var current_facet = this.current_facet;
+
+ if (current_facet && !current_facet.can_leave()) {
+ var permit_clb = function() {
+ // Some facet's might not call reset before this call but after
+ // so they are still dirty. Calling reset prevent's opening of
+ // dirty dialog again.
+ if (current_facet.is_dirty()) current_facet.reset(); //TODO change
+ this.router.navigate_to_hash(event.hash, event.facet);
+ };
+
+ var dialog = current_facet.show_leave_dialog(permit_clb);
+ this.router.canceled = true;
+ dialog.open();
+ }
+ },
+
+ on_facet_canceled: function(event) {
+ },
+
+ on_facet_state_changed: function(event) {
+ if (event.facet === this.current_facet) {
+ var hash = this.router.create_hash(event.facet, event.state);
+ this.router.update_hash(hash, true);
+ }
+ },
+
+ on_facet_show: function(event) {
+ var facet = event.facet;
+
+ // update menu
+ var menu_item = this._find_menu_item(facet);
+ if (menu_item) this.menu.select(menu_item);
+
+ if (!facet.container) {
+ facet.container_node = this.app_widget.content_node;
+ }
+ if (this.current_facet) {
+ this.current_facet.hide();
+ }
+ this.current_facet = facet;
+ facet.show();
+ },
+
+ _find_menu_item: function(facet) {
+
+ var items;
+
+ // entity facets
+ if (facet.entity) {
+ items = this.menu.query({ entity: facet.entity.name, facet: facet.name });
+ }
+
+ // normal facets
+ if (!items.total) {
+ items = this.menu.query({ facet: facet.name });
+ }
+
+ // entity fallback
+ if (!items.total && facet.entity) {
+ items = this.menu.query({ entity: facet.entity.name });
+ }
+
+ // fallback: Top level item
+ if (!items.total) {
+ items = this.menu.query({ parent: null });
+ }
+
+ // select first
+ if (items.total) {
+ return items[0];
+ }
+ },
+
+ /**
+ * Tries to find menu item with assigned facet and navigate to it.
+ */
+ on_menu_click: function(menu_item) {
+ this._navigate_to_menu_item(menu_item);
+ },
+
+ _navigate_to_menu_item: function(menu_item) {
+
+ if (menu_item.entity) {
+ // entity pages
+ this.router.navigate_to_entity_facet(
+ menu_item.entity,
+ menu_item.facet,
+ menu_item.pkeys,
+ menu_item.args);
+ } else if (menu_item.facet) {
+ // concrete facets
+ this.router.navigate_to_facet(menu_item.facet, menu_item.args);
+ } else {
+ // categories, select first posible child
+ var children = this.menu.query({parent: menu_item.name });
+ if (children.total) {
+ var success = false;
+ for (var i=0; i<children.total;i++) {
+ success = this._navigate_to_menu_item(children[i]);
+ if (success) break;
+ }
+ } else {
+ return false;
+ }
+ }
+
+ return true;
+ },
+
+ /**
+ * Watches menu changes and adjusts facet space when there is
+ * a need for larger menu space.
+ *
+ * Show extended menu space when:
+ * * there is 3+ levels of menu
+ *
+ * Don't show when:
+ * * all items of levels 3+ are hidden
+ */
+ on_menu_select: function(select_state) {
+
+ var has_visible = function(query_result) {
+ for (var i=0; i<query_result.total; i++) {
+ if (!query_result[i].hidden) return true;
+ }
+ return false;
+ };
+
+ var item = select_state.item;
+ var visible_simblings = has_visible(this.menu.query({parent: item.parent}));
+ var visible_children = has_visible(this.menu.query({parent: item.name}));
+
+ var levels = select_state.new_selection.length;
+
+ var three_levels = levels >= 3 && (visible_children > 0 || visible_simblings > 0);
+
+ dom_class.toggle(this.app_widget.content_node,
+ 'nav-space-3',
+ three_levels);
+ }
+ });
+
+ return App;
+}); \ No newline at end of file