Merge pull request #3965 from tgxworld/decorate_category_hashtag
Decorate category hashtag
This commit is contained in:
commit
c2c1aea381
|
@ -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
|
||||
// --------------------------------------------------
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ module CategoryHashtag
|
|||
|
||||
class_methods do
|
||||
def query_from_hashtag_slug(category_slug)
|
||||
parent_slug, child_slug = category_slug.split(":", 2)
|
||||
parent_slug, child_slug = category_slug.split(SEPARATOR, 2)
|
||||
|
||||
category = Category.where(slug: parent_slug, parent_category_id: nil)
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ describe CategoryHashtag do
|
|||
end
|
||||
|
||||
it "should return the right result for a parent and child category slug" do
|
||||
expect(Category.query_from_hashtag_slug("#{parent_category.slug}:#{child_category.slug}"))
|
||||
expect(Category.query_from_hashtag_slug("#{parent_category.slug}#{CategoryHashtag::SEPARATOR}#{child_category.slug}"))
|
||||
.to eq(child_category)
|
||||
end
|
||||
|
||||
|
@ -20,7 +20,7 @@ describe CategoryHashtag do
|
|||
end
|
||||
|
||||
it "should return nil for incorrect parent and child category slug" do
|
||||
expect(Category.query_from_hashtag_slug("random-slug:random-slug")).to eq(nil)
|
||||
expect(Category.query_from_hashtag_slug("random-slug#{CategoryHashtag::SEPARATOR}random-slug")).to eq(nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -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