Plugin settings (#4143)

* Add backend support for plugin settings
* Add plugin settings config
* Add UI support for plugin settings
This commit is contained in:
WithoutPants
2023-10-18 14:09:13 +11:00
committed by GitHub
parent 06d8353f4f
commit 2b8718100b
24 changed files with 445 additions and 57 deletions

View File

@@ -13,19 +13,74 @@ import { CollapseButton } from "../Shared/CollapseButton";
import { Icon } from "../Shared/Icon";
import { LoadingIndicator } from "../Shared/LoadingIndicator";
import { SettingSection } from "./SettingSection";
import { Setting, SettingGroup } from "./Inputs";
import {
BooleanSetting,
NumberSetting,
Setting,
SettingGroup,
StringSetting,
} from "./Inputs";
import { faLink, faSyncAlt } from "@fortawesome/free-solid-svg-icons";
import { useSettings } from "./context";
interface IPluginSettingProps {
pluginID: string;
setting: GQL.PluginSetting;
value: unknown;
onChange: (value: unknown) => void;
}
const PluginSetting: React.FC<IPluginSettingProps> = ({
pluginID,
setting,
value,
onChange,
}) => {
const commonProps = {
heading: setting.display_name ? setting.display_name : setting.name,
id: `plugin-${pluginID}-${setting.name}`,
subHeading: setting.description ?? undefined,
};
switch (setting.type) {
case GQL.PluginSettingTypeEnum.Boolean:
return (
<BooleanSetting
{...commonProps}
checked={(value as boolean) ?? false}
onChange={() => onChange(!value)}
/>
);
case GQL.PluginSettingTypeEnum.String:
return (
<StringSetting
{...commonProps}
value={(value as string) ?? ""}
onChange={(v) => onChange(v)}
/>
);
case GQL.PluginSettingTypeEnum.Number:
return (
<NumberSetting
{...commonProps}
value={(value as number) ?? 0}
onChange={(v) => onChange(v)}
/>
);
}
};
export const SettingsPluginsPanel: React.FC = () => {
const Toast = useToast();
const intl = useIntl();
const { loading: configLoading, plugins, savePluginSettings } = useSettings();
const { data, loading, refetch } = usePlugins();
const [changedPluginID, setChangedPluginID] = React.useState<
string | undefined
>();
const { data, loading, refetch } = usePlugins();
async function onReloadPlugins() {
await mutateReloadPlugins().catch((e) => Toast.error(e));
}
@@ -101,6 +156,7 @@ export const SettingsPluginsPanel: React.FC = () => {
}
>
{renderPluginHooks(plugin.hooks ?? undefined)}
{renderPluginSettings(plugin.id, plugin.settings ?? [])}
</SettingGroup>
));
@@ -145,10 +201,40 @@ export const SettingsPluginsPanel: React.FC = () => {
);
}
return renderPlugins();
}, [data?.plugins, intl, Toast, changedPluginID, refetch]);
function renderPluginSettings(
pluginID: string,
settings: GQL.PluginSetting[]
) {
const pluginSettings = plugins[pluginID] ?? {};
if (loading) return <LoadingIndicator />;
return settings.map((setting) => (
<PluginSetting
key={setting.name}
pluginID={pluginID}
setting={setting}
value={pluginSettings[setting.name]}
onChange={(v) =>
savePluginSettings(pluginID, {
...pluginSettings,
[setting.name]: v,
})
}
/>
));
}
return renderPlugins();
}, [
data?.plugins,
intl,
Toast,
changedPluginID,
refetch,
plugins,
savePluginSettings,
]);
if (loading || configLoading) return <LoadingIndicator />;
return (
<>