]> Untitled Git - lemmy.git/blob - ui/src/components/sidebar.tsx
Add site editing.
[lemmy.git] / ui / src / components / sidebar.tsx
1 import { Component, linkEvent } from 'inferno';
2 import { Link } from 'inferno-router';
3 import { Community, CommunityUser, FollowCommunityForm, CommunityForm as CommunityFormI, UserView } from '../interfaces';
4 import { WebSocketService, UserService } from '../services';
5 import { mdToHtml, getUnixTime } from '../utils';
6 import { CommunityForm } from './community-form';
7
8 interface SidebarProps {
9   community: Community;
10   moderators: Array<CommunityUser>;
11   admins: Array<UserView>;
12 }
13
14 interface SidebarState {
15   showEdit: boolean;
16   showRemoveDialog: boolean;
17   removeReason: string;
18   removeExpires: string;
19 }
20
21 export class Sidebar extends Component<SidebarProps, SidebarState> {
22
23   private emptyState: SidebarState = {
24     showEdit: false,
25     showRemoveDialog: false,
26     removeReason: null,
27     removeExpires: null
28   }
29
30   constructor(props: any, context: any) {
31     super(props, context);
32     this.state = this.emptyState;
33     this.handleEditCommunity = this.handleEditCommunity.bind(this);
34     this.handleEditCancel = this.handleEditCancel.bind(this);
35   }
36
37   render() {
38     return (
39       <div>
40         {!this.state.showEdit 
41           ? this.sidebar()
42           : <CommunityForm 
43           community={this.props.community} 
44           onEdit={this.handleEditCommunity} 
45           onCancel={this.handleEditCancel} />
46         }
47       </div>
48     )
49   }
50
51   sidebar() {
52     let community = this.props.community;
53     return (
54       <div>
55         <h5 className="mb-0">{community.title}
56         {community.removed &&
57           <small className="ml-2 text-muted font-italic">removed</small>
58         }
59       </h5>
60       <Link className="text-muted" to={`/community/${community.id}`}>/f/{community.name}</Link>
61       <ul class="list-inline mb-1 text-muted small font-weight-bold"> 
62         {this.canMod && 
63           <>
64             <li className="list-inline-item">
65               <span class="pointer" onClick={linkEvent(this, this.handleEditClick)}>edit</span>
66             </li>
67             {this.amCreator && 
68               <li className="list-inline-item">
69                 {/* <span class="pointer" onClick={linkEvent(this, this.handleDeleteClick)}>delete</span> */}
70               </li>
71             }
72           </>
73         }
74         {this.canAdmin &&
75           <li className="list-inline-item">
76             {!this.props.community.removed ? 
77             <span class="pointer" onClick={linkEvent(this, this.handleModRemoveShow)}>remove</span> :
78             <span class="pointer" onClick={linkEvent(this, this.handleModRemoveSubmit)}>restore</span>
79             }
80           </li>
81
82         }
83       </ul>
84       {this.state.showRemoveDialog && 
85         <form onSubmit={linkEvent(this, this.handleModRemoveSubmit)}>
86           <div class="form-group row">
87             <label class="col-form-label">Reason</label>
88             <input type="text" class="form-control mr-2" placeholder="Optional" value={this.state.removeReason} onInput={linkEvent(this, this.handleModRemoveReasonChange)} />
89           </div>
90           <div class="form-group row">
91             <label class="col-form-label">Expires</label>
92             <input type="date" class="form-control mr-2" placeholder="Expires" value={this.state.removeExpires} onInput={linkEvent(this, this.handleModRemoveExpiresChange)} />
93           </div>
94           <div class="form-group row">
95             <button type="submit" class="btn btn-secondary">Remove Community</button>
96           </div>
97         </form>
98       }
99       <ul class="my-1 list-inline">
100         <li className="list-inline-item"><Link className="badge badge-light" to="/communities">{community.category_name}</Link></li>
101         <li className="list-inline-item badge badge-light">{community.number_of_subscribers} Subscribers</li>
102         <li className="list-inline-item badge badge-light">{community.number_of_posts} Posts</li>
103         <li className="list-inline-item badge badge-light">{community.number_of_comments} Comments</li>
104         <li className="list-inline-item"><Link className="badge badge-light" to={`/modlog/community/${this.props.community.id}`}>Modlog</Link></li>
105       </ul>
106       <ul class="list-inline small"> 
107         <li class="list-inline-item">mods: </li>
108         {this.props.moderators.map(mod =>
109           <li class="list-inline-item"><Link class="text-info" to={`/user/${mod.user_id}`}>{mod.user_name}</Link></li>
110         )}
111       </ul>
112       <div>
113         {community.subscribed 
114           ? <button class="btn btn-sm btn-secondary" onClick={linkEvent(community.id, this.handleUnsubscribe)}>Unsubscribe</button>
115           : <button class="btn btn-sm btn-secondary" onClick={linkEvent(community.id, this.handleSubscribe)}>Subscribe</button>
116         }
117       </div>
118       {community.description && 
119         <div>
120           <hr />
121           <div className="md-div" dangerouslySetInnerHTML={mdToHtml(community.description)} />
122           <hr />
123         </div>
124       }
125     </div>
126     );
127   }
128
129   handleEditClick(i: Sidebar) {
130     i.state.showEdit = true;
131     i.setState(i.state);
132   }
133
134   handleEditCommunity() {
135     this.state.showEdit = false;
136     this.setState(this.state);
137   }
138
139   handleEditCancel() {
140     this.state.showEdit = false;
141     this.setState(this.state);
142   }
143
144   // TODO no deleting communities yet
145   // handleDeleteClick(i: Sidebar, event) {
146   // }
147
148   handleUnsubscribe(communityId: number) {
149     let form: FollowCommunityForm = {
150       community_id: communityId,
151       follow: false
152     };
153     WebSocketService.Instance.followCommunity(form);
154   }
155
156   handleSubscribe(communityId: number) {
157     let form: FollowCommunityForm = {
158       community_id: communityId,
159       follow: true
160     };
161     WebSocketService.Instance.followCommunity(form);
162   }
163
164   private get amCreator(): boolean {
165     return this.props.community.creator_id == UserService.Instance.user.id;
166   }
167
168   get canMod(): boolean {
169     return UserService.Instance.user && this.props.moderators.map(m => m.user_id).includes(UserService.Instance.user.id);
170   }
171
172   get canAdmin(): boolean {
173     return UserService.Instance.user && this.props.admins.map(a => a.id).includes(UserService.Instance.user.id);
174   }
175
176   handleDeleteClick() {
177   }
178
179   handleModRemoveShow(i: Sidebar) {
180     i.state.showRemoveDialog = true;
181     i.setState(i.state);
182   }
183
184   handleModRemoveReasonChange(i: Sidebar, event: any) {
185     i.state.removeReason = event.target.value;
186     i.setState(i.state);
187   }
188
189   handleModRemoveExpiresChange(i: Sidebar, event: any) {
190     console.log(event.target.value);
191     i.state.removeExpires = event.target.value;
192     i.setState(i.state);
193   }
194
195   handleModRemoveSubmit(i: Sidebar) {
196     event.preventDefault();
197     let deleteForm: CommunityFormI = {
198       name: i.props.community.name,
199       title: i.props.community.title,
200       category_id: i.props.community.category_id,
201       edit_id: i.props.community.id,
202       removed: !i.props.community.removed,
203       reason: i.state.removeReason,
204       expires: getUnixTime(i.state.removeExpires),
205       auth: null,
206     };
207     WebSocketService.Instance.editCommunity(deleteForm);
208
209     i.state.showRemoveDialog = false;
210     i.setState(i.state);
211   }
212 }