Skip to content

Commit

Permalink
create recipe block PoC
Browse files Browse the repository at this point in the history
  • Loading branch information
joshbermanssw committed Oct 14, 2024
1 parent ae3d7b0 commit 2d79307
Show file tree
Hide file tree
Showing 9 changed files with 257 additions and 2 deletions.
5 changes: 5 additions & 0 deletions components/blocks/Blocks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { TinaBanner } from './TinaBanner';
import { HighlightsSection } from './HighlightsSection';
import { SpacerComponent } from './Spacer';
import { CarouselFeatureBlock } from './CarouselFeature';
import RecipeBlock from './Recipe';

export const Blocks = ({
blocks,
Expand Down Expand Up @@ -82,6 +83,10 @@ export const Blocks = ({
return (
<ColumnsBlock key={`block-${index}`} data={block} index={index} />
);
case 'PageBlocksRecipeBlock':
return (
<RecipeBlock data={block} index={index} />
)
case 'PageBlocksShowcase':
return (
<ShowcaseItemsBlock
Expand Down
49 changes: 49 additions & 0 deletions components/blocks/Recipe.template.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
export const RecipeBlock = {
name: 'recipeBlock',
label: 'Recipe Block',
fields: [
{
name: 'title',
label: 'Heading Title',
type: 'string',
},
{
name: 'description',
label: 'Description',
type: 'string',
},
{
name: 'codeblock',
label: 'Code Block',
type: 'rich-text',
},
{
name: 'instruction',
label: 'Instruction',
type: 'object',
list: true,
fields: [
{
name: 'header',
label: 'Header',
type: 'string',
},
{
name: 'itemDescription',
label: 'Item Description',
type: 'string',
},
{
name: 'codeLineStart',
label: 'Code Line Start',
type: 'number',
},
{
name: 'codeLineEnd',
label: 'Code Line End',
type: 'number'
}
],
},
],
};
132 changes: 132 additions & 0 deletions components/blocks/Recipe.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import { TinaMarkdown } from 'tinacms/dist/rich-text';
import React, { useEffect, useState } from 'react';
import Prism from 'prismjs';
import 'prism-themes/themes/prism-night-owl.css';
import 'prismjs/plugins/line-numbers/prism-line-numbers.css';
import 'prismjs/plugins/line-numbers/prism-line-numbers';
import 'prismjs/plugins/line-highlight/prism-line-highlight.css';
import 'prismjs/plugins/line-highlight/prism-line-highlight';

interface RecipeBlockProps {
data: {
title?: string;
description?: string;
codeblock?: any;
instruction?: {
header?: string;
itemDescription?: string;
codeLineStart?: number;
codeLineEnd?: number;
}[];
};
index: number;
}

const RecipeBlock = ({ data }: RecipeBlockProps) => {
const { title, description, codeblock, instruction } = data;

const [highlightLines, setHighlightLines] = useState('7-10');
const [clickedInstruction, setClickedInstruction] = useState<number | null>(null);

useEffect(() => {
console.log(`Highlighting lines: ${highlightLines}`);
}, [highlightLines]);

const handleInstructionClick = (index: number, codeLineStart?: number, codeLineEnd?: number) => {
setHighlightLines(`${codeLineStart}-${codeLineEnd}`);
setClickedInstruction(index === clickedInstruction ? null : index);
};

return (
<div className="recipe-block-container">
<div className="title-description">
<h2 className="font-bold text-3xl">{title || 'Default Title'}</h2>
<p className="font-semibold text-2xl">{description || 'Default Description'}</p>
</div>
<div className="content-wrapper flex">
<div className="instructions w-1/3 flex flex-col">
{instruction?.map((inst, idx) => (
<div
key={idx}
className="instruction-item mb-4 cursor-pointer p-4 border rounded-lg bg-gray-500 text-white"
onClick={() =>
handleInstructionClick(idx, inst.codeLineStart, inst.codeLineEnd)
}
>
<h3 className="font-bold">{`${idx + 1}. ${inst.header || 'Default Header'}`}</h3>
<div
className={`overflow-hidden transition-all duration-500 ease-in-out ${
clickedInstruction === idx ? 'max-h-40 opacity-100' : 'max-h-0 opacity-0'
}`}
>
<p className="mt-2">{inst.itemDescription || 'Default Item Description'}</p>
</div>
</div>
)) || <p>No instructions available.</p>}
</div>

<div className="codeblock w-2/3">
{codeblock ? (
<TinaMarkdown
key={highlightLines}
content={codeblock}
components={{
code_block: (props) => (
console.log('props i found', props),
console.log('highlighted lines', highlightLines),
<CodeBlockWithHighlightLines
{...props}
highlightLines={highlightLines}
/>
),
}}
/>
) : (
<p>No code block available.</p>
)}
</div>
</div>
</div>
);
};

export default RecipeBlock;

interface CodeBlockProps {
value: any;
lang?: string;
children?: React.ReactNode;
highlightLines: string;
}

const CodeBlockWithHighlightLines = ({
value,
lang,
children,
highlightLines,
}: CodeBlockProps) => {
const [isMounted, setIsMounted] = useState(false);

useEffect(() => {
setIsMounted(true);
if (isMounted) {
Prism.highlightAll();
}
}, [isMounted]);

useEffect(() => {
Prism.highlightAll();
}, [highlightLines]);

if (!isMounted) {
return null;
}

return (
<pre className="line-numbers" data-line={highlightLines}>
<code className={`language-${lang || 'jsx'}`}>
{typeof children === 'string' || children ? children : value}
</code>
</pre>
);
};
26 changes: 26 additions & 0 deletions components/tinaMarkdownComponents/recipeComponents.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React, { useEffect } from 'react';
import Prism from 'prismjs';
import 'prism-themes/themes/prism-night-owl.css';
import 'prismjs/plugins/line-numbers/prism-line-numbers.css';
import 'prismjs/plugins/line-numbers/prism-line-numbers';
import 'prismjs/plugins/line-highlight/prism-line-highlight.css';
import 'prismjs/plugins/line-highlight/prism-line-highlight';

export const codeBlockComponents = {
code_block: ({ value, lang, children, highlightLines }) => {
useEffect(() => {

Prism.highlightAll();
}, []);

console.log('this is what I found', highlightLines);

return (
<pre className="line-numbers" data-line={highlightLines || ''}>
<code className={`language-${lang || 'jsx'}`}>
{children || value || ''}
</code>
</pre>
);
},
};
32 changes: 32 additions & 0 deletions content/blocksPages/home.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,38 @@
"description": "TinaCMS is an open-source headless CMS for editing websites with Markdown. Integrates with GitHub and many front-end web frameworks."
},
"blocks": [
{
"title": "Publish all Docs in Category",
"description": "Update each doc in a specific category as published ",
"codeblock": "```javascript\nconst sdk = require('api')('https://docs.readme.com/developers/openapi/62056dee230e07007218be15');\nsdk.auth('PROJECT_API_KEY');\n\nasync function publishDocs() {\n\n const categories = await sdk\n .getCategories({ perPage: \"10\", page: \"1\" })\n .then(res => res.data)\n .catch(err => console.log(err));\n\n const docs = await sdk\n .getCategoryDocs({ slug: categories[0].slug })\n .then(res => res.data)\n .catch(err => console.log(err));\n\n docs.forEach(async (doc) => {\n await sdk.updateDoc({ hidden: false }, { slug: doc.slug });\n });\n}\n\npublishDocs()\n```\n",
"instruction": [
{
"header": "Install the api module from NPM",
"itemDescription": "You can install the api module by running npm install api.",
"codeLineStart": 1,
"codeLineEnd": 5
},
{
"header": "Get the category to mark docs as published",
"itemDescription": "You need the category containing the docs to mark them as published. Here, we'll use the first category",
"codeLineStart": 10,
"codeLineEnd": 12
},
{
"header": "Get all docs in the category",
"itemDescription": "Using the category slug we got from the previous category, we can fetch all of the docs that belong to the category",
"codeLineStart": 7,
"codeLineEnd": 8
},
{
"header": "Iterate over each doc to mark as published",
"itemDescription": "We can iterate over each doc returned in the previous call, and update each one to be published.",
"codeLineStart": 19,
"codeLineEnd": 21
}
],
"_template": "recipeBlock"
},
{
"features": [
{
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
"node-sass": "^9.0.0",
"postcss": "^8.4.18",
"prism-react-renderer": "^2.0.6",
"prism-themes": "^1.9.0",
"prismjs": "^1.29.0",
"prosemirror-tables": "^1.4.0",
"raw-loader": "^4.0.0",
Expand Down
8 changes: 8 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion tina/collectionsSchema/pages.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { tinaBannerTemplate } from '../../components/blocks/TinaBanner.template'
import { highlightsSectionTemplate } from '../../components/blocks/HighlightsSection.template'
import { spacerTemplate } from '../../components/blocks/Spacer.template'
import {carouselFeatureTemplate} from '../../components/blocks/CarouselFeature.template'
import { RecipeBlock } from '../../components/blocks/Recipe.template'

export const pagesCollection = {
label: 'Pages',
Expand Down Expand Up @@ -102,7 +103,8 @@ export const pagesCollection = {
tinaBannerTemplate as Template,
highlightsSectionTemplate as Template,
spacerTemplate as Template,
carouselFeatureTemplate as Template
carouselFeatureTemplate as Template,
RecipeBlock as Template,
],
},
],
Expand Down
2 changes: 1 addition & 1 deletion tina/tina-lock.json

Large diffs are not rendered by default.

0 comments on commit 2d79307

Please sign in to comment.