Marketing website improvements (#3169)
* Website improvement * Improve website design * Start writing script for user guide * Begin adding user guide
This commit is contained in:
@ -0,0 +1,11 @@
|
||||
import { getPost } from "@/app/user-guide/get-posts";
|
||||
|
||||
export default async function BlogPost({ params }: { params: { slug: string[] } }) {
|
||||
const post = await getPost(params.slug as string[]);
|
||||
console.log(post);
|
||||
|
||||
return <div>
|
||||
<h1>{post?.itemInfo.title}</h1>
|
||||
<div>{post?.content}</div>
|
||||
</div>;
|
||||
}
|
||||
97
packages/twenty-website/src/app/user-guide/get-posts.tsx
Normal file
97
packages/twenty-website/src/app/user-guide/get-posts.tsx
Normal file
@ -0,0 +1,97 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { compileMDX } from 'next-mdx-remote/rsc';
|
||||
import { ReactElement } from 'react';
|
||||
|
||||
interface ItemInfo {
|
||||
title: string;
|
||||
position?: number;
|
||||
path: string;
|
||||
type: 'file' | 'directory';
|
||||
}
|
||||
|
||||
export interface FileContent {
|
||||
content: ReactElement;
|
||||
itemInfo: ItemInfo;
|
||||
}
|
||||
|
||||
export interface Directory {
|
||||
[key: string]: FileContent | Directory | ItemInfo;
|
||||
itemInfo: ItemInfo;
|
||||
}
|
||||
|
||||
const basePath = '/src/content/user-guide';
|
||||
|
||||
|
||||
async function getFiles(filePath: string, position: number = 0): Promise<Directory> {
|
||||
const entries = fs.readdirSync(filePath, { withFileTypes: true });
|
||||
|
||||
const urlpath = path.toString().split(basePath);
|
||||
const pathName = urlpath.length > 1 ? urlpath[1] : path.basename(filePath);
|
||||
console.log(pathName);
|
||||
|
||||
const directory: Directory = {
|
||||
itemInfo: {
|
||||
title: path.basename(filePath),
|
||||
position,
|
||||
type: 'directory',
|
||||
path: pathName,
|
||||
},
|
||||
};
|
||||
|
||||
for (const entry of entries) {
|
||||
if (entry.isDirectory()) {
|
||||
directory[entry.name] = await getFiles(path.join(filePath, entry.name), position++);
|
||||
} else if (entry.isFile() && path.extname(entry.name) === '.mdx') {
|
||||
const fileContent = fs.readFileSync(path.join(filePath, entry.name), 'utf8');
|
||||
const { content, frontmatter } = await compileMDX<{ title: string, position?: number }>({ source: fileContent, options: { parseFrontmatter: true } });
|
||||
directory[entry.name] = { content, itemInfo: {...frontmatter, type: 'file', path: pathName + "/" + entry.name.replace(/\.mdx$/, '')} };
|
||||
}
|
||||
}
|
||||
|
||||
return directory;
|
||||
}
|
||||
|
||||
async function parseFrontMatterAndCategory(directory: Directory, dirPath: string): Promise<Directory> {
|
||||
const parsedDirectory: Directory = {
|
||||
itemInfo: directory.itemInfo,
|
||||
};
|
||||
|
||||
for (const entry in directory) {
|
||||
if (entry !== 'itemInfo' && directory[entry] instanceof Object) {
|
||||
parsedDirectory[entry] = await parseFrontMatterAndCategory(directory[entry] as Directory, path.join(dirPath, entry));
|
||||
}
|
||||
}
|
||||
|
||||
const categoryPath = path.join(dirPath, '_category_.json');
|
||||
|
||||
if (fs.existsSync(categoryPath)) {
|
||||
const categoryJson: ItemInfo = JSON.parse(fs.readFileSync(categoryPath, 'utf8'));
|
||||
parsedDirectory.itemInfo = categoryJson;
|
||||
}
|
||||
|
||||
return parsedDirectory;
|
||||
}
|
||||
|
||||
export async function getPosts(): Promise<Directory> {
|
||||
const postsDirectory = path.join(process.cwd(), basePath);
|
||||
const directory = await getFiles(postsDirectory);
|
||||
return parseFrontMatterAndCategory(directory, postsDirectory);
|
||||
}
|
||||
|
||||
export async function getPost(slug: string[]): Promise<FileContent | null> {
|
||||
const postsDirectory = path.join(process.cwd(), basePath);
|
||||
const modifiedSlug = slug.join('/');
|
||||
const filePath = path.join(postsDirectory, `${modifiedSlug}.mdx`);
|
||||
|
||||
console.log(filePath);
|
||||
|
||||
if (!fs.existsSync(filePath)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const fileContent = fs.readFileSync(filePath, 'utf8');
|
||||
const { content, frontmatter } = await compileMDX<{ title: string, position?: number }>({ source: fileContent, options: { parseFrontmatter: true } });
|
||||
|
||||
return { content, itemInfo: {...frontmatter, type: 'file', path: modifiedSlug }};
|
||||
}
|
||||
47
packages/twenty-website/src/app/user-guide/page.tsx
Normal file
47
packages/twenty-website/src/app/user-guide/page.tsx
Normal file
@ -0,0 +1,47 @@
|
||||
import { ContentContainer } from '@/app/components/ContentContainer';
|
||||
import { getPosts, Directory, FileContent } from '@/app/user-guide/get-posts';
|
||||
import Link from 'next/link';
|
||||
|
||||
|
||||
const DirectoryItem = ({ name, item }: { name: string, item: Directory | FileContent }) => {
|
||||
if ('content' in item) {
|
||||
// If the item is a file, we render a link.
|
||||
return (
|
||||
<div key={name}>
|
||||
<Link href={`/user-guide/${item.itemInfo.path}`}>
|
||||
{item.itemInfo.title}
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
// If the item is a directory, we render the title and the items in the directory.
|
||||
return (
|
||||
<div key={name}>
|
||||
<h2>{item.itemInfo.title}</h2>
|
||||
{Object.entries(item).map(([childName, childItem]) => {
|
||||
if (childName !== 'itemInfo') {
|
||||
return <DirectoryItem key={childName} name={childName} item={childItem as Directory | FileContent} />;
|
||||
}
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
export default async function BlogHome() {
|
||||
|
||||
const posts = await getPosts();
|
||||
|
||||
|
||||
return <ContentContainer>
|
||||
<h1>User Guide</h1>
|
||||
<div>
|
||||
{Object.entries(posts).map(([name, item]) => {
|
||||
if (name !== 'itemInfo') {
|
||||
return <DirectoryItem key={name} name={name} item={item as Directory | FileContent} />;
|
||||
}
|
||||
})}
|
||||
</div>
|
||||
</ContentContainer>;
|
||||
}
|
||||
Reference in New Issue
Block a user