Skip to content

Commit 73c3a32

Browse files
authored
Fix: display empty state if lineage is empty + fix regex for detecting text inside. MODEL (#1029)
* display empty state for when lineage is empty, fix regex for editor * restore last selected tab on refresh
1 parent a492cff commit 73c3a32

8 files changed

Lines changed: 175 additions & 151 deletions

File tree

web/client/openapi.json

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1445,11 +1445,21 @@
14451445
},
14461446
"TableDiff": {
14471447
"title": "TableDiff",
1448-
"required": ["schema_diff", "row_diff"],
1448+
"required": ["schema_diff", "row_diff", "on"],
14491449
"type": "object",
14501450
"properties": {
14511451
"schema_diff": { "$ref": "#/components/schemas/SchemaDiff" },
1452-
"row_diff": { "$ref": "#/components/schemas/RowDiff" }
1452+
"row_diff": { "$ref": "#/components/schemas/RowDiff" },
1453+
"on": {
1454+
"title": "On",
1455+
"type": "array",
1456+
"items": {
1457+
"maxItems": 2,
1458+
"minItems": 2,
1459+
"type": "array",
1460+
"items": [{ "type": "string" }, { "type": "string" }]
1461+
}
1462+
}
14531463
}
14541464
},
14551465
"ValidationError": {

web/client/src/context/editor.ts

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export interface Lineage {
1717
}
1818

1919
interface EditorStore {
20+
storedTabsId?: ID
2021
storedTabsIds: ID[]
2122
tabs: Map<ModelFile, EditorTab>
2223
tab?: EditorTab
@@ -59,14 +60,17 @@ export interface EditorTab {
5960
preview?: EditorPreview
6061
}
6162

62-
const [getStoredTabs, setStoredTabs] = useLocalStorage<{ ids: ID[] }>('tabs')
63+
const [getStoredTabs, setStoredTabs] = useLocalStorage<{ ids: ID[]; id: ID }>(
64+
'tabs',
65+
)
6366

6467
const initialFile = createLocalFile()
6568
const initialTab: EditorTab = createTab(initialFile)
6669
const initialTabs = new Map([[initialFile, initialTab]])
6770

6871
export const useStoreEditor = create<EditorStore>((set, get) => ({
69-
storedTabsIds: getStoredTabsIds(),
72+
storedTabsIds: getStoredTabs()?.ids ?? [],
73+
storedTabsId: getStoredTabs()?.id,
7074
tab: initialTab,
7175
tabs: initialTabs,
7276
engine: sqlglotWorker,
@@ -76,14 +80,20 @@ export const useStoreEditor = create<EditorStore>((set, get) => ({
7680
previewConsole: undefined,
7781
direction: 'vertical',
7882
updateStoredTabsIds() {
83+
const s = get()
84+
const id = s.tab?.file.id
85+
const ids = Array.from(get().tabs.values())
86+
.filter(tab => tab.file.isRemote)
87+
.map(tab => tab.file.id)
88+
7989
setStoredTabs({
80-
ids: Array.from(get().tabs.values())
81-
.filter(tab => tab.file.isRemote)
82-
.map(tab => tab.file.id),
90+
id,
91+
ids,
8392
})
8493

8594
set(() => ({
86-
storedTabsIds: getStoredTabsIds(),
95+
storedTabsId: id,
96+
storedTabsIds: ids,
8797
}))
8898
},
8999
refreshTab() {
@@ -174,7 +184,3 @@ function createLocalFile(): ModelFile {
174184
'-- Create arbitrary SQL queries\n-- and execute them against different environments\n\n',
175185
})
176186
}
177-
178-
function getStoredTabsIds(): ID[] {
179-
return getStoredTabs()?.ids ?? []
180-
}

web/client/src/library/components/editor/Editor.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ function Editor(): JSX.Element {
2525

2626
const tab = useStoreEditor(s => s.tab)
2727
const storedTabsIds = useStoreEditor(s => s.storedTabsIds)
28+
const storedTabsId = useStoreEditor(s => s.storedTabsId)
2829
const engine = useStoreEditor(s => s.engine)
2930
const selectTab = useStoreEditor(s => s.selectTab)
3031
const createTab = useStoreEditor(s => s.createTab)
@@ -62,7 +63,13 @@ function Editor(): JSX.Element {
6263
useEffect(() => {
6364
files.forEach(file => {
6465
if (storedTabsIds.includes(file.id)) {
65-
addTab(createTab(file))
66+
const tab = createTab(file)
67+
68+
if (storedTabsId === file.id) {
69+
selectTab(tab)
70+
} else {
71+
addTab(tab)
72+
}
6673
}
6774
})
6875
}, [files])

web/client/src/library/components/editor/EditorCode.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import { useApiFileByPath, useMutationApiSaveFile } from '~/api'
2121
import {
2222
debounceAsync,
2323
debounceSync,
24-
isFalse,
24+
isNil,
2525
isStringEmptyOrNil,
2626
isStringNotEmpty,
2727
} from '~/utils'
@@ -360,7 +360,7 @@ const CodeEditor = function CodeEditor({
360360
value={content}
361361
extensions={extensionsAll}
362362
onChange={onChange}
363-
readOnly={isFalse(Boolean(onChange))}
363+
readOnly={isNil(onChange)}
364364
/>
365365
)
366366
}

web/client/src/library/components/editor/extensions/SqlMeshDialect.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,13 +78,11 @@ export function useSqlMeshExtension(): [
7878
lang.language.data.of({
7979
async autocomplete(ctx: CompletionContext) {
8080
const match = ctx.matchBefore(/\w*$/)?.text.trim() ?? ''
81-
const text = ctx.state.doc.toJSON().join('\n')
81+
const text = ctx.state.doc.toString()
8282
const keywordFrom = ctx.matchBefore(/from.+/i)
8383
const keywordKind = ctx.matchBefore(/kind.+/i)
8484
const keywordDialect = ctx.matchBefore(/dialect.+/i)
85-
const matchModels =
86-
text.match(/MODEL \((?:[^)(]+|\((?:[^)(]+|\([^)(]*\))*\))*\)/g) ??
87-
[]
85+
const matchModels = text.match(/MODEL \(([\s\S]*?)\);/gi) ?? []
8886
const isInsideModel = matchModels
8987
.filter(str => str.includes(match))
9088
.map<[number, number]>(str => [
@@ -95,7 +93,6 @@ export function useSqlMeshExtension(): [
9593
([start, end]: [number, number]) =>
9694
ctx.pos >= start && ctx.pos <= end,
9795
)
98-
9996
let suggestions: Completion[] = tables
10097

10198
if (isFalse(isInsideModel)) {

web/client/src/library/components/graph/Graph.tsx

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -754,6 +754,7 @@ function ModelColumnLineage({
754754
const [nodes, setNodes] = useState<Node[]>([])
755755
const [edges, setEdges] = useState<Edge[]>([])
756756
const [isBuildingLayout, setIsBuildingLayout] = useState(true)
757+
const [isEmpty, setIsEmpty] = useState(true)
757758

758759
const nodeTypes = useMemo(() => ({ model: ModelNode }), [])
759760

@@ -775,17 +776,21 @@ function ModelColumnLineage({
775776

776777
useEffect(() => {
777778
setIsBuildingLayout(isArrayEmpty(nodes) || isArrayEmpty(edges))
779+
setIsEmpty(isArrayEmpty(nodesAndEdges.nodes))
780+
781+
if (isArrayEmpty(nodesAndEdges.nodes)) return
778782

779783
void createGraphLayout(nodesAndEdges)
780784
.then(layout => {
781785
toggleEdgeAndNodes(layout.edges, layout.nodes)
782-
setIsBuildingLayout(
783-
isArrayEmpty(layout.nodes) || isArrayEmpty(layout.edges),
784-
)
786+
setIsEmpty(isArrayEmpty(layout.nodes))
785787
})
786788
.catch(error => {
787789
handleError?.(error)
788790
})
791+
.finally(() => {
792+
setIsBuildingLayout(false)
793+
})
789794
}, [nodesAndEdges])
790795

791796
useEffect(() => {
@@ -863,6 +868,12 @@ function ModelColumnLineage({
863868
<h3 className="text-md">Building Lineage...</h3>
864869
</Loading>
865870
</div>
871+
) : isEmpty ? (
872+
<div className="flex justify-center items-center w-full h-full">
873+
<Loading className="inline-block">
874+
<h3 className="text-md">Empty</h3>
875+
</Loading>
876+
</div>
866877
) : (
867878
<ReactFlow
868879
nodes={nodes}

web/client/src/library/pages/ide/IDE.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import { EnumSize, EnumVariant } from '~/types/enum'
2424
import { Link, Outlet, useLocation, useNavigate } from 'react-router-dom'
2525
import { EnumRoutes } from '~/routes'
2626
import { useStoreFileTree } from '@context/fileTree'
27-
import { EnumErrorKey, ErrorIDE, useIDE } from './context'
27+
import { EnumErrorKey, type ErrorIDE, useIDE } from './context'
2828
import { type Model } from '@api/client'
2929
import { Button } from '@components/button/Button'
3030
import { Divider } from '@components/divider/Divider'

0 commit comments

Comments
 (0)