mirror of
https://framagit.org/framasoft/mobilizon.git
synced 2024-12-26 17:59:26 +00:00
Add pagination to search
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
parent
4ac7ed7e0e
commit
d334f8237f
3 changed files with 77 additions and 29 deletions
|
@ -8,6 +8,8 @@ export const SEARCH_EVENTS = gql`
|
||||||
$term: String
|
$term: String
|
||||||
$beginsOn: DateTime
|
$beginsOn: DateTime
|
||||||
$endsOn: DateTime
|
$endsOn: DateTime
|
||||||
|
$page: Int
|
||||||
|
$limit: Int
|
||||||
) {
|
) {
|
||||||
searchEvents(
|
searchEvents(
|
||||||
location: $location
|
location: $location
|
||||||
|
@ -16,6 +18,8 @@ export const SEARCH_EVENTS = gql`
|
||||||
term: $term
|
term: $term
|
||||||
beginsOn: $beginsOn
|
beginsOn: $beginsOn
|
||||||
endsOn: $endsOn
|
endsOn: $endsOn
|
||||||
|
page: $page
|
||||||
|
limit: $limit
|
||||||
) {
|
) {
|
||||||
total
|
total
|
||||||
elements {
|
elements {
|
||||||
|
@ -36,8 +40,8 @@ export const SEARCH_EVENTS = gql`
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const SEARCH_GROUPS = gql`
|
export const SEARCH_GROUPS = gql`
|
||||||
query SearchGroups($term: String, $location: String, $radius: Float) {
|
query SearchGroups($term: String, $location: String, $radius: Float, $page: Int, $limit: Int) {
|
||||||
searchGroups(term: $term, location: $location, radius: $radius) {
|
searchGroups(term: $term, location: $location, radius: $radius, page: $page, limit: $limit) {
|
||||||
total
|
total
|
||||||
elements {
|
elements {
|
||||||
avatar {
|
avatar {
|
||||||
|
|
|
@ -15,3 +15,8 @@ export interface SearchPerson {
|
||||||
total: number;
|
total: number;
|
||||||
elements: IPerson[];
|
elements: IPerson[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum SearchTabs {
|
||||||
|
EVENTS = 0,
|
||||||
|
GROUPS = 1,
|
||||||
|
}
|
||||||
|
|
|
@ -71,7 +71,8 @@
|
||||||
<b-tag rounded>{{ searchEvents.total }}</b-tag>
|
<b-tag rounded>{{ searchEvents.total }}</b-tag>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
<div v-if="searchEvents.total > 0" class="columns is-multiline">
|
<div v-if="searchEvents.total > 0">
|
||||||
|
<div class="columns is-multiline">
|
||||||
<div
|
<div
|
||||||
class="column is-one-quarter-desktop"
|
class="column is-one-quarter-desktop"
|
||||||
v-for="event in searchEvents.elements"
|
v-for="event in searchEvents.elements"
|
||||||
|
@ -80,6 +81,19 @@
|
||||||
<EventCard :event="event" />
|
<EventCard :event="event" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="pagination">
|
||||||
|
<b-pagination
|
||||||
|
:total="searchEvents.total"
|
||||||
|
v-model="eventPage"
|
||||||
|
:per-page="EVENT_PAGE_LIMIT"
|
||||||
|
:aria-next-label="$t('Next page')"
|
||||||
|
:aria-previous-label="$t('Previous page')"
|
||||||
|
:aria-page-label="$t('Page')"
|
||||||
|
:aria-current-label="$t('Current page')"
|
||||||
|
>
|
||||||
|
</b-pagination>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<b-message v-else-if="$apollo.loading === false" type="is-danger">{{
|
<b-message v-else-if="$apollo.loading === false" type="is-danger">{{
|
||||||
$t("No events found")
|
$t("No events found")
|
||||||
}}</b-message>
|
}}</b-message>
|
||||||
|
@ -91,7 +105,8 @@
|
||||||
{{ $t("Groups") }} <b-tag rounded>{{ searchGroups.total }}</b-tag>
|
{{ $t("Groups") }} <b-tag rounded>{{ searchGroups.total }}</b-tag>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
<div v-if="searchGroups.total > 0" class="columns is-multiline">
|
<div v-if="searchGroups.total > 0">
|
||||||
|
<div class="columns is-multiline">
|
||||||
<div
|
<div
|
||||||
class="column is-one-quarter-desktop"
|
class="column is-one-quarter-desktop"
|
||||||
v-for="group in searchGroups.elements"
|
v-for="group in searchGroups.elements"
|
||||||
|
@ -100,6 +115,19 @@
|
||||||
<group-card :group="group" />
|
<group-card :group="group" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="pagination">
|
||||||
|
<b-pagination
|
||||||
|
:total="searchGroups.total"
|
||||||
|
v-model="groupPage"
|
||||||
|
:per-page="GROUP_PAGE_LIMIT"
|
||||||
|
:aria-next-label="$t('Next page')"
|
||||||
|
:aria-previous-label="$t('Previous page')"
|
||||||
|
:aria-page-label="$t('Page')"
|
||||||
|
:aria-current-label="$t('Current page')"
|
||||||
|
>
|
||||||
|
</b-pagination>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<b-message v-else-if="$apollo.loading === false" type="is-danger">
|
<b-message v-else-if="$apollo.loading === false" type="is-danger">
|
||||||
{{ $t("No groups found") }}
|
{{ $t("No groups found") }}
|
||||||
</b-message>
|
</b-message>
|
||||||
|
@ -129,10 +157,10 @@ import { FETCH_EVENTS } from "../graphql/event";
|
||||||
import { IEvent } from "../types/event.model";
|
import { IEvent } from "../types/event.model";
|
||||||
import RouteName from "../router/name";
|
import RouteName from "../router/name";
|
||||||
import { IAddress, Address } from "../types/address.model";
|
import { IAddress, Address } from "../types/address.model";
|
||||||
import { SearchEvent, SearchGroup } from "../types/search.model";
|
|
||||||
import AddressAutoComplete from "../components/Event/AddressAutoComplete.vue";
|
import AddressAutoComplete from "../components/Event/AddressAutoComplete.vue";
|
||||||
import { SEARCH_EVENTS, SEARCH_GROUPS } from "../graphql/search";
|
import { SEARCH_EVENTS, SEARCH_GROUPS } from "../graphql/search";
|
||||||
import { Paginate } from "../types/paginate";
|
import { Paginate } from "../types/paginate";
|
||||||
|
import { SearchTabs } from "../types/search.model";
|
||||||
import { IGroup } from "../types/actor";
|
import { IGroup } from "../types/actor";
|
||||||
import GroupCard from "../components/Group/GroupCard.vue";
|
import GroupCard from "../components/Group/GroupCard.vue";
|
||||||
import { CONFIG } from "../graphql/config";
|
import { CONFIG } from "../graphql/config";
|
||||||
|
@ -143,16 +171,15 @@ interface ISearchTimeOption {
|
||||||
end?: Date | null;
|
end?: Date | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum SearchTabs {
|
|
||||||
EVENTS = 0,
|
|
||||||
GROUPS = 1,
|
|
||||||
}
|
|
||||||
|
|
||||||
const tabsName: { events: number; groups: number } = {
|
const tabsName: { events: number; groups: number } = {
|
||||||
events: SearchTabs.EVENTS,
|
events: SearchTabs.EVENTS,
|
||||||
groups: SearchTabs.GROUPS,
|
groups: SearchTabs.GROUPS,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const EVENT_PAGE_LIMIT = 1;
|
||||||
|
|
||||||
|
const GROUP_PAGE_LIMIT = 10;
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
components: {
|
components: {
|
||||||
EventCard,
|
EventCard,
|
||||||
|
@ -173,6 +200,8 @@ const tabsName: { events: number; groups: number } = {
|
||||||
beginsOn: this.start,
|
beginsOn: this.start,
|
||||||
endsOn: this.end,
|
endsOn: this.end,
|
||||||
radius: this.radius,
|
radius: this.radius,
|
||||||
|
page: this.eventPage,
|
||||||
|
limit: EVENT_PAGE_LIMIT,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
debounce: 300,
|
debounce: 300,
|
||||||
|
@ -188,6 +217,8 @@ const tabsName: { events: number; groups: number } = {
|
||||||
term: this.search,
|
term: this.search,
|
||||||
location: this.geohash,
|
location: this.geohash,
|
||||||
radius: this.radius,
|
radius: this.radius,
|
||||||
|
page: this.groupPage,
|
||||||
|
limit: GROUP_PAGE_LIMIT,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
skip() {
|
skip() {
|
||||||
|
@ -213,6 +244,10 @@ export default class Search extends Vue {
|
||||||
|
|
||||||
searchGroups: Paginate<IGroup> = { total: 0, elements: [] };
|
searchGroups: Paginate<IGroup> = { total: 0, elements: [] };
|
||||||
|
|
||||||
|
eventPage = 1;
|
||||||
|
|
||||||
|
groupPage = 1;
|
||||||
|
|
||||||
search: string = (this.$route.query.term as string) || "";
|
search: string = (this.$route.query.term as string) || "";
|
||||||
|
|
||||||
activeTab: SearchTabs = tabsName[this.$route.query.searchType as "events" | "groups"] || 0;
|
activeTab: SearchTabs = tabsName[this.$route.query.searchType as "events" | "groups"] || 0;
|
||||||
|
@ -268,23 +303,27 @@ export default class Search extends Vue {
|
||||||
end: null,
|
end: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
radiusString = (radius: number | null) => {
|
EVENT_PAGE_LIMIT = EVENT_PAGE_LIMIT;
|
||||||
|
|
||||||
|
GROUP_PAGE_LIMIT = GROUP_PAGE_LIMIT;
|
||||||
|
|
||||||
|
radiusString = (radius: number | null): string => {
|
||||||
if (radius) {
|
if (radius) {
|
||||||
return this.$tc("{nb} km", radius, { nb: radius });
|
return this.$tc("{nb} km", radius, { nb: radius }) as string;
|
||||||
}
|
}
|
||||||
return this.$t("any distance");
|
return this.$t("any distance") as string;
|
||||||
};
|
};
|
||||||
|
|
||||||
radiusOptions: (number | null)[] = [1, 5, 10, 25, 50, 100, 150, null];
|
radiusOptions: (number | null)[] = [1, 5, 10, 25, 50, 100, 150, null];
|
||||||
|
|
||||||
radius = 50;
|
radius = 50;
|
||||||
|
|
||||||
submit() {
|
submit(): void {
|
||||||
this.$apollo.queries.searchEvents.refetch();
|
this.$apollo.queries.searchEvents.refetch();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Watch("search")
|
@Watch("search")
|
||||||
updateSearchTerm() {
|
updateSearchTerm(): void {
|
||||||
this.$router.push({
|
this.$router.push({
|
||||||
name: RouteName.SEARCH,
|
name: RouteName.SEARCH,
|
||||||
query: { ...this.$route.query, term: this.search },
|
query: { ...this.$route.query, term: this.search },
|
||||||
|
@ -292,7 +331,7 @@ export default class Search extends Vue {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Watch("activeTab")
|
@Watch("activeTab")
|
||||||
updateActiveTab() {
|
updateActiveTab(): void {
|
||||||
const searchType = this.activeTab === tabsName.events ? "events" : "groups";
|
const searchType = this.activeTab === tabsName.events ? "events" : "groups";
|
||||||
this.$router.push({
|
this.$router.push({
|
||||||
name: RouteName.SEARCH,
|
name: RouteName.SEARCH,
|
||||||
|
@ -308,7 +347,7 @@ export default class Search extends Vue {
|
||||||
return { start: startOfDay(start), end: endOfDay(end) };
|
return { start: startOfDay(start), end: endOfDay(end) };
|
||||||
}
|
}
|
||||||
|
|
||||||
get geohash() {
|
get geohash(): string | undefined {
|
||||||
if (this.location && this.location.geom) {
|
if (this.location && this.location.geom) {
|
||||||
const [lon, lat] = this.location.geom.split(";");
|
const [lon, lat] = this.location.geom.split(";");
|
||||||
return ngeohash.encode(lat, lon, 6);
|
return ngeohash.encode(lat, lon, 6);
|
||||||
|
|
Loading…
Reference in a new issue