mirror of
https://github.com/ansible/awx.git
synced 2026-01-11 10:00:01 -03:30
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:
parent
9729c6d203
commit
036352f10e
@ -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 });
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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' } };
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}]);
|
||||
|
||||
@ -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>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user