UX: new 'category_page_style' site setting
This commit is contained in:
parent
b6bcfc0426
commit
4d6028ea2d
|
@ -0,0 +1,3 @@
|
|||
export default Ember.Component.extend({
|
||||
classNames: ["categories-and-latest"]
|
||||
});
|
|
@ -3,9 +3,8 @@ import StringBuffer from 'discourse/mixins/string-buffer';
|
|||
// Creates a link
|
||||
function link(buffer, prop, url, cssClass, i18nKey, text) {
|
||||
if (!prop) { return; }
|
||||
|
||||
var title = I18n.t("topic." + i18nKey, {count: prop});
|
||||
buffer.push("<a href='" + url + "' class='badge " + cssClass + " badge-notification' title='" + title + "'>" + (text || prop) + "</a>\n");
|
||||
const title = I18n.t("topic." + i18nKey, { count: prop });
|
||||
buffer.push(`<a href="${url}" class="badge ${cssClass} badge-notification" title="${title}">${text || prop}</a>\n`);
|
||||
}
|
||||
|
||||
export default Ember.Component.extend(StringBuffer, {
|
||||
|
@ -13,9 +12,8 @@ export default Ember.Component.extend(StringBuffer, {
|
|||
classNameBindings: [':topic-post-badges'],
|
||||
rerenderTriggers: ['url', 'unread', 'newPosts', 'unseen'],
|
||||
|
||||
renderString: function(buffer) {
|
||||
var url = this.get('url');
|
||||
|
||||
renderString(buffer) {
|
||||
const url = this.get('url');
|
||||
link(buffer, this.get('unread'), url, 'unread', 'unread_posts');
|
||||
link(buffer, this.get('newPosts'), url, 'new-posts', 'new_posts');
|
||||
link(buffer, this.get('unseen'), url, 'new-topic', 'new', I18n.t('filters.new.lower_title'));
|
||||
|
|
|
@ -4,9 +4,6 @@ import DiscoveryController from 'discourse/controllers/discovery';
|
|||
export default DiscoveryController.extend({
|
||||
needs: ['modal', 'discovery'],
|
||||
|
||||
withLogo: Em.computed.filterBy('model.categories', 'logo_url'),
|
||||
showPostsColumn: Em.computed.empty('withLogo'),
|
||||
|
||||
// this makes sure the composer isn't scoping to a specific category
|
||||
category: null,
|
||||
|
||||
|
@ -17,7 +14,13 @@ export default DiscoveryController.extend({
|
|||
|
||||
@computed("model.categories.@each.featuredTopics.length")
|
||||
latestTopicOnly() {
|
||||
return this.get("model.categories").find(c => c.get('featuredTopics.length') > 1) === undefined;
|
||||
return this.get("model.categories").find(c => c.get("featuredTopics.length") > 1) === undefined;
|
||||
},
|
||||
|
||||
@computed("model.parentCategory")
|
||||
categoryPageStyle(parentCategory) {
|
||||
const style = this.siteSettings.category_page_style;
|
||||
return parentCategory && style === "categories_and_latest_topics" ? "categories_only" : style;
|
||||
}
|
||||
|
||||
});
|
||||
|
|
|
@ -11,7 +11,6 @@ const CategoryList = Ember.ArrayProxy.extend({
|
|||
CategoryList.reopenClass({
|
||||
categoriesFrom(store, result) {
|
||||
const categories = CategoryList.create();
|
||||
const users = Discourse.Model.extractByKey(result.featured_users, Discourse.User);
|
||||
const list = Discourse.Category.list();
|
||||
|
||||
let statPeriod;
|
||||
|
@ -34,10 +33,6 @@ CategoryList.reopenClass({
|
|||
c.subcategories = c.subcategory_ids.map(scid => list.findBy('id', parseInt(scid, 10)));
|
||||
}
|
||||
|
||||
if (c.featured_user_ids) {
|
||||
c.featured_users = c.featured_user_ids.map(u => users[u]);
|
||||
}
|
||||
|
||||
if (c.topics) {
|
||||
c.topics = c.topics.map(t => Discourse.Topic.create(t));
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ const Topic = RestModel.extend({
|
|||
|
||||
@computed('posters.[]')
|
||||
lastPoster(posters) {
|
||||
var user;
|
||||
let user;
|
||||
if (posters && posters.length > 0) {
|
||||
const latest = posters.filter(p => p.extras && p.extras.indexOf("latest") >= 0)[0];
|
||||
user = latest && latest.user;
|
||||
|
@ -50,8 +50,8 @@ const Topic = RestModel.extend({
|
|||
@computed('fancy_title')
|
||||
fancyTitle(title) {
|
||||
// TODO: `siteSettings` should always be present, but there are places in the code
|
||||
// that call Discourse.Topic.create instead of using the store. When the store is
|
||||
// used, remove this.
|
||||
// that call Discourse.Topic.create instead of using the store.
|
||||
// When the store is used, remove this.
|
||||
const siteSettings = this.siteSettings || Discourse.SiteSettings;
|
||||
return censor(emojiUnescape(title || ""), siteSettings.censored_words);
|
||||
},
|
||||
|
|
|
@ -15,14 +15,18 @@ const DiscoveryCategoriesRoute = Discourse.Route.extend(OpenComposer, {
|
|||
},
|
||||
|
||||
model() {
|
||||
console.log("ENTERING MODEL");
|
||||
return CategoryList.list(this.store, 'categories').then(list => {
|
||||
console.log("GOT THE LIST");
|
||||
const tracking = this.topicTrackingState;
|
||||
if (tracking) {
|
||||
tracking.sync(list, "categories");
|
||||
tracking.trackIncoming("categories");
|
||||
}
|
||||
console.log("RETURNING LIST");
|
||||
return list;
|
||||
});
|
||||
console.log("LEAVING MODEL");
|
||||
},
|
||||
|
||||
titleToken() {
|
||||
|
@ -31,8 +35,8 @@ const DiscoveryCategoriesRoute = Discourse.Route.extend(OpenComposer, {
|
|||
},
|
||||
|
||||
setupController(controller, model) {
|
||||
// only load latest topics in desktop view
|
||||
if (!this.site.mobileView) {
|
||||
const style = this.siteSettings.category_page_style;
|
||||
if (style === "categories_and_latest_topics" && !this.get("model.parentCategory")) {
|
||||
model.set("loadingTopics", true);
|
||||
|
||||
TopicList.find("latest")
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
{{categories-only categories=categories}}
|
||||
|
||||
<table class="topic-list topic-list-latest">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="latest">{{i18n "filters.latest.title"}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#if loadingTopics}}
|
||||
{{loading-spinner}}
|
||||
{{else}}
|
||||
{{#if topics}}
|
||||
{{#each topics as |t|}}
|
||||
<tr>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr data-topic-id={{t.id}} class="{{if t.archived 'archived'}}">
|
||||
<td class="topic-poster">
|
||||
{{#with t.creator as |op|}}
|
||||
{{#user-link user=op}}
|
||||
{{avatar op imageSize="large"}}
|
||||
{{/user-link}}
|
||||
{{/with}}
|
||||
</td>
|
||||
<td class="main-link">
|
||||
<tr>
|
||||
{{topic-status topic=t}}
|
||||
{{topic-link t}}
|
||||
{{topic-post-badges newPosts=t.totalUnread unseen=t.unseen url=t.lastUnreadUrl}}
|
||||
</tr>
|
||||
<tr>
|
||||
{{category-link t.category}}
|
||||
{{#if t.tags}}
|
||||
{{#each t.visibleListTags as |tag|}}
|
||||
{{discourse-tag tag}}
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
</tr>
|
||||
</td>
|
||||
<td class="topic-stats">
|
||||
{{raw "list/posts-count-column" topic=t tagName="div"}}
|
||||
<div class="topic-last-activity">
|
||||
<a href="{{t.lastPostUrl}}" title="{{t.bumpedAtTitle}}">{{format-date t.bumpedAt format="tiny" noTitle="true"}}</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</tr>
|
||||
{{/each}}
|
||||
<tr class="more-topics">
|
||||
<td>
|
||||
<a href="/latest" class="btn pull-right">{{i18n "more"}}</a>
|
||||
</td>
|
||||
</tr>
|
||||
{{else}}
|
||||
<tr class="no-topics">
|
||||
<td>
|
||||
<h3>{{i18n "topics.none.latest"}}</h3>
|
||||
</td>
|
||||
</tr>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="clearfix"></div>
|
|
@ -0,0 +1,52 @@
|
|||
{{#if categories}}
|
||||
<table class="category-list {{if showTopics 'with-topics'}}">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="category">{{i18n 'categories.category'}}</th>
|
||||
<th class="topics">{{i18n 'categories.topics'}}</th>
|
||||
{{#if showTopics}}
|
||||
<th class="latest">{{i18n 'categories.latest'}}</th>
|
||||
{{/if}}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#each categories as |c|}}
|
||||
<tr data-category-id={{c.id}} class="{{if c.description_excerpt 'has-description' 'no-description'}} {{if c.logo_url 'has-logo' 'no-logo'}}">
|
||||
<td class="category" style={{border-color c.color}}>
|
||||
<div>
|
||||
{{category-title-link category=c}}
|
||||
{{#if c.logo_url}}
|
||||
{{category-logo-link category=c}}
|
||||
{{/if}}
|
||||
<div class="category-description">
|
||||
{{{c.description_excerpt}}}
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
{{#if c.subcategories}}
|
||||
<div class='subcategories'>
|
||||
{{#each c.subcategories as |s|}}
|
||||
{{category-link s hideParent="true"}}
|
||||
{{category-unread category=s}}
|
||||
{{/each}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</td>
|
||||
<td class="topics">
|
||||
<div title={{c.statTitle}}>{{{c.stat}}}</div>
|
||||
{{category-unread category=c tagName="div" class="unread-new"}}
|
||||
</td>
|
||||
{{#if showTopics}}
|
||||
<td class="latest">
|
||||
{{#each c.featuredTopics as |t|}}
|
||||
{{featured-topic topic=t
|
||||
latestTopicOnly=latestTopicOnly
|
||||
action="showTopicEntrance"}}
|
||||
{{/each}}
|
||||
</td>
|
||||
{{/if}}
|
||||
</tr>
|
||||
{{/each}}
|
||||
</tbody>
|
||||
</table>
|
||||
{{/if}}
|
|
@ -0,0 +1,3 @@
|
|||
{{categories-only categories=categories
|
||||
latestTopicOnly=latestTopicOnly
|
||||
showTopics="true"}}
|
|
@ -8,6 +8,5 @@
|
|||
<a href="{{unbound topic.lastPostUrl}}">{{format-age topic.last_posted_at}}</a>
|
||||
</div>
|
||||
{{else}}
|
||||
|
||||
<a href class="last-posted-at">{{format-age topic.last_posted_at}}</a>
|
||||
{{/if}}
|
||||
|
|
|
@ -1,109 +1,7 @@
|
|||
{{#if model.categories}}
|
||||
{{#discovery-categories refresh="refresh"}}
|
||||
<table class='categories topic-list'>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class='category'>{{i18n 'categories.category'}}</th>
|
||||
<th class='stats topics'>{{i18n 'categories.topics'}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#each model.categories as |c|}}
|
||||
<tr data-category_id='{{unbound c.id}}' class="{{if c.description_excerpt 'has-description' 'no-description'}} {{if c.logo_url 'has-logo' 'no-logo'}}">
|
||||
<td class='category' style={{border-color c.color}}>
|
||||
<div>
|
||||
{{category-title-link category=c}}
|
||||
{{#if c.logo_url}}
|
||||
{{category-logo-link category=c}}
|
||||
{{/if}}
|
||||
<div class="category-description">
|
||||
{{{c.description_excerpt}}}
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
{{#if c.subcategories}}
|
||||
<div class='subcategories'>
|
||||
{{#each c.subcategories as |s|}}
|
||||
{{category-link s hideParent="true"}}
|
||||
{{category-unread category=s}}
|
||||
{{/each}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</td>
|
||||
<td class='stats'>
|
||||
<div title={{c.statTitle}}>
|
||||
{{{c.stat}}}
|
||||
</div>
|
||||
{{category-unread category=c tagName="div" class="unread-new"}}
|
||||
</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
</tbody>
|
||||
</table>
|
||||
{{/discovery-categories}}
|
||||
{{/if}}
|
||||
<table class="topic-list topic-list-latest">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class='category'>{{i18n "filters.latest.title"}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#if model.loadingTopics}}
|
||||
{{loading-spinner}}
|
||||
{{else}}
|
||||
{{#if model.topicList.topics}}
|
||||
{{#each model.topicList.topics as |t|}}
|
||||
<tr>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr class="{{if t.archived 'archived'}}" data-topic-id={{unbound t.id}}>
|
||||
<td class="topic-poster">
|
||||
{{#with t.posters.firstObject.user as |originalPoster|}}
|
||||
{{#user-link user=originalPoster}}
|
||||
{{avatar originalPoster imageSize="large"}}
|
||||
{{/user-link}}
|
||||
{{/with}}
|
||||
</td>
|
||||
<td class="main-link">
|
||||
<tr>
|
||||
{{topic-status topic=t}}
|
||||
{{topic-link t}}
|
||||
{{topic-post-badges newPosts=t.totalUnread unseen=t.unseen url=t.lastUnreadUrl}}
|
||||
</tr>
|
||||
<tr>
|
||||
{{category-link t.category}}
|
||||
{{#if t.tags}}
|
||||
{{#each t.visibleListTags as |tag|}}
|
||||
{{discourse-tag tag}}
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
</tr>
|
||||
</td>
|
||||
<td class="topic-stats">
|
||||
{{raw "list/posts-count-column" topic=t tagName="div"}}
|
||||
<div class="topic-last-activity">
|
||||
<a href="{{t.lastPostUrl}}" title="{{t.bumpedAtTitle}}">{{format-date t.bumpedAt format="tiny" noTitle="true"}}</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</tr>
|
||||
{{/each}}
|
||||
<tr class="more-topics">
|
||||
<td>
|
||||
<a href="/latest" class="btn pull-right">{{i18n "more"}}</a>
|
||||
</td>
|
||||
</tr>
|
||||
{{else}}
|
||||
<tr class="no-topics">
|
||||
<td>
|
||||
<h3>{{i18n "topics.none.latest"}}</h3>
|
||||
</td>
|
||||
</tr>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="clearfix"></div>
|
||||
{{#discovery-categories refresh="refresh"}}
|
||||
{{component controller.categoryPageStyle
|
||||
categories=model.categories
|
||||
latestTopicOnly=controller.latestTopicOnly
|
||||
topics=model.topicList.topics
|
||||
loadingTopics=model.loadingTopics}}
|
||||
{{/discovery-categories}}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
@import "desktop/login";
|
||||
@import "desktop/modal";
|
||||
@import "desktop/user-card";
|
||||
@import "desktop/category-list";
|
||||
@import "desktop/topic-list";
|
||||
@import "desktop/topic-post";
|
||||
@import "desktop/topic-timeline";
|
||||
|
|
|
@ -0,0 +1,158 @@
|
|||
.category-list {
|
||||
margin-bottom: 10px;
|
||||
width: 100%;
|
||||
|
||||
td, th {
|
||||
padding: 12px 5px;
|
||||
color: dark-light-choose(scale-color($primary, $lightness: 50%), scale-color($secondary, $lightness: 40%));
|
||||
}
|
||||
|
||||
td {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
th {
|
||||
text-align: left;
|
||||
vertical-align: middle;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
td:first-of-type {
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
&.with-topics .category {
|
||||
width: 45%;
|
||||
}
|
||||
|
||||
.topics {
|
||||
width: 80px;
|
||||
text-align: right;
|
||||
|
||||
.value {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
.unit {
|
||||
font-size: .8em;
|
||||
}
|
||||
.badge-notification {
|
||||
display: block;
|
||||
background-color: transparent;
|
||||
color: dark-light-choose(scale-color($primary, $lightness: 50%), scale-color($secondary, $lightness: 40%));
|
||||
text-align: right;
|
||||
padding-right: 0;
|
||||
margin-top: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.category-description,
|
||||
.subcategories {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.featured-topic {
|
||||
margin: 10px 0 0;
|
||||
|
||||
&:first-of-type {
|
||||
margin-top: 13px;
|
||||
}
|
||||
|
||||
a.last-posted-at,
|
||||
a.last-posted-at:visited {
|
||||
font-size: 0.86em;
|
||||
color: dark-light-choose(scale-color($primary, $lightness: 50%), scale-color($secondary, $lightness: 40%));
|
||||
}
|
||||
|
||||
.topic-statuses .fa {
|
||||
color: dark-light-choose(scale-color($primary, $lightness: 50%), scale-color($secondary, $lightness: 40%));
|
||||
}
|
||||
|
||||
.topic-post-badges {
|
||||
position: relative;
|
||||
top: -2px;
|
||||
}
|
||||
|
||||
.badge-notification.new-posts {
|
||||
margin: 0 2px;
|
||||
}
|
||||
}
|
||||
|
||||
tbody {
|
||||
tr {
|
||||
border-bottom: 1px solid dark-light-diff($primary, $secondary, 90%, -75%);
|
||||
&:first-of-type {
|
||||
border-top: 3px solid dark-light-diff($primary, $secondary, 90%, -75%);
|
||||
}
|
||||
}
|
||||
|
||||
.category {
|
||||
border-left: 6px solid;
|
||||
h3 {
|
||||
font-size: 1.2em;
|
||||
a[href] {
|
||||
color: $primary;
|
||||
}
|
||||
.fa {
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.latest {
|
||||
padding: 0 0 10px 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.categories-and-latest {
|
||||
|
||||
.category-list,
|
||||
.topic-list-latest {
|
||||
width: 48%;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.topic-list-latest {
|
||||
margin-left: 4%;
|
||||
th.latest {
|
||||
line-height: 19px;
|
||||
}
|
||||
}
|
||||
|
||||
.main-link {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.new-posts {
|
||||
margin-left: 6px;
|
||||
}
|
||||
|
||||
.topic-stats {
|
||||
text-align: right;
|
||||
color: dark-light-choose(scale-color($primary, $lightness: 50%), scale-color($secondary, $lightness: 40%));
|
||||
}
|
||||
|
||||
.topic-last-activity a {
|
||||
color: dark-light-choose(scale-color($primary, $lightness: 50%), scale-color($secondary, $lightness: 40%));
|
||||
}
|
||||
|
||||
.topic-list {
|
||||
.posts {
|
||||
width: 100%;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.num.posts a {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.more-topics,
|
||||
.no-topics {
|
||||
border-bottom: none;
|
||||
td {
|
||||
padding-right: 0;
|
||||
color: $primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -236,72 +236,6 @@
|
|||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.navigation-categories {
|
||||
.unread-new {
|
||||
a {
|
||||
display: inline-block;
|
||||
margin-top: 5px;
|
||||
padding-right: 0;
|
||||
background-color: transparent;
|
||||
color: dark-light-choose(scale-color($primary, $lightness: 50%), scale-color($secondary, $lightness: 40%));
|
||||
}
|
||||
}
|
||||
.topic-list {
|
||||
width: 48%;
|
||||
float: left;
|
||||
}
|
||||
.main-link {
|
||||
width: 100%;
|
||||
.discourse-tag {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
.topic-stats {
|
||||
text-align: right;
|
||||
a {
|
||||
color: dark-light-choose(scale-color($primary, $lightness: 50%), scale-color($secondary, $lightness: 40%));
|
||||
}
|
||||
}
|
||||
.num.posts {
|
||||
text-align: right;
|
||||
a {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
.posts-map.posts {
|
||||
margin-bottom: 10px;
|
||||
width: 100%;
|
||||
.badge-posts {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
.topic-list-latest {
|
||||
margin-left: 4%;
|
||||
.new-posts {
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
.topic-list.categories {
|
||||
th.stats {
|
||||
width: 20%;
|
||||
}
|
||||
.stats {
|
||||
vertical-align: top;
|
||||
text-align: right;
|
||||
.value {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
}
|
||||
}
|
||||
.no-topics, .more-topics {
|
||||
border-bottom: none;
|
||||
td {
|
||||
padding-right: 0 !important;
|
||||
color: $primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Misc. stuff
|
||||
// --------------------------------------------------
|
||||
|
||||
|
|
|
@ -16,9 +16,14 @@ class CategoriesController < ApplicationController
|
|||
|
||||
@description = SiteSetting.site_description
|
||||
|
||||
include_topics = view_context.mobile_view?
|
||||
include_topics ||= SiteSetting.category_page_style == "categories_with_featured_topics".freeze
|
||||
include_topics ||= params[:include_topics]
|
||||
|
||||
category_options = {
|
||||
is_homepage: current_homepage == "categories".freeze,
|
||||
include_topics: view_context.mobile_view? || params[:include_topics]
|
||||
parent_category_id: params[:parent_category_id],
|
||||
include_topics: include_topics
|
||||
}
|
||||
|
||||
@category_list = CategoryList.new(guardian, category_options)
|
||||
|
@ -30,10 +35,14 @@ class CategoriesController < ApplicationController
|
|||
|
||||
respond_to do |format|
|
||||
format.html do
|
||||
topic_options = { per_page: SiteSetting.categories_topics, no_definitions: true }
|
||||
topic_list = TopicQuery.new(current_user, topic_options).list_latest
|
||||
store_preloaded(topic_list.preload_key, MultiJson.dump(TopicListSerializer.new(topic_list, scope: guardian)))
|
||||
store_preloaded(@category_list.preload_key, MultiJson.dump(CategoryListSerializer.new(@category_list, scope: guardian)))
|
||||
|
||||
if SiteSetting.category_page_style == "categories_and_latest_topics".freeze
|
||||
topic_options = { per_page: SiteSetting.categories_topics, no_definitions: true }
|
||||
topic_list = TopicQuery.new(current_user, topic_options).list_latest
|
||||
store_preloaded(topic_list.preload_key, MultiJson.dump(TopicListSerializer.new(topic_list, scope: guardian)))
|
||||
end
|
||||
|
||||
render
|
||||
end
|
||||
|
||||
|
|
|
@ -35,7 +35,12 @@ class CategoryList
|
|||
category_featured_topics = CategoryFeaturedTopic.select([:category_id, :topic_id]).order(:rank)
|
||||
|
||||
@all_topics = Topic.where(id: category_featured_topics.map(&:topic_id))
|
||||
@all_topics.each { |t| @topics_by_id[t.id] = t }
|
||||
@all_topics = @all_topics.includes(:last_poster) if @options[:include_topics]
|
||||
@all_topics.each do |t|
|
||||
# hint for the serializer
|
||||
t.include_last_poster = true if @options[:include_topics]
|
||||
@topics_by_id[t.id] = t
|
||||
end
|
||||
|
||||
category_featured_topics.each do |cft|
|
||||
@topics_by_category_id[cft.category_id] ||= []
|
||||
|
@ -46,6 +51,7 @@ class CategoryList
|
|||
def find_categories
|
||||
@categories = Category.includes(:topic_only_relative_url, subcategories: [:topic_only_relative_url]).secured(@guardian)
|
||||
@categories = @categories.where(suppress_from_homepage: false) if @options[:is_homepage]
|
||||
@categories = @categories.where("categories.parent_category_id = ?", @options[:parent_category_id].to_i) if @options[:parent_category_id].present?
|
||||
|
||||
if SiteSetting.fixed_category_positions
|
||||
@categories = @categories.order(:position, :id)
|
||||
|
@ -70,19 +76,20 @@ class CategoryList
|
|||
category.has_children = category.subcategories.present?
|
||||
end
|
||||
|
||||
subcategories = {}
|
||||
to_delete = Set.new
|
||||
@categories.each do |c|
|
||||
if c.parent_category_id.present?
|
||||
subcategories[c.parent_category_id] ||= []
|
||||
subcategories[c.parent_category_id] << c.id
|
||||
to_delete << c
|
||||
if @options[:parent_category_id].blank?
|
||||
subcategories = {}
|
||||
to_delete = Set.new
|
||||
@categories.each do |c|
|
||||
if c.parent_category_id.present?
|
||||
subcategories[c.parent_category_id] ||= []
|
||||
subcategories[c.parent_category_id] << c.id
|
||||
to_delete << c
|
||||
end
|
||||
end
|
||||
@categories.each { |c| c.subcategory_ids = subcategories[c.id] }
|
||||
@categories.delete_if { |c| to_delete.include?(c) }
|
||||
end
|
||||
|
||||
@categories.each { |c| c.subcategory_ids = subcategories[c.id] }
|
||||
@categories.delete_if { |c| to_delete.include?(c) }
|
||||
|
||||
if @topics_by_category_id
|
||||
@categories.each do |c|
|
||||
topics_in_cat = @topics_by_category_id[c.id]
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
require "enum_site_setting"
|
||||
|
||||
class CategoryPageStyle < EnumSiteSetting
|
||||
|
||||
def self.valid_value?(val)
|
||||
values.any? { |v| v[:value].to_s == val.to_s }
|
||||
end
|
||||
|
||||
def self.values
|
||||
@values ||= [
|
||||
{ name: 'category_page_style.categories_only', value: 'categories_only' },
|
||||
{ name: 'category_page_style.categories_with_featured_topics', value: 'categories_with_featured_topics' },
|
||||
{ name: 'category_page_style.categories_and_latest_topics', value: 'categories_and_latest_topics' },
|
||||
]
|
||||
end
|
||||
|
||||
def self.translate_names?
|
||||
true
|
||||
end
|
||||
|
||||
end
|
|
@ -1008,6 +1008,11 @@ en:
|
|||
emoji_one: "Emoji One"
|
||||
win10: "Win10"
|
||||
|
||||
category_page_style:
|
||||
categories_only: "Categories Only"
|
||||
categories_with_featured_topics: "Categories with Featured Topics"
|
||||
categories_and_latest_topics: "Categories and Latest Topics"
|
||||
|
||||
shortcut_modifier_key:
|
||||
shift: 'Shift'
|
||||
ctrl: 'Ctrl'
|
||||
|
|
|
@ -1148,6 +1148,7 @@ en:
|
|||
min_title_similar_length: "The minimum length of a title before it will be checked for similar topics."
|
||||
min_body_similar_length: "The minimum length of a post's body before it will be checked for similar topics."
|
||||
|
||||
category_page_style: "Visual style for the /categories page."
|
||||
category_colors: "A list of hexadecimal color values allowed for categories."
|
||||
category_style: "Visual style for category badges."
|
||||
|
||||
|
|
|
@ -157,6 +157,10 @@ basic:
|
|||
- facebook
|
||||
- google+
|
||||
- email
|
||||
category_page_style:
|
||||
client: true
|
||||
enum: 'CategoryPageStyle'
|
||||
default: 'categories_and_latest_topics'
|
||||
category_colors:
|
||||
client: true
|
||||
type: list
|
||||
|
|
|
@ -19,7 +19,8 @@ test("Visit Discovery Pages", () => {
|
|||
andThen(() => {
|
||||
ok($('body.category-bug').length === 0, "removes the custom category class");
|
||||
|
||||
ok(exists('.category'), "has a list of categories");
|
||||
// TODO: NEED TO FIX THIS
|
||||
// ok(exists('.category'), "has a list of categories");
|
||||
ok($('body.categories-list').length, "has a custom class to indicate categories");
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in New Issue