(js) Improve attendees editor performance

This commit is contained in:
Francis Lachapelle
2019-08-26 16:38:00 -04:00
parent 4df69587a2
commit 991f1d25a4
4 changed files with 190 additions and 42 deletions
@@ -23,6 +23,7 @@
this.slotEndTimeLimit.setMinutes(0);
this.slotEndTimeLimit.setHours(Attendees.dayEndHour);
this.$days = [];
this.$futureFreebusyData = {};
this.updateFreeBusyCoverage();
this.updateFreeBusy();
}
@@ -432,6 +433,8 @@
promise = Attendees.$q.when();
}
this.$futureFreebusyData[attendee.uid] = promise;
return promise;
}
};
@@ -0,0 +1,58 @@
/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
(function() {
/**
* sgFreebusy - A directive that watches some attributes of a component. Any child component
* should depends on this directive and extend the 'onUpdate' method instead of creating new
* independent watchers.
* @memberof SOGo.SchedulerUI
*/
function sgFreebusy() {
return {
restrict: 'C',
scope: {},
bindToController: {
component: '=sgComponent'
},
controller: sgFreebusyController
};
}
/**
* @ngInject
*/
sgFreebusyController.$inject = ['$scope', '$element', '$q'];
function sgFreebusyController($scope, $element, $q) {
var $ctrl = this;
this.$onInit = function () {
var watchedAttrs = ['start', 'end', 'attendees'];
$scope.$watch(
function() {
return $ctrl.component? [ _.pick($ctrl.component, watchedAttrs) ] : null;
},
function(newId, oldId) {
if ($ctrl.component) {
// Component has changed
$q.all(_.values($ctrl.component.$attendees.$futureFreebusyData)).then(function() {
$ctrl.onUpdate();
});
}
},
true // compare for object equality
);
};
this.onUpdate = function () {
// console.debug('dates or attendees changed -- refresh freebusy');
};
}
angular
.module('SOGo.SchedulerUI')
.directive('sgFreebusy', sgFreebusy);
})();
@@ -0,0 +1,116 @@
/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
(function() {
/*
* sgFreebusyDay - A representation of the freebusy data for an attendee for one day.
* @memberof SOGo.SchedulerUI
* @restrict element
* @param {string} sgDay - the day string
* @param {object} sgAttendees - the Attendees object instance of the component
* @param {object} sgAttendee - the object representing the attendee
*
* @example:
<sg-freebusy-day
ng-repeat="currentAttendee in component.attendees"
sg-day="day.getDayString"
sg-attendees="component.$attendees"
sg-attendee="currentAttendee" />
*/
function sgFreebusyDay() {
return {
restrict: 'E',
require: '^^sgFreebusy',
bindToController: {
day: '=sgDay',
attendees: '=sgAttendees',
attendee: '=sgAttendee'
},
replace: true,
template: function(tElement, tAttrs) {
var template = [
'<md-list-item>'
];
for (var hour = 0; hour < 24; hour++) {
template.push(' <div class="hour">');
for (var quarter = 0; quarter < 4; quarter++) {
template.push(' <div class="quarter">');
template.push(' <div class="busy ng-hide"></div>');
template.push(' </div>');
}
template.push(' </div>');
}
template.push(' <md-divider><!-- divider --></md-divider>');
template.push('</md-list-item>');
return template.join('');
},
link: postLink,
controller: sgFreebusyDayController,
controllerAs: '$ctrl'
};
function postLink(scope, element, attrs, parentController) {
scope.parentController = parentController;
}
}
/**
* @ngInject
*/
sgFreebusyDayController.$inject = ['$scope', '$element'];
function sgFreebusyDayController($scope, $element) {
var $ctrl = this;
this.$postLink = function () {
var hours = [], quarters = [], busys = [], parentControllerOnUpdate;
this.parentController = $scope.parentController;
parentControllerOnUpdate = this.parentController.onUpdate;
_.forEach($element.find('div'), function(div) {
if (div.className.startsWith('hour')) hours.push(div);
else if (div.className.startsWith('quarter')) quarters.push(div);
else if (div.className.startsWith('busy')) busys.push(div);
});
this.parentController.onUpdate = function () {
var freebusys = $ctrl.attendee.freebusy[$ctrl.day];
if (!$ctrl.attendee.uid) {
_.forEach(hours, function(div) {
div.classList.add('sg-no-freebusy');
});
}
for (var hour = 0; hour < 24; hour++) {
for (var quarter = 0; quarter < 4; quarter++) {
var index = hour * 4 + quarter;
if ($ctrl.coversFreebusy(hour, quarter)) {
quarters[index].classList.add('event');
} else {
quarters[index].classList.remove('event');
}
if (freebusys[hour][quarter]) {
busys[index].classList.remove('ng-hide');
} else {
busys[index].classList.add('ng-hide');
}
}
}
// Call original method on parent controller
angular.bind($ctrl.parentController, parentControllerOnUpdate)();
};
};
this.coversFreebusy = function (hour, quarter) {
return $ctrl.attendees.coversFreeBusy($ctrl.day, hour, quarter);
};
}
angular
.module('SOGo.SchedulerUI')
.directive('sgFreebusyDay', sgFreebusyDay);
})();