diff --git a/web/src/components/features/versionHistory/VersionHistoryPanel.tsx b/web/src/components/features/versionHistory/VersionHistoryPanel.tsx index 0e9f4f5e4..d424626c0 100644 --- a/web/src/components/features/versionHistory/VersionHistoryPanel.tsx +++ b/web/src/components/features/versionHistory/VersionHistoryPanel.tsx @@ -13,7 +13,6 @@ import { AppTooltip } from '@/components/ui/tooltip'; import Link from 'next/link'; import { useGetFileLink } from '@/context/Assets/useGetFileLink'; import { useChatLayoutContextSelector } from '@/layouts/ChatLayout'; -import { useRouter } from 'next/navigation'; import { useCallback } from 'react'; export const VersionHistoryPanel = React.memo( diff --git a/web/src/components/ui/dropdown/Dropdown.tsx b/web/src/components/ui/dropdown/Dropdown.tsx index a66a58fb2..b824190f0 100644 --- a/web/src/components/ui/dropdown/Dropdown.tsx +++ b/web/src/components/ui/dropdown/Dropdown.tsx @@ -242,7 +242,7 @@ export const DropdownContent = ({ }}> {hasShownItem ? ( <> - {selectedItems.map((item) => { + {selectedItems.map((item, index) => { // Only increment index for selectable items if ((item as DropdownItem).value && !(item as DropdownItem).items) { hotkeyIndex++; @@ -250,7 +250,7 @@ export const DropdownContent = ({ return ( ({ {selectedItems.length > 0 && } - {dropdownItems.map((item) => { + {dropdownItems.map((item, index) => { // Only increment index for selectable items if ((item as DropdownItem).value && !(item as DropdownItem).items) { hotkeyIndex++; @@ -272,7 +272,7 @@ export const DropdownContent = ({ return ( x.secondaryView); const dashboardVersionNumber = useChatLayoutContextSelector((x) => x.dashboardVersionNumber); const metricVersionNumber = useChatLayoutContextSelector((x) => x.metricVersionNumber); - const isVersionHistoryMode = useChatLayoutContextSelector((x) => x.isVersionHistoryMode); const isCompletedStream = useGetChatMessage(lastMessageId, (x) => x?.isCompletedStream); const getInitialChatFileHref = useGetInitialChatFile(); diff --git a/web/src/layouts/ChatLayout/ChatLayoutContext/useLayoutConfig/useLayoutConfig.ts b/web/src/layouts/ChatLayout/ChatLayoutContext/useLayoutConfig/useLayoutConfig.ts index 6b24d1456..3e115482e 100644 --- a/web/src/layouts/ChatLayout/ChatLayoutContext/useLayoutConfig/useLayoutConfig.ts +++ b/web/src/layouts/ChatLayout/ChatLayoutContext/useLayoutConfig/useLayoutConfig.ts @@ -92,7 +92,9 @@ export const useLayoutConfig = ({ return; } - if (secondaryView) { + if (!chatId) { + animateOpenSplitter('right'); + } else if (secondaryView) { animateOpenSplitter('right'); //if the chat is open, we need to wait for the splitter to close before opening the secondary view @@ -192,7 +194,7 @@ export const useLayoutConfig = ({ fileView, secondaryView: secondaryViewFromSelected }); - }, [metricId, secondaryView, dashboardId, currentRoute]); + }, [metricId, secondaryView, chatId, dashboardId, currentRoute]); return { selectedLayout, diff --git a/web/src/layouts/ChatLayout/FileContainer/FileContainerHeader/MetricContainerHeaderButtons/MetricContainerHeaderButtons.tsx b/web/src/layouts/ChatLayout/FileContainer/FileContainerHeader/MetricContainerHeaderButtons/MetricContainerHeaderButtons.tsx index 381f45635..15c9e7b23 100644 --- a/web/src/layouts/ChatLayout/FileContainer/FileContainerHeader/MetricContainerHeaderButtons/MetricContainerHeaderButtons.tsx +++ b/web/src/layouts/ChatLayout/FileContainer/FileContainerHeader/MetricContainerHeaderButtons/MetricContainerHeaderButtons.tsx @@ -17,11 +17,15 @@ import { canEdit, getIsEffectiveOwner } from '@/lib/share'; import Link from 'next/link'; import { assetParamsToRoute } from '@/lib/assets'; import { useAppLayoutContextSelector } from '@/context/BusterAppLayout'; +import { useIsMetricReadOnly } from '@/context/Metrics/useIsMetricReadOnly'; export const MetricContainerHeaderButtons: React.FC = React.memo(() => { const selectedLayout = useChatLayoutContextSelector((x) => x.selectedLayout); - const selectedFileId = useChatIndividualContextSelector((x) => x.selectedFileId)!; - const metricId = selectedFileId; + const metricId = useChatIndividualContextSelector((x) => x.selectedFileId)!; + const metricVersionNumber = useChatLayoutContextSelector((x) => x.metricVersionNumber); + const { isViewingOldVersion } = useIsMetricReadOnly({ + metricId: metricId || '' + }); const { error: metricError, data: permission } = useGetMetric( { id: metricId }, { select: (x) => x.permission } @@ -35,12 +39,16 @@ export const MetricContainerHeaderButtons: React.FC = return ( - {isEditor && } - {isEffectiveOwner && } + {isEditor && !isViewingOldVersion && } + {isEffectiveOwner && !isViewingOldVersion && } - {isEffectiveOwner && } - + {isEffectiveOwner && !isViewingOldVersion && } + @@ -55,8 +63,8 @@ const EditChartButton = React.memo(({ metricId }: { metricId: string }) => { (x) => x.selectedFileViewSecondary ); const onChangePage = useAppLayoutContextSelector((x) => x.onChangePage); - const onChangeQueryParams = useAppLayoutContextSelector((x) => x.onChangeQueryParams); const chatId = useChatIndividualContextSelector((x) => x.chatId); + const metricVersionNumber = useChatLayoutContextSelector((x) => x.metricVersionNumber); const editableSecondaryView: MetricFileViewSecondary = 'chart-edit'; const isSelectedView = selectedFileViewSecondary === editableSecondaryView; @@ -66,7 +74,8 @@ const EditChartButton = React.memo(({ metricId }: { metricId: string }) => { chatId, assetId: metricId, type: 'metric', - secondaryView: null + secondaryView: null, + versionNumber: metricVersionNumber }); } @@ -74,9 +83,10 @@ const EditChartButton = React.memo(({ metricId }: { metricId: string }) => { chatId, assetId: metricId, type: 'metric', - secondaryView: 'chart-edit' + secondaryView: 'chart-edit', + versionNumber: metricVersionNumber }); - }, [chatId, metricId, isSelectedView]); + }, [chatId, metricId, isSelectedView, metricVersionNumber]); const onClickButton = useMemoizedFn(() => { onChangePage(href, { shallow: true }); @@ -108,6 +118,7 @@ const EditSQLButton = React.memo(({ metricId }: { metricId: string }) => { ); const onSetFileView = useChatLayoutContextSelector((x) => x.onSetFileView); const chatId = useChatIndividualContextSelector((x) => x.chatId); + const metricVersionNumber = useChatLayoutContextSelector((x) => x.metricVersionNumber); const editableSecondaryView: MetricFileViewSecondary = 'sql-edit'; const isSelectedView = selectedFileViewSecondary === editableSecondaryView; @@ -116,9 +127,10 @@ const EditSQLButton = React.memo(({ metricId }: { metricId: string }) => { chatId, assetId: metricId, type: 'metric', - secondaryView: 'sql-edit' + secondaryView: 'sql-edit', + versionNumber: metricVersionNumber }); - }, [chatId, metricId]); + }, [chatId, metricId, metricVersionNumber]); const onClickButton = useMemoizedFn(() => { const secondaryView = isSelectedView ? null : editableSecondaryView; @@ -147,8 +159,3 @@ const SaveToDashboardButton = React.memo(({ metricId }: { metricId: string }) => return ; }); SaveToDashboardButton.displayName = 'SaveToDashboardButton'; - -const ShareMetricButtonLocal = React.memo(({ metricId }: { metricId: string }) => { - return ; -}); -ShareMetricButtonLocal.displayName = 'ShareMetricButtonLocal'; diff --git a/web/src/layouts/ChatLayout/FileContainer/FileContainerHeader/MetricContainerHeaderButtons/MetricThreeDotMenu.tsx b/web/src/layouts/ChatLayout/FileContainer/FileContainerHeader/MetricContainerHeaderButtons/MetricThreeDotMenu.tsx index e3a0af5af..93c7a3ad8 100644 --- a/web/src/layouts/ChatLayout/FileContainer/FileContainerHeader/MetricContainerHeaderButtons/MetricThreeDotMenu.tsx +++ b/web/src/layouts/ChatLayout/FileContainer/FileContainerHeader/MetricContainerHeaderButtons/MetricThreeDotMenu.tsx @@ -56,82 +56,92 @@ import { BusterRoutes, createBusterRoute } from '@/routes'; import { useListVersionDropdownItems } from '@/components/features/versionHistory/useListVersionDropdownItems'; import { useChatIndividualContextSelector } from '@/layouts/ChatLayout/ChatContext'; -export const ThreeDotMenuButton = React.memo(({ metricId }: { metricId: string }) => { - const chatId = useChatIndividualContextSelector((x) => x.chatId); - const { openSuccessMessage } = useBusterNotifications(); - const { data: permission } = useGetMetric({ id: metricId }, { select: (x) => x.permission }); - const openFullScreenMetric = useOpenFullScreenMetric({ metricId }); - const onSetSelectedFile = useChatLayoutContextSelector((x) => x.onSetSelectedFile); - const dashboardSelectMenu = useDashboardSelectMenu({ metricId }); - const versionHistoryItems = useVersionHistorySelectMenu({ metricId }); - const collectionSelectMenu = useCollectionSelectMenu({ metricId }); - const statusSelectMenu = useStatusSelectMenu({ metricId }); - const favoriteMetric = useFavoriteMetricSelectMenu({ metricId }); - const editChartMenu = useEditChartSelectMenu(); - const resultsViewMenu = useResultsViewSelectMenu(); - const sqlEditorMenu = useSQLEditorSelectMenu(); - const downloadCSVMenu = useDownloadCSVSelectMenu({ metricId }); - const downloadPNGMenu = useDownloadPNGSelectMenu({ metricId }); - const deleteMetricMenu = useDeleteMetricSelectMenu({ metricId }); - const renameMetricMenu = useRenameMetricSelectMenu({ metricId }); - const shareMenu = useShareMenuSelectMenu({ metricId }); +export const ThreeDotMenuButton = React.memo( + ({ + metricId, + isViewingOldVersion, + versionNumber + }: { + metricId: string; + isViewingOldVersion: boolean; + versionNumber: number | undefined; + }) => { + const chatId = useChatIndividualContextSelector((x) => x.chatId); + const { openSuccessMessage } = useBusterNotifications(); + const { data: permission } = useGetMetric({ id: metricId }, { select: (x) => x.permission }); + const openFullScreenMetric = useOpenFullScreenMetric({ metricId, versionNumber }); + const onSetSelectedFile = useChatLayoutContextSelector((x) => x.onSetSelectedFile); + const dashboardSelectMenu = useDashboardSelectMenu({ metricId }); + const versionHistoryItems = useVersionHistorySelectMenu({ metricId }); + const collectionSelectMenu = useCollectionSelectMenu({ metricId }); + const statusSelectMenu = useStatusSelectMenu({ metricId }); + const favoriteMetric = useFavoriteMetricSelectMenu({ metricId }); + const editChartMenu = useEditChartSelectMenu(); + const resultsViewMenu = useResultsViewSelectMenu(); + const sqlEditorMenu = useSQLEditorSelectMenu(); + const downloadCSVMenu = useDownloadCSVSelectMenu({ metricId }); + const downloadPNGMenu = useDownloadPNGSelectMenu({ metricId }); + const deleteMetricMenu = useDeleteMetricSelectMenu({ metricId }); + const renameMetricMenu = useRenameMetricSelectMenu({ metricId }); + const shareMenu = useShareMenuSelectMenu({ metricId }); - const isEditor = canEdit(permission); - const isOwnerEffective = getIsEffectiveOwner(permission); - const isOwner = getIsOwner(permission); + const isEditor = canEdit(permission); + const isOwnerEffective = getIsEffectiveOwner(permission); + const isOwner = getIsOwner(permission); - const items: DropdownItems = useMemo( - () => + const items: DropdownItems = useMemo( + () => + [ + chatId && openFullScreenMetric, + isOwnerEffective && !isViewingOldVersion && shareMenu, + isEditor && !isViewingOldVersion && statusSelectMenu, + { type: 'divider' }, + !isViewingOldVersion && dashboardSelectMenu, + !isViewingOldVersion && collectionSelectMenu, + !isViewingOldVersion && favoriteMetric, + { type: 'divider' }, + isEditor && !isViewingOldVersion && editChartMenu, + !isViewingOldVersion && resultsViewMenu, + !isViewingOldVersion && sqlEditorMenu, + isEditor && versionHistoryItems, + { type: 'divider' }, + downloadCSVMenu, + downloadPNGMenu, + { type: 'divider' }, + isEditor && !isViewingOldVersion && renameMetricMenu, + isOwner && !isViewingOldVersion && deleteMetricMenu + ].filter(Boolean) as DropdownItems, [ - chatId && openFullScreenMetric, - isOwnerEffective && shareMenu, - isEditor && statusSelectMenu, - { type: 'divider' }, + chatId, + openFullScreenMetric, + isEditor, + isOwner, + isOwnerEffective, + renameMetricMenu, dashboardSelectMenu, - collectionSelectMenu, - favoriteMetric, - { type: 'divider' }, - isEditor && editChartMenu, - resultsViewMenu, - sqlEditorMenu, - isEditor && versionHistoryItems, - { type: 'divider' }, + deleteMetricMenu, downloadCSVMenu, downloadPNGMenu, - { type: 'divider' }, - isEditor && renameMetricMenu, - isOwner && deleteMetricMenu - ].filter(Boolean) as DropdownItems, - [ - chatId, - openFullScreenMetric, - isEditor, - isOwner, - isOwnerEffective, - renameMetricMenu, - dashboardSelectMenu, - deleteMetricMenu, - downloadCSVMenu, - downloadPNGMenu, - openSuccessMessage, - onSetSelectedFile, - versionHistoryItems, - favoriteMetric, - statusSelectMenu, - collectionSelectMenu, - editChartMenu, - resultsViewMenu, - sqlEditorMenu, - shareMenu - ] - ); + openSuccessMessage, + onSetSelectedFile, + versionHistoryItems, + favoriteMetric, + statusSelectMenu, + collectionSelectMenu, + editChartMenu, + resultsViewMenu, + sqlEditorMenu, + shareMenu + ] + ); - return ( - -