AC-331 Separated 'expand/collapse' function from 'select' function on Hosts tab tree. It now functions more like the Gmail label tree. Added Wait() utiltiy that can be used to freeze the API during longer than usual API operations. Using it on the 'group move' function.

This commit is contained in:
chouseknecht 2013-08-16 01:15:02 -04:00
parent 9729c6d203
commit 036352f10e
8 changed files with 377 additions and 261 deletions

View File

@ -216,7 +216,6 @@ function InventoriesEdit ($scope, $rootScope, $compile, $location, $log, $routeP
LoadInventory({ scope: scope, doPostSteps: true });
$('#inventory-tabs a[href="#inventory-hosts"]').on('show.bs.tab', function() {
LoadSearchTree({ scope: scope, inventory_id: scope['inventory_id'] });
HostsReload({ scope: scope, inventory_id: scope['inventory_id'], group_id: scope['group_id'] });
if (!scope.$$phase) {
scope.$digest();
}
@ -382,10 +381,10 @@ function InventoriesEdit ($scope, $rootScope, $compile, $location, $log, $routeP
scope.inventoryEditHide = true;
scope.groupDeleteHide = false;
scope.createButtonShow = true;
scope.group_id = node.attr('group_id');
scope.groupName = n.data;
scope.groupTitle = '<h4>' + n.data + '</h4>';
scope.groupTitle += (node.attr('description')) ? '<p>' + node.attr('description') + '</p>' : '';
//scope.group_id = node.attr('group_id');
//scope.groupName = n.data;
//scope.groupTitle = '<h4>' + n.data + '</h4>';
//scope.groupTitle += (node.attr('description')) ? '<p>' + node.attr('description') + '</p>' : '';
}
else if (type == 'inventory') {
url = node.attr('hosts');
@ -395,9 +394,9 @@ function InventoriesEdit ($scope, $rootScope, $compile, $location, $log, $routeP
scope.inventoryEditHide=false;
scope.groupDeleteHide = true;
scope.createButtonShow = false;
scope.groupName = 'All Hosts';
scope.groupTitle = '<h4>All Hosts</h4>';
scope.group_id = null;
//scope.groupName = 'All Hosts';
//scope.groupTitle = '<h4>All Hosts</h4>';
//scope.group_id = null;
}
if (!scope.$$phase) {
@ -460,11 +459,12 @@ function InventoriesEdit ($scope, $rootScope, $compile, $location, $log, $routeP
});
}
scope.showHosts = function(e) {
console.log('here');
var elm = angular.elment(e.srcElement);
console.log('Need to show hosts: ' + elm.attr('data-hosts'));
}
// Respond to the scope.$emit from awTree directive
scope.$on('refreshHost', function(e, group, title) {
scope.groupTitle = title;
scope.group_id = group;
HostsReload({ scope: scope, inventory_id: scope['inventory_id'], group_id: group });
});
}

View File

@ -12,7 +12,7 @@
function OrganizationsList ($routeParams, $scope, $rootScope, $location, $log, Rest, Alert, LoadBreadCrumbs, Prompt,
GenerateList, OrganizationList, SearchInit, PaginateInit, ClearScope, ProcessErrors,
GetBasePath, SelectionInit)
GetBasePath, SelectionInit, Wait)
{
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
@ -70,7 +70,7 @@ function OrganizationsList ($routeParams, $scope, $rootScope, $location, $log, R
OrganizationsList.$inject=[ '$routeParams', '$scope', '$rootScope', '$location', '$log', 'Rest', 'Alert', 'LoadBreadCrumbs', 'Prompt',
'GenerateList', 'OrganizationList', 'SearchInit', 'PaginateInit', 'ClearScope', 'ProcessErrors',
'GetBasePath', 'SelectionInit' ];
'GetBasePath', 'SelectionInit', 'Wait' ];
function OrganizationsAdd ($scope, $rootScope, $compile, $location, $log, $routeParams, OrganizationForm,

View File

@ -410,10 +410,12 @@ angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'H
function(RelatedSearchInit, RelatedPaginateInit, InventoryForm, GetBasePath) {
return function(params) {
// Rerfresh the Hosts view on right side of page
scope = params.scope;
var group_id = params.group_id;
var scope = params.scope;
scope['hosts'] = null;
var url = (scope.group_id !== null && scope.group_id !== undefined) ? GetBasePath('groups') + scope.group_id + '/all_hosts/' :
var url = (group_id !== null && group_id !== undefined) ? GetBasePath('groups') + group_id + '/all_hosts/' :
GetBasePath('inventory') + params.inventory_id + '/hosts/';
var relatedSets = { hosts: { url: url, iterator: 'host' } };

View File

@ -100,8 +100,8 @@ angular.module('InventoryHelper', [ 'RestServices', 'Utilities', 'OrganizationLi
}])
.factory('TreeInit', ['Alert', 'Rest', 'Authorization', '$http', 'LoadTreeData', 'GetBasePath', 'ProcessErrors',
function(Alert, Rest, Authorization, $http, LoadTreeData, GetBasePath, ProcessErrors) {
.factory('TreeInit', ['Alert', 'Rest', 'Authorization', '$http', 'LoadTreeData', 'GetBasePath', 'ProcessErrors', 'Wait',
function(Alert, Rest, Authorization, $http, LoadTreeData, GetBasePath, ProcessErrors, Wait) {
return function(params) {
var scope = params.scope;
@ -200,6 +200,7 @@ angular.module('InventoryHelper', [ 'RestServices', 'Utilities', 'OrganizationLi
$(tree_id).bind('move_node.jstree', function(e, data) {
// When user drags-n-drops a node, update the API
Wait('start');
var node, target, url, parent, inv_id, variables;
node = $('#tree-view li[id="' + data.rslt.o[0].id + '"]'); // node being moved
parent = $('#tree-view li[id="' + data.args[0].op[0].id + '"]'); //node moving from
@ -214,9 +215,7 @@ angular.module('InventoryHelper', [ 'RestServices', 'Utilities', 'OrganizationLi
function showSuccessMsg() {
var parent_descr = (parent.attr('type') == 'inventory') ? 'the inventory root' : parent.attr('name');
var target_descr = (target.attr('type') == 'inventory') ? 'the inventory root' : target.attr('name');
Alert('Group Moved', 'Group ' + node.attr('name') + ' was successfully moved from ' + parent_descr +
' to ' + target_descr + '.', 'alert-success');
scope['treeLoading'] = false;
Wait('stop');
if (!scope.$$phase) {
scope.$digest();
}
@ -302,7 +301,7 @@ angular.module('InventoryHelper', [ 'RestServices', 'Utilities', 'OrganizationLi
'. GET returned status: ' + status });
});
scope['treeLoading'] = true;
//scope['treeLoading'] = true;
if (!scope.$$phase) {
scope.$digest();

View File

@ -24,6 +24,35 @@ body {
color: @black;
}
.spinny {
display: none;
position: absolute;
z-index: 2000;
width: 75px;
height: 75px;
text-align:center;
color: #eee;
background-color: @black;
border: 1px solid @grey;
border-radius: 6px;
padding-top: 10px;
p {
padding-top: 10px;
font-size: 11px;
}
}
.overlay {
display: none;
position: absolute;
top: 0;
left: 0;
z-index: 1999;
background-color: @black;
opacity: .4;
}
.tooltip {
z-index: 1050;
}
@ -603,7 +632,7 @@ input[type="text"].job-successful {
.search-tree {
ul {
list-style-type: none;
padding-left: 10px;
padding-left: 13px;
}
ul:first-child {
padding-left: 0;
@ -611,10 +640,21 @@ input[type="text"].job-successful {
}
.search-tree .active {
background-color: #ddd;
/*background-color: #ddd;
padding: 1px 1px 1px 0;
border: 1px solid #ddd;
border-radius: 4px;
border-radius: 4px;*/
font-weight: bold;
color: #000;
}
.search-tree .expand {
padding: 3px;
}
.search-tree .expand:hover {
background-color: #ddd;
border: 1px solid #ddd;
}
.parse-selection {

View File

@ -317,8 +317,8 @@ angular.module('AWDirectives', ['RestServices', 'Utilities', 'AuthService', 'Hos
}
}])
.directive('awTree', ['Rest', 'ProcessErrors', 'Authorization', '$compile', '$rootScope', 'HostsReload',
function(Rest, ProcessErrors, Authorization, $compile, $rootScope, HostsReload) {
.directive('awTree', ['Rest', 'ProcessErrors', 'Authorization', '$compile', '$rootScope',
function(Rest, ProcessErrors, Authorization, $compile, $rootScope) {
return {
//require: 'ngModel',
@ -335,104 +335,143 @@ angular.module('AWDirectives', ['RestServices', 'Utilities', 'AuthService', 'Hos
template:
"<div class=\"search-tree well\" id=\"search-tree-container\">\n" +
"<ul>\n" +
"<li><a href=\"\" id=\"search-node-1000\" class=\"active\" data-state=\"closed\" data-hosts=\"{{ treeData[0].hosts}}\" " +
"<li id=\"search-node-1000\" data-state=\"closed\" data-hosts=\"{{ treeData[0].hosts}}\" " +
"data-hosts=\"{{ treeData[0].hosts }}\" " +
"data-description=\"{{ treeData[0].description }}\" " +
"data-failures=\"{{ treeData[0].failures }}\" " +
"data-groups=\"{{ treeData[0].groups }}\" " +
"data-name=\"{{ treeData[0].name }}\" " +
"><i class=\"icon-caret-right\"></i> {{ treeData[0].name}}</a></li>\n" +
"data-name=\"{{ treeData[0].name }}\">" +
"<a href=\"\" class=\"expand\"><i class=\"icon-caret-right\"></i></a> <a href=\"\" class=\"activate active\">{{ treeData[0].name }}</a></li>\n" +
"</li>\n"+
"</ul>\n" +
"</div>\n",
link: function(scope, elm , attrs) {
var idx=1000;
function toggle(e) {
var id = (e.target.tagName == 'I') ? e.target.parentNode.attributes.id.value : e.target.attributes.id.value;
var elm = angular.element(document.getElementById(id));
function activate() {
/* Set the clicked node as active */
$('.search-tree .active').removeClass('active');
elm.addClass('active');
var group = (elm.attr('data-group-id')) ? elm.attr('data-group-id') : null;
var parentScope = angular.element(document.getElementById('htmlTemplate')).scope();
console.log('calling for group: ' + group);
HostsReload({ scope: parentScope, inventory_id: parentScope['inventory_id'], group_id: group });
function refresh(parent) {
var group, title;
if (parent.attr('data-group-id')) {
group = parent.attr('data-group-id');
title = '<h4>' + parent.attr('data-name') + '</h4>';
title += (parent.attr('data-description') !== "") ? '<p>' + parent.attr('data-description') + '</p>' : '';
}
else {
group = null;
title = '<h4>All Hosts</h4>'
}
scope.$emit('refreshHost', group, title);
}
function activate(e) {
/* Set the clicked node as active */
var elm = angular.element(e.target); //<a>
var parent = angular.element(e.target.parentNode); //<li>
$('.search-tree .active').removeClass('active');
elm.addClass('active');
refresh(parent);
}
function toggle(e) {
var id, parent, elm, icon;
if (e.target.tagName == 'I') {
id = e.target.parentNode.parentNode.attributes.id.value;
parent = angular.element(e.target.parentNode.parentNode); //<li>
elm = angular.element(e.target.parentNode); // <a>
}
else {
id = e.target.parentNode.attributes.id.value;
parent = angular.element(e.target.parentNode);
elm = angular.element(e.target);
}
var sibling = angular.element(parent.children()[1]); // <a>
var state = parent.attr('data-state');
var icon = angular.element(elm.children()[0]);
/* Open/close the node and expand */
if (scope.childrenLoadedRemove) {
scope.childrenLoadedRemove();
}
scope.childrenLoadedRemove = scope.$on('childrenLoaded', function() {
childlists = elm.parent().find('ul'); //look for children
childlists = parent.find('ul'); //look for children
if (childlists && childlists.length > 0) {
// bind toggle() to click event of each link in the group we clicked on
var parent = angular.element(elm.parent()[0]);
var links = parent.find('a');
for (var i=0; i < links.length; i++) {
var link = angular.element(links[i]);
link.unbind('click', toggle);
link.bind('click', toggle);
if (link.hasClass('expand')) {
link.unbind('click', toggle);
link.bind('click', toggle);
}
if (link.hasClass('activate')) {
link.unbind('click', activate);
link.bind('click', activate);
}
}
toggle(e);
}
else {
var icon = angular.element(elm.children()[0]);
icon.removeClass('icon-caret-down').removeClass('icon-caret-right').addClass('icon-ellipsis-horizontal');
icon.removeClass('icon-caret-right').addClass('icon-caret-down');
//activate(e);
}
});
if (elm.attr('data-state') == 'closed') {
if (state == 'closed') {
// expand the elment
var childlists = elm.parent().find('ul');
var childlists = parent.find('ul');
if (childlists && childlists.length > 0) {
// already has childen
for (var i=0; i < childlists.length; i++) {
var listChild = angular.element(childlists[i]);
var listParent = angular.element(listChild.parent().find('a')[0]);
if (listParent.attr('id') == elm.attr('id')) {
var listParent = angular.element(listChild.parent());
if (listParent.attr('id') == id) {
angular.element(childlists[i]).removeClass('hidden');
}
// all the children should be in a closed state
var aList = listChild.find('a');
for (var j=0; j < aList.length; j++) {
var thisList = angular.element(aList[j]);
var liList = listChild.find('li');
for (var j=0; j < liList.length; j++) {
var thisList = angular.element(liList[j]);
var anchor = angular.element(thisList.find('a')[0]);
var thisIcon = angular.element(anchor.children()[0]);
thisIcon.removeClass('icon-caret-down').addClass('icon-caret-right');
thisList.attr('data-state', 'closed');
var icon = angular.element(thisList.children()[0]);
icon.removeClass('icon-caret-down').removeClass('icon-ellipsis-horizontal').addClass('icon-caret-right');
}
}
elm.attr('data-state','open');
var icon = angular.element(elm.children()[0]);
icon.removeClass('icon-caret-right').removeClass('icon-ellipsis-horizontal').addClass('icon-caret-down');
activate();
parent.attr('data-state','open');
icon.removeClass('icon-caret-right').addClass('icon-caret-down');
}
else {
getChildren(elm);
getChildren(elm, parent, sibling);
}
}
else {
// close the element
elm.attr('data-state','closed');
parent.attr('data-state','closed');
var icon = angular.element(elm.children()[0]);
icon.removeClass('icon-caret-down').removeClass('icon-ellipsis-horizontal').addClass('icon-caret-right');
var childlists = elm.parent().find('ul');
icon.removeClass('icon-caret-down').addClass('icon-caret-right');
var childlists = parent.find('ul');
if (childlists && childlists.length > 0) {
// has childen
for (var i=0; i < childlists.length; i++) {
angular.element(childlists[i]).addClass('hidden');
}
}
activate();
/* When the active node's parent is closed, activate the parent*/
if ($(parent).find('.active').length > 0) {
$(parent).find('.active').removeClass('active');
sibling.addClass('active');
refresh(parent);
}
}
}
}
function getChildren(elm) {
var url = elm.attr('data-groups');
function getChildren(elm, parent, sibling) {
var url = parent.attr('data-groups');
var html = '';
var token = Authorization.getToken();
/* For reasons unknown calling Rest fails. It just dies with no errors
@ -445,23 +484,21 @@ angular.module('AWDirectives', ['RestServices', 'Utilities', 'AuthService', 'Hos
// build html and append to parent of clicked link
for (var i=0; i < data.results.length; i++) {
idx++;
html += "<li>\n";
html += "<a href=\"\" data-state=\"closed\" ";
html += "<li ";
html += "id=\"search-tree-" + idx +"\" ";
html += "date-state=\"closed\" ";
html += "data-hosts=\"" + data.results[i].related.all_hosts + "\" ";
html += "data-description=\"" + data.results[i].description + "\" ";
html += "data-failures=\"" +data.results[i].has_active_failures + "\" ";
html += "data-groups=\"" + data.results[i].related.children + "\" ";
html += "data-name=\"" + data.results[i].name + "\" ";
html += "data-group-id=\"" + data.results[i].id + "\" ";
html += "><i class=\"icon-caret-right\"></i> " + data.results[i].name;
html += "</a></li>\n";
html += "data-group-id=\"" + data.results[i].id + "\">";
html += "<a href=\"\" class=\"expand\"><i class=\"icon-caret-right\"></i></a> ";
html += "<a href=\"\" class=\"activate\">" + data.results[i].name + "</a></li>\n";
}
html = (html !== '') ? "<ul>" + html + "</ul>\n" : "";
var parent = angular.element(elm.parent()[0]);
var compiled = $compile(html)(scope);
parent.append(compiled); //append the new list to the parent <li>
console.log('childrenLoaded');
scope.$emit('childrenLoaded');
},
error: function(data, status) {
@ -474,7 +511,10 @@ angular.module('AWDirectives', ['RestServices', 'Utilities', 'AuthService', 'Hos
function initialize() {
var root = angular.element(document.getElementById('search-node-1000'));
root.bind('click', toggle);
var toggleElm = angular.element(root.find('a')[0]);
var activateElm = angular.element(root.find('a')[1])
toggleElm.bind('click', toggle);
activateElm.bind('click', activate);
}
if ($rootScope.hostTabInitRemove) {
@ -484,18 +524,23 @@ angular.module('AWDirectives', ['RestServices', 'Utilities', 'AuthService', 'Hos
var container = angular.element(document.getElementById('search-tree-container'));
container.empty();
var html = "<ul>\n" +
"<li><a href=\"\" id=\"search-node-1000\" class=\"active\" data-state=\"closed\" data-hosts=\"{{ treeData[0].hosts}}\" " +
"<li id=\"search-node-1000\" data-state=\"closed\" data-hosts=\"{{ treeData[0].hosts}}\" " +
"data-hosts=\"{{ treeData[0].hosts }}\" " +
"data-description=\"{{ treeData[0].description }}\" " +
"data-failures=\"{{ treeData[0].failures }}\" " +
"data-groups=\"{{ treeData[0].groups }}\" " +
"data-name=\"{{ treeData[0].name }}\" " +
"><i class=\"icon-caret-right\"></i> {{ treeData[0].name }}</a></li>\n" +
"><a href=\"\" class=\"expand\"><i class=\"icon-caret-right\"></i></a> <a href=\"\" class=\"activate active\">{{ treeData[0].name }}</a>" +
"</li>\n" +
"</ul>\n";
var compiled = $compile(html)(scope);
container.append(compiled);
initialize();
//setTimeout(function() { $('.search-tree .active').click(); }, 1000); //click the root node, forcing level 1 nodes to appear
// Expand the root node and show All Hosts
setTimeout(function() {
$('#search-node-1000 .expand').click();
$('#search-node-1000 .activate').click();
}, 500);
});
}

View File

@ -8,206 +8,233 @@
angular.module('Utilities',[])
.factory('ClearScope', function() {
return function(id) {
var element = document.getElementById(id);
var scope = angular.element(element).scope();
scope.$destroy();
}
return function(id) {
var element = document.getElementById(id);
var scope = angular.element(element).scope();
scope.$destroy();
}
})
.factory('ToggleClass', function() {
return function(selector, cssClass) {
// Toggles the existance of a css class on a given element
if ( $(selector) && $(selector).hasClass(cssClass) ) {
$(selector).removeClass(cssClass);
}
else if ($(selector)) {
$(selector).addClass(cssClass);
}
}
return function(selector, cssClass) {
// Toggles the existance of a css class on a given element
if ( $(selector) && $(selector).hasClass(cssClass) ) {
$(selector).removeClass(cssClass);
}
else if ($(selector)) {
$(selector).addClass(cssClass);
}
}
})
.factory('Alert', ['$rootScope', '$location', function($rootScope, $location) {
return function(hdr, msg, cls, action, secondAlert, disableButtons) {
// Pass in the header and message you want displayed on TB modal dialog found in index.html.
// Assumes an #id of 'alert-modal'. Pass in an optional TB alert class (i.e. alert-danger, alert-success,
// alert-info...). Pass an optional function(){}, if you want a specific action to occur when user
// clicks 'OK' button. Set secondAlert to true, when a second dialog is needed.
if (secondAlert) {
$rootScope.alertHeader2 = hdr;
$rootScope.alertBody2 = msg;
$rootScope.alertClass2 = (cls) ? cls : 'alert-danger'; //default alert class is alert-danger
$('#alert-modal2').modal({ show: true, keyboard: true , backdrop: 'static' });
$rootScope.disableButtons2 = (disableButtons) ? true : false;
if (action) {
$('#alert-modal2').on('hidden', function() {
action();
});
}
$(document).bind('keydown', function(e) {
if (e.keyCode === 27) {
$('#alert-modal2').modal('hide');
if (action) {
action();
}
}
});
}
else {
$rootScope.alertHeader = hdr;
$rootScope.alertBody = msg;
$rootScope.alertClass = (cls) ? cls : 'alert-danger'; //default alert class is alert-danger
$('#alert-modal').modal({ show: true, keyboard: true , backdrop: 'static' });
return function(hdr, msg, cls, action, secondAlert, disableButtons) {
// Pass in the header and message you want displayed on TB modal dialog found in index.html.
// Assumes an #id of 'alert-modal'. Pass in an optional TB alert class (i.e. alert-danger, alert-success,
// alert-info...). Pass an optional function(){}, if you want a specific action to occur when user
// clicks 'OK' button. Set secondAlert to true, when a second dialog is needed.
if (secondAlert) {
$rootScope.alertHeader2 = hdr;
$rootScope.alertBody2 = msg;
$rootScope.alertClass2 = (cls) ? cls : 'alert-danger'; //default alert class is alert-danger
$('#alert-modal2').modal({ show: true, keyboard: true , backdrop: 'static' });
$rootScope.disableButtons2 = (disableButtons) ? true : false;
if (action) {
$('#alert-modal2').on('hidden', function() {
action();
});
}
$(document).bind('keydown', function(e) {
if (e.keyCode === 27) {
$('#alert-modal2').modal('hide');
if (action) {
action();
}
}
});
}
else {
$rootScope.alertHeader = hdr;
$rootScope.alertBody = msg;
$rootScope.alertClass = (cls) ? cls : 'alert-danger'; //default alert class is alert-danger
$('#alert-modal').modal({ show: true, keyboard: true , backdrop: 'static' });
$(document).bind('keydown', function(e) {
if (e.keyCode === 27) {
$('#alert-modal').modal('hide');
if (action) {
action();
}
}
});
$(document).bind('keydown', function(e) {
if (e.keyCode === 27) {
$('#alert-modal').modal('hide');
if (action) {
action();
}
}
});
$rootScope.disableButtons = (disableButtons) ? true : false;
if (action) {
$('#alert-modal').on('hidden', function() {
action();
});
}
}
}
$rootScope.disableButtons = (disableButtons) ? true : false;
if (action) {
$('#alert-modal').on('hidden', function() {
action();
});
}
}
}
}])
.factory('ProcessErrors', ['$log', 'Alert', function($log, Alert) {
return function(scope, data, status, form, defaultMsg) {
if (status == 403) {
var msg = 'The API responded with a 403 Access Denied error. ';
if (data['detail']) {
msg += 'Detail: ' + data['detail'];
}
else {
msg += 'Please contact your system administrator.';
}
Alert(defaultMsg.hdr, msg);
}
else if (data.non_field_errors) {
Alert('Error!', data.non_field_errors);
}
else if (data.detail) {
Alert(defaultMsg.hdr, defaultMsg.msg + ' ' + data.detail);
}
else if (data['__all__']) {
Alert('Error!', data['__all__']);
}
else if (form) {
var fieldErrors = false;
for (var field in form.fields ) {
if (form.fields[field].realName) {
if (data[form.fields[field].realName]) {
scope[field + '_api_error'] = data[form.fields[field]][0];
fieldErrors = true;
}
}
if (form.fields[field].sourceModel) {
if (data[field]) {
scope[form.fields[field].sourceModel + '_' + form.fields[field].sourceField + '_api_error'] =
data[field][0];
fieldErrors = true;
}
}
else {
if (data[field]) {
scope[field + '_api_error'] = data[field][0];
fieldErrors = true;
}
}
}
if ( (!fieldErrors) && defaultMsg) {
Alert(defaultMsg.hdr, defaultMsg.msg);
}
}
else {
Alert(defaultMsg.hdr, defaultMsg.msg);
}
}
return function(scope, data, status, form, defaultMsg) {
if (status == 403) {
var msg = 'The API responded with a 403 Access Denied error. ';
if (data['detail']) {
msg += 'Detail: ' + data['detail'];
}
else {
msg += 'Please contact your system administrator.';
}
Alert(defaultMsg.hdr, msg);
}
else if (data.non_field_errors) {
Alert('Error!', data.non_field_errors);
}
else if (data.detail) {
Alert(defaultMsg.hdr, defaultMsg.msg + ' ' + data.detail);
}
else if (data['__all__']) {
Alert('Error!', data['__all__']);
}
else if (form) {
var fieldErrors = false;
for (var field in form.fields ) {
if (form.fields[field].realName) {
if (data[form.fields[field].realName]) {
scope[field + '_api_error'] = data[form.fields[field]][0];
fieldErrors = true;
}
}
if (form.fields[field].sourceModel) {
if (data[field]) {
scope[form.fields[field].sourceModel + '_' + form.fields[field].sourceField + '_api_error'] =
data[field][0];
fieldErrors = true;
}
}
else {
if (data[field]) {
scope[field + '_api_error'] = data[field][0];
fieldErrors = true;
}
}
}
if ( (!fieldErrors) && defaultMsg) {
Alert(defaultMsg.hdr, defaultMsg.msg);
}
}
else {
Alert(defaultMsg.hdr, defaultMsg.msg);
}
}
}])
.factory('LoadBreadCrumbs', ['$rootScope', '$routeParams', '$location', function($rootScope, $routeParams, $location, Rest) {
return function(crumb) {
//Keep a list of path/title mappings. When we see /organizations/XX in the path, for example,
//we'll know the actual organization name it maps to.
if (crumb !== null && crumb !== undefined) {
var found = false;
for (var i=0; i < $rootScope.crumbCache.length; i++) {
if ($rootScope.crumbCache[i].path == crumb.path) {
found = true;
$rootScope.crumbCache[i] = crumb;
break;
}
}
if (found == false) {
$rootScope.crumbCache.push(crumb);
}
}
return function(crumb) {
//Keep a list of path/title mappings. When we see /organizations/XX in the path, for example,
//we'll know the actual organization name it maps to.
if (crumb !== null && crumb !== undefined) {
var found = false;
for (var i=0; i < $rootScope.crumbCache.length; i++) {
if ($rootScope.crumbCache[i].path == crumb.path) {
found = true;
$rootScope.crumbCache[i] = crumb;
break;
}
}
if (found == false) {
$rootScope.crumbCache.push(crumb);
}
}
var paths = $location.path().replace(/^\//,'').split('/');
var ppath = '';
$rootScope.breadcrumbs = [];
if (paths.length > 1) {
var parent, child;
for (var i=0; i < paths.length - 1; i++) {
if (i > 0 && paths[i].match(/\d+/)) {
parent = paths[i-1];
if (parent == 'inventories') {
var paths = $location.path().replace(/^\//,'').split('/');
var ppath = '';
$rootScope.breadcrumbs = [];
if (paths.length > 1) {
var parent, child;
for (var i=0; i < paths.length - 1; i++) {
if (i > 0 && paths[i].match(/\d+/)) {
parent = paths[i-1];
if (parent == 'inventories') {
child = 'inventory';
}
else {
child = parent.substring(0,parent.length - 1); //assumes parent ends with 's'
}
// find the correct title
for (var j=0; j < $rootScope.crumbCache.length; j++) {
if ($rootScope.crumbCache[j].path == '/' + parent + '/' + paths[i]) {
child = $rootScope.crumbCache[j].title;
break;
}
}
$rootScope.breadcrumbs.push({ title: child, path: ppath + '/' + paths[i] });
}
else {
$rootScope.breadcrumbs.push({ title: paths[i], path: ppath + '/' + paths[i] });
}
ppath += '/' + paths[i];
}
}
}
}
else {
child = parent.substring(0,parent.length - 1); //assumes parent ends with 's'
}
// find the correct title
for (var j=0; j < $rootScope.crumbCache.length; j++) {
if ($rootScope.crumbCache[j].path == '/' + parent + '/' + paths[i]) {
child = $rootScope.crumbCache[j].title;
break;
}
}
$rootScope.breadcrumbs.push({ title: child, path: ppath + '/' + paths[i] });
}
else {
$rootScope.breadcrumbs.push({ title: paths[i], path: ppath + '/' + paths[i] });
}
ppath += '/' + paths[i];
}
}
}
}])
.factory('ReturnToCaller', ['$location', function($location) {
return function(idx) {
// Split the current path by '/' and use the array elements from 0 up to and
// including idx as the new path. If no idx value supplied, use 0 to length - 1.
return function(idx) {
// Split the current path by '/' and use the array elements from 0 up to and
// including idx as the new path. If no idx value supplied, use 0 to length - 1.
var paths = $location.path().replace(/^\//,'').split('/');
var newpath = '';
idx = (idx == null || idx == undefined) ? paths.length - 1 : idx + 1;
for (var i=0; i < idx; i++) {
newpath += '/' + paths[i]
}
$location.path(newpath);
}
var paths = $location.path().replace(/^\//,'').split('/');
var newpath = '';
idx = (idx == null || idx == undefined) ? paths.length - 1 : idx + 1;
for (var i=0; i < idx; i++) {
newpath += '/' + paths[i]
}
$location.path(newpath);
}
}])
.factory('FormatDate', [ function() {
return function(dt) {
var result = ('0' + (dt.getMonth() + 1)).slice(-2) + '/';
result += ('0' + dt.getDate()).slice(-2) + '/';
result += ('0' + (dt.getFullYear() - 2000)).slice(-2) + ' ';
result += ('0' + dt.getHours()).slice(-2) + ':';
result += ('0' + dt.getMinutes()).slice(-2) + ':';
result += ('0' + dt.getSeconds()).slice(-2);
//result += ('000' + dt.getMilliseconds()).slice(-3);
return result;
}
return function(dt) {
var result = ('0' + (dt.getMonth() + 1)).slice(-2) + '/';
result += ('0' + dt.getDate()).slice(-2) + '/';
result += ('0' + (dt.getFullYear() - 2000)).slice(-2) + ' ';
result += ('0' + dt.getHours()).slice(-2) + ':';
result += ('0' + dt.getMinutes()).slice(-2) + ':';
result += ('0' + dt.getSeconds()).slice(-2);
//result += ('000' + dt.getMilliseconds()).slice(-3);
return result;
}
}])
.factory('Wait', [ function() {
return function(directive) {
// Display a spinning icon in the center of the screen to freeze the
// UI while waiting on async things to complete (i.e. API calls).
// Wait('start' | 'stop');
if (directive == 'start') {
var docw = $(document).width();
var doch = $(document).height();
var spinnyw = $('.spinny').width();
var spinnyh = $('.spinny').height();
var x = (docw - spinnyw) / 2;
var y = (doch - spinnyh) / 2;
console.log($(document));
$('.overlay').css({
width: $('html').width(),
height: $(document).height() + 200
}).fadeIn(500);
$('.spinny').css({
top: y,
left: x,
}).fadeIn(500);
}
else {
$('.spinny, .overlay').fadeOut(2000);
}
}
}]);

View File

@ -320,6 +320,9 @@
</div><!-- modal -->
</div><!-- container -->
<div class="overlay"></div>
<div class="spinny"><i class="icon-cog icon-spin icon-2x"></i> <p>working...</p></div>
<div class="site-footer">
<div>