Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Enhancement] #848 increase column width and page size #934

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,5 +72,8 @@
},
"engines": {
"yarn": "^1.21.1"
},
"dependencies": {
"@opensearch-project/oui": "^1.4.0"
}
}
}
1 change: 1 addition & 0 deletions public/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import { PluginInitializerContext } from "opensearch-dashboards/public";
import { IndexManagementPlugin } from "./plugin";
import { Action, UIAction } from "../models/interfaces";
import "@opensearch-project/oui/dist/oui_theme_light.css";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The theme and its css should already be imported in OSD core, I do not think we should explicitly import theme.css in a plugin.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup @SuZhou-Joe. I got rid of OUI(faced issues with the library and documentation) entirely and switched to EuiDataGrid.
I am still working on the pagination part for the table. I will push the latest code with screenshots as I get some time to test for edge cases.

Thanks,
KC


// export for other plugins to register action
export { Action, UIAction } from "../models/interfaces";
Expand Down
109 changes: 87 additions & 22 deletions public/pages/Indices/containers/Indices/Indices.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,26 @@ import _ from "lodash";
import { RouteComponentProps } from "react-router-dom";
import queryString from "query-string";
import {
EuiBasicTable,
EuiHorizontalRule,
// @ts-ignore
Criteria,
EuiTableSortingType,
Direction,
// @ts-ignore
Pagination,
EuiTableSelectionType,
ArgsWithError,
ArgsWithQuery,
Query,
EuiHealth,
EuiLink,
} from "@elastic/eui";

import { OuiDataGrid, OuiDataGridPaginationProps, OuiDataGridSorting, OuiText, OuiTitle } from "@opensearch-project/oui";

import { ContentPanel, ContentPanelActions } from "../../../../components/ContentPanel";
import IndexControls from "../../components/IndexControls";
import IndexEmptyPrompt from "../../components/IndexEmptyPrompt";
import { DEFAULT_PAGE_SIZE_OPTIONS, DEFAULT_QUERY_PARAMS, indicesColumns } from "../../utils/constants";
import { DEFAULT_PAGE_SIZE_OPTIONS, DEFAULT_QUERY_PARAMS, HEALTH_TO_COLOR, indicesColumns, renderNumber } from "../../utils/constants";
import IndexService from "../../../../services/IndexService";
import CommonService from "../../../../services/CommonService";
import { DataStream, ManagedCatIndex } from "../../../../../server/models/interfaces";
Expand All @@ -37,6 +40,7 @@ import { SECURITY_EXCEPTION_PREFIX } from "../../../../../server/utils/constants
import IndicesActions from "../IndicesActions";
import { destroyListener, EVENT_MAP, listenEvent } from "../../../../JobHandler";
import "./index.scss";
import IndexDetail from "../../../IndexDetail/containers/IndexDetail";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
import IndexDetail from "../../../IndexDetail/containers/IndexDetail";
import IndexDetail from "../../containers/IndexDetail";

You are using wrong component here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The IndexDetail inside IndexDetail page is a super heavy component and should not be rendered inside a cell of data grid.


interface IndicesProps extends RouteComponentProps {
indexService: IndexService;
Expand All @@ -60,6 +64,7 @@ interface IndicesState {

export default class Indices extends Component<IndicesProps, IndicesState> {
static contextType = CoreServicesContext;

constructor(props: IndicesProps) {
super(props);
const { from, size, search, sortField, sortDirection, showDataStreams } = getURLQueryParams(this.props.location);
Expand Down Expand Up @@ -194,6 +199,16 @@ export default class Indices extends Component<IndicesProps, IndicesState> {
this.setState({ search: DEFAULT_QUERY_PARAMS.search, query: Query.parse(DEFAULT_QUERY_PARAMS.search) });
};

onSort = (sortingColumns: string | any[]) => {
const sort = sortingColumns.length > 0 ? sortingColumns[0] : undefined;
if (sort) {
this.setState({
sortField: sort.id,
sortDirection: sort.direction,
});
}
};

render() {
const {
totalIndices,
Expand All @@ -211,25 +226,79 @@ export default class Indices extends Component<IndicesProps, IndicesState> {
const filterIsApplied = !!search;
const page = Math.floor(from / size);

const pagination: Pagination = {
const pagination: OuiDataGridPaginationProps = {
pageIndex: page,
pageSize: size,
pageSizeOptions: DEFAULT_PAGE_SIZE_OPTIONS,
totalItemCount: totalIndices,
onChangeItemsPerPage: (newSize) => this.setState({ size: newSize }),
onChangePage: (newPage) => this.setState({ from: newPage * size }),
};

const sorting: EuiTableSortingType<ManagedCatIndex> = {
sort: {
direction: sortDirection,
field: sortField,
},
const sorting: OuiDataGridSorting = {
onSort: this.onSort,
columns: this.state.sortField ? [{ id: this.state.sortField, direction: this.state.sortDirection }] : [],
};

const selection: EuiTableSelectionType<ManagedCatIndex> = {
onSelectionChange: this.onSelectionChange,
};

const { history } = this.props;
const renderCellValue = ({ rowIndex, columnId }) => {
const rowData = this.state.indices[rowIndex];

console.log(rowData);

switch (columnId) {
case "index":
return <IndexDetail {...this.props} index={rowData.index} />;
Comment on lines +252 to +253
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Loading this IndexDetail component is the cause of endless call. @kohinoor98 can you reach out to @SuZhou-Joe the writter for some guidance here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, will do. Thanks @bowenlan-amzn


case "health":
const color = rowData.health ? HEALTH_TO_COLOR[rowData.health] : "subdued";
return (
<EuiHealth color={color} className="indices-health">
{rowData.health || rowData.status}
</EuiHealth>
);

case "data_stream":
return rowData.data_stream ? (
<EuiLink href={`#${ROUTES.CREATE_DATA_STREAM}/${rowData.data_stream}`}>{rowData.data_stream}</EuiLink>
) : (
"-"
);

case "managed":
return renderNumber(rowData.managed);

case "status":
return <span className="camel-first-letter">{rowData.extraStatus || rowData.status}</span>;

case "store.size":
return renderNumber(rowData["store.size"]);

case "pri.store.size":
return renderNumber(rowData["pri.store.size"]);

case "docs.count":
return <span title={rowData["docs.count"].toString()}>{rowData["docs.count"] || "-"}</span>;

case "docs.deleted":
return <span title={rowData["docs.deleted"].toString()}>{rowData["docs.deleted"] || "-"}</span>;

case "pri":
return rowData.pri.toString();

case "rep":
return rowData.rep.toString();

default:
return rowData[columnId] ?? "-";
}
};

const columns = indicesColumns(isDataStreamColumnVisible, { history: this.props.history });

const gridLabelId = "tableIndexMangementPlugin";

return (
<ContentPanel
Expand Down Expand Up @@ -283,18 +352,14 @@ export default class Indices extends Component<IndicesProps, IndicesState> {

<EuiHorizontalRule margin="xs" />

<EuiBasicTable
columns={indicesColumns(isDataStreamColumnVisible, {
history,
})}
loading={this.state.loadingIndices}
isSelectable={true}
itemId="index"
items={indices}
noItemsMessage={<IndexEmptyPrompt filterIsApplied={filterIsApplied} loading={loadingIndices} resetFilters={this.resetFilters} />}
onChange={this.onTableChange}
<OuiDataGrid
aria-labelledby={gridLabelId}
columns={columns}
columnVisibility={{ visibleColumns: columns.map((column) => column.id), setVisibleColumns: () => {} }}
rowCount={totalIndices}
inMemory={{ level: "sorting" }}
renderCellValue={renderCellValue}
pagination={pagination}
selection={selection}
sorting={sorting}
/>
</ContentPanel>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ exports[`<Indices /> spec renders the component 1`] = `
data-test-subj="tableHeaderCell_index_0"
role="columnheader"
scope="col"
style="width: 250px;"
style="width: 320px;"
>
<button
class="euiTableHeaderButton euiTableHeaderButton-isSorted"
Expand Down
145 changes: 52 additions & 93 deletions public/pages/Indices/utils/constants.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@
* SPDX-License-Identifier: Apache-2.0
*/

import React from "react";
import { EuiHealth, EuiLink, EuiTableFieldDataColumnType } from "@elastic/eui";
import { OuiDataGridColumn } from "@opensearch-project/oui";
import IndexDetail, { IndexDetailModalProps } from "../containers/IndexDetail";
import { ManagedCatIndex } from "../../../../server/models/interfaces";
import { ROUTES, SortDirection } from "../../../utils/constants";

const renderNumber = (value) => {
export const renderNumber = (value) => {
return value || "-";
};

Expand Down Expand Up @@ -37,122 +36,82 @@ export const HEALTH_TO_COLOR: {

interface IColumnOptions extends Omit<IndexDetailModalProps, "index"> {}

const getColumns = (props: IColumnOptions): EuiTableFieldDataColumnType<ManagedCatIndex>[] => {
const getColumns = (props: IColumnOptions): OuiDataGridColumn[] => {
return [
{
field: "index",
name: "Index",
sortable: true,
truncateText: false,
textOnly: true,
width: "250px",
render: (index: string) => {
return <IndexDetail {...props} index={index} />;
},
id: "index",
displayAsText: "Index",
isSortable: true,
initialWidth: 320,
},
{
field: "health",
name: "Health",
sortable: true,
truncateText: true,
textOnly: true,
render: (health: string, item: ManagedCatIndex) => {
const color = health ? HEALTH_TO_COLOR[health] : "subdued";
const text = health || item.status;
return (
<EuiHealth color={color} className="indices-health">
{text}
</EuiHealth>
);
},
id: "health",
displayAsText: "Health",
isSortable: true,
},
{
field: "data_stream",
name: "Data stream",
sortable: true,
truncateText: true,
textOnly: true,
width: "120px",
render: (data_stream) => (data_stream ? <EuiLink href={`#${ROUTES.CREATE_DATA_STREAM}/${data_stream}`}>{data_stream}</EuiLink> : "-"),
id: "data_stream",
displayAsText: "Data stream",
isSortable: true,
initialWidth: 120,
},
{
field: "managed",
name: "Managed by policy",
sortable: false,
truncateText: true,
textOnly: true,
render: renderNumber,
id: "managed",
displayAsText: "Managed by policy",
isSortable: false,
},
{
field: "status",
name: "Status",
sortable: true,
truncateText: true,
textOnly: true,
render: (status: string, item: ManagedCatIndex) => {
return <span className="camel-first-letter">{item.extraStatus || status}</span>;
},
id: "status",
displayAsText: "Status",
isSortable: true,
},
{
field: "store.size",
name: "Total size",
sortable: true,
truncateText: true,
textOnly: true,
dataType: "number",
render: renderNumber,
id: "store.size",
displayAsText: "Total size",
isSortable: true,
schema: "numeric",
},
{
field: "pri.store.size",
name: "Size of primaries",
sortable: true,
truncateText: true,
textOnly: true,
dataType: "number",
render: renderNumber,
id: "pri.store.size",
displayAsText: "Size of primaries",
isSortable: true,
schema: "numeric",
},
{
field: "docs.count",
name: "Total documents",
sortable: true,
truncateText: true,
textOnly: true,
dataType: "number",
render: (count: string) => <span title={count}>{count || "-"}</span>,
id: "docs.count",
displayAsText: "Total documents",
isSortable: true,
schema: "numeric",
},
{
field: "docs.deleted",
name: "Deleted documents",
sortable: true,
truncateText: true,
textOnly: true,
dataType: "number",
render: (deleted: string) => <span title={deleted}>{deleted || "-"}</span>,
id: "docs.deleted",
displayAsText: "Deleted documents",
isSortable: true,
schema: "numeric",
},
{
field: "pri",
name: "Primaries",
sortable: true,
truncateText: true,
textOnly: true,
dataType: "number",
id: "pri",
displayAsText: "Primaries",
isSortable: true,
schema: "numeric",
},
{
field: "rep",
name: "Replicas",
sortable: true,
truncateText: true,
textOnly: true,
dataType: "number",
id: "rep",
displayAsText: "Replicas",
isSortable: true,
schema: "numeric",
},
];
};

export const indicesColumns = (
isDataStreamColumnVisible: boolean,
options: IColumnOptions
): EuiTableFieldDataColumnType<ManagedCatIndex>[] => {
return isDataStreamColumnVisible ? getColumns(options) : getColumns(options).filter((col) => col["field"] !== "data_stream");
export const indicesColumns = (isDataStreamColumnVisible: boolean, options: IColumnOptions): OuiDataGridColumn[] => {
let columns = getColumns(options);

if (!isDataStreamColumnVisible) {
columns = columns.filter((column) => column.id !== "data_stream");
}

return columns;
};

export const DEFAULT_QUERY = JSON.stringify(
Expand Down
Loading