From 91d46041b21d441d0de570845f7adfacc95184e7 Mon Sep 17 00:00:00 2001 From: Mat Fish Date: Sun, 18 Jun 2023 11:04:58 +0300 Subject: [PATCH] auto label unlabelled actions --- CHANGELOG.md | 7 ++++++ README.md | 4 ++- src/controllers/ActionsController.php | 17 ++++++++++--- src/controllers/ActivityLogController.php | 30 ++++++++++++++++++++++- src/helpers/ActionSegmentsToLabel.php | 24 ++++++++++++++++++ src/services/Stats/Retrievers/Actions.php | 13 ++++++++-- 6 files changed, 87 insertions(+), 8 deletions(-) create mode 100644 src/helpers/ActionSegmentsToLabel.php diff --git a/CHANGELOG.md b/CHANGELOG.md index a18fe3c..e12a0cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Release Notes for Activity Log +## 1.5.0 - 2023-06-18 +### Fixed +- Do not load natively labeled actions on Actions page + +### Improved +- Auto label unlabeled actions on Actions filter and Actions widget + ## 1.4.2 - 2023-06-18 ### Fixed - Unicode for column url throws error when title is in Chinese [#9](https://github.com/matfish2/craft-activity-log/issues/9) diff --git a/README.md b/README.md index 41adf33..dc373e3 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,9 @@ return [ The `$this` object in this context will be an instance of the request class (`craft\web\Request`). Only requests satisfying the condition (returning `true`) will be recorded. -The user can also give labels to all recorded actions for ease of search. +Actions are automatically labelled using a naming convention. E.g ["fields","save-group"] will become "Fields Save Group". +This is relevant for the "Action" search dropdown on the Logs page and for the Actions widget on the Statistics page. +In addition the user can optionally override this convention by giving explicit labels to recorded actions under the Actions page. ![craft4 test_adminos_settings_activity-logs_actions_site=default](https://user-images.githubusercontent.com/1510460/190848960-05dc091f-fe01-4e96-ade1-aba8600b00a9.png) Requests can be viewed and filtered under the Activity Log page. diff --git a/src/controllers/ActionsController.php b/src/controllers/ActionsController.php index 5aa4ff4..8c36965 100644 --- a/src/controllers/ActionsController.php +++ b/src/controllers/ActionsController.php @@ -13,7 +13,10 @@ class ActionsController extends Controller { public function actionIndex() { - // 1. Get all actions (not-native) from actions table + // 1. Get all natively labelled actions in order to exclude from page + $native = ActivityLogAction::find()->where('native=1')->all(); + + // 2. Get all non-native actions from actions table in order to allow editing $actions1 = ActivityLogAction::find()->where('native=0')->all(); $actions1 = array_map(static function ($action) { return [ @@ -23,12 +26,18 @@ public function actionIndex() ]; }, $actions1); - $existingActions = array_map(static function ($action) { + // 3. Merge native and non-native actions in order to exclude from search in logs + $nonnative = array_map(static function ($action) { return "'" . $action['action'] . "'"; }, $actions1); + $native = array_map(static function ($action) { + return "'" . $action->action . "'"; + }, $native); + + $existingActions = array_merge($nonnative, $native); - // 2. Get all unlabeled actions from activity logs table + // 4. Get all unlabeled actions from activity logs table $existingActionsExp = count($existingActions) > 0 ? implode(',', $existingActions) : "'xxx'"; $actions2 = ActivityLog::find()->select('actionSegments') ->where('actionSegments is not null AND actionSegments not in (' . $existingActionsExp . ')') @@ -42,7 +51,7 @@ public function actionIndex() ]; }, $actions2); - // 3. merge 1 and 2 + // 5. merge actions from actions table with actions from logs table $actions = array_merge($actions1, $actions2); return $this->renderTemplate('activity-logs/actions', ['actions' => $actions]); diff --git a/src/controllers/ActivityLogController.php b/src/controllers/ActivityLogController.php index a8311b6..686a270 100644 --- a/src/controllers/ActivityLogController.php +++ b/src/controllers/ActivityLogController.php @@ -10,6 +10,8 @@ use craft\records\Site; use craft\web\assets\dashboard\DashboardAsset; use matfish\ActivityLog\ActivityLogAssetBundle; +use matfish\ActivityLog\helpers\ActionSegmentsToLabel; +use matfish\ActivityLog\records\ActivityLog; use matfish\ActivityLog\records\ActivityLogAction; use matfish\ActivityLog\records\ActivityLogWidget; use matfish\ActivityLog\services\Stats\WidgetsHandler; @@ -138,12 +140,38 @@ public function actionInitialData(): Response $res = [ 'sites' => Site::find()->select(['id', 'name'])->all(), 'svgPath' => $this->getSvgPath(), - 'actions' => ActivityLogAction::find()->all() + 'actions' => $this->getActionsList() ]; return $this->asJson($res); } + protected function getActionsList(): array + { + $labeled = ActivityLogAction::find()->all(); + $labeledArr = array_map(static function ($action) { + return "'" . $action['action'] . "'"; + }, $labeled); + + $labeledExp = count($labeledArr) > 0 ? implode(',', $labeledArr) : "'xxx'"; + + $unlabeled = ActivityLog::find()->select('actionSegments') + ->where('actionSegments is not null AND actionSegments not in (' . $labeledExp . ')') + ->groupBy('actionSegments')->all(); + + $unlabeled = array_map(/** + * @throws \JsonException + */ static function ($action) { + return [ + 'id' => null, + 'action' => $action->actionSegments, + 'label' => ActionSegmentsToLabel::convert($action->actionSegments) + ]; + }, $unlabeled); + + return array_merge($labeled, $unlabeled); + } + public function actionData(): Response { $res = (new VueTablesActivityLogRetriever())->retrieve(); diff --git a/src/helpers/ActionSegmentsToLabel.php b/src/helpers/ActionSegmentsToLabel.php new file mode 100644 index 0000000..2f39a24 --- /dev/null +++ b/src/helpers/ActionSegmentsToLabel.php @@ -0,0 +1,24 @@ +query() - ->select(['{{%activitylog_actions}}.[[label]] name', 'count(*) n']) + ->select(['IF({{%activitylog_actions}}.[[label]] IS NULL,0,1) has_label','IF({{%activitylog_actions}}.[[label]] IS NOT NULL,{{%activitylog_actions}}.[[label]],{{%activitylog}}.[[actionSegments]]) name', 'count(*) n']) ->andWhere('{{%activitylog}}.[[isAction]]=1') ->leftJoin('{{%users}}', '{{%users}}.[[id]]={{%activitylog}}.[[userId]]') - ->innerJoin('{{%activitylog_actions}}', '{{%activitylog_actions}}.[[action]]={{%activitylog}}.[[actionSegments]]') + ->leftJoin('{{%activitylog_actions}}', '{{%activitylog_actions}}.[[action]]={{%activitylog}}.[[actionSegments]]') ->orderBy('count(*) DESC') ->groupBy('[[actionSegments]]')->all(); + $res = array_map(static function($x) { + if ($x['has_label']==='0') { + $x['name'] = ActionSegmentsToLabel::convert($x['name']); + } + + return $x; + },$res); + $resWithOther = $this->groupOthers($res); return $this->toKeyValuePairs($resWithOther, 'name', 'n');