Migrate `createViewWithBodyClass` helper to components

This commit is contained in:
Robin Ward 2016-11-10 13:33:31 -05:00
parent ecb9574a32
commit 0904ad5537
38 changed files with 683 additions and 621 deletions

View File

@ -0,0 +1,45 @@
import DiscourseURL from 'discourse/lib/url';
// Can add a body class from within a component, also will scroll to the top automatically.
export default Ember.Component.extend({
tagName: 'section',
_scrollTop() {
if (Ember.testing) { return; }
$(document).scrollTop(0);
},
didInsertElement() {
this._super();
const pageClass = this.get('pageClass');
if (pageClass) {
$('body').addClass(`${pageClass}-page`);
}
const bodyClass = this.get('bodyClass');
if (bodyClass) {
$('body').addClass(bodyClass);
}
if (this.get('scrollTop') === "false") {
return;
}
if (DiscourseURL.isJumpScheduled()) { return; }
Ember.run.scheduleOnce('afterRender', this, this._scrollTop);
},
willDestroyElement() {
this._super();
const pageClass = this.get('pageClass');
if (pageClass) {
$('body').removeClass(`${pageClass}-page`);
}
const bodyClass = this.get('bodyClass');
if (bodyClass) {
$('body').removeClass(bodyClass);
}
}
});

View File

@ -1,15 +0,0 @@
import { on } from 'ember-addons/ember-computed-decorators';
export function createViewWithBodyClass(body_class) {
return Ember.View.extend({
@on("didInsertElement")
addBodyClass() {
$('body').addClass(body_class);
},
@on("willDestroyElement")
removeBodyClass() {
$('body').removeClass(body_class);
}
});
}

View File

@ -1,4 +1,5 @@
<div class='container'> {{#d-section pageClass="about"}}
<div class='container'>
<div class='contents clearfix body-page'> <div class='contents clearfix body-page'>
<ul class="nav-pills"> <ul class="nav-pills">
@ -94,4 +95,5 @@
{{/if}} {{/if}}
</div> </div>
</div> </div>
{{/d-section}}

View File

@ -1,4 +1,5 @@
<div class='container badges'> {{#d-section pageClass="badges"}}
<div class='container badges'>
<h1>{{i18n 'badges.title'}}</h1> <h1>{{i18n 'badges.title'}}</h1>
<div class='badge-groups'> <div class='badge-groups'>
@ -14,4 +15,5 @@
</div> </div>
{{/each}} {{/each}}
</div> </div>
</div> </div>
{{/d-section}}

View File

@ -1,4 +1,5 @@
<div class="search row clearfix"> {{#d-section pageClass="search" class="search-container"}}
<div class="search row clearfix">
{{search-text-field value=searchTerm class="full-page-search input-xxlarge search no-blur" action="search" hasAutofocus=hasAutofocus}} {{search-text-field value=searchTerm class="full-page-search input-xxlarge search no-blur" action="search" hasAutofocus=hasAutofocus}}
{{d-button action="search" icon="search" class="btn-primary" disabled=searching}} {{d-button action="search" icon="search" class="btn-primary" disabled=searching}}
@ -21,30 +22,30 @@
{{d-button icon="list" class="bulk-select" title="topics.bulk.toggle" action="toggleBulkSelect"}} {{d-button icon="list" class="bulk-select" title="topics.bulk.toggle" action="toggleBulkSelect"}}
{{bulk-select-button selected=selected action="search"}} {{bulk-select-button selected=selected action="search"}}
{{/if}} {{/if}}
</div> </div>
{{#if bulkSelectEnabled}} {{#if bulkSelectEnabled}}
<div class='fps-select'> <div class='fps-select'>
<a {{action "selectAll"}}>{{i18n "search.select_all"}}</a> <a {{action "selectAll"}}>{{i18n "search.select_all"}}</a>
<a {{action "clearAll"}}>{{i18n "search.clear_all"}}</a> <a {{action "clearAll"}}>{{i18n "search.clear_all"}}</a>
</div> </div>
{{/if}} {{/if}}
{{#if invalidSearch}} {{#if invalidSearch}}
<div class='fps-invalid'> <div class='fps-invalid'>
{{i18n "search.too_short"}} {{i18n "search.too_short"}}
</div> </div>
{{/if}} {{/if}}
{{#if context}} {{#if context}}
<div class='fps-search-context'> <div class='fps-search-context'>
<label> <label>
{{input type="checkbox" name="searchContext" checked=searchContextEnabled}} {{searchContextDescription}} {{input type="checkbox" name="searchContext" checked=searchContextEnabled}} {{searchContextDescription}}
</label> </label>
</div> </div>
{{/if}} {{/if}}
{{#conditional-loading-spinner condition=loading}} {{#conditional-loading-spinner condition=loading}}
{{#unless hasResults}} {{#unless hasResults}}
<h3> <h3>
@ -129,4 +130,5 @@
</h3> </h3>
{{/if}} {{/if}}
{{/conditional-loading-spinner}} {{/conditional-loading-spinner}}
{{/d-section}}

View File

@ -1,7 +1,9 @@
{{bread-crumbs categories=categories}} {{#d-section bodyClass="navigation-topics" scrollTop="false"}}
{{bread-crumbs categories=categories}}
{{navigation-bar navItems=navItems filterMode=filterMode}} {{navigation-bar navItems=navItems filterMode=filterMode}}
{{#if canCreateTopic}} {{#if canCreateTopic}}
<button id="create-topic" class='btn btn-default' {{action "createTopic"}}><i class='fa fa-plus'></i>{{i18n 'topic.create'}}</button> <button id="create-topic" class='btn btn-default' {{action "createTopic"}}><i class='fa fa-plus'></i>{{i18n 'topic.create'}}</button>
{{/if}} {{/if}}
{{/d-section}}

View File

@ -1,4 +1,4 @@
<section class='user-content user-preferences'> {{#d-section pageClass="user-preferences" class="user-content user-preferences"}}
<form class="form-horizontal"> <form class="form-horizontal">
@ -367,4 +367,4 @@
</div> </div>
{{/if}} {{/if}}
</form> </form>
</section> {{/d-section}}

View File

@ -1,4 +1,5 @@
<div class="container list-container"> {{#d-section pageClass="tags"}}
<div class="container list-container">
<div class="row"> <div class="row">
<div class="full-width"> <div class="full-width">
<div id='list-area'> <div id='list-area'>
@ -6,4 +7,5 @@
</div> </div>
</div> </div>
</div> </div>
</div> </div>
{{/d-section}}

View File

@ -1,4 +1,5 @@
{{#if canInviteToForum}} {{#d-section pageClass="user-invites"}}
{{#if canInviteToForum}}
{{#load-more class="paginated-topics-list" selector=".paginated-topics-list .user-invite-list tr" action="loadMore"}} {{#load-more class="paginated-topics-list" selector=".paginated-topics-list .user-invite-list tr" action="loadMore"}}
<section class='user-content'> <section class='user-content'>
<h2>{{i18n 'user.invited.title'}}</h2> <h2>{{i18n 'user.invited.title'}}</h2>
@ -106,4 +107,5 @@
{{/if}} {{/if}}
</section> </section>
{{/load-more}} {{/load-more}}
{{/if}} {{/if}}
{{/d-section}}

View File

@ -1,4 +1,4 @@
<section class='user-navigation'> {{#d-section pageClass="user-activity" class="user-nagivation" scrollTop="false"}}
{{#mobile-nav class='activity-nav' desktopClass='action-list activity-list nav-stacked' currentPath=currentPath}} {{#mobile-nav class='activity-nav' desktopClass='action-list activity-list nav-stacked' currentPath=currentPath}}
<li class='no-glyph'> <li class='no-glyph'>
{{#link-to 'userActivity.index'}}{{i18n 'user.filters.all'}}{{/link-to}} {{#link-to 'userActivity.index'}}{{i18n 'user.filters.all'}}{{/link-to}}
@ -31,10 +31,8 @@
{{d-button action="exportUserArchive" label="user.download_archive" icon="download"}} {{d-button action="exportUserArchive" label="user.download_archive" icon="download"}}
</div> </div>
{{/if}} {{/if}}
{{/d-section}}
</section>
<section class='user-right'> <section class='user-right'>
{{outlet}} {{outlet}}
</section> </section>

View File

@ -1,5 +1,5 @@
<section class='user-content user-badges-list'> {{#d-section pageClass="user-badges" class="user-content user-badges-list"}}
{{#each sortedBadges as |ub|}} {{#each sortedBadges as |ub|}}
{{badge-card badge=ub.badge count=ub.count navigateOnClick="true" username=username}} {{badge-card badge=ub.badge count=ub.count navigateOnClick="true" username=username}}
{{/each}} {{/each}}
</section> {{/d-section}}

View File

@ -1,4 +1,4 @@
<section class='user-navigation'> {{#d-section class="user-navigation" pageClass="user-messages"}}
{{#unless site.mobileView}} {{#unless site.mobileView}}
{{#if showNewPM}} {{#if showNewPM}}
{{d-button class="btn-primary new-private-message" action="composePrivateMessage" icon="envelope" label="user.new_private_message"}} {{d-button class="btn-primary new-private-message" action="composePrivateMessage" icon="envelope" label="user.new_private_message"}}
@ -37,8 +37,7 @@
{{/if}} {{/if}}
{{/each}} {{/each}}
{{/mobile-nav}} {{/mobile-nav}}
{{/d-section}}
</section>
<section class='user-right messages'> <section class='user-right messages'>

View File

@ -1,4 +1,4 @@
<section class='user-navigation'> {{#d-section pageClass="user-notifications" class="user-notifications"}}
{{#mobile-nav class='notifications-nav' desktopClass='notification-list action-list nav-stacked' currentPath=application.currentPath}} {{#mobile-nav class='notifications-nav' desktopClass='notification-list action-list nav-stacked' currentPath=application.currentPath}}
<li class='no-glyph'> <li class='no-glyph'>
{{#link-to 'userNotifications.index'}}{{i18n 'user.filters.all'}}{{/link-to}} {{#link-to 'userNotifications.index'}}{{i18n 'user.filters.all'}}{{/link-to}}
@ -26,7 +26,7 @@
icon='check' icon='check'
disabled=allNotificationsRead}} disabled=allNotificationsRead}}
{{/if}} {{/if}}
</section> {{/d-section}}
<section class='user-right'> <section class='user-right'>
{{#load-more class="notification-history user-stream" selector=".user-stream .notification" action="loadMore"}} {{#load-more class="notification-history user-stream" selector=".user-stream .notification" action="loadMore"}}

View File

@ -1,4 +1,5 @@
<div class='top-section stats-section'> {{#d-section pageClass="user-summary"}}
<div class='top-section stats-section'>
<h3 class='stats-title'>{{i18n "user.summary.stats"}}</h3> <h3 class='stats-title'>{{i18n "user.summary.stats"}}</h3>
<ul> <ul>
<li> <li>
@ -37,9 +38,9 @@
{{user-stat value=model.likes_received label="user.summary.likes_received"}} {{user-stat value=model.likes_received label="user.summary.likes_received"}}
</li> </li>
</ul> </ul>
</div> </div>
<div class='top-section'> <div class='top-section'>
<div class='top-sub-section replies-section pull-left'> <div class='top-sub-section replies-section pull-left'>
<h3 class='stats-title'>{{i18n "user.summary.top_replies"}}</h3> <h3 class='stats-title'>{{i18n "user.summary.top_replies"}}</h3>
{{#if model.replies.length}} {{#if model.replies.length}}
@ -90,9 +91,9 @@
<p>{{i18n "user.summary.no_topics"}}</p> <p>{{i18n "user.summary.no_topics"}}</p>
{{/if}} {{/if}}
</div> </div>
</div> </div>
<div class='top-section'> <div class='top-section'>
<div class='top-sub-section links-section pull-left'> <div class='top-sub-section links-section pull-left'>
<h3 class='stats-title'>{{i18n "user.summary.top_links"}}</h3> <h3 class='stats-title'>{{i18n "user.summary.top_links"}}</h3>
{{#if model.links.length}} {{#if model.links.length}}
@ -133,9 +134,9 @@
<p>{{i18n "user.summary.no_replies"}}</p> <p>{{i18n "user.summary.no_replies"}}</p>
{{/if}} {{/if}}
</div> </div>
</div> </div>
<div class='top-section'> <div class='top-section'>
<div class='top-sub-section likes-section pull-left'> <div class='top-sub-section likes-section pull-left'>
<h3 class='stats-title'>{{i18n "user.summary.most_liked_by"}}</h3> <h3 class='stats-title'>{{i18n "user.summary.most_liked_by"}}</h3>
{{#if model.most_liked_by_users.length}} {{#if model.most_liked_by_users.length}}
@ -170,9 +171,9 @@
<p>{{i18n "user.summary.no_likes"}}</p> <p>{{i18n "user.summary.no_likes"}}</p>
{{/if}} {{/if}}
</div> </div>
</div> </div>
<div class='top-section badges-section'> <div class='top-section badges-section'>
<h3 class='stats-title'>{{i18n "user.summary.top_badges"}}</h3> <h3 class='stats-title'>{{i18n "user.summary.top_badges"}}</h3>
{{#each model.badges as |badge|}} {{#each model.badges as |badge|}}
{{badge-card badge=badge count=badge.count navigateOnClick="true" username=user.username_lower}} {{badge-card badge=badge count=badge.count navigateOnClick="true" username=user.username_lower}}
@ -182,4 +183,5 @@
{{#if moreBadges}} {{#if moreBadges}}
<p>{{#link-to "user.badges" user class="more"}}{{i18n "user.summary.more_badges"}}{{/link-to}}</p> <p>{{#link-to "user.badges" user class="more"}}{{i18n "user.summary.more_badges"}}{{/link-to}}</p>
{{/if}} {{/if}}
</div> </div>
{{/d-section}}

View File

@ -1,4 +1,5 @@
{{#load-more selector=".directory tbody tr" action="loadMore"}} {{#d-section pageClass="users"}}
{{#load-more selector=".directory tbody tr" action="loadMore"}}
<div class="container"> <div class="container">
<div class='directory'> <div class='directory'>
@ -41,4 +42,5 @@
</div> </div>
</div> </div>
{{/load-more}} {{/load-more}}
{{/d-section}}

View File

@ -1,3 +0,0 @@
import { createViewWithBodyClass } from 'discourse/lib/create-view';
export default createViewWithBodyClass('about-page');

View File

@ -1,4 +0,0 @@
import ScrollTop from 'discourse/mixins/scroll-top';
import { createViewWithBodyClass } from 'discourse/lib/create-view';
export default createViewWithBodyClass('badges-page').extend(ScrollTop);

View File

@ -1,5 +0,0 @@
import { createViewWithBodyClass } from 'discourse/lib/create-view';
export default createViewWithBodyClass('search-page').extend({
classNames: ['search-container']
});

View File

@ -1,3 +0,0 @@
import { createViewWithBodyClass } from 'discourse/lib/create-view';
export default createViewWithBodyClass('navigation-topics');

View File

@ -1,6 +0,0 @@
import { createViewWithBodyClass } from 'discourse/lib/create-view';
export default createViewWithBodyClass('user-preferences-page').extend({
templateName: 'user/preferences',
classNames: ['user-preferences']
});

View File

@ -1,3 +0,0 @@
import { createViewWithBodyClass } from 'discourse/lib/create-view';
export default createViewWithBodyClass('tags-page');

View File

@ -1,3 +0,0 @@
import { createViewWithBodyClass } from 'discourse/lib/create-view';
export default createViewWithBodyClass('user-activity-page');

View File

@ -1,4 +0,0 @@
import ScrollTop from 'discourse/mixins/scroll-top';
import { createViewWithBodyClass } from 'discourse/lib/create-view';
export default createViewWithBodyClass('user-badges-page').extend(ScrollTop);

View File

@ -1,3 +0,0 @@
import { createViewWithBodyClass } from 'discourse/lib/create-view';
export default createViewWithBodyClass('user-invites-page');

View File

@ -1,3 +0,0 @@
import { createViewWithBodyClass } from 'discourse/lib/create-view';
export default createViewWithBodyClass('user-messages-page');

View File

@ -1,3 +0,0 @@
import { createViewWithBodyClass } from 'discourse/lib/create-view';
export default createViewWithBodyClass('user-notifications-page');

View File

@ -1,3 +0,0 @@
import { createViewWithBodyClass } from 'discourse/lib/create-view';
export default createViewWithBodyClass('user-summary-page');

View File

@ -1,3 +0,0 @@
import { createViewWithBodyClass } from 'discourse/lib/create-view';
export default createViewWithBodyClass('users-page');

View File

@ -4,6 +4,7 @@ acceptance("About");
test("viewing", () => { test("viewing", () => {
visit("/about"); visit("/about");
andThen(() => { andThen(() => {
ok($('body.about-page').length, "has body class");
ok(exists('.about.admins .user-info'), 'has admins'); ok(exists('.about.admins .user-info'), 'has admins');
ok(exists('.about.moderators .user-info'), 'has moderators'); ok(exists('.about.moderators .user-info'), 'has moderators');
ok(exists('.about.stats tr td'), 'has stats'); ok(exists('.about.stats tr td'), 'has stats');

View File

@ -5,6 +5,7 @@ acceptance("Badges");
test("Visit Badge Pages", () => { test("Visit Badge Pages", () => {
visit("/badges"); visit("/badges");
andThen(() => { andThen(() => {
ok($('body.badges-page').length, "has body class");
ok(exists('.badge-groups .badge-card'), "has a list of badges"); ok(exists('.badge-groups .badge-card'), "has a list of badges");
}); });

View File

@ -5,6 +5,7 @@ test("update some fields", () => {
visit("/users/eviltrout/preferences"); visit("/users/eviltrout/preferences");
andThen(() => { andThen(() => {
ok($('body.user-preferences-page').length, "has the body class");
equal(currentURL(), '/users/eviltrout/preferences', "it doesn't redirect"); equal(currentURL(), '/users/eviltrout/preferences', "it doesn't redirect");
ok(exists('.user-preferences'), 'it shows the preferences'); ok(exists('.user-preferences'), 'it shows the preferences');
}); });

View File

@ -43,6 +43,8 @@ test("perform various searches", assert => {
visit("/search"); visit("/search");
andThen(() => { andThen(() => {
ok($('body.search-page').length, "has body class");
ok(exists('.search-container'), "has container class");
assert.ok(find('input.search').length > 0); assert.ok(find('input.search').length > 0);
assert.ok(find('.fps-topic').length === 0); assert.ok(find('.fps-topic').length === 0);
}); });

View File

@ -0,0 +1,11 @@
import { acceptance } from "helpers/qunit-helpers";
acceptance("Tags", { loggedIn: true });
test("list the tags", () => {
visit("/tags");
andThen(() => {
ok($('body.tags-page').length, "has the body class");
ok(exists('.tag-eviltrout'), "shows the evil trout tag");
});
});

View File

@ -4,6 +4,7 @@ acceptance("Topic Discovery");
test("Visit Discovery Pages", () => { test("Visit Discovery Pages", () => {
visit("/"); visit("/");
andThen(() => { andThen(() => {
ok($('body.navigation-topics').length, "has the default navigation");
ok(exists(".topic-list"), "The list of topics was rendered"); ok(exists(".topic-list"), "The list of topics was rendered");
ok(exists('.topic-list .topic-list-item'), "has topics"); ok(exists('.topic-list .topic-list-item'), "has topics");
}); });

View File

@ -24,6 +24,9 @@ test("Root URL", () => {
test("Filters", () => { test("Filters", () => {
visit("/users/eviltrout/activity"); visit("/users/eviltrout/activity");
andThen(() => {
ok($('body.user-activity-page').length, "has the body class");
});
hasStream(); hasStream();
visit("/users/eviltrout/activity/topics"); visit("/users/eviltrout/activity/topics");
@ -33,6 +36,14 @@ test("Filters", () => {
hasStream(); hasStream();
}); });
test("Badges", () => {
visit("/users/eviltrout/badges");
andThen(() => {
ok($('body.user-badges-page').length, "has the body class");
ok(exists(".user-badges-list .badge-card"), "shows a badge");
});
});
test("Restricted Routes", () => { test("Restricted Routes", () => {
visit("/users/eviltrout/preferences"); visit("/users/eviltrout/preferences");

View File

@ -1,17 +1,32 @@
import { acceptance } from "helpers/qunit-helpers"; import { acceptance } from "helpers/qunit-helpers";
import { hasStream } from 'acceptance/user-anonymous-test';
acceptance("User", {loggedIn: true}); acceptance("User", {loggedIn: true});
test("Pending", () => { test("Invites", () => {
visit("/users/eviltrout/activity/pending"); visit("/users/eviltrout/invited/pending");
hasStream(); andThen(() => {
ok($('body.user-invites-page').length, "has the body class");
});
});
test("Messages", () => {
visit("/users/eviltrout/messages");
andThen(() => {
ok($('body.user-messages-page').length, "has the body class");
});
});
test("Notifications", () => {
visit("/users/eviltrout/notifications");
andThen(() => {
ok($('body.user-notifications-page').length, "has the body class");
});
}); });
test("Root URL - Viewing Self", () => { test("Root URL - Viewing Self", () => {
visit("/users/eviltrout"); visit("/users/eviltrout");
andThen(() => { andThen(() => {
ok($('body.user-summary-page').length, "has the body class");
equal(currentPath(), 'user.summary', "it defaults to summary"); equal(currentPath(), 'user.summary', "it defaults to summary");
}); });
}); });

View File

@ -4,6 +4,7 @@ acceptance("User Directory");
test("Visit Page", function() { test("Visit Page", function() {
visit("/users"); visit("/users");
andThen(() => { andThen(() => {
ok($('body.users-page').length, "has the body class");
ok(exists('.directory table tr'), "has a list of users"); ok(exists('.directory table tr'), "has a list of users");
}); });
}); });

View File

@ -56,6 +56,13 @@ export default function() {
return response(json); return response(json);
}); });
this.get('/tags', () => {
return response({ tags: [{
id: 'eviltrout',
count: 1
}] });
});
this.get('/users/eviltrout.json', () => { this.get('/users/eviltrout.json', () => {
const json = fixturesByUrl['/users/eviltrout.json']; const json = fixturesByUrl['/users/eviltrout.json'];
if (loggedIn()) { if (loggedIn()) {
@ -76,6 +83,20 @@ export default function() {
}); });
}); });
this.get('/users/eviltrout/invited_count.json', () => {
return response({
"counts": { "pending": 1, "redeemed": 0, "total": 0 }
});
});
this.get('/users/eviltrout/invited.json', () => {
return response({ "invites": [ {id: 1} ] });
});
this.get('/topics/private-messages/eviltrout.json', () => {
return response({ topic_list: { topics: [] } });
});
this.get('/clicks/track', success); this.get('/clicks/track', success);
this.get('/search', request => { this.get('/search', request => {