Add relay machine controls and program picker integration:
- Added `relay_machine_program_picker_id` and `relay_machine_cleaner_id` fields across components, views, and localization files. - Updated relay control logic to include program picker and cleaner relays. - Extended e2e and unit tests to validate new relay functionalities. - Refactored related components to handle expanded relay configurations.
This commit is contained in:
@@ -55,6 +55,8 @@ watch(() => props.objects, () => {
|
||||
<th>{{ SessionUser.objects.department_lanes.columns.relay_in_id.label }}</th>
|
||||
<th>{{ SessionUser.objects.department_lanes.columns.relay_out_id.label }}</th>
|
||||
<th>{{ SessionUser.objects.department_lanes.columns.relay_machine_id.label }}</th>
|
||||
<th>{{ SessionUser.objects.department_lanes.columns.relay_machine_program_picker_id.label }}</th>
|
||||
<th>{{ SessionUser.objects.department_lanes.columns.relay_machine_cleaner_id.label }}</th>
|
||||
<th>{{ SessionUser.objects.department_lanes.columns.dynamic_image_id.label }}</th>
|
||||
<th>{{ SessionUser.objects.department_lanes.columns.machine_type_id.label }}</th>
|
||||
</template>
|
||||
@@ -116,6 +118,18 @@ watch(() => props.objects, () => {
|
||||
column="relay_machine_id"
|
||||
:edit-function="SessionUser.objects.department_lanes.showEditObjectFieldForm"
|
||||
/>
|
||||
<EditableTableColumn
|
||||
:object="object"
|
||||
:loadList="loadList"
|
||||
column="relay_machine_program_picker_id"
|
||||
:edit-function="SessionUser.objects.department_lanes.showEditObjectFieldForm"
|
||||
/>
|
||||
<EditableTableColumn
|
||||
:object="object"
|
||||
:loadList="loadList"
|
||||
column="relay_machine_cleaner_id"
|
||||
:edit-function="SessionUser.objects.department_lanes.showEditObjectFieldForm"
|
||||
/>
|
||||
<EditableTableColumn
|
||||
:object="object"
|
||||
:loadList="loadList"
|
||||
|
||||
@@ -75,6 +75,22 @@ const t = (key) => i18n.global.t(key);
|
||||
required: false
|
||||
}
|
||||
},
|
||||
relay_machine_program_picker_id: {
|
||||
label: t('objects.columns.relay_machine_program_picker_id'),
|
||||
type: "string",
|
||||
sortable: true,
|
||||
creation: {
|
||||
required: false
|
||||
}
|
||||
},
|
||||
relay_machine_cleaner_id: {
|
||||
label: t('objects.columns.relay_machine_cleaner_id'),
|
||||
type: "string",
|
||||
sortable: true,
|
||||
creation: {
|
||||
required: false
|
||||
}
|
||||
},
|
||||
dynamic_image_id: {
|
||||
label: t('objects.columns.dynamic_image_id'),
|
||||
type: "number",
|
||||
@@ -103,7 +119,17 @@ const t = (key) => i18n.global.t(key);
|
||||
}
|
||||
};
|
||||
},
|
||||
add: async (department, name, relay_in_id = null, relay_out_id = null, relay_machine_id = null, dynamic_image_id = null, machine_type_id = null) => {
|
||||
add: async (
|
||||
department,
|
||||
name,
|
||||
relay_in_id = null,
|
||||
relay_out_id = null,
|
||||
relay_machine_id = null,
|
||||
relay_machine_program_picker_id = null,
|
||||
relay_machine_cleaner_id = null,
|
||||
dynamic_image_id = null,
|
||||
machine_type_id = null
|
||||
) => {
|
||||
return ObjectsGlobal.add.object(
|
||||
DepartmentLanes.meta.endpoint,
|
||||
{
|
||||
@@ -112,6 +138,8 @@ const t = (key) => i18n.global.t(key);
|
||||
relay_in_id: relay_in_id,
|
||||
relay_out_id: relay_out_id,
|
||||
relay_machine_id: relay_machine_id,
|
||||
relay_machine_program_picker_id: relay_machine_program_picker_id,
|
||||
relay_machine_cleaner_id: relay_machine_cleaner_id,
|
||||
dynamic_image_id: dynamic_image_id ? parseInt(dynamic_image_id) : null,
|
||||
machine_type_id: machine_type_id ? parseInt(machine_type_id) : null
|
||||
}
|
||||
@@ -158,6 +186,22 @@ const t = (key) => i18n.global.t(key);
|
||||
relay_machine_id
|
||||
)
|
||||
},
|
||||
relay_machine_program_picker_id: async (id, relay_machine_program_picker_id) => {
|
||||
return ObjectsGlobal.set.column(
|
||||
DepartmentLanes.meta.endpoint,
|
||||
id,
|
||||
"relay_machine_program_picker_id",
|
||||
relay_machine_program_picker_id
|
||||
)
|
||||
},
|
||||
relay_machine_cleaner_id: async (id, relay_machine_cleaner_id) => {
|
||||
return ObjectsGlobal.set.column(
|
||||
DepartmentLanes.meta.endpoint,
|
||||
id,
|
||||
"relay_machine_cleaner_id",
|
||||
relay_machine_cleaner_id
|
||||
)
|
||||
},
|
||||
dynamic_image_id: async (id, dynamic_image_id) => {
|
||||
return ObjectsGlobal.set.column(
|
||||
DepartmentLanes.meta.endpoint,
|
||||
|
||||
@@ -2206,6 +2206,8 @@
|
||||
"reference": "Referanse",
|
||||
"relay_in_id": "Indgangs relæ ID",
|
||||
"relay_machine_id": "Maskine relæ ID",
|
||||
"relay_machine_program_picker_id": "Machine program picker relay ID",
|
||||
"relay_machine_cleaner_id": "Machine cleaner relay ID",
|
||||
"relay_out_id": "Udgangs relæ ID",
|
||||
"role_id": "Rolle ID",
|
||||
"rule": "Regel",
|
||||
|
||||
@@ -2206,6 +2206,8 @@
|
||||
"reference": "Referenz",
|
||||
"relay_in_id": "Indgangs relæ ID",
|
||||
"relay_machine_id": "Maskine relæ ID",
|
||||
"relay_machine_program_picker_id": "Machine program picker relay ID",
|
||||
"relay_machine_cleaner_id": "Machine cleaner relay ID",
|
||||
"relay_out_id": "Udgangs relæ ID",
|
||||
"role_id": "Rollen-ID",
|
||||
"rule": "Regel",
|
||||
|
||||
@@ -2206,6 +2206,8 @@
|
||||
"reference": "Reference",
|
||||
"relay_in_id": "Input relay ID",
|
||||
"relay_machine_id": "Machine relay ID",
|
||||
"relay_machine_program_picker_id": "Machine program picker relay ID",
|
||||
"relay_machine_cleaner_id": "Machine cleaner relay ID",
|
||||
"relay_out_id": "Output relay ID",
|
||||
"role_id": "Role ID",
|
||||
"rule": "Rule",
|
||||
|
||||
@@ -2201,6 +2201,8 @@
|
||||
"reference": "Referanse",
|
||||
"relay_in_id": "Inndatarelé-ID",
|
||||
"relay_machine_id": "Maskinrelé-ID",
|
||||
"relay_machine_program_picker_id": "Machine program picker relay ID",
|
||||
"relay_machine_cleaner_id": "Machine cleaner relay ID",
|
||||
"relay_out_id": "Utgangsrelé-ID",
|
||||
"role_id": "Rolle-ID",
|
||||
"rule": "Regel",
|
||||
|
||||
@@ -2201,6 +2201,8 @@
|
||||
"reference": "Referens",
|
||||
"relay_in_id": "Ingångsrelä-ID",
|
||||
"relay_machine_id": "Maskinrelä-ID",
|
||||
"relay_machine_program_picker_id": "Machine program picker relay ID",
|
||||
"relay_machine_cleaner_id": "Machine cleaner relay ID",
|
||||
"relay_out_id": "Utgångsrelä-ID",
|
||||
"role_id": "Role ID",
|
||||
"rule": "Rule",
|
||||
|
||||
@@ -2092,6 +2092,8 @@
|
||||
"reference": "Referens",
|
||||
"relay_in_id": "Indgangs relæ ID",
|
||||
"relay_machine_id": "Maskine relæ ID",
|
||||
"relay_machine_program_picker_id": "Machine program picker relay ID",
|
||||
"relay_machine_cleaner_id": "Machine cleaner relay ID",
|
||||
"relay_out_id": "Udgangs relæ ID",
|
||||
"role_id": "Role ID",
|
||||
"rule": "Rule",
|
||||
|
||||
@@ -136,6 +136,28 @@ onMounted(() => {
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ SessionUser.objects.department_lanes.columns.relay_machine_program_picker_id.label }}</th>
|
||||
<td>
|
||||
<span class="icon" :class="{ 'has-text-warning': !lane.relay_machine_program_picker_id, 'has-text-success': lane.relay_machine_program_picker_id }">
|
||||
<i :class="!lane.relay_machine_program_picker_id ? 'fas fa-exclamation-triangle' : 'fas fa-check-circle'"></i>
|
||||
</span>
|
||||
<span>
|
||||
{{ lane.relay_machine_program_picker_id || SessionUser.objects.global.language.not_configured }}
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ SessionUser.objects.department_lanes.columns.relay_machine_cleaner_id.label }}</th>
|
||||
<td>
|
||||
<span class="icon" :class="{ 'has-text-warning': !lane.relay_machine_cleaner_id, 'has-text-success': lane.relay_machine_cleaner_id }">
|
||||
<i :class="!lane.relay_machine_cleaner_id ? 'fas fa-exclamation-triangle' : 'fas fa-check-circle'"></i>
|
||||
</span>
|
||||
<span>
|
||||
{{ lane.relay_machine_cleaner_id || SessionUser.objects.global.language.not_configured }}
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ SessionUser.objects.department_lanes.columns.dynamic_image_id.label }}</th>
|
||||
<td>
|
||||
|
||||
@@ -172,6 +172,28 @@ onMounted(() => {
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ SessionUser.objects.department_lanes.columns.relay_machine_program_picker_id.label }}</th>
|
||||
<td>
|
||||
<span class="icon" :class="{ 'has-text-warning': !lane.relay_machine_program_picker_id, 'has-text-success': lane.relay_machine_program_picker_id }">
|
||||
<i :class="!lane.relay_machine_program_picker_id ? 'fas fa-exclamation-triangle' : 'fas fa-check-circle'"></i>
|
||||
</span>
|
||||
<span>
|
||||
{{ lane.relay_machine_program_picker_id || SessionUser.objects.global.language.not_configured }}
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ SessionUser.objects.department_lanes.columns.relay_machine_cleaner_id.label }}</th>
|
||||
<td>
|
||||
<span class="icon" :class="{ 'has-text-warning': !lane.relay_machine_cleaner_id, 'has-text-success': lane.relay_machine_cleaner_id }">
|
||||
<i :class="!lane.relay_machine_cleaner_id ? 'fas fa-exclamation-triangle' : 'fas fa-check-circle'"></i>
|
||||
</span>
|
||||
<span>
|
||||
{{ lane.relay_machine_cleaner_id || SessionUser.objects.global.language.not_configured }}
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ SessionUser.objects.department_lanes.columns.dynamic_image_id.label }}</th>
|
||||
<td>
|
||||
|
||||
+2
-2
@@ -54,7 +54,7 @@ export const relays = {
|
||||
on: on
|
||||
}
|
||||
),
|
||||
MACHINE_PROGRAM_PICKER: (laneId: number, on: boolean) => SessionUser.request(
|
||||
PROGRAM_PICKER: (laneId: number, on: boolean) => SessionUser.request(
|
||||
"/modules/self-serve/lane/relay/machine_program_picker/set",
|
||||
"POST",
|
||||
{
|
||||
@@ -62,7 +62,7 @@ export const relays = {
|
||||
on: on
|
||||
}
|
||||
),
|
||||
MACHINE_CLEANER: (laneId: number, on: boolean) => SessionUser.request(
|
||||
CLEANER: (laneId: number, on: boolean) => SessionUser.request(
|
||||
"/modules/self-serve/lane/relay/machine_cleaner/set",
|
||||
"POST",
|
||||
{
|
||||
|
||||
+47
-8
@@ -1,30 +1,69 @@
|
||||
<script setup lang="ts">
|
||||
import {defineProps, defineEmits} from 'vue';
|
||||
import {BButton} from "buefy";
|
||||
import {defineProps, onMounted, ref} from 'vue';
|
||||
import {BButton, BSwitch} from "buefy";
|
||||
import { relays } from "@/views/dashboards/superUserDashboard/selfserve/components/SelfServeMachineConnectivity.vue";
|
||||
import SelfServeMachineStatus
|
||||
from "@/views/dashboards/superUserDashboard/selfserve/displays/machine/SelfServeMachineStatus.vue";
|
||||
defineProps<{machine: any}>();
|
||||
import type MachineType from "@/views/dashboards/superUserDashboard/selfserve/types/MachineType.vue";
|
||||
const props = defineProps<{machine: MachineType}>();
|
||||
|
||||
const machineRelayStatus = ref(null);
|
||||
const programPickerRelayStatus = ref(null);
|
||||
const cleanerRelayStatus = ref(null);
|
||||
|
||||
// Get status on mount
|
||||
onMounted(() => {
|
||||
relays.get.status.MACHINE(props.machine.id).then((response) => {
|
||||
/**
|
||||
* {
|
||||
* "lane_id": 3,
|
||||
* "relay": "MACHINE",
|
||||
* "relay_id": "e4b3231cce40",
|
||||
* "online": true,
|
||||
* "on": true
|
||||
* }
|
||||
*/
|
||||
machineRelayStatus.value = response.data.data;
|
||||
})
|
||||
relays.get.status.PROGRAM_PICKER(props.machine.id).then((response) => {
|
||||
programPickerRelayStatus.value = response.data.data;
|
||||
})
|
||||
relays.get.status.CLEANER(props.machine.id).then((response) => {
|
||||
cleanerRelayStatus.value = response.data.data;
|
||||
})
|
||||
});
|
||||
|
||||
const parseStatus = (status: any) => {
|
||||
if (!status) return "MAINTENANCE";
|
||||
if (!status.online) return "OFFLINE";
|
||||
return status.on ? "ON" : "OFF";
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<p>Relay Controls</p>
|
||||
<div class="columns is-multiline is-mobile">
|
||||
|
||||
<div class="column is-half">
|
||||
<p>Machine Relay</p>
|
||||
</div>
|
||||
<div class="column is-half">
|
||||
<SelfServeMachineStatus :machine-status="parseStatus(machineRelayStatus)" />
|
||||
<b-button @click="relays.get.status.MACHINE(props.machine.id)" size="is-small" type="is-info">Get Status</b-button>
|
||||
</div>
|
||||
<div class="column is-half">
|
||||
<p>Program Picker Relay</p>
|
||||
</div>
|
||||
<div class="column is-half">
|
||||
<SelfServeMachineStatus machine-status="OFFLINE" />
|
||||
<b-button @click="relays.get.status.PROGRAM_PICKER(machine.id)" size="is-small" type="is-info">Get Status</b-button>
|
||||
<SelfServeMachineStatus :machine-status="parseStatus(programPickerRelayStatus)" />
|
||||
<b-button @click="relays.get.status.PROGRAM_PICKER(props.machine.id)" size="is-small" type="is-info">Get Status</b-button>
|
||||
</div>
|
||||
<div class="column is-half">
|
||||
<p>Cleaner Relay</p>
|
||||
</div>
|
||||
<div class="column is-half">
|
||||
<SelfServeMachineStatus machine-status="OFFLINE" />
|
||||
<b-button @click="relays.get.status.CLEANER(machine.id)" size="is-small" type="is-info">Get Status</b-button>
|
||||
<SelfServeMachineStatus :machine-status="parseStatus(cleanerRelayStatus)" />
|
||||
<b-button @click="relays.get.status.CLEANER(props.machine.id)" size="is-small" type="is-info">Get Status</b-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+4
@@ -8,11 +8,15 @@ const icon = {
|
||||
ONLINE: "check",
|
||||
OFFLINE: "close",
|
||||
MAINTENANCE: "tools",
|
||||
ON: "check",
|
||||
OFF: "close",
|
||||
}
|
||||
const type = {
|
||||
ONLINE: "is-success",
|
||||
OFFLINE: "is-danger",
|
||||
MAINTENANCE: "is-warning",
|
||||
ON: "is-success",
|
||||
OFF: "is-danger",
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
@@ -3,6 +3,8 @@ const MachineStatus = {
|
||||
ONLINE: "ONLINE",
|
||||
OFFLINE: "OFFLINE",
|
||||
MAINTENANCE: "MAINTENANCE",
|
||||
ON: "ON",
|
||||
OFF: "OFF",
|
||||
} as const;
|
||||
export type { MachineStatus };
|
||||
export default MachineStatus;
|
||||
|
||||
@@ -71,6 +71,8 @@ function createSelfServeFixture(overrides = {}) {
|
||||
relay_in_id: "IN-7",
|
||||
relay_out_id: "OUT-7",
|
||||
relay_machine_id: "M-7",
|
||||
relay_machine_program_picker_id: "MPP-7",
|
||||
relay_machine_cleaner_id: "MC-7",
|
||||
dynamic_image_id: 77,
|
||||
machine_type_id: null,
|
||||
},
|
||||
@@ -84,6 +86,8 @@ function createSelfServeFixture(overrides = {}) {
|
||||
relay_in_id: "IN-8",
|
||||
relay_out_id: "OUT-8",
|
||||
relay_machine_id: "M-8",
|
||||
relay_machine_program_picker_id: "MPP-8",
|
||||
relay_machine_cleaner_id: "MC-8",
|
||||
dynamic_image_id: 78,
|
||||
machine_type_id: null,
|
||||
},
|
||||
@@ -107,6 +111,8 @@ function createSelfServeFixture(overrides = {}) {
|
||||
relay_in_id: "IN-9",
|
||||
relay_out_id: "OUT-9",
|
||||
relay_machine_id: "M-9",
|
||||
relay_machine_program_picker_id: "MPP-9",
|
||||
relay_machine_cleaner_id: "MC-9",
|
||||
dynamic_image_id: 79,
|
||||
machine_type_id: null,
|
||||
},
|
||||
@@ -130,6 +136,8 @@ function createSelfServeFixture(overrides = {}) {
|
||||
relay_in_id: "IN-10",
|
||||
relay_out_id: "OUT-10",
|
||||
relay_machine_id: "M-10",
|
||||
relay_machine_program_picker_id: "MPP-10",
|
||||
relay_machine_cleaner_id: "MC-10",
|
||||
dynamic_image_id: 80,
|
||||
machine_type_id: null,
|
||||
},
|
||||
|
||||
@@ -5,16 +5,23 @@ import { describe, expect, it } from "vitest";
|
||||
const readSource = (relativePath) => readFileSync(join(process.cwd(), relativePath), "utf8");
|
||||
|
||||
describe("self-serve alignment", () => {
|
||||
it("registers reusable machine types and lane machine_type_id wiring", () => {
|
||||
it("registers reusable machine types and lane relay/machine_type wiring", () => {
|
||||
const sessionUserSource = readSource("src/components/session/token/SessionUser.vue");
|
||||
const laneSource = readSource("src/components/session/token/SessionUser/Objects/DepartmentLanes.vue");
|
||||
const laneViewSource = readSource("src/views/dashboards/departmentDashboard/modules/wash-lanes/DepartmentWashLane.vue");
|
||||
const laneAdminViewSource = readSource("src/views/dashboards/departmentDashboard/modules/wash-lanes/DepartmentWashLane.vue");
|
||||
const laneSuperUserViewSource = readSource("src/views/dashboards/superUserDashboard/department/lanes/DepartmentLane.vue");
|
||||
|
||||
expect(sessionUserSource).toMatch(/self_serve_machine_types\s*:\s*SelfServeMachineTypes\s*,/);
|
||||
expect(sessionUserSource).not.toMatch(/get\s+self_serve_machine_types\s*\(/);
|
||||
expect(laneSource).toContain("relay_machine_program_picker_id:");
|
||||
expect(laneSource).toContain("relay_machine_cleaner_id:");
|
||||
expect(laneSource).toContain("machine_type_id:");
|
||||
expect(laneSource).toContain("SessionUser.objects.self_serve_machine_types.get.all()");
|
||||
expect(laneViewSource).toContain(":set-machine-type-filter=\"lane.machine_type_id || null\"");
|
||||
expect(laneAdminViewSource).toContain(":set-machine-type-filter=\"lane.machine_type_id || null\"");
|
||||
expect(laneAdminViewSource).toContain("lane.relay_machine_program_picker_id");
|
||||
expect(laneAdminViewSource).toContain("lane.relay_machine_cleaner_id");
|
||||
expect(laneSuperUserViewSource).toContain("lane.relay_machine_program_picker_id");
|
||||
expect(laneSuperUserViewSource).toContain("lane.relay_machine_cleaner_id");
|
||||
});
|
||||
|
||||
it("normalizes self-serve config reads and submits merged config payloads", () => {
|
||||
|
||||
Reference in New Issue
Block a user