feat: Rename image and data files
- Add PostCard component - Add WysiwygEditor component - Use 'front-matter' to parse front matter in markdown files for metadata instead of using redundant data objects
This commit is contained in:
80
src/components/Cards/PostCard.jsx
Normal file
80
src/components/Cards/PostCard.jsx
Normal file
@@ -0,0 +1,80 @@
|
||||
// PostCard.jsx
|
||||
import React from 'react';
|
||||
import { Button } from '@progress/kendo-react-buttons';
|
||||
import { Card, CardImage, CardBody } from '@progress/kendo-react-layout';
|
||||
|
||||
const PostCard = ({ post, onEdit }) => {
|
||||
const dataPath = post.header.image;
|
||||
const relativePath = `../../${dataPath}`;
|
||||
const imageUrl = new URL(relativePath, import.meta.url).href;
|
||||
|
||||
const formatDate = (utcString) => {
|
||||
if (!utcString) return '';
|
||||
|
||||
// 1. Create Date object. It parses the UTC string automatically.
|
||||
const date = new Date(utcString);
|
||||
|
||||
// 2. Define options for the desired output format (local time zone)
|
||||
const dateOptions = {
|
||||
year: 'numeric',
|
||||
month: 'short', // e.g., 'Sep'
|
||||
day: 'numeric',
|
||||
hour: 'numeric',
|
||||
minute: '2-digit',
|
||||
hour12: true, // e.g., '9:51 PM'
|
||||
timeZoneName: undefined // Removes the timezone name from the output
|
||||
};
|
||||
|
||||
// 3. Convert to local, human-readable string and clean up formatting
|
||||
// The space between date and time may vary by locale, so we use string replacement for consistency.
|
||||
const formattedDate = date.toLocaleDateString(undefined, dateOptions);
|
||||
|
||||
// This attempts to convert the format '9/20/2025, 9:51 PM' to 'Sep 20, 2025, 9:51 PM'
|
||||
const parts = formattedDate.split(',');
|
||||
if (parts.length > 1) {
|
||||
const timePart = date.toLocaleTimeString(undefined, { hour: 'numeric', minute: '2-digit', hour12: true });
|
||||
const datePart = date.toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric' });
|
||||
return `${datePart}, ${timePart}`;
|
||||
}
|
||||
|
||||
return formattedDate;
|
||||
};
|
||||
|
||||
return (
|
||||
<Card key={post.slug} style={{ width: '250px', textAlign: 'center', display: 'flex' }}>
|
||||
|
||||
{/* 1. Thumbnail Image */}
|
||||
<CardImage
|
||||
src={imageUrl}
|
||||
alt={post.title}
|
||||
style={{ width: '100%', height: '100px', objectFit: 'cover' }}
|
||||
/>
|
||||
|
||||
{/* 2. Title, Date, and Button Container */}
|
||||
<CardBody style={{ flexGrow: 1, padding: '10px', display: 'flex', flexDirection: 'column', justifyContent: 'space-between' }}>
|
||||
|
||||
{/* Title Link */}
|
||||
<div style={{ marginBottom: '5px' }}>
|
||||
<a className="k-link" href={post.canonical_url} target="_blank" rel="noreferrer" style={{ fontWeight: 'bold' }}>
|
||||
{post.title}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{/* Date and Edit Button */}
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', fontSize: '0.85em' }}>
|
||||
<span>{formatDate(post.date)}</span>
|
||||
<Button
|
||||
look="flat"
|
||||
themeColor="primary"
|
||||
onClick={() => onEdit(post.slug)}
|
||||
>
|
||||
Edit
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
</CardBody>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
export default PostCard;
|
@@ -0,0 +1,44 @@
|
||||
import {
|
||||
RichTextEditorComponent,
|
||||
Inject,
|
||||
Toolbar,
|
||||
HtmlEditor,
|
||||
MarkdownEditor,
|
||||
SourceCode,
|
||||
Link, Image
|
||||
} from '@syncfusion/ej2-react-richtexteditor';
|
||||
import * as React from 'react';
|
||||
|
||||
function CampfireToggleEditor(props) {
|
||||
const toolbarOptions = {
|
||||
items: [
|
||||
'Bold', 'Italic', 'Underline', '|',
|
||||
'Formats', 'Alignments', 'OrderedList', 'UnorderedList', '|',
|
||||
'CreateLink', 'Image', '|',
|
||||
'SourceCode',
|
||||
'Undo', 'Redo'
|
||||
]
|
||||
};
|
||||
|
||||
return (
|
||||
<RichTextEditorComponent
|
||||
value={props.value}
|
||||
change={handleEditorChange}
|
||||
editorMode={'Html'}
|
||||
toolbarSettings={toolbarOptions}
|
||||
>
|
||||
<Inject
|
||||
services={[
|
||||
Toolbar,
|
||||
Link,
|
||||
Image,
|
||||
HtmlEditor,
|
||||
MarkdownEditor,
|
||||
SourceCode
|
||||
]}
|
||||
/>
|
||||
</RichTextEditorComponent>
|
||||
);
|
||||
};
|
||||
|
||||
export default CampfireToggleEditor;
|
@@ -11,7 +11,7 @@ export default function Copyright() {
|
||||
>
|
||||
<p>
|
||||
© 2025{" | "}Derek L. Seitz{" | "}
|
||||
<a href="https://dlseitz.dev" target="_blank" rel="noopener noreferrer" class="k-link">
|
||||
<a href="https://dlseitz.dev" target="_blank" rel="noopener noreferrer" className="k-link">
|
||||
dlseitz.dev
|
||||
</a>
|
||||
</p>
|
||||
|
Reference in New Issue
Block a user