]> Untitled Git - lemmy.git/commitdiff
Adding save user settings
authorDessalines <tyhou13@gmx.com>
Wed, 14 Aug 2019 02:28:46 +0000 (19:28 -0700)
committerDessalines <tyhou13@gmx.com>
Wed, 14 Aug 2019 02:28:46 +0000 (19:28 -0700)
12 files changed:
docker_db_backup.sh
server/src/api/mod.rs
server/src/api/user.rs
server/src/websocket/server.rs
ui/package.json
ui/src/components/setup.tsx
ui/src/components/user.tsx
ui/src/interfaces.ts
ui/src/services/WebSocketService.ts
ui/src/translations/en.ts
ui/tslint.json
ui/yarn.lock

index 5b87b818b2f933a7fd4cdcdd7240d7bcb839b17e..e361da1941b17d473b4f3b63543baf81866bc1ee 100755 (executable)
@@ -1 +1 @@
-docker exec -it lemmy_db_1 pg_dumpall -c -U rrr > dump_`date +%d-%m-%Y"_"%H_%M_%S`.sql
+docker exec -it lemmy_db_1 pg_dumpall -c -U rrr > dump_`date +%Y-%m-%d"_"%H_%M_%S`.sql
index e10770b4df8bf4015f4827925f3703c0659ab716..3a4a08658a0dc31e32d95aa4ee2d86b827fd06b4 100644 (file)
@@ -22,7 +22,7 @@ pub mod site;
 
 #[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, MarkAllAsRead
+  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, SaveUserSettings
 }
 
 #[derive(Fail, Debug)]
index b8f7408baa6651c87029ae0e71a3a012763949a8..2a6c214a788111c5307edb8109def94eeddc4a52 100644 (file)
@@ -18,6 +18,12 @@ pub struct Register {
   show_nsfw: bool,
 }
 
+#[derive(Serialize, Deserialize)]
+pub struct SaveUserSettings {
+  show_nsfw: bool,
+  auth: String,
+}
+
 #[derive(Serialize, Deserialize)]
 pub struct LoginResponse {
   op: String,
@@ -221,6 +227,50 @@ impl Perform<LoginResponse> for Oper<Register> {
   }
 }
 
+impl Perform<LoginResponse> for Oper<SaveUserSettings> {
+  fn perform(&self) -> Result<LoginResponse, Error> {
+    let data: &SaveUserSettings = &self.data;
+    let conn = establish_connection();
+
+    let claims = match Claims::decode(&data.auth) {
+      Ok(claims) => claims.claims,
+      Err(_e) => {
+        return Err(APIError::err(&self.op, "not_logged_in"))?
+      }
+    };
+
+    let user_id = claims.id;
+    
+    let read_user = User_::read(&conn, user_id)?;
+
+    let user_form = UserForm {
+      name: read_user.name,
+      fedi_name: read_user.fedi_name,
+      email: read_user.email,
+      password_encrypted: read_user.password_encrypted,
+      preferred_username: read_user.preferred_username,
+      updated: Some(naive_now()),
+      admin: read_user.admin,
+      banned: read_user.banned,
+      show_nsfw: data.show_nsfw,
+    };
+
+    let updated_user = match User_::update(&conn, user_id, &user_form) {
+      Ok(user) => user,
+      Err(_e) => {
+        return Err(APIError::err(&self.op, "couldnt_update_user"))?
+      }
+    };
+
+    // Return the jwt
+    Ok(
+      LoginResponse {
+        op: self.op.to_string(), 
+        jwt: updated_user.jwt()
+      }
+      )
+  }
+}
 
 impl Perform<GetUserDetailsResponse> for Oper<GetUserDetails> {
   fn perform(&self) -> Result<GetUserDetailsResponse, Error> {
index fd2073b062cde2f659f1f9f09cdc2be971f3f9f4..64f94f4cd4fc5242e167577be4bba060aa518b24 100644 (file)
@@ -305,6 +305,11 @@ fn parse_json_message(chat: &mut ChatServer, msg: StandardMessage) -> Result<Str
       let res = Oper::new(user_operation, get_user_details).perform()?;
       Ok(serde_json::to_string(&res)?)
     },
+    UserOperation::SaveUserSettings => {
+      let save_user_settings: SaveUserSettings = serde_json::from_str(data)?;
+      let res = Oper::new(user_operation, save_user_settings).perform()?;
+      Ok(serde_json::to_string(&res)?)
+    },
     UserOperation::AddAdmin => {
       let add_admin: AddAdmin = serde_json::from_str(data)?;
       let res = Oper::new(user_operation, add_admin).perform()?;
index d86725f254d45b35a846d9a5bf197820828cdc26..523700a23b8113c26db66aef83fe5f7dcdce2275 100644 (file)
@@ -41,6 +41,6 @@
     "fuse-box": "^3.1.3",
     "ts-transform-classcat": "^0.0.2",
     "ts-transform-inferno": "^4.0.2",
-    "typescript": "^3.3.3333"
+    "typescript": "^3.5.3"
   }
 }
index f11dc14e0d07b64a238b8d527b86258bc454ef19..24a5f2d68961709a73fd49587e6307693c5c8954 100644 (file)
@@ -23,6 +23,7 @@ export class Setup extends Component<any, State> {
       password: undefined,
       password_verify: undefined,
       admin: true,
+      show_nsfw: true,
     },
     doneRegisteringUser: false,
     userLoading: false,
index c6a70560f497b74eeccbbe2f0795b12866fbf51d..39a13e16218033d34af9b78275cca7a29734c804 100644 (file)
@@ -2,8 +2,8 @@ import { Component, linkEvent } from 'inferno';
 import { Link } from 'inferno-router';
 import { Subscription } from "rxjs";
 import { retryWhen, delay, take } from 'rxjs/operators';
-import { UserOperation, Post, Comment, CommunityUser, GetUserDetailsForm, SortType, UserDetailsResponse, UserView, CommentResponse } from '../interfaces';
-import { WebSocketService } from '../services';
+import { UserOperation, Post, Comment, CommunityUser, GetUserDetailsForm, SortType, UserDetailsResponse, UserView, CommentResponse, UserSettingsForm, LoginResponse } from '../interfaces';
+import { WebSocketService, UserService } from '../services';
 import { msgOp, fetchLimit, routeSortTypeToEnum, capitalizeFirstLetter } from '../utils';
 import { PostListing } from './post-listing';
 import { CommentNodes } from './comment-nodes';
@@ -28,6 +28,8 @@ interface UserState {
   sort: SortType;
   page: number;
   loading: boolean;
+  userSettingsForm: UserSettingsForm;
+  userSettingsLoading: boolean;
 }
 
 export class User extends Component<any, UserState> {
@@ -54,6 +56,11 @@ export class User extends Component<any, UserState> {
     view: this.getViewFromProps(this.props),
     sort: this.getSortTypeFromProps(this.props),
     page: this.getPageFromProps(this.props),
+    userSettingsForm: {
+      show_nsfw: null,
+      auth: null,
+    },
+    userSettingsLoading: null,
   }
 
   constructor(props: any, context: any) {
@@ -75,6 +82,10 @@ export class User extends Component<any, UserState> {
     this.refetch();
   }
 
+  get isCurrentUser() {
+    return UserService.Instance.user && UserService.Instance.user.id == this.state.user.id;
+  }
+
   getViewFromProps(props: any): View {
     return (props.match.params.view) ? 
       View[capitalizeFirstLetter(props.match.params.view)] : 
@@ -131,6 +142,9 @@ export class User extends Component<any, UserState> {
           </div>
           <div class="col-12 col-md-3">
             {this.userInfo()}
+            {this.isCurrentUser &&
+              this.userSettings()
+            }
             {this.moderates()}
             {this.follows()}
           </div>
@@ -219,7 +233,7 @@ export class User extends Component<any, UserState> {
     return (
       <div>
         <h5>{user.name}</h5>
-        <div>{i18n.t('joined')}<MomentTime data={user} /></div>
+        <div>{i18n.t('joined')} <MomentTime data={user} /></div>
         <table class="table table-bordered table-sm mt-2">
           <tr>
             <td><T i18nKey="number_of_points" interpolation={{count: user.post_score}}>#</T></td>
@@ -235,6 +249,30 @@ export class User extends Component<any, UserState> {
     )
   }
 
+  userSettings() {  
+    return (
+      <div>
+        <h5><T i18nKey="settings">#</T></h5>
+        <form onSubmit={linkEvent(this, this.handleUserSettingsSubmit)}>
+          <div class="form-group row">
+            <div class="col-12">
+              <div class="form-check">
+                <input class="form-check-input" type="checkbox" checked={this.state.userSettingsForm.show_nsfw} onChange={linkEvent(this, this.handleUserSettingsShowNsfwChange)}/>
+                <label class="form-check-label"><T i18nKey="show_nsfw">#</T></label>
+              </div>
+            </div>
+          </div>
+          <div class="form-group row">
+            <div class="col-12">
+              <button type="submit" class="btn btn-secondary">{this.state.userSettingsLoading ? 
+              <svg class="icon icon-spinner spin"><use xlinkHref="#icon-spinner"></use></svg> : capitalizeFirstLetter(i18n.t('save'))}</button>
+            </div>
+          </div>
+        </form>
+      </div>
+    )
+  }
+
   moderates() {
     return (
       <div>
@@ -329,6 +367,19 @@ export class User extends Component<any, UserState> {
     i.refetch();
   }
 
+  handleUserSettingsShowNsfwChange(i: User, event: any) {
+    i.state.userSettingsForm.show_nsfw = event.target.checked;
+    i.setState(i.state);
+  }
+
+  handleUserSettingsSubmit(i: User, event: any) {
+    event.preventDefault();
+    i.state.userSettingsLoading = true;
+    i.setState(i.state);
+
+    WebSocketService.Instance.saveUserSettings(i.state.userSettingsForm);
+  }
+
   parseMessage(msg: any) {
     console.log(msg);
     let op: UserOperation = msgOp(msg);
@@ -343,6 +394,9 @@ export class User extends Component<any, UserState> {
       this.state.moderates = res.moderates;
       this.state.posts = res.posts;
       this.state.loading = false;
+      if (this.isCurrentUser) {
+        this.state.userSettingsForm.show_nsfw = UserService.Instance.user.show_nsfw;
+      }
       document.title = `/u/${this.state.user.name} - ${WebSocketService.Instance.site.name}`;
       window.scrollTo(0,0);
       this.setState(this.state);
@@ -378,6 +432,12 @@ export class User extends Component<any, UserState> {
       if (res.comment.my_vote !== null) 
         found.my_vote = res.comment.my_vote;
       this.setState(this.state);
+    } else if (op == UserOperation.SaveUserSettings) {
+        this.state = this.emptyState;
+        this.state.userSettingsLoading = false;
+        this.setState(this.state);
+        let res: LoginResponse = msg;
+        UserService.Instance.login(res);
     }
   }
 }
index 7078ccaccefc3d6b4e31d0472b64ecbd6a926018..ebd42340d193034aaf89aad017e9b4b6066e3da3 100644 (file)
@@ -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, MarkAllAsRead
+  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, SaveUserSettings
 }
 
 export enum CommentSortType {
@@ -347,7 +347,10 @@ export interface LoginResponse {
   jwt: string;
 }
 
-
+export interface UserSettingsForm {
+  show_nsfw: boolean;
+  auth: string;
+}
 
 export interface CommunityForm {
   name: string;
index c192c2b77add21af3462149398dad568674f874d..c34b6b3c15e0bde6bf28d0bd9e05c23cae95fe24 100644 (file)
@@ -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, SearchForm } 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, UserSettingsForm } from '../interfaces';
 import { webSocket } from 'rxjs/webSocket';
 import { Subject } from 'rxjs';
 import { retryWhen, delay, take } from 'rxjs/operators';
@@ -184,6 +184,11 @@ export class WebSocketService {
     this.subject.next(this.wsSendWrapper(UserOperation.MarkAllAsRead, form));
   }
 
+  public saveUserSettings(userSettingsForm: UserSettingsForm) {
+    this.setAuth(userSettingsForm);
+    this.subject.next(this.wsSendWrapper(UserOperation.SaveUserSettings, userSettingsForm));
+  }
+
   private wsSendWrapper(op: UserOperation, data: any) {
     let send = { op: UserOperation[op], data: data };
     console.log(send);
index a8726b798471485b9068a72fb25f69159ebd46c2..1f79bef2f23309438147a05a41e56120b701b046 100644 (file)
@@ -29,6 +29,7 @@ export const en = {
     mod: 'mod',
     mods: 'mods',
     moderates: 'Moderates',
+    settings: 'Settings',
     remove_as_mod: 'remove as mod',
     appoint_as_mod: 'appoint as mod',
     modlog: 'Modlog',
index d3e7a8a97242ade6a3f24cb1b53df2426dcb72a0..938502e473c519ba0903f21928b0fc46be64589b 100644 (file)
@@ -2,7 +2,7 @@
     "extends": "tslint:recommended",
     "rules": {
                        "forin": false,
-                       "indent": [ true, "tabs" ],
+                       "indent": [ true, "spaces" ],
                        "interface-name": false,
                        "ban-types": true,
                        "max-classes-per-file": true,
index f47c16c45912d5edf90adf73f97c51835d656f7d..f31f45ae5a80d124b8ddaca2f7cf5206748e5c8b 100644 (file)
@@ -2773,7 +2773,7 @@ typescript@^2.6.2:
   resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.9.2.tgz#1cbf61d05d6b96269244eb6a3bce4bd914e0f00c"
   integrity sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w==
 
-typescript@^3.3.3333:
+typescript@^3.5.3:
   version "3.5.3"
   resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.5.3.tgz#c830f657f93f1ea846819e929092f5fe5983e977"
   integrity sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g==