File "index.js"
Full Path: /home/warrior1/public_html/wp-content/plugins/elementor/app/modules/kit-library/assets/js/pages/index/index.js
File size: 9.1 KB
MIME-type: text/x-java
Charset: utf-8
import Content from '../../../../../../assets/js/layout/content';
import EnvatoPromotion from '../../components/envato-promotion';
import ErrorScreen from '../../components/error-screen';
import FilterIndicationText from '../../components/filter-indication-text';
import IndexHeader from './index-header';
import IndexSidebar from './index-sidebar';
import KitList from '../../components/kit-list';
import Layout from '../../components/layout';
import PageLoader from '../../components/page-loader';
import SearchInput from '../../components/search-input';
import SortSelect from '../../components/sort-select';
import TaxonomiesFilter from '../../components/taxonomies-filter';
import useKits, { defaultQueryParams } from '../../hooks/use-kits';
import usePageTitle from 'elementor-app/hooks/use-page-title';
import useTaxonomies from '../../hooks/use-taxonomies';
import { Grid } from '@elementor/app-ui';
import { useCallback, useMemo, useEffect } from 'react';
import { useLastFilterContext } from '../../context/last-filter-context';
import { useLocation } from '@reach/router';
import { appsEventTrackingDispatch } from 'elementor-app/event-track/apps-event-tracking';
import './index.scss';
/**
* Generate select and unselect taxonomy functions.
*
* @param {Function} setQueryParams
* @return {((function(*, *): *)|(function(*=): *))[]} taxonomy functions
*/
function useTaxonomiesSelection( setQueryParams ) {
const selectTaxonomy = useCallback( ( type, callback ) => setQueryParams(
( prev ) => {
const taxonomies = { ...prev.taxonomies };
taxonomies[ type ] = callback( prev.taxonomies[ type ] );
return { ...prev, taxonomies };
},
), [ setQueryParams ] );
const unselectTaxonomy = useCallback( ( taxonomy ) => setQueryParams( ( prev ) => {
const taxonomies = Object.entries( prev.taxonomies )
.reduce( ( current, [ key, groupedTaxonomies ] ) => ( {
...current,
[ key ]: groupedTaxonomies.filter( ( item ) => item !== taxonomy ),
} ), {} );
return { ...prev, taxonomies };
} ), [ setQueryParams ] );
return [ selectTaxonomy, unselectTaxonomy ];
}
/**
* Generate the menu items for the index page.
*
* @param {string} path
* @return {Array} menu items
*/
function useMenuItems( path ) {
return useMemo( () => {
const page = path.replace( '/', '' );
return [
{
label: __( 'All Website Kits', 'elementor' ),
icon: 'eicon-filter',
isActive: ! page,
url: '/kit-library',
trackEventData: { command: 'kit-library/select-organizing-category', category: 'all' },
},
{
label: __( 'Favorites', 'elementor' ),
icon: 'eicon-heart-o',
isActive: 'favorites' === page,
url: '/kit-library/favorites',
trackEventData: { command: 'kit-library/select-organizing-category', category: 'favorites' },
},
];
}, [ path ] );
}
/**
* Update and read the query param from the url
*
* @param {*} queryParams
* @param {*} setQueryParams
* @param {Array<string>} exclude
*/
function useRouterQueryParams( queryParams, setQueryParams, exclude = [] ) {
const location = useLocation(),
{ setLastFilter } = useLastFilterContext();
useEffect( () => {
const filteredQueryParams = Object.fromEntries(
Object.entries( queryParams )
.filter( ( [ key, item ] ) => ! exclude.includes( key ) && item ),
);
setLastFilter( filteredQueryParams );
history.replaceState(
null,
'',
decodeURI(
`#${ wp.url.addQueryArgs( location.pathname.split( '?' )[ 0 ] || '/', filteredQueryParams ) }`,
),
);
}, [ queryParams ] );
useEffect( () => {
const routerQueryParams = Object.keys( defaultQueryParams ).reduce( ( current, key ) => {
// TODO: Replace with `wp.url.getQueryArgs` when WordPress 5.7 is the min version
const queryArg = wp.url.getQueryArg( location.pathname, key );
if ( ! queryArg ) {
return current;
}
return {
...current,
[ key ]: queryArg,
};
}, {} );
setQueryParams( ( prev ) => ( {
...prev,
...routerQueryParams,
taxonomies: {
...prev.taxonomies,
...routerQueryParams.taxonomies,
},
ready: true,
} ) );
}, [] );
}
export default function Index( props ) {
usePageTitle( {
title: __( 'Kit Library', 'elementor' ),
} );
const menuItems = useMenuItems( props.path );
const {
data,
isSuccess,
isLoading,
isFetching,
isError,
queryParams,
setQueryParams,
clearQueryParams,
forceRefetch,
isFilterActive,
} = useKits( props.initialQueryParams );
useRouterQueryParams( queryParams, setQueryParams, [ 'ready', ...Object.keys( props.initialQueryParams ) ] );
const {
data: taxonomiesData,
forceRefetch: forceRefetchTaxonomies,
isFetching: isFetchingTaxonomies,
} = useTaxonomies();
const [ selectTaxonomy, unselectTaxonomy ] = useTaxonomiesSelection( setQueryParams );
const eventTracking = ( command, elementPosition, search = null, direction = null, sortType = null, action = null, eventType = 'click' ) => {
appsEventTrackingDispatch(
command,
{
page_source: 'home page',
element_position: elementPosition,
search_term: search,
sort_direction: direction,
sort_type: sortType,
event_type: eventType,
action,
},
);
};
return (
<Layout
sidebar={
<IndexSidebar
tagsFilterSlot={ <TaxonomiesFilter
selected={ queryParams.taxonomies }
onSelect={ selectTaxonomy }
taxonomies={ taxonomiesData }
category={ props.path }
/> }
menuItems={ menuItems }
/>
}
header={
<IndexHeader
refetch={ () => {
forceRefetch();
forceRefetchTaxonomies();
} }
isFetching={ isFetching || isFetchingTaxonomies }
/>
}
>
<div className="e-kit-library__index-layout-container">
<Grid container className="e-kit-library__index-layout-top-area">
<Grid item className="e-kit-library__index-layout-top-area-search">
<SearchInput
// eslint-disable-next-line @wordpress/i18n-ellipsis
placeholder={ __( 'Search all Website Kits...', 'elementor' ) }
value={ queryParams.search }
onChange={ ( value ) => {
setQueryParams( ( prev ) => ( { ...prev, search: value } ) );
eventTracking( 'kit-library/kit-free-search', 'top_area_search', value, null, null, null, 'search' );
} }
/>
{ isFilterActive && <FilterIndicationText
queryParams={ queryParams }
resultCount={ data.length || 0 }
onClear={ clearQueryParams }
onRemoveTag={ unselectTaxonomy }
/> }
</Grid>
<Grid
item
className="e-kit-library__index-layout-top-area-sort"
>
<SortSelect
options={ [
{
label: __( 'Featured', 'elementor' ),
value: 'featuredIndex',
defaultOrder: 'asc',
orderDisabled: true,
},
{
label: __( 'New', 'elementor' ),
value: 'createdAt',
defaultOrder: 'desc',
},
{
label: __( 'Popular', 'elementor' ),
value: 'popularityIndex',
defaultOrder: 'desc',
},
{
label: __( 'Trending', 'elementor' ),
value: 'trendIndex',
defaultOrder: 'desc',
},
] }
value={ queryParams.order }
onChange={ ( order ) => setQueryParams( ( prev ) => ( { ...prev, order } ) ) }
onChangeSortDirection={ ( direction ) => eventTracking( 'kit-library/change-sort-direction', 'top_area_sort', null, direction ) }
onChangeSortValue={ ( value ) => eventTracking( 'kit-library/change-sort-value', 'top_area_sort', null, null, value ) }
onSortSelectOpen={ () => eventTracking( 'kit-library/change-sort-type', 'top_area_sort', null, null, null, 'expand' ) }
/>
</Grid>
</Grid>
<Content className="e-kit-library__index-layout-main">
<>
{ isLoading && <PageLoader /> }
{
isError && <ErrorScreen
title={ __( 'Something went wrong.', 'elementor' ) }
description={ __( 'Nothing to worry about, use 🔄 on the top right to try again. If the problem continues, head over to the Help Center.', 'elementor' ) }
button={ {
text: __( 'Learn More', 'elementor' ),
url: 'http://go.elementor.com/app-kit-library-error/',
target: '_blank',
} }
/>
}
{ isSuccess && 0 < data.length && queryParams.ready && <KitList data={ data } queryParams={ queryParams } source={ props.path } /> }
{
isSuccess && 0 === data.length && queryParams.ready && props.renderNoResultsComponent( {
defaultComponent: <ErrorScreen
title={ __( 'No results matched your search.', 'elementor' ) }
description={ __( 'Try different keywords or ', 'elementor' ) }
button={ {
text: __( 'Continue browsing.', 'elementor' ),
action: clearQueryParams,
category: props.path,
} }
/>,
isFilterActive,
} )
}
<EnvatoPromotion category={ props.path } />
</>
</Content>
</div>
</Layout>
);
}
Index.propTypes = {
path: PropTypes.string,
initialQueryParams: PropTypes.object,
renderNoResultsComponent: PropTypes.func,
};
Index.defaultProps = {
initialQueryParams: {},
renderNoResultsComponent: ( { defaultComponent } ) => defaultComponent,
};