Migrated Developer Docs (#5683)

- Migrated developer docs to Twenty website

- Modified User Guide and Docs layout to include sections and
subsections

**Section Example:**
<img width="549" alt="Screenshot 2024-05-30 at 15 44 42"
src="https://github.com/twentyhq/twenty/assets/102751374/41bd4037-4b76-48e6-bc79-48d3d6be9ab8">

**Subsection Example:**
<img width="557" alt="Screenshot 2024-05-30 at 15 44 55"
src="https://github.com/twentyhq/twenty/assets/102751374/f14c65a9-ab0c-4530-b624-5b20fc00511a">


- Created different components (Tabs, Tables, Editors etc.) for the mdx
files

**Tabs & Editor**

<img width="665" alt="Screenshot 2024-05-30 at 15 47 39"
src="https://github.com/twentyhq/twenty/assets/102751374/5166b5c7-b6cf-417d-9f29-b1f674c1c531">

**Tables**

<img width="698" alt="Screenshot 2024-05-30 at 15 57 39"
src="https://github.com/twentyhq/twenty/assets/102751374/2bbfe937-ec19-4004-ab00-f7a56e96db4a">

<img width="661" alt="Screenshot 2024-05-30 at 16 03 32"
src="https://github.com/twentyhq/twenty/assets/102751374/ae95b47c-dd92-44f9-b535-ccdc953f71ff">

- Created a crawler for Twenty Developers (now that it will be on the
twenty website). Once this PR is merged and the website is re-deployed,
we need to start crawling and make sure the index name is
‘twenty-developer’
- Added a dropdown menu in the header to access User Guide and
Developers + added Developers to footer


https://github.com/twentyhq/twenty/assets/102751374/1bd1fbbd-1e65-4461-b18b-84d4ddbb8ea1

- Made new layout responsive

Please fill in the information for each mdx file so that it can appear
on its card, as well as in the ‘In this article’ section. Example with
‘Getting Started’ in the User Guide:

<img width="786" alt="Screenshot 2024-05-30 at 16 29 39"
src="https://github.com/twentyhq/twenty/assets/102751374/2714b01d-a664-4ddc-9291-528632ee12ea">

Example with info and sectionInfo filled in for 'Getting Started':

<img width="620" alt="Screenshot 2024-05-30 at 16 33 57"
src="https://github.com/twentyhq/twenty/assets/102751374/bc69e880-da6a-4b7e-bace-1effea866c11">


Please keep in mind that the images that are being used for Developers
are the same as those found in User Guide and may not match the article.

---------

Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
This commit is contained in:
Ady Beraud
2024-06-03 19:52:43 +03:00
committed by GitHub
parent f7cdd14c75
commit 671de4170f
139 changed files with 7057 additions and 494 deletions

View File

@ -1,26 +1,35 @@
export const USER_GUIDE_INDEX = {
'Getting Started': [
{ fileName: 'what-is-twenty' },
{ fileName: 'create-workspace' },
],
Objects: [
{ fileName: 'objects' },
{ fileName: 'fields' },
{ fileName: 'views-sort-filter' },
{ fileName: 'table-views' },
{ fileName: 'kanban-views' },
{ fileName: 'import-export-data' },
],
Functions: [
{ fileName: 'emails' },
{ fileName: 'notes' },
{ fileName: 'tasks' },
{ fileName: 'integrations' },
{ fileName: 'api-webhooks' },
],
Other: [
{ fileName: 'glossary' },
{ fileName: 'tips' },
{ fileName: 'github' },
],
'User Guide': {
'Getting Started': [
{ fileName: 'getting-started' },
{ fileName: 'what-is-twenty' },
{ fileName: 'create-workspace' },
],
Objects: [
{ fileName: 'objects' },
{ fileName: 'standard-objects' },
{ fileName: 'fields' },
{ fileName: 'views-sort-filter' },
{ fileName: 'table-views' },
{ fileName: 'kanban-views' },
{ fileName: 'import-export-data' },
],
Functions: [
{ fileName: 'functions' },
{ fileName: 'emails' },
{ fileName: 'notes' },
{ fileName: 'tasks' },
{ fileName: 'integrations' },
{ fileName: 'api-webhooks' },
],
Other: [
{ fileName: 'other' },
{ fileName: 'glossary' },
{ fileName: 'tips' },
{ fileName: 'github' },
],
},
Developers: {
'Empty Section': [],
},
};

View File

@ -0,0 +1,107 @@
import fs from 'fs';
import matter from 'gray-matter';
import path from 'path';
import { DOCS_INDEX } from '@/content/developers/constants/DocsIndex';
import { TWENTY_UI_INDEX } from '@/content/twenty-ui/constants/TwentyUiIndex';
import { USER_GUIDE_INDEX } from '@/content/user-guide/constants/UserGuideIndex';
export interface DocsArticlesProps {
title: string;
info: string;
image: string;
fileName: string;
topic: string;
section: string;
sectionInfo: string;
numberOfFiles: number;
}
export function getDocsArticles(basePath: string, isSideBar = false) {
const guides: DocsArticlesProps[] = [];
const index = basePath.includes('developers')
? DOCS_INDEX
: basePath.includes('user-guide')
? USER_GUIDE_INDEX
: TWENTY_UI_INDEX;
const findFileRecursively = (
directory: string,
fileName: string,
): string | null => {
const files = fs.readdirSync(directory);
for (const file of files) {
const fullPath = path.join(directory, file);
const stat = fs.statSync(fullPath);
if (stat.isDirectory()) {
const nestedResult = findFileRecursively(fullPath, fileName);
if (nestedResult) {
return nestedResult;
}
} else if (stat.isFile() && path.basename(fullPath) === fileName) {
return fullPath;
}
}
return null;
};
const processFiles = (
section: string,
topic: string,
files: { fileName: string }[],
): void => {
if (files.length === 0) {
guides.push({
title: '',
info: '',
image: '',
fileName: '',
topic: topic,
section: section,
sectionInfo: '',
numberOfFiles: 0,
});
return;
}
files.forEach(({ fileName }) => {
let filePath;
if (isSideBar) {
const nestedPath = findFileRecursively(basePath, `${fileName}.mdx`);
const directPath = `${basePath}${fileName}.mdx`;
filePath = nestedPath || directPath;
} else {
filePath = `${basePath}${fileName}.mdx`;
}
if (fs.existsSync(filePath)) {
const fileContent = fs.readFileSync(filePath, 'utf-8');
const { data: frontmatter } = matter(fileContent);
guides.push({
title: frontmatter.title || '',
info: frontmatter.info || '',
image: frontmatter.image || '',
fileName: fileName,
topic: topic,
section: section,
sectionInfo: frontmatter.sectionInfo || '',
numberOfFiles: files.length,
});
}
});
};
for (const [mainTopic, subTopics] of Object.entries(index)) {
if (typeof subTopics === 'object' && !Array.isArray(subTopics)) {
for (const [subTopic, files] of Object.entries(subTopics)) {
processFiles(mainTopic, subTopic, files as { fileName: string }[]);
}
} else {
processFiles(mainTopic, mainTopic, subTopics);
}
}
return guides;
}

View File

@ -1,36 +0,0 @@
import fs from 'fs';
import matter from 'gray-matter';
import { USER_GUIDE_INDEX } from '@/content/user-guide/constants/UserGuideIndex';
export interface UserGuideArticlesProps {
title: string;
info: string;
image: string;
fileName: string;
topic: string;
}
export function getUserGuideArticles() {
const guides: UserGuideArticlesProps[] = [];
for (const [topic, files] of Object.entries(USER_GUIDE_INDEX)) {
files.forEach(({ fileName }) => {
const filePath = `src/content/user-guide/${fileName}.mdx`;
if (fs.existsSync(filePath)) {
const fileContent = fs.readFileSync(filePath, 'utf-8');
const { data: frontmatter } = matter(fileContent);
guides.push({
title: frontmatter.title || '',
info: frontmatter.info || '',
image: frontmatter.image || '',
fileName: fileName,
topic: topic,
});
}
});
}
return guides;
}

View File

@ -1,14 +1,14 @@
import { UserGuideArticlesProps } from '@/content/user-guide/constants/getUserGuideArticles';
import { DocsArticlesProps } from '@/content/user-guide/constants/getDocsArticles';
export const groupArticlesByTopic = (
items: UserGuideArticlesProps[],
): Record<string, UserGuideArticlesProps[]> => {
items: DocsArticlesProps[],
): Record<string, DocsArticlesProps[]> => {
return items.reduce(
(acc, item) => {
acc[item.topic] = acc[item.topic] || [];
acc[item.topic].push(item);
return acc;
},
{} as Record<string, UserGuideArticlesProps[]>,
{} as Record<string, DocsArticlesProps[]>,
);
};