1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-08-08 15:25:22 +02:00

refactor(app): convert tag-selector to react [EE-2983] (#6783)

This commit is contained in:
Chaim Lev-Ari 2022-05-29 09:14:14 +03:00 committed by GitHub
parent 75d854e6ad
commit d52417c14f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
29 changed files with 103 additions and 288 deletions

View file

@ -9,13 +9,11 @@ angular.module('portainer.app').component('groupForm', {
pageType: '@',
model: '=',
availableEndpoints: '=',
availableTags: '<',
associatedEndpoints: '=',
addLabelAction: '<',
removeLabelAction: '<',
formAction: '<',
formActionLabel: '@',
actionInProgress: '<',
onCreateTag: '<',
},
});

View file

@ -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>

View file

@ -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() {

View file

@ -1,10 +0,0 @@
angular.module('portainer.app').component('tagSelector', {
templateUrl: './tagSelector.html',
controller: 'TagSelectorController',
bindings: {
tags: '<',
model: '=',
onCreate: '<',
allowCreate: '<',
},
});

View file

@ -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>

View file

@ -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);

View file

@ -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;

View file

@ -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');

View file

@ -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">

View file

@ -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');

View file

@ -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;

View file

@ -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">

View file

@ -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>

View file

@ -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();

View file

@ -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();

View file

@ -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>

View file

@ -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>

View file

@ -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) {