Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Security Solution] Reduce dropdown options and improve tooltip texts in Rule Upgrade flyout #203222

Merged
merged 83 commits into from
Dec 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
51464ba
rename components for better readability
maximpn Nov 22, 2024
963c64d
fix wrong texts
maximpn Nov 22, 2024
40b406c
display initially edit mode for NON_SOLVABLE conflicts
maximpn Nov 22, 2024
db04859
add save button
maximpn Nov 22, 2024
04b918d
display save button at the final side header
maximpn Nov 23, 2024
b5baa0f
implement rule field resolver scenarios
maximpn Nov 23, 2024
92a5615
add no_conflict state
maximpn Nov 24, 2024
e63bc65
add FieldEditFormContext explanation
maximpn Nov 25, 2024
e4b9150
change rule upgrade callout according to the design
maximpn Nov 25, 2024
7dc16f7
display modified badge for customized fields
maximpn Nov 25, 2024
dbea30e
remove excess padding
maximpn Nov 25, 2024
7b86e68
add upgrade rule header details
maximpn Nov 25, 2024
cfdb2c0
fix non scrollable tab content
maximpn Nov 25, 2024
f528936
toss files and folders for better readability
maximpn Nov 26, 2024
11d7600
simplify implementation by merging used react contexts
maximpn Nov 26, 2024
13db2da
use a proper key for SubfieldChanges component rendered items
maximpn Nov 26, 2024
27e213c
remove unused translations keys
maximpn Nov 26, 2024
155aa85
simplify layout for field update header
maximpn Nov 26, 2024
55436ef
simplify conflicts number calculation
maximpn Nov 27, 2024
e99dcf8
show current rule update info as last update
maximpn Nov 27, 2024
0dd8ac9
copy side header to SIEM migrations
maximpn Nov 27, 2024
2ab328a
fix broken imports
maximpn Nov 28, 2024
6abef52
use human friendly names for rule/field versions
maximpn Nov 29, 2024
1e707b9
display a proper field description
maximpn Dec 3, 2024
8494eea
fix translations
maximpn Dec 3, 2024
7a2715b
fix rule upgrade state callout
maximpn Dec 3, 2024
d77b40f
add a proper key for subfield changes
maximpn Dec 3, 2024
6f773f7
fix rule upgrade info
maximpn Dec 3, 2024
6e50d6b
fix improper rule.id usage for rule upgrade flyout
maximpn Dec 3, 2024
e486317
move upgradeAllRule to UpgradePrebuiltRulesTableContext
maximpn Dec 3, 2024
496e63e
simplify hasUnresolvedConflicts calculation
maximpn Dec 3, 2024
49d56c0
improve calcCustomizableFieldsDiff implementation
maximpn Dec 3, 2024
2d1ae44
update field modified condition
maximpn Dec 3, 2024
5ef654c
add dynamically updating rule upgrade state
maximpn Dec 3, 2024
63d8f7b
delay unnecessary calculations until rule upgrade flyout is shown
maximpn Dec 3, 2024
0865ee2
fix an icon
maximpn Dec 3, 2024
9062b56
fix hasRulesToUpgrade calculation
maximpn Dec 3, 2024
1f6b254
remove unused translation keys
maximpn Dec 4, 2024
2fd19e7
reduce unnecessary rulesUpgradeState recalculation
maximpn Dec 4, 2024
e158773
simplify modals implementation
maximpn Dec 4, 2024
e5ad437
fix unnecessary header wrapping
maximpn Dec 4, 2024
6bef7d5
rollback use_fetch_prebuilt_rules_upgrade_review_query.ts changes
maximpn Dec 4, 2024
7c99d90
remove unnecessary file after rebase
maximpn Dec 5, 2024
4684c3f
calc everyFieldHasConflict based on conflict resolution state
maximpn Dec 5, 2024
d94635b
display a number of solved and non solved conflicts in rule callout
maximpn Dec 5, 2024
e26cd43
add modified badge tooltip
maximpn Dec 5, 2024
09a0edf
fix variable naming
maximpn Dec 5, 2024
8e8ecb7
set min-width for version picker component
maximpn Dec 5, 2024
ebd5e83
make field names in updates matching design
maximpn Dec 5, 2024
eae9df7
fix translation keys
maximpn Dec 5, 2024
761407c
fix update selected rules button's condition
maximpn Dec 6, 2024
54167fc
disallow rule upgrade requests without rules specified
maximpn Dec 6, 2024
f358957
post-rebase fix
maximpn Dec 6, 2024
e744e2d
allow to unset values
maximpn Dec 6, 2024
4e36df8
properly calculate customized state for optional fields
maximpn Dec 6, 2024
9a87fe5
fix rule upgrade state numbers
maximpn Dec 6, 2024
d125acb
take into account conflict resolved state for field upgrade expandabl…
maximpn Dec 6, 2024
56e68ae
add no update state
maximpn Dec 6, 2024
2f7e68d
fix translations keys
maximpn Dec 6, 2024
696ee63
disallow rule type change upgrade in rule upgrades table
maximpn Dec 6, 2024
0988d20
hide field updates for rule type change
maximpn Dec 6, 2024
de9fc27
change rule type change callout for a case without customization
maximpn Dec 6, 2024
86a453a
make hasUnresolvedConflicts calculation clearer
maximpn Dec 7, 2024
93701fa
eliminate double hasConflict calculation
maximpn Dec 7, 2024
1c24509
fix invariant's message
maximpn Dec 10, 2024
5a5bf49
remove unnecessary added fragment
maximpn Dec 10, 2024
831c8a5
use invariant instead of if condition
maximpn Dec 10, 2024
3f30fdb
improve readability
maximpn Dec 10, 2024
137c404
roll back useFilterPrebuiltRulesToUpgrade changes
maximpn Dec 10, 2024
e5d13cd
remove field's Modified badge
maximpn Dec 10, 2024
907218c
fix a typing issue
maximpn Dec 10, 2024
5a455a9
Reduce number of options, update tooltips
nikitaindik Dec 10, 2024
b650bd5
Merge branch 'main' into finalize-prebuilt-rule-customization-layout
maximpn Dec 11, 2024
d340f8c
Merge remote-tracking branch 'maximpn/finalize-prebuilt-rule-customiz…
nikitaindik Dec 11, 2024
46af2d1
Merge remote-tracking branch 'upstream/main' into better-popup-texts
nikitaindik Dec 11, 2024
ccd36e6
Merge remote-tracking branch 'upstream/main' into better-popup-texts
nikitaindik Dec 12, 2024
3d33521
Move `hasResolvedValueDifferentFromSuggested` calculation into a `Fie…
nikitaindik Dec 12, 2024
19ba5ec
Rename "My customization" -> "My original changes"
nikitaindik Dec 12, 2024
5b852ee
Add "My original changes" only in case ABC-NS
nikitaindik Dec 12, 2024
555c39a
Refactor `VersionsPicker` and related components
nikitaindik Dec 13, 2024
f41f801
Merge remote-tracking branch 'upstream/main' into better-popup-texts
nikitaindik Dec 13, 2024
3eab22a
Address last-minute feedback
nikitaindik Dec 14, 2024
e23f918
Merge remote-tracking branch 'upstream/main' into better-popup-texts
nikitaindik Dec 14, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,10 @@ import React from 'react';
import useToggle from 'react-use/lib/useToggle';
import { EuiPopover, EuiText, EuiButtonIcon } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n-react';
import { i18n } from '@kbn/i18n';
import { TITLE } from './translations';
import {
BASE_VERSION,
CURRENT_VERSION,
FINAL_VERSION,
TARGET_VERSION,
} from './versions_picker/translations';
import type { VersionsPickerOptionEnum } from './versions_picker/versions_picker';
import { useFieldUpgradeContext } from '../rule_upgrade/field_upgrade_context';
import { getOptionDetails } from './utils';

/**
* Theme doesn't expose width variables. Using provided size variables will require
Expand All @@ -27,9 +23,18 @@ import {
*/
const POPOVER_WIDTH = 320;

export function ComparisonSideHelpInfo(): JSX.Element {
interface ComparisonSideHelpInfoProps {
options: VersionsPickerOptionEnum[];
}

export function ComparisonSideHelpInfo({ options }: ComparisonSideHelpInfoProps): JSX.Element {
const [isPopoverOpen, togglePopover] = useToggle(false);

const { hasResolvedValueDifferentFromSuggested } = useFieldUpgradeContext();
const optionsWithDescriptions = options.map((option) =>
getOptionDetails(option, hasResolvedValueDifferentFromSuggested)
);

const button = (
<EuiButtonIcon
iconType="questionInCircle"
Expand All @@ -43,25 +48,20 @@ export function ComparisonSideHelpInfo(): JSX.Element {
<EuiText style={{ width: POPOVER_WIDTH }} size="s">
<FormattedMessage
id="xpack.securitySolution.detectionEngine.rules.upgradeRules.comparisonSide.upgradeHelpText"
defaultMessage="{title} shows field's JSON diff between prebuilt rule field versions affecting the rule update process. {versions}"
defaultMessage="The {title} lets you compare the values of a field across different versions of a rule: {versions} Differences are shown as JSON, with red lines showing what was removed, green lines showing additions, and bold text highlighting changes. Use {title} to review and understand changes across versions."
values={{
title: <strong>{TITLE}</strong>,
versions: (
<>
<br />
<ul>
<li>
<strong>{BASE_VERSION}</strong> {'-'} {BASE_VERSION_EXPLANATION}
</li>
<li>
<strong>{CURRENT_VERSION}</strong> {'-'} {CURRENT_VERSION_EXPLANATION}
</li>
<li>
<strong>{TARGET_VERSION}</strong> {'-'} {TARGET_VERSION_EXPLANATION}
</li>
<li>
<strong>{FINAL_VERSION}</strong> {'-'} {FINAL_VERSION_EXPLANATION}
</li>
{optionsWithDescriptions.map(
({ title: displayName, description: explanation }) => (
<li>
<strong>{displayName}</strong> {'-'} {explanation}
</li>
)
)}
</ul>
</>
),
Expand All @@ -71,35 +71,3 @@ export function ComparisonSideHelpInfo(): JSX.Element {
</EuiPopover>
);
}

const BASE_VERSION_EXPLANATION = i18n.translate(
'xpack.securitySolution.detectionEngine.rules.upgradeRules.versions.baseVersionExplanation',
{
defaultMessage: 'version originally installed from Elastic prebuilt rules package',
}
);

const CURRENT_VERSION_EXPLANATION = (
<FormattedMessage
id="xpack.securitySolution.detectionEngine.rules.upgradeRules.currentVersionExplanation"
defaultMessage="current version including modification made after prebuilt rule installation. With lack of modifications it matches with {base}."
values={{
base: <strong>{BASE_VERSION}</strong>,
}}
/>
);

const TARGET_VERSION_EXPLANATION = i18n.translate(
'xpack.securitySolution.detectionEngine.rules.upgradeRules.versions.targetVersionExplanation',
{
defaultMessage: 'version coming from a new version of Elastic prebuilt rules package',
}
);

const FINAL_VERSION_EXPLANATION = i18n.translate(
'xpack.securitySolution.detectionEngine.rules.upgradeRules.versions.finalVersionExplanation',
{
defaultMessage:
'version used to the update the rule. Initial value is suggested by the diff algorithm.',
}
);
Original file line number Diff line number Diff line change
Expand Up @@ -5,35 +5,56 @@
* 2.0.
*/

import React, { useState } from 'react';
import React, { useState, useEffect } from 'react';
import { EuiFlexGroup, EuiFlexItem, EuiTitle } from '@elastic/eui';
import { VersionsPicker } from './versions_picker/versions_picker';
import type { Version } from './versions_picker/constants';
import { SelectedVersions } from './versions_picker/constants';
import { isEqual } from 'lodash';
import usePrevious from 'react-use/lib/usePrevious';
import { VersionsPicker, VersionsPickerOptionEnum } from './versions_picker/versions_picker';
import { FieldUpgradeSideHeader } from '../field_upgrade_side_header';
import { useFieldUpgradeContext } from '../rule_upgrade/field_upgrade_context';
import { pickFieldValueForVersion } from './utils';
import {
getComparisonOptionsForDiffOutcome,
getVersionsForComparison,
pickFieldValueForVersion,
} from './utils';
import { getSubfieldChanges } from './get_subfield_changes';
import { SubfieldChanges } from './subfield_changes';
import { ComparisonSideHelpInfo } from './comparison_side_help_info';
import * as i18n from './translations';

export function FieldComparisonSide(): JSX.Element {
const { fieldName, fieldDiff, finalDiffableRule } = useFieldUpgradeContext();
const { fieldName, fieldDiff, finalDiffableRule, hasResolvedValueDifferentFromSuggested } =
useFieldUpgradeContext();
const resolvedValue = finalDiffableRule[fieldName];

const [selectedVersions, setSelectedVersions] = useState<SelectedVersions>(
SelectedVersions.CurrentFinal
const options = getComparisonOptionsForDiffOutcome(
fieldDiff.diff_outcome,
fieldDiff.conflict,
hasResolvedValueDifferentFromSuggested
);
const [selectedOption, setSelectedOption] = useState<VersionsPickerOptionEnum>(options[0]);

const [oldVersionType, newVersionType] = selectedVersions.split('_') as [Version, Version];
const [oldVersionType, newVersionType] = getVersionsForComparison(
selectedOption,
fieldDiff.has_base_version
);

const oldFieldValue = pickFieldValueForVersion(oldVersionType, fieldDiff, resolvedValue);

const newFieldValue = pickFieldValueForVersion(newVersionType, fieldDiff, resolvedValue);

const subfieldChanges = getSubfieldChanges(fieldName, oldFieldValue, newFieldValue);

/* Change selected option to "My changes" if user has modified resolved value */
const prevResolvedValue = usePrevious(resolvedValue);
useEffect(() => {
if (
selectedOption !== VersionsPickerOptionEnum.MyChanges &&
!isEqual(prevResolvedValue, resolvedValue)
) {
setSelectedOption(VersionsPickerOptionEnum.MyChanges);
}
}, [hasResolvedValueDifferentFromSuggested, selectedOption, prevResolvedValue, resolvedValue]);

return (
<>
<FieldUpgradeSideHeader>
Expand All @@ -42,15 +63,16 @@ export function FieldComparisonSide(): JSX.Element {
<EuiTitle size="xxs">
<h3>
{i18n.TITLE}
<ComparisonSideHelpInfo />
<ComparisonSideHelpInfo options={options} />
</h3>
</EuiTitle>
</EuiFlexItem>
<EuiFlexItem>
<VersionsPicker
hasBaseVersion={fieldDiff.has_base_version}
selectedVersions={selectedVersions}
onChange={setSelectedVersions}
options={options}
selectedOption={selectedOption}
onChange={setSelectedOption}
hasResolvedValueDifferentFromSuggested={hasResolvedValueDifferentFromSuggested}
/>
</EuiFlexItem>
</EuiFlexGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/

import { i18n } from '@kbn/i18n';
import { FINAL_UPDATE } from '../field_final_side/components/translations';

export const TITLE = i18n.translate(
'xpack.securitySolution.detectionEngine.rules.upgradeRules.comparisonSide.title',
Expand All @@ -20,3 +21,75 @@ export const NO_CHANGES = i18n.translate(
defaultMessage: 'No changes',
}
);

export const UPDATE_FROM_ELASTIC_TITLE = i18n.translate(
'xpack.securitySolution.detectionEngine.rules.upgradeRules.versions.updateFromElasticTitle',
{
defaultMessage: 'Update from Elastic',
}
);

export const UPDATE_FROM_ELASTIC_EXPLANATION = i18n.translate(
'xpack.securitySolution.detectionEngine.rules.upgradeRules.versions.updateFromElasticExplanation',
{
defaultMessage: 'view the changes in Elastic’s latest update',
}
);

export const MY_CHANGES_TITLE = i18n.translate(
'xpack.securitySolution.detectionEngine.rules.upgradeRules.versions.myChangesTitle',
{
defaultMessage: 'My changes',
}
);

export const MY_CHANGES_EXPLANATION = i18n.translate(
'xpack.securitySolution.detectionEngine.rules.upgradeRules.versions.myChangesExplanation',
{
defaultMessage: `view what you have changed in your installed rule and in the {finalUpdateSectionLabel} section`,
values: {
finalUpdateSectionLabel: FINAL_UPDATE,
},
}
);

export const MY_CHANGES_IN_RULE_UPGRADE_WORKFLOW_EXPLANATION = i18n.translate(
'xpack.securitySolution.detectionEngine.rules.upgradeRules.versions.myChangesFinalUpdateOnlyExplanation',
{
defaultMessage: `view the changes you made in the {finalUpdateSectionLabel} section`,
values: {
finalUpdateSectionLabel: FINAL_UPDATE,
},
}
);

export const MERGED_CHANGES_TITLE = i18n.translate(
'xpack.securitySolution.detectionEngine.rules.upgradeRules.versions.mergedChangesTitle',
{
defaultMessage: 'My changes merged with Elastic’s',
}
);

export const MERGED_CHANGES_EXPLANATION = i18n.translate(
'xpack.securitySolution.detectionEngine.rules.upgradeRules.versions.mergedChangesExplanation',
{
defaultMessage: 'view an update suggestion that combines your changes with Elastic’s',
}
);

export const MY_ORIGINAL_CHANGES_TITLE = i18n.translate(
'xpack.securitySolution.detectionEngine.rules.upgradeRules.versions.myOriginalChangesTitle',
{
defaultMessage: 'My original changes',
}
);

export const MY_ORIGINAL_CHANGES_EXPLANATION = i18n.translate(
'xpack.securitySolution.detectionEngine.rules.upgradeRules.versions.myCustomizationExplanation',
{
defaultMessage: `view what you have changed in your installed rule. Doesn’t include changes made in the {finalUpdateSectionLabel} section.`,
values: {
finalUpdateSectionLabel: FINAL_UPDATE,
},
}
);
Loading
Loading