| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 |
- import { useCallback, useEffect, useRef } from 'react'
- import { Entity } from '@/data/entity-types/entity-types-infinite-query'
- import useLatest from '@/hooks/misc/useLatest'
- import { createTabId, editorEntityTypes, useTabsStateSnapshot } from '@/state/tabs'
- export function useTableEditorTabsCleanUp() {
- const tabs = useTabsStateSnapshot()
- const tabMapRef = useLatest(tabs.tabsMap)
- const recentItemsRef = useLatest(tabs.recentItems)
- const openTabsRef = useLatest(tabs.openTabs)
- return useCallback(({ schemas, entities }: { schemas: string[]; entities: Entity[] }) => {
- // Identity all entities by tab ID
- const entitiesById: string[] = entities.map((x: Entity) => createTabId(x.type, { id: x.id }))
- const recentItemsFilteredToSchemas: string[] = []
- for (const schema of schemas) {
- recentItemsFilteredToSchemas.push(
- ...recentItemsRef.current.filter((x) => x.metadata?.schema === schema).map((x) => x.id)
- )
- }
- const recentItemsToRemove = [
- ...recentItemsFilteredToSchemas.filter((entityId) => !entitiesById.includes(entityId)),
- ]
- tabs.removeRecentItems(recentItemsToRemove)
- const tabsFilteredToSchemas: string[] = []
- for (const schema of schemas) {
- tabsFilteredToSchemas.push(
- ...openTabsRef.current.filter((tabId) => {
- const tab = tabMapRef.current[tabId]
- return tab?.metadata?.schema === schema
- })
- )
- }
- const tableEditorTabsToBeCleaned = [
- ...tabsFilteredToSchemas.filter(
- (id) => !id.startsWith('sql') && !id.startsWith('schema') && !entitiesById.includes(id)
- ),
- ]
- // perform tabs cleanup
- tabs.removeTabs(tableEditorTabsToBeCleaned)
- // [Joshen] Validate for opened tabs, if their label matches the entity's name - update label if not
- // As the entity could've been renamed outside of the table editor
- // e.g Using the SQL editor to rename the entity
- const openTabs = openTabsRef.current
- .map((id) => tabMapRef.current[id])
- .filter((tab) => !!tab && editorEntityTypes['table']?.includes(tab.type))
- openTabs.forEach((tab) => {
- const entity = entities?.find((x) => tab.metadata?.tableId === x.id)
- if (!!entity && entity.name !== tab.label) tabs.updateTab(tab.id, { label: entity.name })
- })
- }, [])
- }
- export function useSqlEditorTabsCleanup() {
- const tabs = useTabsStateSnapshot()
- const tabMapRef = useLatest(tabs.tabsMap)
- const openTabsRef = useLatest(tabs.openTabs)
- return useCallback(({ snippets }: { snippets: { id: string; type: string; name: string }[] }) => {
- // these are tabs that are static content
- // these canot be removed from localstorage based on this query request
- const IGNORED_TAB_IDS = ['sql-templates', 'sql-quickstarts']
- // Identify all SQL snippets / content by their tab ids
- const currentContentIds = [
- ...snippets
- .filter((content) => content.type === 'sql')
- .map((content) => createTabId('sql', { id: content.id })),
- // append ignored tab IDs
- ...IGNORED_TAB_IDS,
- ]
- // Remove any snippet tabs that might no longer be existing (removed outside of the dashboard session)
- const snippetTabsToBeCleaned = openTabsRef.current.filter(
- (id: string) => id.startsWith('sql') && !currentContentIds.includes(id)
- )
- tabs.removeTabs(snippetTabsToBeCleaned)
- // Remove any recent items that might no longer be existing (removed outside of the dashboard session)
- const recentItems = tabs.getRecentItemsByType('sql')
- tabs.removeRecentItems(
- recentItems
- ? recentItems.filter((item) => !currentContentIds.includes(item.id)).map((item) => item.id)
- : []
- )
- // [Joshen] Validate for opened tabs, if their label matches the snippet's name - update label if not
- // As the snippets name could've been updated outside of the SQL Editor session
- // e.g for a shared snippet, the owner could've updated the name of the snippet
- const openSqlTabs = openTabsRef.current
- .map((id) => tabMapRef.current[id])
- .filter((tab) => !!tab && editorEntityTypes['sql']?.includes(tab.type))
- openSqlTabs.forEach((tab) => {
- const snippet = snippets?.find((x) => tab.metadata?.sqlId === x.id)
- if (!!snippet && snippet.name !== tab.label) tabs.updateTab(tab.id, { label: snippet.name })
- })
- }, [])
- }
- interface UseTabsScrollOptions {
- activeTab: string | null | undefined
- tabCount: number
- }
- export function useTabsScroll({ activeTab, tabCount }: UseTabsScrollOptions) {
- const tabsListRef = useRef<HTMLDivElement>(null)
- const prevTabCountRef = useRef<number>(tabCount)
- const isInitialMount = useRef(true)
- useEffect(() => {
- if (tabsListRef.current) {
- tabsListRef.current.scrollLeft = tabsListRef.current.scrollWidth
- }
- }, [])
- useEffect(() => {
- if (isInitialMount.current) {
- isInitialMount.current = false
- return
- }
- if (!tabsListRef.current) return
- const tabCountIncreased = tabCount > prevTabCountRef.current
- if (tabCountIncreased) {
- tabsListRef.current.scrollLeft = tabsListRef.current.scrollWidth
- } else if (activeTab) {
- const activeTabElement = tabsListRef.current.querySelector(
- `[data-state="active"]`
- ) as HTMLElement
- if (activeTabElement) {
- activeTabElement.scrollIntoView({
- behavior: 'smooth',
- block: 'nearest',
- inline: 'nearest',
- })
- }
- }
- prevTabCountRef.current = tabCount
- }, [activeTab, tabCount])
- return { tabsListRef }
- }
|