grafana/public/app/features/live/pages/PipelineTable.tsx
2021-10-22 08:56:16 -07:00

145 lines
4.2 KiB
TypeScript

import React, { useEffect, useState } from 'react';
import { getBackendSrv } from '@grafana/runtime';
import { Tag, useStyles, IconButton } from '@grafana/ui';
import { css } from '@emotion/css';
import { GrafanaTheme } from '@grafana/data';
import { Rule, Output, RuleType } from './types';
import { RuleModal } from './RuleModal';
import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
function renderOutputTags(key: string, output?: Output): React.ReactNode {
if (!output?.type) {
return null;
}
return <Tag key={key} name={output.type} />;
}
interface Props {
rules: Rule[];
onRuleChanged: () => void;
selectRule?: Rule;
}
export const PipelineTable: React.FC<Props> = (props) => {
const { rules } = props;
const [isOpen, setOpen] = useState(false);
const [selectedRule, setSelectedRule] = useState<Rule>();
const [clickColumn, setClickColumn] = useState<RuleType>('converter');
const styles = useStyles(getStyles);
const onRowClick = (rule: Rule, event?: any) => {
if (!rule) {
return;
}
let column = event?.target?.getAttribute('data-column');
if (!column || column === 'pattern') {
column = 'converter';
}
setClickColumn(column);
setSelectedRule(rule);
setOpen(true);
};
// Supports selecting a rule from external config (after add rule)
useEffect(() => {
if (props.selectRule) {
onRowClick(props.selectRule);
}
}, [props.selectRule]);
const onRemoveRule = (pattern: string) => {
getBackendSrv()
.delete(`api/live/channel-rules`, JSON.stringify({ pattern: pattern }))
.catch((e) => console.error(e))
.finally(() => {
props.onRuleChanged();
});
};
const renderPattern = (pattern: string) => {
if (pattern.startsWith('ds/')) {
const idx = pattern.indexOf('/', 4);
if (idx > 3) {
const uid = pattern.substring(3, idx);
const ds = getDatasourceSrv().getInstanceSettings(uid);
if (ds) {
return (
<div>
<Tag name={ds.name} colorIndex={1} /> &nbsp;
<span>{pattern.substring(idx + 1)}</span>
</div>
);
}
}
}
return pattern;
};
return (
<div>
<div className="admin-list-table">
<table className="filter-table filter-table--hover form-inline">
<thead>
<tr>
<th>Channel</th>
<th>Converter</th>
<th>Processor</th>
<th>Output</th>
<th style={{ width: 10 }}>&nbsp;</th>
</tr>
</thead>
<tbody>
{rules.map((rule) => (
<tr key={rule.pattern} onClick={(e) => onRowClick(rule, e)} className={styles.row}>
<td data-pattern={rule.pattern} data-column="pattern">
{renderPattern(rule.pattern)}
</td>
<td data-pattern={rule.pattern} data-column="converter">
{rule.settings?.converter?.type}
</td>
<td data-pattern={rule.pattern} data-column="processor">
{rule.settings?.frameProcessors?.map((processor) => (
<span key={rule.pattern + processor.type}>{processor.type}</span>
))}
</td>
<td data-pattern={rule.pattern} data-column="output">
{rule.settings?.frameOutputs?.map((output) => (
<span key={rule.pattern + output.type}>{renderOutputTags('out', output)}</span>
))}
</td>
<td>
<IconButton
name="trash-alt"
onClick={(e) => {
e.stopPropagation();
onRemoveRule(rule.pattern);
}}
></IconButton>
</td>
</tr>
))}
</tbody>
</table>
</div>
{isOpen && selectedRule && (
<RuleModal
rule={selectedRule}
isOpen={isOpen}
onClose={() => {
setOpen(false);
}}
clickColumn={clickColumn}
/>
)}
</div>
);
};
const getStyles = (theme: GrafanaTheme) => {
return {
row: css`
cursor: pointer;
`,
};
};