This commit is contained in:
Dobie Wollert
2014-07-25 03:00:29 -04:00
parent c63d462188
commit a403c9079f
39 changed files with 2875 additions and 3541 deletions

View File

@ -168,16 +168,16 @@ angular.module('biomed.directives', [])
}
// Use native interface for touch devices
if(isTouch && element.prop('type') === 'text') {
// if(isTouch && element.prop('type') === 'text') {
//
// element.prop('type', 'date');
// element.on('change', function(ev) {
// scope.$apply(function () {
// controller.$setViewValue(moment(element.val()).toDate());
// });
// });
element.prop('type', 'date');
element.on('change', function(ev) {
scope.$apply(function () {
controller.$setViewValue(moment(element.val()).toDate());
});
});
} else {
// } else {
// If we have a controller (i.e. ngModelController) then wire it up
if(controller) {
@ -208,7 +208,7 @@ angular.module('biomed.directives', [])
forceParse: attrs.forceParse || false
});
}
// }
// Support add-on
var component = element.siblings('[data-toggle="datepicker"]');
@ -219,8 +219,143 @@ angular.module('biomed.directives', [])
}
};
})
.directive('techpicker', function() {
.directive('techschedule', function() {
return {
restrict: 'E',
scope: {
schedule: '=',
date: '=',
onEntryClick: '&'
},
templateUrl: '/partials/techSchedule.html',
replace: true,
link: function($scope, element, attrs) {
var x, rangeDate, rangeStart, rangeEnd;
function setupScale() {
x = d3.scale.linear()
.range([0, 100])
.domain([420, 1320])
.clamp(true);
}
setupScale();
var color = d3.scale.category20();
var hourWidth = 100 / 15;
$scope.hourMarkers = [];
for (var i = 7; i < 22; i++) {
$scope.hourMarkers.push({
date: moment({ hour: i }).toDate(),
style: {
left: x(i * 60) + '%',
width: hourWidth + '%'
}
});
}
$scope.$watch('schedule', function(newVal, oldVal) {
generateDate();
});
$scope.$watch('date', function(newVal, oldVal) {
setupScale();
});
function generateDate() {
var range = moment($scope.date);
var data = {};
for (var i = 0; i < 7; i++) {
var day = range.clone().add(i, 'days');
var key = day.format('MM-DD-YYYY');
var label = day.format('ddd MMM Do YYYY');
data[key] = {
label: label,
values: []
};
}
var c = 0;
angular.forEach($scope.schedule, function(workorder) {
var start = moment(workorder.scheduling.start);
var startMinutes = start.diff(start.clone().startOf('day'), 'minutes');
var end = moment(workorder.scheduling.end);
var endMinutes = end.diff(end.clone().startOf('day'), 'minutes');
var length = end.diff(start, 'days') + 1;
console.log('length: ' + length + ' start: ' + startMinutes + ' end: ' + endMinutes);
var backgroundColor = color(c++);
for (var i = 0; i < length; i++) {
var adjStart, adjEnd;
var key = start.clone().add(i, 'days').format('MM-DD-YYYY');
if (i == 0) {
adjStart = startMinutes;
} else {
adjStart = 420;
}
if (i == length - 1) {
adjEnd = endMinutes;
} else {
adjEnd = 1320;
}
if (data[key]) {
data[key].values.push({
style: {
backgroundColor: color(c),
left: x(adjStart) + '%',
width: (x(adjEnd) - x(adjStart)) + '%'
},
workorder: workorder
});
}
}
return;
angular.forEach(workorder.techs, function(tech) {
var key = tech.name.first + ' ' + tech.name.last;
if (!data[key])
return;
var start = moment(workorder.scheduling.start);
var end = moment(workorder.scheduling.end);
data[key].values.push({
style: {
backgroundColor: color(key),
left: x(start) + "%",
width: (x(end) - x(start)) + "%"
},
workorder: workorder
});
})
});
$scope.data = data;
}
}
};
})
.filter('pretty', function() {
return function(input) {
return "\n" + angular.toJson(input, true);
}
})
.directive('techpicker', function() {
return {
restrict: 'E',
scope: {
@ -232,24 +367,31 @@ angular.module('biomed.directives', [])
templateUrl: '/partials/techPicker.html',
replace: true,
link: function($scope, element, attrs) {
var timePickerParser = d3.time.format('%I:%M%p');
var rangeStart = timePickerParser.parse('7:00am');
var rangeEnd = timePickerParser.parse('10:00pm');
var x, rangeDate, rangeStart, rangeEnd;
var x = d3.time.scale()
.range([0, 100])
.domain([rangeStart, rangeEnd]);
function setupScale() {
rangeDate = moment($scope.date).startOf('day');
rangeStart = moment(rangeDate).add('hours', 7);
rangeEnd = moment(rangeDate).add('hours', 22);
x = d3.time.scale()
.range([0, 100])
.domain([rangeStart.toDate(), rangeEnd.toDate()])
.clamp(true);
}
setupScale();
var color = d3.scale.category20();
var totalHours = moment.duration(moment(rangeEnd) - moment(rangeStart)).hours();
var totalHours = moment.duration(rangeEnd - rangeStart).hours();
var hourWidth = 100 / totalHours;
$scope.hourMarkers = [];
for (var i = 0; i < totalHours; i++) {
var date = moment(rangeStart).add('hours', i).toDate();
$scope.hourMarkers.push({
date: date,
style: {
@ -267,6 +409,10 @@ angular.module('biomed.directives', [])
generateDate();
});
$scope.$watch('date', function(newVal, oldVal) {
setupScale();
});
function generateDate() {
var data = {};
@ -275,7 +421,10 @@ angular.module('biomed.directives', [])
angular.forEach($scope.users, function(user) {
var key = user.name.first + ' ' + user.name.last;
labels.push(key);
data[key] = [];
data[key] = {
id: user._id,
values: []
};
});
labels.sort();
@ -285,13 +434,13 @@ angular.module('biomed.directives', [])
angular.forEach(workorder.techs, function(tech) {
var key = tech.name.first + ' ' + tech.name.last;
if (!data[key])
return;
if (!data[key])
return;
var start = moment(workorder.scheduling.start).year(1900).month(0).date(1).toDate();
var end = moment(workorder.scheduling.end).year(1900).month(0).date(1).toDate();
var start = moment(workorder.scheduling.start);
var end = moment(workorder.scheduling.end);
data[key].push({
data[key].values.push({
style: {
backgroundColor: color(key),
left: x(start) + "%",
@ -306,7 +455,224 @@ angular.module('biomed.directives', [])
}
};
})
.directive('uiSelect2', function ($timeout) {
.value('uiSelect2Config', {})
.directive('uiSelect2', ['uiSelect2Config', '$timeout', function (uiSelect2Config, $timeout) {
var options = {};
if (uiSelect2Config) {
angular.extend(options, uiSelect2Config);
}
return {
require: 'ngModel',
priority: 1,
compile: function (tElm, tAttrs) {
var watch,
repeatOption,
repeatAttr,
isSelect = tElm.is('select'),
isMultiple = angular.isDefined(tAttrs.multiple);
// Enable watching of the options dataset if in use
if (tElm.is('select')) {
repeatOption = tElm.find( 'optgroup[ng-repeat], optgroup[data-ng-repeat], option[ng-repeat], option[data-ng-repeat]');
if (repeatOption.length) {
repeatAttr = repeatOption.attr('ng-repeat') || repeatOption.attr('data-ng-repeat');
watch = jQuery.trim(repeatAttr.split('|')[0]).split(' ').pop();
}
}
return function (scope, elm, attrs, controller) {
// instance-specific options
var opts = angular.extend({}, options, scope.$eval(attrs.uiSelect2));
/*
Convert from Select2 view-model to Angular view-model.
*/
var convertToAngularModel = function(select2_data) {
var model;
if (opts.simple_tags) {
model = [];
angular.forEach(select2_data, function(value, index) {
model.push(value.id);
});
} else {
model = select2_data;
}
return model;
};
/*
Convert from Angular view-model to Select2 view-model.
*/
var convertToSelect2Model = function(angular_data) {
var model = [];
if (!angular_data) {
return model;
}
if (opts.simple_tags) {
model = [];
angular.forEach(
angular_data,
function(value, index) {
model.push({'id': value, 'text': value});
});
} else {
model = angular_data;
}
return model;
};
if (isSelect) {
// Use <select multiple> instead
delete opts.multiple;
delete opts.initSelection;
} else if (isMultiple) {
opts.multiple = true;
}
if (controller) {
// Watch the model for programmatic changes
scope.$watch(tAttrs.ngModel, function(current, old) {
if (!current) {
return;
}
if (current === old) {
return;
}
blah();
// controller.$render();
}, true);
var blah = controller.$render = function () {
if (isSelect) {
elm.select2('val', controller.$viewValue);
} else {
if (opts.multiple) {
var viewValue = controller.$viewValue;
if (angular.isString(viewValue)) {
viewValue = viewValue.split(',');
}
elm.select2(
'data', convertToSelect2Model(viewValue));
} else {
if (angular.isObject(controller.$viewValue)) {
elm.select2('data', controller.$viewValue);
} else if (!controller.$viewValue) {
elm.select2('data', null);
} else {
elm.select2('val', controller.$viewValue);
}
}
}
};
// Watch the options dataset for changes
if (watch) {
scope.$watch(watch, function (newVal, oldVal, scope) {
if (angular.equals(newVal, oldVal)) {
return;
}
// Delayed so that the options have time to be rendered
$timeout(function () {
elm.select2('val', controller.$viewValue);
// Refresh angular to remove the superfluous option
elm.trigger('change');
if(newVal && !oldVal && controller.$setPristine) {
controller.$setPristine(true);
}
});
});
}
// Update valid and dirty statuses
controller.$parsers.push(function (value) {
var div = elm.prev();
div
.toggleClass('ng-invalid', !controller.$valid)
.toggleClass('ng-valid', controller.$valid)
.toggleClass('ng-invalid-required', !controller.$valid)
.toggleClass('ng-valid-required', controller.$valid)
.toggleClass('ng-dirty', controller.$dirty)
.toggleClass('ng-pristine', controller.$pristine);
return value;
});
if (!isSelect) {
// Set the view and model value and update the angular template manually for the ajax/multiple select2.
elm.bind("change", function (e) {
e.stopImmediatePropagation();
if (scope.$$phase || scope.$root.$$phase) {
return;
}
scope.$apply(function () {
controller.$setViewValue(
convertToAngularModel(elm.select2('data')));
});
});
if (opts.initSelection) {
var initSelection = opts.initSelection;
opts.initSelection = function (element, callback) {
initSelection(element, function (value) {
var isPristine = controller.$pristine;
controller.$setViewValue(convertToAngularModel(value));
callback(value);
if (isPristine) {
controller.$setPristine();
}
elm.prev().toggleClass('ng-pristine', controller.$pristine);
});
};
}
}
}
elm.bind("$destroy", function() {
elm.select2("destroy");
});
attrs.$observe('disabled', function (value) {
elm.select2('enable', !value);
});
attrs.$observe('readonly', function (value) {
elm.select2('readonly', !!value);
});
if (attrs.ngMultiple) {
scope.$watch(attrs.ngMultiple, function(newVal) {
attrs.$set('multiple', !!newVal);
elm.select2(opts);
});
}
// Initialize the plugin late so that the injected DOM does not disrupt the template compiler
$timeout(function () {
elm.select2(opts);
// Set initial value - I'm not sure about this but it seems to need to be there
elm.select2('data', controller.$modelValue);
// important!
controller.$render();
// Not sure if I should just check for !isSelect OR if I should check for 'tags' key
if (!opts.initSelection && !isSelect) {
var isPristine = controller.$pristine;
controller.$setViewValue(
convertToAngularModel(elm.select2('data'))
);
if (isPristine) {
controller.$setPristine();
}
elm.prev().toggleClass('ng-pristine', controller.$pristine);
}
});
};
}
};
}])
.directive('uiSelect2-old', function ($timeout) {
var options = {};
return {
@ -421,4 +787,4 @@ angular.module('biomed.directives', [])
};
}
};
});
});