Skip to content

Commit 84a8997

Browse files
committed
feat: add good indictation when no database is selected
1 parent 5de8a0c commit 84a8997

File tree

3 files changed

+152
-99
lines changed

3 files changed

+152
-99
lines changed

src/renderer/components/DatabaseTable/DatabaseSelection.tsx

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,27 @@ function DatabaseSelectionModal({
3232

3333
const { common } = useSqlExecute();
3434

35+
const openDatabase = useCallback(
36+
(databaseName: string) => {
37+
if (databaseName !== currentDatabase && databaseName) {
38+
common
39+
.switchDatabase(databaseName)
40+
.then((result) => {
41+
if (result) {
42+
onClose();
43+
}
44+
})
45+
.catch(console.error);
46+
}
47+
},
48+
[onClose, common, currentDatabase]
49+
);
50+
3551
const onOpenClicked = useCallback(() => {
36-
if (selectedDatabase !== currentDatabase && selectedDatabase) {
37-
common
38-
.switchDatabase(selectedDatabase)
39-
.then((result) => {
40-
if (result) {
41-
onClose();
42-
}
43-
})
44-
.catch(console.error);
52+
if (selectedDatabase) {
53+
openDatabase(selectedDatabase);
4554
}
46-
}, [common, selectedDatabase, currentDatabase, onClose]);
55+
}, [openDatabase, selectedDatabase]);
4756

4857
return (
4958
<Modal open={open} title="Database Selection" onClose={onClose}>
@@ -56,6 +65,9 @@ function DatabaseSelectionModal({
5665
selectedItem={selectedDatabase}
5766
onSelectChange={(item) => setSelectedDatabase(item)}
5867
items={databaseList}
68+
onDoubleClick={(item) => {
69+
openDatabase(item);
70+
}}
5971
extractMeta={(database) => ({
6072
text: database,
6173
key: database,
@@ -88,9 +100,23 @@ export default function DatabaseSelection() {
88100
return (
89101
<>
90102
<div className={styles.header} onClick={onOpen}>
91-
<FontAwesomeIcon icon={faDatabase} color="#27ae60" />
92-
<span>{currentDatabase}</span>
93-
<FontAwesomeIcon icon={faChevronRight} />
103+
{currentDatabase ? (
104+
<>
105+
<FontAwesomeIcon icon={faDatabase} color="#27ae60" />
106+
<span>{currentDatabase}</span>
107+
<FontAwesomeIcon icon={faChevronRight} />
108+
</>
109+
) : (
110+
<>
111+
<div>
112+
<div className={styles.ping}></div>
113+
</div>
114+
<span>
115+
<i>Please select database</i>
116+
</span>
117+
<FontAwesomeIcon icon={faChevronRight} />
118+
</>
119+
)}
94120
</div>
95121
<DatabaseSelectionModal onClose={onClose} open={open} />
96122
</>

src/renderer/components/DatabaseTable/DatabaseTableList.tsx

Lines changed: 88 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { useContextMenu } from 'renderer/contexts/ContextMenuProvider';
1616
import SqlTableSchemaTab from 'renderer/screens/DatabaseScreen/SqlTableSchemaTab';
1717
import Layout from '../Layout';
1818
import DatabaseSelection from './DatabaseSelection';
19+
import ListViewEmptyState from '../ListView/ListViewEmptyState';
1920

2021
export default function DatabaseTableList() {
2122
const { schema, currentDatabase } = useSchmea();
@@ -27,9 +28,11 @@ export default function DatabaseTableList() {
2728
}>
2829
>();
2930
const { newWindow } = useWindowTab();
30-
const [collapsed, setCollapsed] = useState<string[] | undefined>(
31-
currentDatabase ? [`database/${currentDatabase}`] : []
32-
);
31+
const [collapsed, setCollapsed] = useState<string[] | undefined>([
32+
'tables',
33+
'events',
34+
'triggers',
35+
]);
3336

3437
const { handleContextMenu } = useContextMenu(() => {
3538
const tableName = selected?.data?.name;
@@ -71,65 +74,61 @@ export default function DatabaseTableList() {
7174

7275
const schemaListItem = useMemo(() => {
7376
if (!schema) return [];
77+
if (!currentDatabase) return [];
7478

75-
return Object.values(schema).map((database) => {
76-
let children = Object.values(database.tables).map((table) => ({
77-
id: `database/${database.name}/table/${table.name}`,
78-
text: table.name,
79-
icon:
80-
table.type === 'TABLE' ? (
81-
<FontAwesomeIcon icon={faTableList} color="#3498db" />
82-
) : (
83-
<FontAwesomeIcon icon={faEye} color="#e67e22" />
84-
),
85-
data: {
86-
name: table.name,
87-
type: table.type === 'TABLE' ? 'table' : 'view',
88-
database: database.name,
89-
},
90-
}));
91-
92-
if (database.events.length > 0) {
93-
children = children.concat(
94-
database.events.map((event) => ({
95-
id: `database/${database.name}/event/${event}`,
96-
text: event,
97-
icon: <FontAwesomeIcon icon={faCalendar} color="#27ae60" />,
98-
data: {
99-
name: event,
100-
type: 'event',
101-
database: database.name,
102-
},
103-
}))
104-
);
105-
}
79+
const currentDatabaseSchema = schema[currentDatabase];
80+
if (!currentDatabaseSchema) return [];
10681

107-
if (database.triggers.length > 0) {
108-
children = children.concat(
109-
database.triggers.map((trigger) => ({
110-
id: `database/${database.name}/trigger/${trigger}`,
111-
text: trigger,
112-
icon: <FontAwesomeIcon icon={faGear} color="#bdc3c7" />,
113-
data: {
114-
name: trigger,
115-
database: database.name,
116-
type: 'trigger',
117-
},
118-
}))
119-
);
120-
}
121-
122-
children.sort((item1, item2) => {
123-
return item1.text.localeCompare(item2.text);
124-
});
125-
126-
return {
127-
id: `database/${database.name}`,
128-
text: database.name,
129-
children,
130-
};
131-
});
132-
}, [schema]);
82+
return [
83+
{
84+
id: 'tables',
85+
text: `Tables (${Object.values(currentDatabaseSchema.tables).length})`,
86+
children: Object.values(currentDatabaseSchema.tables).map((table) => ({
87+
id: `table/${table.name}`,
88+
text: table.name,
89+
icon:
90+
table.type === 'TABLE' ? (
91+
<FontAwesomeIcon icon={faTableList} color="#3498db" />
92+
) : (
93+
<FontAwesomeIcon icon={faEye} color="#e67e22" />
94+
),
95+
data: {
96+
name: table.name,
97+
type: table.type === 'TABLE' ? 'table' : 'view',
98+
database: currentDatabase,
99+
},
100+
})),
101+
},
102+
{
103+
id: 'events',
104+
text: `Events (${currentDatabaseSchema.events.length})`,
105+
children: currentDatabaseSchema.events.map((event) => ({
106+
id: `event/${event}`,
107+
text: event,
108+
icon: <FontAwesomeIcon icon={faCalendar} color="#27ae60" />,
109+
data: {
110+
name: event,
111+
type: 'event',
112+
database: currentDatabase,
113+
},
114+
})),
115+
},
116+
{
117+
id: 'triggers',
118+
text: `Triggers (${currentDatabaseSchema.triggers.length})`,
119+
children: currentDatabaseSchema.triggers.map((trigger) => ({
120+
id: `trigger/${trigger}`,
121+
text: trigger,
122+
icon: <FontAwesomeIcon icon={faGear} color="#bdc3c7" />,
123+
data: {
124+
name: trigger,
125+
database: currentDatabase,
126+
type: 'trigger',
127+
},
128+
})),
129+
},
130+
];
131+
}, [schema, currentDatabase]);
133132

134133
if (!schema) return <div />;
135134

@@ -140,33 +139,36 @@ export default function DatabaseTableList() {
140139
<DatabaseSelection />
141140
</Layout.Fixed>
142141
<Layout.Grow>
143-
<TreeView
144-
selected={selected}
145-
onSelectChange={setSelected}
146-
collapsedKeys={collapsed}
147-
onCollapsedChange={setCollapsed}
148-
onContextMenu={handleContextMenu}
149-
onDoubleClick={(item) => {
150-
const tableName = item.data?.name;
151-
const type = item.data?.type;
152-
if ((type === 'table' || type === 'view') && tableName) {
153-
newWindow(`SELECT ${tableName}`, (key, name) => (
154-
<QueryWindow
155-
initialSql={new QueryBuilder('mysql')
156-
.table(tableName)
157-
.limit(200)
158-
.toRawSQL()}
159-
initialRun
160-
tabKey={key}
161-
name={name}
162-
/>
163-
));
164-
}
165-
}}
166-
items={schemaListItem}
167-
/>
142+
{currentDatabase ? (
143+
<TreeView
144+
selected={selected}
145+
onSelectChange={setSelected}
146+
collapsedKeys={collapsed}
147+
onCollapsedChange={setCollapsed}
148+
onContextMenu={handleContextMenu}
149+
onDoubleClick={(item) => {
150+
const tableName = item.data?.name;
151+
const type = item.data?.type;
152+
if ((type === 'table' || type === 'view') && tableName) {
153+
newWindow(`SELECT ${tableName}`, (key, name) => (
154+
<QueryWindow
155+
initialSql={new QueryBuilder('mysql')
156+
.table(tableName)
157+
.limit(200)
158+
.toRawSQL()}
159+
initialRun
160+
tabKey={key}
161+
name={name}
162+
/>
163+
));
164+
}
165+
}}
166+
items={schemaListItem}
167+
/>
168+
) : (
169+
<ListViewEmptyState text="Please select database to see tables, events, triggers, etc..." />
170+
)}
168171
</Layout.Grow>
169-
<Layout.Fixed>Footer</Layout.Fixed>
170172
</Layout>
171173
</div>
172174
);

src/renderer/components/DatabaseTable/styles.module.scss

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
@keyframes ping {
2+
0% {
3+
transform: scale(1);
4+
background: #e74c3c;
5+
}
6+
50% {
7+
transform: scale(1.5);
8+
background: #ff7979;
9+
}
10+
100% {
11+
transform: scale(1);
12+
background: #ff7979;
13+
}
14+
}
15+
16+
117
.tables {
218
background: var(--color-list-surface);
319
height: 100%
@@ -14,4 +30,13 @@
1430
span {
1531
flex-grow: 1;
1632
}
33+
}
34+
35+
.ping {
36+
display: inline-block;
37+
height: 10px;
38+
width: 10px;
39+
background: #e74c3c;
40+
border-radius: 50%;
41+
animation: ping 1s ease-out infinite;
1742
}

0 commit comments

Comments
 (0)