diff options
Diffstat (limited to 'ui/src/components')
-rw-r--r-- | ui/src/components/comment-form.tsx | 3 | ||||
-rw-r--r-- | ui/src/components/comment-node.tsx | 6 | ||||
-rw-r--r-- | ui/src/components/comment-nodes.tsx | 2 | ||||
-rw-r--r-- | ui/src/components/communities.tsx | 16 | ||||
-rw-r--r-- | ui/src/components/footer.tsx | 36 | ||||
-rw-r--r-- | ui/src/components/login.tsx | 4 | ||||
-rw-r--r-- | ui/src/components/main.tsx | 65 | ||||
-rw-r--r-- | ui/src/components/modlog.tsx | 81 | ||||
-rw-r--r-- | ui/src/components/navbar.tsx | 6 | ||||
-rw-r--r-- | ui/src/components/post-form.tsx | 9 | ||||
-rw-r--r-- | ui/src/components/post-listing.tsx | 3 | ||||
-rw-r--r-- | ui/src/components/post-listings.tsx | 6 | ||||
-rw-r--r-- | ui/src/components/post.tsx | 4 | ||||
-rw-r--r-- | ui/src/components/setup.tsx | 147 | ||||
-rw-r--r-- | ui/src/components/sidebar.tsx | 21 | ||||
-rw-r--r-- | ui/src/components/site-form.tsx | 86 |
16 files changed, 405 insertions, 90 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> + {this.props.moderators.map(mod => + <li class="list-inline-item"><Link class="text-info" to={`/user/${mod.user_id}`}>{mod.user_name}</Link></li> + )} </ul> <div> {community.subscribed @@ -103,15 +110,9 @@ export class Sidebar extends Component<SidebarProps, SidebarState> { <div> <hr /> <div className="md-div" dangerouslySetInnerHTML={mdToHtml(community.description)} /> + <hr /> </div> } - <hr /> - <h4>Moderators</h4> - <ul class="list-inline"> - {this.props.moderators.map(mod => - <li class="list-inline |