Allow comment/post upvoting from other pages.

- Fixes #355
- Votes now coming back for posts and comments on search page.
pull/722/head
Dessalines 2020-01-20 18:39:45 -05:00
parent 86871d17ac
commit a964b4ce21
6 changed files with 154 additions and 99 deletions

View File

@ -19,6 +19,7 @@ pub struct Search {
sort: String, sort: String,
page: Option<i64>, page: Option<i64>,
limit: Option<i64>, limit: Option<i64>,
auth: Option<String>,
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
@ -313,6 +314,17 @@ impl Perform<SearchResponse> for Oper<Search> {
fn perform(&self, conn: &PgConnection) -> Result<SearchResponse, Error> { fn perform(&self, conn: &PgConnection) -> Result<SearchResponse, Error> {
let data: &Search = &self.data; let data: &Search = &self.data;
let user_id: Option<i32> = match &data.auth {
Some(auth) => match Claims::decode(&auth) {
Ok(claims) => {
let user_id = claims.claims.id;
Some(user_id)
}
Err(_e) => None,
},
None => None,
};
let sort = SortType::from_str(&data.sort)?; let sort = SortType::from_str(&data.sort)?;
let type_ = SearchType::from_str(&data.type_)?; let type_ = SearchType::from_str(&data.type_)?;
@ -330,6 +342,7 @@ impl Perform<SearchResponse> for Oper<Search> {
.show_nsfw(true) .show_nsfw(true)
.for_community_id(data.community_id) .for_community_id(data.community_id)
.search_term(data.q.to_owned()) .search_term(data.q.to_owned())
.my_user_id(user_id)
.page(data.page) .page(data.page)
.limit(data.limit) .limit(data.limit)
.list()?; .list()?;
@ -338,6 +351,7 @@ impl Perform<SearchResponse> for Oper<Search> {
comments = CommentQueryBuilder::create(&conn) comments = CommentQueryBuilder::create(&conn)
.sort(&sort) .sort(&sort)
.search_term(data.q.to_owned()) .search_term(data.q.to_owned())
.my_user_id(user_id)
.page(data.page) .page(data.page)
.limit(data.limit) .limit(data.limit)
.list()?; .list()?;
@ -364,6 +378,7 @@ impl Perform<SearchResponse> for Oper<Search> {
.show_nsfw(true) .show_nsfw(true)
.for_community_id(data.community_id) .for_community_id(data.community_id)
.search_term(data.q.to_owned()) .search_term(data.q.to_owned())
.my_user_id(user_id)
.page(data.page) .page(data.page)
.limit(data.limit) .limit(data.limit)
.list()?; .list()?;
@ -371,6 +386,7 @@ impl Perform<SearchResponse> for Oper<Search> {
comments = CommentQueryBuilder::create(&conn) comments = CommentQueryBuilder::create(&conn)
.sort(&sort) .sort(&sort)
.search_term(data.q.to_owned()) .search_term(data.q.to_owned())
.my_user_id(user_id)
.page(data.page) .page(data.page)
.limit(data.limit) .limit(data.limit)
.list()?; .list()?;

View File

@ -52,7 +52,6 @@ interface PostListingProps {
post: Post; post: Post;
showCommunity?: boolean; showCommunity?: boolean;
showBody?: boolean; showBody?: boolean;
viewOnly?: boolean;
moderators?: Array<CommunityUser>; moderators?: Array<CommunityUser>;
admins?: Array<UserView>; admins?: Array<UserView>;
} }
@ -118,10 +117,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
let post = this.props.post; let post = this.props.post;
return ( return (
<div class="listing col-12"> <div class="listing col-12">
<div <div className={`vote-bar mr-2 float-left small text-center`}>
className={`vote-bar mr-2 float-left small text-center ${this.props
.viewOnly && 'no-click'}`}
>
<button <button
disabled={!UserService.Instance.user} disabled={!UserService.Instance.user}
className={`btn p-0 ${ className={`btn p-0 ${

View File

@ -12,6 +12,8 @@ import {
SearchForm, SearchForm,
SearchResponse, SearchResponse,
SearchType, SearchType,
CreatePostLikeResponse,
CommentResponse,
} from '../interfaces'; } from '../interfaces';
import { WebSocketService } from '../services'; import { WebSocketService } from '../services';
import { import {
@ -123,8 +125,6 @@ export class Search extends Component<any, SearchState> {
render() { render() {
return ( return (
<div class="container"> <div class="container">
<div class="row">
<div class="col-12">
<h5> <h5>
<T i18nKey="search">#</T> <T i18nKey="search">#</T>
</h5> </h5>
@ -138,8 +138,6 @@ export class Search extends Component<any, SearchState> {
{this.noResults()} {this.noResults()}
{this.paginator()} {this.paginator()}
</div> </div>
</div>
</div>
); );
} }
@ -252,9 +250,10 @@ export class Search extends Component<any, SearchState> {
return ( return (
<div> <div>
{combined.map(i => ( {combined.map(i => (
<div> <div class="row">
<div class="col-12">
{i.type_ == 'posts' && ( {i.type_ == 'posts' && (
<PostListing post={i.data as Post} showCommunity viewOnly /> <PostListing post={i.data as Post} showCommunity />
)} )}
{i.type_ == 'comments' && ( {i.type_ == 'comments' && (
<CommentNodes <CommentNodes
@ -301,6 +300,7 @@ export class Search extends Component<any, SearchState> {
</div> </div>
)} )}
</div> </div>
</div>
))} ))}
</div> </div>
); );
@ -308,45 +308,58 @@ export class Search extends Component<any, SearchState> {
comments() { comments() {
return ( return (
<div> <>
{this.state.searchResponse.comments.map(comment => ( {this.state.searchResponse.comments.map(comment => (
<div class="row">
<div class="col-12">
<CommentNodes nodes={[{ comment: comment }]} locked noIndent /> <CommentNodes nodes={[{ comment: comment }]} locked noIndent />
))}
</div> </div>
</div>
))}
</>
); );
} }
posts() { posts() {
return ( return (
<div> <>
{this.state.searchResponse.posts.map(post => ( {this.state.searchResponse.posts.map(post => (
<PostListing post={post} showCommunity viewOnly /> <div class="row">
))} <div class="col-12">
<PostListing post={post} showCommunity />
</div> </div>
</div>
))}
</>
); );
} }
// Todo possibly create UserListing and CommunityListing // Todo possibly create UserListing and CommunityListing
communities() { communities() {
return ( return (
<div> <>
{this.state.searchResponse.communities.map(community => ( {this.state.searchResponse.communities.map(community => (
<div> <div class="row">
<div class="col-12">
<span> <span>
<Link to={`/c/${community.name}`}>{`/c/${community.name}`}</Link> <Link
to={`/c/${community.name}`}
>{`/c/${community.name}`}</Link>
</span> </span>
<span>{` - ${community.title} - ${community.number_of_subscribers} subscribers`}</span> <span>{` - ${community.title} - ${community.number_of_subscribers} subscribers`}</span>
</div> </div>
))}
</div> </div>
))}
</>
); );
} }
users() { users() {
return ( return (
<div> <>
{this.state.searchResponse.users.map(user => ( {this.state.searchResponse.users.map(user => (
<div> <div class="row">
<div class="col-12">
<span> <span>
<Link <Link
className="text-info" className="text-info"
@ -355,8 +368,9 @@ export class Search extends Component<any, SearchState> {
</span> </span>
<span>{` - ${user.comment_score} comment karma`}</span> <span>{` - ${user.comment_score} comment karma`}</span>
</div> </div>
))}
</div> </div>
))}
</>
); );
} }
@ -477,6 +491,30 @@ export class Search extends Component<any, SearchState> {
}`; }`;
window.scrollTo(0, 0); window.scrollTo(0, 0);
this.setState(this.state); this.setState(this.state);
} else if (op == UserOperation.CreateCommentLike) {
let res: CommentResponse = msg;
let found: Comment = this.state.searchResponse.comments.find(
c => c.id === res.comment.id
);
found.score = res.comment.score;
found.upvotes = res.comment.upvotes;
found.downvotes = res.comment.downvotes;
if (res.comment.my_vote !== null) {
found.my_vote = res.comment.my_vote;
found.upvoteLoading = false;
found.downvoteLoading = false;
}
this.setState(this.state);
} else if (op == UserOperation.CreatePostLike) {
let res: CreatePostLikeResponse = msg;
let found = this.state.searchResponse.posts.find(
c => c.id == res.post.id
);
found.my_vote = res.post.my_vote;
found.score = res.post.score;
found.upvotes = res.post.upvotes;
found.downvotes = res.post.downvotes;
this.setState(this.state);
} }
} }
} }

View File

@ -18,6 +18,7 @@ import {
BanUserResponse, BanUserResponse,
AddAdminResponse, AddAdminResponse,
DeleteAccountForm, DeleteAccountForm,
CreatePostLikeResponse,
} from '../interfaces'; } from '../interfaces';
import { WebSocketService, UserService } from '../services'; import { WebSocketService, UserService } from '../services';
import { import {
@ -307,7 +308,6 @@ export class User extends Component<any, UserState> {
post={i.data as Post} post={i.data as Post}
admins={this.state.admins} admins={this.state.admins}
showCommunity showCommunity
viewOnly
/> />
) : ( ) : (
<CommentNodes <CommentNodes
@ -340,12 +340,7 @@ export class User extends Component<any, UserState> {
return ( return (
<div> <div>
{this.state.posts.map(post => ( {this.state.posts.map(post => (
<PostListing <PostListing post={post} admins={this.state.admins} showCommunity />
post={post}
admins={this.state.admins}
showCommunity
viewOnly
/>
))} ))}
</div> </div>
); );
@ -1043,6 +1038,14 @@ export class User extends Component<any, UserState> {
found.downvotes = res.comment.downvotes; found.downvotes = res.comment.downvotes;
if (res.comment.my_vote !== null) found.my_vote = res.comment.my_vote; if (res.comment.my_vote !== null) found.my_vote = res.comment.my_vote;
this.setState(this.state); this.setState(this.state);
} else if (op == UserOperation.CreatePostLike) {
let res: CreatePostLikeResponse = msg;
let found = this.state.posts.find(c => c.id == res.post.id);
found.my_vote = res.post.my_vote;
found.score = res.post.score;
found.upvotes = res.post.upvotes;
found.downvotes = res.post.downvotes;
this.setState(this.state);
} else if (op == UserOperation.BanUser) { } else if (op == UserOperation.BanUser) {
let res: BanUserResponse = msg; let res: BanUserResponse = msg;
this.state.comments this.state.comments

View File

@ -700,6 +700,7 @@ export interface SearchForm {
sort: string; sort: string;
page?: number; page?: number;
limit?: number; limit?: number;
auth?: string;
} }
export interface SearchResponse { export interface SearchResponse {

View File

@ -255,6 +255,7 @@ export class WebSocketService {
} }
public search(form: SearchForm) { public search(form: SearchForm) {
this.setAuth(form, false);
this.subject.next(this.wsSendWrapper(UserOperation.Search, form)); this.subject.next(this.wsSendWrapper(UserOperation.Search, form));
} }