Add topic,category,group,reltime rendering

This commit is contained in:
Kane York 2015-09-21 14:43:23 -07:00
parent 9145e32162
commit 9956b9833e
12 changed files with 115 additions and 33 deletions

View File

@ -96,6 +96,10 @@ const QueryResultComponent = Ember.Component.extend({
return transformedRelTable(this.get('content.relations.topic'));
}.property('content.relations.topic'),
transformedGroupTable: function() {
return transformedRelTable(this.get('site.groups'));
}.property('site.groups'),
lookupUser(id) {
return this.get('transformedUserTable')[id];
},
@ -108,6 +112,9 @@ const QueryResultComponent = Ember.Component.extend({
lookupTopic(id) {
return this.get('transformedTopicTable')[id];
},
lookupGroup(id) {
return this.get('transformedGroupTable')[id];
},
lookupCategory(id) {
return this.site.get('categoriesById')[id];

View File

@ -1,4 +1,8 @@
import { categoryLinkHTML } from 'discourse/helpers/category-link';
import { autoUpdatingRelativeAge } from 'discourse/lib/formatter';
function icon_or_image_replacement(str, ctx) {
str = Ember.get(ctx.contexts[0], str);
if (Ember.isEmpty(str)) { return ""; }
@ -10,12 +14,16 @@ function icon_or_image_replacement(str, ctx) {
}
}
function shorthandTinyAvatar(avatar_template, ctx) {
return new Handlebars.SafeString(Discourse.Utilities.avatarImg({
size: "tiny",
extraClasses: '',
avatarTemplate: avatar_template
}));
function category_badge_replacement(str, ctx) {
const category = Ember.get(ctx.contexts[0], str);
return categoryLinkHTML(category, {
allowUncategorized: true,
});
}
function bound_date_replacement(str, ctx) {
const value = Ember.get(ctx.contexts[0], str);
return new Handlebars.SafeString(autoUpdatingRelativeAge(new Date(value), {title: true }));
}
const esc = Handlebars.Utils.escapeExpression;
@ -28,28 +36,42 @@ const QueryRowContentComponent = Ember.Component.extend({
const row = this.get('row');
const parent = self.get('parent');
const fallback = parent.get('fallbackTemplate');
const helpers = {
"icon-or-image": icon_or_image_replacement,
"category-link": category_badge_replacement,
"reltime": bound_date_replacement,
};
const parts = this.get('columnTemplates').map(function(t, idx) {
const ctx = {};
const params = {}
if (t.name === "text") {
const value = row[idx],
id = parseInt(value);
const ctx = {value, id, baseuri: Discourse.BaseUri === '/' ? '' : Discourse.BaseUri };
const params = {};
if (row[idx] === null) {
return "NULL";
} else if (t.name === "text") {
return esc(row[idx]);
} else if (t.name === "user") {
ctx.user = parent.lookupUser(parseInt(row[idx]));
if (!ctx.user) {
return esc(row[idx]);
}
} else if (t.name === "badge") {
ctx.badge = parent.lookupBadge(parseInt(row[idx]));
params.helpers = {"icon-or-image": icon_or_image_replacement};
} else if (t.name === "post") {
ctx.post = parent.lookupPost(parseInt(row[idx]));
params.helpers = {avatar: shorthandTinyAvatar};
} else {
ctx.value = row[idx];
}
return new Handlebars.SafeString((t.template || fallback)(ctx, params));
const lookupFunc = parent[`lookup${t.name.capitalize()}`];
if (lookupFunc) {
ctx[t.name] = parent[`lookup${t.name.capitalize()}`](id);
}
if (t.name === "category" || t.name === "badge" || t.name === "reltime") {
// only replace helpers if needed
params.helpers = helpers;
}
try {
return new Handlebars.SafeString((t.template || fallback)(ctx, params));
} catch (e) {
console.error(e);
debugger;
return "error";
}
});
buffer.push("<td>" + parts.join("</td><td>") + "</td>");

View File

@ -1,2 +1,6 @@
{{! source: badge-button component }}
<span class="user-badge {{badge.badgeTypeClassName}}" title="{{badge.displayDescription}}" data-badge-name="{{badge.name}}">{{icon-or-image badge.icon}} <span class="badge-display-name">{{badge.displayName}}</span></span>
<a href="{{baseuri}}/badges/{{badge.id}}/{{badge.name}}"
class="user-badge {{badge.badgeTypeClassName}}"
title="{{badge.displayDescription}}"
data-badge-name="{{badge.name}}">{{icon-or-image badge.icon}}
<span class="badge-display-name">{{badge.displayName}}</span></a>

View File

@ -0,0 +1,5 @@
{{#if category}}
{{category-link category}}
{{else}}
<a href="{{baseuri}}/t/{{id}}">{{id}}</a>
{{/if}}

View File

@ -0,0 +1,5 @@
{{#if group}}
<a href="{{baseuri}}/groups/{{group.name}}">{{group.name}}</a>
{{else}}
{{id}}
{{/if}}

View File

@ -1,4 +1,15 @@
<aside class="quote" data-post="{{post.post_number}}" data-topic="{{post.topic_id}}"><div class="title" style="cursor: pointer;">
<div class="quote-controls">{{!<i class="fa fa-chevron-down" title="expand/collapse"></i>}}<a href="/t/via-quote/{{post.topic_id}}/{{post.post_number}}" title="go to the quoted post" class="quote-other-topic"></a></div>
{{avatar post.username post.uploaded_avatar_id}}{{post.username}}:</div>
<blockquote><p>{{{post.excerpt}}}</p></blockquote></aside>
{{~#if post}}
<aside class="quote"
data-post="{{post.post_number}}"
data-topic="{{post.topic_id}}">
<div class="title" style="cursor: pointer;">
<div class="quote-controls">
{{!<i class="fa fa-chevron-down" title="expand/collapse"></i>}}
<a href="/t/via-quote/{{post.topic_id}}/{{post.post_number}}"
title="go to the quoted post"
class="quote-other-topic"></a></div>
{{avatar post imageSize="tiny"}}{{post.username}}:</div>
<blockquote><p>{{{post.excerpt}}}</p></blockquote></aside>
{{~else}}
{{id}}
{{~/if}}

View File

@ -0,0 +1 @@
{{reltime value}}

View File

@ -1,2 +1 @@
{{value}}
{{! note - this template isn't actually used, it gets short-circuited in query-row-content.js.es6}}

View File

@ -0,0 +1,6 @@
{{#if topic}}
<a href="{{baseuri}}/t/{{topic.slug}}/{{topic.id}}"
>{{{topic.fancy_title}}}</a> ({{topic.posts_count}})
{{else}}
<a href="{{baseuri}}/t/{{id}}">{{id}}</a>
{{/if}}

View File

@ -1 +1,6 @@
<a href="/users/{{user.username}}/activity">{{avatar user imageSize="tiny"}} {{user.username}}</a>
{{#if user}}
<a href="{{baseuri}}/users/{{user.username}}/activity"
data-user-card="{{user.username}}">{{avatar user imageSize="tiny"}} {{user.username}}</a>
{{else}}
{{id}}
{{/if}}

View File

@ -50,7 +50,7 @@ after_initialize do
Post.excerpt(object.cooked, 70)
end
def username; object.user.username; end
def uploaded_avatar_id; object.user.avatar_template; end
def avatar_template; object.user.avatar_template; end
end
# Run a data explorer query on the currently connected database.
@ -141,6 +141,7 @@ SQL
badge: {class: Badge, fields: [:id, :name, :badge_type_id, :description, :icon], include: [:badge_type], serializer: SmallBadgeSerializer},
post: {class: Post, fields: [:id, :topic_id, :post_number, :cooked, :user_id], include: [:user], serializer: SmallPostWithExcerptSerializer},
topic: {class: Topic, fields: [:id, :title, :slug, :posts_count], serializer: BasicTopicSerializer},
group: {class: Group, ignore: true},
category: {class: Category, ignore: true},
reltime: {ignore: true},
html: {ignore: true},
@ -196,8 +197,13 @@ SQL
ids.map! &:to_i
object_class = support_info[:class]
all_objs = object_class.select(support_info[:fields]).
where(id: ids.to_a.sort).includes(support_info[:include]).order(:id)
all_objs = object_class
all_objs = all_objs.with_deleted if all_objs.respond_to? :with_deleted
all_objs = all_objs
.select(support_info[:fields])
.where(id: ids.to_a.sort)
.includes(support_info[:include])
.order(:id)
ret[cls] = ActiveModel::ArraySerializer.new(all_objs, each_serializer: support_info[:serializer])
end

11
test/test_query.sql Normal file
View File

@ -0,0 +1,11 @@
SELECT
(SELECT id FROM badges LIMIT 1) as badge_id,
(SELECT id FROM categories LIMIT 1) as category_id,
(SELECT id FROM groups LIMIT 1) as group_id,
'<h2 class="fa fa-google"> hello</h2>' as html$html,
(SELECT id FROM posts LIMIT 1) as post_id,
'hello' as text$text,
(SELECT id FROM topics LIMIT 1) as topic_id,
(SELECT id FROM users LIMIT 1) as user_id,
TIMESTAMP 'yesterday' as reltime$time,
1 as end