org cards implementation with rollups

This commit is contained in:
John Mitchell
2016-01-20 15:55:31 -05:00
parent c8d7778ed5
commit 3cee94c1e9
8 changed files with 221 additions and 39 deletions

View File

@@ -27,6 +27,7 @@
font-weight: bold; font-weight: bold;
white-space: nowrap; white-space: nowrap;
padding-bottom: 20px; padding-bottom: 20px;
min-height: 40px;
} }
.Form-title--is_superuser{ .Form-title--is_superuser{
@@ -69,6 +70,7 @@
.Form-tabHolder{ .Form-tabHolder{
display: flex; display: flex;
margin-bottom: 20px; margin-bottom: 20px;
min-height: 30px;
} }
.Form-tab { .Form-tab {

View File

@@ -569,9 +569,14 @@ var tower = angular.module('Tower', [
} }
}). }).
state('organizations.cards', {
url: '/foo',
templateUrl: urlPrefix + 'organizations/cards.partial.html',
}).
state('organizations.add', { state('organizations.add', {
url: '/add', url: '/add',
templateUrl: urlPrefix + 'partials/organizations.html', templateUrl: urlPrefix + 'partials/organizations.crud.html',
controller: OrganizationsAdd, controller: OrganizationsAdd,
ncyBreadcrumb: { ncyBreadcrumb: {
parent: "organizations", parent: "organizations",
@@ -586,7 +591,7 @@ var tower = angular.module('Tower', [
state('organizations.edit', { state('organizations.edit', {
url: '/:organization_id', url: '/:organization_id',
templateUrl: urlPrefix + 'partials/organizations.html', templateUrl: urlPrefix + 'partials/organizations.crud.html',
controller: OrganizationsEdit, controller: OrganizationsEdit,
resolve: { resolve: {
features: ['FeaturesService', function(FeaturesService) { features: ['FeaturesService', function(FeaturesService) {

View File

@@ -12,27 +12,58 @@
export function OrganizationsList($stateParams, $scope, $rootScope, $location, export function OrganizationsList($stateParams, $scope, $rootScope, $location,
$log, Rest, Alert, Prompt, GenerateList, OrganizationList, SearchInit, $log, Rest, Alert, Prompt, ClearScope, ProcessErrors, GetBasePath, Wait,
PaginateInit, ClearScope, ProcessErrors, GetBasePath, SelectionInit, Wait,
Stream, $state) { Stream, $state) {
ClearScope(); ClearScope();
var list = OrganizationList, var defaultUrl = GetBasePath('organizations');
generate = GenerateList,
paths = $location.path().replace(/^\//, '').split('/'), var parseCardData = function (cards) {
mode = (paths[0] === 'organizations') ? 'edit' : 'select', return cards.map(function (card) {
defaultUrl = GetBasePath('organizations'), var val = {};
url; val.name = card.name;
val.id = card.id;
if (card.id + "" === cards.activeCard) {
val.isActiveCard = true;
}
val.description = card.description || undefined;
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("ReloadOrganzationCards", function(e, id) {
$scope.activeCard = id;
getOrganization(id);
});
$scope.$on("HideOrgListHeader", function() {
$scope.hideListHeader = true;
});
$scope.$on("ShowOrgListHeader", function() {
$scope.hideListHeader = false;
});
getOrganization();
generate.inject(OrganizationList, { mode: mode, scope: $scope });
$rootScope.flashMessage = null; $rootScope.flashMessage = null;
if (mode === 'select') {
url = GetBasePath('projects') + $stateParams.project_id + '/organizations/';
SelectionInit({ scope: $scope, list: list, url: url, returnToCaller: 1 });
}
if ($scope.removePostRefresh) { if ($scope.removePostRefresh) {
$scope.removePostRefresh(); $scope.removePostRefresh();
} }
@@ -42,20 +73,6 @@ export function OrganizationsList($stateParams, $scope, $rootScope, $location,
$('#prompt-modal').modal('hide'); $('#prompt-modal').modal('hide');
}); });
// Initialize search and pagination, then load data
SearchInit({
scope: $scope,
set: list.name,
list: list,
url: defaultUrl
});
PaginateInit({
scope: $scope,
list: list,
url: defaultUrl
});
$scope.search(list.iterator);
$scope.showActivity = function () { $scope.showActivity = function () {
Stream({ scope: $scope }); Stream({ scope: $scope });
}; };
@@ -65,6 +82,7 @@ export function OrganizationsList($stateParams, $scope, $rootScope, $location,
}; };
$scope.editOrganization = function (id) { $scope.editOrganization = function (id) {
$scope.activeCard = id;
$state.transitionTo('organizations.edit', {organization_id: id}); $state.transitionTo('organizations.edit', {organization_id: id});
}; };
@@ -77,7 +95,10 @@ export function OrganizationsList($stateParams, $scope, $rootScope, $location,
Rest.setUrl(url); Rest.setUrl(url);
Rest.destroy() Rest.destroy()
.success(function () { .success(function () {
$scope.search(list.iterator); if ($state.current.name !== "organzations") {
$state.transitionTo("organizations");
}
$scope.$emit("ReloadOrganzationCards");
}) })
.error(function (data, status) { .error(function (data, status) {
ProcessErrors($scope, data, status, null, { hdr: 'Error!', ProcessErrors($scope, data, status, null, { hdr: 'Error!',
@@ -94,9 +115,8 @@ export function OrganizationsList($stateParams, $scope, $rootScope, $location,
} }
OrganizationsList.$inject = ['$stateParams', '$scope', '$rootScope', OrganizationsList.$inject = ['$stateParams', '$scope', '$rootScope',
'$location', '$log', 'Rest', 'Alert', 'Prompt', 'generateList', '$location', '$log', 'Rest', 'Alert', 'Prompt', 'ClearScope',
'OrganizationList', 'SearchInit', 'PaginateInit', 'ClearScope', 'ProcessErrors', 'GetBasePath', 'Wait',
'ProcessErrors', 'GetBasePath', 'SelectionInit', 'Wait',
'Stream', '$state' 'Stream', '$state'
]; ];
@@ -115,6 +135,8 @@ export function OrganizationsAdd($scope, $rootScope, $compile, $location, $log,
generator.inject(form, { mode: 'add', related: false, scope: $scope}); generator.inject(form, { mode: 'add', related: false, scope: $scope});
generator.reset(); generator.reset();
$scope.$emit("HideOrgListHeader");
// Save // Save
$scope.formSave = function () { $scope.formSave = function () {
generator.clearApiErrors(); generator.clearApiErrors();
@@ -125,6 +147,7 @@ export function OrganizationsAdd($scope, $rootScope, $compile, $location, $log,
Rest.post({ name: $scope.name, description: $scope.description }) Rest.post({ name: $scope.name, description: $scope.description })
.success(function (data) { .success(function (data) {
Wait('stop'); Wait('stop');
$scope.$emit("ReloadOrganzationCards", data.id);
if (base === 'organizations') { if (base === 'organizations') {
$rootScope.flashMessage = "New organization successfully created!"; $rootScope.flashMessage = "New organization successfully created!";
$location.path('/organizations/' + data.id); $location.path('/organizations/' + data.id);
@@ -139,6 +162,8 @@ export function OrganizationsAdd($scope, $rootScope, $compile, $location, $log,
}; };
$scope.formCancel = function () { $scope.formCancel = function () {
$scope.$emit("ReloadOrganzationCards");
$scope.$emit("ShowOrgListHeader");
$state.transitionTo('organizations'); $state.transitionTo('organizations');
}; };
} }
@@ -166,6 +191,10 @@ export function OrganizationsEdit($scope, $rootScope, $compile, $location, $log,
id = $stateParams.organization_id, id = $stateParams.organization_id,
relatedSets = {}; relatedSets = {};
$scope.$emit("HideOrgListHeader");
$scope.$emit("ReloadOrganzationCards", id);
$scope.organization_id = id; $scope.organization_id = id;
generator.inject(form, { mode: 'edit', related: true, scope: $scope}); generator.inject(form, { mode: 'edit', related: true, scope: $scope});
@@ -225,11 +254,12 @@ export function OrganizationsEdit($scope, $rootScope, $compile, $location, $log,
} }
Rest.setUrl(defaultUrl + id + '/'); Rest.setUrl(defaultUrl + id + '/');
Rest.put(params) Rest.put(params)
.success(function () { .success(function (data) {
Wait('stop'); Wait('stop');
$scope.organization_name = $scope.name; $scope.organization_name = $scope.name;
master = params; master = params;
$rootScope.flashMessage = "Your changes were successfully saved!"; $rootScope.flashMessage = "Your changes were successfully saved!";
$scope.$emit("ReloadOrganzationCards", data.id);
}) })
.error(function (data, status) { .error(function (data, status) {
ProcessErrors($scope, data, status, OrganizationForm, { hdr: 'Error!', ProcessErrors($scope, data, status, OrganizationForm, { hdr: 'Error!',
@@ -244,6 +274,8 @@ export function OrganizationsEdit($scope, $rootScope, $compile, $location, $log,
}; };
$scope.formCancel = function () { $scope.formCancel = function () {
$scope.$emit("ReloadOrganzationCards");
$scope.$emit("ShowOrgListHeader");
$state.transitionTo('organizations'); $state.transitionTo('organizations');
}; };

View File

@@ -82,8 +82,6 @@ export default
scope.getPage(currentPage, set, iterator); scope.getPage(currentPage, set, iterator);
}); });
} else if ($location.$$url.split("/")[1] === params.set && $location.$$url.split("/")[2] && $location.$$url.split("/")[2] !== "add" && !scope.getNewPage) { } else if ($location.$$url.split("/")[1] === params.set && $location.$$url.split("/")[2] && $location.$$url.split("/")[2] !== "add" && !scope.getNewPage) {
delete $rootScope.rowBeingEdited;
delete $rootScope.listBeingEdited;
var id = $location.$$url.split("/")[2]; var id = $location.$$url.split("/")[2];
var restUrl = params.url.split("?")[0]; var restUrl = params.url.split("?")[0];
var pageSize = scope[iterator + '_page_size']; var pageSize = scope[iterator + '_page_size'];

View File

@@ -0,0 +1,98 @@
/** @define OrgCards */
.OrgCards {
display: flex;
flex-wrap: wrap;
}
.OrgCards-card {
background-color: #fff;
padding: 20px;
border-radius: 5px;
border: 1px solid #e8e8e8;
display: flex;
flex-wrap: wrap;
align-items: baseline;
margin-top: 20px;
}
.OrgCards-card--selected {
padding-left: 16px;
border-left: 5px solid #1678C4;
}
.OrgCards-header {
display: flex;
flex-wrap: nowrap;
align-items: baseline;
width: 100%;
}
.OrgCards-label {
margin-top: 0px;
text-transform: uppercase;
font-size: 14px;
font-weight: bold;
color: #848992;
margin-bottom: 25px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.OrgCards-actionItems {
margin-left: auto;
display: flex;
flex-wrap: nowrap;
}
.OrgCards-actionItem {
margin-left: 15px;
}
.OrgCards-description {
margin-bottom: 0px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
@media (min-width: 1179px) {
.OrgCards-card {
width: ~"calc(25% - 15px)";
margin-right: 20px;
}
.OrgCards-card:nth-child(4n+4) {
margin-right: 0px;
}
}
@media (min-width: 901px) and (max-width: 1178px) {
.OrgCards-card {
width: ~"calc(33% - 11px)";
margin-right: 20px;
}
.OrgCards-card:nth-child(3n+3) {
margin-right: 0px;
}
}
@media (min-width: 616px) and (max-width: 900px) {
.OrgCards-card {
width: ~"calc(50% - 10px)";
margin-right: 20px;
}
.OrgCards-card:nth-child(2n+2) {
margin-right: 0px;
}
}
@media (max-width: 615px) {
.OrgCards-card {
width: 100%;
margin-right: 0px;
}
}

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

@@ -1,4 +1,47 @@
<div class="tab-pane" id="organizations"> <div class="tab-pane" id="organizations">
<div ui-view></div> <div ui-view></div>
<div ng-cloak id="htmlTemplate" class="Panel"></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-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>
</div>
</div> </div>

View File

@@ -53,7 +53,7 @@
@list-pagin-bord-act: @default-icon-hov; @list-pagin-bord-act: @default-icon-hov;
@list-pagin-bg-act: @default-icon-hov; @list-pagin-bg-act: @default-icon-hov;
@list-title-txt: @default-interface-txt; @list-title-txt: @default-interface-txt;
@list-title-badge: @default-icon-hov; @list-title-badge: @default-icon;
@list-srch-inpt-bg: @default-secondary-bg; @list-srch-inpt-bg: @default-secondary-bg;
@list-srch-inpt-txt: @default-data-txt; @list-srch-inpt-txt: @default-data-txt;
@list-srch-inpt-ph-txt: @default-icon; @list-srch-inpt-ph-txt: @default-icon;