178 lines
4.8 KiB
JavaScript
178 lines
4.8 KiB
JavaScript
class GuestbookForm extends HTMLElement {
|
|
static get observedAttributes() {
|
|
return ['guestbook'];
|
|
}
|
|
|
|
constructor() {
|
|
super();
|
|
this.attachShadow({ mode: 'open' });
|
|
this._guestbook = this.getAttribute('guestbook') || '';
|
|
this._postUrl = `${this._guestbook}/comments/create/remote`
|
|
this.render();
|
|
}
|
|
|
|
attributeChangedCallback(name, oldValue, newValue) {
|
|
if (name === 'guestbook') {
|
|
this._guestbook = newValue;
|
|
this.render();
|
|
}
|
|
}
|
|
|
|
render() {
|
|
this.shadowRoot.innerHTML = `
|
|
<style>
|
|
form div {
|
|
margin-bottom: 0.75em;
|
|
}
|
|
label {
|
|
display: block;
|
|
font-weight: bold;
|
|
margin-bottom: 0.25em;
|
|
}
|
|
input[type="text"], textarea {
|
|
width: 100%;
|
|
box-sizing: border-box;
|
|
}
|
|
input[type="submit"] {
|
|
font-size: 1em;
|
|
padding: 0.5em 1em;
|
|
}
|
|
</style>
|
|
<form action="${this._postUrl}" method="post">
|
|
<div>
|
|
<label for="authorname">Name</label>
|
|
<input type="text" name="authorname" id="authorname"/>
|
|
</div>
|
|
<div>
|
|
<label for="authoremail">Email (Optional)</label>
|
|
<input type="text" name="authoremail" id="authoremail"/>
|
|
</div>
|
|
<div>
|
|
<label for="authorsite">Site Url (Optional)</label>
|
|
<input type="text" name="authorsite" id="authorsite"/>
|
|
</div>
|
|
<div>
|
|
<label for="content">Comment</label>
|
|
<textarea name="content" id="content"></textarea>
|
|
</div>
|
|
<div>
|
|
<input type="hidden" value="${window.location.pathname}" name="redirect" id="redirect" />
|
|
</div>
|
|
<div>
|
|
<input type="submit" value="Submit"/>
|
|
</div>
|
|
</form>
|
|
`;
|
|
}
|
|
}
|
|
|
|
class CommentList extends HTMLElement {
|
|
static get observedAttributes() {
|
|
return ['guestbook'];
|
|
}
|
|
|
|
constructor() {
|
|
super();
|
|
this.attachShadow({ mode: 'open' });
|
|
this.comments = [];
|
|
this.loading = false;
|
|
this.error = null;
|
|
}
|
|
|
|
connectedCallback() {
|
|
if (this.hasAttribute('guestbook')) {
|
|
this.fetchComments();
|
|
}
|
|
}
|
|
|
|
attributeChangedCallback(name, oldValue, newValue) {
|
|
if (name === 'guestbook' && oldValue !== newValue) {
|
|
this.fetchComments();
|
|
}
|
|
}
|
|
|
|
async fetchComments() {
|
|
const guestbook = this.getAttribute('guestbook');
|
|
if (!guestbook) return;
|
|
this.loading = true;
|
|
this.error = null;
|
|
this.render();
|
|
|
|
const commentsUrl = `${guestbook}/comments`
|
|
|
|
try {
|
|
const response = await fetch(commentsUrl);
|
|
if (!response.ok) throw new Error(`HTTP error: ${response.status}`);
|
|
const data = await response.json();
|
|
this.comments = Array.isArray(data) ? data : [];
|
|
this.loading = false;
|
|
this.render();
|
|
} catch (err) {
|
|
this.error = err.message;
|
|
this.loading = false;
|
|
this.render();
|
|
}
|
|
}
|
|
|
|
formatDate(isoString) {
|
|
if (!isoString) return '';
|
|
const date = new Date(isoString);
|
|
return date.toLocaleString();
|
|
}
|
|
|
|
render() {
|
|
this.shadowRoot.innerHTML = `
|
|
<style>
|
|
.comment-list {
|
|
font-family: Arial, sans-serif;
|
|
border: 1px solid #ddd;
|
|
border-radius: 6px;
|
|
padding: 1em;
|
|
background: #fafafa;
|
|
}
|
|
.comment {
|
|
border-bottom: 1px solid #eee;
|
|
padding: 0.7em 0;
|
|
}
|
|
.comment:last-child {
|
|
border-bottom: none;
|
|
}
|
|
.author {
|
|
font-weight: bold;
|
|
margin-right: 1em;
|
|
}
|
|
.timestamp {
|
|
color: #888;
|
|
font-size: 0.85em;
|
|
}
|
|
.text {
|
|
margin: 0.2em 0 0 0;
|
|
}
|
|
.error {
|
|
color: red;
|
|
}
|
|
</style>
|
|
<div class="comment-list">
|
|
${this.loading
|
|
? `<div>Loading comments...</div>`
|
|
: this.error
|
|
? `<div class="error">Error: ${this.error}</div>`
|
|
: this.comments.length === 0
|
|
? `<div>No comments found.</div>`
|
|
: this.comments.map(comment => `
|
|
<div class="comment">
|
|
<span class="author">${comment.AuthorName || 'Unknown Author'}</span>
|
|
<span class="timestamp">${this.formatDate(comment.Created)}</span>
|
|
<div class="text">${comment.CommentText || ''}</div>
|
|
</div>
|
|
`).join('')
|
|
}
|
|
</div>
|
|
`;
|
|
}
|
|
}
|
|
|
|
customElements.define('guestbook-form', GuestbookForm);
|
|
customElements.define('guestbook-comments', CommentList);
|
|
|