From dd29af44756c2e4dd7c6914b5660ce25a46a05d5 Mon Sep 17 00:00:00 2001 From: Robin Ward <robin.ward@gmail.com> Date: Tue, 30 Apr 2019 15:22:03 -0400 Subject: [PATCH] REFACTOR: `{{avatar}}` and `{{date}}` helpers in vdom templates This is a step towards a nicer flag display under posts. --- .../javascripts/discourse/helpers/node.js.es6 | 5 ++ .../discourse/widgets/actions-summary.js.es6 | 48 ++++++------------- .../javascripts/discourse/widgets/post.js.es6 | 5 ++ lib/javascripts/widget-hbs-compiler.js.es6 | 45 ++++++++++++----- 4 files changed, 57 insertions(+), 46 deletions(-) diff --git a/app/assets/javascripts/discourse/helpers/node.js.es6 b/app/assets/javascripts/discourse/helpers/node.js.es6 index e73345dab4a..21d4d9d2c8b 100644 --- a/app/assets/javascripts/discourse/helpers/node.js.es6 +++ b/app/assets/javascripts/discourse/helpers/node.js.es6 @@ -17,6 +17,11 @@ export function dateNode(dt) { } } +// TODO: Improve how helpers are registered for vdom compliation +if (typeof Discourse !== "undefined") { + Discourse.__widget_helpers.dateNode = dateNode; +} + export function numberNode(num, opts) { opts = opts || {}; num = parseInt(num, 10); diff --git a/app/assets/javascripts/discourse/widgets/actions-summary.js.es6 b/app/assets/javascripts/discourse/widgets/actions-summary.js.es6 index 3206a124a16..50c6d8a9e23 100644 --- a/app/assets/javascripts/discourse/widgets/actions-summary.js.es6 +++ b/app/assets/javascripts/discourse/widgets/actions-summary.js.es6 @@ -1,9 +1,8 @@ import { createWidget } from "discourse/widgets/widget"; import { avatarFor } from "discourse/widgets/post"; -import { iconNode } from "discourse-common/lib/icon-library"; import { h } from "virtual-dom"; -import { dateNode } from "discourse/helpers/node"; import { userPath } from "discourse/lib/url"; +import hbs from "discourse/widgets/hbs-compiler"; export function avatarAtts(user) { return { @@ -156,38 +155,19 @@ createWidget("actions-summary-item", { } }); -createWidget("deleted-post", { - tagName: "div.post-action.deleted-post", - - html(attrs) { - return [ - iconNode("far-trash-alt"), - " ", - avatarFor.call(this, "small", { - template: attrs.deletedByAvatarTemplate, - username: attrs.deletedByUsername - }), - " ", - dateNode(attrs.deleted_at) - ]; - } -}); - export default createWidget("actions-summary", { tagName: "section.post-actions", - - html(attrs) { - const actionsSummary = attrs.actionsSummary || []; - const body = []; - actionsSummary.forEach(as => { - body.push(this.attach("actions-summary-item", as)); - body.push(h("div.clearfix")); - }); - - if (attrs.deleted_at) { - body.push(this.attach("deleted-post", attrs)); - } - - return body; - } + template: hbs` + {{#each attrs.actionsSummary as |as|}} + {{attach widget="actions-summary-item" attrs=as}} + <div class='clearfix'></div> + {{/each}} + {{#if attrs.deleted_at}} + <div class='post-action deleted-post'> + {{d-icon "far-trash-alt"}} + {{avatar size="small" template=attrs.deletedByAvatarTemplate username=attrs.deletedByUsername}} + {{date attrs.deleted_at}} + </div> + {{/if}} + ` }); diff --git a/app/assets/javascripts/discourse/widgets/post.js.es6 b/app/assets/javascripts/discourse/widgets/post.js.es6 index 35b86f4aace..daa19ec9465 100644 --- a/app/assets/javascripts/discourse/widgets/post.js.es6 +++ b/app/assets/javascripts/discourse/widgets/post.js.es6 @@ -59,6 +59,11 @@ export function avatarFor(wanted, attrs) { ); } +// TODO: Improve how helpers are registered for vdom compliation +if (typeof Discourse !== "undefined") { + Discourse.__widget_helpers.avatar = avatarFor; +} + createWidget("select-post", { tagName: "div.select-posts", diff --git a/lib/javascripts/widget-hbs-compiler.js.es6 b/lib/javascripts/widget-hbs-compiler.js.es6 index 17e963f8080..a55dfaebf7b 100644 --- a/lib/javascripts/widget-hbs-compiler.js.es6 +++ b/lib/javascripts/widget-hbs-compiler.js.es6 @@ -33,6 +33,15 @@ function argValue(arg) { } } +function useHelper(state, name) { + let id = state.helpersUsed[name]; + if (!id) { + id = ++state.helperNumber; + state.helpersUsed[name] = id; + } + return `__h${id}`; +} + function mustacheValue(node, state) { let path = node.path.original; @@ -63,18 +72,30 @@ function mustacheValue(node, state) { } break; - case "fa-icon": + case "avatar": + let template = argValue(node.hash.pairs.find(p => p.key === "template")); + let username = argValue(node.hash.pairs.find(p => p.key === "username")); + let size = argValue(node.hash.pairs.find(p => p.key === "size")); + return `${useHelper( + state, + "avatar" + )}(${size}, { template: ${template}, username: ${username} })`; + break; + case "date": + value = resolve(node.params[0].original); + return `${useHelper(state, "dateNode")}(${value})`; + break; case "d-icon": - state.helpersUsed.iconNode = true; let icon = node.params[0].value; - return `__iN("${icon}")`; + return `${useHelper(state, "iconNode")}("${icon}")`; break; default: if (node.escaped) { return `${resolve(path)}`; } else { - state.helpersUsed.rawHtml = true; - return `new __rH({ html: '<span>' + ${resolve(path)} + '</span>'})`; + return `new ${useHelper(state, "rawHtml")}({ html: '<span>' + ${resolve( + path + )} + '</span>'})`; } break; } @@ -86,7 +107,8 @@ class Compiler { this.ast = ast; this.state = { - helpersUsed: {} + helpersUsed: {}, + helperNumber: 0 }; } @@ -212,12 +234,11 @@ function compile(template) { let code = compiler.compile(); let imports = ""; - if (compiler.state.helpersUsed.iconNode) { - imports += "var __iN = Discourse.__widget_helpers.iconNode; "; - } - if (compiler.state.helpersUsed.rawHtml) { - imports += "var __rH = Discourse.__widget_helpers.rawHtml; "; - } + + Object.keys(compiler.state.helpersUsed).forEach(h => { + let id = compiler.state.helpersUsed[h]; + imports += `var __h${id} = Discourse.__widget_helpers.${h}; `; + }); return `function(attrs, state) { ${imports}var _r = [];\n${code}\nreturn _r; }`; }