Adding usable search urls

- Fixes #242
This commit is contained in:
Dessalines 2019-09-05 18:34:10 -07:00
parent 299285abb8
commit aca2c1abec
4 changed files with 64 additions and 8 deletions

View file

@ -106,11 +106,12 @@ export class Main extends Component<any, MainState> {
// Necessary for back button for some reason // Necessary for back button for some reason
componentWillReceiveProps(nextProps: any) { componentWillReceiveProps(nextProps: any) {
if (nextProps.history.action == 'POP') { if (nextProps.history.action == 'POP' || nextProps.history.action == 'PUSH') {
this.state = this.emptyState; this.state = this.emptyState;
this.state.type_ = this.getListingTypeFromProps(nextProps); this.state.type_ = this.getListingTypeFromProps(nextProps);
this.state.sort = this.getSortTypeFromProps(nextProps); this.state.sort = this.getSortTypeFromProps(nextProps);
this.state.page = this.getPageFromProps(nextProps); this.state.page = this.getPageFromProps(nextProps);
this.setState(this.state);
this.fetchPosts(); this.fetchPosts();
} }
} }

View file

@ -4,7 +4,7 @@ import { Subscription } from "rxjs";
import { retryWhen, delay, take } from 'rxjs/operators'; import { retryWhen, delay, take } from 'rxjs/operators';
import { UserOperation, Post, Comment, Community, UserView, SortType, SearchForm, SearchResponse, SearchType } from '../interfaces'; import { UserOperation, Post, Comment, Community, UserView, SortType, SearchForm, SearchResponse, SearchType } from '../interfaces';
import { WebSocketService } from '../services'; import { WebSocketService } from '../services';
import { msgOp, fetchLimit } from '../utils'; import { msgOp, fetchLimit, routeSearchTypeToEnum, routeSortTypeToEnum } from '../utils';
import { PostListing } from './post-listing'; import { PostListing } from './post-listing';
import { CommentNodes } from './comment-nodes'; import { CommentNodes } from './comment-nodes';
import { i18n } from '../i18next'; import { i18n } from '../i18next';
@ -23,10 +23,10 @@ export class Search extends Component<any, SearchState> {
private subscription: Subscription; private subscription: Subscription;
private emptyState: SearchState = { private emptyState: SearchState = {
q: undefined, q: this.getSearchQueryFromProps(this.props),
type_: SearchType.All, type_: this.getSearchTypeFromProps(this.props),
sort: SortType.TopAll, sort: this.getSortTypeFromProps(this.props),
page: 1, page: this.getPageFromProps(this.props),
searchResponse: { searchResponse: {
op: null, op: null,
type_: null, type_: null,
@ -38,6 +38,26 @@ export class Search extends Component<any, SearchState> {
loading: false, loading: false,
} }
getSearchQueryFromProps(props: any): string {
return (props.match.params.q) ? props.match.params.q : '';
}
getSearchTypeFromProps(props: any): SearchType {
return (props.match.params.type) ?
routeSearchTypeToEnum(props.match.params.type) :
SearchType.All;
}
getSortTypeFromProps(props: any): SortType {
return (props.match.params.sort) ?
routeSortTypeToEnum(props.match.params.sort) :
SortType.TopAll;
}
getPageFromProps(props: any): number {
return (props.match.params.page) ? Number(props.match.params.page) : 1;
}
constructor(props: any, context: any) { constructor(props: any, context: any) {
super(props, context); super(props, context);
@ -51,12 +71,29 @@ export class Search extends Component<any, SearchState> {
() => console.log('complete') () => console.log('complete')
); );
if (this.state.q) {
this.search();
}
} }
componentWillUnmount() { componentWillUnmount() {
this.subscription.unsubscribe(); this.subscription.unsubscribe();
} }
// Necessary for back button for some reason
componentWillReceiveProps(nextProps: any) {
if (nextProps.history.action == 'POP' || nextProps.history.action == 'PUSH') {
this.state = this.emptyState;
this.state.q = this.getSearchQueryFromProps(nextProps);
this.state.type_ = this.getSearchTypeFromProps(nextProps);
this.state.sort = this.getSortTypeFromProps(nextProps);
this.state.page = this.getPageFromProps(nextProps);
this.setState(this.state);
this.search();
}
}
componentDidMount() { componentDidMount() {
document.title = `${i18n.t('search')} - ${WebSocketService.Instance.site.name}`; document.title = `${i18n.t('search')} - ${WebSocketService.Instance.site.name}`;
} }
@ -256,12 +293,14 @@ export class Search extends Component<any, SearchState> {
nextPage(i: Search) { nextPage(i: Search) {
i.state.page++; i.state.page++;
i.setState(i.state); i.setState(i.state);
i.updateUrl();
i.search(); i.search();
} }
prevPage(i: Search) { prevPage(i: Search) {
i.state.page--; i.state.page--;
i.setState(i.state); i.setState(i.state);
i.updateUrl();
i.search(); i.search();
} }
@ -275,19 +314,23 @@ export class Search extends Component<any, SearchState> {
limit: fetchLimit, limit: fetchLimit,
}; };
WebSocketService.Instance.search(form); if (this.state.q != '') {
WebSocketService.Instance.search(form);
}
} }
handleSortChange(i: Search, event: any) { handleSortChange(i: Search, event: any) {
i.state.sort = Number(event.target.value); i.state.sort = Number(event.target.value);
i.state.page = 1; i.state.page = 1;
i.setState(i.state); i.setState(i.state);
i.updateUrl();
} }
handleTypeChange(i: Search, event: any) { handleTypeChange(i: Search, event: any) {
i.state.type_ = Number(event.target.value); i.state.type_ = Number(event.target.value);
i.state.page = 1; i.state.page = 1;
i.setState(i.state); i.setState(i.state);
i.updateUrl();
} }
handleSearchSubmit(i: Search, event: any) { handleSearchSubmit(i: Search, event: any) {
@ -295,6 +338,7 @@ export class Search extends Component<any, SearchState> {
i.state.loading = true; i.state.loading = true;
i.search(); i.search();
i.setState(i.state); i.setState(i.state);
i.updateUrl();
} }
handleQChange(i: Search, event: any) { handleQChange(i: Search, event: any) {
@ -302,6 +346,12 @@ export class Search extends Component<any, SearchState> {
i.setState(i.state); i.setState(i.state);
} }
updateUrl() {
let typeStr = SearchType[this.state.type_].toLowerCase();
let sortStr = SortType[this.state.sort].toLowerCase();
this.props.history.push(`/search/q/${this.state.q}/type/${typeStr}/sort/${sortStr}/page/${this.state.page}`);
}
parseMessage(msg: any) { parseMessage(msg: any) {
console.log(msg); console.log(msg);
let op: UserOperation = msgOp(msg); let op: UserOperation = msgOp(msg);

1
ui/src/index.tsx vendored
View file

@ -61,6 +61,7 @@ class Index extends Component<any, any> {
<Route path={`/modlog/community/:community_id`} component={Modlog} /> <Route path={`/modlog/community/:community_id`} component={Modlog} />
<Route path={`/modlog`} component={Modlog} /> <Route path={`/modlog`} component={Modlog} />
<Route path={`/setup`} component={Setup} /> <Route path={`/setup`} component={Setup} />
<Route path={`/search/q/:q/type/:type/sort/:sort/page/:page`} component={Search} />
<Route path={`/search`} component={Search} /> <Route path={`/search`} component={Search} />
<Route path={`/sponsors`} component={Sponsors} /> <Route path={`/sponsors`} component={Sponsors} />
</Switch> </Switch>

6
ui/src/utils.ts vendored
View file

@ -7,7 +7,7 @@ import 'moment/locale/sv';
import 'moment/locale/ru'; import 'moment/locale/ru';
import 'moment/locale/nl'; import 'moment/locale/nl';
import { UserOperation, Comment, User, SortType, ListingType } from './interfaces'; import { UserOperation, Comment, User, SortType, ListingType, SearchType } from './interfaces';
import * as markdown_it from 'markdown-it'; import * as markdown_it from 'markdown-it';
import * as markdownitEmoji from 'markdown-it-emoji/light'; import * as markdownitEmoji from 'markdown-it-emoji/light';
import * as markdown_it_container from 'markdown-it-container'; import * as markdown_it_container from 'markdown-it-container';
@ -144,6 +144,10 @@ export function routeListingTypeToEnum(type: string): ListingType {
return ListingType[capitalizeFirstLetter(type)]; return ListingType[capitalizeFirstLetter(type)];
} }
export function routeSearchTypeToEnum(type: string): SearchType {
return SearchType[capitalizeFirstLetter(type)];
}
export async function getPageTitle(url: string) { export async function getPageTitle(url: string) {
let res = await fetch(`https://textance.herokuapp.com/title/${url}`); let res = await fetch(`https://textance.herokuapp.com/title/${url}`);
let data = await res.text(); let data = await res.text();