This commit is contained in:
parent
b5d2cfc18c
commit
f86697e00d
28
Dockerfile
28
Dockerfile
|
@ -1,28 +0,0 @@
|
||||||
# Stage 1: Build the Astro project
|
|
||||||
FROM node:20-alpine AS builder
|
|
||||||
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
# Copy package.json and package-lock.json files
|
|
||||||
COPY package*.json ./
|
|
||||||
|
|
||||||
# Install dependencies
|
|
||||||
RUN npm install
|
|
||||||
|
|
||||||
# Copy the rest of the application files
|
|
||||||
COPY . .
|
|
||||||
|
|
||||||
# Build the Astro project
|
|
||||||
RUN npm run build
|
|
||||||
|
|
||||||
# Stage 2: Serve with nginx
|
|
||||||
FROM nginx:alpine
|
|
||||||
|
|
||||||
# Copy the built static files from the builder stage
|
|
||||||
COPY --from=builder /app/dist /usr/share/nginx/html
|
|
||||||
|
|
||||||
# Copy custom nginx configuration file if needed
|
|
||||||
# COPY default.conf /etc/nginx/conf.d/default.conf
|
|
||||||
|
|
||||||
# Expose port 80 to the outside world
|
|
||||||
EXPOSE 80
|
|
49
src/components/EmojiReactionForm.astro
Normal file
49
src/components/EmojiReactionForm.astro
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
---
|
||||||
|
const { entryId } = Astro.props;
|
||||||
|
const backendHost = import.meta.env.PUBLIC_BACKEND_HOST;
|
||||||
|
---
|
||||||
|
|
||||||
|
<style is:global>
|
||||||
|
.emoji-button {
|
||||||
|
border: none;
|
||||||
|
@apply text-lg rounded-full p-2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.emoji-buttons-container {
|
||||||
|
@apply flex flex-row gap-2;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<form
|
||||||
|
hx-post=`${backendHost}/blog/api/forms/emoji/post`
|
||||||
|
hx-target="#reaction-buttons"
|
||||||
|
>
|
||||||
|
<input type="hidden" name="postId" value=`${entryId}` />
|
||||||
|
<div
|
||||||
|
id="reaction-buttons"
|
||||||
|
hx-get=`${backendHost}/blog/api/forms/emoji?postId=${entryId}`
|
||||||
|
hx-trigger="load"
|
||||||
|
hx-swap="innerHTML"
|
||||||
|
>
|
||||||
|
<div class="emoji-buttons-container">
|
||||||
|
<button name="emojiInput" value="👍" type="submit" class="emoji-button"
|
||||||
|
>👍 </button
|
||||||
|
>
|
||||||
|
<button name="emojiInput" value="👎" type="submit" class="emoji-button"
|
||||||
|
>👎 </button
|
||||||
|
>
|
||||||
|
<button name="emojiInput" value="😀" type="submit" class="emoji-button"
|
||||||
|
>😀 </button
|
||||||
|
>
|
||||||
|
<button name="emojiInput" value="😑" type="submit" class="emoji-button"
|
||||||
|
>😑 </button
|
||||||
|
>
|
||||||
|
<button name="emojiInput" value="🤢" type="submit" class="emoji-button"
|
||||||
|
>🤢 </button
|
||||||
|
>
|
||||||
|
<button name="emojiInput" value="👀" type="submit" class="emoji-button"
|
||||||
|
>👀 </button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
|
@ -55,14 +55,24 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import ConwaySimulator from "../scripts/conway-simulator";
|
import ConwaySimulator from "../scripts/conway-simulator";
|
||||||
|
let rows = 8;
|
||||||
let cols = 24;
|
let cols = 24;
|
||||||
let pixelSize = 4;
|
let pixelSize = 6;
|
||||||
|
let delay = 250;
|
||||||
|
|
||||||
if (screen.availWidth > 768) {
|
if (screen.availWidth > 768) {
|
||||||
cols = 46;
|
cols = 46;
|
||||||
pixelSize = 8;
|
pixelSize = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
let gol = new ConwaySimulator(8, cols, pixelSize, 250);
|
let gameOfLife = new ConwaySimulator(rows, cols, pixelSize, delay);
|
||||||
document.getElementById("board")?.append(gol.canvas);
|
|
||||||
gol.start();
|
const boardElement = document.getElementById("board");
|
||||||
|
if (boardElement) {
|
||||||
|
boardElement.append(gameOfLife.canvas);
|
||||||
|
} else {
|
||||||
|
console.error("Board element could not be found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
gameOfLife.start();
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -8,34 +8,53 @@ interface Props {
|
||||||
|
|
||||||
const { post, componentType } = Astro.props;
|
const { post, componentType } = Astro.props;
|
||||||
|
|
||||||
let showTags, shortSummary, longSummary, fullText, postFooter;
|
// default options for the post component
|
||||||
|
const deafultOptions = {
|
||||||
|
showTags: false,
|
||||||
|
shortSummary: false,
|
||||||
|
longSummary: false,
|
||||||
|
fullText: false,
|
||||||
|
postFooter: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
const options = { ...deafultOptions };
|
||||||
|
// Determine which options should be applied to post
|
||||||
switch (componentType) {
|
switch (componentType) {
|
||||||
case "full":
|
case "full":
|
||||||
postFooter = true;
|
options.postFooter = true;
|
||||||
showTags = true;
|
options.showTags = true;
|
||||||
fullText = true;
|
options.fullText = true;
|
||||||
break;
|
break;
|
||||||
case "long":
|
case "long":
|
||||||
longSummary = true;
|
options.longSummary = true;
|
||||||
showTags = true;
|
options.showTags = true;
|
||||||
break;
|
break;
|
||||||
case "short":
|
case "short":
|
||||||
shortSummary = true;
|
options.shortSummary = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Options should not mutated further
|
||||||
|
Object.freeze(options);
|
||||||
|
|
||||||
|
// Format datae
|
||||||
const postDateFormatted = post.data.date.toLocaleDateString("tr-TR", {
|
const postDateFormatted = post.data.date.toLocaleDateString("tr-TR", {
|
||||||
day: "numeric",
|
day: "numeric",
|
||||||
month: "long",
|
month: "long",
|
||||||
year: "numeric",
|
year: "numeric",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Create post link
|
||||||
const postLink = `/category/${post.data.category}/${post.slug}`;
|
const postLink = `/category/${post.data.category}/${post.slug}`;
|
||||||
|
|
||||||
|
// Create post content as an astro component
|
||||||
const { Content } = await post.render();
|
const { Content } = await post.render();
|
||||||
|
|
||||||
|
import { Image } from "astro:assets";
|
||||||
|
import questionMark from "@/images/questionMark.svg";
|
||||||
|
import calendar from "@/images/calendar.svg";
|
||||||
---
|
---
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
@ -57,17 +76,9 @@ const { Content } = await post.render();
|
||||||
>
|
>
|
||||||
<div class="flex flex-row gap-2">
|
<div class="flex flex-row gap-2">
|
||||||
{
|
{
|
||||||
showTags && (
|
options.showTags && (
|
||||||
<div class="flex items-center gap-1">
|
<div class="flex items-center gap-1">
|
||||||
<svg
|
<Image alt="question mark" src={questionMark} />
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
width="18"
|
|
||||||
height="18"
|
|
||||||
fill="#6d6d6d"
|
|
||||||
viewBox="0 0 256 256"
|
|
||||||
>
|
|
||||||
<path d="M140,180a12,12,0,1,1-12-12A12,12,0,0,1,140,180ZM128,72c-22.06,0-40,16.15-40,36v4a8,8,0,0,0,16,0v-4c0-11,10.77-20,24-20s24,9,24,20-10.77,20-24,20a8,8,0,0,0-8,8v8a8,8,0,0,0,16,0v-.72c18.24-3.35,32-17.9,32-35.28C168,88.15,150.06,72,128,72Zm104,56A104,104,0,1,1,128,24,104.11,104.11,0,0,1,232,128Zm-16,0a88,88,0,1,0-88,88A88.1,88.1,0,0,0,216,128Z" />
|
|
||||||
</svg>
|
|
||||||
<ul class="list-none flex pl-0 meta-list">
|
<ul class="list-none flex pl-0 meta-list">
|
||||||
{post.data.tags.map((tag) => (
|
{post.data.tags.map((tag) => (
|
||||||
<li class="text-sm text-gray-500">{tag}</li>
|
<li class="text-sm text-gray-500">{tag}</li>
|
||||||
|
@ -78,26 +89,17 @@ const { Content } = await post.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
<div class="flex items-center gap-1">
|
<div class="flex items-center gap-1">
|
||||||
<svg
|
<Image alt="calendar" src={calendar} />
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
width="18"
|
|
||||||
height="18"
|
|
||||||
fill="#6d6d6d"
|
|
||||||
viewBox="0 0 256 256"
|
|
||||||
><path
|
|
||||||
d="M208,32H184V24a8,8,0,0,0-16,0v8H88V24a8,8,0,0,0-16,0v8H48A16,16,0,0,0,32,48V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V48A16,16,0,0,0,208,32ZM72,48v8a8,8,0,0,0,16,0V48h80v8a8,8,0,0,0,16,0V48h24V80H48V48ZM208,208H48V96H208V208Zm-68-76a12,12,0,1,1-12-12A12,12,0,0,1,140,132Zm44,0a12,12,0,1,1-12-12A12,12,0,0,1,184,132ZM96,172a12,12,0,1,1-12-12A12,12,0,0,1,96,172Zm44,0a12,12,0,1,1-12-12A12,12,0,0,1,140,172Zm44,0a12,12,0,1,1-12-12A12,12,0,0,1,184,172Z"
|
|
||||||
></path></svg
|
|
||||||
>
|
|
||||||
<ul class="list-none flex pl-0 meta-list">
|
<ul class="list-none flex pl-0 meta-list">
|
||||||
<p class="text-sm text-gray-500">{postDateFormatted}</p>
|
<p class="text-sm text-gray-500">{postDateFormatted}</p>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{shortSummary && <p class="post-summary">{post.data.summary}</p>}
|
{options.shortSummary && <p class="post-summary">{post.data.summary}</p>}
|
||||||
|
|
||||||
{
|
{
|
||||||
longSummary && (
|
options.longSummary && (
|
||||||
<>
|
<>
|
||||||
<p class="post-long-summary">
|
<p class="post-long-summary">
|
||||||
{post.body.slice(0, 500).replace(/(<([^>]+)>)/gi, "")}
|
{post.body.slice(0, 500).replace(/(<([^>]+)>)/gi, "")}
|
||||||
|
@ -114,11 +116,15 @@ const { Content } = await post.render();
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
fullText && (
|
options.fullText && (
|
||||||
<div class="text-lg">
|
<div class="text-lg">
|
||||||
<Content />
|
<Content />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
{postFooter && <p class="text-gray-600 text-sm">{postDateFormatted}</p>}
|
{
|
||||||
|
options.postFooter && (
|
||||||
|
<p class="text-gray-600 text-sm">{postDateFormatted}</p>
|
||||||
|
)
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
10
src/images/calendar.svg
Normal file
10
src/images/calendar.svg
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="18"
|
||||||
|
height="18"
|
||||||
|
fill="#6d6d6d"
|
||||||
|
viewBox="0 0 256 256"
|
||||||
|
><path
|
||||||
|
d="M208,32H184V24a8,8,0,0,0-16,0v8H88V24a8,8,0,0,0-16,0v8H48A16,16,0,0,0,32,48V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V48A16,16,0,0,0,208,32ZM72,48v8a8,8,0,0,0,16,0V48h80v8a8,8,0,0,0,16,0V48h24V80H48V48ZM208,208H48V96H208V208Zm-68-76a12,12,0,1,1-12-12A12,12,0,0,1,140,132Zm44,0a12,12,0,1,1-12-12A12,12,0,0,1,184,132ZM96,172a12,12,0,1,1-12-12A12,12,0,0,1,96,172Zm44,0a12,12,0,1,1-12-12A12,12,0,0,1,140,172Zm44,0a12,12,0,1,1-12-12A12,12,0,0,1,184,172Z"
|
||||||
|
></path></svg
|
||||||
|
>
|
After Width: | Height: | Size: 610 B |
9
src/images/questionMark.svg
Normal file
9
src/images/questionMark.svg
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="18"
|
||||||
|
height="18"
|
||||||
|
fill="#6d6d6d"
|
||||||
|
viewBox="0 0 256 256"
|
||||||
|
>
|
||||||
|
<path d="M140,180a12,12,0,1,1-12-12A12,12,0,0,1,140,180ZM128,72c-22.06,0-40,16.15-40,36v4a8,8,0,0,0,16,0v-4c0-11,10.77-20,24-20s24,9,24,20-10.77,20-24,20a8,8,0,0,0-8,8v8a8,8,0,0,0,16,0v-.72c18.24-3.35,32-17.9,32-35.28C168,88.15,150.06,72,128,72Zm104,56A104,104,0,1,1,128,24,104.11,104.11,0,0,1,232,128Zm-16,0a88,88,0,1,0-88,88A88.1,88.1,0,0,0,216,128Z" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 489 B |
|
@ -5,6 +5,7 @@ import Footer from "@/components/Footer.astro";
|
||||||
import Header from "@/components/Header.astro";
|
import Header from "@/components/Header.astro";
|
||||||
import Layout from "@/layouts/Layout.astro";
|
import Layout from "@/layouts/Layout.astro";
|
||||||
import Post from "@/components/Post.astro";
|
import Post from "@/components/Post.astro";
|
||||||
|
import EmojiReactionForm from "@/components/EmojiReactionForm.astro";
|
||||||
|
|
||||||
const { entry } = Astro.props;
|
const { entry } = Astro.props;
|
||||||
|
|
||||||
|
@ -15,38 +16,11 @@ export async function getStaticPaths() {
|
||||||
props: { entry },
|
props: { entry },
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
const backendHost = import.meta.env.PUBLIC_BACKEND_HOST;
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<style>
|
|
||||||
.emoji-label {
|
|
||||||
@apply cursor-pointer bg-zinc-200 p-1 rounded-full;
|
|
||||||
}
|
|
||||||
.emoji-input {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.emoji-input:checked + .emoji-label {
|
|
||||||
@apply cursor-pointer bg-zinc-200 p-1 rounded-full outline outline-1;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<Layout title="log101">
|
<Layout title="log101">
|
||||||
<Header />
|
<Header />
|
||||||
<Post post={entry} componentType="full" />
|
<Post post={entry} componentType="full" />
|
||||||
|
<EmojiReactionForm postId={entry.id} />
|
||||||
<form
|
|
||||||
hx-post=`${backendHost}/blog/api/forms/emoji/post`
|
|
||||||
hx-target="#reaction-buttons"
|
|
||||||
>
|
|
||||||
<input type="hidden" name="postId" value=`${entry.id}` />
|
|
||||||
<div
|
|
||||||
id="reaction-buttons"
|
|
||||||
hx-get=`${backendHost}/blog/api/forms/emoji?postId=${entry.id}`
|
|
||||||
hx-trigger="load"
|
|
||||||
hx-swap="innerHTML"
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
<Footer />
|
<Footer />
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|
|
@ -1,6 +1,20 @@
|
||||||
const cells = ['30', '20', '51', '01', '62', '63', '03', '64', '54', '44', '34', '24', '14']
|
const cells = [
|
||||||
|
"30",
|
||||||
|
"20",
|
||||||
|
"51",
|
||||||
|
"01",
|
||||||
|
"62",
|
||||||
|
"63",
|
||||||
|
"03",
|
||||||
|
"64",
|
||||||
|
"54",
|
||||||
|
"44",
|
||||||
|
"34",
|
||||||
|
"24",
|
||||||
|
"14",
|
||||||
|
];
|
||||||
|
|
||||||
export const heavyWeightSpaceshipCell = (x, y) => {
|
export const heavyWeightSpaceshipCell = (x, y) => {
|
||||||
const coor = `${x}${y}`
|
const coordinates = `${x}${y}`;
|
||||||
return cells.includes(coor)
|
return cells.includes(coordinates);
|
||||||
}
|
};
|
||||||
|
|
|
@ -18,15 +18,6 @@ body {
|
||||||
background-color: #f5fffa;
|
background-color: #f5fffa;
|
||||||
}
|
}
|
||||||
|
|
||||||
.emoji-button {
|
|
||||||
border: none;
|
|
||||||
@apply text-lg rounded-full p-2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.emoji-buttons-container {
|
|
||||||
@apply flex flex-row gap-2;
|
|
||||||
}
|
|
||||||
|
|
||||||
@layer components {
|
@layer components {
|
||||||
.posts {
|
.posts {
|
||||||
@apply flex flex-col gap-10 md:gap-8;
|
@apply flex flex-col gap-10 md:gap-8;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user