PipelineTable.tsx 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. import { css } from '@emotion/css';
  2. import React, { useEffect, useState } from 'react';
  3. import { GrafanaTheme } from '@grafana/data';
  4. import { getBackendSrv } from '@grafana/runtime';
  5. import { Tag, useStyles, IconButton } from '@grafana/ui';
  6. import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
  7. import { RuleModal } from './RuleModal';
  8. import { Rule, Output, RuleType } from './types';
  9. function renderOutputTags(key: string, output?: Output): React.ReactNode {
  10. if (!output?.type) {
  11. return null;
  12. }
  13. return <Tag key={key} name={output.type} />;
  14. }
  15. interface Props {
  16. rules: Rule[];
  17. onRuleChanged: () => void;
  18. selectRule?: Rule;
  19. }
  20. export const PipelineTable: React.FC<Props> = (props) => {
  21. const { rules } = props;
  22. const [isOpen, setOpen] = useState(false);
  23. const [selectedRule, setSelectedRule] = useState<Rule>();
  24. const [clickColumn, setClickColumn] = useState<RuleType>('converter');
  25. const styles = useStyles(getStyles);
  26. const onRowClick = (rule: Rule, event?: any) => {
  27. if (!rule) {
  28. return;
  29. }
  30. let column = event?.target?.getAttribute('data-column');
  31. if (!column || column === 'pattern') {
  32. column = 'converter';
  33. }
  34. setClickColumn(column);
  35. setSelectedRule(rule);
  36. setOpen(true);
  37. };
  38. // Supports selecting a rule from external config (after add rule)
  39. useEffect(() => {
  40. if (props.selectRule) {
  41. onRowClick(props.selectRule);
  42. }
  43. }, [props.selectRule]);
  44. const onRemoveRule = (pattern: string) => {
  45. getBackendSrv()
  46. .delete(`api/live/channel-rules`, JSON.stringify({ pattern: pattern }))
  47. .catch((e) => console.error(e))
  48. .finally(() => {
  49. props.onRuleChanged();
  50. });
  51. };
  52. const renderPattern = (pattern: string) => {
  53. if (pattern.startsWith('ds/')) {
  54. const idx = pattern.indexOf('/', 4);
  55. if (idx > 3) {
  56. const uid = pattern.substring(3, idx);
  57. const ds = getDatasourceSrv().getInstanceSettings(uid);
  58. if (ds) {
  59. return (
  60. <div>
  61. <Tag name={ds.name} colorIndex={1} /> &nbsp;
  62. <span>{pattern.substring(idx + 1)}</span>
  63. </div>
  64. );
  65. }
  66. }
  67. }
  68. return pattern;
  69. };
  70. return (
  71. <div>
  72. <div className="admin-list-table">
  73. <table className="filter-table filter-table--hover form-inline">
  74. <thead>
  75. <tr>
  76. <th>Channel</th>
  77. <th>Converter</th>
  78. <th>Processor</th>
  79. <th>Output</th>
  80. <th style={{ width: 10 }}>&nbsp;</th>
  81. </tr>
  82. </thead>
  83. <tbody>
  84. {rules.map((rule) => (
  85. <tr key={rule.pattern} onClick={(e) => onRowClick(rule, e)} className={styles.row}>
  86. <td data-pattern={rule.pattern} data-column="pattern">
  87. {renderPattern(rule.pattern)}
  88. </td>
  89. <td data-pattern={rule.pattern} data-column="converter">
  90. {rule.settings?.converter?.type}
  91. </td>
  92. <td data-pattern={rule.pattern} data-column="processor">
  93. {rule.settings?.frameProcessors?.map((processor) => (
  94. <span key={rule.pattern + processor.type}>{processor.type}</span>
  95. ))}
  96. </td>
  97. <td data-pattern={rule.pattern} data-column="output">
  98. {rule.settings?.frameOutputs?.map((output) => (
  99. <span key={rule.pattern + output.type}>{renderOutputTags('out', output)}</span>
  100. ))}
  101. </td>
  102. <td>
  103. <IconButton
  104. name="trash-alt"
  105. onClick={(e) => {
  106. e.stopPropagation();
  107. onRemoveRule(rule.pattern);
  108. }}
  109. ></IconButton>
  110. </td>
  111. </tr>
  112. ))}
  113. </tbody>
  114. </table>
  115. </div>
  116. {isOpen && selectedRule && (
  117. <RuleModal
  118. rule={selectedRule}
  119. isOpen={isOpen}
  120. onClose={() => {
  121. setOpen(false);
  122. }}
  123. clickColumn={clickColumn}
  124. />
  125. )}
  126. </div>
  127. );
  128. };
  129. const getStyles = (theme: GrafanaTheme) => {
  130. return {
  131. row: css`
  132. cursor: pointer;
  133. `,
  134. };
  135. };