Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Speak-32 Add search algorithm #195

Merged
merged 6 commits into from
Dec 15, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 64 additions & 8 deletions web/src/components/Search.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,25 @@
sm="6"
>
<v-autocomplete
label="Topic"
placeholder="Start typing to Search"
:label="$t('findSpeaker.topics')"
:placeholder="$t('findSpeaker.searchPlaceholder')"
prepend-icon="search"
clearable
:items="topicItems"
@change="selectItem('topic', $event)"
/>
</v-col>
<v-col
cols="12"
sm="6"
>
<v-autocomplete
label="City, Prefecture, or Region"
placeholder="Start typing to Search"
:label="$t('findSpeaker.places')"
:placeholder="$t('findSpeaker.searchPlaceholder')"
prepend-icon="search"
clearable
:items="locationItems"
@change="selectItem('location', $event)"
/>
</v-col>
</v-row>
Expand All @@ -27,10 +33,60 @@

<script>
export default {
data() {
return {

};
data: () => ({
topic: '',
location: '',
topicItems: [],
locationItems: [],
}),
created() {
this.getTopicItems();
this.getLocationItems();
},
methods: {
selectItem(fieldName, value) {
this[fieldName] = value || '';
this.emitValues();
},
emitValues() {
bus.$emit('search-by-params', {
topic: this.topic,
location: this.location,
});
},
getTopicItems() {
this.$db('Topics')
.select({
view: 'All',
fields: ['name'],
sort: [{ field: 'name', direction: 'asc' }],
})
.eachPage(
(records) => {
const topics = this.getItemsWithField(records, 'name');
this.topicItems.push(...topics);
},
);
},
getLocationItems() {
this.$db('Location')
.select({
view: 'All',
fields: ['prefecture'],
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤔 I just noticed that the region column is in the DB, but there are no values. Probably best to add it later and fill out the DB.

sort: [
{ field: 'prefecture', direction: 'asc' },
],
})
.eachPage(
(records) => {
const prefectureNames = this.getItemsWithField(records, 'prefecture');
this.locationItems.push(...prefectureNames);
},
);
},
getItemsWithField(records, fieldName) {
return records.map((record) => record.get(fieldName)).filter(Boolean);
},
},
};
</script>
5 changes: 5 additions & 0 deletions web/src/components/no-results/NoResults.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<template>
<div class="pa-9 text-center">
<span class="display-1">{{ $t('findSpeaker.noResults') }}</span>
</div>
</template>
6 changes: 5 additions & 1 deletion web/src/i18n/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,11 @@
},
"findSpeaker": {
"title": "Find a speaker",
"pronouns": "Pronouns: {0}"
"pronouns": "Pronouns: {0}",
"topics": "Topic",
"places": "Prefecture",
"searchPlaceholder": "Start typing to Search",
"noResults": "No speakers found"
},
"footer": {
"title": "SpeakHer Japan 2020",
Expand Down
92 changes: 58 additions & 34 deletions web/src/views/FindSpeaker.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
<contact-dialog
:speaker="selectedSpeaker"
:show="showDialog"
@close="showDialog=false"
@submit="showDialog= false; showSuccess = true"
@close="showDialog = false"
@submit="showDialog = false; showSuccess = true"
/>
<contact-result
:show="showSuccess"
Expand All @@ -16,30 +16,32 @@
no-gutters
>
<v-col lg="10">
<v-row>
<h2 class="mx-2 mb-2">
<v-row
justify="space-between"
align="center"
>
<h2 class="py-2">
{{ $t('findSpeaker.title') }}
</h2>
<pagination-row
v-if="speakers.length"
:first-entry="(page - 1) * pageSize + 1"
:last-entry="lastEntry"
:is-last-page="isLastPage"
@onNextPage="getNextPage()"
@onPrevPage="getPreviousPage()"
/>
</v-row>
<pagination-row
v-if="speakers.length"
:first-entry="(page - 1) * pageSize + 1"
:last-entry="lastEntry"
:is-last-page="isLastPage"
@onNextPage="getNextPage()"
@onPrevPage="getPreviousPage()"
/>
<search v-if="false" />
<search />
<v-row
v-if="isLoading"
justify="space-around"
class="my-10"
>
<v-col lg="1">
<v-progress-circular
indeterminate
color="primary"
/>
</v-col>
<v-progress-circular
indeterminate
color="primary"
/>
</v-row>
<div
v-if="!isLoading"
Expand All @@ -65,6 +67,7 @@
@onNextPage="getNextPage()"
@onPrevPage="getPreviousPage()"
/>
<no-results v-if="hasNoSpeakers" />
</v-col>
</v-row>
</v-container>
Expand All @@ -73,11 +76,12 @@
<script>
// @ is an alias to /src
import api from '@/services/api';
import SpeakerCard from '@/components/speaker/SpeakerCard.vue';
import Search from '@/components/Search.vue';
import SpeakerCard from '@/components/speaker/SpeakerCard.vue';
import ContactDialog from '@/components/contact/ContactDialog.vue';
import ContactResult from '@/components/contact/ContactResult.vue';
import PaginationRow from '@/components/PaginationRow.vue';
import NoResults from '@/components/no-results/NoResults.vue';

export default {
components: {
Expand All @@ -86,6 +90,7 @@ export default {
Search,
SpeakerCard,
PaginationRow,
NoResults,
},
data: () => ({
speakers: [],
Expand All @@ -103,13 +108,12 @@ export default {
}),
computed: {
selectedName() {
if (this.selectedSpeaker) {
if (this.$i18n.locale === 'ja') {
return this.selectedSpeaker.get('name_ja') || this.selectedSpeaker.get('name_en') || '';
}
return this.selectedSpeaker.get('name_en') || '';
if (!this.selectedSpeaker) return '';
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we keep this PR focused on search and avoid making other refactors? It gets confusing to follow the changes.


if (this.$i18n.locale === 'ja') {
return this.selectedSpeaker.get('name_ja') || this.selectedSpeaker.get('name_en') || '';
}
return '';
return this.selectedSpeaker.get('name_en') || '';
},
getSpeakersForPage() {
const offset = (this.page - 1) * this.pageSize;
Expand All @@ -119,22 +123,32 @@ export default {
const lastPageEntry = this.page * this.pageSize;
return lastPageEntry > this.speakers.length ? this.speakers.length : lastPageEntry;
},
hasNoSpeakers() {
return !this.speakers.length && !this.isLoading;
},
},
mounted() {
api.getLocations(this.setPrefectures, this.setError);
api.getTopics(this.setTopics, this.setError);
api.getLanguages(this.setLanguageList, this.setError);
this.getSpeakers();

bus.$on('contact-speaker', (speaker) => {
this.selectedSpeaker = speaker;
this.showDialog = true;
});
this.setupBusEvents();
},
beforeDestroy() {
bus.$off('contact-speaker');
bus.$off('search-by-params');
},
methods: {
setupBusEvents() {
bus.$on('contact-speaker', (speaker) => {
this.selectedSpeaker = speaker;
this.showDialog = true;
});
bus.$on('search-by-params', (params) => {
this.resetPreSearchParams();
this.getSpeakers(params);
});
},
setPrefectures(records) {
this.prefectures = records;
},
Expand Down Expand Up @@ -177,35 +191,45 @@ export default {

this.getNextPageInternal();
},
getSpeakers() {
getSpeakers(params = { topic: '', location: '' }) {
const filter = `AND(FIND("${params.topic}", topics), FIND("${params.location}", location_id))`;

this.$db('People')
.select({
view: 'Published',
sort: [{ field: 'name_en', direction: 'asc' }],
pageSize: this.pageSize,
filterByFormula: filter,
})
.eachPage(
(records, next) => {
this.speakers.push(...records);
this.page += 1;
this.airTableNextPage = next;
this.isLoading = false;
this.isLastPage = this.pageSize > records.length;
},
(err) => {
if (err) {
this.error = err;
}

// if the error is null no new page exists
this.isLastPage = true;
this.isLoading = false;

// set airTableNextPage to undefined to mark that we can not fetch any more pages
// and have to switch to internal pagination logic
this.airTableNextPage = undefined;
},
);
},
resetPreSearchParams() {
this.speakers = [];
this.page = 0;
this.isLastPage = false;
this.isLoading = true;
this.airTableNextPage = undefined;
this.selectedSpeaker = undefined;
},
},
};
</script>