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:
Meier Lukas
2024-03-20 20:30:58 +01:00
committed by GitHub
parent 4753bc7162
commit 361700b239
59 changed files with 1763 additions and 1338 deletions

View File

@@ -3,6 +3,7 @@
import { useCallback, useMemo, useState } from "react";
import type { IntegrationKind, WidgetKind } from "@homarr/definitions";
import { useModalAction } from "@homarr/modals";
import { showSuccessNotification } from "@homarr/notifications";
import { useScopedI18n } from "@homarr/translation/client";
import {
@@ -17,10 +18,11 @@ import {
import {
loadWidgetDynamic,
reduceWidgetOptionsWithDefaultValues,
WidgetEditModal,
widgetImports,
} from "@homarr/widgets";
import { modalEvents } from "../../modals";
import { PreviewDimensionsModal } from "./_dimension-modal";
import type { Dimensions } from "./_dimension-modal";
interface WidgetPreviewPageContentProps {
@@ -38,6 +40,10 @@ export const WidgetPreviewPageContent = ({
integrationData,
}: WidgetPreviewPageContentProps) => {
const t = useScopedI18n("widgetPreview");
const { openModal: openWidgetEditModal } = useModalAction(WidgetEditModal);
const { openModal: openPreviewDimensionsModal } = useModalAction(
PreviewDimensionsModal,
);
const currentDefinition = useMemo(
() => widgetImports[kind].definition,
[kind],
@@ -55,28 +61,25 @@ export const WidgetPreviewPageContent = ({
integrations: [],
});
const Comp = loadWidgetDynamic(kind);
const openWitgetEditModal = useCallback(() => {
return modalEvents.openManagedModal({
modal: "widgetEditModal",
innerProps: {
kind,
value: state,
onSuccessfulEdit: (value) => {
setState(value);
},
integrationData: integrationData.filter(
(integration) =>
"supportedIntegrations" in currentDefinition &&
(currentDefinition.supportedIntegrations as string[]).some(
(kind) => kind === integration.kind,
),
),
integrationSupport: "supportedIntegrations" in currentDefinition,
const handleOpenEditWidgetModal = useCallback(() => {
openWidgetEditModal({
kind,
value: state,
onSuccessfulEdit: (value) => {
setState(value);
},
integrationData: integrationData.filter(
(integration) =>
"supportedIntegrations" in currentDefinition &&
(currentDefinition.supportedIntegrations as string[]).some(
(kind) => kind === integration.kind,
),
),
integrationSupport: "supportedIntegrations" in currentDefinition,
});
}, [kind, state, integrationData, currentDefinition]);
}, [currentDefinition, integrationData, kind, openWidgetEditModal, state]);
const Comp = loadWidgetDynamic(kind);
const toggleEditMode = useCallback(() => {
setEditMode((editMode) => !editMode);
@@ -86,15 +89,11 @@ export const WidgetPreviewPageContent = ({
}, [editMode, t]);
const openDimensionsModal = useCallback(() => {
modalEvents.openManagedModal({
modal: "dimensionsModal",
title: t("dimensions.title"),
innerProps: {
dimensions,
setDimensions,
},
openPreviewDimensionsModal({
dimensions,
setDimensions,
});
}, [dimensions, t]);
}, [dimensions, openPreviewDimensionsModal]);
return (
<>
@@ -107,7 +106,8 @@ export const WidgetPreviewPageContent = ({
<Comp
options={state.options as never}
integrations={state.integrations.map(
(id) => integrationData.find((x) => x.id === id)!,
(id) =>
integrationData.find((integration) => integration.id === id)!,
)}
width={dimensions.width}
height={dimensions.height}
@@ -119,7 +119,7 @@ export const WidgetPreviewPageContent = ({
size={48}
variant="default"
radius="xl"
onClick={openWitgetEditModal}
onClick={handleOpenEditWidgetModal}
>
<IconPencil size={24} />
</ActionIcon>

View File

@@ -1,8 +1,7 @@
"use client";
import type { ManagedModal } from "mantine-modal-manager";
import { useForm } from "@homarr/form";
import { createModal } from "@homarr/modals";
import { useI18n } from "@homarr/translation/client";
import { Button, Group, InputWrapper, Slider, Stack } from "@homarr/ui";
@@ -11,49 +10,50 @@ interface InnerProps {
setDimensions: (dimensions: Dimensions) => void;
}
export const PreviewDimensionsModal: ManagedModal<InnerProps> = ({
actions,
innerProps,
}) => {
const t = useI18n();
const form = useForm({
initialValues: innerProps.dimensions,
});
export const PreviewDimensionsModal = createModal<InnerProps>(
({ actions, innerProps }) => {
const t = useI18n();
const form = useForm({
initialValues: innerProps.dimensions,
});
const handleSubmit = (values: Dimensions) => {
innerProps.setDimensions(values);
actions.closeModal();
};
const handleSubmit = (values: Dimensions) => {
innerProps.setDimensions(values);
actions.closeModal();
};
return (
<form onSubmit={form.onSubmit(handleSubmit)}>
<Stack>
<InputWrapper label={t("item.move.field.width.label")}>
<Slider
min={64}
max={1024}
step={64}
{...form.getInputProps("width")}
/>
</InputWrapper>
<InputWrapper label={t("item.move.field.height.label")}>
<Slider
min={64}
max={1024}
step={64}
{...form.getInputProps("height")}
/>
</InputWrapper>
<Group justify="end">
<Button variant="subtle" color="gray" onClick={actions.closeModal}>
{t("common.action.cancel")}
</Button>
<Button type="submit">{t("common.action.confirm")}</Button>
</Group>
</Stack>
</form>
);
};
return (
<form onSubmit={form.onSubmit(handleSubmit)}>
<Stack>
<InputWrapper label={t("item.move.field.width.label")}>
<Slider
min={64}
max={1024}
step={64}
{...form.getInputProps("width")}
/>
</InputWrapper>
<InputWrapper label={t("item.move.field.height.label")}>
<Slider
min={64}
max={1024}
step={64}
{...form.getInputProps("height")}
/>
</InputWrapper>
<Group justify="end">
<Button variant="subtle" color="gray" onClick={actions.closeModal}>
{t("common.action.cancel")}
</Button>
<Button type="submit">{t("common.action.confirm")}</Button>
</Group>
</Stack>
</form>
);
},
).withOptions({
defaultTitle: (t) => t("widgetPreview.dimensions.title"),
});
export interface Dimensions {
width: number;