mirror of
https://github.com/discourse/discourse.git
synced 2024-11-23 03:09:00 +08:00
UX: Show group card with animated loading state (#15253)
* Remove _calculateTopOffset entirely * Show group card with animated loading state Showing the animated loading state before rending the actual content prevents an awkward scroll position jump when displaying this card. This mimics the behaviour of the user card (which uses the same `CardContentsBase` mixin). * Fix two user card issues 1. A JS console error (with no consequences) when clicking a group mention 2. User cards weren't being loaded from the header (for example, for PMs) Co-authored-by: Penar Musaraj <pmusaraj@gmail.com>
This commit is contained in:
parent
9fd92f329e
commit
a2fcc360dd
|
@ -41,11 +41,13 @@ export default Component.extend(CardContentsBase, CleansUp, {
|
|||
},
|
||||
|
||||
_showCallback(username, $target) {
|
||||
this.store
|
||||
this._positionCard($target);
|
||||
this.setProperties({ visible: true, loading: true });
|
||||
|
||||
return this.store
|
||||
.find("group", username)
|
||||
.then((group) => {
|
||||
this.setProperties({ group, visible: true });
|
||||
this._positionCard($target);
|
||||
this.setProperties({ group });
|
||||
if (!group.flair_url && !group.flair_bg_color) {
|
||||
group.set("flair_url", "fa-users");
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ import DiscourseURL from "discourse/lib/url";
|
|||
import Mixin from "@ember/object/mixin";
|
||||
import afterTransition from "discourse/lib/after-transition";
|
||||
import { escapeExpression } from "discourse/lib/utilities";
|
||||
import headerOutletHeights from "discourse/lib/header-outlet-height";
|
||||
import { inject as service } from "@ember/service";
|
||||
import { wantsNewWindow } from "discourse/lib/intercept-click";
|
||||
import { bind } from "discourse-common/utils/decorators";
|
||||
|
@ -63,7 +62,7 @@ export default Mixin.create({
|
|||
}
|
||||
|
||||
const closestArticle = target.closest("article");
|
||||
const postId = closestArticle ? closestArticle.dataset.postId : null;
|
||||
const postId = closestArticle?.dataset?.postId || null;
|
||||
const wasVisible = this.visible;
|
||||
const previousTarget = this.cardTarget;
|
||||
|
||||
|
@ -164,9 +163,9 @@ export default Mixin.create({
|
|||
return false;
|
||||
},
|
||||
|
||||
_topicHeaderTrigger(username, $target) {
|
||||
_topicHeaderTrigger(username, target) {
|
||||
this.setProperties({ isFixed: true, isDocked: true });
|
||||
return this._show(username, $target);
|
||||
return this._show(username, target);
|
||||
},
|
||||
|
||||
_bindMobileScroll() {
|
||||
|
@ -234,10 +233,9 @@ export default Mixin.create({
|
|||
}
|
||||
}
|
||||
|
||||
position.top -= this._calculateTopOffset(
|
||||
$("#main-outlet").offset(),
|
||||
headerOutletHeights()
|
||||
);
|
||||
// It looks better to have the card aligned slightly higher
|
||||
position.top -= 24;
|
||||
|
||||
if (isFixed) {
|
||||
position.top -= $("html").scrollTop();
|
||||
//if content is fixed and will be cut off on the bottom, display it above...
|
||||
|
@ -286,13 +284,6 @@ export default Mixin.create({
|
|||
});
|
||||
},
|
||||
|
||||
// some plugins/themes modify the page layout and may
|
||||
// need to override this calculation for the card to
|
||||
// position correctly
|
||||
_calculateTopOffset(mainOutletOffset, outletHeights) {
|
||||
return mainOutletOffset.top - outletHeights;
|
||||
},
|
||||
|
||||
@bind
|
||||
_hide() {
|
||||
if (!this.visible) {
|
||||
|
|
|
@ -1,69 +1,81 @@
|
|||
{{#if visible}}
|
||||
<div class="card-content">
|
||||
<div class="card-row first-row">
|
||||
<div class="group-card-avatar">
|
||||
<a href={{groupPath}} {{action "showGroup" group}} class="card-huge-avatar">
|
||||
{{avatar-flair
|
||||
flairName=group.name
|
||||
flairUrl=group.flair_url
|
||||
flairBgColor=group.flair_bg_color
|
||||
flairColor=group.flair_color
|
||||
}}
|
||||
</a>
|
||||
{{#if this.loading}}
|
||||
<div class="card-row first-row">
|
||||
<div class="group-card-avatar">
|
||||
<div class="card-avatar-placeholder animated-placeholder placeholder-animation"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="names">
|
||||
<span>
|
||||
<h1 class={{group.name}}>
|
||||
<a href={{groupPath}} {{action "showGroup" group}} class="group-page-link">{{group.name}}</a>
|
||||
</h1>
|
||||
{{#if group.full_name}}
|
||||
<h2 class="full-name">{{group.full_name}}</h2>
|
||||
{{else}}
|
||||
<h2 class="username">{{group.name}}</h2>
|
||||
{{/if}}
|
||||
</span>
|
||||
</div>
|
||||
<ul class="usercard-controls group-details-button">
|
||||
<li>
|
||||
{{group-membership-button
|
||||
model=group
|
||||
showLogin=(route-action "showLogin")
|
||||
}}
|
||||
</li>
|
||||
{{#if group.messageable}}
|
||||
<li>
|
||||
{{d-button
|
||||
action=(action "messageGroup")
|
||||
class="btn-primary group-message-button inline"
|
||||
icon="envelope"
|
||||
label="groups.message"
|
||||
}}
|
||||
</li>
|
||||
{{/if}}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{{#if this.group.bio_excerpt}}
|
||||
<div class="card-row second-row">
|
||||
<div class="bio">
|
||||
{{html-safe this.group.bio_excerpt}}
|
||||
</div>
|
||||
<div class="animated-placeholder placeholder-animation"></div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if group.members}}
|
||||
<div class="card-row third-row">
|
||||
<div class="members metadata">
|
||||
{{#each group.members as |user|}}
|
||||
<a {{action "close"}} href={{user.path}} class="card-tiny-avatar">{{bound-avatar user "tiny"}}</a>
|
||||
{{/each}}
|
||||
{{#if showMoreMembers}}
|
||||
<a href={{groupPath}} {{action "showGroup" group}} class="more-members-link">
|
||||
<span class="more-members-count">+{{moreMembersCount}} {{i18n "more"}}</span>
|
||||
</a>
|
||||
{{else}}
|
||||
<div class="card-row first-row">
|
||||
<div class="group-card-avatar">
|
||||
<a href={{groupPath}} {{action "showGroup" group}} class="card-huge-avatar">
|
||||
{{avatar-flair
|
||||
flairName=group.name
|
||||
flairUrl=group.flair_url
|
||||
flairBgColor=group.flair_bg_color
|
||||
flairColor=group.flair_color
|
||||
}}
|
||||
</a>
|
||||
</div>
|
||||
<div class="names">
|
||||
<span>
|
||||
<h1 class={{group.name}}>
|
||||
<a href={{groupPath}} {{action "showGroup" group}} class="group-page-link">{{group.name}}</a>
|
||||
</h1>
|
||||
{{#if group.full_name}}
|
||||
<h2 class="full-name">{{group.full_name}}</h2>
|
||||
{{else}}
|
||||
<h2 class="username">{{group.name}}</h2>
|
||||
{{/if}}
|
||||
</span>
|
||||
</div>
|
||||
<ul class="usercard-controls group-details-button">
|
||||
<li>
|
||||
{{group-membership-button
|
||||
model=group
|
||||
showLogin=(route-action "showLogin")
|
||||
}}
|
||||
</li>
|
||||
{{#if group.messageable}}
|
||||
<li>
|
||||
{{d-button
|
||||
action=(action "messageGroup")
|
||||
class="btn-primary group-message-button inline"
|
||||
icon="envelope"
|
||||
label="groups.message"
|
||||
}}
|
||||
</li>
|
||||
{{/if}}
|
||||
</div>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{{#if this.group.bio_excerpt}}
|
||||
<div class="card-row second-row">
|
||||
<div class="bio">
|
||||
{{html-safe this.group.bio_excerpt}}
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if group.members}}
|
||||
<div class="card-row third-row">
|
||||
<div class="members metadata">
|
||||
{{#each group.members as |user|}}
|
||||
<a {{action "close"}} href={{user.path}} class="card-tiny-avatar">{{bound-avatar user "tiny"}}</a>
|
||||
{{/each}}
|
||||
{{#if showMoreMembers}}
|
||||
<a href={{groupPath}} {{action "showGroup" group}} class="more-members-link">
|
||||
<span class="more-members-count">+{{moreMembersCount}} {{i18n "more"}}</span>
|
||||
</a>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
|
|
@ -46,11 +46,10 @@ createWidget("topic-header-participant", {
|
|||
},
|
||||
|
||||
click(e) {
|
||||
const $target = $(e.target);
|
||||
this.appEvents.trigger(
|
||||
`topic-header:trigger-${this.attrs.type}-card`,
|
||||
this.attrs.username,
|
||||
$target
|
||||
e.target
|
||||
);
|
||||
e.preventDefault();
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue
Block a user