Modlog, admin-settings, search, and user done.

This commit is contained in:
Dessalines 2020-09-08 21:40:36 -05:00
parent 95b74ad74c
commit bea7a37983
6 changed files with 170 additions and 133 deletions

View File

@ -1,7 +1,6 @@
import { Component, linkEvent } from 'inferno';
import { Helmet } from 'inferno-helmet';
import { Subscription } from 'rxjs';
import { retryWhen, delay, take } from 'rxjs/operators';
import {
UserOperation,
SiteResponse,
@ -9,9 +8,20 @@ import {
SiteConfigForm,
GetSiteConfigResponse,
WebSocketJsonResponse,
GetSiteConfig,
} from 'lemmy-js-client';
import { WebSocketService } from '../services';
import { wsJsonToRes, capitalizeFirstLetter, toast, randomStr } from '../utils';
import {
wsJsonToRes,
capitalizeFirstLetter,
toast,
randomStr,
setIsoData,
wsSubscribe,
isBrowser,
lemmyHttp,
setAuth,
} from '../utils';
import autosize from 'autosize';
import { SiteForm } from './site-form';
import { UserListing } from './user-listing';
@ -27,29 +37,10 @@ interface AdminSettingsState {
export class AdminSettings extends Component<any, AdminSettingsState> {
private siteConfigTextAreaId = `site-config-${randomStr()}`;
private isoData = setIsoData(this.context);
private subscription: Subscription;
private emptyState: AdminSettingsState = {
siteRes: {
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,
number_of_communities: null,
enable_downvotes: null,
open_registration: null,
enable_nsfw: null,
},
admins: [],
banned: [],
online: null,
version: null,
federated_instances: null,
},
siteRes: this.isoData.site,
siteConfigForm: {
config_hjson: null,
auth: null,
@ -66,28 +57,41 @@ export class AdminSettings extends Component<any, AdminSettingsState> {
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')
);
this.parseMessage = this.parseMessage.bind(this);
this.subscription = wsSubscribe(this.parseMessage);
WebSocketService.Instance.getSite();
WebSocketService.Instance.getSiteConfig();
// Only fetch the data if coming from another route
if (this.isoData.path == this.context.router.route.match.url) {
this.state.siteConfigRes = this.isoData.routeData[0];
this.state.siteConfigForm.config_hjson = this.state.siteConfigRes.config_hjson;
this.state.siteConfigLoading = false;
this.state.loading = false;
} else {
WebSocketService.Instance.getSiteConfig();
}
}
static fetchInitialData(auth: string, _path: string): Promise<any>[] {
let form: GetSiteConfig = {};
setAuth(form, auth);
return [lemmyHttp.getSiteConfig(form)];
}
componentDidMount() {
if (isBrowser()) {
var textarea: any = document.getElementById(this.siteConfigTextAreaId);
autosize(textarea);
}
}
componentWillUnmount() {
this.subscription.unsubscribe();
if (isBrowser()) {
this.subscription.unsubscribe();
}
}
get documentTitle(): string {
if (this.state.siteRes.site.name) {
return `${i18n.t('admin_settings')} - ${this.state.siteRes.site.name}`;
} else {
return 'Lemmy';
}
return `${i18n.t('admin_settings')} - ${this.state.siteRes.site.name}`;
}
render() {
@ -226,15 +230,6 @@ export class AdminSettings extends Component<any, AdminSettingsState> {
this.setState(this.state);
return;
} else if (msg.reconnect) {
} else if (res.op == UserOperation.GetSite) {
let data = res.data as GetSiteResponse;
// This means it hasn't been set up yet
if (!data.site) {
this.context.router.history.push('/setup');
}
this.state.siteRes = data;
this.setState(this.state);
} else if (res.op == UserOperation.EditSite) {
let data = res.data as SiteResponse;
this.state.siteRes.site = data.site;

View File

@ -2,7 +2,6 @@ import { Component, linkEvent } from 'inferno';
import { Helmet } from 'inferno-helmet';
import { Link } from 'inferno-router';
import { Subscription } from 'rxjs';
import { retryWhen, delay, take } from 'rxjs/operators';
import {
UserOperation,
GetModlogForm,
@ -17,11 +16,19 @@ import {
ModAddCommunity,
ModAdd,
WebSocketJsonResponse,
GetSiteResponse,
Site,
} from 'lemmy-js-client';
import { WebSocketService } from '../services';
import { wsJsonToRes, addTypeInfo, fetchLimit, toast } from '../utils';
import {
wsJsonToRes,
addTypeInfo,
fetchLimit,
toast,
setIsoData,
wsSubscribe,
isBrowser,
lemmyHttp,
} from '../utils';
import { MomentTime } from './moment-time';
import moment from 'moment';
import { i18n } from '../i18next';
@ -45,12 +52,13 @@ interface ModlogState {
}
export class Modlog extends Component<any, ModlogState> {
private isoData = setIsoData(this.context);
private subscription: Subscription;
private emptyState: ModlogState = {
combined: [],
page: 1,
loading: true,
site: undefined,
site: this.isoData.site.site,
};
constructor(props: any, context: any) {
@ -60,20 +68,24 @@ export class Modlog extends Component<any, ModlogState> {
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(
msg => this.parseMessage(msg),
err => console.error(err),
() => console.log('complete')
);
this.refetch();
WebSocketService.Instance.getSite();
this.parseMessage = this.parseMessage.bind(this);
this.subscription = wsSubscribe(this.parseMessage);
// Only fetch the data if coming from another route
if (this.isoData.path == this.context.router.route.match.url) {
let data = this.isoData.routeData[0];
this.setCombined(data);
this.state.loading = false;
} else {
this.refetch();
}
}
componentWillUnmount() {
this.subscription.unsubscribe();
if (isBrowser()) {
this.subscription.unsubscribe();
}
}
setCombined(res: GetModlogResponse) {
@ -119,8 +131,6 @@ export class Modlog extends Component<any, ModlogState> {
this.state.combined.sort((a, b) =>
b.data.when_.localeCompare(a.data.when_)
);
this.setState(this.state);
}
combined() {
@ -434,6 +444,24 @@ export class Modlog extends Component<any, ModlogState> {
WebSocketService.Instance.getModlog(modlogForm);
}
static fetchInitialData(_auth: string, path: string): Promise<any>[] {
let pathSplit = path.split('/');
let communityId = pathSplit[3];
let promises: Promise<any>[] = [];
let modlogForm: GetModlogForm = {
page: 1,
limit: fetchLimit,
};
if (communityId) {
modlogForm.community_id = Number(communityId);
}
promises.push(lemmyHttp.getModlog(modlogForm));
return promises;
}
parseMessage(msg: WebSocketJsonResponse) {
console.log(msg);
let res = wsJsonToRes(msg);
@ -445,9 +473,6 @@ export class Modlog extends Component<any, ModlogState> {
this.state.loading = false;
window.scrollTo(0, 0);
this.setCombined(data);
} else if (res.op == UserOperation.GetSite) {
let data = res.data as GetSiteResponse;
this.state.site = data.site;
this.setState(this.state);
}
}

View File

@ -1,7 +1,6 @@
import { Component, linkEvent } from 'inferno';
import { Helmet } from 'inferno-helmet';
import { Subscription } from 'rxjs';
import { retryWhen, delay, take } from 'rxjs/operators';
import {
UserOperation,
Post,
@ -15,7 +14,6 @@ import {
PostResponse,
CommentResponse,
WebSocketJsonResponse,
GetSiteResponse,
Site,
} from 'lemmy-js-client';
import { WebSocketService } from '../services';
@ -28,7 +26,10 @@ import {
createCommentLikeRes,
createPostLikeFindRes,
commentsToFlatNodes,
getPageFromProps,
setIsoData,
wsSubscribe,
lemmyHttp,
setAuth,
} from '../utils';
import { PostListing } from './post-listing';
import { UserListing } from './user-listing';
@ -37,6 +38,13 @@ import { SortSelect } from './sort-select';
import { CommentNodes } from './comment-nodes';
import { i18n } from '../i18next';
interface SearchProps {
q: string;
type_: SearchType;
sort: SortType;
page: number;
}
interface SearchState {
q: string;
type_: SearchType;
@ -48,13 +56,6 @@ interface SearchState {
searchText: string;
}
interface SearchProps {
q: string;
type_: SearchType;
sort: SortType;
page: number;
}
interface UrlParams {
q?: string;
type_?: SearchType;
@ -63,13 +64,14 @@ interface UrlParams {
}
export class Search extends Component<any, SearchState> {
private isoData = setIsoData(this.context);
private subscription: Subscription;
private emptyState: SearchState = {
q: Search.getSearchQueryFromProps(this.props),
type_: Search.getSearchTypeFromProps(this.props),
sort: Search.getSortTypeFromProps(this.props),
page: getPageFromProps(this.props),
searchText: Search.getSearchQueryFromProps(this.props),
q: Search.getSearchQueryFromProps(this.props.match.params.q),
type_: Search.getSearchTypeFromProps(this.props.match.params.type),
sort: Search.getSortTypeFromProps(this.props.match.params.sort),
page: Search.getPageFromProps(this.props.match.params.page),
searchText: Search.getSearchQueryFromProps(this.props.match.params.q),
searchResponse: {
type_: null,
posts: [],
@ -78,36 +80,23 @@ export class Search extends Component<any, SearchState> {
users: [],
},
loading: false,
site: {
id: undefined,
name: undefined,
creator_id: undefined,
published: undefined,
creator_name: undefined,
number_of_users: undefined,
number_of_posts: undefined,
number_of_comments: undefined,
number_of_communities: undefined,
enable_downvotes: undefined,
open_registration: undefined,
enable_nsfw: undefined,
},
site: this.isoData.site.site,
};
static getSearchQueryFromProps(props: any): string {
return props.match.params.q ? props.match.params.q : '';
static getSearchQueryFromProps(q: string): string {
return q || '';
}
static getSearchTypeFromProps(props: any): SearchType {
return props.match.params.type
? routeSearchTypeToEnum(props.match.params.type)
: SearchType.All;
static getSearchTypeFromProps(type_: string): SearchType {
return type_ ? routeSearchTypeToEnum(type_) : SearchType.All;
}
static getSortTypeFromProps(props: any): SortType {
return props.match.params.sort
? routeSortTypeToEnum(props.match.params.sort)
: SortType.TopAll;
static getSortTypeFromProps(sort: string): SortType {
return sort ? routeSortTypeToEnum(sort) : SortType.TopAll;
}
static getPageFromProps(page: string): number {
return page ? Number(page) : 1;
}
constructor(props: any, context: any) {
@ -116,18 +105,17 @@ export class Search extends Component<any, SearchState> {
this.state = this.emptyState;
this.handleSortChange = this.handleSortChange.bind(this);
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')
);
this.parseMessage = this.parseMessage.bind(this);
this.subscription = wsSubscribe(this.parseMessage);
WebSocketService.Instance.getSite();
if (this.state.q) {
this.search();
// Only fetch the data if coming from another route
if (this.state.q != '') {
if (this.isoData.path == this.context.router.route.match.url) {
this.state.searchResponse = this.isoData.routeData[0];
this.state.loading = false;
} else {
this.search();
}
}
}
@ -137,13 +125,33 @@ export class Search extends Component<any, SearchState> {
static getDerivedStateFromProps(props: any): SearchProps {
return {
q: Search.getSearchQueryFromProps(props),
type_: Search.getSearchTypeFromProps(props),
sort: Search.getSortTypeFromProps(props),
page: getPageFromProps(props),
q: Search.getSearchQueryFromProps(props.match.params.q),
type_: Search.getSearchTypeFromProps(props.match.params.type),
sort: Search.getSortTypeFromProps(props.match.params.sort),
page: Search.getPageFromProps(props.match.params.page),
};
}
static fetchInitialData(auth: string, path: string): Promise<any>[] {
let pathSplit = path.split('/');
let promises: Promise<any>[] = [];
let form: SearchForm = {
q: this.getSearchQueryFromProps(pathSplit[3]),
type_: this.getSearchTypeFromProps(pathSplit[5]),
sort: this.getSortTypeFromProps(pathSplit[7]),
page: this.getPageFromProps(pathSplit[9]),
limit: fetchLimit,
};
setAuth(form, auth);
if (form.q != '') {
promises.push(lemmyHttp.search(form));
}
return promises;
}
componentDidUpdate(_: any, lastState: SearchState) {
if (
lastState.q !== this.state.q ||
@ -289,6 +297,7 @@ export class Search extends Component<any, SearchState> {
<div class="col-12">
{i.type_ == 'posts' && (
<PostListing
communities={[]}
key={(i.data as Post).id}
post={i.data as Post}
showCommunity
@ -351,6 +360,7 @@ export class Search extends Component<any, SearchState> {
<div class="row">
<div class="col-12">
<PostListing
communities={[]}
post={post}
showCommunity
enableDownvotes={this.state.site.enable_downvotes}
@ -527,10 +537,6 @@ export class Search extends Component<any, SearchState> {
let data = res.data as PostResponse;
createPostLikeFindRes(data, this.state.searchResponse.posts);
this.setState(this.state);
} else if (res.op == UserOperation.GetSite) {
let data = res.data as GetSiteResponse;
this.state.site = data.site;
this.setState(this.state);
}
}
}

View File

@ -68,11 +68,7 @@ export class Sponsors extends Component<any, SponsorsState> {
}
get documentTitle(): string {
if (this.state.site) {
return `${i18n.t('sponsors')} - ${this.state.site.name}`;
} else {
return 'Lemmy';
}
return `${i18n.t('sponsors')} - ${this.state.site.name}`;
}
render() {

View File

@ -109,15 +109,30 @@ export const routes: IRoutePropsWithFetch[] = [
{
path: `/modlog/community/:community_id`,
component: Modlog,
fetchInitialData: (auth, path) => Modlog.fetchInitialData(auth, path),
},
{
path: `/modlog`,
component: Modlog,
fetchInitialData: (auth, path) => Modlog.fetchInitialData(auth, path),
},
{ path: `/modlog`, component: Modlog },
{ path: `/setup`, component: Setup },
{ path: `/admin`, component: AdminSettings },
{
path: `/admin`,
component: AdminSettings,
fetchInitialData: (auth, path) =>
AdminSettings.fetchInitialData(auth, path),
},
{
path: `/search/q/:q/type/:type/sort/:sort/page/:page`,
component: Search,
fetchInitialData: (auth, path) => Search.fetchInitialData(auth, path),
},
{
path: `/search`,
component: Search,
fetchInitialData: (auth, path) => Search.fetchInitialData(auth, path),
},
{ path: `/search`, component: Search },
{ path: `/sponsors`, component: Sponsors },
{
path: `/password_change/:token`,

View File

@ -301,7 +301,7 @@ export function routeDataTypeToEnum(type: string): DataType {
}
export function routeSearchTypeToEnum(type: string): SearchType {
return SearchType[capitalizeFirstLetter(type)];
return SearchType[type];
}
export async function getPageTitle(url: string) {