mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-30 13:53:59 +00:00
export chart to HTML
This commit is contained in:
@@ -1,6 +1,8 @@
|
|||||||
|
const uuidv1 = require('uuid/v1');
|
||||||
const fs = require('fs-extra');
|
const fs = require('fs-extra');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const { filesdir, archivedir, resolveArchiveFolder } = require('../utility/directories');
|
const { filesdir, archivedir, resolveArchiveFolder, uploadsdir } = require('../utility/directories');
|
||||||
|
const getChartExport = require('../utility/getChartExport');
|
||||||
const hasPermission = require('../utility/hasPermission');
|
const hasPermission = require('../utility/hasPermission');
|
||||||
const socket = require('../utility/socket');
|
const socket = require('../utility/socket');
|
||||||
const scheduler = require('./scheduler');
|
const scheduler = require('./scheduler');
|
||||||
@@ -114,4 +116,12 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
exportChart_meta: 'post',
|
||||||
|
async exportChart({ title, config }) {
|
||||||
|
const html = getChartExport(title, config);
|
||||||
|
const fileName = `${uuidv1()}.html`;
|
||||||
|
await fs.writeFile(path.join(uploadsdir(), fileName), html);
|
||||||
|
return fileName;
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
38
packages/api/src/utility/getChartExport.js
Normal file
38
packages/api/src/utility/getChartExport.js
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
const getChartExport = (title, config) => {
|
||||||
|
return `<html>
|
||||||
|
<meta charset='utf-8'>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
${title ? `<title>${title}</title>` : ''}
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.6.0/chart.min.js" integrity="sha512-GMGzUEevhWh8Tc/njS0bDpwgxdCJLQBWG3Z2Ct+JGOpVnEmjvNx6ts4v6A2XJf1HOrtOsfhv3hBKpK9kE5z8AQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js" integrity="sha512-qTXRIMyZIFb8iQcfjXWCO8+M5Tbc38Qi5WzdPOYZHIlZpzBHG3L3by84BBBOiRGiEb7KKtAOAs5qYdUiZiQNNQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-adapter-moment/1.0.0/chartjs-adapter-moment.min.js" integrity="sha512-oh5t+CdSBsaVVAvxcZKy3XJdP7ZbYUBSRCXDTVn0ODewMDDNnELsrG9eDm8rVZAQg7RsDD/8K3MjPAFB13o6eA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const config = ${JSON.stringify(config)};
|
||||||
|
|
||||||
|
function showChart() {
|
||||||
|
document.getElementById('myImage').style.display = "none";
|
||||||
|
|
||||||
|
const myChart = new Chart(
|
||||||
|
document.getElementById('myChart'),
|
||||||
|
config
|
||||||
|
);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
</html>
|
||||||
|
|
||||||
|
<body onload="showChart()">
|
||||||
|
<img src="img1.png" id="myImage" />
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<canvas id="myChart"></canvas>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>`;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = getChartExport;
|
||||||
@@ -1,18 +1,39 @@
|
|||||||
<script lang="ts" context="module">
|
<script lang="ts" context="module">
|
||||||
import Chart from 'chart.js/auto';
|
import Chart from 'chart.js/auto';
|
||||||
import 'chartjs-adapter-moment';
|
import 'chartjs-adapter-moment';
|
||||||
|
|
||||||
|
const getCurrentEditor = () => getActiveComponent('ChartCore');
|
||||||
|
|
||||||
|
registerCommand({
|
||||||
|
id: 'chart.export',
|
||||||
|
category: 'Chart',
|
||||||
|
toolbarName: 'Export',
|
||||||
|
name: 'Export chart',
|
||||||
|
icon: 'icon report',
|
||||||
|
toolbar: true,
|
||||||
|
isRelatedToTab: true,
|
||||||
|
onClick: () => getCurrentEditor().exportChart(),
|
||||||
|
testEnabled: () => getCurrentEditor() != null,
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { onMount, afterUpdate, onDestroy } from 'svelte';
|
import { onMount, afterUpdate, onDestroy } from 'svelte';
|
||||||
|
import registerCommand from '../commands/registerCommand';
|
||||||
|
import axiosInstance from '../utility/axiosInstance';
|
||||||
|
|
||||||
import contextMenu from '../utility/contextMenu';
|
import contextMenu, { getContextMenu, registerMenu } from '../utility/contextMenu';
|
||||||
|
import createActivator, { getActiveComponent } from '../utility/createActivator';
|
||||||
|
import resolveApi from '../utility/resolveApi';
|
||||||
|
|
||||||
export let data;
|
export let data;
|
||||||
|
export let title;
|
||||||
export let type = 'line';
|
export let type = 'line';
|
||||||
export let options = {};
|
export let options = {};
|
||||||
export let plugins = {};
|
// export let plugins = {};
|
||||||
export let menu;
|
// export let menu;
|
||||||
|
|
||||||
|
export const activator = createActivator('ChartCore', true);
|
||||||
|
|
||||||
let chart = null;
|
let chart = null;
|
||||||
let domChart;
|
let domChart;
|
||||||
@@ -21,10 +42,7 @@
|
|||||||
chart = new Chart(domChart, {
|
chart = new Chart(domChart, {
|
||||||
type,
|
type,
|
||||||
data,
|
data,
|
||||||
options: {
|
options,
|
||||||
...options,
|
|
||||||
plugins,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -32,10 +50,7 @@
|
|||||||
if (!chart) return;
|
if (!chart) return;
|
||||||
chart.data = data;
|
chart.data = data;
|
||||||
chart.type = type;
|
chart.type = type;
|
||||||
chart.options = {
|
chart.options = options;
|
||||||
...options,
|
|
||||||
plugins,
|
|
||||||
};
|
|
||||||
// chart.plugins = plugins;
|
// chart.plugins = plugins;
|
||||||
chart.update();
|
chart.update();
|
||||||
});
|
});
|
||||||
@@ -43,6 +58,23 @@
|
|||||||
onDestroy(() => {
|
onDestroy(() => {
|
||||||
chart = null;
|
chart = null;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export async function exportChart() {
|
||||||
|
const resp = await axiosInstance.post('files/export-chart', {
|
||||||
|
title,
|
||||||
|
config: {
|
||||||
|
type,
|
||||||
|
data,
|
||||||
|
options,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
window.open(`${resolveApi()}/uploads/get?file=${resp.data}`, '_blank');
|
||||||
|
}
|
||||||
|
|
||||||
|
registerMenu({ command: 'chart.export', tag: 'export' });
|
||||||
|
|
||||||
|
const menu = getContextMenu();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<canvas bind:this={domChart} {...$$restProps} use:contextMenu={menu} />
|
<canvas bind:this={domChart} {...$$restProps} use:contextMenu={menu} />
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
export let conid;
|
export let conid;
|
||||||
export let database;
|
export let database;
|
||||||
export let sql;
|
export let sql;
|
||||||
export let menu;
|
// export let menu;
|
||||||
|
|
||||||
let availableColumnNames = [];
|
let availableColumnNames = [];
|
||||||
let error = null;
|
let error = null;
|
||||||
@@ -151,7 +151,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<svelte:fragment slot="2">
|
<svelte:fragment slot="2">
|
||||||
<DataChart data={data || loadedData} {menu} />
|
<DataChart data={data || loadedData} />
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
</HorizontalSplitter>
|
</HorizontalSplitter>
|
||||||
</FormProviderCore>
|
</FormProviderCore>
|
||||||
|
|||||||
@@ -130,7 +130,7 @@
|
|||||||
import { currentThemeDefinition } from '../stores';
|
import { currentThemeDefinition } from '../stores';
|
||||||
|
|
||||||
export let data;
|
export let data;
|
||||||
export let menu;
|
// export let menu;
|
||||||
|
|
||||||
const { values } = getFormContext();
|
const { values } = getFormContext();
|
||||||
|
|
||||||
@@ -163,9 +163,8 @@
|
|||||||
height={clientHeight}
|
height={clientHeight}
|
||||||
data={chartData[0]}
|
data={chartData[0]}
|
||||||
type={$values.chartType}
|
type={$values.chartType}
|
||||||
options={chartData[1]}
|
title={$values.chartTitle}
|
||||||
plugins={chartData[2]}
|
options={{ ...chartData[1], plugins: chartData[2] }}
|
||||||
{menu}
|
|
||||||
/>
|
/>
|
||||||
{/key}
|
{/key}
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
@@ -11,6 +11,18 @@
|
|||||||
|
|
||||||
undoRedo: true,
|
undoRedo: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
registerCommand({
|
||||||
|
id: 'chart.export',
|
||||||
|
category: 'Chart',
|
||||||
|
toolbarName: 'Export',
|
||||||
|
name: 'Export chart',
|
||||||
|
icon: 'icon report',
|
||||||
|
toolbar: true,
|
||||||
|
isRelatedToTab: true,
|
||||||
|
onClick: () => getCurrentEditor().exportChart(),
|
||||||
|
testEnabled: () => getCurrentEditor() != null,
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
@@ -18,6 +30,7 @@
|
|||||||
import { derived } from 'svelte/store';
|
import { derived } from 'svelte/store';
|
||||||
import ChartEditor from '../charts/ChartEditor.svelte';
|
import ChartEditor from '../charts/ChartEditor.svelte';
|
||||||
import invalidateCommands from '../commands/invalidateCommands';
|
import invalidateCommands from '../commands/invalidateCommands';
|
||||||
|
import registerCommand from '../commands/registerCommand';
|
||||||
import { registerFileCommands } from '../commands/stdCommands';
|
import { registerFileCommands } from '../commands/stdCommands';
|
||||||
|
|
||||||
import ErrorInfo from '../elements/ErrorInfo.svelte';
|
import ErrorInfo from '../elements/ErrorInfo.svelte';
|
||||||
@@ -25,8 +38,11 @@
|
|||||||
import LoadingInfo from '../elements/LoadingInfo.svelte';
|
import LoadingInfo from '../elements/LoadingInfo.svelte';
|
||||||
|
|
||||||
import useEditorData from '../query/useEditorData';
|
import useEditorData from '../query/useEditorData';
|
||||||
|
import axiosInstance from '../utility/axiosInstance';
|
||||||
|
import { getContextMenu, registerMenu } from '../utility/contextMenu';
|
||||||
import createActivator, { getActiveComponent } from '../utility/createActivator';
|
import createActivator, { getActiveComponent } from '../utility/createActivator';
|
||||||
import createUndoReducer from '../utility/createUndoReducer';
|
import createUndoReducer from '../utility/createUndoReducer';
|
||||||
|
import resolveApi from '../utility/resolveApi';
|
||||||
|
|
||||||
export let tabid;
|
export let tabid;
|
||||||
export let conid;
|
export let conid;
|
||||||
@@ -90,15 +106,14 @@
|
|||||||
dispatchModel({ type: 'redo' });
|
dispatchModel({ type: 'redo' });
|
||||||
}
|
}
|
||||||
|
|
||||||
function createMenu() {
|
registerMenu(
|
||||||
return [
|
{ command: 'chart.save' },
|
||||||
{ command: 'chart.save' },
|
{ command: 'chart.saveAs' },
|
||||||
{ command: 'chart.saveAs' },
|
{ placeTag: 'export' },
|
||||||
{ divider: true },
|
{ divider: true },
|
||||||
{ command: 'chart.undo' },
|
{ command: 'chart.undo' },
|
||||||
{ command: 'chart.redo' },
|
{ command: 'chart.redo' }
|
||||||
];
|
);
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if $editorState.isLoading}
|
{#if $editorState.isLoading}
|
||||||
@@ -112,6 +127,5 @@
|
|||||||
sql={$modelState.value && $modelState.value.sql}
|
sql={$modelState.value && $modelState.value.sql}
|
||||||
{conid}
|
{conid}
|
||||||
{database}
|
{database}
|
||||||
menu={createMenu}
|
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
Reference in New Issue
Block a user