1 import { Component, linkEvent } from 'inferno';
2 import { Link } from 'inferno-router';
10 AddModToCommunityForm,
11 } from '../interfaces';
12 import { WebSocketService, UserService } from '../services';
13 import { mdToHtml, getUnixTime } from '../utils';
14 import { CommunityForm } from './community-form';
15 import { UserListing } from './user-listing';
16 import { CommunityLink } from './community-link';
17 import { BannerIconHeader } from './banner-icon-header';
18 import { i18n } from '../i18next';
20 interface SidebarProps {
22 moderators: Array<CommunityUser>;
23 admins: Array<UserView>;
29 interface SidebarState {
31 showRemoveDialog: boolean;
33 removeExpires: string;
34 showConfirmLeaveModTeam: boolean;
37 export class Sidebar extends Component<SidebarProps, SidebarState> {
38 private emptyState: SidebarState = {
40 showRemoveDialog: false,
43 showConfirmLeaveModTeam: false,
46 constructor(props: any, context: any) {
47 super(props, context);
48 this.state = this.emptyState;
49 this.handleEditCommunity = this.handleEditCommunity.bind(this);
50 this.handleEditCancel = this.handleEditCancel.bind(this);
56 {!this.state.showEdit ? (
60 community={this.props.community}
61 onEdit={this.handleEditCommunity}
62 onCancel={this.handleEditCancel}
63 enableNsfw={this.props.enableNsfw}
73 <div class="card bg-transparent border-secondary mb-3">
74 <div class="card-header bg-transparent border-secondary">
75 {this.communityTitle()}
78 <div class="card-body">{this.subscribes()}</div>
80 <div class="card bg-transparent border-secondary mb-3">
81 <div class="card-body">
92 let community = this.props.community;
96 {this.props.showIcon && (
97 <BannerIconHeader icon={community.icon} banner={community.banner} />
99 <span>{community.title}</span>
100 {community.removed && (
101 <small className="ml-2 text-muted font-italic">
105 {community.deleted && (
106 <small className="ml-2 text-muted font-italic">
111 <small className="ml-2 text-muted font-italic">
117 community={community}
128 let community = this.props.community;
130 <ul class="my-1 list-inline">
131 <li className="list-inline-item badge badge-light">
132 {i18n.t('number_online', { count: this.props.online })}
134 <li className="list-inline-item badge badge-light">
135 {i18n.t('number_of_subscribers', {
136 count: community.number_of_subscribers,
139 <li className="list-inline-item badge badge-light">
140 {i18n.t('number_of_posts', {
141 count: community.number_of_posts,
144 <li className="list-inline-item badge badge-light">
145 {i18n.t('number_of_comments', {
146 count: community.number_of_comments,
149 <li className="list-inline-item">
150 <Link className="badge badge-light" to="/communities">
151 {community.category_name}
154 <li className="list-inline-item">
156 className="badge badge-light"
157 to={`/modlog/community/${this.props.community.id}`}
162 <li className="list-inline-item badge badge-light">
163 <CommunityLink community={community} realLink />
171 <ul class="list-inline small">
172 <li class="list-inline-item">{i18n.t('mods')}: </li>
173 {this.props.moderators.map(mod => (
174 <li class="list-inline-item">
178 preferred_username: mod.user_preferred_username,
181 local: mod.user_local,
182 actor_id: mod.user_actor_id,
192 let community = this.props.community;
194 <div class="d-flex flex-wrap">
196 class={`btn btn-secondary flex-fill mr-2 mb-2 ${
197 community.deleted || community.removed ? 'no-click' : ''
199 to={`/create_post?community=${community.name}`}
201 {i18n.t('create_a_post')}
203 {community.subscribed ? (
205 class="btn btn-secondary flex-fill mb-2"
207 onClick={linkEvent(community.id, this.handleUnsubscribe)}
209 {i18n.t('unsubscribe')}
213 class="btn btn-secondary flex-fill mb-2"
215 onClick={linkEvent(community.id, this.handleSubscribe)}
217 {i18n.t('subscribe')}
225 let community = this.props.community;
227 community.description && (
230 dangerouslySetInnerHTML={mdToHtml(community.description)}
237 let community = this.props.community;
240 <ul class="list-inline mb-1 text-muted font-weight-bold">
243 <li className="list-inline-item-action">
246 onClick={linkEvent(this, this.handleEditClick)}
247 data-tippy-content={i18n.t('edit')}
249 <svg class="icon icon-inline">
250 <use xlinkHref="#icon-edit"></use>
255 (!this.state.showConfirmLeaveModTeam ? (
256 <li className="list-inline-item-action">
261 this.handleShowConfirmLeaveModTeamClick
264 {i18n.t('leave_mod_team')}
269 <li className="list-inline-item-action">
270 {i18n.t('are_you_sure')}
272 <li className="list-inline-item-action">
275 onClick={linkEvent(this, this.handleLeaveModTeamClick)}
280 <li className="list-inline-item-action">
285 this.handleCancelLeaveModTeamClick
294 <li className="list-inline-item-action">
297 onClick={linkEvent(this, this.handleDeleteClick)}
299 !community.deleted ? i18n.t('delete') : i18n.t('restore')
303 class={`icon icon-inline ${
304 community.deleted && 'text-danger'
307 <use xlinkHref="#icon-trash"></use>
315 <li className="list-inline-item">
316 {!this.props.community.removed ? (
319 onClick={linkEvent(this, this.handleModRemoveShow)}
326 onClick={linkEvent(this, this.handleModRemoveSubmit)}
334 {this.state.showRemoveDialog && (
335 <form onSubmit={linkEvent(this, this.handleModRemoveSubmit)}>
336 <div class="form-group row">
337 <label class="col-form-label" htmlFor="remove-reason">
343 class="form-control mr-2"
344 placeholder={i18n.t('optional')}
345 value={this.state.removeReason}
346 onInput={linkEvent(this, this.handleModRemoveReasonChange)}
349 {/* TODO hold off on expires for now */}
350 {/* <div class="form-group row"> */}
351 {/* <label class="col-form-label">Expires</label> */}
352 {/* <input type="date" class="form-control mr-2" placeholder={i18n.t('expires')} value={this.state.removeExpires} onInput={linkEvent(this, this.handleModRemoveExpiresChange)} /> */}
354 <div class="form-group row">
355 <button type="submit" class="btn btn-secondary">
356 {i18n.t('remove_community')}
365 handleEditClick(i: Sidebar) {
366 i.state.showEdit = true;
370 handleEditCommunity() {
371 this.state.showEdit = false;
372 this.setState(this.state);
376 this.state.showEdit = false;
377 this.setState(this.state);
380 handleDeleteClick(i: Sidebar) {
381 event.preventDefault();
382 let deleteForm: DeleteCommunityForm = {
383 edit_id: i.props.community.id,
384 deleted: !i.props.community.deleted,
386 WebSocketService.Instance.deleteCommunity(deleteForm);
389 handleShowConfirmLeaveModTeamClick(i: Sidebar) {
390 i.state.showConfirmLeaveModTeam = true;
394 handleLeaveModTeamClick(i: Sidebar) {
395 let form: AddModToCommunityForm = {
396 user_id: UserService.Instance.user.id,
397 community_id: i.props.community.id,
400 WebSocketService.Instance.addModToCommunity(form);
401 i.state.showConfirmLeaveModTeam = false;
405 handleCancelLeaveModTeamClick(i: Sidebar) {
406 i.state.showConfirmLeaveModTeam = false;
410 handleUnsubscribe(communityId: number) {
411 event.preventDefault();
412 let form: FollowCommunityForm = {
413 community_id: communityId,
416 WebSocketService.Instance.followCommunity(form);
419 handleSubscribe(communityId: number) {
420 event.preventDefault();
421 let form: FollowCommunityForm = {
422 community_id: communityId,
425 WebSocketService.Instance.followCommunity(form);
428 private get amCreator(): boolean {
429 return this.props.community.creator_id == UserService.Instance.user.id;
432 get canMod(): boolean {
434 UserService.Instance.user &&
435 this.props.moderators
437 .includes(UserService.Instance.user.id)
441 get canAdmin(): boolean {
443 UserService.Instance.user &&
444 this.props.admins.map(a => a.id).includes(UserService.Instance.user.id)
448 handleModRemoveShow(i: Sidebar) {
449 i.state.showRemoveDialog = true;
453 handleModRemoveReasonChange(i: Sidebar, event: any) {
454 i.state.removeReason = event.target.value;
458 handleModRemoveExpiresChange(i: Sidebar, event: any) {
459 console.log(event.target.value);
460 i.state.removeExpires = event.target.value;
464 handleModRemoveSubmit(i: Sidebar) {
465 event.preventDefault();
466 let removeForm: RemoveCommunityForm = {
467 edit_id: i.props.community.id,
468 removed: !i.props.community.removed,
469 reason: i.state.removeReason,
470 expires: getUnixTime(i.state.removeExpires),
472 WebSocketService.Instance.removeCommunity(removeForm);
474 i.state.showRemoveDialog = false;