feat: Major updates to backend structure and security enhancements
- Removed `COMMON_ERRORS.md` file to streamline documentation. - Added `Flask-Limiter` for rate limiting and `redis` for session management in `requirements.txt`. - Expanded `ROADMAP.md` to include completed security features and planned enhancements for version 2.2. - Enhanced `setup_myp.sh` for ultra-secure kiosk installation, including system hardening and security configurations. - Updated `app.py` to integrate CSRF protection and improved logging setup. - Refactored user model to include username and active status for better user management. - Improved job scheduler with uptime tracking and task management features. - Updated various templates for a more cohesive user interface and experience.
This commit is contained in:
431
backend/app/static/js/charts/chart-config.js
Normal file
431
backend/app/static/js/charts/chart-config.js
Normal file
@@ -0,0 +1,431 @@
|
||||
/**
|
||||
* MYP Platform Chart-Konfigurationen
|
||||
* Basierend auf ApexCharts Bibliothek
|
||||
* Version: 1.0.0
|
||||
*/
|
||||
|
||||
// Standard Farben für Diagramme
|
||||
const MYP_CHART_COLORS = {
|
||||
primary: '#3b82f6', // Blau
|
||||
secondary: '#8b5cf6', // Lila
|
||||
success: '#10b981', // Grün
|
||||
warning: '#f59e0b', // Orange
|
||||
danger: '#ef4444', // Rot
|
||||
info: '#06b6d4', // Türkis
|
||||
gray: '#6b7280', // Grau
|
||||
gradient: {
|
||||
blue: ['#3b82f6', '#93c5fd'],
|
||||
purple: ['#8b5cf6', '#c4b5fd'],
|
||||
green: ['#10b981', '#6ee7b7'],
|
||||
red: ['#ef4444', '#fca5a5'],
|
||||
orange: ['#f59e0b', '#fcd34d'],
|
||||
}
|
||||
};
|
||||
|
||||
// Gemeinsame Grundeinstellungen für alle Diagramme
|
||||
const getBaseChartOptions = () => {
|
||||
return {
|
||||
chart: {
|
||||
fontFamily: 'Inter, sans-serif',
|
||||
toolbar: {
|
||||
show: false
|
||||
},
|
||||
zoom: {
|
||||
enabled: false
|
||||
},
|
||||
animations: {
|
||||
enabled: true,
|
||||
easing: 'easeinout',
|
||||
speed: 800,
|
||||
animateGradually: {
|
||||
enabled: true,
|
||||
delay: 150
|
||||
},
|
||||
dynamicAnimation: {
|
||||
enabled: true,
|
||||
speed: 350
|
||||
}
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
enabled: true,
|
||||
theme: 'dark',
|
||||
style: {
|
||||
fontSize: '12px',
|
||||
fontFamily: 'Inter, sans-serif'
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
show: true,
|
||||
borderColor: '#334155',
|
||||
strokeDashArray: 4,
|
||||
position: 'back',
|
||||
xaxis: {
|
||||
lines: {
|
||||
show: false
|
||||
}
|
||||
},
|
||||
yaxis: {
|
||||
lines: {
|
||||
show: true
|
||||
}
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
position: 'bottom',
|
||||
horizontalAlign: 'center',
|
||||
offsetY: 8,
|
||||
fontSize: '14px',
|
||||
fontFamily: 'Inter, sans-serif',
|
||||
markers: {
|
||||
width: 10,
|
||||
height: 10,
|
||||
strokeWidth: 0,
|
||||
radius: 4
|
||||
},
|
||||
itemMargin: {
|
||||
horizontal: 10,
|
||||
vertical: 0
|
||||
}
|
||||
},
|
||||
stroke: {
|
||||
curve: 'smooth',
|
||||
width: 3
|
||||
},
|
||||
xaxis: {
|
||||
labels: {
|
||||
style: {
|
||||
fontSize: '12px',
|
||||
fontFamily: 'Inter, sans-serif',
|
||||
colors: '#94a3b8'
|
||||
}
|
||||
},
|
||||
axisBorder: {
|
||||
show: false
|
||||
},
|
||||
axisTicks: {
|
||||
show: false
|
||||
}
|
||||
},
|
||||
yaxis: {
|
||||
labels: {
|
||||
style: {
|
||||
fontSize: '12px',
|
||||
fontFamily: 'Inter, sans-serif',
|
||||
colors: '#94a3b8'
|
||||
}
|
||||
}
|
||||
},
|
||||
dataLabels: {
|
||||
enabled: false
|
||||
},
|
||||
responsive: [
|
||||
{
|
||||
breakpoint: 768,
|
||||
options: {
|
||||
chart: {
|
||||
height: '300px'
|
||||
},
|
||||
legend: {
|
||||
position: 'bottom',
|
||||
offsetY: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Liniendiagramm Konfiguration
|
||||
* @param {Array} series - Datenreihen
|
||||
* @param {Array} categories - X-Achsen Kategorien
|
||||
* @param {Object} customOptions - Benutzerdefinierte Optionen
|
||||
* @returns {Object} Konfigurationsobjekt für ApexCharts
|
||||
*/
|
||||
function getLineChartConfig(series, categories, customOptions = {}) {
|
||||
const baseOptions = getBaseChartOptions();
|
||||
|
||||
const defaultOptions = {
|
||||
chart: {
|
||||
...baseOptions.chart,
|
||||
type: 'line',
|
||||
height: 350
|
||||
},
|
||||
colors: [
|
||||
MYP_CHART_COLORS.primary,
|
||||
MYP_CHART_COLORS.secondary,
|
||||
MYP_CHART_COLORS.success
|
||||
],
|
||||
series: series || [],
|
||||
xaxis: {
|
||||
...baseOptions.xaxis,
|
||||
categories: categories || []
|
||||
}
|
||||
};
|
||||
|
||||
// Optionen zusammenführen
|
||||
return mergeDeep(mergeDeep({}, baseOptions), mergeDeep(defaultOptions, customOptions));
|
||||
}
|
||||
|
||||
/**
|
||||
* Flächendiagramm Konfiguration
|
||||
* @param {Array} series - Datenreihen
|
||||
* @param {Array} categories - X-Achsen Kategorien
|
||||
* @param {Object} customOptions - Benutzerdefinierte Optionen
|
||||
* @returns {Object} Konfigurationsobjekt für ApexCharts
|
||||
*/
|
||||
function getAreaChartConfig(series, categories, customOptions = {}) {
|
||||
const baseOptions = getBaseChartOptions();
|
||||
|
||||
const defaultOptions = {
|
||||
chart: {
|
||||
...baseOptions.chart,
|
||||
type: 'area',
|
||||
height: 350
|
||||
},
|
||||
colors: [
|
||||
MYP_CHART_COLORS.primary,
|
||||
MYP_CHART_COLORS.success
|
||||
],
|
||||
series: series || [],
|
||||
xaxis: {
|
||||
...baseOptions.xaxis,
|
||||
categories: categories || []
|
||||
},
|
||||
fill: {
|
||||
type: 'gradient',
|
||||
gradient: {
|
||||
shadeIntensity: 1,
|
||||
opacityFrom: 0.7,
|
||||
opacityTo: 0.3,
|
||||
stops: [0, 90, 100]
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Optionen zusammenführen
|
||||
return mergeDeep(mergeDeep({}, baseOptions), mergeDeep(defaultOptions, customOptions));
|
||||
}
|
||||
|
||||
/**
|
||||
* Balkendiagramm Konfiguration
|
||||
* @param {Array} series - Datenreihen
|
||||
* @param {Array} categories - X-Achsen Kategorien
|
||||
* @param {Object} customOptions - Benutzerdefinierte Optionen
|
||||
* @returns {Object} Konfigurationsobjekt für ApexCharts
|
||||
*/
|
||||
function getBarChartConfig(series, categories, customOptions = {}) {
|
||||
const baseOptions = getBaseChartOptions();
|
||||
|
||||
const defaultOptions = {
|
||||
chart: {
|
||||
...baseOptions.chart,
|
||||
type: 'bar',
|
||||
height: 350
|
||||
},
|
||||
colors: [
|
||||
MYP_CHART_COLORS.primary,
|
||||
MYP_CHART_COLORS.secondary
|
||||
],
|
||||
series: series || [],
|
||||
xaxis: {
|
||||
...baseOptions.xaxis,
|
||||
categories: categories || []
|
||||
},
|
||||
plotOptions: {
|
||||
bar: {
|
||||
horizontal: false,
|
||||
columnWidth: '70%',
|
||||
borderRadius: 6,
|
||||
dataLabels: {
|
||||
position: 'top'
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Optionen zusammenführen
|
||||
return mergeDeep(mergeDeep({}, baseOptions), mergeDeep(defaultOptions, customOptions));
|
||||
}
|
||||
|
||||
/**
|
||||
* Kreisdiagramm Konfiguration
|
||||
* @param {Array} series - Datenreihen (Werte)
|
||||
* @param {Array} labels - Beschriftungen
|
||||
* @param {Object} customOptions - Benutzerdefinierte Optionen
|
||||
* @returns {Object} Konfigurationsobjekt für ApexCharts
|
||||
*/
|
||||
function getPieChartConfig(series, labels, customOptions = {}) {
|
||||
const baseOptions = getBaseChartOptions();
|
||||
|
||||
const defaultOptions = {
|
||||
chart: {
|
||||
...baseOptions.chart,
|
||||
type: 'pie',
|
||||
height: 350
|
||||
},
|
||||
colors: [
|
||||
MYP_CHART_COLORS.primary,
|
||||
MYP_CHART_COLORS.success,
|
||||
MYP_CHART_COLORS.warning,
|
||||
MYP_CHART_COLORS.danger,
|
||||
MYP_CHART_COLORS.info
|
||||
],
|
||||
series: series || [],
|
||||
labels: labels || [],
|
||||
legend: {
|
||||
position: 'bottom'
|
||||
},
|
||||
responsive: [
|
||||
{
|
||||
breakpoint: 480,
|
||||
options: {
|
||||
chart: {
|
||||
width: 300
|
||||
},
|
||||
legend: {
|
||||
position: 'bottom'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
// Optionen zusammenführen
|
||||
return mergeDeep(mergeDeep({}, baseOptions), mergeDeep(defaultOptions, customOptions));
|
||||
}
|
||||
|
||||
/**
|
||||
* Donut-Diagramm Konfiguration
|
||||
* @param {Array} series - Datenreihen (Werte)
|
||||
* @param {Array} labels - Beschriftungen
|
||||
* @param {Object} customOptions - Benutzerdefinierte Optionen
|
||||
* @returns {Object} Konfigurationsobjekt für ApexCharts
|
||||
*/
|
||||
function getDonutChartConfig(series, labels, customOptions = {}) {
|
||||
const baseOptions = getBaseChartOptions();
|
||||
|
||||
const defaultOptions = {
|
||||
chart: {
|
||||
...baseOptions.chart,
|
||||
type: 'donut',
|
||||
height: 350
|
||||
},
|
||||
colors: [
|
||||
MYP_CHART_COLORS.primary,
|
||||
MYP_CHART_COLORS.success,
|
||||
MYP_CHART_COLORS.warning,
|
||||
MYP_CHART_COLORS.danger,
|
||||
MYP_CHART_COLORS.info
|
||||
],
|
||||
series: series || [],
|
||||
labels: labels || [],
|
||||
legend: {
|
||||
position: 'bottom'
|
||||
},
|
||||
plotOptions: {
|
||||
pie: {
|
||||
donut: {
|
||||
size: '70%',
|
||||
labels: {
|
||||
show: true,
|
||||
name: {
|
||||
show: true
|
||||
},
|
||||
value: {
|
||||
show: true,
|
||||
formatter: function(val) {
|
||||
return val;
|
||||
}
|
||||
},
|
||||
total: {
|
||||
show: true,
|
||||
formatter: function(w) {
|
||||
return w.globals.seriesTotals.reduce((a, b) => a + b, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Optionen zusammenführen
|
||||
return mergeDeep(mergeDeep({}, baseOptions), mergeDeep(defaultOptions, customOptions));
|
||||
}
|
||||
|
||||
/**
|
||||
* Radial-Diagramm Konfiguration
|
||||
* @param {Array} series - Datenreihen (Werte)
|
||||
* @param {Array} labels - Beschriftungen
|
||||
* @param {Object} customOptions - Benutzerdefinierte Optionen
|
||||
* @returns {Object} Konfigurationsobjekt für ApexCharts
|
||||
*/
|
||||
function getRadialChartConfig(series, labels, customOptions = {}) {
|
||||
const baseOptions = getBaseChartOptions();
|
||||
|
||||
const defaultOptions = {
|
||||
chart: {
|
||||
...baseOptions.chart,
|
||||
type: 'radialBar',
|
||||
height: 350
|
||||
},
|
||||
colors: [
|
||||
MYP_CHART_COLORS.primary,
|
||||
MYP_CHART_COLORS.success,
|
||||
MYP_CHART_COLORS.warning
|
||||
],
|
||||
series: series || [],
|
||||
labels: labels || [],
|
||||
plotOptions: {
|
||||
radialBar: {
|
||||
dataLabels: {
|
||||
name: {
|
||||
fontSize: '22px',
|
||||
},
|
||||
value: {
|
||||
fontSize: '16px',
|
||||
},
|
||||
total: {
|
||||
show: true,
|
||||
label: 'Gesamt',
|
||||
formatter: function(w) {
|
||||
return w.globals.seriesTotals.reduce((a, b) => a + b, 0) + '%';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Optionen zusammenführen
|
||||
return mergeDeep(mergeDeep({}, baseOptions), mergeDeep(defaultOptions, customOptions));
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper-Funktion zum tiefen Zusammenführen von Objekten
|
||||
*/
|
||||
function mergeDeep(target, source) {
|
||||
const isObject = obj => obj && typeof obj === 'object';
|
||||
|
||||
if (!isObject(target) || !isObject(source)) {
|
||||
return source;
|
||||
}
|
||||
|
||||
const output = { ...target };
|
||||
|
||||
Object.keys(source).forEach(key => {
|
||||
if (isObject(source[key])) {
|
||||
if (!(key in target)) {
|
||||
output[key] = source[key];
|
||||
} else {
|
||||
output[key] = mergeDeep(target[key], source[key]);
|
||||
}
|
||||
} else {
|
||||
output[key] = source[key];
|
||||
}
|
||||
});
|
||||
|
||||
return output;
|
||||
}
|
Reference in New Issue
Block a user