SmartIT_Extensions/BMC/smart-it-full-helix/scripts/app/change/calendar-book-view-directiv...

334 lines
18 KiB
JavaScript

"use strict";
(function () {
'use strict';
angular.module('changeModule')
.directive('calendarBookView', ['$timeout', '$log', 'events', '$rootScope', 'dateFilter', '$locale', '$state',
function ($timeout, $log, events, $rootScope, dateFilter, $locale, $state) {
return {
restrict: 'E',
templateUrl: 'views/change/calendar-book-view.html',
require: '^calendar',
scope: {},
link: function (scope, element, attrs, calendarCtrl) {
scope.model = calendarCtrl.model;
var timelineDays = 5, zoomLevel = 3, maxTimelineDays = 20, halfTimelineDays = Math.floor(timelineDays / 2), timelineStart = scope.model.context.scheduledStartDate
? new DayPilot.Date(scope.model.context.scheduledStartDate, true).addDays(-halfTimelineDays)
: new DayPilot.Date();
var zoomLevels = [
{
cellDuration: 15,
timeHeaders: [
{ groupBy: "Day" },
{ groupBy: "Hour" },
{ groupBy: "Cell" }
],
minTimelineDays: 5,
formats: ['dayAndDate', 'shortestTime']
},
{
cellDuration: 30,
timeHeaders: [
{ groupBy: "Day" },
{ groupBy: "Hour" },
{ groupBy: "Cell" }
],
minTimelineDays: 5,
formats: ['dayAndDate', 'shortestTime']
},
{
cellDuration: 60,
timeHeaders: [
{ groupBy: "Day" },
{ groupBy: "Cell" }
],
minTimelineDays: 5,
formats: ['dayAndDate', 'shortestTime']
},
{
cellDuration: 120,
timeHeaders: [
{ groupBy: "Day" },
{ groupBy: "Cell" }
],
minTimelineDays: 5,
formats: ['dayAndDate', 'shortestTime']
},
{
cellDuration: 240,
timeHeaders: [
{ groupBy: "Day" },
{ groupBy: "Cell" }
],
minTimelineDays: 10,
formats: ['dayAndDate', 'shortestTime']
},
{
cellDuration: 360,
timeHeaders: [
{ groupBy: "Day" },
{ groupBy: "Cell" }
],
minTimelineDays: 14,
formats: ['dayAndDate', 'shortestTime']
},
{
cellDuration: 480,
timeHeaders: [
{ groupBy: "Day" },
{ groupBy: "Cell" }
],
minTimelineDays: 18,
formats: ['dayAndDate', 'shortestTime']
}
];
scope.isChangeCalendar = ($state.current.name && $state.current.name.indexOf('changeCalendar') !== -1);
scope.config = {
heightSpec: "Parent100Pct",
days: timelineDays,
startDate: timelineStart,
scale: "CellDuration",
cellDuration: zoomLevels[zoomLevel].cellDuration,
timeHeaders: zoomLevels[zoomLevel].timeHeaders,
theme: 'bookview',
cssClassPrefix: 'bookview',
resources: generateResourceArray(25),
onIncludeTimeCell: function (args) {
var Sunday = 0;
var Saturday = 6;
if (!scope.model.showWeekends && (args.cell.start.getDayOfWeek() === Sunday ||
args.cell.start.getDayOfWeek() === Saturday)) {
args.cell.visible = false;
}
},
onBeforeTimeHeaderRender: function (args) {
var format = zoomLevels[zoomLevel].formats[args.header.level];
if (args.header.level === 0 && window.myitsmLocale === 'en' && $locale.id.toLowerCase() !== 'en-us') {
format = 'shortDate';
}
if (format) {
var htmlText = dateFilter(args.header.start.toDateLocal(), format);
if (args.header.level === 0 && window.myitsmLocale === 'en' && $locale.id.toLowerCase() !== 'en-us') {
if ($locale.id.toLowerCase() === 'en-ca') {
//remove yy- at the beginning
htmlText = htmlText.substring(htmlText.indexOf('-') + 1);
}
else if ($locale.id.toLowerCase() === 'en-za') {
//remove yy/ at the beginning
htmlText = htmlText.substring(htmlText.indexOf('/') + 1);
}
else {
//remove /yy at the end
htmlText = htmlText.substring(0, htmlText.lastIndexOf('/'));
}
}
args.header.html = htmlText;
args.header.toolTip = htmlText;
}
},
onTimeRangeSelected: function (args) {
if (scope.isChangeCalendar) {
args.preventDefault();
}
else {
scope.changeBookView.clearSelection();
if (args.resource === scope.model.currentRequestResourceId) {
scope.model.context.scheduledStartDate = args.start.toDateLocal();
scope.model.context.scheduledEndDate = args.end.toDateLocal();
scope.$apply();
}
}
},
onEventMove: function (args) {
if (scope.isChangeCalendar || (args.newResource !== scope.model.currentRequestResourceId)) {
args.preventDefault();
}
},
onEventMoved: function (args) {
if (args.newResource === scope.model.currentRequestResourceId) {
scope.model.context.scheduledStartDate = args.newStart.toDateLocal();
scope.model.context.scheduledEndDate = args.newEnd.toDateLocal();
scope.$apply();
}
},
onEventResize: function (args) {
if (scope.isChangeCalendar || (args.e.resource() !== scope.model.currentRequestResourceId)) {
args.preventDefault();
}
},
onEventResized: function (args) {
if (args.e.resource() === scope.model.currentRequestResourceId) {
scope.model.context.scheduledStartDate = args.newStart.toDateLocal();
scope.model.context.scheduledEndDate = args.newEnd.toDateLocal();
scope.$apply();
}
},
onEventClicked: calendarCtrl.onEventClicked
};
scope.$watch('model.showWeekends', function () {
updateBookView();
});
scope.$watch('model.expanded', function () {
if (scope.model.expanded) {
$timeout(function () {
updateBookView();
}, 500);
}
});
scope.$watch('model.context.scheduledStartDate', function () {
enqueueRescheduleChangeRequest();
});
scope.$watch('model.context.scheduledEndDate', function () {
enqueueRescheduleChangeRequest();
});
scope.$watch('model.selectedCalendarView', function () {
if (scope.model.selectedCalendarView === scope.model.calendarViews[0]) {
$timeout(function () {
updateBookView();
positionTimeline();
});
}
});
var off = $rootScope.$on(events.CHANGE_COLLISION_STATUS_CHANGED, function (event, addressedCollisions) {
calendarCtrl.applyAddressedCollisions(addressedCollisions);
displayCollisions();
});
scope.$on('$destroy', function () {
off();
});
scope.$watch('model.context', function () {
calendarCtrl.updateCalendarHandling(scope.changeBookView);
}, true);
scope.$watch('model.collisions', function () {
displayCollisions();
}, true);
scope.$watch('model.calendarTypes', function () {
displayCollisions();
}, true);
scope.$on(events.ZOOM_LEVEL_CHANGED, function (event, increment) {
applyZoomLevel(increment);
});
function displayCollisions() {
calendarCtrl.displayCollisions({
calendar: scope.changeBookView,
resources: scope.config.resources,
outagesIndex: computeOutagesIndex(),
businessEventsIndex: computeBusinessEventsIndex(),
changeCollisionCss: 'bookview_event_collision',
changeNonCollisionCss: 'bookview_event_secondary',
outageCollisionCss: 'bookview_event_outage_collision',
outageNonCollisionCss: 'bookview_event_outage_secondary',
businessEventCollisionCss: 'bookview_event_business_event_collision',
businessEventNonCollisionCss: 'bookview_event_business_event_secondary',
updateCalendar: function () {
updateBookView(true);
}
});
}
function computeOutagesIndex() {
return (calendarCtrl.changeRequestFilterSelected() ? calendarCtrl.visibleChangeRequests(scope.changeBookView).length : 0) + 1;
}
function computeBusinessEventsIndex() {
var outageIndex = computeOutagesIndex();
return calendarCtrl.outageFilterSelected() ? outageIndex + 1 : outageIndex;
}
function updateBookView(forceUpdate) {
var start = scope.model.context.scheduledStartDate, end = scope.model.context.scheduledEndDate, update = !!(start && end);
if (update) {
$log.log("update book view: start=" + start + "(" + start.getTime() + "), end=" + end + "(" + end.getTime() + ")");
scope.changeBookView.collisionStart = new DayPilot.Date(start, true);
scope.changeBookView.collisionEnd = new DayPilot.Date(end, true);
}
else {
scope.changeBookView.collisionStart = null;
scope.changeBookView.collisionEnd = null;
}
if (update || forceUpdate) {
scope.changeBookView.update();
}
}
function positionTimeline() {
var start = scope.model.context.scheduledStartDate
? scope.model.context.scheduledStartDate
: new Date();
startTimelineOn(start);
}
function startTimelineOn(date) {
if (date instanceof Date) {
date = new DayPilot.Date(date, true);
}
date = date.addHours(-date.getHours()).addMinutes(-date.getMinutes());
scope.changeBookView.scrollTo(date);
}
function enqueueRescheduleChangeRequest() {
$timeout(function () {
rescheduleChangeRequest(scope.model.context.scheduledStartDate, scope.model.context.scheduledEndDate);
});
}
function rescheduleChangeRequest(start, end) {
if (calendarCtrl.rescheduleChangeRequest(scope.changeBookView, start, end)
&& !extendTimeline(start, end)) {
updateBookView();
}
}
function extendTimeline(start, end) {
if (!start || !end) {
return false;
}
if (start instanceof Date) {
start = new DayPilot.Date(start, true);
}
if (end instanceof Date) {
end = new DayPilot.Date(end, true);
}
var edgeDays = 1, bufferDays = 2, timelineStartMoment = moment(timelineStart.toDateLocal()).startOf("day"), timelineEnd = timelineStart.addDays(timelineDays), timelineEndMoment = moment(timelineEnd.toDateLocal()).startOf("day"), startMoment = moment(start.toDateLocal()).startOf("day"), endMoment = moment(end.toDateLocal()).startOf("day"), timelineModified = false;
var startDiff = startMoment.diff(timelineStartMoment, "days");
var endDiff = timelineEndMoment.diff(endMoment, "days");
if (startDiff < edgeDays || endDiff <= edgeDays) {
timelineStartMoment = startMoment.subtract(bufferDays, "days");
timelineEndMoment = endMoment.add(bufferDays + 1, "days"); // +1 is required to have full bufferDays number after end date, otherwise the actual number would be 1 day less
timelineDays = timelineEndMoment.diff(timelineStartMoment, "days");
timelineDays = Math.min(timelineDays, maxTimelineDays);
timelineDays = Math.max(timelineDays, zoomLevels[zoomLevel].minTimelineDays);
timelineStart = new DayPilot.Date(timelineStartMoment.toDate());
timelineModified = true;
}
if (timelineModified) {
$log.log("book view timeline extended: start=" + timelineStart + " days=" + timelineDays);
scope.changeBookView.days = scope.config.days = timelineDays;
scope.changeBookView.startDate = scope.config.startDate = timelineStart;
updateBookView();
positionTimeline();
}
return timelineModified;
}
function generateResourceArray(count) {
count = count || 10;
var resources = [
{ name: "", id: scope.model.currentRequestResourceId }
];
for (var i = 1; i < count; i++) {
resources.push({ name: "", id: i.toString() });
}
return resources;
}
function applyZoomLevel(increment) {
zoomLevel += increment;
if (zoomLevel < 0 || zoomLevel >= zoomLevels.length) {
zoomLevel -= increment;
return;
}
scope.model.zoomInDisabled = zoomLevel === 0;
scope.model.zoomOutDisabled = zoomLevel === zoomLevels.length - 1;
$log.log("book view timeline zoomed to " + zoomLevel + " level.");
scope.changeBookView.cellDuration = scope.config.cellDuration = zoomLevels[zoomLevel].cellDuration;
scope.changeBookView.timeHeaders = scope.config.timeHeaders = zoomLevels[zoomLevel].timeHeaders;
scope.changeBookView.days = scope.config.days = Math.max(timelineDays, zoomLevels[zoomLevel].minTimelineDays);
updateBookView();
}
positionTimeline();
}
};
}
]);
})();