0
0
Fork 0

feat: refs #6346 new wagon type section

This commit is contained in:
Jon Elias 2024-07-23 13:22:54 +02:00
parent 5926381f36
commit 12370b6437
11 changed files with 551 additions and 760 deletions

View File

@ -919,6 +919,7 @@ wagon:
typeCreate: Create type typeCreate: Create type
typeEdit: Edit type typeEdit: Edit type
wagonCounter: Trolley counter wagonCounter: Trolley counter
wagonTray: Tray List
type: type:
name: Name name: Name
submit: Submit submit: Submit

View File

@ -907,6 +907,7 @@ wagon:
typeCreate: Crear tipo typeCreate: Crear tipo
typeEdit: Editar tipo typeEdit: Editar tipo
wagonCounter: Contador de carros wagonCounter: Contador de carros
wagonTray: Listado bandejas
type: type:
name: Nombre name: Nombre
submit: Guardar submit: Guardar

View File

@ -189,7 +189,7 @@ const columns = computed(() => [
{ {
align: 'left', align: 'left',
field: 'finished', field: 'finished',
label: t('Has recover'), label: t('Has recovery'),
name: 'finished', name: 'finished',
}, },
]); ]);
@ -408,4 +408,5 @@ es:
Credit I.: Crédito A. Credit I.: Crédito A.
Credit insurance: Crédito asegurado Credit insurance: Crédito asegurado
From: Desde From: Desde
Has recovery: Tiene recobro
</i18n> </i18n>

View File

@ -0,0 +1,148 @@
<script setup>
import { ref, watch } from 'vue';
import VnSelect from 'src/components/common/VnSelect.vue';
import FormPopup from 'src/components/FormPopup.vue';
import VnRow from 'src/components/ui/VnRow.vue';
import VnInput from 'src/components/common/VnInput.vue';
import FetchData from 'src/components/FetchData.vue';
import { useI18n } from 'vue-i18n';
import { useQuasar } from 'quasar';
import axios from 'axios';
const $props = defineProps({
entityId: {
type: Number,
required: true,
},
height: {
type: Number,
default: 0,
},
color: {
type: Array,
default: () => [],
},
});
const entityId = ref($props.entityId);
const selectedTrayColor = ref();
const trayHeight = ref();
const wagonColors = ref([]);
const wagonColorTranslated = ref();
const heights = ref();
const existingTrayHeight = ref($props.height);
const { t } = useI18n();
const { notify } = useQuasar();
watch(wagonColors, () => {
wagonColorTranslated.value = wagonColors.value.map((color) => {
return { ...color, name: t(`colors.${color.name}`) };
});
});
const emit = defineEmits(['onSubmit']);
async function getTrays() {
const data = await axios.get('WagonTypeTrays', undefined, {
filter: { wagonTypeFk: entityId.value },
});
existingTrayHeight.value = data.data.filter(
(item) => item.wagonTypeFk == entityId.value
);
heights.value = existingTrayHeight.value.map((item) => item.height);
}
function onSubmit() {
if (heights.value.includes(parseInt(trayHeight.value))) {
notify({
message: t(
'A tray with the same height already exists, try with a different height'
),
type: 'negative',
});
return;
}
if (trayHeight.value - heights.value[heights.value.length - 1] < 50) {
notify({
message: t('The minimum height between trays is 50cm'),
type: 'negative',
});
return;
}
if (trayHeight.value > 200) {
notify({
message: t(
'The maximum height of the wagon is 200cm, try with a lower height'
),
type: 'negative',
});
return;
}
const newTray = {
wagonTypeFk: entityId.value,
wagonTypeColorFk: selectedTrayColor.value,
height: trayHeight.value,
};
emit('onSubmit', newTray);
}
getTrays();
</script>
<template>
<FetchData
url="WagonTypeColors"
@on-fetch="(data) => (wagonColors = data)"
auto-load
/>
<FormPopup
ref="createTrayFormDialogRef"
@on-submit="onSubmit()"
:title="t('Add new tray')"
:entity-id="selectedEntityId"
>
<template #form-inputs>
<VnRow class="row q-gutter-md q-mb-md">
<VnSelect
v-model="selectedTrayColor"
:options="wagonColorTranslated"
option-label="name"
option-value="id"
id="id"
:label="t('Select a tray color')"
>
<template #option="scope">
<QItem v-bind="scope.itemProps" clickable>
<QItemSection>
<QItemLabel>{{ scope.opt.name }}</QItemLabel>
</QItemSection>
</QItem>
</template>
</VnSelect>
<VnInput v-model="trayHeight" :label="t('Height')" type="number" />
</VnRow>
</template>
</FormPopup>
</template>
<i18n>
en:
Select a tray: Select a tray
colors:
white: White
red: Red
green: Green
blue: Blue
es:
Select a tray color: Seleccione un color
Add new tray: Añadir nueva bandeja
Height: Altura
The minimum height between trays is 50cm: La altura mínima entre bandejas es de 50cm
The maximum height of the wagon is 200cm: La altura máxima del vagón es de 200cm
A tray with the same height already exists, try with a different height: Ya existe una bandeja con la misma altura, prueba con una diferente
colors:
white: Blanco
red: Rojo
green: Verde
blue: Azul
</i18n>

View File

@ -1,419 +0,0 @@
<script setup>
import { computed, ref, onMounted, onUpdated } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { useQuasar } from 'quasar';
import VnInput from 'src/components/common/VnInput.vue';
import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
import { useI18n } from 'vue-i18n';
import axios from 'axios';
onMounted(() => fetch());
onUpdated(() => fetch());
const { t } = useI18n();
const { notify } = useQuasar();
const route = useRoute();
const router = useRouter();
const $props = defineProps({
id: {
type: Number,
required: false,
default: null,
},
});
const entityId = computed(() => $props.id || route.params.id);
const wagon = ref([]);
const divisible = ref(false);
const name = ref('');
const colorPickerActive = ref(false);
let originalData = { trays: [] };
let maxTrays, maxWagonHeight, minHeightBetweenTrays;
let wagonTypeColors;
let currentTrayColorPicked;
async function fetch() {
try {
({
data: [{ maxTrays, maxWagonHeight, minHeightBetweenTrays }],
} = await axios.get('WagonConfigs'));
await axios.get(`WagonTypeColors`).then(async (res) => {
if ((wagonTypeColors = res.data)) {
if (entityId.value) {
await axios
.get(`WagonTypeTrays`, {
params: { filter: { where: { typeFk: entityId.value } } },
})
.then(async (res) => {
if (res.data) {
for (let i = 0; i < res.data.length; i++) {
const tray = res.data[i];
wagon.value.push({
id: res.data.length - i - 1,
position: tray.height,
color: {
...wagonTypeColors.find((color) => {
return color.id === tray.colorFk;
}),
},
action: tray.height == 0 ? 'add' : 'delete',
});
}
wagon.value.forEach((value) => {
originalData.trays.push({ ...value });
});
}
});
} else
wagon.value.push({
id: 0,
position: 0,
color: { ...wagonTypeColors[0] },
action: 'add',
});
}
});
if (entityId.value)
await axios.get(`WagonTypes/${entityId.value}`).then((res) => {
if (res.data) {
originalData.name = name.value = res.data.name;
originalData.divisible = divisible.value = res.data.divisible;
}
});
} catch (e) {
//
}
}
function addTray() {
if (
wagon.value.find((tray) => {
return tray.position == null;
})
)
return notify({
message: t('wagon.warnings.uncompleteTrays'),
type: 'warning',
});
if (wagon.value.length < maxTrays)
wagon.value.unshift({
id: wagon.value.length,
position: null,
color: { ...wagonTypeColors[0] },
action: 'delete',
});
else
notify({
message: t('wagon.warnings.maxTrays'),
type: 'warning',
});
}
function deleteTray(trayToDelete) {
wagon.value = wagon.value.filter((tray) => tray.id !== trayToDelete.id);
reorderIds();
}
function reorderIds() {
for (let index = wagon.value.length - 1; index >= 0; index--)
wagon.value[index].id = index;
}
async function onSubmit() {
try {
const path = entityId.value
? 'WagonTypes/editWagonType'
: 'WagonTypes/createWagonType';
const params = {
id: entityId.value,
name: name.value,
divisible: divisible.value,
trays: wagon.value,
};
await axios.patch(path, params).then((res) => {
if (res.status == 204) router.push({ path: `/wagon/type/list` });
});
} catch (error) {
//
}
}
async function onReset() {
name.value = entityId.value ? originalData.name : null;
divisible.value = entityId.value ? originalData.divisible : false;
wagon.value = entityId.value
? [...originalData.trays]
: [
{
id: 0,
position: 0,
color: { ...wagonTypeColors[0] },
action: 'add',
},
];
}
function doAction(tray) {
if (tray.action == 'add') addTray();
else deleteTray(tray);
}
function showColorPicker(tray) {
colorPickerActive.value = true;
currentTrayColorPicked = wagon.value.findIndex((val) => {
return val.id === tray.id;
});
}
function updateColor(newColor) {
wagon.value[currentTrayColorPicked].color = {
...wagonTypeColors.find((color) => {
return color.rgb === newColor;
}),
};
}
function onPositionBlur(tray) {
if (tray.position) {
if (tray.position == '' || tray.position < 0) return (tray.position = null);
tray.position = parseInt(tray.position);
wagon.value.sort((a, b) => b.position - a.position);
reorderIds();
for (let index = wagon.value.length - 1; index > 0; index--) {
if (exceedMaxHeight(index - 1)) continue;
if (
wagon.value[index - 1].position - wagon.value[index].position >=
minHeightBetweenTrays
)
continue;
else {
wagon.value[index - 1].position +=
minHeightBetweenTrays -
(wagon.value[index - 1].position - wagon.value[index].position);
notify({
message:
t('wagon.warnings.minHeightBetweenTrays') +
minHeightBetweenTrays +
' cm',
type: 'warning',
});
exceedMaxHeight(index - 1);
}
}
}
}
function exceedMaxHeight(pos) {
if (wagon.value[pos].position < maxWagonHeight) return false;
wagon.value.splice(pos, 1);
notify({
message: t('wagon.warnings.maxWagonHeight') + maxWagonHeight + ' cm',
type: 'warning',
});
return true;
}
</script>
<template>
<VnSubToolbar />
<QPage class="q-pa-sm q-mx-xl">
<QForm @submit="onSubmit()" @reset="onReset()" class="q-pa-sm">
<QCard class="q-pa-md">
<VnInput
filled
v-model="name"
:label="t('wagon.type.name')"
:rules="[(val) => !!val || t('wagon.warnings.nameNotEmpty')]"
/>
<QCheckbox class="q-mb-sm" v-model="divisible" label="Divisible" />
<div class="wagon-tray q-mx-lg" v-for="tray in wagon" :key="tray.id">
<div class="position">
<QInput
autofocus
filled
type="number"
:class="{ isVisible: tray.action == 'add' }"
v-model="tray.position"
@blur="onPositionBlur(tray)"
>
<QTooltip :delay="2000">
{{
t('wagon.warnings.minHeightBetweenTrays') +
minHeightBetweenTrays +
' cm'
}}
<QSpace />
{{
t('wagon.warnings.maxWagonHeight') +
maxWagonHeight +
' cm'
}}
</QTooltip>
</QInput>
</div>
<div class="shelving">
<div class="shelving-half">
<div class="shelving-up"></div>
<div
class="shelving-down"
:style="{ backgroundColor: tray.color.rgb }"
@click="showColorPicker(tray)"
></div>
</div>
<div
class="shelving-divisible"
:class="{ isVisible: !divisible }"
></div>
<div class="shelving-half">
<div class="shelving-up"></div>
<div
class="shelving-down"
:style="{ backgroundColor: tray.color.rgb }"
@click="showColorPicker(tray)"
></div>
</div>
</div>
<div class="action-button">
<QBtn
flat
round
color="primary"
:icon="tray.action"
@click="doAction(tray)"
/>
</div>
</div>
<div class="q-mb-sm wheels">
<QIcon color="grey-6" name="trip_origin" size="xl" />
<QIcon color="grey-6" name="trip_origin" size="xl" />
</div>
<QDialog
v-model="colorPickerActive"
position="right"
:no-backdrop-dismiss="false"
>
<QCard>
<QCardSection>
<div class="text-h6">{{ t('wagon.type.trayColor') }}</div>
</QCardSection>
<QCardSection class="row items-center no-wrap">
<QColor
flat
v-model="wagon[currentTrayColorPicked].color.rgb"
no-header
no-footer
default-view="palette"
:palette="
wagonTypeColors.map((color) => {
return color.rgb;
})
"
@change="updateColor($event)"
/>
<QBtn flat round icon="close" v-close-popup />
</QCardSection>
</QCard>
</QDialog>
</QCard>
<div class="q-mt-md">
<QBtn :label="t('wagon.type.submit')" type="submit" color="primary" />
<QBtn
:label="t('wagon.type.reset')"
type="reset"
color="primary"
flat
class="q-ml-sm"
/>
</div>
</QForm>
</QPage>
</template>
<style lang="scss" scoped>
.q-page {
display: flex;
justify-content: center;
align-items: flex-start;
}
.q-form {
width: 70%;
}
.q-dialog {
.q-card {
width: 100%;
}
}
.wheels {
margin-left: 5%;
display: flex;
justify-content: space-around;
}
.wagon-tray {
display: flex;
height: 6rem;
.position {
width: 20%;
border-right: 1rem solid gray;
display: flex;
align-items: flex-end;
justify-content: flex-end;
padding-right: 1rem;
}
.shelving {
display: flex;
width: 75%;
.shelving-half {
width: 50%;
height: 100%;
.shelving-up {
height: 80%;
width: 100%;
}
.shelving-down {
height: 20%;
width: 100%;
}
}
.shelving-divisible {
width: 1%;
height: 100%;
border-left: 0.5rem dashed grey;
border-right: 0.5rem dashed grey;
}
}
.action-button {
width: 10%;
border-left: 1rem solid gray;
display: flex;
align-items: flex-end;
justify-content: flex-start;
padding-left: 1rem;
}
.isVisible {
display: none;
}
}
</style>

View File

@ -0,0 +1,301 @@
<script setup>
import { computed, ref, watch } from 'vue';
import { useRoute } from 'vue-router';
import { useQuasar } from 'quasar';
import VnInput from 'src/components/common/VnInput.vue';
import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
import FormModel from 'src/components/FormModel.vue';
import { useI18n } from 'vue-i18n';
import axios from 'axios';
import VnPaginate from 'components/ui/VnPaginate.vue';
import WagonCreateTray from './WagonCreateTray.vue';
const { t } = useI18n();
const { notify } = useQuasar();
const route = useRoute();
const entityId = computed(() => route.params.id);
const wagonTrays = ref([]);
const createTrayFormDialogRef = ref();
const selectedEntityId = ref();
async function loadTrays() {
try {
const res = await axios.get('WagonTypeTrays');
const filteredTrays = res.data.filter(
(tray) => tray.wagonTypeFk === entityId.value
);
wagonTrays.value = filteredTrays;
return;
} catch (err) {
console.error('Error loading trays:', err);
}
}
async function addTray(newTray) {
try {
const res = await axios.post(`WagonTypeTrays`, newTray);
wagonTrays.value.push(res.data);
notify({
message: t(`Tray added successfully`),
type: 'positive',
});
} catch (err) {
console.log('err: ', err);
}
}
async function deleteTray(trayToDelete) {
try {
await axios.delete(`WagonTypeTrays/${trayToDelete.id}`);
const index = wagonTrays.value.findIndex((tray) => tray.id === trayToDelete.id);
if (index !== -1) {
wagonTrays.value.splice(index, 1);
}
notify({
message: t('Tray deleted successfully'),
type: 'positive',
});
} catch (err) {
console.log('err: ', err);
}
}
const filter = {
where: { wagonTypeFk: entityId.value },
include: {
relation: 'color',
scope: {
fields: ['rgb'],
},
},
};
const formFilter = { where: { wagonTypeFk: entityId.value } };
const showCreateTrayForm = (id) => {
selectedEntityId.value = id;
createTrayFormDialogRef.value.show();
};
watch(
() => wagonTrays.value,
async (newVal, oldVal) => {
if (newVal.length !== oldVal.length) {
await loadTrays();
}
},
{ deep: true }
);
</script>
<template>
<VnSubToolbar />
<QPage class="q-pa-sm q-mx-xl">
<FormModel
:url="`WagonTypes/ ${entityId}`"
:url-update="`WagonTypes/ ${entityId}`"
:filter="formFilter"
model="WagonType"
auto-load
>
<template #form="{ data }">
<QCard class="q-pa-md">
<VnInput
filled
v-model="data.name"
:label="t('wagon.type.name')"
:rules="[(val) => !!val || t('wagon.warnings.nameNotEmpty')]"
/>
<QCheckbox
class="q-mb-sm"
v-model="data.divisible"
label="Divisible"
/>
<VnPaginate
data-key="wagonTypeTray"
url="WagonTypeTrays"
order="id DESC"
:filter="filter"
auto-load
ref="vnPaginateRef"
v-bind="$attrs"
:key="wagonTrays.length"
>
<template #body="{ rows }">
<div v-for="row in rows" :key="row.id">
<div class="shelving"></div>
<div class="action-button">
<div class="wagon-tray q-mx-lg">
<div class="position">
<VnInput
borderless
type="number"
disable
class="input-tray q-mb-sm"
:label="t('Height') + ': '"
v-model="row.height"
/>
</div>
<div class="shelving">
<div class="shelving-half">
<div class="shelving-up"></div>
<div
class="shelving-down"
:style="{
backgroundColor: row.color.rgb,
}"
></div>
</div>
<div
class="shelving-divisible"
:class="{ isVisible: !data.divisible }"
></div>
<div class="shelving-half">
<div class="shelving-up"></div>
<div
class="shelving-down"
:style="{
backgroundColor: row.color.rgb,
}"
></div>
</div>
</div>
<div class="action-button">
<QBtn
v-if="row.height === 0"
flat
round
color="primary"
:icon="'add'"
class="btn-tray"
@click="showCreateTrayForm(entityId)"
/>
<QBtn
v-else
flat
round
color="primary"
:icon="'delete'"
class="btn-tray"
@click="deleteTray(row)"
/>
</div>
</div>
</div>
</div>
</template>
</VnPaginate>
<div class="q-mb-sm wheels">
<QIcon color="grey-6" name="trip_origin" size="xl" />
<QIcon color="grey-6" name="trip_origin" size="xl" />
</div>
</QCard>
<QDialog ref="createTrayFormDialogRef">
<WagonCreateTray :entity-id="entityId" @on-submit="addTray($event)" />
</QDialog>
</template>
</FormModel>
</QPage>
</template>
<style lang="scss" scoped>
.q-page {
display: flex;
justify-content: center;
align-items: flex-start;
}
.q-form {
width: 70%;
}
.q-dialog {
.q-card {
width: 100%;
}
}
.wheels {
margin-left: 5%;
display: flex;
justify-content: space-around;
}
.wagon-tray {
display: flex;
height: 6rem;
.position {
width: 26%;
border-right: 1rem solid gray;
display: flex;
align-items: flex-start;
justify-content: flex-start;
padding-right: 2rem;
padding-left: 3rem;
}
.shelving {
display: flex;
width: 54%;
.shelving-half {
width: 100%;
height: 100%;
.shelving-up {
height: 80%;
width: 100%;
}
.shelving-down {
height: 20%;
width: 100%;
}
}
.shelving-divisible {
width: 1%;
height: 100%;
border-left: 0.5rem dashed grey;
border-right: 0.5rem dashed grey;
}
}
.action-button {
width: 20%;
border-left: 1rem solid gray;
align-items: baseline;
padding-left: 3rem;
}
.isVisible {
display: none;
}
}
.btn-tray {
margin-right: 100%;
margin-top: 100%;
}
.input-tray {
margin-top: 100%;
margin-left: 40%;
}
</style>
<i18n>
en:
tray: Tray
wagonColor: Wagon color
Select a tray: Select a tray
es:
tray: Bandeja
wagonColor: Color de la bandeja
Select a tray: Seleccione una bandeja
Create new Wagon type: Crear nuevo tipo de vagón
Add new tray: Añadir nueva bandeja
Height: Altura
Tray added successfully: Bandeja añadida correctamente
Tray deleted successfully: Bandeja eliminada correctamente
</i18n>

View File

@ -1,4 +1,5 @@
<script setup> <script setup>
import { ref, computed } from 'vue';
import axios from 'axios'; import axios from 'axios';
import { useQuasar } from 'quasar'; import { useQuasar } from 'quasar';
import VnPaginate from 'src/components/ui/VnPaginate.vue'; import VnPaginate from 'src/components/ui/VnPaginate.vue';
@ -6,36 +7,40 @@ import { useArrayData } from 'src/composables/useArrayData';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import CardList from 'components/ui/CardList.vue'; import CardList from 'components/ui/CardList.vue';
import FormModelPopup from 'src/components/FormModelPopup.vue';
import VnInput from 'src/components/common/VnInput.vue';
import VnRow from 'src/components/ui/VnRow.vue';
const quasar = useQuasar(); const quasar = useQuasar();
const arrayData = useArrayData('WagonTypeList'); const arrayData = useArrayData('WagonTypeList');
const store = arrayData.store; const store = arrayData.store;
const router = useRouter(); const dialog = ref();
const { push } = useRouter();
const { t } = useI18n(); const { t } = useI18n();
const paginate = ref();
function navigate(id) { const initialData = computed(() => {
router.push({ path: `/wagon/type/${id}/edit` }); return {
name: null,
};
});
function reloadData() {
initialData.value.name = null;
paginate.value.fetch();
} }
function create() { function navigate(id, name) {
router.push({ path: `/wagon/type/create` }); push({ path: `/wagon/type/${id}/edit`, query: { name } });
} }
async function remove(row) { async function remove(row) {
try { await axios.delete(`WagonTypes/${row.id}`);
const id = row.id;
await axios
.delete(`WagonTypes/deleteWagonType`, { params: { id } })
.then(async () => {
quasar.notify({ quasar.notify({
message: t('wagon.type.removeItem'), message: t('wagon.type.removeItem'),
type: 'positive', type: 'positive',
}); });
store.data.splice(store.data.indexOf(row), 1); store.data.splice(store.data.indexOf(row), 1);
});
} catch (error) {
//
}
} }
</script> </script>
@ -43,8 +48,9 @@ async function remove(row) {
<QPage class="column items-center q-pa-md"> <QPage class="column items-center q-pa-md">
<div class="vn-card-list"> <div class="vn-card-list">
<VnPaginate <VnPaginate
ref="paginate"
data-key="WagonTypeList" data-key="WagonTypeList"
url="/WagonTypes" url="WagonTypes"
order="id DESC" order="id DESC"
auto-load auto-load
> >
@ -54,7 +60,7 @@ async function remove(row) {
:key="row.id" :key="row.id"
:title="(row.name || '').toString()" :title="(row.name || '').toString()"
:id="row.id" :id="row.id"
@click="navigate(row.id)" @click="navigate(row.id, row.name)"
> >
<template #list-items> <template #list-items>
<QCheckbox <QCheckbox
@ -66,7 +72,7 @@ async function remove(row) {
<template #actions> <template #actions>
<QBtn <QBtn
:label="t('components.smartCard.openCard')" :label="t('components.smartCard.openCard')"
@click.stop="navigate(row.id)" @click.stop="navigate(row.id, row.name)"
outline outline
/> />
<QBtn <QBtn
@ -80,8 +86,42 @@ async function remove(row) {
</template> </template>
</VnPaginate> </VnPaginate>
</div> </div>
<QPageSticky position="bottom-right" :offset="[18, 18]"> <QPageSticky :offset="[18, 18]">
<QBtn @click="create" fab icon="add" color="primary" /> <QBtn @click.stop="dialog.show()" color="primary" fab icon="add">
<QDialog ref="dialog">
<FormModelPopup
:title="t('Create new Wagon type')"
url-create="WagonTypes"
model="WagonType"
:form-initial-data="initialData"
@on-data-saved="reloadData()"
auto-load
>
<template #form-inputs="{ data }">
<VnRow class="row q-gutter-md q-mb-md">
<VnInput
filled
v-model="data.name"
:label="t('Name')"
:rules="[(val) => !!val || t('nameNotEmpty')]"
/>
</VnRow>
</template>
</FormModelPopup>
</QDialog>
</QBtn>
<QTooltip>
{{ t('globals.new') }}
</QTooltip>
</QPageSticky> </QPageSticky>
</QPage> </QPage>
</template> </template>
<i18n>
en:
nameNotEmpty: The name cannot be empty
es:
Create new Wagon type: Crear nuevo tipo de vagón
Name: Nombre
nameNotEmpty: El nombre no puede estar vacío
</i18n>

View File

@ -11,7 +11,7 @@ export default {
component: RouterView, component: RouterView,
redirect: { name: 'WagonMain' }, redirect: { name: 'WagonMain' },
menus: { menus: {
main: ['WagonList', 'WagonTypeList', 'WagonCounter'], main: ['WagonList', 'WagonTypeList', 'WagonCounter', 'WagonTray'],
card: [], card: [],
}, },
children: [ children: [
@ -81,7 +81,7 @@ export default {
title: 'typeCreate', title: 'typeCreate',
icon: 'create', icon: 'create',
}, },
component: () => import('src/pages/Wagon/Type/WagonTypeCreate.vue'), component: () => import('src/pages/Wagon/Type/WagonTypeList.vue'),
}, },
{ {
path: ':id/edit', path: ':id/edit',
@ -90,7 +90,7 @@ export default {
title: 'typeEdit', title: 'typeEdit',
icon: 'edit', icon: 'edit',
}, },
component: () => import('src/pages/Wagon/Type/WagonTypeCreate.vue'), component: () => import('src/pages/Wagon/Type/WagonTypeEdit.vue'),
}, },
], ],
}, },

View File

@ -5,50 +5,12 @@ describe('WagonTypeCreate', () => {
cy.visit('/#/wagon/type/create'); cy.visit('/#/wagon/type/create');
}); });
function chooseColor(color) { it('should create a new wagon type', () => {
cy.get('div.shelving-down').eq(1).click(); cy.get('.q-page-sticky > div > .q-btn').click();
cy.get('div.q-color-picker__cube').eq(color).click();
cy.get('div.q-card__section').find('button').click();
}
function addTray(position) {
cy.get('div.action-button').last().find('button').click();
cy.focused().type(position);
cy.focused().blur();
}
it('should create and delete a new wagon type', () => {
cy.get('input').first().type('Example for testing'); cy.get('input').first().type('Example for testing');
cy.get('div.q-checkbox__bg').click();
chooseColor(1);
// Insert invalid position (not minimal height)
addTray(20);
cy.get('div[role="alert"]').should('exist');
chooseColor(2);
addTray(150);
chooseColor(3);
addTray(100);
// Insert invalid position (max height reached)
addTray(210);
cy.get('div[role="alert"]').should('exist');
// Save
cy.get('button[type="submit"]').click(); cy.get('button[type="submit"]').click();
});
// Check data has been saved successfully it('delete a wagon type', () => {
cy.get(':nth-child(1) > :nth-child(1) > .justify-between > .flex > .title')
.contains('Example for testing')
.click();
cy.get('input').first().should('have.value', 'Example for testing');
cy.get('div.wagon-tray').should('have.length', 4);
cy.get('div.position').eq(0).find('input').should('have.value', '150');
cy.get('div.position').eq(1).find('input').should('have.value', '100');
cy.get('div.position').eq(2).find('input').should('have.value', '50');
// Delete wagon type created
cy.go('back');
cy.get( cy.get(
':nth-child(2) > :nth-child(1) > .card-list-body > .actions > .q-btn--standard' ':nth-child(2) > :nth-child(1) > .card-list-body > .actions > .q-btn--standard'
).click(); ).click();

View File

@ -0,0 +1,27 @@
describe('WagonTypeEdit', () => {
const trayColorRow =
'.q-select > .q-field__inner > .q-field__control > .q-field__control-container';
beforeEach(() => {
cy.viewport(1920, 1080);
cy.login('developer');
cy.visit('/#/wagon/type/2/edit');
});
it('should edit the name and the divisible field of the wagon type', () => {
cy.get('.q-card');
cy.get('input').first().type(' changed');
cy.get('div.q-checkbox__bg').first().click();
cy.get('.q-btn--standard').click();
});
it('should create a tray', () => {
cy.get('.action-button > .q-btn > .q-btn__content > .q-icon').click();
cy.get('input').last().type('150');
cy.get(trayColorRow).type('{downArrow}{downArrow}{enter}');
});
it('should delete a tray', () => {
cy.get('.action-button > .q-btn > .q-btn__content > .q-icon').first().click();
cy.reload();
});
});

View File

@ -1,271 +0,0 @@
import { axios, createWrapper } from 'app/test/vitest/helper';
import WagonTypeCreate from 'pages/Wagon/Type/WagonTypeCreate.vue';
import { afterEach, beforeAll, describe, expect, it, vi } from 'vitest';
describe('WagonTypeCreate', () => {
let vmCreate, vmEdit;
const entityId = 1;
beforeAll(() => {
vmEdit = createWrapper(WagonTypeCreate, {propsData: {
id: entityId,
}}).vm;
vmCreate = createWrapper(WagonTypeCreate).vm;
vmEdit.wagonConfig = vmCreate.wagonConfig = {maxTrays: 2 ,minHeightBetweenTrays: 50, maxWagonHeight: 200 };
vmEdit.wagonTypeColors = vmCreate.wagonTypeColors = [{id: 1, color:'white', rgb:'#000000'}];
});
afterEach(() => {
vi.clearAllMocks();
});
describe('addTray()', () => {
it('should throw message if there are uncomplete trays', async () => {
vi.spyOn(vmEdit.quasar, 'notify');
vmEdit.wagon = [{
id: 1,
position: null,
color: vmEdit.wagonTypeColors[0]
}];
await vmEdit.addTray();
expect(vmEdit.quasar.notify).toHaveBeenCalledWith(
expect.objectContaining({
type: 'warning',
})
);
});
it('should create a new tray if the limit has not been reached', async () => {
vmEdit.wagon = [{
id: 1,
position: 0,
color: vmEdit.wagonTypeColors[0]
}];
await vmEdit.addTray();
expect(vmEdit.wagon.length).toEqual(2);
});
it('should throw message if there are uncomplete trays', async () => {
vi.spyOn(vmEdit.quasar, 'notify');
vmEdit.wagon = [{
id: 1,
position: 0,
color: vmEdit.wagonTypeColors[0]
},{
id: 2,
position: 50,
color: vmEdit.wagonTypeColors[0]
}];
await vmEdit.addTray();
expect(vmEdit.quasar.notify).toHaveBeenCalledWith(
expect.objectContaining({
type: 'warning',
})
);
});
});
describe('deleteTray() reorderIds()', () => {
it('should delete a tray and reorder the ids', async () => {
const trayToDelete = {
id: 1,
position: 0,
color: vmEdit.wagonTypeColors[0]
};
const trayMaintained = {
id: 2,
position: 50,
color: vmEdit.wagonTypeColors[0]
};
vmEdit.wagon = [trayToDelete,trayMaintained];
await vmEdit.deleteTray(trayToDelete);
expect(vmEdit.wagon.length).toEqual(1);
expect(vmEdit.wagon[0].id).toEqual(0);
expect(vmEdit.wagon[0].position).toEqual(50);
});
});
describe('onSubmit()', () => {
it('should make a patch to editWagonType if have id', async () => {
vi.spyOn(axios, 'patch').mockResolvedValue({ data: true });
const wagon = {
id: entityId,
name: "Mock name",
divisible: true,
trays: [{
id: 1,
position: 0,
color: vmEdit.wagonTypeColors[0]
}]
}
vmEdit.name = wagon.name;
vmEdit.divisible = wagon.divisible;
vmEdit.wagon = wagon.trays;
await vmEdit.onSubmit();
expect(axios.patch).toHaveBeenCalledWith(
`WagonTypes/editWagonType`, wagon
);
});
it('should make a patch to createtWagonType if not have id', async () => {
vi.spyOn(axios, 'patch').mockResolvedValue({ data: true });
const wagon = {
name: "Mock name",
divisible: true,
trays: [{
id: 1,
position: 0,
color: vmCreate.wagonTypeColors[0]
}]
}
vmCreate.name = wagon.name;
vmCreate.divisible = wagon.divisible;
vmCreate.wagon = wagon.trays;
await vmCreate.onSubmit();
expect(axios.patch).toHaveBeenCalledWith(
`WagonTypes/createWagonType`, wagon
);
});
});
describe('onReset()', () => {
it('should reset if have id', async () => {
vmEdit.name = 'Changed name';
vmEdit.divisible = false;
vmEdit.wagon = [];
vmEdit.originalData = {
name: 'Original name',
divisible: true,
trays: [{
id: 1,
position: 0,
color: vmEdit.wagonTypeColors[0]
},{
id: 2,
position: 50,
color: vmEdit.wagonTypeColors[0]
}]
};
vmEdit.onReset();
expect(vmEdit.name).toEqual(vmEdit.originalData.name);
expect(vmEdit.divisible).toEqual(vmEdit.originalData.divisible);
expect(vmEdit.wagon).toEqual(vmEdit.originalData.trays);
});
it('should reset if not have id', async () => {
vmCreate.name = 'Changed name';
vmCreate.divisible = false;
vmCreate.wagon = [];
vmCreate.onReset();
expect(vmCreate.name).toEqual(null);
expect(vmCreate.divisible).toEqual(false);
expect(vmCreate.wagon.length).toEqual(1);
});
});
describe('onPositionBlur()', () => {
it('should set position null if position is negative', async () => {
const negativeTray = {
id: 1,
position: -1,
color: vmCreate.wagonTypeColors[0]
};
vmCreate.onPositionBlur(negativeTray);
expect(negativeTray.position).toEqual(null);
});
it('should set position and reorder array', async () => {
const trays = [{
id: 0,
position: 100,
color: vmCreate.wagonTypeColors[0]
},{
id: 1,
position: 0,
color: vmCreate.wagonTypeColors[0]
}];
const newTray = {
id: 2,
position: 50,
color: vmCreate.wagonTypeColors[0]
};
trays.push(newTray);
vmCreate.wagon = trays;
vmCreate.onPositionBlur(newTray);
expect(vmCreate.wagon[0].position).toEqual(100);
expect(vmCreate.wagon[1].position).toEqual(50);
expect(vmCreate.wagon[2].position).toEqual(0);
});
it('should throw message if not have min height between trays and should set new adequate positions', async () => {
vi.spyOn(vmCreate.quasar, 'notify');
const trays = [{
id: 0,
position: 0,
color: vmCreate.wagonTypeColors[0]
}];
const newTray = {
id: 1,
position: 20,
color: vmCreate.wagonTypeColors[0]
};
trays.push(newTray);
vmCreate.wagon = trays;
vmCreate.onPositionBlur(newTray);
expect(vmCreate.wagon[0].position).toEqual(50);
expect(vmCreate.wagon[1].position).toEqual(0);
expect(vmCreate.quasar.notify).toHaveBeenCalledWith(
expect.objectContaining({
type: 'warning',
})
);
});
it('should throw message if max height has been exceed', async () => {
vi.spyOn(vmCreate.quasar, 'notify');
const trays = [{
id: 0,
position: 0,
color: vmCreate.wagonTypeColors[0]
}];
const newTray = {
id: 1,
position: 210,
color: vmCreate.wagonTypeColors[0]
};
trays.push(newTray);
vmCreate.wagon = trays;
vmCreate.onPositionBlur(newTray);
expect(vmCreate.wagon.length).toEqual(1);
expect(vmCreate.quasar.notify).toHaveBeenCalledWith(
expect.objectContaining({
type: 'warning',
})
);
});
});
});