From 0d4b7d107a251a9209f56e9ff7fb172262565f3c Mon Sep 17 00:00:00 2001 From: Rendall Date: Fri, 17 Nov 2023 12:00:55 +0200 Subject: [PATCH 1/9] Add topic path to local dev server --- webpack.frontend.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/webpack.frontend.js b/webpack.frontend.js index 6b23d2c..7599f91 100644 --- a/webpack.frontend.js +++ b/webpack.frontend.js @@ -36,6 +36,9 @@ module.exports = { compress: true, port: 5000, static: path.join(__dirname, "dist"), + historyApiFallback: { + rewrites: [{ from: /^\/topic\/.*$/, to: "/topic/index.html" }], + }, }, devtool: "source-map", entry: { From 70ca67080a61b5ce60962463e8b9820cdbfc4b3c Mon Sep 17 00:00:00 2001 From: Rendall Date: Fri, 17 Nov 2023 12:01:17 +0200 Subject: [PATCH 2/9] Add topic page --- src/static/topic/index.html | 288 +++++++++++++++++++++++++++++++++++- 1 file changed, 284 insertions(+), 4 deletions(-) diff --git a/src/static/topic/index.html b/src/static/topic/index.html index 7813acf..7420227 100644 --- a/src/static/topic/index.html +++ b/src/static/topic/index.html @@ -1,11 +1,291 @@ - - - Hello World + Simple Comment + + + + + + + + + + + + + -

Hello World

+
+ + +

Simple Comment

+
+
+
+

Simple Comment newsletter

+

+ To join the mailing list for news and updates, or to request your own + free instance of Simple Comment, add your email address here. +

+
+
+ + +
+
+ + +
+
+ + + +
+ + +
+
+
+

Simple Comment demo

+

+ Simple Comment is a commenting system that can be added easily + to any website. To try it out, add a comment and your info. You can + use the Question of the Day as a prompt, or type whatever is on your + mind. +

+

+ Question for the day: What kind of people do you most enjoy hanging + out with? +

+
+
+
+ + From f9e71e8288986f290a3f2de07ee35211c2cf9be1 Mon Sep 17 00:00:00 2001 From: Rendall Date: Fri, 17 Nov 2023 12:09:53 +0200 Subject: [PATCH 3/9] Fix threadComments when allComments is undefined --- src/frontend-utilities.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/frontend-utilities.ts b/src/frontend-utilities.ts index 052ce78..5a76e3c 100644 --- a/src/frontend-utilities.ts +++ b/src/frontend-utilities.ts @@ -25,9 +25,10 @@ type MinComment = { */ export const threadComments = ( comment: T, - allComments: U[], + allComments: U[] | undefined, sort: (a: U, b: U) => number = (a, b) => (b.id < a.id ? 0 : 1) ): T => { + if (!allComments) return { ...comment, replies: [] } // Make this robust but warn allComments = allComments.filter(reply => { if (reply && reply.id) return true From 69cd92afaaf1938feb3221baef536293f28adf50 Mon Sep 17 00:00:00 2001 From: Rendall Date: Fri, 17 Nov 2023 12:46:29 +0200 Subject: [PATCH 4/9] Update layout --- src/lib/discussion.xstate.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/discussion.xstate.ts b/src/lib/discussion.xstate.ts index 4074a62..d97521b 100644 --- a/src/lib/discussion.xstate.ts +++ b/src/lib/discussion.xstate.ts @@ -34,7 +34,7 @@ export const discussionMachine = createMachine< DiscussionTypestate >( { - /** @xstate-layout N4IgpgJg5mDOIC5QQJawMYFdaxQewDsBaAMwBs8B3AOhQjLAGIBtABgF1FQAHPXAF3wEuIAB6IiAFgCcADmrSA7AFZFrSZNbTWi6coA0IAJ6IAjK1PVTANknKZagEzKlpgMwBfD4dQZsuQlIKGgoAQ1QCKEYAZQBVAGF4gFFo6LZOJBBeASERcQQiN1N5a0dbFxtpW2s3QxMER0US61ZZc2trPWLZRS8fNCwcISCqajCIqKSAJSmAeSn0kWyUQUI8iTdG6kVHWWULN1kepVrjREli6kk3SV1lTpt3U2U+kF9BgOJyUfQAJzBQoJIjEEslUotMstVsJMvlpJpqI5WG5WEjlLJHG4OpI6mZJI4FNIiXoUS5JEdrK93v5ht8aH8AUDJjN5hCeHwVrlYYh4axEcjUax0ZjsbiGrJpNR7o4ZG45Bcdo4qQMaYE6dQGYDICwOEsOdD1gVHGUpbdNJ09tcyWLTETqBLbmpZJ19sbZMq-EM1cExnhwtr4lMkgBBAAqSTZWX1XNA+Q0fJ02hRdnschlYqKBJ66k2jmKlVMHo+tJ9YF+vzwv0YQdDUwAmpGoTGxGZTIpEYpnnJpOZzLJWmL4dRrDY9hjTM9bPii6qvqXy5XGIGQ+HG9G1tyEOYdMOepo3PYdodTvVMZLWKUZLINLID4peq8CHgIHARNSvXOqHqchvYxJ7m41BuFieiKCOMhaDiZwFKUUoWLaeyND2SKUt4bwqh+Iw0HQDDfpyv4tgUyjPEBIFYmByJtKYYoyoSRysOoxqtA4M6Yeq4woJEeEGpuRDEcopEumBpgQfCNrSIBqLoioEEKqh-Sep8WEav8gKcVA3HNvkbRZtc1iqNojg9sBGYWAo1h7hKyL8SorFKeqmr8JAmkEfkE4XIiV63kUF6KIcNotMOSg9DKrTKAe8J2SWozjM5kLrjCf4FBo2wouo5pCsUEkGNBKKWFUllJjZUXeqMZYVr8LmJYRImAX2HQ6BZejSGKdgEneNSPK0VmeF4HhAA */ + /** @xstate-layout N4IgpgJg5mDOIC5QQJawMYFdaxQewDsBaAMwBs8B3AOhQjLAGIBtABgF1FQAHPXAF3wEuIAB6IALAE4AHNQkB2AIwTWKpawUBWCToA0IAJ6IATKwDM1TUq0yAbOYkmtCu7IC+7g6gzZchUgoaCgBDVAIoRgBlAFUAYTiAUSiotk4kEF4BIRFxBGk5RRU1CQ1tXQkDYwQTaWoZVxMZEyVzOzclGXNPbzQsHCFAqmpQ8MjEgCUJgHkJtJEslEFCXMQFR3qW83N7CS67bSrEGwVqFy0Tc0uGuxUpOx6QH37-YnJh9AAnMBDBCOj4kkUvMMotlsIMnkTJdqCYpAopI4FHDdBolEcEOZ1vUpKw8dCruZWDIpI9nn5Bu8aF8fn9xlNZiCeHwljlIZItEpYV0SeYVBIsQiMbpTiTrIpbHZat0vE8+hSAlTqDTfpAWBwFizwat8rJ5MpVOpNDp9EZEOZOdQ7HjlBc7IoZKwpBIyfKBoqgiM8GE1QAZaYAQQAIkzMlq2aA8gV9cUjeVTdU4VIrTJUyoTMo1LdXb53W9PWBPp88J9GBNEgAVCYATVDYIjYkQMi0WmoUiUiKKOxMDkqZsxrBMbZaEntWjxTk0OZelILRZLjDi5YDFcSdfDK3ZCFxooUqjxWjsDQRWgx22o63tLWbUlvzqUnllBDwEDgInJeaGlE12U3kcQRB6koCItPcUrKPadgYkQWiWJK458k0Ap4lIWjTgq+bDHQDA-qyf6NpiyjyFIBLrGBNgmBiZhcsi7bIessGqA8sofq8X5emEKARLh2pble8hKAcZgZvaFpSFR8JnGojilDe9wPixbpsUqKp0jxDZ5DBrDUMBJEdu0GaCaOwpStQOx7g47Ydm07ToZ+KnfKqEDqfheRYnYxHXrYCJgQm5rjrCthNESFpqLeMq9LmymeqMkAuRC-6EVy0ikeY5GwRJNFHgc0gSHlzoyHZ0XDIWxafPFOrwh5uIkmYDQ6PlZ54rC2yocFpSsIej7uEAA */ id: "discussion-flow", initial: "idle", context: {}, From 2335ab664bf89d421fe2d3a6e71564134567ce6e Mon Sep 17 00:00:00 2001 From: Rendall Date: Fri, 17 Nov 2023 12:46:55 +0200 Subject: [PATCH 5/9] Fix the create topic flow --- src/components/DiscussionDisplay.svelte | 31 ++++++++++++++++++------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/src/components/DiscussionDisplay.svelte b/src/components/DiscussionDisplay.svelte index 076c5c8..a40b1c0 100644 --- a/src/components/DiscussionDisplay.svelte +++ b/src/components/DiscussionDisplay.svelte @@ -16,6 +16,13 @@ export let discussionId: string export let title: string = "" export let currentUser: User | undefined + const emptyTopicMessages = [ + "Looks like this topic is waiting for its first thoughts. Be the pioneer and start the conversation!", + "This space is all yours! Kick off the discussion with your insights.", + "No comments yet. Share your perspective and spark the dialogue!", + "It's quiet here... Why not break the ice with your viewpoint?", + "A fresh topic awaits your input. Lead the way with your comment!", + ] let repliesFlatArray: (Comment & { isNew?: true })[] = [] let discussion: Discussion = { @@ -49,9 +56,9 @@ const updateDiscussionDisplay = ( topic: Discussion, - topicReplies: Comment[] + topicReplies: Comment[] | undefined ) => { - repliesFlatArray = topicReplies + repliesFlatArray = topicReplies ?? [] discussion = threadComments( topic, topicReplies, @@ -76,12 +83,13 @@ const { status, statusText, ok, body } = error as ServerResponse if (ok) console.warn("Error handler caught an OK response", error) - if ( - status === 404 && - statusText === "Not Found" && - body.startsWith("Topic") - ) { - send("CREATE") + const isUnknownTopic = + status === 404 && statusText === "Not Found" && body.startsWith("Topic") + + if (isUnknownTopic) { + setTimeout(() => { + send("CREATE") + }, 1) return } @@ -183,6 +191,13 @@
+ {#if !discussion?.replies} +

+ {emptyTopicMessages[ + Math.floor(Math.random() * emptyTopicMessages.length) + ]} +

+ {/if} {#if showReply === discussionId} Date: Fri, 17 Nov 2023 15:56:18 +0200 Subject: [PATCH 6/9] Change /topic to /icebreakers --- src/simple-comment-icebreakers.ts | 75 +++++++++++ src/static/_redirects | 2 +- src/static/{topic => icebreakers}/index.html | 127 ++++++------------- webpack.frontend.js | 3 +- 4 files changed, 116 insertions(+), 91 deletions(-) create mode 100644 src/simple-comment-icebreakers.ts rename src/static/{topic => icebreakers}/index.html (57%) diff --git a/src/simple-comment-icebreakers.ts b/src/simple-comment-icebreakers.ts new file mode 100644 index 0000000..8363d55 --- /dev/null +++ b/src/simple-comment-icebreakers.ts @@ -0,0 +1,75 @@ +declare global { + interface Window { + getQuestion: (slug: string) => Promise + } +} + +const toSlug = (str: string): string => + str + .toLowerCase() + .replace(/ /g, "-") + .replace(/[^\w-]+/g, "") + .replace(/_/g, "") + .replace(/-{2,}/g, "-") + .replace(/-$/, "") + .replace(/^-/, "") + +const isSlugMatch = (slug: string, question: string) => + slug === toSlug(question) + +const reverseSlug = (slug: string, questions: string[]) => + questions.find(question => isSlugMatch(slug, question)) + +const fetchAndStoreQuestions = () => + new Promise(async (resolve, reject) => { + const storageKey = "icebreakerQuestions" + const timeStampKey = "icebreakerQuestionsTimeStamp" + + const currentTimestamp = + document?.getElementById("questions-time-stamp")?.innerText || "0" + const storedTimestamp = localStorage.getItem(timeStampKey) + + const isStoredQuestionsValid = + storedTimestamp && parseInt(storedTimestamp) >= parseInt(currentTimestamp) + + const storedQuestions = localStorage.getItem(storageKey) + if (isStoredQuestionsValid && storedQuestions) { + resolve(JSON.parse(storedQuestions)) + return + } + try { + const questionFile = await fetch( + "https://raw.githubusercontent.com/rendall/icebreakers/master/QUESTIONS.md" + ) + const questionsText = await questionFile.text() + const questionLines = questionsText.split("\n") + const questions = questionLines + .filter(line => /^ \* [A-Z]/.test(line)) + .map(line => line.slice(4)) + + localStorage.setItem(storageKey, JSON.stringify(questions)) + localStorage.setItem(timeStampKey, currentTimestamp) + resolve(questions) + } catch (error) { + reject(error) + } + }) + +const getQuestion = (slug: string) => + new Promise((resolve, reject) => { + fetchAndStoreQuestions() + .then(questions => { + console.log(questions.map(toSlug)) + const question = reverseSlug(slug, questions) + if (question) { + resolve(question) + } else { + reject("No question found") + } + }) + .catch(reject) + }) + +window.getQuestion = getQuestion + +export default getQuestion diff --git a/src/static/_redirects b/src/static/_redirects index 06f3d16..6024817 100644 --- a/src/static/_redirects +++ b/src/static/_redirects @@ -1 +1 @@ -/topic/* /topic/index.html 200 +/icebreakers/* /icebreakers/index.html 200 diff --git a/src/static/topic/index.html b/src/static/icebreakers/index.html similarity index 57% rename from src/static/topic/index.html rename to src/static/icebreakers/index.html index 7420227..4af9e7c 100644 --- a/src/static/topic/index.html +++ b/src/static/icebreakers/index.html @@ -1,34 +1,19 @@ + Simple Comment - + - - - + + + - - + - +
-

Simple Comment

+
+

Icebreakers

+

Questions to Break the Ice

+
-
-

Simple Comment newsletter

-

- To join the mailing list for news and updates, or to request your own - free instance of Simple Comment, add your email address here. -

-
-
- - -
-
- - -
-
- - - -
- - -
-
-

Simple Comment demo

-

- Simple Comment is a commenting system that can be added easily - to any website. To try it out, add a comment and your info. You can - use the Question of the Day as a prompt, or type whatever is on your - mind. -

-

- Question for the day: What kind of people do you most enjoy hanging - out with? -

+

What's your take? Share your answer or respond to someone else's. Whether it's a + thoughtful insight, a quick remark, or a deep reflection, your voice adds to the mix.

+
+ - + + \ No newline at end of file diff --git a/webpack.frontend.js b/webpack.frontend.js index 7599f91..977310c 100644 --- a/webpack.frontend.js +++ b/webpack.frontend.js @@ -37,12 +37,13 @@ module.exports = { port: 5000, static: path.join(__dirname, "dist"), historyApiFallback: { - rewrites: [{ from: /^\/topic\/.*$/, to: "/topic/index.html" }], + rewrites: [{ from: /^\/icebreakers\/.*$/, to: "/icebreakers/index.html" }], }, }, devtool: "source-map", entry: { "simple-comment": path.resolve(__dirname, "src/simple-comment.ts"), + "simple-comment-icebreakers": path.resolve(__dirname, "src/simple-comment-icebreakers.ts"), "simple-comment-style": path.resolve( __dirname, "src/scss/simple-comment-style.scss" From 9f9c8bcae371629382c594c1140e0f267dad4a77 Mon Sep 17 00:00:00 2001 From: Rendall Date: Fri, 17 Nov 2023 15:57:27 +0200 Subject: [PATCH 7/9] Add 'cancel' and 'load...' functions --- src/simple-comment.ts | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/simple-comment.ts b/src/simple-comment.ts index 7005ac3..1941450 100644 --- a/src/simple-comment.ts +++ b/src/simple-comment.ts @@ -4,19 +4,23 @@ import SimpleComment from "./components/SimpleComment.svelte" declare global { interface Window { - setSimpleCommentOptions: (setupOptions: { [key: string]: unknown }) => void + loadSimpleComment: (options: Options) => void setSimpleCommentDiscussion: (discussionId: string) => void + setSimpleCommentOptions: (setupOptions: { [key: string]: unknown }) => void } } let simpleComment let options = { + cancel: false, discussionId: getDefaultDiscussionId(), - title: document.title, target: document.getElementById("simple-comment") ?? document.body, + title: document.title, } +type Options = typeof options + /** * Sets the options for the SimpleComment component. * This function merges the provided options with the default options. @@ -51,16 +55,28 @@ window.setSimpleCommentOptions = setupOptions => window.setSimpleCommentDiscussion = (discussionId: string) => window.setSimpleCommentOptions({ discussionId }) -// Wait for DOMContentLoaded event before initializing SimpleComment -document.addEventListener("DOMContentLoaded", () => { +const loadSimpleComment = (setupOptions:Options) => { + options = { ...options, ...setupOptions } simpleComment = new SimpleComment({ target: options.target, props: { discussionId: options.discussionId, title: options.title }, }) +} + +window.loadSimpleComment = loadSimpleComment + +// Wait for DOMContentLoaded event before initializing SimpleComment +document.addEventListener("DOMContentLoaded", () => { + console.log("DOMContentLoaded", {options}) + if (options.cancel) return + else loadSimpleComment(options) }) + + export default { simpleComment, setSimpleCommentOptions: window.setSimpleCommentOptions, setSimpleCommentDiscussion: window.setSimpleCommentDiscussion, + loadSimpleComment: window.loadSimpleComment, } From 3fc64ba3c025098fe45ea00c9e8b6c84d4839ca3 Mon Sep 17 00:00:00 2001 From: Rendall Date: Fri, 17 Nov 2023 15:58:53 +0200 Subject: [PATCH 8/9] Add Icebreakers styling --- src/scss/simple-comment-style.scss | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/scss/simple-comment-style.scss b/src/scss/simple-comment-style.scss index cad0c0b..feaf306 100644 --- a/src/scss/simple-comment-style.scss +++ b/src/scss/simple-comment-style.scss @@ -563,3 +563,29 @@ $highlight-text-color: color.scale( background-color: inherit; } } + +.icebreakers { + header { + max-width: 62rem; + align-items: flex-start; + margin: 3rem auto; + + .headlines { + margin-left: 3rem; + h1, + h2 { + margin: 0; + padding: 0; + } + + h2.icebreakers-logotype { + font-size: 2.2rem; + margin-bottom: 2rem; + } + } + + p.instructions { + margin-bottom: 2rem; + } + } +} From 811ae8e82117c7c887d52fbae6c862337aa59342 Mon Sep 17 00:00:00 2001 From: Rendall Date: Fri, 17 Nov 2023 15:59:11 +0200 Subject: [PATCH 9/9] Add icebreakers functionality --- src/simple-comment-icebreakers.ts | 43 +++++++++++++------------ src/simple-comment.ts | 5 +-- src/static/icebreakers/index.html | 53 ++++++++++++++++++++++--------- webpack.frontend.js | 9 ++++-- 4 files changed, 69 insertions(+), 41 deletions(-) diff --git a/src/simple-comment-icebreakers.ts b/src/simple-comment-icebreakers.ts index 8363d55..0202de4 100644 --- a/src/simple-comment-icebreakers.ts +++ b/src/simple-comment-icebreakers.ts @@ -3,6 +3,8 @@ declare global { getQuestion: (slug: string) => Promise } } +const storageKey = "icebreakerQuestions" +const timeStampKey = "icebreakerQuestionsTimeStamp" const toSlug = (str: string): string => str @@ -21,10 +23,7 @@ const reverseSlug = (slug: string, questions: string[]) => questions.find(question => isSlugMatch(slug, question)) const fetchAndStoreQuestions = () => - new Promise(async (resolve, reject) => { - const storageKey = "icebreakerQuestions" - const timeStampKey = "icebreakerQuestionsTimeStamp" - + new Promise((resolve, reject) => { const currentTimestamp = document?.getElementById("questions-time-stamp")?.innerText || "0" const storedTimestamp = localStorage.getItem(timeStampKey) @@ -37,29 +36,33 @@ const fetchAndStoreQuestions = () => resolve(JSON.parse(storedQuestions)) return } - try { - const questionFile = await fetch( - "https://raw.githubusercontent.com/rendall/icebreakers/master/QUESTIONS.md" - ) - const questionsText = await questionFile.text() - const questionLines = questionsText.split("\n") - const questions = questionLines - .filter(line => /^ \* [A-Z]/.test(line)) - .map(line => line.slice(4)) - localStorage.setItem(storageKey, JSON.stringify(questions)) - localStorage.setItem(timeStampKey, currentTimestamp) - resolve(questions) - } catch (error) { - reject(error) - } + fetchQuestions(currentTimestamp, resolve, reject) }) +const fetchQuestions = async (currentTimestamp, resolve, reject) => { + try { + const questionFile = await fetch( + "https://raw.githubusercontent.com/rendall/icebreakers/master/QUESTIONS.md" + ) + const questionsText = await questionFile.text() + const questionLines = questionsText.split("\n") + const questions = questionLines + .filter(line => /^ {2}\* [A-Z]/.test(line)) + .map(line => line.slice(4)) + + localStorage.setItem(storageKey, JSON.stringify(questions)) + localStorage.setItem(timeStampKey, currentTimestamp) + resolve(questions) + } catch (error) { + reject(error) + } +} + const getQuestion = (slug: string) => new Promise((resolve, reject) => { fetchAndStoreQuestions() .then(questions => { - console.log(questions.map(toSlug)) const question = reverseSlug(slug, questions) if (question) { resolve(question) diff --git a/src/simple-comment.ts b/src/simple-comment.ts index 1941450..8e2c081 100644 --- a/src/simple-comment.ts +++ b/src/simple-comment.ts @@ -55,7 +55,7 @@ window.setSimpleCommentOptions = setupOptions => window.setSimpleCommentDiscussion = (discussionId: string) => window.setSimpleCommentOptions({ discussionId }) -const loadSimpleComment = (setupOptions:Options) => { +const loadSimpleComment = (setupOptions: Options) => { options = { ...options, ...setupOptions } simpleComment = new SimpleComment({ target: options.target, @@ -67,13 +67,10 @@ window.loadSimpleComment = loadSimpleComment // Wait for DOMContentLoaded event before initializing SimpleComment document.addEventListener("DOMContentLoaded", () => { - console.log("DOMContentLoaded", {options}) if (options.cancel) return else loadSimpleComment(options) }) - - export default { simpleComment, setSimpleCommentOptions: window.setSimpleCommentOptions, diff --git a/src/static/icebreakers/index.html b/src/static/icebreakers/index.html index 4af9e7c..3cb614d 100644 --- a/src/static/icebreakers/index.html +++ b/src/static/icebreakers/index.html @@ -1,19 +1,33 @@ - Simple Comment - + - - - + + + - +