diff --git a/src/dt.py b/src/dt.py index d6ee2d0..6a39036 100644 --- a/src/dt.py +++ b/src/dt.py @@ -12,7 +12,6 @@ MIN_TIMESTAMP = int(MIN_DATETIME.timestamp() / 60) MAX_TIMESTAMP = int(MAX_DATETIME.timestamp() / 60) DAY1_SPAN = 60 * 24 DAY7_SPAN = 7 * DAY1_SPAN -YEAR400_SPAN = DAY1_SPAN * 400 * 365 def ResolveLoopStr(strl, starttime, tzoffset): # check no loop @@ -91,7 +90,7 @@ def LoopHandle_Month(searchResult, starttime, times, tzoffset): if loopType == 'A': while times > 0: newMonth += 1 - if newMonth > 12 + if newMonth > 12: newMonth = 1 newYear += 1 maxDays = MonthDayCount[newMonth - 1] + (1 if newMonth == 2 and IsLeapYear(newYear) else 0) @@ -100,7 +99,7 @@ def LoopHandle_Month(searchResult, starttime, times, tzoffset): elif loopType == 'B': while times > 0: newMonth += 1 - if newMonth > 12 + if newMonth > 12: newMonth = 1 newYear += 1 maxDays = MonthDayCount[newMonth - 1] + (1 if newMonth == 2 and IsLeapYear(newYear) else 0) @@ -109,7 +108,7 @@ def LoopHandle_Month(searchResult, starttime, times, tzoffset): elif loopType == 'C': while times > 0: newMonth += 1 - if newMonth > 12 + if newMonth > 12: newMonth = 1 newYear += 1 monthStatistics = GetMonthWeekStatistics(newYear, newMonth) @@ -118,7 +117,7 @@ def LoopHandle_Month(searchResult, starttime, times, tzoffset): elif loopType == 'D': while times > 0: newMonth += 1 - if newMonth > 12 + if newMonth > 12: newMonth = 1 newYear += 1 monthStatistics = GetMonthWeekStatistics(newYear, newMonth) @@ -172,8 +171,8 @@ precompiledLoopRules = ( ) precompiledLoopStopRules = { - 'infinity': re.compile(r'F') - 'datetime': re.compile(r'^D([1-9]\d*|0)$') + 'infinity': re.compile(r'F'), + 'datetime': re.compile(r'^D([1-9]\d*|0)$'), 'times': re.compile(r'^T([1-9]\d*)$') } diff --git a/src/static/css/calendar.css b/src/static/css/calendar.css index 9a09f21..8feb2ea 100644 --- a/src/static/css/calendar.css +++ b/src/static/css/calendar.css @@ -1,4 +1,4 @@ -#ccn-calendar-calendarBbody div:nth-child(n+2) div { +#ccn-calendar-calendarBody div:nth-child(n+2) div { border-top: 0 solid black; border-left: 0 solid black; border-right: 1px solid black; @@ -13,15 +13,15 @@ overflow: hidden; } -#ccn-calendar-calendarBbody div:nth-child(n+2) div:nth-child(1) { +#ccn-calendar-calendarBody div:nth-child(n+2) div:nth-child(1) { border-left: 1px solid black; } -#ccn-calendar-calendarBbody div:nth-child(2) div { +#ccn-calendar-calendarBody div:nth-child(2) div { border-top: 1px solid black; } -#ccn-calendar-calendarBbody div div { +#ccn-calendar-calendarBody div div { flex-grow: 1; flex-basis: 0; flex-shrink: 0; @@ -29,7 +29,7 @@ overflow: hidden; } -#ccn-calendar-calendarBbody div { +#ccn-calendar-calendarBody div { display: flex; flex-flow: row; } @@ -78,7 +78,7 @@ div.schedule-event-icon { margin-left: 0.75rem; } -#schedule-list div.schedule-day:nth-child(n+2) { +#ccn-calendar-scheduleList div.schedule-day:nth-child(n+2) { border-top: 1px solid rgba(219,219,219,.5); } @@ -121,4 +121,5 @@ div.control-list { div.control-list > * { margin-right: 0.75rem; margin-bottom: 0.75rem; + margin-left: 0 !important; } \ No newline at end of file diff --git a/src/static/i18n/strings_en-US.properties b/src/static/i18n/strings_en-US.properties index f9c3b0b..6770ca0 100644 --- a/src/static/i18n/strings_en-US.properties +++ b/src/static/i18n/strings_en-US.properties @@ -38,17 +38,60 @@ ccn-calendar-calendar-scheduleList=Schedule ccn-calendar-tabcontrol-tabCalendar=Calendar ccn-calendar-tabcontrol-tabShared=Shared ccn-calendar-tabcontrol-tabSharing=Sharing -ccn-calendar-week-monday=Monday -ccn-calendar-week-tuesday=Tuesday -ccn-calendar-week-wednesday=Wednesday -ccn-calendar-week-thursday=Thursday -ccn-calendar-week-friday=Friday -ccn-calendar-week-saturday=Saturday -ccn-calendar-week-sunday=Sunday +ccn-calendar-text-year=Year +ccn-calendar-text-month=Month +ccn-calendar-text-day=Day +ccn-calendar-text-hour=Hour +ccn-calendar-text-minute=Minute +ccn-calendar-week-1=Monday +ccn-calendar-week-2=Tuesday +ccn-calendar-week-3=Wednesday +ccn-calendar-week-4=Thursday +ccn-calendar-week-5=Friday +ccn-calendar-week-6=Saturday +ccn-calendar-week-7=Sunday +ccn-calendar-modalEvent-header=Edit Event +ccn-calendar-modalEvent-title=Title +ccn-calendar-modalEvent-description=Description +ccn-calendar-modalEvent-collection=Collection +ccn-calendar-modalEvent-startDateTime=Start Date Time +ccn-calendar-modalEvent-endDateTime=Stop Date Time +ccn-calendar-modalEvent-btnSpot=Spot +ccn-calendar-modalEvent-btnFullDay=Full day +ccn-calendar-modalEvent-loop=Event Loop +ccn-calendar-modalEvent-loop-never=Never +ccn-calendar-modalEvent-loop-day=Day +ccn-calendar-modalEvent-loop-week=Week +ccn-calendar-modalEvent-loop-month=Month +ccn-calendar-modalEvent-loop-year=Year +ccn-calendar-modalEvent-loopDay-span=Day span +ccn-calendar-modalEvent-loopWeek-span=Week span +ccn-calendar-modalEvent-loopWeek-option=Week options +ccn-calendar-modalEvent-loopMonth-span=Month span +ccn-calendar-modalEvent-loopWeek-option=Month mode +ccn-calendar-modalEvent-loopWeek-optionA=Day {0} in month +ccn-calendar-modalEvent-loopWeek-optionB=Day {0} from the end of the month +ccn-calendar-modalEvent-loopWeek-optionC=Week {0}, day {1} in month +ccn-calendar-modalEvent-loopWeek-optionD=Week {0}, day {1} from the end of the month +ccn-calendar-modalEvent-loopYear-span=Year span +ccn-calendar-modalEvent-loopStop=Event Loop Stop +ccn-calendar-modalEvent-loopStop-forever=Forever +ccn-calendar-modalEvent-loopStop-datetime=Date Time +ccn-calendar-modalEvent-loopStop-times=Times +ccn-calendar-modalEvent-timezone-title=Timezone +ccn-calendar-modalEvent-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-calendar-modalEvent-timezone-keep=Keep timezone +ccn-calendar-modalEvent-timezone-replace=Use my timezone +ccn-calendar-modalEvent-strictMode-title=Strict Mode in Event Loop +ccn-calendar-modalEvent-strictMode-warning=You can choose strict mode or rough mode in following content. This is only effect on looped event. +ccn-calendar-modalEvent-strictMode-strict=Strict Mode. If ordered day is not existing, skip it. +ccn-calendar-modalEvent-strictMode-rough=Rough mode. If ordered day is not existing, choose the day closing with original day to arrange event. +ccn-calendar-modalEvent-btnSubmit=Submit +ccn-calendar-modalEvent-btnCancel=Cancel ccn-calendar-shared-list=Shared -ccn-calendar-ownedList=Owned -ccn-calendar-sharing-sharingTargetList=Sharing target -ccn-calendar-sharing-sharingTargetEditing=Editing: +ccn-calendar-owned-list=Owned +ccn-calendar-sharing-list=Sharing target +ccn-calendar-sharing-editing=Editing: ccn-calendar-sharedItem-sharedBy=Shared by: ccn-admin-tabcontrol-tabProfile=My Profile diff --git a/src/static/i18n/strings_zh-CN.properties b/src/static/i18n/strings_zh-CN.properties index 99ba143..7a9d170 100644 --- a/src/static/i18n/strings_zh-CN.properties +++ b/src/static/i18n/strings_zh-CN.properties @@ -38,17 +38,72 @@ ccn-calendar-calendar-scheduleList=日程安排 ccn-calendar-tabcontrol-tabCalendar=日历 ccn-calendar-tabcontrol-tabShared=被共享的 ccn-calendar-tabcontrol-tabSharing=共享给其他人 -ccn-calendar-week-monday=星期一 -ccn-calendar-week-tuesday=星期二 -ccn-calendar-week-wednesday=星期三 -ccn-calendar-week-thursday=星期四 -ccn-calendar-week-friday=星期五 -ccn-calendar-week-saturday=星期六 -ccn-calendar-week-sunday=星期日 +ccn-calendar-text-year=年 +ccn-calendar-text-month=月 +ccn-calendar-text-day=日 +ccn-calendar-text-hour=时 +ccn-calendar-text-minute=分 +ccn-calendar-week-1=星期一 +ccn-calendar-week-2=星期二 +ccn-calendar-week-3=星期三 +ccn-calendar-week-4=星期四 +ccn-calendar-week-5=星期五 +ccn-calendar-week-6=星期六 +ccn-calendar-week-7=星期日 +ccn-calendar-month-1=1月 +ccn-calendar-month-2=2月 +ccn-calendar-month-3=3月 +ccn-calendar-month-4=4月 +ccn-calendar-month-5=5月 +ccn-calendar-month-6=6月 +ccn-calendar-month-7=7月 +ccn-calendar-month-8=8月 +ccn-calendar-month-9=9月 +ccn-calendar-month-10=10月 +ccn-calendar-month-11=11月 +ccn-calendar-month-12=12月 +ccn-calendar-modalEvent-header=编辑事件 +ccn-calendar-modalEvent-title=标题 +ccn-calendar-modalEvent-description=描述 +ccn-calendar-modalEvent-collection=集合 +ccn-calendar-modalEvent-startDateTime=开始时间 +ccn-calendar-modalEvent-endDateTime=结束时间 +ccn-calendar-modalEvent-btnSpot=时间点 +ccn-calendar-modalEvent-btnFullDay=全天 +ccn-calendar-modalEvent-loop=事件循环 +ccn-calendar-modalEvent-loop-never=从不 +ccn-calendar-modalEvent-loop-day=按天 +ccn-calendar-modalEvent-loop-week=按周 +ccn-calendar-modalEvent-loop-month=按月 +ccn-calendar-modalEvent-loop-year=按年 +ccn-calendar-modalEvent-loopDay-span=间隔天数 +ccn-calendar-modalEvent-loopWeek-span=间隔周数 +ccn-calendar-modalEvent-loopWeek-option=在下列这些星期上循环 +ccn-calendar-modalEvent-loopMonth-span=间隔月数 +ccn-calendar-modalEvent-loopWeek-option=月份模式 +ccn-calendar-modalEvent-loopWeek-optionA=第{0}天 +ccn-calendar-modalEvent-loopWeek-optionB=倒数第{0}天 +ccn-calendar-modalEvent-loopWeek-optionC=第{0}个星期第{1}天 +ccn-calendar-modalEvent-loopWeek-optionD=倒数第{0}个星期第{1}天 +ccn-calendar-modalEvent-loopYear-span=间隔年数 +ccn-calendar-modalEvent-loopStop=事件循环停止方式 +ccn-calendar-modalEvent-loopStop-forever=永不停止 +ccn-calendar-modalEvent-loopStop-datetime=指定时间 +ccn-calendar-modalEvent-loopStop-times=指定次数 +ccn-calendar-modalEvent-timezone-title=时区设定 +ccn-calendar-modalEvent-timezone-warning=您当前设置的事件的时区与您的时区不匹配,您可以在下面修改您对于此事件的时区选择,如果您不熟悉时区,请选择保持原有时区。 +ccn-calendar-modalEvent-timezone-keep=保持原有时区 +ccn-calendar-modalEvent-timezone-replace=使用我现在的时区 +ccn-calendar-modalEvent-strictMode-title=循环的严格与宽松 +ccn-calendar-modalEvent-strictMode-warning=允许您在严格模式与宽松模式种进行选择,此选择只对循环事件有效。 +ccn-calendar-modalEvent-strictMode-strict=严格模式,严格遵守日期要求,如果日期不存在,就不安排。 +ccn-calendar-modalEvent-strictMode-rough=宽松模式,不在意日期要求的精确性,如果日期不存在,则找到最近的符合条件的日子安排。 +ccn-calendar-modalEvent-btnSubmit=提交 +ccn-calendar-modalEvent-btnCancel=取消 ccn-calendar-shared-list=被共享的集合 -ccn-calendar-ownedList=我的集合 -ccn-calendar-sharing-sharingTargetList=分享目标 -ccn-calendar-sharing-sharingTargetEditing=正在编辑集合: +ccn-calendar-owned-list=我的集合 +ccn-calendar-sharing-list=分享目标 +ccn-calendar-sharing-editing=正在编辑集合: ccn-calendar-sharedItem-sharedBy=共享人: ccn-admin-tabcontrol-tabProfile=我的资料 diff --git a/src/static/js/datetime.js b/src/static/js/datetime.js new file mode 100644 index 0000000..58c689c --- /dev/null +++ b/src/static/js/datetime.js @@ -0,0 +1,19 @@ +ccn_datetime_monthDayCount = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; + +ccn_datetime_MIN_YEAR = 1950; +ccn_datetime_MAX_YEAR = 2199; +ccn_datetime_MIN_DATETIME = new Date(Date.UTC(1950, 1, 1, 0, 0, 0, 0)); +ccn_datetime_MAX_DATETIME = new Date(Date.UTC(2200, 1, 1, 0, 0, 0, 0)); +ccn_datetime_MIN_TIMESTAMP = Math.floor(ccn_datetime_MIN_DATETIME.getTime() / 60000); +ccn_datetime_MAX_TIMESTAMP = Math.floor(ccn_datetime_MAX_DATETIME.getTime() / 60000); + +ccn_datetime_DAY1_SPAN = 60 * 24; +ccn_datetime_DAY7_SPAN = 7 * ccn_datetime_DAY1_SPAN; + +function ccn_datetime_IsLeapYear(year) { + var isLeap = true; + if (year % 4 == 0) isLeap = true; + if (year % 100 == 0) isLeap = false; + if (year % 400 == 0) isLeap = true; + return isLeap; +} diff --git a/src/static/js/page/calendar.js b/src/static/js/page/calendar.js index 5579066..0d32d84 100644 --- a/src/static/js/page/calendar.js +++ b/src/static/js/page/calendar.js @@ -11,6 +11,13 @@ var ccn_calendar_sharing_editingOwned = undefined; // the uuid of owned collecti var ccn_calendar_sharing_displayCache = []; var ccn_calendar_shared_displayCache = []; +// modal editing object. +// undefined mean add +// not undefined mean update +var ccn_calendar_eventModal_editing = undefined; +var ccn_calendar_calendar_listCache = []; +var ccn_calendar_calendar_displayCache = []; + $(document).ready(function() { ccn_pages_currentPage = ccn_pages_enumPages.calendar; @@ -27,7 +34,7 @@ $(document).ready(function() { ccn_messagebox_BindEvent(); // process calendar it self - ccn_calendar_LoadCalendarBody(); + ccn_calendar_calendar_LoadCalendarBody(); // bind tab control switcher and set current tab $("#tabcontrol-tab-1-1").click(function(){ @@ -41,6 +48,15 @@ $(document).ready(function() { }); ccn_tabcontrol_SwitchTab(1, 1); + // init datetimepicker + ccn_calendar_datetimepicker_Init(); + + // init span picker + $('.spanpicker').attr('max', 100) + .attr('min', 1) + .attr('step', 1) + .val(1); + // apply i18n ccn_i18n_LoadLanguage(); ccn_i18n_ApplyLanguage(); @@ -52,15 +68,145 @@ $(document).ready(function() { // bind event $('#ccn-calendar-shared-btnRefresh').click(ccn_calendar_shared_Refresh); $('#ccn-calendar-owned-btnAdd').click(ccn_calendar_owned_Add); - $('#ccn-calendar-own-btnRefresh').click(ccn_calendar_owned_Refresh); + $('#ccn-calendar-owned-btnRefresh').click(ccn_calendar_owned_Refresh); $('#ccn-calendar-sharing-btnAdd').click(ccn_calendar_sharing_Add); $('#ccn-calendar-sharing-btnRefresh').click(ccn_calendar_sharing_Refresh); + + $('#ccn-calendar-calendar-btnJump').click(ccn_calendar_calendar_Refresh); + $('#ccn-calendar-calendar-btnToday').click(ccn_calendar_calendar_Today); + $('#ccn-calendar-calendar-btnAdd').click(ccn_calendar_calendar_Add); + + $('#ccn-calendar-modalEvent-btnSubmit').click(ccn_calendar_calendar_ItemUpdate); + $('#ccn-calendar-modalEvent-btnCancel').click(ccn_calendar_calendar_ItemCancel); + $('#ccn-calendar-modalEvent-btnClose').click(ccn_calendar_calendar_ItemCancel); }); +// ================== assist func + +function ccn_calendar_datetimepicker_Init() { + var nowtime = new Date(); + + $('.datetimepicker-year').attr('min', ccn_datetime_MIN_YEAR) + .attr('max', ccn_datetime_MAX_YEAR) + .attr('step', 1) + .val(nowtime.getFullYear()) + .bind('propertychange', ccn_calendar_datetimepicker_Sync); + + $('.datetimepicker-month').attr('min', 1) + .attr('max', 12) + .attr('step', 1) + .val(nowtime.getMonth() + 1) + .bind('propertychange', ccn_calendar_datetimepicker_Sync); + + $('.datetimepicker-day').attr('min', 1) + .attr('step', 1) + .each(function(){ + ccn_calendar_datetimepicker_SyncEx($(this).attr("datetimepicker")); + }) + .val(nowtime.getDate()); + + $('.datetimepicker-hour').attr('min', 0) + .attr('max', 23) + .attr('step', 1) + .val(nowtime.getHours()); + + $('.datetimepicker-minute').attr('min', 0) + .attr('max', 59) + .attr('step', 1) + .val(nowtime.getMinutes()); +} + +function ccn_calendar_datetimepicker_Sync() { + var pickerIndex = $(this).attr("datetimepicker"); + ccn_calendar_datetimepicker_SyncEx(pickerIndex); +} + +function ccn_calendar_datetimepicker_SyncEx(pickerIndex) { + year = $('.datetimepicker-year[datetimepicker=' + pickerIndex + ']').val(); + month = $('.datetimepicker-month[datetimepicker=' + pickerIndex + ']').val(); + + dayDOM = $('.datetimepicker-day[datetimepicker=' + pickerIndex + ']'); + if (typeof(year) == 'undefined' || typeof(month) == 'undefined') { + dayDOM.attr('max', 1) + .val(1); + } else { + dayDOM.attr('max', ccn_datetime_monthDayCount[month - 1] + ((month == 2 && ccn_datetime_IsLeapYear(year) ? 1 : 0))) + .val(1); + } +} + +function ccn_calendar_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_calendar_datetimepicker_Get(pickerIndex) { + year = $('.datetimepicker-year[datetimepicker=' + pickerIndex + ']').val(); + month = $('.datetimepicker-month[datetimepicker=' + pickerIndex + ']').val(); + day = $('.datetimepicker-day[datetimepicker=' + pickerIndex + ']').val(); + hour = $('.datetimepicker-hour[datetimepicker=' + pickerIndex + ']').val(); + minute = $('.datetimepicker-minute[datetimepicker=' + pickerIndex + ']').val(); + if (IsUndefinedOrEmpty(year)) year = ccn_datetime_MIN_YEAR; + if (IsUndefinedOrEmpty(month)) month = 1; + if (IsUndefinedOrEmpty(day)) day = 1; + if (IsUndefinedOrEmpty(hour)) hour = 0; + if (IsUndefinedOrEmpty(minute)) minute = 0; + + return new Date(year, month - 1, day, hour, minute, 0, 0); +} + // ================== calendar -function ccn_calendar_LoadCalendarBody() { - $('#ccn-calendar-calendarBbody').append(ccn_template_calendarItem.render()); +function ccn_calendar_calendar_LoadCalendarBody() { + $('#ccn-calendar-calendarBody').append(ccn_template_calendarItem.render()); +} + +function ccn_calendar_calendar_Refresh() { + gottenDateTime = ccn_calendar_datetimepicker_Get(4); + gottenYear = gottenDateTime.getFullYear(); + gottenMonth = gottenDateTime.getMonth() + 1; +} + +function ccn_calendar_calendar_Render() { + +} + +function ccn_calendar_calendar_AnalyseEvent() { + +} + +function ccn_calendar_calendar_Today() { + var nowtime = new Date(); + ccn_calendar_datetimepicker_Set(4, nowtime); + ccn_calendar_calendar_Refresh(); +} + +function ccn_calendar_calendar_Add() { + $('#ccn-calendar-modalEvent').addClass('is-active'); +} + +function ccn_calendar_calendar_ItemEdit() { + $('#ccn-calendar-modalEvent').addClass('is-active'); +} + +function ccn_calendar_calendar_ItemUpdate() { + $('#ccn-calendar-modalEvent').removeClass('is-active'); +} + +function ccn_calendar_calendar_ItemCancel() { + $('#ccn-calendar-modalEvent').removeClass('is-active'); +} + +function ccn_calendar_calendar_DeployEventModal() { + +} + +// return undefined to indicate an error +function ccn_calendar_calendar_GetEventModal() { + } // ================== collection diff --git a/src/static/js/utils.js b/src/static/js/utils.js index 933b621..38c9bfc 100644 --- a/src/static/js/utils.js +++ b/src/static/js/utils.js @@ -39,4 +39,8 @@ function SetApiToken(value) { function LineBreaker2Br(strl) { return $('