more POE tweaks, validate dates
parent
8ec273219c
commit
07b44ba69e
|
@ -84,6 +84,9 @@
|
||||||
border: none;
|
border: none;
|
||||||
background: none;
|
background: none;
|
||||||
padding: 0.1em 0.5em;
|
padding: 0.1em 0.5em;
|
||||||
|
&:invalid {
|
||||||
|
background: mix($c-error, $c-bg-box, 30%);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ export class ExplorerConfigCtrl {
|
||||||
rating: storedJsonProp('explorer.rating', () => allRatings),
|
rating: storedJsonProp('explorer.rating', () => allRatings),
|
||||||
speed: storedJsonProp<ExplorerSpeed[]>('explorer.speed', () => allSpeeds),
|
speed: storedJsonProp<ExplorerSpeed[]>('explorer.speed', () => allSpeeds),
|
||||||
mode: storedJsonProp<ExplorerMode[]>('explorer.mode', () => allModes),
|
mode: storedJsonProp<ExplorerMode[]>('explorer.mode', () => allModes),
|
||||||
since: storedProp('explorer.since', ''),
|
since: storedProp('explorer.since', '2010-01'),
|
||||||
until: storedProp('explorer.until', ''),
|
until: storedProp('explorer.until', ''),
|
||||||
playerName: {
|
playerName: {
|
||||||
open: prop(false),
|
open: prop(false),
|
||||||
|
@ -176,9 +176,13 @@ const monthInput = (prop: StoredProp<Month>) =>
|
||||||
type: 'month',
|
type: 'month',
|
||||||
pattern: '^20[12][0-9]-(0[1-9]|1[012])$',
|
pattern: '^20[12][0-9]-(0[1-9]|1[012])$',
|
||||||
min: '2010-01',
|
min: '2010-01',
|
||||||
|
max: '2030-01',
|
||||||
value: prop() || '',
|
value: prop() || '',
|
||||||
},
|
},
|
||||||
hook: bind('change', e => prop((e.target as HTMLInputElement).value)),
|
hook: bind('change', e => {
|
||||||
|
const input = e.target as HTMLInputElement;
|
||||||
|
if (input.checkValidity()) prop(input.value);
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
const monthSection = (ctrl: ExplorerConfigCtrl) =>
|
const monthSection = (ctrl: ExplorerConfigCtrl) =>
|
||||||
|
|
|
@ -113,7 +113,7 @@ export default class ExplorerCtrl {
|
||||||
processData
|
processData
|
||||||
)
|
)
|
||||||
.then(stream => {
|
.then(stream => {
|
||||||
stream.end.promise.then(this.root.redraw);
|
stream.end.promise.then(err => (err ? onError(err) : this.root.redraw()));
|
||||||
return stream;
|
return stream;
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
|
@ -454,15 +454,13 @@ export default function (ctrl: AnalyseCtrl): VNode | undefined {
|
||||||
[
|
[
|
||||||
h('div.overlay'),
|
h('div.overlay'),
|
||||||
content,
|
content,
|
||||||
!content || explorer.failing()
|
h('button.fbt.toconf', {
|
||||||
? null
|
attrs: {
|
||||||
: h('button.fbt.toconf', {
|
'aria-label': configOpened ? 'Close configuration' : 'Open configuration',
|
||||||
attrs: {
|
...dataIcon(configOpened ? '' : ''),
|
||||||
'aria-label': configOpened ? 'Close configuration' : 'Open configuration',
|
},
|
||||||
...dataIcon(configOpened ? '' : ''),
|
hook: bind('click', () => ctrl.explorer.config.toggleOpen(), ctrl.redraw),
|
||||||
},
|
}),
|
||||||
hook: bind('click', () => ctrl.explorer.config.toggleOpen(), ctrl.redraw),
|
|
||||||
}),
|
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import { ExplorerData, ExplorerDb, ExplorerMode, ExplorerSpeed, OpeningData, TablebaseData } from './interfaces';
|
import { ExplorerData, ExplorerDb, OpeningData, TablebaseData } from './interfaces';
|
||||||
import * as xhr from 'common/xhr';
|
import * as xhr from 'common/xhr';
|
||||||
import { readNdJson, CancellableStream } from 'common/ndjson';
|
import { readNdJson, CancellableStream } from 'common/ndjson';
|
||||||
import { ExplorerConfigData } from './explorerConfig';
|
import { ExplorerConfigData } from './explorerConfig';
|
||||||
|
import { sync } from 'common/sync';
|
||||||
|
|
||||||
interface OpeningXhrOpts {
|
interface OpeningXhrOpts {
|
||||||
endpoint: string;
|
endpoint: string;
|
||||||
|
@ -16,7 +17,10 @@ interface OpeningXhrOpts {
|
||||||
withGames?: boolean;
|
withGames?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function opening(opts: OpeningXhrOpts, processData: (data: ExplorerData) => void): Promise<CancellableStream> {
|
export async function opening(
|
||||||
|
opts: OpeningXhrOpts,
|
||||||
|
processData: (data: ExplorerData) => void
|
||||||
|
): Promise<CancellableStream> {
|
||||||
const conf = opts.config;
|
const conf = opts.config;
|
||||||
const endpoint = opts.db == 'player' ? opts.endpoint3 : opts.endpoint;
|
const endpoint = opts.db == 'player' ? opts.endpoint3 : opts.endpoint;
|
||||||
const url = new URL(opts.db === 'lichess' ? '/lichess' : opts.db == 'player' ? '/personal' : '/master', endpoint);
|
const url = new URL(opts.db === 'lichess' ? '/lichess' : opts.db == 'player' ? '/personal' : '/master', endpoint);
|
||||||
|
@ -34,25 +38,32 @@ export function opening(opts: OpeningXhrOpts, processData: (data: ExplorerData)
|
||||||
params.set('update', 'true');
|
params.set('update', 'true');
|
||||||
params.set('speeds', conf.speed().join(','));
|
params.set('speeds', conf.speed().join(','));
|
||||||
params.set('modes', conf.mode().join(','));
|
params.set('modes', conf.mode().join(','));
|
||||||
if (conf.since()) params.set('since', conf.since().replace('-', '/'));
|
if (conf.since()) params.set('since', conf.since());
|
||||||
if (conf.until()) params.set('until', conf.until().replace('-', '/'));
|
if (conf.until()) params.set('until', conf.until());
|
||||||
}
|
}
|
||||||
if (!opts.withGames) {
|
if (!opts.withGames) {
|
||||||
params.set('topGames', '0');
|
params.set('topGames', '0');
|
||||||
params.set('recentGames', '0');
|
params.set('recentGames', '0');
|
||||||
}
|
}
|
||||||
const stream = fetch(url.href, {
|
const res = await fetch(url.href, {
|
||||||
cache: 'default',
|
cache: 'default',
|
||||||
headers: {}, // avoid default headers for cors
|
headers: {}, // avoid default headers for cors
|
||||||
credentials: 'omit',
|
credentials: 'omit',
|
||||||
});
|
});
|
||||||
|
|
||||||
const onMessage = (line: any) => {
|
const onMessage = (line: any) => {
|
||||||
const data = line as Partial<OpeningData>;
|
const data = line as Partial<OpeningData>;
|
||||||
data.isOpening = true;
|
data.isOpening = true;
|
||||||
data.fen = opts.fen;
|
data.fen = opts.fen;
|
||||||
processData(data as OpeningData);
|
processData(data as OpeningData);
|
||||||
};
|
};
|
||||||
return stream.then(readNdJson(onMessage));
|
|
||||||
|
if (res.ok) return readNdJson(onMessage)(res);
|
||||||
|
|
||||||
|
return {
|
||||||
|
cancel() {},
|
||||||
|
end: sync(Promise.resolve(new Error(`Explorer error: ${res.status}`))),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function tablebase(endpoint: string, variant: VariantKey, fen: Fen): Promise<TablebaseData> {
|
export async function tablebase(endpoint: string, variant: VariantKey, fen: Fen): Promise<TablebaseData> {
|
||||||
|
|
|
@ -4,7 +4,7 @@ export type ProcessLine = (line: any) => void;
|
||||||
|
|
||||||
export interface CancellableStream {
|
export interface CancellableStream {
|
||||||
cancel(): void;
|
cancel(): void;
|
||||||
end: Sync<boolean>;
|
end: Sync<Error | undefined>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -21,11 +21,11 @@ export const readNdJson =
|
||||||
const decoder = new TextDecoder();
|
const decoder = new TextDecoder();
|
||||||
let buf = '';
|
let buf = '';
|
||||||
|
|
||||||
const loop = (): Promise<boolean> =>
|
const loop = (): Promise<Error | undefined> =>
|
||||||
stream.read().then(({ done, value }) => {
|
stream.read().then(({ done, value }) => {
|
||||||
if (done) {
|
if (done) {
|
||||||
if (buf.length > 0) processLine(JSON.parse(buf));
|
if (buf.length > 0) processLine(JSON.parse(buf));
|
||||||
return Promise.resolve(true);
|
return Promise.resolve(undefined);
|
||||||
} else {
|
} else {
|
||||||
const chunk = decoder.decode(value, { stream: true });
|
const chunk = decoder.decode(value, { stream: true });
|
||||||
buf += chunk;
|
buf += chunk;
|
||||||
|
|
Loading…
Reference in New Issue