mirror of https://github.com/portainer/portainer
feat(analytics): track existing features (#5448) [EE-1076]
parent
b8e6c5ea91
commit
4ffee27a4b
|
@ -163,5 +163,19 @@
|
|||
"// @failure 500 \"Server error\"",
|
||||
"// @router /{id} [get]"
|
||||
]
|
||||
},
|
||||
"analytics": {
|
||||
"prefix": "nlt",
|
||||
"body": ["analytics-on", "analytics-category=\"$1\"", "analytics-event=\"$2\""],
|
||||
"description": "analytics"
|
||||
},
|
||||
"analytics-if": {
|
||||
"prefix": "nltf",
|
||||
"body": ["analytics-if=\"$1\""],
|
||||
"description": "analytics"
|
||||
},
|
||||
"analytics-metadata": {
|
||||
"prefix": "nltm",
|
||||
"body": "analytics-properties=\"{ metadata: { $1 } }\""
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import angular from 'angular';
|
||||
import _ from 'lodash-es';
|
||||
|
||||
const basePath = 'http://portainer-ce.app';
|
||||
|
||||
|
@ -131,7 +132,8 @@ function config($analyticsProvider, $windowProvider) {
|
|||
|
||||
let metadataString = '';
|
||||
if (metadata) {
|
||||
metadataString = JSON.stringify(metadata).toLowerCase();
|
||||
const kebabCasedMetadata = Object.fromEntries(Object.entries(metadata).map(([key, value]) => [_.kebabCase(key), value]));
|
||||
metadataString = JSON.stringify(kebabCasedMetadata).toLowerCase();
|
||||
}
|
||||
|
||||
push([
|
||||
|
|
|
@ -199,6 +199,10 @@
|
|||
ng-click="$ctrl.createStack()"
|
||||
button-spinner="$ctrl.state.actionInProgress"
|
||||
data-cy="edgeStackCreate-createStackButton"
|
||||
analytics-on
|
||||
analytics-event="edge-stack-creation"
|
||||
analytics-category="edge"
|
||||
analytics-properties="$ctrl.buildAnalyticsProperties()"
|
||||
>
|
||||
<span ng-hide="$ctrl.state.actionInProgress">Deploy the stack</span>
|
||||
<span ng-show="$ctrl.state.actionInProgress">Deployment in progress...</span>
|
||||
|
|
|
@ -43,6 +43,30 @@ export class CreateEdgeStackViewController {
|
|||
this.onChangeFormValues = this.onChangeFormValues.bind(this);
|
||||
}
|
||||
|
||||
buildAnalyticsProperties() {
|
||||
const format = 'compose';
|
||||
const metadata = { type: methodLabel(this.state.Method), format };
|
||||
|
||||
if (metadata.type === 'template') {
|
||||
metadata.templateName = this.selectedTemplate.title;
|
||||
}
|
||||
|
||||
return { metadata };
|
||||
|
||||
function methodLabel(method) {
|
||||
switch (method) {
|
||||
case 'editor':
|
||||
return 'web-editor';
|
||||
case 'repository':
|
||||
return 'git';
|
||||
case 'upload':
|
||||
return 'file-upload';
|
||||
case 'template':
|
||||
return 'template';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async uiCanExit() {
|
||||
if (this.state.Method === 'editor' && this.formValues.StackFileContent && this.state.isEditorDirty) {
|
||||
return this.ModalService.confirmWebEditorDiscard();
|
||||
|
|
|
@ -1,4 +1,13 @@
|
|||
<button type="button" class="btn btn-xs btn-primary" ng-click="$ctrl.connectConsole()" ng-disabled="$ctrl.state.shell.connected" data-cy="k8sSidebar-shellButton">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-xs btn-primary"
|
||||
ng-click="$ctrl.connectConsole()"
|
||||
ng-disabled="$ctrl.state.shell.connected"
|
||||
data-cy="k8sSidebar-shellButton"
|
||||
analytics-on
|
||||
analytics-category="kubernetes"
|
||||
analytics-event="kubernetes-kubectl-shell"
|
||||
>
|
||||
<i class="fa fa-terminal space-right"></i> kubectl shell
|
||||
</button>
|
||||
|
||||
|
|
|
@ -299,6 +299,11 @@
|
|||
ng-click="ctrl.configure()"
|
||||
ng-disabled="ctrl.state.actionInProgress || !kubernetesClusterSetupForm.$valid || !ctrl.hasValidStorageConfiguration()"
|
||||
button-spinner="ctrl.state.actionInProgress"
|
||||
analytics-on
|
||||
analytics-if="ctrl.restrictDefaultToggledOn()"
|
||||
analytics-category="kubernetes"
|
||||
analytics-event="kubernetes-configure"
|
||||
analytics-properties="{ metadata: { restrictAccessToDefaultNamespace: ctrl.formValues.RestrictDefaultNamespace } }"
|
||||
>
|
||||
<span ng-hide="ctrl.state.actionInProgress">Save configuration</span>
|
||||
<span ng-show="ctrl.state.actionInProgress">Saving configuration...</span>
|
||||
|
|
|
@ -237,6 +237,10 @@ class KubernetesConfigureController {
|
|||
}
|
||||
/* #endregion */
|
||||
|
||||
restrictDefaultToggledOn() {
|
||||
return this.formValues.RestrictDefaultNamespace && !this.oldFormValues.RestrictDefaultNamespace;
|
||||
}
|
||||
|
||||
/* #region ON INIT */
|
||||
async onInit() {
|
||||
this.state = {
|
||||
|
@ -287,6 +291,8 @@ class KubernetesConfigureController {
|
|||
ic.NeedsDeletion = false;
|
||||
return ic;
|
||||
});
|
||||
|
||||
this.oldFormValues = Object.assign({}, this.formValues);
|
||||
} catch (err) {
|
||||
this.Notifications.error('Failure', err, 'Unable to retrieve endpoint configuration');
|
||||
} finally {
|
||||
|
|
|
@ -151,6 +151,10 @@
|
|||
ng-click="ctrl.deploy()"
|
||||
button-spinner="ctrl.state.actionInProgress"
|
||||
data-cy="k8sAppDeploy-deployButton"
|
||||
analytics-on
|
||||
analytics-category="kubernetes"
|
||||
analytics-event="kubernetes-application-advanced-deployment"
|
||||
analytics-properties="ctrl.buildAnalyticsProperties()"
|
||||
>
|
||||
<span ng-hide="ctrl.state.actionInProgress">Deploy</span>
|
||||
<span ng-show="ctrl.state.actionInProgress">Deployment in progress...</span>
|
||||
|
|
|
@ -7,10 +7,11 @@ import { KubernetesDeployManifestTypes, KubernetesDeployBuildMethods, Kubernetes
|
|||
import { buildOption } from '@/portainer/components/box-selector';
|
||||
class KubernetesDeployController {
|
||||
/* @ngInject */
|
||||
constructor($async, $state, $window, CustomTemplateService, ModalService, Notifications, EndpointProvider, KubernetesResourcePoolService, StackService) {
|
||||
constructor($async, $state, $window, Authentication, CustomTemplateService, ModalService, Notifications, EndpointProvider, KubernetesResourcePoolService, StackService) {
|
||||
this.$async = $async;
|
||||
this.$state = $state;
|
||||
this.$window = $window;
|
||||
this.Authentication = Authentication;
|
||||
this.CustomTemplateService = CustomTemplateService;
|
||||
this.ModalService = ModalService;
|
||||
this.Notifications = Notifications;
|
||||
|
@ -52,6 +53,47 @@ class KubernetesDeployController {
|
|||
this.onChangeFormValues = this.onChangeFormValues.bind(this);
|
||||
this.onRepoUrlChange = this.onRepoUrlChange.bind(this);
|
||||
this.onRepoRefChange = this.onRepoRefChange.bind(this);
|
||||
this.buildAnalyticsProperties = this.buildAnalyticsProperties.bind(this);
|
||||
}
|
||||
|
||||
buildAnalyticsProperties() {
|
||||
const metadata = {
|
||||
type: buildLabel(this.state.BuildMethod),
|
||||
format: formatLabel(this.state.DeployType),
|
||||
role: roleLabel(this.Authentication.isAdmin()),
|
||||
};
|
||||
|
||||
if (this.state.BuildMethod === KubernetesDeployBuildMethods.GIT) {
|
||||
metadata.auth = this.formValues.RepositoryAuthentication;
|
||||
}
|
||||
|
||||
return { metadata };
|
||||
|
||||
function roleLabel(isAdmin) {
|
||||
if (isAdmin) {
|
||||
return 'admin';
|
||||
}
|
||||
|
||||
return 'standard';
|
||||
}
|
||||
|
||||
function buildLabel(buildMethod) {
|
||||
switch (buildMethod) {
|
||||
case KubernetesDeployBuildMethods.GIT:
|
||||
return 'git';
|
||||
case KubernetesDeployBuildMethods.WEB_EDITOR:
|
||||
return 'web-editor';
|
||||
}
|
||||
}
|
||||
|
||||
function formatLabel(format) {
|
||||
switch (format) {
|
||||
case KubernetesDeployManifestTypes.COMPOSE:
|
||||
return 'compose';
|
||||
case KubernetesDeployManifestTypes.KUBERNETES:
|
||||
return 'manifest';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
disableDeploy() {
|
||||
|
@ -59,11 +101,13 @@ class KubernetesDeployController {
|
|||
this.state.BuildMethod === KubernetesDeployBuildMethods.GIT &&
|
||||
(!this.formValues.RepositoryURL ||
|
||||
!this.formValues.FilePathInRepository ||
|
||||
(this.formValues.RepositoryAuthentication && (!this.formValues.RepositoryUsername || !this.formValues.RepositoryPassword))) && _.isEmpty(this.formValues.Namespace);
|
||||
const isWebEditorInvalid = this.state.BuildMethod === KubernetesDeployBuildMethods.WEB_EDITOR && _.isEmpty(this.formValues.EditorContent) && _.isEmpty(this.formValues.Namespace);
|
||||
(this.formValues.RepositoryAuthentication && (!this.formValues.RepositoryUsername || !this.formValues.RepositoryPassword))) &&
|
||||
_.isEmpty(this.formValues.Namespace);
|
||||
const isWebEditorInvalid =
|
||||
this.state.BuildMethod === KubernetesDeployBuildMethods.WEB_EDITOR && _.isEmpty(this.formValues.EditorContent) && _.isEmpty(this.formValues.Namespace);
|
||||
const isURLFormInvalid = this.state.BuildMethod == KubernetesDeployBuildMethods.WEB_EDITOR.URL && _.isEmpty(this.formValues.ManifestURL);
|
||||
|
||||
return isGitFormInvalid || isWebEditorInvalid || isURLFormInvalid || this.state.actionInProgress;
|
||||
return isGitFormInvalid || isWebEditorInvalid || isURLFormInvalid || this.state.actionInProgress;
|
||||
}
|
||||
|
||||
onChangeFormValues(values) {
|
||||
|
@ -127,7 +171,7 @@ class KubernetesDeployController {
|
|||
case KubernetesDeployBuildMethods.CUSTOM_TEMPLATE:
|
||||
method = KubernetesDeployRequestMethods.STRING;
|
||||
composeFormat = false;
|
||||
break;
|
||||
break;
|
||||
case this.BuildMethods.URL:
|
||||
method = KubernetesDeployRequestMethods.URL;
|
||||
break;
|
||||
|
|
|
@ -8,8 +8,8 @@ class CustomTemplateSelectorController {
|
|||
}
|
||||
|
||||
async handleChangeTemplate(templateId) {
|
||||
this.selectedTemplate = this.templates.find((t) => t.id === templateId);
|
||||
this.onChange(templateId);
|
||||
this.selectedTemplate = this.templates.find((t) => t.Id === templateId);
|
||||
this.onChange(templateId, this.selectedTemplate);
|
||||
}
|
||||
|
||||
$onChanges({ value }) {
|
||||
|
|
|
@ -71,7 +71,16 @@
|
|||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<button type="submit" class="btn btn-primary btn-sm" ng-disabled="$ctrl.actionInProgress || !registryFormAzure.$valid" button-spinner="$ctrl.actionInProgress">
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-primary btn-sm"
|
||||
ng-disabled="$ctrl.actionInProgress || !registryFormAzure.$valid"
|
||||
button-spinner="$ctrl.actionInProgress"
|
||||
analytics-on
|
||||
analytics-category="portainer"
|
||||
analytics-event="portainer-registry-creation"
|
||||
analytics-properties="{ metadata: { type: 'azure' } }"
|
||||
>
|
||||
<span ng-hide="$ctrl.actionInProgress">{{ $ctrl.formActionLabel }}</span>
|
||||
<span ng-show="$ctrl.actionInProgress">In progress...</span>
|
||||
</button>
|
||||
|
|
|
@ -93,7 +93,16 @@
|
|||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<button type="submit" class="btn btn-primary btn-sm" ng-disabled="$ctrl.actionInProgress || !registryFormCustom.$valid" button-spinner="$ctrl.actionInProgress">
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-primary btn-sm"
|
||||
ng-disabled="$ctrl.actionInProgress || !registryFormCustom.$valid"
|
||||
button-spinner="$ctrl.actionInProgress"
|
||||
analytics-on
|
||||
analytics-category="portainer"
|
||||
analytics-event="portainer-registry-creation"
|
||||
analytics-properties="{ metadata: { type: 'custom' }}"
|
||||
>
|
||||
<span ng-hide="$ctrl.actionInProgress">{{ $ctrl.formActionLabel }}</span>
|
||||
<span ng-show="$ctrl.actionInProgress">In progress...</span>
|
||||
</button>
|
||||
|
|
|
@ -54,7 +54,16 @@
|
|||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<button type="submit" class="btn btn-primary btn-sm" ng-disabled="$ctrl.actionInProgress || !registryFormDockerhub.$valid" button-spinner="$ctrl.actionInProgress">
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-primary btn-sm"
|
||||
ng-disabled="$ctrl.actionInProgress || !registryFormDockerhub.$valid"
|
||||
button-spinner="$ctrl.actionInProgress"
|
||||
analytics-on
|
||||
analytics-category="portainer"
|
||||
analytics-event="portainer-registry-creation"
|
||||
analytics-properties="{ metadata: { type: 'dockerhub' } }"
|
||||
>
|
||||
<span ng-hide="$ctrl.actionInProgress">{{ $ctrl.formActionLabel }}</span>
|
||||
<span ng-show="$ctrl.actionInProgress">In progress...</span>
|
||||
</button>
|
||||
|
|
|
@ -133,6 +133,10 @@
|
|||
class="btn btn-primary btn-sm"
|
||||
ng-disabled="$ctrl.actionInProgress || !$ctrl.state.gitlab.selectedItemCount"
|
||||
button-spinner="$ctrl.actionInProgress"
|
||||
analytics-on
|
||||
analytics-category="portainer"
|
||||
analytics-event="portainer-registry-creation"
|
||||
analytics-properties="{ metadata: { type: 'gitlab' } }"
|
||||
>
|
||||
<span ng-hide="$ctrl.actionInProgress">Create registries</span>
|
||||
<span ng-show="$ctrl.actionInProgress">In progress...</span>
|
||||
|
|
|
@ -100,7 +100,16 @@
|
|||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<button type="submit" class="btn btn-primary btn-sm" ng-disabled="$ctrl.actionInProgress || !registryFormProGet.$valid" button-spinner="$ctrl.actionInProgress">
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-primary btn-sm"
|
||||
ng-disabled="$ctrl.actionInProgress || !registryFormProGet.$valid"
|
||||
button-spinner="$ctrl.actionInProgress"
|
||||
analytics-on
|
||||
analytics-category="portainer"
|
||||
analytics-event="portainer-registry-creation"
|
||||
analytics-properties="{ metadata: { type: 'proget' } }"
|
||||
>
|
||||
<span ng-hide="$ctrl.actionInProgress">{{ $ctrl.formActionLabel }}</span>
|
||||
<span ng-show="$ctrl.actionInProgress">In progress...</span>
|
||||
</button>
|
||||
|
|
|
@ -67,7 +67,16 @@
|
|||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<button type="submit" class="btn btn-primary btn-sm" ng-disabled="$ctrl.actionInProgress || !registryFormQuay.$valid" button-spinner="$ctrl.actionInProgress">
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-primary btn-sm"
|
||||
ng-disabled="$ctrl.actionInProgress || !registryFormQuay.$valid"
|
||||
button-spinner="$ctrl.actionInProgress"
|
||||
analytics-on
|
||||
analytics-category="portainer"
|
||||
analytics-event="portainer-registry-creation"
|
||||
analytics-properties="{ metadata: { type: 'quay' } }"
|
||||
>
|
||||
<span ng-hide="$ctrl.actionInProgress">{{ $ctrl.formActionLabel }}</span>
|
||||
<span ng-show="$ctrl.actionInProgress">In progress...</span>
|
||||
</button>
|
||||
|
|
|
@ -25,7 +25,7 @@ class StackRedeployGitFormController {
|
|||
RepositoryUsername: '',
|
||||
RepositoryPassword: '',
|
||||
Env: [],
|
||||
// auto upadte
|
||||
// auto update
|
||||
AutoUpdate: {
|
||||
RepositoryAutomaticUpdates: false,
|
||||
RepositoryMechanism: 'Interval',
|
||||
|
@ -38,6 +38,26 @@ class StackRedeployGitFormController {
|
|||
this.onChangeRef = this.onChangeRef.bind(this);
|
||||
this.onChangeAutoUpdate = this.onChangeAutoUpdate.bind(this);
|
||||
this.onChangeEnvVar = this.onChangeEnvVar.bind(this);
|
||||
this.handleEnvVarChange = this.handleEnvVarChange.bind(this);
|
||||
}
|
||||
|
||||
buildAnalyticsProperties() {
|
||||
const metadata = {};
|
||||
|
||||
if (this.formValues.RepositoryAutomaticUpdates) {
|
||||
metadata.automaticUpdates = autoSyncLabel(this.formValues.RepositoryMechanism);
|
||||
}
|
||||
return { metadata };
|
||||
|
||||
function autoSyncLabel(type) {
|
||||
switch (type) {
|
||||
case 'Interval':
|
||||
return 'polling';
|
||||
case 'Webhook':
|
||||
return 'webhook';
|
||||
}
|
||||
return 'off';
|
||||
}
|
||||
}
|
||||
|
||||
onChange(values) {
|
||||
|
@ -100,10 +120,17 @@ class StackRedeployGitFormController {
|
|||
return this.$async(async () => {
|
||||
try {
|
||||
this.state.inProgress = true;
|
||||
await this.StackService.updateGitStackSettings(this.stack.Id, this.stack.EndpointId, this.FormHelper.removeInvalidEnvVars(this.formValues.Env), this.formValues);
|
||||
const stack = await this.StackService.updateGitStackSettings(
|
||||
this.stack.Id,
|
||||
this.stack.EndpointId,
|
||||
this.FormHelper.removeInvalidEnvVars(this.formValues.Env),
|
||||
this.formValues
|
||||
);
|
||||
this.savedFormValues = angular.copy(this.formValues);
|
||||
this.state.hasUnsavedChanges = false;
|
||||
this.Notifications.success('Save stack settings successfully');
|
||||
|
||||
this.stack = stack;
|
||||
} catch (err) {
|
||||
this.Notifications.error('Failure', err, 'Unable to save stack settings');
|
||||
} finally {
|
||||
|
@ -116,6 +143,16 @@ class StackRedeployGitFormController {
|
|||
return this.state.inProgress || this.state.redeployInProgress;
|
||||
}
|
||||
|
||||
handleEnvVarChange(value) {
|
||||
this.formValues.Env = value;
|
||||
}
|
||||
|
||||
isAutoUpdateChanged() {
|
||||
const wasEnabled = !!(this.stack.AutoUpdate && (this.stack.AutoUpdate.Interval || this.stack.AutoUpdate.Webhook));
|
||||
const isEnabled = this.formValues.AutoUpdate.RepositoryAutomaticUpdates;
|
||||
return isEnabled !== wasEnabled;
|
||||
}
|
||||
|
||||
$onInit() {
|
||||
this.formValues.RefName = this.model.ReferenceName;
|
||||
this.formValues.Env = this.stack.Env;
|
||||
|
|
|
@ -50,8 +50,9 @@
|
|||
ng-disabled="$ctrl.isSubmitButtonDisabled() || $ctrl.state.hasUnsavedChanges || !$ctrl.redeployGitForm.$valid"
|
||||
style="margin-top: 7px; margin-left: 0;"
|
||||
button-spinner="$ctrl.state.redeployInProgress"
|
||||
style="margin-top: 7px; margin-left: 0;"
|
||||
button-spinner="$ctrl.state.inProgress"
|
||||
analytics-on
|
||||
analytics-event="docker-stack-pull-redeploy"
|
||||
analytics-category="docker"
|
||||
>
|
||||
<span ng-hide="$ctrl.state.redeployInProgress"> <i class="fa fa-sync space-right" aria-hidden="true"></i> Pull and redeploy </span>
|
||||
<span ng-show="$ctrl.state.redeployInProgress">In progress...</span>
|
||||
|
@ -63,6 +64,10 @@
|
|||
ng-disabled="$ctrl.isSubmitButtonDisabled() || !$ctrl.state.hasUnsavedChanges || !$ctrl.redeployGitForm.$valid"
|
||||
style="margin-top: 7px; margin-left: 0;"
|
||||
button-spinner="$ctrl.state.inProgress"
|
||||
analytics-on
|
||||
analytics-event="docker-stack-update-git-settings"
|
||||
analytics-category="docker"
|
||||
analytics-properties="$ctrl.buildAnalyticsProperties()"
|
||||
>
|
||||
<span ng-hide="$ctrl.state.inProgress"> Save settings </span>
|
||||
<span ng-show="$ctrl.state.inProgress">In progress...</span>
|
||||
|
|
|
@ -51,6 +51,10 @@ class SslCertificateController {
|
|||
});
|
||||
}
|
||||
|
||||
wasHTTPsChanged() {
|
||||
return this.originalValues.forceHTTPS !== this.formValues.forceHTTPS;
|
||||
}
|
||||
|
||||
async $onInit() {
|
||||
return this.$async(async () => {
|
||||
try {
|
||||
|
|
|
@ -80,6 +80,11 @@
|
|||
ng-disabled="$ctrl.state.actionInProgress || !$ctrl.isFormChanged()"
|
||||
ng-click="$ctrl.save()"
|
||||
button-spinner="$ctrl.state.actionInProgress"
|
||||
analytics-on
|
||||
analytics-if="$ctrl.wasHTTPsChanged()"
|
||||
analytics-category="portainer"
|
||||
analytics-event="portainer-settings-edit"
|
||||
analytics-properties="{ metadata: { forceHTTPS: $ctrl.formValues.forceHTTPS } }"
|
||||
>
|
||||
<span ng-hide="$ctrl.state.actionInProgress || $ctrl.state.reloadingPage">Apply Changes</span>
|
||||
<span ng-show="$ctrl.state.actionInProgress">Saving in progress...</span>
|
||||
|
|
|
@ -5,6 +5,7 @@ angular
|
|||
.module('portainer.app')
|
||||
.controller('CreateEndpointController', function CreateEndpointController(
|
||||
$async,
|
||||
$analytics,
|
||||
$q,
|
||||
$scope,
|
||||
$state,
|
||||
|
@ -167,16 +168,32 @@ angular
|
|||
});
|
||||
};
|
||||
|
||||
$scope.addAgentEndpoint = function () {
|
||||
var name = $scope.formValues.Name;
|
||||
// var URL = $filter('stripprotocol')($scope.formValues.URL);
|
||||
var URL = $scope.formValues.URL;
|
||||
var publicURL = $scope.formValues.PublicURL === '' ? URL.split(':')[0] : $scope.formValues.PublicURL;
|
||||
var groupId = $scope.formValues.GroupId;
|
||||
var tagIds = $scope.formValues.TagIds;
|
||||
$scope.addAgentEndpoint = addAgentEndpoint;
|
||||
async function addAgentEndpoint() {
|
||||
return $async(async () => {
|
||||
const name = $scope.formValues.Name;
|
||||
const URL = $scope.formValues.URL;
|
||||
const publicURL = $scope.formValues.PublicURL === '' ? URL.split(':')[0] : $scope.formValues.PublicURL;
|
||||
const groupId = $scope.formValues.GroupId;
|
||||
const tagIds = $scope.formValues.TagIds;
|
||||
|
||||
addEndpoint(name, PortainerEndpointCreationTypes.AgentEnvironment, URL, publicURL, groupId, tagIds, true, true, true, null, null, null);
|
||||
};
|
||||
const endpoint = await addEndpoint(name, PortainerEndpointCreationTypes.AgentEnvironment, URL, publicURL, groupId, tagIds, true, true, true, null, null, null);
|
||||
$analytics.eventTrack('portainer-endpoint-creation', { category: 'portainer', metadata: { type: 'agent', platform: platformLabel(endpoint.Type) } });
|
||||
});
|
||||
|
||||
function platformLabel(type) {
|
||||
switch (type) {
|
||||
case PortainerEndpointTypes.DockerEnvironment:
|
||||
case PortainerEndpointTypes.AgentOnDockerEnvironment:
|
||||
case PortainerEndpointTypes.EdgeAgentOnDockerEnvironment:
|
||||
return 'docker';
|
||||
case PortainerEndpointTypes.KubernetesLocalEnvironment:
|
||||
case PortainerEndpointTypes.AgentOnKubernetesEnvironment:
|
||||
case PortainerEndpointTypes.EdgeAgentOnKubernetesEnvironment:
|
||||
return 'kubernetes';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$scope.addEdgeAgentEndpoint = function () {
|
||||
var name = $scope.formValues.Name;
|
||||
|
@ -213,24 +230,26 @@ angular
|
|||
});
|
||||
}
|
||||
|
||||
function addEndpoint(name, creationType, URL, PublicURL, groupId, tagIds, TLS, TLSSkipVerify, TLSSkipClientVerify, TLSCAFile, TLSCertFile, TLSKeyFile, CheckinInterval) {
|
||||
$scope.state.actionInProgress = true;
|
||||
EndpointService.createRemoteEndpoint(
|
||||
name,
|
||||
creationType,
|
||||
URL,
|
||||
PublicURL,
|
||||
groupId,
|
||||
tagIds,
|
||||
TLS,
|
||||
TLSSkipVerify,
|
||||
TLSSkipClientVerify,
|
||||
TLSCAFile,
|
||||
TLSCertFile,
|
||||
TLSKeyFile,
|
||||
CheckinInterval
|
||||
)
|
||||
.then(function success(endpoint) {
|
||||
async function addEndpoint(name, creationType, URL, PublicURL, groupId, tagIds, TLS, TLSSkipVerify, TLSSkipClientVerify, TLSCAFile, TLSCertFile, TLSKeyFile, CheckinInterval) {
|
||||
return $async(async () => {
|
||||
$scope.state.actionInProgress = true;
|
||||
try {
|
||||
const endpoint = await EndpointService.createRemoteEndpoint(
|
||||
name,
|
||||
creationType,
|
||||
URL,
|
||||
PublicURL,
|
||||
groupId,
|
||||
tagIds,
|
||||
TLS,
|
||||
TLSSkipVerify,
|
||||
TLSSkipClientVerify,
|
||||
TLSCAFile,
|
||||
TLSCertFile,
|
||||
TLSKeyFile,
|
||||
CheckinInterval
|
||||
);
|
||||
|
||||
Notifications.success('Endpoint created', name);
|
||||
switch (endpoint.Type) {
|
||||
case PortainerEndpointTypes.EdgeAgentOnDockerEnvironment:
|
||||
|
@ -244,13 +263,14 @@ angular
|
|||
$state.go('portainer.endpoints', {}, { reload: true });
|
||||
break;
|
||||
}
|
||||
})
|
||||
.catch(function error(err) {
|
||||
|
||||
return endpoint;
|
||||
} catch (err) {
|
||||
Notifications.error('Failure', err, 'Unable to create endpoint');
|
||||
})
|
||||
.finally(function final() {
|
||||
} finally {
|
||||
$scope.state.actionInProgress = false;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function initView() {
|
||||
|
|
|
@ -482,6 +482,10 @@
|
|||
ng-click="addDockerEndpoint()"
|
||||
button-spinner="state.actionInProgress"
|
||||
data-cy="endpointCreate-createDockerEndpoint"
|
||||
analytics-on
|
||||
analytics-category="portainer"
|
||||
analytics-event="portainer-endpoint-creation"
|
||||
analytics-properties="{ metadata: { type: 'docker-api' } }"
|
||||
>
|
||||
<span ng-hide="state.actionInProgress"><i class="fa fa-plus" aria-hidden="true"></i> Add endpoint</span>
|
||||
<span ng-show="state.actionInProgress">Creating endpoint...</span>
|
||||
|
@ -506,6 +510,10 @@
|
|||
ng-click="addEdgeAgentEndpoint()"
|
||||
button-spinner="state.actionInProgress"
|
||||
data-cy="endpointCreate-createEdgeAgentEndpoint"
|
||||
analytics-on
|
||||
analytics-category="portainer"
|
||||
analytics-event="portainer-endpoint-creation"
|
||||
analytics-properties="{ metadata: { type: 'edge-agent' } }"
|
||||
>
|
||||
<span ng-hide="state.actionInProgress"><i class="fa fa-plus" aria-hidden="true"></i> Add endpoint</span>
|
||||
<span ng-show="state.actionInProgress">Creating endpoint...</span>
|
||||
|
@ -517,6 +525,10 @@
|
|||
ng-disabled="state.actionInProgress || !endpointCreationForm.$valid"
|
||||
ng-click="addKubernetesEndpoint()"
|
||||
button-spinner="state.actionInProgress"
|
||||
analytics-on
|
||||
analytics-category="portainer"
|
||||
analytics-event="portainer-endpoint-creation"
|
||||
analytics-properties="{ metadata: { type: 'kubernetes-api' } }"
|
||||
>
|
||||
<span ng-hide="state.actionInProgress"><i class="fa fa-plus" aria-hidden="true"></i> Add endpoint</span>
|
||||
<span ng-show="state.actionInProgress">Creating endpoint...</span>
|
||||
|
@ -529,6 +541,10 @@
|
|||
ng-click="addAzureEndpoint()"
|
||||
button-spinner="state.actionInProgress"
|
||||
data-cy="endpointCreate-createAzureEndpoint"
|
||||
analytics-on
|
||||
analytics-category="portainer"
|
||||
analytics-event="portainer-endpoint-creation"
|
||||
analytics-properties="{ metadata: { type: 'azure-api' } }"
|
||||
>
|
||||
<span ng-hide="state.actionInProgress"><i class="fa fa-plus" aria-hidden="true"></i> Add endpoint</span>
|
||||
<span ng-show="state.actionInProgress">Creating endpoint...</span>
|
||||
|
|
|
@ -23,7 +23,16 @@
|
|||
Edge identifier: <code>{{ endpoint.EdgeID }}</code>
|
||||
</p>
|
||||
<p>
|
||||
<button type="button" class="btn btn-primary btn-sm" ng-disabled="state.actionInProgress" ng-click="onDeassociateEndpoint()" button-spinner="state.actionInProgress">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary btn-sm"
|
||||
ng-disabled="state.actionInProgress"
|
||||
ng-click="onDeassociateEndpoint()"
|
||||
button-spinner="state.actionInProgress"
|
||||
analytics-on
|
||||
analytics-event="edge-endpoint-deassociate"
|
||||
analytics-category="edge"
|
||||
>
|
||||
<span ng-hide="state.actionInProgress">De-associate</span>
|
||||
</button>
|
||||
</p>
|
||||
|
|
|
@ -26,6 +26,7 @@ angular
|
|||
clipboard
|
||||
) {
|
||||
$scope.onChangeTemplateId = onChangeTemplateId;
|
||||
$scope.buildAnalyticsProperties = buildAnalyticsProperties;
|
||||
|
||||
$scope.formValues = {
|
||||
Name: '',
|
||||
|
@ -54,6 +55,8 @@ angular
|
|||
editorYamlValidationError: '',
|
||||
uploadYamlValidationError: '',
|
||||
isEditorDirty: false,
|
||||
selectedTemplate: null,
|
||||
selectedTemplateId: null,
|
||||
};
|
||||
|
||||
$window.onbeforeunload = () => {
|
||||
|
@ -76,6 +79,47 @@ angular
|
|||
$scope.formValues.AdditionalFiles.splice(index, 1);
|
||||
};
|
||||
|
||||
function buildAnalyticsProperties() {
|
||||
const metadata = { type: methodLabel($scope.state.Method) };
|
||||
|
||||
if ($scope.state.Method === 'repository') {
|
||||
metadata.automaticUpdates = 'off';
|
||||
if ($scope.formValues.RepositoryAutomaticUpdates) {
|
||||
metadata.automaticUpdates = autoSyncLabel($scope.formValues.RepositoryMechanism);
|
||||
}
|
||||
metadata.auth = $scope.formValues.RepositoryAuthentication;
|
||||
}
|
||||
|
||||
if ($scope.state.Method === 'template') {
|
||||
metadata.templateName = $scope.state.selectedTemplate.Title;
|
||||
}
|
||||
|
||||
return { metadata };
|
||||
|
||||
function methodLabel(method) {
|
||||
switch (method) {
|
||||
case 'editor':
|
||||
return 'web-editor';
|
||||
case 'repository':
|
||||
return 'git';
|
||||
case 'upload':
|
||||
return 'file-upload';
|
||||
case 'template':
|
||||
return 'custom-template';
|
||||
}
|
||||
}
|
||||
|
||||
function autoSyncLabel(type) {
|
||||
switch (type) {
|
||||
case 'Interval':
|
||||
return 'polling';
|
||||
case 'Webhook':
|
||||
return 'webhook';
|
||||
}
|
||||
return 'off';
|
||||
}
|
||||
}
|
||||
|
||||
function validateForm(accessControlData, isAdmin) {
|
||||
$scope.state.formValidationError = '';
|
||||
var error = '';
|
||||
|
@ -238,10 +282,11 @@ angular
|
|||
}
|
||||
};
|
||||
|
||||
function onChangeTemplateId(templateId) {
|
||||
function onChangeTemplateId(templateId, template) {
|
||||
return $async(async () => {
|
||||
try {
|
||||
$scope.state.templateId = templateId;
|
||||
$scope.state.selectedTemplateId = templateId;
|
||||
$scope.state.selectedTemplate = template;
|
||||
|
||||
const fileContent = await CustomTemplateService.customTemplateFile(templateId);
|
||||
$scope.onChangeFileContent(fileContent);
|
||||
|
|
|
@ -120,11 +120,11 @@
|
|||
new-template-path="docker.templates.custom.new"
|
||||
stack-type="state.StackType"
|
||||
on-change="(onChangeTemplateId)"
|
||||
value="state.templateId"
|
||||
value="state.selectedTemplateId"
|
||||
></custom-template-selector>
|
||||
|
||||
<web-editor-form
|
||||
ng-if="state.Method === 'editor' || (state.Method === 'template' && state.templateId)"
|
||||
ng-if="state.Method === 'editor' || (state.Method === 'template' && state.selectedTemplateId)"
|
||||
identifier="stack-creation-editor"
|
||||
value="formValues.StackFileContent"
|
||||
on-change="(onChangeFileContent)"
|
||||
|
@ -164,6 +164,10 @@
|
|||
|| !formValues.Name"
|
||||
ng-click="deployStack()"
|
||||
button-spinner="state.actionInProgress"
|
||||
analytics-on
|
||||
analytics-category="docker"
|
||||
analytics-event="docker-stack-create"
|
||||
analytics-properties="buildAnalyticsProperties()"
|
||||
>
|
||||
<span ng-hide="state.actionInProgress">Deploy the stack</span>
|
||||
<span ng-show="state.actionInProgress">Deployment in progress...</span>
|
||||
|
|
Loading…
Reference in New Issue