From bea7a37983ca2e10f9f7bd1129954e33395b7324 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Tue, 8 Sep 2020 21:40:36 -0500 Subject: [PATCH] Modlog, admin-settings, search, and user done. --- src/shared/components/admin-settings.tsx | 89 ++++++++--------- src/shared/components/modlog.tsx | 63 ++++++++---- src/shared/components/search.tsx | 120 ++++++++++++----------- src/shared/components/sponsors.tsx | 6 +- src/shared/routes.ts | 21 +++- src/shared/utils.ts | 2 +- 6 files changed, 169 insertions(+), 132 deletions(-) diff --git a/src/shared/components/admin-settings.tsx b/src/shared/components/admin-settings.tsx index a3bfdd8..a77ef6f 100644 --- a/src/shared/components/admin-settings.tsx +++ b/src/shared/components/admin-settings.tsx @@ -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 { 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 { 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); + + // 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(); + } + } - WebSocketService.Instance.getSite(); - WebSocketService.Instance.getSiteConfig(); + static fetchInitialData(auth: string, _path: string): Promise[] { + 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 { 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; diff --git a/src/shared/components/modlog.tsx b/src/shared/components/modlog.tsx index 6bbe392..ba0fe8d 100644 --- a/src/shared/components/modlog.tsx +++ b/src/shared/components/modlog.tsx @@ -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 { + 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 { 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 { 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 { WebSocketService.Instance.getModlog(modlogForm); } + static fetchInitialData(_auth: string, path: string): Promise[] { + let pathSplit = path.split('/'); + let communityId = pathSplit[3]; + let promises: Promise[] = []; + + 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 { 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); } } diff --git a/src/shared/components/search.tsx b/src/shared/components/search.tsx index fa9f3f6..e086a92 100644 --- a/src/shared/components/search.tsx +++ b/src/shared/components/search.tsx @@ -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,22 +38,22 @@ import { SortSelect } from './sort-select'; import { CommentNodes } from './comment-nodes'; import { i18n } from '../i18next'; -interface SearchState { +interface SearchProps { q: string; type_: SearchType; sort: SortType; page: number; - searchResponse: SearchResponse; - loading: boolean; - site: Site; - searchText: string; } -interface SearchProps { +interface SearchState { q: string; type_: SearchType; sort: SortType; page: number; + searchResponse: SearchResponse; + loading: boolean; + site: Site; + searchText: string; } interface UrlParams { @@ -63,13 +64,14 @@ interface UrlParams { } export class Search extends Component { + 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 { 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(type_: string): SearchType { + return type_ ? routeSearchTypeToEnum(type_) : SearchType.All; } - static getSearchTypeFromProps(props: any): SearchType { - return props.match.params.type - ? routeSearchTypeToEnum(props.match.params.type) - : SearchType.All; + static getSortTypeFromProps(sort: string): SortType { + return sort ? routeSortTypeToEnum(sort) : SortType.TopAll; } - static getSortTypeFromProps(props: any): SortType { - return props.match.params.sort - ? routeSortTypeToEnum(props.match.params.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 { 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 { 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[] { + let pathSplit = path.split('/'); + let promises: Promise[] = []; + + 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 {
{i.type_ == 'posts' && ( {
{ 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); } } } diff --git a/src/shared/components/sponsors.tsx b/src/shared/components/sponsors.tsx index 0a87380..9e3da9d 100644 --- a/src/shared/components/sponsors.tsx +++ b/src/shared/components/sponsors.tsx @@ -68,11 +68,7 @@ export class Sponsors extends Component { } 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() { diff --git a/src/shared/routes.ts b/src/shared/routes.ts index 14d5495..f485605 100644 --- a/src/shared/routes.ts +++ b/src/shared/routes.ts @@ -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`, diff --git a/src/shared/utils.ts b/src/shared/utils.ts index e48edf0..c8c8d93 100644 --- a/src/shared/utils.ts +++ b/src/shared/utils.ts @@ -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) { -- 2.44.1