admin/custom: persist section

Massimo Melina committed Apr 12, 2024 at 12:40 UTC ee6af530f562771860ff2864fc4352bf81e2c74e
3 files changed +14 -6
admin/src/CustomHtmlPage.ts
+10 -4
@@ -10,6 +10,7 @@ import { Save } from '@mui/icons-material'
10 import _ from 'lodash'
11 import { useDebounce } from 'usehooks-ts'
12 import { TextEditor } from './TextEditor';
13 +import { state, useSnapState } from './state'
14
15 const names: any = {
16 top: "Top of HTML Body",
@@ -18,15 +19,15 @@ const names: any = {
19
20 export default function CustomHtmlPage() {
21 const { data, reload } = useApiEx<{ sections: Dict<string> }>('get_custom_html')
21 - const [section, setSection] = useState('')
22 + const { customHtmlSection: section } = useSnapState()
23 const [all, setAll] = useState<Dict<string>>({})
24 const [saved, setSaved] = useState({})
25 useEffect(() => data && setSaved(data?.sections), [data])
26 useEffect(() => setAll(saved), [saved])
27 const options = useMemo(() => {
28 const keys = _.sortBy(Object.keys(all), x => !isNaN(+x)) // http codes at the bottom
28 - if (!keys.includes(section))
29 - setSection(_.findKey(all, Boolean) || keys?.[0] || '') // prefer any key with content
29 + if (keys.length && !keys.includes(section))
30 + state.customHtmlSection = _.findKey(all, Boolean) || keys?.[0] || '' // prefer any key with content
31 return keys.map(x => ({
32 value: x,
33 label: (names[x] || prefix('HTTP ', HTTP_MESSAGES[x as any]) || _.startCase(x)) + (all[x]?.trim() ? ' *' : '')
@@ -40,7 +41,12 @@ export default function CustomHtmlPage() {
41 wikiLink('customization', "More help")
42 ),
43 h(Box, { display: 'flex', alignItems: 'center', gap: 1, mb: 1 },
43 - h(SelectField as Field<string>, { label: "Section", value: section, options, onChange: setSection }),
44 + h(SelectField as Field<string>, {
45 + label: "Section",
46 + value: section,
47 + options,
48 + onChange: v => state.customHtmlSection = v
49 + }),
50 reloadBtn(reload),
51 h(IconBtn, {
52 icon: Save,
admin/src/FileForm.ts
+1 -1
@@ -5,7 +5,7 @@ import { createElement as h, forwardRef, ReactElement, ReactNode, useEffect, use
5 import { Alert, Box, Collapse, FormHelperText, Link, MenuItem, MenuList, useTheme } from '@mui/material'
6 import { BoolField, DisplayField, Field, FieldProps, Form, MultiSelectField, SelectField, StringField
7 } from '@hfs/mui-grid-form'
8 -import { apiCall, UseApi, useApiEx } from './api'
8 +import { apiCall, UseApi } from './api'
9 import { basename, defaultPerms, formatBytes, formatTimestamp, isEqualLax, isWhoObject, newDialog, objSameKeys,
10 onlyTruthy, prefix, VfsPerms, wantArray, Who, WhoObject, matches, HTTP_MESSAGES, xlate, md } from './misc'
11 import { Btn, IconBtn, LinkBtn, modifiedProps, useBreakpoint, wikiLink } from './mui'
admin/src/state.ts
+3 -1
@@ -16,6 +16,7 @@ export const state = proxy<{
16 loginRequired: boolean | number
17 username: string
18 monitorOnlyFiles: boolean
19 + customHtmlSection: string,
20 onlinePluginsColumns: Dict<boolean>
21 }>(Object.assign({
22 title: '',
@@ -26,6 +27,7 @@ export const state = proxy<{
27 loginRequired: false,
28 username: '',
29 monitorOnlyFiles: true,
30 + customHtmlSection: '',
31 onlinePluginsColumns: {
32 version: false,
33 pushed_at: false,
@@ -33,7 +35,7 @@ export const state = proxy<{
35 }
36 }, JSON.parse(localStorage[STORAGE_KEY]||null)))
37
36 -const SETTINGS_TO_STORE: (keyof typeof state)[] = ['onlinePluginsColumns', 'monitorOnlyFiles']
38 +const SETTINGS_TO_STORE: (keyof typeof state)[] = ['onlinePluginsColumns', 'monitorOnlyFiles', 'customHtmlSection']
39 const storeSettings = _.debounce(() =>
40 localStorage[STORAGE_KEY] = JSON.stringify(_.pick(state, SETTINGS_TO_STORE)), 500, { maxWait: 1000 })
41 for (const k of SETTINGS_TO_STORE)