/* * CloudBeaver - Cloud Database Manager * Copyright (C) 2020-2022 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0. * you may not use this file except in compliance with the License. */ import { observable } from 'mobx'; import { observer } from 'mobx-react-lite'; import { useCallback } from 'react'; import styled, { css } from 'reshadow'; import { TabHandlerPanelComponent, NavTreeResource, NavNodeInfoResource } from '@cloudbeaver/core-app'; import { TabsBox, TabPanel, useTabLocalState } from '@cloudbeaver/core-ui'; import { Loader, TextPlaceholder, Button, useMapResource, useObservableRef } from '@cloudbeaver/core-blocks'; import { ConnectionInfoResource, ConnectionsManagerService } from '@cloudbeaver/core-connections'; import { useService } from '@cloudbeaver/core-di'; import { useTranslate } from '@cloudbeaver/core-localization'; import { useStyles, composes } from '@cloudbeaver/core-theming'; import { MetadataMap } from '@cloudbeaver/core-utils'; import type { IObjectViewerTabState } from './IObjectViewerTabState'; import { DBObjectPagePanel } from './ObjectPage/DBObjectPagePanel'; import { DBObjectPageService } from './ObjectPage/DBObjectPageService'; import { DBObjectPageTab } from './ObjectPage/DBObjectPageTab'; const styles = composes( css` Tab { composes: theme-ripple theme-background-surface theme-text-text-primary-on-light from global; } tabs { composes: theme-background-background theme-text-text-primary-on-light from global; } `, css` tab-outer:only-child { display: none; } ExceptionMessage { padding: 24px; } ` ); export const ObjectViewerPanel: TabHandlerPanelComponent = observer(function ObjectViewerPanel({ tab, }) { const translate = useTranslate(); const style = useStyles(styles); const dbObjectPagesService = useService(DBObjectPageService); const connectionsManagerService = useService(ConnectionsManagerService); const navNodeInfoResource = useService(NavNodeInfoResource); const innerTabState = useTabLocalState(() => new MetadataMap()); const objectId = tab.handlerState.objectId; const connectionId = tab.handlerState.connectionId || null; const parentId = tab.handlerState.parentId; const parents = tab.handlerState.parents; const state = useObservableRef(() => ({ connecting: false, notFound: false, }), { connecting: observable.ref, notFound: observable.ref, }, false); const connection = useMapResource(ObjectViewerPanel, ConnectionInfoResource, connectionId, { isActive: resource => !connectionId || !resource.has(connectionId), }); const children = useMapResource(ObjectViewerPanel, NavTreeResource, parentId, { onLoad: async resource => { const preload = await resource.preloadNodeParents(parents); state.notFound = !preload; return state.notFound; }, isActive: () => connection.data?.connected || false, onData: data => { state.notFound = !data.includes(objectId); }, preload: [connection], }); const node = useMapResource(ObjectViewerPanel, navNodeInfoResource, objectId, { onLoad: async () => !(await children.resource.preloadNodeParents(parents, objectId)), onData(data) { tab.handlerState.tabIcon = data.icon; tab.handlerState.tabTitle = data.name; }, isActive: () => !state.notFound, preload: [children], }); const pages = dbObjectPagesService.orderedPages; const handleConnect = useCallback(async () => { if (state.connecting || !connection.data) { return; } state.connecting = true; try { await connectionsManagerService.requireConnection(connection.data.id); } finally { state.connecting = false; } }, []); if (connection.data && !connection.data.connected) { if (state.connecting || connection.isLoading()) { return ; } return ( ); } if (tab.handlerState.error || state.notFound) { return {translate('plugin_object_viewer_error')}; } return styled(style)( {() => styled(style)( <> {node.data ? ( ( ))} localState={innerTabState} style={styles} > {pages.map(page => ( ))} ) : ( {translate('plugin_object_viewer_table_no_items')} )} )} ); });