From 2aa41f8a3326c5f946fac77eeea5213c07aca034 Mon Sep 17 00:00:00 2001 From: grafixeyehero <32230989+grafixeyehero@users.noreply.github.com> Date: Wed, 5 Jan 2022 20:35:58 +0300 Subject: [PATCH 1/5] Convert userPasswordPage & UserImagePage to react --- .../dashboard/users/UserPasswordForm.tsx | 283 ++++++++++++++++++ src/components/pages/UserImagePage.tsx | 165 ++++++++++ src/components/pages/UserPasswordPage.tsx | 47 +++ .../dashboard/users/userpassword.html | 69 ----- .../dashboard/users/userpasswordpage.js | 182 ----------- src/controllers/user/profile/index.html | 68 +---- src/controllers/user/profile/index.js | 104 ------- src/scripts/routes.js | 4 +- 8 files changed, 498 insertions(+), 424 deletions(-) create mode 100644 src/components/dashboard/users/UserPasswordForm.tsx create mode 100644 src/components/pages/UserImagePage.tsx create mode 100644 src/components/pages/UserPasswordPage.tsx delete mode 100644 src/controllers/dashboard/users/userpasswordpage.js delete mode 100644 src/controllers/user/profile/index.js diff --git a/src/components/dashboard/users/UserPasswordForm.tsx b/src/components/dashboard/users/UserPasswordForm.tsx new file mode 100644 index 0000000000..4ccfd28ce0 --- /dev/null +++ b/src/components/dashboard/users/UserPasswordForm.tsx @@ -0,0 +1,283 @@ +import React, { FunctionComponent, useEffect, useRef } from 'react'; +import Dashboard from '../../../scripts/clientUtils'; +import globalize from '../../../scripts/globalize'; +import LibraryMenu from '../../../scripts/libraryMenu'; +import confirm from '../../confirm/confirm'; +import loading from '../../loading/loading'; +import toast from '../../toast/toast'; +import ButtonElement from './ButtonElement'; +import CheckBoxElement from './CheckBoxElement'; +import InputElement from './InputElement'; + +type IProps = { + userId?: string; +} + +const UserPasswordForm: FunctionComponent = ({userId}: IProps) => { + const element = useRef(null); + + const loadUser = (Id) => { + window.ApiClient.getUser(Id).then(function (user) { + Dashboard.getCurrentUser().then(function (loggedInUser) { + LibraryMenu.setTitle(user.Name); + + let showPasswordSection = true; + let showLocalAccessSection = false; + + if (user.ConnectLinkType == 'Guest') { + element.current?.querySelector('.localAccessSection').classList.add('hide'); + showPasswordSection = false; + } else if (user.HasConfiguredPassword) { + element.current?.querySelector('.btnResetPassword').classList.remove('hide'); + element.current?.querySelector('#fldCurrentPassword').classList.remove('hide'); + showLocalAccessSection = true; + } else { + element.current?.querySelector('.btnResetPassword').classList.add('hide'); + element.current?.querySelector('#fldCurrentPassword').classList.add('hide'); + } + + if (showPasswordSection && (loggedInUser.Policy.IsAdministrator || user.Policy.EnableUserPreferenceAccess)) { + element.current?.querySelector('.passwordSection').classList.remove('hide'); + } else { + element.current?.querySelector('.passwordSection').classList.add('hide'); + } + + if (showLocalAccessSection && (loggedInUser.Policy.IsAdministrator || user.Policy.EnableUserPreferenceAccess)) { + element.current?.querySelector('.localAccessSection').classList.remove('hide'); + } else { + element.current?.querySelector('.localAccessSection').classList.add('hide'); + } + + const txtEasyPassword = element.current?.querySelector('#txtEasyPassword'); + txtEasyPassword.value = ''; + + if (user.HasConfiguredEasyPassword) { + txtEasyPassword.placeholder = '******'; + element.current?.querySelector('.btnResetEasyPassword').classList.remove('hide'); + } else { + txtEasyPassword.removeAttribute('placeholder'); + txtEasyPassword.placeholder = ''; + element.current?.querySelector('.btnResetEasyPassword').classList.add('hide'); + } + + element.current.querySelector('.chkEnableLocalEasyPassword').checked = user.Configuration.EnableLocalPassword; + + import('../../autoFocuser').then(({default: autoFocuser}) => { + autoFocuser.autoFocus(element.current); + }); + }); + }); + + element.current.querySelector('#txtCurrentPassword').value = ''; + element.current.querySelector('#txtNewPassword').value = ''; + element.current.querySelector('#txtNewPasswordConfirm').value = ''; + }; + + useEffect(() => { + loadUser(userId); + + const onSubmit = (e) => { + const form = element.current; + + if (form.querySelector('#txtNewPassword').value != form.querySelector('#txtNewPasswordConfirm').value) { + toast(globalize.translate('PasswordMatchError')); + } else { + loading.show(); + savePassword(); + } + + e.preventDefault(); + return false; + }; + + const savePassword = () => { + let currentPassword = element.current?.querySelector('#txtCurrentPassword').value; + const newPassword = element.current?.querySelector('#txtNewPassword').value; + + if (element.current?.querySelector('#fldCurrentPassword').classList.contains('hide')) { + // Firefox does not respect autocomplete=off, so clear it if the field is supposed to be hidden (and blank) + // This should only happen when user.HasConfiguredPassword is false, but this information is not passed on + currentPassword = ''; + } + + window.ApiClient.updateUserPassword(userId, currentPassword, newPassword).then(function () { + loading.hide(); + toast(globalize.translate('PasswordSaved')); + + loadUser(userId); + }, function () { + loading.hide(); + Dashboard.alert({ + title: globalize.translate('HeaderLoginFailure'), + message: globalize.translate('MessageInvalidUser') + }); + }); + }; + + const onLocalAccessSubmit = (e) => { + loading.show(); + saveEasyPassword(); + e.preventDefault(); + return false; + }; + + const saveEasyPassword = () => { + const easyPassword = element.current?.querySelector('#txtEasyPassword').value; + + if (easyPassword) { + window.ApiClient.updateEasyPassword(userId, easyPassword).then(function () { + onEasyPasswordSaved(userId); + }); + } else { + onEasyPasswordSaved(userId); + } + }; + + const onEasyPasswordSaved = (Id) => { + window.ApiClient.getUser(Id).then(function (user) { + user.Configuration.EnableLocalPassword = element.current?.querySelector('.chkEnableLocalEasyPassword').checked; + window.ApiClient.updateUserConfiguration(user.Id, user.Configuration).then(function () { + loading.hide(); + toast(globalize.translate('SettingsSaved')); + + loadUser(userId); + }); + }); + }; + + const resetEasyPassword = () => { + const msg = globalize.translate('PinCodeResetConfirmation'); + + confirm(msg, globalize.translate('HeaderPinCodeReset')).then(function () { + loading.show(); + window.ApiClient.resetEasyPassword(userId).then(function () { + loading.hide(); + Dashboard.alert({ + message: globalize.translate('PinCodeResetComplete'), + title: globalize.translate('HeaderPinCodeReset') + }); + loadUser(userId); + }); + }); + }; + + const resetPassword = () => { + const msg = globalize.translate('PasswordResetConfirmation'); + confirm(msg, globalize.translate('ResetPassword')).then(function () { + loading.show(); + window.ApiClient.resetUserPassword(userId).then(function () { + loading.hide(); + Dashboard.alert({ + message: globalize.translate('PasswordResetComplete'), + title: globalize.translate('ResetPassword') + }); + loadUser(userId); + }); + }); + }; + + element?.current?.querySelector('.updatePasswordForm').addEventListener('submit', onSubmit); + element?.current?.querySelector('.localAccessForm').addEventListener('submit', onLocalAccessSubmit); + + element?.current?.querySelector('.btnResetEasyPassword').addEventListener('click', resetEasyPassword); + element?.current?.querySelector('.btnResetPassword').addEventListener('click', resetPassword); + }, [userId]); + + return ( +
+
+
+
+ +
+
+ +
+
+ +
+
+
+ + +
+
+
+
+
+
+
+ {globalize.translate('HeaderEasyPinCode')} +
+
+
+ {globalize.translate('EasyPasswordHelp')} +
+
+
+ +
+
+
+ +
+ {globalize.translate('LabelInNetworkSignInWithEasyPasswordHelp')} +
+
+
+ + +
+
+
+
+ ); +}; + +export default UserPasswordForm; diff --git a/src/components/pages/UserImagePage.tsx b/src/components/pages/UserImagePage.tsx new file mode 100644 index 0000000000..51c00ed00d --- /dev/null +++ b/src/components/pages/UserImagePage.tsx @@ -0,0 +1,165 @@ +import React, { FunctionComponent, useEffect, useState, useRef } from 'react'; + +import Dashboard from '../../scripts/clientUtils'; +import globalize from '../../scripts/globalize'; +import LibraryMenu from '../../scripts/libraryMenu'; +import { appHost } from '../apphost'; +import confirm from '../confirm/confirm'; +import ButtonElement from '../dashboard/users/ButtonElement'; +import UserPasswordForm from '../dashboard/users/UserPasswordForm'; +import loading from '../loading/loading'; +import toast from '../toast/toast'; + +type IProps = { + userId?: string; +} + +const UserImagePage: FunctionComponent = ({userId}: IProps) => { + const [ userName, setUserName ] = useState(''); + + const element = useRef(null); + + const reloadUser = (Id) => { + loading.show(); + window.ApiClient.getUser(Id).then(function (user) { + 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 = element.current?.querySelector('#image'); + userImage.style.backgroundImage = 'url(' + imageUrl + ')'; + + Dashboard.getCurrentUser().then(function (loggedInUser) { + if (user.PrimaryImageTag) { + element.current?.querySelector('.btnAddImage').classList.add('hide'); + element.current?.querySelector('.btnDeleteImage').classList.remove('hide'); + } else if (appHost.supports('fileinput') && (loggedInUser.Policy.IsAdministrator || user.Policy.EnableUserPreferenceAccess)) { + element.current?.querySelector('.btnDeleteImage').classList.add('hide'); + element.current?.querySelector('.btnAddImage').classList.remove('hide'); + } + }); + loading.hide(); + }); + }; + + useEffect(() => { + reloadUser(userId); + + const onFileReaderError = (evt) => { + loading.hide(); + switch (evt.target.error.code) { + case evt.target.error.NOT_FOUND_ERR: + toast(globalize.translate('FileNotFound')); + break; + case evt.target.error.ABORT_ERR: + onFileReaderAbort(); + break; + case evt.target.error.NOT_READABLE_ERR: + default: + toast(globalize.translate('FileReadError')); + } + }; + + const onFileReaderAbort = () => { + loading.hide(); + toast(globalize.translate('FileReadCancelled')); + }; + + const setFiles = (evt) => { + const userImage = element?.current?.querySelector('#image'); + const file = evt.target.files[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, 'Primary', file).then(function () { + loading.hide(); + reloadUser(userId); + }); + }; + + reader.readAsDataURL(file); + }; + + element?.current?.querySelector('.btnDeleteImage').addEventListener('click', function () { + confirm( + globalize.translate('DeleteImageConfirmation'), + globalize.translate('DeleteImage') + ).then(function () { + loading.show(); + window.ApiClient.deleteUserImage(userId, 'primary').then(function () { + loading.hide(); + reloadUser(userId); + }); + }); + }); + + element?.current?.querySelector('.btnAddImage').addEventListener('click', function () { + element?.current?.querySelector('#uploadImage').click(); + }); + + element?.current?.querySelector('#uploadImage').addEventListener('change', function (evt) { + setFiles(evt); + }); + }, [userId]); + + return ( +
+
+
+
+ +
+
+
+

+ {userName} +

+
+ + +
+
+ +
+
+ ); +}; + +export default UserImagePage; diff --git a/src/components/pages/UserPasswordPage.tsx b/src/components/pages/UserPasswordPage.tsx new file mode 100644 index 0000000000..68b1108b7c --- /dev/null +++ b/src/components/pages/UserPasswordPage.tsx @@ -0,0 +1,47 @@ +import React, { FunctionComponent, useEffect, useState } from 'react'; +import { appRouter } from '../appRouter'; +import SectionTitleLinkElement from '../dashboard/users/SectionTitleLinkElement'; +import SectionTabs from '../dashboard/users/SectionTabs'; +import UserPasswordForm from '../dashboard/users/UserPasswordForm'; + +const UserPasswordPage: FunctionComponent = () => { + const userId = appRouter.param('userId'); + const [ userName, setUserName ] = useState(''); + + const loadUser = (Id) => { + window.ApiClient.getUser(Id).then(function (user) { + setUserName(user.Name); + }); + }; + + useEffect(() => { + loadUser(userId); + }, [userId]); + + return ( +
+
+
+
+

+ {userName} +

+ +
+
+ +
+ +
+
+
+ ); +}; + +export default UserPasswordPage; diff --git a/src/controllers/dashboard/users/userpassword.html b/src/controllers/dashboard/users/userpassword.html index 285533cc4c..984fcc2c9c 100644 --- a/src/controllers/dashboard/users/userpassword.html +++ b/src/controllers/dashboard/users/userpassword.html @@ -1,72 +1,3 @@
-
-
-
-
-

- ${Help} -
-
- - -
-
-
-
- -
-
- -
-
- -
-
-
- - -
-
-
-
-
-
-
- ${HeaderEasyPinCode} -
-
-
${EasyPasswordHelp}
-
-
- -
-
-
- -
${LabelInNetworkSignInWithEasyPasswordHelp}
-
-
- - -
-
-
-
-
-
diff --git a/src/controllers/dashboard/users/userpasswordpage.js b/src/controllers/dashboard/users/userpasswordpage.js deleted file mode 100644 index fa9c95ce20..0000000000 --- a/src/controllers/dashboard/users/userpasswordpage.js +++ /dev/null @@ -1,182 +0,0 @@ -import loading from '../../../components/loading/loading'; -import libraryMenu from '../../../scripts/libraryMenu'; -import globalize from '../../../scripts/globalize'; -import '../../../elements/emby-button/emby-button'; -import Dashboard from '../../../scripts/clientUtils'; -import toast from '../../../components/toast/toast'; -import confirm from '../../../components/confirm/confirm'; - -/* eslint-disable indent */ - - function loadUser(page, params) { - const userid = params.userId; - ApiClient.getUser(userid).then(function (user) { - Dashboard.getCurrentUser().then(function (loggedInUser) { - libraryMenu.setTitle(user.Name); - page.querySelector('.username').innerText = user.Name; - let showPasswordSection = true; - let showLocalAccessSection = false; - - if (user.ConnectLinkType == 'Guest') { - page.querySelector('.localAccessSection').classList.add('hide'); - showPasswordSection = false; - } else if (user.HasConfiguredPassword) { - page.querySelector('#btnResetPassword').classList.remove('hide'); - page.querySelector('#fldCurrentPassword').classList.remove('hide'); - showLocalAccessSection = true; - } else { - page.querySelector('#btnResetPassword').classList.add('hide'); - page.querySelector('#fldCurrentPassword').classList.add('hide'); - } - - if (showPasswordSection && (loggedInUser.Policy.IsAdministrator || user.Policy.EnableUserPreferenceAccess)) { - page.querySelector('.passwordSection').classList.remove('hide'); - } else { - page.querySelector('.passwordSection').classList.add('hide'); - } - - if (showLocalAccessSection && (loggedInUser.Policy.IsAdministrator || user.Policy.EnableUserPreferenceAccess)) { - page.querySelector('.localAccessSection').classList.remove('hide'); - } else { - page.querySelector('.localAccessSection').classList.add('hide'); - } - - const txtEasyPassword = page.querySelector('#txtEasyPassword'); - txtEasyPassword.value = ''; - - if (user.HasConfiguredEasyPassword) { - txtEasyPassword.placeholder = '******'; - page.querySelector('#btnResetEasyPassword').classList.remove('hide'); - } else { - txtEasyPassword.removeAttribute('placeholder'); - txtEasyPassword.placeholder = ''; - page.querySelector('#btnResetEasyPassword').classList.add('hide'); - } - - page.querySelector('.chkEnableLocalEasyPassword').checked = user.Configuration.EnableLocalPassword; - - import('../../../components/autoFocuser').then(({default: autoFocuser}) => { - autoFocuser.autoFocus(page); - }); - }); - }); - page.querySelector('#txtCurrentPassword').value = ''; - page.querySelector('#txtNewPassword').value = ''; - page.querySelector('#txtNewPasswordConfirm').value = ''; - } - - export default function (view, params) { - function saveEasyPassword() { - const userId = params.userId; - const easyPassword = view.querySelector('#txtEasyPassword').value; - - if (easyPassword) { - ApiClient.updateEasyPassword(userId, easyPassword).then(function () { - onEasyPasswordSaved(userId); - }); - } else { - onEasyPasswordSaved(userId); - } - } - - function onEasyPasswordSaved(userId) { - ApiClient.getUser(userId).then(function (user) { - user.Configuration.EnableLocalPassword = view.querySelector('.chkEnableLocalEasyPassword').checked; - ApiClient.updateUserConfiguration(user.Id, user.Configuration).then(function () { - loading.hide(); - toast(globalize.translate('SettingsSaved')); - - loadUser(view, params); - }); - }); - } - - function savePassword() { - const userId = params.userId; - let currentPassword = view.querySelector('#txtCurrentPassword').value; - const newPassword = view.querySelector('#txtNewPassword').value; - - if (view.querySelector('#fldCurrentPassword').classList.contains('hide')) { - // Firefox does not respect autocomplete=off, so clear it if the field is supposed to be hidden (and blank) - // This should only happen when user.HasConfiguredPassword is false, but this information is not passed on - currentPassword = ''; - } - - ApiClient.updateUserPassword(userId, currentPassword, newPassword).then(function () { - loading.hide(); - toast(globalize.translate('PasswordSaved')); - - loadUser(view, params); - }, function () { - loading.hide(); - Dashboard.alert({ - title: globalize.translate('HeaderLoginFailure'), - message: globalize.translate('MessageInvalidUser') - }); - }); - } - - function onSubmit(e) { - const form = this; - - if (form.querySelector('#txtNewPassword').value != form.querySelector('#txtNewPasswordConfirm').value) { - toast(globalize.translate('PasswordMatchError')); - } else { - loading.show(); - savePassword(); - } - - e.preventDefault(); - return false; - } - - function onLocalAccessSubmit(e) { - loading.show(); - saveEasyPassword(); - e.preventDefault(); - return false; - } - - function resetPassword() { - const msg = globalize.translate('PasswordResetConfirmation'); - confirm(msg, globalize.translate('ResetPassword')).then(function () { - const userId = params.userId; - loading.show(); - ApiClient.resetUserPassword(userId).then(function () { - loading.hide(); - Dashboard.alert({ - message: globalize.translate('PasswordResetComplete'), - title: globalize.translate('ResetPassword') - }); - loadUser(view, params); - }); - }); - } - - function resetEasyPassword() { - const msg = globalize.translate('PinCodeResetConfirmation'); - - confirm(msg, globalize.translate('HeaderPinCodeReset')).then(function () { - const userId = params.userId; - loading.show(); - ApiClient.resetEasyPassword(userId).then(function () { - loading.hide(); - Dashboard.alert({ - message: globalize.translate('PinCodeResetComplete'), - title: globalize.translate('HeaderPinCodeReset') - }); - loadUser(view, params); - }); - }); - } - - view.querySelector('.updatePasswordForm').addEventListener('submit', onSubmit); - view.querySelector('.localAccessForm').addEventListener('submit', onLocalAccessSubmit); - view.querySelector('#btnResetEasyPassword').addEventListener('click', resetEasyPassword); - view.querySelector('#btnResetPassword').addEventListener('click', resetPassword); - view.addEventListener('viewshow', function () { - loadUser(view, params); - }); - } - -/* eslint-enable indent */ diff --git a/src/controllers/user/profile/index.html b/src/controllers/user/profile/index.html index 3eaa2f7299..91c3f7d7d9 100644 --- a/src/controllers/user/profile/index.html +++ b/src/controllers/user/profile/index.html @@ -1,69 +1,3 @@
-
-
-
- -
-
-
-

-
- - -
-
-
-
-

- ${HeaderPassword} -

-
- -
-
- -
-
- -
-
- - -
-
-
-
-
-

${HeaderEasyPinCode}

-
${EasyPasswordHelp}
-
-
- -
-
- -
${LabelInNetworkSignInWithEasyPasswordHelp}
-
-
- - -
-
-
-
+
diff --git a/src/controllers/user/profile/index.js b/src/controllers/user/profile/index.js deleted file mode 100644 index c6d23eb2f9..0000000000 --- a/src/controllers/user/profile/index.js +++ /dev/null @@ -1,104 +0,0 @@ -import UserPasswordPage from '../../dashboard/users/userpasswordpage'; -import loading from '../../../components/loading/loading'; -import libraryMenu from '../../../scripts/libraryMenu'; -import { appHost } from '../../../components/apphost'; -import globalize from '../../../scripts/globalize'; -import '../../../elements/emby-button/emby-button'; -import Dashboard from '../../../scripts/clientUtils'; -import toast from '../../../components/toast/toast'; -import confirm from '../../../components/confirm/confirm'; - -function reloadUser(page) { - const userId = getParameterByName('userId'); - loading.show(); - ApiClient.getUser(userId).then(function (user) { - page.querySelector('.username').innerText = user.Name; - libraryMenu.setTitle(user.Name); - - let imageUrl = 'assets/img/avatar.png'; - if (user.PrimaryImageTag) { - imageUrl = ApiClient.getUserImageUrl(user.Id, { - tag: user.PrimaryImageTag, - type: 'Primary' - }); - } - - const userImage = page.querySelector('#image'); - userImage.style.backgroundImage = 'url(' + imageUrl + ')'; - - Dashboard.getCurrentUser().then(function (loggedInUser) { - if (user.PrimaryImageTag) { - page.querySelector('#btnAddImage').classList.add('hide'); - page.querySelector('#btnDeleteImage').classList.remove('hide'); - } else if (appHost.supports('fileinput') && (loggedInUser.Policy.IsAdministrator || user.Policy.EnableUserPreferenceAccess)) { - page.querySelector('#btnDeleteImage').classList.add('hide'); - page.querySelector('#btnAddImage').classList.remove('hide'); - } - }); - loading.hide(); - }); -} - -function onFileReaderError(evt) { - loading.hide(); - switch (evt.target.error.code) { - case evt.target.error.NOT_FOUND_ERR: - toast(globalize.translate('FileNotFound')); - break; - case evt.target.error.ABORT_ERR: - onFileReaderAbort(); - break; - case evt.target.error.NOT_READABLE_ERR: - default: - toast(globalize.translate('FileReadError')); - } -} - -function onFileReaderAbort() { - loading.hide(); - toast(globalize.translate('FileReadCancelled')); -} - -function setFiles(page, files) { - const userImage = page.querySelector('#image'); - const file = files[0]; - - if (!file || !file.type.match('image.*')) { - return false; - } - - const reader = new FileReader(); - reader.onerror = onFileReaderError; - reader.onabort = onFileReaderAbort; - reader.onload = function (evt) { - userImage.style.backgroundImage = 'url(' + evt.target.result + ')'; - const userId = getParameterByName('userId'); - ApiClient.uploadUserImage(userId, 'Primary', file).then(function () { - loading.hide(); - reloadUser(page); - }); - }; - - reader.readAsDataURL(file); -} - -export default function (view, params) { - reloadUser(view); - new UserPasswordPage(view, params); - view.querySelector('#btnDeleteImage').addEventListener('click', function () { - confirm(globalize.translate('DeleteImageConfirmation'), globalize.translate('DeleteImage')).then(function () { - loading.show(); - const userId = getParameterByName('userId'); - ApiClient.deleteUserImage(userId, 'primary').then(function () { - loading.hide(); - reloadUser(view); - }); - }); - }); - view.querySelector('#btnAddImage').addEventListener('click', function () { - view.querySelector('#uploadImage').click(); - }); - view.querySelector('#uploadImage').addEventListener('change', function (evt) { - setFiles(view, evt.target.files); - }); -} diff --git a/src/scripts/routes.js b/src/scripts/routes.js index 538c0c03ef..f2e0507521 100644 --- a/src/scripts/routes.js +++ b/src/scripts/routes.js @@ -81,7 +81,7 @@ import { appRouter } from '../components/appRouter'; alias: '/myprofile.html', path: 'user/profile/index.html', autoFocus: false, - controller: 'user/profile/index' + pageComponent: 'UserImagePage' }); defineRoute({ @@ -471,7 +471,7 @@ import { appRouter } from '../components/appRouter'; alias: '/userpassword.html', path: 'dashboard/users/userpassword.html', autoFocus: false, - controller: 'dashboard/users/userpasswordpage' + pageComponent: 'UserPasswordPage' }); defineRoute({ From 417a9ddc9963382611dc3217eec218ade7f83362 Mon Sep 17 00:00:00 2001 From: grafixeyehero <32230989+grafixeyehero@users.noreply.github.com> Date: Thu, 3 Mar 2022 03:37:56 +0300 Subject: [PATCH 2/5] update TypeScript --- .../dashboard/users/UserPasswordForm.tsx | 137 +++++++++++------- src/components/pages/UserImagePage.tsx | 78 ++++++---- src/components/pages/UserPasswordPage.tsx | 16 +- 3 files changed, 147 insertions(+), 84 deletions(-) diff --git a/src/components/dashboard/users/UserPasswordForm.tsx b/src/components/dashboard/users/UserPasswordForm.tsx index 4ccfd28ce0..2ccaa17d75 100644 --- a/src/components/dashboard/users/UserPasswordForm.tsx +++ b/src/components/dashboard/users/UserPasswordForm.tsx @@ -1,4 +1,4 @@ -import React, { FunctionComponent, useEffect, useRef } from 'react'; +import React, { FunctionComponent, useCallback, useEffect, useRef } from 'react'; import Dashboard from '../../../scripts/clientUtils'; import globalize from '../../../scripts/globalize'; import LibraryMenu from '../../../scripts/libraryMenu'; @@ -10,76 +10,103 @@ import CheckBoxElement from './CheckBoxElement'; import InputElement from './InputElement'; type IProps = { - userId?: string; + userId: string; } const UserPasswordForm: FunctionComponent = ({userId}: IProps) => { - const element = useRef(null); + const element = useRef(null); + + const loadUser = useCallback(() => { + const page = element.current; + + if (!page) { + console.error('Unexpected null reference'); + return; + } + + window.ApiClient.getUser(userId).then(function (user) { + Dashboard.getCurrentUser().then(function (loggedInUser: { Policy: { IsAdministrator: boolean; }; }) { + if (!user.Id) { + throw new Error('Unexpected null user.Id'); + } + + if (!user.Policy) { + throw new Error('Unexpected null user.Policy'); + } + + if (!user.Id) { + throw new Error('Unexpected null user.Id'); + } + + if (!user.Configuration) { + throw new Error('Unexpected null user.Configuration'); + } - const loadUser = (Id) => { - window.ApiClient.getUser(Id).then(function (user) { - Dashboard.getCurrentUser().then(function (loggedInUser) { LibraryMenu.setTitle(user.Name); - let showPasswordSection = true; + const showPasswordSection = true; let showLocalAccessSection = false; - if (user.ConnectLinkType == 'Guest') { - element.current?.querySelector('.localAccessSection').classList.add('hide'); - showPasswordSection = false; - } else if (user.HasConfiguredPassword) { - element.current?.querySelector('.btnResetPassword').classList.remove('hide'); - element.current?.querySelector('#fldCurrentPassword').classList.remove('hide'); + if (user.HasConfiguredPassword) { + (page.querySelector('.btnResetPassword') as HTMLDivElement).classList.remove('hide'); + (page.querySelector('#fldCurrentPassword') as HTMLDivElement).classList.remove('hide'); showLocalAccessSection = true; } else { - element.current?.querySelector('.btnResetPassword').classList.add('hide'); - element.current?.querySelector('#fldCurrentPassword').classList.add('hide'); + (page.querySelector('.btnResetPassword') as HTMLDivElement).classList.add('hide'); + (page.querySelector('#fldCurrentPassword') as HTMLDivElement).classList.add('hide'); } if (showPasswordSection && (loggedInUser.Policy.IsAdministrator || user.Policy.EnableUserPreferenceAccess)) { - element.current?.querySelector('.passwordSection').classList.remove('hide'); + (page.querySelector('.passwordSection') as HTMLDivElement).classList.remove('hide'); } else { - element.current?.querySelector('.passwordSection').classList.add('hide'); + (page.querySelector('.passwordSection') as HTMLDivElement).classList.add('hide'); } if (showLocalAccessSection && (loggedInUser.Policy.IsAdministrator || user.Policy.EnableUserPreferenceAccess)) { - element.current?.querySelector('.localAccessSection').classList.remove('hide'); + (page.querySelector('.localAccessSection') as HTMLDivElement).classList.remove('hide'); } else { - element.current?.querySelector('.localAccessSection').classList.add('hide'); + (page.querySelector('.localAccessSection') as HTMLDivElement).classList.add('hide'); } - const txtEasyPassword = element.current?.querySelector('#txtEasyPassword'); + const txtEasyPassword = page.querySelector('#txtEasyPassword') as HTMLInputElement; txtEasyPassword.value = ''; if (user.HasConfiguredEasyPassword) { txtEasyPassword.placeholder = '******'; - element.current?.querySelector('.btnResetEasyPassword').classList.remove('hide'); + (page.querySelector('.btnResetEasyPassword') as HTMLDivElement).classList.remove('hide'); } else { txtEasyPassword.removeAttribute('placeholder'); txtEasyPassword.placeholder = ''; - element.current?.querySelector('.btnResetEasyPassword').classList.add('hide'); + (page.querySelector('.btnResetEasyPassword') as HTMLDivElement).classList.add('hide'); } - element.current.querySelector('.chkEnableLocalEasyPassword').checked = user.Configuration.EnableLocalPassword; + const chkEnableLocalEasyPassword = page.querySelector('.chkEnableLocalEasyPassword') as HTMLInputElement; + + chkEnableLocalEasyPassword.checked = user.Configuration.EnableLocalPassword || false; import('../../autoFocuser').then(({default: autoFocuser}) => { - autoFocuser.autoFocus(element.current); + autoFocuser.autoFocus(page); }); }); }); - element.current.querySelector('#txtCurrentPassword').value = ''; - element.current.querySelector('#txtNewPassword').value = ''; - element.current.querySelector('#txtNewPasswordConfirm').value = ''; - }; + (page.querySelector('#txtCurrentPassword') as HTMLInputElement).value = ''; + (page.querySelector('#txtNewPassword') as HTMLInputElement).value = ''; + (page.querySelector('#txtNewPasswordConfirm') as HTMLInputElement).value = ''; + }, [userId]); useEffect(() => { - loadUser(userId); + const page = element.current; - const onSubmit = (e) => { - const form = element.current; + if (!page) { + console.error('Unexpected null reference'); + return; + } - if (form.querySelector('#txtNewPassword').value != form.querySelector('#txtNewPasswordConfirm').value) { + loadUser(); + + const onSubmit = (e: Event) => { + if ((page.querySelector('#txtNewPassword') as HTMLInputElement).value != (page.querySelector('#txtNewPasswordConfirm') as HTMLInputElement).value) { toast(globalize.translate('PasswordMatchError')); } else { loading.show(); @@ -91,10 +118,10 @@ const UserPasswordForm: FunctionComponent = ({userId}: IProps) => { }; const savePassword = () => { - let currentPassword = element.current?.querySelector('#txtCurrentPassword').value; - const newPassword = element.current?.querySelector('#txtNewPassword').value; + let currentPassword = (page.querySelector('#txtCurrentPassword') as HTMLInputElement).value; + const newPassword = (page.querySelector('#txtNewPassword') as HTMLInputElement).value; - if (element.current?.querySelector('#fldCurrentPassword').classList.contains('hide')) { + if ((page.querySelector('#fldCurrentPassword') as HTMLDivElement).classList.contains('hide')) { // Firefox does not respect autocomplete=off, so clear it if the field is supposed to be hidden (and blank) // This should only happen when user.HasConfiguredPassword is false, but this information is not passed on currentPassword = ''; @@ -104,7 +131,7 @@ const UserPasswordForm: FunctionComponent = ({userId}: IProps) => { loading.hide(); toast(globalize.translate('PasswordSaved')); - loadUser(userId); + loadUser(); }, function () { loading.hide(); Dashboard.alert({ @@ -114,7 +141,7 @@ const UserPasswordForm: FunctionComponent = ({userId}: IProps) => { }); }; - const onLocalAccessSubmit = (e) => { + const onLocalAccessSubmit = (e: Event) => { loading.show(); saveEasyPassword(); e.preventDefault(); @@ -122,25 +149,33 @@ const UserPasswordForm: FunctionComponent = ({userId}: IProps) => { }; const saveEasyPassword = () => { - const easyPassword = element.current?.querySelector('#txtEasyPassword').value; + const easyPassword = (page.querySelector('#txtEasyPassword') as HTMLInputElement).value; if (easyPassword) { window.ApiClient.updateEasyPassword(userId, easyPassword).then(function () { - onEasyPasswordSaved(userId); + onEasyPasswordSaved(); }); } else { - onEasyPasswordSaved(userId); + onEasyPasswordSaved(); } }; - const onEasyPasswordSaved = (Id) => { - window.ApiClient.getUser(Id).then(function (user) { - user.Configuration.EnableLocalPassword = element.current?.querySelector('.chkEnableLocalEasyPassword').checked; + const onEasyPasswordSaved = () => { + window.ApiClient.getUser(userId).then(function (user) { + if (!user.Configuration) { + throw new Error('Unexpected null user.Configuration'); + } + + if (!user.Id) { + throw new Error('Unexpected null user.Id'); + } + + user.Configuration.EnableLocalPassword = (page.querySelector('.chkEnableLocalEasyPassword') as HTMLInputElement).checked; window.ApiClient.updateUserConfiguration(user.Id, user.Configuration).then(function () { loading.hide(); toast(globalize.translate('SettingsSaved')); - loadUser(userId); + loadUser(); }); }); }; @@ -156,7 +191,7 @@ const UserPasswordForm: FunctionComponent = ({userId}: IProps) => { message: globalize.translate('PinCodeResetComplete'), title: globalize.translate('HeaderPinCodeReset') }); - loadUser(userId); + loadUser(); }); }); }; @@ -171,17 +206,17 @@ const UserPasswordForm: FunctionComponent = ({userId}: IProps) => { message: globalize.translate('PasswordResetComplete'), title: globalize.translate('ResetPassword') }); - loadUser(userId); + loadUser(); }); }); }; - element?.current?.querySelector('.updatePasswordForm').addEventListener('submit', onSubmit); - element?.current?.querySelector('.localAccessForm').addEventListener('submit', onLocalAccessSubmit); + (page.querySelector('.updatePasswordForm') as HTMLFormElement).addEventListener('submit', onSubmit); + (page.querySelector('.localAccessForm') as HTMLFormElement).addEventListener('submit', onLocalAccessSubmit); - element?.current?.querySelector('.btnResetEasyPassword').addEventListener('click', resetEasyPassword); - element?.current?.querySelector('.btnResetPassword').addEventListener('click', resetPassword); - }, [userId]); + (page.querySelector('.btnResetEasyPassword') as HTMLButtonElement).addEventListener('click', resetEasyPassword); + (page.querySelector('.btnResetPassword') as HTMLButtonElement).addEventListener('click', resetPassword); + }, [loadUser, userId]); return (
diff --git a/src/components/pages/UserImagePage.tsx b/src/components/pages/UserImagePage.tsx index 51c00ed00d..702bb36855 100644 --- a/src/components/pages/UserImagePage.tsx +++ b/src/components/pages/UserImagePage.tsx @@ -1,4 +1,4 @@ -import React, { FunctionComponent, useEffect, useState, useRef } from 'react'; +import React, { FunctionComponent, useEffect, useState, useRef, useCallback } from 'react'; import Dashboard from '../../scripts/clientUtils'; import globalize from '../../scripts/globalize'; @@ -11,17 +11,32 @@ import loading from '../loading/loading'; import toast from '../toast/toast'; type IProps = { - userId?: string; + userId: string; } const UserImagePage: FunctionComponent = ({userId}: IProps) => { const [ userName, setUserName ] = useState(''); - const element = useRef(null); + const element = useRef(null); + + const reloadUser = useCallback(() => { + const page = element.current; + + if (!page) { + console.error('Unexpected null reference'); + return; + } - const reloadUser = (Id) => { loading.show(); - window.ApiClient.getUser(Id).then(function (user) { + 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); @@ -32,27 +47,37 @@ const UserImagePage: FunctionComponent = ({userId}: IProps) => { type: 'Primary' }); } - - const userImage = element.current?.querySelector('#image'); + const userImage = (page.querySelector('#image') as HTMLDivElement); userImage.style.backgroundImage = 'url(' + imageUrl + ')'; - Dashboard.getCurrentUser().then(function (loggedInUser) { + Dashboard.getCurrentUser().then(function (loggedInUser: { Policy: { IsAdministrator: boolean; }; }) { + if (!user.Policy) { + throw new Error('Unexpected null user.Policy'); + } + if (user.PrimaryImageTag) { - element.current?.querySelector('.btnAddImage').classList.add('hide'); - element.current?.querySelector('.btnDeleteImage').classList.remove('hide'); + (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)) { - element.current?.querySelector('.btnDeleteImage').classList.add('hide'); - element.current?.querySelector('.btnAddImage').classList.remove('hide'); + (page.querySelector('.btnDeleteImage') as HTMLButtonElement).classList.add('hide'); + (page.querySelector('.btnAddImage') as HTMLButtonElement).classList.remove('hide'); } }); loading.hide(); }); - }; + }, [userId]); useEffect(() => { - reloadUser(userId); + const page = element.current; - const onFileReaderError = (evt) => { + if (!page) { + console.error('Unexpected null reference'); + return; + } + + reloadUser(); + + const onFileReaderError = (evt: any) => { loading.hide(); switch (evt.target.error.code) { case evt.target.error.NOT_FOUND_ERR: @@ -72,9 +97,10 @@ const UserImagePage: FunctionComponent = ({userId}: IProps) => { toast(globalize.translate('FileReadCancelled')); }; - const setFiles = (evt) => { - const userImage = element?.current?.querySelector('#image'); - const file = evt.target.files[0]; + 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; @@ -87,34 +113,34 @@ const UserImagePage: FunctionComponent = ({userId}: IProps) => { userImage.style.backgroundImage = 'url(' + reader.result + ')'; window.ApiClient.uploadUserImage(userId, 'Primary', file).then(function () { loading.hide(); - reloadUser(userId); + reloadUser(); }); }; reader.readAsDataURL(file); }; - element?.current?.querySelector('.btnDeleteImage').addEventListener('click', function () { + (page.querySelector('.btnDeleteImage') as HTMLButtonElement).addEventListener('click', function () { confirm( globalize.translate('DeleteImageConfirmation'), globalize.translate('DeleteImage') ).then(function () { loading.show(); - window.ApiClient.deleteUserImage(userId, 'primary').then(function () { + window.ApiClient.deleteUserImage(userId, 'Primary').then(function () { loading.hide(); - reloadUser(userId); + reloadUser(); }); }); }); - element?.current?.querySelector('.btnAddImage').addEventListener('click', function () { - element?.current?.querySelector('#uploadImage').click(); + (page.querySelector('.btnAddImage') as HTMLButtonElement).addEventListener('click', function () { + (page.querySelector('#uploadImage') as HTMLInputElement).click(); }); - element?.current?.querySelector('#uploadImage').addEventListener('change', function (evt) { + (page.querySelector('#uploadImage') as HTMLInputElement).addEventListener('change', function (evt: Event) { setFiles(evt); }); - }, [userId]); + }, [reloadUser, userId]); return (
diff --git a/src/components/pages/UserPasswordPage.tsx b/src/components/pages/UserPasswordPage.tsx index 68b1108b7c..a32498af16 100644 --- a/src/components/pages/UserPasswordPage.tsx +++ b/src/components/pages/UserPasswordPage.tsx @@ -1,4 +1,4 @@ -import React, { FunctionComponent, useEffect, useState } from 'react'; +import React, { FunctionComponent, useCallback, useEffect, useState } from 'react'; import { appRouter } from '../appRouter'; import SectionTitleLinkElement from '../dashboard/users/SectionTitleLinkElement'; import SectionTabs from '../dashboard/users/SectionTabs'; @@ -8,15 +8,17 @@ const UserPasswordPage: FunctionComponent = () => { const userId = appRouter.param('userId'); const [ userName, setUserName ] = useState(''); - const loadUser = (Id) => { - window.ApiClient.getUser(Id).then(function (user) { + const loadUser = useCallback(() => { + window.ApiClient.getUser(userId).then(function (user) { + if (!user.Name) { + throw new Error('Unexpected null user.Name'); + } setUserName(user.Name); }); - }; - - useEffect(() => { - loadUser(userId); }, [userId]); + useEffect(() => { + loadUser(); + }, [loadUser]); return (
From 08807dca19d74300a7c65df1b324ae6f0a39d8ef Mon Sep 17 00:00:00 2001 From: grafixeyehero <32230989+grafixeyehero@users.noreply.github.com> Date: Thu, 3 Mar 2022 03:48:20 +0300 Subject: [PATCH 3/5] change ImageType to string --- src/apiclient.d.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/apiclient.d.ts b/src/apiclient.d.ts index 48cc65df0d..d46bd29f4c 100644 --- a/src/apiclient.d.ts +++ b/src/apiclient.d.ts @@ -93,7 +93,7 @@ declare module 'jellyfin-apiclient' { deleteItemImage(itemId: string, imageType: ImageType, imageIndex?: number): Promise; deleteItem(itemId: string): Promise; deleteLiveTvRecording(id: string): Promise; - deleteUserImage(userId: string, imageType: ImageType, imageIndex?: number): Promise; + deleteUserImage(userId: string, imageType: string, imageIndex?: number): Promise; deleteUser(userId: string): Promise; detectBitrate(force: boolean): Promise; deviceId(): string; @@ -299,7 +299,7 @@ declare module 'jellyfin-apiclient' { updateVirtualFolderOptions(id: string, libraryOptions?: any): Promise; uploadItemImage(itemId: string, imageType: ImageType, file: File): Promise; uploadItemSubtitle(itemId: string, language: string, isForced: boolean, file: File): Promise; - uploadUserImage(userId: string, imageType: ImageType, file: File): Promise; + uploadUserImage(userId: string, imageType: string, file: File): Promise; } class AppStore { From 3886b7da1fa770523da70a1d41138dc673748497 Mon Sep 17 00:00:00 2001 From: grafixeyehero <32230989+grafixeyehero@users.noreply.github.com> Date: Wed, 9 Mar 2022 19:36:22 +0300 Subject: [PATCH 4/5] apply suggestion --- src/apiclient.d.ts | 4 ++-- src/components/dashboard/users/UserPasswordForm.tsx | 11 +---------- .../pages/{UserImagePage.tsx => UserProfilePage.tsx} | 9 +++++---- src/controllers/user/profile/index.html | 2 +- src/scripts/routes.js | 2 +- 5 files changed, 10 insertions(+), 18 deletions(-) rename src/components/pages/{UserImagePage.tsx => UserProfilePage.tsx} (94%) diff --git a/src/apiclient.d.ts b/src/apiclient.d.ts index d46bd29f4c..48cc65df0d 100644 --- a/src/apiclient.d.ts +++ b/src/apiclient.d.ts @@ -93,7 +93,7 @@ declare module 'jellyfin-apiclient' { deleteItemImage(itemId: string, imageType: ImageType, imageIndex?: number): Promise; deleteItem(itemId: string): Promise; deleteLiveTvRecording(id: string): Promise; - deleteUserImage(userId: string, imageType: string, imageIndex?: number): Promise; + deleteUserImage(userId: string, imageType: ImageType, imageIndex?: number): Promise; deleteUser(userId: string): Promise; detectBitrate(force: boolean): Promise; deviceId(): string; @@ -299,7 +299,7 @@ declare module 'jellyfin-apiclient' { updateVirtualFolderOptions(id: string, libraryOptions?: any): Promise; uploadItemImage(itemId: string, imageType: ImageType, file: File): Promise; uploadItemSubtitle(itemId: string, language: string, isForced: boolean, file: File): Promise; - uploadUserImage(userId: string, imageType: string, file: File): Promise; + uploadUserImage(userId: string, imageType: ImageType, file: File): Promise; } class AppStore { diff --git a/src/components/dashboard/users/UserPasswordForm.tsx b/src/components/dashboard/users/UserPasswordForm.tsx index 2ccaa17d75..6b64953569 100644 --- a/src/components/dashboard/users/UserPasswordForm.tsx +++ b/src/components/dashboard/users/UserPasswordForm.tsx @@ -26,25 +26,16 @@ const UserPasswordForm: FunctionComponent = ({userId}: IProps) => { window.ApiClient.getUser(userId).then(function (user) { Dashboard.getCurrentUser().then(function (loggedInUser: { Policy: { IsAdministrator: boolean; }; }) { - if (!user.Id) { - throw new Error('Unexpected null user.Id'); - } - if (!user.Policy) { throw new Error('Unexpected null user.Policy'); } - if (!user.Id) { - throw new Error('Unexpected null user.Id'); - } - if (!user.Configuration) { throw new Error('Unexpected null user.Configuration'); } LibraryMenu.setTitle(user.Name); - const showPasswordSection = true; let showLocalAccessSection = false; if (user.HasConfiguredPassword) { @@ -56,7 +47,7 @@ const UserPasswordForm: FunctionComponent = ({userId}: IProps) => { (page.querySelector('#fldCurrentPassword') as HTMLDivElement).classList.add('hide'); } - if (showPasswordSection && (loggedInUser.Policy.IsAdministrator || user.Policy.EnableUserPreferenceAccess)) { + if (loggedInUser.Policy.IsAdministrator || user.Policy.EnableUserPreferenceAccess) { (page.querySelector('.passwordSection') as HTMLDivElement).classList.remove('hide'); } else { (page.querySelector('.passwordSection') as HTMLDivElement).classList.add('hide'); diff --git a/src/components/pages/UserImagePage.tsx b/src/components/pages/UserProfilePage.tsx similarity index 94% rename from src/components/pages/UserImagePage.tsx rename to src/components/pages/UserProfilePage.tsx index 702bb36855..dd39f523cc 100644 --- a/src/components/pages/UserImagePage.tsx +++ b/src/components/pages/UserProfilePage.tsx @@ -1,3 +1,4 @@ +import { ImageType } from '@thornbill/jellyfin-sdk/dist/generated-client'; import React, { FunctionComponent, useEffect, useState, useRef, useCallback } from 'react'; import Dashboard from '../../scripts/clientUtils'; @@ -14,7 +15,7 @@ type IProps = { userId: string; } -const UserImagePage: FunctionComponent = ({userId}: IProps) => { +const UserProfilePage: FunctionComponent = ({userId}: IProps) => { const [ userName, setUserName ] = useState(''); const element = useRef(null); @@ -111,7 +112,7 @@ const UserImagePage: FunctionComponent = ({userId}: IProps) => { reader.onabort = onFileReaderAbort; reader.onload = () => { userImage.style.backgroundImage = 'url(' + reader.result + ')'; - window.ApiClient.uploadUserImage(userId, 'Primary', file).then(function () { + window.ApiClient.uploadUserImage(userId, ImageType.Primary, file).then(function () { loading.hide(); reloadUser(); }); @@ -126,7 +127,7 @@ const UserImagePage: FunctionComponent = ({userId}: IProps) => { globalize.translate('DeleteImage') ).then(function () { loading.show(); - window.ApiClient.deleteUserImage(userId, 'Primary').then(function () { + window.ApiClient.deleteUserImage(userId, ImageType.Primary).then(function () { loading.hide(); reloadUser(); }); @@ -188,4 +189,4 @@ const UserImagePage: FunctionComponent = ({userId}: IProps) => { ); }; -export default UserImagePage; +export default UserProfilePage; diff --git a/src/controllers/user/profile/index.html b/src/controllers/user/profile/index.html index 91c3f7d7d9..c8fb3ae19d 100644 --- a/src/controllers/user/profile/index.html +++ b/src/controllers/user/profile/index.html @@ -1,3 +1,3 @@ -
+
diff --git a/src/scripts/routes.js b/src/scripts/routes.js index f2e0507521..62bd82e0b4 100644 --- a/src/scripts/routes.js +++ b/src/scripts/routes.js @@ -81,7 +81,7 @@ import { appRouter } from '../components/appRouter'; alias: '/myprofile.html', path: 'user/profile/index.html', autoFocus: false, - pageComponent: 'UserImagePage' + pageComponent: 'UserProfilePage' }); defineRoute({ From fc5a385d08a4fa9076d89a35e5e9996d68f5b1ab Mon Sep 17 00:00:00 2001 From: grafixeyehero <32230989+grafixeyehero@users.noreply.github.com> Date: Wed, 9 Mar 2022 19:52:47 +0300 Subject: [PATCH 5/5] use UserDto type from API --- src/components/dashboard/users/UserPasswordForm.tsx | 7 ++++--- src/components/pages/UserProfilePage.tsx | 6 +++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/components/dashboard/users/UserPasswordForm.tsx b/src/components/dashboard/users/UserPasswordForm.tsx index 6b64953569..6f14142207 100644 --- a/src/components/dashboard/users/UserPasswordForm.tsx +++ b/src/components/dashboard/users/UserPasswordForm.tsx @@ -1,3 +1,4 @@ +import { UserDto } from '@thornbill/jellyfin-sdk/dist/generated-client'; import React, { FunctionComponent, useCallback, useEffect, useRef } from 'react'; import Dashboard from '../../../scripts/clientUtils'; import globalize from '../../../scripts/globalize'; @@ -25,7 +26,7 @@ const UserPasswordForm: FunctionComponent = ({userId}: IProps) => { } window.ApiClient.getUser(userId).then(function (user) { - Dashboard.getCurrentUser().then(function (loggedInUser: { Policy: { IsAdministrator: boolean; }; }) { + Dashboard.getCurrentUser().then(function (loggedInUser: UserDto) { if (!user.Policy) { throw new Error('Unexpected null user.Policy'); } @@ -47,13 +48,13 @@ const UserPasswordForm: FunctionComponent = ({userId}: IProps) => { (page.querySelector('#fldCurrentPassword') as HTMLDivElement).classList.add('hide'); } - if (loggedInUser.Policy.IsAdministrator || user.Policy.EnableUserPreferenceAccess) { + if (loggedInUser?.Policy?.IsAdministrator || user.Policy.EnableUserPreferenceAccess) { (page.querySelector('.passwordSection') as HTMLDivElement).classList.remove('hide'); } else { (page.querySelector('.passwordSection') as HTMLDivElement).classList.add('hide'); } - if (showLocalAccessSection && (loggedInUser.Policy.IsAdministrator || user.Policy.EnableUserPreferenceAccess)) { + if (showLocalAccessSection && (loggedInUser?.Policy?.IsAdministrator || user.Policy.EnableUserPreferenceAccess)) { (page.querySelector('.localAccessSection') as HTMLDivElement).classList.remove('hide'); } else { (page.querySelector('.localAccessSection') as HTMLDivElement).classList.add('hide'); diff --git a/src/components/pages/UserProfilePage.tsx b/src/components/pages/UserProfilePage.tsx index dd39f523cc..b2f365e7c6 100644 --- a/src/components/pages/UserProfilePage.tsx +++ b/src/components/pages/UserProfilePage.tsx @@ -1,4 +1,4 @@ -import { ImageType } from '@thornbill/jellyfin-sdk/dist/generated-client'; +import { ImageType, UserDto } from '@thornbill/jellyfin-sdk/dist/generated-client'; import React, { FunctionComponent, useEffect, useState, useRef, useCallback } from 'react'; import Dashboard from '../../scripts/clientUtils'; @@ -51,7 +51,7 @@ const UserProfilePage: FunctionComponent = ({userId}: IProps) => { const userImage = (page.querySelector('#image') as HTMLDivElement); userImage.style.backgroundImage = 'url(' + imageUrl + ')'; - Dashboard.getCurrentUser().then(function (loggedInUser: { Policy: { IsAdministrator: boolean; }; }) { + Dashboard.getCurrentUser().then(function (loggedInUser: UserDto) { if (!user.Policy) { throw new Error('Unexpected null user.Policy'); } @@ -59,7 +59,7 @@ const UserProfilePage: FunctionComponent = ({userId}: IProps) => { 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)) { + } 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'); }