mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-28 06:06:00 +00:00
files widget
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
<script context="module">
|
||||
const getContextMenu = (data, $openedConnections) => () => {
|
||||
const handleRefresh = () => {
|
||||
axios.post('server-connections/refresh', { conid: data._id });
|
||||
axiosInstance.post('server-connections/refresh', { conid: data._id });
|
||||
};
|
||||
const handleDisconnect = () => {
|
||||
openedConnections.update(list => list.filter(x => x != data._id));
|
||||
@@ -42,7 +42,7 @@
|
||||
import _ from 'lodash';
|
||||
import AppObjectCore from './AppObjectCore.svelte';
|
||||
import { currentDatabase, extensions, openedConnections } from '../stores';
|
||||
import axios from '../utility/axios';
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import { filterName } from 'dbgate-datalib';
|
||||
import { showModal } from '../modals/modalTools';
|
||||
import ConnectionModal from '../modals/ConnectionModal.svelte';
|
||||
|
||||
140
packages/web/src/appobj/SavedFileAppObject.svelte
Normal file
140
packages/web/src/appobj/SavedFileAppObject.svelte
Normal file
@@ -0,0 +1,140 @@
|
||||
<script lang="ts" context="module">
|
||||
interface FileTypeHandler {
|
||||
icon: string;
|
||||
format: string;
|
||||
tabComponent: string;
|
||||
folder: string;
|
||||
currentConnection: boolean;
|
||||
}
|
||||
|
||||
const sql: FileTypeHandler = {
|
||||
icon: 'img sql-file',
|
||||
format: 'text',
|
||||
tabComponent: 'QueryTab',
|
||||
folder: 'sql',
|
||||
currentConnection: true,
|
||||
};
|
||||
|
||||
const shell: FileTypeHandler = {
|
||||
icon: 'img shell',
|
||||
format: 'text',
|
||||
tabComponent: 'ShellTab',
|
||||
folder: 'shell',
|
||||
currentConnection: false,
|
||||
};
|
||||
|
||||
const markdown: FileTypeHandler = {
|
||||
icon: 'img markdown',
|
||||
format: 'text',
|
||||
tabComponent: 'MarkdownEditorTab',
|
||||
folder: 'markdown',
|
||||
currentConnection: false,
|
||||
};
|
||||
|
||||
const charts: FileTypeHandler = {
|
||||
icon: 'img chart',
|
||||
format: 'json',
|
||||
tabComponent: 'ChartTab',
|
||||
folder: 'charts',
|
||||
currentConnection: true,
|
||||
};
|
||||
|
||||
const query: FileTypeHandler = {
|
||||
icon: 'img query-design',
|
||||
format: 'json',
|
||||
tabComponent: 'QueryDesignTab',
|
||||
folder: 'query',
|
||||
currentConnection: true,
|
||||
};
|
||||
|
||||
const HANDLERS = {
|
||||
sql,
|
||||
shell,
|
||||
markdown,
|
||||
charts,
|
||||
query,
|
||||
};
|
||||
|
||||
export const extractKey = data => data.file;
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import _ from 'lodash';
|
||||
import ConfirmModal from '../modals/ConfirmModal.svelte';
|
||||
import InputTextModal from '../modals/InputTextModal.svelte';
|
||||
import { showModal } from '../modals/modalTools';
|
||||
|
||||
import { currentDatabase } from '../stores';
|
||||
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import hasPermission from '../utility/hasPermission';
|
||||
import openNewTab from '../utility/openNewTab';
|
||||
|
||||
import AppObjectCore from './AppObjectCore.svelte';
|
||||
|
||||
export let data;
|
||||
|
||||
$: folder = data?.folder;
|
||||
$: handler = HANDLERS[folder] as FileTypeHandler;
|
||||
|
||||
function createMenu() {
|
||||
return [
|
||||
{ text: 'Open', onClick: openTab },
|
||||
hasPermission(`files/${data.folder}/write`) && { text: 'Rename', onClick: handleRename },
|
||||
hasPermission(`files/${data.folder}/write`) && { text: 'Delete', onClick: handleDelete },
|
||||
];
|
||||
}
|
||||
|
||||
const handleDelete = () => {
|
||||
showModal(ConfirmModal, {
|
||||
message: `Really delete file ${data.file}?`,
|
||||
onConfirm: () => {
|
||||
axiosInstance.post('files/delete', data);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const handleRename = () => {
|
||||
showModal(InputTextModal, {
|
||||
value: data.file,
|
||||
label: 'New file name',
|
||||
header: 'Rename file',
|
||||
onConfirm: newFile => {
|
||||
axiosInstance.post('files/rename', { ...data, newFile });
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
async function openTab() {
|
||||
const resp = await axiosInstance.post('files/load', { folder, file: data.file, format: handler.format });
|
||||
|
||||
const connProps: any = {};
|
||||
let tooltip = undefined;
|
||||
|
||||
if (handler.currentConnection) {
|
||||
const connection = _.get($currentDatabase, 'connection') || {};
|
||||
const database = _.get($currentDatabase, 'name');
|
||||
connProps.conid = connection._id;
|
||||
connProps.database = database;
|
||||
tooltip = `${connection.displayName || connection.server}\n${database}`;
|
||||
}
|
||||
|
||||
openNewTab(
|
||||
{
|
||||
title: data.file,
|
||||
icon: handler.icon,
|
||||
tabComponent: handler.tabComponent,
|
||||
tooltip,
|
||||
props: {
|
||||
savedFile: data.file,
|
||||
savedFolder: handler.folder,
|
||||
savedFormat: handler.format,
|
||||
...connProps,
|
||||
},
|
||||
},
|
||||
{ editor: resp.data }
|
||||
);
|
||||
}
|
||||
</script>
|
||||
|
||||
<AppObjectCore {...$$restProps} {data} icon={handler?.icon} title={data?.file} menu={createMenu()} on:click={openTab} />
|
||||
@@ -165,7 +165,7 @@
|
||||
import keycodes from '../utility/keycodes';
|
||||
import { activeTabId, nullStore } from '../stores';
|
||||
import memberStore from '../utility/memberStore';
|
||||
import axios from '../utility/axios';
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import { copyTextToClipboard } from '../utility/clipboard';
|
||||
|
||||
export let onLoadNextData = undefined;
|
||||
@@ -280,7 +280,7 @@
|
||||
}
|
||||
|
||||
export async function reconnect() {
|
||||
await axios.post('database-connections/refresh', { conid, database });
|
||||
await axiosInstance.post('database-connections/refresh', { conid, database });
|
||||
display.reload();
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
async function loadDataPage(props, offset, limit) {
|
||||
const { jslid, display } = props;
|
||||
|
||||
const response = await axios.post('jsldata/get-rows', {
|
||||
const response = await axiosInstance.post('jsldata/get-rows', {
|
||||
jslid,
|
||||
offset,
|
||||
limit,
|
||||
@@ -19,7 +19,7 @@
|
||||
async function loadRowCount(props) {
|
||||
const { jslid } = props;
|
||||
|
||||
const response = await axios.request({
|
||||
const response = await axiosInstance.request({
|
||||
url: 'jsldata/get-stats',
|
||||
method: 'get',
|
||||
params: {
|
||||
@@ -33,7 +33,7 @@
|
||||
<script lang="ts">
|
||||
import _ from 'lodash';
|
||||
|
||||
import axios from '../utility/axios';
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import socket from '../utility/socket';
|
||||
import useEffect from '../utility/useEffect';
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
const sql = display.getPageQuery(offset, limit);
|
||||
|
||||
const response = await axios.request({
|
||||
const response = await axiosInstance.request({
|
||||
url: 'database-connections/query-data',
|
||||
method: 'post',
|
||||
params: {
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
const sql = display.getCountQuery();
|
||||
|
||||
const response = await axios.request({
|
||||
const response = await axiosInstance.request({
|
||||
url: 'database-connections/query-data',
|
||||
method: 'post',
|
||||
params: {
|
||||
@@ -50,7 +50,7 @@
|
||||
import ErrorMessageModal from '../modals/ErrorMessageModal.svelte';
|
||||
import { showModal } from '../modals/modalTools';
|
||||
|
||||
import axios from '../utility/axios';
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import ChangeSetGrider from './ChangeSetGrider';
|
||||
|
||||
import LoadingDataGridCore from './LoadingDataGridCore.svelte';
|
||||
@@ -71,7 +71,7 @@
|
||||
// $: console.log('GRIDER', grider);
|
||||
|
||||
async function handleConfirmSql(sql) {
|
||||
const resp = await axios.request({
|
||||
const resp = await axiosInstance.request({
|
||||
url: 'database-connections/query-data',
|
||||
method: 'post',
|
||||
params: {
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { writable } from 'svelte/store';
|
||||
import FormFieldTemplateLarge from '../modals/FormFieldTemplateLarge.svelte';
|
||||
import FormProviderCore from './FormProviderCore.svelte';
|
||||
|
||||
export let initialValues = {};
|
||||
export let template;
|
||||
export let template = FormFieldTemplateLarge;
|
||||
|
||||
const values = writable(initialValues);
|
||||
</script>
|
||||
|
||||
28
packages/web/src/modals/ConfirmModal.svelte
Normal file
28
packages/web/src/modals/ConfirmModal.svelte
Normal file
@@ -0,0 +1,28 @@
|
||||
<script lang="ts">
|
||||
import FormStyledButton from '../elements/FormStyledButton.svelte';
|
||||
|
||||
import FormProvider from '../forms/FormProvider.svelte';
|
||||
import FormSubmit from '../forms/FormSubmit.svelte';
|
||||
import ModalBase from './ModalBase.svelte';
|
||||
import { closeCurrentModal } from './modalTools';
|
||||
|
||||
export let message;
|
||||
export let onConfirm;
|
||||
</script>
|
||||
|
||||
<FormProvider>
|
||||
<ModalBase {...$$restProps}>
|
||||
{message}
|
||||
|
||||
<svelte:fragment slot="footer">
|
||||
<FormSubmit
|
||||
value="OK"
|
||||
on:click={() => {
|
||||
closeCurrentModal();
|
||||
onConfirm();
|
||||
}}
|
||||
/>
|
||||
<FormStyledButton type="button" value="Close" on:click={closeCurrentModal} />
|
||||
</svelte:fragment>
|
||||
</ModalBase>
|
||||
</FormProvider>
|
||||
@@ -4,7 +4,7 @@
|
||||
import FormProvider from '../forms/FormProvider.svelte';
|
||||
import FormSubmit from '../forms/FormSubmit.svelte';
|
||||
import FontIcon from '../icons/FontIcon.svelte';
|
||||
import axios from '../utility/axios';
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import TabControl from '../elements/TabControl.svelte';
|
||||
import ConnectionModalDriverFields from './ConnectionModalDriverFields.svelte';
|
||||
import ConnectionModalSshTunnelFields from './ConnectionModalSshTunnelFields.svelte';
|
||||
@@ -25,7 +25,7 @@
|
||||
isTesting = true;
|
||||
testIdRef.current += 1;
|
||||
const testid = testIdRef.current;
|
||||
const resp = await axios.post('connections/test', e.detail);
|
||||
const resp = await axiosInstance.post('connections/test', e.detail);
|
||||
if (testIdRef.current != testid) return;
|
||||
|
||||
isTesting = false;
|
||||
@@ -38,7 +38,7 @@
|
||||
}
|
||||
|
||||
async function handleSubmit(e) {
|
||||
axios.post('connections/save', e.detail);
|
||||
axiosInstance.post('connections/save', e.detail);
|
||||
closeCurrentModal();
|
||||
}
|
||||
</script>
|
||||
|
||||
35
packages/web/src/modals/InputTextModal.svelte
Normal file
35
packages/web/src/modals/InputTextModal.svelte
Normal file
@@ -0,0 +1,35 @@
|
||||
<script lang="ts">
|
||||
import FormStyledButton from '../elements/FormStyledButton.svelte';
|
||||
|
||||
import FormProvider from '../forms/FormProvider.svelte';
|
||||
import FormSubmit from '../forms/FormSubmit.svelte';
|
||||
import FormTextField from '../forms/FormTextField.svelte';
|
||||
import ModalBase from './ModalBase.svelte';
|
||||
import { closeCurrentModal } from './modalTools';
|
||||
|
||||
export let header;
|
||||
export let value;
|
||||
export let label;
|
||||
export let onConfirm;
|
||||
|
||||
const handleSubmit = async values => {
|
||||
const { value } = values;
|
||||
closeCurrentModal();
|
||||
onConfirm(value);
|
||||
};
|
||||
</script>
|
||||
|
||||
<FormProvider initialValues={{ value }}>
|
||||
<ModalBase {...$$restProps}>
|
||||
<svelte:fragment slot="header">
|
||||
{header}
|
||||
</svelte:fragment>
|
||||
|
||||
<FormTextField {label} name="value" focused />
|
||||
|
||||
<svelte:fragment slot="footer">
|
||||
<FormSubmit value="OK" on:click={e => handleSubmit(e.detail)} />
|
||||
<FormStyledButton type="button" value="Cancel" on:click={closeCurrentModal} />
|
||||
</svelte:fragment>
|
||||
</ModalBase>
|
||||
</FormProvider>
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts" context="module">
|
||||
const dbgateEnv = {
|
||||
axios,
|
||||
axios: axiosInstance,
|
||||
};
|
||||
|
||||
async function loadPlugins(pluginsDict, installedPlugins) {
|
||||
@@ -8,7 +8,7 @@
|
||||
for (const installed of installedPlugins || []) {
|
||||
if (!_.keys(pluginsDict).includes(installed.name)) {
|
||||
console.log('Loading module', installed.name);
|
||||
const resp = await axios.request({
|
||||
const resp = await axiosInstance.request({
|
||||
method: 'get',
|
||||
url: 'plugins/script',
|
||||
params: {
|
||||
@@ -48,7 +48,7 @@
|
||||
<script lang="ts">
|
||||
import _ from 'lodash';
|
||||
import { extensions } from '../stores';
|
||||
import axios from '../utility/axios';
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import { useInstalledPlugins } from '../utility/metadataLoaders';
|
||||
import { buildFileFormats } from './fileformats';
|
||||
import { buildThemes } from './themes';
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
import useEditorData from '../query/useEditorData';
|
||||
import { activeTabId, extensions, nullStore } from '../stores';
|
||||
import applySqlTemplate from '../utility/applySqlTemplate';
|
||||
import axios from '../utility/axios';
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import { changeTab } from '../utility/common';
|
||||
import { useConnectionInfo } from '../utility/metadataLoaders';
|
||||
import socket from '../utility/socket';
|
||||
@@ -133,7 +133,7 @@
|
||||
|
||||
let sesid = sessionId;
|
||||
if (!sesid) {
|
||||
const resp = await axios.post('sessions/create', {
|
||||
const resp = await axiosInstance.post('sessions/create', {
|
||||
conid,
|
||||
database,
|
||||
});
|
||||
@@ -142,14 +142,14 @@
|
||||
}
|
||||
busy = true;
|
||||
// timerLabel.start();
|
||||
await axios.post('sessions/execute-query', {
|
||||
await axiosInstance.post('sessions/execute-query', {
|
||||
sesid,
|
||||
sql: selectedText || $editorValue,
|
||||
});
|
||||
}
|
||||
|
||||
export async function kill() {
|
||||
await axios.post('sessions/kill', {
|
||||
await axiosInstance.post('sessions/kill', {
|
||||
sesid: sessionId,
|
||||
});
|
||||
sessionId = null;
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
import _ from 'lodash';
|
||||
import { openedConnections, currentDatabase } from '../stores';
|
||||
import axios from './axios';
|
||||
import axiosInstance from './axiosInstance';
|
||||
|
||||
const doServerPing = value => {
|
||||
axios.post('server-connections/ping', { connections: value });
|
||||
axiosInstance.post('server-connections/ping', { connections: value });
|
||||
};
|
||||
|
||||
const doDatabasePing = value => {
|
||||
const database = _.get(value, 'name');
|
||||
const conid = _.get(value, 'connection._id');
|
||||
if (conid && database) {
|
||||
axios.post('database-connections/ping', { conid, database });
|
||||
axiosInstance.post('database-connections/ping', { conid, database });
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
15
packages/web/src/utility/hasPermission.ts
Normal file
15
packages/web/src/utility/hasPermission.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { compilePermissions, testPermission } from 'dbgate-tools';
|
||||
import { useConfig } from './metadataLoaders';
|
||||
|
||||
let compiled = null;
|
||||
|
||||
const config = useConfig();
|
||||
config.subscribe(value => {
|
||||
if (!value) return;
|
||||
const { permissions } = value;
|
||||
compiled = compilePermissions(permissions);
|
||||
});
|
||||
|
||||
export default function hasPermission(tested) {
|
||||
return testPermission(tested, compiled);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import axios from './axios';
|
||||
import axiosInstance from './axiosInstance';
|
||||
import _ from 'lodash';
|
||||
import { cacheGet, cacheSet, getCachedPromise } from './cache';
|
||||
import stableStringify from 'json-stable-stringify';
|
||||
@@ -130,7 +130,7 @@ async function getCore(loader, args) {
|
||||
const key = stableStringify({ url, ...params });
|
||||
|
||||
async function doLoad() {
|
||||
const resp = await axios.request({
|
||||
const resp = await axiosInstance.request({
|
||||
method: 'get',
|
||||
url,
|
||||
params,
|
||||
@@ -154,7 +154,7 @@ function useCore(loader, args) {
|
||||
subscribe: onChange => {
|
||||
async function handleReload() {
|
||||
async function doLoad() {
|
||||
const resp = await axios.request({
|
||||
const resp = await axiosInstance.request({
|
||||
method: 'get',
|
||||
params,
|
||||
url,
|
||||
@@ -331,7 +331,7 @@ export function getConfig() {
|
||||
return getCore(configLoader, {}) || {};
|
||||
}
|
||||
export function useConfig() {
|
||||
return useCore(configLoader, {}) || {};
|
||||
return useCore(configLoader, {});
|
||||
}
|
||||
|
||||
export function getPlatformInfo() {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import _ from 'lodash';
|
||||
import axios from './axios';
|
||||
import axiosInstance from './axiosInstance';
|
||||
import { writable } from 'svelte/store';
|
||||
|
||||
export default function useFetch({ url, data = undefined, params = undefined, defaultValue = undefined, ...config }) {
|
||||
const result = writable(defaultValue);
|
||||
|
||||
axios
|
||||
axiosInstance
|
||||
.request({
|
||||
method: 'get',
|
||||
params,
|
||||
|
||||
12
packages/web/src/widgets/FilesWidget.svelte
Normal file
12
packages/web/src/widgets/FilesWidget.svelte
Normal file
@@ -0,0 +1,12 @@
|
||||
<script lang="ts">
|
||||
import SavedFilesList from './SavedFilesList.svelte';
|
||||
|
||||
import WidgetColumnBar from './WidgetColumnBar.svelte';
|
||||
import WidgetColumnBarItem from './WidgetColumnBarItem.svelte';
|
||||
</script>
|
||||
|
||||
<WidgetColumnBar>
|
||||
<WidgetColumnBarItem title="Saved files" name="files">
|
||||
<SavedFilesList />
|
||||
</WidgetColumnBarItem>
|
||||
</WidgetColumnBar>
|
||||
28
packages/web/src/widgets/SavedFilesList.svelte
Normal file
28
packages/web/src/widgets/SavedFilesList.svelte
Normal file
@@ -0,0 +1,28 @@
|
||||
<script lang="ts">
|
||||
import _ from 'lodash';
|
||||
|
||||
import AppObjectList from '../appobj/AppObjectList.svelte';
|
||||
import * as savedFileAppObject from '../appobj/SavedFileAppObject.svelte';
|
||||
import { useFiles } from '../utility/metadataLoaders';
|
||||
|
||||
import WidgetsInnerContainer from './WidgetsInnerContainer.svelte';
|
||||
|
||||
const sqlFiles = useFiles({ folder: 'sql' });
|
||||
const shellFiles = useFiles({ folder: 'shell' });
|
||||
const markdownFiles = useFiles({ folder: 'markdown' });
|
||||
const chartFiles = useFiles({ folder: 'charts' });
|
||||
const queryFiles = useFiles({ folder: 'query' });
|
||||
|
||||
$: files = [
|
||||
...($sqlFiles || []),
|
||||
...($shellFiles || []),
|
||||
...($markdownFiles || []),
|
||||
...($chartFiles || []),
|
||||
...($queryFiles || []),
|
||||
];
|
||||
|
||||
</script>
|
||||
|
||||
<WidgetsInnerContainer>
|
||||
<AppObjectList list={files} module={savedFileAppObject} groupFunc={data => _.startCase(data.folder)} />
|
||||
</WidgetsInnerContainer>
|
||||
@@ -10,7 +10,7 @@
|
||||
import SubColumnParamList from '../appobj/SubColumnParamList.svelte';
|
||||
import { chevronExpandIcon } from '../icons/expandIcons';
|
||||
import ErrorInfo from '../elements/ErrorInfo.svelte';
|
||||
import axios from '../utility/axios';
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import LoadingInfo from '../elements/LoadingInfo.svelte';
|
||||
|
||||
export let conid;
|
||||
@@ -31,7 +31,7 @@
|
||||
);
|
||||
|
||||
const handleRefreshDatabase = () => {
|
||||
axios.post('database-connections/refresh', { conid, database });
|
||||
axiosInstance.post('database-connections/refresh', { conid, database });
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { selectedWidget } from '../stores';
|
||||
import DatabaseWidget from './DatabaseWidget.svelte';
|
||||
import FilesWidget from './FilesWidget.svelte';
|
||||
|
||||
|
||||
</script>
|
||||
@@ -8,3 +9,6 @@
|
||||
{#if $selectedWidget == 'database'}
|
||||
<DatabaseWidget />
|
||||
{/if}
|
||||
{#if $selectedWidget == 'file'}
|
||||
<FilesWidget />
|
||||
{/if}
|
||||
|
||||
Reference in New Issue
Block a user