diff --git a/.yarn/patches/@wordpress-dataviews-npm-0.4.1-2c01fa0792.patch b/.yarn/patches/@wordpress-dataviews-npm-0.4.1-2c01fa0792.patch new file mode 100644 index 0000000000000..ac1aef8391498 --- /dev/null +++ b/.yarn/patches/@wordpress-dataviews-npm-0.4.1-2c01fa0792.patch @@ -0,0 +1,87 @@ +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 adeaa27b17d5b..14a42f526230a 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,6 +14,10 @@ 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 8c5ce203b0e4c..e4d5a9282e345 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,24 +1,19 @@ -import { filterSortAndPaginate } from '@wordpress/dataviews'; -import { useMemo, useState, useEffect } from 'react'; +import { 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 { Field } from '@wordpress/dataviews'; +import type { DataViewsColumn } from '../../items-dashboard/items-dataviews/interfaces'; interface Props { items: SiteItem[]; - fields: Field< any >[]; + fields: DataViewsColumn[]; } 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 ( data.length ) { + if ( items.length ) { const handleRowClick = ( event: Event ) => { const target = event.target as HTMLElement; @@ -56,20 +51,22 @@ export default function WPCOMSitesTableContent( { items, fields }: Props ) { } }; } - }, [ dataViewsState, data ] ); + }, [ dataViewsState, items ] ); return ( `${ item.id }`, - pagination: paginationInfo, + pagination: { + totalItems: 1, + totalPages: 1, + }, 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 9b4a298921eb9..c90731128f4fa 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,6 +55,10 @@ export default function WPCOMSitesTable( { isPartnerOAuthTokenLoaded: false, searchQuery: '', currentPage: 1, + sort: { + field: '', + direction: '', + }, perPage: 1, agencyId, filter: { @@ -116,7 +120,7 @@ export default function WPCOMSitesTable( { ? [ { id: 'site', - label: ( + header: (
{ item.site }
), + width: '100%', enableHiding: false, enableSorting: false, }, @@ -149,7 +154,7 @@ export default function WPCOMSitesTable( { : [ { id: 'site', - label: ( + header: (
), + width: '100%', enableHiding: false, enableSorting: false, }, { id: 'date', - label: translate( 'Date' ).toUpperCase(), + header: translate( 'Date' ).toUpperCase(), getValue: () => '-', render: ( { item }: { item: SiteItem } ) => new Date( item.date ).toLocaleDateString(), + width: '100%', enableHiding: false, enableSorting: false, }, { id: 'type', - label: translate( 'Type' ).toUpperCase(), + header: translate( 'Type' ).toUpperCase(), getValue: () => '-', render: ( { item }: { item: SiteItem } ) => , + width: '100%', enableHiding: false, enableSorting: false, }, @@ -199,8 +207,6 @@ 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 af095d7e9c852..4a2938ac09a32 100644 --- a/client/a8c-for-agencies/components/items-dashboard/constants.ts +++ b/client/a8c-for-agencies/components/items-dashboard/constants.ts @@ -14,5 +14,6 @@ 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 0c1f45c1baa15..d7b4307dc7c6a 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,8 +4,7 @@ import { useTranslate } from 'i18n-calypso'; import { ReactNode, useRef, useLayoutEffect } from 'react'; import ReactDOM from 'react-dom'; import { DataViews } from 'calypso/components/dataviews'; -import { ItemsDataViewsType } from './interfaces'; -import type { Field } from '@wordpress/dataviews'; +import { ItemsDataViewsType, DataViewsColumn } from './interfaces'; import './style.scss'; @@ -24,7 +23,7 @@ const getIdByPath = ( item: object, path: string ) => { /** * Create an item column for the DataViews component * @param id - * @param label + * @param header * @param displayField * @param getValue * @param isSortable @@ -32,19 +31,18 @@ const getIdByPath = ( item: object, path: string ) => { */ export const createItemColumn = ( id: string, - label: ReactNode, + header: ReactNode, displayField: () => ReactNode, getValue: () => undefined, isSortable: boolean = false, canHide: boolean = false -): Field< any > => { +): DataViewsColumn => { return { id, enableSorting: isSortable, enableHiding: canHide, getValue, - // @ts-expect-error -- Need to fix the label type upstream in @wordpress/dataviews to support React elements. - label, + header, render: displayField, }; }; @@ -66,7 +64,9 @@ const ItemsDataViews = ( { data, isLoading = false, className }: ItemsDataViewsP ! scrollContainerRef.current || previousDataViewsState?.type !== data.dataViewsState.type ) { - scrollContainerRef.current = document.querySelector( '.dataviews-view-list' ) as HTMLElement; + scrollContainerRef.current = document.querySelector( + '.dataviews-view-list, .dataviews-view-table-wrapper' + ) as HTMLElement; } if ( ! previousDataViewsState?.selectedItem && data.dataViewsState.selectedItem ) { @@ -85,13 +85,12 @@ const ItemsDataViews = ( { data, isLoading = false, className }: ItemsDataViewsP return (
data.setDataViewsState( () => newView ) } + data={ data.items } + paginationInfo={ data.pagination } fields={ data.fields } + view={ data.dataViewsState } search={ data?.enableSearch ?? true } searchLabel={ data.searchLabel ?? translate( 'Search' ) } - actions={ data.actions } getItemId={ data.getItemId ?? ( ( item: any ) => { @@ -100,12 +99,11 @@ 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 628d6368cb103..2825c947a60b6 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,21 +1,47 @@ -import type { View, Field, Action, SortDirection } from '@wordpress/dataviews'; -import type { ReactNode } from 'react'; +import { ReactNode } from 'react'; export interface ItemsDataViewsType< T > { items: T[] | undefined; pagination: DataViewsPaginationInfo; enableSearch?: boolean; searchLabel?: string; - fields: Field< T >[]; - actions?: Action< T >[]; + fields: DataViewsColumn[]; + actions?: DataViewsAction[]; 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; - selection?: string[]; - onSelectionChange?: ( items: string[] ) => void; - defaultLayouts?: any; // TODO: improve this type - header?: ReactNode; + 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; } export interface DataViewsPaginationInfo { @@ -25,10 +51,23 @@ export interface DataViewsPaginationInfo { export interface DataViewsSort { field: string; - direction: SortDirection; + direction: 'asc' | 'desc' | ''; } -export type DataViewsState = View & { +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; 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 new file mode 100644 index 0000000000000..c511c47daacb5 --- /dev/null +++ b/client/a8c-for-agencies/components/items-dashboard/items-dataviews/site-sort/index.tsx @@ -0,0 +1,101 @@ +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 new file mode 100644 index 0000000000000..d54e0243a2cb8 --- /dev/null +++ b/client/a8c-for-agencies/components/items-dashboard/items-dataviews/site-sort/style.scss @@ -0,0 +1,43 @@ +.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 7753fd32a54b4..a948592130a18 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,7 +22,6 @@ 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); @@ -36,16 +35,3 @@ 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 b17668ddd6f10..d8bd5d9032201 100644 --- a/client/a8c-for-agencies/hooks/use-no-active-site.ts +++ b/client/a8c-for-agencies/hooks/use-no-active-site.ts @@ -14,6 +14,10 @@ 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 235b8fb6b43e5..0cd1796bad6e9 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( false ); + const { data: products, isFetching: isFetchingProductInfo } = useFetchClientProducts(); 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 4726a9318a72c..bd2c0adf2b86c 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,5 +1,4 @@ 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'; @@ -45,7 +44,7 @@ export default function SubscriptionsList() { () => [ { id: 'purchase', - label: translate( 'Purchase' ).toUpperCase(), + header: translate( 'Purchase' ).toUpperCase(), getValue: () => '-', render: ( { item }: { item: Subscription } ): ReactNode => { const product = products?.find( ( product ) => product.product_id === item.product_id ); @@ -56,7 +55,7 @@ export default function SubscriptionsList() { }, { id: 'price', - label: translate( 'Price' ).toUpperCase(), + header: translate( 'Price' ).toUpperCase(), getValue: () => '-', render: ( { item }: { item: Subscription } ): ReactNode => { const product = products?.find( ( product ) => product.product_id === item.product_id ); @@ -67,7 +66,7 @@ export default function SubscriptionsList() { }, { id: 'subscription-status', - label: translate( 'Subscription Status' ).toUpperCase(), + header: translate( 'Subscription Status' ).toUpperCase(), getValue: () => '-', render: ( { item }: { item: Subscription } ): ReactNode => { return ; @@ -77,7 +76,7 @@ export default function SubscriptionsList() { }, { id: 'actions', - label: translate( 'Actions' ).toUpperCase(), + header: translate( 'Actions' ).toUpperCase(), getValue: () => '-', render: ( { item }: { item: Subscription } ): ReactNode => { return ( @@ -93,9 +92,6 @@ 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 3235fbb3eba6d..8c2032887a214 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,36 +1,33 @@ -import { filterSortAndPaginate } from '@wordpress/dataviews'; -import { useState, useMemo } from 'react'; +import { useState } 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 { Field } from '@wordpress/dataviews'; +import type { DataViewsColumn } from 'calypso/a8c-for-agencies/components/items-dashboard/items-dataviews/interfaces'; import './style.scss'; interface Props { items: ReferralPurchase[]; // Update this when we have more types - fields: Field< ReferralPurchase >[]; + fields: DataViewsColumn[]; } 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 beee9cfbadc59..65a08aa01b6a9 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,6 +90,14 @@ $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%); + } } } } @@ -164,6 +172,8 @@ $data-view-border-color: #f1f1f1; } li:not(.section-nav-tab) { + margin-inline: -24px; + padding: 16px 24px; border-bottom: 1px solid $data-view-border-color; } @@ -179,7 +189,8 @@ $data-view-border-color: #f1f1f1; margin-block-end: 0; } - .a4a-layout__top-wrapper > * { + .a4a-layout__top-wrapper > *, + .a4a-layout__body > * { 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 30628bab840ce..15159c54a5177 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', - label: translate( 'Product Details' ).toUpperCase(), + header: 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', - label: translate( 'Assigned to' ).toUpperCase(), + header: translate( 'Assigned to' ).toUpperCase(), getValue: () => '-', render: ( { item }: { item: ReferralPurchase } ): ReactNode => { return ( @@ -57,7 +57,7 @@ export default function ReferralPurchases( { purchases }: { purchases: ReferralP }, { id: 'date', - label: translate( 'Assigned on' ).toUpperCase(), + header: translate( 'Assigned on' ).toUpperCase(), getValue: () => '-', render: ( { item }: { item: ReferralPurchase } ): ReactNode => { return ; @@ -67,7 +67,7 @@ export default function ReferralPurchases( { purchases }: { purchases: ReferralP }, { id: 'total', - label: translate( 'Total' ).toUpperCase(), + header: 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 09126d0a2c54d..68943618d6c52 100644 --- a/client/a8c-for-agencies/sections/referrals/referral-details/style.scss +++ b/client/a8c-for-agencies/sections/referrals/referral-details/style.scss @@ -29,11 +29,3 @@ 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 92e683be9f0ca..faf014892e643 100644 --- a/client/a8c-for-agencies/sections/referrals/referrals-list/index.tsx +++ b/client/a8c-for-agencies/sections/referrals/referrals-list/index.tsx @@ -1,6 +1,5 @@ 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'; @@ -8,10 +7,9 @@ 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 { Field } from '@wordpress/dataviews'; +import type { Referral, ReferralInvoice } from '../types'; import './style.scss'; @@ -44,14 +42,14 @@ export default function ReferralList( { [ dispatch, setDataViewsState ] ); - const fields: Field< any >[] = useMemo( + const fields = useMemo( () => dataViewsState.selectedItem || ! isDesktop ? [ // Show the client column as a button on mobile { id: 'client', - label: translate( 'Client' ).toUpperCase(), + header: translate( 'Client' ).toUpperCase(), getValue: () => '-', render: ( { item }: { item: Referral } ): ReactNode => (