diff --git a/webapp/src/app/page.tsx b/webapp/src/app/page.tsx index af3f571..643b3e3 100644 --- a/webapp/src/app/page.tsx +++ b/webapp/src/app/page.tsx @@ -1,9 +1,6 @@ -import { Cache } from '@/Cache'; +import { accessProjects } from '@/dataAccess'; +import { Promises } from '@/utils/Promises'; import HomeDashboard from '@/components/HomeDashboard'; -import MessageAdapterFactory from '@/utils/adapters/MessageAdapterFactory'; -import { ProjectCardProps } from '@/components/ProjectCard'; -import { RepoGit } from '@/RepoGit'; -import { ServerConfig } from '@/utils/serverConfig'; // Force dynamic rendering for this page. By default Next.js attempts to render // this page statically. That means that it tries to render the page at build @@ -19,39 +16,27 @@ import { ServerConfig } from '@/utils/serverConfig'; export const dynamic = 'force-dynamic'; export default async function Home() { - const serverConfig = await ServerConfig.read(); - const projects = await Promise.all( - serverConfig.projects.map>(async (project) => { - await RepoGit.cloneIfNotExist(project); - const repoGit = await RepoGit.getRepoGit(project); - const lyraConfig = await repoGit.getLyraConfig(); - const projectConfig = lyraConfig.getProjectConfigByPath( - project.projectPath, - ); - const msgAdapter = MessageAdapterFactory.createAdapter(projectConfig); - const messages = await msgAdapter.getMessages(); - const store = await Cache.getProjectStore(projectConfig); - const languages = await Promise.all( - projectConfig.languages.map(async (lang) => { - const translations = await store.getTranslations(lang); - return { - href: `/projects/${project.name}/${lang}`, - language: lang, - progress: translations - ? (Object.keys(translations).length / messages.length) * 100 - : 0, - }; - }), - ); + const projectData = await accessProjects(); + const projects = await Promises.of(projectData) + .map(async ({ name, messages, languagesWithTranslations }) => { + const languages = await Promises.of(languagesWithTranslations) + .map(({ lang, translations }) => ({ + href: `/projects/${name}/${lang}`, + language: lang, + progress: translations + ? (Object.keys(translations).length / messages.length) * 100 + : 0, + })) + .all(); return { - href: `/projects/${project.name}`, + href: `/projects/${name}`, languages, messageCount: messages.length, - name: project.name, + name, }; - }), - ); + }) + .all(); return ; } diff --git a/webapp/src/app/projects/[projectName]/page.tsx b/webapp/src/app/projects/[projectName]/page.tsx index 24c30d7..a660d64 100644 --- a/webapp/src/app/projects/[projectName]/page.tsx +++ b/webapp/src/app/projects/[projectName]/page.tsx @@ -1,50 +1,34 @@ import { NextPage } from 'next'; import { notFound } from 'next/navigation'; -import { Cache } from '@/Cache'; -import MessageAdapterFactory from '@/utils/adapters/MessageAdapterFactory'; +import { accessProject } from '@/dataAccess'; +import { Promises } from '@/utils/Promises'; import ProjectDashboard from '@/components/ProjectDashboard'; -import { RepoGit } from '@/RepoGit'; -import { ServerConfig } from '@/utils/serverConfig'; const ProjectPage: NextPage<{ params: { projectName: string }; }> = async ({ params }) => { - const serverConfig = await ServerConfig.read(); - const project = serverConfig.projects.find( - (project) => project.name === params.projectName, - ); - + const project = await accessProject(params.projectName); if (!project) { return notFound(); } - - await RepoGit.cloneIfNotExist(project); - const repoGit = await RepoGit.getRepoGit(project); - const lyraConfig = await repoGit.getLyraConfig(); - const projectConfig = lyraConfig.getProjectConfigByPath(project.projectPath); - const msgAdapter = MessageAdapterFactory.createAdapter(projectConfig); - const messages = await msgAdapter.getMessages(); - const store = await Cache.getProjectStore(projectConfig); - const languages = await Promise.all( - projectConfig.languages.map(async (lang) => { - const translations = await store.getTranslations(lang); - return { - href: `/projects/${project.name}/${lang}`, - language: lang, - messagesLeft: messages.length - Object.keys(translations).length, - progress: translations - ? (Object.keys(translations).length / messages.length) * 100 - : 0, - }; - }), - ); + const { name, messages, languagesWithTranslations } = project; + const languages = await Promises.of(languagesWithTranslations) + .map(({ lang, translations }) => ({ + href: `/projects/${name}/${lang}`, + language: lang, + messagesLeft: messages.length - Object.keys(translations).length, + progress: translations + ? (Object.keys(translations).length / messages.length) * 100 + : 0, + })) + .all(); return ( ); }; diff --git a/webapp/src/dataAccess.ts b/webapp/src/dataAccess.ts new file mode 100644 index 0000000..35040d4 --- /dev/null +++ b/webapp/src/dataAccess.ts @@ -0,0 +1,41 @@ +import { Cache } from '@/Cache'; +import MessageAdapterFactory from '@/utils/adapters/MessageAdapterFactory'; +import { RepoGit } from '@/RepoGit'; +import { ServerConfig, ServerProjectConfig } from '@/utils/serverConfig'; + +export async function accessProjects() { + const serverConfig = await ServerConfig.read(); + return serverConfig.projects.map(async (project) => { + return await readProject(project); + }); +} + +export async function accessProject(name: string) { + const serverConfig = await ServerConfig.read(); + const project = serverConfig.projects.find( + (project) => project.name === name, + ); + + if (!project) { + return null; + } + + return readProject(project); +} + +async function readProject(project: ServerProjectConfig) { + await RepoGit.cloneIfNotExist(project); + const repoGit = await RepoGit.getRepoGit(project); + const lyraConfig = await repoGit.getLyraConfig(); + const projectConfig = lyraConfig.getProjectConfigByPath(project.projectPath); + const msgAdapter = MessageAdapterFactory.createAdapter(projectConfig); + const messages = await msgAdapter.getMessages(); + const store = await Cache.getProjectStore(projectConfig); + const languagesWithTranslations = projectConfig.languages.map( + async (lang) => { + const translations = await store.getTranslations(lang); + return { lang, translations }; + }, + ); + return { languagesWithTranslations, messages, name: project.name }; +} diff --git a/webapp/src/utils/Promises.ts b/webapp/src/utils/Promises.ts new file mode 100644 index 0000000..792da72 --- /dev/null +++ b/webapp/src/utils/Promises.ts @@ -0,0 +1,15 @@ +export class Promises { + private constructor(private array: Array>) {} + + static of(array: Array>) { + return new Promises(array); + } + + map(callbackFn: (value: T) => U | Promise): Promises { + return new Promises(this.array.map((p) => p.then(callbackFn))); + } + + all() { + return Promise.all(this.array); + } +}