mirror of https://github.com/buster-so/buster.git
update timeouts for switching layouts
This commit is contained in:
parent
f417ada44a
commit
e2f5e64475
|
@ -20,7 +20,7 @@ import {
|
||||||
DropdownMenuLink
|
DropdownMenuLink
|
||||||
} from './DropdownBase';
|
} from './DropdownBase';
|
||||||
import { CircleSpinnerLoader } from '../loaders/CircleSpinnerLoader';
|
import { CircleSpinnerLoader } from '../loaders/CircleSpinnerLoader';
|
||||||
import { useMemoizedFn, useMount } from '@/hooks';
|
import { useMemoizedFn } from '@/hooks';
|
||||||
import { cn } from '@/lib/classMerge';
|
import { cn } from '@/lib/classMerge';
|
||||||
import { Input } from '../inputs/Input';
|
import { Input } from '../inputs/Input';
|
||||||
import { useDebounceSearch } from '@/hooks';
|
import { useDebounceSearch } from '@/hooks';
|
||||||
|
@ -159,6 +159,8 @@ export const DropdownContent = <T,>({
|
||||||
debounceTime: 50
|
debounceTime: 50
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log(filteredItems, searchText);
|
||||||
|
|
||||||
const hasShownItem = useMemo(() => {
|
const hasShownItem = useMemo(() => {
|
||||||
return filteredItems.length > 0 && filteredItems.some((item) => (item as DropdownItem).value);
|
return filteredItems.length > 0 && filteredItems.some((item) => (item as DropdownItem).value);
|
||||||
}, [filteredItems]);
|
}, [filteredItems]);
|
||||||
|
@ -264,13 +266,13 @@ export const DropdownContent = <T,>({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DropdownItemSelector
|
<DropdownItemSelector
|
||||||
item={item as DropdownItems<T>[number]}
|
key={dropdownItemKey(item, hotkeyIndex)}
|
||||||
|
item={item}
|
||||||
index={hotkeyIndex}
|
index={hotkeyIndex}
|
||||||
selectType={selectType}
|
selectType={selectType}
|
||||||
onSelect={onSelect}
|
onSelect={onSelect}
|
||||||
onSelectItem={onSelectItem}
|
onSelectItem={onSelectItem}
|
||||||
closeOnSelect={closeOnSelect}
|
closeOnSelect={closeOnSelect}
|
||||||
key={dropdownItemKey(item, hotkeyIndex)}
|
|
||||||
showIndex={showIndex}
|
showIndex={showIndex}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -419,7 +421,7 @@ const DropdownItem = <T,>({
|
||||||
}
|
}
|
||||||
|
|
||||||
//I do not think this selected check is stable... look into refactoring
|
//I do not think this selected check is stable... look into refactoring
|
||||||
if (selectType === 'single' || selected) {
|
if (selectType === 'single') {
|
||||||
return (
|
return (
|
||||||
<DropdownMenuCheckboxItemSingle
|
<DropdownMenuCheckboxItemSingle
|
||||||
checked={selected}
|
checked={selected}
|
||||||
|
|
|
@ -2,9 +2,10 @@
|
||||||
|
|
||||||
import type { Meta, StoryObj } from '@storybook/react';
|
import type { Meta, StoryObj } from '@storybook/react';
|
||||||
import { SelectMultiple } from './SelectMultiple';
|
import { SelectMultiple } from './SelectMultiple';
|
||||||
import { useState } from 'react';
|
import { useMemo, useState } from 'react';
|
||||||
import { type SelectItem } from './Select';
|
import { type SelectItem } from './Select';
|
||||||
import { fn } from '@storybook/test';
|
import { fn } from '@storybook/test';
|
||||||
|
import { faker } from '@faker-js/faker';
|
||||||
|
|
||||||
const meta = {
|
const meta = {
|
||||||
title: 'UI/Select/SelectMultiple',
|
title: 'UI/Select/SelectMultiple',
|
||||||
|
@ -113,19 +114,40 @@ export const CustomWidth: Story = {
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const WithHundredItemsWithHooks = () => {
|
||||||
|
const [value, setValue] = useState<string[]>([]);
|
||||||
|
|
||||||
|
const items = useMemo(
|
||||||
|
() =>
|
||||||
|
Array.from({ length: 100 }, (_, index) => ({
|
||||||
|
value: index.toString(),
|
||||||
|
label: faker.company.name()
|
||||||
|
})),
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleSelect = (selectedValues: string[]) => {
|
||||||
|
setValue(selectedValues);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="w-[300px]">
|
||||||
|
<SelectMultiple
|
||||||
|
items={items}
|
||||||
|
onChange={handleSelect}
|
||||||
|
placeholder="Select multiple options..."
|
||||||
|
value={value}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export const WithHundredItems: Story = {
|
export const WithHundredItems: Story = {
|
||||||
args: {
|
args: {
|
||||||
items: Array.from({ length: 100 }, (_, index) => ({
|
items: [],
|
||||||
value: index.toString(),
|
|
||||||
label: `Option ${index + 1}`
|
|
||||||
})),
|
|
||||||
value: [],
|
value: [],
|
||||||
onChange: fn(),
|
onChange: fn(),
|
||||||
placeholder: 'Select multiple options...'
|
placeholder: 'Select multiple options...'
|
||||||
},
|
},
|
||||||
render: (args) => (
|
render: () => <WithHundredItemsWithHooks />
|
||||||
<div className="w-[300px]">
|
|
||||||
<SelectMultiple {...args} />
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -16,6 +16,7 @@ interface SelectMultipleProps extends VariantProps<typeof selectVariants> {
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
value: string[];
|
value: string[];
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
|
useSearch?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SelectMultiple: React.FC<SelectMultipleProps> = React.memo(
|
export const SelectMultiple: React.FC<SelectMultipleProps> = React.memo(
|
||||||
|
@ -27,7 +28,8 @@ export const SelectMultiple: React.FC<SelectMultipleProps> = React.memo(
|
||||||
size = 'default',
|
size = 'default',
|
||||||
variant = 'default',
|
variant = 'default',
|
||||||
value,
|
value,
|
||||||
disabled
|
disabled,
|
||||||
|
useSearch = true
|
||||||
}) => {
|
}) => {
|
||||||
const selectedRecord = useMemo(() => {
|
const selectedRecord = useMemo(() => {
|
||||||
return itemsProp.reduce<Record<string, boolean>>((acc, item) => {
|
return itemsProp.reduce<Record<string, boolean>>((acc, item) => {
|
||||||
|
@ -72,6 +74,7 @@ export const SelectMultiple: React.FC<SelectMultipleProps> = React.memo(
|
||||||
<Dropdown
|
<Dropdown
|
||||||
items={items}
|
items={items}
|
||||||
onSelect={handleSelect}
|
onSelect={handleSelect}
|
||||||
|
menuHeader={useSearch ? 'Search...' : undefined}
|
||||||
selectType="multiple"
|
selectType="multiple"
|
||||||
align="start"
|
align="start"
|
||||||
modal={false}
|
modal={false}
|
||||||
|
|
|
@ -1,8 +1,13 @@
|
||||||
import type { FileType, AllFileTypes } from '@/api/asset_interfaces';
|
import type { FileType, AllFileTypes } from '@/api/asset_interfaces';
|
||||||
import { BusterRoutes, createBusterRoute } from '@/routes';
|
import { BusterRoutes, createBusterRoute } from '@/routes';
|
||||||
import type { FileView } from './useLayoutConfig';
|
import type {
|
||||||
|
DashboardFileViewSecondary,
|
||||||
|
FileView,
|
||||||
|
FileViewSecondary,
|
||||||
|
MetricFileViewSecondary
|
||||||
|
} from './useLayoutConfig';
|
||||||
|
|
||||||
const chatRouteRecord: Record<AllFileTypes, (chatId: string, assetId: string) => string> = {
|
const chatRouteRecord: Record<AllFileTypes, (chatId: string, assetId: string) => string | null> = {
|
||||||
collection: (chatId, assetId) =>
|
collection: (chatId, assetId) =>
|
||||||
createBusterRoute({
|
createBusterRoute({
|
||||||
route: BusterRoutes.APP_CHAT_ID_COLLECTION_ID,
|
route: BusterRoutes.APP_CHAT_ID_COLLECTION_ID,
|
||||||
|
@ -48,18 +53,57 @@ const chatRouteRecord: Record<AllFileTypes, (chatId: string, assetId: string) =>
|
||||||
empty: () => ''
|
empty: () => ''
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const assetRouteRecord: Record<AllFileTypes, (assetId: string) => string | null> = {
|
||||||
|
collection: (assetId) =>
|
||||||
|
createBusterRoute({
|
||||||
|
route: BusterRoutes.APP_COLLECTIONS_ID,
|
||||||
|
collectionId: assetId
|
||||||
|
}),
|
||||||
|
dataset: (assetId) =>
|
||||||
|
createBusterRoute({
|
||||||
|
route: BusterRoutes.APP_DATASETS_ID,
|
||||||
|
datasetId: assetId
|
||||||
|
}),
|
||||||
|
metric: (assetId) =>
|
||||||
|
createBusterRoute({
|
||||||
|
route: BusterRoutes.APP_METRIC_ID,
|
||||||
|
metricId: assetId
|
||||||
|
}),
|
||||||
|
dashboard: (assetId) =>
|
||||||
|
createBusterRoute({
|
||||||
|
route: BusterRoutes.APP_DASHBOARD_ID,
|
||||||
|
dashboardId: assetId
|
||||||
|
}),
|
||||||
|
term: (assetId) =>
|
||||||
|
createBusterRoute({
|
||||||
|
route: BusterRoutes.APP_TERMS_ID,
|
||||||
|
termId: assetId
|
||||||
|
}),
|
||||||
|
value: (assetId) =>
|
||||||
|
createBusterRoute({
|
||||||
|
route: BusterRoutes.APP_VALUE_ID,
|
||||||
|
valueId: assetId
|
||||||
|
}),
|
||||||
|
reasoning: () => null,
|
||||||
|
empty: () => null
|
||||||
|
};
|
||||||
|
|
||||||
export const createChatAssetRoute = ({
|
export const createChatAssetRoute = ({
|
||||||
chatId,
|
chatId,
|
||||||
assetId,
|
assetId,
|
||||||
type
|
type
|
||||||
}: {
|
}: {
|
||||||
chatId: string;
|
chatId: string | undefined;
|
||||||
assetId: string;
|
assetId: string;
|
||||||
type: FileType;
|
type: FileType;
|
||||||
}) => {
|
}) => {
|
||||||
const routeBuilder = chatRouteRecord[type];
|
const routeBuilder = chatRouteRecord[type];
|
||||||
if (!routeBuilder) return null;
|
if (!routeBuilder) return null;
|
||||||
return routeBuilder(chatId, assetId);
|
if (chatId) return routeBuilder(chatId, assetId);
|
||||||
|
|
||||||
|
const assetRouteBuilder = assetRouteRecord[type];
|
||||||
|
if (!assetRouteBuilder) return null;
|
||||||
|
return assetRouteBuilder(assetId);
|
||||||
};
|
};
|
||||||
|
|
||||||
const routeToFileView: Partial<Record<BusterRoutes, FileView>> = {
|
const routeToFileView: Partial<Record<BusterRoutes, FileView>> = {
|
||||||
|
@ -86,3 +130,88 @@ export const DEFAULT_FILE_VIEW: Record<FileType, FileView> = {
|
||||||
// term: 'results',
|
// term: 'results',
|
||||||
// dataset: 'results',
|
// dataset: 'results',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const assetParamsToRoute = ({
|
||||||
|
chatId,
|
||||||
|
assetId,
|
||||||
|
type,
|
||||||
|
secondaryView: secondaryViewProp
|
||||||
|
}: {
|
||||||
|
chatId: string | undefined;
|
||||||
|
assetId: string;
|
||||||
|
type: FileType;
|
||||||
|
secondaryView?: FileViewSecondary;
|
||||||
|
}) => {
|
||||||
|
if (type === 'metric') {
|
||||||
|
const secondaryView = secondaryViewProp as MetricFileViewSecondary | undefined;
|
||||||
|
if (chatId) {
|
||||||
|
switch (secondaryView) {
|
||||||
|
case 'chart-edit':
|
||||||
|
return createBusterRoute({
|
||||||
|
route: BusterRoutes.APP_CHAT_ID_METRIC_ID_CHART,
|
||||||
|
chatId,
|
||||||
|
metricId: assetId
|
||||||
|
});
|
||||||
|
case 'sql-edit':
|
||||||
|
return createBusterRoute({
|
||||||
|
route: BusterRoutes.APP_CHAT_ID_METRIC_ID_RESULTS,
|
||||||
|
chatId,
|
||||||
|
metricId: assetId
|
||||||
|
});
|
||||||
|
case 'version-history':
|
||||||
|
return createBusterRoute({
|
||||||
|
route: BusterRoutes.APP_CHAT_ID_METRIC_ID_CHART,
|
||||||
|
chatId,
|
||||||
|
metricId: assetId
|
||||||
|
});
|
||||||
|
default:
|
||||||
|
const test: never | undefined = secondaryView;
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (secondaryView) {
|
||||||
|
case 'chart-edit':
|
||||||
|
return createBusterRoute({
|
||||||
|
route: BusterRoutes.APP_METRIC_ID_CHART,
|
||||||
|
metricId: assetId
|
||||||
|
});
|
||||||
|
case 'sql-edit':
|
||||||
|
return createBusterRoute({
|
||||||
|
route: BusterRoutes.APP_METRIC_ID_RESULTS,
|
||||||
|
metricId: assetId
|
||||||
|
});
|
||||||
|
case 'version-history':
|
||||||
|
return createBusterRoute({
|
||||||
|
route: BusterRoutes.APP_METRIC_ID_CHART,
|
||||||
|
metricId: assetId
|
||||||
|
});
|
||||||
|
default:
|
||||||
|
const test: never | undefined = secondaryView;
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === 'dashboard') {
|
||||||
|
const secondaryView = secondaryViewProp as DashboardFileViewSecondary | undefined;
|
||||||
|
if (chatId) {
|
||||||
|
switch (secondaryView) {
|
||||||
|
case 'version-history':
|
||||||
|
return createBusterRoute({
|
||||||
|
route: BusterRoutes.APP_CHAT_ID_DASHBOARD_ID,
|
||||||
|
chatId,
|
||||||
|
dashboardId: assetId
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return createBusterRoute({
|
||||||
|
route: BusterRoutes.APP_DASHBOARD_ID,
|
||||||
|
dashboardId: assetId
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
console.warn('Asset params to route has not been implemented for this file type', type);
|
||||||
|
|
||||||
|
return createChatAssetRoute({ chatId, assetId, type }) || '';
|
||||||
|
};
|
||||||
|
|
|
@ -88,7 +88,7 @@ export const useLayoutConfig = ({
|
||||||
|
|
||||||
if (secondaryView) {
|
if (secondaryView) {
|
||||||
animateOpenSplitter('right');
|
animateOpenSplitter('right');
|
||||||
await timeout(250); //wait for splitter to close before opening secondary view
|
await timeout(chatId ? 250 : 0); //wait for splitter to close before opening secondary view
|
||||||
} else if (chatId) {
|
} else if (chatId) {
|
||||||
animateOpenSplitter('both');
|
animateOpenSplitter('both');
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,12 +6,13 @@ import { useTransition } from 'react';
|
||||||
|
|
||||||
export const useCloseVersionHistory = () => {
|
export const useCloseVersionHistory = () => {
|
||||||
const [isPending, startTransition] = useTransition();
|
const [isPending, startTransition] = useTransition();
|
||||||
|
const chatId = useChatLayoutContextSelector((x) => x.chatId);
|
||||||
const onChangeQueryParams = useAppLayoutContextSelector((x) => x.onChangeQueryParams);
|
const onChangeQueryParams = useAppLayoutContextSelector((x) => x.onChangeQueryParams);
|
||||||
const closeSecondaryView = useChatLayoutContextSelector((x) => x.closeSecondaryView);
|
const closeSecondaryView = useChatLayoutContextSelector((x) => x.closeSecondaryView);
|
||||||
|
|
||||||
const removeVersionHistoryQueryParams = useMemoizedFn(async () => {
|
const removeVersionHistoryQueryParams = useMemoizedFn(async () => {
|
||||||
closeSecondaryView();
|
closeSecondaryView();
|
||||||
await timeout(250);
|
await timeout(chatId ? 250 : 0);
|
||||||
startTransition(() => {
|
startTransition(() => {
|
||||||
onChangeQueryParams({ metric_version_number: null, dashboard_version_number: null });
|
onChangeQueryParams({ metric_version_number: null, dashboard_version_number: null });
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import React from 'react';
|
import React, { useMemo } from 'react';
|
||||||
import { FileContainerButtonsProps } from '../interfaces';
|
import { FileContainerButtonsProps } from '../interfaces';
|
||||||
import { MetricFileViewSecondary, useChatLayoutContextSelector } from '../../../ChatLayoutContext';
|
import { MetricFileViewSecondary, useChatLayoutContextSelector } from '../../../ChatLayoutContext';
|
||||||
import { useMemoizedFn } from '@/hooks';
|
import { useMemoizedFn } from '@/hooks';
|
||||||
|
@ -14,6 +14,12 @@ import { SquareChartPen, SquareCode } from '@/components/ui/icons';
|
||||||
import { useGetMetric } from '@/api/buster_rest/metrics';
|
import { useGetMetric } from '@/api/buster_rest/metrics';
|
||||||
import { ThreeDotMenuButton } from './MetricThreeDotMenu';
|
import { ThreeDotMenuButton } from './MetricThreeDotMenu';
|
||||||
import { canEdit, getIsEffectiveOwner } from '@/lib/share';
|
import { canEdit, getIsEffectiveOwner } from '@/lib/share';
|
||||||
|
import Link from 'next/link';
|
||||||
|
import { BusterRoutes, createBusterRoute } from '@/routes';
|
||||||
|
import {
|
||||||
|
assetParamsToRoute,
|
||||||
|
createChatAssetRoute
|
||||||
|
} from '@/layouts/ChatLayout/ChatLayoutContext/helpers';
|
||||||
|
|
||||||
export const MetricContainerHeaderButtons: React.FC<FileContainerButtonsProps> = React.memo(() => {
|
export const MetricContainerHeaderButtons: React.FC<FileContainerButtonsProps> = React.memo(() => {
|
||||||
const selectedLayout = useChatLayoutContextSelector((x) => x.selectedLayout);
|
const selectedLayout = useChatLayoutContextSelector((x) => x.selectedLayout);
|
||||||
|
@ -32,8 +38,8 @@ export const MetricContainerHeaderButtons: React.FC<FileContainerButtonsProps> =
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FileButtonContainer>
|
<FileButtonContainer>
|
||||||
{isEditor && <EditChartButton />}
|
{isEditor && <EditChartButton metricId={metricId} />}
|
||||||
{isEffectiveOwner && <EditSQLButton />}
|
{isEffectiveOwner && <EditSQLButton metricId={metricId} />}
|
||||||
<SaveToCollectionButton metricId={metricId} />
|
<SaveToCollectionButton metricId={metricId} />
|
||||||
<SaveToDashboardButton metricId={metricId} />
|
<SaveToDashboardButton metricId={metricId} />
|
||||||
{isEffectiveOwner && <ShareMetricButton metricId={metricId} />}
|
{isEffectiveOwner && <ShareMetricButton metricId={metricId} />}
|
||||||
|
@ -47,50 +53,74 @@ export const MetricContainerHeaderButtons: React.FC<FileContainerButtonsProps> =
|
||||||
|
|
||||||
MetricContainerHeaderButtons.displayName = 'MetricContainerHeaderButtons';
|
MetricContainerHeaderButtons.displayName = 'MetricContainerHeaderButtons';
|
||||||
|
|
||||||
const EditChartButton = React.memo(() => {
|
const EditChartButton = React.memo(({ metricId }: { metricId: string }) => {
|
||||||
const selectedFileViewSecondary = useChatLayoutContextSelector(
|
const selectedFileViewSecondary = useChatLayoutContextSelector(
|
||||||
(x) => x.selectedFileViewSecondary
|
(x) => x.selectedFileViewSecondary
|
||||||
);
|
);
|
||||||
|
const chatId = useChatIndividualContextSelector((x) => x.chatId);
|
||||||
const onSetFileView = useChatLayoutContextSelector((x) => x.onSetFileView);
|
const onSetFileView = useChatLayoutContextSelector((x) => x.onSetFileView);
|
||||||
const editableSecondaryView: MetricFileViewSecondary = 'chart-edit';
|
const editableSecondaryView: MetricFileViewSecondary = 'chart-edit';
|
||||||
const isSelectedView = selectedFileViewSecondary === editableSecondaryView;
|
const isSelectedView = selectedFileViewSecondary === editableSecondaryView;
|
||||||
|
|
||||||
|
const href = useMemo(() => {
|
||||||
|
return assetParamsToRoute({
|
||||||
|
chatId,
|
||||||
|
assetId: metricId,
|
||||||
|
type: 'metric',
|
||||||
|
secondaryView: 'chart-edit'
|
||||||
|
});
|
||||||
|
}, [chatId, metricId]);
|
||||||
|
|
||||||
const onClickButton = useMemoizedFn(() => {
|
const onClickButton = useMemoizedFn(() => {
|
||||||
const secondaryView = isSelectedView ? null : editableSecondaryView;
|
const secondaryView = isSelectedView ? null : editableSecondaryView;
|
||||||
onSetFileView({ secondaryView, fileView: 'chart' });
|
onSetFileView({ secondaryView, fileView: 'chart' });
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SelectableButton
|
<Link href={href}>
|
||||||
tooltipText="Edit chart"
|
<SelectableButton
|
||||||
icon={<SquareChartPen />}
|
tooltipText="Edit chart"
|
||||||
onClick={onClickButton}
|
icon={<SquareChartPen />}
|
||||||
selected={isSelectedView}
|
onClick={onClickButton}
|
||||||
/>
|
selected={isSelectedView}
|
||||||
|
/>
|
||||||
|
</Link>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
EditChartButton.displayName = 'EditChartButton';
|
EditChartButton.displayName = 'EditChartButton';
|
||||||
|
|
||||||
const EditSQLButton = React.memo(() => {
|
const EditSQLButton = React.memo(({ metricId }: { metricId: string }) => {
|
||||||
const selectedFileViewSecondary = useChatLayoutContextSelector(
|
const selectedFileViewSecondary = useChatLayoutContextSelector(
|
||||||
(x) => x.selectedFileViewSecondary
|
(x) => x.selectedFileViewSecondary
|
||||||
);
|
);
|
||||||
const onSetFileView = useChatLayoutContextSelector((x) => x.onSetFileView);
|
const onSetFileView = useChatLayoutContextSelector((x) => x.onSetFileView);
|
||||||
|
const chatId = useChatIndividualContextSelector((x) => x.chatId);
|
||||||
const editableSecondaryView: MetricFileViewSecondary = 'sql-edit';
|
const editableSecondaryView: MetricFileViewSecondary = 'sql-edit';
|
||||||
const isSelectedView = selectedFileViewSecondary === editableSecondaryView;
|
const isSelectedView = selectedFileViewSecondary === editableSecondaryView;
|
||||||
|
|
||||||
|
const href = useMemo(() => {
|
||||||
|
return assetParamsToRoute({
|
||||||
|
chatId,
|
||||||
|
assetId: metricId,
|
||||||
|
type: 'metric',
|
||||||
|
secondaryView: 'sql-edit'
|
||||||
|
});
|
||||||
|
}, [chatId, metricId]);
|
||||||
|
|
||||||
const onClickButton = useMemoizedFn(() => {
|
const onClickButton = useMemoizedFn(() => {
|
||||||
const secondaryView = isSelectedView ? null : editableSecondaryView;
|
const secondaryView = isSelectedView ? null : editableSecondaryView;
|
||||||
onSetFileView({ secondaryView, fileView: 'results' });
|
onSetFileView({ secondaryView, fileView: 'results' });
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SelectableButton
|
<Link href={href}>
|
||||||
tooltipText="SQL editor"
|
<SelectableButton
|
||||||
icon={<SquareCode />}
|
tooltipText="SQL editor"
|
||||||
onClick={onClickButton}
|
icon={<SquareCode />}
|
||||||
selected={isSelectedView}
|
onClick={onClickButton}
|
||||||
/>
|
selected={isSelectedView}
|
||||||
|
/>
|
||||||
|
</Link>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
EditSQLButton.displayName = 'EditSQLButton';
|
EditSQLButton.displayName = 'EditSQLButton';
|
||||||
|
|
Loading…
Reference in New Issue