Initial commit

This commit is contained in:
Isaac Parenteau committed 2018-07-07 20:43:51 -05:00
commit 880e39de2e
511 files changed
+38363

No files matched your search

@@ -0,0 +1,22 @@
angular.module('portal.common.directives.compareTo', ['ui.router'])
.directive('compareTo', function(){
return {
require: 'ngModel',
scope: {
otherModelValue: '=compareTo'
},
link: function(scope, element, attributes, ngModel) {
ngModel.$validators.compareTo = function(modelValue) {
if ((modelValue === null || modelValue === undefined) && scope.otherModelValue === null) {
return true;
}
return modelValue === scope.otherModelValue;
};
scope.$watch('otherModelValue', function() {
ngModel.$validate();
});
}
};
});
@@ -0,0 +1,32 @@
(function() {
'use strict';
angular.module('portal.common.directives.permissions', ['ui.router'])
.directive('hasPermission', function(permissions){
return {
link: function(scope, element, attrs) {
if (!_.isString(attrs.hasPermission)){
throw 'hasPermission value must be a string';
}
var value = attrs.hasPermission.trim();
var notPermissionFlag = value[0] === '!';
if (notPermissionFlag) {
value = value.slice(1).trim();
}
function toggleVisibility() {
permissions.canView({permission: value}).then(function(allowed){
if ((allowed && !notPermissionFlag) || (!allowed && notPermissionFlag)) {
element.css('display', 'block');
} else {
element.css('display', 'none');
}
});
}
toggleVisibility();
scope.$on('permissionsChanged', toggleVisibility);
}
};
});
})();
@@ -0,0 +1,14 @@
<md-tabs md-selected="tabIndex" layout="column" layout-fill class="stretch-height">
<md-tab ng-repeat="tab in visibleTabs" md-on-select="processTabClick($event, tab, $index);" active="tab.active"layout="column" layout-fill>
<md-tab-label>
<div layout="row">
<div ng-bind-html="tab.leftItem"></div>
<span id="{{tab.title.toLowerCase()}}-tab">{{tab.title}}</span>
<div ng-bind-html="tab.rightItem"></div>
</div>
</md-tab-label>
<md-tab-body>
<div ng-include src="tab.source" style="height:100%"></div>
</md-tab-body>
</md-tab>
</md-tabs>
@@ -0,0 +1,129 @@
(function () {
'use strict';
var _$state;
/**
* Creates a tabset with a scrollable tab bar
* Based on the incredible example at http://www.bootply.com/l2ChB4vYmC
*/
angular.module('portal.common.directives.portalTabset', ['ui.router'])
.directive('portalTabSet', function ($state) {
_$state = $state;
return {
restrict: 'E',
replace: false, //Nothing shows up if you use replace: true
transclude: true,
scope: {
tabs: '=',
tabIndex: '=?',
},
templateUrl: 'common/directives/portal-tab-set/portal-tab-set.html',
link: repoTabsetLink
};
});
function repoTabsetLink(scope, element, attrs, fn) {
//The default starting position of the tab group.
var DEFAULT_TAB_POSITION = 0;
scope.tabIndex = scope.tabIndex === null || scope.tabIndex === undefined ? 0 : scope.tabIndex;
scope.visibleTabs = [];
scope.$watch('tabIndex', function(value) {
if (scope.tabIndex === null || scope.tabIndex === undefined) {
return;
}
scope.tabIndex = value;
});
scope.tabsetSelectChange = function(index) {
scope.tabIndex = index;
scope.$emit('tabsetSelectChange', index);
};
scope.$on('changeTabSelection', function(value) {
scope.tabIndex = value;
});
/**
* Determines if the state object for a tab is active.
*
* @param {type} state A tab's state
* @returns {boolean} True if the state is active, false otherwise.
*/
function isActive(state) {
var isState = _$state.is(state);
return isState || (_$state.current.name.indexOf(state) >= 0); // allow for sub tabs.
}
/**
* Updates the tabs after the state succesfully changes.
*
* @param {type} tabs An array of tabs. See action-pane.js for example
* @returns {undefined}
*/
function updateTabStates(tabs) {
//Update the active tag for each tab to reflect state change
var activeTab = false;
if (angular.isArray(tabs)) {
tabs.forEach(function (tab) {
tab.active = isActive(tab.state);
activeTab = activeTab || tab.active;
});
//If no tab has been specified, activate the first tab.
if (!activeTab && angular.isDefined(tabs[0])) {
tabs[0].default = true;
tabs[0].active = true;
}
//Now notify tabs to respect tab activation
scope.$broadcast('tabActivated');
}
}
scope.$on('tabsetDidChange', function (evt, tabs) {
scope.tabs = tabs;
update();
});
function update() {
updateVisisbleTabls();
updateTabStates(scope.tabs);
}
function updateVisisbleTabls() {
for (var i = 0; i < scope.tabs.length; i++) {
var tab = scope.tabs[i];
if (tab.visible === undefined || tab.visible) {
scope.visibleTabs[i] = tab;
}
}
}
scope.$on('$stateChangeSuccess', function () {
updateTabStates(scope.tabs);
});
/**
* Changes the state to the specified tab state. If the control key was
* held when the tab was click on, opens the tab's "big" state (fullscreen) in
* a new tab.
*
* @param {$event} evt The click event. Used to determine if ctrl/cmd was held
* during the click.
* @param {type} tab The tab to activate. A tab object from $scope.tabs.
*
* @returns {undefined}
*/
scope.processTabClick = function (evt, tab, index) {
_$state.go(tab.state);
update();
scope.tabsetSelectChange(index);
};
updateVisisbleTabls();
update();
} //end dcdTabsetLink function
})();
@@ -0,0 +1,3 @@
<div>
<i id="icon" class="material-icons" title="{{stats}}">{{iconImage}}</i>
</div>
@@ -0,0 +1,357 @@
angular.module('portal.common.directives.portalWebsocket', ['ui.router'])
.directive('portalWebsocket', PortalWebsocket);
function PortalWebsocket(Request, $timeout, portalUtils, PortalPubSub) {
return {
restrict: 'E',
templateUrl: 'common/directives/portal-websocket/portal-websocket.html',
link: function (scope) {
scope.iconImage = 'import_export';
scope.stats = 'not started';
var PingPong = function (msg) {
this.date = msg.date;
this.pull = msg.pull;
this.data = msg.data;
};
var Pinger = function () {
this.progress = 0;
this.count = 0;
this.iterations = null;
this.ping = null;
this.pong = null;
this.bwConvert = function (bytes, msec) {
var res = bytes / msec * 1000 * 8; // bits/second;
var units;
if (res > 1000000) {
res /= 1024000; // Mbits/sec
units = 'Mbps';
} else if (res > 1024) {
res /= 1000; // Kbits/sec
units = 'Kbps';
} else {
units = 'bps';
}
return this.round(res, 1) + units;
};
this.round = function (value, decimals) {
return Number(Math.round(value + 'e' + decimals) + 'e-' + decimals);
};
this.isDone = function () {
if (this.count >= this.iterations) {
this.progress = 100;
return true;
} else {
this.progress = this.round(this.count / this.iterations * 100, 0);
return false;
}
};
return this;
};
var LatencyTask = portalUtils.inherit(function () {
Pinger.call(this);
this.iterations = 100;
this.latencySum = 0;
this.latencyMin = 0;
this.latencyAve = 0;
this.latencyMax = 0;
this.pps = 'n/a';
this.getPing = function () {
this.ping = new PingPong({'date': new Date().getTime(), 'pull': 0, 'data': []});
return this.ping;
};
this.onPong = function (pong) {
this.pong = pong;
this.count++;
var now = new Date().getTime();
var msec = now - this.pong.date;
this.latencySum += msec;
this.latencyAve = this.round(this.latencySum / this.count, 0);
if (this.latencyMin === 0 || msec < this.latencyMin) {
this.latencyMin = msec;
}
if (this.latencyMax === 0 || msec > this.latencyMax) {
this.latencyMax = msec;
}
// calc aggregate ppps
this.pps = this.count / this.latencySum * 1000;
this.pps = this.round(this.pps, 1);
return this.isDone();
};
return this;
}, Pinger);
var DownloadTask = portalUtils.inherit(function (latencyTask) {
Pinger.call(this);
this.iterations = 20;
this.downloadBytes = 0;
this.downloadTime = 0;
this.download = 0;
this.pull = 10000;
this.getPing = function () {
this.ping = new PingPong({'date': new Date().getTime(), 'pull': this.pull, 'data': []});
return this.ping;
};
this.onPong = function (pong) {
this.pong = pong;
this.count++;
var now = new Date().getTime();
var msec = now - this.pong.date - latencyTask.latencyAve / 2;
var bytes = this.pong.data.length;
this.downloadBytes += bytes;
this.downloadTime += msec;
// calc aggregate download bandwidth
this.download = this.bwConvert(this.downloadBytes, this.downloadTime);
return this.isDone();
};
return this;
}, Pinger);
var UploadTask = portalUtils.inherit(function (latencyTask, downloadTask) {
Pinger.call(this);
this.iterations = 20;
this.uploadBytes = 0;
this.uploadTime = 0;
this.upload = 0;
this.getPing = function () {
this.ping = new PingPong({'date': new Date().getTime(), 'pull': 0, 'data': downloadTask.pong.data});
return this.ping;
};
this.onPong = function (pong) {
this.pong = pong;
this.count++;
var now = new Date().getTime();
var msec = now - this.pong.date - latencyTask.latencyAve / 2;
var bytes = this.ping.data.length;
this.uploadBytes += bytes;
this.uploadTime += msec;
this.upload = this.bwConvert(this.uploadBytes, this.uploadTime);
return this.isDone();
};
return this;
}, Pinger);
var icon = document.getElementById('icon');
var latencyTask = new LatencyTask();
var downloadTask = new DownloadTask(latencyTask);
var uploadTask = new UploadTask(latencyTask, downloadTask);
var task = latencyTask;
var transport = null;
var stompClient = null;
var subscription = null;
function onConnectionSuccess(frame) {
transport = stompClient.ws.transport;
// subscribe to the /info/pong queue for this user, requires controller annotations:
// @SubscribeMapping('/info/ping')
// @SendToUser('/queue/info/pong')
var headers = {/*ack: 'client'*/};
subscription = stompClient.subscribe('/user/queue/pong', onPong, headers);
// if not websocket scale down the number of iterations
if (transport !== 'websocket') {
var div = 5;
latencyTask.iterations /= div;
downloadTask.iterations /= div;
uploadTask.iterations /= div;
}
// kick it off
task = latencyTask;
sendPing();
}
function onPong(frame) {
// frame.ack();
scope.$apply(function () {
var done = task.onPong(new PingPong(JSON.parse(frame.body)));
// switch tasks when finished
if (done && task === latencyTask) {
task = downloadTask;
} else if (done && task === downloadTask) {
task = uploadTask;
} else if (done && task === uploadTask) {
task = null;
}
if (task !== null) {
sendPing();
} else {
finish();
}
});
}
scope.busy = function () {
return task !== null;
};
function connect(transports) {
// create stomp client
var options = {transports: transports};
var socket = new SockJS(Request.baseURI + '/ws/stomp', null, options);
stompClient = Stomp.over(socket);
stompClient.debug = null;
// connect to server
scope.stats = 'connecting';
var headers = {};
stompClient.connect(headers, onConnectionSuccess, onConnectionFailure);
}
function sendPing() {
setActiveStatus();
stompClient.send('/start/ping', {}, JSON.stringify(task.getPing()));
}
var timer = null;
function flash() {
icon.style.color = (icon.style.color === 'green') ? 'goldenrod' : 'green';
if (getProgress() < 100) {
timer = $timeout(flash, 250);
}
}
function getProgress() {
return Math.round((latencyTask.progress + uploadTask.progress + downloadTask.progress) / 3);
}
function finish() {
$timeout.cancel(timer);
// shutdown the websocket connection
subscription.unsubscribe();
stompClient.disconnect();
stompClient = null;
if (transport === 'websocket') {
setSuccessfulStatus();
} else {
setDegradedStatus();
}
}
function onConnectionFailure(error) {
$timeout.cancel(timer);
stompClient = null; // Stomp connections are closed on failure
setFailureStatus(error.toString());
}
function createStats() {
var min = latencyTask.latencyMin;
var ave = latencyTask.latencyAve;
var max = latencyTask.latencyMax;
var pps = latencyTask.pps;
var upload = uploadTask.upload;
var download = downloadTask.download;
var latency = min + '/' + ave + '/' + max;
// always start with the transport
var stats = transport;
if (latencyTask.progress > 0) {
stats += ', ' + latency + 'ms, ' + pps + 'pps';
}
if (downloadTask.progress > 0) {
stats += ', ' + download;
}
if (uploadTask.progress > 0) {
stats += '/' + upload;
}
if (getProgress() < 100) {
stats += ', ' + getProgress() + '%';
}
return stats;
}
function setActiveStatus() {
// make available to html
scope.stats = createStats();
// icon stays flashing
// notify login dialog that we are not finished
PortalPubSub.publish('StompTestStatus', {status: 'active', stats: scope.stats});
}
// green
function setSuccessfulStatus() {
// make available to html
scope.stats = createStats();
// flashing has stopped, set green check
scope.iconImage = 'check';
icon.style.color = 'green';
// publish status (to login dialog)
PortalPubSub.publish('StompTestStatus', {status: 'successful', stats: scope.stats});
}
// yellow
function setDegradedStatus() {
// make available to html
scope.stats = createStats();
// flashing has stopped, set yellow info flag
scope.iconImage = 'info';
icon.style.color = 'goldenrod';
// publish status (to login dialog)
PortalPubSub.publish('StompTestStatus', {status: 'degraded', stats: scope.stats});
}
//red
function setFailureStatus(msg) {
// set hover over
scope.stats = 'failed: ' + msg;
// flashing has stopped, set red error flag
scope.iconImage = 'error';
icon.style.color = 'red';
// publish status (to login dialog)
PortalPubSub.publish('StompTestStatus', {status: 'failure', stats: scope.stats});
}
// start the test
flash();
var transports = [/*'websocket', 'xhr-streaming', 'eventsource', 'xhr-polling', 'jsonp-polling'*/];
connect(transports);
}
};
}