diff --git a/app/Transformers/Api/Client/ActivityLogTransformer.php b/app/Transformers/Api/Client/ActivityLogTransformer.php index 077b11b7f..e6ff72a6f 100644 --- a/app/Transformers/Api/Client/ActivityLogTransformer.php +++ b/app/Transformers/Api/Client/ActivityLogTransformer.php @@ -21,7 +21,8 @@ class ActivityLogTransformer extends BaseClientTransformer 'event' => $model->event, 'ip' => $model->ip, 'description' => $model->description, - 'properties' => $model->properties, + 'properties' => $model->properties ? $model->properties->toArray() : [], + 'has_additional_metadata' => $this->hasAdditionalMetadata($model), 'timestamp' => $model->timestamp->toIso8601String(), ]; } @@ -34,4 +35,32 @@ class ActivityLogTransformer extends BaseClientTransformer return $this->item($model->actor, $this->makeTransformer(UserTransformer::class), User::RESOURCE_NAME); } + + /** + * Determines if there are any log properties that we've not already exposed + * in the response language string and that are not just the IP address or + * the browser useragent. + * + * This is used by the front-end to selectively display an "additional metadata" + * button that is pointless if there is nothing the user can't already see from + * the event description. + */ + protected function hasAdditionalMetadata(ActivityLog $model): bool + { + if (is_null($model->properties) || $model->properties->isEmpty()) { + return false; + } + + $str = trans('activity.' . str_replace(':', '.', $model->event)); + preg_match_all('/:(?[\w-]+)(?:\W?|$)/', $str, $matches); + + $exclude = array_merge($matches['key'], ['ip', 'useragent']); + foreach ($model->properties->keys() as $key) { + if (!in_array($key, $exclude, true)) { + return true; + } + } + + return false; + } } diff --git a/resources/scripts/api/definitions/user/models.d.ts b/resources/scripts/api/definitions/user/models.d.ts index 1f26683aa..a46d1e918 100644 --- a/resources/scripts/api/definitions/user/models.d.ts +++ b/resources/scripts/api/definitions/user/models.d.ts @@ -25,6 +25,7 @@ interface ActivityLog extends Model<'actor'> { ip: string; description: string | null; properties: Record; + hasAdditionalMetadata: boolean; timestamp: Date; relationships: { actor: User | null; diff --git a/resources/scripts/api/definitions/user/transformers.ts b/resources/scripts/api/definitions/user/transformers.ts index 3941d539e..128480266 100644 --- a/resources/scripts/api/definitions/user/transformers.ts +++ b/resources/scripts/api/definitions/user/transformers.ts @@ -36,6 +36,7 @@ export default class Transformers { ip: attributes.ip, description: attributes.description, properties: attributes.properties, + hasAdditionalMetadata: attributes.has_additional_metadata ?? false, timestamp: new Date(attributes.timestamp), relationships: { actor: transform(actor as FractalResponseData, this.toUser, null), diff --git a/resources/scripts/components/elements/activity/ActivityLogEntry.tsx b/resources/scripts/components/elements/activity/ActivityLogEntry.tsx index 942f9551d..3d9b58702 100644 --- a/resources/scripts/components/elements/activity/ActivityLogEntry.tsx +++ b/resources/scripts/components/elements/activity/ActivityLogEntry.tsx @@ -73,7 +73,7 @@ export default ({ activity, children }: Props) => { - + {activity.hasAdditionalMetadata && } ); diff --git a/resources/scripts/components/elements/activity/ActivityLogMetaButton.tsx b/resources/scripts/components/elements/activity/ActivityLogMetaButton.tsx index e893a5008..9b894562c 100644 --- a/resources/scripts/components/elements/activity/ActivityLogMetaButton.tsx +++ b/resources/scripts/components/elements/activity/ActivityLogMetaButton.tsx @@ -1,5 +1,4 @@ import React, { useState } from 'react'; -import { isEmptyObject } from '@/helpers'; import { ClipboardListIcon } from '@heroicons/react/outline'; import { Dialog } from '@/components/elements/dialog'; import { Button } from '@/components/elements/button/index'; @@ -7,10 +6,6 @@ import { Button } from '@/components/elements/button/index'; export default ({ meta }: { meta: Record }) => { const [ open, setOpen ] = useState(false); - if (isEmptyObject(meta)) { - return null; - } - return (