import _ from 'lodash'; import React from 'react'; import styled from 'styled-components'; import { DropDownMenuItem, DropDownMenuDivider } from './modals/DropDownMenu'; import { useOpenedTabs, useSetOpenedTabs, useCurrentDatabase, useSetCurrentDatabase } from './utility/globalState'; import { getConnectionInfo } from './utility/metadataLoaders'; import { FontIcon } from './icons'; import useTheme from './theme/useTheme'; import usePropsCompare from './utility/usePropsCompare'; import { useShowMenu } from './modals/showMenu'; // const files = [ // { name: 'app.js' }, // { name: 'BranchCategory', type: 'table', selected: true }, // { name: 'ApplicationList' }, // ]; const DbGroupHandler = styled.div` display: flex; flex: 1; align-content: stretch; `; const DbWrapperHandler = styled.div` display: flex; flex-direction: column; align-items: stretch; `; const DbNameWrapper = styled.div` text-align: center; font-size: 8pt; border-bottom: 1px solid ${(props) => props.theme.border}; border-right: 1px solid ${(props) => props.theme.border}; cursor: pointer; user-select: none; padding: 1px; position: relative; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; // height: 15px; &:hover { background-color: ${(props) => props.theme.tabs_background3}; } background-color: ${(props) => // @ts-ignore props.selected ? props.theme.tabs_background1 : 'inherit'}; `; // const DbNameWrapperInner = styled.div` // position: absolute; // white-space: nowrap; // `; const FileTabItem = styled.div` border-right: 1px solid ${(props) => props.theme.border}; padding-left: 15px; padding-right: 15px; flex-shrink: 1; flex-grow: 1; min-width: 10px; display: flex; align-items: center; cursor: pointer; user-select: none; &:hover { color: ${(props) => props.theme.tabs_font_hover}; } background-color: ${(props) => // @ts-ignore props.selected ? props.theme.tabs_background1 : 'inherit'}; `; const FileNameWrapper = styled.span` margin-left: 5px; `; const CloseButton = styled(FontIcon)` margin-left: 5px; color: gray; &:hover { color: ${(props) => props.theme.tabs_font2}; } `; function TabContextMenu({ close, closeAll, closeOthers, closeWithSameDb, closeWithOtherDb, props }) { const { database } = props || {}; const { conid } = props || {}; return ( <> Close Close all Close others {conid && database && ( Close with same DB - {database} )} {conid && database && ( Close with other DB than {database} )} ); } function getTabDbName(tab) { if (tab.props && tab.props.conid && tab.props.database) return tab.props.database; if (tab.props && tab.props.archiveFolder) return tab.props.archiveFolder; return '(no DB)'; } function getTabDbKey(tab) { if (tab.props && tab.props.conid && tab.props.database) return `database://${tab.props.database}-${tab.props.conid}`; if (tab.props && tab.props.archiveFolder) return `archive://${tab.props.archiveFolder}`; return '_no'; } function getDbIcon(key) { if (key.startsWith('database://')) return 'icon database'; if (key.startsWith('archive://')) return 'icon archive'; return 'icon file'; } export default function TabsPanel() { // const formatDbKey = (conid, database) => `${database}-${conid}`; const theme = useTheme(); const showMenu = useShowMenu(); const tabs = useOpenedTabs(); const setOpenedTabs = useSetOpenedTabs(); const currentDb = useCurrentDatabase(); const setCurrentDb = useSetCurrentDatabase(); const { name, connection } = currentDb || {}; const currentDbKey = name && connection ? `database://${name}-${connection._id}` : '_no'; const handleTabClick = (e, tabid) => { if (e.target.closest('.tabCloseButton')) { return; } setOpenedTabs((files) => files.map((x) => ({ ...x, selected: x.tabid == tabid, })) ); }; const closeTabFunc = (closeCondition) => (tabid) => { setOpenedTabs((files) => { const active = files.find((x) => x.tabid == tabid); if (!active) return files; const lastSelectedIndex = _.findIndex(files, (x) => x.tabid == tabid); let selectedIndex = lastSelectedIndex; const newFiles = files.map((x) => ({ ...x, closedTime: x.closedTime || (closeCondition(x, active) ? new Date().getTime() : undefined), })); while (selectedIndex >= 0 && newFiles[selectedIndex].closedTime) selectedIndex -= 1; if (selectedIndex < 0) { selectedIndex = lastSelectedIndex; while (selectedIndex < newFiles.length && newFiles[selectedIndex].closedTime) selectedIndex += 1; } if (selectedIndex != lastSelectedIndex) { return newFiles.map((x, index) => ({ ...x, selected: index == selectedIndex, })); } return newFiles; }); }; const closeTab = closeTabFunc((x, active) => x.tabid == active.tabid); const closeAll = () => { const closedTime = new Date().getTime(); setOpenedTabs((tabs) => tabs.map((tab) => ({ ...tab, closedTime: tab.closedTime || closedTime, selected: false, })) ); }; const closeWithSameDb = closeTabFunc( (x, active) => _.get(x, 'props.conid') == _.get(active, 'props.conid') && _.get(x, 'props.database') == _.get(active, 'props.database') ); const closeWithOtherDb = closeTabFunc( (x, active) => _.get(x, 'props.conid') != _.get(active, 'props.conid') || _.get(x, 'props.database') != _.get(active, 'props.database') ); const closeOthers = closeTabFunc((x, active) => x.tabid != active.tabid); const handleMouseUp = (e, tabid) => { if (e.button == 1) { e.preventDefault(); closeTab(tabid); } }; const handleContextMenu = (event, tabid, props) => { event.preventDefault(); showMenu( event.pageX, event.pageY, closeTab(tabid)} closeAll={closeAll} closeOthers={() => closeOthers(tabid)} closeWithSameDb={() => closeWithSameDb(tabid)} closeWithOtherDb={() => closeWithOtherDb(tabid)} props={props} /> ); }; // console.log( // 't', // tabs.map(x => x.tooltip) // ); const tabsWithDb = tabs .filter((x) => !x.closedTime) .map((tab) => ({ ...tab, tabDbName: getTabDbName(tab), tabDbKey: getTabDbKey(tab), })); const tabsByDb = _.groupBy(tabsWithDb, 'tabDbKey'); const dbKeys = _.keys(tabsByDb).sort(); const handleSetDb = async (props) => { const { conid, database } = props || {}; if (conid) { const connection = await getConnectionInfo({ conid, database }); if (connection) { setCurrentDb({ connection, name: database }); return; } } setCurrentDb(null); }; return ( <> {dbKeys.map((dbKey) => ( handleSetDb(tabsByDb[dbKey][0].props)} theme={theme} > {tabsByDb[dbKey][0].tabDbName} {_.sortBy(tabsByDb[dbKey], 'title').map((tab) => ( handleTabClick(e, tab.tabid)} onMouseUp={(e) => handleMouseUp(e, tab.tabid)} onContextMenu={(e) => handleContextMenu(e, tab.tabid, tab.props)} > {} {tab.title} { e.preventDefault(); closeTab(tab.tabid); }} /> ))} ))} ); }