Merge pull request #1596 from jsit/feat/toggle-body-1595

feat(UI): Always put post body behind toggle on post listings
This commit is contained in:
Jay Sitter 2023-06-27 09:13:20 -04:00 committed by GitHub
commit ef3924507b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 67 additions and 86 deletions

View file

@ -8,60 +8,54 @@ interface MetadataCardProps {
post: Post;
}
interface MetadataCardState {
expanded: boolean;
}
export class MetadataCard extends Component<
MetadataCardProps,
MetadataCardState
> {
export class MetadataCard extends Component<MetadataCardProps> {
constructor(props: any, context: any) {
super(props, context);
}
render() {
const post = this.props.post;
return (
<>
{post.embed_title && post.url && (
<div className="post-metadata-card card border-secondary mt-3 mb-2">
<div className="row">
<div className="col-12">
<div className="card-body">
{post.name !== post.embed_title && (
<>
<h5 className="card-title d-inline">
<a className="text-body" href={post.url} rel={relTags}>
{post.embed_title}
</a>
</h5>
<span className="d-inline-block ms-2 mb-2 small text-muted">
<a
className="text-muted fst-italic"
href={post.url}
rel={relTags}
>
{new URL(post.url).hostname}
<Icon icon="external-link" classes="ms-1" />
</a>
</span>
</>
)}
{post.embed_description && (
<div
className="card-text small text-muted md-div"
dangerouslySetInnerHTML={{
__html: sanitizeHtml(post.embed_description),
}}
/>
)}
</div>
if (post.embed_title && post.url) {
return (
<div className="post-metadata-card card border-secondary mt-3 mb-2">
<div className="row">
<div className="col-12">
<div className="card-body">
{post.name !== post.embed_title && (
<>
<h5 className="card-title d-inline">
<a className="text-body" href={post.url} rel={relTags}>
{post.embed_title}
</a>
</h5>
<span className="d-inline-block ms-2 mb-2 small text-muted">
<a
className="text-muted fst-italic"
href={post.url}
rel={relTags}
>
{new URL(post.url).hostname}
<Icon icon="external-link" classes="ms-1" />
</a>
</span>
</>
)}
{post.embed_description && (
<div
className="card-text small text-muted md-div"
dangerouslySetInnerHTML={{
__html: sanitizeHtml(post.embed_description),
}}
/>
)}
</div>
</div>
</div>
)}
</>
);
</div>
);
} else {
return <></>;
}
}
}

View file

@ -49,7 +49,7 @@ import {
PurgeType,
VoteContentType,
} from "../../interfaces";
import { mdNoImages, mdToHtml, mdToHtmlInline } from "../../markdown";
import { mdToHtml, mdToHtmlInline } from "../../markdown";
import { I18NextService, UserService } from "../../services";
import { setupTippy } from "../../tippy";
import { Icon, PurgeWarning, Spinner } from "../common/icon";
@ -105,6 +105,9 @@ interface PostListingProps {
allLanguages: Language[];
siteLanguages: number[];
showCommunity?: boolean;
/**
* Controls whether to show both the body *and* the metadata preview card
*/
showBody?: boolean;
hideImage?: boolean;
enableDownvotes?: boolean;
@ -200,7 +203,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
<>
{this.listing()}
{this.state.imageExpanded && !this.props.hideImage && this.img}
{post.url && this.state.showBody && post.embed_title && (
{this.showBody && post.url && post.embed_title && (
<MetadataCard post={post} />
)}
{this.showBody && this.body()}
@ -482,6 +485,15 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
)}
</h5>
{/**
* If there is a URL, an embed title, and we were not told to show the
* body by the parent component, show the MetadataCard/body toggle.
*/}
{!this.props.showBody &&
post.url &&
post.embed_title &&
this.showPreviewButton()}
{post.removed && (
<small className="ms-2 badge text-bg-secondary">
{I18NextService.i18n.t("removed")}
@ -624,27 +636,6 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
);
}
showPreviewButton() {
const post_view = this.postView;
const body = post_view.post.body;
return (
<button
className="btn btn-sm btn-animate text-muted py-0"
data-tippy-content={body && mdNoImages.render(body)}
data-tippy-allowHtml={true}
onClick={linkEvent(this, this.handleShowBody)}
>
<Icon
icon="book-open"
classes={classNames("icon-inline me-1", {
"text-success": this.state.showBody,
})}
/>
</button>
);
}
postActions() {
// Possible enhancement: Priority+ pattern instead of just hard coding which get hidden behind the show more button.
// Possible enhancement: Make each button a component.
@ -656,14 +647,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
{this.saveButton}
{this.crossPostButton}
{/**
* If there is a URL, or if the post has a body and we were told not to
* show the body, show the MetadataCard/body toggle.
*/}
{(post.url || (post.body && !this.props.showBody)) &&
this.showPreviewButton()}
{this.showBody && post_view.post.body && this.viewSourceButton}
{this.props.showBody && post_view.post.body && this.viewSourceButton}
<div className="dropdown">
<button
@ -1387,15 +1371,18 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
);
}
showBodyPreview() {
const { body, id } = this.postView.post;
return !this.showBody && body ? (
<Link className="text-body mt-2 d-block" to={`/post/${id}`}>
<div className="md-div mb-1 preview-lines">{body}</div>
</Link>
) : (
<></>
showPreviewButton() {
return (
<button
type="button"
className="btn btn-sm btn-link link-dark link-opacity-75 link-opacity-100-hover py-0 align-baseline"
onClick={linkEvent(this, this.handleShowBody)}
>
<Icon
icon={!this.state.showBody ? "plus-square" : "minus-square"}
classes="icon-inline"
/>
</button>
);
}