summaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
authorDessalines <tyhou13@gmx.com>2019-04-16 16:04:23 -0700
committerDessalines <tyhou13@gmx.com>2019-04-16 16:04:23 -0700
commit3f33cf8dcb53d20e67d8abc9214c7192a28dca94 (patch)
treeaab1da1b0eb54d6d0cb1e00f4f38cb218901ac53 /ui
parente94885eb97b3240ed9cec7f97d0f405b2819e922 (diff)
Before big moderation merge
Diffstat (limited to 'ui')
-rw-r--r--ui/src/components/comment-form.tsx3
-rw-r--r--ui/src/components/comment-node.tsx6
-rw-r--r--ui/src/components/comment-nodes.tsx2
-rw-r--r--ui/src/components/communities.tsx16
-rw-r--r--ui/src/components/footer.tsx36
-rw-r--r--ui/src/components/login.tsx4
-rw-r--r--ui/src/components/main.tsx65
-rw-r--r--ui/src/components/modlog.tsx81
-rw-r--r--ui/src/components/navbar.tsx6
-rw-r--r--ui/src/components/post-form.tsx9
-rw-r--r--ui/src/components/post-listing.tsx3
-rw-r--r--ui/src/components/post-listings.tsx6
-rw-r--r--ui/src/components/post.tsx4
-rw-r--r--ui/src/components/setup.tsx147
-rw-r--r--ui/src/components/sidebar.tsx21
-rw-r--r--ui/src/components/site-form.tsx86
-rw-r--r--ui/src/index.tsx5
-rw-r--r--ui/src/interfaces.ts61
-rw-r--r--ui/src/services/UserService.ts4
-rw-r--r--ui/src/services/WebSocketService.ts25
20 files changed, 491 insertions, 99 deletions
diff --git a/ui/src/components/comment-form.tsx b/ui/src/components/comment-form.tsx
index 66f3094e..df079ba3 100644
--- a/ui/src/components/comment-form.tsx
+++ b/ui/src/components/comment-form.tsx
@@ -23,7 +23,7 @@ export class CommentForm extends Component<CommentFormProps, CommentFormState> {
auth: null,
content: null,
post_id: this.props.node ? this.props.node.comment.post_id : this.props.postId,
- creator_id: UserService.Instance.loggedIn ? UserService.Instance.user.id : null,
+ creator_id: UserService.Instance.user ? UserService.Instance.user.id : null,
},
buttonTitle: !this.props.node ? "Post" : this.props.edit ? "Edit" : "Reply",
}
@@ -71,6 +71,7 @@ export class CommentForm extends Component<CommentFormProps, CommentFormState> {
}
handleCommentSubmit(i: CommentForm, event: any) {
+ event.preventDefault();
if (i.props.edit) {
WebSocketService.Instance.editComment(i.state.commentForm);
} else {
diff --git a/ui/src/components/comment-node.tsx b/ui/src/components/comment-node.tsx
index eba36009..1fba1d92 100644
--- a/ui/src/components/comment-node.tsx
+++ b/ui/src/components/comment-node.tsx
@@ -154,13 +154,13 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
}
get myComment(): boolean {
- return UserService.Instance.loggedIn && 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 canMod(): boolean {
// You can do moderator actions only on the mods added after you.
- if (UserService.Instance.loggedIn) {
+ if (UserService.Instance.user) {
let modIds = this.props.moderators.map(m => m.user_id);
let yourIndex = modIds.findIndex(id => id == UserService.Instance.user.id);
if (yourIndex == -1) {
@@ -240,6 +240,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
}
handleModRemoveSubmit(i: CommentNode) {
+ event.preventDefault();
let form: CommentFormI = {
content: i.props.node.comment.content,
edit_id: i.props.node.comment.id,
@@ -272,6 +273,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
}
handleModBanSubmit(i: CommentNode) {
+ event.preventDefault();
let form: BanFromCommunityForm = {
user_id: i.props.node.comment.creator_id,
community_id: i.props.node.comment.community_id,
diff --git a/ui/src/components/comment-nodes.tsx b/ui/src/components/comment-nodes.tsx
index 19ba30c6..498c69b8 100644
--- a/ui/src/components/comment-nodes.tsx
+++ b/ui/src/components/comment-nodes.tsx
@@ -7,7 +7,7 @@ interface CommentNodesState {
interface CommentNodesProps {
nodes: Array<CommentNodeI>;
- moderators: Array<CommunityUser>;
+ moderators?: Array<CommunityUser>;
noIndent?: boolean;
viewOnly?: boolean;
locked?: boolean;
diff --git a/ui/src/components/communities.tsx b/ui/src/components/communities.tsx
index f8cce2c0..a78e43a7 100644
--- a/ui/src/components/communities.tsx
+++ b/ui/src/components/communities.tsx
@@ -62,9 +62,9 @@ export class Communities extends Component<any, CommunitiesState> {
<th>Name</th>
<th>Title</th>
<th>Category</th>
- <th class="text-right">Subscribers</th>
- <th class="text-right">Posts</th>
- <th class="text-right">Comments</th>
+ <th class="text-right d-none d-md-table-cell">Subscribers</th>
+ <th class="text-right d-none d-md-table-cell">Posts</th>
+ <th class="text-right d-none d-md-table-cell">Comments</th>
<th></th>
</tr>
</thead>
@@ -74,13 +74,13 @@ export class Communities extends Component<any, CommunitiesState> {
<td><Link to={`/community/${community.id}`}>{community.name}</Link></td>
<td>{community.title}</td>
<td>{community.category_name}</td>
- <td class="text-right">{community.number_of_subscribers}</td>
- <td class="text-right">{community.number_of_posts}</td>
- <td class="text-right">{community.number_of_comments}</td>
+ <td class="text-right d-none d-md-table-cell">{community.number_of_subscribers}</td>
+ <td class="text-right d-none d-md-table-cell">{community.number_of_posts}</td>
+ <td class="text-right d-none d-md-table-cell">{community.number_of_comments}</td>
<td class="text-right">
{community.subscribed ?
- <button class="btn btn-sm btn-secondary" onClick={linkEvent(community.id, this.handleUnsubscribe)}>Unsubscribe</button> :
- <button class="btn btn-sm btn-secondary" onClick={linkEvent(community.id, this.handleSubscribe)}>Subscribe</button>
+ <span class="pointer btn-link" onClick={linkEvent(community.id, this.handleUnsubscribe)}>Unsubscribe</span> :
+ <span class="pointer btn-link" onClick={linkEvent(community.id, this.handleSubscribe)}>Subscribe</span>
}
</td>
</tr>
diff --git a/ui/src/components/footer.tsx b/ui/src/components/footer.tsx
new file mode 100644
index 00000000..fe6d971a
--- /dev/null
+++ b/ui/src/components/footer.tsx
@@ -0,0 +1,36 @@
+import { Component } from 'inferno';
+import { Link } from 'inferno-router';
+import { repoUrl } from '../utils';
+import { version } from '../version';
+
+export class Footer extends Component<any, any> {
+
+
+ constructor(props: any, context: any) {
+ super(props, context);
+ }
+
+ render() {
+ return (
+ <nav title={version} class="container navbar navbar-expand-md navbar-light navbar-bg p-0 px-3 my-2">
+ <div className="navbar-collapse">
+ <ul class="navbar-nav ml-auto">
+ <li class="nav-item">
+ <Link class="nav-link" to="/modlog">Modlog</Link>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href={repoUrl}>Contribute</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href={repoUrl}>Code</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href={repoUrl}>About</a>
+ </li>
+ </ul>
+ </div>
+ </nav>
+ );
+ }
+}
+
diff --git a/ui/src/components/login.tsx b/ui/src/components/login.tsx
index 2d2339f5..e871acef 100644
--- a/ui/src/components/login.tsx
+++ b/ui/src/components/login.tsx
@@ -20,7 +20,8 @@ let emptyState: State = {
registerForm: {
username: undefined,
password: undefined,
- password_verify: undefined
+ password_verify: undefined,
+ admin: false,
},
loginLoading: false,
registerLoading: false
@@ -147,6 +148,7 @@ export class Login extends Component<any, State> {
}
handleRegisterSubmit(i: Login, event: any) {
+ event.preventDefault();
i.state.registerLoading = true;
i.setState(i.state);
event.preventDefault();
diff --git a/ui/src/components/main.tsx b/ui/src/components/main.tsx
index 55066d00..2badb23e 100644
--- a/ui/src/components/main.tsx
+++ b/ui/src/components/main.tsx
@@ -2,14 +2,15 @@ import { Component } from 'inferno';
import { Link } from 'inferno-router';
import { Subscription } from "rxjs";
import { retryWhen, delay, take } from 'rxjs/operators';
-import { UserOperation, CommunityUser, GetFollowedCommunitiesResponse, ListCommunitiesForm, ListCommunitiesResponse, Community, SortType } from '../interfaces';
+import { UserOperation, CommunityUser, GetFollowedCommunitiesResponse, ListCommunitiesForm, ListCommunitiesResponse, Community, SortType, GetSiteResponse } from '../interfaces';
import { WebSocketService, UserService } from '../services';
import { PostListings } from './post-listings';
-import { msgOp, repoUrl } from '../utils';
+import { msgOp, repoUrl, mdToHtml } from '../utils';
interface State {
subscribedCommunities: Array<CommunityUser>;
trendingCommunities: Array<Community>;
+ site: GetSiteResponse;
loading: boolean;
}
@@ -19,6 +20,21 @@ export class Main extends Component<any, State> {
private emptyState: State = {
subscribedCommunities: [],
trendingCommunities: [],
+ site: {
+ op: null,
+ site: {
+ id: null,
+ name: null,
+ creator_id: null,
+ creator_name: null,
+ published: null,
+ number_of_users: null,
+ number_of_posts: null,
+ number_of_comments: null,
+ },
+ admins: [],
+ banned: [],
+ },
loading: true
}
@@ -35,7 +51,9 @@ export class Main extends Component<any, State> {
() => console.log('complete')
);
- if (UserService.Instance.loggedIn) {
+ WebSocketService.Instance.getSite();
+
+ if (UserService.Instance.user) {
WebSocketService.Instance.getFollowedCommunities();
}
@@ -63,7 +81,7 @@ export class Main extends Component<any, State> {
<h4><svg class="icon icon-spinner spin"><use xlinkHref="#icon-spinner"></use></svg></h4> :
<div>
{this.trendingCommunities()}
- {UserService.Instance.loggedIn ?
+ {UserService.Instance.user && this.state.subscribedCommunities.length > 0 &&
<div>
<h4>Subscribed forums</h4>
<ul class="list-inline">
@@ -71,9 +89,9 @@ export class Main extends Component<any, State> {
<li class="list-inline-item"><Link to={`/community/${community.community_id}`}>{community.community_name}</Link></li>
)}
</ul>
- </div> :
- this.landing()
+ </div>
}
+ {this.landing()}
</div>
}
</div>
@@ -85,7 +103,7 @@ export class Main extends Component<any, State> {
trendingCommunities() {
return (
<div>
- <h4>Trending forums</h4>
+ <h4>Trending <Link class="text-white" to="/communities">forums</Link></h4>
<ul class="list-inline">
{this.state.trendingCommunities.map(community =>
<li class="list-inline-item"><Link to={`/community/${community.id}`}>{community.name}</Link></li>
@@ -98,6 +116,26 @@ export class Main extends Component<any, State> {
landing() {
return (
<div>
+ <h4>{`${this.state.site.site.name}`}</h4>
+ <ul class="my-1 list-inline">
+ <li className="list-inline-item badge badge-light">{this.state.site.site.number_of_users} Users</li>
+ <li className="list-inline-item badge badge-light">{this.state.site.site.number_of_posts} Posts</li>
+ <li className="list-inline-item badge badge-light">{this.state.site.site.number_of_comments} Comments</li>
+ <li className="list-inline-item"><Link className="badge badge-light" to="/modlog">Modlog</Link></li>
+ </ul>
+ <ul class="list-inline small">
+ <li class="list-inline-item">admins: </li>
+ {this.state.site.admins.map(admin =>
+ <li class="list-inline-item"><Link class="text-info" to={`/user/${admin.id}`}>{admin.name}</Link></li>
+ )}
+ </ul>
+ {this.state.site.site.description &&
+ <div>
+ <hr />
+ <div className="md-div" dangerouslySetInnerHTML={mdToHtml(this.state.site.site.description)} />
+ <hr />
+ </div>
+ }
<h4>Welcome to
<svg class="icon mx-2"><use xlinkHref="#icon-mouse"></use></svg>
<a href={repoUrl}>Lemmy<sup>Beta</sup></a>
@@ -127,7 +165,18 @@ export class Main extends Component<any, State> {
this.state.trendingCommunities = res.communities;
this.state.loading = false;
this.setState(this.state);
- }
+ } else if (op == UserOperation.GetSite) {
+ let res: GetSiteResponse = msg;
+
+ // This means it hasn't been set up yet
+ if (!res.site) {
+ this.context.router.history.push("/setup");
+ }
+ this.state.site.admins = res.admins;
+ this.state.site.site = res.site;
+ this.state.site.banned = res.banned;
+ this.setState(this.state);
+ }
}
}
diff --git a/ui/src/components/modlog.tsx b/ui/src/components/modlog.tsx
index 356cbc92..e4567885 100644
--- a/ui/src/components/modlog.tsx
+++ b/ui/src/components/modlog.tsx
@@ -9,34 +9,24 @@ import { MomentTime } from './moment-time';
import * as moment from 'moment';
interface ModlogState {
- removed_posts: Array<ModRemovePost>,
- locked_posts: Array<ModLockPost>,
- removed_comments: Array<ModRemoveComment>,
- removed_communities: Array<ModRemoveCommunity>,
- banned_from_community: Array<ModBanFromCommunity>,
- banned: Array<ModBan>,
- added_to_community: Array<ModAddCommunity>,
- added: Array<ModAdd>,
+ combined: Array<{type_: string, data: ModRemovePost | ModLockPost | ModRemoveCommunity}>,
+ communityId?: number,
+ communityName?: string,
loading: boolean;
}
export class Modlog extends Component<any, ModlogState> {
private subscription: Subscription;
private emptyState: ModlogState = {
- removed_posts: [],
- locked_posts: [],
- removed_comments: [],
- removed_communities: [],
- banned_from_community: [],
- banned: [],
- added_to_community: [],
- added: [],
- loading: true
+ combined: [],
+ 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.subscription = WebSocketService.Instance.subject
.pipe(retryWhen(errors => errors.pipe(delay(3000), take(10))))
.subscribe(
@@ -46,7 +36,7 @@ export class Modlog extends Component<any, ModlogState> {
);
let modlogForm: GetModlogForm = {
-
+ community_id: this.state.communityId
};
WebSocketService.Instance.getModlog(modlogForm);
}
@@ -55,30 +45,35 @@ export class Modlog extends Component<any, ModlogState> {
this.subscription.unsubscribe();
}
- combined() {
- let combined: Array<{type_: string, data: ModRemovePost | ModLockPost | ModRemoveCommunity}> = [];
- let removed_posts = addTypeInfo(this.state.removed_posts, "removed_posts");
- let locked_posts = addTypeInfo(this.state.locked_posts, "locked_posts");
- let removed_comments = addTypeInfo(this.state.removed_comments, "removed_comments");
- let removed_communities = addTypeInfo(this.state.removed_communities, "removed_communities");
- let banned_from_community = addTypeInfo(this.state.banned_from_community, "banned_from_community");
- let added_to_community = addTypeInfo(this.state.added_to_community, "added_to_community");
-
- combined.push(...removed_posts);
- combined.push(...locked_posts);
- combined.push(...removed_comments);
- combined.push(...removed_communities);
- combined.push(...banned_from_community);
- combined.push(...added_to_community);
+ setCombined(res: GetModlogResponse) {
+ let removed_posts = addTypeInfo(res.removed_posts, "removed_posts");
+ let locked_posts = addTypeInfo(res.locked_posts, "locked_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");
+
+ this.state.combined.push(...removed_posts);
+ this.state.combined.push(...locked_posts);
+ this.state.combined.push(...removed_comments);
+ this.state.combined.push(...removed_communities);
+ this.state.combined.push(...banned_from_community);
+ this.state.combined.push(...added_to_community);
+
+ if (this.state.communityId && this.state.combined.length > 0) {
+ this.state.communityName = this.state.combined[0].data.community_name;
+ }
// Sort them by time
- combined.sort((a, b) => b.data.when_.localeCompare(a.data.when_));
+ this.state.combined.sort((a, b) => b.data.when_.localeCompare(a.data.when_));
- console.log(combined);
+ this.setState(this.state);
+ }
+ combined() {
return (
<tbody>
- {combined.map(i =>
+ {this.state.combined.map(i =>
<tr>
<td><MomentTime data={i.data} /></td>
<td><Link to={`/user/${i.data.mod_user_id}`}>{i.data.mod_user_name}</Link></td>
@@ -143,7 +138,10 @@ export class Modlog extends Component<any, ModlogState> {
{this.state.loading ?
<h4 class=""><svg class="icon icon-spinner spin"><use xlinkHref="#icon-spinner"></use></svg></h4> :
<div>
- <h4>Modlog</h4>
+ <h4>
+ {this.state.communityName && <Link className="text-white" to={`/community/${this.state.communityId}`}>/f/{this.state.communityName} </Link>}
+ <span>Modlog</span>
+ </h4>
<div class="table-responsive">
<table id="modlog_table" class="table table-sm table-hover">
<thead class="pointer">
@@ -171,14 +169,7 @@ export class Modlog extends Component<any, ModlogState> {
} else if (op == UserOperation.GetModlog) {
let res: GetModlogResponse = msg;
this.state.loading = false;
- this.state.removed_posts = res.removed_posts;
- this.state.locked_posts = res.locked_posts;
- this.state.removed_comments = res.removed_comments;
- this.state.removed_communities = res.removed_communities;
- this.state.banned_from_community = res.banned_from_community;
- this.state.added_to_community = res.added_to_community;
-
- this.setState(this.state);
+ this.setCombined(res);
}
}
}
diff --git a/ui/src/components/navbar.tsx b/ui/src/components/navbar.tsx
index 64bf6e01..ae693825 100644
--- a/ui/src/components/navbar.tsx
+++ b/ui/src/components/navbar.tsx
@@ -1,6 +1,5 @@
import { Component, linkEvent } from 'inferno';
import { Link } from 'inferno-router';
-import { repoUrl } from '../utils';
import { UserService } from '../services';
import { version } from '../version';
@@ -13,7 +12,7 @@ interface NavbarState {
export class Navbar extends Component<any, NavbarState> {
emptyState: NavbarState = {
- isLoggedIn: UserService.Instance.loggedIn,
+ isLoggedIn: UserService.Instance.user !== undefined,
expanded: false,
expandUserDropdown: false
}
@@ -51,9 +50,6 @@ export class Navbar extends Component<any, NavbarState> {
<div className={`${!this.state.expanded && 'collapse'} navbar-collapse`}>
<ul class="navbar-nav mr-auto">
<li class="nav-item">
- <a class="nav-link" href={repoUrl}>About</a>
- </li>
- <li class="nav-item">
<Link class="nav-link" to="/communities">Forums</Link>
</li>
<li class="nav-item">
diff --git a/ui/src/components/post-form.tsx b/ui/src/components/post-form.tsx
index b2042c1f..b8ea359f 100644
--- a/ui/src/components/post-form.tsx
+++ b/ui/src/components/post-form.tsx
@@ -27,7 +27,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
name: null,
auth: null,
community_id: null,
- creator_id: UserService.Instance.loggedIn ? UserService.Instance.user.id : null
+ creator_id: (UserService.Instance.user) ? UserService.Instance.user.id : null,
},
communities: [],
loading: false
@@ -95,7 +95,9 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
<textarea value={this.state.postForm.body} onInput={linkEvent(this, this.handlePostBodyChange)} class="form-control" rows={4} />
</div>
</div>
- <div class="form-group row">
+ {/* Cant change a community from an edit */}
+ {!this.props.post &&
+ <div class="form-group row">
<label class="col-sm-2 col-form-label">Forum</label>
<div class="col-sm-10">
<select class="form-control" value={this.state.postForm.community_id} onInput={linkEvent(this, this.handlePostCommunityChange)}>
@@ -104,7 +106,8 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
)}
</select>
</div>
- </div>
+ </div>
+ }
<div class="form-group row">
<div class="col-sm-10">
<button type="submit" class="btn btn-secondary mr-2">
diff --git a/ui/src/components/post-listing.tsx b/ui/src/components/post-listing.tsx
index d2bfc7bd..46e2a994 100644
--- a/ui/src/components/post-listing.tsx
+++ b/ui/src/components/post-listing.tsx
@@ -160,7 +160,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
}
private get myPost(): boolean {
- return UserService.Instance.loggedIn && this.props.post.creator_id == UserService.Instance.user.id;
+ return UserService.Instance.user && this.props.post.creator_id == UserService.Instance.user.id;
}
handlePostLike(i: PostListing) {
@@ -220,6 +220,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
}
handleModRemoveSubmit(i: PostListing) {
+ event.preventDefault();
let form: PostFormI = {
name: i.props.post.name,
community_id: i.props.post.community_id,
diff --git a/ui/src/components/post-listings.tsx b/ui/src/components/post-listings.tsx
index ce7833b2..34814400 100644
--- a/ui/src/components/post-listings.tsx
+++ b/ui/src/components/post-listings.tsx
@@ -43,7 +43,7 @@ export class PostListings extends Component<PostListingsProps, PostListingsState
sortType: SortType.Hot,
type_: this.props.communityId
? ListingType.Community
- : UserService.Instance.loggedIn
+ : UserService.Instance.user
? ListingType.Subscribed
: ListingType.All,
loading: true
@@ -86,7 +86,7 @@ export class PostListings extends Component<PostListingsProps, PostListingsState
{this.state.posts.length > 0
? this.state.posts.map(post =>
<PostListing post={post} showCommunity={!this.props.communityId}/>)
- : <div>No Listings. Subscribe to some <Link to="/communities">forums</Link>.</div>
+ : <div>No Listings. {!this.props.communityId && <span>Subscribe to some <Link to="/communities">forums</Link>.</span>}</div>
}
</div>
}
@@ -109,7 +109,7 @@ export class PostListings extends Component<PostListingsProps, PostListingsState
<option value={SortType.TopAll}>All</option>
</select>
{!this.props.communityId &&
- UserService.Instance.loggedIn &&
+ UserService.Instance.user &&
<select value={this.state.type_} onChange={linkEvent(this, this.handleTypeChange)} class="ml-2 custom-select w-auto">
<option disabled>Type</option>
<option value={ListingType.All}>All</option>
diff --git a/ui/src/components/post.tsx b/ui/src/components/post.tsx
index c65f463d..d79a6c97 100644
--- a/ui/src/components/post.tsx
+++ b/ui/src/components/post.tsx
@@ -79,14 +79,14 @@ export class Post extends Component<any, PostState> {
{this.state.loading ?
<h4><svg class="icon icon-spinner spin"><use xlinkHref="#icon-spinner"></use></svg></h4> :
<div class="row">
- <div class="col-12 col-sm-8 col-lg-7 mb-3">
+ <div class="col-12 col-md-8 col-lg-7 mb-3">
<PostListing post={this.state.post} showBody showCommunity editable />
<div className="mb-2" />
<CommentForm postId={this.state.post.id} disabled={this.state.post.locked} />
{this.sortRadios()}
{this.commentsTree()}
</div>
- <div class="col-12 col-sm-4 col-lg-3 mb-3">
+ <div class="col-12 col-md-4 col-lg-3 mb-3 d-none d-md-block">
{this.state.comments.length > 0 && this.newComments()}
</div>
<div class="col-12 col-sm-12 col-lg-2">
diff --git a/ui/src/components/setup.tsx b/ui/src/components/setup.tsx
new file mode 100644
index 00000000..94480ee8
--- /dev/null
+++ b/ui/src/components/setup.tsx
@@ -0,0 +1,147 @@
+import { Component, linkEvent } from 'inferno';
+import { Subscription } from "rxjs";
+import { retryWhen, delay, take } from 'rxjs/operators';
+import { RegisterForm, LoginResponse, UserOperation } from '../interfaces';
+import { WebSocketService, UserService } from '../services';
+import { msgOp } from '../utils';
+import { SiteForm } from './site-form';
+
+interface State {
+ userForm: RegisterForm;
+ doneRegisteringUser: boolean;
+ userLoading: boolean;
+}
+
+export class Setup extends Component<any, State> {
+ private subscription: Subscription;
+
+ private emptyState: State = {
+ userForm: {
+ username: undefined,
+ password: undefined,
+ password_verify: undefined,
+ admin: true,
+ },
+ doneRegisteringUser: false,
+ userLoading: false,
+ }
+
+
+ constructor(props: any, context: any) {
+ super(props, context);
+
+ this.state = this.emptyState;
+
+ this.subscription = WebSocketService.Instance.subject
+ .pipe(retryWhen(errors => errors.pipe(delay(3000), take(10))))
+ .subscribe(
+ (msg) => this.parseMessage(msg),
+ (err) => console.error(err),
+ () => console.log("complete")
+ );
+ }
+
+ componentWillUnmount() {
+ this.subscription.unsubscribe();
+ }
+
+ render() {
+ return (
+ <div class="container">
+ <div class="row">
+ <div class="col-12 offset-lg-3 col-lg-6">
+ <h3>Lemmy Instance Setup</h3>
+ {!this.state.doneRegisteringUser ? this.registerUser() : <SiteForm />}
+ </div>
+ </div>
+ </div>
+ )
+ }
+
+ registerUser() {
+ return (
+ <form onSubmit={linkEvent(this, this.handleRegisterSubmit)}>
+ <h4>Set up Site Administrator</h4>
+ <div class="form-group row">
+ <label class="col-sm-2 col-form-label">Username</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} pattern="[a-zA-Z0-9_]+" />
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-2 col-form-label">Email</label>
+ <div class="col-sm-10">
+ <input type="email" class="form-control" placeholder="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">Password</label>
+ <div class="col-sm-10">
+ <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">Verify Password</label>
+ <div class="col-sm-10">
+ <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> : 'Sign Up'}</button>
+
+ </div>
+ </div>
+ </form>
+ );
+ }
+
+
+ handleRegisterSubmit(i: Setup, event: any) {
+ event.preventDefault();
+ i.state.userLoading = true;
+ i.setState(i.state);
+ event.preventDefault();
+ WebSocketService.Instance.register(i.state.userForm);
+ }
+
+ handleRegisterUsernameChange(i: Setup, event: any) {
+ i.state.userForm.username = event.target.value;
+ i.setState(i.state);
+ }
+
+ handleRegisterEmailChange(i: Setup, event: any) {
+ i.state.userForm.email = event.target.value;
+ i.setState(i.state);
+ }
+
+ handleRegisterPasswordChange(i: Setup, event: any) {
+ i.state.userForm.password = event.target.value;
+ i.setState(i.state);
+ }
+
+ handleRegisterPasswordVerifyChange(i: Setup, event: any) {
+ i.state.userForm.password_verify = event.target.value;
+ i.setState(i.state);
+ }
+
+ parseMessage(msg: any) {
+ let op: UserOperation = msgOp(msg);
+ if (msg.error) {
+ alert(msg.error);
+ this.state.userLoading = false;
+ this.setState(this.state);
+ return;
+ } else if (op == UserOperation.Register) {
+ this.state.userLoading = false;
+ this.state.doneRegisteringUser = true;
+ let res: LoginResponse = msg;
+ UserService.Instance.login(res);
+ console.log(res);
+ this.setState(this.state);
+ } else if (op == UserOperation.CreateSite) {
+ this.props.history.push('/');
+ }
+ }
+}
diff --git a/ui/src/components/sidebar.tsx b/ui/src/components/sidebar.tsx
index 6640d84a..b0c0b7b9 100644
--- a/ui/src/components/sidebar.tsx
+++ b/ui/src/components/sidebar.tsx
@@ -87,11 +87,18 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
</div>
</form>
}
- <ul class="mt-1 list-inline">
+ <ul class="my-1 list-inline">
<li className="list-inline-item"><Link className="badge badge-light" to="/communities">{community.category_name}</Link></li>
<li className="list-inline-item badge badge-light">{community.number_of_subscribers} Subscribers</li>
<li className="list-inline-item badge badge-light">{community.number_of_posts} Posts</li>
<li className="list-inline-item badge badge-light">{community.number_of_comments} Comments</li>
+ <li className="list-inline-item"><Link className="badge badge-light" to={`/modlog/community/${this.props.community.id}`}>Modlog</Link></li>
+ </ul>
+ <ul class="list-inline small">
+ <li class="list-inline-item">mods: </li>