@@ -17,8 +17,15 @@
|
||||
<div class="card-header bg-dark text-light fw-bold rounded-top">
|
||||
<i class="bi bi-camera-video me-1"></i>{{ _('Live Webcam') }}
|
||||
</div>
|
||||
<div class="card-body p-0 ratio ratio-16x9">
|
||||
<div class="card-body p-0 ratio ratio-16x9 bg-secondary bg-opacity-25 d-flex align-items-center justify-content-center">
|
||||
{% if current_user.is_guest %}
|
||||
<div class="text-center text-dark">
|
||||
<i class="bi bi-lock-fill display-4 d-block mb-3"></i>
|
||||
<h5 class="mb-0">{{ _('Please login to view the webcam stream.') }}</h5>
|
||||
</div>
|
||||
{% else %}
|
||||
<img src="{{ webcam_url }}" alt="{{ _('Loading webcam stream...') }}" class="w-100 h-100 object-fit-cover">
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<i class="bi bi-info-circle me-1"></i>{{ _('Current State') }}
|
||||
</div>
|
||||
<div class="card-body text-center">
|
||||
<h3 class="display-6 mt-3 text-primary">{{ status.get('state', {}).get('text', 'Unknown') }}</h3>
|
||||
<h3 class="display-6 mt-3 text-primary" id="printer-state-text">{{ status.get('state', {}).get('text', 'Unknown') if status else 'Unknown' }}</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -33,43 +33,42 @@
|
||||
<i class="bi bi-thermometer-half me-1"></i>{{ _('Temperatures') }}
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% set temps = status.get('temperature', {}) %}
|
||||
{% set temps = status.get('temperature', {}) if status else {} %}
|
||||
|
||||
<h5 class="mb-1"><i class="bi bi-fire text-danger me-2"></i>{{ _('Tool/Nozzle') }}</h5>
|
||||
<h4 class="ms-4 mb-4">
|
||||
{{ temps.get('tool0', {}).get('actual', 0) }} °C
|
||||
<small class="text-muted fs-6">/ {{ temps.get('tool0', {}).get('target', 0) }} °C</small>
|
||||
<span id="tool-actual">{{ temps.get('tool0', {}).get('actual', 0) }}</span> °C
|
||||
<small class="text-muted fs-6">/ <span id="tool-target">{{ temps.get('tool0', {}).get('target', 0) }}</span> °C</small>
|
||||
</h4>
|
||||
|
||||
<h5 class="mb-1"><i class="bi bi-square-fill text-warning me-2"></i>{{ _('Bed') }}</h5>
|
||||
<h4 class="ms-4">
|
||||
{{ temps.get('bed', {}).get('actual', 0) }} °C
|
||||
<small class="text-muted fs-6">/ {{ temps.get('bed', {}).get('target', 0) }} °C</small>
|
||||
<span id="bed-actual">{{ temps.get('bed', {}).get('actual', 0) }}</span> °C
|
||||
<small class="text-muted fs-6">/ <span id="bed-target">{{ temps.get('bed', {}).get('target', 0) }}</span> °C</small>
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if job and job.get('job', {}).get('file', {}).get('name') %}
|
||||
<div class="card shadow-sm mt-4 border-success">
|
||||
<div class="card shadow-sm mt-4 border-success" id="active-job-card" style="display: {% if job and job.get('job', {}).get('file', {}).get('name') %}block{% else %}none{% endif %};">
|
||||
<div class="card-header bg-success text-white fw-bold">
|
||||
<i class="bi bi-play-circle me-1"></i>{{ _('Active Print Job') }}
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<h5>{{ job.get('job', {}).get('file', {}).get('name') }}</h5>
|
||||
<h5 id="job-file-name">{{ job.get('job', {}).get('file', {}).get('display_name') or job.get('job', {}).get('file', {}).get('name') if job else '' }}</h5>
|
||||
|
||||
{% set progress = job.get('progress', {}).get('completion', 0) %}
|
||||
{% set progress = job.get('progress', {}).get('completion', 0) if job else 0 %}
|
||||
{% if progress == None %}{% set progress = 0 %}{% endif %}
|
||||
<div class="progress mt-3 mb-2" style="height: 25px;">
|
||||
<div class="progress-bar progress-bar-striped progress-bar-animated bg-success" role="progressbar" style="width: {{ progress }}%;" aria-valuenow="{{ progress }}" aria-valuemin="0" aria-valuemax="100">
|
||||
{{ "%.1f"|format(progress) }}%
|
||||
<div id="job-progress-bar" class="progress-bar progress-bar-striped progress-bar-animated bg-success" role="progressbar" style="width: {{ progress }}%;" aria-valuenow="{{ progress }}" aria-valuemin="0" aria-valuemax="100">
|
||||
<span id="job-progress-text">{{ "%.1f"|format(progress) }}%</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-between text-muted small mt-2">
|
||||
<span><strong>{{ _('Print Time:') }}</strong> {{ job.get('progress', {}).get('printTime', 0) }}s</span>
|
||||
<span><strong>{{ _('Time Left:') }}</strong> {{ job.get('progress', {}).get('printTimeLeft', 0) }}s</span>
|
||||
<span><strong>{{ _('Print Time:') }}</strong> <span id="job-print-time">{{ job.get('progress', {}).get('printTime', 0) if job else 0 }}</span>s</span>
|
||||
<span><strong>{{ _('Time Left:') }}</strong> <span id="job-time-left">{{ job.get('progress', {}).get('printTimeLeft', 0) if job else 0 }}</span>s</span>
|
||||
</div>
|
||||
|
||||
<div class="mt-4 gap-2 d-flex">
|
||||
@@ -78,11 +77,47 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
<script>
|
||||
function updateStatus() {
|
||||
fetch('{{ url_for("printer.api_status_data") }}')
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
if(data.success) {
|
||||
if(data.status && data.status.state) {
|
||||
document.getElementById('printer-state-text').innerText = data.status.state.text || 'Unknown';
|
||||
}
|
||||
if(data.status && data.status.temperature) {
|
||||
const tool = data.status.temperature.tool0 || {};
|
||||
const bed = data.status.temperature.bed || {};
|
||||
document.getElementById('tool-actual').innerText = tool.actual !== undefined ? tool.actual : 0;
|
||||
document.getElementById('tool-target').innerText = tool.target !== undefined ? tool.target : 0;
|
||||
document.getElementById('bed-actual').innerText = bed.actual !== undefined ? bed.actual : 0;
|
||||
document.getElementById('bed-target').innerText = bed.target !== undefined ? bed.target : 0;
|
||||
}
|
||||
const jobCard = document.getElementById('active-job-card');
|
||||
if(data.job && data.job.job && data.job.job.file && data.job.job.file.name) {
|
||||
jobCard.style.display = 'block';
|
||||
document.getElementById('job-file-name').innerText = data.job.job.file.display_name || data.job.job.file.name;
|
||||
let progress = data.job.progress && data.job.progress.completion ? data.job.progress.completion : 0;
|
||||
document.getElementById('job-progress-bar').style.width = progress + '%';
|
||||
document.getElementById('job-progress-bar').setAttribute('aria-valuenow', progress);
|
||||
document.getElementById('job-progress-text').innerText = progress.toFixed(1) + '%';
|
||||
document.getElementById('job-print-time').innerText = data.job.progress ? (data.job.progress.printTime || 0) : 0;
|
||||
document.getElementById('job-time-left').innerText = data.job.progress ? (data.job.progress.printTimeLeft || 0) : 0;
|
||||
} else {
|
||||
jobCard.style.display = 'none';
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(err => console.error("Error fetching status:", err));
|
||||
}
|
||||
{% if not error %}
|
||||
setInterval(updateStatus, 1000);
|
||||
{% endif %}
|
||||
|
||||
function sendCmd(cmd) {
|
||||
if(cmd === 'cancel') {
|
||||
window.customConfirm("{{ _('Are you sure you want to cancel the print?') }}", () => doSendCmd(cmd));
|
||||
@@ -99,12 +134,11 @@ function doSendCmd(cmd) {
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
if(data.success) {
|
||||
window.location.reload();
|
||||
updateStatus();
|
||||
} else {
|
||||
window.customAlert("Error: " + data.error);
|
||||
}
|
||||
});
|
||||
}
|
||||
setTimeout(() => { if (!window.pauseRefresh) window.location.reload(); }, 15000);
|
||||
</script>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user