GUACAMOLE-1509: Merge add contextual CSS classes to reduce template ambiguity.

This commit is contained in:
Virtually Nick
2022-01-23 15:30:37 -05:00
committed by GitHub
41 changed files with 184 additions and 65 deletions

View File

@@ -41,6 +41,7 @@
<div class="totp-code"> <div class="totp-code">
<input type="text" <input type="text"
placeholder="{{'TOTP.FIELD_PLACEHOLDER_CODE' |translate}}" placeholder="{{'TOTP.FIELD_PLACEHOLDER_CODE' |translate}}"
ng-attr-name="{{ field.name }}"
ng-model="model" autocorrect="off" autocapitalize="off" autofocus> ng-model="model" autocorrect="off" autocapitalize="off" autofocus>
</div> </div>

View File

@@ -243,6 +243,7 @@ angular.module('client').directive('guacClientNotification', [function guacClien
if (connectionState === ManagedClientState.ConnectionState.CONNECTING if (connectionState === ManagedClientState.ConnectionState.CONNECTING
|| connectionState === ManagedClientState.ConnectionState.WAITING) { || connectionState === ManagedClientState.ConnectionState.WAITING) {
$scope.status = { $scope.status = {
className : "connecting",
title: "CLIENT.DIALOG_HEADER_CONNECTING", title: "CLIENT.DIALOG_HEADER_CONNECTING",
text: { text: {
key : "CLIENT.TEXT_CLIENT_STATUS_" + connectionState.toUpperCase() key : "CLIENT.TEXT_CLIENT_STATUS_" + connectionState.toUpperCase()
@@ -360,6 +361,7 @@ angular.module('client').directive('guacClientNotification', [function guacClien
// Prompt for parameters // Prompt for parameters
$scope.status = { $scope.status = {
className : "parameters-required",
formNamespace : Protocol.getNamespace($scope.client.protocol), formNamespace : Protocol.getNamespace($scope.client.protocol),
forms : $scope.client.forms, forms : $scope.client.forms,
formModel : requiredParameters, formModel : requiredParameters,

View File

@@ -1,4 +1,4 @@
<div class="connection"> <div class="connection-select-menu-connection connection">
<input type="checkbox" <input type="checkbox"
ng-model="context.attachedClients[item.getClientIdentifier()]" ng-model="context.attachedClients[item.getClientIdentifier()]"
ng-change="context.updateAttachedClients(item.getClientIdentifier())"> ng-change="context.updateAttachedClients(item.getClientIdentifier())">

View File

@@ -1,4 +1,4 @@
<div class="connection-group"> <div class="connection-select-menu-connection-group connection-group">
<input type="checkbox" <input type="checkbox"
ng-show="item.balancing" ng-show="item.balancing"
ng-model="context.attachedClients[item.getClientIdentifier()]" ng-model="context.attachedClients[item.getClientIdentifier()]"

View File

@@ -1,4 +1,4 @@
<div class="list-item"> <div class="file-browser-file list-item">
<!-- Filename and icon --> <!-- Filename and icon -->
<div class="caption"> <div class="caption">

View File

@@ -1,4 +1,4 @@
<div class="main" <div class="client-main main"
ng-class="{ 'drop-pending': dropPending }" ng-class="{ 'drop-pending': dropPending }"
guac-resize="mainElementResized" guac-resize="mainElementResized"
guac-touch-drag="clientDrag" guac-touch-drag="clientDrag"
@@ -14,4 +14,4 @@
</div> </div>
</div> </div>

View File

@@ -86,6 +86,7 @@ angular.module('form').directive('guacForm', [function form() {
controller: ['$scope', '$injector', function formController($scope, $injector) { controller: ['$scope', '$injector', function formController($scope, $injector) {
// Required services // Required services
var formService = $injector.get('formService');
var translationStringService = $injector.get('translationStringService'); var translationStringService = $injector.get('translationStringService');
/** /**
@@ -134,6 +135,22 @@ angular.module('form').directive('guacForm', [function form() {
}; };
/**
* Returns an object as would be provided to the ngClass directive
* that defines the CSS classes that should be applied to the given
* form.
*
* @param {Form} form
* The form to generate the CSS classes for.
*
* @return {!Object.<string, boolean>}
* The ngClass object defining the CSS classes for the given
* form.
*/
$scope.getFormClasses = function getFormClasses(form) {
return formService.getClasses('form-', form);
};
/** /**
* Determines whether the given object is a form, under the * Determines whether the given object is a form, under the
* assumption that the object is either a form or a field. * assumption that the object is either a form or a field.

View File

@@ -155,6 +155,21 @@ angular.module('form').directive('guacFormField', [function formField() {
}; };
/**
* Returns an object as would be provided to the ngClass directive
* that defines the CSS classes that should be applied to this
* field.
*
* @return {!Object.<string, boolean>}
* The ngClass object defining the CSS classes for the current
* field.
*/
$scope.getFieldClasses = function getFieldClasses() {
return formService.getClasses('labeled-field-', $scope.field, {
empty: !$scope.model
});
};
/** /**
* Returns whether the current field should be displayed. * Returns whether the current field should be displayed.
* *

View File

@@ -91,7 +91,7 @@ angular.module('form').provider('formService', function formServiceProvider() {
* @type FieldType * @type FieldType
*/ */
'USERNAME' : { 'USERNAME' : {
templateUrl : 'app/form/templates/textField.html' templateUrl : 'app/form/templates/usernameField.html'
}, },
/** /**
@@ -272,6 +272,53 @@ angular.module('form').provider('formService', function formServiceProvider() {
}; };
/**
* Given form content and an arbitrary prefix, returns a corresponding
* CSS class object as would be provided to the ngClass directive that
* assigns a content-specific CSS class based on the prefix and
* form/field name. Generated class names follow the lowercase with
* dashes naming convention. For example, if the prefix is "field-" and
* the provided content is a field with the name "Swap red/blue", the
* object { 'field-swap-red-blue' : true } would be returned.
*
* @param {!string} prefix
* The arbitrary prefix to prepend to the name of the generated CSS
* class.
*
* @param {!(Form|Field)} [content]
* The form or field whose name should be used to produce the CSS
* class name.
*
* @param {Object.<string, boolean>} [object={}]
* The optional base ngClass object that should be used to provide
* additional name/value pairs within the returned object.
*
* @return {!Object.<string, boolean>}
* The ngClass object based on the provided object and defining a
* CSS class name for the given content.
*/
service.getClasses = function getClasses(prefix, content, object) {
// Default to no additional properties
object = object || {};
// Perform no transformation if there is no content or
// corresponding name
if (!content || !content.name)
return object;
// Transform content name and prefix into lowercase-with-dashes
// CSS class name
var className = prefix + content.name.replace(/[^a-zA-Z0-9]+/g, '-').toLowerCase();
// Add CSS class name to provided base object (without touching
// base object)
var classes = angular.extend({}, object);
classes[className] = true;
return classes;
};
/** /**
* Compiles and links the field associated with the given name to the given * Compiles and links the field associated with the given name to the given
* scope, producing a distinct and independent DOM Element which functions * scope, producing a distinct and independent DOM Element which functions

View File

@@ -1,7 +1,10 @@
<input type="checkbox" <div class="checkbox-field">
ng-attr-id="{{ fieldId }}" <input type="checkbox"
ng-disabled="disabled" ng-attr-id="{{ fieldId }}"
ng-model="typedValue" ng-attr-name="{{ field.name }}"
guac-focus="focused" ng-disabled="disabled"
autocorrect="off" ng-model="typedValue"
autocapitalize="off"> guac-focus="focused"
autocorrect="off"
autocapitalize="off">
</div>

View File

@@ -2,6 +2,7 @@
<input type="date" <input type="date"
ng-disabled="disabled" ng-disabled="disabled"
ng-attr-id="{{ fieldId }}" ng-attr-id="{{ fieldId }}"
ng-attr-name="{{ field.name }}"
ng-model="typedValue" ng-model="typedValue"
ng-model-options="modelOptions" ng-model-options="modelOptions"
guac-lenient-date guac-lenient-date

View File

@@ -2,6 +2,7 @@
<input type="email" <input type="email"
ng-disabled="disabled" ng-disabled="disabled"
ng-attr-id="{{ fieldId }}" ng-attr-id="{{ fieldId }}"
ng-attr-name="{{ field.name }}"
ng-model="model" ng-model="model"
ng-hide="readOnly" ng-hide="readOnly"
guac-focus="focused" guac-focus="focused"

View File

@@ -1,9 +1,10 @@
<div class="form-group"> <div class="form-group">
<div ng-repeat="form in forms" class="form" <div ng-repeat="form in forms" class="form"
ng-class="getFormClasses(form)"
ng-show="containsVisible(form.fields)"> ng-show="containsVisible(form.fields)">
<!-- Form name --> <!-- Form name -->
<h3 ng-show="form.name">{{getSectionHeader(form) | translate}}</h3> <h3 class="form-header" ng-show="form.name">{{getSectionHeader(form) | translate}}</h3>
<!-- All fields in form --> <!-- All fields in form -->
<div class="fields"> <div class="fields">

View File

@@ -1,4 +1,5 @@
<div class="labeled-field" ng-class="{empty: !model}" ng-show="isFieldVisible()"> <div class="labeled-field" ng-show="isFieldVisible()"
ng-class="getFieldClasses()">
<!-- Field header --> <!-- Field header -->
<div class="field-header"> <div class="field-header">

View File

@@ -1,4 +1,7 @@
<select guac-focus="focused" <div class="language-field">
ng-attr-id="{{ fieldId }}" <select guac-focus="focused"
ng-model="model" ng-attr-id="{{ fieldId }}"
ng-options="language.key as language.value for language in languages | toArray | orderBy: key"></select> ng-attr-name="{{ field.name }}"
ng-model="model"
ng-options="language.key as language.value for language in languages | toArray | orderBy: key"></select>
</div>

View File

@@ -1,7 +1,10 @@
<input type="number" <div class="number-field">
ng-disabled="disabled" <input type="number"
ng-attr-id="{{ fieldId }}" ng-disabled="disabled"
ng-model="typedValue" ng-attr-id="{{ fieldId }}"
guac-focus="focused" ng-attr-name="{{ field.name }}"
autocorrect="off" ng-model="typedValue"
autocapitalize="off"> guac-focus="focused"
autocorrect="off"
autocapitalize="off">
</div>

View File

@@ -2,6 +2,7 @@
<input type="{{passwordInputType}}" <input type="{{passwordInputType}}"
ng-disabled="disabled" ng-disabled="disabled"
ng-attr-id="{{ fieldId }}" ng-attr-id="{{ fieldId }}"
ng-attr-name="{{ field.name }}"
ng-model="model" ng-model="model"
ng-trim="false" ng-trim="false"
guac-focus="focused" guac-focus="focused"

View File

@@ -1,5 +1,8 @@
<select ng-attr-id="{{ fieldId }}" <div class="select-field">
ng-disabled="disabled" <select ng-attr-id="{{ fieldId }}"
guac-focus="focused" ng-attr-name="{{ field.name }}"
ng-model="model" ng-disabled="disabled"
ng-options="option as getFieldOption(option) | translate for option in field.options | orderBy: value"></select> guac-focus="focused"
ng-model="model"
ng-options="option as getFieldOption(option) | translate for option in field.options | orderBy: value"></select>
</div>

View File

@@ -4,7 +4,9 @@
}"> }">
<!-- Pre-defined color scheme options --> <!-- Pre-defined color scheme options -->
<select ng-attr-id="{{ fieldId }}" ng-model="selectedColorScheme"> <select ng-attr-id="{{ fieldId }}"
ng-attr-name="{{ field.name }}"
ng-model="selectedColorScheme">
<option ng-repeat="option in field.options | orderBy: value" <option ng-repeat="option in field.options | orderBy: value"
ng-value="option">{{ getFieldOption(option) | translate }}</option> ng-value="option">{{ getFieldOption(option) | translate }}</option>
<option value="custom">{{ 'COLOR_SCHEME.FIELD_OPTION_CUSTOM' | translate }}</option> <option value="custom">{{ 'COLOR_SCHEME.FIELD_OPTION_CUSTOM' | translate }}</option>

View File

@@ -1,6 +1,9 @@
<textarea ng-attr-id="{{ fieldId }}" <div class="text-area-field">
ng-model="model" <textarea ng-attr-id="{{ fieldId }}"
ng-disabled="disabled" ng-attr-name="{{ field.name }}"
guac-focus="focused" ng-model="model"
autocorrect="off" ng-disabled="disabled"
autocapitalize="off"></textarea> guac-focus="focused"
autocorrect="off"
autocapitalize="off"></textarea>
</div>

View File

@@ -2,6 +2,7 @@
<input type="text" <input type="text"
ng-attr-id="{{ fieldId }}" ng-attr-id="{{ fieldId }}"
ng-attr-list="{{ dataListId }}" ng-attr-list="{{ dataListId }}"
ng-attr-name="{{ field.name }}"
ng-model="model" ng-model="model"
ng-disabled="disabled" ng-disabled="disabled"
guac-focus="focused" guac-focus="focused"

View File

@@ -2,6 +2,7 @@
<input type="time" <input type="time"
ng-disabled="disabled" ng-disabled="disabled"
ng-attr-id="{{ fieldId }}" ng-attr-id="{{ fieldId }}"
ng-attr-name="{{ field.name }}"
ng-model="typedValue" ng-model="typedValue"
ng-model-options="modelOptions" ng-model-options="modelOptions"
guac-focus="focused" guac-focus="focused"

View File

@@ -10,6 +10,7 @@
<!-- Time zones within selected region --> <!-- Time zones within selected region -->
<select class="time-zone" <select class="time-zone"
ng-attr-name="{{ field.name }}"
ng-disabled="disabled || !region" ng-disabled="disabled || !region"
ng-model="model" ng-model="model"
ng-options="timeZone.value as timeZone.key for timeZone in timeZones[region] | toArray | orderBy: key"></select> ng-options="timeZone.value as timeZone.key for timeZone in timeZones[region] | toArray | orderBy: key"></select>

View File

@@ -0,0 +1,10 @@
<div class="username-field">
<input type="text"
ng-attr-id="{{ fieldId }}"
ng-attr-name="{{ field.name }}"
ng-model="model"
ng-disabled="disabled"
guac-focus="focused"
autocorrect="off"
autocapitalize="off">
</div>

View File

@@ -1,4 +1,4 @@
<div> <div class="recent-connections">
<!-- Text displayed if no recent connections exist --> <!-- Text displayed if no recent connections exist -->
<p class="placeholder" ng-hide="hasRecentConnections()">{{'HOME.INFO_NO_RECENT_CONNECTIONS' | translate}}</p> <p class="placeholder" ng-hide="hasRecentConnections()">{{'HOME.INFO_NO_RECENT_CONNECTIONS' | translate}}</p>

View File

@@ -1,5 +1,4 @@
<div class="home-view view" ng-class="{loading: !isLoaded()}">
<div class="view" ng-class="{loading: !isLoaded()}">
<div class="connection-list-ui"> <div class="connection-list-ui">
@@ -8,9 +7,7 @@
<h2>{{'HOME.SECTION_HEADER_RECENT_CONNECTIONS' | translate}}</h2> <h2>{{'HOME.SECTION_HEADER_RECENT_CONNECTIONS' | translate}}</h2>
<guac-user-menu></guac-user-menu> <guac-user-menu></guac-user-menu>
</div> </div>
<div class="recent-connections"> <guac-recent-connections root-groups="rootConnectionGroups"></guac-recent-connections>
<guac-recent-connections root-groups="rootConnectionGroups"></guac-recent-connections>
</div>
<!-- All connections for this user --> <!-- All connections for this user -->
<div class="header"> <div class="header">
@@ -33,4 +30,4 @@
</div> </div>
</div> </div>

View File

@@ -1,4 +1,4 @@
<div class="choice"> <div class="connection-group-permission choice">
<!-- Connection group icon --> <!-- Connection group icon -->
<div class="icon type"></div> <div class="icon type"></div>

View File

@@ -1,4 +1,4 @@
<div class="choice"> <div class="connection-permission choice">
<!-- Connection icon --> <!-- Connection icon -->
<div class="icon type" ng-class="item.protocol"></div> <div class="icon type" ng-class="item.protocol"></div>

View File

@@ -1,4 +1,4 @@
<span class="name" ng-click="context.chooseGroup(item.wrappedItem)"> <span class="location-chooser-connection-group name"
ng-click="context.chooseGroup(item.wrappedItem)">
{{item.name}} {{item.name}}
</span> </span>

View File

@@ -1,5 +1,5 @@
<div class="view" ng-class="{loading: !isLoaded()}"> <div class="manage-connection view" ng-class="{loading: !isLoaded()}">
<!-- Main property editor --> <!-- Main property editor -->
<div class="header"> <div class="header">

View File

@@ -1,5 +1,5 @@
<div class="view" ng-class="{loading: !isLoaded()}"> <div class="manage-connection-group view" ng-class="{loading: !isLoaded()}">
<!-- Main property editor --> <!-- Main property editor -->
<div class="header"> <div class="header">

View File

@@ -1,4 +1,4 @@
<div class="view" ng-class="{loading: !isLoaded()}"> <div class="manage-sharing-profile view" ng-class="{loading: !isLoaded()}">
<!-- Main property editor --> <!-- Main property editor -->
<div class="header"> <div class="header">

View File

@@ -1,6 +1,6 @@
<div class="action-buttons"> <div class="action-buttons">
<button ng-show="permissions.canSaveObject" ng-click="saveObject()">{{namespace + '.ACTION_SAVE' | translate}}</button> <button ng-show="permissions.canSaveObject" ng-click="saveObject()" class="save">{{namespace + '.ACTION_SAVE' | translate}}</button>
<button ng-show="permissions.canCloneObject" ng-click="cloneObject()">{{namespace + '.ACTION_CLONE' | translate}}</button> <button ng-show="permissions.canCloneObject" ng-click="cloneObject()" class="clone">{{namespace + '.ACTION_CLONE' | translate}}</button>
<button ng-click="cancel()">{{namespace + '.ACTION_CANCEL' | translate}}</button> <button ng-click="cancel()" class="cancel">{{namespace + '.ACTION_CANCEL' | translate}}</button>
<button ng-show="permissions.canDeleteObject" ng-click="deleteObject()" class="danger">{{namespace + '.ACTION_DELETE' | translate}}</button> <button ng-show="permissions.canDeleteObject" ng-click="deleteObject()" class="danger delete">{{namespace + '.ACTION_DELETE' | translate}}</button>
</div> </div>

View File

@@ -1,4 +1,4 @@
<div class="choice"> <div class="sharing-profile-permission choice">
<!-- Sharing profile icon --> <!-- Sharing profile icon -->
<div class="icon type"></div> <div class="icon type"></div>

View File

@@ -1,5 +1,6 @@
<a ng-href="#/manage/{{item.dataSource}}/connections/{{item.identifier}}" <a ng-href="#/manage/{{item.dataSource}}/connections/{{item.identifier}}"
ng-class="{active: item.getActiveConnections()}"> ng-class="{active: item.getActiveConnections()}"
class="settings-connection">
<!-- Connection icon --> <!-- Connection icon -->
<div class="icon type" ng-class="item.protocol"></div> <div class="icon type" ng-class="item.protocol"></div>

View File

@@ -1,4 +1,5 @@
<a ng-href="#/manage/{{item.dataSource}}/connectionGroups/{{item.identifier}}"> <a ng-href="#/manage/{{item.dataSource}}/connectionGroups/{{item.identifier}}"
class="settings-connection-group">
<!-- Connection group icon --> <!-- Connection group icon -->
<div class="icon type"></div> <div class="icon type"></div>

View File

@@ -1,3 +1,4 @@
<a ng-href="#/manage/{{item.dataSource}}/connections/?parent={{item.wrappedItem.identifier}}"> <a ng-href="#/manage/{{item.dataSource}}/connections/?parent={{item.wrappedItem.identifier}}"
class="new-connection">
<span class="name">{{'SETTINGS_CONNECTIONS.ACTION_NEW_CONNECTION' | translate}}</span> <span class="name">{{'SETTINGS_CONNECTIONS.ACTION_NEW_CONNECTION' | translate}}</span>
</a> </a>

View File

@@ -1,3 +1,4 @@
<a ng-href="#/manage/{{item.dataSource}}/connectionGroups/?parent={{item.wrappedItem.identifier}}"> <a ng-href="#/manage/{{item.dataSource}}/connectionGroups/?parent={{item.wrappedItem.identifier}}"
class="new-connection-group">
<span class="name">{{'SETTINGS_CONNECTIONS.ACTION_NEW_CONNECTION_GROUP' | translate}}</span> <span class="name">{{'SETTINGS_CONNECTIONS.ACTION_NEW_CONNECTION_GROUP' | translate}}</span>
</a> </a>

View File

@@ -1,3 +1,4 @@
<a ng-href="#/manage/{{item.dataSource}}/sharingProfiles/?parent={{item.wrappedItem.identifier}}"> <a ng-href="#/manage/{{item.dataSource}}/sharingProfiles/?parent={{item.wrappedItem.identifier}}"
class="new-sharing-profile">
<span class="name">{{'SETTINGS_CONNECTIONS.ACTION_NEW_SHARING_PROFILE' | translate}}</span> <span class="name">{{'SETTINGS_CONNECTIONS.ACTION_NEW_SHARING_PROFILE' | translate}}</span>
</a> </a>

View File

@@ -1,5 +1,4 @@
<div class="settings-view view">
<div class="view">
<div class="header tabbed"> <div class="header tabbed">
<h2>{{'SETTINGS.SECTION_HEADER_SETTINGS' | translate}}</h2> <h2>{{'SETTINGS.SECTION_HEADER_SETTINGS' | translate}}</h2>

View File

@@ -1,4 +1,5 @@
<a ng-href="#/manage/{{item.dataSource}}/sharingProfiles/{{item.identifier}}"> <a ng-href="#/manage/{{item.dataSource}}/sharingProfiles/{{item.identifier}}"
class="settings-sharing-profile">
<!-- Sharing profile icon --> <!-- Sharing profile icon -->
<div class="icon type"></div> <div class="icon type"></div>