start ajax services
This commit is contained in:
parent
00b06985e4
commit
e72a59fe9d
@ -1,6 +1,6 @@
|
||||
import * as fs from 'fs';
|
||||
import Pokemon from 'pokemongo-json-pokedex/output/pokemon.json';
|
||||
import { IPokemon, IStats, League, Grade } from './src/ts/models/Pokemon';
|
||||
import { ILeaguePokemon, IPokemon, IStats, League, Grade } from './src/ts/app/models/Pokemon';
|
||||
|
||||
interface ICpAndTotalFound {
|
||||
[ key : number ] : Array<IStats>;
|
||||
@ -34,12 +34,12 @@ const getClosestCpMultiplierIndex = (value : number) => {
|
||||
|
||||
const familyOrder : Array<string> = [];
|
||||
const familyEvolutionOrder : { [ key : string ] : Array<string> } = {};
|
||||
const familyEncountered : { [ key : string ] : Array<IPokemon> } = {};
|
||||
const familyEncountered : { [ key : string ] : Array<ILeaguePokemon> } = {};
|
||||
Pokemon.forEach((mon) => {
|
||||
const baseAtk = mon.stats.baseAttack;
|
||||
const baseDef = mon.stats.baseDefense;
|
||||
const baseHp = mon.stats.baseStamina;
|
||||
const pokemon : IPokemon = {
|
||||
const pokemon : ILeaguePokemon = {
|
||||
id: mon.id,
|
||||
name: mon.name,
|
||||
dex: mon.dex,
|
||||
@ -184,7 +184,7 @@ Pokemon.forEach((mon) => {
|
||||
});
|
||||
});
|
||||
|
||||
const pokemonOrder : Array<{ id : string, name : string }> = [];
|
||||
const pokemonOrder : Array<IPokemon> = [];
|
||||
familyOrder.forEach((familyId) => {
|
||||
familyEvolutionOrder[familyId].forEach((id, order) => {
|
||||
familyEncountered[familyId].some((pokemon, index) => {
|
||||
@ -196,11 +196,9 @@ familyOrder.forEach((familyId) => {
|
||||
});
|
||||
});
|
||||
|
||||
familyEncountered[familyId].forEach((pokemon) => {
|
||||
pokemonOrder.push({
|
||||
id: pokemon.id,
|
||||
name: pokemon.name,
|
||||
});
|
||||
familyEncountered[familyId].forEach((leaguePokemon) => {
|
||||
const { pvp, ...pokemon } = leaguePokemon;
|
||||
pokemonOrder.push(pokemon);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
223
src/ts/api/AjaxUtils.ts
Normal file
223
src/ts/api/AjaxUtils.ts
Normal file
@ -0,0 +1,223 @@
|
||||
export interface IRestApiRejection {
|
||||
message : string;
|
||||
status : number;
|
||||
xhr : XMLHttpRequest;
|
||||
error : Error | null;
|
||||
type : string | null;
|
||||
content : any | null;
|
||||
}
|
||||
|
||||
const buildQueryString = (queryObject : any) => {
|
||||
const queryParameters : Array<string> = [];
|
||||
let queryString = '';
|
||||
Object.keys(queryObject || {}).forEach((key : string) => {
|
||||
queryParameters.push(key + '=' + encodeURIComponent(queryObject[key]));
|
||||
});
|
||||
if (queryParameters.length > 0) {
|
||||
queryString = '?' + queryParameters.join('&');
|
||||
}
|
||||
return queryString;
|
||||
};
|
||||
|
||||
const handleXhrOnLoad = (resolve : (value : any) => void, reject : (reason : any) => void, xhr : XMLHttpRequest) : void => {
|
||||
if (xhr.readyState === 4 && (xhr.status === 200 || xhr.status === 204)) {
|
||||
if (xhr.responseType === '' && xhr.responseText === '') {
|
||||
return resolve(undefined);
|
||||
}
|
||||
if (xhr.responseType === 'text') {
|
||||
return resolve(xhr.response);
|
||||
}
|
||||
try {
|
||||
const responseJSON = JSON.parse(xhr.response);
|
||||
|
||||
if (typeof(responseJSON.success) !== 'undefined' && !responseJSON.success) {
|
||||
if (responseJSON.error === 'user_required') {
|
||||
window.location.reload();
|
||||
}
|
||||
}
|
||||
|
||||
return resolve(responseJSON);
|
||||
} catch (e) {
|
||||
const rejection : IRestApiRejection = {
|
||||
message: e.message,
|
||||
status: xhr.status,
|
||||
xhr,
|
||||
error: e,
|
||||
type: null,
|
||||
content: null,
|
||||
};
|
||||
// tslint:disable-next-line:no-console
|
||||
console.error('Failed to parse response', xhr);
|
||||
return reject(rejection);
|
||||
}
|
||||
} else {
|
||||
return handleXhrOnLoadCaughtException(reject, xhr);
|
||||
}
|
||||
};
|
||||
|
||||
const handleXhrOnLoadCaughtException = (reject : (reason : any) => void, xhr : XMLHttpRequest) : void => {
|
||||
if (xhr.status === 401) {
|
||||
window.location.reload();
|
||||
}
|
||||
|
||||
if (xhr.responseType === 'text' || xhr.responseType === '') {
|
||||
const rejection : IRestApiRejection = {
|
||||
message: xhr.responseText || xhr.statusText,
|
||||
status: xhr.status,
|
||||
xhr,
|
||||
error: null,
|
||||
type: null,
|
||||
content: null,
|
||||
};
|
||||
return reject(rejection);
|
||||
}
|
||||
try {
|
||||
const responseJSON = JSON.parse(xhr.response);
|
||||
|
||||
const rejection : IRestApiRejection = {
|
||||
message: responseJSON.message || xhr.statusText,
|
||||
status: xhr.status,
|
||||
xhr,
|
||||
error: null,
|
||||
type: responseJSON.exception_type,
|
||||
content: responseJSON.content,
|
||||
};
|
||||
return reject(rejection);
|
||||
} catch (e) {
|
||||
const rejection : IRestApiRejection = {
|
||||
message: e.message,
|
||||
status: xhr.status,
|
||||
xhr,
|
||||
error: e,
|
||||
type: null,
|
||||
content: null,
|
||||
};
|
||||
// tslint:disable-next-line:no-console
|
||||
console.error('Failed to parse response', xhr);
|
||||
return reject(rejection);
|
||||
}
|
||||
};
|
||||
|
||||
export const AjaxUtils = {
|
||||
ajaxGet(url : string, queryObject? : any) : Promise<any> {
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
const xhr = new XMLHttpRequest();
|
||||
const cacheBustingQueryObject = (queryObject || {}); // IE 11 caches GET requests
|
||||
cacheBustingQueryObject._cache_busting_arg_ = +new Date(); // this parameter name must be in the backend's excluded parameter set (see api_utils.py)
|
||||
|
||||
xhr.open('GET', url + buildQueryString(cacheBustingQueryObject));
|
||||
xhr.withCredentials = true;
|
||||
xhr.onload = () => {
|
||||
if (xhr.readyState === 4 && xhr.status === 200) {
|
||||
try {
|
||||
return resolve(JSON.parse(xhr.response));
|
||||
} catch (e) {
|
||||
const rejection : IRestApiRejection = {
|
||||
message: e.message,
|
||||
status: xhr.status,
|
||||
xhr,
|
||||
error: e,
|
||||
type: null,
|
||||
content: null,
|
||||
};
|
||||
// tslint:disable-next-line:no-console
|
||||
console.error('Failure to parse response', xhr);
|
||||
return reject(rejection);
|
||||
}
|
||||
} else {
|
||||
return handleXhrOnLoadCaughtException(reject, xhr);
|
||||
}
|
||||
};
|
||||
xhr.onerror = (e) => {
|
||||
return handleXhrOnLoadCaughtException(reject, xhr);
|
||||
};
|
||||
xhr.send();
|
||||
});
|
||||
},
|
||||
|
||||
ajaxPost(url : string, postBody : any, queryObject? : any, type? : 'text' | 'json') : Promise<any> {
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open('POST', url + buildQueryString(queryObject));
|
||||
xhr.withCredentials = true;
|
||||
xhr.setRequestHeader('Content-Type', 'application/json');
|
||||
xhr.setRequestHeader('X-CSRFToken', (window as any).CSRF_TOKEN);
|
||||
xhr.onload = () => {
|
||||
if (xhr.readyState === 4 && (xhr.status === 200 || xhr.status === 201)) {
|
||||
if (type === 'text') {
|
||||
return resolve(xhr.response);
|
||||
}
|
||||
try {
|
||||
return resolve(JSON.parse(xhr.response));
|
||||
} catch (e) {
|
||||
const rejection : IRestApiRejection = {
|
||||
message: e.message,
|
||||
status: xhr.status,
|
||||
xhr,
|
||||
error: e,
|
||||
type: null,
|
||||
content: null,
|
||||
};
|
||||
// tslint:disable-next-line:no-console
|
||||
console.error('Failure to parse response', xhr);
|
||||
return reject(rejection);
|
||||
}
|
||||
} else {
|
||||
return handleXhrOnLoadCaughtException(reject, xhr);
|
||||
}
|
||||
};
|
||||
xhr.onerror = (e) => {
|
||||
return handleXhrOnLoadCaughtException(reject, xhr);
|
||||
};
|
||||
xhr.send(JSON.stringify(postBody || undefined));
|
||||
});
|
||||
},
|
||||
|
||||
ajaxPostForm(url : string, formData? : FormData, queryObject? : any) : Promise<any> {
|
||||
// Lesman 4/24/2017
|
||||
// NOTE: you do not set the Content-Type on this request,
|
||||
// the browser will automatically encode the form data and
|
||||
// set the appropriate Content-Type. The encoding is browser
|
||||
// specific so you MUST allow the browser to set the header
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open('POST', url + buildQueryString(queryObject));
|
||||
xhr.withCredentials = true;
|
||||
xhr.setRequestHeader('X-CSRFToken', (window as any).CSRF_TOKEN);
|
||||
xhr.onload = () => handleXhrOnLoad(resolve, reject, xhr);
|
||||
xhr.onerror = (e) => {
|
||||
return handleXhrOnLoadCaughtException(reject, xhr);
|
||||
};
|
||||
xhr.send(formData);
|
||||
});
|
||||
},
|
||||
|
||||
ajaxPut(url : string, postBody : any, queryObject? : any) : Promise<any> {
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open('PUT', url + buildQueryString(queryObject));
|
||||
xhr.withCredentials = true;
|
||||
xhr.setRequestHeader('Content-Type', 'application/json');
|
||||
xhr.setRequestHeader('X-CSRFToken', (window as any).CSRF_TOKEN);
|
||||
xhr.onload = () => handleXhrOnLoad(resolve, reject, xhr);
|
||||
xhr.onerror = (e) => {
|
||||
return handleXhrOnLoadCaughtException(reject, xhr);
|
||||
};
|
||||
xhr.send(JSON.stringify(postBody || undefined));
|
||||
});
|
||||
},
|
||||
|
||||
ajaxDelete(url : string, queryObject? : any) : Promise<any> {
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open('DELETE', url + buildQueryString(queryObject));
|
||||
xhr.withCredentials = true;
|
||||
xhr.setRequestHeader('X-CSRFToken', (window as any).CSRF_TOKEN);
|
||||
xhr.onload = () => handleXhrOnLoad(resolve, reject, xhr);
|
||||
xhr.onerror = (e) => {
|
||||
return handleXhrOnLoadCaughtException(reject, xhr);
|
||||
};
|
||||
xhr.send();
|
||||
});
|
||||
},
|
||||
};
|
||||
51
src/ts/api/PokemonService.ts
Normal file
51
src/ts/api/PokemonService.ts
Normal file
@ -0,0 +1,51 @@
|
||||
import { AjaxUtils } from 'src/ts/api/AjaxUtils';
|
||||
|
||||
import { IPokemon } from 'src/ts/app/models/Pokemon';
|
||||
|
||||
interface IPokemonService {
|
||||
|
||||
}
|
||||
|
||||
export class PokemonService implements IPokemonService {
|
||||
public getPokemonList() {
|
||||
const queryParameters = {
|
||||
type: 'no touch',
|
||||
is_active: true,
|
||||
};
|
||||
|
||||
return AjaxUtils.ajaxGet('/api/billing/plan', queryParameters)
|
||||
.then((response : Array<object>) => {
|
||||
return Promise.resolve(this.serializePokemonList(response));
|
||||
});
|
||||
}
|
||||
|
||||
// does `object` need to be `any`?
|
||||
private serializePokemonList(jsonPokemonList : Array<object>) : Array<IPokemon> {
|
||||
const pokemonList = jsonPokemonList.map((jsonPokemon) => {
|
||||
let pokemon : IPokemon | null = null;
|
||||
try {
|
||||
if (typeof jsonPokemon.name !== 'string') {
|
||||
throw 'pokemon missing name';
|
||||
}
|
||||
if (typeof jsonPokemon.id !== 'string') {
|
||||
throw 'pokemon missing id';
|
||||
}
|
||||
if (typeof jsonPokemon.family !== 'string') {
|
||||
throw 'pokemon missing family';
|
||||
}
|
||||
if (typeof jsonPokemon.dex !== 'number') {
|
||||
throw 'pokemon missing dex';
|
||||
}
|
||||
if (typeof jsonPokemon.stats !== 'object') {
|
||||
throw 'pokemon missing stats';
|
||||
}
|
||||
pokemon = { ...jsonPokemon };
|
||||
} catch (e) {
|
||||
console.error(jsonPokemon, e.message);
|
||||
}
|
||||
return pokemon;
|
||||
});
|
||||
// TODO should we allow `null`s?
|
||||
return pokemonList;
|
||||
}
|
||||
}
|
||||
@ -13,13 +13,15 @@ export interface IBaseStats {
|
||||
baseStamina : number;
|
||||
}
|
||||
|
||||
export type League = 'great' | 'ultra';
|
||||
export interface IPokemon {
|
||||
name : string;
|
||||
id : string;
|
||||
family : string;
|
||||
dex : number;
|
||||
stats : IBaseStats;
|
||||
}
|
||||
export type League = 'great' | 'ultra';
|
||||
export interface ILeaguePokemon extends IPokemon {
|
||||
pvp : {
|
||||
great : Array<IStats>;
|
||||
ultra : Array<IStats>;
|
||||
Loading…
x
Reference in New Issue
Block a user