From 858d7f94adbb9e2e614bedfbea724dfaa124e6e6 Mon Sep 17 00:00:00 2001 From: Przemek Kuliga Date: Wed, 21 Aug 2024 22:35:04 +0200 Subject: [PATCH] Subscriptions: Add content summary modal to Paid Subscribers importer (#93773) * add modal * renaming things * shows real data * Add attachment and page numbers to the import summary --------- Co-authored-by: Enej Bajgoric --- .../content-upload/file-importer.jsx | 40 ++++++++++++++++--- .../content-upload/import-summary-modal.tsx | 36 +++++++++++++++++ .../my-sites/importer/newsletter/content.tsx | 6 ++- client/state/action-types.ts | 2 + client/state/imports/actions.js | 12 ++++++ client/state/imports/reducer.js | 20 ++++++++++ 6 files changed, 110 insertions(+), 6 deletions(-) create mode 100644 client/my-sites/importer/newsletter/content-upload/import-summary-modal.tsx diff --git a/client/my-sites/importer/newsletter/content-upload/file-importer.jsx b/client/my-sites/importer/newsletter/content-upload/file-importer.jsx index f6d2f7664d75c0..ce40157444f317 100644 --- a/client/my-sites/importer/newsletter/content-upload/file-importer.jsx +++ b/client/my-sites/importer/newsletter/content-upload/file-importer.jsx @@ -6,8 +6,14 @@ import { PureComponent } from 'react'; import { connect } from 'react-redux'; import ErrorPane from 'calypso/my-sites/importer/error-pane'; import { recordTracksEvent } from 'calypso/state/analytics/actions'; -import { startImport, cancelImport } from 'calypso/state/imports/actions'; +import { + startImport, + cancelImport, + openSummaryModal, + closeSummaryModal, +} from 'calypso/state/imports/actions'; import { appStates } from 'calypso/state/imports/constants'; +import ImportSummaryModal from './import-summary-modal'; import ImportingPane from './importing-pane'; import UploadingPane from './uploading-pane'; @@ -47,6 +53,7 @@ class FileImporter extends PureComponent { importerState: PropTypes.string.isRequired, statusMessage: PropTypes.string, type: PropTypes.string.isRequired, + summaryModalOpen: PropTypes.bool, } ), site: PropTypes.shape( { ID: PropTypes.number.isRequired, @@ -75,7 +82,7 @@ class FileImporter extends PureComponent { render() { const { title, overrideDestination, uploadDescription, optionalUrl } = this.props.importerData; const { importerStatus, site, fromSite, nextStepUrl, skipNextStep } = this.props; - const { errorData, importerState } = importerStatus; + const { errorData, importerState, summaryModalOpen } = importerStatus; const isEnabled = appStates.DISABLED !== importerState; const showStart = includes( compactStates, importerState ); const cardClasses = clsx( 'importer__file-importer-card', { @@ -100,6 +107,14 @@ class FileImporter extends PureComponent { cardProps.onClick = this.handleClick.bind( this, false ); } + if ( importerState === appStates.UPLOAD_SUCCESS && ! summaryModalOpen ) { + this.props.openSummaryModal( importerStatus.importerId ); + } + + const showImportingPane = + includes( importingStates, importerState ) && summaryModalOpen === false; + const showUploadingPane = includes( uploadingStates, importerState ) || summaryModalOpen; + return ( { errorData && ( @@ -113,7 +128,16 @@ class FileImporter extends PureComponent { } } /> ) } - { includes( importingStates, importerState ) && ( + { summaryModalOpen && ( + this.props.closeSummaryModal( importerStatus.importerId ) } + postsNumber={ importerStatus?.customData?.postsNumber || 0 } + pagesNumber={ importerStatus?.customData?.pagesNumber || 0 } + attachmentsNumber={ importerStatus?.customData?.attachmentsNumber || 0 } + authorsNumber={ importerStatus?.customData?.sourceAuthors.length } + /> + ) } + { showImportingPane && ( ) } - { includes( uploadingStates, importerState ) && ( + { showUploadingPane && ( void; + postsNumber: number; + pagesNumber: number; + attachmentsNumber: number; + authorsNumber?: number; +} + +export default function ImportSummaryModal( { + onRequestClose, + postsNumber, + pagesNumber, + attachmentsNumber, + authorsNumber, +}: ImportSummaryModalProps ) { + return ( + +

+ We’ve found { postsNumber } posts, { pagesNumber } pages{ ' ' } + and { attachmentsNumber } media to import. + { authorsNumber && ( + <> +
+ Your Substack publication has { authorsNumber } authors. Next, you can + match them with existing site users. + + ) } +

+ +
+ ); +} diff --git a/client/my-sites/importer/newsletter/content.tsx b/client/my-sites/importer/newsletter/content.tsx index 3f0b941ea39c98..3164e6bee06744 100644 --- a/client/my-sites/importer/newsletter/content.tsx +++ b/client/my-sites/importer/newsletter/content.tsx @@ -32,6 +32,7 @@ export default function Content( { const siteImports = useSelector( ( state ) => getImporterStatusForSiteId( state, siteId ) ); const dispatch = useDispatch(); + function fetchImporters() { siteId && dispatch( fetchImporterState( siteId ) ); } @@ -58,11 +59,14 @@ export default function Content( { siteTitle, } ).substack; + const showStepDescriptions = + importerStatus?.importerState !== appStates.MAP_AUTHORS || importerStatus?.summaryModalOpen; + return ( - { importerStatus?.importerState !== appStates.MAP_AUTHORS && ( + { showStepDescriptions && ( <>

Step 1: Export your content from Substack

diff --git a/client/state/action-types.ts b/client/state/action-types.ts index ce2c244deae583..e9dcc3dc4a7d59 100644 --- a/client/state/action-types.ts +++ b/client/state/action-types.ts @@ -316,6 +316,8 @@ export const IMPORTS_UPLOAD_FAILED = 'IMPORTS_UPDLOAD_FAILED'; export const IMPORTS_PRE_UPLOAD_FAILED = 'IMPORTS_PRE_UPDLOAD_FAILED'; export const IMPORTS_UPLOAD_SET_PROGRESS = 'IMPORTS_UPLOAD_SET_PROGRESS'; export const IMPORTS_UPLOAD_START = 'IMPORTS_UPLOAD_START'; +export const IMPORTS_SUMMARY_MODAL_OPEN = 'IMPORTS_SUMMARY_MODAL_OPEN'; +export const IMPORTS_SUMMARY_MODAL_CLOSE = 'IMPORTS_SUMMARY_MODAL_CLOSE'; export const INVITE_ACCEPTED = 'INVITE_ACCEPTED'; export const INVITE_RESEND_REQUEST = 'INVITE_RESEND_REQUEST'; export const INVITE_RESEND_REQUEST_FAILURE = 'INVITE_RESEND_REQUEST_FAILURE'; diff --git a/client/state/imports/actions.js b/client/state/imports/actions.js index 00aefc697a3cb2..dd040036c88c88 100644 --- a/client/state/imports/actions.js +++ b/client/state/imports/actions.js @@ -15,6 +15,8 @@ import { IMPORTS_UPLOAD_COMPLETED, IMPORTS_UPLOAD_SET_PROGRESS, IMPORTS_UPLOAD_START, + IMPORTS_SUMMARY_MODAL_OPEN, + IMPORTS_SUMMARY_MODAL_CLOSE, } from 'calypso/state/action-types'; import { fromApi, toApi } from './api'; import { appStates } from './constants'; @@ -257,6 +259,16 @@ export const startUpload = } ); }; +export const openSummaryModal = ( importerId ) => ( { + type: IMPORTS_SUMMARY_MODAL_OPEN, + importerId, +} ); + +export const closeSummaryModal = ( importerId ) => ( { + type: IMPORTS_SUMMARY_MODAL_CLOSE, + importerId, +} ); + export const failPreUpload = ( importerId, message, code, file ) => ( { type: IMPORTS_PRE_UPLOAD_FAILED, importerId, diff --git a/client/state/imports/reducer.js b/client/state/imports/reducer.js index 0dedda8d993deb..ec1814017d76e0 100644 --- a/client/state/imports/reducer.js +++ b/client/state/imports/reducer.js @@ -16,6 +16,8 @@ import { IMPORTS_UPLOAD_COMPLETED, IMPORTS_UPLOAD_SET_PROGRESS, IMPORTS_UPLOAD_START, + IMPORTS_SUMMARY_MODAL_OPEN, + IMPORTS_SUMMARY_MODAL_CLOSE, } from 'calypso/state/action-types'; import { combineReducers, keyedReducer } from 'calypso/state/utils'; import { fromApi } from './api'; @@ -165,6 +167,24 @@ function importerStatus( state = {}, action ) { filename: action.filename, }, }; + + case IMPORTS_SUMMARY_MODAL_OPEN: + return { + ...state, + [ action.importerId ]: { + ...state[ action.importerId ], + summaryModalOpen: true, + }, + }; + + case IMPORTS_SUMMARY_MODAL_CLOSE: + return { + ...state, + [ action.importerId ]: { + ...state[ action.importerId ], + summaryModalOpen: false, + }, + }; } return state;