Skip to content

feat: lineage scoping and explorer dependency chain sort#56

Open
wicky-zipstack wants to merge 6 commits intomainfrom
feat/lineage-scoping
Open

feat: lineage scoping and explorer dependency chain sort#56
wicky-zipstack wants to merge 6 commits intomainfrom
feat/lineage-scoping

Conversation

@wicky-zipstack
Copy link
Copy Markdown
Contributor

@wicky-zipstack wicky-zipstack commented Apr 10, 2026

What

  • Lineage scoping: highlight selected model's parent/child chain, fade unrelated nodes
  • Explorer: dependency chain sort (default), execution order, A-Z, Z-A sorting
  • Child models indented in explorer to show hierarchy
  • Explorer auto-refreshes when model configuration (references) is saved
  • Add references field to explorer API response

Why

  • When a model is opened, the lineage tab showed ALL project models equally — confusing with large model counts
  • No way to understand parent-child relationships from the explorer without opening lineage tab
  • No sorting options for models in the explorer pane

How

  • lineage-tab.jsx & no-code-model.jsx: getRelatedNodeIds() traverses edges to find ancestors/descendants, applyScopedStyles() applies opacity + dashed border
  • file_explorer.py: added references field from model_data to API response
  • explorer-component.jsx: sortModels() with dep_chain grouping, applyModelDecorations() for child indent, sort dropdown with 4 options
  • setRefreshModels(true) after config save triggers explorer re-fetch

Can this PR break any existing features. If yes, please list possible items. If no, please explain why. (PS: Admins do not merge the PR without this section filled)

  • No. Lineage scoping is purely visual (opacity/border styles). Explorer sort is additive — default "Dependency Chain" maintains all models visible. Backend change only adds a new field to the API response, no existing fields changed.

Database Migrations

  • None required

Env Config

  • None required

Relevant Docs

  • N/A

Related Issues or PRs

Dependencies Versions

  • No dependency changes

Notes on Testing

  • Open a model tab, check lineage: selected model should have dashed blue border, its chain highlighted, unrelated nodes faded
  • Toggle layout direction: scoping should persist
  • Check explorer sort dropdown: Dependency Chain groups parents with children, A-Z/Z-A alphabetical
  • Change model references in Configuration modal: explorer should auto-refresh with updated ordering
  • Child/reference models should appear slightly indented

Screenshots

image

Checklist

- Lineage scoping: highlight selected model's parent/child chain, fade unrelated nodes
- Selected model shown with dashed blue border, related edges in blue
- Explorer: add references to API, dependency chain sort (default), A-Z, Z-A, execution order
- Child models indented in explorer to show hierarchy
- Explorer auto-refreshes on model config save via setRefreshModels
- Applied in both bottom section lineage and standalone LineageTab
@wicky-zipstack wicky-zipstack requested review from a team as code owners April 10, 2026 16:27
@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Apr 10, 2026

Greptile Summary

This PR adds lineage scoping (ancestor/descendant highlighting with opacity fading), a sort dropdown for the model explorer (dep-chain, execution order, A-Z, Z-A), child-model indentation, and explorer auto-refresh on config save. The shared lineage-utils.js utility is a clean extraction, and the backend references field addition is safe and additive.

  • P1 — Child indentation never appears on initial load: transformTree is called before applyModelDecorations in getExplorer, rebuildTree, and the modelsRunning effect. Because transformTree checks node._isChild (which is only written by applyModelDecorations inside setTreeData), the explorer-child-model CSS class is never attached to node data on load. Indentation only becomes visible after the user manually clicks a sort option, which is the one path (handleModelSort) that runs applyModelDecorations before transformTree.

Confidence Score: 4/5

Safe to merge for lineage-scoping and backend changes; child-model indentation should be fixed before shipping to avoid a confusing first-impression where hierarchy is invisible until the user interacts with the sort dropdown.

One P1 defect: child-model indentation is silently broken on all initial-load paths. Lineage scoping and the backend references field are correct and well-implemented, but the highlighted hierarchy-visible-in-explorer UX goal won't be realized until applyModelDecorations is moved before transformTree in the non-sort-click paths.

frontend/src/ide/explorer/explorer-component.jsx — specifically the ordering of transformTree vs applyModelDecorations in getExplorer and rebuildTree.

Important Files Changed

Filename Overview
frontend/src/ide/explorer/explorer-component.jsx Adds dep-chain sort, child-model decorations, and sort dropdown; child-model className is never set on initial load because applyModelDecorations runs after transformTree in all non-sort-click paths.
frontend/src/ide/editor/lineage-utils.js New shared utility extracting getRelatedNodeIds and applyScopedStyles — logic is clean and correctly handles null (no selected node found) via an early-return guard.
frontend/src/ide/editor/lineage-tab/lineage-tab.jsx Integrates optional selectedModelName prop and applies scoped styles from the shared utility; three call sites (initial fetch, layout toggle, sample fetch) are consistently updated.
frontend/src/ide/editor/no-code-model/no-code-model.jsx Applies scoped lineage styles when modelName is available and triggers setRefreshModels(true) after config save to refresh the explorer.
backend/backend/application/file_explorer/file_explorer.py Adds references field to the explorer API response using a safe .get(name, []) lookup; no existing fields changed.
frontend/src/store/project-store.js Adds schemaList to persisted store and a setSchemaList action — straightforward additive change.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[getExplorer / rebuildTree] --> B["transformTree(freshData)\n(no _isChild yet → className NOT set)"]
    B --> C["setTreeData(freshData)"]
    C --> D["treeNoCodeModeTitleIcon(el.children)"]
    D --> E["sortModels(children, modelSortBy)"]
    E --> F["applyModelDecorations(children)\n(_isChild = true — but transformTree\nalready ran, className never set)"]
    F --> G["setTree(resp)\n❌ className missing → no indent"]

    H[handleModelSort click] --> I["applyModelDecorations(child.children)\n(_isChild = true)"]
    I --> J["transformTree(freshData)\n(sees _isChild → className set)"]
    J --> K["setTreeData(freshData, false)"]
    K --> L["setTree(resp)\n✅ className present → indent visible"]

    style G fill:#ffcccc,stroke:#cc0000
    style L fill:#ccffcc,stroke:#00aa00
Loading
Prompt To Fix All With AI
This is a comment left during a code review.
Path: frontend/src/ide/explorer/explorer-component.jsx
Line: 427-432

Comment:
**Child indentation never appears on initial load**

`transformTree` is called before `setTreeData` in every code path except `handleModelSort` (`getExplorer`, `rebuildTree`, and the `modelsRunning` effect all follow the same `transformTree → setTreeData` order). `transformTree` sets `className = "explorer-child-model"` only when `node._isChild` is already present, but `_isChild` is written by `applyModelDecorations` which runs *inside* `treeNoCodeModeTitleIcon`, *inside* `setTreeData` — i.e., after `transformTree` has already finished.

Concretely, on first load (`getExplorer`):
1. `transformTree(treeData)` — no `_isChild` flags yet → no `className` set
2. `setTreeData(treeData)``treeNoCodeModeTitleIcon``applyModelDecorations``_isChild` is set, but `transformTree` already ran

The child-model `className` is therefore never attached to the tree-node data, so the CSS indent rule `.explorerTree .ant-tree-treenode.explorer-child-model` never fires. Indentation is only visible after the user manually clicks a sort option (which goes through `handleModelSort`, the one path where `applyModelDecorations` precedes `transformTree`).

Fix: move the `applyModelDecorations` call before `transformTree` in `getExplorer` and `rebuildTree`, or restructure so `transformTree` runs on the already-decorated data.

How can I resolve this? If you propose a fix, please make it concise.

Reviews (6): Last reviewed commit: "fix: wrap handleModelSort in useCallback..." | Re-trigger Greptile

…r external refs

- handleModelSort: pass sortBy directly to sortModels instead of relying on async state
- applyModelDecorations: filter references to only include sibling model names, ignore external table references
Copy link
Copy Markdown
Contributor

@tahierhussain tahierhussain left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wicky-zipstack Please make the following changes:

  1. Add optional chaining wherever necessary in the frontend to avoid runtime errors.
  2. Please add screenshots for the UI changes addressed in this PR to the PR description.

- Remove !important from explorer-child-model padding — use higher specificity selector instead
- Move static sort dropdown items to MODULE_SORT_ITEMS constant outside component
- Memoize sort menu config with useMemo to avoid recreation on every render
- Wrap handleModelSort with useCallback
…le, exec_order

- Extract getRelatedNodeIds and applyScopedStyles into shared lineage-utils.js
- Remove duplicate functions from lineage-tab.jsx and no-code-model.jsx
- Move hardcoded #1677ff to --lineage-selected-border CSS variable (light: #1677ff, dark: #69b1ff)
- Add comment clarifying exec_order fallback uses backend's topological order
- handleModelSort and modelSortMenu were defined before setTreeData, causing
  'Cannot access setTreeData before initialization' ReferenceError
- Moved both after rebuildTree/setTreeData definition to fix initialization order
Copy link
Copy Markdown
Contributor

@tahierhussain tahierhussain left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants