@automattic/jetpack-components 0.70.1 → 0.72.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/CHANGELOG.md +20 -1
  2. package/build/components/dot-pager/index.d.ts +14 -0
  3. package/build/components/dot-pager/index.js +52 -0
  4. package/build/components/number-control/index.js +1 -1
  5. package/build/components/split-button/index.js +2 -2
  6. package/build/components/swipeable/index.d.ts +12 -0
  7. package/build/components/swipeable/index.js +293 -0
  8. package/build/index.d.ts +2 -3
  9. package/build/index.js +2 -3
  10. package/components/dot-pager/README.md +20 -0
  11. package/components/dot-pager/index.tsx +147 -0
  12. package/components/dot-pager/style.scss +80 -0
  13. package/components/number-control/index.jsx +3 -1
  14. package/components/split-button/index.tsx +14 -12
  15. package/components/split-button/style.module.scss +5 -0
  16. package/components/swipeable/README.md +34 -0
  17. package/components/swipeable/index.tsx +425 -0
  18. package/components/swipeable/style.scss +34 -0
  19. package/index.ts +2 -3
  20. package/package.json +1 -3
  21. package/build/components/threat-fixer-button/index.d.ts +0 -17
  22. package/build/components/threat-fixer-button/index.js +0 -56
  23. package/build/components/threat-severity-badge/index.d.ts +0 -4
  24. package/build/components/threat-severity-badge/index.js +0 -13
  25. package/build/components/threats-data-views/constants.d.ts +0 -33
  26. package/build/components/threats-data-views/constants.js +0 -37
  27. package/build/components/threats-data-views/index.d.ts +0 -30
  28. package/build/components/threats-data-views/index.js +0 -413
  29. package/build/components/threats-data-views/threats-status-toggle-group-control.d.ts +0 -16
  30. package/build/components/threats-data-views/threats-status-toggle-group-control.js +0 -95
  31. package/components/threat-fixer-button/index.tsx +0 -101
  32. package/components/threat-fixer-button/styles.module.scss +0 -16
  33. package/components/threat-modal/fixer-state-notice.tsx +0 -63
  34. package/components/threat-modal/index.tsx +0 -109
  35. package/components/threat-modal/styles.module.scss +0 -81
  36. package/components/threat-modal/threat-actions.tsx +0 -93
  37. package/components/threat-modal/threat-fix-confirmation.tsx +0 -54
  38. package/components/threat-modal/threat-fix-details.tsx +0 -65
  39. package/components/threat-modal/threat-notice.tsx +0 -84
  40. package/components/threat-modal/threat-summary.tsx +0 -30
  41. package/components/threat-modal/threat-technical-details.tsx +0 -67
  42. package/components/threat-severity-badge/index.tsx +0 -26
  43. package/components/threat-severity-badge/styles.module.scss +0 -27
  44. package/components/threats-data-views/constants.ts +0 -49
  45. package/components/threats-data-views/index.tsx +0 -534
  46. package/components/threats-data-views/styles.module.scss +0 -40
  47. package/components/threats-data-views/threats-status-toggle-group-control.tsx +0 -158
@@ -1,17 +0,0 @@
1
- /// <reference types="react" resolution-mode="require"/>
2
- import { type Threat } from '@automattic/jetpack-scan';
3
- /**
4
- * Threat Fixer Button component.
5
- *
6
- * @param {object} props - Component props.
7
- * @param {object} props.threat - The threat.
8
- * @param {Function} props.onClick - The onClick function.
9
- * @param {string} props.className - The className.
10
- *
11
- * @return {JSX.Element} The component.
12
- */
13
- export default function ThreatFixerButton({ threat, className, onClick, }: {
14
- threat: Threat;
15
- onClick: (items: Threat[]) => void;
16
- className?: string;
17
- }): JSX.Element;
@@ -1,56 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { getFixerState, getFixerAction, getFixerDescription, } from '@automattic/jetpack-scan';
3
- import { Tooltip } from '@wordpress/components';
4
- import { useCallback, useMemo } from '@wordpress/element';
5
- import { __ } from '@wordpress/i18n';
6
- import { Button } from '@automattic/jetpack-components';
7
- import styles from './styles.module.scss';
8
- /**
9
- * Threat Fixer Button component.
10
- *
11
- * @param {object} props - Component props.
12
- * @param {object} props.threat - The threat.
13
- * @param {Function} props.onClick - The onClick function.
14
- * @param {string} props.className - The className.
15
- *
16
- * @return {JSX.Element} The component.
17
- */
18
- export default function ThreatFixerButton({ threat, className, onClick, }) {
19
- const fixerState = useMemo(() => {
20
- return getFixerState(threat.fixer);
21
- }, [threat.fixer]);
22
- const tooltipText = useMemo(() => {
23
- if (!threat.fixable) {
24
- return null;
25
- }
26
- if (fixerState.error) {
27
- return __('An error occurred auto-fixing this threat.', 'jetpack-components');
28
- }
29
- if (fixerState.stale) {
30
- return __('The auto-fixer is taking longer than expected.', 'jetpack-components');
31
- }
32
- if (fixerState.inProgress) {
33
- return __('An auto-fixer is in progress.', 'jetpack-components');
34
- }
35
- return getFixerDescription(threat);
36
- }, [threat, fixerState]);
37
- const buttonText = useMemo(() => {
38
- if (!threat.fixable) {
39
- return null;
40
- }
41
- if (fixerState.error) {
42
- return __('Error', 'jetpack-components');
43
- }
44
- return getFixerAction(threat);
45
- }, [threat, fixerState.error]);
46
- const handleClick = useCallback((event) => {
47
- event.stopPropagation();
48
- onClick([threat]);
49
- }, [onClick, threat]);
50
- if (!threat.fixable) {
51
- return null;
52
- }
53
- return (_jsx("div", { children: _jsx(Tooltip, { className: styles.tooltip, text: tooltipText, children: _jsx(Button, { size: "small", weight: "regular", variant: "secondary", onClick: handleClick, children: buttonText, className: className, isLoading: fixerState.inProgress, isDestructive: (threat.fixable && threat.fixable.fixer === 'delete') ||
54
- fixerState.error ||
55
- fixerState.stale, style: { minWidth: '72px' } }) }) }));
56
- }
@@ -1,4 +0,0 @@
1
- declare const ThreatSeverityBadge: ({ severity }: {
2
- severity: any;
3
- }) => import("react/jsx-runtime").JSX.Element;
4
- export default ThreatSeverityBadge;
@@ -1,13 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { _x } from '@wordpress/i18n';
3
- import Badge from '../badge/index.js';
4
- const ThreatSeverityBadge = ({ severity }) => {
5
- if (severity >= 5) {
6
- return (_jsx(Badge, { variant: "danger", children: _x('Critical', 'Severity label for issues rated 5 or higher.', 'jetpack-components') }));
7
- }
8
- if (severity >= 3 && severity < 5) {
9
- return (_jsx(Badge, { variant: "warning", children: _x('High', 'Severity label for issues rated between 3 and 5.', 'jetpack-components') }));
10
- }
11
- return (_jsx(Badge, { children: _x('Low', 'Severity label for issues rated below 3.', 'jetpack-components') }));
12
- };
13
- export default ThreatSeverityBadge;
@@ -1,33 +0,0 @@
1
- export declare const THREAT_STATUSES: {
2
- value: string;
3
- label: string;
4
- variant?: 'success' | 'warning';
5
- }[];
6
- export declare const THREAT_TYPES: {
7
- value: string;
8
- label: string;
9
- }[];
10
- export declare const THREAT_ICONS: {
11
- plugins: any;
12
- themes: any;
13
- core: any;
14
- file: any;
15
- default: any;
16
- };
17
- export declare const THREAT_FIELD_THREAT = "threat";
18
- export declare const THREAT_FIELD_TITLE = "title";
19
- export declare const THREAT_FIELD_DESCRIPTION = "description";
20
- export declare const THREAT_FIELD_ICON = "icon";
21
- export declare const THREAT_FIELD_STATUS = "status";
22
- export declare const THREAT_FIELD_TYPE = "type";
23
- export declare const THREAT_FIELD_EXTENSION = "extension";
24
- export declare const THREAT_FIELD_PLUGIN = "plugin";
25
- export declare const THREAT_FIELD_THEME = "theme";
26
- export declare const THREAT_FIELD_SEVERITY = "severity";
27
- export declare const THREAT_FIELD_SIGNATURE = "signature";
28
- export declare const THREAT_FIELD_FIRST_DETECTED = "first-detected";
29
- export declare const THREAT_FIELD_FIXED_ON = "fixed-on";
30
- export declare const THREAT_FIELD_AUTO_FIX = "auto-fix";
31
- export declare const THREAT_ACTION_FIX = "fix";
32
- export declare const THREAT_ACTION_IGNORE = "ignore";
33
- export declare const THREAT_ACTION_UNIGNORE = "unignore";
@@ -1,37 +0,0 @@
1
- import { __ } from '@wordpress/i18n';
2
- import { code as fileIcon, color as themeIcon, plugins as pluginIcon, shield as shieldIcon, wordpress as coreIcon, } from '@wordpress/icons';
3
- export const THREAT_STATUSES = [
4
- { value: 'current', label: __('Active', 'jetpack-components'), variant: 'warning' },
5
- { value: 'fixed', label: __('Fixed', 'jetpack-components'), variant: 'success' },
6
- { value: 'ignored', label: __('Ignored', 'jetpack-components') },
7
- ];
8
- export const THREAT_TYPES = [
9
- { value: 'plugins', label: __('Plugin', 'jetpack-components') },
10
- { value: 'themes', label: __('Theme', 'jetpack-components') },
11
- { value: 'core', label: __('WordPress', 'jetpack-components') },
12
- { value: 'file', label: __('File', 'jetpack-components') },
13
- ];
14
- export const THREAT_ICONS = {
15
- plugins: pluginIcon,
16
- themes: themeIcon,
17
- core: coreIcon,
18
- file: fileIcon,
19
- default: shieldIcon,
20
- };
21
- export const THREAT_FIELD_THREAT = 'threat';
22
- export const THREAT_FIELD_TITLE = 'title';
23
- export const THREAT_FIELD_DESCRIPTION = 'description';
24
- export const THREAT_FIELD_ICON = 'icon';
25
- export const THREAT_FIELD_STATUS = 'status';
26
- export const THREAT_FIELD_TYPE = 'type';
27
- export const THREAT_FIELD_EXTENSION = 'extension';
28
- export const THREAT_FIELD_PLUGIN = 'plugin';
29
- export const THREAT_FIELD_THEME = 'theme';
30
- export const THREAT_FIELD_SEVERITY = 'severity';
31
- export const THREAT_FIELD_SIGNATURE = 'signature';
32
- export const THREAT_FIELD_FIRST_DETECTED = 'first-detected';
33
- export const THREAT_FIELD_FIXED_ON = 'fixed-on';
34
- export const THREAT_FIELD_AUTO_FIX = 'auto-fix';
35
- export const THREAT_ACTION_FIX = 'fix';
36
- export const THREAT_ACTION_IGNORE = 'ignore';
37
- export const THREAT_ACTION_UNIGNORE = 'unignore';
@@ -1,30 +0,0 @@
1
- /// <reference types="react" resolution-mode="require"/>
2
- import { type Threat } from '@automattic/jetpack-scan';
3
- import { type ActionButton, type Filter } from '@wordpress/dataviews';
4
- /**
5
- * DataViews component for displaying security threats.
6
- *
7
- * @param {object} props - Component props.
8
- * @param {Array} props.data - Threats data.
9
- * @param {Array} props.filters - Initial DataView filters.
10
- * @param {Function} props.onChangeSelection - Callback function run when an item is selected.
11
- * @param {Function} props.onFixThreats - Threat fix action callback.
12
- * @param {Function} props.onIgnoreThreats - Threat ignore action callback.
13
- * @param {Function} props.onUnignoreThreats - Threat unignore action callback.
14
- * @param {Function} props.isThreatEligibleForFix - Function to determine if a threat is eligible for fixing.
15
- * @param {Function} props.isThreatEligibleForIgnore - Function to determine if a threat is eligible for ignoring.
16
- * @param {Function} props.isThreatEligibleForUnignore - Function to determine if a threat is eligible for unignoring.
17
- *
18
- * @return {JSX.Element} The ThreatsDataViews component.
19
- */
20
- export default function ThreatsDataViews({ data, filters, onChangeSelection, isThreatEligibleForFix, isThreatEligibleForIgnore, isThreatEligibleForUnignore, onFixThreats, onIgnoreThreats, onUnignoreThreats, }: {
21
- data: Threat[];
22
- filters?: Filter[];
23
- onChangeSelection?: (selectedItemIds: string[]) => void;
24
- isThreatEligibleForFix?: (threat: Threat) => boolean;
25
- isThreatEligibleForIgnore?: (threat: Threat) => boolean;
26
- isThreatEligibleForUnignore?: (threat: Threat) => boolean;
27
- onFixThreats?: (threats: Threat[]) => void;
28
- onIgnoreThreats?: ActionButton<Threat>['callback'];
29
- onUnignoreThreats?: ActionButton<Threat>['callback'];
30
- }): JSX.Element;
@@ -1,413 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { getThreatType } from '@automattic/jetpack-scan';
3
- import { DataViews, filterSortAndPaginate, } from '@wordpress/dataviews';
4
- import { dateI18n } from '@wordpress/date';
5
- import { __ } from '@wordpress/i18n';
6
- import { Icon } from '@wordpress/icons';
7
- import { useCallback, useMemo, useState } from 'react';
8
- import Badge from '../badge/index.js';
9
- import ThreatFixerButton from '../threat-fixer-button/index.js';
10
- import ThreatSeverityBadge from '../threat-severity-badge/index.js';
11
- import { 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_FIXED_ON, THREAT_FIELD_ICON, THREAT_FIELD_PLUGIN, THREAT_FIELD_SEVERITY, THREAT_FIELD_SIGNATURE, THREAT_FIELD_STATUS, THREAT_FIELD_THEME, THREAT_FIELD_TITLE, THREAT_FIELD_TYPE, THREAT_ICONS, THREAT_STATUSES, THREAT_TYPES, } from './constants.js';
12
- import styles from './styles.module.scss';
13
- import ThreatsStatusToggleGroupControl from './threats-status-toggle-group-control.js';
14
- /**
15
- * DataViews component for displaying security threats.
16
- *
17
- * @param {object} props - Component props.
18
- * @param {Array} props.data - Threats data.
19
- * @param {Array} props.filters - Initial DataView filters.
20
- * @param {Function} props.onChangeSelection - Callback function run when an item is selected.
21
- * @param {Function} props.onFixThreats - Threat fix action callback.
22
- * @param {Function} props.onIgnoreThreats - Threat ignore action callback.
23
- * @param {Function} props.onUnignoreThreats - Threat unignore action callback.
24
- * @param {Function} props.isThreatEligibleForFix - Function to determine if a threat is eligible for fixing.
25
- * @param {Function} props.isThreatEligibleForIgnore - Function to determine if a threat is eligible for ignoring.
26
- * @param {Function} props.isThreatEligibleForUnignore - Function to determine if a threat is eligible for unignoring.
27
- *
28
- * @return {JSX.Element} The ThreatsDataViews component.
29
- */
30
- export default function ThreatsDataViews({ data, filters, onChangeSelection, isThreatEligibleForFix, isThreatEligibleForIgnore, isThreatEligibleForUnignore, onFixThreats, onIgnoreThreats, onUnignoreThreats, }) {
31
- const baseView = {
32
- sort: {
33
- field: 'severity',
34
- direction: 'desc',
35
- },
36
- search: '',
37
- filters: filters || [],
38
- page: 1,
39
- perPage: 20,
40
- };
41
- /**
42
- * DataView default layouts.
43
- *
44
- * 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.
45
- *
46
- * @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-dataviews/#defaultlayouts-record-string-view
47
- */
48
- const defaultLayouts = {
49
- table: {
50
- ...baseView,
51
- fields: [THREAT_FIELD_SEVERITY, THREAT_FIELD_TYPE, THREAT_FIELD_AUTO_FIX],
52
- titleField: THREAT_FIELD_TITLE,
53
- descriptionField: THREAT_FIELD_DESCRIPTION,
54
- showMedia: false,
55
- },
56
- list: {
57
- ...baseView,
58
- fields: [
59
- THREAT_FIELD_SEVERITY,
60
- THREAT_FIELD_TYPE,
61
- THREAT_FIELD_EXTENSION,
62
- THREAT_FIELD_SIGNATURE,
63
- ],
64
- titleField: THREAT_FIELD_TITLE,
65
- mediaField: THREAT_FIELD_ICON,
66
- showMedia: true,
67
- },
68
- };
69
- /**
70
- * DataView view object - configures how the dataset is visible to the user.
71
- *
72
- * @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-dataviews/#view-object
73
- */
74
- const [view, setView] = useState({
75
- type: 'table',
76
- ...defaultLayouts.table,
77
- });
78
- /**
79
- * Compute values from the provided threats data.
80
- *
81
- * @member {object[]} themes - List of unique themes included in the threats data.
82
- * @member {object[]} plugins - plugins included in the threats data.
83
- * @member {object[]} signatures - List of unique threat signatures.
84
- * @member {string[]} dataFields - List of unique fields.
85
- */
86
- const { themes, plugins, signatures, dataFields, } = useMemo(() => {
87
- return data.reduce((acc, threat) => {
88
- // Extensions (Themes and Plugins)
89
- if (threat.extension) {
90
- switch (threat.extension.type) {
91
- case 'themes':
92
- if (!acc.themes.find(({ value }) => value === threat.extension.slug)) {
93
- acc.themes.push({ value: threat.extension.slug, label: threat.extension.name });
94
- }
95
- break;
96
- case 'plugins':
97
- if (!acc.plugins.find(({ value }) => value === threat.extension.slug)) {
98
- acc.plugins.push({ value: threat.extension.slug, label: threat.extension.name });
99
- }
100
- break;
101
- default:
102
- break;
103
- }
104
- }
105
- // Signatures
106
- if (threat.signature) {
107
- if (!acc.signatures.find(({ value }) => value === threat.signature)) {
108
- acc.signatures.push({ value: threat.signature, label: threat.signature });
109
- }
110
- }
111
- // Fields
112
- const fields = Object.keys(threat);
113
- fields.forEach(field => {
114
- if (!acc.dataFields.includes(field) &&
115
- threat[field] !== null &&
116
- threat[field] !== undefined) {
117
- acc.dataFields.push(field);
118
- }
119
- });
120
- return acc;
121
- }, {
122
- themes: [],
123
- plugins: [],
124
- signatures: [],
125
- dataFields: [],
126
- });
127
- }, [data]);
128
- /**
129
- * DataView fields - describes the visible items for each record in the dataset.
130
- *
131
- * @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-dataviews/#fields-object
132
- */
133
- const fields = useMemo(() => {
134
- const result = [
135
- {
136
- id: THREAT_FIELD_TITLE,
137
- label: __('Threat', 'jetpack-components'),
138
- enableGlobalSearch: true,
139
- enableHiding: false,
140
- render: ({ item }) => (_jsx("div", { className: styles.threat__title, children: item.title })),
141
- },
142
- {
143
- id: THREAT_FIELD_DESCRIPTION,
144
- label: __('Description', 'jetpack-components'),
145
- enableGlobalSearch: true,
146
- enableHiding: false,
147
- render: ({ item }) => (_jsx("div", { className: styles.threat__description, children: item.description })),
148
- },
149
- {
150
- id: THREAT_FIELD_ICON,
151
- label: __('Icon', 'jetpack-components'),
152
- enableHiding: false,
153
- getValue({ item }) {
154
- return getThreatType(item);
155
- },
156
- render({ item }) {
157
- return (_jsx("div", { className: styles.threat__media, children: _jsx(Icon, { icon: THREAT_ICONS[getThreatType(item)], size: 20 }) }));
158
- },
159
- },
160
- {
161
- id: THREAT_FIELD_STATUS,
162
- label: __('Status', 'jetpack-components'),
163
- elements: THREAT_STATUSES,
164
- getValue({ item }) {
165
- if (!item.status) {
166
- return 'current';
167
- }
168
- return (THREAT_STATUSES.find(({ value }) => value === item.status)?.value ?? item.status);
169
- },
170
- render({ item }) {
171
- if (item.status) {
172
- const status = THREAT_STATUSES.find(({ value }) => value === item.status);
173
- if (status) {
174
- return _jsx(Badge, { variant: status?.variant, children: status.label });
175
- }
176
- }
177
- return _jsx(Badge, { variant: "warning", children: __('Active', 'jetpack-components') });
178
- },
179
- },
180
- {
181
- id: THREAT_FIELD_TYPE,
182
- label: __('Type', 'jetpack-components'),
183
- elements: THREAT_TYPES,
184
- getValue({ item }) {
185
- switch (getThreatType(item)) {
186
- case 'core':
187
- return __('WordPress', 'jetpack-components');
188
- case 'plugins':
189
- return __('Plugin', 'jetpack-components');
190
- case 'themes':
191
- return __('Theme', 'jetpack-components');
192
- case 'file':
193
- return __('File', 'jetpack-components');
194
- default:
195
- return __('Unknown', 'jetpack-components');
196
- }
197
- },
198
- },
199
- {
200
- id: THREAT_FIELD_EXTENSION,
201
- label: __('Extension', 'jetpack-components'),
202
- enableGlobalSearch: true,
203
- enableHiding: true,
204
- getValue({ item }) {
205
- return item.extension ? item.extension.slug : '';
206
- },
207
- render({ item }) {
208
- return item.extension ? item.extension.name : '';
209
- },
210
- },
211
- {
212
- id: THREAT_FIELD_PLUGIN,
213
- label: __('Plugin', 'jetpack-components'),
214
- enableGlobalSearch: true,
215
- enableHiding: false,
216
- elements: plugins,
217
- getValue({ item }) {
218
- return item.extension ? item.extension.slug : '';
219
- },
220
- },
221
- {
222
- id: THREAT_FIELD_THEME,
223
- label: __('Theme', 'jetpack-components'),
224
- enableGlobalSearch: true,
225
- enableHiding: false,
226
- elements: themes,
227
- getValue({ item }) {
228
- return item.extension ? item.extension.slug : '';
229
- },
230
- },
231
- ...(dataFields.includes('severity')
232
- ? [
233
- {
234
- id: THREAT_FIELD_SEVERITY,
235
- label: __('Severity', 'jetpack-components'),
236
- type: 'integer',
237
- getValue({ item }) {
238
- return item.severity ?? 0;
239
- },
240
- render({ item }) {
241
- return _jsx(ThreatSeverityBadge, { severity: item.severity });
242
- },
243
- },
244
- ]
245
- : []),
246
- ...(dataFields.includes('signature')
247
- ? [
248
- {
249
- id: THREAT_FIELD_SIGNATURE,
250
- label: __('Signature', 'jetpack-components'),
251
- elements: signatures,
252
- enableGlobalSearch: true,
253
- getValue({ item }) {
254
- return item.signature || '';
255
- },
256
- },
257
- ]
258
- : []),
259
- ...(dataFields.includes('firstDetected')
260
- ? [
261
- {
262
- id: THREAT_FIELD_FIRST_DETECTED,
263
- label: __('First Detected', 'jetpack-components'),
264
- type: 'datetime',
265
- getValue({ item }) {
266
- return item.firstDetected ? new Date(item.firstDetected) : null;
267
- },
268
- render({ item }) {
269
- return item.firstDetected ? (_jsx("span", { className: styles.threat__firstDetected, children: dateI18n('F j Y', item.firstDetected, false) })) : null;
270
- },
271
- },
272
- ]
273
- : []),
274
- ...(dataFields.includes('fixedOn')
275
- ? [
276
- {
277
- id: THREAT_FIELD_FIXED_ON,
278
- label: __('Fixed On', 'jetpack-components'),
279
- type: 'datetime',
280
- getValue({ item }) {
281
- return item.fixedOn ? new Date(item.fixedOn) : null;
282
- },
283
- render({ item }) {
284
- return item.fixedOn ? (_jsx("span", { className: styles.threat__fixedOn, children: dateI18n('F j Y', item.fixedOn, false) })) : null;
285
- },
286
- },
287
- ]
288
- : []),
289
- ...(dataFields.includes('fixable')
290
- ? [
291
- {
292
- id: THREAT_FIELD_AUTO_FIX,
293
- label: __('Auto-fix', 'jetpack-components'),
294
- enableHiding: false,
295
- elements: [
296
- {
297
- value: 'yes',
298
- label: __('Yes', 'jetpack-components'),
299
- },
300
- {
301
- value: 'no',
302
- label: __('No', 'jetpack-components'),
303
- },
304
- ],
305
- getValue({ item }) {
306
- return item.fixable ? 'yes' : 'no';
307
- },
308
- render({ item }) {
309
- if (!item.fixable) {
310
- return null;
311
- }
312
- return _jsx(ThreatFixerButton, { threat: item, onClick: onFixThreats });
313
- },
314
- },
315
- ]
316
- : []),
317
- ];
318
- return result;
319
- }, [dataFields, plugins, themes, signatures, onFixThreats]);
320
- /**
321
- * DataView actions - collection of operations that can be performed upon each record.
322
- *
323
- * @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-dataviews/#actions-object
324
- */
325
- const actions = useMemo(() => {
326
- const result = [];
327
- if (dataFields.includes('fixable')) {
328
- result.push({
329
- id: THREAT_ACTION_FIX,
330
- label: __('Auto-fix', 'jetpack-components'),
331
- isPrimary: true,
332
- callback: onFixThreats,
333
- isEligible(item) {
334
- if (!onFixThreats) {
335
- return false;
336
- }
337
- if (isThreatEligibleForFix) {
338
- return isThreatEligibleForFix(item);
339
- }
340
- return !!item.fixable;
341
- },
342
- });
343
- }
344
- if (dataFields.includes('status')) {
345
- result.push({
346
- id: THREAT_ACTION_IGNORE,
347
- label: __('Ignore', 'jetpack-components'),
348
- isPrimary: true,
349
- isDestructive: true,
350
- callback: onIgnoreThreats,
351
- isEligible(item) {
352
- if (!onIgnoreThreats) {
353
- return false;
354
- }
355
- if (isThreatEligibleForIgnore) {
356
- return isThreatEligibleForIgnore(item);
357
- }
358
- return item.status === 'current';
359
- },
360
- });
361
- }
362
- if (dataFields.includes('status')) {
363
- result.push({
364
- id: THREAT_ACTION_UNIGNORE,
365
- label: __('Unignore', 'jetpack-components'),
366
- isPrimary: true,
367
- isDestructive: true,
368
- callback: onUnignoreThreats,
369
- isEligible(item) {
370
- if (!onUnignoreThreats) {
371
- return false;
372
- }
373
- if (isThreatEligibleForUnignore) {
374
- return isThreatEligibleForUnignore(item);
375
- }
376
- return item.status === 'ignored';
377
- },
378
- });
379
- }
380
- return result;
381
- }, [
382
- dataFields,
383
- onFixThreats,
384
- onIgnoreThreats,
385
- onUnignoreThreats,
386
- isThreatEligibleForFix,
387
- isThreatEligibleForIgnore,
388
- isThreatEligibleForUnignore,
389
- ]);
390
- /**
391
- * Apply the view settings (i.e. filters, sorting, pagination) to the dataset.
392
- *
393
- * @see https://github.com/WordPress/gutenberg/blob/trunk/packages/dataviews/src/filter-and-sort-data-view.ts
394
- */
395
- const { data: processedData, paginationInfo } = useMemo(() => {
396
- return filterSortAndPaginate(data, view, fields);
397
- }, [data, view, fields]);
398
- /**
399
- * Callback function to update the view state.
400
- *
401
- * @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-dataviews/#onchangeview-function
402
- */
403
- const onChangeView = useCallback((newView) => {
404
- setView(newView);
405
- }, []);
406
- /**
407
- * DataView getItemId function - returns the unique ID for each record in the dataset.
408
- *
409
- * @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-dataviews/#getitemid-function
410
- */
411
- const getItemId = useCallback((item) => item.id.toString(), []);
412
- return (_jsx(DataViews, { actions: actions, data: processedData, defaultLayouts: defaultLayouts, fields: fields, getItemId: getItemId, onChangeSelection: onChangeSelection, onChangeView: onChangeView, paginationInfo: paginationInfo, view: view, header: _jsx(ThreatsStatusToggleGroupControl, { data: data, view: view, onChangeView: onChangeView }) }));
413
- }
@@ -1,16 +0,0 @@
1
- /// <reference types="react" resolution-mode="require"/>
2
- import { type Threat } from '@automattic/jetpack-scan';
3
- import { type View } from '@wordpress/dataviews';
4
- /**
5
- * ToggleGroupControl component for filtering threats by status.
6
- * @param {object} props - Component props.
7
- * @param { Threat[]} props.data - Threats data.
8
- * @param { View } props.view - The current view.
9
- * @param { Function } props.onChangeView - Callback function to handle view changes.
10
- * @return {JSX.Element|null} The component or null.
11
- */
12
- export default function ThreatsStatusToggleGroupControl({ data, view, onChangeView, }: {
13
- data: Threat[];
14
- view: View;
15
- onChangeView: (newView: View) => void;
16
- }): JSX.Element;