From deb5b51ddc43742c48d8e1c46f4e9aba22632e8c Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 21 Jul 2018 13:22:57 -0700 Subject: [PATCH] GUACAMOLE-220: Add generic directive for displaying tabs which divide a section into logical views. --- .../navigation/directives/guacSectionTabs.js | 143 ++++++++++++++++++ .../styles/{page-tabs.css => tabs.css} | 20 ++- .../navigation/templates/guacSectionTabs.html | 10 ++ 3 files changed, 167 insertions(+), 6 deletions(-) create mode 100644 guacamole/src/main/webapp/app/navigation/directives/guacSectionTabs.js rename guacamole/src/main/webapp/app/navigation/styles/{page-tabs.css => tabs.css} (76%) create mode 100644 guacamole/src/main/webapp/app/navigation/templates/guacSectionTabs.html diff --git a/guacamole/src/main/webapp/app/navigation/directives/guacSectionTabs.js b/guacamole/src/main/webapp/app/navigation/directives/guacSectionTabs.js new file mode 100644 index 000000000..97c87c2e6 --- /dev/null +++ b/guacamole/src/main/webapp/app/navigation/directives/guacSectionTabs.js @@ -0,0 +1,143 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * Directive which displays a set of tabs dividing a section of a page into + * logical subsections or views. The currently selected tab is communicated + * through assignment to the variable bound to the current + * attribute. No navigation occurs as a result of selecting a tab. + */ +angular.module('navigation').directive('guacSectionTabs', ['$injector', + function guacSectionTabs($injector) { + + // Required services + var translationStringService = $injector.get('translationStringService'); + + var directive = { + + restrict : 'E', + replace : true, + templateUrl : 'app/navigation/templates/guacSectionTabs.html', + + scope : { + + /** + * The translation namespace to use when producing translation + * strings for each tab. Tab translation strings will be of the + * form: + * + * NAMESPACE.SECTION_HEADER_NAME + * + * where NAMESPACE is the namespace provided to this + * attribute and NAME is one of the names within the + * array provided to the tabs attribute and + * transformed via translationStringService.canonicalize(). + */ + namespace : '@', + + /** + * The name of the currently selected tab. This name MUST be one of + * the names present in the array given via the tabs + * attribute. This directive will not automatically choose an + * initially selected tab, and a default value should be manually + * assigned to current to ensure a tab is initially + * selected. + * + * @type String + */ + current : '=', + + /** + * The unique names of all tabs which should be made available, in + * display order. These names will be assigned to the variable + * bound to the current attribute when the current + * tab changes. + * + * @type String[] + */ + tabs : '=' + + } + + }; + + directive.controller = ['$scope', function dataSourceTabsController($scope) { + + /** + * Produces the translation string for the section header representing + * the tab having the given name. The translation string will be of the + * form: + * + * NAMESPACE.SECTION_HEADER_NAME + * + * where NAMESPACE is the namespace provided to the + * directive and NAME is the given name transformed + * via translationStringService.canonicalize(). + * + * @param {String} name + * The name of the tab. + * + * @returns {String} + * The translation string which produces the translated header + * of the tab having the given name. + */ + $scope.getSectionHeader = function getSectionHeader(name) { + + // If no name, then no header + if (!name) + return ''; + + return translationStringService.canonicalize($scope.namespace || 'MISSING_NAMESPACE') + + '.SECTION_HEADER_' + translationStringService.canonicalize(name); + + }; + + /** + * Selects the tab having the given name. The name of the currently + * selected tab will be communicated outside the directive through + * $scope.current. + * + * @param {String} name + * The name of the tab to select. + */ + $scope.selectTab = function selectTab(name) { + $scope.current = name; + }; + + /** + * Returns whether the tab having the given name is currently + * selected. A tab is currently selected if its name is stored within + * $scope.current, as assigned externally or by selectTab(). + * + * @param {String} name + * The name of the tab to test. + * + * @returns {Boolean} + * true if the tab having the given name is currently selected, + * false otherwise. + */ + $scope.isSelected = function isSelected(name) { + return $scope.current === name; + }; + + }]; + + return directive; + +}]); diff --git a/guacamole/src/main/webapp/app/navigation/styles/page-tabs.css b/guacamole/src/main/webapp/app/navigation/styles/tabs.css similarity index 76% rename from guacamole/src/main/webapp/app/navigation/styles/page-tabs.css rename to guacamole/src/main/webapp/app/navigation/styles/tabs.css index 5e88cd0e1..3d1c8cdec 100644 --- a/guacamole/src/main/webapp/app/navigation/styles/page-tabs.css +++ b/guacamole/src/main/webapp/app/navigation/styles/tabs.css @@ -17,23 +17,27 @@ * under the License. */ -.page-tabs .page-list ul { +.page-tabs .page-list ul, +.section-tabs ul { margin: 0; padding: 0; background: rgba(0, 0, 0, 0.0125); border-bottom: 1px solid rgba(0, 0, 0, 0.05); } -.page-tabs .page-list ul + ul { +.page-tabs .page-list ul + ul, +.section-tabs ul + ul { font-size: 0.75em; } -.page-tabs .page-list li { +.page-tabs .page-list li, +.section-tabs li { display: inline-block; list-style: none; } -.page-tabs .page-list li a[href] { +.page-tabs .page-list li a[href], +.section-tabs li a { display: block; color: black; text-decoration: none; @@ -44,12 +48,16 @@ color: black; } -.page-tabs .page-list li a[href]:hover { +.page-tabs .page-list li a[href]:hover, +.section-tabs li a:hover { background-color: #CDA; + cursor: pointer; } .page-tabs .page-list li a[href].current, -.page-tabs .page-list li a[href].current:hover { +.page-tabs .page-list li a[href].current:hover, +.section-tabs li a.current, +.section-tabs li a.current:hover { background: rgba(0,0,0,0.3); cursor: default; } diff --git a/guacamole/src/main/webapp/app/navigation/templates/guacSectionTabs.html b/guacamole/src/main/webapp/app/navigation/templates/guacSectionTabs.html new file mode 100644 index 000000000..a02871534 --- /dev/null +++ b/guacamole/src/main/webapp/app/navigation/templates/guacSectionTabs.html @@ -0,0 +1,10 @@ + \ No newline at end of file