diff options
| author | Andrew Lee <alee14498@protonmail.com> | 2024-02-04 16:48:49 -0500 |
|---|---|---|
| committer | Andrew Lee <alee14498@protonmail.com> | 2024-02-04 16:57:23 -0500 |
| commit | 6cd9fb7c8964f8f1b3cc8137bbda45a633e62587 (patch) | |
| tree | 74451a3cac396db1b576379e08870d05448de7e7 /src | |
| parent | 415abb0753801d7155adbcc8ee3b13d6c1d96221 (diff) | |
| download | personal-website-6cd9fb7c8964f8f1b3cc8137bbda45a633e62587.tar.gz personal-website-6cd9fb7c8964f8f1b3cc8137bbda45a633e62587.tar.bz2 personal-website-6cd9fb7c8964f8f1b3cc8137bbda45a633e62587.zip | |
Update AstroJS; sanitize HTML and markdown support in Guestbook form
Diffstat (limited to 'src')
| -rw-r--r-- | src/components/Guestbook.jsx | 25 | ||||
| -rw-r--r-- | src/components/GuestbookForm.jsx | 75 | ||||
| -rw-r--r-- | src/pages/guestbook.astro | 7 | ||||
| -rw-r--r-- | src/services/GuestbookService.js | 13 | ||||
| -rw-r--r-- | src/styles/GuestbookForm.css | 36 |
5 files changed, 98 insertions, 58 deletions
diff --git a/src/components/Guestbook.jsx b/src/components/Guestbook.jsx index 91e2a0f..498bbbe 100644 --- a/src/components/Guestbook.jsx +++ b/src/components/Guestbook.jsx @@ -1,6 +1,7 @@ import { h, Component } from 'preact'; import { pb } from '../services/pocketbase'; import { formatDate } from "../util"; +import sanitizeHtml from 'sanitize-html'; class Guestbook extends Component { state = { @@ -8,7 +9,7 @@ class Guestbook extends Component { error: null }; - async componentDidMount() { + fetchMessages = async () => { try { const message = await pb.collection('guestbook').getFullList({ sort: '-created', @@ -20,6 +21,10 @@ class Guestbook extends Component { } } + async componentDidMount() { + await this.fetchMessages(); + } + render() { const { message, error } = this.state; @@ -33,14 +38,16 @@ class Guestbook extends Component { return ( <div> - {message.map((g) => ( - <article class="card"> - <h1>Message from: {g.name}</h1> - <small>{formatDate(g.created)}</small> - <p>{g.message}</p> - {g.website && <a href={g.website}>Website</a>} - </article> - ))} + <div class="grid"> + {message.map((g) => ( + <article class="card"> + <h1>Message from: {g.name}</h1> + <small>{formatDate(g.created)}</small> + <div dangerouslySetInnerHTML={{__html: sanitizeHtml(g.message)}}/> + {g.website && <a href={g.website}>Website</a>} + </article> + ))} + </div> </div> ); } diff --git a/src/components/GuestbookForm.jsx b/src/components/GuestbookForm.jsx index aae5e10..b8fc1c2 100644 --- a/src/components/GuestbookForm.jsx +++ b/src/components/GuestbookForm.jsx @@ -1,12 +1,16 @@ import { h, Component } from 'preact'; import { createMessage } from '../services/GuestbookService'; +import '../styles/GuestbookForm.css'; +import { marked } from "marked"; +import DOMPurify from 'dompurify'; class GuestbookForm extends Component { state = { name: '', email: '', website: '', - message: '' + message: '', + isMessageSent: false, }; handleChange = (e) => { @@ -15,40 +19,49 @@ class GuestbookForm extends Component { handleSubmit = async (e) => { e.preventDefault(); - await createMessage(this.state); - this.setState({ - name: '', - email: '', - website: '', - message: '' - }); + + if (this.state.isMessageSent) { + return; + } + + const messageHtml = marked(DOMPurify.sanitize(this.state.message)); + try { + await createMessage({ ...this.state, message: messageHtml }); + + this.setState({ + name: '', + email: '', + website: '', + message: '', + isMessageSent: true, + errorMessage: '' + }); + } catch (error) { + this.setState({ errorMessage: error.message }); + } } render() { return ( - <form class="card" onSubmit={this.handleSubmit}> - <h2>Submit Message</h2> - <label> - Name<br /> - <input type="text" name="name" placeholder="Name" required value={this.state.name} onChange={this.handleChange} /> - </label> - <br /> - <label> - Email Address<br /> - <input type="email" name="email" placeholder="Email Address (optional)" value={this.state.email} onChange={this.handleChange} /> - </label> - <br /> - <label> - Your Website<br /> - <input type="url" name="website" placeholder="https://example.com (optional)" value={this.state.website} onChange={this.handleChange} /> - </label> - <br /> - <label> - Message<br /> - <textarea name="message" placeholder="Message (Up to 1000 characters)" required value={this.state.message} onChange={this.handleChange}></textarea> - </label> - <button type="submit">Send</button> - </form> + <div class="card"> + <form onSubmit={this.handleSubmit}> + <h2>Submit Message</h2> + <label>Name</label> + <input type="text" name="name" placeholder="Name" required value={this.state.name} + onChange={this.handleChange}/> + <label>Email Address</label> + <input type="email" name="email" placeholder="hello@example.com (optional)" value={this.state.email} + onChange={this.handleChange}/> + <label>Your Website</label> + <input type="url" name="website" placeholder="https://example.com (optional)" + value={this.state.website} onChange={this.handleChange}/> + <label>Message (Supports Markdown)</label> + <textarea name="message" placeholder="Message" required value={this.state.message} + onChange={this.handleChange}></textarea> + <button type="submit">Send</button> + </form> + {this.state.isMessageSent && <p>Sent successfully!</p>} + </div> ); } } diff --git a/src/pages/guestbook.astro b/src/pages/guestbook.astro index 3ea4c28..661dff2 100644 --- a/src/pages/guestbook.astro +++ b/src/pages/guestbook.astro @@ -11,11 +11,6 @@ import Guestbook from '../components/Guestbook' <p>Feel free to send a nice message here!</p> </div> <GuestbookForm client:visible /> - <div class="grid"> - <Guestbook client:visible /> - </div> + <Guestbook client:visible /> </main> </Page> -<script> - -</script> diff --git a/src/services/GuestbookService.js b/src/services/GuestbookService.js index 3e29c8d..eebb8e5 100644 --- a/src/services/GuestbookService.js +++ b/src/services/GuestbookService.js @@ -1,18 +1,7 @@ import { pb } from './pocketbase' -let name; -let email; -let website; -let message; - -export async function createMessage() { +export async function createMessage(data) { try { - const data = { - name: name, - email: email, - website: website, - message: message - }; return await pb.collection('guestbook').create(data); } catch (error) { console.error(error); diff --git a/src/styles/GuestbookForm.css b/src/styles/GuestbookForm.css new file mode 100644 index 0000000..fa31429 --- /dev/null +++ b/src/styles/GuestbookForm.css @@ -0,0 +1,36 @@ +.card form { + display: flex; + flex-direction: column; + gap: 10px; +} + +.card form input, +.card form textarea { + padding: 10px; + border-radius: 5px; + background: #2c2c2c; + color: #FFFFFF; + border: 1px solid #4b4b4b; +} + +.card form textarea[name="message"] { + height: 200px; +} + +.card form button { + padding: 10px; + border-radius: 5px; + border: none; + background-color: #609460; + color: white; + cursor: pointer; +} + +.card form button:hover { + background-color: #486e48; + transition: ease-in-out 0.2s; +} + +.card form label { + display: block; +} |
