Skip to content

Commit 6d37d67

Browse files
authored
GUACAMOLE-2220: Merge add K8s support for terminal-type.
2 parents 894dca4 + 2908053 commit 6d37d67

5 files changed

Lines changed: 110 additions & 14 deletions

File tree

guacamole-ext/src/main/java/org/apache/guacamole/form/Field.java

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import com.fasterxml.jackson.annotation.JsonInclude;
2323
import com.fasterxml.jackson.annotation.JsonInclude.Include;
2424
import java.util.Collection;
25+
import java.util.Map;
2526

2627
/**
2728
* Represents an arbitrary field, such as an HTTP parameter, the parameter of a
@@ -147,6 +148,31 @@ public static class Type {
147148
*/
148149
private Collection<String> options;
149150

151+
/**
152+
* Conditionally overrides this field's label with an alternate
153+
* label based on the value of another field.
154+
*
155+
* This value is a map of string keys to values, similar to a
156+
* JSON object. For example:
157+
*
158+
* {
159+
* "field" : "exec-command",
160+
* "equals" : "",
161+
* "labelKey" : "FIELD_HEADER_TERMINAL_TYPE_ATTACH"
162+
* }
163+
*
164+
* Supported entries include:
165+
* - "field" : (String) name of the field to evaluate
166+
* - "equals" : (Object) value the field must equal (optional)
167+
* - "notEquals" : (Object) value the field must not equal (optional)
168+
* - "labelKey" : (String) label key to use if the condition
169+
* matches
170+
*
171+
* Exactly one of "equals" or "notEquals" should be specified. If both
172+
* are specified, "equals" takes precedence and "notEquals" is ignored.
173+
*/
174+
private Map<String, Object> conditionalLabel;
175+
150176
/**
151177
* Creates a new Parameter with no associated name or type.
152178
*/
@@ -247,4 +273,25 @@ public void setOptions(Collection<String> options) {
247273
this.options = options;
248274
}
249275

276+
/**
277+
* Returns the conditional label definition for this field, or null if the
278+
* label is unconditional.
279+
*
280+
* @return
281+
* The conditional label map, or null.
282+
*/
283+
public Map<String, Object> getConditionalLabel() {
284+
return conditionalLabel;
285+
}
286+
287+
/**
288+
* Sets the conditional label definition for this field.
289+
*
290+
* @param conditionalLabel
291+
* The conditional label map, or null for no condition.
292+
*/
293+
public void setConditionalLabel(Map<String, Object> conditionalLabel) {
294+
this.conditionalLabel = conditionalLabel;
295+
}
296+
250297
}

guacamole-ext/src/main/resources/org/apache/guacamole/protocols/kubernetes.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,16 @@
119119
"name" : "backspace",
120120
"type" : "ENUM",
121121
"options" : [ "", "127", "8" ]
122+
},
123+
{
124+
"name" : "terminal-type",
125+
"type" : "ENUM",
126+
"options" : [ "", "xterm", "xterm-256color", "vt220", "vt100", "ansi", "linux" ],
127+
"conditionalLabel" : {
128+
"field" : "exec-command",
129+
"equals" : "",
130+
"labelKey" : "FIELD_HEADER_TERMINAL_TYPE_ATTACH"
131+
}
122132
}
123133
]
124134
},

guacamole/src/main/frontend/src/app/form/directives/formField.js

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,15 @@ angular.module('form').directive('guacFormField', [function formField() {
7575
*
7676
* @type ManagedClient
7777
*/
78-
client: '='
78+
client: '=',
79+
80+
/**
81+
* All current field values in the form, keyed by field name.
82+
* Required to evaluate conditionalLabel conditions.
83+
*
84+
* @type Object.<String, String>
85+
*/
86+
values: '='
7987

8088
},
8189
templateUrl: 'app/form/templates/formField.html',
@@ -107,27 +115,47 @@ angular.module('form').directive('guacFormField', [function formField() {
107115
}) + '-' + new Date().getTime().toString(36);
108116

109117
/**
110-
* Produces the translation string for the header of the current
111-
* field. The translation string will be of the form:
112-
*
113-
* <code>NAMESPACE.FIELD_HEADER_NAME<code>
114-
*
115-
* where <code>NAMESPACE</code> is the namespace provided to the
116-
* directive and <code>NAME</code> is the field name transformed
117-
* via translationStringService.canonicalize().
118+
* Returns the translation key for this field's label, of the form
119+
* NAMESPACE.FIELD_HEADER_NAME. If the field defines a
120+
* conditionalLabel and its condition is met, returns the alternate
121+
* key instead.
118122
*
119123
* @returns {String}
120-
* The translation string which produces the translated header
121-
* of the field.
122124
*/
123125
$scope.getFieldHeader = function getFieldHeader() {
124126

125127
// If no field, or no name, then no header
126128
if (!$scope.field || !$scope.field.name)
127129
return '';
128130

129-
return translationStringService.canonicalize($scope.namespace || 'MISSING_NAMESPACE')
130-
+ '.FIELD_HEADER_' + translationStringService.canonicalize($scope.field.name);
131+
var ns = translationStringService.canonicalize($scope.namespace || 'MISSING_NAMESPACE');
132+
133+
var conditionalLabel = $scope.field.conditionalLabel;
134+
if (conditionalLabel && conditionalLabel.labelKey && $scope.values) {
135+
136+
var depValue = $scope.values[conditionalLabel.field];
137+
if (depValue == null)
138+
depValue = '';
139+
140+
// equals and notEquals are mutually exclusive; equals wins if both are set
141+
var hasEquals = 'equals' in conditionalLabel;
142+
var hasNotEquals = 'notEquals' in conditionalLabel;
143+
var conditionMet;
144+
if (hasEquals)
145+
conditionMet = depValue === conditionalLabel.equals;
146+
else if (hasNotEquals)
147+
conditionMet = depValue !== conditionalLabel.notEquals;
148+
else {
149+
$log.warn('conditionalLabel for field "' + $scope.field.name
150+
+ '" specifies neither "equals" nor "notEquals"; ignoring.');
151+
conditionMet = false;
152+
}
153+
154+
if (conditionMet)
155+
return ns + '.' + conditionalLabel.labelKey;
156+
}
157+
158+
return ns + '.FIELD_HEADER_' + translationStringService.canonicalize($scope.field.name);
131159

132160
};
133161

guacamole/src/main/frontend/src/app/form/templates/form.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ <h3 class="form-header" ng-show="form.name">{{getSectionHeader(form) | translate
1414
focused="isFocused(field)"
1515
field="field"
1616
client="client"
17-
model="values[field.name]"></guac-form-field>
17+
model="values[field.name]"
18+
values="values"></guac-form-field>
1819
</div>
1920

2021
</div>

guacamole/src/main/frontend/src/translations/en.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,8 @@
531531
"FIELD_HEADER_RECORDING_NAME" : "Recording name:",
532532
"FIELD_HEADER_RECORDING_PATH" : "Recording path:",
533533
"FIELD_HEADER_SCROLLBACK" : "Maximum scrollback size:",
534+
"FIELD_HEADER_TERMINAL_TYPE" : "Terminal type (available as $TERM in command):",
535+
"FIELD_HEADER_TERMINAL_TYPE_ATTACH" : "Terminal type (set manually in session):",
534536
"FIELD_HEADER_TYPESCRIPT_NAME" : "Typescript name:",
535537
"FIELD_HEADER_TYPESCRIPT_PATH" : "Typescript path:",
536538
"FIELD_HEADER_TYPESCRIPT_WRITE_EXISTING" : "@:APP.FIELD_HEADER_TYPESCRIPT_WRITE_EXISTING",
@@ -562,6 +564,14 @@
562564
"FIELD_OPTION_FONT_SIZE_96" : "96",
563565
"FIELD_OPTION_FONT_SIZE_EMPTY" : "",
564566

567+
"FIELD_OPTION_TERMINAL_TYPE_ANSI" : "ansi",
568+
"FIELD_OPTION_TERMINAL_TYPE_EMPTY" : "",
569+
"FIELD_OPTION_TERMINAL_TYPE_LINUX" : "linux",
570+
"FIELD_OPTION_TERMINAL_TYPE_VT100" : "vt100",
571+
"FIELD_OPTION_TERMINAL_TYPE_VT220" : "vt220",
572+
"FIELD_OPTION_TERMINAL_TYPE_XTERM" : "xterm",
573+
"FIELD_OPTION_TERMINAL_TYPE_XTERM_256COLOR" : "xterm-256color",
574+
565575
"NAME" : "Kubernetes",
566576

567577
"SECTION_HEADER_AUTHENTICATION" : "Authentication",

0 commit comments

Comments
 (0)