const templateUrl = require('~features/output/details.partial.html'); let $http; let $filter; let $state; let error; let parse; let prompt; let resource; let strings; let wait; let vm; function mapChoices (choices) { if (!choices) return {}; return Object.assign(...choices.map(([k, v]) => ({ [k]: v }))); } function getStatusDetails (jobStatus) { const unmapped = jobStatus || resource.model.get('status'); if (!unmapped) { return null; } const choices = mapChoices(resource.model.options('actions.GET.status.choices')); const label = strings.get('labels.STATUS'); const icon = `fa icon-job-${unmapped}`; const value = choices[unmapped]; return { label, icon, value }; } function getStartDetails (started) { const unfiltered = started || resource.model.get('started'); const label = strings.get('labels.STARTED'); let value; if (unfiltered) { value = $filter('longDate')(unfiltered); } else { value = strings.get('details.NOT_STARTED'); } return { label, value }; } function getFinishDetails (finished) { const unfiltered = finished || resource.model.get('finished'); const label = strings.get('labels.FINISHED'); let value; if (unfiltered) { value = $filter('longDate')(unfiltered); } else { value = strings.get('details.NOT_FINISHED'); } return { label, value }; } function getModuleArgDetails () { const value = resource.model.get('module_args'); const label = strings.get('labels.MODULE_ARGS'); if (!value) { return null; } return { label, value }; } function getJobTypeDetails () { const unmapped = resource.model.get('job_type'); if (!unmapped) { return null; } const choices = mapChoices(resource.model.options('actions.GET.job_type.choices')); const label = strings.get('labels.JOB_TYPE'); const value = choices[unmapped]; return { label, value }; } function getVerbosityDetails () { const verbosity = resource.model.get('verbosity'); if (!verbosity) { return null; } const choices = mapChoices(resource.model.options('actions.GET.verbosity.choices')); const label = strings.get('labels.VERBOSITY'); const value = choices[verbosity]; return { label, value }; } function getSourceWorkflowJobDetails () { const sourceWorkflowJob = resource.model.get('summary_fields.source_workflow_job'); if (!sourceWorkflowJob) { return null; } const link = `/#/workflows/${sourceWorkflowJob.id}`; const tooltip = strings.get('tooltips.SOURCE_WORKFLOW_JOB'); return { link, tooltip }; } function getJobTemplateDetails () { const jobTemplate = resource.model.get('summary_fields.job_template'); if (!jobTemplate) { return null; } const label = strings.get('labels.JOB_TEMPLATE'); const link = `/#/templates/job_template/${jobTemplate.id}`; const value = $filter('sanitize')(jobTemplate.name); const tooltip = strings.get('tooltips.JOB_TEMPLATE'); return { label, link, value, tooltip }; } function getInventoryJobNameDetails () { if (resource.model.get('type') !== 'inventory_update') { return null; } const jobArgs = resource.model.get('job_args'); if (!jobArgs) { return null; } let parsedJobArgs; try { parsedJobArgs = JSON.parse(jobArgs); } catch (e) { return null; } if (!Array.isArray(parsedJobArgs)) { return null; } const jobArgIndex = parsedJobArgs.indexOf('--inventory-id'); const inventoryId = parsedJobArgs[jobArgIndex + 1]; if (jobArgIndex < 0) { return null; } if (!Number.isInteger(parseInt(inventoryId, 10))) { return null; } const name = resource.model.get('name'); const id = resource.model.get('id'); const label = strings.get('labels.NAME'); const tooltip = strings.get('tooltips.INVENTORY'); const value = `${id} - ${$filter('sanitize')(name)}`; const link = `/#/inventories/inventory/${inventoryId}`; return { label, link, tooltip, value }; } function getInventorySourceDetails () { if (!resource.model.has('summary_fields.inventory_source.source')) { return null; } const { source } = resource.model.get('summary_fields.inventory_source'); const choices = mapChoices(resource.model.options('actions.GET.source.choices')); const label = strings.get('labels.SOURCE'); const value = choices[source]; return { label, value }; } function getOverwriteDetails () { if (!resource.model.has('overwrite')) { return null; } const label = strings.get('labels.OVERWRITE'); const value = resource.model.get('overwrite'); return { label, value }; } function getOverwriteVarsDetails () { if (!resource.model.has('overwrite_vars')) { return null; } const label = strings.get('labels.OVERWRITE_VARS'); const value = resource.model.get('overwrite_vars'); return { label, value }; } function getLicenseErrorDetails () { if (!resource.model.has('license_error')) { return null; } const label = strings.get('labels.LICENSE_ERROR'); const value = resource.model.get('license_error'); return { label, value }; } function getLaunchedByDetails () { const createdBy = resource.model.get('summary_fields.created_by'); const jobTemplate = resource.model.get('summary_fields.job_template'); const relatedSchedule = resource.model.get('related.schedule'); const schedule = resource.model.get('summary_fields.schedule'); if (!createdBy && !schedule) { return null; } const label = strings.get('labels.LAUNCHED_BY'); let link; let tooltip; let value; if (createdBy) { tooltip = strings.get('tooltips.USER'); link = `/#/users/${createdBy.id}`; value = $filter('sanitize')(createdBy.username); } else if (relatedSchedule && jobTemplate) { tooltip = strings.get('tooltips.SCHEDULE'); link = `/#/templates/job_template/${jobTemplate.id}/schedules/${schedule.id}`; value = $filter('sanitize')(schedule.name); } else { tooltip = null; link = null; value = $filter('sanitize')(schedule.name); } return { label, link, tooltip, value }; } function getInventoryDetails () { const inventory = resource.model.get('summary_fields.inventory'); if (!inventory) { return null; } const label = strings.get('labels.INVENTORY'); const tooltip = strings.get('tooltips.INVENTORY'); const value = $filter('sanitize')(inventory.name); let link; if (inventory.kind === 'smart') { link = `/#/inventories/smart/${inventory.id}`; } else { link = `/#/inventories/inventory/${inventory.id}`; } return { label, link, tooltip, value }; } function getProjectDetails () { const project = resource.model.get('summary_fields.project'); if (!project) { return null; } const label = strings.get('labels.PROJECT'); const link = `/#/projects/${project.id}`; const value = $filter('sanitize')(project.name); const tooltip = strings.get('tooltips.PROJECT'); return { label, link, value, tooltip }; } function getProjectStatusDetails (projectStatus) { const project = resource.model.get('summary_fields.project'); const jobStatus = projectStatus || resource.model.get('summary_fields.project_update.status'); if (!project) { return null; } return jobStatus; } function getProjectUpdateDetails (updateId) { const project = resource.model.get('summary_fields.project'); const jobId = updateId || resource.model.get('summary_fields.project_update.id'); if (!project) { return null; } const link = `/#/jobs/project/${jobId}`; const tooltip = strings.get('tooltips.PROJECT_UPDATE'); return { link, tooltip }; } function getSCMRevisionDetails () { const label = strings.get('labels.SCM_REVISION'); const value = resource.model.get('scm_revision'); if (!value) { return null; } return { label, value }; } function getPlaybookDetails () { const label = strings.get('labels.PLAYBOOK'); const value = resource.model.get('playbook'); if (!value) { return null; } return { label, value }; } function getJobExplanationDetails () { const explanation = resource.model.get('job_explanation'); if (!explanation) { return null; } const limit = 150; const label = strings.get('labels.JOB_EXPLANATION'); let more = explanation; if (explanation.split(':')[0] === 'Previous Task Failed') { const taskStringIndex = explanation.split(':')[0].length + 1; const task = JSON.parse(explanation.substring(taskStringIndex)); more = `${task.job_type} failed for ${task.job_name} with ID ${task.job_id}`; } const less = $filter('limitTo')(more, limit); const showMore = false; const hasMoreToShow = more.length > limit; return { label, less, more, showMore, hasMoreToShow }; } function getResultTracebackDetails () { const traceback = resource.model.get('result_traceback'); if (!traceback) { return null; } const limit = 150; const label = strings.get('labels.RESULT_TRACEBACK'); const more = traceback; const less = $filter('limitTo')(more, limit); const showMore = false; const hasMoreToShow = more.length > limit; return { label, less, more, showMore, hasMoreToShow }; } function getCredentialDetails () { const credentials = resource.model.get('summary_fields.credentials'); let credentialTags = []; if (!credentials || credentials.length < 1) { return null; } credentialTags = credentials.map((cred) => buildCredentialDetails(cred)); const label = strings.get('labels.CREDENTIAL'); const value = credentialTags; return { label, value }; } function buildCredentialDetails (credential) { const icon = `${credential.kind}`; const link = `/#/credentials/${credential.id}`; const tooltip = strings.get('tooltips.CREDENTIAL'); const value = $filter('sanitize')(credential.name); return { icon, link, tooltip, value }; } function getForkDetails () { const label = strings.get('labels.FORKS'); const value = resource.model.get('forks'); if (!value) { return null; } return { label, value }; } function getLimitDetails () { const label = strings.get('labels.LIMIT'); const value = resource.model.get('limit'); if (!value) { return null; } return { label, value }; } function getInstanceGroupDetails () { const instanceGroup = resource.model.get('summary_fields.instance_group'); if (!instanceGroup) { return null; } const label = strings.get('labels.INSTANCE_GROUP'); const value = $filter('sanitize')(instanceGroup.name); let isolated = null; if (instanceGroup.controller_id) { isolated = strings.get('details.ISOLATED'); } return { label, value, isolated }; } function getJobTagDetails () { const tagString = resource.model.get('job_tags'); let jobTags; if (tagString) { jobTags = tagString.split(',').filter(tag => tag !== ''); } else { jobTags = []; } if (jobTags.length < 1) { return null; } const label = strings.get('labels.JOB_TAGS'); const more = false; const value = jobTags.map($filter('sanitize')); return { label, more, value }; } function getSkipTagDetails () { const tagString = resource.model.get('skip_tags'); let skipTags; if (tagString) { skipTags = tagString.split(',').filter(tag => tag !== ''); } else { skipTags = []; } if (skipTags.length < 1) { return null; } const more = false; const label = strings.get('labels.SKIP_TAGS'); const value = skipTags.map($filter('sanitize')); return { label, more, value }; } function getExtraVarsDetails () { const extraVars = resource.model.get('extra_vars'); if (!extraVars) { return null; } const label = strings.get('labels.EXTRA_VARS'); const tooltip = strings.get('tooltips.EXTRA_VARS'); const value = parse(extraVars); const disabled = true; return { label, tooltip, value, disabled }; } function getLabelDetails () { const jobLabels = _.get(resource.model.get('related.labels'), 'results', []); if (jobLabels.length < 1) { return null; } const label = strings.get('labels.LABELS'); const more = false; const value = jobLabels.map(({ name }) => name).map($filter('sanitize')); return { label, more, value }; } function createErrorHandler (path, action) { return res => { const hdr = strings.get('error.HEADER'); const msg = strings.get('error.CALL', { path, action, status: res.status }); error(null, res.data, res.status, null, { hdr, msg }); }; } const ELEMENT_LABELS = '#job-results-labels'; const ELEMENT_JOB_TAGS = '#job-results-job-tags'; const ELEMENT_SKIP_TAGS = '#job-results-skip-tags'; const ELEMENT_PROMPT_MODAL = '#prompt-modal'; const TAGS_SLIDE_DISTANCE = 200; function toggleLabels () { if (!this.labels.more) { $(ELEMENT_LABELS).slideUp(TAGS_SLIDE_DISTANCE); this.labels.more = true; } else { $(ELEMENT_LABELS).slideDown(TAGS_SLIDE_DISTANCE); this.labels.more = false; } } function toggleJobTags () { if (!this.jobTags.more) { $(ELEMENT_JOB_TAGS).slideUp(TAGS_SLIDE_DISTANCE); this.jobTags.more = true; } else { $(ELEMENT_JOB_TAGS).slideDown(TAGS_SLIDE_DISTANCE); this.jobTags.more = false; } } function toggleSkipTags () { if (!this.skipTags.more) { $(ELEMENT_SKIP_TAGS).slideUp(TAGS_SLIDE_DISTANCE); this.skipTags.more = true; } else { $(ELEMENT_SKIP_TAGS).slideDown(TAGS_SLIDE_DISTANCE); this.skipTags.more = false; } } function cancelJob () { const actionText = strings.get('cancelJob.CANCEL_JOB'); const hdr = strings.get('cancelJob.HEADER'); const warning = strings.get('cancelJob.SUBMIT_REQUEST'); const cancelText = strings.get('cancelJob.RETURN'); const id = resource.model.get('id'); const name = $filter('sanitize')(resource.model.get('name')); const body = `