From 56f41b1abc9d79a77987d99ac9d8c3b526d98ec7 Mon Sep 17 00:00:00 2001 From: Nate Weller Date: Thu, 14 Nov 2024 10:42:12 -0700 Subject: [PATCH 1/2] Init project branch From a1cbfc93427fa0891e5f55ccb676b484a367a150 Mon Sep 17 00:00:00 2001 From: Nate Weller Date: Thu, 26 Dec 2024 21:22:56 -0700 Subject: [PATCH 2/2] Threats Data Views: Use React Context --- .../threats-data-views/constants.ts | 41 ++++++++ .../components/threats-data-views/context.ts | 23 +++++ .../components/threats-data-views/index.tsx | 93 +++++-------------- .../threats-status-toggle-group-control.tsx | 25 ++--- 4 files changed, 96 insertions(+), 86 deletions(-) create mode 100644 projects/js-packages/components/components/threats-data-views/context.ts diff --git a/projects/js-packages/components/components/threats-data-views/constants.ts b/projects/js-packages/components/components/threats-data-views/constants.ts index 41e69f8be9558..2541b291a94cc 100644 --- a/projects/js-packages/components/components/threats-data-views/constants.ts +++ b/projects/js-packages/components/components/threats-data-views/constants.ts @@ -1,3 +1,4 @@ +import { SortDirection, SupportedLayouts } from '@wordpress/dataviews'; import { __ } from '@wordpress/i18n'; import { code as fileIcon, @@ -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, + }, +}; diff --git a/projects/js-packages/components/components/threats-data-views/context.ts b/projects/js-packages/components/components/threats-data-views/context.ts new file mode 100644 index 0000000000000..3faf53a92a12f --- /dev/null +++ b/projects/js-packages/components/components/threats-data-views/context.ts @@ -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; diff --git a/projects/js-packages/components/components/threats-data-views/index.tsx b/projects/js-packages/components/components/threats-data-views/index.tsx index 04e1341018ba0..4bba75f781ce0 100644 --- a/projects/js-packages/components/components/threats-data-views/index.tsx +++ b/projects/js-packages/components/components/threats-data-views/index.tsx @@ -3,8 +3,6 @@ import { type Action, type ActionButton, type Filter, - type SortDirection, - type SupportedLayouts, type View, DataViews, filterSortAndPaginate, @@ -12,19 +10,12 @@ import { 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'; @@ -68,46 +59,6 @@ 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. * @@ -115,9 +66,15 @@ export default function ThreatsDataViews( { */ 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, @@ -222,23 +179,19 @@ export default function ThreatsDataViews( { const getItemId = useCallback( ( item: Threat ) => item.id.toString(), [] ); return ( - - } - /> + + } + /> + ); } diff --git a/projects/js-packages/components/components/threats-data-views/threats-status-toggle-group-control.tsx b/projects/js-packages/components/components/threats-data-views/threats-status-toggle-group-control.tsx index f8642fcb1784c..a1c885abe82f9 100644 --- a/projects/js-packages/components/components/threats-data-views/threats-status-toggle-group-control.tsx +++ b/projects/js-packages/components/components/threats-data-views/threats-status-toggle-group-control.tsx @@ -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. *