diff options
-rw-r--r-- | server/src/actions/comment_view.rs | 29 | ||||
-rw-r--r-- | server/src/actions/post_view.rs | 30 | ||||
-rw-r--r-- | server/src/lib.rs | 18 | ||||
-rw-r--r-- | server/src/websocket_server/server.rs | 163 | ||||
-rw-r--r-- | ui/src/components/navbar.tsx | 2 | ||||
-rw-r--r-- | ui/src/components/search.tsx | 259 | ||||
-rw-r--r-- | ui/src/index.tsx | 2 | ||||
-rw-r--r-- | ui/src/interfaces.ts | 21 | ||||
-rw-r--r-- | ui/src/services/WebSocketService.ts | 7 |
9 files changed, 513 insertions, 18 deletions
diff --git a/server/src/actions/comment_view.rs b/server/src/actions/comment_view.rs index 2e3ae058..85ddf587 100644 --- a/server/src/actions/comment_view.rs +++ b/server/src/actions/comment_view.rs @@ -3,7 +3,7 @@ use diesel::*; use diesel::result::Error; use diesel::dsl::*; use serde::{Deserialize, Serialize}; -use { SortType, limit_and_offset }; +use { SortType, limit_and_offset, fuzzy_search }; // The faked schema since diesel doesn't do views table! { @@ -60,6 +60,7 @@ impl CommentView { sort: &SortType, for_post_id: Option<i32>, for_creator_id: Option<i32>, + search_term: Option<String>, my_user_id: Option<i32>, saved_only: bool, page: Option<i64>, @@ -86,6 +87,10 @@ impl CommentView { if let Some(for_post_id) = for_post_id { query = query.filter(post_id.eq(for_post_id)); }; + + if let Some(search_term) = search_term { + query = query.filter(content.ilike(fuzzy_search(&search_term))); + }; if saved_only { query = query.filter(saved.eq(true)); @@ -353,8 +358,26 @@ mod tests { saved: None, }; - let read_comment_views_no_user = CommentView::list(&conn, &SortType::New, Some(inserted_post.id), None, None, false, None, None).unwrap(); - let read_comment_views_with_user = CommentView::list(&conn, &SortType::New, Some(inserted_post.id), None, Some(inserted_user.id), false, None, None).unwrap(); + let read_comment_views_no_user = CommentView::list( + &conn, + &SortType::New, + Some(inserted_post.id), + None, + None, + None, + false, + None, + None).unwrap(); + let read_comment_views_with_user = CommentView::list( + &conn, + &SortType::New, + Some(inserted_post.id), + None, + None, + Some(inserted_user.id), + false, + None, + None).unwrap(); let like_removed = CommentLike::remove(&conn, &comment_like_form).unwrap(); let num_deleted = Comment::delete(&conn, inserted_comment.id).unwrap(); Post::delete(&conn, inserted_post.id).unwrap(); diff --git a/server/src/actions/post_view.rs b/server/src/actions/post_view.rs index ccad9317..e24b0ed2 100644 --- a/server/src/actions/post_view.rs +++ b/server/src/actions/post_view.rs @@ -3,7 +3,7 @@ use diesel::*; use diesel::result::Error; use diesel::dsl::*; use serde::{Deserialize, Serialize}; -use { SortType, limit_and_offset }; +use { SortType, limit_and_offset, fuzzy_search }; #[derive(EnumString,ToString,Debug, Serialize, Deserialize)] pub enum PostListingType { @@ -74,6 +74,7 @@ impl PostView { sort: &SortType, for_community_id: Option<i32>, for_creator_id: Option<i32>, + search_term: Option<String>, my_user_id: Option<i32>, saved_only: bool, unread_only: bool, @@ -94,6 +95,10 @@ impl PostView { query = query.filter(creator_id.eq(for_creator_id)); }; + if let Some(search_term) = search_term { + query = query.filter(name.ilike(fuzzy_search(&search_term))); + }; + // TODO these are wrong, bc they'll only show saved for your logged in user, not theirs if saved_only { query = query.filter(saved.eq(true)); @@ -295,8 +300,27 @@ mod tests { }; - let read_post_listings_with_user = PostView::list(&conn, PostListingType::Community, &SortType::New, Some(inserted_community.id), None, Some(inserted_user.id), false, false, None, None).unwrap(); - let read_post_listings_no_user = PostView::list(&conn, PostListingType::Community, &SortType::New, Some(inserted_community.id), None, None, false, false, None, None).unwrap(); + let read_post_listings_with_user = PostView::list(&conn, + PostListingType::Community, + &SortType::New, Some(inserted_community.id), + None, + None, + Some(inserted_user.id), + false, + false, + None, + None).unwrap(); + let read_post_listings_no_user = PostView::list(&conn, + PostListingType::Community, + &SortType::New, + Some(inserted_community.id), + None, + None, + None, + false, + false, + None, + None).unwrap(); let read_post_listing_no_user = PostView::read(&conn, inserted_post.id, None).unwrap(); let read_post_listing_with_user = PostView::read(&conn, inserted_post.id, Some(inserted_user.id)).unwrap(); diff --git a/server/src/lib.rs b/server/src/lib.rs index 8347c23d..d8d7f152 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -97,6 +97,11 @@ pub enum SortType { Hot, New, TopDay, TopWeek, TopMonth, TopYear, TopAll } +#[derive(EnumString,ToString,Debug, Serialize, Deserialize)] +pub enum SearchType { + Both, Comments, Posts +} + pub fn to_datetime_utc(ndt: NaiveDateTime) -> DateTime<Utc> { DateTime::<Utc>::from_utc(ndt, Utc) } @@ -121,6 +126,11 @@ pub fn has_slurs(test: &str) -> bool { SLUR_REGEX.is_match(test) } +pub fn fuzzy_search(q: &str) -> String { + let replaced = q.replace(" ", "%"); + format!("%{}%", replaced) +} + pub fn limit_and_offset(page: Option<i64>, limit: Option<i64>) -> (i64, i64) { let page = page.unwrap_or(1); let limit = limit.unwrap_or(10); @@ -130,7 +140,7 @@ pub fn limit_and_offset(page: Option<i64>, limit: Option<i64>) -> (i64, i64) { #[cfg(test)] mod tests { - use {Settings, is_email_regex, remove_slurs, has_slurs}; + use {Settings, is_email_regex, remove_slurs, has_slurs, fuzzy_search}; #[test] fn test_api() { assert_eq!(Settings::get().api_endpoint(), "http://0.0.0.0/api/v1"); @@ -148,9 +158,15 @@ mod tests { assert!(has_slurs(&test)); assert!(!has_slurs(slur_free)); } + + #[test] fn test_fuzzy_search() { + let test = "This is a fuzzy search"; + assert_eq!(fuzzy_search(test), "%This%is%a%fuzzy%search%".to_string()); + } } + lazy_static! { static ref EMAIL_REGEX: Regex = Regex::new(r"^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$").unwrap(); static ref SLUR_REGEX: Regex = Regex::new(r"(fag(g|got|tard)?|maricos?|cock\s?sucker(s|ing)?|\bnig(\b|g?(a|er)?s?)\b|dindu(s?)|mudslime?s?|kikes?|mongoloids?|towel\s*heads?|\bspi(c|k)s?\b|\bchinks?|niglets?|beaners?|\bnips?\b|\bcoons?\b|jungle\s*bunn(y|ies?)|jigg?aboo?s?|\bpakis?\b|rag\s*heads?|gooks?|cunts?|bitch(es|ing|y)?|puss(y|ies?)|twats?|feminazis?|whor(es?|ing)|\bslut(s|t?y)?|\btrann?(y|ies?)|ladyboy(s?))").unwrap(); diff --git a/server/src/websocket_server/server.rs b/server/src/websocket_server/server.rs index c61756e1..d7b93416 100644 --- a/server/src/websocket_server/server.rs +++ b/server/src/websocket_server/server.rs @@ -12,7 +12,7 @@ use std::str::FromStr; use diesel::PgConnection; use failure::Error; -use {Crud, Joinable, Likeable, Followable, Bannable, Saveable, establish_connection, naive_now, naive_from_unix, SortType, has_slurs, remove_slurs}; +use {Crud, Joinable, Likeable, Followable, Bannable, Saveable, establish_connection, naive_now, naive_from_unix, SortType, SearchType, has_slurs, remove_slurs}; use actions::community::*; use actions::user::*; use actions::post::*; @@ -27,7 +27,7 @@ use actions::moderator::*; #[derive(EnumString,ToString,Debug)] pub enum UserOperation { - Login, Register, CreateCommunity, CreatePost, ListCommunities, ListCategories, GetPost, GetCommunity, CreateComment, EditComment, SaveComment, CreateCommentLike, GetPosts, CreatePostLike, EditPost, SavePost, EditCommunity, FollowCommunity, GetFollowedCommunities, GetUserDetails, GetReplies, GetModlog, BanFromCommunity, AddModToCommunity, CreateSite, EditSite, GetSite, AddAdmin, BanUser + Login, Register, CreateCommunity, CreatePost, ListCommunities, ListCategories, GetPost, GetCommunity, CreateComment, EditComment, SaveComment, CreateCommentLike, GetPosts, CreatePostLike, EditPost, SavePost, EditCommunity, FollowCommunity, GetFollowedCommunities, GetUserDetails, GetReplies, GetModlog, BanFromCommunity, AddModToCommunity, CreateSite, EditSite, GetSite, AddAdmin, BanUser, Search } #[derive(Fail, Debug)] @@ -458,6 +458,23 @@ pub struct GetRepliesResponse { replies: Vec<ReplyView>, } +#[derive(Serialize, Deserialize)] +pub struct Search { + q: String, + type_: String, + community_id: Option<i32>, + sort: String, + page: Option<i64>, + limit: Option<i64>, +} + +#[derive(Serialize, Deserialize)] +pub struct SearchResponse { + op: String, + comments: Vec<CommentView>, + posts: Vec<PostView>, +} + /// `ChatServer` manages chat rooms and responsible for coordinating chat /// session. implementation is super primitive pub struct ChatServer { @@ -500,6 +517,7 @@ impl ChatServer { Some(community_id), None, None, + None, false, false, None, @@ -703,6 +721,10 @@ fn parse_json_message(chat: &mut ChatServer, msg: StandardMessage) -> Result<Str let get_replies: GetReplies = serde_json::from_str(data)?; get_replies.perform(chat, msg.id) }, + UserOperation::Search => { + let search: Search = serde_json::from_str(data)?; + search.perform(chat, msg.id) + }, } } @@ -1106,7 +1128,7 @@ impl Perform for GetPost { chat.rooms.get_mut(&self.id).unwrap().insert(addr); - let comments = CommentView::list(&conn, &SortType::New, Some(self.id), None, user_id, false, None, Some(9999))?; + let comments = CommentView::list(&conn, &SortType::New, Some(self.id), None, None, user_id, false, None, Some(9999))?; let community = CommunityView::read(&conn, post_view.community_id, user_id)?; @@ -1537,7 +1559,17 @@ impl Perform for GetPosts { let type_ = PostListingType::from_str(&self.type_)?; let sort = SortType::from_str(&self.sort)?; - let posts = match PostView::list(&conn, type_, &sort, self.community_id, None, user_id, false, false, self.page, self.limit) { + let posts = match PostView::list(&conn, + type_, + &sort, + self.community_id, + None, + None, + user_id, + false, + false, + self.page, + self.limit) { Ok(posts) => posts, Err(_e) => { return Err(self.error("Couldn't get posts"))? @@ -2006,15 +2038,52 @@ impl Perform for GetUserDetails { let sort = SortType::from_str(&self.sort)?; let user_view = UserView::read(&conn, self.user_id)?; + // If its saved only, you don't care what creator it was let posts = if self.saved_only { - PostView::list(&conn, PostListingType::All, &sort, self.community_id, None, Some(self.user_id), self.saved_only, false, self.page, self.limit)? + PostView::list(&conn, + PostListingType::All, + &sort, + self.community_id, + None, + None, + Some(self.user_id), + self.saved_only, + false, + self.page, + self.limit)? } else { - PostView::list(&conn, PostListingType::All, &sort, self.community_id, Some(self.user_id), None, self.saved_only, false, self.page, self.limit)? + PostView::list(&conn, + PostListingType::All, + &sort, + self.community_id, + Some(self.user_id), + None, + None, + self.saved_only, + false, + self.page, + self.limit)? }; let comments = if self.saved_only { - CommentView::list(&conn, &sort, None, None, Some(self.user_id), self.saved_only, self.page, self.limit)? + CommentView::list(&conn, + &sort, + None, + None, + None, + Some(self.user_id), + self.saved_only, + self.page, + self.limit)? } else { - CommentView::list(&conn, &sort, None, Some(self.user_id), None, self.saved_only, self.page, self.limit)? + CommentView::list(&conn, + &sort, + None, + Some(self.user_id), + None, + None, + self.saved_only, + self.page, + self.limit)? }; let follows = CommunityFollowerView::for_user(&conn, self.user_id)?; @@ -2539,3 +2608,81 @@ impl Perform for BanUser { } } + +impl Perform for Search { + fn op_type(&self) -> UserOperation { + UserOperation::Search + } + + fn perform(&self, _chat: &mut ChatServer, _addr: usize) -> Result<String, Error> { + + let conn = establish_connection(); + + let sort = SortType::from_str(&self.sort)?; + let type_ = SearchType::from_str(&self.type_)?; + + let mut posts = Vec::new(); + let mut comments = Vec::new(); + + match type_ { + SearchType::Posts => { + posts = PostView::list(&conn, + PostListingType::All, + &sort, + self.community_id, + None, + Some(self.q.to_owned()), + None, + false, + false, + self.page, + self.limit)?; + }, + SearchType::Comments => { + comments = CommentView::list(&conn, + &sort, + None, + None, + Some(self.q.to_owned()), + None, + false, + self.page, + self.limit)?; + }, + SearchType::Both => { + posts = PostView::list(&conn, + PostListingType::All, + &sort, + self.community_id, + None, + Some(self.q.to_owned()), + None, + false, + false, + self.page, + self.limit)?; + comments = CommentView::list(&conn, + &sort, + None, + None, + Some(self.q.to_owned()), + None, + false, + self.page, + self.limit)?; + } + }; + + + // Return the jwt + Ok( + serde_json::to_string( + &SearchResponse { + op: self.op_type().to_string(), + comments: comments, + posts: posts, + } + )? + ) + } +} diff --git a/ui/src/components/navbar.tsx b/ui/src/components/navbar.tsx index 77ffa9af..fb8f5755 100644 --- a/ui/src/components/navbar.tsx +++ b/ui/src/components/navbar.tsx @@ -76,7 +76,7 @@ export class Navbar extends Component<any, NavbarState> { <Link class="nav-link" to="/communities">Forums</Link> </li> <li class="nav-item"> - <Link class="nav-link" to="/modlog">Modlog</Link> + <Link class="nav-link" to="/search">Search</Link> </li> <li class="nav-item"> <Link class="nav-link" to="/create_post">Create Post</Link> diff --git a/ui/src/components/search.tsx b/ui/src/components/search.tsx new file mode 100644 index 00000000..a4b389e7 --- /dev/null +++ b/ui/src/components/search.tsx @@ -0,0 +1,259 @@ +import { Component, linkEvent } from 'inferno'; +import { Subscription } from "rxjs"; +import { retryWhen, delay, take } from 'rxjs/operators'; +import { UserOperation, Post, Comment, SortType, SearchForm, SearchResponse, SearchType } from '../interfaces'; +import { WebSocketService } from '../services'; +import { msgOp, fetchLimit } from '../utils'; +import { PostListing } from './post-listing'; +import { CommentNodes } from './comment-nodes'; + +interface SearchState { + q: string, + type_: SearchType, + sort: SortType, + page: number, + searchResponse: SearchResponse; + loading: boolean; +} + +export class Search extends Component<any, SearchState> { + + private subscription: Subscription; + private emptyState: SearchState = { + q: undefined, + type_: SearchType.Both, + sort: SortType.TopAll, + page: 1, + searchResponse: { + op: null, + posts: [], + comments: [], + }, + loading: false, + } + + constructor(props: any, context: any) { + super(props, context); + + this.state = this.emptyState; + + this.subscription = WebSocketService.Instance.subject + .pipe(retryWhen(errors => errors.pipe(delay(3000), take(10)))) + .subscribe( + (msg) => this.parseMessage(msg), + (err) => console.error(err), + () => console.log('complete') + ); + + } + + componentWillUnmount() { + this.subscription.unsubscribe(); + } + + componentDidMount() { + document.title = "Search - Lemmy"; + } + + render() { + return ( + <div class="container"> + <div class="row"> + <div class="col-12"> + <h5>Search</h5> + {this.selects()} + {this.searchForm()} + {this.state.type_ == SearchType.Both && + this.both() + } + {this.state.type_ == SearchType.Comments && + this.comments() + } + {this.state.type_ == SearchType.Posts && + this.posts() + } + {this.noResults()} + {this.paginator()} + </div> + </div> + </div> + ) + } + + searchForm() { + return ( + <form class="form-inline" onSubmit={linkEvent(this, this.handleSearchSubmit)}> + <input type="text" class="form-control mr-2" value={this.state.q} placeholder="Search..." onInput={linkEvent(this, this.handleQChange)} required minLength={3} /> + <button type="submit" class="btn btn-secondary mr-2"> + {this.state.loading ? + <svg class="icon icon-spinner spin"><use xlinkHref="#icon-spinner"></use></svg> : + <span>Search</span> + } + </button> + </form> + ) + } + + selects() { + return ( + <div className="mb-2"> + <select value={this.state.type_} onChange={linkEvent(this, this.handleTypeChange)} class="custom-select w-auto"> + <option disabled>Type</option> + <option value={SearchType.Both}>Both</option> + <option value={SearchType.Comments}>Comments</option> + <option value={SearchType.Posts}>Posts</option> + </select> + <select value={this.state.sort} onChange={linkEvent(this, this.handleSortChange)} class="custom-select w-auto ml-2"> + <option disabled>Sort Type</option> + <option value={SortType.New}>New</option> + <option value={SortType.TopDay}>Top Day</option> + <option value={SortType.TopWeek}>Week</option> + <option value={SortType.TopMonth}>Month</option> + <option value={SortType.TopYear}>Year</option> + <option value={SortType.TopAll}>All</option> + </select> + </div> + ) + + } + + both() { + let combined: Array<{type_: string, data: Comment | Post}> = []; + let comments = this.state.searchResponse.comments.map(e => {return {type_: "comments", data: e}}); + let posts = this.state.searchResponse.posts.map(e => {return {type_: "posts", data: e}}); + + combined.push(...comments); + combined.push(...posts); + + // Sort it + if (this.state.sort == SortType.New) { + combined.sort((a, b) => b.data.published.localeCompare(a.data.published)); + } else { + combined.sort((a, b) => b.data.score - a.data.score); + } + + return ( + <div> + {combined.map(i => + <div> + {i.type_ == "posts" + ? <PostListing post={i.data as Post} showCommunity viewOnly /> + : <CommentNodes nodes={[{comment: i.data as Comment}]} viewOnly noIndent /> + } + </div> + ) + } + </div> + ) + } + + comments() { + return ( + <div> + {this.state.searchResponse.comments.map(comment => + <CommentNodes nodes={[{comment: comment}]} noIndent viewOnly /> + )} + </div> + ); + } + + posts() { + return ( + <div> + {this.state.searchResponse.posts.map(post => + <PostListing post={post} showCommunity viewOnly /> + )} + </div> + ); + } + + paginator() { + return ( + <div class="mt-2"> + {this.state.page > 1 && + <button class="btn btn-sm btn-secondary mr-1" onClick={linkEvent(this, this.prevPage)}>Prev</button> + } + <button class="btn btn-sm btn-secondary" onClick={linkEvent(this, this.nextPage)}>Next</button> + </div> + ); + } + + noResults() { + let res = this.state.searchResponse; + return ( + <div> + {res && res.op && res.posts.length == 0 && res.comments.length == 0 && + <span>No Results</span> + } + </div> + ) + } + + nextPage(i: Search) { + i.state.page++; + i.setState(i.state); + i.search(); + } + + prevPage(i: Search) { + i.state.page--; + i.setState(i.state); + i.search(); + } + + search() { + // TODO community + let form: SearchForm = { + q: this.state.q, + type_: SearchType[this.state.type_], + sort: SortType[this.state.sort], + page: this.state.page, + limit: fetchLimit, + }; + + WebSocketService.Instance.search(form); + } + + handleSortChange(i: Search, event: any) { + i.state.sort = Number(event.target.value); + i.state.page = 1; + i.setState(i.state); + i.search(); + } + + handleTypeChange(i: Search, event: any) { + i.state.type_ = Number(event.target.value); + i.state.page = 1; + i.setState(i.state); + i.search(); + } + + handleSearchSubmit(i: Search, event: any) { + event.preventDefault(); + i.state.loading = true; + i.search(); + i.setState(i.state); + } + + handleQChange(i: Search, event: any) { + i.state.q = event.target.value; + i.setState(i.state); + } + + parseMessage(msg: any) { + console.log(msg); + let op: UserOperation = msgOp(msg); + if (msg.error) { + alert(msg.error); + return; + } else if (op == UserOperation.Search) { + let res: SearchResponse = msg; + this.state.searchResponse = res; + this.state.loading = false; + document.title = `Search - ${this.state.q} - Lemmy`; + this.setState(this.state); + + } + } +} + diff --git a/ui/src/index.tsx b/ui/src/index.tsx index 716684de..b3b46904 100644 --- a/ui/src/index.tsx +++ b/ui/src/index.tsx @@ -14,6 +14,7 @@ import { User } from './components/user'; import { Modlog } from './components/modlog'; import { Setup } from './components/setup'; import { Inbox } from './components/inbox'; +import { Search } from './components/search'; import { Symbols } from './components/symbols'; import './css/bootstrap.min.css'; @@ -52,6 +53,7 @@ class Index extends Component<any, any> { <Route path={`/modlog/community/:community_id`} component={Modlog} /> <Route path={`/modlog`} component={Modlog} /> <Route path={`/setup`} component={Setup} /> + <Route path={`/search`} component={Search} /> </Switch> <Symbols /> </div> diff --git a/ui/src/interfaces.ts b/ui/src/interfaces.ts index ec111719..05987fe3 100644 --- a/ui/src/interfaces.ts +++ b/ui/src/interfaces.ts @@ -1,5 +1,5 @@ export enum UserOperation { - Login, Register, CreateCommunity, CreatePost, ListCommunities, ListCategories, GetPost, GetCommunity, CreateComment, EditComment, SaveComment, CreateCommentLike, GetPosts, CreatePostLike, EditPost, SavePost, EditCommunity, FollowCommunity, GetFollowedCommunities, GetUserDetails, GetReplies, GetModlog, BanFromCommunity, AddModToCommunity, CreateSite, EditSite, GetSite, AddAdmin, BanUser + Login, Register, CreateCommunity, CreatePost, ListCommunities, ListCategories, GetPost, GetCommunity, CreateComment, EditComment, SaveComment, CreateCommentLike, GetPosts, CreatePostLike, EditPost, SavePost, EditCommunity, FollowCommunity, GetFollowedCommunities, GetUserDetails, GetReplies, GetModlog, BanFromCommunity, AddModToCommunity, CreateSite, EditSite, GetSite, AddAdmin, BanUser, Search } export enum CommentSortType { @@ -14,6 +14,10 @@ export enum SortType { Hot, New, TopDay, TopWeek, TopMonth, TopYear, TopAll } +export enum SearchType { + Both, Comments, Posts +} + export interface User { id: number; iss: string; @@ -517,3 +521,18 @@ export interface AddAdminResponse { op: string; admins: Array<UserView>; } + +export interface SearchForm { + q: string; + type_: string; + community_id?: number; + sort: string; + page?: number; + limit?: number; +} + +export interface SearchResponse { + op: string; + posts?: Array<Post>; + comments?: Array<Comment>; +} diff --git a/ui/src/services/WebSocketService.ts b/ui/src/services/WebSocketService.ts index ac59631e..dc06df28 100644 --- a/ui/src/services/WebSocketService.ts +++ b/ui/src/services/WebSocketService.ts @@ -1,5 +1,5 @@ import { wsUri } from '../env'; -import { LoginForm, RegisterForm, UserOperation, CommunityForm, PostForm, SavePostForm, CommentForm, SaveCommentForm, CommentLikeForm, GetPostsForm, CreatePostLikeForm, FollowCommunityForm, GetUserDetailsForm, ListCommunitiesForm, GetModlogForm, BanFromCommunityForm, AddModToCommunityForm, AddAdminForm, BanUserForm, SiteForm, Site, UserView, GetRepliesForm } from '../interfaces'; +import { LoginForm, RegisterForm, UserOperation, CommunityForm, PostForm, SavePostForm, CommentForm, SaveCommentForm, CommentLikeForm, GetPostsForm, CreatePostLikeForm, FollowCommunityForm, GetUserDetailsForm, ListCommunitiesForm, GetModlogForm, BanFromCommunityForm, AddModToCommunityForm, AddAdminForm, BanUserForm, SiteForm, Site, UserView, GetRepliesForm, SearchForm } from '../interfaces'; import { webSocket } from 'rxjs/webSocket'; import { Subject } from 'rxjs'; import { retryWhen, delay, take } from 'rxjs/operators'; @@ -163,10 +163,15 @@ export class WebSocketService { this.setAuth(siteForm); this.subject.next(this.wsSendWrapper(UserOperation.EditSite, siteForm)); } + public getSite() { this.subject.next(this.wsSendWrapper(UserOperation.GetSite, {})); } + public search(form: SearchForm) { + this.subject.next(this.wsSendWrapper(UserOperation.Search, form)); + } + private wsSendWrapper(op: UserOperation, data: any) { let send = { op: UserOperation[op], data: data }; console.log(send); |