FEATURE: Decorate category hashtag links.
This commit is contained in:
parent
0812807a53
commit
4a7f560a35
|
@ -3,6 +3,7 @@ import loadScript from 'discourse/lib/load-script';
|
|||
import { default as computed, on, observes } from 'ember-addons/ember-computed-decorators';
|
||||
import { showSelector } from "discourse/lib/emoji/emoji-toolbar";
|
||||
import Category from 'discourse/models/category';
|
||||
import { SEPARATOR as categoryHashtagSeparator } from 'discourse/lib/category-hashtags';
|
||||
|
||||
// Our head can be a static string or a function that returns a string
|
||||
// based on input (like for numbered lists).
|
||||
|
@ -255,7 +256,7 @@ export default Ember.Component.extend({
|
|||
template: template,
|
||||
key: '#',
|
||||
transformComplete(category) {
|
||||
return Category.slugFor(category, ":");
|
||||
return Category.slugFor(category, categoryHashtagSeparator);
|
||||
},
|
||||
dataSource(term) {
|
||||
return Category.search(term);
|
||||
|
|
|
@ -21,7 +21,7 @@ export function categoryBadgeHTML(category, opts) {
|
|||
|
||||
var description = get(category, 'description_text'),
|
||||
restricted = get(category, 'read_restricted'),
|
||||
url = Discourse.getURL("/c/") + Discourse.Category.slugFor(category),
|
||||
url = opts.url ? opts.url : Discourse.getURL("/c/") + Discourse.Category.slugFor(category),
|
||||
href = (opts.link === false ? '' : url),
|
||||
tagName = (opts.link === false || opts.link === "false" ? 'span' : 'a'),
|
||||
extraClasses = (opts.extraClasses ? (' ' + opts.extraClasses) : ''),
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
import Category from 'discourse/models/category';
|
||||
import { categoryBadgeHTML } from 'discourse/helpers/category-link';
|
||||
|
||||
export const SEPARATOR = ":";
|
||||
|
||||
export function findCategoryByHashtagSlug(hashtagSlug) {
|
||||
if (hashtagSlug.indexOf('#') === 0) hashtagSlug = hashtagSlug.slice(1);
|
||||
return Category.findBySlug.apply(null, hashtagSlug.split(SEPARATOR, 2).reverse());
|
||||
};
|
||||
|
||||
export function replaceSpan($elem, categorySlug, categoryLink) {
|
||||
const category = findCategoryByHashtagSlug(categorySlug);
|
||||
|
||||
if (!category) {
|
||||
$elem.replaceWith(categorySlug);
|
||||
} else {
|
||||
$elem.replaceWith(categoryBadgeHTML(
|
||||
category, { url: categoryLink, allowUncategorized: true }
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
export function decorateLinks($elems) {
|
||||
$elems.each((_, elem) => replaceSpan($(elem), elem.text, elem.href));
|
||||
}
|
||||
|
|
@ -1,12 +1,10 @@
|
|||
import { replaceSpan } from 'discourse/lib/category-hashtags';
|
||||
|
||||
const validCategoryHashtags = {};
|
||||
const checkedCategoryHashtags = [];
|
||||
const testedKey = 'tested';
|
||||
const testedClass = `hashtag-${testedKey}`;
|
||||
|
||||
function replaceSpan($elem, categorySlug, categoryLink) {
|
||||
$elem.replaceWith(`<a href="${categoryLink}" class="hashtag">#${categorySlug}</a>`);
|
||||
}
|
||||
|
||||
function updateFound($hashtags, categorySlugs) {
|
||||
Ember.run.schedule('afterRender', () => {
|
||||
$hashtags.each((index, hashtag) => {
|
||||
|
|
|
@ -3,6 +3,7 @@ import { number } from 'discourse/lib/formatter';
|
|||
import DiscourseURL from 'discourse/lib/url';
|
||||
import { default as computed, on } from 'ember-addons/ember-computed-decorators';
|
||||
import { fmt } from 'discourse/lib/computed';
|
||||
import { decorateLinks as decorateCategoryHashtagLinks } from 'discourse/lib/category-hashtags';
|
||||
|
||||
const DAY = 60 * 50 * 1000;
|
||||
|
||||
|
@ -75,6 +76,7 @@ const PostView = Discourse.GroupedView.extend(Ember.Evented, {
|
|||
_cookedWasChanged() {
|
||||
this.trigger('postViewUpdated', this.$());
|
||||
this._insertQuoteControls();
|
||||
this._decorateCategoryHashtagLinks();
|
||||
},
|
||||
|
||||
mouseUp(e) {
|
||||
|
@ -318,6 +320,7 @@ const PostView = Discourse.GroupedView.extend(Ember.Evented, {
|
|||
const $post = this.$(),
|
||||
postNumber = this.get('post').get('post_number');
|
||||
|
||||
this._decorateCategoryHashtagLinks();
|
||||
this._showLinkCounts();
|
||||
|
||||
ScreenTrack.current().track($post.prop('id'), postNumber);
|
||||
|
@ -375,7 +378,12 @@ const PostView = Discourse.GroupedView.extend(Ember.Evented, {
|
|||
cooked.unhighlight();
|
||||
this._highlighted = false;
|
||||
}
|
||||
}.observes('searchService.highlightTerm', 'cooked')
|
||||
}.observes('searchService.highlightTerm', 'cooked'),
|
||||
|
||||
_decorateCategoryHashtagLinks() {
|
||||
const $elems = this.$('.cooked a.hashtag');
|
||||
if ($elems.length > 0) decorateCategoryHashtagLinks($elems);
|
||||
}
|
||||
});
|
||||
|
||||
export default PostView;
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
color: $primary !important;
|
||||
padding: 3px;
|
||||
vertical-align: text-top;
|
||||
margin-top: -3px; //vertical alignment fix
|
||||
margin-top: -2px; //vertical alignment fix
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
|
@ -38,21 +38,18 @@
|
|||
.extra-info-wrapper & {
|
||||
color: $header-primary !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.badge-category-parent-bg, .badge-category-bg {
|
||||
display: inline-block;
|
||||
padding: 1px;
|
||||
|
||||
&:before {
|
||||
content: "\a0";
|
||||
}
|
||||
|
||||
}
|
||||
.badge-category-parent-bg, .badge-category-bg {
|
||||
display: inline-block;
|
||||
padding: 1px;
|
||||
|
||||
&:before {
|
||||
content: "\a0";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
&.bullet { //bullet category style
|
||||
display: inline-flex;
|
||||
align-items: baseline;
|
||||
|
@ -71,31 +68,30 @@
|
|||
.extra-info-wrapper & {
|
||||
color: $header-primary !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.badge-category-parent-bg, .badge-category-bg {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
margin-right: 5px;
|
||||
display: inline-block;
|
||||
line-height: 1;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
margin-right: 5px;
|
||||
display: inline-block;
|
||||
line-height: 1;
|
||||
|
||||
&:before {
|
||||
content: "\a0";
|
||||
}
|
||||
}
|
||||
&:before {
|
||||
content: "\a0";
|
||||
}
|
||||
}
|
||||
|
||||
span {
|
||||
&.badge-category-parent-bg { //subcategory style
|
||||
width: 5px;
|
||||
margin-right: 0;
|
||||
& + .badge-category-bg {
|
||||
width: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
span {
|
||||
&.badge-category-parent-bg { //subcategory style
|
||||
width: 5px;
|
||||
margin-right: 0;
|
||||
& + .badge-category-bg {
|
||||
width: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
&.box { //box category style (apply custom widths to the wrapper, not the children)
|
||||
|
@ -134,6 +130,59 @@
|
|||
}
|
||||
}
|
||||
|
||||
@mixin cooked-badge-bullet($length, $offset:0px) {
|
||||
.badge-wrapper.bullet {
|
||||
span {
|
||||
position: relative;
|
||||
|
||||
&.badge-category-bg {
|
||||
width: $length;
|
||||
height: $length;
|
||||
top: $offset;
|
||||
}
|
||||
|
||||
&.badge-category-parent-bg {
|
||||
width: $length / 2;
|
||||
height: $length;
|
||||
top: $offset;
|
||||
|
||||
& + .badge-category-bg {
|
||||
width: $length / 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.cooked, .d-editor-preview {
|
||||
p .badge-wrapper.bullet {
|
||||
margin: 0px 2.5px;
|
||||
}
|
||||
|
||||
h1 { @include cooked-badge-bullet(22px) }
|
||||
h2 { @include cooked-badge-bullet(17px) }
|
||||
h3 { @include cooked-badge-bullet(14px) }
|
||||
h4 { @include cooked-badge-bullet(12px) }
|
||||
h5 { @include cooked-badge-bullet(10px, -1.1px) }
|
||||
h6 { @include cooked-badge-bullet(9px, -1.5px) }
|
||||
|
||||
.badge-wrapper.box {
|
||||
span {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.badge-notification.clicks {
|
||||
display: inline-block;
|
||||
overflow: visible;
|
||||
top: 0px;
|
||||
}
|
||||
|
||||
.badge-category-bg {
|
||||
padding-right: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Category badge dropdown
|
||||
// --------------------------------------------------
|
||||
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
import createStore from 'helpers/create-store';
|
||||
import Category from 'discourse/models/category';
|
||||
import { findCategoryByHashtagSlug } from "discourse/lib/category-hashtags";
|
||||
|
||||
module("lib:category-hashtags");
|
||||
|
||||
test('findCategoryByHashtagSlug', () => {
|
||||
const store = createStore();
|
||||
|
||||
const parentCategory = store.createRecord('category', { slug: 'test1' });
|
||||
|
||||
const childCategory = store.createRecord('category', {
|
||||
slug: 'test2', parentCategory: parentCategory
|
||||
});
|
||||
|
||||
sandbox.stub(Category, 'list').returns([parentCategory, childCategory]);
|
||||
|
||||
equal(findCategoryByHashtagSlug('test1'), parentCategory, 'returns the right category');
|
||||
equal(findCategoryByHashtagSlug('test1:test2'), childCategory, 'returns the right category');
|
||||
equal(findCategoryByHashtagSlug('#test1'), parentCategory, 'returns the right category');
|
||||
equal(findCategoryByHashtagSlug('#test1:test2'), childCategory, 'returns the right category');
|
||||
});
|
Loading…
Reference in New Issue