diff --git a/src/components/panels/RendersSummaryChartTrait.php b/src/components/panels/RendersSummaryChartTrait.php index 83ef4bd4..9334dc72 100644 --- a/src/components/panels/RendersSummaryChartTrait.php +++ b/src/components/panels/RendersSummaryChartTrait.php @@ -31,21 +31,31 @@ protected function getChartModel() * * @return array */ - protected function getChartData() + protected function getChartData($start = null, $end = null) { //initialise defaults (0 entries) for each day $defaults = []; - $startDate = strtotime('-6 days'); - foreach (range(-6, 0) as $day) { - $defaults[date('D: Y-m-d', strtotime($day . 'days'))] = 0; + if(!$start && !$end) { + $startDate = date('Y-m-d 00:00:00', strtotime('-6 days')); + $endDate = date('Y-m-d 23:59:59'); + foreach (range(-6, 0) as $day) { + $defaults[date('D: Y-m-d', strtotime($day . 'days'))] = 0; + } + } else { + $startDate = date('Y-m-d 00:00:00', strtotime($start)); + $endDate = date('Y-m-d 23:59:59', strtotime($end)); + $days = round(((strtotime($endDate) - strtotime($startDate))/ (60 * 60 * 24))-1); + foreach (range(0, $days) as $day) { + $defaults[date('D: Y-m-d', strtotime($startDate.'+' .$day . 'days'))] = 0; + } } $panelModel = $this->getChartModel(); $results = $panelModel::find() ->select(["COUNT(DISTINCT id) as count", "created AS day"]) ->where(['between', 'created', - date('Y-m-d 00:00:00', $startDate), - date('Y-m-d 23:59:59')]) + $startDate, + $endDate]) ->groupBy("created")->indexBy('day')->column(); // replace defaults with data from db where available diff --git a/src/controllers/DefaultController.php b/src/controllers/DefaultController.php index b53dcd15..447b06f0 100644 --- a/src/controllers/DefaultController.php +++ b/src/controllers/DefaultController.php @@ -5,6 +5,8 @@ use bedezign\yii2\audit\components\panels\RendersSummaryChartTrait; use bedezign\yii2\audit\components\web\Controller; use bedezign\yii2\audit\models\AuditEntry; +use bedezign\yii2\audit\models\AuditEntrySearch; +use bedezign\yii2\audit\models\AuditTrailSearch; use Yii; /** @@ -21,8 +23,15 @@ class DefaultController extends Controller */ public function actionIndex() { - $chartData = $this->getChartData(); - return $this->render('index', ['chartData' => $chartData]); + $startDate = $endDate = null; + $searchModel = new AuditEntrySearch(); + if(isset(Yii::$app->request->queryParams['AuditEntrySearch'])){ + $startDate = Yii::$app->request->queryParams['AuditEntrySearch']['start_date']; + $endDate = Yii::$app->request->queryParams['AuditEntrySearch']['end_date']; + } + $chartData = $this->getChartData($startDate, $endDate); + $searchTrailModel = new AuditTrailSearch(); + return $this->render('index', ['model' => $searchModel, 'chartData' => $chartData, 'trailModel' => $searchTrailModel]); } protected function getChartModel() diff --git a/src/models/AuditEntrySearch.php b/src/models/AuditEntrySearch.php index 69e8ae08..16e71658 100644 --- a/src/models/AuditEntrySearch.php +++ b/src/models/AuditEntrySearch.php @@ -13,6 +13,7 @@ */ class AuditEntrySearch extends AuditEntry { + public $start_date, $end_date; /** * @return array */ @@ -20,7 +21,9 @@ public function rules() { // only fields in rules() are searchable return [ - [['id', 'user_id', 'ip', 'created', 'duration', 'memory_max', 'route', 'request_method', 'ajax'], 'safe'], + [['id', 'user_id', 'ip', 'created', 'duration', 'memory_max', 'route', 'request_method', 'ajax', 'start_date', 'end_date'], 'safe'], + ['start_date', 'validateDate'], + ['end_date', 'validateDate'] ]; } @@ -39,7 +42,9 @@ public function scenarios() */ public function search($params) { - $query = AuditEntry::find()->where(['NOT LIKE', 'route', 'site/login']); + $query = AuditEntry::find() + ->where(['NOT LIKE', 'route', 'site/login']) + ->andWhere(['NOT LIKE', 'request_method', 'CLI']); $dataProvider = new ActiveDataProvider([ 'query' => $query, @@ -103,6 +108,15 @@ public function searchAccessLog($params) return $dataProvider; } + public function validateDate($attribute) + { + $dateTime = DateTime::createFromFormat('Y/m/d', $this->$attribute); + $errors = DateTime::getLastErrors(); + if (!empty($errors['warning_count'])) { + $this->addError($attribute, 'Invalid date'); + } + } + /** * @return array */ @@ -125,6 +139,7 @@ static public function methodFilter() $methods = AuditEntry::getDb()->cache(function () { return AuditEntry::find()->distinct(true) ->select('request_method')->where(['is not', 'request_method', null]) + ->where(['NOT LIKE', 'request_method', 'CLI']) ->groupBy('request_method')->orderBy('request_method ASC')->column(); }, 240); return array_combine($methods, $methods); diff --git a/src/models/AuditTrailSearch.php b/src/models/AuditTrailSearch.php index b2391cfb..9495f841 100644 --- a/src/models/AuditTrailSearch.php +++ b/src/models/AuditTrailSearch.php @@ -2,7 +2,7 @@ namespace bedezign\yii2\audit\models; - +use bedezign\yii2\audit\Audit; use yii\base\Model; use yii\data\ActiveDataProvider; @@ -12,6 +12,7 @@ */ class AuditTrailSearch extends AuditTrail { + public $start_date, $end_date; /** * @return array */ @@ -19,7 +20,7 @@ public function rules() { // Note: The model is used by both the entry and the trail index pages, hence the separate use of `id` and `entry_id` return [ - [['id', 'user_id', 'entry_id', 'action', 'model', 'model_id', 'field', 'created'], 'safe'], + [['id', 'user_id', 'entry_id', 'action', 'model', 'model_id', 'field', 'created', 'start_date', 'end_date'], 'safe'], ]; } @@ -56,13 +57,14 @@ public function search($params, $query = null) } // adjust the query by adding the filters - $userId = $this->user_id; - if (strlen($this->user_id)) - $userId = intval($this->user_id) ?: 0; + // $userId = $this->user_id; + // if (strlen($this->user_id)) + // $userId = intval($this->user_id) ?: 0; $query->andFilterWhere(['id' => $this->id]); + $this->filterUserId($this->user_id, $query); $query->andFilterWhere(['entry_id' => $this->entry_id]); - $query->andFilterWhere(['user_id' => $userId]); + // $query->andFilterWhere(['user_id' => $userId]); $query->andFilterWhere(['action' => $this->action]); $query->andFilterWhere(['like', 'model', $this->model]); $query->andFilterWhere(['model_id' => $this->model_id]); @@ -87,4 +89,20 @@ static public function actionFilter() 'action' ); } + + /** + * @param $userId + * @param ActiveQuery $query + */ + protected function filterUserId($userId, $query) + { + if (strlen($userId)) { + if (!is_numeric($userId) && $callback = Audit::getInstance()->userFilterCallback) { + $userId = call_user_func($callback, $userId); + } else { + $userId = intval($userId) ?: 0; + } + $query->andWhere(['user_id' => $userId]); + } + } } diff --git a/src/panels/TrailPanel.php b/src/panels/TrailPanel.php index 32c44589..d28a4361 100644 --- a/src/panels/TrailPanel.php +++ b/src/panels/TrailPanel.php @@ -80,11 +80,17 @@ protected function getChartModel() /** * @inheritdoc */ - public function getChart() + public function getChart($request = null) { + $start = $end = null; + if($request){ + $start = Yii::$app->request->queryParams['AuditTrailSearch']['start_date']; + $end = Yii::$app->request->queryParams['AuditTrailSearch']['end_date']; + } + return \Yii::$app->view->render('panels/trail/chart', [ - 'panel' => $this, - 'chartData' => $this->getChartData() + 'start' => $start, + 'end' => $end, ]); } diff --git a/src/views/default/index.php b/src/views/default/index.php index b559c2b9..1862c28f 100644 --- a/src/views/default/index.php +++ b/src/views/default/index.php @@ -4,11 +4,13 @@ use bedezign\yii2\audit\components\panels\Panel; use dosamigos\chartjs\ChartJs; use yii\helpers\Html; +use yii\widgets\ActiveForm; +use yii\web\View; /* @var $this yii\web\View */ /* @var $dataProvider yii\data\ActiveDataProvider */ -$this->title = Yii::t('audit', 'Audit Module'); +$this->title = Yii::t('audit', 'Summary'); $this->params['breadcrumbs'][] = $this->title; $this->registerCss('canvas {width: 100% !important;height: 400px;}'); @@ -19,8 +21,35 @@
-

+ 'entryform', + 'action' => [$this->context->action->id], + 'method' => 'get', + 'options' => [ + 'class' => 'form-inline' + ], + ]); ?> + field($model, 'start_date', ['inputOptions' => ['autofocus' => 'autofocus', 'class' => 'form-control', 'style' => 'margin-right: 10px;']]) + ->textInput()->textInput(['placeholder' => "Start Date"]) + ->label(false) + ?> + + field($model, 'end_date', + ['inputOptions' => ['autofocus' => 'autofocus', 'class' => 'form-control', 'style' => 'margin-right: 10px;']]) + ->textInput()->textInput(['placeholder' => "End Date"]) + ->label(false) + ?> + + + 'btn btn-primary', 'style' => 'margin-top: -10px']) ?> + + +
+ +
+

+
panels as $panel) { /** @var Panel $panel */ - $chart = $panel->getChart(); + if($panel->getName() == 'Trails'){ + $request = null; + if(isset(Yii::$app->request->queryParams['AuditTrailSearch'])){ + $request = Yii::$app->request->queryParams['AuditTrailSearch']; + } + $chart = $panel->getChart($request); + } else { + $chart = $panel->getChart(); + } + if (!$chart) { continue; } $indexUrl = $panel->getIndexUrl(); ?> -
-

getName(), $indexUrl) : $panel->getName(); ?>

+
+ getName(); + if($panel->getName() == 'Trails'){ + $title = Yii::t('audit', 'Database Log'); + } + ?> +

+ 'trailform', + 'action' => [$this->context->action->id], + 'method' => 'get', + 'options' => [ + 'class' => 'form-inline' + ], + ]); ?> + field($trailModel, 'start_date', ['inputOptions' => ['autofocus' => 'autofocus', 'class' => 'form-control', 'style' => 'margin-right: 10px;']]) + ->textInput()->textInput(['placeholder' => "Start Date"]) + ->label(false) + ?> + + field($trailModel, 'end_date', + ['inputOptions' => ['autofocus' => 'autofocus', 'class' => 'form-control', 'style' => 'margin-right: 10px;']]) + ->textInput()->textInput(['placeholder' => "End Date"]) + ->label(false) + ?> + + + 'btn btn-primary', 'style' => 'margin-top: -10px']) ?> + +
@@ -71,3 +139,4 @@
+ diff --git a/src/views/default/panels/trail/chart.php b/src/views/default/panels/trail/chart.php index 994fd6b0..e8619450 100644 --- a/src/views/default/panels/trail/chart.php +++ b/src/views/default/panels/trail/chart.php @@ -6,45 +6,56 @@ use dosamigos\chartjs\ChartJs; //initialise defaults (0 entries) for each day +// dd($chartData); $defaults = []; -$startDate = strtotime('-6 days'); -foreach (range(-6, 0) as $day) { - $defaults[date('D: Y-m-d', strtotime($day . 'days'))] = 0; +if(!$start && !$end) { + $startDate = date('Y-m-d 00:00:00', strtotime('-6 days')); + $endDate = date('Y-m-d 23:59:59'); + foreach (range(-6, 0) as $day) { + $defaults[date('D: Y-m-d', strtotime($day . 'days'))] = 0; + } +} else { + $startDate = date('Y-m-d 00:00:00', strtotime($start)); + $endDate = date('Y-m-d 23:59:59', strtotime($end)); + $days = round(((strtotime($endDate) - strtotime($startDate))/ (60 * 60 * 24))-1); + foreach (range(0, $days) as $day) { + $defaults[date('D: Y-m-d', strtotime($startDate.'+' .$day . 'days'))] = 0; + } } $results = AuditTrail::find() ->select(["COUNT(DISTINCT id) as count", "created AS day"]) ->where(['between', 'created', - date('Y-m-d 00:00:00', $startDate), - date('Y-m-d 23:59:59')]) + $startDate, + $endDate]) ->groupBy("created")->indexBy('day')->column(); // format dates properly -$formattedData = []; foreach ($results as $date => $count) { $date = date('D: Y-m-d', strtotime($date)); - $formattedData[$date] = $count; + $defaults[$date] += $count; } -$results = $formattedData; - -// replace defaults with data from db where available -$results = array_merge($defaults, $results); +// return $defaults; +// dd($defaults); echo ChartJs::widget([ 'type' => 'bar', + 'options' => [ + 'height' => '400', + ], 'clientOptions' => [ 'legend' => ['display' => false], 'tooltips' => ['enabled' => false], ], 'data' => [ - 'labels' => array_keys($chartData), + 'labels' => array_keys($defaults), 'datasets' => [ [ - 'fillColor' => 'rgba(151,187,205,0.5)', - 'strokeColor' => 'rgba(151,187,205,1)', - 'pointColor' => 'rgba(151,187,205,1)', + 'fillColor' => 'rgba(255, 99, 71, 0.8)', + 'strokeColor' => 'rgba(255, 99, 71, 0.8)', + 'pointColor' => 'rgba(255, 99, 71, 0.8)', 'pointStrokeColor' => '#fff', - 'data' => array_values($chartData), + 'data' => array_values($defaults), ], ], ] diff --git a/src/views/entry/index.php b/src/views/entry/index.php index 13afc47e..f8391970 100644 --- a/src/views/entry/index.php +++ b/src/views/entry/index.php @@ -9,7 +9,7 @@ /* @var $this yii\web\View */ /* @var $dataProvider yii\data\ActiveDataProvider */ -$this->title = Yii::t('audit', 'Entries'); +$this->title = Yii::t('audit', 'Activity Log'); $this->params['breadcrumbs'][] = ['label' => Yii::t('audit', 'Audit'), 'url' => ['default/index']]; $this->params['breadcrumbs'][] = $this->title; ?> diff --git a/src/views/layouts/main.php b/src/views/layouts/main.php index d75d81e6..a8f6a27f 100644 --- a/src/views/layouts/main.php +++ b/src/views/layouts/main.php @@ -36,8 +36,8 @@ ]); $items = [ - ['label' => Yii::t('audit', 'Entries'), 'url' => ['entry/index']], ['label' => Yii::t('audit', 'Access Log'), 'url' => ['access-log/index']], + ['label' => Yii::t('audit', 'Activity Log'), 'url' => ['entry/index']], ]; foreach (Audit::getInstance()->panels as $panel) { /** @var Panel $panel */ @@ -45,7 +45,11 @@ if (!$indexUrl) { continue; } - $items[] = ['label' => $panel->getName(), 'url' => $indexUrl]; + $label = $panel->getName(); + if($panel->getName() == 'Trails'){ + $label = Yii::t('audit', 'Database Log'); + } + $items[] = ['label' => $label, 'url' => $indexUrl]; } echo WebHelper::bootstrap('Nav', 'widget', [ @@ -54,7 +58,7 @@ ]); echo WebHelper::bootstrap('Nav', 'widget', [ 'items' => [ - ['label' => Yii::$app->name, 'url' => Yii::$app->getHomeUrl()], + ['label' => 'Admin Panel', 'url' => Yii::$app->getHomeUrl()], ], 'options' => ['class' => 'navbar-nav navbar-right'], ]); diff --git a/src/views/trail/index.php b/src/views/trail/index.php index a193b177..f0029140 100644 --- a/src/views/trail/index.php +++ b/src/views/trail/index.php @@ -10,7 +10,7 @@ /* @var $this yii\web\View */ /* @var $dataProvider yii\data\ActiveDataProvider */ -$this->title = Yii::t('audit', 'Trails'); +$this->title = Yii::t('audit', 'Database Log'); $this->params['breadcrumbs'][] = ['label' => Yii::t('audit', 'Audit'), 'url' => ['default/index']]; $this->params['breadcrumbs'][] = $this->title; ?> @@ -33,8 +33,9 @@ 'format' => 'raw', ], [ + 'attribute' => 'user_id', - 'label' => Yii::t('audit', 'User ID'), + 'label' => Yii::t('audit', 'User'), 'class' => 'yii\grid\DataColumn', 'value' => function ($data) { return Audit::getInstance()->getUserIdentifier($data->user_id);