Tooltip for widget options

This commit is contained in:
Tagaishi
2023-07-25 21:07:43 +02:00
parent 18e0e2a8ff
commit 5cc2fac8bc
2 changed files with 141 additions and 58 deletions

View File

@@ -13,16 +13,17 @@ import {
Text,
TextInput,
Title,
Tooltip,
useMantineTheme,
} from '@mantine/core';
import { ContextModalProps } from '@mantine/modals';
import { IconAlertTriangle, IconPlaylistX, IconPlus } from '@tabler/icons-react';
import { IconAlertTriangle, IconPlaylistX, IconPlus, IconAlertCircle } from '@tabler/icons-react';
import { Trans, useTranslation } from 'next-i18next';
import { FC, useState } from 'react';
import { useConfigContext } from '../../../../config/provider';
import { useConfigStore } from '../../../../config/store';
import { mapObject } from '../../../../tools/client/objects';
import { useColorTheme } from '../../../../tools/color';
import Widgets from '../../../../widgets';
import type { IDraggableListInputValue, IWidgetOptionValue } from '../../../../widgets/widgets';
import { IWidget } from '../../../../widgets/widgets';
@@ -135,70 +136,120 @@ const WidgetOptionTypeSwitch: FC<{
handleChange: (key: string, value: IntegrationOptionsValueType) => void;
}> = ({ option, widgetId, propName: key, value, handleChange }) => {
const { t } = useTranslation([`modules/${widgetId}`, 'common']);
const { primaryColor } = useColorTheme();
const { fn } = useMantineTheme();
switch (option.type) {
case 'switch':
return (
<Switch
label={t(`descriptor.settings.${key}.label`)}
checked={value as boolean}
onChange={(ev) => handleChange(key, ev.currentTarget.checked)}
/>
<Group align="center" spacing="sm">
<Switch
label={t(`descriptor.settings.${key}.label`)}
checked={value as boolean}
onChange={(ev) => handleChange(key, ev.currentTarget.checked)}
{...option.inputProps}
/>
{option.info?
<Tooltip.Floating label={t(`descriptor.settings.${key}.info`)} position="right-start" color={fn.darken(fn.primaryColor(), 0.5)}>
<IconAlertCircle size="1.25rem" style={{ display: 'block', opacity: 0.5 }} />
</Tooltip.Floating> : undefined
}
</Group>
);
case 'text':
return (
<TextInput
color={primaryColor}
label={t(`descriptor.settings.${key}.label`)}
value={value as string}
onChange={(ev) => handleChange(key, ev.currentTarget.value)}
/>
<Stack spacing={0}>
<Group align="center" spacing="sm">
<Text size="0.875rem" weight="500">{t(`descriptor.settings.${key}.label`)}</Text>
{option.info?
<Tooltip.Floating label={t(`descriptor.settings.${key}.info`)} position="right-start" color={fn.darken(fn.primaryColor(), 0.5)}>
<IconAlertCircle size="1.25rem" style={{ display: 'block', opacity: 0.5 }} />
</Tooltip.Floating> : undefined
}
</Group>
<TextInput
value={value as string}
onChange={(ev) => handleChange(key, ev.currentTarget.value)}
{...option.inputProps}
/>
</Stack>
);
case 'multi-select':
return (
<MultiSelect
color={primaryColor}
data={option.data}
label={t(`descriptor.settings.${key}.label`)}
value={value as string[]}
defaultValue={option.defaultValue}
onChange={(v) => handleChange(key, v)}
/>
<Stack spacing={0}>
<Group align="center" spacing="sm">
<Text size="0.875rem" weight="500">{t(`descriptor.settings.${key}.label`)}</Text>
{option.info?
<Tooltip.Floating label={t(`descriptor.settings.${key}.info`)} position="right-start" color={fn.darken(fn.primaryColor(), 0.5)}>
<IconAlertCircle size="1.25rem" style={{ display: 'block', opacity: 0.5 }} />
</Tooltip.Floating> : undefined
}
</Group>
<MultiSelect
data={option.data}
value={value as string[]}
defaultValue={option.defaultValue}
onChange={(v) => handleChange(key, v)}
{...option.inputProps}
/>
</Stack>
);
case 'select':
return (
<Select
color={primaryColor}
defaultValue={option.defaultValue}
data={option.data}
label={t(`descriptor.settings.${key}.label`)}
value={value as string}
onChange={(v) => handleChange(key, v ?? option.defaultValue)}
/>
<Stack spacing={0}>
<Group align="center" spacing="sm">
<Text size="0.875rem" weight="500">{t(`descriptor.settings.${key}.label`)}</Text>
{option.info?
<Tooltip.Floating label={t(`descriptor.settings.${key}.info`)} position="right-start" color={fn.darken(fn.primaryColor(), 0.5)}>
<IconAlertCircle size="1.25rem" style={{ display: 'block', opacity: 0.5 }} />
</Tooltip.Floating> : undefined
}
</Group>
<Select
defaultValue={option.defaultValue}
data={option.data}
value={value as string}
onChange={(v) => handleChange(key, v ?? option.defaultValue)}
{...option.inputProps}
/>
</Stack>
);
case 'number':
return (
<NumberInput
color={primaryColor}
label={t(`descriptor.settings.${key}.label`)}
value={value as number}
onChange={(v) => handleChange(key, v!)}
{...option.inputProps}
/>
<Stack spacing={0}>
<Group align="center" spacing="sm">
<Text size="0.875rem" weight="500">{t(`descriptor.settings.${key}.label`)}</Text>
{option.info?
<Tooltip.Floating label={t(`descriptor.settings.${key}.info`)} position="right-start" color={fn.darken(fn.primaryColor(), 0.5)}>
<IconAlertCircle size="1.25rem" style={{ display: 'block', opacity: 0.5 }} />
</Tooltip.Floating> : undefined
}
</Group>
<NumberInput
value={value as number}
onChange={(v) => handleChange(key, v!)}
{...option.inputProps}
/>
</Stack>
);
case 'slider':
return (
<Stack spacing="xs">
<Text>{t(`descriptor.settings.${key}.label`)}</Text>
<Stack spacing={0}>
<Group align="center" spacing="sm">
<Text size="0.875rem" weight="500">{t(`descriptor.settings.${key}.label`)}</Text>
{option.info?
<Tooltip.Floating label={t(`descriptor.settings.${key}.info`)} position="right-start" color={fn.darken(fn.primaryColor(), 0.5)}>
<IconAlertCircle size="1.25rem" style={{ display: 'block', opacity: 0.5 }} />
</Tooltip.Floating> : undefined
}
</Group>
<Slider
color={primaryColor}
label={value}
value={value as number}
min={option.min}
max={option.max}
step={option.step}
onChange={(v) => handleChange(key, v)}
{...option.inputProps}
/>
</Stack>
);
@@ -237,7 +288,14 @@ const WidgetOptionTypeSwitch: FC<{
return (
<Stack spacing="xs">
<Text>{t(`descriptor.settings.${key}.label`)}</Text>
<Group align="center" spacing="sm">
<Text>{t(`descriptor.settings.${key}.label`)}</Text>
{option.info?
<Tooltip.Floating label={t(`descriptor.settings.${key}.info`)} position="right-start" color={fn.darken(fn.primaryColor(), 0.5)}>
<IconAlertCircle size="1.25rem" style={{ display: 'block', opacity: 0.5 }} />
</Tooltip.Floating> : undefined
}
</Group>
<StaticDraggableList
value={typedVal}
onChange={(v) => handleChange(key, v)}
@@ -262,28 +320,44 @@ const WidgetOptionTypeSwitch: FC<{
);
case 'multiple-text':
return (
<MultiSelect
data={value.map((name: any) => ({ value: name, label: name }))}
label={t(`descriptor.settings.${key}.label`)}
description={t(`descriptor.settings.${key}.description`)}
defaultValue={value as string[]}
withinPortal
searchable
creatable
getCreateLabel={(query) => t('common:createItem', { item: query })}
onChange={(values) =>
handleChange(
key,
values.map((item: string) => item)
)
}
/>
<Stack spacing={0}>
<Group align="center" spacing="sm">
<Text size="0.875rem" weight="500">{t(`descriptor.settings.${key}.label`)}</Text>
{option.info?
<Tooltip.Floating label={t(`descriptor.settings.${key}.info`)} position="right-start" color={fn.darken(fn.primaryColor(), 0.5)}>
<IconAlertCircle size="1.25rem" style={{ display: 'block', opacity: 0.5 }} />
</Tooltip.Floating> : undefined
}
</Group>
<MultiSelect
data={value.map((name: any) => ({ value: name, label: name }))}
description={t(`descriptor.settings.${key}.description`)}
defaultValue={value as string[]}
withinPortal
searchable
creatable
getCreateLabel={(query) => t('common:createItem', { item: query })}
onChange={(values) =>
handleChange(
key,
values.map((item: string) => item)
)
}
/>
</Stack>
);
case 'draggable-editable-list':
const { t: translateDraggableList } = useTranslation('widgets/draggable-list');
return (
<Stack spacing="xs">
<Text>{t(`descriptor.settings.${key}.label`)}</Text>
<Group align="center" spacing="sm">
<Text>{t(`descriptor.settings.${key}.label`)}</Text>
{option.info?
<Tooltip.Floating label={t(`descriptor.settings.${key}.info`)} position="right-start" color={fn.darken(fn.primaryColor(), 0.5)}>
<IconAlertCircle size="1.25rem" style={{ display: 'block', opacity: 0.5 }} />
</Tooltip.Floating> : undefined
}
</Group>
<DraggableList
items={Array.from(value).map((v: any) => ({
data: v,

View File

@@ -53,6 +53,7 @@ interface DataType {
export type IMultiSelectOptionValue = {
type: 'multi-select';
defaultValue: string[];
info?: boolean;
data: DataType[];
inputProps?: Partial<MultiSelectProps>;
};
@@ -61,6 +62,7 @@ export type IMultiSelectOptionValue = {
export type ISelectOptionValue = {
type: 'select';
defaultValue: string;
info?: boolean;
data: DataType[];
inputProps?: Partial<SelectProps>;
};
@@ -69,6 +71,7 @@ export type ISelectOptionValue = {
export type ISwitchOptionValue = {
type: 'switch';
defaultValue: boolean;
info?: boolean;
inputProps?: Partial<SwitchProps>;
};
@@ -76,6 +79,7 @@ export type ISwitchOptionValue = {
export type ITextInputOptionValue = {
type: 'text';
defaultValue: string;
info?: boolean;
inputProps?: Partial<TextInputProps>;
};
@@ -83,6 +87,7 @@ export type ITextInputOptionValue = {
export type INumberInputOptionValue = {
type: 'number';
defaultValue: number;
info?: boolean;
inputProps?: Partial<NumberInputProps>;
};
@@ -90,6 +95,7 @@ export type INumberInputOptionValue = {
export type ISliderInputOptionValue = {
type: 'slider';
defaultValue: number;
info?: boolean;
min: number;
max: number;
step: number;
@@ -108,6 +114,7 @@ export type IDraggableListInputValue = {
key: string;
subValues?: Record<string, any>;
}[];
info?: boolean;
items: Record<
string,
Record<string, Omit<Exclude<IWidgetOptionValue, IDraggableListInputValue>, 'defaultValue'>>
@@ -117,6 +124,7 @@ export type IDraggableListInputValue = {
export type IDraggableEditableListInputValue<TData extends { id: string }> = {
type: 'draggable-editable-list';
defaultValue: TData[];
info?: boolean;
create: () => TData;
getLabel: (data: TData) => string | JSX.Element;
itemComponent: (props: {
@@ -130,6 +138,7 @@ export type IDraggableEditableListInputValue<TData extends { id: string }> = {
export type IMultipleTextInputOptionValue = {
type: 'multiple-text';
defaultValue: string[];
info?: boolean;
inputProps?: Partial<TextInputProps>;
};