Update content documentation and implement basic learn page
This commit is contained in:
@@ -93,6 +93,9 @@ export default async function BlogPostPage({ params }) {
|
||||
// Get related articles with improved algorithm
|
||||
const allPosts = getAllPosts();
|
||||
|
||||
// Create slug order for consistent background cycling
|
||||
const slugOrder = allPosts.map((post) => post.slug);
|
||||
|
||||
// Simple related articles algorithm based on content similarity
|
||||
const getRelatedArticles = (currentPost, allPosts, limit = 3) => {
|
||||
const otherPosts = allPosts.filter((p) => p.slug !== currentPost.slug);
|
||||
@@ -265,6 +268,7 @@ export default async function BlogPostPage({ params }) {
|
||||
<RelatedArticles
|
||||
relatedPosts={relatedArticles}
|
||||
currentPostSlug={post.slug}
|
||||
slugOrder={slugOrder}
|
||||
/>
|
||||
|
||||
{/* Ask Organizer Section */}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { getAllBlogPosts } from "../../lib/content";
|
||||
import Header from "../components/Header";
|
||||
import ContentThumbnailTemplate from "../components/ContentThumbnailTemplate";
|
||||
import ContentContainer from "../components/ContentContainer";
|
||||
|
||||
@@ -31,7 +30,6 @@ export default function BlogPage() {
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-[#F4F3F1]">
|
||||
<Header />
|
||||
<main className="pt-16">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
|
||||
<div className="text-center mb-12">
|
||||
|
||||
@@ -13,9 +13,10 @@ const ContentThumbnailTemplate = ({
|
||||
post,
|
||||
className = "",
|
||||
variant = "vertical", // Internal prop for testing/development
|
||||
slugOrder = [], // Array of slugs for consistent icon cycling
|
||||
}) => {
|
||||
// Post-specific background selection - different SVG for each post
|
||||
const getBackgroundImage = (slug, variant) => {
|
||||
const getBackgroundImage = (slug, variant, slugOrder) => {
|
||||
const verticalImages = [
|
||||
getAssetPath(ASSETS.VERTICAL_1),
|
||||
getAssetPath(ASSETS.VERTICAL_2),
|
||||
@@ -28,23 +29,20 @@ const ContentThumbnailTemplate = ({
|
||||
getAssetPath(ASSETS.HORIZONTAL_3),
|
||||
];
|
||||
|
||||
const images = variant === "vertical" ? verticalImages : horizontalImages;
|
||||
if (!slug)
|
||||
return variant === "vertical" ? verticalImages[0] : horizontalImages[0];
|
||||
|
||||
if (!slug) return images[0];
|
||||
|
||||
// Simple cycling approach to ensure different styles
|
||||
const slugOrder = [
|
||||
"building-community-trust",
|
||||
"operational-security-mutual-aid",
|
||||
"making-decisions-without-hierarchy",
|
||||
"resolving-active-conflicts",
|
||||
];
|
||||
// Use the passed slugOrder for consistent cycling through background variants
|
||||
const index = slugOrder.indexOf(slug);
|
||||
const finalIndex = index >= 0 ? index % images.length : 0;
|
||||
return images[finalIndex];
|
||||
const backgroundIndex = index >= 0 ? index % 3 : 0; // Cycle through 3 background variants
|
||||
|
||||
// Return the same background index for both vertical and horizontal variants
|
||||
return variant === "vertical"
|
||||
? verticalImages[backgroundIndex]
|
||||
: horizontalImages[backgroundIndex];
|
||||
};
|
||||
|
||||
const backgroundImage = getBackgroundImage(post.slug, variant);
|
||||
const backgroundImage = getBackgroundImage(post.slug, variant, slugOrder);
|
||||
|
||||
if (variant === "vertical") {
|
||||
return (
|
||||
|
||||
@@ -9,7 +9,7 @@ import { getAssetPath, ASSETS } from "../../lib/assetUtils";
|
||||
// Configuration data for testing
|
||||
export const navigationItems = [
|
||||
{ href: "#", text: "Use cases", extraPadding: true },
|
||||
{ href: "#", text: "Learn" },
|
||||
{ href: "/learn", text: "Learn" },
|
||||
{ href: "#", text: "About" },
|
||||
];
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ export default function HomeHeader() {
|
||||
|
||||
const navigationItems = [
|
||||
{ href: "#", text: "Use cases", extraPadding: true },
|
||||
{ href: "#", text: "Learn" },
|
||||
{ href: "/learn", text: "Learn" },
|
||||
{ href: "#", text: "About" },
|
||||
];
|
||||
|
||||
@@ -79,10 +79,10 @@ export default function HomeHeader() {
|
||||
? size === "home" || size === "homeMd"
|
||||
? "homeMd"
|
||||
: size === "large"
|
||||
? "large"
|
||||
: size === "homeXlarge"
|
||||
? "homeXlarge"
|
||||
: "xsmallUseCases"
|
||||
? "large"
|
||||
: size === "homeXlarge"
|
||||
? "homeXlarge"
|
||||
: "xsmallUseCases"
|
||||
: size
|
||||
}
|
||||
variant={
|
||||
|
||||
@@ -3,10 +3,14 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import ContentThumbnailTemplate from "./ContentThumbnailTemplate";
|
||||
|
||||
export default function RelatedArticles({ relatedPosts, currentPostSlug }) {
|
||||
export default function RelatedArticles({
|
||||
relatedPosts,
|
||||
currentPostSlug,
|
||||
slugOrder = [],
|
||||
}) {
|
||||
// Filter out the current post from related posts
|
||||
const filteredPosts = relatedPosts.filter(
|
||||
(post) => post.slug !== currentPostSlug,
|
||||
(post) => post.slug !== currentPostSlug
|
||||
);
|
||||
|
||||
const [currentIndex, setCurrentIndex] = useState(0);
|
||||
@@ -93,7 +97,7 @@ export default function RelatedArticles({ relatedPosts, currentPostSlug }) {
|
||||
const handleMouseUp = () => {
|
||||
document.removeEventListener(
|
||||
"mousemove",
|
||||
handleMouseMove,
|
||||
handleMouseMove
|
||||
);
|
||||
document.removeEventListener("mouseup", handleMouseUp);
|
||||
};
|
||||
@@ -112,6 +116,7 @@ export default function RelatedArticles({ relatedPosts, currentPostSlug }) {
|
||||
<ContentThumbnailTemplate
|
||||
post={relatedPost}
|
||||
variant="vertical"
|
||||
slugOrder={slugOrder}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
@@ -133,8 +138,8 @@ export default function RelatedArticles({ relatedPosts, currentPostSlug }) {
|
||||
index === currentIndex
|
||||
? `${progress}%`
|
||||
: index < currentIndex
|
||||
? "100%"
|
||||
: "0%",
|
||||
? "100%"
|
||||
: "0%",
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
import ContentThumbnailTemplate from "../components/ContentThumbnailTemplate";
|
||||
|
||||
// Mock blog post data for testing
|
||||
const mockPost1 = {
|
||||
slug: "resolving-active-conflicts",
|
||||
frontmatter: {
|
||||
title: "Resolving Active Conflicts",
|
||||
description:
|
||||
"Practical steps for resolving conflicts while maintaining trust, cooperation, and shared goals",
|
||||
author: "Author name",
|
||||
date: "2025-04-15",
|
||||
},
|
||||
};
|
||||
|
||||
const mockPost2 = {
|
||||
slug: "operational-security-mutual-aid",
|
||||
frontmatter: {
|
||||
title: "Operational Security for Mutual Aid",
|
||||
description:
|
||||
"Tactics to protect members, secure communication, and prevent Infiltration",
|
||||
author: "Author name",
|
||||
date: "2025-04-10",
|
||||
},
|
||||
};
|
||||
|
||||
const mockPost3 = {
|
||||
slug: "making-decisions-without-hierarchy",
|
||||
frontmatter: {
|
||||
title: "Making decisions without hierarchy",
|
||||
description:
|
||||
"A brief guide to collaborative nonhierarchical decision making",
|
||||
author: "Author name",
|
||||
date: "2025-04-05",
|
||||
},
|
||||
};
|
||||
|
||||
export default function LearnPage() {
|
||||
// Mock slug order for consistent background cycling
|
||||
const mockSlugOrder = [
|
||||
"resolving-active-conflicts",
|
||||
"operational-security-mutual-aid",
|
||||
"making-decisions-without-hierarchy",
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-[#F4F3F1]">
|
||||
<div className="max-w-6xl mx-auto p-8 pt-24">
|
||||
<h1 className="text-3xl font-bold text-[var(--color-content-default-primary)] mb-8">
|
||||
Learn
|
||||
</h1>
|
||||
|
||||
<div className="space-y-12">
|
||||
{/* Featured Articles */}
|
||||
<section>
|
||||
<h2 className="text-2xl font-semibold text-[var(--color-content-default-primary)] mb-6">
|
||||
Featured Articles
|
||||
</h2>
|
||||
<div className="flex flex-wrap gap-6">
|
||||
<ContentThumbnailTemplate
|
||||
post={mockPost1}
|
||||
className="mb-4"
|
||||
slugOrder={mockSlugOrder}
|
||||
/>
|
||||
<ContentThumbnailTemplate
|
||||
post={mockPost2}
|
||||
className="mb-4"
|
||||
slugOrder={mockSlugOrder}
|
||||
/>
|
||||
<ContentThumbnailTemplate
|
||||
post={mockPost3}
|
||||
className="mb-4"
|
||||
slugOrder={mockSlugOrder}
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* More Articles */}
|
||||
<section>
|
||||
<h2 className="text-2xl font-semibold text-[var(--color-content-default-primary)] mb-6">
|
||||
More Articles
|
||||
</h2>
|
||||
<div className="space-y-4">
|
||||
<ContentThumbnailTemplate
|
||||
post={mockPost1}
|
||||
variant="horizontal"
|
||||
slugOrder={mockSlugOrder}
|
||||
/>
|
||||
<ContentThumbnailTemplate
|
||||
post={mockPost2}
|
||||
variant="horizontal"
|
||||
slugOrder={mockSlugOrder}
|
||||
/>
|
||||
<ContentThumbnailTemplate
|
||||
post={mockPost3}
|
||||
variant="horizontal"
|
||||
slugOrder={mockSlugOrder}
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Coming Soon */}
|
||||
<section className="bg-white p-6 rounded-lg shadow">
|
||||
<h2 className="text-xl font-semibold text-[var(--color-content-default-primary)] mb-4">
|
||||
More Content Coming Soon
|
||||
</h2>
|
||||
<p className="text-[var(--color-content-default-secondary)]">
|
||||
We're working on adding more educational content to help you build
|
||||
better communities. Check back soon for new articles and
|
||||
resources.
|
||||
</p>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,116 +0,0 @@
|
||||
import ContentThumbnailTemplate from "../components/ContentThumbnailTemplate";
|
||||
|
||||
// Mock blog post data for testing
|
||||
const mockPost1 = {
|
||||
slug: "resolving-active-conflicts",
|
||||
frontmatter: {
|
||||
title: "Resolving Active Conflicts",
|
||||
description:
|
||||
"Practical steps for resolving conflicts while maintaining trust, cooperation, and shared goals",
|
||||
author: "Author name",
|
||||
date: "2025-04-15",
|
||||
},
|
||||
};
|
||||
|
||||
const mockPost2 = {
|
||||
slug: "operational-security-mutual-aid",
|
||||
frontmatter: {
|
||||
title: "Operational Security for Mutual Aid",
|
||||
description:
|
||||
"Tactics to protect members, secure communication, and prevent Infiltration",
|
||||
author: "Author name",
|
||||
date: "2025-04-10",
|
||||
},
|
||||
};
|
||||
|
||||
const mockPost3 = {
|
||||
slug: "making-decisions-without-hierarchy",
|
||||
frontmatter: {
|
||||
title: "Making decisions without hierarchy",
|
||||
description:
|
||||
"A brief guide to collaborative nonhierarchical decision making",
|
||||
author: "Author name",
|
||||
date: "2025-04-05",
|
||||
},
|
||||
};
|
||||
|
||||
export default function TestThumbnailPage() {
|
||||
return (
|
||||
<div className="min-h-screen bg-gray-50 p-8">
|
||||
<div className="max-w-6xl mx-auto">
|
||||
<h1 className="text-3xl font-bold text-gray-900 mb-8">
|
||||
ContentThumbnailTemplate Test
|
||||
</h1>
|
||||
|
||||
<div className="space-y-12">
|
||||
{/* Vertical Variant */}
|
||||
<section>
|
||||
<h2 className="text-2xl font-semibold text-gray-800 mb-6">
|
||||
Vertical Variant
|
||||
</h2>
|
||||
<div className="flex flex-wrap gap-6">
|
||||
<ContentThumbnailTemplate post={mockPost1} className="mb-4" />
|
||||
<ContentThumbnailTemplate post={mockPost2} className="mb-4" />
|
||||
<ContentThumbnailTemplate post={mockPost3} className="mb-4" />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Horizontal Variant */}
|
||||
<section>
|
||||
<h2 className="text-2xl font-semibold text-gray-800 mb-6">
|
||||
Horizontal Variant
|
||||
</h2>
|
||||
<div className="space-y-4">
|
||||
<ContentThumbnailTemplate post={mockPost1} variant="horizontal" />
|
||||
<ContentThumbnailTemplate post={mockPost2} variant="horizontal" />
|
||||
<ContentThumbnailTemplate post={mockPost3} variant="horizontal" />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Component Props */}
|
||||
<section className="bg-white p-6 rounded-lg shadow">
|
||||
<h2 className="text-xl font-semibold text-gray-800 mb-4">
|
||||
Component Props
|
||||
</h2>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 text-sm">
|
||||
<div>
|
||||
<h3 className="font-medium text-gray-700 mb-2">
|
||||
Required Props:
|
||||
</h3>
|
||||
<ul className="space-y-1 text-gray-600">
|
||||
<li>
|
||||
<code>post</code> - Blog post object with frontmatter
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="font-medium text-gray-700 mb-2">
|
||||
Optional Props:
|
||||
</h3>
|
||||
<ul className="space-y-1 text-gray-600">
|
||||
<li>
|
||||
<code>className</code> - Additional CSS classes
|
||||
</li>
|
||||
<li>
|
||||
<code>variant</code> - "vertical" (default) or
|
||||
"horizontal" (for development/testing)
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Mock Data */}
|
||||
<section className="bg-white p-6 rounded-lg shadow">
|
||||
<h2 className="text-xl font-semibold text-gray-800 mb-4">
|
||||
Mock Data Structure
|
||||
</h2>
|
||||
<pre className="bg-gray-100 p-4 rounded text-sm overflow-x-auto">
|
||||
{JSON.stringify(mockPost1, null, 2)}
|
||||
</pre>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -2,6 +2,31 @@
|
||||
|
||||
A simple guide for creating blog content for Community Rule.
|
||||
|
||||
## How to Upload an Article
|
||||
|
||||
Here's how to contribute a new article:
|
||||
|
||||
1. **Fork the repository** (if you haven't already)
|
||||
2. **Create a new branch** for your article: `git checkout -b add-my-article-title`
|
||||
3. **Create your article file** in the `content/blog/` directory
|
||||
4. **Test locally** (optional but recommended):
|
||||
- Run `npm install` to install dependencies
|
||||
- Run `npm run dev` to start the development server
|
||||
- Visit `http://localhost:3000/blog/your-article-slug` to preview
|
||||
5. **Commit your changes**:
|
||||
```bash
|
||||
git add content/blog/your-article.md
|
||||
git commit -m "Add article: Your Article Title"
|
||||
```
|
||||
6. **Push to your fork**:
|
||||
```bash
|
||||
git push origin add-my-article-title
|
||||
```
|
||||
7. **Create a pull request** in Gitea with:
|
||||
- Clear title describing your article
|
||||
- Brief description of what the article covers
|
||||
- Any relevant context or notes for reviewers
|
||||
|
||||
## Quick Start
|
||||
|
||||
1. **Copy the template**: Use `content/blog/_template.md` as your starting point
|
||||
|
||||
Reference in New Issue
Block a user