mirror of
https://github.com/portainer/portainer.git
synced 2025-08-05 05:45:22 +02:00
refactor(edge/stacks): migrate edit view to react [EE-2222] (#11648)
Some checks are pending
ci / build_images (map[arch:amd64 platform:linux version:]) (push) Waiting to run
ci / build_images (map[arch:amd64 platform:windows version:1809]) (push) Waiting to run
ci / build_images (map[arch:amd64 platform:windows version:ltsc2022]) (push) Waiting to run
ci / build_images (map[arch:arm platform:linux version:]) (push) Waiting to run
ci / build_images (map[arch:arm64 platform:linux version:]) (push) Waiting to run
ci / build_images (map[arch:ppc64le platform:linux version:]) (push) Waiting to run
ci / build_images (map[arch:s390x platform:linux version:]) (push) Waiting to run
ci / build_manifests (push) Blocked by required conditions
/ triage (push) Waiting to run
Lint / Run linters (push) Waiting to run
Test / test-client (push) Waiting to run
Test / test-server (map[arch:amd64 platform:linux]) (push) Waiting to run
Test / test-server (map[arch:amd64 platform:windows version:1809]) (push) Waiting to run
Test / test-server (map[arch:amd64 platform:windows version:ltsc2022]) (push) Waiting to run
Test / test-server (map[arch:arm64 platform:linux]) (push) Waiting to run
Some checks are pending
ci / build_images (map[arch:amd64 platform:linux version:]) (push) Waiting to run
ci / build_images (map[arch:amd64 platform:windows version:1809]) (push) Waiting to run
ci / build_images (map[arch:amd64 platform:windows version:ltsc2022]) (push) Waiting to run
ci / build_images (map[arch:arm platform:linux version:]) (push) Waiting to run
ci / build_images (map[arch:arm64 platform:linux version:]) (push) Waiting to run
ci / build_images (map[arch:ppc64le platform:linux version:]) (push) Waiting to run
ci / build_images (map[arch:s390x platform:linux version:]) (push) Waiting to run
ci / build_manifests (push) Blocked by required conditions
/ triage (push) Waiting to run
Lint / Run linters (push) Waiting to run
Test / test-client (push) Waiting to run
Test / test-server (map[arch:amd64 platform:linux]) (push) Waiting to run
Test / test-server (map[arch:amd64 platform:windows version:1809]) (push) Waiting to run
Test / test-server (map[arch:amd64 platform:windows version:ltsc2022]) (push) Waiting to run
Test / test-server (map[arch:arm64 platform:linux]) (push) Waiting to run
This commit is contained in:
parent
27e309754e
commit
cd5f342da0
31 changed files with 847 additions and 499 deletions
|
@ -1,11 +1,10 @@
|
|||
import angular from 'angular';
|
||||
|
||||
import { AccessHeaders } from '@/portainer/authorization-guard';
|
||||
import edgeStackModule from './views/edge-stacks';
|
||||
import { reactModule } from './react';
|
||||
|
||||
angular
|
||||
.module('portainer.edge', [edgeStackModule, reactModule])
|
||||
.module('portainer.edge', [reactModule])
|
||||
|
||||
.config(function config($stateRegistryProvider) {
|
||||
const edge = {
|
||||
|
@ -82,7 +81,7 @@ angular
|
|||
url: '/:stackId?tab&status',
|
||||
views: {
|
||||
'content@': {
|
||||
component: 'editEdgeStackView',
|
||||
component: 'edgeStacksItemView',
|
||||
},
|
||||
},
|
||||
params: {
|
||||
|
|
|
@ -6,22 +6,15 @@ import { withReactQuery } from '@/react-tools/withReactQuery';
|
|||
import { EdgeCheckinIntervalField } from '@/react/edge/components/EdgeCheckInIntervalField';
|
||||
import { EdgeScriptForm } from '@/react/edge/components/EdgeScriptForm';
|
||||
import { EdgeAsyncIntervalsForm } from '@/react/edge/components/EdgeAsyncIntervalsForm';
|
||||
import { EdgeStackDeploymentTypeSelector } from '@/react/edge/edge-stacks/components/EdgeStackDeploymentTypeSelector';
|
||||
import { EditEdgeStackForm } from '@/react/edge/edge-stacks/ItemView/EditEdgeStackForm/EditEdgeStackForm';
|
||||
import { withCurrentUser } from '@/react-tools/withCurrentUser';
|
||||
import { withUIRouter } from '@/react-tools/withUIRouter';
|
||||
import { EdgeGroupAssociationTable } from '@/react/edge/components/EdgeGroupAssociationTable';
|
||||
import { AssociatedEdgeEnvironmentsSelector } from '@/react/edge/components/AssociatedEdgeEnvironmentsSelector';
|
||||
import { EnvironmentsDatatable } from '@/react/edge/edge-stacks/ItemView/EnvironmentsDatatable';
|
||||
|
||||
import { edgeJobsModule } from './edge-jobs';
|
||||
|
||||
const ngModule = angular
|
||||
.module('portainer.edge.react.components', [edgeJobsModule])
|
||||
.component(
|
||||
'edgeStackEnvironmentsDatatable',
|
||||
r2a(withUIRouter(withReactQuery(EnvironmentsDatatable)), [])
|
||||
)
|
||||
|
||||
.component(
|
||||
'edgeGroupsSelector',
|
||||
r2a(withUIRouter(withReactQuery(EdgeGroupsSelector)), [
|
||||
|
@ -64,27 +57,6 @@ const ngModule = angular
|
|||
'fieldSettings',
|
||||
])
|
||||
)
|
||||
.component(
|
||||
'edgeStackDeploymentTypeSelector',
|
||||
r2a(withReactQuery(EdgeStackDeploymentTypeSelector), [
|
||||
'value',
|
||||
'onChange',
|
||||
'hasDockerEndpoint',
|
||||
'hasKubeEndpoint',
|
||||
'allowKubeToSelectCompose',
|
||||
])
|
||||
)
|
||||
.component(
|
||||
'editEdgeStackForm',
|
||||
r2a(withUIRouter(withReactQuery(withCurrentUser(EditEdgeStackForm))), [
|
||||
'edgeStack',
|
||||
'fileContent',
|
||||
'isSubmitting',
|
||||
'onEditorChange',
|
||||
'onSubmit',
|
||||
'allowKubeToSelectCompose',
|
||||
])
|
||||
)
|
||||
.component(
|
||||
'edgeGroupAssociationTable',
|
||||
r2a(withReactQuery(EdgeGroupAssociationTable), [
|
||||
|
|
|
@ -4,10 +4,20 @@ import { r2a } from '@/react-tools/react2angular';
|
|||
import { withCurrentUser } from '@/react-tools/withCurrentUser';
|
||||
import { withUIRouter } from '@/react-tools/withUIRouter';
|
||||
import { CreateView } from '@/react/edge/edge-stacks/CreateView/CreateView';
|
||||
import { ItemView } from '@/react/edge/edge-stacks/ItemView/ItemView';
|
||||
import { ListView } from '@/react/edge/edge-stacks/ListView';
|
||||
|
||||
export const stacksModule = angular
|
||||
.module('portainer.edge.react.views.stacks', [])
|
||||
.component(
|
||||
'edgeStacksCreateView',
|
||||
r2a(withCurrentUser(withUIRouter(CreateView)), [])
|
||||
)
|
||||
.component(
|
||||
'edgeStacksItemView',
|
||||
r2a(withCurrentUser(withUIRouter(ItemView)), [])
|
||||
)
|
||||
.component(
|
||||
'edgeStacksView',
|
||||
r2a(withUIRouter(withCurrentUser(ListView)), [])
|
||||
).name;
|
||||
|
|
|
@ -5,7 +5,6 @@ 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 EdgeStacksListView } from '@/react/edge/edge-stacks/ListView';
|
||||
import { ListView as EdgeGroupsListView } from '@/react/edge/edge-groups/ListView';
|
||||
|
||||
import { templatesModule } from './templates';
|
||||
|
@ -22,10 +21,6 @@ export const viewsModule = angular
|
|||
'waitingRoomView',
|
||||
r2a(withUIRouter(withReactQuery(withCurrentUser(WaitingRoomView))), [])
|
||||
)
|
||||
.component(
|
||||
'edgeStacksView',
|
||||
r2a(withUIRouter(withCurrentUser(EdgeStacksListView)), [])
|
||||
)
|
||||
.component(
|
||||
'edgeGroupsView',
|
||||
r2a(withUIRouter(withCurrentUser(EdgeGroupsListView)), [])
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
<page-header title="'Edit Edge stack'" breadcrumbs="[{label:'Edge Stacks', link:'edge.stacks'}, $ctrl.stack.Name]" reload="true"> </page-header>
|
||||
|
||||
<div class="row" ng-if="$ctrl.stack">
|
||||
<div class="col-sm-12">
|
||||
<rd-widget>
|
||||
<rd-widget-body classes="no-padding">
|
||||
<uib-tabset active="$ctrl.state.activeTab" justified="true" type="pills">
|
||||
<uib-tab index="0" classes="btn-sm">
|
||||
<uib-tab-heading>
|
||||
<span><pr-icon icon="'layers'"></pr-icon></span> Stack
|
||||
</uib-tab-heading>
|
||||
|
||||
<div style="padding: 20px">
|
||||
<edit-edge-stack-form
|
||||
ng-if="$ctrl.edgeGroups && $ctrl.stack && $ctrl.formValues.content !== null"
|
||||
edge-groups="$ctrl.edgeGroups"
|
||||
edge-stack="$ctrl.stack"
|
||||
is-submitting="$ctrl.state.actionInProgress"
|
||||
on-submit="($ctrl.deployStack)"
|
||||
on-editor-change="($ctrl.onEditorChange)"
|
||||
file-content="$ctrl.formValues.content"
|
||||
allow-kube-to-select-compose="$ctrl.allowKubeToSelectCompose"
|
||||
></edit-edge-stack-form>
|
||||
</div>
|
||||
</uib-tab>
|
||||
<uib-tab index="1" classes="btn-sm">
|
||||
<uib-tab-heading>
|
||||
<span><pr-icon icon="'hard-drive'"></pr-icon></span> Environments
|
||||
</uib-tab-heading>
|
||||
|
||||
<div style="margin-top: 25px">
|
||||
<edge-stack-environments-datatable></edge-stack-environments-datatable>
|
||||
</div>
|
||||
</uib-tab>
|
||||
</uib-tabset>
|
||||
</rd-widget-body>
|
||||
</rd-widget>
|
||||
</div>
|
||||
</div>
|
|
@ -1,117 +0,0 @@
|
|||
import { confirmWebEditorDiscard } from '@@/modals/confirm';
|
||||
import { EnvironmentType } from '@/react/portainer/environments/types';
|
||||
import { createWebhookId } from '@/portainer/helpers/webhookHelper';
|
||||
|
||||
export class EditEdgeStackViewController {
|
||||
/* @ngInject */
|
||||
constructor($async, $state, $window, EdgeGroupService, EdgeStackService, Notifications) {
|
||||
this.$async = $async;
|
||||
this.$state = $state;
|
||||
this.$window = $window;
|
||||
this.EdgeGroupService = EdgeGroupService;
|
||||
this.EdgeStackService = EdgeStackService;
|
||||
this.Notifications = Notifications;
|
||||
|
||||
this.stack = null;
|
||||
this.edgeGroups = null;
|
||||
|
||||
this.state = {
|
||||
actionInProgress: false,
|
||||
activeTab: 0,
|
||||
isStackDeployed: false,
|
||||
};
|
||||
|
||||
this.formValues = {
|
||||
content: null,
|
||||
};
|
||||
|
||||
this.deployStack = this.deployStack.bind(this);
|
||||
this.deployStackAsync = this.deployStackAsync.bind(this);
|
||||
this.onEditorChange = this.onEditorChange.bind(this);
|
||||
this.isEditorDirty = this.isEditorDirty.bind(this);
|
||||
}
|
||||
|
||||
async $onInit() {
|
||||
return this.$async(async () => {
|
||||
const { stackId, tab } = this.$state.params;
|
||||
this.state.activeTab = tab ? parseInt(tab, 10) : 0;
|
||||
try {
|
||||
const [edgeGroups, model, file] = await Promise.all([
|
||||
this.EdgeGroupService.groups(),
|
||||
this.EdgeStackService.stack(stackId),
|
||||
this.EdgeStackService.stackFile(stackId).catch(() => ''),
|
||||
]);
|
||||
|
||||
this.edgeGroups = edgeGroups;
|
||||
this.stack = model;
|
||||
this.originalFileContent = file;
|
||||
this.formValues = {
|
||||
content: file,
|
||||
};
|
||||
|
||||
const stackEdgeGroups = model.EdgeGroups.map((id) => this.edgeGroups.find((e) => e.Id === id));
|
||||
const endpointTypes = stackEdgeGroups.flatMap((group) => group.EndpointTypes);
|
||||
const initiallyContainsKubeEnv = endpointTypes.includes(EnvironmentType.EdgeAgentOnKubernetes);
|
||||
const isComposeStack = this.stack.DeploymentType === 0;
|
||||
|
||||
this.allowKubeToSelectCompose = initiallyContainsKubeEnv && isComposeStack;
|
||||
} catch (err) {
|
||||
this.Notifications.error('Failure', err, 'Unable to retrieve stack data');
|
||||
}
|
||||
|
||||
this.oldFileContent = this.formValues.StackFileContent;
|
||||
|
||||
this.$window.onbeforeunload = () => {
|
||||
if (this.isEditorDirty()) {
|
||||
return '';
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
$onDestroy() {
|
||||
this.$window.onbeforeunload = undefined;
|
||||
}
|
||||
|
||||
async uiCanExit() {
|
||||
if (this.isEditorDirty()) {
|
||||
return confirmWebEditorDiscard();
|
||||
}
|
||||
}
|
||||
|
||||
onEditorChange(content) {
|
||||
this.formValues.content = content;
|
||||
}
|
||||
|
||||
isEditorDirty() {
|
||||
return !this.state.isStackDeployed && this.formValues.content.replace(/(\r\n|\n|\r)/gm, '') !== this.originalFileContent.replace(/(\r\n|\n|\r)/gm, '');
|
||||
}
|
||||
|
||||
deployStack(values) {
|
||||
return this.deployStackAsync(values);
|
||||
}
|
||||
|
||||
async deployStackAsync(values) {
|
||||
this.state.actionInProgress = true;
|
||||
try {
|
||||
const updateVersion = !!(this.originalFileContent != values.content || values.useManifestNamespaces !== this.stack.UseManifestNamespaces);
|
||||
|
||||
await this.EdgeStackService.updateStack(this.stack.Id, {
|
||||
stackFileContent: values.content,
|
||||
edgeGroups: values.edgeGroups,
|
||||
deploymentType: values.deploymentType,
|
||||
updateVersion,
|
||||
retryDeploy: values.retryDeploy,
|
||||
webhook: values.webhookEnabled ? this.stack.Webhook || createWebhookId() : '',
|
||||
envVars: values.envVars,
|
||||
});
|
||||
this.Notifications.success('Success', 'Stack successfully deployed');
|
||||
this.state.isStackDeployed = true;
|
||||
this.$state.go('edge.stacks');
|
||||
} catch (err) {
|
||||
this.Notifications.error('Deployment error', err, 'Unable to deploy stack');
|
||||
} finally {
|
||||
this.state.actionInProgress = false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
import angular from 'angular';
|
||||
|
||||
import { EditEdgeStackViewController } from './editEdgeStackViewController';
|
||||
|
||||
angular.module('portainer.edge').component('editEdgeStackView', {
|
||||
templateUrl: './editEdgeStackView.html',
|
||||
controller: EditEdgeStackViewController,
|
||||
});
|
|
@ -1,3 +0,0 @@
|
|||
import angular from 'angular';
|
||||
|
||||
export default angular.module('portainer.edge.stacks', []).name;
|
Loading…
Add table
Add a link
Reference in a new issue