Merge remote-tracking branch 'origin/staging' into dallin-bus-1843-on-all-errors-retry

This commit is contained in:
dal 2025-09-19 10:46:18 -06:00
commit c2ffce7526
No known key found for this signature in database
GPG Key ID: 16F4B0E1E9F61122
5 changed files with 136 additions and 103 deletions

View File

@ -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>
);
};

View File

@ -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();

View File

@ -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,

View File

@ -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;
}> => {

View File

@ -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 {