InvenTree/src/frontend/src/pages/Index/Settings/PluginSettingsGroup.tsx

149 lines
3.9 KiB
TypeScript

import { ApiEndpoints, StylishText } from '@lib/index';
import type { SettingsStateProps } from '@lib/types/Settings';
import { t } from '@lingui/core/macro';
import { Accordion, Alert, Group, Stack, Text } from '@mantine/core';
import { IconInfoCircle } from '@tabler/icons-react';
import { useCallback, useMemo, useState } from 'react';
import {
GlobalSettingList,
PluginSettingList,
PluginUserSettingList
} from '../../../components/settings/SettingList';
import { useInstance } from '../../../hooks/UseInstance';
import { PLUGIN_SETTINGS_KEYS } from './AdminCenter/PluginManagementPanel';
function PluginSettingGroupItem({
global,
pluginKey,
pluginName,
pluginDescription
}: {
global: boolean;
pluginKey: string;
pluginName: string;
pluginDescription?: string;
}) {
// Hide the accordion item if there are no settings for this plugin
const [count, setCount] = useState<number>(0);
const [doGet, setDoGet] = useState<boolean>(true);
// Callback once the plugin settings have been loaded
const onLoaded = useCallback(
(settings: SettingsStateProps) => {
setCount(settings.getSettingLength());
setDoGet(false);
},
[pluginKey]
);
return (
<Accordion.Item
key={`plugin-${pluginKey}`}
value={pluginKey}
hidden={count === 0}
>
<Accordion.Control>
<Group justify='space-between'>
<Text size='lg'>{pluginName}</Text>
{pluginDescription && (
<Text size='sm' style={{ paddingRight: 25 }}>
{pluginDescription}
</Text>
)}
</Group>
</Accordion.Control>
<Accordion.Panel>
{global ? (
<PluginSettingList
pluginKey={pluginKey}
onLoaded={onLoaded}
doGet={doGet}
/>
) : (
<PluginUserSettingList
pluginKey={pluginKey}
onLoaded={onLoaded}
doGet={doGet}
/>
)}
</Accordion.Panel>
</Accordion.Item>
);
}
/**
* Displays an accordion of user-specific plugin settings
* - Each element in the accordion corresponds to a plugin
* - Each plugin can have multiple settings
* - If a plugin has no settings, it will not be displayed
*/
export default function PluginSettingsGroup({
mixin,
message,
includeBaseSettings,
global
}: {
global: boolean;
message?: string;
includeBaseSettings?: boolean;
mixin?: string;
}) {
const mixins: string = useMemo(() => {
const mixinList: string[] = ['settings'];
if (mixin) {
mixinList.push(mixin);
}
return mixinList.join(',');
}, [mixin]);
// All *active* plugins which require settings
const activePlugins = useInstance({
endpoint: ApiEndpoints.plugin_list,
params: {
active: true,
mixin: mixins
},
hasPrimaryKey: false,
defaultValue: []
});
return (
<Stack gap='xs'>
{includeBaseSettings == true && (
<Accordion defaultValue='plugin-settings'>
<Accordion.Item value='plugin-settings'>
<Accordion.Control>
<StylishText size='lg'>{t`Plugin Settings`}</StylishText>
</Accordion.Control>
<Accordion.Panel>
<GlobalSettingList keys={PLUGIN_SETTINGS_KEYS} />
</Accordion.Panel>
</Accordion.Item>
</Accordion>
)}
<Alert color='blue' icon={<IconInfoCircle />}>
<Text>
{message ??
t`The settings below are specific to each available plugin`}
</Text>
</Alert>
<Accordion multiple>
{activePlugins.instance?.map((plugin: any) => {
return (
<PluginSettingGroupItem
global={global}
key={plugin.key}
pluginKey={plugin.key}
pluginName={plugin.meta?.human_name ?? plugin.name}
pluginDescription={plugin?.meta?.description}
/>
);
})}
</Accordion>
</Stack>
);
}