mirror of
https://github.com/portainer/portainer.git
synced 2025-08-08 15:25:22 +02:00
refactor(ui/box-selector): replace all selectors [EE-3856] (#7902)
This commit is contained in:
parent
c9253319d9
commit
2dddc1c6b9
80 changed files with 1267 additions and 1011 deletions
|
@ -35,12 +35,14 @@ export const BoxSelectorAngular: IComponentOptions = {
|
|||
on-change="$ctrl.handleChange"
|
||||
options="$ctrl.options"
|
||||
radio-name="$ctrl.radioName"
|
||||
slim="$ctrl.slim"
|
||||
></box-selector-react>`,
|
||||
bindings: {
|
||||
value: '<',
|
||||
onChange: '<',
|
||||
options: '<',
|
||||
radioName: '<',
|
||||
slim: '<',
|
||||
},
|
||||
require: {
|
||||
formCtrl: '^form',
|
||||
|
|
|
@ -8,10 +8,12 @@ import { BoxSelectorAngular } from './BoxSelectorAngular';
|
|||
|
||||
export { buildOption } from './utils';
|
||||
const BoxSelectorReact = react2angular(BoxSelector, [
|
||||
'isMulti',
|
||||
'value',
|
||||
'onChange',
|
||||
'options',
|
||||
'radioName',
|
||||
'slim',
|
||||
]);
|
||||
|
||||
export const boxSelectorModule = angular
|
||||
|
|
|
@ -4,11 +4,11 @@ import { BoxSelectorOption } from '@@/BoxSelector/types';
|
|||
import { IconProps } from '@@/Icon';
|
||||
|
||||
export function buildOption<T extends number | string>(
|
||||
id: string,
|
||||
id: BoxSelectorOption<T>['id'],
|
||||
icon: IconProps['icon'],
|
||||
label: string,
|
||||
description: string,
|
||||
value: T,
|
||||
label: BoxSelectorOption<T>['label'],
|
||||
description: BoxSelectorOption<T>['description'],
|
||||
value: BoxSelectorOption<T>['value'],
|
||||
feature?: FeatureId
|
||||
): BoxSelectorOption<T> {
|
||||
return { id, icon, label, description, value, feature };
|
||||
|
|
|
@ -15,57 +15,16 @@
|
|||
</div>
|
||||
<!-- !access-control-switch -->
|
||||
<!-- restricted-access -->
|
||||
<div class="form-group" ng-if="$ctrl.formData.AccessControlEnabled">
|
||||
<div class="col-sm-12">
|
||||
<div class="boxselector_wrapper">
|
||||
<div ng-if="$ctrl.isAdmin">
|
||||
<input type="radio" id="access_administrators" ng-model="$ctrl.formData.Ownership" value="administrators" />
|
||||
<label for="access_administrators" data-cy="portainer-selectAdminAccess">
|
||||
<div class="boxselector_header">
|
||||
<pr-icon icon="'eye-off'"></pr-icon>
|
||||
Administrators
|
||||
</div>
|
||||
<p class="boxselector_content">I want to restrict the management of this resource to administrators only</p>
|
||||
</label>
|
||||
</div>
|
||||
<div ng-if="$ctrl.isAdmin">
|
||||
<input type="radio" id="access_restricted" ng-model="$ctrl.formData.Ownership" value="restricted" />
|
||||
<label for="access_restricted" data-cy="portainer-selectRestrictedAccess">
|
||||
<div class="boxselector_header">
|
||||
<pr-icon icon="'users'"></pr-icon>
|
||||
Restricted
|
||||
</div>
|
||||
<p class="boxselector_content"> I want to restrict the management of this resource to a set of users and/or teams </p>
|
||||
</label>
|
||||
</div>
|
||||
<div ng-if="!$ctrl.isAdmin">
|
||||
<input type="radio" id="access_private" ng-model="$ctrl.formData.Ownership" value="private" />
|
||||
<label for="access_private">
|
||||
<div class="boxselector_header">
|
||||
<pr-icon icon="'eye-off'"></pr-icon>
|
||||
Private
|
||||
</div>
|
||||
<p> I want to restrict this resource to be manageable by myself only </p>
|
||||
</label>
|
||||
</div>
|
||||
<div ng-if="!$ctrl.isAdmin && $ctrl.availableTeams.length > 0">
|
||||
<input type="radio" id="access_restricted" ng-model="$ctrl.formData.Ownership" value="restricted" />
|
||||
<label for="access_restricted">
|
||||
<div class="boxselector_header">
|
||||
<pr-icon icon="'users'"></pr-icon>
|
||||
|
||||
Restricted
|
||||
</div>
|
||||
<p ng-if="$ctrl.availableTeams.length === 1">
|
||||
I want any member of my team (<b>{{ $ctrl.availableTeams[0].Name }}</b
|
||||
>) to be able to manage this resource
|
||||
</p>
|
||||
<p ng-if="$ctrl.availableTeams.length > 1"> I want to restrict the management of this resource to one or more of my teams </p>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<access-type-selector
|
||||
ng-if="$ctrl.formData.AccessControlEnabled"
|
||||
value="$ctrl.formData.Ownership"
|
||||
on-change="($ctrl.onChangeOwnership)"
|
||||
is-admin="$ctrl.isAdmin"
|
||||
name="Ownership"
|
||||
teams="$ctrl.availableTeams"
|
||||
></access-type-selector>
|
||||
|
||||
<!-- restricted-access -->
|
||||
<!-- authorized-teams -->
|
||||
<div
|
||||
|
|
|
@ -21,6 +21,13 @@ angular.module('portainer.app').controller('porAccessControlFormController', [
|
|||
ctrl.availableTeams = [];
|
||||
ctrl.availableUsers = [];
|
||||
|
||||
ctrl.onChangeEnablement = onChangeEnablement;
|
||||
ctrl.onChangeOwnership = onChangeOwnership;
|
||||
|
||||
function onChangeOwnership(ownership) {
|
||||
onChange({ Ownership: ownership });
|
||||
}
|
||||
|
||||
function setOwnership(resourceControl, isAdmin) {
|
||||
if (isAdmin && resourceControl.Ownership === RCO.PRIVATE) {
|
||||
ctrl.formData.Ownership = RCO.RESTRICTED;
|
||||
|
@ -88,15 +95,11 @@ angular.module('portainer.app').controller('porAccessControlFormController', [
|
|||
.catch(function error(err) {
|
||||
Notifications.error('Failure', err, 'Unable to retrieve access control information');
|
||||
});
|
||||
}
|
||||
|
||||
this.onChangeEnablement = function (enable) {
|
||||
$scope.$evalAsync(() => {
|
||||
ctrl.formData.AccessControlEnabled = enable;
|
||||
if (enable) {
|
||||
ctrl.formData.Ownership = isAdmin ? RCO.ADMINISTRATORS : RCO.PRIVATE;
|
||||
}
|
||||
});
|
||||
};
|
||||
function onChangeEnablement(enable) {
|
||||
const isAdmin = Authentication.isAdmin();
|
||||
onChange({ AccessControlEnabled: enable, Ownership: isAdmin ? RCO.ADMINISTRATORS : RCO.PRIVATE });
|
||||
}
|
||||
},
|
||||
]);
|
||||
|
|
|
@ -22,55 +22,16 @@
|
|||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group"></div>
|
||||
<!-- endpoint-tls-mode -->
|
||||
<div class="form-group" ng-if="$ctrl.formData.TLS">
|
||||
<div class="col-sm-12">
|
||||
<div class="boxselector_wrapper">
|
||||
<div>
|
||||
<input type="radio" id="tls_client_ca" ng-model="$ctrl.formData.TLSMode" value="tls_client_ca" />
|
||||
<label for="tls_client_ca">
|
||||
<div class="boxselector_header">
|
||||
<pr-icon icon="'shield'"></pr-icon>
|
||||
TLS with server and client verification
|
||||
</div>
|
||||
<p>Use client certificates and server verification</p>
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<input type="radio" id="tls_client_noca" ng-model="$ctrl.formData.TLSMode" value="tls_client_noca" />
|
||||
<label for="tls_client_noca">
|
||||
<div class="boxselector_header">
|
||||
<pr-icon icon="'shield'"></pr-icon>
|
||||
TLS with client verification only
|
||||
</div>
|
||||
<p>Use client certificates without server verification</p>
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<input type="radio" id="tls_ca" ng-model="$ctrl.formData.TLSMode" value="tls_ca" />
|
||||
<label for="tls_ca">
|
||||
<div class="boxselector_header">
|
||||
<pr-icon icon="'shield'"></pr-icon>
|
||||
TLS with server verification only
|
||||
</div>
|
||||
<p>Only verify the server certificate</p>
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<input type="radio" id="tls_only" ng-model="$ctrl.formData.TLSMode" value="tls_only" />
|
||||
<label for="tls_only">
|
||||
<div class="boxselector_header">
|
||||
<pr-icon icon="'shield'"></pr-icon>
|
||||
TLS only
|
||||
</div>
|
||||
<p>No server/client verification</p>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- !endpoint-tls-mode -->
|
||||
|
||||
<box-selector
|
||||
ng-if="$ctrl.formData.TLS"
|
||||
slim="true"
|
||||
radio-name="'tls_mode'"
|
||||
options="$ctrl.tlsOptions"
|
||||
value="$ctrl.formData.TLSMode"
|
||||
on-change="($ctrl.onChangeTLSMode)"
|
||||
></box-selector>
|
||||
|
||||
<div class="col-sm-12 form-section-title" ng-if="$ctrl.formData.TLS && $ctrl.formData.TLSMode !== 'tls_only'"> Required TLS files </div>
|
||||
<!-- tls-file-upload -->
|
||||
<div ng-if="$ctrl.formData.TLS">
|
||||
|
|
|
@ -1,13 +1,30 @@
|
|||
import { tlsOptions } from './tls-options';
|
||||
|
||||
angular.module('portainer.app').controller('porEndpointSecurityController', [
|
||||
'$scope',
|
||||
function ($scope) {
|
||||
var ctrl = this;
|
||||
|
||||
ctrl.onToggleTLS = function (newValue) {
|
||||
this.tlsOptions = tlsOptions;
|
||||
|
||||
function onChange(values) {
|
||||
$scope.$evalAsync(() => {
|
||||
ctrl.formData.TLS = newValue;
|
||||
ctrl.formData = {
|
||||
...ctrl.formData,
|
||||
...values,
|
||||
};
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
ctrl.onChangeTLSMode = onChangeTLSMode;
|
||||
function onChangeTLSMode(mode) {
|
||||
onChange({ TLSMode: mode });
|
||||
}
|
||||
|
||||
ctrl.onToggleTLS = onToggleTLS;
|
||||
function onToggleTLS(newValue) {
|
||||
onChange({ TLS: newValue });
|
||||
}
|
||||
|
||||
this.$onInit = $onInit;
|
||||
function $onInit() {
|
||||
|
|
38
app/portainer/components/endpointSecurity/tls-options.tsx
Normal file
38
app/portainer/components/endpointSecurity/tls-options.tsx
Normal file
|
@ -0,0 +1,38 @@
|
|||
import { Shield } from 'lucide-react';
|
||||
|
||||
import { BoxSelectorOption } from '@@/BoxSelector';
|
||||
|
||||
export const tlsOptions: ReadonlyArray<BoxSelectorOption<string>> = [
|
||||
{
|
||||
id: 'tls_client_ca',
|
||||
value: 'tls_client_ca',
|
||||
icon: Shield,
|
||||
iconType: 'badge',
|
||||
label: 'TLS with server and client verification',
|
||||
description: 'Use client certificates and server verification',
|
||||
},
|
||||
{
|
||||
id: 'tls_client_noca',
|
||||
value: 'tls_client_noca',
|
||||
icon: Shield,
|
||||
iconType: 'badge',
|
||||
label: 'TLS with client verification only',
|
||||
description: 'Use client certificates without server verification',
|
||||
},
|
||||
{
|
||||
id: 'tls_ca',
|
||||
value: 'tls_ca',
|
||||
icon: Shield,
|
||||
iconType: 'badge',
|
||||
label: 'TLS with server verification only',
|
||||
description: 'Only verify the server certificate',
|
||||
},
|
||||
{
|
||||
id: 'tls_only',
|
||||
value: 'tls_only',
|
||||
icon: Shield,
|
||||
iconType: 'badge',
|
||||
label: 'TLS only',
|
||||
description: 'No server/client verification',
|
||||
},
|
||||
] as const;
|
|
@ -18,6 +18,7 @@ import { InternalAuth } from '@/react/portainer/settings/AuthenticationView/Inte
|
|||
import { PorAccessControlFormTeamSelector } from '@/react/portainer/access-control/PorAccessControlForm/TeamsSelector';
|
||||
import { PorAccessControlFormUserSelector } from '@/react/portainer/access-control/PorAccessControlForm/UsersSelector';
|
||||
import { PorAccessManagementUsersSelector } from '@/react/portainer/access-control/AccessManagement/PorAccessManagementUsersSelector';
|
||||
import { AccessTypeSelector } from '@/react/portainer/access-control/EditDetails/AccessTypeSelector';
|
||||
|
||||
import { PageHeader } from '@@/PageHeader';
|
||||
import { TagSelector } from '@@/TagSelector';
|
||||
|
@ -66,6 +67,17 @@ export const componentsModule = angular
|
|||
'tagButton',
|
||||
r2a(TagButton, ['value', 'label', 'title', 'onRemove'])
|
||||
)
|
||||
.component(
|
||||
'accessTypeSelector',
|
||||
r2a(AccessTypeSelector, [
|
||||
'isAdmin',
|
||||
'isPublicVisible',
|
||||
'name',
|
||||
'onChange',
|
||||
'value',
|
||||
'teams',
|
||||
])
|
||||
)
|
||||
.component(
|
||||
'portainerTooltip',
|
||||
r2a(Tooltip, ['message', 'position', 'className', 'setHtmlMessage'])
|
||||
|
|
|
@ -15,42 +15,15 @@
|
|||
<!-- build-method -->
|
||||
<div ng-if="!$ctrl.state.fromStack">
|
||||
<div class="col-sm-12 form-section-title"> Build method </div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<div class="boxselector_wrapper">
|
||||
<div>
|
||||
<input type="radio" id="method_editor" ng-model="$ctrl.state.Method" value="editor" ng-change="$ctrl.onChangeMethod()" />
|
||||
<label for="method_editor">
|
||||
<div class="boxselector_header">
|
||||
<pr-icon icon="'edit'"></pr-icon>
|
||||
Web editor
|
||||
</div>
|
||||
<p>Use our Web editor</p>
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<input type="radio" id="method_upload" ng-model="$ctrl.state.Method" value="upload" ng-change="$ctrl.onChangeMethod()" />
|
||||
<label for="method_upload">
|
||||
<div class="boxselector_header">
|
||||
<pr-icon icon="'upload'"></pr-icon>
|
||||
Upload
|
||||
</div>
|
||||
<p>Upload from your computer</p>
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<input type="radio" id="method_repository" ng-model="$ctrl.state.Method" value="repository" ng-change="$ctrl.onChangeMethod()" />
|
||||
<label for="method_repository">
|
||||
<div class="boxselector_header">
|
||||
<pr-icon icon="'git-pull-request'"></pr-icon>
|
||||
Repository
|
||||
</div>
|
||||
<p>Use a git repository</p>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<box-selector
|
||||
slim="true"
|
||||
options="$ctrl.buildMethods"
|
||||
value="$ctrl.state.Method"
|
||||
on-change="($ctrl.onChangeMethod)"
|
||||
radio-name="'buildMethod'"
|
||||
slim="true"
|
||||
></box-selector>
|
||||
</div>
|
||||
<!-- !build-method -->
|
||||
<!-- web-editor -->
|
||||
|
|
|
@ -3,14 +3,29 @@ import { AccessControlFormData } from 'Portainer/components/accessControlForm/po
|
|||
import { TEMPLATE_NAME_VALIDATION_REGEX } from '@/constants';
|
||||
import { getTemplateVariables, intersectVariables } from '@/react/portainer/custom-templates/components/utils';
|
||||
import { isBE } from '@/react/portainer/feature-flags/feature-flags.service';
|
||||
import { editor, upload, git } from '@@/BoxSelector/common-options/build-methods';
|
||||
|
||||
class CreateCustomTemplateViewController {
|
||||
/* @ngInject */
|
||||
constructor($async, $state, $window, Authentication, ModalService, CustomTemplateService, FormValidator, Notifications, ResourceControlService, StackService, StateManager) {
|
||||
constructor(
|
||||
$async,
|
||||
$state,
|
||||
$scope,
|
||||
$window,
|
||||
Authentication,
|
||||
ModalService,
|
||||
CustomTemplateService,
|
||||
FormValidator,
|
||||
Notifications,
|
||||
ResourceControlService,
|
||||
StackService,
|
||||
StateManager
|
||||
) {
|
||||
Object.assign(this, {
|
||||
$async,
|
||||
$state,
|
||||
$window,
|
||||
$scope,
|
||||
Authentication,
|
||||
ModalService,
|
||||
CustomTemplateService,
|
||||
|
@ -21,6 +36,8 @@ class CreateCustomTemplateViewController {
|
|||
StateManager,
|
||||
});
|
||||
|
||||
this.buildMethods = [editor, upload, git];
|
||||
|
||||
this.isTemplateVariablesEnabled = isBE;
|
||||
|
||||
this.formValues = {
|
||||
|
@ -85,10 +102,13 @@ class CreateCustomTemplateViewController {
|
|||
return this.$async(this.createCustomTemplateAsync);
|
||||
}
|
||||
|
||||
onChangeMethod() {
|
||||
this.formValues.FileContent = '';
|
||||
this.formValues.Variables = [];
|
||||
this.selectedTemplate = null;
|
||||
onChangeMethod(method) {
|
||||
return this.$scope.$evalAsync(() => {
|
||||
this.formValues.FileContent = '';
|
||||
this.formValues.Variables = [];
|
||||
this.selectedTemplate = null;
|
||||
this.state.Method = method;
|
||||
});
|
||||
}
|
||||
|
||||
async createCustomTemplateAsync() {
|
||||
|
|
|
@ -16,22 +16,8 @@
|
|||
<!-- !name-input -->
|
||||
<!-- build-method -->
|
||||
<div class="col-sm-12 form-section-title"> Profile configuration </div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<div class="boxselector_wrapper">
|
||||
<div>
|
||||
<input type="radio" id="method_editor" ng-model="state.method" value="editor" />
|
||||
<label for="method_editor">
|
||||
<div class="boxselector_header">
|
||||
<pr-icon icon="'edit'"></pr-icon>
|
||||
Web editor
|
||||
</div>
|
||||
<p>Use our Web editor</p>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<box-selector slim="true" options="buildMethods" value="state.method"></box-selector>
|
||||
|
||||
<!-- !build-method -->
|
||||
|
||||
<web-editor-form
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
import angular from 'angular';
|
||||
import { editor } from '@@/BoxSelector/common-options/build-methods';
|
||||
|
||||
import { createProfile } from 'Portainer/hostmanagement/fdo/fdo.service';
|
||||
|
||||
angular.module('portainer.app').controller('AddProfileController', AddProfileController);
|
||||
|
||||
export default function AddProfileController($scope, $async, $state, $window, ModalService, Authentication, Notifications) {
|
||||
$scope.buildMethods = [editor];
|
||||
|
||||
$scope.formValues = {
|
||||
name: '',
|
||||
profileFileContent: '',
|
||||
|
|
|
@ -16,23 +16,9 @@
|
|||
<!-- !name-input -->
|
||||
<!-- build-method -->
|
||||
<div class="col-sm-12 form-section-title"> Profile configuration </div>
|
||||
<div class="form-group"></div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<div class="boxselector_wrapper">
|
||||
<div>
|
||||
<input type="radio" id="method_editor" ng-model="state.method" value="editor" />
|
||||
<label for="method_editor">
|
||||
<div class="boxselector_header">
|
||||
<pr-icon icon="'edit'"></pr-icon>
|
||||
Web editor
|
||||
</div>
|
||||
<p>Use our Web editor</p>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<box-selector slim="true" options="buildMethods" value="state.method"></box-selector>
|
||||
|
||||
<!-- !build-method -->
|
||||
|
||||
<web-editor-form
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
import angular from 'angular';
|
||||
import { editor } from '@@/BoxSelector/common-options/build-methods';
|
||||
import { getProfile, updateProfile } from 'Portainer/hostmanagement/fdo/fdo.service';
|
||||
|
||||
angular.module('portainer.app').controller('EditProfileController', EditProfileController);
|
||||
|
||||
export default function EditProfileController($scope, $async, $state, $window, ModalService, Authentication, Notifications) {
|
||||
$scope.buildMethods = [editor];
|
||||
|
||||
$scope.formValues = {
|
||||
name: '',
|
||||
profileFileContent: '',
|
||||
|
|
|
@ -131,37 +131,9 @@
|
|||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- !note -->
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<div class="boxselector_wrapper">
|
||||
<div>
|
||||
<input type="radio" id="restore_file" checked="checked" />
|
||||
<label for="restore_file" data-cy="init-selectLocalFile">
|
||||
<div class="boxselector_header">
|
||||
<pr-icon icon="'upload'"></pr-icon>
|
||||
Upload backup file
|
||||
</div>
|
||||
<p></p>
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<input type="radio" id="restore_s3" disabled />
|
||||
<label for="restore_s3" class="boxselector_disabled">
|
||||
<div class="boxselector_header">
|
||||
<pr-icon icon="'download'"></pr-icon>
|
||||
Retrieve from S3
|
||||
</div>
|
||||
<p
|
||||
>This feature is available in
|
||||
<a class="hyperlink" href="https://www.portainer.io/business-upsell?from=restore-s3-form" target="_blank"> Portainer Business Edition</a></p
|
||||
>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- note -->
|
||||
|
||||
<box-selector slim="true" options="restoreOptions" value="formValues.restoreFormType" on-change="(onChangeRestoreType)" radio-name="'restore-type'"></box-selector>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<span class="small text-muted"> You can upload a backup file from your computer. </span>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { getEnvironments } from '@/react/portainer/environments/environment.service';
|
||||
import { restoreOptions } from './restore-options';
|
||||
|
||||
angular.module('portainer.app').controller('InitAdminController', [
|
||||
'$scope',
|
||||
|
@ -11,6 +12,8 @@ angular.module('portainer.app').controller('InitAdminController', [
|
|||
'BackupService',
|
||||
'StatusService',
|
||||
function ($scope, $state, Notifications, Authentication, StateManager, SettingsService, UserService, BackupService, StatusService) {
|
||||
$scope.restoreOptions = restoreOptions;
|
||||
|
||||
$scope.uploadBackup = uploadBackup;
|
||||
|
||||
$scope.logo = StateManager.getState().application.logo;
|
||||
|
@ -35,6 +38,13 @@ angular.module('portainer.app').controller('InitAdminController', [
|
|||
$scope.state.showRestorePortainer = !$scope.state.showRestorePortainer;
|
||||
};
|
||||
|
||||
$scope.onChangeRestoreType = onChangeRestoreType;
|
||||
function onChangeRestoreType(value) {
|
||||
$scope.$evalAsync(() => {
|
||||
$scope.formValues.restoreFormType = value;
|
||||
});
|
||||
}
|
||||
|
||||
$scope.createAdminUser = function () {
|
||||
var username = $scope.formValues.Username;
|
||||
var password = $scope.formValues.Password;
|
||||
|
|
23
app/portainer/views/init/admin/restore-options.tsx
Normal file
23
app/portainer/views/init/admin/restore-options.tsx
Normal file
|
@ -0,0 +1,23 @@
|
|||
import { Download, Upload } from 'lucide-react';
|
||||
|
||||
import { FeatureId } from '@/react/portainer/feature-flags/enums';
|
||||
|
||||
import { BoxSelectorOption } from '@@/BoxSelector';
|
||||
|
||||
export const restoreOptions: ReadonlyArray<BoxSelectorOption<string>> = [
|
||||
{
|
||||
id: 'restore_file',
|
||||
value: 'file',
|
||||
icon: Upload,
|
||||
iconType: 'badge',
|
||||
label: 'Upload backup file',
|
||||
},
|
||||
{
|
||||
id: 'restore_s3',
|
||||
value: 's3',
|
||||
icon: Download,
|
||||
iconType: 'badge',
|
||||
label: 'Retrieve from S3',
|
||||
feature: FeatureId.S3_RESTORE,
|
||||
},
|
||||
] as const;
|
|
@ -278,7 +278,7 @@
|
|||
<form class="form-horizontal" ng-submit="backupPortainer()" name="backupPortainerForm">
|
||||
<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 slim="true" options="backupOptions" value="formValues.backupFormType" on-change="(onBackupOptionsChange)" radio-name="'backupOptions'"></box-selector>
|
||||
|
||||
<div ng-if="formValues.backupFormType === BACKUP_FORM_TYPES.S3">
|
||||
<!-- Schedule automatic backups -->
|
||||
|
|
|
@ -7,6 +7,7 @@ import { RepositoryMechanismTypes } from '@/kubernetes/models/deploy';
|
|||
import { FeatureId } from '@/react/portainer/feature-flags/enums';
|
||||
import { isBE } from '@/react/portainer/feature-flags/feature-flags.service';
|
||||
import { renderTemplate } from '@/react/portainer/custom-templates/components/utils';
|
||||
import { editor, upload, git, customTemplate } from '@@/BoxSelector/common-options/build-methods';
|
||||
|
||||
angular
|
||||
.module('portainer.app')
|
||||
|
@ -37,6 +38,7 @@ angular
|
|||
$scope.isTemplateVariablesEnabled = isBE;
|
||||
$scope.buildAnalyticsProperties = buildAnalyticsProperties;
|
||||
$scope.stackWebhookFeature = FeatureId.STACK_WEBHOOK;
|
||||
$scope.buildMethods = [editor, upload, git, customTemplate];
|
||||
$scope.STACK_NAME_VALIDATION_REGEX = STACK_NAME_VALIDATION_REGEX;
|
||||
$scope.isAdmin = Authentication.isAdmin();
|
||||
|
||||
|
@ -83,6 +85,13 @@ angular
|
|||
});
|
||||
|
||||
$scope.onChangeFormValues = onChangeFormValues;
|
||||
$scope.onBuildMethodChange = onBuildMethodChange;
|
||||
|
||||
function onBuildMethodChange(value) {
|
||||
$scope.$evalAsync(() => {
|
||||
$scope.state.Method = value;
|
||||
});
|
||||
}
|
||||
|
||||
$scope.onEnableWebhookChange = function (enable) {
|
||||
$scope.$evalAsync(() => {
|
||||
|
|
|
@ -49,52 +49,9 @@
|
|||
</div>
|
||||
<!-- build-method -->
|
||||
<div class="col-sm-12 form-section-title"> Build method </div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<div class="boxselector_wrapper">
|
||||
<div>
|
||||
<input type="radio" id="method_editor" ng-model="state.Method" value="editor" />
|
||||
<label for="method_editor">
|
||||
<div class="boxselector_header">
|
||||
<pr-icon icon="'edit'"></pr-icon>
|
||||
Web editor
|
||||
</div>
|
||||
<p>Use our Web editor</p>
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<input type="radio" id="method_upload" ng-model="state.Method" value="upload" />
|
||||
<label for="method_upload">
|
||||
<div class="boxselector_header">
|
||||
<pr-icon icon="'upload'"></pr-icon>
|
||||
Upload
|
||||
</div>
|
||||
<p>Upload from your computer</p>
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<input type="radio" id="method_repository" ng-model="state.Method" value="repository" />
|
||||
<label for="method_repository">
|
||||
<div class="boxselector_header">
|
||||
<pr-icon icon="'git-pull-request'"></pr-icon>
|
||||
Repository
|
||||
</div>
|
||||
<p>Use a git repository</p>
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<input type="radio" id="method_template" ng-model="state.Method" value="template" />
|
||||
<label for="method_template">
|
||||
<div class="boxselector_header">
|
||||
<pr-icon icon="'edit'"></pr-icon>
|
||||
Custom template
|
||||
</div>
|
||||
<p>Use a custom template</p>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<box-selector slim="true" radio-name="'build-method'" options="buildMethods" value="state.Method" on-change="(onBuildMethodChange)" slim="true"></box-selector>
|
||||
|
||||
<!-- !build-method -->
|
||||
|
||||
<!-- upload -->
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue