diff --git a/packages/frontend/app/components/reports/subject/learning-material.js b/packages/frontend/app/components/reports/subject/learning-material.js index 7a58fbe6e0..ce655e1b44 100644 --- a/packages/frontend/app/components/reports/subject/learning-material.js +++ b/packages/frontend/app/components/reports/subject/learning-material.js @@ -10,6 +10,9 @@ export default class ReportsSubjectLearningMaterialComponent extends Component { @service graphql; @service intl; + controller = new AbortController(); + signal = this.controller.signal; + @cached get data() { return new TrackedAsyncData( @@ -58,7 +61,19 @@ export default class ReportsSubjectLearningMaterialComponent extends Component { prepositionalObjectTableRowId, school, ); - const result = await this.graphql.find('learningMaterials', filters, 'id, title'); + + if (this.graphql.findTask.isRunning) { + this.controller.abort('running query canceled so new one could run'); + } + this.controller = new AbortController(); + this.signal = this.controller.signal; + + const result = await this.graphql.findTask.perform( + 'learningMaterials', + filters, + 'id, title', + this.signal, + ); return result.data.learningMaterials.map(({ title }) => title); } diff --git a/packages/frontend/app/services/graphql.js b/packages/frontend/app/services/graphql.js index 6619880cca..d01b45c5fc 100644 --- a/packages/frontend/app/services/graphql.js +++ b/packages/frontend/app/services/graphql.js @@ -1,4 +1,5 @@ import Service, { service } from '@ember/service'; +import { task } from 'ember-concurrency'; export default class GraphqlService extends Service { @service session; @@ -39,4 +40,41 @@ export default class GraphqlService extends Service { const filterString = filters.length ? '(' + filters.join(', ') + ')' : ''; return this.#query(`query { ${endpoint}${filterString} { ${attributes} } }`); } + + findTask = task(async (endpoint, filters, attributes, signal) => { + const filterString = filters.length ? '(' + filters.join(', ') + ')' : ''; + const url = `${this.host}/api/graphql`; + const headers = this.authHeaders; + headers['Content-Type'] = 'application/json'; + headers['Accept'] = 'application/json'; + const q = `query { ${endpoint}${filterString} { ${attributes} } }`; + + let response = null; + try { + response = await fetch(url, { + method: 'POST', + headers, + body: JSON.stringify({ query: q }), + signal, + }); + + return response.json(); + } catch (e) { + if (signal.aborted) { + if (signal.reason) { + console.log(`graphql canceled with reason: ${signal.reason}`); + } else { + console.warn('graphql canceled but no reason was given.'); + } + } else { + console.error('graphql failed due to unknown error', e); + } + + return { + error: 'bad stuff', + }; + } finally { + console.log('graphql completed'); + } + }); }