mirror of
https://github.com/ansible/awx.git
synced 2026-01-14 19:30:39 -03:30
This uses select2 for styling of the <select> form elements. I'm forcing some styling overrides for select2, therefore we no longer need the select2-bootstrap-theme library. For all add-forms, select2 is attached after the form compiles in form-generator. For edit-forms however, the select2 module couldn't be attached to the select element until after the options selection had taken place (which takes place after the REST request). Therefore I had to add some calls to CreateSelect2 in the edit controllers.
378 lines
16 KiB
JavaScript
378 lines
16 KiB
JavaScript
/*************************************************
|
|
* Copyright (c) 2015 Ansible, Inc.
|
|
*
|
|
* All Rights Reserved
|
|
*************************************************/
|
|
|
|
/**
|
|
* @ngdoc function
|
|
* @name forms.function:Projects
|
|
* @description This form is for adding/editing projects
|
|
*/
|
|
|
|
export default
|
|
angular.module('ProjectFormDefinition', ['SchedulesListDefinition'])
|
|
.value('ProjectsFormObject', {
|
|
|
|
addTitle: 'New Project',
|
|
editTitle: '{{ name }}',
|
|
name: 'project',
|
|
forceListeners: true,
|
|
tabs: true,
|
|
|
|
fields: {
|
|
name: {
|
|
label: 'Name',
|
|
type: 'text',
|
|
addRequired: true,
|
|
editRequired: true,
|
|
capitalize: false
|
|
},
|
|
description: {
|
|
label: 'Description',
|
|
type: 'text',
|
|
addRequired: false,
|
|
editRequired: false
|
|
},
|
|
organization: {
|
|
label: 'Organization',
|
|
type: 'lookup',
|
|
sourceModel: 'organization',
|
|
sourceField: 'name',
|
|
addRequired: true,
|
|
editRequired: false,
|
|
excludeMode: 'edit',
|
|
ngClick: 'lookUpOrganization()',
|
|
awRequiredWhen: {
|
|
variable: "organizationrequired",
|
|
init: "true"
|
|
},
|
|
awPopOver: '<p>A project must have at least one organization. Pick one organization now to create the project, and then after ' +
|
|
'the project is created you can add additional organizations.</p><p>Only super users and organization administrators are allowed ' +
|
|
'to make changes to projects. Associating one or more organizations to a project determins which organizations admins have ' +
|
|
'access to modify the project.',
|
|
dataTitle: 'Organization',
|
|
dataContainer: 'body',
|
|
dataPlacement: 'right'
|
|
},
|
|
scm_type: {
|
|
label: 'SCM Type',
|
|
type: 'select',
|
|
class: 'Form-dropDown--scmType',
|
|
ngOptions: 'type.label for type in scm_type_options track by type.value',
|
|
ngChange: 'scmChange()',
|
|
addRequired: true,
|
|
editRequired: true
|
|
},
|
|
missing_path_alert: {
|
|
type: 'alertblock',
|
|
"class": 'alert-info',
|
|
ngShow: "showMissingPlaybooksAlert && scm_type.value == 'manual'",
|
|
alertTxt: '<p class=\"text-justify\"><strong>WARNING:</strong> There are no available playbook directories in {{ base_dir }}. ' +
|
|
'Either that directory is empty, or all of the contents are already assigned to other projects. ' +
|
|
'Create a new directory there and make sure the playbook files can be read by the "awx" system user, ' +
|
|
'or have Tower directly retrieve your playbooks from source control using the SCM Type option above.</p>',
|
|
closeable: false
|
|
},
|
|
base_dir: {
|
|
label: 'Project Base Path',
|
|
type: 'textarea',
|
|
//"class": 'col-lg-6',
|
|
showonly: true,
|
|
ngShow: "scm_type.value == 'manual' " ,
|
|
awPopOver: '<p>Base path used for locating playbooks. Directories found inside this path will be listed in the playbook directory drop-down. ' +
|
|
'Together the base path and selected playbook directory provide the full path used to locate playbooks.</p>' +
|
|
'<p>Use PROJECTS_ROOT in your environment settings file to determine the base path value.</p>',
|
|
dataTitle: 'Project Base Path',
|
|
dataContainer: 'body',
|
|
dataPlacement: 'right'
|
|
},
|
|
local_path: {
|
|
label: 'Playbook Directory',
|
|
type: 'select',
|
|
id: 'local-path-select',
|
|
ngOptions: 'path.label for path in project_local_paths',
|
|
awRequiredWhen: {
|
|
variable: "pathRequired",
|
|
init: false
|
|
},
|
|
ngShow: "scm_type.value == 'manual' && !showMissingPlaybooksAlert",
|
|
awPopOver: '<p>Select from the list of directories found in the base path.' +
|
|
'Together the base path and the playbook directory provide the full path used to locate playbooks.</p>' +
|
|
'<p>Use PROJECTS_ROOT in your environment settings file to determine the base path value.</p>',
|
|
dataTitle: 'Project Path',
|
|
dataContainer: 'body',
|
|
dataPlacement: 'right'
|
|
},
|
|
scm_url: {
|
|
label: 'SCM URL',
|
|
type: 'text',
|
|
ngShow: "scm_type && scm_type.value !== 'manual'",
|
|
awRequiredWhen: {
|
|
variable: "scmRequired",
|
|
init: false
|
|
},
|
|
helpCollapse: [{
|
|
hdr: 'GIT URLs',
|
|
content: '<p>Example URLs for GIT SCM include:</p><ul class=\"no-bullets\"><li>https://github.com/ansible/ansible.git</li>' +
|
|
'<li>git@github.com:ansible/ansible.git</li><li>git://servername.example.com/ansible.git</li></ul>' +
|
|
'<p><strong>Note:</strong> When using SSH protocol for GitHub or Bitbucket, enter an SSH key only, ' +
|
|
'do not enter a username (other than git). Additionally, GitHub and Bitbucket do not support password authentication when using ' +
|
|
'SSH. GIT read only protocol (git://) does not use username or password information.',
|
|
show: "scm_type.value == 'git'"
|
|
}, {
|
|
hdr: 'SVN URLs',
|
|
content: '<p>Example URLs for Subversion SCM include:</p>' +
|
|
'<ul class=\"no-bullets\"><li>https://github.com/ansible/ansible</li><li>svn://servername.example.com/path</li>' +
|
|
'<li>svn+ssh://servername.example.com/path</li></ul>',
|
|
show: "scm_type.value == 'svn'"
|
|
}, {
|
|
hdr: 'Mercurial URLs',
|
|
content: '<p>Example URLs for Mercurial SCM include:</p>' +
|
|
'<ul class=\"no-bullets\"><li>https://bitbucket.org/username/project</li><li>ssh://hg@bitbucket.org/username/project</li>' +
|
|
'<li>ssh://server.example.com/path</li></ul>' +
|
|
'<p><strong>Note:</strong> Mercurial does not support password authentication for SSH. ' +
|
|
'Do not put the username and key in the URL. ' +
|
|
'If using Bitbucket and SSH, do not supply your Bitbucket username.',
|
|
show: "scm_type.value == 'hg'"
|
|
}]
|
|
},
|
|
scm_branch: {
|
|
labelBind: "scmBranchLabel",
|
|
type: 'text',
|
|
ngShow: "scm_type && scm_type.value !== 'manual'",
|
|
addRequired: false,
|
|
editRequired: false
|
|
},
|
|
credential: {
|
|
label: 'SCM Credential',
|
|
type: 'lookup',
|
|
ngShow: "scm_type && scm_type.value !== 'manual'",
|
|
sourceModel: 'credential',
|
|
sourceField: 'name',
|
|
ngClick: 'lookUpCredential()',
|
|
addRequired: false,
|
|
editRequired: false
|
|
},
|
|
checkbox_group: {
|
|
label: 'SCM Update Options',
|
|
type: 'checkbox_group',
|
|
ngShow: "scm_type && scm_type.value !== 'manual'",
|
|
fields: [{
|
|
name: 'scm_clean',
|
|
label: 'Clean',
|
|
type: 'checkbox',
|
|
addRequired: false,
|
|
editRequired: false,
|
|
awPopOver: '<p>Remove any local modifications prior to performing an update.</p>',
|
|
dataTitle: 'SCM Clean',
|
|
dataContainer: 'body',
|
|
dataPlacement: 'right',
|
|
labelClass: 'checkbox-options'
|
|
}, {
|
|
name: 'scm_delete_on_update',
|
|
label: 'Delete on Update',
|
|
type: 'checkbox',
|
|
addRequired: false,
|
|
editRequired: false,
|
|
awPopOver: '<p>Delete the local repository in its entirety prior to performing an update.</p><p>Depending on the size of the ' +
|
|
'repository this may significantly increase the amount of time required to complete an update.</p>',
|
|
dataTitle: 'SCM Delete',
|
|
dataContainer: 'body',
|
|
dataPlacement: 'right',
|
|
labelClass: 'checkbox-options'
|
|
}, {
|
|
name: 'scm_update_on_launch',
|
|
label: 'Update on Launch',
|
|
type: 'checkbox',
|
|
addRequired: false,
|
|
editRequired: false,
|
|
awPopOver: '<p>Each time a job runs using this project, perform an update to the local repository prior to starting the job.</p>',
|
|
dataTitle: 'SCM Update',
|
|
dataContainer: 'body',
|
|
dataPlacement: 'right',
|
|
labelClass: 'checkbox-options'
|
|
}]
|
|
},
|
|
scm_update_cache_timeout: {
|
|
label: 'Cache Timeout<span class=\"small-text\"> (seconds)</span>',
|
|
id: 'scm-cache-timeout',
|
|
type: 'number',
|
|
integer: true,
|
|
min: 0,
|
|
ngShow: "scm_update_on_launch",
|
|
spinner: true,
|
|
"default": '0',
|
|
addRequired: false,
|
|
editRequired: false,
|
|
awPopOver: '<p>Time in seconds to consider a project to be current. During job runs and callbacks the task system will ' +
|
|
'evaluate the timestamp of the latest project update. If it is older than Cache Timeout, it is not considered current, ' +
|
|
'and a new project update will be performed.</p>',
|
|
dataTitle: 'Cache Timeout',
|
|
dataPlacement: 'right',
|
|
dataContainer: "body"
|
|
}
|
|
},
|
|
|
|
buttons: {
|
|
save: {
|
|
ngClick: 'formSave()',
|
|
ngDisabled: true
|
|
},
|
|
cancel: {
|
|
ngClick: 'formCancel()'
|
|
}
|
|
},
|
|
|
|
related: {
|
|
organizations: {
|
|
type: 'collection',
|
|
title: 'Organizations',
|
|
iterator: 'organization',
|
|
index: false,
|
|
open: false,
|
|
|
|
actions: {
|
|
add: {
|
|
ngClick: "add('organizations')",
|
|
label: 'Add',
|
|
awToolTip: 'Add an organization',
|
|
actionClass: 'btn List-buttonSubmit',
|
|
buttonContent: '+ ADD'
|
|
}
|
|
},
|
|
|
|
fields: {
|
|
name: {
|
|
key: true,
|
|
label: 'Name'
|
|
},
|
|
description: {
|
|
label: 'Description'
|
|
}
|
|
},
|
|
|
|
fieldActions: {
|
|
edit: {
|
|
label: 'Edit',
|
|
ngClick: "edit('organizations', organization.id, organization.name)",
|
|
icon: 'icon-edit',
|
|
awToolTip: 'Edit the organization',
|
|
'class': 'btn btn-default'
|
|
},
|
|
"delete": {
|
|
label: 'Delete',
|
|
ngClick: "delete('organizations', organization.id, organization.name, 'organization')",
|
|
icon: 'icon-trash',
|
|
"class": 'btn-danger',
|
|
awToolTip: 'Delete the organization'
|
|
}
|
|
}
|
|
},
|
|
|
|
schedules: {
|
|
type: 'collection',
|
|
title: 'Schedules',
|
|
iterator: 'schedule',
|
|
index: false,
|
|
open: false,
|
|
|
|
actions: {
|
|
refresh: {
|
|
mode: 'all',
|
|
awToolTip: "Refresh the page",
|
|
ngClick: "refreshSchedules()",
|
|
actionClass: 'btn List-buttonDefault',
|
|
buttonContent: 'REFRESH',
|
|
ngHide: 'scheduleLoading == false && schedule_active_search == false && schedule_total_rows < 1'
|
|
},
|
|
add: {
|
|
mode: 'all',
|
|
ngClick: 'addSchedule()',
|
|
awToolTip: 'Add a new schedule',
|
|
actionClass: 'btn List-buttonSubmit',
|
|
buttonContent: '+ ADD'
|
|
}
|
|
},
|
|
fields: {
|
|
name: {
|
|
key: true,
|
|
label: 'Name',
|
|
ngClick: "editSchedule(schedule.id)",
|
|
columnClass: "col-md-3 col-sm-3 col-xs-3"
|
|
},
|
|
dtstart: {
|
|
label: 'First Run',
|
|
filter: "longDate",
|
|
searchable: false,
|
|
columnClass: "col-md-2 col-sm-3 hidden-xs"
|
|
},
|
|
next_run: {
|
|
label: 'Next Run',
|
|
filter: "longDate",
|
|
searchable: false,
|
|
columnClass: "col-md-2 col-sm-3 col-xs-3"
|
|
},
|
|
dtend: {
|
|
label: 'Final Run',
|
|
filter: "longDate",
|
|
searchable: false,
|
|
columnClass: "col-md-2 col-sm-3 hidden-xs"
|
|
}
|
|
},
|
|
fieldActions: {
|
|
"play": {
|
|
mode: "all",
|
|
ngClick: "toggleSchedule($event, schedule.id)",
|
|
awToolTip: "{{ schedule.play_tip }}",
|
|
dataTipWatch: "schedule.play_tip",
|
|
iconClass: "{{ 'fa icon-schedule-enabled-' + schedule.enabled }}",
|
|
dataPlacement: "top"
|
|
},
|
|
edit: {
|
|
label: 'Edit',
|
|
ngClick: "editSchedule(schedule.id)",
|
|
icon: 'icon-edit',
|
|
awToolTip: 'Edit schedule',
|
|
dataPlacement: 'top'
|
|
},
|
|
"delete": {
|
|
label: 'Delete',
|
|
ngClick: "deleteSchedule(schedule.id)",
|
|
icon: 'icon-trash',
|
|
awToolTip: 'Delete schedule',
|
|
dataPlacement: 'top'
|
|
}
|
|
}
|
|
}
|
|
|
|
},
|
|
|
|
relatedSets: function(urls) {
|
|
return {
|
|
organizations: {
|
|
iterator: 'organization',
|
|
url: urls.organizations
|
|
},
|
|
schedules: {
|
|
iterator: 'schedule',
|
|
url: urls.schedules
|
|
}
|
|
};
|
|
}
|
|
|
|
})
|
|
|
|
.factory('ProjectsForm', ['ProjectsFormObject', 'SchedulesList', function(ProjectsFormObject, ScheduleList) {
|
|
return function() {
|
|
var itm;
|
|
for (itm in ProjectsFormObject.related) {
|
|
if (ProjectsFormObject.related[itm].include === "SchedulesList") {
|
|
ProjectsFormObject.related[itm] = ScheduleList;
|
|
ProjectsFormObject.related[itm].generateList = true; // tell form generator to call list generator and inject a list
|
|
}
|
|
}
|
|
return ProjectsFormObject;
|
|
};
|
|
}]);
|