/* * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 */ import { EuiBasicTable, EuiButton, EuiEmptyPrompt, EuiHealth, EuiHorizontalRule, EuiLink, EuiTableFieldDataColumnType, EuiTableSortingType, SortDirection, } from '@elastic/eui'; import { Criteria } from '@elastic/eui/src/components/basic_table/basic_table'; import { Pagination } from '@elastic/eui/src/components/basic_table/pagination_bar'; import _ from 'lodash'; import React, { Component } from 'react'; import { RouteComponentProps } from 'react-router-dom'; import { ChannelItemType, TableState } from '../../../models/interfaces'; import { ContentPanel, ContentPanelActions, } from '../../components/ContentPanel'; import { CoreServicesContext } from '../../components/coreServices'; import { NotificationService } from '../../services'; import { BREADCRUMBS, CHANNEL_TYPE, ROUTES, } from '../../utils/constants'; import { getErrorMessage } from '../../utils/helpers'; import { DEFAULT_PAGE_SIZE_OPTIONS } from '../Notifications/utils/constants'; import { ChannelActions } from './components/ChannelActions'; import { ChannelControls } from './components/ChannelControls'; import { ChannelFiltersType } from './types'; interface ChannelsProps extends RouteComponentProps { notificationService: NotificationService; } interface ChannelsState extends TableState { filters: ChannelFiltersType; } export class Channels extends Component { static contextType = CoreServicesContext; columns: EuiTableFieldDataColumnType[]; constructor(props: ChannelsProps) { super(props); this.state = { total: 0, from: 0, size: 10, search: '', filters: {}, sortField: 'name', sortDirection: SortDirection.ASC, items: [], selectedItems: [], loading: true, }; this.columns = [ { field: 'name', name: 'Name', sortable: true, truncateText: true, render: (name: string, item: ChannelItemType) => ( {name} ), }, { field: 'is_enabled', name: 'Notification status', sortable: true, render: (enabled: boolean) => { const color = enabled ? 'success' : 'subdued'; const label = enabled ? 'Active' : 'Muted'; return {label}; }, }, { field: 'config_type', name: 'Type', sortable: true, truncateText: false, render: (type: string) => _.get(CHANNEL_TYPE, type, '-'), }, { field: 'description', name: 'Description', sortable: true, truncateText: true, render: (description: string) => description || '-', }, ]; this.refresh = this.refresh.bind(this); } async componentDidMount() { this.context.chrome.setBreadcrumbs([ BREADCRUMBS.NOTIFICATIONS, BREADCRUMBS.CHANNELS, ]); window.scrollTo(0, 0); await this.refresh(); } async componentDidUpdate(prevProps: ChannelsProps, prevState: ChannelsState) { const prevQuery = Channels.getQueryObjectFromState(prevState); const currQuery = Channels.getQueryObjectFromState(this.state); if (!_.isEqual(prevQuery, currQuery)) { await this.refresh(); } } static getQueryObjectFromState(state: ChannelsState) { const config_type = _.isEmpty(state.filters.type) ? Object.keys(CHANNEL_TYPE) // by default get all channels but not email senders/groups : state.filters.type; const queryObject: any = { from_index: state.from, max_items: state.size, query: state.search, config_type, sort_field: state.sortField, sort_order: state.sortDirection, }; if (state.filters.state != undefined) queryObject.is_enabled = state.filters.state; return queryObject; } async refresh() { this.setState({ loading: true }); try { const queryObject = Channels.getQueryObjectFromState(this.state); const channels = await this.props.notificationService.getChannels( queryObject ); this.setState({ items: channels.items, total: channels.total }); } catch (error) { this.context.notifications.toasts.addDanger( getErrorMessage(error, 'There was a problem loading channels.') ); } this.setState({ loading: false }); } onTableChange = ({ page: tablePage, sort, }: Criteria): void => { const { index: page, size } = tablePage!; const { field: sortField, direction: sortDirection } = sort!; this.setState({ from: page * size, size, sortField, sortDirection }); }; onSelectionChange = (selectedItems: ChannelItemType[]): void => { this.setState({ selectedItems }); }; onSearchChange = (search: string): void => { this.setState({ from: 0, search }); }; onFiltersChange = (filters: ChannelFiltersType): void => { this.setState({ from: 0, filters }); }; render() { const filterIsApplied = !!this.state.search; const page = Math.floor(this.state.from / this.state.size); const pagination: Pagination = { pageIndex: page, pageSize: this.state.size, pageSizeOptions: DEFAULT_PAGE_SIZE_OPTIONS, totalItemCount: this.state.total, }; const sorting: EuiTableSortingType = { sort: { direction: this.state.sortDirection, field: this.state.sortField, }, }; const selection = { selectable: () => true, onSelectionChange: this.onSelectionChange, }; return ( <> this.setState({ selectedItems }) } items={this.state.items} setItems={(items: ChannelItemType[]) => this.setState({ items }) } refresh={this.refresh} /> ), }, { component: ( Create channel ), }, ]} /> } bodyStyles={{ padding: 'initial' }} title="Channels" titleSize="m" total={this.state.total} > No channels to display} body="To send or receive notifications, you will need to create a notification channel." actions={ Create channel } /> } onChange={this.onTableChange} pagination={pagination} sorting={sorting} tableLayout="auto" loading={this.state.loading} /> ); } }