Fixing saved / starred. Fixes #42

This commit is contained in:
Dessalines 2020-09-26 11:18:49 -05:00
parent 5c740cdff0
commit be939c90a9
2 changed files with 325 additions and 297 deletions

View file

@ -54,6 +54,7 @@ interface PostListingState {
imageExpanded: boolean; imageExpanded: boolean;
viewSource: boolean; viewSource: boolean;
showAdvanced: boolean; showAdvanced: boolean;
showMoreMobile: boolean;
my_vote: number; my_vote: number;
score: number; score: number;
upvotes: number; upvotes: number;
@ -85,6 +86,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
imageExpanded: false, imageExpanded: false,
viewSource: false, viewSource: false,
showAdvanced: false, showAdvanced: false,
showMoreMobile: false,
my_vote: this.props.post.my_vote, my_vote: this.props.post.my_vote,
score: this.props.post.score, score: this.props.post.score,
upvotes: this.props.post.upvotes, upvotes: this.props.post.upvotes,
@ -493,7 +495,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
commentsLine(mobile: boolean = false) { commentsLine(mobile: boolean = false) {
let post = this.props.post; let post = this.props.post;
return ( return (
<div class="d-flex justify-content-between justify-content-lg-start flex-wrap text-muted font-weight-bold"> <div class="d-flex justify-content-between justify-content-lg-start flex-wrap text-muted font-weight-bold mb-1">
<button class="btn btn-link text-muted p-0"> <button class="btn btn-link text-muted p-0">
<Link <Link
className="text-muted small" className="text-muted small"
@ -510,18 +512,39 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
})} })}
</Link> </Link>
</button> </button>
{!mobile && this.state.downvotes !== 0 && ( {!mobile && (
<button <>
class="btn text-muted py-0" {this.state.downvotes !== 0 && (
data-tippy-content={this.pointsTippy} <button
> class="btn text-muted py-0 pr-0"
<small> data-tippy-content={this.pointsTippy}
<svg class="icon icon-inline mr-1"> >
<use xlinkHref="#icon-arrow-down1"></use> <small>
</svg> <svg class="icon icon-inline mr-1">
<span>{this.state.downvotes}</span> <use xlinkHref="#icon-arrow-down1"></use>
</small> </svg>
</button> <span>{this.state.downvotes}</span>
</small>
</button>
)}
{!this.props.showBody && (
<button
class="btn btn-link btn-animate text-muted py-0"
onClick={linkEvent(this, this.handleSavePostClick)}
data-tippy-content={
post.saved ? i18n.t('unsave') : i18n.t('save')
}
>
<small>
<svg
class={`icon icon-inline ${post.saved && 'text-warning'}`}
>
<use xlinkHref="#icon-star"></use>
</svg>
</small>
</button>
)}
</>
)} )}
{/* This is an expanding spacer for mobile */} {/* This is an expanding spacer for mobile */}
<div className="flex-grow-1"></div> <div className="flex-grow-1"></div>
@ -541,7 +564,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
{this.state.upvotes} {this.state.upvotes}
</button> </button>
<button <button
className={`ml-2 btn-animate btn py-0 px-1 ${ className={`ml-2 btn-animate btn py-0 pl-1 ${
this.state.my_vote == -1 ? 'text-danger' : 'text-muted' this.state.my_vote == -1 ? 'text-danger' : 'text-muted'
}`} }`}
onClick={linkEvent(this, this.handlePostDisLike)} onClick={linkEvent(this, this.handlePostDisLike)}
@ -556,7 +579,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
</button> </button>
</div> </div>
<button <button
class="btn btn-link btn-animate text-muted py-0 pl-1 pr-0" class="btn btn-link btn-animate text-muted py-0 pl-1"
onClick={linkEvent(this, this.handleSavePostClick)} onClick={linkEvent(this, this.handleSavePostClick)}
data-tippy-content={ data-tippy-content={
post.saved ? i18n.t('unsave') : i18n.t('save') post.saved ? i18n.t('unsave') : i18n.t('save')
@ -566,6 +589,19 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
<use xlinkHref="#icon-star"></use> <use xlinkHref="#icon-star"></use>
</svg> </svg>
</button> </button>
{!this.state.showMoreMobile && this.props.showBody && (
<button
class="btn btn-link btn-animate text-muted py-0 p-0"
onClick={linkEvent(this, this.handleShowMoreMobile)}
data-tippy-content={i18n.t('more')}
>
<svg class="icon icon-inline">
<use xlinkHref="#icon-more-vertical"></use>
</svg>
</button>
)}
{this.state.showMoreMobile && this.postActions(mobile)}
</> </>
)} )}
</div> </div>
@ -591,313 +627,284 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
); );
} }
postActions() { postActions(mobile: boolean = false) {
let post = this.props.post; let post = this.props.post;
return ( return (
<ul class="list-inline mb-1 text-muted font-weight-bold"> UserService.Instance.user && (
{UserService.Instance.user && ( <>
<> {this.props.showBody && (
{this.props.showBody && ( <>
<> {!mobile && (
<li className="list-inline-item"> <button
<Link class="btn btn-link btn-animate text-muted py-0 pl-0"
className="btn btn-link btn-animate text-muted" onClick={linkEvent(this, this.handleSavePostClick)}
to={`/create_post${this.crossPostParams}`} data-tippy-content={
title={i18n.t('cross_post')} post.saved ? i18n.t('unsave') : i18n.t('save')
}
>
<svg
class={`icon icon-inline ${post.saved && 'text-warning'}`}
> >
<svg class="icon icon-inline"> <use xlinkHref="#icon-star"></use>
<use xlinkHref="#icon-copy"></use> </svg>
</svg> </button>
</Link> )}
</li> <Link
</> className="btn btn-link btn-animate text-muted py-0"
)} to={`/create_post${this.crossPostParams}`}
{this.myPost && this.props.showBody && ( title={i18n.t('cross_post')}
<> >
<li className="list-inline-item"> <svg class="icon icon-inline">
<use xlinkHref="#icon-copy"></use>
</svg>
</Link>
</>
)}
{this.myPost && this.props.showBody && (
<>
<button
class="btn btn-link btn-animate text-muted py-0"
onClick={linkEvent(this, this.handleEditClick)}
data-tippy-content={i18n.t('edit')}
>
<svg class="icon icon-inline">
<use xlinkHref="#icon-edit"></use>
</svg>
</button>
<button
class="btn btn-link btn-animate text-muted py-0"
onClick={linkEvent(this, this.handleDeleteClick)}
data-tippy-content={
!post.deleted ? i18n.t('delete') : i18n.t('restore')
}
>
<svg
class={`icon icon-inline ${post.deleted && 'text-danger'}`}
>
<use xlinkHref="#icon-trash"></use>
</svg>
</button>
</>
)}
{!this.state.showAdvanced && this.props.showBody ? (
<button
class="btn btn-link btn-animate text-muted py-0"
onClick={linkEvent(this, this.handleShowAdvanced)}
data-tippy-content={i18n.t('more')}
>
<svg class="icon icon-inline">
<use xlinkHref="#icon-more-vertical"></use>
</svg>
</button>
) : (
<>
{this.props.showBody && post.body && (
<button
class="btn btn-link btn-animate text-muted py-0"
onClick={linkEvent(this, this.handleViewSource)}
data-tippy-content={i18n.t('view_source')}
>
<svg
class={`icon icon-inline ${
this.state.viewSource && 'text-success'
}`}
>
<use xlinkHref="#icon-file-text"></use>
</svg>
</button>
)}
{this.canModOnSelf && (
<>
<button <button
class="btn btn-link btn-animate text-muted" class="btn btn-link btn-animate text-muted py-0"
onClick={linkEvent(this, this.handleEditClick)} onClick={linkEvent(this, this.handleModLock)}
data-tippy-content={i18n.t('edit')} data-tippy-content={
post.locked ? i18n.t('unlock') : i18n.t('lock')
}
> >
<svg class="icon icon-inline"> <svg
<use xlinkHref="#icon-edit"></use> class={`icon icon-inline ${post.locked && 'text-danger'}`}
>
<use xlinkHref="#icon-lock"></use>
</svg> </svg>
</button> </button>
</li>
<li className="list-inline-item">
<button <button
class="btn btn-link btn-animate text-muted" class="btn btn-link btn-animate text-muted py-0"
onClick={linkEvent(this, this.handleDeleteClick)} onClick={linkEvent(this, this.handleModSticky)}
data-tippy-content={ data-tippy-content={
!post.deleted ? i18n.t('delete') : i18n.t('restore') post.stickied ? i18n.t('unsticky') : i18n.t('sticky')
} }
> >
<svg <svg
class={`icon icon-inline ${ class={`icon icon-inline ${
post.deleted && 'text-danger' post.stickied && 'text-success'
}`} }`}
> >
<use xlinkHref="#icon-trash"></use> <use xlinkHref="#icon-pin"></use>
</svg> </svg>
</button> </button>
</li> </>
</> )}
)} {/* Mods can ban from community, and appoint as mods to community */}
{(this.canMod || this.canAdmin) &&
{!this.state.showAdvanced && this.props.showBody ? ( (!post.removed ? (
<li className="list-inline-item"> <span
<button class="pointer"
class="btn btn-link btn-animate text-muted" onClick={linkEvent(this, this.handleModRemoveShow)}
onClick={linkEvent(this, this.handleShowAdvanced)} >
data-tippy-content={i18n.t('more')} {i18n.t('remove')}
> </span>
<svg class="icon icon-inline"> ) : (
<use xlinkHref="#icon-more-vertical"></use> <span
</svg> class="pointer"
</button> onClick={linkEvent(this, this.handleModRemoveSubmit)}
</li> >
) : ( {i18n.t('restore')}
<> </span>
{this.props.showBody && post.body && ( ))}
<li className="list-inline-item"> {this.canMod && (
<button <>
class="btn btn-link btn-animate text-muted" {!this.isMod &&
onClick={linkEvent(this, this.handleViewSource)} (!post.banned_from_community ? (
data-tippy-content={i18n.t('view_source')}
>
<svg
class={`icon icon-inline ${
this.state.viewSource && 'text-success'
}`}
>
<use xlinkHref="#icon-file-text"></use>
</svg>
</button>
</li>
)}
{this.canModOnSelf && (
<>
<li className="list-inline-item">
<button
class="btn btn-link btn-animate text-muted"
onClick={linkEvent(this, this.handleModLock)}
data-tippy-content={
post.locked ? i18n.t('unlock') : i18n.t('lock')
}
>
<svg
class={`icon icon-inline ${
post.locked && 'text-danger'
}`}
>
<use xlinkHref="#icon-lock"></use>
</svg>
</button>
</li>
<li className="list-inline-item">
<button
class="btn btn-link btn-animate text-muted"
onClick={linkEvent(this, this.handleModSticky)}
data-tippy-content={
post.stickied ? i18n.t('unsticky') : i18n.t('sticky')
}
>
<svg
class={`icon icon-inline ${
post.stickied && 'text-success'
}`}
>
<use xlinkHref="#icon-pin"></use>
</svg>
</button>
</li>
</>
)}
{/* Mods can ban from community, and appoint as mods to community */}
{(this.canMod || this.canAdmin) && (
<li className="list-inline-item">
{!post.removed ? (
<span
class="pointer"
onClick={linkEvent(this, this.handleModRemoveShow)}
>
{i18n.t('remove')}
</span>
) : (
<span
class="pointer"
onClick={linkEvent(this, this.handleModRemoveSubmit)}
>
{i18n.t('restore')}
</span>
)}
</li>
)}
{this.canMod && (
<>
{!this.isMod && (
<li className="list-inline-item">
{!post.banned_from_community ? (
<span
class="pointer"
onClick={linkEvent(
this,
this.handleModBanFromCommunityShow
)}
>
{i18n.t('ban')}
</span>
) : (
<span
class="pointer"
onClick={linkEvent(
this,
this.handleModBanFromCommunitySubmit
)}
>
{i18n.t('unban')}
</span>
)}
</li>
)}
{!post.banned_from_community && post.creator_local && (
<li className="list-inline-item">
<span
class="pointer"
onClick={linkEvent(
this,
this.handleAddModToCommunity
)}
>
{this.isMod
? i18n.t('remove_as_mod')
: i18n.t('appoint_as_mod')}
</span>
</li>
)}
</>
)}
{/* Community creators and admins can transfer community to another mod */}
{(this.amCommunityCreator || this.canAdmin) &&
this.isMod &&
post.creator_local && (
<li className="list-inline-item">
{!this.state.showConfirmTransferCommunity ? (
<span
class="pointer"
onClick={linkEvent(
this,
this.handleShowConfirmTransferCommunity
)}
>
{i18n.t('transfer_community')}
</span>
) : (
<>
<span class="d-inline-block mr-1">
{i18n.t('are_you_sure')}
</span>
<span
class="pointer d-inline-block mr-1"
onClick={linkEvent(
this,
this.handleTransferCommunity
)}
>
{i18n.t('yes')}
</span>
<span
class="pointer d-inline-block"
onClick={linkEvent(
this,
this.handleCancelShowConfirmTransferCommunity
)}
>
{i18n.t('no')}
</span>
</>
)}
</li>
)}
{/* Admins can ban from all, and appoint other admins */}
{this.canAdmin && (
<>
{!this.isAdmin && (
<li className="list-inline-item">
{!post.banned ? (
<span
class="pointer"
onClick={linkEvent(this, this.handleModBanShow)}
>
{i18n.t('ban_from_site')}
</span>
) : (
<span
class="pointer"
onClick={linkEvent(this, this.handleModBanSubmit)}
>
{i18n.t('unban_from_site')}
</span>
)}
</li>
)}
{!post.banned && post.creator_local && (
<li className="list-inline-item">
<span
class="pointer"
onClick={linkEvent(this, this.handleAddAdmin)}
>
{this.isAdmin
? i18n.t('remove_as_admin')
: i18n.t('appoint_as_admin')}
</span>
</li>
)}
</>
)}
{/* Site Creator can transfer to another admin */}
{this.amSiteCreator && this.isAdmin && (
<li className="list-inline-item">
{!this.state.showConfirmTransferSite ? (
<span <span
class="pointer" class="pointer"
onClick={linkEvent( onClick={linkEvent(
this, this,
this.handleShowConfirmTransferSite this.handleModBanFromCommunityShow
)} )}
> >
{i18n.t('transfer_site')} {i18n.t('ban')}
</span> </span>
) : ( ) : (
<> <span
<span class="d-inline-block mr-1"> class="pointer"
{i18n.t('are_you_sure')} onClick={linkEvent(
</span> this,
<span this.handleModBanFromCommunitySubmit
class="pointer d-inline-block mr-1" )}
onClick={linkEvent(this, this.handleTransferSite)} >
> {i18n.t('unban')}
{i18n.t('yes')} </span>
</span> ))}
<span {!post.banned_from_community && post.creator_local && (
class="pointer d-inline-block" <span
onClick={linkEvent( class="pointer"
this, onClick={linkEvent(this, this.handleAddModToCommunity)}
this.handleCancelShowConfirmTransferSite >
)} {this.isMod
> ? i18n.t('remove_as_mod')
{i18n.t('no')} : i18n.t('appoint_as_mod')}
</span> </span>
</> )}
</>
)}
{/* Community creators and admins can transfer community to another mod */}
{(this.amCommunityCreator || this.canAdmin) &&
this.isMod &&
post.creator_local &&
(!this.state.showConfirmTransferCommunity ? (
<span
class="pointer"
onClick={linkEvent(
this,
this.handleShowConfirmTransferCommunity
)} )}
</li> >
)} {i18n.t('transfer_community')}
</> </span>
)} ) : (
</> <>
)} <span class="d-inline-block mr-1">
</ul> {i18n.t('are_you_sure')}
</span>
<span
class="pointer d-inline-block mr-1"
onClick={linkEvent(this, this.handleTransferCommunity)}
>
{i18n.t('yes')}
</span>
<span
class="pointer d-inline-block"
onClick={linkEvent(
this,
this.handleCancelShowConfirmTransferCommunity
)}
>
{i18n.t('no')}
</span>
</>
))}
{/* Admins can ban from all, and appoint other admins */}
{this.canAdmin && (
<>
{!this.isAdmin &&
(!post.banned ? (
<span
class="pointer"
onClick={linkEvent(this, this.handleModBanShow)}
>
{i18n.t('ban_from_site')}
</span>
) : (
<span
class="pointer"
onClick={linkEvent(this, this.handleModBanSubmit)}
>
{i18n.t('unban_from_site')}
</span>
))}
{!post.banned && post.creator_local && (
<span
class="pointer"
onClick={linkEvent(this, this.handleAddAdmin)}
>
{this.isAdmin
? i18n.t('remove_as_admin')
: i18n.t('appoint_as_admin')}
</span>
)}
</>
)}
{/* Site Creator can transfer to another admin */}
{this.amSiteCreator &&
this.isAdmin &&
(!this.state.showConfirmTransferSite ? (
<span
class="pointer"
onClick={linkEvent(
this,
this.handleShowConfirmTransferSite
)}
>
{i18n.t('transfer_site')}
</span>
) : (
<>
<span class="d-inline-block mr-1">
{i18n.t('are_you_sure')}
</span>
<span
class="pointer d-inline-block mr-1"
onClick={linkEvent(this, this.handleTransferSite)}
>
{i18n.t('yes')}
</span>
<span
class="pointer d-inline-block"
onClick={linkEvent(
this,
this.handleCancelShowConfirmTransferSite
)}
>
{i18n.t('no')}
</span>
</>
))}
</>
)}
</>
)
); );
} }
@ -1014,7 +1021,6 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
{this.commentsLine(true)} {this.commentsLine(true)}
{this.duplicatesLine()} {this.duplicatesLine()}
{this.postActions()}
{this.removeAndBanDialogs()} {this.removeAndBanDialogs()}
</div> </div>
</div> </div>
@ -1443,6 +1449,13 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
setupTippy(); setupTippy();
} }
handleShowMoreMobile(i: PostListing) {
i.state.showMoreMobile = !i.state.showMoreMobile;
i.state.showAdvanced = !i.state.showAdvanced;
i.setState(i.state);
setupTippy();
}
get pointsTippy(): string { get pointsTippy(): string {
let points = i18n.t('number_of_points', { let points = i18n.t('number_of_points', {
count: this.state.score, count: this.state.score,

View file

@ -43,6 +43,7 @@ import {
setAuth, setAuth,
lemmyHttp, lemmyHttp,
previewLines, previewLines,
editPostFindRes,
} from '../utils'; } from '../utils';
import { UserListing } from './user-listing'; import { UserListing } from './user-listing';
import { HtmlTags } from './html-tags'; import { HtmlTags } from './html-tags';
@ -884,6 +885,9 @@ export class User extends Component<any, UserState> {
this.props.history.push( this.props.history.push(
`/u/${this.state.userName}/view/${viewStr}/sort/${sortStr}/page/${page}` `/u/${this.state.userName}/view/${viewStr}/sort/${sortStr}/page/${page}`
); );
this.state.loading = true;
this.setState(this.state);
this.fetchUserData();
} }
handlePageChange(page: number) { handlePageChange(page: number) {
@ -1141,6 +1145,17 @@ export class User extends Component<any, UserState> {
const data = res.data as CommentResponse; const data = res.data as CommentResponse;
saveCommentRes(data, this.state.userRes.comments); saveCommentRes(data, this.state.userRes.comments);
this.setState(this.state); this.setState(this.state);
} else if (
res.op == UserOperation.EditPost ||
res.op == UserOperation.DeletePost ||
res.op == UserOperation.RemovePost ||
res.op == UserOperation.LockPost ||
res.op == UserOperation.StickyPost ||
res.op == UserOperation.SavePost
) {
let data = res.data as PostResponse;
editPostFindRes(data, this.state.userRes.posts);
this.setState(this.state);
} else if (res.op == UserOperation.CreatePostLike) { } else if (res.op == UserOperation.CreatePostLike) {
const data = res.data as PostResponse; const data = res.data as PostResponse;
createPostLikeFindRes(data, this.state.userRes.posts); createPostLikeFindRes(data, this.state.userRes.posts);