All checks were successful
Deploy Development / deploy (push) Successful in 40s
Test Suite / pytest-backend (push) Successful in 38s
Test Suite / lint-backend (push) Successful in 1s
Test Suite / build-frontend (push) Successful in 12s
Test Suite / k6 /health Baseline (push) Successful in 33s
Test Suite / playwright-tests (push) Successful in 1m17s
- Introduced new helper functions for managing artifact type corpus, improving code organization and readability. - Updated the `compute_club_corpus_reference` function to utilize the new corpus handling methods, enhancing clarity and maintainability. - Refactored skill profile functions to leverage the new corpus structure, ensuring consistent data retrieval across different artifact types. - Improved the handling of visibility clauses for library content, streamlining database queries for skill profiles. - Enhanced the batch skill profile summary function to aggregate reference data by artifact type, improving performance and accuracy.
111 lines
3.4 KiB
JavaScript
111 lines
3.4 KiB
JavaScript
export function frameworkSkillSummaryKey(id) {
|
|
return `framework_program:${id}`
|
|
}
|
|
|
|
export function moduleSkillSummaryKey(id) {
|
|
return `training_module:${id}`
|
|
}
|
|
|
|
export function skillEntryFromSummary(summary, skillId) {
|
|
if (!summary) return null
|
|
const sid = String(skillId)
|
|
const fromSkills = (summary.skills || []).find((s) => String(s.skill_id) === sid)
|
|
if (fromSkills) return fromSkills
|
|
return (summary.top_by_category || []).find((s) => String(s.skill_id) === sid) || null
|
|
}
|
|
|
|
export function summaryHasSkill(summary, skillId, minClubPct = 0) {
|
|
const sk = skillEntryFromSummary(summary, skillId)
|
|
if (!sk || !(Number(sk.weight) > 0)) return false
|
|
const pct = sk.universal_percent
|
|
if (pct == null) return minClubPct === 0
|
|
return pct >= minClubPct
|
|
}
|
|
|
|
export function maxSelectedSkillClubPercent(summary, skillIds = []) {
|
|
if (!summary || !skillIds.length) return null
|
|
let max = null
|
|
for (const id of skillIds) {
|
|
const sk = skillEntryFromSummary(summary, id)
|
|
if (!sk) continue
|
|
const pct = sk.universal_percent
|
|
if (pct == null) continue
|
|
if (max == null || pct > max) max = pct
|
|
}
|
|
return max
|
|
}
|
|
|
|
export function formatClubPercent(value) {
|
|
if (value == null || !Number.isFinite(Number(value))) return '—'
|
|
const n = Math.min(100, Number(value))
|
|
return n % 1 === 0 ? `${n}%` : `${n.toFixed(1)}%`
|
|
}
|
|
|
|
export function formatSkillWeight(value) {
|
|
const n = Number(value)
|
|
if (!Number.isFinite(n)) return '—'
|
|
return n % 1 === 0 ? String(n) : n.toFixed(1)
|
|
}
|
|
|
|
const PEER_LABELS = {
|
|
framework_program: 'Rahmenpr.',
|
|
training_module: 'Module',
|
|
progression_graph: 'Pfade',
|
|
}
|
|
|
|
const PEER_COUNT_LABELS = {
|
|
framework_program: 'Rahmenprogramme',
|
|
training_module: 'Module',
|
|
progression_graph: 'Regressionspfade',
|
|
}
|
|
|
|
export function peerPercentSuffix(artifactType = 'training_module') {
|
|
return PEER_LABELS[artifactType] || 'Peers'
|
|
}
|
|
|
|
export function peerCorpusCountLabel(artifactType = 'training_module') {
|
|
return PEER_COUNT_LABELS[artifactType] || 'Planungs-Artefakte'
|
|
}
|
|
|
|
/** KPI-Zeilen: immer Top je Unterkategorie; bei Skill-Filter nur passende Kategorien. */
|
|
export function kpiRowsFromSummary(summary, { skillIds = [], limit = 8 } = {}) {
|
|
if (!summary) return []
|
|
let rows = (summary.top_by_category || []).map((row) => ({
|
|
skill_id: row.skill_id,
|
|
skill_name: row.skill_name,
|
|
category_name: row.category_name,
|
|
main_category_name: row.main_category_name,
|
|
weight: row.weight ?? row.score,
|
|
universal_percent: row.universal_percent,
|
|
is_club_best_for_skill: row.is_club_best_for_skill,
|
|
}))
|
|
if (skillIds.length) {
|
|
const wanted = new Set(skillIds.map(String))
|
|
rows = rows.filter((row) => wanted.has(String(row.skill_id)))
|
|
}
|
|
return rows.slice(0, limit)
|
|
}
|
|
|
|
/** @deprecated Nutze kpiRowsFromSummary für Listen */
|
|
export function compactSkillDisplayRows(summary, opts = {}) {
|
|
return kpiRowsFromSummary(summary, opts)
|
|
}
|
|
|
|
export function artifactTypeLabel(type) {
|
|
if (type === 'framework_program') return 'Rahmenprogramm'
|
|
if (type === 'training_module') return 'Modul'
|
|
if (type === 'progression_graph') return 'Regressionspfad'
|
|
return type || 'Artefakt'
|
|
}
|
|
|
|
export function artifactPath(ref) {
|
|
if (!ref) return null
|
|
if (ref.artifact_type === 'framework_program') {
|
|
return `/planning/framework-programs/${ref.artifact_id}`
|
|
}
|
|
if (ref.artifact_type === 'training_module') {
|
|
return `/planning/training-modules/${ref.artifact_id}`
|
|
}
|
|
return null
|
|
}
|