|
1 | | -import React, { useState, useCallback, useRef, useEffect } from "react"; |
| 1 | +import React, { |
| 2 | + useState, |
| 3 | + useCallback, |
| 4 | + useRef, |
| 5 | + useEffect, |
| 6 | + useMemo, |
| 7 | +} from "react"; |
2 | 8 | import { createPortal } from "react-dom"; |
3 | 9 | import PropTypes from "prop-types"; |
4 | 10 | import { |
@@ -58,6 +64,14 @@ import { SpinnerLoader } from "../../widgets/spinner_loader/index.js"; |
58 | 64 | import { useRefreshModelsStore } from "../../store/refresh-models-store.js"; |
59 | 65 | import { LinearScale } from "../../base/icons"; |
60 | 66 |
|
| 67 | +// Static sort options for model explorer |
| 68 | +const MODEL_SORT_ITEMS = [ |
| 69 | + { label: "Dependency Chain", key: "dep_chain" }, |
| 70 | + { label: "Execution Order", key: "exec_order" }, |
| 71 | + { label: "A \u2192 Z", key: "alpha_asc" }, |
| 72 | + { label: "Z \u2192 A", key: "alpha_desc" }, |
| 73 | +]; |
| 74 | + |
61 | 75 | const IdeExplorer = ({ |
62 | 76 | currentNode, |
63 | 77 | onSelect = () => {}, |
@@ -244,24 +258,36 @@ const IdeExplorer = ({ |
244 | 258 | }); |
245 | 259 | }; |
246 | 260 |
|
247 | | - const handleModelSort = (sortBy) => { |
248 | | - setModelSortBy(sortBy); |
249 | | - if (rawTreeDataRef.current.length > 0) { |
250 | | - const freshData = JSON.parse(JSON.stringify(rawTreeDataRef.current)); |
251 | | - freshData.forEach((node) => { |
252 | | - if (node.title === "models" && node.children) { |
253 | | - node.children.forEach((child) => { |
254 | | - if (child.title === "no_code" && child.children) { |
255 | | - child.children = sortModels(child.children, sortBy); |
256 | | - applyModelDecorations(child.children); |
257 | | - } |
258 | | - }); |
259 | | - } |
260 | | - }); |
261 | | - transformTree(freshData); |
262 | | - setTreeData(freshData, false); |
263 | | - } |
264 | | - }; |
| 261 | + const handleModelSort = useCallback( |
| 262 | + (sortBy) => { |
| 263 | + setModelSortBy(sortBy); |
| 264 | + if (rawTreeDataRef.current.length > 0) { |
| 265 | + const freshData = JSON.parse(JSON.stringify(rawTreeDataRef.current)); |
| 266 | + freshData.forEach((node) => { |
| 267 | + if (node.title === "models" && node.children) { |
| 268 | + node.children.forEach((child) => { |
| 269 | + if (child.title === "no_code" && child.children) { |
| 270 | + child.children = sortModels(child.children, sortBy); |
| 271 | + applyModelDecorations(child.children); |
| 272 | + } |
| 273 | + }); |
| 274 | + } |
| 275 | + }); |
| 276 | + transformTree(freshData); |
| 277 | + setTreeData(freshData, false); |
| 278 | + } |
| 279 | + }, |
| 280 | + [setTreeData] |
| 281 | + ); |
| 282 | + |
| 283 | + const modelSortMenu = useMemo( |
| 284 | + () => ({ |
| 285 | + items: MODEL_SORT_ITEMS, |
| 286 | + selectedKeys: [modelSortBy], |
| 287 | + onClick: ({ key }) => handleModelSort(key), |
| 288 | + }), |
| 289 | + [modelSortBy, handleModelSort] |
| 290 | + ); |
265 | 291 |
|
266 | 292 | // Function to map string icons from API to actual icon components |
267 | 293 | // depth: 0 = root (Database), 1 = schema, 2 = table, 3 = column |
@@ -537,22 +563,7 @@ const IdeExplorer = ({ |
537 | 563 | </Typography.Text> |
538 | 564 | </Tooltip> |
539 | 565 | <Dropdown |
540 | | - menu={{ |
541 | | - items: [ |
542 | | - { |
543 | | - label: "Dependency Chain", |
544 | | - key: "dep_chain", |
545 | | - }, |
546 | | - { |
547 | | - label: "Execution Order", |
548 | | - key: "exec_order", |
549 | | - }, |
550 | | - { label: "A \u2192 Z", key: "alpha_asc" }, |
551 | | - { label: "Z \u2192 A", key: "alpha_desc" }, |
552 | | - ], |
553 | | - selectedKeys: [modelSortBy], |
554 | | - onClick: ({ key }) => handleModelSort(key), |
555 | | - }} |
| 566 | + menu={modelSortMenu} |
556 | 567 | trigger={["click"]} |
557 | 568 | placement="bottomRight" |
558 | 569 | > |
|
0 commit comments