feat: add board access settings (#249)
* wip: add board access settings * wip: add user access control * wip: add user access control * feat: add user access control * refactor: move away from mantine-modal-manager * fix: ci issues and failing tests * fix: lint issue * fix: format issue * fix: deepsource issues * chore: address pull request feedback
This commit is contained in:
@@ -1,8 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import type { ManagedModal } from "mantine-modal-manager";
|
||||
|
||||
import type { WidgetKind } from "@homarr/definitions";
|
||||
import { createModal } from "@homarr/modals";
|
||||
import { useI18n } from "@homarr/translation/client";
|
||||
import { Button, Group, Stack } from "@homarr/ui";
|
||||
|
||||
@@ -26,61 +25,67 @@ interface ModalProps<TSort extends WidgetKind> {
|
||||
integrationSupport: boolean;
|
||||
}
|
||||
|
||||
export const WidgetEditModal: ManagedModal<ModalProps<WidgetKind>> = ({
|
||||
actions,
|
||||
innerProps,
|
||||
}) => {
|
||||
const t = useI18n();
|
||||
const form = useForm({
|
||||
initialValues: innerProps.value,
|
||||
});
|
||||
export const WidgetEditModal = createModal<ModalProps<WidgetKind>>(
|
||||
({ actions, innerProps }) => {
|
||||
const t = useI18n();
|
||||
const form = useForm({
|
||||
initialValues: innerProps.value,
|
||||
});
|
||||
|
||||
const { definition } = widgetImports[innerProps.kind];
|
||||
const { definition } = widgetImports[innerProps.kind];
|
||||
|
||||
return (
|
||||
<form
|
||||
onSubmit={form.onSubmit((v) => {
|
||||
innerProps.onSuccessfulEdit(v);
|
||||
actions.closeModal();
|
||||
})}
|
||||
>
|
||||
<FormProvider form={form}>
|
||||
<Stack>
|
||||
{innerProps.integrationSupport && (
|
||||
<WidgetIntegrationSelect
|
||||
label={t("item.edit.field.integrations.label")}
|
||||
data={innerProps.integrationData}
|
||||
{...form.getInputProps("integrations")}
|
||||
/>
|
||||
)}
|
||||
{Object.entries(definition.options).map(
|
||||
([key, value]: [string, OptionsBuilderResult[string]]) => {
|
||||
const Input = getInputForType(value.type);
|
||||
return (
|
||||
<form
|
||||
onSubmit={form.onSubmit((values) => {
|
||||
innerProps.onSuccessfulEdit(values);
|
||||
actions.closeModal();
|
||||
})}
|
||||
>
|
||||
<FormProvider form={form}>
|
||||
<Stack>
|
||||
{innerProps.integrationSupport && (
|
||||
<WidgetIntegrationSelect
|
||||
label={t("item.edit.field.integrations.label")}
|
||||
data={innerProps.integrationData}
|
||||
{...form.getInputProps("integrations")}
|
||||
/>
|
||||
)}
|
||||
{Object.entries(definition.options).map(
|
||||
([key, value]: [string, OptionsBuilderResult[string]]) => {
|
||||
const Input = getInputForType(value.type);
|
||||
|
||||
if (!Input || value.shouldHide?.(form.values.options as never)) {
|
||||
return null;
|
||||
}
|
||||
if (
|
||||
!Input ||
|
||||
value.shouldHide?.(form.values.options as never)
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Input
|
||||
key={key}
|
||||
kind={innerProps.kind}
|
||||
property={key}
|
||||
options={value as never}
|
||||
/>
|
||||
);
|
||||
},
|
||||
)}
|
||||
<Group justify="right">
|
||||
<Button onClick={actions.closeModal} variant="subtle" color="gray">
|
||||
{t("common.action.cancel")}
|
||||
</Button>
|
||||
<Button type="submit" color="teal">
|
||||
{t("common.action.saveChanges")}
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</FormProvider>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
return (
|
||||
<Input
|
||||
key={key}
|
||||
kind={innerProps.kind}
|
||||
property={key}
|
||||
options={value as never}
|
||||
/>
|
||||
);
|
||||
},
|
||||
)}
|
||||
<Group justify="right">
|
||||
<Button
|
||||
onClick={actions.closeModal}
|
||||
variant="subtle"
|
||||
color="gray"
|
||||
>
|
||||
{t("common.action.cancel")}
|
||||
</Button>
|
||||
<Button type="submit" color="teal">
|
||||
{t("common.action.saveChanges")}
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</FormProvider>
|
||||
</form>
|
||||
);
|
||||
},
|
||||
).withOptions({});
|
||||
|
||||
@@ -48,17 +48,17 @@ export const WidgetIntegrationSelect = ({
|
||||
const handleValueSelect = (selectedValue: string) =>
|
||||
onChange(
|
||||
multiSelectValues.includes(selectedValue)
|
||||
? multiSelectValues.filter((v) => v !== selectedValue)
|
||||
? multiSelectValues.filter((value) => value !== selectedValue)
|
||||
: [...multiSelectValues, selectedValue],
|
||||
);
|
||||
|
||||
const handleValueRemove = (val: string) =>
|
||||
onChange(multiSelectValues.filter((v) => v !== val));
|
||||
const handleValueRemove = (valueToRemove: string) =>
|
||||
onChange(multiSelectValues.filter((value) => value !== valueToRemove));
|
||||
|
||||
const values = multiSelectValues.map((item) => (
|
||||
<IntegrationPill
|
||||
key={item}
|
||||
option={data.find((i) => i.id === item)!}
|
||||
option={data.find((integration) => integration.id === item)!}
|
||||
onRemove={() => handleValueRemove(item)}
|
||||
/>
|
||||
));
|
||||
|
||||
Reference in New Issue
Block a user