import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
/**
 * Copyright (c) 2020-present, Goldman Sachs
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import { observer } from 'mobx-react-lite';
import { useState } from 'react';
import { ChevronDownIcon, ChevronRightIcon, CompressIcon, CopyIcon, ExpandAllIcon, ExternalLinkIcon, EyeIcon, FilterIcon, KeyIcon, PURE_DatabaseIcon, PURE_DatabaseSchemaIcon, PURE_DatabaseTableIcon, PURE_DatabaseTableJoinIcon, PURE_DataProductIcon, SearchIcon, TimesIcon, clsx, } from '@finos/legend-art';
import {} from '@finos/legend-graph';
import { DatabaseAnnotationDisplay } from './DatabaseAnnotationDisplay.js';
import { getRelationNodeId, getSchemaNodeId, } from '../../../../stores/editor/editor-state/element-editor-state/DatabaseEditorState.js';
import { getColumnTypeLabel, getTableColumns, isCrossDatabaseJoin, isPrimaryKey, isSelfJoin, matchesSearch, resolveFilterFormula, resolveJoinFormula, resolveViewColumnFormula, resolveViewGroupByFormula, summarizeMilestoning, } from './DatabaseDiagramHelper.js';
/**
 * Small inline copy-to-clipboard button rendered next to rendered Pure code
 * (filter/join/view-column/groupBy formulas). Two-state visual: shows the
 * default copy icon, briefly flips to a "Copied!" label after a successful
 * write, then resets. Click stops propagation so the surrounding row's
 * click handler (which usually selects/focuses the row) doesn't fire.
 */
const CopyFormulaButton = ({ value, label = 'Copy', }) => {
    const [copied, setCopied] = useState(false);
    return (_jsx("button", { type: "button", className: clsx('database-diagram__copy-btn', {
            'database-diagram__copy-btn--copied': copied,
        }), title: copied ? 'Copied!' : label, onClick: (event) => {
            event.stopPropagation();
            // `navigator.clipboard` may be unavailable in test/insecure contexts;
            // fall through silently in that case rather than throwing.
            navigator.clipboard
                .writeText(value)
                .then(() => {
                setCopied(true);
                window.setTimeout(() => setCopied(false), 1200);
            })
                .catch(() => {
                /* no-op \u2014 copy failures are non-fatal */
            });
        }, children: _jsx(CopyIcon, {}) }));
};
/**
 * Pure-CSS shimmer placeholder shown in place of formula text while the
 * batched engine call is still in flight. We swap from skeleton to text
 * once the corresponding `is...Loading` flag flips false on the editor
 * state. Compact one-line bar so layout doesn't shift on resolve.
 */
const FormulaSkeleton = () => (_jsx("span", { className: "database-diagram__skeleton", "aria-label": "Loading formula", "aria-busy": true }));
/**
 * Empty-state row shown when a side-panel section has zero rows of its
 * primary kind (e.g. a database with no joins). Lighter than rendering
 * nothing because users sometimes wonder if the panel is broken when a
 * section is silently absent.
 */
const EmptySectionRow = ({ message }) => (_jsx("div", { className: "database-diagram__side-panel__empty", children: message }));
/**
 * Predicates that determine whether a tree node should be rendered under
 * the current search filter. A node is shown when it OR any descendant
 * matches the (already lowercased) query. Empty query short-circuits so
 * everything is shown, which keeps the no-filter render path cheap.
 */
const relationMatchesSearch = (rel, query) => {
    if (!query) {
        return true;
    }
    if (matchesSearch(rel.name, query)) {
        return true;
    }
    // For tables walk Column.name; for views walk ColumnMapping.columnName.
    // Either way the comparison is a flat substring on visible identifiers.
    if ('columnMappings' in rel) {
        return rel.columnMappings.some((m) => matchesSearch(m.columnName, query));
    }
    return getTableColumns(rel).some((c) => matchesSearch(c.name, query));
};
const schemaMatchesSearch = (schema, query) => {
    if (!query) {
        return true;
    }
    if (matchesSearch(schema.name, query)) {
        return true;
    }
    return (schema.tables.some((t) => relationMatchesSearch(t, query)) ||
        schema.views.some((v) => relationMatchesSearch(v, query)));
};
/**
 * Renders one column under an expanded Table. Clicking focuses the column,
 * which (per `DatabaseEditorState.focusOnColumn`) selects the parent table,
 * marks the specific column, and requests a canvas pan.
 *
 * Columns aren't expandable — they're leaves of the tree.
 */
const DatabaseTreeTableColumnRow = observer((props) => {
    const { editorState, table, column } = props;
    const isSelected = editorState.selectedColumn === column;
    const isPK = isPrimaryKey(table, column.name);
    return (_jsxs("button", { type: "button", className: clsx('database-diagram__tree__column', {
            'database-diagram__tree__column--selected': isSelected,
            'database-diagram__tree__column--pk': isPK,
        }), onClick: () => editorState.focusOnColumn(table, column), title: `${table.schema.name}.${table.name}.${column.name}: ${getColumnTypeLabel(column)}`, children: [_jsx("span", { className: "database-diagram__tree__column__icon", children: isPK ? (_jsx(KeyIcon, {})) : (_jsx("span", { className: "database-diagram__tree__column__bullet", children: "\u2022" })) }), _jsxs("span", { className: "database-diagram__tree__column__name", children: [column.name, column.nullable === true && (_jsx("span", { className: "database-diagram__tree__column__nullable", title: "Nullable", children: "?" }))] }), _jsx("span", { className: "database-diagram__tree__column__type", children: getColumnTypeLabel(column) }), _jsx(DatabaseAnnotationDisplay, { stereotypes: column.stereotypes, taggedValues: column.taggedValues, layout: "compact" })] }));
});
/**
 * Renders one column-mapping under an expanded View. Visually similar to a
 * table-column row but the secondary text is the formula placeholder rather
 * than a SQL type. Not selectable individually in the MVP — clicking just
 * focuses the parent view.
 */
const DatabaseTreeViewColumnRow = observer((props) => {
    const { editorState, view, columnMapping } = props;
    const isPK = isPrimaryKey(view, columnMapping.columnName);
    const isSelected = editorState.selectedRelation === view &&
        editorState.selectedViewColumnName === columnMapping.columnName;
    // Pull the live formula from the editor state. Re-renders when the
    // batched engine call resolves and updates `viewColumnFormulas`.
    const formula = resolveViewColumnFormula(editorState.viewColumnFormulas, view.schema.name, view.name, columnMapping.columnName);
    const isLoading = editorState.isLoadingViewColumnFormulas &&
        !editorState.viewColumnFormulas.has(`${view.schema.name}.${view.name}.${columnMapping.columnName}`);
    return (_jsxs("button", { type: "button", className: clsx('database-diagram__tree__column', 'database-diagram__tree__column--view', {
            'database-diagram__tree__column--pk': isPK,
            'database-diagram__tree__column--selected': isSelected,
        }), onClick: () => editorState.focusOnViewColumn(view, columnMapping.columnName), title: `${view.schema.name}.${view.name}.${columnMapping.columnName}: ${formula}`, children: [_jsx("span", { className: "database-diagram__tree__column__icon", children: isPK ? (_jsx(KeyIcon, {})) : (_jsx("span", { className: "database-diagram__tree__column__bullet", children: "\u2022" })) }), _jsx("span", { className: "database-diagram__tree__column__name", children: columnMapping.columnName }), _jsx("span", { className: "database-diagram__tree__column__type", children: isLoading ? _jsx(FormulaSkeleton, {}) : formula }), !isLoading && (_jsx(CopyFormulaButton, { value: formula, label: "Copy formula" }))] }));
});
/**
 * Renders one Table row plus (when expanded) its Column children. Clicking
 * the row both *selects the table on the canvas* (with a pan-to) AND toggles
 * expansion. Bundling these is intentional — when a user navigates to a
 * relation, they almost always want to see its columns too.
 */
const DatabaseTreeTableRow = observer((props) => {
    const { editorState, table } = props;
    const query = editorState.searchText.trim().toLowerCase();
    if (!relationMatchesSearch(table, query)) {
        return null;
    }
    const id = getRelationNodeId(table.schema.name, table.name);
    // When a filter is active force-expand the row so matches deeper in
    // the tree are immediately visible without an extra click.
    const isExpanded = query !== '' || editorState.expandedRelationIds.has(id);
    const isSelected = editorState.selectedRelation === table;
    const columns = getTableColumns(table);
    // When filtering, only show columns that match the query (or all
    // columns if the table itself matched by name).
    const tableNameMatches = matchesSearch(table.name, query);
    const visibleColumns = query === '' || tableNameMatches
        ? columns
        : columns.filter((c) => matchesSearch(c.name, query));
    return (_jsxs("div", { className: "database-diagram__tree__table", children: [_jsxs("button", { type: "button", className: clsx('database-diagram__tree__table__row', {
                    'database-diagram__tree__table__row--selected': isSelected,
                }), onClick: () => {
                    editorState.focusOnRelation(table);
                    editorState.toggleRelationExpanded(id);
                }, title: `${table.schema.name}.${table.name}`, children: [_jsx("span", { className: "database-diagram__tree__caret", children: isExpanded ? _jsx(ChevronDownIcon, {}) : _jsx(ChevronRightIcon, {}) }), _jsx(PURE_DatabaseTableIcon, {}), _jsx("span", { className: "database-diagram__tree__table__name", children: table.name }), _jsx("span", { className: "database-diagram__tree__table__count", children: columns.length }), _jsx(DatabaseAnnotationDisplay, { stereotypes: table.stereotypes, taggedValues: table.taggedValues, layout: "compact" })] }), isExpanded && (_jsxs("div", { className: "database-diagram__tree__table__children", children: [table.milestoning.map((milestoning) => {
                        const summary = summarizeMilestoning(milestoning);
                        return (_jsxs("div", { className: clsx('database-diagram__tree__table__meta-row', `database-diagram__tree__table__meta-row--milestoning-${summary.kind}`), title: summary.description, children: [_jsx("span", { className: "database-diagram__tree__table__meta-row__label", children: "milestoning" }), _jsx("span", { className: "database-diagram__tree__table__meta-row__value", children: summary.label })] }, summary.label));
                    }), visibleColumns.map((column) => (_jsx(DatabaseTreeTableColumnRow, { editorState: editorState, table: table, column: column }, column.name)))] }))] }));
});
/**
 * Renders the View → Filter mapping reference under an expanded view. Shows
 * `<owning-database>.<filterName>`. When the referenced filter belongs to
 * the database currently being edited, clicking navigates to it via
 * `focusOnFilter`; cross-database references are non-interactive (filters
 * from other databases aren't reachable from this editor).
 */
const DatabaseTreeViewFilterRow = observer((props) => {
    const { editorState, view, filterMapping } = props;
    const ownerPath = filterMapping.filter.ownerReference.valueForSerialization ?? '';
    const filterValue = filterMapping.filter.value;
    // Filters live on a Database; if the owning DB matches the one we're
    // editing we can navigate. Otherwise the row is informational.
    const isLocal = filterValue.owner === editorState.database;
    const display = `${ownerPath}.${filterMapping.filterName}`;
    const formula = isLocal
        ? resolveFilterFormula(editorState.filterFormulas, filterValue.name)
        : undefined;
    return (_jsxs("button", { type: "button", className: clsx('database-diagram__tree__column', 'database-diagram__tree__column--view', 'database-diagram__tree__column--view-meta'), onClick: () => {
            if (isLocal) {
                editorState.focusOnFilter(filterValue);
            }
            else {
                editorState.focusOnRelation(view);
            }
        }, disabled: !isLocal, title: formula
            ? `${display}: ${formula}`
            : `${display}${isLocal ? '' : ' (external)'}`, children: [_jsx("span", { className: "database-diagram__tree__column__icon", children: _jsx(FilterIcon, {}) }), _jsx("span", { className: "database-diagram__tree__column__name", children: "filter" }), _jsx("span", { className: "database-diagram__tree__column__type", children: display })] }));
});
/**
 * Renders one row per `View.groupBy.columns[i]` Pure expression. Each row
 * lazily reads its rendered formula from `viewGroupByFormulas` — until the
 * batched engine call resolves it falls back to a static placeholder.
 *
 * Rows aren't clickable: the underlying RelationalOperationElement isn't a
 * navigable graph node and the parent view is already focused via the
 * surrounding tree row.
 */
const DatabaseTreeViewGroupByRow = observer((props) => {
    const { editorState, view, index } = props;
    const formula = resolveViewGroupByFormula(editorState.viewGroupByFormulas, view.schema.name, view.name, index);
    const isLoading = editorState.isLoadingViewGroupByFormulas &&
        !editorState.viewGroupByFormulas.has(`${view.schema.name}.${view.name}.groupBy[${index}]`);
    return (_jsxs("div", { className: clsx('database-diagram__tree__column', 'database-diagram__tree__column--view', 'database-diagram__tree__column--view-meta', 'database-diagram__tree__column--readonly'), title: `group by [${index}]: ${formula}`, children: [_jsx("span", { className: "database-diagram__tree__column__icon", children: _jsx("span", { className: "database-diagram__tree__column__bullet", children: "\u00B7" }) }), _jsx("span", { className: "database-diagram__tree__column__name", children: `[${index}]` }), _jsx("span", { className: "database-diagram__tree__column__type", children: isLoading ? _jsx(FormulaSkeleton, {}) : formula }), !isLoading && (_jsx(CopyFormulaButton, { value: formula, label: "Copy expression" }))] }));
});
/**
 * Renders one View row plus (when expanded) its column-mapping children.
 * Visually distinct from the table row via the eye icon. Same click semantics
 * as tables (select + expand).
 */
const DatabaseTreeViewRow = observer((props) => {
    const { editorState, view } = props;
    const query = editorState.searchText.trim().toLowerCase();
    if (!relationMatchesSearch(view, query)) {
        return null;
    }
    const id = getRelationNodeId(view.schema.name, view.name);
    // Same auto-expand-on-filter behavior as tables.
    const isExpanded = query !== '' || editorState.expandedRelationIds.has(id);
    const isSelected = editorState.selectedRelation === view;
    const groupBy = view.groupBy;
    const groupByCount = groupBy?.columns.length ?? 0;
    const viewNameMatches = matchesSearch(view.name, query);
    const visibleMappings = query === '' || viewNameMatches
        ? view.columnMappings
        : view.columnMappings.filter((m) => matchesSearch(m.columnName, query));
    return (_jsxs("div", { className: "database-diagram__tree__table database-diagram__tree__table--view", children: [_jsxs("button", { type: "button", className: clsx('database-diagram__tree__table__row', {
                    'database-diagram__tree__table__row--selected': isSelected,
                }), onClick: () => {
                    editorState.focusOnRelation(view);
                    editorState.toggleRelationExpanded(id);
                }, title: `${view.schema.name}.${view.name} (view)`, children: [_jsx("span", { className: "database-diagram__tree__caret", children: isExpanded ? _jsx(ChevronDownIcon, {}) : _jsx(ChevronRightIcon, {}) }), _jsx(EyeIcon, {}), _jsx("span", { className: "database-diagram__tree__table__name", children: view.name }), _jsx("span", { className: "database-diagram__tree__table__count", children: view.columnMappings.length }), view.distinct === true && (_jsx("span", { className: "database-diagram__tree__table__view-tag database-diagram__tree__table__view-tag--distinct", title: "View applies DISTINCT", children: "DISTINCT" })), view.filter && (_jsx("span", { className: "database-diagram__tree__table__view-tag database-diagram__tree__table__view-tag--filtered", title: `Filtered by ${view.filter.filter.ownerReference.valueForSerialization ?? ''}.${view.filter.filterName}`, children: "FILTERED" })), groupByCount > 0 && (_jsx("span", { className: "database-diagram__tree__table__view-tag database-diagram__tree__table__view-tag--grouped", title: `GROUP BY ${groupByCount} expression${groupByCount === 1 ? '' : 's'}`, children: `GROUP BY (${groupByCount})` })), _jsx(DatabaseAnnotationDisplay, { stereotypes: view.stereotypes, taggedValues: view.taggedValues, layout: "compact" })] }), isExpanded && (_jsxs("div", { className: "database-diagram__tree__table__children", children: [visibleMappings.map((mapping) => (_jsx(DatabaseTreeViewColumnRow, { editorState: editorState, view: view, columnMapping: mapping }, mapping.columnName))), query === '' && view.filter && (_jsx(DatabaseTreeViewFilterRow, { editorState: editorState, view: view, filterMapping: view.filter })), query === '' &&
                        groupBy?.columns.map((_, index) => (_jsx(DatabaseTreeViewGroupByRow
                        // Ordering is the only identity for groupBy columns.
                        // eslint-disable-next-line react/no-array-index-key
                        , { editorState: editorState, view: view, index: index }, `groupBy:${index}`)))] }))] }));
});
/**
 * Renders one Schema header plus (when expanded) its Table and View children.
 * Tables come before views within each schema — both kinds are siblings in
 * the tree, distinguished only by icon and the column-row content.
 *
 * Schemas don't have a "selected" state — they only toggle.
 */
const DatabaseTreeSchemaRow = observer((props) => {
    const { editorState, schema } = props;
    const query = editorState.searchText.trim().toLowerCase();
    if (!schemaMatchesSearch(schema, query)) {
        return null;
    }
    const schemaId = getSchemaNodeId(schema.name);
    // Force-expand under search so matches are immediately visible.
    const isExpanded = query !== '' || editorState.expandedSchemaIds.has(schemaId);
    const totalChildren = schema.tables.length + schema.views.length;
    return (_jsxs("div", { className: "database-diagram__tree__schema", children: [_jsxs("button", { type: "button", className: "database-diagram__tree__schema__row", onClick: () => editorState.toggleSchemaExpanded(schemaId), children: [_jsx("span", { className: "database-diagram__tree__caret", children: isExpanded ? _jsx(ChevronDownIcon, {}) : _jsx(ChevronRightIcon, {}) }), _jsx(PURE_DatabaseSchemaIcon, {}), _jsx("span", { className: "database-diagram__tree__schema__name", children: schema.name }), _jsx("span", { className: "database-diagram__tree__schema__count", children: totalChildren }), _jsx(DatabaseAnnotationDisplay, { stereotypes: schema.stereotypes, taggedValues: schema.taggedValues, layout: "compact" })] }), isExpanded && (_jsxs("div", { className: "database-diagram__tree__schema__children", children: [schema.tables.map((table) => (_jsx(DatabaseTreeTableRow, { editorState: editorState, table: table }, `table:${table.name}`))), schema.views.map((view) => (_jsx(DatabaseTreeViewRow, { editorState: editorState, view: view }, `view:${view.name}`)))] }))] }));
});
/**
 * Renders one Lakehouse `IncludeStore` reference: an `ExternalLinkIcon`-
 * suffixed button whose body shows the generator element path and a small
 * `storeType` badge to differentiate the kinds of generator (DataProduct vs
 * IngestDefinition vs whatever future types appear). Clicking opens the
 * generator element in a new tab — same affordance as the classic
 * "Included Stores" rows above. Kept as a named sub-component (not an
 * inline IIFE) so the JSX in `DatabaseSchemaTree` stays readable.
 */
const LakehouseStoreRow = observer((props) => {
    const { editorState, spec } = props;
    const path = spec.packageableElementPointer.valueForSerialization ??
        spec.packageableElementPointer.value.path;
    return (_jsxs("button", { type: "button", className: "database-diagram__side-panel__included-store", title: `${path}\n(generator: ${spec.storeType})\n\n(click to open)`, onClick: () => editorState.editorStore.graphEditorMode.openElement(spec.packageableElementPointer.value), children: [_jsx(PURE_DataProductIcon, {}), _jsx("span", { className: "database-diagram__side-panel__included-store__path", children: path }), _jsx("span", { className: "database-diagram__side-panel__included-store__type", children: spec.storeType }), _jsx("span", { className: "database-diagram__side-panel__included-store__open", children: _jsx(ExternalLinkIcon, {}) })] }));
});
/**
 * The full side-panel tree. Renders schemas → (tables, views) → columns plus
 * a flat "Joins" section at the bottom (joins are cross-relation
 * relationships and don't naturally fit in the tree hierarchy).
 *
 * State (selection, expansion) lives entirely in `DatabaseEditorState` so it
 * survives reprocessing and so other components (the canvas) can react to it.
 */
export const DatabaseSchemaTree = observer((props) => {
    const { editorState } = props;
    const { database } = editorState;
    const query = editorState.searchText.trim().toLowerCase();
    // Pre-compute filtered counts so each section header surfaces "showing
    // N of M" feedback when the user is filtering. Cheap walks on the
    // already-typed query \u2014 we don't memoize because the per-render cost
    // is dominated by row JSX, not these filters.
    const visibleSchemas = query === ''
        ? database.schemas
        : database.schemas.filter((s) => schemaMatchesSearch(s, query));
    const visibleJoins = query === ''
        ? database.joins
        : database.joins.filter((j) => matchesSearch(j.name, query));
    const visibleFilters = query === ''
        ? database.filters
        : database.filters.filter((f) => matchesSearch(f.name, query));
    return (_jsxs("div", { className: "database-diagram__side-panel", children: [_jsxs("div", { className: "database-diagram__side-panel__toolbar", children: [_jsxs("div", { className: "database-diagram__side-panel__search", children: [_jsx(SearchIcon, {}), _jsx("input", { type: "text", className: "database-diagram__side-panel__search__input", placeholder: "Filter schemas, tables, columns...", value: editorState.searchText, onChange: (e) => editorState.setSearchText(e.target.value), spellCheck: false }), editorState.searchText !== '' && (_jsx("button", { type: "button", className: "database-diagram__side-panel__search__clear", title: "Clear filter", onClick: () => editorState.setSearchText(''), children: _jsx(TimesIcon, {}) }))] }), _jsx("button", { type: "button", className: "database-diagram__side-panel__toolbar__btn", title: "Expand all schemas", onClick: () => editorState.expandAllSchemas(), children: _jsx(ExpandAllIcon, {}) }), _jsx("button", { type: "button", className: "database-diagram__side-panel__toolbar__btn", title: "Collapse all", onClick: () => editorState.collapseAll(), children: _jsx(CompressIcon, {}) })] }), (database.stereotypes.length > 0 ||
                database.taggedValues.length > 0) && (_jsxs("div", { className: "database-diagram__side-panel__section", children: [_jsx("div", { className: "database-diagram__side-panel__section__header", children: "Annotations" }), _jsx("div", { className: "database-diagram__side-panel__annotations", children: _jsx(DatabaseAnnotationDisplay, { stereotypes: database.stereotypes, taggedValues: database.taggedValues, layout: "block" }) })] })), _jsxs("div", { className: "database-diagram__side-panel__section", children: [_jsxs("div", { className: "database-diagram__side-panel__section__header", children: ["Schemas", ' ', _jsx("span", { className: "database-diagram__side-panel__section__count", children: query === ''
                                    ? `(${database.schemas.length})`
                                    : `(${visibleSchemas.length}/${database.schemas.length})` })] }), database.schemas.length === 0 ? (_jsx(EmptySectionRow, { message: "No schemas defined." })) : visibleSchemas.length === 0 ? (_jsx(EmptySectionRow, { message: "No schemas match the current filter." })) : (database.schemas.map((schema) => (_jsx(DatabaseTreeSchemaRow, { editorState: editorState, schema: schema }, schema.name))))] }), _jsxs("div", { className: "database-diagram__side-panel__section", children: [_jsxs("div", { className: "database-diagram__side-panel__section__header", children: ["Joins", ' ', _jsx("span", { className: "database-diagram__side-panel__section__count", children: query === ''
                                    ? `(${database.joins.length})`
                                    : `(${visibleJoins.length}/${database.joins.length})` })] }), database.joins.length === 0 ? (_jsx(EmptySectionRow, { message: "No joins defined." })) : visibleJoins.length === 0 ? (_jsx(EmptySectionRow, { message: "No joins match the current filter." })) : (visibleJoins.map((join) => {
                        const isSelected = editorState.selectedJoin === join;
                        const formula = resolveJoinFormula(editorState.joinFormulas, join.name);
                        const isLoading = editorState.isLoadingJoinFormulas &&
                            !editorState.joinFormulas.has(join.name);
                        const selfJoin = isSelfJoin(join);
                        const crossDb = !selfJoin && isCrossDatabaseJoin(join, database);
                        return (_jsxs("button", { type: "button", className: clsx('database-diagram__side-panel__join', {
                                'database-diagram__side-panel__join--selected': isSelected,
                            }), onClick: () => editorState.focusOnJoin(join), title: `${join.name}: ${formula}`, children: [_jsx("span", { className: "database-diagram__side-panel__join__icon", children: _jsx(PURE_DatabaseTableJoinIcon, {}) }), _jsxs("span", { className: "database-diagram__side-panel__join__body", children: [_jsxs("span", { className: "database-diagram__side-panel__join__name", children: [join.name, selfJoin && (_jsx("span", { className: "database-diagram__side-panel__join__marker database-diagram__side-panel__join__marker--self", title: "Self-join (source and target are the same relation)", children: "SELF" })), crossDb && (_jsx("span", { className: "database-diagram__side-panel__join__marker database-diagram__side-panel__join__marker--cross-db", title: "Cross-database join (one or both endpoints live in an included store)", children: "CROSS-DB" }))] }), _jsx("span", { className: "database-diagram__side-panel__join__formula", children: isLoading ? _jsx(FormulaSkeleton, {}) : formula })] }), !isLoading && (_jsx(CopyFormulaButton, { value: formula, label: "Copy join formula" }))] }, join.name));
                    }))] }), _jsxs("div", { className: "database-diagram__side-panel__section", children: [_jsxs("div", { className: "database-diagram__side-panel__section__header", children: ["Filters", ' ', _jsx("span", { className: "database-diagram__side-panel__section__count", children: query === ''
                                    ? `(${database.filters.length})`
                                    : `(${visibleFilters.length}/${database.filters.length})` })] }), database.filters.length === 0 ? (_jsx(EmptySectionRow, { message: "No filters defined." })) : visibleFilters.length === 0 ? (_jsx(EmptySectionRow, { message: "No filters match the current filter." })) : (visibleFilters.map((filter) => {
                        const isSelected = editorState.selectedFilter === filter;
                        const formula = resolveFilterFormula(editorState.filterFormulas, filter.name);
                        const isLoading = editorState.isLoadingFilterFormulas &&
                            !editorState.filterFormulas.has(filter.name);
                        return (_jsxs("button", { type: "button", className: clsx('database-diagram__side-panel__filter', {
                                'database-diagram__side-panel__filter--selected': isSelected,
                            }), onClick: () => editorState.focusOnFilter(filter), title: `${filter.name}: ${formula}`, children: [_jsx("span", { className: "database-diagram__side-panel__filter__icon", children: _jsx(FilterIcon, {}) }), _jsxs("span", { className: "database-diagram__side-panel__filter__body", children: [_jsx("span", { className: "database-diagram__side-panel__filter__name", children: filter.name }), _jsx("span", { className: "database-diagram__side-panel__filter__formula", children: isLoading ? _jsx(FormulaSkeleton, {}) : formula })] }), !isLoading && (_jsx(CopyFormulaButton, { value: formula, label: "Copy filter formula" }))] }, filter.name));
                    }))] }), database.includes.length > 0 && (_jsxs("div", { className: "database-diagram__side-panel__section", children: [_jsxs("div", { className: "database-diagram__side-panel__section__header", children: ["Included Stores", ' ', _jsxs("span", { className: "database-diagram__side-panel__section__count", children: ["(", database.includes.length, ")"] })] }), database.includes.map((ref) => {
                        const path = ref.valueForSerialization ?? ref.value.path;
                        return (_jsxs("button", { type: "button", className: "database-diagram__side-panel__included-store", title: `${path}\n\n(click to open)`, onClick: () => editorState.editorStore.graphEditorMode.openElement(ref.value), children: [_jsx(PURE_DatabaseIcon, {}), _jsx("span", { className: "database-diagram__side-panel__included-store__path", children: path }), _jsx("span", { className: "database-diagram__side-panel__included-store__open", children: _jsx(ExternalLinkIcon, {}) })] }, path));
                    })] })), database.includedStoreSpecifications.length > 0 && (_jsxs("div", { className: "database-diagram__side-panel__section", children: [_jsxs("div", { className: "database-diagram__side-panel__section__header", children: ["Lakehouse Stores", ' ', _jsxs("span", { className: "database-diagram__side-panel__section__count", children: ["(", database.includedStoreSpecifications.length, ")"] })] }), database.includedStoreSpecifications.map((spec) => (_jsx(LakehouseStoreRow, { editorState: editorState, spec: spec }, `${spec.storeType}:${spec.packageableElementPointer.value.path}`)))] }))] }));
});
//# sourceMappingURL=DatabaseSchemaTree.js.map