Rename module fusion_authorizer_portal -> fusion_portal everywhere: manifest/assets, controllers, models, views, JS (odoo.define + asset URLs), migration MODULE constants; plus cross-module refs in fusion_schedule, fusion_repairs, fusion_quotations (depends + inherit_id) and the pdf_filler import in fusion_claims. Add rename_module.sql for the one-time in-place DB rename (ir_module_module, ir_model_data, ir_ui_view.key, ir_module_module_dependency) required on installed envs before -u fusion_portal. Document the rename gotcha as rule 16 in CLAUDE.md. Redesign the Accessibility Assessment selector: replace Font Awesome icon tiles with photo-banner cards using 7 optimized images (1000x750 PNG -> 800x600 JPEG, ~8MB -> 488KB), per-type colour accent bar + centered pill button, hover lift/zoom. Images ship as module static files so they deploy/sync with the module. Drop the regenerable graphify-out cache from the module. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
185 lines
11 KiB
XML
185 lines
11 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<odoo>
|
|
|
|
<!-- ============================================================ -->
|
|
<!-- Visual PDF Field Position Editor -->
|
|
<!-- Drag field types from sidebar onto PDF, resize on page -->
|
|
<!-- ============================================================ -->
|
|
<template id="portal_pdf_field_editor" name="PDF Field Editor">
|
|
<t t-call="web.frontend_layout">
|
|
<t t-set="title">PDF Field Editor</t>
|
|
|
|
<div class="container-fluid py-3" id="pdf_field_editor"
|
|
t-att-data-template-id="template.id"
|
|
t-att-data-page-count="template.page_count or 1"
|
|
t-att-data-current-page="1"
|
|
t-att-data-category="template.category or 'other'">
|
|
|
|
<!-- Header Bar -->
|
|
<div class="d-flex justify-content-between align-items-center mb-3">
|
|
<div>
|
|
<h3 class="mb-0">
|
|
<i class="fa fa-pencil-square-o me-2"/>
|
|
<t t-esc="template.name"/>
|
|
<small class="text-muted ms-2">v<t t-esc="template.version"/></small>
|
|
</h3>
|
|
<small class="text-muted">
|
|
<t t-esc="template.page_count or 0"/> page(s) |
|
|
<span id="field_count"><t t-esc="len(fields)"/></span> field(s)
|
|
</small>
|
|
</div>
|
|
<div class="d-flex gap-2">
|
|
<button type="button" class="btn btn-outline-info btn-sm" id="btn_preview">
|
|
<i class="fa fa-eye me-1"/>Preview PDF
|
|
</button>
|
|
<a t-att-href="'/web#id=%d&model=fusion.pdf.template&view_type=form' % template.id"
|
|
class="btn btn-secondary btn-sm">
|
|
<i class="fa fa-arrow-left me-1"/>Back
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Page Navigation -->
|
|
<div class="d-flex justify-content-center align-items-center mb-3 gap-3"
|
|
t-if="(template.page_count or 1) > 1">
|
|
<button type="button" class="btn btn-sm btn-outline-secondary" id="btn_prev_page">
|
|
<i class="fa fa-chevron-left"/>
|
|
</button>
|
|
<span>
|
|
Page <strong id="current_page_display">1</strong>
|
|
of <strong><t t-esc="template.page_count or 1"/></strong>
|
|
</span>
|
|
<button type="button" class="btn btn-sm btn-outline-secondary" id="btn_next_page">
|
|
<i class="fa fa-chevron-right"/>
|
|
</button>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<!-- Left Sidebar: Field Type Palette -->
|
|
<div class="col-md-2">
|
|
<!-- Draggable Field Types -->
|
|
<div class="card mb-3">
|
|
<div class="card-header bg-dark text-white py-2">
|
|
<h6 class="mb-0"><i class="fa fa-th-list me-1"/>Field Types</h6>
|
|
</div>
|
|
<div class="card-body p-2">
|
|
<p class="text-muted small mb-2">Drag a field onto the PDF</p>
|
|
|
|
<div class="d-grid gap-2">
|
|
<div class="pdf-palette-item" draggable="true"
|
|
data-field-type="text"
|
|
style="padding: 8px 10px; border: 2px solid #3498db; border-radius: 5px;
|
|
background: rgba(52,152,219,0.1); cursor: grab; font-size: 13px; font-weight: 600;">
|
|
<i class="fa fa-font me-2" style="color: #3498db;"/>Text Field
|
|
</div>
|
|
|
|
<div class="pdf-palette-item" draggable="true"
|
|
data-field-type="checkbox"
|
|
style="padding: 8px 10px; border: 2px solid #2ecc71; border-radius: 5px;
|
|
background: rgba(46,204,113,0.1); cursor: grab; font-size: 13px; font-weight: 600;">
|
|
<i class="fa fa-check-square-o me-2" style="color: #2ecc71;"/>Checkbox
|
|
</div>
|
|
|
|
<div class="pdf-palette-item" draggable="true"
|
|
data-field-type="date"
|
|
style="padding: 8px 10px; border: 2px solid #e67e22; border-radius: 5px;
|
|
background: rgba(230,126,34,0.1); cursor: grab; font-size: 13px; font-weight: 600;">
|
|
<i class="fa fa-calendar me-2" style="color: #e67e22;"/>Date Field
|
|
</div>
|
|
|
|
<div class="pdf-palette-item" draggable="true"
|
|
data-field-type="signature"
|
|
style="padding: 8px 10px; border: 2px solid #9b59b6; border-radius: 5px;
|
|
background: rgba(155,89,182,0.1); cursor: grab; font-size: 13px; font-weight: 600;">
|
|
<i class="fa fa-pencil me-2" style="color: #9b59b6;"/>Signature
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Data Keys Reference (collapsible, populated by JS) -->
|
|
<div class="card">
|
|
<div class="card-header py-2" style="cursor: pointer;"
|
|
data-bs-toggle="collapse" data-bs-target="#dataKeysCollapse">
|
|
<h6 class="mb-0">
|
|
<i class="fa fa-key me-1"/>Data Keys
|
|
<i class="fa fa-chevron-down float-end mt-1" style="font-size: 10px;"/>
|
|
</h6>
|
|
</div>
|
|
<div id="dataKeysCollapse" class="collapse">
|
|
<div class="card-body p-2" id="dataKeysList"
|
|
style="max-height: 300px; overflow-y: auto; font-size: 11px;">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- PDF Page Canvas Area -->
|
|
<div class="col-md-7">
|
|
<div class="card">
|
|
<div class="card-body p-0">
|
|
<div id="pdf_canvas_container"
|
|
style="position: relative; width: 100%; overflow: hidden;
|
|
border: 2px solid #dee2e6; background: #f8f9fa;
|
|
min-height: 600px;">
|
|
<!-- PDF page image -->
|
|
<img id="pdf_page_image"
|
|
style="width: 100%; display: block; user-select: none;"
|
|
draggable="false"
|
|
t-att-src="preview_url or ''"
|
|
t-attf-alt="Page #{1}"
|
|
t-if="preview_url"/>
|
|
|
|
<!-- Upload form when no preview exists -->
|
|
<div t-if="not preview_url" class="text-center py-5" id="no_preview_placeholder">
|
|
<div class="mb-3">
|
|
<i class="fa fa-file-image-o fa-3x text-muted"/>
|
|
<p class="text-muted mt-2 mb-1">No page preview image yet.</p>
|
|
<p class="text-muted small">
|
|
Upload a screenshot/photo of the PDF page, or click
|
|
"Generate Page Previews" in the backend form.
|
|
</p>
|
|
</div>
|
|
<form t-attf-action="/fusion/pdf-editor/upload-preview"
|
|
method="post" enctype="multipart/form-data"
|
|
class="d-inline-block">
|
|
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/>
|
|
<input type="hidden" name="template_id" t-att-value="template.id"/>
|
|
<input type="hidden" name="page" value="1"/>
|
|
<div class="input-group" style="max-width: 400px; margin: 0 auto;">
|
|
<input type="file" name="preview_image" class="form-control"
|
|
accept="image/png,image/jpeg,image/jpg" required="required"/>
|
|
<button type="submit" class="btn btn-primary">
|
|
<i class="fa fa-upload me-1"/>Upload
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
|
|
<!-- Field markers rendered by JS -->
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Right Sidebar: Field Properties -->
|
|
<div class="col-md-3">
|
|
<div class="card" id="field_properties_panel">
|
|
<div class="card-header bg-primary text-white py-2">
|
|
<h6 class="mb-0"><i class="fa fa-cog me-1"/>Field Properties</h6>
|
|
</div>
|
|
<div class="card-body" id="field_props_body">
|
|
<p class="text-muted small">Click a field on the PDF to edit its properties.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- JavaScript -->
|
|
<script type="text/javascript" src="/fusion_portal/static/src/js/pdf_field_editor.js"/>
|
|
</t>
|
|
</template>
|
|
|
|
</odoo>
|