feat(ui): portainer settings page ui EE-3566 (#7259)

* settings page ui change
pull/7351/head
Richard Wei 2022-07-27 13:05:25 +12:00 committed by GitHub
parent 3239a61bda
commit ac6296b86d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 104 additions and 75 deletions

View File

@ -8,6 +8,7 @@ export const switchField = r2a(SwitchField, [
'label', 'label',
'name', 'name',
'labelClass', 'labelClass',
'fieldClass',
'dataCy', 'dataCy',
'disabled', 'disabled',
'onChange', 'onChange',

View File

@ -1,22 +1,27 @@
<div class="row"> <div class="row">
<div class="col-sm-12"> <div class="col-sm-12">
<rd-widget> <rd-widget>
<rd-widget-header icon="fa-key" title-text="SSL certificate"></rd-widget-header> <rd-widget-header icon="key" feather-icon="true" title-text="SSL certificate"></rd-widget-header>
<rd-widget-body> <rd-widget-body>
<form class="form-horizontal" name="$ctrl.sslForm"> <form class="form-horizontal" name="$ctrl.sslForm">
<span class="small"> <span class="small">
<p class="text-muted"> <p class="text-muted vertical-center">
<i class="fa fa-exclamation-circle orange-icon" aria-hidden="true" style="margin-right: 2px"></i> <pr-icon icon="'alert-circle'" feather="true" class-name="'icon-warning =vertical-center'"></pr-icon>
Forcing HTTPs only will cause Portainer to stop listening on the HTTP port. Any edge agent environment that is using HTTP will no longer be available. Forcing HTTPs only will cause Portainer to stop listening on the HTTP port. Any edge agent environment that is using HTTP will no longer be available.
</p> </p>
</span> </span>
<div class="form-group">
<por-switch-field checked="$ctrl.formValues.forceHTTPS" label="'Force HTTPS only'" on-change="($ctrl.onChangeForceHTTPS)"></por-switch-field> <por-switch-field
checked="$ctrl.formValues.forceHTTPS"
<hr /> label="'Force HTTPS only'"
on-change="($ctrl.onChangeForceHTTPS)"
field-class="'col-sm-12'"
label-class="'col-sm-2'"
></por-switch-field>
</div>
<div class="form-group"> <div class="form-group">
<span class="col-sm-12"> Provide a new SSL Certificate to replace the existing one that is used for HTTPS connections. </span> <span class="col-sm-12 control-label"> Provide a new SSL Certificate to replace the existing one that is used for HTTPS connections. </span>
</div> </div>
<div class="form-group"> <div class="form-group">
@ -28,7 +33,7 @@
<button class="btn btn-sm btn-primary" ngf-select ng-model="$ctrl.formValues.certFile" ngf-pattern="$ctrl.certFilePattern" name="certFile"> Select file </button> <button class="btn btn-sm btn-primary" ngf-select ng-model="$ctrl.formValues.certFile" ngf-pattern="$ctrl.certFilePattern" name="certFile"> Select file </button>
<span style="margin-left: 5px"> <span style="margin-left: 5px">
{{ $ctrl.formValues.certFile.name }} {{ $ctrl.formValues.certFile.name }}
<i class="fa fa-times red-icon" ng-if="!$ctrl.formValues.certFile" aria-hidden="true"></i> <pr-icon icon="'x-circle'" feather="true" class-name="'icon-danger'" ng-if="!$ctrl.formValues.certFile"></pr-icon>
</span> </span>
</div> </div>
</div> </div>
@ -49,7 +54,7 @@
<button class="btn btn-sm btn-primary" ngf-select ng-model="$ctrl.formValues.keyFile" ngf-pattern="$ctrl.keyFilePattern" name="keyFile"> Select file </button> <button class="btn btn-sm btn-primary" ngf-select ng-model="$ctrl.formValues.keyFile" ngf-pattern="$ctrl.keyFilePattern" name="keyFile"> Select file </button>
<span style="margin-left: 5px"> <span style="margin-left: 5px">
{{ $ctrl.formValues.keyFile.name }} {{ $ctrl.formValues.keyFile.name }}
<i class="fa fa-times red-icon" ng-if="!$ctrl.formValues.keyFile" aria-hidden="true"></i> <pr-icon icon="'x-circle'" feather="true" class-name="'icon-danger'" ng-if="!$ctrl.formValues.keyFile"></pr-icon>
</span> </span>
</div> </div>
</div> </div>
@ -61,7 +66,6 @@
</div> </div>
</div> </div>
<hr />
<div class="form-group"> <div class="form-group">
<div class="col-sm-12"> <div class="col-sm-12">
<button <button

View File

@ -0,0 +1,20 @@
import { FeatureId } from '@/portainer/feature-flags/enums';
export const options = [
{
id: 'backup_file',
icon: 'download',
featherIcon: true,
label: 'Download backup file',
value: 'file',
},
{
id: 'backup_s3',
icon: 'upload',
featherIcon: true,
label: 'Store in S3',
description: 'Define a cron schedule',
value: 's3',
feature: FeatureId.S3_BACKUP_SETTING,
},
];

View File

@ -3,28 +3,28 @@
<div class="row"> <div class="row">
<div class="col-sm-12"> <div class="col-sm-12">
<rd-widget> <rd-widget>
<rd-widget-header icon="fa-cogs" title-text="Application settings"></rd-widget-header> <rd-widget-header icon="settings" feather-icon="true" title-text="Application settings"></rd-widget-header>
<rd-widget-body> <rd-widget-body>
<form class="form-horizontal"> <form class="form-horizontal">
<!-- snapshot-interval --> <!-- snapshot-interval -->
<div class="form-group"> <div class="form-group">
<label for="snapshot_interval" class="col-sm-2 control-label text-left">Snapshot interval</label> <label for="snapshot_interval" class="col-sm-2 control-label text-left">Snapshot interval</label>
<div class="col-sm-10"> <div class="col-sm-8">
<input type="text" class="form-control" ng-model="settings.SnapshotInterval" id="snapshot_interval" placeholder="e.g. 15m" /> <input type="text" class="form-control" ng-model="settings.SnapshotInterval" id="snapshot_interval" placeholder="e.g. 15m" />
</div> </div>
</div> </div>
<!-- !snapshot-interval --> <!-- !snapshot-interval -->
<!-- logo --> <!-- logo -->
<div class="form-group"> <div class="form-group">
<div class="col-sm-12"> <por-switch-field
<por-switch-field label="'Use custom logo'"
label="'Use custom logo'" checked="formValues.customLogo"
checked="formValues.customLogo" name="'toggle_logo'"
name="'toggle_logo'" disabled="state.isDemo"
disabled="state.isDemo" on-change="(onToggleCustomLogo)"
on-change="(onToggleCustomLogo)" field-class="'col-sm-12'"
></por-switch-field> label-class="'col-sm-2'"
</div> ></por-switch-field>
<div class="col-sm-12" ng-if="state.isDemo" style="margin-top: 10px"> <div class="col-sm-12" ng-if="state.isDemo" style="margin-top: 10px">
<span class="small text-muted">You cannot use this feature in the demo version of Portainer.</span> <span class="small text-muted">You cannot use this feature in the demo version of Portainer.</span>
</div> </div>
@ -35,8 +35,8 @@
<span class="col-sm-12 text-muted small"> You can specify the URL to your logo here. For an optimal display, logo dimensions should be 155px by 55px. </span> <span class="col-sm-12 text-muted small"> You can specify the URL to your logo here. For an optimal display, logo dimensions should be 155px by 55px. </span>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="logo_url" class="col-sm-1 control-label text-left"> URL </label> <label for="logo_url" class="col-sm-2 control-label text-left"> URL </label>
<div class="col-sm-11"> <div class="col-sm-8">
<input type="text" class="form-control" ng-model="settings.LogoURL" id="logo_url" placeholder="https://mycompany.com/logo.png" /> <input type="text" class="form-control" ng-model="settings.LogoURL" id="logo_url" placeholder="https://mycompany.com/logo.png" />
</div> </div>
</div> </div>
@ -44,15 +44,15 @@
<!-- !logo --> <!-- !logo -->
<div class="form-group"> <div class="form-group">
<div class="col-sm-12"> <por-switch-field
<por-switch-field label="'Allow the collection of anonymous statistics'"
label="'Allow the collection of anonymous statistics'" checked="formValues.enableTelemetry"
checked="formValues.enableTelemetry" name="'toggle_enableTelemetry'"
name="'toggle_enableTelemetry'" on-change="(onToggleEnableTelemetry)"
on-change="(onToggleEnableTelemetry)" disabled="state.isDemo"
disabled="state.isDemo" field-class="'col-sm-12'"
></por-switch-field> label-class="'col-sm-2'"
</div> ></por-switch-field>
<div class="col-sm-12" ng-if="state.isDemo" style="margin-top: 10px"> <div class="col-sm-12" ng-if="state.isDemo" style="margin-top: 10px">
<span class="small text-muted">You cannot use this feature in the demo version of Portainer.</span> <span class="small text-muted">You cannot use this feature in the demo version of Portainer.</span>
</div> </div>
@ -71,8 +71,8 @@
</span> </span>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="templates_url" class="col-sm-1 control-label text-left"> URL </label> <label for="templates_url" class="col-sm-2 control-label text-left"> URL </label>
<div class="col-sm-11"> <div class="col-sm-8">
<input <input
type="text" type="text"
class="form-control" class="form-control"
@ -96,8 +96,8 @@
</span> </span>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="helmrepository_url" class="col-sm-1 control-label text-left"> URL </label> <label for="helmrepository_url" class="col-sm-2 control-label text-left"> URL </label>
<div class="col-sm-11"> <div class="col-sm-8">
<input type="text" class="form-control" ng-model="settings.HelmRepositoryURL" id="helmrepository_url" placeholder="https://charts.bitnami.com/bitnami" /> <input type="text" class="form-control" ng-model="settings.HelmRepositoryURL" id="helmrepository_url" placeholder="https://charts.bitnami.com/bitnami" />
</div> </div>
</div> </div>
@ -108,7 +108,7 @@
<div class="col-sm-12 form-section-title"> Kubernetes </div> <div class="col-sm-12 form-section-title"> Kubernetes </div>
<div class="form-group"> <div class="form-group">
<label for="kubeconfig_expiry" class="col-sm-2 control-label text-left"> Kubeconfig expiry </label> <label for="kubeconfig_expiry" class="col-sm-2 control-label text-left"> Kubeconfig expiry </label>
<div class="col-sm-10"> <div class="col-sm-8">
<select <select
id="kubeconfig_expiry" id="kubeconfig_expiry"
class="form-control" class="form-control"
@ -146,7 +146,7 @@
<div class="row"> <div class="row">
<div class="col-sm-12"> <div class="col-sm-12">
<rd-widget> <rd-widget>
<rd-widget-header icon="fa-tags" title-text="Hidden containers"></rd-widget-header> <rd-widget-header icon="box" feather-icon="true" title-text="Hidden containers"></rd-widget-header>
<rd-widget-body> <rd-widget-body>
<form class="form-horizontal" ng-submit="addFilteredContainerLabel()" name="addTagForm"> <form class="form-horizontal" ng-submit="addFilteredContainerLabel()" name="addTagForm">
<div class="form-group"> <div class="form-group">
@ -157,12 +157,12 @@
<div class="col-sm-11 col-md-4"> <div class="col-sm-11 col-md-4">
<input type="text" required class="form-control" id="header_name" name="label_name" ng-model="formValues.labelName" placeholder="e.g. com.example.foo" /> <input type="text" required class="form-control" id="header_name" name="label_name" ng-model="formValues.labelName" placeholder="e.g. com.example.foo" />
</div> </div>
<label for="header_value" class="col-sm-1 margin-sm-top control-label text-left">Value</label> <label for="header_value" class="col-sm-1 control-label text-left">Value</label>
<div class="col-sm-11 col-md-4 margin-sm-top"> <div class="col-sm-11 col-md-4">
<input type="text" class="form-control" id="header_value" ng-model="formValues.labelValue" placeholder="e.g. bar" /> <input type="text" class="form-control" id="header_value" ng-model="formValues.labelValue" placeholder="e.g. bar" />
</div> </div>
<div class="col-sm-12 col-md-2 margin-sm-top"> <div class="col-sm-12 col-md-2">
<button type="submit" class="btn btn-primary btn-sm" ng-disabled="!formValues.labelName"> <i class="fa fa-plus space-right" aria-hidden="true"></i>Add filter</button> <button type="submit" class="btn btn-primary btn-sm" ng-disabled="!formValues.labelName"><i class="fa fa-plus space-right" aria-hidden="true"></i>Add filter</button>
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
@ -205,24 +205,23 @@
<div class="row"> <div class="row">
<div class="col-sm-12"> <div class="col-sm-12">
<rd-widget> <rd-widget>
<rd-widget-header icon="fa-download" title-text="Backup Portainer"></rd-widget-header> <rd-widget-header icon="download" feather-icon="true" title-text="Backup Portainer"></rd-widget-header>
<rd-widget-body> <rd-widget-body>
<form class="form-horizontal" ng-submit="backupPortainer()" name="backupPortainerForm"> <form class="form-horizontal" ng-submit="backupPortainer()" name="backupPortainerForm">
<div class="col-sm-12 form-section-title"> Backup configuration </div> <div class="col-sm-12 form-section-title"> Backup configuration </div>
<box-selector options="backupOptions" value="formValues.backupFormType" on-change="(onBackupOptionsChange)" radio-name="'backupOptions'"></box-selector> <box-selector options="backupOptions" value="formValues.backupFormType" on-change="(onBackupOptionsChange)" radio-name="'backupOptions'"></box-selector>
<div ng-if="formValues.backupFormType === BACKUP_FORM_TYPES.S3"> <div ng-if="formValues.backupFormType === BACKUP_FORM_TYPES.S3">
<!-- Schedule automatic backups --> <!-- Schedule automatic backups -->
<div class="form-group"> <div class="form-group mt-3">
<div class="col-sm-12"> <por-switch-field
<por-switch-field label="'Schedule automatic backups'"
label="'Schedule automatic backups'" name="'s3-backup-setting'"
name="'s3-backup-setting'" feature-id="s3BackupFeatureId"
feature-id="s3BackupFeatureId" checked="formValues.scheduleAutomaticBackups"
checked="formValues.scheduleAutomaticBackups" field-class="'col-sm-12'"
label-class="'col-sm-2'" label-class="'col-sm-2'"
on-change="(onToggleAutoBackups)" on-change="(onToggleAutoBackups)"
></por-switch-field> ></por-switch-field>
</div>
</div> </div>
<!-- !Schedule automatic backups --> <!-- !Schedule automatic backups -->
<!-- Cron rule --> <!-- Cron rule -->
@ -321,18 +320,24 @@
<div class="col-sm-12 form-section-title"> Security settings </div> <div class="col-sm-12 form-section-title"> Security settings </div>
<!-- Password protect S3 --> <!-- Password protect S3 -->
<div class="form-group"> <div class="form-group">
<label for="password_protect" class="col-sm-1 control-label text-left">Password protect</label> <label for="password_protect" class="col-sm-2 control-label text-left">Password protect</label>
<div class="col-sm-1"> <div class="col-sm-8">
<label class="switch" data-cy="settings-s3PasswordToggle"> <label class="switch">
<input type="checkbox" id="password_protect_s3" name="password_protect_s3" ng-model="formValues.passwordProtectS3" disabled /> <input
<i></i> type="checkbox"
id="password_protect_s3"
name="password_protect_s3"
ng-model="formValues.passwordProtectS3"
data-cy="settings-passwordProtectToggleS3"
disabled
/><span class="slider round"></span>
</label> </label>
</div> </div>
</div> </div>
<!-- !Password protect S3 --> <!-- !Password protect S3 -->
<!-- Password S3 --> <!-- Password S3 -->
<div class="form-group" ng-if="formValues.passwordProtectS3"> <div class="form-group" ng-if="formValues.passwordProtectS3">
<label for="password" class="col-sm-1 control-label text-left">Password</label> <label for="password" class="col-sm-2 control-label text-left">Password</label>
<div class="col-sm-3"> <div class="col-sm-3">
<input type="password" class="form-control" ng-model="formValues.passwordS3" id="password_S3" name="password_S3" required data-cy="settings-backups3pw" /> <input type="password" class="form-control" ng-model="formValues.passwordS3" id="password_S3" name="password_S3" required data-cy="settings-backups3pw" />
</div> </div>
@ -340,7 +345,7 @@
<div class="form-group col-md-12" ng-show="backupPortainerForm.password_S3.$invalid"> <div class="form-group col-md-12" ng-show="backupPortainerForm.password_S3.$invalid">
<div class="small text-warning"> <div class="small text-warning">
<div ng-messages="backupPortainerForm.password_S3.$error"> <div ng-messages="backupPortainerForm.password_S3.$error">
<p ng-message="required"> <i class="fa fa-exclamation-triangle" aria-hidden="true"></i> This field is required.</p> <p ng-message="required"> <pr-icon icon="'alert-triangle'" feather="true"></pr-icon> This field is required.</p>
</div> </div>
</div> </div>
</div> </div>
@ -381,11 +386,10 @@
<div class="col-sm-12 form-section-title"> Security settings </div> <div class="col-sm-12 form-section-title"> Security settings </div>
<!-- Password protect --> <!-- Password protect -->
<div class="form-group"> <div class="form-group">
<label for="password_protect" class="col-sm-1 control-label text-left">Password protect</label> <label for="password_protect" class="col-sm-2 control-label text-left">Password protect</label>
<div class="col-sm-1"> <div class="col-sm-2">
<label class="switch" data-cy="settings-passwordProtectLocal"> <label class="switch" data-cy="settings-passwordProtectLocal">
<input type="checkbox" id="password_protect" name="password_protect" ng-model="formValues.passwordProtect" /> <input type="checkbox" id="password_protect" name="password_protect" ng-model="formValues.passwordProtect" /><span class="slider round"></span>
<i></i>
</label> </label>
</div> </div>
</div> </div>
@ -393,7 +397,7 @@
<!-- Password --> <!-- Password -->
<div class="form-group" ng-if="formValues.passwordProtect"> <div class="form-group" ng-if="formValues.passwordProtect">
<label for="password" class="col-sm-1 control-label text-left">Password</label> <label for="password" class="col-sm-2 control-label text-left">Password</label>
<div class="col-sm-3"> <div class="col-sm-3">
<input type="password" class="form-control" ng-model="formValues.password" id="password" name="password" required data-cy="settings-backupLocalPassword" /> <input type="password" class="form-control" ng-model="formValues.password" id="password" name="password" required data-cy="settings-backupLocalPassword" />
</div> </div>
@ -401,7 +405,7 @@
<div class="form-group col-md-12" ng-show="backupPortainerForm.password.$invalid"> <div class="form-group col-md-12" ng-show="backupPortainerForm.password.$invalid">
<div class="small text-warning"> <div class="small text-warning">
<div ng-messages="backupPortainerForm.password.$error"> <div ng-messages="backupPortainerForm.password.$error">
<p ng-message="required"> <i class="fa fa-exclamation-triangle" aria-hidden="true"></i> This field is required.</p> <p ng-message="required"> <pr-icon icon="'alert-triangle'" feather="true"></pr-icon> This field is required.</p>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,7 +1,7 @@
import angular from 'angular'; import angular from 'angular';
import { buildOption } from '@/portainer/components/BoxSelector';
import { FeatureId } from '@/portainer/feature-flags/enums'; import { FeatureId } from '@/portainer/feature-flags/enums';
import { options } from './options';
angular.module('portainer.app').controller('SettingsController', [ angular.module('portainer.app').controller('SettingsController', [
'$scope', '$scope',
@ -14,10 +14,8 @@ angular.module('portainer.app').controller('SettingsController', [
'Blob', 'Blob',
function ($scope, $state, Notifications, SettingsService, StateManager, BackupService, FileSaver) { function ($scope, $state, Notifications, SettingsService, StateManager, BackupService, FileSaver) {
$scope.s3BackupFeatureId = FeatureId.S3_BACKUP_SETTING; $scope.s3BackupFeatureId = FeatureId.S3_BACKUP_SETTING;
$scope.backupOptions = [
buildOption('backup_file', 'fa fa-download', 'Download backup file', '', 'file'), $scope.backupOptions = options;
buildOption('backup_s3', 'fa fa-upload', 'Store in S3', 'Define a cron schedule', 's3', FeatureId.S3_BACKUP_SETTING),
];
$scope.state = { $scope.state = {
isDemo: false, isDemo: false,

View File

@ -16,6 +16,7 @@ export interface Props {
tooltip?: string; tooltip?: string;
labelClass?: string; labelClass?: string;
switchClass?: string; switchClass?: string;
fieldClass?: string;
dataCy?: string; dataCy?: string;
disabled?: boolean; disabled?: boolean;
featureId?: FeatureId; featureId?: FeatureId;
@ -31,6 +32,7 @@ export function SwitchField({
label, label,
name, name,
labelClass, labelClass,
fieldClass,
dataCy, dataCy,
disabled, disabled,
onChange, onChange,
@ -41,10 +43,10 @@ export function SwitchField({
const toggleName = name ? `toggle_${name}` : ''; const toggleName = name ? `toggle_${name}` : '';
return ( return (
<label className={styles.root}> <label className={clsx(styles.root, fieldClass)}>
<span <span
className={clsx( className={clsx(
'control-label text-left space-right', 'text-left space-right control-label',
styles.label, styles.label,
labelClass labelClass
)} )}