From 27134b891994097fc5024cd5e1fe03a5ea19bd64 Mon Sep 17 00:00:00 2001 From: Michael Gartner Date: Wed, 29 Nov 2023 22:30:59 -0600 Subject: [PATCH] addCommand "Create Query Block" and "Preview" kb shortcut (#178) * addCommand "Create Query Block" * add preview keyboard shortcut for QueryEditor * Create Query Block command fixes * move preview to addCommand via CustomEvent * rm unused import * 1.14.0 * update docs * update docs again --- docs/query-builder.md | 2 +- package-lock.json | 4 +- package.json | 2 +- src/components/QueryEditor.tsx | 19 ++++++++ src/components/QueryPage.tsx | 10 ++--- src/index.ts | 79 ++++++++++++++++++++++++++++++++++ 6 files changed, 107 insertions(+), 9 deletions(-) diff --git a/docs/query-builder.md b/docs/query-builder.md index e226b48f..8affbf12 100644 --- a/docs/query-builder.md +++ b/docs/query-builder.md @@ -10,7 +10,7 @@ These queries are far more powerful than vanilla Roam queries, as it taps into R The above UI is available as a block component. This allows you to create several on a page, wherever on the page you want. -To create one, simply add `{{query block}}` to any block on the page. +To create one, simply add `{{query block}}` to any block on the page or use the `Create Query Block` from the Roam Command Palette. ## Query Pages diff --git a/package-lock.json b/package-lock.json index 7ef60249..0eb12cf2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "query-builder", - "version": "1.13.0", + "version": "1.14.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "query-builder", - "version": "1.13.0", + "version": "1.14.0", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 43b8e95c..cb30305b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "query-builder", - "version": "1.13.0", + "version": "1.14.0", "description": "Introduces new user interfaces for building queries in Roam", "main": "./build/main.js", "author": { diff --git a/src/components/QueryEditor.tsx b/src/components/QueryEditor.tsx index 67eff564..508cb7e2 100644 --- a/src/components/QueryEditor.tsx +++ b/src/components/QueryEditor.tsx @@ -436,6 +436,7 @@ const getConditionByUid = ( type QueryEditorComponent = (props: { parentUid: string; onQuery?: () => void; + setHasResults?: () => void; hideCustomSwitch?: boolean; showAlias?: boolean; }) => JSX.Element; @@ -443,9 +444,27 @@ type QueryEditorComponent = (props: { const QueryEditor: QueryEditorComponent = ({ parentUid, onQuery, + setHasResults, hideCustomSwitch, showAlias, }) => { + useEffect(() => { + const previewQuery = ((e: CustomEvent) => { + if (parentUid !== e.detail) return; + if (setHasResults) setHasResults(); + }) as EventListener; + document.body.addEventListener( + "roamjs-query-builder:fire-query", + previewQuery + ); + + return () => { + document.body.removeEventListener( + "roamjs-query-builder:fire-query", + previewQuery + ); + }; + }, [setHasResults, parentUid]); const [conditionLabels, setConditionLabels] = useState( () => new Set(getConditionLabels()) ); diff --git a/src/components/QueryPage.tsx b/src/components/QueryPage.tsx index 762272c5..b605a3d2 100644 --- a/src/components/QueryPage.tsx +++ b/src/components/QueryPage.tsx @@ -31,11 +31,7 @@ type QueryPageComponent = (props: { type Props = Parameters[0]; -const QueryPage = ({ - pageUid, - isEditBlock, - showAlias, -}: Props) => { +const QueryPage = ({ pageUid, isEditBlock, showAlias }: Props) => { const extensionAPI = useExtensionAPI(); const hideMetadata = useMemo( () => !!extensionAPI && !!extensionAPI.settings.get("hide-metadata"), @@ -159,6 +155,10 @@ const QueryPage = ({ setHasResults(true); setIsEdit(false); }} + setHasResults={() => { + setHasResults(true); + onRefresh(); + }} showAlias={showAlias} /> diff --git a/src/index.ts b/src/index.ts index 306d599a..47eb8db0 100644 --- a/src/index.ts +++ b/src/index.ts @@ -43,6 +43,8 @@ import getUids from "roamjs-components/dom/getUids"; import { render as renderMessageBlock } from "./components/MessageBlock"; import getBlockProps, { json } from "./utils/getBlockProps"; import resolveQueryBuilderRef from "./utils/resolveQueryBuilderRef"; +import getBlockUidFromTarget from "roamjs-components/dom/getBlockUidFromTarget"; +import { render as renderToast } from "roamjs-components/components/Toast"; const loadedElsewhere = document.currentScript ? document.currentScript.getAttribute("data-source") === "discourse-graph" @@ -606,6 +608,83 @@ svg.rs-svg-container { }) ), }); + extensionAPI.ui.commandPalette.addCommand({ + label: "Create Query Block", + callback: async () => { + const uid = window.roamAlphaAPI.ui.getFocusedBlock()?.["block-uid"]; + if (!uid) { + renderToast({ + id: "query-builder-create-block", + content: "Must be focused on a block to create a Query Block", + }); + return; + } + + // setTimeout is needed because sometimes block is left blank + setTimeout(async () => { + await updateBlock({ + uid, + text: "{{query block}}", + open: false, + }); + }, 200); + + await createBlock({ + node: { + text: "scratch", + children: [ + { + text: "custom", + }, + { + text: "selections", + }, + { + text: "conditions", + children: [ + { + text: "clause", + children: [ + { + text: "source", + children: [{ text: "node" }], + }, + { + text: "relation", + }, + ], + }, + ], + }, + ], + }, + parentUid: uid, + }); + document.querySelector("body")?.click(); + // TODO replace with document.body.dispatchEvent(new CustomEvent) + setTimeout(() => { + const el = document.querySelector(`.roam-block[id*="${uid}"]`); + const conditionEl = el?.querySelector( + ".roamjs-query-condition-relation" + ); + const conditionInput = conditionEl?.querySelector( + "input" + ) as HTMLInputElement; + conditionInput?.focus(); + }, 200); + }, + }); + + extensionAPI.ui.commandPalette.addCommand({ + label: "Preview Current Query Builder Results", + callback: () => { + const target = document.activeElement as HTMLElement; + const uid = getBlockUidFromTarget(target); + document.body.dispatchEvent( + new CustomEvent("roamjs-query-builder:fire-query", { detail: uid }) + ); + }, + }); const renderCustomBlockView = ({ view,