diff --git a/client/src/components/circle/LearningSequence.vue b/client/src/components/circle/LearningSequence.vue index 1d5a2405..23780eec 100644 --- a/client/src/components/circle/LearningSequence.vue +++ b/client/src/components/circle/LearningSequence.vue @@ -1,5 +1,6 @@ @@ -28,7 +29,10 @@ defineProps(['learningSequence']) v-for="learningContent in learningUnit.learningContents" class="flex items-center gap-4 pb-3" > - +
+ + +
{{ learningContent.contents[0].type }}: {{ learningContent.title }}
diff --git a/client/src/fetchHelpers.js b/client/src/fetchHelpers.js new file mode 100644 index 00000000..bc397aa1 --- /dev/null +++ b/client/src/fetchHelpers.js @@ -0,0 +1,53 @@ +import { getCookieValue } from '@/router/guards'; + +class FetchError extends Error { + constructor(response, message = 'HTTP error ' + response.status) { + super(message); + this.response = response; + } +} + +export const itFetch = (url, options) => { + return fetch(url, options).then(response => { + if (!response.ok) { + throw new FetchError(response); + } + + return response; + }); +}; + +export const itPost = (url, data, options) => { + options = Object.assign({}, options); + + const headers = Object.assign({ + Accept: 'application/json', + 'Content-Type': 'application/json;charset=UTF-8', + }, options?.headers); + + if (options?.headers) { + delete options.headers; + } + + options = Object.assign({ + method: 'POST', + headers: headers, + body: JSON.stringify(data) + }, options); + + options.headers['X-CSRFToken'] = getCookieValue('csrftoken'); + + if (options.method === 'GET') { + delete options.body; + } + + return itFetch(url, options).then((response) => { + return response.json().catch(() => { + return Promise.resolve(null); + }); + }); +}; + +export const itGet = (url) => { + return itPost(url, {}, {method: 'GET'}); +}; diff --git a/client/src/router/guards.ts b/client/src/router/guards.ts index a4a909d8..b96e1849 100644 --- a/client/src/router/guards.ts +++ b/client/src/router/guards.ts @@ -22,7 +22,7 @@ export const redirectToLoginIfRequired: NavigationGuardWithThis = (to } } -const getCookieValue = (cookieName: string): string => { +export const getCookieValue = (cookieName: string): string => { // https://stackoverflow.com/questions/5639346/what-is-the-shortest-function-for-reading-a-cookie-by-name-in-javascript const cookieValue = document.cookie.match('(^|[^;]+)\\s*' + cookieName + '\\s*=\\s*([^;]+)') if (!cookieValue) { diff --git a/client/src/stores/user.ts b/client/src/stores/user.ts index 7b450ba0..15a52714 100644 --- a/client/src/stores/user.ts +++ b/client/src/stores/user.ts @@ -1,4 +1,4 @@ -import { defineStore } from 'pinia' +import {defineStore} from 'pinia' // typed state https://stackoverflow.com/questions/71012513/when-using-pinia-and-typescript-how-do-you-use-an-action-to-set-the-state export type UserState = { diff --git a/client/src/views/CircleView.vue b/client/src/views/CircleView.vue index f8d26c7e..55154b55 100644 --- a/client/src/views/CircleView.vue +++ b/client/src/views/CircleView.vue @@ -1,9 +1,9 @@