diff --git a/.yarn/patches/@wordpress-dataviews-npm-0.4.1-2c01fa0792.patch b/.yarn/patches/@wordpress-dataviews-npm-0.4.1-2c01fa0792.patch deleted file mode 100644 index ac1aef83914985..00000000000000 --- a/.yarn/patches/@wordpress-dataviews-npm-0.4.1-2c01fa0792.patch +++ /dev/null @@ -1,87 +0,0 @@ -diff --git a/build/lock-unlock.js b/build/lock-unlock.js -index b1e3c1e3b950c7d3095876fdf32dc9d0094a8f7a..3885591aaed7c99d345b7428a57b9b7dcbb982dd 100644 ---- a/build/lock-unlock.js -+++ b/build/lock-unlock.js -@@ -1,7 +1,7 @@ - "use strict"; - - Object.defineProperty(exports, "__esModule", { -- value: true -+ value: true, - }); - exports.unlock = exports.lock = void 0; - var _privateApis = require("@wordpress/private-apis"); -@@ -9,10 +9,11 @@ var _privateApis = require("@wordpress/private-apis"); - * WordPress dependencies - */ - --const { -- lock, -- unlock --} = (0, _privateApis.__dangerousOptInToUnstableAPIsOnlyForCoreModules)('I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/dataviews'); -+const { lock, unlock } = (0, -+_privateApis.__dangerousOptInToUnstableAPIsOnlyForCoreModules)( -+ "I acknowledge private features are not for use in themes or plugins and doing so will break in the next version of WordPress.", -+ "@wordpress/dataviews" -+); - exports.unlock = unlock; - exports.lock = lock; - //# sourceMappingURL=lock-unlock.js.map -diff --git a/build/lock-unlock.js.map b/build/lock-unlock.js.map -index b20c8e5e5cc50b108035dbfb4c765b354835476a..3edcce8eed204c1da1a55175bb617fb66c89d8a9 100644 ---- a/build/lock-unlock.js.map -+++ b/build/lock-unlock.js.map -@@ -1 +1 @@ --{"version":3,"names":["_privateApis","require","lock","unlock","__dangerousOptInToUnstableAPIsOnlyForCoreModules","exports"],"sources":["@wordpress/dataviews/src/lock-unlock.js"],"sourcesContent":["/**\n * WordPress dependencies\n */\nimport { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/private-apis';\n\nexport const { lock, unlock } =\n\t__dangerousOptInToUnstableAPIsOnlyForCoreModules(\n\t\t'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.',\n\t\t'@wordpress/dataviews'\n\t);\n"],"mappings":";;;;;;AAGA,IAAAA,YAAA,GAAAC,OAAA;AAHA;AACA;AACA;;AAGO,MAAM;EAAEC,IAAI;EAAEC;AAAO,CAAC,GAC5B,IAAAC,6DAAgD,EAC/C,iHAAiH,EACjH,sBACD,CAAC;AAACC,OAAA,CAAAF,MAAA,GAAAA,MAAA;AAAAE,OAAA,CAAAH,IAAA,GAAAA,IAAA"} -\ No newline at end of file -+{"version":3,"names":["_privateApis","require","lock","unlock","__dangerousOptInToUnstableAPIsOnlyForCoreModules","exports"],"sources":["@wordpress/dataviews/src/lock-unlock.js"],"sourcesContent":["/**\n * WordPress dependencies\n */\nimport { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/private-apis';\n\nexport const { lock, unlock } =\n\t__dangerousOptInToUnstableAPIsOnlyForCoreModules(\n\t\t'I acknowledge private features are not for use in themes or plugins and doing so will break in the next version of WordPress.',\n\t\t'@wordpress/dataviews'\n\t);\n"],"mappings":";;;;;;AAGA,IAAAA,YAAA,GAAAC,OAAA;AAHA;AACA;AACA;;AAGO,MAAM;EAAEC,IAAI;EAAEC;AAAO,CAAC,GAC5B,IAAAC,6DAAgD,EAC/C,iHAAiH,EACjH,sBACD,CAAC;AAACC,OAAA,CAAAF,MAAA,GAAAA,MAAA;AAAAE,OAAA,CAAAH,IAAA,GAAAA,IAAA"} -\ No newline at end of file -diff --git a/build-module/lock-unlock.js b/build-module/lock-unlock.js -index 79b912f8d2976acba70c34235d856368bf906425..0c778415d2bcf2ee21fab94d5518d123730c6623 100644 ---- a/build-module/lock-unlock.js -+++ b/build-module/lock-unlock.js -@@ -1,9 +1,10 @@ - /** - * WordPress dependencies - */ --import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/private-apis'; --export const { -- lock, -- unlock --} = __dangerousOptInToUnstableAPIsOnlyForCoreModules('I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/dataviews'); -+import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from "@wordpress/private-apis"; -+export const { lock, unlock } = -+ __dangerousOptInToUnstableAPIsOnlyForCoreModules( -+ "I acknowledge private features are not for use in themes or plugins and doing so will break in the next version of WordPress.", -+ "@wordpress/dataviews" -+ ); - //# sourceMappingURL=lock-unlock.js.map -diff --git a/build-module/lock-unlock.js.map b/build-module/lock-unlock.js.map -index 36173786489d0182174357e2b57e4e3351f50055..28dc0b6ae24f362442a98877134784a19bc2fc7f 100644 ---- a/build-module/lock-unlock.js.map -+++ b/build-module/lock-unlock.js.map -@@ -1 +1 @@ --{"version":3,"names":["__dangerousOptInToUnstableAPIsOnlyForCoreModules","lock","unlock"],"sources":["@wordpress/dataviews/src/lock-unlock.js"],"sourcesContent":["/**\n * WordPress dependencies\n */\nimport { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/private-apis';\n\nexport const { lock, unlock } =\n\t__dangerousOptInToUnstableAPIsOnlyForCoreModules(\n\t\t'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.',\n\t\t'@wordpress/dataviews'\n\t);\n"],"mappings":"AAAA;AACA;AACA;AACA,SAASA,gDAAgD,QAAQ,yBAAyB;AAE1F,OAAO,MAAM;EAAEC,IAAI;EAAEC;AAAO,CAAC,GAC5BF,gDAAgD,CAC/C,iHAAiH,EACjH,sBACD,CAAC"} -\ No newline at end of file -+{"version":3,"names":["__dangerousOptInToUnstableAPIsOnlyForCoreModules","lock","unlock"],"sources":["@wordpress/dataviews/src/lock-unlock.js"],"sourcesContent":["/**\n * WordPress dependencies\n */\nimport { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/private-apis';\n\nexport const { lock, unlock } =\n\t__dangerousOptInToUnstableAPIsOnlyForCoreModules(\n\t\t'I acknowledge private features are not for use in themes or plugins and doing so will break in the next version of WordPress.',\n\t\t'@wordpress/dataviews'\n\t);\n"],"mappings":"AAAA;AACA;AACA;AACA,SAASA,gDAAgD,QAAQ,yBAAyB;AAE1F,OAAO,MAAM;EAAEC,IAAI;EAAEC;AAAO,CAAC,GAC5BF,gDAAgD,CAC/C,iHAAiH,EACjH,sBACD,CAAC"} -\ No newline at end of file -diff --git a/src/lock-unlock.js b/src/lock-unlock.js -index 18318773cefefee8becd93b68574d2b8659b5707..bf7fc262ddb2b241de42ab70ab207c34ccf487a6 100644 ---- a/src/lock-unlock.js -+++ b/src/lock-unlock.js -@@ -1,10 +1,10 @@ - /** - * WordPress dependencies - */ --import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/private-apis'; -+import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from "@wordpress/private-apis"; - - export const { lock, unlock } = -- __dangerousOptInToUnstableAPIsOnlyForCoreModules( -- 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', -- '@wordpress/dataviews' -- ); -+ __dangerousOptInToUnstableAPIsOnlyForCoreModules( -+ "I acknowledge private features are not for use in themes or plugins and doing so will break in the next version of WordPress.", -+ "@wordpress/dataviews" -+ ); diff --git a/client/a8c-for-agencies/components/add-new-site-button/import-from-wpcom-modal/hooks/use-managed-sites-map.ts b/client/a8c-for-agencies/components/add-new-site-button/import-from-wpcom-modal/hooks/use-managed-sites-map.ts index 14a42f526230a9..adeaa27b17d5b6 100644 --- a/client/a8c-for-agencies/components/add-new-site-button/import-from-wpcom-modal/hooks/use-managed-sites-map.ts +++ b/client/a8c-for-agencies/components/add-new-site-button/import-from-wpcom-modal/hooks/use-managed-sites-map.ts @@ -14,10 +14,6 @@ export default function useManagedSitesMap( { size = 100 }: Props ) { isPartnerOAuthTokenLoaded: false, searchQuery: '', currentPage: 1, - sort: { - field: '', - direction: '', - }, perPage: size, agencyId, filter: { diff --git a/client/a8c-for-agencies/components/add-new-site-button/import-from-wpcom-modal/table-content.tsx b/client/a8c-for-agencies/components/add-new-site-button/import-from-wpcom-modal/table-content.tsx index e4d5a9282e345e..8c5ce203b0e4c7 100644 --- a/client/a8c-for-agencies/components/add-new-site-button/import-from-wpcom-modal/table-content.tsx +++ b/client/a8c-for-agencies/components/add-new-site-button/import-from-wpcom-modal/table-content.tsx @@ -1,19 +1,24 @@ -import { useState, useEffect } from 'react'; +import { filterSortAndPaginate } from '@wordpress/dataviews'; +import { useMemo, useState, useEffect } from 'react'; import { initialDataViewsState } from 'calypso/a8c-for-agencies/components/items-dashboard/constants'; import ItemsDataViews from 'calypso/a8c-for-agencies/components/items-dashboard/items-dataviews'; import { SiteItem } from './wpcom-sites-table'; -import type { DataViewsColumn } from '../../items-dashboard/items-dataviews/interfaces'; +import type { Field } from '@wordpress/dataviews'; interface Props { items: SiteItem[]; - fields: DataViewsColumn[]; + fields: Field< any >[]; } export default function WPCOMSitesTableContent( { items, fields }: Props ) { const [ dataViewsState, setDataViewsState ] = useState( initialDataViewsState ); + const { data, paginationInfo } = useMemo( () => { + return filterSortAndPaginate( items, dataViewsState, fields ); + }, [ items, dataViewsState, fields ] ); + useEffect( () => { - if ( items.length ) { + if ( data.length ) { const handleRowClick = ( event: Event ) => { const target = event.target as HTMLElement; @@ -51,22 +56,20 @@ export default function WPCOMSitesTableContent( { items, fields }: Props ) { } }; } - }, [ dataViewsState, items ] ); + }, [ dataViewsState, data ] ); return ( `${ item.id }`, - pagination: { - totalItems: 1, - totalPages: 1, - }, + pagination: paginationInfo, enableSearch: false, actions: [], dataViewsState: dataViewsState, setDataViewsState: setDataViewsState, + defaultLayouts: { table: {} }, } } /> ); diff --git a/client/a8c-for-agencies/components/add-new-site-button/import-from-wpcom-modal/wpcom-sites-table.tsx b/client/a8c-for-agencies/components/add-new-site-button/import-from-wpcom-modal/wpcom-sites-table.tsx index c90731128f4fae..9b4a298921eb99 100644 --- a/client/a8c-for-agencies/components/add-new-site-button/import-from-wpcom-modal/wpcom-sites-table.tsx +++ b/client/a8c-for-agencies/components/add-new-site-button/import-from-wpcom-modal/wpcom-sites-table.tsx @@ -55,10 +55,6 @@ export default function WPCOMSitesTable( { isPartnerOAuthTokenLoaded: false, searchQuery: '', currentPage: 1, - sort: { - field: '', - direction: '', - }, perPage: 1, agencyId, filter: { @@ -120,7 +116,7 @@ export default function WPCOMSitesTable( { ? [ { id: 'site', - header: ( + label: (
{ item.site }
), - width: '100%', enableHiding: false, enableSorting: false, }, @@ -154,7 +149,7 @@ export default function WPCOMSitesTable( { : [ { id: 'site', - header: ( + label: (
), - width: '100%', enableHiding: false, enableSorting: false, }, { id: 'date', - header: translate( 'Date' ).toUpperCase(), + label: translate( 'Date' ).toUpperCase(), getValue: () => '-', render: ( { item }: { item: SiteItem } ) => new Date( item.date ).toLocaleDateString(), - width: '100%', enableHiding: false, enableSorting: false, }, { id: 'type', - header: translate( 'Type' ).toUpperCase(), + label: translate( 'Type' ).toUpperCase(), getValue: () => '-', render: ( { item }: { item: SiteItem } ) => , - width: '100%', enableHiding: false, enableSorting: false, }, @@ -207,6 +199,8 @@ export default function WPCOMSitesTable( { { isPending ? ( ) : ( + // @ts-expect-error the error is because field.label types do not admit JSX.Elements. + // To remove when this is using dataviews@4.2.0 ) }
diff --git a/client/a8c-for-agencies/components/items-dashboard/constants.ts b/client/a8c-for-agencies/components/items-dashboard/constants.ts index 4a2938ac09a329..af095d7e9c8525 100644 --- a/client/a8c-for-agencies/components/items-dashboard/constants.ts +++ b/client/a8c-for-agencies/components/items-dashboard/constants.ts @@ -14,6 +14,5 @@ export const initialDataViewsState: DataViewsState = { perPage: 50, page: 1, search: '', - hiddenFields: [], layout: {}, }; diff --git a/client/a8c-for-agencies/components/items-dashboard/items-dataviews/index.tsx b/client/a8c-for-agencies/components/items-dashboard/items-dataviews/index.tsx index d7b4307dc7c6ab..0c1f45c1baa157 100644 --- a/client/a8c-for-agencies/components/items-dashboard/items-dataviews/index.tsx +++ b/client/a8c-for-agencies/components/items-dashboard/items-dataviews/index.tsx @@ -4,7 +4,8 @@ import { useTranslate } from 'i18n-calypso'; import { ReactNode, useRef, useLayoutEffect } from 'react'; import ReactDOM from 'react-dom'; import { DataViews } from 'calypso/components/dataviews'; -import { ItemsDataViewsType, DataViewsColumn } from './interfaces'; +import { ItemsDataViewsType } from './interfaces'; +import type { Field } from '@wordpress/dataviews'; import './style.scss'; @@ -23,7 +24,7 @@ const getIdByPath = ( item: object, path: string ) => { /** * Create an item column for the DataViews component * @param id - * @param header + * @param label * @param displayField * @param getValue * @param isSortable @@ -31,18 +32,19 @@ const getIdByPath = ( item: object, path: string ) => { */ export const createItemColumn = ( id: string, - header: ReactNode, + label: ReactNode, displayField: () => ReactNode, getValue: () => undefined, isSortable: boolean = false, canHide: boolean = false -): DataViewsColumn => { +): Field< any > => { return { id, enableSorting: isSortable, enableHiding: canHide, getValue, - header, + // @ts-expect-error -- Need to fix the label type upstream in @wordpress/dataviews to support React elements. + label, render: displayField, }; }; @@ -64,9 +66,7 @@ const ItemsDataViews = ( { data, isLoading = false, className }: ItemsDataViewsP ! scrollContainerRef.current || previousDataViewsState?.type !== data.dataViewsState.type ) { - scrollContainerRef.current = document.querySelector( - '.dataviews-view-list, .dataviews-view-table-wrapper' - ) as HTMLElement; + scrollContainerRef.current = document.querySelector( '.dataviews-view-list' ) as HTMLElement; } if ( ! previousDataViewsState?.selectedItem && data.dataViewsState.selectedItem ) { @@ -85,12 +85,13 @@ const ItemsDataViews = ( { data, isLoading = false, className }: ItemsDataViewsP return (
data.setDataViewsState( () => newView ) } + fields={ data.fields } search={ data?.enableSearch ?? true } searchLabel={ data.searchLabel ?? translate( 'Search' ) } + actions={ data.actions } getItemId={ data.getItemId ?? ( ( item: any ) => { @@ -99,11 +100,12 @@ const ItemsDataViews = ( { data, isLoading = false, className }: ItemsDataViewsP return item.id; } ) } - onSelectionChange={ data.onSelectionChange } - onChangeView={ data.setDataViewsState } - supportedLayouts={ [ 'table' ] } - actions={ data.actions } isLoading={ isLoading } + paginationInfo={ data.pagination } + defaultLayouts={ data.defaultLayouts } + selection={ data.selection } + onChangeSelection={ data.onSelectionChange } + header={ data.header } /> { dataviewsWrapper && ReactDOM.createPortal( diff --git a/client/a8c-for-agencies/components/items-dashboard/items-dataviews/interfaces.ts b/client/a8c-for-agencies/components/items-dashboard/items-dataviews/interfaces.ts index 2825c947a60b63..628d6368cb103f 100644 --- a/client/a8c-for-agencies/components/items-dashboard/items-dataviews/interfaces.ts +++ b/client/a8c-for-agencies/components/items-dashboard/items-dataviews/interfaces.ts @@ -1,47 +1,21 @@ -import { ReactNode } from 'react'; +import type { View, Field, Action, SortDirection } from '@wordpress/dataviews'; +import type { ReactNode } from 'react'; export interface ItemsDataViewsType< T > { items: T[] | undefined; pagination: DataViewsPaginationInfo; enableSearch?: boolean; searchLabel?: string; - fields: DataViewsColumn[]; - actions?: DataViewsAction[]; + fields: Field< T >[]; + actions?: Action< T >[]; getItemId?: ( item: T ) => string; itemFieldId?: string; // The field path to get the item id. Examples `id` or `site.blog_id` setDataViewsState: ( callback: ( prevState: DataViewsState ) => DataViewsState ) => void; dataViewsState: DataViewsState; - onSelectionChange?: ( item: T[] ) => void; -} - -export interface DataViewsColumn { - id: string; - enableHiding?: boolean; - enableSorting?: boolean; - elements?: { - value: number; - label: string; - }[]; - filterBy?: { - operators: string[]; - isPrimary?: boolean; - }; - type?: string; - header: ReactNode; - getValue?: ( item: any ) => string | boolean | number | undefined; - render?: ( item: any ) => ReactNode | null; -} - -export interface DataViewsAction { - id: string; - label: string; - isPrimary?: boolean; - icon?: string; - isEligible?: ( record: any ) => boolean; - isDestructive?: boolean; - callback?: () => void; - RenderModal?: ReactNode; - hideModalHeader?: boolean; + selection?: string[]; + onSelectionChange?: ( items: string[] ) => void; + defaultLayouts?: any; // TODO: improve this type + header?: ReactNode; } export interface DataViewsPaginationInfo { @@ -51,23 +25,10 @@ export interface DataViewsPaginationInfo { export interface DataViewsSort { field: string; - direction: 'asc' | 'desc' | ''; + direction: SortDirection; } -export interface DataViewsFilter { - field: string; - operator: string; - value: number; -} - -export interface DataViewsState { - type: 'table' | 'list' | 'grid'; - search: string; - filters: DataViewsFilter[]; - perPage: number; - page: number; - sort: DataViewsSort; - hiddenFields?: string[]; - layout: object; +export type DataViewsState = View & { selectedItem?: any | undefined; -} + layout?: any; // TODO: improve this type. +}; diff --git a/client/a8c-for-agencies/components/items-dashboard/items-dataviews/site-sort/index.tsx b/client/a8c-for-agencies/components/items-dashboard/items-dataviews/site-sort/index.tsx deleted file mode 100644 index c511c47daacb5a..00000000000000 --- a/client/a8c-for-agencies/components/items-dashboard/items-dataviews/site-sort/index.tsx +++ /dev/null @@ -1,101 +0,0 @@ -import { Icon } from '@wordpress/icons'; -import clsx from 'clsx'; -import { useContext } from 'react'; -// todo: Extract the context -import SitesDashboardContext from 'calypso/a8c-for-agencies/sections/sites/sites-dashboard-context'; -// todo: Copy the sort icons from Jetpack Cloud -import { - defaultSortIcon, - ascendingSortIcon, - descendingSortIcon, -} from 'calypso/jetpack-cloud/sections/agency-dashboard/icons'; - -import './style.scss'; - -const SORT_DIRECTION_ASC = 'asc'; -const SORT_DIRECTION_DESC = 'desc'; - -// Mapping the columns to the site data keys -const SITE_COLUMN_KEY_MAP: { [ key: string ]: string } = { - site: 'url', -}; - -export default function SiteSort( { - columnKey, - isLargeScreen, - children, - isSortable, -}: { - columnKey: string; - isLargeScreen?: boolean; - children?: React.ReactNode; - isSortable?: boolean; -} ) { - const { dataViewsState, setDataViewsState } = useContext( SitesDashboardContext ); - - const { field, direction } = dataViewsState.sort; - - const isDefault = field !== SITE_COLUMN_KEY_MAP?.[ columnKey ] || ! field || ! direction; - - const setSort = () => { - const updatedSort = { ...dataViewsState.sort }; - if ( isDefault ) { - updatedSort.field = SITE_COLUMN_KEY_MAP?.[ columnKey ]; - updatedSort.direction = SORT_DIRECTION_ASC; - } else if ( direction === SORT_DIRECTION_ASC ) { - updatedSort.direction = SORT_DIRECTION_DESC; - } else if ( direction === SORT_DIRECTION_DESC ) { - updatedSort.field = ''; - updatedSort.direction = ''; - } - - setDataViewsState( ( sitesViewState ) => ( { - ...sitesViewState, - sort: updatedSort, - } ) ); - }; - - const getSortIcon = () => { - if ( isDefault ) { - return defaultSortIcon; - } else if ( direction === SORT_DIRECTION_ASC ) { - return ascendingSortIcon; - } else if ( direction === SORT_DIRECTION_DESC ) { - return descendingSortIcon; - } - return defaultSortIcon; - }; - - if ( ! isSortable ) { - return { children }; - } - - const handleOnKeyDown = ( event: React.KeyboardEvent< HTMLDivElement > ) => { - if ( event.key === 'Enter' || event.key === ' ' ) { - setSort(); - } - }; - - return ( - - { children } - { isSortable && ( - - ) } - - ); -} diff --git a/client/a8c-for-agencies/components/items-dashboard/items-dataviews/site-sort/style.scss b/client/a8c-for-agencies/components/items-dashboard/items-dataviews/site-sort/style.scss deleted file mode 100644 index d54e0243a2cb8c..00000000000000 --- a/client/a8c-for-agencies/components/items-dashboard/items-dataviews/site-sort/style.scss +++ /dev/null @@ -1,43 +0,0 @@ -.site-sort__icon { - position: relative; - inset-block-start: 3px; - inset-inline-start: 8px; -} - -.site-sort__icon-large_screen { - &.site-sort { - position: relative; - width: 100%; - height: 100%; - display: inline-flex; - align-items: center; - margin-inline-start: -16px; - padding-inline: 16px; - } - - .site-sort__icon { - position: absolute; - inset-inline-end: 16px; - inset-block-start: unset; - inset-inline-start: unset; - } -} - -.site-sort__icon-hidden { - visibility: hidden; -} - -.site-sort__clickable { - cursor: pointer; - // Inline block to ensure focus outline is rectangular. - display: inline-block; - // 5px right padding so focus border doesnt overlap icon. - padding-right: 5px; - border-radius: 2px; - .accessible-focus &:focus { - outline-style: solid; - outline-color: var(--color-primary-light); - outline-width: 2px; - outline-offset: 2px; - } -} diff --git a/client/a8c-for-agencies/components/items-dashboard/items-dataviews/style.scss b/client/a8c-for-agencies/components/items-dashboard/items-dataviews/style.scss index a948592130a18c..7753fd32a54b42 100644 --- a/client/a8c-for-agencies/components/items-dashboard/items-dataviews/style.scss +++ b/client/a8c-for-agencies/components/items-dashboard/items-dataviews/style.scss @@ -22,6 +22,7 @@ justify-content: space-between !important; padding: 12px 16px 12px 16px; margin-top: auto; + z-index: 1; .components-input-control__backdrop { border-color: var(--Gray-Gray-5, #dcdcde); @@ -35,3 +36,16 @@ bottom: 0; } } + +/* + * This is a hotfix for the the button disabled state. + * The button is getting a color that is almost identical to the active state. + * It needs to be looked at and fixed separately. + * See https://github.com/Automattic/wp-calypso/pull/93503#issuecomment-2304078241 + */ +.dataviews-wrapper .components-button.is-tertiary:visited, +.dataviews-wrapper .components-button.is-tertiary[disabled], +.dataviews-wrapper .components-button.is-tertiary:disabled, +.dataviews-wrapper .components-button.is-tertiary.disabled { + color: #949494; // Same as core https://github.com/WordPress/gutenberg/blob/2cbba93a29600f09f6f95c09f690576b90e79e9f/packages/components/src/button/style.scss#L125 +} diff --git a/client/a8c-for-agencies/hooks/use-no-active-site.ts b/client/a8c-for-agencies/hooks/use-no-active-site.ts index d8bd5d90322019..b17668ddd6f104 100644 --- a/client/a8c-for-agencies/hooks/use-no-active-site.ts +++ b/client/a8c-for-agencies/hooks/use-no-active-site.ts @@ -14,10 +14,6 @@ export default function useNoActiveSite() { showOnlyFavorites: false, showOnlyDevelopmentSites: false, }, - sort: { - field: '', - direction: '', - }, agencyId, } ); diff --git a/client/a8c-for-agencies/sections/client/cancel-subscription-confirmation-dialog/index.tsx b/client/a8c-for-agencies/sections/client/cancel-subscription-confirmation-dialog/index.tsx index 0cd1796bad6e95..235b8fb6b43e5b 100644 --- a/client/a8c-for-agencies/sections/client/cancel-subscription-confirmation-dialog/index.tsx +++ b/client/a8c-for-agencies/sections/client/cancel-subscription-confirmation-dialog/index.tsx @@ -20,7 +20,7 @@ export default function CancelSubscriptionAction( { subscription, onCancelSubscr const [ isVisible, setIsVisible ] = useState( false ); - const { data: products, isFetching: isFetchingProductInfo } = useFetchClientProducts(); + const { data: products, isFetching: isFetchingProductInfo } = useFetchClientProducts( false ); const { mutate: cancelSubscription, isPending } = useCancelClientSubscription( { onSuccess: () => { diff --git a/client/a8c-for-agencies/sections/client/primary/subscriptions-list/index.tsx b/client/a8c-for-agencies/sections/client/primary/subscriptions-list/index.tsx index bd2c0adf2b86c2..4726a9318a72ce 100644 --- a/client/a8c-for-agencies/sections/client/primary/subscriptions-list/index.tsx +++ b/client/a8c-for-agencies/sections/client/primary/subscriptions-list/index.tsx @@ -1,4 +1,5 @@ import { useDesktopBreakpoint } from '@automattic/viewport-react'; +import { filterSortAndPaginate } from '@wordpress/dataviews'; import clsx from 'clsx'; import { useTranslate } from 'i18n-calypso'; import { useMemo, ReactNode, useState, useCallback } from 'react'; @@ -44,7 +45,7 @@ export default function SubscriptionsList() { () => [ { id: 'purchase', - header: translate( 'Purchase' ).toUpperCase(), + label: translate( 'Purchase' ).toUpperCase(), getValue: () => '-', render: ( { item }: { item: Subscription } ): ReactNode => { const product = products?.find( ( product ) => product.product_id === item.product_id ); @@ -55,7 +56,7 @@ export default function SubscriptionsList() { }, { id: 'price', - header: translate( 'Price' ).toUpperCase(), + label: translate( 'Price' ).toUpperCase(), getValue: () => '-', render: ( { item }: { item: Subscription } ): ReactNode => { const product = products?.find( ( product ) => product.product_id === item.product_id ); @@ -66,7 +67,7 @@ export default function SubscriptionsList() { }, { id: 'subscription-status', - header: translate( 'Subscription Status' ).toUpperCase(), + label: translate( 'Subscription Status' ).toUpperCase(), getValue: () => '-', render: ( { item }: { item: Subscription } ): ReactNode => { return ; @@ -76,7 +77,7 @@ export default function SubscriptionsList() { }, { id: 'actions', - header: translate( 'Actions' ).toUpperCase(), + label: translate( 'Actions' ).toUpperCase(), getValue: () => '-', render: ( { item }: { item: Subscription } ): ReactNode => { return ( @@ -92,6 +93,9 @@ export default function SubscriptionsList() { ], [ isFetchingProducts, onCancelSubscription, products, translate ] ); + const { data: items, paginationInfo } = useMemo( () => { + return filterSortAndPaginate( data ?? [], dataViewsState, fields ); + }, [ data, dataViewsState, fields ] ); return ( diff --git a/client/a8c-for-agencies/sections/referrals/common/referral-details-table/index.tsx b/client/a8c-for-agencies/sections/referrals/common/referral-details-table/index.tsx index 8c2032887a214a..3235fbb3eba6dd 100644 --- a/client/a8c-for-agencies/sections/referrals/common/referral-details-table/index.tsx +++ b/client/a8c-for-agencies/sections/referrals/common/referral-details-table/index.tsx @@ -1,33 +1,36 @@ -import { useState } from 'react'; +import { filterSortAndPaginate } from '@wordpress/dataviews'; +import { useState, useMemo } from 'react'; import { initialDataViewsState } from 'calypso/a8c-for-agencies/components/items-dashboard/constants'; import ItemsDataViews from 'calypso/a8c-for-agencies/components/items-dashboard/items-dataviews'; import type { ReferralPurchase } from '../../types'; -import type { DataViewsColumn } from 'calypso/a8c-for-agencies/components/items-dashboard/items-dataviews/interfaces'; +import type { Field } from '@wordpress/dataviews'; import './style.scss'; interface Props { items: ReferralPurchase[]; // Update this when we have more types - fields: DataViewsColumn[]; + fields: Field< ReferralPurchase >[]; } export default function ReferralDetailsTable( { items, fields }: Props ) { const [ dataViewsState, setDataViewsState ] = useState( initialDataViewsState ); + const { data, paginationInfo } = useMemo( () => { + return filterSortAndPaginate( items, dataViewsState, fields ); + }, [ items, dataViewsState, fields ] ); + return (
diff --git a/client/a8c-for-agencies/sections/referrals/primary/referrals-overview/style.scss b/client/a8c-for-agencies/sections/referrals/primary/referrals-overview/style.scss index 65a08aa01b6a9b..beee9cfbadc596 100644 --- a/client/a8c-for-agencies/sections/referrals/primary/referrals-overview/style.scss +++ b/client/a8c-for-agencies/sections/referrals/primary/referrals-overview/style.scss @@ -90,14 +90,6 @@ $data-view-border-color: #f1f1f1; position: sticky; right: 0; z-index: 1; - background: linear-gradient(to right, transparent 0%, #fff 25%); - } - - &:hover { - th:last-child, - td:last-child { - background: linear-gradient(to right, transparent 0%, var(--color-neutral-0) 25%); - } } } } @@ -172,8 +164,6 @@ $data-view-border-color: #f1f1f1; } li:not(.section-nav-tab) { - margin-inline: -24px; - padding: 16px 24px; border-bottom: 1px solid $data-view-border-color; } @@ -189,8 +179,7 @@ $data-view-border-color: #f1f1f1; margin-block-end: 0; } - .a4a-layout__top-wrapper > *, - .a4a-layout__body > * { + .a4a-layout__top-wrapper > * { padding-inline: 24px; } diff --git a/client/a8c-for-agencies/sections/referrals/referral-details/purchases.tsx b/client/a8c-for-agencies/sections/referrals/referral-details/purchases.tsx index 15159c54a51770..30628bab840cee 100644 --- a/client/a8c-for-agencies/sections/referrals/referral-details/purchases.tsx +++ b/client/a8c-for-agencies/sections/referrals/referral-details/purchases.tsx @@ -30,7 +30,7 @@ export default function ReferralPurchases( { purchases }: { purchases: ReferralP () => [ { id: 'product-details', - header: translate( 'Product Details' ).toUpperCase(), + label: translate( 'Product Details' ).toUpperCase(), getValue: () => '-', render: ( { item }: { item: ReferralPurchase } ): ReactNode => { return ; @@ -40,7 +40,7 @@ export default function ReferralPurchases( { purchases }: { purchases: ReferralP }, { id: 'assigned-to', - header: translate( 'Assigned to' ).toUpperCase(), + label: translate( 'Assigned to' ).toUpperCase(), getValue: () => '-', render: ( { item }: { item: ReferralPurchase } ): ReactNode => { return ( @@ -57,7 +57,7 @@ export default function ReferralPurchases( { purchases }: { purchases: ReferralP }, { id: 'date', - header: translate( 'Assigned on' ).toUpperCase(), + label: translate( 'Assigned on' ).toUpperCase(), getValue: () => '-', render: ( { item }: { item: ReferralPurchase } ): ReactNode => { return ; @@ -67,7 +67,7 @@ export default function ReferralPurchases( { purchases }: { purchases: ReferralP }, { id: 'total', - header: translate( 'Total' ).toUpperCase(), + label: translate( 'Total' ).toUpperCase(), getValue: () => '-', render: ( { item }: { item: ReferralPurchase } ): ReactNode => { return ; diff --git a/client/a8c-for-agencies/sections/referrals/referral-details/style.scss b/client/a8c-for-agencies/sections/referrals/referral-details/style.scss index 68943618d6c528..09126d0a2c54d9 100644 --- a/client/a8c-for-agencies/sections/referrals/referral-details/style.scss +++ b/client/a8c-for-agencies/sections/referrals/referral-details/style.scss @@ -29,3 +29,11 @@ width: auto; } } + +// TODO: remove when the list view declares a proper primary field. +// +// The issue here is that the email is not provided as a primary field, +// hence it's displayed below the space reserved for the media+primary field in list view. +.dataviews-view-list__media-wrapper { + display: none !important; +} diff --git a/client/a8c-for-agencies/sections/referrals/referrals-list/index.tsx b/client/a8c-for-agencies/sections/referrals/referrals-list/index.tsx index faf014892e6433..92e683be9f0caf 100644 --- a/client/a8c-for-agencies/sections/referrals/referrals-list/index.tsx +++ b/client/a8c-for-agencies/sections/referrals/referrals-list/index.tsx @@ -1,5 +1,6 @@ import { Button, Gridicon } from '@automattic/components'; import { useDesktopBreakpoint } from '@automattic/viewport-react'; +import { filterSortAndPaginate } from '@wordpress/dataviews'; import { useTranslate } from 'i18n-calypso'; import { useMemo, useCallback, ReactNode, useEffect } from 'react'; import { DATAVIEWS_LIST } from 'calypso/a8c-for-agencies/components/items-dashboard/constants'; @@ -7,9 +8,10 @@ import ItemsDataViews from 'calypso/a8c-for-agencies/components/items-dashboard/ import { DataViewsState } from 'calypso/a8c-for-agencies/components/items-dashboard/items-dataviews/interfaces'; import { useDispatch } from 'calypso/state'; import { recordTracksEvent } from 'calypso/state/analytics/actions'; +import { Referral, ReferralInvoice } from '../types'; import CommissionsColumn from './commissions-column'; import SubscriptionStatus from './subscription-status'; -import type { Referral, ReferralInvoice } from '../types'; +import type { Field } from '@wordpress/dataviews'; import './style.scss'; @@ -42,14 +44,14 @@ export default function ReferralList( { [ dispatch, setDataViewsState ] ); - const fields = useMemo( + const fields: Field< any >[] = useMemo( () => dataViewsState.selectedItem || ! isDesktop ? [ // Show the client column as a button on mobile { id: 'client', - header: translate( 'Client' ).toUpperCase(), + label: translate( 'Client' ).toUpperCase(), getValue: () => '-', render: ( { item }: { item: Referral } ): ReactNode => (