mirror of
https://github.com/Spythere/genera-tor.git
synced 2026-05-04 22:18:13 +00:00
Compare commits
43 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3713289339 | |||
| cafdbb9653 | |||
| 7934a83cfd | |||
| 33f59db5f3 | |||
| 201c49845f | |||
| a1d0c47910 | |||
| fb82ac9fb2 | |||
| 76a31c345d | |||
| 4181119bd2 | |||
| 53029d37a5 | |||
| f5747db62d | |||
| 35bc44b969 | |||
| 1085170004 | |||
| d762d42344 | |||
| 31c241b3b7 | |||
| e4a5c7babb | |||
| b4c673ea51 | |||
| e53cf6faba | |||
| 3a3ba61454 | |||
| 6dcc96a677 | |||
| 897091468c | |||
| 0160a27bf4 | |||
| 802da68576 | |||
| 78e82df63d | |||
| b5a4ba9c0a | |||
| b93a65007e | |||
| 70d29284a5 | |||
| 5fb235c9a7 | |||
| 40c7e47632 | |||
| eac9b47e10 | |||
| 6af0e9b822 | |||
| 6306a07562 | |||
| a0a5e72701 | |||
| 7784e08f03 | |||
| 98fda8e849 | |||
| 81f484793f | |||
| 5a2be7b25e | |||
| 73c397a1bc | |||
| f54eada94d | |||
| fa4504fec7 | |||
| 9118c186cf | |||
| 14f730f8ca | |||
| 7afef587cc |
@@ -1,5 +1,5 @@
|
||||
VITE_APP_API_URL=https://stacjownik.spythere.eu/api
|
||||
VITE_APP_SWDR_URL=https://api.td2.info.pl
|
||||
|
||||
VITE_APP_ORDER_VERSION=2
|
||||
VITE_APP_ORDER_VERSION=3 # 3 - NEW 2025 ORDER INSTRUCTIONS
|
||||
#VITE_UPDATE_TEST='test'
|
||||
@@ -5,7 +5,7 @@ name: Deploy to Firebase Hosting on merge
|
||||
'on':
|
||||
push:
|
||||
branches:
|
||||
- main-old
|
||||
- main
|
||||
jobs:
|
||||
build_and_deploy:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
name: Build & Deploy to VPS
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
env:
|
||||
PROJECT_NAME: generator-td2
|
||||
|
||||
jobs:
|
||||
build_and_deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Build the app
|
||||
run: yarn && yarn build
|
||||
- name: Setup SSH key for connection with the server
|
||||
run: |
|
||||
mkdir -p ~/.ssh
|
||||
echo "${{ secrets.VPS_SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa && chmod 600 ~/.ssh/id_rsa
|
||||
- name: Send new files
|
||||
run: rsync -avP -e "ssh -o StrictHostKeyChecking=no -i ~/.ssh/id_rsa -p 2022" ./dist/ ${{ secrets.VPS_USER }}@${{ secrets.VPS_HOST }}:/var/www/$PROJECT_NAME --delete
|
||||
@@ -25,3 +25,6 @@ pnpm-debug.log*
|
||||
|
||||
# Firebase
|
||||
.firebase
|
||||
|
||||
#Yarn lock files
|
||||
yarn.lock
|
||||
+1
-33
@@ -54,41 +54,9 @@
|
||||
crossorigin
|
||||
/>
|
||||
|
||||
<link rel="preload" href="/favicon.ico" as="image" />
|
||||
|
||||
<title>GeneraTOR</title>
|
||||
<meta name="description" content="Generator rozkazów pisemnych dla symulatora Train Driver 2" />
|
||||
|
||||
<!-- Static OpenGraph meta -->
|
||||
<meta property="og:url" content="https://generator-td2.web.app/" />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:title" content="GeneraTOR" />
|
||||
<meta
|
||||
property="og:description"
|
||||
content="Generator rozkazów pisemnych dla symulatora Train Driver 2"
|
||||
/>
|
||||
|
||||
<meta
|
||||
property="og:image"
|
||||
content="https://raw.githubusercontent.com/Spythere/api/refs/heads/main/thumbnails/generator-banner.png"
|
||||
/>
|
||||
|
||||
<meta property="og:image:width" content="1200" />
|
||||
<meta property="og:image:height" content="630" />
|
||||
<meta property="og:site_name" content="GeneraTOR" />
|
||||
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta name="twitter:title" content="GeneraTOR" />
|
||||
<meta
|
||||
name="twitter:description"
|
||||
content="Generator rozkazów pisemnych dla symulatora Train Driver 2"
|
||||
/>
|
||||
<meta
|
||||
name="twitter:image"
|
||||
content="https://raw.githubusercontent.com/Spythere/api/refs/heads/main/thumbnails/generator-banner.png"
|
||||
/>
|
||||
<meta name="description" content="Generator rozkazów pisemnych online" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
|
||||
+2
-1
@@ -12,7 +12,8 @@
|
||||
"format": "prettier --write src/"
|
||||
},
|
||||
"dependencies": {
|
||||
"lucide-vue-next": "^0.562.0",
|
||||
"axios": "^1.6.2",
|
||||
"lucide-vue-next": "^0.525.0",
|
||||
"pinia": "^2.1.7",
|
||||
"showdown": "^2.1.0",
|
||||
"vue": "^3.3.11",
|
||||
|
||||
+43
-101
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div id="app_wrapper">
|
||||
<div>
|
||||
<transition name="slide-anim">
|
||||
<UpdateCard />
|
||||
</transition>
|
||||
@@ -8,12 +8,8 @@
|
||||
<UpdatePrompt />
|
||||
</transition>
|
||||
|
||||
<transition name="slide-anim">
|
||||
<MigrationInfo v-if="store.isMigrationInfoOpen" />
|
||||
</transition>
|
||||
|
||||
<div class="app-body">
|
||||
<Navbar />
|
||||
<AppNavbar />
|
||||
|
||||
<main>
|
||||
<RouterView />
|
||||
@@ -22,110 +18,73 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import UpdateCard from './components/Global/UpdateCard.vue';
|
||||
import orderStorageMixin from './mixins/orderStorageMixin';
|
||||
import { useStore } from './store/store';
|
||||
<script lang="ts" setup>
|
||||
import packageInfo from '../package.json';
|
||||
import StorageManager from './managers/storageManager';
|
||||
import Navbar from './components/App/Navbar.vue';
|
||||
import axios from 'axios';
|
||||
import { useStore } from './store/store';
|
||||
|
||||
import UpdateCard from './components/Global/UpdateCard.vue';
|
||||
import UpdatePrompt from './components/Global/UpdatePrompt.vue';
|
||||
import MigrationInfo from './components/Global/MigrationInfo.vue';
|
||||
import AppNavbar from './components/App/AppNavbar.vue';
|
||||
import StorageManager from './managers/storageManager';
|
||||
import { onMounted } from 'vue';
|
||||
|
||||
const STORAGE_VERSION_KEY = 'app_version';
|
||||
|
||||
export default defineComponent({
|
||||
components: { UpdateCard, UpdatePrompt, Navbar, MigrationInfo },
|
||||
const store = useStore();
|
||||
const appVersion = packageInfo.version;
|
||||
|
||||
mixins: [orderStorageMixin],
|
||||
onMounted(() => {
|
||||
loadLang();
|
||||
loadSettings();
|
||||
checkAppVersion();
|
||||
handleQueries();
|
||||
});
|
||||
|
||||
data() {
|
||||
return { appVersion: packageInfo.version, store: useStore() };
|
||||
},
|
||||
function loadSettings() {
|
||||
document.title = `GeneraTOR ${appVersion}`;
|
||||
store.orderDarkMode = StorageManager.getBooleanValue('dark-mode');
|
||||
}
|
||||
|
||||
created() {
|
||||
this.init();
|
||||
},
|
||||
|
||||
methods: {
|
||||
init() {
|
||||
this.loadLang();
|
||||
this.setupDarkMode();
|
||||
this.loadSettings();
|
||||
this.handleMigrationInfo();
|
||||
this.checkAppVersion();
|
||||
this.handleQueries();
|
||||
},
|
||||
|
||||
loadSettings() {
|
||||
document.title = `GeneraTOR ${this.appVersion}`;
|
||||
},
|
||||
|
||||
setupDarkMode() {
|
||||
if (this.getOrderSetting('dark-mode') === null) {
|
||||
const prefersDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||
|
||||
this.saveOrderSetting('dark-mode', prefersDarkMode);
|
||||
}
|
||||
|
||||
this.store.orderDarkMode = this.getOrderSetting('dark-mode') === 'true';
|
||||
document.documentElement.setAttribute(
|
||||
'data-theme',
|
||||
this.store.orderDarkMode ? 'dark' : 'light'
|
||||
);
|
||||
},
|
||||
|
||||
handleQueries() {
|
||||
function handleQueries() {
|
||||
const query = new URLSearchParams(window.location.search);
|
||||
|
||||
const id = query.get('sceneryId');
|
||||
|
||||
if (id != null) {
|
||||
this.store.panelMode = 'OrderTrainPickerPanel';
|
||||
store.panelMode = 'OrderTrainPickerPanel';
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
async checkAppVersion() {
|
||||
async function checkAppVersion() {
|
||||
const storageVersion = StorageManager.getStringValue(STORAGE_VERSION_KEY);
|
||||
|
||||
try {
|
||||
const releaseResponse = await fetch(
|
||||
'https://api.github.com/repos/Spythere/genera-tor/releases/latest'
|
||||
);
|
||||
|
||||
if (!releaseResponse.ok) return;
|
||||
|
||||
const releaseData = await releaseResponse.json();
|
||||
const releaseData = await (
|
||||
await axios.get('https://api.github.com/repos/Spythere/genera-tor/releases/latest')
|
||||
).data;
|
||||
|
||||
if (!releaseData) return;
|
||||
|
||||
this.store.appUpdateData.version = this.appVersion;
|
||||
this.store.appUpdateData.changelog = releaseData.body;
|
||||
this.store.appUpdateData.releaseURL = releaseData.html_url;
|
||||
store.appUpdateData.version = appVersion;
|
||||
store.appUpdateData.changelog = releaseData.body;
|
||||
store.appUpdateData.releaseURL = releaseData.html_url;
|
||||
|
||||
this.store.updateCardOpen =
|
||||
(storageVersion != '' && storageVersion != this.appVersion) ||
|
||||
store.updateCardOpen =
|
||||
(storageVersion != '' && storageVersion != appVersion) ||
|
||||
import.meta.env.VITE_UPDATE_TEST === 'test';
|
||||
} catch (error) {
|
||||
console.error(`Wystąpił błąd podczas pobierania danych z API GitHuba: ${error}`);
|
||||
}
|
||||
|
||||
StorageManager.setStringValue(STORAGE_VERSION_KEY, this.appVersion);
|
||||
},
|
||||
StorageManager.setStringValue(STORAGE_VERSION_KEY, appVersion);
|
||||
}
|
||||
|
||||
changeLang(lang: string) {
|
||||
this.$i18n.locale = lang;
|
||||
this.store.currentAppLocale = lang;
|
||||
|
||||
StorageManager.setStringValue('lang', lang);
|
||||
},
|
||||
|
||||
loadLang() {
|
||||
function loadLang() {
|
||||
const storageLang = StorageManager.getStringValue('lang');
|
||||
|
||||
if (storageLang) {
|
||||
this.changeLang(storageLang);
|
||||
store.changeLang(storageLang);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -134,25 +93,9 @@ export default defineComponent({
|
||||
const naviLanguage = window.navigator.language.toString();
|
||||
|
||||
if (!naviLanguage.startsWith('pl')) {
|
||||
this.changeLang('en');
|
||||
store.changeLang('en');
|
||||
}
|
||||
},
|
||||
|
||||
handleMigrationInfo() {
|
||||
// Show only on old domain
|
||||
if (location.hostname !== 'generator-td2.web.app' && location.hostname != 'localhost') return;
|
||||
|
||||
const showInfo = localStorage.getItem('showMigrationInfo');
|
||||
|
||||
// Do not show if already acknowledged
|
||||
if (showInfo === 'false') return;
|
||||
|
||||
setTimeout(() => {
|
||||
this.store.isMigrationInfoOpen = true;
|
||||
}, 2000);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@@ -164,9 +107,8 @@ export default defineComponent({
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 500px) {
|
||||
#app {
|
||||
font-size: calc(1vw + 0.65rem);
|
||||
}
|
||||
footer {
|
||||
text-align: center;
|
||||
padding: 0.5em 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
<template>
|
||||
<footer>
|
||||
© <a href="https://td2.info.pl/profile/?u=20777">Spythere</a>
|
||||
{{ new Date().getUTCFullYear() }} |
|
||||
<button class="g-button text" @click="store.updateCardOpen = true">v{{ props.version }}</button>
|
||||
</footer>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useStore } from '../../store/store';
|
||||
|
||||
const store = useStore();
|
||||
|
||||
const props = defineProps({
|
||||
version: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
@@ -2,14 +2,9 @@
|
||||
<nav class="app-navbar">
|
||||
<div class="navbar-brand">
|
||||
<img src="/favicon.ico" alt="generator logo" width="30" />
|
||||
<div>
|
||||
<b>
|
||||
Genera<span class="text--accent">TOR</span>
|
||||
<sup class="text--grayed">v{{ version }}</sup>
|
||||
Genera<span class="text--accent">TOR</span> <sup class="text--grayed">v{{ version }}</sup>
|
||||
</b>
|
||||
|
||||
<b class="brand-author"> by Spythere</b>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="navbar-actions">
|
||||
@@ -36,7 +31,6 @@ const store = useStore();
|
||||
function switchDarkMode() {
|
||||
store.orderDarkMode = !store.orderDarkMode;
|
||||
window.localStorage.setItem('dark-mode', `${store.orderDarkMode}`);
|
||||
document.documentElement.setAttribute('data-theme', store.orderDarkMode ? 'dark' : 'light');
|
||||
}
|
||||
|
||||
function switchLang() {
|
||||
@@ -66,11 +60,6 @@ function switchLang() {
|
||||
}
|
||||
}
|
||||
|
||||
.brand-author {
|
||||
font-size: 0.8em;
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
.navbar-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -1,67 +0,0 @@
|
||||
<template>
|
||||
<div class="migrate-info">
|
||||
<div class="info-content">
|
||||
<i18n-t keypath="migrate-info.line-1" for="migrate-info" tag="div">
|
||||
<a href="https://generator-td2.spythere.eu/" target="_blank">{{
|
||||
t('migrate-info.link')
|
||||
}}</a>
|
||||
</i18n-t>
|
||||
<button class="g-button action accept-btn" @click="onAcceptButtonClick">
|
||||
{{ t('migrate-info.accept-btn') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useStore } from '../../store/store';
|
||||
|
||||
const store = useStore();
|
||||
const { t } = useI18n();
|
||||
|
||||
function onAcceptButtonClick() {
|
||||
store.isMigrationInfoOpen = false;
|
||||
localStorage.setItem('showMigrationInfo', 'false');
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use '../../styles/colors';
|
||||
|
||||
.migrate-info {
|
||||
position: fixed;
|
||||
z-index: 100;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
|
||||
padding: 0.25em;
|
||||
text-align: center;
|
||||
|
||||
width: 100%;
|
||||
background-color: colors.$warnCol;
|
||||
color: black;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.info-content {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.5em;
|
||||
}
|
||||
|
||||
a {
|
||||
color: black;
|
||||
text-decoration: underline;
|
||||
|
||||
&:hover {
|
||||
color: black;
|
||||
}
|
||||
}
|
||||
|
||||
.accept-btn {
|
||||
color: white;
|
||||
}
|
||||
</style>
|
||||
@@ -1,68 +0,0 @@
|
||||
<template>
|
||||
<div class="order-helper g-modal">
|
||||
<div class="modal-bg" @click="store.helperModalOpen = false"></div>
|
||||
|
||||
<div class="content modal-content">
|
||||
<h2>Rozkazy pisemne - najczęstsze przypadki zastosowań w TD2</h2>
|
||||
|
||||
<hr />
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<b>Przetaczanie (manewr) taboru poza wskaźnik W 5 (granicy przetaczania)</b>
|
||||
<p>
|
||||
Rozkazu <u>nie stosujemy</u> w przypadku wyjazdu taboru na szlak dwutorowy, na którym
|
||||
odbywa się ruch w kierunku zasadniczym, tj. "prawostronnym". Dla wszystkich szlaków
|
||||
jednotorowych lub dwutorowych w sytuacji innej niż wymieniona wykorzystujemy działkę 4.
|
||||
rozkazu pisemnego "S". <br /><br />
|
||||
<i
|
||||
>Szczegółowe informacje: instrukcja Ir-1 (R-1) § 12 pkt 4 "Manewry na torach
|
||||
głównych"</i
|
||||
>
|
||||
</p>
|
||||
<button class="g-button action">Wygeneruj treść rozkazu</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { useStore } from '../../store/store';
|
||||
|
||||
export default defineComponent({
|
||||
setup() {
|
||||
return { store: useStore() };
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use '../../styles/colors';
|
||||
|
||||
.content {
|
||||
width: 100%;
|
||||
max-width: 800px;
|
||||
|
||||
height: 100vh;
|
||||
max-height: 800px;
|
||||
|
||||
margin: 1em;
|
||||
padding: 1em;
|
||||
background-color: #2b2b2b;
|
||||
}
|
||||
|
||||
h2 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
ul {
|
||||
text-align: left;
|
||||
|
||||
li b {
|
||||
font-size: 1.1em;
|
||||
color: colors.$accentCol;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -8,7 +8,7 @@
|
||||
<script setup lang="ts">
|
||||
import { useRegisterSW } from 'virtual:pwa-register/vue';
|
||||
|
||||
const { needRefresh, updateServiceWorker } = useRegisterSW({ immediate: true });
|
||||
const { offlineReady, needRefresh, updateServiceWorker } = useRegisterSW({ immediate: true });
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
<template>
|
||||
<div class="order" :class="{ dark: store.orderDarkMode }">
|
||||
<OrderHeader />
|
||||
<OrderMainContent />
|
||||
<OrderFooter />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useStore } from '../../store/store';
|
||||
import OrderHeader from './OrderHeader.vue';
|
||||
import OrderMainContent from './OrderMainContent.vue';
|
||||
import OrderFooter from './OrderFooter.vue';
|
||||
import { computed, onMounted, watch } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
const { t } = useI18n();
|
||||
const store = useStore();
|
||||
|
||||
onMounted(() => {
|
||||
generateMessage();
|
||||
});
|
||||
|
||||
watch(
|
||||
store.orderData,
|
||||
() => {
|
||||
generateMessage();
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
|
||||
watch(
|
||||
computed(() => store.currentAppLocale),
|
||||
() => {
|
||||
generateMessage();
|
||||
}
|
||||
);
|
||||
|
||||
function generateMessage() {
|
||||
let messageHtml = `<b>${t('order.title')}</b><br />`;
|
||||
messageHtml += '-------------<br />';
|
||||
|
||||
const headerData = store.orderData['header'];
|
||||
const headerDateString = headerData['B']
|
||||
? new Date(headerData['B']).toLocaleDateString('pl-PL', {
|
||||
day: '2-digit',
|
||||
month: '2-digit',
|
||||
year: 'numeric'
|
||||
})
|
||||
: '';
|
||||
|
||||
messageHtml += `${t('order.header.A')}: ${headerData['A'] || '---'}<br />`;
|
||||
messageHtml += `${t('order.header.B')}: ${headerDateString || '---'}<br />`;
|
||||
messageHtml += `${t('order.header.C')}: ${headerData['C'] || '---'}<br />`;
|
||||
messageHtml += `${t('order.header.D')}: ${headerData['D'] || '---'}<br />`;
|
||||
|
||||
const instructions = store.orderData['instructions'];
|
||||
|
||||
Object.entries(instructions).forEach(([i, value]) => {
|
||||
if (value.active) {
|
||||
if (value.inputFields) {
|
||||
const localeKey = `order.${value.key}`;
|
||||
|
||||
const messageValues = Object.values(value.inputFields).map((fieldKey: string) => {
|
||||
if (fieldKey.startsWith('select')) return t(`order.${value.key}.${fieldKey}`);
|
||||
|
||||
return fieldKey || '---';
|
||||
});
|
||||
|
||||
messageHtml += '-------------<br />';
|
||||
|
||||
messageHtml += `<b>[${value.name}]</b> ${t(
|
||||
localeKey + '.message-html',
|
||||
messageValues,
|
||||
Object.keys(value.inputFields).filter(
|
||||
(k) => value.optionalFieldNames.includes(k) && value.inputFields[k].trim() != ''
|
||||
).length
|
||||
)}<br />`;
|
||||
|
||||
if (value.key == '2310' && value.listFields) {
|
||||
messageHtml += '<br />';
|
||||
value.listFields.forEach((listItem, i) => {
|
||||
if (!listItem.active) return;
|
||||
|
||||
const listItemValues = Object.values(listItem.values).map((itemFieldKey) => {
|
||||
return itemFieldKey || '---';
|
||||
});
|
||||
|
||||
messageHtml += t(
|
||||
`${localeKey}.message-html-list`,
|
||||
[i + 1, ...listItemValues],
|
||||
Object.keys(listItem.values).filter(
|
||||
(k) => listItem.values[k].trim() != '' && k.startsWith('signalbox')
|
||||
).length
|
||||
);
|
||||
messageHtml += '<br />';
|
||||
});
|
||||
}
|
||||
} else {
|
||||
messageHtml += `<b>[${i}]</b> ${t('order.' + i + '.message-html')}<br />`;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const footerData = store.orderData['footer'];
|
||||
|
||||
messageHtml += '-------------<br />';
|
||||
messageHtml += `${t('order.footer.V')}: ${footerData['V'] || '---'}<br />`;
|
||||
messageHtml += `${t('order.footer.W')}: ${footerData['W'] || '---'}<br />`;
|
||||
messageHtml += `${t('order.footer.Y')}: ${footerData['Y'] || '---'}<br />`;
|
||||
messageHtml += `${t('order.footer.Z')}: ${footerData['Z'] || '---'}<br />`;
|
||||
|
||||
store.orderMessage = messageHtml;
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@use '../../styles/order';
|
||||
</style>
|
||||
@@ -0,0 +1,81 @@
|
||||
<template>
|
||||
<table class="order-table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td width="50%">
|
||||
<div>
|
||||
<input
|
||||
type="text"
|
||||
class="order-input"
|
||||
id="footer-V"
|
||||
v-model="store.orderData.footer.V"
|
||||
:placeholder="t('order.footer.V-placeholder')"
|
||||
/>
|
||||
<label class="order-input-label" for="footer-V">{{ t('order.footer.V') }}</label>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div>
|
||||
<input
|
||||
type="text"
|
||||
class="order-input"
|
||||
id="footer-W"
|
||||
v-model="store.orderData.footer.W"
|
||||
:placeholder="t('order.footer.W-placeholder')"
|
||||
/>
|
||||
<label class="order-input-label" for="footer-W">{{ t('order.footer.W') }}</label>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
<div>
|
||||
<input
|
||||
type="text"
|
||||
class="order-input"
|
||||
id="footer-Y"
|
||||
v-model="store.orderData.footer.Y"
|
||||
:placeholder="t('order.footer.Y-placeholder')"
|
||||
/>
|
||||
<label class="order-input-label" for="footer-Y">{{ t('order.footer.Y') }}</label>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div>
|
||||
<input
|
||||
type="text"
|
||||
class="order-input"
|
||||
id="footer-Z"
|
||||
v-model="store.orderData.footer.Z"
|
||||
:placeholder="t('order.footer.Z-placeholder')"
|
||||
/>
|
||||
<label class="order-input-label" for="footer-Z">{{ t('order.footer.Z') }}</label>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useStore } from '../../store/store';
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const store = useStore();
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.order-input {
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.order-table > tbody > tr > td > div {
|
||||
width: 100%;
|
||||
padding: 0.5em 1rem;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,90 @@
|
||||
<template>
|
||||
<table class="order-table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="padding: 0.25em" colspan="2">
|
||||
<b>{{ t('order.title') }}</b>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td width="50%">
|
||||
<div class="header-input-box">
|
||||
<input
|
||||
type="text"
|
||||
class="order-input"
|
||||
id="header-A"
|
||||
v-model="store.orderData.header.A"
|
||||
:placeholder="t('order.header.A-placeholder')"
|
||||
/>
|
||||
<label class="order-input-label" for="header-A">{{ t('order.header.A') }}</label>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="header-input-box">
|
||||
<input
|
||||
type="date"
|
||||
class="order-input"
|
||||
id="header-B"
|
||||
v-model="store.orderData.header.B"
|
||||
/>
|
||||
<label class="order-input-label" for="header-B">{{ t('order.header.B') }}</label>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
<div class="header-input-box">
|
||||
<input
|
||||
type="text"
|
||||
class="order-input"
|
||||
id="header-C"
|
||||
v-model="store.orderData.header.C"
|
||||
:placeholder="t('order.header.C-placeholder')"
|
||||
/>
|
||||
<label class="order-input-label" for="header-C">{{ t('order.header.C') }}</label>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="header-input-box">
|
||||
<input
|
||||
type="text"
|
||||
class="order-input"
|
||||
id="header-D"
|
||||
v-model="store.orderData.header.D"
|
||||
:placeholder="t('order.header.D-placeholder')"
|
||||
/>
|
||||
<label class="order-input-label" for="header-D">{{ t('order.header.D') }}</label>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useStore } from '../../store/store';
|
||||
|
||||
const { t } = useI18n();
|
||||
const store = useStore();
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.header-input-box {
|
||||
width: 100%;
|
||||
padding: 0.5em 1em;
|
||||
}
|
||||
|
||||
.order-input {
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.order-table,
|
||||
.order-table tr:last-child td {
|
||||
border-bottom: none;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,204 @@
|
||||
<template>
|
||||
<table class="order-table">
|
||||
<tbody>
|
||||
<!-- First row - 22 & 99 instructions -->
|
||||
<tr>
|
||||
<td width="10%" class="order-instruction-number">
|
||||
<OrderRowCheckbox :row-index="0" />
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<b>
|
||||
{{ t('order.22.text') }}
|
||||
</b>
|
||||
</td>
|
||||
|
||||
<td width="5%" class="order-instruction-number">
|
||||
<OrderRowCheckbox :row-index="1" />
|
||||
</td>
|
||||
|
||||
<td width="45%">
|
||||
<div>
|
||||
<b>{{ t('order.99.text') }}</b>
|
||||
</div>
|
||||
<input
|
||||
type="text"
|
||||
class="order-input"
|
||||
id="input-99-x1"
|
||||
v-model="store.orderData.instructions[1].inputFields!.x1"
|
||||
/>
|
||||
<label for="input-99-x1" class="order-input-label">{{ t('order.99.x1') }}</label>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- From 21.10 -->
|
||||
<tr
|
||||
v-for="(instruction, i) in store.orderData.instructions.slice(2)"
|
||||
:class="{
|
||||
'bg-lighter': instruction.key.startsWith('218'),
|
||||
dark: store.orderDarkMode
|
||||
}"
|
||||
>
|
||||
<td width="10%" class="order-instruction-number">
|
||||
<OrderRowCheckbox :row-index="i + 2" />
|
||||
</td>
|
||||
|
||||
<td colspan="3">
|
||||
<i18n-t :keypath="`order.${instruction.key}.text`" tag="div" scope="global">
|
||||
<!-- For text directives (<b>, <u>, <br> etc.) -->
|
||||
<template v-slot:[directive] v-for="directive in instruction.textDirectives">
|
||||
<b v-if="directive.startsWith('bold')">
|
||||
{{ t(`order.${instruction.key}.${directive}`) }}
|
||||
</b>
|
||||
<u v-else-if="directive.startsWith('underline')">
|
||||
{{ t(`order.${instruction.key}.${directive}`) }}
|
||||
</u>
|
||||
<u v-else-if="directive.startsWith('highlight')">
|
||||
<b>{{ t(`order.${instruction.key}.${directive}`) }}</b>
|
||||
</u>
|
||||
<br v-if="directive.startsWith('br')" />
|
||||
</template>
|
||||
|
||||
<!-- For all instructions with input fields -->
|
||||
<template v-slot:[fieldKey] v-for="(_, fieldKey) in instruction.inputFields">
|
||||
<textarea
|
||||
v-if="fieldKey == 'other2320'"
|
||||
v-model="instruction.inputFields[fieldKey]"
|
||||
class="order-textarea"
|
||||
:id="`order-${instruction.key}-${fieldKey}`"
|
||||
:placeholder="t(`order.${instruction.key}.${fieldKey}`)"
|
||||
autocomplete="off"
|
||||
></textarea>
|
||||
|
||||
<label class="order-input-box" v-else>
|
||||
<input
|
||||
v-model="instruction.inputFields[fieldKey]"
|
||||
class="order-input"
|
||||
:id="`order-${instruction.key}-${fieldKey}`"
|
||||
:style="{ width: calculateInputWidthByFieldName(fieldKey) }"
|
||||
autocomplete="off"
|
||||
/>
|
||||
<span>{{ t(`order.${instruction.key}.${fieldKey}`) }}</span>
|
||||
</label>
|
||||
</template>
|
||||
|
||||
<!-- For all instructions with select fields -->
|
||||
<template v-for="(selectField, fieldKey) in instruction.selectFields" v-slot:[fieldKey]>
|
||||
<select
|
||||
class="order-select"
|
||||
:id="`order-${instruction.key}-${fieldKey}`"
|
||||
v-model="instruction.inputFields[fieldKey]"
|
||||
>
|
||||
<option :value="value" v-for="value in selectField.options">
|
||||
{{ t(`order.${instruction.key}.${value}`) }}
|
||||
</option>
|
||||
</select>
|
||||
</template>
|
||||
|
||||
<!-- For 23.10 only -->
|
||||
<template v-slot:text-list v-if="instruction.key == '2310'">
|
||||
<i18n-t
|
||||
v-for="(listItem, i) in instruction.listFields"
|
||||
:keypath="`order.${instruction.key}.text-list`"
|
||||
tag="div"
|
||||
scope="global"
|
||||
>
|
||||
<template v-slot:bold>
|
||||
<label>
|
||||
<input
|
||||
v-model="listItem.active"
|
||||
type="checkbox"
|
||||
:id="`order-${instruction.key}-checkbox-${i}`"
|
||||
/>
|
||||
|
||||
<b>{{ t(`order.${instruction.key}.bold`, [i + 1]) }}</b>
|
||||
</label>
|
||||
</template>
|
||||
|
||||
<template v-slot:v>
|
||||
<br />
|
||||
<span style="font-size: 1.5em">v</span>
|
||||
</template>
|
||||
|
||||
<template v-slot:[fieldKey] v-for="(_, fieldKey, j) in listItem.values">
|
||||
<label class="order-input-box">
|
||||
<input
|
||||
v-model="instruction.listFields![i]['values'][fieldKey]"
|
||||
class="order-input"
|
||||
:id="`order-${instruction.key}-${fieldKey}-${i}`"
|
||||
:style="{ width: calculateInputWidthByFieldName(fieldKey) }"
|
||||
autocomplete="off"
|
||||
/>
|
||||
<span>{{
|
||||
t(`order.${instruction.key}.${fieldKey}`, [j + 1 + 6 * i, 91 + i])
|
||||
}}</span>
|
||||
</label>
|
||||
</template>
|
||||
</i18n-t>
|
||||
</template>
|
||||
</i18n-t>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useStore } from '../../store/store';
|
||||
import OrderRowCheckbox from './OrderRowCheckbox.vue';
|
||||
|
||||
const { t } = useI18n();
|
||||
const store = useStore();
|
||||
|
||||
function calculateInputWidthByFieldName(fieldName: string) {
|
||||
if (fieldName.startsWith('track')) return '90px';
|
||||
else if (fieldName.startsWith('signalbox')) return '130px';
|
||||
else if (fieldName.startsWith('signal')) return '150px';
|
||||
else if (fieldName.startsWith('train')) return '150px';
|
||||
else if (fieldName.startsWith('other2320')) return '100%';
|
||||
else if (fieldName.startsWith('other')) return '200px';
|
||||
|
||||
return '100px';
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.order-table {
|
||||
border-top: none;
|
||||
border-bottom: none;
|
||||
|
||||
td {
|
||||
padding: 0.25em;
|
||||
}
|
||||
|
||||
tr:not(:first-child) td {
|
||||
padding: 0.25em 1em;
|
||||
line-height: 2em;
|
||||
text-align: justify;
|
||||
}
|
||||
|
||||
tr.bg-lighter {
|
||||
background-color: #eeece1;
|
||||
}
|
||||
|
||||
tr.bg-lighter.dark {
|
||||
background-color: #111;
|
||||
}
|
||||
}
|
||||
|
||||
.order-instruction-number {
|
||||
position: relative;
|
||||
height: 60px;
|
||||
|
||||
& > label {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
padding: 0.5em;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,90 @@
|
||||
<template>
|
||||
<label class="order-instruction-checkbox">
|
||||
<input
|
||||
type="checkbox"
|
||||
v-model="instructionObject.active"
|
||||
:id="`instruction-checkbox-${instructionObject.name}`"
|
||||
/>
|
||||
<div class="checkmark" :class="{ dark: store.orderDarkMode }"></div>
|
||||
<div class="text">{{ instructionObject.name }}</div>
|
||||
</label>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import { useStore } from '../../store/store';
|
||||
|
||||
const store = useStore();
|
||||
|
||||
const props = defineProps({
|
||||
rowIndex: {
|
||||
type: Number,
|
||||
required: true
|
||||
}
|
||||
});
|
||||
|
||||
const instructionObject = computed(() => store.orderData.instructions[props.rowIndex]);
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.order-instruction-checkbox {
|
||||
display: block;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
|
||||
& > input {
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
height: 0;
|
||||
width: 0;
|
||||
cursor: pointer;
|
||||
|
||||
&:checked ~ .checkmark:after {
|
||||
content: '\d7';
|
||||
}
|
||||
|
||||
&:focus-visible ~ .text {
|
||||
text-decoration: underline;
|
||||
outline: 1px solid black;
|
||||
}
|
||||
}
|
||||
|
||||
.checkmark {
|
||||
display: block;
|
||||
position: relative;
|
||||
|
||||
margin: 0 auto;
|
||||
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
background-color: #eee;
|
||||
border: 2px solid black;
|
||||
|
||||
background-color: gold;
|
||||
|
||||
&.dark {
|
||||
color: black;
|
||||
}
|
||||
|
||||
&:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
font-size: 20px;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
}
|
||||
|
||||
&:hover input ~ .checkmark {
|
||||
background-color: #ffe44b;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,247 +0,0 @@
|
||||
<template>
|
||||
<div class="order-container">
|
||||
<OrderSideBar />
|
||||
|
||||
<div class="order" :class="{ dark: store.orderDarkMode }">
|
||||
<div class="order_content">
|
||||
<transition name="order-anim" mode="out-in">
|
||||
<keep-alive>
|
||||
<component :is="chosenOrderComponent" :key="chosenOrderComponent.name"></component>
|
||||
</keep-alive>
|
||||
</transition>
|
||||
<OrderFooter />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { useStore } from '../../store/store';
|
||||
import OrderN from './OrderN.vue';
|
||||
import OrderS from './OrderS.vue';
|
||||
import OrderO from './OrderO.vue';
|
||||
import OrderFooter from './OrderFooter.vue';
|
||||
import OrderSideBar from './OrderSideBar.vue';
|
||||
|
||||
const orderComponents = { orderN: OrderN, orderS: OrderS, orderO: OrderO };
|
||||
|
||||
export default defineComponent({
|
||||
components: { OrderN, OrderO, OrderS, OrderFooter, OrderSideBar },
|
||||
|
||||
setup() {
|
||||
const store = useStore();
|
||||
|
||||
return { store };
|
||||
},
|
||||
|
||||
computed: {
|
||||
chosenOrderComponent() {
|
||||
return orderComponents[this.store.chosenOrderType];
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@use '../../styles/colors';
|
||||
|
||||
$darkModeTextCol: #eee;
|
||||
|
||||
.order-container {
|
||||
display: flex;
|
||||
align-items: start;
|
||||
max-width: 800px;
|
||||
|
||||
@media screen and (max-width: 1150px) {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
||||
.order {
|
||||
background-color: white;
|
||||
color: black;
|
||||
|
||||
max-height: calc(100vh - 5em);
|
||||
overflow: auto;
|
||||
|
||||
&.dark {
|
||||
background-color: colors.$bgColDarker;
|
||||
color: $darkModeTextCol;
|
||||
}
|
||||
|
||||
font-size: 15px;
|
||||
|
||||
h2 {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
textarea:focus-visible {
|
||||
outline: 2px solid colors.$accentCol;
|
||||
}
|
||||
|
||||
input[type='checkbox']:focus-visible,
|
||||
input[type='radio']:focus-visible {
|
||||
outline: 2px solid colors.$accentCol;
|
||||
}
|
||||
|
||||
input[type='checkbox'],
|
||||
input[type='radio'],
|
||||
select {
|
||||
margin-top: 0.5em;
|
||||
margin-right: 0.5em;
|
||||
font-size: 0.8em;
|
||||
color: black;
|
||||
}
|
||||
|
||||
textarea.others {
|
||||
width: 100%;
|
||||
min-height: 200px;
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 550px) {
|
||||
font-size: 3vw;
|
||||
}
|
||||
}
|
||||
|
||||
.order_header {
|
||||
padding: 0.5em;
|
||||
border: 2px solid black;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.order_content {
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
.flex-row {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-items: flex-end;
|
||||
|
||||
margin-top: 0.5em;
|
||||
|
||||
input {
|
||||
max-width: 10em;
|
||||
}
|
||||
}
|
||||
|
||||
.flex-center {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.horizontal-bar {
|
||||
width: 100%;
|
||||
height: 2px;
|
||||
|
||||
background-color: black;
|
||||
margin: 0.5em 0;
|
||||
}
|
||||
|
||||
.order input {
|
||||
max-width: 100px;
|
||||
background-color: transparent;
|
||||
outline: none;
|
||||
border: none;
|
||||
font-size: 1em;
|
||||
|
||||
text-align: center;
|
||||
border-bottom: 2px dotted black;
|
||||
|
||||
&:focus-visible {
|
||||
border-bottom: 2px solid colors.$accentCol;
|
||||
}
|
||||
|
||||
&.row-checkbox + input::placeholder {
|
||||
color: red;
|
||||
}
|
||||
}
|
||||
|
||||
/* Dark mode */
|
||||
.order.dark {
|
||||
input {
|
||||
border-color: $darkModeTextCol !important;
|
||||
color: $darkModeTextCol !important;
|
||||
|
||||
&:focus-visible {
|
||||
border-bottom: 2px solid colors.$accentCol !important;
|
||||
}
|
||||
|
||||
&::placeholder {
|
||||
color: #ccc !important;
|
||||
}
|
||||
}
|
||||
|
||||
select {
|
||||
color: $darkModeTextCol !important;
|
||||
border-color: $darkModeTextCol;
|
||||
|
||||
&:focus-visible {
|
||||
border-color: colors.$accentCol;
|
||||
}
|
||||
}
|
||||
|
||||
option,
|
||||
textarea {
|
||||
color: $darkModeTextCol !important;
|
||||
border-color: $darkModeTextCol !important;
|
||||
background-color: colors.$bgColDarker !important;
|
||||
}
|
||||
|
||||
.horizontal-bar {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.order_header,
|
||||
.order_other,
|
||||
table,
|
||||
tr,
|
||||
td {
|
||||
border-color: $darkModeTextCol !important;
|
||||
}
|
||||
}
|
||||
|
||||
.order_table-container {
|
||||
table {
|
||||
width: 100%;
|
||||
|
||||
td:first-child {
|
||||
width: 10%;
|
||||
|
||||
text-align: center;
|
||||
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 0.35em;
|
||||
text-align: justify;
|
||||
vertical-align: top;
|
||||
|
||||
line-height: 1.5em;
|
||||
}
|
||||
}
|
||||
|
||||
table,
|
||||
td {
|
||||
border: 2px solid black;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
}
|
||||
|
||||
.order-anim {
|
||||
&-enter-active,
|
||||
&-leave-active {
|
||||
transition: opacity 150ms ease-in-out;
|
||||
}
|
||||
|
||||
&-enter-from,
|
||||
&-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,101 +0,0 @@
|
||||
<template>
|
||||
<section class="order_info">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td colspan="4">
|
||||
<input type="text" v-model="footerInfo.stationName" placeholder="nazwa stacji" />
|
||||
<br />
|
||||
stacja
|
||||
</td>
|
||||
|
||||
<td colspan="3">
|
||||
<input type="text" v-model="footerInfo.checkpointName" placeholder="skrót posterunku" />
|
||||
<br />
|
||||
posterunek
|
||||
</td>
|
||||
|
||||
<td colspan="2">
|
||||
<input type="text" v-model="footerInfo.hour" placeholder="godzina" />
|
||||
<br />
|
||||
godz.
|
||||
</td>
|
||||
|
||||
<td colspan="1">
|
||||
<input type="text" v-model="footerInfo.minutes" placeholder="minuta" />
|
||||
<br />
|
||||
min.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td colspan="5">
|
||||
<input type="text" v-model="footerInfo.dispatcherName" placeholder="dyżurny" />
|
||||
<br />
|
||||
dyżurny ruchu
|
||||
</td>
|
||||
|
||||
<td colspan="5">
|
||||
<input
|
||||
type="text"
|
||||
v-model="footerInfo.secondaryDispatcherName"
|
||||
placeholder="dyżurny (wypełnić jedno)"
|
||||
/>
|
||||
<br />
|
||||
z polecenia dyżurnego ruchu
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import orderFooterMixin from '../../mixins/orderFooterMixin';
|
||||
import { useStore } from '../../store/store';
|
||||
|
||||
export default defineComponent({
|
||||
mixins: [orderFooterMixin],
|
||||
|
||||
setup() {
|
||||
const store = useStore();
|
||||
|
||||
return {
|
||||
store,
|
||||
footerInfo: store.orderFooter
|
||||
};
|
||||
},
|
||||
|
||||
watch: {
|
||||
footerInfo: {
|
||||
deep: true,
|
||||
handler() {
|
||||
this.generateFooter();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.order_info {
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
table-layout: fixed;
|
||||
|
||||
td {
|
||||
border: 2px solid black;
|
||||
border-collapse: collapse;
|
||||
padding: 0.35em;
|
||||
}
|
||||
|
||||
input {
|
||||
max-width: 95%;
|
||||
}
|
||||
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,518 +0,0 @@
|
||||
<template>
|
||||
<section class="order-n">
|
||||
<section class="order_header" ref="header">
|
||||
<h2 class="flex-center">
|
||||
Rozkaz pisemny "N" nr
|
||||
<input type="number" v-model="order.header.orderNo" placeholder="nr rozkazu" min="1" />
|
||||
</h2>
|
||||
<div class="flex-row">
|
||||
dla pociągu nr
|
||||
<input type="text" v-model="order.header.trainNo" placeholder="nr pociągu" />
|
||||
dnia
|
||||
<input type="text" v-model="order.header.date" placeholder="data" />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="order_table-container">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="row-enabled-1">1</label>
|
||||
<div>
|
||||
<input type="checkbox" id="row-enabled-1" v-model="order.rows[0].enabled" />
|
||||
</div>
|
||||
</td>
|
||||
<td ref="row-1">
|
||||
Od
|
||||
<input type="text" v-model="order.rows[0].from" holder="stacja / post." />
|
||||
do
|
||||
<input type="text" v-model="order.rows[0].to" holder="stacja / post." />
|
||||
tor nr
|
||||
<input type="text" v-model="order.rows[0].trackNo" holder="nr toru" />
|
||||
jest zamknięty, ruch jednotorowy dwukierunkowy wprowadzono po torze nr
|
||||
<input type="text" v-model="order.rows[0].trackNo2" holder="nr toru" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="row-enabled-2">2</label>
|
||||
<div>
|
||||
<input type="checkbox" id="row-enabled-2" v-model="order.rows[1].enabled" />
|
||||
</div>
|
||||
</td>
|
||||
<td ref="row-2">
|
||||
<strong>ZEZWALAM</strong> po otrzymaniu
|
||||
<select id="select-2a" v-model="order.rows[1].option1">
|
||||
<option :value="`sygnału "Nakaz Jazdy"`">sygnału "Nakaz Jazdy"</option>
|
||||
<option value="tylko tego rozkazu pisemnego">tylko tego rozkazu pisemnego</option>
|
||||
</select>
|
||||
<div style="margin-top: 0.5rem">
|
||||
<input
|
||||
type="radio"
|
||||
name="section-2"
|
||||
id="checkbox-2a"
|
||||
value="checkbox-2a"
|
||||
v-model="order.rows[1].checkbox"
|
||||
:checked="order.rows[1].checkbox == 'checkbox-2a'"
|
||||
@change="handleRowCheckboxChange(2)"
|
||||
/>
|
||||
<label for="checkbox-2a">
|
||||
przejechać obok wskazującego sygnał "Stój" semafora
|
||||
<div style="margin-left: 1rem">
|
||||
<input
|
||||
type="radio"
|
||||
name="section-2a"
|
||||
id="radio-2a-1"
|
||||
value="wyjazdowego"
|
||||
v-model="order.rows[1].signalType"
|
||||
@change="handleRowCheckboxChange(2)"
|
||||
/>
|
||||
<label for="radio-2a-1">
|
||||
wyjazdowego
|
||||
<input
|
||||
type="text"
|
||||
v-model="order.rows[1].signal1"
|
||||
holder="nazwa sem."
|
||||
:radio-checked="
|
||||
order.rows[1].checkbox == 'checkbox-2a' &&
|
||||
order.rows[1].signalType == 'wyjazdowego'
|
||||
"
|
||||
/>
|
||||
</label>
|
||||
<br />
|
||||
<input
|
||||
type="radio"
|
||||
name="section-2a"
|
||||
id="radio-2a-2"
|
||||
value="drogowskazowego"
|
||||
v-model="order.rows[1].signalType"
|
||||
@change="handleRowCheckboxChange(2)"
|
||||
/>
|
||||
<label for="radio-2a-2">
|
||||
drogowskazowego
|
||||
<input
|
||||
type="text"
|
||||
v-model="order.rows[1].signal2"
|
||||
holder="nazwa sem."
|
||||
:radio-checked="
|
||||
order.rows[1].checkbox == 'checkbox-2a' &&
|
||||
order.rows[1].signalType == 'drogowskazowego'
|
||||
"
|
||||
/>
|
||||
(odnoszącego się do wyjazdu pociągu)
|
||||
</label>
|
||||
<br />
|
||||
<input
|
||||
type="radio"
|
||||
name="section-2a"
|
||||
id="radio-2a-3"
|
||||
value="wjazdowego"
|
||||
v-model="order.rows[1].signalType"
|
||||
@change="handleRowCheckboxChange(2)"
|
||||
/>
|
||||
<label for="radio-2a-3">
|
||||
wjazdowego
|
||||
<input
|
||||
type="text"
|
||||
v-model="order.rows[1].signal3"
|
||||
holder="nazwa sem."
|
||||
:radio-checked="
|
||||
order.rows[1].checkbox == 'checkbox-2a' &&
|
||||
order.rows[1].signalType == 'wjazdowego'
|
||||
"
|
||||
/>
|
||||
na post. odg. bez sem. wyjazdowego
|
||||
</label>
|
||||
</div>
|
||||
i wyjechać w kierunku
|
||||
<input
|
||||
type="text"
|
||||
v-model="order.rows[1].direction1"
|
||||
holder="stacja / post."
|
||||
:radio-checked="order.rows[1].checkbox == 'checkbox-2a'"
|
||||
/>
|
||||
na tor szlakowy
|
||||
<select v-model="order.rows[1].option2">
|
||||
<option value="lewy">lewy</option>
|
||||
<option value="prawy">prawy</option>
|
||||
</select>
|
||||
nr
|
||||
<input
|
||||
type="text"
|
||||
v-model="order.rows[1].trackNoTo1"
|
||||
holder="nr toru"
|
||||
:radio-checked="order.rows[1].checkbox == 'checkbox-2a'"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
<div style="margin-top: 0.5rem">
|
||||
<input
|
||||
type="radio"
|
||||
name="section-2"
|
||||
id="checkbox-2b"
|
||||
value="checkbox-2b"
|
||||
v-model="order.rows[1].checkbox"
|
||||
:checked="order.rows[1].checkbox == 'checkbox-2b'"
|
||||
@change="handleRowCheckboxChange(2)"
|
||||
/>
|
||||
<label for="checkbox-2b">
|
||||
z toru nr
|
||||
<input
|
||||
type="text"
|
||||
v-model="order.rows[1].trackNoFrom"
|
||||
holder="nr toru"
|
||||
:radio-checked="order.rows[1].checkbox == 'checkbox-2b'"
|
||||
/>
|
||||
nie posiadającego semafora wyjazdowego wyjechać w kierunku
|
||||
<input
|
||||
type="text"
|
||||
v-model="order.rows[1].direction2"
|
||||
holder="stacja / post."
|
||||
:radio-checked="order.rows[1].checkbox == 'checkbox-2b'"
|
||||
/>
|
||||
na tor szlakowy
|
||||
<select v-model="order.rows[1].option3">
|
||||
<option value="lewy">lewy</option>
|
||||
<option value="prawy">prawy</option>
|
||||
</select>
|
||||
nr
|
||||
<input
|
||||
type="text"
|
||||
v-model="order.rows[1].trackNoTo2"
|
||||
holder="nr toru"
|
||||
:radio-checked="order.rows[1].checkbox == 'checkbox-2b'"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="row-enabled-3">3</label>
|
||||
<div>
|
||||
<input type="checkbox" id="row-enabled-3" v-model="order.rows[2].enabled" />
|
||||
</div>
|
||||
</td>
|
||||
<td ref="row-3">
|
||||
<select v-model="order.rows[2].option1">
|
||||
<option value="Jazda">Jazda</option>
|
||||
<option value="Popychanie">Popychanie</option>
|
||||
</select>
|
||||
pociągu odbędzie się w kierunku:
|
||||
<input type="text" v-model="order.rows[2].direction" holder="stacja / post." />
|
||||
do km
|
||||
<input type="text" v-model="order.rows[2].toKilometer" holder="kilometry" />
|
||||
skąd
|
||||
<select v-model="order.rows[2].option2">
|
||||
<option value="pociąg">pociąg</option>
|
||||
<option value="popychacz">popychacz</option>
|
||||
</select>
|
||||
ma wrócić po torze lewym nr
|
||||
<input type="text" v-model="order.rows[2].trackNo" holder="nr toru" />
|
||||
najpóźniej o godz.
|
||||
<input type="text" v-model="order.rows[2].untilHour" holder="godzina" />
|
||||
min.
|
||||
<input type="text" v-model="order.rows[2].untilMin" holder="minuta" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="row-enabled-4">4</label>
|
||||
<div>
|
||||
<input type="checkbox" id="row-enabled-4" v-model="order.rows[3].enabled" />
|
||||
</div>
|
||||
</td>
|
||||
<td ref="row-4">
|
||||
<strong>WJAZD</strong> z toru szlakowego nr
|
||||
<input type="text" v-model="order.rows[3].trackNo" holder="nr toru" />
|
||||
na
|
||||
<select v-model="order.rows[3].optionStation">
|
||||
<option value="stację">stację</option>
|
||||
<option value="posterunek odgałęźny">posterunek odgałęźny</option>
|
||||
</select>
|
||||
<input type="text" v-model="order.rows[3].stationName" holder="stacja / post." />
|
||||
odbędzie się po otrzymaniu:
|
||||
<div style="margin-top: 0.5rem">
|
||||
<input
|
||||
type="radio"
|
||||
name="section-4"
|
||||
id="checkbox-4a"
|
||||
value="checkbox-4a"
|
||||
v-model="order.rows[3].checkbox"
|
||||
/>
|
||||
<label for="checkbox-4a">
|
||||
sygnału zastępczego "Sz" na osobnym urządzeniu ustawionym z
|
||||
<select v-model="order.rows[3].side">
|
||||
<option value="lewej">lewej</option>
|
||||
<option value="prawej">prawej</option>
|
||||
</select>
|
||||
strony toru
|
||||
</label>
|
||||
</div>
|
||||
<div style="margin-top: 0.5rem">
|
||||
<input
|
||||
type="radio"
|
||||
name="section-4"
|
||||
id="checkbox-4b"
|
||||
value="checkbox-4b"
|
||||
v-model="order.rows[3].checkbox"
|
||||
/>
|
||||
<label for="checkbox-4b">
|
||||
rozkazu pisemnego "N" (doręczonego lub przekazanego przez urządzenia łączności)
|
||||
</label>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="row-enabled-5">5</label>
|
||||
<div>
|
||||
<input type="checkbox" id="row-enabled-5" v-model="order.rows[4].enabled" />
|
||||
</div>
|
||||
</td>
|
||||
<td ref="row-5">
|
||||
<strong>ZEZWALAM</strong> wjechać z toru szlakowego nr
|
||||
<input type="text" v-model="order.rows[4].trackNo" holder="nr toru" />
|
||||
z kierunku
|
||||
<input type="text" v-model="order.rows[4].direction" holder="stacja / post." />
|
||||
na
|
||||
<select v-model="order.rows[4].stationType">
|
||||
<option value="stację">stację</option>
|
||||
<option value="posterunek odgałęźny">posterunek odgałęźny</option>
|
||||
</select>
|
||||
<input type="text" v-model="order.rows[4].stationName" holder="stacja / post." />
|
||||
i przejechać obok sygnału "Stój" na
|
||||
<input type="text" v-model="order.rows[4].on" holder="nazwa sygnału" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr style="height: 270px">
|
||||
<td>
|
||||
<label for="row-enabled-6">6</label>
|
||||
<div>
|
||||
<input type="checkbox" id="row-enabled-6" v-model="order.rows[5].enabled" />
|
||||
</div>
|
||||
</td>
|
||||
<td ref="row-6">
|
||||
<button
|
||||
class="g-button text"
|
||||
@click="order.rows[5].twoWay.enabled = !order.rows[5].twoWay.enabled"
|
||||
>
|
||||
>
|
||||
<span v-if="!order.rows[5].twoWay.enabled">
|
||||
Wygeneruj treść na wprowadzenie ruchu dwukierunkowego
|
||||
</span>
|
||||
<span v-else>Wpisz treść własnoręcznie</span>
|
||||
</button>
|
||||
|
||||
<div>Inne:</div>
|
||||
|
||||
<div v-if="order.rows[5].twoWay.enabled">
|
||||
od
|
||||
<input type="text" v-model="order.rows[5].twoWay.from" holder="stacja / post." />
|
||||
do
|
||||
<input type="text" v-model="order.rows[5].twoWay.to" holder="stacja / post." />
|
||||
po torze nr
|
||||
<input type="text" v-model="order.rows[5].twoWay.trackNo" holder="nr toru" />
|
||||
wprowadzono ruch dwukierunkowy.
|
||||
</div>
|
||||
|
||||
<textarea
|
||||
v-else
|
||||
class="others"
|
||||
cols="30"
|
||||
rows="10"
|
||||
v-model="order.rows[5].content"
|
||||
></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, reactive } from 'vue';
|
||||
import { handleOrderPlaceholders } from '../../handlers/orderPlaceholderHandler';
|
||||
import { useStore } from '../../store/store';
|
||||
|
||||
type TOrderRows = 1 | 2 | 3 | 4 | 5;
|
||||
|
||||
export default defineComponent({
|
||||
name: 'OrderN',
|
||||
|
||||
setup() {
|
||||
const store = useStore();
|
||||
const order = reactive(store.orderN);
|
||||
|
||||
const rowMethods = [
|
||||
() => {
|
||||
const { header } = order;
|
||||
|
||||
const message = `\n<i><b>Rozkaz pisemny "N" nr ${header.orderNo || '_'}</b> dla pociągu nr ${
|
||||
header.trainNo || '_'
|
||||
} dnia ${header.date}</i>`;
|
||||
|
||||
return message;
|
||||
},
|
||||
|
||||
() => {
|
||||
const row = order.rows[0];
|
||||
|
||||
const message = `Od ${row.from || '_'} do ${row.to || '_'} tor nr ${
|
||||
row.trackNo || '_'
|
||||
} jest zamknięty, ruch jednotorowy dwukierunkowy wprowadzono po torze nr ${
|
||||
row.trackNo2 || '_'
|
||||
}`;
|
||||
|
||||
return message;
|
||||
},
|
||||
|
||||
() => {
|
||||
const row = order.rows[1];
|
||||
|
||||
let message = `ZEZWALAM po otrzymaniu ${row.option1 || '_'}`;
|
||||
|
||||
if (row.checkbox == 'checkbox-2a') {
|
||||
message += ` przejechać obok wskazującego sygnał "Stój" semafora ${
|
||||
row.signalType || '_'
|
||||
} `;
|
||||
|
||||
if (row.signalType == 'wyjazdowego') message += row.signal1 || '_';
|
||||
if (row.signalType == 'drogowskazowego')
|
||||
message += `${row.signal2 || '_'} (odnoszącego się do wyjazdu pociągu)`;
|
||||
if (row.signalType == 'wjazdowego')
|
||||
message += `${row.signal3 || '_'} na post. odg. bez sem. wyjazdowego`;
|
||||
|
||||
message += ` i wyjechać w kierunku ${row.direction1 || '_'} na tor szlakowy ${
|
||||
row.option2 || '_'
|
||||
} nr ${row.trackNoTo1 || '_'}`;
|
||||
}
|
||||
|
||||
if (row.checkbox == 'checkbox-2b') {
|
||||
message += ` z toru nr ${
|
||||
row.trackNoFrom || '_'
|
||||
} nie posiadającego semafora wyjazdowego wyjechać w kierunku ${
|
||||
row.direction2 || '_'
|
||||
} na tor szlakowy ${row.option3 || '_'} nr ${row.trackNoTo2 || '_'}`;
|
||||
}
|
||||
|
||||
return message;
|
||||
},
|
||||
|
||||
() => {
|
||||
const row = order.rows[2];
|
||||
|
||||
let message = `${row.option1 || '_'} pociągu odbędzie się w kierunku: ${
|
||||
row.direction || '_'
|
||||
} do km ${row.toKilometer || '_'} skąd ${row.option2 || '_'} ma wrócić po torze lewym nr ${
|
||||
row.trackNo || '_'
|
||||
} najpóźniej o godz. ${row.untilHour || '_'} min. ${row.untilMin || '_'}`;
|
||||
|
||||
return message;
|
||||
},
|
||||
|
||||
() => {
|
||||
const row = order.rows[3];
|
||||
|
||||
let message = `WJAZD z toru szlakowego nr ${row.trackNo || '_'} na ${
|
||||
row.optionStation || '_'
|
||||
} ${row.stationName || '_'} odbędzie się po otrzymaniu: `;
|
||||
|
||||
if (row.checkbox == 'checkbox-4a')
|
||||
message += `sygnału zastępczego "Sz" na osobnym urządzeniu ustawionym z ${
|
||||
row.side || '_'
|
||||
} strony toru`;
|
||||
|
||||
if (row.checkbox == 'checkbox-4b')
|
||||
message +=
|
||||
'rozkazu pisemnego "N" (doręczonego lub przekazanego przez urządzenia łączności)';
|
||||
|
||||
return message;
|
||||
},
|
||||
|
||||
() => {
|
||||
const row = order.rows[4];
|
||||
|
||||
const message = `ZEZWALAM wjechać z toru szlakowego nr ${row.trackNo || '_'} z kierunku ${
|
||||
row.direction || '_'
|
||||
} na ${row.stationType || '_'} ${
|
||||
row.stationName || '_'
|
||||
} i przejechać obok sygnału "Stój" na ${row.on || '_'} `;
|
||||
|
||||
return message;
|
||||
},
|
||||
|
||||
() => {
|
||||
const row = order.rows[5];
|
||||
|
||||
if (row.twoWay.enabled)
|
||||
return `Inne: od ${row.twoWay.from || '_'} do ${row.twoWay.to || '_'} po torze nr ${
|
||||
row.twoWay.trackNo || '_'
|
||||
} wprowadzono ruch dwukierunkowy.`;
|
||||
|
||||
return 'Inne: ' + row.content;
|
||||
}
|
||||
];
|
||||
|
||||
return {
|
||||
store,
|
||||
order,
|
||||
rowMethods
|
||||
};
|
||||
},
|
||||
|
||||
watch: {
|
||||
order: {
|
||||
deep: true,
|
||||
handler() {
|
||||
this.generateMessage();
|
||||
}
|
||||
},
|
||||
'order.rows': {
|
||||
deep: true,
|
||||
handler() {
|
||||
this.updatePlaceholders();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.updatePlaceholders();
|
||||
},
|
||||
|
||||
activated() {
|
||||
this.generateMessage();
|
||||
},
|
||||
|
||||
methods: {
|
||||
updatePlaceholders() {
|
||||
this.order.rows.forEach((_, i) => {
|
||||
this.handleRowCheckboxChange((i + 1) as TOrderRows);
|
||||
});
|
||||
},
|
||||
|
||||
handleRowCheckboxChange(rowIndex: TOrderRows) {
|
||||
const isRowEnabled = this.order.rows[rowIndex - 1].enabled;
|
||||
const rowRef = this.$refs[`row-${rowIndex}`] as HTMLTableElement;
|
||||
|
||||
this.$nextTick(() => {
|
||||
handleOrderPlaceholders(isRowEnabled, rowRef);
|
||||
});
|
||||
},
|
||||
|
||||
generateMessage() {
|
||||
let message = this.rowMethods[0]();
|
||||
|
||||
for (let i = 0; i < this.order.rows.length; i++) {
|
||||
if (!this.order.rows[i].enabled) continue;
|
||||
|
||||
message += `\n--------\n<b>[ ${i + 1} ]</b> ${this.rowMethods[i + 1]()}`;
|
||||
}
|
||||
|
||||
this.store.orderMessage = message;
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@@ -1,198 +0,0 @@
|
||||
<template>
|
||||
<section class="order-o">
|
||||
<section class="order_header">
|
||||
<h2 class="flex-center" style="padding: 0 0.5em">
|
||||
Rozkaz pisemny "O" nr
|
||||
<input type="number" v-model="order.header.orderNo" placeholder="nr rozkazu" min="1" />
|
||||
</h2>
|
||||
|
||||
<div class="flex-row" style="padding: 0 0.5em">
|
||||
dla pociągu nr
|
||||
<input type="text" v-model="order.header.trainNo" placeholder="nr pociągu" />
|
||||
dnia
|
||||
<input type="text" v-model="order.header.date" />
|
||||
</div>
|
||||
|
||||
<div class="horizontal-bar"></div>
|
||||
|
||||
<div style="display: flex; padding: 0 0.5em">
|
||||
<b>1.</b>
|
||||
|
||||
<div style="margin-left: 1.5em">
|
||||
1) zmniejszyć prędkość jazdy i zachować ostrożność <br />2) jechać ostrożnie (j.o.)
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="order_table">
|
||||
<table cellborder="1">
|
||||
<tbody>
|
||||
<tr class="tr-header">
|
||||
<td rowspan="2" width="35%">
|
||||
Na posterunku, <br />
|
||||
na szlaku
|
||||
</td>
|
||||
<td width="20%">od</td>
|
||||
<td width="20%">do</td>
|
||||
<td rowspan="2">1) prędkość najwyżej km/h</td>
|
||||
<td rowspan="2">2) j.o.</td>
|
||||
<td rowspan="2" width="35%">z powodu</td>
|
||||
</tr>
|
||||
|
||||
<tr class="tr-header">
|
||||
<td colspan="2">kilometra</td>
|
||||
</tr>
|
||||
|
||||
<tr v-for="(row, i) in order.orderList" :key="i" class="tr-data">
|
||||
<td>
|
||||
<textarea v-model="row.name"></textarea>
|
||||
</td>
|
||||
<td>
|
||||
<textarea v-model="row.from"></textarea>
|
||||
</td>
|
||||
<td>
|
||||
<textarea v-model="row.to"></textarea>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" v-model="row.vmax" />
|
||||
</td>
|
||||
<td>
|
||||
<input type="checkbox" v-model="row.jo" />
|
||||
</td>
|
||||
<td>
|
||||
<textarea v-model="row.reason"></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
|
||||
<div class="order_other">
|
||||
<span><b>2.</b> Inne:</span>
|
||||
<br />
|
||||
<textarea class="others" cols="30" rows="10" v-model="order.other"></textarea>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, reactive } from 'vue';
|
||||
import { useStore } from '../../store/store';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'OrderO',
|
||||
|
||||
setup() {
|
||||
const store = useStore();
|
||||
const order = reactive(store.orderO);
|
||||
|
||||
const rowMethods = [
|
||||
() => {
|
||||
const { header } = order;
|
||||
|
||||
return `\n<i><b>Rozkaz pisemny "O" nr ${header.orderNo || '_'}</b> dla pociągu nr ${
|
||||
header.trainNo || '_'
|
||||
} dnia ${header.date || '_'}</i>`;
|
||||
}
|
||||
];
|
||||
|
||||
return {
|
||||
store,
|
||||
order,
|
||||
rowMethods
|
||||
};
|
||||
},
|
||||
|
||||
activated() {
|
||||
this.generateMessage();
|
||||
},
|
||||
|
||||
watch: {
|
||||
order: {
|
||||
deep: true,
|
||||
handler() {
|
||||
this.generateMessage();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
generateMessage() {
|
||||
let message = this.rowMethods[0]();
|
||||
|
||||
if (this.order.orderList.some((row) => row.name)) {
|
||||
message += `\n--------\n<b>[ 1 ]</b>`;
|
||||
message += '\n1) zmniejszyć prędkość jazdy i zachować ostrożność';
|
||||
message += '\n2) jechać ostrożnie (j.o.)\n';
|
||||
}
|
||||
|
||||
for (let i = 0; i < this.order.orderList.length; i++) {
|
||||
const row = this.order.orderList[i];
|
||||
if (!row.name) continue;
|
||||
|
||||
message += `\n- ${row.name || '_'} od ${row.from || '_'} do ${row.to || '_'} kilometra`;
|
||||
|
||||
if (row.vmax) message += ` prędkość najwyżej ${row.vmax} km/h`;
|
||||
if (row.jo) message += ` jechać ostrożnie`;
|
||||
|
||||
message += ` z powodu: ${row.reason || '_'}`;
|
||||
}
|
||||
|
||||
if (this.order.other) message += `\n--------\n<b>[ 2 ]</b> Inne: ${this.order.other}`;
|
||||
|
||||
this.store.orderMessage = message;
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
table,
|
||||
td,
|
||||
th {
|
||||
border: 2px solid black;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.order_header {
|
||||
padding: 0.5em 0;
|
||||
}
|
||||
|
||||
.order_table {
|
||||
.tr-header td {
|
||||
padding: 1em 0.5em;
|
||||
}
|
||||
|
||||
.tr-data td {
|
||||
padding: 0.5em 0;
|
||||
}
|
||||
|
||||
tbody {
|
||||
font-weight: normal;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
input {
|
||||
width: 80%;
|
||||
}
|
||||
}
|
||||
|
||||
.order_table {
|
||||
textarea {
|
||||
width: 90%;
|
||||
min-height: 50px;
|
||||
resize: vertical;
|
||||
}
|
||||
}
|
||||
|
||||
.order_other {
|
||||
border-left: 2px solid black;
|
||||
border-right: 2px solid black;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
padding: 0.5em;
|
||||
}
|
||||
</style>
|
||||
@@ -1,450 +0,0 @@
|
||||
<template>
|
||||
<section class="order-s">
|
||||
<section class="order_header">
|
||||
<h2 class="flex-center">
|
||||
Rozkaz pisemny "S" nr
|
||||
<input type="number" v-model="order.header.orderNo" placeholder="nr rozkazu" min="1" />
|
||||
</h2>
|
||||
<div class="flex-row">
|
||||
dla
|
||||
<select id="select-header" v-model="order.header.for">
|
||||
<option value="pociągu">pociągu</option>
|
||||
<option value="manewru">manewru</option>
|
||||
</select>
|
||||
nr
|
||||
<input type="text" v-model="order.header.trainNo" :placeholder="`nr ${order.header.for}`" />
|
||||
dnia
|
||||
<input type="text" v-model="order.header.date" placeholder="data" />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="order_table-container">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="row-enabled-1">1</label>
|
||||
<div>
|
||||
<input
|
||||
type="checkbox"
|
||||
id="row-enabled-1"
|
||||
v-model="order.rows[0].enabled"
|
||||
@change="handleRowCheckboxChange(1)"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
<td ref="row-1">
|
||||
zezwalam po otrzymaniu
|
||||
<select id="select-1a" v-model="order.rows[0].option1">
|
||||
<option :value="`sygnału "nakaz jazdy"`">sygnału "nakaz jazdy"</option>
|
||||
<option value="tylko tego rozkazu pisemnego">tylko tego rozkazu pisemnego</option>
|
||||
</select>
|
||||
<div style="margin-top: 0.5rem">
|
||||
<input
|
||||
type="radio"
|
||||
name="section-1a"
|
||||
id="radio-1a-1"
|
||||
value="radio-1a-1"
|
||||
v-model="order.rows[0].radio1"
|
||||
@change="handleRowCheckboxChange(1)"
|
||||
/>
|
||||
<label for="radio-1a-1">
|
||||
przejechać obok wskazującego sygnał "Stój" semafora
|
||||
<select id="select-signal" v-model="order.rows[0].optionSignal">
|
||||
<option value="wyjazdowego">wyjazdowego</option>
|
||||
<option value="drogowskazowego">drogowskazowego</option>
|
||||
</select>
|
||||
<input
|
||||
type="text"
|
||||
v-model="order.rows[0].signal1"
|
||||
holder="nazwa sem."
|
||||
:radio-checked="order.rows[0].radio1 == 'radio-1a-1'"
|
||||
/>
|
||||
<span v-if="order.rows[0].optionSignal == 'drogowskazowego'">
|
||||
(odnoszącego się do wyjazdu pociągu)</span
|
||||
>
|
||||
<br />
|
||||
</label>
|
||||
<hr />
|
||||
<input
|
||||
type="radio"
|
||||
name="section-1a"
|
||||
id="radio-1a-2"
|
||||
value="radio-1a-2"
|
||||
v-model="order.rows[0].radio1"
|
||||
@change="handleRowCheckboxChange(1)"
|
||||
/>
|
||||
<label for="radio-1a-2">
|
||||
wyjechać z toru nr
|
||||
<input
|
||||
type="text"
|
||||
v-model="order.rows[0].trackNo"
|
||||
holder="nr toru"
|
||||
:radio-checked="order.rows[0].radio1 == 'radio-1a-2'"
|
||||
/>
|
||||
nie posiadającego semafora wyjazdowego
|
||||
</label>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="row-enabled-2">2</label>
|
||||
<div>
|
||||
<input
|
||||
type="checkbox"
|
||||
id="row-enabled-2"
|
||||
v-model="order.rows[1].enabled"
|
||||
@change="handleRowCheckboxChange(2)"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
<td ref="row-2">
|
||||
zezwalam przejechać obok wskazującego sygnał "Stój" semafora:
|
||||
<div>
|
||||
<input
|
||||
type="radio"
|
||||
name="section-2a"
|
||||
id="radio-2a-1"
|
||||
value="wyjazdowego"
|
||||
@change="handleRowCheckboxChange(2)"
|
||||
v-model="order.rows[1].signalType"
|
||||
/>
|
||||
<label for="radio-2a-1">
|
||||
wjazdowego
|
||||
<input
|
||||
type="text"
|
||||
v-model="order.rows[1].signal1"
|
||||
holder="nazwa sem."
|
||||
:radio-checked="order.rows[1].signalType == 'wyjazdowego'"
|
||||
/>
|
||||
</label>
|
||||
<br />
|
||||
<input
|
||||
type="radio"
|
||||
name="section-2a"
|
||||
id="radio-2a-2"
|
||||
value="drogowskazowego"
|
||||
@change="handleRowCheckboxChange(2)"
|
||||
v-model="order.rows[1].signalType"
|
||||
/>
|
||||
<label for="radio-2a-2">
|
||||
drogowskazowego
|
||||
<input
|
||||
type="text"
|
||||
v-model="order.rows[1].signal2"
|
||||
holder="nazwa sem."
|
||||
:radio-checked="order.rows[1].signalType == 'drogowskazowego'"
|
||||
/>
|
||||
(odnoszącego się do wjazdu pociągu)
|
||||
</label>
|
||||
<br />
|
||||
<input
|
||||
type="radio"
|
||||
name="section-2a"
|
||||
id="radio-2a-3"
|
||||
value="odstępowego"
|
||||
@change="handleRowCheckboxChange(2)"
|
||||
v-model="order.rows[1].signalType"
|
||||
/>
|
||||
<label for="radio-2a-3">
|
||||
odstępowego
|
||||
<input
|
||||
type="text"
|
||||
v-model="order.rows[1].signal3"
|
||||
holder="nazwa sem."
|
||||
:radio-checked="order.rows[1].signalType == 'odstępowego'"
|
||||
/></label>
|
||||
<br />
|
||||
<input
|
||||
type="radio"
|
||||
name="section-2a"
|
||||
id="radio-2a-4"
|
||||
value="toru"
|
||||
v-model="order.rows[1].signalType"
|
||||
@change="handleRowCheckboxChange(2)"
|
||||
/>
|
||||
<label for="radio-2a-4">
|
||||
wjechać z zamkniętego toru nr
|
||||
<input
|
||||
type="text"
|
||||
v-model="order.rows[1].trackNo"
|
||||
holder="nr toru"
|
||||
:radio-checked="order.rows[1].signalType == 'toru'"
|
||||
/>
|
||||
nie posiadającego semafora wjazdowego
|
||||
</label>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="row-enabled-3">3</label>
|
||||
<div>
|
||||
<input
|
||||
type="checkbox"
|
||||
id="row-enabled-3"
|
||||
v-model="order.rows[2].enabled"
|
||||
@change="handleRowCheckboxChange(3)"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
<td ref="row-3">
|
||||
Od
|
||||
<input type="text" v-model="order.rows[2].from" holder="stacja / post." />
|
||||
do
|
||||
<input type="text" v-model="order.rows[2].to" holder="stacja / post." />
|
||||
po torze nr
|
||||
<input type="text" v-model="order.rows[2].trackNo" holder="nr toru" />
|
||||
ruch pociągów prowadzony jest w odstępie posterunków następczych. Wskazania semaforów
|
||||
sbl są nieważne. Zachować ostrożność od ostatniego semafora ze wskaźnikiem "W18".
|
||||
Szlak wolny, ostatni pociąg nr
|
||||
<input type="text" v-model="order.rows[2].trainNo" holder="nr pociągu" />
|
||||
przybył do
|
||||
<input type="text" v-model="order.rows[2].arrivedTo" holder="stacja / post." />
|
||||
o godzinie
|
||||
<input type="text" v-model="order.rows[2].hour" holder="godzina" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr style="height: 270px">
|
||||
<td>
|
||||
<label for="row-enabled-4">4</label>
|
||||
<div>
|
||||
<input
|
||||
type="checkbox"
|
||||
id="row-enabled-4"
|
||||
v-model="order.rows[3].enabled"
|
||||
@change="handleRowCheckboxChange(4)"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
<td ref="row-4">
|
||||
<button
|
||||
class="g-button text"
|
||||
@click="order.rows[3].w5.enabled = !order.rows[3].w5.enabled"
|
||||
>
|
||||
>
|
||||
<span v-if="!order.rows[3].w5.enabled"
|
||||
>Wygeneruj treść na pominięcie wskaźnika W5</span
|
||||
>
|
||||
<span v-else>Wpisz treść własnoręcznie</span>
|
||||
</button>
|
||||
|
||||
<div>Inne:</div>
|
||||
<div v-if="order.rows[3].w5.enabled">
|
||||
zezwalam na wyjazd poza
|
||||
<select id="select-borderType" v-model="order.rows[3].w5.borderType">
|
||||
<option value="wskaźnik przetaczania W5">wskaźnik przetaczania W5</option>
|
||||
<option value="granicę przetaczania">granicę przetaczania</option>
|
||||
</select>
|
||||
po torze szlakowym nr
|
||||
<input type="text" v-model="order.rows[3].w5.trackNo" holder="nr szlaku" />
|
||||
do kilometra
|
||||
<input type="text" v-model="order.rows[3].w5.maxKm" holder="km szlaku" />. Powrót
|
||||
odbędzie się na
|
||||
<select
|
||||
id="select-returnWay"
|
||||
v-model="order.rows[3].w5.returnWay"
|
||||
style="width: 250px"
|
||||
>
|
||||
<option :value="`sygnał ręczny "Do mnie"`">
|
||||
sygnał ręczny "Do mnie"
|
||||
</option>
|
||||
<option
|
||||
:value="`sygnał "Do mnie" przekazany przez urządzenia radiołączności`"
|
||||
>
|
||||
sygnał "Do mnie" przekazany przez urządzenia radiołączności
|
||||
</option>
|
||||
<option value="sygnał Ms2 podany na tarczy manewrowej">
|
||||
sygnał Ms2 podany na tarczy manewrowej
|
||||
</option>
|
||||
</select>
|
||||
<input
|
||||
type="text"
|
||||
v-model="order.rows[3].w5.tmName"
|
||||
holder="nazwa tarczy"
|
||||
v-if="order.rows[3].w5.returnWay.includes('tarczy')"
|
||||
/>
|
||||
do godziny
|
||||
<input type="text" v-model="order.rows[3].w5.maxHour" holder="godzina" />
|
||||
</div>
|
||||
|
||||
<textarea
|
||||
v-else
|
||||
class="others"
|
||||
cols="30"
|
||||
rows="10"
|
||||
v-model="order.rows[3].content"
|
||||
></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, reactive } from 'vue';
|
||||
import { handleOrderPlaceholders } from '../../handlers/orderPlaceholderHandler';
|
||||
import { useStore } from '../../store/store';
|
||||
|
||||
type TOrderRows = 1 | 2 | 3 | 4;
|
||||
|
||||
export default defineComponent({
|
||||
name: 'OrderS',
|
||||
|
||||
setup() {
|
||||
const store = useStore();
|
||||
const order = reactive(store.orderS);
|
||||
|
||||
const rowMethods = [
|
||||
() => {
|
||||
const { header } = order;
|
||||
|
||||
return `\n<i><b>Rozkaz pisemny "S" nr ${header.orderNo || '_'}</b> dla ${header.for || '_'} nr ${
|
||||
header.trainNo || '_'
|
||||
} dnia ${header.date || '_'}</i>`;
|
||||
},
|
||||
|
||||
() => {
|
||||
const row = order.rows[0];
|
||||
|
||||
let message = `zezwalam po otrzymaniu ${row.option1 || '_'}`;
|
||||
|
||||
if (row.radio1 == 'radio-1a-1')
|
||||
message += ` przejechać obok wskazującego sygnał "Stój" semafora ${
|
||||
row.optionSignal || '_'
|
||||
} ${row.signal1 || '_'}${row.optionSignal == 'drogowskazowego' ? ' (odnoszącego się do wyjazdu pociągu)' : ''}`;
|
||||
else
|
||||
message += ` wyjechać z toru nr ${
|
||||
row.trackNo || '_'
|
||||
} nie posiadającego semafora wyjazdowego`;
|
||||
|
||||
return message;
|
||||
},
|
||||
|
||||
() => {
|
||||
const row = order.rows[1];
|
||||
|
||||
let message = `zezwalam przejechać obok wskazującego sygnał "Stój" semafora `;
|
||||
|
||||
switch (row.signalType) {
|
||||
case 'wyjazdowego':
|
||||
message += `wjazdowego ${row.signal1 || '_'}`;
|
||||
break;
|
||||
case 'drogowskazowego':
|
||||
message += `drogowskazowego ${row.signal2 || '_'} (odnoszącego się do wjazdu pociągu)`;
|
||||
break;
|
||||
case 'odstępowego':
|
||||
message += `odstępowego ${row.signal3 || '_'}`;
|
||||
break;
|
||||
case 'toru':
|
||||
message += `wjechać z zamkniętego toru nr ${
|
||||
row.trackNo || '_'
|
||||
} nie posiadającego semafora wjazdowego`;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return message;
|
||||
},
|
||||
() => {
|
||||
const row = order.rows[2];
|
||||
|
||||
return `Od ${row.from || '_'} do ${row.to || '_'} po torze nr ${
|
||||
row.trackNo || '_'
|
||||
} ruch pociągów prowadzony jest w odstępie posterunków następczych. Wskazania semaforów sbl są nieważne. Zachować ostrożność od ostatniego semafora ze wskaźnikiem "W18". Szlak wolny, ostatni pociąg nr ${
|
||||
row.trainNo || '_'
|
||||
} przybył do ${row.arrivedTo || '_'} o godzinie ${row.hour || '_'}`;
|
||||
},
|
||||
|
||||
() => {
|
||||
const row = order.rows[3];
|
||||
|
||||
if (row.w5.enabled) {
|
||||
const { borderType, trackNo, maxHour, maxKm, returnWay, tmName } = row.w5;
|
||||
const textArray = [];
|
||||
|
||||
textArray.push(
|
||||
'Inne: zezwalam na wyjazd poza',
|
||||
borderType || '_',
|
||||
'po torze szlakowym nr',
|
||||
trackNo || '_'
|
||||
);
|
||||
if (maxKm) textArray.push(`do kilometra ${maxKm}`);
|
||||
textArray.push('.');
|
||||
textArray.push('Powrót odbędzie się na', returnWay || '_');
|
||||
if (returnWay.includes('tarczy')) textArray.push(tmName || '_');
|
||||
textArray.push(`do godziny ${maxHour || '_'}`);
|
||||
|
||||
return textArray.join(' ').replace(/ \./, '.');
|
||||
}
|
||||
|
||||
return `Inne: ${row.content}`;
|
||||
}
|
||||
];
|
||||
|
||||
return {
|
||||
store,
|
||||
order,
|
||||
rowMethods
|
||||
};
|
||||
},
|
||||
|
||||
activated() {
|
||||
this.generateMessage();
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.updatePlaceholders();
|
||||
},
|
||||
|
||||
watch: {
|
||||
order: {
|
||||
deep: true,
|
||||
handler() {
|
||||
this.generateMessage();
|
||||
}
|
||||
},
|
||||
|
||||
'order.rows': {
|
||||
deep: true,
|
||||
handler() {
|
||||
this.updatePlaceholders();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
updatePlaceholders() {
|
||||
this.order.rows.forEach((_, i) => {
|
||||
this.handleRowCheckboxChange((i + 1) as TOrderRows);
|
||||
});
|
||||
},
|
||||
|
||||
generateMessage() {
|
||||
let message = this.rowMethods[0]();
|
||||
|
||||
for (let i = 0; i < 4; i++) {
|
||||
if (!this.order.rows[i].enabled) continue;
|
||||
|
||||
message += `\n--------\n<b>[ ${i + 1} ]</b> ${this.rowMethods[i + 1]()}`;
|
||||
}
|
||||
|
||||
this.store.orderMessage = message;
|
||||
},
|
||||
|
||||
handleRowCheckboxChange(rowIndex: TOrderRows) {
|
||||
const isRowEnabled = this.order.rows[rowIndex - 1].enabled;
|
||||
const rowRef = this.$refs[`row-${rowIndex}`] as HTMLTableElement;
|
||||
|
||||
this.$nextTick(() => {
|
||||
handleOrderPlaceholders(isRowEnabled, rowRef);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@@ -1,144 +0,0 @@
|
||||
<template>
|
||||
<section class="sidebar">
|
||||
<div class="sidebar_content">
|
||||
<!-- <button class="option-save" @click="toggleOrderMode" :data-selected="store.orderMode == 'OrderList'">
|
||||
<img :src="saveIcon" alt="save icon" />
|
||||
</button> -->
|
||||
|
||||
<!-- <button @click="store.helperModalOpen = true">?</button> -->
|
||||
|
||||
<button
|
||||
v-for="orderType in orderTypeList"
|
||||
:key="orderType.id"
|
||||
@click="selectOrderType(orderType.id)"
|
||||
:data-selected="store.chosenOrderType == orderType.id"
|
||||
>
|
||||
{{ orderType.name }}
|
||||
|
||||
<div class="bar"></div>
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { useStore } from '../../store/store';
|
||||
|
||||
export default defineComponent({
|
||||
data() {
|
||||
return {
|
||||
orderTypeList: [
|
||||
{
|
||||
id: 'orderN',
|
||||
name: 'N'
|
||||
},
|
||||
{
|
||||
id: 'orderS',
|
||||
name: 'S'
|
||||
},
|
||||
{
|
||||
id: 'orderO',
|
||||
name: 'O'
|
||||
}
|
||||
]
|
||||
};
|
||||
},
|
||||
setup() {
|
||||
return {
|
||||
store: useStore()
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
selectOrderType(type: any) {
|
||||
if (type != this.store.chosenOrderType) this.store.chosenLocalOrderId = '';
|
||||
|
||||
this.store.chosenOrderType = type;
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use '../../styles/colors';
|
||||
|
||||
.sidebar_content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.25em;
|
||||
|
||||
font-size: 1.5em;
|
||||
font-weight: bold;
|
||||
height: 100%;
|
||||
|
||||
& > button {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
color: white;
|
||||
background-color: colors.$bgColDarker;
|
||||
width: 50px;
|
||||
height: 85px;
|
||||
|
||||
.bar {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
|
||||
height: 100%;
|
||||
width: 4px;
|
||||
|
||||
transform: translateX(100%);
|
||||
transition: all 200ms ease-in-out;
|
||||
}
|
||||
|
||||
&[data-selected='true'] .bar {
|
||||
transform: translateX(0);
|
||||
|
||||
background-color: colors.$accentCol;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
background-color: #6d6d6d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
button.option-save {
|
||||
background-color: #000000aa;
|
||||
|
||||
img {
|
||||
width: 80%;
|
||||
height: 80%;
|
||||
}
|
||||
|
||||
&[data-selected='true'] {
|
||||
background-color: colors.$accentCol;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1150px) {
|
||||
.sidebar_content {
|
||||
flex-direction: row;
|
||||
|
||||
& > button {
|
||||
height: 40px;
|
||||
width: 100px;
|
||||
|
||||
.bar {
|
||||
width: 100%;
|
||||
height: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,10 +1,10 @@
|
||||
<template>
|
||||
<section class="order-list">
|
||||
<h3>{{ $t('order-list.title') }} ({{ localOrderList.length }})</h3>
|
||||
<h3>{{ t('order-list.title') }} ({{ storageOrderList.length }})</h3>
|
||||
|
||||
<transition-group name="list" tag="ul">
|
||||
<li class="no-orders-warning" v-if="sortedOrderList.length == 0" :key="-1">
|
||||
{{ $t('order-list.no-saved-orders') }}
|
||||
{{ t('order-list.no-saved-orders') }}
|
||||
</li>
|
||||
|
||||
<li
|
||||
@@ -12,13 +12,11 @@
|
||||
:selected="order.id == store.chosenLocalOrderId"
|
||||
:key="order.id"
|
||||
>
|
||||
<b class="text--accent">#{{ order.id.split('-')[1] }} </b>
|
||||
<b class="text--accent">#{{ order.id.split('-')[2] }} </b>
|
||||
<b>
|
||||
{{
|
||||
$t('order-list.order-title', {
|
||||
orderName: getOrderName(order.orderType),
|
||||
orderNo: order.orderBody['header']['orderNo'],
|
||||
trainNo: order.orderBody['header']['trainNo']
|
||||
t('order-list.order-title', {
|
||||
trainNo: order.orderData.header.A
|
||||
})
|
||||
}}
|
||||
</b>
|
||||
@@ -26,21 +24,34 @@
|
||||
v-if="!order.orderVersion || order.orderVersion != ORDER_VERSION"
|
||||
class="wrong-order-indicator"
|
||||
tabindex="0"
|
||||
data-tooltip="Przestarzała wersja rozkazu! Może generować złe informacje!"
|
||||
:data-tooltip="t('order-list.warning-deprecated-version')"
|
||||
>⚠
|
||||
</span>
|
||||
<br />
|
||||
{{ $t(`order-list.order-${order.createdAt ? 'added' : 'updated'}`) }}
|
||||
|
||||
<div>
|
||||
{{
|
||||
t('order-list.order-subtitle', [
|
||||
order.orderData.instructions
|
||||
.filter((v) => v.active)
|
||||
.map((v) => v.name)
|
||||
.join(', ')
|
||||
])
|
||||
}}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{{ t(`order-list.order-${order.createdAt ? 'added' : 'updated'}`) }}
|
||||
{{ new Date(order.createdAt || order.updatedAt || 0).toLocaleString('pl-PL') }}
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="buttons">
|
||||
<button class="g-button" @click="selectLocalOrder(order)">
|
||||
{{ $t('order-list.button-order-select') }}
|
||||
{{ t('order-list.button-order-select') }}
|
||||
</button>
|
||||
<button class="g-button" @click="removeOrder(order)">
|
||||
{{ $t('order-list.button-order-remove') }}
|
||||
<button class="g-button" @click="removeOrder(order.id)">
|
||||
{{ t('order-list.button-order-remove') }}
|
||||
</button>
|
||||
</div>
|
||||
</li>
|
||||
@@ -48,67 +59,89 @@
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import orderStorageMixin from '../../mixins/orderStorageMixin';
|
||||
<script lang="ts" setup>
|
||||
import { computed, onActivated, onMounted, Reactive, reactive } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useStore } from '../../store/store';
|
||||
import { LocalStorageOrder } from '../../types/orderTypes';
|
||||
import { IStorageOrderData, LocalStorageOrderLegacy } from '../../types/orderTypes';
|
||||
import StorageManager from '../../managers/storageManager';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'OrderList',
|
||||
mixins: [orderStorageMixin],
|
||||
const { t } = useI18n();
|
||||
const store = useStore();
|
||||
const storageOrderList = reactive<Reactive<IStorageOrderData[]>>([]);
|
||||
|
||||
data() {
|
||||
return {
|
||||
localOrderList: [] as LocalStorageOrder[],
|
||||
ORDER_VERSION: import.meta.env['VITE_APP_ORDER_VERSION']
|
||||
};
|
||||
},
|
||||
const ORDER_VERSION = import.meta.env['VITE_APP_ORDER_VERSION'];
|
||||
|
||||
setup() {
|
||||
return {
|
||||
store: useStore(),
|
||||
localStorage: window.localStorage
|
||||
};
|
||||
},
|
||||
function removeOrder(orderId: string) {
|
||||
StorageManager.removeValue(orderId);
|
||||
|
||||
methods: {
|
||||
getOrderName(orderType: string) {
|
||||
return orderType.split('order')[1];
|
||||
},
|
||||
if (store.chosenLocalOrderId == orderId) store.chosenLocalOrderId = '';
|
||||
|
||||
removeOrder(order: LocalStorageOrder) {
|
||||
if (!order) return;
|
||||
const orderIndex = storageOrderList.findIndex((o) => o.id == orderId);
|
||||
if (orderIndex != -1) storageOrderList.splice(orderIndex, 1);
|
||||
|
||||
this.removeLocalOrder(order);
|
||||
this.localOrderList = this.localOrderList.filter((o) => o.id != order.id);
|
||||
if (storageOrderList.length == 0) StorageManager.setNumericValue('orderCountV3', 0);
|
||||
}
|
||||
|
||||
if (this.localOrderList.length == 0) this.saveOrderSetting('orderCount', 0);
|
||||
}
|
||||
},
|
||||
function selectLocalOrder(order: IStorageOrderData) {
|
||||
Object.entries(order.orderData.header).forEach(([k, v]) => {
|
||||
(store.orderData['header'] as any)[k] = v;
|
||||
});
|
||||
|
||||
computed: {
|
||||
sortedOrderList() {
|
||||
return this.localOrderList
|
||||
Object.entries(order.orderData.footer).forEach(([k, v]) => {
|
||||
(store.orderData['footer'] as any)[k] = v;
|
||||
});
|
||||
|
||||
Object.entries(order.orderData.instructions).forEach(([k, v]) => {
|
||||
(store.orderData['instructions'] as any)[k] = v;
|
||||
});
|
||||
|
||||
store.panelMode = 'OrderMessagePanel';
|
||||
store.chosenLocalOrderId = order.id;
|
||||
}
|
||||
|
||||
function isOrderDeprecated(
|
||||
order: IStorageOrderData | LocalStorageOrderLegacy
|
||||
): order is LocalStorageOrderLegacy {
|
||||
return 'orderType' in order;
|
||||
}
|
||||
|
||||
const sortedOrderList = computed(() => {
|
||||
return storageOrderList
|
||||
.slice()
|
||||
.sort((a, b) => (b.createdAt || b.updatedAt!) - (a.createdAt || a.updatedAt!));
|
||||
}
|
||||
},
|
||||
.sort((a, b) => (b.createdAt || b.updatedAt || 0) - (a.createdAt || a.updatedAt || 0));
|
||||
});
|
||||
|
||||
activated() {
|
||||
onActivated(() => {
|
||||
const localStorage = window.localStorage;
|
||||
const orderList = [];
|
||||
const orderList: IStorageOrderData[] = [];
|
||||
|
||||
let deprecatedOrders: string[] = [];
|
||||
for (let key in localStorage) {
|
||||
if (!/^order-/g.test(key)) continue;
|
||||
|
||||
const orderObj: LocalStorageOrder = JSON.parse(localStorage[key]);
|
||||
const orderObj: IStorageOrderData | LocalStorageOrderLegacy = JSON.parse(localStorage[key]);
|
||||
if (!orderObj) continue;
|
||||
|
||||
if (isOrderDeprecated(orderObj)) {
|
||||
console.warn(`Deprecated order found with ID: ${orderObj.id}`);
|
||||
deprecatedOrders.push(key);
|
||||
continue;
|
||||
}
|
||||
|
||||
orderList.push(orderObj);
|
||||
}
|
||||
|
||||
this.localOrderList = orderList;
|
||||
storageOrderList.length = 0;
|
||||
storageOrderList.push(...orderList);
|
||||
|
||||
if (deprecatedOrders.length > 0) {
|
||||
window.alert(
|
||||
t('order-list.warning-removed-deprecated-orders', { count: deprecatedOrders.length })
|
||||
);
|
||||
|
||||
deprecatedOrders.forEach((orderKey) => StorageManager.removeValue(orderKey));
|
||||
StorageManager.removeValue('orderCount');
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@@ -130,6 +163,7 @@ export default defineComponent({
|
||||
|
||||
&-leave-active {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,6 +178,7 @@ hr {
|
||||
|
||||
ul {
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
h3 {
|
||||
|
||||
@@ -25,8 +25,8 @@
|
||||
>
|
||||
<LucidePencil />
|
||||
{{ $t('order-message.button-update') }}
|
||||
<span class="text--accent" v-if="store.chosenLocalOrderId"
|
||||
>#{{ store.chosenLocalOrderId.split('-')[1] }}
|
||||
<span class="text--accent">
|
||||
{{ store.chosenLocalOrderId && `#${store.chosenLocalOrderId.split('-')[2]}` }}
|
||||
</span>
|
||||
</button>
|
||||
|
||||
@@ -72,191 +72,346 @@
|
||||
</div>
|
||||
|
||||
<transition name="monit-anim">
|
||||
<div class="action_monit" v-if="actionMonit" v-html="actionMonit"></div>
|
||||
<div
|
||||
class="action_monit"
|
||||
v-if="actionMonit.content"
|
||||
v-html="actionMonit.content"
|
||||
:class="{
|
||||
'text--warn': actionMonit.type == 'warning'
|
||||
}"
|
||||
></div>
|
||||
</transition>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import orderStorageMixin from '../../mixins/orderStorageMixin';
|
||||
import orderValidationMixin from '../../mixins/orderValidationMixin';
|
||||
import { useStore } from '../../store/store';
|
||||
import { currentFormattedHours, currentFormattedMinutes } from '../../utils/dateUtils';
|
||||
<script lang="ts" setup>
|
||||
import { computed, onMounted, Reactive, reactive, ref, watch } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
import { LucideCopy, LucidePencil, LucideRotateCcw, LucideSave } from 'lucide-vue-next';
|
||||
import { setOrderToDefault } from '../../utils/orderUtils';
|
||||
import { useStore } from '../../store/store';
|
||||
import { IOrderHeader, IOrderFooter, IStorageOrderData } from '../../types/orderTypes';
|
||||
import StorageManager from '../../managers/storageManager';
|
||||
import { getOrderFullId } from '../../utils/orderUtils';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'OrderMessage',
|
||||
components: { LucideCopy, LucidePencil, LucideRotateCcw, LucideSave },
|
||||
type TActionMonitType = 'warning' | 'info' | 'success';
|
||||
|
||||
mixins: [orderStorageMixin, orderValidationMixin],
|
||||
interface IActionMonit {
|
||||
type: TActionMonitType;
|
||||
content: string;
|
||||
timeoutId: number | null;
|
||||
}
|
||||
|
||||
data() {
|
||||
return {
|
||||
actionMonit: '',
|
||||
monitTimeout: null as number | null,
|
||||
const { t } = useI18n();
|
||||
const store = useStore();
|
||||
|
||||
incrementOnSave: true,
|
||||
incrementOnCopy: true,
|
||||
updateDate: true
|
||||
};
|
||||
},
|
||||
const actionMonit: Reactive<IActionMonit> = reactive({
|
||||
visible: false,
|
||||
type: 'info',
|
||||
content: '',
|
||||
timeoutId: null
|
||||
});
|
||||
|
||||
setup() {
|
||||
return {
|
||||
store: useStore()
|
||||
};
|
||||
},
|
||||
const incrementOnSave = ref(true);
|
||||
const incrementOnCopy = ref(true);
|
||||
const updateDate = ref(true);
|
||||
|
||||
mounted() {
|
||||
this.incrementOnSave = this.getOrderSetting('save-increment') !== 'false';
|
||||
this.incrementOnCopy = this.getOrderSetting('copy-increment') !== 'false';
|
||||
this.updateDate = this.getOrderSetting('update-date') !== 'false';
|
||||
},
|
||||
onMounted(() => {
|
||||
incrementOnSave.value = StorageManager.getBooleanValue('save-increment');
|
||||
incrementOnCopy.value = StorageManager.getBooleanValue('copy-increment');
|
||||
updateDate.value = StorageManager.getBooleanValue('update-date');
|
||||
});
|
||||
|
||||
computed: {
|
||||
fullOrderMessage() {
|
||||
return this.store.orderMessage + this.store.footerMessage;
|
||||
},
|
||||
const orderMessagePreview = computed(() => store.orderMessage);
|
||||
|
||||
// Replace all new line tags with <br> for preview and get rid of the first one (visible only on simulator's chat)
|
||||
orderMessagePreview() {
|
||||
return this.fullOrderMessage.replace(/\n/g, '<br>').replace('<br>', '');
|
||||
}
|
||||
},
|
||||
watch(orderMessagePreview, () => {
|
||||
if (updateDate.value == true) {
|
||||
store.orderData.header.B = new Date().toISOString().split('T')[0];
|
||||
|
||||
watch: {
|
||||
fullOrderMessage() {
|
||||
if (this.updateDate) {
|
||||
this.store.orderFooter['hour'] = currentFormattedHours();
|
||||
this.store.orderFooter['minutes'] = currentFormattedMinutes();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
onCheckboxChange(e: Event) {
|
||||
const checkbox = e.target as HTMLInputElement;
|
||||
this.saveOrderSetting(checkbox.id, checkbox.checked);
|
||||
},
|
||||
|
||||
showActionMonit(text: string) {
|
||||
if (this.monitTimeout != null) {
|
||||
this.actionMonit = '';
|
||||
clearTimeout(this.monitTimeout);
|
||||
|
||||
setTimeout(() => {
|
||||
this.actionMonit = text;
|
||||
}, 100);
|
||||
} else {
|
||||
this.actionMonit = text;
|
||||
}
|
||||
|
||||
this.monitTimeout = window.setTimeout(() => {
|
||||
this.actionMonit = '';
|
||||
this.monitTimeout = null;
|
||||
}, 5000);
|
||||
},
|
||||
|
||||
incrementOrderNo() {
|
||||
const order = this.store[this.store.chosenOrderType];
|
||||
|
||||
order.header.orderNo = (Number(order.header.orderNo) + 1).toString();
|
||||
},
|
||||
|
||||
copyMessage() {
|
||||
if (!navigator.clipboard)
|
||||
return this.showActionMonit(this.$t('order-message.warning-outdated-clipboard'));
|
||||
|
||||
const hasAtLeastOneRow = /(\[ \d \])/g.test(this.fullOrderMessage);
|
||||
const hasAllInputsFilled = !/_/g.test(this.store.orderMessage);
|
||||
|
||||
if (!hasAllInputsFilled)
|
||||
return this.showActionMonit(
|
||||
`<span class="text--warn">${this.$t('order-message.warning-fill-inputs')}</span>`
|
||||
);
|
||||
if (!hasAtLeastOneRow)
|
||||
return this.showActionMonit(
|
||||
`<span class="text--warn">${this.$t('order-message.warning-add-rows')}</span>`
|
||||
);
|
||||
|
||||
const fieldsToCorrect = this.verifyOrderFields();
|
||||
|
||||
if (fieldsToCorrect.length > 0)
|
||||
return this.showActionMonit(
|
||||
`<span class="text--warn">${this.$t('order-message.warning-fill-footer')} ${fieldsToCorrect.join(
|
||||
', '
|
||||
)}</span>`
|
||||
);
|
||||
|
||||
navigator.clipboard.writeText(this.fullOrderMessage);
|
||||
|
||||
if (this.incrementOnCopy) this.incrementOrderNo();
|
||||
|
||||
this.showActionMonit(this.$t('order-message.success-copy-html'));
|
||||
},
|
||||
|
||||
saveOrder() {
|
||||
const savedOrderStatus = this.saveLocalOrder();
|
||||
|
||||
switch (savedOrderStatus) {
|
||||
case -1:
|
||||
this.showActionMonit(
|
||||
`<span class="text--warn">${this.$t('order-message.warning-fill-top')}</span>`
|
||||
);
|
||||
break;
|
||||
case 0:
|
||||
this.showActionMonit(
|
||||
`<span class="text--warn">${this.$t('order-message.warning-order-identical')}</span>`
|
||||
);
|
||||
break;
|
||||
case 1:
|
||||
this.showActionMonit(this.$t('order-message.success-save-html'));
|
||||
|
||||
if (this.incrementOnSave) this.incrementOrderNo();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
updateOrder() {
|
||||
const updatedOrderStatus = this.updateLocalOrder();
|
||||
|
||||
switch (updatedOrderStatus) {
|
||||
case -1:
|
||||
this.showActionMonit(
|
||||
`<span class="text--warn">${this.$t('order-message.error-update')}</span>`
|
||||
);
|
||||
break;
|
||||
|
||||
case 0:
|
||||
this.showActionMonit(
|
||||
`<span class="text--warn">${this.$t('order-message.warning-no-order-selected')}</span>`
|
||||
);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
this.showActionMonit(this.$t('order-message.success-update-html'));
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
resetOrder() {
|
||||
setOrderToDefault(this.store[this.store.chosenOrderType]);
|
||||
}
|
||||
store.orderData.footer.Y = new Date().toLocaleTimeString('pl-PL', {
|
||||
hour: 'numeric',
|
||||
minute: '2-digit'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
function onCheckboxChange(e: Event) {
|
||||
const checkbox = e.target as HTMLInputElement;
|
||||
StorageManager.setBooleanValue(checkbox.id, checkbox.checked);
|
||||
}
|
||||
|
||||
function showActionMonit(content: string, type: TActionMonitType) {
|
||||
if (actionMonit.timeoutId != null) {
|
||||
actionMonit.content = '';
|
||||
|
||||
clearTimeout(actionMonit.timeoutId);
|
||||
|
||||
setTimeout(() => {
|
||||
actionMonit.content = content;
|
||||
actionMonit.type = type;
|
||||
|
||||
actionMonit.timeoutId = window.setTimeout(() => {
|
||||
actionMonit.content = '';
|
||||
actionMonit.timeoutId = null;
|
||||
}, 5000);
|
||||
}, 100);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
actionMonit.content = content;
|
||||
actionMonit.type = type;
|
||||
|
||||
actionMonit.timeoutId = window.setTimeout(() => {
|
||||
actionMonit.content = '';
|
||||
actionMonit.timeoutId = null;
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
function checkConflicts() {
|
||||
if (
|
||||
store.orderData.instructions
|
||||
.filter((i) => i.key == '2110' || i.key == '2115')
|
||||
.every((i) => i.active)
|
||||
) {
|
||||
showActionMonit(
|
||||
t('order-message.warning-conflicting-instructions', ['21.10', '21.15']),
|
||||
'warning'
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function areOrderFieldsCorrect() {
|
||||
const fieldsToCorrect: string[] = [];
|
||||
|
||||
for (let headerKey in store.orderData.header) {
|
||||
if (store.orderData.header[headerKey as keyof IOrderHeader].trim() == '') {
|
||||
fieldsToCorrect.push(headerKey);
|
||||
}
|
||||
}
|
||||
|
||||
for (let footerKey in store.orderData.footer) {
|
||||
if (store.orderData.footer[footerKey as keyof IOrderFooter].trim() == '') {
|
||||
fieldsToCorrect.push(footerKey);
|
||||
}
|
||||
}
|
||||
|
||||
const areConflicting = checkConflicts();
|
||||
|
||||
if (areConflicting) return false;
|
||||
|
||||
// Header & footer fields check
|
||||
if (fieldsToCorrect.length > 0) {
|
||||
showActionMonit(t('order-message.warning-fill-missing'), 'warning');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Active instructions' fields check
|
||||
let hasAllInputsFilled = true,
|
||||
hasNoActiveInstructions = true;
|
||||
|
||||
for (const instructionKey in store.orderData.instructions) {
|
||||
const instruction = store.orderData.instructions[instructionKey];
|
||||
|
||||
if (!instruction.active) continue;
|
||||
|
||||
hasNoActiveInstructions = false;
|
||||
|
||||
for (const fieldKey in instruction.inputFields) {
|
||||
const fieldValue = instruction.inputFields[fieldKey];
|
||||
|
||||
if (fieldValue.trim() == '' && !instruction.optionalFieldNames.includes(fieldKey)) {
|
||||
hasAllInputsFilled = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (instruction.listFields) {
|
||||
let hasAtLeastOneActive = false;
|
||||
|
||||
for (const listFieldKey in instruction.listFields) {
|
||||
const listField = instruction.listFields[listFieldKey];
|
||||
|
||||
if (listField.active == false) continue;
|
||||
|
||||
hasAtLeastOneActive = true;
|
||||
|
||||
for (const fieldKey in listField.values) {
|
||||
const fieldValue = listField.values[fieldKey];
|
||||
|
||||
if (fieldValue.trim() == '') {
|
||||
hasAllInputsFilled = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasAtLeastOneActive) {
|
||||
hasAllInputsFilled = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Active instructions check
|
||||
if (hasNoActiveInstructions) {
|
||||
showActionMonit(t('order-message.warning-add-instruction'), 'warning');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!hasAllInputsFilled) {
|
||||
showActionMonit(t('order-message.warning-fill-inputs'), 'warning');
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function hasHeaderFieldsComplete() {
|
||||
return Object.values(store.orderData.header).every((v) => {
|
||||
return v.trim().length != 0;
|
||||
});
|
||||
}
|
||||
|
||||
function incrementOrderNo() {
|
||||
const idData = store.orderData.footer.Z.split('-');
|
||||
|
||||
if (idData.length == 4) {
|
||||
const sceneryHash = idData[2];
|
||||
let orderNumber = Number(idData[1]) || 0;
|
||||
|
||||
store.orderData.footer.Z = getOrderFullId(++orderNumber, sceneryHash);
|
||||
}
|
||||
}
|
||||
|
||||
function copyMessage() {
|
||||
if (!navigator.clipboard)
|
||||
return showActionMonit(t('order-message.warning-outdated-clipboard'), 'warning');
|
||||
|
||||
const areFieldsCorrect = areOrderFieldsCorrect();
|
||||
|
||||
if (!areFieldsCorrect) return;
|
||||
|
||||
const simulatorChatMessage = '\n' + orderMessagePreview.value.replace(/<br \/>/g, '\n');
|
||||
|
||||
navigator.clipboard.writeText(simulatorChatMessage);
|
||||
|
||||
if (incrementOnCopy.value) incrementOrderNo();
|
||||
|
||||
showActionMonit(t('order-message.success-copy-html'), 'success');
|
||||
}
|
||||
|
||||
function saveOrder() {
|
||||
if (!hasHeaderFieldsComplete()) {
|
||||
showActionMonit(`${t('order-message.warning-fill-top-save')}`, 'warning');
|
||||
return;
|
||||
}
|
||||
|
||||
const orderDataToSave: IStorageOrderData = {
|
||||
id: '',
|
||||
createdAt: Date.now(),
|
||||
orderVersion: import.meta.env['VITE_APP_ORDER_VERSION'] || '3',
|
||||
orderData: store.orderData
|
||||
};
|
||||
|
||||
const localOrderCount = StorageManager.getNumericValue('orderCountV3') || 0;
|
||||
|
||||
if (localOrderCount == 0) StorageManager.setNumericValue('orderCountV3', 0);
|
||||
|
||||
const prevLocalOrder = StorageManager.getValue(`order-v3-${localOrderCount}`);
|
||||
|
||||
if (prevLocalOrder) {
|
||||
try {
|
||||
const prevOrderObj = JSON.parse(prevLocalOrder) as IStorageOrderData;
|
||||
|
||||
if (JSON.stringify(prevOrderObj.orderData) == JSON.stringify(orderDataToSave.orderData)) {
|
||||
showActionMonit(t('order-message.warning-order-identical'), 'warning');
|
||||
return;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(
|
||||
`Ups! An error occured when trying to parse previous local order (count: ${localOrderCount})`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const nextOrderCount = localOrderCount + 1;
|
||||
const nextOrderId = `order-v3-${nextOrderCount}`;
|
||||
orderDataToSave['id'] = nextOrderId;
|
||||
|
||||
StorageManager.setNumericValue('orderCountV3', nextOrderCount);
|
||||
StorageManager.setValue(nextOrderId, JSON.stringify(orderDataToSave));
|
||||
|
||||
store.chosenLocalOrderId = nextOrderId;
|
||||
showActionMonit(t('order-message.success-save-html'), 'success');
|
||||
|
||||
if (incrementOnSave.value) incrementOrderNo();
|
||||
}
|
||||
|
||||
function updateOrder() {
|
||||
if (!store.chosenLocalOrderId) {
|
||||
showActionMonit(t('order-message.warning-no-order-selected'), 'warning');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!hasHeaderFieldsComplete()) {
|
||||
showActionMonit(t('order-message.warning-fill-top-update'), 'warning');
|
||||
return;
|
||||
}
|
||||
|
||||
const localOrder = window.localStorage.getItem(store.chosenLocalOrderId);
|
||||
|
||||
if (!localOrder) {
|
||||
showActionMonit(t('order-message.error-update'), 'warning');
|
||||
return;
|
||||
}
|
||||
|
||||
const orderDataToUpdate: IStorageOrderData = {
|
||||
id: store.chosenLocalOrderId,
|
||||
orderData: store.orderData,
|
||||
updatedAt: Date.now(),
|
||||
orderVersion: import.meta.env['VITE_APP_ORDER_VERSION'] || '3'
|
||||
};
|
||||
|
||||
window.localStorage.setItem(store.chosenLocalOrderId, JSON.stringify(orderDataToUpdate));
|
||||
showActionMonit(t('order-message.success-update-html'), 'success');
|
||||
}
|
||||
|
||||
function resetOrder() {
|
||||
Object.keys(store.orderData.header).forEach((k) => {
|
||||
store.orderData['header'][k as keyof IOrderHeader] = '';
|
||||
});
|
||||
|
||||
Object.keys(store.orderData.footer).forEach((k) => {
|
||||
store.orderData['footer'][k as keyof IOrderFooter] = '';
|
||||
});
|
||||
|
||||
store.orderData.instructions.forEach((instruction) => {
|
||||
instruction.active = false;
|
||||
|
||||
Object.keys(instruction.inputFields).forEach((k) => {
|
||||
instruction.inputFields[k] = '';
|
||||
});
|
||||
|
||||
if (instruction.listFields) {
|
||||
instruction.listFields.forEach((field) => {
|
||||
Object.keys(field.values).forEach((k) => {
|
||||
field.active = false;
|
||||
field.values[k] = '';
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use '../../styles/colors';
|
||||
|
||||
.order-message {
|
||||
overflow: auto;
|
||||
|
||||
h3 {
|
||||
margin: 0;
|
||||
margin-bottom: 1em;
|
||||
@@ -270,6 +425,7 @@ export default defineComponent({
|
||||
|
||||
.message_body {
|
||||
height: 350px;
|
||||
overflow: auto;
|
||||
|
||||
background-color: colors.$bgColLighter;
|
||||
color: white;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
name="dispatcher-select"
|
||||
id="dispatcher-select"
|
||||
v-model="selectedSceneryId"
|
||||
@change="selectOption"
|
||||
@change="selectCheckpointOption"
|
||||
>
|
||||
<option :value="null" disabled>
|
||||
{{ $t('order-train-picker.placeholder-scenery-name') }}
|
||||
@@ -24,7 +24,7 @@
|
||||
name="region-select"
|
||||
id="region-select"
|
||||
v-model="selectedRegion"
|
||||
@change="selectOption"
|
||||
@change="selectCheckpointOption"
|
||||
>
|
||||
<option :value="null" disabled>
|
||||
{{ $t('order-train-picker.placeholder-region-name') }}
|
||||
@@ -55,16 +55,6 @@
|
||||
{{ cp }}
|
||||
</option>
|
||||
</select>
|
||||
|
||||
<label for="fill-checkpoint" class="g-checkbox">
|
||||
<input
|
||||
type="checkbox"
|
||||
name="fill-checkpoint"
|
||||
id="fill-checkpoint"
|
||||
v-model="fillCheckpointName"
|
||||
/>
|
||||
<span> {{ $t('order-train-picker.autofill-checkpoint-id') }}</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
@@ -82,7 +72,7 @@
|
||||
<li
|
||||
v-for="train in sceneryTrains"
|
||||
:key="train.trainNo + train.driverName"
|
||||
@click="fillOrder(train.trainNo)"
|
||||
@click="fillOrderData(train)"
|
||||
>
|
||||
<button class="g-button">
|
||||
<span
|
||||
@@ -109,98 +99,83 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted, onActivated, onDeactivated, computed } from 'vue';
|
||||
import http from '../../http';
|
||||
import { useStore } from '../../store/store';
|
||||
import { API } from '../../types/apiTypes';
|
||||
import { ISceneryData } from '../../types/dataTypes';
|
||||
import {
|
||||
currentFormattedDate,
|
||||
currentFormattedHours,
|
||||
currentFormattedMinutes
|
||||
} from '../../utils/dateUtils';
|
||||
import StorageManager from '../../managers/storageManager';
|
||||
import { getRegionNameById } from '../../utils/sceneryUtils';
|
||||
import { getOrderFullId } from '../../utils/orderUtils';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'order-train-picker',
|
||||
const store = useStore();
|
||||
const regions = ['eu', 'cae', 'usw', 'us', 'ru'];
|
||||
const refreshInterval = ref(-1);
|
||||
|
||||
data() {
|
||||
return {
|
||||
sceneriesData: undefined as ISceneryData[] | undefined,
|
||||
activeData: undefined as API.ActiveData.Response | undefined,
|
||||
let sceneriesData = ref<ISceneryData[] | null>(null);
|
||||
let activeData = ref<API.ActiveData.Response | null>(null);
|
||||
|
||||
selectedSceneryId: null as string | null,
|
||||
selectedCheckpointName: null as string | null,
|
||||
selectedRegion: 'eu',
|
||||
const selectedSceneryId = ref<string | null>(null);
|
||||
const selectedCheckpointName = ref<string | null>(null);
|
||||
const selectedRegion = ref('eu');
|
||||
|
||||
fillCheckpointName: false,
|
||||
onMounted(() => {
|
||||
fetchSceneriesData();
|
||||
});
|
||||
|
||||
refreshInterval: -1,
|
||||
store: useStore(),
|
||||
onActivated(async () => {
|
||||
await fetchActiveData();
|
||||
handleQueries();
|
||||
|
||||
regions: ['eu', 'cae', 'usw', 'us', 'ru']
|
||||
};
|
||||
},
|
||||
window.clearInterval(refreshInterval.value);
|
||||
|
||||
created() {
|
||||
this.fillCheckpointName = window.localStorage.getItem('fill-checkpoint') !== 'false';
|
||||
refreshInterval.value = window.setInterval(() => {
|
||||
fetchActiveData();
|
||||
}, 25000);
|
||||
});
|
||||
|
||||
this.fetchSceneriesData();
|
||||
},
|
||||
onDeactivated(() => {
|
||||
window.clearInterval(refreshInterval.value);
|
||||
});
|
||||
|
||||
async activated() {
|
||||
await this.fetchActiveData();
|
||||
this.handleQueries();
|
||||
const selectedScenery = computed(() => {
|
||||
if (activeData.value == null) return null;
|
||||
|
||||
this.refreshInterval = window.setInterval(() => {
|
||||
this.fetchActiveData();
|
||||
}, 25 * 1000);
|
||||
},
|
||||
|
||||
deactivated() {
|
||||
window.clearInterval(this.refreshInterval);
|
||||
},
|
||||
|
||||
watch: {
|
||||
fillCheckpointName(val: boolean) {
|
||||
window.localStorage.setItem('fill-checkpoint', `${val}`);
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
selectedScenery() {
|
||||
return this.activeData?.activeSceneries?.find(
|
||||
return (
|
||||
activeData.value.activeSceneries?.find(
|
||||
(scenery) =>
|
||||
this.selectedSceneryId ==
|
||||
selectedSceneryId.value ==
|
||||
`${scenery.stationName}|${scenery.stationHash}|${scenery.dispatcherName}|${scenery.region}` &&
|
||||
this.selectedRegion == scenery.region
|
||||
selectedRegion.value == scenery.region
|
||||
) ?? null
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
filteredSceneries() {
|
||||
return this.activeData?.activeSceneries
|
||||
?.filter((s) => s.isOnline && s.region == this.selectedRegion)
|
||||
const filteredSceneries = computed(() => {
|
||||
return activeData.value?.activeSceneries
|
||||
?.filter((s) => s.isOnline && s.region == selectedRegion.value)
|
||||
.sort((s1, s2) => s1.stationName.localeCompare(s2.stationName));
|
||||
},
|
||||
});
|
||||
|
||||
checkpointNameList() {
|
||||
if (!this.selectedScenery) return [];
|
||||
const checkpointNameList = computed(() => {
|
||||
if (!selectedScenery.value) return [];
|
||||
|
||||
const checkpoints =
|
||||
this.sceneriesData?.find((s) => s.name == this.selectedScenery?.stationName)?.checkpoints ??
|
||||
sceneriesData.value?.find((s) => s.name == selectedScenery.value?.stationName)?.checkpoints ??
|
||||
'';
|
||||
|
||||
if (checkpoints.length == 0) return [this.selectedScenery.stationName];
|
||||
if (checkpoints.length == 0) return [selectedScenery.value.stationName];
|
||||
|
||||
return checkpoints.split(';');
|
||||
},
|
||||
});
|
||||
|
||||
sceneryTrains() {
|
||||
if (!this.selectedScenery || !this.activeData?.trains) return [];
|
||||
const sceneryTrains = computed(() => {
|
||||
if (!selectedScenery.value || !activeData.value?.trains) return [];
|
||||
|
||||
const scenery = this.selectedScenery;
|
||||
const scenery = selectedScenery.value;
|
||||
|
||||
return this.activeData.trains
|
||||
return activeData.value.trains
|
||||
?.filter(
|
||||
(t) =>
|
||||
(t.currentStationName == scenery.stationName &&
|
||||
@@ -215,69 +190,49 @@ export default defineComponent({
|
||||
t1.driverName.localeCompare(t2.driverName)
|
||||
);
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
methods: {
|
||||
getRegionNameById,
|
||||
async function fetchSceneriesData() {
|
||||
const data = (await http.get<ISceneryData[]>('api/getSceneries')).data;
|
||||
|
||||
async fetchSceneriesData() {
|
||||
const response = await fetch(`${import.meta.env.VITE_APP_API_URL}/getSceneries`);
|
||||
sceneriesData.value = data ?? null;
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
this.sceneriesData = undefined;
|
||||
return;
|
||||
async function fetchActiveData() {
|
||||
const data = (await http.get<API.ActiveData.Response>('api/getActiveData')).data;
|
||||
|
||||
activeData.value = data ?? null;
|
||||
}
|
||||
|
||||
function selectCheckpointOption() {
|
||||
selectedCheckpointName.value =
|
||||
checkpointNameList.value.length == 0 ? null : checkpointNameList.value[0];
|
||||
}
|
||||
|
||||
function fillOrderData(train: API.ActiveTrains.Data) {
|
||||
if (!selectedScenery.value) return;
|
||||
|
||||
const scenery = selectedScenery.value;
|
||||
|
||||
store.orderData.header.A = train.trainNo.toString();
|
||||
store.orderData.header.C = train.currentStationName;
|
||||
store.orderData.header.D = selectedCheckpointName.value || scenery.stationName;
|
||||
|
||||
store.orderData.footer.V = train.driverName;
|
||||
store.orderData.footer.W = scenery.dispatcherName;
|
||||
|
||||
const idData = store.orderData.footer.Z.split('-');
|
||||
|
||||
if (idData.length != 4) {
|
||||
store.orderData.footer.Z = getOrderFullId(0, scenery.stationHash);
|
||||
} else {
|
||||
store.orderData.footer.Z = getOrderFullId(Number(idData[1]) || 0, scenery.stationHash);
|
||||
}
|
||||
|
||||
const data: ISceneryData[] = await response.json();
|
||||
store.panelMode = 'OrderMessagePanel';
|
||||
}
|
||||
|
||||
this.sceneriesData = data;
|
||||
},
|
||||
|
||||
async fetchActiveData() {
|
||||
const response = await fetch(`${import.meta.env.VITE_APP_API_URL}/getActiveData`);
|
||||
|
||||
if (!response.ok) {
|
||||
this.activeData = undefined;
|
||||
return;
|
||||
}
|
||||
|
||||
const data: API.ActiveData.Response = await response.json();
|
||||
|
||||
this.activeData = data;
|
||||
},
|
||||
|
||||
selectOption() {
|
||||
this.selectedCheckpointName =
|
||||
this.checkpointNameList.length == 0 ? null : this.checkpointNameList[0];
|
||||
},
|
||||
|
||||
fillOrder(trainNo: number) {
|
||||
if (!this.selectedScenery) return;
|
||||
|
||||
const chosenOrder = this.store[this.store.chosenOrderType];
|
||||
chosenOrder.header.trainNo = trainNo.toString();
|
||||
chosenOrder.header.date = currentFormattedDate();
|
||||
|
||||
this.store.orderFooter.dispatcherName = this.selectedScenery.dispatcherName;
|
||||
this.store.orderFooter.stationName =
|
||||
this.selectedCheckpointName?.split(',')[0] || this.selectedScenery.stationName;
|
||||
this.store.orderFooter.hour = currentFormattedHours();
|
||||
this.store.orderFooter.minutes = currentFormattedMinutes();
|
||||
|
||||
if (this.fillCheckpointName) {
|
||||
const sceneryAbbrev = this.sceneriesData?.find(
|
||||
({ name }) => name === this.selectedScenery!.stationName
|
||||
)?.abbr;
|
||||
|
||||
this.store.orderFooter.checkpointName =
|
||||
sceneryAbbrev || this.store.orderFooter.stationName.slice(0, 2);
|
||||
}
|
||||
|
||||
this.store.panelMode = 'OrderMessagePanel';
|
||||
},
|
||||
|
||||
handleQueries() {
|
||||
function handleQueries() {
|
||||
const query = new URLSearchParams(window.location.search);
|
||||
|
||||
const id = query.get('sceneryId');
|
||||
@@ -285,23 +240,21 @@ export default defineComponent({
|
||||
if (id) {
|
||||
const [sceneryName, sceneryRegion] = id.split('|');
|
||||
|
||||
this.selectedRegion = sceneryRegion;
|
||||
selectedRegion.value = sceneryRegion;
|
||||
|
||||
const queryScenery = this.activeData?.activeSceneries?.find(
|
||||
const queryScenery = activeData.value?.activeSceneries?.find(
|
||||
(sc) => sc.stationName == sceneryName && sc.region == sceneryRegion && sc.isOnline
|
||||
);
|
||||
|
||||
if (queryScenery) {
|
||||
this.selectedSceneryId = `${queryScenery.stationName}|${queryScenery.stationHash}|${queryScenery.dispatcherName}|${queryScenery.region}`;
|
||||
selectedSceneryId.value = `${queryScenery.stationName}|${queryScenery.stationHash}|${queryScenery.dispatcherName}|${queryScenery.region}`;
|
||||
|
||||
this.selectOption();
|
||||
selectCheckpointOption();
|
||||
|
||||
this.store.panelMode = 'OrderTrainPickerPanel';
|
||||
store.panelMode = 'OrderTrainPickerPanel';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
// For use inside OrderS and OrderN
|
||||
export const handleOrderPlaceholders = (isRowEnabled: boolean, rowRef: HTMLTableElement) => {
|
||||
rowRef.querySelectorAll('input[type="text"]').forEach((node) => {
|
||||
if (!isRowEnabled) {
|
||||
if (node.getAttribute('placeholder') != null) {
|
||||
node.setAttribute('holder', node.getAttribute('placeholder')!);
|
||||
node.removeAttribute('placeholder');
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!node.getAttribute('holder')) return;
|
||||
const radioCheckedAttr = node.getAttribute('radio-checked');
|
||||
|
||||
if (radioCheckedAttr == null)
|
||||
return node.setAttribute('placeholder', node.getAttribute('holder')!);
|
||||
if (radioCheckedAttr == 'true')
|
||||
return node.setAttribute('placeholder', node.getAttribute('holder')!);
|
||||
if (node.getAttribute('placeholder') == null) return;
|
||||
|
||||
node.setAttribute('holder', node.getAttribute('placeholder')!);
|
||||
node.removeAttribute('placeholder');
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
import axios from 'axios';
|
||||
|
||||
const http = axios.create({
|
||||
baseURL: 'https://stacjownik.spythere.eu'
|
||||
});
|
||||
|
||||
export default http;
|
||||
+216
-13
@@ -20,17 +20,19 @@
|
||||
"order-message": {
|
||||
"title": "Message to display in the simulator's chatbox:",
|
||||
"info": "Copy or save the content of the generated train order using buttons below:",
|
||||
"button-save": "Save as new",
|
||||
"button-copy": "Copy the message",
|
||||
"button-update": "Update",
|
||||
"button-reset": "Reset",
|
||||
"button-save": "Save as new order",
|
||||
"button-copy": "Copy order message",
|
||||
"button-update": "Update order",
|
||||
"button-reset": "Reset order",
|
||||
"warning-outdated-clipboard": "Oops! Your browser may be a little bit depraceted since it's not supporting saving data to the clipboard! :/",
|
||||
"warning-fill-inputs": "Fill all the empty fields before copying the order!",
|
||||
"warning-add-rows": "Add at least one row before copying the order!",
|
||||
"warning-fill-footer": "Fill the following rows in the order's footer before copying it:",
|
||||
"warning-fill-top": "Fill the order number, train number and date before saving it!",
|
||||
"warning-add-instruction": "Add at least one order instruction before copying the order!",
|
||||
"warning-fill-missing": "Fill rows in the order's header and footer before copying it!",
|
||||
"warning-fill-top-save": "Fill at least fields A, B, C and D in the order's header before saving it!",
|
||||
"warning-fill-top-update": "Fill at least fields A, B, C and D in the order's header before updating it!",
|
||||
"warning-order-identical": "Last saved order is identical as the current one!",
|
||||
"warning-no-order-selected": "Choose the already saved order first!",
|
||||
"warning-conflicting-instructions": "Instruction {0} and {1} can't be on the same order!",
|
||||
"error-update": "An error occurred while saving this order! :/",
|
||||
"success-update-html": "Updated this <b class=\"text--accent\">order's</b> message!",
|
||||
"success-save-html": "Saved <b class=\"text--accent\">order's</b> message in the browser memory!",
|
||||
@@ -53,12 +55,15 @@
|
||||
},
|
||||
"order-list": {
|
||||
"title": "Saved train orders",
|
||||
"order-title": "Order \"{orderName}\" no. {orderNo} for train no. {trainNo}",
|
||||
"order-title": "Train order for no. {trainNo}",
|
||||
"order-subtitle": "Selected instructions: {0}",
|
||||
"no-saved-orders": "No saved orders!",
|
||||
"order-added": "Added:",
|
||||
"order-updated": "Updated:",
|
||||
"button-order-select": "Select",
|
||||
"button-order-remove": "Remove"
|
||||
"button-order-remove": "Remove",
|
||||
"warning-deprecated-version": "Deprecated version of the order - may generate incorrect information!",
|
||||
"warning-removed-deprecated-orders": "Removed deprecated train orders ({count}) due to their replacement with a new format in Polish railway!"
|
||||
},
|
||||
"order-train-picker": {
|
||||
"placeholder-scenery-name": "Scenery name",
|
||||
@@ -70,9 +75,207 @@
|
||||
"subtitle": "Click on the user below to fill the current order with their information",
|
||||
"no-trains": "No trains to display"
|
||||
},
|
||||
"migrate-info": {
|
||||
"line-1": "GeneraTOR is being moved to a new domain - {0}! You can still use the current website, but it will no longer be updated and will be shut down in the nearest future!",
|
||||
"link": "https://generator-td2.spythere.eu/",
|
||||
"accept-btn": "ROGER THAT!"
|
||||
"order": {
|
||||
"title": "Polish Railway Train Order",
|
||||
"header": {
|
||||
"A": "A Train No {'|'} Shunting composition No",
|
||||
"A-placeholder": "Train / shunting composition number",
|
||||
"B": "B Date",
|
||||
"C": "C Location of train {'|'} Location of shunting composition",
|
||||
"C-placeholder": "Name of the post / line / scenery",
|
||||
"D": "D Location of issuer",
|
||||
"D-placeholder": "Name of the post / scenery"
|
||||
},
|
||||
"22": {
|
||||
"text": "Applies to left-track traffic",
|
||||
"message-html": "<b>Applies to left-track traffic</b>"
|
||||
},
|
||||
"99": {
|
||||
"text": "Revoke the train order",
|
||||
"x1": "x.1 Train order identifier",
|
||||
"message-html": "<b>Revoke the train order</b> {0}"
|
||||
},
|
||||
"2110": {
|
||||
"text": "{bold1} from track no. {track1} from {signalbox1} {br} to track no. {track2} in the direction of {signalbox2} {br} Pass Stop signals {signal1} and {signal2} and {signal3}",
|
||||
"bold1": "Is allowed to exit",
|
||||
"track1": "x.1 track",
|
||||
"signalbox1": "x.2 signalbox",
|
||||
"track2": "x.3 track",
|
||||
"signalbox2": "x.4 signalbox",
|
||||
"signal1": "x.5 signal",
|
||||
"signal2": "x.6 signal",
|
||||
"signal3": "x.7 signal",
|
||||
"message-html": "<b>Is allowed to exit</b> from track no. {0} from {1} to track no. {2} in the direction of {3}. Pass Stop signals {4} and {5} and {6}"
|
||||
},
|
||||
"2115": {
|
||||
"text": "{bold1} from track no. {track1} to {signalbox1} on track no. {track2} {br} Pass signals {signal1} and {signal2} and {signal3}",
|
||||
"bold1": "Is allowed to enter",
|
||||
"track1": "x.1 track",
|
||||
"signalbox1": "x.2 signalbox",
|
||||
"track2": "x.3 track",
|
||||
"signal1": "x.4 signal",
|
||||
"signal2": "x.5 signal",
|
||||
"signal3": "x.6 signal",
|
||||
"message-html": "<b>Is allowed to enter</b> from track no. {0} to {1} on track no. {2}. Pass signals {3} and {4} and {5}"
|
||||
},
|
||||
"2120": {
|
||||
"text": "From {signalbox1} to {signalbox2} on track {track1} {br} {highlight1} {br} {underline1}{highlight2}.",
|
||||
"highlight1": "SBL signalling indications are to be ignored.",
|
||||
"underline1": "Stay alert after passing the signal with indicator",
|
||||
"highlight2": " W18",
|
||||
"signalbox1": "x.1 signalbox",
|
||||
"signalbox2": "x.2 signalbox",
|
||||
"track1": "x.3 track no",
|
||||
"message-html": "From {0} to {1} on track {2} <b>SBL signals are to be ignored.</b> Stay alert after passing the signal with indicator <b>W18.</b>"
|
||||
},
|
||||
"2125": {
|
||||
"text": "Is allowed to pass {select1} in the direction of {signalbox1} on track {track1} to km {km1} to hour {hour1}.",
|
||||
"select1-a": "indicator W5",
|
||||
"select1-b": "last switch",
|
||||
"signalbox1": "x.1 signalbox",
|
||||
"track1": "x.2 track",
|
||||
"km1": "x.3 km",
|
||||
"hour1": "x.4 hour",
|
||||
"message-html": "Is allowed to pass {0} in the direction of {1} on track {2} to km {3} to hour {4}."
|
||||
},
|
||||
"2135": {
|
||||
"text": "{bold1} on track no. {track1} in the direction of {signalbox1}.",
|
||||
"bold1": "Is allowed to proceed",
|
||||
"track1": "x.1 track",
|
||||
"signalbox1": "x.2 signalbox",
|
||||
"message-html": "<b>Is allowed to proceed</b> on track no. {0} in the direction of {1}"
|
||||
},
|
||||
"2140": {
|
||||
"text": "{bold1} at post/line {signalbox1}{'|'}{signalbox2} at km {km1} for {other1}",
|
||||
"bold1": "Train halt",
|
||||
"signalbox1": "x.1 signalbox",
|
||||
"signalbox2": "x.2 signalbox",
|
||||
"km1": "x.3 km",
|
||||
"other1": "x.96 cause",
|
||||
"message-html": "<b>Train halt</b> at post {0} at km {2} for {3} | <b>Train halt</b> on line {0} {'|'} {1} at km {2} for {3} | <b>Train halt</b> on line {0} {'|'} {1} at km {2} for {3}"
|
||||
},
|
||||
"2145": {
|
||||
"text": "At {signalbox1} the clear signal {signal1}{br}{bold1}",
|
||||
"bold1": "is invalid. Stop the train before this signal.",
|
||||
"signalbox1": "x.1 signalbox",
|
||||
"signal1": "x.2 signal",
|
||||
"message-html": "At {0} the clear signal {1} <b>is invalid, stop the train before this signal.</b>"
|
||||
},
|
||||
"2150": {
|
||||
"text": "{bold1} at post/line {br} {signalbox1} / {signalbox2} referring to level crossing at km {km1}{br}{bold2}",
|
||||
"bold1": "Level crossing distant signals (TOP)",
|
||||
"bold2": "are to be ignored. Proceed with timetable speed.",
|
||||
"signalbox1": "x.1 signalbox",
|
||||
"signalbox2": "x.2 signalbox",
|
||||
"km1": "x.3 km",
|
||||
"message-html": "<b>Level crossing distant signals (TOP)</b> at post {0} referring to level crossing at km {1} <b>are to be ignored. Proceed with timetable speed.</b> | <b>Wskazania tarcz ostrzegawczych</b> na line {0} / {1} referring to level crossing at km {2} <b>are to be ignored. Proceed with timetable speed.</b> | <b>Wskazania tarcz ostrzegawczych</b> na line {0} / {1} referring to level crossing at km {2} <b>are to be ignored. Proceed with timetable speed.</b>"
|
||||
},
|
||||
"2155": {
|
||||
"text": "{bold1} at post/line {signalbox1}{'|'}{signalbox2} referring to signal {signal1}.",
|
||||
"bold1": "Damaged SHP device",
|
||||
"signalbox1": "x.1 signalbox",
|
||||
"signalbox2": "x.2 signalbox",
|
||||
"signal1": "x.3 signal",
|
||||
"message-html": "<b>Damaged SHP device</b> at post {0} referring to signal {2}|<b>Damaged SHP device</b> on line {0} {'|'} {1} referring to signal {2}|<b>Uszkodzone urządzenia SHP</b> on line {0} {'|'} {1} referring to signal {2}"
|
||||
},
|
||||
"2160": {
|
||||
"text": "{bold1} from {signalbox1} to {signalbox2}, rerouted via {signalbox3} by line {line1} with the speed of {vmax1}.",
|
||||
"bold1": "Route change",
|
||||
"signalbox1": "x.1 signalbox",
|
||||
"signalbox2": "x.2 signalbox",
|
||||
"signalbox3": "x.3 signalbox",
|
||||
"line1": "x.4 line",
|
||||
"vmax1": "x.5 km/h",
|
||||
"message-html": "<b>Route change</b> from {0} to {1}, rerouted via {2} by line {3} with the speed of {4}."
|
||||
},
|
||||
"2165": {
|
||||
"text": "{bold1} from {km1} to {km2}.",
|
||||
"bold1": "Run with lowered pantographs",
|
||||
"km1": "x.1 km",
|
||||
"km2": "x.2 km",
|
||||
"message-html": "<b>Run with lowered pantographs</b> from {0} to {1}."
|
||||
},
|
||||
"2170": {
|
||||
"text": "{bold1} {signalbox1} and {signalbox2} of the line no. {line1}{br}{bold2}",
|
||||
"bold1": "At section between",
|
||||
"bold2": "ride with the analog contact.",
|
||||
"signalbox1": "x.1 signalbox",
|
||||
"signalbox2": "x.2 signalbox",
|
||||
"line1": "x.3 line",
|
||||
"message-html": "<b>At section between</b> {0} and {1} of the line no. {2} <b>ride with the analog contact.</b>"
|
||||
},
|
||||
"2180": {
|
||||
"text": "{bold1} no. {track1} in the directon of {signalbox1} to km {km1} turning to {signalbox2} until hour {hour1}",
|
||||
"bold1": "Run on the closed track",
|
||||
"track1": "x.1 tor",
|
||||
"signalbox1": "x.2 signalbox",
|
||||
"km1": "x.3 km",
|
||||
"signalbox2": "x.4 signalbox",
|
||||
"hour1": "x.5 hour",
|
||||
"message-html": "<b>Run on the closed track</b> no. {0} in the directon of {1} to km {2} turning to {3} until hour {4}"
|
||||
},
|
||||
"2181": {
|
||||
"text": "{bold1}",
|
||||
"bold1": "Track is closed with no rolling stock",
|
||||
"message-html": "<b>Track is closed with no rolling stock</b> "
|
||||
},
|
||||
"2182": {
|
||||
"text": "Train {train1} {bold1} at km {km1}",
|
||||
"bold1": "is working on track",
|
||||
"train1": "x.1 train no.",
|
||||
"km1": "x.2 km",
|
||||
"message-html": "Train {0} <b>is working on track</b> at km {1}"
|
||||
},
|
||||
"2183": {
|
||||
"text": "Train {train1} {bold1} to km {km1}",
|
||||
"bold1": "will be dispatched",
|
||||
"train1": "x.1 train no.",
|
||||
"km1": "x.2 km",
|
||||
"message-html": "Train {0} <b>will be dispatched</b> to km {1}"
|
||||
},
|
||||
"2185": {
|
||||
"text": "{bold1} on track no. {track1} at km {km1} on line {signalbox1} {'|'} {signalbox2}",
|
||||
"bold1": "Is allowed to insert a PSD vehicle",
|
||||
"track1": "x.1 track",
|
||||
"km1": "x.2 km",
|
||||
"signalbox1": "x.3 signalbox",
|
||||
"signalbox2": "x.4 signalbox",
|
||||
"message-html": "<b>Is allowed to insert a PSD vehicle</b> on track no. {0} at km {1} on line {2} {'|'} {3}"
|
||||
},
|
||||
"2310": {
|
||||
"text": "{bold1}{br}{text-list}",
|
||||
"bold1": "Do not exceed the speed and stay alert:",
|
||||
"text-list": "{bold} {signalbox1}/{signalbox2} track no. {track1} {v} {vmax1} from {km1} to {km2} {other1}",
|
||||
"bold": "{0}. On post/line",
|
||||
"signalbox1": "x.{0} signalbox",
|
||||
"signalbox2": "x.{0} signalbox",
|
||||
"track1": "x.{0} track",
|
||||
"vmax1": "x.{0} km/h",
|
||||
"km1": "x.{0} km",
|
||||
"km2": "x.{0} km",
|
||||
"other1": "x.{1} cause",
|
||||
"message-html": "<b>Nie przekraczać prędkości i zachować ostrożność:</b>",
|
||||
"message-html-list": "<b>{0}. On post</b> {1} track no. {3} v{4}km/h from {5}km to {6}km - cause: {7}|<b>{0}. On post</b> {1} tor nr {3} v{4} from {5}km to {6}km - cause: {7}|<b>{0}. On line</b> {1}/{2} tor nr {3} v{4} from {5}km to {6}km - cause: {7}"
|
||||
},
|
||||
"2311": {
|
||||
"text": "{bold1}",
|
||||
"bold1": "Use „Baczność” signal multiple times",
|
||||
"message-html": "<b>Use „Baczność” signal multiple times</b>"
|
||||
},
|
||||
"2320": {
|
||||
"text": "{other2320}",
|
||||
"other2320": "x.96 other",
|
||||
"message-html": "Other: {0}"
|
||||
},
|
||||
"footer": {
|
||||
"V": "V Driver identifier",
|
||||
"V-placeholder": "Driver nickname",
|
||||
"W": "W Issuer identifier",
|
||||
"W-placeholder": "Dispatcher nickname",
|
||||
"Y": "Y Hour",
|
||||
"Y-placeholder": "HH:MM, e.g. 09:25",
|
||||
"Z": "Z Train order identifier",
|
||||
"Z-placeholder": "RD-(order no.)-(sc. hash)-(2 last year digits)"
|
||||
}
|
||||
}
|
||||
}
|
||||
+216
-13
@@ -20,17 +20,19 @@
|
||||
"order-message": {
|
||||
"title": "Wiadomość do wyświetlenia na czacie symulatora:",
|
||||
"info": "Po wygenerowaniu rozkazu skopiuj jego treść lub zapisz w pamięci przeglądarki za pomocą przycisków poniżej:",
|
||||
"button-save": "Zapisz nowy",
|
||||
"button-copy": "Skopiuj treść",
|
||||
"button-update": "Zaktualizuj",
|
||||
"button-reset": "Zresetuj",
|
||||
"button-save": "Zapisz nowy rozkaz",
|
||||
"button-copy": "Kopiuj treść rozkazu",
|
||||
"button-update": "Zaktualizuj rozkaz",
|
||||
"button-reset": "Wyczyść rozkaz",
|
||||
"warning-outdated-clipboard": "Ups! Twoja przeglądarka musi być dosyć przestarzała, ponieważ nie obsługuje zapisu do schowka! :/",
|
||||
"warning-fill-inputs": "Wypełnij puste rubryki rozkazu przed jego skopiowaniem!",
|
||||
"warning-add-rows": "Dodaj co najmniej jedną działkę rozkazu przed jego skopiowaniem!",
|
||||
"warning-fill-footer": "Uzupełnij następujące rubryki na dole rozkazu przed jego skopiowaniem:",
|
||||
"warning-fill-top": "Wypełnij numer rozkazu, numer pociągu i datę zanim dodasz rozkaz!",
|
||||
"warning-add-instruction": "Dodaj co najmniej jedną instrukcję rozkazu przed jego skopiowaniem!",
|
||||
"warning-fill-missing": "Uzupełnij rubryki w nagłówku i stopce rozkazu przed jego skopiowaniem!",
|
||||
"warning-fill-top-save": "Wypełnij co najmniej rubryki A, B, C i D w nagłówku rozkazu przed jego zapisaniem!",
|
||||
"warning-fill-top-update": "Wypełnij co najmniej rubryki A, B, C i D w nagłówku rozkazu przed jego zaktualizowaniem!",
|
||||
"warning-order-identical": "Ostatni zapisany rozkaz jest identyczny z obecnym!",
|
||||
"warning-no-order-selected": "Wybierz rozkaz, który chcesz zaktualizować!",
|
||||
"warning-conflicting-instructions": "Instrukcje {0} i {1} nie mogą znajdować się na tym samym rozkazie jednocześnie!",
|
||||
"error-update": "Wystąpił błąd podczas aktualizowania tego rozkazu! :/",
|
||||
"success-update-html": "Zaktualizowano treść <b class=\"text--accent\">rozkazu</b>!",
|
||||
"success-save-html": "Zapisano treść <b class=\"text--accent\">rozkazu</b> w pamięci przeglądarki!",
|
||||
@@ -54,11 +56,14 @@
|
||||
"order-list": {
|
||||
"title": "Zapisane rozkazy pisemne",
|
||||
"no-saved-orders": "Brak zapisanych rozkazów!",
|
||||
"order-title": "Rozkaz \"{orderName}\" nr {orderNo} dla pociągu nr {trainNo}",
|
||||
"order-title": "Rozkaz pisemny dla pociągu nr {trainNo}",
|
||||
"order-subtitle": "Zaznaczone instrukcje: {0}",
|
||||
"order-added": "Dodano:",
|
||||
"order-updated": "Zaktualizowano:",
|
||||
"button-order-select": "Wybierz",
|
||||
"button-order-remove": "Usuń"
|
||||
"button-order-remove": "Usuń",
|
||||
"warning-deprecated-version": "Przestarzała wersja rozkazu! Może generować złe informacje!",
|
||||
"warning-removed-deprecated-orders": "Usunięto nieaktualne rozkazy pisemne ({count}) w związku z wejściem w życie ich nowego formatu!"
|
||||
},
|
||||
"order-train-picker": {
|
||||
"placeholder-scenery-name": "Sceneria",
|
||||
@@ -70,9 +75,207 @@
|
||||
"subtitle": "Kliknij na gracza, aby wypełnić obecny rozkaz jego danymi",
|
||||
"no-trains": "Brak pociągów do wyświetlenia"
|
||||
},
|
||||
"migrate-info": {
|
||||
"line-1": "GeneraTOR zostaje przeniesiony na nową domenę - {0}! Możesz korzystać z obecnej strony, jednak nie będzie ona otrzymywać już aktualizacji i w przyszłości zostanie wyłączona!",
|
||||
"link": "https://generator-td2.spythere.eu/",
|
||||
"accept-btn": "PRZYJĄŁEM!"
|
||||
"order": {
|
||||
"title": "Rozkaz pisemny",
|
||||
"header": {
|
||||
"A": "A Nr pociągu {'|'} składu manewrowego",
|
||||
"A-placeholder": "Numer pociągu lub manewru",
|
||||
"B": "B Data",
|
||||
"C": "C Lokalizacja pociągu {'|'} składu manewrowego",
|
||||
"C-placeholder": "Nazwa posterunku / szlaku / scenerii",
|
||||
"D": "D Lokalizacja nadawcy",
|
||||
"D-placeholder": "Nazwa posterunku / scenerii"
|
||||
},
|
||||
"22": {
|
||||
"text": "Dotyczy jazdy torem lewym",
|
||||
"message-html": "<b>Dotyczy jazdy torem lewym</b>"
|
||||
},
|
||||
"99": {
|
||||
"text": "Odwołanie rozkazu pisemnego",
|
||||
"x1": "x.1 Identyfikator rozkazu pisemnego",
|
||||
"message-html": "<b>Odwołanie rozkazu pisemnego</b> {0}"
|
||||
},
|
||||
"2110": {
|
||||
"text": "{bold1} z toru nr {track1} z {signalbox1} {br} na tor nr {track2} w kierunku {signalbox2} {br} Pominięcie sygnałów stój {signal1} i {signal2} i {signal3}",
|
||||
"bold1": "Zezwalam na wyjazd",
|
||||
"track1": "x.1 tor",
|
||||
"signalbox1": "x.2 posterunek",
|
||||
"track2": "x.3 tor",
|
||||
"signalbox2": "x.4 posterunek",
|
||||
"signal1": "x.5 sygnalizator",
|
||||
"signal2": "x.6 sygnalizator",
|
||||
"signal3": "x.7 sygnalizator",
|
||||
"message-html": "<b>Zezwalam na wyjazd</b> z toru nr {0} z {1} na tor nr {2} w kierunku {3}. Pominięcie sygnałów stój {4} i {5} i {6}"
|
||||
},
|
||||
"2115": {
|
||||
"text": "{bold1} z toru nr {track1} do {signalbox1} na tor nr {track2} {br} Pominięcie sygnałów {signal1} i {signal2} i {signal3}",
|
||||
"bold1": "Zezwalam na wjazd",
|
||||
"track1": "x.1 tor",
|
||||
"signalbox1": "x.2 posterunek",
|
||||
"track2": "x.3 tor",
|
||||
"signal1": "x.4 sygnalizator",
|
||||
"signal2": "x.5 sygnalizator",
|
||||
"signal3": "x.6 sygnalizator",
|
||||
"message-html": "<b>Zezwalam na wjazd</b> z toru nr {0} do {1} na tor nr {2}. Pominięcie sygnałów {3} i {4} i {5}"
|
||||
},
|
||||
"2120": {
|
||||
"text": "Od {signalbox1} do {signalbox2} po torze {track1} {br} {highlight1} {br} {underline1}{highlight2}.",
|
||||
"highlight1": "wskazania semaforów SBL są nieważne.",
|
||||
"underline1": "Zachować ostrożność od semafora ze wskaźnikiem",
|
||||
"highlight2": " W18",
|
||||
"signalbox1": "x.1 posterunek",
|
||||
"signalbox2": "x.2 posterunek",
|
||||
"track1": "x.3 nr toru",
|
||||
"message-html": "Od {0} do {1} po torze {2} <b>wskazania semaforów SBL są nieważne.</b> Zachować ostrożność od semafora ze wskaźnikiem <b>W18.</b>"
|
||||
},
|
||||
"2125": {
|
||||
"text": "Zezwalam przejechać za {select1} w kierunku {signalbox1} torem {track1} do km {km1} do godz. {hour1}.",
|
||||
"select1-a": "wskaźnik W5",
|
||||
"select1-b": "ostatni rozjazd",
|
||||
"signalbox1": "x.1 posterunek",
|
||||
"track1": "x.2 tor",
|
||||
"km1": "x.3 km",
|
||||
"hour1": "x.4 godzina",
|
||||
"message-html": "Zezwalam przejechać za {0} w kierunku {1} torem {2} do km {3} do godz. {4}."
|
||||
},
|
||||
"2135": {
|
||||
"text": "{bold1} po torze nr {track1} w kierunku {signalbox1}.",
|
||||
"bold1": "Zezwalam na kontynuacje jazdy",
|
||||
"track1": "x.1 tor",
|
||||
"signalbox1": "x.2 posterunek",
|
||||
"message-html": "<b>Zezwalam na kontynuacje jazdy</b> po torze nr {0} w kierunku {1}"
|
||||
},
|
||||
"2140": {
|
||||
"text": "{bold1} na posterunku/szlaku {signalbox1}{'|'}{signalbox2} w km {km1} celem {other1}",
|
||||
"bold1": "Zatrzymanie pociągu",
|
||||
"signalbox1": "x.1 posterunek",
|
||||
"signalbox2": "x.2 posterunek",
|
||||
"km1": "x.3 km",
|
||||
"other1": "x.96 inne",
|
||||
"message-html": "<b>Zatrzymanie pociągu</b> na posterunku {0} w km {2} celem {3} | <b>Zatrzymanie pociągu</b> na szlaku {0} {'|'} {1} w km {2} celem {3} | <b>Zatrzymanie pociągu</b> na szlaku {0} {'|'} {1} w km {2} celem {3}"
|
||||
},
|
||||
"2145": {
|
||||
"text": "Na {signalbox1} na sygnalizatorze {signal1}{br}{bold1}",
|
||||
"bold1": "sygnał zezwalający jest nieważny, zatrzymać pociąg przed tym sygnalizatorem.",
|
||||
"signalbox1": "x.1 posterunek",
|
||||
"signal1": "x.2 sygnalizator",
|
||||
"message-html": "Na {0} na sygnalizatorze {1} <b>sygnał zezwalający jest nieważny, zatrzymać pociąg przed tym sygnalizatorem.</b>"
|
||||
},
|
||||
"2150": {
|
||||
"text": "{bold1} przejazdowych na posterunku/szlaku {br} {signalbox1} / {signalbox2} odnoszących się do przejazdu w km {km1}{br}{bold2}",
|
||||
"bold1": "Wskazania tarcz ostrzegawczych",
|
||||
"bold2": "są nieważne. Jazda z prędkością rozkładową.",
|
||||
"signalbox1": "x.1 posterunek",
|
||||
"signalbox2": "x.2 posterunek",
|
||||
"km1": "x.3 km",
|
||||
"message-html": "<b>Wskazania tarcz ostrzegawczych</b> przejazdowych na posterunku {0} odnoszących się do przejazdu w km {1} <b>są nieważne. Jazda z prędkością rozkładową.</b> | <b>Wskazania tarcz ostrzegawczych</b> przejazdowych na szlaku {0} / {1} odnoszących się do przejazdu w km {2} <b>są nieważne. Jazda z prędkością rozkładową.</b> | <b>Wskazania tarcz ostrzegawczych</b> przejazdowych na szlaku {0} / {1} odnoszących się do przejazdu w km {2} <b>są nieważne. Jazda z prędkością rozkładową.</b>"
|
||||
},
|
||||
"2155": {
|
||||
"text": "{bold1} na posterunku/szlaku {signalbox1}{'|'}{signalbox2} odnoszące się do sygnalizatora {signal1}.",
|
||||
"bold1": "Uszkodzone urządzenia SHP",
|
||||
"signalbox1": "x.1 posterunek",
|
||||
"signalbox2": "x.2 posterunek",
|
||||
"signal1": "x.3 sygnalizator",
|
||||
"message-html": "<b>Uszkodzone urządzenia SHP</b> na posterunku {0} odnoszące się do sygnalizatora {2}|<b>Uszkodzone urządzenia SHP</b> na szlaku {0} {'|'} {1} odnoszące się do sygnalizatora {2}|<b>Uszkodzone urządzenia SHP</b> na szlaku {0} {'|'} {1} odnoszące się do sygnalizatora {2}"
|
||||
},
|
||||
"2160": {
|
||||
"text": "{bold1} na odcinku od {signalbox1} do {signalbox2}, jazda przez {signalbox3} linią {line1} z prędkością {vmax1}.",
|
||||
"bold1": "Zmiana trasy",
|
||||
"signalbox1": "x.1 posterunek",
|
||||
"signalbox2": "x.2 posterunek",
|
||||
"signalbox3": "x.3 posterunek",
|
||||
"line1": "x.4 linia",
|
||||
"vmax1": "x.5 km/h",
|
||||
"message-html": "<b>Zmiana trasy</b> na odcinku od {0} do {1}, jazda przez {2} linią {3} z prędkością {4}."
|
||||
},
|
||||
"2165": {
|
||||
"text": "{bold1} na odcinku od {km1} do {km2}.",
|
||||
"bold1": "Jazda z opuszczonymi pantografami",
|
||||
"km1": "x.1 km",
|
||||
"km2": "x.2 km",
|
||||
"message-html": "<b>Jazda z opuszczonymi pantografami</b> na odcinku od {0} do {1}."
|
||||
},
|
||||
"2170": {
|
||||
"text": "{bold1} od {signalbox1} do {signalbox2} linii nr {line1}{br}{bold2}",
|
||||
"bold1": "Na odcinku",
|
||||
"bold2": "jazda pociągu z łącznością analogową.",
|
||||
"signalbox1": "x.1 posterunek",
|
||||
"signalbox2": "x.2 posterunek",
|
||||
"line1": "x.3 linia",
|
||||
"message-html": "<b>Na odcinku</b> na odcinku od {0} do {1} linii nr {2} <b>jazda pociągu z łącznością analogową.</b>"
|
||||
},
|
||||
"2180": {
|
||||
"text": "{bold1} nr {track1} w kierunku {signalbox1} do km {km1} zjazd do {signalbox2} do godz. {hour1}",
|
||||
"bold1": "Polecam jazdę po torze zamkniętym",
|
||||
"track1": "x.1 tor",
|
||||
"signalbox1": "x.2 posterunek",
|
||||
"km1": "x.3 km",
|
||||
"signalbox2": "x.4 posterunek",
|
||||
"hour1": "x.5 godzina",
|
||||
"message-html": "<b>Polecam jazdę po torze zamkniętym</b> nr {0} w kierunku {1} do km {2} zjazd do {3} do godz. {4}"
|
||||
},
|
||||
"2181": {
|
||||
"text": "{bold1}",
|
||||
"bold1": "Tor zamknięty wolny od taboru",
|
||||
"message-html": "<b>Tor zamknięty wolny od taboru</b> "
|
||||
},
|
||||
"2182": {
|
||||
"text": "{bold1} {train1} w km {km1}",
|
||||
"bold1": "Na torze pracuje pociąg",
|
||||
"train1": "x.1 numer pociągu",
|
||||
"km1": "x.2 km",
|
||||
"message-html": "<b>Na torze pracuje pociąg</b> {0} w km {1}"
|
||||
},
|
||||
"2183": {
|
||||
"text": "{bold1} {train1} do km {km1}",
|
||||
"bold1": "Na tor zostanie wyprawiony pociąg",
|
||||
"train1": "x.1 numer pociągu",
|
||||
"km1": "x.2 km",
|
||||
"message-html": "<b>Na tor zostanie wyprawiony pociąg</b> {0} do km {1}"
|
||||
},
|
||||
"2185": {
|
||||
"text": "{bold1} na tor nr {track1} w km {km1} na szlaku {signalbox1} {'|'} {signalbox2}",
|
||||
"bold1": "Zezwalam na wstawienie PSD",
|
||||
"track1": "x.1 tor",
|
||||
"km1": "x.2 km",
|
||||
"signalbox1": "x.3 posterunek",
|
||||
"signalbox2": "x.4 posterunek",
|
||||
"message-html": "<b>Zezwalam na wstawienie PSD</b> na tor nr {0} w km {1} na szlaku {2} {'|'} {3}"
|
||||
},
|
||||
"2310": {
|
||||
"text": "{bold1}{br}{text-list}",
|
||||
"bold1": "Nie przekraczać prędkości i zachować ostrożność:",
|
||||
"text-list": "{bold} {signalbox1}/{signalbox2} tor nr {track1} {v} {vmax1} od {km1} do {km2} {other1}",
|
||||
"bold": "{0}. Na posterunku/szlaku",
|
||||
"signalbox1": "x.{0} posterunek",
|
||||
"signalbox2": "x.{0} posterunek",
|
||||
"track1": "x.{0} tor",
|
||||
"vmax1": "x.{0} km/h",
|
||||
"km1": "x.{0} km",
|
||||
"km2": "x.{0} km",
|
||||
"other1": "x.{1} przyczyna",
|
||||
"message-html": "<b>Nie przekraczać prędkości i zachować ostrożność:</b>",
|
||||
"message-html-list": "<b>{0}. Na posterunku</b> {1} tor nr {3} v{4}km/h od {5}km do {6}km - przyczyna: {7}|<b>{0}. Na posterunku</b> {1} tor nr {3} v{4} od {5}km do {6}km - przyczyna: {7}|<b>{0}. Na szlaku</b> {1}/{2} tor nr {3} v{4} od {5}km do {6}km - przyczyna: {7}"
|
||||
},
|
||||
"2311": {
|
||||
"text": "{bold1}",
|
||||
"bold1": "Podawać sygnał „Baczność”",
|
||||
"message-html": "<b>Podawać sygnał „Baczność”</b>"
|
||||
},
|
||||
"2320": {
|
||||
"text": "{other2320}",
|
||||
"other2320": "x.96 inne",
|
||||
"message-html": "Inne: {0}"
|
||||
},
|
||||
"footer": {
|
||||
"V": "V Identyfikator maszynisty",
|
||||
"V-placeholder": "Nick maszynisty",
|
||||
"W": "W Identyfikator nadawcy",
|
||||
"W-placeholder": "Nick dyżurnego",
|
||||
"Y": "Y Godzina",
|
||||
"Y-placeholder": "Godzina w formacie HH:MM np. 09:25",
|
||||
"Z": "Z Identyfikator rozkazu pisemnego",
|
||||
"Z-placeholder": "RD-(nr rozkazu)-(hash sc.)-(2 ostatnie cyfry roku)"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
import { defineComponent } from 'vue';
|
||||
import { useStore } from '../store/store';
|
||||
|
||||
export default defineComponent({
|
||||
setup() {
|
||||
return {
|
||||
store: useStore()
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
generateFooter() {
|
||||
const footer = this.store.orderFooter;
|
||||
|
||||
const messageArray = [];
|
||||
|
||||
messageArray.push(`stacja: ${footer.stationName ?? ''}`);
|
||||
if (footer.checkpointName) messageArray.push(`posterunek: ${footer.checkpointName}`);
|
||||
if (footer.hour) messageArray.push(`godz. ${footer.hour}`);
|
||||
if (footer.minutes) messageArray.push(`min. ${footer.minutes}`);
|
||||
if (footer.dispatcherName) messageArray.push(`dyżurny ruchu ${footer.dispatcherName}`);
|
||||
if (footer.secondaryDispatcherName)
|
||||
messageArray.push(`z polecenia dyżurnego ruchu ${footer.secondaryDispatcherName}`);
|
||||
|
||||
this.store.footerMessage = `\n--------\n${messageArray.join(
|
||||
', '
|
||||
)}\n--------\nRozkaz otrzymałem, maszynista: <i>(potwierdzić otrzymanie rozkazu)</i>`;
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1,163 +0,0 @@
|
||||
import { defineComponent } from 'vue';
|
||||
import { useStore } from '../store/store';
|
||||
import { LocalStorageOrder } from '../types/orderTypes';
|
||||
|
||||
function alertWrongOrderFormat() {
|
||||
alert('Wystąpił błąd podczas przetwarzania rozkazu! Informacje mogą być niepoprawne!');
|
||||
console.warn('Zły format zapisanego rozkazu!');
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
setup() {
|
||||
return {
|
||||
store: useStore()
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
saveOrderSetting(key: string, value: string | number | boolean) {
|
||||
window.localStorage.setItem(key, value.toString());
|
||||
},
|
||||
|
||||
getOrderSetting(key: string) {
|
||||
return window.localStorage.getItem(key);
|
||||
},
|
||||
|
||||
removeOrderSetting(key: string) {
|
||||
window.localStorage.removeItem(key);
|
||||
},
|
||||
|
||||
saveLocalOrder() {
|
||||
const orderObj: LocalStorageOrder = {
|
||||
id: '',
|
||||
orderType: this.store.chosenOrderType,
|
||||
orderBody: this.store[this.store.chosenOrderType],
|
||||
orderFooter: this.store.orderFooter,
|
||||
createdAt: Date.now(),
|
||||
orderVersion: import.meta.env['VITE_APP_ORDER_VERSION'] || '1'
|
||||
};
|
||||
|
||||
const headerInfo = orderObj['orderBody']['header'];
|
||||
|
||||
if (!headerInfo['orderNo']) return -1;
|
||||
if (!headerInfo['trainNo']) return -1;
|
||||
if (!headerInfo['date']) return -1;
|
||||
|
||||
const localStorage = window.localStorage;
|
||||
const localOrderCount = localStorage.getItem('orderCount') || '0';
|
||||
|
||||
if (localOrderCount == '0') localStorage.setItem('orderCount', '0');
|
||||
|
||||
const prevLocalOrder = localStorage.getItem(`order-${Number(localOrderCount)}`);
|
||||
if (prevLocalOrder && prevLocalOrder == JSON.stringify(orderObj)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const nextOrderCount = Number(localOrderCount) + 1;
|
||||
const orderId = `order-${nextOrderCount}`;
|
||||
orderObj['id'] = orderId;
|
||||
|
||||
localStorage.setItem('orderCount', `${nextOrderCount}`);
|
||||
localStorage.setItem(orderId, JSON.stringify(orderObj));
|
||||
|
||||
this.store.chosenLocalOrderId = orderId;
|
||||
return 1;
|
||||
},
|
||||
|
||||
updateLocalOrder() {
|
||||
if (!this.store.chosenLocalOrderId) return 0;
|
||||
const localOrder = window.localStorage.getItem(this.store.chosenLocalOrderId);
|
||||
|
||||
if (!localOrder) return -1;
|
||||
|
||||
const orderObj: LocalStorageOrder = {
|
||||
id: this.store.chosenLocalOrderId,
|
||||
orderType: this.store.chosenOrderType,
|
||||
orderBody: this.store[this.store.chosenOrderType],
|
||||
orderFooter: this.store.orderFooter,
|
||||
updatedAt: Date.now(),
|
||||
orderVersion: import.meta.env['VITE_APP_ORDER_VERSION'] || '1'
|
||||
};
|
||||
|
||||
window.localStorage.setItem(this.store.chosenLocalOrderId, JSON.stringify(orderObj));
|
||||
|
||||
return 1;
|
||||
},
|
||||
|
||||
removeLocalOrder(order: LocalStorageOrder) {
|
||||
localStorage.removeItem(order.id);
|
||||
|
||||
if (this.store.chosenLocalOrderId == order.id) this.store.chosenLocalOrderId = '';
|
||||
// localStorage.setItem('orderCount', (Number(localStorage.getItem('orderCount')) - 1).toString());
|
||||
},
|
||||
|
||||
selectLocalOrder(localOrder: LocalStorageOrder) {
|
||||
// const localOrder = JSON.parse(JSON.stringify(order));
|
||||
const { orderBody: localOrderBody, orderFooter: localOrderFooter } = localOrder;
|
||||
|
||||
this.store[localOrder.orderType].header.date = localOrderBody.header.date;
|
||||
this.store[localOrder.orderType].header.orderNo = localOrderBody.header.orderNo;
|
||||
this.store[localOrder.orderType].header.trainNo = localOrderBody.header.trainNo;
|
||||
|
||||
if (localOrder.orderType == 'orderN' || localOrder.orderType == 'orderS') {
|
||||
const currentOrder = this.store[localOrder.orderType];
|
||||
|
||||
if (localOrderBody.rows.length != currentOrder.rows.length) {
|
||||
alertWrongOrderFormat();
|
||||
return;
|
||||
}
|
||||
|
||||
for (let rowIndex = 0; rowIndex < currentOrder.rows.length; rowIndex++) {
|
||||
const row = currentOrder.rows[rowIndex];
|
||||
|
||||
if (localOrderBody.rows[rowIndex] === undefined) {
|
||||
alertWrongOrderFormat();
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const rowProp in row) {
|
||||
if (localOrderBody.rows[rowIndex][rowProp] === undefined) {
|
||||
alertWrongOrderFormat();
|
||||
continue;
|
||||
}
|
||||
|
||||
(currentOrder.rows[rowIndex] as any)[rowProp] = localOrderBody.rows[rowIndex][rowProp];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (localOrder.orderType == 'orderO') {
|
||||
const currentOrder = this.store[localOrder.orderType];
|
||||
|
||||
for (let rowIndex = 0; rowIndex < currentOrder.orderList.length; rowIndex++) {
|
||||
const row = currentOrder.orderList[rowIndex];
|
||||
|
||||
if (localOrderBody.orderList[rowIndex] === undefined) {
|
||||
alertWrongOrderFormat();
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const rowProp in row) {
|
||||
if (localOrderBody.orderList[rowIndex][rowProp] === undefined) {
|
||||
alertWrongOrderFormat();
|
||||
continue;
|
||||
}
|
||||
|
||||
(currentOrder.orderList[rowIndex] as any)[rowProp] =
|
||||
localOrderBody.orderList[rowIndex][rowProp];
|
||||
}
|
||||
}
|
||||
|
||||
currentOrder.other = localOrderBody.other;
|
||||
}
|
||||
|
||||
for (const key in this.store.orderFooter) {
|
||||
(this.store.orderFooter as any)[key] = localOrderFooter[key];
|
||||
}
|
||||
|
||||
this.store.chosenOrderType = localOrder.orderType;
|
||||
this.store.chosenLocalOrderId = localOrder.id;
|
||||
this.store.panelMode = 'OrderMessagePanel';
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1,32 +0,0 @@
|
||||
import { defineComponent } from 'vue';
|
||||
import { useStore } from '../store/store';
|
||||
|
||||
export default defineComponent({
|
||||
setup() {
|
||||
return {
|
||||
store: useStore(),
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
verifyOrderFields() {
|
||||
// const header = this.store[this.store.chosenOrderType].header;
|
||||
const footer = this.store.orderFooter;
|
||||
|
||||
const fieldsToCorrect = [];
|
||||
|
||||
// if (!header.orderNo) fieldsToCorrect.push('numer rozkazu');
|
||||
// if (!header.trainNo) fieldsToCorrect.push('numer pociągu / manewru');
|
||||
// if (!header.date) fieldsToCorrect.push('data');
|
||||
|
||||
if (!footer.stationName) fieldsToCorrect.push('stacja');
|
||||
if (!footer.checkpointName) fieldsToCorrect.push('posterunek');
|
||||
if (!footer.hour) fieldsToCorrect.push('godzina');
|
||||
if (!footer.minutes) fieldsToCorrect.push('minuta');
|
||||
if (!footer.dispatcherName && !footer.secondaryDispatcherName)
|
||||
fieldsToCorrect.push('dyżurny ruchu (lub z polecenia dyżurnego ruchu)');
|
||||
|
||||
return fieldsToCorrect;
|
||||
}
|
||||
}
|
||||
});
|
||||
+300
-178
@@ -1,12 +1,9 @@
|
||||
import { defineStore } from 'pinia';
|
||||
import { IOrderN, IOrderO, IOrderS, TOrder, TPanel } from '../types/orderTypes';
|
||||
import {
|
||||
currentFormattedDate,
|
||||
currentFormattedHours,
|
||||
currentFormattedMinutes
|
||||
} from '../utils/dateUtils';
|
||||
import i18n from '../i18n';
|
||||
import { IOrderData } from '../types/orderTypes';
|
||||
|
||||
import StorageManager from '../managers/storageManager';
|
||||
import i18n from '../i18n';
|
||||
import { TPanelMode } from '../types/dataTypes';
|
||||
|
||||
export const useStore = defineStore('store', {
|
||||
state: () => {
|
||||
@@ -19,203 +16,328 @@ export const useStore = defineStore('store', {
|
||||
releaseURL: ''
|
||||
},
|
||||
|
||||
isMigrationInfoOpen: false,
|
||||
updateCardOpen: false,
|
||||
helperModalOpen: false,
|
||||
orderDarkMode: false,
|
||||
|
||||
chosenOrderType: 'orderN' as TOrder,
|
||||
panelMode: 'OrderMessagePanel' as TPanelMode,
|
||||
|
||||
chosenLocalOrderId: '',
|
||||
|
||||
panelMode: 'OrderMessagePanel' as TPanel,
|
||||
|
||||
orderFooter: {
|
||||
stationName: '',
|
||||
checkpointName: '',
|
||||
hour: currentFormattedHours(),
|
||||
minutes: currentFormattedMinutes(),
|
||||
dispatcherName: '',
|
||||
secondaryDispatcherName: ''
|
||||
},
|
||||
|
||||
orderMessage: '',
|
||||
footerMessage: '',
|
||||
|
||||
orderO: {
|
||||
orderData: {
|
||||
header: {
|
||||
orderNo: '1',
|
||||
trainNo: '',
|
||||
date: currentFormattedDate()
|
||||
A: '',
|
||||
B: '',
|
||||
C: '',
|
||||
D: ''
|
||||
},
|
||||
|
||||
orderList: [
|
||||
instructions: [
|
||||
{
|
||||
name: '',
|
||||
from: '',
|
||||
to: '',
|
||||
vmax: '',
|
||||
jo: false,
|
||||
reason: ''
|
||||
key: '22',
|
||||
name: '22',
|
||||
active: false,
|
||||
inputFields: {},
|
||||
optionalFieldNames: [],
|
||||
textDirectives: []
|
||||
},
|
||||
{
|
||||
name: '',
|
||||
from: '',
|
||||
to: '',
|
||||
vmax: '',
|
||||
jo: false,
|
||||
reason: ''
|
||||
key: '99',
|
||||
name: '99',
|
||||
active: false,
|
||||
inputFields: {
|
||||
x1: ''
|
||||
},
|
||||
optionalFieldNames: [],
|
||||
textDirectives: []
|
||||
},
|
||||
{
|
||||
name: '',
|
||||
from: '',
|
||||
to: '',
|
||||
vmax: '',
|
||||
jo: false,
|
||||
reason: ''
|
||||
key: '2110',
|
||||
name: '21.10',
|
||||
active: false,
|
||||
inputFields: {
|
||||
track1: '',
|
||||
signalbox1: '',
|
||||
track2: '',
|
||||
signalbox2: '',
|
||||
signal1: '',
|
||||
signal2: '',
|
||||
signal3: ''
|
||||
},
|
||||
optionalFieldNames: ['signal1', 'signal2', 'signal3'],
|
||||
textDirectives: ['bold1', 'br']
|
||||
},
|
||||
{
|
||||
name: '',
|
||||
from: '',
|
||||
to: '',
|
||||
vmax: '',
|
||||
jo: false,
|
||||
reason: ''
|
||||
key: '2115',
|
||||
name: '21.15',
|
||||
active: false,
|
||||
inputFields: {
|
||||
track1: '',
|
||||
signalbox1: '',
|
||||
track2: '',
|
||||
signal1: '',
|
||||
signal2: '',
|
||||
signal3: ''
|
||||
},
|
||||
optionalFieldNames: ['signal1', 'signal2', 'signal3'],
|
||||
textDirectives: ['bold1', 'br']
|
||||
},
|
||||
{
|
||||
name: '',
|
||||
from: '',
|
||||
to: '',
|
||||
vmax: '',
|
||||
jo: false,
|
||||
reason: ''
|
||||
key: '2120',
|
||||
name: '21.20',
|
||||
active: false,
|
||||
inputFields: {
|
||||
signalbox1: '',
|
||||
signalbox2: '',
|
||||
track1: ''
|
||||
},
|
||||
optionalFieldNames: [],
|
||||
textDirectives: ['highlight1', 'highlight2', 'underline1', 'br']
|
||||
},
|
||||
{
|
||||
key: '2125',
|
||||
name: '21.25',
|
||||
active: false,
|
||||
inputFields: {
|
||||
select1: 'select1-a',
|
||||
signalbox1: '',
|
||||
track1: '',
|
||||
km1: '',
|
||||
hour1: ''
|
||||
},
|
||||
selectFields: {
|
||||
select1: {
|
||||
options: ['select1-a', 'select1-b']
|
||||
}
|
||||
},
|
||||
optionalFieldNames: [],
|
||||
textDirectives: []
|
||||
},
|
||||
{
|
||||
key: '2135',
|
||||
name: '21.35',
|
||||
active: false,
|
||||
inputFields: {
|
||||
track1: '',
|
||||
signalbox1: ''
|
||||
},
|
||||
optionalFieldNames: [],
|
||||
textDirectives: ['bold1']
|
||||
},
|
||||
{
|
||||
key: '2140',
|
||||
name: '21.40',
|
||||
active: false,
|
||||
inputFields: {
|
||||
signalbox1: '',
|
||||
signalbox2: '',
|
||||
km1: '',
|
||||
other1: ''
|
||||
},
|
||||
optionalFieldNames: ['signalbox2'],
|
||||
textDirectives: ['bold1']
|
||||
},
|
||||
{
|
||||
key: '2145',
|
||||
name: '21.45',
|
||||
active: false,
|
||||
inputFields: {
|
||||
signalbox1: '',
|
||||
signal1: ''
|
||||
},
|
||||
optionalFieldNames: [],
|
||||
textDirectives: ['bold1', 'br']
|
||||
},
|
||||
{
|
||||
key: '2150',
|
||||
name: '21.50',
|
||||
active: false,
|
||||
inputFields: {
|
||||
signalbox1: '',
|
||||
signalbox2: '',
|
||||
km1: ''
|
||||
},
|
||||
optionalFieldNames: ['signalbox2'],
|
||||
textDirectives: ['bold1', 'br', 'bold2']
|
||||
},
|
||||
{
|
||||
key: '2155',
|
||||
name: '21.55',
|
||||
active: false,
|
||||
inputFields: {
|
||||
signalbox1: '',
|
||||
signalbox2: '',
|
||||
signal1: ''
|
||||
},
|
||||
optionalFieldNames: ['signalbox2'],
|
||||
textDirectives: ['bold1']
|
||||
},
|
||||
{
|
||||
key: '2160',
|
||||
name: '21.60',
|
||||
active: false,
|
||||
inputFields: {
|
||||
signalbox1: '',
|
||||
signalbox2: '',
|
||||
signalbox3: '',
|
||||
line1: '',
|
||||
vmax1: ''
|
||||
},
|
||||
optionalFieldNames: [],
|
||||
textDirectives: ['bold1']
|
||||
},
|
||||
{
|
||||
key: '2165',
|
||||
name: '21.65',
|
||||
active: false,
|
||||
inputFields: {
|
||||
km1: '',
|
||||
km2: ''
|
||||
},
|
||||
optionalFieldNames: [],
|
||||
textDirectives: ['bold1']
|
||||
},
|
||||
{
|
||||
key: '2170',
|
||||
name: '21.70',
|
||||
active: false,
|
||||
inputFields: {
|
||||
signalbox1: '',
|
||||
signalbox2: '',
|
||||
line1: ''
|
||||
},
|
||||
optionalFieldNames: [],
|
||||
textDirectives: ['bold1', 'br', 'bold2']
|
||||
},
|
||||
{
|
||||
key: '2180',
|
||||
name: '21.80',
|
||||
active: false,
|
||||
inputFields: {
|
||||
track1: '',
|
||||
signalbox1: '',
|
||||
km1: '',
|
||||
signalbox2: '',
|
||||
hour1: ''
|
||||
},
|
||||
optionalFieldNames: [],
|
||||
textDirectives: ['bold1']
|
||||
},
|
||||
{
|
||||
key: '2181',
|
||||
name: '21.81',
|
||||
active: false,
|
||||
inputFields: {},
|
||||
optionalFieldNames: [],
|
||||
textDirectives: ['bold1']
|
||||
},
|
||||
{
|
||||
key: '2182',
|
||||
name: '21.82',
|
||||
active: false,
|
||||
inputFields: {
|
||||
train1: '',
|
||||
km1: ''
|
||||
},
|
||||
optionalFieldNames: [],
|
||||
textDirectives: ['bold1']
|
||||
},
|
||||
{
|
||||
key: '2183',
|
||||
name: '21.83',
|
||||
active: false,
|
||||
inputFields: {
|
||||
train1: '',
|
||||
km1: ''
|
||||
},
|
||||
optionalFieldNames: [],
|
||||
textDirectives: ['bold1']
|
||||
},
|
||||
{
|
||||
key: '2185',
|
||||
name: '21.85',
|
||||
active: false,
|
||||
inputFields: {
|
||||
track1: '',
|
||||
km1: '',
|
||||
signalbox1: '',
|
||||
signalbox2: ''
|
||||
},
|
||||
optionalFieldNames: [],
|
||||
textDirectives: ['bold1']
|
||||
},
|
||||
{
|
||||
key: '2310',
|
||||
name: '23.10',
|
||||
active: false,
|
||||
inputFields: {},
|
||||
listFields: [
|
||||
{
|
||||
active: false,
|
||||
values: {
|
||||
signalbox1: '',
|
||||
signalbox2: '',
|
||||
track1: '',
|
||||
vmax1: '',
|
||||
km1: '',
|
||||
km2: '',
|
||||
other1: ''
|
||||
}
|
||||
},
|
||||
{
|
||||
active: false,
|
||||
values: {
|
||||
signalbox1: '',
|
||||
signalbox2: '',
|
||||
track1: '',
|
||||
vmax1: '',
|
||||
km1: '',
|
||||
km2: '',
|
||||
other1: ''
|
||||
}
|
||||
},
|
||||
{
|
||||
active: false,
|
||||
values: {
|
||||
signalbox1: '',
|
||||
signalbox2: '',
|
||||
track1: '',
|
||||
vmax1: '',
|
||||
km1: '',
|
||||
km2: '',
|
||||
other1: ''
|
||||
}
|
||||
}
|
||||
],
|
||||
other: ''
|
||||
} as IOrderO,
|
||||
|
||||
orderN: {
|
||||
header: {
|
||||
orderNo: '1',
|
||||
trainNo: '',
|
||||
date: currentFormattedDate()
|
||||
},
|
||||
|
||||
rows: [
|
||||
{
|
||||
enabled: false,
|
||||
from: '',
|
||||
to: '',
|
||||
trackNo: '',
|
||||
trackNo2: ''
|
||||
optionalFieldNames: [],
|
||||
textDirectives: ['bold1', 'br']
|
||||
},
|
||||
{
|
||||
enabled: false,
|
||||
option1: 'sygnału "Nakaz Jazdy"',
|
||||
option2: 'lewy',
|
||||
option3: 'lewy',
|
||||
signal1: '',
|
||||
signal2: '',
|
||||
signal3: '',
|
||||
signalType: 'wyjazdowego',
|
||||
checkbox: 'checkbox-2a',
|
||||
direction1: '',
|
||||
direction2: '',
|
||||
trackNoFrom: '',
|
||||
trackNoTo1: '',
|
||||
trackNoTo2: ''
|
||||
key: '2311',
|
||||
name: '23.11',
|
||||
active: false,
|
||||
inputFields: {},
|
||||
optionalFieldNames: [],
|
||||
textDirectives: ['bold1']
|
||||
},
|
||||
{
|
||||
enabled: false,
|
||||
option1: 'Jazda',
|
||||
option2: 'pociąg',
|
||||
|
||||
direction: '',
|
||||
toKilometer: '',
|
||||
trackNo: '',
|
||||
untilHour: '',
|
||||
untilMin: ''
|
||||
key: '2320',
|
||||
name: '23.20',
|
||||
active: false,
|
||||
inputFields: {
|
||||
other2320: ''
|
||||
},
|
||||
{
|
||||
enabled: false,
|
||||
trackNo: '',
|
||||
optionStation: 'stację',
|
||||
stationName: '',
|
||||
checkbox: 'checkbox-4a',
|
||||
side: 'lewej'
|
||||
},
|
||||
{
|
||||
enabled: false,
|
||||
trackNo: '',
|
||||
direction: '',
|
||||
stationType: 'stację',
|
||||
stationName: '',
|
||||
on: ''
|
||||
},
|
||||
{
|
||||
enabled: false,
|
||||
content: '',
|
||||
twoWay: {
|
||||
enabled: false,
|
||||
from: '',
|
||||
to: '',
|
||||
trackNo: ''
|
||||
optionalFieldNames: [],
|
||||
textDirectives: []
|
||||
}
|
||||
],
|
||||
footer: {
|
||||
V: '',
|
||||
W: '',
|
||||
Y: '',
|
||||
Z: ''
|
||||
}
|
||||
]
|
||||
} as IOrderN,
|
||||
} as IOrderData,
|
||||
|
||||
orderS: {
|
||||
header: {
|
||||
orderNo: '1',
|
||||
trainNo: '',
|
||||
for: 'pociągu',
|
||||
date: currentFormattedDate()
|
||||
},
|
||||
|
||||
rows: [
|
||||
{
|
||||
enabled: false,
|
||||
option1: 'sygnału "nakaz jazdy"',
|
||||
optionSignal: 'wyjazdowego',
|
||||
radio1: 'radio-1a-1',
|
||||
signal1: '',
|
||||
trackNo: ''
|
||||
},
|
||||
|
||||
{
|
||||
enabled: false,
|
||||
signalType: 'wyjazdowego',
|
||||
signal1: '',
|
||||
signal2: '',
|
||||
signal3: '',
|
||||
trackNo: ''
|
||||
},
|
||||
|
||||
{
|
||||
enabled: false,
|
||||
from: '',
|
||||
to: '',
|
||||
trackNo: '',
|
||||
trainNo: '',
|
||||
arrivedTo: '',
|
||||
hour: ''
|
||||
},
|
||||
|
||||
{
|
||||
enabled: false,
|
||||
content: '',
|
||||
w5: {
|
||||
enabled: false,
|
||||
maxHour: '',
|
||||
borderType: 'wskaźnik przetaczania W5',
|
||||
tmName: '',
|
||||
maxKm: '',
|
||||
returnWay: 'sygnał ręczny "Do mnie"',
|
||||
trackNo: ''
|
||||
}
|
||||
}
|
||||
]
|
||||
} as IOrderS
|
||||
orderMessage: ''
|
||||
};
|
||||
},
|
||||
actions: {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
$bgCol: #141414;
|
||||
$bgCol: #0e0e0e;
|
||||
$bgColLighter: #292929;
|
||||
$bgColDarker: #080808;
|
||||
$accentCol: #ff6060;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
/* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
|
||||
/* libre-franklin-regular - latin_latin-ext */
|
||||
@font-face {
|
||||
font-display: swap;
|
||||
font-family: 'Libre Franklin';
|
||||
@@ -5,7 +7,7 @@
|
||||
font-weight: 400;
|
||||
src: url('/fonts/libre-franklin-regular.woff2') format('woff2');
|
||||
}
|
||||
|
||||
/* libre-franklin-500 - latin_latin-ext */
|
||||
@font-face {
|
||||
font-display: swap;
|
||||
font-family: 'Libre Franklin';
|
||||
@@ -13,7 +15,7 @@
|
||||
font-weight: 500;
|
||||
src: url('/fonts/libre-franklin-500.woff2') format('woff2');
|
||||
}
|
||||
|
||||
/* libre-franklin-700 - latin_latin-ext */
|
||||
@font-face {
|
||||
font-display: swap;
|
||||
font-family: 'Libre Franklin';
|
||||
@@ -21,7 +23,7 @@
|
||||
font-weight: 700;
|
||||
src: url('/fonts/libre-franklin-700.woff2') format('woff2');
|
||||
}
|
||||
|
||||
/* libre-franklin-800 - latin_latin-ext */
|
||||
@font-face {
|
||||
font-display: swap;
|
||||
font-family: 'Libre Franklin';
|
||||
|
||||
+10
-6
@@ -1,9 +1,6 @@
|
||||
@use 'fonts';
|
||||
@use 'colors';
|
||||
|
||||
[data-theme='dark'] {
|
||||
color-scheme: dark;
|
||||
}
|
||||
@use 'sass:color';
|
||||
|
||||
body,
|
||||
html {
|
||||
@@ -57,14 +54,13 @@ button.g-button {
|
||||
&.action {
|
||||
background-color: colors.$bgColDarker;
|
||||
padding: 0.5em;
|
||||
color: white;
|
||||
|
||||
&:focus-visible {
|
||||
outline: 2px solid colors.$accentCol;
|
||||
}
|
||||
|
||||
&:hover:not([data-disabled='true']) {
|
||||
background-color: colors.$bgColLighter;
|
||||
background-color: color.adjust(colors.$bgColDarker, $lightness: 15%);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,6 +96,10 @@ button.g-button {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
&:focus-visible {
|
||||
outline: 1px solid white;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,6 +112,10 @@ button.g-button {
|
||||
&--warn {
|
||||
color: colors.$warnCol;
|
||||
}
|
||||
|
||||
&--grayed {
|
||||
color: #ccc;
|
||||
}
|
||||
}
|
||||
|
||||
// Select style
|
||||
|
||||
@@ -0,0 +1,157 @@
|
||||
@use 'colors';
|
||||
|
||||
$darkModeTextCol: #eee;
|
||||
|
||||
.order {
|
||||
width: 100%;
|
||||
background-color: white;
|
||||
color: black;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
|
||||
&.dark {
|
||||
background-color: colors.$bgColDarker;
|
||||
color: $darkModeTextCol;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 550px) {
|
||||
font-size: 0.85em;
|
||||
}
|
||||
}
|
||||
|
||||
table.order-table {
|
||||
width: 100%;
|
||||
overflow: auto;
|
||||
table-layout: fixed;
|
||||
min-width: 750px;
|
||||
|
||||
border: 2px solid black;
|
||||
border-collapse: collapse;
|
||||
|
||||
td {
|
||||
border: 2px solid black;
|
||||
border-collapse: collapse;
|
||||
|
||||
text-align: justify;
|
||||
vertical-align: top;
|
||||
}
|
||||
}
|
||||
|
||||
.order-input-box {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
padding-bottom: 1.25em;
|
||||
|
||||
& > span {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 0;
|
||||
transform: translate(-50%, 2em);
|
||||
font-size: 0.8em;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
input.order-input {
|
||||
max-width: 100%;
|
||||
background-color: transparent;
|
||||
outline: none;
|
||||
border: none;
|
||||
font-size: 1em;
|
||||
|
||||
text-align: center;
|
||||
border-bottom: 2px dotted black;
|
||||
|
||||
&:focus-visible {
|
||||
border-bottom: 2px solid colors.$accentCol;
|
||||
}
|
||||
|
||||
&.row-checkbox + input::placeholder {
|
||||
color: red;
|
||||
}
|
||||
|
||||
&[type='checkbox']:focus-visible,
|
||||
&[type='radio']:focus-visible {
|
||||
outline: 2px solid colors.$accentCol;
|
||||
}
|
||||
|
||||
&[type='checkbox'],
|
||||
&[type='radio'] {
|
||||
margin-top: 0.5em;
|
||||
margin-right: 0.5em;
|
||||
font-size: 0.8em;
|
||||
color: black;
|
||||
}
|
||||
|
||||
&::placeholder {
|
||||
font-size: 0.85em;
|
||||
}
|
||||
}
|
||||
|
||||
label.order-input-label {
|
||||
display: block;
|
||||
margin-top: 0.5rem;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
select.order-select {
|
||||
margin-top: 0.5em;
|
||||
margin-right: 0.5em;
|
||||
font-size: 0.8em;
|
||||
color: black;
|
||||
}
|
||||
|
||||
textarea.order-textarea {
|
||||
width: 100%;
|
||||
min-height: 200px;
|
||||
resize: vertical;
|
||||
|
||||
&:focus-visible {
|
||||
outline: 2px solid colors.$accentCol;
|
||||
}
|
||||
}
|
||||
|
||||
// Dark mode
|
||||
.order.dark {
|
||||
input.order-input {
|
||||
border-color: $darkModeTextCol !important;
|
||||
color: $darkModeTextCol !important;
|
||||
|
||||
&:focus-visible {
|
||||
border-bottom: 2px solid colors.$accentCol !important;
|
||||
}
|
||||
|
||||
&::placeholder {
|
||||
color: #ccc !important;
|
||||
}
|
||||
}
|
||||
|
||||
select.order-select {
|
||||
color: $darkModeTextCol !important;
|
||||
border-color: $darkModeTextCol;
|
||||
|
||||
&:focus-visible {
|
||||
border-color: colors.$accentCol;
|
||||
}
|
||||
}
|
||||
|
||||
select.order-select option,
|
||||
textarea.order-textarea {
|
||||
color: $darkModeTextCol !important;
|
||||
border-color: $darkModeTextCol !important;
|
||||
background-color: colors.$bgColDarker !important;
|
||||
}
|
||||
|
||||
.horizontal-bar {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.order_header,
|
||||
.order_other,
|
||||
table.order-table,
|
||||
tr,
|
||||
td {
|
||||
border-color: $darkModeTextCol !important;
|
||||
}
|
||||
}
|
||||
+2
-17
@@ -33,20 +33,5 @@ export interface ISceneryData {
|
||||
signalType: string;
|
||||
url: string;
|
||||
}
|
||||
// export interface ITrainData {
|
||||
// trainNo: number;
|
||||
// driverId: number;
|
||||
// driverName: string;
|
||||
// driverIsSupporter: boolean;
|
||||
// dataSignal: string;
|
||||
// dataSceneryConnection: string;
|
||||
// dataDistance: number;
|
||||
// dataCon: string;
|
||||
// dataSpeed: number;
|
||||
// dataMass: number;
|
||||
// dataLength: number;
|
||||
// region: string;
|
||||
// isOnline: number;
|
||||
// lastSeen: number;
|
||||
// station?: ISceneryData;
|
||||
// }
|
||||
|
||||
export type TPanelMode = 'OrderListPanel' | 'OrderMessagePanel' | 'OrderTrainPickerPanel';
|
||||
+40
-171
@@ -1,7 +1,6 @@
|
||||
export type TOrder = 'orderO' | 'orderS' | 'orderN';
|
||||
export type TPanel = 'OrderMessagePanel' | 'OrderListPanel' | 'OrderTrainPickerPanel';
|
||||
|
||||
export interface LocalStorageOrder {
|
||||
export interface LocalStorageOrderLegacy {
|
||||
id: string;
|
||||
orderType: TOrder;
|
||||
orderBody: any;
|
||||
@@ -11,177 +10,47 @@ export interface LocalStorageOrder {
|
||||
orderVersion?: string;
|
||||
}
|
||||
|
||||
export interface IOrderN {
|
||||
header: {
|
||||
orderNo: string;
|
||||
trainNo: string;
|
||||
date: string;
|
||||
};
|
||||
|
||||
rows: [
|
||||
{
|
||||
enabled: boolean;
|
||||
from: string;
|
||||
to: string;
|
||||
trackNo: string;
|
||||
trackNo2: string;
|
||||
},
|
||||
{
|
||||
enabled: boolean;
|
||||
option1: string;
|
||||
option2: string;
|
||||
option3: string;
|
||||
signal1: string;
|
||||
signal2: string;
|
||||
signal3: string;
|
||||
signalType: string;
|
||||
checkbox: string;
|
||||
direction1: string;
|
||||
direction2: string;
|
||||
trackNoFrom: string;
|
||||
trackNoTo1: string;
|
||||
trackNoTo2: string;
|
||||
},
|
||||
{
|
||||
enabled: boolean;
|
||||
option1: string;
|
||||
option2: string;
|
||||
|
||||
direction: string;
|
||||
toKilometer: string;
|
||||
trackNo: string;
|
||||
untilHour: string;
|
||||
untilMin: string;
|
||||
},
|
||||
{
|
||||
enabled: boolean;
|
||||
trackNo: string;
|
||||
optionStation: string;
|
||||
stationName: string;
|
||||
checkbox: string;
|
||||
side: string;
|
||||
},
|
||||
{
|
||||
enabled: boolean;
|
||||
trackNo: string;
|
||||
direction: string;
|
||||
stationType: string;
|
||||
stationName: string;
|
||||
on: string;
|
||||
},
|
||||
{
|
||||
enabled: boolean;
|
||||
content: string;
|
||||
twoWay: {
|
||||
enabled: boolean;
|
||||
from: string;
|
||||
to: string;
|
||||
trackNo: string;
|
||||
};
|
||||
}
|
||||
];
|
||||
export interface IStorageOrderData {
|
||||
id: string;
|
||||
orderVersion: string;
|
||||
createdAt?: number;
|
||||
updatedAt?: number;
|
||||
orderData: IOrderData;
|
||||
}
|
||||
|
||||
export interface IOrderS {
|
||||
header: {
|
||||
orderNo: string;
|
||||
trainNo: string;
|
||||
for: string;
|
||||
date: string;
|
||||
};
|
||||
|
||||
rows: [
|
||||
{
|
||||
enabled: boolean;
|
||||
option1: string;
|
||||
optionSignal: string;
|
||||
radio1: string;
|
||||
signal1: string;
|
||||
trackNo: string;
|
||||
},
|
||||
{
|
||||
enabled: boolean;
|
||||
signalType: string;
|
||||
signal1: string;
|
||||
signal2: string;
|
||||
signal3: string;
|
||||
trackNo: string;
|
||||
},
|
||||
{
|
||||
enabled: boolean;
|
||||
from: string;
|
||||
to: string;
|
||||
trackNo: string;
|
||||
trainNo: string;
|
||||
arrivedTo: string;
|
||||
hour: string;
|
||||
},
|
||||
{
|
||||
enabled: boolean;
|
||||
content: string;
|
||||
|
||||
w5: {
|
||||
enabled: boolean;
|
||||
borderType: string;
|
||||
trackNo: string;
|
||||
maxKm: string;
|
||||
returnWay: string;
|
||||
maxHour: string;
|
||||
tmName: string;
|
||||
};
|
||||
}
|
||||
];
|
||||
export interface IOrderData {
|
||||
header: IOrderHeader;
|
||||
instructions: IOrderInstruction[];
|
||||
footer: IOrderFooter;
|
||||
}
|
||||
|
||||
export interface IOrderO {
|
||||
header: {
|
||||
orderNo: string;
|
||||
trainNo: string;
|
||||
date: string;
|
||||
};
|
||||
|
||||
orderList: [
|
||||
{
|
||||
name: string;
|
||||
from: string;
|
||||
to: string;
|
||||
vmax: string;
|
||||
jo: boolean;
|
||||
reason: string;
|
||||
},
|
||||
{
|
||||
name: string;
|
||||
from: string;
|
||||
to: string;
|
||||
vmax: string;
|
||||
jo: boolean;
|
||||
reason: string;
|
||||
},
|
||||
{
|
||||
name: string;
|
||||
from: string;
|
||||
to: string;
|
||||
vmax: string;
|
||||
jo: boolean;
|
||||
reason: string;
|
||||
},
|
||||
{
|
||||
name: string;
|
||||
from: string;
|
||||
to: string;
|
||||
vmax: string;
|
||||
jo: boolean;
|
||||
reason: string;
|
||||
},
|
||||
{
|
||||
name: string;
|
||||
from: string;
|
||||
to: string;
|
||||
vmax: string;
|
||||
jo: boolean;
|
||||
reason: string;
|
||||
}
|
||||
];
|
||||
|
||||
other: string;
|
||||
export interface IOrderHeader {
|
||||
A: string;
|
||||
B: string;
|
||||
C: string;
|
||||
D: string;
|
||||
}
|
||||
|
||||
export interface IOrderFooter {
|
||||
V: string;
|
||||
W: string;
|
||||
Y: string;
|
||||
Z: string;
|
||||
}
|
||||
|
||||
export interface IOrderFieldItem {
|
||||
active: false;
|
||||
values: Record<string, string>;
|
||||
}
|
||||
|
||||
export interface IOrderInstruction {
|
||||
key: string;
|
||||
name: string;
|
||||
active: boolean;
|
||||
inputFields: Record<string, string>;
|
||||
optionalFieldNames: string[];
|
||||
textDirectives: string[];
|
||||
|
||||
selectFields?: Record<string, Record<string, string[]>>;
|
||||
listFields?: IOrderFieldItem[];
|
||||
}
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
export function currentFormattedDate() {
|
||||
return (
|
||||
new Date().toLocaleDateString('pl-PL', {
|
||||
day: 'numeric',
|
||||
month: 'numeric',
|
||||
year: 'numeric'
|
||||
}) + 'r.'
|
||||
);
|
||||
}
|
||||
|
||||
export function currentFormattedMinutes() {
|
||||
const date = new Date();
|
||||
return (date.getMinutes() < 10 ? '0' : '') + date.getMinutes();
|
||||
}
|
||||
|
||||
export function currentFormattedHours() {
|
||||
return new Date().toLocaleTimeString('pl-PL', { hour: '2-digit' });
|
||||
}
|
||||
+22
-191
@@ -1,197 +1,28 @@
|
||||
import { IOrderN, IOrderO, IOrderS, TOrder } from '../types/orderTypes';
|
||||
import { currentFormattedDate } from './dateUtils';
|
||||
|
||||
const orderDefaults = {
|
||||
orderN: {
|
||||
header: {
|
||||
orderNo: '1',
|
||||
trainNo: '',
|
||||
date: ''
|
||||
},
|
||||
|
||||
rows: [
|
||||
{
|
||||
enabled: false,
|
||||
from: '',
|
||||
to: '',
|
||||
trackNo: '',
|
||||
trackNo2: ''
|
||||
},
|
||||
{
|
||||
enabled: false,
|
||||
option1: 'sygnału "Nakaz Jazdy"',
|
||||
option2: 'lewy',
|
||||
option3: 'lewy',
|
||||
signal1: '',
|
||||
signal2: '',
|
||||
signal3: '',
|
||||
signalType: 'wyjazdowego',
|
||||
checkbox: 'checkbox-2a',
|
||||
direction1: '',
|
||||
direction2: '',
|
||||
trackNoFrom: '',
|
||||
trackNoTo1: '',
|
||||
trackNoTo2: ''
|
||||
},
|
||||
{
|
||||
enabled: false,
|
||||
option1: 'Jazda',
|
||||
option2: 'pociąg',
|
||||
|
||||
direction: '',
|
||||
toKilometer: '',
|
||||
trackNo: '',
|
||||
untilHour: '',
|
||||
untilMin: ''
|
||||
},
|
||||
{
|
||||
enabled: false,
|
||||
trackNo: '',
|
||||
optionStation: 'stację',
|
||||
stationName: '',
|
||||
checkbox: 'checkbox-4a',
|
||||
side: 'lewej'
|
||||
},
|
||||
{
|
||||
enabled: false,
|
||||
trackNo: '',
|
||||
direction: '',
|
||||
stationType: 'stację',
|
||||
stationName: '',
|
||||
on: ''
|
||||
},
|
||||
{
|
||||
enabled: false,
|
||||
content: '',
|
||||
twoWay: {
|
||||
enabled: false,
|
||||
from: '',
|
||||
to: '',
|
||||
trackNo: ''
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
orderS: {
|
||||
header: {
|
||||
orderNo: '1',
|
||||
trainNo: '',
|
||||
for: 'pociągu',
|
||||
date: ''
|
||||
},
|
||||
|
||||
rows: [
|
||||
{
|
||||
enabled: false,
|
||||
option1: 'sygnału "nakaz jazdy"',
|
||||
optionSignal: 'wyjazdowego',
|
||||
radio1: 'radio-1a-1',
|
||||
signal1: '',
|
||||
trackNo: ''
|
||||
},
|
||||
|
||||
{
|
||||
enabled: false,
|
||||
signalType: 'wyjazdowego',
|
||||
signal1: '',
|
||||
signal2: '',
|
||||
signal3: '',
|
||||
trackNo: ''
|
||||
},
|
||||
|
||||
{
|
||||
enabled: false,
|
||||
from: '',
|
||||
to: '',
|
||||
trackNo: '',
|
||||
trainNo: '',
|
||||
arrivedTo: '',
|
||||
hour: ''
|
||||
},
|
||||
|
||||
{
|
||||
enabled: false,
|
||||
content: '',
|
||||
w5: {
|
||||
enabled: false,
|
||||
maxHour: '',
|
||||
borderType: 'wskaźnik przetaczania W5',
|
||||
tmName: '',
|
||||
maxKm: '',
|
||||
returnWay: 'sygnał ręczny "Do mnie"',
|
||||
trackNo: ''
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
orderO: {
|
||||
header: {
|
||||
orderNo: '1',
|
||||
trainNo: '',
|
||||
date: ''
|
||||
},
|
||||
|
||||
orderList: [
|
||||
{
|
||||
name: '',
|
||||
from: '',
|
||||
to: '',
|
||||
vmax: '',
|
||||
jo: false,
|
||||
reason: ''
|
||||
},
|
||||
{
|
||||
name: '',
|
||||
from: '',
|
||||
to: '',
|
||||
vmax: '',
|
||||
jo: false,
|
||||
reason: ''
|
||||
},
|
||||
{
|
||||
name: '',
|
||||
from: '',
|
||||
to: '',
|
||||
vmax: '',
|
||||
jo: false,
|
||||
reason: ''
|
||||
},
|
||||
{
|
||||
name: '',
|
||||
from: '',
|
||||
to: '',
|
||||
vmax: '',
|
||||
jo: false,
|
||||
reason: ''
|
||||
},
|
||||
{
|
||||
name: '',
|
||||
from: '',
|
||||
to: '',
|
||||
vmax: '',
|
||||
jo: false,
|
||||
reason: ''
|
||||
}
|
||||
],
|
||||
other: ''
|
||||
}
|
||||
export const getOrderFullId = (orderNumber: number, sceneryHash: string) => {
|
||||
return `RD-${orderNumber}-${sceneryHash}-${new Date().getUTCFullYear().toString().slice(2)}`;
|
||||
};
|
||||
|
||||
export function getOrderType(order: IOrderN | IOrderO | IOrderS): TOrder {
|
||||
if ('rows' in order && 'for' in order.header) return 'orderS';
|
||||
else if ('rows' in order) return 'orderN';
|
||||
export const handleOrderPlaceholders = (isRowEnabled: boolean, rowRef: HTMLTableElement) => {
|
||||
rowRef.querySelectorAll('input[type="text"]').forEach((node) => {
|
||||
if (!isRowEnabled) {
|
||||
if (node.getAttribute('placeholder') != null) {
|
||||
node.setAttribute('holder', node.getAttribute('placeholder')!);
|
||||
node.removeAttribute('placeholder');
|
||||
}
|
||||
|
||||
return 'orderO';
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
export function setOrderToDefault(order: IOrderN | IOrderO | IOrderS) {
|
||||
const orderType = getOrderType(order);
|
||||
const defaultOrderObjectCopy = JSON.parse(JSON.stringify(orderDefaults[orderType]));
|
||||
if (!node.getAttribute('holder')) return;
|
||||
const radioCheckedAttr = node.getAttribute('radio-checked');
|
||||
|
||||
Object.assign(order, defaultOrderObjectCopy);
|
||||
if (radioCheckedAttr == null)
|
||||
return node.setAttribute('placeholder', node.getAttribute('holder')!);
|
||||
if (radioCheckedAttr == 'true')
|
||||
return node.setAttribute('placeholder', node.getAttribute('holder')!);
|
||||
if (node.getAttribute('placeholder') == null) return;
|
||||
|
||||
// Update date in the header
|
||||
order.header.date = currentFormattedDate();
|
||||
}
|
||||
node.setAttribute('holder', node.getAttribute('placeholder')!);
|
||||
node.removeAttribute('placeholder');
|
||||
});
|
||||
};
|
||||
+33
-20
@@ -1,9 +1,9 @@
|
||||
<template>
|
||||
<!-- <OrderHelper v-if="store.helperModalOpen" /> -->
|
||||
|
||||
<div class="home">
|
||||
<div class="home-container">
|
||||
<div class="order-container">
|
||||
<Order />
|
||||
</div>
|
||||
|
||||
<div class="panel-container">
|
||||
<div class="panel-nav">
|
||||
@@ -11,7 +11,7 @@
|
||||
key="OrderMessagePanel"
|
||||
class="g-button"
|
||||
:data-active="store.panelMode == 'OrderMessagePanel'"
|
||||
@click="selectPanelMode('OrderMessagePanel')"
|
||||
@click="selectOrderMode('OrderMessagePanel')"
|
||||
>
|
||||
<MessageSquareTextIcon :size="20" />
|
||||
{{ t(`navbar.OrderMessagePanel`) }}
|
||||
@@ -21,7 +21,7 @@
|
||||
key="OrderListPanel"
|
||||
class="g-button"
|
||||
:data-active="store.panelMode == 'OrderListPanel'"
|
||||
@click="selectPanelMode('OrderListPanel')"
|
||||
@click="selectOrderMode('OrderListPanel')"
|
||||
>
|
||||
<BookMarkedIcon :size="20" />
|
||||
{{ t(`navbar.OrderListPanel`) }}
|
||||
@@ -31,7 +31,7 @@
|
||||
key="OrderTrainPickerPanel"
|
||||
class="g-button"
|
||||
:data-active="store.panelMode == 'OrderTrainPickerPanel'"
|
||||
@click="selectPanelMode('OrderTrainPickerPanel')"
|
||||
@click="selectOrderMode('OrderTrainPickerPanel')"
|
||||
>
|
||||
<TrainFrontIcon :size="20" />
|
||||
{{ t(`navbar.OrderTrainPickerPanel`) }}
|
||||
@@ -50,20 +50,20 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useStore } from '../store/store';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
import Order from '../components/Order/Order.vue';
|
||||
import OrderMessagePanel from '../components/Panels/OrderMessagePanel.vue';
|
||||
import OrderListPanel from '../components/Panels/OrderListPanel.vue';
|
||||
import OrderTrainPickerPanel from '../components/Panels/OrderTrainPickerPanel.vue';
|
||||
import SideBar from '../components/App/SideBar.vue';
|
||||
import Order from '../components/Orders/Order.vue';
|
||||
import { TPanelMode } from '../types/dataTypes';
|
||||
import { BookMarkedIcon, MessageSquareTextIcon, TrainFrontIcon } from 'lucide-vue-next';
|
||||
import { TPanel } from '../types/orderTypes';
|
||||
|
||||
const store = useStore();
|
||||
const { t } = useI18n();
|
||||
const store = useStore();
|
||||
|
||||
function selectPanelMode(mode: TPanel) {
|
||||
function selectOrderMode(mode: TPanelMode) {
|
||||
store.panelMode = mode;
|
||||
}
|
||||
|
||||
@@ -95,35 +95,48 @@ const panelComponent = computed(() => {
|
||||
|
||||
.home-container {
|
||||
display: grid;
|
||||
grid-template-columns: 600px 500px;
|
||||
grid-template-columns: 800px 500px;
|
||||
justify-content: center;
|
||||
gap: 2em 1em;
|
||||
padding: 1em;
|
||||
width: 100%;
|
||||
|
||||
@media screen and (max-width: 1150px) {
|
||||
& > div {
|
||||
height: calc(100vh - 5em);
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1350px) {
|
||||
grid-template-columns: auto;
|
||||
padding: 1em 0.5em;
|
||||
}
|
||||
}
|
||||
|
||||
.panel-container {
|
||||
display: grid;
|
||||
grid-template-rows: auto auto 1fr;
|
||||
color-scheme: dark;
|
||||
.order-container {
|
||||
display: flex;
|
||||
align-items: start;
|
||||
max-width: 800px;
|
||||
|
||||
@media screen and (max-width: 650px) {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
||||
.panel-container {
|
||||
padding: 2px;
|
||||
max-width: 800px;
|
||||
height: calc(100vh - 5em);
|
||||
overflow: auto;
|
||||
|
||||
display: grid;
|
||||
grid-template-rows: auto auto 1fr;
|
||||
}
|
||||
|
||||
.panel-nav {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.25em;
|
||||
flex-wrap: wrap;
|
||||
|
||||
margin-bottom: 1.5em;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ export default defineConfig({
|
||||
VitePWA({
|
||||
registerType: 'prompt',
|
||||
workbox: {
|
||||
globPatterns: ['**/*.{js,css,html,png,svg,img,woff2,ico}'],
|
||||
globPatterns: ['**/*.{js,css,html,png,svg,img,woff2}'],
|
||||
runtimeCaching: [
|
||||
{
|
||||
urlPattern: /^https:\/\/stacjownik.spythere.eu\/\/api\/getSceneries/i,
|
||||
|
||||
Reference in New Issue
Block a user