Added a bunch of stuff

This commit is contained in:
Dobie Wollert
2015-08-05 06:03:02 -07:00
parent b4e727c0e6
commit fdc8727044
35 changed files with 1815 additions and 276 deletions

View File

@ -66,10 +66,6 @@ angular.module('biomed', ['biomed.filters', 'biomed.services', 'biomed.directive
controller: "DeviceTypeIndexCtrl",
reloadOnSearch: false
})
.when('/devices/add', {
templateUrl: '/partials/devices/add.html',
controller: "DeviceAddCtrl"
})
.when('/deviceTypes/add', {
templateUrl: '/partials/deviceTypes/add.html',
controller: "DeviceTypeAddCtrl"
@ -78,6 +74,35 @@ angular.module('biomed', ['biomed.filters', 'biomed.services', 'biomed.directive
templateUrl: '/partials/deviceTypes/edit.html',
controller: "DeviceTypeEditCtrl"
})
.when('/devices/add', {
templateUrl: '/partials/devices/add.html',
controller: "DeviceAddCtrl"
})
.when('/devices/:id', {
templateUrl: '/partials/devices/edit.html',
controller: "DeviceEditCtrl"
})
.when('/checkLists', {
templateUrl: '/partials/checkLists/index.html',
controller: "CheckListIndexCtrl",
reloadOnSearch: false
})
.when('/checkLists/add', {
templateUrl: '/partials/checkLists/add.html',
controller: "CheckListAddCtrl"
})
.when('/checkLists/:id', {
templateUrl: '/partials/checkLists/add.html',
controller: "CheckListEditCtrl"
})
.when('/testRuns/add', {
templateUrl: '/partials/testRuns/add.html',
controller: "TestRunAddCtrl"
})
.when('/testRuns/:id', {
templateUrl: '/partials/testRuns/view.html',
controller: "TestRunViewCtrl"
})
.when('/accounting', {
templateUrl: '/partials/accounting/index.html',
controller: "AccountingIndexCtrl",

View File

@ -936,6 +936,10 @@ angular.module('biomed')
var client = $scope.clientPicker.data;
$scope.model.client = client._id;
$scope.currentClient = client;
$scope.devices = Clients.devices({id: client._id}, function() {
console.log($scope.devices);
});
} else {
$scope.model.client = null;
$scope.currentClient = null;
@ -1082,7 +1086,7 @@ angular.module('biomed')
}
})
.controller("WorkorderEditCtrl", function($scope, $routeParams, Workorders, Schedule, Users) {
.controller("WorkorderEditCtrl", function($scope, $routeParams, Workorders, Schedule, Users, Clients) {
$scope.emailsOptions = {
'multiple': true,
'simple_tags': true,
@ -1099,17 +1103,24 @@ angular.module('biomed')
$scope.$watch('group', updateUsers);
$scope.master = Workorders.get($routeParams, function() {
$scope.loading = false;
Workorders.get($routeParams, function(workorderData) {
Clients.devices({id: workorderData.client._id}, function(devicesData) {
if ($scope.master.reason == "Meeting") {
$scope.workorderType = "meeting";
}
$scope.allDevices = devicesData;
$scope.master = workorderData;
if ($scope.master.reason == "Meeting") {
$scope.workorderType = "meeting";
}
$scope.loading = false;
});
});
$scope.emails = createController();
$scope.status = createController();
$scope.remarks = createController();
$scope.devices = createController();
$scope.scheduling = createSchedulingController();
function updateStatus() {

View File

@ -0,0 +1,102 @@
angular.module('biomed')
.controller("CheckListIndexCtrl", checkListsIndexController)
.controller("CheckListAddCtrl", checkListsControllerFactory(false))
.controller("CheckListEditCtrl", checkListsControllerFactory(true))
function checkListsIndexController($scope, $filter, $routeParams, CheckLists, LocationBinder) {
$scope.loading = true;
var allData = CheckLists.index(function() {
$scope.loading = false;
$scope.filter();
});
var filteredData = [];
var index = 0;
var initialPageSize = 100;
var pageSize = 5;
$scope.canLoad = true;
$scope.$watch('query', function() {
$scope.filter();
});
LocationBinder($scope, ['query']);
$scope.filter = function() {
filteredData = $filter('orderBy')($filter('filter')(allData, $scope.query), $scope.sort.column, $scope.sort.descending);
index = initialPageSize;
$scope.canLoad = true;
$scope.checkLists = filteredData.slice(0, initialPageSize);
};
$scope.addItems = function() {
$scope.checkLists = $scope.checkLists.concat(filteredData.slice(index, index + pageSize));
index += pageSize;
$scope.canLoad = index < filteredData.length;
}
$scope.sort = {
column: 'name',
descending: false
};
$scope.selectedCls = function(column) {
return column == $scope.sort.column && 'sort-' + $scope.sort.descending;
}
$scope.changeSorting = function(column) {
var sort = $scope.sort;
if (sort.column == column) {
sort.descending = !sort.descending;
} else {
sort.column = column;
sort.descending = false;
}
$scope.filter();
};
}
function checkListsControllerFactory(isEdit) {
return function($scope, CheckLists, $location, $filter, $routeParams) {
function addField() {
$scope.model.fields.push({ type: 'boolean' })
}
function removeField(index) {
console.log('Index: ', index);
if (index != -1) {
$scope.model.fields.splice(index, 1);
}
}
function save() {
if (isEdit) {
CheckLists.update({id: $scope.model._id}, $scope.model);
} else {
CheckLists.create($scope.model, function(result) {
$location.path("/checkLists/" + result._id);
});
}
}
$scope.addField = addField;
$scope.removeField = removeField;
$scope.save = save;
$scope.isEdit = isEdit;
if (!isEdit) {
$scope.model = {
name: '',
fields: []
};
addField();
} else {
$scope.model = CheckLists.get($routeParams);
}
}
}

View File

@ -56,12 +56,14 @@ angular.module('biomed')
};
})
.controller("DeviceTypeAddCtrl", function($scope, DeviceTypes, $location, $filter) {
.controller("DeviceTypeAddCtrl", function($scope, DeviceTypes, CheckLists, $location, $filter) {
$scope.model = {};
$scope.categories = DeviceTypes.categories();
$scope.deviceMakes = DeviceTypes.makes();
$scope.checkLists = CheckLists.index();
$scope.categoryOpts = {
containerCssClass: 'input-xxlarge',
placeholder: 'Choose a Device Type',
@ -147,7 +149,7 @@ angular.module('biomed')
};
})
.controller("DeviceTypeEditCtrl", function($scope, DeviceTypes, $location, $filter, $routeParams) {
.controller("DeviceTypeEditCtrl", function($scope, DeviceTypes, Devices, CheckLists, $location, $filter, $routeParams) {
var images = {};
$scope.model = DeviceTypes.get($routeParams, function() {
@ -164,9 +166,16 @@ angular.module('biomed')
$scope.makePicker = {id: $scope.model.make, text: $scope.model.make};
});
console.log($routeParams);
$scope.devices = Devices.index({ deviceType: $routeParams.id });
$scope.categories = DeviceTypes.categories();
$scope.deviceMakes = DeviceTypes.makes();
$scope.checkLists = CheckLists.index();
$scope.categoryOpts = {
containerCssClass: 'input-xxlarge',
placeholder: 'Choose a Device Type',

View File

@ -1 +1,160 @@
angular.module('biomed')
.controller("DeviceAddCtrl", devicesControllerFactory(false))
.controller("DeviceEditCtrl", devicesControllerFactory(true))
function devicesControllerFactory(isEdit) {
return function($scope, Devices, DeviceTypes, $location, $filter, $routeParams) {
function buildDeviceTypeFilterQuery(ignore) {
var query = {};
_.each(['category', 'make', 'model'], function(key) {
if (key == ignore)
return;
if ($scope.deviceTypes[key].picker) {
query[key] = $scope.deviceTypes[key].picker.id;
}
})
return query;
}
function filterDeviceTypeSelectors() {
console.log('Filtering Device Data');
var data = {};
_.each(['category', 'make', 'model'], function(key) {
var query = buildDeviceTypeFilterQuery(key);
var filteredResults = $filter('filter')(deviceTypesList, query);
data[key] = [];
_.each(filteredResults, function(entry) {
data[key].push(entry[key]);
});
});
_.each(['category', 'make', 'model'], function(key) {
$scope.deviceTypes[key].data = _.uniq(data[key]);
if (data[key].length == 1) {
var value = data[key][0];
$scope.deviceTypes[key].picker = { id: value, text: value };
}
});
}
function deviceTypePickerFactory(key, label) {
var optsKey = key + 'Opts';
$scope.deviceTypes[key] = {};
$scope.deviceTypes[key].opts = {
containerCssClass: 'input-xxlarge',
placeholder: 'Choose a ' + label,
query: function(query) {
var data = $filter('filter')($scope.deviceTypes[key].data, query.term);
query.callback({
results: _.map(data, function(entry) {
return { id: entry, text: entry }
})
});
}
};
$scope.$watch('deviceTypes.' + key + '.picker',function() {
filterDeviceTypeSelectors();
updateDeviceTypeSelection();
}, true);
}
function clearDeviceTypePickers() {
_.each(['category', 'make', 'model'], function(key) {
$scope.deviceTypes[key].picker = null;
});
}
function updateDeviceTypeSelection() {
var query = buildDeviceTypeFilterQuery();
var results = $filter('filter')(deviceTypesList, query);
$scope.model.deviceType = (results.length == 1) ? results[0]._id : null;
}
function generateRandomIdentifier() {
$scope.model.biomedId = hashids.encode(Date.now());
}
function toggleFrequency(index) {
$scope.model.frequencySchedule[index] = !$scope.model.frequencySchedule[index];
console.log($scope.model);
}
function create() {
Devices.create($scope.model, function(result) {
console.log('here');
$location.path("/devices/" + result._id);
});
}
function update() {
Devices.update({id: $scope.model._id}, $scope.model);
}
var hashids = new Hashids("biomed");
var search = $location.search();
$scope.model = {
frequencySchedule: [false, false, false, false, false, false, false, false, false, false, false, false]
};
$scope.toggleFrequency = toggleFrequency;
$scope.deviceTypes = {};
$scope.deviceTypes.reset = clearDeviceTypePickers;
$scope.biomedId = {};
$scope.biomedId.reset = generateRandomIdentifier;
$scope.create = create;
$scope.update = update;
deviceTypePickerFactory('category', 'Device Type');
deviceTypePickerFactory('make', 'Make');
deviceTypePickerFactory('model', 'Model');
var deviceTypesList = DeviceTypes.index(filterDeviceTypeSelectors)
console.log((isEdit ? "Edit" : "Create") + " Mode");
if (isEdit) {
$scope.model = Devices.get($routeParams, function() {
$scope.loading = false;
var deviceType = $scope.model.deviceType;
_.each(['category', 'make', 'model'], function(key) {
$scope.deviceTypes[key].picker = { id: deviceType[key], text: deviceType[key] };
});
$scope.model.client = $scope.model.client._id;
$scope.model.deviceType = $scope.model.deviceType._id;
$scope.testRuns = Devices.testRuns($routeParams, function() {
console.log($scope.testRuns);
});
});
} else {
if (search.clientId) {
$scope.model.client = search.clientId;
} else {
$location.path("/deviceTypes");
return;
}
generateRandomIdentifier();
}
}
}

View File

@ -0,0 +1,58 @@
angular.module('biomed')
.controller("TestRunAddCtrl", testRunAddController)
.controller("TestRunViewCtrl", testRunViewController)
function testRunAddController($scope, Devices, CheckLists, TestRuns, $location, $filter, $routeParams) {
var search = $location.search();
console.log(search);
$scope.device = Devices.get({id: search.deviceId}, function() {
console.log($scope.device);
$scope.checkList = CheckLists.get({id: $scope.device.deviceType.checkList}, function() {
$scope.loading = false;
$scope.model = {
device: $scope.device._id,
date: new Date(),
fields: []
};
_.each($scope.checkList.fields, function(field) {
if (field.type == 'boolean') {
field.value = 'false'
}
field.result = false;
$scope.model.fields.push(field);
});
})
});
$scope.$watch('model', function() {
$scope.model.result = true;
_.each($scope.model.fields, function(field) {
if (field.type == 'boolean') {
field.result = (field.value == 'true');
} else if (field.type == 'range') {
field.result = field.value >= field.min && field.value <= field.max;
}
$scope.model.result &= field.result;
})
}, true);
$scope.save = function() {
TestRuns.create($scope.model, function(result) {
$location.path("/testRuns/" + result._id);
});
}
}
function testRunViewController($scope, Devices, CheckLists, TestRuns, $location, $filter, $routeParams) {
$scope.model = TestRuns.get($routeParams);
}

View File

@ -872,3 +872,36 @@ angular.module('biomed.directives', [])
}
};
})
.directive('abDeviceUnique', function(Devices, $timeout) {
return {
restrict: 'A',
require: 'ngModel',
link: function(scope, element, attrs, ngModel) {
var stop_timeout;
return scope.$watch(function() {
return ngModel.$modelValue;
}, function(name) {
$timeout.cancel(stop_timeout);
if (!name) {
ngModel.$setValidity('unique', true);
}
stop_timeout = $timeout(function() {
var keyProperty = scope.$eval(attrs.abDeviceUnique);
if (name) {
Devices.isUnique({
key: keyProperty.key,
field: keyProperty.field,
value: name
}, function(result) {
console.log('unique = ' + result.isUnique);
ngModel.$setValidity('unique', result.isUnique);
});
}
}, 200);
});
}
};
})

352
public/js/lib/hashids.js Normal file
View File

@ -0,0 +1,352 @@
/*
Hashids
http://hashids.org/javascript
(c) 2013 Ivan Akimov
https://github.com/ivanakimov/hashids.js
hashids may be freely distributed under the MIT license.
*/
/*jslint plusplus: true, nomen: true, browser: true */
/*global define */
var Hashids = (function () {
"use strict";
function Hashids(salt, minHashLength, alphabet) {
var uniqueAlphabet, i, j, len, sepsLength, diff, guardCount;
this.version = "1.0.2";
/* internal settings */
this.minAlphabetLength = 16;
this.sepDiv = 3.5;
this.guardDiv = 12;
/* error messages */
this.errorAlphabetLength = "error: alphabet must contain at least X unique characters";
this.errorAlphabetSpace = "error: alphabet cannot contain spaces";
/* alphabet vars */
this.alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
this.seps = "cfhistuCFHISTU";
this.minHashLength = parseInt(minHashLength, 10) > 0 ? minHashLength : 0;
this.salt = (typeof salt === "string") ? salt : "";
if (typeof alphabet === "string") {
this.alphabet = alphabet;
}
for (uniqueAlphabet = "", i = 0, len = this.alphabet.length; i !== len; i++) {
if (uniqueAlphabet.indexOf(this.alphabet.charAt(i)) === -1) {
uniqueAlphabet += this.alphabet.charAt(i);
}
}
this.alphabet = uniqueAlphabet;
if (this.alphabet.length < this.minAlphabetLength) {
throw this.errorAlphabetLength.replace("X", this.minAlphabetLength);
}
if (this.alphabet.search(" ") !== -1) {
throw this.errorAlphabetSpace;
}
/* seps should contain only characters present in alphabet; alphabet should not contains seps */
for (i = 0, len = this.seps.length; i !== len; i++) {
j = this.alphabet.indexOf(this.seps.charAt(i));
if (j === -1) {
this.seps = this.seps.substr(0, i) + " " + this.seps.substr(i + 1);
} else {
this.alphabet = this.alphabet.substr(0, j) + " " + this.alphabet.substr(j + 1);
}
}
this.alphabet = this.alphabet.replace(/ /g, "");
this.seps = this.seps.replace(/ /g, "");
this.seps = this.consistentShuffle(this.seps, this.salt);
if (!this.seps.length || (this.alphabet.length / this.seps.length) > this.sepDiv) {
sepsLength = Math.ceil(this.alphabet.length / this.sepDiv);
if (sepsLength === 1) {
sepsLength++;
}
if (sepsLength > this.seps.length) {
diff = sepsLength - this.seps.length;
this.seps += this.alphabet.substr(0, diff);
this.alphabet = this.alphabet.substr(diff);
} else {
this.seps = this.seps.substr(0, sepsLength);
}
}
this.alphabet = this.consistentShuffle(this.alphabet, this.salt);
guardCount = Math.ceil(this.alphabet.length / this.guardDiv);
if (this.alphabet.length < 3) {
this.guards = this.seps.substr(0, guardCount);
this.seps = this.seps.substr(guardCount);
} else {
this.guards = this.alphabet.substr(0, guardCount);
this.alphabet = this.alphabet.substr(guardCount);
}
}
Hashids.prototype.encode = function () {
var ret = "", i, len,
numbers = Array.prototype.slice.call(arguments);
if (!numbers.length) {
return ret;
}
if (numbers[0] instanceof Array) {
numbers = numbers[0];
}
for (i = 0, len = numbers.length; i !== len; i++) {
if (typeof numbers[i] !== "number" || numbers[i] % 1 !== 0 || numbers[i] < 0) {
return ret;
}
}
return this._encode(numbers);
};
Hashids.prototype.decode = function (hash) {
var ret = [];
if (!hash.length || typeof hash !== "string") {
return ret;
}
return this._decode(hash, this.alphabet);
};
Hashids.prototype.encodeHex = function (str) {
var i, len, numbers;
str = str.toString();
if (!/^[0-9a-fA-F]+$/.test(str)) {
return "";
}
numbers = str.match(/[\w\W]{1,12}/g);
for (i = 0, len = numbers.length; i !== len; i++) {
numbers[i] = parseInt("1" + numbers[i], 16);
}
return this.encode.apply(this, numbers);
};
Hashids.prototype.decodeHex = function (hash) {
var ret = [], i, len,
numbers = this.decode(hash);
for (i = 0, len = numbers.length; i !== len; i++) {
ret += (numbers[i]).toString(16).substr(1);
}
return ret;
};
Hashids.prototype._encode = function (numbers) {
var ret, lottery, i, len, number, buffer, last, sepsIndex, guardIndex, guard, halfLength, excess,
alphabet = this.alphabet,
numbersSize = numbers.length,
numbersHashInt = 0;
for (i = 0, len = numbers.length; i !== len; i++) {
numbersHashInt += (numbers[i] % (i + 100));
}
lottery = ret = alphabet.charAt(numbersHashInt % alphabet.length);
for (i = 0, len = numbers.length; i !== len; i++) {
number = numbers[i];
buffer = lottery + this.salt + alphabet;
alphabet = this.consistentShuffle(alphabet, buffer.substr(0, alphabet.length));
last = this.hash(number, alphabet);
ret += last;
if (i + 1 < numbersSize) {
number %= (last.charCodeAt(0) + i);
sepsIndex = number % this.seps.length;
ret += this.seps.charAt(sepsIndex);
}
}
if (ret.length < this.minHashLength) {
guardIndex = (numbersHashInt + ret[0].charCodeAt(0)) % this.guards.length;
guard = this.guards[guardIndex];
ret = guard + ret;
if (ret.length < this.minHashLength) {
guardIndex = (numbersHashInt + ret[2].charCodeAt(0)) % this.guards.length;
guard = this.guards[guardIndex];
ret += guard;
}
}
halfLength = parseInt(alphabet.length / 2, 10);
while (ret.length < this.minHashLength) {
alphabet = this.consistentShuffle(alphabet, alphabet);
ret = alphabet.substr(halfLength) + ret + alphabet.substr(0, halfLength);
excess = ret.length - this.minHashLength;
if (excess > 0) {
ret = ret.substr(excess / 2, this.minHashLength);
}
}
return ret;
};
Hashids.prototype._decode = function (hash, alphabet) {
var ret = [], i = 0,
lottery, len, subHash, buffer,
r = new RegExp("[" + this.guards + "]", "g"),
hashBreakdown = hash.replace(r, " "),
hashArray = hashBreakdown.split(" ");
if (hashArray.length === 3 || hashArray.length === 2) {
i = 1;
}
hashBreakdown = hashArray[i];
if (typeof hashBreakdown[0] !== "undefined") {
lottery = hashBreakdown[0];
hashBreakdown = hashBreakdown.substr(1);
r = new RegExp("[" + this.seps + "]", "g");
hashBreakdown = hashBreakdown.replace(r, " ");
hashArray = hashBreakdown.split(" ");
for (i = 0, len = hashArray.length; i !== len; i++) {
subHash = hashArray[i];
buffer = lottery + this.salt + alphabet;
alphabet = this.consistentShuffle(alphabet, buffer.substr(0, alphabet.length));
ret.push(this.unhash(subHash, alphabet));
}
if (this._encode(ret) !== hash) {
ret = [];
}
}
return ret;
};
Hashids.prototype.consistentShuffle = function (alphabet, salt) {
var integer, j, temp, i, v, p;
if (!salt.length) {
return alphabet;
}
for (i = alphabet.length - 1, v = 0, p = 0; i > 0; i--, v++) {
v %= salt.length;
p += integer = salt.charAt(v).charCodeAt(0);
j = (integer + v + p) % i;
temp = alphabet.charAt(j);
alphabet = alphabet.substr(0, j) + alphabet.charAt(i) + alphabet.substr(j + 1);
alphabet = alphabet.substr(0, i) + temp + alphabet.substr(i + 1);
}
return alphabet;
};
Hashids.prototype.hash = function (input, alphabet) {
var hash = "",
alphabetLength = alphabet.length;
do {
hash = alphabet.charAt(input % alphabetLength) + hash;
input = parseInt(input / alphabetLength, 10);
} while (input);
return hash;
};
Hashids.prototype.unhash = function (input, alphabet) {
var number = 0, pos, i;
for (i = 0; i < input.length; i++) {
pos = alphabet.indexOf(input[i]);
number += pos * Math.pow(alphabet.length, input.length - i - 1);
}
return number;
};
/* require.js bit */
if (typeof define === "function" && typeof define.amd === "object" && define.amd) {
define(function () {
return Hashids;
});
}
return Hashids;
}());

View File

@ -29,6 +29,41 @@ angular.module('biomed.services', [])
destroy: { method: 'DELETE', params: { id: 0 } },
});
})
.factory("Devices", function($resource) {
return $resource('/api/devices/:id/:cmd',
{ id: "@id", cmd: "@cmd" },
{
index: { method: 'GET', params: {}, isArray: true },
get: { method: 'GET', params: { id: 0} },
create: { method: 'POST', params: {} },
update: { method: 'POST', params: { id: 0} },
destroy: { method: 'DELETE', params: { id: 0 } },
testRuns: { method: 'GET', params: { id: 0, cmd: 'test_runs' }, isArray: true },
isUnique: { method: 'GET', params: { cmd: 'isUnique' } },
});
})
.factory("CheckLists", function($resource) {
return $resource('/api/check_lists/:id/:cmd',
{ id: "@id", cmd: "@cmd" },
{
index: { method: 'GET', params: {}, isArray: true },
get: { method: 'GET', params: { id: 0} },
create: { method: 'POST', params: {} },
update: { method: 'POST', params: { id: 0} },
destroy: { method: 'DELETE', params: { id: 0 } },
});
})
.factory("TestRuns", function($resource) {
return $resource('/api/test_runs/:id/:cmd',
{ id: "@id", cmd: "@cmd" },
{
index: { method: 'GET', params: {}, isArray: true },
get: { method: 'GET', params: { id: 0} },
create: { method: 'POST', params: {} },
update: { method: 'POST', params: { id: 0} },
destroy: { method: 'DELETE', params: { id: 0 } },
});
})
.factory("Posts", function($resource) {
return $resource('/api/posts/:id',
{ id: "@id" },