mirror of
https://github.com/ZwareBear/awx.git
synced 2026-05-13 05:38:36 -05:00
Merge pull request #4436 from jbradberry/webhook-receivers
Webhook receivers Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
This commit is contained in:
@@ -14,6 +14,7 @@ function JobsStrings (BaseString) {
|
||||
ROW_ITEM_LABEL_INVENTORY: t.s('Inventory'),
|
||||
ROW_ITEM_LABEL_PROJECT: t.s('Project'),
|
||||
ROW_ITEM_LABEL_CREDENTIALS: t.s('Credentials'),
|
||||
ROW_ITEM_LABEL_WEBHOOK: t.s('Webhook'),
|
||||
NO_RUNNING: t.s('There are no running jobs.'),
|
||||
JOB: t.s('Job'),
|
||||
STATUS_TOOLTIP: status => t.s('Job {{status}}. Click for details.', { status }),
|
||||
|
||||
@@ -142,19 +142,13 @@ function ListJobsController (
|
||||
return { icon, link, value };
|
||||
});
|
||||
|
||||
vm.getSliceJobDetails = (job) => {
|
||||
if (!job.job_slice_count) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (job.job_slice_count === 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (job.job_slice_number && job.job_slice_count) {
|
||||
vm.getSecondaryTagLabel = (job) => {
|
||||
if (job.job_slice_number && job.job_slice_count && job.job_slice_count > 1) {
|
||||
return `${strings.get('list.SLICE_JOB')} ${job.job_slice_number}/${job.job_slice_count}`;
|
||||
}
|
||||
|
||||
if (job.launch_type === 'webhook') {
|
||||
return strings.get('list.ROW_ITEM_LABEL_WEBHOOK');
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
header-value="{{ job.id }} - {{ job.name }}"
|
||||
header-state="{{ vm.getSref(job) }}"
|
||||
header-tag="{{ vm.jobTypes[job.type] }}"
|
||||
secondary-tag="{{ vm.getSliceJobDetails(job) }}">
|
||||
secondary-tag="{{ vm.getSecondaryTagLabel(job) }}">
|
||||
</at-row-item>
|
||||
<div class="at-Row-actions">
|
||||
<at-relaunch job="job" ng-show="job.summary_fields.user_capabilities.start">
|
||||
|
||||
@@ -251,10 +251,12 @@ function getHostLimitErrorDetails () {
|
||||
function getLaunchedByDetails () {
|
||||
const createdBy = resource.model.get('summary_fields.created_by');
|
||||
const jobTemplate = resource.model.get('summary_fields.job_template');
|
||||
const workflowJobTemplate = resource.model.get('summary_fields.workflow_job_template');
|
||||
const relatedSchedule = resource.model.get('related.schedule');
|
||||
const schedule = resource.model.get('summary_fields.schedule');
|
||||
const launchType = resource.model.get('launch_type');
|
||||
|
||||
if (!createdBy && !schedule) {
|
||||
if (!createdBy && !schedule && !launchType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -264,7 +266,15 @@ function getLaunchedByDetails () {
|
||||
let tooltip;
|
||||
let value;
|
||||
|
||||
if (createdBy) {
|
||||
if (launchType === 'webhook' && jobTemplate) {
|
||||
tooltip = strings.get('tooltips.WEBHOOK_JOB_TEMPLATE');
|
||||
link = `/#/templates/job_template/${jobTemplate.id}`;
|
||||
value = strings.get('details.WEBHOOK');
|
||||
} else if (launchType === 'webhook' && workflowJobTemplate) {
|
||||
tooltip = strings.get('tooltips.WEBHOOK_WORKFLOW_JOB_TEMPLATE');
|
||||
link = `/#/templates/workflow_job_template/${workflowJobTemplate.id}`;
|
||||
value = strings.get('details.WEBHOOK');
|
||||
} else if (createdBy) {
|
||||
tooltip = strings.get('tooltips.USER');
|
||||
link = `/#/users/${createdBy.id}`;
|
||||
value = $filter('sanitize')(createdBy.username);
|
||||
|
||||
@@ -38,6 +38,8 @@ function OutputStrings (BaseString) {
|
||||
MENU_UP: t.s('Get previous page'),
|
||||
MENU_LAST: t.s('Go to last page of available output'),
|
||||
MENU_FOLLOWING: t.s('Currently following output as it arrives. Click to unfollow'),
|
||||
WEBHOOK_JOB_TEMPLATE: t.s('View the webhook configuration on the job template.'),
|
||||
WEBHOOK_WORKFLOW_JOB_TEMPLATE: t.s('View the webhook configuration on the workflow job template.'),
|
||||
};
|
||||
|
||||
ns.details = {
|
||||
@@ -48,6 +50,7 @@ function OutputStrings (BaseString) {
|
||||
SHOW_LESS: t.s('Show Less'),
|
||||
SHOW_MORE: t.s('Show More'),
|
||||
UNKNOWN: t.s('Finished'),
|
||||
WEBHOOK: t.s('Webhook'),
|
||||
};
|
||||
|
||||
ns.labels = {
|
||||
|
||||
@@ -288,6 +288,8 @@
|
||||
line-height: @at-line-height-list-row-item-tag;
|
||||
word-break: keep-all;
|
||||
display: inline-flex;
|
||||
margin-right: 10px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.at-RowItem-tag--primary {
|
||||
|
||||
@@ -112,6 +112,7 @@
|
||||
@import '../../src/workflow-results/standard-out.block.less';
|
||||
@import '../../src/templates/prompt/prompt.block.less';
|
||||
@import '../../src/templates/job_templates/multi-credential/multi-credential.block.less';
|
||||
@import '../../src/templates/job_templates/webhook-credential/webhook-credential.block.less';
|
||||
@import '../../src/templates/labels/labelsList.block.less';
|
||||
@import '../../src/templates/survey-maker/survey-maker.block.less';
|
||||
@import '../../src/templates/survey-maker/survey-maker.block.less';
|
||||
|
||||
@@ -794,9 +794,21 @@ angular.module('FormGenerator', [GeneratorHelpers.name, 'Utilities', listGenerat
|
||||
}
|
||||
|
||||
if (field.genHash) {
|
||||
html += "<span class=\"input-group-btn input-group-prepend\"><button type=\"button\" class=\"btn Form-lookupButton\" ng-click=\"genHash('" + fld + "')\" " +
|
||||
"aw-tool-tip=\"Generate " + field.label + "\" data-placement=\"top\" id=\"" + this.form.name + "_" + fld + "_gen_btn\">" +
|
||||
"<i class=\"fa fa-magic\"></i></button></span>\n</div>\n";
|
||||
const defaultGenHashButtonTemplate = `
|
||||
<span class="input-group-btn input-group-prepend">
|
||||
<button
|
||||
type="button"
|
||||
class="btn Form-lookupButton"
|
||||
ng-click="genHash('${fld}')"
|
||||
aw-tool-tip="Generate ${field.label}"
|
||||
data-placement="top"
|
||||
id="${this.form.name}_${fld}_gen_btn"
|
||||
>
|
||||
<i class="fa fa-refresh" />
|
||||
</button>
|
||||
</span>`;
|
||||
const genHashButtonTemplate = _.get(field, 'genHashButtonTemplate', defaultGenHashButtonTemplate);
|
||||
html += `${genHashButtonTemplate}\n</div>\n`;
|
||||
}
|
||||
|
||||
// Add error messages
|
||||
|
||||
+145
-3
@@ -10,14 +10,14 @@
|
||||
'ProcessErrors', 'GetBasePath', 'hashSetup', 'ParseTypeChange', 'Wait',
|
||||
'Empty', 'ToJSON', 'CallbackHelpInit', 'GetChoices', '$state', 'availableLabels',
|
||||
'CreateSelect2', '$q', 'i18n', 'Inventory', 'Project', 'InstanceGroupsService',
|
||||
'MultiCredentialService', 'ConfigData', 'resolvedModels',
|
||||
'MultiCredentialService', 'ConfigData', 'resolvedModels', '$compile',
|
||||
function(
|
||||
$filter, $scope,
|
||||
$stateParams, JobTemplateForm, GenerateForm, Rest, Alert,
|
||||
ProcessErrors, GetBasePath, hashSetup, ParseTypeChange, Wait,
|
||||
Empty, ToJSON, CallbackHelpInit, GetChoices,
|
||||
$state, availableLabels, CreateSelect2, $q, i18n, Inventory, Project, InstanceGroupsService,
|
||||
MultiCredentialService, ConfigData, resolvedModels
|
||||
MultiCredentialService, ConfigData, resolvedModels, $compile
|
||||
) {
|
||||
|
||||
// Inject dynamic view
|
||||
@@ -39,10 +39,121 @@
|
||||
$scope.can_edit = true;
|
||||
$scope.allow_callbacks = false;
|
||||
$scope.playbook_options = [];
|
||||
$scope.webhook_service_options = [];
|
||||
$scope.mode = "add";
|
||||
$scope.parseType = 'yaml';
|
||||
$scope.credentialNotPresent = false;
|
||||
$scope.canGetAllRelatedResources = true;
|
||||
$scope.webhook_key_help = i18n._('Webhook services can use this as a shared secret.');
|
||||
|
||||
//
|
||||
// webhook credential - all handlers, dynamic state, etc. live here
|
||||
//
|
||||
|
||||
$scope.webhookCredential = {
|
||||
id: null,
|
||||
name: null,
|
||||
isModalOpen: false,
|
||||
isModalReady: false,
|
||||
modalTitle: i18n._('Select Webhook Credential'),
|
||||
modalBaseParams: {
|
||||
order_by: 'name',
|
||||
page_size: 5,
|
||||
credential_type__namespace: null,
|
||||
},
|
||||
modalSelectedId: null,
|
||||
modalSelectedName: null,
|
||||
};
|
||||
|
||||
$scope.handleWebhookCredentialLookupClick = () => {
|
||||
$scope.webhookCredential.modalSelectedId = $scope.webhookCredential.id;
|
||||
$scope.webhookCredential.isModalOpen = true;
|
||||
};
|
||||
|
||||
$scope.handleWebhookCredentialTagDelete = () => {
|
||||
$scope.webhookCredential.id = null;
|
||||
$scope.webhookCredential.name = null;
|
||||
};
|
||||
|
||||
$scope.handleWebhookCredentialModalClose = () => {
|
||||
$scope.webhookCredential.isModalOpen = false;
|
||||
$scope.webhookCredential.isModalReady = false;
|
||||
};
|
||||
|
||||
$scope.handleWebhookCredentialModalReady = () => {
|
||||
$scope.webhookCredential.isModalReady = true;
|
||||
};
|
||||
|
||||
$scope.handleWebhookCredentialModalItemSelect = (item) => {
|
||||
$scope.webhookCredential.modalSelectedId = item.id;
|
||||
$scope.webhookCredential.modalSelectedName = item.name;
|
||||
};
|
||||
|
||||
$scope.handleWebhookCredentialModalCancel = () => {
|
||||
$scope.webhookCredential.isModalOpen = false;
|
||||
$scope.webhookCredential.isModalReady = false;
|
||||
$scope.webhookCredential.modalSelectedId = null;
|
||||
$scope.webhookCredential.modalSelectedName = null;
|
||||
|
||||
};
|
||||
|
||||
$scope.handleWebhookCredentialSelect = () => {
|
||||
$scope.webhookCredential.isModalOpen = false;
|
||||
$scope.webhookCredential.isModalReady = false;
|
||||
$scope.webhookCredential.id = $scope.webhookCredential.modalSelectedId;
|
||||
$scope.webhookCredential.name = $scope.webhookCredential.modalSelectedName;
|
||||
$scope.webhookCredential.modalSelectedId = null;
|
||||
$scope.webhookCredential.modalSelectedName = null;
|
||||
};
|
||||
|
||||
$scope.handleWebhookKeyButtonClick = () => {};
|
||||
|
||||
$('#content-container').append($compile(`
|
||||
<at-dialog
|
||||
title="webhookCredential.modalTitle"
|
||||
on-close="handleWebhookCredentialModalClose"
|
||||
ng-if="webhookCredential.isModalOpen"
|
||||
ng-show="webhookCredential.isModalOpen && webhookCredential.isModalReady"
|
||||
>
|
||||
<at-lookup-list
|
||||
ng-show="webhookCredential.isModalOpen && webhookCredential.isModalReady"
|
||||
resource-name="credential"
|
||||
base-params="webhookCredential.modalBaseParams"
|
||||
selected-id="webhookCredential.modalSelectedId"
|
||||
on-ready="handleWebhookCredentialModalReady"
|
||||
on-item-select="handleWebhookCredentialModalItemSelect"
|
||||
/>
|
||||
<at-action-group col="12" pos="right">
|
||||
<at-action-button
|
||||
variant="tertiary"
|
||||
ng-click="handleWebhookCredentialModalCancel()"
|
||||
>
|
||||
${i18n._('CANCEL')}
|
||||
</at-action-button>
|
||||
<at-action-button
|
||||
variant="primary"
|
||||
ng-click="handleWebhookCredentialSelect()"
|
||||
>
|
||||
${i18n._('SELECT')}
|
||||
</at-action-button>
|
||||
</at-action-group>
|
||||
</at-dialog>`)($scope));
|
||||
|
||||
$scope.$watch('webhook_service', (newValue, oldValue) => {
|
||||
const newServiceValue = newValue && typeof newValue === 'object' ? newValue.value : newValue;
|
||||
const oldServiceValue = oldValue && typeof oldValue === 'object' ? oldValue.value : oldValue;
|
||||
if (newServiceValue !== oldServiceValue || newServiceValue === newValue) {
|
||||
$scope.webhook_service = { value: newServiceValue };
|
||||
sync_webhook_service_select2();
|
||||
$scope.webhookCredential.modalBaseParams.credential_type__namespace = newServiceValue ?
|
||||
`${newServiceValue}_token`
|
||||
: null;
|
||||
if (newServiceValue !== newValue || newValue === null) {
|
||||
$scope.webhookCredential.id = null;
|
||||
$scope.webhookCredential.name = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
hashSetup({
|
||||
scope: $scope,
|
||||
@@ -51,6 +162,9 @@
|
||||
default_val: false
|
||||
});
|
||||
CallbackHelpInit({ scope: $scope });
|
||||
// set initial vals for webhook checkbox
|
||||
$scope.enable_webhook = false;
|
||||
master.enable_webhook = false;
|
||||
|
||||
$scope.surveyTooltip = i18n._('Please save before adding a survey to this job template.');
|
||||
|
||||
@@ -131,6 +245,14 @@
|
||||
multiple: false,
|
||||
opts: $scope.custom_virtualenvs_options
|
||||
});
|
||||
CreateSelect2({
|
||||
element:'#webhook-service-select',
|
||||
addNew: false,
|
||||
multiple: false,
|
||||
scope: $scope,
|
||||
options: 'webhook_service_options',
|
||||
model: 'webhook_service'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -151,7 +273,13 @@
|
||||
variable: 'job_type_options',
|
||||
callback: 'choicesReadyVerbosity'
|
||||
});
|
||||
|
||||
GetChoices({
|
||||
scope: $scope,
|
||||
url: defaultUrl,
|
||||
field: 'webhook_service',
|
||||
variable: 'webhook_service_options',
|
||||
callback: 'choicesReadyVerbosity'
|
||||
});
|
||||
$scope.labelOptions = availableLabels
|
||||
.map((i) => ({label: i.name, value: i.id}));
|
||||
$scope.$emit("choicesReadyVerbosity");
|
||||
@@ -167,6 +295,17 @@
|
||||
});
|
||||
}
|
||||
|
||||
function sync_webhook_service_select2() {
|
||||
CreateSelect2({
|
||||
element:'#webhook-service-select',
|
||||
addNew: false,
|
||||
multiple: false,
|
||||
scope: $scope,
|
||||
options: 'webhook_service_options',
|
||||
model: 'webhook_service'
|
||||
});
|
||||
}
|
||||
|
||||
$scope.toggleForm = function(key) {
|
||||
$scope[key] = !$scope[key];
|
||||
};
|
||||
@@ -328,6 +467,9 @@
|
||||
// be provided to the related credentials endpoint by the template save success handler.
|
||||
delete data.credential;
|
||||
delete data.vault_credential;
|
||||
delete data.webhook_url;
|
||||
delete data.webhook_key;
|
||||
data.webhook_credential = $scope.webhookCredential.id;
|
||||
|
||||
data.extra_vars = ToJSON($scope.parseType, $scope.extra_vars, true);
|
||||
|
||||
|
||||
+197
-6
@@ -19,7 +19,7 @@ export default
|
||||
'initSurvey', '$state', 'CreateSelect2', 'isNotificationAdmin',
|
||||
'ToggleNotification','$q', 'InstanceGroupsService', 'InstanceGroupsData',
|
||||
'MultiCredentialService', 'availableLabels', 'projectGetPermissionDenied',
|
||||
'inventoryGetPermissionDenied', 'jobTemplateData', 'ParseVariableString', 'ConfigData',
|
||||
'inventoryGetPermissionDenied', 'jobTemplateData', 'ParseVariableString', 'ConfigData', '$compile', 'webhookKey',
|
||||
function(
|
||||
$filter, $scope,
|
||||
$stateParams, JobTemplateForm, GenerateForm, Rest, Alert,
|
||||
@@ -29,7 +29,7 @@ export default
|
||||
SurveyControllerInit, $state, CreateSelect2, isNotificationAdmin,
|
||||
ToggleNotification, $q, InstanceGroupsService, InstanceGroupsData,
|
||||
MultiCredentialService, availableLabels, projectGetPermissionDenied,
|
||||
inventoryGetPermissionDenied, jobTemplateData, ParseVariableString, ConfigData
|
||||
inventoryGetPermissionDenied, jobTemplateData, ParseVariableString, ConfigData, $compile, webhookKey
|
||||
) {
|
||||
|
||||
$scope.$watch('job_template_obj.summary_fields.user_capabilities.edit', function(val) {
|
||||
@@ -61,7 +61,10 @@ export default
|
||||
$scope.sufficientRoleForNotifToggle = isNotificationAdmin;
|
||||
$scope.sufficientRoleForNotif = isNotificationAdmin || $scope.user_is_system_auditor;
|
||||
$scope.playbook_options = null;
|
||||
$scope.webhook_service_options = null;
|
||||
$scope.playbook = null;
|
||||
$scope.webhook_service = jobTemplateData.webhook_service;
|
||||
$scope.webhook_url = '';
|
||||
$scope.mode = 'edit';
|
||||
$scope.parseType = 'yaml';
|
||||
$scope.showJobType = false;
|
||||
@@ -72,6 +75,148 @@ export default
|
||||
$scope.skip_tag_options = [];
|
||||
const virtualEnvs = ConfigData.custom_virtualenvs || [];
|
||||
$scope.custom_virtualenvs_options = virtualEnvs;
|
||||
$scope.webhook_url_help = i18n._('Webhook services can launch jobs with this job template by making a POST request to this URL.');
|
||||
$scope.webhook_key_help = i18n._('Webhook services can use this as a shared secret.');
|
||||
|
||||
$scope.currentlySavedWebhookKey = webhookKey;
|
||||
$scope.webhook_key = webhookKey;
|
||||
|
||||
//
|
||||
// webhook credential - all handlers, dynamic state, etc. live here
|
||||
//
|
||||
|
||||
$scope.webhookCredential = {
|
||||
id: _.get(jobTemplateData, ['summary_fields', 'webhook_credential', 'id']),
|
||||
name: _.get(jobTemplateData, ['summary_fields', 'webhook_credential', 'name']),
|
||||
isModalOpen: false,
|
||||
isModalReady: false,
|
||||
modalSelectedId: null,
|
||||
modalSelectedName: null,
|
||||
modalBaseParams: {
|
||||
order_by: 'name',
|
||||
page_size: 5,
|
||||
credential_type__namespace: `${jobTemplateData.webhook_service}_token`,
|
||||
},
|
||||
modalTitle: i18n._('Select Webhook Credential'),
|
||||
};
|
||||
|
||||
$scope.handleWebhookCredentialLookupClick = () => {
|
||||
$scope.webhookCredential.modalSelectedId = $scope.webhookCredential.id;
|
||||
$scope.webhookCredential.isModalOpen = true;
|
||||
};
|
||||
|
||||
$scope.handleWebhookCredentialTagDelete = () => {
|
||||
$scope.webhookCredential.id = null;
|
||||
$scope.webhookCredential.name = null;
|
||||
};
|
||||
|
||||
$scope.handleWebhookCredentialModalClose = () => {
|
||||
$scope.webhookCredential.isModalOpen = false;
|
||||
$scope.webhookCredential.isModalReady = false;
|
||||
};
|
||||
|
||||
$scope.handleWebhookCredentialModalReady = () => {
|
||||
$scope.webhookCredential.isModalReady = true;
|
||||
};
|
||||
|
||||
$scope.handleWebhookCredentialModalItemSelect = (item) => {
|
||||
$scope.webhookCredential.modalSelectedId = item.id;
|
||||
$scope.webhookCredential.modalSelectedName = item.name;
|
||||
};
|
||||
|
||||
$scope.handleWebhookCredentialModalCancel = () => {
|
||||
$scope.webhookCredential.isModalOpen = false;
|
||||
$scope.webhookCredential.isModalReady = false;
|
||||
$scope.webhookCredential.modalSelectedId = null;
|
||||
$scope.webhookCredential.modalSelectedName = null;
|
||||
};
|
||||
|
||||
$scope.handleWebhookCredentialSelect = () => {
|
||||
$scope.webhookCredential.isModalOpen = false;
|
||||
$scope.webhookCredential.isModalReady = false;
|
||||
$scope.webhookCredential.id = $scope.webhookCredential.modalSelectedId;
|
||||
$scope.webhookCredential.name = $scope.webhookCredential.modalSelectedName;
|
||||
$scope.webhookCredential.modalSelectedId = null;
|
||||
$scope.webhookCredential.modalSelectedName = null;
|
||||
};
|
||||
|
||||
$scope.handleWebhookKeyButtonClick = () => {
|
||||
Rest.setUrl(jobTemplateData.related.webhook_key);
|
||||
Wait('start');
|
||||
Rest.post({})
|
||||
.then(({ data }) => {
|
||||
$scope.currentlySavedWebhookKey = data.webhook_key;
|
||||
$scope.webhook_key = data.webhook_key;
|
||||
})
|
||||
.catch(({ data }) => {
|
||||
const errorMsg = `Failed to generate new webhook key. POST returned status: ${status}`;
|
||||
ProcessErrors($scope, data, status, form, { hdr: 'Error!', msg: errorMsg });
|
||||
})
|
||||
.finally(() => {
|
||||
Wait('stop');
|
||||
});
|
||||
};
|
||||
|
||||
$('#content-container').append($compile(`
|
||||
<at-dialog
|
||||
title="webhookCredential.modalTitle"
|
||||
on-close="handleWebhookCredentialModalClose"
|
||||
ng-if="webhookCredential.isModalOpen"
|
||||
ng-show="webhookCredential.isModalOpen && webhookCredential.isModalReady"
|
||||
>
|
||||
<at-lookup-list
|
||||
ng-show="webhookCredential.isModalOpen && webhookCredential.isModalReady"
|
||||
resource-name="credential"
|
||||
base-params="webhookCredential.modalBaseParams"
|
||||
selected-id="webhookCredential.modalSelectedId"
|
||||
on-ready="handleWebhookCredentialModalReady"
|
||||
on-item-select="handleWebhookCredentialModalItemSelect"
|
||||
/>
|
||||
<at-action-group col="12" pos="right">
|
||||
<at-action-button
|
||||
variant="tertiary"
|
||||
ng-click="handleWebhookCredentialModalCancel()"
|
||||
>
|
||||
${i18n._('CANCEL')}
|
||||
</at-action-button>
|
||||
<at-action-button
|
||||
variant="primary"
|
||||
ng-click="handleWebhookCredentialSelect()"
|
||||
>
|
||||
${i18n._('SELECT')}
|
||||
</at-action-button>
|
||||
</at-action-group>
|
||||
</at-dialog>`)($scope));
|
||||
|
||||
$scope.$watch('webhook_service', (newValue, oldValue) => {
|
||||
const newServiceValue = newValue && typeof newValue === 'object' ? newValue.value : newValue;
|
||||
const oldServiceValue = oldValue && typeof oldValue === 'object' ? oldValue.value : oldValue;
|
||||
if (newServiceValue) {
|
||||
$scope.webhook_url = `${$scope.callback_server_path}${jobTemplateData.url}${newServiceValue}/`;
|
||||
} else {
|
||||
$scope.webhook_url = '';
|
||||
$scope.webhook_key = '';
|
||||
}
|
||||
if (newServiceValue !== oldServiceValue || newServiceValue === newValue) {
|
||||
$scope.webhook_service = { value: newServiceValue };
|
||||
sync_webhook_service_select2();
|
||||
$scope.webhookCredential.modalBaseParams.credential_type__namespace = newServiceValue ?
|
||||
`${newServiceValue}_token` : null;
|
||||
if (newServiceValue !== newValue || newValue === null) {
|
||||
$scope.webhookCredential.id = null;
|
||||
$scope.webhookCredential.name = null;
|
||||
}
|
||||
if (newServiceValue !== newValue) {
|
||||
if (newServiceValue === jobTemplateData.webhook_service) {
|
||||
$scope.webhook_key = $scope.currentlySavedWebhookKey;
|
||||
} else {
|
||||
$scope.webhook_key = i18n._('A NEW WEBHOOK KEY WILL BE GENERATED ON SAVE');
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$scope.$watch('verbosity', sync_verbosity_select2);
|
||||
|
||||
SurveyControllerInit({
|
||||
scope: $scope,
|
||||
@@ -174,9 +319,6 @@ export default
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// watch for changes to 'verbosity', ensure we keep our select2 in sync when it changes.
|
||||
$scope.$watch('verbosity', sync_verbosity_select2);
|
||||
}
|
||||
|
||||
callback = function() {
|
||||
@@ -202,6 +344,17 @@ export default
|
||||
}));
|
||||
}
|
||||
|
||||
function sync_webhook_service_select2() {
|
||||
select2LoadDefer.push(CreateSelect2({
|
||||
element:'#webhook-service-select',
|
||||
addNew: false,
|
||||
multiple: false,
|
||||
scope: $scope,
|
||||
options: 'webhook_service_options',
|
||||
model: 'webhook_service'
|
||||
}));
|
||||
}
|
||||
|
||||
function jobTemplateLoadFinished(){
|
||||
select2LoadDefer.push(CreateSelect2({
|
||||
element:'#job_template_job_type',
|
||||
@@ -225,6 +378,14 @@ export default
|
||||
multiple: false,
|
||||
opts: $scope.custom_virtualenvs_options
|
||||
}));
|
||||
select2LoadDefer.push(CreateSelect2({
|
||||
element:'#webhook-service-select',
|
||||
addNew: false,
|
||||
multiple: false,
|
||||
scope: $scope,
|
||||
options: 'webhook_service_options',
|
||||
model: 'webhook_service'
|
||||
}));
|
||||
|
||||
if (!launchHasBeenEnabled) {
|
||||
$q.all(select2LoadDefer).then(() => {
|
||||
@@ -296,6 +457,15 @@ export default
|
||||
default_val: dft
|
||||
});
|
||||
|
||||
// set initial vals for webhook checkbox
|
||||
if (jobTemplateData.webhook_service) {
|
||||
$scope.enable_webhook = true;
|
||||
master.enable_webhook = true;
|
||||
} else {
|
||||
$scope.enable_webhook = false;
|
||||
master.enable_webhook = false;
|
||||
}
|
||||
|
||||
ParseTypeChange({
|
||||
scope: $scope,
|
||||
field_id: 'extra_vars',
|
||||
@@ -498,6 +668,14 @@ export default
|
||||
callback: 'choicesReady'
|
||||
});
|
||||
|
||||
GetChoices({
|
||||
scope: $scope,
|
||||
url: defaultUrl,
|
||||
field: 'webhook_service',
|
||||
variable: 'webhook_service_options',
|
||||
callback: 'choicesReady'
|
||||
});
|
||||
|
||||
$scope.labelOptions = availableLabels
|
||||
.map((i) => ({label: i.name, value: i.id}));
|
||||
|
||||
@@ -553,7 +731,6 @@ export default
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
var orgDefer = $q.defer();
|
||||
var associationDefer = $q.defer();
|
||||
var associatedLabelsDefer = $q.defer();
|
||||
@@ -729,6 +906,20 @@ export default
|
||||
data.job_tags = (Array.isArray($scope.job_tags)) ? _.uniq($scope.job_tags).join() : "";
|
||||
data.skip_tags = (Array.isArray($scope.skip_tags)) ? _.uniq($scope.skip_tags).join() : "";
|
||||
|
||||
delete data.webhook_url;
|
||||
delete data.webhook_key;
|
||||
delete data.enable_webhook;
|
||||
data.webhook_credential = $scope.webhookCredential.id;
|
||||
|
||||
if (!data.webhook_service) {
|
||||
data.webhook_credential = null;
|
||||
}
|
||||
|
||||
if (!$scope.enable_webhook) {
|
||||
data.webhook_service = '';
|
||||
data.webhook_credential = null;
|
||||
}
|
||||
|
||||
Rest.setUrl(defaultUrl + $state.params.job_template_id);
|
||||
Rest.patch(data)
|
||||
.then(({data}) => {
|
||||
|
||||
@@ -338,6 +338,16 @@ function(NotificationsList, i18n) {
|
||||
dataTitle: i18n._('Allow Provisioning Callbacks'),
|
||||
dataContainer: "body",
|
||||
ngDisabled: '!(job_template_obj.summary_fields.user_capabilities.edit || canAddJobTemplate)'
|
||||
}, {
|
||||
name: 'enable_webhook',
|
||||
label: i18n._('Enable Webhook'),
|
||||
type: 'checkbox',
|
||||
column: 2,
|
||||
awPopOver: "<p>" + i18n._("Enable webhook for this job template.") + "</p>",
|
||||
dataPlacement: 'right',
|
||||
dataTitle: i18n._('Enable Webhook'),
|
||||
dataContainer: "body",
|
||||
ngDisabled: '!(job_template_obj.summary_fields.user_capabilities.edit || canAddJobTemplate)'
|
||||
}, {
|
||||
name: 'allow_simultaneous',
|
||||
label: i18n._('Enable Concurrent Jobs'),
|
||||
@@ -391,6 +401,80 @@ function(NotificationsList, i18n) {
|
||||
alwaysShowAsterisk: true
|
||||
}
|
||||
},
|
||||
webhook_service: {
|
||||
label: i18n._('Webhook Service'),
|
||||
type:'select',
|
||||
defaultText: i18n._('Choose a Webhook Service'),
|
||||
ngOptions: 'svc.label for svc in webhook_service_options track by svc.value',
|
||||
ngShow: "enable_webhook && enable_webhook !== 'false'",
|
||||
ngDisabled: "!(job_template_obj.summary_fields.user_capabilities.edit || canAddJobTemplate) || !canGetAllRelatedResources",
|
||||
id: 'webhook-service-select',
|
||||
column: 1,
|
||||
awPopOver: "<p>" + i18n._("Select a webhook service.") + "</p>",
|
||||
dataTitle: i18n._('Webhook Service'),
|
||||
dataPlacement: 'right',
|
||||
dataContainer: "body",
|
||||
},
|
||||
webhook_url: {
|
||||
label: i18n._('Webhook URL'),
|
||||
type: 'text',
|
||||
ngShow: "job_template_obj && enable_webhook && enable_webhook !== 'false'",
|
||||
awPopOver: "webhook_url_help",
|
||||
awPopOverWatch: "webhook_url_help",
|
||||
dataPlacement: 'top',
|
||||
dataTitle: i18n._('Webhook URL'),
|
||||
dataContainer: "body",
|
||||
readonly: true
|
||||
},
|
||||
webhook_key: {
|
||||
label: i18n._('Webhook Key'),
|
||||
type: 'text',
|
||||
ngShow: "enable_webhook && enable_webhook !== 'false'",
|
||||
genHash: true,
|
||||
genHashButtonTemplate: `
|
||||
<span
|
||||
ng-if="job_template_obj && webhook_service.value && currentlySavedWebhookKey === webhook_key"
|
||||
class="input-group-btn input-group-prepend"
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
class="btn Form-lookupButton"
|
||||
ng-click="handleWebhookKeyButtonClick()"
|
||||
aw-tool-tip="${i18n._('Rotate Webhook Key')}"
|
||||
data-placement="top"
|
||||
id="job_template_webhook_key_gen_btn"
|
||||
>
|
||||
<i class="fa fa-refresh" />
|
||||
</button>
|
||||
</span>
|
||||
`,
|
||||
genHashButtonClickHandlerName: "handleWebhookKeyButtonClick",
|
||||
awPopOver: "webhook_key_help",
|
||||
awPopOverWatch: "webhook_key_help",
|
||||
dataPlacement: 'right',
|
||||
dataTitle: i18n._("Webhook Key"),
|
||||
dataContainer: "body",
|
||||
readonly: true,
|
||||
required: false,
|
||||
},
|
||||
webhook_credential: {
|
||||
label: i18n._('Webhook Credential'),
|
||||
type: 'custom',
|
||||
ngShow: "enable_webhook && enable_webhook !== 'false'",
|
||||
control: `
|
||||
<webhook-credential-input
|
||||
is-field-disabled="!(job_template_obj.summary_fields.user_capabilities.edit || canAddJobTemplate) || !(webhookCredential.modalBaseParams.credential_type__namespace)"
|
||||
tag-name="webhookCredential.name"
|
||||
on-lookup-click="handleWebhookCredentialLookupClick"
|
||||
on-tag-delete="handleWebhookCredentialTagDelete"
|
||||
</webhook-credential-input>`,
|
||||
awPopOver: "<p>" + i18n._("Optionally, select the credential to use to send status updates back to the webhook service") + "</p>",
|
||||
dataTitle: i18n._('Webhook Credential'),
|
||||
dataPlacement: 'right',
|
||||
dataContainer: "body",
|
||||
ngDisabled: '!(webhook_service || webhook_service.value)',
|
||||
required: false,
|
||||
},
|
||||
extra_vars: {
|
||||
label: i18n._('Extra Variables'),
|
||||
type: 'textarea',
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import jobTemplateAdd from './add-job-template/main';
|
||||
import jobTemplateEdit from './edit-job-template/main';
|
||||
import multiCredential from './multi-credential/main';
|
||||
import webhookCredential from './webhook-credential';
|
||||
import hashSetup from './factories/hash-setup.factory';
|
||||
import CallbackHelpInit from './factories/callback-help-init.factory';
|
||||
import JobTemplateForm from './job-template.form';
|
||||
|
||||
export default
|
||||
angular.module('jobTemplates', [jobTemplateAdd.name, jobTemplateEdit.name,
|
||||
multiCredential.name])
|
||||
.factory('hashSetup', hashSetup)
|
||||
.factory('CallbackHelpInit', CallbackHelpInit)
|
||||
.factory('JobTemplateForm', JobTemplateForm);
|
||||
angular.module('jobTemplates', [jobTemplateAdd.name, jobTemplateEdit.name, multiCredential.name, webhookCredential.name])
|
||||
.factory('hashSetup', hashSetup)
|
||||
.factory('CallbackHelpInit', CallbackHelpInit)
|
||||
.factory('JobTemplateForm', JobTemplateForm);
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
import webhookCredentialInput from './webhook-credential-input.component';
|
||||
|
||||
export default angular.module('webhookCredential', [])
|
||||
.component('webhookCredentialInput', webhookCredentialInput);
|
||||
@@ -0,0 +1,9 @@
|
||||
import webhookCredential from './webhook-credential.directive';
|
||||
import webhookCredentialModal from './webhook-credential-modal.directive';
|
||||
import webhookCredentialService from './webhook-credential.service';
|
||||
|
||||
export default
|
||||
angular.module('webhookCredential', [])
|
||||
.directive('webhookCredential', webhookCredential)
|
||||
.directive('webhookCredentialModal', webhookCredentialModal)
|
||||
.service('WebhookCredentialService', webhookCredentialService);
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
const templateUrl = require('~src/templates/job_templates/webhook-credential/webhook-credential-input.partial.html');
|
||||
export default {
|
||||
templateUrl,
|
||||
controllerAs: 'vm',
|
||||
bindings: {
|
||||
isFieldDisabled: '<',
|
||||
tagName: '<',
|
||||
onLookupClick: '<',
|
||||
onTagDelete: '<',
|
||||
},
|
||||
};
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
<div class="input-group Form-mixedInputGroup">
|
||||
<span class="input-group-btn Form-variableHeightButtonGroup input-group-prepend">
|
||||
<button type="button"
|
||||
class="Form-lookupButton
|
||||
Form-lookupButton--variableHeight btn btn-default"
|
||||
ng-click="vm.onLookupClick()"
|
||||
ng-disabled="vm.isFieldDisabled">
|
||||
<i class="fa fa-search"></i>
|
||||
</button>
|
||||
</span>
|
||||
<span class="form-control Form-textInput Form-textInput--variableHeight input-medium lookup"
|
||||
ng-disabled="vm.isFieldDisabled"
|
||||
style="padding: 4px 6px;">
|
||||
<div class="WebhookCredential-tags" ng-show="vm.tagName">
|
||||
<div class="WebhookCredential-tagSection">
|
||||
<div class="WebhookCredential-flexContainer">
|
||||
<div class="WebhookCredential-tagContainer ng-scope"
|
||||
ng-class="{'WebhookCredential-tagContainer--disabled': vm.tag.readOnly}">
|
||||
<div class="WebhookCredential-iconContainer--disabled" ng-if="vm.isFieldDisabled">
|
||||
<i class="fa fa-key WebhookCredential-tagIcon"></i>
|
||||
</div>
|
||||
<div class="WebhookCredential-iconContainer" ng-if="!vm.isFieldDisabled">
|
||||
<i class="fa fa-key WebhookCredential-tagIcon"></i>
|
||||
</div>
|
||||
<div
|
||||
class="WebhookCredential-tag"
|
||||
ng-class="{'WebhookCredential-tag--deletable': !vm.isFieldDisabled, 'WebhookCredential-tag--disabled': vm.isFieldDisabled}"
|
||||
>
|
||||
<span class="WebhookCredential-name--label ng-binding">
|
||||
{{ vm.tagName }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="WebhookCredential-deleteContainer"
|
||||
ng-click="vm.onTagDelete()"
|
||||
ng-hide="vm.isFieldDisabled">
|
||||
<i class="fa fa-times WebhookCredential-tagDelete"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
.WebhookCredential-tags {
|
||||
padding-left: 0px;
|
||||
}
|
||||
|
||||
.WebhookCredential-flexContainer {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.WebhookCredential-tagContainer {
|
||||
display: flex;
|
||||
max-width: 100%;
|
||||
background-color: @default-link;
|
||||
color: @default-bg;
|
||||
border-radius: 5px;
|
||||
padding: 0px 0px 0px 10px;
|
||||
margin: 3px 10px 3px 0px;
|
||||
}
|
||||
|
||||
.WebhookCredential-tagContainer--disabled {
|
||||
background-color: @default-icon;
|
||||
}
|
||||
|
||||
.WebhookCredential-tag {
|
||||
font-size: 12px;
|
||||
margin-right: 10px;
|
||||
max-width: 100%;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
padding: 2px 0px 2px 15px;
|
||||
}
|
||||
|
||||
.WebhookCredential-tag--disabled {
|
||||
border-top-left-radius: 0px;
|
||||
border-bottom-left-radius: 0px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.WebhookCredential-tag--deletable {
|
||||
margin-right: 0px;
|
||||
border-top-right-radius: 0px;
|
||||
border-bottom-right-radius: 0px;
|
||||
border-right: 0;
|
||||
max-width: ~"calc(100% - 23px)";
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.WebhookCredential-deleteContainer {
|
||||
border-top-right-radius: 5px;
|
||||
border-bottom-right-radius: 5px;
|
||||
padding: 2px 5px;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.WebhookCredential-tagDelete {
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.WebhookCredential-iconContainer {
|
||||
border-top-left-radius: 0px;
|
||||
border-bottom-left-radius: 0px;
|
||||
padding: 0px 5px;
|
||||
margin: 3px 0px;
|
||||
margin-left: -3px;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.WebhookCredential-iconContainer--disabled {
|
||||
border-top-left-radius: 5px;
|
||||
border-bottom-left-radius: 5px;
|
||||
padding: 0 5px;
|
||||
padding-left: 10px;
|
||||
margin: 3px 0px;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
|
||||
.WebhookCredential-tagIcon {
|
||||
margin: 0px 0px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.WebhookCredential-name {
|
||||
flex: initial;
|
||||
font-size: 12px;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.WebhookCredential-name--label {
|
||||
color: @default-list-header-bg;
|
||||
font-size: 12px;
|
||||
margin-left: -8px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.WebhookCredential-tag--deletable > .WebhookCredential-name {
|
||||
max-width: ~"calc(100% - 23px)";
|
||||
}
|
||||
|
||||
.WebhookCredential-deleteContainer:hover {
|
||||
border-color: @default-err;
|
||||
background-color: @default-err!important;
|
||||
}
|
||||
|
||||
.WebhookCredential-deleteContainer:hover > .WebhookCredential-tagDelete {
|
||||
color: @default-bg;
|
||||
}
|
||||
@@ -296,7 +296,24 @@ angular.module('templates', [surveyMaker.name, jobTemplates.name, labels.name, p
|
||||
msg: i18n._('Failed to get organizations for which this user is a notification administrator. GET returned ') + status
|
||||
});
|
||||
});
|
||||
}]
|
||||
}],
|
||||
webhookKey: ['Rest', 'ProcessErrors', 'jobTemplateData', 'i18n',
|
||||
function(Rest, ProcessErrors, jobTemplateData, i18n) {
|
||||
Rest.setUrl(jobTemplateData.related.webhook_key);
|
||||
return Rest.get()
|
||||
.then(({ data = {} }) => {
|
||||
return data.webhook_key || '';
|
||||
})
|
||||
.catch(({data, status}) => {
|
||||
if (status === 403) {
|
||||
return;
|
||||
}
|
||||
ProcessErrors(null, data, status, null, {
|
||||
hdr: i18n._('Error!'),
|
||||
msg: i18n._('Failed to get webhook key GET returned ') + status
|
||||
});
|
||||
});
|
||||
}],
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -457,7 +474,24 @@ angular.module('templates', [surveyMaker.name, jobTemplates.name, labels.name, p
|
||||
msg: i18n._('Failed to get organizations for which this user is a notification administrator. GET returned ') + status
|
||||
});
|
||||
});
|
||||
}]
|
||||
}],
|
||||
webhookKey: ['Rest', 'ProcessErrors', 'workflowJobTemplateData', 'i18n',
|
||||
function(Rest, ProcessErrors, workflowJobTemplateData, i18n) {
|
||||
Rest.setUrl(workflowJobTemplateData.related.webhook_key);
|
||||
return Rest.get()
|
||||
.then(({ data = {} }) => {
|
||||
return data.webhook_key || '';
|
||||
})
|
||||
.catch(({data, status}) => {
|
||||
if (status === 403) {
|
||||
return;
|
||||
}
|
||||
ProcessErrors(null, data, status, null, {
|
||||
hdr: i18n._('Error!'),
|
||||
msg: i18n._('Failed to get webhook key GET returned ') + status
|
||||
});
|
||||
});
|
||||
}],
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -162,8 +162,92 @@ export default ['NotificationsList', 'i18n', function(NotificationsList, i18n) {
|
||||
dataTitle: i18n._('Enable Concurrent Jobs'),
|
||||
dataContainer: "body",
|
||||
ngDisabled: '!(workflow_job_template_obj.summary_fields.user_capabilities.edit || canAddOrEdit)'
|
||||
}, {
|
||||
name: 'enable_webhook',
|
||||
label: i18n._('Enable Webhook'),
|
||||
type: 'checkbox',
|
||||
column: 2,
|
||||
awPopOver: "<p>" + i18n._("Enable webhook for this workflow job template.") + "</p>",
|
||||
dataPlacement: 'right',
|
||||
dataTitle: i18n._('Enable Webhook'),
|
||||
dataContainer: "body",
|
||||
ngDisabled: '!(workflow_job_template_obj.summary_fields.user_capabilities.edit || canAddOrEdit)'
|
||||
}]
|
||||
}
|
||||
},
|
||||
webhook_service: {
|
||||
label: i18n._('Webhook Service'),
|
||||
type:'select',
|
||||
defaultText: i18n._('Choose a Webhook Service'),
|
||||
ngOptions: 'svc.label for svc in webhook_service_options track by svc.value',
|
||||
ngShow: "enable_webhook && enable_webhook !== 'false'",
|
||||
ngDisabled: "!(workflow_job_template_obj.summary_fields.user_capabilities.edit || canAddOrEdit)",
|
||||
id: 'webhook-service-select',
|
||||
column: 1,
|
||||
awPopOver: "<p>" + i18n._("Select a webhook service.") + "</p>",
|
||||
dataTitle: i18n._('Webhook Service'),
|
||||
dataPlacement: 'right',
|
||||
dataContainer: "body",
|
||||
},
|
||||
webhook_url: {
|
||||
label: i18n._('Webhook URL'),
|
||||
type: 'text',
|
||||
ngShow: "workflow_job_template_obj && enable_webhook && enable_webhook !== 'false'",
|
||||
awPopOver: "webhook_url_help",
|
||||
awPopOverWatch: "webhook_url_help",
|
||||
dataPlacement: 'top',
|
||||
dataTitle: i18n._('Webhook URL'),
|
||||
dataContainer: "body",
|
||||
readonly: true
|
||||
},
|
||||
webhook_key: {
|
||||
label: i18n._('Webhook Key'),
|
||||
type: 'text',
|
||||
ngShow: "enable_webhook && enable_webhook !== 'false'",
|
||||
genHash: true,
|
||||
genHashButtonTemplate: `
|
||||
<span
|
||||
ng-if="workflow_job_template_obj && webhook_service.value && currentlySavedWebhookKey === webhook_key"
|
||||
class="input-group-btn input-group-prepend"
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
class="btn Form-lookupButton"
|
||||
ng-click="handleWebhookKeyButtonClick()"
|
||||
aw-tool-tip="${i18n._('Rotate Webhook Key')}"
|
||||
data-placement="top"
|
||||
id="workflow_job_template_webhook_key_gen_btn"
|
||||
>
|
||||
<i class="fa fa-refresh" />
|
||||
</button>
|
||||
</span>
|
||||
`,
|
||||
genHashButtonClickHandlerName: "handleWebhookKeyButtonClick",
|
||||
awPopOver: "webhook_key_help",
|
||||
awPopOverWatch: "webhook_key_help",
|
||||
dataPlacement: 'right',
|
||||
dataTitle: i18n._("Webhook Key"),
|
||||
dataContainer: "body",
|
||||
readonly: true,
|
||||
required: false,
|
||||
},
|
||||
webhook_credential: {
|
||||
label: i18n._('Webhook Credential'),
|
||||
type: 'custom',
|
||||
ngShow: "enable_webhook && enable_webhook !== 'false'",
|
||||
control: `
|
||||
<webhook-credential-input
|
||||
is-field-disabled="!(workflow_job_template_obj.summary_fields.user_capabilities.edit || canAddOrEdit) || !(webhookCredential.modalBaseParams.credential_type__namespace)"
|
||||
tag-name="webhookCredential.name"
|
||||
on-lookup-click="handleWebhookCredentialLookupClick"
|
||||
on-tag-delete="handleWebhookCredentialTagDelete"
|
||||
</webhook-credential-input>`,
|
||||
awPopOver: "<p>" + i18n._("Select the credential to use with the webhook service.") + "</p>",
|
||||
dataTitle: i18n._('Webhook Credential'),
|
||||
dataPlacement: 'right',
|
||||
dataContainer: "body",
|
||||
ngDisabled: '!webhook_service.value',
|
||||
required: false,
|
||||
},
|
||||
},
|
||||
|
||||
buttons: { //for now always generates <button> tags
|
||||
|
||||
@@ -8,11 +8,11 @@ export default [
|
||||
'$scope', 'WorkflowForm', 'GenerateForm', 'Alert', 'ProcessErrors',
|
||||
'Wait', '$state', 'CreateSelect2', 'TemplatesService',
|
||||
'ToJSON', 'ParseTypeChange', '$q', 'Rest', 'GetBasePath', 'availableLabels', 'i18n',
|
||||
'resolvedModels',
|
||||
'resolvedModels', 'GetChoices', '$compile',
|
||||
function($scope, WorkflowForm, GenerateForm, Alert, ProcessErrors,
|
||||
Wait, $state, CreateSelect2, TemplatesService, ToJSON,
|
||||
ParseTypeChange, $q, Rest, GetBasePath, availableLabels, i18n,
|
||||
resolvedModels) {
|
||||
resolvedModels, GetChoices, $compile) {
|
||||
|
||||
// Inject dynamic view
|
||||
let form = WorkflowForm(),
|
||||
@@ -52,6 +52,138 @@ export default [
|
||||
$scope.workflowEditorTooltip = i18n._("Please save before defining the workflow graph.");
|
||||
$scope.surveyTooltip = i18n._('Please save before adding a survey to this workflow.');
|
||||
|
||||
$scope.webhook_service_options = null;
|
||||
|
||||
// populate webhook service choices
|
||||
GetChoices({
|
||||
scope: $scope,
|
||||
url: GetBasePath('workflow_job_templates'),
|
||||
field: 'webhook_service',
|
||||
variable: 'webhook_service_options',
|
||||
});
|
||||
|
||||
// set initial val for webhook checkbox
|
||||
$scope.enable_webhook = false;
|
||||
|
||||
//
|
||||
// webhook credential - all handlers, dynamic state, etc. live here
|
||||
//
|
||||
|
||||
$scope.webhookCredential = {
|
||||
id: null,
|
||||
name: null,
|
||||
isModalOpen: false,
|
||||
isModalReady: false,
|
||||
modalSelectedId: null,
|
||||
modalSelectedName: null,
|
||||
modalBaseParams: {
|
||||
order_by: 'name',
|
||||
page_size: 5,
|
||||
credential_type__namespace: null,
|
||||
},
|
||||
modalTitle: i18n._('Select Webhook Credential'),
|
||||
};
|
||||
|
||||
$scope.handleWebhookCredentialLookupClick = () => {
|
||||
$scope.webhookCredential.modalSelectedId = $scope.webhookCredential.id;
|
||||
$scope.webhookCredential.isModalOpen = true;
|
||||
};
|
||||
|
||||
$scope.handleWebhookCredentialTagDelete = () => {
|
||||
$scope.webhookCredential.id = null;
|
||||
$scope.webhookCredential.name = null;
|
||||
};
|
||||
|
||||
$scope.handleWebhookCredentialModalClose = () => {
|
||||
$scope.webhookCredential.isModalOpen = false;
|
||||
$scope.webhookCredential.isModalReady = false;
|
||||
};
|
||||
|
||||
$scope.handleWebhookCredentialModalReady = () => {
|
||||
$scope.webhookCredential.isModalReady = true;
|
||||
};
|
||||
|
||||
$scope.handleWebhookCredentialModalItemSelect = (item) => {
|
||||
$scope.webhookCredential.modalSelectedId = item.id;
|
||||
$scope.webhookCredential.modalSelectedName = item.name;
|
||||
};
|
||||
|
||||
$scope.handleWebhookCredentialModalCancel = () => {
|
||||
$scope.webhookCredential.isModalOpen = false;
|
||||
$scope.webhookCredential.isModalReady = false;
|
||||
$scope.webhookCredential.modalSelectedId = null;
|
||||
$scope.webhookCredential.modalSelectedName = null;
|
||||
};
|
||||
|
||||
$scope.handleWebhookCredentialSelect = () => {
|
||||
$scope.webhookCredential.isModalOpen = false;
|
||||
$scope.webhookCredential.isModalReady = false;
|
||||
$scope.webhookCredential.id = $scope.webhookCredential.modalSelectedId;
|
||||
$scope.webhookCredential.name = $scope.webhookCredential.modalSelectedName;
|
||||
$scope.webhookCredential.modalSelectedId = null;
|
||||
$scope.webhookCredential.modalSelectedName = null;
|
||||
};
|
||||
|
||||
$scope.handleWebhookKeyButtonClick = () => {};
|
||||
|
||||
$('#content-container').append($compile(`
|
||||
<at-dialog
|
||||
title="webhookCredential.modalTitle"
|
||||
on-close="handleWebhookCredentialModalClose"
|
||||
ng-if="webhookCredential.isModalOpen"
|
||||
ng-show="webhookCredential.isModalOpen && webhookCredential.isModalReady"
|
||||
>
|
||||
<at-lookup-list
|
||||
ng-show="webhookCredential.isModalOpen && webhookCredential.isModalReady"
|
||||
resource-name="credential"
|
||||
base-params="webhookCredential.modalBaseParams"
|
||||
selected-id="webhookCredential.modalSelectedId"
|
||||
on-ready="handleWebhookCredentialModalReady"
|
||||
on-item-select="handleWebhookCredentialModalItemSelect"
|
||||
/>
|
||||
<at-action-group col="12" pos="right">
|
||||
<at-action-button
|
||||
variant="tertiary"
|
||||
ng-click="handleWebhookCredentialModalCancel()"
|
||||
>
|
||||
${i18n._('CANCEL')}
|
||||
</at-action-button>
|
||||
<at-action-button
|
||||
variant="primary"
|
||||
ng-click="handleWebhookCredentialSelect()"
|
||||
>
|
||||
${i18n._('SELECT')}
|
||||
</at-action-button>
|
||||
</at-action-group>
|
||||
</at-dialog>`)($scope));
|
||||
|
||||
$scope.$watch('webhook_service', (newValue, oldValue) => {
|
||||
const newServiceValue = newValue && typeof newValue === 'object' ? newValue.value : newValue;
|
||||
const oldServiceValue = oldValue && typeof oldValue === 'object' ? oldValue.value : oldValue;
|
||||
if (newServiceValue !== oldServiceValue || newServiceValue === newValue) {
|
||||
$scope.webhook_service = { value: newServiceValue };
|
||||
sync_webhook_service_select2();
|
||||
$scope.webhookCredential.modalBaseParams.credential_type__namespace = newServiceValue ?
|
||||
`${newServiceValue}_token`
|
||||
: null;
|
||||
if (newServiceValue !== newValue || newValue === null) {
|
||||
$scope.webhookCredential.id = null;
|
||||
$scope.webhookCredential.name = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function sync_webhook_service_select2() {
|
||||
CreateSelect2({
|
||||
element:'#webhook-service-select',
|
||||
addNew: false,
|
||||
multiple: false,
|
||||
scope: $scope,
|
||||
options: 'webhook_service_options',
|
||||
model: 'webhook_service'
|
||||
});
|
||||
}
|
||||
|
||||
$scope.formSave = function () {
|
||||
let fld, data = {};
|
||||
|
||||
@@ -98,6 +230,25 @@ export default [
|
||||
.filter("[data-label-is-present=true]")
|
||||
.map((i, val) => ({name: $(val).text()}));
|
||||
|
||||
|
||||
delete data.webhook_url;
|
||||
delete data.webhook_key;
|
||||
delete data.enable_webhook;
|
||||
data.webhook_credential = $scope.webhookCredential.id;
|
||||
|
||||
if (!data.webhook_service) {
|
||||
data.webhook_credential = null;
|
||||
}
|
||||
|
||||
if (!$scope.enable_webhook) {
|
||||
data.webhook_service = '';
|
||||
data.webhook_credential = null;
|
||||
}
|
||||
|
||||
if (data.webhook_service && typeof data.webhook_service === 'object') {
|
||||
data.webhook_service = data.webhook_service.value;
|
||||
}
|
||||
|
||||
TemplatesService.createWorkflowJobTemplate(data)
|
||||
.then(function(data) {
|
||||
|
||||
|
||||
@@ -10,12 +10,12 @@ export default [
|
||||
'Wait', 'Empty', 'ToJSON', 'initSurvey', '$state', 'CreateSelect2',
|
||||
'ParseVariableString', 'TemplatesService', 'Rest', 'ToggleNotification',
|
||||
'OrgAdminLookup', 'availableLabels', 'selectedLabels', 'workflowJobTemplateData', 'i18n',
|
||||
'workflowLaunch', '$transitions', 'WorkflowJobTemplateModel', 'Inventory', 'isNotificationAdmin',
|
||||
'workflowLaunch', '$transitions', 'WorkflowJobTemplateModel', 'Inventory', 'isNotificationAdmin', 'webhookKey', '$compile', '$location', 'GetChoices',
|
||||
function($scope, $stateParams, WorkflowForm, GenerateForm, Alert,
|
||||
ProcessErrors, GetBasePath, $q, ParseTypeChange, Wait, Empty,
|
||||
ToJSON, SurveyControllerInit, $state, CreateSelect2, ParseVariableString,
|
||||
TemplatesService, Rest, ToggleNotification, OrgAdminLookup, availableLabels, selectedLabels, workflowJobTemplateData, i18n,
|
||||
workflowLaunch, $transitions, WorkflowJobTemplate, Inventory, isNotificationAdmin
|
||||
workflowLaunch, $transitions, WorkflowJobTemplate, Inventory, isNotificationAdmin, webhookKey, $compile, $location, GetChoices
|
||||
) {
|
||||
|
||||
// To toggle notifications a user needs to have a read role on the WFJT
|
||||
@@ -63,6 +63,179 @@ export default [
|
||||
$scope.inventory_name = Inventory.name;
|
||||
}
|
||||
|
||||
$scope.webhook_service_options = null;
|
||||
$scope.webhook_service = workflowJobTemplateData.webhook_service;
|
||||
$scope.webhook_url = '';
|
||||
$scope.webhook_url_help = i18n._('Webhook services can launch jobs with this job template by making a POST request to this URL.');
|
||||
$scope.webhook_key_help = i18n._('Webhook services can use this as a shared secret.');
|
||||
$scope.currentlySavedWebhookKey = webhookKey;
|
||||
$scope.webhook_key = webhookKey;
|
||||
|
||||
// populate webhook service choices
|
||||
GetChoices({
|
||||
scope: $scope,
|
||||
url: GetBasePath('workflow_job_templates'),
|
||||
field: 'webhook_service',
|
||||
variable: 'webhook_service_options',
|
||||
});
|
||||
|
||||
// set initial val for webhook checkbox
|
||||
if (workflowJobTemplateData.webhook_service) {
|
||||
$scope.enable_webhook = true;
|
||||
} else {
|
||||
$scope.enable_webhook = false;
|
||||
}
|
||||
|
||||
// set domain / base url
|
||||
$scope.baseURL = $location.protocol() + '://' + $location.host() + (($location.port()) ? ':' + $location.port() : '');
|
||||
|
||||
//
|
||||
// webhook credential - all handlers, dynamic state, etc. live here
|
||||
//
|
||||
|
||||
$scope.webhookCredential = {
|
||||
id: _.get(workflowJobTemplateData, ['summary_fields', 'webhook_credential', 'id']),
|
||||
name: _.get(workflowJobTemplateData, ['summary_fields', 'webhook_credential', 'name']),
|
||||
isModalOpen: false,
|
||||
isModalReady: false,
|
||||
modalSelectedId: null,
|
||||
modalSelectedName: null,
|
||||
modalBaseParams: {
|
||||
order_by: 'name',
|
||||
page_size: 5,
|
||||
credential_type__namespace: `${workflowJobTemplateData.webhook_service}_token`,
|
||||
},
|
||||
modalTitle: i18n._('Select Webhook Credential'),
|
||||
};
|
||||
|
||||
$scope.handleWebhookCredentialLookupClick = () => {
|
||||
$scope.webhookCredential.modalSelectedId = $scope.webhookCredential.id;
|
||||
$scope.webhookCredential.isModalOpen = true;
|
||||
};
|
||||
|
||||
$scope.handleWebhookCredentialTagDelete = () => {
|
||||
$scope.webhookCredential.id = null;
|
||||
$scope.webhookCredential.name = null;
|
||||
};
|
||||
|
||||
$scope.handleWebhookCredentialModalClose = () => {
|
||||
$scope.webhookCredential.isModalOpen = false;
|
||||
$scope.webhookCredential.isModalReady = false;
|
||||
};
|
||||
|
||||
$scope.handleWebhookCredentialModalReady = () => {
|
||||
$scope.webhookCredential.isModalReady = true;
|
||||
};
|
||||
|
||||
$scope.handleWebhookCredentialModalItemSelect = (item) => {
|
||||
$scope.webhookCredential.modalSelectedId = item.id;
|
||||
$scope.webhookCredential.modalSelectedName = item.name;
|
||||
};
|
||||
|
||||
$scope.handleWebhookCredentialModalCancel = () => {
|
||||
$scope.webhookCredential.isModalOpen = false;
|
||||
$scope.webhookCredential.isModalReady = false;
|
||||
$scope.webhookCredential.modalSelectedId = null;
|
||||
$scope.webhookCredential.modalSelectedName = null;
|
||||
};
|
||||
|
||||
$scope.handleWebhookCredentialSelect = () => {
|
||||
$scope.webhookCredential.isModalOpen = false;
|
||||
$scope.webhookCredential.isModalReady = false;
|
||||
$scope.webhookCredential.id = $scope.webhookCredential.modalSelectedId;
|
||||
$scope.webhookCredential.name = $scope.webhookCredential.modalSelectedName;
|
||||
$scope.webhookCredential.modalSelectedId = null;
|
||||
$scope.webhookCredential.modalSelectedName = null;
|
||||
};
|
||||
|
||||
$scope.handleWebhookKeyButtonClick = () => {
|
||||
Rest.setUrl(workflowJobTemplateData.related.webhook_key);
|
||||
Wait('start');
|
||||
Rest.post({})
|
||||
.then(({ data }) => {
|
||||
$scope.currentlySavedWebhookKey = data.webhook_key;
|
||||
$scope.webhook_key = data.webhook_key;
|
||||
})
|
||||
.catch(({ data }) => {
|
||||
const errorMsg = `Failed to generate new webhook key. POST returned status: ${status}`;
|
||||
ProcessErrors($scope, data, status, form, { hdr: 'Error!', msg: errorMsg });
|
||||
})
|
||||
.finally(() => {
|
||||
Wait('stop');
|
||||
});
|
||||
};
|
||||
|
||||
$('#content-container').append($compile(`
|
||||
<at-dialog
|
||||
title="webhookCredential.modalTitle"
|
||||
on-close="handleWebhookCredentialModalClose"
|
||||
ng-if="webhookCredential.isModalOpen"
|
||||
ng-show="webhookCredential.isModalOpen && webhookCredential.isModalReady"
|
||||
>
|
||||
<at-lookup-list
|
||||
ng-show="webhookCredential.isModalOpen && webhookCredential.isModalReady"
|
||||
resource-name="credential"
|
||||
base-params="webhookCredential.modalBaseParams"
|
||||
selected-id="webhookCredential.modalSelectedId"
|
||||
on-ready="handleWebhookCredentialModalReady"
|
||||
on-item-select="handleWebhookCredentialModalItemSelect"
|
||||
/>
|
||||
<at-action-group col="12" pos="right">
|
||||
<at-action-button
|
||||
variant="tertiary"
|
||||
ng-click="handleWebhookCredentialModalCancel()"
|
||||
>
|
||||
${i18n._('CANCEL')}
|
||||
</at-action-button>
|
||||
<at-action-button
|
||||
variant="primary"
|
||||
ng-click="handleWebhookCredentialSelect()"
|
||||
>
|
||||
${i18n._('SELECT')}
|
||||
</at-action-button>
|
||||
</at-action-group>
|
||||
</at-dialog>`)($scope));
|
||||
|
||||
$scope.$watch('webhook_service', (newValue, oldValue) => {
|
||||
const newServiceValue = newValue && typeof newValue === 'object' ? newValue.value : newValue;
|
||||
const oldServiceValue = oldValue && typeof oldValue === 'object' ? oldValue.value : oldValue;
|
||||
if (newServiceValue) {
|
||||
$scope.webhook_url = `${$scope.baseURL}${workflowJobTemplateData.url}${newServiceValue}/`;
|
||||
$scope.enable_webhook = true;
|
||||
} else {
|
||||
$scope.webhook_url = '';
|
||||
$scope.webhook_key = '';
|
||||
}
|
||||
if (newServiceValue !== oldServiceValue || newServiceValue === newValue) {
|
||||
$scope.webhook_service = { value: newServiceValue };
|
||||
sync_webhook_service_select2();
|
||||
$scope.webhookCredential.modalBaseParams.credential_type__namespace = newServiceValue ?
|
||||
`${newServiceValue}_token` : null;
|
||||
if (newServiceValue !== newValue || newValue === null) {
|
||||
$scope.webhookCredential.id = null;
|
||||
$scope.webhookCredential.name = null;
|
||||
}
|
||||
if (newServiceValue !== newValue) {
|
||||
if (newServiceValue === workflowJobTemplateData.webhook_service) {
|
||||
$scope.webhook_key = $scope.currentlySavedWebhookKey;
|
||||
} else {
|
||||
$scope.webhook_key = i18n._('A NEW WEBHOOK KEY WILL BE GENERATED ON SAVE');
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function sync_webhook_service_select2() {
|
||||
CreateSelect2({
|
||||
element:'#webhook-service-select',
|
||||
addNew: false,
|
||||
multiple: false,
|
||||
scope: $scope,
|
||||
options: 'webhook_service_options',
|
||||
model: 'webhook_service'
|
||||
});
|
||||
}
|
||||
|
||||
$scope.openWorkflowMaker = function() {
|
||||
$state.go('templates.editWorkflowJobTemplate.workflowMaker');
|
||||
};
|
||||
@@ -124,6 +297,25 @@ export default [
|
||||
.filter("[data-label-is-present=true]")
|
||||
.map((i, val) => ({name: $(val).text()}));
|
||||
|
||||
|
||||
delete data.webhook_url;
|
||||
delete data.webhook_key;
|
||||
delete data.enable_webhook;
|
||||
data.webhook_credential = $scope.webhookCredential.id;
|
||||
|
||||
if (!data.webhook_service) {
|
||||
data.webhook_credential = null;
|
||||
}
|
||||
|
||||
if (!$scope.enable_webhook) {
|
||||
data.webhook_service = '';
|
||||
data.webhook_credential = null;
|
||||
}
|
||||
|
||||
if (data.webhook_service && typeof data.webhook_service === 'object') {
|
||||
data.webhook_service = data.webhook_service.value;
|
||||
}
|
||||
|
||||
TemplatesService.updateWorkflowJobTemplate({
|
||||
id: id,
|
||||
data: data
|
||||
|
||||
@@ -37,6 +37,11 @@ export default ['workflowData', 'workflowResultsService', 'workflowDataOptions',
|
||||
$scope.cloud_credential_link = getLink('cloud_credential');
|
||||
$scope.network_credential_link = getLink('network_credential');
|
||||
|
||||
$scope.launched_by_webhook_link = null;
|
||||
if ($scope.workflow.launch_type === 'webhook') {
|
||||
$scope.launched_by_webhook_link = $scope.workflow_template_link;
|
||||
}
|
||||
|
||||
if ($scope.workflow.summary_fields.inventory) {
|
||||
if ($scope.workflow.summary_fields.inventory.kind === 'smart') {
|
||||
$scope.inventory_link = '/#/inventories/smart/' + $scope.workflow.inventory;
|
||||
@@ -57,6 +62,7 @@ export default ['workflowData', 'workflowResultsService', 'workflowDataOptions',
|
||||
EDIT_INVENTORY: i18n._('Edit the inventory'),
|
||||
SOURCE_WORKFLOW_JOB: i18n._('View the source Workflow Job'),
|
||||
TOGGLE_STDOUT_FULLSCREEN: i18n._('Expand Output'),
|
||||
WEBHOOK_WORKFLOW_JOB_TEMPLATE: i18n._('View the webhook configuration on the workflow job template.'),
|
||||
STATUS: '' // re-assigned elsewhere
|
||||
},
|
||||
labels: {
|
||||
@@ -79,6 +85,7 @@ export default ['workflowData', 'workflowResultsService', 'workflowDataOptions',
|
||||
NOT_STARTED: i18n._('Not Started'),
|
||||
SHOW_LESS: i18n._('Show Less'),
|
||||
SHOW_MORE: i18n._('Show More'),
|
||||
WEBHOOK: i18n._('Webhook'),
|
||||
},
|
||||
results: {
|
||||
TOTAL_NODES: i18n._('Total Nodes'),
|
||||
|
||||
@@ -177,7 +177,7 @@
|
||||
|
||||
<!-- CREATED BY DETAIL -->
|
||||
<div class="WorkflowResults-resultRow"
|
||||
ng-show="workflow.summary_fields.created_by.username">
|
||||
ng-show="workflow.summary_fields.created_by.username && !launched_by_webhook_link">
|
||||
<label class="WorkflowResults-resultRowLabel">
|
||||
{{ strings.labels.LAUNCHED_BY }}
|
||||
</label>
|
||||
@@ -192,7 +192,7 @@
|
||||
|
||||
<!-- SCHEDULED BY DETAIL -->
|
||||
<div class="WorkflowResults-resultRow toggle-show"
|
||||
ng-show="workflow.summary_fields.schedule.name">
|
||||
ng-show="workflow.summary_fields.schedule.name && !launched_by_webhook_link">
|
||||
<label
|
||||
class="WorkflowResults-resultRowLabel">
|
||||
{{ strings.labels.LAUNCHED_BY }}
|
||||
@@ -206,6 +206,23 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- LAUNCHED BY WEBHOOK DETAIL -->
|
||||
<div class="WorkflowResults-resultRow toggle-show"
|
||||
ng-show="launched_by_webhook_link">
|
||||
<label
|
||||
class="WorkflowResults-resultRowLabel">
|
||||
{{ strings.labels.LAUNCHED_BY }}
|
||||
</label>
|
||||
<div class="WorkflowResults-resultRowText">
|
||||
<a href="{{ launched_by_webhook_link }}"
|
||||
aw-tool-tip="{{ strings.tooltips.WEBHOOK_WORKFLOW_JOB_TEMPLATE }}"
|
||||
data-placement="top">
|
||||
{{ strings.details.WEBHOOK }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- SLIIIIIICE -->
|
||||
<div class="WorkflowResults-resultRow"
|
||||
ng-show="workflow.summary_fields.job_template.name">
|
||||
|
||||
@@ -97,6 +97,10 @@ describe('Controller: WorkflowAdd', () => {
|
||||
.whenGET(/^\/api\/?$/)
|
||||
.respond(200, '');
|
||||
|
||||
$httpBackend
|
||||
.when('OPTIONS', '/')
|
||||
.respond(200, '');
|
||||
|
||||
$httpBackend
|
||||
.whenGET(/\/static\/*/)
|
||||
.respond(200, {});
|
||||
@@ -149,6 +153,8 @@ describe('Controller: WorkflowAdd', () => {
|
||||
labels: undefined,
|
||||
variables: undefined,
|
||||
allow_simultaneous: undefined,
|
||||
webhook_service: '',
|
||||
webhook_credential: null,
|
||||
ask_inventory_on_launch: false,
|
||||
ask_variables_on_launch: false,
|
||||
ask_limit_on_launch: false,
|
||||
|
||||
@@ -6,6 +6,6 @@ import './file.unit';
|
||||
import './layout.unit';
|
||||
import './side-nav.unit';
|
||||
import './side-nav-item.unit';
|
||||
import './jobs-list-split-jobs.unit';
|
||||
import './jobs-list.unit';
|
||||
import './job-details-split-jobs.unit';
|
||||
import './stream.unit';
|
||||
|
||||
+28
-14
@@ -36,6 +36,9 @@ describe('View: Split Jobs List', () => {
|
||||
if (str === 'list.SLICE_JOB') {
|
||||
return 'Slice Job';
|
||||
}
|
||||
if (str === 'list.ROW_ITEM_LABEL_WEBHOOK') {
|
||||
return 'Webhook';
|
||||
}
|
||||
return '';
|
||||
}
|
||||
};
|
||||
@@ -96,40 +99,51 @@ describe('View: Split Jobs List', () => {
|
||||
it('is created successfully', () => {
|
||||
expect(JobList).toBeDefined();
|
||||
});
|
||||
it('has method "getSplitJobDetails"', () => {
|
||||
expect(JobList.getSliceJobDetails).toBeDefined();
|
||||
it('has method "getSecondaryTagLabel"', () => {
|
||||
expect(JobList.getSecondaryTagLabel).toBeDefined();
|
||||
});
|
||||
it('returns a string', () => {
|
||||
it('returns the expected string when slice data is available', () => {
|
||||
const data = {
|
||||
job_slice_number: 1,
|
||||
job_slice_count: 2
|
||||
job_slice_count: 2,
|
||||
launch_type: 'manual',
|
||||
};
|
||||
const result = JobList.getSliceJobDetails(data);
|
||||
const result = JobList.getSecondaryTagLabel(data);
|
||||
expect(result).toEqual('Slice Job 1/2');
|
||||
});
|
||||
it('returns null when data is null', () => {
|
||||
it('returns null when slice data is null', () => {
|
||||
const data = {
|
||||
job_slice_number: null,
|
||||
job_slice_count: null
|
||||
job_slice_count: null,
|
||||
launch_type: 'manual',
|
||||
};
|
||||
const result = JobList.getSliceJobDetails(data);
|
||||
const result = JobList.getSecondaryTagLabel(data);
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
it('returns null when data is undefined', () => {
|
||||
it('returns null when slice data is undefined', () => {
|
||||
const data = {
|
||||
job_slice_number: undefined,
|
||||
job_slice_count: undefined
|
||||
job_slice_count: undefined,
|
||||
launch_type: 'manual',
|
||||
};
|
||||
const result = JobList.getSliceJobDetails(data);
|
||||
const result = JobList.getSecondaryTagLabel(data);
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
it('returns null when job is not a sliced job', () => {
|
||||
it('returns null when job is not a sliced or webhook job', () => {
|
||||
const data = {
|
||||
job_slice_number: null,
|
||||
job_slice_count: 1
|
||||
job_slice_count: 1,
|
||||
launch_type: 'manual',
|
||||
};
|
||||
const result = JobList.getSliceJobDetails(data);
|
||||
const result = JobList.getSecondaryTagLabel(data);
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
it('returns the expected string for webhook jobs', () => {
|
||||
const data = {
|
||||
launch_type: 'webhook',
|
||||
};
|
||||
const result = JobList.getSecondaryTagLabel(data);
|
||||
expect(result).toEqual('Webhook');
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user