Skip to content

Commit

Permalink
UI Framework for deprecating pipeline functions (#21467)
Browse files Browse the repository at this point in the history
* added deprecated label to rulebuilder actions list

* changelog file

* added deprecated label to rule builder

* fix eslint issues

* added deprecated label to Rules quick reference

* fix eslint issue

* add tests

* removed duplicated test
  • Loading branch information
gally47 authored Feb 3, 2025
1 parent e656082 commit 9af34d1
Show file tree
Hide file tree
Showing 9 changed files with 88 additions and 40 deletions.
5 changes: 5 additions & 0 deletions changelog/unreleased/pr-21467.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
type = "f"
message = "UI Framework for deprecating pipeline functions"

pulls = ["21467"]
issues = ["19287"]
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ import * as React from 'react';
import { fireEvent, render, screen } from 'wrappedTestingLibrary';

import RuleBlockDisplay from './RuleBlockDisplay';
import { buildRuleBlock } from './fixtures';
import { RuleBuilderTypes } from './types';
import { actionsBlockDict, buildRuleBlock } from './fixtures';
import RuleBuilderProvider from './RuleBuilderProvider';

const block = buildRuleBlock({
Expand Down Expand Up @@ -52,7 +51,7 @@ describe('RuleBlockDisplay', () => {
it('shows the outputvariable and its return type', async () => {
render(
<RuleBuilderProvider>
<RuleBlockDisplay block={block} onDelete={mockDelete} onEdit={mockEdit} onNegate={mockNegate} onDuplicate={mockDuplicate} onInsertAbove={mockInsertAbove} onInsertBelow={mockInsertBelow} returnType={RuleBuilderTypes.Number} type={type} />
<RuleBlockDisplay block={block} onDelete={mockDelete} onEdit={mockEdit} onNegate={mockNegate} onDuplicate={mockDuplicate} onInsertAbove={mockInsertAbove} onInsertBelow={mockInsertBelow} selectedBlockDict={actionsBlockDict[1]} type={type} />
</RuleBuilderProvider>,
);

Expand Down Expand Up @@ -116,4 +115,14 @@ describe('RuleBlockDisplay', () => {

expect(screen.getByText('wrong 1, not right 2')).toBeInTheDocument();
});

it('shows a deprecated label for deprecating pipeline functions', async () => {
render(
<RuleBuilderProvider>
<RuleBlockDisplay block={block} onDelete={mockDelete} onEdit={mockEdit} onNegate={mockNegate} onDuplicate={mockDuplicate} onInsertAbove={mockInsertAbove} onInsertBelow={mockInsertBelow} selectedBlockDict={actionsBlockDict[0]} type={type} />
</RuleBuilderProvider>,
);

expect(screen.getByText('Deprecated')).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { IconButton } from 'components/common';
import { MORE_ACTIONS_TITLE, MORE_ACTIONS_HOVER_TITLE } from 'components/common/EntityDataTable/Constants';
import OverlayDropdownButton from 'components/common/OverlayDropdownButton';

import type { BlockType, RuleBlock } from './types';
import type { BlockDict, BlockType, RuleBlock } from './types';
import { RuleBuilderTypes } from './types';
import { useRuleBuilder } from './RuleBuilderContext';

Expand All @@ -35,7 +35,7 @@ type Props = {
onDuplicate: () => void,
onInsertAbove: () => void,
onInsertBelow: () => void,
returnType?: RuleBuilderTypes,
selectedBlockDict?: BlockDict,
type: BlockType,
}

Expand Down Expand Up @@ -89,7 +89,11 @@ const EditIconButton = styled(IconButton)(({ theme }) => css`
margin-right: ${theme.spacings.xs};
`);

const RuleBlockDisplay = ({ block, negatable = false, onEdit, onDelete, onNegate, onDuplicate, onInsertAbove, onInsertBelow, returnType, type } : Props) => {
const DeprecatedLabel = styled(Label)`
padding: 2px 8px;
`;

const RuleBlockDisplay = ({ block = undefined, negatable = false, onEdit, onDelete, onNegate, onDuplicate, onInsertAbove, onInsertBelow, selectedBlockDict = undefined, type } : Props) => {
const [showActions, setShowActions] = useState<boolean>(false);
const [isDropdownOpen, setIsDropdownOpen] = useState<boolean>(false);
const [highlightedOutput, setHighlightedOutput] = useRuleBuilder().useHighlightedOutput;
Expand All @@ -108,7 +112,7 @@ const RuleBlockDisplay = ({ block, negatable = false, onEdit, onDelete, onNegate
}
};

const returnTypeLabel = readableReturnType(returnType);
const returnTypeLabel = readableReturnType(selectedBlockDict?.return_type);

const highlightedRuleTitle = (termToHighlight: string, title: string = '') => {
const parts = title.split(/('\$.*?')/);
Expand All @@ -122,13 +126,10 @@ const RuleBlockDisplay = ({ block, negatable = false, onEdit, onDelete, onNegate
});

return (partsWithHighlight.map((item, index) => (

(

<React.Fragment key={index}>
{item}
</React.Fragment>
)
// eslint-disable-next-line react/no-array-index-key
<React.Fragment key={index}>
{item}
</React.Fragment>
)));
};

Expand All @@ -147,6 +148,9 @@ const RuleBlockDisplay = ({ block, negatable = false, onEdit, onDelete, onNegate
{highlightedOutput ? (
highlightedRuleTitle(highlightedOutput, block?.step_title)
) : block?.step_title}
{selectedBlockDict?.deprecated && (
<span>&nbsp;<DeprecatedLabel bsStyle="warning" bsSize="xs">Deprecated</DeprecatedLabel></span>
)}
{block?.errors?.length > 0 && (
<ErrorMessage title={errorMessage}>{errorMessage}</ErrorMessage>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,4 +170,10 @@ describe('RuleBlockForm', () => {
expect(screen.getByText('wrong 1')).toBeInTheDocument();
expect(screen.getByText('not right 2')).toBeInTheDocument();
});

it('shows a deprecated label for deprecating pipeline functions', async () => {
render(comp({ selectedBlockDict: actionsBlockDict[0] }));

expect(screen.getByText('Deprecated')).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { Formik } from 'formik';
import styled, { css } from 'styled-components';

import { FormSubmit, Icon, OverlayTrigger, Select, NestedForm } from 'components/common';
import { Button, Col, Row } from 'components/bootstrap';
import { Button, Col, Label, Row } from 'components/bootstrap';
import RuleBlockFormField from 'components/rules/rule-builder/RuleBlockFormField';
import { getPathnameWithoutId } from 'util/URLUtils';
import useLocation from 'routing/useLocation';
Expand All @@ -32,7 +32,7 @@ import type { BlockType, RuleBlock, BlockDict, BlockFieldDict, OutputVariables }

import RuleHelperTable from '../rule-helper/RulerHelperTable';

type Option = { label: string, value: any, description?: string | null };
type Option = { label: string, value: any, description?: string | null, deprecated?: boolean };

type Props = {
existingBlock?: RuleBlock,
Expand Down Expand Up @@ -81,16 +81,25 @@ const OptionDescription = styled.p<{ $isSelected: boolean }>(({ theme, $isSelect
overflow: hidden;
`);

const OptionContainer = styled.div`
display: flex;
justify-content: space-between;
`;

const DeprecatedLabel = styled.span`
float: right;
`;

const RuleBlockForm = ({
existingBlock,
existingBlock = undefined,
onAdd,
onCancel,
onSelect,
onUpdate,
options,
order,
outputVariableList,
selectedBlockDict,
outputVariableList = [],
selectedBlockDict = undefined,
type,
}: Props) => {
const [initialValues, setInitialValues] = useState<{}>({});
Expand Down Expand Up @@ -166,7 +175,10 @@ const RuleBlockForm = ({

const optionRenderer = (option: Option, isSelected: boolean) => (
<>
<OptionTitle>{option.label}</OptionTitle>
<OptionContainer>
<OptionTitle>{option.label}</OptionTitle>
<span>{option.deprecated && <Label bsStyle="warning" bsSize="xs">Deprecated</Label>}</span>
</OptionContainer>
{option.description && (<OptionDescription $isSelected={isSelected}>{option.description}</OptionDescription>)}
</>
);
Expand Down Expand Up @@ -210,6 +222,9 @@ const RuleBlockForm = ({
data-testid="funcSyntaxHelpIcon" />
</Button>
</OverlayTrigger>
{selectedBlockDict.deprecated && (
<DeprecatedLabel>&nbsp;<Label bsStyle="warning" bsSize="xs">Deprecated</Label></DeprecatedLabel>
)}
</h5>
<BlockDescription>{selectedBlockDict.description}</BlockDescription>
</Col>
Expand All @@ -225,8 +240,7 @@ const RuleBlockForm = ({
blockType={type}
resetField={(fieldName) => resetField(fieldName, setFieldValue)} />
</Row>
),
)}
))}

<Errors objectWithErrors={existingBlock} />
<FormSubmit bsSize="small"
Expand All @@ -237,7 +251,6 @@ const RuleBlockForm = ({
resetForm();
onCancel();
}} />

</SelectedBlock>
)}
</NestedForm>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ type Props = {
const RuleBuilderBlock = ({
type,
blockDict,
block,
block = undefined,
order,
outputVariableList,
outputVariableList = [],
addBlock,
updateBlock,
deleteBlock,
Expand Down Expand Up @@ -210,7 +210,7 @@ const RuleBuilderBlock = ({

const isBlockNegatable = (): boolean => type === 'condition';

const options = blockDict.map(({ name, description, rule_builder_name }) => ({ label: rule_builder_name, value: name, description: description }));
const options = blockDict.map(({ name, description, rule_builder_name, deprecated }) => ({ label: rule_builder_name, value: name, description, deprecated }));

const showForm = !block || editMode;

Expand All @@ -236,7 +236,7 @@ const RuleBuilderBlock = ({
onDuplicate={onDuplicate}
onInsertAbove={onInsertAbove}
onInsertBelow={onInsertBelow}
returnType={currentBlockDict?.return_type}
selectedBlockDict={currentBlockDict}
negatable={isBlockNegatable()}
type={type} />
{Boolean(insertMode) && (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { RuleBuilderTypes } from './types';
const conditionsBlockDict: BlockDict[] = [
{
name: 'has_field_less_or_equal',
deprecated: false,
pure: false,
return_type: RuleBuilderTypes.Boolean,
params: [
Expand Down Expand Up @@ -50,6 +51,7 @@ const conditionsBlockDict: BlockDict[] = [
},
{
name: 'has_field',
deprecated: false,
pure: false,
return_type: RuleBuilderTypes.Boolean,
params: [
Expand Down Expand Up @@ -80,6 +82,7 @@ const conditionsBlockDict: BlockDict[] = [
},
{
name: 'has_field_greater_or_equal',
deprecated: false,
pure: false,
return_type: RuleBuilderTypes.Boolean,
params: [
Expand Down Expand Up @@ -111,6 +114,7 @@ const conditionsBlockDict: BlockDict[] = [
},
{
name: 'has_field_equals',
deprecated: false,
pure: false,
return_type: RuleBuilderTypes.Boolean,
params: [
Expand Down Expand Up @@ -144,6 +148,7 @@ const conditionsBlockDict: BlockDict[] = [
const actionsBlockDict: BlockDict[] = [
{
name: 'has_field',
deprecated: true,
pure: false,
return_type: RuleBuilderTypes.Boolean,
params: [
Expand Down Expand Up @@ -174,6 +179,7 @@ const actionsBlockDict: BlockDict[] = [
},
{
name: 'to_long',
deprecated: false,
pure: false,
return_type: RuleBuilderTypes.Number,
params: [
Expand Down Expand Up @@ -204,6 +210,7 @@ const actionsBlockDict: BlockDict[] = [
},
{
name: 'get_field',
deprecated: false,
pure: false,
return_type: RuleBuilderTypes.Object,
params: [
Expand Down Expand Up @@ -234,6 +241,7 @@ const actionsBlockDict: BlockDict[] = [
},
{
name: 'set_grok_to_fields',
deprecated: false,
pure: false,
return_type: RuleBuilderTypes.Void,
params: [
Expand Down Expand Up @@ -291,6 +299,7 @@ const actionsBlockDict: BlockDict[] = [
},
{
name: 'substring',
deprecated: false,
pure: false,
return_type: RuleBuilderTypes.String,
params: [
Expand Down Expand Up @@ -330,6 +339,7 @@ const actionsBlockDict: BlockDict[] = [
},
{
name: 'to_string',
deprecated: false,
pure: false,
return_type: RuleBuilderTypes.String,
params: [
Expand Down Expand Up @@ -360,6 +370,7 @@ const actionsBlockDict: BlockDict[] = [
},
{
name: 'set_field',
deprecated: false,
pure: false,
return_type: RuleBuilderTypes.Void,
params: [
Expand Down Expand Up @@ -426,6 +437,7 @@ const actionsBlockDict: BlockDict[] = [
},
{
name: 'format_date',
deprecated: false,
pure: false,
return_type: RuleBuilderTypes.String,
params: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ export type BlockFieldDict = {
export type BlockDict = {
name: string,
pure: boolean,
deprecated: boolean,
return_type: RuleBuilderTypes,
params: Array<BlockFieldDict>,
description: string | null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
*/
import React from 'react';

import { Table } from 'components/bootstrap';
import { Label, Table } from 'components/bootstrap';
import { Icon } from 'components/common';

import RuleHelperStyle from './RuleHelper.css';
Expand All @@ -30,7 +30,7 @@ type Props = {
onFunctionClick?: (functionName: string) => void
}

const RuleHelperTable = ({ entries, expanded = {}, onFunctionClick } : Props) => {
const RuleHelperTable = ({ entries, expanded = {}, onFunctionClick = undefined } : Props) => {
const parameters = (descriptor: BlockDict) => descriptor.params.map((p) => (
<tr key={p.name}>
<td className={RuleHelperStyle.adjustedTableCellWidth}>{p.name}</td>
Expand Down Expand Up @@ -72,17 +72,15 @@ const RuleHelperTable = ({ entries, expanded = {}, onFunctionClick } : Props) =>

return (
<tbody key={d.name}>
{onFunctionClick ? (
<tr onClick={() => onFunctionClick(d.name)} className={RuleHelperStyle.clickableRow}>
<td className={RuleHelperStyle.functionTableCell}><code>{functionSignature(d)}</code></td>
<td>{d.description}</td>
</tr>
) : (
<tr>
<td className={RuleHelperStyle.functionTableCell}><code>{functionSignature(d)}</code></td>
<td>{d.description}</td>
</tr>
)}
<tr onClick={onFunctionClick ? () => onFunctionClick(d.name) : undefined} className={onFunctionClick ? RuleHelperStyle.clickableRow : undefined}>
<td className={RuleHelperStyle.functionTableCell}><code>{functionSignature(d)}</code></td>
<td>
{d.deprecated && (
<span><Label bsStyle="warning" bsSize="xs">Deprecated</Label>&nbsp;</span>
)}
{d.description}
</td>
</tr>
{details}
</tbody>
);
Expand Down

0 comments on commit 9af34d1

Please sign in to comment.