mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-04-27 07:48:01 -07:00
Webatrice: card import wizard (#4397)
This commit is contained in:
parent
dde0f568d9
commit
36e5a399d5
41 changed files with 1479 additions and 35 deletions
104
webclient/src/services/CardImporterService.ts
Normal file
104
webclient/src/services/CardImporterService.ts
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
// Fetch and parse card sets
|
||||
|
||||
class CardImporterService {
|
||||
importCards(url): Promise<any> {
|
||||
const error = 'Card import must be in valid MTG JSON format';
|
||||
|
||||
return fetch(url)
|
||||
.then(response => {
|
||||
if (response.headers.get('Content-Type') !== 'application/json') {
|
||||
throw new Error(error);
|
||||
}
|
||||
|
||||
return response.json();
|
||||
})
|
||||
.then((json) => {
|
||||
try {
|
||||
const sortedSets = Object.keys(json.data)
|
||||
.map(key => json.data[key])
|
||||
.sort((a, b) => new Date(a.releaseDate).getTime() - new Date(b.releaseDate).getTime());
|
||||
|
||||
const sets = sortedSets.map(({ cards, tokens, ...set}) => ({
|
||||
...set,
|
||||
cards: cards.map(({ name }) => name),
|
||||
tokens: tokens.map(({ name }) => name),
|
||||
}));
|
||||
|
||||
const unsortedCards = sortedSets.reduce((acc, set) => {
|
||||
set.cards.forEach(card => acc[card.name] = card);
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
const cards = Object.keys(unsortedCards)
|
||||
.sort((a, b) => a.localeCompare(b))
|
||||
.map(key => unsortedCards[key]);
|
||||
|
||||
return { cards, sets };
|
||||
} catch (e) {
|
||||
throw new Error(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
importTokens(url): Promise<any> {
|
||||
const error = 'Token import must be in valid MTG XML format';
|
||||
|
||||
return fetch(url)
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to fetch');
|
||||
}
|
||||
|
||||
return response.text()
|
||||
})
|
||||
.then((xmlString) => {
|
||||
try {
|
||||
const parser = new DOMParser();
|
||||
const dom = parser.parseFromString(xmlString, "application/xml");
|
||||
|
||||
const tokens = Array.from(dom.querySelectorAll('card')).map(
|
||||
(tokenElement) => this.parseXmlAttributes(tokenElement)
|
||||
);
|
||||
|
||||
return tokens;
|
||||
} catch (e) {
|
||||
throw new Error(error);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private parseXmlAttributes(dom: Element) {
|
||||
return Array.from(dom.children).reduce((attributes, child) => {
|
||||
const value = child.children.length ? this.parseXmlAttributes(child) : child.innerHTML;
|
||||
|
||||
let parsedAttributes = { value };
|
||||
|
||||
if (child.attributes.length) {
|
||||
const childAttributes = Array.from(child.attributes).reduce((acc, { name, value }) => {
|
||||
acc[name] = value;
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
parsedAttributes = {
|
||||
...parsedAttributes,
|
||||
...childAttributes,
|
||||
};
|
||||
}
|
||||
|
||||
// @TODO: clean this up and normalize what i'm returning
|
||||
if (attributes[child.tagName]) {
|
||||
if (Array.isArray(attributes[child.tagName])) {
|
||||
attributes[child.tagName].push(parsedAttributes)
|
||||
} else {
|
||||
attributes[child.tagName] = [ parsedAttributes ];
|
||||
}
|
||||
} else {
|
||||
attributes[child.tagName] = parsedAttributes;
|
||||
}
|
||||
|
||||
return attributes;
|
||||
}, {});
|
||||
}
|
||||
}
|
||||
|
||||
export const cardImporterService = new CardImporterService();
|
||||
19
webclient/src/services/DexieDTOs/CardDTO.ts
Normal file
19
webclient/src/services/DexieDTOs/CardDTO.ts
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
import { Card } from 'types';
|
||||
|
||||
import { dexieService } from '../DexieService';
|
||||
|
||||
export class CardDTO extends Card {
|
||||
save() {
|
||||
return dexieService.cards.put(this);
|
||||
}
|
||||
|
||||
static get(name) {
|
||||
return dexieService.cards.where('name').equalsIgnoreCase(name).first();
|
||||
}
|
||||
|
||||
static bulkAdd(cards: CardDTO[]): Promise<any> {
|
||||
return dexieService.cards.bulkPut(cards);
|
||||
}
|
||||
};
|
||||
|
||||
dexieService.cards.mapToClass(CardDTO);
|
||||
19
webclient/src/services/DexieDTOs/SetDTO.ts
Normal file
19
webclient/src/services/DexieDTOs/SetDTO.ts
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
import { Set } from 'types';
|
||||
|
||||
import { dexieService } from '../DexieService';
|
||||
|
||||
export class SetDTO extends Set {
|
||||
save() {
|
||||
return dexieService.sets.put(this);
|
||||
}
|
||||
|
||||
static get(name) {
|
||||
return dexieService.sets.where('name').equalsIgnoreCase(name).first();
|
||||
}
|
||||
|
||||
static bulkAdd(sets: SetDTO[]): Promise<any> {
|
||||
return dexieService.sets.bulkPut(sets);
|
||||
}
|
||||
};
|
||||
|
||||
dexieService.cards.mapToClass(SetDTO);
|
||||
19
webclient/src/services/DexieDTOs/TokenDTO.ts
Normal file
19
webclient/src/services/DexieDTOs/TokenDTO.ts
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
import { Token } from 'types';
|
||||
|
||||
import { dexieService } from '../DexieService';
|
||||
|
||||
export class TokenDTO extends Token {
|
||||
save() {
|
||||
return dexieService.tokens.put(this);
|
||||
}
|
||||
|
||||
static get(name) {
|
||||
return dexieService.tokens.where('name.value').equalsIgnoreCase(name).first();
|
||||
}
|
||||
|
||||
static bulkAdd(tokens: TokenDTO[]): Promise<any> {
|
||||
return dexieService.tokens.bulkPut(tokens);
|
||||
}
|
||||
};
|
||||
|
||||
dexieService.tokens.mapToClass(TokenDTO);
|
||||
3
webclient/src/services/DexieDTOs/index.ts
Normal file
3
webclient/src/services/DexieDTOs/index.ts
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
export * from './CardDTO';
|
||||
export * from './SetDTO';
|
||||
export * from './TokenDTO';
|
||||
35
webclient/src/services/DexieService.ts
Normal file
35
webclient/src/services/DexieService.ts
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
import Dexie from 'dexie';
|
||||
|
||||
enum Stores {
|
||||
CARDS = 'cards',
|
||||
SETS = 'sets',
|
||||
TOKENS = 'tokens',
|
||||
}
|
||||
|
||||
const StoreKeyIndexes = {
|
||||
[Stores.CARDS]: "name",
|
||||
[Stores.SETS]: "code",
|
||||
[Stores.TOKENS]: "name.value",
|
||||
};
|
||||
|
||||
class DexieService {
|
||||
private db: Dexie = new Dexie('Webatrice');
|
||||
|
||||
constructor() {
|
||||
this.db.version(1).stores(StoreKeyIndexes);
|
||||
}
|
||||
|
||||
get cards() {
|
||||
return this.db.table(Stores.CARDS);
|
||||
}
|
||||
|
||||
get sets() {
|
||||
return this.db.table(Stores.SETS);
|
||||
}
|
||||
|
||||
get tokens() {
|
||||
return this.db.table(Stores.TOKENS);
|
||||
}
|
||||
}
|
||||
|
||||
export const dexieService = new DexieService();
|
||||
2
webclient/src/services/index.ts
Normal file
2
webclient/src/services/index.ts
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
export * from "./CardImporterService";
|
||||
export * from './DexieDTOs';
|
||||
Loading…
Add table
Add a link
Reference in a new issue