Last active
October 14, 2022 16:35
-
-
Save daltonrooney/927a68196e915829349b7a087a1644a5 to your computer and use it in GitHub Desktop.
Craft CMS GQL query w/ filters and pagination
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Vue from 'vue' | |
import { debounce } from './utils/debounce'; | |
import { ProCatalogCategoriesQuery } from './queries/proCatalogCategories.gql'; | |
import { makeProCatalogResourcesQuery } from './queries/proCatalogResources'; | |
import Loading from './components/loading.vue'; | |
const GraphqlEndpoint = '/api' | |
const ResultsPerPage = 12; | |
const el = document.querySelector('#professional-catalog-app') | |
if (el !== null) { | |
const vm = new Vue({ | |
delimiters: ['${', '}'], | |
components: { | |
Loading | |
}, | |
data: { | |
results: [], | |
topics: [], | |
currentPage: 1, | |
totalPages: 0, | |
pagination: { | |
pages: [], | |
hasNext: false, | |
hasPrev: false, | |
nextPageUrl: '', | |
prevPageUrl: '', | |
}, | |
baseUrl: '', | |
searching: false, | |
loaded: false, | |
selectedTopic: '', | |
selectedCourseType: '', | |
textKeywords: '', | |
}, | |
watch: { | |
totalPages() { | |
this.updatePagination(); | |
} | |
}, | |
computed: { | |
catalogClass() { | |
return { | |
'catalog-items--searching': this.searching, | |
'catalog--loaded': true, | |
} | |
} | |
}, | |
methods: { | |
async queryGraphQL(query) { | |
const response = await fetch(GraphqlEndpoint, { | |
method: 'POST', | |
cache: 'no-cache', | |
credentials: 'same-origin', | |
headers: { | |
'Content-Type': 'application/graphql' | |
}, | |
body: query | |
}); | |
return await response.json(); | |
}, | |
async updateCategories() { | |
const response = await this.queryGraphQL(ProCatalogCategoriesQuery); | |
this.topics = response.data.topics; | |
}, | |
async updateResults() { | |
const { selectedTopic, selectedCourseType, textKeywords } = this; | |
const params = []; | |
this.searching = true; | |
if (selectedTopic) params.push(`courseTopic: ${selectedTopic}`); | |
if (selectedCourseType) params.push(`courseType: "${selectedCourseType}"`); | |
if (textKeywords) params.push(`search: "${textKeywords}"`); | |
params.push('section: "professionalLearningCourses"'); | |
params.push(`limit: ${ResultsPerPage}`); | |
params.push(`offset: ${(this.currentPage - 1) * ResultsPerPage}`); | |
params.push('orderBy: "title ASC"'); | |
const query = makeProCatalogResourcesQuery(params); | |
const response = await this.queryGraphQL(query); | |
if (response.data) { | |
this.totalPages = Math.ceil(Number(response.data.entryCount) / ResultsPerPage); | |
this.results = response.data.entries; | |
} else { | |
this.results = []; | |
this.totalPages = 0; | |
} | |
setTimeout(() => { | |
this.searching = false; | |
}, 1000); | |
}, | |
updateCurrentPage() { | |
const pageRegex = window.location.pathname.match(/\/page\/(\d+)$/); | |
this.currentPage = 1; | |
if (pageRegex) { | |
this.currentPage = Number(pageRegex[1]); | |
} | |
}, | |
formatDateRange(dateFrom, dateTo) { | |
if (!dateFrom || !dateTo) return ''; | |
const [monthFrom, dayFrom] = dateFrom.split('-'); | |
const [monthTo, dayTo] = dateTo.split('-'); | |
if (monthFrom === monthTo) { | |
return `${monthFrom} ${dayFrom}-${dayTo}`; | |
} else { | |
return `${monthFrom} ${dayFrom} - ${monthTo} ${dayTo}`; | |
} | |
}, | |
getBackgroundStyle(entry) { | |
const url = entry.featuredImage[0] ? entry.featuredImage[0].url : ''; | |
return `background-image: url('${url}')`; | |
}, | |
getPageUrl(index = this.currentPage) { | |
const { baseUrl } = this; | |
let url = new URL(baseUrl); | |
if (this.selectedCourseType) url.searchParams.set('courseType', this.selectedCourseType); | |
if (this.selectedTopic) url.searchParams.set('topic', this.selectedTopic); | |
if (this.textKeywords) url.searchParams.set('q', `${this.textKeywords}`); | |
if (index > 1) { | |
url.pathname += `/page/${index}`; | |
} | |
return url.toString(); | |
}, | |
resetPagination() { | |
this.currentPage = 1; | |
const url = this.getPageUrl(); | |
if (window.history.replaceState) { | |
window.history.replaceState(null, '', url); | |
} | |
}, | |
restoreFromUrlParams() { | |
const url = new URL(window.location.href); | |
const params = url.searchParams; | |
if (params.has('courseType')) this.selectedCourseType = params.get('courseType'); | |
if (params.has('topic')) this.selectedTopic = params.get('topic'); | |
if (params.has('q')) this.textKeywords = params.get('q'); | |
}, | |
updatePagination() { | |
const { pagination, currentPage, totalPages } = this; | |
pagination.pages = []; | |
for (let i = 0; i < totalPages; i++) { | |
const index = i + 1; | |
pagination.pages.push({ | |
text: index, | |
url: this.getPageUrl(index), | |
current: index === currentPage | |
}); | |
} | |
pagination.hasNext = currentPage < totalPages; | |
pagination.hasPrev = currentPage > 1; | |
pagination.nextPageUrl = this.getPageUrl(currentPage + 1); | |
pagination.prevPageUrl = this.getPageUrl(currentPage - 1); | |
}, | |
onSearchFilterChanged() { | |
this.resetPagination(); | |
this.updateCurrentPage(); | |
this.updateResultsDebounced(); | |
} | |
}, | |
async mounted() { | |
this.baseUrl = this.$refs.pagination.getAttribute('data-base-url'); | |
this.updateResultsDebounced = debounce(this.updateResults, 500); | |
this.restoreFromUrlParams(); | |
this.updateCurrentPage(); | |
await this.updateCategories(); | |
await this.updateResults(); | |
this.loaded = true; | |
} | |
}) | |
vm.$mount(el) | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export const ProCatalogCategoriesQuery = ` | |
query { | |
topics: categories(group: "topic") { | |
... on topic_Category { id, title } | |
} | |
levels: categories(group: "level") { | |
... on level_Category { id, title } | |
} | |
} | |
` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export function makeProCatalogResourcesQuery(params = []) { | |
return ` | |
{ | |
entries(${params.join(', ')}) { | |
... on professionalLearningCourses_professionalLearningCourses_Entry { | |
id | |
url | |
title | |
} | |
} | |
entryCount(${params.join(', ')}) | |
}` | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment