/** * Base model class * * @author Nicolas Stein * @author Michael Fallise * @version 1.2 * @category Core * @subcategory Application */ class Model { /** * * @param {object} response * @returns {object} */ _processResponse(response, resolve, reject){ if(response.ok){ // All ok if( (response.headers.get('Content-Type')) && (response.headers.get('Content-Type').toLocaleLowerCase().indexOf('application/json')>-1) ) { resolve(response.json()); } else { resolve( response.text().then(rawResponse => { if(rawResponse != '') { console.warn('Server did not declare response as Json...trying to parse it anyway', rawResponse) return(JSON.parse(rawResponse)); } else if(response.status==204) return(true); // Normal to have no content, so make sure other layers see it as success else return(''); }) ) } } else { // server error // server error with json error details if( (response.headers.get('Content-Type')) && (response.headers.get('Content-Type').toLocaleLowerCase().indexOf('application/json')>-1) ){ response.json().then( cleanJson => { // json error details is clean let error = { 'code': response.status, 'displayMessage': (cleanJson.error.displayMessage || ' !!No debugMessage from server!!'), 'debugMessage': response.statusText+'\n'+(cleanJson.error.debugMessage || ' !!No debugMessage from server!!'), } this.onRequestError(error); reject(error); }, text => { let error = { // json error details is garbage 'code': response.status, 'displayMessage': 'Could not request to server!?', 'debugMessage': 'Additionally, bad Json returned :', text, } this.onRequestError(error); reject(error); } ) } else { // server error with text return response.text().then( text => { let error = { 'code': response.status, 'displayMessage': 'Could not request to server!?', 'debugMessage': `Server responded: ${text}`, } this.onRequestError(error); reject(error); }, ) } } } /** * Generic API service call * @param {string} uri * @param {string} method * @param {object} payload * @returns {object} */ request(uri, method, payload) { // Fetch chooses its own resolve/reject (see https://developer.mozilla.org/en-US/docs/Web/API/fetch) // Errors like 404 are not rejected. and we can't change the -already done- resolve/reject choice. // therefore we return our own promise. if((!method) || (!uri)) { return( new Promise((resolve, reject) => reject( { sucess :false, payload: null, error: { displayError: 'Server Error (no endpoint)', debugError: 'Missing endpoint' }, }) )) } return ( new Promise((resolve, reject) => { let body = null; if(method.toLowerCase()!='get') body = payload ? JSON.stringify(payload): null; else if(payload) uri += '?'+Object.entries(payload).map(kv => kv.map(encodeURIComponent).join("=")).join("&"); fetch(uri, { method: method, headers: { 'Accept': 'application/json', 'Content-Type':'application/json'}, body: body, credentials: 'include', //By nike: mandatory for MT to get session !!! }) .then( response => { this._processResponse(response, resolve, reject); }) .catch(debugMessage => { // Other errors like metwork, protocol, CORs errors, or 200 but bad JSON let error = { 'displayMessage': 'Could not request to server!?', 'debugMessage': debugMessage, 'code': '4XX' // non http but >299 } this.onRequestError(error); reject(error); }) }) ); } /** * Request error handler * @param {object} error */ onRequestError(error) { console.error('Ajax request error:', error); } } app.registerClass('Model', Model)