hfs 0.26.8 → 0.26.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (161) hide show
  1. package/admin/assets/index.bb5198ec.js +281 -0
  2. package/admin/assets/index.dcc78777.css +1 -0
  3. package/admin/assets/sha512.9dfe82e1.js +8 -0
  4. package/admin/index.html +3 -1
  5. package/admin/{public/logo.svg → logo.svg} +0 -0
  6. package/frontend/assets/index.27a78796.js +85 -0
  7. package/frontend/assets/index.93366732.css +1 -0
  8. package/frontend/assets/sha512.6af42937.js +8 -0
  9. package/frontend/{public/fontello.css → fontello.css} +0 -0
  10. package/frontend/{public/fontello.woff2 → fontello.woff2} +0 -0
  11. package/frontend/index.html +3 -1
  12. package/package.json +1 -1
  13. package/src/QuickZipStream.js +285 -0
  14. package/src/ThrottledStream.js +93 -0
  15. package/src/adminApis.js +169 -0
  16. package/src/api.accounts.js +59 -0
  17. package/src/api.auth.js +128 -0
  18. package/src/api.file_list.js +103 -0
  19. package/src/api.helpers.js +32 -0
  20. package/src/api.monitor.js +102 -0
  21. package/src/api.plugins.js +127 -0
  22. package/src/api.vfs.js +164 -0
  23. package/src/apiMiddleware.js +120 -0
  24. package/src/block.js +33 -0
  25. package/src/commands.js +124 -0
  26. package/src/config.js +168 -0
  27. package/src/connections.js +57 -0
  28. package/src/const.js +83 -0
  29. package/src/crypt.js +21 -0
  30. package/src/debounceAsync.js +48 -0
  31. package/src/events.js +9 -0
  32. package/src/frontEndApis.js +38 -0
  33. package/src/github.js +102 -0
  34. package/src/index.js +56 -0
  35. package/src/listen.js +235 -0
  36. package/src/log.js +137 -0
  37. package/src/middlewares.js +175 -0
  38. package/src/misc.js +160 -0
  39. package/src/pbkdf2.js +74 -0
  40. package/src/perm.js +181 -0
  41. package/src/plugins.js +343 -0
  42. package/src/serveFile.js +105 -0
  43. package/src/serveGuiFiles.js +113 -0
  44. package/src/sse.js +29 -0
  45. package/src/throttler.js +91 -0
  46. package/src/update.js +69 -0
  47. package/src/util-files.js +148 -0
  48. package/src/util-generators.js +30 -0
  49. package/src/util-http.js +30 -0
  50. package/src/vfs.js +230 -0
  51. package/src/watchLoad.js +73 -0
  52. package/src/zip.js +72 -0
  53. package/admin/.DS_Store +0 -0
  54. package/admin/.eslintrc +0 -8
  55. package/admin/.gitignore +0 -23
  56. package/admin/package.json +0 -67
  57. package/admin/src/AccountForm.ts +0 -92
  58. package/admin/src/AccountsPage.ts +0 -143
  59. package/admin/src/App.ts +0 -83
  60. package/admin/src/ArrayField.ts +0 -84
  61. package/admin/src/ConfigPage.ts +0 -279
  62. package/admin/src/FileField.ts +0 -52
  63. package/admin/src/FileForm.ts +0 -148
  64. package/admin/src/FilePicker.ts +0 -166
  65. package/admin/src/HomePage.ts +0 -96
  66. package/admin/src/InstalledPlugins.ts +0 -158
  67. package/admin/src/LoginRequired.ts +0 -75
  68. package/admin/src/LogoutPage.ts +0 -27
  69. package/admin/src/LogsPage.ts +0 -75
  70. package/admin/src/MainMenu.ts +0 -74
  71. package/admin/src/MenuButton.ts +0 -38
  72. package/admin/src/MonitorPage.ts +0 -200
  73. package/admin/src/OnlinePlugins.ts +0 -101
  74. package/admin/src/PermField.ts +0 -80
  75. package/admin/src/PluginsPage.ts +0 -27
  76. package/admin/src/VfsMenuBar.ts +0 -58
  77. package/admin/src/VfsPage.ts +0 -124
  78. package/admin/src/VfsTree.ts +0 -95
  79. package/admin/src/addFiles.ts +0 -59
  80. package/admin/src/api.ts +0 -246
  81. package/admin/src/dialog.ts +0 -203
  82. package/admin/src/index.css +0 -21
  83. package/admin/src/index.ts +0 -10
  84. package/admin/src/md.ts +0 -31
  85. package/admin/src/misc.ts +0 -141
  86. package/admin/src/react-app-env.d.ts +0 -1
  87. package/admin/src/reportWebVitals.ts +0 -15
  88. package/admin/src/setupTests.ts +0 -5
  89. package/admin/src/state.ts +0 -40
  90. package/admin/src/theme.ts +0 -37
  91. package/admin/tsconfig.json +0 -26
  92. package/admin/vite.config.ts +0 -32
  93. package/frontend/.DS_Store +0 -0
  94. package/frontend/.eslintrc +0 -8
  95. package/frontend/.gitignore +0 -23
  96. package/frontend/package.json +0 -51
  97. package/frontend/src/App.ts +0 -25
  98. package/frontend/src/Breadcrumbs.ts +0 -43
  99. package/frontend/src/BrowseFiles.ts +0 -141
  100. package/frontend/src/Head.ts +0 -45
  101. package/frontend/src/UserPanel.ts +0 -52
  102. package/frontend/src/api.ts +0 -78
  103. package/frontend/src/components.ts +0 -54
  104. package/frontend/src/dialog.css +0 -76
  105. package/frontend/src/dialog.ts +0 -105
  106. package/frontend/src/icons.ts +0 -46
  107. package/frontend/src/index.scss +0 -307
  108. package/frontend/src/index.ts +0 -10
  109. package/frontend/src/login.ts +0 -50
  110. package/frontend/src/menu.ts +0 -188
  111. package/frontend/src/misc.ts +0 -54
  112. package/frontend/src/options.ts +0 -52
  113. package/frontend/src/react-app-env.d.ts +0 -1
  114. package/frontend/src/reportWebVitals.ts +0 -15
  115. package/frontend/src/setupTests.ts +0 -5
  116. package/frontend/src/state.ts +0 -82
  117. package/frontend/src/useAuthorized.ts +0 -17
  118. package/frontend/src/useFetchList.ts +0 -144
  119. package/frontend/src/useTheme.ts +0 -23
  120. package/frontend/tsconfig.json +0 -26
  121. package/frontend/vite.config.ts +0 -21
  122. package/src/QuickZipStream.ts +0 -279
  123. package/src/ThrottledStream.ts +0 -98
  124. package/src/adminApis.ts +0 -161
  125. package/src/api.accounts.ts +0 -78
  126. package/src/api.auth.ts +0 -131
  127. package/src/api.file_list.ts +0 -102
  128. package/src/api.helpers.ts +0 -30
  129. package/src/api.monitor.ts +0 -106
  130. package/src/api.plugins.ts +0 -139
  131. package/src/api.vfs.ts +0 -182
  132. package/src/apiMiddleware.ts +0 -124
  133. package/src/block.ts +0 -35
  134. package/src/commands.ts +0 -122
  135. package/src/config.ts +0 -166
  136. package/src/connections.ts +0 -60
  137. package/src/const.ts +0 -57
  138. package/src/crypt.ts +0 -16
  139. package/src/debounceAsync.ts +0 -51
  140. package/src/events.ts +0 -6
  141. package/src/frontEndApis.ts +0 -17
  142. package/src/github.ts +0 -102
  143. package/src/index.ts +0 -53
  144. package/src/listen.ts +0 -220
  145. package/src/log.ts +0 -128
  146. package/src/middlewares.ts +0 -176
  147. package/src/misc.ts +0 -149
  148. package/src/pbkdf2.ts +0 -83
  149. package/src/perm.ts +0 -194
  150. package/src/plugins.ts +0 -342
  151. package/src/serveFile.ts +0 -104
  152. package/src/serveGuiFiles.ts +0 -95
  153. package/src/sse.ts +0 -29
  154. package/src/throttler.ts +0 -106
  155. package/src/update.ts +0 -67
  156. package/src/util-files.ts +0 -137
  157. package/src/util-generators.ts +0 -29
  158. package/src/util-http.ts +0 -29
  159. package/src/vfs.ts +0 -258
  160. package/src/watchLoad.ts +0 -75
  161. package/src/zip.ts +0 -69
@@ -1,203 +0,0 @@
1
- // This file is part of HFS - Copyright 2021-2022, Massimo Melina <a@rejetto.com> - License https://www.gnu.org/licenses/gpl-3.0.txt
2
-
3
- import {
4
- Box,
5
- Button,
6
- CircularProgress,
7
- Dialog as MuiDialog,
8
- DialogContent,
9
- DialogProps,
10
- DialogTitle,
11
- IconButton
12
- } from '@mui/material'
13
- import {
14
- createElement as h, Fragment,
15
- isValidElement,
16
- ReactElement,
17
- useEffect,
18
- useRef,
19
- useState
20
- } from 'react'
21
- import { Check, Close, Error as ErrorIcon, Forward, Info, Warning } from '@mui/icons-material'
22
- import { newDialog, closeDialog, dialogsDefaults, DialogOptions } from '@hfs/shared'
23
- import { Form, FormProps } from '@hfs/mui-grid-form'
24
- import { useBreakpoint } from './misc'
25
- import { Flex } from '@hfs/frontend/src/components'
26
- export * from '@hfs/shared/lib/dialogs'
27
-
28
- dialogsDefaults.Container = function Container(d:DialogOptions) {
29
- useEffect(()=>{
30
- ref.current?.focus()
31
- }, [])
32
- const ref = useRef<HTMLElement>()
33
- d = { ...dialogsDefaults, ...d }
34
- const { sx, root, ...rest } = d.dialogProps||{}
35
- const p = d.padding ? 2 : 0
36
- return h(MuiDialog, {
37
- open: true,
38
- maxWidth: 'lg',
39
- fullScreen: !useBreakpoint('sm'),
40
- ...rest,
41
- ...root,
42
- onClose: ()=> closeDialog(),
43
- },
44
- d.title && h(DialogTitle, {}, d.title),
45
- h(DialogContent, {
46
- ref,
47
- sx: { ...sx, px: p, pb: p, display: 'flex', flexDirection: 'column', }
48
- }, h(d.Content) )
49
- )
50
- }
51
-
52
- type AlertType = 'error' | 'warning' | 'info' | 'success'
53
-
54
- const type2ico = {
55
- error: ErrorIcon,
56
- warning: Warning,
57
- info: Info,
58
- success: Check,
59
- }
60
- export async function alertDialog(msg: ReactElement | string | Error, options?: AlertType | ({ type?:AlertType, icon?: ReactElement } & Partial<DialogOptions>)) {
61
- return new Promise(resolve => {
62
- const opt = typeof options === 'string' ? { type: options } : (options ?? {})
63
- let { type='info', ...rest } = opt
64
- if (msg instanceof Error) {
65
- msg = msg.message || String(msg)
66
- type = 'error'
67
- }
68
- const close = newDialog({
69
- className: 'dialog-alert-' + type,
70
- icon: '!',
71
- onClose: resolve,
72
- ...rest,
73
- Content() {
74
- return h(Box, { display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 1 },
75
- h(IconButton, {
76
- onClick() {
77
- close()
78
- },
79
- size: 'small',
80
- sx: { position: 'absolute', right: 0, top: 0, opacity: .5 }
81
- }, h(Close)),
82
- opt.icon ?? h(type2ico[type], { color: type, fontSize: 'large' }),
83
- isValidElement(msg) ? msg
84
- : h(Box, { fontSize: 'large', mb: 1, lineHeight: '1.8em' }, String(msg)),
85
- )
86
- }
87
- })
88
- })
89
- }
90
-
91
- interface ConfirmOptions { href?: string }
92
- export async function confirmDialog(msg: string | ReactElement, { href }: ConfirmOptions={}) : Promise<boolean> {
93
- return new Promise(resolve => newDialog({
94
- className: 'dialog-confirm',
95
- icon: '?',
96
- onClose: resolve,
97
- Content
98
- }) )
99
-
100
- function Content() {
101
- return h(Fragment, {},
102
- h(Box, { mb: 2 }, msg),
103
- h(Flex, {},
104
- h('a', {
105
- href,
106
- onClick: () => closeDialog(true),
107
- }, h(Button, { variant: 'contained' }, "Confirm")),
108
- h(Button, { onClick: () => closeDialog(false) }, "Don't"),
109
- ),
110
- )
111
- }
112
- }
113
-
114
- type FormDialog<T> = Pick<DialogProps, 'fullScreen' | 'title'>
115
- & Pick<DialogOptions, 'dialogProps'>
116
- & Omit<FormProps<T>, 'values' | 'save' | 'set'>
117
- & Partial<Pick<FormProps<T>, 'values' | 'save'>>
118
- & {
119
- onChange?: (values:Partial<T>, extra: { setValues: React.Dispatch<React.SetStateAction<Partial<T>>> }) => void,
120
- before?: any
121
- }
122
- export async function formDialog<T>({ fullScreen, title, onChange, before, ...props }: FormDialog<T>) : Promise<T> {
123
- return new Promise(resolve => newDialog({
124
- className: 'dialog-confirm',
125
- icon: '?',
126
- onClose: resolve,
127
- title,
128
- Content
129
- }) )
130
-
131
- function Content() {
132
- const [values, setValues] = useState<Partial<T>>(props.values||{})
133
- return h(Fragment, {},
134
- before,
135
- h(Form, {
136
- ...props,
137
- values,
138
- set(v, k) {
139
- const newV = { ...values, [k]: v }
140
- setValues(newV)
141
- onChange?.(newV, { setValues })
142
- },
143
- save: {
144
- ...props.save,
145
- onClick() {
146
- closeDialog(values)
147
- }
148
- }
149
- })
150
- )
151
- }
152
- }
153
-
154
- export async function promptDialog(msg: string, props:any={}) : Promise<string | undefined> {
155
- return formDialog<{ text: string }>({
156
- ...props,
157
- fields: [
158
- { k: 'text', label: null, autoFocus: true,
159
- before: h(Box, { mb: 2 }, msg),
160
- ...props.field
161
- },
162
- ],
163
- save: {
164
- children: "Continue",
165
- startIcon: h(Forward),
166
- ...props.save,
167
- },
168
- saveOnEnter: true,
169
- barSx: { gap: 2 },
170
- addToBar: [
171
- h(Button, { onClick: closeDialog }, "Cancel"),
172
- ...props.addToBar||[],
173
- ]
174
- }).then(values => values?.text)
175
- }
176
-
177
- export function waitDialog() {
178
- return newDialog({ Content: CircularProgress, closable: false })
179
- }
180
-
181
- export function toast(msg: string | ReactElement, type: AlertType | ReactElement='info') {
182
- const ms = 3000
183
- const close = newDialog({
184
- Content,
185
- dialogProps: {
186
- PaperProps: {
187
- sx: { transition: `opacity ${ms}ms ease-in` },
188
- ref(x: HTMLElement) { // we need to set opacity later, to trigger transition
189
- if (x)
190
- x.style.opacity = '0'
191
- }
192
- }
193
- }
194
- })
195
- setTimeout(close, ms)
196
-
197
- function Content(){
198
- return h(Box, { display:'flex', flexDirection: 'column', alignItems: 'center', gap: 1 },
199
- isValidElement(type) ? type : h(type2ico[type], { color:type }),
200
- isValidElement(msg) ? msg : h('div', {}, String(msg))
201
- )
202
- }
203
- }
@@ -1,21 +0,0 @@
1
- body {
2
- margin: 0;
3
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
4
- 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
5
- sans-serif;
6
- -webkit-font-smoothing: antialiased;
7
- -moz-osx-font-smoothing: grayscale;
8
- height: 100vh;
9
- }
10
- #root { min-height: 100%; display:flex; }
11
-
12
- code {
13
- font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
14
- monospace;
15
- }
16
-
17
- .MuiTreeItem-content {
18
- box-sizing: border-box; /* avoid unwanted scrolling caused by its width:100% + padding */
19
- }
20
-
21
- ol, ul { margin-top: .2em }
@@ -1,10 +0,0 @@
1
- // This file is part of HFS - Copyright 2021-2022, Massimo Melina <a@rejetto.com> - License https://www.gnu.org/licenses/gpl-3.0.txt
2
-
3
- import { createElement as h, StrictMode } from 'react'
4
- import { createRoot } from 'react-dom/client'
5
- import './index.css'
6
- import '@hfs/shared/src/min-crypto-polyfill'
7
- import App from './App'
8
-
9
- createRoot(document.getElementById('root')!)
10
- .render( h(StrictMode, {}, h(App)) )
package/admin/src/md.ts DELETED
@@ -1,31 +0,0 @@
1
- // This file is part of HFS - Copyright 2021-2022, Massimo Melina <a@rejetto.com> - License https://www.gnu.org/licenses/gpl-3.0.txt
2
-
3
- import { createElement as h, Fragment } from 'react'
4
-
5
- // markdown inspired syntax to transform text into react elements: * for bold, / for italic, _ for underline, ` for code
6
- export default function md(text: string | TemplateStringsArray) {
7
- if (typeof text !== 'string')
8
- text = text[0]
9
- const re = /([`*/_])(.+)\1|(\n)/g
10
- const res = []
11
- let last = 0
12
- let match
13
- while (match = re.exec(text)) { //eslint-disable-line no-cond-assign
14
- res.push( text.slice(last, match.index) )
15
- if (match[3])
16
- res.push(h('br'))
17
- else {
18
- const tag = ({
19
- '`': 'code',
20
- '*': 'b',
21
- '/': 'i',
22
- '_': 'u',
23
- })[ match[1] ]
24
- if (!tag)
25
- throw Error("should never happen")
26
- res.push( h(tag,{}, match[2]) )
27
- }
28
- last = match.index + match[0].length
29
- }
30
- return h(Fragment, {}, ...res, text.slice(last, Infinity))
31
- }
package/admin/src/misc.ts DELETED
@@ -1,141 +0,0 @@
1
- // This file is part of HFS - Copyright 2021-2022, Massimo Melina <a@rejetto.com> - License https://www.gnu.org/licenses/gpl-3.0.txt
2
-
3
- import { createElement as h, FC, ReactNode } from 'react'
4
- import { Box, Breakpoint, CircularProgress, IconButton, Link, Tooltip, useMediaQuery } from '@mui/material'
5
- import { Link as RouterLink } from 'react-router-dom'
6
- import { SxProps } from '@mui/system'
7
- import { SvgIconComponent } from '@mui/icons-material'
8
- import { alertDialog, confirmDialog } from './dialog'
9
- import { apiCall } from './api'
10
- import { onlyTruthy, useStateMounted } from '@hfs/shared'
11
- export * from '@hfs/shared'
12
-
13
- export function spinner() {
14
- return h(CircularProgress)
15
- }
16
-
17
- export function isWindowsDrive(s?: string) {
18
- return s && /^[a-zA-Z]:$/.test(s)
19
- }
20
-
21
- export function isEqualLax(a: any,b: any): boolean {
22
- return a == b //eslint-disable-line
23
- || (a && b && typeof a === 'object' && typeof b === 'object'
24
- && Object.entries(a).every(([k,v]) => isEqualLax(v, b[k])) )
25
- }
26
-
27
- export function modifiedSx(is: boolean) {
28
- return is ? { outline: '2px solid' } : undefined
29
- }
30
-
31
- interface IconBtnProps {
32
- title?: ReactNode
33
- icon: SvgIconComponent
34
- disabled?: boolean | string
35
- progress?: boolean | number
36
- link?: string
37
- confirm?: string
38
- [rest: string]: any
39
- }
40
-
41
- export function IconBtn({ title, icon, onClick, disabled, progress, link, tooltipProps, confirm, ...rest }: IconBtnProps) {
42
- const [loading, setLoading] = useStateMounted(false)
43
- if (typeof disabled === 'string')
44
- title = disabled
45
- if (link)
46
- onClick = () => window.open(link)
47
- let ret: ReturnType<FC> = h(IconButton, {
48
- disabled: Boolean(loading || progress || disabled),
49
- ...rest,
50
- async onClick() {
51
- if (confirm && !await confirmDialog(confirm)) return
52
- const ret = onClick?.apply(this,arguments)
53
- if (ret && ret instanceof Promise) {
54
- setLoading(true)
55
- ret.catch(alertDialog).finally(()=> setLoading(false))
56
- }
57
- }
58
- }, h(icon))
59
- if ((progress || loading) && progress !== false) // false is also useful to inhibit behavior with loading
60
- ret = h(Box, { position:'relative', display: 'inline-block' },
61
- h(CircularProgress, {
62
- ...(typeof progress === 'number' ? { value: progress*100, variant: 'determinate' } : null),
63
- style: { position:'absolute', top: 4, left: 4, width: 32, height: 32 }
64
- }),
65
- ret
66
- )
67
- if (title)
68
- ret = h(Tooltip, { title, ...tooltipProps, children: h('span',{},ret) })
69
- return ret
70
- }
71
-
72
- export function iconTooltip(icon: SvgIconComponent, tooltip: string, sx?: SxProps) {
73
- return h(Tooltip, { title: tooltip, children: h(icon, { sx }) })
74
- }
75
-
76
- export function InLink(props:any) {
77
- return h(Link, { component: RouterLink, ...props })
78
- }
79
-
80
- export function Center(props: any) {
81
- return h(Box, { display:'flex', height:'100%', width:'100%', justifyContent:'center', alignItems:'center', ...props })
82
- }
83
-
84
- export async function manipulateConfig(k: string, work:(data:any) => any) {
85
- const cfg = await apiCall('get_config', { only: [k] })
86
- const was = cfg[k]
87
- const will = await work(was)
88
- if (JSON.stringify(was) !== JSON.stringify(will))
89
- await apiCall('set_config', { values: { [k]: will } })
90
- }
91
-
92
- export function typedKeys<T extends {}>(o: T) {
93
- return Object.keys(o) as (keyof T)[]
94
- }
95
-
96
- export function dirname(s: string) {
97
- let i = s.lastIndexOf('/')
98
- if (i < 0)
99
- i = s.lastIndexOf('\\')
100
- return i < 0 ? '' : s.slice(0, i)
101
- }
102
-
103
- export function isAbsolutePath(s: string) {
104
- return s && (s[0] === '/' || isWindowsDrive(s.slice(0,2)))
105
- }
106
-
107
- export function pathJoin(...args: any[]) {
108
- const delimiter = findFirst(args, x => /\\|\//.exec('\\a/b')?.[0])
109
- const good = onlyTruthy(args.map(x => x == null ? '' : String(x)))
110
- return good.map((x, i) => i === good.length-1 || x.endsWith('\\') || x.endsWith('/') ? x : x + delimiter)
111
- .join('')
112
- }
113
-
114
- export function findFirst<I=any, O=any>(a: I[], cb:(v:I)=>O): any {
115
- for (const x of a) {
116
- const ret = cb(x)
117
- if (ret !== undefined)
118
- return ret
119
- }
120
- }
121
-
122
- export function xlate(input: any, table: Record<string, any>) {
123
- return table[input] ?? input
124
- }
125
-
126
- // return true if same size or larger
127
- export function useBreakpoint(breakpoint: Breakpoint) {
128
- return useMediaQuery((theme: any) => theme.breakpoints.up(breakpoint), { noSsr:true }) // without noSsr, first execution always returns false
129
- }
130
-
131
- export function err2msg(code: string) {
132
- return {
133
- ENOENT: "Not found",
134
- ENOTDIR: "Not a folder",
135
- }[code] || code
136
- }
137
-
138
- export function wantArray<T>(x?: void | T | T[]) {
139
- return x == null ? [] : Array.isArray(x) ? x : [x]
140
- }
141
-
@@ -1 +0,0 @@
1
- /// <reference types="react-scripts" />
@@ -1,15 +0,0 @@
1
- import { ReportHandler } from 'web-vitals';
2
-
3
- const reportWebVitals = (onPerfEntry?: ReportHandler) => {
4
- if (onPerfEntry && onPerfEntry instanceof Function) {
5
- import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
6
- getCLS(onPerfEntry);
7
- getFID(onPerfEntry);
8
- getFCP(onPerfEntry);
9
- getLCP(onPerfEntry);
10
- getTTFB(onPerfEntry);
11
- });
12
- }
13
- };
14
-
15
- export default reportWebVitals;
@@ -1,5 +0,0 @@
1
- // jest-dom adds custom jest matchers for asserting on DOM nodes.
2
- // allows you to do things like:
3
- // expect(element).toHaveTextContent(/react/i)
4
- // learn more: https://github.com/testing-library/jest-dom
5
- import '@testing-library/jest-dom';
@@ -1,40 +0,0 @@
1
- // This file is part of HFS - Copyright 2021-2022, Massimo Melina <a@rejetto.com> - License https://www.gnu.org/licenses/gpl-3.0.txt
2
-
3
- import { proxy, useSnapshot } from 'valtio'
4
- import { Dict } from './misc'
5
- import { VfsNode } from './VfsPage'
6
- import _ from 'lodash'
7
- import { subscribeKey } from 'valtio/utils'
8
-
9
- const STORAGE_KEY = 'admin_state'
10
- export const state = proxy<{
11
- title: string
12
- config: Dict
13
- vfs: VfsNode | undefined
14
- selectedFiles: VfsNode[]
15
- loginRequired: boolean
16
- username: string
17
- onlinePluginsColumns: Dict<boolean>
18
- }>(Object.assign({
19
- title: '',
20
- config: {},
21
- selectedFiles: [],
22
- vfs: undefined,
23
- loginRequired: false,
24
- username: '',
25
- onlinePluginsColumns: {
26
- version: false,
27
- pushed_at: false,
28
- license: false,
29
- }
30
- }, JSON.parse(localStorage[STORAGE_KEY]||null)))
31
-
32
- const SETTINGS_TO_STORE: (keyof typeof state)[] = ['onlinePluginsColumns']
33
- const storeSettings = _.debounce(() =>
34
- localStorage[STORAGE_KEY] = JSON.stringify(_.pick(state, SETTINGS_TO_STORE)), 500, { maxWait: 1000 })
35
- for (const k of SETTINGS_TO_STORE)
36
- subscribeKey(state, k, storeSettings)
37
-
38
- export function useSnapState() {
39
- return useSnapshot(state)
40
- }
@@ -1,37 +0,0 @@
1
- // This file is part of HFS - Copyright 2021-2022, Massimo Melina <a@rejetto.com> - License https://www.gnu.org/licenses/gpl-3.0.txt
2
-
3
- import { createTheme, useMediaQuery } from '@mui/material'
4
- import { useMemo } from 'react'
5
-
6
- const EMPTY = {}
7
- export function useMyTheme() {
8
- const lightMode = useMediaQuery('(prefers-color-scheme: dark)') ? null : EMPTY
9
- return useMemo(() => createTheme({
10
- palette: lightMode || {
11
- mode: 'dark',
12
- text: { primary: '#bbb' },
13
- primary: { main: '#469' },
14
- },
15
- typography: {
16
- fontFamily: 'Roboto, "Noto sans", "Segoe UI", "San Francisco", "Helvetica Neue", Arial, sans-serif'
17
- },
18
- components: {
19
- MuiTextField: {
20
- defaultProps: { variant: 'filled' },
21
- styleOverrides: lightMode || {
22
- root: { '& label.Mui-focused': { color: '#ccc' } } // our primary.main is too dark for mui's dark theme, and when input element is :-webkit-autofill it will make not enough contrast
23
- }
24
- },
25
- MuiButton: {
26
- defaultProps: { variant: 'outlined' },
27
- styleOverrides: lightMode || {
28
- root({ ownerState }) {
29
- return ownerState.color === 'primary' && {
30
- color: ownerState.variant === 'contained' ? '#ddd' : '#68c'
31
- }
32
- }
33
- }
34
- }
35
- }
36
- }), [lightMode])
37
- }
@@ -1,26 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "es2017",
4
- "lib": [
5
- "dom",
6
- "dom.iterable",
7
- "esnext"
8
- ],
9
- "allowJs": true,
10
- "skipLibCheck": true,
11
- "esModuleInterop": true,
12
- "allowSyntheticDefaultImports": true,
13
- "strict": true,
14
- "forceConsistentCasingInFileNames": true,
15
- "noFallthroughCasesInSwitch": true,
16
- "module": "esnext",
17
- "moduleResolution": "node",
18
- "resolveJsonModule": true,
19
- "isolatedModules": true,
20
- "noEmit": true,
21
- "jsx": "react-jsx"
22
- },
23
- "include": [
24
- "src"
25
- ]
26
- }
@@ -1,32 +0,0 @@
1
- import { defineConfig } from 'vite'
2
- import vitePluginImport from 'vite-plugin-babel-import';
3
-
4
- // https://vitejs.dev/config/
5
- export default defineConfig({
6
- build: {
7
- outDir: '../dist/admin',
8
- emptyOutDir: true,
9
- target: "es2015",
10
- },
11
- plugins: [
12
- vitePluginImport([] || [
13
- { // this is (currently) speeding up build process, by bringing "modules transformed" from 11k+ down to 1.5k+
14
- libraryName: '@mui/icons-material',
15
- libraryDirectory: '',
16
- libraryChangeCase: "camelCase",
17
- ignoreStyles: [],
18
- },
19
- ])
20
- ],
21
- server: {
22
- port: 3006,
23
- proxy: {
24
- '/~/': {
25
- target: 'http://localhost',
26
- proxyTimeout: 2000,
27
- changeOrigin: true,
28
- ws: true,
29
- }
30
- }
31
- }
32
- })
Binary file
@@ -1,8 +0,0 @@
1
- {
2
- "extends": "react-app",
3
- "rules": {
4
- "no-mixed-operators": 0,
5
- "no-ex-assign": 0,
6
- "no-throw-literal": 0
7
- }
8
- }
@@ -1,23 +0,0 @@
1
- # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2
-
3
- # dependencies
4
- /node_modules
5
- /.pnp
6
- .pnp.js
7
-
8
- # testing
9
- /coverage
10
-
11
- # production
12
- /build
13
-
14
- # misc
15
- .DS_Store
16
- .env.local
17
- .env.development.local
18
- .env.test.local
19
- .env.production.local
20
-
21
- npm-debug.log*
22
- yarn-debug.log*
23
- yarn-error.log*
@@ -1,51 +0,0 @@
1
- {
2
- "name": "@hfs/frontend",
3
- "private": true,
4
- "proxy": "http://localhost",
5
- "scripts": {
6
- "start": "vite",
7
- "build": "tsc && vite build",
8
- "preview": "vite preview",
9
- "test-dep": "npm audit --production"
10
- },
11
- "dependencies": {
12
- "@hfs/shared": "*",
13
- "js-sha512": "^0.8.0",
14
- "lodash": "^4.17.21",
15
- "react": "^18.2.0",
16
- "react-dom": "^18.2.0",
17
- "react-router-dom": "^6.1.1",
18
- "tssrp6a": "^3.0.0",
19
- "use-debounce": "^7.0.1",
20
- "usehooks-ts": "^2.6.0",
21
- "valtio": "^1.2.7",
22
- "web-vitals": "^2.1.4"
23
- },
24
- "devDependencies": {
25
- "@types/lodash": "^4.14.178",
26
- "@types/node": "^16.11.21",
27
- "@types/react": "^18.0.15",
28
- "@types/react-dom": "^18.0.6",
29
- "cross-env": "^7.0.3",
30
- "sass": "^1.54.5",
31
- "vite": "^3.0.0"
32
- },
33
- "eslintConfig": {
34
- "extends": [
35
- "react-app",
36
- "react-app/jest"
37
- ]
38
- },
39
- "browserslist": {
40
- "production": [
41
- ">0.2%",
42
- "not dead",
43
- "not op_mini all"
44
- ],
45
- "development": [
46
- "last 1 chrome version",
47
- "last 1 firefox version",
48
- "last 1 safari version"
49
- ]
50
- }
51
- }