plugins: config.showIf
Massimo Melina committed
Dec 13, 2024 at 23:36 UTC
36abf3ab3fb495b8d421cb978fbb426f1d94eda4
3 files changed
+20
-7
admin/src/InstalledPlugins.ts
+11
-4
@@ -101,7 +101,7 @@ export default function InstalledPlugins({ updates }: { updates?: true }) {
101
title: `Options for ${id}`,
102
form: values => ({
103
before: h(Box, { mx: 2, mb: 3 }, row.description),
104
- fields: makeFields(row.config),
104
+ fields: makeFields(row.config, values),
105
save: { children: "Save and close" },
106
barSx: { gap: 1 },
107
addToBar: [h(Btn, { variant: 'outlined', onClick: () => save(values) }, "Save")],
@@ -167,17 +167,24 @@ export function renderName({ row, value }: any) {
167
}
168
}
169
170
-function makeFields(config: any) {
170
+function makeFields(config: any, values: any) {
171
return Object.entries(config).map(([k,o]: [string,any]) => {
172
if (!_.isPlainObject(o))
173
return o
174
- let { type, defaultValue, fields, frontend, helperText, ...rest } = o
174
+ let { type, defaultValue, fields, frontend, helperText, showIf, ...rest } = o
175
+ try {
176
+ if (typeof showIf === 'string') // compile once
177
+ o.showIf = showIf = eval(showIf) // eval is normally considered a threat, but this code is coming from a plugin that's already running on your server, so you already decided to trust it. Here it will run in your browser, and inside the page that administrating the same server.
178
+ if (showIf && !showIf(values))
179
+ return
180
+ }
181
+ catch {}
182
if (helperText)
183
helperText = md(helperText, { html: false })
184
const comp = (type2comp as any)[type] as Field<any> | undefined
185
if (comp === ArrayField) {
186
rest.valuesForAdd = newObj(fields, x => x.defaultValue)
180
- fields = makeFields(fields)
187
+ fields = makeFields(fields, values)
188
}
189
if (defaultValue !== undefined && type === 'boolean')
190
rest.placeholder = `Default value is ${JSON.stringify(defaultValue)}`
dev-plugins.md
+4
-2
@@ -136,11 +136,12 @@ used must be strictly JSON (thus, no single quotes, only double quotes for strin
136
137
### FieldDescriptor
138
139
-Currently, these properties are supported:
139
+A FieldDescriptor is an object and can be empty. Currently, these optional properties are supported:
140
- `type: 'string' | 'number' | 'boolean' | 'select' | 'multiselect' | 'real_path' | 'vfs_path' | 'array' | 'username' | 'color'` . Default is `string`.
141
- `label: string` what name to display next to the field. Default is based on `key`.
142
-- `defaultValue: any` value to be used when nothing is set.
142
+- `defaultValue: any` value to be used when nothing is set. Default is undefined.
143
- `helperText: string` extra text printed next to the field.
144
+- `showIf: (values: object) => boolean` only show this field if the function returns truthy. Must not reference variables of the outer scope.
145
- `frontend: boolean` expose this setting on the frontend, so that javascript can access it
146
using `HFS.getPluginConfig()[CONFIG_KEY]` but also css can access it as `var(--PLUGIN_NAME-CONFIG_KEY)`.
147
Hint: if you need to use a numeric config in CSS but you need to add a unit (like `em`),
@@ -699,6 +700,7 @@ If you want to override a text regardless of the language, use the special langu
700
- HFS.urlParams
701
- exports.beforePlugin + afterPlugin
702
- config.type: color
703
+ - config.showIf
704
- init can now return directly the unload function
705
- api.i18n
706
- frontend event: newListEntries
src/api.plugins.ts
+5
-1
@@ -15,6 +15,7 @@ import {
15
} from './github'
16
import { HTTP_FAILED_DEPENDENCY, HTTP_NOT_FOUND, HTTP_SERVER_ERROR } from './const'
17
import { SendListReadable } from './SendList'
18
+import produce from 'immer'
19
20
const apis: ApiHandlers = {
21
@@ -174,10 +175,13 @@ const apis: ApiHandlers = {
175
export default apis
176
177
function serialize(p: Readonly<Plugin> | AvailablePlugin) {
177
- const o = 'getData' in p ? Object.assign(_.pick(p, ['id','started']), p.getData())
178
+ let o = 'getData' in p ? Object.assign(_.pick(p, ['id','started']), p.getData())
179
: { ...p } // _.defaults mutates object, and we don't want that
180
if (typeof o.repo === 'object') // custom repo
181
o.repo = o.repo.web
182
+ o = produce(o, (o: any) => {
183
+ _.each(o.config, x => x.showIf &&= String(x.showIf))
184
+ })
185
return _.defaults(o, { started: null, badApi: null }) // nulls should be used to be sure to overwrite previous values,
186
}
187