33 * SPDX-License-Identifier: Apache-2.0
44 */
55
6- import React , { useState } from 'react' ;
6+ import React , { useState , useMemo , useCallback } from 'react' ;
77import {
88 EuiPage ,
99 EuiPageBody ,
1010 EuiPageHeader ,
1111 EuiPageContent ,
12- EuiBasicTable ,
1312 EuiLink ,
14- Direction ,
15- CriteriaWithPagination ,
13+ EuiButton ,
14+ EuiInMemoryTable ,
15+ EuiTableSelectionType ,
16+ EuiSearchBarProps ,
1617} from '@elastic/eui' ;
1718import useObservable from 'react-use/lib/useObservable' ;
18- import { useMemo , useCallback } from 'react' ;
1919import { of } from 'rxjs' ;
20+ import { i18n } from '@osd/i18n' ;
2021import { WorkspaceAttribute } from '../../../../../core/public' ;
2122
2223import { useOpenSearchDashboards } from '../../../../../plugins/opensearch_dashboards_react/public' ;
23- import { switchWorkspace } from '../utils/workspace' ;
24+ import { switchWorkspace , updateWorkspace } from '../utils/workspace' ;
25+ import { debounce } from '../utils/common' ;
26+
27+ import { WORKSPACE_CREATE_APP_ID } from '../../../common/constants' ;
28+
29+ import { cleanWorkspaceId } from '../../../../../core/public' ;
30+
31+ const WORKSPACE_LIST_PAGE_DESCRIPTIOIN = i18n . translate ( 'workspace.list.description' , {
32+ defaultMessage :
33+ 'Workspace allow you to save and organize library items, such as index patterns, visualizations, dashboards, saved searches, and share them with other OpenSearch Dashboards users. You can control which features are visible in each workspace, and which users and groups have read and write access to the library items in the workspace.' ,
34+ } ) ;
2435
2536export const WorkspaceList = ( ) => {
2637 const {
2738 services : { workspaces, application, http } ,
2839 } = useOpenSearchDashboards ( ) ;
2940
30- const [ pageIndex , setPageIndex ] = useState ( 0 ) ;
31- const [ pageSize , setPageSize ] = useState ( 5 ) ;
32- const [ sortField , setSortField ] = useState < 'name' | 'id' > ( 'name' ) ;
33- const [ sortDirection , setSortDirection ] = useState < Direction > ( 'asc' ) ;
34-
41+ const initialSortField = 'name' ;
42+ const initialSortDirection = 'asc' ;
3543 const workspaceList = useObservable ( workspaces ?. workspaceList$ ?? of ( [ ] ) , [ ] ) ;
44+ const [ queryInput , setQueryInput ] = useState < string > ( '' ) ;
45+ const [ pagination , setPagination ] = useState ( {
46+ pageIndex : 0 ,
47+ pageSize : 5 ,
48+ pageSizeOptions : [ 5 , 10 , 20 ] ,
49+ } ) ;
3650
37- const pageOfItems = useMemo ( ( ) => {
38- return workspaceList
39- . sort ( ( a , b ) => {
40- const compare = a [ sortField ] . localeCompare ( b [ sortField ] ) ;
41- return sortDirection === 'asc' ? compare : - compare ;
42- } )
43- . slice ( pageIndex * pageSize , ( pageIndex + 1 ) * pageSize ) ;
44- } , [ workspaceList , pageIndex , pageSize , sortField , sortDirection ] ) ;
51+ // Will be uesed when updating table actions
52+ const [ , setSelection ] = useState < WorkspaceAttribute [ ] > ( [ ] ) ;
4553
4654 const handleSwitchWorkspace = useCallback (
4755 ( id : string ) => {
@@ -52,6 +60,29 @@ export const WorkspaceList = () => {
5260 [ application , http ]
5361 ) ;
5462
63+ const handleUpdateWorkspace = useCallback (
64+ ( id : string ) => {
65+ if ( application && http ) {
66+ updateWorkspace ( { application, http } , id ) ;
67+ }
68+ } ,
69+ [ application , http ]
70+ ) ;
71+
72+ const searchResult = useMemo ( ( ) => {
73+ if ( queryInput ) {
74+ const normalizedQuery = queryInput . toLowerCase ( ) ;
75+ const result = workspaceList . filter ( ( item ) => {
76+ return (
77+ item . id . toLowerCase ( ) . indexOf ( normalizedQuery ) > - 1 ||
78+ item . name . toLowerCase ( ) . indexOf ( normalizedQuery ) > - 1
79+ ) ;
80+ } ) ;
81+ return result ;
82+ }
83+ return workspaceList ;
84+ } , [ workspaceList , queryInput ] ) ;
85+
5586 const columns = [
5687 {
5788 field : 'name' ,
@@ -79,46 +110,95 @@ export const WorkspaceList = () => {
79110 isExpander : true ,
80111 hasActions : true ,
81112 } ,
113+ {
114+ name : 'Actions' ,
115+ field : '' ,
116+ actions : [
117+ {
118+ name : 'Edit' ,
119+ icon : 'pencil' ,
120+ type : 'icon' ,
121+ description : 'edit workspace' ,
122+ onClick : ( { id } : WorkspaceAttribute ) => handleUpdateWorkspace ( id ) ,
123+ } ,
124+ ] ,
125+ } ,
82126 ] ;
83127
84- const onTableChange = ( { page, sort } : CriteriaWithPagination < WorkspaceAttribute > ) => {
85- const { field, direction } = sort ! ;
86- const { index, size } = page ;
128+ const workspaceCreateUrl = useMemo ( ( ) => {
129+ if ( ! application || ! http ) {
130+ return '' ;
131+ }
132+
133+ return cleanWorkspaceId (
134+ application . getUrlForApp ( WORKSPACE_CREATE_APP_ID , {
135+ absolute : false ,
136+ } )
137+ ) ;
138+ } , [ application , http ] ) ;
139+
140+ const debouncedSetQueryInput = useMemo ( ( ) => {
141+ return debounce ( setQueryInput , 300 ) ;
142+ } , [ setQueryInput ] ) ;
143+
144+ const handleSearchInput : EuiSearchBarProps [ 'onChange' ] = ( { query } ) => {
145+ debouncedSetQueryInput ( query ?. text ?? '' ) ;
146+ } ;
147+
148+ const search : EuiSearchBarProps = {
149+ onChange : handleSearchInput ,
150+ box : {
151+ incremental : true ,
152+ } ,
153+ toolsRight : [
154+ < EuiButton href = { workspaceCreateUrl } key = "create_workspace" >
155+ Create workspace
156+ </ EuiButton > ,
157+ ] ,
158+ } ;
87159
88- setPageIndex ( index ) ;
89- setPageSize ( size ) ;
90- setSortField ( field as 'name' | 'id' ) ;
91- setSortDirection ( direction ) ;
160+ const selectionValue : EuiTableSelectionType < WorkspaceAttribute > = {
161+ selectable : ( ) => true ,
162+ onSelectionChange : ( selection ) => {
163+ setSelection ( selection ) ;
164+ } ,
92165 } ;
93166
94167 return (
95168 < EuiPage paddingSize = "none" >
96169 < EuiPageBody panelled >
97- < EuiPageHeader restrictWidth pageTitle = "Workspace list" />
170+ < EuiPageHeader
171+ restrictWidth
172+ pageTitle = "Workspaces"
173+ description = { WORKSPACE_LIST_PAGE_DESCRIPTIOIN }
174+ />
98175 < EuiPageContent
99176 verticalPosition = "center"
100177 horizontalPosition = "center"
101178 paddingSize = "none"
102- color = "subdued "
179+ panelPaddingSize = "l "
103180 hasShadow = { false }
104181 style = { { width : '100%' , maxWidth : 1000 } }
105182 >
106- < EuiBasicTable
107- items = { pageOfItems }
183+ < EuiInMemoryTable
184+ items = { searchResult }
108185 columns = { columns }
109- pagination = { {
110- pageIndex,
111- pageSize,
112- totalItemCount : workspaceList . length ,
113- pageSizeOptions : [ 5 , 10 , 20 ] ,
114- } }
186+ itemId = "id"
187+ onTableChange = { ( { page : { index, size } } ) =>
188+ setPagination ( ( prev ) => {
189+ return { ...prev , pageIndex : index , pageSize : size } ;
190+ } )
191+ }
192+ pagination = { pagination }
115193 sorting = { {
116194 sort : {
117- field : sortField ,
118- direction : sortDirection ,
195+ field : initialSortField ,
196+ direction : initialSortDirection ,
119197 } ,
120198 } }
121- onChange = { onTableChange }
199+ isSelectable = { true }
200+ selection = { selectionValue }
201+ search = { search }
122202 />
123203 </ EuiPageContent >
124204 </ EuiPageBody >
0 commit comments