Finish Search

This commit is contained in:
Jai A
2020-09-17 22:14:57 -07:00
parent aa8215df34
commit 24035c4ae8
2 changed files with 228 additions and 119 deletions

100
components/Pagination.vue Normal file
View File

@@ -0,0 +1,100 @@
<template>
<div v-if="pages.length > 1" class="columns paginates">
<svg
:class="{ 'disabled-paginate': currentPage === 1 }"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
@click="currentPage !== 1 ? switchPage(currentPage - 1) : null"
>
<polyline points="15 18 9 12 15 6"></polyline>
</svg>
<p
v-for="(item, index) in pages"
:key="'page-' + item"
:class="{
'active-page-number': currentPage !== item,
}"
@click="currentPage !== item ? switchPage(item) : null"
>
<span v-if="pages[index - 1] + 1 !== item && item !== 1">...</span>
<span :class="{ 'disabled-page-number': currentPage === item }">{{
item
}}</span>
</p>
<svg
:class="{
'disabled-paginate': currentPage === pages[pages.length - 1],
}"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
@click="
currentPage !== pages[pages.length - 1]
? switchPage(currentPage + 1)
: null
"
>
<polyline points="9 18 15 12 9 6"></polyline>
</svg>
</div>
</template>
<script>
export default {
name: 'Pagination',
props: {
currentPage: {
type: Number,
default: 1,
},
pages: {
type: Array,
default() {
return []
},
},
},
methods: {
switchPage(newPage) {
this.$emit('switch-page', newPage)
},
},
}
</script>
<style scoped>
.paginates {
align-items: center;
}
.paginates p {
margin-left: 5px;
margin-right: 5px;
}
.disabled-paginate {
cursor: default;
color: var(--color-grey-5);
}
.active-page-number {
user-select: none;
cursor: pointer;
}
.disabled-page-number {
user-select: none;
cursor: default;
padding: 2px 3px;
border-radius: 3px;
background-color: var(--color-grey-1);
}
</style>

View File

@@ -2,7 +2,7 @@
<div class="columns"> <div class="columns">
<div class="content column-grow-4"> <div class="content column-grow-4">
<h2>Mods</h2> <h2>Mods</h2>
<section id="search-pagination"> <section class="search-bar">
<div class="iconified-input column-grow-2"> <div class="iconified-input column-grow-2">
<input <input
id="search" id="search"
@@ -43,52 +43,11 @@
<polyline points="6 9 12 15 18 9"></polyline> <polyline points="6 9 12 15 18 9"></polyline>
</svg> </svg>
</div> </div>
<div v-if="pages.length > 1" class="columns paginates"> <pagination
<svg :current-page="currentPage"
:class="{ 'disabled-paginate': currentPage === 1 }" :pages="pages"
viewBox="0 0 24 24" @switch-page="onSearchChange"
fill="none" ></pagination>
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
@click="currentPage !== 1 ? onSearchChange(currentPage - 1) : null"
>
<polyline points="15 18 9 12 15 6"></polyline>
</svg>
<p
v-for="(item, index) in pages"
:key="'page-' + item"
:class="{
'active-page-number': currentPage !== item,
}"
@click="currentPage !== item ? onSearchChange(item) : null"
>
<span v-if="pages[index - 1] + 1 !== item && item !== 1">...</span>
<span :class="{ 'disabled-page-number': currentPage === item }">{{
item
}}</span>
</p>
<svg
:class="{
'disabled-paginate': currentPage === pages[pages.length - 1],
}"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
@click="
currentPage !== pages[pages.length - 1]
? onSearchChange(currentPage + 1)
: null
"
>
<polyline points="9 18 15 12 9 6"></polyline>
</svg>
</div>
</section> </section>
<div class="results column-grow-4"> <div class="results column-grow-4">
<SearchResult <SearchResult
@@ -108,6 +67,34 @@
:categories="result.categories" :categories="result.categories"
/> />
</div> </div>
<section v-if="pages.length > 1" class="search-bottom">
<div class="iconified-select">
<select id="max-results" @input="changeMaxResults">
<option value="5" selected>5</option>
<option value="10">10</option>
<option value="15">15</option>
<option value="20">20</option>
<option value="50">50</option>
<option value="100">100</option>
</select>
<svg
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
</div>
<pagination
:current-page="currentPage"
:pages="pages"
@switch-page="onSearchChangeToTop"
></pagination>
</section>
</div> </div>
<section class="filters"> <section class="filters">
<!--#region filters --> <!--#region filters -->
@@ -374,6 +361,7 @@
import Multiselect from 'vue-multiselect' import Multiselect from 'vue-multiselect'
import axios from 'axios' import axios from 'axios'
import SearchResult from '@/components/ModResult' import SearchResult from '@/components/ModResult'
import Pagination from '@/components/Pagination'
const config = { const config = {
headers: { headers: {
@@ -384,6 +372,7 @@ const config = {
export default { export default {
components: { components: {
SearchResult, SearchResult,
Pagination,
Multiselect, Multiselect,
}, },
data() { data() {
@@ -395,12 +384,11 @@ export default {
results: [], results: [],
pages: [], pages: [],
currentPage: 1, currentPage: 1,
overrideOffset: 0,
sortType: 'relevance', sortType: 'relevance',
maxResults: 6, maxResults: 5,
} }
}, },
async mounted() { async created() {
if (this.$route.query.q) this.query = this.$route.query.q if (this.$route.query.q) this.query = this.$route.query.q
if (this.$route.query.f) { if (this.$route.query.f) {
const facets = this.$route.query.f.split(',') const facets = this.$route.query.f.split(',')
@@ -409,16 +397,21 @@ export default {
} }
if (this.$route.query.v) if (this.$route.query.v)
this.selectedVersions = this.$route.query.v.split(',') this.selectedVersions = this.$route.query.v.split(',')
if (this.$route.query.s) this.sortType = this.$route.query.s if (this.$route.query.s) {
if (this.$route.query.o) this.overrideOffset = this.$route.query.o this.sortType = this.$route.query.s
}
if (this.$route.query.m) {
this.maxResults = this.$route.query.m
}
if (this.$route.query.o)
this.currentPage = Math.ceil(this.$route.query.o / this.maxResults) + 1
await this.fillInitialVersions() await this.fillInitialVersions()
await this.onSearchChange(this.currentPage)
window.addEventListener('resize', this.resize)
await this.resize()
}, },
destroyed() { mounted() {
window.removeEventListener('resize', this.resize) document.getElementById('sort-type').value = this.sortType
document.getElementById('max-results').value = this.maxResults
}, },
methods: { methods: {
async fillInitialVersions() { async fillInitialVersions() {
@@ -429,27 +422,20 @@ export default {
) )
const versions = res.data.versions const versions = res.data.versions
const betaVersions = []
const legacyVersions = []
for (const version of versions) { for (const version of versions) {
this.versions.push(version.id) if (version.type === 'release') this.versions.push(version.id)
if (version.type === 'snapshot') betaVersions.push(version.id)
if (version.type === 'old_beta' || version.type === 'old_alpha')
legacyVersions.push(version.id)
} }
this.versions.concat(betaVersions, legacyVersions)
} catch (err) { } catch (err) {
// eslint-disable-next-line no-console
console.error(err) console.error(err)
} }
}, },
async resize() {
const vh = Math.max(
document.documentElement.clientHeight || 0,
window.innerHeight || 0
)
this.maxResults = Math.floor((vh - 200) / 120)
await this.onSearchChange(this.currentPage)
if (this.currentPage > this.pages[this.pages.length - 1]) {
this.currentPage = this.pages[this.pages.length - 1]
await this.onSearchChange(this.currentPage)
}
},
async clearFilters() { async clearFilters() {
for (const facet of [...this.facets]) await this.toggleFacet(facet, true) for (const facet of [...this.facets]) await this.toggleFacet(facet, true)
@@ -457,24 +443,38 @@ export default {
await this.onSearchChange(1) await this.onSearchChange(1)
}, },
async toggleFacet(elementName, sendRequest) { async toggleFacet(elementName, sendRequest) {
const element = document.getElementById(elementName) const element = process.client
const index = this.facets.indexOf(element.id) ? document.getElementById(elementName)
: null
const index = this.facets.indexOf(elementName)
if (index !== -1) { if (index !== -1) {
element.classList.remove('filter-active') if (process.client) element.classList.remove('filter-active')
this.facets.splice(index, 1) this.facets.splice(index, 1)
} else { } else {
element.classList.add('filter-active') if (process.client) element.classList.add('filter-active')
this.facets.push(element.id) this.facets.push(elementName)
} }
if (!sendRequest) await this.onSearchChange(1) if (!sendRequest) await this.onSearchChange(1)
}, },
async changeSortType() { async changeSortType() {
this.sortType = document.getElementById('sort-type').value if (process.client)
this.sortType = document.getElementById('sort-type').value
await this.onSearchChange(1) await this.onSearchChange(1)
}, },
async changeMaxResults() {
if (process.client)
this.maxResults = document.getElementById('max-results').value
await this.onSearchChangeToTop(1)
},
async onSearchChangeToTop(newPageNumber) {
if (process.client) window.scrollTo(0, 0)
await this.onSearchChange(newPageNumber)
},
async onSearchChange(newPageNumber) { async onSearchChange(newPageNumber) {
try { try {
const params = [`limit=${this.maxResults}`, `index=${this.sortType}`] const params = [`limit=${this.maxResults}`, `index=${this.sortType}`]
@@ -501,11 +501,7 @@ export default {
} }
const offset = (newPageNumber - 1) * this.maxResults const offset = (newPageNumber - 1) * this.maxResults
if (this.overrideOffset > 0) { if (newPageNumber !== 1) {
console.log(this.overrideOffset)
params.push(`offset=${this.overrideOffset}`)
this.overrideOffset = 0
} else if (newPageNumber !== 1) {
params.push(`offset=${offset}`) params.push(`offset=${offset}`)
} }
@@ -547,15 +543,21 @@ export default {
this.pages = Array.from({ length: pageAmount }, (_, i) => i + 1) this.pages = Array.from({ length: pageAmount }, (_, i) => i + 1)
} }
url = `mods?q=${encodeURIComponent( if (process.client) {
this.query url = `mods?q=${encodeURIComponent(this.query)}`
)}&o=${offset}&f=${encodeURIComponent(
this.facets.toString()
)}&v=${encodeURIComponent(
this.selectedVersions.toString()
)}&s=${encodeURIComponent(this.sortType)}`
window.history.pushState(new Date(), 'Mods', url) if (offset > 0) url += `&o=${offset}`
if (this.facets.length > 0)
url += `&f=${encodeURIComponent(this.facets)}`
if (this.selectedVersions.length > 0)
url += `&v=${encodeURIComponent(this.selectedVersions)}`
if (this.sortType !== 'relevance')
url += `&s=${encodeURIComponent(this.sortType)}`
if (this.maxResults > 5)
url += `&m=${encodeURIComponent(this.maxResults)}`
window.history.pushState(new Date(), 'Mods', url)
}
} catch (err) { } catch (err) {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
console.error(err) console.error(err)
@@ -570,23 +572,24 @@ export default {
<style src="vue-multiselect/dist/vue-multiselect.min.css"></style> <style src="vue-multiselect/dist/vue-multiselect.min.css"></style>
<style lang="scss"> <style lang="scss">
#search-pagination { .search-bar {
align-items: center; align-items: center;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
} }
.paginates { .search-bottom {
align-items: center; align-items: center;
} display: flex;
justify-content: flex-end;
.paginates p { select {
margin-left: 5px; width: 100px;
margin-right: 5px; margin-right: 20px;
}
} }
.content { .content {
min-height: 95vh; min-height: 96vh;
} }
.filters { .filters {
@@ -620,12 +623,14 @@ export default {
button { button {
width: 100%; width: 100%;
padding: 5px 0; padding: 5px 0;
color: #718096; outline: none;
color: var(--color-grey-5);
background-color: var(--color-grey-1);
border: none; border: none;
border-radius: 5px; border-radius: 5px;
&:hover { &:hover {
background-color: var(--color-grey-1); background-color: var(--color-grey-2);
color: var(--color-text); color: var(--color-text);
} }
} }
@@ -661,24 +666,6 @@ export default {
} }
} }
.disabled-paginate {
cursor: default;
color: var(--color-grey-3);
}
.active-page-number {
user-select: none;
cursor: pointer;
}
.disabled-page-number {
user-select: none;
cursor: default;
padding: 2px 3px;
border-radius: 3px;
background-color: var(--color-grey-3);
}
.iconified-select { .iconified-select {
margin-left: 1em; margin-left: 1em;
align-items: center; align-items: center;
@@ -726,4 +713,26 @@ select {
color: var(--color-text); color: var(--color-text);
} }
} }
.multiselect__tags {
background: var(--color-bg);
}
.multiselect__input {
color: var(--color-text);
background: var(--color-bg);
}
.multiselect__option {
color: var(--color-text);
background: var(--color-bg);
}
.multiselect__option--highlight {
background: var(--color-brand);
}
.multiselect__tag {
background: var(--color-brand);
}
</style> </style>