HEEE
Signed-off-by: Max Schmidt <max.schmidt@outlook.de>
This commit is contained in:
parent
a4b119614d
commit
7a57a69259
1
astro/.dockerignore
Normal file
1
astro/.dockerignore
Normal file
@ -0,0 +1 @@
|
||||
node_modules
|
4
astro/.vscode/extensions.json
vendored
4
astro/.vscode/extensions.json
vendored
@ -1,4 +0,0 @@
|
||||
{
|
||||
"recommendations": ["astro-build.astro-vscode"],
|
||||
"unwantedRecommendations": []
|
||||
}
|
11
astro/.vscode/launch.json
vendored
11
astro/.vscode/launch.json
vendored
@ -1,11 +0,0 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"command": "./node_modules/.bin/astro dev",
|
||||
"name": "Development server",
|
||||
"request": "launch",
|
||||
"type": "node-terminal"
|
||||
}
|
||||
]
|
||||
}
|
@ -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
8608
astro/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -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"
|
||||
}
|
||||
}
|
||||
|
@ -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>→</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>
|
@ -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>
|
||||
|
@ -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>
|
||||
|
93
astro/src/pages/posts/[id].astro
Normal file
93
astro/src/pages/posts/[id].astro
Normal 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> </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>
|
@ -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;
|
||||
}
|
||||
|
8
astro/tailwind.config.cjs
Normal file
8
astro/tailwind.config.cjs
Normal 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: [],
|
||||
}
|
@ -1,3 +1,6 @@
|
||||
{
|
||||
"extends": "astro/tsconfigs/strict"
|
||||
}
|
||||
"extends": "astro/tsconfigs/strict",
|
||||
"compilerOptions": {
|
||||
"types": ["@astrojs/image/client"]
|
||||
}
|
||||
}
|
||||
|
1202
astro/yarn.lock
1202
astro/yarn.lock
File diff suppressed because it is too large
Load Diff
10
node_modules/.yarn-integrity
generated
vendored
Normal file
10
node_modules/.yarn-integrity
generated
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"systemParams": "darwin-arm64-108",
|
||||
"modulesFolders": [],
|
||||
"flags": [],
|
||||
"linkedModules": [],
|
||||
"topLevelPatterns": [],
|
||||
"lockfileEntries": {},
|
||||
"files": [],
|
||||
"artifacts": {}
|
||||
}
|
@ -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;
|
22
payload/src/collections/Media.ts
Normal file
22
payload/src/collections/Media.ts
Normal 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;
|
@ -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",
|
||||
|
@ -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;
|
BIN
payload/src/media/experimental4_c6a5b96de6.jpg
Normal file
BIN
payload/src/media/experimental4_c6a5b96de6.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 305 KiB |
@ -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"),
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user