@samitouri / QOSami-HFS / commits / c1880ac5

ux: admin/options: clear button for some number fields

Massimo Melina committed Sep 22, 2024 at 18:00 UTC c1880ac5c11bda08708cc4466691f77caf497bac
3 files changed +20 -17
admin/src/OptionsPage.ts
+5 -5
@@ -57,7 +57,6 @@ export default function OptionsPage() {
57 }
58 const maxDownloadsDefaults = {
59 comp: NumberField,
60 - min: 0,
60 placeholder: "no limit",
61 toField: (x: any) => x || '',
62 sm: 4,
@@ -146,7 +145,7 @@ export default function OptionsPage() {
145 helperText: "Access Admin-panel without entering credentials"
146 },
147
149 - { k: 'proxies', comp: NumberField, min: 0, max: 9, label: "Number of HTTP proxies", placeholder: "none",
148 + { k: 'proxies', comp: NumberField, max: 9, label: "Number of HTTP proxies", placeholder: "none",
149 error: proxyWarning(values, status),
150 helperText: "Wrong number will prevent detection of users' IP address"
151 },
@@ -182,7 +181,7 @@ export default function OptionsPage() {
181
182 { k: 'auto_play_seconds', comp: NumberField, xs: 6, sm: 3, min: 1, max: 10000, required: true,
183 label: "Auto-play seconds delay", helperText: md(`Default value for the [Show interface](${REPO_URL}discussions/270)`) },
185 - { k: 'tile_size', comp: NumberField, xs: 6, sm: 3, min: 0, max: MAX_TILE_SIZE, required: true,
184 + { k: 'tile_size', comp: NumberField, xs: 6, sm: 3, max: MAX_TILE_SIZE, required: true,
185 label: "Default tiles size", helperText: wikiLink('Tiles', "To enable tiles-mode") },
186 { k: 'theme', comp: SelectField, xs: 6, sm: 3, options: THEME_OPTIONS },
187 { k: 'sort_by', comp: SelectField, xs: 6, sm: 3, options: SORT_BY_OPTIONS },
@@ -196,7 +195,8 @@ export default function OptionsPage() {
195 h(Section, { title: "Uploads" }),
196 { k: 'dont_overwrite_uploading', comp: BoolField, md: 4, label: "Uploads don't overwrite",
197 helperText: "Files will be numbered to avoid overwriting" },
199 - { k : CFG.split_uploads, comp: NumberField, unit: 'MB', md: 2, fromField: x => x * 1E6, toField: x => x ? x / 1E6 : null, min: 0, step: .1,
198 + { k : CFG.split_uploads, comp: NumberField, unit: 'MB', md: 2, step: .1,
199 + fromField: x => x * 1E6, toField: x => x ? x / 1E6 : null,
200 placeholder: "disabled", label: "Split uploads in chunks", helperText: "Overcome proxy limits" },
201 { k: 'delete_unfinished_uploads_after', comp: NumberField, md: 3, min : 0, unit: "seconds", placeholder: "Never",
202 helperText: "Leave empty to never delete" },
@@ -206,7 +206,7 @@ export default function OptionsPage() {
206 h(Section, { title: "Others" }),
207 { k: 'keep_session_alive', comp: BoolField, sm: 4, md: 6, helperText: "Keeps you logged in while the page is left open and the computer is on" },
208 { k: 'session_duration', comp: NumberField, sm: 4, md: 3, min: 5, unit: "seconds", required: true },
209 - { k: 'zip_calculate_size_for_seconds', comp: NumberField, sm: 4, md: 3, unit: "seconds", required: true, min: 0,
209 + { k: 'zip_calculate_size_for_seconds', comp: NumberField, sm: 4, md: 3, unit: "seconds", required: true,
210 label: "Calculate ZIP size for", helperText: "If time is not enough, the browser will not show download percentage" },
211
212 { k: 'descript_ion', comp: BoolField, ...isWindows && { sm: 4, md: 3 }, label: "Enable comments", helperText: "In file DESCRIPT.ION" },
admin/src/importAccountsCsv.ts
+1 -1
@@ -37,7 +37,7 @@ export async function importAccountsCsv(cb?: () => void) {
37 save: { startIcon: h(Upload), children: 'Go' },
38 fields: [
39 h(Box, { p: 1 }, "Total lines:", rows.length),
40 - { k: 'skipFirstLines', comp: NumberField, min: 0, max: rows.length-1, typing: true, md: 6,
40 + { k: 'skipFirstLines', comp: NumberField, max: rows.length-1, typing: true, md: 6,
41 helperText: h(Fragment, {}, "First line: ", h('code', {}, row.join(', ')) ),
42 },
43 { k: 'overwriteExistingAccounts', comp: BoolField, md: 6 },
mui-grid-form/misc-fields.ts
+14 -11
@@ -4,16 +4,10 @@ import { createElement as h, useEffect, useState } from 'react'
4 import { StringField } from './StringField'
5 import { FieldProps } from '.'
6 import {
7 - Box,
8 - Checkbox,
9 - FormControl,
10 - FormControlLabel,
11 - FormGroup,
12 - FormHelperText,
13 - FormLabel,
14 - InputAdornment,
15 - Switch
7 + Box, Checkbox, FormControl, FormControlLabel, FormGroup, FormHelperText, FormLabel, IconButton,
8 + InputAdornment, Switch
9 } from '@mui/material'
10 +import { Cancel } from '@mui/icons-material'
11 import _ from 'lodash'
12
13 export function DisplayField({ value, empty='-', ...props }: any) {
@@ -22,7 +16,7 @@ export function DisplayField({ value, empty='-', ...props }: any) {
16 return h(StringField, { ...props, value, disabled: true })
17 }
18
25 -export function NumberField({ value, onChange, setApi, required, min, max, step, unit, ...props }: FieldProps<number | null>) {
19 +export function NumberField({ value, onChange, setApi, required, min=0, max, step, unit, clearable, ...props }: FieldProps<number | null>) {
20 setApi?.({
21 getError() {
22 return value == null ? (required ? "required" : false)
@@ -40,7 +34,16 @@ export function NumberField({ value, onChange, setApi, required, min, max, step,
34 },
35 inputProps: { min, max, step, },
36 InputProps: _.merge({
43 - sx: { '& input': { appearance: 'textfield' } }
37 + sx: { '& input': { appearance: 'textfield' } },
38 + startAdornment: (clearable ?? props.placeholder) && (value || value === 0) && h(InputAdornment, {
39 + position: 'start',
40 + }, h(IconButton, {
41 + size: 'small',
42 + edge: 'start',
43 + sx: { ml: -1, opacity: .5 },
44 + 'aria-label': "clear",
45 + onClick(event){ onChange(null, { was: value, event }) }
46 + }, h(Cancel))),
47 }, unit && {
48 sx: { pr: '6px', '& input': { pl: '.2em', textAlign: 'right' } },
49 endAdornment: h(InputAdornment, {