Merge pull request #1264 from kensible/688-orgCards-counts

688 org cards counts
This commit is contained in:
kensible 2016-03-17 10:48:50 -04:00
commit cc98c6ce3c
14 changed files with 618 additions and 438 deletions

View File

@ -27,6 +27,7 @@ import {JobsListController} from './controllers/Jobs';
import {PortalController} from './controllers/Portal';
import systemTracking from './system-tracking/main';
import inventoryScripts from './inventory-scripts/main';
import organizations from './organizations/main';
import permissions from './permissions/main';
import managementJobs from './management-jobs/main';
import jobDetail from './job-detail/main';
@ -50,7 +51,9 @@ import lookUpHelper from './lookup/main';
import JobTemplates from './job-templates/main';
import {ScheduleEditController} from './controllers/Schedules';
import {ProjectsList, ProjectsAdd, ProjectsEdit} from './controllers/Projects';
import {OrganizationsList, OrganizationsAdd, OrganizationsEdit} from './controllers/Organizations';
import OrganizationsList from './organizations/list/organizations-list.controller';
import OrganizationsAdd from './organizations/add/organizations-add.controller';
import OrganizationsEdit from './organizations/edit/organizations-edit.controller';
import {InventoriesList, InventoriesAdd, InventoriesEdit, InventoriesManage} from './controllers/Inventories';
import {AdminsList} from './controllers/Admins';
import {UsersList, UsersAdd, UsersEdit} from './controllers/Users';
@ -85,6 +88,7 @@ var tower = angular.module('Tower', [
browserData.name,
systemTracking.name,
inventoryScripts.name,
organizations.name,
permissions.name,
managementJobs.name,
setupMenu.name,
@ -428,61 +432,6 @@ var tower = angular.module('Tower', [
}
}).
state('organizations', {
url: '/organizations',
templateUrl: urlPrefix + 'partials/organizations.html',
controller: OrganizationsList,
data: {
activityStream: true,
activityStreamTarget: 'organization'
},
ncyBreadcrumb: {
parent: function($scope) {
$scope.$parent.$emit("ReloadOrgListView");
return "setup";
},
label: "ORGANIZATIONS"
},
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}).
state('organizations.add', {
url: '/add',
templateUrl: urlPrefix + 'partials/organizations.crud.html',
controller: OrganizationsAdd,
ncyBreadcrumb: {
parent: "organizations",
label: "CREATE ORGANIZATION"
},
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}).
state('organizations.edit', {
url: '/:organization_id',
templateUrl: urlPrefix + 'partials/organizations.crud.html',
controller: OrganizationsEdit,
data: {
activityStreamId: 'organization_id'
},
ncyBreadcrumb: {
parent: "organizations",
label: "{{name}}"
},
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}).
state('organizationAdmins', {
url: '/organizations/:organization_id/admins',
templateUrl: urlPrefix + 'partials/organizations.html',

View File

@ -1,382 +0,0 @@
/*************************************************
* Copyright (c) 2015 Ansible, Inc.
*
* All Rights Reserved
*************************************************/
/**
* @ngdoc function
* @name controllers.function:Organizations
* @description This controller's for the Organizations page
*/
export function OrganizationsList($stateParams, $scope, $rootScope, $location,
$log, $compile, Rest, PaginateWidget, PaginateInit, SearchInit, OrganizationList, Alert, Prompt, ClearScope, ProcessErrors, GetBasePath, Wait,
$state) {
ClearScope();
var defaultUrl = GetBasePath('organizations'),
list = OrganizationList,
pageSize = $scope.orgCount;
PaginateInit({
scope: $scope,
list: list,
url: defaultUrl,
pageSize: pageSize,
});
SearchInit({
scope: $scope,
list: list,
url: defaultUrl,
});
$scope.search(list.iterator);
$scope.PaginateWidget = PaginateWidget({
iterator: list.iterator,
set: 'organizations'
});
var paginationContainer = $('#pagination-container');
paginationContainer.html($scope.PaginateWidget);
$compile(paginationContainer.contents())($scope)
var parseCardData = function (cards) {
return cards.map(function (card) {
var val = {};
val.name = card.name;
val.id = card.id;
if (card.id + "" === cards.activeCard) {
val.isActiveCard = true;
}
val.description = card.description || undefined;
val.links = [];
val.links.push({
href: card.related.users,
name: "USERS"
});
val.links.push({
href: card.related.teams,
name: "TEAMS"
});
val.links.push({
href: card.related.inventories,
name: "INVENTORIES"
});
val.links.push({
href: card.related.projects,
name: "PROJECTS"
});
val.links.push({
href: card.related.job_templates,
name: "JOB TEMPLATES"
});
val.links.push({
href: card.related.admins,
name: "ADMINS"
});
return val;
});
};
var getOrganization = function (id) {
Rest.setUrl(defaultUrl);
Rest.get()
.success(function (data) {
data.results.activeCard = id;
$scope.orgCount = data.count;
$scope.orgCards = parseCardData(data.results);
Wait("stop");
})
.error(function (data, status) {
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
msg: 'Call to ' + defaultUrl + ' failed. DELETE returned status: ' + status });
});
};
$scope.$on("ReloadOrgListView", function() {
if ($state.$current.self.name === "organizations") {
delete $scope.activeCard;
if ($scope.orgCards) {
$scope.orgCards = $scope.orgCards.map(function (card) {
delete card.isActiveCard;
return card;
});
}
$scope.hideListHeader = false;
}
});
$scope.$on("ReloadOrganzationCards", function(e, id) {
$scope.activeCard = id;
getOrganization(id);
});
$scope.$on("HideOrgListHeader", function() {
$scope.hideListHeader = true;
});
$scope.$on("ShowOrgListHeader", function() {
$scope.hideListHeader = false;
});
getOrganization();
$rootScope.flashMessage = null;
if ($scope.removePostRefresh) {
$scope.removePostRefresh();
}
$scope.removePostRefresh = $scope.$on('PostRefresh', function () {
// Cleanup after a delete
Wait('stop');
$('#prompt-modal').modal('hide');
});
$scope.addOrganization = function () {
$state.transitionTo('organizations.add');
};
$scope.editOrganization = function (id) {
$scope.activeCard = id;
$state.transitionTo('organizations.edit', {organization_id: id});
};
$scope.deleteOrganization = function (id, name) {
var action = function () {
$('#prompt-modal').modal('hide');
Wait('start');
var url = defaultUrl + id + '/';
Rest.setUrl(url);
Rest.destroy()
.success(function () {
if ($state.current.name !== "organzations") {
$state.transitionTo("organizations");
}
$scope.$emit("ReloadOrganzationCards");
})
.error(function (data, status) {
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status });
});
};
Prompt({
hdr: 'Delete',
body: '<div class="Prompt-bodyQuery">Are you sure you want to delete the organization below?</div><div class="Prompt-bodyTarget">' + name + '</div>',
action: action,
actionText: 'DELETE'
});
};
}
OrganizationsList.$inject = ['$stateParams', '$scope', '$rootScope',
'$location', '$log', '$compile', 'Rest', 'PaginateWidget', 'PaginateInit', 'SearchInit', 'OrganizationList', 'Alert', 'Prompt', 'ClearScope',
'ProcessErrors', 'GetBasePath', 'Wait',
'$state'
];
export function OrganizationsAdd($scope, $rootScope, $compile, $location, $log,
$stateParams, OrganizationForm, GenerateForm, Rest, Alert, ProcessErrors,
ClearScope, GetBasePath, ReturnToCaller, Wait, $state) {
ClearScope();
// Inject dynamic view
var generator = GenerateForm,
form = OrganizationForm,
base = $location.path().replace(/^\//, '').split('/')[0];
generator.inject(form, { mode: 'add', related: false, scope: $scope});
generator.reset();
$scope.$emit("HideOrgListHeader");
// Save
$scope.formSave = function () {
generator.clearApiErrors();
Wait('start');
var url = GetBasePath(base);
url += (base !== 'organizations') ? $stateParams.project_id + '/organizations/' : '';
Rest.setUrl(url);
Rest.post({ name: $scope.name, description: $scope.description })
.success(function (data) {
Wait('stop');
$scope.$emit("ReloadOrganzationCards", data.id);
if (base === 'organizations') {
$rootScope.flashMessage = "New organization successfully created!";
$location.path('/organizations/' + data.id);
} else {
ReturnToCaller(1);
}
})
.error(function (data, status) {
ProcessErrors($scope, data, status, form, { hdr: 'Error!',
msg: 'Failed to add new organization. Post returned status: ' + status });
});
};
$scope.formCancel = function () {
$scope.$emit("ReloadOrganzationCards");
$scope.$emit("ShowOrgListHeader");
$state.transitionTo('organizations');
};
}
OrganizationsAdd.$inject = ['$scope', '$rootScope', '$compile', '$location',
'$log', '$stateParams', 'OrganizationForm', 'GenerateForm', 'Rest', 'Alert',
'ProcessErrors', 'ClearScope', 'GetBasePath', 'ReturnToCaller', 'Wait',
'$state'
];
export function OrganizationsEdit($scope, $rootScope, $compile, $location, $log,
$stateParams, OrganizationForm, GenerateForm, Rest, Alert, ProcessErrors,
RelatedSearchInit, RelatedPaginateInit, Prompt, ClearScope, GetBasePath,
Wait, $state) {
ClearScope();
// Inject dynamic view
var form = OrganizationForm,
generator = GenerateForm,
defaultUrl = GetBasePath('organizations'),
base = $location.path().replace(/^\//, '').split('/')[0],
master = {},
id = $stateParams.organization_id,
relatedSets = {};
$scope.$emit("HideOrgListHeader");
$scope.$emit("ReloadOrganzationCards", id);
$scope.organization_id = id;
generator.inject(form, { mode: 'edit', related: true, scope: $scope});
generator.reset();
// After the Organization is loaded, retrieve each related set
if ($scope.organizationLoadedRemove) {
$scope.organizationLoadedRemove();
}
$scope.organizationLoadedRemove = $scope.$on('organizationLoaded', function () {
for (var set in relatedSets) {
$scope.search(relatedSets[set].iterator);
}
Wait('stop');
});
// Retrieve detail record and prepopulate the form
Wait('start');
Rest.setUrl(defaultUrl + id + '/');
Rest.get()
.success(function (data) {
var fld, related, set;
$scope.organization_name = data.name;
for (fld in form.fields) {
if (data[fld]) {
$scope[fld] = data[fld];
master[fld] = data[fld];
}
}
related = data.related;
for (set in form.related) {
if (related[set]) {
relatedSets[set] = {
url: related[set],
iterator: form.related[set].iterator
};
}
}
// Initialize related search functions. Doing it here to make sure relatedSets object is populated.
RelatedSearchInit({ scope: $scope, form: form, relatedSets: relatedSets });
RelatedPaginateInit({ scope: $scope, relatedSets: relatedSets });
$scope.$emit('organizationLoaded');
})
.error(function (data, status) {
ProcessErrors($scope, data, status, form, { hdr: 'Error!',
msg: 'Failed to retrieve organization: ' + $stateParams.id + '. GET status: ' + status });
});
// Save changes to the parent
$scope.formSave = function () {
var fld, params = {};
generator.clearApiErrors();
Wait('start');
for (fld in form.fields) {
params[fld] = $scope[fld];
}
Rest.setUrl(defaultUrl + id + '/');
Rest.put(params)
.success(function (data) {
Wait('stop');
$scope.organization_name = $scope.name;
master = params;
$rootScope.flashMessage = "Your changes were successfully saved!";
$scope.$emit("ReloadOrganzationCards", data.id);
})
.error(function (data, status) {
ProcessErrors($scope, data, status, OrganizationForm, { hdr: 'Error!',
msg: 'Failed to update organization: ' + id + '. PUT status: ' + status });
});
};
$scope.formCancel = function () {
$scope.$emit("ReloadOrganzationCards");
$scope.$emit("ShowOrgListHeader");
$state.transitionTo('organizations');
};
// Related set: Add button
$scope.add = function (set) {
$rootScope.flashMessage = null;
$location.path('/' + base + '/' + $stateParams.organization_id + '/' + set);
};
// Related set: Edit button
$scope.edit = function (set, id) {
$rootScope.flashMessage = null;
$location.path('/' + set + '/' + id);
};
// Related set: Delete button
$scope['delete'] = function (set, itm_id, name, title) {
$rootScope.flashMessage = null;
var action = function () {
Wait('start');
var url = defaultUrl + $stateParams.organization_id + '/' + set + '/';
Rest.setUrl(url);
Rest.post({ id: itm_id, disassociate: 1 })
.success(function () {
$('#prompt-modal').modal('hide');
$scope.search(form.related[set].iterator);
})
.error(function (data, status) {
$('#prompt-modal').modal('hide');
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
msg: 'Call to ' + url + ' failed. POST returned status: ' + status });
});
};
Prompt({
hdr: 'Delete',
body: '<div class="Prompt-bodyQuery">Are you sure you want to remove the ' + title + ' below from ' + $scope.name + '?</div><div class="Prompt-bodyTarget">' + name + '</div>',
action: action,
actionText: 'DELETE'
});
};
}
OrganizationsEdit.$inject = ['$scope', '$rootScope', '$compile', '$location',
'$log', '$stateParams', 'OrganizationForm', 'GenerateForm', 'Rest', 'Alert',
'ProcessErrors', 'RelatedSearchInit', 'RelatedPaginateInit', 'Prompt',
'ClearScope', 'GetBasePath', 'Wait', '$state'
];

View File

@ -0,0 +1,14 @@
/*************************************************
* Copyright (c) 2015 Ansible, Inc.
*
* All Rights Reserved
*************************************************/
import route from './organizations-add.route';
import controller from './organizations-add.controller';
export default
angular.module('organizationsAdd', [])
.run(['$stateExtender', function($stateExtender) {
$stateExtender.addState(route);
}]);

View File

@ -0,0 +1,66 @@
/*************************************************
* Copyright (c) 2016 Ansible, Inc.
*
* All Rights Reserved
*************************************************/
export default ['$scope', '$rootScope', '$compile', '$location',
'$log', '$stateParams', 'OrganizationForm', 'GenerateForm', 'Rest', 'Alert',
'ProcessErrors', 'ClearScope', 'GetBasePath', 'ReturnToCaller', 'Wait',
'$state',
function($scope, $rootScope, $compile, $location, $log,
$stateParams, OrganizationForm, GenerateForm, Rest, Alert, ProcessErrors,
ClearScope, GetBasePath, ReturnToCaller, Wait, $state) {
ClearScope();
// Inject dynamic view
var generator = GenerateForm,
form = OrganizationForm,
base = $location.path().replace(/^\//, '').split('/')[0];
generator.inject(form, {
mode: 'add',
related: false,
scope: $scope
});
generator.reset();
$scope.$emit("HideOrgListHeader");
// Save
$scope.formSave = function() {
generator.clearApiErrors();
Wait('start');
var url = GetBasePath(base);
url += (base !== 'organizations') ? $stateParams.project_id + '/organizations/' : '';
Rest.setUrl(url);
Rest.post({
name: $scope.name,
description: $scope.description
})
.success(function(data) {
Wait('stop');
$scope.$emit("ReloadOrganzationCards", data.id);
if (base === 'organizations') {
$rootScope.flashMessage = "New organization successfully created!";
$location.path('/organizations/' + data.id);
} else {
ReturnToCaller(1);
}
})
.error(function(data, status) {
ProcessErrors($scope, data, status, form, {
hdr: 'Error!',
msg: 'Failed to add new organization. Post returned status: ' + status
});
});
};
$scope.formCancel = function() {
$scope.$emit("ReloadOrganzationCards");
$scope.$emit("ShowOrgListHeader");
$state.transitionTo('organizations');
};
}
]

View File

@ -0,0 +1,4 @@
<div class="tab-pane" id="organizations">
<div ui-view></div>
<div ng-cloak id="htmlTemplate" class="Panel"></div>
</div>

View File

@ -0,0 +1,24 @@
/*************************************************
* Copyright (c) 2016 Ansible, Inc.
*
* All Rights Reserved
*************************************************/
import {templateUrl} from '../../shared/template-url/template-url.factory';
import OrganizationsAdd from './organizations-add.controller';
export default {
name: 'organizations.add',
route: '/add',
templateUrl: templateUrl('organizations/add/organizations-add'),
controller: OrganizationsAdd,
ncyBreadcrumb: {
parent: "organizations",
label: "CREATE ORGANIZATION"
},
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
};

View File

@ -0,0 +1,15 @@
/*************************************************
* Copyright (c) 2015 Ansible, Inc.
*
* All Rights Reserved
*************************************************/
import route from './organizations-edit.route';
import controller from './organizations-edit.controller';
export default
angular.module('organizationsEdit', [])
.controller('organizationsEditController', controller)
.run(['$stateExtender', function($stateExtender) {
$stateExtender.addState(route);
}]);

View File

@ -0,0 +1,150 @@
/*************************************************
* Copyright (c) 2016 Ansible, Inc.
*
* All Rights Reserved
*************************************************/
export default ['$scope', '$rootScope', '$compile', '$location',
'$log', '$stateParams', 'OrganizationForm', 'GenerateForm', 'Rest', 'Alert',
'ProcessErrors', 'RelatedSearchInit', 'RelatedPaginateInit', 'Prompt',
'ClearScope', 'GetBasePath', 'Wait', '$state',
function($scope, $rootScope, $compile, $location, $log,
$stateParams, OrganizationForm, GenerateForm, Rest, Alert, ProcessErrors,
RelatedSearchInit, RelatedPaginateInit, Prompt, ClearScope, GetBasePath,
Wait, $state) {
ClearScope();
// Inject dynamic view
var form = OrganizationForm,
generator = GenerateForm,
defaultUrl = GetBasePath('organizations'),
base = $location.path().replace(/^\//, '').split('/')[0],
master = {},
id = $stateParams.organization_id,
relatedSets = {};
$scope.$emit("HideOrgListHeader");
$scope.$emit("ReloadOrganzationCards", id);
$scope.organization_id = id;
generator.inject(form, { mode: 'edit', related: true, scope: $scope});
generator.reset();
// After the Organization is loaded, retrieve each related set
if ($scope.organizationLoadedRemove) {
$scope.organizationLoadedRemove();
}
$scope.organizationLoadedRemove = $scope.$on('organizationLoaded', function () {
for (var set in relatedSets) {
$scope.search(relatedSets[set].iterator);
}
Wait('stop');
});
// Retrieve detail record and prepopulate the form
Wait('start');
Rest.setUrl(defaultUrl + id + '/');
Rest.get()
.success(function (data) {
var fld, related, set;
$scope.organization_name = data.name;
for (fld in form.fields) {
if (data[fld]) {
$scope[fld] = data[fld];
master[fld] = data[fld];
}
}
related = data.related;
for (set in form.related) {
if (related[set]) {
relatedSets[set] = {
url: related[set],
iterator: form.related[set].iterator
};
}
}
// Initialize related search functions. Doing it here to make sure relatedSets object is populated.
RelatedSearchInit({ scope: $scope, form: form, relatedSets: relatedSets });
RelatedPaginateInit({ scope: $scope, relatedSets: relatedSets });
$scope.$emit('organizationLoaded');
})
.error(function (data, status) {
ProcessErrors($scope, data, status, form, { hdr: 'Error!',
msg: 'Failed to retrieve organization: ' + $stateParams.id + '. GET status: ' + status });
});
// Save changes to the parent
$scope.formSave = function () {
var fld, params = {};
generator.clearApiErrors();
Wait('start');
for (fld in form.fields) {
params[fld] = $scope[fld];
}
Rest.setUrl(defaultUrl + id + '/');
Rest.put(params)
.success(function (data) {
Wait('stop');
$scope.organization_name = $scope.name;
master = params;
$rootScope.flashMessage = "Your changes were successfully saved!";
$scope.$emit("ReloadOrganzationCards", data.id);
})
.error(function (data, status) {
ProcessErrors($scope, data, status, OrganizationForm, { hdr: 'Error!',
msg: 'Failed to update organization: ' + id + '. PUT status: ' + status });
});
};
$scope.formCancel = function () {
$scope.$emit("ReloadOrganzationCards");
$scope.$emit("ShowOrgListHeader");
$state.transitionTo('organizations');
};
// Related set: Add button
$scope.add = function (set) {
$rootScope.flashMessage = null;
$location.path('/' + base + '/' + $stateParams.organization_id + '/' + set);
};
// Related set: Edit button
$scope.edit = function (set, id) {
$rootScope.flashMessage = null;
$location.path('/' + set + '/' + id);
};
// Related set: Delete button
$scope['delete'] = function (set, itm_id, name, title) {
$rootScope.flashMessage = null;
var action = function () {
Wait('start');
var url = defaultUrl + $stateParams.organization_id + '/' + set + '/';
Rest.setUrl(url);
Rest.post({ id: itm_id, disassociate: 1 })
.success(function () {
$('#prompt-modal').modal('hide');
$scope.search(form.related[set].iterator);
})
.error(function (data, status) {
$('#prompt-modal').modal('hide');
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
msg: 'Call to ' + url + ' failed. POST returned status: ' + status });
});
};
Prompt({
hdr: 'Delete',
body: '<div class="Prompt-bodyQuery">Are you sure you want to remove the ' + title + ' below from ' + $scope.name + '?</div><div class="Prompt-bodyTarget">' + name + '</div>',
action: action,
actionText: 'DELETE'
});
};
}
]

View File

@ -0,0 +1,29 @@
/*************************************************
* Copyright (c) 2016 Ansible, Inc.
*
* All Rights Reserved
*************************************************/
import {
templateUrl
} from '../../shared/template-url/template-url.factory';
import OrganizationsEdit from './organizations-edit.controller';
export default {
name: 'organizations.edit',
route: '/:organization_id',
templateUrl: templateUrl('organizations/add/organizations-add'),
controller: OrganizationsEdit,
data: {
activityStreamId: 'organization_id'
},
ncyBreadcrumb: {
parent: "organizations",
label: "{{name}}"
},
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
};

View File

@ -0,0 +1,14 @@
/*************************************************
* Copyright (c) 2015 Ansible, Inc.
*
* All Rights Reserved
*************************************************/
import route from './organizations-list.route';
import controller from './organizations-list.controller';
export default
angular.module('organizationsList', [])
.run(['$stateExtender', function($stateExtender) {
$stateExtender.addState(route);
}]);

View File

@ -0,0 +1,188 @@
/*************************************************
* Copyright (c) 2016 Ansible, Inc.
*
* All Rights Reserved
*************************************************/
export default ['$stateParams', '$scope', '$rootScope', '$location',
'$log', '$compile', 'Rest', 'PaginateWidget', 'PaginateInit',
'SearchInit', 'OrganizationList', 'Alert', 'Prompt', 'ClearScope',
'ProcessErrors', 'GetBasePath', 'Wait',
'$state',
function($stateParams, $scope, $rootScope, $location,
$log, $compile, Rest, PaginateWidget, PaginateInit,
SearchInit, OrganizationList, Alert, Prompt, ClearScope,
ProcessErrors, GetBasePath, Wait,
$state) {
ClearScope();
var defaultUrl = GetBasePath('organizations'),
list = OrganizationList,
pageSize = $scope.orgCount;
PaginateInit({
scope: $scope,
list: list,
url: defaultUrl,
pageSize: pageSize,
});
SearchInit({
scope: $scope,
list: list,
url: defaultUrl,
});
$scope.search(list.iterator);
$scope.PaginateWidget = PaginateWidget({
iterator: list.iterator,
set: 'organizations'
});
var paginationContainer = $('#pagination-container');
paginationContainer.html($scope.PaginateWidget);
$compile(paginationContainer.contents())($scope)
var parseCardData = function(cards) {
return cards.map(function(card) {
var val = {};
val.name = card.name;
val.id = card.id;
if (card.id + "" === cards.activeCard) {
val.isActiveCard = true;
}
val.description = card.description || undefined;
val.links = [];
val.links.push({
href: card.related.users,
name: "USERS",
count: card.summary_fields.related_field_counts.users
});
val.links.push({
href: card.related.teams,
name: "TEAMS",
count: card.summary_fields.related_field_counts.teams
});
val.links.push({
href: card.related.inventories,
name: "INVENTORIES",
count: card.summary_fields.related_field_counts.inventories
});
val.links.push({
href: card.related.projects,
name: "PROJECTS",
count: card.summary_fields.related_field_counts.projects
});
val.links.push({
href: card.related.job_templates,
name: "JOB TEMPLATES",
count: card.summary_fields.related_field_counts.job_templates
});
val.links.push({
href: card.related.admins,
name: "ADMINS",
count: card.summary_fields.related_field_counts.admins
});
return val;
});
};
var getOrganization = function(id) {
Rest.setUrl(defaultUrl);
Rest.get()
.success(function(data) {
data.results.activeCard = id;
$scope.orgCount = data.count;
$scope.orgCards = parseCardData(data.results);
Wait("stop");
})
.error(function(data, status) {
ProcessErrors($scope, data, status, null, {
hdr: 'Error!',
msg: 'Call to ' + defaultUrl + ' failed. DELETE returned status: ' + status
});
});
};
$scope.$on("ReloadOrgListView", function() {
if ($state.$current.self.name === "organizations") {
delete $scope.activeCard;
if ($scope.orgCards) {
$scope.orgCards = $scope.orgCards.map(function(card) {
delete card.isActiveCard;
return card;
});
}
$scope.hideListHeader = false;
}
});
$scope.$on("ReloadOrganzationCards", function(e, id) {
$scope.activeCard = id;
getOrganization(id);
});
$scope.$on("HideOrgListHeader", function() {
$scope.hideListHeader = true;
});
$scope.$on("ShowOrgListHeader", function() {
$scope.hideListHeader = false;
});
getOrganization();
$rootScope.flashMessage = null;
if ($scope.removePostRefresh) {
$scope.removePostRefresh();
}
$scope.removePostRefresh = $scope.$on('PostRefresh', function() {
// Cleanup after a delete
Wait('stop');
$('#prompt-modal').modal('hide');
});
$scope.addOrganization = function() {
$state.transitionTo('organizations.add');
};
$scope.editOrganization = function(id) {
$scope.activeCard = id;
$state.transitionTo('organizations.edit', {
organization_id: id
});
};
$scope.deleteOrganization = function(id, name) {
var action = function() {
$('#prompt-modal').modal('hide');
Wait('start');
var url = defaultUrl + id + '/';
Rest.setUrl(url);
Rest.destroy()
.success(function() {
if ($state.current.name !== "organzations") {
$state.transitionTo("organizations");
}
$scope.$emit("ReloadOrganzationCards");
})
.error(function(data, status) {
ProcessErrors($scope, data, status, null, {
hdr: 'Error!',
msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status
});
});
};
Prompt({
hdr: 'Delete',
body: '<div class="Prompt-bodyQuery">Are you sure you want to delete the organization below?</div><div class="Prompt-bodyTarget">' + name + '</div>',
action: action,
actionText: 'DELETE'
});
};
}
]

View File

@ -0,0 +1,62 @@
<div class="tab-pane" id="organizations">
<div ui-view></div>
<div ng-cloak id="htmlTemplate" class="Panel" ng-hide="hideListHeader">
<div class="List-header">
<div class="List-title">
<div class="List-titleText">
organizations
</div>
<span class="badge List-titleBadge">
{{ orgCount }}
</span>
</div>
<div class="List-actions">
<button class="btn List-buttonSubmit"
aw-tool-tip="Create a new organization"
ng-click="addOrganization()">
+ ADD
</button>
</div>
</div>
</div>
<div class="OrgCards">
<div class="OrgCards-card"
ng-class="{'OrgCards-card--selected': activeCard === card.id || card.isActiveCard }"
ng-repeat="card in orgCards track by card.id">
<div class="OrgCards-header">
<h3 class="OrgCards-label">{{ card.name }}</h3>
<div class="OrgCards-actionItems">
<button class="OrgCards-actionItem
List-actionButton"
ng-class="{'List-editButton--selected': activeCard === card.id || card.isActiveCard }"
ng-click="editOrganization(card.id)">
<i class="OrgCards-actionItemIcon fa fa-pencil">
</i>
</button>
<button class="OrgCards-actionItem List-actionButton
List-actionButton--delete"
ng-click="deleteOrganization(card.id, card.name)">
<i class="OrgCards-actionItemIcon
fa fa-trash-o">
</i>
</button>
</div>
</div>
<p class="OrgCards-description">{{ card.description || "Place organization description here" }}</p>
<div class="OrgCards-links">
<div class="OrgCards-link" ng-repeat="link in card.links">
<span class="badge List-titleBadge
OrgCards-linkBadge">
{{ link.count }}
</span>
<a class="OrgCards-linkName"
ng-href="{{ link.href }}">
{{ link.name }}
</a>
</div>
</div>
</div>
</div>
<div id="pagination-container" ng-hide="organization_num_pages < 2">
</div>
</div>

View File

@ -0,0 +1,31 @@
/*************************************************
* Copyright (c) 2016 Ansible, Inc.
*
* All Rights Reserved
*************************************************/
import {templateUrl} from '../../shared/template-url/template-url.factory';
import OrganizationsList from './organizations-list.controller';
export default {
name: 'organizations',
route: '/organizations',
templateUrl: templateUrl('organizations/list/organizations-list'),
controller: OrganizationsList,
data: {
activityStream: true,
activityStreamTarget: 'organization'
},
ncyBreadcrumb: {
parent: function($scope) {
$scope.$parent.$emit("ReloadOrgListView");
return "setup";
},
label: "ORGANIZATIONS"
},
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
};

View File

@ -0,0 +1,16 @@
/*************************************************
* Copyright (c) 2016 Ansible, Inc.
*
* All Rights Reserved
*************************************************/
import organizationsList from './list/main';
import organizationsAdd from './add/main';
import organizationsEdit from './edit/main';
export default
angular.module('organizations', [
organizationsList.name,
organizationsAdd.name,
organizationsEdit.name,
]);