mirror of
https://github.com/grafana/grafana.git
synced 2025-08-02 15:28:01 +08:00

* i18n: removes useTranslate hook * chore: fix duplicate imports * chore: fix import sorting and hook dependencies
117 lines
3.5 KiB
TypeScript
117 lines
3.5 KiB
TypeScript
import { cx } from '@emotion/css';
|
|
import { useEffect, useState } from 'react';
|
|
|
|
import { t } from '@grafana/i18n';
|
|
import { FadeTransition, LoadingPlaceholder, useStyles2 } from '@grafana/ui';
|
|
|
|
import { NestedEntry } from './NestedEntry';
|
|
import getStyles from './styles';
|
|
import { ResourceRow, ResourceRowGroup, ResourceRowType } from './types';
|
|
import { findRow } from './utils';
|
|
|
|
interface NestedRowProps {
|
|
row: ResourceRow;
|
|
level: number;
|
|
selectedRows: ResourceRowGroup;
|
|
requestNestedRows: (row: ResourceRow) => Promise<void>;
|
|
onRowSelectedChange: (row: ResourceRow, selected: boolean) => void;
|
|
selectableEntryTypes: ResourceRowType[];
|
|
disableRow: (row: ResourceRow, selectedRows: ResourceRowGroup) => boolean;
|
|
scrollIntoView?: boolean;
|
|
}
|
|
|
|
const NestedRow = ({
|
|
row,
|
|
selectedRows,
|
|
level,
|
|
requestNestedRows,
|
|
onRowSelectedChange,
|
|
selectableEntryTypes,
|
|
scrollIntoView,
|
|
disableRow,
|
|
}: NestedRowProps) => {
|
|
const styles = useStyles2(getStyles);
|
|
const [rowStatus, setRowStatus] = useState<'open' | 'closed' | 'loading'>('closed');
|
|
|
|
const isSelected = !!selectedRows.find((v) => v.uri.toLowerCase() === row.uri.toLowerCase());
|
|
const isDisabled = !isSelected && disableRow(row, selectedRows);
|
|
const isOpen = rowStatus === 'open';
|
|
|
|
const onRowToggleCollapse = async () => {
|
|
if (rowStatus === 'open') {
|
|
setRowStatus('closed');
|
|
return;
|
|
}
|
|
setRowStatus('loading');
|
|
requestNestedRows(row)
|
|
.then(() => setRowStatus('open'))
|
|
.catch(() => setRowStatus('closed'));
|
|
};
|
|
|
|
// opens the resource group on load of component if there was a previously saved selection
|
|
useEffect(() => {
|
|
// Assuming we don't have multi-select yet
|
|
const selectedRow = selectedRows[0];
|
|
|
|
const containsChild = selectedRow && !!findRow(row.children ?? [], selectedRow.uri);
|
|
|
|
if (containsChild) {
|
|
setRowStatus('open');
|
|
}
|
|
}, [selectedRows, row]);
|
|
|
|
return (
|
|
<>
|
|
<tr className={cx(styles.row, isDisabled && styles.disabledRow)} key={row.id}>
|
|
<td className={styles.cell}>
|
|
<NestedEntry
|
|
level={level}
|
|
isSelected={isSelected}
|
|
isDisabled={isDisabled}
|
|
isOpen={isOpen}
|
|
entry={row}
|
|
onToggleCollapse={onRowToggleCollapse}
|
|
onSelectedChange={onRowSelectedChange}
|
|
isSelectable={selectableEntryTypes.some((type) => type === row.type)}
|
|
scrollIntoView={scrollIntoView}
|
|
/>
|
|
</td>
|
|
|
|
<td className={styles.cell}>{row.typeLabel}</td>
|
|
|
|
<td className={styles.cell}>{row.location ?? '-'}</td>
|
|
</tr>
|
|
|
|
{isOpen &&
|
|
row.children &&
|
|
Object.keys(row.children).length > 0 &&
|
|
row.children.map((childRow) => (
|
|
<NestedRow
|
|
key={childRow.uri}
|
|
row={childRow}
|
|
selectedRows={selectedRows}
|
|
level={level + 1}
|
|
requestNestedRows={requestNestedRows}
|
|
onRowSelectedChange={onRowSelectedChange}
|
|
selectableEntryTypes={selectableEntryTypes}
|
|
scrollIntoView={scrollIntoView}
|
|
disableRow={disableRow}
|
|
/>
|
|
))}
|
|
|
|
<FadeTransition visible={rowStatus === 'loading'}>
|
|
<tr>
|
|
<td className={cx(styles.cell, styles.loadingCell)} colSpan={3}>
|
|
<LoadingPlaceholder
|
|
text={t('components.nested-row.text-loading', 'Loading...')}
|
|
className={styles.spinner}
|
|
/>
|
|
</td>
|
|
</tr>
|
|
</FadeTransition>
|
|
</>
|
|
);
|
|
};
|
|
|
|
export default NestedRow;
|