mirror of
https://github.com/portainer/portainer.git
synced 2025-08-02 20:35:25 +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
22
app/edge/components/edge-job-form/cron-method-options.tsx
Normal file
22
app/edge/components/edge-job-form/cron-method-options.tsx
Normal file
|
@ -0,0 +1,22 @@
|
|||
import { Calendar, Edit } from 'lucide-react';
|
||||
|
||||
import { BoxSelectorOption } from '@@/BoxSelector';
|
||||
|
||||
export const cronMethodOptions: ReadonlyArray<BoxSelectorOption<string>> = [
|
||||
{
|
||||
id: 'config_basic',
|
||||
value: 'basic',
|
||||
icon: Calendar,
|
||||
iconType: 'badge',
|
||||
label: 'Basic configuration',
|
||||
description: 'Select date from calendar',
|
||||
},
|
||||
{
|
||||
id: 'config_advanced',
|
||||
value: 'advanced',
|
||||
icon: Edit,
|
||||
iconType: 'badge',
|
||||
label: 'Advanced configuration',
|
||||
description: 'Write your own cron rule',
|
||||
},
|
||||
] as const;
|
|
@ -34,33 +34,9 @@
|
|||
<!-- cron-input -->
|
||||
<!-- edge-job-method-select -->
|
||||
<div class="col-sm-12 form-section-title"> Edge job configuration </div>
|
||||
<div class="form-group"></div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<div class="boxselector_wrapper !mt-0">
|
||||
<div>
|
||||
<input type="radio" id="config_basic" ng-model="$ctrl.formValues.cronMethod" value="basic" />
|
||||
<label for="config_basic">
|
||||
<div class="boxselector_header vertical-center">
|
||||
<pr-icon icon="'calendar'"></pr-icon>
|
||||
Basic configuration
|
||||
</div>
|
||||
<p>Select date from calendar</p>
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<input type="radio" id="config_advanced" ng-model="$ctrl.formValues.cronMethod" value="advanced" />
|
||||
<label for="config_advanced">
|
||||
<div class="boxselector_header vertical-center">
|
||||
<pr-icon icon="'edit'"></pr-icon>
|
||||
Advanced configuration
|
||||
</div>
|
||||
<p>Write your own cron rule</p>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<box-selector slim="true" radio-name="'configuration'" value="$ctrl.formValues.cronMethod" options="$ctrl.cronMethods" on-change="($ctrl.onCronMethodChange)"></box-selector>
|
||||
|
||||
<!-- !edge-job-method-select -->
|
||||
<!-- basic-edge-job -->
|
||||
<div ng-if="$ctrl.formValues.cronMethod === 'basic'">
|
||||
|
@ -154,34 +130,10 @@
|
|||
<!-- execution-method -->
|
||||
<div ng-if="!$ctrl.model.Id">
|
||||
<div class="col-sm-12 form-section-title"> Job content </div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<div class="boxselector_wrapper">
|
||||
<div>
|
||||
<input type="radio" id="method_editor" ng-model="$ctrl.formValues.method" value="editor" />
|
||||
<label for="method_editor">
|
||||
<div class="boxselector_header vertical-center">
|
||||
<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.formValues.method" value="upload" />
|
||||
<label for="method_upload">
|
||||
<div class="boxselector_header vertical-center">
|
||||
<pr-icon icon="'upload'"></pr-icon>
|
||||
Upload
|
||||
</div>
|
||||
<p>Upload from your computer</p>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<box-selector value="$ctrl.formValues.method" options="$ctrl.buildMethods" radio-name="buildMethod" on-change="($ctrl.onBuildMethodChange)" slim="true"></box-selector>
|
||||
</div>
|
||||
<!-- !execution-method -->
|
||||
|
||||
<!-- web-editor -->
|
||||
<div ng-show="$ctrl.formValues.method === 'editor'">
|
||||
<div class="col-sm-12 form-section-title"> Web editor </div>
|
||||
|
|
|
@ -1,9 +1,20 @@
|
|||
import _ from 'lodash-es';
|
||||
import moment from 'moment';
|
||||
import { editor, upload } from '@@/BoxSelector/common-options/build-methods';
|
||||
|
||||
import { cronMethodOptions } from './cron-method-options';
|
||||
|
||||
export class EdgeJobFormController {
|
||||
/* @ngInject */
|
||||
constructor($async, $scope, EdgeGroupService, Notifications) {
|
||||
this.$scope = $scope;
|
||||
this.$async = $async;
|
||||
this.EdgeGroupService = EdgeGroupService;
|
||||
this.Notifications = Notifications;
|
||||
|
||||
this.cronMethods = cronMethodOptions;
|
||||
this.buildMethods = [editor, upload];
|
||||
|
||||
this.state = {
|
||||
formValidationError: '',
|
||||
};
|
||||
|
@ -34,17 +45,31 @@ export class EdgeJobFormController {
|
|||
this.cronRegex =
|
||||
/(@(annually|yearly|monthly|weekly|daily|hourly|reboot))|(@every (\d+(ns|us|µs|ms|s|m|h))+)|((((\d+,)+\d+|(\d+(\/|-)\d+)|\d+|\*) ){4,6}((\d+,)+\d+|(\d+(\/|-)\d+)|\d+|\*))/;
|
||||
|
||||
this.$async = $async;
|
||||
this.$scope = $scope;
|
||||
|
||||
this.action = this.action.bind(this);
|
||||
this.editorUpdate = this.editorUpdate.bind(this);
|
||||
this.associateEndpoint = this.associateEndpoint.bind(this);
|
||||
this.dissociateEndpoint = this.dissociateEndpoint.bind(this);
|
||||
this.onChangeGroups = this.onChangeGroups.bind(this);
|
||||
this.onChange = this.onChange.bind(this);
|
||||
this.onCronMethodChange = this.onCronMethodChange.bind(this);
|
||||
this.onBuildMethodChange = this.onBuildMethodChange.bind(this);
|
||||
}
|
||||
|
||||
this.EdgeGroupService = EdgeGroupService;
|
||||
this.Notifications = Notifications;
|
||||
onChange(values) {
|
||||
this.$scope.$evalAsync(() => {
|
||||
this.formValues = {
|
||||
...this.formValues,
|
||||
...values,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
onBuildMethodChange(value) {
|
||||
this.onChange({ method: value });
|
||||
}
|
||||
|
||||
onCronMethodChange(value) {
|
||||
this.onChange({ cronMethod: value });
|
||||
}
|
||||
|
||||
onChangeModel(model) {
|
||||
|
|
22
app/edge/components/group-form/group-type-options.tsx
Normal file
22
app/edge/components/group-form/group-type-options.tsx
Normal file
|
@ -0,0 +1,22 @@
|
|||
import { List, Tag } from 'lucide-react';
|
||||
|
||||
import { BoxSelectorOption } from '@@/BoxSelector';
|
||||
|
||||
export const groupTypeOptions: ReadonlyArray<BoxSelectorOption<boolean>> = [
|
||||
{
|
||||
id: 'static-group',
|
||||
value: false,
|
||||
label: 'Static',
|
||||
description: 'Manually select Edge environments',
|
||||
icon: List,
|
||||
iconType: 'badge',
|
||||
},
|
||||
{
|
||||
id: 'dynamic-group',
|
||||
value: true,
|
||||
label: 'Dynamic',
|
||||
description: 'Automatically associate environments via tags',
|
||||
icon: Tag,
|
||||
iconType: 'badge',
|
||||
},
|
||||
] as const;
|
|
@ -24,32 +24,8 @@
|
|||
</div>
|
||||
|
||||
<div class="col-sm-12 form-section-title"> Group type </div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<div class="boxselector_wrapper">
|
||||
<div class="boxselector">
|
||||
<input type="radio" id="static-group" ng-model="$ctrl.model.Dynamic" ng-value="false" ng-checked="!$ctrl.model.Dynamic" />
|
||||
<label for="static-group">
|
||||
<div class="boxselector_header vertical-center">
|
||||
<pr-icon icon="'list'"></pr-icon>
|
||||
Static
|
||||
</div>
|
||||
<p>Manually select Edge environments</p>
|
||||
</label>
|
||||
</div>
|
||||
<div class="boxselector">
|
||||
<input type="radio" id="dynamic-group" ng-model="$ctrl.model.Dynamic" ng-value="true" ng-checked="$ctrl.model.Dynamic" />
|
||||
<label for="dynamic-group">
|
||||
<div class="boxselector_header vertical-center">
|
||||
<pr-icon icon="'tag'"></pr-icon>
|
||||
Dynamic
|
||||
</div>
|
||||
<p>Automatically associate environments via tags</p>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<box-selector slim="true" value="$ctrl.model.Dynamic" on-change="($ctrl.onChangeDynamic)" options="$ctrl.groupTypeOptions"></box-selector>
|
||||
|
||||
<!-- StaticGroup -->
|
||||
<div ng-if="!$ctrl.model.Dynamic">
|
||||
|
@ -78,32 +54,8 @@
|
|||
<!-- DynamicGroup -->
|
||||
<div ng-if="$ctrl.model.Dynamic">
|
||||
<div class="col-sm-12 form-section-title"> Tags </div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<div class="boxselector_wrapper">
|
||||
<div class="boxselector">
|
||||
<input type="radio" id="or-selector" ng-model="$ctrl.model.PartialMatch" ng-value="true" ng-checked="$ctrl.model.PartialMatch" />
|
||||
<label for="or-selector">
|
||||
<div class="boxselector_header vertical-center">
|
||||
<pr-icon icon="'tag'"></pr-icon>
|
||||
Partial match
|
||||
</div>
|
||||
<p>Associate any environment matching at least one of the selected tags</p>
|
||||
</label>
|
||||
</div>
|
||||
<div class="boxselector">
|
||||
<input type="radio" id="and-selector" ng-model="$ctrl.model.PartialMatch" ng-value="false" ng-checked="!$ctrl.model.PartialMatch" />
|
||||
<label for="and-selector">
|
||||
<div class="boxselector_header vertical-center">
|
||||
<pr-icon icon="'tag'"></pr-icon>
|
||||
Full match
|
||||
</div>
|
||||
<p>Associate any environment matching all of the selected tags</p>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<box-selector slim="true" value="$ctrl.model.PartialMatch" on-change="($ctrl.onChangePartialMatch)" options="$ctrl.tagOptions"></box-selector>
|
||||
|
||||
<tag-selector ng-if="$ctrl.model.TagIds" value="$ctrl.model.TagIds" on-change="($ctrl.onChangeTags)"> </tag-selector>
|
||||
|
||||
|
|
|
@ -4,6 +4,8 @@ import { EdgeTypes } from '@/react/portainer/environments/types';
|
|||
import { getEnvironments } from '@/react/portainer/environments/environment.service';
|
||||
import { getTags } from '@/portainer/tags/tags.service';
|
||||
import { notifyError } from '@/portainer/services/notifications';
|
||||
import { groupTypeOptions } from './group-type-options';
|
||||
import { tagOptions } from './tag-options';
|
||||
|
||||
export class EdgeGroupFormController {
|
||||
/* @ngInject */
|
||||
|
@ -11,6 +13,9 @@ export class EdgeGroupFormController {
|
|||
this.$async = $async;
|
||||
this.$scope = $scope;
|
||||
|
||||
this.groupTypeOptions = groupTypeOptions;
|
||||
this.tagOptions = tagOptions;
|
||||
|
||||
this.endpoints = {
|
||||
state: {
|
||||
limit: '10',
|
||||
|
@ -28,6 +33,9 @@ export class EdgeGroupFormController {
|
|||
this.getDynamicEndpointsAsync = this.getDynamicEndpointsAsync.bind(this);
|
||||
this.getDynamicEndpoints = this.getDynamicEndpoints.bind(this);
|
||||
this.onChangeTags = this.onChangeTags.bind(this);
|
||||
this.onChangeDynamic = this.onChangeDynamic.bind(this);
|
||||
this.onChangeModel = this.onChangeModel.bind(this);
|
||||
this.onChangePartialMatch = this.onChangePartialMatch.bind(this);
|
||||
|
||||
$scope.$watch(
|
||||
() => this.model,
|
||||
|
@ -40,12 +48,27 @@ export class EdgeGroupFormController {
|
|||
);
|
||||
}
|
||||
|
||||
onChangeTags(value) {
|
||||
onChangeModel(model) {
|
||||
return this.$scope.$evalAsync(() => {
|
||||
this.model.TagIds = value;
|
||||
this.model = {
|
||||
...this.model,
|
||||
...model,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
onChangePartialMatch(value) {
|
||||
return this.onChangeModel({ PartialMatch: value });
|
||||
}
|
||||
|
||||
onChangeDynamic(value) {
|
||||
this.onChangeModel({ Dynamic: value });
|
||||
}
|
||||
|
||||
onChangeTags(value) {
|
||||
this.onChangeModel({ TagIds: value });
|
||||
}
|
||||
|
||||
associateEndpoint(endpoint) {
|
||||
if (!_.includes(this.model.Endpoints, endpoint.Id)) {
|
||||
this.model.Endpoints = [...this.model.Endpoints, endpoint.Id];
|
||||
|
|
23
app/edge/components/group-form/tag-options.tsx
Normal file
23
app/edge/components/group-form/tag-options.tsx
Normal file
|
@ -0,0 +1,23 @@
|
|||
import { Tag } from 'lucide-react';
|
||||
|
||||
import { BoxSelectorOption } from '@@/BoxSelector';
|
||||
|
||||
export const tagOptions: ReadonlyArray<BoxSelectorOption<boolean>> = [
|
||||
{
|
||||
id: 'or-selector',
|
||||
value: true,
|
||||
label: 'Partial Match',
|
||||
description:
|
||||
'Associate any environment matching at least one of the selected tags',
|
||||
icon: Tag,
|
||||
iconType: 'badge',
|
||||
},
|
||||
{
|
||||
id: 'and-selector',
|
||||
value: false,
|
||||
label: 'Full Match',
|
||||
description: 'Associate any environment matching all of the selected tags',
|
||||
icon: Tag,
|
||||
iconType: 'badge',
|
||||
},
|
||||
];
|
Loading…
Add table
Add a link
Reference in a new issue