mirror of
https://github.com/inverse-inc/sogo.git
synced 2026-07-20 15:44:53 +00:00
(js) Add drag'n'drop to month's view
This commit is contained in:
@@ -29,10 +29,11 @@
|
||||
},
|
||||
replace: true,
|
||||
template: [
|
||||
'<div class="sg-event sg-draggable-calendar-block"',
|
||||
'<div class="sg-event"',
|
||||
// Add a class while dragging
|
||||
' ng-class="{\'sg-event--dragging\': block.dragging}">',
|
||||
' <div class="eventInside" ng-click="clickBlock({clickEvent: $event, clickComponent: block.component})">',
|
||||
' <div class="eventInside"',
|
||||
' ng-click="clickBlock({clickEvent: $event, clickComponent: block.component})">',
|
||||
// Categories color stripes
|
||||
' <div class="sg-category" ng-repeat="category in block.component.categories"',
|
||||
' ng-class="\'bg-category\' + category"',
|
||||
@@ -86,7 +87,8 @@
|
||||
iElement.addClass('lasts' + scope.block.length);
|
||||
|
||||
// Set background color
|
||||
iElement.addClass('bg-folder' + scope.block.component.pid);
|
||||
if (scope.block.component)
|
||||
iElement.addClass('bg-folder' + scope.block.component.pid);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+27
-46
@@ -4,49 +4,22 @@
|
||||
'use strict';
|
||||
|
||||
/*
|
||||
* sgCalendarDayBlockGhost - An event ghost block to be displayed while dragging an event block. Each day of the
|
||||
* calendar's view is associated to a ghost block.
|
||||
* sgCalendarBlock - Applied to an event ghost block to be displayed while dragging an event block. Each day of the
|
||||
* calendar's view must have a ghost block.
|
||||
* @memberof SOGo.SchedulerUI
|
||||
* @restrict element
|
||||
* @restrict attribute
|
||||
*
|
||||
* @example:
|
||||
|
||||
<sg-calendar-day-block-ghost/>
|
||||
<sg-calendar-day-block
|
||||
sg-calendar-ghost
|
||||
sg-block="list.component.$ghost">/
|
||||
*/
|
||||
sgCalendarDayBlockGhost.$inject = ['$rootScope', '$timeout', 'CalendarSettings', 'Calendar', 'Component'];
|
||||
function sgCalendarDayBlockGhost($rootScope, $timeout, CalendarSettings, Calendar, Component) {
|
||||
sgCalendarGhost.$inject = ['$rootScope', '$timeout', 'CalendarSettings', 'Calendar', 'Component'];
|
||||
function sgCalendarGhost($rootScope, $timeout, CalendarSettings, Calendar, Component) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
restrict: 'A',
|
||||
require: ['^sgCalendarDay', '^sgCalendarScrollView'],
|
||||
replace: true,
|
||||
template: [
|
||||
'<div class="sg-event sg-event--ghost md-whiteframe-3dp ng-hide">',
|
||||
' <div class="eventInside">',
|
||||
// Categories color stripes
|
||||
' <div class="sg-category" ng-repeat="category in block.component.categories"',
|
||||
' ng-class="\'bg-category\' + category"',
|
||||
' ng-style="{ right: ($index * 3) + \'px\' }"></div>',
|
||||
' <div class="text">{{ block.component.summary }}',
|
||||
' <span class="icons">',
|
||||
// Component is reccurent
|
||||
' <md-icon ng-if="block.component.occurrenceId" class="material-icons icon-repeat"></md-icon>',
|
||||
// Component has an alarm
|
||||
' <md-icon ng-if="block.component.c_nextalarm" class="material-icons icon-alarm"></md-icon>',
|
||||
// Component is confidential
|
||||
' <md-icon ng-if="block.component.c_classification == 1" class="material-icons icon-visibility-off"></md-icon>',
|
||||
// Component is private
|
||||
' <md-icon ng-if="block.component.c_classification == 2" class="material-icons icon-vpn-key"></md-icon>',
|
||||
' </span>',
|
||||
// Location
|
||||
' <div class="secondary" ng-if="block.component.c_location">',
|
||||
' <md-icon>place</md-icon> {{block.component.c_location}}',
|
||||
' </div>',
|
||||
' </div>',
|
||||
' </div>',
|
||||
' <div class="ghostStartHour" ng-if="startHour">{{ startHour }}</div>',
|
||||
' <div class="ghostEndHour" ng-if="endHour">{{ endHour }}</div>',
|
||||
'</div>'
|
||||
].join(''),
|
||||
link: link
|
||||
};
|
||||
|
||||
@@ -57,6 +30,8 @@
|
||||
calendarDayCtrl = ctrls[0];
|
||||
scrollViewCtrl = ctrls[1];
|
||||
|
||||
iElement.addClass('sg-event--ghost md-whiteframe-3dp ng-hide');
|
||||
|
||||
// Listen on drag gestures
|
||||
var deregisterDragStart = $rootScope.$on('calendar:dragstart', initGhost);
|
||||
var deregisterDrag = $rootScope.$on('calendar:drag', updateGhost);
|
||||
@@ -88,7 +63,7 @@
|
||||
|
||||
function updateGhost() {
|
||||
// From SOGoEventDragGhostController._updateGhosts
|
||||
var showGhost, isAllDay, originalDay, currentDay, wasOtherBlock,
|
||||
var showGhost, isRelative, originalDay, currentDay, wasOtherBlock,
|
||||
start, duration, durationLeft, maxDuration, enableTransition;
|
||||
|
||||
showGhost = false;
|
||||
@@ -99,7 +74,7 @@
|
||||
if (Calendar.$view && Calendar.$view.type == scrollViewCtrl.type) {
|
||||
// The view of the dragging block is the scrolling view of this ghost block
|
||||
|
||||
isAllDay = scope.block.component.c_isallday;
|
||||
isRelative = scrollViewCtrl.type === 'multiday-allday' || scrollViewCtrl.type === 'monthly';
|
||||
originalDay = scope.block.pointerHandler.originalEventCoordinates.dayNumber;
|
||||
currentDay = scope.block.pointerHandler.currentEventCoordinates.dayNumber;
|
||||
start = scope.block.pointerHandler.currentEventCoordinates.start;
|
||||
@@ -119,14 +94,19 @@
|
||||
if (currentDay > -1 && currentDay == calendarDayCtrl.dayNumber) {
|
||||
// This ghost block (day) is the first of the dragging event
|
||||
showGhost = true;
|
||||
if (!isAllDay) {
|
||||
if (!isRelative) {
|
||||
// Show start hour and set the vertical position
|
||||
scope.startHour = getStartTime(start);
|
||||
wasOtherBlock = parseInt(iElement.css('top')) === 0;
|
||||
if (wasOtherBlock)
|
||||
iElement.addClass('sg-event--notransition');
|
||||
iElement.css('top', (start * Calendar.$view.quarterHeight) + 'px');
|
||||
iElement.css('height', (duration * Calendar.$view.quarterHeight) + 'px');
|
||||
// Set the height
|
||||
if (Calendar.$view.quarterHeight) {
|
||||
iElement.css('top', (start * Calendar.$view.quarterHeight) + 'px');
|
||||
iElement.css('height', (duration * Calendar.$view.quarterHeight) + 'px');
|
||||
}
|
||||
else
|
||||
iElement.css('top', Calendar.$view.topOffset + 'px');
|
||||
if (wasOtherBlock)
|
||||
$timeout(enableTransition);
|
||||
}
|
||||
@@ -146,13 +126,14 @@
|
||||
if (currentDay > -1 && currentDay == calendarDayCtrl.dayNumber) {
|
||||
// The dragging event overlaps this current ghost's day
|
||||
showGhost = true;
|
||||
if (!isAllDay) {
|
||||
if (!isRelative) {
|
||||
wasOtherBlock = parseInt(iElement.css('top')) !== 0;
|
||||
if (wasOtherBlock)
|
||||
iElement.addClass('sg-event--notransition');
|
||||
iElement.css('top', Calendar.$view.topOffset + 'px');
|
||||
// Set the height
|
||||
iElement.css('top', '0px');
|
||||
iElement.css('height', (duration * Calendar.$view.quarterHeight) + 'px');
|
||||
if (Calendar.$view.quarterHeight)
|
||||
iElement.css('height', (duration * Calendar.$view.quarterHeight) + 'px');
|
||||
if (wasOtherBlock)
|
||||
$timeout(enableTransition);
|
||||
}
|
||||
@@ -168,7 +149,7 @@
|
||||
}
|
||||
if (!durationLeft) {
|
||||
// Reached last ghost block
|
||||
if (isAllDay) {
|
||||
if (isRelative) {
|
||||
iElement.addClass('sg-event--ghost--last');
|
||||
}
|
||||
else {
|
||||
@@ -211,5 +192,5 @@
|
||||
|
||||
angular
|
||||
.module('SOGo.SchedulerUI')
|
||||
.directive('sgCalendarDayBlockGhost', sgCalendarDayBlockGhost);
|
||||
.directive('sgCalendarGhost', sgCalendarGhost);
|
||||
})();
|
||||
@@ -27,6 +27,7 @@
|
||||
},
|
||||
template: [
|
||||
'<sg-calendar-month-event',
|
||||
' class="sg-draggable-calendar-block"',
|
||||
' ng-repeat="block in blocks[day]"',
|
||||
' sg-block="block"',
|
||||
' sg-click="clickBlock({event: clickEvent, component: clickComponent})"/>'
|
||||
|
||||
@@ -24,8 +24,11 @@
|
||||
},
|
||||
replace: true,
|
||||
template: [
|
||||
'<div class="sg-event sg-draggable" ng-click="clickBlock({clickEvent: $event, clickComponent: block.component})">',
|
||||
' <span class="secondary" ng-if="!block.component.c_isallday">{{ block.starthour }} - </span>',
|
||||
'<div class="sg-event"',
|
||||
// Add a class while dragging
|
||||
' ng-class="{\'sg-event--dragging\': block.dragging}"',
|
||||
' ng-click="clickBlock({clickEvent: $event, clickComponent: block.component})">',
|
||||
' <span class="secondary" ng-if="!block.component.c_isallday">{{ block.starthour }}</span>',
|
||||
' {{ block.component.summary }}',
|
||||
' <span class="icons">',
|
||||
// Component is reccurent
|
||||
@@ -37,15 +40,14 @@
|
||||
// Component is private
|
||||
' <md-icon ng-if="block.component.c_classification == 2" class="material-icons icon-vpn-key"></md-icon>',
|
||||
' </span>',
|
||||
' <div class="leftDragGrip"></div>',
|
||||
' <div class="rightDragGrip"></div>',
|
||||
'</div>'
|
||||
].join(''),
|
||||
link: link
|
||||
};
|
||||
|
||||
function link(scope, iElement, attrs) {
|
||||
iElement.addClass('bg-folder' + scope.block.component.pid);
|
||||
if (scope.block.component)
|
||||
iElement.addClass('bg-folder' + scope.block.component.pid);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -68,29 +68,33 @@
|
||||
}
|
||||
|
||||
function getQuarterHeight() {
|
||||
var hour0, hour23, height;
|
||||
var hour0, hour23, height = null;
|
||||
|
||||
hour0 = document.getElementById('hour0');
|
||||
hour23 = document.getElementById('hour23');
|
||||
height = ((hour23.offsetTop - hour0.offsetTop) / (23 * 4));
|
||||
if (hour0 && hour23)
|
||||
height = ((hour23.offsetTop - hour0.offsetTop) / (23 * 4));
|
||||
|
||||
return height;
|
||||
}
|
||||
|
||||
function getDayWidth(viewLeft) {
|
||||
var width, offset, nodes, domRect;
|
||||
function getDayDimensions(viewLeft) {
|
||||
var width, height, leftOffset, topOffset, nodes, domRect, tileHeader;
|
||||
|
||||
width = 0;
|
||||
offset = 0;
|
||||
height = width = leftOffset = topOffset = 0;
|
||||
nodes = scrollView.getElementsByClassName('day0');
|
||||
|
||||
if (nodes.length > 0) {
|
||||
domRect = nodes[0].getBoundingClientRect();
|
||||
height = domRect.height;
|
||||
width = domRect.width;
|
||||
offset = domRect.left - viewLeft;
|
||||
leftOffset = domRect.left - viewLeft;
|
||||
tileHeader = nodes[0].getElementsByClassName('sg-calendar-tile-header');
|
||||
if (tileHeader.length > 0)
|
||||
topOffset = tileHeader[0].clientHeight;
|
||||
}
|
||||
|
||||
return [width, offset];
|
||||
return { height: height, width: width, offset: { left: leftOffset, top: topOffset } };
|
||||
}
|
||||
|
||||
function getMaxColumns() {
|
||||
@@ -104,20 +108,22 @@
|
||||
}
|
||||
|
||||
// View has been resized;
|
||||
// Compute the view's origins (x, y), a day's width (dayWidth) and the left margin (daysOffset).
|
||||
// Compute the view's origins (x, y), a day's dimensions and left margin.
|
||||
function updateCoordinates() {
|
||||
var domRect, dayWidth;
|
||||
var domRect, dayDimensions;
|
||||
|
||||
domRect = scrollView.getBoundingClientRect();
|
||||
dayWidth = getDayWidth(domRect.left);
|
||||
dayDimensions = getDayDimensions(domRect.left);
|
||||
|
||||
angular.extend(view, {
|
||||
coordinates: {
|
||||
x: domRect.left,
|
||||
y: domRect.top
|
||||
},
|
||||
dayWidth: dayWidth[0],
|
||||
daysOffset: dayWidth[1]
|
||||
dayHeight: dayDimensions.height,
|
||||
dayWidth: dayDimensions.width,
|
||||
daysOffset: dayDimensions.offset.left,
|
||||
topOffset: dayDimensions.offset.top
|
||||
});
|
||||
}
|
||||
|
||||
@@ -138,31 +144,31 @@
|
||||
scrollStep = view.scrollStep;
|
||||
pointerHandler = Component.$ghost.pointerHandler;
|
||||
if (pointerHandler) {
|
||||
pointerCoordinates = pointerHandler.getContainerBasedCoordinates(view);
|
||||
pointerCoordinates = pointerHandler.getContainerBasedCoordinates(view);
|
||||
|
||||
if (pointerCoordinates) {
|
||||
// Pointer is inside view; Adjust scrollbar if necessary
|
||||
Calendar.$view = view;
|
||||
now = new Date().getTime();
|
||||
if (!lastScroll || now > lastScroll + 100) {
|
||||
lastScroll = now;
|
||||
scrollY = pointerCoordinates.y - scrollStep;
|
||||
if (scrollY < 0) {
|
||||
minY = -scrollView.scrollTop;
|
||||
if (scrollY < minY)
|
||||
scrollY = minY;
|
||||
scrollView.scrollTop += scrollY;
|
||||
}
|
||||
else {
|
||||
scrollY = pointerCoordinates.y + scrollStep;
|
||||
delta = scrollY - scrollView.clientHeight;
|
||||
if (delta > 0) {
|
||||
scrollView.scrollTop += delta;
|
||||
if (pointerCoordinates) {
|
||||
// Pointer is inside view; Adjust scrollbar if necessary
|
||||
Calendar.$view = view;
|
||||
now = new Date().getTime();
|
||||
if (!lastScroll || now > lastScroll + 100) {
|
||||
lastScroll = now;
|
||||
scrollY = pointerCoordinates.y - scrollStep;
|
||||
if (scrollY < 0) {
|
||||
minY = -scrollView.scrollTop;
|
||||
if (scrollY < minY)
|
||||
scrollY = minY;
|
||||
scrollView.scrollTop += scrollY;
|
||||
}
|
||||
else {
|
||||
scrollY = pointerCoordinates.y + scrollStep;
|
||||
delta = scrollY - scrollView.clientHeight;
|
||||
if (delta > 0) {
|
||||
scrollView.scrollTop += delta;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -47,7 +47,8 @@
|
||||
dragGrip = angular.element('<div class="dragGrip"></div>');
|
||||
dragGrip.addClass('bdr-folder' + component.pid);
|
||||
|
||||
if (component.c_isallday) {
|
||||
if (component.c_isallday ||
|
||||
element[0].parentNode.tagName === 'SG-CALENDAR-MONTH-DAY') {
|
||||
if (isFirstBlock) {
|
||||
leftGrip = angular.element('<div class="dragGrip-left"></div>').append(dragGrip);
|
||||
element.append(leftGrip);
|
||||
@@ -73,8 +74,7 @@
|
||||
var block, dragMode, eventType, startDate, newData, newComponent, pointerHandler;
|
||||
|
||||
dragMode = 'move-event';
|
||||
eventType = 'multiday';
|
||||
|
||||
|
||||
if (scope.block && scope.block.component) {
|
||||
// Move or resize existing component
|
||||
if (ev.target.className == 'dragGrip-top' ||
|
||||
@@ -136,7 +136,9 @@
|
||||
b.dragging = true;
|
||||
});
|
||||
|
||||
if (block.component.c_isallday)
|
||||
if (element[0].parentNode.tagName === 'SG-CALENDAR-MONTH-DAY')
|
||||
eventType = 'monthly';
|
||||
else if (block.component.c_isallday)
|
||||
eventType = 'multiday-allday';
|
||||
|
||||
// Update pointer handler
|
||||
@@ -145,6 +147,7 @@
|
||||
pointerHandler.initFromBlock(block);
|
||||
|
||||
// Update Component.$ghost
|
||||
Component.$ghost.starthour = block.starthour;
|
||||
Component.$ghost.component = block.component;
|
||||
|
||||
$log.debug('emit calendar:dragstart');
|
||||
@@ -220,7 +223,8 @@
|
||||
/**
|
||||
* SOGoEventDragEventCoordinates
|
||||
*/
|
||||
function SOGoEventDragEventCoordinates() {
|
||||
function SOGoEventDragEventCoordinates(eventType) {
|
||||
this.setEventType(eventType);
|
||||
}
|
||||
|
||||
SOGoEventDragEventCoordinates.prototype = {
|
||||
@@ -235,13 +239,19 @@
|
||||
},
|
||||
|
||||
initFromBlock: function(block) {
|
||||
// Get the start (first quarter) from the event's first block
|
||||
this.start = block.component.blocks[0].start;
|
||||
if (this.eventType === 'monthly')
|
||||
this.start = 0;
|
||||
else
|
||||
// Get the start (first quarter) from the event's first block
|
||||
this.start = block.component.blocks[0].start;
|
||||
|
||||
// Compute overall length
|
||||
this.duration = _.sum(block.component.blocks, function(b) {
|
||||
return b.length;
|
||||
});
|
||||
if (this.eventType === 'monthly')
|
||||
this.duration = block.component.blocks.length * 96;
|
||||
else
|
||||
this.duration = _.sum(block.component.blocks, function(b) {
|
||||
return b.length;
|
||||
});
|
||||
|
||||
// Get the dayNumber from the event's first block
|
||||
this.dayNumber = block.component.blocks[0].dayNumber;
|
||||
@@ -299,7 +309,7 @@
|
||||
originalCoordinates: null,
|
||||
currentCoordinates: null,
|
||||
|
||||
// Pointer relative xy coordinates within view
|
||||
// Pointer relative xy coordinates within view (row-column)
|
||||
originalViewCoordinates: null,
|
||||
currentViewCoordinates: null,
|
||||
|
||||
@@ -314,8 +324,8 @@
|
||||
getEventViewCoordinates: null,
|
||||
|
||||
initFromBlock: function SEDPH_initFromBlock(block) {
|
||||
this.currentEventCoordinates = new SOGoEventDragEventCoordinates();
|
||||
this.originalEventCoordinates = new SOGoEventDragEventCoordinates();
|
||||
this.currentEventCoordinates = new SOGoEventDragEventCoordinates(this.eventType);
|
||||
this.originalEventCoordinates = new SOGoEventDragEventCoordinates(this.eventType);
|
||||
this.originalEventCoordinates.initFromBlock(block);
|
||||
},
|
||||
|
||||
@@ -375,7 +385,7 @@
|
||||
var deltaQuarters = delta.x * CalendarSettings.EventDragDayLength + delta.y;
|
||||
$log.debug('quarters delta ' + deltaQuarters);
|
||||
|
||||
if (!this.originalEventCoordinates.start) {
|
||||
if (angular.isUndefined(this.originalEventCoordinates.start)) {
|
||||
this.originalEventCoordinates.dayNumber = this.originalViewCoordinates.x;
|
||||
this.originalEventCoordinates.start = this.originalViewCoordinates.y;
|
||||
}
|
||||
@@ -498,35 +508,36 @@
|
||||
|
||||
return coordinates;
|
||||
},
|
||||
// getEventMonthlyViewCoordinates: function SEDPH_gEMonthlyViewC() {
|
||||
// /* x = day; y = quarter */
|
||||
// var coordinates;
|
||||
getEventMonthlyViewCoordinates: function SEDPH_gEMonthlyViewC(view, pointerCoordinates) {
|
||||
/* x = day; y = quarter */
|
||||
var coordinates;
|
||||
|
||||
// var pxCoordinates = this.getContainerBasedCoordinates();
|
||||
// if (pxCoordinates) {
|
||||
// coordinates = new SOGoCoordinates();
|
||||
// var utilities = SOGoEventDragUtilities();
|
||||
// var daysOffset = utilities.getDaysOffset();
|
||||
// var daysTopOffset = daysOffset; /* change later */
|
||||
// var dayHeight = utilities.getDayHeight();
|
||||
// var daysY = Math.floor((pxCoordinates.y - daysTopOffset) / dayHeight);
|
||||
// if (daysY < 0)
|
||||
// daysY = 0;
|
||||
// var dayWidth = utilities.getDayWidth();
|
||||
var pxCoordinates = this.getContainerBasedCoordinates(view, pointerCoordinates);
|
||||
if (pxCoordinates) {
|
||||
coordinates = new SOGoCoordinates();
|
||||
|
||||
// coordinates.x = Math.floor((pxCoordinates.x - daysOffset) / dayWidth);
|
||||
// if (coordinates.x < 0)
|
||||
// coordinates.x = 0;
|
||||
// else if (coordinates.x > 6)
|
||||
// coordinates.x = 6;
|
||||
// coordinates.x += 7 * daysY;
|
||||
// coordinates.y = 0;
|
||||
// } else {
|
||||
// coordinates = null;
|
||||
// }
|
||||
var daysTopOffset = 0;
|
||||
var dayWidth = view.dayWidth;
|
||||
var daysOffset = view.daysOffset;
|
||||
var dayHeight = view.dayHeight;
|
||||
var daysY = Math.floor((pxCoordinates.y - daysTopOffset) / dayHeight);
|
||||
if (daysY < 0)
|
||||
daysY = 0;
|
||||
|
||||
// return coordinates;
|
||||
// },
|
||||
coordinates.x = Math.floor((pxCoordinates.x - daysOffset) / dayWidth);
|
||||
if (coordinates.x < 0)
|
||||
coordinates.x = 0;
|
||||
else if (coordinates.x > 6)
|
||||
coordinates.x = 6;
|
||||
coordinates.x += 7 * daysY;
|
||||
coordinates.y = 0;
|
||||
}
|
||||
else {
|
||||
coordinates = null;
|
||||
}
|
||||
|
||||
return coordinates;
|
||||
},
|
||||
|
||||
getDistance: function SEDPH_getDistance() {
|
||||
return this.currentCoordinates.getDistance(this.originalCoordinates);
|
||||
|
||||
Reference in New Issue
Block a user