mirror of
https://github.com/ansible/awx.git
synced 2026-03-06 11:11:07 -03:30
Merge pull request #499 from jaredevantabor/project-based-nav
Adding Project Based Navigation of Job Templates
This commit is contained in:
@@ -13,6 +13,7 @@ import { N_ } from '../i18n';
|
|||||||
import GetProjectPath from './factories/get-project-path.factory';
|
import GetProjectPath from './factories/get-project-path.factory';
|
||||||
import GetProjectIcon from './factories/get-project-icon.factory';
|
import GetProjectIcon from './factories/get-project-icon.factory';
|
||||||
import GetProjectToolTip from './factories/get-project-tool-tip.factory';
|
import GetProjectToolTip from './factories/get-project-tool-tip.factory';
|
||||||
|
import ProjectsTemplatesRoute from './projects-templates.route';
|
||||||
|
|
||||||
export default
|
export default
|
||||||
angular.module('Projects', [])
|
angular.module('Projects', [])
|
||||||
@@ -24,9 +25,10 @@ angular.module('Projects', [])
|
|||||||
.factory('GetProjectToolTip', GetProjectToolTip)
|
.factory('GetProjectToolTip', GetProjectToolTip)
|
||||||
.factory('ProjectList', ProjectList)
|
.factory('ProjectList', ProjectList)
|
||||||
.factory('ProjectsForm', ProjectsForm)
|
.factory('ProjectsForm', ProjectsForm)
|
||||||
.config(['$stateProvider', 'stateDefinitionsProvider',
|
.config(['$stateProvider', 'stateDefinitionsProvider', '$stateExtenderProvider',
|
||||||
function($stateProvider, stateDefinitionsProvider) {
|
function($stateProvider, stateDefinitionsProvider,$stateExtenderProvider) {
|
||||||
let stateDefinitions = stateDefinitionsProvider.$get();
|
let stateDefinitions = stateDefinitionsProvider.$get();
|
||||||
|
let stateExtender = $stateExtenderProvider.$get();
|
||||||
var projectResolve = {
|
var projectResolve = {
|
||||||
CredentialTypes: ['Rest', '$stateParams', 'GetBasePath', 'ProcessErrors',
|
CredentialTypes: ['Rest', '$stateParams', 'GetBasePath', 'ProcessErrors',
|
||||||
(Rest, $stateParams, GetBasePath, ProcessErrors) => {
|
(Rest, $stateParams, GetBasePath, ProcessErrors) => {
|
||||||
@@ -45,12 +47,9 @@ angular.module('Projects', [])
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
// lazily generate a tree of substates which will replace this node in ui-router's stateRegistry
|
|
||||||
// see: stateDefinition.factory for usage documentation
|
function generateStateTree() {
|
||||||
$stateProvider.state({
|
let projectTree = stateDefinitions.generateTree({
|
||||||
name: 'projects.**',
|
|
||||||
url: '/projects',
|
|
||||||
lazyLoad: () => stateDefinitions.generateTree({
|
|
||||||
parent: 'projects', // top-most node in the generated tree (will replace this state definition)
|
parent: 'projects', // top-most node in the generated tree (will replace this state definition)
|
||||||
modes: ['add', 'edit'],
|
modes: ['add', 'edit'],
|
||||||
list: 'ProjectList',
|
list: 'ProjectList',
|
||||||
@@ -76,7 +75,25 @@ angular.module('Projects', [])
|
|||||||
add: projectResolve,
|
add: projectResolve,
|
||||||
edit: projectResolve
|
edit: projectResolve
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
});
|
|
||||||
|
return Promise.all([
|
||||||
|
projectTree
|
||||||
|
]).then((generated) => {
|
||||||
|
return {
|
||||||
|
states: _.reduce(generated, (result, definition) => {
|
||||||
|
return result.concat(definition.states);
|
||||||
|
}, [
|
||||||
|
stateExtender.buildDefinition(ProjectsTemplatesRoute),
|
||||||
|
])
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let stateTree = {
|
||||||
|
name: 'projects.**',
|
||||||
|
url: '/projects',
|
||||||
|
lazyLoad: () => generateStateTree()
|
||||||
|
};
|
||||||
|
$stateProvider.state(stateTree);
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
|||||||
56
awx/ui/client/src/projects/projects-templates.route.js
Normal file
56
awx/ui/client/src/projects/projects-templates.route.js
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
import { N_ } from '../i18n';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
url: "/templates",
|
||||||
|
name: 'projects.edit.templates',
|
||||||
|
params: {
|
||||||
|
template_search: {
|
||||||
|
value: {
|
||||||
|
page_size: '20',
|
||||||
|
project: '',
|
||||||
|
order_by: "-id"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ncyBreadcrumb: {
|
||||||
|
label: N_("JOB TEMPLATES")
|
||||||
|
},
|
||||||
|
views: {
|
||||||
|
'related': {
|
||||||
|
templateProvider: function(FormDefinition, GenerateForm) {
|
||||||
|
let html = GenerateForm.buildCollection({
|
||||||
|
mode: 'edit',
|
||||||
|
related: 'templates',
|
||||||
|
form: typeof(FormDefinition) === 'function' ?
|
||||||
|
FormDefinition() : FormDefinition
|
||||||
|
});
|
||||||
|
return html;
|
||||||
|
},
|
||||||
|
controller: 'TemplatesListController'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
resolve: {
|
||||||
|
ListDefinition: ['TemplateList', '$transition$', (TemplateList, $transition$) => {
|
||||||
|
let id = $transition$.params().project_id;
|
||||||
|
TemplateList.actions.add.ngClick = `$state.go('templates.addJobTemplate', {project_id: ${id}})`;
|
||||||
|
TemplateList.basePath = 'job_templates';
|
||||||
|
return TemplateList;
|
||||||
|
}],
|
||||||
|
Dataset: ['ListDefinition', 'QuerySet', '$stateParams', 'GetBasePath', '$interpolate', '$rootScope',
|
||||||
|
(list, qs, $stateParams, GetBasePath, $interpolate, $rootScope) => {
|
||||||
|
// allow related list definitions to use interpolated $rootScope / $stateParams in basePath field
|
||||||
|
let path, interpolator;
|
||||||
|
if (GetBasePath(list.basePath)) {
|
||||||
|
path = GetBasePath(list.basePath);
|
||||||
|
} else {
|
||||||
|
interpolator = $interpolate(list.basePath);
|
||||||
|
path = interpolator({ $rootScope: $rootScope, $stateParams: $stateParams });
|
||||||
|
}
|
||||||
|
let project_id = $stateParams.project_id;
|
||||||
|
$stateParams[`${list.iterator}_search`].project = project_id;
|
||||||
|
path = GetBasePath('job_templates');
|
||||||
|
return qs.search(path, $stateParams[`${list.iterator}_search`]);
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -10,7 +10,8 @@
|
|||||||
* @description This form is for adding/editing projects
|
* @description This form is for adding/editing projects
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export default ['i18n', 'NotificationsList', function(i18n, NotificationsList) {
|
export default ['i18n', 'NotificationsList', 'TemplateList',
|
||||||
|
function(i18n, NotificationsList, TemplateList) {
|
||||||
return function() {
|
return function() {
|
||||||
var projectsFormObj = {
|
var projectsFormObj = {
|
||||||
addTitle: i18n._('NEW PROJECT'),
|
addTitle: i18n._('NEW PROJECT'),
|
||||||
@@ -267,7 +268,10 @@ export default ['i18n', 'NotificationsList', function(i18n, NotificationsList) {
|
|||||||
},
|
},
|
||||||
notifications: {
|
notifications: {
|
||||||
include: "NotificationsList",
|
include: "NotificationsList",
|
||||||
}
|
},
|
||||||
|
templates: {
|
||||||
|
include: "TemplateList",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
@@ -275,6 +279,11 @@ export default ['i18n', 'NotificationsList', function(i18n, NotificationsList) {
|
|||||||
var itm;
|
var itm;
|
||||||
|
|
||||||
for (itm in projectsFormObj.related) {
|
for (itm in projectsFormObj.related) {
|
||||||
|
if (projectsFormObj.related[itm].include === "TemplateList") {
|
||||||
|
projectsFormObj.related[itm] = _.clone(TemplateList);
|
||||||
|
projectsFormObj.related[itm].title = i18n._('Job Templates');
|
||||||
|
projectsFormObj.related[itm].skipGenerator = true;
|
||||||
|
}
|
||||||
if (projectsFormObj.related[itm].include === "NotificationsList") {
|
if (projectsFormObj.related[itm].include === "NotificationsList") {
|
||||||
projectsFormObj.related[itm] = NotificationsList;
|
projectsFormObj.related[itm] = NotificationsList;
|
||||||
projectsFormObj.related[itm].generateList = true; // tell form generator to call list generator and inject a list
|
projectsFormObj.related[itm].generateList = true; // tell form generator to call list generator and inject a list
|
||||||
|
|||||||
@@ -1950,29 +1950,31 @@ angular.module('FormGenerator', [GeneratorHelpers.name, 'Utilities', listGenerat
|
|||||||
if (collection.fieldActions) {
|
if (collection.fieldActions) {
|
||||||
html += "<td class=\"List-actionsContainer\"><div class=\"List-tableCell List-actionButtonCell actions\">";
|
html += "<td class=\"List-actionsContainer\"><div class=\"List-tableCell List-actionButtonCell actions\">";
|
||||||
for (act in collection.fieldActions) {
|
for (act in collection.fieldActions) {
|
||||||
fAction = collection.fieldActions[act];
|
if (act !== 'columnClass') {
|
||||||
html += "<button id=\"" + ((fAction.id) ? fAction.id : act + "-action") + "\" ";
|
fAction = collection.fieldActions[act];
|
||||||
html += (fAction.awToolTip) ? 'aw-tool-tip="' + fAction.awToolTip + '"' : '';
|
html += "<button id=\"" + ((fAction.id) ? fAction.id : act + "-action") + "\" ";
|
||||||
html += (fAction.dataPlacement) ? 'data-placement="' + fAction.dataPlacement + '"' : '';
|
html += (fAction.awToolTip) ? 'aw-tool-tip="' + fAction.awToolTip + '"' : '';
|
||||||
html += (fAction.href) ? "href=\"" + fAction.href + "\" " : "";
|
html += (fAction.dataPlacement) ? 'data-placement="' + fAction.dataPlacement + '"' : '';
|
||||||
html += (fAction.ngClick) ? this.attr(fAction, 'ngClick') : "";
|
html += (fAction.href) ? "href=\"" + fAction.href + "\" " : "";
|
||||||
html += (fAction.ngHref) ? this.attr(fAction, 'ngHref') : "";
|
html += (fAction.ngClick) ? this.attr(fAction, 'ngClick') : "";
|
||||||
html += (fAction.ngShow) ? this.attr(fAction, 'ngShow') : "";
|
html += (fAction.ngHref) ? this.attr(fAction, 'ngHref') : "";
|
||||||
html += " class=\"List-actionButton ";
|
html += (fAction.ngShow) ? this.attr(fAction, 'ngShow') : "";
|
||||||
html += (act === 'delete') ? "List-actionButton--delete" : "";
|
html += " class=\"List-actionButton ";
|
||||||
html += "\"";
|
html += (act === 'delete') ? "List-actionButton--delete" : "";
|
||||||
|
html += "\"";
|
||||||
|
|
||||||
html += ">";
|
html += ">";
|
||||||
if (fAction.iconClass) {
|
if (fAction.iconClass) {
|
||||||
html += "<i class=\"" + fAction.iconClass + "\"></i>";
|
html += "<i class=\"" + fAction.iconClass + "\"></i>";
|
||||||
} else {
|
} else {
|
||||||
html += SelectIcon({
|
html += SelectIcon({
|
||||||
action: act
|
action: act
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
// html += SelectIcon({ action: act });
|
||||||
|
//html += (fAction.label) ? "<span class=\"list-action-label\"> " + fAction.label + "</span>": "";
|
||||||
|
html += "</button>";
|
||||||
}
|
}
|
||||||
// html += SelectIcon({ action: act });
|
|
||||||
//html += (fAction.label) ? "<span class=\"list-action-label\"> " + fAction.label + "</span>": "";
|
|
||||||
html += "</button>";
|
|
||||||
}
|
}
|
||||||
html += "</div></td>";
|
html += "</div></td>";
|
||||||
html += "</tr>\n";
|
html += "</tr>\n";
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ export default
|
|||||||
self.socket.onopen = function () {
|
self.socket.onopen = function () {
|
||||||
$log.debug("Websocket connection opened. Socket readyState: " + self.socket.readyState);
|
$log.debug("Websocket connection opened. Socket readyState: " + self.socket.readyState);
|
||||||
socketPromise.resolve();
|
socketPromise.resolve();
|
||||||
console.log('promise resolved, and readyState: '+ self.readyState);
|
|
||||||
self.checkStatus();
|
self.checkStatus();
|
||||||
if(needsResubscribing){
|
if(needsResubscribing){
|
||||||
self.subscribe(self.getLast());
|
self.subscribe(self.getLast());
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ angular.module('templates', [surveyMaker.name, templatesList.name, jobTemplates.
|
|||||||
|
|
||||||
addJobTemplate = stateDefinitions.generateTree({
|
addJobTemplate = stateDefinitions.generateTree({
|
||||||
name: 'templates.addJobTemplate',
|
name: 'templates.addJobTemplate',
|
||||||
url: '/add_job_template?inventory_id&credential_id',
|
url: '/add_job_template?inventory_id&credential_id&project_id',
|
||||||
modes: ['add'],
|
modes: ['add'],
|
||||||
form: 'JobTemplateForm',
|
form: 'JobTemplateForm',
|
||||||
controllers: {
|
controllers: {
|
||||||
@@ -69,10 +69,10 @@ angular.module('templates', [surveyMaker.name, templatesList.name, jobTemplates.
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}],
|
}],
|
||||||
Project: ['$stateParams', 'Rest', 'GetBasePath', 'ProcessErrors',
|
Project: ['Rest', 'GetBasePath', 'ProcessErrors', '$transition$',
|
||||||
function($stateParams, Rest, GetBasePath, ProcessErrors){
|
function(Rest, GetBasePath, ProcessErrors, $transition$){
|
||||||
if($stateParams.credential_id){
|
if($transition$.params().credential_id){
|
||||||
let path = `${GetBasePath('projects')}?credential__id=${Number($stateParams.credential_id)}`;
|
let path = `${GetBasePath('projects')}?credential__id=${Number($transition$.params().credential_id)}`;
|
||||||
Rest.setUrl(path);
|
Rest.setUrl(path);
|
||||||
return Rest.get().
|
return Rest.get().
|
||||||
then(function(data){
|
then(function(data){
|
||||||
@@ -85,6 +85,20 @@ angular.module('templates', [surveyMaker.name, templatesList.name, jobTemplates.
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
else if($transition$.params().project_id){
|
||||||
|
let path = `${GetBasePath('projects')}${$transition$.params().project_id}`;
|
||||||
|
Rest.setUrl(path);
|
||||||
|
return Rest.get().
|
||||||
|
then(function(data){
|
||||||
|
return data.data;
|
||||||
|
}).catch(function(response) {
|
||||||
|
ProcessErrors(null, response.data, response.status, null, {
|
||||||
|
hdr: 'Error!',
|
||||||
|
msg: 'Failed to get project info. GET returned status: ' +
|
||||||
|
response.status
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
}],
|
}],
|
||||||
availableLabels: ['ProcessErrors', 'TemplatesService',
|
availableLabels: ['ProcessErrors', 'TemplatesService',
|
||||||
function(ProcessErrors, TemplatesService) {
|
function(ProcessErrors, TemplatesService) {
|
||||||
|
|||||||
Reference in New Issue
Block a user