mirror of
https://github.com/portainer/portainer.git
synced 2025-08-08 23:35:31 +02:00
feat(UX): introduce new env variables UI (#4175)
* feat(app): introduce new env vars ui feat(app): introduce new env vars ui feat(UX): WIP new env variables UI feat(UX): update button and placeholder feat(UX): mention .env file in message feat(UX): allow add/remove value & load correctly feat(UX): restrict filesize to 1MB feat(UX): vertical align error message feat(UX): fill UI from file & when switching modes feat(UX): strip un-needed newline character feat(UX): introduce component to other views feat(UX): fix title alignment feat(UX): only populate editor on mode switch when key exists feat(UX): prevent trimming of whitespace on values feat(UX): change editor to async feat(UX): add message describing use feat(UX): Refactor variable text to editorText refactor(app): rename env vars controller refactor(app): move env var explanation to parent refactor(app): order env var panels refactor(app): move simple env vars mode to component refactor(app): parse env vars refactor(app): move styles to css refactor(app): rename functions refactor(container): parse env vars refactor(env-vars): move utils to helper module refactor(env-vars): use util function for parse dot env file fix(env-vars): ignore comments refactor(services): use env vars utils refactor(env-vars): rename files refactor(env-panel): use utils style(stack): revert EnvContent to Env style(service): revert EnvContent to Env style(container): revert EnvContent to Env refactor(env-vars): support default value refactor(service): use new env var component refactor(env-var): use one way data flow refactor(containers): remove unused function * fix(env-vars): prevent using non .env files * refactor(env-vars): move env vars items to a component * feat(app): fixed env vars form validation in Stack * feat(services): disable env form submit if invalid * fix(app): show key pairs correctly * fix(env-var): use the same validation as with kubernetes * fix(env-vars): parse env var Co-authored-by: Chaim Lev-Ari <chiptus@gmail.com> Co-authored-by: Felix Han <felix.han@portainer.io>
This commit is contained in:
parent
6e9f472723
commit
a5e8cf62d2
24 changed files with 506 additions and 265 deletions
|
@ -1,8 +1,8 @@
|
|||
<div ng-if="service.EnvironmentVariables" id="service-env-variables">
|
||||
<ng-form ng-if="service.EnvironmentVariables" id="service-env-variables" name="serviceEnvForm">
|
||||
<rd-widget>
|
||||
<rd-widget-header icon="fa-tasks" title-text="Environment variables">
|
||||
<div class="nopadding" authorization="DockerServiceUpdate">
|
||||
<a class="btn btn-default btn-sm pull-right" ng-click="isUpdating ||addEnvironmentVariable(service)" ng-disabled="isUpdating">
|
||||
<a class="btn btn-default btn-sm pull-right" ng-click="isUpdating || addEnvironmentVariable(service)" ng-disabled="isUpdating">
|
||||
<i class="fa fa-plus-circle" aria-hidden="true"></i> environment variable
|
||||
</a>
|
||||
</div>
|
||||
|
@ -10,49 +10,20 @@
|
|||
<rd-widget-body ng-if="service.EnvironmentVariables.length === 0">
|
||||
<p>There are no environment variables for this service.</p>
|
||||
</rd-widget-body>
|
||||
<rd-widget-body ng-if="service.EnvironmentVariables.length > 0" classes="no-padding">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Value</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="var in service.EnvironmentVariables | orderBy: 'originalKey'">
|
||||
<td>
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="input-group-addon fit-text-size">name</span>
|
||||
<input type="text" class="form-control" ng-model="var.key" ng-disabled="var.added || isUpdating" placeholder="e.g. FOO" />
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="input-group-addon fit-text-size">value</span>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
ng-model="var.value"
|
||||
ng-change="updateEnvironmentVariable(service, var)"
|
||||
placeholder="e.g. bar"
|
||||
ng-disabled="isUpdating"
|
||||
disable-authorization="DockerServiceUpdate"
|
||||
/>
|
||||
<span class="input-group-btn" authorization="DockerServiceUpdate">
|
||||
<button class="btn btn-sm btn-danger" type="button" ng-click="removeEnvironmentVariable(service, var)" ng-disabled="isUpdating">
|
||||
<i class="fa fa-trash" aria-hidden="true"></i>
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<rd-widget-body ng-if="service.EnvironmentVariables.length > 0">
|
||||
<environment-variables-panel is-name-disabled="true" ng-model="service.EnvironmentVariables" on-change="(onChangeEnvVars)"></environment-variables-panel>
|
||||
</rd-widget-body>
|
||||
<rd-widget-footer authorization="DockerServiceUpdate">
|
||||
<div class="btn-toolbar" role="toolbar">
|
||||
<div class="btn-group" role="group">
|
||||
<button type="button" class="btn btn-primary btn-sm" ng-disabled="!hasChanges(service, ['EnvironmentVariables'])" ng-click="updateService(service)">Apply changes</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary btn-sm"
|
||||
ng-disabled="!hasChanges(service, ['EnvironmentVariables']) || serviceEnvForm.$invalid"
|
||||
ng-click="updateService(service)"
|
||||
>
|
||||
Apply changes
|
||||
</button>
|
||||
<button type="button" class="btn btn-default btn-sm dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
|
@ -64,4 +35,4 @@
|
|||
</div>
|
||||
</rd-widget-footer>
|
||||
</rd-widget>
|
||||
</div>
|
||||
</ng-form>
|
||||
|
|
|
@ -18,6 +18,9 @@ require('./includes/tasks.html');
|
|||
require('./includes/updateconfig.html');
|
||||
|
||||
import _ from 'lodash-es';
|
||||
|
||||
import * as envVarsUtils from '@/portainer/helpers/env-vars';
|
||||
|
||||
import { PorImageRegistryModel } from 'Docker/models/porImageRegistry';
|
||||
|
||||
angular.module('portainer.docker').controller('ServiceController', [
|
||||
|
@ -114,21 +117,25 @@ angular.module('portainer.docker').controller('ServiceController', [
|
|||
};
|
||||
|
||||
$scope.addEnvironmentVariable = function addEnvironmentVariable(service) {
|
||||
service.EnvironmentVariables.push({ key: '', value: '', originalValue: '' });
|
||||
service.EnvironmentVariables.push({ name: '', value: '' });
|
||||
updateServiceArray(service, 'EnvironmentVariables', service.EnvironmentVariables);
|
||||
};
|
||||
$scope.removeEnvironmentVariable = function removeEnvironmentVariable(service, item) {
|
||||
const index = service.EnvironmentVariables.indexOf(item);
|
||||
const removedElement = service.EnvironmentVariables.splice(index, 1);
|
||||
if (removedElement !== null) {
|
||||
updateServiceArray(service, 'EnvironmentVariables', service.EnvironmentVariables);
|
||||
}
|
||||
};
|
||||
$scope.updateEnvironmentVariable = function updateEnvironmentVariable(service, variable) {
|
||||
if (variable.value !== variable.originalValue || variable.key !== variable.originalKey) {
|
||||
updateServiceArray(service, 'EnvironmentVariables', service.EnvironmentVariables);
|
||||
}
|
||||
};
|
||||
|
||||
$scope.onChangeEnvVars = onChangeEnvVars;
|
||||
|
||||
function onChangeEnvVars(env) {
|
||||
const service = $scope.service;
|
||||
|
||||
const orgEnv = service.EnvironmentVariables;
|
||||
service.EnvironmentVariables = env.map((v) => {
|
||||
const orgVar = orgEnv.find(({ name }) => v.name === name);
|
||||
const added = orgVar && orgVar.added;
|
||||
return { ...v, added };
|
||||
});
|
||||
|
||||
updateServiceArray(service, 'EnvironmentVariables', service.EnvironmentVariables);
|
||||
}
|
||||
|
||||
$scope.addConfig = function addConfig(service, config) {
|
||||
if (
|
||||
config &&
|
||||
|
@ -395,7 +402,7 @@ angular.module('portainer.docker').controller('ServiceController', [
|
|||
var config = ServiceHelper.serviceToConfig(service.Model);
|
||||
config.Name = service.Name;
|
||||
config.Labels = LabelHelper.fromKeyValueToLabelHash(service.ServiceLabels);
|
||||
config.TaskTemplate.ContainerSpec.Env = ServiceHelper.translateEnvironmentVariablesToEnv(service.EnvironmentVariables);
|
||||
config.TaskTemplate.ContainerSpec.Env = envVarsUtils.convertToArrayOfStrings(service.EnvironmentVariables);
|
||||
config.TaskTemplate.ContainerSpec.Labels = LabelHelper.fromKeyValueToLabelHash(service.ServiceContainerLabels);
|
||||
|
||||
if ($scope.hasChanges(service, ['Image'])) {
|
||||
|
@ -625,7 +632,10 @@ angular.module('portainer.docker').controller('ServiceController', [
|
|||
function translateServiceArrays(service) {
|
||||
service.ServiceSecrets = service.Secrets ? service.Secrets.map(SecretHelper.flattenSecret) : [];
|
||||
service.ServiceConfigs = service.Configs ? service.Configs.map(ConfigHelper.flattenConfig) : [];
|
||||
service.EnvironmentVariables = ServiceHelper.translateEnvironmentVariables(service.Env);
|
||||
service.EnvironmentVariables = envVarsUtils
|
||||
.parseArrayOfStrings(service.Env)
|
||||
.map((v) => ({ ...v, added: true }))
|
||||
.sort((v1, v2) => (v1.name > v2.name ? 1 : -1));
|
||||
service.LogDriverOpts = ServiceHelper.translateLogDriverOptsToKeyValue(service.LogDriverOpts);
|
||||
service.ServiceLabels = LabelHelper.fromLabelHashToKeyValue(service.Labels);
|
||||
service.ServiceContainerLabels = LabelHelper.fromLabelHashToKeyValue(service.ContainerLabels);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue