Abuse the translation engine to handle more of the formatting for us
This commit is contained in:
parent
b052d29a5f
commit
95de4c30fc
4 changed files with 94 additions and 51 deletions
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace Pterodactyl\Transformers\Api\Client;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
use Pterodactyl\Models\User;
|
||||
use Pterodactyl\Models\ActivityLog;
|
||||
|
||||
|
@ -22,7 +23,7 @@ class ActivityLogTransformer extends BaseClientTransformer
|
|||
'is_api' => !is_null($model->api_key_id),
|
||||
'ip' => $model->ip,
|
||||
'description' => $model->description,
|
||||
'properties' => $model->properties ? $model->properties->toArray() : [],
|
||||
'properties' => $this->properties($model),
|
||||
'has_additional_metadata' => $this->hasAdditionalMetadata($model),
|
||||
'timestamp' => $model->timestamp->toIso8601String(),
|
||||
];
|
||||
|
@ -37,6 +38,33 @@ class ActivityLogTransformer extends BaseClientTransformer
|
|||
return $this->item($model->actor, $this->makeTransformer(UserTransformer::class), User::RESOURCE_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms any array values in the properties into a countable field for easier
|
||||
* use within the translation outputs.
|
||||
*/
|
||||
protected function properties(ActivityLog $model): array
|
||||
{
|
||||
if (!$model->properties || $model->properties->isEmpty()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$properties = $model->properties
|
||||
->mapWithKeys(function ($value, $key) {
|
||||
if (!is_array($value)) {
|
||||
return [$key => $value];
|
||||
}
|
||||
|
||||
return [$key => $value, "{$key}_count" => count($value)];
|
||||
});
|
||||
|
||||
$keys = $properties->keys()->filter(fn ($key) => Str::endsWith($key, '_count'))->values();
|
||||
if ($keys->containsOneItem()) {
|
||||
$properties = $properties->merge(['count' => $properties->get($keys[0])])->except($keys[0]);
|
||||
}
|
||||
|
||||
return $properties->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
|
|
@ -15,20 +15,20 @@ return [
|
|||
'checkpoint' => 'Two-factor authentication requested',
|
||||
'recovery-token' => 'Used two-factor recovery token',
|
||||
'token' => 'Solved two-factor challenge',
|
||||
'ip-blocked' => 'Blocked request from unlisted IP address for <strong>:identifier</strong>',
|
||||
'ip-blocked' => 'Blocked request from unlisted IP address for :identifier',
|
||||
],
|
||||
'user' => [
|
||||
'account' => [
|
||||
'email-changed' => 'Changed email from <strong>:old</strong> to <strong>:new</strong>',
|
||||
'email-changed' => 'Changed email from :old to :new',
|
||||
'password-changed' => 'Changed password',
|
||||
],
|
||||
'api-key' => [
|
||||
'create' => 'Created new API key <strong>:identifier</strong>',
|
||||
'delete' => 'Deleted API key <strong>:identifier</strong>',
|
||||
'create' => 'Created new API key :identifier',
|
||||
'delete' => 'Deleted API key :identifier',
|
||||
],
|
||||
'ssh-key' => [
|
||||
'create' => 'Added SSH key <strong>:fingerprint</strong> to account',
|
||||
'delete' => 'Removed SSH key <strong>:fingerprint</strong> from account',
|
||||
'create' => 'Added SSH key :fingerprint to account',
|
||||
'delete' => 'Removed SSH key :fingerprint from account',
|
||||
],
|
||||
'two-factor' => [
|
||||
'create' => 'Enabled two-factor auth',
|
||||
|
@ -37,64 +37,66 @@ return [
|
|||
],
|
||||
'server' => [
|
||||
'backup' => [
|
||||
'download' => 'Downloaded the <strong>:name</strong> backup',
|
||||
'delete' => 'Deleted the <strong>:name</strong> backup',
|
||||
'restore' => 'Restored the <strong>:name</strong> backup (deleted files: :truncate)',
|
||||
'restore-complete' => 'Completed restoration of the <strong>:name</strong> backup',
|
||||
'restore-failed' => 'Failed to complete restoration of the <strong>:name</strong> backup',
|
||||
'start' => 'Started a new backup <strong>:name</strong>',
|
||||
'complete' => 'Marked the <strong>:name</strong> backup as complete',
|
||||
'fail' => 'Marked the <strong>:name</strong> backup as failed',
|
||||
'lock' => 'Locked the <strong>:name</strong> backup',
|
||||
'unlock' => 'Unlocked the <strong>:name</strong> backup',
|
||||
'download' => 'Downloaded the :name backup',
|
||||
'delete' => 'Deleted the :name backup',
|
||||
'restore' => 'Restored the :name backup (deleted files: :truncate)',
|
||||
'restore-complete' => 'Completed restoration of the :name backup',
|
||||
'restore-failed' => 'Failed to complete restoration of the :name backup',
|
||||
'start' => 'Started a new backup :name',
|
||||
'complete' => 'Marked the :name backup as complete',
|
||||
'fail' => 'Marked the :name backup as failed',
|
||||
'lock' => 'Locked the :name backup',
|
||||
'unlock' => 'Unlocked the :name backup',
|
||||
],
|
||||
'database' => [
|
||||
'create' => 'Created new database <strong>:name</strong>',
|
||||
'rotate-password' => 'Password rotated for database <strong>:name</strong>',
|
||||
'delete' => 'Deleted database <strong>:name</strong>',
|
||||
'create' => 'Created new database :name',
|
||||
'rotate-password' => 'Password rotated for database :name',
|
||||
'delete' => 'Deleted database :name',
|
||||
],
|
||||
'file' => [
|
||||
'compress' => 'Created new file archive of files in <strong>:directory</strong>',
|
||||
'read' => 'Viewed the contents of <strong>:file</strong>',
|
||||
'copy' => 'Created a copy of <strong>:file</strong>',
|
||||
'create-directory' => 'Created a new directory <strong>:name</strong> in <strong>:directory</strong>',
|
||||
'decompress' => 'Decompressed a file archive in <strong>:directory</strong>',
|
||||
'delete' => 'Deleted files in <strong>:directory</strong>',
|
||||
'download' => 'Downloaded <strong>:file</strong>',
|
||||
'pull' => 'Downloaded a remote file from :url to <strong>:directory</strong>',
|
||||
'rename' => 'Renamed files in <strong>:directory</strong>',
|
||||
'write' => 'Wrote new content to <strong>:file</strong>',
|
||||
'compress_one' => 'Compressed :directory/:file',
|
||||
'compress_other' => 'Compressed :count files in :directory',
|
||||
'read' => 'Viewed the contents of :file',
|
||||
'copy' => 'Created a copy of :file',
|
||||
'create-directory' => 'Created a new directory :name in :directory',
|
||||
'decompress' => 'Decompressed :files in :directory',
|
||||
'delete_one' => 'Deleted :directory/:files',
|
||||
'delete_other' => 'Deleted :count files in :directory',
|
||||
'download' => 'Downloaded :file',
|
||||
'pull' => 'Downloaded a remote file from :url to :directory',
|
||||
'rename' => 'Renamed files in :directory',
|
||||
'write' => 'Wrote new content to :file',
|
||||
'upload' => 'Began a file upload',
|
||||
],
|
||||
'allocation' => [
|
||||
'create' => 'Added <strong>:allocation</strong> to the server',
|
||||
'notes' => 'Updated the notes for <strong>:allocation</strong> from ":old" to ":new"',
|
||||
'primary' => 'Set <strong>:allocation</strong> as the primary server allocation',
|
||||
'delete' => 'Deleted the <strong>:allocation</strong> allocation',
|
||||
'create' => 'Added :allocation to the server',
|
||||
'notes' => 'Updated the notes for :allocation from ":old" to ":new"',
|
||||
'primary' => 'Set :allocation as the primary server allocation',
|
||||
'delete' => 'Deleted the :allocation allocation',
|
||||
],
|
||||
'schedule' => [
|
||||
'store' => 'Created the <strong>:name</strong> schedule',
|
||||
'update' => 'Updated the <strong>:name</strong> schedule',
|
||||
'execute' => 'Manually executed the <strong>:name</strong> schedule',
|
||||
'delete' => 'Deleted the <strong>:name</strong> schedule',
|
||||
'store' => 'Created the :name schedule',
|
||||
'update' => 'Updated the :name schedule',
|
||||
'execute' => 'Manually executed the :name schedule',
|
||||
'delete' => 'Deleted the :name schedule',
|
||||
],
|
||||
'task' => [
|
||||
'create' => 'Created a new ":action" task for the <strong>:name</strong> schedule',
|
||||
'update' => 'Updated the ":action" task for the <strong>:name</strong> schedule',
|
||||
'delete' => 'Deleted a task for the <strong>:name</strong> schedule',
|
||||
'create' => 'Created a new ":action" task for the :name schedule',
|
||||
'update' => 'Updated the ":action" task for the :name schedule',
|
||||
'delete' => 'Deleted a task for the :name schedule',
|
||||
],
|
||||
'settings' => [
|
||||
'rename' => 'Renamed the server from <strong>:old</strong> to <strong>:new</strong>',
|
||||
'rename' => 'Renamed the server from :old to :new',
|
||||
'reinstall' => 'Triggered a server reinstall',
|
||||
],
|
||||
'startup' => [
|
||||
'edit' => 'Edited the <strong>:variable</strong> startup variable for the server from ":old" to ":new"',
|
||||
'image' => 'Updated the Docker Image for the server from <strong>:old</strong> to <strong>:new</strong>',
|
||||
'edit' => 'Changed the :variable variable from ":old" to ":new"',
|
||||
'image' => 'Updated the Docker Image for the server from :old to :new',
|
||||
],
|
||||
'subuser' => [
|
||||
'create' => 'Added <strong>:email</strong> as a subuser',
|
||||
'update' => 'Updated the subuser permissions for <strong>:email</strong>',
|
||||
'delete' => 'Removed <strong>:email</strong> as a subuser',
|
||||
'create' => 'Added :email as a subuser',
|
||||
'update' => 'Updated the subuser permissions for :email',
|
||||
'delete' => 'Removed :email as a subuser',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
|
|
@ -27,6 +27,13 @@ export default ({ activity, children }: Props) => {
|
|||
return current.toString();
|
||||
};
|
||||
|
||||
const properties = Object.keys(activity.properties).reduce((obj, key) => ({
|
||||
...obj,
|
||||
[key]: key === 'count' || key.endsWith('_count')
|
||||
? activity.properties[key]
|
||||
: `<strong>${activity.properties[key]}</strong>`,
|
||||
}), {});
|
||||
|
||||
return (
|
||||
<div className={'grid grid-cols-10 py-4 border-b-2 border-gray-800 last:rounded-b last:border-0 group'}>
|
||||
<div className={'hidden sm:flex sm:col-span-1 items-center justify-center select-none'}>
|
||||
|
@ -60,10 +67,8 @@ export default ({ activity, children }: Props) => {
|
|||
{children}
|
||||
</div>
|
||||
</div>
|
||||
<p className={'mt-1 text-sm break-words line-clamp-2 pr-4'}>
|
||||
<Translate ns={'activity'} values={activity.properties}>
|
||||
{activity.event.replace(':', '.')}
|
||||
</Translate>
|
||||
<p className={style.description}>
|
||||
<Translate ns={'activity'} values={properties} i18nKey={activity.event.replace(':', '.')}/>
|
||||
</p>
|
||||
<div className={'mt-1 flex items-center text-sm'}>
|
||||
<Link
|
||||
|
|
|
@ -9,3 +9,11 @@
|
|||
@apply w-4 h-4;
|
||||
}
|
||||
}
|
||||
|
||||
.description {
|
||||
@apply mt-1 text-sm break-words line-clamp-2 pr-4;
|
||||
|
||||
& strong {
|
||||
@apply text-gray-50 font-semibold;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue