@@ -7,6 +7,7 @@ import { AGENTS_ENABLED, canAccessHomeSection, getConnectionAccessBadge, getConn
77import { PERMISSIONS } from '@/lib/permissions'
88import ManageConnectionsModal from '@/components/ManageConnectionsModal'
99import SettingsModal from '@/components/SettingsModal'
10+ import ProfileSwitch from './ProfileSwitch'
1011import { useAuth } from '@/hooks/useAuth'
1112import styles from './AppSidebar.module.css'
1213
@@ -30,7 +31,7 @@ export default function AppSidebar() {
3031 const [ showConnectionDropdown , setShowConnectionDropdown ] = useState ( false )
3132 const userMenuRef = useRef ( null )
3233 const connectionDropdownRef = useRef ( null )
33- const { logout, role, username, impersonating, permissions, hasPermission } = useAuth ( )
34+ const { logout, role, username, impersonating, permissions, hasPermission, canSwitchProfile } = useAuth ( )
3435 // Connections (add/edit/delete a database) is administrative: the backend already
3536 // refuses it to Developer and Data Engineer with 403, so hiding the button stops the
3637 // UI offering a door that only leads to an error. Settings is likewise administrative
@@ -137,12 +138,13 @@ export default function AppSidebar() {
137138 { /* Bottom: connections + profile */ }
138139 < div className = { styles . divider } />
139140 < div className = { styles . bottom } >
141+ { canSwitchProfile && < ProfileSwitch collapsed = { collapsed } /> }
140142 < div className = { styles . connectionSwitcher } ref = { connectionDropdownRef } >
141143 < button
142144 className = { styles . bottomItem }
143145 onClick = { ( ) => setShowConnectionDropdown ( ( v ) => ! v ) }
144146 title = { collapsed ? connectionLabel : undefined }
145- disabled = { isLoading || connections . length === 0 }
147+ disabled = { isLoading || ( connections . length === 0 && ! canManageConnections ) }
146148 >
147149 < Database size = { 15 } className = { styles . navIcon } />
148150 < span className = { `${ styles . navLabel } ${ collapsed ? styles . navLabelHidden : '' } ` } >
@@ -154,62 +156,69 @@ export default function AppSidebar() {
154156 { ! collapsed && < ChevronDown size = { 14 } className = { styles . chevronIcon } /> }
155157 </ button >
156158
157- { showConnectionDropdown && ! collapsed && connections . length > 0 && (
159+ { showConnectionDropdown && ! collapsed && (
158160 < div className = { styles . connectionDropdown } >
159- < div className = { styles . dropdownLabel } > Connections</ div >
160- { connections . map ( ( conn ) => (
161- < div
162- key = { conn . id }
163- className = { `${ styles . dropdownRow } ${ conn . id === connectionId ? styles . dropdownItemActive : '' } ` }
164- >
161+ { connections . length > 0 && (
162+ < >
163+ < div className = { styles . dropdownLabel } > Connections</ div >
164+ { connections . map ( ( conn ) => (
165+ < div
166+ key = { conn . id }
167+ className = { `${ styles . dropdownRow } ${ conn . id === connectionId ? styles . dropdownItemActive : '' } ` }
168+ >
169+ < button
170+ className = { styles . dropdownItem }
171+ onClick = { ( ) => {
172+ changeConnection ( conn . id )
173+ setShowConnectionDropdown ( false )
174+ } }
175+ >
176+ < Database size = { 14 } />
177+ < span className = { styles . dropdownItemName } >
178+ { conn . connectionName }
179+ { getConnectionAccessLabel ( conn ) ? ` · ${ getConnectionAccessLabel ( conn ) } ` : '' }
180+ </ span >
181+ < span className = { styles . dbTypeBadge } > { getConnectionAccessBadge ( conn ) || conn . dbType } </ span >
182+ { conn . id === connectionId && < Check size = { 13 } className = { styles . dropdownItemCheck } /> }
183+ </ button >
184+ < button
185+ className = { `${ styles . dropdownPin } ${ conn . pinned ? styles . dropdownPinActive : '' } ` }
186+ onClick = { ( ) =>
187+ setConnectionPin . mutate ( { connectionId : conn . id , pinned : ! conn . pinned } )
188+ }
189+ disabled = { setConnectionPin . isPending }
190+ aria-pressed = { Boolean ( conn . pinned ) }
191+ title = {
192+ conn . pinned
193+ ? 'Pinned as your default — DeepSQL opens on this connection. Click to unpin.'
194+ : 'Pin as your default — DeepSQL will open on this connection every time you load it.'
195+ }
196+ >
197+ < Pin size = { 13 } />
198+ </ button >
199+ </ div >
200+ ) ) }
201+ </ >
202+ ) }
203+ { canManageConnections && (
204+ < >
205+ { connections . length > 0 && < div className = { styles . dropdownDivider } /> }
165206 < button
166- className = { styles . dropdownItem }
207+ className = { styles . dropdownManage }
167208 onClick = { ( ) => {
168- changeConnection ( conn . id )
169209 setShowConnectionDropdown ( false )
210+ setShowConnections ( true )
170211 } }
171212 >
172- < Database size = { 14 } />
173- < span className = { styles . dropdownItemName } >
174- { conn . connectionName }
175- { getConnectionAccessLabel ( conn ) ? ` · ${ getConnectionAccessLabel ( conn ) } ` : '' }
176- </ span >
177- < span className = { styles . dbTypeBadge } > { getConnectionAccessBadge ( conn ) || conn . dbType } </ span >
178- { conn . id === connectionId && < Check size = { 13 } className = { styles . dropdownItemCheck } /> }
213+ < Settings size = { 14 } />
214+ < span > Manage connections…</ span >
179215 </ button >
180- < button
181- className = { `${ styles . dropdownPin } ${ conn . pinned ? styles . dropdownPinActive : '' } ` }
182- onClick = { ( ) =>
183- setConnectionPin . mutate ( { connectionId : conn . id , pinned : ! conn . pinned } )
184- }
185- disabled = { setConnectionPin . isPending }
186- aria-pressed = { Boolean ( conn . pinned ) }
187- title = {
188- conn . pinned
189- ? 'Pinned as your default — DeepSQL opens on this connection. Click to unpin.'
190- : 'Pin as your default — DeepSQL will open on this connection every time you load it.'
191- }
192- >
193- < Pin size = { 13 } />
194- </ button >
195- </ div >
196- ) ) }
216+ </ >
217+ ) }
197218 </ div >
198219 ) }
199220 </ div >
200221
201- { canManageConnections && (
202- < button
203- className = { styles . bottomItem }
204- onClick = { ( ) => setShowConnections ( true ) }
205- title = { collapsed ? 'Connections' : undefined }
206- >
207- < Settings size = { 15 } className = { styles . navIcon } />
208- < span className = { `${ styles . navLabel } ${ collapsed ? styles . navLabelHidden : '' } ` } >
209- Connections
210- </ span >
211- </ button >
212- ) }
213222 < div className = { styles . userMenuWrap } ref = { userMenuRef } >
214223 < button
215224 className = { styles . bottomItem }
0 commit comments