finish add/update event page
This commit is contained in:
@@ -228,7 +228,7 @@ class CalendarDatabase(object):
|
||||
|
||||
# get prev data
|
||||
self.cursor.execute('SELECT * FROM calendar WHERE [ccn_uuid] = ? AND [ccn_lastChange] = ?;', (uuid, lastChange))
|
||||
analyseData = self.cursor.fetchone()
|
||||
analyseData = list(self.cursor.fetchone())
|
||||
|
||||
# construct update data
|
||||
lastupdate = utils.GenerateUUID()
|
||||
|
||||
36
src/dt.py
36
src/dt.py
@@ -28,7 +28,7 @@ def ResolveLoopStr(strl, starttime, tzoffset):
|
||||
return int(cache.group(1)) # group 1 is datetime
|
||||
cache = precompiledLoopStopRules['times'].search(loopStopRules)
|
||||
if cache is not None:
|
||||
loopTimes = cache # for follwing calc
|
||||
loopTimes = int(cache.group(1)) # for follwing calc
|
||||
else:
|
||||
raise Exception('Invalid loopStopRules') # invalid rules
|
||||
|
||||
@@ -41,7 +41,7 @@ def ResolveLoopStr(strl, starttime, tzoffset):
|
||||
|
||||
|
||||
def LoopHandle_Year(searchResult, starttime, times, tzoffset):
|
||||
clientDate = datetime.datetime.fromtimestamp(starttime, UTCTimezone(tzoffset))
|
||||
clientDate = datetime.datetime.fromtimestamp(starttime * 60, UTCTimezone(tzoffset))
|
||||
isStrict = searchResult.group(1) == 'S'
|
||||
yearSpan = int(searchResult.group(2))
|
||||
|
||||
@@ -77,13 +77,14 @@ def LoopHandle_Month(searchResult, starttime, times, tzoffset):
|
||||
|
||||
# we should get original data in each method
|
||||
times -= 1
|
||||
clientDate = datetime.datetime.fromtimestamp(starttime, UTCTimezone(tzoffset))
|
||||
clientDate = datetime.datetime.fromtimestamp(starttime * 60, UTCTimezone(tzoffset))
|
||||
newYear = clientYear = clientDate.year
|
||||
newMonth = clientMonth = clientDate.month
|
||||
newDay = clientDay = clientDate.day
|
||||
# data struct
|
||||
# dayStatistics =
|
||||
# (dayForwards, dayBackwards, weeksForward, dayOfWeekForward, weeksBackwards, dayOfWeekBackward)
|
||||
# (dayForwards || dayBackwards || weeksForward, dayOfWeek || weeksBackwards, dayOfWeek)
|
||||
# ( A || B || C || D )
|
||||
dayStatistics = GetDayInMonth(clientYear, clientMonth, clientDay)
|
||||
|
||||
if isStrict:
|
||||
@@ -139,13 +140,16 @@ def LoopHandle_Week(searchResult, starttime, times, tzoffset):
|
||||
raise Exception('Invalid week format')
|
||||
|
||||
weekSpan = int(searchResult.group(2))
|
||||
nowDayOfWeek = datetime.datetime.fromtimestamp(starttime, UTCTimezone(tzoffset)).weekday()
|
||||
nowDayOfWeek = datetime.datetime.fromtimestamp(starttime * 60, UTCTimezone(tzoffset)).weekday()
|
||||
if not weekOccupied[nowDayOfWeek]:
|
||||
times+=1 # if first event is not suit for week loop rules, add one more event to suit it.
|
||||
fullWeek = times / weekEventCount
|
||||
times-=1 # if first event is not suit for week loop rules, minus one more event to suit it.
|
||||
fullWeek = int(times / weekEventCount)
|
||||
remainEvent = times % weekEventCount
|
||||
print(fullWeek)
|
||||
print(remainEvent)
|
||||
print(nowDayOfWeek)
|
||||
|
||||
val = DAY7_SPAN * fullWeek * weekSpan
|
||||
val = starttime + DAY7_SPAN * fullWeek * weekSpan
|
||||
if val > MAX_TIMESTAMP:
|
||||
return MAX_TIMESTAMP # return now, to reduce calc usage
|
||||
|
||||
@@ -231,21 +235,15 @@ def DayOfWeek(year, month, day):
|
||||
def GetDayInMonth(year, month, day):
|
||||
days = MonthDayCount[month - 1] + (1 if (month == 2 and IsLeapYear(year)) else 0)
|
||||
firstDayOfWeek = DayOfWeek(year, month, 1)
|
||||
lastDayOfWeek = (firstDayOfWeek + days - 1) % 7
|
||||
dayOfWeek = (firstDayOfWeek + day - 1) % 7
|
||||
|
||||
dayForwards = day
|
||||
dayBackwards = days - day + 1
|
||||
|
||||
weeksForward = (dayForwards - 1) / 7
|
||||
weeksBackwards = (dayBackwards - 1) / 7
|
||||
weeksForward = int((dayForwards - 1) / 7) + 1
|
||||
weeksBackwards = int((dayBackwards - 1) / 7) + 1
|
||||
|
||||
dayOfWeekForward = (firstDayOfWeek + ((dayForwards - 1) % 7)) % 7
|
||||
# 7 don't change week
|
||||
# # just keep this is the positive number and prevent pretential minus number calc problem
|
||||
dayOfWeekBackward = (7 + lastDayOfWeek - ((dayBackwards - 1) % 7)) % 7
|
||||
|
||||
return (dayForwards, dayBackwards, weeksForward, dayOfWeekForward, weeksBackwards, dayOfWeekBackward)
|
||||
return (dayForwards, dayBackwards, weeksForward, dayOfWeek, weeksBackwards, dayOfWeek)
|
||||
|
||||
def GetMonthWeekStatistics(year, month):
|
||||
days = MonthDayCount[month - 1] + (1 if (month == 2 and IsLeapYear(year)) else 0)
|
||||
@@ -253,7 +251,7 @@ def GetMonthWeekStatistics(year, month):
|
||||
lastDayOfWeek = (firstDayOfWeek + days - 1) % 7
|
||||
|
||||
result = [4, 4, 4, 4, 4, 4, 4]
|
||||
remain = (days - 1) % 7
|
||||
remain = days % 7
|
||||
week = firstDayOfWeek
|
||||
while remain > 0:
|
||||
result[week % 7] += 1
|
||||
@@ -273,4 +271,4 @@ class UTCTimezone(datetime.tzinfo):
|
||||
return 'UTC {}'.format(self._offset)
|
||||
|
||||
def dst(self, dt):
|
||||
return timedelta(0)
|
||||
return datetime.timedelta(0)
|
||||
@@ -173,8 +173,7 @@ def api_calendar_addHandle():
|
||||
('eventDateTimeStart', int, False),
|
||||
('eventDateTimeEnd', int, False),
|
||||
('loopRules', str, False),
|
||||
('timezoneOffset', int, False),
|
||||
('lastChange', str, False)))
|
||||
('timezoneOffset', int, False)))
|
||||
|
||||
@app.route('/api/calendar/delete', methods=['POST'])
|
||||
def api_calendar_deleteHandle():
|
||||
|
||||
@@ -27,18 +27,18 @@ ccn-i18n-universal-week-4=Thursday
|
||||
ccn-i18n-universal-week-5=Friday
|
||||
ccn-i18n-universal-week-6=Saturday
|
||||
ccn-i18n-universal-week-7=Sunday
|
||||
ccn-i18n-universal-month-1=1月
|
||||
ccn-i18n-universal-month-2=2月
|
||||
ccn-i18n-universal-month-3=3月
|
||||
ccn-i18n-universal-month-4=4月
|
||||
ccn-i18n-universal-month-5=5月
|
||||
ccn-i18n-universal-month-6=6月
|
||||
ccn-i18n-universal-month-7=7月
|
||||
ccn-i18n-universal-month-8=8月
|
||||
ccn-i18n-universal-month-9=9月
|
||||
ccn-i18n-universal-month-10=10月
|
||||
ccn-i18n-universal-month-11=11月
|
||||
ccn-i18n-universal-month-12=12月
|
||||
ccn-i18n-universal-month-1=January
|
||||
ccn-i18n-universal-month-2=February
|
||||
ccn-i18n-universal-month-3=March
|
||||
ccn-i18n-universal-month-4=April
|
||||
ccn-i18n-universal-month-5=May
|
||||
ccn-i18n-universal-month-6=June
|
||||
ccn-i18n-universal-month-7=July
|
||||
ccn-i18n-universal-month-8=August
|
||||
ccn-i18n-universal-month-9=September
|
||||
ccn-i18n-universal-month-10=October
|
||||
ccn-i18n-universal-month-11=November
|
||||
ccn-i18n-universal-month-12=December
|
||||
|
||||
ccn-i18n-messagebox-confirm=OK
|
||||
ccn-i18n-messagebox-title=Notification
|
||||
@@ -50,6 +50,7 @@ ccn-i18n-js-fail-add=An add operation failed. It may caused by wrong arguments.
|
||||
ccn-i18n-js-fail-update=An update operation failed. It may caused by wrong arguments or lost target. Refreshing page may fix system problem. Before refreshing page, please backup all your unsaved data.
|
||||
ccn-i18n-js-fail-delete=A delete operation failed. It may caused by no matched item. Refreshing page may fix system problem. Before refreshing page, please backup all your unsaved data.
|
||||
ccn-i18n-js-success=Operation OK.
|
||||
ccn-i18n-js-fail-form=Your filled event form is not fufilled or have error. Please check it and try again.
|
||||
|
||||
ccn-i18n-home-desc=<h1 class="title">coconut-leaf</h1><p>A light, self-host calendar system.</p><p>Originally, this app is served for yyc12345 personal use.</p><br /><p>Pull request / issue / translation are welcomed.</p><p>Submit them in our <a href="https://github.com/yyc12345/coconut-leaf">GitHub project</a>.</p><p>This project source code is licensed <a href="https://www.gnu.org/licenses/agpl-3.0.html">AGPL v3</a>.</p>
|
||||
|
||||
@@ -88,15 +89,15 @@ ccn-i18n-event-loopMonth-span=Month span
|
||||
ccn-i18n-event-loopWeek-option=Month mode
|
||||
ccn-i18n-event-loopWeek-optionA=Day {0} in month
|
||||
ccn-i18n-event-loopWeek-optionB=Day {0} from the end of the month
|
||||
ccn-i18n-event-loopWeek-optionC=Week {0}, day {1} in month
|
||||
ccn-i18n-event-loopWeek-optionD=Week {0}, day {1} from the end of the month
|
||||
ccn-i18n-event-loopWeek-optionC=Day {1} in week {0}
|
||||
ccn-i18n-event-loopWeek-optionD=Day {1} in week {0} from the end of the month
|
||||
ccn-i18n-event-loopYear-span=Year span
|
||||
ccn-i18n-event-loopStop=Event Loop Stop
|
||||
ccn-i18n-event-loopStop-forever=Forever
|
||||
ccn-i18n-event-loopStop-datetime=Date Time
|
||||
ccn-i18n-event-loopStop-times=Times
|
||||
ccn-i18n-event-timezone-title=Timezone
|
||||
ccn-i18n-event-timezone-warning=The timezone of this event is not corresponding with your current timezone. You can choose a timezone option in follwing content. If you are not familar with this, please pick keep timezone.
|
||||
ccn-i18n-event-timezone-warning=The timezone of this event is not corresponding with your current timezone. All of date and time in this page are shown as the original timezone of this event. You can choose a timezone option in follwing content. If you are not familar with this, please pick keep timezone.
|
||||
ccn-i18n-event-timezone-keep=Keep timezone
|
||||
ccn-i18n-event-timezone-replace=Use my timezone
|
||||
ccn-i18n-event-strictMode-title=Strict Mode in Event Loop
|
||||
|
||||
@@ -50,6 +50,7 @@ ccn-i18n-js-fail-add=一个添加操作失败了,可能是您输入的参数
|
||||
ccn-i18n-js-fail-update=一个更新操作失败了,可能是没有找到匹配的条目或者您的参数输入错误。刷新页面可能会解决问题。请在刷新页面前备份好自己的数据。
|
||||
ccn-i18n-js-fail-delete=一个删除操作失败了,可能是没有找到对应条目。刷新页面可能会解决问题。请在刷新页面前备份好自己的数据。
|
||||
ccn-i18n-js-success=操作成功
|
||||
ccn-i18n-js-fail-form=您所填写的事件内容存在缺漏或有错误字段,请检查后再提交。
|
||||
|
||||
ccn-i18n-home-desc=<h1 class="title">coconut-leaf</h1><p>一个轻量的自建日历系统</p><p>原本是出于yyc12345的个人使用而制作的。</p><br /><p>欢迎提出Pull request / issue / 翻译</p><p>将他们提交到我们的<a href="https://github.com/yyc12345/coconut-leaf">GitHub项目</a>.</p><p>本工程代码使用<a href="https://www.gnu.org/licenses/agpl-3.0.html">AGPL v3</a>授权。</p>
|
||||
|
||||
@@ -94,15 +95,15 @@ ccn-i18n-event-loopMonth-span=间隔月数
|
||||
ccn-i18n-event-loopWeek-option=月份模式
|
||||
ccn-i18n-event-loopWeek-optionA=第{0}天
|
||||
ccn-i18n-event-loopWeek-optionB=倒数第{0}天
|
||||
ccn-i18n-event-loopWeek-optionC=第{0}个星期第{1}天
|
||||
ccn-i18n-event-loopWeek-optionD=倒数第{0}个星期第{1}天
|
||||
ccn-i18n-event-loopWeek-optionC=第{0}个星期{1}
|
||||
ccn-i18n-event-loopWeek-optionD=倒数第{0}个星期{1}
|
||||
ccn-i18n-event-loopYear-span=间隔年数
|
||||
ccn-i18n-event-loopStop=事件循环停止方式
|
||||
ccn-i18n-event-loopStop-forever=永不停止
|
||||
ccn-i18n-event-loopStop-datetime=指定时间
|
||||
ccn-i18n-event-loopStop-times=指定次数
|
||||
ccn-i18n-event-timezone-title=时区设定
|
||||
ccn-i18n-event-timezone-warning=您当前设置的事件的时区与您的时区不匹配,您可以在下面修改您对于此事件的时区选择,如果您不熟悉时区,请选择保持原有时区。
|
||||
ccn-i18n-event-timezone-warning=您当前设置的事件的时区与您的时区不匹配,本页面以事件的原时区进行时间显示。您可以在下面修改您对于此事件的时区选择,如果您不熟悉时区,请选择保持原有时区。
|
||||
ccn-i18n-event-timezone-keep=保持原有时区
|
||||
ccn-i18n-event-timezone-replace=使用我现在的时区
|
||||
ccn-i18n-event-strictMode-title=循环的严格与宽松
|
||||
|
||||
@@ -200,20 +200,28 @@ function ccn_api_calendar_getDetail(_uuid) {
|
||||
}
|
||||
|
||||
function ccn_api_calendar_update(_uuid, _belongTo, _title, _description, _eventDateTimeStart, _eventDateTimeEnd, _loopRules, _timezoneOffset, _lastChange) {
|
||||
var data = {};
|
||||
if (typeof(_belongTo) != 'undefined')
|
||||
data.belongTo = _belongTo;
|
||||
if (typeof(_title) != 'undefined')
|
||||
data.title = _title;
|
||||
if (typeof(_description) != 'undefined')
|
||||
data.description = _description;
|
||||
if (typeof(_eventDateTimeStart) != 'undefined')
|
||||
data.eventDateTimeStart = _eventDateTimeStart;
|
||||
if (typeof(_eventDateTimeEnd) != 'undefined')
|
||||
data.eventDateTimeEnd = _eventDateTimeEnd;
|
||||
if (typeof(_loopRules) != 'undefined')
|
||||
data.loopRules = _loopRules;
|
||||
if (typeof(_timezoneOffset) != 'undefined')
|
||||
data.timezoneOffset = _timezoneOffset;
|
||||
|
||||
data.token = GetApiToken();
|
||||
data.uuid = _uuid;
|
||||
data.lastChange = _lastChange;
|
||||
return ccn_api_dataTemplate(
|
||||
'/api/calendar/update',
|
||||
{
|
||||
token: GetApiToken(),
|
||||
uuid: _uuid,
|
||||
belongTo: _belongTo,
|
||||
title: _title,
|
||||
description: _description,
|
||||
eventDateTimeStart: _eventDateTimeStart,
|
||||
eventDateTimeEnd: _eventDateTimeEnd,
|
||||
loopRules: _loopRules,
|
||||
timezoneOffset: _timezoneOffset,
|
||||
lastChange: _lastChange
|
||||
}
|
||||
data
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// NOTE: this file is sync with dt.py. if this file or dt.py have bugs, all code should be changed
|
||||
ccn_datetime_monthDayCount = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
||||
|
||||
ccn_datetime_MIN_YEAR = 1950;
|
||||
@@ -47,15 +48,16 @@ function ccn_datetime_ResolveLoopRules4UI(strl) {
|
||||
var loopStopRules = undefined;
|
||||
|
||||
if (ccn_datetime_precompiledLoopRules.year.test(sp[0])) {
|
||||
loopRules = [1, RegExp.$1 == 'S', parseInt(RegExp.$2)];
|
||||
loopRules = [0, RegExp.$1 == 'S', parseInt(RegExp.$2)];
|
||||
} else if (ccn_datetime_precompiledLoopRules.month.test(sp[0])) {
|
||||
loopRules = [2, RegExp.$1 == 'S', RegExp.$2, parseInt(RedExp.$3)];
|
||||
loopRules = [1, RegExp.$1 == 'S', RegExp.$2, parseInt(RedExp.$3)];
|
||||
} else if (ccn_datetime_precompiledLoopRules.week.test(sp[0])) {
|
||||
loopRules = [3];
|
||||
for (index in RegExp.$1) loopRules.push(RegExp.$1[index] == 'T');
|
||||
loopRules = [2];
|
||||
for (var i = 0; i < 7; i++)
|
||||
loopRules.push(RegExp.$1[i] == 'T');
|
||||
loopRules.push(parseInt(RegExp.$2));
|
||||
} else if (ccn_datetime_precompiledLoopRules.day.test(sp[0])) {
|
||||
loopRules = [4, parseInt(RegExp.$1)];
|
||||
loopRules = [3, parseInt(RegExp.$1)];
|
||||
} else return undefined;
|
||||
|
||||
|
||||
@@ -74,6 +76,71 @@ function ccn_datetime_ResolveLoopRules4Event(strl) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function ccn_datetime_LeapYearCountEx(endYear, includeThis, baseYear, includeBase) {
|
||||
if (!includeThis) endYear--;
|
||||
if (includeBase) baseYear--;
|
||||
|
||||
var endly = Math.floor(endYear / 4);
|
||||
endly -= Math.floor(endYear / 100);
|
||||
endly += Math.floor(endYear / 400);
|
||||
|
||||
var basely = Math.floor(baseYear / 4);
|
||||
basely -= Math.floor(baseYear / 100);
|
||||
basely += Math.floor(baseYear / 400);
|
||||
|
||||
return (endly - basely);
|
||||
}
|
||||
|
||||
function ccn_datetime_DaysCount(year, month, day) {
|
||||
var ly = ccn_datetime_LeapYearCountEx(year, false, 1, true);
|
||||
var days = 365 * (year - 1);
|
||||
days += ly;
|
||||
|
||||
for(var index = 1; index < month; index++)
|
||||
days += ccn_datetime_monthDayCount[index - 1];
|
||||
|
||||
if (month > 2 && ccn_datetime_IsLeapYear(year))
|
||||
days += 1;
|
||||
|
||||
days += day - 1;
|
||||
return days;
|
||||
}
|
||||
|
||||
function ccn_datetime_DayOfWeek(year, month, day) {
|
||||
return ccn_datetime_DaysCount(year, month, day) % 7;
|
||||
}
|
||||
|
||||
function ccn_datetime_GetDayInMonth(year, month, day) {
|
||||
var days = ccn_datetime_monthDayCount[month - 1] + ((month == '2' && ccn_datetime_IsLeapYear(year)) ? 1 : 0);
|
||||
var firstDayOfWeek = ccn_datetime_DayOfWeek(year, month, 1);
|
||||
var dayOfWeek = (firstDayOfWeek + day - 1) % 7;
|
||||
|
||||
var dayForwards = day;
|
||||
var dayBackwards = days - day + 1;
|
||||
|
||||
var weeksForward = Math.floor((dayForwards - 1) / 7) + 1;
|
||||
var weeksBackwards = Math.floor((dayBackwards - 1) / 7) + 1;
|
||||
|
||||
return [dayForwards, dayBackwards, weeksForward, dayOfWeek, weeksBackwards, dayOfWeek];
|
||||
}
|
||||
|
||||
function ccn_datetime_GetMonthWeekStatistics(year, month) {
|
||||
var days = ccn_datetime_monthDayCount[month - 1] + ((month == '2' && ccn_datetime_IsLeapYear(year)) ? 1 : 0);
|
||||
var firstDayOfWeek = ccn_datetime_DayOfWeek(year, month, 1);
|
||||
var lastDayOfWeek = (firstDayOfWeek + days - 1) % 7;
|
||||
|
||||
var result = [4, 4, 4, 4, 4, 4, 4];
|
||||
var remain = days % 7;
|
||||
var week = firstDayOfWeek;
|
||||
while (remain > 0) {
|
||||
result[week % 7] += 1;
|
||||
week++;
|
||||
remain--;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function ccn_datetime_IsLeapYear(year) {
|
||||
var isLeap = false;
|
||||
if (year % 4 == 0) isLeap = true;
|
||||
|
||||
@@ -50,15 +50,15 @@ function ccn_datetimepicker_SyncEx(pickerIndex) {
|
||||
}
|
||||
}
|
||||
|
||||
function ccn_datetimepicker_Set(pickerIndex, dt) {
|
||||
$('.datetimepicker-year[datetimepicker=' + pickerIndex + ']').val(dt.getFullYear());
|
||||
$('.datetimepicker-month[datetimepicker=' + pickerIndex + ']').val(dt.getMonth() + 1);
|
||||
$('.datetimepicker-day[datetimepicker=' + pickerIndex + ']').val(dt.getDate());
|
||||
$('.datetimepicker-hour[datetimepicker=' + pickerIndex + ']').val(dt.getHours());
|
||||
$('.datetimepicker-minute[datetimepicker=' + pickerIndex + ']').val(dt.getMinutes());
|
||||
function ccn_datetimepicker_Set(pickerIndex, dt, isUTC) {
|
||||
$('.datetimepicker-year[datetimepicker=' + pickerIndex + ']').val(isUTC ? dt.getUTCFullYear() : dt.getFullYear());
|
||||
$('.datetimepicker-month[datetimepicker=' + pickerIndex + ']').val((isUTC ? dt.getUTCMonth() : dt.getMonth()) + 1);
|
||||
$('.datetimepicker-day[datetimepicker=' + pickerIndex + ']').val(isUTC ? dt.getUTCDate() : dt.getDate());
|
||||
$('.datetimepicker-hour[datetimepicker=' + pickerIndex + ']').val(isUTC ? dt.getUTCHours() : dt.getHours());
|
||||
$('.datetimepicker-minute[datetimepicker=' + pickerIndex + ']').val(isUTC ? dt.getUTCMinutes() : dt.getMinutes());
|
||||
}
|
||||
|
||||
function ccn_datetimepicker_Get(pickerIndex) {
|
||||
function ccn_datetimepicker_Get(pickerIndex, isUTC) {
|
||||
year = $('.datetimepicker-year[datetimepicker=' + pickerIndex + ']').val();
|
||||
month = $('.datetimepicker-month[datetimepicker=' + pickerIndex + ']').val();
|
||||
day = $('.datetimepicker-day[datetimepicker=' + pickerIndex + ']').val();
|
||||
@@ -70,5 +70,6 @@ function ccn_datetimepicker_Get(pickerIndex) {
|
||||
if (IsUndefinedOrEmpty(hour)) hour = 0;
|
||||
if (IsUndefinedOrEmpty(minute)) minute = 0;
|
||||
|
||||
return new Date(year, parseInt(month) - 1, day, hour, minute, 0, 0);
|
||||
if (isUTC) return new Date(Date.UTC(year, parseInt(month) - 1, day, hour, minute, 0, 0));
|
||||
else return new Date(year, parseInt(month) - 1, day, hour, minute, 0, 0);
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ function ccn_calendar_calendar_LoadCalendarBody() {
|
||||
}
|
||||
|
||||
function ccn_calendar_calendar_Refresh() {
|
||||
gottenDateTime = ccn_datetimepicker_Get(1);
|
||||
gottenDateTime = ccn_datetimepicker_Get(1, false);
|
||||
gottenYear = gottenDateTime.getFullYear();
|
||||
gottenMonth = gottenDateTime.getMonth() + 1;
|
||||
}
|
||||
@@ -81,7 +81,7 @@ function ccn_calendar_calendar_AnalyseEvent() {
|
||||
|
||||
function ccn_calendar_calendar_Today() {
|
||||
var nowtime = new Date();
|
||||
ccn_datetimepicker_Set(1, nowtime);
|
||||
ccn_datetimepicker_Set(1, nowtime, false);
|
||||
ccn_calendar_calendar_Refresh();
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,15 @@ $(document).ready(function() {
|
||||
// bind event
|
||||
$('input[type=radio][name=loop-method]').click(ccn_event_RefreshRadioDiaplay);
|
||||
$('input[type=radio][name=loop-end]').click(ccn_event_RefreshRadioDiaplay);
|
||||
$('.datetimepicker-year[datetimepicker=1],.datetimepicker-month[datetimepicker=1],.datetimepicker-day[datetimepicker=1]').bind(
|
||||
'input propertychange',
|
||||
ccn_event_RefreshLoopMonthType
|
||||
);
|
||||
|
||||
$('#ccn-event-btnSubmit').click(ccn_event_btnSubmit);
|
||||
$('#ccn-event-btnCancel').click(ccn_event_btnCancel);
|
||||
$('#ccn-event-btnSpot').click(ccn_event_btnSpot);
|
||||
$('#ccn-event-btnFullDay').click(ccn_event_btnFullDay);
|
||||
|
||||
// init form
|
||||
ccn_event_Init();
|
||||
@@ -91,7 +100,7 @@ function ccn_event_Init() {
|
||||
}
|
||||
// in add mode, set as -1, otherwise try to match original data
|
||||
// indexOf will return -1 if no matched item
|
||||
collectionDOM.val(isAdd ? '' : ccn_calendar_eventModal_editing[1]);
|
||||
collectionDOM.val(isAdd ? '' : ccn_event_editingEvent[1]);
|
||||
|
||||
// init start and end datetime
|
||||
if (isAdd) {
|
||||
@@ -100,18 +109,18 @@ function ccn_event_Init() {
|
||||
currentDateTime.setMilliseconds(0);
|
||||
currentDateTime.setSeconds(0);
|
||||
currentDateTime.setMinutes(0);
|
||||
ccn_datetimepicker_Set(1, currentDateTime);
|
||||
ccn_datetimepicker_Set(1, currentDateTime, false);
|
||||
|
||||
// time span is 2 hours
|
||||
currentDateTime.setHours(currentDateTime.getHours() + 2);
|
||||
ccn_datetimepicker_Set(2, currentDateTime);
|
||||
ccn_datetimepicker_Set(2, currentDateTime, false);
|
||||
} else {
|
||||
// in update mode, match it with original data
|
||||
var originalDateTime = new Date(ccn_event_editingEvent[5] * 60000);
|
||||
ccn_datetimepicker_Set(1, originalDateTime);
|
||||
var originalDateTime = new Date((ccn_event_editingEvent[5] + ccn_event_editingEvent[7]) * 60000);
|
||||
ccn_datetimepicker_Set(1, originalDateTime, true);
|
||||
|
||||
originalDateTime = new Date(ccn_event_editingEvent[6] * 60000);
|
||||
ccn_datetimepicker_Set(2, originalDateTime);
|
||||
originalDateTime = new Date((ccn_event_editingEvent[6] + ccn_event_editingEvent[7]) * 60000);
|
||||
ccn_datetimepicker_Set(2, originalDateTime, true);
|
||||
}
|
||||
|
||||
// setup timezone here
|
||||
@@ -120,7 +129,7 @@ function ccn_event_Init() {
|
||||
$('#ccn-event-timezone-radioKeep').prop('checked', true); // give a default value
|
||||
var nowtime = new Date();
|
||||
SmarterShowHide(
|
||||
(!isAdd) && nowtime.getTimezoneOffset() != ccn_event_editingEvent[7],
|
||||
(!isAdd) && (-nowtime.getTimezoneOffset()) != ccn_event_editingEvent[7],
|
||||
$('#ccn-event-boxTimezone')
|
||||
);
|
||||
|
||||
@@ -133,23 +142,26 @@ function ccn_event_Init() {
|
||||
|
||||
// give some value with a default value
|
||||
$('#ccn-event-loopMonth-radioA').prop('checked', true);
|
||||
var weekDate = undefined;
|
||||
if (isAdd) weekDate = nowtime;
|
||||
else weekDate = new Date(ccn_event_editingEvent[5] * 60000);
|
||||
$('#ccn-event-loopWeek-check' + (weekDate.getDay() + 1)).prop('checked', true);
|
||||
$('#ccn-event-loopWeek-check' + (nowtime.getWeekday() + 1)).prop('checked', true);
|
||||
$('#ccn-event-strictMode-radioStrict').prop('checked', true);
|
||||
|
||||
// real process
|
||||
if (isAdd) $('#ccn-event-radioLoopNever').prop('checked', true);
|
||||
else {
|
||||
if (isAdd) {
|
||||
$('#ccn-event-radioLoopNever').prop('checked', true);
|
||||
} else {
|
||||
switch(data[0][0]) {
|
||||
case 0:
|
||||
$('#ccn-event-radioLoopYear').prop('checked', true);
|
||||
$('#ccn-event-loopYear-inputSpan').val(data[0][2]);
|
||||
if (data[0][1]) $('#ccn-event-strictMode-radioStrict').prop('checked', true);
|
||||
else $('#ccn-event-strictMode-radioRough').prop('checked', true);
|
||||
break;
|
||||
case 1:
|
||||
$('#ccn-event-radioLoopMonth').prop('checked', true);
|
||||
$('#ccn-event-loopMonth-inputSpan').val(data[0][3]);
|
||||
$('#ccn-event-loopMonth-radio' + data[0][2]).prop('checked', true);
|
||||
if (data[0][1]) $('#ccn-event-strictMode-radioStrict').prop('checked', true);
|
||||
else $('#ccn-event-strictMode-radioRough').prop('checked', true);
|
||||
break;
|
||||
case 2:
|
||||
$('#ccn-event-radioLoopWeek').prop('checked', true);
|
||||
@@ -165,9 +177,11 @@ function ccn_event_Init() {
|
||||
}
|
||||
}
|
||||
|
||||
// give some item a default value
|
||||
ccn_datetimepicker_Set(3, nowtime, false);
|
||||
|
||||
if (isAdd) {
|
||||
$('#ccn-event-loopStop-radioForever').prop('checked', true);
|
||||
ccn_datetimepicker_Set(3, nowtime);
|
||||
} else {
|
||||
switch(data[1][0]) {
|
||||
case 0:
|
||||
@@ -175,8 +189,8 @@ function ccn_event_Init() {
|
||||
break;
|
||||
case 1:
|
||||
$('#ccn-event-loopStop-radioDateTime').prop('checked', true);
|
||||
var stopDatetime = new Date(data[1][1] * 60000);
|
||||
ccn_datetimepicker_Set(3, stopDatetime);
|
||||
var stopDatetime = new Date((data[1][1] + ccn_event_editingEvent[7]) * 60000);
|
||||
ccn_datetimepicker_Set(3, stopDatetime, true);
|
||||
break;
|
||||
case 2:
|
||||
$('#ccn-event-loopStop-radioTimes').prop('checked', true);
|
||||
@@ -212,11 +226,163 @@ function ccn_event_RefreshRadioDiaplay() {
|
||||
}
|
||||
|
||||
function ccn_event_RefreshLoopMonthType() {
|
||||
var picker = ccn_datetimepicker_Get(1, false);
|
||||
var data = ccn_datetime_GetDayInMonth(picker.getFullYear(), picker.getMonth() + 1, picker.getDate());
|
||||
|
||||
$('#ccn-event-loopMonth-textA').text($.i18n.prop('ccn-i18n-event-loopWeek-optionA').format(data[0]));
|
||||
$('#ccn-event-loopMonth-textB').text($.i18n.prop('ccn-i18n-event-loopWeek-optionB').format(data[1]));
|
||||
$('#ccn-event-loopMonth-textC').text($.i18n.prop('ccn-i18n-event-loopWeek-optionC').format(data[2], data[3] + 1));
|
||||
$('#ccn-event-loopMonth-textD').text($.i18n.prop('ccn-i18n-event-loopWeek-optionD').format(data[4], data[5] + 1));
|
||||
}
|
||||
|
||||
// return undefined to indicate an error
|
||||
function ccn_event_Get() {
|
||||
// or
|
||||
// [belongTo, title, description, eventDateTimeStart, eventDateTimeEnd, timezoneOffset, loopRules]
|
||||
function ccn_event_GetForm() {
|
||||
// basic
|
||||
var title = $('#ccn-event-inputTitle').val();
|
||||
if (title == '') return undefined;
|
||||
var description = $('#ccn-event-inputDescription').val();
|
||||
if (description == '') return undefined;
|
||||
var belongTo = $('#ccn-event-inputCollection').val();
|
||||
if (belongTo == null) return undefined; // if no selected item, val return null, not undefined
|
||||
|
||||
var isAdd = typeof(ccn_event_editingEvent) == 'undefined';
|
||||
var keepTimezone = $('#ccn-event-timezone-radioKeep').prop('checked');
|
||||
var isStrict = $('#ccn-event-strictMode-radioStrict').prop('checked');
|
||||
|
||||
// time
|
||||
var eventDateTimeStart = undefined;
|
||||
var eventDateTimeEnd = undefined;
|
||||
var timezoneOffset = undefined;
|
||||
if ((!isAdd) && (!keepTimezone)) {
|
||||
// get datetime as utc, then minus original timezone to get unix timestamp
|
||||
timezoneOffset = ccn_event_editingEvent[7]; // keep timezone
|
||||
eventDateTimeStart = Math.floor(ccn_datetimepicker_Get(1, true).getTime() / 60000) - timezoneOffset;
|
||||
eventDateTimeEnd = Math.floor(ccn_datetimepicker_Get(2, true).getTime() / 60000) - timezoneOffset;
|
||||
} else {
|
||||
// use my timezone, resolve presented data as my local time
|
||||
var cache = ccn_datetimepicker_Get(1, false);
|
||||
timezoneOffset = -cache.getTimezoneOffset();
|
||||
eventDateTimeStart = Math.floor(cache.getTime() / 60000);
|
||||
eventDateTimeEnd = Math.floor(ccn_datetimepicker_Get(2, false).getTime() / 60000);
|
||||
}
|
||||
|
||||
// loopRules
|
||||
var loopRules = undefined;
|
||||
if ($('#ccn-event-radioLoopNever').prop('checked')) {
|
||||
loopRules = "";
|
||||
} else if ($('#ccn-event-radioLoopDay').prop('checked')) {
|
||||
loopRules = "D{0}".format($('#ccn-event-loopDay-inputSpan').val());
|
||||
} else if ($('#ccn-event-radioLoopWeek').prop('checked')) {
|
||||
var cache = ""
|
||||
for(var i = 1; i < 8; i++)
|
||||
cache += $('#ccn-event-loopWeek-check' + i).prop('checked') ? 'T' : 'F';
|
||||
loopRules = 'W{0}{1}'.format(
|
||||
cache,
|
||||
$('#ccn-event-loopWeek-inputSpan').val()
|
||||
);
|
||||
} else if ($('#ccn-event-radioLoopMonth').prop('checked')) {
|
||||
var cache = undefined;
|
||||
if ($('#ccn-event-loopMonth-radioA').prop('checked')) cache='A';
|
||||
else if ($('#ccn-event-loopMonth-radioB').prop('checked')) cache='B';
|
||||
else if ($('#ccn-event-loopMonth-radioC').prop('checked')) cache='C';
|
||||
else if ($('#ccn-event-loopMonth-radioD').prop('checked')) cache='D';
|
||||
else return undefined;
|
||||
|
||||
loopRules = "M{0}{1}{2}".format(
|
||||
isStrict ? "S" : "R",
|
||||
cache,
|
||||
$('#ccn-event-loopMonth-inputSpan').val()
|
||||
);
|
||||
} else if ($('#ccn-event-radioLoopYear').prop('checked')) {
|
||||
loopRules = "Y{0}{1}".format(
|
||||
isStrict ? "S" : "R",
|
||||
$('#ccn-event-loopDay-inputSpan').val()
|
||||
);
|
||||
}
|
||||
|
||||
// no need to process stop if this is not a loop event
|
||||
if (loopRules != "") {
|
||||
loopRules += '-';
|
||||
if ($('#ccn-event-loopStop-radioForever').prop('checked')) {
|
||||
loopRules += 'F';
|
||||
} else if ($('#ccn-event-loopStop-radioDateTime').prop('checked')) {
|
||||
var timestamp = undefined;
|
||||
if ((!isAdd) && (!keepTimezone)) {
|
||||
// keep timezone
|
||||
var cache = ccn_datetimepicker_Get(3, true);
|
||||
cache.setUTCHours(23);
|
||||
cache.setUTCMinutes(59);
|
||||
timestamp = Math.floor(cache.getTime() / 60000) - timezoneOffset;
|
||||
} else {
|
||||
// use my timezone
|
||||
timestamp = Math.floor(ccn_datetimepicker_Get(3, false).getTime() / 60000);
|
||||
}
|
||||
|
||||
loopRules += 'D{0}'.format(timestamp);
|
||||
} else if ($('#ccn-event-loopStop-radioTimes').prop('checked')) {
|
||||
loopRules += 'T{0}'.format($('#ccn-event-loopStop-inputTimes').val());
|
||||
}
|
||||
}
|
||||
|
||||
return [belongTo, title, description, eventDateTimeStart, eventDateTimeEnd, timezoneOffset, loopRules];
|
||||
}
|
||||
|
||||
function ccn_event_btnSpot() {
|
||||
var datetime = ccn_datetimepicker_Get(1, false);
|
||||
datetime.setMinutes(datetime.getMinutes() + 1);
|
||||
ccn_datetimepicker_Set(2, datetime, false);
|
||||
}
|
||||
|
||||
function ccn_event_btnFullDay() {
|
||||
var datetime = ccn_datetimepicker_Get(1, false);
|
||||
datetime.setMinutes(0);
|
||||
datetime.setHours(0);
|
||||
ccn_datetimepicker_Set(1, datetime, false);
|
||||
datetime.setMinutes(59);
|
||||
datetime.setHours(23);
|
||||
ccn_datetimepicker_Set(2, datetime, false);
|
||||
}
|
||||
|
||||
function ccn_event_btnCancel() {
|
||||
window.location.href = '/web/calendar';
|
||||
}
|
||||
|
||||
function ccn_event_btnSubmit() {
|
||||
var submitData = ccn_event_GetForm();
|
||||
if (typeof(submitData) == 'undefined') {
|
||||
ccn_messagebox_Show($.i18n.prop("ccn-i18n-js-fail-form"));
|
||||
return;
|
||||
}
|
||||
|
||||
var isAdd = typeof(ccn_event_editingEvent) == 'undefined';
|
||||
if (isAdd) {
|
||||
var result = ccn_api_calendar_add(
|
||||
submitData[0],
|
||||
submitData[1],
|
||||
submitData[2],
|
||||
submitData[3],
|
||||
submitData[4],
|
||||
submitData[6],
|
||||
submitData[5]
|
||||
);
|
||||
if (typeof(result) == 'undefined') ccn_messagebox_Show($.i18n.prop("ccn-i18n-js-fail-add"));
|
||||
else window.location.href = '/web/calendar';
|
||||
} else {
|
||||
var result = ccn_api_calendar_update(
|
||||
ccn_event_editingEvent[0],
|
||||
ccn_event_editingEvent[1] == submitData[0] ? undefined : submitData[0],
|
||||
ccn_event_editingEvent[2] == submitData[1] ? undefined : submitData[1],
|
||||
ccn_event_editingEvent[3] == submitData[2] ? undefined : submitData[2],
|
||||
ccn_event_editingEvent[5] == submitData[3] ? undefined : submitData[3],
|
||||
ccn_event_editingEvent[6] == submitData[4] ? undefined : submitData[4],
|
||||
ccn_event_editingEvent[8] == submitData[6] ? undefined : submitData[6],
|
||||
ccn_event_editingEvent[7] == submitData[5] ? undefined : submitData[5],
|
||||
ccn_event_editingEvent[4]
|
||||
);
|
||||
if (typeof(result) == 'undefined') ccn_messagebox_Show($.i18n.prop("ccn-i18n-js-fail-update"));
|
||||
else window.location.href = '/web/calendar';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ function ComputeSHA256(strl) {
|
||||
*/
|
||||
|
||||
function IsResponseOK(data) {
|
||||
if (typeof(data) == 'undefined') {
|
||||
if (typeof (data) == 'undefined') {
|
||||
console.log("Fail to execute an api!");
|
||||
return false;
|
||||
}
|
||||
@@ -38,15 +38,31 @@ function SetApiToken(value) {
|
||||
}
|
||||
|
||||
function LineBreaker2Br(strl) {
|
||||
return $('<div>').text(strl).html().replace(/\n/g,'<br />');
|
||||
return $('<div>').text(strl).html().replace(/\n/g, '<br />');
|
||||
}
|
||||
|
||||
function IsUndefinedOrEmpty(data) {
|
||||
return (typeof(data) == 'undefined' || data == "");
|
||||
return (typeof (data) == 'undefined' || data == "");
|
||||
}
|
||||
|
||||
function SmarterShowHide(boolean, element) {
|
||||
if (typeof(element) == 'undefined') return;
|
||||
if (typeof (element) == 'undefined') return;
|
||||
if (boolean) element.show();
|
||||
else element.hide();
|
||||
}
|
||||
|
||||
String.prototype.format = function() {
|
||||
var e = arguments;
|
||||
return !!this && this.replace(
|
||||
/\{(\d+)\}/g,
|
||||
function (t, n) {
|
||||
return e[n].toString() ? e[n].toString() : t;
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
Date.prototype.getWeekday = function() {
|
||||
var temp = this.getDay();
|
||||
if (temp == 0) return 6;
|
||||
else return temp - 1;
|
||||
};
|
||||
Reference in New Issue
Block a user