Lokalne zapisywanie rozkazów

This commit is contained in:
2022-07-22 00:17:39 +02:00
parent 459c23df17
commit 667987bdb6
13 changed files with 450 additions and 77 deletions
+3 -3
View File
@@ -33,11 +33,11 @@ export default defineComponent({
computed: {
chosenOrderComponent() {
switch (this.store.chosenOrderType) {
case 'OrderN':
case 'orderN':
return OrderNVue;
case 'OrderS':
case 'orderS':
return OrderSVue;
case 'OrderO':
case 'orderO':
return OrderOVue;
default:
return OrderNVue;
+118
View File
@@ -0,0 +1,118 @@
<template>
<section class="order-list">
<h3>Zapisane rozkazy pisemne ({{ localOrderCount }})</h3>
<ul>
<li v-for="order in sortedOrderList" @click="selectLocalOrder(order)">
<b>
{{ getOrderName(order.orderType) }} nr {{ order.orderBody['header']['orderNo'] }} dla pociągu nr
{{ order.orderBody['header']['trainNo'] }}
</b>
<br />
Dodano: {{ new Date(order.createdAt).toLocaleString('pl-PL') }}
</li>
</ul>
</section>
</template>
<script lang="ts">
import { defineComponent, reactive } from 'vue';
import { useStore } from '../store/store';
import { LocalStorageOrder } from '../types/orderTypes';
export default defineComponent({
name: 'OrderList',
data() {
return {
localOrderCount: 0,
localOrderList: [] as LocalStorageOrder[],
};
},
setup() {
return {
store: useStore(),
};
},
methods: {
getOrderName(orderType: string) {
return `Rozkaz "${orderType.split('order')[1]}"`;
},
selectLocalOrder(order: LocalStorageOrder) {
this.store.chosenOrderType = order.orderType;
const orderBody = JSON.parse(JSON.stringify(order.orderBody));
switch (order.orderType) {
case 'orderN':
// for (let key in this.store[order.orderType]) {
// (this.store[order.orderType] as any)[key] = orderBody[key];
// }
// this.store['orderN']['header'] = orderBody['header'];
// this.store['orderN']['row1'] = orderBody['row1'];
// this.store['orderN']['header'] = orderBody['header'];
// this.store['orderN']['header'] = orderBody['header'];
// this.store['orderN']['header'] = orderBody['header'];
break;
default:
break;
}
this.store[order.orderType] = reactive(JSON.parse(JSON.stringify(order.orderBody)));
},
},
computed: {
sortedOrderList() {
return this.localOrderList.sort((a, b) => a.createdAt - b.createdAt);
},
},
activated() {
const localStorage = window.localStorage;
const orderList = [];
this.localOrderCount = Number(localStorage.getItem('orderCount')) || 0;
for (let key in localStorage) {
if (!/^order-/g.test(key)) continue;
const orderObj: LocalStorageOrder = JSON.parse(localStorage[key]);
if (!orderObj) continue;
orderList.push(orderObj);
}
this.localOrderList = orderList;
},
});
</script>
<style lang="scss" scoped>
.order-list {
padding: 1em;
width: 500px;
}
ul {
overflow: auto;
height: 60vh;
}
h3 {
margin: 0;
margin-bottom: 1em;
text-align: center;
}
li {
text-align: left;
padding: 1em;
margin: 0.5em;
background-color: #222;
cursor: pointer;
}
</style>
+174
View File
@@ -0,0 +1,174 @@
<template>
<section class="order-message">
<h3>Wiadomość do wyświetlenia na czacie symulatora:</h3>
<div class="message_body" v-html="fullOrderMessage"></div>
<div class="message_actions">
<button class="g-button" @click="saveOrder"><img :src="saveIcon" alt="save icon" />Zapisz ten rozkaz</button>
<button class="g-button" @click="copyMessage">Kopiuj wiadomość rozkazu</button>
</div>
<transition name="monit-anim">
<div class="action_monit" v-if="actionMonit" v-html="actionMonit"></div>
</transition>
</section>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { useStore } from '../store/store';
import saveIcon from '../assets/icon-save.svg';
import orderStorageMixin from '../mixins/orderStorageMixin';
export default defineComponent({
name: 'OrderMessage',
mixins: [orderStorageMixin],
data() {
return {
saveIcon,
actionMonit: '',
monitTimeout: undefined as number | undefined,
};
},
setup() {
return {
store: useStore(),
};
},
computed: {
fullOrderMessage() {
return this.store.orderMessage + this.store.footerMessage;
},
},
methods: {
showActionMonit(text: string) {
if (this.monitTimeout) {
this.actionMonit = '';
clearTimeout(this.monitTimeout);
setTimeout(() => {
this.actionMonit = text;
this.monitTimeout = setTimeout(() => {
this.actionMonit = '';
}, 5000);
}, 300);
return;
}
this.actionMonit = text;
this.monitTimeout = setTimeout(() => {
this.actionMonit = '';
}, 5000);
},
copyMessage() {
if (!navigator.clipboard)
return this.showActionMonit(
'Ups! Twoja przeglądarka musi być dosyć przestarzała, ponieważ nie obsługuje zapisu do schowka! :/'
);
navigator.clipboard.writeText(this.fullOrderMessage);
this.showActionMonit(
'Skopiowano do <b class="text--accent">schowka</b>! Możesz teraz wkleić treść rozkazu na czacie symulatora!'
);
},
saveOrder() {
const savedOrderStatus = this.saveOrderToStorage();
switch (savedOrderStatus) {
case -1:
this.showActionMonit('<span class="text--warn">Wypełnij numer rozkazu, numer pociągu i datę zanim dodasz rozkaz!</span>');
break;
case 0:
this.showActionMonit('<span class="text--warn">Ostatni zapisany rozkaz jest identyczny z obecnym!</span>');
break;
case 1:
this.showActionMonit('Zapisano treść <b class="text--accent">rozkazu</b> w pamięci przeglądarki!');
break;
default:
break;
}
},
},
});
</script>
<style lang="scss" scoped>
.order-message {
padding: 1em;
width: 500px;
h3 {
margin: 0;
margin-bottom: 1em;
text-align: center;
}
button {
margin: 0 0.5em;
}
@media screen and (max-width: 550px) {
max-width: 100%;
}
}
.message_body {
height: 250px;
overflow: auto;
text-align: justify;
background-color: #fff;
border-radius: 0.5em;
color: black;
padding: 0.5em;
user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
}
.message_actions {
display: flex;
align-items: center;
justify-content: center;
margin-top: 1em;
button img {
height: 2ch;
vertical-align: text-bottom;
margin-right: 0.5em;
}
}
.action_monit {
text-align: center;
padding: 1.5em;
font-size: 1.15em;
}
.monit-anim {
&-enter-active,
&-leave-active {
transition: all 100ms ease-in-out;
}
&-enter-from,
&-leave-to {
opacity: 0;
transform: translateY(-20px);
}
}
</style>
+1 -1
View File
@@ -312,7 +312,7 @@ export default defineComponent({
return {
store,
order: store.orderN,
order,
rowMethods,
};
},
+1 -1
View File
@@ -96,7 +96,7 @@ export default defineComponent({
return {
store,
order: store.orderO,
order,
rowMethods,
};
},
+1 -1
View File
@@ -215,7 +215,7 @@ export default defineComponent({
return {
store,
order: store.orderS,
order,
rowMethods,
};
},
+33 -7
View File
@@ -11,6 +11,11 @@
<div class="bar"></div>
</button>
<button class="option-save" @click="toggleOrderMode" :data-selected="store.orderMode == 'OrderList'">
<img :src="saveIcon" alt="save icon" />
<div class="bar"></div>
</button>
</div>
</section>
</template>
@@ -19,20 +24,24 @@
import { defineComponent } from 'vue';
import { useStore } from '../store/store';
import saveIcon from '../assets/icon-save.svg';
export default defineComponent({
data() {
return {
saveIcon,
orderTypeList: [
{
id: 'OrderN',
id: 'orderN',
name: 'N',
},
{
id: 'OrderS',
id: 'orderS',
name: 'S',
},
{
id: 'OrderO',
id: 'orderO',
name: 'O',
},
],
@@ -45,9 +54,13 @@ export default defineComponent({
},
methods: {
selectOrderType(type: string) {
selectOrderType(type: any) {
this.store.chosenOrderType = type;
},
toggleOrderMode() {
this.store.orderMode = this.store.orderMode == 'OrderMessage' ? 'OrderList' : 'OrderMessage';
},
},
});
</script>
@@ -67,7 +80,7 @@ export default defineComponent({
.sidebar_content {
display: grid;
grid-template-rows: repeat(3, 1fr);
grid-template-rows: repeat(4, 1fr);
gap: 0.25em;
font-size: 1.5em;
@@ -111,6 +124,19 @@ export default defineComponent({
}
}
button.option-save {
background-color: $accentCol;
img {
width: 80%;
height: 80%;
}
&[data-selected='true'] .bar {
background-color: #111;
}
}
@media screen and (max-width: 650px) {
.sidebar {
left: 50%;
@@ -121,10 +147,10 @@ export default defineComponent({
.sidebar_content {
grid-template-rows: 1fr;
grid-template-columns: repeat(3, 1fr);
grid-template-columns: repeat(4, 1fr);
& > button {
height: 50px;
height: 60px;
width: 60px;
.bar {