forked from Alex/Pterodactyl-Panel
admin(ui): display dynamic user information on sidebar
This commit is contained in:
parent
9eed88b430
commit
2352ef0369
@ -25,9 +25,11 @@ class VersionController extends ApplicationApiController
|
||||
}
|
||||
|
||||
/**
|
||||
* ?
|
||||
* Returns version information.
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function __invoke()
|
||||
public function __invoke(): JsonResponse
|
||||
{
|
||||
return new JsonResponse($this->softwareVersionService->getVersionData());
|
||||
}
|
||||
|
@ -168,9 +168,13 @@ class User extends Model implements
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function toVueObject(): array
|
||||
public function toReactObject(): array
|
||||
{
|
||||
return (new Collection($this->toArray()))->except(['id', 'external_id'])->toArray();
|
||||
$object = (new Collection($this->toArray()))->except(['id', 'external_id'])->toArray();
|
||||
$object['avatar_url'] = $this->avatarURL();
|
||||
$object['role_name'] = $this->roleName();
|
||||
|
||||
return $object;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -203,6 +207,26 @@ class User extends Model implements
|
||||
return trim($this->name_first . ' ' . $this->name_last);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get's the avatar url for the user.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function avatarURL(): string
|
||||
{
|
||||
return 'https://www.gravatar.com/avatar/' . md5($this->email) . '.jpg';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get's the name of the role assigned to a user.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function roleName():? string
|
||||
{
|
||||
return $this->root_admin ? 'Super Administrator' : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all servers that a user owns.
|
||||
*
|
||||
|
@ -20,12 +20,12 @@ abstract class BaseTransformer extends TransformerAbstract
|
||||
/**
|
||||
* @var \Pterodactyl\Models\ApiKey
|
||||
*/
|
||||
private $key;
|
||||
private ApiKey $key;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $rootAdmin;
|
||||
private bool $rootAdmin;
|
||||
|
||||
/**
|
||||
* Return the resource name for the JSONAPI output.
|
||||
|
@ -43,11 +43,10 @@ class UserTransformer extends BaseTransformer
|
||||
'language' => $model->language,
|
||||
'root_admin' => (bool) $model->root_admin,
|
||||
'2fa' => (bool) $model->use_totp,
|
||||
'avatar_url' => 'https://www.gravatar.com/avatar/' . md5($model->email) . '.jpg?s=40',
|
||||
'role_name' => $model->root_admin ? 'Super Administrator' : null,
|
||||
'avatar_url' => $model->avatarURL(),
|
||||
'role_name' => $model->roleName(),
|
||||
'created_at' => $this->formatTimestamp($model->created_at),
|
||||
'updated_at' => $this->formatTimestamp($model->updated_at),
|
||||
'avatar'
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -24,9 +24,13 @@ interface ExtendedWindow extends Window {
|
||||
username: string;
|
||||
email: string;
|
||||
/* eslint-disable camelcase */
|
||||
name_first: string;
|
||||
name_last: string;
|
||||
root_admin: boolean;
|
||||
use_totp: boolean;
|
||||
language: string;
|
||||
avatar_url: string;
|
||||
role_name: string;
|
||||
updated_at: string;
|
||||
created_at: string;
|
||||
/* eslint-enable camelcase */
|
||||
@ -52,9 +56,13 @@ const App = () => {
|
||||
uuid: PterodactylUser.uuid,
|
||||
username: PterodactylUser.username,
|
||||
email: PterodactylUser.email,
|
||||
firstName: PterodactylUser.name_first,
|
||||
lastName: PterodactylUser.name_last,
|
||||
language: PterodactylUser.language,
|
||||
rootAdmin: PterodactylUser.root_admin,
|
||||
useTotp: PterodactylUser.use_totp,
|
||||
avatarURL: PterodactylUser.avatar_url,
|
||||
roleName: PterodactylUser.role_name,
|
||||
createdAt: new Date(PterodactylUser.created_at),
|
||||
updatedAt: new Date(PterodactylUser.updated_at),
|
||||
});
|
||||
|
@ -117,7 +117,7 @@ const UsersContainer = () => {
|
||||
<NavLink to={`${match.url}/${user.id}`}>
|
||||
<div css={tw`flex items-center`}>
|
||||
<div css={tw`flex-shrink-0 h-10 w-10`}>
|
||||
<img css={tw`h-10 w-10 rounded-full`} alt="" src={user.avatarURL}/>
|
||||
<img css={tw`h-10 w-10 rounded-full`} alt="" src={user.avatarURL + '?s=40'}/>
|
||||
</div>
|
||||
|
||||
<div css={tw`ml-4`}>
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { useState } from 'react';
|
||||
import { NavLink, Route, RouteComponentProps, Switch } from 'react-router-dom';
|
||||
import { useStoreState } from 'easy-peasy';
|
||||
import { State, useStoreState } from 'easy-peasy';
|
||||
import tw from 'twin.macro';
|
||||
import styled from 'styled-components/macro';
|
||||
import { ApplicationStore } from '@/state';
|
||||
@ -88,7 +88,9 @@ const Sidebar = styled.div<{ collapsed?: boolean }>`
|
||||
`;
|
||||
|
||||
const AdminRouter = ({ location, match }: RouteComponentProps) => {
|
||||
const name = useStoreState((state: ApplicationStore) => state.settings.data!.name);
|
||||
const user = useStoreState((state: State<ApplicationStore>) => state.user.data);
|
||||
const applicationName = useStoreState((state: ApplicationStore) => state.settings.data!.name);
|
||||
|
||||
const [ collapsed, setCollapsed ] = useState<boolean>();
|
||||
|
||||
return (
|
||||
@ -96,7 +98,7 @@ const AdminRouter = ({ location, match }: RouteComponentProps) => {
|
||||
<Sidebar collapsed={collapsed}>
|
||||
<div className={'header'} onClick={ () => { setCollapsed(!collapsed); } }>
|
||||
{ !collapsed ?
|
||||
<h1 css={tw`text-2xl text-neutral-50 whitespace-nowrap`}>{name}</h1>
|
||||
<h1 css={tw`text-2xl text-neutral-50 whitespace-nowrap`}>{applicationName}</h1>
|
||||
:
|
||||
<img src={'/favicons/android-icon-48x48.png'} alt={'Pterodactyl Icon'} />
|
||||
}
|
||||
@ -162,11 +164,11 @@ const AdminRouter = ({ location, match }: RouteComponentProps) => {
|
||||
</NavLink>
|
||||
|
||||
<div className={'user'}>
|
||||
<img src={'https://www.gravatar.com/avatar/78a6a270ec41715a8ae96c02b8961f9e?s=64'} alt="Profile Picture" css={tw`h-10 w-10 rounded-full select-none`} />
|
||||
<img src={user !== undefined ? user.avatarURL + '?s=64' : ''} alt="Profile Picture" css={tw`h-10 w-10 rounded-full select-none`} />
|
||||
|
||||
<div css={tw`flex flex-col ml-4`}>
|
||||
<span css={tw`font-header font-medium text-sm text-neutral-50 whitespace-nowrap leading-tight select-none`}>Matthew Penner</span>
|
||||
<span css={tw`font-header font-normal text-xs text-neutral-300 whitespace-nowrap leading-tight select-none`}>Super Administrator</span>
|
||||
<span css={tw`font-header font-medium text-sm text-neutral-50 whitespace-nowrap leading-tight select-none`}>{user?.firstName} {user?.lastName}</span>
|
||||
<span css={tw`font-header font-normal text-xs text-neutral-300 whitespace-nowrap leading-tight select-none`}>{user?.roleName}</span>
|
||||
</div>
|
||||
|
||||
<NavLink to={'/auth/logout'} css={tw`h-8 w-8 flex items-center justify-center text-neutral-300 hover:text-red-400 hover:bg-neutral-800 rounded ml-auto transition-all duration-100`}>
|
||||
|
@ -5,9 +5,13 @@ export interface UserData {
|
||||
uuid: string;
|
||||
username: string;
|
||||
email: string;
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
language: string;
|
||||
rootAdmin: boolean;
|
||||
useTotp: boolean;
|
||||
avatarURL: string;
|
||||
roleName: string;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
}
|
||||
@ -21,6 +25,7 @@ export interface UserStore {
|
||||
|
||||
const user: UserStore = {
|
||||
data: undefined,
|
||||
|
||||
setUserData: action((state, payload) => {
|
||||
state.data = payload;
|
||||
}),
|
||||
|
@ -21,7 +21,7 @@
|
||||
@section('user-data')
|
||||
@if(!is_null(Auth::user()))
|
||||
<script>
|
||||
window.PterodactylUser = {!! json_encode(Auth::user()->toVueObject()) !!};
|
||||
window.PterodactylUser = {!! json_encode(Auth::user()->toReactObject()) !!};
|
||||
</script>
|
||||
@endif
|
||||
@if(!empty($siteConfiguration))
|
||||
|
Loading…
Reference in New Issue
Block a user