mirror of
https://github.com/portainer/portainer.git
synced 2025-08-05 22:05:23 +02:00
refactor(edge/groups): migrate view to react [EE-2219] (#11758)
Some checks failed
ci / build_images (map[arch:amd64 platform:linux version:]) (push) Has been cancelled
ci / build_images (map[arch:amd64 platform:windows version:1809]) (push) Has been cancelled
ci / build_images (map[arch:amd64 platform:windows version:ltsc2022]) (push) Has been cancelled
ci / build_images (map[arch:arm platform:linux version:]) (push) Has been cancelled
ci / build_images (map[arch:arm64 platform:linux version:]) (push) Has been cancelled
ci / build_images (map[arch:ppc64le platform:linux version:]) (push) Has been cancelled
ci / build_images (map[arch:s390x platform:linux version:]) (push) Has been cancelled
/ triage (push) Has been cancelled
Lint / Run linters (push) Has been cancelled
Test / test-client (push) Has been cancelled
Test / test-server (map[arch:amd64 platform:linux]) (push) Has been cancelled
Test / test-server (map[arch:amd64 platform:windows version:1809]) (push) Has been cancelled
Test / test-server (map[arch:amd64 platform:windows version:ltsc2022]) (push) Has been cancelled
Test / test-server (map[arch:arm64 platform:linux]) (push) Has been cancelled
ci / build_manifests (push) Has been cancelled
Some checks failed
ci / build_images (map[arch:amd64 platform:linux version:]) (push) Has been cancelled
ci / build_images (map[arch:amd64 platform:windows version:1809]) (push) Has been cancelled
ci / build_images (map[arch:amd64 platform:windows version:ltsc2022]) (push) Has been cancelled
ci / build_images (map[arch:arm platform:linux version:]) (push) Has been cancelled
ci / build_images (map[arch:arm64 platform:linux version:]) (push) Has been cancelled
ci / build_images (map[arch:ppc64le platform:linux version:]) (push) Has been cancelled
ci / build_images (map[arch:s390x platform:linux version:]) (push) Has been cancelled
/ triage (push) Has been cancelled
Lint / Run linters (push) Has been cancelled
Test / test-client (push) Has been cancelled
Test / test-server (map[arch:amd64 platform:linux]) (push) Has been cancelled
Test / test-server (map[arch:amd64 platform:windows version:1809]) (push) Has been cancelled
Test / test-server (map[arch:amd64 platform:windows version:ltsc2022]) (push) Has been cancelled
Test / test-server (map[arch:arm64 platform:linux]) (push) Has been cancelled
ci / build_manifests (push) Has been cancelled
This commit is contained in:
parent
b7cde35c3d
commit
9c70a43ac3
39 changed files with 579 additions and 386 deletions
|
@ -35,7 +35,7 @@ angular
|
|||
url: '/new',
|
||||
views: {
|
||||
'content@': {
|
||||
component: 'createEdgeGroupView',
|
||||
component: 'edgeGroupsCreateView',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -45,7 +45,7 @@ angular
|
|||
url: '/:groupId',
|
||||
views: {
|
||||
'content@': {
|
||||
component: 'editEdgeGroupView',
|
||||
component: 'edgeGroupsItemView',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,79 +0,0 @@
|
|||
<form class="form-horizontal" name="EdgeGroupForm" ng-submit="$ctrl.handleSubmit()">
|
||||
<div class="form-group">
|
||||
<label for="group_name" class="col-sm-3 col-lg-2 control-label required text-left"> Name </label>
|
||||
<div class="col-sm-9 col-lg-10">
|
||||
<input
|
||||
type="text"
|
||||
data-cy="edgeGroupCreate-groupNameInput"
|
||||
class="form-control"
|
||||
id="group_name"
|
||||
name="group_name"
|
||||
ng-model="$ctrl.model.Name"
|
||||
required
|
||||
auto-focus
|
||||
placeholder="e.g. mygroup"
|
||||
/>
|
||||
<div class="help-block" ng-show="EdgeGroupForm.group_name.$invalid">
|
||||
<div class="small text-warning">
|
||||
<div ng-messages="EdgeGroupForm.group_name.$error">
|
||||
<p ng-message="required" class="vertical-center"> <pr-icon icon="'alert-triangle'" class-name="'icon-sm icon-warning'"></pr-icon> This field is required. </p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-12 form-section-title"> Group type </div>
|
||||
|
||||
<box-selector slim="true" value="$ctrl.model.Dynamic" on-change="($ctrl.onChangeDynamic)" options="$ctrl.groupTypeOptions" radio-name="'groupTypeDynamic'"></box-selector>
|
||||
|
||||
<!-- StaticGroup -->
|
||||
<div ng-if="!$ctrl.model.Dynamic">
|
||||
<div ng-if="!$ctrl.noEndpoints">
|
||||
<!-- environments -->
|
||||
<div class="col-sm-12 form-section-title"> Associated environments </div>
|
||||
<div class="form-group">
|
||||
<associated-edge-environments-selector value="$ctrl.model.Endpoints" on-change="($ctrl.onChangeEnvironments)"></associated-edge-environments-selector>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" ng-if="$ctrl.noEndpoints">
|
||||
<div class="col-sm-12 small text-muted">
|
||||
No Edge environments are available. Head over to the <a ui-sref="portainer.endpoints">Environments view</a> to add environments.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- !StaticGroup -->
|
||||
|
||||
<!-- DynamicGroup -->
|
||||
<div ng-if="$ctrl.model.Dynamic">
|
||||
<div class="col-sm-12 form-section-title"> Tags </div>
|
||||
|
||||
<box-selector slim="true" value="$ctrl.model.PartialMatch" on-change="($ctrl.onChangePartialMatch)" options="$ctrl.tagOptions" radio-name="'partialMatch'"></box-selector>
|
||||
|
||||
<tag-selector ng-if="$ctrl.model.TagIds" value="$ctrl.model.TagIds" on-change="($ctrl.onChangeTags)"> </tag-selector>
|
||||
|
||||
<edge-group-association-table
|
||||
title="'Associated environments by tags'"
|
||||
empty-content-message="'No associated available'"
|
||||
query="$ctrl.dynamicQuery"
|
||||
></edge-group-association-table>
|
||||
</div>
|
||||
<!-- !DynamicGroup -->
|
||||
|
||||
<!-- actions -->
|
||||
<div class="col-sm-12 form-section-title"> Actions </div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-primary btn-sm"
|
||||
ng-disabled="$ctrl.actionInProgress || !EdgeGroupForm.$valid"
|
||||
button-spinner="$ctrl.actionInProgress"
|
||||
data-cy="edgeGroupCreate-addGroupButton"
|
||||
>
|
||||
<span ng-hide="$ctrl.actionInProgress">{{ $ctrl.formActionLabel }}</span>
|
||||
<span ng-show="$ctrl.actionInProgress">In progress...</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
|
@ -1,86 +0,0 @@
|
|||
import { confirmDestructive } from '@@/modals/confirm';
|
||||
import { EdgeTypes } from '@/react/portainer/environments/types';
|
||||
import { buildConfirmButton } from '@@/modals/utils';
|
||||
import { tagOptions } from '@/react/edge/edge-groups/CreateView/tag-options';
|
||||
import { groupTypeOptions } from '@/react/edge/edge-groups/CreateView/group-type-options';
|
||||
|
||||
export class EdgeGroupFormController {
|
||||
/* @ngInject */
|
||||
constructor($async, $scope) {
|
||||
this.$async = $async;
|
||||
this.$scope = $scope;
|
||||
|
||||
this.groupTypeOptions = groupTypeOptions;
|
||||
this.tagOptions = tagOptions;
|
||||
|
||||
this.dynamicQuery = {
|
||||
types: EdgeTypes,
|
||||
tagIds: [],
|
||||
tagsPartialMatch: false,
|
||||
};
|
||||
|
||||
this.onChangeEnvironments = this.onChangeEnvironments.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);
|
||||
this.handleSubmit = this.handleSubmit.bind(this);
|
||||
|
||||
$scope.$watch(
|
||||
() => this.model,
|
||||
() => {
|
||||
if (this.model.Dynamic) {
|
||||
this.dynamicQuery = {
|
||||
types: EdgeTypes,
|
||||
tagIds: this.model.TagIds,
|
||||
tagsPartialMatch: this.model.PartialMatch,
|
||||
};
|
||||
}
|
||||
},
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
onChangeModel(model) {
|
||||
return this.$scope.$evalAsync(() => {
|
||||
this.model = {
|
||||
...this.model,
|
||||
...model,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
onChangePartialMatch(value) {
|
||||
return this.onChangeModel({ PartialMatch: value });
|
||||
}
|
||||
|
||||
onChangeDynamic(value) {
|
||||
this.onChangeModel({ Dynamic: value });
|
||||
}
|
||||
|
||||
onChangeTags(value) {
|
||||
this.onChangeModel({ TagIds: value });
|
||||
}
|
||||
|
||||
onChangeEnvironments(value, meta) {
|
||||
return this.$async(async () => {
|
||||
if (meta.type === 'remove' && this.pageType === 'edit') {
|
||||
const confirmed = await confirmDestructive({
|
||||
title: 'Confirm action',
|
||||
message: 'Removing the environment from this group will remove its corresponding edge stacks',
|
||||
confirmButton: buildConfirmButton('Confirm'),
|
||||
});
|
||||
|
||||
if (!confirmed) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.onChangeModel({ Endpoints: value });
|
||||
});
|
||||
}
|
||||
|
||||
handleSubmit() {
|
||||
this.formAction(this.model);
|
||||
}
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
import angular from 'angular';
|
||||
|
||||
import { EdgeGroupFormController } from './groupFormController';
|
||||
|
||||
angular.module('portainer.edge').component('edgeGroupForm', {
|
||||
templateUrl: './groupForm.html',
|
||||
controller: EdgeGroupFormController,
|
||||
bindings: {
|
||||
model: '<',
|
||||
formActionLabel: '@',
|
||||
formAction: '<',
|
||||
actionInProgress: '<',
|
||||
loaded: '<',
|
||||
pageType: '@',
|
||||
},
|
||||
});
|
|
@ -1,14 +1,13 @@
|
|||
import angular from 'angular';
|
||||
|
||||
import { EdgeGroupsSelector } from '@/react/edge/edge-stacks/components/EdgeGroupsSelector';
|
||||
import { r2a } from '@/react-tools/react2angular';
|
||||
import { withReactQuery } from '@/react-tools/withReactQuery';
|
||||
import { withUIRouter } from '@/react-tools/withUIRouter';
|
||||
import { AssociatedEdgeEnvironmentsSelector } from '@/react/edge/components/AssociatedEdgeEnvironmentsSelector';
|
||||
import { EdgeAsyncIntervalsForm } from '@/react/edge/components/EdgeAsyncIntervalsForm';
|
||||
import { EdgeCheckinIntervalField } from '@/react/edge/components/EdgeCheckInIntervalField';
|
||||
import { EdgeScriptForm } from '@/react/edge/components/EdgeScriptForm';
|
||||
import { EdgeAsyncIntervalsForm } from '@/react/edge/components/EdgeAsyncIntervalsForm';
|
||||
import { withUIRouter } from '@/react-tools/withUIRouter';
|
||||
import { EdgeGroupAssociationTable } from '@/react/edge/components/EdgeGroupAssociationTable';
|
||||
import { AssociatedEdgeEnvironmentsSelector } from '@/react/edge/components/AssociatedEdgeEnvironmentsSelector';
|
||||
import { EdgeGroupsSelector } from '@/react/edge/edge-stacks/components/EdgeGroupsSelector';
|
||||
|
||||
import { edgeJobsModule } from './edge-jobs';
|
||||
|
||||
|
@ -57,20 +56,12 @@ const ngModule = angular
|
|||
'fieldSettings',
|
||||
])
|
||||
)
|
||||
.component(
|
||||
'edgeGroupAssociationTable',
|
||||
r2a(withReactQuery(EdgeGroupAssociationTable), [
|
||||
'onClickRow',
|
||||
'query',
|
||||
'title',
|
||||
'data-cy',
|
||||
])
|
||||
)
|
||||
.component(
|
||||
'associatedEdgeEnvironmentsSelector',
|
||||
r2a(withReactQuery(AssociatedEdgeEnvironmentsSelector), [
|
||||
'onChange',
|
||||
'value',
|
||||
'error',
|
||||
])
|
||||
);
|
||||
|
||||
|
|
20
app/edge/react/views/groups.ts
Normal file
20
app/edge/react/views/groups.ts
Normal file
|
@ -0,0 +1,20 @@
|
|||
import angular from 'angular';
|
||||
|
||||
import { r2a } from '@/react-tools/react2angular';
|
||||
import { withCurrentUser } from '@/react-tools/withCurrentUser';
|
||||
import { withUIRouter } from '@/react-tools/withUIRouter';
|
||||
import { ListView } from '@/react/edge/edge-groups/ListView';
|
||||
import { CreateView } from '@/react/edge/edge-groups/CreateView/CreateView';
|
||||
import { ItemView } from '@/react/edge/edge-groups/ItemView/ItemView';
|
||||
|
||||
export const groupsModule = angular
|
||||
.module('portainer.edge.react.views.groups', [])
|
||||
.component('edgeGroupsView', r2a(withUIRouter(withCurrentUser(ListView)), []))
|
||||
.component(
|
||||
'edgeGroupsCreateView',
|
||||
r2a(withUIRouter(withCurrentUser(CreateView)), [])
|
||||
)
|
||||
.component(
|
||||
'edgeGroupsItemView',
|
||||
r2a(withUIRouter(withCurrentUser(ItemView)), [])
|
||||
).name;
|
|
@ -5,23 +5,20 @@ import { withCurrentUser } from '@/react-tools/withCurrentUser';
|
|||
import { withReactQuery } from '@/react-tools/withReactQuery';
|
||||
import { withUIRouter } from '@/react-tools/withUIRouter';
|
||||
import { WaitingRoomView } from '@/react/edge/edge-devices/WaitingRoomView';
|
||||
import { ListView as EdgeGroupsListView } from '@/react/edge/edge-groups/ListView';
|
||||
|
||||
import { templatesModule } from './templates';
|
||||
import { jobsModule } from './jobs';
|
||||
import { stacksModule } from './edge-stacks';
|
||||
import { groupsModule } from './groups';
|
||||
|
||||
export const viewsModule = angular
|
||||
.module('portainer.edge.react.views', [
|
||||
templatesModule,
|
||||
jobsModule,
|
||||
stacksModule,
|
||||
groupsModule,
|
||||
])
|
||||
.component(
|
||||
'waitingRoomView',
|
||||
r2a(withUIRouter(withReactQuery(withCurrentUser(WaitingRoomView))), [])
|
||||
)
|
||||
.component(
|
||||
'edgeGroupsView',
|
||||
r2a(withUIRouter(withCurrentUser(EdgeGroupsListView)), [])
|
||||
).name;
|
||||
|
|
|
@ -5,11 +5,7 @@ angular.module('portainer.edge').factory('EdgeGroups', function EdgeGroupsFactor
|
|||
API_ENDPOINT_EDGE_GROUPS + '/:id/:action',
|
||||
{},
|
||||
{
|
||||
create: { method: 'POST', ignoreLoadingBar: true },
|
||||
query: { method: 'GET', isArray: true },
|
||||
get: { method: 'GET', params: { id: '@id' } },
|
||||
update: { method: 'PUT', params: { id: '@Id' } },
|
||||
remove: { method: 'DELETE', params: { id: '@id' } },
|
||||
}
|
||||
);
|
||||
});
|
||||
|
|
|
@ -3,25 +3,9 @@ import angular from 'angular';
|
|||
angular.module('portainer.edge').factory('EdgeGroupService', function EdgeGroupServiceFactory(EdgeGroups) {
|
||||
var service = {};
|
||||
|
||||
service.group = function group(groupId) {
|
||||
return EdgeGroups.get({ id: groupId }).$promise;
|
||||
};
|
||||
|
||||
service.groups = function groups() {
|
||||
return EdgeGroups.query({}).$promise;
|
||||
};
|
||||
|
||||
service.remove = function remove(groupId) {
|
||||
return EdgeGroups.remove({ id: groupId }).$promise;
|
||||
};
|
||||
|
||||
service.create = function create(group) {
|
||||
return EdgeGroups.create(group).$promise;
|
||||
};
|
||||
|
||||
service.update = function update(group) {
|
||||
return EdgeGroups.update(group).$promise;
|
||||
};
|
||||
|
||||
return service;
|
||||
});
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
<page-header title="'Create edge group'" breadcrumbs="[{label:'Edge groups', link:'edge.groups'}, 'Add edge group']"> </page-header>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<rd-widget>
|
||||
<rd-widget-body>
|
||||
<edge-group-form
|
||||
loaded="$ctrl.state.loaded"
|
||||
page-type="create"
|
||||
form-action-label="Add edge group"
|
||||
form-action="$ctrl.createGroup"
|
||||
groups="$ctrl.endpointGroups"
|
||||
model="$ctrl.model"
|
||||
></edge-group-form>
|
||||
</rd-widget-body>
|
||||
</rd-widget>
|
||||
</div>
|
||||
</div>
|
|
@ -1,47 +0,0 @@
|
|||
export class CreateEdgeGroupController {
|
||||
/* @ngInject */
|
||||
constructor(EdgeGroupService, GroupService, Notifications, $state, $async) {
|
||||
this.EdgeGroupService = EdgeGroupService;
|
||||
this.GroupService = GroupService;
|
||||
this.Notifications = Notifications;
|
||||
this.$state = $state;
|
||||
this.$async = $async;
|
||||
|
||||
this.state = {
|
||||
actionInProgress: false,
|
||||
loaded: false,
|
||||
};
|
||||
|
||||
this.model = {
|
||||
Name: '',
|
||||
Endpoints: [],
|
||||
Dynamic: false,
|
||||
TagIds: [],
|
||||
PartialMatch: false,
|
||||
};
|
||||
|
||||
this.createGroup = this.createGroup.bind(this);
|
||||
}
|
||||
|
||||
async $onInit() {
|
||||
const endpointGroups = await this.GroupService.groups();
|
||||
|
||||
this.endpointGroups = endpointGroups;
|
||||
this.state.loaded = true;
|
||||
}
|
||||
|
||||
async createGroup(model) {
|
||||
return this.$async(async () => {
|
||||
this.state.actionInProgress = true;
|
||||
try {
|
||||
await this.EdgeGroupService.create(model);
|
||||
this.Notifications.success('Success', 'Edge group successfully created');
|
||||
this.$state.go('edge.groups');
|
||||
} catch (err) {
|
||||
this.Notifications.error('Failure', err, 'Unable to create edge group');
|
||||
} finally {
|
||||
this.state.actionInProgress = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
import angular from 'angular';
|
||||
|
||||
import { CreateEdgeGroupController } from './createEdgeGroupViewController';
|
||||
|
||||
angular.module('portainer.edge').component('createEdgeGroupView', {
|
||||
templateUrl: './createEdgeGroupView.html',
|
||||
controller: CreateEdgeGroupController,
|
||||
});
|
|
@ -1,19 +0,0 @@
|
|||
<page-header title="'Edit edge group'" breadcrumbs="[{label:'Edge Groups', link:'edge.groups'}, $ctrl.model.Name]"> </page-header>
|
||||
|
||||
<div class="row" ng-if="$ctrl.model">
|
||||
<div class="col-sm-12">
|
||||
<rd-widget>
|
||||
<rd-widget-body>
|
||||
<edge-group-form
|
||||
loaded="$ctrl.state.loaded"
|
||||
page-type="edit"
|
||||
form-action-label="Save edge group"
|
||||
form-action="$ctrl.updateGroup"
|
||||
endpoints="$ctrl.endpoints"
|
||||
groups="$ctrl.endpointGroups"
|
||||
model="$ctrl.model"
|
||||
></edge-group-form>
|
||||
</rd-widget-body>
|
||||
</rd-widget>
|
||||
</div>
|
||||
</div>
|
|
@ -1,44 +0,0 @@
|
|||
export class EditEdgeGroupController {
|
||||
/* @ngInject */
|
||||
constructor(EdgeGroupService, GroupService, Notifications, $state, $async) {
|
||||
this.EdgeGroupService = EdgeGroupService;
|
||||
this.GroupService = GroupService;
|
||||
this.Notifications = Notifications;
|
||||
this.$state = $state;
|
||||
this.$async = $async;
|
||||
|
||||
this.state = {
|
||||
actionInProgress: false,
|
||||
loaded: false,
|
||||
};
|
||||
|
||||
this.updateGroup = this.updateGroup.bind(this);
|
||||
}
|
||||
|
||||
async $onInit() {
|
||||
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.endpointGroups = endpointGroups;
|
||||
this.model = group;
|
||||
this.state.loaded = true;
|
||||
}
|
||||
|
||||
updateGroup(group) {
|
||||
return this.$async(async () => {
|
||||
this.state.actionInProgress = true;
|
||||
try {
|
||||
await this.EdgeGroupService.update(group);
|
||||
this.Notifications.success('Success', 'Edge group successfully updated');
|
||||
this.$state.go('edge.groups');
|
||||
} catch (err) {
|
||||
this.Notifications.error('Failure', err, 'Unable to update edge group');
|
||||
} finally {
|
||||
this.state.actionInProgress = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
import angular from 'angular';
|
||||
|
||||
import { EditEdgeGroupController } from './editEdgeGroupViewController';
|
||||
|
||||
angular.module('portainer.edge').component('editEdgeGroupView', {
|
||||
templateUrl: './editEdgeGroupView.html',
|
||||
controller: EditEdgeGroupController,
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue