Files

258 lines
8.7 KiB
QML

import QtQuick
import qs.Common
import qs.Services
import qs.DCommon.Widgets
import qs.Modules.Settings.Widgets
Column {
id: root
LayoutMirroring.enabled: I18n.isRtl
LayoutMirroring.childrenInherit: true
property var eventData: null
property date initialDate: new Date()
property var transientSurfaceTracker: null
signal saved
signal closeRequested
property string fTitle: ""
property bool fAllDay: false
property date fDate: initialDate
property int fStartHour: 10
property int fStartMinute: 0
property int fEndHour: 11
property int fEndMinute: 0
property string fLocation: ""
property string fDescription: ""
property string fCalendarId: ""
property int fReminder: -1
property string errorText: ""
property bool saving: false
readonly property var _cals: CalendarService.writableCalendars()
readonly property var _remLabels: [I18n.tr("No reminder"), I18n.tr("At start"), I18n.tr("%1 before", "calendar reminder option, %1 is a duration such as 15 minutes").arg(I18n.duration(300)), I18n.tr("%1 before", "calendar reminder option, %1 is a duration such as 15 minutes").arg(I18n.duration(600)), I18n.tr("%1 before", "calendar reminder option, %1 is a duration such as 15 minutes").arg(I18n.duration(900)), I18n.tr("%1 before", "calendar reminder option, %1 is a duration such as 15 minutes").arg(I18n.duration(1800)), I18n.tr("%1 before", "calendar reminder option, %1 is a duration such as 15 minutes").arg(I18n.duration(3600)), I18n.tr("%1 before", "calendar reminder option, %1 is a duration such as 15 minutes").arg(I18n.duration(86400))]
readonly property var _remMins: [-1, 0, 5, 10, 15, 30, 60, 1440]
spacing: Theme.spacingM
function _isoFromDateTime(dateObj, h, m) {
const d = new Date(dateObj);
d.setHours(h, m, 0, 0);
return d.toISOString();
}
function _allDayIso(dateObj, dayOffset) {
return new Date(Date.UTC(dateObj.getFullYear(), dateObj.getMonth(), dateObj.getDate() + dayOffset)).toISOString();
}
function _calendarName(id) {
for (let i = 0; i < _cals.length; i++) {
if (_cals[i].id === id)
return _cals[i].name;
}
return _cals.length > 0 ? _cals[0].name : "";
}
function shiftDate(days) {
const d = new Date(fDate);
d.setDate(d.getDate() + days);
fDate = d;
}
function save() {
const title = fTitle.trim();
if (!title) {
errorText = I18n.tr("Title is required");
return;
}
let calId = fCalendarId;
if (!calId) {
const def = CalendarService.defaultCalendar();
calId = def ? def.id : "";
}
if (!calId) {
errorText = I18n.tr("No writable calendar available");
return;
}
let startIso, endIso;
if (fAllDay) {
startIso = _allDayIso(fDate, 0);
endIso = _allDayIso(fDate, 1);
} else {
startIso = _isoFromDateTime(fDate, fStartHour, fStartMinute);
endIso = _isoFromDateTime(fDate, fEndHour, fEndMinute);
if (new Date(endIso).getTime() <= new Date(startIso).getTime()) {
errorText = I18n.tr("End must be after start");
return;
}
}
const fields = {
"calendarId": calId,
"summary": title,
"description": fDescription,
"location": fLocation,
"start": startIso,
"end": endIso,
"allDay": fAllDay,
"reminders": fReminder >= 0 ? [
{
"method": "popup",
"minutes": fReminder
}
] : []
};
saving = true;
errorText = "";
const cb = response => {
saving = false;
if (response.error) {
errorText = response.error;
return;
}
root.saved();
};
if (eventData && eventData.id)
CalendarService.updateEvent(eventData.id, fields, cb);
else
CalendarService.createEvent(fields, cb);
}
Component.onCompleted: {
if (!eventData) {
fCalendarId = CalendarService.defaultCalendar() ? CalendarService.defaultCalendar().id : "";
return;
}
fTitle = eventData.title || "";
fAllDay = !!eventData.allDay;
fDate = eventData.start;
fStartHour = eventData.start.getHours();
fStartMinute = eventData.start.getMinutes();
fEndHour = eventData.end.getHours();
fEndMinute = eventData.end.getMinutes();
fLocation = eventData.location || "";
fDescription = eventData.description || "";
fCalendarId = eventData.calendarId || "";
if (eventData.reminders && eventData.reminders.length > 0)
fReminder = eventData.reminders[0].minutes;
}
SettingsGroup {
width: parent.width
slotColor: Theme.chipSurface
SettingsTextFieldRow {
text: I18n.tr("Title")
leftIconName: "title"
placeholderText: I18n.tr("Event title")
value: root.fTitle
onValueEdited: value => root.fTitle = value
onAccepted: root.save()
}
SettingsToggleRow {
text: I18n.tr("All day")
checked: root.fAllDay
onToggled: checked => root.fAllDay = checked
}
SettingsRow {
title: I18n.tr("Date")
subtitle: Qt.formatDate(root.fDate, "ddd, MMM d yyyy")
subtitleColor: Theme.surfaceText
DActionButton {
iconName: I18n.isRtl ? "chevron_right" : "chevron_left"
Accessible.name: I18n.tr("Previous")
onClicked: root.shiftDate(-1)
}
DActionButton {
iconName: I18n.isRtl ? "chevron_left" : "chevron_right"
Accessible.name: I18n.tr("Next")
onClicked: root.shiftDate(1)
}
}
SettingsTimeRow {
visible: !root.fAllDay
is24Hour: SettingsData.use24HourClock
startTitle: I18n.tr("Start")
startHour: root.fStartHour
startMinute: root.fStartMinute
endTitle: I18n.tr("End")
endHour: root.fEndHour
endMinute: root.fEndMinute
onStartChanged: (hour, minute) => {
root.fStartHour = hour;
root.fStartMinute = minute;
}
onEndChanged: (hour, minute) => {
root.fEndHour = hour;
root.fEndMinute = minute;
}
}
SettingsDropdownRow {
text: I18n.tr("Calendar")
transientSurfaceTracker: root.transientSurfaceTracker
options: root._cals.map(c => c.name)
currentValue: root._calendarName(root.fCalendarId)
onValueChanged: value => {
const cal = root._cals.find(c => c.name === value);
if (cal)
root.fCalendarId = cal.id;
}
}
SettingsDropdownRow {
text: I18n.tr("Reminder", "noun, calendar event reminder time dropdown label")
transientSurfaceTracker: root.transientSurfaceTracker
options: root._remLabels
currentValue: root._remLabels[Math.max(0, root._remMins.indexOf(root.fReminder))]
onValueChanged: value => {
const idx = root._remLabels.indexOf(value);
if (idx >= 0)
root.fReminder = root._remMins[idx];
}
}
SettingsTextFieldRow {
text: I18n.tr("Location", "calendar event venue field label", true)
leftIconName: "place"
placeholderText: I18n.tr("Add location")
value: root.fLocation
onValueEdited: value => root.fLocation = value
}
SettingsTextFieldRow {
text: I18n.tr("Notes", "noun, calendar event notes field label")
leftIconName: "notes"
placeholderText: I18n.tr("Add notes")
value: root.fDescription
onValueEdited: value => root.fDescription = value
}
}
Row {
width: parent.width
spacing: Theme.spacingS
layoutDirection: Qt.RightToLeft
DButton {
text: root.saving ? I18n.tr("Saving...") : I18n.tr("Save")
iconName: "check"
enabled: !root.saving
onClicked: root.save()
}
DButton {
text: I18n.tr("Cancel")
backgroundColor: "transparent"
textColor: Theme.primary
onClicked: root.closeRequested()
}
}
}