chore: added generating message text for custom instructions

This commit is contained in:
2025-09-27 14:49:23 +02:00
parent 9118c186cf
commit fa4504fec7
5 changed files with 302 additions and 199 deletions
+114 -87
View File
@@ -1,13 +1,10 @@
<template>
<table class="order-table">
<tbody>
<!-- First row - 22 & 99 instructions -->
<tr>
<td width="10%" class="order-instruction-number">
<label class="order-instruction-checkbox">
<input type="checkbox" v-model="store.orderData.instructions[0].active" />
<div class="checkmark"></div>
<div class="text">22</div>
</label>
<OrderRowCheckbox :row-index="0" />
</td>
<td>
@@ -17,11 +14,7 @@
</td>
<td width="5%" class="order-instruction-number">
<label class="order-instruction-checkbox">
<input type="checkbox" v-model="store.orderData.instructions[1].active" />
<div class="checkmark"></div>
<div class="text">99</div>
</label>
<OrderRowCheckbox :row-index="1" />
</td>
<td width="45%">
@@ -39,88 +32,53 @@
</tr>
<!-- From 21.10 -->
<tr v-for="(instruction, i) in store.orderData.instructions.slice(2)">
<tr
v-for="(instruction, i) in store.orderData.instructions.slice(2)"
:style="{
'background-color': instruction.key.startsWith('218') ? '#eeece1' : 'inherit'
}"
>
<td width="10%" class="order-instruction-number">
<label class="order-instruction-checkbox">
<input type="checkbox" v-model="instruction.active" />
<div class="checkmark"></div>
<div class="text">{{ instruction.name }}</div>
</label>
<OrderRowCheckbox :row-index="i + 2" />
</td>
<td colspan="3">
<i18n-t :keypath="`order.${instruction.key}.text`" tag="div">
<!-- For all instructions with text directives -->
<template v-slot:bold1>
<b>{{ t(`order.${instruction.key}.bold1`) }}</b>
</template>
<template v-slot:bold2>
<b>{{ t(`order.${instruction.key}.bold2`) }}</b>
</template>
<template v-slot:underline1>
<u>{{ t(`order.${instruction.key}.underline1`) }}</u>
</template>
<template v-slot:highlight1>
<u>
<b>{{ t(`order.${instruction.key}.highlight1`) }}</b>
<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>
</template>
<template v-slot:highlight2>
<u>
<b>{{ t(`order.${instruction.key}.highlight2`) }}</b>
<u v-else-if="directive.startsWith('highlight')">
<b>{{ t(`order.${instruction.key}.${directive}`) }}</b>
</u>
</template>
<template v-slot:br>
<br />
</template>
<!-- For 23.10 only -->
<template v-slot:text-list v-if="instruction.key == '2310'">
<i18n-t
v-for="(fieldInputs, i) in instruction.listFields"
:keypath="`order.${instruction.key}.text-list`"
tag="div"
>
<template v-slot:bold>
<label>
<input type="checkbox" />
<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 fieldInputs">
<input
class="order-input"
:id="`order-${instruction.key}-${fieldKey}`"
:style="{ width: calculateInputWidthByFieldName(fieldKey) }"
v-model="instruction.listFields![i][fieldKey]"
:placeholder="
t(`order.${instruction.key}.${fieldKey}`, [j + 1 + 6 * i, 91 + i])
"
/>
</template>
</i18n-t>
<br v-if="directive.startsWith('br')" />
</template>
<!-- For all instructions with input fields -->
<template v-slot:[fieldKey] v-for="(_, fieldKey) in instruction.inputFields">
<input
class="order-input"
:id="`order-${instruction.key}-${fieldKey}`"
:style="{ width: calculateInputWidthByFieldName(fieldKey) }"
<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 -->
@@ -135,6 +93,48 @@
</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`"
/>
&nbsp;
<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>
@@ -146,6 +146,7 @@
import { useI18n } from 'vue-i18n';
import { useStore } from '../../store/store';
import { onMounted, watch } from 'vue';
import OrderRowCheckbox from './OrderRowCheckbox.vue';
const { t } = useI18n();
const store = useStore();
@@ -164,8 +165,11 @@ watch(
function calculateInputWidthByFieldName(fieldName: string) {
if (fieldName.startsWith('track')) return '90px';
else if (fieldName.startsWith('signalbox')) return '150px';
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';
}
@@ -176,11 +180,10 @@ function generateMessage() {
const headerData = store.orderData['header'];
Object.entries(headerData).forEach(([key, value]) => {
messageHtml += `${t('order.header.' + key)}: ${value}<br />`;
});
messageHtml += '-------------<br />';
messageHtml += `${t('order.header.A')}: ${headerData['A']}<br />`;
messageHtml += `${t('order.header.B')}: ${headerData['B']}<br />`;
messageHtml += `${t('order.header.C')}: ${headerData['C']}<br />`;
messageHtml += `${t('order.header.D')}: ${headerData['D']}<br />`;
const instructions = store.orderData['instructions'];
@@ -195,16 +198,40 @@ function generateMessage() {
return fieldKey || '---';
});
messageHtml += '-------------<br />';
messageHtml += `<b>[${value.name}]</b> ${t(
localeKey + '.message-html',
messageValues
)}<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]);
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'] || '---'} | `;
messageHtml += `${t('order.footer.W')}: ${footerData['W'] || '---'}<br />`;
messageHtml += `${t('order.footer.Y')}: ${footerData['Y'] || '---'} | `;
messageHtml += `${t('order.footer.Z')}: ${footerData['Z'] || '---'}<br />`;
store.orderMessage = messageHtml;
}
</script>
@@ -227,7 +254,7 @@ function generateMessage() {
.order-instruction-number {
position: relative;
height: 65px;
height: 60px;
& > label {
position: absolute;
+81
View File
@@ -0,0 +1,81 @@
<template>
<label class="order-instruction-checkbox">
<input type="checkbox" v-model="instructionObject.active" />
<div class="checkmark"></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: 'X';
}
&:focus-visible ~ .text {
text-decoration: underline;
outline: 1px solid black;
}
}
.checkmark {
display: block;
position: relative;
margin: 0 auto;
height: 1.3em;
width: 1.3em;
background-color: #eee;
border: 2px solid black;
background-color: gold;
&:after {
position: absolute;
content: '';
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
}
&:hover input ~ .checkmark {
background-color: #ffe44b;
}
}
</style>
+2 -1
View File
@@ -245,7 +245,8 @@
"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> <br /> "
"message-html": "<b>Nie przekraczać prędkości i zachować ostrożność:</b>",
"message-html-list": "<b>{0}. Na posterunku/szlaku</b> {1}/{2} tor nr {3} v{4} od {5}km do {6}km - przyczyna: {7}"
},
"2311": {
"text": "{bold1}",
+89 -52
View File
@@ -37,7 +37,8 @@ export const useStore = defineStore('store', {
name: '22',
active: false,
inputFields: {},
optionalFieldNames: []
optionalFieldNames: [],
textDirectives: []
},
{
key: '99',
@@ -46,7 +47,8 @@ export const useStore = defineStore('store', {
inputFields: {
x1: ''
},
optionalFieldNames: []
optionalFieldNames: [],
textDirectives: []
},
{
key: '2110',
@@ -61,7 +63,8 @@ export const useStore = defineStore('store', {
signal2: '',
signal3: ''
},
optionalFieldNames: ['signal1', 'signal2', 'signal3']
optionalFieldNames: ['signal1', 'signal2', 'signal3'],
textDirectives: ['bold1', 'br']
},
{
key: '2115',
@@ -75,7 +78,8 @@ export const useStore = defineStore('store', {
signal2: '',
signal3: ''
},
optionalFieldNames: ['signal1', 'signal2', 'signal3']
optionalFieldNames: ['signal1', 'signal2', 'signal3'],
textDirectives: ['bold1', 'br']
},
{
key: '2120',
@@ -85,7 +89,9 @@ export const useStore = defineStore('store', {
track1: '',
signalbox1: '',
signalbox2: ''
}
},
optionalFieldNames: [],
textDirectives: ['highlight1', 'highlight2', 'underline1', 'br']
},
{
key: '2125',
@@ -102,7 +108,9 @@ export const useStore = defineStore('store', {
select1: {
options: ['select1-a', 'select1-b']
}
}
},
optionalFieldNames: [],
textDirectives: []
},
{
key: '2135',
@@ -111,7 +119,9 @@ export const useStore = defineStore('store', {
inputFields: {
track1: '',
signalbox1: ''
}
},
optionalFieldNames: [],
textDirectives: ['bold1']
},
{
key: '2140',
@@ -123,7 +133,8 @@ export const useStore = defineStore('store', {
km1: '',
other1: ''
},
optionalFieldNames: ['signalbox2']
optionalFieldNames: ['signalbox2'],
textDirectives: ['bold1']
},
{
key: '2145',
@@ -132,7 +143,9 @@ export const useStore = defineStore('store', {
inputFields: {
signalbox1: '',
signal1: ''
}
},
optionalFieldNames: [],
textDirectives: ['bold1']
},
{
key: '2150',
@@ -143,7 +156,8 @@ export const useStore = defineStore('store', {
signalbox2: '',
km1: ''
},
optionalFieldNames: ['signalbox2']
optionalFieldNames: ['signalbox2'],
textDirectives: ['bold1', 'br']
},
{
key: '2155',
@@ -154,7 +168,8 @@ export const useStore = defineStore('store', {
signalbox2: '',
signal1: ''
},
optionalFieldNames: ['signalbox2']
optionalFieldNames: ['signalbox2'],
textDirectives: ['bold1']
},
{
key: '2160',
@@ -166,7 +181,9 @@ export const useStore = defineStore('store', {
signalbox3: '',
line1: '',
vmax1: ''
}
},
optionalFieldNames: [],
textDirectives: ['bold1']
},
{
key: '2165',
@@ -175,7 +192,9 @@ export const useStore = defineStore('store', {
inputFields: {
km1: '',
km2: ''
}
},
optionalFieldNames: [],
textDirectives: ['bold1']
},
{
key: '2170',
@@ -185,7 +204,9 @@ export const useStore = defineStore('store', {
signalbox1: '',
signalbox2: '',
line1: ''
}
},
optionalFieldNames: [],
textDirectives: ['bold1', 'br']
},
{
key: '2180',
@@ -197,13 +218,17 @@ export const useStore = defineStore('store', {
km1: '',
signalbox2: '',
hour1: ''
}
},
optionalFieldNames: [],
textDirectives: ['bold1']
},
{
key: '2181',
name: '21.81',
active: false,
inputFields: {}
inputFields: {},
optionalFieldNames: [],
textDirectives: ['bold1']
},
{
key: '2182',
@@ -212,7 +237,9 @@ export const useStore = defineStore('store', {
inputFields: {
train1: '',
km1: ''
}
},
optionalFieldNames: [],
textDirectives: ['bold1']
},
{
key: '2183',
@@ -221,7 +248,9 @@ export const useStore = defineStore('store', {
inputFields: {
train1: '',
km1: ''
}
},
optionalFieldNames: [],
textDirectives: ['bold1']
},
{
key: '2185',
@@ -232,7 +261,9 @@ export const useStore = defineStore('store', {
km1: '',
signalbox1: '',
signalbox2: ''
}
},
optionalFieldNames: [],
textDirectives: ['bold1']
},
{
key: '2310',
@@ -241,39 +272,52 @@ export const useStore = defineStore('store', {
inputFields: {},
listFields: [
{
signalbox1: '',
signalbox2: '',
track1: '',
vmax1: '',
km1: '',
km2: '',
other1: ''
active: false,
values: {
signalbox1: '',
signalbox2: '',
track1: '',
vmax1: '',
km1: '',
km2: '',
other1: ''
}
},
{
signalbox1: '',
signalbox2: '',
track1: '',
vmax1: '',
km1: '',
km2: '',
other1: ''
active: false,
values: {
signalbox1: '',
signalbox2: '',
track1: '',
vmax1: '',
km1: '',
km2: '',
other1: ''
}
},
{
signalbox1: '',
signalbox2: '',
track1: '',
vmax1: '',
km1: '',
km2: '',
other1: ''
active: false,
values: {
signalbox1: '',
signalbox2: '',
track1: '',
vmax1: '',
km1: '',
km2: '',
other1: ''
}
}
]
],
optionalFieldNames: [],
textDirectives: ['bold1', 'br']
},
{
key: '2311',
name: '23.11',
active: false,
inputFields: {}
inputFields: {},
optionalFieldNames: [],
textDirectives: ['bold1']
},
{
key: '2320',
@@ -281,18 +325,11 @@ export const useStore = defineStore('store', {
active: false,
inputFields: {
other2320: ''
}
},
optionalFieldNames: [],
textDirectives: []
}
],
customInstructions: {
'2310': {
name: '23.10',
active: false,
inputFields: {},
optionalFieldNames: []
}
},
footer: {
V: '',
W: '',
+16 -59
View File
@@ -29,13 +29,28 @@ table.order-table {
td {
border: 2px solid black;
border-collapse: collapse;
line-height: 1.25em;
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;
@@ -134,61 +149,3 @@ textarea.order-textarea {
border-color: $darkModeTextCol !important;
}
}
/* Instruction Checkbox */
.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: 'X';
}
&:focus-visible ~ .text {
text-decoration: underline;
outline: 1px solid black;
}
}
.checkmark {
display: block;
position: relative;
margin: 0 auto;
margin-bottom: 0.35em;
height: 1.3em;
width: 1.3em;
background-color: #eee;
border: 2px solid black;
background-color: gold;
&:after {
position: absolute;
content: '';
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
}
&:hover input ~ .checkmark {
background-color: #ffe44b;
}
}