Add dedicated tags page

This commit is contained in:
Toby Zerner 2015-06-15 12:21:08 +09:30
parent ed2fb779e6
commit f3f0684eee
4 changed files with 185 additions and 23 deletions

View File

@ -17,6 +17,10 @@ app.initializers.add('flarum-tags', function() {
app.routes['tags'] = ['/tags', TagsPage.component()];
app.routes['tag'] = ['/t/:tags', IndexPage.component()];
app.route.tag = function(tag) {
return app.route('tag', { tags: tag.slug() });
};
// Register models.
app.store.models['tags'] = Tag;
Discussion.prototype.tags = Model.many('tags');

View File

@ -4,25 +4,26 @@ import NavItem from 'flarum/components/nav-item';
import Separator from 'flarum/components/separator';
import TagNavItem from 'flarum-tags/components/tag-nav-item';
import TagsPage from 'flarum-tags/components/tags-page';
export default function() {
// Add a link to the tags page, as well as a list of all the tags,
// to the index page's sidebar.
extend(IndexPage.prototype, 'navItems', function(items) {
items.add('tags', NavItem.component({
icon: 'reorder',
icon: 'th-large',
label: 'Tags',
href: app.route('tags'),
config: m.route
}), {last: true});
if (app.current instanceof TagsPage) return;
items.add('separator', Separator.component(), {last: true});
var params = this.stickyParams();
var tags = app.store.all('tags');
items.add('untagged', TagNavItem.component({params}), {last: true});
var addTag = tag => {
var currentTag = this.currentTag();
var active = currentTag === tag;

View File

@ -1,38 +1,75 @@
import Component from 'flarum/component';
import WelcomeHero from 'flarum/components/welcome-hero';
import IndexPage from 'flarum/components/index-page';
import icon from 'flarum/helpers/icon';
import listItems from 'flarum/helpers/list-items';
import abbreviateNumber from 'flarum/utils/abbreviate-number';
import humanTime from 'flarum/helpers/human-time';
import sortTags from 'flarum-tags/utils/sort-tags';
export default class TagsPage extends Component {
constructor(props) {
super(props);
this.categories = m.prop(app.store.all('categories'));
this.tags = sortTags(app.store.all('tags').filter(tag => !tag.parent()));
app.current = this;
app.history.push('tags');
}
view() {
return m('div.categories-area', [
m('div.title-control.categories-forum-title', app.config.forum_title),
WelcomeHero.component(),
var pinned = this.tags.filter(tag => tag.position() !== null);
var cloud = this.tags.filter(tag => tag.position() === null);
return m('div.tags-area', {config: this.onload.bind(this)}, [
IndexPage.prototype.hero(),
m('div.container', [
m('ul.category-list.category-list-tiles', [
m('li.filter-tile', [
m('a', {href: app.route('index'), config: m.route}, 'All Discussions'),
// m('ul.filter-list', [
// m('li', m('a', {href: app.route('index'), config: m.route}, m('span', [icon('star'), ' Following']))),
// m('li', m('a', {href: app.route('index'), config: m.route}, m('span', [icon('envelope-o'), ' Inbox'])))
// ])
m('nav.side-nav.index-nav', [
m('ul', listItems(IndexPage.prototype.sidebarItems().toArray()))
]),
m('div.offset-content.tags-content', [
m('ul.tag-tiles', [
pinned.map(tag => {
var lastDiscussion = tag.lastDiscussion();
var children = app.store.all('tags').filter(child => {
var parent = child.parent();
return parent && parent.id() == tag.id();
});
return m('li.tag-tile', {style: 'background-color: '+tag.color()}, [
m('a.tag-info', {href: app.route.tag(tag), config: m.route}, [
m('h3.name', tag.name()),
m('p.description', tag.description()),
children ? m('div.children', children.map(tag =>
m('a', {href: app.route.tag(tag), config: m.route, onclick: (e) => e.stopPropagation()}, tag.name())
)) : ''
]),
lastDiscussion
? m('a.last-discussion', {
href: app.route.discussion(lastDiscussion, lastDiscussion.lastPostNumber()),
config: m.route
}, [m('span.title', lastDiscussion.title()), humanTime(lastDiscussion.lastTime())])
: m('span.last-discussion')
]);
})
]),
this.categories().map(category =>
m('li.category-tile', {style: 'background-color: '+category.color()}, [
m('a', {href: app.route('category', {categories: category.slug()}), config: m.route}, [
m('h3.title', category.title()),
m('p.description', category.description()),
m('span.count', category.discussionsCount()+' discussions'),
])
])
)
m('div.tag-cloud', [
m('h4', 'Tags'),
m('div.tag-cloud-content', cloud.map(tag =>
m('a', {href: app.route.tag(tag), config: m.route, style: tag.color() ? 'color: '+tag.color() : ''}, tag.name())
))
])
])
])
]);
}
onload(element, isInitialized, context) {
IndexPage.prototype.onload.apply(this, arguments);
}
onunload() {
IndexPage.prototype.onunload.apply(this);
}
}

View File

@ -212,3 +212,123 @@
}
}
}
.tag-tiles {
list-style-type: none;
padding: 0;
margin: 0;
overflow: hidden;
& > li {
float: left;
width: ~"calc(50% - 1px)";
height: 200px;
margin-right: 1px;
margin-bottom: 1px;
overflow: hidden;
&:first-child {
border-radius: @border-radius-base 0 0 0;
}
&:nth-child(2) {
border-radius: 0 @border-radius-base 0 0;
}
&:nth-last-child(2):nth-child(even), &:last-child {
border-radius: 0 0 @border-radius-base 0;
}
&:nth-last-child(2):nth-child(odd), &:last-child:nth-child(odd) {
border-radius: 0 0 0 @border-radius-base;
}
}
}
.tag-tile {
position: relative;
&, & a {
color: #fff;
}
& .tag-info, & .last-discussion {
padding: 20px;
text-decoration: none;
display: block;
position: absolute;
left: 0;
right: 0;
}
& > a {
transition: background 0.2s;
&:hover {
background: fade(#000, 10%);
}
&:active {
background: fade(#000, 20%);
}
}
& .tag-info {
top: 0;
bottom: 55px;
padding-right: 20px;
& .name {
font-size: 20px;
margin: 0 0 10px;
font-weight: normal;
}
& .description {
color: fade(#fff, 50%);
margin: 0 0 15px;
}
& .children {
text-transform: uppercase;
font-weight: 600;
font-size: 12px;
& > a {
margin-right: 15px;
}
}
}
& .last-discussion {
bottom: 0;
height: 55px;
border-top: 1px solid rgba(0, 0, 0, 0.1);
padding-top: 17px;
padding-bottom: 17px;
color: fade(#fff, 50%);
& .title {
margin-right: 15px;
}
}
}
.tag-cloud {
margin-top: 30px;
text-align: center;
& h4 {
font-size: 12px;
font-weight: bold;
color: @fl-body-muted-color;
text-transform: uppercase;
margin-bottom: 15px;
&:before {
.fa();
content: @fa-var-tags;
margin-right: 5px;
font-size: 14px;
}
}
}
.tag-cloud-content {
font-size: 14px;
&, & a {
color: @fl-body-muted-color;
}
& a {
margin: 0 6px;
}
}