1
+ import React , { useEffect , useState } from "react" ;
2
+ import { useParams , useHistory } from "react-router-dom" ;
3
+ import history from "@lowcoder-ee/util/history" ;
4
+ import { useWorkspaceDetail } from "./hooks/useWorkspaceDetail" ;
5
+
6
+
7
+ import {
8
+ Spin ,
9
+ Typography ,
10
+ Card ,
11
+ Row ,
12
+ Col ,
13
+ Tabs ,
14
+ Alert ,
15
+ Button ,
16
+ Statistic ,
17
+ Divider ,
18
+ Breadcrumb
19
+ } from "antd" ;
20
+ import {
21
+ ReloadOutlined ,
22
+ AppstoreOutlined ,
23
+ DatabaseOutlined ,
24
+ CodeOutlined ,
25
+ HomeOutlined ,
26
+ TeamOutlined ,
27
+ SyncOutlined ,
28
+ ArrowLeftOutlined
29
+ } from "@ant-design/icons" ;
30
+ import { getEnvironmentById } from './services/environments.service' ;
31
+ import AppsList from './components/AppsList' ;
32
+ import { Workspace } from './types/workspace.types' ;
33
+ import { Environment } from './types/environment.types' ;
34
+ import { App } from './types/app.types' ;
35
+
36
+ const { Title, Text } = Typography ;
37
+ const { TabPane } = Tabs ;
38
+
39
+
40
+ const WorkspaceDetail : React . FC = ( ) => {
41
+ // Get parameters from URL
42
+ const { environmentId, workspaceId } = useParams < {
43
+ environmentId : string ;
44
+ workspaceId : string ;
45
+ } > ( ) ;
46
+
47
+ // Use the custom hook
48
+ const {
49
+ environment,
50
+ workspace,
51
+ apps,
52
+ appsLoading,
53
+ appsError,
54
+ refreshApps,
55
+ appStats,
56
+ isLoading,
57
+ hasError
58
+ } = useWorkspaceDetail ( environmentId , workspaceId ) ;
59
+
60
+ // Handle loading/error states
61
+ if ( isLoading ) {
62
+ return < Spin /> ;
63
+ }
64
+
65
+ // Handle loading/error states
66
+ if ( isLoading ) {
67
+ return (
68
+ < div style = { { display : 'flex' , justifyContent : 'center' , alignItems : 'center' , height : '100%' , padding : '50px' } } >
69
+ < Spin size = "large" tip = "Loading workspace details..." />
70
+ </ div >
71
+ ) ;
72
+ }
73
+
74
+ // Handle error state
75
+ if ( hasError || ! environment || ! workspace ) {
76
+ return (
77
+ < Alert
78
+ message = "Error loading workspace details"
79
+ description = "Could not load the workspace or environment data. Please try again."
80
+ type = "error"
81
+ showIcon
82
+ style = { { margin : '24px' } }
83
+ action = {
84
+ < Button type = "primary" onClick = { ( ) => history . push ( `/home/settings/environments/${ environmentId } ` ) } >
85
+ Back to Environment
86
+ </ Button >
87
+ }
88
+ />
89
+ ) ;
90
+ }
91
+
92
+ return (
93
+ < div className = "workspace-detail-container" style = { { padding : '24px' } } >
94
+ { /* Breadcrumb navigation */ }
95
+ < Breadcrumb style = { { marginBottom : '16px' } } >
96
+ < Breadcrumb . Item onClick = { ( ) => history . push ( '/home/settings/environments' ) } >
97
+ < HomeOutlined /> Environments
98
+ </ Breadcrumb . Item >
99
+ < Breadcrumb . Item onClick = { ( ) => history . push ( `/home/settings/environments/${ environmentId } ` ) } >
100
+ < TeamOutlined /> { environment . environmentName }
101
+ </ Breadcrumb . Item >
102
+ < Breadcrumb . Item >
103
+ { workspace . name }
104
+ </ Breadcrumb . Item >
105
+ </ Breadcrumb >
106
+
107
+ { /* Header with workspace name and controls */ }
108
+ < div className = "workspace-header" style = { { marginBottom : '24px' , display : 'flex' , justifyContent : 'space-between' , alignItems : 'center' } } >
109
+ < div >
110
+ < Button
111
+ type = "link"
112
+ icon = { < ArrowLeftOutlined /> }
113
+ onClick = { ( ) => history . push ( `/home/settings/environments/${ environmentId } ` ) }
114
+ style = { { marginLeft : - 12 , marginRight : 8 } }
115
+ >
116
+ Back to Environment
117
+ </ Button >
118
+ < Title level = { 3 } > { workspace . name } </ Title >
119
+ < Text type = "secondary" > ID: { workspace . id } </ Text >
120
+ </ div >
121
+ </ div >
122
+
123
+ { /* Tabs for Apps, Data Sources, and Queries */ }
124
+ < Tabs defaultActiveKey = "apps" >
125
+ < TabPane
126
+ tab = { < span > < AppstoreOutlined /> Apps</ span > }
127
+ key = "apps"
128
+ >
129
+ < Card >
130
+ { /* Header with refresh button */ }
131
+ < div style = { { display : 'flex' , justifyContent : 'space-between' , alignItems : 'center' , marginBottom : '16px' } } >
132
+ < Title level = { 5 } > Apps in this Workspace</ Title >
133
+ < Button
134
+ icon = { < SyncOutlined /> }
135
+ onClick = { refreshApps }
136
+ size = "small"
137
+ loading = { appsLoading }
138
+ >
139
+ Refresh Apps
140
+ </ Button >
141
+ </ div >
142
+
143
+ { /* App Statistics */ }
144
+ < Row gutter = { 16 } style = { { marginBottom : '24px' } } >
145
+ < Col span = { 8 } >
146
+ < Statistic
147
+ title = "Total Apps"
148
+ value = { appStats . total }
149
+ prefix = { < AppstoreOutlined /> }
150
+ />
151
+ </ Col >
152
+ < Col span = { 8 } >
153
+ < Statistic
154
+ title = "Published Apps"
155
+ value = { appStats . published }
156
+ prefix = { < AppstoreOutlined /> }
157
+ />
158
+ </ Col >
159
+ </ Row >
160
+
161
+ < Divider style = { { margin : '16px 0' } } />
162
+
163
+ { /* Show error if apps loading failed */ }
164
+ { appsError && (
165
+ < Alert
166
+ message = "Error loading apps"
167
+ description = { appsError }
168
+ type = "error"
169
+ showIcon
170
+ style = { { marginBottom : '16px' } }
171
+ action = {
172
+ < Button size = "small" type = "primary" onClick = { refreshApps } >
173
+ Try Again
174
+ </ Button >
175
+ }
176
+ />
177
+ ) }
178
+
179
+ { /* Apps List */ }
180
+ < AppsList
181
+ apps = { apps }
182
+ loading = { appsLoading }
183
+ error = { appsError }
184
+ />
185
+ </ Card >
186
+ </ TabPane >
187
+
188
+ < TabPane
189
+ tab = { < span > < DatabaseOutlined /> Data Sources</ span > }
190
+ key = "dataSources"
191
+ >
192
+ < Card >
193
+ < Alert
194
+ message = "Data Sources"
195
+ description = "Data Sources feature will be implemented in the next phase."
196
+ type = "info"
197
+ showIcon
198
+ />
199
+ </ Card >
200
+ </ TabPane >
201
+
202
+ < TabPane
203
+ tab = { < span > < CodeOutlined /> Queries</ span > }
204
+ key = "queries"
205
+ >
206
+ < Card >
207
+ < Alert
208
+ message = "Queries"
209
+ description = "Queries feature will be implemented in the next phase."
210
+ type = "info"
211
+ showIcon
212
+ />
213
+ </ Card >
214
+ </ TabPane >
215
+ </ Tabs >
216
+ </ div >
217
+ ) ;
218
+ }
219
+
220
+
221
+ export default WorkspaceDetail
0 commit comments