mirror of https://github.com/portainer/portainer
refactor(app): convert tag-selector to react [EE-2983] (#6783)
parent
75d854e6ad
commit
d52417c14f
|
@ -3,6 +3,7 @@ import '../app/assets/css';
|
|||
import { pushStateLocationPlugin, UIRouter } from '@uirouter/react';
|
||||
import { initialize as initMSW, mswDecorator } from 'msw-storybook-addon';
|
||||
import { handlers } from '@/setup-tests/server-handlers';
|
||||
import { QueryClient, QueryClientProvider } from 'react-query';
|
||||
|
||||
// Initialize MSW
|
||||
initMSW({
|
||||
|
@ -31,11 +32,17 @@ export const parameters = {
|
|||
},
|
||||
};
|
||||
|
||||
const testQueryClient = new QueryClient({
|
||||
defaultOptions: { queries: { retry: false } },
|
||||
});
|
||||
|
||||
export const decorators = [
|
||||
(Story) => (
|
||||
<UIRouter plugins={[pushStateLocationPlugin]}>
|
||||
<Story />
|
||||
</UIRouter>
|
||||
<QueryClientProvider client={testQueryClient}>
|
||||
<UIRouter plugins={[pushStateLocationPlugin]}>
|
||||
<Story />
|
||||
</UIRouter>
|
||||
</QueryClientProvider>
|
||||
),
|
||||
mswDecorator,
|
||||
];
|
||||
|
|
|
@ -807,13 +807,6 @@ json-tree .branch-preview {
|
|||
}
|
||||
/* !spinkit override */
|
||||
|
||||
/* uib-typeahead override */
|
||||
#scrollable-dropdown-menu .dropdown-menu {
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
/* !uib-typeahead override */
|
||||
|
||||
.kubectl-shell {
|
||||
display: block;
|
||||
text-align: center;
|
||||
|
|
|
@ -93,12 +93,9 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<tag-selector ng-if="$ctrl.tags.length" tags="$ctrl.tags" model="$ctrl.model.TagIds"></tag-selector>
|
||||
<div ng-if="$ctrl.tags && !$ctrl.tags.length" class="col-sm-12 small text-muted">
|
||||
No tags available. Head over to the <a ui-sref="portainer.tags">Tags view</a> to add tags
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<tag-selector ng-if="$ctrl.model.TagIds" value="$ctrl.model.TagIds" on-change="($ctrl.onChangeTags)"> </tag-selector>
|
||||
|
||||
<div class="col-sm-12 form-section-title"> Associated environments by tags </div>
|
||||
<div class="col-sm-12 form-group">
|
||||
<group-association-table
|
||||
|
|
|
@ -6,6 +6,7 @@ export class EdgeGroupFormController {
|
|||
constructor(EndpointService, $async, $scope) {
|
||||
this.EndpointService = EndpointService;
|
||||
this.$async = $async;
|
||||
this.$scope = $scope;
|
||||
|
||||
this.endpoints = {
|
||||
state: {
|
||||
|
@ -22,6 +23,7 @@ export class EdgeGroupFormController {
|
|||
this.dissociateEndpoint = this.dissociateEndpoint.bind(this);
|
||||
this.getDynamicEndpointsAsync = this.getDynamicEndpointsAsync.bind(this);
|
||||
this.getDynamicEndpoints = this.getDynamicEndpoints.bind(this);
|
||||
this.onChangeTags = this.onChangeTags.bind(this);
|
||||
|
||||
$scope.$watch(
|
||||
() => this.model,
|
||||
|
@ -34,6 +36,12 @@ export class EdgeGroupFormController {
|
|||
);
|
||||
}
|
||||
|
||||
onChangeTags(value) {
|
||||
return this.$scope.$evalAsync(() => {
|
||||
this.model.TagIds = value;
|
||||
});
|
||||
}
|
||||
|
||||
associateEndpoint(endpoint) {
|
||||
if (!_.includes(this.model.Endpoints, endpoint.Id)) {
|
||||
this.model.Endpoints = [...this.model.Endpoints, endpoint.Id];
|
||||
|
|
|
@ -8,7 +8,6 @@ angular.module('portainer.edge').component('edgeGroupForm', {
|
|||
bindings: {
|
||||
model: '<',
|
||||
groups: '<',
|
||||
tags: '<',
|
||||
formActionLabel: '@',
|
||||
formAction: '<',
|
||||
actionInProgress: '<',
|
||||
|
|
|
@ -13,9 +13,7 @@
|
|||
form-action-label="Add edge group"
|
||||
form-action="$ctrl.createGroup"
|
||||
groups="$ctrl.endpointGroups"
|
||||
tags="$ctrl.tags"
|
||||
model="$ctrl.model"
|
||||
on-change-tags="($ctrl.onChangeTags)"
|
||||
></edge-group-form>
|
||||
</rd-widget-body>
|
||||
</rd-widget>
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
export class CreateEdgeGroupController {
|
||||
/* @ngInject */
|
||||
constructor(EdgeGroupService, GroupService, TagService, Notifications, $state, $async) {
|
||||
constructor(EdgeGroupService, GroupService, Notifications, $state, $async) {
|
||||
this.EdgeGroupService = EdgeGroupService;
|
||||
this.GroupService = GroupService;
|
||||
this.TagService = TagService;
|
||||
this.Notifications = Notifications;
|
||||
this.$state = $state;
|
||||
this.$async = $async;
|
||||
|
@ -26,8 +25,8 @@ export class CreateEdgeGroupController {
|
|||
}
|
||||
|
||||
async $onInit() {
|
||||
const [tags, endpointGroups] = await Promise.all([this.TagService.tags(), this.GroupService.groups()]);
|
||||
this.tags = tags;
|
||||
const endpointGroups = await this.GroupService.groups();
|
||||
|
||||
this.endpointGroups = endpointGroups;
|
||||
this.state.loaded = true;
|
||||
}
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
form-action="$ctrl.updateGroup"
|
||||
endpoints="$ctrl.endpoints"
|
||||
groups="$ctrl.endpointGroups"
|
||||
tags="$ctrl.tags"
|
||||
model="$ctrl.model"
|
||||
></edge-group-form>
|
||||
</rd-widget-body>
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
export class EditEdgeGroupController {
|
||||
/* @ngInject */
|
||||
constructor(EdgeGroupService, GroupService, TagService, Notifications, $state, $async) {
|
||||
constructor(EdgeGroupService, GroupService, Notifications, $state, $async) {
|
||||
this.EdgeGroupService = EdgeGroupService;
|
||||
this.GroupService = GroupService;
|
||||
this.TagService = TagService;
|
||||
this.Notifications = Notifications;
|
||||
this.$state = $state;
|
||||
this.$async = $async;
|
||||
|
@ -18,13 +17,12 @@ export class EditEdgeGroupController {
|
|||
}
|
||||
|
||||
async $onInit() {
|
||||
const [tags, endpointGroups, group] = await Promise.all([this.TagService.tags(), this.GroupService.groups(), this.EdgeGroupService.group(this.$state.params.groupId)]);
|
||||
const [endpointGroups, group] = await Promise.all([this.GroupService.groups(), this.EdgeGroupService.group(this.$state.params.groupId)]);
|
||||
|
||||
if (!group) {
|
||||
this.Notifications.error('Failed to find edge group', {});
|
||||
this.$state.go('edge.groups');
|
||||
}
|
||||
this.tags = tags;
|
||||
this.endpointGroups = endpointGroups;
|
||||
this.model = group;
|
||||
this.state.loaded = true;
|
||||
|
|
|
@ -9,13 +9,11 @@ angular.module('portainer.app').component('groupForm', {
|
|||
pageType: '@',
|
||||
model: '=',
|
||||
availableEndpoints: '=',
|
||||
availableTags: '<',
|
||||
associatedEndpoints: '=',
|
||||
addLabelAction: '<',
|
||||
removeLabelAction: '<',
|
||||
formAction: '<',
|
||||
formActionLabel: '@',
|
||||
actionInProgress: '<',
|
||||
onCreateTag: '<',
|
||||
},
|
||||
});
|
||||
|
|
|
@ -23,17 +23,9 @@
|
|||
</div>
|
||||
<!-- !description-input -->
|
||||
<div class="col-sm-12 form-section-title"> Metadata </div>
|
||||
<!-- tags -->
|
||||
<div class="form-group">
|
||||
<tag-selector
|
||||
ng-if="$ctrl.model && $ctrl.availableTags"
|
||||
tags="$ctrl.availableTags"
|
||||
model="$ctrl.model.TagIds"
|
||||
allow-create="$ctrl.state.allowCreateTag"
|
||||
on-create="($ctrl.onCreateTag)"
|
||||
></tag-selector>
|
||||
</div>
|
||||
<!-- !tags -->
|
||||
|
||||
<tag-selector ng-if="$ctrl.model.TagIds" value="$ctrl.model.TagIds" on-change="($ctrl.onChangeTags)" allow-create="$ctrl.state.allowCreateTag"> </tag-selector>
|
||||
|
||||
<!-- environments -->
|
||||
<div ng-if="$ctrl.model.Id !== 1">
|
||||
<div class="col-sm-12 form-section-title"> Associated environments </div>
|
||||
|
|
|
@ -3,8 +3,9 @@ import angular from 'angular';
|
|||
|
||||
class GroupFormController {
|
||||
/* @ngInject */
|
||||
constructor($q, EndpointService, GroupService, Notifications, Authentication) {
|
||||
constructor($q, $scope, EndpointService, GroupService, Notifications, Authentication) {
|
||||
this.$q = $q;
|
||||
this.$scope = $scope;
|
||||
this.EndpointService = EndpointService;
|
||||
this.GroupService = GroupService;
|
||||
this.Notifications = Notifications;
|
||||
|
@ -13,6 +14,13 @@ class GroupFormController {
|
|||
this.associateEndpoint = this.associateEndpoint.bind(this);
|
||||
this.dissociateEndpoint = this.dissociateEndpoint.bind(this);
|
||||
this.getPaginatedEndpointsByGroup = this.getPaginatedEndpointsByGroup.bind(this);
|
||||
this.onChangeTags = this.onChangeTags.bind(this);
|
||||
}
|
||||
|
||||
onChangeTags(value) {
|
||||
return this.$scope.$evalAsync(() => {
|
||||
this.model.TagIds = value;
|
||||
});
|
||||
}
|
||||
|
||||
$onInit() {
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
angular.module('portainer.app').component('tagSelector', {
|
||||
templateUrl: './tagSelector.html',
|
||||
controller: 'TagSelectorController',
|
||||
bindings: {
|
||||
tags: '<',
|
||||
model: '=',
|
||||
onCreate: '<',
|
||||
allowCreate: '<',
|
||||
},
|
||||
});
|
|
@ -1,35 +0,0 @@
|
|||
<div ng-show="$ctrl.model.length > 0" class="col-sm-12" style="padding: 0; margin-bottom: 15px">
|
||||
<label class="col-sm-3 col-lg-2 control-label text-left"> Selected tags </label>
|
||||
<div class="col-sm-9 col-lg-10" style="padding-top: 4px">
|
||||
<span class="tag space-right interactive" ng-repeat="tag in $ctrl.state.selectedTags" ng-click="$ctrl.removeTag(tag)">
|
||||
{{ tag.Name }}
|
||||
<a title="Remove tag" ng-click="$ctrl.removeTag(tag)" style="margin-left: 2px">
|
||||
<span class="fa fa-trash-alt white-icon" aria-hidden="true"></span>
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12" style="padding: 0">
|
||||
<label for="tags" class="col-sm-3 col-lg-2 control-label text-left"> Tags </label>
|
||||
<div class="col-sm-9 col-lg-10" id="scrollable-dropdown-menu" ng-if="$ctrl.allowCreate || $ctrl.tags.length > 0">
|
||||
<input
|
||||
type="text"
|
||||
ng-model="$ctrl.state.selectedValue"
|
||||
id="tags"
|
||||
class="form-control"
|
||||
placeholder="Select tags..."
|
||||
uib-typeahead="tag.Id as tag.Name for tag in $ctrl.filterTags($viewValue)"
|
||||
typeahead-on-select="$ctrl.selectTag($item, $model, $label)"
|
||||
typeahead-no-results="$ctrl.state.noResult"
|
||||
typeahead-show-hint="true"
|
||||
typeahead-min-length="0"
|
||||
data-cy="tags-tagInput"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-sm-9 col-lg-10" ng-if="!$ctrl.allowCreate && $ctrl.tags.length === 0">
|
||||
<span class="small text-muted"> No tags available. </span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-offset-3 col-lg-offset-2 col-sm-12" ng-if="!$ctrl.allowCreate && $ctrl.state.noResult" style="margin-top: 2px">
|
||||
<span class="small text-muted"> No tags matching your filter. </span>
|
||||
</div>
|
|
@ -1,62 +0,0 @@
|
|||
import angular from 'angular';
|
||||
import _ from 'lodash-es';
|
||||
|
||||
class TagSelectorController {
|
||||
/* @ngInject */
|
||||
constructor() {
|
||||
this.state = {
|
||||
selectedValue: '',
|
||||
selectedTags: [],
|
||||
noResult: false,
|
||||
};
|
||||
}
|
||||
|
||||
removeTag(tag) {
|
||||
_.remove(this.model, (id) => tag.Id === id);
|
||||
_.remove(this.state.selectedTags, { Id: tag.Id });
|
||||
}
|
||||
|
||||
selectTag($item) {
|
||||
this.state.selectedValue = '';
|
||||
if ($item.create && this.allowCreate) {
|
||||
this.onCreate($item.value);
|
||||
return;
|
||||
}
|
||||
this.state.selectedTags.push($item);
|
||||
this.model.push($item.Id);
|
||||
}
|
||||
|
||||
filterTags(searchValue) {
|
||||
let filteredTags = _.filter(this.tags, (tag) => !_.includes(this.model, tag.Id));
|
||||
if (!searchValue) {
|
||||
return filteredTags;
|
||||
}
|
||||
|
||||
const exactTag = _.find(this.tags, (tag) => tag.Name === searchValue);
|
||||
filteredTags = _.filter(filteredTags, (tag) => _.includes(tag.Name.toLowerCase(), searchValue.toLowerCase()));
|
||||
if (exactTag || !this.allowCreate) {
|
||||
return filteredTags;
|
||||
}
|
||||
|
||||
return filteredTags.concat({ Name: `Create "${searchValue}"`, create: true, value: searchValue });
|
||||
}
|
||||
|
||||
generateSelectedTags(model, tags) {
|
||||
this.state.selectedTags = _.map(model, (id) => _.find(tags, (t) => t.Id === id));
|
||||
}
|
||||
|
||||
$onInit() {
|
||||
this.generateSelectedTags(this.model, this.tags);
|
||||
}
|
||||
|
||||
$onChanges({ tags, model }) {
|
||||
const tagsValue = tags && tags.currentValue ? tags.currentValue : this.tags;
|
||||
const modelValue = model && model.currentValue ? model.currentValue : this.model;
|
||||
if (modelValue && tagsValue) {
|
||||
this.generateSelectedTags(modelValue, tagsValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default TagSelectorController;
|
||||
angular.module('portainer.app').controller('TagSelectorController', TagSelectorController);
|
|
@ -1,6 +1,11 @@
|
|||
import angular from 'angular';
|
||||
|
||||
export const componentsModule = angular.module(
|
||||
'portainer.app.react.components',
|
||||
[]
|
||||
).name;
|
||||
import { r2a } from '@/react-tools/react2angular';
|
||||
import { TagSelector } from '@/react/components/TagSelector';
|
||||
|
||||
export const componentsModule = angular
|
||||
.module('portainer.app.react.components', [])
|
||||
.component(
|
||||
'tagSelector',
|
||||
r2a(TagSelector, ['allowCreate', 'onChange', 'value'])
|
||||
).name;
|
||||
|
|
|
@ -13,7 +13,7 @@ export async function getTags() {
|
|||
|
||||
export async function createTag(name: string) {
|
||||
try {
|
||||
const { data: tag } = await axios.post(buildUrl(), { name });
|
||||
const { data: tag } = await axios.post<Tag>(buildUrl(), { name });
|
||||
return tag;
|
||||
} catch (err) {
|
||||
throw parseAxiosError(err as Error, 'Unable to create tag');
|
||||
|
|
|
@ -188,12 +188,9 @@
|
|||
</div>
|
||||
</div>
|
||||
<!-- !group -->
|
||||
<!-- tags -->
|
||||
<div class="form-group">
|
||||
<tag-selector ng-if="formValues && availableTags" tags="availableTags" model="formValues.TagIds" allow-create="state.allowCreateTag" on-create="(onCreateTag)">
|
||||
</tag-selector>
|
||||
</div>
|
||||
<!-- !tags -->
|
||||
|
||||
<tag-selector ng-if="formValues" value="formValues.TagIds" allow-create="state.allowCreateTag" on-change="(onChangeTags)"> </tag-selector>
|
||||
|
||||
<!-- actions -->
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
|
|
|
@ -28,6 +28,12 @@ angular
|
|||
|
||||
$scope.profiles = [];
|
||||
|
||||
$scope.onChangeTags = function onChangeTags(value) {
|
||||
return $scope.$evalAsync(() => {
|
||||
$scope.formValues.TagIds = value;
|
||||
});
|
||||
};
|
||||
|
||||
$scope.onVoucherFilesChange = function () {
|
||||
if ($scope.formValues.VoucherFiles.length < 1) {
|
||||
return;
|
||||
|
@ -53,20 +59,6 @@ angular
|
|||
});
|
||||
};
|
||||
|
||||
$scope.onCreateTag = function onCreateTag(tagName) {
|
||||
return $async(onCreateTagAsync, tagName);
|
||||
};
|
||||
|
||||
async function onCreateTagAsync(tagName) {
|
||||
try {
|
||||
const tag = await TagService.createTag(tagName);
|
||||
$scope.availableTags = $scope.availableTags.concat(tag);
|
||||
$scope.formValues.TagIds = $scope.formValues.TagIds.concat(tag.Id);
|
||||
} catch (err) {
|
||||
Notifications.error('Failure', err, 'Unable to create tag');
|
||||
}
|
||||
}
|
||||
|
||||
$scope.createEndpointAndConfigureDevice = function () {
|
||||
return $async(async () => {
|
||||
$scope.state.actionInProgress = true;
|
||||
|
@ -133,11 +125,9 @@ angular
|
|||
|
||||
$q.all({
|
||||
groups: GroupService.groups(),
|
||||
tags: TagService.tags(),
|
||||
})
|
||||
.then(function success(data) {
|
||||
$scope.groups = data.groups;
|
||||
$scope.availableTags = data.tags;
|
||||
})
|
||||
.catch(function error(err) {
|
||||
Notifications.error('Failure', err, 'Unable to load groups');
|
||||
|
|
|
@ -17,7 +17,6 @@ angular
|
|||
clipboard,
|
||||
EndpointService,
|
||||
GroupService,
|
||||
TagService,
|
||||
SettingsService,
|
||||
Notifications,
|
||||
Authentication,
|
||||
|
@ -91,20 +90,12 @@ angular
|
|||
$scope.formValues.URL = '';
|
||||
};
|
||||
|
||||
$scope.onCreateTag = function onCreateTag(tagName) {
|
||||
return $async(onCreateTagAsync, tagName);
|
||||
$scope.onChangeTags = function onChangeTags(value) {
|
||||
return $scope.$evalAsync(() => {
|
||||
$scope.formValues.TagIds = value;
|
||||
});
|
||||
};
|
||||
|
||||
async function onCreateTagAsync(tagName) {
|
||||
try {
|
||||
const tag = await TagService.createTag(tagName);
|
||||
$scope.availableTags = $scope.availableTags.concat(tag);
|
||||
$scope.formValues.TagIds = $scope.formValues.TagIds.concat(tag.Id);
|
||||
} catch (err) {
|
||||
Notifications.error('Failure', err, 'Unable to create tag');
|
||||
}
|
||||
}
|
||||
|
||||
function onChangeCheckInInterval(value) {
|
||||
setFieldValue('EdgeCheckinInterval', value);
|
||||
}
|
||||
|
@ -310,12 +301,10 @@ angular
|
|||
function initView() {
|
||||
$q.all({
|
||||
groups: GroupService.groups(),
|
||||
tags: TagService.tags(),
|
||||
settings: SettingsService.settings(),
|
||||
})
|
||||
.then(function success(data) {
|
||||
$scope.groups = data.groups;
|
||||
$scope.availableTags = data.tags;
|
||||
|
||||
const settings = data.settings;
|
||||
|
||||
|
|
|
@ -436,12 +436,9 @@
|
|||
</div>
|
||||
</div>
|
||||
<!-- !group -->
|
||||
<!-- tags -->
|
||||
<div class="form-group">
|
||||
<tag-selector ng-if="formValues && availableTags" tags="availableTags" model="formValues.TagIds" allow-create="state.allowCreateTag" on-create="(onCreateTag)">
|
||||
</tag-selector>
|
||||
</div>
|
||||
<!-- !tags -->
|
||||
|
||||
<tag-selector ng-if="formValues" value="formValues.TagIds" allow-create="state.allowCreateTag" on-change="(onChangeTags)"> </tag-selector>
|
||||
|
||||
<div class="col-sm-12 form-section-title"> Actions </div>
|
||||
<!-- actions -->
|
||||
<div class="form-group">
|
||||
|
|
|
@ -60,7 +60,7 @@
|
|||
<div class="col-sm-12 form-section-title" style="margin-top: 25px"> Join token </div>
|
||||
<p>
|
||||
<i class="fa fa-info-circle blue-icon" aria-hidden="true" style="margin-right: 2px"></i>
|
||||
For those prestaging the edge agent, use the following join token to associate the Edge agent with this environment.
|
||||
For those pre-staging the edge agent, use the following join token to associate the Edge agent with this environment.
|
||||
</p>
|
||||
<p> You can read more about pre-staging in the userguide available <a href="https://downloads.portainer.io/edge_agent_guide.pdf">here.</a> </p>
|
||||
<div style="margin-top: 10px; overflow-wrap: break-word">
|
||||
|
@ -159,11 +159,9 @@
|
|||
</div>
|
||||
</div>
|
||||
<!-- !group -->
|
||||
<!-- tags -->
|
||||
<div class="form-group">
|
||||
<tag-selector ng-if="endpoint && availableTags" tags="availableTags" model="endpoint.TagIds" on-create="(onCreateTag)" allow-create="state.allowCreate"></tag-selector>
|
||||
</div>
|
||||
<!-- !tags -->
|
||||
|
||||
<tag-selector ng-if="endpoint" value="endpoint.TagIds" allow-create="state.allowCreate" on-change="(onChangeTags)"></tag-selector>
|
||||
|
||||
<!-- endpoint-security -->
|
||||
<div ng-if="endpointType === 'remote' && !state.azureEndpoint && !state.kubernetesEndpoint && !state.edgeEndpoint && endpoint.Type !== 6">
|
||||
<div class="col-sm-12 form-section-title"> Security </div>
|
||||
|
|
|
@ -20,7 +20,7 @@ function EndpointController(
|
|||
clipboard,
|
||||
EndpointService,
|
||||
GroupService,
|
||||
TagService,
|
||||
|
||||
Notifications,
|
||||
Authentication,
|
||||
SettingsService,
|
||||
|
@ -28,6 +28,7 @@ function EndpointController(
|
|||
) {
|
||||
$scope.onChangeCheckInInterval = onChangeCheckInInterval;
|
||||
$scope.setFieldValue = setFieldValue;
|
||||
$scope.onChangeTags = onChangeTags;
|
||||
|
||||
$scope.state = {
|
||||
uploadInProgress: false,
|
||||
|
@ -51,26 +52,12 @@ function EndpointController(
|
|||
$('#copyNotificationEdgeKey').show().fadeOut(2500);
|
||||
};
|
||||
|
||||
$scope.onCreateTag = function onCreateTag(tagName) {
|
||||
return $async(onCreateTagAsync, tagName);
|
||||
};
|
||||
|
||||
$scope.onToggleAllowSelfSignedCerts = function onToggleAllowSelfSignedCerts(checked) {
|
||||
return $scope.$evalAsync(() => {
|
||||
$scope.state.allowSelfSignedCerts = checked;
|
||||
});
|
||||
};
|
||||
|
||||
async function onCreateTagAsync(tagName) {
|
||||
try {
|
||||
const tag = await TagService.createTag(tagName);
|
||||
$scope.availableTags = $scope.availableTags.concat(tag);
|
||||
$scope.endpoint.TagIds = $scope.endpoint.TagIds.concat(tag.Id);
|
||||
} catch (err) {
|
||||
Notifications.error('Failue', err, 'Unable to create tag');
|
||||
}
|
||||
}
|
||||
|
||||
$scope.onDisassociateEndpoint = async function () {
|
||||
ModalService.confirmDisassociate((confirmed) => {
|
||||
if (confirmed) {
|
||||
|
@ -98,6 +85,10 @@ function EndpointController(
|
|||
setFieldValue('EdgeCheckinInterval', value);
|
||||
}
|
||||
|
||||
function onChangeTags(value) {
|
||||
setFieldValue('TagIds', value);
|
||||
}
|
||||
|
||||
function setFieldValue(name, value) {
|
||||
return $scope.$evalAsync(() => {
|
||||
$scope.endpoint = {
|
||||
|
@ -229,12 +220,7 @@ function EndpointController(
|
|||
async function initView() {
|
||||
return $async(async () => {
|
||||
try {
|
||||
const [endpoint, groups, tags, settings] = await Promise.all([
|
||||
EndpointService.endpoint($transition$.params().id),
|
||||
GroupService.groups(),
|
||||
TagService.tags(),
|
||||
SettingsService.settings(),
|
||||
]);
|
||||
const [endpoint, groups, settings] = await Promise.all([EndpointService.endpoint($transition$.params().id), GroupService.groups(), SettingsService.settings()]);
|
||||
|
||||
if (endpoint.URL.indexOf('unix://') === 0 || endpoint.URL.indexOf('npipe://') === 0) {
|
||||
$scope.endpointType = 'local';
|
||||
|
@ -254,7 +240,6 @@ function EndpointController(
|
|||
$scope.endpoint = endpoint;
|
||||
$scope.initialTagIds = endpoint.TagIds.slice();
|
||||
$scope.groups = groups;
|
||||
$scope.availableTags = tags;
|
||||
|
||||
configureState();
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { EndpointGroupDefaultModel } from '../../../models/group';
|
||||
|
||||
angular.module('portainer.app').controller('CreateGroupController', function CreateGroupController($async, $scope, $state, GroupService, TagService, Notifications) {
|
||||
angular.module('portainer.app').controller('CreateGroupController', function CreateGroupController($async, $scope, $state, GroupService, Notifications) {
|
||||
$scope.state = {
|
||||
actionInProgress: false,
|
||||
};
|
||||
|
@ -28,31 +28,10 @@ angular.module('portainer.app').controller('CreateGroupController', function Cre
|
|||
});
|
||||
};
|
||||
|
||||
$scope.onCreateTag = function onCreateTag(tagName) {
|
||||
return $async(onCreateTagAsync, tagName);
|
||||
};
|
||||
|
||||
async function onCreateTagAsync(tagName) {
|
||||
try {
|
||||
const tag = await TagService.createTag(tagName);
|
||||
$scope.availableTags = $scope.availableTags.concat(tag);
|
||||
$scope.model.TagIds = $scope.model.TagIds.concat(tag.Id);
|
||||
} catch (err) {
|
||||
Notifications.error('Failue', err, 'Unable to create tag');
|
||||
}
|
||||
}
|
||||
|
||||
function initView() {
|
||||
TagService.tags()
|
||||
.then((tags) => {
|
||||
$scope.availableTags = tags;
|
||||
$scope.associatedEndpoints = [];
|
||||
$scope.model = new EndpointGroupDefaultModel();
|
||||
$scope.loaded = true;
|
||||
})
|
||||
.catch((err) => {
|
||||
Notifications.error('Failure', err, 'Unable to retrieve tags');
|
||||
});
|
||||
$scope.associatedEndpoints = [];
|
||||
$scope.model = new EndpointGroupDefaultModel();
|
||||
$scope.loaded = true;
|
||||
}
|
||||
|
||||
initView();
|
||||
|
|
|
@ -12,14 +12,12 @@
|
|||
page-type="create"
|
||||
model="model"
|
||||
available-endpoints="availableEndpoints"
|
||||
available-tags="availableTags"
|
||||
associated-endpoints="associatedEndpoints"
|
||||
add-label-action="addLabel"
|
||||
remove-label-action="removeLabel"
|
||||
form-action="create"
|
||||
form-action-label="Create the group"
|
||||
action-in-progress="state.actionInProgress"
|
||||
on-create-tag="(onCreateTag)"
|
||||
></group-form>
|
||||
</rd-widget-body>
|
||||
</rd-widget>
|
||||
|
|
|
@ -12,14 +12,12 @@
|
|||
page-type="edit"
|
||||
model="group"
|
||||
available-endpoints="availableEndpoints"
|
||||
available-tags="availableTags"
|
||||
associated-endpoints="associatedEndpoints"
|
||||
add-label-action="addLabel"
|
||||
remove-label-action="removeLabel"
|
||||
form-action="update"
|
||||
form-action-label="Update the group"
|
||||
action-in-progress="state.actionInProgress"
|
||||
on-create-tag="(onCreateTag)"
|
||||
></group-form>
|
||||
</rd-widget-body>
|
||||
</rd-widget>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
angular.module('portainer.app').controller('GroupController', function GroupController($q, $async, $scope, $state, $transition$, GroupService, TagService, Notifications) {
|
||||
angular.module('portainer.app').controller('GroupController', function GroupController($q, $scope, $state, $transition$, GroupService, Notifications) {
|
||||
$scope.state = {
|
||||
actionInProgress: false,
|
||||
};
|
||||
|
@ -20,30 +20,14 @@ angular.module('portainer.app').controller('GroupController', function GroupCont
|
|||
});
|
||||
};
|
||||
|
||||
$scope.onCreateTag = function onCreateTag(tagName) {
|
||||
return $async(onCreateTagAsync, tagName);
|
||||
};
|
||||
|
||||
async function onCreateTagAsync(tagName) {
|
||||
try {
|
||||
const tag = await TagService.createTag(tagName);
|
||||
$scope.availableTags = $scope.availableTags.concat(tag);
|
||||
$scope.group.TagIds = $scope.group.TagIds.concat(tag.Id);
|
||||
} catch (err) {
|
||||
Notifications.error('Failue', err, 'Unable to create tag');
|
||||
}
|
||||
}
|
||||
|
||||
function initView() {
|
||||
var groupId = $transition$.params().id;
|
||||
|
||||
$q.all({
|
||||
group: GroupService.group(groupId),
|
||||
tags: TagService.tags(),
|
||||
})
|
||||
.then(function success(data) {
|
||||
$scope.group = data.group;
|
||||
$scope.availableTags = data.tags;
|
||||
$scope.loaded = true;
|
||||
})
|
||||
.catch(function error(err) {
|
||||
|
|
|
@ -62,18 +62,19 @@ export function TagSelector({ value, allowCreate = false, onChange }: Props) {
|
|||
{value.length > 0 && (
|
||||
<FormControl label="Selected tags">
|
||||
{selectedTags.map((tag) => (
|
||||
<span className="tag space-right interactive" key={tag.value}>
|
||||
<button
|
||||
type="button"
|
||||
title="Remove tag"
|
||||
className={clsx(styles.removeTagBtn, 'space-left', 'tag')}
|
||||
onClick={() => handleRemove(tag.value)}
|
||||
key={tag.value}
|
||||
>
|
||||
{tag.label}
|
||||
|
||||
<button
|
||||
type="button"
|
||||
title="Remove tag"
|
||||
className={clsx(styles.removeTagBtn, 'space-left')}
|
||||
onClick={() => handleRemove(tag.value)}
|
||||
>
|
||||
<i className="fa fa-trash-alt white-icon" aria-hidden="true" />
|
||||
</button>
|
||||
</span>
|
||||
<i
|
||||
className="fa fa-trash-alt white-icon space-left"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</button>
|
||||
))}
|
||||
</FormControl>
|
||||
)}
|
||||
|
|
|
@ -12,6 +12,11 @@ import { createMockTeams, createMockUsers } from '../react-tools/test-mocks';
|
|||
|
||||
import { azureHandlers } from './setup-handlers/azure';
|
||||
|
||||
const tags: Tag[] = [
|
||||
{ ID: 1, Name: 'tag1' },
|
||||
{ ID: 2, Name: 'tag2' },
|
||||
];
|
||||
|
||||
const licenseInfo: LicenseInfo = {
|
||||
nodes: 1000,
|
||||
type: LicenseType.Subscription,
|
||||
|
@ -48,11 +53,11 @@ export const handlers = [
|
|||
};
|
||||
return res(ctx.json(group));
|
||||
}),
|
||||
rest.get('/api/tags', (req, res, ctx) => {
|
||||
const tags: Tag[] = [
|
||||
{ ID: 1, Name: 'tag1' },
|
||||
{ ID: 2, Name: 'tag2' },
|
||||
];
|
||||
return res(ctx.json(tags));
|
||||
rest.get('/api/tags', (req, res, ctx) => res(ctx.json(tags))),
|
||||
rest.post<{ name: string }>('/api/tags', (req, res, ctx) => {
|
||||
const tagName = req.body.name;
|
||||
const tag = { ID: tags.length + 1, Name: tagName };
|
||||
tags.push(tag);
|
||||
return res(ctx.json(tag));
|
||||
}),
|
||||
];
|
||||
|
|
Loading…
Reference in New Issue