all in one

This commit is contained in:
Ivan Dimitrov 2023-11-11 19:54:06 +02:00
parent 31a126572b
commit 884b72a257
12 changed files with 126 additions and 122 deletions

View File

@ -3,6 +3,7 @@ title: Multi-tenant knowledge base website based on Google APIs
goal: Create a modern multi-tenant web app that lets users use their Google Drive as a knowledge base
role: Design and implement the web app
date: Jul 29, 2023 - Nov 5, 2023
z: 1
---
<details>

View File

@ -0,0 +1,8 @@
---
title: Wells Fargo Open Banking APIs integration
goal:
role:
date: Feb, 2021 - Aug, 2021
z: 3
draft: true
---

28
new.ts Normal file
View File

@ -0,0 +1,28 @@
import { baseDir, getAllContent } from "@/app/lib/content";
import fs from "fs"
const args = process.argv.slice(2)
const path = args[0]
if (!path) {
throw new Error("Path is needed!")
}
const slug = path.split("/");
const t = slug[slug.length - 1]
const nextZ = Math.max.apply(Math, getAllContent().map(c => Number(c.data.z))) + 1
const meta = (title: string = t, goal: string = "", role: string = "", date: string = "", z: number = nextZ) => `---
title: ${title}
goal: ${goal}
role: ${role}
date: ${date}
z: ${z}
draft: true
---
`
fs.writeFileSync(`${baseDir}${path}.md`, meta(), {flag: "w+"})

View File

@ -6,7 +6,8 @@
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
"lint": "next lint",
"new": "bun new.ts"
},
"dependencies": {
"@fortawesome/fontawesome-svg-core": "^6.4.2",

View File

@ -23,56 +23,47 @@ export default function Content({ params }: Props) {
const imgSize = 1024;
const { data, content } = getContent(params.slug);
const title = () => {
return (
<span className="text-3xl">
{data.title}
</span>
)
}
const goal = () => {
const g = data.goal
return g ?
const title = () =>
<span className="text-3xl">
{data.title}
</span>
const goal = () =>
data.goal ?
(
<div>
<h2>The goal</h2>
{g}
{data.goal}
</div>
) :
""
}
const role = () => {
const r = data.role
return r ?
const role = () =>
data.role ?
(
<div>
<h2>My role</h2>
{r}
{data.role}
</div>
) :
""
}
const ctnt = () => {
return (
<Markdown
className={styles.md}
remarkPlugins={[remarkGfm, remarkFrontmatter]}
rehypePlugins={[rehypeRaw, rehypeHighlight]}
components={{
img({ height, width, src, alt }) {
return (
<span className="w-full h-max p-20">
<Image className="w-full h-full" alt={alt!} height={Number(height) || imgSize} width={Number(width) || imgSize} src={`${data.slug}${src}`}></Image>
</span>
)
}
}}
>
{content}
</Markdown>
)
}
const ctnt = () =>
<Markdown
className={styles.md}
remarkPlugins={[remarkGfm, remarkFrontmatter]}
rehypePlugins={[rehypeRaw, rehypeHighlight]}
components={{
img({ height, width, src, alt }) {
return (
<span className="w-full h-max p-20">
<Image className="w-full h-full" alt={alt!} height={Number(height) || imgSize} width={Number(width) || imgSize} src={`${data.slug}${src}`}></Image>
</span>
)
}
}}
>
{content}
</Markdown>
return (
<div className="w-full h-full p-20 overflow-x-hidden overflow-scroll">
<div className="flex flex-col gap-4 text-center">

View File

@ -1,7 +1,5 @@
import Cases from "$components/cases";
export default function CasesPage() {
return (
<Cases />
)
}
const CasesPage = () => <Cases />
export default CasesPage

View File

@ -2,24 +2,16 @@ import { GrayMatterFile } from "gray-matter";
import Link from "next/link";
import { getCases } from "../lib/content";
export default function Cases() {
const cases: GrayMatterFile<string>[] = getCases()
return (
<div className="p-20 w-3/4 mx-auto">
{cases.map((c) => {
const d = c.data;
const date = d.date.split("-")
const from = date[0]?.trim()
const to = date[1]?.trim()
return (
<div key={d.slug} className="w-full h-max flex justify-center">
<Link className="btn flex flex-col w-full text-center" href={d.slug}>
<span className="text-lg px-6">{d.title}</span>
{from} {to ? `- ${to}` : ""}
</Link>
</div>
)
})}
</div>
)
}
const cases: GrayMatterFile<string>[] = getCases()
const Cases = () =>
<div className="p-20 w-3/4 mx-auto flex flex-col gap-4">
{cases.filter(c => !c.data.draft).sort(c => c.data.z).map((c) => c.data).map((d) =>
<div key={d.slug} className="w-full h-max flex justify-center">
<Link className="btn flex flex-col w-full text-center" href={d.slug}>
<span className="text-lg px-6">{d.title}</span>
<span>{d.date}</span>
</Link>
</div>
)}
</div>
export default Cases;

View File

@ -2,18 +2,16 @@ import { faGithub, faGitlab } from "@fortawesome/free-brands-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import Link from "next/link";
export default function Links() {
return (
<div className="grid w-full h-full place-content-center">
<div className={"grid grid-cols-2 gap-4 place-content-center"}>
<Link aria-label="GitHub" href={process.env.NEXT_PUBLIC_GITHUB_URL!} target="_blank">
<FontAwesomeIcon icon={faGithub} />
</Link>
<Link aria-label="GitLab" href={process.env.NEXT_PUBLIC_GITLAB_URL!} target="_blank">
<FontAwesomeIcon icon={faGitlab} />
</Link>
</div>
const Links = () =>
<div className="grid w-full h-full place-content-center">
<div className={"grid grid-cols-2 gap-4 place-content-center"}>
<Link aria-label="GitHub" href={process.env.NEXT_PUBLIC_GITHUB_URL!} target="_blank">
<FontAwesomeIcon icon={faGithub} />
</Link>
<Link aria-label="GitLab" href={process.env.NEXT_PUBLIC_GITLAB_URL!} target="_blank">
<FontAwesomeIcon icon={faGitlab} />
</Link>
</div>
)
}
</div>
export default Links

View File

@ -2,24 +2,21 @@
import Link from "next/link";
import { usePathname } from "next/navigation";
export default function Navbar() {
const link = (text: string, href: string) => {
const path = usePathname()
const link = (text: string, href: string) => {
return (
<Link data-selected={path === href} className="btn" aria-label={text} href={href}>
{text}
</Link>
)
}
return (
<div className="w-max h-max px-6 py-2 mx-auto rounded-full bg-slate-900 grid place-content-center">
<div className="flex flex-row gap-6">
{link("Home", "/")}
{link("Cases", "/cases")}
{link("Contact", "/contact")}
</div>
</div>
<Link data-selected={path === href} className="btn" aria-label={text} href={href}>
{text}
</Link>
)
}
const Navbar = () =>
<div className="w-max h-max px-6 py-2 mx-auto rounded-full bg-slate-900 grid place-content-center">
<div className="flex flex-row gap-6">
{link("Home", "/")}
{link("Cases", "/cases")}
{link("Contact", "/contact")}
</div>
</div>
export default Navbar

View File

@ -1,16 +1,13 @@
import { faEnvelope } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
export default function Contact() {
const email = "ivan@idimitrov.dev";
const mailto = `mailto:${email}`
return (
<div className="w-full h-full p-2 grid place-content-center">
<div className="flex flex-row gap-4">
<a aria-label={mailto} href={mailto}><FontAwesomeIcon icon={faEnvelope} /></a>
</div>
const email = "ivan@idimitrov.dev";
const mailto = `mailto:${email}`
const Contact = () =>
<div className="w-full h-full p-2 grid place-content-center">
<div className="flex flex-row gap-4">
<a aria-label={mailto} href={mailto}><FontAwesomeIcon icon={faEnvelope} /></a>
</div>
)
}
</div>
export default Contact

View File

@ -2,7 +2,7 @@ import fs from "fs";
import matter, { GrayMatterFile } from "gray-matter";
import path from "path";
const baseDir = "./_content/"
export const baseDir = "./_content/"
export const getContent = (slug: string[]): GrayMatterFile<string> => {
let p = path.join(baseDir)
@ -17,13 +17,10 @@ export const getContent = (slug: string[]): GrayMatterFile<string> => {
const getAllPathsRecursive = (base = baseDir): string[] => {
let results = [] as string[];
const files = fs.readdirSync(base);
for (const file of files) {
const filePath = path.join(base, file);
const stat = fs.statSync(filePath);
if (stat.isDirectory()) {
results = results.concat(getAllPathsRecursive(filePath));
} else if (path.extname(filePath) === '.md') {
@ -33,11 +30,9 @@ const getAllPathsRecursive = (base = baseDir): string[] => {
return results;
}
export const getAllPaths = (base = baseDir): string[] => {
return getAllPathsRecursive(base).map(p => p.substring(9))
}
export const getAllPaths = (base = baseDir): string[] => getAllPathsRecursive(base).map(p => p.substring(9))
export const getCases = (): GrayMatterFile<string>[] => {
return getAllPaths(`${baseDir}cases/`).map(s => s.split("/")).map(getContent)
}
export const getCases = (): GrayMatterFile<string>[] => getAllPaths(`${baseDir}cases/`).map(s => s.split("/")).map(getContent)
export const getAllContent = (): GrayMatterFile<string>[] => getAllPaths().map(s => s.split("/")).map(getContent)

View File

@ -1,7 +1,5 @@
import Links from "$components/links";
export default function Home() {
return (
<Links />
)
}
const Home = () => <Links />
export default Home;