feat: hypertables object type with runtime availability gating in Objects view (Task 5)
This commit is contained in:
@@ -22,10 +22,6 @@ interface ObjectExplorerPageProps {
|
|||||||
sidebarMode?: boolean;
|
sidebarMode?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const OBJECT_TYPE_OPTIONS = (Object.keys(TYPE_LABELS) as ObjectType[]).map(
|
|
||||||
(t) => ({ value: t, label: TYPE_LABELS[t] }),
|
|
||||||
);
|
|
||||||
|
|
||||||
/** Natural plural for empty-state copy, derived from SINGULAR_LABELS with known irregulars mapped explicitly. */
|
/** Natural plural for empty-state copy, derived from SINGULAR_LABELS with known irregulars mapped explicitly. */
|
||||||
function emptyPlural(type: ObjectType): string {
|
function emptyPlural(type: ObjectType): string {
|
||||||
const singular = SINGULAR_LABELS[type];
|
const singular = SINGULAR_LABELS[type];
|
||||||
@@ -75,6 +71,7 @@ function typeToDdlType(type: ObjectType): string {
|
|||||||
sequences: "sequence",
|
sequences: "sequence",
|
||||||
enums: "enum",
|
enums: "enum",
|
||||||
extensions: "extension",
|
extensions: "extension",
|
||||||
|
hypertables: "table",
|
||||||
indexes: "index",
|
indexes: "index",
|
||||||
constraints: "constraint",
|
constraints: "constraint",
|
||||||
roles: "role",
|
roles: "role",
|
||||||
@@ -125,6 +122,19 @@ export function ObjectExplorerPage({
|
|||||||
const changesQueue = useDbViewerStore((s) => s.changesQueue);
|
const changesQueue = useDbViewerStore((s) => s.changesQueue);
|
||||||
const openObjectTab = useDbViewerStore((s) => s.openObjectTab);
|
const openObjectTab = useDbViewerStore((s) => s.openObjectTab);
|
||||||
const refreshTree = useDbViewerStore((s) => s.refreshTree);
|
const refreshTree = useDbViewerStore((s) => s.refreshTree);
|
||||||
|
const hypertablesAvailable = useDbViewerStore((s) => s.hypertablesAvailable);
|
||||||
|
const setHypertablesAvailable = useDbViewerStore((s) => s.setHypertablesAvailable);
|
||||||
|
// Build the dropdown from the full object-type union, gating hypertables
|
||||||
|
// on confirmed TimescaleDB availability (visibleObjectTypes in ObjectTree
|
||||||
|
// is scoped to that tree's smaller type set).
|
||||||
|
const objectTypeOptions = useMemo(() => {
|
||||||
|
const all = Object.keys(TYPE_LABELS) as ObjectType[];
|
||||||
|
const visible =
|
||||||
|
hypertablesAvailable === true
|
||||||
|
? all
|
||||||
|
: all.filter((t) => t !== "hypertables");
|
||||||
|
return visible.map((t) => ({ value: t, label: TYPE_LABELS[t] }));
|
||||||
|
}, [hypertablesAvailable]);
|
||||||
|
|
||||||
// Use store for persistence, but allow re-fetching when schema changes
|
// Use store for persistence, but allow re-fetching when schema changes
|
||||||
const [items, setItems] = useState<AnyObject[] | null>(null);
|
const [items, setItems] = useState<AnyObject[] | null>(null);
|
||||||
@@ -218,6 +228,23 @@ export function ObjectExplorerPage({
|
|||||||
}
|
}
|
||||||
}, [currentSchema, fetch]);
|
}, [currentSchema, fetch]);
|
||||||
|
|
||||||
|
// Probe TimescaleDB availability once per connection so the hypertables
|
||||||
|
// object type only appears in the dropdown when it is actually supported.
|
||||||
|
useEffect(() => {
|
||||||
|
let cancelled = false;
|
||||||
|
(async () => {
|
||||||
|
try {
|
||||||
|
const res = await cmd.getHypertables(connectionId);
|
||||||
|
if (!cancelled) setHypertablesAvailable(res.available);
|
||||||
|
} catch {
|
||||||
|
if (!cancelled) setHypertablesAvailable(false);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
return () => {
|
||||||
|
cancelled = true;
|
||||||
|
};
|
||||||
|
}, [connectionId, setHypertablesAvailable]);
|
||||||
|
|
||||||
// After a commit containing ddl items succeeds, refetch the current
|
// After a commit containing ddl items succeeds, refetch the current
|
||||||
// object-type list + refresh the schema tree so newly created/dropped
|
// object-type list + refresh the schema tree so newly created/dropped
|
||||||
// objects show up without a manual refresh.
|
// objects show up without a manual refresh.
|
||||||
@@ -325,7 +352,7 @@ export function ObjectExplorerPage({
|
|||||||
<SelectDropdown
|
<SelectDropdown
|
||||||
value={type}
|
value={type}
|
||||||
onChange={(v) => handleTypeChange(v as ObjectType)}
|
onChange={(v) => handleTypeChange(v as ObjectType)}
|
||||||
options={OBJECT_TYPE_OPTIONS}
|
options={objectTypeOptions}
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
aria-label="Object type"
|
aria-label="Object type"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import { describe, it, expect } from "vitest";
|
||||||
|
import { TYPE_LABELS, visibleObjectTypes } from "./ObjectTree";
|
||||||
|
|
||||||
|
describe("hypertables object type", () => {
|
||||||
|
it("registers label and stays in the type union", () => {
|
||||||
|
expect(TYPE_LABELS.hypertables).toBe("hypertables");
|
||||||
|
expect(Object.keys(TYPE_LABELS)).toContain("hypertables");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("hides hypertables until availability is confirmed true", () => {
|
||||||
|
const base = Object.keys(TYPE_LABELS) as ReturnType<typeof visibleObjectTypes>;
|
||||||
|
expect(visibleObjectTypes(null)).not.toContain("hypertables");
|
||||||
|
expect(visibleObjectTypes(false)).not.toContain("hypertables");
|
||||||
|
expect(visibleObjectTypes(true)).toContain("hypertables");
|
||||||
|
expect(visibleObjectTypes(true).length).toBe(base.length);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -1,22 +1,23 @@
|
|||||||
import { useEffect, useState, useMemo } from "react";
|
import { useEffect, useState, useMemo } from "react";
|
||||||
import { ChevronRight, ChevronDown, FunctionSquare, GitBranch, ListOrdered, Tag, Puzzle, Search } from "lucide-react";
|
import { ChevronRight, ChevronDown, FunctionSquare, GitBranch, ListOrdered, Tag, Puzzle, Layers, Search } from "lucide-react";
|
||||||
import { useDbViewerStore } from "../../stores/dbViewerStore";
|
import { useDbViewerStore } from "../../stores/dbViewerStore";
|
||||||
import * as cmd from "../../lib/commands";
|
import * as cmd from "../../lib/commands";
|
||||||
import type { FunctionInfo, TriggerInfo, SequenceInfo, EnumInfo, ExtensionInfo } from "../../lib/types";
|
import type { FunctionInfo, TriggerInfo, SequenceInfo, EnumInfo, ExtensionInfo, HypertableInfo } from "../../lib/types";
|
||||||
|
|
||||||
type ObjectType = "functions" | "triggers" | "sequences" | "enums" | "extensions";
|
type ObjectType = "functions" | "triggers" | "sequences" | "enums" | "extensions" | "hypertables";
|
||||||
|
|
||||||
interface ObjectTreeProps {
|
interface ObjectTreeProps {
|
||||||
type: ObjectType;
|
type: ObjectType;
|
||||||
connectionId: string;
|
connectionId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const TYPE_LABELS: Record<ObjectType, string> = {
|
export const TYPE_LABELS: Record<ObjectType, string> = {
|
||||||
functions: "functions",
|
functions: "functions",
|
||||||
triggers: "triggers",
|
triggers: "triggers",
|
||||||
sequences: "sequences",
|
sequences: "sequences",
|
||||||
enums: "enums",
|
enums: "enums",
|
||||||
extensions: "extensions",
|
extensions: "extensions",
|
||||||
|
hypertables: "hypertables",
|
||||||
};
|
};
|
||||||
|
|
||||||
const ICONS: Record<ObjectType, React.ReactNode> = {
|
const ICONS: Record<ObjectType, React.ReactNode> = {
|
||||||
@@ -25,8 +26,18 @@ const ICONS: Record<ObjectType, React.ReactNode> = {
|
|||||||
sequences: <ListOrdered size={14} className="text-text-muted shrink-0" />,
|
sequences: <ListOrdered size={14} className="text-text-muted shrink-0" />,
|
||||||
enums: <Tag size={14} className="text-text-muted shrink-0" />,
|
enums: <Tag size={14} className="text-text-muted shrink-0" />,
|
||||||
extensions: <Puzzle size={14} className="text-text-muted shrink-0" />,
|
extensions: <Puzzle size={14} className="text-text-muted shrink-0" />,
|
||||||
|
hypertables: <Layers size={14} className="text-text-muted shrink-0" />,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Object types visible in the dropdown. Hypertables only show when the
|
||||||
|
* connection confirmed TimescaleDB availability (available === true). */
|
||||||
|
export function visibleObjectTypes(hypertablesAvailable: boolean | null): ObjectType[] {
|
||||||
|
const all = Object.keys(TYPE_LABELS) as ObjectType[];
|
||||||
|
return hypertablesAvailable === true
|
||||||
|
? all
|
||||||
|
: all.filter((t) => t !== "hypertables");
|
||||||
|
}
|
||||||
|
|
||||||
function SourceCode({ source }: { source: string }) {
|
function SourceCode({ source }: { source: string }) {
|
||||||
const [expanded, setExpanded] = useState(false);
|
const [expanded, setExpanded] = useState(false);
|
||||||
const maxLen = 500;
|
const maxLen = 500;
|
||||||
@@ -59,11 +70,13 @@ export function ObjectTree({ type, connectionId }: ObjectTreeProps) {
|
|||||||
const sequences = useDbViewerStore((s) => s.sequences);
|
const sequences = useDbViewerStore((s) => s.sequences);
|
||||||
const enums = useDbViewerStore((s) => s.enums);
|
const enums = useDbViewerStore((s) => s.enums);
|
||||||
const extensions = useDbViewerStore((s) => s.extensions);
|
const extensions = useDbViewerStore((s) => s.extensions);
|
||||||
|
const hypertables = useDbViewerStore((s) => s.hypertables);
|
||||||
const setFunctions = useDbViewerStore((s) => s.setFunctions);
|
const setFunctions = useDbViewerStore((s) => s.setFunctions);
|
||||||
const setTriggers = useDbViewerStore((s) => s.setTriggers);
|
const setTriggers = useDbViewerStore((s) => s.setTriggers);
|
||||||
const setSequences = useDbViewerStore((s) => s.setSequences);
|
const setSequences = useDbViewerStore((s) => s.setSequences);
|
||||||
const setEnums = useDbViewerStore((s) => s.setEnums);
|
const setEnums = useDbViewerStore((s) => s.setEnums);
|
||||||
const setExtensions = useDbViewerStore((s) => s.setExtensions);
|
const setExtensions = useDbViewerStore((s) => s.setExtensions);
|
||||||
|
const setHypertables = useDbViewerStore((s) => s.setHypertables);
|
||||||
|
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [expandedKeys, setExpandedKeys] = useState<Set<string>>(new Set());
|
const [expandedKeys, setExpandedKeys] = useState<Set<string>>(new Set());
|
||||||
@@ -77,8 +90,9 @@ export function ObjectTree({ type, connectionId }: ObjectTreeProps) {
|
|||||||
case "sequences": return sequences;
|
case "sequences": return sequences;
|
||||||
case "enums": return enums;
|
case "enums": return enums;
|
||||||
case "extensions": return extensions;
|
case "extensions": return extensions;
|
||||||
|
case "hypertables": return hypertables;
|
||||||
}
|
}
|
||||||
}, [type, functions, triggers, sequences, enums, extensions]);
|
}, [type, functions, triggers, sequences, enums, extensions, hypertables]);
|
||||||
|
|
||||||
const setter = useMemo(() => {
|
const setter = useMemo(() => {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@@ -87,8 +101,9 @@ export function ObjectTree({ type, connectionId }: ObjectTreeProps) {
|
|||||||
case "sequences": return setSequences;
|
case "sequences": return setSequences;
|
||||||
case "enums": return setEnums;
|
case "enums": return setEnums;
|
||||||
case "extensions": return setExtensions;
|
case "extensions": return setExtensions;
|
||||||
|
case "hypertables": return setHypertables;
|
||||||
}
|
}
|
||||||
}, [type, setFunctions, setTriggers, setSequences, setEnums, setExtensions]);
|
}, [type, setFunctions, setTriggers, setSequences, setEnums, setExtensions, setHypertables]);
|
||||||
|
|
||||||
// Fetch on mount if not in store
|
// Fetch on mount if not in store
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -113,6 +128,9 @@ export function ObjectTree({ type, connectionId }: ObjectTreeProps) {
|
|||||||
} else if (type === "enums") {
|
} else if (type === "enums") {
|
||||||
const result = await cmd.getEnums(connectionId, currentSchema ?? undefined);
|
const result = await cmd.getEnums(connectionId, currentSchema ?? undefined);
|
||||||
if (!cancelled) (setEnums as (v: EnumInfo[]) => void)(result);
|
if (!cancelled) (setEnums as (v: EnumInfo[]) => void)(result);
|
||||||
|
} else if (type === "hypertables") {
|
||||||
|
const res = await cmd.getHypertables(connectionId, currentSchema ?? undefined);
|
||||||
|
if (!cancelled) (setHypertables as (v: HypertableInfo[]) => void)(res.available ? res.items : []);
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
// Silently fail — store remains null, we show the empty state
|
// Silently fail — store remains null, we show the empty state
|
||||||
@@ -123,7 +141,7 @@ export function ObjectTree({ type, connectionId }: ObjectTreeProps) {
|
|||||||
|
|
||||||
fetchData();
|
fetchData();
|
||||||
return () => { cancelled = true; };
|
return () => { cancelled = true; };
|
||||||
}, [type, connectionId, currentSchema, data, setter, setFunctions, setTriggers, setSequences, setEnums, setExtensions]);
|
}, [type, connectionId, currentSchema, data, setter, setFunctions, setTriggers, setSequences, setEnums, setExtensions, setHypertables]);
|
||||||
|
|
||||||
const q = search.toLowerCase().trim();
|
const q = search.toLowerCase().trim();
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
ListChecks,
|
ListChecks,
|
||||||
ListOrdered,
|
ListOrdered,
|
||||||
Puzzle,
|
Puzzle,
|
||||||
|
Layers,
|
||||||
ShieldCheck,
|
ShieldCheck,
|
||||||
SquareFunction,
|
SquareFunction,
|
||||||
Tag,
|
Tag,
|
||||||
@@ -29,6 +30,7 @@ export const TYPE_LABELS: Record<ObjectType, string> = {
|
|||||||
sequences: "Sequences",
|
sequences: "Sequences",
|
||||||
enums: "Enums",
|
enums: "Enums",
|
||||||
extensions: "Extensions",
|
extensions: "Extensions",
|
||||||
|
hypertables: "Hypertables",
|
||||||
indexes: "Indexes",
|
indexes: "Indexes",
|
||||||
constraints: "Constraints",
|
constraints: "Constraints",
|
||||||
procedures: "Procedures",
|
procedures: "Procedures",
|
||||||
@@ -41,6 +43,7 @@ export const SINGULAR_LABELS: Record<ObjectType, string> = {
|
|||||||
sequences: "sequence",
|
sequences: "sequence",
|
||||||
enums: "enum",
|
enums: "enum",
|
||||||
extensions: "extension",
|
extensions: "extension",
|
||||||
|
hypertables: "hypertable",
|
||||||
indexes: "index",
|
indexes: "index",
|
||||||
constraints: "constraint",
|
constraints: "constraint",
|
||||||
procedures: "procedure",
|
procedures: "procedure",
|
||||||
@@ -55,6 +58,7 @@ export const OBJECT_ICONS: Record<ObjectType, React.ReactNode> = {
|
|||||||
sequences: <ListOrdered size={14} className="text-text-muted shrink-0" />,
|
sequences: <ListOrdered size={14} className="text-text-muted shrink-0" />,
|
||||||
enums: <Tag size={14} className="text-text-muted shrink-0" />,
|
enums: <Tag size={14} className="text-text-muted shrink-0" />,
|
||||||
extensions: <Puzzle size={14} className="text-text-muted shrink-0" />,
|
extensions: <Puzzle size={14} className="text-text-muted shrink-0" />,
|
||||||
|
hypertables: <Layers size={14} className="text-text-muted shrink-0" />,
|
||||||
indexes: <BookMarked size={14} className="text-text-muted shrink-0" />,
|
indexes: <BookMarked size={14} className="text-text-muted shrink-0" />,
|
||||||
constraints: <ListChecks size={14} className="text-text-muted shrink-0" />,
|
constraints: <ListChecks size={14} className="text-text-muted shrink-0" />,
|
||||||
procedures: <SquareFunction size={14} className="text-text-muted shrink-0" />,
|
procedures: <SquareFunction size={14} className="text-text-muted shrink-0" />,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { invoke } from "@tauri-apps/api/core";
|
import { invoke } from "@tauri-apps/api/core";
|
||||||
import type { Connection, ConnectionInput, ConnectionTestResult, Folder, FolderInput, Tag, TagInput, Settings, ImportResult, TableInfo, QueryResult, BackupOptions, RestoreOptions, SyncOptions, PgToolStatus, MySqlToolStatus, MySqlBackupOptions, MySqlRestoreOptions, SqliteBackupOptions, SqliteRestoreOptions, FunctionInfo, TriggerInfo, SequenceInfo, EnumInfo, ExtensionInfo, SchemaGraph, IndexInfo, ConstraintInfo, RecentConnection, ObjectSearchHit, DependencyInfo, RoleInfo, PrivilegeEntry, RebuildReadiness, MaintenanceResult, TablespaceInfo, ColumnInfo } from "./types";
|
import type { Connection, ConnectionInput, ConnectionTestResult, Folder, FolderInput, Tag, TagInput, Settings, ImportResult, TableInfo, QueryResult, BackupOptions, RestoreOptions, SyncOptions, PgToolStatus, MySqlToolStatus, MySqlBackupOptions, MySqlRestoreOptions, SqliteBackupOptions, SqliteRestoreOptions, FunctionInfo, TriggerInfo, SequenceInfo, EnumInfo, ExtensionInfo, SchemaGraph, IndexInfo, ConstraintInfo, RecentConnection, ObjectSearchHit, DependencyInfo, RoleInfo, PrivilegeEntry, RebuildReadiness, MaintenanceResult, TablespaceInfo, ColumnInfo, HypertableListResponse } from "./types";
|
||||||
import type { FilterRule, SortRule } from "../stores/dbViewerStore";
|
import type { FilterRule, SortRule } from "../stores/dbViewerStore";
|
||||||
import type { ChangePayload } from "./changePayload";
|
import type { ChangePayload } from "./changePayload";
|
||||||
import { buildObjectDdl as buildObjectDdlImpl, type ObjectKind, type DdlParams } from "./objectCrud";
|
import { buildObjectDdl as buildObjectDdlImpl, type ObjectKind, type DdlParams } from "./objectCrud";
|
||||||
@@ -226,6 +226,13 @@ export async function getExtensions(connectionId: string): Promise<ExtensionInfo
|
|||||||
return invoke<ExtensionInfo[]>("get_extensions", { connectionId });
|
return invoke<ExtensionInfo[]>("get_extensions", { connectionId });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getHypertables(
|
||||||
|
connectionId: string,
|
||||||
|
schema?: string,
|
||||||
|
): Promise<HypertableListResponse> {
|
||||||
|
return invoke<HypertableListResponse>("get_hypertables", { connectionId, schema });
|
||||||
|
}
|
||||||
|
|
||||||
export async function getSchemaGraph(
|
export async function getSchemaGraph(
|
||||||
connectionId: string,
|
connectionId: string,
|
||||||
schema?: string,
|
schema?: string,
|
||||||
|
|||||||
@@ -367,6 +367,7 @@ export type ObjectType =
|
|||||||
| "sequences"
|
| "sequences"
|
||||||
| "enums"
|
| "enums"
|
||||||
| "extensions"
|
| "extensions"
|
||||||
|
| "hypertables"
|
||||||
| "indexes"
|
| "indexes"
|
||||||
| "constraints"
|
| "constraints"
|
||||||
| "procedures"
|
| "procedures"
|
||||||
@@ -378,6 +379,21 @@ export interface ObjectSearchHit {
|
|||||||
object_type: string; // TABLE | VIEW | MATERIALIZED VIEW | FUNCTION | PROCEDURE | TRIGGER | SEQUENCE | ENUM | EXTENSION | INDEX | CONSTRAINT
|
object_type: string; // TABLE | VIEW | MATERIALIZED VIEW | FUNCTION | PROCEDURE | TRIGGER | SEQUENCE | ENUM | EXTENSION | INDEX | CONSTRAINT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface HypertableInfo {
|
||||||
|
name: string;
|
||||||
|
schema: string;
|
||||||
|
num_dimensions: number;
|
||||||
|
compression_enabled: boolean;
|
||||||
|
num_chunks: number;
|
||||||
|
total_size_bytes: number | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HypertableListResponse {
|
||||||
|
available: boolean;
|
||||||
|
reason: string | null;
|
||||||
|
items: HypertableInfo[];
|
||||||
|
}
|
||||||
|
|
||||||
export interface DependencyInfo {
|
export interface DependencyInfo {
|
||||||
deptype: string;
|
deptype: string;
|
||||||
class: string;
|
class: string;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { create } from "zustand";
|
import { create } from "zustand";
|
||||||
import type { QueryResult, TableInfo, ChangeItemType, FunctionInfo, TriggerInfo, SequenceInfo, EnumInfo, ExtensionInfo, IndexInfo, ConstraintInfo, ObjectType, RoleInfo } from "../lib/types";
|
import type { QueryResult, TableInfo, ChangeItemType, FunctionInfo, TriggerInfo, SequenceInfo, EnumInfo, ExtensionInfo, HypertableInfo, IndexInfo, ConstraintInfo, ObjectType, RoleInfo } from "../lib/types";
|
||||||
import { getDatabases, getSchemas, getTables } from "../lib/commands";
|
import { getDatabases, getSchemas, getTables } from "../lib/commands";
|
||||||
import type { ObjectKind, DdlParams } from "../lib/objectCrud";
|
import type { ObjectKind, DdlParams } from "../lib/objectCrud";
|
||||||
|
|
||||||
@@ -117,6 +117,8 @@ interface DbViewerState {
|
|||||||
sequences: SequenceInfo[] | null;
|
sequences: SequenceInfo[] | null;
|
||||||
enums: EnumInfo[] | null;
|
enums: EnumInfo[] | null;
|
||||||
extensions: ExtensionInfo[] | null;
|
extensions: ExtensionInfo[] | null;
|
||||||
|
hypertables: HypertableInfo[] | null;
|
||||||
|
hypertablesAvailable: boolean | null;
|
||||||
indexes: IndexInfo[] | null;
|
indexes: IndexInfo[] | null;
|
||||||
setSchemaTreeLoading: (loading: boolean) => void;
|
setSchemaTreeLoading: (loading: boolean) => void;
|
||||||
constraints: ConstraintInfo[] | null;
|
constraints: ConstraintInfo[] | null;
|
||||||
@@ -182,6 +184,8 @@ interface DbViewerState {
|
|||||||
setSequences: (sequences: SequenceInfo[]) => void;
|
setSequences: (sequences: SequenceInfo[]) => void;
|
||||||
setEnums: (enums: EnumInfo[]) => void;
|
setEnums: (enums: EnumInfo[]) => void;
|
||||||
setExtensions: (extensions: ExtensionInfo[]) => void;
|
setExtensions: (extensions: ExtensionInfo[]) => void;
|
||||||
|
setHypertables: (hypertables: HypertableInfo[]) => void;
|
||||||
|
setHypertablesAvailable: (v: boolean | null) => void;
|
||||||
setIndexes: (indexes: IndexInfo[]) => void;
|
setIndexes: (indexes: IndexInfo[]) => void;
|
||||||
setConstraints: (constraints: ConstraintInfo[]) => void;
|
setConstraints: (constraints: ConstraintInfo[]) => void;
|
||||||
setRoles: (roles: RoleInfo[]) => void;
|
setRoles: (roles: RoleInfo[]) => void;
|
||||||
@@ -224,6 +228,8 @@ const initialState = {
|
|||||||
sequences: null as SequenceInfo[] | null,
|
sequences: null as SequenceInfo[] | null,
|
||||||
enums: null as EnumInfo[] | null,
|
enums: null as EnumInfo[] | null,
|
||||||
extensions: null as ExtensionInfo[] | null,
|
extensions: null as ExtensionInfo[] | null,
|
||||||
|
hypertables: null as HypertableInfo[] | null,
|
||||||
|
hypertablesAvailable: null as boolean | null,
|
||||||
indexes: null as IndexInfo[] | null,
|
indexes: null as IndexInfo[] | null,
|
||||||
constraints: null as ConstraintInfo[] | null,
|
constraints: null as ConstraintInfo[] | null,
|
||||||
roles: [] as RoleInfo[],
|
roles: [] as RoleInfo[],
|
||||||
@@ -586,6 +592,8 @@ export const useDbViewerStore = create<DbViewerState>((set, get) => ({
|
|||||||
setSequences: (sequences) => set({ sequences }),
|
setSequences: (sequences) => set({ sequences }),
|
||||||
setEnums: (enums) => set({ enums }),
|
setEnums: (enums) => set({ enums }),
|
||||||
setExtensions: (extensions) => set({ extensions }),
|
setExtensions: (extensions) => set({ extensions }),
|
||||||
|
setHypertables: (hypertables) => set({ hypertables }),
|
||||||
|
setHypertablesAvailable: (v) => set({ hypertablesAvailable: v }),
|
||||||
setIndexes: (indexes) => set({ indexes }),
|
setIndexes: (indexes) => set({ indexes }),
|
||||||
setConstraints: (constraints) => set({ constraints }),
|
setConstraints: (constraints) => set({ constraints }),
|
||||||
setRoles: (roles) => set({ roles }),
|
setRoles: (roles) => set({ roles }),
|
||||||
|
|||||||
Reference in New Issue
Block a user