diff --git a/apps/common/main/lib/component/Calendar.js b/apps/common/main/lib/component/Calendar.js new file mode 100644 index 000000000..cc4f360e1 --- /dev/null +++ b/apps/common/main/lib/component/Calendar.js @@ -0,0 +1,374 @@ +/* + * + * (c) Copyright Ascensio System SIA 2010-2019 + * + * This program is a free software product. You can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License (AGPL) + * version 3 as published by the Free Software Foundation. In accordance with + * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect + * that Ascensio System SIA expressly excludes the warranty of non-infringement + * of any third-party rights. + * + * This program is distributed WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For + * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html + * + * You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha + * street, Riga, Latvia, EU, LV-1050. + * + * The interactive user interfaces in modified source and object code versions + * of the Program must display Appropriate Legal Notices, as required under + * Section 5 of the GNU AGPL version 3. + * + * Pursuant to Section 7(b) of the License you must retain the original Product + * logo when distributing the program. Pursuant to Section 7(e) we decline to + * grant you any rights under trademark law for use of our trademarks. + * + * All the Product's GUI elements, including illustrations and icon sets, as + * well as technical writing content are licensed under the terms of the + * Creative Commons Attribution-ShareAlike 4.0 International. See the License + * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode + * +*/ +if (Common === undefined) + var Common = {}; + +define([ + 'common/main/lib/component/BaseView', + 'common/main/lib/util/utils' + +], function () { + 'use strict'; + + Common.UI.Calendar = Common.UI.BaseView.extend({ + + template : + _.template([ + '
', + '
', + '
', + '
', + '
', + '
', + '
', + '
', + '
', + '
', + '
', + '
' + ].join('')), + + options: { + date: undefined + }, + + initialize : function(options) { + Common.UI.BaseView.prototype.initialize.call(this, options); + + var me = this; + me.cmpEl = me.$el || $(this.el); + + this.monthNames = [this.textJanuary, this.textFebruary, this.textMarch, this.textApril, this.textMay, this.textJune, this.textJuly, this.textAugust, this.textSeptember, this.textOctober, this.textNovember, this.textDecember]; + this.dayNamesShort = [this.textShortSunday, this.textShortMonday, this.textShortTuesday, this.textShortWednesday, this.textShortThursday, this.textShortFriday, this.textShortSaturday]; + this.monthShortNames = [this.textShortJanuary, this.textShortFebruary, this.textShortMarch, this.textShortApril, this.textShortMay, this.textShortJune, this.textShortJuly, this.textShortAugust, this.textShortSeptember, this.textShortOctober, this.textShortNovember, this.textShortDecember]; + + me.options.date = options.date; + + me._state = undefined; + + me.render(); + }, + + render: function () { + (this.$el || $(this.el)).html(this.template()); + + var me = this; + + me.currentDate = me.options.date || new Date(); + + me.btnPrev = new Common.UI.Button({ + cls: 'btn-toolbar', + iconCls: 'mmerge-prev', + }); + me.btnPrev.render(me.cmpEl.find('#prev-arrow')); + me.btnPrev.on('click', _.bind(me.onClickPrev, me)); + + me.btnNext = new Common.UI.Button({ + cls: 'btn-toolbar', + iconCls: 'mmerge-next', + }); + me.btnNext.render(me.cmpEl.find('#next-arrow')); + me.btnNext.on('click', _.bind(me.onClickNext, me)); + + me.renderMonth(me.currentDate); + + this.trigger('render:after', this); + return this; + }, + + onClickPrev: function () { + var me = this; + if (me._state === 'month') { + me.currentDate.setMonth(me.currentDate.getMonth() - 1); + me.renderMonth(me.currentDate); + } else if (me._state === 'months') { + me.currentDate.setFullYear(me.currentDate.getFullYear() - 1); + me.renderMonths(me.currentDate); + } else if (me._state === 'years') { + var year = me.currentDate.getFullYear(), + newYear; + if (year % 10 !== 0) { + newYear = String(year); + newYear = Number(newYear.slice(0, -1) + '0') - 1; + } else { + newYear = year - 1; + } + me.currentDate.setFullYear(newYear); + me.renderYears(newYear); + } + }, + + onClickNext: function () { + var me = this; + if (me._state === 'month') { + me.currentDate.setMonth(me.currentDate.getMonth() + 1); + me.renderMonth(me.currentDate); + } else if (me._state === 'months') { + me.currentDate.setFullYear(me.currentDate.getFullYear() + 1); + me.renderMonths(me.currentDate); + } else if (me._state === 'years') { + var year = me.currentDate.getFullYear(), + newYear; + if (year % 10 !== 9) { + newYear = String(year); + newYear = Number(newYear.slice(0, -1) + '9') + 1; + } else { + newYear = year + 1; + } + me.currentDate.setFullYear(newYear); + me.renderYears(newYear); + } + }, + + renderYears: function (year) { + var me = this, + year = _.isNumber(year) ? year : (me.currentDate ? me.currentDate.getFullYear() : (new Date()).getFullYear()); + + me._state = 'years'; + + var firstYear = year, + lastYear = year; + if ((firstYear % 10) !== 0) { + var strYear = String(year); + firstYear = Number(strYear.slice(0, -1) + '0'); + } + if ((lastYear % 10) !== 9) { + var strYear = String(year); + lastYear = Number(strYear.slice(0, -1) + '9'); + } + + me.topTitle = _.template([ + '' + ].join('')); + me.cmpEl.find('.calendar-header .title').html(me.topTitle); + + me.bottomTitle = _.template([ + '' + ].join('')); + me.cmpEl.find('.calendar-header .bottom-row').html(me.bottomTitle); + + var arrYears = []; + var tmpYear = firstYear - 3; + + for (var i = 0; i < 16; i++) { + arrYears.push({ + year: tmpYear, + isCurrentDecade: ((tmpYear >= firstYear) && (tmpYear <= lastYear)) ? true : false + }); + tmpYear++; + } + + me.yearPicker = new Common.UI.DataView({ + el: $('.calendar-content'), + store: new Common.UI.DataViewStore(arrYears), + itemTemplate: _.template('
<%= year %>
') + }); + me.yearPicker.on('item:click', function (picker, item) { + var selectYear = item.$el.children(), + year = selectYear.data('year'); + var date = new Date(); + date.setFullYear(year); + me.renderMonths(date); + }); + }, + + renderMonths: function (date) { + var me = this, + curDate = (_.isDate(date)) ? date : (me.currentDate ? me.currentDate : new Date()), + year = curDate.getFullYear(); + + me._state = 'months'; + + // Number of year + me.topTitle = _.template([ + '' + ].join('')); + me.cmpEl.find('.calendar-header .title').html(me.topTitle); + me.cmpEl.find('.calendar-header .title').on('click', _.bind(me.renderYears, me)); + + me.bottomTitle = _.template([ + '' + ].join('')); + me.cmpEl.find('.calendar-header .bottom-row').html(me.bottomTitle); + + var arrMonths = []; + + for (var ind = 0; ind < 12; ind++) { + arrMonths.push({ + indexMonth: ind, + nameMonth: me.monthShortNames[ind], + year: year, + curYear: true, + isCurrentMonth: (ind === curDate.getMonth()) + }); + } + for (var ind = 0; ind < 4; ind++) { + arrMonths.push({ + indexMonth: ind, + nameMonth: me.monthShortNames[ind], + year: year + 1, + curYear: false + }); + } + + me.monthPicker = new Common.UI.DataView({ + el: $('.calendar-content'), + store: new Common.UI.DataViewStore(arrMonths), + itemTemplate: _.template('
<%= nameMonth %>
') + }); + me.monthPicker.on('item:click', function (picker, item) { + var selectMonth = item.$el.children(), + month = selectMonth.data('month'), + year = selectMonth.data('year'); + var date = new Date(year, month); + me.renderMonth(date); + }); + }, + + renderMonth: function (date) { + var me = this; + me._state = 'month'; + // Current date + var curDate = date || new Date(), + curMonth = curDate.getMonth(), + curIndexDayInWeek = curDate.getDay(), + curNumberDayInMonth = curDate.getDate(), + curYear = curDate.getFullYear(); + + // Name month + me.topTitle = _.template([ + '', + '' + ].join('')); + me.cmpEl.find('.calendar-header .title').html(me.topTitle); + me.cmpEl.find('.calendar-header .title').on('click', _.bind(me.renderMonths, me)); + + // Name days of week + var dayNamesTemplate = ''; + me.dayNamesShort.forEach(function (item) { + dayNamesTemplate += ''; + }); + me.cmpEl.find('.calendar-header .bottom-row').html(_.template(dayNamesTemplate)); + + // Month + var rows = 6, + cols = 7, + firstNumber = me.options.firstNumber; + + var arrDays = []; + + var d = new Date(curDate); + d.setDate(1); + var firstDayOfMonthIndex = d.getDay(); + + var daysInPrevMonth = me.daysInMonth(d.getTime() - (10 * 24 * 60 * 60 * 1000)), + numberDay = (firstDayOfMonthIndex > 0) ? (daysInPrevMonth - (firstDayOfMonthIndex - 1)) : 1, + month, + year; + if (firstDayOfMonthIndex > 0) { + if (curMonth - 1 >= 0) { + month = curMonth - 1 + year = curYear; + } else { + month = 11; + year = curYear - 1; + } + } else { + month = curMonth; + year = curYear; + } + + var tmp = new Date(year, month, numberDay); + + for(var r = 0; r < rows; r++) { + for(var c = 0; c < cols; c++) { + arrDays.push({ + indexInWeek: tmp.getDay(), + dayNumber: tmp.getDate(), + month: tmp.getMonth(), + year: tmp.getFullYear(), + isToday: (tmp.getDate() === curNumberDayInMonth) ? true : false, + isCurrentMonth: (tmp.getMonth() === curMonth) ? true : false + }); + tmp.setDate(tmp.getDate() + 1); + } + } + + me.monthPicker = new Common.UI.DataView({ + el: $('.calendar-content'), + store: new Common.UI.DataViewStore(arrDays), + itemTemplate: _.template('
<%= dayNumber %>
') + }); + }, + + daysInMonth: function (date) { + var d; + d = date ? new Date(date) : new Date(); + return (new Date(d.getFullYear(), d.getMonth() + 1, 0)).getDate(); + }, + + textJanuary: 'January', + textFebruary: 'February', + textMarch: 'March', + textApril: 'April', + textMay: 'May', + textJune: 'June', + textJuly: 'July', + textAugust: 'August', + textSeptember: 'September', + textOctober: 'October', + textNovember: 'November', + textDecember: 'December', + textShortJanuary: 'Jan', + textShortFebruary: 'Feb', + textShortMarch: 'Mar', + textShortApril: 'Apr', + textShortMay: 'May', + textShortJune: 'Jun', + textShortJuly: 'Jul', + textShortAugust: 'Aug', + textShortSeptember: 'Sep', + textShortOctober: 'Oct', + textShortNovember: 'Nov', + textShortDecember: 'Dec', + textShortSunday: 'Su', + textShortMonday: 'Mo', + textShortTuesday: 'Tu', + textShortWednesday: 'We', + textShortThursday: 'Th', + textShortFriday: 'Fr', + textShortSaturday: 'Sa', + textMonths: 'Months', + textYears: 'Years' + }); +}); \ No newline at end of file diff --git a/apps/common/main/lib/view/Calendar.js b/apps/common/main/lib/view/Calendar.js index 7e433f35b..5cd483371 100644 --- a/apps/common/main/lib/view/Calendar.js +++ b/apps/common/main/lib/view/Calendar.js @@ -44,8 +44,8 @@ if (Common === undefined) define([ 'common/main/lib/component/Window', - 'underscore' -], function (base, _) { + 'common/main/lib/component/Calendar', +], function () { 'use strict'; Common.Views.Calendar = Common.UI.Window.extend(_.extend({ @@ -57,8 +57,8 @@ define([ _.extend(_options, { closable: false, - width: 192, - height: 214, + width: 200, + height: 220, header: false, modal: false, alias: 'Common.Views.Calendar', @@ -69,27 +69,11 @@ define([ this.template = options.template || [ '
', '
', - '
', - '
', - '
', - '
', - '
', - '
', - '
', - '
', - '
', - '
', - '
', - '
', '
', '
' ].join(''); - this.monthNames = [this.textJanuary, this.textFebruary, this.textMarch, this.textApril, this.textMay, this.textJune, this.textJuly, this.textAugust, this.textSeptember, this.textOctober, this.textNovember, this.textDecember]; - this.dayNamesShort = [this.textShortSunday, this.textShortMonday, this.textShortTuesday, this.textShortWednesday, this.textShortThursday, this.textShortFriday, this.textShortSaturday]; - - _options.tpl = _.template(this.template)(_options); @@ -105,7 +89,7 @@ define([ window.css({ height: '', - minHeight: '', + minHeight: 222, overflow: 'hidden', position: 'absolute', zIndex: '990' @@ -116,29 +100,9 @@ define([ body.css('position', 'relative'); } - me.btnPrev = new Common.UI.Button({ - cls: 'btn-toolbar', - iconCls: 'mmerge-prev', + me.calendar = new Common.UI.Calendar({ + el: $('#id-popover') }); - me.btnPrev.render(me.$window.find('#prev-arrow')); - - me.btnNext = new Common.UI.Button({ - cls: 'btn-toolbar', - iconCls: 'mmerge-next', - }); - me.btnNext.render(me.$window.find('#next-arrow')); - - me.topTitle = _.template([ - '', - '' - ].join('')); - me.$window.find('.calendar-header .title').html(me.topTitle); - - var dayNamesTemplate = ''; - me.dayNamesShort.forEach(function (item) { - dayNamesTemplate += ''; - }); - me.$window.find('.calendar-header .bottom-row').html(_.template(dayNamesTemplate)); }, @@ -268,25 +232,5 @@ define([ } }, - textJanuary: 'January', - textFebruary: 'February', - textMarch: 'March', - textApril: 'April', - textMay: 'May', - textJune: 'June', - textJuly: 'July', - textAugust: 'August', - textSeptember: 'September', - textOctober: 'October', - textNovember: 'November', - textDecember: 'December', - textShortSunday: 'Su', - textShortMonday: 'Mo', - textShortTuesday: 'Tu', - textShortWednesday: 'We', - textShortThursday: 'Th', - textShortFriday: 'Fr', - textShortSaturday: 'Sa' - }, Common.Views.Calendar || {})) }); \ No newline at end of file diff --git a/apps/common/main/resources/less/calendar.less b/apps/common/main/resources/less/calendar.less index 9ba98c372..5bcd74011 100644 --- a/apps/common/main/resources/less/calendar.less +++ b/apps/common/main/resources/less/calendar.less @@ -3,11 +3,11 @@ .calendar-window { border-radius: 0; box-shadow: none; - border: 1px solid @calendar-bg-color; } -.calendar-popover { - width: 190px; - height: 214px; +.calendar-box { + width: 198px; + height: 220px; + border: 1px solid @calendar-bg-color; .btn { background-color: transparent; border: none; @@ -31,8 +31,8 @@ } .bottom-row { display: flex; - justify-content: space-between; - padding: 0 10px; + justify-content: space-around; + padding: 0; } .title { padding-top: 6px; @@ -44,6 +44,54 @@ } } + } + } + .calendar-content { + .item { + margin: 0; + padding: 0; + height: auto; + width: auto; + box-shadow: none; + border: 1px solid #fff; + .name-month, .name-year { + height: 40px; + width: 47px; + background-color: #F1F1F1; + display: flex; + justify-content: center; + align-items: center; + font-size: 13px; + } + .number-day { + height: 26px; + width: 26px; + background-color: #F1F1F1; + display: flex; + justify-content: center; + align-items: center; + } + &.selected { + .number-day, .name-month, .name-year { + color: #fff; + background-color: #7D858C; + } + } + .weekend { + color: #D25252; + } + .no-current-month, .no-cur-year, .no-current-decade { + color: #A5A5A5; + } + &:not(.disabled):not(.selected) { + .number-day, .name-month, .name-year { + &:hover { + background-color: #D9D9D9; + } + } + } + + } } } \ No newline at end of file