Add quick actions and mass resources to level upgrade
This commit is contained in:
parent
9d37697b13
commit
ed66b0a308
51
src/Action/UpgradeResourceToLevel.ts
Normal file
51
src/Action/UpgradeResourceToLevel.ts
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import { ActionController, registerAction } from './ActionController';
|
||||||
|
import { Args } from '../Common';
|
||||||
|
import { ActionError, GrabError, TryLaterError } from '../Errors';
|
||||||
|
import { Task } from '../Storage/TaskQueue';
|
||||||
|
import { clickUpgradeButton } from '../Page/BuildingPage';
|
||||||
|
import { grabResourceDeposits } from '../Page/SlotBlock';
|
||||||
|
import { UpgradeBuildingTask } from '../Task/UpgradeBuildingTask';
|
||||||
|
|
||||||
|
@registerAction
|
||||||
|
export class UpgradeResourceToLevel extends ActionController {
|
||||||
|
async run(args: Args, task: Task): Promise<any> {
|
||||||
|
const deposits = grabResourceDeposits();
|
||||||
|
if (deposits.length === 0) {
|
||||||
|
throw new ActionError(task.id, 'No deposits');
|
||||||
|
}
|
||||||
|
|
||||||
|
const villageId = args.villageId;
|
||||||
|
const requiredLevel = args.level;
|
||||||
|
const tasks = this.scheduler.getTaskItems();
|
||||||
|
|
||||||
|
const allUpgraded = deposits.reduce((memo, dep) => memo && dep.level >= requiredLevel, true);
|
||||||
|
|
||||||
|
if (allUpgraded) {
|
||||||
|
this.scheduler.completeTask(task.id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const available = deposits
|
||||||
|
.sort((x, y) => x.level - y.level)
|
||||||
|
.filter(dep => dep.ready)
|
||||||
|
.filter(
|
||||||
|
dep =>
|
||||||
|
tasks.find(
|
||||||
|
t =>
|
||||||
|
t.name === UpgradeBuildingTask.name &&
|
||||||
|
t.args.villageId === villageId &&
|
||||||
|
t.args.buildId === dep.buildId
|
||||||
|
) === undefined
|
||||||
|
);
|
||||||
|
|
||||||
|
if (available.length === 0) {
|
||||||
|
throw new TryLaterError(task.id, 10 * 60, 'No available deposits');
|
||||||
|
}
|
||||||
|
|
||||||
|
const targetDep = available[0];
|
||||||
|
|
||||||
|
this.scheduler.scheduleTask(UpgradeBuildingTask.name, { villageId, buildId: targetDep.buildId });
|
||||||
|
|
||||||
|
throw new TryLaterError(task.id, 20 * 60, 'Sleep for next round');
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,6 @@
|
|||||||
export interface Args {
|
export interface Args {
|
||||||
|
villageId?: number;
|
||||||
|
buildId?: number;
|
||||||
[name: string]: any;
|
[name: string]: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
<div id="dashboard-inner">
|
<div id="dashboard-inner">
|
||||||
<hdr></hdr>
|
<hdr></hdr>
|
||||||
<task-list></task-list>
|
<task-list></task-list>
|
||||||
|
<hr class="separator" />
|
||||||
|
<quick-actions></quick-actions>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
</template>
|
</template>
|
||||||
@ -10,10 +12,12 @@
|
|||||||
<script>
|
<script>
|
||||||
import Header from './Header';
|
import Header from './Header';
|
||||||
import TaskList from './TaskList';
|
import TaskList from './TaskList';
|
||||||
|
import QuickActions from './QuickActions';
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
hdr: Header,
|
hdr: Header,
|
||||||
'task-list': TaskList,
|
'task-list': TaskList,
|
||||||
|
'quick-actions': QuickActions,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {};
|
return {};
|
||||||
@ -38,5 +42,9 @@ export default {
|
|||||||
#dashboard-inner {
|
#dashboard-inner {
|
||||||
background-color: white;
|
background-color: white;
|
||||||
margin: 4px;
|
margin: 4px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
.separator {
|
||||||
|
margin: 10px auto;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
34
src/Dashboard/Components/QuickActions.vue
Normal file
34
src/Dashboard/Components/QuickActions.vue
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<template>
|
||||||
|
<ul class="actions">
|
||||||
|
<li v-for="action in actions">
|
||||||
|
<a href="#" v-on:click.prevent="onAction(action.cb)">{{ action.label }}</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
shared: this.$root.$data,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
actions() {
|
||||||
|
return this.shared.quickActions;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onAction(cb) {
|
||||||
|
cb();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.actions {
|
||||||
|
margin: 10px auto;
|
||||||
|
padding-inline-start: 20px;
|
||||||
|
}
|
||||||
|
</style>
|
@ -3,9 +3,12 @@
|
|||||||
<p class="summary">Task count: {{ shared.taskList.length }}</p>
|
<p class="summary">Task count: {{ shared.taskList.length }}</p>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<table class="task-table">
|
<table class="task-table">
|
||||||
<tr class="task-item" v-for="task in shared.taskList">
|
<tr v-for="task in shared.taskList" class="task-item" :class="{ 'this-village': isThisVillageTask(task) }">
|
||||||
<td :title="formatDate(task.ts)">{{ formatDate(task.ts) }}</td>
|
<td :title="formatDate(task.ts)">{{ formatDate(task.ts) }}</td>
|
||||||
<td :title="task.id">{{ task.id }}</td>
|
<td :title="task.id">{{ task.id }}</td>
|
||||||
|
<td>
|
||||||
|
<a href="#" title="Remove task" class="remove-action" v-on:click.prevent="onRemove(task.id)">×</a>
|
||||||
|
</td>
|
||||||
<td :title="task.name">{{ task.name }}</td>
|
<td :title="task.name">{{ task.name }}</td>
|
||||||
<td :title="JSON.stringify(task.args)">{{ JSON.stringify(task.args) }}</td>
|
<td :title="JSON.stringify(task.args)">{{ JSON.stringify(task.args) }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -23,11 +26,21 @@ export default {
|
|||||||
shared: this.$root.$data,
|
shared: this.$root.$data,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
computed: {},
|
||||||
methods: {
|
methods: {
|
||||||
formatDate(ts) {
|
formatDate(ts) {
|
||||||
const d = new Date(ts * 1000);
|
const d = new Date(ts * 1000);
|
||||||
return dateFormat(d, 'HH:MM:ss');
|
return dateFormat(d, 'HH:MM:ss');
|
||||||
},
|
},
|
||||||
|
isThisVillageTask(task) {
|
||||||
|
const taskVillageId = (task.args || {}).villageId;
|
||||||
|
const currentVillageId = (this.shared.village || {}).id;
|
||||||
|
return taskVillageId !== undefined && taskVillageId === currentVillageId;
|
||||||
|
},
|
||||||
|
onRemove(taskId) {
|
||||||
|
console.log('ON REMOVE TASK', taskId);
|
||||||
|
this.shared.removeTask(taskId);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
@ -54,4 +67,11 @@ export default {
|
|||||||
padding: 2px 4px;
|
padding: 2px 4px;
|
||||||
max-width: 25%;
|
max-width: 25%;
|
||||||
}
|
}
|
||||||
|
.this-village {
|
||||||
|
color: blue;
|
||||||
|
}
|
||||||
|
.remove-action {
|
||||||
|
font-weight: bold;
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,14 +1,18 @@
|
|||||||
import * as URLParse from 'url-parse';
|
import * as URLParse from 'url-parse';
|
||||||
import { markPage, uniqId, waitForLoad } from '../utils';
|
import { uniqId, waitForLoad } from '../utils';
|
||||||
import { Scheduler } from '../Scheduler';
|
import { Scheduler } from '../Scheduler';
|
||||||
import { TaskQueueRenderer } from '../TaskQueueRenderer';
|
|
||||||
import { BuildPage } from '../Page/BuildPage';
|
import { BuildPage } from '../Page/BuildPage';
|
||||||
import { UpgradeBuildingTask } from '../Task/UpgradeBuildingTask';
|
import { UpgradeBuildingTask } from '../Task/UpgradeBuildingTask';
|
||||||
import { grabResources } from '../Page/ResourcesBlock';
|
import { grabActiveVillage, grabActiveVillageId } from '../Page/VillageBlock';
|
||||||
import { grabActiveVillage, grabActiveVillageId, grabVillageList } from '../Page/VillageBlock';
|
import {
|
||||||
import { onResourceSlotCtrlClick, showBuildingSlotIds, showResourceSlotIds } from '../Page/SlotBlock';
|
grabResourceDeposits,
|
||||||
|
onResourceSlotCtrlClick,
|
||||||
|
showBuildingSlotIds,
|
||||||
|
showResourceSlotIds,
|
||||||
|
} from '../Page/SlotBlock';
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import DashboardApp from './Components/DashboardApp.vue';
|
import DashboardApp from './Components/DashboardApp.vue';
|
||||||
|
import { ResourcesToLevel } from '../Task/ResourcesToLevel';
|
||||||
|
|
||||||
export class Dashboard {
|
export class Dashboard {
|
||||||
private readonly version: string;
|
private readonly version: string;
|
||||||
@ -25,45 +29,54 @@ export class Dashboard {
|
|||||||
const p = new URLParse(window.location.href, true);
|
const p = new URLParse(window.location.href, true);
|
||||||
this.log('PARSED LOCATION', p);
|
this.log('PARSED LOCATION', p);
|
||||||
|
|
||||||
const res = grabResources();
|
|
||||||
this.log('RES', res);
|
|
||||||
|
|
||||||
const villages = grabVillageList();
|
|
||||||
this.log('VILL', villages);
|
|
||||||
|
|
||||||
const villageId = grabActiveVillageId();
|
const villageId = grabActiveVillageId();
|
||||||
|
|
||||||
|
const scheduler = this.scheduler;
|
||||||
|
const quickActions: any[] = [];
|
||||||
|
|
||||||
const state = {
|
const state = {
|
||||||
name: 'Dashboard',
|
name: 'Dashboard',
|
||||||
village: grabActiveVillage(),
|
village: grabActiveVillage(),
|
||||||
version: this.version,
|
version: this.version,
|
||||||
taskList: this.scheduler.getTaskItems(),
|
taskList: this.scheduler.getTaskItems(),
|
||||||
|
quickActions: quickActions,
|
||||||
|
|
||||||
|
refreshTasks() {
|
||||||
|
this.taskList = scheduler.getTaskItems();
|
||||||
|
},
|
||||||
|
|
||||||
|
removeTask(taskId: string) {
|
||||||
|
scheduler.removeTask(taskId);
|
||||||
|
this.taskList = scheduler.getTaskItems();
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const appId = `app-${uniqId()}`;
|
setInterval(() => state.refreshTasks(), 1000);
|
||||||
jQuery('body').prepend(`<div id="${appId}"></div>`);
|
|
||||||
new Vue({
|
|
||||||
el: `#${appId}`,
|
|
||||||
data: state,
|
|
||||||
render: h => h(DashboardApp),
|
|
||||||
});
|
|
||||||
|
|
||||||
// markPage('Dashboard', this.version);
|
const deposits = grabResourceDeposits();
|
||||||
// this.renderTaskQueue();
|
if (deposits.length) {
|
||||||
// setInterval(() => this.renderTaskQueue(), 5000);
|
const sorted = deposits.sort((x, y) => x.level - y.level);
|
||||||
|
const minLevel = sorted[0].level;
|
||||||
|
for (let i = minLevel + 1; i < minLevel + 4; ++i) {
|
||||||
|
quickActions.push({
|
||||||
|
label: `Ресурсы до уровня ${i}`,
|
||||||
|
cb: () => {
|
||||||
|
scheduler.scheduleTask(ResourcesToLevel.name, { villageId, level: i });
|
||||||
|
state.refreshTasks();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const tasks = this.scheduler.getTaskItems();
|
const tasks = this.scheduler.getTaskItems();
|
||||||
const buildingsInQueue = tasks
|
const buildingsInQueue = tasks
|
||||||
.filter(t => t.name === UpgradeBuildingTask.name && t.args.villageId === villageId)
|
.filter(t => t.name === UpgradeBuildingTask.name && t.args.villageId === villageId)
|
||||||
.map(t => t.args.buildId);
|
.map(t => t.args.buildId || 0);
|
||||||
|
|
||||||
if (p.pathname === '/dorf1.php') {
|
if (p.pathname === '/dorf1.php') {
|
||||||
showResourceSlotIds(buildingsInQueue);
|
showResourceSlotIds(buildingsInQueue);
|
||||||
onResourceSlotCtrlClick(buildId => {
|
onResourceSlotCtrlClick(buildId => this.onResourceSlotCtrlClick(villageId, buildId, state));
|
||||||
this.scheduler.scheduleTask(UpgradeBuildingTask.name, { villageId, buildId });
|
console.log(grabResourceDeposits());
|
||||||
const n = new Notification(`Building ${buildId} scheduled`);
|
|
||||||
setTimeout(() => n && n.close(), 4000);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p.pathname === '/dorf2.php') {
|
if (p.pathname === '/dorf2.php') {
|
||||||
@ -73,11 +86,25 @@ export class Dashboard {
|
|||||||
if (p.pathname === '/build.php') {
|
if (p.pathname === '/build.php') {
|
||||||
new BuildPage(this.scheduler, Number(p.query.id)).run();
|
new BuildPage(this.scheduler, Number(p.query.id)).run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.createControlPanel(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
private renderTaskQueue() {
|
private createControlPanel(state) {
|
||||||
this.log('RENDER TASK QUEUE');
|
const appId = `app-${uniqId()}`;
|
||||||
new TaskQueueRenderer().render(this.scheduler.getTaskItems());
|
jQuery('body').prepend(`<div id="${appId}"></div>`);
|
||||||
|
new Vue({
|
||||||
|
el: `#${appId}`,
|
||||||
|
data: state,
|
||||||
|
render: h => h(DashboardApp),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private onResourceSlotCtrlClick(villageId: number, buildId: number, state) {
|
||||||
|
this.scheduler.scheduleTask(UpgradeBuildingTask.name, { villageId, buildId });
|
||||||
|
state.refreshTasks();
|
||||||
|
const n = new Notification(`Building ${buildId} scheduled`);
|
||||||
|
setTimeout(() => n && n.close(), 4000);
|
||||||
}
|
}
|
||||||
|
|
||||||
private log(...args) {
|
private log(...args) {
|
||||||
|
22
src/Game.ts
22
src/Game.ts
@ -12,6 +12,15 @@ export const ResourceMapping: ReadonlyArray<{ num: number; type: ResourceType }>
|
|||||||
{ num: 4, type: ResourceType.Crop },
|
{ num: 4, type: ResourceType.Crop },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export function numberToResourceType(typeAsNumber: number): ResourceType {
|
||||||
|
for (let mp of ResourceMapping) {
|
||||||
|
if (typeAsNumber === mp.num) {
|
||||||
|
return mp.type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Error(`Type ${typeAsNumber} in not valid`);
|
||||||
|
}
|
||||||
|
|
||||||
export type ResourceList = Array<{ num: number; type: ResourceType; value: number }>;
|
export type ResourceList = Array<{ num: number; type: ResourceType; value: number }>;
|
||||||
|
|
||||||
export class Resources {
|
export class Resources {
|
||||||
@ -80,3 +89,16 @@ export type HeroAllResourcesType = 'all';
|
|||||||
export const HeroAllResources: HeroAllResourcesType = 'all';
|
export const HeroAllResources: HeroAllResourcesType = 'all';
|
||||||
|
|
||||||
export type HeroResourceType = ResourceType | HeroAllResourcesType;
|
export type HeroResourceType = ResourceType | HeroAllResourcesType;
|
||||||
|
|
||||||
|
export class ResourceDeposit {
|
||||||
|
readonly buildId: number;
|
||||||
|
readonly type: ResourceType;
|
||||||
|
readonly level: number;
|
||||||
|
readonly ready: boolean;
|
||||||
|
constructor(buildId: number, type: ResourceType, level: number, ready: boolean) {
|
||||||
|
this.buildId = buildId;
|
||||||
|
this.type = type;
|
||||||
|
this.level = level;
|
||||||
|
this.ready = ready;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -59,7 +59,7 @@ export class BuildPage {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private onTrainTroopClick(buildId: Number, troopId: Number, el: HTMLElement) {
|
private onTrainTroopClick(buildId: number, troopId: number, el: HTMLElement) {
|
||||||
console.log('TRAIN TROOPERS', 'TROOP ID', troopId, 'BUILDING ID', buildId);
|
console.log('TRAIN TROOPERS', 'TROOP ID', troopId, 'BUILDING ID', buildId);
|
||||||
const villageId = grabActiveVillageId();
|
const villageId = grabActiveVillageId();
|
||||||
const input = jQuery(el).find(`input[name="t${troopId}"]`);
|
const input = jQuery(el).find(`input[name="t${troopId}"]`);
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { elClassId, getNumber } from '../utils';
|
import { elClassId, getNumber } from '../utils';
|
||||||
|
import { numberToResourceType, ResourceDeposit } from '../Game';
|
||||||
|
|
||||||
interface Slot {
|
interface Slot {
|
||||||
el: HTMLElement;
|
el: HTMLElement;
|
||||||
@ -14,7 +15,7 @@ function slotElements(prefix: string): Array<Slot> {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function showSlotIds(prefix: string, buildingIds: number[]): void {
|
function showSlotIds(prefix: string, buildingIds: Array<number>): void {
|
||||||
const slots = slotElements(prefix);
|
const slots = slotElements(prefix);
|
||||||
slots.forEach(slot => {
|
slots.forEach(slot => {
|
||||||
const oldLabel = jQuery(slot.el)
|
const oldLabel = jQuery(slot.el)
|
||||||
@ -54,3 +55,17 @@ export function onResourceSlotCtrlClick(cb: (buildId: number) => void): void {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function slotToDepositMapper(slot: Slot): ResourceDeposit {
|
||||||
|
const el = slot.el;
|
||||||
|
const classes = jQuery(el).attr('class') || '';
|
||||||
|
const buildId = getNumber(elClassId(classes, 'buildingSlot'));
|
||||||
|
const level = getNumber(elClassId(classes, 'level'));
|
||||||
|
const type = getNumber(elClassId(classes, 'gid'));
|
||||||
|
const ready = !jQuery(el).hasClass('notNow');
|
||||||
|
return new ResourceDeposit(buildId, numberToResourceType(type), level, ready);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function grabResourceDeposits(): Array<ResourceDeposit> {
|
||||||
|
return slotElements('buildingSlot').map(slotToDepositMapper);
|
||||||
|
}
|
||||||
|
@ -145,6 +145,7 @@ export class Scheduler {
|
|||||||
|
|
||||||
completeTask(id: TaskId) {
|
completeTask(id: TaskId) {
|
||||||
this.taskQueue.complete(id);
|
this.taskQueue.complete(id);
|
||||||
|
this.actionQueue.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
scheduleTask(name: string, args: Args): void {
|
scheduleTask(name: string, args: Args): void {
|
||||||
@ -152,6 +153,11 @@ export class Scheduler {
|
|||||||
this.taskQueue.push(name, args, timestamp());
|
this.taskQueue.push(name, args, timestamp());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
removeTask(id: TaskId) {
|
||||||
|
this.taskQueue.remove(id);
|
||||||
|
this.actionQueue.clear();
|
||||||
|
}
|
||||||
|
|
||||||
scheduleActions(actions: Array<Command>): void {
|
scheduleActions(actions: Array<Command>): void {
|
||||||
this.actionQueue.assign(actions);
|
this.actionQueue.assign(actions);
|
||||||
}
|
}
|
||||||
|
@ -76,6 +76,11 @@ export class TaskQueue {
|
|||||||
this.flushItems(items);
|
this.flushItems(items);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
remove(id: TaskId) {
|
||||||
|
const [_, items] = this.shiftTask(id);
|
||||||
|
this.flushItems(items);
|
||||||
|
}
|
||||||
|
|
||||||
seeItems(): TaskList {
|
seeItems(): TaskList {
|
||||||
return this.getItems();
|
return this.getItems();
|
||||||
}
|
}
|
||||||
|
22
src/Task/ResourcesToLevel.ts
Normal file
22
src/Task/ResourcesToLevel.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import { Args, Command } from '../Common';
|
||||||
|
import { Task } from '../Storage/TaskQueue';
|
||||||
|
import { TaskController, registerTask } from './TaskController';
|
||||||
|
import { GoToPageAction } from '../Action/GoToPageAction';
|
||||||
|
import { CompleteTaskAction } from '../Action/CompleteTaskAction';
|
||||||
|
import { path } from '../utils';
|
||||||
|
import { UpgradeResourceToLevel } from '../Action/UpgradeResourceToLevel';
|
||||||
|
|
||||||
|
@registerTask
|
||||||
|
export class ResourcesToLevel extends TaskController {
|
||||||
|
async run(task: Task) {
|
||||||
|
const args: Args = { ...task.args, taskId: task.id };
|
||||||
|
this.scheduler.scheduleActions([
|
||||||
|
new Command(GoToPageAction.name, {
|
||||||
|
...args,
|
||||||
|
path: path('/dorf1.php', { newdid: args.villageId }),
|
||||||
|
}),
|
||||||
|
new Command(UpgradeResourceToLevel.name, args),
|
||||||
|
new Command(CompleteTaskAction.name, args),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
@ -85,10 +85,12 @@ export function getNumber(value: any, def: number = 0): number {
|
|||||||
return converted === undefined ? def : converted;
|
return converted === undefined ? def : converted;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function path(p: string, query: { [key: string]: string | number } = {}) {
|
export function path(p: string, query: { [key: string]: string | number | undefined } = {}) {
|
||||||
let parts: string[] = [];
|
let parts: string[] = [];
|
||||||
for (let k in query) {
|
for (let k in query) {
|
||||||
parts.push(`${k}=${query[k]}`);
|
if (query[k] !== undefined) {
|
||||||
|
parts.push(`${k}=${query[k]}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return p + (parts.length ? '?' + parts.join('&') : '');
|
return p + (parts.length ? '?' + parts.join('&') : '');
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
"outDir": "./dist",
|
"outDir": "./dist",
|
||||||
"strictNullChecks": true,
|
"strictNullChecks": true,
|
||||||
"strictPropertyInitialization": true,
|
"strictPropertyInitialization": true,
|
||||||
"target": "es2015",
|
"target": "es2018",
|
||||||
"types": ["node", "url-parse", "jquery", "mocha", "chai"]
|
"types": ["node", "url-parse", "jquery", "mocha", "chai"]
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
|
Loading…
Reference in New Issue
Block a user