diff --git a/src/components/ConnectionRequired.tsx b/src/components/ConnectionRequired.tsx index 7ec089af50..82371fe853 100644 --- a/src/components/ConnectionRequired.tsx +++ b/src/components/ConnectionRequired.tsx @@ -1,5 +1,5 @@ import React, { FunctionComponent, useEffect, useState } from 'react'; -import { useNavigate } from 'react-router-dom'; +import { Outlet, useNavigate } from 'react-router-dom'; import alert from './alert'; import { appRouter } from './appRouter'; @@ -33,7 +33,6 @@ type ConnectionRequiredProps = { * If a condition fails, this component will navigate to the appropriate page. */ const ConnectionRequired: FunctionComponent = ({ - children, isAdminRequired = false, isUserRequired = true }) => { @@ -162,7 +161,9 @@ const ConnectionRequired: FunctionComponent = ({ } return ( - <>{children} +
+ +
); }; diff --git a/src/components/Page.tsx b/src/components/Page.tsx index be1253740f..c4677fee48 100644 --- a/src/components/Page.tsx +++ b/src/components/Page.tsx @@ -6,6 +6,7 @@ type PageProps = { id: string, // id is required for libraryMenu title?: string, isBackButtonEnabled?: boolean, + isMenuButtonEnabled?: boolean, isNowPlayingBarEnabled?: boolean, isThemeMediaSupported?: boolean }; @@ -20,6 +21,7 @@ const Page: FunctionComponent> = ({ className = '', title, isBackButtonEnabled = true, + isMenuButtonEnabled = false, isNowPlayingBarEnabled = true, isThemeMediaSupported = false }) => { @@ -60,6 +62,7 @@ const Page: FunctionComponent> = ({ className={`page ${className}`} data-title={title} data-backbutton={`${isBackButtonEnabled}`} + data-menubutton={`${isMenuButtonEnabled}`} > {children} diff --git a/src/components/appRouter.js b/src/components/appRouter.js index cab40043b1..f2bc0e27b0 100644 --- a/src/components/appRouter.js +++ b/src/components/appRouter.js @@ -9,7 +9,6 @@ import loading from './loading/loading'; import viewManager from './viewManager/viewManager'; import ServerConnections from './ServerConnections'; import alert from './alert'; -import reactControllerFactory from './reactControllerFactory'; export const history = createHashHistory(); @@ -264,9 +263,7 @@ class AppRouter { this.#sendRouteToViewManager(ctx, next, route, controllerFactory); }; - if (route.pageComponent) { - onInitComplete(reactControllerFactory); - } else if (route.controller) { + if (route.controller) { import('../controllers/' + route.controller).then(onInitComplete); } else { onInitComplete(); @@ -293,7 +290,6 @@ class AppRouter { fullscreen: route.fullscreen, controllerFactory: controllerFactory, options: { - pageComponent: route.pageComponent, supportsThemeMedia: route.supportsThemeMedia || false, enableMediaControl: route.enableMediaControl !== false }, diff --git a/src/components/dashboard/users/AccessContainer.tsx b/src/components/dashboard/users/AccessContainer.tsx index 5c0d6341b7..656292ece7 100644 --- a/src/components/dashboard/users/AccessContainer.tsx +++ b/src/components/dashboard/users/AccessContainer.tsx @@ -1,6 +1,6 @@ import React, { FunctionComponent } from 'react'; import globalize from '../../../scripts/globalize'; -import CheckBoxElement from './CheckBoxElement'; +import CheckBoxElement from '../../../elements/CheckBoxElement'; type IProps = { containerClassName?: string; @@ -18,7 +18,11 @@ const AccessContainer: FunctionComponent = ({containerClassName, headerT return (

{globalize.translate(headerTitle)}

- +

diff --git a/src/components/dashboard/users/AccessScheduleList.tsx b/src/components/dashboard/users/AccessScheduleList.tsx index 1e788d796f..1c776d12c6 100644 --- a/src/components/dashboard/users/AccessScheduleList.tsx +++ b/src/components/dashboard/users/AccessScheduleList.tsx @@ -1,17 +1,7 @@ import React, { FunctionComponent } from 'react'; import datetime from '../../../scripts/datetime'; import globalize from '../../../scripts/globalize'; - -const createButtonElement = (index: number) => ({ - __html: `` -}); +import IconButtonElement from '../../../elements/IconButtonElement'; type IProps = { index: number; @@ -48,8 +38,12 @@ const AccessScheduleList: FunctionComponent = ({index, DayOfWeek, StartH {getDisplayTime(StartHour) + ' - ' + getDisplayTime(EndHour)}

-
); diff --git a/src/components/dashboard/users/BlockedTagList.tsx b/src/components/dashboard/users/BlockedTagList.tsx index 8f686381f4..58db4eb2e1 100644 --- a/src/components/dashboard/users/BlockedTagList.tsx +++ b/src/components/dashboard/users/BlockedTagList.tsx @@ -1,15 +1,5 @@ import React, { FunctionComponent } from 'react'; - -const createButtonElement = (tag?: string) => ({ - __html: `` -}); +import IconButtonElement from '../../../elements/IconButtonElement'; type IProps = { tag?: string; @@ -24,11 +14,14 @@ const BlockedTagList: FunctionComponent = ({tag}: IProps) => { {tag}
-
- ); }; diff --git a/src/components/dashboard/users/ButtonElement.tsx b/src/components/dashboard/users/ButtonElement.tsx deleted file mode 100644 index c63a1feeb8..0000000000 --- a/src/components/dashboard/users/ButtonElement.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import React, { FunctionComponent } from 'react'; -import globalize from '../../../scripts/globalize'; - -const createButtonElement = ({ type, className, title }: { type?: string, className?: string, title?: string }) => ({ - __html: `` -}); - -type IProps = { - type?: string; - className?: string; - title?: string -} - -const ButtonElement: FunctionComponent = ({ type, className, title }: IProps) => { - return ( -
- ); -}; - -export default ButtonElement; diff --git a/src/components/dashboard/users/CheckBoxElement.tsx b/src/components/dashboard/users/CheckBoxElement.tsx deleted file mode 100644 index 36136e393a..0000000000 --- a/src/components/dashboard/users/CheckBoxElement.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import React, { FunctionComponent } from 'react'; -import globalize from '../../../scripts/globalize'; - -const createCheckBoxElement = ({ labelClassName, type, className, title }: { labelClassName?: string, type?: string, className?: string, title?: string }) => ({ - __html: `` -}); - -type IProps = { - labelClassName?: string; - type?: string; - className?: string; - title?: string -} - -const CheckBoxElement: FunctionComponent = ({ labelClassName, type, className, title }: IProps) => { - return ( -
- ); -}; - -export default CheckBoxElement; diff --git a/src/components/dashboard/users/CheckBoxListItem.tsx b/src/components/dashboard/users/CheckBoxListItem.tsx deleted file mode 100644 index 02f7560e5f..0000000000 --- a/src/components/dashboard/users/CheckBoxListItem.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import escapeHtml from 'escape-html'; -import React, { FunctionComponent } from 'react'; - -type IProps = { - className?: string; - Name?: string; - Id?: string; - ItemType?: string; - AppName?: string; - checkedAttribute?: string; -} - -const createCheckBoxElement = ({className, Name, dataAttributes, AppName, checkedAttribute}: {className?: string, Name?: string, dataAttributes?: string, AppName?: string, checkedAttribute?: string}) => ({ - __html: `` -}); - -const CheckBoxListItem: FunctionComponent = ({className, Name, Id, ItemType, AppName, checkedAttribute}: IProps) => { - return ( -
- ); -}; - -export default CheckBoxListItem; - diff --git a/src/components/dashboard/users/SectionTitleButtonElement.tsx b/src/components/dashboard/users/SectionTitleButtonElement.tsx deleted file mode 100644 index 1c0c8de22a..0000000000 --- a/src/components/dashboard/users/SectionTitleButtonElement.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import React, { FunctionComponent } from 'react'; -import globalize from '../../../scripts/globalize'; - -type IProps = { - title: string; - className?: string; - icon: string, -} - -const createButtonElement = ({ className, title, icon }: { className?: string, title: string, icon: string }) => ({ - __html: `` -}); - -const SectionTitleButtonElement: FunctionComponent = ({ className, title, icon }: IProps) => { - return ( -
- ); -}; - -export default SectionTitleButtonElement; diff --git a/src/components/dashboard/users/SectionTitleContainer.tsx b/src/components/dashboard/users/SectionTitleContainer.tsx deleted file mode 100644 index e5e4b8952a..0000000000 --- a/src/components/dashboard/users/SectionTitleContainer.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import React, { FunctionComponent } from 'react'; -import SectionTitleButtonElement from './SectionTitleButtonElement'; -import SectionTitleLinkElement from './SectionTitleLinkElement'; - -type IProps = { - title: string; - isBtnVisible?: boolean; - titleLink?: string; -} - -const SectionTitleContainer: FunctionComponent = ({title, isBtnVisible = false, titleLink}: IProps) => { - return ( -
-
-

- {title} -

- - {isBtnVisible && } - - -
-
- ); -}; - -export default SectionTitleContainer; diff --git a/src/components/dashboard/users/SelectElement.tsx b/src/components/dashboard/users/SelectElement.tsx deleted file mode 100644 index 329dd9b575..0000000000 --- a/src/components/dashboard/users/SelectElement.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import escapeHtml from 'escape-html'; -import React, { FunctionComponent } from 'react'; -import globalize from '../../../scripts/globalize'; - -const createSelectElement = ({ className, label, option }: { className?: string, label: string, option: string[] }) => ({ - __html: `` -}); - -type ProvidersArr = { - Name?: string; - Id?: string; -} - -type IProps = { - className?: string; - label?: string; - currentProviderId: string; - providers: ProvidersArr[] -} - -const SelectElement: FunctionComponent = ({ className, label, currentProviderId, providers }: IProps) => { - const renderOption = providers.map((provider) => { - const selected = provider.Id === currentProviderId || providers.length < 2 ? ' selected' : ''; - return ''; - }); - - return ( -
- ); -}; - -export default SelectElement; diff --git a/src/components/dashboard/users/SelectMaxParentalRating.tsx b/src/components/dashboard/users/SelectMaxParentalRating.tsx deleted file mode 100644 index d1865b29e7..0000000000 --- a/src/components/dashboard/users/SelectMaxParentalRating.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import escapeHtml from 'escape-html'; -import React, { FunctionComponent } from 'react'; -import globalize from '../../../scripts/globalize'; - -const createSelectElement = ({ className, label, option }: { className?: string, label: string, option: string }) => ({ - __html: `` -}); - -type RatingsArr = { - Name: string; - Value: number; -} - -type IProps = { - className?: string; - label?: string; - parentalRatings: RatingsArr[]; -} - -const SelectMaxParentalRating: FunctionComponent = ({ className, label, parentalRatings }: IProps) => { - const renderOption = () => { - let content = ''; - for (const rating of parentalRatings) { - content += ``; - } - return content; - }; - - return ( -
- ); -}; - -export default SelectMaxParentalRating; diff --git a/src/components/dashboard/users/SelectSyncPlayAccessElement.tsx b/src/components/dashboard/users/SelectSyncPlayAccessElement.tsx deleted file mode 100644 index ca4a664794..0000000000 --- a/src/components/dashboard/users/SelectSyncPlayAccessElement.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import React, { FunctionComponent } from 'react'; -import globalize from '../../../scripts/globalize'; - -const createSelectElement = ({ className, id, label }: { className?: string, id?: string, label: string }) => ({ - __html: `` -}); - -type IProps = { - className?: string; - id?: string; - label?: string -} - -const SelectSyncPlayAccessElement: FunctionComponent = ({ className, id, label }: IProps) => { - return ( -
- ); -}; - -export default SelectSyncPlayAccessElement; diff --git a/src/components/dashboard/users/UserCardBox.tsx b/src/components/dashboard/users/UserCardBox.tsx index 28d38cce5a..0346e8d264 100644 --- a/src/components/dashboard/users/UserCardBox.tsx +++ b/src/components/dashboard/users/UserCardBox.tsx @@ -4,6 +4,8 @@ import { formatDistanceToNow } from 'date-fns'; import { localeWithSuffix } from '../../../scripts/dfnshelper'; import globalize from '../../../scripts/globalize'; import cardBuilder from '../../cardbuilder/cardBuilder'; +import IconButtonElement from '../../../elements/IconButtonElement'; +import escapeHTML from 'escape-html'; const createLinkElement = ({ user, renderImgUrl }: { user: UserDto, renderImgUrl: string }) => ({ __html: `` }); -const createButtonElement = () => ({ - __html: `` -}); - type IProps = { user?: UserDto; } @@ -81,16 +73,20 @@ const UserCardBox: FunctionComponent = ({ user = {} }: IProps) => { />
-
-
- {user.Name} -
-
+
+
+ {escapeHTML(user.Name)} +
- {lastSeen != '' ? lastSeen : ''} + {lastSeen != '' ? lastSeen : ''}
diff --git a/src/components/dashboard/users/UserPasswordForm.tsx b/src/components/dashboard/users/UserPasswordForm.tsx index e387090949..7a43446901 100644 --- a/src/components/dashboard/users/UserPasswordForm.tsx +++ b/src/components/dashboard/users/UserPasswordForm.tsx @@ -6,9 +6,9 @@ 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'; +import ButtonElement from '../../../elements/ButtonElement'; +import CheckBoxElement from '../../../elements/CheckBoxElement'; +import InputElement from '../../../elements/InputElement'; type IProps = { userId: string; @@ -40,11 +40,11 @@ const UserPasswordForm: FunctionComponent = ({userId}: IProps) => { let showLocalAccessSection = false; if (user.HasConfiguredPassword) { - (page.querySelector('.btnResetPassword') as HTMLDivElement).classList.remove('hide'); + (page.querySelector('#btnResetPassword') as HTMLDivElement).classList.remove('hide'); (page.querySelector('#fldCurrentPassword') as HTMLDivElement).classList.remove('hide'); showLocalAccessSection = true; } else { - (page.querySelector('.btnResetPassword') as HTMLDivElement).classList.add('hide'); + (page.querySelector('#btnResetPassword') as HTMLDivElement).classList.add('hide'); (page.querySelector('#fldCurrentPassword') as HTMLDivElement).classList.add('hide'); } @@ -65,11 +65,11 @@ const UserPasswordForm: FunctionComponent = ({userId}: IProps) => { if (user.HasConfiguredEasyPassword) { txtEasyPassword.placeholder = '******'; - (page.querySelector('.btnResetEasyPassword') as HTMLDivElement).classList.remove('hide'); + (page.querySelector('#btnResetEasyPassword') as HTMLDivElement).classList.remove('hide'); } else { txtEasyPassword.removeAttribute('placeholder'); txtEasyPassword.placeholder = ''; - (page.querySelector('.btnResetEasyPassword') as HTMLDivElement).classList.add('hide'); + (page.querySelector('#btnResetEasyPassword') as HTMLDivElement).classList.add('hide'); } const chkEnableLocalEasyPassword = page.querySelector('.chkEnableLocalEasyPassword') as HTMLInputElement; @@ -206,8 +206,8 @@ const UserPasswordForm: FunctionComponent = ({userId}: IProps) => { (page.querySelector('.updatePasswordForm') as HTMLFormElement).addEventListener('submit', onSubmit); (page.querySelector('.localAccessForm') as HTMLFormElement).addEventListener('submit', onLocalAccessSubmit); - (page.querySelector('.btnResetEasyPassword') as HTMLButtonElement).addEventListener('click', resetEasyPassword); - (page.querySelector('.btnResetPassword') as HTMLButtonElement).addEventListener('click', resetPassword); + (page.querySelector('#btnResetEasyPassword') as HTMLButtonElement).addEventListener('click', resetEasyPassword); + (page.querySelector('#btnResetPassword') as HTMLButtonElement).addEventListener('click', resetPassword); }, [loadUser, userId]); return ( @@ -250,7 +250,8 @@ const UserPasswordForm: FunctionComponent = ({userId}: IProps) => { />
@@ -281,7 +282,6 @@ const UserPasswordForm: FunctionComponent = ({userId}: IProps) => {
@@ -297,7 +297,8 @@ const UserPasswordForm: FunctionComponent = ({userId}: IProps) => { />
diff --git a/src/components/reactControllerFactory.js b/src/components/reactControllerFactory.js deleted file mode 100644 index 9611b706ee..0000000000 --- a/src/components/reactControllerFactory.js +++ /dev/null @@ -1,17 +0,0 @@ -import React from 'react'; -import ReactDOM from 'react-dom'; - -export default (view, params, { detail }) => { - if (detail.options?.pageComponent) { - // Fetch and render the page component to the view - import(/* webpackChunkName: "[request]" */ `./pages/${detail.options.pageComponent}`) - .then(({ default: component }) => { - ReactDOM.render(React.createElement(component, params), view); - }); - - // Unmount component when view is destroyed - view.addEventListener('viewdestroy', () => { - ReactDOM.unmountComponentAtNode(view); - }); - } -}; diff --git a/src/components/viewManager/viewManager.js b/src/components/viewManager/viewManager.js index 5073cccf8c..48c708d2a0 100644 --- a/src/components/viewManager/viewManager.js +++ b/src/components/viewManager/viewManager.js @@ -21,9 +21,9 @@ viewContainer.setOnBeforeChange(function (newView, isRestored, options) { newView.initComplete = true; if (typeof options.controllerFactory === 'function') { - new options.controllerFactory(newView, eventDetail.detail.params, eventDetail); + new options.controllerFactory(newView, eventDetail.detail.params); } else if (options.controllerFactory && typeof options.controllerFactory.default === 'function') { - new options.controllerFactory.default(newView, eventDetail.detail.params, eventDetail); + new options.controllerFactory.default(newView, eventDetail.detail.params); } if (!options.controllerFactory || dispatchPageEvents) { diff --git a/src/controllers/dashboard/users/useredit.html b/src/controllers/dashboard/users/useredit.html deleted file mode 100644 index e4b6afd33e..0000000000 --- a/src/controllers/dashboard/users/useredit.html +++ /dev/null @@ -1,3 +0,0 @@ -
- -
diff --git a/src/controllers/dashboard/users/userlibraryaccess.html b/src/controllers/dashboard/users/userlibraryaccess.html deleted file mode 100644 index abcbfaf103..0000000000 --- a/src/controllers/dashboard/users/userlibraryaccess.html +++ /dev/null @@ -1,3 +0,0 @@ -
- -
diff --git a/src/controllers/dashboard/users/usernew.html b/src/controllers/dashboard/users/usernew.html deleted file mode 100644 index c3f77c5e49..0000000000 --- a/src/controllers/dashboard/users/usernew.html +++ /dev/null @@ -1,3 +0,0 @@ -
- -
diff --git a/src/controllers/dashboard/users/userparentalcontrol.html b/src/controllers/dashboard/users/userparentalcontrol.html deleted file mode 100644 index 8a93c3f931..0000000000 --- a/src/controllers/dashboard/users/userparentalcontrol.html +++ /dev/null @@ -1,3 +0,0 @@ -
- -
diff --git a/src/controllers/dashboard/users/userpassword.html b/src/controllers/dashboard/users/userpassword.html deleted file mode 100644 index 984fcc2c9c..0000000000 --- a/src/controllers/dashboard/users/userpassword.html +++ /dev/null @@ -1,3 +0,0 @@ -
- -
diff --git a/src/controllers/dashboard/users/userprofiles.html b/src/controllers/dashboard/users/userprofiles.html deleted file mode 100644 index 047cdff1fc..0000000000 --- a/src/controllers/dashboard/users/userprofiles.html +++ /dev/null @@ -1,3 +0,0 @@ -
- -
diff --git a/src/controllers/user/menu/index.html b/src/controllers/user/menu/index.html index 185dad7c7d..2741f89282 100644 --- a/src/controllers/user/menu/index.html +++ b/src/controllers/user/menu/index.html @@ -3,7 +3,7 @@

-
+
diff --git a/src/controllers/user/menu/index.js b/src/controllers/user/menu/index.js index 0dce218036..69606f1d05 100644 --- a/src/controllers/user/menu/index.js +++ b/src/controllers/user/menu/index.js @@ -26,7 +26,7 @@ export default function (view, params) { const userId = params.userId || Dashboard.getCurrentUserId(); const page = this; - page.querySelector('.lnkMyProfile').setAttribute('href', '#/myprofile.html?userId=' + userId); + page.querySelector('.lnkUserProfile').setAttribute('href', '#/userprofile.html?userId=' + userId); page.querySelector('.lnkDisplayPreferences').setAttribute('href', '#/mypreferencesdisplay.html?userId=' + userId); page.querySelector('.lnkHomePreferences').setAttribute('href', '#/mypreferenceshome.html?userId=' + userId); page.querySelector('.lnkPlaybackPreferences').setAttribute('href', '#/mypreferencesplayback.html?userId=' + userId); diff --git a/src/controllers/user/profile/index.html b/src/controllers/user/profile/index.html deleted file mode 100644 index c8fb3ae19d..0000000000 --- a/src/controllers/user/profile/index.html +++ /dev/null @@ -1,3 +0,0 @@ -
- -
diff --git a/src/elements/ButtonElement.tsx b/src/elements/ButtonElement.tsx new file mode 100644 index 0000000000..3de90f0c11 --- /dev/null +++ b/src/elements/ButtonElement.tsx @@ -0,0 +1,41 @@ +import React, { FunctionComponent } from 'react'; +import globalize from '../scripts/globalize'; + +const createButtonElement = ({ type, id, className, title, leftIcon, rightIcon }: IProps) => ({ + __html: `` +}); + +type IProps = { + type?: string; + id?: string; + className?: string; + title?: string; + leftIcon?: string; + rightIcon?: string; +} + +const ButtonElement: FunctionComponent = ({ type, id, className, title, leftIcon, rightIcon }: IProps) => { + return ( +