Refactor Skill Tree Picker and Catalog Functions for Clarity and Efficiency
Some checks failed
Deploy Development / deploy (push) Successful in 41s
Test Suite / pytest-backend (push) Successful in 36s
Test Suite / lint-backend (push) Successful in 0s
Test Suite / build-frontend (push) Successful in 13s
Test Suite / k6 /health Baseline (push) Successful in 33s
Test Suite / playwright-tests (push) Has been cancelled
Some checks failed
Deploy Development / deploy (push) Successful in 41s
Test Suite / pytest-backend (push) Successful in 36s
Test Suite / lint-backend (push) Successful in 0s
Test Suite / build-frontend (push) Successful in 13s
Test Suite / k6 /health Baseline (push) Successful in 33s
Test Suite / playwright-tests (push) Has been cancelled
- Simplified the rendering of skill group labels in `SkillTreePickerPanel` for improved readability. - Updated comments in `skillCatalogTree.js` to clarify the structure of expandable nodes and default expansion behavior. - Refactored the skill catalog tree building logic to streamline the mapping of categories and skills, enhancing performance and maintainability. - Adjusted tests in `skillCatalogTree.test.js` to reflect changes in the structure of skill nodes, ensuring accurate validation of functionality.
This commit is contained in:
parent
39b1fd04f0
commit
b2f77ca627
|
|
@ -5320,12 +5320,6 @@ html.modal-scroll-locked .app-main {
|
||||||
line-height: 1.35;
|
line-height: 1.35;
|
||||||
}
|
}
|
||||||
|
|
||||||
.skill-tree__group-label--skill-group {
|
|
||||||
font-weight: 500;
|
|
||||||
color: var(--text2);
|
|
||||||
font-size: 0.84rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.multi-assoc-block {
|
.multi-assoc-block {
|
||||||
border: 1px solid var(--border);
|
border: 1px solid var(--border);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
|
|
|
||||||
|
|
@ -55,11 +55,7 @@ function SkillTreeNodes({ nodes, depth, expanded, exclude, onToggle, onPickSkill
|
||||||
) : (
|
) : (
|
||||||
<span className="skill-tree__toggle-spacer" aria-hidden />
|
<span className="skill-tree__toggle-spacer" aria-hidden />
|
||||||
)}
|
)}
|
||||||
<span
|
<span className={`skill-tree__group-label skill-tree__group-label--${node.type}`}>
|
||||||
className={`skill-tree__group-label skill-tree__group-label--${node.type}${
|
|
||||||
node.type === 'skillGroup' ? ' skill-tree__group-label--skill-group' : ''
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
{node.label}
|
{node.label}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -82,7 +78,7 @@ function SkillTreeNodes({ nodes, depth, expanded, exclude, onToggle, onPickSkill
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ausklappbare Baumliste: Hauptgruppe → Kategorie (beide standard offen) → Fähigkeiten-Gruppe (standard zu).
|
* Ausklappbare Baumliste: Hauptgruppe → Kategorie → Fähigkeit (Hauptgruppe und Kategorie standard offen).
|
||||||
*/
|
*/
|
||||||
export default function SkillTreePickerPanel({
|
export default function SkillTreePickerPanel({
|
||||||
skills = [],
|
skills = [],
|
||||||
|
|
|
||||||
|
|
@ -80,33 +80,18 @@ export function buildSkillCatalogTree(skills) {
|
||||||
if (a.sortOrder !== b.sortOrder) return a.sortOrder - b.sortOrder
|
if (a.sortOrder !== b.sortOrder) return a.sortOrder - b.sortOrder
|
||||||
return a.label.localeCompare(b.label, 'de')
|
return a.label.localeCompare(b.label, 'de')
|
||||||
})
|
})
|
||||||
.map((cat) => {
|
.map((cat) => ({
|
||||||
const skillLeaves = [...cat.skills].sort(bySortThenName).map((skill) => ({
|
key: cat.key,
|
||||||
|
type: cat.type,
|
||||||
|
label: cat.label,
|
||||||
|
children: [...cat.skills].sort(bySortThenName).map((skill) => ({
|
||||||
key: `s-${skill.id}`,
|
key: `s-${skill.id}`,
|
||||||
type: 'skill',
|
type: 'skill',
|
||||||
label: (skill.name || '').trim() || `#${skill.id}`,
|
label: (skill.name || '').trim() || `#${skill.id}`,
|
||||||
skillId: Number(skill.id),
|
skillId: Number(skill.id),
|
||||||
skill,
|
skill,
|
||||||
}))
|
})),
|
||||||
const n = skillLeaves.length
|
})),
|
||||||
return {
|
|
||||||
key: cat.key,
|
|
||||||
type: cat.type,
|
|
||||||
label: cat.label,
|
|
||||||
children:
|
|
||||||
n > 0
|
|
||||||
? [
|
|
||||||
{
|
|
||||||
key: `${cat.key}-skills`,
|
|
||||||
type: 'skillGroup',
|
|
||||||
label: n === 1 ? '1 Fähigkeit' : `${n} Fähigkeiten`,
|
|
||||||
skillCount: n,
|
|
||||||
children: skillLeaves,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
: [],
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -132,8 +117,7 @@ export function collectSkillLeavesFromTree(tree, excludeIds) {
|
||||||
out.push({ id: n.skillId, label: n.label, pathLabel, skill: n.skill })
|
out.push({ id: n.skillId, label: n.label, pathLabel, skill: n.skill })
|
||||||
}
|
}
|
||||||
} else if (n.children?.length) {
|
} else if (n.children?.length) {
|
||||||
const nextPath = n.type === 'skillGroup' ? pathParts : [...pathParts, n.label]
|
walk(n.children, [...pathParts, n.label])
|
||||||
walk(n.children, nextPath)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -153,9 +137,6 @@ export function filterSkillTreeByQuery(tree, query) {
|
||||||
if (n.type === 'skill') {
|
if (n.type === 'skill') {
|
||||||
const hay = `${n.label} ${skillCatalogPathLabel(n.skill)}`.toLowerCase()
|
const hay = `${n.label} ${skillCatalogPathLabel(n.skill)}`.toLowerCase()
|
||||||
if (hay.includes(q)) result.push(n)
|
if (hay.includes(q)) result.push(n)
|
||||||
} else if (n.type === 'skillGroup') {
|
|
||||||
const kids = filterNodes(n.children || [])
|
|
||||||
if (kids.length) result.push({ ...n, children: kids })
|
|
||||||
} else {
|
} else {
|
||||||
const kids = filterNodes(n.children || [])
|
const kids = filterNodes(n.children || [])
|
||||||
if (kids.length) result.push({ ...n, children: kids })
|
if (kids.length) result.push({ ...n, children: kids })
|
||||||
|
|
@ -166,7 +147,7 @@ export function filterSkillTreeByQuery(tree, query) {
|
||||||
return filterNodes(tree)
|
return filterNodes(tree)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Alle aufklappbaren Knoten (inkl. Fähigkeiten-Gruppen unter Kategorien). */
|
/** Alle aufklappbaren Knoten (Hauptgruppe und Kategorie). */
|
||||||
export function allExpandableKeys(tree) {
|
export function allExpandableKeys(tree) {
|
||||||
const keys = []
|
const keys = []
|
||||||
const walk = (nodes) => {
|
const walk = (nodes) => {
|
||||||
|
|
@ -181,7 +162,7 @@ export function allExpandableKeys(tree) {
|
||||||
return keys
|
return keys
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Standard: Hauptgruppe + Kategorie offen, Fähigkeiten-Liste zugeklappt. */
|
/** Standard: Hauptgruppe und Kategorie aufgeklappt (Fähigkeiten direkt darunter sichtbar). */
|
||||||
export function defaultExpandedKeysForSkillTree(tree) {
|
export function defaultExpandedKeysForSkillTree(tree) {
|
||||||
const keys = []
|
const keys = []
|
||||||
const walk = (nodes) => {
|
const walk = (nodes) => {
|
||||||
|
|
|
||||||
|
|
@ -44,9 +44,9 @@ describe('skillCatalogTree', () => {
|
||||||
expect(tree[0].label).toBe('Karate')
|
expect(tree[0].label).toBe('Karate')
|
||||||
expect(tree[0].children).toHaveLength(2)
|
expect(tree[0].children).toHaveLength(2)
|
||||||
expect(tree[0].children[0].label).toBe('Kata')
|
expect(tree[0].children[0].label).toBe('Kata')
|
||||||
const kataSkills = tree[0].children[0].children[0]
|
const kataSkill = tree[0].children[0].children[0]
|
||||||
expect(kataSkills.type).toBe('skillGroup')
|
expect(kataSkill.type).toBe('skill')
|
||||||
expect(kataSkills.children[0].skillId).toBe(2)
|
expect(kataSkill.skillId).toBe(2)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('defaultExpandedKeysForSkillTree opens main and category only', () => {
|
it('defaultExpandedKeysForSkillTree opens main and category only', () => {
|
||||||
|
|
@ -54,7 +54,7 @@ describe('skillCatalogTree', () => {
|
||||||
const keys = defaultExpandedKeysForSkillTree(tree)
|
const keys = defaultExpandedKeysForSkillTree(tree)
|
||||||
expect(keys).toContain('m-10')
|
expect(keys).toContain('m-10')
|
||||||
expect(keys.some((k) => k.includes('c-21'))).toBe(true)
|
expect(keys.some((k) => k.includes('c-21'))).toBe(true)
|
||||||
expect(keys.some((k) => k.endsWith('-skills'))).toBe(false)
|
expect(keys.some((k) => k.startsWith('s-'))).toBe(false)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('skillCatalogPathLabel', () => {
|
it('skillCatalogPathLabel', () => {
|
||||||
|
|
@ -72,8 +72,7 @@ describe('skillCatalogTree', () => {
|
||||||
const tree = buildSkillCatalogTree(sample)
|
const tree = buildSkillCatalogTree(sample)
|
||||||
const filtered = filterSkillTreeByQuery(tree, 'dachi')
|
const filtered = filterSkillTreeByQuery(tree, 'dachi')
|
||||||
const kihon = filtered[0].children.find((c) => c.label === 'Kihon')
|
const kihon = filtered[0].children.find((c) => c.label === 'Kihon')
|
||||||
const group = kihon?.children?.[0]
|
expect(kihon?.children?.some((s) => s.skillId === 1)).toBe(true)
|
||||||
expect(group?.children?.some((s) => s.skillId === 1)).toBe(true)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('catalogSkillsForSelection lists unassigned buckets', () => {
|
it('catalogSkillsForSelection lists unassigned buckets', () => {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user