diff --git a/src/code_lens_provider/virtualSqlCodeLensProvider.ts b/src/code_lens_provider/virtualSqlCodeLensProvider.ts
index 78ad9a604..0e93854e4 100644
--- a/src/code_lens_provider/virtualSqlCodeLensProvider.ts
+++ b/src/code_lens_provider/virtualSqlCodeLensProvider.ts
@@ -34,7 +34,10 @@ export class VirtualSqlCodeLensProvider implements CodeLensProvider {
token: CancellationToken,
): CodeLens[] | Thenable {
// Enable this code lens only for adhoc query files created using command: dbtPowerUser.createSqlFile
- if (document.uri.scheme !== "untitled" && document.languageId !== "sql") {
+ if (
+ document.uri.scheme !== "untitled" &&
+ document.languageId !== "jinja-sql"
+ ) {
return [];
}
diff --git a/src/commands/index.ts b/src/commands/index.ts
index 0749d2a20..86fa97834 100644
--- a/src/commands/index.ts
+++ b/src/commands/index.ts
@@ -539,77 +539,81 @@ export class VSCodeCommands implements Disposable {
this.dbtTerminal.logLine(`Error=${e}`);
}
}),
- commands.registerCommand("dbtPowerUser.createSqlFile", async () => {
- try {
- const project =
- await this.queryManifestService.getOrPickProjectFromWorkspace();
- if (!project) {
- window.showErrorMessage("No dbt project selected.");
- return;
- }
+ commands.registerCommand(
+ "dbtPowerUser.createSqlFile",
+ async ({ code, fileName }: { code?: string; fileName?: string }) => {
+ try {
+ const project =
+ await this.queryManifestService.getOrPickProjectFromWorkspace();
+ if (!project) {
+ window.showErrorMessage("No dbt project selected.");
+ return;
+ }
- const uri = Uri.parse(
- `${project.projectRoot}/poweruser-${getFormattedDateTime()}.sql`,
- ).with({ scheme: "untitled" });
- const annotationDecoration: TextEditorDecorationType =
- window.createTextEditorDecorationType({
- rangeBehavior: DecorationRangeBehavior.OpenOpen,
- });
+ const fileNamePrefix = fileName || "poweruser";
+ const uri = Uri.parse(
+ `${project.projectRoot}/${fileNamePrefix}-${getFormattedDateTime()}.sql`,
+ ).with({ scheme: "untitled" });
+ const annotationDecoration: TextEditorDecorationType =
+ window.createTextEditorDecorationType({
+ rangeBehavior: DecorationRangeBehavior.OpenOpen,
+ });
- const contentText =
- "Enter your query here and execute it just like any dbt model file. This file is unsaved, you can either save it to your project or save it as a bookmark for later usage or share it with your team members.";
+ const contentText =
+ "Enter your query here and execute it just like any dbt model file. This file is unsaved, you can either save it to your project or save it as a bookmark for later usage or share it with your team members.";
- const decorations = [
- {
- renderOptions: {
- before: {
- color: "#666666",
- contentText,
- // hacking to add more css properties
- width: "90%;display: block;white-space: pre-line;",
+ const decorations = [
+ {
+ renderOptions: {
+ before: {
+ color: "#666666",
+ contentText,
+ // hacking to add more css properties
+ width: "90%;display: block;white-space: pre-line;",
+ },
},
+ range: new Range(2, 0, 2, 0),
},
- range: new Range(2, 0, 2, 0),
- },
- ];
+ ];
- workspace.openTextDocument(uri).then((doc) => {
- // set this to sql language so we can bind codelens and other features
- languages.setTextDocumentLanguage(doc, "sql");
- window.showTextDocument(doc).then((editor) => {
- editor.edit((editBuilder) => {
- const entireDocumentRange = new Range(
- doc.positionAt(0),
- doc.positionAt(doc.getText().length),
- );
- editBuilder.replace(entireDocumentRange, "\n");
+ workspace.openTextDocument(uri).then((doc) => {
+ // set this to sql language so we can bind codelens and other features
+ languages.setTextDocumentLanguage(doc, "jinja-sql");
+ window.showTextDocument(doc).then((editor) => {
+ editor.edit((editBuilder) => {
+ const entireDocumentRange = new Range(
+ doc.positionAt(0),
+ doc.positionAt(doc.getText().length),
+ );
+ editBuilder.replace(entireDocumentRange, code || "\n");
- editor.setDecorations(annotationDecoration, decorations);
- setTimeout(() => {
- commands.executeCommand("cursorMove", {
- to: "up",
- by: "line",
- value: 1,
- });
- }, 0);
- const disposable = workspace.onDidChangeTextDocument((e) => {
- const activeEditor = window.activeTextEditor;
- if (activeEditor && e.document === editor.document) {
- if (activeEditor.document.getText().trim()) {
- activeEditor.setDecorations(annotationDecoration, []);
- disposable.dispose();
+ editor.setDecorations(annotationDecoration, decorations);
+ setTimeout(() => {
+ commands.executeCommand("cursorMove", {
+ to: "up",
+ by: "line",
+ value: 1,
+ });
+ }, 0);
+ const disposable = workspace.onDidChangeTextDocument((e) => {
+ const activeEditor = window.activeTextEditor;
+ if (activeEditor && e.document === editor.document) {
+ if (activeEditor.document.getText().trim()) {
+ activeEditor.setDecorations(annotationDecoration, []);
+ disposable.dispose();
+ }
}
- }
+ });
});
});
});
- });
- } catch (e) {
- const message = (e as Error).message;
- this.dbtTerminal.error("createSqlFile", message, e, true);
- window.showErrorMessage(message);
- }
- }),
+ } catch (e) {
+ const message = (e as Error).message;
+ this.dbtTerminal.error("createSqlFile", message, e, true);
+ window.showErrorMessage(message);
+ }
+ },
+ ),
commands.registerCommand("dbtPowerUser.sqlLineage", async () => {
window.withProgress(
{
diff --git a/src/dbtPowerUserExtension.ts b/src/dbtPowerUserExtension.ts
index 33885c147..7fc9b222f 100644
--- a/src/dbtPowerUserExtension.ts
+++ b/src/dbtPowerUserExtension.ts
@@ -32,7 +32,7 @@ export class DBTPowerUserExtension implements Disposable {
static DBT_SQL_SELECTOR = [
{ language: "jinja-sql", scheme: "file" },
{ language: "sql", scheme: "file" },
- { language: "sql", scheme: "untitled" },
+ { language: "jinja-sql", scheme: "untitled" },
];
static DBT_YAML_SELECTOR = [
{ language: "yaml", scheme: "file" },
diff --git a/src/webview_provider/docsEditPanel.ts b/src/webview_provider/docsEditPanel.ts
index ea73c3cc2..903df47fc 100644
--- a/src/webview_provider/docsEditPanel.ts
+++ b/src/webview_provider/docsEditPanel.ts
@@ -339,7 +339,7 @@ export class DocsEditViewPanel implements WebviewViewProvider {
const testFullName: string = namespace ? `${namespace}.${name}` : name;
const columnTestConfigFromYml = getColumnTestConfigFromYml(
- existingColumn.tests,
+ existingColumn?.tests,
kwargs,
testFullName,
);
diff --git a/src/webview_provider/queryResultPanel.ts b/src/webview_provider/queryResultPanel.ts
index 547840c4c..ee84653fa 100644
--- a/src/webview_provider/queryResultPanel.ts
+++ b/src/webview_provider/queryResultPanel.ts
@@ -92,6 +92,7 @@ enum InboundCommand {
GetQueryTabData = "getQueryTabData",
RunAdhocQuery = "runAdhocQuery",
ViewResultSet = "viewResultSet",
+ OpenCodeInEditor = "openCodeInEditor",
}
interface RecInfo {
@@ -323,11 +324,24 @@ export class QueryResultPanel extends AltimateWebviewProvider {
}
}
+ private async handleOpenCodeInEditor(message: {
+ code: string;
+ name: string;
+ }) {
+ commands.executeCommand("dbtPowerUser.createSqlFile", {
+ code: message.code,
+ name: message.name,
+ });
+ }
+
/** Primary interface for WebviewView inbound communication */
private setupWebviewHooks() {
this._panel!.webview.onDidReceiveMessage(
async (message) => {
switch (message.command) {
+ case InboundCommand.OpenCodeInEditor:
+ this.handleOpenCodeInEditor(message);
+ break;
case InboundCommand.ViewResultSet:
const queryHistoryData = message.queryHistory;
this._queryTabData = {
diff --git a/webview_panels/src/assets/icons/index.tsx b/webview_panels/src/assets/icons/index.tsx
index cb35fcdd6..025e8f7dc 100644
--- a/webview_panels/src/assets/icons/index.tsx
+++ b/webview_panels/src/assets/icons/index.tsx
@@ -155,3 +155,7 @@ export const SearchIcon = (props: HTMLAttributes): JSX.Element => (
export const FileCodeIcon = (
props: HTMLAttributes,
): JSX.Element => ;
+
+export const OpenNewIcon = (
+ props: HTMLAttributes,
+): JSX.Element => ;
diff --git a/webview_panels/src/lib/altimate/altimate-components.d.ts b/webview_panels/src/lib/altimate/altimate-components.d.ts
index 78afa3822..43ecfc86a 100644
--- a/webview_panels/src/lib/altimate/altimate-components.d.ts
+++ b/webview_panels/src/lib/altimate/altimate-components.d.ts
@@ -1,6 +1,5 @@
-///
-
import { JSX as JSX_2 } from "react/jsx-runtime";
+import { ReactNode } from "react";
export declare const ApiHelper: {
get: (
@@ -21,6 +20,7 @@ export declare const CodeBlock: ({
fileName,
theme,
showLineNumbers,
+ titleActions,
}: Props_4) => JSX.Element;
export declare interface Conversation {
@@ -131,6 +131,7 @@ declare interface Props_4 {
fileName?: string;
showLineNumbers?: boolean;
theme?: "vs" | "vsc-dark-plus" | "solarizedLight";
+ titleActions?: ReactNode;
}
declare interface User {
diff --git a/webview_panels/src/lib/altimate/main.js b/webview_panels/src/lib/altimate/main.js
index f3fb6956d..ef87bd87d 100644
--- a/webview_panels/src/lib/altimate/main.js
+++ b/webview_panels/src/lib/altimate/main.js
@@ -40,12 +40,12 @@ var Sn = /* @__PURE__ */ ((e) => (
typeof globalThis < "u"
? globalThis
: typeof window < "u"
- ? window
- : typeof global < "u"
- ? global
- : typeof self < "u"
- ? self
- : {};
+ ? window
+ : typeof global < "u"
+ ? global
+ : typeof self < "u"
+ ? self
+ : {};
function $t(e) {
return e && e.__esModule && Object.prototype.hasOwnProperty.call(e, "default")
? e.default
@@ -882,12 +882,12 @@ Check the top-level render call using <` +
h === null
? (de = "null")
: qt(h)
- ? (de = "array")
- : h !== void 0 && h.$$typeof === t
- ? ((de = "<" + (G(h.type) || "Unknown") + " />"),
- (ne =
- " Did you accidentally export a JSX literal instead of a component?"))
- : (de = typeof h),
+ ? (de = "array")
+ : h !== void 0 && h.$$typeof === t
+ ? ((de = "<" + (G(h.type) || "Unknown") + " />"),
+ (ne =
+ " Did you accidentally export a JSX literal instead of a component?"))
+ : (de = typeof h),
_(
"React.jsx: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: %s.%s",
de,
@@ -2560,10 +2560,10 @@ var Lr = { exports: {} };
R && L
? u.SplitType.both
: R
- ? u.SplitType.head
- : L
- ? u.SplitType.tail
- : u.SplitType.none),
+ ? u.SplitType.head
+ : L
+ ? u.SplitType.tail
+ : u.SplitType.none),
H.setAttribute("data-" + d.DATASET_SPLIT_TYPE, x),
A.parentNode.replaceChild(G, A),
H
@@ -2751,8 +2751,8 @@ const pi = (e) => {
? void 0
: o.querySelector("td:nth-child(3)")
: (n = On()) == null
- ? void 0
- : n.firstChild
+ ? void 0
+ : n.firstChild
: Tn();
},
vi = (e) => {
@@ -3098,8 +3098,8 @@ var Rn = {
return e.finalized_ || !Ne(n)
? n
: n === Zt(e.base_, t)
- ? (Jt(e), (e.copy_[t] = gn(n, e)))
- : n;
+ ? (Jt(e), (e.copy_[t] = gn(n, e)))
+ : n;
},
has(e, t) {
return t in Le(e);
@@ -3191,10 +3191,10 @@ function Ri(e, t, o) {
? "value" in n
? n.value
: // This is a very special case, if the prop is a getter defined by the
- // prototype, we should invoke it with the draft as context!
- (r = n.get) == null
- ? void 0
- : r.call(e.draft_)
+ // prototype, we should invoke it with the draft as context!
+ (r = n.get) == null
+ ? void 0
+ : r.call(e.draft_)
: void 0;
}
function Yr(e, t) {
@@ -3316,8 +3316,8 @@ function gn(e, t) {
const o = Bt(e)
? ze("MapSet").proxyMap_(e, t)
: Ht(e)
- ? ze("MapSet").proxySet_(e, t)
- : Di(e, t);
+ ? ze("MapSet").proxySet_(e, t)
+ : Di(e, t);
return (t ? t.scope_ : qr()).drafts_.push(o), o;
}
function Kr(e) {
@@ -5527,11 +5527,17 @@ const Va = (e) => {
fileName: o,
theme: n = "vs",
showLineNumbers: r,
+ titleActions: i,
}) =>
/* @__PURE__ */ w.jsxs(jt, {
className: es.codeblock,
children: [
- o ? /* @__PURE__ */ w.jsx(kr, { children: o }) : null,
+ o
+ ? /* @__PURE__ */ w.jsxs(kr, {
+ className: "d-flex justify-content-between",
+ children: [o, " ", i],
+ })
+ : null,
/* @__PURE__ */ w.jsx(Mt, {
children: /* @__PURE__ */ w.jsx(oi, {
showLineNumbers: r,
@@ -6261,10 +6267,10 @@ function yr(e) {
pt(e, n, o[n]);
})
: Object.getOwnPropertyDescriptors
- ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(o))
- : mr(Object(o)).forEach(function (n) {
- Object.defineProperty(e, n, Object.getOwnPropertyDescriptor(o, n));
- });
+ ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(o))
+ : mr(Object(o)).forEach(function (n) {
+ Object.defineProperty(e, n, Object.getOwnPropertyDescriptor(o, n));
+ });
}
return e;
}
@@ -6336,10 +6342,10 @@ function Ke(e) {
pt(e, n, o[n]);
})
: Object.getOwnPropertyDescriptors
- ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(o))
- : Er(Object(o)).forEach(function (n) {
- Object.defineProperty(e, n, Object.getOwnPropertyDescriptor(o, n));
- });
+ ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(o))
+ : Er(Object(o)).forEach(function (n) {
+ Object.defineProperty(e, n, Object.getOwnPropertyDescriptor(o, n));
+ });
}
return e;
}
@@ -6479,10 +6485,10 @@ function st(e) {
pt(e, n, o[n]);
})
: Object.getOwnPropertyDescriptors
- ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(o))
- : br(Object(o)).forEach(function (n) {
- Object.defineProperty(e, n, Object.getOwnPropertyDescriptor(o, n));
- });
+ ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(o))
+ : br(Object(o)).forEach(function (n) {
+ Object.defineProperty(e, n, Object.getOwnPropertyDescriptor(o, n));
+ });
}
return e;
}
@@ -7465,19 +7471,19 @@ Valid keys: ` +
return C === "symbol"
? !0
: D
- ? D["@@toStringTag"] === "Symbol" ||
- (typeof Symbol == "function" && D instanceof Symbol)
- : !1;
+ ? D["@@toStringTag"] === "Symbol" ||
+ (typeof Symbol == "function" && D instanceof Symbol)
+ : !1;
}
function T(C) {
var D = typeof C;
return Array.isArray(C)
? "array"
: C instanceof RegExp
- ? "object"
- : I(D, C)
- ? "symbol"
- : D;
+ ? "object"
+ : I(D, C)
+ ? "symbol"
+ : D;
}
function x(C) {
if (typeof C > "u" || C === null) return "" + C;
@@ -8303,10 +8309,10 @@ function Fr(e) {
ee(e, n, o[n]);
})
: Object.getOwnPropertyDescriptors
- ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(o))
- : Nr(Object(o)).forEach(function (n) {
- Object.defineProperty(e, n, Object.getOwnPropertyDescriptor(o, n));
- });
+ ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(o))
+ : Nr(Object(o)).forEach(function (n) {
+ Object.defineProperty(e, n, Object.getOwnPropertyDescriptor(o, n));
+ });
}
return e;
}
@@ -8790,10 +8796,10 @@ function De(e) {
ee(e, n, o[n]);
})
: Object.getOwnPropertyDescriptors
- ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(o))
- : jr(Object(o)).forEach(function (n) {
- Object.defineProperty(e, n, Object.getOwnPropertyDescriptor(o, n));
- });
+ ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(o))
+ : jr(Object(o)).forEach(function (n) {
+ Object.defineProperty(e, n, Object.getOwnPropertyDescriptor(o, n));
+ });
}
return e;
}
@@ -10903,27 +10909,27 @@ const ic = /* @__PURE__ */ $t(oc),
return e
? /* @__PURE__ */ w.jsx("div", { children: "Loading..." })
: !(t != null && t.catalog_presigned_url) ||
- !(t != null && t.manifest_presigned_url)
- ? /* @__PURE__ */ w.jsx("div", {
- children: "Unable to load required artifacts. Please try again.",
- })
- : /* @__PURE__ */ w.jsxs("div", {
- children: [
- /* @__PURE__ */ w.jsxs("div", {
- className: "d-flex justify-content-end mb-2",
- children: [
- /* @__PURE__ */ w.jsx(Pc, {}),
- /* @__PURE__ */ w.jsx(ss, {}),
- ],
- }),
- /* @__PURE__ */ w.jsx(Ac, {}),
- /* @__PURE__ */ w.jsx(Nc, {
- shareDetails: t,
- onSelectionEnd: i,
- }),
- r ? /* @__PURE__ */ w.jsx(is, { pos: r, onAddComment: a }) : null,
- ],
- });
+ !(t != null && t.manifest_presigned_url)
+ ? /* @__PURE__ */ w.jsx("div", {
+ children: "Unable to load required artifacts. Please try again.",
+ })
+ : /* @__PURE__ */ w.jsxs("div", {
+ children: [
+ /* @__PURE__ */ w.jsxs("div", {
+ className: "d-flex justify-content-end mb-2",
+ children: [
+ /* @__PURE__ */ w.jsx(Pc, {}),
+ /* @__PURE__ */ w.jsx(ss, {}),
+ ],
+ }),
+ /* @__PURE__ */ w.jsx(Ac, {}),
+ /* @__PURE__ */ w.jsx(Nc, {
+ shareDetails: t,
+ onSelectionEnd: i,
+ }),
+ r ? /* @__PURE__ */ w.jsx(is, { pos: r, onAddComment: a }) : null,
+ ],
+ });
},
jc = Fc,
Mc = ({ shareId: e, userId: t, conversationGroupId: o, source: n }) =>
diff --git a/webview_panels/src/modules/queryPanel/QueryPanelDefaultView.tsx b/webview_panels/src/modules/queryPanel/QueryPanelDefaultView.tsx
index 5c38a82e6..5f7df5c51 100644
--- a/webview_panels/src/modules/queryPanel/QueryPanelDefaultView.tsx
+++ b/webview_panels/src/modules/queryPanel/QueryPanelDefaultView.tsx
@@ -1,4 +1,4 @@
-import { Stack } from "@uicore";
+import { Alert, Stack } from "@uicore";
import HelpContent from "./components/help/HelpContent";
import QueryLimit from "./components/queryLimit/QueryLimit";
@@ -21,6 +21,13 @@ const QueryPanelDefaultView = (): JSX.Element => {
You can also rerun queries directly from your history or bookmarks.
+
+
+ This feature is in private beta. If you are interested, please{" "}
+ contact us to
+ try it out!
+
+
diff --git a/webview_panels/src/modules/queryPanel/components/queryPanelBookmarks/BookmarkPrivacySettingButton.tsx b/webview_panels/src/modules/queryPanel/components/queryPanelBookmarks/BookmarkPrivacySettingButton.tsx
index c217f1eb9..873bdd281 100644
--- a/webview_panels/src/modules/queryPanel/components/queryPanelBookmarks/BookmarkPrivacySettingButton.tsx
+++ b/webview_panels/src/modules/queryPanel/components/queryPanelBookmarks/BookmarkPrivacySettingButton.tsx
@@ -32,7 +32,8 @@ const BookmarkPrivacySettingButton = ({
const { refetchBookmarks } = useQueryPanelCommonActions();
useEffect(() => {
- setPrivacy(bookmark.privacy);
+ // Modify the setting when opening the popover to avoid one extra action from user
+ setPrivacy(bookmark.privacy === "private" ? "public" : "private");
}, [bookmark.privacy]);
const saveSettings = async () => {
diff --git a/webview_panels/src/modules/queryPanel/components/queryPanelBookmarks/QueryPanelBookmarks.tsx b/webview_panels/src/modules/queryPanel/components/queryPanelBookmarks/QueryPanelBookmarks.tsx
index ae27a5580..ef3d05663 100644
--- a/webview_panels/src/modules/queryPanel/components/queryPanelBookmarks/QueryPanelBookmarks.tsx
+++ b/webview_panels/src/modules/queryPanel/components/queryPanelBookmarks/QueryPanelBookmarks.tsx
@@ -2,11 +2,12 @@ import styles from "../../querypanel.module.scss";
import { Stack, CodeBlock, Label, IconButton } from "@uicore";
import { useEffect, useState } from "react";
import { QueryBookmark } from "@modules/queryPanel/context/types";
-import { ChevronRightIcon } from "@assets/icons";
+import { ChevronRightIcon, OpenNewIcon } from "@assets/icons";
import BookmarkAccordion from "./BookmarkAccordion";
import useQueryPanelState from "@modules/queryPanel/useQueryPanelState";
import { QueryPanelTitleTabState } from "../QueryPanelContents/types";
import useQueryPanelCommonActions from "@modules/queryPanel/useQueryPanelCommonActions";
+import { executeRequestInAsync } from "@modules/app/requestExecutor";
const QueryPanelBookmarks = (): JSX.Element => {
const [activeBookmark, setActiveBookmark] = useState(
@@ -32,6 +33,13 @@ const QueryPanelBookmarks = (): JSX.Element => {
setActiveBookmark(null);
};
+ const handleOpenNewClick = () => {
+ executeRequestInAsync("openCodeInEditor", {
+ code: activeBookmark?.raw_sql,
+ name: activeBookmark?.name,
+ });
+ };
+
const tags = (queryBookmarksTagsFromDB ?? []).map((t) => t.tag);
return (
{
{activeBookmark.adapter_type}
-
- {activeBookmark.privacy}
+
+ {activeBookmark.privacy === "private" ? "No" : "Yes"}
@@ -85,6 +93,16 @@ const QueryPanelBookmarks = (): JSX.Element => {
language="sql"
fileName="Code"
showLineNumbers
+ titleActions={
+
+
+
+
+
+ }
/>
) : null}
diff --git a/webview_panels/src/modules/queryPanel/components/queryPanelQueryHistory/QueryPanelHistory.tsx b/webview_panels/src/modules/queryPanel/components/queryPanelQueryHistory/QueryPanelHistory.tsx
index 343fdd27b..0ae1a31b1 100644
--- a/webview_panels/src/modules/queryPanel/components/queryPanelQueryHistory/QueryPanelHistory.tsx
+++ b/webview_panels/src/modules/queryPanel/components/queryPanelQueryHistory/QueryPanelHistory.tsx
@@ -12,7 +12,7 @@ import styles from "../../querypanel.module.scss";
import { useEffect, useMemo, useState } from "react";
import { QueryHistory } from "@modules/queryPanel/context/types";
import Filters, { QueryFilters } from "../filters/Filters";
-import { ChevronRightIcon, NoHistoryIcon } from "@assets/icons";
+import { ChevronRightIcon, NoHistoryIcon, OpenNewIcon } from "@assets/icons";
import { executeRequestInAsync } from "@modules/app/requestExecutor";
import useQueryPanelCommonActions from "@modules/queryPanel/useQueryPanelCommonActions";
import AutoCollapsingNotification from "@modules/AutoCollapsingNotification/AutoCollapsingNotification";
@@ -61,6 +61,10 @@ const QueryPanelHistory = (): JSX.Element => {
});
};
+ const handleOpenNewClick = () => {
+ executeRequestInAsync("openCodeInEditor", { code: activeHistory?.rawSql });
+ };
+
return (
@@ -142,6 +146,13 @@ const QueryPanelHistory = (): JSX.Element => {
language="sql"
fileName="Code"
showLineNumbers
+ titleActions={
+
+
+
+
+
+ }
/>
) : null}
diff --git a/webview_panels/src/uiCore/components/codeblock/index.tsx b/webview_panels/src/uiCore/components/codeblock/index.tsx
index 1e3c8a453..68ee6983c 100644
--- a/webview_panels/src/uiCore/components/codeblock/index.tsx
+++ b/webview_panels/src/uiCore/components/codeblock/index.tsx
@@ -2,18 +2,21 @@ import useAppContext from "@modules/app/useAppContext";
import { Themes } from "@modules/app/types";
import { CodeBlock as CodeblockLib } from "@lib";
import classes from "./codeblock.module.scss";
+import { ReactNode } from "react";
interface Props {
code: string;
language: Parameters["0"]["language"];
fileName?: string;
showLineNumbers?: boolean;
+ titleActions?: ReactNode;
}
const CodeBlockComponent = ({
code,
language,
fileName,
showLineNumbers,
+ titleActions,
}: Props): JSX.Element => {
const {
state: { theme },
@@ -27,6 +30,7 @@ const CodeBlockComponent = ({
fileName={fileName}
theme={codeBlockTheme}
language={language}
+ titleActions={titleActions}
/>
);
diff --git a/webview_panels/src/uiCore/components/iconButton/IconButton.tsx b/webview_panels/src/uiCore/components/iconButton/IconButton.tsx
index 2096d9185..c4f0617bf 100644
--- a/webview_panels/src/uiCore/components/iconButton/IconButton.tsx
+++ b/webview_panels/src/uiCore/components/iconButton/IconButton.tsx
@@ -5,9 +5,9 @@ import classes from "./styles.module.scss";
interface Props extends ButtonHTMLAttributes {
color?: string;
}
-const IconButton = ({ title, ...props }: Props): JSX.Element => {
+const IconButton = (props: Props): JSX.Element => {
return (
-
+