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

Threats Data Views: Use Context #40749

Draft
wants to merge 2 commits into
base: add/threats-data-views/controlled-fields
Choose a base branch
from
Draft
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
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { SortDirection, SupportedLayouts } from '@wordpress/dataviews';
import { __ } from '@wordpress/i18n';
import {
code as fileIcon,
Expand Down Expand Up @@ -81,3 +82,43 @@ export const THREAT_FIELDS = [
export const THREAT_ACTION_FIX = 'fix';
export const THREAT_ACTION_IGNORE = 'ignore';
export const THREAT_ACTION_UNIGNORE = 'unignore';

const BASE_VIEW = {
sort: {
field: 'severity',
direction: 'desc' as SortDirection,
},
search: '',
filters: [],
page: 1,
perPage: 20,
};

/**
* DataView default layouts.
*
* This property provides layout information about the view types that are active. If empty, enables all layout types (see “Layout Types”) with empty layout data.
*
* @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-dataviews/#defaultlayouts-record-string-view
*/
export const DEFAULT_LAYOUTS: SupportedLayouts = {
table: {
...BASE_VIEW,
fields: [ THREAT_FIELD_SEVERITY, THREAT_FIELD_FIRST_DETECTED, THREAT_FIELD_AUTO_FIX ],
titleField: THREAT_FIELD_TITLE,
descriptionField: THREAT_FIELD_DESCRIPTION,
showMedia: false,
},
list: {
...BASE_VIEW,
fields: [
THREAT_FIELD_SEVERITY,
THREAT_FIELD_TYPE,
THREAT_FIELD_EXTENSION,
THREAT_FIELD_SIGNATURE,
],
titleField: THREAT_FIELD_TITLE,
mediaField: THREAT_FIELD_ICON,
showMedia: true,
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Threat } from '@automattic/jetpack-scan';
import { View } from '@wordpress/dataviews';
import { createContext } from 'react';
import { DEFAULT_LAYOUTS } from './constants';

export interface ThreatsDataViewsContextInterface {
view: View;
setView: ( view: View ) => void;
onChangeView?: ( view: View ) => void;
data: Threat[];
}

const ThreatsDataViewsContext = createContext< ThreatsDataViewsContextInterface >( {
view: {
type: 'table',
...DEFAULT_LAYOUTS.table,
},
setView: () => {},
onChangeView: () => {},
data: [],
} );

export default ThreatsDataViewsContext;
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,19 @@ import {
type Action,
type ActionButton,
type Filter,
type SortDirection,
type SupportedLayouts,
type View,
DataViews,
filterSortAndPaginate,
} from '@wordpress/dataviews';
import { __ } from '@wordpress/i18n';
import { useCallback, useMemo, useState } from 'react';
import {
DEFAULT_LAYOUTS,
THREAT_ACTION_FIX,
THREAT_ACTION_IGNORE,
THREAT_ACTION_UNIGNORE,
THREAT_FIELD_AUTO_FIX,
THREAT_FIELD_DESCRIPTION,
THREAT_FIELD_EXTENSION,
THREAT_FIELD_FIRST_DETECTED,
THREAT_FIELD_ICON,
THREAT_FIELD_SEVERITY,
THREAT_FIELD_SIGNATURE,
THREAT_FIELD_TITLE,
THREAT_FIELD_TYPE,
} from './constants';
import ThreatsDataViewsContext from './context';
import ThreatsStatusToggleGroupControl from './threats-status-toggle-group-control';
import useControlledFields from './use-controlled-fields';

Expand Down Expand Up @@ -68,56 +59,22 @@ export default function ThreatsDataViews( {
onIgnoreThreats?: ActionButton< Threat >[ 'callback' ];
onUnignoreThreats?: ActionButton< Threat >[ 'callback' ];
} ): JSX.Element {
const baseView = {
sort: {
field: 'severity',
direction: 'desc' as SortDirection,
},
search: '',
filters: filters || [],
page: 1,
perPage: 20,
};

/**
* DataView default layouts.
*
* This property provides layout information about the view types that are active. If empty, enables all layout types (see “Layout Types”) with empty layout data.
*
* @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-dataviews/#defaultlayouts-record-string-view
*/
const defaultLayouts: SupportedLayouts = {
table: {
...baseView,
fields: [ THREAT_FIELD_SEVERITY, THREAT_FIELD_FIRST_DETECTED, THREAT_FIELD_AUTO_FIX ],
titleField: THREAT_FIELD_TITLE,
descriptionField: THREAT_FIELD_DESCRIPTION,
showMedia: false,
},
list: {
...baseView,
fields: [
THREAT_FIELD_SEVERITY,
THREAT_FIELD_TYPE,
THREAT_FIELD_EXTENSION,
THREAT_FIELD_SIGNATURE,
],
titleField: THREAT_FIELD_TITLE,
mediaField: THREAT_FIELD_ICON,
showMedia: true,
},
};

/**
* DataView view object - configures how the dataset is visible to the user.
*
* @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-dataviews/#view-object
*/
const [ view, setView ] = useState< View >( {
type: 'table',
...defaultLayouts.table,
...DEFAULT_LAYOUTS.table,
filters: filters ?? DEFAULT_LAYOUTS.table.filters,
} );

/**
* DataView fields.
*
* @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-dataviews/#fields-api
*/
const { fields, controlFields } = useControlledFields( {
data,
view,
Expand Down Expand Up @@ -222,23 +179,19 @@ export default function ThreatsDataViews( {
const getItemId = useCallback( ( item: Threat ) => item.id.toString(), [] );

return (
<DataViews
actions={ actions }
data={ processedData }
defaultLayouts={ defaultLayouts }
fields={ fields }
getItemId={ getItemId }
onChangeSelection={ onChangeSelection }
onChangeView={ onChangeView }
paginationInfo={ paginationInfo }
view={ view }
header={
<ThreatsStatusToggleGroupControl
data={ data }
view={ view }
onChangeView={ onChangeView }
/>
}
/>
<ThreatsDataViewsContext.Provider value={ { data, view, setView, onChangeView } }>
<DataViews
actions={ actions }
data={ processedData }
defaultLayouts={ DEFAULT_LAYOUTS }
fields={ fields }
getItemId={ getItemId }
onChangeSelection={ onChangeSelection }
onChangeView={ onChangeView }
paginationInfo={ paginationInfo }
view={ view }
header={ <ThreatsStatusToggleGroupControl /> }
/>
</ThreatsDataViewsContext.Provider>
);
}
Original file line number Diff line number Diff line change
@@ -1,32 +1,25 @@
import { ThreatStatus, type Threat } from '@automattic/jetpack-scan';
import { ThreatStatus } from '@automattic/jetpack-scan';
import {
__experimentalToggleGroupControl as ToggleGroupControl, // eslint-disable-line @wordpress/no-unsafe-wp-apis
__experimentalToggleGroupControlOption as ToggleGroupControlOption, // eslint-disable-line @wordpress/no-unsafe-wp-apis
} from '@wordpress/components';
import { type View } from '@wordpress/dataviews';
import { useMemo, useCallback } from '@wordpress/element';
import { __, sprintf } from '@wordpress/i18n';
import { useContext } from 'react';
import ThreatsDataViewsContext from './context';
import styles from './styles.module.scss';

/**
* ToggleGroupControl component for filtering threats by status.
*
* @param {object} props - Component props.
* @param { Threat[]} props.data - Threats data.
* @param { View } props.view - The current view.
* @param { Function } props.onChangeView - Callback function to handle view changes.
*
* @return {JSX.Element|null} The component or null.
*/
export default function ThreatsStatusToggleGroupControl( {
data,
view,
onChangeView,
}: {
data: Threat[];
view: View;
onChangeView: ( newView: View ) => void;
} ): JSX.Element {
export default function ThreatsStatusToggleGroupControl(): JSX.Element {
/**
* Access the parent DataViews props via context.
*/
const { data, view, onChangeView } = useContext( ThreatsDataViewsContext );

/**
* Compute values from the provided threats data.
*
Expand Down
Loading