Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 31 additions & 17 deletions src/components/SQLQueryBuilder/resource-picker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,16 @@ function useDebouncedValue<T>(value: T, delay: number): T {
return v;
}

function useCandidates(search: string, enabled = true) {
function useCandidates(
search: string,
enabled = true,
kinds: CandidateKind[] = ["ViewDefinition", "SQLQuery"],
) {
const client = useAidboxClient();
const debouncedSearch = useDebouncedValue(search, 200);
const kindsKey = kinds.slice().sort().join(",");
return useQuery<CandidateOption[]>({
queryKey: ["sqlquery-depends-on-candidates", debouncedSearch],
queryKey: ["sqlquery-depends-on-candidates", debouncedSearch, kindsKey],
enabled,
queryFn: async () => {
const baseParams: Array<[string, string]> = [
Expand All @@ -83,20 +88,25 @@ function useCandidates(search: string, enabled = true) {
["_sort", "-_createdAt"],
];
if (debouncedSearch) baseParams.push(["_ilike", debouncedSearch]);
const want = (k: CandidateKind) => kinds.includes(k);
const [vd, lib] = await Promise.all([
client.request<Bundle>({
method: "GET",
url: "/fhir/ViewDefinition",
params: baseParams,
}),
client.request<Bundle>({
method: "GET",
url: "/fhir/Library",
params: [...baseParams, ["type", SQL_QUERY_TYPE_TOKEN]],
}),
want("ViewDefinition")
? client.request<Bundle>({
method: "GET",
url: "/fhir/ViewDefinition",
params: baseParams,
})
: null,
want("SQLQuery")
? client.request<Bundle>({
method: "GET",
url: "/fhir/Library",
params: [...baseParams, ["type", SQL_QUERY_TYPE_TOKEN]],
})
: null,
]);
const out: CandidateOption[] = [];
if (vd.isOk()) {
if (vd?.isOk()) {
for (const entry of vd.value.resource.entry ?? []) {
const r = entry.resource as unknown as RawCandidate;
out.push({
Expand All @@ -111,7 +121,7 @@ function useCandidates(search: string, enabled = true) {
});
}
}
if (lib.isOk()) {
if (lib?.isOk()) {
for (const entry of lib.value.resource.entry ?? []) {
const r = entry.resource as unknown as RawCandidate;
const relatedArtifacts = (r.relatedArtifact ?? []).flatMap((ra) =>
Expand Down Expand Up @@ -144,15 +154,19 @@ export function ResourcePicker({
value,
onChange,
className,
kinds,
placeholder,
}: {
value: string | undefined;
onChange: (reference: string) => void;
className?: string;
kinds?: CandidateKind[];
placeholder?: string;
}) {
const [open, setOpen] = React.useState(false);
const [search, setSearch] = React.useState("");
const { data: candidates = [] } = useCandidates(search, open);
const { data: allCandidates = [] } = useCandidates("", open);
const { data: candidates = [] } = useCandidates(search, open, kinds);
const { data: allCandidates = [] } = useCandidates("", open, kinds);
const commandRef = React.useRef<HTMLDivElement>(null);
const lookupByUrl = React.useMemo(() => {
const map = new Map<string, CandidateOption>();
Expand Down Expand Up @@ -182,7 +196,7 @@ export function ResourcePicker({
onClick={(e) => e.stopPropagation()}
>
<span className={`truncate ${value ? "" : "text-text-tertiary"}`}>
{value || "Select view or query…"}
{value || placeholder || "Select view or query…"}
</span>
<ChevronDown className="size-4 shrink-0 opacity-50" />
</HSComp.Button>
Expand Down
29 changes: 26 additions & 3 deletions src/components/notebook-editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,18 @@ import {
normalizeMarkdown,
RestCellView,
SqlCellView,
SqlQueryCellView,
ViewDefinitionCellView,
} from "../routes/notebooks.$id";
import { ConfirmDialog } from "./confirm-dialog";

export type CellType = "rest" | "sql" | "markdown" | "rpc";
export type CellType =
| "rest"
| "sql"
| "markdown"
| "rpc"
| "view-definition"
| "sql-query";

export type EditableCell = {
id: string;
Expand All @@ -36,16 +44,19 @@ export type EditableNotebook = {

const CELL_TYPES: { value: CellType; label: string }[] = [
{ value: "rest", label: "REST" },
{ value: "rpc", label: "RPC" },
{ value: "sql", label: "SQL" },
{ value: "markdown", label: "Markdown" },
{ value: "view-definition", label: "ViewDefinition" },
{ value: "sql-query", label: "SQLQuery" },
];

const DEFAULT_CELL_VALUE: Record<CellType, string> = {
rest: "GET /fhir/Patient",
rpc: "POST /rpc\ncontent-type: application/json\n\n{}",
sql: "SELECT 1;",
markdown: "",
"view-definition": "",
"sql-query": "",
};

function genCellId(): string {
Expand All @@ -57,7 +68,7 @@ function genCellId(): string {
export function emptyNotebook(): EditableNotebook {
return {
name: "",
description: "",
description: "Description",
cells: [],
};
}
Expand Down Expand Up @@ -170,6 +181,18 @@ function CellWrapper({
onValueChange={handleValue}
onResultChange={handleResult}
/>
) : cell.type === "view-definition" ? (
<ViewDefinitionCellView
cell={cellLike}
onValueChange={handleValue}
onResultChange={handleResult}
/>
) : cell.type === "sql-query" ? (
<SqlQueryCellView
cell={cellLike}
onValueChange={handleValue}
onResultChange={handleResult}
/>
) : cell.type === "markdown" ? (
<MarkdownEditCell cell={cell} onChange={handleValue} />
) : (
Expand Down
Loading