Extract scheduler to separate component

This commit is contained in:
2020-04-18 11:07:44 +03:00
parent c285338705
commit 631151ab0b
10 changed files with 200 additions and 158 deletions

View File

@ -0,0 +1,55 @@
<template>
<main id="dashboard">
<div id="dashboard-inner">
<hdr></hdr>
<village-state-list></village-state-list>
<hr class="separator" />
<quick-actions></quick-actions>
<hr class="separator" />
<task-list></task-list>
</div>
</main>
</template>
<script>
import Header from './Header';
import TaskList from './TaskList';
import QuickActions from './QuickActions';
import VillageStateList from './VillageStateList';
export default {
components: {
hdr: Header,
'task-list': TaskList,
'quick-actions': QuickActions,
'village-state-list': VillageStateList,
},
data() {
return {
shared: this.$root.$data,
};
},
};
</script>
<style scoped>
#dashboard {
position: absolute;
display: block;
left: 0;
top: 0;
height: 100%;
width: 500px;
z-index: 9999;
/*overflow: hidden;*/
}
#dashboard * {
box-sizing: border-box;
}
#dashboard-inner {
background-color: white;
padding: 5px;
}
.separator {
margin: 10px auto;
}
</style>

View File

@ -0,0 +1,35 @@
<template>
<section>
<h1 class="title">
[{{ shared.name }}] {{ villageName }}
<span class="version">- {{ shared.version }}</span>
</h1>
</section>
</template>
<script>
export default {
data() {
return {
shared: this.$root.$data,
};
},
computed: {
villageName() {
let village = this.shared.activeVillage;
return village ? village.name : 'Unknown';
},
},
};
</script>
<style scoped>
.title {
font-size: 160%;
padding-top: 8px;
margin-bottom: 8px;
}
.version {
font-size: 14px;
}
</style>

View 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>

View File

@ -0,0 +1,79 @@
<template>
<section class="task-list">
<p class="summary">Task count: {{ shared.taskList.length }}</p>
<div class="container">
<table class="task-table">
<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="task.id">{{ task.id }}</td>
<td>
<a href="#" title="Remove task" class="remove-action" v-on:click.prevent="onRemove(task.id)">&times;</a>
</td>
<td :title="task.name">{{ task.name }}</td>
<td :title="JSON.stringify(task.args)">{{ JSON.stringify(task.args) }}</td>
</tr>
</table>
</div>
</section>
</template>
<script>
import * as dateFormat from 'dateformat';
export default {
data() {
return {
shared: this.$root.$data,
activeVillage: this.$root.$data.activeVillage,
};
},
methods: {
formatDate(ts) {
const d = new Date(ts * 1000);
return dateFormat(d, 'HH:MM:ss');
},
isThisVillageTask(task) {
const taskVillageId = (task.args || {}).villageId;
const currentVillageId = this.activeVillage.id;
return taskVillageId !== undefined && taskVillageId === currentVillageId;
},
onRemove(taskId) {
console.log('ON REMOVE TASK', taskId);
this.shared.removeTask(taskId);
},
},
};
</script>
<style scoped>
.task-list {
margin-top: 8px;
margin-bottom: 8px;
}
.summary {
margin-top: 10px;
margin-bottom: 0;
}
.container {
overflow-y: scroll;
overflow-x: hidden;
max-height: 300px;
}
.task-table {
width: 100%;
border-collapse: collapse;
margin: 6px auto 0;
}
.task-item > td {
border-top: 1px solid #ddd;
padding: 2px 4px;
max-width: 25%;
}
.this-village {
color: blue;
}
.remove-action {
font-weight: bold;
color: red;
}
</style>

View File

@ -0,0 +1,152 @@
<template>
<section>
<table class="village-table">
<thead>
<tr>
<th></th>
<th class="right">Дерево</th>
<th class="right">Глина</th>
<th class="right">Железо</th>
<th class="right">Зерно</th>
<th class="right">Склад</th>
<th class="right">Амбар</th>
</tr>
</thead>
<tbody>
<template v-for="village in shared.villages">
<tr class="normal-line top-line">
<td :class="{ active: village.active }" :title="village.id">{{ village.name }}</td>
<td
class="right"
v-text="village.lumber"
:title="resourceTitle(village.lumber, village.warehouse, village.lumber_hour)"
></td>
<td
class="right"
v-text="village.clay"
:title="resourceTitle(village.clay, village.warehouse, village.clay_hour)"
></td>
<td
class="right"
v-text="village.iron"
:title="resourceTitle(village.iron, village.warehouse, village.iron_hour)"
></td>
<td
class="right"
v-text="village.crop"
:title="resourceTitle(village.crop, village.granary, village.crop_hour)"
></td>
<td class="right">
<a :href="warehousePath(village)" v-text="village.warehouse"></a>
</td>
<td class="right" v-text="village.granary"></td>
</tr>
<tr class="performance-line">
<td></td>
<td class="right small">+{{ village.lumber_hour }}</td>
<td class="right small">+{{ village.clay_hour }}</td>
<td class="right small">+{{ village.iron_hour }}</td>
<td class="right small">+{{ village.crop_hour }}</td>
<td></td>
<td></td>
</tr>
<tr class="normal-line">
<td></td>
<td class="right" colspan="6">
<a
class="village-quick-link"
v-for="v in shared.villages"
v-if="v.id !== village.id"
:href="marketPath(village, v)"
:title="'Отправить ресурсы из ' + village.name + ' в ' + v.name"
>->{{ v.name }}</a
>
<a class="village-quick-link" :href="quartersPath(village)">Казармы</a>
</td>
</tr>
</template>
</tbody>
</table>
</section>
</template>
<script>
import { path } from '../utils';
export default {
data() {
return {
shared: this.$root.$data,
activeVillage: this.$root.$data.activeVillage,
};
},
methods: {
path(name, args) {
return path(name, args);
},
marketPath(fromVillage, toVillage) {
return path('/build.php', { newdid: fromVillage.id, gid: 17, t: 5, x: toVillage.crd.x, y: toVillage.crd.y });
},
warehousePath(village) {
return path('/build.php', { newdid: village.id, gid: 10 });
},
quartersPath(village) {
return path('/build.php', { newdid: village.id, gid: 19 });
},
resourceTitle(current, max, speed) {
const percent = Math.floor((current / max) * 100);
if (speed < 0) {
const time = this.fractionalHourToTime(current / speed);
return `${current}, ${percent}%, опустеет через ${time}`;
} else {
const time = this.fractionalHourToTime((max - current) / speed);
return `${current}, ${percent}%, заполнится через ${time}`;
}
},
fractionalHourToTime(value) {
const hours = Math.floor(value);
const minutes = Math.round((value - hours) * 60);
return `${hours}:${String(minutes).padStart(2, '0')}`;
},
},
};
</script>
<style scoped>
.village-table {
width: 100%;
border-collapse: collapse;
}
.normal-line td {
padding: 4px;
}
.performance-line td {
padding: 0 4px 4px;
}
.village-table td.active {
font-weight: bold;
}
.top-line td {
border-top: 1px solid #ddd;
}
.right {
text-align: right;
}
.small {
font-size: 90%;
}
.village-quick-link {
display: inline-block;
}
.village-quick-link + .village-quick-link {
margin-left: 0.4em;
}
</style>