Commit c6a960b4 authored by Ernesto Rico Schmidt's avatar Ernesto Rico Schmidt
Browse files

Merge branch 'kmohrf/flow-control' into 'master'

Allow API store consumers to use traditional flow-control

See merge request !10
parents a8014ba0 f4da882f
Pipeline #1871 passed with stages
in 6 minutes and 31 seconds
import { has } from '@/utilities'
function isErrorObject (obj) {
return has(obj, 'message') && has(obj, 'code')
}
/**
* Parses the variety of error formats that are emitted by
* Django REST framework and yields error objects.
*/
function * extractResponseErrors(responseData) {
if (isErrorObject(responseData)) {
yield responseData
} else if (has(responseData, 'detail') && isErrorObject(responseData.detail)) {
yield responseData.detail
} else if (Array.isArray(responseData)) {
for (const item of responseData) {
if (isErrorObject(item)) {
yield item
}
}
}
}
export class APIError extends Error {
constructor(message, response) {
super(message ?? response?.statusText)
this.response = response
this.errors = Array.from(extractResponseErrors(response?.data))
}
/**
* Handle API response errors by either calling the provided callbacks
* or throwing exceptions that can be processed in promise handlers.
*/
static handle(error, message, context, vm) {
if (typeof context?.callback === 'function' || typeof context?.callbackCancel === 'function') {
// This API request was made by a callback-style caller,
// so we do error handling like we used to do it.
handleApiError(vm, error, message)
context?.callbackCancel?.()
} else {
// This API request was made by a caller that did not define any callback handlers.
// We take this as an indication, that the caller wants to use
// traditional flow-control with try-catch statements.
throw new APIError(message, error.response)
}
}
}
export function handleApiError(vm, err, message) {
if (err.response) {
vm.$log.error(err.response.status + ' ' + err.response.statusText)
vm.$log.error(err.response)
let msg = 'Error: '
if (message) {
msg += message
}
msg += '\n\n'
msg += 'Status code: ' + err.response.status + ' ' + err.response.statusText
alert(msg)
} else {
vm.$log.error(err)
if (message) {
alert('Error: ' + message + '\nInspect the console for more details.')
} else {
alert('Unspecified error. Inspect the console for details.')
}
}
}
/**
* Like APIError.handle this is a helper to allow us to migrate from the
* callback-oriented to promise-based response handling.
*
* When a callback is provided it mimics the old callback behaviour and
* calls the callback with the response and returns undefined.
* If no callback is provided we assume the caller wants to handle
* the response promise.
*/
export function callOrReturn (response, callback) {
if (typeof callback === 'function') {
callback(response)
return undefined
} else {
return response
}
}
export default function handleApiError(vm, err, message) {
if (err.response) {
vm.$log.error(err.response.status + ' ' + err.response.statusText)
vm.$log.error(err.response)
let msg = 'Error: '
if (message) {
msg += message
}
msg += '\n\n'
msg += 'Status code: ' + err.response.status + ' ' + err.response.statusText
alert(msg)
} else {
vm.$log.error(err)
if (message) {
alert('Error: ' + message + '\nInspect the console for more details.')
} else {
alert('Unspecified error. Inspect the console for details.')
}
}
}
import axios from 'axios' import axios from 'axios'
import oidc from 'oidc-client' import oidc from 'oidc-client'
import handleApiError from '../handleApiError' import { handleApiError } from '../api-helper'
const oidcmgr = new oidc.UserManager({ const oidcmgr = new oidc.UserManager({
userStore: new oidc.WebStorageStateStore(), userStore: new oidc.WebStorageStateStore(),
......
import axios from 'axios' import axios from 'axios'
import handleApiError from '../handleApiError' import { handleApiError } from '../api-helper'
const state = { const state = {
files: [], files: [],
......
import axios from 'axios' import axios from 'axios'
import handleApiError from '../handleApiError' import { handleApiError } from '../api-helper'
const state = { const state = {
playlists: [], playlists: [],
......
import axios from 'axios' import axios from 'axios'
import handleApiError from '../handleApiError' import { handleApiError } from '../api-helper'
const cloneMinimalShowObject = function (show) { const cloneMinimalShowObject = function (show) {
/* returns a new minimal object from the current show object with all /* returns a new minimal object from the current show object with all
......
...@@ -5,3 +5,11 @@ export function uppercaseFirst(string = "") { ...@@ -5,3 +5,11 @@ export function uppercaseFirst(string = "") {
export function lowercaseFirst(string = "") { export function lowercaseFirst(string = "") {
return string.charAt(0).toLowerCase() + string.slice(1) return string.charAt(0).toLowerCase() + string.slice(1)
} }
export function has(obj, prop) {
try {
return Object.prototype.hasOwnProperty.call(obj, prop)
} catch (e) {
return false
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment