diff --git a/histoire.setup.ts b/histoire.setup.ts index bc0bb5ed..e558b776 100644 --- a/histoire.setup.ts +++ b/histoire.setup.ts @@ -37,3 +37,8 @@ const route = urlParams.get('route') if (route) { history.pushState({}, '', route) } + +// set theme attribute on load +if (document.documentElement.classList.contains('htw-dark')) { + document.documentElement.setAttribute('data-theme', 'dark') +} diff --git a/src/data-fetching/useDoctype.ts b/src/data-fetching/useDoctype.ts new file mode 100644 index 00000000..e69de29b diff --git a/src/data-fetching/useDocument.ts b/src/data-fetching/useDocument.ts new file mode 100644 index 00000000..e69de29b diff --git a/src/data-fetching/useFrappeFetch.ts b/src/data-fetching/useFrappeFetch.ts new file mode 100644 index 00000000..0bcd200d --- /dev/null +++ b/src/data-fetching/useFrappeFetch.ts @@ -0,0 +1,60 @@ +import { createFetch } from '@vueuse/core' + +const useFrappeFetch = createFetch({ + options: { + beforeFetch({ options }) { + options.headers = setHeaders(options.headers || {}) + return { options } + }, + afterFetch(ctx) { + console.log('afterFetch', ctx) + let data = JSON.parse(ctx.data).data + ctx.data = data + return ctx + }, + onFetchError(ctx) { + type FrappeError = { + title: string + message: string + type: string + indicator: string + } + let errors: Array = [] + try { + errors = JSON.parse(ctx.data).errors + } catch (e) { + errors = [ + { + title: 'Internal Server Error', + message: 'Internal Server Error', + type: 'ServerError', + indicator: 'red', + }, + ] + } + let error = errors[0] // assuming only one error for now + let frappeError = new Error(`${error.type}: ${error.message}`) + // e.type = error.type + // e.exception = exception + + ctx.error = frappeError + return ctx + }, + }, +}) + +function setHeaders(headers: HeadersInit) { + const defaultHeaders: Record = { + Accept: 'application/json', + 'Content-Type': 'application/json; charset=utf-8', + 'X-Frappe-Site-Name': window.location.hostname, + } + + if (window.csrf_token && window.csrf_token !== '{{ csrf_token }}') { + defaultHeaders['X-Frappe-CSRF-Token'] = window.csrf_token + } + + return { ...headers, ...defaultHeaders } +} + +export default useFrappeFetch diff --git a/src/data-fetching/useList.ts b/src/data-fetching/useList.ts new file mode 100644 index 00000000..ebee74c0 --- /dev/null +++ b/src/data-fetching/useList.ts @@ -0,0 +1,41 @@ +import useFrappeFetch from './useFrappeFetch' + +interface ListOptions { + filters: any + fields: string[] +} + +export default function useList( + doctype: string, + options: ListOptions = { filters: {}, fields: [] }, +) { + let params = new URLSearchParams() + if (options.fields?.length) { + params.append('fields', JSON.stringify(options.fields)) + } + if (options.filters) { + params.append('filters', JSON.stringify(options.filters)) + } + let url = `/api/v2/document/${doctype}?${params.toString()}` + const { + data, + error, + isFetching, + isFinished, + canAbort, + abort, + aborted, + execute, + } = useFrappeFetch(url) + + return { + data, + error, + isFetching, + isFinished, + canAbort, + abort, + aborted, + execute, + } +}