1
0
Fork 0
mirror of https://github.com/jellyfin/jellyfin-web synced 2025-03-30 19:56:21 +00:00

migrate User Profile Page

This commit is contained in:
grafixeyehero 2022-06-29 04:16:20 +03:00
parent d2df5830b5
commit ab02f210ca
7 changed files with 41 additions and 31 deletions

View file

@ -4,17 +4,20 @@ import UserPasswordForm from '../components/dashboard/users/UserPasswordForm';
import { getParameterByName } from '../utils/url';
import SectionTitleContainer from '../components/dashboard/elements/SectionTitleContainer';
import Page from '../components/Page';
import loading from '../components/loading/loading';
const UserPasswordPage: FunctionComponent = () => {
const userId = getParameterByName('userId');
const [ userName, setUserName ] = useState('');
const loadUser = useCallback(() => {
loading.show();
window.ApiClient.getUser(userId).then(function (user) {
if (!user.Name) {
throw new Error('Unexpected null user.Name');
}
setUserName(user.Name);
loading.hide();
});
}, [userId]);
useEffect(() => {

View file

@ -0,0 +1,200 @@
import { ImageType, UserDto } from '@thornbill/jellyfin-sdk/dist/generated-client';
import React, { FunctionComponent, useEffect, useState, useRef, useCallback } from 'react';
import Dashboard from '../utils/dashboard';
import globalize from '../scripts/globalize';
import LibraryMenu from '../scripts/libraryMenu';
import { appHost } from '../components/apphost';
import confirm from '../components/confirm/confirm';
import ButtonElement from '../components/dashboard/elements/ButtonElement';
import UserPasswordForm from '../components/dashboard/users/UserPasswordForm';
import loading from '../components/loading/loading';
import toast from '../components/toast/toast';
import { getParameterByName } from '../utils/url';
import Page from '../components/Page';
const UserProfilePage: FunctionComponent = () => {
const userId = getParameterByName('userId');
const [ userName, setUserName ] = useState('');
const element = useRef<HTMLDivElement>(null);
const reloadUser = useCallback(() => {
const page = element.current;
if (!page) {
console.error('Unexpected null reference');
return;
}
loading.show();
window.ApiClient.getUser(userId).then(function (user) {
if (!user.Name) {
throw new Error('Unexpected null user.Name');
}
if (!user.Id) {
throw new Error('Unexpected null user.Id');
}
setUserName(user.Name);
LibraryMenu.setTitle(user.Name);
let imageUrl = 'assets/img/avatar.png';
if (user.PrimaryImageTag) {
imageUrl = window.ApiClient.getUserImageUrl(user.Id, {
tag: user.PrimaryImageTag,
type: 'Primary'
});
}
const userImage = (page.querySelector('#image') as HTMLDivElement);
userImage.style.backgroundImage = 'url(' + imageUrl + ')';
Dashboard.getCurrentUser().then(function (loggedInUser: UserDto) {
if (!user.Policy) {
throw new Error('Unexpected null user.Policy');
}
if (user.PrimaryImageTag) {
(page.querySelector('#btnAddImage') as HTMLButtonElement).classList.add('hide');
(page.querySelector('#btnDeleteImage') as HTMLButtonElement).classList.remove('hide');
} else if (appHost.supports('fileinput') && (loggedInUser?.Policy?.IsAdministrator || user.Policy.EnableUserPreferenceAccess)) {
(page.querySelector('#btnDeleteImage') as HTMLButtonElement).classList.add('hide');
(page.querySelector('#btnAddImage') as HTMLButtonElement).classList.remove('hide');
}
});
loading.hide();
});
}, [userId]);
useEffect(() => {
const page = element.current;
if (!page) {
console.error('Unexpected null reference');
return;
}
reloadUser();
const onFileReaderError = (evt: ProgressEvent<FileReader>) => {
loading.hide();
switch (evt.target?.error?.code) {
case DOMException.NOT_FOUND_ERR:
toast(globalize.translate('FileNotFound'));
break;
case DOMException.ABORT_ERR:
onFileReaderAbort();
break;
default:
toast(globalize.translate('FileReadError'));
}
};
const onFileReaderAbort = () => {
loading.hide();
toast(globalize.translate('FileReadCancelled'));
};
const setFiles = (evt: Event) => {
const userImage = (page.querySelector('#image') as HTMLDivElement);
const target = evt.target as HTMLInputElement;
const file = (target.files as FileList)[0];
if (!file || !file.type.match('image.*')) {
return false;
}
const reader: FileReader = new FileReader();
reader.onerror = onFileReaderError;
reader.onabort = onFileReaderAbort;
reader.onload = () => {
userImage.style.backgroundImage = 'url(' + reader.result + ')';
window.ApiClient.uploadUserImage(userId, ImageType.Primary, file).then(function () {
loading.hide();
reloadUser();
});
};
reader.readAsDataURL(file);
};
(page.querySelector('#btnDeleteImage') as HTMLButtonElement).addEventListener('click', function () {
confirm(
globalize.translate('DeleteImageConfirmation'),
globalize.translate('DeleteImage')
).then(function () {
loading.show();
window.ApiClient.deleteUserImage(userId, ImageType.Primary).then(function () {
loading.hide();
reloadUser();
});
});
});
(page.querySelector('#btnAddImage') as HTMLButtonElement).addEventListener('click', function () {
const uploadImage = page.querySelector('#uploadImage') as HTMLInputElement;
uploadImage.value = '';
uploadImage.click();
});
(page.querySelector('#uploadImage') as HTMLInputElement).addEventListener('change', function (evt: Event) {
setFiles(evt);
});
}, [reloadUser, userId]);
return (
<Page
id='userProfilePage'
title={globalize.translate('Profile')}
className='mainAnimatedPage libraryPage userPreferencesPage userPasswordPage noSecondaryNavPage'
>
<div ref={element} className='padded-left padded-right padded-bottom-page'>
<div
className='readOnlyContent'
style={{margin: '0 auto', marginBottom: '1.8em', padding: '0 1em', display: 'flex', flexDirection: 'row', alignItems: 'center'}}
>
<div
className='imagePlaceHolder'
style={{position: 'relative', display: 'inline-block', maxWidth: 200 }}
>
<input
id='uploadImage'
type='file'
accept='image/*'
style={{position: 'absolute', right: 0, width: '100%', height: '100%', opacity: 0, cursor: 'pointer'}}
/>
<div
id='image'
style={{width: 200, height: 200, backgroundRepeat: 'no-repeat', backgroundPosition: 'center', borderRadius: '100%', backgroundSize: 'cover'}}
/>
</div>
<div style={{verticalAlign: 'top', margin: '1em 2em', display: 'flex', flexDirection: 'column', alignItems: 'center'}}>
<h2 className='username' style={{margin: 0, fontSize: 'xx-large'}}>
{userName}
</h2>
<br />
<ButtonElement
type='button'
id='btnAddImage'
className='raised button-submit hide'
title='ButtonAddImage'
/>
<ButtonElement
type='button'
id='btnDeleteImage'
className='raised button-delete hide'
title='DeleteImage'
/>
</div>
</div>
<UserPasswordForm
userId={userId}
/>
</div>
</Page>
);
};
export default UserProfilePage;

View file

@ -8,6 +8,7 @@ import UserEditPage from './UserEditPage';
import UserLibraryAccessPage from './UserLibraryAccessPage';
import UserParentalControl from './UserParentalControl';
import UserPasswordPage from './UserPasswordPage';
import UserProfilePage from './UserProfilePage';
import UserProfilesPage from './UserProfilesPage';
const AppRoutes = () => (
@ -69,6 +70,14 @@ const AppRoutes = () => (
</ConnectionRequired>
}
/>
<Route
path='myprofile.html'
element={
<ConnectionRequired>
<UserProfilePage />
</ConnectionRequired>
}
/>
{/* Suppress warnings for unhandled routes */}
<Route path='*' element={null} />
</Route>