added docker-compose for linux

This commit is contained in:
2026-02-21 19:53:04 +02:00
parent be91231b05
commit 58b1ae9a5e
23 changed files with 761 additions and 16 deletions
@@ -8,6 +8,30 @@ import { useElementSelection } from './hooks/useElementSelection';
import { getElementStyle, isTextMultiLine, getTextWhiteSpace } from './utils/elementUtils';
import './elements.css';
function formatValue(raw, dataType) {
if (raw === '' || raw === null || raw === undefined) return '';
switch (dataType) {
case 'number': {
const n = Number(raw);
return isNaN(n) ? '' : String(n);
}
case 'date': {
const d = new Date(raw);
return isNaN(d.getTime()) ? '' : d.toLocaleDateString();
}
case 'time': {
const d = new Date(raw);
return isNaN(d.getTime()) ? '' : d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
}
case 'datetime': {
const d = new Date(raw);
return isNaN(d.getTime()) ? '' : d.toLocaleDateString() + ' ' + d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
}
default:
return String(raw);
}
}
function DBTextField({
element,
isSelected,
@@ -51,12 +75,16 @@ function DBTextField({
};
// Resolve data value
const displayContent = previewMode
const rawValue = previewMode
? resolveDBTextValue(reportData, element.objectKey, element.fieldPath, parentBandId, { currentBandData })
: parentBandId
? `{${element.fieldPath}}` // Inside band: show field only
: `{${element.objectKey}.${element.fieldPath}}`; // Outside band: show object.field
const displayContent = previewMode
? formatValue(rawValue, element.dataType || 'general')
: rawValue;
// Check if data is resolved
// If inside a band, only fieldPath is required; otherwise both objectKey and fieldPath are required
const isUnresolved = parentBandId
@@ -71,7 +99,8 @@ function DBTextField({
...getElementStyle(element, charWidth, charHeight),
minWidth: `${charWidth}px`,
minHeight: `${charHeight}px`,
whiteSpace
whiteSpace,
textAlign: element.alignment || 'left',
};
return (
@@ -237,6 +237,32 @@ function ObjectInspector({ element, onUpdate, allElements = [] }) {
</div>
</>
)}
<div className="property-row">
<label>Data Type:</label>
<select
value={element.dataType || 'general'}
onChange={(e) => handleChange('dataType', e.target.value)}
>
<option value="general">General</option>
<option value="number">Number</option>
<option value="date">Date</option>
<option value="time">Time</option>
<option value="datetime">Date &amp; Time</option>
</select>
</div>
<div className="property-row">
<label>Alignment:</label>
<select
value={element.alignment || 'left'}
onChange={(e) => handleChange('alignment', e.target.value)}
>
<option value="left">Left</option>
<option value="center">Center</option>
<option value="right">Right</option>
</select>
</div>
</div>
)}
@@ -1,5 +1,6 @@
import React, { useState, useEffect } from 'react';
import { DataProvider } from './DataContext';
import { useLocation } from 'react-router-dom';
import { DataProvider, useReportData } from './DataContext';
import { BandProvider } from './BandContext';
import Toolbar from './Toolbar';
import EditorCanvas from './EditorCanvas';
@@ -33,6 +34,38 @@ function ReportEditorContent() {
const [savedReports, setSavedReports] = useState([]);
const [loadingReports, setLoadingReports] = useState(false);
// Auto-load report and vehicle data passed via router state
const location = useLocation();
const { setData } = useReportData();
useEffect(() => {
const { reportName, vehicleData } = location.state || {};
if (!reportName) return;
api.get('/api/reports/').then(res => {
const reports = res.data.results || res.data;
const found = reports.find(r => r.name === reportName);
if (found) {
setReport({
name: found.name,
pageWidth: found.page_width,
pageHeight: found.page_height,
apiEndpoint: found.api_endpoint || '',
elements: found.elements || [],
});
setReportId(found.id);
} else {
// Report doesn't exist yet — pre-fill the name so Save creates it
setReport(prev => ({ ...prev, name: reportName }));
}
if (vehicleData) {
setData(vehicleData);
}
}).catch(err => {
console.error('Failed to auto-load report:', err);
});
}, []);
const handleAddElement = (element) => {
setReport(prev => {
// Check if the new element is positioned inside a band
@@ -113,12 +113,14 @@ export class Element {
* Database-bound text field element
*/
export class DBTextElement extends Element {
constructor({ id, x, y, width = 10, height = 1, objectKey = '', fieldPath = '' }) {
constructor({ id, x, y, width = 10, height = 1, objectKey = '', fieldPath = '', dataType = 'general', alignment = 'left' }) {
super({ id, type: 'dbtext', x, y });
this.width = width;
this.height = height;
this.objectKey = objectKey;
this.fieldPath = fieldPath;
this.dataType = dataType;
this.alignment = alignment;
}
getBounds() {
@@ -148,7 +150,9 @@ export class DBTextElement extends Element {
width: this.width,
height: this.height,
objectKey: this.objectKey,
fieldPath: this.fieldPath
fieldPath: this.fieldPath,
dataType: this.dataType,
alignment: this.alignment
};
}
}