Merge pull request #57 from q6q9/calendarWidget_reports_and_birthdays
Calendar widget, reports and birthdays
This commit is contained in:
commit
81738c78b3
32
backend/modules/calendar/controllers/AjaxController.php
Normal file
32
backend/modules/calendar/controllers/AjaxController.php
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace backend\modules\calendar\controllers;
|
||||||
|
|
||||||
|
use backend\modules\card\models\UserCardSearch;
|
||||||
|
use Yii;
|
||||||
|
use yii\helpers\ArrayHelper;
|
||||||
|
use yii\web\Response;
|
||||||
|
|
||||||
|
class AjaxController extends \yii\web\Controller
|
||||||
|
{
|
||||||
|
public function actionGetBirthdayByMonth($month )
|
||||||
|
{
|
||||||
|
$searchModel = new UserCardSearch();
|
||||||
|
$models = $searchModel->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;
|
||||||
|
}
|
||||||
|
}?>
|
@ -3,7 +3,6 @@
|
|||||||
namespace backend\modules\calendar\controllers;
|
namespace backend\modules\calendar\controllers;
|
||||||
|
|
||||||
use backend\modules\card\models\UserCardSearch;
|
use backend\modules\card\models\UserCardSearch;
|
||||||
use common\classes\Debug;
|
|
||||||
use Yii;
|
use Yii;
|
||||||
use yii\data\ArrayDataProvider;
|
use yii\data\ArrayDataProvider;
|
||||||
use yii\filters\AccessControl;
|
use yii\filters\AccessControl;
|
||||||
@ -43,6 +42,10 @@ class CalendarController extends Controller
|
|||||||
* Renders the index view for the module
|
* Renders the index view for the module
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
|
public function actionCalendar(){
|
||||||
|
return $this->render('calendar');
|
||||||
|
}
|
||||||
|
|
||||||
public function actionIndex()
|
public function actionIndex()
|
||||||
{
|
{
|
||||||
$searchModel = new UserCardSearch();
|
$searchModel = new UserCardSearch();
|
||||||
|
59
backend/modules/calendar/views/calendar/calendar.php
Normal file
59
backend/modules/calendar/views/calendar/calendar.php
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<?php
|
||||||
|
use yii\helpers\Html;
|
||||||
|
|
||||||
|
$this->title = 'Календарь ДР';
|
||||||
|
?>
|
||||||
|
<?= \backend\widgets\Calendar::widget([
|
||||||
|
|
||||||
|
'css' => '.success{color: orange;}',
|
||||||
|
|
||||||
|
'button' => Html::a('<i class="fas fa-long-arrow-alt-left"></i> Назад',
|
||||||
|
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 = `<table class="table table-striped table-bordered">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>#</th>
|
||||||
|
<th>ФИО</th>
|
||||||
|
<th>Дата рождения</th>
|
||||||
|
<th class="action-column"> </th>
|
||||||
|
</tr>
|
||||||
|
</thead><tbody>`;
|
||||||
|
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 += `<tr data-key="${model["id"]}">`
|
||||||
|
html += `<td>${i}</td>`
|
||||||
|
html += `<td>${model["fio"]}</td>`
|
||||||
|
html += `<td>${model["dob"]}</td>`
|
||||||
|
html += CalendarHelper._getActionColumn(`secure/calendar/calendar`,model[`id`])
|
||||||
|
html += `</tr>`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
html += `</tbody></table>`
|
||||||
|
if (flag) return html;
|
||||||
|
return "empty"
|
||||||
|
}'
|
||||||
|
]) ?>
|
||||||
|
|
||||||
|
|
@ -4,9 +4,10 @@
|
|||||||
/* @var $dataProvider yii\data\ActiveDataProvider */
|
/* @var $dataProvider yii\data\ActiveDataProvider */
|
||||||
|
|
||||||
use yii\grid\GridView;
|
use yii\grid\GridView;
|
||||||
|
use yii\helpers\Html;
|
||||||
use yii\widgets\Pjax;
|
use yii\widgets\Pjax;
|
||||||
?>
|
?>
|
||||||
|
<div style="display: flex;align-items: flex-start;">
|
||||||
<p>
|
<p>
|
||||||
<select id="options" class="btn btn-secondary dropdown-toggle">
|
<select id="options" class="btn btn-secondary dropdown-toggle">
|
||||||
<option selected="selected" value="?month=00">Выберите месяц</option>
|
<option selected="selected" value="?month=00">Выберите месяц</option>
|
||||||
@ -25,7 +26,9 @@ use yii\widgets\Pjax;
|
|||||||
<option value="?month=12">декабрь</option>
|
<option value="?month=12">декабрь</option>
|
||||||
</select>
|
</select>
|
||||||
</p>
|
</p>
|
||||||
|
<?=Html::a('Календарь дней рождений '.Html::tag('i', null, ['class' => 'far fa-calendar-alt']),
|
||||||
|
['calendar'], ['class' => 'btn btn-success', 'style' => 'margin-left: 10px'])?>
|
||||||
|
</div>
|
||||||
<?php
|
<?php
|
||||||
Pjax::begin(['id' => 'reload']);
|
Pjax::begin(['id' => 'reload']);
|
||||||
echo GridView::widget([
|
echo GridView::widget([
|
||||||
|
@ -6,7 +6,6 @@ use common\classes\Debug;
|
|||||||
use Yii;
|
use Yii;
|
||||||
use yii\base\Model;
|
use yii\base\Model;
|
||||||
use yii\data\ActiveDataProvider;
|
use yii\data\ActiveDataProvider;
|
||||||
use backend\modules\card\models\UserCard;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UserCardSearch represents the model behind the search form of `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]);
|
$query->where(['deleted_at' => null]);
|
||||||
|
|
||||||
|
if (isset($params['month'])) {
|
||||||
|
$query->andFilterWhere(['=', 'MONTH(dob)', $params['month']]);
|
||||||
|
}
|
||||||
|
|
||||||
// grid filtering conditions
|
// grid filtering conditions
|
||||||
$query->andFilterWhere([
|
$query->andFilterWhere([
|
||||||
'id' => $this->id,
|
'id' => $this->id,
|
||||||
|
@ -3,10 +3,9 @@
|
|||||||
namespace backend\modules\reports\controllers;
|
namespace backend\modules\reports\controllers;
|
||||||
|
|
||||||
use backend\modules\reports\models\Month;
|
use backend\modules\reports\models\Month;
|
||||||
use common\classes\Debug;
|
|
||||||
use Yii;
|
use Yii;
|
||||||
use backend\modules\reports\models\ReportsSearch;
|
use backend\modules\reports\models\ReportsSearch;
|
||||||
use yii\web\JsonResponseFormatter;
|
use yii\helpers\ArrayHelper;
|
||||||
use yii\web\Response;
|
use yii\web\Response;
|
||||||
|
|
||||||
class AjaxController extends \yii\web\Controller
|
class AjaxController extends \yii\web\Controller
|
||||||
@ -15,20 +14,28 @@ class AjaxController extends \yii\web\Controller
|
|||||||
public function actionGetReportsForMonthByIdYearMonth($user_id, $year, $month){
|
public function actionGetReportsForMonthByIdYearMonth($user_id, $year, $month){
|
||||||
$searchModel = new ReportsSearch();
|
$searchModel = new ReportsSearch();
|
||||||
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
|
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
|
||||||
|
$reports_array = ArrayHelper::toArray($dataProvider->getModels(), [
|
||||||
$reports = $dataProvider->getModels();
|
'common\models\Reports' => [
|
||||||
$reports_array = array_column($reports, 'attributes');
|
'id',
|
||||||
foreach ($reports as $i => $report){
|
'created_at',
|
||||||
$reports_array[$i]['today'] = array_column($report->task, 'attributes');
|
'difficulties',
|
||||||
}
|
'tomorrow',
|
||||||
|
'user_card_id',
|
||||||
|
'today' => function ($report) {
|
||||||
|
return ArrayHelper::toArray($report->task, [
|
||||||
|
'common\models\ReportsTask' => [
|
||||||
|
'hours_spent',
|
||||||
|
'task'
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
$response = Yii::$app->response;
|
$response = Yii::$app->response;
|
||||||
$response->format = Response::FORMAT_JSON;
|
$response->format = Response::FORMAT_JSON;
|
||||||
$response->getHeaders()->set('Content-Type', 'application/json; charset=utf-8');
|
$response->getHeaders()->set('Content-Type', 'application/json; charset=utf-8');
|
||||||
$response->content = json_encode(array_merge(
|
$response->content = json_encode($reports_array);
|
||||||
['reports' => $reports_array],
|
|
||||||
['month' => (array)new Month($year.'-'.$month.'-01')])
|
|
||||||
);
|
|
||||||
|
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,8 @@ use Yii;
|
|||||||
use common\models\Reports;
|
use common\models\Reports;
|
||||||
use backend\modules\reports\models\ReportsSearch;
|
use backend\modules\reports\models\ReportsSearch;
|
||||||
use yii\filters\AccessControl;
|
use yii\filters\AccessControl;
|
||||||
|
use yii\helpers\ArrayHelper;
|
||||||
use yii\web\Controller;
|
use yii\web\Controller;
|
||||||
use yii\web\JsonResponseFormatter;
|
|
||||||
use yii\web\NotFoundHttpException;
|
use yii\web\NotFoundHttpException;
|
||||||
use yii\filters\VerbFilter;
|
use yii\filters\VerbFilter;
|
||||||
|
|
||||||
@ -48,9 +48,14 @@ class ReportsController extends Controller
|
|||||||
public function actionIndex()
|
public function actionIndex()
|
||||||
{
|
{
|
||||||
$searchModel = new ReportsSearch();
|
$searchModel = new ReportsSearch();
|
||||||
$user_id__fio = [];
|
$user_id__fio = ArrayHelper::map(ArrayHelper::toArray($searchModel->search([])->getModels(), [
|
||||||
foreach ($searchModel->search([])->getModels() as $model)
|
'common\models\Reports' => [
|
||||||
$user_id__fio[$model->user_card_id] = \common\models\Reports::getFio($model);
|
'user_card_id',
|
||||||
|
'fio' => function ($report) {
|
||||||
|
return Reports::getFio($report);
|
||||||
|
}
|
||||||
|
],
|
||||||
|
]),'user_card_id', 'fio');
|
||||||
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
|
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
|
||||||
|
|
||||||
return $this->render('index', [
|
return $this->render('index', [
|
||||||
@ -61,14 +66,38 @@ class ReportsController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function actionUser($user_id)
|
public function actionCalendar($user_id)
|
||||||
{
|
{
|
||||||
$searchModel = new ReportsSearch();
|
$searchModel = new ReportsSearch();
|
||||||
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
|
$searchModel->user_card_id = $user_id;
|
||||||
|
$dataProvider = $searchModel->search([]);
|
||||||
|
|
||||||
return $this->render('user', [
|
|
||||||
'searchModel' => $searchModel,
|
$reports_array = ArrayHelper::toArray($dataProvider->getModels(), [
|
||||||
'dataProvider' => $dataProvider,
|
'common\models\Reports' => [
|
||||||
|
'id',
|
||||||
|
'created_at',
|
||||||
|
'difficulties',
|
||||||
|
'tomorrow',
|
||||||
|
'user_card_id',
|
||||||
|
'today' => function ($report) {
|
||||||
|
return ArrayHelper::toArray($report->task, [
|
||||||
|
'common\models\ReportsTask' => [
|
||||||
|
'hours_spent',
|
||||||
|
'task'
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (!$dataProvider->getCount()){
|
||||||
|
return $this->render('non-exist_user_id', ['id' => $user_id]);
|
||||||
|
}
|
||||||
|
return $this->render('calendar', [
|
||||||
|
'reports' => $reports_array,
|
||||||
|
'fio' => Reports::getFio($searchModel),
|
||||||
|
'USER_ID' => $user_id
|
||||||
]);
|
]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
89
backend/modules/reports/views/reports/calendar.php
Normal file
89
backend/modules/reports/views/reports/calendar.php
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use backend\widgets\Calendar;
|
||||||
|
use yii\helpers\Html;
|
||||||
|
|
||||||
|
/* @var $this yii\web\View */
|
||||||
|
/* @var $fio */
|
||||||
|
/* @var $USER_ID */
|
||||||
|
|
||||||
|
$this->title = 'Календарь пользователя - ' . $fio;
|
||||||
|
?>
|
||||||
|
|
||||||
|
<?=Calendar::widget([
|
||||||
|
|
||||||
|
'button' => Html::a('<i class="fas fa-long-arrow-alt-left"></i> Назад',
|
||||||
|
Yii::$app->request->referrer, ['class' => 'btn btn-primary',]),
|
||||||
|
|
||||||
|
'runBuild' => "function (date, content){
|
||||||
|
contentDays = []
|
||||||
|
for (let item of content){
|
||||||
|
contentDays.push(item['created_at'])
|
||||||
|
}
|
||||||
|
this.build(date, contentDays)
|
||||||
|
}",
|
||||||
|
|
||||||
|
'updateContent' => "function(date){
|
||||||
|
let monthNumber = date.substr(5, 2);
|
||||||
|
let yearNumber = date.substr(0, 4);
|
||||||
|
return fetch('../ajax/get-reports-for-month-by-id-year-month?user_id='+".$USER_ID."+
|
||||||
|
'&month=' + monthNumber +
|
||||||
|
'&year=' + yearNumber)
|
||||||
|
.then((res) => {
|
||||||
|
return res.json()
|
||||||
|
})
|
||||||
|
}",
|
||||||
|
|
||||||
|
'getColor' => "function (date, dates = null) {
|
||||||
|
let d = date;
|
||||||
|
if ([6, 0].includes(d.getDay()))
|
||||||
|
return;
|
||||||
|
for (let i = 0; i < dates.length; i++) {
|
||||||
|
if (dates[i] == DateHelper.dateToString(date)) {
|
||||||
|
return 'success';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 'danger';
|
||||||
|
}",
|
||||||
|
|
||||||
|
'getHtmlContentForDate' => "function (content, date) {
|
||||||
|
if ([0, 6].includes(new Date(date).getDay())) {
|
||||||
|
return 'Выходной день';
|
||||||
|
}
|
||||||
|
let j = 0;
|
||||||
|
let html = `<ul class='sidebar__list'>
|
||||||
|
<table class='table table-striped table-bordered'>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>#</th>
|
||||||
|
<th>Что было сделано сегодня?</th>
|
||||||
|
<th>Какие сложности возникли?</th>
|
||||||
|
<th>Что планируется сделать завтра?</th>
|
||||||
|
<th class='action-column'> </th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>`;
|
||||||
|
for (let k = 0, i = 0; i < content.length; i++) {
|
||||||
|
let report = content[i];
|
||||||
|
if (report['created_at'] == date) {
|
||||||
|
k++;
|
||||||
|
html += `<tr data-key='\${report['id']}'>
|
||||||
|
<td>\${k}</td><td>`;
|
||||||
|
|
||||||
|
for (j = 0; j < Object.keys(report['today']).length; j++) {
|
||||||
|
html += `<p>\${j + 1}. (\${report['today'][j]['hours_spent']} ч.)
|
||||||
|
\${report['today'][j]['task']}</p>`
|
||||||
|
}
|
||||||
|
|
||||||
|
html += `</td>
|
||||||
|
<td>\${report['difficulties']}</td>
|
||||||
|
<td>\${report['tomorrow']}</td>
|
||||||
|
\${CalendarHelper._getActionColumn(`/secure/reports/reports`, report['id'])}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (j == 0) {
|
||||||
|
return 'За этот день не было отчетов';
|
||||||
|
}
|
||||||
|
return html;
|
||||||
|
}"
|
||||||
|
]) ?>
|
@ -5,6 +5,7 @@ use common\models\Reports;
|
|||||||
use yii\helpers\Html;
|
use yii\helpers\Html;
|
||||||
use yii\grid\GridView;
|
use yii\grid\GridView;
|
||||||
use yii\widgets\ActiveForm;
|
use yii\widgets\ActiveForm;
|
||||||
|
use yii\widgets\Pjax;
|
||||||
|
|
||||||
|
|
||||||
/* @var $this yii\web\View */
|
/* @var $this yii\web\View */
|
||||||
@ -14,15 +15,7 @@ use yii\widgets\ActiveForm;
|
|||||||
|
|
||||||
$this->title = 'Отчеты';
|
$this->title = 'Отчеты';
|
||||||
$this->params['breadcrumbs'][] = $this->title;
|
$this->params['breadcrumbs'][] = $this->title;
|
||||||
$this->registerCss('
|
$this->registerCss('.row * {margin-right: 10px;}');
|
||||||
.date_sort {
|
|
||||||
display: inline-flex;
|
|
||||||
}
|
|
||||||
.row * {
|
|
||||||
margin-right: 10px;
|
|
||||||
}
|
|
||||||
');
|
|
||||||
|
|
||||||
define('TODAY', date('Y-m-d'));
|
define('TODAY', date('Y-m-d'));
|
||||||
define('WEEK_AGO', date('Y-m-d', time() - 3600 * 24 * 7));
|
define('WEEK_AGO', date('Y-m-d', time() - 3600 * 24 * 7));
|
||||||
function next_day($date, $number)
|
function next_day($date, $number)
|
||||||
@ -50,7 +43,7 @@ function next_day($date, $number)
|
|||||||
|
|
||||||
<?= Html::beginTag('div', ['class' => 'row'])?>
|
<?= Html::beginTag('div', ['class' => 'row'])?>
|
||||||
<?= Html::beginTag('div', ['class' => 'col-xs-6'])?>
|
<?= Html::beginTag('div', ['class' => 'col-xs-6'])?>
|
||||||
<?php $form = ActiveForm::begin(['method' => 'get', 'options' => ['class' => 'date_sort'] ])?>
|
<?php $form = ActiveForm::begin(['method' => 'get', 'options' => ['style' => 'display: inline-flex;'] ])?>
|
||||||
|
|
||||||
<?php foreach (array_keys($searchModel->attributes )as $attribute): ?>
|
<?php foreach (array_keys($searchModel->attributes )as $attribute): ?>
|
||||||
<?php if($attribute == 'user_card_id'):?>
|
<?php if($attribute == 'user_card_id'):?>
|
||||||
@ -77,6 +70,7 @@ function next_day($date, $number)
|
|||||||
<?php ActiveForm::end() ?>
|
<?php ActiveForm::end() ?>
|
||||||
<?= Html::endTag('div')?>
|
<?= Html::endTag('div')?>
|
||||||
<?= Html::endTag('div')?>
|
<?= Html::endTag('div')?>
|
||||||
|
<?php Pjax::begin();?>
|
||||||
<?= GridView::widget([
|
<?= GridView::widget([
|
||||||
'dataProvider' => $dataProvider,
|
'dataProvider' => $dataProvider,
|
||||||
'filterModel' => $searchModel,
|
'filterModel' => $searchModel,
|
||||||
@ -122,7 +116,7 @@ function next_day($date, $number)
|
|||||||
]),
|
]),
|
||||||
'value' => function ($model) {
|
'value' => function ($model) {
|
||||||
return Html::a(Reports::getFio($model).' '.Html::tag('i', null, ['class' => 'far fa-calendar-alt']),
|
return Html::a(Reports::getFio($model).' '.Html::tag('i', null, ['class' => 'far fa-calendar-alt']),
|
||||||
['user', 'user_id' => $model['user_card_id']]);
|
['calendar', 'user_id' => $model['user_card_id']]);
|
||||||
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -130,3 +124,4 @@ function next_day($date, $number)
|
|||||||
['class' => 'yii\grid\ActionColumn'],
|
['class' => 'yii\grid\ActionColumn'],
|
||||||
],
|
],
|
||||||
]);?>
|
]);?>
|
||||||
|
<?php Pjax::end();?>
|
||||||
|
10
backend/modules/reports/views/reports/non-exist_user_id.php
Normal file
10
backend/modules/reports/views/reports/non-exist_user_id.php
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
/* @var $this yii\web\View */
|
||||||
|
/* @var $id */
|
||||||
|
|
||||||
|
$this->title = 'Ошибка. Не удалось найти пользователя с таким ID - '.$id;
|
||||||
|
if (!Yii::$app->request->referrer){
|
||||||
|
echo \yii\helpers\Html::a('<i class="fas fa-long-arrow-alt-left"></i> Репорты', ['index'], ['class' => 'btn btn-primary',]);
|
||||||
|
} else{
|
||||||
|
echo \yii\helpers\Html::a('<i class="fas fa-long-arrow-alt-left"></i> Назад', Yii::$app->request->referrer, ['class' => 'btn btn-primary',]);
|
||||||
|
}
|
@ -1,374 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
use yii\helpers\Html;
|
|
||||||
use common\models\Reports;
|
|
||||||
use backend\modules\reports\models\Month;
|
|
||||||
|
|
||||||
/* @var $this yii\web\View */
|
|
||||||
/* @var $searchModel backend\modules\reports\models\ReportsSearch */
|
|
||||||
/* @var $dataProvider yii\data\ActiveDataProvider */
|
|
||||||
|
|
||||||
$reports = $dataProvider->getModels();
|
|
||||||
$USER_ID = $searchModel->user_card_id;
|
|
||||||
|
|
||||||
$reports_array = array_column($reports, 'attributes');
|
|
||||||
foreach ($reports as $i => $report){
|
|
||||||
$reports_array[$i]['today'] = array_column($report->task, 'attributes');
|
|
||||||
}
|
|
||||||
$reports_month = json_encode(array_merge(
|
|
||||||
['reports' => $reports_array],
|
|
||||||
['month' => (array)new Month()])
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->registerCssFile('@web/css/calendar.css');
|
|
||||||
$this->title = 'Календарь пользователя - ' . Reports::getFio($searchModel);
|
|
||||||
?>
|
|
||||||
|
|
||||||
<?=Html::beginTag('section', ['class' => 'calendar-contain'])?>
|
|
||||||
<?=Html::beginTag('aside', ['class' => 'calendar__sidebar'])?>
|
|
||||||
<?=Html::beginTag('section', ['class' => 'title-bar'])?>
|
|
||||||
<?= Html::a('<i class="fas fa-long-arrow-alt-left"></i> Назад', Yii::$app->request->referrer, ['class' => 'btn btn-primary',]) ?>
|
|
||||||
<?= Html::input('date', null, date('Y-m-d'), ['class' => 'form-control', 'id' => 'date',]) ?>
|
|
||||||
<?=Html::endTag('section')?>
|
|
||||||
|
|
||||||
<?=Html::tag('h2', date('l').'<br>'.date('F d'), ['class' => 'sidebar__heading'])?>
|
|
||||||
|
|
||||||
<?=Html::beginTag('ul', ['class' => 'sidebar__list'])?>
|
|
||||||
<?=Html::endTag('ul')?>
|
|
||||||
<?=Html::endTag('aside')?>
|
|
||||||
|
|
||||||
<?=Html::beginTag('section', ['class' => 'calendar__days'])?>
|
|
||||||
<?=Html::endTag('section')?>
|
|
||||||
|
|
||||||
<?=Html::endTag('section')?>
|
|
||||||
|
|
||||||
|
|
||||||
<script>
|
|
||||||
class HtmlCalendar {
|
|
||||||
|
|
||||||
constructor(month, reports, before = '') {
|
|
||||||
this.month = month;
|
|
||||||
this.reports = reports;
|
|
||||||
this.before = before;
|
|
||||||
this.datePicker = datePicker;
|
|
||||||
|
|
||||||
this.classDay = 'calendar__day';
|
|
||||||
|
|
||||||
this.initBefore();
|
|
||||||
}
|
|
||||||
|
|
||||||
getHtml() {
|
|
||||||
console.log(reports)
|
|
||||||
this.getInactiveBegin();
|
|
||||||
this.getActive();
|
|
||||||
this.getInactiveEnd();
|
|
||||||
return this.html;
|
|
||||||
}
|
|
||||||
|
|
||||||
update(month, reports) {
|
|
||||||
this.month = month;
|
|
||||||
this.reports = reports;
|
|
||||||
this.initBefore();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
initBefore() {
|
|
||||||
this.html = '';
|
|
||||||
this.index = 1;
|
|
||||||
this.indexRaw = 0;
|
|
||||||
this.date = document.querySelector('#date').value.substr(0, 7);
|
|
||||||
}
|
|
||||||
|
|
||||||
getInactiveBegin() {
|
|
||||||
if (Object.keys(this.month['inactive_begin']).length > 0) {
|
|
||||||
this.html += '<section class="calendar__week">';
|
|
||||||
|
|
||||||
for (; this.index <= Object.keys(this.month['inactive_begin']).length; this.index++, this.indexRaw++) {
|
|
||||||
this.html += this.getCalendarDay('inactive_begin', 'inactive');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getActive() {
|
|
||||||
for (; this.index <= this.getLastKey(this.month['active']); this.index++, this.indexRaw++) {
|
|
||||||
if (this.indexRaw % 7 == 0) {
|
|
||||||
if (this.index != 1) {
|
|
||||||
this.html += '</section>';
|
|
||||||
}
|
|
||||||
this.html += '<section class="calendar__week">';
|
|
||||||
}
|
|
||||||
this.html += this.getCalendarDay('active')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getInactiveEnd() {
|
|
||||||
for (; this.index <= this.getLastKey(this.month['inactive_end']); this.index++, this.indexRaw++) {
|
|
||||||
if (this.indexRaw % 7 == 0) {
|
|
||||||
this.html += `</section>
|
|
||||||
<section class="calendar__week ">`;
|
|
||||||
}
|
|
||||||
this.html += this.getCalendarDay('inactive_end', 'inactive');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getCalendarDay(type, className = '') {
|
|
||||||
return `<div class="${this.classDay} ${className}">
|
|
||||||
<span class="calendar__date ${this.getColor(this.date + '-' + IntToDate(this.month[type][this.index]) )}">${this.month[type][this.index]}</span>
|
|
||||||
</div>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
getColor(date) {
|
|
||||||
let d = new Date(date)
|
|
||||||
if ([6, 0].includes(d.getDay()))
|
|
||||||
return;
|
|
||||||
for (let i = 0; i < Object.keys(this.reports).length; i++) {
|
|
||||||
|
|
||||||
if (this.reports[i]['created_at'] == date) {
|
|
||||||
return 'success';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 'danger';
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
getLastKey(obj) {
|
|
||||||
return Object.keys(obj)[Object.keys(obj).length - 1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class HtmlReports {
|
|
||||||
constructor(reports) {
|
|
||||||
//TODO выходные дни - праздники
|
|
||||||
this.reports = reports;
|
|
||||||
}
|
|
||||||
|
|
||||||
getHtmlByDate(date) {
|
|
||||||
|
|
||||||
if ([0, 6].includes(new Date(date).getDay())) {
|
|
||||||
return "Выходной день";
|
|
||||||
}
|
|
||||||
if (!this.reports)
|
|
||||||
return 'Нет репортов за месяц';
|
|
||||||
let j = 0;
|
|
||||||
let html = `<ul class="sidebar__list">
|
|
||||||
<table class="table table-striped table-bordered">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>#</th>
|
|
||||||
<th><a href="/secure/reports/reports/index?date=2021-08-31&sort=today" data-sort="today">Что
|
|
||||||
было сделано
|
|
||||||
сегодня?</a></th>
|
|
||||||
<th><a href="/secure/reports/reports/index?date=2021-08-31&sort=difficulties"
|
|
||||||
data-sort="difficulties">Какие
|
|
||||||
сложности возникли?</a></th>
|
|
||||||
<th><a href="/secure/reports/reports/index?date=2021-08-31&sort=tomorrow" data-sort="tomorrow">Что
|
|
||||||
планируется сделать завтра?</a></th>
|
|
||||||
<th class="action-column"> </th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>`;
|
|
||||||
for (let k = 0, i = 0, report = this.reports[i]; i < Object.keys(this.reports).length; i++) {
|
|
||||||
report = this.reports[i];
|
|
||||||
if (report['created_at'] == date) {
|
|
||||||
k++;
|
|
||||||
html += `<tr data-key="${report['id']}">
|
|
||||||
<td>${k}</td><td>`;
|
|
||||||
|
|
||||||
for (j = 0; j < Object.keys(report['today']).length; j++) {
|
|
||||||
html += `<p>${j + 1}. (${report['today'][j]['hours_spent']} ч.)
|
|
||||||
${report['today'][j]['task']}</p>`
|
|
||||||
}
|
|
||||||
|
|
||||||
html += `</td>
|
|
||||||
<td>${report['difficulties']}</td>
|
|
||||||
<td>${report['tomorrow']}</td>
|
|
||||||
<td>
|
|
||||||
<a href="/secure/reports/reports/view?id=${report['id']}" title="Просмотр" aria-label="Просмотр"
|
|
||||||
data-pjax="0">
|
|
||||||
<svg aria-hidden="true"
|
|
||||||
style="display:inline-block;font-size:inherit;height:1em;overflow:visible;vertical-align:-.125em;width:1.125em"
|
|
||||||
xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512">
|
|
||||||
<path fill="currentColor"
|
|
||||||
d="M573 241C518 136 411 64 288 64S58 136 3 241a32 32 0 000 30c55 105 162 177 285 177s230-72 285-177a32 32 0 000-30zM288 400a144 144 0 11144-144 144 144 0 01-144 144zm0-240a95 95 0 00-25 4 48 48 0 01-67 67 96 96 0 1092-71z"></path>
|
|
||||||
</svg>
|
|
||||||
</a>
|
|
||||||
<a href="/secure/reports/reports/update?id=${report['id']}" title="Редактировать"
|
|
||||||
aria-label="Редактировать"
|
|
||||||
data-pjax="0">
|
|
||||||
<svg aria-hidden="true"
|
|
||||||
style="display:inline-block;font-size:inherit;height:1em;overflow:visible;vertical-align:-.125em;width:1em"
|
|
||||||
xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
|
|
||||||
<path fill="currentColor"
|
|
||||||
d="M498 142l-46 46c-5 5-13 5-17 0L324 77c-5-5-5-12 0-17l46-46c19-19 49-19 68 0l60 60c19 19 19 49 0 68zm-214-42L22 362 0 484c-3 16 12 30 28 28l122-22 262-262c5-5 5-13 0-17L301 100c-4-5-12-5-17 0zM124 340c-5-6-5-14 0-20l154-154c6-5 14-5 20 0s5 14 0 20L144 340c-6 5-14 5-20 0zm-36 84h48v36l-64 12-32-31 12-65h36v48z"></path>
|
|
||||||
</svg>
|
|
||||||
</a>
|
|
||||||
<a href="/secure/reports/reports/delete?id=${report['id']}" title="Удалить" aria-label="Удалить"
|
|
||||||
data-pjax="0"
|
|
||||||
data-confirm="Вы уверены, что хотите удалить этот элемент?" data-method="post">
|
|
||||||
<svg aria-hidden="true"
|
|
||||||
style="display:inline-block;font-size:inherit;height:1em;overflow:visible;vertical-align:-.125em;width:.875em"
|
|
||||||
xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
|
|
||||||
<path fill="currentColor"
|
|
||||||
d="M32 464a48 48 0 0048 48h288a48 48 0 0048-48V128H32zm272-256a16 16 0 0132 0v224a16 16 0 01-32 0zm-96 0a16 16 0 0132 0v224a16 16 0 01-32 0zm-96 0a16 16 0 0132 0v224a16 16 0 01-32 0zM432 32H312l-9-19a24 24 0 00-22-13H167a24 24 0 00-22 13l-9 19H16A16 16 0 000 48v32a16 16 0 0016 16h416a16 16 0 0016-16V48a16 16 0 00-16-16z"></path>
|
|
||||||
</svg>
|
|
||||||
</a></td>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (j == 0) {
|
|
||||||
return "За этот день не было отчетов";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return html;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const CALENDAR_BAR = ` < section
|
|
||||||
|
|
||||||
class
|
|
||||||
|
|
||||||
= "calendar__top-bar" >
|
|
||||||
< span
|
|
||||||
|
|
||||||
class
|
|
||||||
|
|
||||||
= "top-bar__days" > Mon < /span>
|
|
||||||
<span class="top-bar__days">Tue</span>
|
|
||||||
<span class="top-bar__days">Wed</span>
|
|
||||||
<span class="top-bar__days">Thu</span>
|
|
||||||
<span class="top-bar__days">Fri</span>
|
|
||||||
<span class="top-bar__days">Sat</span>
|
|
||||||
<span class="top-bar__days">Sun</span>
|
|
||||||
</section>
|
|
||||||
`;
|
|
||||||
|
|
||||||
let reports = (JSON.parse('<?=$reports_month?>'))['reports'];
|
|
||||||
let month = (JSON.parse('<?=$reports_month?>'))['month'];
|
|
||||||
let datePicker = document.querySelector('#date');
|
|
||||||
let oldDate = datePicker.value.substr(0, 7);
|
|
||||||
let nameDateBoard = document.querySelector('.sidebar__heading');
|
|
||||||
|
|
||||||
let reportsBoard = document.querySelector('.sidebar__list');
|
|
||||||
let htmlReports = new HtmlReports(reports);
|
|
||||||
|
|
||||||
let htmlCalendar = new HtmlCalendar(month, reports, CALENDAR_BAR);
|
|
||||||
let calendar = document.querySelector('.calendar__days');
|
|
||||||
|
|
||||||
|
|
||||||
calendar.load = async function (day) {
|
|
||||||
htmlCalendar.update(month, reports)
|
|
||||||
calendar.innerHTML = htmlCalendar.getHtml();
|
|
||||||
|
|
||||||
htmlReports.reports = reports;
|
|
||||||
htmlReports.getHtmlByDate('2021-08-31')
|
|
||||||
|
|
||||||
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 (!isOldDatePicker(datePicker, oldDate)) {
|
|
||||||
oldDate = datePicker.value.substr(0, 7);
|
|
||||||
|
|
||||||
updateMonthReports(datePicker.value)
|
|
||||||
.then(reportsMonth => {
|
|
||||||
reports = reportsMonth['reports'];
|
|
||||||
month = reportsMonth['month'];
|
|
||||||
|
|
||||||
calendar.load(day);
|
|
||||||
let date = new Date(datePicker.value);
|
|
||||||
let monthName = date.toLocaleString('default', {month: 'long'});
|
|
||||||
let dayWeekName = date.toLocaleString('default', {weekday: 'long'});
|
|
||||||
nameDateBoard.innerHTML = `${dayWeekName} <br>${monthName} ${datePicker.value.substr(8, 2)}`;
|
|
||||||
reportsBoard.innerHTML = htmlReports.getHtmlByDate(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} <br>${monthName} ${datePicker.value.substr(8, 2)}`;
|
|
||||||
reportsBoard.innerHTML = htmlReports.getHtmlByDate(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 = 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) + IntToDate(dateDay);
|
|
||||||
datePicker.onchange(this)
|
|
||||||
days[i].classList.add('active_day')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
calendar.load()
|
|
||||||
datePicker.onchange()
|
|
||||||
|
|
||||||
function isOldDatePicker(datePicker, oldDate) {
|
|
||||||
if (datePicker.value.substr(0, 7) == oldDate)
|
|
||||||
return true;
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
async function updateMonthReports(date) {
|
|
||||||
|
|
||||||
let monthNumber = date.substr(5, 2);
|
|
||||||
let yearNumber = date.substr(0, 4);
|
|
||||||
return fetch('../ajax/get-reports-for-month-by-id-year-month?user_id=<?=$USER_ID?>' +
|
|
||||||
'&month=' + monthNumber +
|
|
||||||
'&year=' + yearNumber)
|
|
||||||
.then((res) => {
|
|
||||||
return res.json()
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function 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() + '-' + IntToDate(date.getMonth() + 1) + '-' + IntToDate(value);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function IntToDate(number_date) {
|
|
||||||
if (Math.floor(number_date / 10) === 0)
|
|
||||||
number_date = '0' + number_date;
|
|
||||||
return number_date
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
|
|
@ -291,6 +291,9 @@
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex: 56px 0 0;
|
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 {
|
.top-bar__days {
|
||||||
@ -299,7 +302,7 @@
|
|||||||
color: #2d4338;
|
color: #2d4338;
|
||||||
font-weight: 100;
|
font-weight: 100;
|
||||||
-webkit-font-smoothing: subpixel-antialiased;
|
-webkit-font-smoothing: subpixel-antialiased;
|
||||||
font-size: 1rem;
|
font-size: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.calendar__week {
|
.calendar__week {
|
||||||
|
17
backend/widgets/AppAsset.php
Normal file
17
backend/widgets/AppAsset.php
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
namespace backend\widgets;
|
||||||
|
|
||||||
|
|
||||||
|
use yii\web\AssetBundle;
|
||||||
|
|
||||||
|
class AppAsset extends AssetBundle
|
||||||
|
{
|
||||||
|
public $sourcePath = '@backend/widgets/Calendar/assets';
|
||||||
|
public $baseUrl = '@web';
|
||||||
|
public $css = ['css/style.css'];
|
||||||
|
public $js = [
|
||||||
|
'js/script.js',
|
||||||
|
'js/src/CalendarHelper.js',
|
||||||
|
'js/src/DateHelper.js'
|
||||||
|
];
|
||||||
|
}
|
79
backend/widgets/Calendar.php
Normal file
79
backend/widgets/Calendar.php
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace backend\widgets;
|
||||||
|
|
||||||
|
|
||||||
|
use yii\base\Widget;
|
||||||
|
use yii\helpers\Html;
|
||||||
|
|
||||||
|
|
||||||
|
class Calendar extends Widget
|
||||||
|
{
|
||||||
|
public $button;
|
||||||
|
|
||||||
|
public $css;
|
||||||
|
|
||||||
|
public $runBuild = 'function (date, content){
|
||||||
|
this.build(date, content)
|
||||||
|
}';
|
||||||
|
|
||||||
|
public $updateContent = "function(){
|
||||||
|
return [];
|
||||||
|
/*
|
||||||
|
Example, return [model1, model2, model3 , ...] :
|
||||||
|
|
||||||
|
let monthNumber = date.substr(5, 2);
|
||||||
|
return fetch('../ajax/get-birthday-by-month?' +
|
||||||
|
'month=' + monthNumber)
|
||||||
|
.then((res) => {
|
||||||
|
return res.json()
|
||||||
|
})*/
|
||||||
|
}";
|
||||||
|
|
||||||
|
public $getColor = "function (date, dates = null) {
|
||||||
|
return `className`;
|
||||||
|
}";
|
||||||
|
|
||||||
|
public $getHtmlContentForDate = 'function (content, date) {
|
||||||
|
return `<div class="content">${content}</div>`;
|
||||||
|
}';
|
||||||
|
|
||||||
|
public $script = 'CalendarHelper.main()';
|
||||||
|
|
||||||
|
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') . '<br>' . 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 . ';
|
||||||
|
|
||||||
|
'.$this->script
|
||||||
|
);
|
||||||
|
$this->view->registerCss($this->css);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
383
backend/widgets/Calendar/assets/css/style.css
Normal file
383
backend/widgets/Calendar/assets/css/style.css
Normal file
@ -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;
|
||||||
|
}
|
0
backend/widgets/Calendar/assets/js/script.js
Normal file
0
backend/widgets/Calendar/assets/js/script.js
Normal file
220
backend/widgets/Calendar/assets/js/src/CalendarHelper.js
Normal file
220
backend/widgets/Calendar/assets/js/src/CalendarHelper.js
Normal file
@ -0,0 +1,220 @@
|
|||||||
|
class CalendarHelper {
|
||||||
|
|
||||||
|
static build(date, dates = null) {
|
||||||
|
const _daysNames = `<section class="calendar__top-bar">
|
||||||
|
<span class="top-bar__days"> Mon </span>
|
||||||
|
<span class="top-bar__days">Tue</span>
|
||||||
|
<span class="top-bar__days">Wed</span>
|
||||||
|
<span class="top-bar__days">Thu</span>
|
||||||
|
<span class="top-bar__days">Fri</span>
|
||||||
|
<span class="top-bar__days">Sat</span>
|
||||||
|
<span class="top-bar__days">Sun</span>
|
||||||
|
</section>`;
|
||||||
|
|
||||||
|
|
||||||
|
let month = DateHelper.getMonth(date)
|
||||||
|
|
||||||
|
let html = `<section class="calendar__week">`, 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 += `</section><section class="calendar__week">`
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
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 (parseInt(days[i].textContent)===parseInt(datePicker.value.substr(8,2))){
|
||||||
|
days[i].classList.add('active_day')
|
||||||
|
} else
|
||||||
|
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} <br>${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} <br>${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 (parseInt(datePicker.value.substr(8,2)) == 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
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 `<div class="calendar__day ${className}">
|
||||||
|
<span class="calendar__date ${color}">${dayNum}</span>
|
||||||
|
</div>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static _getActionColumn(url, id) {
|
||||||
|
|
||||||
|
return `
|
||||||
|
<td>
|
||||||
|
<a href="${url}/view?id=${id}" title="Просмотр" aria-label="Просмотр" data-pjax="0">
|
||||||
|
<svg aria-hidden="true"
|
||||||
|
style="display:inline-block;font-size:inherit;height:1em;overflow:visible;vertical-align:-.125em;width:1.125em"
|
||||||
|
xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512">
|
||||||
|
<path fill="currentColor"
|
||||||
|
d="M573 241C518 136 411 64 288 64S58 136 3 241a32 32 0 000 30c55 105 162 177 285 177s230-72 285-177a32 32 0 000-30zM288 400a144 144 0 11144-144 144 144 0 01-144 144zm0-240a95 95 0 00-25 4 48 48 0 01-67 67 96 96 0 1092-71z"></path>
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
<a href="${url}/update?id=${id}" title="Редактировать" aria-label="Редактировать"
|
||||||
|
data-pjax="0">
|
||||||
|
<svg aria-hidden="true"
|
||||||
|
style="display:inline-block;font-size:inherit;height:1em;overflow:visible;vertical-align:-.125em;width:1em"
|
||||||
|
xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
|
||||||
|
<path fill="currentColor"
|
||||||
|
d="M498 142l-46 46c-5 5-13 5-17 0L324 77c-5-5-5-12 0-17l46-46c19-19 49-19 68 0l60 60c19 19 19 49 0 68zm-214-42L22 362 0 484c-3 16 12 30 28 28l122-22 262-262c5-5 5-13 0-17L301 100c-4-5-12-5-17 0zM124 340c-5-6-5-14 0-20l154-154c6-5 14-5 20 0s5 14 0 20L144 340c-6 5-14 5-20 0zm-36 84h48v36l-64 12-32-31 12-65h36v48z"></path>
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
<a href="${url}/delete?id=${id}" title="Удалить" aria-label="Удалить" data-pjax="0"
|
||||||
|
data-confirm="Вы уверены, что хотите удалить этот элемент?" data-method="post">
|
||||||
|
<svg aria-hidden="true"
|
||||||
|
style="display:inline-block;font-size:inherit;height:1em;overflow:visible;vertical-align:-.125em;width:.875em"
|
||||||
|
xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
|
||||||
|
<path fill="currentColor"
|
||||||
|
d="M32 464a48 48 0 0048 48h288a48 48 0 0048-48V128H32zm272-256a16 16 0 0132 0v224a16 16 0 01-32 0zm-96 0a16 16 0 0132 0v224a16 16 0 01-32 0zm-96 0a16 16 0 0132 0v224a16 16 0 01-32 0zM432 32H312l-9-19a24 24 0 00-22-13H167a24 24 0 00-22 13l-9 19H16A16 16 0 000 48v32a16 16 0 0016 16h416a16 16 0 0016-16V48a16 16 0 00-16-16z"></path>
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
</td>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
87
backend/widgets/Calendar/assets/js/src/DateHelper.js
Normal file
87
backend/widgets/Calendar/assets/js/src/DateHelper.js
Normal file
@ -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
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user