mirror of
https://github.com/shishantbiswas/bknd.git
synced 2026-03-16 04:27:21 +00:00
fix field date error in modal, adjust notification spacing, added entity quick switcher
This commit is contained in:
@@ -45,7 +45,7 @@ function AdminInternal() {
|
||||
|
||||
return (
|
||||
<MantineProvider {...createMantineTheme(theme as any)}>
|
||||
<Notifications />
|
||||
<Notifications position="top-right" />
|
||||
<FlashMessage />
|
||||
<BkndModalsProvider>
|
||||
<Routes />
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -63,9 +63,10 @@ export function StepEntityFields() {
|
||||
};
|
||||
});
|
||||
|
||||
console.log("valid");
|
||||
nextStep("create")();
|
||||
} else {
|
||||
console.warn("not valid");
|
||||
console.warn("not valid", ref.current?.getErrors());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 />
|
||||
|
||||
Reference in New Issue
Block a user