Compare commits
35 Commits
46a2c994e5
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 8a4cb3964e | |||
|
|
8b0204a344 | ||
|
|
68a19230ed | ||
|
|
b37aebd4ba | ||
| e072c77c69 | |||
| c6e7e88c06 | |||
| f25040b4d7 | |||
| 4998bb0c85 | |||
| 28597979a7 | |||
|
|
ce15e86252 | ||
|
|
7795ba0703 | ||
| ccaaca4b4e | |||
| ff4dcd2834 | |||
| 423a904d7e | |||
|
|
69dc786cac | ||
|
|
8f64d2abdb | ||
|
|
3817618208 | ||
|
|
f867cac9c1 | ||
|
|
79debe5f46 | ||
|
|
70460b3310 | ||
|
|
e31ab73c05 | ||
|
|
b6e8dca365 | ||
|
|
e9402ecb4a | ||
|
|
6005691b5b | ||
|
|
af738c165b | ||
|
|
e53e6b3906 | ||
|
|
43834e9ee3 | ||
|
|
b44f9f4198 | ||
|
|
2362bc3233 | ||
|
|
86b3164f10 | ||
|
|
8b078ae776 | ||
|
|
e27cf6c10c | ||
|
|
d7ed1f8c00 | ||
|
|
cbde2d65b5 | ||
|
|
330e4c6d8c |
77
README.md
77
README.md
@@ -1,4 +1,6 @@
|
||||
# exportPDF
|
||||
> **Precaución:**
|
||||
> Para instalar en modo desarrollo utilize la rama dev/no_docker
|
||||
|
||||
Funcionalidad para implementar la capacidad de exportar los datos de un recurso a formato PDF.
|
||||
Los modelos de recursos habilitados para la función son los siguientes:
|
||||
@@ -13,7 +15,7 @@ Procedimiento válido para un proyecto en modo desarrollo implementado con un en
|
||||
Para el caso de un enfoque utilizando contenedores o en modo Producción, el proceso varía levemente.
|
||||
|
||||
### 0. Instalar dependencias y librerias de python (servidor Ubuntu)
|
||||
Solo en caso de que su proyecto de arches resida en una implementación según la guía oficial de archesproject
|
||||
Solo en caso de que su proyecto de arches haya sido desplegado según la guía oficial de archesproject si desplegó según las guías del repositorio gitea.patrimonio.org.bo, no necesita instalar las dependencias de ubuntu
|
||||
|
||||
```shell
|
||||
sudo apt install build-essential python3.12-dev python3.12-pip python3.12-setuptools python3.12-wheel python3.12-cffi
|
||||
@@ -24,60 +26,67 @@ y en el entorno de (arches) python:
|
||||
```python
|
||||
pip install django-weasyprint
|
||||
pip install pypdf
|
||||
pip install folium # provisional, se estan evaluando otras librerias como py-staticmaps y selenium
|
||||
```
|
||||
|
||||
### 1. Clonar este repositorio en alguna carpeta de su servidor.
|
||||
|
||||
```shell
|
||||
# puede ser en el home del servidor
|
||||
git clone https://gitea.patrimonio.org.bo/sysadmin/sprpcb-exportpdf-func.git
|
||||
```
|
||||
|
||||
### 2. Agregar la vista personalizada creando (copiando) la carpeta indicada y moviendo la vista adentro:
|
||||
|
||||
### 2. Copiar los archivos necesarios para crear una nueva plantilla de reporte que contendrá los botones necesarios:
|
||||
```shell
|
||||
# en caso de que el repo clonado esté en el home y se encuentra en la 1er carpeta mi_proyecto
|
||||
cp -r ../sprpcb-exportpdf-func/pdf mi_proyecto/pdf # copia la carpeta incluida la vista
|
||||
# o si prefiere crea la carpeta primero y luego copia el contenido
|
||||
cp -r ../sprpcb-exportpdf-func/reportes ./mi_proyecto/reportes
|
||||
cp ../sprpcb-exportpdf-func/templates_views_report-templates/export-pdf-report.htm ./mi_proyecto/templates/views/report-templates/
|
||||
cp ../sprpcb-exportpdf-func/media_js_reports/export-pdf-report.js ./mi_proyecto/media/js/reports/
|
||||
```
|
||||
### 3. Agregar la entrada de ruta en el archivo urls.py del proyecto:
|
||||
|
||||
### 3. Registrar la plantilla personalizada de proyecto que agrega los botones necesarios:
|
||||
```python
|
||||
python manage.py report register -s mi_proyecto/reportes/export-pdf-report.json
|
||||
```
|
||||
|
||||
### 4. Agregar la vista personalizada creando (copiando) las carpetas indicadas y luego los contenidos respectivos:
|
||||
|
||||
```shell
|
||||
# en caso de que el repo clonado esté en el home y desde la 1er carpeta mi_proyecto
|
||||
cp -r ../sprpcb-exportpdf-func/pdf ./mi_proyecto/pdf
|
||||
```
|
||||
|
||||
### 5. Copiar las plantillas pdf correspondientes a los modelos de recursos:
|
||||
```shell
|
||||
cp -r ../sprpcb-exportpdf-func/templates_reports ./mi_proyecto/templates/reports
|
||||
```
|
||||
|
||||
### 6. Agregar una fuente y una entrada de ruta en el archivo urls.py como valor de urlpatterns:
|
||||
|
||||
```shell
|
||||
from .pdf.views import export_resource_pdf
|
||||
#urlpatterns = [
|
||||
# ...
|
||||
urlpatterns = [
|
||||
# ...
|
||||
path('export/pdf/<str:resourceid>/<str:printubic>/<str:printimgs>/<str:printpdfs>/', export_resource_pdf, name='export_resource_pdf'),
|
||||
path('export/pdf/<str:resourceid>/<str:printubic>/<str:satmap>/<str:printimgs>/<str:printpdfs>/', export_resource_pdf, name='export_resource_pdf'),
|
||||
# project-level urls
|
||||
]
|
||||
# ...
|
||||
#]
|
||||
|
||||
```
|
||||
|
||||
### 4. Copiar las plantillas de la funcionalidad correspondientes a los modelos de recursos:
|
||||
```python
|
||||
python manage.py migrate
|
||||
```
|
||||
|
||||
### 5. Copiar los arachivos necesarios para una nueva plantilla de reporte:
|
||||
```python
|
||||
python manage.py migrate
|
||||
```
|
||||
|
||||
### 6. Registrar la plantilla personalizada de proyecto que agrega los botones necesarios:
|
||||
```python
|
||||
python manage.py migrate
|
||||
```
|
||||
|
||||
### 7. A continuación, asegúrese de reconstruir la interfaz de su proyecto para incluir el complemento:
|
||||
### 7. A continuación, asegúrese de reconstruir la interfaz de su proyecto para habilitar los cambios:
|
||||
|
||||
```
|
||||
npm run build_development
|
||||
```
|
||||
|
||||
### 8. Cuando haya terminado, debería ver los botones de exportar en la ventana de vista de reporte de su modelo de recursos:
|
||||

|
||||
### 8. Configuración final
|
||||
Por último, se deben modificar los modelos de recursos para que adopten la nueva plantilla de reporte registrada:
|
||||
|
||||
Cuando haya terminado, debería ver los botones de exportar en la ventana de vista de reporte de su modelo de recursos:
|
||||

|
||||
|
||||
### 9. Forma de uso:
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
El botón "Exportar a PDF", de manera predeterminada, crea el reporte PDF incluyendo casi todos los datos del recurso. Y de manera opcional se pueden incluir 3 características adicionales a través de los botones adyacentes que controlan los siguientes parámetros:
|
||||
* **Incluir ubicación detallada** Se puede incluir datos de ubicación (geo-localización) que podrían estar contraindicados en algunos tipos de recursos.
|
||||
* **Mapa satelital** Si la anterior opción está habilitada, puede cambiar el tipo de mapa de simple a satelital.
|
||||
* **Adjuntar imágenes** Una galería de imágenes distribuida en mosaicos de 2x6 imágenes por hoja a manera de Anexo al informe (existen recursos que tienen más de 20 imágenes relacionadas)
|
||||
* **Adjuntar documentos (pdf)** se ajuntan los documentos relacionados en el mismo archivo pdf del informe
|
||||
|
||||
BIN
captura_exportPDF.jpg
Executable file
BIN
captura_exportPDF.jpg
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
26
copy2proyfolder.sh
Executable file
26
copy2proyfolder.sh
Executable file
@@ -0,0 +1,26 @@
|
||||
#!bin/bash
|
||||
|
||||
#Script demostrativo para copiar del repo clonado a las carpetas de proyecto
|
||||
#Utilize con precaución
|
||||
|
||||
echo -e "\n\t Script para copiar a carpeta de proyecto"
|
||||
read -p "Escribe la carpeta de proyecto ( ejem: ~/mi_proy/miproy ): " destino
|
||||
|
||||
echo $destino
|
||||
if [ ! -d "$destino" ]; then
|
||||
echo "La carpeta de destino no existe. Intente nuevamente!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p $destino/pdf
|
||||
cp ./pdf/views.py $destino/pdf/
|
||||
|
||||
cp ./media_js_reports/export-pdf-report.js $destino/media/js/reports/
|
||||
|
||||
cp -r ./reportes $destino/
|
||||
|
||||
mkdir -p $destino/templates/views/report-templates
|
||||
cp ./templates_views_report-templates/export-pdf-report.htm $destino/templates/views/report-templates/
|
||||
|
||||
mkdir -p $destino/templates/reports
|
||||
cp ./templates_reports/* $destino/templates/reports/
|
||||
37
media_js_reports/export-pdf-report.js
Normal file
37
media_js_reports/export-pdf-report.js
Normal file
@@ -0,0 +1,37 @@
|
||||
define([
|
||||
'knockout',
|
||||
'viewmodels/report',
|
||||
'templates/views/report-templates/export-pdf-report.htm'
|
||||
], function(ko, ReportViewModel, exportPdfReportTemplate) {
|
||||
return ko.components.register('export-pdf-report', {
|
||||
viewModel: function(params) {
|
||||
params.configKeys = [];
|
||||
var self = this;
|
||||
|
||||
ReportViewModel.apply(this, [params]);
|
||||
|
||||
//console.log('Params:', params);
|
||||
this.anexarUbic = ko.observable(false);
|
||||
this.satMap = ko.observable(false);
|
||||
this.anexarImagenes = ko.observable(false);
|
||||
this.anexarPdfs = ko.observable(false);
|
||||
|
||||
const boolToStr = (bool) => bool ? "1" : "0";
|
||||
|
||||
self.resourceId = ko.observable(
|
||||
params.report?.report_json?.resourceinstanceid || null
|
||||
);
|
||||
|
||||
self.exportPDF = function() {
|
||||
var id = self.resourceId();
|
||||
if (id) {
|
||||
var url = '/export/pdf/' + id + '/' + boolToStr(self.anexarUbic()) + '/' + boolToStr(self.satMap()) + '/' + boolToStr(self.anexarImagenes()) + '/' + boolToStr(self.anexarPdfs()) + '/';
|
||||
window.open(url, '_blank');
|
||||
} else {
|
||||
alert('No se encontró el ID del recurso.');
|
||||
}
|
||||
};
|
||||
},
|
||||
template: exportPdfReportTemplate,
|
||||
});
|
||||
});
|
||||
103
pdf/views.py
103
pdf/views.py
@@ -12,9 +12,64 @@ from zoneinfo import ZoneInfo
|
||||
from functools import reduce
|
||||
from operator import getitem
|
||||
from pypdf import PdfReader, PdfWriter
|
||||
from django.conf import settings
|
||||
import boto3
|
||||
import urllib.parse
|
||||
import requests
|
||||
import base64
|
||||
import json
|
||||
import ast
|
||||
|
||||
def static_map_view(geojson_colec, sat_map):
|
||||
|
||||
geojson_dict = ast.literal_eval(geojson_colec)
|
||||
if sat_map:
|
||||
for geo in geojson_dict['features'] :
|
||||
if geo['geometry'].get('type') == 'Polygon':
|
||||
geo['properties'] = {
|
||||
"stroke": "#00ffff",
|
||||
"stroke-width": 2,
|
||||
"stroke-opacity": 0.8,
|
||||
"fill": "#00ffff",
|
||||
"fill-opacity": 0.3
|
||||
}
|
||||
elif geo['geometry'].get('type') == 'Point':
|
||||
geo['properties'] = {
|
||||
"marker-color": "#ff0000",
|
||||
"marker-size": "small"
|
||||
}
|
||||
elif geo['geometry'].get('type') == 'LineString':
|
||||
geo['properties'] = {
|
||||
"stroke": "#0000ff",
|
||||
"stroke-width": 2,
|
||||
"stroke-opacity": 0.8
|
||||
}
|
||||
|
||||
geojson_string = json.dumps(geojson_dict, separators=(',', ':'))
|
||||
encoded_geojson = urllib.parse.quote(geojson_string)
|
||||
|
||||
username = "mapbox"
|
||||
if sat_map:
|
||||
style_id = "satellite-streets-v12" # streets-v12 | outdoors-v11 | satellite-streets-v12
|
||||
else:
|
||||
style_id = "light-v11"
|
||||
|
||||
width, height = 400, 400
|
||||
padding = 100
|
||||
|
||||
# Procedimiento pendiente para extraer el token desde la configuración del sistema
|
||||
access_token = 'pk.eyJ1IjoianNidXJnb3N2IiwiYSI6ImNsaWhoN3ZtMTBxeHUzZm1xaGM0cGpxOXIifQ.ki3vldVB5MwZMqDSpLSjLg'
|
||||
|
||||
mapbox_url = (
|
||||
f"https://api.mapbox.com/styles/v1/{username}/{style_id}/static/"
|
||||
f"geojson({encoded_geojson})/auto/{width}x{height}"
|
||||
f"?padding={padding}&access_token={access_token}"
|
||||
)
|
||||
|
||||
response = requests.get(mapbox_url)
|
||||
|
||||
return base64.b64encode(response.content).decode('utf-8')
|
||||
|
||||
def ajustar_medios(resource_media_rel, medios_list):
|
||||
medios = []
|
||||
img=["image/bmp", "image/gif", "image/jpg", "image/jpeg", "image/png", "image/tif", "image/tiff"]
|
||||
@@ -83,12 +138,13 @@ def strdict_to_dict(strdict):
|
||||
pass
|
||||
return value
|
||||
|
||||
def export_resource_pdf(request, resourceid, printubic, printimgs, printpdfs):
|
||||
def export_resource_pdf(request, resourceid, printubic, satmap, printimgs, printpdfs):
|
||||
resource = Resource.objects.get(pk=resourceid)
|
||||
resource_data = resource.to_json()
|
||||
|
||||
# Corrección de medios relacionados, se normalizan claves y se adicionan propiedades
|
||||
ruta_medios = find_key_path( resource_data, "Medio de información")
|
||||
|
||||
if ruta_medios is not None:
|
||||
valor_medios=reduce(lambda dict_layer, key: dict_layer[key], ruta_medios, resource_data)
|
||||
resource_rel=resource.get_related_resources(user=request.user,resourceinstance_graphid='6afc4e9e-727e-4152-8084-309267752650')
|
||||
@@ -96,6 +152,7 @@ def export_resource_pdf(request, resourceid, printubic, printimgs, printpdfs):
|
||||
reduce(getitem, ruta_medios[:-1], resource_data)[ruta_medios[-1]] = ajustar_medios(resource_rel,valor_medios)
|
||||
|
||||
# Cambio de datos gis en texto a formato json
|
||||
|
||||
ruta_gis = find_key_path( resource_data, "Coordenadas / Geometría")
|
||||
if ruta_gis is not None:
|
||||
valor_gis=reduce(lambda dict_layer, key: dict_layer[key], ruta_gis, resource_data)["@value"]
|
||||
@@ -112,6 +169,12 @@ def export_resource_pdf(request, resourceid, printubic, printimgs, printpdfs):
|
||||
sprpcb_url=request.build_absolute_uri('/')[:-1]
|
||||
fecha=datetime.now(ZoneInfo("America/La_Paz"))
|
||||
|
||||
map_img = None
|
||||
|
||||
if ruta_gis is not None and bool(int(printubic)) :
|
||||
if reduce(getitem, ruta_gis[:-1], resource_data)[ruta_gis[-1]]["@value"] :
|
||||
map_img = static_map_view(reduce(getitem, ruta_gis[:-1], resource_data)[ruta_gis[-1]]["@value"], bool(int(satmap)))
|
||||
|
||||
resources = [{
|
||||
'resourceinstanceid': str(resource.resourceinstanceid),
|
||||
'graph_id': str(resource.graph_id),
|
||||
@@ -120,8 +183,10 @@ def export_resource_pdf(request, resourceid, printubic, printimgs, printpdfs):
|
||||
'sprpcb_url': sprpcb_url,
|
||||
'fecha': fecha,
|
||||
'eta_group': eta_group,
|
||||
'print_ubic': bool(int(printubic)),
|
||||
'print_imgs': bool(int(printimgs)),
|
||||
'print_pdfs': bool(int(printpdfs))
|
||||
'print_pdfs': bool(int(printpdfs)),
|
||||
'map_img': map_img
|
||||
}]
|
||||
|
||||
context = {'resources': resources}
|
||||
@@ -149,18 +214,34 @@ def export_resource_pdf(request, resourceid, printubic, printimgs, printpdfs):
|
||||
merger = PdfWriter()
|
||||
merger.append(PdfReader(io.BytesIO(gen_pdf_file)))
|
||||
|
||||
root_path = Path(__file__).resolve().parent.parent
|
||||
|
||||
if ruta_medios is not None and bool(int(printpdfs)) :
|
||||
for medio in reduce(getitem, ruta_medios[:-1], resource_data)[ruta_medios[-1]] :
|
||||
if medio['formato'] == 'application/pdf' and bool(int(printpdfs)) :
|
||||
merger.append(PdfReader(f'{root_path}/uploadedfiles/{medio["file"]}'))
|
||||
if medio['formato'] == 'application/pdf' :
|
||||
try :
|
||||
minio_bucket=settings.AWS_STORAGE_BUCKET_NAME
|
||||
s3_client = boto3.client('s3',
|
||||
endpoint_url=settings.AWS_S3_ENDPOINT_URL,
|
||||
aws_access_key_id=settings.AWS_ACCESS_KEY_ID,
|
||||
aws_secret_access_key=settings.AWS_SECRET_ACCESS_KEY
|
||||
)
|
||||
pdf_s3_url = s3_client.generate_presigned_url(
|
||||
'get_object',
|
||||
Params={'Bucket': minio_bucket, 'Key': f'uploadedfiles/{medio["file"]}'},
|
||||
ExpiresIn=3600
|
||||
)
|
||||
response_s3 = requests.get(pdf_s3_url, timeout=10)
|
||||
response_s3.raise_for_status()
|
||||
remote_pdf_stream = io.BytesIO(response_s3.content)
|
||||
merger.append(remote_pdf_stream)
|
||||
remote_pdf_stream.close()
|
||||
except requests.RequestException as e:
|
||||
return HttpResponse(f"Error al incluir el archivo PDF: {e}", status=502)
|
||||
|
||||
output_buffer = io.BytesIO()
|
||||
merger.write(output_buffer)
|
||||
output_buffer.seek(0)
|
||||
merger.close()
|
||||
else:
|
||||
output_buffer = io.BytesIO()
|
||||
merger.write(output_buffer)
|
||||
merger.close()
|
||||
response = HttpResponse(output_buffer.getvalue(), content_type='application/pdf')
|
||||
|
||||
response = HttpResponse(output_buffer.read(), content_type='application/pdf')
|
||||
response['Content-Disposition'] = f'attachment; filename="{nombre_pdf}.pdf"'
|
||||
return response
|
||||
@@ -1,183 +0,0 @@
|
||||
{% load i18n %}
|
||||
<!-- ko if: !$data.configForm -->
|
||||
<!-- ko if: !$data.summary -->
|
||||
{% block report %}
|
||||
|
||||
|
||||
{% block report_title_bar %}
|
||||
<!-- Report Title Bar -->
|
||||
<div class="relative report-title-bar">
|
||||
|
||||
<!-- Title Block -->
|
||||
<div class="report-toolbar-preview ep-form-toolbar">
|
||||
<div class="h4 report-toolbar-title"><span data-bind="text: report.get('name')"></span> - <span data-bind="text: report.get('displayname') "></span></div>
|
||||
|
||||
<!-- Tools -->
|
||||
<div class="ep-form-toolbar-tools mar-no flex">
|
||||
<p class="report-print-date">
|
||||
<span data-bind="text: $root.translations.reportDate"></span>
|
||||
<span data-bind="text: reportDate"></span>
|
||||
</p>
|
||||
|
||||
<div
|
||||
class="report-print-date"
|
||||
data-bind="component: {
|
||||
name: 'views/components/simple-switch',
|
||||
params: {
|
||||
value: hideEmptyNodes,
|
||||
config:{ label: $root.translations.hideNullValues, subtitle: ''}
|
||||
}
|
||||
}"
|
||||
></div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock report_title_bar %}
|
||||
|
||||
|
||||
<!-- Report Content -->
|
||||
<div class="rp-report-container-preview">
|
||||
|
||||
{% block header %}
|
||||
{% endblock header %}
|
||||
|
||||
{% block body %}
|
||||
<!--ko if: hasProvisionalData() && (editorContext === false) -->
|
||||
<div class="report-provisional-flag"><span data-bind="text: $root.translations.pendingProvisionalEditsNotDisplayed"></span></div>
|
||||
<!--/ko-->
|
||||
<!--ko if: hasProvisionalData() && (editorContext === true && report.userisreviewer === true) -->
|
||||
<div class="report-provisional-flag"><span data-bind="text: $root.translations.pendingProvisionalEditsNotDisplayed"></span></div>
|
||||
<!--/ko-->
|
||||
<!--ko if: hasProvisionalData() && (editorContext === true && report.userisreviewer === false) -->
|
||||
<div class="report-provisional-flag"><span data-bind="text: $root.translations.pendingProvisionalEdits"></div>
|
||||
<!--/ko-->
|
||||
|
||||
<div class="rp-report-section relative rp-report-section-root">
|
||||
<div class="rp-report-section-title">
|
||||
<!-- ko foreach: { data: report.cards, as: 'card' } -->
|
||||
<!-- ko if: ($parent.hideEmptyNodes() === false || card.tiles().length > 0) && ko.unwrap(card.model.visible) -->
|
||||
<!-- ko if: $index() !== 0 --><hr class="rp-tile-separator"><!-- /ko -->
|
||||
<div class="rp-card-section">
|
||||
<!-- ko component: {
|
||||
name: card.model.cardComponentLookup[card.model.component_id()].componentname,
|
||||
params: {
|
||||
state: 'report',
|
||||
preview: $parent.report.preview,
|
||||
card: card,
|
||||
pageVm: {...$root, report: $parent.report},
|
||||
hideEmptyNodes: $parent.hideEmptyNodes
|
||||
}
|
||||
} --> <!-- /ko -->
|
||||
</div>
|
||||
<!-- /ko -->
|
||||
<!-- /ko -->
|
||||
</div>
|
||||
</div>
|
||||
{% endblock body %}
|
||||
|
||||
|
||||
{% block related_resources %}
|
||||
<div class="rp-report-section relative report-related-resources">
|
||||
<div class="rp-report-section-title">
|
||||
<div class="h4 rp-section-title"><span data-bind="text: $root.translations.relatedResources"></span></div>
|
||||
</div>
|
||||
|
||||
<!-- ko foreach: { data: Object.values(report.relatedResourcesLookup()), as: 'resourceData' } -->
|
||||
<!-- ko if: resourceData.totalRelatedResources > 0 || !$parent.hideEmptyNodes() -->
|
||||
<div class="h5 rp-tile-title">
|
||||
<span class="rp-tile-title-float" data-bind="text: resourceData.name"></span>
|
||||
</div>
|
||||
|
||||
<div class="rp-card-section">
|
||||
<!-- ko foreach: { data: resourceData.loadedRelatedResources(), as: 'relatedResource' } -->
|
||||
<div class="rp-report-container-tile">
|
||||
<div class="row rp-report-tile">
|
||||
<dl class="dl-horizontal">
|
||||
<dt><a data-bind="text: relatedResource.displayName, attr: {href: relatedResource.link}"></a></dt>
|
||||
<!-- ko if: relatedResource.relationship -->
|
||||
<dd data-bind="text: '( ' + relatedResource.relationship + ' )'"></dd>
|
||||
<!-- /ko -->
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /ko -->
|
||||
|
||||
<!-- ko if: resourceData.paginator() && resourceData.paginator().has_next -->
|
||||
<button class="btn btn-primary" data-bind="click: $parent.report.getRelatedResources.bind($parent.report, false)">
|
||||
<span data-bind="text: $root.translations.loadMore" ></span>
|
||||
<span data-bind="text: '(' + resourceData.remainingResources() + ')'"></span>
|
||||
</button>
|
||||
|
||||
<button class="btn btn-primary" data-bind="click: $parent.report.getRelatedResources.bind($parent.report, true)">
|
||||
<span data-bind="text: $root.translations.loadAll" ></span>
|
||||
<span data-bind="text: '(' + (resourceData.totalRelatedResources - resourceData.loadedRelatedResources().length) + ')'"></span>
|
||||
</button>
|
||||
<!-- /ko -->
|
||||
|
||||
<!--ko if: resourceData.totalRelatedResources === 0 -->
|
||||
<div class="rp-report-container-tile">
|
||||
<div class="row rp-report-tile rp-no-data"><span data-bind="text: $root.translations.noRelationshipsAdded"></span></div>
|
||||
</div>
|
||||
<!--/ko-->
|
||||
</div>
|
||||
<!-- /ko -->
|
||||
<!-- /ko -->
|
||||
</div>
|
||||
{% endblock related_resources %}
|
||||
|
||||
{% block footer %}
|
||||
{% endblock footer %}
|
||||
</div>
|
||||
{% endblock report %}
|
||||
<!-- /ko -->
|
||||
|
||||
<!-- ko if: $data.summary -->
|
||||
{% block summary %}
|
||||
<div class="relative report-title-bar">
|
||||
|
||||
<!-- Title Block -->
|
||||
<div class="report-toolbar-preview ep-form-toolbar">
|
||||
<h4 class="report-toolbar-title"><span data-bind="text: report.get('name')"></span> - <span data-bind="text: report.get('displayname') "></span></h4>
|
||||
|
||||
<!-- Tools -->
|
||||
<div class="ep-form-toolbar-tools mar-no flex">
|
||||
<p class="report-print-date">
|
||||
<span data-bind="text: $root.translations.reportDate"></span>
|
||||
<span data-bind="text: reportDate"></span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="rp-report-container-preview">
|
||||
<div class="rp-report-section relative rp-report-section-root">
|
||||
<div class="rp-report-section-title">
|
||||
<!-- ko if: report.cards.length > 0 -->
|
||||
<!--ko let: { card: report.cards[0] }-->
|
||||
<div class="rp-card-section">
|
||||
<!-- ko component: {
|
||||
name: card.model.cardComponentLookup[card.model.component_id()].componentname,
|
||||
params: {
|
||||
state: 'report',
|
||||
preview: report.preview,
|
||||
card: card,
|
||||
pageVm: $root
|
||||
}
|
||||
} --> <!-- /ko -->
|
||||
</div>
|
||||
<!--/ko-->
|
||||
<!-- /ko -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock summary %}
|
||||
<!-- /ko -->
|
||||
<!-- end of not configForm -->
|
||||
<!-- /ko -->
|
||||
|
||||
|
||||
<!-- ko if: $data.configForm && ($data.configType === 'header') -->
|
||||
{% block header_form %}
|
||||
{% endblock header_form %}
|
||||
<!-- /ko -->
|
||||
8
reportes/export-pdf-report.json
Normal file
8
reportes/export-pdf-report.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "Reporte a pdf",
|
||||
"componentid": "5b76b2f1-e7be-4407-82dc-da3b1ede6b78",
|
||||
"component": "reports/export-pdf-report",
|
||||
"componentname": "export-pdf-report",
|
||||
"description": "Reporte personalizado para agregar función de exportar a PDF.",
|
||||
"defaultconfig": {}
|
||||
}
|
||||
@@ -16,14 +16,15 @@
|
||||
h3 { font-size: 12pt;}
|
||||
h4 { font-size: 11pt;}
|
||||
|
||||
.tiles-grid-grp { display: grid; grid-template-columns: 3fr 2fr; grid-template-rows: auto auto; gap: 2px;}
|
||||
.tiles-grid-grp { display: grid; grid-template-columns: 1fr 1fr; grid-template-rows: auto auto; gap: 2px;}
|
||||
.tiles-grid-grp-col { grid-column: 2; grid-row: 1 / span 2; }
|
||||
.tile-block { border: 1px solid var(--ceniza); border-radius: 4px; padding: 2px; margin: 2px 0; background-color: var(--claro);}
|
||||
.tile-title { font-size: 11pt; font-weight: bold; color: var(--oscuro); border-bottom: 1px solid var(--ceniza); padding-bottom: 2px; margin-bottom: 5px;}
|
||||
.data-row { display: flex; padding: 2px 0; border-bottom: 1px solid var(--claro);}
|
||||
.data-label { font-weight: 600; letter-spacing: -0.05em; width: 40%; color: var(--oscuro);}
|
||||
.data-value { width: 40%; letter-spacing: -0.05em; word-wrap: break-word;}
|
||||
.data-value { width: 60%; font-size:.9em; word-wrap: break-word;}
|
||||
.no-data { color: var(--ceniza); font-style: italic;}
|
||||
.tiles-grid-grp-col .tile-block img { object-fit: cover; width: 330px; max-height: 230px;}
|
||||
|
||||
@page {
|
||||
@top-left { background: var(--resaltado); content: counter(page); height: 1cm; text-align: center; width: 1cm;}
|
||||
@@ -117,7 +118,7 @@
|
||||
{% with gis_vector=resource_data|val_from_key:"Ubicación simple"|val_from_key:"Coordenadas / Geometría"|val_from_key:"@value"|json_to_obj %}
|
||||
{% for gis in gis_vector.features %}
|
||||
<div class="data-row">
|
||||
<span class="data-value" style="width: 100%;">{{ gis.geometry }}</span>
|
||||
<span class="data-value" style="width: 100%; font-size: .72em;">{{ gis.geometry|truncatewords:24 }}</span>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endwith %}
|
||||
@@ -131,6 +132,7 @@
|
||||
<div class="tiles-grid-grp-col">
|
||||
<div class="tile-block">
|
||||
<div class="data-label">Mapa de referencia</div>
|
||||
<img src="data:image/png;base64,{{ resource.map_img }}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
.rtable{margin:0 0 0 30px;table-layout: fixed;width:95%;display:table; border:1px solid var(--ceniza)}
|
||||
.rrow{display:table-row; flex-direction:row }
|
||||
.rcol-larga{width: auto;}.rcol-media{width: 25%;}.rcol-corta{width: 10%;}
|
||||
.rcol-larga{width: auto;}.rcol-media{width: 22%;}.rcol-corta{width: 10%;}
|
||||
.rcell{padding:3px 6px;display:table-cell;border:1px solid var(--ceniza)}
|
||||
.rrow.rheader{ background-color: solid var(--ceniza); border:1px solid var(--ceniza)}
|
||||
.rrow.rheader .rcell{font-weight:600; border-bottom: 1px solid var(--ceniza);}
|
||||
@@ -162,7 +162,7 @@
|
||||
{% with gis_vector=resource_data|val_from_key:"Ubicación BIM"|val_from_key:"Coordenadas / Geometría"|val_from_key:"@value"|json_to_obj %}
|
||||
{% for gis in gis_vector.features %}
|
||||
<div class="data-row">
|
||||
<span class="data-value" style="width: 100%;">{{ gis.geometry }}</span>
|
||||
<span class="data-value" style="width: 100%; font-size: .72em;">{{ gis.geometry|truncatewords:24 }}</span>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endwith %}
|
||||
@@ -175,6 +175,7 @@
|
||||
<div class="tiles-grid-grp-col">
|
||||
<div class="tile-block">
|
||||
<div class="tile-title">Mapa de referencia</div>
|
||||
<img src="data:image/png;base64,{{ resource.map_img }}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -417,13 +418,11 @@
|
||||
<div class="tile-block">
|
||||
<div class="tile-title">Medios adjuntos</div>
|
||||
{% if resource_data|has_key:"Recursos" %}
|
||||
<div class="flex-container">
|
||||
<div class="tiles-grid-grp">
|
||||
{% for medio in resource_data|val_from_key:'Recursos'|val_from_key:'Medio de información' %}
|
||||
<div class="flex-item">
|
||||
<div class="data-row" style="margin-left: 15px;">
|
||||
<div class="data-row" style="margin-left: 15px; padding: 0;">
|
||||
<a href={{resource.sprpcb_url}}{{ medio.url }} >{{ medio.tipo }} : {{ medio|val_from_key:'@value' }} ({{ medio.formato|slice:"-4:" }})</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
@@ -152,6 +152,7 @@
|
||||
<span class="data-label">Espacio: </span>
|
||||
<span class="data-value">{{ resource_data|val_from_key:"Localización"|val_from_key:"Espacio" }}</span>
|
||||
</div>
|
||||
{% if resource.print_ubic %}
|
||||
<div class="data-row">
|
||||
<span class="data-label">Inmueble: </span>
|
||||
<span class="data-value">{{ resource_data|val_from_key:"Localización"|val_from_key:"Inmueble" }}</span>
|
||||
@@ -160,7 +161,8 @@
|
||||
<span class="data-label">Colección: </span>
|
||||
<span class="data-value">{{ resource_data|val_from_key:"Localización"|val_from_key:"Colección" }}</span>
|
||||
</div>
|
||||
{% if resource_data|val_from_key:"Localización"|has_key:"Ubicación" %}
|
||||
{% endif %}
|
||||
{% if resource_data|val_from_key:"Localización"|has_key:"Ubicación" and resource.print_ubic %}
|
||||
<div class="data-row" style="margin-left: 15px;">
|
||||
<span class="data-value" style="width: 100%;"><b>Ambiente : </b> {{resource_data|val_from_key:"Localización"|val_from_key:"Ubicación"|val_from_key:"Ambiente" }}</span>
|
||||
</div>
|
||||
@@ -180,11 +182,11 @@
|
||||
<div class="data-row">
|
||||
<span class="data-label" style="width: 100%;">Coordenadas / Geometría: </span>
|
||||
</div>
|
||||
{% if resource_data|val_from_key:"Localización"|has_key:"Coordenadas / Geometría" %}
|
||||
{% if resource_data|val_from_key:"Localización"|has_key:"Coordenadas / Geometría" and resource.print_ubic %}
|
||||
{% with gis_vector=resource_data|val_from_key:"Localización"|val_from_key:"Coordenadas / Geometría"|val_from_key:"@value"|json_to_obj %}
|
||||
{% for gis in gis_vector.features %}
|
||||
<div class="data-row">
|
||||
<span class="data-value" style="width: 100%;">{{ gis.geometry }}</span>
|
||||
<span class="data-value" style="width: 100%; font-size: .72em;">{{ gis.geometry|truncatewords:24 }}</span>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endwith %}
|
||||
@@ -197,6 +199,7 @@
|
||||
<div class="tiles-grid-grp-col">
|
||||
<div class="tile-block">
|
||||
<div class="tile-title">Mapa de referencia</div>
|
||||
<img src="data:image/png;base64,{{ resource.map_img }}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -309,13 +312,11 @@
|
||||
<div class="tile-block">
|
||||
<div class="tile-title">Medios adjuntos</div>
|
||||
{% if resource_data|has_key:"Recursos adjuntos" %}
|
||||
<div class="flex-container">
|
||||
<div class="tiles-grid-grp">
|
||||
{% for medio in resource_data|val_from_key:'Recursos adjuntos'|val_from_key:'Medio de información' %}
|
||||
<div class="flex-item">
|
||||
<div class="data-row" style="margin-left: 15px;">
|
||||
<div class="data-row" style="margin-left: 15px; padding: 0;">
|
||||
<a href={{resource.sprpcb_url}}{{ medio.url }} >{{ medio.tipo }} : {{ medio|val_from_key:'@value' }} ({{ medio.formato|slice:"-4:" }})</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
@@ -126,7 +126,7 @@
|
||||
{% with gis_vector=resource_data|val_from_key:"Ubicación 2"|val_from_key:"Coordenadas / Geometría"|val_from_key:"@value"|json_to_obj %}
|
||||
{% for gis in gis_vector.features %}
|
||||
<div class="data-row">
|
||||
<span class="data-value" style="width: 100%;">{{ gis.geometry }}</span>
|
||||
<span class="data-value" style="width: 100%; font-size: .72em;">{{ gis.geometry|truncatewords:24 }}</span>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endwith %}
|
||||
@@ -140,6 +140,7 @@
|
||||
<div class="tiles-grid-grp-col">
|
||||
<div class="tile-block">
|
||||
<div class="tile-title">Mapa de referencia</div>
|
||||
<img src="data:image/png;base64,{{ resource.map_img }}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -252,13 +253,11 @@
|
||||
<div class="tile-block">
|
||||
<div class="tile-title">Medios adjuntos</div>
|
||||
{% if resource_data|has_key:"Información gráfica" %}
|
||||
<div class="flex-container">
|
||||
<div class="tiles-grid-grp">
|
||||
{% for medio in resource_data|val_from_key:'Información gráfica'|val_from_key:'Medio de información' %}
|
||||
<div class="flex-item">
|
||||
<div class="data-row" style="margin-left: 15px;">
|
||||
<div class="data-row" style="margin-left: 15px; padding: 0;">
|
||||
<a href={{resource.sprpcb_url}}{{ medio.url }} >{{ medio.tipo }} : {{ medio|val_from_key:'@value' }} ({{ medio.formato|slice:"-4:" }})</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
@@ -15,11 +15,15 @@
|
||||
</div>
|
||||
<div class="report-print-date" data-bind="component: {
|
||||
name: 'views/components/simple-switch',
|
||||
params: { value: anexarImagenes, config:{ label: 'Incluir imágenes adjuntas'}}}">
|
||||
params: { value: satMap, config:{ label: 'Mapa satelital'}}}">
|
||||
</div>
|
||||
<div class="report-print-date" data-bind="component: {
|
||||
name: 'views/components/simple-switch',
|
||||
params: { value: anexarPdfs, config:{ label: 'Incluir documentos (pdf) adjuntos'}}}">
|
||||
params: { value: anexarImagenes, config:{ label: 'Adjuntar imágenes'}}}">
|
||||
</div>
|
||||
<div class="report-print-date" data-bind="component: {
|
||||
name: 'views/components/simple-switch',
|
||||
params: { value: anexarPdfs, config:{ label: 'Adjuntar documentos (pdf)'}}}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user