fix field date error in modal, adjust notification spacing, added entity quick switcher

This commit is contained in:
dswbx
2025-02-27 14:07:49 +01:00
parent 3e28124494
commit 3bf3bb32a4
11 changed files with 94 additions and 15 deletions

View File

@@ -45,7 +45,7 @@ function AdminInternal() {
return (
<MantineProvider {...createMantineTheme(theme as any)}>
<Notifications />
<Notifications position="top-right" />
<FlashMessage />
<BkndModalsProvider>
<Routes />

View File

@@ -26,7 +26,7 @@ export function getSchemaActions({ api, setSchema, reloadSchema }: SchemaActions
autoClose: 3000,
};
if (res.success === true) {
if (res.success) {
console.log("update config", action, module, path, res.body);
if (res.body.success) {
setSchema((prev) => {

View File

@@ -42,6 +42,11 @@ const useLocationFromRouter = (router) => {
];
};
export function isLinkActive(href: string, strict?: boolean) {
const path = window.location.pathname;
return strict ? path === href : path.includes(href);
}
export function Link({
className,
native,

View File

@@ -202,7 +202,7 @@ export const SidebarLink = <E extends React.ElementType = "a">({
<Tag
{...otherProps}
className={twMerge(
"flex flex-row px-4 py-2.5 items-center gap-2",
"flex flex-row px-4 items-center gap-2 h-12",
!disabled &&
"cursor-pointer rounded-md [&.active]:bg-primary/10 [&.active]:hover:bg-primary/15 [&.active]:font-medium hover:bg-primary/5 focus:bg-primary/5 link",
disabled && "opacity-50 cursor-not-allowed pointer-events-none",

View File

@@ -14,6 +14,7 @@ import {
Textarea,
createTheme,
} from "@mantine/core";
import { Notifications } from "@mantine/notifications";
import { twMerge } from "tailwind-merge";
// default: https://github.com/mantinedev/mantine/blob/master/packages/%40mantine/core/src/core/MantineProvider/default-theme.ts
@@ -126,6 +127,13 @@ export function createMantineTheme(scheme: "light" | "dark"): {
indicator: light ? "bg-background" : "bg-primary/15",
}),
}),
Notifications: Notifications.extend({
classNames: (theme, props) => {
return {
notification: "-top-4 -right-4",
};
},
}),
},
primaryColor: "dark",
primaryShade: 9,

View File

@@ -53,6 +53,14 @@ export function withAbsolute(url: string) {
return `~/${basepath}/${url}`.replace(/\/+/g, "/");
}
export function useRouteNavigate() {
const [navigate] = useNavigate();
return (fn: (r: typeof routes) => string, options?: Parameters<typeof navigate>[1]) => {
navigate(fn(routes), options);
};
}
export function useNavigate() {
const [location, navigate] = useLocation();
const router = useRouter();

View File

@@ -63,9 +63,10 @@ export function StepEntityFields() {
};
});
console.log("valid");
nextStep("create")();
} else {
console.warn("not valid");
console.warn("not valid", ref.current?.getErrors());
}
}

View File

@@ -7,18 +7,20 @@ import {
IconPhoto,
IconPlus,
IconSettings,
IconSwitchHorizontal,
} from "@tabler/icons-react";
import type { Entity, TEntityType } from "data";
import { TbDatabasePlus } from "react-icons/tb";
import { twMerge } from "tailwind-merge";
import { useBkndData } from "ui/client/schema/data/use-bknd-data";
import { Button } from "ui/components/buttons/Button";
import { IconButton } from "ui/components/buttons/IconButton";
import { Empty } from "ui/components/display/Empty";
import { Dropdown, type DropdownClickableChild } from "ui/components/overlay/Dropdown";
import { Link } from "ui/components/wouter/Link";
import { Link, isLinkActive } from "ui/components/wouter/Link";
import { useBrowserTitle } from "ui/hooks/use-browser-title";
import * as AppShell from "ui/layouts/AppShell/AppShell";
import { routes, useNavigate } from "ui/lib/routes";
import { routes, useNavigate, useRouteNavigate } from "ui/lib/routes";
export function DataRoot({ children }) {
// @todo: settings routes should be centralized
@@ -106,6 +108,7 @@ const EntityLinkList = ({
suggestCreate = false,
}: { entities: Entity[]; title?: string; context: "data" | "schema"; suggestCreate?: boolean }) => {
const { $data } = useBkndData();
const navigate = useRouteNavigate();
if (entities.length === 0) {
return suggestCreate ? (
<Empty
@@ -119,6 +122,22 @@ const EntityLinkList = ({
) : null;
}
function handleClick(entity: Entity) {
return (e) => {
e.stopPropagation();
e.preventDefault();
switch (context) {
case "schema":
navigate((r) => r.data.entity.list(entity.name));
break;
case "data":
navigate((r) => r.data.schema.entity(entity.name));
break;
}
};
}
return (
<nav
className={twMerge(
@@ -135,8 +154,22 @@ const EntityLinkList = ({
: routes.data.schema.entity(entity.name);
return (
<EntityContextMenu key={entity.name} entity={entity}>
<AppShell.SidebarLink as={Link} href={href}>
<AppShell.SidebarLink
as={Link}
href={href}
className="justify-between items-center"
>
{entity.label}
{isLinkActive(href) && (
<Button
IconLeft={IconSwitchHorizontal}
size="small"
onClick={handleClick(entity)}
>
{context === "schema" ? "Data" : "Fields"}
</Button>
)}
</AppShell.SidebarLink>
</EntityContextMenu>
);

View File

@@ -225,6 +225,9 @@ const Fields = ({
<Button size="small" onClick={() => setRes(ref.current?.getData())}>
data
</Button>
<Button size="small" onClick={() => setRes(ref.current?.getErrors())}>
errors
</Button>
<Button size="small" onClick={handleUpdate}>
update
</Button>

View File

@@ -1,14 +1,14 @@
import { typeboxResolver } from "@hookform/resolvers/typebox";
import { Tabs, TextInput, Textarea, Tooltip } from "@mantine/core";
import { useDisclosure } from "@mantine/hooks";
import { Type } from "@sinclair/typebox";
import {
Default,
type Static,
StringIdentifier,
Type,
objectCleanEmpty,
ucFirstAllSnakeToPascalWithSpaces,
} from "core/utils";
import { Entity } from "data";
import {
type TAppDataEntityFields,
fieldsSchemaObject as originalFieldsSchemaObject,
@@ -31,11 +31,16 @@ import { dataFieldsUiSchema } from "../../settings/routes/data.settings";
const fieldsSchemaObject = originalFieldsSchemaObject;
const fieldsSchema = Type.Union(Object.values(fieldsSchemaObject));
const fieldSchema = Type.Object({
name: StringIdentifier,
new: Type.Optional(Type.Boolean({ const: true })),
field: fieldsSchema,
});
const fieldSchema = Type.Object(
{
name: StringIdentifier,
new: Type.Optional(Type.Boolean({ const: true })),
field: fieldsSchema,
},
{
additionalProperties: false,
},
);
type TFieldSchema = Static<typeof fieldSchema>;
const schema = Type.Object({
@@ -63,6 +68,7 @@ export type EntityFieldsFormRef = {
getValues: () => TFieldsFormSchema;
getData: () => TAppDataEntityFields;
isValid: () => boolean;
getErrors: () => any;
reset: () => void;
};
@@ -117,6 +123,7 @@ export const EntityFieldsForm = forwardRef<EntityFieldsFormRef, EntityFieldsForm
return toCleanValues(getValues());
},
isValid: () => isValid,
getErrors: () => errors,
}));
function handleAppend(_type: keyof typeof fieldsSchemaObject) {
@@ -125,7 +132,7 @@ export const EntityFieldsForm = forwardRef<EntityFieldsFormRef, EntityFieldsForm
new: true,
field: {
type: _type,
config: {},
config: Default(fieldsSchemaObject[_type]?.properties.config, {}) as any,
},
};
append(newField);

View File

@@ -1,5 +1,6 @@
import { Button, Modal, Switch, Tooltip, useMantineColorScheme } from "@mantine/core";
import { useColorScheme, useDisclosure } from "@mantine/hooks";
import { notifications } from "@mantine/notifications";
import { Button as AppButton } from "../../../components/buttons/Button";
export default function MantineTest() {
@@ -10,6 +11,19 @@ export default function MantineTest() {
<Button color="blue">Mantine</Button>
<AppButton>Button</AppButton>
<AppButton variant="primary">Button</AppButton>
<Button
onClick={() => {
notifications.show({
title: "Notification",
message: "This is a notification",
autoClose: false,
color: "blue",
});
}}
>
Notification
</Button>
</div>
<MantineModal />
<MantineTooltip />