Skip to content

Commit

Permalink
Merge pull request #971 from logto-io/charles-log-10635-docs-tutorial…
Browse files Browse the repository at this point in the history
…-a-x-b-cross-selection-list-page

refactor: docs tutorial a x b cross selection list page
  • Loading branch information
charIeszhao authored Jan 20, 2025
2 parents 2a0b37b + 92babfe commit b6d698b
Show file tree
Hide file tree
Showing 26 changed files with 617 additions and 131 deletions.
1 change: 1 addition & 0 deletions docusaurus.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,7 @@ const config: Config = {
path: './tutorial',
blogSidebarCount: 0,
showReadingTime: false,
postsPerPage: 'ALL',
},
],
[
Expand Down
4 changes: 2 additions & 2 deletions i18n/de/code.json
Original file line number Diff line number Diff line change
Expand Up @@ -483,10 +483,10 @@
"message": "Datenschutz"
},
"theme.common.sdk.placeholder": {
"message": "Ihr SDK"
"message": "dein SDK"
},
"theme.common.connector.placeholder": {
"message": "Ihr Anbieter"
"message": "dein anbieter"
},
"theme.common.sdk.native": {
"message": "Nativ"
Expand Down
4 changes: 2 additions & 2 deletions i18n/es/code.json
Original file line number Diff line number Diff line change
Expand Up @@ -483,10 +483,10 @@
"message": "Privacidad"
},
"theme.common.sdk.placeholder": {
"message": "Tu SDK"
"message": "tu SDK"
},
"theme.common.connector.placeholder": {
"message": "Tu proveedor"
"message": "tu proveedor"
},
"theme.common.sdk.native": {
"message": "Nativo"
Expand Down
4 changes: 2 additions & 2 deletions i18n/fr/code.json
Original file line number Diff line number Diff line change
Expand Up @@ -483,10 +483,10 @@
"message": "Confidentialité"
},
"theme.common.sdk.placeholder": {
"message": "Votre SDK"
"message": "ton SDK"
},
"theme.common.connector.placeholder": {
"message": "Votre fournisseur"
"message": "ton fournisseur"
},
"theme.common.sdk.native": {
"message": "Natif"
Expand Down
4 changes: 2 additions & 2 deletions i18n/pt-BR/code.json
Original file line number Diff line number Diff line change
Expand Up @@ -483,10 +483,10 @@
"message": "Privacidade"
},
"theme.common.sdk.placeholder": {
"message": "Seu SDK"
"message": "seu SDK"
},
"theme.common.connector.placeholder": {
"message": "Seu provedor"
"message": "seu provedor"
},
"theme.common.sdk.native": {
"message": "Nativo"
Expand Down
8 changes: 4 additions & 4 deletions plugins/tutorial-generator/utils.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { type DocMetadata } from '@docusaurus/plugin-content-docs';

export const getSdkDisplayName = (sdk: DocMetadata) =>
String(sdk.frontMatter.tutorial_name ?? sdk.frontMatter.sidebar_label ?? '');
export const getSdkDisplayName = (sdk?: DocMetadata) =>
String(sdk?.frontMatter.tutorial_name ?? sdk?.frontMatter.sidebar_label ?? '');

export const getConnectorDisplayName = (connector: DocMetadata) =>
String(connector.frontMatter.tutorial_name ?? connector.frontMatter.sidebar_label ?? '');
export const getConnectorDisplayName = (connector?: DocMetadata) =>
String(connector?.frontMatter.tutorial_name ?? connector?.frontMatter.sidebar_label ?? '');

export const getSdkPath = (metadata: DocMetadata) => {
const sdkName = String(metadata.frontMatter.tutorial_name ?? '');
Expand Down
24 changes: 14 additions & 10 deletions src/hooks/use-categorized-tutorial-metadata.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { type DocMetadata } from '@docusaurus/plugin-content-docs';
import { useMemo } from 'react';

import metadata from '@site/tutorial/build-with-logto/metadata.json';

Expand Down Expand Up @@ -47,16 +48,19 @@ const useCategorizedTutorialMetadata = () => {
{ nativeSdks: [], traditionalSdks: [], spaSdks: [] }
);

return {
allSdks: sdks,
allConnectors: [...socialConnectors, ...emailConnectors, ...smsConnectors],
nativeSdks,
traditionalSdks,
spaSdks,
socialConnectors,
emailConnectors,
smsConnectors,
};
return useMemo(
() => ({
allSdks: sdks,
allConnectors: [...socialConnectors, ...emailConnectors, ...smsConnectors],
nativeSdks,
traditionalSdks,
spaSdks,
socialConnectors,
emailConnectors,
smsConnectors,
}),
[sdks, socialConnectors, emailConnectors, smsConnectors, nativeSdks, traditionalSdks, spaSdks]
);
};

export default useCategorizedTutorialMetadata;
42 changes: 42 additions & 0 deletions src/theme/BlogLayout/index.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
.container {
max-width: 1000px;
width: 100%;
margin: 0 auto;
padding: 0 24px;

.row {
display: flex;
gap: 24px;

.main {
flex: 1;
display: flex;
flex-direction: column;
gap: 24px;
overflow: hidden;
margin-bottom: 50px;
}

.toc {
flex: 0 0 276px;
}
}

&.hasToc {
max-width: 1200px;
}
}

@media (max-width: 996px) {
.container {
max-width: 100vw;

&.hasToc {
max-width: 100vw;
}

.row .toc {
display: none;
}
}
}
19 changes: 7 additions & 12 deletions src/theme/BlogLayout/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import Layout from '@theme/Layout';
import clsx from 'clsx';
import ReactModal from 'react-modal';

import styles from './index.module.scss';

ReactModal.setAppElement('#__docusaurus');

export default function BlogLayout(props: Props): JSX.Element {
Expand All @@ -12,18 +14,11 @@ export default function BlogLayout(props: Props): JSX.Element {

return (
<Layout {...layoutProps}>
<div className="container">
<div className="row">
<BlogSidebar sidebar={sidebar} />
<main
className={clsx('col', {
'col--7': hasSidebar,
'col--9 col--offset-1': !hasSidebar,
})}
>
{children}
</main>
{toc && <div className="col col--2">{toc}</div>}
<div className={clsx(styles.container, toc && styles.hasToc)}>
<div className={styles.row}>
{hasSidebar && <BlogSidebar sidebar={sidebar} />}
<main className={styles.main}>{children}</main>
{toc && <div className={styles.toc}>{toc}</div>}
</div>
</div>
</Layout>
Expand Down
11 changes: 11 additions & 0 deletions src/theme/BlogListPage/index.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.title {
font: var(--font-headline-1);
margin-block: 32px 0;
text-align: center;
}

.subtitle {
font: var(--font-body-0);
text-align: center;
margin-bottom: 16px;
}
112 changes: 112 additions & 0 deletions src/theme/BlogListPage/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import Translate from '@docusaurus/Translate';
import { useHistory, useLocation } from '@docusaurus/router';
import { PageMetadata, HtmlClassNameProvider, ThemeClassNames } from '@docusaurus/theme-common';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import { conditional } from '@silverhand/essentials';
import BlogLayout from '@theme/BlogLayout';
import type { Props } from '@theme/BlogListPage';
import BlogListPageStructuredData from '@theme/BlogListPage/StructuredData';
import BlogListPaginator from '@theme/BlogListPaginator';
import BlogPostItems from '@theme/BlogPostItems';
import SearchMetadata from '@theme/SearchMetadata';
import clsx from 'clsx';
import { useMemo } from 'react';

import { getConnectorPath, getSdkPath } from '@site/plugins/tutorial-generator/utils';

import TitleWithSelectionDropdown from '../BlogPostItem/Header/TitleWithSelectionDropdown';

import styles from './index.module.scss';

function BlogListPageMetadata(props: Props): JSX.Element {
const { metadata } = props;
const {
siteConfig: { title: siteTitle },
} = useDocusaurusContext();

const { blogDescription, blogTitle, permalink } = metadata;
const isBlogOnlyMode = permalink === '/';
const title = isBlogOnlyMode ? siteTitle : blogTitle;
return (
<>
<PageMetadata title={title} description={blogDescription} />
<SearchMetadata tag="blog_posts_list" />
</>
);
}

function BlogListPageContent(props: Props): JSX.Element {
const { metadata, items, sidebar } = props;
const { search } = useLocation();
const { push } = useHistory();
const searchParams = new URLSearchParams(search);
const sdk = conditional(searchParams.get('sdk'));
const connector = conditional(searchParams.get('connector'));

const filteredItems = useMemo(() => {
if (!sdk && !connector) {
return items;
}
if (!sdk && connector) {
return items.filter((item) => item.content.metadata.tags[1]?.label === connector);
}
if (sdk && !connector) {
return items.filter((item) => item.content.metadata.tags[2]?.label === sdk);
}
return items.filter(
(item) =>
item.content.metadata.tags[1]?.label === connector &&
item.content.metadata.tags[2]?.label === sdk
);
}, [items, sdk, connector]);

return (
<BlogLayout sidebar={sidebar}>
<h1 className={styles.title}>
<TitleWithSelectionDropdown
defaultConnectorSlugPart={connector}
defaultSdkSlugPart={sdk}
onSelectConnector={(selection) => {
if (selection) {
searchParams.set('connector', getConnectorPath(selection));
} else {
searchParams.delete('connector');
}
push({
search: searchParams.toString(),
});
}}
onSelectSdk={(selection) => {
if (selection) {
searchParams.set('sdk', getSdkPath(selection));
} else {
searchParams.delete('sdk');
}
push({
search: searchParams.toString(),
});
}}
/>
</h1>
<h2 className={styles.subtitle}>
<Translate id="theme.blog.tutorial.subtitle">
Follow our step-by-step tutorial to set up an authentication system right away.
</Translate>
</h2>
<BlogPostItems items={filteredItems} />
<BlogListPaginator metadata={metadata} />
</BlogLayout>
);
}

export default function BlogListPage(props: Props): JSX.Element {
return (
<HtmlClassNameProvider
className={clsx(ThemeClassNames.wrapper.blogPages, ThemeClassNames.page.blogListPage)}
>
<BlogListPageMetadata {...props} />
<BlogListPageStructuredData {...props} />
<BlogListPageContent {...props} />
</HtmlClassNameProvider>
);
}
5 changes: 5 additions & 0 deletions src/theme/BlogPostItem/Container/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import type { Props } from '@theme/BlogPostItem/Container';

export default function BlogPostItemContainer({ children, className }: Props): JSX.Element {
return <article className={className}>{children}</article>;
}
65 changes: 65 additions & 0 deletions src/theme/BlogPostItem/Footer/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { useBlogPost } from '@docusaurus/plugin-content-blog/client';
import { ThemeClassNames } from '@docusaurus/theme-common';
import EditMetaRow from '@theme/EditMetaRow';
import TagsListInline from '@theme/TagsListInline';
import clsx from 'clsx';

export default function BlogPostItemFooter() {
const { metadata, isBlogPostPage } = useBlogPost();
const { tags, editUrl, hasTruncateMarker, lastUpdatedBy, lastUpdatedAt } = metadata;

// A post is truncated if it's in the "list view" and it has a truncate marker
const truncatedPost = !isBlogPostPage && hasTruncateMarker;

const tagsExists = tags.length > 0;

const renderFooter = tagsExists || truncatedPost || editUrl;

if (!renderFooter || !isBlogPostPage) {
return null;
}

// BlogPost footer - details view
const canDisplayEditMetaRow = !!(editUrl || lastUpdatedAt || lastUpdatedBy);

return (
<footer className="docusaurus-mt-lg">
{tagsExists && (
<div className={clsx('row', 'margin-top--sm', ThemeClassNames.blog.blogFooterEditMetaRow)}>
<div className="col">
<TagsListInline tags={tags} />
</div>
</div>
)}
{canDisplayEditMetaRow && (
<EditMetaRow
className={clsx('margin-top--sm', ThemeClassNames.blog.blogFooterEditMetaRow)}
editUrl={editUrl}
lastUpdatedAt={lastUpdatedAt}
lastUpdatedBy={lastUpdatedBy}
/>
)}
</footer>
);

// BlogPost footer - list view - Charles commented out - We don't need tags in list view
// else {
// return (
// <footer className="row docusaurus-mt-lg">
// {tagsExists && (
// <div className={clsx('col', {'col--9': truncatedPost})}>
// <TagsListInline tags={tags} />
// </div>
// )}
// {truncatedPost && (
// <div
// className={clsx('col text--right', {
// 'col--3': tagsExists,
// })}>
// <ReadMoreLink blogPostTitle={title} to={metadata.permalink} />
// </div>
// )}
// </footer>
// );
// }
}
Loading

0 comments on commit b6d698b

Please sign in to comment.