diff --git a/ui/src/personal/HelpMsg.js b/ui/src/personal/HelpMsg.js
new file mode 100644
index 000000000..d95eec1b6
--- /dev/null
+++ b/ui/src/personal/HelpMsg.js
@@ -0,0 +1,8 @@
+import HelpOutlineIcon from '@material-ui/icons/HelpOutline'
+
+export const HelpMsg = ({ caption }) => (
+ <>
+
+ {caption}
+ >
+)
diff --git a/ui/src/personal/NotificationsToggle.js b/ui/src/personal/NotificationsToggle.js
new file mode 100644
index 000000000..f9b424fb7
--- /dev/null
+++ b/ui/src/personal/NotificationsToggle.js
@@ -0,0 +1,64 @@
+import { useNotify, useTranslate } from 'react-admin'
+import { useDispatch, useSelector } from 'react-redux'
+import { setNotificationsState } from '../actions'
+import {
+ FormControl,
+ FormControlLabel,
+ FormHelperText,
+ Switch,
+} from '@material-ui/core'
+
+export const NotificationsToggle = () => {
+ const translate = useTranslate()
+ const dispatch = useDispatch()
+ const notify = useNotify()
+ const currentSetting = useSelector((state) => state.settings.notifications)
+ const notAvailable = !('Notification' in window) || !window.isSecureContext
+
+ if (
+ (currentSetting && Notification.permission !== 'granted') ||
+ notAvailable
+ ) {
+ dispatch(setNotificationsState(false))
+ }
+
+ const toggleNotifications = (event) => {
+ if (currentSetting && !event.target.checked) {
+ dispatch(setNotificationsState(false))
+ } else {
+ if (Notification.permission === 'denied') {
+ notify(translate('message.notifications_blocked'), 'warning')
+ } else {
+ Notification.requestPermission().then((permission) => {
+ dispatch(setNotificationsState(permission === 'granted'))
+ })
+ }
+ }
+ }
+
+ return (
+
+
+ }
+ label={
+
+ {translate('menu.personal.options.desktop_notifications')}
+
+ }
+ />
+ {notAvailable && (
+
+ {translate('message.notifications_not_available')}
+
+ )}
+
+ )
+}
diff --git a/ui/src/personal/Personal.js b/ui/src/personal/Personal.js
index 114cf49fb..1a1925886 100644
--- a/ui/src/personal/Personal.js
+++ b/ui/src/personal/Personal.js
@@ -1,196 +1,15 @@
-import React from 'react'
-import { useDispatch, useSelector } from 'react-redux'
-import {
- Card,
- FormControl,
- FormHelperText,
- FormControlLabel,
- Switch,
-} from '@material-ui/core'
-import {
- SelectInput,
- SimpleForm,
- Title,
- useLocale,
- useNotify,
- useSetLocale,
- useTranslate,
-} from 'react-admin'
+import { SimpleForm, Title, useTranslate } from 'react-admin'
+import { Card } from '@material-ui/core'
import { makeStyles } from '@material-ui/core/styles'
-import HelpOutlineIcon from '@material-ui/icons/HelpOutline'
-import { changeTheme, setNotificationsState } from '../actions'
-import themes from '../themes'
-import { docsUrl } from '../utils'
-import { useGetLanguageChoices } from '../i18n'
-import albumLists, { defaultAlbumList } from '../album/albumLists'
-import { AUTO_THEME_ID } from '../consts'
+import { SelectLanguage } from './SelectLanguage'
+import { SelectTheme } from './SelectTheme'
+import { SelectDefaultView } from './SelectDefaultView'
+import { NotificationsToggle } from './NotificationsToggle'
const useStyles = makeStyles({
root: { marginTop: '1em' },
})
-const helpKey = '_help'
-
-function openInNewTab(url) {
- const win = window.open(url, '_blank')
- win.focus()
-}
-
-const HelpMsg = ({ caption }) => (
- <>
-
- {caption}
- >
-)
-
-const SelectLanguage = (props) => {
- const translate = useTranslate()
- const setLocale = useSetLocale()
- const locale = useLocale()
- const { choices } = useGetLanguageChoices()
-
- choices.push({
- id: helpKey,
- name: ,
- })
-
- return (
- {
- if (event.target.value === helpKey) {
- openInNewTab(docsUrl('/docs/developers/translations/'))
- return
- }
- setLocale(event.target.value).then(() => {
- localStorage.setItem('locale', event.target.value)
- })
- }}
- />
- )
-}
-
-const SelectTheme = (props) => {
- const translate = useTranslate()
- const dispatch = useDispatch()
- const currentTheme = useSelector((state) => state.theme)
- const themeChoices = [
- {
- id: AUTO_THEME_ID,
- name: 'Auto',
- },
- ]
- themeChoices.push(
- ...Object.keys(themes).map((key) => {
- return { id: key, name: themes[key].themeName }
- })
- )
- themeChoices.push({
- id: helpKey,
- name: ,
- })
- return (
- {
- if (event.target.value === helpKey) {
- openInNewTab(docsUrl('/docs/developers/creating-themes/'))
- return
- }
- dispatch(changeTheme(event.target.value))
- }}
- />
- )
-}
-
-const SelectDefaultView = (props) => {
- const translate = useTranslate()
- const current = localStorage.getItem('defaultView') || defaultAlbumList
- const choices = Object.keys(albumLists).map((type) => ({
- id: type,
- name: translate(`resources.album.lists.${type}`),
- }))
-
- return (
- {
- localStorage.setItem('defaultView', event.target.value)
- }}
- />
- )
-}
-
-const NotificationsToggle = () => {
- const translate = useTranslate()
- const dispatch = useDispatch()
- const notify = useNotify()
- const currentSetting = useSelector((state) => state.settings.notifications)
- const notAvailable = !('Notification' in window) || !window.isSecureContext
-
- if (
- (currentSetting && Notification.permission !== 'granted') ||
- notAvailable
- ) {
- dispatch(setNotificationsState(false))
- }
-
- const toggleNotifications = (event) => {
- if (currentSetting && !event.target.checked) {
- dispatch(setNotificationsState(false))
- } else {
- if (Notification.permission === 'denied') {
- notify(translate('message.notifications_blocked'), 'warning')
- } else {
- Notification.requestPermission().then((permission) => {
- dispatch(setNotificationsState(permission === 'granted'))
- })
- }
- }
- }
-
- return (
-
-
- }
- label={
-
- {translate('menu.personal.options.desktop_notifications')}
-
- }
- />
- {notAvailable && (
-
- {translate('message.notifications_not_available')}
-
- )}
-
- )
-}
-
const Personal = () => {
const translate = useTranslate()
const classes = useStyles()
diff --git a/ui/src/personal/SelectDefaultView.js b/ui/src/personal/SelectDefaultView.js
new file mode 100644
index 000000000..71c87305c
--- /dev/null
+++ b/ui/src/personal/SelectDefaultView.js
@@ -0,0 +1,25 @@
+import { SelectInput, useTranslate } from 'react-admin'
+import albumLists, { defaultAlbumList } from '../album/albumLists'
+
+export const SelectDefaultView = (props) => {
+ const translate = useTranslate()
+ const current = localStorage.getItem('defaultView') || defaultAlbumList
+ const choices = Object.keys(albumLists).map((type) => ({
+ id: type,
+ name: translate(`resources.album.lists.${type}`),
+ }))
+
+ return (
+ {
+ localStorage.setItem('defaultView', event.target.value)
+ }}
+ />
+ )
+}
diff --git a/ui/src/personal/SelectLanguage.js b/ui/src/personal/SelectLanguage.js
new file mode 100644
index 000000000..700d902e1
--- /dev/null
+++ b/ui/src/personal/SelectLanguage.js
@@ -0,0 +1,38 @@
+import { SelectInput, useLocale, useSetLocale, useTranslate } from 'react-admin'
+import { useGetLanguageChoices } from '../i18n'
+import { HelpMsg } from './HelpMsg'
+import { docsUrl, openInNewTab } from '../utils'
+
+const helpKey = '_help'
+
+export const SelectLanguage = (props) => {
+ const translate = useTranslate()
+ const setLocale = useSetLocale()
+ const locale = useLocale()
+ const { choices } = useGetLanguageChoices()
+
+ choices.push({
+ id: helpKey,
+ name: ,
+ })
+
+ return (
+ {
+ if (event.target.value === helpKey) {
+ openInNewTab(docsUrl('/docs/developers/translations/'))
+ return
+ }
+ setLocale(event.target.value).then(() => {
+ localStorage.setItem('locale', event.target.value)
+ })
+ }}
+ />
+ )
+}
diff --git a/ui/src/personal/SelectTheme.js b/ui/src/personal/SelectTheme.js
new file mode 100644
index 000000000..e69d996ff
--- /dev/null
+++ b/ui/src/personal/SelectTheme.js
@@ -0,0 +1,47 @@
+import { SelectInput, useTranslate } from 'react-admin'
+import { useDispatch, useSelector } from 'react-redux'
+import { AUTO_THEME_ID } from '../consts'
+import themes from '../themes'
+import { HelpMsg } from './HelpMsg'
+import { docsUrl, openInNewTab } from '../utils'
+import { changeTheme } from '../actions'
+
+const helpKey = '_help'
+
+export const SelectTheme = (props) => {
+ const translate = useTranslate()
+ const dispatch = useDispatch()
+ const currentTheme = useSelector((state) => state.theme)
+ const themeChoices = [
+ {
+ id: AUTO_THEME_ID,
+ name: 'Auto',
+ },
+ ]
+ themeChoices.push(
+ ...Object.keys(themes).map((key) => {
+ return { id: key, name: themes[key].themeName }
+ })
+ )
+ themeChoices.push({
+ id: helpKey,
+ name: ,
+ })
+ return (
+ {
+ if (event.target.value === helpKey) {
+ openInNewTab(docsUrl('/docs/developers/creating-themes/'))
+ return
+ }
+ dispatch(changeTheme(event.target.value))
+ }}
+ />
+ )
+}
diff --git a/ui/src/utils/index.js b/ui/src/utils/index.js
index a5248211a..da366f14e 100644
--- a/ui/src/utils/index.js
+++ b/ui/src/utils/index.js
@@ -2,3 +2,4 @@ export * from './baseUrl'
export * from './docsUrl'
export * from './formatters'
export * from './notifications'
+export * from './openInNewTab'
diff --git a/ui/src/utils/openInNewTab.js b/ui/src/utils/openInNewTab.js
new file mode 100644
index 000000000..b5ad35612
--- /dev/null
+++ b/ui/src/utils/openInNewTab.js
@@ -0,0 +1,4 @@
+export const openInNewTab = (url) => {
+ const win = window.open(url, '_blank')
+ win.focus()
+}