Moving away from Azure Devops #1

Merged
Janus007 merged 113 commits from refac into master 2026-02-03 00:04:27 +01:00
4 changed files with 156 additions and 5 deletions
Showing only changes of commit 6c3662f571 - Show all commits

8
package-lock.json generated
View file

@ -10,7 +10,7 @@
"dependencies": {
"@novadi/core": "^0.6.0",
"@rollup/rollup-win32-x64-msvc": "^4.52.2",
"@sevenweirdpeople/swp-charting": "^0.1.7",
"@sevenweirdpeople/swp-charting": "^0.2.1",
"dayjs": "^1.11.19",
"fuse.js": "^7.1.0",
"json-diff-ts": "^4.8.2",
@ -1175,9 +1175,9 @@
]
},
"node_modules/@sevenweirdpeople/swp-charting": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/@sevenweirdpeople/swp-charting/-/swp-charting-0.1.7.tgz",
"integrity": "sha512-i3HEQMQmltmxykPGXCRcN8VMJZXD1sI8urb7rN8eTjB9EscDsACdkS+WyvxOEEEhyHj1hMdtULeX3BIZ1ZNrng==",
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/@sevenweirdpeople/swp-charting/-/swp-charting-0.2.1.tgz",
"integrity": "sha512-QtY77Dyv4Vs/rWfBVSDTmuxgD4L8tGu4pmTF0l3i8HDwK6qtT2wEtH35UHD1RDFE1VtOGcnU0/dTdqjNWCqzxA==",
"license": "MIT"
},
"node_modules/@types/chai": {

View file

@ -41,7 +41,7 @@
"dependencies": {
"@novadi/core": "^0.6.0",
"@rollup/rollup-win32-x64-msvc": "^4.52.2",
"@sevenweirdpeople/swp-charting": "^0.1.7",
"@sevenweirdpeople/swp-charting": "^0.2.1",
"dayjs": "^1.11.19",
"fuse.js": "^7.1.0",
"json-diff-ts": "^4.8.2",

View file

@ -0,0 +1,67 @@
{
"categories": ["Uge 40", "Uge 41", "Uge 42", "Uge 43", "Uge 44", "Uge 45", "Uge 46", "Uge 47", "Uge 48", "Uge 49", "Uge 50", "Uge 51", "Uge 52", "Uge 1", "Uge 2", "Uge 3", "Uge 4", "Uge 5", "Uge 6", "Uge 7", "Uge 8", "Uge 9", "Uge 10", "Uge 11", "Uge 12"],
"nowCategory": "Uge 52",
"forecastStartCategory": "Uge 1",
"actual": {
"revenue": [
{ "x": "Uge 40", "y": 38500 },
{ "x": "Uge 41", "y": 42000 },
{ "x": "Uge 42", "y": 35200 },
{ "x": "Uge 43", "y": 44800 },
{ "x": "Uge 44", "y": 41500 },
{ "x": "Uge 45", "y": 39200 },
{ "x": "Uge 46", "y": 46100 },
{ "x": "Uge 47", "y": 43800 },
{ "x": "Uge 48", "y": 40500 },
{ "x": "Uge 49", "y": 45200 },
{ "x": "Uge 50", "y": 42800 },
{ "x": "Uge 51", "y": 44500 },
{ "x": "Uge 52", "y": 28450 }
],
"utilization": [
{ "x": "Uge 40", "y": 82 },
{ "x": "Uge 41", "y": 88 },
{ "x": "Uge 42", "y": 75 },
{ "x": "Uge 43", "y": 91 },
{ "x": "Uge 44", "y": 85 },
{ "x": "Uge 45", "y": 80 },
{ "x": "Uge 46", "y": 94 },
{ "x": "Uge 47", "y": 89 },
{ "x": "Uge 48", "y": 83 },
{ "x": "Uge 49", "y": 92 },
{ "x": "Uge 50", "y": 87 },
{ "x": "Uge 51", "y": 90 },
{ "x": "Uge 52", "y": 84 }
]
},
"forecast": {
"revenue": [
{ "x": "Uge 1", "y": 0 },
{ "x": "Uge 2", "y": 32500 },
{ "x": "Uge 3", "y": 28800 },
{ "x": "Uge 4", "y": 22400 },
{ "x": "Uge 5", "y": 15200 },
{ "x": "Uge 6", "y": 9800 },
{ "x": "Uge 7", "y": 6500 },
{ "x": "Uge 8", "y": 4200 },
{ "x": "Uge 9", "y": 2800 },
{ "x": "Uge 10", "y": 1500 },
{ "x": "Uge 11", "y": 800 },
{ "x": "Uge 12", "y": 0 }
],
"utilization": [
{ "x": "Uge 1", "y": 0 },
{ "x": "Uge 2", "y": 74 },
{ "x": "Uge 3", "y": 58 },
{ "x": "Uge 4", "y": 39 },
{ "x": "Uge 5", "y": 21 },
{ "x": "Uge 6", "y": 11 },
{ "x": "Uge 7", "y": 8 },
{ "x": "Uge 8", "y": 5 },
{ "x": "Uge 9", "y": 3 },
{ "x": "Uge 10", "y": 2 },
{ "x": "Uge 11", "y": 1 },
{ "x": "Uge 12", "y": 0 }
]
}
}

View file

@ -1895,6 +1895,13 @@
color: var(--color-text-secondary);
}
swp-chart-subtitle {
display: block;
font-size: 12px;
color: var(--color-text-muted);
margin-top: 2px;
}
swp-chart-legend {
display: flex;
gap: 16px;
@ -2658,6 +2665,17 @@
</swp-stat-card>
</div>
<!-- Omsætning & Belægningsgrad chart -->
<swp-card style="margin-bottom: 24px;">
<swp-chart-section>
<swp-chart-header>
<swp-chart-title>Omsætning & Belægningsgrad</swp-chart-title>
<swp-chart-subtitle>3 måneder bagud · 3 måneder frem</swp-chart-subtitle>
</swp-chart-header>
<swp-chart-container id="revenueUtilizationChart" style="height: 300px;"></swp-chart-container>
</swp-chart-section>
</swp-card>
<div class="grid-2">
<swp-card>
<swp-chart-section>
@ -3489,6 +3507,72 @@
height: 200,
legend: false
});
// Revenue & Utilization chart - dual axis (3 mdr bagud + 3 mdr frem)
fetch('data/employee-revenue-utilization.json')
.then(res => res.json())
.then(data => {
createChart(document.getElementById('revenueUtilizationChart'), {
xAxis: { categories: data.categories },
yAxis: [
{ min: 0, max: 50000, format: v => `${(v/1000).toFixed(0)}k` }, // Left: Revenue
{ min: 0, max: 100, format: v => `${v}%` }, // Right: Utilization
],
series: [
// Actual revenue (solid bars)
{
name: 'Omsætning',
color: '#3b82f6',
type: 'bar',
yAxisIndex: 0,
unit: 'kr',
data: data.actual.revenue,
bar: { radius: 2 },
},
// Forecast revenue (transparent bars)
{
name: 'Omsætning (forecast)',
color: '#3b82f6',
type: 'bar',
yAxisIndex: 0,
unit: 'kr',
data: data.forecast.revenue,
bar: { radius: 2, opacity: 0.35 },
},
// Actual utilization (solid line)
{
name: 'Belægning',
color: '#00897b',
type: 'line',
yAxisIndex: 1,
unit: '%',
data: data.actual.utilization,
line: { width: 2.5 },
point: { radius: 0 },
showArea: false,
},
// Forecast utilization (dashed line)
{
name: 'Belægning (forecast)',
color: '#00897b',
type: 'line',
yAxisIndex: 1,
unit: '%',
data: data.forecast.utilization,
line: { width: 2.5, dashArray: '4 4' },
point: { radius: 0 },
showArea: false,
},
],
annotations: [
{ type: 'region', x: data.forecastStartCategory, x2: data.categories[data.categories.length - 1], backgroundColor: 'rgba(0,0,0,0.03)' },
{ type: 'verticalLine', x: data.nowCategory, dashArray: '4 4', label: 'Nu', labelPosition: 'top' },
],
legend: { position: 'top', align: 'end' },
padding: { right: 60 },
height: 280,
});
});
</script>
</body>