]> Untitled Git - lemmy.git/commitdiff
Running prettier on code.
authorDessalines <tyhou13@gmx.com>
Sat, 19 Oct 2019 00:20:27 +0000 (17:20 -0700)
committerDessalines <tyhou13@gmx.com>
Sat, 19 Oct 2019 00:20:27 +0000 (17:20 -0700)
- #305 , #309

43 files changed:
ui/src/components/comment-form.tsx
ui/src/components/comment-node.tsx
ui/src/components/comment-nodes.tsx
ui/src/components/communities.tsx
ui/src/components/community-form.tsx
ui/src/components/community.tsx
ui/src/components/create-community.tsx
ui/src/components/create-post.tsx
ui/src/components/footer.tsx
ui/src/components/inbox.tsx
ui/src/components/login.tsx
ui/src/components/main.tsx
ui/src/components/modlog.tsx
ui/src/components/moment-time.tsx
ui/src/components/navbar.tsx
ui/src/components/post-form.tsx
ui/src/components/post-listing.tsx
ui/src/components/post-listings.tsx
ui/src/components/post.tsx
ui/src/components/search.tsx
ui/src/components/setup.tsx
ui/src/components/sidebar.tsx
ui/src/components/site-form.tsx
ui/src/components/sponsors.tsx
ui/src/components/symbols.tsx
ui/src/components/user.tsx
ui/src/env.ts
ui/src/i18next.ts
ui/src/index.tsx
ui/src/interfaces.ts
ui/src/services/UserService.ts
ui/src/services/WebSocketService.ts
ui/src/translations/de.ts
ui/src/translations/en.ts
ui/src/translations/eo.ts
ui/src/translations/es.ts
ui/src/translations/fr.ts
ui/src/translations/nl.ts
ui/src/translations/ru.ts
ui/src/translations/sv.ts
ui/src/translations/zh.ts
ui/src/utils.ts
ui/src/version.ts

index 2095e9e5f5a7e69f974f60ae653c48a1c990448c..bebe62694147aa41a22e2b037f7f05947b5d0f6e 100644 (file)
@@ -1,7 +1,22 @@
 import { Component, linkEvent } from 'inferno';
-import { CommentNode as CommentNodeI, CommentForm as CommentFormI, SearchForm, SearchType, SortType, UserOperation, SearchResponse } from '../interfaces';
-import { Subscription } from "rxjs";
-import { capitalizeFirstLetter, mentionDropdownFetchLimit, msgOp, mdToHtml, randomStr, markdownHelpUrl } from '../utils';
+import {
+  CommentNode as CommentNodeI,
+  CommentForm as CommentFormI,
+  SearchForm,
+  SearchType,
+  SortType,
+  UserOperation,
+  SearchResponse,
+} from '../interfaces';
+import { Subscription } from 'rxjs';
+import {
+  capitalizeFirstLetter,
+  mentionDropdownFetchLimit,
+  msgOp,
+  mdToHtml,
+  randomStr,
+  markdownHelpUrl,
+} from '../utils';
 import { WebSocketService, UserService } from '../services';
 import * as autosize from 'autosize';
 import { i18n } from '../i18next';
@@ -25,7 +40,6 @@ interface CommentFormState {
 }
 
 export class CommentForm extends Component<CommentFormProps, CommentFormState> {
-
   private id = `comment-form-${randomStr()}`;
   private userSub: Subscription;
   private communitySub: Subscription;
@@ -34,13 +48,21 @@ export class CommentForm extends Component<CommentFormProps, CommentFormState> {
     commentForm: {
       auth: null,
       content: null,
-      post_id: this.props.node ? this.props.node.comment.post_id : this.props.postId,
-      creator_id: UserService.Instance.user ? UserService.Instance.user.id : null,
+      post_id: this.props.node
+        ? this.props.node.comment.post_id
+        : this.props.postId,
+      creator_id: UserService.Instance.user
+        ? UserService.Instance.user.id
+        : null,
     },
-    buttonTitle: !this.props.node ? capitalizeFirstLetter(i18n.t('post')) : this.props.edit ? capitalizeFirstLetter(i18n.t('edit')) : capitalizeFirstLetter(i18n.t('reply')),
+    buttonTitle: !this.props.node
+      ? capitalizeFirstLetter(i18n.t('post'))
+      : this.props.edit
+      ? capitalizeFirstLetter(i18n.t('edit'))
+      : capitalizeFirstLetter(i18n.t('reply')),
     previewMode: false,
     imageLoading: false,
-  }
+  };
 
   constructor(props: any, context: any) {
     super(props, context);
@@ -57,7 +79,9 @@ export class CommentForm extends Component<CommentFormProps, CommentFormState> {
           selectTemplate: (item: any) => {
             return `:${item.original.key}:`;
           },
-          values: Object.entries(emojiShortName).map(e => {return {'key': e[1], 'val': e[0]}}),
+          values: Object.entries(emojiShortName).map(e => {
+            return { key: e[1], val: e[0] };
+          }),
           allowSpaces: false,
           autocompleteMode: true,
           menuItemLimit: mentionDropdownFetchLimit,
@@ -88,8 +112,8 @@ export class CommentForm extends Component<CommentFormProps, CommentFormState> {
           allowSpaces: false,
           autocompleteMode: true,
           menuItemLimit: mentionDropdownFetchLimit,
-        }
-      ]
+        },
+      ],
     });
 
     this.state = this.emptyState;
@@ -104,7 +128,7 @@ export class CommentForm extends Component<CommentFormProps, CommentFormState> {
         // A reply gets a new parent id
         this.state.commentForm.parent_id = this.props.node.comment.id;
       }
-    }  
+    }
   }
 
   componentDidMount() {
@@ -124,27 +148,82 @@ export class CommentForm extends Component<CommentFormProps, CommentFormState> {
         <form onSubmit={linkEvent(this, this.handleCommentSubmit)}>
           <div class="form-group row">
             <div className={`col-sm-12`}>
-              <textarea id={this.id} className={`form-control ${this.state.previewMode && 'd-none'}`} value={this.state.commentForm.content} onInput={linkEvent(this, this.handleCommentContentChange)} required disabled={this.props.disabled} rows={2} maxLength={10000} />
-              {this.state.previewMode && 
-                <div className="md-div" dangerouslySetInnerHTML={mdToHtml(this.state.commentForm.content)} />
-              }
+              <textarea
+                id={this.id}
+                className={`form-control ${this.state.previewMode && 'd-none'}`}
+                value={this.state.commentForm.content}
+                onInput={linkEvent(this, this.handleCommentContentChange)}
+                required
+                disabled={this.props.disabled}
+                rows={2}
+                maxLength={10000}
+              />
+              {this.state.previewMode && (
+                <div
+                  className="md-div"
+                  dangerouslySetInnerHTML={mdToHtml(
+                    this.state.commentForm.content
+                  )}
+                />
+              )}
             </div>
           </div>
           <div class="row">
             <div class="col-sm-12">
-              <button type="submit" class="btn btn-sm btn-secondary mr-2" disabled={this.props.disabled}>{this.state.buttonTitle}</button>
-              {this.state.commentForm.content &&
-                <button className={`btn btn-sm mr-2 btn-secondary ${this.state.previewMode && 'active'}`} onClick={linkEvent(this, this.handlePreviewToggle)}><T i18nKey="preview">#</T></button>
-              }
-              {this.props.node && <button type="button" class="btn btn-sm btn-secondary mr-2" onClick={linkEvent(this, this.handleReplyCancel)}><T i18nKey="cancel">#</T></button>}
-              <a href={markdownHelpUrl} target="_blank" class="d-inline-block float-right text-muted small font-weight-bold"><T i18nKey="formatting_help">#</T></a>
+              <button
+                type="submit"
+                class="btn btn-sm btn-secondary mr-2"
+                disabled={this.props.disabled}
+              >
+                {this.state.buttonTitle}
+              </button>
+              {this.state.commentForm.content && (
+                <button
+                  className={`btn btn-sm mr-2 btn-secondary ${this.state
+                    .previewMode && 'active'}`}
+                  onClick={linkEvent(this, this.handlePreviewToggle)}
+                >
+                  <T i18nKey="preview">#</T>
+                </button>
+              )}
+              {this.props.node && (
+                <button
+                  type="button"
+                  class="btn btn-sm btn-secondary mr-2"
+                  onClick={linkEvent(this, this.handleReplyCancel)}
+                >
+                  <T i18nKey="cancel">#</T>
+                </button>
+              )}
+              <a
+                href={markdownHelpUrl}
+                target="_blank"
+                class="d-inline-block float-right text-muted small font-weight-bold"
+              >
+                <T i18nKey="formatting_help">#</T>
+              </a>
               <form class="d-inline-block mr-2 float-right text-muted small font-weight-bold">
-                <label htmlFor={`file-upload-${this.id}`} className={`${UserService.Instance.user && 'pointer'}`}><T i18nKey="upload_image">#</T></label>
-                <input id={`file-upload-${this.id}`} type="file" accept="image/*,video/*" name="file" class="d-none" disabled={!UserService.Instance.user} onChange={linkEvent(this, this.handleImageUpload)} />
+                <label
+                  htmlFor={`file-upload-${this.id}`}
+                  className={`${UserService.Instance.user && 'pointer'}`}
+                >
+                  <T i18nKey="upload_image">#</T>
+                </label>
+                <input
+                  id={`file-upload-${this.id}`}
+                  type="file"
+                  accept="image/*,video/*"
+                  name="file"
+                  class="d-none"
+                  disabled={!UserService.Instance.user}
+                  onChange={linkEvent(this, this.handleImageUpload)}
+                />
               </form>
-              {this.state.imageLoading && 
-                <svg class="icon icon-spinner spin"><use xlinkHref="#icon-spinner"></use></svg>
-              }
+              {this.state.imageLoading && (
+                <svg class="icon icon-spinner spin">
+                  <use xlinkHref="#icon-spinner"></use>
+                </svg>
+              )}
             </div>
           </div>
         </form>
@@ -200,23 +279,24 @@ export class CommentForm extends Component<CommentFormProps, CommentFormState> {
       method: 'POST',
       body: formData,
     })
-    .then(res => res.json())
-    .then(res => {
-      let url = `${window.location.origin}/pictshare/${res.url}`;
-      let markdown = (res.filetype == 'mp4') ? `[vid](${url}/raw)` : `![](${url})`;
-      let content = i.state.commentForm.content;
-      content = (content) ? `${content} ${markdown}` : markdown;
-      i.state.commentForm.content = content;
-      i.state.imageLoading = false;
-      i.setState(i.state);
-    })
-    .catch((error) => {
-      i.state.imageLoading = false;
-      i.setState(i.state);
-      alert(error);
-    })
+      .then(res => res.json())
+      .then(res => {
+        let url = `${window.location.origin}/pictshare/${res.url}`;
+        let markdown =
+          res.filetype == 'mp4' ? `[vid](${url}/raw)` : `![](${url})`;
+        let content = i.state.commentForm.content;
+        content = content ? `${content} ${markdown}` : markdown;
+        i.state.commentForm.content = content;
+        i.state.imageLoading = false;
+        i.setState(i.state);
+      })
+      .catch(error => {
+        i.state.imageLoading = false;
+        i.setState(i.state);
+        alert(error);
+      });
   }
-  
+
   userSearch(text: string, cb: any) {
     if (text) {
       let form: SearchForm = {
@@ -229,18 +309,19 @@ export class CommentForm extends Component<CommentFormProps, CommentFormState> {
 
       WebSocketService.Instance.search(form);
 
-      this.userSub = WebSocketService.Instance.subject
-      .subscribe(
-        (msg) => {  
+      this.userSub = WebSocketService.Instance.subject.subscribe(
+        msg => {
           let op: UserOperation = msgOp(msg);
           if (op == UserOperation.Search) {
             let res: SearchResponse = msg;
-            let users = res.users.map(u => {return {key: u.name}});
+            let users = res.users.map(u => {
+              return { key: u.name };
+            });
             cb(users);
             this.userSub.unsubscribe();
           }
         },
-        (err) => console.error(err),
+        err => console.error(err),
         () => console.log('complete')
       );
     } else {
@@ -260,18 +341,19 @@ export class CommentForm extends Component<CommentFormProps, CommentFormState> {
 
       WebSocketService.Instance.search(form);
 
-      this.communitySub = WebSocketService.Instance.subject
-      .subscribe(
-        (msg) => {  
+      this.communitySub = WebSocketService.Instance.subject.subscribe(
+        msg => {
           let op: UserOperation = msgOp(msg);
           if (op == UserOperation.Search) {
             let res: SearchResponse = msg;
-            let communities = res.communities.map(u => {return {key: u.name}});
+            let communities = res.communities.map(u => {
+              return { key: u.name };
+            });
             cb(communities);
             this.communitySub.unsubscribe();
           }
         },
-        (err) => console.error(err),
+        err => console.error(err),
         () => console.log('complete')
       );
     } else {
index ce4bb51085a2b35df59084e294eb2e9b65ec6c65..7eb5d9d4658454056bee58550c6a7a53e3e480c5 100644 (file)
@@ -1,6 +1,20 @@
 import { Component, linkEvent } from 'inferno';
 import { Link } from 'inferno-router';
-import { CommentNode as CommentNodeI, CommentLikeForm, CommentForm as CommentFormI, SaveCommentForm, BanFromCommunityForm, BanUserForm, CommunityUser, UserView, AddModToCommunityForm, AddAdminForm, TransferCommunityForm, TransferSiteForm, BanType } from '../interfaces';
+import {
+  CommentNode as CommentNodeI,
+  CommentLikeForm,
+  CommentForm as CommentFormI,
+  SaveCommentForm,
+  BanFromCommunityForm,
+  BanUserForm,
+  CommunityUser,
+  UserView,
+  AddModToCommunityForm,
+  AddAdminForm,
+  TransferCommunityForm,
+  TransferSiteForm,
+  BanType,
+} from '../interfaces';
 import { WebSocketService, UserService } from '../services';
 import { mdToHtml, getUnixTime, canMod, isMod } from '../utils';
 import * as moment from 'moment';
@@ -37,7 +51,6 @@ interface CommentNodeProps {
 }
 
 export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
-
   private emptyState: CommentNodeState = {
     showReply: false,
     showEdit: false,
@@ -51,7 +64,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
     viewSource: false,
     showConfirmTransferSite: false,
     showConfirmTransferCommunity: false,
-  }
+  };
 
   constructor(props: any, context: any) {
     super(props, context);
@@ -65,176 +78,405 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
   render() {
     let node = this.props.node;
     return (
-      <div className={`comment ${node.comment.parent_id  && !this.props.noIndent ? 'ml-4' : ''}`}>
-        {!this.state.collapsed && 
-          <div className={`vote-bar mr-2 float-left small text-center ${this.props.viewOnly && 'no-click'}`}>
-            <button className={`btn p-0 ${node.comment.my_vote == 1 ? 'text-info' : 'text-muted'}`} onClick={linkEvent(node, this.handleCommentLike)}>
-              <svg class="icon upvote"><use xlinkHref="#icon-arrow-up"></use></svg>
+      <div
+        className={`comment ${
+          node.comment.parent_id && !this.props.noIndent ? 'ml-4' : ''
+        }`}
+      >
+        {!this.state.collapsed && (
+          <div
+            className={`vote-bar mr-2 float-left small text-center ${this.props
+              .viewOnly && 'no-click'}`}
+          >
+            <button
+              className={`btn p-0 ${
+                node.comment.my_vote == 1 ? 'text-info' : 'text-muted'
+              }`}
+              onClick={linkEvent(node, this.handleCommentLike)}
+            >
+              <svg class="icon upvote">
+                <use xlinkHref="#icon-arrow-up"></use>
+              </svg>
             </button>
-            <div class={`font-weight-bold text-muted`}>{node.comment.score}</div>
-            <button className={`btn p-0 ${node.comment.my_vote == -1 ? 'text-danger' : 'text-muted'}`} onClick={linkEvent(node, this.handleCommentDisLike)}>
-              <svg class="icon downvote"><use xlinkHref="#icon-arrow-down"></use></svg>
+            <div class={`font-weight-bold text-muted`}>
+              {node.comment.score}
+            </div>
+            <button
+              className={`btn p-0 ${
+                node.comment.my_vote == -1 ? 'text-danger' : 'text-muted'
+              }`}
+              onClick={linkEvent(node, this.handleCommentDisLike)}
+            >
+              <svg class="icon downvote">
+                <use xlinkHref="#icon-arrow-down"></use>
+              </svg>
             </button>
           </div>
-        }
-        <div id={`comment-${node.comment.id}`} className={`details comment-node ml-4 ${this.isCommentNew ? 'mark' : ''}`}>
+        )}
+        <div
+          id={`comment-${node.comment.id}`}
+          className={`details comment-node ml-4 ${
+            this.isCommentNew ? 'mark' : ''
+          }`}
+        >
           <ul class="list-inline mb-0 text-muted small">
             <li className="list-inline-item">
-              <Link className="text-info" to={`/u/${node.comment.creator_name}`}>{node.comment.creator_name}</Link>
+              <Link
+                className="text-info"
+                to={`/u/${node.comment.creator_name}`}
+              >
+                {node.comment.creator_name}
+              </Link>
             </li>
-            {this.isMod && 
-              <li className="list-inline-item badge badge-light"><T i18nKey="mod">#</T></li>
-            }
-            {this.isAdmin && 
-              <li className="list-inline-item badge badge-light"><T i18nKey="admin">#</T></li>
-            }
-            {this.isPostCreator && 
-              <li className="list-inline-item badge badge-light"><T i18nKey="creator">#</T></li>
-            }
-            {(node.comment.banned_from_community || node.comment.banned) &&  
-              <li className="list-inline-item badge badge-danger"><T i18nKey="banned">#</T></li>
-            }
+            {this.isMod && (
+              <li className="list-inline-item badge badge-light">
+                <T i18nKey="mod">#</T>
+              </li>
+            )}
+            {this.isAdmin && (
+              <li className="list-inline-item badge badge-light">
+                <T i18nKey="admin">#</T>
+              </li>
+            )}
+            {this.isPostCreator && (
+              <li className="list-inline-item badge badge-light">
+                <T i18nKey="creator">#</T>
+              </li>
+            )}
+            {(node.comment.banned_from_community || node.comment.banned) && (
+              <li className="list-inline-item badge badge-danger">
+                <T i18nKey="banned">#</T>
+              </li>
+            )}
             <li className="list-inline-item">
-              <span>(
-                <span className="text-info">+{node.comment.upvotes}</span>
+              <span>
+                (<span className="text-info">+{node.comment.upvotes}</span>
                 <span> | </span>
                 <span className="text-danger">-{node.comment.downvotes}</span>
                 <span>) </span>
               </span>
             </li>
             <li className="list-inline-item">
-              <span><MomentTime data={node.comment} /></span>
+              <span>
+                <MomentTime data={node.comment} />
+              </span>
             </li>
             <li className="list-inline-item">
-              <div className="pointer text-monospace" onClick={linkEvent(this, this.handleCommentCollapse)}>{this.state.collapsed ? '[+]' : '[-]'}</div>
+              <div
+                className="pointer text-monospace"
+                onClick={linkEvent(this, this.handleCommentCollapse)}
+              >
+                {this.state.collapsed ? '[+]' : '[-]'}
+              </div>
             </li>
           </ul>
-          {this.state.showEdit && <CommentForm node={node} edit onReplyCancel={this.handleReplyCancel} disabled={this.props.locked} />}
-          {!this.state.showEdit && !this.state.collapsed &&
+          {this.state.showEdit && (
+            <CommentForm
+              node={node}
+              edit
+              onReplyCancel={this.handleReplyCancel}
+              disabled={this.props.locked}
+            />
+          )}
+          {!this.state.showEdit && !this.state.collapsed && (
             <div>
-              {this.state.viewSource ? <pre>{this.commentUnlessRemoved}</pre> : 
-              <div className="md-div" dangerouslySetInnerHTML={mdToHtml(this.commentUnlessRemoved)} />
-              }
+              {this.state.viewSource ? (
+                <pre>{this.commentUnlessRemoved}</pre>
+              ) : (
+                <div
+                  className="md-div"
+                  dangerouslySetInnerHTML={mdToHtml(this.commentUnlessRemoved)}
+                />
+              )}
               <ul class="list-inline mb-1 text-muted small font-weight-bold">
-                {UserService.Instance.user && !this.props.viewOnly && 
+                {UserService.Instance.user && !this.props.viewOnly && (
                   <>
                     <li className="list-inline-item">
-                      <span class="pointer" onClick={linkEvent(this, this.handleReplyClick)}><T i18nKey="reply">#</T></span>
+                      <span
+                        class="pointer"
+                        onClick={linkEvent(this, this.handleReplyClick)}
+                      >
+                        <T i18nKey="reply">#</T>
+                      </span>
                     </li>
                     <li className="list-inline-item mr-2">
-                      <span class="pointer" onClick={linkEvent(this, this.handleSaveCommentClick)}>{node.comment.saved ? i18n.t('unsave') : i18n.t('save')}</span>
+                      <span
+                        class="pointer"
+                        onClick={linkEvent(this, this.handleSaveCommentClick)}
+                      >
+                        {node.comment.saved ? i18n.t('unsave') : i18n.t('save')}
+                      </span>
                     </li>
-                    {this.myComment && 
+                    {this.myComment && (
                       <>
                         <li className="list-inline-item">
-                          <span class="pointer" onClick={linkEvent(this, this.handleEditClick)}><T i18nKey="edit">#</T></span>
+                          <span
+                            class="pointer"
+                            onClick={linkEvent(this, this.handleEditClick)}
+                          >
+                            <T i18nKey="edit">#</T>
+                          </span>
                         </li>
                         <li className="list-inline-item">
-                          <span class="pointer" onClick={linkEvent(this, this.handleDeleteClick)}>
-                            {!node.comment.deleted ? i18n.t('delete') : i18n.t('restore')}
+                          <span
+                            class="pointer"
+                            onClick={linkEvent(this, this.handleDeleteClick)}
+                          >
+                            {!node.comment.deleted
+                              ? i18n.t('delete')
+                              : i18n.t('restore')}
                           </span>
                         </li>
                       </>
-                    }
+                    )}
                     {/* Admins and mods can remove comments */}
-                    {(this.canMod || this.canAdmin) && 
+                    {(this.canMod || this.canAdmin) && (
                       <li className="list-inline-item">
-                        {!node.comment.removed ? 
-                        <span class="pointer" onClick={linkEvent(this, this.handleModRemoveShow)}><T i18nKey="remove">#</T></span> :
-                        <span class="pointer" onClick={linkEvent(this, this.handleModRemoveSubmit)}><T i18nKey="restore">#</T></span>
-                        }
+                        {!node.comment.removed ? (
+                          <span
+                            class="pointer"
+                            onClick={linkEvent(this, this.handleModRemoveShow)}
+                          >
+                            <T i18nKey="remove">#</T>
+                          </span>
+                        ) : (
+                          <span
+                            class="pointer"
+                            onClick={linkEvent(
+                              this,
+                              this.handleModRemoveSubmit
+                            )}
+                          >
+                            <T i18nKey="restore">#</T>
+                          </span>
+                        )}
                       </li>
-                    }
+                    )}
                     {/* Mods can ban from community, and appoint as mods to community */}
-                    {this.canMod &&
+                    {this.canMod && (
                       <>
-                        {!this.isMod && 
+                        {!this.isMod && (
                           <li className="list-inline-item">
-                            {!node.comment.banned_from_community ? 
-                            <span class="pointer" onClick={linkEvent(this, this.handleModBanFromCommunityShow)}><T i18nKey="ban">#</T></span> :
-                            <span class="pointer" onClick={linkEvent(this, this.handleModBanFromCommunitySubmit)}><T i18nKey="unban">#</T></span>
-                            }
+                            {!node.comment.banned_from_community ? (
+                              <span
+                                class="pointer"
+                                onClick={linkEvent(
+                                  this,
+                                  this.handleModBanFromCommunityShow
+                                )}
+                              >
+                                <T i18nKey="ban">#</T>
+                              </span>
+                            ) : (
+                              <span
+                                class="pointer"
+                                onClick={linkEvent(
+                                  this,
+                                  this.handleModBanFromCommunitySubmit
+                                )}
+                              >
+                                <T i18nKey="unban">#</T>
+                              </span>
+                            )}
                           </li>
-                        }
-                        {!node.comment.banned_from_community &&
+                        )}
+                        {!node.comment.banned_from_community && (
                           <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>
+                            <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 &&
+                    {(this.amCommunityCreator || this.canAdmin) && this.isMod && (
                       <li className="list-inline-item">
-                        {!this.state.showConfirmTransferCommunity ?
-                        <span class="pointer" onClick={linkEvent(this, this.handleShowConfirmTransferCommunity)}><T i18nKey="transfer_community">#</T>
-                      </span> : <>
-                        <span class="d-inline-block mr-1"><T i18nKey="are_you_sure">#</T></span>
-                        <span class="pointer d-inline-block mr-1" onClick={linkEvent(this, this.handleTransferCommunity)}><T i18nKey="yes">#</T></span>
-                        <span class="pointer d-inline-block" onClick={linkEvent(this, this.handleCancelShowConfirmTransferCommunity)}><T i18nKey="no">#</T></span>
-                      </>
-                        }
+                        {!this.state.showConfirmTransferCommunity ? (
+                          <span
+                            class="pointer"
+                            onClick={linkEvent(
+                              this,
+                              this.handleShowConfirmTransferCommunity
+                            )}
+                          >
+                            <T i18nKey="transfer_community">#</T>
+                          </span>
+                        ) : (
+                          <>
+                            <span class="d-inline-block mr-1">
+                              <T i18nKey="are_you_sure">#</T>
+                            </span>
+                            <span
+                              class="pointer d-inline-block mr-1"
+                              onClick={linkEvent(
+                                this,
+                                this.handleTransferCommunity
+                              )}
+                            >
+                              <T i18nKey="yes">#</T>
+                            </span>
+                            <span
+                              class="pointer d-inline-block"
+                              onClick={linkEvent(
+                                this,
+                                this.handleCancelShowConfirmTransferCommunity
+                              )}
+                            >
+                              <T i18nKey="no">#</T>
+                            </span>
+                          </>
+                        )}
                       </li>
-                    }
+                    )}
                     {/* Admins can ban from all, and appoint other admins */}
-                    {this.canAdmin &&
+                    {this.canAdmin && (
                       <>
-                        {!this.isAdmin && 
+                        {!this.isAdmin && (
                           <li className="list-inline-item">
-                            {!node.comment.banned ? 
-                            <span class="pointer" onClick={linkEvent(this, this.handleModBanShow)}><T i18nKey="ban_from_site">#</T></span> :
-                            <span class="pointer" onClick={linkEvent(this, this.handleModBanSubmit)}><T i18nKey="unban_from_site">#</T></span>
-                            }
+                            {!node.comment.banned ? (
+                              <span
+                                class="pointer"
+                                onClick={linkEvent(this, this.handleModBanShow)}
+                              >
+                                <T i18nKey="ban_from_site">#</T>
+                              </span>
+                            ) : (
+                              <span
+                                class="pointer"
+                                onClick={linkEvent(
+                                  this,
+                                  this.handleModBanSubmit
+                                )}
+                              >
+                                <T i18nKey="unban_from_site">#</T>
+                              </span>
+                            )}
                           </li>
-                        }
-                        {!node.comment.banned &&
+                        )}
+                        {!node.comment.banned && (
                           <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>
+                            <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 &&
+                    {this.amSiteCreator && this.isAdmin && (
                       <li className="list-inline-item">
-                        {!this.state.showConfirmTransferSite ?
-                        <span class="pointer" onClick={linkEvent(this, this.handleShowConfirmTransferSite)}><T i18nKey="transfer_site">#</T>
-                      </span> : <>
-                        <span class="d-inline-block mr-1"><T i18nKey="are_you_sure">#</T></span>
-                        <span class="pointer d-inline-block mr-1" onClick={linkEvent(this, this.handleTransferSite)}><T i18nKey="yes">#</T></span>
-                        <span class="pointer d-inline-block" onClick={linkEvent(this, this.handleCancelShowConfirmTransferSite)}><T i18nKey="no">#</T></span>
-                      </>
-                        }
+                        {!this.state.showConfirmTransferSite ? (
+                          <span
+                            class="pointer"
+                            onClick={linkEvent(
+                              this,
+                              this.handleShowConfirmTransferSite
+                            )}
+                          >
+                            <T i18nKey="transfer_site">#</T>
+                          </span>
+                        ) : (
+                          <>
+                            <span class="d-inline-block mr-1">
+                              <T i18nKey="are_you_sure">#</T>
+                            </span>
+                            <span
+                              class="pointer d-inline-block mr-1"
+                              onClick={linkEvent(this, this.handleTransferSite)}
+                            >
+                              <T i18nKey="yes">#</T>
+                            </span>
+                            <span
+                              class="pointer d-inline-block"
+                              onClick={linkEvent(
+                                this,
+                                this.handleCancelShowConfirmTransferSite
+                              )}
+                            >
+                              <T i18nKey="no">#</T>
+                            </span>
+                          </>
+                        )}
                       </li>
-                    }
+                    )}
                   </>
-                }
+                )}
                 <li className="list-inline-item">
-                  <span className="pointer" onClick={linkEvent(this, this.handleViewSource)}><T i18nKey="view_source">#</T></span>
+                  <span
+                    className="pointer"
+                    onClick={linkEvent(this, this.handleViewSource)}
+                  >
+                    <T i18nKey="view_source">#</T>
+                  </span>
                 </li>
                 <li className="list-inline-item">
-                  <Link className="text-muted" to={`/post/${node.comment.post_id}/comment/${node.comment.id}`}><T i18nKey="link">#</T></Link>
+                  <Link
+                    className="text-muted"
+                    to={`/post/${node.comment.post_id}/comment/${node.comment.id}`}
+                  >
+                    <T i18nKey="link">#</T>
+                  </Link>
                 </li>
-                {this.props.markable && 
+                {this.props.markable && (
                   <li className="list-inline-item">
-                    <span class="pointer" onClick={linkEvent(this, this.handleMarkRead)}>{node.comment.read ? i18n.t('mark_as_unread') : i18n.t('mark_as_read')}</span>
+                    <span
+                      class="pointer"
+                      onClick={linkEvent(this, this.handleMarkRead)}
+                    >
+                      {node.comment.read
+                        ? i18n.t('mark_as_unread')
+                        : i18n.t('mark_as_read')}
+                    </span>
                   </li>
-                }
+                )}
               </ul>
             </div>
-          }
+          )}
         </div>
-        {this.state.showRemoveDialog && 
-          <form class="form-inline" onSubmit={linkEvent(this, this.handleModRemoveSubmit)}>
-            <input type="text" class="form-control mr-2" placeholder={i18n.t('reason')} value={this.state.removeReason} onInput={linkEvent(this, this.handleModRemoveReasonChange)} />
-            <button type="submit" class="btn btn-secondary"><T i18nKey="remove_comment">#</T></button>
+        {this.state.showRemoveDialog && (
+          <form
+            class="form-inline"
+            onSubmit={linkEvent(this, this.handleModRemoveSubmit)}
+          >
+            <input
+              type="text"
+              class="form-control mr-2"
+              placeholder={i18n.t('reason')}
+              value={this.state.removeReason}
+              onInput={linkEvent(this, this.handleModRemoveReasonChange)}
+            />
+            <button type="submit" class="btn btn-secondary">
+              <T i18nKey="remove_comment">#</T>
+            </button>
           </form>
-        }
-        {this.state.showBanDialog && 
+        )}
+        {this.state.showBanDialog && (
           <form onSubmit={linkEvent(this, this.handleModBanBothSubmit)}>
             <div class="form-group row">
-              <label class="col-form-label"><T i18nKey="reason">#</T></label>
-              <input type="text" class="form-control mr-2" placeholder={i18n.t('reason')} value={this.state.banReason} onInput={linkEvent(this, this.handleModBanReasonChange)} />
+              <label class="col-form-label">
+                <T i18nKey="reason">#</T>
+              </label>
+              <input
+                type="text"
+                class="form-control mr-2"
+                placeholder={i18n.t('reason')}
+                value={this.state.banReason}
+                onInput={linkEvent(this, this.handleModBanReasonChange)}
+              />
             </div>
             {/* TODO hold off on expires until later */}
             {/* <div class="form-group row"> */}
@@ -242,42 +484,59 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
             {/*   <input type="date" class="form-control mr-2" placeholder={i18n.t('expires')} value={this.state.banExpires} onInput={linkEvent(this, this.handleModBanExpiresChange)} /> */}
             {/* </div> */}
             <div class="form-group row">
-              <button type="submit" class="btn btn-secondary">{i18n.t('ban')} {node.comment.creator_name}</button>
+              <button type="submit" class="btn btn-secondary">
+                {i18n.t('ban')} {node.comment.creator_name}
+              </button>
             </div>
           </form>
-        }
-        {this.state.showReply && 
-          <CommentForm 
-            node={node} 
-            onReplyCancel={this.handleReplyCancel} 
-            disabled={this.props.locked} 
+        )}
+        {this.state.showReply && (
+          <CommentForm
+            node={node}
+            onReplyCancel={this.handleReplyCancel}
+            disabled={this.props.locked}
           />
-        }
-        {node.children && !this.state.collapsed &&
-          <CommentNodes 
-            nodes={node.children} 
-            locked={this.props.locked} 
+        )}
+        {node.children && !this.state.collapsed && (
+          <CommentNodes
+            nodes={node.children}
+            locked={this.props.locked}
             moderators={this.props.moderators}
             admins={this.props.admins}
             postCreatorId={this.props.postCreatorId}
           />
-        }
+        )}
         {/* A collapsed clearfix */}
         {this.state.collapsed && <div class="row col-12"></div>}
       </div>
-    )
+    );
   }
 
   get myComment(): boolean {
-    return UserService.Instance.user && this.props.node.comment.creator_id == UserService.Instance.user.id;
+    return (
+      UserService.Instance.user &&
+      this.props.node.comment.creator_id == UserService.Instance.user.id
+    );
   }
 
   get isMod(): boolean {
-    return this.props.moderators && isMod(this.props.moderators.map(m => m.user_id), this.props.node.comment.creator_id);
+    return (
+      this.props.moderators &&
+      isMod(
+        this.props.moderators.map(m => m.user_id),
+        this.props.node.comment.creator_id
+      )
+    );
   }
 
   get isAdmin(): boolean {
-    return this.props.admins && isMod(this.props.admins.map(a => a.id), this.props.node.comment.creator_id);
+    return (
+      this.props.admins &&
+      isMod(
+        this.props.admins.map(a => a.id),
+        this.props.node.comment.creator_id
+      )
+    );
   }
 
   get isPostCreator(): boolean {
@@ -285,38 +544,57 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
   }
 
   get canMod(): boolean {
-
     if (this.props.admins && this.props.moderators) {
-      let adminsThenMods = this.props.admins.map(a => a.id)
-      .concat(this.props.moderators.map(m => m.user_id));
-
-      return canMod(UserService.Instance.user, adminsThenMods, this.props.node.comment.creator_id);
-      } else { 
+      let adminsThenMods = this.props.admins
+        .map(a => a.id)
+        .concat(this.props.moderators.map(m => m.user_id));
+
+      return canMod(
+        UserService.Instance.user,
+        adminsThenMods,
+        this.props.node.comment.creator_id
+      );
+    } else {
       return false;
     }
   }
 
   get canAdmin(): boolean {
-    return this.props.admins && canMod(UserService.Instance.user, this.props.admins.map(a => a.id), this.props.node.comment.creator_id);
+    return (
+      this.props.admins &&
+      canMod(
+        UserService.Instance.user,
+        this.props.admins.map(a => a.id),
+        this.props.node.comment.creator_id
+      )
+    );
   }
 
   get amCommunityCreator(): boolean {
-    return this.props.moderators && 
-      UserService.Instance.user && 
-      (this.props.node.comment.creator_id != UserService.Instance.user.id) &&
-      (UserService.Instance.user.id == this.props.moderators[0].user_id);
+    return (
+      this.props.moderators &&
+      UserService.Instance.user &&
+      this.props.node.comment.creator_id != UserService.Instance.user.id &&
+      UserService.Instance.user.id == this.props.moderators[0].user_id
+    );
   }
 
   get amSiteCreator(): boolean {
-    return this.props.admins && 
-      UserService.Instance.user && 
-      (this.props.node.comment.creator_id != UserService.Instance.user.id) &&
-      (UserService.Instance.user.id == this.props.admins[0].id);
+    return (
+      this.props.admins &&
+      UserService.Instance.user &&
+      this.props.node.comment.creator_id != UserService.Instance.user.id &&
+      UserService.Instance.user.id == this.props.admins[0].id
+    );
   }
-  
-  get commentUnlessRemoved(): string {  
+
+  get commentUnlessRemoved(): string {
     let node = this.props.node;
-    return node.comment.removed ? `*${i18n.t('removed')}*` : node.comment.deleted ? `*${i18n.t('deleted')}*` : node.comment.content;
+    return node.comment.removed
+      ? `*${i18n.t('removed')}*`
+      : node.comment.deleted
+      ? `*${i18n.t('deleted')}*`
+      : node.comment.content;
   }
 
   handleReplyClick(i: CommentNode) {
@@ -337,16 +615,19 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
       post_id: i.props.node.comment.post_id,
       parent_id: i.props.node.comment.parent_id,
       deleted: !i.props.node.comment.deleted,
-      auth: null
+      auth: null,
     };
     WebSocketService.Instance.editComment(deleteForm);
   }
 
   handleSaveCommentClick(i: CommentNode) {
-    let saved = (i.props.node.comment.saved == undefined) ? true : !i.props.node.comment.saved;
+    let saved =
+      i.props.node.comment.saved == undefined
+        ? true
+        : !i.props.node.comment.saved;
     let form: SaveCommentForm = {
       comment_id: i.props.node.comment.id,
-      save: saved
+      save: saved,
     };
 
     WebSocketService.Instance.saveComment(form);
@@ -358,13 +639,11 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
     this.setState(this.state);
   }
 
-
   handleCommentLike(i: CommentNodeI) {
-
     let form: CommentLikeForm = {
       comment_id: i.comment.id,
       post_id: i.comment.post_id,
-      score: (i.comment.my_vote == 1) ? 0 : 1
+      score: i.comment.my_vote == 1 ? 0 : 1,
     };
     WebSocketService.Instance.likeComment(form);
   }
@@ -373,7 +652,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
     let form: CommentLikeForm = {
       comment_id: i.comment.id,
       post_id: i.comment.post_id,
-      score: (i.comment.my_vote == -1) ? 0 : -1
+      score: i.comment.my_vote == -1 ? 0 : -1,
     };
     WebSocketService.Instance.likeComment(form);
   }
@@ -398,7 +677,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
       parent_id: i.props.node.comment.parent_id,
       removed: !i.props.node.comment.removed,
       reason: i.state.removeReason,
-      auth: null
+      auth: null,
     };
     WebSocketService.Instance.editComment(form);
 
@@ -414,12 +693,11 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
       post_id: i.props.node.comment.post_id,
       parent_id: i.props.node.comment.parent_id,
       read: !i.props.node.comment.read,
-      auth: null
+      auth: null,
     };
     WebSocketService.Instance.editComment(form);
   }
 
-
   handleModBanFromCommunityShow(i: CommentNode) {
     i.state.showBanDialog = true;
     i.state.banType = BanType.Community;
@@ -499,12 +777,12 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
     i.setState(i.state);
   }
 
-  handleShowConfirmTransferCommunity(i: CommentNode) { 
+  handleShowConfirmTransferCommunity(i: CommentNode) {
     i.state.showConfirmTransferCommunity = true;
     i.setState(i.state);
   }
 
-  handleCancelShowConfirmTransferCommunity(i: CommentNode) { 
+  handleCancelShowConfirmTransferCommunity(i: CommentNode) {
     i.state.showConfirmTransferCommunity = false;
     i.setState(i.state);
   }
@@ -519,12 +797,12 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
     i.setState(i.state);
   }
 
-  handleShowConfirmTransferSite(i: CommentNode) { 
+  handleShowConfirmTransferSite(i: CommentNode) {
     i.state.showConfirmTransferSite = true;
     i.setState(i.state);
   }
 
-  handleCancelShowConfirmTransferSite(i: CommentNode) { 
+  handleCancelShowConfirmTransferSite(i: CommentNode) {
     i.state.showConfirmTransferSite = false;
     i.setState(i.state);
   }
index 1e61c2f04bfbc32f6d355cd8c1cedd6c2f33433e..18faf1ac4c87ff14bad3ce1d94ca709013d56bd8 100644 (file)
@@ -1,9 +1,12 @@
 import { Component } from 'inferno';
-import { CommentNode as CommentNodeI, CommunityUser, UserView } from '../interfaces';
+import {
+  CommentNode as CommentNodeI,
+  CommunityUser,
+  UserView,
+} from '../interfaces';
 import { CommentNode } from './comment-node';
 
-interface CommentNodesState {
-}
+interface CommentNodesState {}
 
 interface CommentNodesProps {
   nodes: Array<CommentNodeI>;
@@ -16,8 +19,10 @@ interface CommentNodesProps {
   markable?: boolean;
 }
 
-export class CommentNodes extends Component<CommentNodesProps, CommentNodesState> {
-
+export class CommentNodes extends Component<
+  CommentNodesProps,
+  CommentNodesState
+> {
   constructor(props: any, context: any) {
     super(props, context);
   }
@@ -25,20 +30,19 @@ export class CommentNodes extends Component<CommentNodesProps, CommentNodesState
   render() {
     return (
       <div className="comments">
-        {this.props.nodes.map(node =>
-          <CommentNode node={node} 
-            noIndent={this.props.noIndent} 
-            viewOnly={this.props.viewOnly} 
-            locked={this.props.locked} 
+        {this.props.nodes.map(node => (
+          <CommentNode
+            node={node}
+            noIndent={this.props.noIndent}
+            viewOnly={this.props.viewOnly}
+            locked={this.props.locked}
             moderators={this.props.moderators}
             admins={this.props.admins}
             postCreatorId={this.props.postCreatorId}
             markable={this.props.markable}
           />
-        )}
+        ))}
       </div>
-    )
+    );
   }
-
 }
-
index 49b982dc95df564674ad980d1ebda18d9125638e..7e4a0ef8b973ecd2027dc596a6337cb37da07e55 100644 (file)
@@ -1,8 +1,16 @@
 import { Component, linkEvent } from 'inferno';
 import { Link } from 'inferno-router';
-import { Subscription } from "rxjs";
+import { Subscription } from 'rxjs';
 import { retryWhen, delay, take } from 'rxjs/operators';
-import { UserOperation, Community, ListCommunitiesResponse, CommunityResponse, FollowCommunityForm, ListCommunitiesForm, SortType } from '../interfaces';
+import {
+  UserOperation,
+  Community,
+  ListCommunitiesResponse,
+  CommunityResponse,
+  FollowCommunityForm,
+  ListCommunitiesForm,
+  SortType,
+} from '../interfaces';
 import { WebSocketService } from '../services';
 import { msgOp } from '../utils';
 import { i18n } from '../i18next';
@@ -22,25 +30,31 @@ export class Communities extends Component<any, CommunitiesState> {
     communities: [],
     loading: true,
     page: this.getPageFromProps(this.props),
-  }
+  };
 
   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))))
+      .pipe(
+        retryWhen(errors =>
+          errors.pipe(
+            delay(3000),
+            take(10)
+          )
+        )
+      )
       .subscribe(
-        (msg) => this.parseMessage(msg),
-        (err) => console.error(err),
+        msg => this.parseMessage(msg),
+        err => console.error(err),
         () => console.log('complete')
       );
 
     this.refetch();
-
   }
 
   getPageFromProps(props: any): number {
-    return (props.match.params.page) ? Number(props.match.params.page) : 1;
+    return props.match.params.page ? Number(props.match.params.page) : 1;
   }
 
   componentWillUnmount() {
@@ -48,7 +62,9 @@ export class Communities extends Component<any, CommunitiesState> {
   }
 
   componentDidMount() {
-    document.title = `${i18n.t('communities')} - ${WebSocketService.Instance.site.name}`;
+    document.title = `${i18n.t('communities')} - ${
+      WebSocketService.Instance.site.name
+    }`;
   }
 
   // Necessary for back button for some reason
@@ -63,46 +79,92 @@ export class Communities extends Component<any, CommunitiesState> {
   render() {
     return (
       <div class="container">
-        {this.state.loading ? 
-        <h5 class=""><svg class="icon icon-spinner spin"><use xlinkHref="#icon-spinner"></use></svg></h5> : 
-        <div>
-          <h5><T i18nKey="list_of_communities">#</T></h5>
-          <div class="table-responsive">
-            <table id="community_table" class="table table-sm table-hover">
-              <thead class="pointer">
-                <tr>
-                  <th><T i18nKey="name">#</T></th>
-                  <th class="d-none d-lg-table-cell"><T i18nKey="title">#</T></th>
-                  <th><T i18nKey="category">#</T></th>
-                  <th class="text-right"><T i18nKey="subscribers">#</T></th>
-                  <th class="text-right d-none d-lg-table-cell"><T i18nKey="posts">#</T></th>
-                  <th class="text-right d-none d-lg-table-cell"><T i18nKey="comments">#</T></th>
-                  <th></th>
-                </tr>
-              </thead>
-              <tbody>
-                {this.state.communities.map(community =>
+        {this.state.loading ? (
+          <h5 class="">
+            <svg class="icon icon-spinner spin">
+              <use xlinkHref="#icon-spinner"></use>
+            </svg>
+          </h5>
+        ) : (
+          <div>
+            <h5>
+              <T i18nKey="list_of_communities">#</T>
+            </h5>
+            <div class="table-responsive">
+              <table id="community_table" class="table table-sm table-hover">
+                <thead class="pointer">
                   <tr>
-                    <td><Link to={`/c/${community.name}`}>{community.name}</Link></td>
-                    <td class="d-none d-lg-table-cell">{community.title}</td>
-                    <td>{community.category_name}</td>
-                    <td class="text-right">{community.number_of_subscribers}</td>
-                    <td class="text-right d-none d-lg-table-cell">{community.number_of_posts}</td>
-                    <td class="text-right d-none d-lg-table-cell">{community.number_of_comments}</td>
-                    <td class="text-right">
-                      {community.subscribed ? 
-                      <span class="pointer btn-link" onClick={linkEvent(community.id, this.handleUnsubscribe)}><T i18nKey="unsubscribe">#</T></span> : 
-                      <span class="pointer btn-link" onClick={linkEvent(community.id, this.handleSubscribe)}><T i18nKey="subscribe">#</T></span>
-                      }
-                    </td>
+                    <th>
+                      <T i18nKey="name">#</T>
+                    </th>
+                    <th class="d-none d-lg-table-cell">
+                      <T i18nKey="title">#</T>
+                    </th>
+                    <th>
+                      <T i18nKey="category">#</T>
+                    </th>
+                    <th class="text-right">
+                      <T i18nKey="subscribers">#</T>
+                    </th>
+                    <th class="text-right d-none d-lg-table-cell">
+                      <T i18nKey="posts">#</T>
+                    </th>
+                    <th class="text-right d-none d-lg-table-cell">
+                      <T i18nKey="comments">#</T>
+                    </th>
+                    <th></th>
                   </tr>
-                )}
-              </tbody>
-            </table>
+                </thead>
+                <tbody>
+                  {this.state.communities.map(community => (
+                    <tr>
+                      <td>
+                        <Link to={`/c/${community.name}`}>
+                          {community.name}
+                        </Link>
+                      </td>
+                      <td class="d-none d-lg-table-cell">{community.title}</td>
+                      <td>{community.category_name}</td>
+                      <td class="text-right">
+                        {community.number_of_subscribers}
+                      </td>
+                      <td class="text-right d-none d-lg-table-cell">
+                        {community.number_of_posts}
+                      </td>
+                      <td class="text-right d-none d-lg-table-cell">
+                        {community.number_of_comments}
+                      </td>
+                      <td class="text-right">
+                        {community.subscribed ? (
+                          <span
+                            class="pointer btn-link"
+                            onClick={linkEvent(
+                              community.id,
+                              this.handleUnsubscribe
+                            )}
+                          >
+                            <T i18nKey="unsubscribe">#</T>
+                          </span>
+                        ) : (
+                          <span
+                            class="pointer btn-link"
+                            onClick={linkEvent(
+                              community.id,
+                              this.handleSubscribe
+                            )}
+                          >
+                            <T i18nKey="subscribe">#</T>
+                          </span>
+                        )}
+                      </td>
+                    </tr>
+                  ))}
+                </tbody>
+              </table>
+            </div>
+            {this.paginator()}
           </div>
-          {this.paginator()}
-        </div>
-        }
+        )}
       </div>
     );
   }
@@ -110,10 +172,20 @@ export class Communities extends Component<any, CommunitiesState> {
   paginator() {
     return (
       <div class="mt-2">
-        {this.state.page > 1 && 
-          <button class="btn btn-sm btn-secondary mr-1" onClick={linkEvent(this, this.prevPage)}><T i18nKey="prev">#</T></button>
-        }
-        <button class="btn btn-sm btn-secondary" onClick={linkEvent(this, this.nextPage)}><T i18nKey="next">#</T></button>
+        {this.state.page > 1 && (
+          <button
+            class="btn btn-sm btn-secondary mr-1"
+            onClick={linkEvent(this, this.prevPage)}
+          >
+            <T i18nKey="prev">#</T>
+          </button>
+        )}
+        <button
+          class="btn btn-sm btn-secondary"
+          onClick={linkEvent(this, this.nextPage)}
+        >
+          <T i18nKey="next">#</T>
+        </button>
       </div>
     );
   }
@@ -122,14 +194,14 @@ export class Communities extends Component<any, CommunitiesState> {
     this.props.history.push(`/communities/page/${this.state.page}`);
   }
 
-  nextPage(i: Communities) { 
+  nextPage(i: Communities) {
     i.state.page++;
     i.setState(i.state);
     i.updateUrl();
     i.refetch();
   }
 
-  prevPage(i: Communities) { 
+  prevPage(i: Communities) {
     i.state.page--;
     i.setState(i.state);
     i.updateUrl();
@@ -139,7 +211,7 @@ export class Communities extends Component<any, CommunitiesState> {
   handleUnsubscribe(communityId: number) {
     let form: FollowCommunityForm = {
       community_id: communityId,
-      follow: false
+      follow: false,
     };
     WebSocketService.Instance.followCommunity(form);
   }
@@ -147,7 +219,7 @@ export class Communities extends Component<any, CommunitiesState> {
   handleSubscribe(communityId: number) {
     let form: FollowCommunityForm = {
       community_id: communityId,
-      follow: true
+      follow: true,
     };
     WebSocketService.Instance.followCommunity(form);
   }
@@ -157,10 +229,9 @@ export class Communities extends Component<any, CommunitiesState> {
       sort: SortType[SortType.TopAll],
       limit: 100,
       page: this.state.page,
-    }
+    };
 
     WebSocketService.Instance.listCommunities(listCommunitiesForm);
-
   }
 
   parseMessage(msg: any) {
@@ -172,9 +243,11 @@ export class Communities extends Component<any, CommunitiesState> {
     } else if (op == UserOperation.ListCommunities) {
       let res: ListCommunitiesResponse = msg;
       this.state.communities = res.communities;
-      this.state.communities.sort((a, b) => b.number_of_subscribers - a.number_of_subscribers);
+      this.state.communities.sort(
+        (a, b) => b.number_of_subscribers - a.number_of_subscribers
+      );
       this.state.loading = false;
-      window.scrollTo(0,0);
+      window.scrollTo(0, 0);
       this.setState(this.state);
       let table = document.querySelector('#community_table');
       Sortable.initTable(table);
@@ -184,6 +257,6 @@ export class Communities extends Component<any, CommunitiesState> {
       found.subscribed = res.community.subscribed;
       found.number_of_subscribers = res.community.number_of_subscribers;
       this.setState(this.state);
-    } 
+    }
   }
 }
index 833d8a3f0acf3aaeefcbe3352142abb5b6cd8570..e6c8ef0924f7cc8231f179c1f54d5680a1ff32ac 100644 (file)
@@ -1,7 +1,13 @@
 import { Component, linkEvent } from 'inferno';
-import { Subscription } from "rxjs";
+import { Subscription } from 'rxjs';
 import { retryWhen, delay, take } from 'rxjs/operators';
-import { CommunityForm as CommunityFormI, UserOperation, Category, ListCategoriesResponse, CommunityResponse } from '../interfaces';
+import {
+  CommunityForm as CommunityFormI,
+  UserOperation,
+  Category,
+  ListCategoriesResponse,
+  CommunityResponse,
+} from '../interfaces';
 import { WebSocketService } from '../services';
 import { msgOp, capitalizeFirstLetter } from '../utils';
 import * as autosize from 'autosize';
@@ -23,7 +29,10 @@ interface CommunityFormState {
   loading: boolean;
 }
 
-export class CommunityForm extends Component<CommunityFormProps, CommunityFormState> {
+export class CommunityForm extends Component<
+  CommunityFormProps,
+  CommunityFormState
+> {
   private subscription: Subscription;
 
   private emptyState: CommunityFormState = {
@@ -34,8 +43,8 @@ export class CommunityForm extends Component<CommunityFormProps, CommunityFormSt
       nsfw: false,
     },
     categories: [],
-    loading: false
-  }
+    loading: false,
+  };
 
   constructor(props: any, context: any) {
     super(props, context);
@@ -50,16 +59,23 @@ export class CommunityForm extends Component<CommunityFormProps, CommunityFormSt
         description: this.props.community.description,
         edit_id: this.props.community.id,
         nsfw: this.props.community.nsfw,
-        auth: null
-      }
+        auth: null,
+      };
     }
 
     this.subscription = WebSocketService.Instance.subject
-      .pipe(retryWhen(errors => errors.pipe(delay(3000), take(10))))
+      .pipe(
+        retryWhen(errors =>
+          errors.pipe(
+            delay(3000),
+            take(10)
+          )
+        )
+      )
       .subscribe(
-        (msg) => this.parseMessage(msg),
-        (err) => console.error(err),
-        () => console.log("complete")
+        msg => this.parseMessage(msg),
+        err => console.error(err),
+        () => console.log('complete')
       );
 
     WebSocketService.Instance.listCategories();
@@ -73,53 +89,110 @@ export class CommunityForm extends Component<CommunityFormProps, CommunityFormSt
     this.subscription.unsubscribe();
   }
 
-
   render() {
     return (
       <form onSubmit={linkEvent(this, this.handleCreateCommunitySubmit)}>
         <div class="form-group row">
-          <label class="col-12 col-form-label"><T i18nKey="name">#</T></label>
+          <label class="col-12 col-form-label">
+            <T i18nKey="name">#</T>
+          </label>
           <div class="col-12">
-            <input type="text" class="form-control" value={this.state.communityForm.name} onInput={linkEvent(this, this.handleCommunityNameChange)} required minLength={3} maxLength={20} pattern="[a-z0-9_]+" title={i18n.t('community_reqs')}/>
+            <input
+              type="text"
+              class="form-control"
+              value={this.state.communityForm.name}
+              onInput={linkEvent(this, this.handleCommunityNameChange)}
+              required
+              minLength={3}
+              maxLength={20}
+              pattern="[a-z0-9_]+"
+              title={i18n.t('community_reqs')}
+            />
           </div>
         </div>
         <div class="form-group row">
-          <label class="col-12 col-form-label"><T i18nKey="title">#</T></label>
+          <label class="col-12 col-form-label">
+            <T i18nKey="title">#</T>
+          </label>
           <div class="col-12">
-            <input type="text" value={this.state.communityForm.title} onInput={linkEvent(this, this.handleCommunityTitleChange)} class="form-control" required minLength={3} maxLength={100} />
+            <input
+              type="text"
+              value={this.state.communityForm.title}
+              onInput={linkEvent(this, this.handleCommunityTitleChange)}
+              class="form-control"
+              required
+              minLength={3}
+              maxLength={100}
+            />
           </div>
         </div>
         <div class="form-group row">
-          <label class="col-12 col-form-label"><T i18nKey="sidebar">#</T></label>
+          <label class="col-12 col-form-label">
+            <T i18nKey="sidebar">#</T>
+          </label>
           <div class="col-12">
-            <textarea value={this.state.communityForm.description} onInput={linkEvent(this, this.handleCommunityDescriptionChange)} class="form-control" rows={3} maxLength={10000} />
+            <textarea
+              value={this.state.communityForm.description}
+              onInput={linkEvent(this, this.handleCommunityDescriptionChange)}
+              class="form-control"
+              rows={3}
+              maxLength={10000}
+            />
           </div>
         </div>
         <div class="form-group row">
-          <label class="col-12 col-form-label"><T i18nKey="category">#</T></label>
+          <label class="col-12 col-form-label">
+            <T i18nKey="category">#</T>
+          </label>
           <div class="col-12">
-            <select class="form-control" value={this.state.communityForm.category_id} onInput={linkEvent(this, this.handleCommunityCategoryChange)}>
-              {this.state.categories.map(category =>
+            <select
+              class="form-control"
+              value={this.state.communityForm.category_id}
+              onInput={linkEvent(this, this.handleCommunityCategoryChange)}
+            >
+              {this.state.categories.map(category => (
                 <option value={category.id}>{category.name}</option>
-              )}
+              ))}
             </select>
           </div>
         </div>
         <div class="form-group row">
           <div class="col-12">
             <div class="form-check">
-              <input class="form-check-input" type="checkbox" checked={this.state.communityForm.nsfw} onChange={linkEvent(this, this.handleCommunityNsfwChange)}/>
-              <label class="form-check-label"><T i18nKey="nsfw">#</T></label>
+              <input
+                class="form-check-input"
+                type="checkbox"
+                checked={this.state.communityForm.nsfw}
+                onChange={linkEvent(this, this.handleCommunityNsfwChange)}
+              />
+              <label class="form-check-label">
+                <T i18nKey="nsfw">#</T>
+              </label>
             </div>
           </div>
         </div>
         <div class="form-group row">
           <div class="col-12">
             <button type="submit" class="btn btn-secondary mr-2">
-              {this.state.loading ? 
-              <svg class="icon icon-spinner spin"><use xlinkHref="#icon-spinner"></use></svg> : 
-              this.props.community ? capitalizeFirstLetter(i18n.t('save')) : capitalizeFirstLetter(i18n.t('create'))}</button>
-              {this.props.community && <button type="button" class="btn btn-secondary" onClick={linkEvent(this, this.handleCancel)}><T i18nKey="cancel">#</T></button>}
+              {this.state.loading ? (
+                <svg class="icon icon-spinner spin">
+                  <use xlinkHref="#icon-spinner"></use>
+                </svg>
+              ) : this.props.community ? (
+                capitalizeFirstLetter(i18n.t('save'))
+              ) : (
+                capitalizeFirstLetter(i18n.t('create'))
+              )}
+            </button>
+            {this.props.community && (
+              <button
+                type="button"
+                class="btn btn-secondary"
+                onClick={linkEvent(this, this.handleCancel)}
+              >
+                <T i18nKey="cancel">#</T>
+              </button>
+            )}
           </div>
         </div>
       </form>
@@ -174,7 +247,7 @@ export class CommunityForm extends Component<CommunityFormProps, CommunityFormSt
       this.state.loading = false;
       this.setState(this.state);
       return;
-    } else if (op == UserOperation.ListCategories){
+    } else if (op == UserOperation.ListCategories) {
       let res: ListCategoriesResponse = msg;
       this.state.categories = res.categories;
       if (!this.props.community) {
@@ -185,7 +258,7 @@ export class CommunityForm extends Component<CommunityFormProps, CommunityFormSt
       let res: CommunityResponse = msg;
       this.state.loading = false;
       this.props.onCreate(res.community);
-    } 
+    }
     // TODO is ths necessary
     else if (op == UserOperation.EditCommunity) {
       let res: CommunityResponse = msg;
@@ -193,5 +266,4 @@ export class CommunityForm extends Component<CommunityFormProps, CommunityFormSt
       this.props.onEdit(res.community);
     }
   }
-
 }
index 580e9a498da230708d83c145d7a37b70db0dbb86..434f45305f9eda66dd255fc42a648cfce1fcd440 100644 (file)
@@ -1,11 +1,29 @@
 import { Component, linkEvent } from 'inferno';
-import { Subscription } from "rxjs";
+import { Subscription } from 'rxjs';
 import { retryWhen, delay, take } from 'rxjs/operators';
-import { UserOperation, Community as CommunityI, GetCommunityResponse, CommunityResponse,  CommunityUser, UserView, SortType, Post, GetPostsForm, ListingType, GetPostsResponse, CreatePostLikeResponse } from '../interfaces';
+import {
+  UserOperation,
+  Community as CommunityI,
+  GetCommunityResponse,
+  CommunityResponse,
+  CommunityUser,
+  UserView,
+  SortType,
+  Post,
+  GetPostsForm,
+  ListingType,
+  GetPostsResponse,
+  CreatePostLikeResponse,
+} from '../interfaces';
 import { WebSocketService } from '../services';
 import { PostListings } from './post-listings';
 import { Sidebar } from './sidebar';
-import { msgOp, routeSortTypeToEnum, fetchLimit, postRefetchSeconds } from '../utils';
+import {
+  msgOp,
+  routeSortTypeToEnum,
+  fetchLimit,
+  postRefetchSeconds,
+} from '../utils';
 import { T, i18n } from 'inferno-i18next';
 
 interface State {
@@ -21,7 +39,6 @@ interface State {
 }
 
 export class Community extends Component<any, State> {
-
   private subscription: Subscription;
   private postFetcher: any;
   private emptyState: State = {
@@ -49,16 +66,16 @@ export class Community extends Component<any, State> {
     posts: [],
     sort: this.getSortTypeFromProps(this.props),
     page: this.getPageFromProps(this.props),
-  }
+  };
 
   getSortTypeFromProps(props: any): SortType {
-    return (props.match.params.sort) ? 
-      routeSortTypeToEnum(props.match.params.sort) : 
-      SortType.Hot;
+    return props.match.params.sort
+      ? routeSortTypeToEnum(props.match.params.sort)
+      SortType.Hot;
   }
 
   getPageFromProps(props: any): number {
-    return (props.match.params.page) ? Number(props.match.params.page) : 1;
+    return props.match.params.page ? Number(props.match.params.page) : 1;
   }
 
   constructor(props: any, context: any) {
@@ -67,19 +84,25 @@ export class Community extends Component<any, State> {
     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),
+      .pipe(
+        retryWhen(errors =>
+          errors.pipe(
+            delay(3000),
+            take(10)
+          )
+        )
+      )
+      .subscribe(
+        msg => this.parseMessage(msg),
+        err => console.error(err),
         () => console.log('complete')
-    );
+      );
 
     if (this.state.communityId) {
       WebSocketService.Instance.getCommunity(this.state.communityId);
     } else if (this.state.communityName) {
       WebSocketService.Instance.getCommunityByName(this.state.communityName);
     }
-
   }
 
   componentWillUnmount() {
@@ -100,78 +123,118 @@ export class Community extends Component<any, State> {
   render() {
     return (
       <div class="container">
-        {this.state.loading ? 
-        <h5><svg class="icon icon-spinner spin"><use xlinkHref="#icon-spinner"></use></svg></h5> : 
-        <div class="row">
-          <div class="col-12 col-md-8">
-            <h5>{this.state.community.title}
-            {this.state.community.removed &&
-              <small className="ml-2 text-muted font-italic"><T i18nKey="removed">#</T></small>
-            }
-            {this.state.community.nsfw &&
-              <small className="ml-2 text-muted font-italic"><T i18nKey="nsfw">#</T></small>
-            }
+        {this.state.loading ? (
+          <h5>
+            <svg class="icon icon-spinner spin">
+              <use xlinkHref="#icon-spinner"></use>
+            </svg>
           </h5>
-          {this.selects()}
-          <PostListings posts={this.state.posts} />
-          {this.paginator()}
-          </div>
-          <div class="col-12 col-md-4">
-            <Sidebar 
-              community={this.state.community} 
-              moderators={this.state.moderators} 
-              admins={this.state.admins}
-            />
+        ) : (
+          <div class="row">
+            <div class="col-12 col-md-8">
+              <h5>
+                {this.state.community.title}
+                {this.state.community.removed && (
+                  <small className="ml-2 text-muted font-italic">
+                    <T i18nKey="removed">#</T>
+                  </small>
+                )}
+                {this.state.community.nsfw && (
+                  <small className="ml-2 text-muted font-italic">
+                    <T i18nKey="nsfw">#</T>
+                  </small>
+                )}
+              </h5>
+              {this.selects()}
+              <PostListings posts={this.state.posts} />
+              {this.paginator()}
+            </div>
+            <div class="col-12 col-md-4">
+              <Sidebar
+                community={this.state.community}
+                moderators={this.state.moderators}
+                admins={this.state.admins}
+              />
+            </div>
           </div>
-        </div>
-        }
+        )}
       </div>
-    )
+    );
   }
 
   selects() {
     return (
       <div className="mb-2">
-        <select value={this.state.sort} onChange={linkEvent(this, this.handleSortChange)} class="custom-select custom-select-sm w-auto">
-          <option disabled><T i18nKey="sort_type">#</T></option>
-          <option value={SortType.Hot}><T i18nKey="hot">#</T></option>
-          <option value={SortType.New}><T i18nKey="new">#</T></option>
+        <select
+          value={this.state.sort}
+          onChange={linkEvent(this, this.handleSortChange)}
+          class="custom-select custom-select-sm w-auto"
+        >
+          <option disabled>
+            <T i18nKey="sort_type">#</T>
+          </option>
+          <option value={SortType.Hot}>
+            <T i18nKey="hot">#</T>
+          </option>
+          <option value={SortType.New}>
+            <T i18nKey="new">#</T>
+          </option>
           <option disabled>──────</option>
-          <option value={SortType.TopDay}><T i18nKey="top_day">#</T></option>
-          <option value={SortType.TopWeek}><T i18nKey="week">#</T></option>
-          <option value={SortType.TopMonth}><T i18nKey="month">#</T></option>
-          <option value={SortType.TopYear}><T i18nKey="year">#</T></option>
-          <option value={SortType.TopAll}><T i18nKey="all">#</T></option>
+          <option value={SortType.TopDay}>
+            <T i18nKey="top_day">#</T>
+          </option>
+          <option value={SortType.TopWeek}>
+            <T i18nKey="week">#</T>
+          </option>
+          <option value={SortType.TopMonth}>
+            <T i18nKey="month">#</T>
+          </option>
+          <option value={SortType.TopYear}>
+            <T i18nKey="year">#</T>
+          </option>
+          <option value={SortType.TopAll}>
+            <T i18nKey="all">#</T>
+          </option>
         </select>
       </div>
-    )
+    );
   }
 
   paginator() {
     return (
       <div class="my-2">
-        {this.state.page > 1 && 
-          <button class="btn btn-sm btn-secondary mr-1" onClick={linkEvent(this, this.prevPage)}><T i18nKey="prev">#</T></button>
-        }
-        <button class="btn btn-sm btn-secondary" onClick={linkEvent(this, this.nextPage)}><T i18nKey="next">#</T></button>
+        {this.state.page > 1 && (
+          <button
+            class="btn btn-sm btn-secondary mr-1"
+            onClick={linkEvent(this, this.prevPage)}
+          >
+            <T i18nKey="prev">#</T>
+          </button>
+        )}
+        <button
+          class="btn btn-sm btn-secondary"
+          onClick={linkEvent(this, this.nextPage)}
+        >
+          <T i18nKey="next">#</T>
+        </button>
       </div>
     );
   }
 
-  nextPage(i: Community) { 
+  nextPage(i: Community) {
     i.state.page++;
     i.setState(i.state);
     i.updateUrl();
     i.fetchPosts();
-    window.scrollTo(0,0);
+    window.scrollTo(0, 0);
   }
 
-  prevPage(i: Community) { 
+  prevPage(i: Community) {
     i.state.page--;
     i.setState(i.state);
     i.updateUrl();
     i.fetchPosts();
-    window.scrollTo(0,0);
+    window.scrollTo(0, 0);
   }
 
   handleSortChange(i: Community, event: any) {
@@ -180,12 +243,14 @@ export class Community extends Component<any, State> {
     i.setState(i.state);
     i.updateUrl();
     i.fetchPosts();
-    window.scrollTo(0,0);
+    window.scrollTo(0, 0);
   }
 
   updateUrl() {
     let sortStr = SortType[this.state.sort].toLowerCase();
-    this.props.history.push(`/c/${this.state.community.name}/sort/${sortStr}/page/${this.state.page}`);
+    this.props.history.push(
+      `/c/${this.state.community.name}/sort/${sortStr}/page/${this.state.page}`
+    );
   }
 
   keepFetchingPosts() {
@@ -200,7 +265,7 @@ export class Community extends Component<any, State> {
       sort: SortType[this.state.sort],
       type_: ListingType[ListingType.Community],
       community_id: this.state.community.id,
-    }
+    };
     WebSocketService.Instance.getPosts(getPostsForm);
   }
 
@@ -225,7 +290,8 @@ export class Community extends Component<any, State> {
     } else if (op == UserOperation.FollowCommunity) {
       let res: CommunityResponse = msg;
       this.state.community.subscribed = res.community.subscribed;
-      this.state.community.number_of_subscribers = res.community.number_of_subscribers;
+      this.state.community.number_of_subscribers =
+        res.community.number_of_subscribers;
       this.setState(this.state);
     } else if (op == UserOperation.GetPosts) {
       let res: GetPostsResponse = msg;
@@ -243,4 +309,3 @@ export class Community extends Component<any, State> {
     }
   }
 }
-
index 61245e739f659fdc2d38ebbe1e74c5d01538eb5f..f16b64259ccf5c183756cafad9917ddfeffb7737 100644 (file)
@@ -6,14 +6,15 @@ import { i18n } from '../i18next';
 import { T } from 'inferno-i18next';
 
 export class CreateCommunity extends Component<any, any> {
-
   constructor(props: any, context: any) {
     super(props, context);
     this.handleCommunityCreate = this.handleCommunityCreate.bind(this);
   }
 
   componentDidMount() {
-    document.title = `${i18n.t('create_community')} - ${WebSocketService.Instance.site.name}`;
+    document.title = `${i18n.t('create_community')} - ${
+      WebSocketService.Instance.site.name
+    }`;
   }
 
   render() {
@@ -21,17 +22,17 @@ export class CreateCommunity extends Component<any, any> {
       <div class="container">
         <div class="row">
           <div class="col-12 col-lg-6 offset-lg-3 mb-4">
-            <h5><T i18nKey="create_community">#</T></h5>
-            <CommunityForm onCreate={this.handleCommunityCreate}/>
+            <h5>
+              <T i18nKey="create_community">#</T>
+            </h5>
+            <CommunityForm onCreate={this.handleCommunityCreate} />
           </div>
         </div>
       </div>
-    )
+    );
   }
 
   handleCommunityCreate(community: Community) {
     this.props.history.push(`/c/${community.name}`);
   }
 }
-
-
index 3e00bd80af9020510e0092833fd77201de40b635..eeb9bc6c886819648a78c8bbbca9b9a5e9ab361a 100644 (file)
@@ -6,14 +6,15 @@ import { i18n } from '../i18next';
 import { T } from 'inferno-i18next';
 
 export class CreatePost extends Component<any, any> {
-
   constructor(props: any, context: any) {
     super(props, context);
     this.handlePostCreate = this.handlePostCreate.bind(this);
   }
 
   componentDidMount() {
-    document.title = `${i18n.t('create_post')} - ${WebSocketService.Instance.site.name}`;
+    document.title = `${i18n.t('create_post')} - ${
+      WebSocketService.Instance.site.name
+    }`;
   }
 
   render() {
@@ -21,21 +22,23 @@ export class CreatePost extends Component<any, any> {
       <div class="container">
         <div class="row">
           <div class="col-12 col-lg-6 offset-lg-3 mb-4">
-            <h5><T i18nKey="create_post">#</T></h5>
+            <h5>
+              <T i18nKey="create_post">#</T>
+            </h5>
             <PostForm onCreate={this.handlePostCreate} params={this.params} />
           </div>
         </div>
       </div>
-    )
+    );
   }
 
   get params(): PostFormParams {
     let urlParams = new URLSearchParams(this.props.location.search);
     let params: PostFormParams = {
-      name: urlParams.get("name"),
-      community: urlParams.get("community") || this.prevCommunityName,
-      body: urlParams.get("body"),
-      url: urlParams.get("url"),
+      name: urlParams.get('name'),
+      community: urlParams.get('community') || this.prevCommunityName,
+      body: urlParams.get('body'),
+      url: urlParams.get('url'),
     };
 
     return params;
@@ -46,9 +49,9 @@ export class CreatePost extends Component<any, any> {
       return this.props.match.params.name;
     } else if (this.props.location.state) {
       let lastLocation = this.props.location.state.prevPath;
-      if (lastLocation.includes("/c/")) {
-        return lastLocation.split("/c/")[1];
-      }    
+      if (lastLocation.includes('/c/')) {
+        return lastLocation.split('/c/')[1];
+      }
     }
     return undefined;
   }
@@ -57,5 +60,3 @@ export class CreatePost extends Component<any, any> {
     this.props.history.push(`/post/${id}`);
   }
 }
-
-
index 2d607ae9838507ad2510f9d6976cad65302b8cfa..237830dd9dd64af56b3469860d426f044f37deb8 100644 (file)
@@ -5,8 +5,6 @@ import { version } from '../version';
 import { T } from 'inferno-i18next';
 
 export class Footer extends Component<any, any> {
-
-
   constructor(props: any, context: any) {
     super(props, context);
   }
@@ -20,16 +18,24 @@ export class Footer extends Component<any, any> {
               <span class="navbar-text">{version}</span>
             </li>
             <li class="nav-item">
-              <Link class="nav-link" to="/modlog"><T i18nKey="modlog">#</T></Link>
+              <Link class="nav-link" to="/modlog">
+                <T i18nKey="modlog">#</T>
+              </Link>
             </li>
             <li class="nav-item">
-              <a class="nav-link" href={`${repoUrl}/blob/master/docs/api.md`}><T i18nKey="api">#</T></a>
+              <a class="nav-link" href={`${repoUrl}/blob/master/docs/api.md`}>
+                <T i18nKey="api">#</T>
+              </a>
             </li>
             <li class="nav-item">
-              <Link class="nav-link" to="/sponsors"><T i18nKey="sponsors">#</T></Link>
+              <Link class="nav-link" to="/sponsors">
+                <T i18nKey="sponsors">#</T>
+              </Link>
             </li>
             <li class="nav-item">
-              <a class="nav-link" href={repoUrl}><T i18nKey="code">#</T></a>
+              <a class="nav-link" href={repoUrl}>
+                <T i18nKey="code">#</T>
+              </a>
             </li>
           </ul>
         </div>
@@ -37,4 +43,3 @@ export class Footer extends Component<any, any> {
     );
   }
 }
-
index c9f46b36af6521c97a59e9ccb15acf010cf36115..9d548f8d43803e8c3abc355b2c3a18acc17896d2 100644 (file)
@@ -1,8 +1,15 @@
 import { Component, linkEvent } from 'inferno';
 import { Link } from 'inferno-router';
-import { Subscription } from "rxjs";
+import { Subscription } from 'rxjs';
 import { retryWhen, delay, take } from 'rxjs/operators';
-import { UserOperation, Comment, SortType, GetRepliesForm, GetRepliesResponse, CommentResponse } from '../interfaces';
+import {
+  UserOperation,
+  Comment,
+  SortType,
+  GetRepliesForm,
+  GetRepliesResponse,
+  CommentResponse,
+} from '../interfaces';
 import { WebSocketService, UserService } from '../services';
 import { msgOp } from '../utils';
 import { CommentNodes } from './comment-nodes';
@@ -10,7 +17,8 @@ import { i18n } from '../i18next';
 import { T } from 'inferno-i18next';
 
 enum UnreadType {
-  Unread, All
+  Unread,
+  All,
 }
 
 interface InboxState {
@@ -21,14 +29,13 @@ interface InboxState {
 }
 
 export class Inbox extends Component<any, InboxState> {
-
   private subscription: Subscription;
   private emptyState: InboxState = {
     unreadType: UnreadType.Unread,
     replies: [],
     sort: SortType.New,
     page: 1,
-  }
+  };
 
   constructor(props: any, context: any) {
     super(props, context);
@@ -36,12 +43,19 @@ export class Inbox extends Component<any, InboxState> {
     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),
+      .pipe(
+        retryWhen(errors =>
+          errors.pipe(
+            delay(3000),
+            take(10)
+          )
+        )
+      )
+      .subscribe(
+        msg => this.parseMessage(msg),
+        err => console.error(err),
         () => console.log('complete')
-    );
+      );
 
     this.refetch();
   }
@@ -51,7 +65,9 @@ export class Inbox extends Component<any, InboxState> {
   }
 
   componentDidMount() {
-    document.title = `/u/${UserService.Instance.user.username} ${i18n.t('inbox')} - ${WebSocketService.Instance.site.name}`;
+    document.title = `/u/${UserService.Instance.user.username} ${i18n.t(
+      'inbox'
+    )} - ${WebSocketService.Instance.site.name}`;
   }
 
   render() {
@@ -61,52 +77,86 @@ export class Inbox extends Component<any, InboxState> {
         <div class="row">
           <div class="col-12">
             <h5 class="mb-0">
-              <span><T i18nKey="inbox_for" interpolation={{user: user.username}}>#<Link to={`/u/${user.username}`}>#</Link></T></span>
+              <span>
+                <T i18nKey="inbox_for" interpolation={{ user: user.username }}>
+                  #<Link to={`/u/${user.username}`}>#</Link>
+                </T>
+              </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}><T i18nKey="mark_all_as_read">#</T></span>
-                </li>
-              </ul>
-            }
+            {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}>
+                      <T i18nKey="mark_all_as_read">#</T>
+                    </span>
+                  </li>
+                </ul>
+              )}
             {this.selects()}
             {this.replies()}
             {this.paginator()}
           </div>
         </div>
       </div>
-    )
+    );
   }
 
   selects() {
     return (
       <div className="mb-2">
-        <select value={this.state.unreadType} onChange={linkEvent(this, this.handleUnreadTypeChange)} class="custom-select custom-select-sm w-auto">
-          <option disabled><T i18nKey="type">#</T></option>
-          <option value={UnreadType.Unread}><T i18nKey="unread">#</T></option>
-          <option value={UnreadType.All}><T i18nKey="all">#</T></option>
+        <select
+          value={this.state.unreadType}
+          onChange={linkEvent(this, this.handleUnreadTypeChange)}
+          class="custom-select custom-select-sm w-auto"
+        >
+          <option disabled>
+            <T i18nKey="type">#</T>
+          </option>
+          <option value={UnreadType.Unread}>
+            <T i18nKey="unread">#</T>
+          </option>
+          <option value={UnreadType.All}>
+            <T i18nKey="all">#</T>
+          </option>
         </select>
-        <select value={this.state.sort} onChange={linkEvent(this, this.handleSortChange)} class="custom-select custom-select-sm w-auto ml-2">
-          <option disabled><T i18nKey="sort_type">#</T></option>
-          <option value={SortType.New}><T i18nKey="new">#</T></option>
-          <option value={SortType.TopDay}><T i18nKey="top_day">#</T></option>
-          <option value={SortType.TopWeek}><T i18nKey="week">#</T></option>
-          <option value={SortType.TopMonth}><T i18nKey="month">#</T></option>
-          <option value={SortType.TopYear}><T i18nKey="year">#</T></option>
-          <option value={SortType.TopAll}><T i18nKey="all">#</T></option>
+        <select
+          value={this.state.sort}
+          onChange={linkEvent(this, this.handleSortChange)}
+          class="custom-select custom-select-sm w-auto ml-2"
+        >
+          <option disabled>
+            <T i18nKey="sort_type">#</T>
+          </option>
+          <option value={SortType.New}>
+            <T i18nKey="new">#</T>
+          </option>
+          <option value={SortType.TopDay}>
+            <T i18nKey="top_day">#</T>
+          </option>
+          <option value={SortType.TopWeek}>
+            <T i18nKey="week">#</T>
+          </option>
+          <option value={SortType.TopMonth}>
+            <T i18nKey="month">#</T>
+          </option>
+          <option value={SortType.TopYear}>
+            <T i18nKey="year">#</T>
+          </option>
+          <option value={SortType.TopAll}>
+            <T i18nKey="all">#</T>
+          </option>
         </select>
       </div>
-    )
-
+    );
   }
 
   replies() {
     return (
       <div>
-        {this.state.replies.map(reply => 
-          <CommentNodes nodes={[{comment: reply}]} noIndent markable />
-        )}
+        {this.state.replies.map(reply => (
+          <CommentNodes nodes={[{ comment: reply }]} noIndent markable />
+        ))}
       </div>
     );
   }
@@ -114,21 +164,31 @@ export class Inbox extends Component<any, InboxState> {
   paginator() {
     return (
       <div class="mt-2">
-        {this.state.page > 1 && 
-          <button class="btn btn-sm btn-secondary mr-1" onClick={linkEvent(this, this.prevPage)}><T i18nKey="prev">#</T></button>
-        }
-        <button class="btn btn-sm btn-secondary" onClick={linkEvent(this, this.nextPage)}><T i18nKey="next">#</T></button>
+        {this.state.page > 1 && (
+          <button
+            class="btn btn-sm btn-secondary mr-1"
+            onClick={linkEvent(this, this.prevPage)}
+          >
+            <T i18nKey="prev">#</T>
+          </button>
+        )}
+        <button
+          class="btn btn-sm btn-secondary"
+          onClick={linkEvent(this, this.nextPage)}
+        >
+          <T i18nKey="next">#</T>
+        </button>
       </div>
     );
   }
 
-  nextPage(i: Inbox) { 
+  nextPage(i: Inbox) {
     i.state.page++;
     i.setState(i.state);
     i.refetch();
   }
 
-  prevPage(i: Inbox) { 
+  prevPage(i: Inbox) {
     i.state.page--;
     i.setState(i.state);
     i.refetch();
@@ -144,7 +204,7 @@ export class Inbox extends Component<any, InboxState> {
   refetch() {
     let form: GetRepliesForm = {
       sort: SortType[this.state.sort],
-      unread_only: (this.state.unreadType == UnreadType.Unread),
+      unread_only: this.state.unreadType == UnreadType.Unread,
       page: this.state.page,
       limit: 9999,
     };
@@ -168,11 +228,14 @@ export class Inbox extends Component<any, InboxState> {
     if (msg.error) {
       alert(i18n.t(msg.error));
       return;
-    } else if (op == UserOperation.GetReplies || op == UserOperation.MarkAllAsRead) {
+    } else if (
+      op == UserOperation.GetReplies ||
+      op == UserOperation.MarkAllAsRead
+    ) {
       let res: GetRepliesResponse = msg;
       this.state.replies = res.replies;
       this.sendRepliesCount();
-      window.scrollTo(0,0);
+      window.scrollTo(0, 0);
       this.setState(this.state);
     } else if (op == UserOperation.EditComment) {
       let res: CommentResponse = msg;
@@ -188,7 +251,9 @@ export class Inbox extends Component<any, InboxState> {
 
       // If youre in the unread view, just remove it from the list
       if (this.state.unreadType == UnreadType.Unread && res.comment.read) {
-        this.state.replies = this.state.replies.filter(r => r.id !== res.comment.id);
+        this.state.replies = this.state.replies.filter(
+          r => r.id !== res.comment.id
+        );
       } else {
         let found = this.state.replies.find(c => c.id == res.comment.id);
         found.read = res.comment.read;
@@ -208,18 +273,21 @@ export class Inbox extends Component<any, InboxState> {
       this.setState(this.state);
     } else if (op == UserOperation.CreateCommentLike) {
       let res: CommentResponse = msg;
-      let found: Comment = this.state.replies.find(c => c.id === res.comment.id);
+      let found: Comment = this.state.replies.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;
+      if (res.comment.my_vote !== null) found.my_vote = res.comment.my_vote;
       this.setState(this.state);
     }
   }
 
   sendRepliesCount() {
-    UserService.Instance.sub.next({user: UserService.Instance.user, unreadCount: this.state.replies.filter(r => !r.read).length});
+    UserService.Instance.sub.next({
+      user: UserService.Instance.user,
+      unreadCount: this.state.replies.filter(r => !r.read).length,
+    });
   }
 }
-
index 66962accf113520215e0c5487b8e3514124da029..87fa39fe7cf4362435e18332a9f27bfb13641ea7 100644 (file)
@@ -1,7 +1,12 @@
 import { Component, linkEvent } from 'inferno';
-import { Subscription } from "rxjs";
+import { Subscription } from 'rxjs';
 import { retryWhen, delay, take } from 'rxjs/operators';
-import { LoginForm, RegisterForm, LoginResponse, UserOperation } from '../interfaces';
+import {
+  LoginForm,
+  RegisterForm,
+  LoginResponse,
+  UserOperation,
+} from '../interfaces';
 import { WebSocketService, UserService } from '../services';
 import { msgOp } from '../utils';
 import { i18n } from '../i18next';
@@ -14,14 +19,13 @@ interface State {
   registerLoading: boolean;
 }
 
-
 export class Login extends Component<any, State> {
   private subscription: Subscription;
 
   emptyState: State = {
     loginForm: {
       username_or_email: undefined,
-      password: undefined
+      password: undefined,
     },
     registerForm: {
       username: undefined,
@@ -32,7 +36,7 @@ export class Login extends Component<any, State> {
     },
     loginLoading: false,
     registerLoading: false,
-  }
+  };
 
   constructor(props: any, context: any) {
     super(props, context);
@@ -40,12 +44,19 @@ export class Login extends Component<any, State> {
     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")
-    );
+      .pipe(
+        retryWhen(errors =>
+          errors.pipe(
+            delay(3000),
+            take(10)
+          )
+        )
+      )
+      .subscribe(
+        msg => this.parseMessage(msg),
+        err => console.error(err),
+        () => console.log('complete')
+      );
   }
 
   componentWillUnmount() {
@@ -53,22 +64,20 @@ export class Login extends Component<any, State> {
   }
 
   componentDidMount() {
-    document.title = `${i18n.t('login')} - ${WebSocketService.Instance.site.name}`;
+    document.title = `${i18n.t('login')} - ${
+      WebSocketService.Instance.site.name
+    }`;
   }
 
   render() {
     return (
       <div class="container">
         <div class="row">
-          <div class="col-12 col-lg-6 mb-4">
-            {this.loginForm()}
-          </div>
-          <div class="col-12 col-lg-6">
-            {this.registerForm()}
-          </div>
+          <div class="col-12 col-lg-6 mb-4">{this.loginForm()}</div>
+          <div class="col-12 col-lg-6">{this.registerForm()}</div>
         </div>
       </div>
-    )
+    );
   }
 
   loginForm() {
@@ -77,21 +86,45 @@ export class Login extends Component<any, State> {
         <form onSubmit={linkEvent(this, this.handleLoginSubmit)}>
           <h5>Login</h5>
           <div class="form-group row">
-            <label class="col-sm-2 col-form-label"><T i18nKey="email_or_username">#</T></label>
+            <label class="col-sm-2 col-form-label">
+              <T i18nKey="email_or_username">#</T>
+            </label>
             <div class="col-sm-10">
-              <input type="text" class="form-control" value={this.state.loginForm.username_or_email} onInput={linkEvent(this, this.handleLoginUsernameChange)} required minLength={3} />
+              <input
+                type="text"
+                class="form-control"
+                value={this.state.loginForm.username_or_email}
+                onInput={linkEvent(this, this.handleLoginUsernameChange)}
+                required
+                minLength={3}
+              />
             </div>
           </div>
           <div class="form-group row">
-            <label class="col-sm-2 col-form-label"><T i18nKey="password">#</T></label>
+            <label class="col-sm-2 col-form-label">
+              <T i18nKey="password">#</T>
+            </label>
             <div class="col-sm-10">
-              <input type="password" value={this.state.loginForm.password} onInput={linkEvent(this, this.handleLoginPasswordChange)} class="form-control" required />
+              <input
+                type="password"
+                value={this.state.loginForm.password}
+                onInput={linkEvent(this, this.handleLoginPasswordChange)}
+                class="form-control"
+                required
+              />
             </div>
           </div>
           <div class="form-group row">
             <div class="col-sm-10">
-              <button type="submit" class="btn btn-secondary">{this.state.loginLoading ? 
-              <svg class="icon icon-spinner spin"><use xlinkHref="#icon-spinner"></use></svg> : i18n.t('login')}</button>
+              <button type="submit" class="btn btn-secondary">
+                {this.state.loginLoading ? (
+                  <svg class="icon icon-spinner spin">
+                    <use xlinkHref="#icon-spinner"></use>
+                  </svg>
+                ) : (
+                  i18n.t('login')
+                )}
+              </button>
             </div>
           </div>
         </form>
@@ -101,43 +134,95 @@ export class Login extends Component<any, State> {
   registerForm() {
     return (
       <form onSubmit={linkEvent(this, this.handleRegisterSubmit)}>
-        <h5><T i18nKey="sign_up">#</T></h5>
+        <h5>
+          <T i18nKey="sign_up">#</T>
+        </h5>
         <div class="form-group row">
-          <label class="col-sm-2 col-form-label"><T i18nKey="username">#</T></label>
+          <label class="col-sm-2 col-form-label">
+            <T i18nKey="username">#</T>
+          </label>
           <div class="col-sm-10">
-            <input type="text" class="form-control" value={this.state.registerForm.username} onInput={linkEvent(this, this.handleRegisterUsernameChange)} required minLength={3} maxLength={20} pattern="[a-zA-Z0-9_]+" />
+            <input
+              type="text"
+              class="form-control"
+              value={this.state.registerForm.username}
+              onInput={linkEvent(this, this.handleRegisterUsernameChange)}
+              required
+              minLength={3}
+              maxLength={20}
+              pattern="[a-zA-Z0-9_]+"
+            />
           </div>
         </div>
         <div class="form-group row">
-          <label class="col-sm-2 col-form-label"><T i18nKey="email">#</T></label>
+          <label class="col-sm-2 col-form-label">
+            <T i18nKey="email">#</T>
+          </label>
           <div class="col-sm-10">
-            <input type="email" class="form-control" placeholder={i18n.t('optional')} value={this.state.registerForm.email} onInput={linkEvent(this, this.handleRegisterEmailChange)} minLength={3} />
+            <input
+              type="email"
+              class="form-control"
+              placeholder={i18n.t('optional')}
+              value={this.state.registerForm.email}
+              onInput={linkEvent(this, this.handleRegisterEmailChange)}
+              minLength={3}
+            />
           </div>
         </div>
         <div class="form-group row">
-          <label class="col-sm-2 col-form-label"><T i18nKey="password">#</T></label>
+          <label class="col-sm-2 col-form-label">
+            <T i18nKey="password">#</T>
+          </label>
           <div class="col-sm-10">
-            <input type="password" value={this.state.registerForm.password} onInput={linkEvent(this, this.handleRegisterPasswordChange)} class="form-control" required />
+            <input
+              type="password"
+              value={this.state.registerForm.password}
+              onInput={linkEvent(this, this.handleRegisterPasswordChange)}
+              class="form-control"
+              required
+            />
           </div>
         </div>
         <div class="form-group row">
-          <label class="col-sm-2 col-form-label"><T i18nKey="verify_password">#</T></label>
+          <label class="col-sm-2 col-form-label">
+            <T i18nKey="verify_password">#</T>
+          </label>
           <div class="col-sm-10">
-            <input type="password" value={this.state.registerForm.password_verify} onInput={linkEvent(this, this.handleRegisterPasswordVerifyChange)} class="form-control" required />
+            <input
+              type="password"
+              value={this.state.registerForm.password_verify}
+              onInput={linkEvent(this, this.handleRegisterPasswordVerifyChange)}
+              class="form-control"
+              required
+            />
           </div>
         </div>
         <div class="form-group row">
           <div class="col-sm-10">
             <div class="form-check">
-              <input class="form-check-input" type="checkbox" checked={this.state.registerForm.show_nsfw} onChange={linkEvent(this, this.handleRegisterShowNsfwChange)}/>
-              <label class="form-check-label"><T i18nKey="show_nsfw">#</T></label>
+              <input
+                class="form-check-input"
+                type="checkbox"
+                checked={this.state.registerForm.show_nsfw}
+                onChange={linkEvent(this, this.handleRegisterShowNsfwChange)}
+              />
+              <label class="form-check-label">
+                <T i18nKey="show_nsfw">#</T>
+              </label>
             </div>
           </div>
         </div>
         <div class="form-group row">
           <div class="col-sm-10">
-            <button type="submit" class="btn btn-secondary">{this.state.registerLoading ? 
-            <svg class="icon icon-spinner spin"><use xlinkHref="#icon-spinner"></use></svg> : i18n.t('sign_up')}</button>
+            <button type="submit" class="btn btn-secondary">
+              {this.state.registerLoading ? (
+                <svg class="icon icon-spinner spin">
+                  <use xlinkHref="#icon-spinner"></use>
+                </svg>
+              ) : (
+                i18n.t('sign_up')
+              )}
+            </button>
           </div>
         </div>
       </form>
@@ -217,5 +302,4 @@ export class Login extends Component<any, State> {
       }
     }
   }
-
 }
index 1366c162c8e7064812f49b8a2d1402997ba383e9..b1ddef4cebb948e0d14089b0a5a3160dbbce473f 100644 (file)
@@ -1,12 +1,35 @@
 import { Component, linkEvent } from 'inferno';
 import { Link } from 'inferno-router';
-import { Subscription } from "rxjs";
+import { Subscription } from 'rxjs';
 import { retryWhen, delay, take } from 'rxjs/operators';
-import { UserOperation, CommunityUser, GetFollowedCommunitiesResponse, ListCommunitiesForm, ListCommunitiesResponse, Community, SortType, GetSiteResponse, ListingType, SiteResponse, GetPostsResponse, CreatePostLikeResponse, Post, GetPostsForm } from '../interfaces';
+import {
+  UserOperation,
+  CommunityUser,
+  GetFollowedCommunitiesResponse,
+  ListCommunitiesForm,
+  ListCommunitiesResponse,
+  Community,
+  SortType,
+  GetSiteResponse,
+  ListingType,
+  SiteResponse,
+  GetPostsResponse,
+  CreatePostLikeResponse,
+  Post,
+  GetPostsForm,
+} from '../interfaces';
 import { WebSocketService, UserService } from '../services';
 import { PostListings } from './post-listings';
 import { SiteForm } from './site-form';
-import { msgOp, repoUrl, mdToHtml, fetchLimit, routeSortTypeToEnum, routeListingTypeToEnum, postRefetchSeconds } from '../utils';
+import {
+  msgOp,
+  repoUrl,
+  mdToHtml,
+  fetchLimit,
+  routeSortTypeToEnum,
+  routeListingTypeToEnum,
+  postRefetchSeconds,
+} from '../utils';
 import { i18n } from '../i18next';
 import { T } from 'inferno-i18next';
 
@@ -23,7 +46,6 @@ interface MainState {
 }
 
 export class Main extends Component<any, MainState> {
-
   private subscription: Subscription;
   private postFetcher: any;
   private emptyState: MainState = {
@@ -52,24 +74,24 @@ export class Main extends Component<any, MainState> {
     type_: this.getListingTypeFromProps(this.props),
     sort: this.getSortTypeFromProps(this.props),
     page: this.getPageFromProps(this.props),
-  }
+  };
 
   getListingTypeFromProps(props: any): ListingType {
-    return (props.match.params.type) ? 
-      routeListingTypeToEnum(props.match.params.type) : 
-      UserService.Instance.user ? 
-      ListingType.Subscribed : 
-      ListingType.All;
+    return props.match.params.type
+      ? routeListingTypeToEnum(props.match.params.type)
+      : UserService.Instance.user
+      ? ListingType.Subscribed
+      ListingType.All;
   }
 
   getSortTypeFromProps(props: any): SortType {
-    return (props.match.params.sort) ? 
-      routeSortTypeToEnum(props.match.params.sort) : 
-      SortType.Hot;
+    return props.match.params.sort
+      ? routeSortTypeToEnum(props.match.params.sort)
+      SortType.Hot;
   }
 
   getPageFromProps(props: any): number {
-    return (props.match.params.page) ? Number(props.match.params.page) : 1;
+    return props.match.params.page ? Number(props.match.params.page) : 1;
   }
 
   constructor(props: any, context: any) {
@@ -79,12 +101,19 @@ export class Main extends Component<any, MainState> {
     this.handleEditCancel = this.handleEditCancel.bind(this);
 
     this.subscription = WebSocketService.Instance.subject
-    .pipe(retryWhen(errors => errors.pipe(delay(3000), take(10))))
-    .subscribe(
-      (msg) => this.parseMessage(msg),
-        (err) => console.error(err),
+      .pipe(
+        retryWhen(errors =>
+          errors.pipe(
+            delay(3000),
+            take(10)
+          )
+        )
+      )
+      .subscribe(
+        msg => this.parseMessage(msg),
+        err => console.error(err),
         () => console.log('complete')
-    );
+      );
 
     WebSocketService.Instance.getSite();
 
@@ -94,8 +123,8 @@ export class Main extends Component<any, MainState> {
 
     let listCommunitiesForm: ListCommunitiesForm = {
       sort: SortType[SortType.Hot],
-      limit: 6
-    }
+      limit: 6,
+    };
 
     WebSocketService.Instance.listCommunities(listCommunitiesForm);
 
@@ -109,7 +138,10 @@ export class Main extends Component<any, MainState> {
 
   // Necessary for back button for some reason
   componentWillReceiveProps(nextProps: any) {
-    if (nextProps.history.action == 'POP' || nextProps.history.action == 'PUSH') {
+    if (
+      nextProps.history.action == 'POP' ||
+      nextProps.history.action == 'PUSH'
+    ) {
       this.state.type_ = this.getListingTypeFromProps(nextProps);
       this.state.sort = this.getSortTypeFromProps(nextProps);
       this.state.page = this.getPageFromProps(nextProps);
@@ -122,39 +154,47 @@ export class Main extends Component<any, MainState> {
     return (
       <div class="container">
         <div class="row">
-          <div class="col-12 col-md-8">
-            {this.posts()}
-          </div>
-          <div class="col-12 col-md-4">
-            {this.my_sidebar()}
-          </div>
+          <div class="col-12 col-md-8">{this.posts()}</div>
+          <div class="col-12 col-md-4">{this.my_sidebar()}</div>
         </div>
       </div>
-    )
+    );
   }
-    
+
   my_sidebar() {
-    return(
+    return (
       <div>
-        {!this.state.loading &&
+        {!this.state.loading && (
           <div>
             <div class="card border-secondary mb-3">
               <div class="card-body">
                 {this.trendingCommunities()}
-                {UserService.Instance.user && this.state.subscribedCommunities.length > 0 && 
-                  <div>
-                    <h5>
-                      <T i18nKey="subscribed_to_communities">#<Link class="text-white" to="/communities">#</Link></T>
-                    </h5> 
-                    <ul class="list-inline"> 
-                      {this.state.subscribedCommunities.map(community =>
-                        <li class="list-inline-item"><Link to={`/c/${community.community_name}`}>{community.community_name}</Link></li>
-                      )}
-                    </ul>
-                  </div>
-                }
-                <Link class="btn btn-sm btn-secondary btn-block" 
-                  to="/create_community">
+                {UserService.Instance.user &&
+                  this.state.subscribedCommunities.length > 0 && (
+                    <div>
+                      <h5>
+                        <T i18nKey="subscribed_to_communities">
+                          #
+                          <Link class="text-white" to="/communities">
+                            #
+                          </Link>
+                        </T>
+                      </h5>
+                      <ul class="list-inline">
+                        {this.state.subscribedCommunities.map(community => (
+                          <li class="list-inline-item">
+                            <Link to={`/c/${community.community_name}`}>
+                              {community.community_name}
+                            </Link>
+                          </li>
+                        ))}
+                      </ul>
+                    </div>
+                  )}
+                <Link
+                  class="btn btn-sm btn-secondary btn-block"
+                  to="/create_community"
+                >
                   <T i18nKey="create_a_community">#</T>
                 </Link>
               </div>
@@ -162,44 +202,54 @@ export class Main extends Component<any, MainState> {
             {this.sidebar()}
             {this.landing()}
           </div>
-        }
+        )}
       </div>
-    )
+    );
   }
 
   trendingCommunities() {
     return (
       <div>
         <h5>
-          <T i18nKey="trending_communities">#<Link class="text-white" to="/communities">#</Link></T>
+          <T i18nKey="trending_communities">
+            #
+            <Link class="text-white" to="/communities">
+              #
+            </Link>
+          </T>
         </h5>
-        <ul class="list-inline"> 
-          {this.state.trendingCommunities.map(community =>
-            <li class="list-inline-item"><Link to={`/c/${community.name}`}>{community.name}</Link></li>
-          )}
+        <ul class="list-inline">
+          {this.state.trendingCommunities.map(community => (
+            <li class="list-inline-item">
+              <Link to={`/c/${community.name}`}>{community.name}</Link>
+            </li>
+          ))}
         </ul>
       </div>
-    )
+    );
   }
 
   sidebar() {
     return (
       <div>
-        {!this.state.showEditSite ?
-          this.siteInfo() :
+        {!this.state.showEditSite ? (
+          this.siteInfo()
+        ) : (
           <SiteForm
-            site={this.state.site.site} 
-            onCancel={this.handleEditCancel} 
+            site={this.state.site.site}
+            onCancel={this.handleEditCancel}
           />
-        }
+        )}
       </div>
-    )
+    );
   }
 
   updateUrl() {
     let typeStr = ListingType[this.state.type_].toLowerCase();
     let sortStr = SortType[this.state.sort].toLowerCase();
-    this.props.history.push(`/home/type/${typeStr}/sort/${sortStr}/page/${this.state.page}`);
+    this.props.history.push(
+      `/home/type/${typeStr}/sort/${sortStr}/page/${this.state.page}`
+    );
   }
 
   siteInfo() {
@@ -208,30 +258,66 @@ export class Main extends Component<any, MainState> {
         <div class="card border-secondary mb-3">
           <div class="card-body">
             <h5 class="mb-0">{`${this.state.site.site.name}`}</h5>
-            {this.canAdmin && 
-              <ul class="list-inline mb-1 text-muted small font-weight-bold"> 
+            {this.canAdmin && (
+              <ul class="list-inline mb-1 text-muted small font-weight-bold">
                 <li className="list-inline-item">
-                  <span class="pointer" onClick={linkEvent(this, this.handleEditClick)}>
+                  <span
+                    class="pointer"
+                    onClick={linkEvent(this, this.handleEditClick)}
+                  >
                     <T i18nKey="edit">#</T>
                   </span>
                 </li>
               </ul>
-            }
+            )}
             <ul class="my-2 list-inline">
               <li className="list-inline-item badge badge-secondary">
-                <T i18nKey="number_online" interpolation={{count: this.state.site.online}}>#</T>
+                <T
+                  i18nKey="number_online"
+                  interpolation={{ count: this.state.site.online }}
+                >
+                  #
+                </T>
               </li>
               <li className="list-inline-item badge badge-secondary">
-                <T i18nKey="number_of_users" interpolation={{count: this.state.site.site.number_of_users}}>#</T>
+                <T
+                  i18nKey="number_of_users"
+                  interpolation={{
+                    count: this.state.site.site.number_of_users,
+                  }}
+                >
+                  #
+                </T>
               </li>
               <li className="list-inline-item badge badge-secondary">
-                <T i18nKey="number_of_communities" interpolation={{count: this.state.site.site.number_of_communities}}>#</T>
+                <T
+                  i18nKey="number_of_communities"
+                  interpolation={{
+                    count: this.state.site.site.number_of_communities,
+                  }}
+                >
+                  #
+                </T>
               </li>
               <li className="list-inline-item badge badge-secondary">
-                <T i18nKey="number_of_posts" interpolation={{count: this.state.site.site.number_of_posts}}>#</T>
+                <T
+                  i18nKey="number_of_posts"
+                  interpolation={{
+                    count: this.state.site.site.number_of_posts,
+                  }}
+                >
+                  #
+                </T>
               </li>
               <li className="list-inline-item badge badge-secondary">
-                <T i18nKey="number_of_comments" interpolation={{count: this.state.site.site.number_of_comments}}>#</T>
+                <T
+                  i18nKey="number_of_comments"
+                  interpolation={{
+                    count: this.state.site.site.number_of_comments,
+                  }}
+                >
+                  #
+                </T>
               </li>
               <li className="list-inline-item">
                 <Link className="badge badge-secondary" to="/modlog">
@@ -239,25 +325,37 @@ export class Main extends Component<any, MainState> {
                 </Link>
               </li>
             </ul>
-            <ul class="mt-1 list-inline small mb-0"> 
+            <ul class="mt-1 list-inline small mb-0">
               <li class="list-inline-item">
-                <T i18nKey="admins" class="d-inline">#</T>:
+                <T i18nKey="admins" class="d-inline">
+                  #
+                </T>
+                :
+              </li>
+              {this.state.site.admins.map(admin => (
+                <li class="list-inline-item">
+                  <Link class="text-info" to={`/u/${admin.name}`}>
+                    {admin.name}
+                  </Link>
                 </li>
-                {this.state.site.admins.map(admin =>
-                  <li class="list-inline-item"><Link class="text-info" to={`/u/${admin.name}`}>{admin.name}</Link></li>
+              ))}
+            </ul>
+          </div>
+        </div>
+        {this.state.site.site.description && (
+          <div class="card border-secondary mb-3">
+            <div class="card-body">
+              <div
+                className="md-div"
+                dangerouslySetInnerHTML={mdToHtml(
+                  this.state.site.site.description
                 )}
-              </ul>
+              />
             </div>
           </div>
-          {this.state.site.site.description && 
-            <div class="card border-secondary mb-3">
-              <div class="card-body">
-                <div className="md-div" dangerouslySetInnerHTML={mdToHtml(this.state.site.site.description)} />
-              </div>
-            </div>
-          }
-        </div>
-    )
+        )}
+      </div>
+    );
   }
 
   landing() {
@@ -265,43 +363,73 @@ export class Main extends Component<any, MainState> {
       <div class="card border-secondary">
         <div class="card-body">
           <h5>
-            <T i18nKey="powered_by" class="d-inline">#</T>
-            <svg class="icon mx-2"><use xlinkHref="#icon-mouse">#</use></svg>
-            <a href={repoUrl}>Lemmy<sup>beta</sup></a>
+            <T i18nKey="powered_by" class="d-inline">
+              #
+            </T>
+            <svg class="icon mx-2">
+              <use xlinkHref="#icon-mouse">#</use>
+            </svg>
+            <a href={repoUrl}>
+              Lemmy<sup>beta</sup>
+            </a>
           </h5>
           <p class="mb-0">
-            <T i18nKey="landing_0">#<a href="https://en.wikipedia.org/wiki/Social_network_aggregation">#</a><a href="https://en.wikipedia.org/wiki/Fediverse">#</a><br></br><code>#</code><br></br><b>#</b><br></br><a href={repoUrl}>#</a><br></br><a href="https://www.rust-lang.org">#</a><a href="https://actix.rs/">#</a><a href="https://infernojs.org">#</a><a href="https://www.typescriptlang.org/">#</a>
-          </T>
-        </p>
+            <T i18nKey="landing_0">
+              #
+              <a href="https://en.wikipedia.org/wiki/Social_network_aggregation">
+                #
+              </a>
+              <a href="https://en.wikipedia.org/wiki/Fediverse">#</a>
+              <br></br>
+              <code>#</code>
+              <br></br>
+              <b>#</b>
+              <br></br>
+              <a href={repoUrl}>#</a>
+              <br></br>
+              <a href="https://www.rust-lang.org">#</a>
+              <a href="https://actix.rs/">#</a>
+              <a href="https://infernojs.org">#</a>
+              <a href="https://www.typescriptlang.org/">#</a>
+            </T>
+          </p>
+        </div>
       </div>
-    </div>
-    )
+    );
   }
 
   posts() {
     return (
       <div>
-        {this.state.loading ? 
-        <h5><svg class="icon icon-spinner spin"><use xlinkHref="#icon-spinner"></use></svg></h5> : 
-        <div>
-          {this.selects()}
-          <PostListings posts={this.state.posts} showCommunity />
-          {this.paginator()}
-        </div>
-        }
+        {this.state.loading ? (
+          <h5>
+            <svg class="icon icon-spinner spin">
+              <use xlinkHref="#icon-spinner"></use>
+            </svg>
+          </h5>
+        ) : (
+          <div>
+            {this.selects()}
+            <PostListings posts={this.state.posts} showCommunity />
+            {this.paginator()}
+          </div>
+        )}
       </div>
-    )
+    );
   }
 
   selects() {
     return (
       <div className="mb-3">
         <div class="btn-group btn-group-toggle">
-          <label className={`btn btn-sm btn-secondary 
+          <label
+            className={`btn btn-sm btn-secondary 
             ${this.state.type_ == ListingType.Subscribed && 'active'}
             ${UserService.Instance.user == undefined ? 'disabled' : 'pointer'}
-            `}>
-            <input type="radio" 
+            `}
+          >
+            <input
+              type="radio"
               value={ListingType.Subscribed}
               checked={this.state.type_ == ListingType.Subscribed}
               onChange={linkEvent(this, this.handleTypeChange)}
@@ -309,43 +437,82 @@ export class Main extends Component<any, MainState> {
             />
             {i18n.t('subscribed')}
           </label>
-          <label className={`pointer btn btn-sm btn-secondary ${this.state.type_ == ListingType.All && 'active'}`}>
-            <input type="radio" 
+          <label
+            className={`pointer btn btn-sm btn-secondary ${this.state.type_ ==
+              ListingType.All && 'active'}`}
+          >
+            <input
+              type="radio"
               value={ListingType.All}
               checked={this.state.type_ == ListingType.All}
               onChange={linkEvent(this, this.handleTypeChange)}
-            /> 
+            />
             {i18n.t('all')}
           </label>
         </div>
-        <select value={this.state.sort} onChange={linkEvent(this, this.handleSortChange)} class="ml-2 custom-select custom-select-sm w-auto">
-          <option disabled><T i18nKey="sort_type">#</T></option>
-          <option value={SortType.Hot}><T i18nKey="hot">#</T></option>
-          <option value={SortType.New}><T i18nKey="new">#</T></option>
+        <select
+          value={this.state.sort}
+          onChange={linkEvent(this, this.handleSortChange)}
+          class="ml-2 custom-select custom-select-sm w-auto"
+        >
+          <option disabled>
+            <T i18nKey="sort_type">#</T>
+          </option>
+          <option value={SortType.Hot}>
+            <T i18nKey="hot">#</T>
+          </option>
+          <option value={SortType.New}>
+            <T i18nKey="new">#</T>
+          </option>
           <option disabled>─────</option>
-          <option value={SortType.TopDay}><T i18nKey="top_day">#</T></option>
-          <option value={SortType.TopWeek}><T i18nKey="week">#</T></option>
-          <option value={SortType.TopMonth}><T i18nKey="month">#</T></option>
-          <option value={SortType.TopYear}><T i18nKey="year">#</T></option>
-          <option value={SortType.TopAll}><T i18nKey="all">#</T></option>
+          <option value={SortType.TopDay}>
+            <T i18nKey="top_day">#</T>
+          </option>
+          <option value={SortType.TopWeek}>
+            <T i18nKey="week">#</T>
+          </option>
+          <option value={SortType.TopMonth}>
+            <T i18nKey="month">#</T>
+          </option>
+          <option value={SortType.TopYear}>
+            <T i18nKey="year">#</T>
+          </option>
+          <option value={SortType.TopAll}>
+            <T i18nKey="all">#</T>
+          </option>
         </select>
       </div>
-    )
+    );
   }
 
   paginator() {
     return (
       <div class="my-2">
-        {this.state.page > 1 && 
-          <button class="btn btn-sm btn-secondary mr-1" onClick={linkEvent(this, this.prevPage)}><T i18nKey="prev">#</T></button>
-        }
-        <button class="btn btn-sm btn-secondary" onClick={linkEvent(this, this.nextPage)}><T i18nKey="next">#</T></button>
+        {this.state.page > 1 && (
+          <button
+            class="btn btn-sm btn-secondary mr-1"
+            onClick={linkEvent(this, this.prevPage)}
+          >
+            <T i18nKey="prev">#</T>
+          </button>
+        )}
+        <button
+          class="btn btn-sm btn-secondary"
+          onClick={linkEvent(this, this.nextPage)}
+        >
+          <T i18nKey="next">#</T>
+        </button>
       </div>
     );
   }
 
   get canAdmin(): boolean {
-    return UserService.Instance.user && this.state.site.admins.map(a => a.id).includes(UserService.Instance.user.id);
+    return (
+      UserService.Instance.user &&
+      this.state.site.admins
+        .map(a => a.id)
+        .includes(UserService.Instance.user.id)
+    );
   }
 
   handleEditClick(i: Main) {
@@ -358,22 +525,22 @@ export class Main extends Component<any, MainState> {
     this.setState(this.state);
   }
 
-  nextPage(i: Main) { 
+  nextPage(i: Main) {
     i.state.page++;
     i.state.loading = true;
     i.setState(i.state);
     i.updateUrl();
     i.fetchPosts();
-    window.scrollTo(0,0);
+    window.scrollTo(0, 0);
   }
 
-  prevPage(i: Main) { 
+  prevPage(i: Main) {
     i.state.page--;
     i.state.loading = true;
     i.setState(i.state);
     i.updateUrl();
     i.fetchPosts();
-    window.scrollTo(0,0);
+    window.scrollTo(0, 0);
   }
 
   handleSortChange(i: Main, event: any) {
@@ -383,7 +550,7 @@ export class Main extends Component<any, MainState> {
     i.setState(i.state);
     i.updateUrl();
     i.fetchPosts();
-    window.scrollTo(0,0);
+    window.scrollTo(0, 0);
   }
 
   handleTypeChange(i: Main, event: any) {
@@ -393,7 +560,7 @@ export class Main extends Component<any, MainState> {
     i.setState(i.state);
     i.updateUrl();
     i.fetchPosts();
-    window.scrollTo(0,0);
+    window.scrollTo(0, 0);
   }
 
   keepFetchingPosts() {
@@ -406,8 +573,8 @@ export class Main extends Component<any, MainState> {
       page: this.state.page,
       limit: fetchLimit,
       sort: SortType[this.state.sort],
-      type_: ListingType[this.state.type_]
-    }
+      type_: ListingType[this.state.type_],
+    };
     WebSocketService.Instance.getPosts(getPostsForm);
   }
 
@@ -430,7 +597,7 @@ export class Main extends Component<any, MainState> {
 
       // This means it hasn't been set up yet
       if (!res.site) {
-        this.context.router.history.push("/setup");
+        this.context.router.history.push('/setup');
       }
       this.state.site.admins = res.admins;
       this.state.site.site = res.site;
@@ -438,7 +605,6 @@ export class Main extends Component<any, MainState> {
       this.state.site.online = res.online;
       this.setState(this.state);
       document.title = `${WebSocketService.Instance.site.name}`;
-
     } else if (op == UserOperation.EditSite) {
       let res: SiteResponse = msg;
       this.state.site.site = res.site;
@@ -460,4 +626,3 @@ export class Main extends Component<any, MainState> {
     }
   }
 }
-
index 3af122a8e6a346a7f497fe5e690a450ea451fdca..425710dd1726076f317c48bba97596c0d033792f 100644 (file)
@@ -1,8 +1,21 @@
 import { Component, linkEvent } from 'inferno';
 import { Link } from 'inferno-router';
-import { Subscription } from "rxjs";
+import { Subscription } from 'rxjs';
 import { retryWhen, delay, take } from 'rxjs/operators';
-import { UserOperation, GetModlogForm, GetModlogResponse, ModRemovePost, ModLockPost, ModStickyPost, ModRemoveComment, ModRemoveCommunity, ModBanFromCommunity, ModBan, ModAddCommunity, ModAdd } from '../interfaces';
+import {
+  UserOperation,
+  GetModlogForm,
+  GetModlogResponse,
+  ModRemovePost,
+  ModLockPost,
+  ModStickyPost,
+  ModRemoveComment,
+  ModRemoveCommunity,
+  ModBanFromCommunity,
+  ModBan,
+  ModAddCommunity,
+  ModAdd,
+} from '../interfaces';
 import { WebSocketService } from '../services';
 import { msgOp, addTypeInfo, fetchLimit } from '../utils';
 import { MomentTime } from './moment-time';
@@ -10,9 +23,18 @@ import * as moment from 'moment';
 import { i18n } from '../i18next';
 
 interface ModlogState {
-  combined: Array<{type_: string, data: ModRemovePost | ModLockPost | ModStickyPost | ModRemoveCommunity | ModAdd | ModBan}>,
-  communityId?: number,
-  communityName?: string,
+  combined: Array<{
+    type_: string;
+    data:
+      | ModRemovePost
+      | ModLockPost
+      | ModStickyPost
+      | ModRemoveCommunity
+      | ModAdd
+      | ModBan;
+  }>;
+  communityId?: number;
+  communityName?: string;
   page: number;
   loading: boolean;
 }
@@ -23,20 +45,29 @@ export class Modlog extends Component<any, ModlogState> {
     combined: [],
     page: 1,
     loading: true,
-  }
+  };
 
   constructor(props: any, context: any) {
     super(props, context);
 
     this.state = this.emptyState;
-    this.state.communityId = this.props.match.params.community_id ? Number(this.props.match.params.community_id) : undefined;
+    this.state.communityId = this.props.match.params.community_id
+      ? Number(this.props.match.params.community_id)
+      : undefined;
     this.subscription = WebSocketService.Instance.subject
-    .pipe(retryWhen(errors => errors.pipe(delay(3000), take(10))))
-    .subscribe(
-      (msg) => this.parseMessage(msg),
-        (err) => console.error(err),
+      .pipe(
+        retryWhen(errors =>
+          errors.pipe(
+            delay(3000),
+            take(10)
+          )
+        )
+      )
+      .subscribe(
+        msg => this.parseMessage(msg),
+        err => console.error(err),
         () => console.log('complete')
-    );
+      );
 
     this.refetch();
   }
@@ -50,15 +81,27 @@ export class Modlog extends Component<any, ModlogState> {
   }
 
   setCombined(res: GetModlogResponse) {
-    let removed_posts = addTypeInfo(res.removed_posts, "removed_posts");
-    let locked_posts = addTypeInfo(res.locked_posts, "locked_posts");
-    let stickied_posts = addTypeInfo(res.stickied_posts, "stickied_posts");
-    let removed_comments = addTypeInfo(res.removed_comments, "removed_comments");
-    let removed_communities = addTypeInfo(res.removed_communities, "removed_communities");
-    let banned_from_community = addTypeInfo(res.banned_from_community, "banned_from_community");
-    let added_to_community = addTypeInfo(res.added_to_community, "added_to_community");
-    let added = addTypeInfo(res.added, "added");
-    let banned = addTypeInfo(res.banned, "banned");
+    let removed_posts = addTypeInfo(res.removed_posts, 'removed_posts');
+    let locked_posts = addTypeInfo(res.locked_posts, 'locked_posts');
+    let stickied_posts = addTypeInfo(res.stickied_posts, 'stickied_posts');
+    let removed_comments = addTypeInfo(
+      res.removed_comments,
+      'removed_comments'
+    );
+    let removed_communities = addTypeInfo(
+      res.removed_communities,
+      'removed_communities'
+    );
+    let banned_from_community = addTypeInfo(
+      res.banned_from_community,
+      'banned_from_community'
+    );
+    let added_to_community = addTypeInfo(
+      res.added_to_community,
+      'added_to_community'
+    );
+    let added = addTypeInfo(res.added, 'added');
+    let banned = addTypeInfo(res.banned, 'banned');
     this.state.combined = [];
 
     this.state.combined.push(...removed_posts);
@@ -72,11 +115,14 @@ export class Modlog extends Component<any, ModlogState> {
     this.state.combined.push(...banned);
 
     if (this.state.communityId && this.state.combined.length > 0) {
-      this.state.communityName = (this.state.combined[0].data as ModRemovePost).community_name;
+      this.state.communityName = (this.state.combined[0]
+        .data as ModRemovePost).community_name;
     }
 
     // Sort them by time
-    this.state.combined.sort((a, b) => b.data.when_.localeCompare(a.data.when_));
+    this.state.combined.sort((a, b) =>
+      b.data.when_.localeCompare(a.data.when_)
+    );
 
     this.setState(this.state);
   }
@@ -84,114 +130,259 @@ export class Modlog extends Component<any, ModlogState> {
   combined() {
     return (
       <tbody>
-        {this.state.combined.map(i =>
+        {this.state.combined.map(i => (
           <tr>
-            <td><MomentTime data={i.data} /></td>
-            <td><Link to={`/u/${i.data.mod_user_name}`}>{i.data.mod_user_name}</Link></td>
             <td>
-              {i.type_ == 'removed_posts' && 
+              <MomentTime data={i.data} />
+            </td>
+            <td>
+              <Link to={`/u/${i.data.mod_user_name}`}>
+                {i.data.mod_user_name}
+              </Link>
+            </td>
+            <td>
+              {i.type_ == 'removed_posts' && (
                 <>
-                  {(i.data as ModRemovePost).removed? 'Removed' : 'Restored'} 
-                  <span> Post <Link to={`/post/${(i.data as ModRemovePost).post_id}`}>{(i.data as ModRemovePost).post_name}</Link></span>
-                  <div>{(i.data as ModRemovePost).reason && ` reason: ${(i.data as ModRemovePost).reason}`}</div>
+                  {(i.data as ModRemovePost).removed ? 'Removed' : 'Restored'}
+                  <span>
+                    {' '}
+                    Post{' '}
+                    <Link to={`/post/${(i.data as ModRemovePost).post_id}`}>
+                      {(i.data as ModRemovePost).post_name}
+                    </Link>
+                  </span>
+                  <div>
+                    {(i.data as ModRemovePost).reason &&
+                      ` reason: ${(i.data as ModRemovePost).reason}`}
+                  </div>
                 </>
-              }
-              {i.type_ == 'locked_posts' && 
+              )}
+              {i.type_ == 'locked_posts' && (
                 <>
-                  {(i.data as ModLockPost).locked? 'Locked' : 'Unlocked'} 
-                  <span> Post <Link to={`/post/${(i.data as ModLockPost).post_id}`}>{(i.data as ModLockPost).post_name}</Link></span>
+                  {(i.data as ModLockPost).locked ? 'Locked' : 'Unlocked'}
+                  <span>
+                    {' '}
+                    Post{' '}
+                    <Link to={`/post/${(i.data as ModLockPost).post_id}`}>
+                      {(i.data as ModLockPost).post_name}
+                    </Link>
+                  </span>
                 </>
-              }
-              {i.type_ == 'stickied_posts' && 
+              )}
+              {i.type_ == 'stickied_posts' && (
                 <>
-                  {(i.data as ModStickyPost).stickied? 'Stickied' : 'Unstickied'} 
-                  <span> Post <Link to={`/post/${(i.data as ModStickyPost).post_id}`}>{(i.data as ModStickyPost).post_name}</Link></span>
+                  {(i.data as ModStickyPost).stickied
+                    ? 'Stickied'
+                    : 'Unstickied'}
+                  <span>
+                    {' '}
+                    Post{' '}
+                    <Link to={`/post/${(i.data as ModStickyPost).post_id}`}>
+                      {(i.data as ModStickyPost).post_name}
+                    </Link>
+                  </span>
                 </>
-              }
-              {i.type_ == 'removed_comments' && 
+              )}
+              {i.type_ == 'removed_comments' && (
                 <>
-                  {(i.data as ModRemoveComment).removed? 'Removed' : 'Restored'} 
-                  <span> Comment <Link to={`/post/${(i.data as ModRemoveComment).post_id}/comment/${(i.data as ModRemoveComment).comment_id}`}>{(i.data as ModRemoveComment).comment_content}</Link></span>
-                  <span> by <Link to={`/u/${(i.data as ModRemoveComment).comment_user_name}`}>{(i.data as ModRemoveComment).comment_user_name}</Link></span>
-                  <div>{(i.data as ModRemoveComment).reason && ` reason: ${(i.data as ModRemoveComment).reason}`}</div>
+                  {(i.data as ModRemoveComment).removed
+                    ? 'Removed'
+                    : 'Restored'}
+                  <span>
+                    {' '}
+                    Comment{' '}
+                    <Link
+                      to={`/post/${
+                        (i.data as ModRemoveComment).post_id
+                      }/comment/${(i.data as ModRemoveComment).comment_id}`}
+                    >
+                      {(i.data as ModRemoveComment).comment_content}
+                    </Link>
+                  </span>
+                  <span>
+                    {' '}
+                    by{' '}
+                    <Link
+                      to={`/u/${
+                        (i.data as ModRemoveComment).comment_user_name
+                      }`}
+                    >
+                      {(i.data as ModRemoveComment).comment_user_name}
+                    </Link>
+                  </span>
+                  <div>
+                    {(i.data as ModRemoveComment).reason &&
+                      ` reason: ${(i.data as ModRemoveComment).reason}`}
+                  </div>
                 </>
-              }
-              {i.type_ == 'removed_communities' && 
+              )}
+              {i.type_ == 'removed_communities' && (
                 <>
-                  {(i.data as ModRemoveCommunity).removed ? 'Removed' : 'Restored'} 
-                  <span> Community <Link to={`/c/${(i.data as ModRemoveCommunity).community_name}`}>{(i.data as ModRemoveCommunity).community_name}</Link></span>
-                  <div>{(i.data as ModRemoveCommunity).reason && ` reason: ${(i.data as ModRemoveCommunity).reason}`}</div>
-                  <div>{(i.data as ModRemoveCommunity).expires && ` expires: ${moment.utc((i.data as ModRemoveCommunity).expires).fromNow()}`}</div>
+                  {(i.data as ModRemoveCommunity).removed
+                    ? 'Removed'
+                    : 'Restored'}
+                  <span>
+                    {' '}
+                    Community{' '}
+                    <Link
+                      to={`/c/${(i.data as ModRemoveCommunity).community_name}`}
+                    >
+                      {(i.data as ModRemoveCommunity).community_name}
+                    </Link>
+                  </span>
+                  <div>
+                    {(i.data as ModRemoveCommunity).reason &&
+                      ` reason: ${(i.data as ModRemoveCommunity).reason}`}
+                  </div>
+                  <div>
+                    {(i.data as ModRemoveCommunity).expires &&
+                      ` expires: ${moment
+                        .utc((i.data as ModRemoveCommunity).expires)
+                        .fromNow()}`}
+                  </div>
                 </>
-              }
-              {i.type_ == 'banned_from_community' && 
+              )}
+              {i.type_ == 'banned_from_community' && (
                 <>
-                  <span>{(i.data as ModBanFromCommunity).banned ? 'Banned ' : 'Unbanned '} </span>
-                  <span><Link to={`/u/${(i.data as ModBanFromCommunity).other_user_name}`}>{(i.data as ModBanFromCommunity).other_user_name}</Link></span>
+                  <span>
+                    {(i.data as ModBanFromCommunity).banned
+                      ? 'Banned '
+                      : 'Unbanned '}{' '}
+                  </span>
+                  <span>
+                    <Link
+                      to={`/u/${
+                        (i.data as ModBanFromCommunity).other_user_name
+                      }`}
+                    >
+                      {(i.data as ModBanFromCommunity).other_user_name}
+                    </Link>
+                  </span>
                   <span> from the community </span>
-                  <span><Link to={`/c/${(i.data as ModBanFromCommunity).community_name}`}>{(i.data as ModBanFromCommunity).community_name}</Link></span>
-                  <div>{(i.data as ModBanFromCommunity).reason && ` reason: ${(i.data as ModBanFromCommunity).reason}`}</div>
-                  <div>{(i.data as ModBanFromCommunity).expires && ` expires: ${moment.utc((i.data as ModBanFromCommunity).expires).fromNow()}`}</div>
+                  <span>
+                    <Link
+                      to={`/c/${
+                        (i.data as ModBanFromCommunity).community_name
+                      }`}
+                    >
+                      {(i.data as ModBanFromCommunity).community_name}
+                    </Link>
+                  </span>
+                  <div>
+                    {(i.data as ModBanFromCommunity).reason &&
+                      ` reason: ${(i.data as ModBanFromCommunity).reason}`}
+                  </div>
+                  <div>
+                    {(i.data as ModBanFromCommunity).expires &&
+                      ` expires: ${moment
+                        .utc((i.data as ModBanFromCommunity).expires)
+                        .fromNow()}`}
+                  </div>
                 </>
-              }
-              {i.type_ == 'added_to_community' && 
+              )}
+              {i.type_ == 'added_to_community' && (
                 <>
-                  <span>{(i.data as ModAddCommunity).removed ? 'Removed ' : 'Appointed '} </span>
-                  <span><Link to={`/u/${(i.data as ModAddCommunity).other_user_name}`}>{(i.data as ModAddCommunity).other_user_name}</Link></span>
+                  <span>
+                    {(i.data as ModAddCommunity).removed
+                      ? 'Removed '
+                      : 'Appointed '}{' '}
+                  </span>
+                  <span>
+                    <Link
+                      to={`/u/${(i.data as ModAddCommunity).other_user_name}`}
+                    >
+                      {(i.data as ModAddCommunity).other_user_name}
+                    </Link>
+                  </span>
                   <span> as a mod to the community </span>
-                  <span><Link to={`/c/${(i.data as ModAddCommunity).community_name}`}>{(i.data as ModAddCommunity).community_name}</Link></span>
+                  <span>
+                    <Link
+                      to={`/c/${(i.data as ModAddCommunity).community_name}`}
+                    >
+                      {(i.data as ModAddCommunity).community_name}
+                    </Link>
+                  </span>
                 </>
-              }
-              {i.type_ == 'banned' && 
+              )}
+              {i.type_ == 'banned' && (
                 <>
-                  <span>{(i.data as ModBan).banned ? 'Banned ' : 'Unbanned '} </span>
-                  <span><Link to={`/u/${(i.data as ModBan).other_user_name}`}>{(i.data as ModBan).other_user_name}</Link></span>
-                  <div>{(i.data as ModBan).reason && ` reason: ${(i.data as ModBan).reason}`}</div>
-                  <div>{(i.data as ModBan).expires && ` expires: ${moment.utc((i.data as ModBan).expires).fromNow()}`}</div>
+                  <span>
+                    {(i.data as ModBan).banned ? 'Banned ' : 'Unbanned '}{' '}
+                  </span>
+                  <span>
+                    <Link to={`/u/${(i.data as ModBan).other_user_name}`}>
+                      {(i.data as ModBan).other_user_name}
+                    </Link>
+                  </span>
+                  <div>
+                    {(i.data as ModBan).reason &&
+                      ` reason: ${(i.data as ModBan).reason}`}
+                  </div>
+                  <div>
+                    {(i.data as ModBan).expires &&
+                      ` expires: ${moment
+                        .utc((i.data as ModBan).expires)
+                        .fromNow()}`}
+                  </div>
                 </>
-              }
-              {i.type_ == 'added' && 
+              )}
+              {i.type_ == 'added' && (
                 <>
-                  <span>{(i.data as ModAdd).removed ? 'Removed ' : 'Appointed '} </span>
-                  <span><Link to={`/u/${(i.data as ModAdd).other_user_name}`}>{(i.data as ModAdd).other_user_name}</Link></span>
+                  <span>
+                    {(i.data as ModAdd).removed ? 'Removed ' : 'Appointed '}{' '}
+                  </span>
+                  <span>
+                    <Link to={`/u/${(i.data as ModAdd).other_user_name}`}>
+                      {(i.data as ModAdd).other_user_name}
+                    </Link>
+                  </span>
                   <span> as an admin </span>
                 </>
-              }
+              )}
             </td>
           </tr>
-                                )
-        }
-
+        ))}
       </tbody>
     );
-
   }
 
   render() {
     return (
       <div class="container">
-        {this.state.loading ? 
-        <h5 class=""><svg class="icon icon-spinner spin"><use xlinkHref="#icon-spinner"></use></svg></h5> : 
-        <div>
-          <h5>
-            {this.state.communityName && <Link className="text-white" to={`/c/${this.state.communityName}`}>/c/{this.state.communityName} </Link>}
-            <span>Modlog</span>
+        {this.state.loading ? (
+          <h5 class="">
+            <svg class="icon icon-spinner spin">
+              <use xlinkHref="#icon-spinner"></use>
+            </svg>
           </h5>
-          <div class="table-responsive">
-            <table id="modlog_table" class="table table-sm table-hover">
-              <thead class="pointer">
-                <tr>
-                  <th>Time</th>
-                  <th>Mod</th>
-                  <th>Action</th>
-                </tr>
-              </thead>
-              {this.combined()}
-            </table>
-            {this.paginator()}
+        ) : (
+          <div>
+            <h5>
+              {this.state.communityName && (
+                <Link
+                  className="text-white"
+                  to={`/c/${this.state.communityName}`}
+                >
+                  /c/{this.state.communityName}{' '}
+                </Link>
+              )}
+              <span>Modlog</span>
+            </h5>
+            <div class="table-responsive">
+              <table id="modlog_table" class="table table-sm table-hover">
+                <thead class="pointer">
+                  <tr>
+                    <th>Time</th>
+                    <th>Mod</th>
+                    <th>Action</th>
+                  </tr>
+                </thead>
+                {this.combined()}
+              </table>
+              {this.paginator()}
+            </div>
           </div>
-        </div>
-        }
+        )}
       </div>
     );
   }
@@ -199,27 +390,37 @@ export class Modlog extends Component<any, ModlogState> {
   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>
+        {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>
     );
   }
 
-  nextPage(i: Modlog) { 
+  nextPage(i: Modlog) {
     i.state.page++;
     i.setState(i.state);
     i.refetch();
   }
 
-  prevPage(i: Modlog) { 
+  prevPage(i: Modlog) {
     i.state.page--;
     i.setState(i.state);
     i.refetch();
   }
 
-  refetch(){
+  refetch() {
     let modlogForm: GetModlogForm = {
       community_id: this.state.communityId,
       page: this.state.page,
@@ -237,8 +438,8 @@ export class Modlog extends Component<any, ModlogState> {
     } else if (op == UserOperation.GetModlog) {
       let res: GetModlogResponse = msg;
       this.state.loading = false;
-      window.scrollTo(0,0);
+      window.scrollTo(0, 0);
       this.setCombined(res);
-    } 
+    }
   }
 }
index c6cd981b32581a9f5e402931482124a440487e14..6bb4d99cfc5365f4cf3b76fa4e61bd081bb04fa7 100644 (file)
@@ -8,11 +8,10 @@ interface MomentTimeProps {
     published?: string;
     when_?: string;
     updated?: string;
-  }
+  };
 }
 
 export class MomentTime extends Component<MomentTimeProps, any> {
-
   constructor(props: any, context: any) {
     super(props, context);
 
@@ -24,13 +23,13 @@ export class MomentTime extends Component<MomentTimeProps, any> {
   render() {
     if (this.props.data.updated) {
       return (
-        <span title={this.props.data.updated} className="font-italics">{i18n.t('modified')} {moment.utc(this.props.data.updated).fromNow()}</span>
-      )
+        <span title={this.props.data.updated} className="font-italics">
+          {i18n.t('modified')} {moment.utc(this.props.data.updated).fromNow()}
+        </span>
+      );
     } else {
       let str = this.props.data.published || this.props.data.when_;
-      return (
-        <span title={str}>{moment.utc(str).fromNow()}</span>
-      )
+      return <span title={str}>{moment.utc(str).fromNow()}</span>;
     }
   }
 }
index c33f8196d22b42cadd090f0b56022d4bf47e5ba6..ba0dead2575eceb9b24cf5d9f3252de335f28f02 100644 (file)
@@ -1,9 +1,16 @@
 import { Component, linkEvent } from 'inferno';
 import { Link } from 'inferno-router';
-import { Subscription } from "rxjs";
+import { Subscription } from 'rxjs';
 import { retryWhen, delay, take } from 'rxjs/operators';
 import { WebSocketService, UserService } from '../services';
-import { UserOperation, GetRepliesForm, GetRepliesResponse, SortType, GetSiteResponse, Comment} from '../interfaces';
+import {
+  UserOperation,
+  GetRepliesForm,
+  GetRepliesResponse,
+  SortType,
+  GetSiteResponse,
+  Comment,
+} from '../interfaces';
 import { msgOp } from '../utils';
 import { version } from '../version';
 import { i18n } from '../i18next';
@@ -13,8 +20,8 @@ interface NavbarState {
   isLoggedIn: boolean;
   expanded: boolean;
   expandUserDropdown: boolean;
-  replies: Array<Comment>,
-  fetchCount: number,
+  replies: Array<Comment>;
+  fetchCount: number;
   unreadCount: number;
   siteName: string;
 }
@@ -23,14 +30,14 @@ export class Navbar extends Component<any, NavbarState> {
   private wsSub: Subscription;
   private userSub: Subscription;
   emptyState: NavbarState = {
-    isLoggedIn: (UserService.Instance.user !== undefined),
+    isLoggedIn: UserService.Instance.user !== undefined,
     unreadCount: 0,
     fetchCount: 0,
     replies: [],
     expanded: false,
     expandUserDropdown: false,
-    siteName: undefined
-  }
+    siteName: undefined,
+  };
 
   constructor(props: any, context: any) {
     super(props, context);
@@ -48,12 +55,19 @@ export class Navbar extends Component<any, NavbarState> {
     });
 
     this.wsSub = WebSocketService.Instance.subject
-    .pipe(retryWhen(errors => errors.pipe(delay(3000), take(10))))
-    .subscribe(
-      (msg) => this.parseMessage(msg),
-        (err) => console.error(err),
+      .pipe(
+        retryWhen(errors =>
+          errors.pipe(
+            delay(3000),
+            take(10)
+          )
+        )
+      )
+      .subscribe(
+        msg => this.parseMessage(msg),
+        err => console.error(err),
         () => console.log('complete')
-    );
+      );
 
     if (this.state.isLoggedIn) {
       this.requestNotificationPermission();
@@ -63,9 +77,7 @@ export class Navbar extends Component<any, NavbarState> {
   }
 
   render() {
-    return (
-      <div>{this.navbar()}</div>
-    )
+    return <div>{this.navbar()}</div>;
   }
 
   componentWillUnmount() {
@@ -80,48 +92,98 @@ export class Navbar extends Component<any, NavbarState> {
         <Link title={version} class="navbar-brand" to="/">
           {this.state.siteName}
         </Link>
-        <button class="navbar-toggler" type="button" onClick={linkEvent(this, this.expandNavbar)}>
+        <button
+          class="navbar-toggler"
+          type="button"
+          onClick={linkEvent(this, this.expandNavbar)}
+        >
           <span class="navbar-toggler-icon"></span>
         </button>
-        <div className={`${!this.state.expanded && 'collapse'} navbar-collapse`}>
+        <div
+          className={`${!this.state.expanded && 'collapse'} navbar-collapse`}
+        >
           <ul class="navbar-nav mr-auto">
             <li class="nav-item">
-              <Link class="nav-link" to="/communities"><T i18nKey="communities">#</T></Link>
+              <Link class="nav-link" to="/communities">
+                <T i18nKey="communities">#</T>
+              </Link>
             </li>
             <li class="nav-item">
-              <Link class="nav-link" to="/search"><T i18nKey="search">#</T></Link>
+              <Link class="nav-link" to="/search">
+                <T i18nKey="search">#</T>
+              </Link>
             </li>
             <li class="nav-item">
-              <Link class="nav-link" to={{pathname: '/create_post', state: { prevPath: this.currentLocation }}}><T i18nKey="create_post">#</T></Link>
+              <Link
+                class="nav-link"
+                to={{
+                  pathname: '/create_post',
+                  state: { prevPath: this.currentLocation },
+                }}
+              >
+                <T i18nKey="create_post">#</T>
+              </Link>
             </li>
             <li class="nav-item">
-              <Link class="nav-link" to="/create_community"><T i18nKey="create_community">#</T></Link>
+              <Link class="nav-link" to="/create_community">
+                <T i18nKey="create_community">#</T>
+              </Link>
             </li>
           </ul>
           <ul class="navbar-nav ml-auto mr-2">
-            {this.state.isLoggedIn ? 
-            <>
-              {
-                <li className="nav-item">
-                  <Link class="nav-link" to="/inbox">
-                    <svg class="icon"><use xlinkHref="#icon-mail"></use></svg>
-                    {this.state.unreadCount> 0 && <span class="ml-1 badge badge-light">{this.state.unreadCount}</span>}
-                  </Link>
+            {this.state.isLoggedIn ? (
+              <>
+                {
+                  <li className="nav-item">
+                    <Link class="nav-link" to="/inbox">
+                      <svg class="icon">
+                        <use xlinkHref="#icon-mail"></use>
+                      </svg>
+                      {this.state.unreadCount > 0 && (
+                        <span class="ml-1 badge badge-light">
+                          {this.state.unreadCount}
+                        </span>
+                      )}
+                    </Link>
+                  </li>
+                }
+                <li
+                  className={`nav-item dropdown ${this.state
+                    .expandUserDropdown && 'show'}`}
+                >
+                  <a
+                    class="pointer nav-link dropdown-toggle"
+                    onClick={linkEvent(this, this.expandUserDropdown)}
+                    role="button"
+                  >
+                    {UserService.Instance.user.username}
+                  </a>
+                  <div
+                    className={`dropdown-menu dropdown-menu-right ${this.state
+                      .expandUserDropdown && 'show'}`}
+                  >
+                    <a
+                      role="button"
+                      class="dropdown-item pointer"
+                      onClick={linkEvent(this, this.handleOverviewClick)}
+                    >
+                      <T i18nKey="overview">#</T>
+                    </a>
+                    <a
+                      role="button"
+                      class="dropdown-item pointer"
+                      onClick={linkEvent(this, this.handleLogoutClick)}
+                    >
+                      <T i18nKey="logout">#</T>
+                    </a>
+                  </div>
                 </li>
-              }
-              <li className={`nav-item dropdown ${this.state.expandUserDropdown && 'show'}`}>
-                <a class="pointer nav-link dropdown-toggle" onClick={linkEvent(this, this.expandUserDropdown)} role="button">
-                  {UserService.Instance.user.username}
-                </a>
-                <div className={`dropdown-menu dropdown-menu-right ${this.state.expandUserDropdown && 'show'}`}>
-                  <a role="button" class="dropdown-item pointer" onClick={linkEvent(this, this.handleOverviewClick)}><T i18nKey="overview">#</T></a>
-                  <a role="button" class="dropdown-item pointer" onClick={ linkEvent(this, this.handleLogoutClick) }><T i18nKey="logout">#</T></a>
-                </div>
-              </li> 
-            </>
-              : 
-              <Link class="nav-link" to="/login"><T i18nKey="login_sign_up">#</T></Link>
-            }
+              </>
+            ) : (
+              <Link class="nav-link" to="/login">
+                <T i18nKey="login_sign_up">#</T>
+              </Link>
+            )}
           </ul>
         </div>
       </nav>
@@ -154,7 +216,7 @@ export class Navbar extends Component<any, NavbarState> {
   parseMessage(msg: any) {
     let op: UserOperation = msgOp(msg);
     if (msg.error) {
-      if (msg.error == "not_logged_in") {
+      if (msg.error == 'not_logged_in') {
         UserService.Instance.logout();
         location.reload();
       }
@@ -162,8 +224,11 @@ export class Navbar extends Component<any, NavbarState> {
     } else if (op == UserOperation.GetReplies) {
       let res: GetRepliesResponse = msg;
       let unreadReplies = res.replies.filter(r => !r.read);
-      if (unreadReplies.length > 0 && this.state.fetchCount > 1 && 
-          (JSON.stringify(this.state.replies) !== JSON.stringify(unreadReplies))) {
+      if (
+        unreadReplies.length > 0 &&
+        this.state.fetchCount > 1 &&
+        JSON.stringify(this.state.replies) !== JSON.stringify(unreadReplies)
+      ) {
         this.notify(unreadReplies);
       }
 
@@ -177,7 +242,7 @@ export class Navbar extends Component<any, NavbarState> {
         WebSocketService.Instance.site = res.site;
         this.setState(this.state);
       }
-    } 
+    }
   }
 
   keepFetchingReplies() {
@@ -193,7 +258,7 @@ export class Navbar extends Component<any, NavbarState> {
         page: 1,
         limit: 9999,
       };
-      if (this.currentLocation !=='/inbox') { 
+      if (this.currentLocation !== '/inbox') {
         WebSocketService.Instance.getReplies(repliesForm);
         this.state.fetchCount++;
       }
@@ -205,37 +270,43 @@ export class Navbar extends Component<any, NavbarState> {
   }
 
   sendRepliesCount(res: GetRepliesResponse) {
-    UserService.Instance.sub.next({user: UserService.Instance.user, unreadCount: res.replies.filter(r => !r.read).length});
+    UserService.Instance.sub.next({
+      user: UserService.Instance.user,
+      unreadCount: res.replies.filter(r => !r.read).length,
+    });
   }
 
   requestNotificationPermission() {
     if (UserService.Instance.user) {
-    document.addEventListener('DOMContentLoaded', function () {
-      if (!Notification) {
-        alert(i18n.t('notifications_error')); 
-        return;
-      }
+      document.addEventListener('DOMContentLoaded', function() {
+        if (!Notification) {
+          alert(i18n.t('notifications_error'));
+          return;
+        }
 
-      if (Notification.permission !== 'granted')
-        Notification.requestPermission();
-    });
+        if (Notification.permission !== 'granted')
+          Notification.requestPermission();
+      });
     }
   }
 
   notify(replies: Array<Comment>) {
     let recentReply = replies[0];
-    if (Notification.permission !== 'granted')
-      Notification.requestPermission();
+    if (Notification.permission !== 'granted') Notification.requestPermission();
     else {
-      var notification = new Notification(`${replies.length} ${i18n.t('unread_messages')}`, {
-        icon: `${window.location.protocol}//${window.location.host}/static/assets/apple-touch-icon.png`,
-        body: `${recentReply.creator_name}: ${recentReply.content}`
-      });
+      var notification = new Notification(
+        `${replies.length} ${i18n.t('unread_messages')}`,
+        {
+          icon: `${window.location.protocol}//${window.location.host}/static/assets/apple-touch-icon.png`,
+          body: `${recentReply.creator_name}: ${recentReply.content}`,
+        }
+      );
 
       notification.onclick = () => {
-        this.context.router.history.push(`/post/${recentReply.post_id}/comment/${recentReply.id}`);
+        this.context.router.history.push(
+          `/post/${recentReply.post_id}/comment/${recentReply.id}`
+        );
       };
-
     }
   }
 }
index 09b9606eadeb67c82e834049cc5f5328bd16c858..d3739b471739a1b76c59ae35adc5182415c7dbab 100644 (file)
@@ -1,10 +1,31 @@
 import { Component, linkEvent } from 'inferno';
 import { PostListings } from './post-listings';
-import { Subscription } from "rxjs";
+import { Subscription } from 'rxjs';
 import { retryWhen, delay, take } from 'rxjs/operators';
-import { PostForm as PostFormI, PostFormParams, Post, PostResponse, UserOperation, Community, ListCommunitiesResponse, ListCommunitiesForm, SortType, SearchForm, SearchType, SearchResponse } from '../interfaces';
+import {
+  PostForm as PostFormI,
+  PostFormParams,
+  Post,
+  PostResponse,
+  UserOperation,
+  Community,
+  ListCommunitiesResponse,
+  ListCommunitiesForm,
+  SortType,
+  SearchForm,
+  SearchType,
+  SearchResponse,
+} from '../interfaces';
 import { WebSocketService, UserService } from '../services';
-import { msgOp, getPageTitle, debounce, validURL, capitalizeFirstLetter, markdownHelpUrl, mdToHtml } from '../utils';
+import {
+  msgOp,
+  getPageTitle,
+  debounce,
+  validURL,
+  capitalizeFirstLetter,
+  markdownHelpUrl,
+  mdToHtml,
+} from '../utils';
 import * as autosize from 'autosize';
 import { i18n } from '../i18next';
 import { T } from 'inferno-i18next';
@@ -29,7 +50,6 @@ interface PostFormState {
 }
 
 export class PostForm extends Component<PostFormProps, PostFormState> {
-
   private subscription: Subscription;
   private emptyState: PostFormState = {
     postForm: {
@@ -37,7 +57,9 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
       nsfw: false,
       auth: null,
       community_id: null,
-      creator_id: (UserService.Instance.user) ? UserService.Instance.user.id : null,
+      creator_id: UserService.Instance.user
+        ? UserService.Instance.user.id
+        : null,
     },
     communities: [],
     loading: false,
@@ -46,7 +68,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
     suggestedTitle: undefined,
     suggestedPosts: [],
     crossPosts: [],
-  }
+  };
 
   constructor(props: any, context: any) {
     super(props, context);
@@ -62,8 +84,8 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
         creator_id: this.props.post.creator_id,
         url: this.props.post.url,
         nsfw: this.props.post.nsfw,
-        auth: null
-      }
+        auth: null,
+      };
     }
 
     if (this.props.params) {
@@ -77,17 +99,24 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
     }
 
     this.subscription = WebSocketService.Instance.subject
-    .pipe(retryWhen(errors => errors.pipe(delay(3000), take(10))))
-    .subscribe(
-      (msg) => this.parseMessage(msg),
-        (err) => console.error(err),
+      .pipe(
+        retryWhen(errors =>
+          errors.pipe(
+            delay(3000),
+            take(10)
+          )
+        )
+      )
+      .subscribe(
+        msg => this.parseMessage(msg),
+        err => console.error(err),
         () => console.log('complete')
-    );
+      );
 
     let listCommunitiesForm: ListCommunitiesForm = {
       sort: SortType[SortType.TopAll],
       limit: 9999,
-    }
+    };
 
     WebSocketService.Instance.listCommunities(listCommunitiesForm);
   }
@@ -105,79 +134,177 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
       <div>
         <form onSubmit={linkEvent(this, this.handlePostSubmit)}>
           <div class="form-group row">
-            <label class="col-sm-2 col-form-label"><T i18nKey="url">#</T></label>
+            <label class="col-sm-2 col-form-label">
+              <T i18nKey="url">#</T>
+            </label>
             <div class="col-sm-10">
-              <input type="url" class="form-control" value={this.state.postForm.url} onInput={linkEvent(this, this.handlePostUrlChange)} />
-              {this.state.suggestedTitle && 
-                <div class="mt-1 text-muted small font-weight-bold pointer" onClick={linkEvent(this, this.copySuggestedTitle)}><T i18nKey="copy_suggested_title" interpolation={{title: this.state.suggestedTitle}}>#</T></div>
-              }
+              <input
+                type="url"
+                class="form-control"
+                value={this.state.postForm.url}
+                onInput={linkEvent(this, this.handlePostUrlChange)}
+              />
+              {this.state.suggestedTitle && (
+                <div
+                  class="mt-1 text-muted small font-weight-bold pointer"
+                  onClick={linkEvent(this, this.copySuggestedTitle)}
+                >
+                  <T
+                    i18nKey="copy_suggested_title"
+                    interpolation={{ title: this.state.suggestedTitle }}
+                  >
+                    #
+                  </T>
+                </div>
+              )}
               <form>
-                <label htmlFor="file-upload" className={`${UserService.Instance.user && 'pointer'} d-inline-block mr-2 float-right text-muted small font-weight-bold`}><T i18nKey="upload_image">#</T></label>
-                <input id="file-upload" type="file" accept="image/*,video/*" name="file" class="d-none" disabled={!UserService.Instance.user} onChange={linkEvent(this, this.handleImageUpload)} />
+                <label
+                  htmlFor="file-upload"
+                  className={`${UserService.Instance.user &&
+                    'pointer'} d-inline-block mr-2 float-right text-muted small font-weight-bold`}
+                >
+                  <T i18nKey="upload_image">#</T>
+                </label>
+                <input
+                  id="file-upload"
+                  type="file"
+                  accept="image/*,video/*"
+                  name="file"
+                  class="d-none"
+                  disabled={!UserService.Instance.user}
+                  onChange={linkEvent(this, this.handleImageUpload)}
+                />
               </form>
-              {this.state.imageLoading && 
-                <svg class="icon icon-spinner spin"><use xlinkHref="#icon-spinner"></use></svg>
-              }
-              {this.state.crossPosts.length > 0 && 
+              {this.state.imageLoading && (
+                <svg class="icon icon-spinner spin">
+                  <use xlinkHref="#icon-spinner"></use>
+                </svg>
+              )}
+              {this.state.crossPosts.length > 0 && (
                 <>
-                  <div class="my-1 text-muted small font-weight-bold"><T i18nKey="cross_posts">#</T></div>
+                  <div class="my-1 text-muted small font-weight-bold">
+                    <T i18nKey="cross_posts">#</T>
+                  </div>
                   <PostListings showCommunity posts={this.state.crossPosts} />
                 </>
-              }
+              )}
             </div>
           </div>
           <div class="form-group row">
-            <label class="col-sm-2 col-form-label"><T i18nKey="title">#</T></label>
+            <label class="col-sm-2 col-form-label">
+              <T i18nKey="title">#</T>
+            </label>
             <div class="col-sm-10">
-              <textarea value={this.state.postForm.name} onInput={linkEvent(this, this.handlePostNameChange)} class="form-control" required rows={2} minLength={3} maxLength={100} />
-              {this.state.suggestedPosts.length > 0 && 
+              <textarea
+                value={this.state.postForm.name}
+                onInput={linkEvent(this, this.handlePostNameChange)}
+                class="form-control"
+                required
+                rows={2}
+                minLength={3}
+                maxLength={100}
+              />
+              {this.state.suggestedPosts.length > 0 && (
                 <>
-                  <div class="my-1 text-muted small font-weight-bold"><T i18nKey="related_posts">#</T></div>
+                  <div class="my-1 text-muted small font-weight-bold">
+                    <T i18nKey="related_posts">#</T>
+                  </div>
                   <PostListings posts={this.state.suggestedPosts} />
                 </>
-              }
+              )}
             </div>
           </div>
           <div class="form-group row">
-            <label class="col-sm-2 col-form-label"><T i18nKey="body">#</T></label>
+            <label class="col-sm-2 col-form-label">
+              <T i18nKey="body">#</T>
+            </label>
             <div class="col-sm-10">
-              <textarea value={this.state.postForm.body} onInput={linkEvent(this, this.handlePostBodyChange)} className={`form-control ${this.state.previewMode && 'd-none'}`} rows={4} maxLength={10000} />
-              {this.state.previewMode && 
-                <div className="md-div" dangerouslySetInnerHTML={mdToHtml(this.state.postForm.body)} />
-              }
-              {this.state.postForm.body &&
-                <button className={`mt-1 mr-2 btn btn-sm btn-secondary ${this.state.previewMode && 'active'}`} onClick={linkEvent(this, this.handlePreviewToggle)}><T i18nKey="preview">#</T></button>
-              }
-              <a href={markdownHelpUrl} target="_blank" class="d-inline-block float-right text-muted small font-weight-bold"><T i18nKey="formatting_help">#</T></a>
+              <textarea
+                value={this.state.postForm.body}
+                onInput={linkEvent(this, this.handlePostBodyChange)}
+                className={`form-control ${this.state.previewMode && 'd-none'}`}
+                rows={4}
+                maxLength={10000}
+              />
+              {this.state.previewMode && (
+                <div
+                  className="md-div"
+                  dangerouslySetInnerHTML={mdToHtml(this.state.postForm.body)}
+                />
+              )}
+              {this.state.postForm.body && (
+                <button
+                  className={`mt-1 mr-2 btn btn-sm btn-secondary ${this.state
+                    .previewMode && 'active'}`}
+                  onClick={linkEvent(this, this.handlePreviewToggle)}
+                >
+                  <T i18nKey="preview">#</T>
+                </button>
+              )}
+              <a
+                href={markdownHelpUrl}
+                target="_blank"
+                class="d-inline-block float-right text-muted small font-weight-bold"
+              >
+                <T i18nKey="formatting_help">#</T>
+              </a>
             </div>
           </div>
-          {!this.props.post &&
+          {!this.props.post && (
             <div class="form-group row">
-            <label class="col-sm-2 col-form-label"><T i18nKey="community">#</T></label>
-            <div class="col-sm-10">
-              <select class="form-control" value={this.state.postForm.community_id} onInput={linkEvent(this, this.handlePostCommunityChange)}>
-                {this.state.communities.map(community =>
-                  <option value={community.id}>{community.name}</option>
-                )}
-              </select>
-            </div>
+              <label class="col-sm-2 col-form-label">
+                <T i18nKey="community">#</T>
+              </label>
+              <div class="col-sm-10">
+                <select
+                  class="form-control"
+                  value={this.state.postForm.community_id}
+                  onInput={linkEvent(this, this.handlePostCommunityChange)}
+                >
+                  {this.state.communities.map(community => (
+                    <option value={community.id}>{community.name}</option>
+                  ))}
+                </select>
+              </div>
             </div>
-            }
+          )}
           <div class="form-group row">
             <div class="col-sm-10">
               <div class="form-check">
-                <input class="form-check-input" type="checkbox" checked={this.state.postForm.nsfw} onChange={linkEvent(this, this.handlePostNsfwChange)}/>
-                <label class="form-check-label"><T i18nKey="nsfw">#</T></label>
+                <input
+                  class="form-check-input"
+                  type="checkbox"
+                  checked={this.state.postForm.nsfw}
+                  onChange={linkEvent(this, this.handlePostNsfwChange)}
+                />
+                <label class="form-check-label">
+                  <T i18nKey="nsfw">#</T>
+                </label>
               </div>
             </div>
           </div>
           <div class="form-group row">
             <div class="col-sm-10">
               <button type="submit" class="btn btn-secondary mr-2">
-              {this.state.loading ? 
-              <svg class="icon icon-spinner spin"><use xlinkHref="#icon-spinner"></use></svg> : 
-              this.props.post ? capitalizeFirstLetter(i18n.t('save')) : capitalizeFirstLetter(i18n.t('create'))}</button>
-              {this.props.post && <button type="button" class="btn btn-secondary" onClick={linkEvent(this, this.handleCancel)}><T i18nKey="cancel">#</T></button>}
+                {this.state.loading ? (
+                  <svg class="icon icon-spinner spin">
+                    <use xlinkHref="#icon-spinner"></use>
+                  </svg>
+                ) : this.props.post ? (
+                  capitalizeFirstLetter(i18n.t('save'))
+                ) : (
+                  capitalizeFirstLetter(i18n.t('create'))
+                )}
+              </button>
+              {this.props.post && (
+                <button
+                  type="button"
+                  class="btn btn-secondary"
+                  onClick={linkEvent(this, this.handleCancel)}
+                >
+                  <T i18nKey="cancel">#</T>
+                </button>
+              )}
             </div>
           </div>
         </form>
@@ -205,7 +332,6 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
   handlePostUrlChange(i: PostForm, event: any) {
     i.state.postForm.url = event.target.value;
     if (validURL(i.state.postForm.url)) {
-
       let form: SearchForm = {
         q: i.state.postForm.url,
         type_: SearchType[SearchType.Url],
@@ -288,21 +414,21 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
       method: 'POST',
       body: formData,
     })
-    .then(res => res.json())
-    .then(res => {
-      let url = `${window.location.origin}/pictshare/${res.url}`;
-      if (res.filetype == 'mp4') {
-        url += '/raw';
-      }
-      i.state.postForm.url = url;
-      i.state.imageLoading = false;
-      i.setState(i.state);
-    })
-    .catch((error) => {
-      i.state.imageLoading = false;
-      i.setState(i.state);
-      alert(error);
-    })
+      .then(res => res.json())
+      .then(res => {
+        let url = `${window.location.origin}/pictshare/${res.url}`;
+        if (res.filetype == 'mp4') {
+          url += '/raw';
+        }
+        i.state.postForm.url = url;
+        i.state.imageLoading = false;
+        i.setState(i.state);
+      })
+      .catch(error => {
+        i.state.imageLoading = false;
+        i.setState(i.state);
+        alert(error);
+      });
   }
 
   parseMessage(msg: any) {
@@ -318,7 +444,9 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
       if (this.props.post) {
         this.state.postForm.community_id = this.props.post.community_id;
       } else if (this.props.params && this.props.params.community) {
-        let foundCommunityId = res.communities.find(r => r.name == this.props.params.community).id;
+        let foundCommunityId = res.communities.find(
+          r => r.name == this.props.params.community
+        ).id;
         this.state.postForm.community_id = foundCommunityId;
       } else {
         this.state.postForm.community_id = res.communities[0].id;
@@ -334,7 +462,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
       this.props.onEdit(res.post);
     } else if (op == UserOperation.Search) {
       let res: SearchResponse = msg;
-      
+
       if (res.type_ == SearchType[SearchType.Posts]) {
         this.state.suggestedPosts = res.posts;
       } else if (res.type_ == SearchType[SearchType.Url]) {
@@ -343,7 +471,4 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
       this.setState(this.state);
     }
   }
-
 }
-
-
index 4468d188eef532220d6e6eaae21456dc0621cb22..4d36ac28313557a584843f637575d4d2b979ca66 100644 (file)
@@ -1,10 +1,31 @@
 import { Component, linkEvent } from 'inferno';
 import { Link } from 'inferno-router';
 import { WebSocketService, UserService } from '../services';
-import { Post, CreatePostLikeForm, PostForm as PostFormI, SavePostForm, CommunityUser, UserView, BanType, BanFromCommunityForm, BanUserForm, AddModToCommunityForm, AddAdminForm, TransferSiteForm, TransferCommunityForm } from '../interfaces';
+import {
+  Post,
+  CreatePostLikeForm,
+  PostForm as PostFormI,
+  SavePostForm,
+  CommunityUser,
+  UserView,
+  BanType,
+  BanFromCommunityForm,
+  BanUserForm,
+  AddModToCommunityForm,
+  AddAdminForm,
+  TransferSiteForm,
+  TransferCommunityForm,
+} from '../interfaces';
 import { MomentTime } from './moment-time';
 import { PostForm } from './post-form';
-import { mdToHtml, canMod, isMod, isImage, isVideo, getUnixTime } from '../utils';
+import {
+  mdToHtml,
+  canMod,
+  isMod,
+  isImage,
+  isVideo,
+  getUnixTime,
+} from '../utils';
 import { i18n } from '../i18next';
 import { T } from 'inferno-i18next';
 
@@ -32,7 +53,6 @@ interface PostListingProps {
 }
 
 export class PostListing extends Component<PostListingProps, PostListingState> {
-
   private emptyState: PostListingState = {
     showEdit: false,
     showRemoveDialog: false,
@@ -45,7 +65,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
     showConfirmTransferCommunity: false,
     imageExpanded: false,
     viewSource: false,
-  }
+  };
 
   constructor(props: any, context: any) {
     super(props, context);
@@ -60,322 +80,625 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
   render() {
     return (
       <div class="row">
-        {!this.state.showEdit 
-          this.listing()
-          : 
+        {!this.state.showEdit ? (
+          this.listing()
+        ) : (
           <div class="col-12">
-            <PostForm post={this.props.post} onEdit={this.handleEditPost} onCancel={this.handleEditCancel}/>
+            <PostForm
+              post={this.props.post}
+              onEdit={this.handleEditPost}
+              onCancel={this.handleEditCancel}
+            />
           </div>
-        }
+        )}
       </div>
-    )
+    );
   }
 
   listing() {
     let post = this.props.post;
     return (
       <div class="listing col-12">
-        <div className={`vote-bar mr-2 float-left small text-center ${this.props.viewOnly && 'no-click'}`}>
-          <button className={`btn p-0 ${post.my_vote == 1 ? 'text-info' : 'text-muted'}`} onClick={linkEvent(this, this.handlePostLike)}>
-            <svg class="icon upvote"><use xlinkHref="#icon-arrow-up"></use></svg>
+        <div
+          className={`vote-bar mr-2 float-left small text-center ${this.props
+            .viewOnly && 'no-click'}`}
+        >
+          <button
+            className={`btn p-0 ${
+              post.my_vote == 1 ? 'text-info' : 'text-muted'
+            }`}
+            onClick={linkEvent(this, this.handlePostLike)}
+          >
+            <svg class="icon upvote">
+              <use xlinkHref="#icon-arrow-up"></use>
+            </svg>
           </button>
           <div class={`font-weight-bold text-muted`}>{post.score}</div>
-          <button className={`btn p-0 ${post.my_vote == -1 ? 'text-danger' : 'text-muted'}`} onClick={linkEvent(this, this.handlePostDisLike)}>
-            <svg class="icon downvote"><use xlinkHref="#icon-arrow-down"></use></svg>
+          <button
+            className={`btn p-0 ${
+              post.my_vote == -1 ? 'text-danger' : 'text-muted'
+            }`}
+            onClick={linkEvent(this, this.handlePostDisLike)}
+          >
+            <svg class="icon downvote">
+              <use xlinkHref="#icon-arrow-down"></use>
+            </svg>
           </button>
         </div>
-        {post.url && isImage(post.url) &&
-          <span title={i18n.t('expand_here')} class="pointer" onClick={linkEvent(this, this.handleImageExpandClick)}><img class="mx-2 mt-1 float-left img-fluid thumbnail rounded" src={post.url} /></span>
-        }
-        {post.url && isVideo(post.url) &&
-          <video playsinline muted loop controls class="mx-2 mt-1 float-left" height="100" width="150">
+        {post.url && isImage(post.url) && (
+          <span
+            title={i18n.t('expand_here')}
+            class="pointer"
+            onClick={linkEvent(this, this.handleImageExpandClick)}
+          >
+            <img
+              class="mx-2 mt-1 float-left img-fluid thumbnail rounded"
+              src={post.url}
+            />
+          </span>
+        )}
+        {post.url && isVideo(post.url) && (
+          <video
+            playsinline
+            muted
+            loop
+            controls
+            class="mx-2 mt-1 float-left"
+            height="100"
+            width="150"
+          >
             <source src={post.url} type="video/mp4" />
           </video>
-        }
+        )}
         <div className="ml-4">
           <div className="post-title">
             <h5 className="mb-0 d-inline">
-              {post.url ? 
-              <a className="text-body" href={post.url} target="_blank" title={post.url}>{post.name}</a> : 
-              <Link className="text-body" to={`/post/${post.id}`} title={i18n.t('comments')}>{post.name}</Link>
-              }
+              {post.url ? (
+                <a
+                  className="text-body"
+                  href={post.url}
+                  target="_blank"
+                  title={post.url}
+                >
+                  {post.name}
+                </a>
+              ) : (
+                <Link
+                  className="text-body"
+                  to={`/post/${post.id}`}
+                  title={i18n.t('comments')}
+                >
+                  {post.name}
+                </Link>
+              )}
             </h5>
-            {post.url && 
+            {post.url && (
               <small>
-                <a className="ml-2 text-muted font-italic" href={post.url} target="_blank" title={post.url}>{(new URL(post.url)).hostname}</a>
+                <a
+                  className="ml-2 text-muted font-italic"
+                  href={post.url}
+                  target="_blank"
+                  title={post.url}
+                >
+                  {new URL(post.url).hostname}
+                </a>
               </small>
-            }
-            { post.url && isImage(post.url) && 
+            )}
+            {post.url && isImage(post.url) && (
               <>
-                { !this.state.imageExpanded
-                  ? <span class="text-monospace pointer ml-2 text-muted small" title={i18n.t('expand_here')} onClick={linkEvent(this, this.handleImageExpandClick)}>[+]</span>
-                  : 
+                {!this.state.imageExpanded ? (
+                  <span
+                    class="text-monospace pointer ml-2 text-muted small"
+                    title={i18n.t('expand_here')}
+                    onClick={linkEvent(this, this.handleImageExpandClick)}
+                  >
+                    [+]
+                  </span>
+                ) : (
                   <span>
-                    <span class="text-monospace pointer ml-2 text-muted small" onClick={linkEvent(this, this.handleImageExpandClick)}>[-]</span>
+                    <span
+                      class="text-monospace pointer ml-2 text-muted small"
+                      onClick={linkEvent(this, this.handleImageExpandClick)}
+                    >
+                      [-]
+                    </span>
                     <div>
-                      <span class="pointer" onClick={linkEvent(this, this.handleImageExpandClick)}><img class="img-fluid" src={post.url} /></span>
+                      <span
+                        class="pointer"
+                        onClick={linkEvent(this, this.handleImageExpandClick)}
+                      >
+                        <img class="img-fluid" src={post.url} />
+                      </span>
                     </div>
                   </span>
-                }
+                )}
               </>
-            }
-            {post.removed &&
-              <small className="ml-2 text-muted font-italic"><T i18nKey="removed">#</T></small>
-            }
-            {post.deleted &&
-              <small className="ml-2 text-muted font-italic"><T i18nKey="deleted">#</T></small>
-            }
-            {post.locked &&
-              <small className="ml-2 text-muted font-italic"><T i18nKey="locked">#</T></small>
-            }
-            {post.stickied &&
-              <small className="ml-2 text-muted font-italic"><T i18nKey="stickied">#</T></small>
-            }
-            {post.nsfw &&
-              <small className="ml-2 text-muted font-italic"><T i18nKey="nsfw">#</T></small>
-            }
+            )}
+            {post.removed && (
+              <small className="ml-2 text-muted font-italic">
+                <T i18nKey="removed">#</T>
+              </small>
+            )}
+            {post.deleted && (
+              <small className="ml-2 text-muted font-italic">
+                <T i18nKey="deleted">#</T>
+              </small>
+            )}
+            {post.locked && (
+              <small className="ml-2 text-muted font-italic">
+                <T i18nKey="locked">#</T>
+              </small>
+            )}
+            {post.stickied && (
+              <small className="ml-2 text-muted font-italic">
+                <T i18nKey="stickied">#</T>
+              </small>
+            )}
+            {post.nsfw && (
+              <small className="ml-2 text-muted font-italic">
+                <T i18nKey="nsfw">#</T>
+              </small>
+            )}
           </div>
         </div>
         <div className="details ml-4">
           <ul class="list-inline mb-0 text-muted small">
             <li className="list-inline-item">
               <span>{i18n.t('by')} </span>
-              <Link className="text-info" to={`/u/${post.creator_name}`}>{post.creator_name}</Link>
-              {this.isMod && 
-                <span className="mx-1 badge badge-light"><T i18nKey="mod">#</T></span>
-              }
-              {this.isAdmin && 
-                <span className="mx-1 badge badge-light"><T i18nKey="admin">#</T></span>
-              }
-              {(post.banned_from_community || post.banned) &&  
-                <span className="mx-1 badge badge-danger"><T i18nKey="banned">#</T></span>
-              }
-              {this.props.showCommunity && 
+              <Link className="text-info" to={`/u/${post.creator_name}`}>
+                {post.creator_name}
+              </Link>
+              {this.isMod && (
+                <span className="mx-1 badge badge-light">
+                  <T i18nKey="mod">#</T>
+                </span>
+              )}
+              {this.isAdmin && (
+                <span className="mx-1 badge badge-light">
+                  <T i18nKey="admin">#</T>
+                </span>
+              )}
+              {(post.banned_from_community || post.banned) && (
+                <span className="mx-1 badge badge-danger">
+                  <T i18nKey="banned">#</T>
+                </span>
+              )}
+              {this.props.showCommunity && (
                 <span>
                   <span> {i18n.t('to')} </span>
-                  <Link to={`/c/${post.community_name}`}>{post.community_name}</Link>
+                  <Link to={`/c/${post.community_name}`}>
+                    {post.community_name}
+                  </Link>
                 </span>
-              }
+              )}
             </li>
             <li className="list-inline-item">
-              <span><MomentTime data={post} /></span>
+              <span>
+                <MomentTime data={post} />
+              </span>
             </li>
             <li className="list-inline-item">
-              <span>(
-                <span className="text-info">+{post.upvotes}</span>
+              <span>
+                (<span className="text-info">+{post.upvotes}</span>
                 <span> | </span>
                 <span className="text-danger">-{post.downvotes}</span>
                 <span>) </span>
               </span>
             </li>
             <li className="list-inline-item">
-              <Link className="text-muted" to={`/post/${post.id}`}><T i18nKey="number_of_comments" interpolation={{count: post.number_of_comments}}>#</T></Link>
+              <Link className="text-muted" to={`/post/${post.id}`}>
+                <T
+                  i18nKey="number_of_comments"
+                  interpolation={{ count: post.number_of_comments }}
+                >
+                  #
+                </T>
+              </Link>
             </li>
           </ul>
-          <ul class="list-inline mb-1 text-muted small font-weight-bold"> 
-            {UserService.Instance.user &&
+          <ul class="list-inline mb-1 text-muted small font-weight-bold">
+            {UserService.Instance.user && (
               <>
-                {this.props.showBody &&
+                {this.props.showBody && (
                   <>
                     <li className="list-inline-item mr-2">
-                      <span class="pointer" onClick={linkEvent(this, this.handleSavePostClick)}>{post.saved ? i18n.t('unsave') : i18n.t('save')}</span>
+                      <span
+                        class="pointer"
+                        onClick={linkEvent(this, this.handleSavePostClick)}
+                      >
+                        {post.saved ? i18n.t('unsave') : i18n.t('save')}
+                      </span>
                     </li>
                     <li className="list-inline-item mr-2">
-                      <Link className="text-muted" to={`/create_post${this.crossPostParams}`}><T i18nKey="cross_post">#</T></Link>
+                      <Link
+                        className="text-muted"
+                        to={`/create_post${this.crossPostParams}`}
+                      >
+                        <T i18nKey="cross_post">#</T>
+                      </Link>
                     </li>
                   </>
-                }
-                {this.myPost && 
+                )}
+                {this.myPost && (
                   <>
                     <li className="list-inline-item">
-                      <span class="pointer" onClick={linkEvent(this, this.handleEditClick)}><T i18nKey="edit">#</T></span>
+                      <span
+                        class="pointer"
+                        onClick={linkEvent(this, this.handleEditClick)}
+                      >
+                        <T i18nKey="edit">#</T>
+                      </span>
                     </li>
                     <li className="list-inline-item mr-2">
-                      <span class="pointer" onClick={linkEvent(this, this.handleDeleteClick)}>
+                      <span
+                        class="pointer"
+                        onClick={linkEvent(this, this.handleDeleteClick)}
+                      >
                         {!post.deleted ? i18n.t('delete') : i18n.t('restore')}
                       </span>
                     </li>
                   </>
-                }
-                {this.canModOnSelf &&
+                )}
+                {this.canModOnSelf && (
                   <>
                     <li className="list-inline-item">
-                      <span class="pointer" onClick={linkEvent(this, this.handleModLock)}>{post.locked ? i18n.t('unlock') : i18n.t('lock')}</span>
+                      <span
+                        class="pointer"
+                        onClick={linkEvent(this, this.handleModLock)}
+                      >
+                        {post.locked ? i18n.t('unlock') : i18n.t('lock')}
+                      </span>
                     </li>
                     <li className="list-inline-item">
-                      <span class="pointer" onClick={linkEvent(this, this.handleModSticky)}>{post.stickied ? i18n.t('unsticky') : i18n.t('sticky')}</span>
+                      <span
+                        class="pointer"
+                        onClick={linkEvent(this, this.handleModSticky)}
+                      >
+                        {post.stickied ? i18n.t('unsticky') : i18n.t('sticky')}
+                      </span>
                     </li>
                   </>
-                }
+                )}
                 {/* Mods can ban from community, and appoint as mods to community */}
-                {(this.canMod || this.canAdmin) &&
+                {(this.canMod || this.canAdmin) && (
                   <li className="list-inline-item">
-                    {!post.removed ? 
-                    <span class="pointer" onClick={linkEvent(this, this.handleModRemoveShow)}><T i18nKey="remove">#</T></span> :
-                    <span class="pointer" onClick={linkEvent(this, this.handleModRemoveSubmit)}><T i18nKey="restore">#</T></span>
-                    }
+                    {!post.removed ? (
+                      <span
+                        class="pointer"
+                        onClick={linkEvent(this, this.handleModRemoveShow)}
+                      >
+                        <T i18nKey="remove">#</T>
+                      </span>
+                    ) : (
+                      <span
+                        class="pointer"
+                        onClick={linkEvent(this, this.handleModRemoveSubmit)}
+                      >
+                        <T i18nKey="restore">#</T>
+                      </span>
+                    )}
                   </li>
-                }
-                {this.canMod && 
+                )}
+                {this.canMod && (
                   <>
-                    {!this.isMod && 
+                    {!this.isMod && (
                       <li className="list-inline-item">
-                        {!post.banned_from_community ? 
-                        <span class="pointer" onClick={linkEvent(this, this.handleModBanFromCommunityShow)}><T i18nKey="ban">#</T></span> :
-                        <span class="pointer" onClick={linkEvent(this, this.handleModBanFromCommunitySubmit)}><T i18nKey="unban">#</T></span>
-                        }
+                        {!post.banned_from_community ? (
+                          <span
+                            class="pointer"
+                            onClick={linkEvent(
+                              this,
+                              this.handleModBanFromCommunityShow
+                            )}
+                          >
+                            <T i18nKey="ban">#</T>
+                          </span>
+                        ) : (
+                          <span
+                            class="pointer"
+                            onClick={linkEvent(
+                              this,
+                              this.handleModBanFromCommunitySubmit
+                            )}
+                          >
+                            <T i18nKey="unban">#</T>
+                          </span>
+                        )}
                       </li>
-                    }
-                    {!post.banned_from_community &&
+                    )}
+                    {!post.banned_from_community && (
                       <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>
+                        <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 &&
+                {(this.amCommunityCreator || this.canAdmin) && this.isMod && (
                   <li className="list-inline-item">
-                    {!this.state.showConfirmTransferCommunity ?
-                    <span class="pointer" onClick={linkEvent(this, this.handleShowConfirmTransferCommunity)}><T i18nKey="transfer_community">#</T>
-                  </span> : <>
-                    <span class="d-inline-block mr-1"><T i18nKey="are_you_sure">#</T></span>
-                    <span class="pointer d-inline-block mr-1" onClick={linkEvent(this, this.handleTransferCommunity)}><T i18nKey="yes">#</T></span>
-                    <span class="pointer d-inline-block" onClick={linkEvent(this, this.handleCancelShowConfirmTransferCommunity)}><T i18nKey="no">#</T></span>
-                  </>
-                    }
+                    {!this.state.showConfirmTransferCommunity ? (
+                      <span
+                        class="pointer"
+                        onClick={linkEvent(
+                          this,
+                          this.handleShowConfirmTransferCommunity
+                        )}
+                      >
+                        <T i18nKey="transfer_community">#</T>
+                      </span>
+                    ) : (
+                      <>
+                        <span class="d-inline-block mr-1">
+                          <T i18nKey="are_you_sure">#</T>
+                        </span>
+                        <span
+                          class="pointer d-inline-block mr-1"
+                          onClick={linkEvent(
+                            this,
+                            this.handleTransferCommunity
+                          )}
+                        >
+                          <T i18nKey="yes">#</T>
+                        </span>
+                        <span
+                          class="pointer d-inline-block"
+                          onClick={linkEvent(
+                            this,
+                            this.handleCancelShowConfirmTransferCommunity
+                          )}
+                        >
+                          <T i18nKey="no">#</T>
+                        </span>
+                      </>
+                    )}
                   </li>
-                }
+                )}
                 {/* Admins can ban from all, and appoint other admins */}
-                {this.canAdmin &&
+                {this.canAdmin && (
                   <>
-                    {!this.isAdmin && 
+                    {!this.isAdmin && (
                       <li className="list-inline-item">
-                        {!post.banned ? 
-                        <span class="pointer" onClick={linkEvent(this, this.handleModBanShow)}><T i18nKey="ban_from_site">#</T></span> :
-                        <span class="pointer" onClick={linkEvent(this, this.handleModBanSubmit)}><T i18nKey="unban_from_site">#</T></span>
-                        }
+                        {!post.banned ? (
+                          <span
+                            class="pointer"
+                            onClick={linkEvent(this, this.handleModBanShow)}
+                          >
+                            <T i18nKey="ban_from_site">#</T>
+                          </span>
+                        ) : (
+                          <span
+                            class="pointer"
+                            onClick={linkEvent(this, this.handleModBanSubmit)}
+                          >
+                            <T i18nKey="unban_from_site">#</T>
+                          </span>
+                        )}
                       </li>
-                    }
-                    {!post.banned &&
+                    )}
+                    {!post.banned && (
                       <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>
+                        <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 &&
+                {this.amSiteCreator && this.isAdmin && (
                   <li className="list-inline-item">
-                    {!this.state.showConfirmTransferSite ?
-                    <span class="pointer" onClick={linkEvent(this, this.handleShowConfirmTransferSite)}><T i18nKey="transfer_site">#</T>
-                  </span> : <>
-                    <span class="d-inline-block mr-1"><T i18nKey="are_you_sure">#</T></span>
-                    <span class="pointer d-inline-block mr-1" onClick={linkEvent(this, this.handleTransferSite)}><T i18nKey="yes">#</T></span>
-                    <span class="pointer d-inline-block" onClick={linkEvent(this, this.handleCancelShowConfirmTransferSite)}><T i18nKey="no">#</T></span>
-                  </>
-                    }
+                    {!this.state.showConfirmTransferSite ? (
+                      <span
+                        class="pointer"
+                        onClick={linkEvent(
+                          this,
+                          this.handleShowConfirmTransferSite
+                        )}
+                      >
+                        <T i18nKey="transfer_site">#</T>
+                      </span>
+                    ) : (
+                      <>
+                        <span class="d-inline-block mr-1">
+                          <T i18nKey="are_you_sure">#</T>
+                        </span>
+                        <span
+                          class="pointer d-inline-block mr-1"
+                          onClick={linkEvent(this, this.handleTransferSite)}
+                        >
+                          <T i18nKey="yes">#</T>
+                        </span>
+                        <span
+                          class="pointer d-inline-block"
+                          onClick={linkEvent(
+                            this,
+                            this.handleCancelShowConfirmTransferSite
+                          )}
+                        >
+                          <T i18nKey="no">#</T>
+                        </span>
+                      </>
+                    )}
                   </li>
-                }
+                )}
               </>
-            }
-            {this.props.showBody && post.body && 
+            )}
+            {this.props.showBody && post.body && (
               <li className="list-inline-item">
-                <span className="pointer" onClick={linkEvent(this, this.handleViewSource)}><T i18nKey="view_source">#</T></span>
+                <span
+                  className="pointer"
+                  onClick={linkEvent(this, this.handleViewSource)}
+                >
+                  <T i18nKey="view_source">#</T>
+                </span>
               </li>
-            }
+            )}
           </ul>
-          {this.state.showRemoveDialog && 
-            <form class="form-inline" onSubmit={linkEvent(this, this.handleModRemoveSubmit)}>
-              <input type="text" class="form-control mr-2" placeholder={i18n.t('reason')} value={this.state.removeReason} onInput={linkEvent(this, this.handleModRemoveReasonChange)} />
-              <button type="submit" class="btn btn-secondary"><T i18nKey="remove_post">#</T></button>
+          {this.state.showRemoveDialog && (
+            <form
+              class="form-inline"
+              onSubmit={linkEvent(this, this.handleModRemoveSubmit)}
+            >
+              <input
+                type="text"
+                class="form-control mr-2"
+                placeholder={i18n.t('reason')}
+                value={this.state.removeReason}
+                onInput={linkEvent(this, this.handleModRemoveReasonChange)}
+              />
+              <button type="submit" class="btn btn-secondary">
+                <T i18nKey="remove_post">#</T>
+              </button>
             </form>
-          }
-          {this.state.showBanDialog && 
+          )}
+          {this.state.showBanDialog && (
             <form onSubmit={linkEvent(this, this.handleModBanBothSubmit)}>
               <div class="form-group row">
-                <label class="col-form-label"><T i18nKey="reason">#</T></label>
-                <input type="text" class="form-control mr-2" placeholder={i18n.t('reason')} value={this.state.banReason} onInput={linkEvent(this, this.handleModBanReasonChange)} />
+                <label class="col-form-label">
+                  <T i18nKey="reason">#</T>
+                </label>
+                <input
+                  type="text"
+                  class="form-control mr-2"
+                  placeholder={i18n.t('reason')}
+                  value={this.state.banReason}
+                  onInput={linkEvent(this, this.handleModBanReasonChange)}
+                />
               </div>
               {/* TODO hold off on expires until later */}
               {/* <div class="form-group row"> */}
-                {/*   <label class="col-form-label">Expires</label> */}
-                {/*   <input type="date" class="form-control mr-2" placeholder={i18n.t('expires')} value={this.state.banExpires} onInput={linkEvent(this, this.handleModBanExpiresChange)} /> */}
-                {/* </div> */}
-                <div class="form-group row">
-                  <button type="submit" class="btn btn-secondary">{i18n.t('ban')} {post.creator_name}</button>
-                </div>
-              </form>
-          }
-            {this.props.showBody && post.body &&
-              <>
-                {this.state.viewSource ? <pre>{post.body}</pre> : 
-                <div className="md-div" dangerouslySetInnerHTML={mdToHtml(post.body)} />
-                }
-              </>
-            }
+              {/*   <label class="col-form-label">Expires</label> */}
+              {/*   <input type="date" class="form-control mr-2" placeholder={i18n.t('expires')} value={this.state.banExpires} onInput={linkEvent(this, this.handleModBanExpiresChange)} /> */}
+              {/* </div> */}
+              <div class="form-group row">
+                <button type="submit" class="btn btn-secondary">
+                  {i18n.t('ban')} {post.creator_name}
+                </button>
+              </div>
+            </form>
+          )}
+          {this.props.showBody && post.body && (
+            <>
+              {this.state.viewSource ? (
+                <pre>{post.body}</pre>
+              ) : (
+                <div
+                  className="md-div"
+                  dangerouslySetInnerHTML={mdToHtml(post.body)}
+                />
+              )}
+            </>
+          )}
         </div>
       </div>
-    )
+    );
   }
 
   private get myPost(): boolean {
-    return UserService.Instance.user && this.props.post.creator_id == UserService.Instance.user.id;
+    return (
+      UserService.Instance.user &&
+      this.props.post.creator_id == UserService.Instance.user.id
+    );
   }
 
   get isMod(): boolean {
-    return this.props.moderators && isMod(this.props.moderators.map(m => m.user_id), this.props.post.creator_id);
+    return (
+      this.props.moderators &&
+      isMod(
+        this.props.moderators.map(m => m.user_id),
+        this.props.post.creator_id
+      )
+    );
   }
 
   get isAdmin(): boolean {
-    return this.props.admins && isMod(this.props.admins.map(a => a.id), this.props.post.creator_id);
+    return (
+      this.props.admins &&
+      isMod(this.props.admins.map(a => a.id), this.props.post.creator_id)
+    );
   }
 
   get canMod(): boolean {
     if (this.props.admins && this.props.moderators) {
-      let adminsThenMods = this.props.admins.map(a => a.id)
-      .concat(this.props.moderators.map(m => m.user_id));
-
-      return canMod(UserService.Instance.user, adminsThenMods, this.props.post.creator_id);
-      } else { 
+      let adminsThenMods = this.props.admins
+        .map(a => a.id)
+        .concat(this.props.moderators.map(m => m.user_id));
+
+      return canMod(
+        UserService.Instance.user,
+        adminsThenMods,
+        this.props.post.creator_id
+      );
+    } else {
       return false;
     }
   }
 
   get canModOnSelf(): boolean {
     if (this.props.admins && this.props.moderators) {
-      let adminsThenMods = this.props.admins.map(a => a.id)
-      .concat(this.props.moderators.map(m => m.user_id));
-
-      return canMod(UserService.Instance.user, adminsThenMods, this.props.post.creator_id, true);
-    } else { 
+      let adminsThenMods = this.props.admins
+        .map(a => a.id)
+        .concat(this.props.moderators.map(m => m.user_id));
+
+      return canMod(
+        UserService.Instance.user,
+        adminsThenMods,
+        this.props.post.creator_id,
+        true
+      );
+    } else {
       return false;
     }
   }
 
   get canAdmin(): boolean {
-    return this.props.admins && canMod(UserService.Instance.user, this.props.admins.map(a => a.id), this.props.post.creator_id);
+    return (
+      this.props.admins &&
+      canMod(
+        UserService.Instance.user,
+        this.props.admins.map(a => a.id),
+        this.props.post.creator_id
+      )
+    );
   }
 
   get amCommunityCreator(): boolean {
-    return this.props.moderators && 
-      UserService.Instance.user && 
-      (this.props.post.creator_id != UserService.Instance.user.id) &&
-      (UserService.Instance.user.id == this.props.moderators[0].user_id);
+    return (
+      this.props.moderators &&
+      UserService.Instance.user &&
+      this.props.post.creator_id != UserService.Instance.user.id &&
+      UserService.Instance.user.id == this.props.moderators[0].user_id
+    );
   }
 
   get amSiteCreator(): boolean {
-    return this.props.admins && 
-      UserService.Instance.user && 
-      (this.props.post.creator_id != UserService.Instance.user.id) &&
-      (UserService.Instance.user.id == this.props.admins[0].id);
+    return (
+      this.props.admins &&
+      UserService.Instance.user &&
+      this.props.post.creator_id != UserService.Instance.user.id &&
+      UserService.Instance.user.id == this.props.admins[0].id
+    );
   }
 
   handlePostLike(i: PostListing) {
-
     let form: CreatePostLikeForm = {
       post_id: i.props.post.id,
-      score: (i.props.post.my_vote == 1) ? 0 : 1
+      score: i.props.post.my_vote == 1 ? 0 : 1,
     };
     WebSocketService.Instance.likePost(form);
   }
@@ -383,7 +706,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
   handlePostDisLike(i: PostListing) {
     let form: CreatePostLikeForm = {
       post_id: i.props.post.id,
-      score: (i.props.post.my_vote == -1) ? 0 : -1
+      score: i.props.post.my_vote == -1 ? 0 : -1,
     };
     WebSocketService.Instance.likePost(form);
   }
@@ -414,16 +737,16 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
       creator_id: i.props.post.creator_id,
       deleted: !i.props.post.deleted,
       nsfw: i.props.post.nsfw,
-      auth: null
+      auth: null,
     };
     WebSocketService.Instance.editPost(deleteForm);
   }
 
   handleSavePostClick(i: PostListing) {
-    let saved = (i.props.post.saved == undefined) ? true : !i.props.post.saved;
+    let saved = i.props.post.saved == undefined ? true : !i.props.post.saved;
     let form: SavePostForm = {
       post_id: i.props.post.id,
-      save: saved
+      save: saved,
     };
 
     WebSocketService.Instance.savePost(form);
@@ -573,12 +896,12 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
     i.setState(i.state);
   }
 
-  handleShowConfirmTransferCommunity(i: PostListing) { 
+  handleShowConfirmTransferCommunity(i: PostListing) {
     i.state.showConfirmTransferCommunity = true;
     i.setState(i.state);
   }
 
-  handleCancelShowConfirmTransferCommunity(i: PostListing) { 
+  handleCancelShowConfirmTransferCommunity(i: PostListing) {
     i.state.showConfirmTransferCommunity = false;
     i.setState(i.state);
   }
@@ -593,12 +916,12 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
     i.setState(i.state);
   }
 
-  handleShowConfirmTransferSite(i: PostListing) { 
+  handleShowConfirmTransferSite(i: PostListing) {
     i.state.showConfirmTransferSite = true;
     i.setState(i.state);
   }
 
-  handleCancelShowConfirmTransferSite(i: PostListing) { 
+  handleCancelShowConfirmTransferSite(i: PostListing) {
     i.state.showConfirmTransferSite = false;
     i.setState(i.state);
   }
@@ -622,4 +945,3 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
     i.setState(i.state);
   }
 }
-
index 833c8e616b3cdbe7caaec5c0bdc6587ca9bf8829..b65c919290fd2e1201c7113e57165435edc12e08 100644 (file)
@@ -10,7 +10,6 @@ interface PostListingsProps {
 }
 
 export class PostListings extends Component<PostListingsProps, any> {
-
   constructor(props: any, context: any) {
     super(props, context);
   }
@@ -18,19 +17,32 @@ export class PostListings extends Component<PostListingsProps, any> {
   render() {
     return (
       <div>
-        {this.props.posts.length > 0 ? this.props.posts.map(post => 
-          <>
-            <PostListing post={post} showCommunity={this.props.showCommunity} />
-            <hr class="d-md-none my-2" />
-            <div class="d-none d-md-block my-2"></div>
-          </>
-            ) : 
+        {this.props.posts.length > 0 ? (
+          this.props.posts.map(post => (
+            <>
+              <PostListing
+                post={post}
+                showCommunity={this.props.showCommunity}
+              />
+              <hr class="d-md-none my-2" />
+              <div class="d-none d-md-block my-2"></div>
+            </>
+          ))
+        ) : (
           <>
-            <div><T i18nKey="no_posts">#</T></div>
-            {this.props.showCommunity !== undefined  && <div><T i18nKey="subscribe_to_communities">#<Link to="/communities">#</Link></T></div>}
+            <div>
+              <T i18nKey="no_posts">#</T>
+            </div>
+            {this.props.showCommunity !== undefined && (
+              <div>
+                <T i18nKey="subscribe_to_communities">
+                  #<Link to="/communities">#</Link>
+                </T>
+              </div>
+            )}
           </>
-        }
+        )}
       </div>
-    )
+    );
   }
 }
index 9e20aa29a79f41367adb760c613e593e2213c75c..a86ce2f4546db57b7ef0773793bba6e4bfd80394 100644 (file)
@@ -1,7 +1,32 @@
 import { Component, linkEvent } from 'inferno';
-import { Subscription } from "rxjs";
+import { Subscription } from 'rxjs';
 import { retryWhen, delay, take } from 'rxjs/operators';
-import { UserOperation, Community, Post as PostI, GetPostResponse, PostResponse, Comment, CommentForm as CommentFormI, CommentResponse, CommentSortType, CreatePostLikeResponse, CommunityUser, CommunityResponse, CommentNode as CommentNodeI, BanFromCommunityResponse, BanUserResponse, AddModToCommunityResponse, AddAdminResponse, UserView, SearchType, SortType, SearchForm, SearchResponse, GetSiteResponse, GetCommunityResponse } from '../interfaces';
+import {
+  UserOperation,
+  Community,
+  Post as PostI,
+  GetPostResponse,
+  PostResponse,
+  Comment,
+  CommentForm as CommentFormI,
+  CommentResponse,
+  CommentSortType,
+  CreatePostLikeResponse,
+  CommunityUser,
+  CommunityResponse,
+  CommentNode as CommentNodeI,
+  BanFromCommunityResponse,
+  BanUserResponse,
+  AddModToCommunityResponse,
+  AddAdminResponse,
+  UserView,
+  SearchType,
+  SortType,
+  SearchForm,
+  SearchResponse,
+  GetSiteResponse,
+  GetCommunityResponse,
+} from '../interfaces';
 import { WebSocketService, UserService } from '../services';
 import { msgOp, hotRank } from '../utils';
 import { PostListing } from './post-listing';
@@ -27,7 +52,6 @@ interface PostState {
 }
 
 export class Post extends Component<any, PostState> {
-
   private subscription: Subscription;
   private emptyState: PostState = {
     post: null,
@@ -36,10 +60,10 @@ export class Post extends Component<any, PostState> {
     community: null,
     moderators: [],
     admins: [],
-    scrolled: false, 
+    scrolled: false,
     loading: true,
     crossPosts: [],
-  }
+  };
 
   constructor(props: any, context: any) {
     super(props, context);
@@ -52,10 +76,17 @@ export class Post extends Component<any, PostState> {
     }
 
     this.subscription = WebSocketService.Instance.subject
-      .pipe(retryWhen(errors => errors.pipe(delay(3000), take(10))))
+      .pipe(
+        retryWhen(errors =>
+          errors.pipe(
+            delay(3000),
+            take(10)
+          )
+        )
+      )
       .subscribe(
-        (msg) => this.parseMessage(msg),
-        (err) => console.error(err),
+        msg => this.parseMessage(msg),
+        err => console.error(err),
         () => console.log('complete')
       );
 
@@ -71,10 +102,16 @@ export class Post extends Component<any, PostState> {
   }
 
   componentDidUpdate(_lastProps: any, lastState: PostState, _snapshot: any) {
-    if (this.state.scrolled_comment_id && !this.state.scrolled && lastState.comments.length > 0) {
-      var elmnt = document.getElementById(`comment-${this.state.scrolled_comment_id}`);
-      elmnt.scrollIntoView(); 
-      elmnt.classList.add("mark");
+    if (
+      this.state.scrolled_comment_id &&
+      !this.state.scrolled &&
+      lastState.comments.length > 0
+    ) {
+      var elmnt = document.getElementById(
+        `comment-${this.state.scrolled_comment_id}`
+      );
+      elmnt.scrollIntoView();
+      elmnt.classList.add('mark');
       this.state.scrolled = true;
       this.markScrolledAsRead(this.state.scrolled_comment_id);
     }
@@ -89,17 +126,20 @@ export class Post extends Component<any, PostState> {
       // this.context.router.history.push('/sponsors');
       // this.context.refresh();
       // this.context.router.history.push(_lastProps.location.pathname);
-
     }
   }
 
   markScrolledAsRead(commentId: number) {
     let found = this.state.comments.find(c => c.id == commentId);
     let parent = this.state.comments.find(c => found.parent_id == c.id);
-    let parent_user_id = parent ? parent.creator_id : this.state.post.creator_id;
-
-    if (UserService.Instance.user && UserService.Instance.user.id == parent_user_id) {
-
+    let parent_user_id = parent
+      ? parent.creator_id
+      : this.state.post.creator_id;
+
+    if (
+      UserService.Instance.user &&
+      UserService.Instance.user.id == parent_user_id
+    ) {
       let form: CommentFormI = {
         content: found.content,
         edit_id: found.id,
@@ -107,7 +147,7 @@ export class Post extends Component<any, PostState> {
         post_id: found.post_id,
         parent_id: found.parent_id,
         read: true,
-        auth: null
+        auth: null,
       };
       WebSocketService.Instance.editComment(form);
     }
@@ -116,26 +156,36 @@ export class Post extends Component<any, PostState> {
   render() {
     return (
       <div class="container">
-        {this.state.loading ? 
-        <h5><svg class="icon icon-spinner spin"><use xlinkHref="#icon-spinner"></use></svg></h5> : 
-        <div class="row">
+        {this.state.loading ? (
+          <h5>
+            <svg class="icon icon-spinner spin">
+              <use xlinkHref="#icon-spinner"></use>
+            </svg>
+          </h5>
+        ) : (
+          <div class="row">
             <div class="col-12 col-md-8 mb-3">
-              <PostListing 
-                post={this.state.post} 
-                showBody 
-                showCommunity 
-                editable 
-                moderators={this.state.moderators} 
+              <PostListing
+                post={this.state.post}
+                showBody
+                showCommunity
+                editable
+                moderators={this.state.moderators}
                 admins={this.state.admins}
               />
-              {this.state.crossPosts.length > 0 && 
+              {this.state.crossPosts.length > 0 && (
                 <>
-                  <div class="my-1 text-muted small font-weight-bold"><T i18nKey="cross_posts">#</T></div>
+                  <div class="my-1 text-muted small font-weight-bold">
+                    <T i18nKey="cross_posts">#</T>
+                  </div>
                   <PostListings showCommunity posts={this.state.crossPosts} />
                 </>
-              }
+              )}
               <div className="mb-2" />
-              <CommentForm postId={this.state.post.id} disabled={this.state.post.locked} />
+              <CommentForm
+                postId={this.state.post.id}
+                disabled={this.state.post.locked}
+              />
               {this.sortRadios()}
               {this.commentsTree()}
             </div>
@@ -144,65 +194,88 @@ export class Post extends Component<any, PostState> {
               {this.sidebar()}
             </div>
           </div>
-        }
+        )}
       </div>
-    )
+    );
   }
 
   sortRadios() {
     return (
       <div class="btn-group btn-group-toggle mb-3">
-        <label className={`btn btn-sm btn-secondary pointer ${this.state.commentSort === CommentSortType.Hot && 'active'}`}>{i18n.t('hot')}
-          <input type="radio" value={CommentSortType.Hot}
-          checked={this.state.commentSort === CommentSortType.Hot} 
-          onChange={linkEvent(this, this.handleCommentSortChange)}  />
+        <label
+          className={`btn btn-sm btn-secondary pointer ${this.state
+            .commentSort === CommentSortType.Hot && 'active'}`}
+        >
+          {i18n.t('hot')}
+          <input
+            type="radio"
+            value={CommentSortType.Hot}
+            checked={this.state.commentSort === CommentSortType.Hot}
+            onChange={linkEvent(this, this.handleCommentSortChange)}
+          />
         </label>
-        <label className={`btn btn-sm btn-secondary pointer ${this.state.commentSort === CommentSortType.Top && 'active'}`}>{i18n.t('top')}
-          <input type="radio" value={CommentSortType.Top}
-          checked={this.state.commentSort === CommentSortType.Top} 
-          onChange={linkEvent(this, this.handleCommentSortChange)}  />
+        <label
+          className={`btn btn-sm btn-secondary pointer ${this.state
+            .commentSort === CommentSortType.Top && 'active'}`}
+        >
+          {i18n.t('top')}
+          <input
+            type="radio"
+            value={CommentSortType.Top}
+            checked={this.state.commentSort === CommentSortType.Top}
+            onChange={linkEvent(this, this.handleCommentSortChange)}
+          />
         </label>
-        <label className={`btn btn-sm btn-secondary pointer ${this.state.commentSort === CommentSortType.New && 'active'}`}>{i18n.t('new')}
-          <input type="radio" value={CommentSortType.New}
-          checked={this.state.commentSort === CommentSortType.New} 
-          onChange={linkEvent(this, this.handleCommentSortChange)}  />
+        <label
+          className={`btn btn-sm btn-secondary pointer ${this.state
+            .commentSort === CommentSortType.New && 'active'}`}
+        >
+          {i18n.t('new')}
+          <input
+            type="radio"
+            value={CommentSortType.New}
+            checked={this.state.commentSort === CommentSortType.New}
+            onChange={linkEvent(this, this.handleCommentSortChange)}
+          />
         </label>
       </div>
-    )
+    );
   }
 
   newComments() {
     return (
       <div class="d-none d-md-block new-comments mb-3 card border-secondary">
         <div class="card-body small">
-          <h6><T i18nKey="recent_comments">#</T></h6>
-          {this.state.comments.map(comment => 
-            <CommentNodes 
-              nodes={[{comment: comment}]} 
-              noIndent 
-              locked={this.state.post.locked} 
-              moderators={this.state.moderators} 
+          <h6>
+            <T i18nKey="recent_comments">#</T>
+          </h6>
+          {this.state.comments.map(comment => (
+            <CommentNodes
+              nodes={[{ comment: comment }]}
+              noIndent
+              locked={this.state.post.locked}
+              moderators={this.state.moderators}
               admins={this.state.admins}
               postCreatorId={this.state.post.creator_id}
             />
-          )}
+          ))}
         </div>
       </div>
-    )
+    );
   }
 
   sidebar() {
-    return ( 
+    return (
       <div class="mb-3">
-        <Sidebar 
-          community={this.state.community} 
-          moderators={this.state.moderators} 
+        <Sidebar
+          community={this.state.community}
+          moderators={this.state.moderators}
           admins={this.state.admins}
         />
       </div>
     );
   }
-  
+
   handleCommentSortChange(i: Post, event: any) {
     i.state.commentSort = Number(event.target.value);
     i.setState(i.state);
@@ -213,16 +286,15 @@ export class Post extends Component<any, PostState> {
     for (let comment of this.state.comments) {
       let node: CommentNodeI = {
         comment: comment,
-        children: []
+        children: [],
       };
       map.set(comment.id, { ...node });
     }
     let tree: Array<CommentNodeI> = [];
     for (let comment of this.state.comments) {
-      if( comment.parent_id ) {
+      if (comment.parent_id) {
         map.get(comment.parent_id).children.push(map.get(comment.id));
-      } 
-      else {
+      } else {
         tree.push(map.get(comment.id));
       }
     }
@@ -233,36 +305,43 @@ export class Post extends Component<any, PostState> {
   }
 
   sortTree(tree: Array<CommentNodeI>) {
-
     // First, put removed and deleted comments at the bottom, then do your other sorts
     if (this.state.commentSort == CommentSortType.Top) {
-      tree.sort((a, b) => (+a.comment.removed - +b.comment.removed) || 
-                (+a.comment.deleted - +b.comment.deleted ) || 
-                (b.comment.score - a.comment.score));
+      tree.sort(
+        (a, b) =>
+          +a.comment.removed - +b.comment.removed ||
+          +a.comment.deleted - +b.comment.deleted ||
+          b.comment.score - a.comment.score
+      );
     } else if (this.state.commentSort == CommentSortType.New) {
-      tree.sort((a, b) => (+a.comment.removed - +b.comment.removed) || 
-                (+a.comment.deleted - +b.comment.deleted ) || 
-                (b.comment.published.localeCompare(a.comment.published)));
+      tree.sort(
+        (a, b) =>
+          +a.comment.removed - +b.comment.removed ||
+          +a.comment.deleted - +b.comment.deleted ||
+          b.comment.published.localeCompare(a.comment.published)
+      );
     } else if (this.state.commentSort == CommentSortType.Hot) {
-      tree.sort((a, b) => (+a.comment.removed - +b.comment.removed) || 
-                (+a.comment.deleted - +b.comment.deleted ) || 
-                (hotRank(b.comment) - hotRank(a.comment)));
+      tree.sort(
+        (a, b) =>
+          +a.comment.removed - +b.comment.removed ||
+          +a.comment.deleted - +b.comment.deleted ||
+          hotRank(b.comment) - hotRank(a.comment)
+      );
     }
 
     for (let node of tree) {
       this.sortTree(node.children);
     }
-
   }
 
   commentsTree() {
     let nodes = this.buildCommentsTree();
     return (
       <div>
-        <CommentNodes 
-          nodes={nodes} 
-          locked={this.state.post.locked} 
-          moderators={this.state.moderators} 
+        <CommentNodes
+          nodes={nodes}
+          locked={this.state.post.locked}
+          moderators={this.state.moderators}
           admins={this.state.admins}
           postCreatorId={this.state.post.creator_id}
         />
@@ -286,7 +365,7 @@ export class Post extends Component<any, PostState> {
       this.state.loading = false;
       document.title = `${this.state.post.name} - ${WebSocketService.Instance.site.name}`;
 
-      // Get cross-posts  
+      // Get cross-posts
       if (this.state.post.url) {
         let form: SearchForm = {
           q: this.state.post.url,
@@ -297,7 +376,7 @@ export class Post extends Component<any, PostState> {
         };
         WebSocketService.Instance.search(form);
       }
-      
+
       this.setState(this.state);
     } else if (op == UserOperation.CreateComment) {
       let res: CommentResponse = msg;
@@ -323,12 +402,13 @@ export class Post extends Component<any, PostState> {
       this.setState(this.state);
     } else if (op == UserOperation.CreateCommentLike) {
       let res: CommentResponse = msg;
-      let found: Comment = this.state.comments.find(c => c.id === res.comment.id);
+      let found: Comment = this.state.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;
+      if (res.comment.my_vote !== null) found.my_vote = res.comment.my_vote;
       this.setState(this.state);
     } else if (op == UserOperation.CreatePostLike) {
       let res: CreatePostLikeResponse = msg;
@@ -354,13 +434,15 @@ export class Post extends Component<any, PostState> {
     } else if (op == UserOperation.FollowCommunity) {
       let res: CommunityResponse = msg;
       this.state.community.subscribed = res.community.subscribed;
-      this.state.community.number_of_subscribers = res.community.number_of_subscribers;
+      this.state.community.number_of_subscribers =
+        res.community.number_of_subscribers;
       this.setState(this.state);
     } else if (op == UserOperation.BanFromCommunity) {
       let res: BanFromCommunityResponse = msg;
-      this.state.comments.filter(c => c.creator_id == res.user.id)
-      .forEach(c => c.banned_from_community = res.banned);
-      if (this.state.post.creator_id == res.user.id) {  
+      this.state.comments
+        .filter(c => c.creator_id == res.user.id)
+        .forEach(c => (c.banned_from_community = res.banned));
+      if (this.state.post.creator_id == res.user.id) {
         this.state.post.banned_from_community = res.banned;
       }
       this.setState(this.state);
@@ -370,9 +452,10 @@ export class Post extends Component<any, PostState> {
       this.setState(this.state);
     } else if (op == UserOperation.BanUser) {
       let res: BanUserResponse = msg;
-      this.state.comments.filter(c => c.creator_id == res.user.id)
-      .forEach(c => c.banned = res.banned);
-      if (this.state.post.creator_id == res.user.id) {  
+      this.state.comments
+        .filter(c => c.creator_id == res.user.id)
+        .forEach(c => (c.banned = res.banned));
+      if (this.state.post.creator_id == res.user.id) {
         this.state.post.banned = res.banned;
       }
       this.setState(this.state);
@@ -384,21 +467,17 @@ export class Post extends Component<any, PostState> {
       let res: SearchResponse = msg;
       this.state.crossPosts = res.posts.filter(p => p.id != this.state.post.id);
       this.setState(this.state);
-    } else if (op == UserOperation.TransferSite) { 
+    } else if (op == UserOperation.TransferSite) {
       let res: GetSiteResponse = msg;
 
       this.state.admins = res.admins;
       this.setState(this.state);
-    } else if (op == UserOperation.TransferCommunity) { 
+    } else if (op == UserOperation.TransferCommunity) {
       let res: GetCommunityResponse = msg;
       this.state.community = res.community;
       this.state.moderators = res.moderators;
       this.state.admins = res.admins;
       this.setState(this.state);
     }
-
   }
 }
-
-
-
index 42e1f3173650d93b23830ce681a6c0ef55f25ea3..daf9aa2d811255baf05b8df7dfe26adb4a2e32ca 100644 (file)
@@ -1,26 +1,40 @@
 import { Component, linkEvent } from 'inferno';
 import { Link } from 'inferno-router';
-import { Subscription } from "rxjs";
+import { Subscription } from 'rxjs';
 import { retryWhen, delay, take } from 'rxjs/operators';
-import { UserOperation, Post, Comment, Community, UserView, SortType, SearchForm, SearchResponse, SearchType } from '../interfaces';
+import {
+  UserOperation,
+  Post,
+  Comment,
+  Community,
+  UserView,
+  SortType,
+  SearchForm,
+  SearchResponse,
+  SearchType,
+} from '../interfaces';
 import { WebSocketService } from '../services';
-import { msgOp, fetchLimit, routeSearchTypeToEnum, routeSortTypeToEnum } from '../utils';
+import {
+  msgOp,
+  fetchLimit,
+  routeSearchTypeToEnum,
+  routeSortTypeToEnum,
+} from '../utils';
 import { PostListing } from './post-listing';
 import { CommentNodes } from './comment-nodes';
 import { i18n } from '../i18next';
 import { T } from 'inferno-i18next';
 
 interface SearchState {
-  q: string,
-  type_: SearchType,
-  sort: SortType,
-  page: number,
+  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: this.getSearchQueryFromProps(this.props),
@@ -36,26 +50,26 @@ export class Search extends Component<any, SearchState> {
       users: [],
     },
     loading: false,
-  }
+  };
 
   getSearchQueryFromProps(props: any): string {
-    return (props.match.params.q) ? props.match.params.q : '';
+    return props.match.params.q ? props.match.params.q : '';
   }
 
   getSearchTypeFromProps(props: any): SearchType {
-    return (props.match.params.type) ? 
-      routeSearchTypeToEnum(props.match.params.type) : 
-      SearchType.All;
+    return props.match.params.type
+      ? routeSearchTypeToEnum(props.match.params.type)
+      SearchType.All;
   }
 
   getSortTypeFromProps(props: any): SortType {
-    return (props.match.params.sort) ? 
-      routeSortTypeToEnum(props.match.params.sort) : 
-      SortType.TopAll;
+    return props.match.params.sort
+      ? routeSortTypeToEnum(props.match.params.sort)
+      SortType.TopAll;
   }
 
   getPageFromProps(props: any): number {
-    return (props.match.params.page) ? Number(props.match.params.page) : 1;
+    return props.match.params.page ? Number(props.match.params.page) : 1;
   }
 
   constructor(props: any, context: any) {
@@ -64,17 +78,23 @@ export class Search extends Component<any, SearchState> {
     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),
+      .pipe(
+        retryWhen(errors =>
+          errors.pipe(
+            delay(3000),
+            take(10)
+          )
+        )
+      )
+      .subscribe(
+        msg => this.parseMessage(msg),
+        err => console.error(err),
         () => console.log('complete')
-    );
-    
+      );
+
     if (this.state.q) {
       this.search();
     }
-
   }
 
   componentWillUnmount() {
@@ -83,7 +103,10 @@ export class Search extends Component<any, SearchState> {
 
   // Necessary for back button for some reason
   componentWillReceiveProps(nextProps: any) {
-    if (nextProps.history.action == 'POP' || nextProps.history.action == 'PUSH') {
+    if (
+      nextProps.history.action == 'POP' ||
+      nextProps.history.action == 'PUSH'
+    ) {
       this.state = this.emptyState;
       this.state.q = this.getSearchQueryFromProps(nextProps);
       this.state.type_ = this.getSearchTypeFromProps(nextProps);
@@ -95,7 +118,9 @@ export class Search extends Component<any, SearchState> {
   }
 
   componentDidMount() {
-    document.title = `${i18n.t('search')} - ${WebSocketService.Instance.site.name}`;
+    document.title = `${i18n.t('search')} - ${
+      WebSocketService.Instance.site.name
+    }`;
   }
 
   render() {
@@ -103,77 +128,129 @@ export class Search extends Component<any, SearchState> {
       <div class="container">
         <div class="row">
           <div class="col-12">
-            <h5><T i18nKey="search">#</T></h5>
+            <h5>
+              <T i18nKey="search">#</T>
+            </h5>
             {this.selects()}
             {this.searchForm()}
-            {this.state.type_ == SearchType.All &&
-              this.all()
-            }
-            {this.state.type_ == SearchType.Comments &&
-              this.comments()
-            }
-            {this.state.type_ == SearchType.Posts &&
-              this.posts()
-            }
-            {this.state.type_ == SearchType.Communities &&
-              this.communities()
-            }
-            {this.state.type_ == SearchType.Users &&
-              this.users()
-            }
+            {this.state.type_ == SearchType.All && this.all()}
+            {this.state.type_ == SearchType.Comments && this.comments()}
+            {this.state.type_ == SearchType.Posts && this.posts()}
+            {this.state.type_ == SearchType.Communities && this.communities()}
+            {this.state.type_ == SearchType.Users && this.users()}
             {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={`${i18n.t('search')}...`} onInput={linkEvent(this, this.handleQChange)} required minLength={3} />
+      <form
+        class="form-inline"
+        onSubmit={linkEvent(this, this.handleSearchSubmit)}
+      >
+        <input
+          type="text"
+          class="form-control mr-2"
+          value={this.state.q}
+          placeholder={`${i18n.t('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><T i18nKey="search">#</T></span>
-          }
+          {this.state.loading ? (
+            <svg class="icon icon-spinner spin">
+              <use xlinkHref="#icon-spinner"></use>
+            </svg>
+          ) : (
+            <span>
+              <T i18nKey="search">#</T>
+            </span>
+          )}
         </button>
       </form>
-    )
+    );
   }
 
   selects() {
     return (
       <div className="mb-2">
-        <select value={this.state.type_} onChange={linkEvent(this, this.handleTypeChange)} class="custom-select custom-select-sm w-auto">
-          <option disabled><T i18nKey="type">#</T></option>
-          <option value={SearchType.All}><T i18nKey="all">#</T></option>
-          <option value={SearchType.Comments}><T i18nKey="comments">#</T></option>
-          <option value={SearchType.Posts}><T i18nKey="posts">#</T></option>
-          <option value={SearchType.Communities}><T i18nKey="communities">#</T></option>
-          <option value={SearchType.Users}><T i18nKey="users">#</T></option>
+        <select
+          value={this.state.type_}
+          onChange={linkEvent(this, this.handleTypeChange)}
+          class="custom-select custom-select-sm w-auto"
+        >
+          <option disabled>
+            <T i18nKey="type">#</T>
+          </option>
+          <option value={SearchType.All}>
+            <T i18nKey="all">#</T>
+          </option>
+          <option value={SearchType.Comments}>
+            <T i18nKey="comments">#</T>
+          </option>
+          <option value={SearchType.Posts}>
+            <T i18nKey="posts">#</T>
+          </option>
+          <option value={SearchType.Communities}>
+            <T i18nKey="communities">#</T>
+          </option>
+          <option value={SearchType.Users}>
+            <T i18nKey="users">#</T>
+          </option>
         </select>
-        <select value={this.state.sort} onChange={linkEvent(this, this.handleSortChange)} class="custom-select custom-select-sm w-auto ml-2">
-          <option disabled><T i18nKey="sort_type">#</T></option>
-          <option value={SortType.New}><T i18nKey="new">#</T></option>
-          <option value={SortType.TopDay}><T i18nKey="top_day">#</T></option>
-          <option value={SortType.TopWeek}><T i18nKey="week">#</T></option>
-          <option value={SortType.TopMonth}><T i18nKey="month">#</T></option>
-          <option value={SortType.TopYear}><T i18nKey="year">#</T></option>
-          <option value={SortType.TopAll}><T i18nKey="all">#</T></option>
+        <select
+          value={this.state.sort}
+          onChange={linkEvent(this, this.handleSortChange)}
+          class="custom-select custom-select-sm w-auto ml-2"
+        >
+          <option disabled>
+            <T i18nKey="sort_type">#</T>
+          </option>
+          <option value={SortType.New}>
+            <T i18nKey="new">#</T>
+          </option>
+          <option value={SortType.TopDay}>
+            <T i18nKey="top_day">#</T>
+          </option>
+          <option value={SortType.TopWeek}>
+            <T i18nKey="week">#</T>
+          </option>
+          <option value={SortType.TopMonth}>
+            <T i18nKey="month">#</T>
+          </option>
+          <option value={SortType.TopYear}>
+            <T i18nKey="year">#</T>
+          </option>
+          <option value={SortType.TopAll}>
+            <T i18nKey="all">#</T>
+          </option>
         </select>
       </div>
-    )
-
+    );
   }
 
   all() {
-    let combined: Array<{type_: string, data: Comment | Post | Community | UserView}> = [];
-    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}});
-    let communities = this.state.searchResponse.communities.map(e => {return {type_: "communities", data: e}});
-    let users = this.state.searchResponse.users.map(e => {return {type_: "users", data: e}});
+    let combined: Array<{
+      type_: string;
+      data: Comment | Post | Community | UserView;
+    }> = [];
+    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 };
+    });
+    let communities = this.state.searchResponse.communities.map(e => {
+      return { type_: 'communities', data: e };
+    });
+    let users = this.state.searchResponse.users.map(e => {
+      return { type_: 'users', data: e };
+    });
 
     combined.push(...comments);
     combined.push(...posts);
@@ -184,49 +261,68 @@ export class Search extends Component<any, SearchState> {
     if (this.state.sort == SortType.New) {
       combined.sort((a, b) => b.data.published.localeCompare(a.data.published));
     } else {
-      combined.sort((a, b) => ((b.data as Comment | Post).score 
-        | (b.data as Community).number_of_subscribers
-          | (b.data as UserView).comment_score) 
-          - ((a.data as Comment | Post).score 
-            | (a.data as Community).number_of_subscribers 
-              | (a.data as UserView).comment_score));
+      combined.sort(
+        (a, b) =>
+          ((b.data as Comment | Post).score |
+            (b.data as Community).number_of_subscribers |
+            (b.data as UserView).comment_score) -
+          ((a.data as Comment | Post).score |
+            (a.data as Community).number_of_subscribers |
+            (a.data as UserView).comment_score)
+      );
     }
 
     return (
       <div>
-        {combined.map(i =>
+        {combined.map(i => (
           <div>
-            {i.type_ == "posts" &&
+            {i.type_ == 'posts' && (
               <PostListing post={i.data as Post} showCommunity viewOnly />
-            }
-            {i.type_ == "comments" && 
-              <CommentNodes nodes={[{comment: i.data as Comment}]} viewOnly noIndent />
-            }
-            {i.type_ == "communities" && 
+            )}
+            {i.type_ == 'comments' && (
+              <CommentNodes
+                nodes={[{ comment: i.data as Comment }]}
+                viewOnly
+                noIndent
+              />
+            )}
+            {i.type_ == 'communities' && (
               <div>
-                <span><Link to={`/c/${(i.data as Community).name}`}>{`/c/${(i.data as Community).name}`}</Link></span>
-                <span>{` - ${(i.data as Community).title} - ${(i.data as Community).number_of_subscribers} subscribers`}</span>
+                <span>
+                  <Link to={`/c/${(i.data as Community).name}`}>{`/c/${
+                    (i.data as Community).name
+                  }`}</Link>
+                </span>
+                <span>{` - ${(i.data as Community).title} - ${
+                  (i.data as Community).number_of_subscribers
+                } subscribers`}</span>
               </div>
-            }
-            {i.type_ == "users" && 
+            )}
+            {i.type_ == 'users' && (
               <div>
-                <span><Link className="text-info" to={`/u/${(i.data as UserView).name}`}>{`/u/${(i.data as UserView).name}`}</Link></span>
-                <span>{` - ${(i.data as UserView).comment_score} comment karma`}</span>
+                <span>
+                  <Link
+                    className="text-info"
+                    to={`/u/${(i.data as UserView).name}`}
+                  >{`/u/${(i.data as UserView).name}`}</Link>
+                </span>
+                <span>{` - ${
+                  (i.data as UserView).comment_score
+                } comment karma`}</span>
               </div>
-            }
+            )}
           </div>
-                     )
-        }
+        ))}
       </div>
-    )
+    );
   }
 
   comments() {
     return (
       <div>
-        {this.state.searchResponse.comments.map(comment => 
-          <CommentNodes nodes={[{comment: comment}]} noIndent viewOnly />
-        )}
+        {this.state.searchResponse.comments.map(comment => (
+          <CommentNodes nodes={[{ comment: comment }]} noIndent viewOnly />
+        ))}
       </div>
     );
   }
@@ -234,9 +330,9 @@ export class Search extends Component<any, SearchState> {
   posts() {
     return (
       <div>
-        {this.state.searchResponse.posts.map(post => 
+        {this.state.searchResponse.posts.map(post => (
           <PostListing post={post} showCommunity viewOnly />
-        )}
+        ))}
       </div>
     );
   }
@@ -245,12 +341,14 @@ export class Search extends Component<any, SearchState> {
   communities() {
     return (
       <div>
-        {this.state.searchResponse.communities.map(community => 
+        {this.state.searchResponse.communities.map(community => (
           <div>
-            <span><Link to={`/c/${community.name}`}>{`/c/${community.name}`}</Link></span>
+            <span>
+              <Link to={`/c/${community.name}`}>{`/c/${community.name}`}</Link>
+            </span>
             <span>{` - ${community.title} - ${community.number_of_subscribers} subscribers`}</span>
           </div>
-        )}
+        ))}
       </div>
     );
   }
@@ -258,12 +356,17 @@ export class Search extends Component<any, SearchState> {
   users() {
     return (
       <div>
-        {this.state.searchResponse.users.map(user => 
+        {this.state.searchResponse.users.map(user => (
           <div>
-            <span><Link className="text-info" to={`/u/${user.name}`}>{`/u/${user.name}`}</Link></span>
+            <span>
+              <Link
+                className="text-info"
+                to={`/u/${user.name}`}
+              >{`/u/${user.name}`}</Link>
+            </span>
             <span>{` - ${user.comment_score} comment karma`}</span>
           </div>
-        )}
+        ))}
       </div>
     );
   }
@@ -271,10 +374,20 @@ export class Search extends Component<any, SearchState> {
   paginator() {
     return (
       <div class="mt-2">
-        {this.state.page > 1 && 
-          <button class="btn btn-sm btn-secondary mr-1" onClick={linkEvent(this, this.prevPage)}><T i18nKey="prev">#</T></button>
-        }
-        <button class="btn btn-sm btn-secondary" onClick={linkEvent(this, this.nextPage)}><T i18nKey="next">#</T></button>
+        {this.state.page > 1 && (
+          <button
+            class="btn btn-sm btn-secondary mr-1"
+            onClick={linkEvent(this, this.prevPage)}
+          >
+            <T i18nKey="prev">#</T>
+          </button>
+        )}
+        <button
+          class="btn btn-sm btn-secondary"
+          onClick={linkEvent(this, this.nextPage)}
+        >
+          <T i18nKey="next">#</T>
+        </button>
       </div>
     );
   }
@@ -283,21 +396,23 @@ export class Search extends Component<any, SearchState> {
     let res = this.state.searchResponse;
     return (
       <div>
-        {res && res.op && res.posts.length == 0 && res.comments.length == 0 && 
-          <span><T i18nKey="no_results">#</T></span>
-        }
+        {res && res.op && res.posts.length == 0 && res.comments.length == 0 && (
+          <span>
+            <T i18nKey="no_results">#</T>
+          </span>
+        )}
       </div>
-    )
+    );
   }
 
-  nextPage(i: Search) { 
+  nextPage(i: Search) {
     i.state.page++;
     i.setState(i.state);
     i.updateUrl();
     i.search();
   }
 
-  prevPage(i: Search) { 
+  prevPage(i: Search) {
     i.state.page--;
     i.setState(i.state);
     i.updateUrl();
@@ -349,7 +464,9 @@ export class Search extends Component<any, SearchState> {
   updateUrl() {
     let typeStr = SearchType[this.state.type_].toLowerCase();
     let sortStr = SortType[this.state.sort].toLowerCase();
-    this.props.history.push(`/search/q/${this.state.q}/type/${typeStr}/sort/${sortStr}/page/${this.state.page}`);
+    this.props.history.push(
+      `/search/q/${this.state.q}/type/${typeStr}/sort/${sortStr}/page/${this.state.page}`
+    );
   }
 
   parseMessage(msg: any) {
@@ -362,10 +479,11 @@ export class Search extends Component<any, SearchState> {
       let res: SearchResponse = msg;
       this.state.searchResponse = res;
       this.state.loading = false;
-      document.title = `${i18n.t('search')} - ${this.state.q} - ${WebSocketService.Instance.site.name}`;
-      window.scrollTo(0,0);
+      document.title = `${i18n.t('search')} - ${this.state.q} - ${
+        WebSocketService.Instance.site.name
+      }`;
+      window.scrollTo(0, 0);
       this.setState(this.state);
     }
   }
 }
-
index 24a5f2d68961709a73fd49587e6307693c5c8954..d421e46f8decabdeaea8f477e0ca18bf7b9320d5 100644 (file)
@@ -1,5 +1,5 @@
 import { Component, linkEvent } from 'inferno';
-import { Subscription } from "rxjs";
+import { Subscription } from 'rxjs';
 import { retryWhen, delay, take } from 'rxjs/operators';
 import { RegisterForm, LoginResponse, UserOperation } from '../interfaces';
 import { WebSocketService, UserService } from '../services';
@@ -27,8 +27,7 @@ export class Setup extends Component<any, State> {
     },
     doneRegisteringUser: false,
     userLoading: false,
-  }
-
+  };
 
   constructor(props: any, context: any) {
     super(props, context);
@@ -36,12 +35,19 @@ export class Setup extends Component<any, State> {
     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")
-    );
+      .pipe(
+        retryWhen(errors =>
+          errors.pipe(
+            delay(3000),
+            take(10)
+          )
+        )
+      )
+      .subscribe(
+        msg => this.parseMessage(msg),
+        err => console.error(err),
+        () => console.log('complete')
+      );
   }
 
   componentWillUnmount() {
@@ -57,54 +63,103 @@ export class Setup extends Component<any, State> {
       <div class="container">
         <div class="row">
           <div class="col-12 offset-lg-3 col-lg-6">
-            <h3><T i18nKey="lemmy_instance_setup">#</T></h3>
-            {!this.state.doneRegisteringUser ? this.registerUser() : <SiteForm />}
+            <h3>
+              <T i18nKey="lemmy_instance_setup">#</T>
+            </h3>
+            {!this.state.doneRegisteringUser ? (
+              this.registerUser()
+            ) : (
+              <SiteForm />
+            )}
           </div>
         </div>
       </div>
-    )
+    );
   }
 
   registerUser() {
     return (
       <form onSubmit={linkEvent(this, this.handleRegisterSubmit)}>
-        <h5><T i18nKey="setup_admin">#</T></h5>
+        <h5>
+          <T i18nKey="setup_admin">#</T>
+        </h5>
         <div class="form-group row">
-          <label class="col-sm-2 col-form-label"><T i18nKey="username">#</T></label>
+          <label class="col-sm-2 col-form-label">
+            <T i18nKey="username">#</T>
+          </label>
           <div class="col-sm-10">
-            <input type="text" class="form-control" value={this.state.userForm.username} onInput={linkEvent(this, this.handleRegisterUsernameChange)} required minLength={3} maxLength={20} pattern="[a-zA-Z0-9_]+" />
+            <input
+              type="text"
+              class="form-control"
+              value={this.state.userForm.username}
+              onInput={linkEvent(this, this.handleRegisterUsernameChange)}
+              required
+              minLength={3}
+              maxLength={20}
+              pattern="[a-zA-Z0-9_]+"
+            />
           </div>
         </div>
         <div class="form-group row">
-          <label class="col-sm-2 col-form-label"><T i18nKey="email">#</T></label>
+          <label class="col-sm-2 col-form-label">
+            <T i18nKey="email">#</T>
+          </label>
           <div class="col-sm-10">
-            <input type="email" class="form-control" placeholder={i18n.t('optional')} value={this.state.userForm.email} onInput={linkEvent(this, this.handleRegisterEmailChange)} minLength={3} />
+            <input
+              type="email"
+              class="form-control"
+              placeholder={i18n.t('optional')}
+              value={this.state.userForm.email}
+              onInput={linkEvent(this, this.handleRegisterEmailChange)}
+              minLength={3}
+            />
           </div>
         </div>
         <div class="form-group row">
-          <label class="col-sm-2 col-form-label"><T i18nKey="password">#</T></label>
+          <label class="col-sm-2 col-form-label">
+            <T i18nKey="password">#</T>
+          </label>
           <div class="col-sm-10">
-            <input type="password" value={this.state.userForm.password} onInput={linkEvent(this, this.handleRegisterPasswordChange)} class="form-control" required />
+            <input
+              type="password"
+              value={this.state.userForm.password}
+              onInput={linkEvent(this, this.handleRegisterPasswordChange)}
+              class="form-control"
+              required
+            />
           </div>
         </div>
         <div class="form-group row">
-          <label class="col-sm-2 col-form-label"><T i18nKey="verify_password">#</T></label>
+          <label class="col-sm-2 col-form-label">
+            <T i18nKey="verify_password">#</T>
+          </label>
           <div class="col-sm-10">
-            <input type="password" value={this.state.userForm.password_verify} onInput={linkEvent(this, this.handleRegisterPasswordVerifyChange)} class="form-control" required />
+            <input
+              type="password"
+              value={this.state.userForm.password_verify}
+              onInput={linkEvent(this, this.handleRegisterPasswordVerifyChange)}
+              class="form-control"
+              required
+            />
           </div>
         </div>
         <div class="form-group row">
           <div class="col-sm-10">
-            <button type="submit" class="btn btn-secondary">{this.state.userLoading ? 
-            <svg class="icon icon-spinner spin"><use xlinkHref="#icon-spinner"></use></svg> : i18n.t('sign_up')}</button>
-
+            <button type="submit" class="btn btn-secondary">
+              {this.state.userLoading ? (
+                <svg class="icon icon-spinner spin">
+                  <use xlinkHref="#icon-spinner"></use>
+                </svg>
+              ) : (
+                i18n.t('sign_up')
+              )}
+            </button>
           </div>
         </div>
       </form>
     );
   }
 
-
   handleRegisterSubmit(i: Setup, event: any) {
     event.preventDefault();
     i.state.userLoading = true;
index df5ad097c217c29176ca54d6d4013dc5c4ccddae..85f81a30c0a31b2de2db9b2fac3c57f89cefe5ee 100644 (file)
@@ -1,6 +1,12 @@
 import { Component, linkEvent } from 'inferno';
 import { Link } from 'inferno-router';
-import { Community, CommunityUser, FollowCommunityForm, CommunityForm as CommunityFormI, UserView } from '../interfaces';
+import {
+  Community,
+  CommunityUser,
+  FollowCommunityForm,
+  CommunityForm as CommunityFormI,
+  UserView,
+} from '../interfaces';
 import { WebSocketService, UserService } from '../services';
 import { mdToHtml, getUnixTime } from '../utils';
 import { CommunityForm } from './community-form';
@@ -21,13 +27,12 @@ interface SidebarState {
 }
 
 export class Sidebar extends Component<SidebarProps, SidebarState> {
-
   private emptyState: SidebarState = {
     showEdit: false,
     showRemoveDialog: false,
     removeReason: null,
-    removeExpires: null
-  }
+    removeExpires: null,
+  };
 
   constructor(props: any, context: any) {
     super(props, context);
@@ -39,15 +44,17 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
   render() {
     return (
       <div>
-        {!this.state.showEdit 
-          ? this.sidebar()
-          : <CommunityForm 
-          community={this.props.community} 
-          onEdit={this.handleEditCommunity} 
-          onCancel={this.handleEditCancel} />
-        }
+        {!this.state.showEdit ? (
+          this.sidebar()
+        ) : (
+          <CommunityForm
+            community={this.props.community}
+            onEdit={this.handleEditCommunity}
+            onCancel={this.handleEditCancel}
+          />
+        )}
       </div>
-    )
+    );
   }
 
   sidebar() {
@@ -58,86 +65,178 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
           <div class="card-body">
             <h5 className="mb-0">
               <span>{community.title}</span>
-              {community.removed &&
-                <small className="ml-2 text-muted font-italic"><T i18nKey="removed">#</T></small>
-              }
-              {community.deleted &&
-                <small className="ml-2 text-muted font-italic"><T i18nKey="deleted">#</T></small>
-              }
+              {community.removed && (
+                <small className="ml-2 text-muted font-italic">
+                  <T i18nKey="removed">#</T>
+                </small>
+              )}
+              {community.deleted && (
+                <small className="ml-2 text-muted font-italic">
+                  <T i18nKey="deleted">#</T>
+                </small>
+              )}
             </h5>
-            <Link className="text-muted" to={`/c/${community.name}`}>/c/{community.name}</Link>
-            <ul class="list-inline mb-1 text-muted small font-weight-bold"> 
-              {this.canMod && 
+            <Link className="text-muted" to={`/c/${community.name}`}>
+              /c/{community.name}
+            </Link>
+            <ul class="list-inline mb-1 text-muted small font-weight-bold">
+              {this.canMod && (
                 <>
                   <li className="list-inline-item">
-                    <span class="pointer" onClick={linkEvent(this, this.handleEditClick)}><T i18nKey="edit">#</T></span>
+                    <span
+                      class="pointer"
+                      onClick={linkEvent(this, this.handleEditClick)}
+                    >
+                      <T i18nKey="edit">#</T>
+                    </span>
                   </li>
-                  {this.amCreator && 
+                  {this.amCreator && (
                     <li className="list-inline-item">
-                      <span class="pointer" onClick={linkEvent(this, this.handleDeleteClick)}>
-                        {!community.deleted ? i18n.t('delete') : i18n.t('restore')}
+                      <span
+                        class="pointer"
+                        onClick={linkEvent(this, this.handleDeleteClick)}
+                      >
+                        {!community.deleted
+                          ? i18n.t('delete')
+                          : i18n.t('restore')}
                       </span>
                     </li>
-                  }
+                  )}
                 </>
-              }
-              {this.canAdmin &&
+              )}
+              {this.canAdmin && (
                 <li className="list-inline-item">
-                  {!this.props.community.removed ? 
-                  <span class="pointer" onClick={linkEvent(this, this.handleModRemoveShow)}><T i18nKey="remove">#</T></span> :
-                  <span class="pointer" onClick={linkEvent(this, this.handleModRemoveSubmit)}><T i18nKey="restore">#</T></span>
-                  }
+                  {!this.props.community.removed ? (
+                    <span
+                      class="pointer"
+                      onClick={linkEvent(this, this.handleModRemoveShow)}
+                    >
+                      <T i18nKey="remove">#</T>
+                    </span>
+                  ) : (
+                    <span
+                      class="pointer"
+                      onClick={linkEvent(this, this.handleModRemoveSubmit)}
+                    >
+                      <T i18nKey="restore">#</T>
+                    </span>
+                  )}
                 </li>
-
-              }
+              )}
             </ul>
-            {this.state.showRemoveDialog && 
+            {this.state.showRemoveDialog && (
               <form onSubmit={linkEvent(this, this.handleModRemoveSubmit)}>
                 <div class="form-group row">
-                  <label class="col-form-label"><T i18nKey="reason">#</T></label>
-                  <input type="text" class="form-control mr-2" placeholder={i18n.t('optional')} value={this.state.removeReason} onInput={linkEvent(this, this.handleModRemoveReasonChange)} />
+                  <label class="col-form-label">
+                    <T i18nKey="reason">#</T>
+                  </label>
+                  <input
+                    type="text"
+                    class="form-control mr-2"
+                    placeholder={i18n.t('optional')}
+                    value={this.state.removeReason}
+                    onInput={linkEvent(this, this.handleModRemoveReasonChange)}
+                  />
                 </div>
                 {/* TODO hold off on expires for now */}
                 {/* <div class="form-group row"> */}
-                  {/*   <label class="col-form-label">Expires</label> */}
-                  {/*   <input type="date" class="form-control mr-2" placeholder={i18n.t('expires')} value={this.state.removeExpires} onInput={linkEvent(this, this.handleModRemoveExpiresChange)} /> */}
-                  {/* </div> */}
-                  <div class="form-group row">
-                    <button type="submit" class="btn btn-secondary"><T i18nKey="remove_community">#</T></button>
-                  </div>
-                </form>
-            }
+                {/*   <label class="col-form-label">Expires</label> */}
+                {/*   <input type="date" class="form-control mr-2" placeholder={i18n.t('expires')} value={this.state.removeExpires} onInput={linkEvent(this, this.handleModRemoveExpiresChange)} /> */}
+                {/* </div> */}
+                <div class="form-group row">
+                  <button type="submit" class="btn btn-secondary">
+                    <T i18nKey="remove_community">#</T>
+                  </button>
+                </div>
+              </form>
+            )}
             <ul class="my-1 list-inline">
-              <li className="list-inline-item"><Link className="badge badge-secondary" to="/communities">{community.category_name}</Link></li>
-              <li className="list-inline-item badge badge-secondary"><T i18nKey="number_of_subscribers" interpolation={{count: community.number_of_subscribers}}>#</T></li>
-              <li className="list-inline-item badge badge-secondary"><T i18nKey="number_of_posts" interpolation={{count: community.number_of_posts}}>#</T></li>
-              <li className="list-inline-item badge badge-secondary"><T i18nKey="number_of_comments" interpolation={{count: community.number_of_comments}}>#</T></li>
-              <li className="list-inline-item"><Link className="badge badge-secondary" to={`/modlog/community/${this.props.community.id}`}><T i18nKey="modlog">#</T></Link></li>
+              <li className="list-inline-item">
+                <Link className="badge badge-secondary" to="/communities">
+                  {community.category_name}
+                </Link>
+              </li>
+              <li className="list-inline-item badge badge-secondary">
+                <T
+                  i18nKey="number_of_subscribers"
+                  interpolation={{ count: community.number_of_subscribers }}
+                >
+                  #
+                </T>
+              </li>
+              <li className="list-inline-item badge badge-secondary">
+                <T
+                  i18nKey="number_of_posts"
+                  interpolation={{ count: community.number_of_posts }}
+                >
+                  #
+                </T>
+              </li>
+              <li className="list-inline-item badge badge-secondary">
+                <T
+                  i18nKey="number_of_comments"
+                  interpolation={{ count: community.number_of_comments }}
+                >
+                  #
+                </T>
+              </li>
+              <li className="list-inline-item">
+                <Link
+                  className="badge badge-secondary"
+                  to={`/modlog/community/${this.props.community.id}`}
+                >
+                  <T i18nKey="modlog">#</T>
+                </Link>
+              </li>
             </ul>
-            <ul class="list-inline small"> 
+            <ul class="list-inline small">
               <li class="list-inline-item">{i18n.t('mods')}: </li>
-              {this.props.moderators.map(mod =>
-                <li class="list-inline-item"><Link class="text-info" to={`/u/${mod.user_name}`}>{mod.user_name}</Link></li>
-              )}
+              {this.props.moderators.map(mod => (
+                <li class="list-inline-item">
+                  <Link class="text-info" to={`/u/${mod.user_name}`}>
+                    {mod.user_name}
+                  </Link>
+                </li>
+              ))}
             </ul>
-            <Link class={`btn btn-sm btn-secondary btn-block mb-3 ${(community.deleted || community.removed) && 'no-click'}`}
-            to={`/create_post?community=${community.name}`}><T i18nKey="create_a_post">#</T></Link>
-          <div>
-            {community.subscribed 
-              ? <button class="btn btn-sm btn-secondary btn-block" onClick={linkEvent(community.id, this.handleUnsubscribe)}><T i18nKey="unsubscribe">#</T></button>
-              : <button class="btn btn-sm btn-secondary btn-block" onClick={linkEvent(community.id, this.handleSubscribe)}><T i18nKey="subscribe">#</T></button>
-            }
+            <Link
+              class={`btn btn-sm btn-secondary btn-block mb-3 ${(community.deleted ||
+                community.removed) &&
+                'no-click'}`}
+              to={`/create_post?community=${community.name}`}
+            >
+              <T i18nKey="create_a_post">#</T>
+            </Link>
+            <div>
+              {community.subscribed ? (
+                <button
+                  class="btn btn-sm btn-secondary btn-block"
+                  onClick={linkEvent(community.id, this.handleUnsubscribe)}
+                >
+                  <T i18nKey="unsubscribe">#</T>
+                </button>
+              ) : (
+                <button
+                  class="btn btn-sm btn-secondary btn-block"
+                  onClick={linkEvent(community.id, this.handleSubscribe)}
+                >
+                  <T i18nKey="subscribe">#</T>
+                </button>
+              )}
+            </div>
           </div>
         </div>
-        </div>
-        {community.description && 
+        {community.description && (
           <div class="card border-secondary">
             <div class="card-body">
-              <div className="md-div" dangerouslySetInnerHTML={mdToHtml(community.description)} />
+              <div
+                className="md-div"
+                dangerouslySetInnerHTML={mdToHtml(community.description)}
+              />
             </div>
           </div>
-        }
-        </div>
+        )}
+      </div>
     );
   }
 
@@ -173,7 +272,7 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
   handleUnsubscribe(communityId: number) {
     let form: FollowCommunityForm = {
       community_id: communityId,
-      follow: false
+      follow: false,
     };
     WebSocketService.Instance.followCommunity(form);
   }
@@ -181,7 +280,7 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
   handleSubscribe(communityId: number) {
     let form: FollowCommunityForm = {
       community_id: communityId,
-      follow: true
+      follow: true,
     };
     WebSocketService.Instance.followCommunity(form);
   }
@@ -191,11 +290,19 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
   }
 
   get canMod(): boolean {
-    return UserService.Instance.user && this.props.moderators.map(m => m.user_id).includes(UserService.Instance.user.id);
+    return (
+      UserService.Instance.user &&
+      this.props.moderators
+        .map(m => m.user_id)
+        .includes(UserService.Instance.user.id)
+    );
   }
 
   get canAdmin(): boolean {
-    return UserService.Instance.user && this.props.admins.map(a => a.id).includes(UserService.Instance.user.id);
+    return (
+      UserService.Instance.user &&
+      this.props.admins.map(a => a.id).includes(UserService.Instance.user.id)
+    );
   }
 
   handleModRemoveShow(i: Sidebar) {
index 011642158e6cb2bd7ead54f27fb868f881c14109..7f8c229dadadc03c701aa2d989b22390c8ae6a0d 100644 (file)
@@ -17,12 +17,12 @@ interface SiteFormState {
 }
 
 export class SiteForm extends Component<SiteFormProps, SiteFormState> {
-  private emptyState: SiteFormState ={
+  private emptyState: SiteFormState = {
     siteForm: {
-      name: null
+      name: null,
     },
-    loading: false
-  }
+    loading: false,
+  };
 
   constructor(props: any, context: any) {
     super(props, context);
@@ -31,7 +31,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
       this.state.siteForm = {
         name: this.props.site.name,
         description: this.props.site.description,
-      }
+      };
     }
   }
 
@@ -42,26 +42,63 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
   render() {
     return (
       <form onSubmit={linkEvent(this, this.handleCreateSiteSubmit)}>
-        <h5>{`${this.props.site ? capitalizeFirstLetter(i18n.t('edit')) : capitalizeFirstLetter(i18n.t('name'))} ${i18n.t('your_site')}`}</h5>
+        <h5>{`${
+          this.props.site
+            ? capitalizeFirstLetter(i18n.t('edit'))
+            : capitalizeFirstLetter(i18n.t('name'))
+        } ${i18n.t('your_site')}`}</h5>
         <div class="form-group row">
-          <label class="col-12 col-form-label"><T i18nKey="name">#</T></label>
+          <label class="col-12 col-form-label">
+            <T i18nKey="name">#</T>
+          </label>
           <div class="col-12">
-            <input type="text" class="form-control" value={this.state.siteForm.name} onInput={linkEvent(this, this.handleSiteNameChange)} required minLength={3} maxLength={20} />
+            <input
+              type="text"
+              class="form-control"
+              value={this.state.siteForm.name}
+              onInput={linkEvent(this, this.handleSiteNameChange)}
+              required
+              minLength={3}
+              maxLength={20}
+            />
           </div>
         </div>
         <div class="form-group row">
-          <label class="col-12 col-form-label"><T i18nKey="sidebar">#</T></label>
+          <label class="col-12 col-form-label">
+            <T i18nKey="sidebar">#</T>
+          </label>
           <div class="col-12">
-            <textarea value={this.state.siteForm.description} onInput={linkEvent(this, this.handleSiteDescriptionChange)} class="form-control" rows={3} maxLength={10000} />
+            <textarea
+              value={this.state.siteForm.description}
+              onInput={linkEvent(this, this.handleSiteDescriptionChange)}
+              class="form-control"
+              rows={3}
+              maxLength={10000}
+            />
           </div>
         </div>
         <div class="form-group row">
           <div class="col-12">
             <button type="submit" class="btn btn-secondary mr-2">
-              {this.state.loading ? 
-              <svg class="icon icon-spinner spin"><use xlinkHref="#icon-spinner"></use></svg> : 
-              this.props.site ? capitalizeFirstLetter(i18n.t('save')) : capitalizeFirstLetter(i18n.t('create'))}</button>
-              {this.props.site && <button type="button" class="btn btn-secondary" onClick={linkEvent(this, this.handleCancel)}><T i18nKey="cancel">#</T></button>}
+              {this.state.loading ? (
+                <svg class="icon icon-spinner spin">
+                  <use xlinkHref="#icon-spinner"></use>
+                </svg>
+              ) : this.props.site ? (
+                capitalizeFirstLetter(i18n.t('save'))
+              ) : (
+                capitalizeFirstLetter(i18n.t('create'))
+              )}
+            </button>
+            {this.props.site && (
+              <button
+                type="button"
+                class="btn btn-secondary"
+                onClick={linkEvent(this, this.handleCancel)}
+              >
+                <T i18nKey="cancel">#</T>
+              </button>
+            )}
           </div>
         </div>
       </form>
index 5d0b1b17236f47a170493b7fb2252983977f7b78..077aa7d3389acf544008607a24b69726e20faed1 100644 (file)
@@ -3,23 +3,21 @@ import { WebSocketService } from '../services';
 import { i18n } from '../i18next';
 import { T } from 'inferno-i18next';
 
-let general = [
-  "riccardo","NotTooHighToHack",
-];
+let general = ['riccardo', 'NotTooHighToHack'];
 // let highlighted = [];
 // let silver = [];
 // let gold = [];
 // let latinum = [];
 
 export class Sponsors extends Component<any, any> {
-
   constructor(props: any, context: any) {
     super(props, context);
-
   }
 
   componentDidMount() {
-    document.title = `${i18n.t('sponsors')} - ${WebSocketService.Instance.site.name}`;
+    document.title = `${i18n.t('sponsors')} - ${
+      WebSocketService.Instance.site.name
+    }`;
   }
 
   render() {
@@ -31,62 +29,85 @@ export class Sponsors extends Component<any, any> {
         <hr />
         {this.bitcoin()}
       </div>
-    )
+    );
   }
 
   topMessage() {
     return (
       <div>
-        <h5><T i18nKey="sponsors_of_lemmy">#</T></h5>
+        <h5>
+          <T i18nKey="sponsors_of_lemmy">#</T>
+        </h5>
         <p>
-          <T i18nKey="sponsor_message">#<a href="https://github.com/dessalines/lemmy">#</a></T>
+          <T i18nKey="sponsor_message">
+            #<a href="https://github.com/dessalines/lemmy">#</a>
+          </T>
         </p>
-        <a class="btn btn-secondary" href="https://www.patreon.com/dessalines"><T i18nKey="support_on_patreon">#</T></a>
+        <a class="btn btn-secondary" href="https://www.patreon.com/dessalines">
+          <T i18nKey="support_on_patreon">#</T>
+        </a>
       </div>
-    )
+    );
   }
   sponsors() {
     return (
       <div class="container">
-        <h5><T i18nKey="sponsors">#</T></h5>
-        <p><T i18nKey="general_sponsors">#</T></p>
+        <h5>
+          <T i18nKey="sponsors">#</T>
+        </h5>
+        <p>
+          <T i18nKey="general_sponsors">#</T>
+        </p>
         <div class="row card-columns">
-          {general.map(s => 
+          {general.map(s => (
             <div class="card col-12 col-md-2">
               <div>{s}</div>
             </div>
-          )}
+          ))}
         </div>
       </div>
-    )
+    );
   }
 
   bitcoin() {
     return (
       <div>
-        <h5><T i18nKey="crypto">#</T></h5>
-      <div class="table-responsive">
-        <table class="table table-hover text-center">
-          <tbody>
-          <tr>
-            <td><T i18nKey="bitcoin">#</T></td>
-            <td><code>1Hefs7miXS5ff5Ck5xvmjKjXf5242KzRtK</code></td>
-          </tr>
-          <tr>
-            <td><T i18nKey="ethereum">#</T></td>
-            <td><code>0x400c96c96acbC6E7B3B43B1dc1BB446540a88A01</code></td>
-          </tr>
-          <tr>
-            <td><T i18nKey="monero">#</T></td>
-            <td>
-              <code>41taVyY6e1xApqKyMVDRVxJ76sPkfZhALLTjRvVKpaAh2pBd4wv9RgYj1tSPrx8wc6iE1uWUfjtQdTmTy2FGMeChGVKPQuV</code>
-            </td>
-          </tr>
-          </tbody>
-        </table>
+        <h5>
+          <T i18nKey="crypto">#</T>
+        </h5>
+        <div class="table-responsive">
+          <table class="table table-hover text-center">
+            <tbody>
+              <tr>
+                <td>
+                  <T i18nKey="bitcoin">#</T>
+                </td>
+                <td>
+                  <code>1Hefs7miXS5ff5Ck5xvmjKjXf5242KzRtK</code>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  <T i18nKey="ethereum">#</T>
+                </td>
+                <td>
+                  <code>0x400c96c96acbC6E7B3B43B1dc1BB446540a88A01</code>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  <T i18nKey="monero">#</T>
+                </td>
+                <td>
+                  <code>
+                    41taVyY6e1xApqKyMVDRVxJ76sPkfZhALLTjRvVKpaAh2pBd4wv9RgYj1tSPrx8wc6iE1uWUfjtQdTmTy2FGMeChGVKPQuV
+                  </code>
+                </td>
+              </tr>
+            </tbody>
+          </table>
+        </div>
       </div>
-    </div>
-    )
+    );
   }
 }
-
index a299ff253122ed597e526f31cf1431d27262a722..5506b58f5999c40f98c1fe2b383952c796316321 100644 (file)
@@ -1,14 +1,19 @@
 import { Component } from 'inferno';
 
 export class Symbols extends Component<any, any> {
-
   constructor(props: any, context: any) {
     super(props, context);
   }
 
   render() {
     return (
-      <svg aria-hidden="true" style="position: absolute; width: 0; height: 0; overflow: hidden;" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlnsXlink="http://www.w3.org/1999/xlink">
+      <svg
+        aria-hidden="true"
+        style="position: absolute; width: 0; height: 0; overflow: hidden;"
+        version="1.1"
+        xmlns="http://www.w3.org/2000/svg"
+        xmlnsXlink="http://www.w3.org/1999/xlink"
+      >
         <defs>
           <symbol id="icon-arrow-down" viewBox="0 0 26 28">
             <title>arrow-down</title>
@@ -17,63 +22,69 @@ export class Symbols extends Component<any, any> {
           <symbol id="icon-arrow-up" viewBox="0 0 26 28">
             <title>arrow-up</title>
             <path d="M25.172 15.172c0 0.531-0.219 1.031-0.578 1.406l-1.172 1.172c-0.375 0.375-0.891 0.594-1.422 0.594s-1.047-0.219-1.406-0.594l-4.594-4.578v11c0 1.125-0.938 1.828-2 1.828h-2c-1.062 0-2-0.703-2-1.828v-11l-4.594 4.578c-0.359 0.375-0.875 0.594-1.406 0.594s-1.047-0.219-1.406-0.594l-1.172-1.172c-0.375-0.375-0.594-0.875-0.594-1.406s0.219-1.047 0.594-1.422l10.172-10.172c0.359-0.375 0.875-0.578 1.406-0.578s1.047 0.203 1.422 0.578l10.172 10.172c0.359 0.375 0.578 0.891 0.578 1.422z"></path>
-          </symbol>         
+          </symbol>
           <symbol id="icon-mail" viewBox="0 0 32 32">
             <title>mail</title>
             <path d="M28 5h-24c-2.209 0-4 1.792-4 4v13c0 2.209 1.791 4 4 4h24c2.209 0 4-1.791 4-4v-13c0-2.208-1.791-4-4-4zM2 10.25l6.999 5.25-6.999 5.25v-10.5zM30 22c0 1.104-0.898 2-2 2h-24c-1.103 0-2-0.896-2-2l7.832-5.875 4.368 3.277c0.533 0.398 1.166 0.6 1.8 0.6 0.633 0 1.266-0.201 1.799-0.6l4.369-3.277 7.832 5.875zM30 20.75l-7-5.25 7-5.25v10.5zM17.199 18.602c-0.349 0.262-0.763 0.4-1.199 0.4s-0.851-0.139-1.2-0.4l-12.8-9.602c0-1.103 0.897-2 2-2h24c1.102 0 2 0.897 2 2l-12.801 9.602z"></path>
-          </symbol>         
-          <symbol id="icon-mouse" version="1.1" x="0px" y="0px"
-            viewBox="0 0 1024 1024">
-  <g
-     id="layer1"
-     transform="translate(0,-26.066658)"
-     style="display:inline">
-    <path
-       style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:28;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
-       d="m 167.03908,270.78735 c -0.94784,-0.002 -1.8939,0.004 -2.83789,0.0215 -4.31538,0.0778 -8.58934,0.3593 -12.8125,0.8457 -33.78522,3.89116 -64.215716,21.86394 -82.871086,53.27344 -18.27982,30.77718 -22.77749,64.66635 -13.46094,96.06837 9.31655,31.40203 31.88488,59.93174 65.296886,82.5332 0.20163,0.13618 0.40678,0.26709 0.61523,0.39258 28.65434,17.27768 57.18167,28.93179 87.74218,34.95508 -0.74566,12.61339 -0.72532,25.5717 0.082,38.84375 2.43989,40.10943 16.60718,77.03742 38.0957,109.67187 l -77.00781,31.4375 c -8.30605,3.25932 -12.34178,12.68234 -8.96967,20.94324 3.37211,8.2609 12.84919,12.16798 21.06342,8.68371 l 84.69727,-34.57617 c 15.70675,18.72702 33.75346,35.68305 53.12109,50.57032 0.74013,0.56891 1.4904,1.12236 2.23437,1.68554 l -49.61132,65.69141 c -5.45446,7.0474 -4.10058,17.19288 3.01098,22.5634 7.11156,5.37052 17.24028,3.89649 22.52612,-3.27824 l 50.38672,-66.71876 c 27.68572,17.53469 57.07524,31.20388 86.07227,40.25196 14.88153,27.28008 43.96965,44.64648 77.58789,44.64648 33.93762,0 63.04252,-18.68693 77.80082,-45.4375 28.7072,-9.21295 57.7527,-22.93196 85.1484,-40.40234 l 51.0977,67.66016 c 5.2858,7.17473 15.4145,8.64876 22.5261,3.27824 7.1115,-5.37052 8.4654,-15.516 3.011,-22.5634 l -50.3614,-66.68555 c 0.334,-0.25394 0.6727,-0.50077 1.0059,-0.75586 19.1376,-14.64919 37.0259,-31.28581 52.7031,-49.63476 l 82.5625,33.70507 c 8.2143,3.48427 17.6913,-0.42281 21.0634,-8.68371 3.3722,-8.2609 -0.6636,-17.68392 -8.9696,-20.94324 l -74.5391,-30.42773 c 22.1722,-32.82971 37.0383,-70.03397 40.1426,-110.46094 1.0253,-13.35251 1.2292,-26.42535 0.6387,-39.17578 30.3557,-6.05408 58.7164,-17.66833 87.2011,-34.84375 0.2085,-0.12549 0.4136,-0.2564 0.6153,-0.39258 33.412,-22.60147 55.9803,-51.13117 65.2968,-82.5332 9.3166,-31.40202 4.8189,-65.29118 -13.4609,-96.06837 -18.6553,-31.40951 -49.0859,-49.38228 -82.8711,-53.27344 -4.2231,-0.4864 -8.4971,-0.76791 -12.8125,-0.8457 -30.2077,-0.54448 -62.4407,8.82427 -93.4316,26.71484 -22.7976,13.16063 -43.3521,33.31423 -59.4375,55.30469 -44.9968,-25.75094 -103.5444,-40.25065 -175.4785,-41.43945 -6.4522,-0.10663 -13.0125,-0.10696 -19.67974,0.002 -80.18875,1.30929 -144.38284,16.5086 -192.87109,43.9922 -0.11914,-0.19111 -0.24287,-0.37932 -0.37109,-0.56446 -16.29,-22.764 -37.41085,-43.73706 -60.89649,-57.29493 -30.02247,-17.33149 -61.21051,-26.66489 -90.59375,-26.73633 z"
-       id="path817-3"
-        />
-    <path
-       id="path1087"
-       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:28;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       d="m 716.85595,362.96478 c 15.29075,-21.36763 35.36198,-41.10921 56.50979,-53.31749 66.66377,-38.48393 137.02617,-33.22172 170.08018,22.43043 33.09493,55.72093 14.98656,117.48866 -47.64399,159.85496 -31.95554,19.26819 -62.93318,30.92309 -97.22892,35.54473 M 307.14407,362.96478 C 291.85332,341.59715 271.78209,321.85557 250.63429,309.64729 183.97051,271.16336 113.60811,276.42557 80.554051,332.07772 47.459131,387.79865 65.56752,449.56638 128.19809,491.93268 c 31.95554,19.26819 62.93319,30.92309 97.22893,35.54473"
-        />
-    <path
-       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:28;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       d="M 801.23205,576.8699 C 812.73478,427.06971 720.58431,321.98291 511.99999,325.38859 303.41568,328.79426 213.71393,428.0311 222.76794,576.8699 c 8.64289,142.08048 176.80223,246.40388 288.12038,246.40388 111.31815,0 279.45076,-104.5447 290.34373,-246.40388 z"
-       id="path969"
-        />
-    <path
-       id="path1084"
-       style="display:inline;opacity:1;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       d="m 610.4991,644.28932 c 0,23.11198 18.70595,41.84795 41.78091,41.84795 23.07495,0 41.7809,-18.73597 41.7809,-41.84795 0,-23.112 -18.70594,-41.84796 -41.7809,-41.84796 -23.07496,0 -41.78091,18.73596 -41.78091,41.84796 z m -280.56002,0 c 0,23.32492 18.87829,42.23352 42.16586,42.23352 23.28755,0 42.16585,-18.9086 42.16585,-42.23352 0,-23.32494 -18.87829,-42.23353 -42.16585,-42.23353 -23.28757,0 -42.16586,18.90859 -42.16586,42.23353 z"
-        />
-    <path
-       id="path1008"
-       style="display:inline;opacity:1;fill:none;stroke:#000000;stroke-width:32;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       d="m 339.72919,769.2467 -54.54422,72.22481 m 399.08582,-72.22481 54.54423,72.22481 M 263.68341,697.82002 175.92752,733.64353 m 579.85765,-35.82351 87.7559,35.82351"
-        />
-    <path
-       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:28;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       d="m 512.00082,713.08977 c -45.86417,0 -75.13006,31.84485 -74.14159,71.10084 1.07048,42.51275 32.46865,71.10323 74.14159,71.10323 41.67296,0 74.05118,-32.99608 74.14161,-71.10323 0.0932,-39.26839 -28.27742,-71.10084 -74.14161,-71.10084 z"
-       id="path1115"
-        />
-  </g>
-            </symbol>
-            <symbol id="icon-search" viewBox="0 0 32 32">
-              <title>search</title>
-              <path d="M31.008 27.231l-7.58-6.447c-0.784-0.705-1.622-1.029-2.299-0.998 1.789-2.096 2.87-4.815 2.87-7.787 0-6.627-5.373-12-12-12s-12 5.373-12 12 5.373 12 12 12c2.972 0 5.691-1.081 7.787-2.87-0.031 0.677 0.293 1.515 0.998 2.299l6.447 7.58c1.104 1.226 2.907 1.33 4.007 0.23s0.997-2.903-0.23-4.007zM12 20c-4.418 0-8-3.582-8-8s3.582-8 8-8 8 3.582 8 8-3.582 8-8 8z"></path>
-            </symbol>
-            <symbol id="icon-github" viewBox="0 0 32 32">
-              <title>github</title>
-              <path d="M16 0.395c-8.836 0-16 7.163-16 16 0 7.069 4.585 13.067 10.942 15.182 0.8 0.148 1.094-0.347 1.094-0.77 0-0.381-0.015-1.642-0.022-2.979-4.452 0.968-5.391-1.888-5.391-1.888-0.728-1.849-1.776-2.341-1.776-2.341-1.452-0.993 0.11-0.973 0.11-0.973 1.606 0.113 2.452 1.649 2.452 1.649 1.427 2.446 3.743 1.739 4.656 1.33 0.143-1.034 0.558-1.74 1.016-2.14-3.554-0.404-7.29-1.777-7.29-7.907 0-1.747 0.625-3.174 1.649-4.295-0.166-0.403-0.714-2.030 0.155-4.234 0 0 1.344-0.43 4.401 1.64 1.276-0.355 2.645-0.532 4.005-0.539 1.359 0.006 2.729 0.184 4.008 0.539 3.054-2.070 4.395-1.64 4.395-1.64 0.871 2.204 0.323 3.831 0.157 4.234 1.026 1.12 1.647 2.548 1.647 4.295 0 6.145-3.743 7.498-7.306 7.895 0.574 0.497 1.085 1.47 1.085 2.963 0 2.141-0.019 3.864-0.019 4.391 0 0.426 0.288 0.925 1.099 0.768 6.354-2.118 10.933-8.113 10.933-15.18 0-8.837-7.164-16-16-16z"></path>
-            </symbol>
-            <symbol id="icon-spinner" viewBox="0 0 32 32">
-              <title>spinner</title>
-              <path d="M16 32c-4.274 0-8.292-1.664-11.314-4.686s-4.686-7.040-4.686-11.314c0-3.026 0.849-5.973 2.456-8.522 1.563-2.478 3.771-4.48 6.386-5.791l1.344 2.682c-2.126 1.065-3.922 2.693-5.192 4.708-1.305 2.069-1.994 4.462-1.994 6.922 0 7.168 5.832 13 13 13s13-5.832 13-13c0-2.459-0.69-4.853-1.994-6.922-1.271-2.015-3.066-3.643-5.192-4.708l1.344-2.682c2.615 1.31 4.824 3.313 6.386 5.791 1.607 2.549 2.456 5.495 2.456 8.522 0 4.274-1.664 8.292-4.686 11.314s-7.040 4.686-11.314 4.686z"></path>
-            </symbol>
-          </defs>
-        </svg>
+          </symbol>
+          <symbol
+            id="icon-mouse"
+            version="1.1"
+            x="0px"
+            y="0px"
+            viewBox="0 0 1024 1024"
+          >
+            <g
+              id="layer1"
+              transform="translate(0,-26.066658)"
+              style="display:inline"
+            >
+              <path
+                style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:28;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+                d="m 167.03908,270.78735 c -0.94784,-0.002 -1.8939,0.004 -2.83789,0.0215 -4.31538,0.0778 -8.58934,0.3593 -12.8125,0.8457 -33.78522,3.89116 -64.215716,21.86394 -82.871086,53.27344 -18.27982,30.77718 -22.77749,64.66635 -13.46094,96.06837 9.31655,31.40203 31.88488,59.93174 65.296886,82.5332 0.20163,0.13618 0.40678,0.26709 0.61523,0.39258 28.65434,17.27768 57.18167,28.93179 87.74218,34.95508 -0.74566,12.61339 -0.72532,25.5717 0.082,38.84375 2.43989,40.10943 16.60718,77.03742 38.0957,109.67187 l -77.00781,31.4375 c -8.30605,3.25932 -12.34178,12.68234 -8.96967,20.94324 3.37211,8.2609 12.84919,12.16798 21.06342,8.68371 l 84.69727,-34.57617 c 15.70675,18.72702 33.75346,35.68305 53.12109,50.57032 0.74013,0.56891 1.4904,1.12236 2.23437,1.68554 l -49.61132,65.69141 c -5.45446,7.0474 -4.10058,17.19288 3.01098,22.5634 7.11156,5.37052 17.24028,3.89649 22.52612,-3.27824 l 50.38672,-66.71876 c 27.68572,17.53469 57.07524,31.20388 86.07227,40.25196 14.88153,27.28008 43.96965,44.64648 77.58789,44.64648 33.93762,0 63.04252,-18.68693 77.80082,-45.4375 28.7072,-9.21295 57.7527,-22.93196 85.1484,-40.40234 l 51.0977,67.66016 c 5.2858,7.17473 15.4145,8.64876 22.5261,3.27824 7.1115,-5.37052 8.4654,-15.516 3.011,-22.5634 l -50.3614,-66.68555 c 0.334,-0.25394 0.6727,-0.50077 1.0059,-0.75586 19.1376,-14.64919 37.0259,-31.28581 52.7031,-49.63476 l 82.5625,33.70507 c 8.2143,3.48427 17.6913,-0.42281 21.0634,-8.68371 3.3722,-8.2609 -0.6636,-17.68392 -8.9696,-20.94324 l -74.5391,-30.42773 c 22.1722,-32.82971 37.0383,-70.03397 40.1426,-110.46094 1.0253,-13.35251 1.2292,-26.42535 0.6387,-39.17578 30.3557,-6.05408 58.7164,-17.66833 87.2011,-34.84375 0.2085,-0.12549 0.4136,-0.2564 0.6153,-0.39258 33.412,-22.60147 55.9803,-51.13117 65.2968,-82.5332 9.3166,-31.40202 4.8189,-65.29118 -13.4609,-96.06837 -18.6553,-31.40951 -49.0859,-49.38228 -82.8711,-53.27344 -4.2231,-0.4864 -8.4971,-0.76791 -12.8125,-0.8457 -30.2077,-0.54448 -62.4407,8.82427 -93.4316,26.71484 -22.7976,13.16063 -43.3521,33.31423 -59.4375,55.30469 -44.9968,-25.75094 -103.5444,-40.25065 -175.4785,-41.43945 -6.4522,-0.10663 -13.0125,-0.10696 -19.67974,0.002 -80.18875,1.30929 -144.38284,16.5086 -192.87109,43.9922 -0.11914,-0.19111 -0.24287,-0.37932 -0.37109,-0.56446 -16.29,-22.764 -37.41085,-43.73706 -60.89649,-57.29493 -30.02247,-17.33149 -61.21051,-26.66489 -90.59375,-26.73633 z"
+                id="path817-3"
+              />
+              <path
+                id="path1087"
+                style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:28;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+                d="m 716.85595,362.96478 c 15.29075,-21.36763 35.36198,-41.10921 56.50979,-53.31749 66.66377,-38.48393 137.02617,-33.22172 170.08018,22.43043 33.09493,55.72093 14.98656,117.48866 -47.64399,159.85496 -31.95554,19.26819 -62.93318,30.92309 -97.22892,35.54473 M 307.14407,362.96478 C 291.85332,341.59715 271.78209,321.85557 250.63429,309.64729 183.97051,271.16336 113.60811,276.42557 80.554051,332.07772 47.459131,387.79865 65.56752,449.56638 128.19809,491.93268 c 31.95554,19.26819 62.93319,30.92309 97.22893,35.54473"
+              />
+              <path
+                style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:28;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+                d="M 801.23205,576.8699 C 812.73478,427.06971 720.58431,321.98291 511.99999,325.38859 303.41568,328.79426 213.71393,428.0311 222.76794,576.8699 c 8.64289,142.08048 176.80223,246.40388 288.12038,246.40388 111.31815,0 279.45076,-104.5447 290.34373,-246.40388 z"
+                id="path969"
+              />
+              <path
+                id="path1084"
+                style="display:inline;opacity:1;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+                d="m 610.4991,644.28932 c 0,23.11198 18.70595,41.84795 41.78091,41.84795 23.07495,0 41.7809,-18.73597 41.7809,-41.84795 0,-23.112 -18.70594,-41.84796 -41.7809,-41.84796 -23.07496,0 -41.78091,18.73596 -41.78091,41.84796 z m -280.56002,0 c 0,23.32492 18.87829,42.23352 42.16586,42.23352 23.28755,0 42.16585,-18.9086 42.16585,-42.23352 0,-23.32494 -18.87829,-42.23353 -42.16585,-42.23353 -23.28757,0 -42.16586,18.90859 -42.16586,42.23353 z"
+              />
+              <path
+                id="path1008"
+                style="display:inline;opacity:1;fill:none;stroke:#000000;stroke-width:32;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+                d="m 339.72919,769.2467 -54.54422,72.22481 m 399.08582,-72.22481 54.54423,72.22481 M 263.68341,697.82002 175.92752,733.64353 m 579.85765,-35.82351 87.7559,35.82351"
+              />
+              <path
+                style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:28;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+                d="m 512.00082,713.08977 c -45.86417,0 -75.13006,31.84485 -74.14159,71.10084 1.07048,42.51275 32.46865,71.10323 74.14159,71.10323 41.67296,0 74.05118,-32.99608 74.14161,-71.10323 0.0932,-39.26839 -28.27742,-71.10084 -74.14161,-71.10084 z"
+                id="path1115"
+              />
+            </g>
+          </symbol>
+          <symbol id="icon-search" viewBox="0 0 32 32">
+            <title>search</title>
+            <path d="M31.008 27.231l-7.58-6.447c-0.784-0.705-1.622-1.029-2.299-0.998 1.789-2.096 2.87-4.815 2.87-7.787 0-6.627-5.373-12-12-12s-12 5.373-12 12 5.373 12 12 12c2.972 0 5.691-1.081 7.787-2.87-0.031 0.677 0.293 1.515 0.998 2.299l6.447 7.58c1.104 1.226 2.907 1.33 4.007 0.23s0.997-2.903-0.23-4.007zM12 20c-4.418 0-8-3.582-8-8s3.582-8 8-8 8 3.582 8 8-3.582 8-8 8z"></path>
+          </symbol>
+          <symbol id="icon-github" viewBox="0 0 32 32">
+            <title>github</title>
+            <path d="M16 0.395c-8.836 0-16 7.163-16 16 0 7.069 4.585 13.067 10.942 15.182 0.8 0.148 1.094-0.347 1.094-0.77 0-0.381-0.015-1.642-0.022-2.979-4.452 0.968-5.391-1.888-5.391-1.888-0.728-1.849-1.776-2.341-1.776-2.341-1.452-0.993 0.11-0.973 0.11-0.973 1.606 0.113 2.452 1.649 2.452 1.649 1.427 2.446 3.743 1.739 4.656 1.33 0.143-1.034 0.558-1.74 1.016-2.14-3.554-0.404-7.29-1.777-7.29-7.907 0-1.747 0.625-3.174 1.649-4.295-0.166-0.403-0.714-2.030 0.155-4.234 0 0 1.344-0.43 4.401 1.64 1.276-0.355 2.645-0.532 4.005-0.539 1.359 0.006 2.729 0.184 4.008 0.539 3.054-2.070 4.395-1.64 4.395-1.64 0.871 2.204 0.323 3.831 0.157 4.234 1.026 1.12 1.647 2.548 1.647 4.295 0 6.145-3.743 7.498-7.306 7.895 0.574 0.497 1.085 1.47 1.085 2.963 0 2.141-0.019 3.864-0.019 4.391 0 0.426 0.288 0.925 1.099 0.768 6.354-2.118 10.933-8.113 10.933-15.18 0-8.837-7.164-16-16-16z"></path>
+          </symbol>
+          <symbol id="icon-spinner" viewBox="0 0 32 32">
+            <title>spinner</title>
+            <path d="M16 32c-4.274 0-8.292-1.664-11.314-4.686s-4.686-7.040-4.686-11.314c0-3.026 0.849-5.973 2.456-8.522 1.563-2.478 3.771-4.48 6.386-5.791l1.344 2.682c-2.126 1.065-3.922 2.693-5.192 4.708-1.305 2.069-1.994 4.462-1.994 6.922 0 7.168 5.832 13 13 13s13-5.832 13-13c0-2.459-0.69-4.853-1.994-6.922-1.271-2.015-3.066-3.643-5.192-4.708l1.344-2.682c2.615 1.31 4.824 3.313 6.386 5.791 1.607 2.549 2.456 5.495 2.456 8.522 0 4.274-1.664 8.292-4.686 11.314s-7.040 4.686-11.314 4.686z"></path>
+          </symbol>
+        </defs>
+      </svg>
     );
   }
 }
index 88476bc82afa092a3a00d85cee9b4103dc31dd55..393d91d5a88871aab1ab8c5133845c82005b94d5 100644 (file)
@@ -1,10 +1,32 @@
 import { Component, linkEvent } from 'inferno';
 import { Link } from 'inferno-router';
-import { Subscription } from "rxjs";
+import { Subscription } from 'rxjs';
 import { retryWhen, delay, take } from 'rxjs/operators';
-import { UserOperation, Post, Comment, CommunityUser, GetUserDetailsForm, SortType, UserDetailsResponse, UserView, CommentResponse, UserSettingsForm, LoginResponse, BanUserResponse, AddAdminResponse, DeleteAccountForm } from '../interfaces';
+import {
+  UserOperation,
+  Post,
+  Comment,
+  CommunityUser,
+  GetUserDetailsForm,
+  SortType,
+  UserDetailsResponse,
+  UserView,
+  CommentResponse,
+  UserSettingsForm,
+  LoginResponse,
+  BanUserResponse,
+  AddAdminResponse,
+  DeleteAccountForm,
+} from '../interfaces';
 import { WebSocketService, UserService } from '../services';
-import { msgOp, fetchLimit, routeSortTypeToEnum, capitalizeFirstLetter, themes, setTheme } from '../utils';
+import {
+  msgOp,
+  fetchLimit,
+  routeSortTypeToEnum,
+  capitalizeFirstLetter,
+  themes,
+  setTheme,
+} from '../utils';
 import { PostListing } from './post-listing';
 import { CommentNodes } from './comment-nodes';
 import { MomentTime } from './moment-time';
@@ -12,7 +34,10 @@ import { i18n } from '../i18next';
 import { T } from 'inferno-i18next';
 
 enum View {
-  Overview, Comments, Posts, Saved
+  Overview,
+  Comments,
+  Posts,
+  Saved,
 }
 
 interface UserState {
@@ -37,7 +62,6 @@ interface UserState {
 }
 
 export class User extends Component<any, UserState> {
-
   private subscription: Subscription;
   private emptyState: UserState = {
     user: {
@@ -72,8 +96,8 @@ export class User extends Component<any, UserState> {
     deleteAccountShowConfirm: false,
     deleteAccountForm: {
       password: null,
-    }
-  }
+    },
+  };
 
   constructor(props: any, context: any) {
     super(props, context);
@@ -84,34 +108,44 @@ export class User extends Component<any, UserState> {
     this.state.username = this.props.match.params.username;
 
     this.subscription = WebSocketService.Instance.subject
-    .pipe(retryWhen(errors => errors.pipe(delay(3000), take(10))))
-    .subscribe(
-      (msg) => this.parseMessage(msg),
-        (err) => console.error(err),
+      .pipe(
+        retryWhen(errors =>
+          errors.pipe(
+            delay(3000),
+            take(10)
+          )
+        )
+      )
+      .subscribe(
+        msg => this.parseMessage(msg),
+        err => console.error(err),
         () => console.log('complete')
-    );
+      );
 
     this.refetch();
   }
 
   get isCurrentUser() {
-    return UserService.Instance.user && UserService.Instance.user.id == this.state.user.id;
+    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)] : 
-      View.Overview;
+    return props.match.params.view
+      ? View[capitalizeFirstLetter(props.match.params.view)]
+      View.Overview;
   }
 
   getSortTypeFromProps(props: any): SortType {
-    return (props.match.params.sort) ? 
-      routeSortTypeToEnum(props.match.params.sort) : 
-      SortType.New;
+    return props.match.params.sort
+      ? routeSortTypeToEnum(props.match.params.sort)
+      SortType.New;
   }
 
   getPageFromProps(props: any): number {
-    return (props.match.params.page) ? Number(props.match.params.page) : 1;
+    return props.match.params.page ? Number(props.match.params.page) : 1;
   }
 
   componentWillUnmount() {
@@ -132,68 +166,98 @@ export class User extends Component<any, UserState> {
   render() {
     return (
       <div class="container">
-        {this.state.loading ? 
-        <h5><svg class="icon icon-spinner spin"><use xlinkHref="#icon-spinner"></use></svg></h5> : 
-        <div class="row">
-          <div class="col-12 col-md-8">
-            <h5>/u/{this.state.user.name}</h5>
-            {this.selects()}
-            {this.state.view == View.Overview &&
-              this.overview()
-            }
-            {this.state.view == View.Comments &&
-              this.comments()
-            }
-            {this.state.view == View.Posts &&
-              this.posts()
-            }
-            {this.state.view == View.Saved &&
-              this.overview()
-            }
-            {this.paginator()}
-          </div>
-          <div class="col-12 col-md-4">
-            {this.userInfo()}
-            {this.isCurrentUser &&
-              this.userSettings()
-            }
-            {this.moderates()}
-            {this.follows()}
+        {this.state.loading ? (
+          <h5>
+            <svg class="icon icon-spinner spin">
+              <use xlinkHref="#icon-spinner"></use>
+            </svg>
+          </h5>
+        ) : (
+          <div class="row">
+            <div class="col-12 col-md-8">
+              <h5>/u/{this.state.user.name}</h5>
+              {this.selects()}
+              {this.state.view == View.Overview && this.overview()}
+              {this.state.view == View.Comments && this.comments()}
+              {this.state.view == View.Posts && this.posts()}
+              {this.state.view == View.Saved && this.overview()}
+              {this.paginator()}
+            </div>
+            <div class="col-12 col-md-4">
+              {this.userInfo()}
+              {this.isCurrentUser && this.userSettings()}
+              {this.moderates()}
+              {this.follows()}
+            </div>
           </div>
-        </div>
-        }
+        )}
       </div>
-    )
+    );
   }
 
   selects() {
     return (
       <div className="mb-2">
-        <select value={this.state.view} onChange={linkEvent(this, this.handleViewChange)} class="custom-select custom-select-sm w-auto">
-          <option disabled><T i18nKey="view">#</T></option>
-          <option value={View.Overview}><T i18nKey="overview">#</T></option>
-          <option value={View.Comments}><T i18nKey="comments">#</T></option>
-          <option value={View.Posts}><T i18nKey="posts">#</T></option>
-          <option value={View.Saved}><T i18nKey="saved">#</T></option>
+        <select
+          value={this.state.view}
+          onChange={linkEvent(this, this.handleViewChange)}
+          class="custom-select custom-select-sm w-auto"
+        >
+          <option disabled>
+            <T i18nKey="view">#</T>
+          </option>
+          <option value={View.Overview}>
+            <T i18nKey="overview">#</T>
+          </option>
+          <option value={View.Comments}>
+            <T i18nKey="comments">#</T>
+          </option>
+          <option value={View.Posts}>
+            <T i18nKey="posts">#</T>
+          </option>
+          <option value={View.Saved}>
+            <T i18nKey="saved">#</T>
+          </option>
         </select>
-        <select value={this.state.sort} onChange={linkEvent(this, this.handleSortChange)} class="custom-select custom-select-sm w-auto ml-2">
-          <option disabled><T i18nKey="sort_type">#</T></option>
-          <option value={SortType.New}><T i18nKey="new">#</T></option>
-          <option value={SortType.TopDay}><T i18nKey="top_day">#</T></option>
-          <option value={SortType.TopWeek}><T i18nKey="week">#</T></option>
-          <option value={SortType.TopMonth}><T i18nKey="month">#</T></option>
-          <option value={SortType.TopYear}><T i18nKey="year">#</T></option>
-          <option value={SortType.TopAll}><T i18nKey="all">#</T></option>
+        <select
+          value={this.state.sort}
+          onChange={linkEvent(this, this.handleSortChange)}
+          class="custom-select custom-select-sm w-auto ml-2"
+        >
+          <option disabled>
+            <T i18nKey="sort_type">#</T>
+          </option>
+          <option value={SortType.New}>
+            <T i18nKey="new">#</T>
+          </option>
+          <option value={SortType.TopDay}>
+            <T i18nKey="top_day">#</T>
+          </option>
+          <option value={SortType.TopWeek}>
+            <T i18nKey="week">#</T>
+          </option>
+          <option value={SortType.TopMonth}>
+            <T i18nKey="month">#</T>
+          </option>
+          <option value={SortType.TopYear}>
+            <T i18nKey="year">#</T>
+          </option>
+          <option value={SortType.TopAll}>
+            <T i18nKey="all">#</T>
+          </option>
         </select>
       </div>
-    )
-
+    );
   }
 
   overview() {
-    let combined: Array<{type_: string, data: Comment | Post}> = [];
-    let comments = this.state.comments.map(e => {return {type_: "comments", data: e}});
-    let posts = this.state.posts.map(e => {return {type_: "posts", data: e}});
+    let combined: Array<{ type_: string; data: Comment | Post }> = [];
+    let comments = this.state.comments.map(e => {
+      return { type_: 'comments', data: e };
+    });
+    let posts = this.state.posts.map(e => {
+      return { type_: 'posts', data: e };
+    });
 
     combined.push(...comments);
     combined.push(...posts);
@@ -207,35 +271,38 @@ export class User extends Component<any, UserState> {
 
     return (
       <div>
-        {combined.map(i =>
+        {combined.map(i => (
           <div>
-            {i.type_ == "posts"
-              ? <PostListing 
-              post={i.data as Post} 
-              admins={this.state.admins}
-              showCommunity 
-              viewOnly />
-              : 
-              <CommentNodes 
-                nodes={[{comment: i.data as Comment}]} 
+            {i.type_ == 'posts' ? (
+              <PostListing
+                post={i.data as Post}
+                admins={this.state.admins}
+                showCommunity
+                viewOnly
+              />
+            ) : (
+              <CommentNodes
+                nodes={[{ comment: i.data as Comment }]}
                 admins={this.state.admins}
-                noIndent />
-            }
+                noIndent
+              />
+            )}
           </div>
-                     )
-        }
+        ))}
       </div>
-    )
+    );
   }
 
   comments() {
     return (
       <div>
-        {this.state.comments.map(comment => 
-          <CommentNodes nodes={[{comment: comment}]} 
+        {this.state.comments.map(comment => (
+          <CommentNodes
+            nodes={[{ comment: comment }]}
             admins={this.state.admins}
-            noIndent />
-        )}
+            noIndent
+          />
+        ))}
       </div>
     );
   }
@@ -243,13 +310,14 @@ export class User extends Component<any, UserState> {
   posts() {
     return (
       <div>
-        {this.state.posts.map(post => 
-          <PostListing 
-            post={post} 
+        {this.state.posts.map(post => (
+          <PostListing
+            post={post}
             admins={this.state.admins}
-            showCommunity 
-            viewOnly />
-        )}
+            showCommunity
+            viewOnly
+          />
+        ))}
       </div>
     );
   }
@@ -263,124 +331,245 @@ export class User extends Component<any, UserState> {
             <h5>
               <ul class="list-inline mb-0">
                 <li className="list-inline-item">{user.name}</li>
-                {user.banned &&  
-                  <li className="list-inline-item badge badge-danger"><T i18nKey="banned">#</T></li>
-                }
+                {user.banned && (
+                  <li className="list-inline-item badge badge-danger">
+                    <T i18nKey="banned">#</T>
+                  </li>
+                )}
               </ul>
             </h5>
-            <div>{i18n.t('joined')} <MomentTime data={user} /></div>
+            <div>
+              {i18n.t('joined')} <MomentTime data={user} />
+            </div>
             <div class="table-responsive">
               <table class="table table-bordered table-sm mt-2 mb-0">
                 <tr>
-                  <td><T i18nKey="number_of_points" interpolation={{count: user.post_score}}>#</T></td>
-                  <td><T i18nKey="number_of_posts" interpolation={{count: user.number_of_posts}}>#</T></td>
+                  <td>
+                    <T
+                      i18nKey="number_of_points"
+                      interpolation={{ count: user.post_score }}
+                    >
+                      #
+                    </T>
+                  </td>
+                  <td>
+                    <T
+                      i18nKey="number_of_posts"
+                      interpolation={{ count: user.number_of_posts }}
+                    >
+                      #
+                    </T>
+                  </td>
                 </tr>
                 <tr>
-                  <td><T i18nKey="number_of_points" interpolation={{count: user.comment_score}}>#</T></td>
-                  <td><T i18nKey="number_of_comments" interpolation={{count: user.number_of_comments}}>#</T></td>
+                  <td>
+                    <T
+                      i18nKey="number_of_points"
+                      interpolation={{ count: user.comment_score }}
+                    >
+                      #
+                    </T>
+                  </td>
+                  <td>
+                    <T
+                      i18nKey="number_of_comments"
+                      interpolation={{ count: user.number_of_comments }}
+                    >
+                      #
+                    </T>
+                  </td>
                 </tr>
               </table>
             </div>
           </div>
         </div>
       </div>
-    )
+    );
   }
 
-  userSettings() {  
+  userSettings() {
     return (
       <div>
         <div class="card border-secondary mb-3">
           <div class="card-body">
-            <h5><T i18nKey="settings">#</T></h5>
+            <h5>
+              <T i18nKey="settings">#</T>
+            </h5>
             <form onSubmit={linkEvent(this, this.handleUserSettingsSubmit)}>
               <div class="form-group">
                 <div class="col-12">
-                  <label><T i18nKey="theme">#</T></label>
-                  <select value={this.state.userSettingsForm.theme} onChange={linkEvent(this, this.handleUserSettingsThemeChange)} class="ml-2 custom-select custom-select-sm w-auto">
-                    <option disabled><T i18nKey="theme">#</T></option>
-                    {themes.map(theme =>
-                      <option value={theme}>{theme}</option>
+                  <label>
+                    <T i18nKey="theme">#</T>
+                  </label>
+                  <select
+                    value={this.state.userSettingsForm.theme}
+                    onChange={linkEvent(
+                      this,
+                      this.handleUserSettingsThemeChange
                     )}
+                    class="ml-2 custom-select custom-select-sm w-auto"
+                  >
+                    <option disabled>
+                      <T i18nKey="theme">#</T>
+                    </option>
+                    {themes.map(theme => (
+                      <option value={theme}>{theme}</option>
+                    ))}
                   </select>
                 </div>
               </div>
               <div class="form-group">
                 <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>
+                    <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 mb-0">
                 <div class="col-12">
-                  <button type="submit" class="btn btn-secondary mr-4">{this.state.userSettingsLoading ? 
-                  <svg class="icon icon-spinner spin"><use xlinkHref="#icon-spinner"></use></svg> : capitalizeFirstLetter(i18n.t('save'))}</button>
-                  <button class="btn btn-danger" onClick={linkEvent(this, this.handleDeleteAccountShowConfirmToggle)}><T i18nKey="delete_account">#</T></button>
-                  {this.state.deleteAccountShowConfirm && 
+                  <button type="submit" class="btn btn-secondary mr-4">
+                    {this.state.userSettingsLoading ? (
+                      <svg class="icon icon-spinner spin">
+                        <use xlinkHref="#icon-spinner"></use>
+                      </svg>
+                    ) : (
+                      capitalizeFirstLetter(i18n.t('save'))
+                    )}
+                  </button>
+                  <button
+                    class="btn btn-danger"
+                    onClick={linkEvent(
+                      this,
+                      this.handleDeleteAccountShowConfirmToggle
+                    )}
+                  >
+                    <T i18nKey="delete_account">#</T>
+                  </button>
+                  {this.state.deleteAccountShowConfirm && (
                     <>
-                      <div class="my-2 alert alert-danger" role="alert"><T i18nKey="delete_account_confirm">#</T></div>
-                      <input type="password" value={this.state.deleteAccountForm.password}  onInput={linkEvent(this, this.handleDeleteAccountPasswordChange)} class="form-control my-2" />
-                      <button class="btn btn-danger mr-4" disabled={!this.state.deleteAccountForm.password} onClick={linkEvent(this, this.handleDeleteAccount)}>{this.state.deleteAccountLoading ? 
-                      <svg class="icon icon-spinner spin"><use xlinkHref="#icon-spinner"></use></svg> : capitalizeFirstLetter(i18n.t('delete'))}</button>
-                      <button class="btn btn-secondary" onClick={linkEvent(this, this.handleDeleteAccountShowConfirmToggle)}><T i18nKey="cancel">#</T></button>
+                      <div class="my-2 alert alert-danger" role="alert">
+                        <T i18nKey="delete_account_confirm">#</T>
+                      </div>
+                      <input
+                        type="password"
+                        value={this.state.deleteAccountForm.password}
+                        onInput={linkEvent(
+                          this,
+                          this.handleDeleteAccountPasswordChange
+                        )}
+                        class="form-control my-2"
+                      />
+                      <button
+                        class="btn btn-danger mr-4"
+                        disabled={!this.state.deleteAccountForm.password}
+                        onClick={linkEvent(this, this.handleDeleteAccount)}
+                      >
+                        {this.state.deleteAccountLoading ? (
+                          <svg class="icon icon-spinner spin">
+                            <use xlinkHref="#icon-spinner"></use>
+                          </svg>
+                        ) : (
+                          capitalizeFirstLetter(i18n.t('delete'))
+                        )}
+                      </button>
+                      <button
+                        class="btn btn-secondary"
+                        onClick={linkEvent(
+                          this,
+                          this.handleDeleteAccountShowConfirmToggle
+                        )}
+                      >
+                        <T i18nKey="cancel">#</T>
+                      </button>
                     </>
-                  }
+                  )}
                 </div>
               </div>
             </form>
           </div>
         </div>
       </div>
-    )
+    );
   }
 
   moderates() {
     return (
       <div>
-        {this.state.moderates.length > 0 &&
+        {this.state.moderates.length > 0 && (
           <div class="card border-secondary mb-3">
             <div class="card-body">
-              <h5><T i18nKey="moderates">#</T></h5>
-              <ul class="list-unstyled mb-0"> 
-                {this.state.moderates.map(community =>
-                  <li><Link to={`/c/${community.community_name}`}>{community.community_name}</Link></li>
-                )}
+              <h5>
+                <T i18nKey="moderates">#</T>
+              </h5>
+              <ul class="list-unstyled mb-0">
+                {this.state.moderates.map(community => (
+                  <li>
+                    <Link to={`/c/${community.community_name}`}>
+                      {community.community_name}
+                    </Link>
+                  </li>
+                ))}
               </ul>
             </div>
           </div>
-        }
+        )}
       </div>
-    )
+    );
   }
 
   follows() {
     return (
       <div>
-        {this.state.follows.length > 0 &&
+        {this.state.follows.length > 0 && (
           <div class="card border-secondary mb-3">
             <div class="card-body">
-              <h5><T i18nKey="subscribed">#</T></h5>
-              <ul class="list-unstyled mb-0"> 
-                {this.state.follows.map(community =>
-                  <li><Link to={`/c/${community.community_name}`}>{community.community_name}</Link></li>
-                )}
+              <h5>
+                <T i18nKey="subscribed">#</T>
+              </h5>
+              <ul class="list-unstyled mb-0">
+                {this.state.follows.map(community => (
+                  <li>
+                    <Link to={`/c/${community.community_name}`}>
+                      {community.community_name}
+                    </Link>
+                  </li>
+                ))}
               </ul>
             </div>
           </div>
-        }
+        )}
       </div>
-    )
+    );
   }
 
   paginator() {
     return (
       <div class="my-2">
-        {this.state.page > 1 && 
-          <button class="btn btn-sm btn-secondary mr-1" onClick={linkEvent(this, this.prevPage)}><T i18nKey="prev">#</T></button>
-        }
-        <button class="btn btn-sm btn-secondary" onClick={linkEvent(this, this.nextPage)}><T i18nKey="next">#</T></button>
+        {this.state.page > 1 && (
+          <button
+            class="btn btn-sm btn-secondary mr-1"
+            onClick={linkEvent(this, this.prevPage)}
+          >
+            <T i18nKey="prev">#</T>
+          </button>
+        )}
+        <button
+          class="btn btn-sm btn-secondary"
+          onClick={linkEvent(this, this.nextPage)}
+        >
+          <T i18nKey="next">#</T>
+        </button>
       </div>
     );
   }
@@ -388,17 +577,19 @@ export class User extends Component<any, UserState> {
   updateUrl() {
     let viewStr = View[this.state.view].toLowerCase();
     let sortStr = SortType[this.state.sort].toLowerCase();
-    this.props.history.push(`/u/${this.state.user.name}/view/${viewStr}/sort/${sortStr}/page/${this.state.page}`);
+    this.props.history.push(
+      `/u/${this.state.user.name}/view/${viewStr}/sort/${sortStr}/page/${this.state.page}`
+    );
   }
 
-  nextPage(i: User) { 
+  nextPage(i: User) {
     i.state.page++;
     i.setState(i.state);
     i.updateUrl();
     i.refetch();
   }
 
-  prevPage(i: User) { 
+  prevPage(i: User) {
     i.state.page--;
     i.setState(i.state);
     i.updateUrl();
@@ -489,11 +680,14 @@ export class User extends Component<any, UserState> {
       this.state.admins = res.admins;
       this.state.loading = false;
       if (this.isCurrentUser) {
-        this.state.userSettingsForm.show_nsfw = UserService.Instance.user.show_nsfw;
-        this.state.userSettingsForm.theme = UserService.Instance.user.theme ? UserService.Instance.user.theme : 'darkly';
+        this.state.userSettingsForm.show_nsfw =
+          UserService.Instance.user.show_nsfw;
+        this.state.userSettingsForm.theme = UserService.Instance.user.theme
+          ? UserService.Instance.user.theme
+          : 'darkly';
       }
       document.title = `/u/${this.state.user.name} - ${WebSocketService.Instance.site.name}`;
-      window.scrollTo(0,0);
+      window.scrollTo(0, 0);
       this.setState(this.state);
     } else if (op == UserOperation.EditComment) {
       let res: CommentResponse = msg;
@@ -520,36 +714,38 @@ export class User extends Component<any, UserState> {
       this.setState(this.state);
     } else if (op == UserOperation.CreateCommentLike) {
       let res: CommentResponse = msg;
-      let found: Comment = this.state.comments.find(c => c.id === res.comment.id);
+      let found: Comment = this.state.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;
+      if (res.comment.my_vote !== null) found.my_vote = res.comment.my_vote;
       this.setState(this.state);
     } else if (op == UserOperation.BanUser) {
       let res: BanUserResponse = msg;
-      this.state.comments.filter(c => c.creator_id == res.user.id)
-      .forEach(c => c.banned = res.banned);
-      this.state.posts.filter(c => c.creator_id == res.user.id)
-      .forEach(c => c.banned = res.banned);
+      this.state.comments
+        .filter(c => c.creator_id == res.user.id)
+        .forEach(c => (c.banned = res.banned));
+      this.state.posts
+        .filter(c => c.creator_id == res.user.id)
+        .forEach(c => (c.banned = res.banned));
       this.setState(this.state);
     } else if (op == UserOperation.AddAdmin) {
       let res: AddAdminResponse = msg;
       this.state.admins = res.admins;
       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);
+      this.state = this.emptyState;
+      this.state.userSettingsLoading = false;
+      this.setState(this.state);
+      let res: LoginResponse = msg;
+      UserService.Instance.login(res);
     } else if (op == UserOperation.DeleteAccount) {
-        this.state.deleteAccountLoading = false;
-        this.state.deleteAccountShowConfirm = false;
-        this.setState(this.state);
-        this.context.router.history.push('/');
+      this.state.deleteAccountLoading = false;
+      this.state.deleteAccountShowConfirm = false;
+      this.setState(this.state);
+      this.context.router.history.push('/');
     }
   }
 }
-
index a0cdcdb06285366036f11ca7efb66546d4cb928c..82377415be498ff7c9fe7733bd8333e90caf7f6f 100644 (file)
@@ -1,4 +1,6 @@
 let host = `${window.location.hostname}`;
-let port = `${window.location.port == "4444" ? '8536' : window.location.port}`;
+let port = `${window.location.port == '4444' ? '8536' : window.location.port}`;
 let endpoint = `${host}:${port}`;
-export let wsUri = `${(window.location.protocol=='https:') ? 'wss://' : 'ws://'}${endpoint}/api/v1/ws`;
+export let wsUri = `${
+  window.location.protocol == 'https:' ? 'wss://' : 'ws://'
+}${endpoint}/api/v1/ws`;
index 069c820d10d5cd2809db744ead91154f9f26503c..083cc7f6ad1d4c572353bad7be9c254c9e3f07c1 100644 (file)
@@ -22,26 +22,24 @@ const resources = {
   sv,
   ru,
   nl,
-}
+};
 
 function format(value: any, format: any, lng: any) {
-       if (format === 'uppercase') return value.toUpperCase();
-       return value;
+  if (format === 'uppercase') return value.toUpperCase();
+  return value;
 }
 
-i18n
-.init({
+i18n.init({
   debug: true,
   // load: 'languageOnly',
 
   // initImmediate: false,
   lng: getLanguage(),
   fallbackLng: 'en',
-       resources,
-       interpolation: {
-    format: format
-    
-  }
+  resources,
+  interpolation: {
+    format: format,
+  },
 });
 
 export { i18n, resources };
index e9deba10499092c4833313d9183dc6bc04ab425f..f3c7ff38ab64cf88b4a3b6d723421a7443df311b 100644 (file)
@@ -24,7 +24,6 @@ import { WebSocketService, UserService } from './services';
 const container = document.getElementById('app');
 
 class Index extends Component<any, any> {
-
   constructor(props: any, context: any) {
     super(props, context);
     WebSocketService.Instance;
@@ -38,7 +37,10 @@ class Index extends Component<any, any> {
           <Navbar />
           <div class="mt-4 p-0">
             <Switch>
-              <Route path={`/home/type/:type/sort/:sort/page/:page`} component={Main} />
+              <Route
+                path={`/home/type/:type/sort/:sort/page/:page`}
+                component={Main}
+              />
               <Route exact path={`/`} component={Main} />
               <Route path={`/login`} component={Login} />
               <Route path={`/create_post`} component={CreatePost} />
@@ -47,17 +49,29 @@ class Index extends Component<any, any> {
               <Route path={`/communities`} component={Communities} />
               <Route path={`/post/:id/comment/:comment_id`} component={Post} />
               <Route path={`/post/:id`} component={Post} />
-              <Route path={`/c/:name/sort/:sort/page/:page`} component={Community} />
+              <Route
+                path={`/c/:name/sort/:sort/page/:page`}
+                component={Community}
+              />
               <Route path={`/community/:id`} component={Community} />
               <Route path={`/c/:name`} component={Community} />
-              <Route path={`/u/:username/view/:view/sort/:sort/page/:page`} component={User} />
+              <Route
+                path={`/u/:username/view/:view/sort/:sort/page/:page`}
+                component={User}
+              />
               <Route path={`/user/:id`} component={User} />
               <Route path={`/u/:username`} component={User} />
               <Route path={`/inbox`} component={Inbox} />
-              <Route path={`/modlog/community/:community_id`} component={Modlog} />
+              <Route
+                path={`/modlog/community/:community_id`}
+                component={Modlog}
+              />
               <Route path={`/modlog`} component={Modlog} />
               <Route path={`/setup`} component={Setup} />
-              <Route path={`/search/q/:q/type/:type/sort/:sort/page/:page`} component={Search} />
+              <Route
+                path={`/search/q/:q/type/:type/sort/:sort/page/:page`}
+                component={Search}
+              />
               <Route path={`/search`} component={Search} />
               <Route path={`/sponsors`} component={Sponsors} />
             </Switch>
@@ -68,7 +82,6 @@ class Index extends Component<any, any> {
       </Provider>
     );
   }
-
 }
 
 render(<Index />, container);
index e11dee04a6bd5263a6b0246a2e1c5ca4fee41d3a..fa14b23852c955a31ef70d3233598d3af41b9cba 100644 (file)
@@ -1,21 +1,70 @@
 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, SaveUserSettings, TransferCommunity, TransferSite, DeleteAccount
+  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,
+  TransferCommunity,
+  TransferSite,
+  DeleteAccount,
 }
 
 export enum CommentSortType {
-  Hot, Top, New
+  Hot,
+  Top,
+  New,
 }
 
 export enum ListingType {
-  All, Subscribed, Community
+  All,
+  Subscribed,
+  Community,
 }
 
 export enum SortType {
-  Hot, New, TopDay, TopWeek, TopMonth, TopYear, TopAll
+  Hot,
+  New,
+  TopDay,
+  TopWeek,
+  TopMonth,
+  TopYear,
+  TopAll,
 }
 
 export enum SearchType {
-  All, Comments, Posts, Communities, Users, Url
+  All,
+  Comments,
+  Posts,
+  Communities,
+  Users,
+  Url,
 }
 
 export interface User {
@@ -104,7 +153,7 @@ export interface Post {
 export interface Comment {
   id: number;
   creator_id: number;
-  post_id: number,
+  post_id: number;
   parent_id?: number;
   content: string;
   removed: boolean;
@@ -112,7 +161,7 @@ export interface Comment {
   read: boolean;
   published: string;
   updated?: string;
-  community_id: number,
+  community_id: number;
   banned: boolean;
   banned_from_community: boolean;
   creator_name: string;
@@ -143,7 +192,10 @@ export interface Site {
   number_of_communities: number;
 }
 
-export enum BanType {Community, Site};
+export enum BanType {
+  Community,
+  Site,
+}
 
 export interface FollowCommunityForm {
   community_id: number;
@@ -193,15 +245,15 @@ export interface BanFromCommunityForm {
   community_id: number;
   user_id: number;
   ban: boolean;
-  reason?: string,
-  expires?: number,
+  reason?: string;
+  expires?: number;
   auth?: string;
 }
 
 export interface BanFromCommunityResponse {
   op: string;
-  user: UserView,
-  banned: boolean,
+  user: UserView;
+  banned: boolean;
 }
 
 export interface AddModToCommunityForm {
@@ -236,15 +288,15 @@ export interface GetModlogForm {
 
 export interface GetModlogResponse {
   op: string;
-  removed_posts: Array<ModRemovePost>,
-  locked_posts: Array<ModLockPost>,
-  stickied_posts: Array<ModStickyPost>,
-  removed_comments: Array<ModRemoveComment>,
-  removed_communities: Array<ModRemoveCommunity>,
-  banned_from_community: Array<ModBanFromCommunity>,
-  banned: Array<ModBan>,
-  added_to_community: Array<ModAddCommunity>,
-  added: Array<ModAdd>,
+  removed_posts: Array<ModRemovePost>;
+  locked_posts: Array<ModLockPost>;
+  stickied_posts: Array<ModStickyPost>;
+  removed_comments: Array<ModRemoveComment>;
+  removed_communities: Array<ModRemoveCommunity>;
+  banned_from_community: Array<ModBanFromCommunity>;
+  banned: Array<ModBan>;
+  added_to_community: Array<ModAddCommunity>;
+  added: Array<ModAdd>;
 }
 
 export interface ModRemovePost {
@@ -253,7 +305,7 @@ export interface ModRemovePost {
   post_id: number;
   reason?: string;
   removed?: boolean;
-  when_: string
+  when_: string;
   mod_user_name: string;
   post_name: string;
   community_id: number;
@@ -261,104 +313,104 @@ export interface ModRemovePost {
 }
 
 export interface ModLockPost {
-  id: number,
-  mod_user_id: number,
-  post_id: number,
-  locked?: boolean,
-  when_: string,
-  mod_user_name: string,
-  post_name: string,
-  community_id: number,
-  community_name: string,
+  id: number;
+  mod_user_id: number;
+  post_id: number;
+  locked?: boolean;
+  when_: string;
+  mod_user_name: string;
+  post_name: string;
+  community_id: number;
+  community_name: string;
 }
 
 export interface ModStickyPost {
-  id: number,
-  mod_user_id: number,
-  post_id: number,
-  stickied?: boolean,
-  when_: string,
-  mod_user_name: string,
-  post_name: string,
-  community_id: number,
-  community_name: string,
+  id: number;
+  mod_user_id: number;
+  post_id: number;
+  stickied?: boolean;
+  when_: string;
+  mod_user_name: string;
+  post_name: string;
+  community_id: number;
+  community_name: string;
 }
 
 export interface ModRemoveComment {
-  id: number,
-  mod_user_id: number,
-  comment_id: number,
-  reason?: string,
-  removed?: boolean,
-  when_: string,
-  mod_user_name: string,
-  comment_user_id: number,
-  comment_user_name: string,
-  comment_content: string,
-  post_id: number,
-  post_name: string,
-  community_id: number,
-  community_name: string,
+  id: number;
+  mod_user_id: number;
+  comment_id: number;
+  reason?: string;
+  removed?: boolean;
+  when_: string;
+  mod_user_name: string;
+  comment_user_id: number;
+  comment_user_name: string;
+  comment_content: string;
+  post_id: number;
+  post_name: string;
+  community_id: number;
+  community_name: string;
 }
 
 export interface ModRemoveCommunity {
-  id: number,
-  mod_user_id: number,
-  community_id: number,
-  reason?: string,
-  removed?: boolean,
-  expires?: number,
-  when_: string,
-  mod_user_name: string,
-  community_name: string,
+  id: number;
+  mod_user_id: number;
+  community_id: number;
+  reason?: string;
+  removed?: boolean;
+  expires?: number;
+  when_: string;
+  mod_user_name: string;
+  community_name: string;
 }
 
 export interface ModBanFromCommunity {
-  id: number,
-  mod_user_id: number,
-  other_user_id: number,
-  community_id: number,
-  reason?: string,
-  banned?: boolean,
-  expires?: number,
-  when_: string,
-  mod_user_name: string,
-  other_user_name: string,
-  community_name: string,
+  id: number;
+  mod_user_id: number;
+  other_user_id: number;
+  community_id: number;
+  reason?: string;
+  banned?: boolean;
+  expires?: number;
+  when_: string;
+  mod_user_name: string;
+  other_user_name: string;
+  community_name: string;
 }
 
 export interface ModBan {
-  id: number,
-  mod_user_id: number,
-  other_user_id: number,
-  reason?: string,
-  banned?: boolean,
-  expires?: number,
-  when_: string,
-  mod_user_name: string,
-  other_user_name: string,
+  id: number;
+  mod_user_id: number;
+  other_user_id: number;
+  reason?: string;
+  banned?: boolean;
+  expires?: number;
+  when_: string;
+  mod_user_name: string;
+  other_user_name: string;
 }
 
 export interface ModAddCommunity {
-  id: number,
-  mod_user_id: number,
-  other_user_id: number,
-  community_id: number,
-  removed?: boolean,
-  when_: string,
-  mod_user_name: string,
-  other_user_name: string,
-  community_name: string,
+  id: number;
+  mod_user_id: number;
+  other_user_id: number;
+  community_id: number;
+  removed?: boolean;
+  when_: string;
+  mod_user_name: string;
+  other_user_name: string;
+  community_name: string;
 }
 
 export interface ModAdd {
-  id: number,
-  mod_user_id: number,
-  other_user_id: number,
-  removed?: boolean,
-  when_: string,
-  mod_user_name: string,
-  other_user_name: string,
+  id: number;
+  mod_user_id: number;
+  other_user_id: number;
+  removed?: boolean;
+  when_: string;
+  mod_user_name: string;
+  other_user_name: string;
 }
 
 export interface LoginForm {
@@ -389,8 +441,8 @@ export interface UserSettingsForm {
 export interface CommunityForm {
   name: string;
   title: string;
-  description?: string,
-  category_id: number,
+  description?: string;
+  category_id: number;
   edit_id?: number;
   removed?: boolean;
   deleted?: boolean;
@@ -407,7 +459,6 @@ export interface GetCommunityResponse {
   admins: Array<UserView>;
 }
 
-
 export interface CommunityResponse {
   op: string;
   community: Community;
@@ -537,7 +588,7 @@ export interface CreatePostLikeResponse {
 
 export interface SiteForm {
   name: string;
-  description?: string,
+  description?: string;
   removed?: boolean;
   reason?: string;
   expires?: number;
@@ -552,7 +603,6 @@ export interface GetSiteResponse {
   online: number;
 }
 
-
 export interface SiteResponse {
   op: string;
   site: Site;
@@ -561,15 +611,15 @@ export interface SiteResponse {
 export interface BanUserForm {
   user_id: number;
   ban: boolean;
-  reason?: string,
-  expires?: number,
+  reason?: string;
+  expires?: number;
   auth?: string;
 }
 
 export interface BanUserResponse {
   op: string;
-  user: UserView,
-  banned: boolean,
+  user: UserView;
+  banned: boolean;
 }
 
 export interface AddAdminForm {
@@ -597,7 +647,7 @@ export interface SearchResponse {
   type_: string;
   posts?: Array<Post>;
   comments?: Array<Comment>;
-  communities: Array<Community>;  
+  communities: Array<Community>;
   users: Array<UserView>;
 }
 
index ac4d485059c8d991460d3f9a8afd5ed882bfa31b..5ca5ff07e757f8c227d8158abf317629e25e70cb 100644 (file)
@@ -5,13 +5,15 @@ import * as jwt_decode from 'jwt-decode';
 import { Subject } from 'rxjs';
 
 export class UserService {
-
   private static _instance: UserService;
   public user: User;
-  public sub: Subject<{user: User, unreadCount: number}> = new Subject<{user: User, unreadCount: number}>();
+  public sub: Subject<{ user: User; unreadCount: number }> = new Subject<{
+    user: User;
+    unreadCount: number;
+  }>();
 
   private constructor() {
-    let jwt = Cookies.get("jwt");
+    let jwt = Cookies.get('jwt');
     if (jwt) {
       this.setUser(jwt);
     } else {
@@ -22,30 +24,30 @@ export class UserService {
 
   public login(res: LoginResponse) {
     this.setUser(res.jwt);
-    Cookies.set("jwt", res.jwt, { expires: 365 });
-    console.log("jwt cookie set");
+    Cookies.set('jwt', res.jwt, { expires: 365 });
+    console.log('jwt cookie set');
   }
 
   public logout() {
     this.user = undefined;
-    Cookies.remove("jwt");
+    Cookies.remove('jwt');
     setTheme();
-    this.sub.next({user: undefined, unreadCount: 0});
-    console.log("Logged out.");
+    this.sub.next({ user: undefined, unreadCount: 0 });
+    console.log('Logged out.');
   }
 
   public get auth(): string {
-    return Cookies.get("jwt");
+    return Cookies.get('jwt');
   }
 
   private setUser(jwt: string) {
     this.user = jwt_decode(jwt);
     setTheme(this.user.theme);
-    this.sub.next({user: this.user, unreadCount: 0});
+    this.sub.next({ user: this.user, unreadCount: 0 });
     console.log(this.user);
   }
 
-  public static get Instance(){
+  public static get Instance() {
     return this._instance || (this._instance = new this());
   }
 }
index 987cbfdf15c12d530728bd3098e26f31fbe21b75..f5d5b5136034eb364c2731a40d9706d1dd7c5773 100644 (file)
@@ -1,5 +1,34 @@
 import { wsUri } from '../env';
-import { LoginForm, RegisterForm, UserOperation, CommunityForm, PostForm, SavePostForm, CommentForm, SaveCommentForm, CommentLikeForm, GetPostsForm, CreatePostLikeForm, FollowCommunityForm, GetUserDetailsForm, ListCommunitiesForm, GetModlogForm, BanFromCommunityForm, AddModToCommunityForm, TransferCommunityForm, AddAdminForm, TransferSiteForm, BanUserForm, SiteForm, Site, UserView, GetRepliesForm, SearchForm, UserSettingsForm, DeleteAccountForm } from '../interfaces';
+import {
+  LoginForm,
+  RegisterForm,
+  UserOperation,
+  CommunityForm,
+  PostForm,
+  SavePostForm,
+  CommentForm,
+  SaveCommentForm,
+  CommentLikeForm,
+  GetPostsForm,
+  CreatePostLikeForm,
+  FollowCommunityForm,
+  GetUserDetailsForm,
+  ListCommunitiesForm,
+  GetModlogForm,
+  BanFromCommunityForm,
+  AddModToCommunityForm,
+  TransferCommunityForm,
+  AddAdminForm,
+  TransferSiteForm,
+  BanUserForm,
+  SiteForm,
+  Site,
+  UserView,
+  GetRepliesForm,
+  SearchForm,
+  UserSettingsForm,
+  DeleteAccountForm,
+} from '../interfaces';
 import { webSocket } from 'rxjs/webSocket';
 import { Subject } from 'rxjs';
 import { retryWhen, delay, take } from 'rxjs/operators';
@@ -19,16 +48,23 @@ export class WebSocketService {
 
     // Necessary to not keep reconnecting
     this.subject
-      .pipe(retryWhen(errors => errors.pipe(delay(60000), take(999))))
+      .pipe(
+        retryWhen(errors =>
+          errors.pipe(
+            delay(60000),
+            take(999)
+          )
+        )
+      )
       .subscribe();
 
-      console.log(`Connected to ${wsUri}`);
+    console.log(`Connected to ${wsUri}`);
   }
 
-  public static get Instance(){
+  public static get Instance() {
     return this._instance || (this._instance = new this());
   }
-   
+
   public login(loginForm: LoginForm) {
     this.subject.next(this.wsSendWrapper(UserOperation.Login, loginForm));
   }
@@ -39,17 +75,23 @@ export class WebSocketService {
 
   public createCommunity(communityForm: CommunityForm) {
     this.setAuth(communityForm);
-    this.subject.next(this.wsSendWrapper(UserOperation.CreateCommunity, communityForm));
+    this.subject.next(
+      this.wsSendWrapper(UserOperation.CreateCommunity, communityForm)
+    );
   }
 
   public editCommunity(communityForm: CommunityForm) {
     this.setAuth(communityForm);
-    this.subject.next(this.wsSendWrapper(UserOperation.EditCommunity, communityForm));
+    this.subject.next(
+      this.wsSendWrapper(UserOperation.EditCommunity, communityForm)
+    );
   }
 
   public followCommunity(followCommunityForm: FollowCommunityForm) {
     this.setAuth(followCommunityForm);
-    this.subject.next(this.wsSendWrapper(UserOperation.FollowCommunity, followCommunityForm));
+    this.subject.next(
+      this.wsSendWrapper(UserOperation.FollowCommunity, followCommunityForm)
+    );
   }
 
   public listCommunities(form: ListCommunitiesForm) {
@@ -58,12 +100,16 @@ export class WebSocketService {
   }
 
   public getFollowedCommunities() {
-    let data = {auth: UserService.Instance.auth };
-    this.subject.next(this.wsSendWrapper(UserOperation.GetFollowedCommunities, data));
+    let data = { auth: UserService.Instance.auth };
+    this.subject.next(
+      this.wsSendWrapper(UserOperation.GetFollowedCommunities, data)
+    );
   }
 
   public listCategories() {
-    this.subject.next(this.wsSendWrapper(UserOperation.ListCategories, undefined));
+    this.subject.next(
+      this.wsSendWrapper(UserOperation.ListCategories, undefined)
+    );
   }
 
   public createPost(postForm: PostForm) {
@@ -72,33 +118,39 @@ export class WebSocketService {
   }
 
   public getPost(postId: number) {
-    let data = {id: postId, auth: UserService.Instance.auth };
+    let data = { id: postId, auth: UserService.Instance.auth };
     this.subject.next(this.wsSendWrapper(UserOperation.GetPost, data));
   }
 
   public getCommunity(communityId: number) {
-    let data = {id: communityId, auth: UserService.Instance.auth };
+    let data = { id: communityId, auth: UserService.Instance.auth };
     this.subject.next(this.wsSendWrapper(UserOperation.GetCommunity, data));
   }
 
   public getCommunityByName(name: string) {
-    let data = {name: name, auth: UserService.Instance.auth };
+    let data = { name: name, auth: UserService.Instance.auth };
     this.subject.next(this.wsSendWrapper(UserOperation.GetCommunity, data));
   }
 
   public createComment(commentForm: CommentForm) {
     this.setAuth(commentForm);
-    this.subject.next(this.wsSendWrapper(UserOperation.CreateComment, commentForm));
+    this.subject.next(
+      this.wsSendWrapper(UserOperation.CreateComment, commentForm)
+    );
   }
 
   public editComment(commentForm: CommentForm) {
     this.setAuth(commentForm);
-    this.subject.next(this.wsSendWrapper(UserOperation.EditComment, commentForm));
+    this.subject.next(
+      this.wsSendWrapper(UserOperation.EditComment, commentForm)
+    );
   }
 
   public likeComment(form: CommentLikeForm) {
     this.setAuth(form);
-    this.subject.next(this.wsSendWrapper(UserOperation.CreateCommentLike, form));
+    this.subject.next(
+      this.wsSendWrapper(UserOperation.CreateCommentLike, form)
+    );
   }
 
   public saveComment(form: SaveCommentForm) {
@@ -133,19 +185,23 @@ export class WebSocketService {
 
   public addModToCommunity(form: AddModToCommunityForm) {
     this.setAuth(form);
-    this.subject.next(this.wsSendWrapper(UserOperation.AddModToCommunity, form));
+    this.subject.next(
+      this.wsSendWrapper(UserOperation.AddModToCommunity, form)
+    );
   }
 
   public transferCommunity(form: TransferCommunityForm) {
     this.setAuth(form);
-    this.subject.next(this.wsSendWrapper(UserOperation.TransferCommunity, form));
+    this.subject.next(
+      this.wsSendWrapper(UserOperation.TransferCommunity, form)
+    );
   }
 
   public transferSite(form: TransferSiteForm) {
     this.setAuth(form);
     this.subject.next(this.wsSendWrapper(UserOperation.TransferSite, form));
   }
-  
+
   public banUser(form: BanUserForm) {
     this.setAuth(form);
     this.subject.next(this.wsSendWrapper(UserOperation.BanUser, form));
@@ -196,7 +252,9 @@ export class WebSocketService {
 
   public saveUserSettings(userSettingsForm: UserSettingsForm) {
     this.setAuth(userSettingsForm);
-    this.subject.next(this.wsSendWrapper(UserOperation.SaveUserSettings, userSettingsForm));
+    this.subject.next(
+      this.wsSendWrapper(UserOperation.SaveUserSettings, userSettingsForm)
+    );
   }
 
   public deleteAccount(form: DeleteAccountForm) {
@@ -214,13 +272,12 @@ export class WebSocketService {
     obj.auth = UserService.Instance.auth;
     if (obj.auth == null && throwErr) {
       alert(i18n.t('not_logged_in'));
-      throw "Not logged in";
+      throw 'Not logged in';
     }
   }
 }
 
-window.onbeforeunload = (() => {
+window.onbeforeunload = () => {
   WebSocketService.Instance.subject.unsubscribe();
   WebSocketService.Instance.subject = null;
-});
-
+};
index 8430d3a51c1ed20c9334e1f59cb63e3c979a6e00..0eed856d682e55403daec49a6e69e56b8cefdbf4 100644 (file)
@@ -5,18 +5,18 @@ export const de = {
     no_posts: 'Keine Beiträge.',
     create_a_post: 'Einen Beitrag anlegen',
     create_post: 'Beitrag anlegen',
-    number_of_posts:'{{count}} Beiträge',
+    number_of_posts: '{{count}} Beiträge',
     posts: 'Beiträge',
     related_posts: 'Diese Beiträge könnten verwandt sein',
     comments: 'Kommentare',
-    number_of_comments:'{{count}} Kommentare',
+    number_of_comments: '{{count}} Kommentare',
     remove_comment: 'Kommentar löschen',
     communities: 'Communities',
     create_a_community: 'Eine community anlegen',
     create_community: 'Community anlegen',
     remove_community: 'Community entfernen',
-    subscribed_to_communities:'Abonnierte <1>communities</1>',
-    trending_communities:'Trending <1>communities</1>',
+    subscribed_to_communities: 'Abonnierte <1>communities</1>',
+    trending_communities: 'Trending <1>communities</1>',
     list_of_communities: 'Liste von communities',
     community_reqs: 'Kleinbuchstaben, Großbuchstaben und keine Leerzeichen.',
     edit: 'editieren',
@@ -53,9 +53,9 @@ export const de = {
     create: 'anlegen',
     username: 'Username',
     email_or_username: 'Email oder Username',
-    number_of_users:'{{count}} Benutzer',
-    number_of_subscribers:'{{count}} Abonnenten',
-    number_of_points:'{{count}} Punkte',
+    number_of_users: '{{count}} Benutzer',
+    number_of_subscribers: '{{count}} Abonnenten',
+    number_of_points: '{{count}} Punkte',
     name: 'Name',
     title: 'Titel',
     category: 'Kategorie',
@@ -88,7 +88,8 @@ export const de = {
     view: 'Ansicht',
     logout: 'Ausloggen',
     login_sign_up: 'Einloggen / Registrieren',
-    notifications_error: 'Desktop-Benachrichtigungen sind in deinem browser nicht verfügbar. Versuche Firefox oder Chrome.',
+    notifications_error:
+      'Desktop-Benachrichtigungen sind in deinem browser nicht verfügbar. Versuche Firefox oder Chrome.',
     unread_messages: 'Ungelesene Nachrichten',
     password: 'Passwort',
     verify_password: 'Passwort überprüfen',
@@ -111,14 +112,17 @@ export const de = {
     modified: 'verändert',
     sponsors: 'Sponsoren',
     sponsors_of_lemmy: 'Sponsoren von Lemmy',
-    sponsor_message: 'Lemmy ist freie <1>Open-Source</1> Software, also ohne Werbung, Monetarisierung oder Venturekapital, Punkt. Deine Spenden gehen direkt an die Vollzeit Entwicklung des Projekts. Vielen Dank an die folgenden Personen:',
+    sponsor_message:
+      'Lemmy ist freie <1>Open-Source</1> Software, also ohne Werbung, Monetarisierung oder Venturekapital, Punkt. Deine Spenden gehen direkt an die Vollzeit Entwicklung des Projekts. Vielen Dank an die folgenden Personen:',
     support_on_patreon: 'Auf Patreon unterstützen',
-    general_sponsors:'Allgemeine Sponsoren sind die, die zwischen $10 und $39 zu Lemmy beitragen.',
+    general_sponsors:
+      'Allgemeine Sponsoren sind die, die zwischen $10 und $39 zu Lemmy beitragen.',
     bitcoin: 'Bitcoin',
     ethereum: 'Ethereum',
     code: 'Code',
     powered_by: 'Bereitgestellt durch',
-    landing_0: 'Lemmy ist ein <1>Link Aggregator</1> / Reddit Alternative im <2>Fediverse</2>.<3></3>Es ist selbst-hostbar, hat live-updates von Kommentar-threads und ist winzig (<4>~80kB</4>). Federation in das ActivityPub Netzwerk ist geplant. <5></5>Dies ist eine <6>sehr frühe Beta Version</6>, und viele Features funktionieren zurzeit nicht richtig oder fehlen. <7></7>Schlage neue Features vor oder melde Bugs <8>hier.</8><9></9>Gebaut mit <10>Rust</10>, <11>Actix</11>, <12>Inferno</12>, <13>Typescript</13>.',
+    landing_0:
+      'Lemmy ist ein <1>Link Aggregator</1> / Reddit Alternative im <2>Fediverse</2>.<3></3>Es ist selbst-hostbar, hat live-updates von Kommentar-threads und ist winzig (<4>~80kB</4>). Federation in das ActivityPub Netzwerk ist geplant. <5></5>Dies ist eine <6>sehr frühe Beta Version</6>, und viele Features funktionieren zurzeit nicht richtig oder fehlen. <7></7>Schlage neue Features vor oder melde Bugs <8>hier.</8><9></9>Gebaut mit <10>Rust</10>, <11>Actix</11>, <12>Inferno</12>, <13>Typescript</13>.',
     not_logged_in: 'Nicht eingeloggt.',
     community_ban: 'Du wurdest von dieser Community gebannt.',
     site_ban: 'Du wurdest von dieser Seite gebannt',
@@ -132,7 +136,8 @@ export const de = {
     couldnt_find_community: 'Konnte Community nicht finden.',
     couldnt_update_community: 'Konnte Community nicht aktualisieren.',
     community_already_exists: 'Community existiert bereits.',
-    community_moderator_already_exists: 'Community Moderator existiert bereits.',
+    community_moderator_already_exists:
+      'Community Moderator existiert bereits.',
     community_follower_already_exists: 'Community Follower existiert bereits.',
     community_user_already_banned: 'Community Nutzer schon gebannt.',
     couldnt_create_post: 'Konnte Beitrag nicht anlegen.',
@@ -145,13 +150,14 @@ export const de = {
     not_an_admin: 'Kein Administrator.',
     site_already_exists: 'Seite existiert bereits.',
     couldnt_update_site: 'Konnte Seite nicht aktualisieren.',
-    couldnt_find_that_username_or_email: 'Konnte Username oder E-Mail nicht finden.',
+    couldnt_find_that_username_or_email:
+      'Konnte Username oder E-Mail nicht finden.',
     password_incorrect: 'Passwort falsch.',
     passwords_dont_match: 'Passwörter stimmen nicht überein.',
     admin_already_created: 'Entschuldigung, es gibt schon einen Administrator.',
     user_already_exists: 'Nutzer existiert bereits.',
     couldnt_update_user: 'Konnte Nutzer nicht aktualisieren',
-    system_err_login: 'Systemfehler. Versuche dich aus- und wieder einzuloggen.',
+    system_err_login:
+      'Systemfehler. Versuche dich aus- und wieder einzuloggen.',
   },
-}
-
+};
index 7a23e20992ff0ee6805b68373617e6f95b86ad2d..551c7ef83403b5f1dc7af5a84303a303dbbc0bf0 100644 (file)
@@ -56,7 +56,8 @@ export const en = {
     delete: 'delete',
     deleted: 'deleted',
     delete_account: 'Delete Account',
-    delete_account_confirm: 'Warning: this will permanently delete all your data. Enter your password to confirm.',
+    delete_account_confirm:
+      'Warning: this will permanently delete all your data. Enter your password to confirm.',
     restore: 'restore',
     ban: 'ban',
     ban_from_site: 'ban from site',
@@ -108,7 +109,8 @@ export const en = {
     login_sign_up: 'Login / Sign up',
     login: 'Login',
     sign_up: 'Sign Up',
-    notifications_error: 'Desktop notifications not available in your browser. Try Firefox or Chrome.',
+    notifications_error:
+      'Desktop notifications not available in your browser. Try Firefox or Chrome.',
     unread_messages: 'Unread Messages',
     password: 'Password',
     verify_password: 'Verify Password',
@@ -134,9 +136,11 @@ export const en = {
     theme: 'Theme',
     sponsors: 'Sponsors',
     sponsors_of_lemmy: 'Sponsors of Lemmy',
-    sponsor_message: 'Lemmy is free, <1>open-source</1> software, meaning no advertising, monetizing, or venture capital, ever. Your donations directly support full-time development of the project. Thank you to the following people:',
+    sponsor_message:
+      'Lemmy is free, <1>open-source</1> software, meaning no advertising, monetizing, or venture capital, ever. Your donations directly support full-time development of the project. Thank you to the following people:',
     support_on_patreon: 'Support on Patreon',
-    general_sponsors: 'General Sponsors are those that pledged $10 to $39 to Lemmy.',
+    general_sponsors:
+      'General Sponsors are those that pledged $10 to $39 to Lemmy.',
     crypto: 'Crypto',
     bitcoin: 'Bitcoin',
     ethereum: 'Ethereum',
@@ -151,40 +155,41 @@ export const en = {
     yes: 'yes',
     no: 'no',
     powered_by: 'Powered by',
-    landing_0: 'Lemmy is a <1>link aggregator</1> / reddit alternative, intended to work in the <2>fediverse</2>.<3></3>It\'s self-hostable, has live-updating comment threads, and is tiny (<4>~80kB</4>). Federation into the ActivityPub network is on the roadmap. <5></5>This is a <6>very early beta version</6>, and a lot of features are currently broken or missing. <7></7>Suggest new features or report bugs <8>here.</8><9></9>Made with <10>Rust</10>, <11>Actix</11>, <12>Inferno</12>, <13>Typescript</13>.',
+    landing_0:
+      "Lemmy is a <1>link aggregator</1> / reddit alternative, intended to work in the <2>fediverse</2>.<3></3>It's self-hostable, has live-updating comment threads, and is tiny (<4>~80kB</4>). Federation into the ActivityPub network is on the roadmap. <5></5>This is a <6>very early beta version</6>, and a lot of features are currently broken or missing. <7></7>Suggest new features or report bugs <8>here.</8><9></9>Made with <10>Rust</10>, <11>Actix</11>, <12>Inferno</12>, <13>Typescript</13>.",
     not_logged_in: 'Not logged in.',
     community_ban: 'You have been banned from this community.',
     site_ban: 'You have been banned from the site',
-    couldnt_create_comment: 'Couldn\'t create comment.',
-    couldnt_like_comment: 'Couldn\'t like comment.',
-    couldnt_update_comment: 'Couldn\'t update comment.',
-    couldnt_save_comment: 'Couldn\'t save comment.',
+    couldnt_create_comment: "Couldn't create comment.",
+    couldnt_like_comment: "Couldn't like comment.",
+    couldnt_update_comment: "Couldn't update comment.",
+    couldnt_save_comment: "Couldn't save comment.",
     no_comment_edit_allowed: 'Not allowed to edit comment.',
     no_post_edit_allowed: 'Not allowed to edit post.',
     no_community_edit_allowed: 'Not allowed to edit community.',
-    couldnt_find_community: 'Couldn\'t find community.',
-    couldnt_update_community: 'Couldn\'t update Community.',
+    couldnt_find_community: "Couldn't find community.",
+    couldnt_update_community: "Couldn't update Community.",
     community_already_exists: 'Community already exists.',
     community_moderator_already_exists: 'Community moderator already exists.',
     community_follower_already_exists: 'Community follower already exists.',
     community_user_already_banned: 'Community user already banned.',
-    couldnt_create_post: 'Couldn\'t create post.',
-    couldnt_like_post: 'Couldn\'t like post.',
-    couldnt_find_post: 'Couldn\'t find post.',
-    couldnt_get_posts: 'Couldn\'t get posts',
-    couldnt_update_post: 'Couldn\'t update post',
-    couldnt_save_post: 'Couldn\'t save post.',
+    couldnt_create_post: "Couldn't create post.",
+    couldnt_like_post: "Couldn't like post.",
+    couldnt_find_post: "Couldn't find post.",
+    couldnt_get_posts: "Couldn't get posts",
+    couldnt_update_post: "Couldn't update post",
+    couldnt_save_post: "Couldn't save post.",
     no_slurs: 'No slurs.',
     not_an_admin: 'Not an admin.',
     site_already_exists: 'Site already exists.',
-    couldnt_update_site: 'Couldn\'t update site.',
-    couldnt_find_that_username_or_email: 'Couldn\'t find that username or email.',
+    couldnt_update_site: "Couldn't update site.",
+    couldnt_find_that_username_or_email:
+      "Couldn't find that username or email.",
     password_incorrect: 'Password incorrect.',
     passwords_dont_match: 'Passwords do not match.',
-    admin_already_created: 'Sorry, there\'s already an admin.',
+    admin_already_created: "Sorry, there's already an admin.",
     user_already_exists: 'User already exists.',
-    couldnt_update_user: 'Couldn\'t update user.',
+    couldnt_update_user: "Couldn't update user.",
     system_err_login: 'System error. Try logging out and back in.',
   },
-}
-
+};
index 07ad7fb7c54ff621840789b86fdd65b8b6b2f6c9..5ef33b25cf873c180cc0f83b1f228a67156e9936 100644 (file)
@@ -5,21 +5,21 @@ export const eo = {
     no_posts: 'Ne Poŝtoj.',
     create_a_post: 'Verki Poŝton',
     create_post: 'Verki Poŝton',
-    number_of_posts:'{{count}} Poŝtoj',
+    number_of_posts: '{{count}} Poŝtoj',
     posts: 'Poŝtoj',
     related_posts: 'Tiuj poŝtoj eble rilatas',
     cross_posts: 'Tiuj ligilo ankaŭ estas poŝtinta al:',
     cross_post: 'laŭapoŝto',
     comments: 'Komentoj',
-    number_of_comments:'{{count}} Komentoj',
+    number_of_comments: '{{count}} Komentoj',
     remove_comment: 'Fortiri Komentojn',
     communities: 'Komunumoj',
     users: 'Uzantoj',
     create_a_community: 'Krei komunumon',
     create_community: 'Krei Komunumon',
     remove_community: 'Forigi Komunumon',
-    subscribed_to_communities:'Abonita al <1>komunumoj</1>',
-    trending_communities:'Furora <1>komunumoj</1>',
+    subscribed_to_communities: 'Abonita al <1>komunumoj</1>',
+    trending_communities: 'Furora <1>komunumoj</1>',
     list_of_communities: 'Listo de komunumoj',
     community_reqs: 'minusklaj leteroj, substrekoj, kaj ne spacetoj.',
     edit: 'redakti',
@@ -57,9 +57,9 @@ export const eo = {
     create: 'krei',
     username: 'Uzantnomo',
     email_or_username: 'Retadreso aŭ Uzantnomo',
-    number_of_users:'{{count}} Uzantoj',
-    number_of_subscribers:'{{count}} Abonantoj',
-    number_of_points:'{{count}} Voĉdonoj',
+    number_of_users: '{{count}} Uzantoj',
+    number_of_subscribers: '{{count}} Abonantoj',
+    number_of_points: '{{count}} Voĉdonoj',
     name: 'Nomo',
     title: 'Titolo',
     category: 'Kategorio',
@@ -95,7 +95,8 @@ export const eo = {
     login_sign_up: 'Ensaluti / Registriĝi',
     login: 'Ensaluti',
     sign_up: 'Registriĝi',
-    notifications_error: 'Labortablaj avizoj estas nehavebla en via retumilo. Provu Firefox-on aŭ Chrome-on.',
+    notifications_error:
+      'Labortablaj avizoj estas nehavebla en via retumilo. Provu Firefox-on aŭ Chrome-on.',
     unread_messages: 'Nelegitaj Mesaĝoj',
     password: 'Pasvorto',
     verify_password: 'Konfirmu Vian Pasvorton',
@@ -120,9 +121,11 @@ export const eo = {
     show_nsfw: 'Vidigi NSFW-an enhavon',
     sponsors: 'Subtenantoj',
     sponsors_of_lemmy: 'Subtenantoj de Lemmy',
-    sponsor_message: 'Lemmy estas senpaga, <1>liberkoda</1> programaro. Tio signifas ne reklami, pagigi, aŭ riska kapitalo, ĉiam. Viaj donacoj rekte subtenas plentempan evoluon de la projekto. Dankon al tiuj homoj:',
+    sponsor_message:
+      'Lemmy estas senpaga, <1>liberkoda</1> programaro. Tio signifas ne reklami, pagigi, aŭ riska kapitalo, ĉiam. Viaj donacoj rekte subtenas plentempan evoluon de la projekto. Dankon al tiuj homoj:',
     support_on_patreon: 'Subteni per Patreon',
-    general_sponsors:'Ĝeneralaj Subtenantoj estas tiuj ke donacis inter $10 kaj $39 al Lemmy.',
+    general_sponsors:
+      'Ĝeneralaj Subtenantoj estas tiuj ke donacis inter $10 kaj $39 al Lemmy.',
     crypto: 'Crypto',
     bitcoin: 'Bitcoin',
     ethereum: 'Ethereum',
@@ -134,7 +137,8 @@ export const eo = {
     transfer_community: 'transdoni la komunumon',
     transfer_site: 'transdoni la retejon',
     powered_by: 'Konstruis per',
-    landing_0: 'Lemmy estas <1>ligila agregatilo</1> / Reddit anstataŭo ke intenciĝas funkci en la <2>federacio-universo</2>.<3></3>ĝi estas mem-gastigebla, havas nuna-ĝisdatigajn komentarojn, kaj estas malgrandega (<4>~80kB</4>). Federacio en la ActivityPub-an reton estas planizita. <5></5>Estas <6>fruega beta versio</6>, kaj multaj trajtoj estas nune difektaj aŭ mankaj. <7></7>Sugestias novajn trajtojn aŭ raportas cimojn <8>ĉi tie.</8><9></9>Faris per <10>Rust</10>, <11>Actix</11>, <12>Inferno</12>, <13>Typescript</13>.',
+    landing_0:
+      'Lemmy estas <1>ligila agregatilo</1> / Reddit anstataŭo ke intenciĝas funkci en la <2>federacio-universo</2>.<3></3>ĝi estas mem-gastigebla, havas nuna-ĝisdatigajn komentarojn, kaj estas malgrandega (<4>~80kB</4>). Federacio en la ActivityPub-an reton estas planizita. <5></5>Estas <6>fruega beta versio</6>, kaj multaj trajtoj estas nune difektaj aŭ mankaj. <7></7>Sugestias novajn trajtojn aŭ raportas cimojn <8>ĉi tie.</8><9></9>Faris per <10>Rust</10>, <11>Actix</11>, <12>Inferno</12>, <13>Typescript</13>.',
     not_logged_in: 'Ne estas ensalutinta.',
     community_ban: 'Vi estas forbarita de la komunumo.',
     site_ban: 'Vi estas forbarita de la retejo',
@@ -161,7 +165,8 @@ export const eo = {
     not_an_admin: 'Ne estas administranto.',
     site_already_exists: 'Retejo jam ekzistas.',
     couldnt_update_site: 'Ne povis ĝisdatigi la retejon.',
-    couldnt_find_that_username_or_email: 'Ne povis trovi tiun uzantnomon aŭ retadreson.',
+    couldnt_find_that_username_or_email:
+      'Ne povis trovi tiun uzantnomon aŭ retadreson.',
     password_incorrect: 'Pasvorto malĝustas.',
     passwords_dont_match: 'Pasvortoj ne samas.',
     admin_already_created: 'Pardonu, jam estas administranto.',
@@ -169,5 +174,4 @@ export const eo = {
     couldnt_update_user: 'Ne povis ĝisdatigi la uzanton.',
     system_err_login: 'Sistema eraro. Provu elsaluti kaj ensaluti.',
   },
-}
-
+};
index ad1f5d1c597b4d120dcf9b650d5e81f1fd53946d..6e1faefeba081ffd2c8ce06b010045edd640d588 100644 (file)
@@ -5,23 +5,23 @@ export const es = {
     no_posts: 'Sin publicaciones.',
     create_a_post: 'Crear una publicación',
     create_post: 'Crear Publicación',
-    number_of_posts:'{{count}} Publicaciones',
+    number_of_posts: '{{count}} Publicaciones',
     posts: 'Publicaciones',
     related_posts: 'Estas publicaciones podrían estar relacionadas',
     cross_posts: 'Este link también ha sido publicado en:',
     cross_post: 'cross-post',
     comments: 'Comentarios',
-    number_of_comments:'{{count}} Comentarios',
+    number_of_comments: '{{count}} Comentarios',
     remove_comment: 'Remover Comentarios',
     communities: 'Comunidades',
     users: 'Usuarios',
     create_a_community: 'Crear una comunidad',
     create_community: 'Crear Comunidad',
     remove_community: 'Remover Comunidad',
-    subscribed_to_communities:'Suscrito a <1>comunidades</1>',
-    trending_communities:'<1>Comunidades</1> en tendencia',
+    subscribed_to_communities: 'Suscrito a <1>comunidades</1>',
+    trending_communities: '<1>Comunidades</1> en tendencia',
     list_of_communities: 'Lista de comunidades',
-    number_of_communities:'{{count}} Comunidades',
+    number_of_communities: '{{count}} Comunidades',
     community_reqs: 'minúsculas, guión bajo, y sin espacios.',
     edit: 'editar',
     reply: 'responder',
@@ -56,7 +56,8 @@ export const es = {
     delete: 'eliminar',
     deleted: 'eliminado',
     delete_account: 'Eliminar Cuenta',
-    delete_account_confirm: 'Peligro: esta acción eliminará permanentemente tu información. ¿Estás seguro?',
+    delete_account_confirm:
+      'Peligro: esta acción eliminará permanentemente tu información. ¿Estás seguro?',
     restore: 'restaurar',
     ban: 'expulsar',
     ban_from_site: 'expulsar del sitio',
@@ -69,9 +70,9 @@ export const es = {
     creator: 'creador',
     username: 'Nombre de Usuario',
     email_or_username: 'Correo electrónico o Nombre de Usuario',
-    number_of_users:'{{count}} Usuarios',
-    number_of_subscribers:'{{count}} Suscriptores',
-    number_of_points:'{{count}} Puntos',
+    number_of_users: '{{count}} Usuarios',
+    number_of_subscribers: '{{count}} Suscriptores',
+    number_of_points: '{{count}} Puntos',
     number_online: '{{count}} Usaurios En Línea',
     name: 'Nombre',
     title: 'Titulo',
@@ -108,7 +109,8 @@ export const es = {
     login_sign_up: 'Iniciar sesión / Crear cuenta',
     login: 'Iniciar sesión',
     sign_up: 'Crear cuenta',
-    notifications_error: 'Notificaciones de escritorio no disponibles en tu navegador. Prueba Firefox o Chrome.',
+    notifications_error:
+      'Notificaciones de escritorio no disponibles en tu navegador. Prueba Firefox o Chrome.',
     unread_messages: 'Mensajes no leídos',
     password: 'Contraseña',
     verify_password: 'Verificar contraseña',
@@ -134,9 +136,11 @@ export const es = {
     theme: 'Tema',
     sponsors: 'Patrocinadores',
     sponsors_of_lemmy: 'Patrocinadores de Lemmy',
-    sponsor_message: 'Lemmy es software libre y de <1>código abierto</1>, lo que significa que no tendrá publicidades, monetización, ni capitales emprendedores, nunca. Tus donaciones apoyan directamente el desarrollo a tiempo completo del proyecto. Muchas gracias a las siguientes personas:',
+    sponsor_message:
+      'Lemmy es software libre y de <1>código abierto</1>, lo que significa que no tendrá publicidades, monetización, ni capitales emprendedores, nunca. Tus donaciones apoyan directamente el desarrollo a tiempo completo del proyecto. Muchas gracias a las siguientes personas:',
     support_on_patreon: 'Apoyo en Patreon',
-    general_sponsors:'Patrocinadores Generales son aquellos que señaron entre $10 y $39 a Lemmy.',
+    general_sponsors:
+      'Patrocinadores Generales son aquellos que señaron entre $10 y $39 a Lemmy.',
     crypto: 'Crypto',
     bitcoin: 'Bitcoin',
     ethereum: 'Ethereum',
@@ -151,7 +155,8 @@ export const es = {
     yes: 'sí',
     no: 'no',
     powered_by: 'Impulsado por',
-    landing_0: 'Lemmy es un <1>agregador de links</1> / alternativa a reddit, con la intención de funcionar en el <2>fediverso</2>.<3></3>Es alojable por uno mismo (sin necesidad de grandes compañías), tiene actualización en vivo de cadenas de comentarios, y es pequeño (<4>~80kB</4>). Federar con el sistema de redes ActivityPub forma parte de los objetivos del proyecto. <5></5>Esta es una <6>version beta muy prematura</6>, y actualmente muchas de las características están rotas o faltan. <7></7>Sugiere nuevas características o reporta errores <8>aquí</8>.<9></9>Hecho con <10>Rust</10>, <11>Actix</11>, <12>Inferno</12>, <13>Typescript</13>.',
+    landing_0:
+      'Lemmy es un <1>agregador de links</1> / alternativa a reddit, con la intención de funcionar en el <2>fediverso</2>.<3></3>Es alojable por uno mismo (sin necesidad de grandes compañías), tiene actualización en vivo de cadenas de comentarios, y es pequeño (<4>~80kB</4>). Federar con el sistema de redes ActivityPub forma parte de los objetivos del proyecto. <5></5>Esta es una <6>version beta muy prematura</6>, y actualmente muchas de las características están rotas o faltan. <7></7>Sugiere nuevas características o reporta errores <8>aquí</8>.<9></9>Hecho con <10>Rust</10>, <11>Actix</11>, <12>Inferno</12>, <13>Typescript</13>.',
     not_logged_in: 'No has iniciado sesión.',
     community_ban: 'Has sido expulsado de esta comunidad.',
     site_ban: 'Has sido expulsado del sitio',
@@ -165,9 +170,12 @@ export const es = {
     couldnt_find_community: 'No se pudo encontrar la comunidad.',
     couldnt_update_community: 'No se pudo actualizar la comunidad.',
     community_already_exists: 'Esta comunidad ya existe.',
-    community_moderator_already_exists: 'Este moderador de la comunidad ya existe.',
-    community_follower_already_exists: 'Este seguidor de la comunidad ya existe.',
-    community_user_already_banned: 'Este usuario de la comunidad ya fue expulsado.',
+    community_moderator_already_exists:
+      'Este moderador de la comunidad ya existe.',
+    community_follower_already_exists:
+      'Este seguidor de la comunidad ya existe.',
+    community_user_already_banned:
+      'Este usuario de la comunidad ya fue expulsado.',
     couldnt_create_post: 'No se pudo crear la publicación.',
     couldnt_like_post: 'No se pudo gustar la publicación.',
     couldnt_find_post: 'No se pudo encontrar la publicación.',
@@ -178,13 +186,14 @@ export const es = {
     not_an_admin: 'No es un administrador.',
     site_already_exists: 'El sitio ya existe.',
     couldnt_update_site: 'No se pudo actualizar el sitio.',
-    couldnt_find_that_username_or_email: 'No se pudo encontrar ese nombre de usuario o correo electrónico.',
+    couldnt_find_that_username_or_email:
+      'No se pudo encontrar ese nombre de usuario o correo electrónico.',
     password_incorrect: 'Contraseña incorrecta.',
     passwords_dont_match: 'Las contraseñas no coinciden.',
     admin_already_created: 'Lo sentimos, ya hay un adminisitrador.',
     user_already_exists: 'El usuario ya existe.',
     couldnt_update_user: 'No se pudo actualizar el usuario.',
-    system_err_login: 'Error del sistema. Intente cerrar sesión e ingresar de nuevo.',
+    system_err_login:
+      'Error del sistema. Intente cerrar sesión e ingresar de nuevo.',
   },
-}
-
+};
index 7e86bf9336a4a9f7df8e0fbd3259d32c4bcfbee6..580193c91a90f2e2f7b42599e01242cdd971479c 100644 (file)
@@ -5,21 +5,21 @@ export const fr = {
     no_posts: 'Pas de sujets.',
     create_a_post: 'Créer un sujet',
     create_post: 'Créer le sujet',
-    number_of_posts:'{{count}} Sujets',
+    number_of_posts: '{{count}} Sujets',
     posts: 'Sujets',
     related_posts: 'Ces sujets peuvent être corrélés',
     cross_posts: 'Ce sujet a également été posté sur :',
     cross_post: 'crossposter',
     comments: 'Commentaires',
-    number_of_comments:'{{count}} Commentaires',
+    number_of_comments: '{{count}} Commentaires',
     remove_comment: 'Supprimer le commentaire',
     communities: 'Communautés',
     users: 'Utilisateurs',
     create_a_community: 'Créer une communauté',
     create_community: 'Créer la communauté',
     remove_community: 'Supprimer la Communauté',
-    subscribed_to_communities:'Abonné à ces <1>communautés</1>',
-    trending_communities:'<1>Communauté</1> en vogue',
+    subscribed_to_communities: 'Abonné à ces <1>communautés</1>',
+    trending_communities: '<1>Communauté</1> en vogue',
     list_of_communities: 'Liste des communautés',
     number_of_communities: '{{count}} communautés',
     community_reqs: 'en minuscule, sans espace et avec tiret du bas.',
@@ -56,7 +56,8 @@ export const fr = {
     delete: 'supprimer',
     deleted: 'supprimé',
     delete_account: 'Supprimer le compte',
-    delete_account_confirm: 'Attention: cette action supprime toutes vos données de façons permanente. Entrez votre mot de passe pour confirmer.',
+    delete_account_confirm:
+      'Attention: cette action supprime toutes vos données de façons permanente. Entrez votre mot de passe pour confirmer.',
     restore: 'restaurer',
     ban: 'bannir',
     ban_from_site: 'bannir du site',
@@ -67,11 +68,11 @@ export const fr = {
     unsave: 'retirer',
     create: 'créer',
     creator: 'createur',
-    username: 'Nom d\'utilisateur',
-    email_or_username: 'Email ou Nom d\'utilisateur',
-    number_of_users:'{{count}} Utilisateurs',
-    number_of_subscribers:'{{count}} Abonnés',
-    number_of_points:'{{count}} Points',
+    username: "Nom d'utilisateur",
+    email_or_username: "Email ou Nom d'utilisateur",
+    number_of_users: '{{count}} Utilisateurs',
+    number_of_subscribers: '{{count}} Abonnés',
+    number_of_points: '{{count}} Points',
     number_online: '{{count}} Utilisateurs en ligne',
     name: 'Nom',
     title: 'Titre',
@@ -80,7 +81,7 @@ export const fr = {
     both: 'Les deux',
     saved: 'Sauvegardé',
     unsubscribe: 'Se désincrire',
-    subscribe: 'S\'inscrire',
+    subscribe: "S'inscrire",
     subscribed: 'Inscris',
     prev: 'Précédent',
     next: 'Suivant',
@@ -105,10 +106,11 @@ export const fr = {
     overview: 'Général',
     view: 'Voir',
     logout: 'Se déconnecter',
-    login_sign_up: 'Se connecter / S\'inscrire',
+    login_sign_up: "Se connecter / S'inscrire",
     login: 'Se connecter',
-    sign_up: 'S\'inscrire',
-    notifications_error: 'Les notifications de bureau ne sont pas discponibles sur votre navigateur. Essayez Firefox ou Chrome.',
+    sign_up: "S'inscrire",
+    notifications_error:
+      'Les notifications de bureau ne sont pas discponibles sur votre navigateur. Essayez Firefox ou Chrome.',
     unread_messages: 'Messages non-lu',
     password: 'Mot de passe',
     verify_password: 'Vérifiez le mot de passe',
@@ -120,12 +122,12 @@ export const fr = {
     copy_suggested_title: 'Ajouter le titre suggéré: {{title}}',
     community: 'Communauté',
     expand_here: 'Développer ici',
-    subscribe_to_communities: 'S\'abonner à quelques <1>communautés</1>.',
+    subscribe_to_communities: "S'abonner à quelques <1>communautés</1>.",
     chat: 'Chat',
     recent_comments: 'Commentaires récents',
     no_results: 'Pas de résultats.',
     setup: 'Installation',
-    lemmy_instance_setup: 'Installation d\'une instance Lemmy',
+    lemmy_instance_setup: "Installation d'une instance Lemmy",
     setup_admin: 'Créer un administrateur',
     your_site: 'votre site',
     modified: 'modifié',
@@ -134,9 +136,11 @@ export const fr = {
     theme: 'Thème',
     sponsors: 'Sponsors',
     sponsors_of_lemmy: 'Sponsors de Lemmy',
-    sponsor_message: 'Lemmy est gratuit et <1>open-source</1>, c\'est à dire sans publicité et sans monétisation. Pour toujours. Vos dons soutiennent directement le développement du projet. Merci à nos soutiens.',
+    sponsor_message:
+      "Lemmy est gratuit et <1>open-source</1>, c'est à dire sans publicité et sans monétisation. Pour toujours. Vos dons soutiennent directement le développement du projet. Merci à nos soutiens.",
     support_on_patreon: 'Soutenir sur Patreon',
-    general_sponsors:'General Sponsors are those that pledged $10 to $39 to Lemmy.',
+    general_sponsors:
+      'General Sponsors are those that pledged $10 to $39 to Lemmy.',
     crypto: 'Crypto',
     bitcoin: 'Bitcoin',
     ethereum: 'Ethereum',
@@ -151,39 +155,44 @@ export const fr = {
     yes: 'oui',
     no: 'non',
     powered_by: 'Propulsé par',
-    landing_0: 'Lemmy est un <1>aggrégateur de lien</1>, similaire à reddit et conçu pour fonctionner sur le <2>fédiverse</2>.<3></3>Il est auto-hébergeable, se met à jour en direct et est léger (<4>~80kB</4>). La fédération via Activitypub est prévue sur la feuille de route. <5></5>Lemmy est une <6>version beta très précoce</6>, et de nombreuses fonctionnalités sont manquantes ou non fonctionnelles. <7></7>Vous pouvez rapporter des bugs et suggérez de nouvelles fonctionnalités <8>ici.</8><9></9>Crée avec <10>Rust</10>, <11>Actix</11>, <12>Inferno</12>, <13>Typescript</13>.',
-    not_logged_in: 'Vous n\'êtes pas connecté.',
+    landing_0:
+      'Lemmy est un <1>aggrégateur de lien</1>, similaire à reddit et conçu pour fonctionner sur le <2>fédiverse</2>.<3></3>Il est auto-hébergeable, se met à jour en direct et est léger (<4>~80kB</4>). La fédération via Activitypub est prévue sur la feuille de route. <5></5>Lemmy est une <6>version beta très précoce</6>, et de nombreuses fonctionnalités sont manquantes ou non fonctionnelles. <7></7>Vous pouvez rapporter des bugs et suggérez de nouvelles fonctionnalités <8>ici.</8><9></9>Crée avec <10>Rust</10>, <11>Actix</11>, <12>Inferno</12>, <13>Typescript</13>.',
+    not_logged_in: "Vous n'êtes pas connecté.",
     community_ban: 'Vous avez été banni de cette communauté.',
     site_ban: 'Vous avez été banni du site',
     couldnt_create_comment: 'Impossible de poster le commentaire.',
-    couldnt_like_comment: 'Impossible d\'aimer le commentaire.',
+    couldnt_like_comment: "Impossible d'aimer le commentaire.",
     couldnt_update_comment: 'Impossible de mettre à jour le commentaire.',
     couldnt_save_comment: 'Impossible de sauvegarder le commentaire.',
-    no_comment_edit_allowed: 'Vous n\'êtes pas autorisé à éditer ce commentaire.',
-    no_post_edit_allowed: 'ous n\'êtes pas autorisé à éditer sujet.',
-    no_community_edit_allowed: 'ous n\'êtes pas autorisé à éditer cette communauté.',
+    no_comment_edit_allowed:
+      "Vous n'êtes pas autorisé à éditer ce commentaire.",
+    no_post_edit_allowed: "ous n'êtes pas autorisé à éditer sujet.",
+    no_community_edit_allowed:
+      "ous n'êtes pas autorisé à éditer cette communauté.",
     couldnt_find_community: 'Impossible de trouver cette communauté.',
-    couldnt_update_community: 'Impossible d\'éditer cette communauté.',
+    couldnt_update_community: "Impossible d'éditer cette communauté.",
     community_already_exists: 'Cette communauté existe déjà.',
     community_moderator_already_exists: 'Ce membre est déjà modérateur.',
     community_follower_already_exists: 'Ce membre est déjà abonné.',
     community_user_already_banned: 'Ce membre est déjà banni.',
     couldnt_create_post: 'Impossible dae créer le sujet.',
-    couldnt_like_post: 'Impossible d\'aimer le sujet.',
+    couldnt_like_post: "Impossible d'aimer le sujet.",
     couldnt_find_post: 'Impossible de trouver le sujet.',
-    couldnt_get_posts: 'Impossible d\'obtenir les sujets',
+    couldnt_get_posts: "Impossible d'obtenir les sujets",
     couldnt_update_post: 'Impossible de mettre à jour le sujet',
     couldnt_save_post: 'Impossible de sauvegarder le sujet.',
-    no_slurs: 'Pas d\'insultes.',
+    no_slurs: "Pas d'insultes.",
     not_an_admin: 'Pas administrateur.',
     site_already_exists: 'Le site existe déjà.',
     couldnt_update_site: 'Impossible de mettre à jour le site.',
-    couldnt_find_that_username_or_email: 'Impossible de trouver cet utilisateur ou cet email.',
+    couldnt_find_that_username_or_email:
+      'Impossible de trouver cet utilisateur ou cet email.',
     password_incorrect: 'Mot de passe incorrect.',
     passwords_dont_match: 'Les mots de passes ne correspondent pas..',
     admin_already_created: 'Désolé, il y a déjà un admin.',
-    user_already_exists: 'L\'utilisateur existe déjà.',
-    couldnt_update_user: 'Impossible de mettre à jour l\'utilisateur.',
-    system_err_login: 'Erreur système. Essayez de vous déconneter puis de vous reconnecter.',
+    user_already_exists: "L'utilisateur existe déjà.",
+    couldnt_update_user: "Impossible de mettre à jour l'utilisateur.",
+    system_err_login:
+      'Erreur système. Essayez de vous déconneter puis de vous reconnecter.',
   },
-}
+};
index 33fc24eb0e43c78e36d9b3ef9d3dde376b513b5b..e89178743fbdbf62d0ef34a42c969b360bf2e267 100644 (file)
@@ -5,23 +5,23 @@ export const nl = {
     no_posts: 'Geen posts.',
     create_a_post: 'Plaats een post',
     create_post: 'Plaats post',
-    number_of_posts:'{{count}} posts',
+    number_of_posts: '{{count}} posts',
     posts: 'posts',
     related_posts: 'Deze posts kunnen gerelateerd zijn',
     cross_posts: 'Deze link is ook geplaatst in:',
     cross_post: 'cross-post',
     comments: 'Reacties',
-    number_of_comments:'{{count}} reacties',
+    number_of_comments: '{{count}} reacties',
     remove_comment: 'Verwijder reactie',
     communities: 'Communities',
     users: 'Gebruikers',
     create_a_community: 'Maak een community',
     create_community: 'Maak community',
     remove_community: 'Verwijder community',
-    subscribed_to_communities:'Geabonneerd op <1>communities</1>',
-    trending_communities:'Populaire <1>communities</1>',
+    subscribed_to_communities: 'Geabonneerd op <1>communities</1>',
+    trending_communities: 'Populaire <1>communities</1>',
     list_of_communities: 'Lijst van communities',
-    number_of_communities:'{{count}} communities',
+    number_of_communities: '{{count}} communities',
     community_reqs: 'kleine letters, onderstrepingsteken en geen spaties',
     edit: 'bewerk',
     reply: 'reageer',
@@ -58,9 +58,9 @@ export const nl = {
     create: 'maak',
     username: 'Gebruikersnaam',
     email_or_username: 'E-mail of gebruikersnaam',
-    number_of_users:'{{count}} gebruikers',
-    number_of_subscribers:'{{count}} abonnees',
-    number_of_points:'{{count}} punten',
+    number_of_users: '{{count}} gebruikers',
+    number_of_subscribers: '{{count}} abonnees',
+    number_of_points: '{{count}} punten',
     name: 'Naam',
     title: 'Titel',
     category: 'Categorie',
@@ -96,7 +96,8 @@ export const nl = {
     login_sign_up: 'Log in / Aanmelden',
     login: 'Log in',
     sign_up: 'Aanmelden',
-    notifications_error: 'Bureabladberichten niet beschikbaar in je browser. Probeer Firefox of Chrome.',
+    notifications_error:
+      'Bureabladberichten niet beschikbaar in je browser. Probeer Firefox of Chrome.',
     unread_messages: 'Ongelezen berichten',
     password: 'Wachtwoord',
     verify_password: 'Herhaal wachtwoord',
@@ -121,9 +122,11 @@ export const nl = {
     show_nsfw: 'Laat NSFW-inhoud zien',
     sponsors: 'Sponsoren',
     sponsors_of_lemmy: 'Sponsoren van Lemmy',
-    sponsor_message: 'Lemmy is vrije, <1>open-source</1> software, dus zonder reclame, winstoogmerk en durfkapitaal, punt. Jouw donaties gaan direct naar de full-time-ontwikkeling van het project. Met veel dank aan de volgende mensen:',
+    sponsor_message:
+      'Lemmy is vrije, <1>open-source</1> software, dus zonder reclame, winstoogmerk en durfkapitaal, punt. Jouw donaties gaan direct naar de full-time-ontwikkeling van het project. Met veel dank aan de volgende mensen:',
     support_on_patreon: 'Ondersteun op Patreon',
-    general_sponsors:'Algemene sponsors zijn sponsors die tussen de $10 en $39 hebben gegeven aan Lemmy.',
+    general_sponsors:
+      'Algemene sponsors zijn sponsors die tussen de $10 en $39 hebben gegeven aan Lemmy.',
     crypto: 'Cryptovaluta',
     bitcoin: 'Bitcoin',
     ethereum: 'Ethereum',
@@ -138,7 +141,8 @@ export const nl = {
     yes: 'ja',
     no: 'nee',
     powered_by: 'Mogelijk gemaakt door',
-    landing_0: 'Lemmy is een <1>linkverzameler</1> / reddit-alternatief, bedoeld om in de <2>fediverse</2> te werken.<3></3>Lemmy kan door om het even wie gehost worden, heeft live-bijgewerkte reacties en is superklein (<4>ca. 80 kB</4>). Federatie in hte ActivityPub-netwerk is gepland. <5></5>Dit is een <6>erg vroege bèta-versie</6>, en een hoop functies zijn stuk of afwezig. <7></7>Stel nieuwe functies voor of meldt fouten <8>hier</8>.<9></9>Gemaakt met <10>Rust</10>, <11>Actix</11>, <12>Inferno</12> en <13>Typescript</13>.',
+    landing_0:
+      'Lemmy is een <1>linkverzameler</1> / reddit-alternatief, bedoeld om in de <2>fediverse</2> te werken.<3></3>Lemmy kan door om het even wie gehost worden, heeft live-bijgewerkte reacties en is superklein (<4>ca. 80 kB</4>). Federatie in hte ActivityPub-netwerk is gepland. <5></5>Dit is een <6>erg vroege bèta-versie</6>, en een hoop functies zijn stuk of afwezig. <7></7>Stel nieuwe functies voor of meldt fouten <8>hier</8>.<9></9>Gemaakt met <10>Rust</10>, <11>Actix</11>, <12>Inferno</12> en <13>Typescript</13>.',
     not_logged_in: 'Niet ingelogd.',
     community_ban: 'Je bent verbannen uit deze community.',
     site_ban: 'Je bent verbannen van deze site.',
@@ -165,12 +169,14 @@ export const nl = {
     not_an_admin: 'Niet een beheerder.',
     site_already_exists: 'Site bestaat al.',
     couldnt_update_site: 'Kon site niet bijwerken.',
-    couldnt_find_that_username_or_email: 'Kon gebruikersnaam of e-mailadres niet vinden.',
+    couldnt_find_that_username_or_email:
+      'Kon gebruikersnaam of e-mailadres niet vinden.',
     password_incorrect: 'Wachtwoord incorrect.',
     passwords_dont_match: 'Wachtwoorden zijn niet gelijk.',
     admin_already_created: 'Sorry, er is al een beheerder.',
     user_already_exists: 'Gebruiker bestaat al.',
     couldnt_update_user: 'Kon gebruiker niet bijwerken.',
-    system_err_login: 'Systeemfout. Probeer uit te loggen en weer in te loggen.',
+    system_err_login:
+      'Systeemfout. Probeer uit te loggen en weer in te loggen.',
   },
-}
+};
index 71e2126422ebd26708cdfa8457458baa39237542..e8ae736190057b5ed9b52c75b460261b0bb2b388 100644 (file)
@@ -5,19 +5,19 @@ export const ru = {
     no_posts: 'Нет записей.',
     create_a_post: 'Создать запись',
     create_post: 'Создать запись',
-    number_of_posts:'{{count}} записей',
+    number_of_posts: '{{count}} записей',
     posts: 'Записи',
     related_posts: 'Эти записи могут быть связаны',
     comments: 'Комментарии',
-    number_of_comments:'{{count}} комментариев',
+    number_of_comments: '{{count}} комментариев',
     remove_comment: 'Удалить комментарий',
     communities: 'Сообщества',
     users: 'Пользователи',
     create_a_community: 'Создать сообщество',
     create_community: 'Создать сообщество',
     remove_community: 'Удалить сообщество',
-    subscribed_to_communities:'Подписаны на <1>сообщества</1>',
-    trending_communities:'<1>Сообщества</1> в тренде',
+    subscribed_to_communities: 'Подписаны на <1>сообщества</1>',
+    trending_communities: '<1>Сообщества</1> в тренде',
     list_of_communities: 'Список сообществ',
     community_reqs: 'строчными буквами, подчеркиваниями и без пробелов.',
     edit: 'редактировать',
@@ -55,9 +55,9 @@ export const ru = {
     create: 'создать',
     username: 'Имя пользователя',
     email_or_username: 'Электронная почта или имя пользователя',
-    number_of_users:'{{count}} пользователей',
-    number_of_subscribers:'{{count}} подписчиков',
-    number_of_points:'{{count}} баллов',
+    number_of_users: '{{count}} пользователей',
+    number_of_subscribers: '{{count}} подписчиков',
+    number_of_points: '{{count}} баллов',
     name: 'Имя',
     title: 'Название',
     category: 'Категория',
@@ -93,7 +93,8 @@ export const ru = {
     login_sign_up: 'Войти / Регистрация',
     login: 'Авторизация',
     sign_up: 'Регистрация',
-    notifications_error: 'Уведомления на рабочем столе недоступны в вашем браузере. Попробуйте Firefox или Chrome.',
+    notifications_error:
+      'Уведомления на рабочем столе недоступны в вашем браузере. Попробуйте Firefox или Chrome.',
     unread_messages: 'Непрочитанные сообщения',
     password: 'Пароль',
     verify_password: 'Повторите пароль',
@@ -117,16 +118,19 @@ export const ru = {
     show_nsfw: 'Показывать NSFW-контент',
     sponsors: 'Спонсоры',
     sponsors_of_lemmy: 'Спонсоры Lemmy',
-    sponsor_message: 'Lemmy это бесплатное, <1>открытое</1> программное обеспечение, что означает отсутствие рекламы, монетизации или венчурного капитала, никогда. Ваши пожертвования напрямую поддерживают развитие проекта. Спасибо нижеуказанным людям:',
+    sponsor_message:
+      'Lemmy это бесплатное, <1>открытое</1> программное обеспечение, что означает отсутствие рекламы, монетизации или венчурного капитала, никогда. Ваши пожертвования напрямую поддерживают развитие проекта. Спасибо нижеуказанным людям:',
     support_on_patreon: 'Поддержать на Patreon',
-    general_sponsors:'Генеральные спонсоры - это те, кто пообещал Lemmy от $10 до $39.',
+    general_sponsors:
+      'Генеральные спонсоры - это те, кто пообещал Lemmy от $10 до $39.',
     crypto: 'Крипто',
     bitcoin: 'Bitcoin',
     ethereum: 'Ethereum',
     code: 'Код',
     joined: 'Присоединился',
     powered_by: 'Работает на',
-    landing_0: 'Lemmy - это <1>агрегатор ссылок</1> / альтернатива reddit, предназначенный для работы в <2>федиверсе</2>.<3></3>Это самодостаточная система, с обновляемыми комментариями, и эта система крошечная (<4>~80 Кб</4>). Федерация в сети ActivityPub находится в разработке. <5></5>Это <6>очень ранняя бета-версия</6>, и многие функции в настоящее время сломаны или отсутствуют. <7></7>Предлагать новые функции или сообщать об ошибках можно <8>здесь.</8><9></9>Сделано на <10>Rust</10>, <11>Actix</11>, <12>Inferno</12>, <13>Typescript</13>.',
+    landing_0:
+      'Lemmy - это <1>агрегатор ссылок</1> / альтернатива reddit, предназначенный для работы в <2>федиверсе</2>.<3></3>Это самодостаточная система, с обновляемыми комментариями, и эта система крошечная (<4>~80 Кб</4>). Федерация в сети ActivityPub находится в разработке. <5></5>Это <6>очень ранняя бета-версия</6>, и многие функции в настоящее время сломаны или отсутствуют. <7></7>Предлагать новые функции или сообщать об ошибках можно <8>здесь.</8><9></9>Сделано на <10>Rust</10>, <11>Actix</11>, <12>Inferno</12>, <13>Typescript</13>.',
     not_logged_in: 'Не авторизованы.',
     community_ban: 'Вы были заблокированы на данном сообществе.',
     site_ban: 'Вы были заблокированы на данном сайте',
@@ -153,13 +157,14 @@ export const ru = {
     not_an_admin: 'Не администратор.',
     site_already_exists: 'Сайт уже существует.',
     couldnt_update_site: 'Не получилось обновить сайт.',
-    couldnt_find_that_username_or_email: 'Не получилось найти данное имя пользователя или электронную почту.',
+    couldnt_find_that_username_or_email:
+      'Не получилось найти данное имя пользователя или электронную почту.',
     password_incorrect: 'Неверный пароль.',
     passwords_dont_match: 'Пароли не совпадают.',
     admin_already_created: 'Извините, уже есть администратор.',
     user_already_exists: 'Пользователь уже существует.',
     couldnt_update_user: 'Не получилось обновить пользователя.',
-    system_err_login: 'Системная ошибка. Попробуйте выйти из системы и вернуться обратно.',
+    system_err_login:
+      'Системная ошибка. Попробуйте выйти из системы и вернуться обратно.',
   },
-}
-
+};
index 4bb25f1a01f40c32bd372a6423174a8acd7ded21..f0a4d79e7869cc0493e71e6dbd7f73c1a0df4d14 100644 (file)
@@ -56,7 +56,8 @@ export const sv = {
     delete: 'radera',
     deleted: 'raderad',
     delete_account: 'Ta bort konto',
-    delete_account_confirm: 'Varning: den här åtgärden kommer radera alla dina data permanent. Är du säker?',
+    delete_account_confirm:
+      'Varning: den här åtgärden kommer radera alla dina data permanent. Är du säker?',
     restore: 'återställ',
     ban: 'blockera',
     ban_from_site: 'blockera från webbplats',
@@ -108,7 +109,8 @@ export const sv = {
     login_sign_up: 'Logga in eller skapa konto',
     login: 'Logga in',
     sign_up: 'Skapa konto',
-    notifications_error: 'Din webbläsare har inte stöd för skrivbordsaviseringar. Testa Firefox eller Chrome.',
+    notifications_error:
+      'Din webbläsare har inte stöd för skrivbordsaviseringar. Testa Firefox eller Chrome.',
     unread_messages: 'Olästa meddelanden',
     password: 'Lösenord',
     verify_password: 'Bekräfta lösenord',
@@ -134,9 +136,11 @@ export const sv = {
     theme: 'Utseende',
     sponsors: 'Sponsorer',
     sponsors_of_lemmy: 'Lemmys sponsorer',
-    sponsor_message: 'Lemmy är fri mjukvara med <1>öppen källkod</1>, vilket innebär att ingen reklam, vinstindrivning eller venturekapital förekommer, någonsin. Dina donationer går direkt till att stöda utvecklingen av projektet. Stort tack till följande personer:',
+    sponsor_message:
+      'Lemmy är fri mjukvara med <1>öppen källkod</1>, vilket innebär att ingen reklam, vinstindrivning eller venturekapital förekommer, någonsin. Dina donationer går direkt till att stöda utvecklingen av projektet. Stort tack till följande personer:',
     support_on_patreon: 'Stöd på Patreon',
-    general_sponsors: 'Allmänna sponsorer är dem som givit mellan 10 och 39\u00a0dollar till Lemmy.',
+    general_sponsors:
+      'Allmänna sponsorer är dem som givit mellan 10 och 39\u00a0dollar till Lemmy.',
     crypto: 'Kryptovaluta',
     bitcoin: 'Bitcoin',
     ethereum: 'Ethereum',
@@ -151,7 +155,8 @@ export const sv = {
     yes: 'ja',
     no: 'nej',
     powered_by: 'Drivs av',
-    landing_0: 'Lemmy är en <1>länksamlare</1> och alternativ till reddit, ämnad att fungera i <2>Fediversumet</2>.<3></3>Lemmy kan drivas av vem som helst, har kommentarstrådar som updateras i realid och är mycket liten (<4>ca 80\u00a0kB</4>). Federering med ActivityPub-nätverket är planerat. <5></5>Detta är en <6>väldigt tidig betaversion</6> och många funktioner saknas därför eller är trasiga.<7></7>Föreslå nya funktioner eller anmäl buggar <8>här</8>.<9></9>Skapad i <10>Rust</10>, <11>Actix</11>, <12>Inferno</12> och <13>Typescript</13>.',
+    landing_0:
+      'Lemmy är en <1>länksamlare</1> och alternativ till reddit, ämnad att fungera i <2>Fediversumet</2>.<3></3>Lemmy kan drivas av vem som helst, har kommentarstrådar som updateras i realid och är mycket liten (<4>ca 80\u00a0kB</4>). Federering med ActivityPub-nätverket är planerat. <5></5>Detta är en <6>väldigt tidig betaversion</6> och många funktioner saknas därför eller är trasiga.<7></7>Föreslå nya funktioner eller anmäl buggar <8>här</8>.<9></9>Skapad i <10>Rust</10>, <11>Actix</11>, <12>Inferno</12> och <13>Typescript</13>.',
     not_logged_in: 'Inte inloggad.',
     community_ban: 'Du har blockerats från den här gemenskapen.',
     site_ban: 'Du har blockerats från webbplatsen.',
@@ -178,7 +183,8 @@ export const sv = {
     not_an_admin: 'Inte en administratör.',
     site_already_exists: 'Webbplatsen finns redan.',
     couldnt_update_site: 'Kunde inte uppdatera webbplats.',
-    couldnt_find_that_username_or_email: 'Kunde inte hitta det användarnamnet eller e-postadressen.',
+    couldnt_find_that_username_or_email:
+      'Kunde inte hitta det användarnamnet eller e-postadressen.',
     password_incorrect: 'Ogiltigt lösenord.',
     passwords_dont_match: 'Lösenorden stämmer inte överens.',
     admin_already_created: 'Beklagar, men det finns redan en administratör.',
@@ -186,4 +192,4 @@ export const sv = {
     couldnt_update_user: 'Kunde inte uppdatera användare.',
     system_err_login: 'Systemfel. Försök att logga ut och sedan in igen.',
   },
-}
+};
index 2a40767859b719a4b0bdfb78e1e6f1fa92086469..7beaf83ec71e5b7e36dd5563658a05338725c943 100644 (file)
@@ -5,18 +5,18 @@ export const zh = {
     no_posts: '没有帖子.',
     create_a_post: '创建新帖子',
     create_post: '创建帖子',
-    number_of_posts:'{{count}} 帖子',
+    number_of_posts: '{{count}} 帖子',
     posts: '帖子',
     related_posts: '相关的帖子',
     comments: '评论',
-    number_of_comments:'{{count}} 评论',
+    number_of_comments: '{{count}} 评论',
     remove_comment: '移除评论',
     communities: '节点',
     create_a_community: '创建新节点',
     create_community: '创建节点',
     remove_community: '移除节点',
-    subscribed_to_communities:'订阅新 <1>节点</1>',
-    trending_communities:'<1>节点</1>趋势',
+    subscribed_to_communities: '订阅新 <1>节点</1>',
+    trending_communities: '<1>节点</1>趋势',
     list_of_communities: '节点列表',
     community_reqs: '包含小写与下划线且没有空格的字符串.',
     edit: '编辑',
@@ -53,9 +53,9 @@ export const zh = {
     create: '创建',
     username: '用户名',
     email_or_username: '邮箱或用户名',
-    number_of_users:'{{count}} 用户',
-    number_of_subscribers:'{{count}} 订阅',
-    number_of_points:'{{count}} 分',
+    number_of_users: '{{count}} 用户',
+    number_of_subscribers: '{{count}} 订阅',
+    number_of_points: '{{count}} 分',
     name: '名字',
     title: '标题',
     category: '分类',
@@ -113,16 +113,19 @@ export const zh = {
     modified: '修改',
     sponsors: 'Sponsors',
     sponsors_of_lemmy: 'Sponsors of Lemmy',
-    sponsor_message: 'Lemmy is free, <1>open-source</1> software, meaning no advertising, monetizing, or venture capital, ever. Your donations directly support full-time development of the project. Thank you to the following people:',
+    sponsor_message:
+      'Lemmy is free, <1>open-source</1> software, meaning no advertising, monetizing, or venture capital, ever. Your donations directly support full-time development of the project. Thank you to the following people:',
     support_on_patreon: 'Support on Patreon',
-    general_sponsors:'General Sponsors are those that pledged $10 to $39 to Lemmy.',
+    general_sponsors:
+      'General Sponsors are those that pledged $10 to $39 to Lemmy.',
     crypto: '加密',
     bitcoin: '比特币',
     ethereum: '以太币',
     code: '代码',
     joined: '已加入',
     powered_by: '保留所有权利',
-    landing_0: 'Lemmy is a <1>link aggregator</1> / reddit alternative, intended to work in the <2>fediverse</2>.<3></3>It\'s self-hostable, has live-updating comment threads, and is tiny (<4>~80kB</4>). Federation into the ActivityPub network is on the roadmap. <5></5>This is a <6>very early beta version</6>, and a lot of features are currently broken or missing. <7></7>Suggest new features or report bugs <8>here.</8><9></9>Made with <10>Rust</10>, <11>Actix</11>, <12>Inferno</12>, <13>Typescript</13>.',
+    landing_0:
+      "Lemmy is a <1>link aggregator</1> / reddit alternative, intended to work in the <2>fediverse</2>.<3></3>It's self-hostable, has live-updating comment threads, and is tiny (<4>~80kB</4>). Federation into the ActivityPub network is on the roadmap. <5></5>This is a <6>very early beta version</6>, and a lot of features are currently broken or missing. <7></7>Suggest new features or report bugs <8>here.</8><9></9>Made with <10>Rust</10>, <11>Actix</11>, <12>Inferno</12>, <13>Typescript</13>.",
     not_logged_in: '未登录.',
     community_ban: '你被此节点禁止.',
     site_ban: '你被此站点禁止',
@@ -157,5 +160,4 @@ export const zh = {
     couldnt_update_user: '不可以更新用户.',
     system_err_login: '系统错误. 尝试注销再登录',
   },
-}
-
+};
index 350a8205ad7030b5b1b6dc52afbee72dd19d0643..ce221e325eb53a9563d24fa0fc85ee7e4105fe05 100644 (file)
@@ -7,7 +7,14 @@ import 'moment/locale/sv';
 import 'moment/locale/ru';
 import 'moment/locale/nl';
 
-import { UserOperation, Comment, User, SortType, ListingType, SearchType } from './interfaces';
+import {
+  UserOperation,
+  Comment,
+  User,
+  SortType,
+  ListingType,
+  SearchType,
+} from './interfaces';
 import * as markdown_it from 'markdown-it';
 import * as markdownitEmoji from 'markdown-it-emoji/light';
 import * as markdown_it_container from 'markdown-it-container';
@@ -17,11 +24,16 @@ import * as emojiShortName from 'emoji-short-name';
 export const repoUrl = 'https://github.com/dessalines/lemmy';
 export const markdownHelpUrl = 'https://commonmark.org/help/';
 
-export const postRefetchSeconds: number = 60*1000;
+export const postRefetchSeconds: number = 60 * 1000;
 export const fetchLimit: number = 20;
 export const mentionDropdownFetchLimit = 6;
 
-export function randomStr() {return Math.random().toString(36).replace(/[^a-z]+/g, '').substr(2, 10)}
+export function randomStr() {
+  return Math.random()
+    .toString(36)
+    .replace(/[^a-z]+/g, '')
+    .substr(2, 10);
+}
 
 export function msgOp(msg: any): UserOperation {
   let opStr: string = msg.op;
@@ -31,27 +43,30 @@ export function msgOp(msg: any): UserOperation {
 export const md = new markdown_it({
   html: false,
   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';
-    }
-  }
-}).use(markdownitEmoji, {
-  defs: objectFlip(emojiShortName)
-});
+  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';
+      }
+    },
+  })
+  .use(markdownitEmoji, {
+    defs: objectFlip(emojiShortName),
+  });
 
 md.renderer.rules.emoji = function(token, idx) {
   return twemoji.parse(token[idx].content);
@@ -64,7 +79,9 @@ export function hotRank(comment: Comment): number {
   let now: Date = new Date();
   let hoursElapsed: number = (now.getTime() - date.getTime()) / 36e5;
 
-  let rank = (10000 *  Math.log10(Math.max(1, 3 + comment.score))) / Math.pow(hoursElapsed + 2, 1.8);
+  let rank =
+    (10000 * Math.log10(Math.max(1, 3 + comment.score))) /
+    Math.pow(hoursElapsed + 2, 1.8);
 
   // console.log(`Comment: ${comment.content}\nRank: ${rank}\nScore: ${comment.score}\nHours: ${hoursElapsed}`);
 
@@ -72,26 +89,36 @@ export function hotRank(comment: Comment): number {
 }
 
 export function mdToHtml(text: string) {
-  return {__html: md.render(text)};
+  return { __html: md.render(text) };
 }
 
-export function getUnixTime(text: string): number { 
-  return text ? new Date(text).getTime()/1000 : undefined;
+export function getUnixTime(text: string): number {
+  return text ? new Date(text).getTime() / 1000 : undefined;
 }
 
-export function addTypeInfo<T>(arr: Array<T>, name: string): Array<{type_: string, data: T}> {  
-  return arr.map(e => {return {type_: name, data: e}});
+export function addTypeInfo<T>(
+  arr: Array<T>,
+  name: string
+): Array<{ type_: string; data: T }> {
+  return arr.map(e => {
+    return { type_: name, data: e };
+  });
 }
 
-export function canMod(user: User, modIds: Array<number>, creator_id: number, onSelf: boolean = false): boolean {
+export function canMod(
+  user: User,
+  modIds: Array<number>,
+  creator_id: number,
+  onSelf: boolean = false
+): boolean {
   // You can do moderator actions only on the mods added after you.
   if (user) {
     let yourIndex = modIds.findIndex(id => id == user.id);
     if (yourIndex == -1) {
       return false;
-    } else { 
+    } else {
       // onSelf +1 on mod actions not for yourself, IE ban, remove, etc
-      modIds = modIds.slice(0, yourIndex+(onSelf ? 0 : 1)); 
+      modIds = modIds.slice(0, yourIndex + (onSelf ? 0 : 1));
       return !modIds.includes(creator_id);
     }
   } else {
@@ -103,8 +130,9 @@ export function isMod(modIds: Array<number>, creator_id: number): boolean {
   return modIds.includes(creator_id);
 }
 
-
-var imageRegex = new RegExp(`(http)?s?:?(\/\/[^"']*\.(?:png|jpg|jpeg|gif|png|svg))`);
+var imageRegex = new RegExp(
+  `(http)?s?:?(\/\/[^"']*\.(?:png|jpg|jpeg|gif|png|svg))`
+);
 var videoRegex = new RegExp(`(http)?s?:?(\/\/[^"']*\.(?:mp4))`);
 
 export function isImage(url: string) {
@@ -127,7 +155,6 @@ export function capitalizeFirstLetter(str: string): string {
   return str.charAt(0).toUpperCase() + str.slice(1);
 }
 
-
 export function routeSortTypeToEnum(sort: string): SortType {
   if (sort == 'new') {
     return SortType.New;
@@ -158,7 +185,11 @@ export async function getPageTitle(url: string) {
   return data;
 }
 
-export function debounce(func: any, wait: number = 500, immediate: boolean = false) {
+export function debounce(
+  func: any,
+  wait: number = 500,
+  immediate: boolean = false
+) {
   // 'private' variable for instance
   // The returned function will be able to reference this due to closure.
   // Each call to the returned function will share this common timer.
@@ -168,46 +199,45 @@ export function debounce(func: any, wait: number = 500, immediate: boolean = fal
   return function() {
     // reference the context and args for the setTimeout function
     var context = this,
-    args = arguments;
-
-  // Should the function be called now? If immediate is true
-  //   and not already in a timeout then the answer is: Yes
-  var callNow = immediate && !timeout;
-
-  // This is the basic debounce behaviour where you can call this 
-  //   function several times, but it will only execute once 
-  //   [before or after imposing a delay]. 
-  //   Each time the returned function is called, the timer starts over.
-  clearTimeout(timeout);
-
-  // Set the new timeout
-  timeout = setTimeout(function() {
-
-    // Inside the timeout function, clear the timeout variable
-    // which will let the next execution run when in 'immediate' mode
-    timeout = null;
-
-    // Check if the function already ran with the immediate flag
-    if (!immediate) {
-      // Call the original function with apply
-      // apply lets you define the 'this' object as well as the arguments 
-      //    (both captured before setTimeout)
-      func.apply(context, args);
-    }
-  }, wait);
-
-  // Immediate mode and no wait timer? Execute the function..
-  if (callNow) func.apply(context, args);
-  }
+      args = arguments;
+
+    // Should the function be called now? If immediate is true
+    //   and not already in a timeout then the answer is: Yes
+    var callNow = immediate && !timeout;
+
+    // This is the basic debounce behaviour where you can call this
+    //   function several times, but it will only execute once
+    //   [before or after imposing a delay].
+    //   Each time the returned function is called, the timer starts over.
+    clearTimeout(timeout);
+
+    // Set the new timeout
+    timeout = setTimeout(function() {
+      // Inside the timeout function, clear the timeout variable
+      // which will let the next execution run when in 'immediate' mode
+      timeout = null;
+
+      // Check if the function already ran with the immediate flag
+      if (!immediate) {
+        // Call the original function with apply
+        // apply lets you define the 'this' object as well as the arguments
+        //    (both captured before setTimeout)
+        func.apply(context, args);
+      }
+    }, wait);
+
+    // Immediate mode and no wait timer? Execute the function..
+    if (callNow) func.apply(context, args);
+  };
 }
 
 export function getLanguage(): string {
-  return (navigator.language || navigator.userLanguage);
+  return navigator.language || navigator.userLanguage;
 }
 
 export function objectFlip(obj: any) {
   const ret = {};
-  Object.keys(obj).forEach((key) => {
+  Object.keys(obj).forEach(key => {
     ret[obj[key]] = key;
   });
   return ret;
@@ -237,16 +267,24 @@ export function getMomentLanguage(): string {
   return lang;
 }
 
-export const themes = ['litera', 'minty', 'solar', 'united', 'cyborg','darkly', 'journal', 'sketchy'];
+export const themes = [
+  'litera',
+  'minty',
+  'solar',
+  'united',
+  'cyborg',
+  'darkly',
+  'journal',
+  'sketchy',
+];
 
 export function setTheme(theme: string = 'darkly') {
-  for (var i=0; i < themes.length; i++) {
-
+  for (var i = 0; i < themes.length; i++) {
     let styleSheet = document.getElementById(themes[i]);
     if (themes[i] == theme) {
-      styleSheet.removeAttribute("disabled");
+      styleSheet.removeAttribute('disabled');
     } else {
-      styleSheet.setAttribute("disabled", "disabled");
-    }      
+      styleSheet.setAttribute('disabled', 'disabled');
+    }
   }
 }
index 8590a5c2251e0ab7ddc748fba4bfd13bfe0b9662..7e9bb86b1176f240331dae45b60db46de098fb23 100644 (file)
@@ -1 +1 @@
-export let version: string = "v0.3.0.4-0-gce10a34";
\ No newline at end of file
+export let version: string = 'v0.3.0.4-0-gce10a34';