tine20/Calendar/js/FreeTimeSearchDialog.js
Rama main · réplica de lectura del repositorio original.
/*
* Tine 2.0
*
* @package Calendar
* @license http://www.gnu.org/licenses/agpl.html AGPL Version 3
* @author Cornelius Weiss <c.weiss@metaways.de>
* @copyright Copyright (c) 2017 Metaways Infosystems GmbH (http://www.metaways.de)
*/
Ext.ns('Tine.Calendar');
/**
* @namespace Tine.Calendar
* @class Tine.Calendar.FreeTimeSearchDialog
* @extends Ext.Panel
*/
Tine.Calendar.FreeTimeSearchDialog = Ext.extend(Ext.Panel, {
cls: 'tw-editdialog',
layout: 'fit',
windowNamePrefix: 'CalFreeTimeSearchWindow_',
optionsStateId: 'FreeTimeSearchOptions',
canonicalName: ['', 'Calendar', 'FreeTimeSearchDialog'].join(Tine.Tinebase.CanonicalPath.separator),
initComponent: function() {
var _ = window.lodash;
this.app = Tine.Tinebase.appMgr.get('Calendar');
this.recordClass = Tine.Calendar.Model.Event;
this.recordProxy = Tine.Calendar.backend;
if (Ext.isString(this.record)) {
this.record = this.recordProxy.recordReader({responseText: this.record});
}
var prefs = this.app.getRegistry().peek('preferences');
Ext.DatePicker.prototype.startDay = parseInt((prefs ? prefs.get('firstdayofweek') : 1), 10);
this.store = new Ext.data.JsonStore({
fields: Tine.Calendar.Model.Event,
proxy: Tine.Calendar.backend,
reader: new Ext.data.JsonReader({})
});
this.calendarView = new Tine.Calendar.DaysView({
store: this.store,
startDate: new Date(),
numOfDays: 7,
readOnly: true
});
this.calendarView.getSelectionModel().on('selectionchange', this.onViewSelectionChange, this);
this.store.on('beforeload', this.onStoreBeforeload, this);
this.store.on('load', this.onStoreLoad, this);
this.detailsPanel = new Tine.Calendar.EventDetailsPanel();
this.freeTimeSlots = [];
this.tbar = [{
text: this.app.i18n._('Back'),
minWidth: 70,
ref: '../buttonBack',
iconCls: 'action_previous',
scope: this,
disabled: true,
handler: this.onButtonBack
}, {
text: this.app.i18n._('Next'),
minWidth: 70,
ref: '../buttonNext',
iconCls: 'action_next',
scope: this,
handler: this.onButtonNext
}, '-', {
text: this.app.i18n._('Options'),
minWidth: 70,
ref: '../buttonOptions',
iconCls: 'action_options',
scope: this,
handler: this.onButtonOptions
}];
this.fbar = ['->', {
text: i18n._('Cancel'),
minWidth: 70,
ref: '../buttonCancel',
scope: this,
handler: this.onButtonCancel,
iconCls: 'action_cancel'
}, {
text: i18n._('Ok'),
minWidth: 70,
ref: '../buttonApply',
scope: this,
handler: this.onButtonApply,
variant: 'primary',
iconCls: 'action_saveAndClose'
}];
this.items = [{
layout: 'border',
border: false,
items: [{
region: 'center',
layout: 'fit',
border: false,
items: this.calendarView
}, {
region: 'south',
border: false,
collapsible: true,
collapseMode: 'mini',
header: false,
split: true,
layout: 'fit',
height: this.detailsPanel.defaultHeight ? this.detailsPanel.defaultHeight : 125,
items: this.detailsPanel
}]
}];
Tine.Calendar.FreeTimeSearchDialog.superclass.initComponent.call(this);
this.constraints = Ext.state.Manager.get(this.optionsStateId, Tine.Calendar.EventFinderOptionsDialog.prototype.defaultOptions);
this.doFreeTimeSearch();
},
afterRender: function() {
Tine.Calendar.FreeTimeSearchDialog.superclass.afterRender.call(this);
this.window.setTitle(this.app.i18n._('Free Time Search'));
this.loadMask = new Ext.LoadMask(this.getEl(), {msg: this.app.i18n._("Searching for Free Time...")});
this.loadMask.show.defer(100, this.loadMask);
},
applyOptions: function(constraints) {
// nothing to do
if (Ext.encode(this.constraints) == Ext.encode(constraints)) return;
this.constraints = constraints;
this.doFreeTimeSearch()
},
doFreeTimeSearch: function(from) {
if (this.loadMask) {
this.loadMask.show();
}
var _ = window.lodash,
datePart = this.record.get('dtstart').add(Date.DAY, -7).format('Y-m-d '),
groupedConstraints = _.groupBy(_.filter(this.constraints, {active: true}), function(constraint) {
return constraint.period.from + '-' + constraint.period.until;
}),
constraints = _.reduce(groupedConstraints, function(result, constraintsGroup) {
return result.concat({
dtstart: datePart + constraintsGroup[0].period.from,
dtend: datePart + constraintsGroup[0].period.until,
rrule: 'FREQ=WEEKLY;INTERVAL=1;BYDAY=' + _.map(constraintsGroup, 'id').join(',')
});
}, []),
options = {
from: from ? from : this.record.get('dtstart'),
constraints: constraints
};
Tine.Calendar.searchFreeTime(this.record.data, options, this.onFreeTimeData, this);
},
onFreeTimeData: function(result) {
if (result.timeSearchStopped) {
return this.onFreeTimeSearchTimeout(result);
}
var _ = window.lodash,
timing = _.get(result, 'results[0]'),
dtStart = Date.parseDate(timing.dtstart, Date.patterns.ISO8601Long),
from = dtStart.clearTime(true).add(Date.DAY, -1 * dtStart.getDay())
.add(Date.DAY, Ext.DatePicker.prototype.startDay - (dtStart.getDay() == 0 ? 7 : 0)),
dtEnd = Date.parseDate(timing.dtend, Date.patterns.ISO8601Long),
until = from.add(Date.DAY, 7),
period = {from: from, until: until},
filterHash = Ext.encode(this.store.baseParams.filter);
this.store.remove(this.record);
this.record.set('dtstart', dtStart);
this.record.set('dtend', dtEnd);
this.freeTimeSlot = result;
// calculate period start
if (Ext.DatePicker.prototype.startDay) {
from = from.add(Date.DAY, Ext.DatePicker.prototype.startDay - (dtStart.getDay() == 0 ? 7 : 0));
}
this.store.baseParams.filter = [
{field: 'period', operator: 'within', value: period},
{field: 'attender', operator: 'in', value: this.record.get('attendee')},
{field: 'attender_status', operator: 'notin', value: 'DECLINED'}
];
if (this.record.get('id')) {
this.store.baseParams.filter.push({field: 'id', operator: 'not', value: this.record.get('id')});
}
if (filterHash == Ext.encode(this.store.baseParams.filter)) {
this.onStoreLoad();
} else {
this.calendarView.updatePeriod(period);
this.store.load();
}
},
onFreeTimeSearchTimeout: function(result) {
var _ = window.lodash,
dtStopped = Date.parseDate(_.get(result, 'timeSearchStopped'), Date.patterns.ISO8601Long),
stoppedString = Tine.Tinebase.common.dateRenderer(dtStopped);
Tine.widgets.dialog.MultiOptionsDialog.openWindow({
title: this.app.i18n._('No Free Time found'),
questionText: String.format(this.app.i18n._('No free timeslot could be found Until {0}. Do you want to continue?'), '<b>' + stoppedString + '</b>') + '<br><br>',
height: 170,
scope: this,
options: [
{text: this.app.i18n._('Continue'), name: 'continue'},
{text: this.app.i18n._('Give up'), name: 'giveUp'}
],
handler: function(option) {
switch(option) {
case 'giveUp':
this.onButtonCancel();
break;
case 'continue':
this.doFreeTimeSearch(Date.parseDate(dtStopped, Date.patterns.ISO8601Long));
break;
}
}
});
},
onStoreBeforeload: function() {
if (this.loadMask) {
this.loadMask.show();
}
},
onStoreLoad: function() {
this.store.each(function(event) {
if (event.ui) {
event.ui.setOpacity(0.5, 0);
}
}, this);
this.store.add([this.record]);
this.record.ui.setOpacity(1, 0);
// @TODO check if event is visible and skip scrolling -> defered scrolling looks ugly
// this.calendarView.scrollTo.defer(500, this.calendarView, [this.record.get('dtstart')]);
this.loadMask.hide();
},
onViewSelectionChange: function(sm, selections) {
this.detailsPanel.onDetailsUpdate(sm);
},
onButtonBack: function() {
this.onFreeTimeData(this.freeTimeSlots.pop());
this.buttonBack.setDisabled(!this.freeTimeSlots.length);
},
onButtonNext: function() {
this.freeTimeSlots.push(this.freeTimeSlot);
this.doFreeTimeSearch(this.record.get('dtend'));
this.buttonBack.enable();
},
onButtonOptions: function() {
Tine.Calendar.EventFinderOptionsDialog.openWindow({
titleText: this.app.i18n._('Free Time Search Options'),
stateId: this.optionsStateId,
recordId: this.record.id,
listeners: {
scope: this,
apply: this.onOptionsApply
}
});
},
onOptionsApply: function(dialog, options) {
this.applyOptions(Ext.decode(options));
},
onButtonCancel: function() {
this.fireEvent('cancel');
this.purgeListeners();
this.window.close();
},
onButtonApply: function() {
this.fireEvent('apply', this, Ext.encode(this.record.data));
this.purgeListeners();
this.window.close();
}
});
/**
* Opens a new free time serach dialog window
*
* @return {Ext.ux.Window}
*/
Tine.Calendar.FreeTimeSearchDialog.openWindow = function (config) {
var _ = window.lodash;
if (! _.isString(config.record)) {
config.record = Ext.encode(config.record.data);
}
return Tine.WindowFactory.getWindow({
width: 1024,
height: 768,
name: Tine.Calendar.FreeTimeSearchDialog.prototype.windowNamePrefix + _.get(config, 'record.id', 0),
contentPanelConstructor: 'Tine.Calendar.FreeTimeSearchDialog',
contentPanelConstructorConfig: config
});
};