mirror of
https://github.com/chaoticbackup/chaoticbackup.github.io.git
synced 2026-04-14 04:45:53 -05:00
search includes thumbs
This commit is contained in:
parent
c37f2e1946
commit
7c9f7762de
|
|
@ -41,6 +41,11 @@
|
|||
"dot-notation": "off",
|
||||
"eqeqeq": "off",
|
||||
"import/no-extraneous-dependencies": ["error", {"devDependencies": ["./webpack.config.babel.js"]}],
|
||||
"indent": ["error", 2, {
|
||||
"SwitchCase": 1,
|
||||
"MemberExpression": "off"
|
||||
}],
|
||||
"keyword-spacing": ["error"],
|
||||
"linebreak-style": "off",
|
||||
"no-plusplus": "off",
|
||||
"no-prototype-builtins": "off",
|
||||
|
|
@ -56,6 +61,7 @@
|
|||
}, {
|
||||
"enforceForRenamedProperties": false
|
||||
}],
|
||||
"prefer-const": "warn",
|
||||
"promise/always-return": "off",
|
||||
"promise/catch-or-return": ["warn", {
|
||||
"allowFinally": true
|
||||
|
|
@ -68,7 +74,8 @@
|
|||
"react/jsx-indent": ["warn", 2, { "indentLogicalExpressions": true }],
|
||||
"react/jsx-indent-props": ["warn", 2],
|
||||
"react/no-unescaped-entities": "off",
|
||||
"react/prop-types": "off"
|
||||
"react/prop-types": "off",
|
||||
"semi": ["warn", "always", { "omitLastInOneLineBlock": true }]
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,38 +3,38 @@ import processString from 'react-process-string';
|
|||
import { Mugic, Element, Discipline, Tribe } from "./_text";
|
||||
|
||||
export function Ability(props) {
|
||||
const mugic_counters = {
|
||||
regex: /([0-9x]*){{mc}}/i,
|
||||
fn: (key, result) => {
|
||||
if (result.length > 1 && result[1] != "") {
|
||||
return (<Mugic key={key} tribe={props.tribe} amount={result[1].toLowerCase()} size="icon14" />);
|
||||
}
|
||||
return (<Mugic key={key} tribe={props.tribe} size="icon14" />);
|
||||
const mugic_counters = {
|
||||
regex: /([0-9x]*){{mc}}/i,
|
||||
fn: (key, result) => {
|
||||
if (result.length > 1 && result[1] != "") {
|
||||
return (<Mugic key={key} tribe={props.tribe} amount={result[1].toLowerCase()} size="icon14" />);
|
||||
}
|
||||
return (<Mugic key={key} tribe={props.tribe} size="icon14" />);
|
||||
}
|
||||
};
|
||||
|
||||
const elements = {
|
||||
regex: new RegExp(/(\b((fire)|(air)|(earth)|(water)))/i),
|
||||
fn: (key, result) => {
|
||||
return (<span key={key}><Element element={result[0].replace(/\b/, '')} value="true" size="icon14" />{result[0]}</span>);
|
||||
}
|
||||
const elements = {
|
||||
regex: new RegExp(/(\b((fire)|(air)|(earth)|(water)))/i),
|
||||
fn: (key, result) => {
|
||||
return (<span key={key}><Element element={result[0].replace(/\b/, '')} value="true" size="icon14" />{result[0]}</span>);
|
||||
}
|
||||
};
|
||||
|
||||
const disciplines = {
|
||||
regex: /(courage)|(power)|(wisdom)|(speed)/i,
|
||||
fn: (key, result) => {
|
||||
return (<span key={key}><Discipline discipline={result[0]} size="icon14" />{result[0]}</span>);
|
||||
}
|
||||
const disciplines = {
|
||||
regex: /(courage)|(power)|(wisdom)|(speed)/i,
|
||||
fn: (key, result) => {
|
||||
return (<span key={key}><Discipline discipline={result[0]} size="icon14" />{result[0]}</span>);
|
||||
}
|
||||
};
|
||||
|
||||
const tribes = {
|
||||
regex: /(danian)|(generic)|(mipedian)|(overworld)|(underworld)|(m'arrillian)/i,
|
||||
fn: (key, result) => {
|
||||
return (<span key={key}><Tribe tribe={result[0]} size="icon14" />{result[0]}</span>);
|
||||
}
|
||||
const tribes = {
|
||||
regex: /(danian)|(generic)|(mipedian)|(overworld)|(underworld)|(m'arrillian)/i,
|
||||
fn: (key, result) => {
|
||||
return (<span key={key}><Tribe tribe={result[0]} size="icon14" />{result[0]}</span>);
|
||||
}
|
||||
};
|
||||
|
||||
const filters = [mugic_counters, elements, disciplines, tribes];
|
||||
const filters = [mugic_counters, elements, disciplines, tribes];
|
||||
|
||||
return <div className={props.type || "ability"}>{processString(filters)(props.ability)}</div>
|
||||
return <div className={props.type || "ability"}>{processString(filters)(props.ability)}</div>;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,19 +1,19 @@
|
|||
import React from 'react';
|
||||
|
||||
export function Initiative(props) {
|
||||
let { initiative } = props;
|
||||
let image = null;
|
||||
if (["Danian", "Generic", "Mipedian", "OverWorld", "UnderWorld", "M'arrillian"].indexOf(initiative) > -1) {
|
||||
image = <img className="icon16" style={{ verticalAlign: 'middle' }} src={("/src/img/icons/tribes/" + initiative + ".png").toLowerCase()} />
|
||||
}
|
||||
else if (["courage", "power", "speed", "wisdom"].indexOf(initiative.toLowerCase()) > -1) {
|
||||
image = <img className="icon16" style={{ verticalAlign: 'middle' }} src={("/src/img/icons/disciplines/" + initiative + ".png").toLowerCase()} />
|
||||
}
|
||||
else if (["fire", "air", "earth", "water"].indexOf(initiative.toLowerCase()) > -1) {
|
||||
image = <img className="icon16" style={{ verticalAlign: 'middle' }} src={("/src/img/icons/elements/" + initiative + ".png").toLowerCase()} />
|
||||
}
|
||||
else if (initiative.toLowerCase() == "mugic counter") {
|
||||
image = <img className="icon16" style={{ verticalAlign: 'middle' }} src={("/src/img/icons/mugic/generic.png").toLowerCase()} />
|
||||
}
|
||||
return (<span>{!props.notitle && ("Initiative: ")}{image} {initiative}</span>);
|
||||
const { initiative } = props;
|
||||
let image = null;
|
||||
if (["Danian", "Generic", "Mipedian", "OverWorld", "UnderWorld", "M'arrillian"].indexOf(initiative) > -1) {
|
||||
image = <img className="icon16" style={{ verticalAlign: 'middle' }} src={("/src/img/icons/tribes/" + initiative + ".png").toLowerCase()} />;
|
||||
}
|
||||
else if (["courage", "power", "speed", "wisdom"].indexOf(initiative.toLowerCase()) > -1) {
|
||||
image = <img className="icon16" style={{ verticalAlign: 'middle' }} src={("/src/img/icons/disciplines/" + initiative + ".png").toLowerCase()} />;
|
||||
}
|
||||
else if (["fire", "air", "earth", "water"].indexOf(initiative.toLowerCase()) > -1) {
|
||||
image = <img className="icon16" style={{ verticalAlign: 'middle' }} src={("/src/img/icons/elements/" + initiative + ".png").toLowerCase()} />;
|
||||
}
|
||||
else if (initiative.toLowerCase() == "mugic counter") {
|
||||
image = <img className="icon16" style={{ verticalAlign: 'middle' }} src={("/src/img/icons/mugic/generic.png").toLowerCase()} />;
|
||||
}
|
||||
return (<span>{!props.notitle && ("Initiative: ")}{image} {initiative}</span>);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,25 +1,25 @@
|
|||
import React from 'react';
|
||||
|
||||
export function Unique(props) {
|
||||
let string = "";
|
||||
if (props.data.unique) {
|
||||
string += "Unique, ";
|
||||
let string = "";
|
||||
if (props.data.unique) {
|
||||
string += "Unique, ";
|
||||
}
|
||||
if (props.data.loyal) {
|
||||
string += "Loyal";
|
||||
if (props.data.tribe == 'M\'arrillian') {
|
||||
string += " - M'arrillians or Minions";
|
||||
}
|
||||
if (props.data.loyal) {
|
||||
string += "Loyal";
|
||||
if (props.data.tribe == 'M\'arrillian') {
|
||||
string += " - M'arrillians or Minions";
|
||||
}
|
||||
// Battlegear loyality
|
||||
if (props.data.loyal != "1") {
|
||||
string += " - " + props.data.loyal;
|
||||
}
|
||||
// Battlegear loyality
|
||||
if (props.data.loyal != "1") {
|
||||
string += " - " + props.data.loyal;
|
||||
}
|
||||
if (props.data.legendary) {
|
||||
string = (string) ? ("Legendary, " + string) : "Legendary";
|
||||
}
|
||||
string = string.replace(/,\s+$/, "");
|
||||
return (
|
||||
<span style={{ fontWeight: "Bold" }}>{string}{string && <br />}</span>
|
||||
);
|
||||
}
|
||||
if (props.data.legendary) {
|
||||
string = (string) ? ("Legendary, " + string) : "Legendary";
|
||||
}
|
||||
string = string.replace(/,\s+$/, "");
|
||||
return (
|
||||
<span style={{ fontWeight: "Bold" }}>{string}{string && <br />}</span>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,24 +2,24 @@ import React from 'react';
|
|||
import API from '../SpreadsheetData';
|
||||
|
||||
export function AttackIcon(props) {
|
||||
let attack = "attack" + ((props.bp && props.bp >= 0) ? "_" + props.bp : "");
|
||||
return <img className={props.size || "icon16"} src={`/src/img/icons/attack/${attack}.png`} />
|
||||
const attack = "attack" + ((props.bp && props.bp >= 0) ? "_" + props.bp : "");
|
||||
return <img className={props.size || "icon16"} src={`/src/img/icons/attack/${attack}.png`} />;
|
||||
}
|
||||
|
||||
export function BattlegearIcon(props) {
|
||||
return <img className={props.size || "icon16"} src="/src/img/icons/battlegear.png" />
|
||||
return <img className={props.size || "icon16"} src="/src/img/icons/battlegear.png" />;
|
||||
}
|
||||
|
||||
export function LocationIcon(props) {
|
||||
return <img className={props.size || "icon16"} src="/src/img/icons/location.png" />
|
||||
return <img className={props.size || "icon16"} src="/src/img/icons/location.png" />;
|
||||
}
|
||||
|
||||
export function Rarity(props) {
|
||||
let { set, rarity } = props;
|
||||
return (
|
||||
<span>
|
||||
{set !== 'PE1' && <img className={props.size || "icon16"} style={{ verticalAlign: 'middle' }} src={("/src/img/icons/set/" + set + "/" + rarity + ".png").toLowerCase()} />}
|
||||
{!props.notext && <>{API.sets[props.set]} | {props.rarity}</>}
|
||||
</span>
|
||||
);
|
||||
const { set, rarity } = props;
|
||||
return (
|
||||
<span>
|
||||
{set !== 'PE1' && <img className={props.size || "icon16"} style={{ verticalAlign: 'middle' }} src={("/src/img/icons/set/" + set + "/" + rarity + ".png").toLowerCase()} />}
|
||||
{!props.notext && <>{API.sets[props.set]} | {props.rarity}</>}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import React from 'react';
|
||||
|
||||
export function Name(props) {
|
||||
let name = props.name.split(",");
|
||||
const name = props.name.split(",");
|
||||
return (<span className="name">
|
||||
<span className="bigger">{name[0]}</span>
|
||||
{name.length > 1 &&
|
||||
|
|
@ -14,24 +14,24 @@ export function Name(props) {
|
|||
}
|
||||
|
||||
export function Mugic(props) {
|
||||
let type = (props.tribe || "generic") + (props.amount != undefined ? `_${props.amount}` : "");
|
||||
let src = ("/src/img/icons/mugic/" + type + ".png").toLowerCase();
|
||||
return <img className={props.size || "icon20"} src={src} alt={"MC"} />
|
||||
const type = (props.tribe || "generic") + (props.amount != undefined ? `_${props.amount}` : "");
|
||||
const src = ("/src/img/icons/mugic/" + type + ".png").toLowerCase();
|
||||
return <img className={props.size || "icon20"} src={src} alt={"MC"} />;
|
||||
}
|
||||
|
||||
export function Element(props) {
|
||||
if (props.value) {
|
||||
return <img className={props.size || "icon20"} src={("/src/img/icons/elements/" + props.element + ".png").toLowerCase()} />
|
||||
return <img className={props.size || "icon20"} src={("/src/img/icons/elements/" + props.element + ".png").toLowerCase()} />;
|
||||
}
|
||||
else {
|
||||
return <img className={props.size || "icon20"} src={("/src/img/icons/elements/" + props.element + "-inactive.png").toLowerCase()} />
|
||||
return <img className={props.size || "icon20"} src={("/src/img/icons/elements/" + props.element + "-inactive.png").toLowerCase()} />;
|
||||
}
|
||||
}
|
||||
|
||||
export function Tribe(props) {
|
||||
return <img className={props.size || "icon16"} src={("/src/img/icons/tribes/" + props.tribe + ".png").toLowerCase()} />
|
||||
return <img className={props.size || "icon16"} src={("/src/img/icons/tribes/" + props.tribe + ".png").toLowerCase()} />;
|
||||
}
|
||||
|
||||
export function Discipline(props) {
|
||||
return <img className={props.size || "icon16"} src={("/src/img/icons/disciplines/" + props.discipline + ".png").toLowerCase()} />
|
||||
return <img className={props.size || "icon16"} src={("/src/img/icons/disciplines/" + props.discipline + ".png").toLowerCase()} />;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ export function Loading(props) {
|
|||
}
|
||||
|
||||
export function Splash(props) {
|
||||
let { image } = props;
|
||||
const { image } = props;
|
||||
return (
|
||||
<div style={{ position: 'absolute', top: '0', left: '0', right: '0', bottom: '0', backgroundImage: 'url(\'' + image + '\') no-repeat center', backgroundSize: 'cover' }} />
|
||||
);
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ class CollectionDB {
|
|||
async getSpreadsheetData(spreadsheet, type, callback) {
|
||||
this.api.getSpreadsheet(spreadsheet, (data) => {
|
||||
callback(data.map((item) => {
|
||||
let temp = {};
|
||||
const temp = {};
|
||||
delete item.content;
|
||||
for (const key of Object.keys(item)) {
|
||||
temp[key] = item[key].$t;
|
||||
|
|
@ -33,11 +33,11 @@ class CollectionDB {
|
|||
@action
|
||||
async setupType(type, resolve) {
|
||||
if (this.building.hasOwnProperty(type)) {
|
||||
let uc_type = type.charAt(0).toUpperCase() + type.slice(1);
|
||||
const uc_type = type.charAt(0).toUpperCase() + type.slice(1);
|
||||
if (this.building[type].get() == "built") {
|
||||
// Check if data has been updated
|
||||
this.getSpreadsheetData(this.api.urls[uc_type][this.format], uc_type, (data) => {
|
||||
let cookie = cookies.get(`${this.format}_${type}`);
|
||||
const cookie = cookies.get(`${this.format}_${type}`);
|
||||
if (cookie) {
|
||||
if ((new Date(data[0].updated)) > (new Date(cookie))) {
|
||||
this[type].clear();
|
||||
|
|
@ -87,7 +87,7 @@ class CollectionDB {
|
|||
|
||||
@action
|
||||
setupDB(format) {
|
||||
let db = new loki(`chaotic_${format}.db`, {
|
||||
const db = new loki(`chaotic_${format}.db`, {
|
||||
autosave: true,
|
||||
autoload: true,
|
||||
autoloadCallback: databaseInitialize.bind(this),
|
||||
|
|
@ -101,7 +101,7 @@ class CollectionDB {
|
|||
["attacks","battlegear", "creatures", "locations", "mugic"]
|
||||
.forEach((type) => {
|
||||
// check if the db already exists in memory
|
||||
let entries = db.getCollection(type);
|
||||
const entries = db.getCollection(type);
|
||||
if (entries === null || entries.data.length === 0) {
|
||||
this[type] = db.addCollection(type);
|
||||
if (this.building[type])
|
||||
|
|
@ -116,7 +116,7 @@ class CollectionDB {
|
|||
else
|
||||
this.building[type] = observable.box("built");
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -134,13 +134,13 @@ class API {
|
|||
static base_url = "https://spreadsheets.google.com/feeds/list/";
|
||||
static data_format = "/od6/public/values?alt=json";
|
||||
// + "/od6/public/basic?alt=json"; // Alternate data format
|
||||
get base_image() { return "https://drive.google.com/uc?id="; }
|
||||
get thumb_missing() { return "1JYjPzkv74IhzlHTyVh2niTDyui73HSfp"; }
|
||||
get card_back() { return "https://i.imgur.com/xbeDBRJ.png"; }
|
||||
get base_image() { return "https://drive.google.com/uc?id=" }
|
||||
get thumb_missing() { return "1JYjPzkv74IhzlHTyVh2niTDyui73HSfp" }
|
||||
get card_back() { return "https://i.imgur.com/xbeDBRJ.png" }
|
||||
|
||||
// Singleton
|
||||
static getInstance() {
|
||||
if (!this.instance) { this.instance = new API(); }
|
||||
if (!this.instance) { this.instance = new API() }
|
||||
return this.instance;
|
||||
}
|
||||
|
||||
|
|
@ -173,8 +173,8 @@ class API {
|
|||
setupDB() {
|
||||
// let base_spreadsheet = "1cUNmwV693zl2zqbH_IG4Wz8o9Va_sOHe7pAZF6M59Es";
|
||||
try {
|
||||
let urls = {};
|
||||
let data = require('./meta_spreadsheet.json');
|
||||
const urls = {};
|
||||
const data = require('./meta_spreadsheet.json');
|
||||
// this.getSpreadsheet(API.path(API.base_spreadsheet), (data) => {
|
||||
// if (data == null) throw "no data from base_spreadsheet";
|
||||
data.forEach((d) => {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ export default class CardList extends React.Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
let { cards } = this.props;
|
||||
const { cards } = this.props;
|
||||
|
||||
if (cards.length == 1 && cards[0].text) {
|
||||
return (
|
||||
|
|
@ -25,18 +25,18 @@ export default class CardList extends React.Component {
|
|||
}
|
||||
return cards.map((card, i) => {
|
||||
switch (card.gsx$type) {
|
||||
case "Attacks":
|
||||
return (<Attack card={card} key={i} ext={this.props.ext} setImage={this.setImage.bind(this)}/>);
|
||||
case "Battlegear":
|
||||
return (<Battlegear card={card} key={i} ext={this.props.ext} setImage={this.setImage.bind(this)}/>);
|
||||
case "Creatures":
|
||||
return (<Creature card={card} key={i} ext={this.props.ext} setImage={this.setImage.bind(this)}/>);
|
||||
case "Locations":
|
||||
return (<Location card={card} key={i} ext={this.props.ext} setImage={this.setImage.bind(this)}/>);
|
||||
case "Mugic":
|
||||
return (<Mugic card={card} key={i} ext={this.props.ext} setImage={this.setImage.bind(this)}/>);
|
||||
default:
|
||||
return (<div key={i}>Invalid Card Type</div>);
|
||||
case "Attacks":
|
||||
return (<Attack card={card} key={i} ext={this.props.ext} setImage={this.setImage.bind(this)}/>);
|
||||
case "Battlegear":
|
||||
return (<Battlegear card={card} key={i} ext={this.props.ext} setImage={this.setImage.bind(this)}/>);
|
||||
case "Creatures":
|
||||
return (<Creature card={card} key={i} ext={this.props.ext} setImage={this.setImage.bind(this)}/>);
|
||||
case "Locations":
|
||||
return (<Location card={card} key={i} ext={this.props.ext} setImage={this.setImage.bind(this)}/>);
|
||||
case "Mugic":
|
||||
return (<Mugic card={card} key={i} ext={this.props.ext} setImage={this.setImage.bind(this)}/>);
|
||||
default:
|
||||
return (<div key={i}>Invalid Card Type</div>);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { observable, action } from "mobx";
|
|||
import { observer, inject } from 'mobx-react';
|
||||
import CardList from './List';
|
||||
import SearchForm from './search/index.js';
|
||||
import './collection.scss'
|
||||
import './collection.scss';
|
||||
|
||||
// https://mobx.js.org/refguide/object.html
|
||||
const fixedStyles = observable({
|
||||
|
|
@ -13,8 +13,8 @@ const fixedStyles = observable({
|
|||
get isFixed() {return (Object.entries(this.style).length !== 0)},
|
||||
setFixed(height) {
|
||||
if (!window.matchMedia("(min-width: 975px)").matches) return;
|
||||
let left = document.getElementById('player').getBoundingClientRect().left + 4;
|
||||
let width = document.querySelector('.collection > .left').getBoundingClientRect().width + 2;
|
||||
const left = document.getElementById('player').getBoundingClientRect().left + 4;
|
||||
const width = document.querySelector('.collection > .left').getBoundingClientRect().width + 2;
|
||||
this.style = {
|
||||
position: "fixed",
|
||||
top: 0,
|
||||
|
|
@ -22,7 +22,7 @@ const fixedStyles = observable({
|
|||
overflowY: "auto",
|
||||
height: `${height}px`,
|
||||
width: `${width}px`,
|
||||
}
|
||||
};
|
||||
},
|
||||
removeFixed() {this.style = {}}
|
||||
}, {
|
||||
|
|
@ -45,7 +45,7 @@ export default class Home extends React.Component {
|
|||
|
||||
constructor() {
|
||||
super();
|
||||
let ext = localStorage.getItem("extended");
|
||||
const ext = localStorage.getItem("extended");
|
||||
if (ext == null) this.ext = false;
|
||||
this.ext = (/true/i).test(ext);
|
||||
}
|
||||
|
|
@ -81,11 +81,11 @@ export default class Home extends React.Component {
|
|||
// Fix the side menu in place when scrolling down
|
||||
if (window.pageYOffset >= 235) {
|
||||
const
|
||||
h = document.documentElement,
|
||||
// b = document.body,
|
||||
st = 'scrollTop',
|
||||
sh = 'scrollHeight',
|
||||
ch = 'clientHeight';
|
||||
h = document.documentElement,
|
||||
// b = document.body,
|
||||
st = 'scrollTop',
|
||||
sh = 'scrollHeight',
|
||||
ch = 'clientHeight';
|
||||
// const percent = (h[st]||b[st]) / ((h[sh]||b[sh]) - h[ch]) * 100;
|
||||
// let exp = h[ch] - (h[ch] * (percent - 85) / 100);
|
||||
const sm = document.getElementById("side-menu");
|
||||
|
|
@ -100,13 +100,13 @@ export default class Home extends React.Component {
|
|||
else if (list.style.minHeight) {
|
||||
list.style.minHeight = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// When nearing the end of the screen
|
||||
// (if element height offset is higher then height of screen)
|
||||
// reduce height by difference so that it doesn't leak past body
|
||||
if (scrollBottom <= 90) {
|
||||
let exp = h[ch] - (90 - scrollBottom);
|
||||
const exp = h[ch] - (90 - scrollBottom);
|
||||
fixedStyles.setFixed(exp);
|
||||
}
|
||||
// Fix with height of side menu to height of viewport
|
||||
|
|
@ -131,7 +131,7 @@ export default class Home extends React.Component {
|
|||
<div className={"collection " + (this.ext ? "extended" : "short")}>
|
||||
<div className="left">
|
||||
<div id="side-menu" style={fixedStyles.fixed}>
|
||||
<ImagePreview url={this.card_img} ref={n => {if (n) this.changeImage = n.getInstance().changeImage}} />
|
||||
<ImagePreview url={this.card_img} ref={n => {if (n) this.changeImage = n.getInstance().changeImage;}} />
|
||||
<SearchForm handleContent={this.handleContent.bind(this)} {...this.props} />
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -153,23 +153,23 @@ export default class Home extends React.Component {
|
|||
return (
|
||||
<div className="ext-button">
|
||||
<button id="buttons" onClick={this.setExt.bind(this)}
|
||||
>{this.ext ? "Short Format" : "Extended Format"}</button>
|
||||
>{this.ext ? "Short Format" : "Extended Format"}</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
navigation() {
|
||||
let numpages = Math.ceil(this.content.length / this.n);
|
||||
const numpages = Math.ceil(this.content.length / this.n);
|
||||
|
||||
let next = () => {
|
||||
if (this.p < numpages) return(<button id="buttons" onClick={ () => {this.p++; window.scrollTo(0, 0);} }>next</button>);
|
||||
else return(<button id="buttons" disabled>next</button>);
|
||||
}
|
||||
const next = () => {
|
||||
if (this.p < numpages) return (<button id="buttons" onClick={ () => {this.p++; window.scrollTo(0, 0)} }>next</button>);
|
||||
else return (<button id="buttons" disabled>next</button>);
|
||||
};
|
||||
|
||||
let prev = () => {
|
||||
if (this.p > 1) return(<button id="buttons" onClick={ () => {this.p--; window.scrollTo(0, 0);} }>prev</button>);
|
||||
else return(<button id="buttons" disabled>prev</button>);
|
||||
}
|
||||
const prev = () => {
|
||||
if (this.p > 1) return (<button id="buttons" onClick={ () => {this.p--; window.scrollTo(0, 0)} }>prev</button>);
|
||||
else return (<button id="buttons" disabled>prev</button>);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="entries">
|
||||
|
|
@ -201,7 +201,7 @@ class imgbase extends React.Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
return(
|
||||
return (
|
||||
<div className="card_img">
|
||||
<img className={(this.display?"":"hidden")} src={this.props.url} />
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ export default class SearchCollection extends React.Component {
|
|||
}
|
||||
|
||||
fetchCollapsed = () => {
|
||||
let collapsed = localStorage.getItem("collapsed")
|
||||
let collapsed = localStorage.getItem("collapsed");
|
||||
|
||||
if (collapsed) collapsed = JSON.parse(collapsed);
|
||||
else collapsed = {
|
||||
|
|
@ -41,19 +41,19 @@ export default class SearchCollection extends React.Component {
|
|||
types: true,
|
||||
rarity: false,
|
||||
sets: false
|
||||
}
|
||||
};
|
||||
|
||||
this.collapsed = collapsed;
|
||||
}
|
||||
|
||||
handleTriggerClick = (type) => {
|
||||
let stored_collapse = this.collapsed;
|
||||
const stored_collapse = this.collapsed;
|
||||
stored_collapse[type] = !this.collapsed[type];
|
||||
localStorage.setItem("collapsed", JSON.stringify(stored_collapse));
|
||||
}
|
||||
|
||||
cleanInput = () => {
|
||||
let input = {
|
||||
const input = {
|
||||
name: "",
|
||||
text: "",
|
||||
subtypes: "",
|
||||
|
|
@ -77,10 +77,10 @@ export default class SearchCollection extends React.Component {
|
|||
parseQuery = () => {
|
||||
const queryString = this.props.location.search.toLowerCase();
|
||||
|
||||
let query = {};
|
||||
let pairs = (queryString[0] === '?' ? queryString.substr(1) : queryString).split('&');
|
||||
const query = {};
|
||||
const pairs = (queryString[0] === '?' ? queryString.substr(1) : queryString).split('&');
|
||||
for (let i = 0; i < pairs.length; i++) {
|
||||
let pair = pairs[i].split('=');
|
||||
const pair = pairs[i].split('=');
|
||||
query[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1] || '');
|
||||
}
|
||||
|
||||
|
|
@ -102,12 +102,12 @@ export default class SearchCollection extends React.Component {
|
|||
if (query.hasOwnProperty('speed')) this.input.disciplines.speed = query.speed;
|
||||
if (query.hasOwnProperty('disc_max')) this.input.disciplines.max = !!query.disc_max;
|
||||
if (query.hasOwnProperty('energy')) {
|
||||
let q = query.energy.split(',');
|
||||
const q = query.energy.split(',');
|
||||
if (q[0] >= 0) this.input.energy.min = q[0];
|
||||
if (q[1] >= 0) this.input.energy.max = q[1];
|
||||
}
|
||||
if (query.hasOwnProperty('mcbp')) {
|
||||
let q = query.mcbp.split(',');
|
||||
const q = query.mcbp.split(',');
|
||||
if (q[0] >= 0) this.input.mcbp.min = q[0];
|
||||
if (q[1] >= 0) this.input.mcbp.max = q[1];
|
||||
}
|
||||
|
|
@ -117,14 +117,14 @@ export default class SearchCollection extends React.Component {
|
|||
async updateQuery() {
|
||||
let queryString = "";
|
||||
|
||||
let update = (query) => {
|
||||
const update = (query) => {
|
||||
let temp = "";
|
||||
Object.keys(this.input[query]).forEach((item) => {
|
||||
if (this.input[query][item] == true) temp += item + ",";
|
||||
});
|
||||
if (temp.length > 0) return query + "=" + temp.replace(/\,$/, '&');
|
||||
else return "";
|
||||
}
|
||||
};
|
||||
|
||||
this.list.forEach(item => queryString += update(item));
|
||||
|
||||
|
|
@ -179,30 +179,31 @@ export default class SearchCollection extends React.Component {
|
|||
this.updateQuery();
|
||||
}
|
||||
|
||||
let results = search_api(this.input);
|
||||
const results = search_api(this.input);
|
||||
|
||||
if (results.length > 0) this.props.handleContent(results);
|
||||
else this.props.handleContent([{ 'text': 'No Results Found' }]);
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.loaded == false) {
|
||||
API.LoadDB([{ 'cards': 'attacks' }, { 'cards': 'battlegear' }, { 'cards': 'creatures' }, { 'cards': 'locations' }, { 'cards': 'mugic' }])
|
||||
if (this.loaded == false) {
|
||||
API.LoadDB([{ 'cards': 'attacks' }, { 'cards': 'battlegear' }, { 'cards': 'creatures' }, { 'cards': 'locations' }, { 'cards': 'mugic' }])
|
||||
.then(() => {
|
||||
this.loaded = true;
|
||||
this.search();
|
||||
});
|
||||
return (<Loading />);
|
||||
}
|
||||
})
|
||||
.catch(() => {});
|
||||
return (<Loading />);
|
||||
}
|
||||
|
||||
const gen = (d, display, text) => {
|
||||
let tmp = [];
|
||||
const tmp = [];
|
||||
Object.keys(this.input[d]).forEach((item, i) => {
|
||||
tmp.push(<label style={{ display: display }} key={i}><input type="checkbox" name={item} checked={this.input[d][item]} onChange={e => this.handleChange(e, d)} />{text(item)}</label>
|
||||
);
|
||||
});
|
||||
return tmp;
|
||||
}
|
||||
};
|
||||
|
||||
const sets = gen("sets", "block", (item) => {
|
||||
return API.sets[item.toUpperCase()];
|
||||
|
|
@ -228,7 +229,7 @@ export default class SearchCollection extends React.Component {
|
|||
return (<span><img className="icon20" src={"/src/img/icons/elements/"+item+".png"} /> </span>);
|
||||
}).slice(0, -2);
|
||||
|
||||
let disciplines = [];
|
||||
const disciplines = [];
|
||||
Object.keys(this.input.disciplines).forEach((item, i) => {
|
||||
if (i == 4) return;
|
||||
disciplines.push(<label key={i} className="disciplines"><input type="text" name={item} value={this.input.disciplines[item]} onChange={e => this.handleChange(e, "disciplines")} />
|
||||
|
|
@ -274,8 +275,8 @@ export default class SearchCollection extends React.Component {
|
|||
<label className="none"><input type="checkbox" name="none" checked={this.input.elements.none} onChange={e => this.handleChange(e, "elements")} /><span>None</span></label>
|
||||
</div>
|
||||
<div className="centeredButtons">
|
||||
<input type="button" value={this.input.elements.none ? "none" : "or"} className="and" disabled={!this.input.elements.and} onClick={(e)=>{this.input.elements.and=false;}} />
|
||||
<input type="button" value={this.input.elements.none ? "only" : "and"} className="and" disabled={this.input.elements.and} onClick={(e)=>{this.input.elements.and=true;}} />
|
||||
<input type="button" value={this.input.elements.none ? "none" : "or"} className="and" disabled={!this.input.elements.and} onClick={(e)=>{this.input.elements.and=false}} />
|
||||
<input type="button" value={this.input.elements.none ? "only" : "and"} className="and" disabled={this.input.elements.and} onClick={(e)=>{this.input.elements.and=true}} />
|
||||
</div>
|
||||
<hr />
|
||||
<CollapsibleWrapper
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ function cleanInputRegex(input) {
|
|||
.replace(/\\/g, '')
|
||||
.replace(/\‘|\’/g, "'")
|
||||
.replace(/\(|\)/g, (match) => ("\\"+match));
|
||||
// .replace(/~(\w+)/, (match) => (`\(?!${match}\)`));
|
||||
// .replace(/~(\w+)/, (match) => (`\(?!${match}\)`));
|
||||
|
||||
return new RegExp(input.trim(), 'i');
|
||||
}
|
||||
|
|
@ -14,7 +14,7 @@ function cleanInputRegex(input) {
|
|||
export default function search_api(input) {
|
||||
|
||||
// Sort data descending alphabetically
|
||||
let filter = (new loki("filter.db")).addCollection('filter');
|
||||
const filter = (new loki("filter.db")).addCollection('filter');
|
||||
var pview = filter.addDynamicView('filter');
|
||||
pview.applySimpleSort('gsx$name');
|
||||
|
||||
|
|
@ -31,21 +31,21 @@ export default function search_api(input) {
|
|||
});
|
||||
battlegearResults = battlegearResults.where((obj) => {
|
||||
return obj.gsx$set != ('');
|
||||
});
|
||||
});
|
||||
creatureResults = creatureResults.where((obj) => {
|
||||
return obj.gsx$set != ('');
|
||||
});
|
||||
});
|
||||
locationResults = locationResults.where((obj) => {
|
||||
return obj.gsx$set != ('');
|
||||
});
|
||||
});
|
||||
mugicResults = mugicResults.where((obj) => {
|
||||
return obj.gsx$set != ('');
|
||||
});
|
||||
});
|
||||
|
||||
// Search by name
|
||||
if (input.name.length > 0) {
|
||||
const negates = [];
|
||||
let inputname = input.name.replace(/(?:~)([\w,()]+)/g, (_, p1) => { negates.push(p1); return ""; });
|
||||
let inputname = input.name.replace(/(?:~)([\w,()]+)/g, (_, p1) => { negates.push(p1); return "" });
|
||||
|
||||
if (inputname.length > 0) {
|
||||
inputname = cleanInputRegex(inputname);
|
||||
|
|
@ -79,7 +79,7 @@ export default function search_api(input) {
|
|||
truth |= (obj.gsx$name.toLowerCase().indexOf(word.toLowerCase().replace('_', ' ')) > -1);
|
||||
});
|
||||
return !truth;
|
||||
}
|
||||
};
|
||||
|
||||
attackResults = attackResults.where(ignoreText);
|
||||
battlegearResults = battlegearResults.where(ignoreText);
|
||||
|
|
@ -94,7 +94,7 @@ export default function search_api(input) {
|
|||
// Card Text
|
||||
if (input.text.length > 0) {
|
||||
const negates = [];
|
||||
let inputtext = input.text.replace(/(?:~)(\w+)/g, (_, p1) => { negates.push(p1); return ""; });
|
||||
let inputtext = input.text.replace(/(?:~)(\w+)/g, (_, p1) => { negates.push(p1); return "" });
|
||||
|
||||
if (inputtext.length > 0) {
|
||||
inputtext = cleanInputRegex(inputtext);
|
||||
|
|
@ -103,7 +103,7 @@ export default function search_api(input) {
|
|||
const list = [
|
||||
{ 'gsx$tags': { '$regex': inputtext }},
|
||||
{ 'gsx$ability': { '$regex': inputtext }}
|
||||
]
|
||||
];
|
||||
if (input.flavor) {
|
||||
list.push({ 'gsx$flavortext': { '$regex': inputtext }});
|
||||
list.push({ 'gsx$artist': { '$regex': inputtext }});
|
||||
|
|
@ -111,7 +111,7 @@ export default function search_api(input) {
|
|||
return list;
|
||||
})();
|
||||
|
||||
attackResults = attackResults.find({ '$or': parm })
|
||||
attackResults = attackResults.find({ '$or': parm });
|
||||
battlegearResults = battlegearResults.find({ '$or': parm });
|
||||
creatureResults = creatureResults.find({ '$or':
|
||||
(parm.concat([{ 'gsx$brainwashed': { '$regex': inputtext }}]))
|
||||
|
|
@ -127,9 +127,9 @@ export default function search_api(input) {
|
|||
truth |= (obj.gsx$ability.toLowerCase().indexOf(word.toLowerCase()) > -1);
|
||||
truth |= (obj.gsx$flavortext.toLowerCase().indexOf(word.toLowerCase()) > -1);
|
||||
if (creature) truth |= (obj.gsx$brainwashed.toLowerCase().indexOf(word.toLowerCase()) > -1);
|
||||
})
|
||||
});
|
||||
return !truth;
|
||||
}
|
||||
};
|
||||
|
||||
attackResults = attackResults.where(ignoreText);
|
||||
battlegearResults = battlegearResults.where(ignoreText);
|
||||
|
|
@ -142,7 +142,7 @@ export default function search_api(input) {
|
|||
|
||||
// Subtypes / Initiative
|
||||
if (input.subtypes.length > 0) {
|
||||
let subtypesList = input.subtypes.split(",").filter(Boolean).map((item) => {
|
||||
const subtypesList = input.subtypes.split(",").filter(Boolean).map((item) => {
|
||||
return ({ '$regex': cleanInputRegex(item) });
|
||||
});
|
||||
|
||||
|
|
@ -154,7 +154,7 @@ export default function search_api(input) {
|
|||
}
|
||||
|
||||
// Search by tribe
|
||||
let tribesList = [];
|
||||
const tribesList = [];
|
||||
for (const tribe in input.tribes) {
|
||||
if (input.tribes[tribe])
|
||||
tribesList.push({ '$regex': new RegExp(tribe, 'i') });
|
||||
|
|
@ -181,13 +181,13 @@ export default function search_api(input) {
|
|||
}
|
||||
else {
|
||||
attackResults = attackResults.where(
|
||||
(obj) => {return (input.elements.fire ? obj.gsx$fire != ('') : obj.gsx$fire == (''));}
|
||||
(obj) => {return (input.elements.fire ? obj.gsx$fire != ('') : obj.gsx$fire == (''))}
|
||||
).where(
|
||||
(obj) => {return (input.elements.air ? obj.gsx$air != ('') : obj.gsx$air == (''));}
|
||||
(obj) => {return (input.elements.air ? obj.gsx$air != ('') : obj.gsx$air == (''))}
|
||||
).where(
|
||||
(obj) => {return (input.elements.earth ? obj.gsx$earth != ('') : obj.gsx$earth == (''));}
|
||||
(obj) => {return (input.elements.earth ? obj.gsx$earth != ('') : obj.gsx$earth == (''))}
|
||||
).where(
|
||||
(obj) => {return (input.elements.water ? obj.gsx$water != ('') : obj.gsx$water == (''));}
|
||||
(obj) => {return (input.elements.water ? obj.gsx$water != ('') : obj.gsx$water == (''))}
|
||||
);
|
||||
|
||||
let el = "";
|
||||
|
|
@ -208,19 +208,19 @@ export default function search_api(input) {
|
|||
mugicResults = mugicResults.limit(0);
|
||||
}
|
||||
else {
|
||||
let elementsList = [];
|
||||
let elementsList2 = [];
|
||||
const elementsList = [];
|
||||
const elementsList2 = [];
|
||||
for (const element in input.elements) {
|
||||
if (element === "none" || element === "and") continue;
|
||||
if (input.elements[element]) {
|
||||
elementsList.push({ '$regex': new RegExp(element, 'i') });
|
||||
elementsList2.push({ ['gsx$'+element]: { '$gte': 0 }})
|
||||
elementsList2.push({ ['gsx$'+element]: { '$gte': 0 }});
|
||||
}
|
||||
}
|
||||
if (elementsList.length > 0) {
|
||||
if (input.elements.and) {
|
||||
creatureResults = creatureResults.find({ 'gsx$elements': { '$and': elementsList }});
|
||||
attackResults = attackResults.find({ '$and': elementsList2 });
|
||||
creatureResults = creatureResults.find({ 'gsx$elements': { '$and': elementsList }});
|
||||
attackResults = attackResults.find({ '$and': elementsList2 });
|
||||
}
|
||||
else {
|
||||
creatureResults = creatureResults.find({ 'gsx$elements': { '$or': elementsList }});
|
||||
|
|
@ -316,17 +316,17 @@ export default function search_api(input) {
|
|||
}
|
||||
|
||||
// Sets
|
||||
let setsList = [];
|
||||
const setsList = [];
|
||||
|
||||
for (let key in input.sets) {
|
||||
for (const key in input.sets) {
|
||||
if (input.sets[key])
|
||||
setsList.push({ '$eq': key.toUpperCase() });
|
||||
}
|
||||
if (setsList.length === 0) {
|
||||
// Only show prototype cards when explicitly selected
|
||||
let keys = Object.keys(input.sets);
|
||||
const keys = Object.keys(input.sets);
|
||||
if (!input.sets.proto) keys.splice(keys.indexOf("proto"));
|
||||
for (let i in keys) {
|
||||
for (const i in keys) {
|
||||
setsList.push({ '$eq': keys[i].toUpperCase() });
|
||||
}
|
||||
}
|
||||
|
|
@ -339,7 +339,7 @@ export default function search_api(input) {
|
|||
}
|
||||
|
||||
// Rarity
|
||||
let rarityList = [];
|
||||
const rarityList = [];
|
||||
for (const key in input.rarity) {
|
||||
if (input.rarity[key])
|
||||
rarityList.push({ '$eq': key.split(" ").map(st => {return st.charAt(0).toUpperCase()+st.slice(1)}).join(" ") });
|
||||
|
|
@ -367,30 +367,30 @@ export default function search_api(input) {
|
|||
// }
|
||||
|
||||
// Merge data
|
||||
let types = !(input.types.attack | input.types.battlegear | input.types.creature | input.types.location | input.types.mugic);
|
||||
const types = !(input.types.attack | input.types.battlegear | input.types.creature | input.types.location | input.types.mugic);
|
||||
|
||||
if (types || input.types.attack) {
|
||||
let temp = attackResults.data();
|
||||
const temp = attackResults.data();
|
||||
temp.forEach((v) => { delete v.$loki });
|
||||
filter.insert(temp);
|
||||
}
|
||||
if (types || input.types.battlegear) {
|
||||
let temp = battlegearResults.data();
|
||||
const temp = battlegearResults.data();
|
||||
temp.forEach((v) => { delete v.$loki });
|
||||
filter.insert(temp);
|
||||
}
|
||||
if (types || input.types.creature) {
|
||||
let temp = creatureResults.data()
|
||||
const temp = creatureResults.data();
|
||||
temp.forEach((v) => { delete v.$loki });
|
||||
filter.insert(temp);
|
||||
}
|
||||
if (types || input.types.location) {
|
||||
let temp = locationResults.data()
|
||||
const temp = locationResults.data();
|
||||
temp.forEach((v) => { delete v.$loki });
|
||||
filter.insert(temp);
|
||||
}
|
||||
if (types || input.types.mugic) {
|
||||
let temp = mugicResults.data()
|
||||
const temp = mugicResults.data();
|
||||
temp.forEach((v) => { delete v.$loki });
|
||||
filter.insert(temp);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import { Rarity, Unique, Name, Element, Ability, AttackIcon } from '../../Snippe
|
|||
export default class Attack extends React.Component {
|
||||
|
||||
render() {
|
||||
let { card } = this.props;
|
||||
const { card } = this.props;
|
||||
|
||||
if (this.props.ext == false) return (
|
||||
<div className="card attack">
|
||||
|
|
@ -31,7 +31,7 @@ export default class Attack extends React.Component {
|
|||
<span className="flavortext">{card.gsx$flavortext}</span>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
else return (
|
||||
<div className="card attack">
|
||||
<div className="fullcard"><img src={API.cardImage(card)} /></div>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import { Rarity, Unique, Name, Ability, BattlegearIcon } from '../../Snippets';
|
|||
export default class Battlegear extends React.Component {
|
||||
|
||||
render() {
|
||||
let { card } = this.props;
|
||||
const { card } = this.props;
|
||||
|
||||
if (this.props.ext == false) return (
|
||||
<div className="card battlegear">
|
||||
|
|
|
|||
|
|
@ -7,15 +7,15 @@ import { Rarity, Unique, Name, Element, Mugic, Discipline, Ability, Tribe } from
|
|||
export default class Creature extends React.Component {
|
||||
|
||||
render() {
|
||||
let { card } = this.props;
|
||||
const { card } = this.props;
|
||||
|
||||
let mugic = [];
|
||||
const mugic = [];
|
||||
for (let i = 0; i < card.gsx$mugicability; i++) {
|
||||
mugic.push(<Mugic key={i} tribe={card.gsx$tribe} />);
|
||||
}
|
||||
|
||||
const TribeLine = () => {
|
||||
let tribe = card.gsx$tribe;
|
||||
const tribe = card.gsx$tribe;
|
||||
let types = card.gsx$types;
|
||||
let past = false;
|
||||
if (types.toLowerCase().includes("past")) {
|
||||
|
|
@ -24,10 +24,10 @@ export default class Creature extends React.Component {
|
|||
}
|
||||
|
||||
// <past> <tribe> <types>
|
||||
let line = " " + (past ? "Past " : "") + (tribe == "Generic" ? "" : tribe + " ") + types;
|
||||
const line = " " + (past ? "Past " : "") + (tribe == "Generic" ? "" : tribe + " ") + types;
|
||||
|
||||
return <span><Tribe tribe={tribe} />{line}</span>
|
||||
}
|
||||
return <span><Tribe tribe={tribe} />{line}</span>;
|
||||
};
|
||||
|
||||
if (this.props.ext == false) return (
|
||||
<div className="card creature">
|
||||
|
|
@ -78,7 +78,7 @@ export default class Creature extends React.Component {
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
else return (
|
||||
<div className="card creature">
|
||||
<div className="fullcard"><img src={API.cardImage(card)} /></div>
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import API from '../../SpreadsheetData';
|
|||
export default class Location extends React.Component {
|
||||
|
||||
render() {
|
||||
let { card } = this.props;
|
||||
const { card } = this.props;
|
||||
|
||||
if (this.props.ext == false) return (
|
||||
<div className="card location">
|
||||
|
|
@ -25,7 +25,7 @@ export default class Location extends React.Component {
|
|||
<span className="flavortext">{card.gsx$flavortext}</span>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
else return (
|
||||
<div className="card location">
|
||||
<div className="fullcard"><img src={API.cardImage(card)} /></div>
|
||||
|
|
|
|||
|
|
@ -9,9 +9,9 @@ import { withRouter } from 'react-router';
|
|||
class Attack extends React.Component {
|
||||
|
||||
render() {
|
||||
let { card, history } = this.props;
|
||||
const { card, history } = this.props;
|
||||
|
||||
let mugicCounters = [];
|
||||
const mugicCounters = [];
|
||||
if (card.gsx$cost == 0) {
|
||||
mugicCounters.push(<Mugic tribe={card.gsx$tribe} key={0} amount={"0"}/>);
|
||||
}
|
||||
|
|
@ -45,7 +45,7 @@ class Attack extends React.Component {
|
|||
<span className="flavortext">{card.gsx$flavortext}</span>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
else return (
|
||||
<div className="card mugic">
|
||||
<div className="fullcard"><img src={API.cardImage(card)} /></div>
|
||||
|
|
|
|||
|
|
@ -24,25 +24,25 @@
|
|||
// }
|
||||
|
||||
|
||||
/* https://codeburst.io/throttling-and-debouncing-in-javascript-646d076d0a44 */
|
||||
export function debounced(delay, fn) {
|
||||
let timerId;
|
||||
return function (...args) {
|
||||
if (timerId) clearTimeout(timerId);
|
||||
timerId = setTimeout(() => {
|
||||
fn(...args);
|
||||
timerId = null;
|
||||
}, delay);
|
||||
}
|
||||
}
|
||||
/* https://codeburst.io/throttling-and-debouncing-in-javascript-646d076d0a44 */
|
||||
export function debounced(delay, fn) {
|
||||
let timerId;
|
||||
return function (...args) {
|
||||
if (timerId) clearTimeout(timerId);
|
||||
timerId = setTimeout(() => {
|
||||
fn(...args);
|
||||
timerId = null;
|
||||
}, delay);
|
||||
};
|
||||
}
|
||||
|
||||
export function throttled(delay, fn) {
|
||||
let lastCall = 0;
|
||||
return function (...args) {
|
||||
const now = (new Date).getTime();
|
||||
if (now - lastCall < delay) return;
|
||||
lastCall = now;
|
||||
return fn(...args);
|
||||
}
|
||||
}
|
||||
export function throttled(delay, fn) {
|
||||
let lastCall = 0;
|
||||
return function (...args) {
|
||||
const now = (new Date).getTime();
|
||||
if (now - lastCall < delay) return;
|
||||
lastCall = now;
|
||||
return fn(...args);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -18,19 +18,19 @@ s.input = {
|
|||
margin: '0.05em',
|
||||
backgroundColor: "rgba(0,0,0,0)",
|
||||
color: "white",
|
||||
}
|
||||
};
|
||||
|
||||
s.inputGroup = {
|
||||
// display: 'flex',
|
||||
alignItems: 'center',
|
||||
}
|
||||
};
|
||||
|
||||
s.hyphen = {
|
||||
background: 'white',
|
||||
height: '0.1em',
|
||||
width: '.5em',
|
||||
display: 'inline-block',
|
||||
}
|
||||
};
|
||||
|
||||
@inject((stores, props, context) => props) @observer
|
||||
export default class EnterTheCode extends React.Component {
|
||||
|
|
@ -46,14 +46,14 @@ export default class EnterTheCode extends React.Component {
|
|||
return (<Loading />);
|
||||
}
|
||||
|
||||
let getRandomInt = (min, max) => {
|
||||
const getRandomInt = (min, max) => {
|
||||
min = Math.ceil(min);
|
||||
max = Math.floor(max);
|
||||
//The maximum is exclusive and the minimum is inclusive
|
||||
return Math.floor(Math.random() * (max - min)) + min;
|
||||
}
|
||||
};
|
||||
|
||||
let validate = (e) => {
|
||||
const validate = (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
|
|
@ -63,9 +63,9 @@ export default class EnterTheCode extends React.Component {
|
|||
);
|
||||
}
|
||||
else {
|
||||
let card = this.fan[getRandomInt(0, this.fan.length)];
|
||||
let rgx = /.*.png|.*.jpg/i;
|
||||
let img = (rgx.test(card.gsx$image.$t) ? card.gsx$image.$t : API.base_image + card.gsx$image.$t);
|
||||
const card = this.fan[getRandomInt(0, this.fan.length)];
|
||||
const rgx = /.*.png|.*.jpg/i;
|
||||
const img = (rgx.test(card.gsx$image.$t) ? card.gsx$image.$t : API.base_image + card.gsx$image.$t);
|
||||
this.message.contents = (
|
||||
<div key={0}>
|
||||
<p> Congrats on your scan! </p><br />
|
||||
|
|
@ -74,9 +74,9 @@ export default class EnterTheCode extends React.Component {
|
|||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return(
|
||||
return (
|
||||
<div>
|
||||
<Interactive as={Link} {...s.link}
|
||||
to={`/EnterTheCode/PackSimulator/`}>Pack Simulator</Interactive>
|
||||
|
|
@ -104,7 +104,7 @@ export default class EnterTheCode extends React.Component {
|
|||
<input type="text" style={s.input} {...props[10]} />
|
||||
<input type="text" style={s.input} {...props[11]} />
|
||||
</div>
|
||||
)}
|
||||
)}
|
||||
</DigitInput>
|
||||
<br />
|
||||
<button onClick={validate}>Validate Code</button>
|
||||
|
|
|
|||
|
|
@ -7,147 +7,147 @@ class GenerateCard {
|
|||
@observable filter = null;
|
||||
|
||||
setupDB = () => {
|
||||
let filter = (new loki("filter.db")).addCollection('filter');
|
||||
const filter = (new loki("filter.db")).addCollection('filter');
|
||||
|
||||
// Sort data descending alphabetically
|
||||
var pview = filter.addDynamicView('alphabetical');
|
||||
pview.applySimpleSort('gsx$name');
|
||||
// Sort data descending alphabetically
|
||||
var pview = filter.addDynamicView('alphabetical');
|
||||
pview.applySimpleSort('gsx$name');
|
||||
|
||||
let temp;
|
||||
let temp;
|
||||
|
||||
temp = API.cards.attacks.find();
|
||||
temp.forEach((v) => delete v.$loki);
|
||||
filter.insert(temp);
|
||||
temp = API.cards.attacks.find();
|
||||
temp.forEach((v) => delete v.$loki);
|
||||
filter.insert(temp);
|
||||
|
||||
temp = API.cards.battlegear.find();
|
||||
temp.forEach((v) => delete v.$loki);
|
||||
filter.insert(temp);
|
||||
temp = API.cards.battlegear.find();
|
||||
temp.forEach((v) => delete v.$loki);
|
||||
filter.insert(temp);
|
||||
|
||||
temp = API.cards.creatures.find();
|
||||
temp.forEach((v) => delete v.$loki);
|
||||
filter.insert(temp);
|
||||
temp = API.cards.creatures.find();
|
||||
temp.forEach((v) => delete v.$loki);
|
||||
filter.insert(temp);
|
||||
|
||||
temp = API.cards.locations.find();
|
||||
temp.forEach((v) => delete v.$loki);
|
||||
filter.insert(temp);
|
||||
temp = API.cards.locations.find();
|
||||
temp.forEach((v) => delete v.$loki);
|
||||
filter.insert(temp);
|
||||
|
||||
temp = API.cards.mugic.find();
|
||||
temp.forEach((v) => delete v.$loki);
|
||||
filter.insert(temp);
|
||||
temp = API.cards.mugic.find();
|
||||
temp.forEach((v) => delete v.$loki);
|
||||
filter.insert(temp);
|
||||
|
||||
this.filter = filter;
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
generate = ({ packs, set }) => {
|
||||
let cards = []; // Returned list of card divs
|
||||
let card_names = []; // Prevent duplicates in pack
|
||||
let key = 0; // React key iterator uniqueness
|
||||
const cards = []; // Returned list of card divs
|
||||
let card_names = []; // Prevent duplicates in pack
|
||||
let key = 0; // React key iterator uniqueness
|
||||
|
||||
let pview = this.filter.addDynamicView('set');
|
||||
const pview = this.filter.addDynamicView('set');
|
||||
|
||||
const gendisp = (avg) => {
|
||||
let min = parseInt(avg) - 10;
|
||||
if (min < 0) min = 0;
|
||||
return (Math.floor(Math.random() * 5)) * 5 + min;
|
||||
}
|
||||
const geneng = (avg) => {
|
||||
let min = parseInt(avg) - 5;
|
||||
if (min < 0) min = 0;
|
||||
return (Math.floor(Math.random() * 3)) * 5 + min;
|
||||
const gendisp = (avg) => {
|
||||
let min = parseInt(avg) - 10;
|
||||
if (min < 0) min = 0;
|
||||
return (Math.floor(Math.random() * 5)) * 5 + min;
|
||||
};
|
||||
const geneng = (avg) => {
|
||||
let min = parseInt(avg) - 5;
|
||||
if (min < 0) min = 0;
|
||||
return (Math.floor(Math.random() * 3)) * 5 + min;
|
||||
};
|
||||
|
||||
const gencard = (results) => {
|
||||
const id = Math.floor(Math.random() * results.length);
|
||||
const card = results[id];
|
||||
|
||||
if (!card) {
|
||||
cards.push(<div key={key++} className="card" style={{ backgroundImage: `url("${API.card_back}")` }}></div>);
|
||||
return;
|
||||
}
|
||||
|
||||
const gencard = (results) => {
|
||||
let id = Math.floor(Math.random() * results.length);
|
||||
let card = results[id];
|
||||
|
||||
if (!card) {
|
||||
cards.push(<div key={key++} className="card" style={{ backgroundImage: `url("${API.card_back}")` }}></div>);
|
||||
return;
|
||||
}
|
||||
|
||||
if (card_names.indexOf(card.gsx$name) > -1 || card.gsx$exclusive.toLowerCase().includes("starter")) {
|
||||
gencard(results);
|
||||
return;
|
||||
}
|
||||
if (card_names.indexOf(card.gsx$name) > -1 || card.gsx$exclusive.toLowerCase().includes("starter")) {
|
||||
gencard(results);
|
||||
return;
|
||||
}
|
||||
|
||||
card_names.push(card.gsx$name);
|
||||
|
||||
if (card.gsx$type != "Creatures") {
|
||||
cards.push(<div key={key++} className="card" style={{ backgroundImage: `url("${API.cardImage(card)}")` }}></div>);
|
||||
}
|
||||
else {
|
||||
cards.push(
|
||||
<div key={key++} className="card" style={{ backgroundImage: `url("${API.cardImage(card)}")` }}>
|
||||
<div className="stats">
|
||||
<span key="courage">{gendisp(card.gsx$courage)}</span>
|
||||
<span key="power">{gendisp(card.gsx$power)}</span>
|
||||
<span key="wisdom">{gendisp(card.gsx$wisdom)}</span>
|
||||
<span key="speed">{gendisp(card.gsx$speed)}</span>
|
||||
<span key="energy">{geneng(card.gsx$energy)}</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
card_names.push(card.gsx$name);
|
||||
|
||||
if (card.gsx$type != "Creatures") {
|
||||
cards.push(<div key={key++} className="card" style={{ backgroundImage: `url("${API.cardImage(card)}")` }}></div>);
|
||||
}
|
||||
else {
|
||||
cards.push(
|
||||
<div key={key++} className="card" style={{ backgroundImage: `url("${API.cardImage(card)}")` }}>
|
||||
<div className="stats">
|
||||
<span key="courage">{gendisp(card.gsx$courage)}</span>
|
||||
<span key="power">{gendisp(card.gsx$power)}</span>
|
||||
<span key="wisdom">{gendisp(card.gsx$wisdom)}</span>
|
||||
<span key="speed">{gendisp(card.gsx$speed)}</span>
|
||||
<span key="energy">{geneng(card.gsx$energy)}</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const genrarity = (rarity, num) => {
|
||||
pview.applyFind({ 'gsx$set': set })
|
||||
};
|
||||
|
||||
const genrarity = (rarity, num) => {
|
||||
pview.applyFind({ 'gsx$set': set })
|
||||
.applyFind({ 'gsx$rarity': rarity });
|
||||
let results = pview.data();
|
||||
for (let i = 0; i < num; i++) gencard(results);
|
||||
pview.removeFilters();
|
||||
const results = pview.data();
|
||||
for (let i = 0; i < num; i++) gencard(results);
|
||||
pview.removeFilters();
|
||||
};
|
||||
|
||||
|
||||
|
||||
// DOP to FUN had 9 cards: 4 Common, 3 Uncommon, 2 Rare+
|
||||
// OP1 had 3 cards: 2 Common, 1 Uncommon+
|
||||
// Premium Packs had 6 cards, 5 Super and 1 Ultra
|
||||
// AU sets had 9 cards: 6 Common and 3 Rare+
|
||||
const randomRare = () => {
|
||||
const randomNumber = Math.floor(Math.random() * 24) + 1;
|
||||
if (randomNumber == 24) return "Ultra Rare";
|
||||
else if (randomNumber % 3 == 0) return "Super Rare";
|
||||
else return "Rare";
|
||||
};
|
||||
|
||||
const newSets = ["AU", "FAS"];
|
||||
|
||||
for (let i = 0; i < packs; i++) {
|
||||
if (set === "OP1") {
|
||||
genrarity("Common", 2);
|
||||
genrarity((() => {
|
||||
const rnd = Math.floor(Math.random() * 75) + 1;
|
||||
if (rnd == 75) return "Ultra Rare";
|
||||
else if (rnd < 19) return "Super Rare";
|
||||
else if (rnd < 44) return "Rare";
|
||||
else return "Uncommon";
|
||||
})(), 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// DOP to FUN had 9 cards: 4 Common, 3 Uncommon, 2 Rare+
|
||||
// OP1 had 3 cards: 2 Common, 1 Uncommon+
|
||||
// Premium Packs had 6 cards, 5 Super and 1 Ultra
|
||||
// AU sets had 9 cards: 6 Common and 3 Rare+
|
||||
const randomRare = () => {
|
||||
let randomNumber = Math.floor(Math.random() * 24) + 1;
|
||||
if (randomNumber == 24) return "Ultra Rare";
|
||||
else if (randomNumber % 3 == 0) return "Super Rare";
|
||||
else return "Rare";
|
||||
};
|
||||
|
||||
const newSets = ["AU", "FAS"];
|
||||
|
||||
for (let i = 0; i < packs; i++) {
|
||||
if (set === "OP1") {
|
||||
genrarity("Common", 2);
|
||||
genrarity((() => {
|
||||
const rnd = Math.floor(Math.random() * 75) + 1;
|
||||
if (rnd == 75) return "Ultra Rare";
|
||||
else if (rnd < 19) return "Super Rare";
|
||||
else if (rnd < 44) return "Rare";
|
||||
else return "Uncommon";
|
||||
})(), 1);
|
||||
}
|
||||
else if (set === "PE1") {
|
||||
genrarity("Super Rare", 5);
|
||||
genrarity("Ultra Rare", 1);
|
||||
}
|
||||
// AU sets and after
|
||||
else if (newSets.indexOf(set) > -1) {
|
||||
genrarity('Common', 6);
|
||||
genrarity('Rare', 2);
|
||||
genrarity(randomRare(), 1);
|
||||
}
|
||||
else {
|
||||
// Before AU sets
|
||||
genrarity('Common', 4);
|
||||
genrarity('Uncommon', 3);
|
||||
genrarity('Rare', 1);
|
||||
genrarity(randomRare(), 1);
|
||||
}
|
||||
card_names = [];
|
||||
else if (set === "PE1") {
|
||||
genrarity("Super Rare", 5);
|
||||
genrarity("Ultra Rare", 1);
|
||||
}
|
||||
// AU sets and after
|
||||
else if (newSets.indexOf(set) > -1) {
|
||||
genrarity('Common', 6);
|
||||
genrarity('Rare', 2);
|
||||
genrarity(randomRare(), 1);
|
||||
}
|
||||
else {
|
||||
// Before AU sets
|
||||
genrarity('Common', 4);
|
||||
genrarity('Uncommon', 3);
|
||||
genrarity('Rare', 1);
|
||||
genrarity(randomRare(), 1);
|
||||
}
|
||||
card_names = [];
|
||||
}
|
||||
|
||||
this.filter.removeDynamicView('set');
|
||||
this.filter.removeDynamicView('set');
|
||||
|
||||
return cards;
|
||||
return cards;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,75 +8,76 @@ import s from '../../../styles/style';
|
|||
import '../packs.scss';
|
||||
|
||||
export default function (props) {
|
||||
const [loaded, setLoaded] = useState(false);
|
||||
const [set, setSet] = useState("");
|
||||
const [setsInput, setSetsInput] = useState([]);
|
||||
const [cards, setCards] = useState([]);
|
||||
const [packs, setPacks] = useState(1);
|
||||
const [loaded, setLoaded] = useState(false);
|
||||
const [set, setSet] = useState("");
|
||||
const [setsInput, setSetsInput] = useState([]);
|
||||
const [cards, setCards] = useState([]);
|
||||
const [packs, setPacks] = useState(1);
|
||||
|
||||
useEffect(() => {
|
||||
API.LoadDB([{ 'cards': 'attacks' }, { 'cards': 'battlegear' }, { 'cards': 'creatures' }, { 'cards': 'locations' }, { 'cards': 'mugic' }])
|
||||
.then(() => {
|
||||
setupDB();
|
||||
setLoaded(true);
|
||||
});
|
||||
useEffect(() => {
|
||||
API.LoadDB([{ 'cards': 'attacks' }, { 'cards': 'battlegear' }, { 'cards': 'creatures' }, { 'cards': 'locations' }, { 'cards': 'mugic' }])
|
||||
.then(() => {
|
||||
setupDB();
|
||||
setLoaded(true);
|
||||
})
|
||||
.catch(() => {});
|
||||
|
||||
let cards = [];
|
||||
for (let i = 0; i < 9; i++) {
|
||||
cards.push(<div key={i} className="card" style={{ backgroundImage: `url("${API.card_back}")` }}></div>);
|
||||
}
|
||||
setCards(cards);
|
||||
|
||||
let setsInput = [];
|
||||
let i = 1;
|
||||
for (const set in API.sets) {
|
||||
setsInput.push(<option key={i++} value={set}>{API.sets[set]}</option>);
|
||||
if (set === "PE1") break;
|
||||
}
|
||||
setSetsInput(setsInput);
|
||||
}, []);
|
||||
|
||||
if (loaded == false) {
|
||||
return (<Loading />);
|
||||
const cards = [];
|
||||
for (let i = 0; i < 9; i++) {
|
||||
cards.push(<div key={i} className="card" style={{ backgroundImage: `url("${API.card_back}")` }}></div>);
|
||||
}
|
||||
setCards(cards);
|
||||
|
||||
const onPacksChange = (e) => {
|
||||
if (e.target.value > 24) e.target.value = 24;
|
||||
setPacks(e.target.value);
|
||||
const setsInput = [];
|
||||
let i = 1;
|
||||
for (const set in API.sets) {
|
||||
setsInput.push(<option key={i++} value={set}>{API.sets[set]}</option>);
|
||||
if (set === "PE1") break;
|
||||
}
|
||||
setSetsInput(setsInput);
|
||||
}, []);
|
||||
|
||||
const onSetChange = (e) => {
|
||||
setSet(e.target.value);
|
||||
}
|
||||
if (loaded == false) {
|
||||
return (<Loading />);
|
||||
}
|
||||
|
||||
const handleSubmit = (e) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
const onPacksChange = (e) => {
|
||||
if (e.target.value > 24) e.target.value = 24;
|
||||
setPacks(e.target.value);
|
||||
};
|
||||
|
||||
setCards(generate({ packs, set }));
|
||||
}
|
||||
const onSetChange = (e) => {
|
||||
setSet(e.target.value);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="packsim">
|
||||
<Interactive as={Link} {...s.link} to={`/EnterTheCode/`}>Enter The Code</Interactive>
|
||||
const handleSubmit = (e) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
setCards(generate({ packs, set }));
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="packsim">
|
||||
<Interactive as={Link} {...s.link} to={`/EnterTheCode/`}>Enter The Code</Interactive>
|
||||
<br /><br />
|
||||
<form onSubmit={handleSubmit}>
|
||||
<label>Packs:
|
||||
<input name="packs" type="number"
|
||||
value={packs}
|
||||
min="1" max="24"
|
||||
style={{ width: "32px", padding: '0px' }}
|
||||
onChange={onPacksChange} />
|
||||
</label>
|
||||
<select name="set" value={set} onChange={onSetChange}>
|
||||
<option defaultValue="selected" hidden style={{ fontStyle: 'italic' }}>Select a Set</option>
|
||||
{setsInput}
|
||||
</select>
|
||||
<br /><br />
|
||||
<form onSubmit={handleSubmit}>
|
||||
<label>Packs:
|
||||
<input name="packs" type="number"
|
||||
value={packs}
|
||||
min="1" max="24"
|
||||
style={{ width: "32px", padding: '0px' }}
|
||||
onChange={onPacksChange} />
|
||||
</label>
|
||||
<select name="set" value={set} onChange={onSetChange}>
|
||||
<option defaultValue="selected" hidden style={{ fontStyle: 'italic' }}>Select a Set</option>
|
||||
{setsInput}
|
||||
</select>
|
||||
<br /><br />
|
||||
<input disabled={!set} type="submit" value="Open Packs" />
|
||||
</form>
|
||||
<br /><br />
|
||||
<div className="pack">{cards}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
<input disabled={!set} type="submit" value="Open Packs" />
|
||||
</form>
|
||||
<br /><br />
|
||||
<div className="pack">{cards}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ const LoreEntry = ({ block, text, sets }) => {
|
|||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default class Home extends React.Component {
|
||||
state = { lore: []};
|
||||
|
|
@ -40,10 +40,9 @@ export default class Home extends React.Component {
|
|||
})
|
||||
.then((lore) => {
|
||||
this.setState({ "lore": lore });
|
||||
return;
|
||||
})
|
||||
.catch(() => {
|
||||
this.setState({ "lore": [{ "block": "Unable to load lore...", "text": []}]})
|
||||
this.setState({ "lore": [{ "block": "Unable to load lore...", "text": []}]});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -62,7 +61,7 @@ export default class Home extends React.Component {
|
|||
</div>
|
||||
<div>Do you like the site? You can donate to support it!</div>
|
||||
<div className="donate"><Donate /></div>
|
||||
<div className="lore">We were unsatisfied with the options on how to search for cards. I took the design of the old Chaotic website and added my own modernizations. With an extensive lists of search options in the <Link to="/collection">collection</Link>, you'll find deck building mores streamlined than ever before. Chaotic is full of rich lore, but unfortunately the best database of official lore disapeared when the <Link to="/portal">Portal to Perim</Link> disapeared along with the site. You can again explore the official lore and information of Creatures!
|
||||
<div className="lore">We were unsatisfied with the options on how to search for cards. I took the design of the old Chaotic website and added my own modernizations. With an extensive lists of search options in the <Link to="/collection">collection</Link>, you'll find deck building mores streamlined than ever before. Chaotic is full of rich lore, but unfortunately the best database of official lore disapeared when the <Link to="/portal">Portal to Perim</Link> disapeared along with the official site. You can again explore the official lore and information!
|
||||
</div>
|
||||
<br />
|
||||
{this.state.lore.length > 0
|
||||
|
|
|
|||
|
|
@ -4,21 +4,21 @@ import { expect } from 'chai';
|
|||
import { parseTune, output } from './mugicparser';
|
||||
|
||||
const cases = {
|
||||
"Canon of Casuality": {
|
||||
input: "2Eb 2F 2D 2G 2Bb 1A 3D",
|
||||
output: ["2Eb4", "2F4", "2D4", "2G4", "2Bb5", "1A5", "3D5"]
|
||||
},
|
||||
"Fortissimo": {
|
||||
input: "2G#4 1C#5 2E5 2C#5 2D#5 1G#4 4F#5",
|
||||
output: ["2G#4", "1C#5", "2E5", "2C#5", "2D#5", "1G#4", "4F#5"]
|
||||
}
|
||||
}
|
||||
"Canon of Casuality": {
|
||||
input: "2Eb 2F 2D 2G 2Bb 1A 3D",
|
||||
output: ["2Eb4", "2F4", "2D4", "2G4", "2Bb5", "1A5", "3D5"]
|
||||
},
|
||||
"Fortissimo": {
|
||||
input: "2G#4 1C#5 2E5 2C#5 2D#5 1G#4 4F#5",
|
||||
output: ["2G#4", "1C#5", "2E5", "2C#5", "2D#5", "1G#4", "4F#5"]
|
||||
}
|
||||
};
|
||||
|
||||
Object.entries(cases).forEach(([key, value]) => {
|
||||
describe(key, () => {
|
||||
it(`should return ${value.output}`, () => {
|
||||
const tune = output(parseTune(value.input));
|
||||
expect(tune).to.deep.equal(value.output);
|
||||
});
|
||||
describe(key, () => {
|
||||
it(`should return ${value.output}`, () => {
|
||||
const tune = output(parseTune(value.input));
|
||||
expect(tune).to.deep.equal(value.output);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -6,61 +6,61 @@ export class Note {
|
|||
velocity: number;
|
||||
|
||||
constructor(duration: number, time: number, value: {pitch: string, octave: number}, velocity?: number) {
|
||||
this.duration = duration;
|
||||
this.time = time;
|
||||
this.pitch = value.pitch;
|
||||
this.octave = value.octave;
|
||||
if (velocity) this.velocity = velocity;
|
||||
this.duration = duration;
|
||||
this.time = time;
|
||||
this.pitch = value.pitch;
|
||||
this.octave = value.octave;
|
||||
if (velocity) this.velocity = velocity;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export const output = (seq: Note[]) => {
|
||||
return seq.map(n => n.duration + n.pitch + n.octave.toString())
|
||||
}
|
||||
return seq.map(n => n.duration + n.pitch + n.octave.toString());
|
||||
};
|
||||
|
||||
// db notation uses duration (quarter notes) and pitch
|
||||
// 2Eb => E flat for 2 quarter notes
|
||||
export const parseTune = (input: string): Note[] => {
|
||||
const seq: Note[] = [];
|
||||
let time = 0;
|
||||
console.log(input.split(" "));
|
||||
input.split(" ").forEach((note) => {
|
||||
const splitter = /(?:[1-8]{1})/;
|
||||
const seq: Note[] = [];
|
||||
let time = 0;
|
||||
console.log(input.split(" "));
|
||||
input.split(" ").forEach((note) => {
|
||||
const splitter = /(?:[1-8]{1})/;
|
||||
|
||||
const match = note.match(splitter);
|
||||
if (match === null) throw new Error("invalid_input");
|
||||
const match = note.match(splitter);
|
||||
if (match === null) throw new Error("invalid_input");
|
||||
|
||||
const dur = parseInt(match[0]);
|
||||
const pitch = note.split(splitter)[1];
|
||||
const dur = parseInt(match[0]);
|
||||
const pitch = note.split(splitter)[1];
|
||||
|
||||
const full_note = /[1-8]{1}[A-Za-z#]{1,2}([1-8]{1})/;
|
||||
if (full_note.test(note)) {
|
||||
const sp = note.match(full_note);
|
||||
if (sp === null) throw new Error("invalid_input");
|
||||
seq.push(new Note(dur, time, { pitch, octave: parseInt(sp[1]) }));
|
||||
}
|
||||
else {
|
||||
seq.push(new Note(dur, time, parseNote(pitch, seq)));
|
||||
}
|
||||
const full_note = /[1-8]{1}[A-Za-z#]{1,2}([1-8]{1})/;
|
||||
if (full_note.test(note)) {
|
||||
const sp = note.match(full_note);
|
||||
if (sp === null) throw new Error("invalid_input");
|
||||
seq.push(new Note(dur, time, { pitch, octave: parseInt(sp[1]) }));
|
||||
}
|
||||
else {
|
||||
seq.push(new Note(dur, time, parseNote(pitch, seq)));
|
||||
}
|
||||
|
||||
time += dur;
|
||||
});
|
||||
time += dur;
|
||||
});
|
||||
|
||||
// If a note is repeated at the same octave, look at trend of last two notes
|
||||
// for (let i = 2; i < seq.length; i++) {
|
||||
// const note = seq[i];
|
||||
// const comp = seq[i-2];
|
||||
// if (note.pitch === comp.pitch && note.octave === comp.octave) {
|
||||
// const pitch = letter_to_number(note.pitch);
|
||||
// seq[i].octave = trend(pitch, i, seq);
|
||||
// }
|
||||
// }
|
||||
// If a note is repeated at the same octave, look at trend of last two notes
|
||||
// for (let i = 2; i < seq.length; i++) {
|
||||
// const note = seq[i];
|
||||
// const comp = seq[i-2];
|
||||
// if (note.pitch === comp.pitch && note.octave === comp.octave) {
|
||||
// const pitch = letter_to_number(note.pitch);
|
||||
// seq[i].octave = trend(pitch, i, seq);
|
||||
// }
|
||||
// }
|
||||
|
||||
console.log(output(seq));
|
||||
console.log(output(seq));
|
||||
|
||||
return seq;
|
||||
}
|
||||
return seq;
|
||||
};
|
||||
|
||||
/*
|
||||
We have an array of previous notes; for the first to cases the octave is middle (4).
|
||||
|
|
@ -74,63 +74,63 @@ export const parseTune = (input: string): Note[] => {
|
|||
* @note The note's
|
||||
*/
|
||||
const parseNote = (pitch: string, seq: Note[]): {pitch: string, octave: number} => {
|
||||
let octave: number = (() => {
|
||||
// If its the first note its "middle octave"
|
||||
if (seq.length === 0) return 4;
|
||||
let octave: number = (() => {
|
||||
// If its the first note its "middle octave"
|
||||
if (seq.length === 0) return 4;
|
||||
|
||||
const l = seq.length - 1;
|
||||
const { octave } = seq[l];
|
||||
const l = seq.length - 1;
|
||||
const { octave } = seq[l];
|
||||
|
||||
const current = pitchValue(pitch, octave);
|
||||
const previous = pitchValue(seq[l]);
|
||||
const distance = compare(previous, current);
|
||||
const current = pitchValue(pitch, octave);
|
||||
const previous = pitchValue(seq[l]);
|
||||
const distance = compare(previous, current);
|
||||
|
||||
// If its less than 3 pitches of the previous note, use the closest pitch
|
||||
if (distance < 3) {
|
||||
if (distance === 0) return octave;
|
||||
// If its less than 3 pitches of the previous note, use the closest pitch
|
||||
if (distance < 3) {
|
||||
if (distance === 0) return octave;
|
||||
|
||||
if (previous > pitchValue(5, octave)) {
|
||||
if (current < pitchValue(3, octave)) {
|
||||
return octave + 1;
|
||||
}
|
||||
else {
|
||||
return octave;
|
||||
}
|
||||
}
|
||||
else if (previous < pitchValue(3, octave)) {
|
||||
if (current > pitchValue(5, octave)) {
|
||||
return octave - 1;
|
||||
}
|
||||
else {
|
||||
return octave;
|
||||
}
|
||||
}
|
||||
return octave;
|
||||
} else if (l === 0) {
|
||||
if (distance === 3) {
|
||||
if (current > previous) {
|
||||
return octave;
|
||||
}
|
||||
else {
|
||||
return octave + 1;
|
||||
}
|
||||
}
|
||||
else if (current > previous) {
|
||||
return octave;
|
||||
}
|
||||
else if (current < previous) {
|
||||
return octave - 1;
|
||||
}
|
||||
if (previous > pitchValue(5, octave)) {
|
||||
if (current < pitchValue(3, octave)) {
|
||||
return octave + 1;
|
||||
}
|
||||
else {
|
||||
return octave;
|
||||
}
|
||||
}
|
||||
else if (previous < pitchValue(3, octave)) {
|
||||
if (current > pitchValue(5, octave)) {
|
||||
return octave - 1;
|
||||
}
|
||||
else {
|
||||
return octave;
|
||||
}
|
||||
}
|
||||
return octave;
|
||||
} else if (l === 0) {
|
||||
if (distance === 3) {
|
||||
if (current > previous) {
|
||||
return octave;
|
||||
}
|
||||
else {
|
||||
return octave + 1;
|
||||
}
|
||||
}
|
||||
else if (current > previous) {
|
||||
return octave;
|
||||
}
|
||||
else if (current < previous) {
|
||||
return octave - 1;
|
||||
}
|
||||
}
|
||||
|
||||
// If its further away, look at the previous notes for a trend
|
||||
return trend(current, l, seq);
|
||||
})();
|
||||
// If its further away, look at the previous notes for a trend
|
||||
return trend(current, l, seq);
|
||||
})();
|
||||
|
||||
if (octave > 5) octave = 5;
|
||||
if (octave > 5) octave = 5;
|
||||
|
||||
return { pitch, octave };
|
||||
}
|
||||
return { pitch, octave };
|
||||
};
|
||||
|
||||
/*
|
||||
* Is the last note a step down from the note before?
|
||||
|
|
@ -146,106 +146,106 @@ const parseNote = (pitch: string, seq: Note[]): {pitch: string, octave: number}
|
|||
* @param l The index of the array to be compared
|
||||
*/
|
||||
const trend = (current: number, l: number, seq: Note[]): number => {
|
||||
if (l < 1) return seq[l].octave;
|
||||
if (l < 1) return seq[l].octave;
|
||||
|
||||
const prev = pitchValue(seq[l]);
|
||||
const prev2 = pitchValue(seq[l-1]);
|
||||
console.log(prev2, prev, current);
|
||||
const prev = pitchValue(seq[l]);
|
||||
const prev2 = pitchValue(seq[l-1]);
|
||||
console.log(prev2, prev, current);
|
||||
|
||||
// downward trend
|
||||
if (prev2 > prev) {
|
||||
if (prev < current) {
|
||||
return seq[l].octave;
|
||||
}
|
||||
return seq[l].octave - 1;
|
||||
// downward trend
|
||||
if (prev2 > prev) {
|
||||
if (prev < current) {
|
||||
return seq[l].octave;
|
||||
}
|
||||
// upward trend
|
||||
else if (prev2 < prev) {
|
||||
if (prev < current) {
|
||||
return seq[l].octave;
|
||||
}
|
||||
return seq[l].octave + 1;
|
||||
return seq[l].octave - 1;
|
||||
}
|
||||
// upward trend
|
||||
else if (prev2 < prev) {
|
||||
if (prev < current) {
|
||||
return seq[l].octave;
|
||||
}
|
||||
// same notes
|
||||
else {
|
||||
return trend(current, l-1, seq);
|
||||
}
|
||||
}
|
||||
return seq[l].octave + 1;
|
||||
}
|
||||
// same notes
|
||||
else {
|
||||
return trend(current, l-1, seq);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Takes two pitches and returns the distance between them
|
||||
*/
|
||||
const compare = (one: number, two: number): number => {
|
||||
const res = Math.abs(one - two);
|
||||
if (res < 4) {
|
||||
return res;
|
||||
}
|
||||
else if (res > 3.5) {
|
||||
return res - 1;
|
||||
}
|
||||
else if (res > 4.5) {
|
||||
return res - 2;
|
||||
}
|
||||
else if (res > 5.5) {
|
||||
return res - 3;
|
||||
}
|
||||
else if (res > 6.5) {
|
||||
return res - 4;
|
||||
}
|
||||
|
||||
const res = Math.abs(one - two);
|
||||
if (res < 4) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
else if (res > 3.5) {
|
||||
return res - 1;
|
||||
}
|
||||
else if (res > 4.5) {
|
||||
return res - 2;
|
||||
}
|
||||
else if (res > 5.5) {
|
||||
return res - 3;
|
||||
}
|
||||
else if (res > 6.5) {
|
||||
return res - 4;
|
||||
}
|
||||
|
||||
return res;
|
||||
};
|
||||
|
||||
function pitchValue(note: Note): number;
|
||||
function pitchValue(letter: number, octave: number): number;
|
||||
function pitchValue(pitch: string, octave: number): number;
|
||||
function pitchValue(arg1: number | string | Note, arg2?: number): number {
|
||||
let pitch: number;
|
||||
let octave: number;
|
||||
if (arg1 instanceof Note) {
|
||||
pitch = letter_to_number(arg1.pitch);
|
||||
octave = arg1.octave;
|
||||
} else {
|
||||
pitch = (typeof arg1 === 'number') ? arg1 : letter_to_number(arg1);
|
||||
octave = arg2 as number;
|
||||
}
|
||||
return pitch + (octave - 1) * 8;
|
||||
let pitch: number;
|
||||
let octave: number;
|
||||
if (arg1 instanceof Note) {
|
||||
pitch = letter_to_number(arg1.pitch);
|
||||
octave = arg1.octave;
|
||||
} else {
|
||||
pitch = (typeof arg1 === 'number') ? arg1 : letter_to_number(arg1);
|
||||
octave = arg2 as number;
|
||||
}
|
||||
return pitch + (octave - 1) * 8;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a pitch to numerical value for calculations
|
||||
*/
|
||||
const letter_to_number = (pitch: string): number => {
|
||||
let num: number;
|
||||
switch (pitch.charAt(0).toUpperCase()) {
|
||||
case "A":
|
||||
num = 1;
|
||||
break;
|
||||
case "B":
|
||||
num = 2;
|
||||
break;
|
||||
case "C":
|
||||
num = 3;
|
||||
break;
|
||||
case "D":
|
||||
num = 4;
|
||||
break;
|
||||
case "E":
|
||||
num = 5;
|
||||
break;
|
||||
case "F":
|
||||
num = 6;
|
||||
break;
|
||||
case "G":
|
||||
num = 7;
|
||||
break;
|
||||
// In the case of incorrect input, coerce note to a C
|
||||
default:
|
||||
num = 3;
|
||||
}
|
||||
if (pitch.length > 1) {
|
||||
if (pitch.charAt(1).toLowerCase() === "b") num -= .5;
|
||||
else if (pitch.charAt(1) === "#") num += .5;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
let num: number;
|
||||
switch (pitch.charAt(0).toUpperCase()) {
|
||||
case "A":
|
||||
num = 1;
|
||||
break;
|
||||
case "B":
|
||||
num = 2;
|
||||
break;
|
||||
case "C":
|
||||
num = 3;
|
||||
break;
|
||||
case "D":
|
||||
num = 4;
|
||||
break;
|
||||
case "E":
|
||||
num = 5;
|
||||
break;
|
||||
case "F":
|
||||
num = 6;
|
||||
break;
|
||||
case "G":
|
||||
num = 7;
|
||||
break;
|
||||
// In the case of incorrect input, coerce note to a C
|
||||
default:
|
||||
num = 3;
|
||||
}
|
||||
if (pitch.length > 1) {
|
||||
if (pitch.charAt(1).toLowerCase() === "b") num -= .5;
|
||||
else if (pitch.charAt(1) === "#") num += .5;
|
||||
}
|
||||
return num;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -14,19 +14,19 @@ interface note_value {
|
|||
}
|
||||
|
||||
class Note_Value extends Note {
|
||||
constructor(note: Note) {
|
||||
const { duration, time, pitch, octave, velocity } = note;
|
||||
super(duration, time, { pitch, octave }, velocity);
|
||||
}
|
||||
constructor(note: Note) {
|
||||
const { duration, time, pitch, octave, velocity } = note;
|
||||
super(duration, time, { pitch, octave }, velocity);
|
||||
}
|
||||
|
||||
get value(): note_value {
|
||||
return {
|
||||
time: Time(this.time).quantize("4n") / 4,
|
||||
pitch: this.pitch + this.octave.toString(),
|
||||
duration: Time(this.duration).quantize("4n") / 4,
|
||||
velocity: this.velocity,
|
||||
}
|
||||
}
|
||||
get value(): note_value {
|
||||
return {
|
||||
time: Time(this.time).quantize("4n") / 4,
|
||||
pitch: this.pitch + this.octave.toString(),
|
||||
duration: Time(this.duration).quantize("4n") / 4,
|
||||
velocity: this.velocity,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class MugicPlayer {
|
||||
|
|
@ -36,29 +36,29 @@ export class MugicPlayer {
|
|||
|
||||
// Singleton
|
||||
static getInstance() {
|
||||
if (!MugicPlayer.instance) MugicPlayer.instance = new MugicPlayer();
|
||||
return MugicPlayer.instance;
|
||||
if (!MugicPlayer.instance) MugicPlayer.instance = new MugicPlayer();
|
||||
return MugicPlayer.instance;
|
||||
}
|
||||
|
||||
constructor() {
|
||||
const options = {
|
||||
frequency: 440,
|
||||
oscillator: {
|
||||
type: "sine" as any
|
||||
},
|
||||
envelope: {
|
||||
attack: 0.40,
|
||||
decay: 0.10,
|
||||
release: 0.5,
|
||||
sustain: 1,
|
||||
attackCurve: "cosine" as EnvelopeCurve,
|
||||
releaseCurve: "exponential" as EnvelopeCurve,
|
||||
decayCurve: "exponential" as BasicEnvelopeCurve
|
||||
},
|
||||
pitchDecay: 0.05
|
||||
};
|
||||
this.synth = new Synth(options).toDestination();
|
||||
Transport.bpm.value = 140;
|
||||
const options = {
|
||||
frequency: 440,
|
||||
oscillator: {
|
||||
type: "sine" as any
|
||||
},
|
||||
envelope: {
|
||||
attack: 0.40,
|
||||
decay: 0.10,
|
||||
release: 0.5,
|
||||
sustain: 1,
|
||||
attackCurve: "cosine" as EnvelopeCurve,
|
||||
releaseCurve: "exponential" as EnvelopeCurve,
|
||||
decayCurve: "exponential" as BasicEnvelopeCurve
|
||||
},
|
||||
pitchDecay: 0.05
|
||||
};
|
||||
this.synth = new Synth(options).toDestination();
|
||||
Transport.bpm.value = 140;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -69,25 +69,25 @@ export class MugicPlayer {
|
|||
// 2Eb 2F 2D 2G 2Bb 1A 3D
|
||||
// up down up up down up
|
||||
play(input: string) {
|
||||
Transport.stop();
|
||||
if (this.part) this.part.dispose();
|
||||
Transport.stop();
|
||||
if (this.part) this.part.dispose();
|
||||
|
||||
try {
|
||||
const tune = parseTune(input).map(note => new Note_Value(note));
|
||||
this.part = new Part(
|
||||
(time, val) => {
|
||||
this.synth.triggerAttackRelease(val.pitch, val.duration, time, val.velocity);
|
||||
},
|
||||
tune.map((n) => n.value)
|
||||
).start();
|
||||
try {
|
||||
const tune = parseTune(input).map(note => new Note_Value(note));
|
||||
this.part = new Part(
|
||||
(time, val) => {
|
||||
this.synth.triggerAttackRelease(val.pitch, val.duration, time, val.velocity);
|
||||
},
|
||||
tune.map((n) => n.value)
|
||||
).start();
|
||||
|
||||
Transport.start();
|
||||
}
|
||||
catch (error) {
|
||||
console.log(error);
|
||||
// TODO show user the error
|
||||
return;
|
||||
}
|
||||
Transport.start();
|
||||
}
|
||||
catch (error) {
|
||||
console.log(error);
|
||||
// TODO show user the error
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ import { MugicPlayer } from './mugicplayer';
|
|||
const player = MugicPlayer.getInstance();
|
||||
|
||||
export default (props: any) => {
|
||||
const play = debounced(200, () => { player.play(props.notes); });
|
||||
return (
|
||||
<input type="button" value="Play" onClick={() => { play() }} />
|
||||
);
|
||||
const play = debounced(200, () => { player.play(props.notes) });
|
||||
return (
|
||||
<input type="button" value="Play" onClick={() => { play() }} />
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -25,11 +25,14 @@ export default class Category extends React.Component {
|
|||
API.LoadDB([{ 'cards': this.type }, { 'portal': this.type }])
|
||||
.then(() => {
|
||||
this.loaded = true;
|
||||
});
|
||||
})
|
||||
.catch(() => {});
|
||||
return (<Loading />);
|
||||
}
|
||||
|
||||
const create_link = (card, data, i, url) => {
|
||||
const create_link = (card, i, url) => {
|
||||
const data = API.cards[this.type].findOne({ 'gsx$name': card.gsx$name });
|
||||
|
||||
// Prevent site from crashing due to misspelled/missing data
|
||||
if (!data) return (<div key={i}></div>);
|
||||
|
||||
|
|
@ -37,7 +40,7 @@ export default class Category extends React.Component {
|
|||
<Interactive as={Link}
|
||||
to={url || `/portal/${this.props.type}/${card.gsx$name}`}
|
||||
{...s.link}
|
||||
>
|
||||
>
|
||||
<span>{card.gsx$name.split(",")[0]}</span><br />
|
||||
<img className="thumb" src={API.base_image + data.gsx$thumb}></img>
|
||||
</Interactive>
|
||||
|
|
@ -49,7 +52,7 @@ export default class Category extends React.Component {
|
|||
let top_content = (<div />);
|
||||
let bottom_nav = [];
|
||||
|
||||
let path = this.props.location.pathname.split("/");
|
||||
const path = this.props.location.pathname.split("/");
|
||||
if (path[path.length-1] == "") path.pop(); // Remove trailing backslash
|
||||
|
||||
// ** Process the tribe ** //
|
||||
|
|
@ -87,13 +90,12 @@ export default class Category extends React.Component {
|
|||
:
|
||||
API.portal[this.type].chain().simplesort('gsx$name').data()
|
||||
).map((card_portal, i) => {
|
||||
let card_data = API.cards[this.type].findOne({ 'gsx$name': card_portal.gsx$name });
|
||||
let url = ((tribe) ?
|
||||
const url = ((tribe) ?
|
||||
`/portal/${this.props.type}/${card_portal.gsx$tribe}/${encodeURIComponent(card_portal.gsx$name)}`
|
||||
:
|
||||
`/portal/${this.props.type}/${encodeURIComponent(card_portal.gsx$name)}`
|
||||
);
|
||||
return create_link(card_portal, card_data, i, url);
|
||||
return create_link(card_portal, i, url);
|
||||
});
|
||||
}
|
||||
else {
|
||||
|
|
@ -107,8 +109,7 @@ export default class Category extends React.Component {
|
|||
bottom_nav = API.portal[this.type].data
|
||||
.sort((a, b) => (a.gsx$name > b.gsx$name) ? 1 : -1)
|
||||
.map((card_portal, i) => {
|
||||
let card_data = API.cards[this.type].findOne({ 'gsx$name': card_portal.gsx$name });
|
||||
return create_link(card_portal, card_data, i);
|
||||
return create_link(card_portal, i);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,28 +17,28 @@ export default class Home extends React.Component {
|
|||
|
||||
const ctx = canvas.getContext('2d');
|
||||
|
||||
let Logo = new Image();
|
||||
const Logo = new Image();
|
||||
Logo.src = "/src/img/portal.png";
|
||||
|
||||
let Creatures = (() => {
|
||||
let Chaor = new Image();
|
||||
const Creatures = (() => {
|
||||
const Chaor = new Image();
|
||||
Chaor.src = API.base_image + "0B6oyUfwoM3u1LWtvNUZ2NVdjTGc";
|
||||
Chaor.onload = (() => { ctx.drawImage(Chaor, 50, 350); });
|
||||
Chaor.onload = (() => { ctx.drawImage(Chaor, 50, 350) });
|
||||
|
||||
let Iflar = new Image();
|
||||
const Iflar = new Image();
|
||||
Iflar.src = API.base_image + "0B6oyUfwoM3u1bFVIclZscHlHTVE";
|
||||
Iflar.onload = (() => { ctx.drawImage(Iflar, canvas.width - 300, 350); });
|
||||
Iflar.onload = (() => { ctx.drawImage(Iflar, canvas.width - 300, 350) });
|
||||
|
||||
let Illexia = new Image();
|
||||
const Illexia = new Image();
|
||||
Illexia.src = API.base_image + "0B6oyUfwoM3u1YzNhLUdSMHlmdFE";
|
||||
Illexia.onload = (() => { ctx.drawImage(Illexia, canvas.width - 350, Logo.height + 10); });
|
||||
Illexia.onload = (() => { ctx.drawImage(Illexia, canvas.width - 350, Logo.height + 10) });
|
||||
|
||||
let Maxxor = new Image();
|
||||
const Maxxor = new Image();
|
||||
Maxxor.src = API.base_image + "0B6oyUfwoM3u1MVVqQlpqYldsVDQ";
|
||||
Maxxor.onload = (() => { ctx.drawImage(Maxxor, 50, Logo.height + 10); });
|
||||
Maxxor.onload = (() => { ctx.drawImage(Maxxor, 50, Logo.height + 10) });
|
||||
});
|
||||
|
||||
let background = new Image();
|
||||
const background = new Image();
|
||||
// background.src = API.base_image + "0B6oyUfwoM3u1VXZOdV9QUXlCclU"; // lighter
|
||||
background.src = API.base_image + "1iu0GFaJQ0UsSN8yYWi77VY1cXsQpM4o7"; //darker
|
||||
background.onload = (() => {
|
||||
|
|
@ -96,10 +96,10 @@ export default class Home extends React.Component {
|
|||
};
|
||||
|
||||
that.render = function () {
|
||||
let s_width = that.width / w_frames;
|
||||
let s_height = that.height / h_frames;
|
||||
let c_width = canvas.width/2 - s_width/2;
|
||||
let c_height = canvas.height/2 - s_height/2;
|
||||
const s_width = that.width / w_frames;
|
||||
const s_height = that.height / h_frames;
|
||||
const c_width = canvas.width/2 - s_width/2;
|
||||
const c_height = canvas.height/2 - s_height/2;
|
||||
|
||||
// Clear the canvas
|
||||
that.context.clearRect(c_width, c_height, s_width, s_height);
|
||||
|
|
@ -127,7 +127,7 @@ export default class Home extends React.Component {
|
|||
this.coin.update();
|
||||
this.coin.render();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Create sprite sheet
|
||||
const coinImage = new Image();
|
||||
|
|
|
|||
|
|
@ -20,13 +20,13 @@ export default class SearchPortal extends React.Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
return (<div className="search">
|
||||
<form onSubmit={this.search}>
|
||||
<input type="text" value={this.query} autoFocus onChange={(e) => this.query = e.target.value} />
|
||||
<button type="submit"><SearchButton /></button>
|
||||
</form>
|
||||
<DBSearch string={this.input}/>
|
||||
</div>);
|
||||
return (<div className="search">
|
||||
<form onSubmit={this.search}>
|
||||
<input type="text" value={this.query} autoFocus onChange={(e) => this.query = e.target.value} />
|
||||
<button type="submit"><SearchButton /></button>
|
||||
</form>
|
||||
<DBSearch string={this.input}/>
|
||||
</div>);
|
||||
}
|
||||
|
||||
search = (event) => {
|
||||
|
|
@ -55,58 +55,56 @@ class DBSearch extends React.Component {
|
|||
]).then(() => {
|
||||
this.loaded = true;
|
||||
})
|
||||
.catch(() => {})
|
||||
.catch(() => {});
|
||||
return (<span>Loading...</span>);
|
||||
}
|
||||
|
||||
let { string } = this.props;
|
||||
const { string } = this.props;
|
||||
|
||||
// No search
|
||||
if (string == "") {
|
||||
return (<div style={{ minHeight: '50px' }}></div>);
|
||||
}
|
||||
|
||||
const makeLink = (card, i) => {
|
||||
let link = "/portal";
|
||||
switch (card.gsx$type) {
|
||||
case "Attacks":
|
||||
link += '/Attacks/' + encodeURIComponent(card.gsx$name);
|
||||
break;
|
||||
case "Battlegear":
|
||||
link += '/Battlegear/' + encodeURIComponent(card.gsx$name);
|
||||
break;
|
||||
case "Creatures":
|
||||
link += '/Creatures/' + encodeURIComponent(card.gsx$name);
|
||||
break;
|
||||
case "Locations":
|
||||
link += '/Locations/' + encodeURIComponent(card.gsx$name);
|
||||
break;
|
||||
case "Mugic":
|
||||
link += '/Mugic/' + encodeURIComponent(card.gsx$name);
|
||||
break;
|
||||
const text_link = (card, i) => {
|
||||
let url;
|
||||
if (["Attacks", "Battlegear", "Creatures", "Locations", "Mugic"].includes(card.gsx$type)) {
|
||||
url = `/portal/${card.gsx$type}/${card.gsx$name}`;
|
||||
}
|
||||
|
||||
if (!url) return (<span key={i}></span>);
|
||||
|
||||
return (<div key={i}>
|
||||
<Interactive as={Link} {...s.link} to={link}>{card.gsx$name}</Interactive>
|
||||
<Interactive as={Link} {...s.link} to={url}>{card.gsx$name}</Interactive>
|
||||
<br />
|
||||
</div>);
|
||||
};
|
||||
|
||||
const create_link = (card, data, i, url) => {
|
||||
const thumb_link = (card, i) => {
|
||||
let url;
|
||||
let data;
|
||||
if (["Attacks", "Battlegear", "Creatures", "Locations", "Mugic"].includes(card.gsx$type)) {
|
||||
url = `/portal/${card.gsx$type}/${card.gsx$name}`;
|
||||
data = API.cards[card.gsx$type.toLowerCase()].findOne({ 'gsx$name': card.gsx$name });
|
||||
}
|
||||
|
||||
// Prevent site from crashing due to misspelled/missing data
|
||||
if (!data) return (<div key={i}></div>);
|
||||
if (!data || !url) return (<span key={i}></span>);
|
||||
|
||||
const name = card.gsx$name.split(",")[0].replace(/\(Unused\)/, "");
|
||||
|
||||
return (<div key={i} className="nav_item">
|
||||
<Interactive as={Link}
|
||||
to={url || `/portal/${this.props.type}/${card.gsx$name}`}
|
||||
to={url}
|
||||
{...s.link}
|
||||
>
|
||||
<span>{card.gsx$name.split(",")[0]}</span><br />
|
||||
<img className="thumb" src={API.base_image + data.gsx$thumb}></img>
|
||||
>
|
||||
<span>{name}</span><br />
|
||||
<img className="thumb" src={API.base_image + (data.gsx$thumb ? data.gsx$thumb : API.thumb_missing)}></img>
|
||||
</Interactive>
|
||||
</div>);
|
||||
};
|
||||
|
||||
let filter = this.filter.addCollection('filter');
|
||||
const filter = this.filter.addCollection('filter');
|
||||
var pview = filter.addDynamicView('filter');
|
||||
pview.applySimpleSort('gsx$name');
|
||||
|
||||
|
|
@ -170,13 +168,13 @@ class DBSearch extends React.Component {
|
|||
temp.forEach(function(v){ delete v.$loki });
|
||||
filter.insert(temp);
|
||||
|
||||
let content = pview.data().map(makeLink);
|
||||
let content = pview.data().map(text_link);
|
||||
this.filter.removeCollection('filter');
|
||||
|
||||
let header;
|
||||
|
||||
// This prioritizes names in the results
|
||||
let names = [].concat(
|
||||
const names = [].concat(
|
||||
API.portal.attacks.find({ 'gsx$name': { '$regex': new RegExp(string, 'i') }}),
|
||||
API.portal.battlegear.find({ 'gsx$name': { '$regex': new RegExp(string, 'i') }}),
|
||||
API.portal.creatures.find({ 'gsx$name': { '$regex': new RegExp(string, 'i') }}),
|
||||
|
|
@ -199,15 +197,16 @@ class DBSearch extends React.Component {
|
|||
.find({ 'gsx$name': { '$regex': new RegExp(string, 'i') }})
|
||||
.where((obj) => {return (obj.gsx$splash != ('') )}).data()
|
||||
).sort((a, b) => {
|
||||
a = a.gsx$name.toLowerCase();
|
||||
b = b.gsx$name.toLowerCase();
|
||||
if (a < b) return -1;
|
||||
else if (a > b) return 1;
|
||||
else return 0;
|
||||
}).map(makeLink);
|
||||
a = a.gsx$name.toLowerCase();
|
||||
b = b.gsx$name.toLowerCase();
|
||||
if (a < b) return -1;
|
||||
else if (a > b) return 1;
|
||||
else return 0;
|
||||
}).map(thumb_link);
|
||||
|
||||
// Check Artists
|
||||
if (content.length == 0) {
|
||||
let artists = [].concat(
|
||||
const artists = [].concat(
|
||||
API.cards.attacks.chain()
|
||||
.find({ 'gsx$artist': { '$regex': new RegExp(string, 'i') }})
|
||||
.where((obj) => {return (obj.gsx$splash != ('') )}).data(),
|
||||
|
|
@ -229,7 +228,7 @@ class DBSearch extends React.Component {
|
|||
if (a < b) return -1;
|
||||
else if (a > b) return 1;
|
||||
else return 0;
|
||||
}).map(makeLink);
|
||||
}).map(text_link);
|
||||
|
||||
if (artists.length > 0) {
|
||||
header = `Art contributed by ${string}:`;
|
||||
|
|
@ -247,7 +246,7 @@ class DBSearch extends React.Component {
|
|||
<hr />
|
||||
{names.length > 0 && <>
|
||||
<div>Entries</div>
|
||||
{names}
|
||||
<div className="entry_nav">{names}</div>
|
||||
<hr />
|
||||
</>}
|
||||
<div>{header}</div>
|
||||
|
|
|
|||
|
|
@ -10,15 +10,15 @@ export default class SingleAttack extends React.Component {
|
|||
|
||||
render() {
|
||||
|
||||
let path = this.props.location.pathname.split("/");
|
||||
const path = this.props.location.pathname.split("/");
|
||||
if (path[path.length-1] == "") path.pop(); // Remove trailing backslash
|
||||
|
||||
// Path too long
|
||||
if ( path.length !== 4 ) {
|
||||
return(<PageNotFound location={this.props.location}/>);
|
||||
return (<PageNotFound location={this.props.location}/>);
|
||||
}
|
||||
|
||||
let name = decodeURIComponent(path[3]);
|
||||
const name = decodeURIComponent(path[3]);
|
||||
|
||||
const attack = API.portal.attacks.findOne({ 'gsx$name': name });
|
||||
const card_data = API.cards.attacks.findOne({ 'gsx$name': name });
|
||||
|
|
@ -42,7 +42,7 @@ export default class SingleAttack extends React.Component {
|
|||
{attack.gsx$details}
|
||||
</div>
|
||||
</>}
|
||||
/>
|
||||
/>
|
||||
);
|
||||
}
|
||||
else if (card_data) {
|
||||
|
|
@ -51,6 +51,6 @@ export default class SingleAttack extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
return(<PageNotFound location={this.props.location}/>);
|
||||
return (<PageNotFound location={this.props.location}/>);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,19 +10,19 @@ export default class SingleBattlegear extends React.Component {
|
|||
|
||||
render() {
|
||||
|
||||
let path = this.props.location.pathname.split("/");
|
||||
const path = this.props.location.pathname.split("/");
|
||||
if (path[path.length-1] == "") path.pop(); // Remove trailing backslash
|
||||
|
||||
// Path too long
|
||||
if ( path.length !== 4 ) {
|
||||
return(<PageNotFound location={this.props.location}/>);
|
||||
return (<PageNotFound location={this.props.location}/>);
|
||||
}
|
||||
|
||||
let name = decodeURIComponent(path[3]);
|
||||
const name = decodeURIComponent(path[3]);
|
||||
|
||||
const battlegear = API.portal.battlegear.findOne({ 'gsx$name': name });
|
||||
const card_data = API.cards.battlegear.findOne({ 'gsx$name': name });
|
||||
|
||||
|
||||
if (battlegear) {
|
||||
return (<Single
|
||||
card={card_data}
|
||||
|
|
@ -50,6 +50,6 @@ export default class SingleBattlegear extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
return(<PageNotFound location={this.props.location}/>);
|
||||
return (<PageNotFound location={this.props.location}/>);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@ import Single from './_base';
|
|||
import { PageNotFound, Element, Mugic, Discipline, Ability, Tribe } from '../../Snippets';
|
||||
|
||||
function Artist(props) {
|
||||
let artists = [];
|
||||
const artists = [];
|
||||
props.artist.split(/(?=, )/).forEach((artist, i) => {
|
||||
artists.push(<Link key={i} to={`/portal/Search/?${artist.replace(", ", "")}`}>{artist}</Link>);
|
||||
});
|
||||
return (<div className="ability">{artists}</div>)
|
||||
return (<div className="ability">{artists}</div>);
|
||||
}
|
||||
|
||||
@inject((stores, props, context) => props) @observer
|
||||
|
|
@ -24,7 +24,7 @@ export default class SingleCreature extends React.Component {
|
|||
// The first / gets counted
|
||||
render() {
|
||||
|
||||
let path = this.props.location.pathname.split("/");
|
||||
const path = this.props.location.pathname.split("/");
|
||||
if (path[path.length-1] == "") path.pop(); // Remove trailing backslash
|
||||
|
||||
const name = (() => {
|
||||
|
|
@ -35,7 +35,7 @@ export default class SingleCreature extends React.Component {
|
|||
const creature = API.portal.creatures.findOne({ 'gsx$name': name });
|
||||
|
||||
if (!creature) {
|
||||
return(<PageNotFound location={this.props.location}/>);
|
||||
return (<PageNotFound location={this.props.location}/>);
|
||||
}
|
||||
|
||||
const tribe = creature.gsx$tribe;
|
||||
|
|
@ -50,12 +50,12 @@ export default class SingleCreature extends React.Component {
|
|||
return <p key={i}><Interactive as={Link} {...s.link} to={"/portal/Battlegear/"+item}><span>{item}</span></Interactive></p>;
|
||||
});
|
||||
|
||||
let mugic = [];
|
||||
const mugic = [];
|
||||
for (let i = 0; i < card_data.gsx$mugicability; i++) {
|
||||
mugic.push(<Mugic key={i} tribe={tribe} />);
|
||||
}
|
||||
|
||||
// TODO readd creature to Portal Search after rewrite
|
||||
// TODO readd creature to Portal Search after rewrite
|
||||
|
||||
return (<Single
|
||||
card={card_data}
|
||||
|
|
|
|||
|
|
@ -9,15 +9,15 @@ export default class SingleLocation extends React.Component {
|
|||
|
||||
render() {
|
||||
|
||||
let path = this.props.location.pathname.split("/");
|
||||
const path = this.props.location.pathname.split("/");
|
||||
if (path[path.length-1] == "") path.pop(); // Remove trailing backslash
|
||||
|
||||
// Path too long
|
||||
if ( path.length !== 4 ) {
|
||||
return(<PageNotFound location={this.props.location}/>);
|
||||
return (<PageNotFound location={this.props.location}/>);
|
||||
}
|
||||
|
||||
let name = decodeURIComponent(path[3]);
|
||||
const name = decodeURIComponent(path[3]);
|
||||
|
||||
const location = API.portal.locations.findOne({ 'gsx$name': name });
|
||||
const card_data = API.cards.locations.findOne({ 'gsx$name': name });
|
||||
|
|
@ -63,6 +63,6 @@ export default class SingleLocation extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
return(<PageNotFound location={this.props.location}/>);
|
||||
return (<PageNotFound location={this.props.location}/>);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ export default class SingleMugic extends React.Component {
|
|||
// The first / gets counted
|
||||
render() {
|
||||
|
||||
let path = this.props.location.pathname.split("/");
|
||||
const path = this.props.location.pathname.split("/");
|
||||
if (path[path.length-1] == "") path.pop(); // Remove trailing backslash
|
||||
|
||||
const name = (() => {
|
||||
|
|
@ -26,7 +26,7 @@ export default class SingleMugic extends React.Component {
|
|||
const card_data = API.cards.mugic.findOne({ 'gsx$name': name });
|
||||
|
||||
const cost = () => {
|
||||
let cost = [];
|
||||
const cost = [];
|
||||
if (card_data.gsx$cost == 0) {
|
||||
cost.push(<span key={0}>0</span>);
|
||||
}
|
||||
|
|
@ -39,7 +39,7 @@ export default class SingleMugic extends React.Component {
|
|||
}
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
};
|
||||
|
||||
if (mugic) {
|
||||
return (<Single
|
||||
|
|
@ -87,6 +87,6 @@ export default class SingleMugic extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
return(<PageNotFound location={this.props.location}/>);
|
||||
return (<PageNotFound location={this.props.location}/>);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,21 +8,21 @@ import s from '../../../styles/app.style';
|
|||
|
||||
// own "name" display function
|
||||
function Name(props) {
|
||||
let name = props.name.split(",");
|
||||
return (<>
|
||||
<span>{name[0]}</span>
|
||||
{ name.length > 1 &&
|
||||
<span className="bigger"><br />{name[1].trim()}</span>
|
||||
}
|
||||
</>);
|
||||
const name = props.name.split(",");
|
||||
return (<>
|
||||
<span>{name[0]}</span>
|
||||
{ name.length > 1 &&
|
||||
<span className="bigger"><br />{name[1].trim()}</span>
|
||||
}
|
||||
</>);
|
||||
}
|
||||
|
||||
function Artist(props) {
|
||||
let artists = [];
|
||||
props.artist.split(/(?=, )/).forEach((artist, i) => {
|
||||
artists.push(<Link key={i} to={`/portal/Search/?${artist.replace(", ", "")}`}>{artist}</Link>);
|
||||
});
|
||||
return (<div className="artist">{artists}</div>)
|
||||
const artists = [];
|
||||
props.artist.split(/(?=, )/).forEach((artist, i) => {
|
||||
artists.push(<Link key={i} to={`/portal/Search/?${artist.replace(", ", "")}`}>{artist}</Link>);
|
||||
});
|
||||
return (<div className="artist">{artists}</div>);
|
||||
}
|
||||
|
||||
@inject((stores, props, context) => props) @observer
|
||||
|
|
@ -30,91 +30,96 @@ export default class Single extends React.Component {
|
|||
@observable fullscreen = false;
|
||||
|
||||
expand(e) {
|
||||
this.fullscreen = true;
|
||||
this.fullscreen = true;
|
||||
}
|
||||
|
||||
close(e) {
|
||||
this.fullscreen = false;
|
||||
this.fullscreen = false;
|
||||
}
|
||||
|
||||
render() {
|
||||
let { card } = this.props;
|
||||
return (<>
|
||||
<div className={"modal" + (this.fullscreen?"":" hidden")}>
|
||||
<span className="close" onClick={this.close.bind(this)}>×</span>
|
||||
<img className="modal-content" src={API.base_image + card.gsx$splash} />
|
||||
const { card } = this.props;
|
||||
|
||||
return (<>
|
||||
<div className={"modal" + (this.fullscreen?"":" hidden")}>
|
||||
<span className="close" onClick={this.close.bind(this)}>×</span>
|
||||
<img className="modal-content" src={API.base_image + card.gsx$splash} />
|
||||
</div>
|
||||
{card.gsx$splash && (
|
||||
<div className="entry_splash">
|
||||
{/*<span className="arrow">⇩</span>*/}
|
||||
<img onClick={this.expand.bind(this)} src={API.base_image + card.gsx$splash} />
|
||||
</div>
|
||||
{card.gsx$splash && (
|
||||
<div className="entry_splash">
|
||||
{/*<span className="arrow">⇩</span>*/}
|
||||
<img onClick={this.expand.bind(this)} src={API.base_image + card.gsx$splash} />
|
||||
</div>
|
||||
)}
|
||||
<div className="entry_body">
|
||||
<div className="title">
|
||||
<Name name={card.gsx$name} />
|
||||
<hr />
|
||||
</div>
|
||||
{this.props.text &&
|
||||
<div className="nocolumn">{this.props.text}</div>
|
||||
}
|
||||
{!this.props.text &&
|
||||
<div className="column">
|
||||
{card.gsx$artist && <>
|
||||
<div>
|
||||
<strong>Artist(s):</strong>
|
||||
<Artist artist={card.gsx$artist} />
|
||||
</div>
|
||||
<hr />
|
||||
</>}
|
||||
{card.gsx$set && <>
|
||||
<div>
|
||||
<strong>Set: </strong>
|
||||
{`${API.sets[card.gsx$set]} (${card.gsx$set})`}
|
||||
</div>
|
||||
<hr />
|
||||
</>
|
||||
}
|
||||
)}
|
||||
<div className="entry_body">
|
||||
<div className="title">
|
||||
<Name name={card.gsx$name} />
|
||||
<hr />
|
||||
</div>
|
||||
{this.props.text &&
|
||||
<div className="nocolumn">{this.props.text}</div>
|
||||
}
|
||||
{!this.props.text &&
|
||||
<div className="column">
|
||||
{card.gsx$artist && <>
|
||||
<div>
|
||||
<strong>Artist(s):</strong>
|
||||
<Artist artist={card.gsx$artist} />
|
||||
</div>
|
||||
<hr />
|
||||
</>}
|
||||
{card.gsx$set && <>
|
||||
<div>
|
||||
<strong>Set: </strong>
|
||||
{`${API.sets[card.gsx$set]} (${card.gsx$set})`}
|
||||
</div>
|
||||
<hr />
|
||||
</>
|
||||
}
|
||||
{card.gsx$rarity && <>
|
||||
<div>
|
||||
<strong>Rarity: </strong>
|
||||
<Rarity set={card.gsx$set} rarity={card.gsx$rarity} notext="true" />
|
||||
{card.gsx$rarity}
|
||||
</div>
|
||||
<hr />
|
||||
</>}
|
||||
{card.gsx$id && <>
|
||||
<div>
|
||||
<strong>Card ID: </strong>
|
||||
{card.gsx$id}
|
||||
</div>
|
||||
{this.props.col0 && <>
|
||||
<hr />
|
||||
{this.props.col0}
|
||||
</>}
|
||||
{card.gsx$ability && <>
|
||||
<hr />
|
||||
<div>
|
||||
<strong>Ability:</strong>
|
||||
<Ability ability={card.gsx$ability} />
|
||||
</div>
|
||||
</>}
|
||||
{card.gsx$flavortext && <>
|
||||
<hr />
|
||||
<div>
|
||||
<strong>Card Flavor:</strong><br />
|
||||
{card.gsx$flavortext}
|
||||
</div>
|
||||
</>}
|
||||
{this.props.col1 && <>
|
||||
<hr />
|
||||
this.props.col1
|
||||
</>}
|
||||
</div>
|
||||
}
|
||||
{!this.props.text &&
|
||||
<div className="column">
|
||||
{this.props.col2}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</>);
|
||||
</>}
|
||||
{this.props.col0 && <>
|
||||
<hr />
|
||||
{this.props.col0}
|
||||
</>}
|
||||
{card.gsx$ability && <>
|
||||
<hr />
|
||||
<div>
|
||||
<strong>Ability:</strong>
|
||||
<Ability ability={card.gsx$ability} />
|
||||
</div>
|
||||
</>}
|
||||
{card.gsx$flavortext && <>
|
||||
<hr />
|
||||
<div>
|
||||
<strong>Card Flavor:</strong><br />
|
||||
{card.gsx$flavortext}
|
||||
</div>
|
||||
</>}
|
||||
{this.props.col1 && <>
|
||||
<hr />
|
||||
this.props.col1
|
||||
</>}
|
||||
</div>
|
||||
}
|
||||
{!this.props.text &&
|
||||
<div className="column">
|
||||
{this.props.col2}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</>);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,12 +33,12 @@ export default class Tribes extends React.Component {
|
|||
return (<Loading />);
|
||||
}
|
||||
|
||||
let path = this.props.location.pathname.split("/");
|
||||
const path = this.props.location.pathname.split("/");
|
||||
if (path[path.length-1] == "") path.pop(); // Remove trailing backslash
|
||||
|
||||
let tribe = path[2];
|
||||
const tribe = path[2];
|
||||
|
||||
let filter = this.filter.addCollection('filter');
|
||||
const filter = this.filter.addCollection('filter');
|
||||
var pview = filter.addDynamicView('filter');
|
||||
pview.applySimpleSort('gsx$name');
|
||||
|
||||
|
|
@ -52,7 +52,7 @@ export default class Tribes extends React.Component {
|
|||
temp.forEach((v) => { delete v.$loki });
|
||||
filter.insert(temp);
|
||||
|
||||
let results = pview.data();
|
||||
const results = pview.data();
|
||||
this.filter.removeCollection('filter');
|
||||
|
||||
const bottom_nav = results.map((card, i) => {
|
||||
|
|
|
|||
|
|
@ -71,13 +71,44 @@
|
|||
width: 18px;
|
||||
}
|
||||
|
||||
.search .results div {
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
.search {
|
||||
.results {
|
||||
&> div {
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
a {
|
||||
font-size: 16px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.search .results a {
|
||||
font-size: 16px;
|
||||
line-height: 20px;
|
||||
.entry_nav {
|
||||
background-color: inherit;
|
||||
overflow-y: auto;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
align-content: space-between;
|
||||
position: relative;
|
||||
|
||||
.nav_item {
|
||||
margin: 3px;
|
||||
max-width: 106px;
|
||||
white-space: initial;
|
||||
overflow-wrap: break-word;
|
||||
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
flex-direction: column;
|
||||
|
||||
.thumb {
|
||||
height: 100px;
|
||||
width: 96px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.entry {
|
||||
|
|
@ -235,14 +266,13 @@
|
|||
}
|
||||
|
||||
&.base_path {
|
||||
.entry_nav, .cat_title {
|
||||
background-color: inherit;
|
||||
}
|
||||
.cat_title {
|
||||
background-color: inherit;
|
||||
padding-top: 1em;
|
||||
padding-bottom: 1em;
|
||||
}
|
||||
.entry_nav {
|
||||
background-color: inherit;
|
||||
overflow-y: auto;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ module.exports = {
|
|||
port: 8000,
|
||||
publicPath: '/build/',
|
||||
contentBase: __dirname,
|
||||
watchContentBase: true,
|
||||
historyApiFallback: {
|
||||
index: 'index.html',
|
||||
},
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user