Line data Source code
1 : /*
2 : * Copyright (C) 2020 Red Hat, Inc.
3 : * SPDX-License-Identifier: LGPL-2.1-or-later
4 : */
5 :
6 342 : import React from 'react';
7 : import { Tab, TabTitleText, Tabs } from "@patternfly/react-core/dist/esm/components/Tabs/index.js";
8 : import './cockpit-components-listing-panel.scss';
9 :
10 : /* tabRenderers optional: list of tab renderers for inline expansion, array of objects with
11 : * - name tab name (has to be unique in the entry, used as react key)
12 : * - renderer react component
13 : * - data render data passed to the tab renderer
14 : */
15 :
16 : interface TabRenderer {
17 : name: string;
18 : // eslint-disable-next-line @typescript-eslint/no-explicit-any
19 : renderer: React.ComponentType<any>;
20 : data?: Record<string, unknown>;
21 : }
22 :
23 : interface ListingPanelProps {
24 : tabRenderers?: TabRenderer[];
25 : listingDetail?: React.ReactNode;
26 : initiallyActiveTab?: number;
27 : }
28 :
29 : interface ListingPanelState {
30 : activeTab: string | number;
31 : }
32 :
33 342 : export class ListingPanel extends React.Component<ListingPanelProps, ListingPanelState> {
34 342 : static defaultProps = {
35 342 : tabRenderers: [],
36 342 : };
37 :
38 4 : constructor(props: ListingPanelProps) {
39 4 : super(props);
40 4 : this.state = {
41 1 : activeTab: props.initiallyActiveTab ? props.initiallyActiveTab : 0, // currently active tab in expanded mode, defaults to first tab
42 4 : };
43 4 : this.handleTabClick = this.handleTabClick.bind(this);
44 4 : }
45 :
46 1 : handleTabClick(event: React.MouseEvent, tabIndex: number | string) {
47 1 : event.preventDefault();
48 1 : if (this.state.activeTab !== tabIndex) {
49 1 : this.setState({ activeTab: tabIndex });
50 1 : }
51 1 : }
52 :
53 4 : render() {
54 4 : let listingDetail;
55 2 : if ('listingDetail' in this.props) {
56 2 : listingDetail = (
57 2 : <span className="ct-listing-panel-caption">
58 2 : {this.props.listingDetail}
59 2 : </span>
60 : );
61 2 : }
62 :
63 4 : return (
64 4 : <div className="ct-listing-panel">
65 2 : {listingDetail && <div className="ct-listing-panel-actions pf-v6-c-tabs">
66 2 : {listingDetail}
67 2 : </div>}
68 4 : {this.props.tabRenderers?.length && <Tabs activeKey={this.state.activeTab} className="ct-listing-panel-tabs" mountOnEnter onSelect={this.handleTabClick}>
69 4 : {this.props.tabRenderers?.map((itm, tabIdx) => {
70 4 : const Renderer = itm.renderer;
71 4 : const rendererData = itm.data;
72 :
73 4 : return (
74 4 : <Tab key={tabIdx} eventKey={tabIdx} title={<TabTitleText>{itm.name}</TabTitleText>}>
75 4 : <div className="ct-listing-panel-body" key={tabIdx} data-key={tabIdx}>
76 4 : <Renderer {...rendererData} />
77 4 : </div>
78 4 : </Tab>
79 : );
80 4 : })}
81 4 : </Tabs>}
82 4 : </div>
83 : );
84 4 : }
85 342 : }
|