Add comments view.

This commit is contained in:
Dillon Kearns 2022-04-11 20:52:03 -07:00
parent cc7c7c3b06
commit 435ccc362b
3 changed files with 72 additions and 36 deletions

View File

@ -1,31 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="modulepreload" href="/assets/index.ef4a3a15.js" />
<script defer src="/elm.0f196877.js" type="text/javascript"></script>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title></title>
<meta name="generator" content="elm-pages v2.1.11" />
<meta name="mobile-web-app-capable" content="yes" />
<meta name="theme-color" content="#ffffff" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta
name="apple-mobile-web-app-status-bar-style"
content="black-translucent"
/>
<link rel="canonical" href="https://elm-pages.com/escaping" /> <meta name="description" content="These quotes should be escaped &quot;ESCAPE THIS&quot;, and so should &lt;CARETS&gt;" /> <meta property="og:image" content="TODO" /> <meta property="og:image:secure_url" content="TODO" /> <meta property="og:image:alt" content="elm-pages logo" /> <meta property="og:title" content="TODO title" /> <meta property="og:url" content="https://elm-pages.com/escaping" /> <meta property="og:description" content="These quotes should be escaped &quot;ESCAPE THIS&quot;, and so should &lt;CARETS&gt;" /> <meta property="og:site_name" content="elm-pages" /> <meta property="twitter:card" content="summary" /> <meta property="twitter:title" content="TODO title" /> <meta property="twitter:description" content="These quotes should be escaped &quot;ESCAPE THIS&quot;, and so should &lt;CARETS&gt;" /> <meta property="twitter:image" content="TODO" /> <meta property="twitter:image:alt" content="elm-pages logo" /> <meta property="og:type" content="website" /> <link rel="icon" sizes="32x32" type="image/png" href="https://res.cloudinary.com/dillonkearns/image/upload/c_pad,w_32,h_32,q_auto,f_png/v1603234028/elm-pages/elm-pages-icon" /> <link rel="icon" sizes="16x16" type="image/png" href="https://res.cloudinary.com/dillonkearns/image/upload/c_pad,w_16,h_16,q_auto,f_png/v1603234028/elm-pages/elm-pages-icon" /> <link rel="apple-touch-icon" sizes="180x180" href="https://res.cloudinary.com/dillonkearns/image/upload/c_pad,w_180,h_180,q_auto,f_png/v1603234028/elm-pages/elm-pages-icon" /> <link rel="apple-touch-icon" sizes="192x192" href="https://res.cloudinary.com/dillonkearns/image/upload/c_pad,w_192,h_192,q_auto,f_png/v1603234028/elm-pages/elm-pages-icon" /> <link rel="sitemap" type="application/xml" href="/sitemap.xml" />
<script id="__ELM_PAGES_BYTES_DATA__" type="application/octet-stream">AAKEPHNjcmlwdD48L3NjcmlwdD4gaXMgdW5zYWZlIGluIEpTT04gdW5sZXNzIGl0IGlzIGVzY2FwZWQgcHJvcGVybHku</script>
<script type="module" crossorigin src="/assets/index.ef4a3a15.js"></script>
<link rel="stylesheet" href="/assets/index.b0f41fb5.css">
</head>
<body>
<div data-url="" display="none"></div>
<div><style></style><label for="note"></label><div><style>div > p {
font-size:14px;
color:rgb(255, 0, 0);
}</style><div><p>Hello! 2 &gt; 1</p></div></div>&lt;script&gt;&lt;/script&gt; is unsafe in JSON unless it is escaped properly.&lt;script&gt;&lt;/script&gt; is unsafe in JSON unless it is escaped properly.</div>
</body>
</html>

View File

@ -8,6 +8,8 @@ import Head
import Head.Seo as Seo
import Html exposing (Html)
import Html.Attributes as Attr
import Json.Decode as Decode
import Json.Encode as Encode
import Pages.PageUrl exposing (PageUrl)
import Pages.Url
import Path exposing (Path)
@ -78,7 +80,7 @@ pages =
type alias Data =
{ story : Item
{ story : ( Item, String )
}
@ -86,7 +88,10 @@ data : RouteParams -> Request.Parser (DataSource (Response Data ErrorPage))
data routeParams =
Request.succeed
(DataSource.Http.get ("https://node-hnapi.herokuapp.com/item/" ++ routeParams.id)
Story.decoder
(Decode.map2 Tuple.pair
Story.decoder
(Decode.field "comments" (Decode.value |> Decode.map (Encode.encode 0)))
)
|> DataSource.map
(\story ->
Response.render
@ -129,8 +134,8 @@ view maybeUrl sharedModel model static =
}
storyView : Item -> Html msg
storyView (Item story entry) =
storyView : ( Item, String ) -> Html msg
storyView ( Item story entry, commentsJson ) =
Html.div
[ Attr.class "item-view"
]
@ -184,6 +189,14 @@ storyView (Item story entry) =
, Html.ul
[ Attr.class "comment-children"
]
[]
((commentsJson
|> Decode.decodeString (Decode.list Decode.value)
|> Result.withDefault []
)
|> List.map
(\comment ->
Html.node "news-comment" [ Attr.property "commentBody" comment ] []
)
)
]
]

View File

@ -4,3 +4,57 @@ export default {
return null;
},
};
customElements.define(
"news-comment",
class extends HTMLElement {
constructor() {
super();
this._commentBody = null;
this.expanded = true;
}
get commentBody() {
return this._commentBody;
}
set commentBody(value) {
if (this._commentBody === value) return;
this._commentBody = value;
}
toggle() {
this.expanded = !this.expanded;
this.connectedCallback();
}
connectedCallback() {
this.shadow = this.shadow || this.attachShadow({ mode: "open" });
const div = document.createElement("div");
let toggleClass = this.expanded ? "open" : "closed";
let displayStyle = this.expanded ? "block" : "none";
div.classList = `toggle ${toggleClass}`;
const button = document.createElement("a");
button.textContent = this.expanded ? "[-]" : "[+] comments collapsed";
button.addEventListener("click", () => this.toggle());
div.appendChild(button);
const nestedComments =
(this._commentBody && this._commentBody.comments) || [];
const nested = document.createElement("ul");
nestedComments.forEach((comment) => {
const newElement = document.createElement("news-comment");
newElement.commentBody = comment;
nested.appendChild(newElement);
});
this.shadow.innerHTML = `<ul
class="comment-children"
style="display: ${displayStyle}"
>
${(this._commentBody && this._commentBody.content) || ""}
</ul>`;
this.shadow.appendChild(nested);
this.shadow.prepend(div);
}
}
);