diff --git a/client/dashboard/customizable.js b/client/dashboard/customizable.js index 8c36685cf5..f11e79c598 100644 --- a/client/dashboard/customizable.js +++ b/client/dashboard/customizable.js @@ -32,7 +32,7 @@ import { import ReportFilters from 'analytics/components/report-filters'; const TaskList = lazy( () => - import( /* webpackChunkName: "task-list" */ './task-list' ) + import( /* webpackChunkName: "task-list" */ '../task-list' ) ); const DASHBOARD_FILTERS_FILTER = 'woocommerce_admin_dashboard_filters'; @@ -311,10 +311,7 @@ class CustomizableDashboard extends Component { { isTaskListEnabled && ( }> - + ) } { isDashboardShown && this.renderDashboardReports() } diff --git a/client/dashboard/task-list/tasks/payments/images/bacs.js b/client/dashboard/task-list/tasks/payments/images/bacs.js deleted file mode 100644 index be355ac90d..0000000000 --- a/client/dashboard/task-list/tasks/payments/images/bacs.js +++ /dev/null @@ -1,24 +0,0 @@ -export default () => ( - - - - - - - - - - - - - - - - - - - - - - -); diff --git a/client/dashboard/task-list/tasks/payments/images/cod.js b/client/dashboard/task-list/tasks/payments/images/cod.js deleted file mode 100644 index 41d413cd6c..0000000000 --- a/client/dashboard/task-list/tasks/payments/images/cod.js +++ /dev/null @@ -1,24 +0,0 @@ -export default () => ( - - - - - - - - - - - - - - - - - - - - - - -); diff --git a/client/homepage/index.js b/client/homepage/index.js index 8f21a57851..0a3c6b5404 100644 --- a/client/homepage/index.js +++ b/client/homepage/index.js @@ -29,7 +29,7 @@ const Homepage = ( { profileItems, query } ) => { ); } - return ; + return ; }; export default compose( diff --git a/client/homepage/layout.js b/client/homepage/layout.js index 96c725b413..bddcc0e0d9 100644 --- a/client/homepage/layout.js +++ b/client/homepage/layout.js @@ -1,9 +1,24 @@ /** * External dependencies */ -import { useState, useRef, useEffect } from '@wordpress/element'; +import { + Fragment, + Suspense, + lazy, + useState, + useRef, + useEffect, +} from '@wordpress/element'; import { Button } from '@wordpress/components'; +import { compose } from '@wordpress/compose'; import classnames from 'classnames'; +import { get } from 'lodash'; +import PropTypes from 'prop-types'; + +/** + * WooCommerce dependencies + */ +import { Spinner } from '@woocommerce/components'; /** * Internal dependencies @@ -11,8 +26,15 @@ import classnames from 'classnames'; import QuickLinks from '../quick-links'; import StatsOverview from './stats-overview'; import './style.scss'; +import { isOnboardingEnabled } from 'dashboard/utils'; +import withSelect from 'wc-api/with-select'; +import TaskListPlaceholder from '../task-list/placeholder'; -const Layout = () => { +const TaskList = lazy( () => + import( /* webpackChunkName: "task-list" */ '../task-list' ) +); + +export const Layout = ( props ) => { const [ showInbox, setShowInbox ] = useState( true ); const [ isContentSticky, setIsContentSticky ] = useState( false ); const content = useRef( null ); @@ -35,45 +57,114 @@ const Layout = () => { }; }, [] ); + const { query, requestingTaskList, taskListHidden } = props; + const isTaskListEnabled = taskListHidden === false; + const isDashboardShown = ! isTaskListEnabled || ! query.task; + + const renderColumns = () => { + return ( + + { showInbox && ( +
+
+ +
+
+
+
+
+
+
+
+ ) } +
+ { isTaskListEnabled && renderTaskList() } + + +
+ + ); + }; + + const renderTaskList = () => { + if ( requestingTaskList ) { + return ; + } + + return ( + }> + + + ); + }; + return (
- { showInbox && ( -
-
- -
-
-
-
-
-
-
-
- ) } -
- - - -
+ { isDashboardShown + ? renderColumns() + : isTaskListEnabled && renderTaskList() + }
); }; -export default Layout; +Layout.propTypes = { + /** + * If the task list option is being fetched. + */ + requestingTaskList: PropTypes.bool.isRequired, + /** + * If the task list is hidden. + */ + taskListHidden: PropTypes.bool, + /** + * Page query, used to determine the current task if any. + */ + query: PropTypes.object.isRequired, +}; + +export default compose( + withSelect( ( select ) => { + const { + getOptions, + isGetOptionsRequesting, + } = select( 'wc-api' ); + + if ( isOnboardingEnabled() ) { + const options = getOptions( [ + 'woocommerce_task_list_hidden', + ] ); + + return { + requestingTaskList: isGetOptionsRequesting( [ + 'woocommerce_task_list_hidden', + ] ), + taskListHidden: get( options, [ 'woocommerce_task_list_hidden' ] ) === 'yes', + }; + } + + return { + requestingTaskList: false, + }; + } ) +)( Layout ); diff --git a/client/homepage/style.scss b/client/homepage/style.scss index 7a33dcb4b7..5fca1a774d 100644 --- a/client/homepage/style.scss +++ b/client/homepage/style.scss @@ -9,6 +9,10 @@ margin: 0 auto; justify-content: space-between; + .woocommerce-task-dashboard__container { + width: 100%; + } + &.hasInbox .woocommerce-homepage-column { width: calc(50% - 12px); margin: 0; diff --git a/client/homepage/test/index.js b/client/homepage/test/index.js new file mode 100644 index 0000000000..6323a6fbba --- /dev/null +++ b/client/homepage/test/index.js @@ -0,0 +1,64 @@ +/** + * External dependencies + */ +import { render, screen } from '@testing-library/react'; +import { Layout } from '../layout'; + +// Rendering breaks tests. +jest.mock( 'homepage/stats-overview', () => jest.fn().mockReturnValue( null ) ); + +// We aren't testing the component here. +jest.mock( 'task-list', () => jest.fn().mockReturnValue( '[TaskList]' ) ); + +describe( 'Homepage Layout', () => { + it( 'should show TaskList placeholder when loading', () => { + const { container } = render( + + ); + + const placeholder = container.querySelector( '.woocommerce-task-card.is-loading' ); + expect( placeholder ).not.toBeNull(); + } ); + + it( 'should show TaskList inline', async () => { + const { container } = render( + + ); + + // Expect that we're rendering the "full" home screen (with columns). + const columns = container.querySelector( '.woocommerce-homepage-column' ); + expect( columns ).not.toBeNull(); + + // Expect that the is there too. + const taskList = await screen.findByText( '[TaskList]' ) + expect( taskList ).toBeDefined(); + } ); + + it( 'should render TaskList alone when on task', async () => { + const { container } = render( + + ); + + // Expect that we're NOT rendering the "full" home screen (with columns). + const columns = container.querySelector( '.woocommerce-homepage-column' ); + expect( columns ).toBeNull(); + + // Expect that the is there though. + const taskList = await screen.findByText( '[TaskList]' ) + expect( taskList ).toBeDefined(); + } ); +} ); diff --git a/client/dashboard/task-list/index.js b/client/task-list/index.js similarity index 97% rename from client/dashboard/task-list/index.js rename to client/task-list/index.js index b35c7752d4..7366e67dd5 100644 --- a/client/dashboard/task-list/index.js +++ b/client/task-list/index.js @@ -20,7 +20,7 @@ import { PLUGINS_STORE_NAME } from '@woocommerce/data'; * Internal dependencies */ import './style.scss'; -import CartModal from '../components/cart-modal'; +import CartModal from 'dashboard/components/cart-modal'; import { getAllTasks } from './tasks'; import { recordEvent } from 'lib/tracks'; import withSelect from 'wc-api/with-select'; @@ -410,12 +410,12 @@ class TaskDashboard extends Component { export default compose( withSelect( ( select, props ) => { - const { getProfileItems, getOptions } = select( - 'wc-api' - ); - const { getActivePlugins, getInstalledPlugins, isJetpackConnected } = select( - PLUGINS_STORE_NAME - ); + const { getProfileItems, getOptions } = select( 'wc-api' ); + const { + getActivePlugins, + getInstalledPlugins, + isJetpackConnected, + } = select( PLUGINS_STORE_NAME ); const profileItems = getProfileItems(); const options = getOptions( [ diff --git a/client/task-list/placeholder.js b/client/task-list/placeholder.js new file mode 100644 index 0000000000..47cbb6c6df --- /dev/null +++ b/client/task-list/placeholder.js @@ -0,0 +1,56 @@ +/** + * Internal dependencies + */ +import './style.scss'; + +const TaskListPlaceholder = ( props ) => { + const { + numTasks = 5, + } = props; + return ( +
+
+
+
+
+ +
+
+ +
+
+
+
+
+ { Array.from( new Array( numTasks ) ).map( ( v, i ) => ( +
+
+
+ +
+
+
+ +
+
+ +
+ +
+
+ +
+
+
+ ) ) } +
+
+
+
+ ); +}; + +export default TaskListPlaceholder; diff --git a/client/dashboard/task-list/style.scss b/client/task-list/style.scss similarity index 92% rename from client/dashboard/task-list/style.scss rename to client/task-list/style.scss index 8411b5f862..473e6a3cc8 100644 --- a/client/dashboard/task-list/style.scss +++ b/client/task-list/style.scss @@ -550,3 +550,59 @@ padding-bottom: 10px; } } + +.woocommerce-task-dashboard__container { + .woocommerce-task-card.is-loading { + .is-placeholder { + @include placeholder(); + display: inline-block; + height: 16px; + } + + .woocommerce-card__title { + .is-placeholder { + width: 70%; + height: 28px; + } + } + + .woocommerce-card__description { + .is-placeholder { + width: 90%; + height: 24px; + } + } + + .woocommerce-list__item-before { + .is-placeholder { + height: 36px; + width: 36px; + } + } + + .woocommerce-list__item-text { + width: 100%; + + .woocommerce-list__item-title { + .is-placeholder { + height: 22px; + width: 60%; + } + } + + .woocommerce-list__item-content { + .is-placeholder { + height: 20px; + width: 80%; + } + } + } + + .woocommerce-list__item-after { + .is-placeholder { + height: 24px; + width: 24px; + } + } + } +} diff --git a/client/dashboard/task-list/tasks.js b/client/task-list/tasks.js similarity index 100% rename from client/dashboard/task-list/tasks.js rename to client/task-list/tasks.js diff --git a/client/dashboard/task-list/tasks/appearance.js b/client/task-list/tasks/appearance.js similarity index 96% rename from client/dashboard/task-list/tasks/appearance.js rename to client/task-list/tasks/appearance.js index c66ee803e1..9dbdfd3802 100644 --- a/client/dashboard/task-list/tasks/appearance.js +++ b/client/task-list/tasks/appearance.js @@ -192,20 +192,24 @@ class Appearance extends Component { path: '/wc-admin/onboarding/tasks/create_homepage', method: 'POST', } ) - .then( response => { + .then( ( response ) => { createNotice( response.status, response.message, { actions: response.edit_post_link ? [ { - label: __( 'Customize', 'woocommerce-admin' ), + label: __( + 'Customize', + 'woocommerce-admin' + ), onClick: () => { - queueRecordEvent( 'tasklist_appearance_customize_homepage', {} ); - window.location = `${ - response.edit_post_link - }&wc_onboarding_active_task=homepage`; + queueRecordEvent( + 'tasklist_appearance_customize_homepage', + {} + ); + window.location = `${ response.edit_post_link }&wc_onboarding_active_task=homepage`; }, }, - ] + ] : null, } ); @@ -296,7 +300,11 @@ class Appearance extends Component { ), content: ( -