Merge remote-tracking branch 'origin/add_task' into add_task

This commit is contained in:
iIronside 2021-12-21 17:39:44 +03:00
commit ce25dc44ea
24 changed files with 308 additions and 92 deletions

View File

@ -19,7 +19,7 @@ echo GridView::widget([
if ($model->task) {
$i = 1;
foreach ($model->task as $task) {
$text .= "<p>$i. ($task->hours_spent ч.) $task->task</p>";
$text .= "<p>$i. ($task->hours_spent ч., $task->minutes_spent мин.) $task->task</p>";
$i++;
}
}

View File

@ -20,7 +20,7 @@ echo GridView::widget([
if ($model->task) {
$i = 1;
foreach ($model->task as $task) {
$text .= "<p>$i. ($task->hours_spent ч.) $task->task</p>";
$text .= "<p>$i. ($task->hours_spent ч., $task->minutes_spent мин.) $task->task</p>";
$i++;
}
}

View File

@ -10,6 +10,8 @@ use yii\widgets\ActiveForm;
/* @var $this yii\web\View */
/* @var $model common\models\Reports */
/* @var $form yii\widgets\ActiveForm */
$this->registerCss('.list-cell__task{width:73%}')
?>
<div class="reports-form">
@ -27,6 +29,7 @@ use yii\widgets\ActiveForm;
echo '<b>Дата заполнения отчета:</b>';
echo DatePicker::widget([
'model' => $model,
'language' => 'ru',
'attribute' => 'created_at',
'options' => [],
'pluginOptions' => [
@ -52,6 +55,13 @@ use yii\widgets\ActiveForm;
'style' => 'width:100px'
],
],
[
'name' => 'minutes_spent',
'title' => 'Кол-во минут',
'options' => [
'type' => 'number',
],
],
],
])->label('Какие задачаи были выполнены:'); ?>

View File

@ -37,7 +37,7 @@ $this->params['breadcrumbs'][] = $this->title;
if ($model->task) {
$i = 1;
foreach ($model->task as $task) {
$text .= "<p>$i. ($task->hours_spent ч.) $task->task</p>";
$text .= "<p>$i. ($task->hours_spent ч., $task->minutes_spent мин.) $task->task</p>";
$i++;
}
}

View File

@ -68,7 +68,7 @@ class DateHelper {
static dateToString(date) {
let year = date.getFullYear()
let day = this.intToDate(date.getDate())
let month = this.intToDate(this.isDecember(date) ? 0 : date.getMonth() + 1)
let month = this.intToDate(date.getMonth() + 1)
return year + '-' + month + '-' + day
}

View File

@ -75,6 +75,7 @@ class Reports extends \yii\db\ActiveRecord
foreach ($this->task as $task) {
$this->_task[$i]['task'] = $task->task;
$this->_task[$i]['hours_spent'] = $task->hours_spent;
$this->_task[$i]['minutes_spent'] = $task->minutes_spent;
$i++;
}
}
@ -102,6 +103,7 @@ class Reports extends \yii\db\ActiveRecord
$taskModel->report_id = $this->id;
$taskModel->task = $task['task'];
$taskModel->hours_spent = (float)$task['hours_spent'];
$taskModel->minutes_spent = (int) $task['minutes_spent'];
$taskModel->status = 1;
$taskModel->created_at = time();
$taskModel->save();

View File

@ -12,12 +12,22 @@ use Yii;
* @property string $task
* @property int $created_at
* @property int $status
* @property int $minutes_spent
* @property float $hours_spent
*
* @property Reports $report
*/
class ReportsTask extends \yii\db\ActiveRecord
{
const SCENARIO_WITHOUT_REPORT_ID = 'withoutReportID';
public function scenarios()
{
$scenarios = parent::scenarios();
$scenarios[self::SCENARIO_WITHOUT_REPORT_ID] = self::attributes();
return $scenarios;
}
/**
* {@inheritdoc}
*/
@ -32,9 +42,10 @@ class ReportsTask extends \yii\db\ActiveRecord
public function rules()
{
return [
[['report_id'], 'required'],
[['report_id', 'created_at', 'status'], 'integer'],
[['report_id'], 'required', 'on' => self::SCENARIO_DEFAULT],
[['report_id', 'created_at', 'status', 'minutes_spent'], 'integer'],
[['hours_spent'], 'number'],
['minutes_spent', 'compare', 'compareValue' => 60, 'operator' => '<'],
[['task'], 'string'],
[['report_id'], 'exist', 'skipOnError' => true, 'targetClass' => Reports::className(), 'targetAttribute' => ['report_id' => 'id']],
];

View File

@ -296,4 +296,5 @@ class UserCard extends \yii\db\ActiveRecord
return $userCard['id'];
}
}

View File

@ -0,0 +1,25 @@
<?php
use yii\db\Migration;
/**
* Handles adding columns to table `{{%reports_task}}`.
*/
class m211122_144548_add_column_to_reports_task_table extends Migration
{
/**
* {@inheritdoc}
*/
public function safeUp()
{
$this->addColumn('reports_task', 'minutes_spent', $this->integer()->defaultValue(0)->notNull());
}
/**
* {@inheritdoc}
*/
public function safeDown()
{
$this->dropColumn('reports_task', 'minutes_spent' );
}
}

View File

@ -258,6 +258,39 @@
`https://guild.craft-group.xyz/api/reports/index?fromDate=2021-08-01&toDate=2021-08-31&user_id=2limit=3&offset=2`
### Один отчет
`https://guild.craft-group.xyz/api/reports/{id}`
<p>
Для получения отчета необходимо отправить <b>GET</b> запрос на URL https://guild.craft-group.xyz/api/reports/{id}
</p>
<p>
Параметры:
</p>
<table>
<tr>
<th>
Параметры
</th>
<th>
Значение
</th>
</tr>
<tr>
<td>
id*
</td>
<td>
ID отчета.
</td>
</tr>
</table>
<p>
Пример запроса на просмотр отчета с ID 13:
</p>
`https://guild.craft-group.xyz/api/reports/13`
### Создать отчет
`https://guild.craft-group.xyz/api/reports/create`
@ -295,10 +328,19 @@
</tr>
<tr>
<td>
today
tasks*
</td>
<td>
Сделанное сегодня.
JSON массив содержащий объекты задач
<pre>
[{
"task" : "Рефакторинг",
"created_at": 1638260728,
"status": 1,
"minutes_spent": 26,
"hours_spent" : 3
}]
</pre>
</td>
</tr>
<tr>

View File

@ -84,6 +84,7 @@ return [
'rules' => [
'site/index' => 'card/user-card/index',
'api/profile/<id:\d+>' => 'api/profile/index',
'api/reports/<id:\d+>' => 'api/reports/view',
'' => 'card/user-card/index',
['class' => 'yii\rest\UrlRule', 'controller' => 'skills'],
],

View File

@ -0,0 +1,30 @@
<?php
namespace frontend\modules\api\controllers;
use common\behaviors\GsCors;
use yii\rest\Controller;
class ApiController extends Controller
{
public function behaviors()
{
return [
'corsFilter' => [
'class' => GsCors::class,
'cors' => [
'Origin' => ['*'],
//'Access-Control-Allow-Credentials' => true,
'Access-Control-Allow-Headers' => [
'Content-Type',
'Access-Control-Allow-Headers',
'Authorization',
'X-Requested-With'
],
]
],
];
}
}

View File

@ -12,17 +12,20 @@ use kavalar\TelegramBotService;
use yii\filters\auth\CompositeAuth;
use yii\filters\auth\HttpBearerAuth;
use yii\filters\auth\QueryParamAuth;
use yii\filters\ContentNegotiator;
use yii\web\Response;
class ProfileController extends \yii\rest\Controller
class ProfileController extends ApiController
{
public function behaviors()
{
return [
$parent = parent::behaviors();
$b = [
[
'class' => \yii\filters\ContentNegotiator::className(),
'class' => ContentNegotiator::className(),
'formats' => [
'application/json' => \yii\web\Response::FORMAT_JSON,
'application/json' => Response::FORMAT_JSON,
],
],
'authenticator' => [
@ -31,20 +34,9 @@ class ProfileController extends \yii\rest\Controller
HttpBearerAuth::class,
],
]
// 'corsFilter' => [
// 'class' => GsCors::class,
// 'cors' => [
// 'Origin' => ['https://itguild.info'],
// //'Access-Control-Allow-Credentials' => true,
// 'Access-Control-Allow-Headers' => [
// 'Content-Type',
// 'Access-Control-Allow-Headers',
// 'Authorization',
// 'X-Requested-With'
// ],
// ]
// ]
];
return array_merge($parent, $b);
}
public function actionIndex($id = null)

View File

@ -5,18 +5,19 @@ namespace frontend\modules\api\controllers;
use common\behaviors\GsCors;
use common\classes\Debug;
use common\models\Reports;
use common\models\ReportsTask;
use common\models\UserCard;
use frontend\modules\api\models\ReportSearchForm;
use JsonException;
use Yii;
use yii\filters\auth\CompositeAuth;
use yii\filters\auth\HttpBearerAuth;
use yii\filters\ContentNegotiator;
use yii\rest\Controller;
use yii\web\BadRequestHttpException;
use yii\web\NotFoundHttpException;
use yii\web\Response;
class ReportsController extends Controller
class ReportsController extends ApiController
{
public function init()
{
@ -25,26 +26,14 @@ class ReportsController extends Controller
public function behaviors()
{
return [
$parent = parent::behaviors();
$b = [
[
'class' => ContentNegotiator::className(),
'formats' => [
'application/json' => Response::FORMAT_JSON,
],
],
// 'corsFilter' => [
// 'class' => GsCors::class,
// 'cors' => [
// 'Origin' => ['*'],
// //'Access-Control-Allow-Credentials' => true,
// 'Access-Control-Allow-Headers' => [
// 'Content-Type',
// 'Access-Control-Allow-Headers',
// 'Authorization',
// 'X-Requested-With'
// ],
// ]
// ],
'authenticator' => [
'class' => CompositeAuth::class,
'authMethods' => [
@ -52,6 +41,8 @@ class ReportsController extends Controller
],
]
];
return array_merge($parent, $b);
}
public function actionIndex(): array
@ -59,6 +50,12 @@ class ReportsController extends Controller
$reportsModel = new ReportSearchForm();
$params = Yii::$app->request->get();
if(!isset($params['user_card_id'])){
$userCard = UserCard::find()->where(['id_user' => Yii::$app->user->id])->one();
if($userCard){
$params['user_card_id'] = $userCard->id;
}
}
$reportsModel->attributes = $params;
if(!$reportsModel->validate()){
@ -67,20 +64,37 @@ class ReportsController extends Controller
return $reportsModel->byParams();
}
public function actionView($id): array{
$report = Reports::findOne($id);
return array_merge($report->toArray(), ['tasks' => $report->_task]);
}
public function actionCreate()
{
$reportsModel = new Reports();
$params = Yii::$app->request->post();
if (!isset($params['tasks'])){
throw new BadRequestHttpException('Нет параметра tasks');
}
if(!isset($params['user_card_id'])){
$userCard = UserCard::find()->where(['id_user' => Yii::$app->user->id])->one();
if($userCard){
$params['user_card_id'] = $userCard->id;
}
}
$reportsModel = new Reports();
$reportsModel->attributes = $params;
$params['tasks'] = (is_array($params['tasks'])) ? $params['tasks'] : json_decode($params['tasks']);
if(!$reportsModel->validate()){
throw new BadRequestHttpException(json_encode($reportsModel->errors));
}
$reportsModel->save();
return $reportsModel->toArray();
return array_merge($reportsModel->toArray());
}
public function actionDelete()

View File

@ -8,16 +8,19 @@ use yii\filters\AccessControl;
use yii\filters\auth\CompositeAuth;
use yii\filters\auth\HttpBearerAuth;
use yii\filters\auth\QueryParamAuth;
use yii\filters\ContentNegotiator;
use yii\web\Response;
class SkillsController extends \yii\rest\Controller
class SkillsController extends ApiController
{
public function behaviors()
{
return [
$parent = parent::behaviors();
$b = [
[
'class' => \yii\filters\ContentNegotiator::className(),
'class' => ContentNegotiator::className(),
'formats' => [
'application/json' => \yii\web\Response::FORMAT_JSON,
'application/json' => Response::FORMAT_JSON,
],
],
'authenticator' => [
@ -26,20 +29,9 @@ class SkillsController extends \yii\rest\Controller
HttpBearerAuth::class,
],
]
// 'corsFilter' => [
// 'class' => GsCors::class,
// 'cors' => [
// 'Origin' => ['*'],
// //'Access-Control-Allow-Credentials' => true,
// 'Access-Control-Allow-Headers' => [
// 'Content-Type',
// 'Access-Control-Allow-Headers',
// 'Authorization',
// 'X-Requested-With'
// ],
// ]
// ]
];
return array_merge($parent, $b);
}
public function actionIndex()

View File

@ -36,19 +36,19 @@ class UserController extends ActiveController
// HttpBearerAuth::class,
// ],
// ],
// 'corsFilter' => [
// 'class' => GsCors::class,
// 'cors' => [
// 'Origin' => ['*'],
// //'Access-Control-Allow-Credentials' => true,
// 'Access-Control-Allow-Headers' => [
// 'Content-Type',
// 'Access-Control-Allow-Headers',
// 'Authorization',
// 'X-Requested-With'
// ],
// ]
// ]
'corsFilter' => [
'class' => GsCors::class,
'cors' => [
'Origin' => ['*'],
//'Access-Control-Allow-Credentials' => true,
'Access-Control-Allow-Headers' => [
'Content-Type',
'Access-Control-Allow-Headers',
'Authorization',
'X-Requested-With'
],
]
]
]);
}

View File

@ -32,6 +32,18 @@ class ProfileSearchForm extends Model
];
}
public function exclude($arr)
{
$ex = ['fio', 'passport', 'resume', 'link_vk', 'link_telegram', 'email', 'salary'];
foreach ($ex as $remove) {
if (isset($arr[$remove])) {
unset($arr[$remove]);
}
}
return $arr;
}
public function checkIsArray()
{
@ -43,12 +55,12 @@ class ProfileSearchForm extends Model
public function byId()
{
if ($this->id) {
return UserCard::find()
return $this->exclude(UserCard::find()
->where(['id' => $this->id])
->with(['skillValues'])
->with(['achievements'])
->asArray()
->one();
->one());
}
return null;
@ -58,14 +70,12 @@ class ProfileSearchForm extends Model
{
$model = UserCard::find();
if ($this->skills) {
$model->joinWith(['skillValues']);
$this->skills = explode(',', $this->skills);
$model->where(['card_skill.skill_id' => $this->skills]);
$model->having('COUNT(DISTINCT skill_id) = ' . count($this->skills));
}
else{
} else {
$model->joinWith('skillValues');
}
@ -78,8 +88,19 @@ class ProfileSearchForm extends Model
$model->groupBy('card_skill.card_id');
return $model->limit($this->limit)
$res = $model->limit($this->limit)
->offset($this->offset)->orderBy('updated_at DESC')->asArray()->all();
if(!$res){
return [];
}
$resArr = [];
foreach ($res as $re){
$resArr[] = $this->exclude($re);
}
return $resArr;
}
}

View File

@ -14,6 +14,10 @@ class ReportSearchForm extends Model
public $fromDate;
public $toDate;
public $user_id;
/**
* @var false
*/
public $byDate;
public function __construct($config = [])
{
@ -23,6 +27,7 @@ class ReportSearchForm extends Model
$this->toDate = date('Y-m-d', time());
$this->fromDate = date('Y-m-01', time());
$this->byDate = false;
parent::__construct($config);
}
@ -30,6 +35,7 @@ class ReportSearchForm extends Model
public function rules(): array
{
return [
[['byDate'], 'safe'],
[['fromDate', 'toDate'], 'date', 'format' => 'php:Y-m-d'],
[['limit', 'offset', 'user_id'], 'integer', 'min' => 0],
];
@ -38,9 +44,15 @@ class ReportSearchForm extends Model
public function byParams()
{
$queryBuilder = Reports::find()
->with('task')
->andWhere(['between', 'reports.created_at', $this->fromDate, $this->toDate])
->limit($this->limit)
->with('task');
if ($this->byDate) {
$queryBuilder->andWhere(['reports.created_at' => $this->byDate]);
} else {
$queryBuilder->andWhere(['between', 'reports.created_at', $this->fromDate, $this->toDate]);
}
$queryBuilder->limit($this->limit)
->offset($this->offset);
if (isset($this->user_id)) {

View File

@ -51,6 +51,11 @@ class UserCardController extends Controller
$result = UserCard::find()->where(['id_user' => $id_user])->asArray()->all();
if($result) {
$id = $result[0]['id'];
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post())) {
$model->updated_at = date('Y-m-d h:i:s');
$model->save();
}
$dataProvider = new ActiveDataProvider([
'query' => FieldsValueNew::find()
->where(['item_id' => $id, 'item_type' => FieldsValueNew::TYPE_PROFILE])
@ -69,7 +74,7 @@ class UserCardController extends Controller
->all();
return $this->render('view', [
'model' => $this->findModel($id),
'model' => $model,
'modelFildValue' => $dataProvider,
'skills' => $skills,
'achievements' => $achievements,
@ -107,6 +112,21 @@ class UserCardController extends Controller
]);
}
public function actionResume()
{
$id_user = Yii::$app->user->id;
$result = UserCard::find()->where(['id_user' => $id_user])->asArray()->all();
if ($result) {
$id = $result[0]['id'];
$model = $this->findModel($id);
return $this->render('resume', [
'model' => $model
]);
} else {
return $this->render('index', ['info' => '<h3>Ваши личные данные не заненсены в базу.</h3>']);
}
}
/**
* Finds the Product model based on its primary key value.
* If the model is not found, a 404 HTTP exception will be thrown.

View File

@ -0,0 +1,27 @@
<?php
use asmoday74\ckeditor5\EditorClassic;
use yii\helpers\Html;
use yii\widgets\ActiveForm;
use yii\helpers\Url;
/* @var $this yii\web\View */
/* @var $model */
$this->title = 'Резюме';
?>
<div class="user-card-view">
<h1>Резюме</h1>
<?php $form = ActiveForm::begin(['action' => Url::base(true)]); ?>
<?= $form->field($model, 'vc_text')->widget(EditorClassic::className(), [
'clientOptions' => [
'language' => 'ru',
]
]); ?>
<div class="form-group">
<?= Html::submitButton('<i class="fas fa-save"></i> Save', ['class' => 'btn btn-success']) ?>
<?= Html::a('<i class="fas fa-long-arrow-alt-left"></i> Back', Url::base(true), ['class' => 'btn btn-primary', 'style' => 'float: right']) ?>
</div>
<?php $form = ActiveForm::end(); ?>
</div>

View File

@ -1,7 +1,9 @@
<?php
use asmoday74\ckeditor5\EditorClassic;
use yii\grid\GridView;
use yii\helpers\Html;
use yii\widgets\ActiveForm;
use yii\widgets\DetailView;
/* @var $this yii\web\View */
@ -17,7 +19,8 @@ $this->title = 'Профиль';
<h3>Личная информация</h3>
<?php
echo Html::a('Изменить профиль', ['/card/user-card/update'], ['class' => 'btn btn-success'])
. '&nbsp' . Html::a('Изменить пароль', ['/card/user-card/password'], ['class' => 'btn btn-success']) . '<br><br>';
. '&nbsp' . Html::a('Изменить пароль', ['/card/user-card/password'], ['class' => 'btn btn-success'])
. '&nbsp' . Html::a('Изменить резюме', ['/card/user-card/resume'], ['class' => 'btn btn-success']). '<br><br>';
echo DetailView::widget([
'model' => $model,
@ -67,4 +70,5 @@ $this->title = 'Профиль';
],
],
]); ?>
</div>

View File

@ -8,6 +8,8 @@ use yii\widgets\ActiveForm;
/* @var $this yii\web\View */
/* @var $model common\models\Reports */
/* @var $form yii\widgets\ActiveForm */
$this->registerCss('.list-cell__task{width:73%}')
?>
<div class="reports-form">
@ -26,6 +28,7 @@ use yii\widgets\ActiveForm;
echo '<b>Дата заполнения отчета:</b>';
echo DatePicker::widget([
'model' => $model,
'language' => 'ru',
'attribute' => 'created_at',
'options' => [],
'pluginOptions' => [
@ -48,7 +51,16 @@ use yii\widgets\ActiveForm;
'title' => 'Кол-во часов',
'options' => [
'type' => 'number',
'style' => 'width:100px'
'min' => '0'
],
],
[
'name' => 'minutes_spent',
'title' => 'Кол-во минут',
'options' => [
'type' => 'number',
'min' => '0',
'max' => '59'
],
],
],

View File

@ -34,7 +34,7 @@ $this->params['breadcrumbs'][] = $this->title;
if ($model->task) {
$i = 1;
foreach ($model->task as $task) {
$text .= "<p>$i. ($task->hours_spent ч.) $task->task</p>";
$text .= "<p>$i. ($task->hours_spent ч., $task->minutes_spent мин.) $task->task</p>";
$i++;
}
}

View File

@ -39,7 +39,7 @@ $this->params['breadcrumbs'][] = $this->title;
if ($model->task) {
$i = 1;
foreach ($model->task as $task) {
$text .= "<p>$i. ($task->hours_spent ч.) $task->task</p>";
$text .= "<p>$i. ($task->hours_spent ч., $task->minutes_spent мин.) $task->task</p>";
$i++;
}
}