1
- import {
2
- ChevronDownIcon ,
3
- ChevronLeftIcon ,
4
- PencilAltIcon ,
5
- PlusCircleIcon ,
6
- PlusIcon ,
7
- } from "@heroicons/react/outline" ;
8
- import { Collapse , Tooltip , useDisclosure } from "@chakra-ui/react" ;
9
- import { ListTable } from "@/plugins/data-sources/abstract-sql-query-service/types" ;
10
- import { View } from "@prisma/client" ;
11
- import { first , isUndefined } from "lodash" ;
1
+ import { PencilAltIcon } from "@heroicons/react/outline" ;
12
2
import { useACLHelpers } from "@/features/authorization/hooks" ;
13
- import { useDataSourceContext , useProfile } from "@/hooks" ;
3
+ import { useDataSourceContext } from "@/hooks" ;
14
4
import { useDataSourceResponse } from "@/features/data-sources/hooks" ;
15
- import { useGetTablesQuery } from "@/features/tables/api-slice" ;
16
- import { useGetViewsQuery } from "@/features/views/api-slice" ;
17
- import { usePrefetch } from "@/features/fields/api-slice" ;
5
+ import DashboardSidebarSection from "@/features/dashboards/components/DashboardsSidebarSection" ;
18
6
import Link from "next/link" ;
19
- import React , { memo , useMemo } from "react" ;
7
+ import React , { memo } from "react" ;
20
8
import Shimmer from "./Shimmer" ;
21
- import SidebarItem from "./SidebarItem" ;
9
+ import TablesSidebarSection from "@/features/tables/components/TablesSidebarSection" ;
10
+ import ViewsSidebarSection from "@/features/views/components/ViewsSidebarSection" ;
22
11
23
12
const Sidebar = ( ) => {
24
- const { dataSourceId, tableName, viewId } = useDataSourceContext ( ) ;
25
-
26
- const { user, isLoading : sessionIsLoading } = useProfile ( ) ;
27
-
13
+ const { dataSourceId } = useDataSourceContext ( ) ;
28
14
const {
29
15
dataSource,
30
- info,
31
16
isLoading : dataSourceIsLoading ,
32
17
info : dataSourceInfo ,
33
18
} = useDataSourceResponse ( dataSourceId ) ;
34
-
35
19
const { isOwner } = useACLHelpers ( { dataSourceInfo } ) ;
36
20
37
- const {
38
- data : tablesResponse ,
39
- isLoading : tablesAreLoading ,
40
- error : tablesError ,
41
- } = useGetTablesQuery ( { dataSourceId } , { skip : ! dataSourceId } ) ;
42
-
43
- const {
44
- data : viewsResponse ,
45
- isLoading : viewsAreLoading ,
46
- error : viewsError ,
47
- } = useGetViewsQuery ( ) ;
48
-
49
- const prefetchColumns = usePrefetch ( "getColumns" ) ;
50
-
51
- const { isOpen : isTablesOpen , onToggle : toggleTablesOpen } = useDisclosure ( {
52
- defaultIsOpen : true ,
53
- } ) ;
54
- const { isOpen : isViewsOpen , onToggle : toggleViewsOpen } = useDisclosure ( {
55
- defaultIsOpen : true ,
56
- } ) ;
57
-
58
- const views = useMemo (
59
- ( ) => ( viewsResponse ?. ok ? viewsResponse ?. data : [ ] ) ,
60
- [ viewsResponse ]
61
- ) ;
62
-
63
- const filteredViews = useMemo (
64
- ( ) =>
65
- views . filter (
66
- ( view : View ) =>
67
- ( view . createdBy === user . id || view . public === true ) &&
68
- view . dataSourceId === parseInt ( dataSourceId )
69
- ) ,
70
- [ views , dataSourceId ]
71
- ) ;
72
-
73
- const viewsLoading = useMemo (
74
- ( ) => viewsAreLoading || sessionIsLoading ,
75
- [ viewsAreLoading || sessionIsLoading ]
76
- ) ;
77
-
78
- const tablesLoading = useMemo (
79
- ( ) => tablesAreLoading || sessionIsLoading ,
80
- [ tablesAreLoading || sessionIsLoading ]
81
- ) ;
82
-
83
- const ViewsSection = ( ) => (
84
- < >
85
- < div className = "relative space-y-1 flex-col" >
86
- < div className = "flex justify-between w-full" >
87
- < div
88
- className = "text-md font-semibold py-2 px-2 rounded-md leading-none m-0 w-full cursor-pointer"
89
- onClick = { toggleViewsOpen }
90
- >
91
- Views{ " " }
92
- { isViewsOpen ? (
93
- < ChevronDownIcon className = "h-3 inline" />
94
- ) : (
95
- < ChevronLeftIcon className = "h-3 inline" />
96
- ) }
97
- </ div >
98
- { viewsResponse ?. ok &&
99
- viewsResponse . data . filter (
100
- ( view : View ) =>
101
- ( view . createdBy === user . id || view . public === true ) &&
102
- view . dataSourceId === parseInt ( dataSourceId )
103
- ) . length > 0 && (
104
- < Link href = { `/views/new?dataSourceId=${ dataSourceId } ` } >
105
- < a className = "flex justify-center items-center mx-2" >
106
- < Tooltip label = "Add view" >
107
- < div >
108
- < PlusCircleIcon className = "h-4 inline cursor-pointer" />
109
- </ div >
110
- </ Tooltip >
111
- </ a >
112
- </ Link >
113
- ) }
114
- </ div >
115
-
116
- < Collapse in = { isViewsOpen } >
117
- { viewsLoading && (
118
- < div className = "flex-1 min-h-full px-1 space-y-2 mt-3" >
119
- < Shimmer height = { 16 } width = { 50 } />
120
- < Shimmer height = { 16 } width = { 90 } />
121
- < Shimmer height = { 16 } width = { 110 } />
122
- < Shimmer height = { 16 } width = { 60 } />
123
- </ div >
124
- ) }
125
- { /* If no views are present, show a nice box with the create message */ }
126
- { ! viewsLoading && filteredViews . length === 0 && (
127
- < Link href = { `/views/new?dataSourceId=${ dataSourceId } ` } passHref >
128
- < div className = "flex justify-center items-center border-2 rounded-md border-dashed border-gray-500 py-6 text-gray-600 cursor-pointer mb-2" >
129
- < PlusIcon className = "h-4 mr-1 flex flex-shrink-0" />
130
- Create view
131
- </ div >
132
- </ Link >
133
- ) }
134
- { /* display only views created by logged in user or public views and having same datasource */ }
135
- { ! viewsLoading &&
136
- filteredViews . map ( ( view : View , idx : number ) => (
137
- < SidebarItem
138
- key = { idx }
139
- active = { view . id === parseInt ( viewId ) }
140
- label = { view . name }
141
- link = { `/views/${ view . id } ` }
142
- />
143
- ) ) }
144
- </ Collapse >
145
- </ div >
146
- < hr className = "mt-2 mb-2" />
147
- </ >
148
- ) ;
149
-
150
21
return (
151
- < div className = "relative py-2 pl-2 w-full overflow-y-auto " >
22
+ < div className = "relative py-2 pl-2 w-full" >
152
23
< div className = "relative space-y-x w-full h-full flex flex-col" >
153
24
< div className = "my-2 mt-4 px-2 font-bold uppercase text leading-none" >
154
25
{ dataSourceIsLoading && (
@@ -170,82 +41,9 @@ const Sidebar = () => {
170
41
) }
171
42
</ div >
172
43
< hr className = "-mt-px mb-2" />
173
- { viewsError && (
174
- < div >
175
- { "data" in viewsError && first ( ( viewsError ?. data as any ) ?. messages ) }
176
- </ div >
177
- ) }
178
- { dataSourceInfo ?. supports ?. views && < ViewsSection /> }
179
- { isOwner && (
180
- < >
181
- { tablesError && (
182
- < div >
183
- { "data" in tablesError &&
184
- first ( ( tablesError ?. data as any ) ?. messages ) }
185
- </ div >
186
- ) }
187
- < div className = "relative space-y-1 flex-1" >
188
- < div
189
- className = "text-md font-semibold py-2 px-2 rounded-md leading-none m-0 cursor-pointer"
190
- onClick = { toggleTablesOpen }
191
- >
192
- Tables{ " " }
193
- < span className = "text-xs text-gray-500" >
194
- (visible only to owners)
195
- </ span >
196
- { isTablesOpen ? (
197
- < ChevronDownIcon className = "h-3 inline" />
198
- ) : (
199
- < ChevronLeftIcon className = "h-3 inline" />
200
- ) }
201
- </ div >
202
- < Collapse in = { isTablesOpen } >
203
- < div className = "" >
204
- { tablesLoading && (
205
- < div className = "flex-1 min-h-full px-1 space-y-2 mt-3" >
206
- < Shimmer height = { 16 } width = { 50 } />
207
- < Shimmer height = { 16 } width = { 60 } />
208
- < Shimmer height = { 16 } width = { 120 } />
209
- < Shimmer height = { 16 } width = { 90 } />
210
- < Shimmer height = { 16 } width = { 60 } />
211
- < Shimmer height = { 16 } width = { 110 } />
212
- < Shimmer height = { 16 } width = { 90 } />
213
- </ div >
214
- ) }
215
- { /* @todo : why does the .data attribute remain populated with old content when the hooks has changed? */ }
216
- { /* Got to a valid DS and then to an invalid one. the data attribute will still have the old data there. */ }
217
- { ! tablesLoading &&
218
- tablesResponse ?. ok &&
219
- tablesResponse . data
220
- . filter ( ( table : ListTable ) =>
221
- dataSource ?. type === "postgresql" && table . schema
222
- ? table . schema === "public"
223
- : true
224
- )
225
- . map ( ( table : ListTable , idx : number ) => (
226
- < SidebarItem
227
- key = { idx }
228
- active = {
229
- table . name === tableName && isUndefined ( viewId )
230
- }
231
- label = { table . name }
232
- link = { `/data-sources/${ dataSourceId } /tables/${ table . name } ` }
233
- onMouseOver = { ( ) => {
234
- // If the datasource supports columns request we'll prefetch it on hover.
235
- if ( info ?. supports ?. columnsRequest ) {
236
- prefetchColumns ( {
237
- dataSourceId,
238
- tableName : table . name ,
239
- } ) ;
240
- }
241
- } }
242
- />
243
- ) ) }
244
- </ div >
245
- </ Collapse >
246
- </ div >
247
- </ >
248
- ) }
44
+ < DashboardSidebarSection />
45
+ { dataSourceInfo ?. supports ?. views && < ViewsSidebarSection /> }
46
+ { isOwner && < TablesSidebarSection /> }
249
47
</ div >
250
48
</ div >
251
49
) ;
0 commit comments