-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #50 from INTO-CPS-Association/9-provide-a-block-te…
…mplates-gallery initial functionality for block templates.
- Loading branch information
Showing
20 changed files
with
1,387 additions
and
87 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,40 @@ | ||
import React from 'react'; | ||
import ChoiceGroupComponent from './choiceGroup'; | ||
import Block from './Components/SingleBlock'; | ||
import BlockDropdownMenu from './Components/BlockDropdownMenu'; | ||
import { useBlockContext } from './Components/BlockContext'; | ||
import { BlockData } from './Data/interface'; | ||
import './App.css'; | ||
import { nanoid } from 'nanoid' | ||
import blockService from './Components/BlocksComponentsMap'; | ||
|
||
|
||
export const App: React.FC = () => { | ||
return ( | ||
<div className = "App"> | ||
<header className = "App-header"> | ||
<ChoiceGroupComponent /> | ||
</header> | ||
</div> | ||
); | ||
} | ||
//state | ||
const { projectData, setProjectData } = useBlockContext(); | ||
|
||
|
||
//------------------ FUNCTIONALITY ------------------// | ||
//add block | ||
const handleBlockAdd = (block: Omit<BlockData, "id">) => { | ||
setProjectData([...projectData, { ...block, id: nanoid() }]); | ||
}; | ||
|
||
|
||
//------------------ RENDER ------------------// | ||
return ( | ||
<div className="app-container"> | ||
<h1 className="app-title">My Project</h1> | ||
<p className="app-description">A project description</p> | ||
|
||
<BlockDropdownMenu onBlockAdd={handleBlockAdd} blockTypes={blockService.getBlockTypes()} /> | ||
|
||
<div className="blocks-container"> | ||
{projectData.map((block) => ( | ||
<Block key={block.id} {...block} /> | ||
))} | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import React, { useState } from 'react'; | ||
import { BlockProps } from '../Data/interface'; | ||
|
||
|
||
const AudioBlock: React.FC<BlockProps> = ({ data, onDataChange }) => { | ||
//state variables | ||
const [src, setSrc] = useState(data); | ||
|
||
//update the src when the data changes | ||
const handleSrcChange = (e: React.ChangeEvent<HTMLInputElement>) => { | ||
const newSrc = e.target.value; | ||
setSrc(newSrc); | ||
onDataChange(newSrc); | ||
}; | ||
|
||
//------------------ RENDER ------------------// | ||
return ( | ||
<div className="audio-block"> | ||
<audio controls src={src}> | ||
Your browser does not support the audio element. | ||
</audio> | ||
<input type="text" placeholder="Enter audio URL..." value={src} onChange={handleSrcChange} /> | ||
</div> | ||
); | ||
}; | ||
|
||
export default AudioBlock; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import React, { useState } from 'react'; | ||
import { BlockProps } from '../Data/interface'; | ||
import AceEditor from 'react-ace'; | ||
import "../Styling/CodeSnippetBlock.css" | ||
import 'ace-builds/src-noconflict/mode-javascript'; | ||
import 'ace-builds/src-noconflict/theme-monokai'; | ||
import 'ace-builds/src-noconflict/worker-javascript'; // this line is important | ||
|
||
|
||
//------------------ CODE SNIPPET BLOCK COMPONENT ------------------// | ||
const CodeSnippetBlock: React.FC<BlockProps> = ({ data, onDataChange }) => { | ||
//state variables | ||
const [code, setCode] = useState(data); | ||
|
||
//update the code when the data changes | ||
const handleCodeChange = (newValue: string) => { | ||
setCode(newValue); | ||
onDataChange(newValue); | ||
}; | ||
|
||
//------------------ RENDER ------------------// | ||
return ( | ||
<AceEditor | ||
mode="javascript" | ||
theme="monokai" | ||
value={code} | ||
onChange={handleCodeChange} | ||
name="UNIQUE_ID_OF_DIV" | ||
editorProps={{ $blockScrolling: true }} | ||
setOptions={{ useWorker: false }} | ||
/> | ||
); | ||
}; | ||
|
||
|
||
export default CodeSnippetBlock; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
import React, {useState} from 'react'; | ||
import { BlockProps } from '../Data/interface'; | ||
import '../Styling/ImageBlock.css'; | ||
|
||
|
||
|
||
const ImageBlock: React.FC<BlockProps> = ({ id, data, onDataChange }) => { | ||
// state variables | ||
const [inputSrc, setInputSrc] = useState(data); | ||
const [isValidSrc, setIsValidSrc] = useState(true); | ||
|
||
// update the src when the data changes | ||
const handleImageChange = (e: React.ChangeEvent<HTMLInputElement>) => { | ||
setInputSrc(e.target.value); | ||
setIsValidSrc(true); // Reset the validation state | ||
}; | ||
|
||
const handleBlur = () => { | ||
// Check if the input is a valid URL | ||
try { | ||
new URL(inputSrc); | ||
} catch (_) { | ||
setIsValidSrc(false); // If the input is not a valid URL, set the validation state to false | ||
} | ||
onDataChange(inputSrc); | ||
} | ||
|
||
const imageUrl = isValidSrc ? inputSrc : '/path-to-default-image.jpg'; | ||
|
||
// RENDER | ||
return ( | ||
<div> | ||
<input | ||
type="text" | ||
placeholder="Enter image URL..." | ||
value={inputSrc} | ||
onChange={handleImageChange} | ||
onBlur={handleBlur} | ||
/> | ||
<div className="block-container" style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', paddingTop: '10px' }}> | ||
<img src={imageUrl} alt="Block content" /> | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
export default ImageBlock; | ||
|
||
/* | ||
const ImageBlock: React.FC<BlockProps> = ({ id, data, onDataChange }) => { | ||
//state variables | ||
const [src, setSrc] = useState(data); | ||
//update the src when the data changes | ||
const handleImageChange = (e: React.ChangeEvent<HTMLInputElement>) => { | ||
const newSrc = e.target.value; | ||
setSrc(newSrc); | ||
onDataChange(newSrc); // notify the parent about the change | ||
}; | ||
//------------------ RENDER ------------------// | ||
return ( | ||
<div className="image-block"> | ||
<input type="text" placeholder="Enter image URL..." value={src} onChange={handleImageChange} /> | ||
<img src={src} onError={(e) => (e.target as HTMLImageElement).src = '/path-to-default-image.jpg'} alt="Block content" /> | ||
</div> | ||
); | ||
}; | ||
export default ImageBlock; | ||
*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
import React, { useState } from 'react'; | ||
import ReactQuill from 'react-quill'; | ||
import { BlockProps } from '../Data/interface'; | ||
import 'react-quill/dist/quill.snow.css'; // import styles | ||
|
||
// Quill modules to attach to editor | ||
const modules = { | ||
toolbar: [ | ||
['bold', 'italic', 'underline', 'strike'], // toggled buttons | ||
[{ 'font': [] }], | ||
[{ 'size': ['small', false, 'large', 'huge'] }], // custom dropdown | ||
], | ||
}; | ||
|
||
// Quill formats to allow in editor | ||
const formats = [ | ||
'bold', 'italic', 'underline', 'strike', | ||
'font', 'size' | ||
]; | ||
|
||
|
||
//------------------ TEXT BLOCK COMPONENT ------------------// | ||
const TextBlock: React.FC<BlockProps> = ({ id, data, onDataChange }) => { | ||
//state variable | ||
const [text, setText] = useState(data); | ||
|
||
//------------------ FUNCTIONALITY ------------------// | ||
const handleChange = (value: string) => { | ||
setText(value); | ||
onDataChange(value); // notify the parent about the change | ||
} | ||
|
||
//------------------ RENDER ------------------// | ||
return ( | ||
<div className="text-block"> | ||
<ReactQuill | ||
value={text} | ||
onChange={handleChange} | ||
modules={modules} | ||
formats={formats} | ||
/> | ||
</div> | ||
); | ||
} | ||
|
||
export default TextBlock; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import React, { createContext, useState, useContext } from 'react'; | ||
import { BlockContextProps, BlockData} from '../Data/interface'; | ||
|
||
//create context | ||
export const BlockContext = createContext<BlockContextProps>({} as BlockContextProps); | ||
|
||
|
||
export const BlockContextProvider: React.FC = ({ children }) => { | ||
//state variables | ||
const [projectData, setProjectData] = useState<BlockData[]>([]); | ||
|
||
//------------------ FUNCTIONALITY ------------------// | ||
const handleBlockDelete = (id: string) => { | ||
setProjectData(prevData => prevData.filter(block => block.id !== id)); | ||
}; | ||
|
||
return ( | ||
<BlockContext.Provider value={{ projectData, setProjectData, handleBlockDelete }}> | ||
{children} | ||
</BlockContext.Provider> | ||
); | ||
}; | ||
|
||
|
||
export const useBlockContext = () => { | ||
const context = useContext(BlockContext); | ||
if (!context) { | ||
throw new Error("useBlockContext must be used within BlockContextProvider"); | ||
} | ||
return context; | ||
}; |
38 changes: 38 additions & 0 deletions
38
components/block-template/src/Components/BlockDropdownMenu.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import React, { useState } from 'react'; | ||
import { BlockData } from '../Data/interface'; | ||
|
||
|
||
//------------------ DROPDOWN COMPONENT ------------------// | ||
const BlockDropdownMenu: React.FC<{ onBlockAdd: (block: Omit<BlockData, 'id'>) => void; // Change the type of block | ||
blockTypes: string[]; | ||
}> = ({ onBlockAdd, blockTypes }) => { | ||
|
||
//state variables | ||
const [selectedBlockType, setSelectedBlockType] = useState<string>(''); | ||
|
||
|
||
//------------------ FUNCTIONALITY ------------------// | ||
//add block | ||
const handleAddBlock = () => { | ||
if (selectedBlockType) { | ||
onBlockAdd({ type: selectedBlockType, data: 'Default Data' }); // remove id from here | ||
} | ||
}; | ||
|
||
//------------------ RENDER ------------------// | ||
return ( | ||
<> | ||
<select value={selectedBlockType} onChange={(e) => setSelectedBlockType(e.target.value)}> | ||
<option value="">--Select a block--</option> | ||
{blockTypes.map((type) => ( | ||
<option key={type} value={type}> | ||
{type} | ||
</option> | ||
))} | ||
</select> | ||
<button onClick={handleAddBlock}>Add Block</button> | ||
</> | ||
); | ||
}; | ||
|
||
export default BlockDropdownMenu; |
Oops, something went wrong.