Added tags system.
This commit is contained in:
parent
af1d853fff
commit
aa20ce04b1
@ -13,13 +13,13 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-8 offset-md-2 centercontents">
|
<div class="col-md-8 offset-md-2 centercontents">
|
||||||
<div id="topmenubuttons">
|
<div id="topmenubuttons">
|
||||||
<div class="btn-group mx-auto" role="group" aria-label="Basic example">
|
<div class="btn-group mx-auto" role="group">
|
||||||
<!-- <button type="button" class="btn btn-secondary">Left</button> -->
|
<!-- <button type="button" class="btn btn-secondary">Left</button> -->
|
||||||
<!-- <button type="button" class="btn btn-secondary">Middle</button> -->
|
<!-- <button type="button" class="btn btn-secondary">Middle</button> -->
|
||||||
<!-- <button type="button" class="btn btn-secondary">Right</button> -->
|
<!-- <button type="button" class="btn btn-secondary">Right</button> -->
|
||||||
<a routerLink="/home"><i class="text-secondary fa fa-home fa-fw fa-2x" tooltip="Huis" placement="bottom" aria-hidden="true"></i></a>
|
<a routerLink="/home"><i class="fa fa-home fa-fw fa-2x" tooltip="Huis" placement="bottom" aria-hidden="true"></i></a>
|
||||||
<a routerLink="/posts"><i class="text-secondary fa fa-sticky-note fa-fw fa-2x" tooltip="Posts" placement="bottom" aria-hidden="true"></i></a>
|
<a routerLink="/posts"><i class="fa fa-sticky-note fa-fw fa-2x" tooltip="Posts" placement="bottom" aria-hidden="true"></i></a>
|
||||||
<a routerLink="/cv"><i class="text-secondary fa fa-id-badge fa-fw fa-2x" tooltip="Curriculum Vitae" placement="bottom" aria-hidden="true"></i></a>
|
<a routerLink="/cv"><i class="fa fa-id-badge fa-fw fa-2x" tooltip="Curriculum Vitae" placement="bottom" aria-hidden="true"></i></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -41,3 +41,13 @@
|
|||||||
border-top: 1px solid black;
|
border-top: 1px solid black;
|
||||||
margin: 35px 30px 25px 30px;
|
margin: 35px 30px 25px 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#topmenubuttons {
|
||||||
|
a {
|
||||||
|
color: lightgrey;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
color: darkorange;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -14,6 +14,9 @@ import { PosttypepipePipe } from './pipes/posttypepipe.pipe';
|
|||||||
import { TooltipModule } from 'ngx-bootstrap/tooltip';
|
import { TooltipModule } from 'ngx-bootstrap/tooltip';
|
||||||
import {SimpledatePipe} from './pipes/simpledate.pipe';
|
import {SimpledatePipe} from './pipes/simpledate.pipe';
|
||||||
import { PosttagComponent } from './components/post/posttag/posttag.component';
|
import { PosttagComponent } from './components/post/posttag/posttag.component';
|
||||||
|
import { ButtonsModule } from 'ngx-bootstrap/buttons';
|
||||||
|
import {FormsModule} from '@angular/forms';
|
||||||
|
import {StateService} from './services/state.service';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
@ -30,9 +33,11 @@ import { PosttagComponent } from './components/post/posttag/posttag.component';
|
|||||||
BrowserModule,
|
BrowserModule,
|
||||||
AppRoutingModule,
|
AppRoutingModule,
|
||||||
HttpClientModule,
|
HttpClientModule,
|
||||||
TooltipModule.forRoot()
|
FormsModule,
|
||||||
|
TooltipModule.forRoot(),
|
||||||
|
ButtonsModule.forRoot()
|
||||||
],
|
],
|
||||||
providers: [DataloaderService],
|
providers: [DataloaderService, StateService],
|
||||||
bootstrap: [AppComponent]
|
bootstrap: [AppComponent]
|
||||||
})
|
})
|
||||||
export class AppModule { }
|
export class AppModule { }
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
.blocktitle {
|
.blocktitle {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 150%;
|
font-size: 150%;
|
||||||
border-bottom: 1px dotted black;
|
border-bottom: 1px solid lightgrey;
|
||||||
margin: 0px 30px 0px 30px;
|
margin: 0px 30px 0px 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -19,7 +19,7 @@ export class CvComponent implements OnInit {
|
|||||||
.setLanguage("nl")
|
.setLanguage("nl")
|
||||||
.setEmployer('Universiteit Gent')
|
.setEmployer('Universiteit Gent')
|
||||||
.setTitle('Doctor in de ingenieurswetenschappen: computerwetenschappen')
|
.setTitle('Doctor in de ingenieurswetenschappen: computerwetenschappen')
|
||||||
.setDescription('Het doctoraatswerk getiteld "XPath-gebaseerde informatie-extractie" behandelt het extraheren van informatie uit semi-gestructureerde documenten zoals HTML, gebruik makend van XPath.')
|
.setDescription('Manuscript: "XPath-gebaseerde informatie-extractie" - informatie extraheren uit semi-gestructureerde documenten zoals HTML, gebruik makend van XPath')
|
||||||
.setFromYear(2010)
|
.setFromYear(2010)
|
||||||
.setToYear(2017)
|
.setToYear(2017)
|
||||||
.setIconName("assets/images/ugent-icon.png"),
|
.setIconName("assets/images/ugent-icon.png"),
|
||||||
|
|||||||
@ -8,7 +8,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="post-tags">
|
<div class="post-tags">
|
||||||
<div class="post-tag" *ngFor="let tag of post.tags">
|
<div class="post-tag" *ngFor="let tag of post.tags">
|
||||||
<app-posttag [tag] = tag></app-posttag>
|
<app-posttag [tag]=tag [class.highlight]="isActiveTag(tag)"></app-posttag>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -41,3 +41,12 @@
|
|||||||
padding-right: 25px;
|
padding-right: 25px;
|
||||||
text-align: justify;
|
text-align: justify;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.post-tag {
|
||||||
|
|
||||||
|
color: lightgrey;
|
||||||
|
|
||||||
|
.highlight {
|
||||||
|
color: grey;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import {Component, OnInit, Input, ViewChild, ElementRef} from '@angular/core';
|
import {Component, OnInit, Input, ViewChild, ElementRef} from '@angular/core';
|
||||||
import { Post } from 'app/model/post';
|
import { Post } from 'app/model/post';
|
||||||
import { DataloaderService } from 'app/services/dataloader.service';
|
import { DataloaderService } from 'app/services/dataloader.service';
|
||||||
|
import {StateService} from '../../services/state.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-post',
|
selector: 'app-post',
|
||||||
@ -12,7 +13,7 @@ export class PostComponent implements OnInit {
|
|||||||
@Input() post: Post;
|
@Input() post: Post;
|
||||||
@ViewChild('htmlcontainer') htmlContainer: ElementRef;
|
@ViewChild('htmlcontainer') htmlContainer: ElementRef;
|
||||||
|
|
||||||
constructor(private dataloaderService: DataloaderService) { }
|
constructor(private dataloaderService: DataloaderService, private stateService:StateService) { }
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
// TODO load the relevant HTML file!
|
// TODO load the relevant HTML file!
|
||||||
@ -30,4 +31,8 @@ export class PostComponent implements OnInit {
|
|||||||
|
|
||||||
console.log('PostComponent.ngOnInit is done.');
|
console.log('PostComponent.ngOnInit is done.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isActiveTag(tag:string):boolean {
|
||||||
|
return this.stateService.isActiveTag(tag);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
<div [ngSwitch]="tag" title="{{tag}}">
|
<div [ngSwitch]="tag" [class.highlight]="highlight">
|
||||||
<ng-template [ngSwitchCase]= "'tech'"><i class="fa fa-wrench"></i></ng-template>
|
<ng-template [ngSwitchCase]= "'tech'"><i class="fa fa-wrench"></i></ng-template>
|
||||||
<ng-template [ngSwitchCase]= "'project'"><i class="fa fa-map"></i></ng-template>
|
<ng-template [ngSwitchCase]= "'project'"><i class="fa fa-map"></i></ng-template>
|
||||||
<ng-template ngSwitchDefault><i class="fa fa-question-circle"></i></ng-template>
|
<ng-template ngSwitchDefault><i class="fa fa-question-circle"></i></ng-template>
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import {Component, Input, OnInit} from '@angular/core';
|
import {Component, Input, OnInit} from '@angular/core';
|
||||||
import {Post} from '../../../model/post';
|
import {Post} from '../../../model/post';
|
||||||
|
import {StateService} from '../../../services/state.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-posttag',
|
selector: 'app-posttag',
|
||||||
@ -9,6 +10,7 @@ import {Post} from '../../../model/post';
|
|||||||
export class PosttagComponent implements OnInit {
|
export class PosttagComponent implements OnInit {
|
||||||
|
|
||||||
@Input() tag: string;
|
@Input() tag: string;
|
||||||
|
@Input() highlight: boolean;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,12 @@
|
|||||||
<div>
|
<div id="tag-filter-buttons-container">
|
||||||
<app-post *ngFor='let post of posts' [post]="post"></app-post>
|
<div class="btn-group tag-filter-buttons">
|
||||||
|
<label class="btn btn-primary" *ngFor="let tag of tags" (click)="toggleTag(tag)" [class.active]="isActiveTag(tag)"
|
||||||
|
data-toggle="button" title="Toggle {{tag}} posts">
|
||||||
|
<app-posttag [tag]=tag></app-posttag>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<app-post *ngFor='let post of postsToDisplay()' [post]="post"></app-post>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
26
src/app/components/posts/posts.component.scss
Normal file
26
src/app/components/posts/posts.component.scss
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#tag-filter-buttons-container {
|
||||||
|
text-align: center;
|
||||||
|
margin-top: -16pt;
|
||||||
|
margin-bottom: 12pt;
|
||||||
|
|
||||||
|
.btn.active {
|
||||||
|
color: grey;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn:hover {
|
||||||
|
color: darkorange;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.active:hover {
|
||||||
|
color: darkgoldenrod;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
color: lightgrey;
|
||||||
|
background-color: white;
|
||||||
|
border: none;
|
||||||
|
padding: 0pt 3pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,5 +1,6 @@
|
|||||||
import {Component, OnDestroy, OnInit} from '@angular/core';
|
import {Component, OnDestroy, OnInit} from '@angular/core';
|
||||||
import { DataloaderService } from 'app/services/dataloader.service';
|
import { DataloaderService } from 'app/services/dataloader.service';
|
||||||
|
import {StateService} from '../../services/state.service';
|
||||||
import { Post } from '../../model/post';
|
import { Post } from '../../model/post';
|
||||||
|
|
||||||
import 'rxjs/add/operator/map';
|
import 'rxjs/add/operator/map';
|
||||||
@ -11,7 +12,7 @@ import 'rxjs/add/operator/distinct';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'app-posts',
|
selector: 'app-posts',
|
||||||
templateUrl: './posts.component.html',
|
templateUrl: './posts.component.html',
|
||||||
styleUrls: ['./posts.component.css']
|
styleUrls: ['./posts.component.scss']
|
||||||
})
|
})
|
||||||
export class PostsComponent implements OnInit, OnDestroy {
|
export class PostsComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
@ -21,8 +22,9 @@ export class PostsComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
posts:Post[];
|
posts:Post[];
|
||||||
|
tags = new Array<string>();
|
||||||
|
|
||||||
constructor(private dataloaderService:DataloaderService) { }
|
constructor(private dataloaderService:DataloaderService, private stateService:StateService) { }
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
console.log('PostsComponent ngOnInit()');
|
console.log('PostsComponent ngOnInit()');
|
||||||
@ -32,8 +34,18 @@ export class PostsComponent implements OnInit, OnDestroy {
|
|||||||
//TODO fix this!!!
|
//TODO fix this!!!
|
||||||
posts2.subscribe(p => {
|
posts2.subscribe(p => {
|
||||||
this.posts = p;
|
this.posts = p;
|
||||||
console.log('dataloaderService.getPosts() call got back! '+p);
|
|
||||||
console.log('posts size: '+p.length);
|
//figure out the different tags so we can filter on them
|
||||||
|
let temptags = new Array<string>();
|
||||||
|
this.posts.forEach(p=>p.tags.forEach(t=>temptags.push(t)));
|
||||||
|
console.log(temptags);
|
||||||
|
//copy the temptags into the tags array, don't include duplicates
|
||||||
|
temptags.forEach(tt=> {
|
||||||
|
if(this.tags.indexOf(tt)==-1)
|
||||||
|
this.tags.push(tt)
|
||||||
|
});
|
||||||
|
//sort the array
|
||||||
|
this.tags.sort((a,b)=>a.localeCompare(b));
|
||||||
});
|
});
|
||||||
console.log('PostsComponent ngOnInit() is done');
|
console.log('PostsComponent ngOnInit() is done');
|
||||||
}
|
}
|
||||||
@ -41,4 +53,26 @@ export class PostsComponent implements OnInit, OnDestroy {
|
|||||||
filterOnType(type:String): void {
|
filterOnType(type:String): void {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
postsToDisplay():Post[] {
|
||||||
|
//console.log('postsToDisplay called');
|
||||||
|
let res = new Array<Post>();
|
||||||
|
if(this.posts == null)
|
||||||
|
return res;
|
||||||
|
for(let post of this.posts) {
|
||||||
|
if(this.stateService.shouldDisplay(post))
|
||||||
|
res.push(post);
|
||||||
|
}
|
||||||
|
//console.log('displaying: '+res.length);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
toggleTag(tag: string) {
|
||||||
|
this.stateService.toggleTag(tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
isActiveTag(tag: string) : boolean {
|
||||||
|
return this.stateService.isActiveTag(tag);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -50,7 +50,7 @@ export class DataloaderService {
|
|||||||
const url = 'assets/post/' + id + '/full.html';
|
const url = 'assets/post/' + id + '/full.html';
|
||||||
|
|
||||||
// console.log('fetching: '+url);
|
// console.log('fetching: '+url);
|
||||||
console.log('getPost called: '+url);
|
//console.log('getPost called: '+url);
|
||||||
|
|
||||||
return this.http.get(url, {responseType: 'text'});
|
return this.http.get(url, {responseType: 'text'});
|
||||||
}
|
}
|
||||||
|
|||||||
15
src/app/services/state.service.spec.ts
Normal file
15
src/app/services/state.service.spec.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { TestBed, inject } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { StateService } from './state.service';
|
||||||
|
|
||||||
|
describe('StateService', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
providers: [StateService]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', inject([StateService], (service: StateService) => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
}));
|
||||||
|
});
|
||||||
57
src/app/services/state.service.ts
Normal file
57
src/app/services/state.service.ts
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import {Post} from '../model/post';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class StateService {
|
||||||
|
|
||||||
|
//this keeps track of which type is enabled / disabled
|
||||||
|
tagFilter:any = [];
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
shouldDisplay(post:Post): boolean {
|
||||||
|
//check whether all filters are true or false: that case, just show everything
|
||||||
|
let foundTrue:boolean = false;
|
||||||
|
let foundFalse:boolean = false;
|
||||||
|
for(let tag of Object.keys(this.tagFilter)) {
|
||||||
|
if(this.tagFilter[tag] === true)
|
||||||
|
foundTrue = true;
|
||||||
|
if(this.tagFilter[tag] === false)
|
||||||
|
foundFalse = true;
|
||||||
|
}
|
||||||
|
// console.log('foundFalse: '+foundFalse);
|
||||||
|
// console.log('foundTrue: '+foundTrue);
|
||||||
|
if(!foundTrue && foundFalse)
|
||||||
|
return true;
|
||||||
|
if(!foundTrue && !foundFalse)
|
||||||
|
//some weird case, just show everything
|
||||||
|
return true;
|
||||||
|
|
||||||
|
//check whether the post should be displayed
|
||||||
|
for(let tag of Object.keys(this.tagFilter)) {
|
||||||
|
if(post.tags.indexOf(tag)!=-1 && this.tagFilter[tag]===true) {
|
||||||
|
//found the tag and its filter is enabled
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
isActiveTag(tag:string):boolean {
|
||||||
|
console.log('isActive');
|
||||||
|
console.log(this.tagFilter);
|
||||||
|
return this.tagFilter[tag]===true;
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleTag(tag: string) {
|
||||||
|
console.log('toggle');
|
||||||
|
console.log(this.tagFilter);
|
||||||
|
if(this.tagFilter[tag]==null)
|
||||||
|
this.tagFilter[tag] = true;
|
||||||
|
else
|
||||||
|
this.tagFilter[tag] = !this.tagFilter[tag];
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user