mirror of https://github.com/buster-so/buster.git
Merge remote-tracking branch 'origin/staging' into dallin-bus-1843-on-all-errors-retry
This commit is contained in:
commit
c2ffce7526
|
@ -1,18 +1,13 @@
|
|||
import ChartStackedBar from '@/components/ui/icons/NucleoIconFilled/chart-line-2';
|
||||
import { cn } from '@/lib/classMerge';
|
||||
|
||||
export type SkeletonElement =
|
||||
| 'toolbar'
|
||||
| 'header'
|
||||
| 'image'
|
||||
| 'chart'
|
||||
| 'paragraphs'
|
||||
| 'additionalContent';
|
||||
export type SkeletonElement = 'header' | 'image' | 'chart' | 'paragraphs' | 'additionalContent';
|
||||
|
||||
interface ReportEditorSkeletonProps {
|
||||
className?: string;
|
||||
/** Array of skeleton elements to render. Defaults to all elements if not provided */
|
||||
elements?: SkeletonElement[];
|
||||
showToolbar?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -44,18 +39,25 @@ interface ReportEditorSkeletonProps {
|
|||
* // Show chart instead of image
|
||||
* <ReportEditorSkeleton elements={['header', 'chart', 'paragraphs']} />
|
||||
*/
|
||||
const DEFAULT_ELEMENTS: SkeletonElement[] = ['header', 'chart', 'paragraphs', 'additionalContent'];
|
||||
const DEFAULT_ELEMENTS: SkeletonElement[] = [
|
||||
'header',
|
||||
'paragraphs',
|
||||
'chart',
|
||||
'additionalContent',
|
||||
'paragraphs',
|
||||
];
|
||||
|
||||
export function ReportEditorSkeleton({
|
||||
className,
|
||||
elements = DEFAULT_ELEMENTS,
|
||||
showToolbar = false,
|
||||
}: ReportEditorSkeletonProps) {
|
||||
return (
|
||||
<div
|
||||
className={cn('mx-auto mt-8 w-full space-y-6 sm:px-[max(64px,calc(50%-350px))]', className)}
|
||||
>
|
||||
{/* Toolbar skeleton */}
|
||||
{elements.includes('toolbar') && (
|
||||
{showToolbar && (
|
||||
<div className="border-border flex h-11 w-full animate-pulse items-center justify-between border-b bg-transparent px-3">
|
||||
<div className="flex items-center space-x-2.5">
|
||||
{/* Tool buttons */}
|
||||
|
@ -76,89 +78,104 @@ export function ReportEditorSkeleton({
|
|||
{/* Content area */}
|
||||
<div className="px-0 pb-12">
|
||||
<div className="border-border animate-pulse space-y-6 rounded-lg bg-transparent">
|
||||
{/* Header skeleton */}
|
||||
{elements.includes('header') && (
|
||||
<div className="space-y-3">
|
||||
<div className="bg-muted h-10 w-3/4 rounded-lg"></div>
|
||||
<div className="bg-muted h-4 w-1/2 rounded"></div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Image placeholder */}
|
||||
{elements.includes('image') && (
|
||||
<div className="bg-muted flex h-48 w-full items-center justify-center rounded-lg">
|
||||
<div className="bg-muted-foreground/5 flex h-16 w-16 items-center justify-center rounded-lg">
|
||||
<svg
|
||||
className="text-muted-foreground/40 h-8 w-8"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Chart placeholder */}
|
||||
{elements.includes('chart') && (
|
||||
<div className="bg-muted flex w-full items-center justify-center rounded-lg">
|
||||
<div className="bg-muted-foreground/3 m-5 mx-5 flex h-full min-h-56 w-full items-center justify-center rounded-lg">
|
||||
<div className="text-muted-foreground/15 flex h-full w-full items-center justify-center text-[40px]">
|
||||
<ChartStackedBar />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Paragraph skeletons */}
|
||||
{elements.includes('paragraphs') && (
|
||||
<div className="space-y-4">
|
||||
{/* First paragraph */}
|
||||
<div className="space-y-2">
|
||||
<div className="bg-muted h-4 w-full rounded"></div>
|
||||
<div className="bg-muted h-4 w-11/12 rounded"></div>
|
||||
<div className="bg-muted h-4 w-4/5 rounded"></div>
|
||||
</div>
|
||||
|
||||
{/* Second paragraph */}
|
||||
<div className="space-y-2">
|
||||
<div className="bg-muted h-4 w-full rounded"></div>
|
||||
<div className="bg-muted h-4 w-5/6 rounded"></div>
|
||||
<div className="bg-muted h-4 w-3/4 rounded"></div>
|
||||
<div className="bg-muted h-4 w-2/3 rounded"></div>
|
||||
</div>
|
||||
|
||||
{/* Third paragraph */}
|
||||
<div className="space-y-2">
|
||||
<div className="bg-muted h-4 w-full rounded"></div>
|
||||
<div className="bg-muted h-4 w-4/5 rounded"></div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Additional content blocks */}
|
||||
{elements.includes('additionalContent') && (
|
||||
<div className="mt-8 grid grid-cols-2 gap-4">
|
||||
<div className="space-y-2">
|
||||
<div className="bg-muted h-6 w-2/3 rounded"></div>
|
||||
<div className="bg-muted h-4 w-full rounded"></div>
|
||||
<div className="bg-muted h-4 w-3/4 rounded"></div>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<div className="bg-muted h-6 w-1/2 rounded"></div>
|
||||
<div className="bg-muted h-4 w-full rounded"></div>
|
||||
<div className="bg-muted h-4 w-5/6 rounded"></div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{elements.map((item) => {
|
||||
if (item === 'header') return <HeaderSkeleton />;
|
||||
if (item === 'image') return <ImageSkeleton />;
|
||||
if (item === 'chart') return <ChartSkeleton />;
|
||||
if (item === 'paragraphs') return <ParagraphsSkeleton />;
|
||||
if (item === 'additionalContent') return <AdditionalContentSkeleton />;
|
||||
const _exhaustiveCheck: never = item;
|
||||
return null;
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const HeaderSkeleton = () => {
|
||||
return (
|
||||
<div className="space-y-3">
|
||||
<div className="bg-muted h-10 w-3/4 rounded-lg"></div>
|
||||
<div className="bg-muted h-4 w-1/2 rounded"></div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const ImageSkeleton = () => {
|
||||
return (
|
||||
<div className="bg-muted flex h-48 w-full items-center justify-center rounded-lg">
|
||||
<div className="bg-muted-foreground/5 flex h-16 w-16 items-center justify-center rounded-lg">
|
||||
<svg
|
||||
className="text-muted-foreground/40 h-8 w-8"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const ChartSkeleton = () => {
|
||||
return (
|
||||
<div className="bg-muted flex w-full items-center justify-center rounded-lg">
|
||||
<div className="bg-muted-foreground/3 m-5 mx-5 flex h-full min-h-56 w-full items-center justify-center rounded-lg">
|
||||
<div className="text-muted-foreground/15 flex h-full w-full items-center justify-center text-[40px]">
|
||||
<ChartStackedBar />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const ParagraphsSkeleton = () => {
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
{/* First paragraph */}
|
||||
<div className="space-y-2">
|
||||
<div className="bg-muted h-4 w-full rounded"></div>
|
||||
<div className="bg-muted h-4 w-11/12 rounded"></div>
|
||||
<div className="bg-muted h-4 w-4/5 rounded"></div>
|
||||
</div>
|
||||
|
||||
{/* Second paragraph */}
|
||||
<div className="space-y-2">
|
||||
<div className="bg-muted h-4 w-full rounded"></div>
|
||||
<div className="bg-muted h-4 w-5/6 rounded"></div>
|
||||
<div className="bg-muted h-4 w-3/4 rounded"></div>
|
||||
<div className="bg-muted h-4 w-2/3 rounded"></div>
|
||||
</div>
|
||||
|
||||
{/* Third paragraph */}
|
||||
<div className="space-y-2">
|
||||
<div className="bg-muted h-4 w-full rounded"></div>
|
||||
<div className="bg-muted h-4 w-4/5 rounded"></div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const AdditionalContentSkeleton = () => {
|
||||
return (
|
||||
<div className="mt-8 grid grid-cols-2 gap-4">
|
||||
<div className="space-y-2">
|
||||
<div className="bg-muted h-6 w-2/3 rounded"></div>
|
||||
<div className="bg-muted h-4 w-full rounded"></div>
|
||||
<div className="bg-muted h-4 w-3/4 rounded"></div>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<div className="bg-muted h-6 w-1/2 rounded"></div>
|
||||
<div className="bg-muted h-4 w-full rounded"></div>
|
||||
<div className="bg-muted h-4 w-5/6 rounded"></div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -94,7 +94,11 @@ const useEditorServerUpdates = ({
|
|||
} else if (editor && value && !hasInitialized.current && isEmptyEditor(editor)) {
|
||||
hasInitialized.current = true;
|
||||
markdownToPlatejs(editor, value).then((elements) => {
|
||||
editor.tf.setValue(elements);
|
||||
editor.tf.reset();
|
||||
editor.tf.init({
|
||||
value: elements,
|
||||
autoSelect: false,
|
||||
});
|
||||
});
|
||||
} else {
|
||||
editor?.getPlugin(StreamContentPlugin)?.api.streamContent.stop();
|
||||
|
|
|
@ -14,14 +14,18 @@ export const staticData = {
|
|||
assetType: 'dashboard_file' as AssetType,
|
||||
};
|
||||
|
||||
export const beforeLoad = ({ search }: { search: { dashboard_version_number?: number } }) => {
|
||||
return {
|
||||
dashboard_version_number: search.dashboard_version_number,
|
||||
};
|
||||
};
|
||||
|
||||
export const loader = async ({
|
||||
params: { dashboardId },
|
||||
context: { queryClient },
|
||||
deps: { dashboard_version_number },
|
||||
context: { queryClient, dashboard_version_number },
|
||||
}: {
|
||||
params: { dashboardId: string; chatId?: string };
|
||||
deps: { dashboard_version_number?: number };
|
||||
context: { queryClient: QueryClient };
|
||||
context: { queryClient: QueryClient; dashboard_version_number?: number };
|
||||
}): Promise<{ title: string | undefined }> => {
|
||||
const data = await prefetchGetDashboard({
|
||||
queryClient,
|
||||
|
|
|
@ -15,14 +15,18 @@ export const staticData = {
|
|||
assetType: 'metric_file' as AssetType,
|
||||
};
|
||||
|
||||
export const beforeLoad = ({ search }: { search: { metric_version_number?: number } }) => {
|
||||
return {
|
||||
metric_version_number: search.metric_version_number,
|
||||
};
|
||||
};
|
||||
|
||||
export const loader = async <T extends { metricId: string }>({
|
||||
params: { metricId },
|
||||
context: { queryClient },
|
||||
deps: { metric_version_number },
|
||||
context: { queryClient, metric_version_number },
|
||||
}: {
|
||||
params: T;
|
||||
deps: { metric_version_number?: number };
|
||||
context: { queryClient: QueryClient };
|
||||
context: { queryClient: QueryClient; metric_version_number?: number };
|
||||
}): Promise<{
|
||||
title: string | undefined;
|
||||
}> => {
|
||||
|
|
|
@ -10,14 +10,18 @@ export const validateSearch = z.object({
|
|||
report_version_number: z.coerce.number().optional(),
|
||||
});
|
||||
|
||||
export const beforeLoad = ({ search }: { search: { report_version_number?: number } }) => {
|
||||
return {
|
||||
report_version_number: search.report_version_number,
|
||||
};
|
||||
};
|
||||
|
||||
export const loader = async ({
|
||||
params: { reportId },
|
||||
context: { queryClient },
|
||||
deps: { report_version_number },
|
||||
context: { queryClient, report_version_number },
|
||||
}: {
|
||||
params: { reportId: string; chatId?: string };
|
||||
deps: { report_version_number?: number };
|
||||
context: { queryClient: QueryClient };
|
||||
context: { queryClient: QueryClient; report_version_number?: number };
|
||||
}): Promise<{ title: string | undefined }> => {
|
||||
const data = await prefetchGetReport(reportId, report_version_number, queryClient);
|
||||
return {
|
||||
|
|
Loading…
Reference in New Issue