diff --git a/backend/modules/calendar/controllers/AjaxController.php b/backend/modules/calendar/controllers/AjaxController.php
new file mode 100644
index 0000000..85530c3
--- /dev/null
+++ b/backend/modules/calendar/controllers/AjaxController.php
@@ -0,0 +1,32 @@
+search(Yii::$app->request->queryParams)->getModels();
+ $models_array = ArrayHelper::toArray($models, [
+ 'backend\modules\card\models\UserCard' => [
+ 'id',
+ 'dob',
+ 'fio'
+ ],
+ ]);
+
+ $response = Yii::$app->response;
+ $response->format = Response::FORMAT_JSON;
+ $response->getHeaders()->set('Content-Type', 'application/json; charset=utf-8');
+ $response->content = json_encode(
+ $models_array
+ );
+ return $response;
+ }
+}?>
diff --git a/backend/modules/calendar/controllers/CalendarController.php b/backend/modules/calendar/controllers/CalendarController.php
index 86ae7e3..c6760bd 100644
--- a/backend/modules/calendar/controllers/CalendarController.php
+++ b/backend/modules/calendar/controllers/CalendarController.php
@@ -3,7 +3,6 @@
namespace backend\modules\calendar\controllers;
use backend\modules\card\models\UserCardSearch;
-use common\classes\Debug;
use Yii;
use yii\data\ArrayDataProvider;
use yii\filters\AccessControl;
@@ -43,6 +42,14 @@ class CalendarController extends Controller
* Renders the index view for the module
* @return string
*/
+ public function actionAlternative(){
+ $searchModel = new UserCardSearch();
+ $dataProvider = $searchModel->search(['month'=>date('m', strtotime('2019-07-03'))]);
+ return $this->render('alternative', [
+ 'dataProvider' => $dataProvider
+ ]);
+ }
+
public function actionIndex()
{
$searchModel = new UserCardSearch();
diff --git a/backend/modules/calendar/views/calendar/alternative.php b/backend/modules/calendar/views/calendar/alternative.php
new file mode 100644
index 0000000..4b20d21
--- /dev/null
+++ b/backend/modules/calendar/views/calendar/alternative.php
@@ -0,0 +1,80 @@
+title = 'Календарь ДР';
+?>
+= \backend\widgets\Calendar::widget([
+ 'button' => Html::a(' Назад',
+ Yii::$app->request->referrer, ['class' => 'btn btn-primary',]),
+ 'runBuild' => "function (date, content){
+ this.build(date, content)
+ }",
+ 'updateContent' => "function(date){
+ let monthNumber = date.substr(5, 2);
+ return fetch('../ajax/get-birthday-by-month?' +
+ 'month=' + monthNumber)
+ .then((res) => {
+ return res.json()
+ })
+ }",
+ 'getColor' => "function (date, dates = null) {
+ for (let contentDate of dates) {
+ if (contentDate['dob'].substr(8, 2) == DateHelper.intToDate(date.getDate())) {
+ return 'success';
+ }
+ }
+ }",
+ 'getHtmlContentForDate' => 'function (content, date) {
+ let flag = false
+ let html = `
+
+
+ #
+ ФИО
+ Дата рождения
+
+
+ `;
+ for (let i = 1; i <= content.length; i++) {
+ let model = content[i - 1];
+ if (model["dob"].substr(8, 2) == date.substr(8, 2)) {
+ flag = true;
+ html += ``
+ html += `${i} `
+ html += `${model["fio"]} `
+ html += `${model["dob"]} `
+ html += `
+
+
+
+
+
+
+
+
+
+
+
+
+ `
+ html += ` `
+ }
+ }
+ html += `
`
+ if (flag) return html;
+ return "empty"
+ }'
+]) ?>
+
+
diff --git a/backend/modules/calendar/views/calendar/index.php b/backend/modules/calendar/views/calendar/index.php
index 148d8a5..18a1223 100644
--- a/backend/modules/calendar/views/calendar/index.php
+++ b/backend/modules/calendar/views/calendar/index.php
@@ -4,9 +4,10 @@
/* @var $dataProvider yii\data\ActiveDataProvider */
use yii\grid\GridView;
+use yii\helpers\Html;
use yii\widgets\Pjax;
?>
-
+
Выберите месяц
@@ -25,7 +26,9 @@ use yii\widgets\Pjax;
декабрь
-
+=Html::a('Календарь дней рождений '.Html::tag('i', null, ['class' => 'far fa-calendar-alt']),
+ ['alternative'], ['class' => 'btn btn-success', 'style' => 'margin-left: 10px'])?>
+
'reload']);
echo GridView::widget([
diff --git a/backend/modules/card/models/UserCardSearch.php b/backend/modules/card/models/UserCardSearch.php
index cb6676b..4fd7e0a 100755
--- a/backend/modules/card/models/UserCardSearch.php
+++ b/backend/modules/card/models/UserCardSearch.php
@@ -6,7 +6,6 @@ use common\classes\Debug;
use Yii;
use yii\base\Model;
use yii\data\ActiveDataProvider;
-use backend\modules\card\models\UserCard;
/**
* UserCardSearch represents the model behind the search form of `backend\modules\card\models\UserCard`.
@@ -64,6 +63,10 @@ class UserCardSearch extends UserCard
$query->where(['deleted_at' => null]);
+ if (isset($params['month'])) {
+ $query->andFilterWhere(['=', 'MONTH(dob)', $params['month']]);
+ }
+
// grid filtering conditions
$query->andFilterWhere([
'id' => $this->id,
diff --git a/backend/web/css/calendar.css b/backend/web/css/calendar.css
index e5f844d..6d9188b 100644
--- a/backend/web/css/calendar.css
+++ b/backend/web/css/calendar.css
@@ -291,6 +291,9 @@
text-align: center;
display: flex;
flex: 56px 0 0;
+ max-height: 44px;
+ box-shadow: 0px 5px 5px -5px rgba(34, 60, 80, 0.6);
+ align-items: center
}
.top-bar__days {
@@ -299,7 +302,7 @@
color: #2d4338;
font-weight: 100;
-webkit-font-smoothing: subpixel-antialiased;
- font-size: 1rem;
+ font-size: 18px;
}
.calendar__week {
diff --git a/backend/widgets/AppAsset.php b/backend/widgets/AppAsset.php
new file mode 100644
index 0000000..0bcc5f8
--- /dev/null
+++ b/backend/widgets/AppAsset.php
@@ -0,0 +1,17 @@
+ {
+ return res.json()
+ })
+ }";
+ public $getColor = "function (date, dates = null) {
+ for (let contentDate of dates) {
+ if (contentDate['dob'].substr(8, 2) == DateHelper.intToDate(date.getDate())) {
+ return 'success';
+ }
+ }
+ }";
+ public $getHtmlContentForDate = 'function (content, date) {
+ console.log(content)
+ let flag = false
+ let html = `
+
+
+ #
+ ФИО
+ Дата рождения
+
+
+ `;
+ for (let i = 1; i <= content.length; i++) {
+ let model = content[i - 1];
+ if (model["dob"].substr(8, 2) == date.substr(8, 2)) {
+ flag = true;
+ html += ``
+ html += `${i} `
+ html += `${model["fio"]} `
+ html += `${model["dob"]} `
+ html += `
+
+
+
+
+
+
+
+
+
+
+
+
+ `
+ html += ` `
+ }
+ }
+ html += `
`
+ if (flag) return html;
+ return "empty"
+ }';
+
+ /*
+
+ CalendarHelper._updateContent = async function(){
+ let monthNumber = date.substr(5, 2);
+ return fetch('../ajax/get-birthday-by-month?' +
+ 'month=' + monthNumber)
+ .then((res) => {
+ return res.json()
+ })
+ }
+
+ CalendarHelper._getColor = function (date, dates = null) {
+ for (let contentDate of dates) {
+ if (contentDate['dob'].substr(8, 2) == DateHelper.intToDate(date.getDate())) {
+ return 'success';
+ }
+ }
+ }
+
+ CalendarHelper._getHtmlContentForDate = function (content, date) {
+ console.log(content)
+ let flag = false
+
+ let html = `
+
+
+ #
+ ФИО
+ Дата рождения
+
+
+ `;
+ for (let i = 1; i <= content.length; i++) {
+
+ let model = content[i - 1];
+ if (model['dob'].substr(8, 2) == date.substr(8, 2)) {
+ flag = true;
+ html += ``
+ html += `${i} `
+ html += `${model['fio']} `
+ html += `${model['dob']} `
+ html += `
+
+
+
+
+
+
+
+
+
+
+
+
+ `
+ html += ` `
+ }
+ }
+ html += `
`
+ if (flag) return html;
+ return "empty"
+ }
+ */
+
+ public function init()
+ {
+ parent::init();
+ $view = $this->getView();
+ AppAsset::register($view);
+ }
+
+ public function run()
+ {
+
+ echo Html::beginTag('section', ['class' => 'calendar-contain']);
+ echo Html::beginTag('aside', ['class' => 'calendar__sidebar']);
+ echo Html::beginTag('section', ['class' => 'title-bar']);
+ echo $this->button;
+ echo Html::input('date', null, date('Y-m-d'), ['class' => 'form-control', 'id' => 'date',]);
+ echo Html::endTag('section');
+ echo Html::tag('h2', date('l') . ' ' . date('F d'), ['class' => 'sidebar__heading']);
+ echo Html::beginTag('ul', ['class' => 'sidebar__list']);
+ echo Html::endTag('ul');
+ echo Html::endTag('aside');
+ echo Html::beginTag('section', ['class' => 'calendar__days']);
+ echo Html::endTag('section');
+ echo Html::endTag('section');
+
+ $this->view->registerJs('
+ CalendarHelper._runBuild = ' . $this->runBuild . ';
+ CalendarHelper._getHtmlContentForDate = ' . $this->getHtmlContentForDate . ';
+ CalendarHelper._updateContent = async ' . $this->updateContent . ';
+ CalendarHelper._getColor = ' . $this->getColor . ';
+
+ CalendarHelper.main()'
+ );
+ }
+
+}
+
+
+?>
+
+
diff --git a/backend/widgets/Calendar/assets/css/style.css b/backend/widgets/Calendar/assets/css/style.css
new file mode 100644
index 0000000..6d9188b
--- /dev/null
+++ b/backend/widgets/Calendar/assets/css/style.css
@@ -0,0 +1,383 @@
+.calendar-contain {
+ position: relative;
+ left: 0;
+ right: 0;
+ border-radius: 0;
+ width: 100%;
+ overflow: hidden;
+ max-width: 1920px;
+ min-width: 450px;
+ margin: 1rem auto;
+ background-color: #f5f7f6;
+ box-shadow: 5px 5px 72px rgba(30, 46, 50, 0.5);
+ color: #040605;
+}
+
+@media screen and (min-width: 55em) {
+ .calendar-contain {
+ margin: auto;
+ top: 5%;
+ }
+}
+
+.title-bar {
+ position: relative;
+ width: 100%;
+ display: flex;
+ text-align: right;
+ background: #f5f7f6;
+ padding: 0.5rem;
+ margin-bottom: 0;
+}
+
+.title-bar:after {
+ display: table;
+ clear: both;
+}
+
+.title-bar__burger {
+ display: block;
+ position: relative;
+ float: left;
+ overflow: hidden;
+ margin: 0;
+ padding: 0;
+ width: 38px;
+ height: 30px;
+ font-size: 0;
+ text-indent: -9999px;
+ appearance: none;
+ box-shadow: none;
+ border: none;
+ cursor: pointer;
+ background: none;
+}
+
+.title-bar__burger:focus {
+ outline: none;
+}
+
+.burger__lines {
+ display: block;
+ position: absolute;
+ width: 18px;
+ top: 15px;
+ left: 0;
+ right: 0;
+ margin: auto;
+ height: 1px;
+ background: #040605;
+}
+
+.burger__lines:before, .burger__lines:after {
+ position: absolute;
+ display: block;
+ left: 0;
+ width: 100%;
+ height: 1px;
+ background-color: #040605;
+ content: "";
+}
+
+.burger__lines:before {
+ top: -5px;
+}
+
+.burger__lines:after {
+ bottom: -5px;
+}
+
+.title-bar__year {
+ display: block;
+ position: relative;
+ float: left;
+ font-size: 1rem;
+ line-height: 30px;
+ width: 43%;
+ padding: 0 0.5rem;
+ text-align: left;
+}
+
+@media screen and (min-width: 55em) {
+ .title-bar__year {
+ width: 27%;
+ }
+}
+
+.title-bar__month {
+ position: relative;
+ /*float: center;*/
+ font-size: 1rem;
+ line-height: 30px;
+ width: 22%;
+ padding: 0 0.5rem;
+ text-align: center;
+ margin-right: 67px;
+ word-spacing: 30px;
+}
+
+@media screen and (min-width: 55em) {
+ .title-bar__month {
+ width: 12%;
+ }
+}
+
+.title-bar__minimize, .title-bar__maximize, .title-bar__close {
+ position: relative;
+ float: left;
+ width: 34px;
+ height: 34px;
+}
+
+.title-bar__minimize:before, .title-bar__maximize:before, .title-bar__close:before, .title-bar__minimize:after, .title-bar__maximize:after, .title-bar__close:after {
+ top: 30%;
+ right: 30%;
+ bottom: 30%;
+ left: 30%;
+ content: " ";
+ position: absolute;
+ border-color: #8e8e8e;
+ border-style: solid;
+ border-width: 0 0 2px 0;
+}
+
+.title-bar .title-bar__controls {
+ display: inline-block;
+ vertical-align: top;
+ position: relative;
+ float: right;
+ width: auto;
+}
+
+.title-bar .title-bar__controls:before, .title-bar .title-bar__controls:after {
+ content: none;
+}
+
+.title-bar .title-bar__minimize:before {
+ border-bottom-width: 2px;
+}
+
+.title-bar .title-bar__maximize:before {
+ border-width: 1px 1px 2px 1px;
+}
+
+.title-bar .title-bar__close:before, .title-bar .title-bar__close:after {
+ bottom: 50%;
+ top: 49.9%;
+}
+
+.title-bar .title-bar__close:before {
+ transform: rotate(45deg);
+}
+
+.title-bar .title-bar__close:after {
+ transform: rotate(-45deg);
+}
+
+.calendar__sidebar {
+ width: 100%;
+ margin: 0 auto;
+ float: none;
+ background: linear-gradient(120deg, #eff3f3, #e1e7e8);
+ padding-bottom: 0.7rem;
+}
+
+@media screen and (min-width: 55em) {
+ .calendar__sidebar {
+ position: absolute;
+ height: 100%;
+ width: 50%;
+ float: left;
+ margin-bottom: 0;
+ }
+}
+
+.calendar__sidebar .content {
+ padding: 2rem 1.5rem 2rem 4rem;
+ color: #040605;
+}
+
+.sidebar__nav {
+ display: flex;
+ align-items: center;
+ justify-content: flex-start;
+ margin-bottom: 0.9rem;
+ padding: 0.7rem 1rem;
+ background-color: #f5f7f6;
+}
+
+.sidebar__nav-item {
+ display: inline-block;
+ width: 22px;
+ margin-right: 23px;
+ padding: 0;
+ opacity: 0.8;
+}
+
+.sidebar__list {
+ list-style: none;
+ margin: 0;
+ padding-left: 1rem;
+ padding-right: 1rem;
+}
+
+.sidebar__list-item {
+ margin: 1.2rem 0;
+ color: #2d4338;
+ font-weight: 100;
+ font-size: 1rem;
+}
+
+.list-item__time {
+ display: inline-block;
+ width: 60px;
+}
+
+@media screen and (min-width: 55em) {
+ .list-item__time {
+ margin-right: 2rem;
+ }
+}
+
+.sidebar__list-item--complete {
+ color: rgba(4, 6, 5, 0.3);
+}
+
+.sidebar__list-item--complete .list-item__time {
+ color: rgba(4, 6, 5, 0.3);
+}
+
+.sidebar__heading {
+ font-size: 2.2rem;
+ font-weight: bold;
+ padding-left: 1rem;
+ padding-right: 1rem;
+ margin-bottom: 3rem;
+ margin-top: 1rem;
+}
+
+.sidebar__heading span {
+ float: right;
+ font-weight: 300;
+}
+
+.calendar__heading-highlight {
+ color: #2d444a;
+ font-weight: 900;
+}
+
+.calendar__days {
+ display: flex;
+ flex-flow: column wrap;
+ align-items: stretch;
+ width: 100%;
+ float: none;
+ min-height: 580px;
+ height: 100%;
+ font-size: 12px;
+ /*padding: 0.8rem 0 1rem 1rem;*/
+ background: #f5f7f6;
+}
+
+@media screen and (min-width: 55em) {
+ .calendar__days {
+ width: 50%;
+ float: right;
+ }
+}
+
+.calendar__top-bar {
+ background: #b8cad6;
+ text-align: center;
+ display: flex;
+ flex: 56px 0 0;
+ max-height: 44px;
+ box-shadow: 0px 5px 5px -5px rgba(34, 60, 80, 0.6);
+ align-items: center
+}
+
+.top-bar__days {
+ width: 100%;
+ padding: 0 5px;
+ color: #2d4338;
+ font-weight: 100;
+ -webkit-font-smoothing: subpixel-antialiased;
+ font-size: 18px;
+}
+
+.calendar__week {
+ display: flex;
+ flex: 1 1 0;
+}
+
+.calendar__day {
+ text-align: center;
+ display: flex;
+ flex-flow: column wrap;
+
+ width: 100%;
+ justify-content: space-around;
+ /*padding: 1.9rem 0.2rem 0.2rem;*/
+}
+
+
+.calendar__date {
+ /*margin: 25px;*/
+ color: #040605;
+ font-size: 1.7rem;
+ font-weight: 600;
+ line-height: 0.7;
+}
+
+@media screen and (min-width: 55em) {
+ .calendar__date {
+ font-size: 2.3rem;
+ }
+}
+
+.calendar__week .inactive .calendar__date, .calendar__week .inactive .task-count {
+ color: #c6c6c6;
+}
+
+.calendar__week .today .calendar__date {
+ color: #fd588a;
+}
+
+.calendar__task {
+ color: #040605;
+ display: flex;
+ font-size: 0.8rem;
+}
+
+@media screen and (min-width: 55em) {
+ .calendar__task {
+ font-size: 1rem;
+ }
+}
+
+.calendar__task.calendar__task--today {
+ color: #fd588a;
+}
+
+
+.danger {
+ color: red;
+}
+
+.success {
+ color: green;
+}
+
+.calendar__day:hover {
+ color: #0a0a0a;
+ background: #c2c2c2;
+ cursor: pointer;
+}
+.calendar__day:active {
+ background: #727272;
+ cursor: pointer;
+}
+
+.active_day {
+ background: #cdcfce;
+}
\ No newline at end of file
diff --git a/backend/widgets/Calendar/assets/js/script.js b/backend/widgets/Calendar/assets/js/script.js
new file mode 100644
index 0000000..e69de29
diff --git a/backend/widgets/Calendar/assets/js/src/CalendarHelper.js b/backend/widgets/Calendar/assets/js/src/CalendarHelper.js
new file mode 100644
index 0000000..aa8dbc7
--- /dev/null
+++ b/backend/widgets/Calendar/assets/js/src/CalendarHelper.js
@@ -0,0 +1,186 @@
+class CalendarHelper {
+
+ static build(date, dates = null) {
+ const _daysNames = `
+ Mon
+ Tue
+ Wed
+ Thu
+ Fri
+ Sat
+ Sun
+ `;
+
+
+ let month = DateHelper.getMonth(date)
+
+ let html = ``, index = 1, indexRaw = 0;
+
+ for (let i = 0, dayNum = month[i]; i < month.length; i++, dayNum = month[i]) {
+ let className = ``
+ if (this._isInactive(dayNum, i)) {
+ className = 'inactive'
+ }
+ let color = this._getColor(new Date(date.getFullYear(), date.getMonth(), dayNum), dates)
+ html += this._getCalendarDay(dayNum, className, color)
+ if ((i + 1) % 7 == 0) {
+
+ html += ` `
+
+
+ }
+
+ }
+ html = removeExcessTagSection(html)
+
+ document.querySelector('.calendar__days').innerHTML = _daysNames + html
+
+
+ function removeExcessTagSection(html) {
+ return html.substr(0, html.length - 9)
+ }
+ }
+
+ static main(day = null) {
+ let datePicker = document.querySelector('#date');
+ let oldDate = datePicker.value.substr(0, 7);
+
+ let nameDateBoard = document.querySelector('.sidebar__heading');
+ let contentBoard = document.querySelector('.sidebar__list');
+
+ this._updateContent(datePicker.value)
+ .then(content => {
+
+ this._runBuild(DateHelper.stringToDate(datePicker.value), content)
+
+ datePicker.onchange = function (day = null) {
+ let days = document.querySelectorAll('.calendar__day ')
+
+ for (let i = 0; i < days.length; i++) {
+ if (days[i].classList.contains('active_day'))
+ days[i].classList.remove('active_day')
+ }
+
+ if (!CalendarHelper.isOldDatePicker(datePicker, oldDate)) {
+ oldDate = datePicker.value.substr(0, 7);
+
+ CalendarHelper._updateContent(datePicker.value)
+ .then(content => {
+
+ CalendarHelper.main(day)
+ let date = new Date(datePicker.value);
+ let monthName = date.toLocaleString('default', {month: 'long'});
+ let dayWeekName = date.toLocaleString('default', {weekday: 'long'});
+ nameDateBoard.innerHTML = `${dayWeekName} ${monthName} ${datePicker.value.substr(8, 2)}`;
+ contentBoard.innerHTML = CalendarHelper._getHtmlContentForDate(content, datePicker.value)
+ })
+
+ }
+ let date = new Date(datePicker.value);
+ let monthName = date.toLocaleString('default', {month: 'long'});
+ let dayWeekName = date.toLocaleString('default', {weekday: 'long'});
+ nameDateBoard.innerHTML = `${dayWeekName} ${monthName} ${datePicker.value.substr(8, 2)}`;
+ contentBoard.innerHTML = CalendarHelper._getHtmlContentForDate(content, datePicker.value)
+ }
+
+ let days = document.querySelectorAll('.calendar__day');
+
+ for (let i = 0; i < Object.keys(days).length; i++) {
+ let dateDay = parseInt(days[i].textContent);
+ if (day) {
+ if (parseInt(day.textContent) == dateDay && !days[i].classList.contains('inactive')) {
+ days[i].classList.add('active_day')
+ }
+ }
+
+ if (days[i].classList.contains('inactive')) {
+ days[i].onclick = function () {
+ let date = CalendarHelper._getFutureDate(datePicker.value, parseInt(days[i].textContent))
+ datePicker.value = date;
+ datePicker.onchange(this)
+ }
+ } else {
+ days[i].onclick = function () {
+ datePicker.value = datePicker.value.substr(0, 8) + DateHelper.intToDate(dateDay);
+ datePicker.onchange(this)
+ days[i].classList.add('active_day')
+ }
+ }
+ }
+
+
+ })
+ }
+
+ static _getHtmlContentForDate(content, date) {
+ /* making html content; Example: return "In this day Birthday of " +content['date']['user']; */
+ }
+
+
+ static _runBuild(date, content) {
+ /*making something for dates from content = [date1, date2, ...]*/
+
+ this.build(date, content)
+ }
+
+ static
+ async _updateContent(date) {
+ let monthNumber = date.substr(5, 2);
+ return fetch('../ajax/get-birthday-by-month?' +
+ 'month=' + monthNumber)
+ .then((res) => {
+ return res.json()
+ })
+
+ }
+
+ static isOldDatePicker(datePicker, oldDate) {
+ if (datePicker.value.substr(0, 7) == oldDate)
+ return true;
+ return false
+ }
+
+ static _isInactive(numDay, i) {
+ if (i < 8 && numDay !== i + 1) {
+ return (numDay > i)
+ } else {
+ return (i - 8) > numDay
+ }
+ }
+
+ static _getCalendarDay(dayNum, className = ``, color = ``) {
+ return `
+ ${dayNum}
+
`;
+ }
+
+ static _getColor(date, dates = null) {
+ if (dates != null && dates.includes(DateHelper.dateToString(date))) {
+ return 'success';
+ }
+ if ([6, 0].includes(date.getDay()))
+ return;
+
+ return 'danger';
+ }
+
+ static _getFutureDate(dat, value) {
+ let date = new Date(dat);
+ if (value < 8) {
+ if (date.getMonth() == 11) {
+ date = new Date(date.getFullYear() + 1, 0, value);
+ } else {
+ date = new Date(date.getFullYear(), date.getMonth() + 1, value);
+ }
+ } else {
+ if (date.getMonth() == 0) {
+ date = new Date(date.getFullYear() - 1, 11, value);
+ } else {
+ date = new Date(date.getFullYear(), date.getMonth() - 1, value);
+ }
+ }
+ return date.getFullYear() + '-' + DateHelper.intToDate(date.getMonth() + 1) + '-' + DateHelper.intToDate(value);
+
+ }
+
+}
diff --git a/backend/widgets/Calendar/assets/js/src/DateHelper.js b/backend/widgets/Calendar/assets/js/src/DateHelper.js
new file mode 100644
index 0000000..c2a524a
--- /dev/null
+++ b/backend/widgets/Calendar/assets/js/src/DateHelper.js
@@ -0,0 +1,87 @@
+class DateHelper {
+ static getMonth(date) {
+ date = this.nextMonth(date)
+ date = this.prevDay(date)
+ let days = [], last = date, quantity = this.getQuantity(date)
+ for (let i = 0; i < (7 - last.getDay()) % 7; i++) {
+ days.push((7 - last.getDay()) % 7 - i)
+ }
+ for (let i = 0; i < last.getDate(); i++) {
+ days.push(last.getDate() - i)
+ }
+ date = this.prevMonth(date)
+ date = this.nextMonth(date)
+ date = this.prevDay(date)
+ for (let i = 0, lenDays = quantity - days.length; i < lenDays; i++) {
+ days.push(date.getDate() - i)
+ }
+ return days.reverse();
+ }
+
+ static getQuantity(date) {
+ if (this.isDayOff(date)) {
+ return 42
+ }
+ if (this.prevDay(this.nextMonth(date)).getDate() == 28) {
+ return 28;
+ }
+ return 35
+
+ }
+
+ static isDayOff(date) {
+ return [6, 0].includes(new Date(date.getFullYear(), date.getMonth(), 1).getDay())
+ }
+
+ static prevDay(date) {
+ return new Date(date.getTime() - 1000 * 3600 * 24)
+ }
+
+ static nextMonth(date) {
+ if (this.isDecember(date)) {
+ return new Date(date.getFullYear() + 1, 0, 1)
+ }
+ return new Date(date.getFullYear(), date.getMonth() + 1, 1)
+ }
+
+ static prevMonth(date) {
+ if (this.isJanuary(date)) {
+ return new Date(date.getFullYear() - 1, 11, 1)
+ }
+ return new Date(date.getFullYear(), date.getMonth() - 1, 1)
+ }
+
+ static isDecember(date) {
+ return 11 == date.getMonth()
+ }
+
+ static isJanuary(date) {
+ return 0 == date.getMonth()
+ }
+
+ static intToDate(number_date) {
+ if (Math.floor(number_date / 10) === 0)
+ number_date = '0' + number_date;
+ return number_date
+ }
+
+ static dateToString(date) {
+ let year = date.getFullYear()
+ let day = this.intToDate(date.getDate())
+ let month = this.intToDate(this.isDecember(date) ? 0 : date.getMonth() + 1)
+ return year + '-' + month + '-' + day
+ }
+
+ static stringToDate(date) {
+ let month = parseInt(date.substr(5, 2))
+ return new Date(date.substr(0, 4), month, date.substr(7, 2))
+ }
+
+ static getDates(array) {
+ let dates = []
+ for (let model of array) {
+ dates.push(model['date'])
+ }
+ return dates
+ }
+}