Signed-off-by: Max Schmidt <max.schmidt@outlook.de>
This commit is contained in:
Max Schmidt 2023-05-15 16:52:29 +02:00
parent a4b119614d
commit 7a57a69259
22 changed files with 1418 additions and 8897 deletions

1
astro/.dockerignore Normal file
View File

@ -0,0 +1 @@
node_modules

View File

@ -1,4 +0,0 @@
{
"recommendations": ["astro-build.astro-vscode"],
"unwantedRecommendations": []
}

View File

@ -1,11 +0,0 @@
{
"version": "0.2.0",
"configurations": [
{
"command": "./node_modules/.bin/astro dev",
"name": "Development server",
"request": "launch",
"type": "node-terminal"
}
]
}

View File

@ -1,4 +1,18 @@
import { defineConfig } from 'astro/config';
import { defineConfig } from "astro/config";
import tailwind from "@astrojs/tailwind";
import image from "@astrojs/image";
import compress from "astro-compress";
import critters from "astro-critters";
// https://astro.build/config
export default defineConfig({});
export default defineConfig({
integrations: [
tailwind(),
image({
serviceEntryPoint: "@astrojs/image/sharp",
}),
compress(),
critters(),
],
});

8608
astro/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,12 +1,21 @@
{
"name": "astro",
"name": "astroad",
"type": "module",
"version": "0.0.1",
"license": "MIT",
"scripts": {
"dev": "astro dev --host",
"build": "astro build"
},
"dependencies": {
"astro": "^2.4.1"
"@astrojs/image": "^0.16.8",
"@astrojs/tailwind": "3.1.2",
"astro": "^2.4.5",
"astro-compress": "^1.1.43",
"astro-critters": "^1.1.34",
"css-select": "5.1.0",
"sharp": "^0.32.1",
"slate-serializers": "0.0.32",
"tailwindcss": "^3.0.24"
}
}

View File

@ -1,63 +0,0 @@
---
export interface Props {
title: string;
body: string;
href: string;
}
const { href, title, body } = Astro.props;
---
<li class="link-card">
<a href={href}>
<h2>
{title}
<span>&rarr;</span>
</h2>
<p>
{body}
</p>
</a>
</li>
<style>
.link-card {
list-style: none;
display: flex;
padding: 0.25rem;
background-color: white;
background-image: none;
background-size: 400%;
border-radius: 0.6rem;
background-position: 100%;
transition: background-position 0.6s cubic-bezier(0.22, 1, 0.36, 1);
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1);
}
.link-card > a {
width: 100%;
text-decoration: none;
line-height: 1.4;
padding: 1rem 1.3rem;
border-radius: 0.35rem;
color: #111;
background-color: white;
opacity: 0.8;
}
h2 {
margin: 0;
font-size: 1.25rem;
transition: color 0.6s cubic-bezier(0.22, 1, 0.36, 1);
}
p {
margin-top: 0.5rem;
margin-bottom: 0;
color: #444;
}
.link-card:is(:hover, :focus-within) {
background-position: 0;
background-image: var(--accent-gradient);
}
.link-card:is(:hover, :focus-within) h2 {
color: rgb(var(--accent));
}
</style>

View File

@ -1,35 +1,19 @@
---
export interface Props {
title: string;
title: string;
}
const { title } = Astro.props;
---
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="generator" content={Astro.generator} />
<title>{title}</title>
</head>
<body>
<slot />
</body>
<html lang="de">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<title>{title}</title>
</head>
<body class="bg-teal-950 text-yellow-100">
<slot />
</body>
</html>
<style is:global>
:root {
--accent: 124, 58, 237;
--accent-gradient: linear-gradient(45deg, rgb(var(--accent)), #da62c4 30%, white 60%);
}
html {
font-family: system-ui, sans-serif;
background-color: #F6F6F6;
}
code {
font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono,
Bitstream Vera Sans Mono, Courier New, monospace;
}
</style>

View File

@ -1,91 +1,29 @@
---
import Layout from '../layouts/Layout.astro';
import Card from '../components/Card.astro';
import type { Post } from '../types';
import Layout from "../layouts/Layout.astro";
import type { Post } from "../types";
const posts: Post[] = (await(await fetch("http://payload:3001/api/posts")).json()).docs;
posts.forEach(post=> console.log(post.title));
const posts: Post[] = (
await (await fetch("http://payload:3001/api/posts")).json()
).docs;
posts.forEach((post) => console.log(post.title));
---
<Layout title="Welcome to Astro.">
<main>
{posts.reverse().map(post => (
<article>
<h2>{post.title}</h2>
<p>{post.updatedAt}</p>
</article>
))}
<h1>Welcome to <span class="text-gradient">Astro</span></h1>
<p class="instructions">
To get started, open the directory <code>src/pages</code> in your project.<br />
<strong>Code Challenge:</strong> Tweak the "Welcome to Astro" message above.
</p>
<ul role="list" class="link-card-grid">
<Card
href="https://docs.astro.build/"
title="Documentation"
body="Learn how Astro works and explore the official API docs."
/>
<Card
href="https://astro.build/integrations/"
title="Integrations"
body="Supercharge your project with new frameworks and libraries."
/>
<Card
href="https://astro.build/themes/"
title="Themes"
body="Explore a galaxy of community-built starter themes."
/>
<Card
href="https://astro.build/chat/"
title="Community"
body="Come say hi to our amazing Discord community. ❤️"
/>
</ul>
</main>
<Layout title="Welcome to Astroad">
<main class="flex flex-col items-center py-10 gap-5">
<h1>This is Astroad</h1>
{
posts ? (
posts.reverse().map((post) => (
<a href={`/posts/${post.id}`}>
<article class="text-teal-950 bg-yellow-100 px-5 py-3 rounded-md shadow-md w-64 text-center">
<h2>{post.title}</h2>
<p>{new Date(post.updatedAt).toLocaleDateString("de-DE")}</p>
</article>
</a>
))
) : (
<p>No posts...</p>
)
}
</main>
</Layout>
<style>
main {
margin: auto;
padding: 1.5rem;
max-width: 60ch;
}
h1 {
font-size: 3rem;
font-weight: 800;
margin: 0;
}
.text-gradient {
background-image: var(--accent-gradient);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-size: 400%;
background-position: 0%;
}
.instructions {
line-height: 1.6;
margin: 1rem 0;
border: 1px solid rgba(var(--accent), 25%);
background-color: white;
padding: 1rem;
border-radius: 0.4rem;
}
.instructions code {
font-size: 0.875em;
font-weight: bold;
background: rgba(var(--accent), 12%);
color: rgb(var(--accent));
border-radius: 4px;
padding: 0.3em 0.45em;
}
.instructions strong {
color: rgb(var(--accent));
}
.link-card-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(24ch, 1fr));
gap: 1rem;
padding: 0;
}
</style>

View File

@ -0,0 +1,93 @@
---
import Layout from "../../layouts/Layout.astro";
import { Element } from "domhandler";
import type { Post } from "../../types";
import { Image } from "@astrojs/image/components";
import {
slateToHtml,
payloadSlateToDomConfig,
SlateToDomConfig,
} from "slate-serializers";
export async function getStaticPaths() {
const paths = (
await (await fetch("http://payload:3001/api/posts")).json()
).docs.map((post: Post) => ({
params: { id: post.id },
}));
return paths;
}
const { id } = Astro.params;
const post = (await (
await fetch(`http://payload:3001/api/posts/${id}`)
).json()) as Post;
const test: SlateToDomConfig = {
...payloadSlateToDomConfig,
elementTransforms: {
...payloadSlateToDomConfig.elementTransforms,
upload: ({ node }) =>
new Element("img", {
src: node.value.filename,
width: `${node.value.width}`,
height: `${node.value.height}`,
}),
},
};
const html = slateToHtml(post.content!, test).replaceAll(
"<p></p>",
"<p>&nbsp;</p>"
);
const htmlImageArray: (
| string
| { src: string; width: number; height: number }
)[] = [];
let lastIndex = 0;
while (true) {
const imgStartIndex = html.indexOf("<img", lastIndex);
if (imgStartIndex === -1) {
htmlImageArray.push(html.substring(lastIndex));
break;
}
const imgEndIndex = html.indexOf(">", imgStartIndex) + 1;
const imgTag = html.substring(imgStartIndex, imgEndIndex);
const remainingHtml = html.substring(lastIndex, imgStartIndex);
const imgObject = {
src: imgTag.match(/src="(.*?)"/)![1],
width: +imgTag.match(/width="(.*?)"/)![1],
height: +imgTag.match(/height="(.*?)"/)![1],
};
htmlImageArray.push(remainingHtml, imgObject);
lastIndex = imgEndIndex;
}
console.log(htmlImageArray);
---
<Layout title={post.title!}>
<h1>{id}</h1>
{
htmlImageArray.map((value) => {
if (typeof value === "string") {
return <div set:html={value} class="whitespace-pre-wrap" />;
} else {
return (
<Image
src={`http://payload:3001/media/${value.src}`}
width={value.width}
height={value.height}
format="webp"
alt="hallo"
/>
);
}
})
}
</Layout>
<style>
p:empty {
display: block;
content: "\00a0";
margin: 0;
padding: 0;
}
</style>

View File

@ -7,24 +7,16 @@
export interface Config {
collections: {
categories: Category;
posts: Post;
tags: Tag;
users: User;
media: Media;
};
globals: {};
}
export interface Category {
id: string;
name?: string;
}
export interface Post {
id: string;
title?: string;
author?: string | User;
publishedDate?: string;
category?: string | Category;
tags?: string[] | Tag[];
content?: {
[k: string]: unknown;
}[];
@ -44,7 +36,14 @@ export interface User {
lockUntil?: string;
password?: string;
}
export interface Tag {
export interface Media {
id: string;
name?: string;
updatedAt: string;
createdAt: string;
url?: string;
filename?: string;
mimeType?: string;
filesize?: number;
width?: number;
height?: number;
}

View File

@ -0,0 +1,8 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],
theme: {
extend: {},
},
plugins: [],
}

View File

@ -1,3 +1,6 @@
{
"extends": "astro/tsconfigs/strict"
}
"extends": "astro/tsconfigs/strict",
"compilerOptions": {
"types": ["@astrojs/image/client"]
}
}

File diff suppressed because it is too large Load Diff

10
node_modules/.yarn-integrity generated vendored Normal file
View File

@ -0,0 +1,10 @@
{
"systemParams": "darwin-arm64-108",
"modulesFolders": [],
"flags": [],
"linkedModules": [],
"topLevelPatterns": [],
"lockfileEntries": {},
"files": [],
"artifacts": {}
}

View File

@ -1,20 +0,0 @@
import { CollectionConfig } from 'payload/types';
const Categories: CollectionConfig = {
slug: 'categories',
admin: {
useAsTitle: 'name',
},
access: {
read: () => true,
},
fields: [
{
name: 'name',
type: 'text',
},
],
timestamps: false,
}
export default Categories;

View File

@ -0,0 +1,22 @@
import { CollectionConfig } from "payload/types";
export const Media: CollectionConfig = {
slug: "media",
labels: {
singular: "Bild",
plural: "Bilder",
},
admin: {},
access: {
read: (): boolean => true,
},
upload: {
staticURL: "/media",
staticDir: "media",
mimeTypes: ["image/*"],
},
fields: [],
};
export default Media;

View File

@ -3,7 +3,7 @@ import { CollectionConfig } from "payload/types";
const Posts: CollectionConfig = {
slug: "posts",
admin: {
defaultColumns: ["title", "author", "category", "tags", "status"],
defaultColumns: ["title", "author", "status"],
useAsTitle: "title",
},
access: {
@ -14,29 +14,32 @@ const Posts: CollectionConfig = {
name: "title",
type: "text",
},
{
name: "author",
type: "relationship",
relationTo: "users",
},
{
name: "publishedDate",
type: "date",
},
{
name: "category",
type: "relationship",
relationTo: "categories",
},
{
name: "tags",
type: "relationship",
relationTo: "tags",
hasMany: true,
},
{
name: "content",
type: "richText",
admin: {
elements: ["h2", "h3", "h4", "link", "ol", "ul", "upload"],
leaves: ["bold", "italic", "underline"],
upload: {
collections: {
media: {
fields: [
{
name: "imagel",
type: "upload",
relationTo: "media",
required: true,
},
],
},
},
},
},
},
{
name: "status",

View File

@ -1,20 +0,0 @@
import { CollectionConfig } from 'payload/types';
const Tags: CollectionConfig = {
slug: 'tags',
admin: {
useAsTitle: 'name',
},
access: {
read: () => true,
},
fields: [
{
name: 'name',
type: 'text',
},
],
timestamps: false,
}
export default Tags;

Binary file not shown.

After

Width:  |  Height:  |  Size: 305 KiB

View File

@ -1,16 +1,15 @@
import { buildConfig } from "payload/config";
import path from "path";
import Categories from "./collections/Categories";
import Posts from "./collections/Posts";
import Tags from "./collections/Tags";
import Users from "./collections/Users";
import Media from "./collections/Media";
export default buildConfig({
serverURL: "http://localhost:3001",
admin: {
user: Users.slug,
},
collections: [Categories, Posts, Tags, Users],
collections: [Posts, Users, Media],
typescript: {
outputFile: path.resolve("/", "types.ts"),
},

4
yarn.lock Normal file
View File

@ -0,0 +1,4 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1