400 lines
16 KiB
HTML
400 lines
16 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<!-- <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'"> -->
|
|
<title>Machine Description Form</title>
|
|
<style>
|
|
body {
|
|
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
|
background-color: #f4f4f9;
|
|
color: #333;
|
|
line-height: 1.6;
|
|
margin: 0;
|
|
padding: 20px;
|
|
}
|
|
.container {
|
|
max-width: 800px;
|
|
margin: auto;
|
|
background: #fff;
|
|
padding: 25px;
|
|
border-radius: 10px;
|
|
box-shadow: 0 0 20px rgba(0,0,0,0.1);
|
|
}
|
|
h2 {
|
|
color: #2649B2;
|
|
text-align: center;
|
|
margin-bottom: 25px;
|
|
}
|
|
fieldset {
|
|
border: 1px solid #D4D9F0;
|
|
border-radius: 8px;
|
|
padding: 20px;
|
|
margin-bottom: 20px;
|
|
}
|
|
legend {
|
|
font-weight: bold;
|
|
color: #4A74F3;
|
|
padding: 0 10px;
|
|
font-size: 1.2em;
|
|
}
|
|
.form-group {
|
|
margin-bottom: 18px;
|
|
}
|
|
label {
|
|
display: block;
|
|
margin-bottom: 6px;
|
|
font-weight: bold;
|
|
}
|
|
input[type="text"],
|
|
input[type="number"],
|
|
input[type="email"],
|
|
input[type="date"],
|
|
select {
|
|
width: 100%;
|
|
padding: 10px;
|
|
border: 1px solid #ccc;
|
|
border-radius: 5px;
|
|
box-sizing: border-box;
|
|
}
|
|
input[readonly] {
|
|
background-color: #e9ecef;
|
|
cursor: not-allowed;
|
|
}
|
|
.radio-group {
|
|
display: flex;
|
|
align-items: center; /* This vertically aligns the text with the button */
|
|
}
|
|
.radio-group label {
|
|
display: inline-block; /* This prevents the label from taking a full line */
|
|
font-weight: normal;
|
|
margin-bottom: 0; /* Remove bottom margin for inline elements */
|
|
margin-left: 4px; /* Space between the button and the text */
|
|
margin-right: 20px; /* Space between the options */
|
|
}
|
|
small {
|
|
display: block;
|
|
margin-top: 5px;
|
|
color: #6c757d;
|
|
}
|
|
input[type="submit"] {
|
|
background-color: #4A74F3;
|
|
color: white;
|
|
padding: 12px 20px;
|
|
border: none;
|
|
border-radius: 5px;
|
|
cursor: pointer;
|
|
font-size: 18px;
|
|
font-weight: bold;
|
|
width: 100%;
|
|
margin-top: 20px;
|
|
transition: background-color 0.3s;
|
|
}
|
|
input[type="submit"]:hover {
|
|
background-color: #2649B2;
|
|
}
|
|
.checkbox-container {
|
|
display: grid;
|
|
grid-template-columns: auto 1fr; /* Checkbox column, then text takes remaining space */
|
|
gap: 0 10px; /* 10px space between checkbox and text */
|
|
align-items: start;
|
|
margin-bottom: 12px; /* Space between each checkbox item */
|
|
}
|
|
.checkbox-container input[type="checkbox"] {
|
|
margin-top: 5px; /* Nudges the checkbox down to align with the text */
|
|
}
|
|
.checkbox-container label {
|
|
font-weight: normal;
|
|
margin-bottom: 0;
|
|
display: block;
|
|
}
|
|
.checkbox-container label strong {
|
|
font-weight: bold; /* Make the label title bold */
|
|
display: block;
|
|
}
|
|
.checkbox-container label small {
|
|
margin-top: 2px;
|
|
line-height: 1.3;
|
|
}
|
|
.tab-nav {
|
|
border-bottom: 2px solid #D4D9F0;
|
|
display: flex;
|
|
}
|
|
.tab-nav button {
|
|
background: none;
|
|
border: none;
|
|
padding: 10px 15px;
|
|
cursor: pointer;
|
|
font-size: 1em;
|
|
color: #6c757d;
|
|
border-bottom: 3px solid transparent;
|
|
}
|
|
.tab-nav button.active {
|
|
color: #2649B2;
|
|
border-bottom-color: #2649B2;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.tab-content {
|
|
display: none;
|
|
padding-top: 20px;
|
|
}
|
|
.tab-content.active {
|
|
display: block;
|
|
}
|
|
|
|
.dynamic-table {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
margin-top: 15px;
|
|
}
|
|
.dynamic-table th, .dynamic-table td {
|
|
border: 1px solid #D4D9F0;
|
|
padding: 8px;
|
|
text-align: left;
|
|
vertical-align: top;
|
|
}
|
|
.dynamic-table th {
|
|
background-color: #f4f4f9;
|
|
}
|
|
.dynamic-table input, .dynamic-table textarea {
|
|
padding: 5px;
|
|
}
|
|
.dynamic-table .col-id {
|
|
width: 10%;
|
|
}
|
|
.dynamic-table .col-name {
|
|
width: 25%;
|
|
}
|
|
.dynamic-table .col-actions {
|
|
width: 15%;
|
|
text-align: center;
|
|
}
|
|
.add-row-btn {
|
|
margin-top: 15px;
|
|
padding: 8px 12px;
|
|
background-color: #6C8BE0;
|
|
color: white;
|
|
border: none;
|
|
border-radius: 5px;
|
|
cursor: pointer;
|
|
}
|
|
.add-row-btn:hover {
|
|
background-color: #5a7dc2;
|
|
}
|
|
.remove-row-btn {
|
|
padding: 5px 10px;
|
|
background-color: #e06c6c;
|
|
color: white;
|
|
border: none;
|
|
border-radius: 5px;
|
|
cursor: pointer;
|
|
}
|
|
.remove-row-btn:hover {
|
|
background-color: #c55a5a;
|
|
}
|
|
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<div class="container">
|
|
<h2>Machine Description</h2>
|
|
|
|
<nav class="tab-nav">
|
|
<button class="tab-btn active" data-tab="machine" id="machine-tab-btn">Machine</button>
|
|
<button class="tab-btn" data-tab="alarms" id="alarms-tab-btn">Alarms</button>
|
|
</nav>
|
|
|
|
<form id="machine-form">
|
|
|
|
<div class="tab-content" id="machine-tab" active>
|
|
<fieldset>
|
|
<legend>Machine Details</legend>
|
|
<div class="form-group">
|
|
<label for="machineType">MachineType</label>
|
|
<select id="machineType" name="machineType">
|
|
<option value="Unspecified">Unspecified</option>
|
|
<option value="Accumulation">Accumulation</option>
|
|
<option value="BulkFeedingSystem">BulkFeedingSystem</option>
|
|
<option value="Bundler">Bundler</option>
|
|
<option value="Capper">Capper</option>
|
|
<option value="Cartoner">Cartoner</option>
|
|
<option value="CasePacker">CasePacker</option>
|
|
<option value="CaseSealer">CaseSealer</option>
|
|
<option value="CheckWeigher">CheckWeigher</option>
|
|
<option value="DePalletizer">DePalletizer</option>
|
|
<option value="Feeder">Feeder</option>
|
|
<option value="Filler">Filler</option>
|
|
<option value="FillerCapper">FillerCapper</option>
|
|
<option value="FillSeal">FillSeal</option>
|
|
<option value="FormFillSeal">FormFillSeal</option>
|
|
<option value="Labeller">Labeller</option>
|
|
<option value="LineManagementController">LineManagementController</option>
|
|
<option value="OverWrapper">OverWrapper</option>
|
|
<option value="Palletizer">Palletizer</option>
|
|
<option value="PickAndPlace">PickAndPlace</option>
|
|
<option value="ShrinkWrapper">ShrinkWrapper</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="vendor">Vendor</label>
|
|
<input type="text" id="vendor" name="vendor">
|
|
<small>Company name of the machine vendor. Avoid whitespaces or special characters.</small>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="model">Model</label>
|
|
<input type="text" id="model" name="model">
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="serialNo">SerialNo</label>
|
|
<input type="text" id="serialNo" name="serialNo">
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="buildYear">Build Year</label>
|
|
<input type="number" id="buildYear" name="buildYear" placeholder="Ex: 2024" min="1980" max="2100">
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="browseName">BrowseName (OPC UA)</label>
|
|
<input type="text" id="browseName" name="browseName">
|
|
<small>This is the name of the machine which appears in the OPC UA server. Recommendation: MachineType + Numeric Suffix (e.g., Labeller1).</small>
|
|
</div>
|
|
</fieldset>
|
|
|
|
<fieldset>
|
|
<legend>Publication & Versioning</legend>
|
|
<div class="form-group">
|
|
<label for="publicationDate">Publication Date</label>
|
|
<input type="date" id="publicationDate" name="publicationDate">
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="authorEmail">Author Email</label>
|
|
<input type="email" id="authorEmail" name="authorEmail" placeholder="firstname.lastname@loreal.com">
|
|
<small>Email of the person to contact about this spreadsheet.</small>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="version">Version</label>
|
|
<input type="text" id="version" name="version" placeholder="Ex: 1.0.0">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Output Filename</label>
|
|
<!-- This is where the generated filename will be displayed -->
|
|
<p id="output-filename-display" style="font-family: monospace; background-color: #e9ecef; padding: 10px; border-radius: 5px;"></p>
|
|
<small>The filename is automatically generated from the BrowseName above.</small>
|
|
</div>
|
|
</fieldset>
|
|
|
|
<fieldset>
|
|
<legend>Alarm Configuration</legend>
|
|
<div class="form-group">
|
|
<label for="alarmRepresentation">AlarmRepresentation</label>
|
|
<select id="alarmRepresentation" name="alarmRepresentation">
|
|
<option value="DistinctAlarms">DistinctAlarms (Each alarm is a separate OPC UA variable)</option>
|
|
<option value="SingleAlarmsArray">SingleAlarmsArray (Alarms are packed in a Boolean array)</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="alarmBehavior">AlarmBehavior</label>
|
|
<select id="alarmBehavior" name="alarmBehavior">
|
|
<option value="STATIC">STATIC (Static allocation, recommended)</option>
|
|
<option value="DYNAMIC">DYNAMIC (Alarms are allocated in a dynamic table)</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="alarmCount">AlarmCount</label>
|
|
<input type="number" id="alarmCount" name="alarmCount" min="0">
|
|
<small>Used as the size of the array for DYNAMIC alarm behavior.</small>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="messagesLanguage">MessagesLanguage</label>
|
|
<select id="messagesLanguage" name="messagesLanguage">
|
|
<option value="EN">EN (English)</option>
|
|
<option value="FR">FR (Français)</option>
|
|
<option value="DE">DE (Deutsch)</option>
|
|
<option value="ES">ES (Español)</option>
|
|
<option value="IT">IT (Italiano)</option>
|
|
</select>
|
|
</div>
|
|
</fieldset>
|
|
|
|
<fieldset>
|
|
<legend>Optional Features</legend>
|
|
<div class="form-group">
|
|
<label>StopReason Generation</label>
|
|
<div class="radio-group">
|
|
<input type="radio" id="stopReasonYes" name="stopReason" value="Yes" checked>
|
|
<label for="stopReasonYes">Yes</label>
|
|
<input type="radio" id="stopReasonNo" name="stopReason" value="No">
|
|
<label for="stopReasonNo">No</label>
|
|
</div>
|
|
<small>Generate the special variable for the root cause of the machine stop. Boolean variable to trigger the read of properties alarmCode and alarmMessage. The StopReason is defined by PackML.</small>
|
|
</div>
|
|
</fieldset>
|
|
|
|
<fieldset>
|
|
<legend>ADD-INs</legend>
|
|
<div class="form-group">
|
|
<div class="checkbox-container">
|
|
<input type="checkbox" id="addins-acpower" name="addins" value="AcPower">
|
|
<label for="addins-acpower">
|
|
<strong>ACPower ADDIN</strong>
|
|
<small>Provides information about electrical consumption.</small>
|
|
</label>
|
|
</div>
|
|
<div class="checkbox-container">
|
|
<input type="checkbox" id="addins-utilities" name="addins" value="Utilities">
|
|
<label for="addins-utilities">
|
|
<strong>Utilities ADDIN</strong>
|
|
<small>Used for machines which consume or produce different sources of energy.</small>
|
|
</label>
|
|
</div>
|
|
<div class="checkbox-container">
|
|
<input type="checkbox" id="addins-trackadvance" name="addins" value="TrackAdvance">
|
|
<label for="addins-trackadvance">
|
|
<strong>TrackAdvance ADDIN</strong>
|
|
<small>Applies to filling machines supporting a cleaning in place (CIP) process.</small>
|
|
</label>
|
|
</div>
|
|
<div class="checkbox-container">
|
|
<input type="checkbox" id="addins-agv" name="addins" value="AGV">
|
|
<label for="addins-agv">
|
|
<strong>AGV ADDIN</strong>
|
|
<small>Applies to Palletizers which are interfaced with AGVs.</small>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</fieldset>
|
|
</div>
|
|
<div id="alarms-tab" class="tab-content">
|
|
<fieldset>
|
|
<legend>Alarms Exposed by the Machine</legend>
|
|
<p>Define all alarms for the machine. If the message is empty, the alarm will not be generated.</p>
|
|
<table class="dynamic-table">
|
|
<thead>
|
|
<tr><th class="col-id">ID</th><th class="col-name">Name</th><th>Message</th><th class="col-actions">Actions</th></tr>
|
|
</thead>
|
|
<tbody id="alarms-table-body"></tbody>
|
|
</table>
|
|
<button type="button" class="add-row-btn" id="add-alarm-btn">Add Alarm</button>
|
|
</fieldset>
|
|
</div>
|
|
|
|
|
|
<input type="submit" value="Validate and Submit Description">
|
|
</form>
|
|
</div>
|
|
|
|
<template id="alarm-row-template">
|
|
<tr>
|
|
<td><input type="number" name="alarm_id" min="1" placeholder="e.g., 1"></td>
|
|
<td><input type="text" name="alarm_name" placeholder="e.g., ALARM_1"></td>
|
|
<td><textarea name="alarm_message" rows="1" cols="50" placeholder="Message displayed on dashboard"></textarea></td>
|
|
<td class="col-actions"><button type="button" class="remove-row-btn">Remove</button></td>
|
|
</tr>
|
|
</template>
|
|
|
|
<script src="renderer.js"></script>
|
|
|
|
</body>
|
|
</html> |