From f23ec6d732565713ff46a478269e596230d0d708 Mon Sep 17 00:00:00 2001 From: AdamBtech <60339324+AdamBtech@users.noreply.github.com> Date: Mon, 2 Jun 2025 21:16:02 +0200 Subject: [PATCH] Added skilltree from about page to dataService --- assets/data/skills.json | 0 assets/data/skilltree.json | 183 ++++++++++++++ .../neural-profile-tree.component.ts | 236 ++++-------------- src/app/shared/services/data.service.ts | 68 ++--- 4 files changed, 263 insertions(+), 224 deletions(-) delete mode 100644 assets/data/skills.json create mode 100644 assets/data/skilltree.json diff --git a/assets/data/skills.json b/assets/data/skills.json deleted file mode 100644 index e69de29..0000000 diff --git a/assets/data/skilltree.json b/assets/data/skilltree.json new file mode 100644 index 0000000..f882c43 --- /dev/null +++ b/assets/data/skilltree.json @@ -0,0 +1,183 @@ +{ + "id": "workstation", + "title": "Workstation/", + "isExpanded": true, + "isSelected": false, + "level": 0, + "hasChildren": true, + "visible": true, + "children": [ + { + "id": "tools", + "title": "Tools/", + "isExpanded": true, + "isSelected": false, + "level": 1, + "hasChildren": true, + "visible": true, + "children": [ + { + "id": "webstorm", + "title": "Webstorm/", + "isExpanded": false, + "isSelected": false, + "level": 2, + "hasChildren": false, + "visible": true + }, + { + "id": "linux", + "title": "Linux_Debian/", + "isExpanded": false, + "isSelected": false, + "level": 2, + "hasChildren": false, + "visible": true + }, + { + "id": "git", + "title": "Git/", + "isExpanded": false, + "isSelected": false, + "level": 2, + "hasChildren": false, + "visible": true + }, + { + "id": "docker", + "title": "Docker/", + "isExpanded": false, + "isSelected": false, + "level": 2, + "hasChildren": false, + "visible": true + } + ] + }, + { + "id": "dev", + "title": "Dev/", + "isExpanded": true, + "isSelected": false, + "level": 1, + "hasChildren": true, + "visible": true, + "children": [ + { + "id": "front", + "title": "Front/", + "isExpanded": true, + "isSelected": false, + "level": 2, + "hasChildren": true, + "visible": true, + "children": [ + { + "id": "angular", + "title": "Angular/", + "isExpanded": false, + "isSelected": false, + "level": 3, + "hasChildren": false, + "visible": true + }, + { + "id": "tailwind", + "title": "Tailwind_SASS/", + "isExpanded": false, + "isSelected": false, + "level": 3, + "hasChildren": false, + "visible": true + }, + { + "id": "html-css", + "title": "HTML_CSS/", + "isExpanded": false, + "isSelected": false, + "level": 3, + "hasChildren": false, + "visible": true + } + ] + }, + { + "id": "back", + "title": "Back/", + "isExpanded": true, + "isSelected": false, + "level": 2, + "hasChildren": true, + "visible": true, + "children": [ + { + "id": "nodejs", + "title": "NodeJS_Express/", + "isExpanded": false, + "isSelected": false, + "level": 3, + "hasChildren": false, + "visible": true + }, + { + "id": "typescript", + "title": "Typescript/", + "isExpanded": false, + "isSelected": false, + "level": 3, + "hasChildren": false, + "visible": true + }, + { + "id": "php", + "title": "PHP_Symfony/", + "isExpanded": false, + "isSelected": false, + "level": 3, + "hasChildren": false, + "visible": true + }, + { + "id": "python", + "title": "Python_Django/", + "isExpanded": false, + "isSelected": false, + "level": 3, + "hasChildren": false, + "visible": true + } + ] + }, + { + "id": "data", + "title": "Data/", + "isExpanded": true, + "isSelected": false, + "level": 2, + "hasChildren": true, + "visible": true, + "children": [ + { + "id": "postgresql", + "title": "PostgreSQL/", + "isExpanded": false, + "isSelected": false, + "level": 3, + "hasChildren": false, + "visible": true + }, + { + "id": "mongodb", + "title": "MongoDB/", + "isExpanded": false, + "isSelected": false, + "level": 3, + "hasChildren": false, + "visible": true + } + ] + } + ] + } + ] +} diff --git a/src/app/pages/about/neural-profile-tree/neural-profile-tree.component.ts b/src/app/pages/about/neural-profile-tree/neural-profile-tree.component.ts index af92f27..622d3b9 100644 --- a/src/app/pages/about/neural-profile-tree/neural-profile-tree.component.ts +++ b/src/app/pages/about/neural-profile-tree/neural-profile-tree.component.ts @@ -1,6 +1,14 @@ -import { Component, input, signal, computed } from '@angular/core'; +import { + Component, + input, + signal, + computed, + inject, + effect, +} from '@angular/core'; import { CommonModule } from '@angular/common'; import { type NeuralProfileNode } from '../../../shared/models/about.model'; +import { DataService } from '../../../shared/services/data.service'; @Component({ selector: 'app-neural-profile-tree', @@ -10,203 +18,51 @@ import { type NeuralProfileNode } from '../../../shared/models/about.model'; styleUrl: './neural-profile-tree.component.css', }) export class NeuralProfileTreeComponent { - // Input for external data (optional) + private readonly dataService = inject(DataService); + + // Input for external data (optional override) externalData = input([]); // Internal tree state and interaction signals - private treeState = signal(this.getInitialData()); + private treeState = signal([]); public hoveredNodeId = signal(null); public selectedNodeId = signal(null); // Computed flattened tree for rendering treeData = computed(() => this.flattenTreeWithVisibility(this.treeState())); - private getInitialData(): NeuralProfileNode[] { - return [ - { - id: 'workstation', - title: 'Workstation/', - isExpanded: true, - isSelected: false, - level: 0, - hasChildren: true, - visible: true, - children: [ - { - id: 'tools', - title: 'Tools/', - isExpanded: true, - isSelected: false, - level: 1, - hasChildren: true, - visible: true, - children: [ - { - id: 'webstorm', - title: 'Webstorm/', - isExpanded: false, - isSelected: false, - level: 2, - hasChildren: false, - visible: true, - }, - { - id: 'linux', - title: 'Linux_Debian/', - isExpanded: false, - isSelected: false, - level: 2, - hasChildren: false, - visible: true, - }, - { - id: 'git', - title: 'Git/', - isExpanded: false, - isSelected: false, - level: 2, - hasChildren: false, - visible: true, - }, - { - id: 'docker', - title: 'Docker/', - isExpanded: false, - isSelected: false, - level: 2, - hasChildren: false, - visible: true, - }, - ], - }, - { - id: 'dev', - title: 'Dev/', - isExpanded: true, - isSelected: false, - level: 1, - hasChildren: true, - visible: true, - children: [ - { - id: 'front', - title: 'Front/', - isExpanded: true, - isSelected: false, - level: 2, - hasChildren: true, - visible: true, - children: [ - { - id: 'angular', - title: 'Angular/', - isExpanded: false, - isSelected: false, - level: 3, - hasChildren: false, - visible: true, - }, - { - id: 'tailwind', - title: 'Tailwind_SASS/', - isExpanded: false, - isSelected: false, - level: 3, - hasChildren: false, - visible: true, - }, - { - id: 'html-css', - title: 'HTML_CSS/', - isExpanded: false, - isSelected: false, - level: 3, - hasChildren: false, - visible: true, - }, - ], - }, - { - id: 'back', - title: 'Back/', - isExpanded: true, - isSelected: false, - level: 2, - hasChildren: true, - visible: true, - children: [ - { - id: 'nodejs', - title: 'NodeJS_Express/', - isExpanded: false, - isSelected: false, - level: 3, - hasChildren: false, - visible: true, - }, - { - id: 'typescript', - title: 'Typescript/', - isExpanded: false, - isSelected: false, - level: 3, - hasChildren: false, - visible: true, - }, - { - id: 'php', - title: 'PHP_Symfony/', - isExpanded: false, - isSelected: false, - level: 3, - hasChildren: false, - visible: true, - }, - { - id: 'python', - title: 'Python_Django/', - isExpanded: false, - isSelected: false, - level: 3, - hasChildren: false, - visible: true, - }, - ], - }, - { - id: 'data', - title: 'Data/', - isExpanded: true, - isSelected: false, - level: 2, - hasChildren: true, - visible: true, - children: [ - { - id: 'postgresql', - title: 'PostgreSQL/', - isExpanded: false, - isSelected: false, - level: 3, - hasChildren: false, - visible: true, - }, - { - id: 'mongodb', - title: 'MongoDB/', - isExpanded: false, - isSelected: false, - level: 3, - hasChildren: false, - visible: true, - }, - ], - }, - ], - }, - ], - }, - ]; + // Computed to determine data source + private dataSource = computed(() => { + const external = this.externalData(); + const fromService = this.dataService.skills(); + + console.log('External data:', external); + console.log('Service data:', fromService); + console.log( + 'Service data type:', + Array.isArray(fromService) ? 'array' : typeof fromService, + ); + + // Use external data if provided, otherwise use service data + let data = external.length > 0 ? external : fromService; + + // Ensure data is an array - if it's a single object, wrap it in an array + if (data && !Array.isArray(data)) { + console.log('Converting single object to array'); + data = [data]; + } + + // Ensure data is actually an array + return Array.isArray(data) ? data : []; + }); + + constructor() { + // Effect to update tree state when data source changes + effect(() => { + const data = this.dataSource(); + console.log('Neural profile data updated:', data); + this.treeState.set(data); + }); } private flattenTreeWithVisibility( @@ -269,7 +125,7 @@ export class NeuralProfileTreeComponent { }); } - // NEW METHOD: Handle chip cell hover + // Handle chip cell hover hoverChipChild(childId: string): void { this.hoveredNodeId.set(childId); } diff --git a/src/app/shared/services/data.service.ts b/src/app/shared/services/data.service.ts index b845efe..fed5369 100644 --- a/src/app/shared/services/data.service.ts +++ b/src/app/shared/services/data.service.ts @@ -2,6 +2,7 @@ import { Injectable, signal, inject } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { type Project } from '../models/project.model'; import { firstValueFrom } from 'rxjs'; +import { NeuralProfileNode } from '../models/about.model'; @Injectable({ providedIn: 'root', @@ -11,9 +12,11 @@ export class DataService { // Private signals for state management private _projects = signal([]); + private _skills = signal([]); // Public readonly signals readonly projects = this._projects.asReadonly(); + readonly skills = this._skills.asReadonly(); constructor() { console.log('DataService initialized'); @@ -22,52 +25,49 @@ export class DataService { private async loadInitialData(): Promise { try { - console.log('Starting to load projects...'); - const projects = await this.fetchProjects(); + console.log('Starting to load data...'); + const [projects, skills] = await Promise.all([ + this.fetchProjects(), + this.fetchSkills(), + ]); + console.log('Projects loaded successfully:', projects); + console.log('Skills loaded successfully:', skills); console.log('Number of projects:', projects.length); + console.log('Number of skills:', skills.length); + this._projects.set(projects); - console.log('Projects signal updated'); + this._skills.set(skills); + console.log('All data signals updated'); } catch (error) { console.error('Error loading data:', error); - - // Fallback to hardcoded data for debugging - console.log('Loading fallback data...'); - const fallbackProjects: Project[] = [ - { - id: 'portfolio', - title: 'PORTFOLIO_SYSTEM.EXE', - status: '[MISSION_ACTIVE]', - classification: 'Personal Showcase Platform', - objective: 'Professional presentation interface with NieR aesthetic', - statusDescription: 'LIVE | CONTINUOUS_UPDATE', - techStack: ['ANGULAR', 'TYPESCRIPT', 'TAILWIND', 'VERCEL'], - demoUrl: 'https://adambenyekkoudev.vercel.app/', - codeUrl: 'https://github.com/adam-benyekkou/angular_portfolio', - isRedacted: false, - }, - { - id: 'redacted-1', - title: 'REDACTED_PROJECT_1', - status: '[REDACTED]', - classification: '', - objective: '', - statusDescription: '', - techStack: [], - isRedacted: true, - }, - ]; - this._projects.set(fallbackProjects); - console.log('Fallback data loaded'); } } private async fetchProjects(): Promise { - console.log('Fetching projects from assets/data/projects.json'); + console.log('Fetching projects from data/projects.json'); const result = await firstValueFrom( this.http.get('data/projects.json'), ); - console.log('HTTP request completed:', result); + console.log('Projects HTTP request completed:', result); return result; } + + private async fetchSkills(): Promise { + console.log('Fetching skills from data/skilltree.json'); + const result = await firstValueFrom( + this.http.get( + 'data/skilltree.json', + ), + ); + console.log('Skills HTTP request completed:', result); + + // If the JSON contains a single object instead of an array, wrap it in an array + if (result && !Array.isArray(result)) { + console.log('Converting single skill object to array'); + return [result as NeuralProfileNode]; + } + + return Array.isArray(result) ? result : []; + } }