mirror of https://github.com/buster-so/buster.git
update code card
This commit is contained in:
parent
f70338ba1f
commit
4db6adc757
|
@ -0,0 +1,98 @@
|
||||||
|
import React, { forwardRef } from 'react';
|
||||||
|
import { AppSplitter, type AppSplitterRef } from '@/components/ui/layouts/AppSplitter';
|
||||||
|
import { SQLContainer } from './SQLContainer';
|
||||||
|
import { DataContainer } from './DataContainer';
|
||||||
|
import type { IDataResult } from '@/api/asset_interfaces';
|
||||||
|
import { DiffSQLContainer } from './DiffSQLContainer';
|
||||||
|
|
||||||
|
const DEFAULT_LAYOUT = ['auto', '300px'];
|
||||||
|
|
||||||
|
export interface AppVerticalDiffCodeSplitterProps {
|
||||||
|
originalValue: string;
|
||||||
|
value: string;
|
||||||
|
setValue: (value: string) => void;
|
||||||
|
language: 'sql' | 'yaml';
|
||||||
|
runSQLError: string | undefined;
|
||||||
|
onRunQuery: () => Promise<void>;
|
||||||
|
data: IDataResult;
|
||||||
|
fetchingData: boolean;
|
||||||
|
defaultLayout?: [string, string];
|
||||||
|
autoSaveId: string;
|
||||||
|
topHidden?: boolean;
|
||||||
|
onSaveSQL?: () => Promise<void>;
|
||||||
|
disabledSave?: boolean;
|
||||||
|
gapAmount?: number;
|
||||||
|
className?: string;
|
||||||
|
fileName?: string;
|
||||||
|
versionNumber?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const AppVerticalDiffCodeSplitter = forwardRef<
|
||||||
|
AppSplitterRef,
|
||||||
|
AppVerticalDiffCodeSplitterProps
|
||||||
|
>(
|
||||||
|
(
|
||||||
|
{
|
||||||
|
originalValue,
|
||||||
|
value,
|
||||||
|
setValue,
|
||||||
|
language,
|
||||||
|
runSQLError,
|
||||||
|
onRunQuery,
|
||||||
|
onSaveSQL,
|
||||||
|
data,
|
||||||
|
fetchingData,
|
||||||
|
defaultLayout = DEFAULT_LAYOUT,
|
||||||
|
autoSaveId,
|
||||||
|
fileName,
|
||||||
|
versionNumber,
|
||||||
|
disabledSave = false,
|
||||||
|
topHidden = false,
|
||||||
|
gapAmount = 3,
|
||||||
|
className
|
||||||
|
},
|
||||||
|
ref
|
||||||
|
) => {
|
||||||
|
//tailwind might not like this, but yolo
|
||||||
|
const sqlContainerClassName = !topHidden ? `mb-${gapAmount}` : '';
|
||||||
|
const dataContainerClassName = !topHidden ? `mt-${gapAmount}` : '';
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AppSplitter
|
||||||
|
ref={ref}
|
||||||
|
leftChildren={
|
||||||
|
<DiffSQLContainer
|
||||||
|
className={sqlContainerClassName}
|
||||||
|
originalValue={originalValue}
|
||||||
|
value={value}
|
||||||
|
setValue={setValue}
|
||||||
|
language={language}
|
||||||
|
error={runSQLError}
|
||||||
|
onRunQuery={onRunQuery}
|
||||||
|
onSaveSQL={onSaveSQL}
|
||||||
|
disabledSave={disabledSave}
|
||||||
|
fileName={fileName}
|
||||||
|
versionNumber={versionNumber}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
rightChildren={
|
||||||
|
<DataContainer
|
||||||
|
className={dataContainerClassName}
|
||||||
|
data={data}
|
||||||
|
fetchingData={fetchingData}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
split="horizontal"
|
||||||
|
defaultLayout={defaultLayout}
|
||||||
|
autoSaveId={autoSaveId}
|
||||||
|
preserveSide="left"
|
||||||
|
rightPanelMinSize={'80px'}
|
||||||
|
leftPanelMinSize={'120px'}
|
||||||
|
leftHidden={topHidden}
|
||||||
|
className={className}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
AppVerticalDiffCodeSplitter.displayName = 'AppVerticalDiffCodeSplitter';
|
|
@ -0,0 +1,114 @@
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Command, ReturnKey } from '@/components/ui/icons';
|
||||||
|
import { useBusterNotifications } from '@/context/BusterNotifications';
|
||||||
|
import { useMemoizedFn } from '@/hooks';
|
||||||
|
import { Button } from '@/components/ui/buttons/Button';
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
import type { AppVerticalCodeSplitterProps } from './AppVerticalCodeSplitter';
|
||||||
|
import { cn } from '@/lib/classMerge';
|
||||||
|
import { ErrorClosableContainer } from '@/components/ui/error/ErrorClosableContainer';
|
||||||
|
import { AppDiffCodeEditor } from '@/components/ui/inputs';
|
||||||
|
import { Copy2 } from '@/components/ui/icons';
|
||||||
|
import { Text } from '@/components/ui/typography';
|
||||||
|
import { VersionPill } from '@/components/ui/tags/VersionPill';
|
||||||
|
|
||||||
|
export const DiffSQLContainer: React.FC<{
|
||||||
|
className?: string;
|
||||||
|
originalValue: string | undefined;
|
||||||
|
value: string | undefined;
|
||||||
|
setValue: (value: string) => void;
|
||||||
|
onRunQuery: () => Promise<void>;
|
||||||
|
onSaveSQL?: AppVerticalCodeSplitterProps['onSaveSQL'];
|
||||||
|
disabledSave?: AppVerticalCodeSplitterProps['disabledSave'];
|
||||||
|
error?: string | null;
|
||||||
|
language: 'sql' | 'yaml';
|
||||||
|
fileName?: string;
|
||||||
|
versionNumber?: number;
|
||||||
|
}> = React.memo(
|
||||||
|
({
|
||||||
|
language,
|
||||||
|
disabledSave,
|
||||||
|
className = '',
|
||||||
|
originalValue,
|
||||||
|
value,
|
||||||
|
setValue,
|
||||||
|
onRunQuery,
|
||||||
|
onSaveSQL,
|
||||||
|
error,
|
||||||
|
fileName,
|
||||||
|
versionNumber
|
||||||
|
}) => {
|
||||||
|
const [isRunning, setIsRunning] = useState(false);
|
||||||
|
const { openInfoMessage } = useBusterNotifications();
|
||||||
|
|
||||||
|
const onCopySQL = useMemoizedFn(() => {
|
||||||
|
navigator.clipboard.writeText(value || '');
|
||||||
|
openInfoMessage('Copied to clipboard');
|
||||||
|
});
|
||||||
|
|
||||||
|
const onRunQueryPreflight = useMemoizedFn(async () => {
|
||||||
|
setIsRunning(true);
|
||||||
|
await onRunQuery();
|
||||||
|
setIsRunning(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
'flex h-full w-full flex-col overflow-hidden',
|
||||||
|
'bg-background rounded border',
|
||||||
|
className
|
||||||
|
)}>
|
||||||
|
<div className="bg-item-select flex h-8 w-full items-center justify-between border-b px-2.5">
|
||||||
|
<div className="flex items-center gap-x-1.5">
|
||||||
|
<Text>{fileName}</Text>
|
||||||
|
{versionNumber && <VersionPill version_number={versionNumber} />}
|
||||||
|
</div>
|
||||||
|
<Button prefix={<Copy2 />} variant="ghost" onClick={onCopySQL} />
|
||||||
|
</div>
|
||||||
|
<AppDiffCodeEditor
|
||||||
|
className="overflow-hidden"
|
||||||
|
modified={value || ''}
|
||||||
|
original={originalValue || ''}
|
||||||
|
language={language}
|
||||||
|
onChange={setValue}
|
||||||
|
readOnly={true}
|
||||||
|
/>
|
||||||
|
<div className="relative hidden items-center justify-between border-t px-4 py-2.5">
|
||||||
|
<Button onClick={onCopySQL}>Copy SQL</Button>
|
||||||
|
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
{onSaveSQL && (
|
||||||
|
<Button
|
||||||
|
disabled={disabledSave || !value || isRunning}
|
||||||
|
variant="black"
|
||||||
|
onClick={onSaveSQL}>
|
||||||
|
Save
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Button
|
||||||
|
variant="default"
|
||||||
|
loading={isRunning}
|
||||||
|
disabled={!value}
|
||||||
|
className="flex items-center space-x-0"
|
||||||
|
onClick={onRunQueryPreflight}
|
||||||
|
suffix={
|
||||||
|
<div className="flex items-center gap-x-1 text-sm">
|
||||||
|
<Command />
|
||||||
|
<ReturnKey />
|
||||||
|
</div>
|
||||||
|
}>
|
||||||
|
Run
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{error && <ErrorClosableContainer error={error} />}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
DiffSQLContainer.displayName = 'DiffSQLContainer';
|
|
@ -0,0 +1,60 @@
|
||||||
|
import type { Meta, StoryObj } from '@storybook/react';
|
||||||
|
import { DashboardFilterDiffModall } from './DashboardFilterDiffModall';
|
||||||
|
import { fn } from '@storybook/test';
|
||||||
|
import { faker } from '@faker-js/faker';
|
||||||
|
|
||||||
|
const meta = {
|
||||||
|
title: 'Features/Modal/DashboardFilterDiffModall',
|
||||||
|
component: DashboardFilterDiffModall,
|
||||||
|
parameters: {
|
||||||
|
layout: 'centered'
|
||||||
|
},
|
||||||
|
tags: ['autodocs']
|
||||||
|
} satisfies Meta<typeof DashboardFilterDiffModall>;
|
||||||
|
|
||||||
|
export default meta;
|
||||||
|
type Story = StoryObj<typeof meta>;
|
||||||
|
|
||||||
|
// Helper to generate random SQL queries
|
||||||
|
const generateSQLCode = () => {
|
||||||
|
const tables = ['users', 'orders', 'products', 'customers', 'transactions'];
|
||||||
|
const columns = ['id', 'name', 'email', 'created_at', 'status', 'price', 'quantity'];
|
||||||
|
const conditions = [
|
||||||
|
'active = true',
|
||||||
|
"created_at > NOW() - INTERVAL '7 days'",
|
||||||
|
"status = 'completed'",
|
||||||
|
'price > 100'
|
||||||
|
];
|
||||||
|
|
||||||
|
const randomTable = tables[Math.floor(Math.random() * tables.length)];
|
||||||
|
const randomColumns = Array.from(
|
||||||
|
{ length: Math.floor(Math.random() * 3) + 1 },
|
||||||
|
() => columns[Math.floor(Math.random() * columns.length)]
|
||||||
|
).join(', ');
|
||||||
|
|
||||||
|
const whereClause =
|
||||||
|
Math.random() > 0.5 ? `WHERE ${conditions[Math.floor(Math.random() * conditions.length)]}` : '';
|
||||||
|
|
||||||
|
return `SELECT ${randomColumns} FROM ${randomTable} ${whereClause} LIMIT 100;`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Default: Story = {
|
||||||
|
args: {
|
||||||
|
open: true,
|
||||||
|
onClose: fn(),
|
||||||
|
metrics: Array.from({ length: 25 }, () => {
|
||||||
|
// Generate two different SQL queries
|
||||||
|
const originalSQL = generateSQLCode();
|
||||||
|
const modifiedSQL = generateSQLCode();
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: faker.string.uuid(),
|
||||||
|
name: faker.lorem.word(),
|
||||||
|
description: faker.lorem.sentence(),
|
||||||
|
code: modifiedSQL,
|
||||||
|
original_code: originalSQL,
|
||||||
|
version_number: faker.number.int({ min: 1, max: 100 })
|
||||||
|
};
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,166 @@
|
||||||
|
import { Button } from '@/components/ui/buttons';
|
||||||
|
import { Xmark } from '@/components/ui/icons';
|
||||||
|
import { AppPageLayout } from '@/components/ui/layouts';
|
||||||
|
import { Dialog, DialogContent } from '@/components/ui/modal/ModalBase';
|
||||||
|
import { cn } from '@/lib/classMerge';
|
||||||
|
import React, { useEffect, useMemo, useState } from 'react';
|
||||||
|
import { AppVerticalDiffCodeSplitter } from '../layouts/AppVerticalCodeSplitter/AppVerticalDiffCodeSplitter';
|
||||||
|
import { DialogTitle } from '@radix-ui/react-dialog';
|
||||||
|
import { useMemoizedFn } from '@/hooks';
|
||||||
|
import { Text, Title } from '@/components/ui/typography';
|
||||||
|
|
||||||
|
interface DashboardFilterDiffModallProps {
|
||||||
|
open: boolean;
|
||||||
|
onClose: () => void;
|
||||||
|
metrics: {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
code: string;
|
||||||
|
original_code: string;
|
||||||
|
version_number: number;
|
||||||
|
}[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const DashboardFilterDiffModall: React.FC<DashboardFilterDiffModallProps> = React.memo(
|
||||||
|
({ open, onClose, metrics }) => {
|
||||||
|
const [selectedMetricId, setSelectedMetricId] = useState<string | null>(null);
|
||||||
|
|
||||||
|
const selectedMetric = useMemo(() => {
|
||||||
|
return metrics.find((metric) => metric.id === selectedMetricId);
|
||||||
|
}, [metrics, selectedMetricId]);
|
||||||
|
|
||||||
|
const onSelectMetric = useMemoizedFn((metricId: string) => {
|
||||||
|
setSelectedMetricId(metricId);
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (metrics.length > 0) {
|
||||||
|
setSelectedMetricId(metrics[0].id);
|
||||||
|
}
|
||||||
|
}, [metrics]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog open={open} onOpenChange={onClose}>
|
||||||
|
<DialogTitle className="hidden">Dashboard Filter Diff Editor</DialogTitle>
|
||||||
|
<DialogContent
|
||||||
|
showClose={false}
|
||||||
|
className="h-[80vh] max-h-[80vh] min-h-[75vh] w-full max-w-[1000px] min-w-[1000px] overflow-hidden">
|
||||||
|
<div className="flex max-h-full w-full overflow-hidden">
|
||||||
|
<Sidebar
|
||||||
|
className="w-full max-w-[250px]"
|
||||||
|
metrics={metrics}
|
||||||
|
selectedMetricId={selectedMetricId}
|
||||||
|
onSelectMetric={onSelectMetric}
|
||||||
|
selectedMetric={selectedMetric}
|
||||||
|
/>
|
||||||
|
<Content className="flex-1" selectedMetric={selectedMetric} />
|
||||||
|
</div>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
DashboardFilterDiffModall.displayName = 'DashboardFilterDiffModall';
|
||||||
|
|
||||||
|
const Sidebar: React.FC<{
|
||||||
|
className?: string;
|
||||||
|
metrics: DashboardFilterDiffModallProps['metrics'];
|
||||||
|
selectedMetricId: string | null;
|
||||||
|
selectedMetric: DashboardFilterDiffModallProps['metrics'][number] | null | undefined;
|
||||||
|
onSelectMetric: (metricId: string) => void;
|
||||||
|
}> = ({ selectedMetric, className, metrics, selectedMetricId, onSelectMetric }) => {
|
||||||
|
const SidebarHeader = useMemo(() => {
|
||||||
|
return (
|
||||||
|
<div className="flex w-full items-center justify-between">
|
||||||
|
<Title as={'h5'}>{selectedMetric?.name}</Title>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}, [selectedMetric?.name]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AppPageLayout
|
||||||
|
headerBorderVariant="ghost"
|
||||||
|
header={SidebarHeader}
|
||||||
|
scrollable
|
||||||
|
className={cn('border-r', className)}>
|
||||||
|
<div className="mx-2 my-1.5 flex flex-col space-y-0.5">
|
||||||
|
{metrics.map((metric) => (
|
||||||
|
<SidebarItem
|
||||||
|
key={metric.id}
|
||||||
|
metric={metric}
|
||||||
|
selectedMetricId={selectedMetricId}
|
||||||
|
onSelectMetric={onSelectMetric}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</AppPageLayout>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const SidebarItem: React.FC<{
|
||||||
|
className?: string;
|
||||||
|
metric: DashboardFilterDiffModallProps['metrics'][number];
|
||||||
|
selectedMetricId: string | null;
|
||||||
|
onSelectMetric: (metricId: string) => void;
|
||||||
|
}> = ({ className, metric, selectedMetricId, onSelectMetric }) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
onClick={() => onSelectMetric(metric.id)}
|
||||||
|
className={cn(
|
||||||
|
'hover:bg-item-hover flex h-11 cursor-pointer flex-col space-y-0.5 rounded px-2 py-1.5',
|
||||||
|
selectedMetricId === metric.id && 'bg-item-select hover:bg-item-select',
|
||||||
|
className
|
||||||
|
)}>
|
||||||
|
<Title as={'h5'}>{metric.name}</Title>
|
||||||
|
<Text size={'sm'} truncate variant={'secondary'}>
|
||||||
|
{metric.description}
|
||||||
|
</Text>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const Content: React.FC<{
|
||||||
|
className?: string;
|
||||||
|
selectedMetric: DashboardFilterDiffModallProps['metrics'][number] | null | undefined;
|
||||||
|
}> = ({ className, selectedMetric }) => {
|
||||||
|
return (
|
||||||
|
<AppPageLayout
|
||||||
|
headerClassName="px-3!"
|
||||||
|
header={useMemo(
|
||||||
|
() => (
|
||||||
|
<div className="flex w-full items-center justify-end">
|
||||||
|
<Button variant="ghost" prefix={<Xmark />} />
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
[]
|
||||||
|
)}
|
||||||
|
className={cn('overflow-hidden', className)}>
|
||||||
|
<div className="bg-item-hover h-full w-full p-5">
|
||||||
|
{selectedMetric && (
|
||||||
|
<AppVerticalDiffCodeSplitter
|
||||||
|
originalValue={selectedMetric.original_code}
|
||||||
|
value={selectedMetric.code}
|
||||||
|
setValue={() => {}}
|
||||||
|
language="sql"
|
||||||
|
runSQLError={undefined}
|
||||||
|
onRunQuery={() => Promise.resolve()}
|
||||||
|
data={[]}
|
||||||
|
defaultLayout={['300px', 'auto']}
|
||||||
|
fetchingData={false}
|
||||||
|
autoSaveId="dashboard-filter-diff-modal"
|
||||||
|
fileName={selectedMetric.name}
|
||||||
|
versionNumber={selectedMetric.version_number}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{!selectedMetric && (
|
||||||
|
<div className="bg-background flex h-full w-full items-center justify-center rounded border p-5">
|
||||||
|
<Text variant={'secondary'}>Select a metric to view the diff</Text>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</AppPageLayout>
|
||||||
|
);
|
||||||
|
};
|
|
@ -14,7 +14,7 @@ export interface AppDiffCodeEditorProps {
|
||||||
isDarkMode?: boolean;
|
isDarkMode?: boolean;
|
||||||
onMount?: (editor: editor.IStandaloneDiffEditor, monaco: typeof import('monaco-editor')) => void;
|
onMount?: (editor: editor.IStandaloneDiffEditor, monaco: typeof import('monaco-editor')) => void;
|
||||||
original?: string;
|
original?: string;
|
||||||
modified?: string;
|
modified: string;
|
||||||
onChange?: (value: string) => void;
|
onChange?: (value: string) => void;
|
||||||
style?: React.CSSProperties;
|
style?: React.CSSProperties;
|
||||||
language?: string;
|
language?: string;
|
||||||
|
@ -23,6 +23,7 @@ export interface AppDiffCodeEditorProps {
|
||||||
monacoEditorOptions?: editor.IStandaloneDiffEditorConstructionOptions;
|
monacoEditorOptions?: editor.IStandaloneDiffEditorConstructionOptions;
|
||||||
variant?: 'bordered' | null;
|
variant?: 'bordered' | null;
|
||||||
viewMode?: 'side-by-side' | 'inline';
|
viewMode?: 'side-by-side' | 'inline';
|
||||||
|
disabled?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AppDiffCodeEditorHandle {
|
export interface AppDiffCodeEditorHandle {
|
||||||
|
@ -34,7 +35,7 @@ export const AppDiffCodeEditor = forwardRef<AppDiffCodeEditorHandle, AppDiffCode
|
||||||
{
|
{
|
||||||
style,
|
style,
|
||||||
monacoEditorOptions,
|
monacoEditorOptions,
|
||||||
language = 'typescript',
|
language = 'sql',
|
||||||
className,
|
className,
|
||||||
readOnly,
|
readOnly,
|
||||||
onChange,
|
onChange,
|
||||||
|
@ -45,7 +46,8 @@ export const AppDiffCodeEditor = forwardRef<AppDiffCodeEditorHandle, AppDiffCode
|
||||||
modified = '',
|
modified = '',
|
||||||
readOnlyMessage = 'Editing code is not allowed',
|
readOnlyMessage = 'Editing code is not allowed',
|
||||||
variant,
|
variant,
|
||||||
viewMode = 'side-by-side'
|
viewMode = 'side-by-side',
|
||||||
|
disabled = false
|
||||||
},
|
},
|
||||||
ref
|
ref
|
||||||
) => {
|
) => {
|
||||||
|
@ -57,7 +59,7 @@ export const AppDiffCodeEditor = forwardRef<AppDiffCodeEditorHandle, AppDiffCode
|
||||||
return {
|
return {
|
||||||
originalEditable: false,
|
originalEditable: false,
|
||||||
automaticLayout: true,
|
automaticLayout: true,
|
||||||
readOnly,
|
readOnly: readOnly || disabled,
|
||||||
renderSideBySide: viewMode === 'side-by-side',
|
renderSideBySide: viewMode === 'side-by-side',
|
||||||
folding: false,
|
folding: false,
|
||||||
lineDecorationsWidth: 15,
|
lineDecorationsWidth: 15,
|
||||||
|
@ -68,7 +70,7 @@ export const AppDiffCodeEditor = forwardRef<AppDiffCodeEditorHandle, AppDiffCode
|
||||||
minimap: {
|
minimap: {
|
||||||
enabled: false
|
enabled: false
|
||||||
},
|
},
|
||||||
renderSideBySideInlineBreakpoint: 600,
|
renderSideBySideInlineBreakpoint: 400,
|
||||||
compactMode: true,
|
compactMode: true,
|
||||||
renderIndicators: false,
|
renderIndicators: false,
|
||||||
onlyShowAccessibleDiffViewer: false,
|
onlyShowAccessibleDiffViewer: false,
|
||||||
|
@ -81,7 +83,7 @@ export const AppDiffCodeEditor = forwardRef<AppDiffCodeEditorHandle, AppDiffCode
|
||||||
},
|
},
|
||||||
...monacoEditorOptions
|
...monacoEditorOptions
|
||||||
} satisfies editor.IStandaloneDiffEditorConstructionOptions;
|
} satisfies editor.IStandaloneDiffEditorConstructionOptions;
|
||||||
}, [readOnlyMessage, monacoEditorOptions, viewMode]);
|
}, [readOnlyMessage, monacoEditorOptions, viewMode, readOnly, disabled]);
|
||||||
|
|
||||||
const onMountDiffEditor = useMemoizedFn(
|
const onMountDiffEditor = useMemoizedFn(
|
||||||
async (editor: editor.IStandaloneDiffEditor, monaco: typeof import('monaco-editor')) => {
|
async (editor: editor.IStandaloneDiffEditor, monaco: typeof import('monaco-editor')) => {
|
||||||
|
@ -106,7 +108,7 @@ export const AppDiffCodeEditor = forwardRef<AppDiffCodeEditorHandle, AppDiffCode
|
||||||
|
|
||||||
// Get the modified editor and add change listener
|
// Get the modified editor and add change listener
|
||||||
const modifiedEditor = editor.getModifiedEditor();
|
const modifiedEditor = editor.getModifiedEditor();
|
||||||
if (!readOnly) {
|
if (!readOnly && !disabled) {
|
||||||
modifiedEditor.onDidChangeModelContent(() => {
|
modifiedEditor.onDidChangeModelContent(() => {
|
||||||
onChange?.(modifiedEditor.getValue() || '');
|
onChange?.(modifiedEditor.getValue() || '');
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue