Skip to content

Commit

Permalink
Simplify useView
Browse files Browse the repository at this point in the history
  • Loading branch information
oandregal committed Aug 2, 2024
1 parent 563abae commit 8c96563
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 102 deletions.
156 changes: 90 additions & 66 deletions packages/edit-site/src/components/post-list/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
OPERATOR_IS_ANY,
OPERATOR_IS_NONE,
LAYOUT_LIST,
LAYOUT_TABLE,
} from '../../utils/constants';

import AddNewPostModal from '../add-new-post';
Expand All @@ -39,100 +40,123 @@ const { useLocation, useHistory } = unlock( routerPrivateApis );
const { useEntityRecordsWithPermissions } = unlock( coreDataPrivateApis );
const EMPTY_ARRAY = [];

const getDefaultView = ( defaultViews, activeView ) => {
return defaultViews.find( ( { slug } ) => slug === activeView )?.view;
};

const getCustomView = ( editedEntityRecord ) => {
if ( ! editedEntityRecord?.content ) {
return undefined;
}

const content = JSON.parse( editedEntityRecord.content );
if ( ! content ) {
return undefined;
}

return {
...content,
layout: defaultLayouts[ content.type ]?.layout,
};
};

/**
* This function abstracts working with default & custom views by
* providing a [ state, setState ] tuple based on the URL parameters.
*
* Consumers use the provided tuple to work with state
* and don't have to deal with the specifics of default & custom views.
*
* @param {string} postType Post type to retrieve default views for.
* @return {Array} The [ state, setState ] tuple.
*/
function useView( postType ) {
const {
params: { activeView = 'all', isCustom = 'false', layout },
} = useLocation();
const history = useHistory();

const defaultViews = useDefaultViews( { postType } );
const selectedDefaultView = useMemo( () => {
const defaultView =
isCustom === 'false' &&
defaultViews.find( ( { slug } ) => slug === activeView )?.view;
if ( isCustom === 'false' && layout ) {
return {
...defaultView,
type: layout,
layout: defaultLayouts[ layout ]?.layout,
};
}
return defaultView;
}, [ isCustom, activeView, layout, defaultViews ] );
const [ view, setView ] = useState( selectedDefaultView );

useEffect( () => {
if ( selectedDefaultView ) {
setView( selectedDefaultView );
}
}, [ selectedDefaultView ] );
const editedViewRecord = useSelect(
const { editEntityRecord } = useDispatch( coreStore );
const editedEntityRecord = useSelect(
( select ) => {
if ( isCustom !== 'true' ) {
return;
return undefined;
}

const { getEditedEntityRecord } = select( coreStore );
const dataviewRecord = getEditedEntityRecord(
return getEditedEntityRecord(
'postType',
'wp_dataviews',
Number( activeView )
);
return dataviewRecord;
},
[ activeView, isCustom ]
);
const { editEntityRecord } = useDispatch( coreStore );

const customView = useMemo( () => {
const storedView =
editedViewRecord?.content &&
JSON.parse( editedViewRecord?.content );
if ( ! storedView ) {
return storedView;
}

return {
...storedView,
layout: defaultLayouts[ storedView?.type ]?.layout,
};
}, [ editedViewRecord?.content ] );

const setCustomView = useCallback(
( viewToSet ) => {
editEntityRecord(
'postType',
'wp_dataviews',
editedViewRecord?.id,
{
content: JSON.stringify( viewToSet ),
const [ view, setView ] = useState( () => {
if ( isCustom === 'true' ) {
return (
getCustomView( editedEntityRecord ) ?? {
type: layout ?? LAYOUT_TABLE,
}
);
},
[ editEntityRecord, editedViewRecord?.id ]
);
}
return (
getDefaultView( defaultViews, activeView ) ?? {
type: layout ?? LAYOUT_TABLE,
}
);
} );

const setViewWithUrlUpdate = useCallback(
( newView ) => {
const { params } = history.getLocationWithParams();

const setDefaultViewAndUpdateUrl = useCallback(
( viewToSet ) => {
if ( viewToSet.type !== view?.type ) {
const { params } = history.getLocationWithParams();
if ( newView.type !== params?.layout ) {
history.push( {
...params,
layout: viewToSet.type,
layout: newView.type,
} );
}
setView( viewToSet );

setView( newView );

if ( isCustom === 'true' && editedEntityRecord?.id ) {
editEntityRecord(
'postType',
'wp_dataviews',
editedEntityRecord?.id,
{
content: JSON.stringify( newView ),
}
);
}
},
[ history, view?.type ]
[ history, isCustom, editedEntityRecord?.id ]
);

if ( isCustom === 'false' ) {
return [ view, setDefaultViewAndUpdateUrl ];
} else if ( isCustom === 'true' && customView ) {
return [ customView, setCustomView ];
}
// When layout URL param changes, update the view type
// without affecting any other config.
useEffect( () => {
setView( ( prevView ) => ( { ...prevView, type: layout } ) );
}, [ layout ] );

// When activeView or isCustom URL parameters change,
// reset the view & update the layout URL param to match the view's type.
useEffect( () => {
let newView;
if ( isCustom === 'true' ) {
newView = getCustomView( editedEntityRecord );
} else {
newView = getDefaultView( defaultViews, activeView );
}

if ( newView ) {
setViewWithUrlUpdate( newView );
}
}, [ activeView, isCustom, defaultViews, editedEntityRecord ] );

// No view was found.
return [ defaultViews[ 0 ].view, setDefaultViewAndUpdateUrl ];
return [ view, setViewWithUrlUpdate ];
}

const DEFAULT_STATUSES = 'draft,future,pending,private,publish'; // All but 'trash'.
Expand Down Expand Up @@ -165,7 +189,7 @@ export default function PostList( { postType } ) {

const queryArgs = useMemo( () => {
const filters = {};
view.filters.forEach( ( filter ) => {
view.filters?.forEach( ( filter ) => {
if (
filter.field === 'status' &&
filter.operator === OPERATOR_IS_ANY
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export const defaultLayouts = {
},
};

const DEFAULT_POST_BASE = {
export const DEFAULT_POST_BASE = {
type: LAYOUT_LIST,
search: '',
filters: [],
Expand Down Expand Up @@ -165,6 +165,8 @@ export function useDefaultViews( { postType } ) {
icon: trash,
view: {
...DEFAULT_POST_BASE,
type: LAYOUT_TABLE,
layout: defaultLayouts[ LAYOUT_TABLE ].layout,
filters: [
{
field: 'status',
Expand Down
36 changes: 1 addition & 35 deletions packages/edit-site/src/components/sidebar-dataviews/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
*/
import { __experimentalItemGroup as ItemGroup } from '@wordpress/components';
import { privateApis as routerPrivateApis } from '@wordpress/router';
import { useRef, useEffect } from '@wordpress/element';
import { usePrevious } from '@wordpress/compose';

/**
* Internal dependencies
Expand All @@ -14,44 +12,12 @@ import { unlock } from '../../lock-unlock';
import DataViewItem from './dataview-item';
import CustomDataViewsList from './custom-dataviews-list';

const { useLocation, useHistory } = unlock( routerPrivateApis );

/**
* Hook to switch to table layout when switching to the trash view.
* When going out of the trash view, it switches back to the previous layout if
* there was an automatic switch to table layout.
*/
function useSwitchToTableOnTrash() {
const {
params: { activeView, layout, ...restParams },
} = useLocation();
const history = useHistory();
const viewToSwitchOutOfTrash = useRef( undefined );
const previousActiveView = usePrevious( activeView );
useEffect( () => {
if ( activeView === 'trash' && previousActiveView !== 'trash' ) {
viewToSwitchOutOfTrash.current = layout || 'list';
history.push( { ...restParams, layout: 'table', activeView } );
} else if (
previousActiveView === 'trash' &&
activeView !== 'trash' &&
viewToSwitchOutOfTrash.current
) {
history.push( {
...restParams,
layout: viewToSwitchOutOfTrash.current,
activeView,
} );
viewToSwitchOutOfTrash.current = undefined;
}
}, [ previousActiveView, activeView, layout, history, restParams ] );
}
const { useLocation } = unlock( routerPrivateApis );

export default function DataViewsSidebarContent() {
const {
params: { postType, activeView = 'all', isCustom = 'false' },
} = useLocation();
useSwitchToTableOnTrash();
const defaultViews = useDefaultViews( { postType } );
if ( ! postType ) {
return null;
Expand Down

0 comments on commit 8c96563

Please sign in to comment.