diff --git a/awx/ui/client/src/app.js b/awx/ui/client/src/app.js
index cbf50b22b6..a64b8c9d62 100644
--- a/awx/ui/client/src/app.js
+++ b/awx/ui/client/src/app.js
@@ -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,60 +432,60 @@ 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', {
+ // 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('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',
diff --git a/awx/ui/client/src/controllers/Organizations.js b/awx/ui/client/src/controllers/Organizations.js
deleted file mode 100644
index fb1ebecfa1..0000000000
--- a/awx/ui/client/src/controllers/Organizations.js
+++ /dev/null
@@ -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: '
Are you sure you want to delete the organization below?
' + name + '
',
- 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: 'Are you sure you want to remove the ' + title + ' below from ' + $scope.name + '?
' + name + '
',
- action: action,
- actionText: 'DELETE'
- });
-
- };
-}
-
-OrganizationsEdit.$inject = ['$scope', '$rootScope', '$compile', '$location',
- '$log', '$stateParams', 'OrganizationForm', 'GenerateForm', 'Rest', 'Alert',
- 'ProcessErrors', 'RelatedSearchInit', 'RelatedPaginateInit', 'Prompt',
- 'ClearScope', 'GetBasePath', 'Wait', '$state'
-];
\ No newline at end of file
diff --git a/awx/ui/client/src/organizations/add/main.js b/awx/ui/client/src/organizations/add/main.js
new file mode 100644
index 0000000000..27b8406e0b
--- /dev/null
+++ b/awx/ui/client/src/organizations/add/main.js
@@ -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);
+ }]);
diff --git a/awx/ui/client/src/organizations/add/organizations-add.controller.js b/awx/ui/client/src/organizations/add/organizations-add.controller.js
new file mode 100644
index 0000000000..00c7ad9579
--- /dev/null
+++ b/awx/ui/client/src/organizations/add/organizations-add.controller.js
@@ -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');
+ };
+ }
+]
diff --git a/awx/ui/client/src/organizations/add/organizations-add.partial.html b/awx/ui/client/src/organizations/add/organizations-add.partial.html
new file mode 100644
index 0000000000..5db1583d13
--- /dev/null
+++ b/awx/ui/client/src/organizations/add/organizations-add.partial.html
@@ -0,0 +1,4 @@
+
diff --git a/awx/ui/client/src/organizations/add/organizations-add.route.js b/awx/ui/client/src/organizations/add/organizations-add.route.js
new file mode 100644
index 0000000000..9deab323b7
--- /dev/null
+++ b/awx/ui/client/src/organizations/add/organizations-add.route.js
@@ -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();
+ }]
+ }
+};
diff --git a/awx/ui/client/src/organizations/edit/main.js b/awx/ui/client/src/organizations/edit/main.js
new file mode 100644
index 0000000000..8f2a825df9
--- /dev/null
+++ b/awx/ui/client/src/organizations/edit/main.js
@@ -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);
+ }]);
diff --git a/awx/ui/client/src/organizations/edit/organizations-edit.controller.js b/awx/ui/client/src/organizations/edit/organizations-edit.controller.js
new file mode 100644
index 0000000000..f9178a1fb1
--- /dev/null
+++ b/awx/ui/client/src/organizations/edit/organizations-edit.controller.js
@@ -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: 'Are you sure you want to remove the ' + title + ' below from ' + $scope.name + '?
' + name + '
',
+ action: action,
+ actionText: 'DELETE'
+ });
+
+ };
+}
+]
diff --git a/awx/ui/client/src/organizations/edit/organizations-edit.route.js b/awx/ui/client/src/organizations/edit/organizations-edit.route.js
new file mode 100644
index 0000000000..ad546e71cc
--- /dev/null
+++ b/awx/ui/client/src/organizations/edit/organizations-edit.route.js
@@ -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();
+ }]
+ }
+};
diff --git a/awx/ui/client/src/organizations/list/main.js b/awx/ui/client/src/organizations/list/main.js
new file mode 100644
index 0000000000..0250a5f5f8
--- /dev/null
+++ b/awx/ui/client/src/organizations/list/main.js
@@ -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);
+ }]);
diff --git a/awx/ui/client/src/organizations/list/organizations-list.controller.js b/awx/ui/client/src/organizations/list/organizations-list.controller.js
new file mode 100644
index 0000000000..2a21b03ffb
--- /dev/null
+++ b/awx/ui/client/src/organizations/list/organizations-list.controller.js
@@ -0,0 +1,182 @@
+/*************************************************
+ * 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"
+ });
+ 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: 'Are you sure you want to delete the organization below?
' + name + '
',
+ action: action,
+ actionText: 'DELETE'
+ });
+ };
+ }
+]
diff --git a/awx/ui/client/src/organizations/list/organizations-list.partial.html b/awx/ui/client/src/organizations/list/organizations-list.partial.html
new file mode 100644
index 0000000000..b6d531897a
--- /dev/null
+++ b/awx/ui/client/src/organizations/list/organizations-list.partial.html
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
{{ card.description || "Place organization description here" }}
+
+
+
+
+
diff --git a/awx/ui/client/src/organizations/list/organizations-list.route.js b/awx/ui/client/src/organizations/list/organizations-list.route.js
new file mode 100644
index 0000000000..a97b939c01
--- /dev/null
+++ b/awx/ui/client/src/organizations/list/organizations-list.route.js
@@ -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();
+ }]
+ }
+};
diff --git a/awx/ui/client/src/organizations/main.js b/awx/ui/client/src/organizations/main.js
new file mode 100644
index 0000000000..b846961f8d
--- /dev/null
+++ b/awx/ui/client/src/organizations/main.js
@@ -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,
+]);