Add group search

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
master
Thomas Citharel 2 years ago
parent 214400aaea
commit 3bae65374f
No known key found for this signature in database
GPG Key ID: A061B9DDE0CA0773
  1. 27
      js/src/components/Group/GroupCard.vue
  2. 48
      js/src/components/Group/GroupMemberCard.vue
  3. 4
      js/src/components/NavBar.vue
  4. 6
      js/src/components/SearchField.vue
  5. 2
      js/src/router/index.ts
  6. 6
      js/src/views/Group/GroupList.vue
  7. 6
      js/src/views/Group/MyGroups.vue
  8. 2
      js/src/views/PageNotFound.vue
  9. 64
      js/src/views/Search.vue

@ -9,21 +9,21 @@
</div>
<div class="media-content">
<router-link
:to="{ name: RouteName.GROUP, params: { preferredUsername: groupFullUsername } }"
:to="{
name: RouteName.GROUP,
params: { preferredUsername: usernameWithDomain(group) },
}"
>
<h3>{{ member.parent.name }}</h3>
<h3>{{ group.name }}</h3>
<p class="is-6 has-text-grey">
<span v-if="member.parent.domain">{{
`@${member.parent.preferredUsername}@${member.parent.domain}`
}}</span>
<span v-else>{{ `@${member.parent.preferredUsername}` }}</span>
<span v-if="group.domain">{{ `@${group.preferredUsername}@${group.domain}` }}</span>
<span v-else>{{ `@${group.preferredUsername}` }}</span>
</p>
<b-tag type="is-info">{{ member.role }}</b-tag>
</router-link>
</div>
</div>
<div class="content">
<p>{{ member.parent.summary }}</p>
<p>{{ group.summary }}</p>
</div>
</div>
</div>
@ -31,20 +31,15 @@
<script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator";
import { IGroup, IMember } from "@/types/actor";
import { IGroup, usernameWithDomain } from "@/types/actor";
import RouteName from "../../router/name";
@Component
export default class GroupCard extends Vue {
@Prop({ required: true }) member!: IMember;
@Prop({ required: true }) group!: IGroup;
RouteName = RouteName;
get groupFullUsername() {
if (this.member.parent.domain) {
return `${this.member.parent.preferredUsername}@${this.member.parent.domain}`;
}
return this.member.parent.preferredUsername;
}
usernameWithDomain = usernameWithDomain;
}
</script>

@ -0,0 +1,48 @@
<template>
<div class="card">
<div class="card-content">
<div class="media">
<div class="media-left">
<figure class="image is-48x48">
<img src="https://bulma.io/images/placeholders/96x96.png" alt="Placeholder image" />
</figure>
</div>
<div class="media-content">
<router-link
:to="{
name: RouteName.GROUP,
params: { preferredUsername: usernameWithDomain(member.parent) },
}"
>
<h3>{{ member.parent.name }}</h3>
<p class="is-6 has-text-grey">
<span v-if="member.parent.domain">{{
`@${member.parent.preferredUsername}@${member.parent.domain}`
}}</span>
<span v-else>{{ `@${member.parent.preferredUsername}` }}</span>
</p>
<b-tag type="is-info">{{ member.role }}</b-tag>
</router-link>
</div>
</div>
<div class="content">
<p>{{ member.parent.summary }}</p>
</div>
</div>
</div>
</template>
<script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator";
import { IMember, usernameWithDomain } from "@/types/actor";
import RouteName from "../../router/name";
@Component
export default class GroupMemberCard extends Vue {
@Prop({ required: true }) member!: IMember;
RouteName = RouteName;
usernameWithDomain = usernameWithDomain;
}
</script>

@ -137,9 +137,7 @@ import RouteName from "../router/name";
this.handleErrors(graphQLErrors);
},
},
config: {
query: CONFIG,
},
config: CONFIG,
},
components: {
Logo,

@ -8,7 +8,7 @@
type="search"
rounded
:placeholder="defaultPlaceHolder"
v-model="searchText"
v-model="search"
@keyup.native.enter="enter"
/>
</label>
@ -21,12 +21,12 @@ import RouteName from "../router/name";
export default class SearchField extends Vue {
@Prop({ type: String, required: false }) placeholder!: string;
searchText = "";
search: string = "";
enter() {
this.$router.push({
name: RouteName.SEARCH,
params: { searchTerm: this.searchText },
query: { term: this.search },
});
}

@ -49,7 +49,7 @@ const router = new Router({
...discussionRoutes,
...errorRoutes,
{
path: "/search/:searchTerm?/:searchType?",
path: "/search",
name: RouteName.SEARCH,
component: Search,
props: true,

@ -3,7 +3,7 @@
<h1>{{ $t("Group List") }} ({{ groups.total }})</h1>
<b-loading :active.sync="$apollo.loading" />
<div class="columns">
<GroupCard
<GroupMemberCard
v-for="group in groups.elements"
:key="group.uuid"
:group="group"
@ -20,7 +20,7 @@
import { Component, Vue } from "vue-property-decorator";
import { LIST_GROUPS } from "@/graphql/actor";
import { Group, IGroup } from "@/types/actor";
import GroupCard from "@/components/Group/GroupCard.vue";
import GroupMemberCard from "@/components/Group/GroupMemberCard.vue";
import RouteName from "../../router/name";
@Component({
@ -30,7 +30,7 @@ import RouteName from "../../router/name";
},
},
components: {
GroupCard,
GroupMemberCard,
},
})
export default class GroupList extends Vue {

@ -12,7 +12,7 @@
/>
</section>
<section v-if="memberships && memberships.length > 0">
<GroupCard v-for="member in memberships" :key="member.id" :member="member" />
<GroupMemberCard v-for="member in memberships" :key="member.id" :member="member" />
</section>
<b-message v-if="$apollo.loading === false && memberships.length === 0" type="is-danger">
{{ $t("No groups found") }}
@ -23,7 +23,7 @@
<script lang="ts">
import { Component, Vue } from "vue-property-decorator";
import { LOGGED_USER_MEMBERSHIPS } from "@/graphql/actor";
import GroupCard from "@/components/Group/GroupCard.vue";
import GroupMemberCard from "@/components/Group/GroupMemberCard.vue";
import InvitationCard from "@/components/Group/InvitationCard.vue";
import { Paginate } from "@/types/paginate";
import { IGroup, IMember, MemberRole } from "@/types/actor";
@ -32,7 +32,7 @@ import { ACCEPT_INVITATION } from "../../graphql/member";
@Component({
components: {
GroupCard,
GroupMemberCard,
InvitationCard,
},
apollo: {

@ -48,7 +48,7 @@ export default class PageNotFound extends Vue {
enter() {
this.$router.push({
name: RouteName.SEARCH,
params: { searchTerm: this.searchText },
query: { term: this.searchText },
});
}
}

@ -34,7 +34,7 @@
</b-select>
</b-field>
<b-field :label="$t('Date')" label-for="date">
<b-select v-model="when" id="date">
<b-select v-model="when" id="date" :disabled="activeTab !== 0">
<option v-for="(option, index) in options" :key="index" :value="option">{{
option.label
}}</option>
@ -78,6 +78,26 @@
$t("No events found")
}}</b-message>
</b-tab-item>
<b-tab-item v-if="config && config.features.groups">
<template slot="header">
<b-icon icon="account-multiple"></b-icon>
<span>
{{ $t("Groups") }} <b-tag rounded>{{ searchGroups.total }}</b-tag>
</span>
</template>
<div v-if="searchGroups.total > 0" class="columns is-multiline">
<div
class="column is-one-quarter-desktop"
v-for="group in searchGroups.elements"
:key="group.uuid"
>
<group-card :group="group" />
</div>
</div>
<b-message v-else-if="$apollo.loading === false" type="is-danger">
{{ $t("No groups found") }}
</b-message>
</b-tab-item>
</b-tabs>
</div>
</template>
@ -107,6 +127,9 @@ import {
startOfMonth,
eachWeekendOfInterval,
} from "date-fns";
import { IGroup } from "../types/actor";
import GroupCard from "../components/Group/GroupCard.vue";
import { CONFIG } from "../graphql/config";
interface ISearchTimeOption {
label: string;
@ -128,8 +151,10 @@ const tabsName: { events: number; groups: number } = {
components: {
EventCard,
AddressAutoComplete,
GroupCard,
},
apollo: {
config: CONFIG,
events: FETCH_EVENTS,
searchEvents: {
query: SEARCH_EVENTS,
@ -148,6 +173,17 @@ const tabsName: { events: number; groups: number } = {
return !this.search && !this.actualTag && !this.geohash && this.end === null;
},
},
searchGroups: {
query: SEARCH_GROUPS,
variables() {
return {
searchText: this.search,
};
},
skip() {
return this.search == null || this.search == "";
},
},
},
metaInfo() {
return {
@ -159,16 +195,14 @@ const tabsName: { events: number; groups: number } = {
},
})
export default class Search extends Vue {
@Prop({ type: String, required: false, default: "" }) searchTerm!: string;
@Prop({ type: String, required: false, default: "events" }) searchType!: "events" | "groups";
events: IEvent[] = [];
searchEvents: Paginate<IEvent> & { initial: boolean } = { total: 0, elements: [], initial: true };
searchGroups: Paginate<IGroup> = { total: 0, elements: [] };
search = this.searchTerm;
search: string = (this.$route.query.term as string) || "";
activeTab: SearchTabs = tabsName[this.searchType];
activeTab: SearchTabs = tabsName[this.$route.query.searchType as "events" | "groups"] || 0;
location: IAddress = new Address();
@ -230,15 +264,27 @@ export default class Search extends Vue {
radiusOptions: (number | null)[] = [1, 5, 10, 25, 50, 100, 150, null];
radius: number | undefined = undefined;
radius: number | null = null;
submit() {
this.$apollo.queries.searchEvents.refetch();
}
@Watch("searchTerm")
@Watch("search")
updateSearchTerm() {
this.search = this.searchTerm;
this.$router.push({
name: RouteName.SEARCH,
query: Object.assign({}, this.$route.query, { term: this.search }),
});
}
@Watch("activeTab")
updateActiveTab() {
const searchType = this.activeTab === tabsName.events ? "events" : "groups";
this.$router.push({
name: RouteName.SEARCH,
query: Object.assign({}, this.$route.query, { searchType }),
});
}
get weekend(): { start: Date; end: Date } {

Loading…
Cancel
Save