start ajax services
This commit is contained in:
parent
00b06985e4
commit
e72a59fe9d
@ -1,6 +1,6 @@
|
|||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import Pokemon from 'pokemongo-json-pokedex/output/pokemon.json';
|
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 {
|
interface ICpAndTotalFound {
|
||||||
[ key : number ] : Array<IStats>;
|
[ key : number ] : Array<IStats>;
|
||||||
@ -34,12 +34,12 @@ const getClosestCpMultiplierIndex = (value : number) => {
|
|||||||
|
|
||||||
const familyOrder : Array<string> = [];
|
const familyOrder : Array<string> = [];
|
||||||
const familyEvolutionOrder : { [ key : string ] : Array<string> } = {};
|
const familyEvolutionOrder : { [ key : string ] : Array<string> } = {};
|
||||||
const familyEncountered : { [ key : string ] : Array<IPokemon> } = {};
|
const familyEncountered : { [ key : string ] : Array<ILeaguePokemon> } = {};
|
||||||
Pokemon.forEach((mon) => {
|
Pokemon.forEach((mon) => {
|
||||||
const baseAtk = mon.stats.baseAttack;
|
const baseAtk = mon.stats.baseAttack;
|
||||||
const baseDef = mon.stats.baseDefense;
|
const baseDef = mon.stats.baseDefense;
|
||||||
const baseHp = mon.stats.baseStamina;
|
const baseHp = mon.stats.baseStamina;
|
||||||
const pokemon : IPokemon = {
|
const pokemon : ILeaguePokemon = {
|
||||||
id: mon.id,
|
id: mon.id,
|
||||||
name: mon.name,
|
name: mon.name,
|
||||||
dex: mon.dex,
|
dex: mon.dex,
|
||||||
@ -184,7 +184,7 @@ Pokemon.forEach((mon) => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const pokemonOrder : Array<{ id : string, name : string }> = [];
|
const pokemonOrder : Array<IPokemon> = [];
|
||||||
familyOrder.forEach((familyId) => {
|
familyOrder.forEach((familyId) => {
|
||||||
familyEvolutionOrder[familyId].forEach((id, order) => {
|
familyEvolutionOrder[familyId].forEach((id, order) => {
|
||||||
familyEncountered[familyId].some((pokemon, index) => {
|
familyEncountered[familyId].some((pokemon, index) => {
|
||||||
@ -196,11 +196,9 @@ familyOrder.forEach((familyId) => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
familyEncountered[familyId].forEach((pokemon) => {
|
familyEncountered[familyId].forEach((leaguePokemon) => {
|
||||||
pokemonOrder.push({
|
const { pvp, ...pokemon } = leaguePokemon;
|
||||||
id: pokemon.id,
|
pokemonOrder.push(pokemon);
|
||||||
name: pokemon.name,
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
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;
|
baseStamina : number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type League = 'great' | 'ultra';
|
|
||||||
export interface IPokemon {
|
export interface IPokemon {
|
||||||
name : string;
|
name : string;
|
||||||
id : string;
|
id : string;
|
||||||
family : string;
|
family : string;
|
||||||
dex : number;
|
dex : number;
|
||||||
stats : IBaseStats;
|
stats : IBaseStats;
|
||||||
|
}
|
||||||
|
export type League = 'great' | 'ultra';
|
||||||
|
export interface ILeaguePokemon extends IPokemon {
|
||||||
pvp : {
|
pvp : {
|
||||||
great : Array<IStats>;
|
great : Array<IStats>;
|
||||||
ultra : Array<IStats>;
|
ultra : Array<IStats>;
|
||||||
Loading…
x
Reference in New Issue
Block a user