mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-25 13:16:00 +00:00
add to favorites basic functionality
This commit is contained in:
@@ -66,6 +66,25 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
favorites_meta: 'get',
|
||||||
|
async favorites() {
|
||||||
|
if (!hasPermission(`files/favorites/read`)) return [];
|
||||||
|
const dir = path.join(filesdir(), 'favorites');
|
||||||
|
if (!(await fs.exists(dir))) return [];
|
||||||
|
const files = await fs.readdir(dir);
|
||||||
|
const res = [];
|
||||||
|
for (const file of files) {
|
||||||
|
const filePath = path.join(dir, file);
|
||||||
|
const text = await fs.readFile(filePath, { encoding: 'utf-8' });
|
||||||
|
res.push({
|
||||||
|
file,
|
||||||
|
folder: 'favorites',
|
||||||
|
...JSON.parse(text),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
},
|
||||||
|
|
||||||
markdownManifest_meta: 'get',
|
markdownManifest_meta: 'get',
|
||||||
async markdownManifest() {
|
async markdownManifest() {
|
||||||
if (!hasPermission(`files/markdown/read`)) return [];
|
if (!hasPermission(`files/markdown/read`)) return [];
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ function Menu({ data, menuExt = null }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function SavedFileAppObjectBase({ data, commonProps, format, icon, onLoad, menuExt = null }) {
|
export function SavedFileAppObjectBase({ data, commonProps, format, icon, onLoad, title = undefined, menuExt = null }) {
|
||||||
const { file, folder } = data;
|
const { file, folder } = data;
|
||||||
|
|
||||||
const onClick = async () => {
|
const onClick = async () => {
|
||||||
@@ -56,7 +56,7 @@ export function SavedFileAppObjectBase({ data, commonProps, format, icon, onLoad
|
|||||||
<AppObjectCore
|
<AppObjectCore
|
||||||
{...commonProps}
|
{...commonProps}
|
||||||
data={data}
|
data={data}
|
||||||
title={file}
|
title={title || file}
|
||||||
icon={icon}
|
icon={icon}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
Menu={menuExt ? (props) => <Menu {...props} menuExt={menuExt} /> : Menu}
|
Menu={menuExt ? (props) => <Menu {...props} menuExt={menuExt} /> : Menu}
|
||||||
@@ -90,7 +90,7 @@ export function SavedSqlFileAppObject({ data, commonProps }) {
|
|||||||
icon: 'img shell',
|
icon: 'img shell',
|
||||||
tabComponent: 'ShellTab',
|
tabComponent: 'ShellTab',
|
||||||
},
|
},
|
||||||
script.getScript()
|
{ editor: script.getScript() }
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -111,6 +111,8 @@ export function SavedSqlFileAppObject({ data, commonProps }) {
|
|||||||
initialData: data,
|
initialData: data,
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
savedFile: file,
|
savedFile: file,
|
||||||
|
savedFolder: 'sql',
|
||||||
|
savedFormat: 'text',
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@@ -135,9 +137,11 @@ export function SavedShellFileAppObject({ data, commonProps }) {
|
|||||||
tabComponent: 'ShellTab',
|
tabComponent: 'ShellTab',
|
||||||
props: {
|
props: {
|
||||||
savedFile: file,
|
savedFile: file,
|
||||||
|
savedFolder: 'shell',
|
||||||
|
savedFormat: 'text',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
data
|
{ editor: data }
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@@ -171,10 +175,12 @@ export function SavedChartFileAppObject({ data, commonProps }) {
|
|||||||
conid: connection._id,
|
conid: connection._id,
|
||||||
database,
|
database,
|
||||||
savedFile: file,
|
savedFile: file,
|
||||||
|
savedFolder: 'charts',
|
||||||
|
savedFormat: 'json',
|
||||||
},
|
},
|
||||||
tabComponent: 'ChartTab',
|
tabComponent: 'ChartTab',
|
||||||
},
|
},
|
||||||
data
|
{ editor: data }
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@@ -191,7 +197,9 @@ export function SavedMarkdownFileAppObject({ data, commonProps }) {
|
|||||||
icon: 'img markdown',
|
icon: 'img markdown',
|
||||||
tabComponent: 'MarkdownViewTab',
|
tabComponent: 'MarkdownViewTab',
|
||||||
props: {
|
props: {
|
||||||
file,
|
savedFile: file,
|
||||||
|
savedFolder: 'markdown',
|
||||||
|
savedFormat: 'text',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -209,9 +217,11 @@ export function SavedMarkdownFileAppObject({ data, commonProps }) {
|
|||||||
tabComponent: 'MarkdownEditorTab',
|
tabComponent: 'MarkdownEditorTab',
|
||||||
props: {
|
props: {
|
||||||
savedFile: file,
|
savedFile: file,
|
||||||
|
savedFolder: 'markdown',
|
||||||
|
savedFormat: 'text',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
data
|
{ editor: data }
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
menuExt={<DropDownMenuItem onClick={showPage}>Show page</DropDownMenuItem>}
|
menuExt={<DropDownMenuItem onClick={showPage}>Show page</DropDownMenuItem>}
|
||||||
@@ -219,7 +229,51 @@ export function SavedMarkdownFileAppObject({ data, commonProps }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
[SavedSqlFileAppObject, SavedShellFileAppObject, SavedChartFileAppObject, SavedMarkdownFileAppObject].forEach((fn) => {
|
export function FavoriteFileAppObject({ data, commonProps }) {
|
||||||
|
const { file, folder, icon, tabComponent, title, props, tabdata } = data;
|
||||||
|
const openNewTab = useOpenNewTab();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SavedFileAppObjectBase
|
||||||
|
data={data}
|
||||||
|
commonProps={commonProps}
|
||||||
|
format="json"
|
||||||
|
icon={icon || 'img favorite'}
|
||||||
|
title={title}
|
||||||
|
onLoad={async (data) => {
|
||||||
|
let tabdataNew = tabdata;
|
||||||
|
if (props.savedFile) {
|
||||||
|
const resp = await axios.post('files/load', {
|
||||||
|
folder: props.savedFolder,
|
||||||
|
file: props.savedFile,
|
||||||
|
format: props.savedFormat,
|
||||||
|
});
|
||||||
|
tabdataNew = {
|
||||||
|
...tabdata,
|
||||||
|
editor: resp.data,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
openNewTab(
|
||||||
|
{
|
||||||
|
title,
|
||||||
|
icon: icon || 'img favorite',
|
||||||
|
props,
|
||||||
|
tabComponent,
|
||||||
|
},
|
||||||
|
tabdataNew
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[
|
||||||
|
SavedSqlFileAppObject,
|
||||||
|
SavedShellFileAppObject,
|
||||||
|
SavedChartFileAppObject,
|
||||||
|
SavedMarkdownFileAppObject,
|
||||||
|
FavoriteFileAppObject,
|
||||||
|
].forEach((fn) => {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
fn.extractKey = (data) => data.file;
|
fn.extractKey = (data) => data.file;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -341,7 +341,7 @@ export default function DataGridCore(props) {
|
|||||||
tabComponent: 'FreeTableTab',
|
tabComponent: 'FreeTableTab',
|
||||||
props: {},
|
props: {},
|
||||||
},
|
},
|
||||||
getSelectedFreeData()
|
{ editor: getSelectedFreeData() }
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -354,8 +354,10 @@ export default function DataGridCore(props) {
|
|||||||
props: {},
|
props: {},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
data: getSelectedFreeData(),
|
editor: {
|
||||||
config: { chartType: 'bar' },
|
data: getSelectedFreeData(),
|
||||||
|
config: { chartType: 'bar' },
|
||||||
|
},
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -92,10 +92,12 @@ export default function SqlDataGridCore(props) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
config: { chartType: 'bar' },
|
editor: {
|
||||||
sql: display.getExportQuery((select) => {
|
config: { chartType: 'bar' },
|
||||||
select.orderBy = null;
|
sql: display.getExportQuery((select) => {
|
||||||
}),
|
select.orderBy = null;
|
||||||
|
}),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ const iconNames = {
|
|||||||
'icon export': 'mdi mdi-application-export',
|
'icon export': 'mdi mdi-application-export',
|
||||||
'icon new-connection': 'mdi mdi-database-plus',
|
'icon new-connection': 'mdi mdi-database-plus',
|
||||||
'icon tables': 'mdi mdi-table-multiple',
|
'icon tables': 'mdi mdi-table-multiple',
|
||||||
|
'icon favorite': 'mdi mdi-star',
|
||||||
|
|
||||||
'icon database': 'mdi mdi-database',
|
'icon database': 'mdi mdi-database',
|
||||||
'icon server': 'mdi mdi-server',
|
'icon server': 'mdi mdi-server',
|
||||||
@@ -65,6 +66,7 @@ const iconNames = {
|
|||||||
'img chart': 'mdi mdi-chart-bar color-magenta-7',
|
'img chart': 'mdi mdi-chart-bar color-magenta-7',
|
||||||
'img markdown': 'mdi mdi-application color-red-7',
|
'img markdown': 'mdi mdi-application color-red-7',
|
||||||
'img preview': 'mdi mdi-file-find color-red-7',
|
'img preview': 'mdi mdi-file-find color-red-7',
|
||||||
|
'img favorite': 'mdi mdi-star color-yellow-7',
|
||||||
|
|
||||||
'img free-table': 'mdi mdi-table color-green-7',
|
'img free-table': 'mdi mdi-table color-green-7',
|
||||||
'img macro': 'mdi mdi-hammer-wrench',
|
'img macro': 'mdi mdi-hammer-wrench',
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ export default function OpenChartLink({ file, children }) {
|
|||||||
savedFile: file,
|
savedFile: file,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
resp.data
|
{ editor: resp.data }
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ function GenerateSctriptButton({ modalState }) {
|
|||||||
icon: 'img shell',
|
icon: 'img shell',
|
||||||
tabComponent: 'ShellTab',
|
tabComponent: 'ShellTab',
|
||||||
},
|
},
|
||||||
code
|
{ editor: code }
|
||||||
);
|
);
|
||||||
modalState.close();
|
modalState.close();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -13,7 +13,12 @@ export default function SaveTabModal({ data, folder, format, modalState, tabid,
|
|||||||
changeTab(tabid, setOpenedTabs, (tab) => ({
|
changeTab(tabid, setOpenedTabs, (tab) => ({
|
||||||
...tab,
|
...tab,
|
||||||
title: name,
|
title: name,
|
||||||
props: { ...tab.props, savedFile: name },
|
props: {
|
||||||
|
...tab.props,
|
||||||
|
savedFile: name,
|
||||||
|
savedFolder: folder,
|
||||||
|
savedFormat: format,
|
||||||
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const handleKeyboard = React.useCallback(
|
const handleKeyboard = React.useCallback(
|
||||||
|
|||||||
@@ -24,6 +24,6 @@ export default function useNewQuery() {
|
|||||||
database,
|
database,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
initialData
|
{ editor: initialData }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,3 +74,5 @@ export default function ChartTab({ tabVisible, toolbarPortalRef, conid, database
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ChartTab.allowAddToFavorites = (props) => props.savedFile;
|
||||||
|
|||||||
@@ -3,13 +3,17 @@ import axios from '../utility/axios';
|
|||||||
import LoadingInfo from '../widgets/LoadingInfo';
|
import LoadingInfo from '../widgets/LoadingInfo';
|
||||||
import MarkdownExtendedView from '../markdown/MarkdownExtendedView';
|
import MarkdownExtendedView from '../markdown/MarkdownExtendedView';
|
||||||
|
|
||||||
export default function MarkdownViewTab({ file }) {
|
export default function MarkdownViewTab({ savedFile }) {
|
||||||
const [isLoading, setIsLoading] = React.useState(false);
|
const [isLoading, setIsLoading] = React.useState(false);
|
||||||
const [text, setText] = React.useState(null);
|
const [text, setText] = React.useState(null);
|
||||||
|
|
||||||
const handleLoad = async () => {
|
const handleLoad = async () => {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
const resp = await axios.post('files/load', { folder: 'markdown', file, format: 'text' });
|
const resp = await axios.post('files/load', {
|
||||||
|
folder: 'markdown',
|
||||||
|
file: savedFile,
|
||||||
|
format: 'text',
|
||||||
|
});
|
||||||
setText(resp.data);
|
setText(resp.data);
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
};
|
};
|
||||||
@@ -28,3 +32,5 @@ export default function MarkdownViewTab({ file }) {
|
|||||||
|
|
||||||
return <MarkdownExtendedView>{text || ''}</MarkdownExtendedView>;
|
return <MarkdownExtendedView>{text || ''}</MarkdownExtendedView>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MarkdownViewTab.allowAddToFavorites = (props) => true;
|
||||||
|
|||||||
@@ -176,3 +176,5 @@ export default function QueryTab({ tabid, conid, database, initialArgs, tabVisib
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QueryTab.allowAddToFavorites = (props) => props.savedFile;
|
||||||
|
|||||||
@@ -139,3 +139,5 @@ export default function ShellTab({ tabid, tabVisible, toolbarPortalRef, ...other
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ShellTab.allowAddToFavorites = (props) => props.savedFile;
|
||||||
|
|||||||
@@ -28,3 +28,4 @@ export default function TableDataTab({ conid, database, schemaName, pureName, ta
|
|||||||
}
|
}
|
||||||
|
|
||||||
TableDataTab.matchingProps = ['conid', 'database', 'schemaName', 'pureName'];
|
TableDataTab.matchingProps = ['conid', 'database', 'schemaName', 'pureName'];
|
||||||
|
TableDataTab.allowAddToFavorites = (props) => true;
|
||||||
|
|||||||
@@ -55,4 +55,5 @@ export default function ViewDataTab({ conid, database, schemaName, pureName, tab
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ViewDataTab.matchingProps = ['conid', 'database', 'schemaName', 'pureName'];
|
ViewDataTab.matchingProps = ['conid', 'database', 'schemaName', 'pureName'];
|
||||||
|
ViewDataTab.allowAddToFavorites = (props) => true;
|
||||||
|
|||||||
@@ -46,6 +46,12 @@ const configLoader = () => ({
|
|||||||
reloadTrigger: 'config-changed',
|
reloadTrigger: 'config-changed',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const favoritesLoader = () => ({
|
||||||
|
url: 'files/favorites',
|
||||||
|
params: {},
|
||||||
|
reloadTrigger: 'files-changed-favorites',
|
||||||
|
});
|
||||||
|
|
||||||
const markdownManifestLoader = () => ({
|
const markdownManifestLoader = () => ({
|
||||||
url: 'files/markdown-manifest',
|
url: 'files/markdown-manifest',
|
||||||
params: {},
|
params: {},
|
||||||
@@ -282,3 +288,10 @@ export function getMarkdownManifest(args) {
|
|||||||
export function useMarkdownManifest(args) {
|
export function useMarkdownManifest(args) {
|
||||||
return useCore(markdownManifestLoader, args);
|
return useCore(markdownManifestLoader, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getFavorites(args) {
|
||||||
|
return getCore(favoritesLoader, args);
|
||||||
|
}
|
||||||
|
export function useFavorites(args) {
|
||||||
|
return useCore(favoritesLoader, args);
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { changeTab } from './common';
|
|||||||
import { useSetOpenedTabs } from './globalState';
|
import { useSetOpenedTabs } from './globalState';
|
||||||
|
|
||||||
export default function useEditorData({ tabid, reloadToken = 0, loadFromArgs = null }) {
|
export default function useEditorData({ tabid, reloadToken = 0, loadFromArgs = null }) {
|
||||||
const localStorageKey = `tabdata_${tabid}`;
|
const localStorageKey = `tabdata_editor_${tabid}`;
|
||||||
const setOpenedTabs = useSetOpenedTabs();
|
const setOpenedTabs = useSetOpenedTabs();
|
||||||
const changeCounterRef = React.useRef(0);
|
const changeCounterRef = React.useRef(0);
|
||||||
const savedCounterRef = React.useRef(0);
|
const savedCounterRef = React.useRef(0);
|
||||||
|
|||||||
@@ -46,7 +46,13 @@ export default function useOpenNewTab() {
|
|||||||
|
|
||||||
const tabid = uuidv1();
|
const tabid = uuidv1();
|
||||||
if (initialData) {
|
if (initialData) {
|
||||||
await localforage.setItem(`tabdata_${tabid}`, initialData);
|
for (const key of _.keys(initialData)) {
|
||||||
|
if (key == 'editor') {
|
||||||
|
await localforage.setItem(`tabdata_${key}_${tabid}`, initialData[key]);
|
||||||
|
} else {
|
||||||
|
localStorage.setItem(`tabdata_${key}_${tabid}`, JSON.stringify(initialData[key]));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
setOpenedTabs((files) => [
|
setOpenedTabs((files) => [
|
||||||
...(files || []).map((x) => ({ ...x, selected: false })),
|
...(files || []).map((x) => ({ ...x, selected: false })),
|
||||||
|
|||||||
57
packages/web/src/widgets/FavoritesWidget.js
Normal file
57
packages/web/src/widgets/FavoritesWidget.js
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import _ from 'lodash';
|
||||||
|
|
||||||
|
import { AppObjectList } from '../appobj/AppObjectList';
|
||||||
|
import { useOpenedTabs } from '../utility/globalState';
|
||||||
|
import ClosedTabAppObject from '../appobj/ClosedTabAppObject';
|
||||||
|
import { WidgetsInnerContainer } from './WidgetStyles';
|
||||||
|
import { FavoriteFileAppObject } from '../appobj/SavedFileAppObject';
|
||||||
|
import WidgetColumnBar, { WidgetColumnBarItem } from './WidgetColumnBar';
|
||||||
|
import { useFavorites, useFiles } from '../utility/metadataLoaders';
|
||||||
|
import useHasPermission from '../utility/useHasPermission';
|
||||||
|
|
||||||
|
function ClosedTabsList() {
|
||||||
|
const tabs = useOpenedTabs();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<WidgetsInnerContainer>
|
||||||
|
<AppObjectList
|
||||||
|
list={_.sortBy(
|
||||||
|
tabs.filter((x) => x.closedTime),
|
||||||
|
(x) => -x.closedTime
|
||||||
|
)}
|
||||||
|
AppObjectComponent={ClosedTabAppObject}
|
||||||
|
/>
|
||||||
|
</WidgetsInnerContainer>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function FavoritesList() {
|
||||||
|
const favorites = useFavorites();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<WidgetsInnerContainer>
|
||||||
|
<AppObjectList list={favorites} AppObjectComponent={FavoriteFileAppObject} />
|
||||||
|
</WidgetsInnerContainer>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function FavoritesWidget() {
|
||||||
|
const hasPermission = useHasPermission();
|
||||||
|
return (
|
||||||
|
<WidgetColumnBar>
|
||||||
|
<WidgetColumnBarItem title="Recently closed tabs" name="closedTabs" height="20%">
|
||||||
|
<ClosedTabsList />
|
||||||
|
</WidgetColumnBarItem>
|
||||||
|
{hasPermission('files/favorites/read') && (
|
||||||
|
<WidgetColumnBarItem title="Favorites" name="favorites" height="15%">
|
||||||
|
<FavoritesList />
|
||||||
|
</WidgetColumnBarItem>
|
||||||
|
)}
|
||||||
|
</WidgetColumnBar>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -15,23 +15,6 @@ import WidgetColumnBar, { WidgetColumnBarItem } from './WidgetColumnBar';
|
|||||||
import { useFiles } from '../utility/metadataLoaders';
|
import { useFiles } from '../utility/metadataLoaders';
|
||||||
import useHasPermission from '../utility/useHasPermission';
|
import useHasPermission from '../utility/useHasPermission';
|
||||||
|
|
||||||
function ClosedTabsList() {
|
|
||||||
const tabs = useOpenedTabs();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<WidgetsInnerContainer>
|
|
||||||
<AppObjectList
|
|
||||||
list={_.sortBy(
|
|
||||||
tabs.filter((x) => x.closedTime),
|
|
||||||
(x) => -x.closedTime
|
|
||||||
)}
|
|
||||||
AppObjectComponent={ClosedTabAppObject}
|
|
||||||
/>
|
|
||||||
</WidgetsInnerContainer>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function SavedSqlFilesList() {
|
function SavedSqlFilesList() {
|
||||||
const files = useFiles({ folder: 'sql' });
|
const files = useFiles({ folder: 'sql' });
|
||||||
@@ -85,9 +68,6 @@ export default function FilesWidget() {
|
|||||||
const hasPermission = useHasPermission();
|
const hasPermission = useHasPermission();
|
||||||
return (
|
return (
|
||||||
<WidgetColumnBar>
|
<WidgetColumnBar>
|
||||||
<WidgetColumnBarItem title="Recently closed tabs" name="closedTabs" height="20%">
|
|
||||||
<ClosedTabsList />
|
|
||||||
</WidgetColumnBarItem>
|
|
||||||
{hasPermission('files/sql/read') && (
|
{hasPermission('files/sql/read') && (
|
||||||
<WidgetColumnBarItem title="Saved SQL files" name="sqlFiles" height="15%">
|
<WidgetColumnBarItem title="Saved SQL files" name="sqlFiles" height="15%">
|
||||||
<SavedSqlFilesList />
|
<SavedSqlFilesList />
|
||||||
|
|||||||
@@ -14,6 +14,9 @@ import { getDefaultFileFormat } from '../utility/fileformats';
|
|||||||
import getElectron from '../utility/getElectron';
|
import getElectron from '../utility/getElectron';
|
||||||
import AboutModal from '../modals/AboutModal';
|
import AboutModal from '../modals/AboutModal';
|
||||||
import useOpenNewTab from '../utility/useOpenNewTab';
|
import useOpenNewTab from '../utility/useOpenNewTab';
|
||||||
|
import axios from '../utility/axios';
|
||||||
|
import tabs from '../tabs';
|
||||||
|
import uuidv1 from 'uuid/v1';
|
||||||
|
|
||||||
const ToolbarContainer = styled.div`
|
const ToolbarContainer = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -36,6 +39,8 @@ export default function ToolBar({ toolbarPortalRef }) {
|
|||||||
const electron = getElectron();
|
const electron = getElectron();
|
||||||
const markdownManifest = useMarkdownManifest();
|
const markdownManifest = useMarkdownManifest();
|
||||||
|
|
||||||
|
const currentTab = openedTabs.find((x) => x.selected);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
window['dbgate_createNewConnection'] = modalState.open;
|
window['dbgate_createNewConnection'] = modalState.open;
|
||||||
window['dbgate_newQuery'] = newQuery;
|
window['dbgate_newQuery'] = newQuery;
|
||||||
@@ -76,6 +81,31 @@ export default function ToolBar({ toolbarPortalRef }) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const addToFavorite = () => {
|
||||||
|
const tabdata = {};
|
||||||
|
|
||||||
|
const re = new RegExp(`tabdata_(.*)_${currentTab.tabid}`);
|
||||||
|
for (const key in localStorage) {
|
||||||
|
const match = key.match(re);
|
||||||
|
if (!match) continue;
|
||||||
|
if (match[1] == 'editor') continue;
|
||||||
|
tabdata[match[1]] = JSON.parse(localStorage.getItem(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
axios.post('files/save', {
|
||||||
|
folder: 'favorites',
|
||||||
|
file: uuidv1(),
|
||||||
|
format: 'json',
|
||||||
|
data: {
|
||||||
|
title: currentTab.title,
|
||||||
|
icon: currentTab.icon,
|
||||||
|
props: currentTab.props,
|
||||||
|
tabComponent: currentTab.tabComponent,
|
||||||
|
tabdata,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
function openTabFromButton(page) {
|
function openTabFromButton(page) {
|
||||||
if (
|
if (
|
||||||
openedTabs.find(
|
openedTabs.find(
|
||||||
@@ -134,6 +164,14 @@ export default function ToolBar({ toolbarPortalRef }) {
|
|||||||
<ToolbarButton onClick={showImport} icon="icon import">
|
<ToolbarButton onClick={showImport} icon="icon import">
|
||||||
Import data
|
Import data
|
||||||
</ToolbarButton>
|
</ToolbarButton>
|
||||||
|
{!!currentTab &&
|
||||||
|
tabs[currentTab.tabComponent] &&
|
||||||
|
tabs[currentTab.tabComponent].allowAddToFavorites &&
|
||||||
|
tabs[currentTab.tabComponent].allowAddToFavorites(currentTab.props) && (
|
||||||
|
<ToolbarButton onClick={addToFavorite} icon="icon favorite">
|
||||||
|
Add to favorites
|
||||||
|
</ToolbarButton>
|
||||||
|
)}
|
||||||
<ToolbarButton onClick={switchTheme} icon="icon theme">
|
<ToolbarButton onClick={switchTheme} icon="icon theme">
|
||||||
{currentTheme == 'dark' ? 'Light mode' : 'Dark mode'}
|
{currentTheme == 'dark' ? 'Light mode' : 'Dark mode'}
|
||||||
</ToolbarButton>
|
</ToolbarButton>
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import React from 'react';
|
|||||||
import { useCurrentWidget } from '../utility/globalState';
|
import { useCurrentWidget } from '../utility/globalState';
|
||||||
import ArchiveWidget from './ArchiveWidget';
|
import ArchiveWidget from './ArchiveWidget';
|
||||||
import DatabaseWidget from './DatabaseWidget';
|
import DatabaseWidget from './DatabaseWidget';
|
||||||
|
import FavoritesWidget from './FavoritesWidget';
|
||||||
import FilesWidget from './FilesWidget';
|
import FilesWidget from './FilesWidget';
|
||||||
import PluginsWidget from './PluginsWidget';
|
import PluginsWidget from './PluginsWidget';
|
||||||
|
|
||||||
@@ -11,5 +12,6 @@ export default function WidgetContainer() {
|
|||||||
if (currentWidget === 'file') return <FilesWidget />;
|
if (currentWidget === 'file') return <FilesWidget />;
|
||||||
if (currentWidget === 'archive') return <ArchiveWidget />;
|
if (currentWidget === 'archive') return <ArchiveWidget />;
|
||||||
if (currentWidget === 'plugins') return <PluginsWidget />;
|
if (currentWidget === 'plugins') return <PluginsWidget />;
|
||||||
|
if (currentWidget === 'favorites') return <FavoritesWidget />;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,6 +56,11 @@ export default function WidgetIconPanel() {
|
|||||||
name: 'plugins',
|
name: 'plugins',
|
||||||
title: 'Extensions & Plugins',
|
title: 'Extensions & Plugins',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
icon: 'icon favorite',
|
||||||
|
name: 'favorites',
|
||||||
|
title: 'Favorites',
|
||||||
|
},
|
||||||
// {
|
// {
|
||||||
// icon: 'fa-cog',
|
// icon: 'fa-cog',
|
||||||
// name: 'settings',
|
// name: 'settings',
|
||||||
|
|||||||
Reference in New Issue
Block a user