Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use router instead of internal component state #61

Merged
merged 10 commits into from
Sep 30, 2024
8 changes: 8 additions & 0 deletions src/api/Posts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,14 @@ export class PostsApi {
return makePostFromApiResponse( response );
}

async findById( id: string ): Promise< Post | null > {
// eslint-disable-next-line react/no-is-mounted
const posts = await this.find( { id } );
return posts.length === 0
? null
: makePostFromApiResponse( posts[ 0 ] );
}

async findByGuid( guid: string ): Promise< Post | null > {
// eslint-disable-next-line react/no-is-mounted
const posts = await this.find( { guid } );
Expand Down
12 changes: 8 additions & 4 deletions src/bus/ContentBus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,16 @@ import MessageSender = browser.runtime.MessageSender;
enum Actions {
EnableHighlighting = 1,
DisableHighlighting,
GetCurrentUrl,
GetCurrentPageInfo,
}

async function getCurrentUrl(): Promise< string > {
interface CurrentPageInfo {
url: string;
title: string;
}
async function getCurrentPageInfo(): Promise< CurrentPageInfo > {
return sendMessageToContent( {
action: Actions.GetCurrentUrl,
action: Actions.GetCurrentPageInfo,
payload: {},
} );
}
Expand All @@ -35,7 +39,7 @@ export const ContentBus = {
stopListening,
enableHighlighting,
disableHighlighting,
getCurrentUrl,
getCurrentPageInfo,
};

let listener: (
Expand Down
7 changes: 5 additions & 2 deletions src/extension/content.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,11 @@ ContentBus.listen(
disableHighlightingCursor();
removeStyle();
break;
case ContentBus.actions.GetCurrentUrl:
sendResponse( document.documentURI );
case ContentBus.actions.GetCurrentPageInfo:
sendResponse( {
url: document.documentURI,
title: document.title,
} );
break;
default:
console.error( `Unknown action: ${ message.action }` );
Expand Down
31 changes: 25 additions & 6 deletions src/ui/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
Route,
RouterProvider,
useLocation,
useNavigate,
useRouteLoaderData,
} from 'react-router-dom';
import { StrictMode, useEffect, useState } from 'react';
Expand All @@ -19,14 +20,23 @@
import { PlaceholderPreview } from '@/ui/preview/PlaceholderPreview';
import { SessionContext, SessionProvider } from '@/ui/session/SessionProvider';
import { ApiClient } from '@/api/ApiClient';
import { BlogPostFlow } from '@/ui/flows/blog-post/BlogPostFlow';
import { PlaygroundClient } from '@wp-playground/client';

Check warning on line 23 in src/ui/App.tsx

View workflow job for this annotation

GitHub Actions / lint

PlaygroundClient not found in '@wp-playground/client'
import { Breadcrumbs } from '@/ui/breadcrumbs/Breadcrumbs';
import { NewBlogPost } from '@/ui/flows/blog-post/NewBlogPost';
import { EditBlogPost } from '@/ui/flows/blog-post/EditBlogPost';

export const Screens = {
home: () => '/start/home',
newSession: () => '/start/new-session',
viewSession: ( sessionId: string ) => `/session/${ sessionId }`,
flows: {
blogPost: {
new: ( sessionId: string ) =>
`/session/${ sessionId }/flow/blog-post/new`,
edit: ( sessionId: string, postId: number ) =>
`/session/${ sessionId }/flow/blog-post/${ postId }`,
},
},
flowBlogPost: ( sessionId: string ) =>
`/session/${ sessionId }/flow/blog-post`,
};
Expand Down Expand Up @@ -68,14 +78,18 @@
>
<Route path="" element={ <ViewSession /> } />
<Route path="flow">
<Route path="blog-post" element={ <BlogPostFlow /> } />
<Route path="blog-post">
<Route path="new" element={ <NewBlogPost /> } />
<Route path=":postId" element={ <EditBlogPost /> } />
</Route>
</Route>
</Route>
</Route>
);
}

function App() {
const navigate = useNavigate();
const location = useLocation();
useEffect( () => {
setConfig( { currentPath: location.pathname } ).catch( ( err ) =>
Expand All @@ -95,11 +109,16 @@

// Debugging tools.
useEffect( () => {
if ( ! apiClient || !! ( window as any ).trywp ) {
return;
if ( ! ( window as any ).trywp ) {
( window as any ).trywp = {
navigateTo: ( url: string ) => navigate( url ),
};
}
( window as any ).trywp = { apiClient, playgroundClient };
}, [ apiClient, playgroundClient ] );
if ( apiClient ) {
( window as any ).trywp.apiClient = apiClient;
( window as any ).trywp.playgroundClient = playgroundClient;
}
}, [ apiClient ] );

Check warning on line 121 in src/ui/App.tsx

View workflow job for this annotation

GitHub Actions / lint

React Hook useEffect has missing dependencies: 'navigate' and 'playgroundClient'. Either include them or remove the dependency array

const preview = ! session ? (
<PlaceholderPreview />
Expand Down
10 changes: 10 additions & 0 deletions src/ui/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -106,3 +106,13 @@ ol {
width: 100%;
height: 100%;
}

/* Blog Post Flow */
.flow-blog-post-toolbar {
display: flex;
margin-bottom: 1rem;
}

.flow-blog-post-toolbar button {
margin-left: auto;
}
63 changes: 0 additions & 63 deletions src/ui/flows/blog-post/BlogPostFlow.tsx

This file was deleted.

83 changes: 83 additions & 0 deletions src/ui/flows/blog-post/EditBlogPost.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { useNavigate, useParams } from 'react-router-dom';
import { useEffect, useState } from 'react';
import { useSessionContext } from '@/ui/session/SessionProvider';
import { Post, PostContent, PostDate, PostTitle } from '@/model/Post';
import { SelectContent } from '@/ui/flows/blog-post/SelectContent';
import { Screens } from '@/ui/App';
import { ContentBus } from '@/bus/ContentBus';
import { Toolbar } from '@/ui/flows/blog-post/Toolbar';

export function EditBlogPost() {
const [ post, setPost ] = useState< Post >();
const { postId } = useParams();
const { session, apiClient, playgroundClient } = useSessionContext();
const navigate = useNavigate();

useEffect( () => {
if ( ! apiClient ) {
return;
}
apiClient.posts.findById( postId! ).then( ( p: Post | null ) => {
if ( ! p ) {
// This can happen when the app initially loads with a URL that was saved in local storage.
// Instead of throwing an error, we just send the user to the "new blog post" screen.
navigate( Screens.flows.blogPost.new( session.id ) );
return;
}
setPost( p );
playgroundClient.goTo( p.url );
} );
}, [ apiClient, postId ] );

Check warning on line 30 in src/ui/flows/blog-post/EditBlogPost.tsx

View workflow job for this annotation

GitHub Actions / lint

React Hook useEffect has missing dependencies: 'navigate', 'playgroundClient', and 'session.id'. Either include them or remove the dependency array

const isValid =
!! post &&
post.title.original !== '' &&
post.date.original !== '' &&
post.content.original !== '';

return (
<>
{ ! post ? (
'Loading...'
) : (
<>
<Toolbar>
<button
disabled={ ! isValid }
onClick={ async () => {
await ContentBus.disableHighlighting();
console.log( 'TODO: import' );
} }
>
Import
</button>
</Toolbar>
<SelectContent
post={ post }
onDateChanged={ async ( date: PostDate ) => {
const p = await apiClient!.posts.update( post.id, {
date,
} );
setPost( p );
void playgroundClient.goTo( post.url );
} }
onTitleChanged={ async ( title: PostTitle ) => {
const p = await apiClient!.posts.update( post.id, {
title,
} );
setPost( p );
void playgroundClient.goTo( post.url );
} }
onContentChanged={ async ( content: PostContent ) => {
const p = await apiClient!.posts.update( post.id, {
content,
} );
setPost( p );
void playgroundClient.goTo( post.url );
} }
/>
</>
) }
</>
);
}
7 changes: 0 additions & 7 deletions src/ui/flows/blog-post/Finish.tsx

This file was deleted.

61 changes: 61 additions & 0 deletions src/ui/flows/blog-post/NewBlogPost.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { useEffect, useState } from 'react';
import { ContentBus } from '@/bus/ContentBus';
import { useSessionContext } from '@/ui/session/SessionProvider';
import { useNavigate } from 'react-router-dom';
import { Screens } from '@/ui/App';
import { Toolbar } from '@/ui/flows/blog-post/Toolbar';

export function NewBlogPost() {
const navigate = useNavigate();
const [ isLoading, setIsLoading ] = useState( true );
const { session, apiClient } = useSessionContext();

// Check if there is already a post for the page that is currently active in the source site,
// and if yes, redirect to that post.
useEffect( () => {
if ( ! apiClient ) {
return;
}
async function maybeRedirect() {
const currentPage = await ContentBus.getCurrentPageInfo();
const post = await apiClient!.posts.findByGuid( currentPage.url );
if ( post ) {
navigate( Screens.flows.blogPost.edit( session.id, post.id ) );
return;
}
setIsLoading( false );
}
maybeRedirect().catch( ( err ) => console.log( err ) );
}, [ session.id, apiClient ] );

Check warning on line 29 in src/ui/flows/blog-post/NewBlogPost.tsx

View workflow job for this annotation

GitHub Actions / lint

React Hook useEffect has a missing dependency: 'navigate'. Either include it or remove the dependency array

const element = (
<>
<Toolbar>
<button
onClick={ async () => {
const currentPage =
await ContentBus.getCurrentPageInfo();
let post = await apiClient!.posts.findByGuid(
currentPage.url
);
if ( ! post ) {
post = await apiClient!.posts.create( {
guid: currentPage.url,
} );
}
navigate(
Screens.flows.blogPost.edit( session.id, post.id )
);
} }
>
Continue
</button>
</Toolbar>
<div>
Navigate to the page of the post you&apos;d like to import
</div>
</>
);

return <>{ isLoading ? 'Loading...' : element }</>;
}
Loading
Loading