Moving away from Azure Devops #1
4 changed files with 156 additions and 5 deletions
8
package-lock.json
generated
8
package-lock.json
generated
|
|
@ -10,7 +10,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@novadi/core": "^0.6.0",
|
"@novadi/core": "^0.6.0",
|
||||||
"@rollup/rollup-win32-x64-msvc": "^4.52.2",
|
"@rollup/rollup-win32-x64-msvc": "^4.52.2",
|
||||||
"@sevenweirdpeople/swp-charting": "^0.1.7",
|
"@sevenweirdpeople/swp-charting": "^0.2.1",
|
||||||
"dayjs": "^1.11.19",
|
"dayjs": "^1.11.19",
|
||||||
"fuse.js": "^7.1.0",
|
"fuse.js": "^7.1.0",
|
||||||
"json-diff-ts": "^4.8.2",
|
"json-diff-ts": "^4.8.2",
|
||||||
|
|
@ -1175,9 +1175,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@sevenweirdpeople/swp-charting": {
|
"node_modules/@sevenweirdpeople/swp-charting": {
|
||||||
"version": "0.1.7",
|
"version": "0.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/@sevenweirdpeople/swp-charting/-/swp-charting-0.1.7.tgz",
|
"resolved": "https://registry.npmjs.org/@sevenweirdpeople/swp-charting/-/swp-charting-0.2.1.tgz",
|
||||||
"integrity": "sha512-i3HEQMQmltmxykPGXCRcN8VMJZXD1sI8urb7rN8eTjB9EscDsACdkS+WyvxOEEEhyHj1hMdtULeX3BIZ1ZNrng==",
|
"integrity": "sha512-QtY77Dyv4Vs/rWfBVSDTmuxgD4L8tGu4pmTF0l3i8HDwK6qtT2wEtH35UHD1RDFE1VtOGcnU0/dTdqjNWCqzxA==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@types/chai": {
|
"node_modules/@types/chai": {
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@novadi/core": "^0.6.0",
|
"@novadi/core": "^0.6.0",
|
||||||
"@rollup/rollup-win32-x64-msvc": "^4.52.2",
|
"@rollup/rollup-win32-x64-msvc": "^4.52.2",
|
||||||
"@sevenweirdpeople/swp-charting": "^0.1.7",
|
"@sevenweirdpeople/swp-charting": "^0.2.1",
|
||||||
"dayjs": "^1.11.19",
|
"dayjs": "^1.11.19",
|
||||||
"fuse.js": "^7.1.0",
|
"fuse.js": "^7.1.0",
|
||||||
"json-diff-ts": "^4.8.2",
|
"json-diff-ts": "^4.8.2",
|
||||||
|
|
|
||||||
67
wwwroot/data/employee-revenue-utilization.json
Normal file
67
wwwroot/data/employee-revenue-utilization.json
Normal 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 }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1895,6 +1895,13 @@
|
||||||
color: var(--color-text-secondary);
|
color: var(--color-text-secondary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
swp-chart-subtitle {
|
||||||
|
display: block;
|
||||||
|
font-size: 12px;
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
margin-top: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
swp-chart-legend {
|
swp-chart-legend {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
|
|
@ -2658,6 +2665,17 @@
|
||||||
</swp-stat-card>
|
</swp-stat-card>
|
||||||
</div>
|
</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">
|
<div class="grid-2">
|
||||||
<swp-card>
|
<swp-card>
|
||||||
<swp-chart-section>
|
<swp-chart-section>
|
||||||
|
|
@ -3489,6 +3507,72 @@
|
||||||
height: 200,
|
height: 200,
|
||||||
legend: false
|
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>
|
</script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue