Always show previous paginator, extract paginator component.

- Fixes #304
This commit is contained in:
Dessalines 2021-07-16 15:40:56 -04:00
parent 0e25ced312
commit 0361b2c700
8 changed files with 102 additions and 229 deletions

View file

@ -26,6 +26,7 @@ import {
setOptionalAuth, setOptionalAuth,
} from "../utils"; } from "../utils";
import { CommunityLink } from "./community-link"; import { CommunityLink } from "./community-link";
import { Paginator } from "./paginator";
import { Spinner } from "./icon"; import { Spinner } from "./icon";
import { i18n } from "../i18next"; import { i18n } from "../i18next";
import { InitialFetchRequest } from "shared/interfaces"; import { InitialFetchRequest } from "shared/interfaces";
@ -58,6 +59,7 @@ export class Communities extends Component<any, CommunitiesState> {
constructor(props: any, context: any) { constructor(props: any, context: any) {
super(props, context); super(props, context);
this.state = this.emptyState; this.state = this.emptyState;
this.handlePageChange = this.handlePageChange.bind(this);
this.parseMessage = this.parseMessage.bind(this); this.parseMessage = this.parseMessage.bind(this);
this.subscription = wsSubscribe(this.parseMessage); this.subscription = wsSubscribe(this.parseMessage);
@ -178,7 +180,10 @@ export class Communities extends Component<any, CommunitiesState> {
</tbody> </tbody>
</table> </table>
</div> </div>
{this.paginator()} <Paginator
page={this.state.page}
onChange={this.handlePageChange}
/>
</div> </div>
)} )}
</div> </div>
@ -211,41 +216,13 @@ export class Communities extends Component<any, CommunitiesState> {
); );
} }
paginator() {
return (
<div class="mt-2">
{this.state.page > 1 && (
<button
class="btn btn-secondary mr-1"
onClick={linkEvent(this, this.prevPage)}
>
{i18n.t("prev")}
</button>
)}
{this.state.communities.length > 0 && (
<button
class="btn btn-secondary"
onClick={linkEvent(this, this.nextPage)}
>
{i18n.t("next")}
</button>
)}
</div>
);
}
updateUrl(paramUpdates: CommunitiesProps) { updateUrl(paramUpdates: CommunitiesProps) {
const page = paramUpdates.page || this.state.page; const page = paramUpdates.page || this.state.page;
this.props.history.push(`/communities/page/${page}`); this.props.history.push(`/communities/page/${page}`);
} }
nextPage(i: Communities) { handlePageChange(page: number) {
i.updateUrl({ page: i.state.page + 1 }); this.updateUrl({ page });
}
prevPage(i: Communities) {
i.updateUrl({ page: i.state.page - 1 });
} }
handleUnsubscribe(communityId: number) { handleUnsubscribe(communityId: number) {

View file

@ -1,4 +1,4 @@
import { Component, linkEvent } from "inferno"; import { Component } from "inferno";
import { Subscription } from "rxjs"; import { Subscription } from "rxjs";
import { DataType, InitialFetchRequest } from "../interfaces"; import { DataType, InitialFetchRequest } from "../interfaces";
import { import {
@ -30,6 +30,7 @@ import { Sidebar } from "./sidebar";
import { CommunityLink } from "./community-link"; import { CommunityLink } from "./community-link";
import { BannerIconHeader } from "./banner-icon-header"; import { BannerIconHeader } from "./banner-icon-header";
import { Icon, Spinner } from "./icon"; import { Icon, Spinner } from "./icon";
import { Paginator } from "./paginator";
import { import {
wsJsonToRes, wsJsonToRes,
fetchLimit, fetchLimit,
@ -108,6 +109,7 @@ export class Community extends Component<any, State> {
this.state = this.emptyState; this.state = this.emptyState;
this.handleSortChange = this.handleSortChange.bind(this); this.handleSortChange = this.handleSortChange.bind(this);
this.handleDataTypeChange = this.handleDataTypeChange.bind(this); this.handleDataTypeChange = this.handleDataTypeChange.bind(this);
this.handlePageChange = this.handlePageChange.bind(this);
this.parseMessage = this.parseMessage.bind(this); this.parseMessage = this.parseMessage.bind(this);
this.subscription = wsSubscribe(this.parseMessage); this.subscription = wsSubscribe(this.parseMessage);
@ -255,7 +257,10 @@ export class Community extends Component<any, State> {
{this.communityInfo()} {this.communityInfo()}
{this.selects()} {this.selects()}
{this.listings()} {this.listings()}
{this.paginator()} <Paginator
page={this.state.page}
onChange={this.handlePageChange}
/>
</div> </div>
<div class="col-12 col-md-4"> <div class="col-12 col-md-4">
<Sidebar <Sidebar
@ -345,36 +350,8 @@ export class Community extends Component<any, State> {
); );
} }
paginator() { handlePageChange(page: number) {
return ( this.updateUrl({ page });
<div class="my-2">
{this.state.page > 1 && (
<button
class="btn btn-secondary mr-1"
onClick={linkEvent(this, this.prevPage)}
>
{i18n.t("prev")}
</button>
)}
{this.state.posts.length > 0 && (
<button
class="btn btn-secondary"
onClick={linkEvent(this, this.nextPage)}
>
{i18n.t("next")}
</button>
)}
</div>
);
}
nextPage(i: Community) {
i.updateUrl({ page: i.state.page + 1 });
window.scrollTo(0, 0);
}
prevPage(i: Community) {
i.updateUrl({ page: i.state.page - 1 });
window.scrollTo(0, 0); window.scrollTo(0, 0);
} }

View file

@ -37,6 +37,7 @@ import {
import { CommentNodes } from "./comment-nodes"; import { CommentNodes } from "./comment-nodes";
import { PrivateMessage } from "./private-message"; import { PrivateMessage } from "./private-message";
import { HtmlTags } from "./html-tags"; import { HtmlTags } from "./html-tags";
import { Paginator } from "./paginator";
import { SortSelect } from "./sort-select"; import { SortSelect } from "./sort-select";
import { Icon, Spinner } from "./icon"; import { Icon, Spinner } from "./icon";
import { i18n } from "../i18next"; import { i18n } from "../i18next";
@ -100,6 +101,7 @@ export class Inbox extends Component<any, InboxState> {
this.state = this.emptyState; this.state = this.emptyState;
this.handleSortChange = this.handleSortChange.bind(this); this.handleSortChange = this.handleSortChange.bind(this);
this.handlePageChange = this.handlePageChange.bind(this);
if (!UserService.Instance.localUserView && isBrowser()) { if (!UserService.Instance.localUserView && isBrowser()) {
toast(i18n.t("not_logged_in"), "danger"); toast(i18n.t("not_logged_in"), "danger");
@ -183,7 +185,10 @@ export class Inbox extends Component<any, InboxState> {
this.mentions()} this.mentions()}
{this.state.messageType == MessageType.Messages && {this.state.messageType == MessageType.Messages &&
this.messages()} this.messages()}
{this.paginator()} <Paginator
page={this.state.page}
onChange={this.handlePageChange}
/>
</div> </div>
</div> </div>
)} )}
@ -429,39 +434,9 @@ export class Inbox extends Component<any, InboxState> {
); );
} }
paginator() { handlePageChange(page: number) {
return ( this.setState({ page });
<div class="mt-2"> this.refetch();
{this.state.page > 1 && (
<button
class="btn btn-secondary mr-1"
onClick={linkEvent(this, this.prevPage)}
>
{i18n.t("prev")}
</button>
)}
{this.unreadCount() > 0 && (
<button
class="btn btn-secondary"
onClick={linkEvent(this, this.nextPage)}
>
{i18n.t("next")}
</button>
)}
</div>
);
}
nextPage(i: Inbox) {
i.state.page++;
i.setState(i.state);
i.refetch();
}
prevPage(i: Inbox) {
i.state.page--;
i.setState(i.state);
i.refetch();
} }
handleUnreadOrAllChange(i: Inbox, event: any) { handleUnreadOrAllChange(i: Inbox, event: any) {

View file

@ -65,6 +65,7 @@ import {
import { i18n } from "../i18next"; import { i18n } from "../i18next";
import { T } from "inferno-i18next"; import { T } from "inferno-i18next";
import { HtmlTags } from "./html-tags"; import { HtmlTags } from "./html-tags";
import { Paginator } from "./paginator";
interface MainState { interface MainState {
subscribedCommunities: CommunityFollowerView[]; subscribedCommunities: CommunityFollowerView[];
@ -119,6 +120,7 @@ export class Main extends Component<any, MainState> {
this.handleSortChange = this.handleSortChange.bind(this); this.handleSortChange = this.handleSortChange.bind(this);
this.handleListingTypeChange = this.handleListingTypeChange.bind(this); this.handleListingTypeChange = this.handleListingTypeChange.bind(this);
this.handleDataTypeChange = this.handleDataTypeChange.bind(this); this.handleDataTypeChange = this.handleDataTypeChange.bind(this);
this.handlePageChange = this.handlePageChange.bind(this);
this.parseMessage = this.parseMessage.bind(this); this.parseMessage = this.parseMessage.bind(this);
this.subscription = wsSubscribe(this.parseMessage); this.subscription = wsSubscribe(this.parseMessage);
@ -132,7 +134,8 @@ export class Main extends Component<any, MainState> {
} }
this.state.trendingCommunities = this.isoData.routeData[1].communities; this.state.trendingCommunities = this.isoData.routeData[1].communities;
if (UserService.Instance.localUserView) { if (UserService.Instance.localUserView) {
this.state.subscribedCommunities = this.isoData.routeData[2].communities; this.state.subscribedCommunities =
this.isoData.routeData[2].communities;
} }
this.state.loading = false; this.state.loading = false;
} else { } else {
@ -553,7 +556,10 @@ export class Main extends Component<any, MainState> {
<div> <div>
{this.selects()} {this.selects()}
{this.listings()} {this.listings()}
{this.paginator()} <Paginator
page={this.state.page}
onChange={this.handlePageChange}
/>
</div> </div>
)} )}
</div> </div>
@ -632,29 +638,6 @@ export class Main extends Component<any, MainState> {
); );
} }
paginator() {
return (
<div class="my-2">
{this.state.page > 1 && (
<button
class="btn btn-secondary mr-1"
onClick={linkEvent(this, this.prevPage)}
>
{i18n.t("prev")}
</button>
)}
{this.state.posts.length > 0 && (
<button
class="btn btn-secondary"
onClick={linkEvent(this, this.nextPage)}
>
{i18n.t("next")}
</button>
)}
</div>
);
}
get canAdmin(): boolean { get canAdmin(): boolean {
return ( return (
UserService.Instance.localUserView && UserService.Instance.localUserView &&
@ -674,13 +657,8 @@ export class Main extends Component<any, MainState> {
this.setState(this.state); this.setState(this.state);
} }
nextPage(i: Main) { handlePageChange(page: number) {
i.updateUrl({ page: i.state.page + 1 }); this.updateUrl({ page });
window.scrollTo(0, 0);
}
prevPage(i: Main) {
i.updateUrl({ page: i.state.page - 1 });
window.scrollTo(0, 0); window.scrollTo(0, 0);
} }

View file

@ -1,4 +1,4 @@
import { Component, linkEvent } from "inferno"; import { Component } from "inferno";
import { Link } from "inferno-router"; import { Link } from "inferno-router";
import { Subscription } from "rxjs"; import { Subscription } from "rxjs";
import { import {
@ -38,6 +38,7 @@ import { InitialFetchRequest } from "shared/interfaces";
import { PersonListing } from "./person-listing"; import { PersonListing } from "./person-listing";
import { CommunityLink } from "./community-link"; import { CommunityLink } from "./community-link";
import { Spinner } from "./icon"; import { Spinner } from "./icon";
import { Paginator } from "./paginator";
enum ModlogEnum { enum ModlogEnum {
ModRemovePost, ModRemovePost,
@ -101,6 +102,8 @@ export class Modlog extends Component<any, ModlogState> {
super(props, context); super(props, context);
this.state = this.emptyState; this.state = this.emptyState;
this.handlePageChange = this.handlePageChange.bind(this);
this.state.communityId = this.props.match.params.community_id this.state.communityId = this.props.match.params.community_id
? Number(this.props.match.params.community_id) ? Number(this.props.match.params.community_id)
: undefined; : undefined;
@ -208,8 +211,9 @@ export class Modlog extends Component<any, ModlogState> {
combined.push(...banned); combined.push(...banned);
if (this.state.communityId && combined.length > 0) { if (this.state.communityId && combined.length > 0) {
this.state.communityName = (combined[0] this.state.communityName = (
.view as ModRemovePostView).community.name; combined[0].view as ModRemovePostView
).community.name;
} }
// Sort them by time // Sort them by time
@ -429,7 +433,10 @@ export class Modlog extends Component<any, ModlogState> {
</thead> </thead>
{this.combined()} {this.combined()}
</table> </table>
{this.paginator()} <Paginator
page={this.state.page}
onChange={this.handlePageChange}
/>
</div> </div>
</div> </div>
)} )}
@ -437,37 +444,9 @@ export class Modlog extends Component<any, ModlogState> {
); );
} }
paginator() { handlePageChange(val: number) {
return ( this.setState({ page: val });
<div class="mt-2"> this.refetch();
{this.state.page > 1 && (
<button
class="btn btn-secondary mr-1"
onClick={linkEvent(this, this.prevPage)}
>
{i18n.t("prev")}
</button>
)}
<button
class="btn btn-secondary"
onClick={linkEvent(this, this.nextPage)}
>
{i18n.t("next")}
</button>
</div>
);
}
nextPage(i: Modlog) {
i.state.page++;
i.setState(i.state);
i.refetch();
}
prevPage(i: Modlog) {
i.state.page--;
i.setState(i.state);
i.refetch();
} }
refetch() { refetch() {

View file

@ -0,0 +1,40 @@
import { Component, linkEvent } from "inferno";
import { i18n } from "../i18next";
interface PaginatorProps {
page: number;
onChange(val: number): any;
}
export class Paginator extends Component<PaginatorProps, any> {
constructor(props: any, context: any) {
super(props, context);
}
render() {
return (
<div class="my-2">
<button
class="btn btn-secondary mr-2"
disabled={this.props.page == 1}
onClick={linkEvent(this, this.handlePrev)}
>
{i18n.t("prev")}
</button>
<button
class="btn btn-secondary"
onClick={linkEvent(this, this.handleNext)}
>
{i18n.t("next")}
</button>
</div>
);
}
handlePrev(i: Paginator) {
i.props.onChange(i.props.page - 1);
}
handleNext(i: Paginator) {
i.props.onChange(i.props.page + 1);
}
}

View file

@ -1,5 +1,4 @@
import { Component, linkEvent } from "inferno"; import { Component } from "inferno";
import { i18n } from "../i18next";
import { import {
PostView, PostView,
CommentView, CommentView,
@ -11,6 +10,7 @@ import { PersonDetailsView } from "../interfaces";
import { commentsToFlatNodes, setupTippy } from "../utils"; import { commentsToFlatNodes, setupTippy } from "../utils";
import { PostListing } from "./post-listing"; import { PostListing } from "./post-listing";
import { CommentNodes } from "./comment-nodes"; import { CommentNodes } from "./comment-nodes";
import { Paginator } from "./paginator";
interface PersonDetailsProps { interface PersonDetailsProps {
personRes: GetPersonDetailsResponse; personRes: GetPersonDetailsResponse;
@ -39,6 +39,7 @@ type ItemType = {
export class PersonDetails extends Component<PersonDetailsProps, any> { export class PersonDetails extends Component<PersonDetailsProps, any> {
constructor(props: any, context: any) { constructor(props: any, context: any) {
super(props, context); super(props, context);
this.handlePageChange = this.handlePageChange.bind(this);
} }
// TODO needed here? // TODO needed here?
@ -60,7 +61,8 @@ export class PersonDetails extends Component<PersonDetailsProps, any> {
return ( return (
<div> <div>
{this.viewSelector(this.props.view)} {this.viewSelector(this.props.view)}
{this.paginator()}
<Paginator page={this.props.page} onChange={this.handlePageChange} />
</div> </div>
); );
} }
@ -182,36 +184,7 @@ export class PersonDetails extends Component<PersonDetailsProps, any> {
); );
} }
paginator() { handlePageChange(val: number) {
return ( this.props.onPageChange(val);
<div class="my-2">
{this.props.page > 1 && (
<button
class="btn btn-secondary mr-1"
onClick={linkEvent(this, this.prevPage)}
>
{i18n.t("prev")}
</button>
)}
{this.props.personRes.comments.length +
this.props.personRes.posts.length >
0 && (
<button
class="btn btn-secondary"
onClick={linkEvent(this, this.nextPage)}
>
{i18n.t("next")}
</button>
)}
</div>
);
}
nextPage(i: PersonDetails) {
i.props.onPageChange(i.props.page + 1);
}
prevPage(i: PersonDetails) {
i.props.onPageChange(i.props.page - 1);
} }
} }

View file

@ -58,6 +58,7 @@ import { CommunityLink } from "./community-link";
import { SortSelect } from "./sort-select"; import { SortSelect } from "./sort-select";
import { ListingTypeSelect } from "./listing-type-select"; import { ListingTypeSelect } from "./listing-type-select";
import { CommentNodes } from "./comment-nodes"; import { CommentNodes } from "./comment-nodes";
import { Paginator } from "./paginator";
import { i18n } from "../i18next"; import { i18n } from "../i18next";
import { InitialFetchRequest } from "shared/interfaces"; import { InitialFetchRequest } from "shared/interfaces";
@ -166,6 +167,7 @@ export class Search extends Component<any, SearchState> {
this.state = this.emptyState; this.state = this.emptyState;
this.handleSortChange = this.handleSortChange.bind(this); this.handleSortChange = this.handleSortChange.bind(this);
this.handleListingTypeChange = this.handleListingTypeChange.bind(this); this.handleListingTypeChange = this.handleListingTypeChange.bind(this);
this.handlePageChange = this.handlePageChange.bind(this);
this.parseMessage = this.parseMessage.bind(this); this.parseMessage = this.parseMessage.bind(this);
this.subscription = wsSubscribe(this.parseMessage); this.subscription = wsSubscribe(this.parseMessage);
@ -328,7 +330,7 @@ export class Search extends Component<any, SearchState> {
{this.state.type_ == SearchType.Users && this.users()} {this.state.type_ == SearchType.Users && this.users()}
{this.state.type_ == SearchType.Url && this.posts()} {this.state.type_ == SearchType.Url && this.posts()}
{this.resultsCount() == 0 && <span>{i18n.t("no_results")}</span>} {this.resultsCount() == 0 && <span>{i18n.t("no_results")}</span>}
{this.paginator()} <Paginator page={this.state.page} onChange={this.handlePageChange} />
</div> </div>
); );
} }
@ -605,30 +607,6 @@ export class Search extends Component<any, SearchState> {
); );
} }
paginator() {
return (
<div class="mt-2">
{this.state.page > 1 && (
<button
class="btn btn-secondary mr-1"
onClick={linkEvent(this, this.prevPage)}
>
{i18n.t("prev")}
</button>
)}
{this.resultsCount() > 0 && (
<button
class="btn btn-secondary"
onClick={linkEvent(this, this.nextPage)}
>
{i18n.t("next")}
</button>
)}
</div>
);
}
resultsCount(): number { resultsCount(): number {
let res = this.state.searchResponse; let res = this.state.searchResponse;
return ( return (
@ -639,12 +617,8 @@ export class Search extends Component<any, SearchState> {
); );
} }
nextPage(i: Search) { handlePageChange(page: number) {
i.updateUrl({ page: i.state.page + 1 }); this.updateUrl({ page });
}
prevPage(i: Search) {
i.updateUrl({ page: i.state.page - 1 });
} }
search() { search() {