mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-03-26 03:11:12 +01:00
Better model updates
This commit is contained in:
@@ -5,7 +5,7 @@ import { Dialog } from './core/Dialog';
|
||||
type DialogEntry = {
|
||||
id: string;
|
||||
render: ({ hide }: { hide: () => void }) => React.ReactNode;
|
||||
} & Pick<DialogProps, 'title' | 'description' | 'hideX' | 'className'>;
|
||||
} & Pick<DialogProps, 'title' | 'description' | 'hideX' | 'className' | 'size'>;
|
||||
|
||||
type DialogEntryOptionalId = Omit<DialogEntry, 'id'> & { id?: string };
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import { useDuplicateRequest } from '../hooks/useDuplicateRequest';
|
||||
import { useRequest } from '../hooks/useRequest';
|
||||
import { Dropdown } from './core/Dropdown';
|
||||
import { Icon } from './core/Icon';
|
||||
import { InlineCode } from './core/InlineCode';
|
||||
|
||||
interface Props {
|
||||
requestId: string;
|
||||
@@ -30,9 +31,12 @@ export function RequestActionsDropdown({ requestId, children }: Props) {
|
||||
onSelect: async () => {
|
||||
const confirmed = await confirm({
|
||||
title: 'Delete Request',
|
||||
description: `Are you sure you want to delete "${request?.name}"?`,
|
||||
confirmButtonColor: 'danger',
|
||||
confirmButtonText: 'Delete',
|
||||
variant: 'delete',
|
||||
description: (
|
||||
<>
|
||||
Are you sure you want to delete <InlineCode>{request?.name}</InlineCode>?
|
||||
</>
|
||||
),
|
||||
});
|
||||
if (confirmed) {
|
||||
deleteRequest.mutate();
|
||||
|
||||
@@ -10,12 +10,13 @@ import { Button } from './core/Button';
|
||||
import type { DropdownItem } from './core/Dropdown';
|
||||
import { Dropdown } from './core/Dropdown';
|
||||
import { Icon } from './core/Icon';
|
||||
import { InlineCode } from './core/InlineCode';
|
||||
|
||||
type Props = {
|
||||
className?: string;
|
||||
};
|
||||
|
||||
export const WorkspaceDropdown = memo(function WorkspaceDropdown({ className }: Props) {
|
||||
export const WorkspaceActionsDropdown = memo(function WorkspaceDropdown({ className }: Props) {
|
||||
const workspaces = useWorkspaces();
|
||||
const activeWorkspace = useActiveWorkspace();
|
||||
const activeWorkspaceId = activeWorkspace?.id ?? null;
|
||||
@@ -51,9 +52,12 @@ export const WorkspaceDropdown = memo(function WorkspaceDropdown({ className }:
|
||||
onSelect: async () => {
|
||||
const confirmed = await confirm({
|
||||
title: 'Delete Workspace',
|
||||
description: `Are you sure you want to delete "${activeWorkspace?.name}"?`,
|
||||
confirmButtonColor: 'danger',
|
||||
confirmButtonText: 'Delete',
|
||||
variant: 'delete',
|
||||
description: (
|
||||
<>
|
||||
Are you sure you want to delete <InlineCode>{activeWorkspace?.name}</InlineCode>?
|
||||
</>
|
||||
),
|
||||
});
|
||||
if (confirmed) {
|
||||
deleteWorkspace.mutate();
|
||||
@@ -5,7 +5,7 @@ import { IconButton } from './core/IconButton';
|
||||
import { HStack } from './core/Stacks';
|
||||
import { RequestActionsDropdown } from './RequestActionsDropdown';
|
||||
import { SidebarActions } from './SidebarActions';
|
||||
import { WorkspaceDropdown } from './WorkspaceDropdown';
|
||||
import { WorkspaceActionsDropdown } from './WorkspaceActionsDropdown';
|
||||
|
||||
interface Props {
|
||||
className?: string;
|
||||
@@ -21,13 +21,12 @@ export const WorkspaceHeader = memo(function WorkspaceHeader({ className }: Prop
|
||||
>
|
||||
<HStack space={0.5} className="flex-1 pointer-events-none" alignItems="center">
|
||||
<SidebarActions />
|
||||
<WorkspaceDropdown className="pointer-events-auto" />
|
||||
<WorkspaceActionsDropdown className="pointer-events-auto" />
|
||||
</HStack>
|
||||
<div className="flex-[2] text-center text-gray-800 text-sm truncate pointer-events-none">
|
||||
{activeRequest?.name}
|
||||
</div>
|
||||
<div className="flex-1 flex justify-end -mr-2 pointer-events-none">
|
||||
<IconButton size="sm" title="" icon="magnifyingGlass" />
|
||||
{activeRequest && (
|
||||
<RequestActionsDropdown requestId={activeRequest?.id}>
|
||||
<IconButton
|
||||
|
||||
@@ -3,8 +3,8 @@ import { motion } from 'framer-motion';
|
||||
import type { ReactNode } from 'react';
|
||||
import { useMemo } from 'react';
|
||||
import { Overlay } from '../Overlay';
|
||||
import { Heading } from './Heading';
|
||||
import { IconButton } from './IconButton';
|
||||
import { VStack } from './Stacks';
|
||||
|
||||
export interface DialogProps {
|
||||
children: ReactNode;
|
||||
@@ -13,14 +13,14 @@ export interface DialogProps {
|
||||
title: ReactNode;
|
||||
description?: ReactNode;
|
||||
className?: string;
|
||||
wide?: boolean;
|
||||
size?: 'sm' | 'md' | 'full' | 'dynamic';
|
||||
hideX?: boolean;
|
||||
}
|
||||
|
||||
export function Dialog({
|
||||
children,
|
||||
className,
|
||||
wide,
|
||||
size = 'full',
|
||||
open,
|
||||
onClose,
|
||||
title,
|
||||
@@ -48,9 +48,12 @@ export function Dialog({
|
||||
className={classnames(
|
||||
className,
|
||||
'relative bg-gray-50 pointer-events-auto',
|
||||
'w-[20rem] max-h-[80vh] p-5 rounded-lg overflow-auto',
|
||||
'max-h-[80vh] p-5 rounded-lg overflow-auto',
|
||||
'dark:border border-gray-200 shadow-md shadow-black/10',
|
||||
wide && 'w-[80vw] max-w-[50rem]',
|
||||
size === 'sm' && 'w-[25rem]',
|
||||
size === 'md' && 'w-[45rem]',
|
||||
size === 'full' && 'w-[80vw]',
|
||||
size === 'dynamic' && 'min-w-[30vw] max-w-[80vw]',
|
||||
)}
|
||||
>
|
||||
{!hideX && (
|
||||
@@ -63,13 +66,11 @@ export function Dialog({
|
||||
className="ml-auto absolute right-1 top-1"
|
||||
/>
|
||||
)}
|
||||
<VStack space={3}>
|
||||
<h1 className="text-xl font-semibold w-full" id={titleId}>
|
||||
{title}
|
||||
</h1>
|
||||
{description && <p id={descriptionId}>{description}</p>}
|
||||
<div>{children}</div>
|
||||
</VStack>
|
||||
<Heading className="text-xl font-semibold w-full" id={titleId}>
|
||||
{title}
|
||||
</Heading>
|
||||
{description && <p id={descriptionId}>{description}</p>}
|
||||
<div className="mt-6">{children}</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
import classnames from 'classnames';
|
||||
import type { ReactNode } from 'react';
|
||||
import type { HTMLAttributes } from 'react';
|
||||
|
||||
type Props = {
|
||||
className?: string;
|
||||
children?: ReactNode;
|
||||
};
|
||||
|
||||
export function Heading({ className, children, ...props }: Props) {
|
||||
export function Heading({ className, children, ...props }: HTMLAttributes<HTMLHeadingElement>) {
|
||||
return (
|
||||
<h1 className={classnames(className, 'text-2xl font-semibold text-gray-900 mb-3')} {...props}>
|
||||
{children}
|
||||
|
||||
14
src-web/components/core/InlineCode.tsx
Normal file
14
src-web/components/core/InlineCode.tsx
Normal file
@@ -0,0 +1,14 @@
|
||||
import classnames from 'classnames';
|
||||
import type { HTMLAttributes } from 'react';
|
||||
|
||||
export function InlineCode({ className, ...props }: HTMLAttributes<HTMLSpanElement>) {
|
||||
return (
|
||||
<code
|
||||
className={classnames(
|
||||
className,
|
||||
'font-mono text-sm bg-highlight border-0 border-gray-200 px-1.5 py-0.5 rounded text-gray-800 shadow-inner',
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user