Files
IT_asset_management/app/templates/paperwork/form.html

169 lines
6.9 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{% extends 'base.html' %}
{% block title %}New Document IT Asset Management{% endblock %}
{% block breadcrumb %}
<li class="breadcrumb-item"><a href="{{ url_for('dashboard.index') }}">Home</a></li>
<li class="breadcrumb-item"><a href="{{ url_for('paperwork.index') }}">Paperwork</a></li>
<li class="breadcrumb-item active">New Document</li>
{% endblock %}
{% block content %}
<div class="page-header mb-4">
<h1><i class="bi bi-file-earmark-plus me-2"></i>Create Document</h1>
</div>
<div class="card border-0 shadow-sm" style="max-width:740px;">
<div class="card-body">
<form method="POST" action="{{ url_for('paperwork.create') }}">
<div class="row g-3 mb-3">
<div class="col-md-6">
<label class="form-label">Document Type <span class="text-danger">*</span></label>
<select name="document_type" class="form-select" id="docType">
{% for val, label in doc_types %}
<option value="{{ val }}">{{ label }}</option>
{% endfor %}
</select>
</div>
<div class="col-md-6">
<label class="form-label">Title</label>
<input type="text" name="title" class="form-control"
placeholder="Leave blank to auto-generate">
</div>
</div>
<!-- Word Template selector -->
{% if all_templates %}
<div class="mb-3">
<label class="form-label">
Word Template
<span class="text-muted small">(optional — generates an editable .docx)</span>
</label>
<select name="template_id" id="templateSelect" class="form-select">
<option value="">— No template (PDF only) —</option>
{% for tpl in all_templates %}
<option value="{{ tpl.id }}">{{ tpl.name }}{% if tpl.category %} [{{ tpl.category }}]{% endif %}</option>
{% endfor %}
</select>
<!-- Variable preview loaded via AJAX -->
<div id="tplVarsBox" class="mt-2" style="display:none">
<div class="small text-muted mb-1">Variables auto-filled from this template:</div>
<div id="tplVarsList" class="d-flex flex-wrap gap-1"></div>
</div>
</div>
{% endif %}
<!-- User search -->
<div class="mb-3">
<label class="form-label">User <span class="text-danger">*</span></label>
<input type="hidden" name="user_id" id="userId" value="{{ preselect_user_id or '' }}">
<input type="text" id="userSearch" class="form-control"
placeholder="Type name or Windows ID…" autocomplete="off">
<div id="userDropdown" class="list-group position-absolute shadow" style="z-index:1000;display:none;min-width:350px;"></div>
<div id="userDisplay" class="form-text text-success fw-semibold"></div>
</div>
<!-- Asset search (optional) -->
<div class="mb-3">
<label class="form-label">Asset <span class="text-muted small">(optional)</span></label>
<input type="hidden" name="asset_id" id="assetId" value="{{ preselect_asset_id or '' }}">
<input type="text" id="assetSearch" class="form-control"
placeholder="Serial number or service tag…" autocomplete="off">
<div id="assetDropdown" class="list-group position-absolute shadow" style="z-index:1000;display:none;min-width:350px;"></div>
<div id="assetDisplay" class="form-text text-success fw-semibold"></div>
</div>
{% if preselect_assignment_id %}
<input type="hidden" name="assignment_id" value="{{ preselect_assignment_id }}">
{% endif %}
<div class="mb-3">
<label class="form-label">Notes</label>
<textarea name="notes" class="form-control" rows="2"></textarea>
</div>
<div class="d-flex gap-2">
<button type="submit" class="btn btn-primary">
<i class="bi bi-file-earmark-check me-1"></i>Generate Document
</button>
<a href="{{ url_for('paperwork.index') }}" class="btn btn-outline-secondary">Cancel</a>
</div>
</form>
</div>
</div>
{% if all_templates %}
<div class="mt-3">
<a href="{{ url_for('doc_templates.index') }}" class="btn btn-sm btn-outline-primary">
<i class="bi bi-file-earmark-word me-1"></i>Manage Templates
</a>
</div>
{% endif %}
{% endblock %}
{% block extra_js %}
<script>
function liveSearch(inputId, dropdownId, hiddenId, displayId, endpoint) {
const input = document.getElementById(inputId);
const dropdown = document.getElementById(dropdownId);
const hidden = document.getElementById(hiddenId);
const display = document.getElementById(displayId);
let timer;
input.addEventListener('input', () => {
clearTimeout(timer);
timer = setTimeout(() => {
const q = input.value.trim();
if (q.length < 2) { dropdown.style.display = 'none'; return; }
fetch(`${endpoint}?q=${encodeURIComponent(q)}`)
.then(r => r.json())
.then(items => {
dropdown.innerHTML = '';
if (!items.length) { dropdown.style.display = 'none'; return; }
items.forEach(item => {
const a = document.createElement('a');
a.className = 'list-group-item list-group-item-action py-2';
a.textContent = item.text;
a.addEventListener('click', () => {
hidden.value = item.id;
input.value = item.text;
display.textContent = '✓ Selected';
dropdown.style.display = 'none';
});
dropdown.appendChild(a);
});
dropdown.style.display = 'block';
});
}, 250);
});
document.addEventListener('click', e => { if (!input.contains(e.target)) dropdown.style.display = 'none'; });
}
liveSearch('userSearch', 'userDropdown', 'userId', 'userDisplay', '{{ url_for("users.search") }}');
liveSearch('assetSearch', 'assetDropdown', 'assetId', 'assetDisplay', '{{ url_for("assets.search") }}');
// Template variable preview
const tplSelect = document.getElementById('templateSelect');
if (tplSelect) {
const PII_VARS = new Set(['user_name', 'user_email', 'user_phone']);
tplSelect.addEventListener('change', () => {
const id = tplSelect.value;
const box = document.getElementById('tplVarsBox');
const list = document.getElementById('tplVarsList');
if (!id) { box.style.display = 'none'; return; }
fetch(`/doc-templates/${id}/variables.json`)
.then(r => r.json())
.then(data => {
list.innerHTML = '';
(data.variables || []).forEach(v => {
const badge = document.createElement('span');
badge.className = 'badge ' + (PII_VARS.has(v) ? 'bg-danger' : 'bg-secondary');
badge.title = PII_VARS.has(v) ? 'PII — will be masked on user departure' : '';
badge.textContent = '{{ ' + v + ' }}';
list.appendChild(badge);
});
box.style.display = 'block';
})
.catch(() => { box.style.display = 'none'; });
});
}
</script>
{% endblock %}