Skip to content
This repository was archived by the owner on Feb 28, 2026. It is now read-only.

Commit 616111d

Browse files
authored
Merge pull request #125 from slashbaseide/develop
v0.9.2
2 parents 1089569 + dbb904e commit 616111d

24 files changed

Lines changed: 448 additions & 215 deletions

File tree

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ __debug_bin
1212
*.dll
1313
*.so
1414
*.dylib
15-
15+
*.syso
1616
# Test binary, built with `go test -c`
1717
*.test
1818

frontend/desktop/src/components/dbfragments/jsontable/jsontable.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,12 @@ type JsonTablePropType = {
1616
mName: string,
1717
isInteractive: boolean,
1818
showHeader?: boolean,
19-
onRefresh:()=> void,
19+
onRefresh: () => void,
2020
onFilterChanged: (newFilter: string[] | undefined) => void,
2121
onSortChanged: (newSort: string[] | undefined) => void,
2222
}
2323

24-
const JsonTable = ({ queryData, dbConnection, mName, isInteractive, showHeader, onFilterChanged, onSortChanged ,onRefresh}: JsonTablePropType) => {
24+
const JsonTable = ({ queryData, dbConnection, mName, isInteractive, showHeader, onFilterChanged, onSortChanged, onRefresh }: JsonTablePropType) => {
2525

2626
const dispatch = useAppDispatch()
2727

@@ -171,17 +171,17 @@ const JsonTable = ({ queryData, dbConnection, mName, isInteractive, showHeader,
171171
</div>
172172
</div>
173173
{isInteractive && !isEditing && <React.Fragment>
174-
<div className="column is-3 is-flex is-justify-content-flex-end">
175-
<button className="button is-primary" onClick={() => { setIsEditing(true) }}>
174+
<div className="column is-3 gap-3 is-flex is-justify-content-flex-end">
175+
<button className="button is-secondary mgr-medium" onClick={onRefresh}>
176176
<span className="icon is-small">
177-
<i className="fas fa-pen" />
177+
<i className="fas fa-refresh" />
178178
</span>
179179
</button>
180-
<button className="button is-primary" onClick={onRefresh}>
180+
&nbsp;&nbsp;
181+
<button className="button is-primary" onClick={() => { setIsEditing(true) }}>
181182
<span className="icon is-small">
182-
<i className="fas fa-refresh" />
183+
<i className="fas fa-pen" />
183184
</span>
184-
Refresh
185185
</button>
186186
</div>
187187
</React.Fragment>}

frontend/desktop/src/components/layouts/footer.tsx

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -27,29 +27,17 @@ const Footer = () => {
2727
navigate(Constants.APP_PATHS.SETTINGS_SUPPORT.path)
2828
}
2929

30-
const refreshDataModels = () => {
31-
dispatch(resetDBDataModels())
32-
dispatch(getDBDataModels({ dbConnId: dbConnection!.id }))
33-
}
3430

3531
return (
3632
<footer className={styles.footer}>
3733
<div>
3834
{showStatus && isDBConnected !== undefined &&
3935
(<button className={styles.button + " is-small"}>
4036
<span className="icon is-small">
41-
{!isDBConnected && <i className="far fa-circle" />}
42-
{isDBConnected && <i className="fas fa-circle" />}
43-
</span>
44-
<span>{(isDBConnected !== undefined && isDBConnected) ? "connected" : "not connected"}</span>
45-
</button>)
46-
}
47-
{showStatus && isDBConnected === true &&
48-
(<button className={styles.button + " is-small"} onClick={refreshDataModels}>
49-
<span className="icon is-small">
50-
<i className="fas fa-sync" />
37+
{!isDBConnected && <i className="fa-solid fa-circle-exclamation" style={{ color: "#ff0000" }} />}
38+
{isDBConnected && <i className="fas fa-circle" style={{ color: "#11ff00" }} />}
5139
</span>
52-
<span>refresh data models</span>
40+
<span>{(isDBConnected !== undefined && isDBConnected) ? " connected" : " not connected"}</span>
5341
</button>)
5442
}
5543
</div>

frontend/desktop/src/components/layouts/header.module.scss

Lines changed: 90 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,109 @@
1818
border-radius: 8px;
1919
transition: all .2s;
2020
margin-right: 5px;
21+
transition: background-color 100ms linear;
2122
.btnMsg {
2223
font-size: 12px;
2324
display: none;
2425
}
2526
}
2627
.btn:hover {
2728
background: #000000;
29+
transition-duration: 0ms;
2830
.btnMsg {
2931
display: inline;
3032
}
33+
3134
}
35+
.btn.home{
36+
z-index: 2;
37+
margin-right: 1px;
38+
border-radius: 0px;
39+
position: relative;
40+
border-top-left-radius: 8px;
41+
border-bottom-left-radius: 8px;
42+
&:after{
43+
44+
content: '';
45+
position: absolute;
46+
border-style: solid;
47+
border-left-width:8px;
48+
margin-left:1px;
49+
top: -1%;
50+
left: 100%;
51+
border-color: #363636;
52+
border-top-color: transparent;
53+
border-top-width:20px;
54+
border-bottom-color: transparent;
55+
border-bottom-width: 20px;
56+
border-right-color: transparent;
57+
transition: border-color 110ms linear;
58+
59+
}
60+
&:hover::after{
61+
border-left-color: #000000;
62+
transition-duration: 1ms;
63+
}
64+
}
65+
.bread{
66+
padding-left: 20px;
67+
z-index: 1;
68+
border-radius: 1px;
69+
position: relative;
70+
&:after{
71+
content: '';
72+
position: absolute;
73+
border-style: solid;
74+
border-left-width:8px;
75+
margin-left:0.5px;
76+
77+
top: -1%;
78+
left: 100%;
79+
border-color: #363636;
80+
border-top-color: transparent;
81+
border-top-width:20px;
82+
border-bottom-color: transparent;
83+
border-bottom-width: 20px;
84+
border-right-color: transparent;
85+
transition: border-color 110ms linear;
86+
}
87+
&:before{
88+
89+
content: '';
90+
position:absolute;
91+
border-style: solid;
92+
border-left-width: 8px;
93+
top: -1;
94+
left: -0.5px;
95+
border-color: #262626;
96+
border-top-color: transparent;
97+
border-bottom-color: transparent;
98+
border-top-width:20px;
99+
border-bottom-width: 20px;
100+
border-right-color: transparent;
101+
transition: border-color 110ms linear;
102+
}
103+
&:hover::after{
104+
z-index: 3;
105+
border-left-color: #000000;
106+
transition-duration: 1ms;
107+
}
108+
}
109+
.dbBread{
110+
padding-left: 20px;
111+
margin-left:-5px;
112+
z-index: 0;
113+
}
114+
.breadEnds{
115+
border-top-right-radius: 8px;
116+
border-bottom-right-radius: 8px;
117+
&:after{
118+
all:initial;
119+
}
120+
}
32121
}
33122
.headerCenter{
34-
height: 40px;
123+
height: 40px;
35124
}
36125
.headerMenu {
37126
display: flex;

frontend/desktop/src/components/layouts/header.tsx

Lines changed: 97 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,11 @@ import { DBConnection, Project } from '../../data/models'
77
import { useAppDispatch, useAppSelector } from '../../redux/hooks'
88
import { selectIsShowingSidebar, setIsShowingSidebar } from '../../redux/configSlice'
99
import { selectProjects } from '../../redux/projectsSlice'
10-
import { selectDBConnection } from '../../redux/dbConnectionSlice'
10+
import { selectAllDBConnections } from '../../redux/allDBConnectionsSlice'
11+
import { selectDBConnection, getDBDataModels, resetDBDataModels } from '../../redux/dbConnectionSlice'
1112
import utils from '../../lib/utils'
13+
import { Tooltip } from 'react-tooltip'
14+
import 'react-tooltip/dist/react-tooltip.css'
1215

1316
const Header = () => {
1417

@@ -19,17 +22,15 @@ const Header = () => {
1922
const dispatch = useAppDispatch()
2023

2124
const projects: Project[] = useAppSelector(selectProjects)
25+
const dbConnections: DBConnection[] = useAppSelector(selectAllDBConnections)
2226
const currentDBConnection: DBConnection | undefined = useAppSelector(selectDBConnection)
2327
const isShowingSidebar: boolean = useAppSelector(selectIsShowingSidebar)
2428

2529

2630
const [isShowingDropDown, setIsShowingDropDown] = useState(false)
2731
const [isShowingNavDropDown, setIsShowingNavDropDown] = useState(false)
32+
const [isShowingDBDropDown, setIsShowingDBDropdown] = useState(false)
2833

29-
const options = [
30-
{ value: 'home', label: 'Home', path: Constants.APP_PATHS.HOME.path },
31-
...projects.map((x: Project) => ({ value: x.id, label: x.name, path: Constants.APP_PATHS.PROJECT.path.replace('[id]', x.id) }))
32-
]
3334

3435
const onNavigate = (option: {
3536
value: string;
@@ -44,54 +45,114 @@ const Header = () => {
4445
dispatch(setIsShowingSidebar(!isShowingSidebar))
4546
}
4647

47-
let currentOption = 'home'
48+
let currentProjectOption: String | undefined = undefined;
49+
let currentDBOption: string | undefined = undefined;
4850
if (location.pathname.startsWith('/project'))
49-
currentOption = String(params.id)
51+
currentProjectOption = String(params.id)
5052
else if (location.pathname.startsWith('/db')) {
5153
if (currentDBConnection)
52-
currentOption = currentDBConnection?.projectId
54+
currentProjectOption = currentDBConnection?.projectId
55+
currentDBOption = currentDBConnection?.id
56+
}
57+
58+
const projectOptions = [
59+
60+
...projects.map((x: Project) => ({ value: x.id, label: x.name, path: Constants.APP_PATHS.PROJECT.path.replace('[id]', x.id) }))
61+
]
62+
const dbOptions = [
63+
...dbConnections.filter((x: DBConnection) => (x.projectId === currentProjectOption)).map((x: DBConnection) => ({ value: x.id, label: x.name, path: Constants.APP_PATHS.DB.path.replace('[id]', x.id) }))
64+
]
65+
66+
const refreshDataModels = () => {
67+
dispatch(resetDBDataModels())
68+
dispatch(getDBDataModels({ dbConnId: currentDBConnection!.id }))
5369
}
5470

5571
return (
5672
<header className={styles.header}>
5773
<div className={styles.leftBtns}>
58-
{!isShowingSidebar && <button className={"button is-dark " + [styles.btn].join(' ')} onClick={toggleSidebar}>
74+
{!isShowingSidebar ? (<button className={"button is-dark " + [styles.btn].join(' ')} onClick={toggleSidebar}>
75+
<i className="fas fa-bars" />
76+
</button>) : (<button className={"button is-dark " + [styles.btn].join(' ')} onClick={toggleSidebar}>
5977
<i className="fas fa-bars" />
60-
</button>}
78+
</button>)}
6179
<Link to={Constants.APP_PATHS.HOME.path}>
62-
<button className={"button is-dark " + [styles.btn].join(' ')}>
80+
<button className={`button is-dark ` + [styles.btn, currentProjectOption !== undefined ? styles.home : ''].join(' ')}>
6381
<span className="icon">
6482
<i className={`fas fa-home`} />
6583
</span>
6684
</button>
6785
</Link>
68-
</div>
69-
<div className={styles.headerCenter}>
70-
<div className={`dropdown${isShowingNavDropDown ? ' is-active' : ''}`}>
71-
<div className="dropdown-trigger">
72-
<button className={"button is-dark " + styles.btn} aria-haspopup="true" aria-controls="dropdown-menu" onClick={() => { setIsShowingNavDropDown(!isShowingNavDropDown) }}>
73-
<span>{options.find(x => x.value === currentOption)?.label}</span>
74-
<span className="icon is-small">
75-
<i className="fas fa-angle-down" aria-hidden="true"></i>
76-
</span>
77-
</button>
78-
</div>
79-
<OutsideClickHandler onOutsideClick={() => { setIsShowingNavDropDown(false) }}>
80-
<div className="dropdown-menu" id="dropdown-menu" role="menu">
81-
<div className="dropdown-content">
82-
{options.map((x) => {
83-
return (
84-
<React.Fragment key={x.value}>
85-
<a onClick={() => { onNavigate(x) }} className={`dropdown-item${x.value === currentOption ? ' is-active' : ''}`}>
86-
{x.label}
87-
</a>
88-
{x.value === 'home' && <hr className="dropdown-divider" />}
89-
</React.Fragment>
90-
)
91-
})}
86+
<div className={styles.headerCenter}>
87+
{currentProjectOption !== undefined && <div className={`dropdown${isShowingNavDropDown ? ' is-active' : ''}`}>
88+
<div className={`dropdown-trigger`}>
89+
<button className={"button is-dark " + [styles.btn, styles.bread, currentDBOption === undefined ? styles.breadEnds : ''].join(' ')} aria-haspopup="true" aria-controls="dropdown-menu" onClick={() => { setIsShowingNavDropDown(!isShowingNavDropDown) }}>
90+
<span className='icon'>
91+
<i className="fas fa-folder" aria-hidden="true"></i>
92+
</span>
93+
<span>{projectOptions.find(x => x.value === currentProjectOption)?.label}</span>
94+
<span className="icon">
95+
<i className="fas fa-angle-down" aria-hidden="true"></i>
96+
</span>
97+
</button>
98+
</div>
99+
<OutsideClickHandler onOutsideClick={() => { setIsShowingNavDropDown(false) }}>
100+
<div className="dropdown-menu" id="dropdown-menu" role="menu">
101+
<div className="dropdown-content">
102+
{projectOptions.map((x) => {
103+
return (
104+
<React.Fragment key={x.value}>
105+
<a onClick={() => { onNavigate(x) }} className={`dropdown-item${x.value === currentProjectOption ? ' is-active' : ''}`}>
106+
{x.label}
107+
</a>
108+
{x.value === 'home' && <hr className="dropdown-divider" />}
109+
</React.Fragment>
110+
)
111+
})}
112+
</div>
92113
</div>
114+
</OutsideClickHandler>
115+
</div>}
116+
{currentProjectOption !== undefined && currentDBOption !== undefined && <div className={`dropdown${isShowingDBDropDown ? ' is-active' : ''}`}>
117+
<div className={`dropdown-trigger`}>
118+
<button className={"button is-dark " + [styles.btn, styles.bread, styles.dbBread, styles.breadEnds].join(' ')} aria-haspopup="true" aria-controls="dropdown-menu" onClick={() => { setIsShowingDBDropdown(!isShowingDBDropDown) }}>
119+
<span className='icon'>
120+
<i className="fas fa-database" aria-hidden="true"></i>
121+
</span>
122+
<span>{dbOptions.find(x => x.value === currentDBOption)?.label}</span>
123+
<span className="icon">
124+
<i className="fas fa-angle-down" aria-hidden="true"></i>
125+
</span>
126+
</button>
93127
</div>
94-
</OutsideClickHandler>
128+
<OutsideClickHandler onOutsideClick={() => { setIsShowingDBDropdown(false) }}>
129+
<div className="dropdown-menu" id="dropdown-menu" role="menu">
130+
<div className="dropdown-content">
131+
{dbOptions.map((x) => {
132+
return (
133+
<React.Fragment key={x.value}>
134+
<a onClick={() => { onNavigate(x) }} className={`dropdown-item${x.value === currentDBOption ? ' is-active' : ''}`}>
135+
{x.label}
136+
</a>
137+
{x.value === 'home' && <hr className="dropdown-divider" />}
138+
</React.Fragment>
139+
)
140+
})}
141+
</div>
142+
</div>
143+
</OutsideClickHandler>
144+
{currentDBOption !== undefined &&
145+
<div>
146+
<button id="refreshBtn" data-tooltip-content="Refresh data models" className={" button is-dark is-small" + [styles.btn].join(' ')} onClick={refreshDataModels} >
147+
<span className="icon is-small">
148+
<i className="fas fa-sync" />
149+
</span>
150+
</button>
151+
<Tooltip anchorId="refreshBtn" />
152+
</div>
153+
}
154+
</div>
155+
}
95156
</div>
96157
</div>
97158
<div className={styles.headerMenu}>

0 commit comments

Comments
 (0)