2021-04-02 11:44:28 +00:00
|
|
|
|
define([
|
|
|
|
|
'jquery',
|
2021-04-13 13:21:24 +00:00
|
|
|
|
'json.sortify',
|
2021-04-02 11:44:28 +00:00
|
|
|
|
'/bower_components/chainpad-crypto/crypto.js',
|
|
|
|
|
'/common/toolbar.js',
|
|
|
|
|
'/bower_components/nthen/index.js',
|
|
|
|
|
'/common/sframe-common.js',
|
|
|
|
|
'/common/common-util.js',
|
|
|
|
|
'/common/common-hash.js',
|
|
|
|
|
'/common/common-interface.js',
|
|
|
|
|
'/common/common-ui-elements.js',
|
|
|
|
|
'/common/common-realtime.js',
|
|
|
|
|
'/common/clipboard.js',
|
|
|
|
|
'/common/inner/common-mediatag.js',
|
|
|
|
|
'/common/hyperscript.js',
|
|
|
|
|
'/customize/messages.js',
|
|
|
|
|
'/customize/application_config.js',
|
|
|
|
|
'/lib/calendar/tui-calendar.min.js',
|
2021-04-15 09:10:11 +00:00
|
|
|
|
'/calendar/export.js',
|
2022-08-30 11:17:57 +00:00
|
|
|
|
'/calendar/recurrence.js',
|
2021-06-17 16:05:25 +00:00
|
|
|
|
'/lib/datepicker/flatpickr.js',
|
2021-04-02 11:44:28 +00:00
|
|
|
|
|
2021-04-06 15:25:18 +00:00
|
|
|
|
'/common/inner/share.js',
|
|
|
|
|
'/common/inner/access.js',
|
|
|
|
|
'/common/inner/properties.js',
|
|
|
|
|
|
2021-04-02 16:21:59 +00:00
|
|
|
|
'/common/jscolor.js',
|
2021-04-15 09:10:11 +00:00
|
|
|
|
'/bower_components/file-saver/FileSaver.min.js',
|
2021-04-02 11:44:28 +00:00
|
|
|
|
'css!/lib/calendar/tui-calendar.min.css',
|
|
|
|
|
'css!/bower_components/components-font-awesome/css/font-awesome.min.css',
|
2022-09-13 13:30:25 +00:00
|
|
|
|
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css',
|
2021-04-02 11:44:28 +00:00
|
|
|
|
'less!/calendar/app-calendar.less',
|
|
|
|
|
], function (
|
|
|
|
|
$,
|
2021-04-13 13:21:24 +00:00
|
|
|
|
JSONSortify,
|
2021-04-02 11:44:28 +00:00
|
|
|
|
Crypto,
|
|
|
|
|
Toolbar,
|
|
|
|
|
nThen,
|
|
|
|
|
SFCommon,
|
|
|
|
|
Util,
|
|
|
|
|
Hash,
|
|
|
|
|
UI,
|
|
|
|
|
UIElements,
|
|
|
|
|
Realtime,
|
|
|
|
|
Clipboard,
|
|
|
|
|
MT,
|
|
|
|
|
h,
|
|
|
|
|
Messages,
|
|
|
|
|
AppConfig,
|
2021-04-06 15:25:18 +00:00
|
|
|
|
Calendar,
|
2021-04-15 09:10:11 +00:00
|
|
|
|
Export,
|
2022-08-30 11:17:57 +00:00
|
|
|
|
Rec,
|
2021-06-17 16:05:25 +00:00
|
|
|
|
Flatpickr,
|
2021-04-06 15:25:18 +00:00
|
|
|
|
Share, Access, Properties
|
2021-04-02 11:44:28 +00:00
|
|
|
|
)
|
|
|
|
|
{
|
2021-04-15 09:10:11 +00:00
|
|
|
|
var SaveAs = window.saveAs;
|
2021-04-02 11:44:28 +00:00
|
|
|
|
var APP = window.APP = {
|
2021-04-02 13:18:59 +00:00
|
|
|
|
calendars: {}
|
2021-04-02 11:44:28 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var common;
|
2021-04-06 16:21:48 +00:00
|
|
|
|
var metadataMgr;
|
2021-04-02 11:44:28 +00:00
|
|
|
|
var sframeChan;
|
|
|
|
|
|
2021-04-02 16:21:59 +00:00
|
|
|
|
var onCalendarsUpdate = Util.mkEvent();
|
2021-04-02 13:18:59 +00:00
|
|
|
|
|
|
|
|
|
var newCalendar = function (data, cb) {
|
|
|
|
|
APP.module.execCommand('CREATE', data, function (obj) {
|
|
|
|
|
if (obj && obj.error) { return void cb(obj.error); }
|
|
|
|
|
cb(null, obj);
|
|
|
|
|
});
|
|
|
|
|
};
|
2021-04-02 16:21:59 +00:00
|
|
|
|
var updateCalendar = function (data, cb) {
|
|
|
|
|
APP.module.execCommand('UPDATE', data, function (obj) {
|
|
|
|
|
if (obj && obj.error) { return void cb(obj.error); }
|
|
|
|
|
cb(null, obj);
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
var deleteCalendar = function (data, cb) {
|
|
|
|
|
APP.module.execCommand('DELETE', data, function (obj) {
|
|
|
|
|
if (obj && obj.error) { return void cb(obj.error); }
|
|
|
|
|
cb(null, obj);
|
|
|
|
|
});
|
|
|
|
|
};
|
2021-04-07 14:41:39 +00:00
|
|
|
|
var importCalendar = function (data, cb) {
|
|
|
|
|
APP.module.execCommand('IMPORT', data, function (obj) {
|
|
|
|
|
if (obj && obj.error) { return void cb(obj.error); }
|
|
|
|
|
cb(null, obj);
|
|
|
|
|
});
|
|
|
|
|
};
|
2021-04-15 15:45:38 +00:00
|
|
|
|
var importICSCalendar = function (data, cb) {
|
|
|
|
|
APP.module.execCommand('IMPORT_ICS', data, function (obj) {
|
|
|
|
|
if (obj && obj.error) { return void cb(obj.error); }
|
|
|
|
|
cb(null, obj);
|
|
|
|
|
});
|
|
|
|
|
};
|
2021-04-02 13:18:59 +00:00
|
|
|
|
var newEvent = function (data, cb) {
|
|
|
|
|
APP.module.execCommand('CREATE_EVENT', data, function (obj) {
|
|
|
|
|
if (obj && obj.error) { return void cb(obj.error); }
|
|
|
|
|
cb(null, obj);
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
var updateEvent = function (data, cb) {
|
|
|
|
|
APP.module.execCommand('UPDATE_EVENT', data, function (obj) {
|
|
|
|
|
if (obj && obj.error) { return void cb(obj.error); }
|
|
|
|
|
cb(null, obj);
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
var deleteEvent = function (data, cb) {
|
|
|
|
|
APP.module.execCommand('DELETE_EVENT', data, function (obj) {
|
|
|
|
|
if (obj && obj.error) { return void cb(obj.error); }
|
|
|
|
|
cb(null, obj);
|
|
|
|
|
});
|
|
|
|
|
};
|
2021-04-02 11:44:28 +00:00
|
|
|
|
|
2021-04-02 13:18:59 +00:00
|
|
|
|
var getContrast = function (color) {
|
|
|
|
|
var rgb = Util.hexToRGB(color);
|
|
|
|
|
// http://www.w3.org/TR/AERT#color-contrast
|
|
|
|
|
var brightness = Math.round(((parseInt(rgb[0]) * 299) +
|
|
|
|
|
(parseInt(rgb[1]) * 587) +
|
|
|
|
|
(parseInt(rgb[2]) * 114)) / 1000);
|
2021-04-22 16:33:17 +00:00
|
|
|
|
return (brightness > 125) ? '#424242' : '#EEEEEE';
|
2021-04-02 13:18:59 +00:00
|
|
|
|
};
|
2021-04-02 16:21:59 +00:00
|
|
|
|
|
2022-10-25 09:07:54 +00:00
|
|
|
|
var getDateLanguage = function () {
|
|
|
|
|
console.error(Messages._languageUsed);
|
|
|
|
|
try {
|
|
|
|
|
new Date().toLocaleDateString(Messages._languageUsed, { weekday: 'long' });
|
|
|
|
|
return Messages._languageUsed;
|
|
|
|
|
} catch (e) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2021-04-27 10:31:13 +00:00
|
|
|
|
var getWeekDays = function (large) {
|
2021-05-17 09:00:25 +00:00
|
|
|
|
var baseDate = new Date(2017, 0, 1); // just a Sunday
|
2021-04-02 16:21:59 +00:00
|
|
|
|
var weekDays = [];
|
2021-04-08 12:02:39 +00:00
|
|
|
|
for(var i = 0; i < 7; i++) {
|
2022-10-25 09:07:54 +00:00
|
|
|
|
weekDays.push(baseDate.toLocaleDateString(getDateLanguage(), { weekday: 'long' }));
|
2021-04-02 16:21:59 +00:00
|
|
|
|
baseDate.setDate(baseDate.getDate() + 1);
|
|
|
|
|
}
|
2021-04-27 10:31:13 +00:00
|
|
|
|
if (!large) {
|
|
|
|
|
weekDays = weekDays.map(function (day) { return day.slice(0,3); });
|
|
|
|
|
}
|
2021-04-08 12:02:39 +00:00
|
|
|
|
return weekDays.map(function (day) { return day.replace(/^./, function (str) { return str.toUpperCase(); }); });
|
2021-04-02 16:21:59 +00:00
|
|
|
|
};
|
|
|
|
|
|
2022-09-14 14:11:54 +00:00
|
|
|
|
// Get week number in our calendar view
|
|
|
|
|
var ISO8601_week_no = function (dt) {
|
|
|
|
|
var tdt = new Date(dt.valueOf());
|
|
|
|
|
var dayn = (dt.getDay() + 6) % 7;
|
|
|
|
|
tdt.setDate(tdt.getDate() - dayn + 3);
|
|
|
|
|
var firstThursday = tdt.valueOf();
|
|
|
|
|
tdt.setMonth(0, 1);
|
|
|
|
|
if (tdt.getDay() !== 4) {
|
|
|
|
|
tdt.setMonth(0, 1 + ((4 - tdt.getDay()) + 7) % 7);
|
|
|
|
|
}
|
|
|
|
|
return 1 + Math.ceil((firstThursday - tdt) / 604800000);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var updateDateRange = function () {
|
|
|
|
|
var range = APP.calendar._renderRange;
|
|
|
|
|
var start = range.start._date.toLocaleDateString();
|
|
|
|
|
var end = range.end._date.toLocaleDateString();
|
|
|
|
|
var week = ISO8601_week_no(range.start._date);
|
|
|
|
|
var date = [
|
|
|
|
|
h('b.cp-small', Messages._getKey('calendar_weekNumber', [week])),
|
|
|
|
|
h('b', start),
|
|
|
|
|
h('span', ' - '),
|
|
|
|
|
h('b', end),
|
|
|
|
|
];
|
|
|
|
|
if (APP.calendar._viewName === "day") {
|
|
|
|
|
date = h('b', start);
|
|
|
|
|
} else if (APP.calendar._viewName === "month") {
|
|
|
|
|
var month;
|
|
|
|
|
var mid = new Date(Math.floor(((+range.start._date) + (+range.end._date)) / 2));
|
|
|
|
|
try {
|
|
|
|
|
month = mid.toLocaleString('default', {
|
|
|
|
|
month: 'long',
|
|
|
|
|
year:'numeric'
|
|
|
|
|
});
|
|
|
|
|
month = month.replace(/^./, function (str) { return str.toUpperCase(); });
|
|
|
|
|
date = h('b', month);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
// Use same as week range: first day of month to last day of month
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
APP.toolbar.$bottomM.empty().append(h('div', date));
|
|
|
|
|
};
|
|
|
|
|
APP.moveToDate = function (time) {
|
|
|
|
|
var cal = APP.calendar;
|
|
|
|
|
if (!cal) { return; }
|
|
|
|
|
|
|
|
|
|
// Move calendar to correct date
|
|
|
|
|
var d = new Date(time);
|
|
|
|
|
cal.setDate(d);
|
|
|
|
|
updateDateRange();
|
|
|
|
|
|
2022-09-15 14:33:50 +00:00
|
|
|
|
if (cal.getViewName() === 'month') { return; }
|
|
|
|
|
|
2022-09-14 14:11:54 +00:00
|
|
|
|
// Scroll to correct time
|
|
|
|
|
setTimeout(function () {
|
|
|
|
|
var h = d.toLocaleTimeString('en-US', { hour12: 0, timeStyle: "short" }).slice(0,2);
|
|
|
|
|
h = Number(h) % 24;
|
|
|
|
|
var $h = $('.tui-full-calendar-timegrid-timezone .tui-full-calendar-timegrid-hour');
|
|
|
|
|
try { $h.get(h).scrollIntoView(); } catch (e) { console.error(e); }
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
2021-04-02 13:18:59 +00:00
|
|
|
|
var getCalendars = function () {
|
2022-03-31 06:27:56 +00:00
|
|
|
|
var LOOKUP = {};
|
|
|
|
|
var TEAMS = {};
|
2021-04-02 13:18:59 +00:00
|
|
|
|
return Object.keys(APP.calendars).map(function (id) {
|
|
|
|
|
var c = APP.calendars[id];
|
2021-04-06 13:01:43 +00:00
|
|
|
|
if (c.hidden || c.restricted || c.loading) { return; }
|
2021-04-02 13:18:59 +00:00
|
|
|
|
var md = Util.find(c, ['content', 'metadata']);
|
|
|
|
|
if (!md) { return void console.error('Ignore calendar without metadata'); }
|
|
|
|
|
return {
|
|
|
|
|
id: id,
|
2021-04-13 09:09:14 +00:00
|
|
|
|
name: md.title,
|
2021-04-02 13:18:59 +00:00
|
|
|
|
color: getContrast(md.color),
|
|
|
|
|
bgColor: md.color,
|
|
|
|
|
dragBgColor: md.color,
|
|
|
|
|
borderColor: md.color,
|
|
|
|
|
};
|
2022-03-31 06:27:56 +00:00
|
|
|
|
}).filter(Boolean).map(function (obj) {
|
|
|
|
|
var id = obj.id;
|
|
|
|
|
var cal = APP.calendars[id];
|
|
|
|
|
var team = cal.teams.sort()[0] || cal.roTeams.sort()[0];
|
|
|
|
|
var title = Util.find(cal, ['content', 'metadata', 'title']) || '';
|
|
|
|
|
LOOKUP[id] = title;
|
|
|
|
|
TEAMS[id] = team;
|
|
|
|
|
return obj;
|
|
|
|
|
}).sort(function (a, b) {
|
|
|
|
|
var team1 = TEAMS[a.id];
|
|
|
|
|
var team2 = TEAMS[b.id];
|
|
|
|
|
var t1 = LOOKUP[a.id];
|
|
|
|
|
var t2 = LOOKUP[b.id];
|
2022-03-30 13:58:47 +00:00
|
|
|
|
return team1 > team2 ? 1 :
|
|
|
|
|
(team1 < team2 ? -1 : (
|
|
|
|
|
t1 > t2 ? 1 : (t1 < t2 ? -1 : 0)));
|
|
|
|
|
});
|
2021-04-02 13:18:59 +00:00
|
|
|
|
};
|
|
|
|
|
var getSchedules = function () {
|
2022-08-30 11:17:57 +00:00
|
|
|
|
APP.recurringEvents = [];
|
|
|
|
|
APP.recurringDone = [];
|
2021-04-02 13:18:59 +00:00
|
|
|
|
var s = [];
|
2021-04-22 16:33:17 +00:00
|
|
|
|
var calendars = Object.keys(APP.calendars);
|
|
|
|
|
if (APP.currentCalendar) {
|
|
|
|
|
var currentCal = calendars.filter(function (id) {
|
|
|
|
|
var c = APP.calendars[id];
|
|
|
|
|
var t = c.teams || [];
|
|
|
|
|
if (id !== APP.currentCalendar) { return; }
|
|
|
|
|
return t.length === 1 && t[0] === 0;
|
|
|
|
|
});
|
|
|
|
|
if (currentCal.length) { calendars = currentCal; }
|
|
|
|
|
}
|
|
|
|
|
calendars.forEach(function (id) {
|
2021-04-02 13:18:59 +00:00
|
|
|
|
var c = APP.calendars[id];
|
2021-04-06 13:01:43 +00:00
|
|
|
|
if (c.hidden || c.restricted || c.loading) { return; }
|
2021-04-02 13:18:59 +00:00
|
|
|
|
var data = c.content || {};
|
|
|
|
|
Object.keys(data.content || {}).forEach(function (uid) {
|
|
|
|
|
var obj = data.content[uid];
|
2021-04-13 09:09:14 +00:00
|
|
|
|
obj.title = obj.title || "";
|
|
|
|
|
obj.location = obj.location || "";
|
2021-06-17 16:05:25 +00:00
|
|
|
|
if (obj.isAllDay && obj.startDay) { obj.start = +Flatpickr.parseDate((obj.startDay)); }
|
2021-04-13 14:38:50 +00:00
|
|
|
|
if (obj.isAllDay && obj.endDay) {
|
2021-06-17 16:05:25 +00:00
|
|
|
|
var endDate = Flatpickr.parseDate(obj.endDay);
|
2021-04-13 14:38:50 +00:00
|
|
|
|
endDate.setHours(23);
|
|
|
|
|
endDate.setMinutes(59);
|
|
|
|
|
endDate.setSeconds(59);
|
|
|
|
|
obj.end = +endDate;
|
|
|
|
|
}
|
2021-04-06 12:03:51 +00:00
|
|
|
|
if (c.readOnly) {
|
|
|
|
|
obj.isReadOnly = true;
|
|
|
|
|
}
|
2022-08-30 11:17:57 +00:00
|
|
|
|
if (obj.recurrenceRule) {
|
|
|
|
|
APP.recurringEvents.push(obj);
|
|
|
|
|
}
|
2022-09-08 15:03:08 +00:00
|
|
|
|
s.push(Util.clone(data.content[uid]));
|
2021-04-02 13:18:59 +00:00
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
return s;
|
|
|
|
|
};
|
2022-08-30 11:17:57 +00:00
|
|
|
|
|
2022-09-12 17:06:25 +00:00
|
|
|
|
var applyUpdates = Rec.applyUpdates;
|
2022-09-08 14:56:58 +00:00
|
|
|
|
|
2022-08-30 11:17:57 +00:00
|
|
|
|
var updateRecurring = function () {}; // Defined later
|
2021-04-02 16:21:59 +00:00
|
|
|
|
var renderCalendar = function () {
|
|
|
|
|
var cal = APP.calendar;
|
|
|
|
|
if (!cal) { return; }
|
|
|
|
|
|
2022-09-08 14:56:58 +00:00
|
|
|
|
try {
|
|
|
|
|
cal.clear();
|
|
|
|
|
cal.setCalendars(getCalendars());
|
|
|
|
|
cal.createSchedules(applyUpdates(getSchedules()), true);
|
|
|
|
|
cal.render();
|
2022-09-14 14:11:54 +00:00
|
|
|
|
if (APP.initTime && APP.moveToDate) {
|
|
|
|
|
APP.moveToDate(APP.initTime);
|
|
|
|
|
delete APP.initTime;
|
|
|
|
|
}
|
2022-09-08 14:56:58 +00:00
|
|
|
|
Rec.resetCache();
|
|
|
|
|
updateRecurring();
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error(e);
|
|
|
|
|
}
|
2021-04-02 16:21:59 +00:00
|
|
|
|
};
|
|
|
|
|
var onCalendarUpdate = function (data) {
|
2021-04-02 13:18:59 +00:00
|
|
|
|
var cal = APP.calendar;
|
|
|
|
|
|
2021-04-06 08:37:31 +00:00
|
|
|
|
if (data.deleted) {
|
|
|
|
|
// Remove this calendar
|
|
|
|
|
delete APP.calendars[data.id];
|
|
|
|
|
} else {
|
|
|
|
|
// Update local data
|
|
|
|
|
APP.calendars[data.id] = data;
|
|
|
|
|
}
|
2021-04-02 11:44:28 +00:00
|
|
|
|
|
2021-04-02 13:18:59 +00:00
|
|
|
|
// If calendar if initialized, update it
|
|
|
|
|
if (!cal) { return; }
|
2021-04-02 16:21:59 +00:00
|
|
|
|
onCalendarsUpdate.fire();
|
|
|
|
|
renderCalendar();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var getTime = function (time) {
|
|
|
|
|
var d = new Date();
|
|
|
|
|
d.setHours(time.hour);
|
|
|
|
|
d.setMinutes(time.minutes);
|
|
|
|
|
return d.toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'});
|
2021-04-02 11:44:28 +00:00
|
|
|
|
};
|
|
|
|
|
|
2021-04-02 16:21:59 +00:00
|
|
|
|
// If this browser doesn't support options to toLocaleTimeString, use default layout
|
|
|
|
|
if (!(function () {
|
|
|
|
|
// Modern browser will return a RangeError if the "locale" argument is invalid.
|
|
|
|
|
// Note: the "locale" argument has the same browser compatibility table as the "options"
|
|
|
|
|
try {
|
|
|
|
|
new Date().toLocaleTimeString('i');
|
|
|
|
|
} catch (e) {
|
|
|
|
|
return e.name === 'RangeError';
|
|
|
|
|
}
|
|
|
|
|
})()) { getTime = undefined; }
|
|
|
|
|
|
2021-04-02 11:44:28 +00:00
|
|
|
|
var templates = {
|
2021-04-13 13:21:24 +00:00
|
|
|
|
popupSave: function (obj) {
|
|
|
|
|
APP.editModalData = obj.data && obj.data.root;
|
|
|
|
|
return Messages.settings_save;
|
|
|
|
|
},
|
|
|
|
|
popupUpdate: function(obj) {
|
|
|
|
|
APP.editModalData = obj.data && obj.data.root;
|
|
|
|
|
return Messages.calendar_update;
|
|
|
|
|
},
|
2021-04-13 13:37:09 +00:00
|
|
|
|
monthGridHeaderExceed: function(hiddenSchedules) {
|
|
|
|
|
return '<span class="tui-full-calendar-weekday-grid-more-schedules">' + Messages._getKey('calendar_more', [hiddenSchedules]) + '</span>';
|
|
|
|
|
},
|
2022-09-08 14:56:58 +00:00
|
|
|
|
popupEdit: function(obj) {
|
|
|
|
|
APP.editModalData = obj.data && obj.data.root;
|
|
|
|
|
return Messages.poll_edit;
|
|
|
|
|
},
|
2021-04-13 09:09:14 +00:00
|
|
|
|
popupDetailLocation: function(schedule) {
|
2022-09-15 15:19:12 +00:00
|
|
|
|
var l = schedule.location;
|
|
|
|
|
var str = Util.fixHTML(l);
|
|
|
|
|
delete APP.nextLocationUid;
|
|
|
|
|
if (/^https?:\/\//.test(l)) {
|
|
|
|
|
var uid = "cp-link-"+Util.uid();
|
|
|
|
|
str = `<a href="${l}" id="${uid}">${str}</a>`;
|
|
|
|
|
APP.nextLocationUid = uid;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Messages._getKey('calendar_location', [str]);
|
2021-04-13 09:35:48 +00:00
|
|
|
|
},
|
|
|
|
|
popupIsAllDay: function() { return Messages.calendar_allDay; },
|
|
|
|
|
titlePlaceholder: function() { return Messages.calendar_title; },
|
|
|
|
|
locationPlaceholder: function() { return Messages.calendar_loc; },
|
|
|
|
|
alldayTitle: function() {
|
|
|
|
|
return '<span class="tui-full-calendar-left-content">'+Messages.calendar_allDay+'</span>';
|
2021-04-13 09:09:14 +00:00
|
|
|
|
},
|
2021-04-02 16:21:59 +00:00
|
|
|
|
timegridDisplayTime: getTime,
|
|
|
|
|
timegridDisplayPrimaryTime: getTime,
|
2021-04-09 10:01:59 +00:00
|
|
|
|
popupDetailDate: function(isAllDay, start, end) {
|
|
|
|
|
var startDate = start._date.toLocaleDateString();
|
|
|
|
|
var endDate = end._date.toLocaleDateString();
|
|
|
|
|
if (isAllDay) {
|
|
|
|
|
if (startDate === endDate) { return startDate; }
|
|
|
|
|
return Messages._getKey('calendar_dateRange', [startDate, endDate]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var startTime = getTime({
|
|
|
|
|
hour: start._date.getHours(),
|
|
|
|
|
minutes: start._date.getMinutes(),
|
|
|
|
|
});
|
|
|
|
|
var endTime = getTime({
|
|
|
|
|
hour: end._date.getHours(),
|
|
|
|
|
minutes: end._date.getMinutes(),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (startDate === endDate && startTime === endTime) {
|
|
|
|
|
return start._date.toLocaleString();
|
|
|
|
|
}
|
|
|
|
|
if (startDate === endDate) {
|
|
|
|
|
return Messages._getKey('calendar_dateTimeRange', [startDate, startTime, endTime]);
|
|
|
|
|
}
|
|
|
|
|
return Messages._getKey('calendar_dateRange', [start._date.toLocaleString(), end._date.toLocaleString()]);
|
|
|
|
|
}
|
2021-04-02 11:44:28 +00:00
|
|
|
|
};
|
|
|
|
|
|
2021-04-02 16:21:59 +00:00
|
|
|
|
var editCalendar = function (id) {
|
|
|
|
|
var isNew = !id;
|
|
|
|
|
var data = APP.calendars[id];
|
|
|
|
|
if (id && !data) { return; }
|
|
|
|
|
var md = {};
|
|
|
|
|
if (!isNew) { md = Util.find(data, ['content', 'metadata']); }
|
|
|
|
|
if (!md) { return; }
|
|
|
|
|
|
|
|
|
|
// Create form data
|
|
|
|
|
var labelTitle = h('label', Messages.kanban_title);
|
|
|
|
|
var title = h('input');
|
|
|
|
|
var $title = $(title);
|
|
|
|
|
$title.val(md.title || Messages.calendar_new);
|
|
|
|
|
var labelColor = h('label', Messages.kanban_color);
|
|
|
|
|
|
|
|
|
|
var $colorPicker = $(h('div.cp-calendar-colorpicker'));
|
|
|
|
|
var jscolorL = new window.jscolor($colorPicker[0], { showOnClick: false, valueElement: undefined, zIndex: 100000 });
|
|
|
|
|
$colorPicker.click(function() {
|
|
|
|
|
jscolorL.show();
|
|
|
|
|
});
|
|
|
|
|
if (md.color) { jscolorL.fromString(md.color); }
|
2021-04-06 10:12:12 +00:00
|
|
|
|
else { jscolorL.fromString(Util.getRandomColor()); }
|
2021-04-02 16:21:59 +00:00
|
|
|
|
|
|
|
|
|
var form = h('div', [
|
|
|
|
|
labelTitle,
|
|
|
|
|
title,
|
|
|
|
|
labelColor,
|
|
|
|
|
$colorPicker[0]
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
var send = function (obj) {
|
|
|
|
|
if (isNew) {
|
|
|
|
|
return void newCalendar(obj, function (err) {
|
|
|
|
|
if (err) { console.error(err); return void UI.warn(Messages.error); }
|
|
|
|
|
UI.log(Messages.saved);
|
2021-04-08 12:02:39 +00:00
|
|
|
|
});
|
|
|
|
|
}
|
2021-04-02 16:21:59 +00:00
|
|
|
|
obj.id = id;
|
|
|
|
|
updateCalendar(obj, function (err) {
|
|
|
|
|
if (err) { console.error(err); return void UI.warn(Messages.error); }
|
|
|
|
|
UI.log(Messages.saved);
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
var m = UI.dialog.customModal(form, {
|
|
|
|
|
buttons: [{
|
|
|
|
|
className: 'cancel',
|
|
|
|
|
name: Messages.cancel,
|
|
|
|
|
onClick: function () {},
|
|
|
|
|
keys: [27]
|
|
|
|
|
}, {
|
|
|
|
|
className: 'primary',
|
|
|
|
|
name: Messages.settings_save,
|
|
|
|
|
onClick: function () {
|
|
|
|
|
var color = jscolorL.toHEXString();
|
|
|
|
|
var title = $title.val();
|
|
|
|
|
var obj = {
|
|
|
|
|
color: color,
|
|
|
|
|
title: title
|
2021-04-08 12:02:39 +00:00
|
|
|
|
};
|
2021-04-02 16:21:59 +00:00
|
|
|
|
if (!title || !title.trim() ||!/^#[0-9a-fA-F]{6}$/.test(color)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
send(obj);
|
|
|
|
|
},
|
|
|
|
|
keys: [13]
|
|
|
|
|
}]
|
|
|
|
|
});
|
|
|
|
|
UI.openCustomModal(m);
|
|
|
|
|
};
|
|
|
|
|
|
2021-04-07 14:41:39 +00:00
|
|
|
|
var isReadOnly = function (id, teamId) {
|
|
|
|
|
var data = APP.calendars[id];
|
|
|
|
|
return data.readOnly || (data.roTeams && data.roTeams.indexOf(teamId) !== -1);
|
|
|
|
|
};
|
2021-04-06 09:31:25 +00:00
|
|
|
|
var makeEditDropdown = function (id, teamId) {
|
2021-04-07 14:41:39 +00:00
|
|
|
|
var options = [];
|
2021-04-06 16:21:48 +00:00
|
|
|
|
var privateData = metadataMgr.getPrivateData();
|
|
|
|
|
var cantRemove = teamId === 0 || (teamId !== 1 && privateData.teams[teamId].viewer);
|
2021-04-07 14:41:39 +00:00
|
|
|
|
var data = APP.calendars[id];
|
|
|
|
|
if (!data.readOnly) {
|
|
|
|
|
options.push({
|
|
|
|
|
tag: 'a',
|
|
|
|
|
attributes: {
|
|
|
|
|
'class': 'fa fa-pencil',
|
|
|
|
|
},
|
|
|
|
|
content: h('span', Messages.tag_edit),
|
|
|
|
|
action: function (e) {
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
editCalendar(id);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
2021-05-04 09:30:06 +00:00
|
|
|
|
if (APP.loggedIn && (data.teams.indexOf(1) === -1 || teamId === 0)) {
|
2021-04-07 14:41:39 +00:00
|
|
|
|
options.push({
|
|
|
|
|
tag: 'a',
|
|
|
|
|
attributes: {
|
|
|
|
|
'class': 'fa fa-clone',
|
|
|
|
|
},
|
|
|
|
|
content: h('span', Messages.calendar_import),
|
|
|
|
|
action: function (e) {
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
importCalendar({
|
|
|
|
|
id: id,
|
|
|
|
|
teamId: teamId
|
2021-05-04 09:30:06 +00:00
|
|
|
|
}, function (err) {
|
|
|
|
|
if (err) {
|
|
|
|
|
console.error(err);
|
|
|
|
|
return void UI.warn(Messages.error);
|
2021-04-07 14:41:39 +00:00
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
if (!data.restricted) {
|
|
|
|
|
options.push({
|
|
|
|
|
tag: 'a',
|
|
|
|
|
attributes: {
|
|
|
|
|
'class': 'fa fa-shhare-alt',
|
|
|
|
|
},
|
|
|
|
|
content: h('span', Messages.shareButton),
|
|
|
|
|
action: function (e) {
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
var friends = common.getFriends();
|
|
|
|
|
var cal = APP.calendars[id];
|
|
|
|
|
var title = Util.find(cal, ['content', 'metadata', 'title']);
|
|
|
|
|
var color = Util.find(cal, ['content', 'metadata', 'color']);
|
|
|
|
|
Share.getShareModal(common, {
|
|
|
|
|
teamId: teamId === 1 ? undefined : teamId,
|
|
|
|
|
origin: APP.origin,
|
|
|
|
|
pathname: "/calendar/",
|
|
|
|
|
friends: friends,
|
|
|
|
|
title: title,
|
2021-04-27 16:02:24 +00:00
|
|
|
|
password: cal.password,
|
2021-04-07 14:41:39 +00:00
|
|
|
|
calendar: {
|
|
|
|
|
title: title,
|
|
|
|
|
color: color,
|
|
|
|
|
channel: id,
|
|
|
|
|
},
|
|
|
|
|
common: common,
|
|
|
|
|
hashes: cal.hashes
|
|
|
|
|
});
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
});
|
2021-04-07 15:51:58 +00:00
|
|
|
|
options.push({
|
|
|
|
|
tag: 'a',
|
|
|
|
|
attributes: {
|
|
|
|
|
'class': 'fa fa-lock',
|
|
|
|
|
},
|
|
|
|
|
content: h('span', Messages.accessButton),
|
|
|
|
|
action: function (e) {
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
var cal = APP.calendars[id];
|
|
|
|
|
var title = Util.find(cal, ['content', 'metadata', 'title']);
|
|
|
|
|
var color = Util.find(cal, ['content', 'metadata', 'color']);
|
|
|
|
|
var h = cal.hashes || {};
|
|
|
|
|
var href = Hash.hashToHref(h.editHash || h.viewHash, 'calendar');
|
|
|
|
|
Access.getAccessModal(common, {
|
|
|
|
|
title: title,
|
2021-04-27 16:02:24 +00:00
|
|
|
|
password: cal.password,
|
2021-04-07 15:51:58 +00:00
|
|
|
|
calendar: {
|
|
|
|
|
title: title,
|
|
|
|
|
color: color,
|
|
|
|
|
channel: id,
|
|
|
|
|
},
|
|
|
|
|
common: common,
|
|
|
|
|
noExpiration: true,
|
2021-04-09 14:11:20 +00:00
|
|
|
|
noEditPassword: true,
|
2021-04-07 15:51:58 +00:00
|
|
|
|
channel: id,
|
|
|
|
|
href: href
|
|
|
|
|
});
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
});
|
2021-04-15 09:10:11 +00:00
|
|
|
|
|
|
|
|
|
if (!data.readOnly) {
|
|
|
|
|
options.push({
|
|
|
|
|
tag: 'a',
|
|
|
|
|
attributes: {
|
|
|
|
|
'class': 'fa fa-upload',
|
|
|
|
|
},
|
|
|
|
|
content: h('span', Messages.importButton),
|
2021-04-19 11:08:38 +00:00
|
|
|
|
action: function () {
|
2021-04-15 15:45:38 +00:00
|
|
|
|
UIElements.importContent('text/calendar', function (res) {
|
|
|
|
|
Export.import(res, id, function (err, json) {
|
|
|
|
|
if (err) { return void UI.warn(Messages.importError); }
|
|
|
|
|
importICSCalendar({
|
|
|
|
|
id: id,
|
|
|
|
|
json: json
|
|
|
|
|
}, function (err) {
|
|
|
|
|
if (err) { return void UI.warn(Messages.error); }
|
|
|
|
|
UI.log(Messages.saved);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
}, {
|
|
|
|
|
accept: ['.ics']
|
|
|
|
|
})();
|
2021-04-15 09:10:11 +00:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
options.push({
|
|
|
|
|
tag: 'a',
|
|
|
|
|
attributes: {
|
|
|
|
|
'class': 'fa fa-download',
|
|
|
|
|
},
|
|
|
|
|
content: h('span', Messages.exportButton),
|
|
|
|
|
action: function (e) {
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
var cal = APP.calendars[id];
|
|
|
|
|
var suggestion = Util.find(cal, ['content', 'metadata', 'title']);
|
|
|
|
|
var types = [];
|
|
|
|
|
types.push({
|
|
|
|
|
tag: 'a',
|
|
|
|
|
attributes: {
|
|
|
|
|
'data-value': '.ics',
|
|
|
|
|
'href': '#'
|
|
|
|
|
},
|
|
|
|
|
content: '.ics'
|
|
|
|
|
});
|
|
|
|
|
var dropdownConfig = {
|
|
|
|
|
text: '.ics', // Button initial text
|
|
|
|
|
caretDown: true,
|
|
|
|
|
options: types, // Entries displayed in the menu
|
|
|
|
|
isSelect: true,
|
|
|
|
|
initialValue: '.ics',
|
2021-09-27 11:19:33 +00:00
|
|
|
|
common: common,
|
|
|
|
|
buttonCls: 'btn',
|
2021-04-15 09:10:11 +00:00
|
|
|
|
};
|
|
|
|
|
var $select = UIElements.createDropdown(dropdownConfig);
|
|
|
|
|
UI.prompt(Messages.exportPrompt,
|
|
|
|
|
Util.fixFileName(suggestion), function (filename)
|
|
|
|
|
{
|
|
|
|
|
if (!(typeof(filename) === 'string' && filename)) { return; }
|
|
|
|
|
var ext = $select.getValue();
|
|
|
|
|
filename = filename + ext;
|
|
|
|
|
var blob = Export.main(cal.content);
|
|
|
|
|
SaveAs(blob, filename);
|
|
|
|
|
}, {
|
|
|
|
|
typeInput: $select[0]
|
|
|
|
|
});
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2021-04-07 16:03:37 +00:00
|
|
|
|
options.push({
|
|
|
|
|
tag: 'a',
|
|
|
|
|
attributes: {
|
|
|
|
|
'class': 'fa fa-info-circle',
|
|
|
|
|
},
|
|
|
|
|
content: h('span', Messages.propertiesButton),
|
|
|
|
|
action: function (e) {
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
var cal = APP.calendars[id];
|
|
|
|
|
var title = Util.find(cal, ['content', 'metadata', 'title']);
|
|
|
|
|
var color = Util.find(cal, ['content', 'metadata', 'color']);
|
|
|
|
|
var h = cal.hashes || {};
|
|
|
|
|
var href = Hash.hashToHref(h.editHash || h.viewHash, 'calendar');
|
|
|
|
|
Properties.getPropertiesModal(common, {
|
|
|
|
|
calendar: {
|
|
|
|
|
title: title,
|
|
|
|
|
color: color,
|
|
|
|
|
channel: id,
|
|
|
|
|
},
|
|
|
|
|
common: common,
|
|
|
|
|
channel: id,
|
|
|
|
|
href: href
|
|
|
|
|
});
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
});
|
2021-04-07 14:41:39 +00:00
|
|
|
|
}
|
2021-04-06 16:21:48 +00:00
|
|
|
|
if (!cantRemove) {
|
|
|
|
|
options.push({
|
|
|
|
|
tag: 'a',
|
|
|
|
|
attributes: {
|
|
|
|
|
'class': 'fa fa-trash-o',
|
|
|
|
|
},
|
2021-09-06 12:55:47 +00:00
|
|
|
|
content: h('span', Messages.poll_remove),
|
2021-04-06 16:21:48 +00:00
|
|
|
|
action: function (e) {
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
var cal = APP.calendars[id];
|
|
|
|
|
var teams = (cal && cal.teams) || [];
|
2021-04-30 02:40:12 +00:00
|
|
|
|
var text = [ Messages.calendar_deleteConfirm ];
|
2021-04-06 16:21:48 +00:00
|
|
|
|
if (teams.length === 1 && teams[0] !== 1) {
|
2021-04-30 02:40:12 +00:00
|
|
|
|
text[0] = Messages.calendar_deleteTeamConfirm;
|
2021-04-06 16:21:48 +00:00
|
|
|
|
}
|
|
|
|
|
if (cal.owned) {
|
2021-04-30 02:40:12 +00:00
|
|
|
|
text = text.concat([' ', Messages.calendar_deleteOwned]);
|
2021-04-06 16:21:48 +00:00
|
|
|
|
}
|
2021-04-30 02:40:12 +00:00
|
|
|
|
UI.confirm(h('span', text), function (yes) {
|
2021-04-08 12:02:39 +00:00
|
|
|
|
if (!yes) { return; }
|
2021-04-06 16:21:48 +00:00
|
|
|
|
deleteCalendar({
|
|
|
|
|
id: id,
|
|
|
|
|
teamId: teamId,
|
|
|
|
|
}, function (err) {
|
|
|
|
|
if (err) {
|
|
|
|
|
console.error(err);
|
2021-08-20 10:32:00 +00:00
|
|
|
|
return void UI.warn(Messages.error);
|
2021-04-06 16:21:48 +00:00
|
|
|
|
}
|
2021-08-20 10:32:00 +00:00
|
|
|
|
renderCalendar();
|
2021-04-06 16:21:48 +00:00
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
2021-04-06 09:31:25 +00:00
|
|
|
|
var dropdownConfig = {
|
|
|
|
|
text: '',
|
|
|
|
|
options: options, // Entries displayed in the menu
|
|
|
|
|
common: common,
|
2022-02-28 15:32:22 +00:00
|
|
|
|
buttonCls: 'btn btn-default fa fa-gear small cp-calendar-actions'
|
2021-04-06 09:31:25 +00:00
|
|
|
|
};
|
|
|
|
|
return UIElements.createDropdown(dropdownConfig)[0];
|
|
|
|
|
};
|
|
|
|
|
var makeCalendarEntry = function (id, teamId) {
|
|
|
|
|
var data = APP.calendars[id];
|
|
|
|
|
var edit;
|
2021-04-06 13:01:43 +00:00
|
|
|
|
if (data.loading) {
|
|
|
|
|
edit = h('i.fa.fa-spinner.fa-spin');
|
2021-04-07 14:41:39 +00:00
|
|
|
|
} else {
|
2021-04-06 09:31:25 +00:00
|
|
|
|
edit = makeEditDropdown(id, teamId);
|
|
|
|
|
}
|
|
|
|
|
var md = Util.find(data, ['content', 'metadata']);
|
|
|
|
|
if (!md) { return; }
|
|
|
|
|
var active = data.hidden ? '' : '.cp-active';
|
2021-04-07 15:51:58 +00:00
|
|
|
|
var restricted = data.restricted ? '.cp-restricted' : '';
|
2021-04-22 16:33:17 +00:00
|
|
|
|
var temp = teamId === 0 ? '.cp-unclickable' : '';
|
|
|
|
|
var calendar = h('div.cp-calendar-entry'+active+restricted+temp, {
|
2021-04-06 15:25:18 +00:00
|
|
|
|
'data-uid': id
|
|
|
|
|
}, [
|
2021-04-22 16:33:17 +00:00
|
|
|
|
h('span.cp-calendar-icon', {
|
2021-04-06 09:31:25 +00:00
|
|
|
|
style: 'background-color: '+md.color+';'
|
2021-04-22 16:33:17 +00:00
|
|
|
|
}, [
|
|
|
|
|
h('i.cp-calendar-active.fa.fa-calendar', {
|
|
|
|
|
style: 'color: '+getContrast(md.color)+';'
|
|
|
|
|
}),
|
|
|
|
|
h('i.cp-calendar-inactive.fa.fa-calendar-o')
|
|
|
|
|
]),
|
2021-04-06 09:31:25 +00:00
|
|
|
|
h('span.cp-calendar-title', md.title),
|
2021-04-07 15:51:58 +00:00
|
|
|
|
data.restricted ? h('i.fa.fa-ban', {title: Messages.fm_restricted}) :
|
|
|
|
|
(isReadOnly(id, teamId) ? h('i.fa.fa-eye', {title: Messages.readonly}) : undefined),
|
2021-04-06 09:31:25 +00:00
|
|
|
|
edit
|
|
|
|
|
]);
|
2021-04-30 02:40:12 +00:00
|
|
|
|
var $calendar = $(calendar).click(function () {
|
2021-04-22 16:33:17 +00:00
|
|
|
|
if (teamId === 0) { return; }
|
2021-04-06 09:31:25 +00:00
|
|
|
|
data.hidden = !data.hidden;
|
2021-04-06 15:25:18 +00:00
|
|
|
|
if (APP.$calendars) {
|
|
|
|
|
APP.$calendars.find('[data-uid="'+id+'"]').toggleClass('cp-active', !data.hidden);
|
|
|
|
|
} else {
|
|
|
|
|
$(calendar).toggleClass('cp-active', !data.hidden);
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-06 09:31:25 +00:00
|
|
|
|
renderCalendar();
|
|
|
|
|
});
|
2021-04-30 02:40:12 +00:00
|
|
|
|
if (!data.loading) {
|
|
|
|
|
$calendar.contextmenu(function (ev) {
|
|
|
|
|
ev.preventDefault();
|
|
|
|
|
$(edit).click();
|
|
|
|
|
});
|
|
|
|
|
}
|
2021-04-06 09:31:25 +00:00
|
|
|
|
if (APP.$calendars) { APP.$calendars.append(calendar); }
|
|
|
|
|
return calendar;
|
|
|
|
|
};
|
2021-04-02 16:21:59 +00:00
|
|
|
|
var makeLeftside = function (calendar, $container) {
|
|
|
|
|
// Show calendars
|
|
|
|
|
var calendars = h('div.cp-calendar-list');
|
2021-04-06 09:31:25 +00:00
|
|
|
|
var $calendars = APP.$calendars = $(calendars).appendTo($container);
|
2021-04-02 16:21:59 +00:00
|
|
|
|
onCalendarsUpdate.reg(function () {
|
|
|
|
|
$calendars.empty();
|
2021-04-06 15:25:18 +00:00
|
|
|
|
var privateData = metadataMgr.getPrivateData();
|
|
|
|
|
var filter = function (teamId) {
|
2022-03-31 06:27:56 +00:00
|
|
|
|
var LOOKUP = {};
|
2021-04-06 15:25:18 +00:00
|
|
|
|
return Object.keys(APP.calendars || {}).filter(function (id) {
|
|
|
|
|
var cal = APP.calendars[id] || {};
|
2021-04-26 12:25:06 +00:00
|
|
|
|
var teams = (cal.teams || []).map(function (tId) { return Number(tId); });
|
|
|
|
|
return teams.indexOf(typeof(teamId) !== "undefined" ? Number(teamId) : 1) !== -1;
|
2022-03-31 06:27:56 +00:00
|
|
|
|
}).map(function (k) {
|
|
|
|
|
// nearly constant-time pre-sort
|
|
|
|
|
var cal = APP.calendars[k] || {};
|
|
|
|
|
var title = Util.find(cal, ['content', 'metadata', 'title']) || '';
|
|
|
|
|
LOOKUP[k] = title;
|
|
|
|
|
return k;
|
2022-03-30 13:58:47 +00:00
|
|
|
|
}).sort(function (a, b) {
|
2022-03-31 06:27:56 +00:00
|
|
|
|
var t1 = LOOKUP[a];
|
|
|
|
|
var t2 = LOOKUP[b];
|
2022-03-30 13:58:47 +00:00
|
|
|
|
return t1 > t2 ? 1 : (t1 === t2 ? 0 : -1);
|
2021-04-06 15:25:18 +00:00
|
|
|
|
});
|
|
|
|
|
};
|
2021-04-06 16:21:48 +00:00
|
|
|
|
var tempCalendars = filter(0);
|
2021-04-22 16:33:17 +00:00
|
|
|
|
if (tempCalendars.length && tempCalendars[0] === APP.currentCalendar) {
|
2021-04-06 16:21:48 +00:00
|
|
|
|
APP.$calendars.append(h('div.cp-calendar-team', [
|
|
|
|
|
h('span', Messages.calendar_tempCalendar)
|
|
|
|
|
]));
|
|
|
|
|
makeCalendarEntry(tempCalendars[0], 0);
|
2021-04-22 16:33:17 +00:00
|
|
|
|
var importTemp = h('button', [
|
|
|
|
|
h('i.fa.fa-calendar-plus-o'),
|
|
|
|
|
h('span', Messages.calendar_import_temp),
|
|
|
|
|
h('span')
|
|
|
|
|
]);
|
|
|
|
|
$(importTemp).click(function () {
|
|
|
|
|
importCalendar({
|
|
|
|
|
id: tempCalendars[0],
|
|
|
|
|
teamId: 0
|
2021-05-04 09:30:06 +00:00
|
|
|
|
}, function (err) {
|
|
|
|
|
if (err) {
|
|
|
|
|
console.error(err);
|
|
|
|
|
return void UI.warn(Messages.error);
|
2021-04-22 16:33:17 +00:00
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
});
|
2021-05-04 09:30:06 +00:00
|
|
|
|
if (APP.loggedIn) {
|
|
|
|
|
APP.$calendars.append(h('div.cp-calendar-entry.cp-ghost', importTemp));
|
|
|
|
|
}
|
2021-04-22 16:33:17 +00:00
|
|
|
|
return;
|
2021-04-06 16:21:48 +00:00
|
|
|
|
}
|
2021-04-06 15:25:18 +00:00
|
|
|
|
var myCalendars = filter(1);
|
|
|
|
|
if (myCalendars.length) {
|
2021-04-27 16:09:45 +00:00
|
|
|
|
var user = metadataMgr.getUserData();
|
|
|
|
|
var avatar = h('span.cp-avatar');
|
|
|
|
|
var name = user.name || Messages.anonymous;
|
|
|
|
|
common.displayAvatar($(avatar), user.avatar, name);
|
2021-04-06 15:25:18 +00:00
|
|
|
|
APP.$calendars.append(h('div.cp-calendar-team', [
|
2021-04-27 16:09:45 +00:00
|
|
|
|
avatar,
|
|
|
|
|
h('span.cp-name', {title: name}, name)
|
2021-04-06 15:25:18 +00:00
|
|
|
|
]));
|
|
|
|
|
}
|
|
|
|
|
myCalendars.forEach(function (id) {
|
|
|
|
|
makeCalendarEntry(id, 1);
|
|
|
|
|
});
|
2021-04-22 16:33:17 +00:00
|
|
|
|
|
|
|
|
|
// Add new button
|
|
|
|
|
var $newContainer = $(h('div.cp-calendar-entry.cp-ghost')).appendTo($calendars);
|
|
|
|
|
var newButton = h('button', [
|
|
|
|
|
h('i.fa.fa-calendar-plus-o'),
|
|
|
|
|
h('span', Messages.calendar_new),
|
|
|
|
|
h('span')
|
|
|
|
|
]);
|
|
|
|
|
$(newButton).click(function () {
|
|
|
|
|
editCalendar();
|
|
|
|
|
}).appendTo($newContainer);
|
|
|
|
|
|
2022-03-30 13:58:47 +00:00
|
|
|
|
Object.keys(privateData.teams).sort().forEach(function (teamId) {
|
2021-04-06 15:25:18 +00:00
|
|
|
|
var calendars = filter(teamId);
|
|
|
|
|
if (!calendars.length) { return; }
|
|
|
|
|
var team = privateData.teams[teamId];
|
|
|
|
|
var avatar = h('span.cp-avatar');
|
2021-08-20 10:32:00 +00:00
|
|
|
|
common.displayAvatar($(avatar), team.avatar, team.displayName || team.name);
|
2021-04-06 15:25:18 +00:00
|
|
|
|
APP.$calendars.append(h('div.cp-calendar-team', [
|
|
|
|
|
avatar,
|
|
|
|
|
h('span.cp-name', {title: team.name}, team.name)
|
|
|
|
|
]));
|
|
|
|
|
calendars.forEach(function (id) {
|
2021-04-06 09:31:25 +00:00
|
|
|
|
makeCalendarEntry(id, teamId);
|
2021-04-02 16:21:59 +00:00
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
onCalendarsUpdate.fire();
|
2021-04-09 08:38:34 +00:00
|
|
|
|
|
2021-04-02 16:21:59 +00:00
|
|
|
|
};
|
2021-04-27 10:31:13 +00:00
|
|
|
|
|
2022-08-30 11:17:57 +00:00
|
|
|
|
var _updateRecurring = function () {
|
|
|
|
|
var cal = APP.calendar;
|
|
|
|
|
if (!cal) { return; }
|
|
|
|
|
|
|
|
|
|
var range = APP.calendar._renderRange;
|
|
|
|
|
var startView = range.start._date;
|
|
|
|
|
var endView = range.end._date;
|
|
|
|
|
endView.setDate(endView.getDate() + 1);
|
|
|
|
|
|
|
|
|
|
var midView = new Date(((+startView) + (+endView)) / 2);
|
|
|
|
|
|
|
|
|
|
// We want to generate recurring events month per month.
|
2022-09-06 16:58:39 +00:00
|
|
|
|
// In "month" view, we may see up to 3 different months
|
2022-08-30 11:17:57 +00:00
|
|
|
|
// at the same time.
|
|
|
|
|
var startId = Rec.getMonthId(startView);
|
|
|
|
|
var midId = Rec.getMonthId(midView);
|
|
|
|
|
var endId = Rec.getMonthId(endView);
|
|
|
|
|
var todo = Util.deduplicateString([startId, midId, endId]);
|
|
|
|
|
todo = todo.filter(function (monthId) {
|
|
|
|
|
return !APP.recurringDone.includes(monthId);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
var toAdd = Rec.getRecurring(todo, APP.recurringEvents);
|
|
|
|
|
|
2022-09-06 16:58:39 +00:00
|
|
|
|
// Mark selected months as done
|
2022-08-30 11:17:57 +00:00
|
|
|
|
todo.forEach(function (monthId) { APP.recurringDone.push(monthId); });
|
|
|
|
|
|
2022-09-08 14:56:58 +00:00
|
|
|
|
cal.createSchedules(applyUpdates(toAdd));
|
2022-08-30 11:17:57 +00:00
|
|
|
|
};
|
|
|
|
|
updateRecurring = function () {
|
|
|
|
|
try {
|
|
|
|
|
_updateRecurring();
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error(e);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
UPDATE A RECCURENT EVENT:
|
|
|
|
|
ICS ==> create a new event with the same UID and a RECURRENCE-ID field (with a value equals to the DTSTART of this recurring event)
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
2022-09-15 11:15:27 +00:00
|
|
|
|
var diffDate = Rec.diffDate;
|
2022-09-08 14:56:58 +00:00
|
|
|
|
|
2021-04-13 13:42:04 +00:00
|
|
|
|
var makeCalendar = function (view) {
|
|
|
|
|
var store = window.cryptpadStore;
|
|
|
|
|
|
2021-04-02 16:21:59 +00:00
|
|
|
|
var $container = $('#cp-sidebarlayout-container');
|
|
|
|
|
var leftside;
|
2021-04-02 11:44:28 +00:00
|
|
|
|
$container.append([
|
2021-04-02 16:21:59 +00:00
|
|
|
|
leftside = h('div#cp-sidebarlayout-leftside'),
|
|
|
|
|
h('div#cp-sidebarlayout-rightside')
|
2021-04-02 11:44:28 +00:00
|
|
|
|
]);
|
|
|
|
|
|
2021-04-27 10:31:13 +00:00
|
|
|
|
var large = $(window).width() >= 800;
|
2021-04-02 16:21:59 +00:00
|
|
|
|
var cal = APP.calendar = new Calendar('#cp-sidebarlayout-rightside', {
|
2021-04-13 13:42:04 +00:00
|
|
|
|
defaultView: view || 'week', // weekly view option
|
2021-04-07 11:51:50 +00:00
|
|
|
|
taskView: false,
|
2021-04-02 11:44:28 +00:00
|
|
|
|
useCreationPopup: true,
|
|
|
|
|
useDetailPopup: true,
|
|
|
|
|
usageStatistics: false,
|
2021-04-02 13:18:59 +00:00
|
|
|
|
calendars: getCalendars(),
|
2021-04-02 16:21:59 +00:00
|
|
|
|
template: templates,
|
|
|
|
|
month: {
|
2021-04-27 10:31:13 +00:00
|
|
|
|
daynames: getWeekDays(large),
|
2021-04-09 11:38:17 +00:00
|
|
|
|
startDayOfWeek: 1,
|
2021-04-02 16:21:59 +00:00
|
|
|
|
},
|
|
|
|
|
week: {
|
2021-04-27 10:31:13 +00:00
|
|
|
|
daynames: getWeekDays(large),
|
2021-04-02 16:21:59 +00:00
|
|
|
|
startDayOfWeek: 1,
|
|
|
|
|
}
|
2021-04-02 11:44:28 +00:00
|
|
|
|
});
|
2021-04-02 16:21:59 +00:00
|
|
|
|
|
2021-04-27 10:31:13 +00:00
|
|
|
|
$(window).on('resize', function () {
|
|
|
|
|
var _large = $(window).width() >= 800;
|
|
|
|
|
if (large !== _large) {
|
|
|
|
|
large = _large;
|
|
|
|
|
cal.setOptions({
|
|
|
|
|
month: {
|
|
|
|
|
daynames: getWeekDays(_large),
|
|
|
|
|
startDayOfWeek: 1,
|
|
|
|
|
},
|
|
|
|
|
week: {
|
|
|
|
|
daynames: getWeekDays(_large),
|
|
|
|
|
startDayOfWeek: 1,
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2021-04-02 16:21:59 +00:00
|
|
|
|
makeLeftside(cal, $(leftside));
|
|
|
|
|
|
2021-04-02 11:44:28 +00:00
|
|
|
|
cal.on('beforeCreateSchedule', function(event) {
|
2021-04-13 13:21:24 +00:00
|
|
|
|
var reminders = APP.notificationsEntries;
|
2021-04-02 11:44:28 +00:00
|
|
|
|
|
2021-04-13 14:38:50 +00:00
|
|
|
|
var startDate = event.start._date;
|
|
|
|
|
var endDate = event.end._date;
|
|
|
|
|
|
2021-04-02 11:44:28 +00:00
|
|
|
|
var schedule = {
|
|
|
|
|
id: Util.uid(),
|
|
|
|
|
calendarId: event.calendarId,
|
2022-09-21 08:09:58 +00:00
|
|
|
|
title: event.title,
|
2021-04-02 11:44:28 +00:00
|
|
|
|
category: "time",
|
2022-09-21 08:09:58 +00:00
|
|
|
|
location: event.location,
|
2021-04-13 14:38:50 +00:00
|
|
|
|
start: +startDate,
|
2021-04-02 13:18:59 +00:00
|
|
|
|
isAllDay: event.isAllDay,
|
2021-04-13 14:38:50 +00:00
|
|
|
|
end: +endDate,
|
2021-04-13 14:42:25 +00:00
|
|
|
|
reminders: reminders,
|
2022-09-06 16:58:39 +00:00
|
|
|
|
recurrenceRule: APP.recurrenceRule
|
2021-04-02 11:44:28 +00:00
|
|
|
|
};
|
|
|
|
|
|
2021-04-02 13:18:59 +00:00
|
|
|
|
newEvent(schedule, function (err) {
|
|
|
|
|
if (err) {
|
|
|
|
|
console.error(err);
|
|
|
|
|
return void UI.warn(err);
|
|
|
|
|
}
|
|
|
|
|
cal.createSchedules([schedule]);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
cal.on('beforeUpdateSchedule', function(event) {
|
|
|
|
|
var changes = event.changes || {};
|
|
|
|
|
delete changes.state;
|
2022-09-06 16:58:39 +00:00
|
|
|
|
|
2021-04-02 13:18:59 +00:00
|
|
|
|
if (changes.end) { changes.end = +new Date(changes.end._date); }
|
|
|
|
|
if (changes.start) { changes.start = +new Date(changes.start._date); }
|
|
|
|
|
var old = event.schedule;
|
2022-09-08 14:56:58 +00:00
|
|
|
|
var id = old.id.split('|')[0];
|
|
|
|
|
|
|
|
|
|
var originalEvent = Util.find(APP.calendars, [old.calendarId, 'content', 'content', id]);
|
2021-04-02 11:44:28 +00:00
|
|
|
|
|
2022-09-12 17:06:25 +00:00
|
|
|
|
var ev = APP.calendar.getSchedule(old.id, old.calendarId);
|
2022-09-13 12:18:38 +00:00
|
|
|
|
var evOrig = APP.calendar.getSchedule(id, old.calendarId);
|
|
|
|
|
|
2022-09-12 17:06:25 +00:00
|
|
|
|
var isOrigin = id === old.id;
|
|
|
|
|
var wasRecurrent = Boolean(originalEvent.recurrenceRule);
|
|
|
|
|
|
2022-09-06 16:58:39 +00:00
|
|
|
|
if (event.calendar) { // Don't update reminders and recurrence with drag&drop event
|
2022-09-12 17:06:25 +00:00
|
|
|
|
var oldReminders = ev.raw.reminders || originalEvent.reminders;
|
2022-09-06 16:58:39 +00:00
|
|
|
|
var reminders = APP.notificationsEntries;
|
|
|
|
|
if (JSONSortify(oldReminders || []) !== JSONSortify(reminders)) {
|
|
|
|
|
changes.reminders = reminders;
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-15 11:15:27 +00:00
|
|
|
|
var oldRec = ev.recurrenceRule;
|
2022-09-06 16:58:39 +00:00
|
|
|
|
var rec = APP.recurrenceRule;
|
2022-09-08 14:56:58 +00:00
|
|
|
|
if (JSONSortify(oldRec || '') !== JSONSortify(rec)) {
|
2022-09-06 16:58:39 +00:00
|
|
|
|
changes.recurrenceRule = rec;
|
|
|
|
|
}
|
2021-04-13 13:21:24 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-09-08 14:56:58 +00:00
|
|
|
|
|
2022-09-12 12:42:54 +00:00
|
|
|
|
if (!event.triggerEventName || event.triggerEventName !== "click") {
|
|
|
|
|
APP.recurrenceRule = ev.recurrenceRule;
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-08 14:56:58 +00:00
|
|
|
|
var afterConfirm = function () {
|
|
|
|
|
var raw = (ev && ev.raw) || {};
|
2022-09-13 12:18:38 +00:00
|
|
|
|
var rawData = { // Exact start and end of the selected event
|
|
|
|
|
start: raw.start || ev.start,
|
|
|
|
|
end: raw.end || ev.end,
|
|
|
|
|
isOrigin: isOrigin
|
|
|
|
|
};
|
2022-09-08 14:56:58 +00:00
|
|
|
|
if (['one', 'from'].includes(APP.editType)) {
|
|
|
|
|
if (changes.start) {
|
|
|
|
|
changes.start = diffDate(raw.start || ev.start, changes.start);
|
|
|
|
|
}
|
|
|
|
|
if (changes.end) {
|
|
|
|
|
changes.end = diffDate(raw.end || ev.end, changes.end);
|
|
|
|
|
}
|
2021-04-02 13:18:59 +00:00
|
|
|
|
}
|
2022-09-08 14:56:58 +00:00
|
|
|
|
|
|
|
|
|
old.id = id;
|
|
|
|
|
updateEvent({
|
|
|
|
|
ev: old,
|
|
|
|
|
changes: changes,
|
2022-09-13 12:18:38 +00:00
|
|
|
|
rawData: rawData,
|
2022-09-08 14:56:58 +00:00
|
|
|
|
type: {
|
|
|
|
|
which: APP.editType,
|
|
|
|
|
when: raw.start || ev.start
|
|
|
|
|
}
|
|
|
|
|
}, function (err) {
|
|
|
|
|
if (err) {
|
|
|
|
|
console.error(err);
|
|
|
|
|
return void UI.warn(err);
|
|
|
|
|
}
|
|
|
|
|
//cal.updateSchedule(old.id, old.calendarId, changes);
|
|
|
|
|
});
|
|
|
|
|
};
|
2022-09-13 14:43:08 +00:00
|
|
|
|
|
2022-09-08 14:56:58 +00:00
|
|
|
|
|
|
|
|
|
// Confirm modal: select which recurring events to update
|
2022-09-13 12:18:38 +00:00
|
|
|
|
if (!Object.keys(changes).length) { return void afterConfirm(); }
|
2022-09-08 14:56:58 +00:00
|
|
|
|
if (!wasRecurrent) { return void afterConfirm(); }
|
|
|
|
|
|
|
|
|
|
var list = ['one','from','all'];
|
|
|
|
|
if (isOrigin) { list = ['one', 'all']; }
|
|
|
|
|
if ((changes.start || changes.end) && !isOrigin) {
|
|
|
|
|
list = list.filter(function (item) {
|
|
|
|
|
return item !== "all";
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var radioEls = list.map(function (k, i) {
|
|
|
|
|
return UI.createRadio('cp-calendar-rec-edit', 'cp-calendar-rec-edit-'+k,
|
|
|
|
|
Messages['calendar_rec_edit_'+k], !i, {input:{ 'data-value':k }});
|
|
|
|
|
});
|
2022-09-13 12:18:38 +00:00
|
|
|
|
var p = h('p', Messages.calendar_rec_edit);
|
|
|
|
|
var warn = h('div.alert.alert-warning');
|
2022-09-08 14:56:58 +00:00
|
|
|
|
var content = h('div', [
|
2022-09-13 12:18:38 +00:00
|
|
|
|
warn,
|
|
|
|
|
p,
|
2022-09-08 14:56:58 +00:00
|
|
|
|
radioEls
|
|
|
|
|
]);
|
|
|
|
|
UI.confirm(content, function (yes) {
|
|
|
|
|
if (!yes) { return; }
|
|
|
|
|
var r = $(content).find('input[name="cp-calendar-rec-edit"]:checked')
|
|
|
|
|
.data('value');
|
|
|
|
|
APP.editType = r;
|
|
|
|
|
afterConfirm();
|
|
|
|
|
});
|
|
|
|
|
$(content).closest('.alertify').on('mousedown', function (e) {
|
|
|
|
|
e.stopPropagation();
|
2021-04-02 13:18:59 +00:00
|
|
|
|
});
|
2022-09-13 12:18:38 +00:00
|
|
|
|
|
|
|
|
|
var $p = $(p);
|
|
|
|
|
var $warn = $(warn);
|
|
|
|
|
var $radio = $(radioEls);
|
|
|
|
|
var recurrenceWarn = function () {
|
|
|
|
|
if (typeof(changes.recurrenceRule) === "undefined") {
|
|
|
|
|
$p.show();
|
|
|
|
|
return $warn.hide();
|
|
|
|
|
}
|
|
|
|
|
$warn.show();
|
|
|
|
|
$p.hide();
|
|
|
|
|
var val = $radio.find('input[name="cp-calendar-rec-edit"]:checked')
|
|
|
|
|
.data('value');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!changes.recurrenceRule) { // Rule was deleted
|
|
|
|
|
if (!val || val === "all") {
|
|
|
|
|
return $warn.text(Messages._getKey('calendar_rec_warn_delall', [
|
|
|
|
|
new Date(evOrig.start).toLocaleDateString()
|
|
|
|
|
]));
|
|
|
|
|
}
|
|
|
|
|
return $warn.text(Messages.calendar_rec_warn_del);
|
|
|
|
|
}
|
|
|
|
|
if (!val || val === "all") {
|
|
|
|
|
return $warn.text(Messages._getKey('calendar_rec_warn_updateall', [
|
|
|
|
|
new Date(evOrig.start).toLocaleDateString()
|
|
|
|
|
]));
|
|
|
|
|
}
|
|
|
|
|
return $warn.text(Messages.calendar_rec_warn_update);
|
|
|
|
|
};
|
|
|
|
|
recurrenceWarn();
|
|
|
|
|
$radio.find('input[type="radio"]').on('change', recurrenceWarn);
|
2021-04-02 11:44:28 +00:00
|
|
|
|
});
|
2021-04-02 13:18:59 +00:00
|
|
|
|
cal.on('beforeDeleteSchedule', function(event) {
|
|
|
|
|
deleteEvent(event.schedule, function (err) {
|
|
|
|
|
if (err) {
|
|
|
|
|
console.error(err);
|
|
|
|
|
return void UI.warn(err);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
2021-04-14 13:18:05 +00:00
|
|
|
|
$('body').on('keydown', function (e) {
|
|
|
|
|
if (e.which === 27) {
|
|
|
|
|
$('.tui-full-calendar-floating-layer').hide();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2021-04-08 16:40:08 +00:00
|
|
|
|
updateDateRange();
|
2021-04-02 16:21:59 +00:00
|
|
|
|
renderCalendar();
|
2021-04-08 16:40:08 +00:00
|
|
|
|
|
|
|
|
|
// Toolbar
|
|
|
|
|
|
|
|
|
|
// Change view mode
|
|
|
|
|
var options = ['day', 'week', 'month'].map(function (k) {
|
|
|
|
|
return {
|
|
|
|
|
tag: 'a',
|
|
|
|
|
attributes: {
|
|
|
|
|
'class': 'cp-calendar-view',
|
|
|
|
|
'data-value': k,
|
|
|
|
|
'href': '#',
|
|
|
|
|
},
|
|
|
|
|
content: Messages['calendar_'+k]
|
|
|
|
|
// Messages.calendar_day
|
|
|
|
|
// Messages.calendar_week
|
|
|
|
|
// Messages.calendar_month
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
var dropdownConfig = {
|
|
|
|
|
text: Messages.calendar_week,
|
|
|
|
|
options: options, // Entries displayed in the menu
|
|
|
|
|
isSelect: true,
|
|
|
|
|
common: common,
|
|
|
|
|
caretDown: true,
|
|
|
|
|
left: true,
|
|
|
|
|
};
|
|
|
|
|
var $block = UIElements.createDropdown(dropdownConfig);
|
2021-04-13 13:42:04 +00:00
|
|
|
|
$block.setValue(view || 'week');
|
2021-04-08 16:40:08 +00:00
|
|
|
|
var $views = $block.find('a');
|
|
|
|
|
$views.click(function () {
|
|
|
|
|
var mode = $(this).attr('data-value');
|
|
|
|
|
cal.changeView(mode);
|
|
|
|
|
updateDateRange();
|
2022-08-30 11:17:57 +00:00
|
|
|
|
updateRecurring();
|
2021-04-13 13:42:04 +00:00
|
|
|
|
store.put('calendarView', mode, function () {});
|
2021-04-08 16:40:08 +00:00
|
|
|
|
});
|
|
|
|
|
APP.toolbar.$bottomR.append($block);
|
|
|
|
|
|
2021-04-09 08:38:34 +00:00
|
|
|
|
// New event button
|
2021-04-27 10:31:13 +00:00
|
|
|
|
var newEventBtn = h('button.cp-calendar-newevent', [
|
2021-04-09 08:38:34 +00:00
|
|
|
|
h('i.fa.fa-plus'),
|
|
|
|
|
h('span', Messages.calendar_newEvent)
|
|
|
|
|
]);
|
2021-04-09 10:01:59 +00:00
|
|
|
|
$(newEventBtn).click(function (e) {
|
2021-04-09 08:38:34 +00:00
|
|
|
|
e.preventDefault();
|
|
|
|
|
cal.openCreationPopup({isAllDay:false});
|
|
|
|
|
}).appendTo(APP.toolbar.$bottomL);
|
|
|
|
|
|
2021-04-08 16:40:08 +00:00
|
|
|
|
// Change page
|
|
|
|
|
var goLeft = h('button.fa.fa-chevron-left');
|
|
|
|
|
var goRight = h('button.fa.fa-chevron-right');
|
|
|
|
|
var goToday = h('button', Messages.calendar_today);
|
2022-09-15 14:33:50 +00:00
|
|
|
|
var goDate = h('button.fa.fa-calendar');
|
2021-04-08 16:40:08 +00:00
|
|
|
|
$(goLeft).click(function () {
|
|
|
|
|
cal.prev();
|
|
|
|
|
updateDateRange();
|
2022-08-30 11:17:57 +00:00
|
|
|
|
updateRecurring();
|
2021-04-08 16:40:08 +00:00
|
|
|
|
});
|
|
|
|
|
$(goRight).click(function () {
|
|
|
|
|
cal.next();
|
|
|
|
|
updateDateRange();
|
2022-08-30 11:17:57 +00:00
|
|
|
|
updateRecurring();
|
2021-04-08 16:40:08 +00:00
|
|
|
|
});
|
|
|
|
|
$(goToday).click(function () {
|
2022-09-14 14:11:54 +00:00
|
|
|
|
APP.moveToDate(+new Date());
|
|
|
|
|
//cal.today();
|
2021-04-08 16:40:08 +00:00
|
|
|
|
updateDateRange();
|
2022-08-30 11:17:57 +00:00
|
|
|
|
updateRecurring();
|
2021-04-08 16:40:08 +00:00
|
|
|
|
});
|
2022-09-15 14:33:50 +00:00
|
|
|
|
$(goDate).click(function () {
|
|
|
|
|
var f = Flatpickr(goDate, {
|
|
|
|
|
enableTime: false,
|
|
|
|
|
defaultDate: APP.calendar.getDate()._date,
|
|
|
|
|
//dateFormat: dateFormat,
|
|
|
|
|
onChange: function (date) {
|
|
|
|
|
date[0].setHours(12);
|
|
|
|
|
f.destroy();
|
|
|
|
|
APP.moveToDate(+date[0]);
|
|
|
|
|
updateDateRange();
|
|
|
|
|
updateRecurring();
|
|
|
|
|
},
|
|
|
|
|
onClose: function () {
|
|
|
|
|
setTimeout(f.destroy);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
f.open();
|
|
|
|
|
});
|
2021-04-08 16:40:08 +00:00
|
|
|
|
APP.toolbar.$bottomL.append(h('div.cp-calendar-browse', [
|
2022-09-15 14:33:50 +00:00
|
|
|
|
goLeft, goToday, goRight, goDate
|
2021-04-08 16:40:08 +00:00
|
|
|
|
]));
|
|
|
|
|
|
2021-04-02 11:44:28 +00:00
|
|
|
|
};
|
|
|
|
|
|
2022-09-06 16:58:39 +00:00
|
|
|
|
|
|
|
|
|
var WEEKDAYS = getWeekDays(true);
|
2022-09-07 15:08:41 +00:00
|
|
|
|
var listItems = function (_arr) {
|
2022-09-08 14:56:58 +00:00
|
|
|
|
var arr = _arr.slice();
|
2022-09-07 15:08:41 +00:00
|
|
|
|
if (arr.length === 1) {
|
|
|
|
|
return arr[0];
|
|
|
|
|
}
|
2022-10-11 14:43:37 +00:00
|
|
|
|
var shift = function () {
|
|
|
|
|
var i = arr.shift();
|
|
|
|
|
if (i === -1) { return Messages.calendar_month_last; }
|
|
|
|
|
return i;
|
|
|
|
|
};
|
|
|
|
|
var str = shift();
|
2022-09-07 15:08:41 +00:00
|
|
|
|
var i = 0;
|
|
|
|
|
while (arr.length > 1 && i < 367) {
|
2022-10-11 14:43:37 +00:00
|
|
|
|
str = Messages._getKey('calendar_list', [str, shift()]);
|
2022-09-07 15:08:41 +00:00
|
|
|
|
i++;
|
|
|
|
|
}
|
2022-10-11 14:43:37 +00:00
|
|
|
|
str = Messages._getKey('calendar_list_end', [str, shift()]);
|
2022-09-07 15:08:41 +00:00
|
|
|
|
return str;
|
|
|
|
|
};
|
|
|
|
|
var translate = function (rule) {
|
|
|
|
|
var str = "";
|
|
|
|
|
if (!rule || !rule.freq) { return; }
|
|
|
|
|
var tmp = new Date();
|
|
|
|
|
|
|
|
|
|
// Freq, interval
|
|
|
|
|
str = Messages._getKey('calendar_str_'+rule.freq, [rule.interval || 1]);
|
|
|
|
|
|
|
|
|
|
var m = rule.by && rule.by.month;
|
|
|
|
|
var d = rule.by && rule.by.day;
|
|
|
|
|
var md = rule.by && rule.by.monthday;
|
|
|
|
|
|
|
|
|
|
var ord = false;
|
|
|
|
|
if (d) {
|
|
|
|
|
d = d.map(function (str) {
|
|
|
|
|
var nth = str.slice(0, -2);
|
|
|
|
|
nth = (nth === '-1') ? 'last' : nth;
|
|
|
|
|
ord = Boolean(nth);
|
|
|
|
|
var day = str.slice(-2);
|
|
|
|
|
var n = Rec.DAYORDER.indexOf(day);
|
|
|
|
|
var dayStr = WEEKDAYS[n];
|
|
|
|
|
if (nth) { return Messages['calendar_nth_'+nth] + " " + dayStr; }
|
|
|
|
|
return dayStr;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
if (m) {
|
|
|
|
|
m = m.map(function (n) {
|
|
|
|
|
tmp.setMonth(n-1);
|
2022-10-25 09:07:54 +00:00
|
|
|
|
return tmp.toLocaleDateString(getDateLanguage(), { month: 'long' });
|
2022-09-07 15:08:41 +00:00
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Until / count
|
|
|
|
|
var end = "";
|
|
|
|
|
if (rule.count) {
|
|
|
|
|
end += " " + Messages._getKey('calendar_str_for', [rule.count]);
|
|
|
|
|
}
|
|
|
|
|
if (rule.until) {
|
|
|
|
|
end += " " + Messages._getKey('calendar_str_until', [
|
2022-10-25 09:07:54 +00:00
|
|
|
|
new Date(rule.until).toLocaleDateString(getDateLanguage(), {
|
2022-09-07 15:08:41 +00:00
|
|
|
|
month: "long",
|
|
|
|
|
day: "numeric",
|
|
|
|
|
year: "numeric"
|
|
|
|
|
})
|
|
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var filters = [];
|
|
|
|
|
// nth day (of month)
|
|
|
|
|
if (rule.freq === "yearly" && m && m.length === 1 && d && d.length === 1
|
|
|
|
|
&& Object.keys(rule.by).length === 2) {
|
|
|
|
|
str += " " + Messages._getKey('calendar_str_nthdayofmonth', [
|
|
|
|
|
d[0],
|
|
|
|
|
m[0]
|
|
|
|
|
]);
|
|
|
|
|
} else if (rule.freq === "monthly" && d && d.length === 1 && ord
|
|
|
|
|
&& Object.keys(rule.by).length === 1) {
|
|
|
|
|
str += " " + Messages._getKey('calendar_str_monthday', [
|
|
|
|
|
d[0]
|
|
|
|
|
]);
|
|
|
|
|
} else if (rule.freq === "monthly" && md && Object.keys(rule.by).length === 1) {
|
|
|
|
|
str += " " + Messages._getKey('calendar_str_monthday', [listItems(md)]);
|
|
|
|
|
} else if (rule.freq === "weekly" && d && Object.keys(rule.by).length === 1) {
|
|
|
|
|
str += " " + Messages._getKey('calendar_str_day', [listItems(d)]);
|
|
|
|
|
} else if (rule.by) {
|
|
|
|
|
filters = Object.keys(rule.by).map(function (k) {
|
|
|
|
|
var val = rule.by[k];
|
|
|
|
|
if (k === "month") { val = m; }
|
|
|
|
|
if (k === "day") { val = d; }
|
|
|
|
|
return Messages._getKey('calendar_str_filter_'+k, [listItems(val)]);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
str += end;
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
str: Messages._getKey('calendar_rec_every_date', [str]),
|
|
|
|
|
filters: filters
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
2022-09-06 16:58:39 +00:00
|
|
|
|
var getMonthlyPattern = function (date, yearly) {
|
|
|
|
|
var d = new Date(+date);
|
|
|
|
|
var day = d.getDay();
|
|
|
|
|
var monthday = d.getDate();
|
|
|
|
|
|
|
|
|
|
// Check nth day
|
|
|
|
|
var s = new Date(+d);
|
|
|
|
|
s.setDate(1);
|
|
|
|
|
while (s.getDay() !== day) { s.setDate(s.getDate() + 1); }
|
|
|
|
|
var nth = ((monthday - s.getDate()) / 7) + 1;
|
|
|
|
|
|
|
|
|
|
// Check last day
|
|
|
|
|
var m = d.getMonth();
|
|
|
|
|
d.setDate(d.getDate() + 7);
|
|
|
|
|
var last = d.getMonth() !== m;
|
|
|
|
|
|
|
|
|
|
var dayCode = Rec.DAYORDER[day];
|
|
|
|
|
var dayStr = WEEKDAYS[day];
|
2022-10-25 09:07:54 +00:00
|
|
|
|
var monthStr = date.toLocaleDateString(getDateLanguage(), { month: 'long' });
|
2022-09-06 16:58:39 +00:00
|
|
|
|
|
|
|
|
|
var key = yearly ? "yearly" : "monthly";
|
|
|
|
|
return {
|
|
|
|
|
nth: nth + dayCode,
|
|
|
|
|
str: Messages._getKey('calendar_rec_'+key+'_nth', [
|
|
|
|
|
Messages['calendar_nth_'+nth],
|
|
|
|
|
dayStr,
|
|
|
|
|
monthStr
|
|
|
|
|
]),
|
|
|
|
|
last: last ? '-1' + dayStr : undefined,
|
|
|
|
|
lastStr: Messages._getKey('calendar_rec_'+key+'_nth', [
|
|
|
|
|
Messages['calendar_nth_last'],
|
|
|
|
|
dayStr,
|
|
|
|
|
monthStr
|
|
|
|
|
]),
|
|
|
|
|
// Messages.calendar_rec_yearly_nth
|
|
|
|
|
// Messages.calendar_rec_monthly_nth
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var getRecurrenceInput = function (date) {
|
|
|
|
|
APP.recurrenceRule = '';
|
|
|
|
|
|
|
|
|
|
var obj = APP.editModalData;
|
|
|
|
|
if (obj.id) { // Edit mode, recover recurrence data
|
|
|
|
|
var cal = obj.selectedCal.id;
|
|
|
|
|
var calData = APP.calendars[cal];
|
|
|
|
|
if (calData) {
|
2022-09-13 14:43:08 +00:00
|
|
|
|
var ev = APP.calendar.getSchedule(obj.id, cal);
|
2022-09-06 16:58:39 +00:00
|
|
|
|
APP.recurrenceRule = ev.recurrenceRule || '';
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-09-13 14:43:08 +00:00
|
|
|
|
var updatedOn = APP.recurrenceRule && APP.recurrenceRule._next;
|
|
|
|
|
if (updatedOn) { delete APP.recurrenceRule._next; }
|
2022-09-08 14:56:58 +00:00
|
|
|
|
APP.wasRecurrent = Boolean(APP.recurrenceRule);
|
2022-09-07 15:08:41 +00:00
|
|
|
|
|
|
|
|
|
// XXX TEST
|
|
|
|
|
/*
|
|
|
|
|
APP.recurrenceRule = {
|
|
|
|
|
freq: 'yearly',
|
|
|
|
|
interval: 2,
|
|
|
|
|
count: 30,
|
|
|
|
|
until: 1924902000000,
|
|
|
|
|
by: {
|
|
|
|
|
month: [1, 3, 5, 7, 9, 11],
|
|
|
|
|
weekno: [1, 11, 21, 31, 41, 51],
|
|
|
|
|
day: ["MO","TU","WE","TH","FR"]
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
var basicStr = {};
|
|
|
|
|
|
2022-09-06 16:58:39 +00:00
|
|
|
|
var options = [{
|
|
|
|
|
tag: 'a',
|
|
|
|
|
attributes: {
|
|
|
|
|
'class': 'cp-calendar-recurrence',
|
|
|
|
|
'data-value': '',
|
|
|
|
|
'href': '#',
|
|
|
|
|
},
|
|
|
|
|
content: Messages.calendar_rec_no
|
|
|
|
|
}];
|
|
|
|
|
// Basic recurrence
|
|
|
|
|
['daily', 'weekly', 'monthly', 'yearly'].forEach(function (rec) {
|
2022-09-07 15:08:41 +00:00
|
|
|
|
basicStr[rec] = JSONSortify({freq: rec});
|
2022-09-06 16:58:39 +00:00
|
|
|
|
options.push({
|
|
|
|
|
tag: 'a',
|
|
|
|
|
attributes: {
|
|
|
|
|
'class': 'cp-calendar-recurrence',
|
2022-09-07 15:08:41 +00:00
|
|
|
|
'data-value': basicStr[rec],
|
2022-09-06 16:58:39 +00:00
|
|
|
|
'href': '#',
|
|
|
|
|
},
|
|
|
|
|
content: Messages._getKey('calendar_rec_' + rec, [
|
|
|
|
|
getWeekDays(true)[date.getDay()],
|
|
|
|
|
date.getDate(),
|
2022-10-25 09:07:54 +00:00
|
|
|
|
date.toLocaleDateString(getDateLanguage(), {month:"long", day:"2-digit"})
|
2022-09-06 16:58:39 +00:00
|
|
|
|
])
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
// Weekdays / Weekend
|
|
|
|
|
var isWeekend = [0,6].includes(date.getDay());
|
|
|
|
|
var weekValue = isWeekend ? ['SA', 'SU'] : ['MO', 'TU', 'WE', 'TH', 'FR'];
|
2022-09-07 15:08:41 +00:00
|
|
|
|
basicStr.days = JSONSortify({
|
|
|
|
|
freq: 'daily',
|
|
|
|
|
by: { day: weekValue }
|
|
|
|
|
});
|
2022-09-06 16:58:39 +00:00
|
|
|
|
options.push({
|
|
|
|
|
tag: 'a',
|
|
|
|
|
attributes: {
|
|
|
|
|
'class': 'cp-calendar-recurrence',
|
2022-09-07 15:08:41 +00:00
|
|
|
|
'data-value': basicStr.days,
|
2022-09-06 16:58:39 +00:00
|
|
|
|
'href': '#',
|
|
|
|
|
},
|
|
|
|
|
content: Messages['calendar_rec_' + (isWeekend ? 'weekend' : 'weekdays')]
|
|
|
|
|
});
|
2022-09-07 15:08:41 +00:00
|
|
|
|
// Custom
|
2022-09-06 16:58:39 +00:00
|
|
|
|
options.push({
|
|
|
|
|
tag: 'a',
|
|
|
|
|
attributes: {
|
|
|
|
|
'class': 'cp-calendar-recurrence',
|
|
|
|
|
'data-value': 'custom',
|
|
|
|
|
'href': '#',
|
|
|
|
|
},
|
|
|
|
|
content: Messages.calendar_rec_custom
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
var dropdownConfig = {
|
|
|
|
|
text: Messages.calendar_rec_no,
|
|
|
|
|
options: options, // Entries displayed in the menu
|
|
|
|
|
isSelect: true,
|
|
|
|
|
common: common,
|
|
|
|
|
buttonCls: 'btn btn-secondary',
|
|
|
|
|
caretDown: true,
|
|
|
|
|
};
|
|
|
|
|
var $block = UIElements.createDropdown(dropdownConfig);
|
|
|
|
|
|
2022-09-07 15:08:41 +00:00
|
|
|
|
var translated = h('div.cp-calendar-rec-translated');
|
|
|
|
|
var $translated = $(translated);
|
2022-09-13 14:43:08 +00:00
|
|
|
|
var _addTranslation = function () {
|
2022-09-07 15:08:41 +00:00
|
|
|
|
$translated.empty();
|
|
|
|
|
|
|
|
|
|
// Dropdown value
|
|
|
|
|
var recStr = JSONSortify(APP.recurrenceRule);
|
|
|
|
|
var set = Object.keys(basicStr).some(function (k) {
|
|
|
|
|
if (recStr === basicStr[k]) {
|
|
|
|
|
$block.setValue(basicStr[k]);
|
|
|
|
|
$translated.empty();
|
2022-09-08 14:56:58 +00:00
|
|
|
|
return true;
|
2022-09-07 15:08:41 +00:00
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
if (set) { return; }
|
|
|
|
|
$block.setValue(APP.recurrenceRule ? 'custom' : '');
|
|
|
|
|
|
|
|
|
|
// Text value
|
|
|
|
|
|
2022-09-08 14:56:58 +00:00
|
|
|
|
var ruleObj = translate(APP.recurrenceRule);
|
2022-09-07 15:08:41 +00:00
|
|
|
|
if (!ruleObj || !ruleObj.str) { return; }
|
|
|
|
|
$translated.append(h('div.cp-calendar-rec-translated-str', ruleObj.str));
|
|
|
|
|
|
|
|
|
|
if (!ruleObj.filters || !Array.isArray(ruleObj.filters)
|
|
|
|
|
|| !ruleObj.filters.length) { return; }
|
|
|
|
|
var toAdd = [];
|
|
|
|
|
toAdd = ruleObj.filters.map(function (str) {
|
|
|
|
|
return h('li', str);
|
|
|
|
|
});
|
|
|
|
|
$translated.append([
|
|
|
|
|
h('div', Messages.calendar_str_filter),
|
|
|
|
|
h('ul', toAdd)
|
|
|
|
|
]);
|
|
|
|
|
};
|
2022-09-13 14:43:08 +00:00
|
|
|
|
var addUpdate = function () {
|
|
|
|
|
if (!updatedOn) { return; }
|
2022-09-15 11:15:27 +00:00
|
|
|
|
var d = new Date(updatedOn).toLocaleDateString();
|
2022-09-13 14:43:08 +00:00
|
|
|
|
$translated.append(h('div', Messages._getKey('calendar_rec_updated', [d])));
|
|
|
|
|
};
|
|
|
|
|
var addTranslation = function () {
|
|
|
|
|
_addTranslation();
|
|
|
|
|
addUpdate();
|
|
|
|
|
};
|
|
|
|
|
|
2022-09-07 15:08:41 +00:00
|
|
|
|
addTranslation();
|
|
|
|
|
|
|
|
|
|
|
2022-09-06 16:58:39 +00:00
|
|
|
|
|
|
|
|
|
var showCustom = function () {
|
|
|
|
|
var rec = APP.recurrenceRule || {};
|
|
|
|
|
|
|
|
|
|
var interval = h('input', {
|
|
|
|
|
type: "number",
|
|
|
|
|
min: 1,
|
|
|
|
|
max: 1000,
|
|
|
|
|
value: rec.interval || 1
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
var options = [];
|
|
|
|
|
['daily', 'weekly', 'monthly', 'yearly'].forEach(function (rec) {
|
|
|
|
|
options.push({
|
|
|
|
|
tag: 'a',
|
|
|
|
|
attributes: {
|
|
|
|
|
'class': 'cp-calendar-recurrence-freq',
|
|
|
|
|
'data-value': rec,
|
|
|
|
|
'href': '#',
|
|
|
|
|
},
|
|
|
|
|
content: Messages['calendar_rec_freq_' + rec]
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
var dropdownConfig = {
|
|
|
|
|
text: Messages.calendar_rec_freq_daily,
|
|
|
|
|
options: options, // Entries displayed in the menu
|
|
|
|
|
isSelect: true,
|
|
|
|
|
common: common,
|
|
|
|
|
buttonCls: 'btn btn-secondary',
|
|
|
|
|
caretDown: true,
|
|
|
|
|
};
|
|
|
|
|
var $freq = UIElements.createDropdown(dropdownConfig);
|
|
|
|
|
$freq.setValue(rec.freq || 'daily');
|
|
|
|
|
|
|
|
|
|
var radioNo = UI.createRadio('cp-calendar-rec-until', 'cp-calendar-rec-until-no',
|
|
|
|
|
Messages.calendar_rec_until_no, !rec.until && !rec.count, {});
|
|
|
|
|
var pickr;
|
|
|
|
|
var untilDate = [
|
|
|
|
|
h('span', Messages.calendar_rec_until_date),
|
|
|
|
|
pickr = h('input', {readonly:"readonly"})
|
|
|
|
|
];
|
|
|
|
|
var startPickr = Flatpickr(pickr, {
|
|
|
|
|
enableTime: false,
|
|
|
|
|
minDate: date,
|
|
|
|
|
//dateFormat: dateFormat,
|
|
|
|
|
onChange: function () {
|
|
|
|
|
//endPickr.set('minDate', startPickr.parseDate(s.value));
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
var endDate = new Date(+date);
|
|
|
|
|
endDate.setMonth(endDate.getMonth() + 1);
|
|
|
|
|
startPickr.setDate(rec.until ? new Date(rec.until) : endDate);
|
|
|
|
|
var radioDate = UI.createRadio('cp-calendar-rec-until', 'cp-calendar-rec-until-date',
|
|
|
|
|
untilDate, Boolean(rec.until), {input:{'data-value':'date'}});
|
|
|
|
|
var untilCount = [
|
|
|
|
|
h('span', Messages.calendar_rec_until_count),
|
|
|
|
|
h('input', {type: "number", value: (rec.count || 5), min: 2}),
|
|
|
|
|
h('span', Messages.calendar_rec_until_count2),
|
|
|
|
|
];
|
|
|
|
|
var radioCount = UI.createRadio('cp-calendar-rec-until', 'cp-calendar-rec-until-count',
|
|
|
|
|
untilCount, Boolean(rec.count), {input:{'data-value':'count'}});
|
|
|
|
|
var untilEls = [radioNo, radioDate, radioCount];
|
|
|
|
|
$(untilEls).find('.cp-checkmark-label input').click(function () {
|
|
|
|
|
$(this).closest('.cp-radio').find('input[type="radio"]').prop('checked', true);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
var repeat = h('div.cp-calendar-rec-inline', [
|
|
|
|
|
h('span', Messages.calendar_rec_txt),
|
|
|
|
|
interval,
|
|
|
|
|
$freq[0]
|
|
|
|
|
]);
|
2022-09-19 16:23:21 +00:00
|
|
|
|
var until = h('div.cp-calendar-rec-block.radio-group', [
|
|
|
|
|
h('div.cp-calendar-rec-block-title', Messages.calendar_rec_until),
|
|
|
|
|
untilEls
|
|
|
|
|
]);
|
2022-09-06 16:58:39 +00:00
|
|
|
|
|
|
|
|
|
var expand = h('div');
|
|
|
|
|
var $expand = $(expand);
|
|
|
|
|
var EXPAND = {};
|
|
|
|
|
EXPAND.daily = function () {};
|
|
|
|
|
EXPAND.weekly = function () {
|
2022-10-11 14:43:37 +00:00
|
|
|
|
$expand.attr('class', 'cp-calendar-rec-inline cp-calendar-weekly-pick');
|
2022-09-06 16:58:39 +00:00
|
|
|
|
var days = getWeekDays();
|
2022-10-11 14:43:37 +00:00
|
|
|
|
var active = (rec.by && rec.by.day) || [Rec.DAYORDER[date.getDay()]];
|
|
|
|
|
var line = [], dayCode;
|
2022-09-06 16:58:39 +00:00
|
|
|
|
for (var i = 1; i < 8; i++) {
|
|
|
|
|
dayCode = Rec.DAYORDER[i%7];
|
2022-10-11 14:43:37 +00:00
|
|
|
|
line.push(h('button.btn.no-margin.cp-calendar-pick-el' +
|
|
|
|
|
(active.includes(dayCode) ? '.btn-primary' : '.btn-default'), {
|
|
|
|
|
'data-value': dayCode
|
|
|
|
|
}, days[i%7]));
|
2022-09-06 16:58:39 +00:00
|
|
|
|
}
|
2022-10-11 14:43:37 +00:00
|
|
|
|
$expand.append(line);
|
|
|
|
|
$expand.find('button').click(function () {
|
|
|
|
|
var $b = $(this);
|
|
|
|
|
if ($b.is('.btn-primary')) {
|
|
|
|
|
return $b.removeClass('btn-primary').addClass('btn-default');
|
|
|
|
|
}
|
|
|
|
|
$b.removeClass('btn-default').addClass('btn-primary');
|
|
|
|
|
});
|
2022-09-06 16:58:39 +00:00
|
|
|
|
};
|
|
|
|
|
EXPAND.monthly = function () {
|
|
|
|
|
$expand.attr('class', 'cp-calendar-rec-block radio-group');
|
|
|
|
|
// Display one or two radio options accordingly
|
|
|
|
|
var checked = (rec.by && rec.by.day) || [];
|
|
|
|
|
var pattern = getMonthlyPattern(date);
|
|
|
|
|
var radioNth = UI.createRadio('cp-calendar-rec-monthly', 'cp-calendar-rec-monthly-nth',
|
|
|
|
|
pattern.str, checked.includes(pattern.nth),
|
|
|
|
|
{input:{'data-value':pattern.nth }});
|
|
|
|
|
$expand.append(radioNth);
|
|
|
|
|
|
|
|
|
|
if (pattern.last) {
|
|
|
|
|
var radioLast = UI.createRadio('cp-calendar-rec-monthly', 'cp-calendar-rec-monthly-last',
|
|
|
|
|
pattern.lastStr, checked.includes(pattern.last),
|
|
|
|
|
{input:{ 'data-value': pattern.last }});
|
|
|
|
|
$expand.append(radioLast);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var active = (rec.by && rec.by.monthday) || [date.getDate()];
|
|
|
|
|
var lines = [], l, n;
|
|
|
|
|
for (var i = 0; i < 5; i++) {
|
|
|
|
|
l = [];
|
|
|
|
|
for (var j = 1; j < 8; j++) {
|
|
|
|
|
n = i * 7 + j;
|
2022-10-11 14:43:37 +00:00
|
|
|
|
if (n > 31) {
|
|
|
|
|
l.push(h('button.btn.no-margin.cp-calendar-pick-el.lastday' +
|
|
|
|
|
(active.includes(-1) ? '.btn-primary' : '.btn-default'), {
|
|
|
|
|
'data-value': -1
|
|
|
|
|
}, Messages.calendar_month_last));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
l.push(h('button.btn.no-margin.cp-calendar-pick-el' +
|
2022-09-19 16:23:59 +00:00
|
|
|
|
(active.includes(n) ? '.btn-primary' : '.btn-default'), {
|
2022-09-06 16:58:39 +00:00
|
|
|
|
'data-value': n
|
|
|
|
|
}, n));
|
|
|
|
|
}
|
|
|
|
|
lines[i] = h('div', l);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var pickr = h('div.cp-calendar-monthly-pick', lines);
|
|
|
|
|
$(pickr).find('button').click(function () {
|
|
|
|
|
var $b = $(this);
|
2022-09-19 16:23:59 +00:00
|
|
|
|
if ($b.is('.btn-primary')) {
|
|
|
|
|
return $b.removeClass('btn-primary').addClass('btn-default');
|
2022-09-06 16:58:39 +00:00
|
|
|
|
}
|
2022-09-19 16:23:59 +00:00
|
|
|
|
$b.removeClass('btn-default').addClass('btn-primary');
|
2022-09-06 16:58:39 +00:00
|
|
|
|
});
|
|
|
|
|
var radioPickContent = [
|
|
|
|
|
h('span', Messages.calendar_rec_monthly_pick),
|
|
|
|
|
pickr
|
|
|
|
|
];
|
|
|
|
|
var radioPick = UI.createRadio('cp-calendar-rec-monthly', 'cp-calendar-rec-monthly-pick',
|
|
|
|
|
radioPickContent, !checked.length, {input:{'data-value':'pick'}});
|
|
|
|
|
$expand.append(radioPick);
|
|
|
|
|
|
|
|
|
|
$expand.find('.cp-checkmark-label button').click(function () {
|
|
|
|
|
$(this).closest('.cp-radio').find('input[type="radio"]').prop('checked', true);
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
EXPAND.yearly = function () {
|
|
|
|
|
$expand.attr('class', 'cp-calendar-rec-block radio-group');
|
|
|
|
|
|
|
|
|
|
var checked = (rec.by && rec.by.day) || [];
|
|
|
|
|
|
|
|
|
|
var radioDate = UI.createRadio('cp-calendar-rec-yearly',
|
|
|
|
|
'cp-calendar-rec-yearly-date',
|
|
|
|
|
Messages._getKey('calendar_rec_every_date', [
|
2022-10-25 09:07:54 +00:00
|
|
|
|
date.toLocaleDateString(getDateLanguage(), { month: 'long', day: 'numeric'})
|
2022-09-06 16:58:39 +00:00
|
|
|
|
]), !checked.length, { 'data-value': '' });
|
|
|
|
|
$expand.append(radioDate);
|
|
|
|
|
|
|
|
|
|
var pattern = getMonthlyPattern(date, true);
|
|
|
|
|
var radioNth = UI.createRadio('cp-calendar-rec-yearly', 'cp-calendar-rec-yearly-nth',
|
|
|
|
|
pattern.str, checked.includes(pattern.nth),
|
|
|
|
|
{input:{ 'data-value': pattern.nth }});
|
|
|
|
|
$expand.append(radioNth);
|
|
|
|
|
|
|
|
|
|
if (pattern.last) {
|
|
|
|
|
var radioLast = UI.createRadio('cp-calendar-rec-yearly', 'cp-calendar-rec-yearly-last',
|
|
|
|
|
pattern.lastStr, checked.includes(pattern.last),
|
|
|
|
|
{input:{ 'data-value': pattern.last }});
|
|
|
|
|
$expand.append(radioLast);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
EXPAND[rec.freq || "daily"]();
|
|
|
|
|
|
2022-09-07 15:08:41 +00:00
|
|
|
|
var currentFreq = rec.freq || 'daily';
|
2022-09-06 16:58:39 +00:00
|
|
|
|
$freq.onChange.reg(function (prettyVal, val) {
|
|
|
|
|
if (val === currentFreq || !val) { return; }
|
|
|
|
|
currentFreq = val;
|
|
|
|
|
rec = {};
|
|
|
|
|
$expand.empty();
|
|
|
|
|
EXPAND[val]();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var content = [repeat, expand, until];
|
|
|
|
|
|
|
|
|
|
var $modal;
|
|
|
|
|
var modal = UI.dialog.customModal(content, {
|
|
|
|
|
buttons: [{
|
|
|
|
|
className: 'cancel',
|
|
|
|
|
name: Messages.cancel,
|
|
|
|
|
onClick: function () {
|
|
|
|
|
if (!APP.recurrenceRule) { $block.setValue(''); }
|
|
|
|
|
},
|
|
|
|
|
keys: [27]
|
|
|
|
|
}, {
|
|
|
|
|
className: 'primary',
|
|
|
|
|
name: Messages.settings_save,
|
|
|
|
|
onClick: function () {
|
|
|
|
|
var freq = $freq.getValue();
|
|
|
|
|
|
|
|
|
|
var rec = APP.recurrenceRule = {
|
|
|
|
|
freq: freq,
|
|
|
|
|
interval: Number($(interval).val()) || 1,
|
|
|
|
|
by: {}
|
|
|
|
|
};
|
2022-09-07 15:08:41 +00:00
|
|
|
|
if (rec.interval === 1) { delete rec.interval; }
|
2022-09-06 16:58:39 +00:00
|
|
|
|
|
|
|
|
|
var until = $modal.find('input[name="cp-calendar-rec-until"]:checked').data('value');
|
|
|
|
|
if (until === "count") {
|
|
|
|
|
rec.count = $(radioCount).find('input[type="number"]').val();
|
|
|
|
|
} else if (until === "date") {
|
|
|
|
|
var _date = Flatpickr.parseDate(pickr.value);
|
|
|
|
|
_date.setDate(_date.getDate()+1);
|
|
|
|
|
rec.until = +_date - 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (freq === "weekly") {
|
|
|
|
|
rec.by.day = [];
|
2022-10-11 14:43:37 +00:00
|
|
|
|
$expand.find('button.cp-calendar-pick-el.btn-primary')
|
|
|
|
|
.each(function (i, el) {
|
2022-09-06 16:58:39 +00:00
|
|
|
|
rec.by.day.push($(el).data('value'));
|
|
|
|
|
});
|
2022-10-11 14:43:37 +00:00
|
|
|
|
if (!rec.by.day.length) { delete rec.by.day; }
|
2022-09-06 16:58:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (freq === "monthly") {
|
|
|
|
|
var _m = $expand.find('input[name="cp-calendar-rec-monthly"]:checked').data('value');
|
|
|
|
|
if (_m === "pick") {
|
|
|
|
|
rec.by.monthday = [];
|
2022-10-11 14:43:37 +00:00
|
|
|
|
$expand.find('div.cp-calendar-monthly-pick button.btn-primary')
|
2022-09-06 16:58:39 +00:00
|
|
|
|
.each(function (i, el) {
|
|
|
|
|
rec.by.monthday.push($(el).data('value'));
|
|
|
|
|
});
|
|
|
|
|
if (!rec.by.monthday.length) { delete rec.by.monthday; }
|
|
|
|
|
} else {
|
|
|
|
|
rec.by.day = [_m];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (freq === "yearly") {
|
|
|
|
|
var _y = $expand.find('input[name="cp-calendar-rec-yearly"]:checked').data('value');
|
|
|
|
|
if (_y) {
|
|
|
|
|
rec.by.month = [date.getMonth()+1];
|
2022-09-07 15:08:41 +00:00
|
|
|
|
rec.by.day = [_y];
|
2022-09-06 16:58:39 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!Object.keys(rec.by).length) { delete rec.by; }
|
2022-09-07 15:08:41 +00:00
|
|
|
|
|
|
|
|
|
addTranslation();
|
2022-09-06 16:58:39 +00:00
|
|
|
|
},
|
|
|
|
|
keys: [13]
|
|
|
|
|
}]
|
|
|
|
|
});
|
|
|
|
|
$modal = $(modal);
|
|
|
|
|
UI.openCustomModal(modal);
|
|
|
|
|
$modal.closest('.alertify').on('mousedown', function (e) {
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
$block.onChange.reg(function(name, val) {
|
|
|
|
|
if (val === "custom") { return void showCustom(); }
|
|
|
|
|
APP.recurrenceRule = val;
|
2022-09-07 15:08:41 +00:00
|
|
|
|
addTranslation();
|
2022-09-06 16:58:39 +00:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return h('div.cp-calendar-recurrence-container', [
|
2022-09-14 12:52:50 +00:00
|
|
|
|
h('span.cp-recurrence-label', [
|
|
|
|
|
h('i.fa.fa-repeat', {'aria-hidden':'true'}),
|
|
|
|
|
Messages.calendar_rec]),
|
2022-09-06 16:58:39 +00:00
|
|
|
|
$block[0],
|
2022-09-14 12:52:50 +00:00
|
|
|
|
translated
|
2022-09-06 16:58:39 +00:00
|
|
|
|
]);
|
|
|
|
|
};
|
|
|
|
|
|
2021-04-13 13:21:24 +00:00
|
|
|
|
var parseNotif = function (minutes) {
|
|
|
|
|
var res = {
|
|
|
|
|
unit: 'minutes',
|
|
|
|
|
value: minutes
|
|
|
|
|
};
|
|
|
|
|
var hours = minutes / 60;
|
|
|
|
|
if (!Number.isInteger(hours)) { return res; }
|
|
|
|
|
res.unit = 'hours';
|
|
|
|
|
res.value = hours;
|
|
|
|
|
var days = hours / 24;
|
|
|
|
|
if (!Number.isInteger(days)) { return res; }
|
|
|
|
|
res.unit = 'days';
|
|
|
|
|
res.value = days;
|
|
|
|
|
return res;
|
|
|
|
|
};
|
|
|
|
|
var getNotificationDropdown = function () {
|
|
|
|
|
var ev = APP.editModalData;
|
|
|
|
|
var calId = ev.selectedCal.id;
|
2021-04-28 13:35:40 +00:00
|
|
|
|
// DEFAULT HERE [10] ==> 10 minutes before the event
|
2022-09-08 14:56:58 +00:00
|
|
|
|
var id = (ev.id && ev.id.split('|')[0]) || undefined;
|
2022-09-12 17:06:25 +00:00
|
|
|
|
var _ev = APP.calendar.getSchedule(ev.id, calId);
|
|
|
|
|
var oldReminders = _ev && _ev.raw && _ev.raw.reminders;
|
|
|
|
|
if (!oldReminders) {
|
|
|
|
|
oldReminders = Util.find(APP.calendars, [calId, 'content', 'content', id, 'reminders']) || [60];
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-13 13:21:24 +00:00
|
|
|
|
APP.notificationsEntries = [];
|
|
|
|
|
var number = h('input.tui-full-calendar-content', {
|
|
|
|
|
type: "number",
|
|
|
|
|
value: 10,
|
|
|
|
|
min: 1,
|
|
|
|
|
max: 60
|
|
|
|
|
});
|
|
|
|
|
var $number = $(number);
|
|
|
|
|
var options = ['minutes', 'hours', 'days'].map(function (k) {
|
|
|
|
|
return {
|
|
|
|
|
tag: 'a',
|
|
|
|
|
attributes: {
|
|
|
|
|
'class': 'cp-calendar-reminder',
|
|
|
|
|
'data-value': k,
|
|
|
|
|
'href': '#',
|
|
|
|
|
},
|
|
|
|
|
content: Messages['calendar_'+k]
|
|
|
|
|
// Messages.calendar_minutes
|
|
|
|
|
// Messages.calendar_hours
|
|
|
|
|
// Messages.calendar_days
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
var dropdownConfig = {
|
|
|
|
|
text: Messages.calendar_minutes,
|
|
|
|
|
options: options, // Entries displayed in the menu
|
|
|
|
|
isSelect: true,
|
|
|
|
|
common: common,
|
|
|
|
|
buttonCls: 'btn btn-secondary',
|
|
|
|
|
caretDown: true,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var $block = UIElements.createDropdown(dropdownConfig);
|
|
|
|
|
$block.setValue('minutes');
|
|
|
|
|
var $types = $block.find('a');
|
|
|
|
|
$types.click(function () {
|
|
|
|
|
var mode = $(this).attr('data-value');
|
|
|
|
|
var max = mode === "minutes" ? 60 : 24;
|
|
|
|
|
$number.attr('max', max);
|
|
|
|
|
if ($number.val() > max) { $number.val(max); }
|
|
|
|
|
});
|
2021-04-22 16:33:17 +00:00
|
|
|
|
var addNotif = h('button.btn.btn-primary-outline.fa.fa-plus');
|
2021-04-13 13:21:24 +00:00
|
|
|
|
var $list = $(h('div.cp-calendar-notif-list'));
|
|
|
|
|
var listContainer = h('div.cp-calendar-notif-list-container', [
|
2022-09-14 12:52:50 +00:00
|
|
|
|
h('span.cp-notif-label', [
|
|
|
|
|
h('i.fa.fa-bell', {'aria-hidden':'true'}),
|
|
|
|
|
Messages.calendar_notifications
|
|
|
|
|
]),
|
2021-04-13 13:21:24 +00:00
|
|
|
|
$list[0],
|
|
|
|
|
h('span.cp-notif-empty', Messages.calendar_noNotification)
|
|
|
|
|
]);
|
2022-09-19 16:25:15 +00:00
|
|
|
|
|
2021-04-13 13:21:24 +00:00
|
|
|
|
var addNotification = function (unit, value) {
|
|
|
|
|
var unitValue = (unit === "minutes") ? 1 : (unit === "hours" ? 60 : (60*24));
|
2022-09-19 16:25:15 +00:00
|
|
|
|
var del = h('button.btn.btn-danger-outline.small.fa.fa-times',
|
2022-10-10 15:05:15 +00:00
|
|
|
|
{'title': Messages.calendar_removeNotification}
|
2022-09-19 16:25:15 +00:00
|
|
|
|
);
|
2021-04-13 13:21:24 +00:00
|
|
|
|
var minutes = value * unitValue;
|
|
|
|
|
if ($list.find('[data-minutes="'+minutes+'"]').length) { return; }
|
|
|
|
|
var span = h('span.cp-notif-entry', {
|
|
|
|
|
'data-minutes': minutes
|
|
|
|
|
}, [
|
2021-04-22 16:33:17 +00:00
|
|
|
|
h('span.cp-notif-value', [
|
|
|
|
|
h('span', value),
|
|
|
|
|
h('span', Messages['calendar_'+unit]),
|
|
|
|
|
h('span.cp-before', Messages.calendar_before)
|
|
|
|
|
]),
|
2021-04-13 13:21:24 +00:00
|
|
|
|
del
|
|
|
|
|
]);
|
|
|
|
|
$(del).click(function () {
|
|
|
|
|
$(span).remove();
|
|
|
|
|
var idx = APP.notificationsEntries.indexOf(minutes);
|
|
|
|
|
APP.notificationsEntries.splice(idx, 1);
|
|
|
|
|
});
|
|
|
|
|
$list.append(span);
|
|
|
|
|
APP.notificationsEntries.push(minutes);
|
|
|
|
|
};
|
|
|
|
|
$(addNotif).click(function () {
|
|
|
|
|
var unit = $block.getValue();
|
|
|
|
|
var value = $number.val();
|
|
|
|
|
addNotification(unit, value);
|
|
|
|
|
});
|
|
|
|
|
oldReminders.forEach(function (minutes) {
|
|
|
|
|
var p = parseNotif(minutes);
|
|
|
|
|
addNotification(p.unit, p.value);
|
|
|
|
|
});
|
|
|
|
|
return h('div.tui-full-calendar-popup-section.cp-calendar-add-notif', [
|
|
|
|
|
listContainer,
|
|
|
|
|
h('div.cp-calendar-notif-form', [
|
|
|
|
|
h('span.cp-notif-label', Messages.calendar_addNotification),
|
|
|
|
|
number,
|
|
|
|
|
$block[0],
|
|
|
|
|
addNotif
|
|
|
|
|
])
|
|
|
|
|
]);
|
|
|
|
|
};
|
|
|
|
|
|
2021-04-02 11:44:28 +00:00
|
|
|
|
var createToolbar = function () {
|
|
|
|
|
var displayed = ['useradmin', 'newpad', 'limit', 'pageTitle', 'notifications'];
|
|
|
|
|
var configTb = {
|
|
|
|
|
displayed: displayed,
|
|
|
|
|
sfCommon: common,
|
|
|
|
|
$container: APP.$toolbar,
|
|
|
|
|
pageTitle: Messages.calendar,
|
|
|
|
|
metadataMgr: common.getMetadataMgr(),
|
|
|
|
|
};
|
|
|
|
|
APP.toolbar = Toolbar.create(configTb);
|
|
|
|
|
APP.toolbar.$rightside.hide();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var onEvent = function (obj) {
|
|
|
|
|
var ev = obj.ev;
|
|
|
|
|
var data = obj.data;
|
|
|
|
|
if (ev === 'UPDATE') {
|
2021-04-02 16:21:59 +00:00
|
|
|
|
onCalendarUpdate(data);
|
2021-04-02 11:44:28 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
nThen(function (waitFor) {
|
|
|
|
|
$(waitFor(UI.addLoadingScreen));
|
|
|
|
|
SFCommon.create(waitFor(function (c) { APP.common = common = c; }));
|
|
|
|
|
}).nThen(function (waitFor) {
|
|
|
|
|
APP.$toolbar = $('#cp-toolbar');
|
|
|
|
|
sframeChan = common.getSframeChannel();
|
|
|
|
|
sframeChan.onReady(waitFor());
|
|
|
|
|
}).nThen(function (/*waitFor*/) {
|
|
|
|
|
createToolbar();
|
2021-04-06 16:21:48 +00:00
|
|
|
|
metadataMgr = common.getMetadataMgr();
|
2021-04-02 13:18:59 +00:00
|
|
|
|
var privateData = metadataMgr.getPrivateData();
|
|
|
|
|
var user = metadataMgr.getUserData();
|
|
|
|
|
|
2021-05-04 09:30:06 +00:00
|
|
|
|
APP.loggedIn = common.isLoggedIn();
|
|
|
|
|
|
2021-04-14 13:51:36 +00:00
|
|
|
|
common.setTabTitle(Messages.calendar);
|
|
|
|
|
|
2021-04-02 11:44:28 +00:00
|
|
|
|
// Fix flatpickr selection
|
|
|
|
|
var MutationObserver = window.MutationObserver;
|
|
|
|
|
var onFlatPickr = function (el) {
|
|
|
|
|
// Don't close event creation popup when clicking on flatpickr
|
|
|
|
|
$(el).mousedown(function (e) {
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
var observer = new MutationObserver(function(mutations) {
|
|
|
|
|
mutations.forEach(function(mutation) {
|
|
|
|
|
var node;
|
|
|
|
|
for (var i = 0; i < mutation.addedNodes.length; i++) {
|
2021-04-08 12:02:39 +00:00
|
|
|
|
node = mutation.addedNodes[i];
|
2021-04-02 11:44:28 +00:00
|
|
|
|
if (node.classList && node.classList.contains('flatpickr-calendar')) {
|
|
|
|
|
onFlatPickr(node);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
observer.observe($('body')[0], {
|
|
|
|
|
childList: true,
|
|
|
|
|
subtree: false
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Customize creation/update popup
|
|
|
|
|
var onCalendarPopup = function (el) {
|
|
|
|
|
var $el = $(el);
|
2021-04-09 10:01:59 +00:00
|
|
|
|
$el.find('.tui-full-calendar-confirm').addClass('btn btn-primary').prepend(h('i.fa.fa-floppy-o'));
|
2021-04-02 11:44:28 +00:00
|
|
|
|
$el.find('input').attr('autocomplete', 'off');
|
|
|
|
|
$el.find('.tui-full-calendar-dropdown-button').addClass('btn btn-secondary');
|
|
|
|
|
$el.find('.tui-full-calendar-popup-close').addClass('btn btn-cancel fa fa-times cp-calendar-close').empty();
|
2021-04-06 12:03:51 +00:00
|
|
|
|
|
2022-09-06 16:58:39 +00:00
|
|
|
|
var $container = $el.closest('.tui-full-calendar-floating-layer');
|
|
|
|
|
$container.addClass('cp-calendar-popup-flex');
|
|
|
|
|
$container.css('display', 'flex').mousedown(function (e) {
|
|
|
|
|
if ($(e.target).is('.cp-calendar-popup-flex')) {
|
|
|
|
|
$el.find('.tui-full-calendar-popup-close').click();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2021-04-06 12:03:51 +00:00
|
|
|
|
var calendars = APP.calendars || {};
|
|
|
|
|
var show = false;
|
|
|
|
|
$el.find('.tui-full-calendar-dropdown-menu li').each(function (i, li) {
|
|
|
|
|
var $li = $(li);
|
|
|
|
|
var id = $li.attr('data-calendar-id');
|
|
|
|
|
var c = calendars[id];
|
|
|
|
|
if (!c || c.readOnly) {
|
|
|
|
|
return void $li.remove();
|
|
|
|
|
}
|
|
|
|
|
// If at least one calendar is editable, show the popup
|
|
|
|
|
show = true;
|
|
|
|
|
});
|
|
|
|
|
if ($el.find('.tui-full-calendar-hide.tui-full-calendar-dropdown').length || !show) {
|
2021-04-06 10:12:12 +00:00
|
|
|
|
$el.hide();
|
|
|
|
|
UI.warn(Messages.calendar_errorNoCalendar);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2021-04-06 09:31:25 +00:00
|
|
|
|
var isUpdate = Boolean($el.find('#tui-full-calendar-schedule-title').val());
|
2021-04-07 15:13:28 +00:00
|
|
|
|
if (!isUpdate) { $el.find('.tui-full-calendar-dropdown-menu li').first().click(); }
|
2021-04-13 13:21:24 +00:00
|
|
|
|
|
|
|
|
|
var $button = $el.find('.tui-full-calendar-section-button-save');
|
2022-09-06 16:58:39 +00:00
|
|
|
|
|
|
|
|
|
var $startDate = $el.find('#tui-full-calendar-schedule-start-date');
|
|
|
|
|
var startDate = Flatpickr.parseDate($startDate.val());
|
2022-09-08 14:56:58 +00:00
|
|
|
|
|
2022-09-06 16:58:39 +00:00
|
|
|
|
var divRec = getRecurrenceInput(startDate);
|
|
|
|
|
$button.before(divRec);
|
|
|
|
|
|
2021-04-13 13:21:24 +00:00
|
|
|
|
var div = getNotificationDropdown();
|
|
|
|
|
$button.before(div);
|
2021-04-13 15:36:22 +00:00
|
|
|
|
|
2022-09-08 14:56:58 +00:00
|
|
|
|
// Use Flatpickr with or without time depending on allday checkbox
|
2021-04-13 15:35:44 +00:00
|
|
|
|
var $cbox = $el.find('#tui-full-calendar-schedule-allday');
|
|
|
|
|
var allDay = $cbox.is(':checked');
|
2022-09-06 16:58:39 +00:00
|
|
|
|
var allDayFormat = 'Y-m-d';
|
|
|
|
|
var timeFormat = '';
|
|
|
|
|
var setFormat = function (allDay) {
|
|
|
|
|
var s = window.CP_startPickr;
|
|
|
|
|
var e = window.CP_endPickr;
|
|
|
|
|
if (!timeFormat) { timeFormat = s.config.dateFormat; }
|
|
|
|
|
s.set('dateFormat', allDay ? allDayFormat : timeFormat);
|
|
|
|
|
e.set('dateFormat', allDay ? allDayFormat : timeFormat);
|
|
|
|
|
};
|
|
|
|
|
setFormat(allDay);
|
2021-04-13 15:35:44 +00:00
|
|
|
|
$el.find('.tui-full-calendar-section-allday').click(function () {
|
|
|
|
|
setTimeout(function () {
|
|
|
|
|
var allDay = $cbox.is(':checked');
|
2022-09-06 16:58:39 +00:00
|
|
|
|
setFormat(allDay);
|
2021-04-13 15:35:44 +00:00
|
|
|
|
});
|
|
|
|
|
});
|
2021-04-02 11:44:28 +00:00
|
|
|
|
};
|
2021-04-06 12:03:51 +00:00
|
|
|
|
var onCalendarEditPopup = function (el) {
|
2021-04-09 10:01:59 +00:00
|
|
|
|
var $el = $(el);
|
|
|
|
|
$el.find('.tui-full-calendar-popup-edit').addClass('btn btn-primary');
|
|
|
|
|
$el.find('.tui-full-calendar-popup-edit .tui-full-calendar-icon').addClass('fa fa-pencil').removeClass('tui-full-calendar-icon');
|
|
|
|
|
$el.find('.tui-full-calendar-content').removeClass('tui-full-calendar-content');
|
2022-09-08 14:56:58 +00:00
|
|
|
|
|
2022-10-11 15:00:13 +00:00
|
|
|
|
var delButton = h('button.btn.btn-danger', [
|
|
|
|
|
h('i.fa.fa-trash'),
|
|
|
|
|
h('span', Messages.kanban_delete)
|
|
|
|
|
]);
|
|
|
|
|
var $del = $el.find('.tui-full-calendar-popup-delete').hide();
|
|
|
|
|
$del.after(delButton);
|
|
|
|
|
UI.confirmButton(delButton, {
|
|
|
|
|
classes: 'danger'
|
|
|
|
|
}, function () {
|
|
|
|
|
$del.click();
|
|
|
|
|
});
|
2022-09-08 14:56:58 +00:00
|
|
|
|
var $section = $el.find('.tui-full-calendar-section-button');
|
|
|
|
|
var ev = APP.editModalData;
|
|
|
|
|
var data = ev.schedule || {};
|
|
|
|
|
var id = data.id;
|
|
|
|
|
if (!id) { return; }
|
|
|
|
|
if (id.indexOf('|') === -1) { return; } // Original event ID doesn't contain |
|
|
|
|
|
|
2022-09-15 15:19:12 +00:00
|
|
|
|
if (APP.nextLocationUid) {
|
|
|
|
|
var uid = APP.nextLocationUid;
|
|
|
|
|
delete APP.nextLocationUid;
|
|
|
|
|
var $a = $el.find('#'+uid);
|
|
|
|
|
$a.click(function (e) {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
common.openUnsafeURL($a.attr('href'));
|
|
|
|
|
});
|
|
|
|
|
}
|
2022-09-08 14:56:58 +00:00
|
|
|
|
// This is a recurring event, add button to stop recurrence now
|
2022-10-12 15:48:24 +00:00
|
|
|
|
var $b = $(h('button.btn.btn-default', [
|
2022-09-08 14:56:58 +00:00
|
|
|
|
h('i.fa.fa-times'),
|
|
|
|
|
h('span', Messages.calendar_rec_stop)
|
|
|
|
|
])).insertBefore($section);
|
2022-10-12 15:48:24 +00:00
|
|
|
|
UI.confirmButton($b[0], { classes: 'btn-default' }, function () {
|
2022-09-08 14:56:58 +00:00
|
|
|
|
var originalId = id.split('|')[0];
|
|
|
|
|
var originalEvent = Util.find(APP.calendars,
|
|
|
|
|
[ev.schedule.calendarId, 'content', 'content', originalId]);
|
|
|
|
|
var rec = originalEvent.recurrenceRule;
|
|
|
|
|
if (!rec) { return; }
|
|
|
|
|
rec.until = (ev.schedule.raw && ev.schedule.raw.start) - 1;
|
|
|
|
|
data.id = originalId;
|
|
|
|
|
updateEvent({
|
|
|
|
|
ev: data,
|
|
|
|
|
changes: {
|
|
|
|
|
recurrenceRule: rec
|
|
|
|
|
},
|
|
|
|
|
type: {
|
|
|
|
|
which: 'all'
|
|
|
|
|
}
|
|
|
|
|
}, function (err) {
|
|
|
|
|
if (err) {
|
|
|
|
|
console.error(err);
|
|
|
|
|
return void UI.warn(err);
|
|
|
|
|
}
|
|
|
|
|
$b.closest('.tui-full-calendar-floating-layer').hide();
|
|
|
|
|
});
|
|
|
|
|
});
|
2021-04-06 12:03:51 +00:00
|
|
|
|
};
|
2021-04-07 11:51:50 +00:00
|
|
|
|
var onPopupRemoved = function () {
|
|
|
|
|
var start, end;
|
|
|
|
|
if (window.CP_startPickr) { start = window.CP_startPickr.calendarContainer; }
|
|
|
|
|
if (window.CP_endPickr) { end = window.CP_endPickr.calendarContainer; }
|
|
|
|
|
$('.flatpickr-calendar').each(function (i, el) {
|
|
|
|
|
if (el === start || el === end) { return; }
|
|
|
|
|
$(el).remove();
|
|
|
|
|
});
|
|
|
|
|
};
|
2021-04-08 12:02:39 +00:00
|
|
|
|
var observer2 = new MutationObserver(function(mutations) {
|
2021-04-02 11:44:28 +00:00
|
|
|
|
mutations.forEach(function(mutation) {
|
2021-04-08 12:02:39 +00:00
|
|
|
|
var node, _node;
|
2021-04-02 11:44:28 +00:00
|
|
|
|
for (var i = 0; i < mutation.addedNodes.length; i++) {
|
2021-04-08 12:02:39 +00:00
|
|
|
|
node = mutation.addedNodes[i];
|
2021-04-06 12:03:51 +00:00
|
|
|
|
try {
|
|
|
|
|
if (node.classList && node.classList.contains('tui-full-calendar-popup')
|
2021-04-07 11:51:50 +00:00
|
|
|
|
&& !node.classList.contains('tui-full-calendar-popup-detail')) {
|
2021-04-06 12:03:51 +00:00
|
|
|
|
onCalendarPopup(node);
|
|
|
|
|
}
|
|
|
|
|
if (node.classList && node.classList.contains('tui-full-calendar-popup')
|
2021-04-07 11:51:50 +00:00
|
|
|
|
&& node.classList.contains('tui-full-calendar-popup-detail')) {
|
2021-04-06 12:03:51 +00:00
|
|
|
|
onCalendarEditPopup(node);
|
|
|
|
|
}
|
|
|
|
|
} catch (e) {}
|
2021-04-02 11:44:28 +00:00
|
|
|
|
}
|
2021-04-07 11:51:50 +00:00
|
|
|
|
for (var j = 0; j < mutation.removedNodes.length; j++) {
|
2021-04-08 12:02:39 +00:00
|
|
|
|
_node = mutation.addedNodes[j];
|
2021-04-07 11:51:50 +00:00
|
|
|
|
try {
|
|
|
|
|
if (_node.classList && _node.classList.contains('tui-full-calendar-popup')) {
|
|
|
|
|
onPopupRemoved();
|
|
|
|
|
}
|
|
|
|
|
} catch (e) {}
|
|
|
|
|
}
|
2021-04-02 11:44:28 +00:00
|
|
|
|
});
|
|
|
|
|
});
|
2021-04-08 12:02:39 +00:00
|
|
|
|
observer2.observe($('body')[0], {
|
2021-04-02 11:44:28 +00:00
|
|
|
|
childList: true,
|
|
|
|
|
subtree: true
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
APP.module = common.makeUniversal('calendar', {
|
|
|
|
|
onEvent: onEvent
|
|
|
|
|
});
|
2021-04-13 13:42:04 +00:00
|
|
|
|
var store = window.cryptpadStore;
|
2021-04-02 13:18:59 +00:00
|
|
|
|
APP.module.execCommand('SUBSCRIBE', null, function (obj) {
|
2021-04-07 13:49:20 +00:00
|
|
|
|
if (obj.empty && !privateData.calendarHash) {
|
2021-05-04 09:30:06 +00:00
|
|
|
|
if (!privateData.loggedIn) {
|
|
|
|
|
return void UI.errorLoadingScreen(Messages.mustLogin, false, function () {
|
|
|
|
|
common.setLoginRedirect('login');
|
|
|
|
|
});
|
|
|
|
|
}
|
2021-04-02 13:18:59 +00:00
|
|
|
|
// No calendar yet, create one
|
|
|
|
|
newCalendar({
|
|
|
|
|
teamId: 1,
|
2021-04-08 10:02:36 +00:00
|
|
|
|
initialCalendar: true,
|
2021-04-02 13:18:59 +00:00
|
|
|
|
color: user.color,
|
|
|
|
|
title: Messages.calendar_default
|
2021-04-08 12:02:39 +00:00
|
|
|
|
}, function (err) {
|
2021-05-04 09:43:58 +00:00
|
|
|
|
if (err) { return void UI.errorLoadingScreen(Messages.error); }
|
2021-04-13 13:42:04 +00:00
|
|
|
|
store.get('calendarView', makeCalendar);
|
2021-04-02 13:18:59 +00:00
|
|
|
|
UI.removeLoadingScreen();
|
|
|
|
|
});
|
|
|
|
|
return;
|
|
|
|
|
}
|
2021-04-06 16:21:48 +00:00
|
|
|
|
if (privateData.calendarHash) {
|
2021-04-22 16:33:17 +00:00
|
|
|
|
var hash = privateData.hashes.editHash || privateData.hashes.viewHash;
|
|
|
|
|
var secret = Hash.getSecrets('calendar', hash, privateData.password);
|
|
|
|
|
APP.currentCalendar = secret.channel;
|
2021-04-06 16:21:48 +00:00
|
|
|
|
APP.module.execCommand('OPEN', {
|
2021-04-22 16:33:17 +00:00
|
|
|
|
hash: hash,
|
2021-04-06 16:21:48 +00:00
|
|
|
|
password: privateData.password
|
|
|
|
|
}, function (obj) {
|
2021-04-07 13:49:20 +00:00
|
|
|
|
if (obj && obj.error) { console.error(obj.error); }
|
2021-04-06 16:21:48 +00:00
|
|
|
|
});
|
2022-09-14 14:11:54 +00:00
|
|
|
|
} else if (privateData.calendarOpts) {
|
|
|
|
|
APP.initTime = privateData.calendarOpts.time;
|
2021-04-06 16:21:48 +00:00
|
|
|
|
}
|
2021-04-13 13:42:04 +00:00
|
|
|
|
store.get('calendarView', makeCalendar);
|
2021-04-02 11:44:28 +00:00
|
|
|
|
UI.removeLoadingScreen();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
APP.origin = privateData.origin;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
});
|