Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
48 changes: 0 additions & 48 deletions oxlint-baseline.json
Original file line number Diff line number Diff line change
Expand Up @@ -2966,54 +2966,6 @@
"sourceLine": "const reportsReloadInterval = ({entities = []}: {entities: Report[]}) =>",
"fingerprint": "src/web/pages/reports/ReportListPage.tsx|typescript(no-useless-default-assignment)|Default value is useless because the property has type `Report[]` (not nullish). This default assignment will never be used.|44|const reportsReloadInterval = ({entities = []}: {entities: Report[]}) =>"
},
{
"filename": "src/web/pages/results/dashboard/DescriptionWordCloudDisplay.jsx",
"code": "eslint(no-class-assign)",
"message": "Unexpected re-assignment of class ResultsDescriptionWordCloudDisplay",
"location": {
"line": 38,
"column": 14,
"offset": 1431
},
"sourceLine": "export class ResultsDescriptionWordCloudDisplay extends React.Component {",
"fingerprint": "src/web/pages/results/dashboard/DescriptionWordCloudDisplay.jsx|eslint(no-class-assign)|Unexpected re-assignment of class ResultsDescriptionWordCloudDisplay|14|export class ResultsDescriptionWordCloudDisplay extends React.Component {"
},
{
"filename": "src/web/pages/results/dashboard/DescriptionWordCloudDisplay.jsx",
"code": "typescript(unbound-method)",
"message": "Avoid referencing unbound methods which may cause unintentional scoping of `this`.",
"location": {
"line": 91,
"column": 53,
"offset": 2885
},
"sourceLine": "isDefined(onFilterChanged) ? this.handleDataClick : undefined",
"fingerprint": "src/web/pages/results/dashboard/DescriptionWordCloudDisplay.jsx|typescript(unbound-method)|Avoid referencing unbound methods which may cause unintentional scoping of `this`.|53|isDefined(onFilterChanged) ? this.handleDataClick : undefined"
},
{
"filename": "src/web/pages/results/dashboard/WordCloudDisplay.jsx",
"code": "eslint(no-class-assign)",
"message": "Unexpected re-assignment of class ResultsWordCloudDisplay",
"location": {
"line": 38,
"column": 14,
"offset": 1420
},
"sourceLine": "export class ResultsWordCloudDisplay extends React.Component {",
"fingerprint": "src/web/pages/results/dashboard/WordCloudDisplay.jsx|eslint(no-class-assign)|Unexpected re-assignment of class ResultsWordCloudDisplay|14|export class ResultsWordCloudDisplay extends React.Component {"
},
{
"filename": "src/web/pages/results/dashboard/WordCloudDisplay.jsx",
"code": "typescript(unbound-method)",
"message": "Avoid referencing unbound methods which may cause unintentional scoping of `this`.",
"location": {
"line": 91,
"column": 53,
"offset": 2856
},
"sourceLine": "isDefined(onFilterChanged) ? this.handleDataClick : undefined",
"fingerprint": "src/web/pages/results/dashboard/WordCloudDisplay.jsx|typescript(unbound-method)|Avoid referencing unbound methods which may cause unintentional scoping of `this`.|53|isDefined(onFilterChanged) ? this.handleDataClick : undefined"
},
{
"filename": "src/web/pages/results/DetailsPage.jsx",
"code": "typescript(unbound-method)",
Expand Down
133 changes: 0 additions & 133 deletions src/web/pages/results/dashboard/DescriptionWordCloudDisplay.jsx

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,35 @@ import createDisplay from 'web/components/dashboard/display/createDisplay';
import CvssDisplay from 'web/components/dashboard/display/cvss/CvssDisplay';
import CvssTableDisplay from 'web/components/dashboard/display/cvss/CvssTableDisplay';
import {registerDisplay} from 'web/components/dashboard/registry';
import {ResultsSeverityLoader} from 'web/pages/results/dashboard/Loaders';
import {ResultsSeverityLoader} from 'web/pages/results/dashboard/ResultLoaders';

export const ResultsCvssDisplay = createDisplay({
loaderComponent: ResultsSeverityLoader,
displayComponent: CvssDisplay,
yLabel: _l('# of Results'),
title: ({data: tdata}) =>
_('Results by CVSS (Total: {{count}})', {count: tdata.total}),
displayComponent: props => (
<CvssDisplay
{...props}
title={({data}) =>
_('Results by CVSS (Total: {{count}})', {count: data.total})
}
yLabel={_('# of Results')}
/>
),
displayId: 'result-by-cvss',
displayName: 'ResultsCvssDisplay',
filtersFilter: RESULTS_FILTER_FILTER,
});

export const ResultsCvssTableDisplay = createDisplay({
loaderComponent: ResultsSeverityLoader,
displayComponent: CvssTableDisplay,
dataTitles: [_l('Severity'), _l('# of Results')],
title: ({data: tdata}) =>
_('Results by CVSS (Total: {{count}})', {count: tdata.total}),
displayComponent: props => (
<CvssTableDisplay
{...props}
dataTitles={[_('Severity'), _('# of Results')]}
title={({data}) =>
_('Results by CVSS (Total: {{count}})', {count: data.total})
}
/>
),
displayId: 'result-by-cvss-table',
displayName: 'ResultsCvssTableDisplay',
filtersFilter: RESULTS_FILTER_FILTER,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
/* SPDX-FileCopyrightText: 2024 Greenbone AG
*
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

import {_, _l} from 'gmp/locale/lang';
import {RESULTS_FILTER_FILTER} from 'gmp/models/filter';
import FilterTerm from 'gmp/models/filter/filter-term';
import QueryFilter from 'gmp/models/filter/query-filter';
import {parseFloat} from 'gmp/parser';
import {isDefined} from 'gmp/utils/identity';
import {isEmpty} from 'gmp/utils/string';
import WordCloudChart from 'web/components/chart/WordCloudChart';
import {type DashboardDisplayProps} from 'web/components/dashboard/DashboardView';
import createDisplay from 'web/components/dashboard/display/createDisplay';
import DataDisplay, {
type DataDisplayProps,
} from 'web/components/dashboard/display/DataDisplay';
import DataTableDisplay from 'web/components/dashboard/display/DataTableDisplay';
import useFilterSelection from 'web/components/dashboard/display/useFilterSelection';
import {randomColor} from 'web/components/dashboard/display/utils';
import {registerDisplay} from 'web/components/dashboard/registry';
import {
ResultsDescriptionWordCountLoader,
type ResultWordCloudData,
} from 'web/pages/results/dashboard/ResultLoaders';

interface TransformResultWordCountDataItem {
value: number;
label: string;
color: string;
filterValue: string;
}

type TransformResultWordCountData = TransformResultWordCountDataItem[];

type ResultWordCountDataDisplayProps = DataDisplayProps<
ResultWordCloudData,
TransformResultWordCountData
>;

type ResultWordCountDisplayProps = DashboardDisplayProps;

const transformWordCountData = (
data: ResultWordCloudData = {},
): TransformResultWordCountData => {
const {groups = []} = data;
const transformedData = groups.map(group => {
const {count, value} = group;
return {
value: parseFloat(count),
label: value,
color: randomColor(),
filterValue: value,
} as TransformResultWordCountDataItem;
});
return transformedData;
};

export const ResultsDescriptionWordCloudDisplay = ({
filter,
filterId,
showFilterSelection,
onFilterChanged,
onFilterIdChanged,
...props
}: ResultWordCountDisplayProps) => {
const {
filter: selectedFilter,
selectFilter,
filterSelectionDialog,
} = useFilterSelection({
filterId,
filtersFilter: RESULTS_FILTER_FILTER,
onFilterIdChanged,
});

const displayFilter = showFilterSelection ? selectedFilter : filter;

const handleDataClick = (filterValue: string) => {
if (!isDefined(onFilterChanged) || isEmpty(filterValue)) {
return;
}

const wordTerm = FilterTerm.fromString(`description~"${filterValue}"`);

if (isDefined(filter) && filter.hasTerm(wordTerm)) {
return;
}
const wordFilter = QueryFilter.fromTerm(wordTerm);

const newFilter = isDefined(displayFilter)
? displayFilter.and(wordFilter)
: wordFilter;

onFilterChanged(newFilter);
};

return (
<>
<ResultsDescriptionWordCountLoader filter={displayFilter}>
{loaderProps => (
<DataDisplay<
ResultWordCloudData,
ResultWordCountDataDisplayProps,
TransformResultWordCountData
>
{...props}
{...loaderProps}
dataTransform={transformWordCountData}
filter={displayFilter}
showToggleLegend={false}
title={() => _('Results Description Word Cloud')}
onSelectFilterClick={showFilterSelection ? selectFilter : undefined}
>
{({width, height, data, svgRef}) => (
<WordCloudChart
data={data}
height={height}
svgRef={svgRef}
width={width}
onDataClick={
isDefined(onFilterChanged) ? handleDataClick : undefined
}
/>
)}
</DataDisplay>
)}
</ResultsDescriptionWordCountLoader>
{filterSelectionDialog}
</>
);
};

ResultsDescriptionWordCloudDisplay.displayId = 'result-by-desc-words';

export const ResultsDescriptionWordCloudTableDisplay = createDisplay({
loaderComponent: ResultsDescriptionWordCountLoader,
displayComponent: props => (
<DataTableDisplay
{...props}
dataRow={row => [row.label, row.value]}
dataTitles={[_('Description'), _('Word Count')]}
dataTransform={transformWordCountData}
title={() => _('Results Description Word Cloud')}
/>
),
displayId: 'result-by-desc-words-table',
displayName: 'ResultsDescriptionWordCloudTableDisplay',
filtersFilter: RESULTS_FILTER_FILTER,
});

registerDisplay(
ResultsDescriptionWordCloudDisplay,
_l('Chart: Results Description Word Cloud'),
);

registerDisplay(
ResultsDescriptionWordCloudTableDisplay,
_l('Table: Results Description Word Cloud'),
);
Loading
Loading