From 621304c52e67281b7219168017decf9f939416ac Mon Sep 17 00:00:00 2001 From: Drew Tate Date: Wed, 7 Jun 2023 15:46:50 -0500 Subject: [PATCH 1/2] declarative API for table list --- .../tabbed_table_list_view/index.ts | 2 +- .../tabbed_table_list_view/src/index.ts | 7 +- .../src/tabbed_table_list_view.tsx | 71 +++++++++++++++++-- .../src/table_list_view_table.tsx | 4 +- .../components/visualize_listing.tsx | 22 +++--- 5 files changed, 89 insertions(+), 17 deletions(-) diff --git a/packages/content-management/tabbed_table_list_view/index.ts b/packages/content-management/tabbed_table_list_view/index.ts index d18ef6ac4c75c7..c00f6854bd0a39 100644 --- a/packages/content-management/tabbed_table_list_view/index.ts +++ b/packages/content-management/tabbed_table_list_view/index.ts @@ -6,6 +6,6 @@ * Side Public License, v 1. */ -export { TabbedTableListView, type TableListTab } from './src'; +export { TabbedTableListView, TabbedTableListViewV2, Tab, type TableListTab } from './src'; export type { UserContentCommonSchema } from '@kbn/content-management-table-list-view-table'; diff --git a/packages/content-management/tabbed_table_list_view/src/index.ts b/packages/content-management/tabbed_table_list_view/src/index.ts index 2eb0f905c21a47..6a413d3f882563 100644 --- a/packages/content-management/tabbed_table_list_view/src/index.ts +++ b/packages/content-management/tabbed_table_list_view/src/index.ts @@ -6,4 +6,9 @@ * Side Public License, v 1. */ -export { TabbedTableListView, type TableListTab } from './tabbed_table_list_view'; +export { + TabbedTableListView, + TabbedTableListViewV2, + Tab, + type TableListTab, +} from './tabbed_table_list_view'; diff --git a/packages/content-management/tabbed_table_list_view/src/tabbed_table_list_view.tsx b/packages/content-management/tabbed_table_list_view/src/tabbed_table_list_view.tsx index 40c0288aafd401..6982b0c95622ef 100644 --- a/packages/content-management/tabbed_table_list_view/src/tabbed_table_list_view.tsx +++ b/packages/content-management/tabbed_table_list_view/src/tabbed_table_list_view.tsx @@ -9,7 +9,7 @@ import { EuiTab, EuiTabs } from '@elastic/eui'; import { css } from '@emotion/react'; import { KibanaPageTemplate } from '@kbn/shared-ux-page-kibana-template'; -import React, { useCallback, useEffect, useState } from 'react'; +import React, { useCallback, useEffect, useMemo, useState } from 'react'; import type { TableListViewTableProps, UserContentCommonSchema, @@ -22,9 +22,7 @@ export type TableListTabParentProps { title: string; id: string; - getTableList: ( - propsFromParent: TableListTabParentProps - ) => Promise | React.ReactNode; + getTableList: () => Promise | React.ReactNode; } type TabbedTableListViewProps = Pick< @@ -100,3 +98,68 @@ export const TabbedTableListView = ({ ); }; + +interface TabProps { + title: string; + onClick: () => void; + active?: boolean; + loadContent: () => Promise | React.ReactNode; +} + +export const Tab = (_props: TabProps) => null; + +type TabbedTableListViewV2Props = Pick< + TableListViewProps, + 'title' | 'description' | 'headingId' | 'children' +> & { children: React.ReactElement | Array> }; + +export const TabbedTableListViewV2 = ({ + title, + description, + headingId, + children, +}: TabbedTableListViewV2Props) => { + const [hasInitialFetchReturned, setHasInitialFetchReturned] = useState(false); + const [pageDataTestSubject, setPageDataTestSubject] = useState(); + const [tableList, setTableList] = useState(null); + + const tabs = useMemo( + () => (Array.isArray(children) ? children : [children]).map((child) => child.props), + [children] + ); + + useEffect(() => { + const loadTableList = async () => { + const activeTab = tabs.find((tab) => tab.active) ?? tabs[0]; + setTableList(await activeTab.loadContent()); + }; + + loadTableList(); + }, [tabs]); + + return ( + + {title}} + description={description} + data-test-subj="top-nav" + css={css` + .euiPageHeaderContent { + padding-bottom: 0; + } + `} + > + + {tabs.map((tab, index) => ( + + {tab.title} + + ))} + + + + {tableList} + + + ); +}; diff --git a/packages/content-management/table_list_view_table/src/table_list_view_table.tsx b/packages/content-management/table_list_view_table/src/table_list_view_table.tsx index 8a84f380ab6643..9d7007f7a943be 100644 --- a/packages/content-management/table_list_view_table/src/table_list_view_table.tsx +++ b/packages/content-management/table_list_view_table/src/table_list_view_table.tsx @@ -270,7 +270,7 @@ function TableListViewTableComp({ refreshListBouncer, setPageDataTestSubject, }: TableListViewTableProps) { - setPageDataTestSubject(`${entityName}LandingPage`); + // setPageDataTestSubject(`${entityName}LandingPage`); TODO reenable if (!getDetailViewLink && !onClickTitle) { throw new Error( @@ -400,7 +400,7 @@ function TableListViewTableComp({ }, }); - onFetchSuccess(); + // onFetchSuccess(); TODO - reenable } } catch (err) { dispatch({ diff --git a/src/plugins/visualizations/public/visualize_app/components/visualize_listing.tsx b/src/plugins/visualizations/public/visualize_app/components/visualize_listing.tsx index e169a7ebaa0344..2c5d6dbd57f9ba 100644 --- a/src/plugins/visualizations/public/visualize_app/components/visualize_listing.tsx +++ b/src/plugins/visualizations/public/visualize_app/components/visualize_listing.tsx @@ -27,7 +27,9 @@ import { useLocation, useParams } from 'react-router-dom'; import type { SavedObjectReference } from '@kbn/core/public'; import { useKibana, useExecutionContext } from '@kbn/kibana-react-plugin/public'; import { + Tab, TabbedTableListView, + TabbedTableListViewV2, type TableListTab, } from '@kbn/content-management-tabbed-table-list-view'; import type { OpenContentEditorParams } from '@kbn/content-management-content-editor'; @@ -398,14 +400,16 @@ export const VisualizeListing = () => { const { activeTab } = useParams<{ activeTab: string }>(); return ( - { - application.navigateToUrl(`#/${id}`); - }} - /> + + {tabs.map((tab, index) => ( + application.navigateToUrl(`#/${tab.id}`)} + active={tab.id === activeTab} + loadContent={tab.getTableList} + /> + ))} + ); }; From 1e6e0a56326fe7d9ae498544b24706c2288684bf Mon Sep 17 00:00:00 2001 From: Drew Tate Date: Thu, 8 Jun 2023 14:53:07 -0500 Subject: [PATCH 2/2] context not working --- .../src/tabbed_table_list_view.tsx | 19 ++++- .../table_list_view/src/table_list_view.tsx | 69 +++++++++++-------- .../table_list_view_table/index.ts | 10 +-- .../table_list_view_table/src/index.ts | 2 +- .../src/table_list_view_table.tsx | 45 +++++++++--- .../public/components/table_list.tsx | 11 +-- 6 files changed, 99 insertions(+), 57 deletions(-) diff --git a/packages/content-management/tabbed_table_list_view/src/tabbed_table_list_view.tsx b/packages/content-management/tabbed_table_list_view/src/tabbed_table_list_view.tsx index 6982b0c95622ef..dbd564ea25dbae 100644 --- a/packages/content-management/tabbed_table_list_view/src/tabbed_table_list_view.tsx +++ b/packages/content-management/tabbed_table_list_view/src/tabbed_table_list_view.tsx @@ -10,7 +10,8 @@ import { EuiTab, EuiTabs } from '@elastic/eui'; import { css } from '@emotion/react'; import { KibanaPageTemplate } from '@kbn/shared-ux-page-kibana-template'; import React, { useCallback, useEffect, useMemo, useState } from 'react'; -import type { +import { + TableListViewTableContext, TableListViewTableProps, UserContentCommonSchema, } from '@kbn/content-management-table-list-view-table'; @@ -137,6 +138,18 @@ export const TabbedTableListViewV2 = ({ loadTableList(); }, [tabs]); + const tableContextValue = useMemo( + () => ({ + onTableDataFetched: () => { + if (!hasInitialFetchReturned) { + setHasInitialFetchReturned(true); + } + }, + setPageDataTestSubject, + }), + [hasInitialFetchReturned] + ); + return ( - {tableList} + + {tableList} + ); diff --git a/packages/content-management/table_list_view/src/table_list_view.tsx b/packages/content-management/table_list_view/src/table_list_view.tsx index 59fbe67a4a4c5b..77a16e60d0edac 100644 --- a/packages/content-management/table_list_view/src/table_list_view.tsx +++ b/packages/content-management/table_list_view/src/table_list_view.tsx @@ -7,9 +7,10 @@ */ import { KibanaPageTemplate } from '@kbn/shared-ux-page-kibana-template'; -import React, { ReactNode, useState } from 'react'; +import React, { ReactNode, useMemo, useState } from 'react'; import { TableListViewTable, + TableListViewTableContext, type TableListViewTableProps, type UserContentCommonSchema, } from '@kbn/content-management-table-list-view-table'; @@ -81,6 +82,18 @@ export const TableListView = ({ const [hasInitialFetchReturned, setHasInitialFetchReturned] = useState(false); const [pageDataTestSubject, setPageDataTestSubject] = useState(); + const tableContextValue = useMemo( + () => ({ + onTableDataFetched: () => { + if (!hasInitialFetchReturned) { + setHasInitialFetchReturned(true); + } + }, + setPageDataTestSubject, + }), + [hasInitialFetchReturned] + ); + return ( ({ {/* Any children passed to the component */} {children} - { - if (!hasInitialFetchReturned) { - setHasInitialFetchReturned(true); - } - }} - setPageDataTestSubject={setPageDataTestSubject} - /> + + + ); diff --git a/packages/content-management/table_list_view_table/index.ts b/packages/content-management/table_list_view_table/index.ts index 66abaeb022bf3e..e346db4886f163 100644 --- a/packages/content-management/table_list_view_table/index.ts +++ b/packages/content-management/table_list_view_table/index.ts @@ -7,18 +7,12 @@ */ export { - TabbedTableListView, TableListViewTable, + TableListViewTableContext, TableListViewProvider, TableListViewKibanaProvider, } from './src'; -export type { - UserContentCommonSchema, - TableListViewTableProps, - TableListTab, - TableListTabParentProps, - RowActions, -} from './src'; +export type { UserContentCommonSchema, TableListViewTableProps, RowActions } from './src'; export type { TableListViewKibanaDependencies } from './src/services'; diff --git a/packages/content-management/table_list_view_table/src/index.ts b/packages/content-management/table_list_view_table/src/index.ts index 4f060ea25b9f1b..57af55fa4cda87 100644 --- a/packages/content-management/table_list_view_table/src/index.ts +++ b/packages/content-management/table_list_view_table/src/index.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -export { TableListViewTable } from './table_list_view_table'; +export { TableListViewTable, TableListViewTableContext } from './table_list_view_table'; export type { TableListViewTableProps, diff --git a/packages/content-management/table_list_view_table/src/table_list_view_table.tsx b/packages/content-management/table_list_view_table/src/table_list_view_table.tsx index 9d7007f7a943be..4800ee426659bf 100644 --- a/packages/content-management/table_list_view_table/src/table_list_view_table.tsx +++ b/packages/content-management/table_list_view_table/src/table_list_view_table.tsx @@ -6,7 +6,15 @@ * Side Public License, v 1. */ -import React, { useReducer, useCallback, useEffect, useRef, useMemo } from 'react'; +import React, { + useReducer, + useCallback, + useEffect, + useRef, + useMemo, + createContext, + useContext, +} from 'react'; import useDebounce from 'react-use/lib/useDebounce'; import { EuiBasicTableColumn, @@ -110,8 +118,6 @@ export interface TableListViewTableProps< // TODO are these used? tableCaption: string; refreshListBouncer?: boolean; - onFetchSuccess: () => void; - setPageDataTestSubject: (subject: string) => void; } export interface State { @@ -243,6 +249,13 @@ const tableColumnMetadata = { }, } as const; +interface Context { + onTableDataFetched: () => void; + setPageDataTestSubject: (subject: string) => void; +} + +export const TableListViewTableContext = createContext(undefined); + function TableListViewTableComp({ tableCaption, entityName, @@ -266,11 +279,17 @@ function TableListViewTableComp({ contentEditor = { enabled: false }, titleColumnName, withoutPageTemplateWrapper, - onFetchSuccess, refreshListBouncer, - setPageDataTestSubject, }: TableListViewTableProps) { - // setPageDataTestSubject(`${entityName}LandingPage`); TODO reenable + const context = useContext(TableListViewTableContext); + + return

{context ? 'context found' : 'context NOT found'}

; + + useEffect(() => { + if (context) { + context.setPageDataTestSubject(`${entityName}LandingPage`); + } + }, []); if (!getDetailViewLink && !onClickTitle) { throw new Error( @@ -400,7 +419,9 @@ function TableListViewTableComp({ }, }); - // onFetchSuccess(); TODO - reenable + if (context) { + context.onTableDataFetched(); + } } } catch (err) { dispatch({ @@ -408,7 +429,7 @@ function TableListViewTableComp({ data: err, }); } - }, [searchQueryParser, searchQuery.text, findItems, onFetchSuccess]); + }, [searchQueryParser, searchQuery.text, findItems, context]); useEffect(() => { fetchItems(); @@ -986,6 +1007,8 @@ function TableListViewTableComp({ ); } -export const TableListViewTable = React.memo( - TableListViewTableComp -) as typeof TableListViewTableComp; +// export const TableListViewTable = React.memo( +// TableListViewTableComp +// ) as typeof TableListViewTableComp; + +export const TableListViewTable = TableListViewTableComp; diff --git a/src/plugins/event_annotation/public/components/table_list.tsx b/src/plugins/event_annotation/public/components/table_list.tsx index d4db655691c3bf..8d7b5489d15400 100644 --- a/src/plugins/event_annotation/public/components/table_list.tsx +++ b/src/plugins/event_annotation/public/components/table_list.tsx @@ -6,10 +6,10 @@ * Side Public License, v 1. */ -import React, { useCallback, useState } from 'react'; +import React, { useCallback, useContext, useState } from 'react'; import { TableListViewTable, - TableListTabParentProps, + TableListViewTableContext, } from '@kbn/content-management-table-list-view-table'; import { i18n } from '@kbn/i18n'; import type { IUiSettingsClient } from '@kbn/core-ui-settings-browser'; @@ -30,7 +30,6 @@ export const EventAnnotationGroupTableList = ({ eventAnnotationService, visualizeCapabilities, savedObjectsTagging, - parentProps, dataViews, createDataView, queryInputServices, @@ -39,11 +38,14 @@ export const EventAnnotationGroupTableList = ({ eventAnnotationService: EventAnnotationServiceType; visualizeCapabilities: Record>; savedObjectsTagging: SavedObjectsTaggingApi; - parentProps: TableListTabParentProps; dataViews: DataView[]; createDataView: (spec: DataViewSpec) => Promise; queryInputServices: QueryInputServices; }) => { + const context = useContext(TableListViewTableContext); + + console.log('context from EventAnnotationGroupTableList', context); + const listingLimit = uiSettings.get(SAVED_OBJECTS_LIMIT_SETTING); const initialPageSize = uiSettings.get(SAVED_OBJECTS_PER_PAGE_SETTING); @@ -137,7 +139,6 @@ export const EventAnnotationGroupTableList = ({ defaultMessage: 'annotation groups', })} onClickTitle={editItem} - {...parentProps} /> {flyout}