Files
2025-12-02 16:27:21 +00:00

157 lines
5.9 KiB
Python

#!/usr/bin/env python3
import json
with open('/home/mdares/.node-red/flows.json', 'r') as f:
flows = json.load(f)
# HTML for resume/restart prompt modal
resume_prompt_html = '''
<!-- Resume/Restart Prompt Modal -->
<div id="resume-modal" class="modal" ng-show="resumePrompt.show">
<div class="modal-card">
<h2>Work Order Already In Progress</h2>
<p class="wo-info">{{ resumePrompt.id }}</p>
<p class="wo-summary">
<strong>{{ resumePrompt.goodParts }}</strong> of <strong>{{ resumePrompt.targetQty }}</strong> parts completed
({{ resumePrompt.progressPercent }}%)
</p>
<p class="wo-summary">Cycle Count: <strong>{{ resumePrompt.cycleCount }}</strong></p>
<div style="margin-top: 1.5rem; display: flex; flex-direction: column; gap: 0.75rem;">
<button class="prompt-continue" ng-click="resumeWorkOrder()">
Resume from {{ resumePrompt.goodParts }} parts
</button>
<button class="prompt-yes" ng-click="confirmRestart()">
Restart from 0 (Warning: Progress will be lost!)
</button>
</div>
</div>
</div>
'''
# JavaScript for handling resume prompt
resume_prompt_js = '''
// Resume/Restart Prompt State
scope.resumePrompt = {
show: false,
id: '',
sku: '',
cycleCount: 0,
goodParts: 0,
targetQty: 0,
progressPercent: 0,
order: null
};
scope.resumeWorkOrder = function() {
if (!scope.resumePrompt.order) {
console.error('No order data for resume');
return;
}
scope.send({
action: 'resume-work-order',
payload: scope.resumePrompt.order
});
scope.resumePrompt.show = false;
scope.hasActiveOrder = true;
};
scope.confirmRestart = function() {
if (!confirm('Are you sure you want to restart? All progress (' + scope.resumePrompt.goodParts + ' parts) will be lost!')) {
return;
}
if (!scope.resumePrompt.order) {
console.error('No order data for restart');
return;
}
scope.send({
action: 'restart-work-order',
payload: scope.resumePrompt.order
});
scope.resumePrompt.show = false;
scope.hasActiveOrder = true;
};
'''
# Watch handler for resume prompt
resume_watch_handler = '''
// Handle resume prompt
if (msg.topic === 'resumePrompt' && msg.payload) {
scope.resumePrompt.show = true;
scope.resumePrompt.id = msg.payload.id || '';
scope.resumePrompt.sku = msg.payload.sku || '';
scope.resumePrompt.cycleCount = msg.payload.cycleCount || 0;
scope.resumePrompt.goodParts = msg.payload.goodParts || 0;
scope.resumePrompt.targetQty = msg.payload.targetQty || 0;
scope.resumePrompt.progressPercent = msg.payload.progressPercent || 0;
scope.resumePrompt.order = msg.payload.order || null;
return;
}
'''
# Find Home Template node and update it
for node in flows:
if node.get('id') == '1821c4842945ecd8' and node.get('name') == 'Home Template':
template = node.get('format', '')
# Add resume modal HTML before the closing </div> of #oee or before scrap modal
if '<div id="scrap-modal"' in template:
# Insert before scrap modal
template = template.replace('<div id="scrap-modal"', resume_prompt_html + '<div id="scrap-modal"')
else:
# Insert before closing body tag or at end
template = template.replace('</div>\n<script>', '</div>\n' + resume_prompt_html + '\n<script>')
# Add resume prompt JS functions before the $watch section
if '(function(scope) {' in template and 'scope.$watch' in template:
# Find the first scope.$watch and insert before it
watch_idx = template.find('scope.$watch')
if watch_idx != -1:
# Find the start of the watch function (go back to find opening of scope function containing it)
# Insert resume JS right after "(function(scope) {" and before renderDashboard or other functions
# Better approach: insert before the closing })(scope); at the very end
closing_idx = template.rfind('})(scope);')
if closing_idx != -1:
template = template[:closing_idx] + resume_prompt_js + '\n ' + template[closing_idx:]
# Add watch handler for resumePrompt topic
# Find the $watch('msg' section and add handler
if "scope.$watch('msg'" in template:
# Find where msg.topic handlers are (look for "if (msg.topic ==" patterns)
# Insert our handler before the closing of the watch function
# Find the watch function and add handler inside it
# Look for the pattern where other topic handlers are
if "if (msg.topic === 'machineStatus')" in template:
# Insert before machineStatus handler
template = template.replace(
"if (msg.topic === 'machineStatus')",
resume_watch_handler + "\n if (msg.topic === 'machineStatus')"
)
elif 'scope.$watch' in template:
# Add at the beginning of the watch function
watch_start = template.find("scope.$watch('msg', function(msg) {")
if watch_start != -1:
# Find the first if statement after the watch declaration
insert_pos = template.find('if (!msg)', watch_start)
if insert_pos != -1:
# Insert after the "if (!msg) { return; }" block
after_null_check = template.find('}', insert_pos) + 1
template = template[:after_null_check] + '\n ' + resume_watch_handler + template[after_null_check:]
node['format'] = template
print("Updated Home Template with resume/restart prompt")
break
# Write back
with open('/home/mdares/.node-red/flows.json', 'w') as f:
json.dump(flows, f, indent=4)
print("Home Template updated successfully")