diff options
author | Dessalines <happydooby@gmail.com> | 2019-04-29 10:18:38 -0700 |
---|---|---|
committer | Dessalines <happydooby@gmail.com> | 2019-04-29 10:18:38 -0700 |
commit | e074fcd2e7ca7355a9b631a705b41fe1605ea8bd (patch) | |
tree | 05418c9c8d3320985b8d1ec2008f608f73ddc286 | |
parent | 2d86dad1a6adb398af2a6930729952438a851f4c (diff) | |
parent | 6ba2dde9f4327706ee6785c2f7968c9d62922e20 (diff) |
Merge branch 'dev'
-rw-r--r-- | server/src/websocket_server/server.rs | 64 | ||||
-rw-r--r-- | ui/package.json | 2 | ||||
-rw-r--r-- | ui/src/components/create-post.tsx | 12 | ||||
-rw-r--r-- | ui/src/components/inbox.tsx | 17 | ||||
-rw-r--r-- | ui/src/components/navbar.tsx | 6 | ||||
-rw-r--r-- | ui/src/components/post-form.tsx | 4 | ||||
-rw-r--r-- | ui/src/interfaces.ts | 2 | ||||
-rw-r--r-- | ui/src/services/WebSocketService.ts | 6 | ||||
-rw-r--r-- | ui/src/utils.ts | 18 | ||||
-rw-r--r-- | ui/yarn.lock | 14 |
10 files changed, 138 insertions, 7 deletions
diff --git a/server/src/websocket_server/server.rs b/server/src/websocket_server/server.rs index 9c609a47..3e361f69 100644 --- a/server/src/websocket_server/server.rs +++ b/server/src/websocket_server/server.rs @@ -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, Search + 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, MarkAllAsRead } #[derive(Fail, Debug)] @@ -478,6 +478,11 @@ pub struct SearchResponse { posts: Vec<PostView>, } +#[derive(Serialize, Deserialize)] +pub struct MarkAllAsRead { + auth: String +} + /// `ChatServer` manages chat rooms and responsible for coordinating chat /// session. implementation is super primitive pub struct ChatServer { @@ -728,6 +733,10 @@ fn parse_json_message(chat: &mut ChatServer, msg: StandardMessage) -> Result<Str let search: Search = serde_json::from_str(data)?; search.perform(chat, msg.id) }, + UserOperation::MarkAllAsRead => { + let mark_all_as_read: MarkAllAsRead = serde_json::from_str(data)?; + mark_all_as_read.perform(chat, msg.id) + }, } } @@ -2709,3 +2718,56 @@ impl Perform for Search { ) } } + + +impl Perform for MarkAllAsRead { + fn op_type(&self) -> UserOperation { + UserOperation::MarkAllAsRead + } + + fn perform(&self, _chat: &mut ChatServer, _addr: usize) -> Result<String, Error> { + + let conn = establish_connection(); + + let claims = match Claims::decode(&self.auth) { + Ok(claims) => claims.claims, + Err(_e) => { + return Err(self.error("Not logged in."))? + } + }; + + let user_id = claims.id; + + let replies = ReplyView::get_replies(&conn, user_id, &SortType::New, true, Some(1), Some(999))?; + + for reply in &replies { + let comment_form = CommentForm { + content: reply.to_owned().content, + parent_id: reply.to_owned().parent_id, + post_id: reply.to_owned().post_id, + creator_id: reply.to_owned().creator_id, + removed: None, + read: Some(true), + updated: reply.to_owned().updated + }; + + let _updated_comment = match Comment::update(&conn, reply.id, &comment_form) { + Ok(comment) => comment, + Err(_e) => { + return Err(self.error("Couldn't update Comment"))? + } + }; + } + + let replies = ReplyView::get_replies(&conn, user_id, &SortType::New, true, Some(1), Some(999))?; + + Ok( + serde_json::to_string( + &GetRepliesResponse { + op: self.op_type().to_string(), + replies: replies, + } + )? + ) + } +} diff --git a/ui/package.json b/ui/package.json index b5bb14ef..d806575c 100644 --- a/ui/package.json +++ b/ui/package.json @@ -19,6 +19,7 @@ "@types/js-cookie": "^2.2.1", "@types/jwt-decode": "^2.2.1", "@types/markdown-it": "^0.0.7", + "@types/markdown-it-container": "^2.0.2", "autosize": "^4.0.2", "classcat": "^1.1.3", "dotenv": "^6.1.0", @@ -27,6 +28,7 @@ "js-cookie": "^2.2.0", "jwt-decode": "^2.2.0", "markdown-it": "^8.4.2", + "markdown-it-container": "^2.0.0", "moment": "^2.24.0", "rxjs": "^6.4.0" }, diff --git a/ui/src/components/create-post.tsx b/ui/src/components/create-post.tsx index e2998ca7..1958be72 100644 --- a/ui/src/components/create-post.tsx +++ b/ui/src/components/create-post.tsx @@ -18,13 +18,23 @@ export class CreatePost extends Component<any, any> { <div class="row"> <div class="col-12 col-lg-6 mb-4"> <h5>Create a Post</h5> - <PostForm onCreate={this.handlePostCreate}/> + <PostForm onCreate={this.handlePostCreate} prevCommunityName={this.prevCommunityName} /> </div> </div> </div> ) } + get prevCommunityName(): string { + if (this.props.location.state) { + let lastLocation = this.props.location.state.prevPath; + if (lastLocation.includes("/c/")) { + return lastLocation.split("/c/")[1]; + } + } + return undefined; + } + handlePostCreate(id: number) { this.props.history.push(`/post/${id}`); } diff --git a/ui/src/components/inbox.tsx b/ui/src/components/inbox.tsx index 02d813f3..f4ef2ecd 100644 --- a/ui/src/components/inbox.tsx +++ b/ui/src/components/inbox.tsx @@ -58,7 +58,16 @@ export class Inbox extends Component<any, InboxState> { <div class="container"> <div class="row"> <div class="col-12"> - <h5>Inbox for <Link to={`/u/${user.username}`}>{user.username}</Link></h5> + <h5 class="mb-0"> + <span>Inbox for <Link to={`/u/${user.username}`}>{user.username}</Link></span> + </h5> + {this.state.replies.length > 0 && this.state.unreadType == UnreadType.Unread && + <ul class="list-inline mb-1 text-muted small font-weight-bold"> + <li className="list-inline-item"> + <span class="pointer" onClick={this.markAllAsRead}>mark all as read</span> + </li> + </ul> + } {this.selects()} {this.replies()} {this.paginator()} @@ -147,13 +156,17 @@ export class Inbox extends Component<any, InboxState> { i.refetch(); } + markAllAsRead() { + WebSocketService.Instance.markAllAsRead(); + } + parseMessage(msg: any) { console.log(msg); let op: UserOperation = msgOp(msg); if (msg.error) { alert(msg.error); return; - } else if (op == UserOperation.GetReplies) { + } else if (op == UserOperation.GetReplies || op == UserOperation.MarkAllAsRead) { let res: GetRepliesResponse = msg; this.state.replies = res.replies; this.sendRepliesCount(); diff --git a/ui/src/components/navbar.tsx b/ui/src/components/navbar.tsx index 31dab61b..ee19e5c5 100644 --- a/ui/src/components/navbar.tsx +++ b/ui/src/components/navbar.tsx @@ -79,7 +79,7 @@ export class Navbar extends Component<any, NavbarState> { <Link class="nav-link" to="/search">Search</Link> </li> <li class="nav-item"> - <Link class="nav-link" to="/create_post">Create Post</Link> + <Link class="nav-link" to={{pathname: '/create_post', state: { prevPath: this.currentLocation }}}>Create Post</Link> </li> <li class="nav-item"> <Link class="nav-link" to="/create_community">Create Community</Link> @@ -165,6 +165,10 @@ export class Navbar extends Component<any, NavbarState> { } } + get currentLocation() { + return this.context.router.history.location.pathname; + } + sendRepliesCount(res: GetRepliesResponse) { UserService.Instance.sub.next({user: UserService.Instance.user, unreadCount: res.replies.filter(r => !r.read).length}); } diff --git a/ui/src/components/post-form.tsx b/ui/src/components/post-form.tsx index ab936282..e4e75df4 100644 --- a/ui/src/components/post-form.tsx +++ b/ui/src/components/post-form.tsx @@ -8,6 +8,7 @@ import * as autosize from 'autosize'; interface PostFormProps { post?: Post; // If a post is given, that means this is an edit + prevCommunityName?: string; onCancel?(): any; onCreate?(id: number): any; onEdit?(post: Post): any; @@ -170,6 +171,9 @@ export class PostForm extends Component<PostFormProps, PostFormState> { this.state.communities = res.communities; if (this.props.post) { this.state.postForm.community_id = this.props.post.community_id; + } else if (this.props.prevCommunityName) { + let foundCommunityId = res.communities.find(r => r.name == this.props.prevCommunityName).id; + this.state.postForm.community_id = foundCommunityId; } else { this.state.postForm.community_id = res.communities[0].id; } diff --git a/ui/src/interfaces.ts b/ui/src/interfaces.ts index 51582f3a..8a16de43 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, Search + 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, MarkAllAsRead } export enum CommentSortType { diff --git a/ui/src/services/WebSocketService.ts b/ui/src/services/WebSocketService.ts index 2389ab84..06e604e9 100644 --- a/ui/src/services/WebSocketService.ts +++ b/ui/src/services/WebSocketService.ts @@ -177,6 +177,12 @@ export class WebSocketService { this.subject.next(this.wsSendWrapper(UserOperation.Search, form)); } + public markAllAsRead() { + let form = {}; + this.setAuth(form); + this.subject.next(this.wsSendWrapper(UserOperation.MarkAllAsRead, form)); + } + private wsSendWrapper(op: UserOperation, data: any) { let send = { op: UserOperation[op], data: data }; console.log(send); diff --git a/ui/src/utils.ts b/ui/src/utils.ts index 4199f09c..3baf2367 100644 --- a/ui/src/utils.ts +++ b/ui/src/utils.ts @@ -1,5 +1,6 @@ import { UserOperation, Comment, User, SortType, ListingType } from './interfaces'; import * as markdown_it from 'markdown-it'; +import * as markdown_it_container from 'markdown-it-container'; export let repoUrl = 'https://github.com/dessalines/lemmy'; @@ -12,6 +13,23 @@ var md = new markdown_it({ html: true, linkify: true, typographer: true +}).use(markdown_it_container, 'spoiler', { + validate: function(params: any) { + return params.trim().match(/^spoiler\s+(.*)$/); + }, + + render: function (tokens: any, idx: any) { + var m = tokens[idx].info.trim().match(/^spoiler\s+(.*)$/); + + if (tokens[idx].nesting === 1) { + // opening tag + return '<details><summary>' + md.utils.escapeHtml(m[1]) + '</summary>\n'; + + } else { + // closing tag + return '</details>\n'; + } + } }); export function hotRank(comment: Comment): number { diff --git a/ui/yarn.lock b/ui/yarn.lock index 5756a444..2b29b787 100644 --- a/ui/yarn.lock +++ b/ui/yarn.lock @@ -38,7 +38,14 @@ resolved "https://registry.yarnpkg.com/@types/linkify-it/-/linkify-it-2.1.0.tgz#ea3dd64c4805597311790b61e872cbd1ed2cd806" integrity sha512-Q7DYAOi9O/+cLLhdaSvKdaumWyHbm7HAk/bFwwyTuU0arR5yyCeW5GOoqt4tJTpDRxhpx9Q8kQL6vMpuw9hDSw== -"@types/markdown-it@^0.0.7": +"@types/markdown-it-container@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@types/markdown-it-container/-/markdown-it-container-2.0.2.tgz#0e624653415a1c2f088a5ae51f7bfff480c03f49" + integrity sha512-T770GL+zJz8Ssh1NpLiOruYhrU96yb8ovPSegLrWY5XIkJc6PVVC7kH/oQaVD0rkePpWMFJK018OgS/pwviOMw== + dependencies: + "@types/markdown-it" "*" + +"@types/markdown-it@*", "@types/markdown-it@^0.0.7": version "0.0.7" resolved "https://registry.yarnpkg.com/@types/markdown-it/-/markdown-it-0.0.7.tgz#75070485a3d8ad11e7deb8287f4430be15bf4d39" integrity sha512-WyL6pa76ollQFQNEaLVa41ZUUvDvPY+qAUmlsphnrpL6I9p1m868b26FyeoOmo7X3/Ta/S9WKXcEYXUSHnxoVQ== @@ -1674,6 +1681,11 @@ map-visit@^1.0.0: dependencies: object-visit "^1.0.0" +markdown-it-container@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/markdown-it-container/-/markdown-it-container-2.0.0.tgz#0019b43fd02eefece2f1960a2895fba81a404695" + integrity sha1-ABm0P9Au7+zi8ZYKKJX7qBpARpU= + markdown-it@^8.4.2: version "8.4.2" resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-8.4.2.tgz#386f98998dc15a37722aa7722084f4020bdd9b54" |