Merge pull request #62 from agnosticeng/feat/add-editor-actions
This commit is contained in:
103
package-lock.json
generated
103
package-lock.json
generated
@@ -25,7 +25,8 @@
|
||||
"d3": "^7.9.0",
|
||||
"dayjs": "^1.11.13",
|
||||
"normalize.css": "^8.0.1",
|
||||
"p-debounce": "^4.0.0"
|
||||
"p-debounce": "^4.0.0",
|
||||
"sql-formatter": "^15.4.9"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sveltejs/adapter-static": "^3.0.8",
|
||||
@@ -1567,6 +1568,12 @@
|
||||
"acorn": ">=8.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/argparse": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
||||
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
|
||||
"license": "Python-2.0"
|
||||
},
|
||||
"node_modules/aria-query": {
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.1.tgz",
|
||||
@@ -2080,6 +2087,12 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/discontinuous-range": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz",
|
||||
"integrity": "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/esbuild": {
|
||||
"version": "0.24.2",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.2.tgz",
|
||||
@@ -2166,6 +2179,18 @@
|
||||
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/get-stdin": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz",
|
||||
"integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/globalyzer": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/globalyzer/-/globalyzer-0.1.0.tgz",
|
||||
@@ -2246,6 +2271,12 @@
|
||||
"@jridgewell/sourcemap-codec": "^1.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/moo": {
|
||||
"version": "0.5.2",
|
||||
"resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz",
|
||||
"integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==",
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/mri": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
|
||||
@@ -2292,6 +2323,34 @@
|
||||
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/nearley": {
|
||||
"version": "2.20.1",
|
||||
"resolved": "https://registry.npmjs.org/nearley/-/nearley-2.20.1.tgz",
|
||||
"integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"commander": "^2.19.0",
|
||||
"moo": "^0.5.0",
|
||||
"railroad-diagrams": "^1.0.0",
|
||||
"randexp": "0.4.6"
|
||||
},
|
||||
"bin": {
|
||||
"nearley-railroad": "bin/nearley-railroad.js",
|
||||
"nearley-test": "bin/nearley-test.js",
|
||||
"nearley-unparse": "bin/nearley-unparse.js",
|
||||
"nearleyc": "bin/nearleyc.js"
|
||||
},
|
||||
"funding": {
|
||||
"type": "individual",
|
||||
"url": "https://nearley.js.org/#give-to-nearley"
|
||||
}
|
||||
},
|
||||
"node_modules/nearley/node_modules/commander": {
|
||||
"version": "2.20.3",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
||||
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/normalize.css": {
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/normalize.css/-/normalize.css-8.0.1.tgz",
|
||||
@@ -2370,6 +2429,25 @@
|
||||
"svelte": "^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0"
|
||||
}
|
||||
},
|
||||
"node_modules/railroad-diagrams": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz",
|
||||
"integrity": "sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==",
|
||||
"license": "CC0-1.0"
|
||||
},
|
||||
"node_modules/randexp": {
|
||||
"version": "0.4.6",
|
||||
"resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz",
|
||||
"integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"discontinuous-range": "1.0.0",
|
||||
"ret": "~0.1.10"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.12"
|
||||
}
|
||||
},
|
||||
"node_modules/readdirp": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz",
|
||||
@@ -2384,6 +2462,15 @@
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/ret": {
|
||||
"version": "0.1.15",
|
||||
"resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
|
||||
"integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.12"
|
||||
}
|
||||
},
|
||||
"node_modules/robust-predicates": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz",
|
||||
@@ -2485,6 +2572,20 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/sql-formatter": {
|
||||
"version": "15.4.9",
|
||||
"resolved": "https://registry.npmjs.org/sql-formatter/-/sql-formatter-15.4.9.tgz",
|
||||
"integrity": "sha512-5vmt2HlCAVozxsBZuXWkAki/KGawaK+b5GG5x+BtXOFVpN/8cqppblFUxHl4jxdA0cvo14lABhM+KBnrUapOlw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"argparse": "^2.0.1",
|
||||
"get-stdin": "=8.0.0",
|
||||
"nearley": "^2.20.1"
|
||||
},
|
||||
"bin": {
|
||||
"sql-formatter": "bin/sql-formatter-cli.cjs"
|
||||
}
|
||||
},
|
||||
"node_modules/style-mod": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.2.tgz",
|
||||
|
||||
@@ -31,7 +31,8 @@
|
||||
"d3": "^7.9.0",
|
||||
"dayjs": "^1.11.13",
|
||||
"normalize.css": "^8.0.1",
|
||||
"p-debounce": "^4.0.0"
|
||||
"p-debounce": "^4.0.0",
|
||||
"sql-formatter": "^15.4.9"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sveltejs/adapter-static": "^3.0.8",
|
||||
|
||||
50
src/lib/icons/ClipboardText.svelte
Normal file
50
src/lib/icons/ClipboardText.svelte
Normal file
@@ -0,0 +1,50 @@
|
||||
<script lang="ts">
|
||||
import type { SvelteHTMLElements } from 'svelte/elements';
|
||||
|
||||
interface Props extends Omit<SvelteHTMLElements['svg'], 'width' | 'height'> {
|
||||
size?: string | number | null;
|
||||
}
|
||||
|
||||
let { size = 24, ...rest }: Props = $props();
|
||||
</script>
|
||||
|
||||
<svg viewBox="0 0 256 256" width={size} height={size} {...rest} data-name="clipboard-text">
|
||||
<line
|
||||
x1="96"
|
||||
y1="152"
|
||||
x2="160"
|
||||
y2="152"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="16"
|
||||
/>
|
||||
<line
|
||||
x1="96"
|
||||
y1="120"
|
||||
x2="160"
|
||||
y2="120"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="16"
|
||||
/>
|
||||
<path
|
||||
d="M160,40h40a8,8,0,0,1,8,8V216a8,8,0,0,1-8,8H56a8,8,0,0,1-8-8V48a8,8,0,0,1,8-8H96"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="16"
|
||||
/>
|
||||
<path
|
||||
d="M88,72V64a40,40,0,0,1,80,0v8Z"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="16"
|
||||
/>
|
||||
</svg>
|
||||
31
src/lib/icons/Copy.svelte
Normal file
31
src/lib/icons/Copy.svelte
Normal file
@@ -0,0 +1,31 @@
|
||||
<script lang="ts">
|
||||
import type { SvelteHTMLElements } from 'svelte/elements';
|
||||
|
||||
interface Props extends Omit<SvelteHTMLElements['svg'], 'width' | 'height'> {
|
||||
size?: string | number | null;
|
||||
}
|
||||
|
||||
let { size = 24, ...rest }: Props = $props();
|
||||
</script>
|
||||
|
||||
<svg viewBox="0 0 256 256" width={size} height={size} {...rest} data-name="copy">
|
||||
<polyline
|
||||
points="168 168 216 168 216 40 88 40 88 88"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="16"
|
||||
/>
|
||||
<rect
|
||||
x="40"
|
||||
y="88"
|
||||
width="128"
|
||||
height="128"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="16"
|
||||
/>
|
||||
</svg>
|
||||
102
src/lib/icons/MagicWand.svelte
Normal file
102
src/lib/icons/MagicWand.svelte
Normal file
@@ -0,0 +1,102 @@
|
||||
<script lang="ts">
|
||||
import type { SvelteHTMLElements } from 'svelte/elements';
|
||||
|
||||
interface Props extends Omit<SvelteHTMLElements['svg'], 'width' | 'height'> {
|
||||
size?: string | number | null;
|
||||
}
|
||||
|
||||
let { size = 24, ...rest }: Props = $props();
|
||||
</script>
|
||||
|
||||
<svg viewBox="0 0 256 256" width={size} height={size} {...rest} data-name="magic-wand">
|
||||
<line
|
||||
x1="216"
|
||||
y1="128"
|
||||
x2="216"
|
||||
y2="176"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="16"
|
||||
/>
|
||||
<line
|
||||
x1="192"
|
||||
y1="152"
|
||||
x2="240"
|
||||
y2="152"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="16"
|
||||
/>
|
||||
<line
|
||||
x1="80"
|
||||
y1="40"
|
||||
x2="80"
|
||||
y2="88"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="16"
|
||||
/>
|
||||
<line
|
||||
x1="56"
|
||||
y1="64"
|
||||
x2="104"
|
||||
y2="64"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="16"
|
||||
/>
|
||||
<line
|
||||
x1="168"
|
||||
y1="184"
|
||||
x2="168"
|
||||
y2="216"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="16"
|
||||
/>
|
||||
<line
|
||||
x1="152"
|
||||
y1="200"
|
||||
x2="184"
|
||||
y2="200"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="16"
|
||||
/>
|
||||
<line
|
||||
x1="144"
|
||||
y1="80"
|
||||
x2="176"
|
||||
y2="112"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="16"
|
||||
/>
|
||||
<rect
|
||||
x="21.49"
|
||||
y="105.37"
|
||||
width="213.02"
|
||||
height="45.25"
|
||||
rx="8"
|
||||
transform="translate(-53.02 128) rotate(-45)"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="16"
|
||||
/>
|
||||
</svg>
|
||||
@@ -11,6 +11,9 @@
|
||||
import { setAppContext } from '$lib/context';
|
||||
import { tablesToSQLNamespace } from '$lib/editor';
|
||||
import Bars3 from '$lib/icons/Bars3.svelte';
|
||||
import ClipboardText from '$lib/icons/ClipboardText.svelte';
|
||||
import Copy from '$lib/icons/Copy.svelte';
|
||||
import MagicWand from '$lib/icons/MagicWand.svelte';
|
||||
import PanelBottom from '$lib/icons/PanelBottom.svelte';
|
||||
import PanelLeft from '$lib/icons/PanelLeft.svelte';
|
||||
import Play from '$lib/icons/Play.svelte';
|
||||
@@ -26,6 +29,7 @@
|
||||
import { ClickHouseDialect, extendsDialectKeywords } from '@agnosticeng/editor/dialect';
|
||||
import { SplitPane } from '@rich_harris/svelte-split-pane';
|
||||
import debounce from 'p-debounce';
|
||||
import { format } from 'sql-formatter';
|
||||
import { tick, type ComponentProps } from 'svelte';
|
||||
import type { PageData } from './$types';
|
||||
|
||||
@@ -98,6 +102,7 @@
|
||||
}
|
||||
|
||||
if (event.key === 'Enter' && event.metaKey) handleExec();
|
||||
if (event.key === 'i' && event.metaKey) handleFormat();
|
||||
}
|
||||
|
||||
async function handleCreateQuery({
|
||||
@@ -227,6 +232,18 @@
|
||||
bottomPanelTab = 'logs';
|
||||
}
|
||||
});
|
||||
|
||||
function handleFormat() {
|
||||
if (!currentTab.contents) return;
|
||||
|
||||
currentTab.contents = format(currentTab.contents, {
|
||||
keywordCase: 'lower',
|
||||
tabWidth: 2,
|
||||
useTabs: true,
|
||||
expressionWidth: 80,
|
||||
language: 'postgresql'
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:window onkeydown={handleKeyDown} bind:innerWidth={screenWidth} />
|
||||
@@ -302,6 +319,22 @@
|
||||
</button>
|
||||
</div>
|
||||
<div class="workspace-actions">
|
||||
<button
|
||||
class="action"
|
||||
onclick={() =>
|
||||
navigator.clipboard.readText().then((t) => (currentTab.contents = t))}
|
||||
>
|
||||
<ClipboardText size="12" />
|
||||
</button>
|
||||
<button
|
||||
class="action"
|
||||
onclick={() => navigator.clipboard.writeText(currentTab.contents)}
|
||||
>
|
||||
<Copy size="12" />
|
||||
</button>
|
||||
<button class="action" onclick={handleFormat}>
|
||||
<MagicWand size="12" />
|
||||
</button>
|
||||
<button class="action" onclick={handleSaveQuery} disabled={!canSave}>
|
||||
<Save size="12" />
|
||||
</button>
|
||||
|
||||
Reference in New Issue
Block a user