Browse Source

Get linkEvent proxy working

main
GreatBearShark 2 years ago
parent
commit
6aab9a58e9
  1. 2
      .gitignore
  2. 14
      package.json
  3. 8
      src/components/about.tsx
  4. 37
      src/components/admin-settings.tsx
  5. 4
      src/components/cake-day.tsx
  6. 18
      src/components/comment-form.tsx
  7. 139
      src/components/comment-node.tsx
  8. 2
      src/components/comment-nodes.tsx
  9. 43
      src/components/communities.tsx
  10. 37
      src/components/community-dropdown.tsx
  11. 99
      src/components/community-form.tsx
  12. 4
      src/components/community-link.tsx
  13. 31
      src/components/community.tsx
  14. 8
      src/components/create-community.tsx
  15. 8
      src/components/create-post.tsx
  16. 8
      src/components/create-private-message.tsx
  17. 7
      src/components/data-type-select.tsx
  18. 42
      src/components/footer.tsx
  19. 8
      src/components/icon.tsx
  20. 28
      src/components/iframely-card.tsx
  21. 29
      src/components/inbox.tsx
  22. 5
      src/components/listing-type-select.tsx
  23. 105
      src/components/login.tsx
  24. 103
      src/components/main.tsx
  25. 71
      src/components/markdown-textarea.tsx
  26. 23
      src/components/modlog.tsx
  27. 2
      src/components/moment-time.tsx
  28. 80
      src/components/navbar.tsx
  29. 33
      src/components/password_change.tsx
  30. 73
      src/components/post-form.tsx
  31. 169
      src/components/post-listing.tsx
  32. 14
      src/components/post-listings.tsx
  33. 23
      src/components/post.tsx
  34. 2
      src/components/privacy-policy.tsx
  35. 49
      src/components/private-message-form.tsx
  36. 35
      src/components/private-message.tsx
  37. 67
      src/components/reports.tsx
  38. 43
      src/components/search.tsx
  39. 49
      src/components/setup.tsx
  40. 69
      src/components/sidebar.tsx
  41. 69
      src/components/site-form.tsx
  42. 5
      src/components/sort-select.tsx
  43. 20
      src/components/sponsors.tsx
  44. 18
      src/components/symbols.tsx
  45. 2
      src/components/tos.tsx
  46. 9
      src/components/user-details.tsx
  47. 6
      src/components/user-listing.tsx
  48. 175
      src/components/user.tsx
  49. 93
      src/components/welcome.tsx
  50. 2
      src/custom-emojis.ts
  51. 2
      src/i18next.ts
  52. 121
      src/index.html
  53. 17
      src/index.tsx
  54. 37
      src/linkEvent.ts
  55. 6
      src/react.ts
  56. 9
      src/utils.ts
  57. 4240
      yarn.lock

2
.gitignore

@ -25,3 +25,5 @@ test/data/result.json
package-lock.json
*.orig
.cache
.parcel-cache

14
package.json

@ -7,11 +7,13 @@
"main": "index.js",
"scripts": {
"api-test": "jest src/api_tests/api.spec.ts",
"build": "node fuse prod",
"build_old": "node fuse prod",
"lint": "tsc --noEmit && eslint --report-unused-disable-directives --ext .js,.ts,.tsx src",
"prebuild": "node generate_translations.js",
"prestart": "node generate_translations.js",
"start": "node fuse dev"
"start_old": "node fuse dev",
"start": "parcel serve ./src/index.html -p 4444",
"build": "parcel build ./src/index.html"
},
"keywords": [],
"dependencies": {
@ -31,9 +33,6 @@
"emoji-short-name": "^1.0.0",
"husky": "^4.2.5",
"i18next": "^19.4.1",
"inferno": "^7.4.2",
"inferno-i18next": "nimbusec-oss/inferno-i18next",
"inferno-router": "^7.4.2",
"js-cookie": "^2.2.0",
"jwt-decode": "^2.2.0",
"markdown-it": "^10.0.0",
@ -42,10 +41,15 @@
"markdown-it-for-inline": "^0.1.1",
"moment": "^2.24.0",
"node-fetch": "^2.6.0",
"parcel": "^2.0.0-beta.1",
"parse-domain": "^3.0.2",
"prettier": "^2.0.4",
"psl": "^1.8.0",
"qs": "^6.9.4",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-i18next": "^11.7.0",
"react-router-dom": "^5.2.0",
"reconnecting-websocket": "^4.4.0",
"register-service-worker": "^1.7.1",
"rxjs": "^6.5.5",

8
src/components/about.tsx

@ -1,7 +1,7 @@
import { Component } from 'inferno';
import React, { Component } from 'react';
import { WebSocketService } from '../services';
import { i18n } from '../i18next';
import { T } from 'inferno-i18next';
import { Trans } from 'react-i18next';
import { repoUrl } from '../utils';
export class About extends Component<any, any> {
@ -18,8 +18,8 @@ export class About extends Component<any, any> {
render() {
return (
<div class="about-container">
<div class="about-header">
<div className="about-container">
<div className="about-header">
<img
src="/static/assets/banner.png"
className="img-fluid"

37
src/components/admin-settings.tsx

@ -1,4 +1,4 @@
import { Component, linkEvent } from 'inferno';
import React, { Component } from 'react';
import { Subscription } from 'rxjs';
import { retryWhen, delay, take } from 'rxjs/operators';
import {
@ -15,6 +15,7 @@ import autosize from 'autosize';
import { SiteForm } from './site-form';
import { UserListing } from './user-listing';
import { i18n } from '../i18next';
import { linkEvent } from '../linkEvent';
interface AdminSettingsState {
siteRes: GetSiteResponse;
@ -83,21 +84,21 @@ export class AdminSettings extends Component<any, AdminSettingsState> {
render() {
console.log(this.state.siteRes.site);
return (
<div class="container">
<div className="container">
{this.state.siteLoading || this.state.siteConfigLoading ? (
<h5>
<svg class="icon icon-spinner spin">
<svg className="icon icon-spinner spin">
<use xlinkHref="#icon-spinner"></use>
</svg>
</h5>
) : (
<div class="row">
<div class="col-12 col-md-6">
<div className="row">
<div className="col-12 col-md-6">
<SiteForm site={this.state.siteRes.site} />
{this.admins()}
{this.bannedUsers()}
</div>
<div class="col-12 col-md-6">{this.adminSettings()}</div>
<div className="col-12 col-md-6">{this.adminSettings()}</div>
</div>
)}
</div>
@ -108,9 +109,9 @@ export class AdminSettings extends Component<any, AdminSettingsState> {
return (
<>
<h5>{capitalizeFirstLetter(i18n.t('admins'))}</h5>
<ul class="list-unstyled">
<ul className="list-unstyled">
{this.state.siteRes.admins.map(admin => (
<li class="list-inline-item">
<li className="list-inline-item">
<UserListing
user={{
name: admin.name,
@ -131,9 +132,9 @@ export class AdminSettings extends Component<any, AdminSettingsState> {
return (
<>
<h5>{i18n.t('banned_users')}</h5>
<ul class="list-unstyled">
<ul className="list-unstyled">
{this.state.siteRes.banned.map(banned => (
<li class="list-inline-item">
<li className="list-inline-item">
<UserListing
user={{
name: banned.name,
@ -155,28 +156,28 @@ export class AdminSettings extends Component<any, AdminSettingsState> {
<div>
<h5>{i18n.t('admin_settings')}</h5>
<form onSubmit={linkEvent(this, this.handleSiteConfigSubmit)}>
<div class="form-group row">
<div className="form-group row">
<label
class="col-12 col-form-label"
className="col-12 col-form-label"
htmlFor={this.siteConfigTextAreaId}
>
{i18n.t('site_config')}
</label>
<div class="col-12">
<div className="col-12">
<textarea
id={this.siteConfigTextAreaId}
value={this.state.siteConfigForm.config_hjson}
onInput={linkEvent(this, this.handleSiteConfigHjsonChange)}
class="form-control text-monospace"
className="form-control text-monospace"
rows={3}
/>
</div>
</div>
<div class="form-group row">
<div class="col-12">
<button type="submit" class="btn btn-secondary mr-2">
<div className="form-group row">
<div className="col-12">
<button type="submit" className="btn btn-secondary mr-2">
{this.state.siteConfigLoading ? (
<svg class="icon icon-spinner spin">
<svg className="icon icon-spinner spin">
<use xlinkHref="#icon-spinner"></use>
</svg>
) : (

4
src/components/cake-day.tsx

@ -1,4 +1,4 @@
import { Component } from 'inferno';
import React, { Component } from 'react';
import { i18n } from '../i18next';
interface CakeDayProps {
@ -12,7 +12,7 @@ export class CakeDay extends Component<CakeDayProps, any> {
className={`mx-2 d-inline-block unselectable pointer`}
data-tippy-content={this.cakeDayTippy()}
>
<svg class="icon icon-inline">
<svg className="icon icon-inline">
<use xlinkHref="#icon-cake"></use>
</svg>
</div>

18
src/components/comment-form.tsx

@ -1,5 +1,5 @@
import { Component } from 'inferno';
import { Link } from 'inferno-router';
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import { Subscription } from 'rxjs';
import { retryWhen, delay, take } from 'rxjs/operators';
import {
@ -12,7 +12,7 @@ import {
import { capitalizeFirstLetter, wsJsonToRes, toast } from '../utils';
import { WebSocketService, UserService } from '../services';
import { i18n } from '../i18next';
import { T } from 'inferno-i18next';
import { Trans } from 'react-i18next';
import { MarkdownTextArea } from './markdown-textarea';
interface CommentFormProps {
@ -91,7 +91,7 @@ export class CommentForm extends Component<CommentFormProps, CommentFormState> {
this.state.commentForm.content.trim() === '') ||
this.state.commentForm.content === null;
return (
<div class="mb-3">
<div className="mb-3">
{UserService.Instance.user ? (
<MarkdownTextArea
initialContent={this.state.commentForm.content}
@ -104,16 +104,16 @@ export class CommentForm extends Component<CommentFormProps, CommentFormState> {
onReplyCancel={this.handleReplyCancel}
/>
) : (
<div class="alert alert-light" role="alert">
<svg class="icon icon-inline mr-2">
<div className="alert alert-light" role="alert">
<svg className="icon icon-inline mr-2">
<use xlinkHref="#icon-alert-triangle"></use>
</svg>
<T i18nKey="must_login" class="d-inline">
<Trans i18nKey="must_login" className="d-inline">
#
<Link class="alert-link" to="/login">
<Link className="alert-link" to="/login">
#
</Link>
</T>
</Trans>
</div>
)}
</div>

139
src/components/comment-node.tsx

@ -1,5 +1,5 @@
import { Component, linkEvent } from 'inferno';
import { Link } from 'inferno-router';
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import {
CommentNode as CommentNodeI,
CommentLikeForm,
@ -38,6 +38,7 @@ import { CommunityLink } from './community-link';
import { i18n } from '../i18next';
import { replaceEmojis } from '../custom-emojis';
import { Icon } from './icon';
import { linkEvent } from '../linkEvent';
interface CommentNodeState {
showReply: boolean;
@ -172,13 +173,13 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
}
>
<div
class={`${
className={`${
!this.props.noIndent &&
this.props.node.comment.parent_id &&
'ml-2'
}`}
>
<div class="d-flex flex-wrap align-items-center text-muted small">
<div className="d-flex flex-wrap align-items-center text-muted small">
<div
className="unselectable pointer mr-2 comment-expand-button"
onClick={linkEvent(this, this.handleCommentCollapse)}
@ -189,7 +190,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
<Icon name="minus" size="16px" />
)}
</div>
<span class="mr-2">
<span className="mr-2">
<UserListing
user={{
name: node.comment.creator_name,
@ -225,7 +226,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
)}
{this.props.showCommunity && (
<>
<span class="mx-1">{i18n.t('to')}</span>
<span className="mx-1">{i18n.t('to')}</span>
<CommunityLink
community={{
name: node.comment.community_name,
@ -234,8 +235,8 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
actor_id: node.comment.community_actor_id,
}}
/>
<span class="mx-2"></span>
<Link class="mr-2" to={`/post/${node.comment.post_id}`}>
<span className="mx-2"></span>
<Link className="mr-2" to={`/post/${node.comment.post_id}`}>
{node.comment.post_name}
</Link>
</>
@ -247,8 +248,8 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
onClick={linkEvent(node, this.handleCommentUpvote)}
data-tippy-content={this.pointsTippy}
>
<Icon name="hexbear" class="icon mr-1 mb-1" />
<span class="mr-1">{this.state.score}</span>
<Icon name="hexbear" className="icon mr-1 mb-1" />
<span className="mr-1">{this.state.score}</span>
</button>
<span className="mr-1"></span>
<span>
@ -277,11 +278,11 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
)}
/>
)}
<div class="d-flex justify-content-between justify-content-lg-start flex-wrap text-muted font-weight-bold">
<div className="d-flex justify-content-between justify-content-lg-start flex-wrap text-muted font-weight-bold">
{this.props.showContext && this.linkBtn}
{this.props.markable && (
<button
class="btn btn-link btn-animate text-muted"
className="btn btn-link btn-animate text-muted"
onClick={linkEvent(this, this.handleMarkRead)}
data-tippy-content={
node.comment.read
@ -293,7 +294,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
this.loadingIcon
) : (
<svg
class={`icon icon-inline ${
className={`icon icon-inline ${
node.comment.read && 'text-success'
}`}
>
@ -313,7 +314,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
>
<Icon name="upvote" />
{this.state.upvotes !== this.state.score && (
<span class="ml-1">{this.state.upvotes}</span>
<span className="ml-1">{this.state.upvotes}</span>
)}
</button>
{this.props.enableDownvotes && (
@ -328,12 +329,12 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
>
<Icon name="downvote" />
{this.state.upvotes !== this.state.score && (
<span class="ml-1">{this.state.downvotes}</span>
<span className="ml-1">{this.state.downvotes}</span>
)}
</button>
)}
<button
class="btn btn-link btn-animate text-muted"
className="btn btn-link btn-animate text-muted"
onClick={linkEvent(this, this.handleReplyClick)}
data-tippy-content={i18n.t('reply')}
>
@ -350,13 +351,13 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
) : (
<>
{!this.myComment && (
<button class="btn btn-link btn-animate">
<button className="btn btn-link btn-animate">
<Link
class="text-muted"
className="text-muted"
to={`/create_private_message?recipient_id=${node.comment.creator_id}`}
title={i18n.t('message').toLowerCase()}
>
<svg class="icon">
<svg className="icon">
<use xlinkHref="#icon-mail"></use>
</svg>
</Link>
@ -364,7 +365,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
)}
{!this.props.showContext && this.linkBtn}
<button
class="btn btn-link btn-animate text-muted"
className="btn btn-link btn-animate text-muted"
onClick={linkEvent(
this,
this.handleSaveCommentClick
@ -379,7 +380,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
this.loadingIcon
) : (
<Icon
class={`icon icon-inline ${
className={`icon icon-inline ${
node.comment.saved && 'text-warning'
}`}
name="star"
@ -392,7 +393,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
data-tippy-content={i18n.t('view_source')}
>
<svg
class={`icon icon-inline ${
className={`icon icon-inline ${
this.state.viewSource && 'text-success'
}`}
>
@ -402,14 +403,14 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
{this.myComment ? (
<>
<button
class="btn btn-link btn-animate text-muted"
className="btn btn-link btn-animate text-muted"
onClick={linkEvent(this, this.handleEditClick)}
data-tippy-content={i18n.t('edit')}
>
<Icon name="edit" />
</button>
<button
class="btn btn-link btn-animate text-muted"
className="btn btn-link btn-animate text-muted"
onClick={linkEvent(
this,
this.handleDeleteClick
@ -421,7 +422,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
}
>
<svg
class={`icon icon-inline ${
className={`icon icon-inline ${
node.comment.deleted && 'text-danger'
}`}
>
@ -431,7 +432,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
</>
) : (
<button
class="btn btn-sm btn-link btn-animate text-muted small"
className="btn btn-sm btn-link btn-animate text-muted small"
onClick={linkEvent(
this,
this.handleReportComment
@ -446,7 +447,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
<>
{!node.comment.removed ? (
<button
class="btn btn-link btn-animate text-muted"
className="btn btn-link btn-animate text-muted"
onClick={linkEvent(
this,
this.handleModRemoveShow
@ -456,7 +457,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
</button>
) : (
<button
class="btn btn-link btn-animate text-muted"
className="btn btn-link btn-animate text-muted"
onClick={linkEvent(
this,
this.handleModRemoveSubmit
@ -473,7 +474,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
{!this.isMod &&
(!node.comment.banned_from_community ? (
<button
class="btn btn-link btn-animate text-muted"
className="btn btn-link btn-animate text-muted"
onClick={linkEvent(
this,
this.handleModBanFromCommunityShow
@ -483,7 +484,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
</button>
) : (
<button
class="btn btn-link btn-animate text-muted"
className="btn btn-link btn-animate text-muted"
onClick={linkEvent(
this,
this.handleModBanFromCommunitySubmit
@ -495,7 +496,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
{!node.comment.banned_from_community &&
(!this.state.showConfirmAppointAsMod ? (
<button
class="btn btn-link btn-animate text-muted"
className="btn btn-link btn-animate text-muted"
onClick={linkEvent(
this,
this.handleShowConfirmAppointAsMod
@ -507,11 +508,11 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
</button>
) : (
<>
<button class="btn btn-link btn-animate text-muted">
<button className="btn btn-link btn-animate text-muted">
{i18n.t('are_you_sure')}
</button>
<button
class="btn btn-link btn-animate text-muted"
className="btn btn-link btn-animate text-muted"
onClick={linkEvent(
this,
this.handleAddModToCommunity
@ -520,7 +521,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
{i18n.t('yes')}
</button>
<button
class="btn btn-link btn-animate text-muted"
className="btn btn-link btn-animate text-muted"
onClick={linkEvent(
this,
this.handleCancelConfirmAppointAsMod
@ -537,7 +538,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
this.isMod &&
(!this.state.showConfirmTransferCommunity ? (
<button
class="btn btn-link btn-animate text-muted"
className="btn btn-link btn-animate text-muted"
onClick={linkEvent(
this,
this.handleShowConfirmTransferCommunity
@ -547,11 +548,11 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
</button>
) : (
<>
<button class="btn btn-link btn-animate text-muted">
<button className="btn btn-link btn-animate text-muted">
{i18n.t('are_you_sure')}
</button>
<button
class="btn btn-link btn-animate text-muted"
className="btn btn-link btn-animate text-muted"
onClick={linkEvent(
this,
this.handleTransferCommunity
@ -560,7 +561,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
{i18n.t('yes')}
</button>
<button
class="btn btn-link btn-animate text-muted"
className="btn btn-link btn-animate text-muted"
onClick={linkEvent(
this,
this
@ -577,7 +578,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
{!this.isAdmin &&
(!node.comment.banned ? (
<button
class="btn btn-link btn-animate text-muted"
className="btn btn-link btn-animate text-muted"
onClick={linkEvent(
this,
this.handleModBanShow
@ -587,7 +588,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
</button>
) : (
<button
class="btn btn-link btn-animate text-muted"
className="btn btn-link btn-animate text-muted"
onClick={linkEvent(
this,
this.handleModBanSubmit
@ -599,7 +600,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
{!node.comment.banned &&
(!this.state.showConfirmAppointAsAdmin ? (
<button
class="btn btn-link btn-animate text-muted"
className="btn btn-link btn-animate text-muted"
onClick={linkEvent(
this,
this.handleShowConfirmAppointAsAdmin
@ -611,11 +612,11 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
</button>
) : (
<>
<button class="btn btn-link btn-animate text-muted">
<button className="btn btn-link btn-animate text-muted">
{i18n.t('are_you_sure')}
</button>
<button
class="btn btn-link btn-animate text-muted"
className="btn btn-link btn-animate text-muted"
onClick={linkEvent(
this,
this.handleAddAdmin
@ -624,7 +625,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
{i18n.t('yes')}
</button>
<button
class="btn btn-link btn-animate text-muted"
className="btn btn-link btn-animate text-muted"
onClick={linkEvent(
this,
this.handleCancelConfirmAppointAsAdmin
@ -641,7 +642,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
this.isAdmin &&
(!this.state.showConfirmTransferSite ? (
<button
class="btn btn-link btn-animate text-muted"
className="btn btn-link btn-animate text-muted"
onClick={linkEvent(
this,
this.handleShowConfirmTransferSite
@ -651,11 +652,11 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
</button>
) : (
<>
<button class="btn btn-link btn-animate text-muted">
<button className="btn btn-link btn-animate text-muted">
{i18n.t('are_you_sure')}
</button>
<button
class="btn btn-link btn-animate text-muted"
className="btn btn-link btn-animate text-muted"
onClick={linkEvent(
this,
this.handleTransferSite
@ -664,7 +665,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
{i18n.t('yes')}
</button>
<button
class="btn btn-link btn-animate text-muted"
className="btn btn-link btn-animate text-muted"
onClick={linkEvent(
this,
this.handleCancelShowConfirmTransferSite
@ -687,40 +688,40 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
{/* end of details */}
{this.state.showRemoveDialog && (
<form
class="form-inline"
className="form-inline"
onSubmit={linkEvent(this, this.handleModRemoveSubmit)}
>
<input
type="text"
class="form-control mr-2"
className="form-control mr-2"
placeholder={i18n.t('reason')}
value={this.state.removeReason}
onInput={linkEvent(this, this.handleModRemoveReasonChange)}
/>
<button type="submit" class="btn btn-secondary">
<button type="submit" className="btn btn-secondary">
{i18n.t('remove_comment')}
</button>
</form>
)}
{this.state.showBanDialog && (
<form onSubmit={linkEvent(this, this.handleModBanBothSubmit)}>
<div class="form-group row">
<label class="col-form-label">{i18n.t('reason')}</label>
<div className="form-group row">
<label className="col-form-label">{i18n.t('reason')}</label>
<input
type="text"
class="form-control mr-2"
className="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 className="form-group row"> */}
{/* <label className="col-form-label">Expires</label> */}
{/* <input type="date" className="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">
<div className="form-group row">
<button type="submit" className="btn btn-secondary">
{i18n.t('ban')} {node.comment.creator_name}
</button>
</div>
@ -729,24 +730,24 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
{this.state.showReportDialog && (
<form
onSubmit={linkEvent(this, this.handleReportSubmit)}
class="px-2"
className="px-2"
>
<div class="form-group row">
<label class="col-form-label" htmlFor="comment-report-dialog">
<div className="form-group row">
<label className="col-form-label" htmlFor="comment-report-dialog">
{i18n.t('reason')}
</label>
<input
id="comment-report-dialog"
type="text"
class="form-control mr-2"
className="form-control mr-2"
placeholder={i18n.t('reason')}
value={this.state.reportReason}
onInput={linkEvent(this, this.handleReportReasonChange)}
maxLength={600}
/>
</div>
<div class="form-group row">
<button type="submit" class="btn btn-secondary">
<div className="form-group row">
<button type="submit" className="btn btn-secondary">
{i18n.t('submit_report')}
</button>
</div>
@ -773,7 +774,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
/>
)}
{/* A collapsed clearfix */}
{this.state.collapsed && <div class="row col-12"></div>}
{this.state.collapsed && <div className="row col-12"></div>}
</div>
);
}
@ -782,11 +783,11 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
let node = this.props.node;
return (
<Link
class="btn btn-link btn-animate text-muted"
className="btn btn-link btn-animate text-muted"
to={`/post/${node.comment.post_id}/comment/${node.comment.id}`}
title={this.props.showContext ? i18n.t('show_context') : i18n.t('link')}
>
<svg class="icon icon-inline">
<svg className="icon icon-inline">
<use xlinkHref="#icon-link"></use>
</svg>
</Link>
@ -795,7 +796,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
get loadingIcon() {
return (
<svg class="icon icon-spinner spin">
<svg className="icon icon-spinner spin">
<use xlinkHref="#icon-spinner"></use>
</svg>
);

2
src/components/comment-nodes.tsx

@ -1,4 +1,4 @@
import { Component } from 'inferno';
import React, { Component } from 'react';
import {
CommentNode as CommentNodeI,
CommunityUser,

43
src/components/communities.tsx

@ -1,4 +1,4 @@
import { Component, linkEvent } from 'inferno';
import React, { Component } from 'react';
import { Subscription } from 'rxjs';
import { retryWhen, delay, take } from 'rxjs/operators';
import {
@ -16,6 +16,7 @@ import { WebSocketService } from '../services';
import { wsJsonToRes, toast, getPageFromProps } from '../utils';
import { CommunityLink } from './community-link';
import { i18n } from '../i18next';
import { linkEvent } from '../linkEvent';
declare const Sortable: any;
@ -73,28 +74,28 @@ export class Communities extends Component<any, CommunitiesState> {
render() {
return (
<div class="container">
<div className="container">
{this.state.loading ? (
<h5 class="">
<svg class="icon icon-spinner spin">
<h5 className="">
<svg className="icon icon-spinner spin">
<use xlinkHref="#icon-spinner"></use>
</svg>
</h5>
) : (
<div>
<h5>{i18n.t('list_of_communities')}</h5>
<div class="table-responsive">
<table id="community_table" class="table table-sm table-hover">
<thead class="pointer">
<div className="table-responsive">
<table id="community_table" className="table table-sm table-hover">
<thead className="pointer">
<tr>
<th>{i18n.t('name')}</th>
<th class="d-none d-lg-table-cell">{i18n.t('title')}</th>
<th className="d-none d-lg-table-cell">{i18n.t('title')}</th>
<th>{i18n.t('category')}</th>
<th class="text-right">{i18n.t('subscribers')}</th>
<th class="text-right d-none d-lg-table-cell">
<th className="text-right">{i18n.t('subscribers')}</th>
<th className="text-right d-none d-lg-table-cell">
{i18n.t('posts')}
</th>
<th class="text-right d-none d-lg-table-cell">
<th className="text-right d-none d-lg-table-cell">
{i18n.t('comments')}
</th>
<th></th>
@ -106,21 +107,21 @@ export class Communities extends Component<any, CommunitiesState> {
<td>
<CommunityLink community={community} />
</td>
<td class="d-none d-lg-table-cell">{community.title}</td>
<td className="d-none d-lg-table-cell">{community.title}</td>
<td>{community.category_name}</td>
<td class="text-right">
<td className="text-right">
{community.number_of_subscribers}
</td>
<td class="text-right d-none d-lg-table-cell">
<td className="text-right d-none d-lg-table-cell">
{community.number_of_posts}
</td>
<td class="text-right d-none d-lg-table-cell">
<td className="text-right d-none d-lg-table-cell">
{community.number_of_comments}
</td>
<td class="text-right">
<td className="text-right">
{community.subscribed ? (
<span
class="pointer btn-link"
className="pointer btn-link"
onClick={linkEvent(
community.id,
this.handleUnsubscribe
@ -130,7 +131,7 @@ export class Communities extends Component<any, CommunitiesState> {
</span>
) : (
<span
class="pointer btn-link"
className="pointer btn-link"
onClick={linkEvent(
community.id,
this.handleSubscribe
@ -154,10 +155,10 @@ export class Communities extends Component<any, CommunitiesState> {
paginator() {
return (
<div class="mt-2">
<div className="mt-2">
{this.state.page > 1 && (
<button
class="btn btn-sm btn-secondary mr-1"
className="btn btn-sm btn-secondary mr-1"
onClick={linkEvent(this, this.prevPage)}
>
{i18n.t('prev')}
@ -166,7 +167,7 @@ export class Communities extends Component<any, CommunitiesState> {
{this.state.communities.length > 0 && (
<button
class="btn btn-sm btn-secondary"
className="btn btn-sm btn-secondary"
onClick={linkEvent(this, this.nextPage)}
>
{i18n.t('next')}

37
src/components/community-dropdown.tsx

@ -11,14 +11,15 @@ import {
UserDetailsResponse,
CommunityUser,
} from '../interfaces';
import { Component, linkEvent, createRef } from 'inferno';
import React, { Component, createRef } from 'react';
import { Subscription } from 'rxjs';
import { WebSocketService, UserService } from '../services';
import { retryWhen, delay, take } from 'rxjs/operators';
import { wsJsonToRes, toast } from '../utils';
import { i18n } from '../i18next';
import { Link } from 'inferno-router';
import { Link } from 'react-router-dom';
import { disableBodyScroll, clearAllBodyScrollLocks } from 'body-scroll-lock';
import { linkEvent } from '../linkEvent';
interface CommunityDropdownState {
favorites: Array<Community> /*not used right now */;
@ -80,47 +81,47 @@ export class CommunityDropdown extends Component<
render() {
return (
<>
<div class="dropdown-block" id="blocking-element"></div>
<div className="dropdown-block" id="blocking-element"></div>
<div
class="floating-container"
className="floating-container"
style={this.getContainerLoc()}
id="floating-container"
ref={this.thisRef}
>
{!this.state.loading && (
<div class="dropdown-content">
<div className="dropdown-content">
<div style="display:flex">
<input
class="dropdown-filter form-control"
className="dropdown-filter form-control"
placeholder="Filter"
onInput={linkEvent(this, this.handleFilterChange)}
></input>
<button
class="dropdown-exit btn"
className="dropdown-exit btn"
onClick={linkEvent(this, this.handleDropdownClose)}
>
<svg class="icon icon-inline">
<svg className="icon icon-inline">
<use xlinkHref="#icon-cancel"></use>
</svg>
</button>
</div>
{this.sortedCommunities.length > 0 ? (
<div class="dropdown-categories">
<div className="dropdown-categories">
{this.sortedSubscriptions.length > 0 && (
<div class="dropdown-category">
<div className="dropdown-category">
<h6>Subscribed</h6>
{this.sortedSubscriptions.map(community => (
<>
<div class="community-listing">
<div className="community-listing">
<span
class="community-icon"
className="community-icon"
style={
'background: ' +
this.generateColor(community.community_name)
}
></span>
<Link
class="community-listing-title"
className="community-listing-title"
to={`/c/${community.community_name}`}
onClick={linkEvent(
this,
@ -134,20 +135,20 @@ export class CommunityDropdown extends Component<
))}
</div>
)}
<div class="dropdown-category">
<div className="dropdown-category">
<h6>Communities</h6>
{this.sortedCommunities.map(community => (
<>
<div class="community-listing">
<div className="community-listing">
<span
class="community-icon"
className="community-icon"
style={
'background: ' +
this.generateColor(community.name)
}
></span>
<Link
class="community-listing-title"
className="community-listing-title"
to={`/c/${community.name}`}
onClick={linkEvent(this, this.handleDropdownClose)}
>
@ -176,7 +177,7 @@ export class CommunityDropdown extends Component<
</div>
)}
<Link
class="dropdown-subtext"
className="dropdown-subtext"
to="/communities"
onClick={linkEvent(this, this.handleDropdownClose)}
>

99
src/components/community-form.tsx

@ -1,5 +1,5 @@
import { Component, linkEvent } from 'inferno';
import { Prompt } from 'inferno-router';
import React, { Component } from 'react';
import { Prompt } from 'react-router-dom';
import { Subscription } from 'rxjs';
import { retryWhen, delay, take } from 'rxjs/operators';
import {
@ -17,6 +17,7 @@ import { i18n } from '../i18next';
import { Community } from '../interfaces';
import { MarkdownTextArea } from './markdown-textarea';
import { linkEvent } from '../linkEvent';
interface CommunityFormProps {
community?: Community; // If a community is given, that means this is an edit
@ -132,15 +133,15 @@ export class CommunityForm extends Component<
/>
<form onSubmit={linkEvent(this, this.handleCreateCommunitySubmit)}>
{!this.props.community && (
<div class="form-group row">
<label class="col-12 col-form-label" htmlFor="community-name">
<div className="form-group row">
<label className="col-12 col-form-label" htmlFor="community-name">
{i18n.t('name')}
</label>
<div class="col-12">
<div className="col-12">
<input
type="text"
id="community-name"
class="form-control"
className="form-control"
value={this.state.communityForm.name}
onInput={linkEvent(this, this.handleCommunityNameChange)}
required
@ -152,41 +153,41 @@ export class CommunityForm extends Component<
</div>
</div>
)}
<div class="form-group row">
<label class="col-12 col-form-label" htmlFor="community-title">
<div className="form-group row">
<label className="col-12 col-form-label" htmlFor="community-title">
{i18n.t('title')}
</label>
<div class="col-12">
<div className="col-12">
<input
type="text"
id="community-title"
value={this.state.communityForm.title}
onInput={linkEvent(this, this.handleCommunityTitleChange)}
class="form-control"
className="form-control"
required
minLength={3}
maxLength={100}
/>
</div>
</div>
<div class="form-group row">
<label class="col-12 col-form-label" htmlFor={this.id}>
<div className="form-group row">
<label className="col-12 col-form-label" htmlFor={this.id}>
{i18n.t('sidebar')}
</label>
<div class="col-12">
<div className="col-12">
<MarkdownTextArea
initialContent={this.state.communityForm.description}
onContentChange={this.handleCommunityDescriptionChange}
/>
</div>
</div>
<div class="form-group row">
<label class="col-12 col-form-label" htmlFor="community-category">
<div className="form-group row">
<label className="col-12 col-form-label" htmlFor="community-category">
{i18n.t('category')}
</label>
<div class="col-12">
<div className="col-12">
<select
class="form-control"
className="form-control"
id="community-category"
value={this.state.communityForm.category_id}
onInput={linkEvent(this, this.handleCommunityCategoryChange)}
@ -199,17 +200,17 @@ export class CommunityForm extends Component<
</div>
{this.props.enableNsfw && (
<div class="form-group row">
<div class="col-12">
<div class="form-check">
<div className="form-group row">
<div className="col-12">
<div className="form-check">
<input
class="form-check-input"
className="form-check-input"
id="community-nsfw"
type="checkbox"
checked={this.state.communityForm.nsfw}
onChange={linkEvent(this, this.handleCommunityNsfwChange)}
/>
<label class="form-check-label" htmlFor="community-nsfw">
<label className="form-check-label" htmlFor="community-nsfw">
{i18n.t('nsfw')}
</label>
</div>
@ -221,15 +222,15 @@ export class CommunityForm extends Component<
this.state.community_settings &&
this.communitySettings()}
<div class="form-group row">
<div class="col-12">
<div className="form-group row">
<div className="col-12">
<button
type="submit"
class="btn btn-secondary mr-2"
className="btn btn-secondary mr-2"
disabled={this.state.loading}
>
{this.state.loading ? (
<svg class="icon icon-spinner spin">
<svg className="icon icon-spinner spin">
<use xlinkHref="#icon-spinner"></use>
</svg>
) : this.props.community ? (
@ -241,7 +242,7 @@ export class CommunityForm extends Component<
{this.props.community && (
<button
type="button"
class="btn btn-secondary"
className="btn btn-secondary"
onClick={linkEvent(this, this.handleCancel)}
>
{i18n.t('cancel')}
@ -256,69 +257,69 @@ export class CommunityForm extends Component<
communitySettings() {
return (
<section class="my-4">
<p class="h5 mb-3">{i18n.t('community_settings')}</p>
{/* <p class="text-muted mb-3">
<section className="my-4">
<p className="h5 mb-3">{i18n.t('community_settings')}</p>
{/* <p className="text-muted mb-3">
<small>{this.state.community_settings.published}</small>
</p> */}
<div class="form-group row">
<div class="col-12">
<div class="form-check">
<div className="form-group row">
<div className="col-12">
<div className="form-check">
<input
class="form-check-input"
className="form-check-input"
id="community-read-only"
type="checkbox"
checked={this.state.community_settings.read_only}
onChange={linkEvent(this, this.handleCommunityReadOnlyChange)}
/>
<label class="form-check-label" htmlFor="community-read-only">
<label className="form-check-label" htmlFor="community-read-only">
{i18n.t('community_read_only')}
</label>
</div>
</div>
</div>
<div class="form-group row">
<div class="col-12">
<div class="form-check">
<div className="form-group row">
<div className="col-12">
<div className="form-check">
<input
class="form-check-input"
className="form-check-input"
id="community-private"
type="checkbox"
checked={this.state.community_settings.private}
onChange={linkEvent(this, this.handleCommunityPrivateChange)}
/>
<label class="form-check-label" htmlFor="community-private">
<label className="form-check-label" htmlFor="community-private">
{i18n.t('community_private')}
</label>
</div>
</div>
</div>
<div class="form-group row mb-3">
<div class="col-12">
<div class="form-check">
<div className="form-group row mb-3">
<div className="col-12">
<div className="form-check">
<input
class="form-check-input"
className="form-check-input"
id="community-post-links"
type="checkbox"
checked={this.state.community_settings.post_links}
onChange={linkEvent(this, this.handleCommunityPostLinksChange)}
/>
<label class="form-check-label" htmlFor="community-post-links">
<label className="form-check-label" htmlFor="community-post-links">
{i18n.t('community_post_links')}
</label>
</div>
</div>
</div>
<div class="form-group row">
<div className="form-group row">
<label
class="col-12 col-form-label pt-0"
className="col-12 col-form-label pt-0"
htmlFor="community-comment-images"
>
{i18n.t('community_comment_images')}
</label>
<div class="col-12">
<div className="col-12">
<input
class="form-control"
className="form-control"
id="community-comment-images"
type="number"
value={this.state.community_settings.comment_images}

4
src/components/community-link.tsx

@ -1,5 +1,5 @@
import { Component } from 'inferno';
import { Link } from 'inferno-router';
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import { Community } from '../interfaces';
import { hostname } from '../utils';

31
src/components/community.tsx

@ -1,5 +1,5 @@
import { Component, linkEvent } from 'inferno';
import { Link } from 'inferno-router';
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import { Subscription } from 'rxjs';
import { retryWhen, delay, take } from 'rxjs/operators';
import {
@ -51,6 +51,7 @@ import {
} from '../utils';
import { i18n } from '../i18next';
import { Icon } from './icon';
import { linkEvent } from '../linkEvent';
interface State {
community: CommunityI;
@ -181,10 +182,10 @@ export class Community extends Component<any, State> {
render() {
const isMobile = window.innerWidth < 992;
return (
<div class="container">
<div className="container">
{this.state.loading ? (
<h5>
<svg class="icon icon-spinner spin">
<svg className="icon icon-spinner spin">
<use xlinkHref="#icon-spinner"></use>
</svg>
</h5>
@ -211,7 +212,7 @@ export class Community extends Component<any, State> {
</div>
{this.state.community.subscribed ? (
<button
class="btn btn-secondary unsubscribe-button"
className="btn btn-secondary unsubscribe-button"
onClick={linkEvent(
this.state.community.id,
this.handleUnsubscribe
@ -221,7 +222,7 @@ export class Community extends Component<any, State> {
</button>
) : (
<button
class="btn btn-secondary subscribe-button"
className="btn btn-secondary subscribe-button"
onClick={linkEvent(
this.state.community.id,
this.handleSubscribe
@ -241,8 +242,8 @@ export class Community extends Component<any, State> {
</div>
</div>
</div>
<div class="row">
<main class="col-12 col-md-8" role="main">
<div className="row">
<main className="col-12 col-md-8" role="main">
{this.selects()}
<h5>
{this.state.community.removed && (
@ -259,7 +260,7 @@ export class Community extends Component<any, State> {
{this.listings()}
{this.paginator()}
</main>
<aside class="col-12 col-md-4 sidebar">
<aside className="col-12 col-md-4 sidebar">
<Sidebar
community={this.state.community}
moderators={this.state.moderators}
@ -297,14 +298,14 @@ export class Community extends Component<any, State> {