src/app/home/home.component.ts
selector | home |
styleUrls | home.component.css |
templateUrl | home.component.html |
constructor(timeNetDataService: TimeNetDataService, router: Router)
|
handleDragEnter |
handleDragEnter()
|
Returns:
void
|
handleDragLeave |
handleDragLeave()
|
Returns:
void
|
handleDrop |
handleDrop(e: any)
|
Returns:
void
|
handleInputChange |
handleInputChange(e: any)
|
Returns:
void
|
openFileLoader |
openFileLoader()
|
Returns:
void
|
fileChange |
fileChange(event: any)
|
Parses the input file
Parameters :
Returns:
void
|
processFile |
processFile(file: File)
|
Returns:
void
|
Public parseGedFile |
parseGedFile(lines: any)
|
Parses the file
Parameters :
Returns:
void
|
Private parseLine |
parseLine(line: String)
|
Parses one single line of a gedcom file
Parameters :
Returns:
RowData
|
Private chartData |
chartData: |
Private dragCounter |
dragCounter: |
Default value: 0
|
Private dragging |
dragging: |
fileInput |
fileInput: |
Private fileName |
fileName: |
Private isLoading |
isLoading: |
Default value: false
|
router |
router: |
timeNetDataService |
timeNetDataService: |
import {
Component,
OnInit, ViewChild, ElementRef
} from '@angular/core';
import { Http, Response } from '@angular/http';
import { Headers, RequestOptions } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import { PersonData, RelationShipData, relationShipTypeEnum, TimeNetDataService } from './timenet.service';
import { Router } from '@angular/router';
export interface RowData {
level: number;
id: string;
tag: string;
value: string;
}
@Component({
// The selector is what angular internally uses
// for `document.querySelectorAll(selector)` in our index.html
// where, in this case, selector is the string 'home'
selector: 'home', // <home></home>
// We need to tell Angular's Dependency Injection which providers are in our app.
providers: [ ],
// Our list of styles in our component. We may add more to compose many styles together
styleUrls: [ './home.component.css' ],
// Every Angular template is first compiled by the browser before Angular runs it's compiler
templateUrl: './home.component.html'
})
export class HomeComponent implements OnInit {
private chartData: any[];
@ViewChild('fileLoader') fileInput: ElementRef;
private dragging: boolean;
// TypeScript public modifiers
constructor(
public timeNetDataService: TimeNetDataService,
public router: Router
) {}
private dragCounter: number = 0;
private isLoading: boolean = false;
private fileName: string = '';
public ngOnInit() { // this.title.getData().subscribe(data => this.data = data);
}
handleDragEnter() {
this.dragCounter++;
this.dragging = true;
}
handleDragLeave() {
this.dragCounter--;
if(this.dragCounter===0)
this.dragging = false;
}
handleDrop(e) {
e.preventDefault();
this.dragging = false;
this.handleInputChange(e);
}
handleInputChange(e) {
let file = e.dataTransfer ? e.dataTransfer.files[0] : e.target.files[0];
let pattern = '\w*(.ged)$';
let reader = new FileReader();
if (!file.name.match(pattern)) {
alert('invalid format');
return;
}
this.processFile(file);
/*this.loaded = false;
reader.onload = this._handleReaderLoaded.bind(this);
reader.readAsDataURL(file);*/
}
openFileLoader() {
let event = new MouseEvent('click', { bubbles: true });
this.fileInput.nativeElement.dispatchEvent(event);
}
/**
* Parses the input file
* @param event
*/
fileChange(event) {
let file: File = event.target.files[0];
this.processFile(file);
}
processFile(file: File)
{
this.isLoading = true;
this.fileName = file.name;
console.log(file);
console.log(this.fileName);
let reader = new FileReader();
let self = this;
reader.onload = function (progressEvent) {
// split into lines
//
let lines = this.result.split('\n');
self.parseGedFile(lines);
};
reader.readAsText(file);
}
/**
* Parses the file
* @param lines
*/
public parseGedFile(lines): void
{
let line = 0;
let end: boolean = false;
let currentRow: RowData;
while (line < lines.length && !end) {
currentRow = this.parseLine(lines[line]);
if (currentRow.level === 0) {
// reading meta data
if (currentRow.tag === 'HEAD') {
let name: string;
let gedVersion: string;
let form: string;
let charset: string;
currentRow = this.parseLine(lines[++line]);
// iterate until lvl 0 is reached again
while (currentRow.level !== 0)
{
if (currentRow.level === 2 && currentRow.tag === 'NAME')
name = currentRow.value;
if (currentRow.level === 2 && currentRow.tag === 'VERS')
gedVersion = currentRow.value;
if (currentRow.level === 2 && currentRow.tag === 'FORM')
form = currentRow.value;
if (currentRow.level === 1 && currentRow.tag === 'CHAR')
charset = currentRow.value;
currentRow = this.parseLine(lines[++line]);
}
// save the metadata in service
this.timeNetDataService.newTimeNetData(this.fileName, name, gedVersion, form, charset);
}
// reading a person
else if (currentRow.tag === 'INDI') {
let names: string[] = [];
let id: string = currentRow.id;
let dateOfBirth: string = '';
let dateOfDeath: string = '';
let sex: string = '';
currentRow = this.parseLine(lines[++line]);
// iterate until lvl 0 is reached again
while (currentRow.level !== 0) {
if (currentRow.level === 1 && currentRow.tag === 'SEX')
sex = currentRow.value;
if (currentRow.level === 1 && currentRow.tag === 'NAME')
names.push(currentRow.value);
if (currentRow.level === 1 && currentRow.tag === 'BIRT')
{
currentRow = this.parseLine(lines[++line]);
while (currentRow.level === 2)
{
if (currentRow.tag === 'DATE')
dateOfBirth += currentRow.value;
if (currentRow.tag === 'TYPE')
dateOfBirth += currentRow.value;
currentRow = this.parseLine(lines[++line]);
}
}
if (currentRow.level === 1 && currentRow.tag === 'DEAT') {
currentRow = this.parseLine(lines[++line]);
while (currentRow.level === 2) {
if (currentRow.tag === 'DATE')
dateOfDeath += currentRow.value;
if (currentRow.tag === 'TYPE')
dateOfDeath += currentRow.value;
currentRow = this.parseLine(lines[++line]);
}
}
if (currentRow.level === 1 && currentRow.tag === 'FAMS') {
/*this.timeNetDataService.addReleationShip(
id, currentRow.id, relationShipTypeEnum['Spouse-Of'], '', ''
);*/
this.timeNetDataService.addSpouseToFamily(currentRow.id,id);
}
if (currentRow.level === 1 && currentRow.tag === 'FAMC') {
/*this.timeNetDataService.addReleationShip(
currentRow.id, id, relationShipTypeEnum['Child-Of'], '', ''
);*/
this.timeNetDataService.addChildToFamily(currentRow.id,id);
}
currentRow = this.parseLine(lines[++line]);
}
// save the metadata in service
this.timeNetDataService.addPerson(id, names, sex, dateOfBirth, dateOfDeath);
}
else if (currentRow.tag === 'FAM')
{
let famId: string = currentRow.id;
// 0 - 1 husband or wife
let husband: string = '';
let wife: string = '';
let children: string[] = [];
currentRow = this.parseLine(lines[++line]);
while (currentRow.level !== 0) {
if (currentRow.tag === 'HUSB' || currentRow.tag === 'WIFE') {
this.timeNetDataService.addSpouseToFamily(famId, currentRow.id);
} else if (currentRow.tag === 'CHIL') {
this.timeNetDataService.addChildToFamily(famId, currentRow.id);
}
currentRow = this.parseLine(lines[++line]);
}
}
else if (currentRow.tag === 'TRLR') {
end = true;
}
else {
line++;
}
} else {
line++;
}
}
this.timeNetDataService.finishImport();
console.log(this.timeNetDataService.getTimeNetData());
console.log('loading finished - redirect to visualization');
this.router.navigate(['vis']);
}
/**
* Parses one single line of a gedcom file
* @param line
* src: https://github.com/dcapwell/gedcom.js/blob/master/lib/gedcom.js
*/
private parseLine(line: String): RowData {
let split = line.split(' '),
lvl = split.shift().trim(),
tmp = split.shift().trim(),
id = null,
tag = null,
value = null;
if (tmp.charAt(0) === '@') {
// line contains an id
id = tmp;
tmp = split.shift().trim();
}
tag = tmp;
if (split.length > 0) {
value = split.join(' ');
if (value.match(/@[^@]+@/)) {
// contains a reference...
// Family Tree Legends seems to put id in value some times, other times it will put it in id location...
id = value;
value = null;
}
}
return <RowData> { level: +lvl, id, tag, value };
}
}