Skip to content

Commit

Permalink
Merge pull request #2133 from cdcabrera/envfrom-enveditors
Browse files Browse the repository at this point in the history
Merged by openshift-bot
  • Loading branch information
OpenShift Bot authored Sep 27, 2017
2 parents ac5246b + 7165cef commit 18330d5
Show file tree
Hide file tree
Showing 11 changed files with 1,099 additions and 619 deletions.
1 change: 1 addition & 0 deletions app/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,7 @@ <h1>JavaScript Required</h1>
<script src="scripts/directives/deleteLink.js"></script>
<script src="scripts/directives/editWebhookTriggers.js"></script>
<script src="scripts/directives/editConfigMap.js"></script>
<script src="scripts/directives/editEnvironmentFrom.js"></script>
<script src="scripts/directives/events.js"></script>
<script src="scripts/directives/eventsSidebar.js"></script>
<script src="scripts/directives/eventsBadge.js"></script>
Expand Down
191 changes: 191 additions & 0 deletions app/scripts/directives/editEnvironmentFrom.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
"use strict";
(function() {
angular.module("openshiftConsole").component('editEnvironmentFrom', {
controller: [
'$attrs',
'$filter',
'keyValueEditorUtils',
EditEnvironmentFrom
],
bindings: {
addRowLink: '@', // creates a link to "add row" and sets its text label
entries: '=', // an array of objects containing configmaps and secrets
envFromSelectorOptions: '<', // dropdown selector options, an array of objects
selectorPlaceholder: '@' // placeholder copy for dropdown selector
},
templateUrl: 'views/directives/edit-environment-from.html'
});

function EditEnvironmentFrom($attrs,
$filter,
utils) {
var ctrl = this;

var canI = $filter('canI');
var humanizeKind = $filter('humanizeKind');
var uniqueId = _.uniqueId();

ctrl.setFocusClass = 'edit-environment-from-set-focus-' + uniqueId;

var addEntry = function(entries, entry) {
entries && entries.push(entry || {});
};

ctrl.onAddRow = function() {
addEntry(ctrl.envFromEntries);
utils.setFocusOn('.'+ ctrl.setFocusClass);
};

ctrl.deleteEntry = function(start, deleteCount) {
if(ctrl.envFromEntries && !ctrl.envFromEntries.length) {
return;
}

ctrl.envFromEntries.splice(start, deleteCount);
if(!ctrl.envFromEntries.length && ctrl.addRowLink) {
addEntry(ctrl.envFromEntries);
}

ctrl.updateEntries(ctrl.envFromEntries);
ctrl.editEnvironmentFromForm.$setDirty();
};

ctrl.isEnvFromReadonly = function(entry) {
return ctrl.isReadonlyAny ||
entry.isReadonlyValue === true ||
((entry.secretRef || entry.configMapRef) && !entry.selectedEnvFrom) ||
_.isEmpty(ctrl.envFromSelectorOptions);
};

ctrl.groupByKind = function(object) {
return humanizeKind(object.kind);
};

//ctrl.uniqueForValue = utils.uniqueForValue;
ctrl.dragControlListeners = {
accept: function (sourceItemHandleScope, destSortableScope) {
return sourceItemHandleScope.itemScope.sortableScope.$id === destSortableScope.$id;
},
orderChanged: function() {
ctrl.editEnvironmentFromForm.$setDirty();
}
};

ctrl.envFromObjectSelected = function(index, entry, selected) {
var newEnvFrom = {};

switch (selected.kind) {
case 'Secret':
newEnvFrom.secretRef = {
name: selected.metadata.name
};
delete ctrl.envFromEntries[index].configMapRef;
break;
case 'ConfigMap':
newEnvFrom.configMapRef = {
name: selected.metadata.name
};
delete ctrl.envFromEntries[index].secretRef;
break;
}

_.assign(ctrl.envFromEntries[index], newEnvFrom);
ctrl.updateEntries(ctrl.envFromEntries);
};

ctrl.updateEntries = function(entries) {
ctrl.entries = _.filter(entries, function (val) {
return val.secretRef || val.configMapRef;
});
};

var updateEnvFromEntries = function(entries) {
ctrl.envFromEntries = entries || [];

if(!ctrl.envFromEntries.length) {
addEntry(ctrl.envFromEntries);
}

_.each(ctrl.envFromEntries, function(entry) {
if(entry) {
if(entry.configMapRef && !canI('configmaps', 'get')) {
entry.isReadonlyValue = true;
}

if(entry.secretRef && !canI('secrets', 'get')) {
entry.isReadonlyValue = true;
}
}
});
};

var getReferenceValue = function(option) {
var referenceValue;

switch(option.kind) {
case 'ConfigMap':
referenceValue = _.find(ctrl.envFromEntries, {configMapRef: {name: option.metadata.name}});
break;
case 'Secret':
referenceValue = _.find(ctrl.envFromEntries, {secretRef: {name: option.metadata.name}});
break;
}

return referenceValue;
};

ctrl.checkEntries = function(option) {
return !!(getReferenceValue(option));
};

var findReferenceValueForEntries = function(entries, envFromSelectorOptions) {
ctrl.cannotAdd = (ctrl.isReadonlyAny || _.isEmpty(envFromSelectorOptions));

if(envFromSelectorOptions) {
_.each(envFromSelectorOptions, function(option) {
var referenceValue = getReferenceValue(option);

if (referenceValue) {
_.set(referenceValue, 'selectedEnvFrom', option);
}
});
}
};

ctrl.$onInit = function() {
updateEnvFromEntries(ctrl.entries);
findReferenceValueForEntries(ctrl.entries, ctrl.envFromSelectorOptions);

if('cannotDelete' in $attrs) {
ctrl.cannotDeleteAny = true;
}

if('cannotSort' in $attrs) {
ctrl.cannotSort = true;
}

if('isReadonly' in $attrs) {
ctrl.isReadonlyAny = true;
}

if('showHeader' in $attrs) {
ctrl.showHeader = true;
}

if(ctrl.envFromEntries && !ctrl.envFromEntries.length) {
addEntry(ctrl.envFromEntries);
}
};

ctrl.$onChanges = function(changes) {
if(changes.entries) {
updateEnvFromEntries(changes.entries.currentValue);
}

if(changes.envFromSelectorOptions) {
findReferenceValueForEntries(ctrl.envFromEntries, changes.envFromSelectorOptions.currentValue);
}
};
}
})();

10 changes: 8 additions & 2 deletions app/scripts/services/environment.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ angular.module("openshiftConsole")
var containers = getContainers(object);
_.each(containers, function(container) {
container.env = container.env || [];
container.envFrom = container.envFrom || [];
});
},

Expand Down Expand Up @@ -50,7 +51,7 @@ angular.module("openshiftConsole")
return false;
}

var i, leftEnv, rightEnv;
var i, leftEnv, rightEnv, leftEnvFrom, rightEnvFrom;
for (i = 0; i < leftContainers.length; i++) {
// If a container name has changed, consider it a conflict.
if (leftContainers[i].name !== rightContainers[i].name) {
Expand All @@ -60,7 +61,11 @@ angular.module("openshiftConsole")
// Check if any of the variable names or values are different.
leftEnv = leftContainers[i].env || [];
rightEnv = rightContainers[i].env || [];
if (!_.isEqual(leftEnv, rightEnv)) {

leftEnvFrom = leftContainers[i].envFrom || [];
rightEnvFrom = rightContainers[i].envFrom || [];

if (!_.isEqual(leftEnv, rightEnv) || !_.isEqual(leftEnvFrom, rightEnvFrom)) {
return false;
}
}
Expand All @@ -78,6 +83,7 @@ angular.module("openshiftConsole")
var targetContainers = getContainers(copy);
for (i = 0; i < targetContainers.length; i++) {
targetContainers[i].env = _.get(sourceContainers, [i, 'env'], []);
targetContainers[i].envFrom = _.get(sourceContainers, [i, 'envFrom'], []);
}

return copy;
Expand Down
39 changes: 34 additions & 5 deletions app/styles/_kve.less
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Angular Key Value Editor styles

.key-value-editor {
.key-value-editor,
.environment-from-editor {
&.as-sortable-dragging {
.as-sortable-item-delete,
.input-group-addon,
Expand Down Expand Up @@ -101,21 +102,47 @@
border-collapse: separate;
display: table;
position: relative;
&.faux-input-single-input {
width: 100%;
}
}

.key-value-editor-buttons {
.key-value-editor-buttons,
.environment-from-editor-button {
position: absolute;
right: 0;
top: 0;
width: (@as-sortable-item-button-width * 2);
}

.key-value-editor-entry {
.key-value-editor-entry,
.environment-from-entry {
display: table;
padding-right: (@as-sortable-item-button-width * 2);
position: relative;
table-layout: fixed;
width: 100%;
@media(min-width: @screen-md-min) {
.environment-from-editor-button {
float: left;
padding-right: 5px;
position: relative;
width: 50%;
}
}
.environment-from-input {
float: left;
padding-right: 5px;
width: 100%;
@media(min-width: @screen-md-min) {
width: 50%;
}
.faux-input-group,
.ui-select {
float: left;
width: 100%;
}
}
}

.key-value-editor-input .ui-select {
Expand All @@ -140,10 +167,12 @@
width: 50%;
}

.key-value-editor-entry-header {
.key-value-editor-entry-header,
.environment-from-editor-entry-header {
padding-right: (@as-sortable-item-button-width * 2);
}

.key-value-editor-header {
.key-value-editor-header,
.environment-from-editor-header {
margin-bottom: 5px;
}
81 changes: 81 additions & 0 deletions app/views/directives/edit-environment-from.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<ng-form name="$ctrl.editEnvironmentFromForm" novalidate>
<div
ng-if="$ctrl.showHeader"
class="environment-from-entry environment-from-editor-entry-header">
<div class="form-group environment-from-editor-header value-header">
<div class="input-group">
<span class="help-block">{{$ctrl.selectorPlaceholder}}</span>
</div>
</div>
</div>

<div ng-model="$ctrl.entries" class="environment-from-editor" as-sortable="$ctrl.dragControlListeners">
<div
class="environment-from-entry"
ng-class-odd="'odd'"
ng-class-even="'even'"
ng-repeat="entry in $ctrl.envFromEntries"
as-sortable-item>

<div class="form-group environment-from-input">
<div ng-if="$ctrl.isEnvFromReadonly(entry)" class="faux-input-group">
<div ng-if="!entry.configMapRef.name && !entry.secretRef.name">
No secrets or config maps have been added as Environment From.
</div>
<div ng-if="entry.configMapRef.name || entry.secretRef.name" class="faux-form-control readonly">
Use all keys and values from
<span ng-if="entry.configMapRef.name">config map {{entry.configMapRef.name}}</span>
<span ng-if="entry.secretRef.name">secret {{entry.secretRef.name}}</span>
</div>
</div>

<div ng-if="!$ctrl.isEnvFromReadonly(entry)">
<div class="ui-select">
<ui-select ng-model="entry.selectedEnvFrom"
ng-required="entry.selectedEnvFrom"
on-select="$ctrl.envFromObjectSelected($index, entry, $select.selected)"
ng-class="{'{{$ctrl.setFocusClass}}' : $last}">
<ui-select-match placeholder="Select a resource">
<span>
{{$select.selected.metadata.name}}
<small class="text-muted">&ndash; {{$select.selected.kind | humanizeKind : true}}</small>
</span>
</ui-select-match>
<ui-select-choices
ui-disable-choice="$ctrl.checkEntries(source)"
repeat="source in $ctrl.envFromSelectorOptions | filter : { metadata: { name: $select.search } } track by (source | uid)"
group-by="$ctrl.groupByKind">
<span ng-bind-html="source.metadata.name | highlight : $select.search"></span>
</ui-select-choices>
</ui-select>
</div>
</div>
</div>

<div ng-if="!$ctrl.isEnvFromReadonly(entry)" class="environment-from-editor-button">
<span
ng-if="!$ctrl.cannotSort"
class="fa fa-bars sort-row"
role="button"
aria-label="Move row"
aria-grabbed="false"
as-sortable-item-handle></span>
<a
ng-if="!$ctrl.cannotDeleteAny"
href=""
class="pficon pficon-close delete-row as-sortable-item-delete"
role="button"
aria-label="Delete row"
ng-click="$ctrl.deleteEntry($index, 1)"></a>
</div>
</div>

<div class="environment-from-entry form-group" ng-if="!$ctrl.cannotAdd">
<a
href=""
class="add-row-link"
role="button"
ng-click="$ctrl.onAddRow()">{{ $ctrl.addRowLink }}</a>
</div>
</div>
</ng-form>
Loading

0 comments on commit 18330d5

Please sign in to comment.