diff --git a/public/app/features/live/pages/AddNewRule.tsx b/public/app/features/live/pages/AddNewRule.tsx
index 44304b4ea7f..78844a8ebea 100644
--- a/public/app/features/live/pages/AddNewRule.tsx
+++ b/public/app/features/live/pages/AddNewRule.tsx
@@ -12,7 +12,7 @@ export function AddNewRule({ onClose }: Props) {
.post(`api/live/channel-rules`, {
pattern: formData.pattern,
settings: {
- output: formData.settings.output,
+ output: formData.settings.frameOutputs,
converter: formData.settings.converter,
},
})
@@ -31,9 +31,11 @@ export function AddNewRule({ onClose }: Props) {
converter: {
type: 'jsonAuto',
},
- output: {
- type: 'managedStream',
- },
+ frameOutputs: [
+ {
+ type: 'managedStream',
+ },
+ ],
},
}}
onSubmit={onSubmit}
diff --git a/public/app/features/live/pages/PipelineAdminPage.tsx b/public/app/features/live/pages/PipelineAdminPage.tsx
index 46a1291db49..8a6120f15b7 100644
--- a/public/app/features/live/pages/PipelineAdminPage.tsx
+++ b/public/app/features/live/pages/PipelineAdminPage.tsx
@@ -13,9 +13,6 @@ function renderOutputTags(key: string, output?: Output): React.ReactNode {
if (!output?.type) {
return null;
}
- if (output.multiple?.outputs?.length) {
- return output.multiple?.outputs.map((v, i) => renderOutputTags(`${key}-${i}`, v));
- }
return ;
}
@@ -47,7 +44,9 @@ export default function PipelineAdminPage() {
const onRowClick = (event: any) => {
const pattern = event.target.getAttribute('data-pattern');
const column = event.target.getAttribute('data-column');
- if (column) {
+ if (column === 'pattern') {
+ setClickColumn('converter');
+ } else {
setClickColumn(column);
}
setSelectedRule(rules.filter((rule) => rule.pattern === pattern)[0]);
@@ -99,10 +98,14 @@ export default function PipelineAdminPage() {
{rule.settings?.converter?.type}
- {rule.settings?.processor?.type}
+ {rule.settings?.frameProcessors?.map((processor) => (
+ {processor.type}
+ ))}
|
- {renderOutputTags('out', rule.settings?.output)}
+ {rule.settings?.frameOutputs?.map((output) => (
+ {renderOutputTags('out', output)}
+ ))}
|
onRemoveRule(rule.pattern)}>
diff --git a/public/app/features/live/pages/RuleModal.tsx b/public/app/features/live/pages/RuleModal.tsx
index 01cd60bfafb..605a564da1f 100644
--- a/public/app/features/live/pages/RuleModal.tsx
+++ b/public/app/features/live/pages/RuleModal.tsx
@@ -6,6 +6,7 @@ import { css } from '@emotion/css';
import { GrafanaTheme } from '@grafana/data';
import { RuleSettingsEditor } from './RuleSettingsEditor';
import { getPipeLineEntities } from './utils';
+import { RuleSettingsArray } from './RuleSettingsArray';
interface Props {
rule: Rule;
@@ -19,8 +20,8 @@ interface TabType {
}
const tabs: TabType[] = [
{ label: 'Converter', value: 'converter' },
- { label: 'Processor', value: 'processor' },
- { label: 'Output', value: 'output' },
+ { label: 'Processors', value: 'frameProcessors' },
+ { label: 'Outputs', value: 'frameOutputs' },
];
export const RuleModal: React.FC = (props) => {
@@ -33,7 +34,7 @@ export const RuleModal: React.FC = (props) => {
const [entitiesInfo, setEntitiesInfo] = useState();
const styles = useStyles(getStyles);
- const onRuleSettingChange = (value: RuleSetting) => {
+ const onRuleSettingChange = (value: RuleSetting | RuleSetting[]) => {
setChange(true);
setRule({
...rule,
@@ -57,6 +58,7 @@ export const RuleModal: React.FC = (props) => {
.put(`api/live/channel-rules`, rule)
.then(() => {
setChange(false);
+ onClose();
})
.catch((e) => console.error(e));
};
@@ -80,7 +82,7 @@ export const RuleModal: React.FC = (props) => {
})}
- {entitiesInfo && rule && (
+ {entitiesInfo && rule && activeTab === 'converter' && (
= (props) => {
entitiesInfo={entitiesInfo}
/>
)}
+ {entitiesInfo && rule && activeTab !== 'converter' && (
+
+ )}
diff --git a/public/app/features/live/pages/RuleSettingsArray.tsx b/public/app/features/live/pages/RuleSettingsArray.tsx
new file mode 100644
index 00000000000..c209e9d578d
--- /dev/null
+++ b/public/app/features/live/pages/RuleSettingsArray.tsx
@@ -0,0 +1,50 @@
+import React, { useState } from 'react';
+import { RuleSettingsEditor } from './RuleSettingsEditor';
+import { RuleType, RuleSetting, PipeLineEntitiesInfo } from './types';
+import { Select } from '@grafana/ui';
+import { SelectableValue } from '../../../../../packages/grafana-data/src';
+
+interface Props {
+ ruleType: RuleType;
+ onChange: (value: RuleSetting[]) => void;
+ value: RuleSetting[];
+ entitiesInfo: PipeLineEntitiesInfo;
+}
+
+export const RuleSettingsArray: React.FC = ({ onChange, value, ruleType, entitiesInfo }) => {
+ const [index, setIndex] = useState(0);
+ const arr = value ?? [];
+ const onRuleChange = (v: RuleSetting) => {
+ if (!value) {
+ onChange([v]);
+ } else {
+ const copy = [...value];
+ copy[index] = v;
+ onChange(copy);
+ }
+ };
+ // create array of value.length + 1
+ let indexArr: Array> = [];
+ for (let i = 0; i <= arr.length; i++) {
+ indexArr.push({
+ label: `${ruleType}: ${i}`,
+ value: i,
+ });
+ }
+
+ return (
+ <>
+
+
+ >
+ );
+};
diff --git a/public/app/features/live/pages/types.ts b/public/app/features/live/pages/types.ts
index e035c930c10..921ad730575 100644
--- a/public/app/features/live/pages/types.ts
+++ b/public/app/features/live/pages/types.ts
@@ -9,9 +9,6 @@ export interface Processor extends RuleSetting {
export interface Output extends RuleSetting {
[t: string]: any;
- multiple?: {
- outputs: Output[];
- };
}
export interface RuleSetting {
@@ -20,8 +17,8 @@ export interface RuleSetting {
}
export interface RuleSettings {
converter?: Converter;
- processor?: Processor;
- output?: Output;
+ frameProcessors?: Processor[];
+ frameOutputs?: Output[];
}
export interface Rule {
@@ -38,22 +35,22 @@ export interface GrafanaCloudBackend {
settings: any;
}
-export type RuleType = 'converter' | 'processor' | 'output';
+export type RuleType = 'converter' | 'frameProcessors' | 'frameOutputs';
export interface PipelineListOption {
type: string;
description: string;
- example: object;
+ example?: object;
}
export interface EntitiesTypes {
converters: PipelineListOption[];
- processors: PipelineListOption[];
- outputs: PipelineListOption[];
+ frameProcessors: PipelineListOption[];
+ frameOutputs: PipelineListOption[];
}
export interface PipeLineEntitiesInfo {
converter: SelectableValue[];
- processor: SelectableValue[];
- output: SelectableValue[];
+ frameProcessors: SelectableValue[];
+ frameOutputs: SelectableValue[];
getExample: (rule: RuleType, type: string) => object;
}
diff --git a/public/app/features/live/pages/utils.ts b/public/app/features/live/pages/utils.ts
index 007ddbb9ea6..edb8e90ad1a 100644
--- a/public/app/features/live/pages/utils.ts
+++ b/public/app/features/live/pages/utils.ts
@@ -7,8 +7,8 @@ export async function getPipeLineEntities(): Promise {
.then((data) => {
return {
converter: transformLabel(data, 'converters'),
- processor: transformLabel(data, 'processors'),
- output: transformLabel(data, 'outputs'),
+ frameProcessors: transformLabel(data, 'frameProcessors'),
+ frameOutputs: transformLabel(data, 'frameOutputs'),
getExample: (ruleType, type) => {
return data[`${ruleType}s`]?.filter((option: PipelineListOption) => option.type === type)?.[0]?.['example'];
},
|