Back in the saddle.

This commit is contained in:
Joachim Nielandt 2018-03-25 14:35:44 +02:00
parent bb4e3e51c0
commit d03380c9fa
24 changed files with 248 additions and 148 deletions

View File

@ -12,8 +12,6 @@ export class HomeComponent implements OnInit {
constructor(private route: ActivatedRoute, private stateService: StateService) { }
ngOnInit() {
// fix up the language, fetch it from the route!
this.stateService.getLanguageFromRoute(this.route.parent).subscribe(language => {console.log('homecomp gets: ' + language); });
}
}

View File

@ -1,5 +1,5 @@
import {Component, Input, OnInit} from '@angular/core';
import {ActivatedRoute} from '@angular/router';
import {ActivatedRoute, NavigationEnd, Router} from '@angular/router';
import {StateService} from '../../services/state.service';
@Component({
@ -21,36 +21,31 @@ export class LanguagetoggleComponent implements OnInit {
*/
private show = false;
constructor(private route: ActivatedRoute, private stateService: StateService) {
constructor(private router: Router, private route: ActivatedRoute, private stateService: StateService) {
}
ngOnInit() {
this.stateService.getLanguageFromRoute(this.route).subscribe(lang => {
if(lang==null) {
console.log('language is null from first level route, ignoring');
return;
}
console.log('languagetoggle gets first level lang: '+lang);
if (lang === this.language) {
console.log('equalled (first level of route)! showing the component' + this.language);
this.show = true;
} else {
this.show = false;
}
});
this.stateService.getLanguageFromRoute(this.route.parent).subscribe(lang => {
if(lang==null) {
console.log('language is null from parent level route, ignoring');
return;
}
console.log('languagetoggle gets parent level lang: '+lang);
if (lang === this.language) {
console.log('equalled (parent level of route)! showing the component ' + this.language);
this.show = true;
} else {
this.show = false;
}
this.route.pathFromRoot.forEach(p => {
this.router.events.filter(e => e instanceof NavigationEnd).subscribe(e => {
console.log('language toggle is detecting a navigation end: have to update values, things might have changed!');
this.updateValues();
});
});
}
private updateValues() {
const lang = this.stateService.getLanguage();
if (lang == null) {
console.log('languagetoggle: language is null from stateservice, ignoring');
return;
}
console.log('languagetoggle gets lang: ' + lang);
if (lang === this.language) {
console.log('languagetoggle: showing the component ' + lang);
this.show = true;
} else {
this.show = false;
}
}
}

View File

@ -4,7 +4,7 @@
{{post.created_timestamp | simpledate}}
</div>
<div class="post-title">
{{post.title}}
{{getPostTitle()}}
</div>
<div class="post-tags">
<div class="post-tag" *ngFor="let tag of post.tags">

View File

@ -13,19 +13,19 @@ export class PostComponent implements OnInit {
@Input() post: Post;
@ViewChild('htmlcontainer') htmlContainer: ElementRef;
constructor(private dataloaderService: DataloaderService, private stateService:StateService) { }
constructor(private dataloaderService: DataloaderService, private stateService: StateService) { }
ngOnInit() {
// TODO load the relevant HTML file!
// console.log('post component has inited: '+this.post.id);
// console.log(this.post);
//console.log('PostComponent is loading: '+this.post.id);
//console.log(this.post);
// console.log('PostComponent is loading: '+this.post.id);
// console.log(this.post);
this.dataloaderService.getPost(this.post.id).subscribe(content => {
//console.log('PostComponent got content for '+this.post.id);
//this is not the cause of the memory leak:\
this.dataloaderService.getFullHtml(this.post, this.stateService.getLanguage()).subscribe(content => {
// console.log('PostComponent got content for '+this.post.id);
// this is not the cause of the memory leak:\
this.htmlContainer.nativeElement.innerHTML = content;
});
@ -35,4 +35,8 @@ export class PostComponent implements OnInit {
isActiveTag(tag:string):boolean {
return this.stateService.isActiveTag(tag);
}
getPostTitle() {
return this.post.title[this.stateService.getLanguage()];
}
}

View File

@ -1,7 +1,7 @@
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/merge';
@ -16,53 +16,66 @@ import 'rxjs/add/operator/distinct';
})
export class PostsComponent implements OnInit, OnDestroy {
posts: Post[];
tags = new Array<string>();
constructor(private dataloaderService: DataloaderService, private stateService: StateService) {
}
ngOnDestroy(): void {
console.log('PostsComponent.ngOnDestroy called');
// console.log('PostsComponent.ngOnDestroy called');
}
posts:Post[];
tags = new Array<string>();
constructor(private dataloaderService:DataloaderService, private stateService:StateService) { }
ngOnInit() {
console.log('PostsComponent ngOnInit()');
//fetch the posts
let posts2 = this.dataloaderService.getPosts();
//subscribing means big fat memory leak
//TODO fix this!!!
// console.log('PostsComponent ngOnInit()');
// fetch the posts
const posts2 = this.dataloaderService.getPosts();
// subscribing means big fat memory leak
// TODO fix this!!!
posts2.subscribe(p => {
this.posts = p;
//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)));
const 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)
temptags.forEach(tt => {
if (this.tags.indexOf(tt) == -1) {
this.tags.push(tt)
}
});
//sort the array
this.tags.sort((a,b)=>a.localeCompare(b));
this.tags.sort((a, b) => a.localeCompare(b));
});
console.log('PostsComponent ngOnInit() is done');
}
filterOnType(type:String): void {
filterOnType(type: String): void {
}
postsToDisplay():Post[] {
postsToDisplay(): Post[] {
//console.log('postsToDisplay called');
let res = new Array<Post>();
if(this.posts == null)
const res = new Array<Post>();
if (this.posts == null) {
return res;
for(let post of this.posts) {
if(this.stateService.shouldDisplay(post))
res.push(post);
}
for (const post of this.posts) {
// console.log(post);
if (this.stateService.shouldDisplay(post)) {
// console.log('we should display this');
// also check the language!
// console.log(post.languages + ' ' + this.stateService.getLanguage());
if (post.languages !== undefined && post.languages.indexOf(this.stateService.getLanguage()) >= 0) {
res.push(post);
}
} else {
// console.log('we should not display this');
}
}
//console.log('displaying: '+res.length);
return res;
}
@ -72,7 +85,8 @@ export class PostsComponent implements OnInit, OnDestroy {
this.stateService.toggleTag(tag);
}
isActiveTag(tag: string) : boolean {
isActiveTag(tag: string): boolean {
return this.stateService.isActiveTag(tag);
}
}

View File

@ -18,9 +18,9 @@
<div id="topmenubuttons">
<div class="btn-group mx-auto" role="group">
<!--removed this from the <i: tooltip="Huis" placement="bottom"-->
<a routerLink="/home" (mouseout)="mouseOut('home')" (mouseover)="mouseOver('home')"><i class="fa fa-home fa-fw fa-2x" aria-hidden="true"></i></a>
<a routerLink="/posts" (mouseout)="mouseOut('posts')" (mouseover)="mouseOver('posts')"><i class="fa fa-sticky-note fa-fw fa-2x" aria-hidden="true"></i></a>
<a routerLink="/cv" (mouseout)="mouseOut('cv')" (mouseover)="mouseOver('cv')"><i class="fa fa-id-badge fa-fw fa-2x" aria-hidden="true"></i></a>
<a routerLink="home" (mouseout)="mouseOut('home')" (mouseover)="mouseOver('home')"><i class="fa fa-home fa-fw fa-2x" aria-hidden="true"></i></a>
<a routerLink="posts" (mouseout)="mouseOut('posts')" (mouseover)="mouseOver('posts')"><i class="fa fa-sticky-note fa-fw fa-2x" aria-hidden="true"></i></a>
<a routerLink="cv" (mouseout)="mouseOut('cv')" (mouseover)="mouseOver('cv')"><i class="fa fa-id-badge fa-fw fa-2x" aria-hidden="true"></i></a>
<a (click)="toggleLanguage()" (mouseout)="mouseOut('language setting')" (mouseover)="mouseOver('language setting')"><i class="fa fa-language fa-fw fa-2x" aria-hidden="true"></i></a>
</div>
</div>
@ -31,7 +31,7 @@
<div class="row">
<div class="col-md-8 offset-md-2">
<div class="pagetype">
{{pageType$ | async}}
{{pageType}}
</div>
</div>
</div>

View File

@ -1,5 +1,5 @@
import {Component, OnInit} from '@angular/core';
import {ActivatedRoute, Router} from '@angular/router';
import {ActivatedRoute, NavigationEnd, ParamMap, Router} from '@angular/router';
import {StateService} from '../../services/state.service';
import {Observable} from 'rxjs/Observable';
@ -14,37 +14,67 @@ export class RootComponent implements OnInit {
title = 'Joachim Homepage';
mousingOver: string = null;
pageType$: Observable<string>;
pageType: string;
constructor(private router: Router, private route: ActivatedRoute, private stateService: StateService) {
}
ngOnInit() {
console.log('oninit of root component');
// console.log('oninit of root component');
this.route.paramMap.subscribe(val => console.log(val));
this.stateService.getLanguageFromRoute(this.route).subscribe(val => {console.log('ngoninit root language: ' + val)});
// this.stateService.getLanguageFromRoute(this.route).subscribe(val => {
// console.log('ngoninit root language: ' + val)
// });
this.pageType$ = this.stateService.getLanguageFromRoute(this.route).map(language => {
if (this.router.url.endsWith('posts')) {
return 'Posts';
/**
* Listen to changes in the param map (this is the root level, so will only see changes in 'language'. good!
*/
this.route.paramMap.subscribe((paramMap: ParamMap) => {
const language = paramMap.get('language');
console.log(`root comp listens for parammap: ${language}`)
// console.log('root: parammap changed ' + language);
if (language !== null) {
console.log('the subscriber of root changes the language to '+language);
this.stateService.setLanguage(language, this.route, this.router);
}
if (this.router.url.endsWith('cv')) {
return 'Curriculum Vitae';
}
if (this.router.url.endsWith('home')) {
if (language === 'nl') {
return 'Intro';
} else {
return 'Home';
}
}
return 'Joa did something wrong...'
});
// we listen to a 'navigation end' event -> at that point we need update our pagetype string
this.router.events.filter(event => event instanceof NavigationEnd).subscribe(event => {
// navigated somewhere, got to make sure the pagetype has updated too
this.updatePageType();
});
// do the first update for the page type
this.updatePageType();
}
/**
* Update the pagetype according to the right language and current router url.
*/
updatePageType() {
// console.log('firing update page type');
// console.log(this.router.url);
if (this.router.url.endsWith('posts')) {
this.pageType = 'Posts';
} else if (this.router.url.endsWith('cv')) {
this.pageType = 'Curriculum Vitae';
} else if (this.router.url.endsWith('home')) {
if (this.stateService.getLanguage() === 'nl') {
this.pageType = 'Thuis';
} else {
this.pageType = 'Home';
}
} else {
this.pageType = 'Joa did something wrong...';
}
}
mouseOver(s: string) {
console.log('mouseover!' + s);
// console.log('mouseover!' + s);
this.mousingOver = s;
}
@ -53,14 +83,15 @@ export class RootComponent implements OnInit {
}
toggleLanguage() {
this.stateService.getLanguageFromRoute(this.route).first().subscribe(val => {
if (val === 'nl') {
this.stateService.setLanguage('en', this.route, this.router);
} else if (val === 'en') {
this.stateService.setLanguage('nl', this.route, this.router);
} else {
console.log('Could not toggle the language, pirates stole your tongue.');
}
});
console.log('toggleLanguage called');
if (this.stateService.getLanguage() === 'nl') {
console.log(' > toggle switched to en');
this.stateService.setLanguage('en', this.route, this.router);
} else if (this.stateService.getLanguage() === 'en') {
this.stateService.setLanguage('nl', this.route, this.router);
console.log(' > toggle switched to nl');
} else {
console.log(' > Could not toggle the language, pirates stole your tongue.');
}
}
}

View File

@ -1,12 +1,13 @@
export class Post {
type: string;
languages: string[];
title: any;
id:String;
id: String;
created_timestamp: Date;
tags: string[];
constructor(id:String) {
constructor(id: String) {
this.id = id;
}
}

View File

@ -5,6 +5,7 @@ import { Observable } from 'rxjs/Observable';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import 'rxjs/add/operator/map';
import 'rxjs/add/observable/of';
@Injectable()
export class DataloaderService {
@ -17,11 +18,12 @@ export class DataloaderService {
// fill it up
for (const index in posts) {
const post: any = posts[index];
console.log(post);
// console.log(post);
const temp: Post = new Post(post.id);
temp.title = post.info.title;
temp.type = post.type;
temp.tags = post.info.tags;
temp.languages = post.info.languages;
// console.log('got this timestamp: ' + post.info.created_timestamp);
temp.created_timestamp = new Date(post.info.created_timestamp * 1000);
// console.log('converted it to this: ' + temp.created_timestamp);
@ -37,18 +39,24 @@ export class DataloaderService {
* Fetch the 'full fat' post. This returns HTML content that can be wrapped in any container, no sanitizing done.
* @param filename the filename for which the post needs to be fetched
*/
getPost(id: String): Observable<String> {
getFullHtml(post: Post, language: string): Observable<String> {
const httpOptions = {
headers: new HttpHeaders({ 'Content-Type': 'text/html', 'Accept': 'text/html' })
};
// console.log('launching GET');
const url = 'assets/post/' + id + '/full.html';
// check if the post actually has a filename for the 'full version' and the post is translated to the given language
if (post.languages === undefined) {
console.log(`post with id ${post.id} has no languages defined...`);
return Observable.of('You encounter a pirate without a tongue. Curious.');
}
if (post.languages.indexOf(language) !== 1) {
// language is defined!
const url = `assets/post/${post.id}/full-${language}.html`;
return this.http.get(url, {responseType: 'text'});
} else {
return Observable.of('You encounter a pirate without a tongue. Curious.');
}
// console.log('fetching: '+url);
// console.log('getPost called: '+url);
return this.http.get(url, {responseType: 'text'});
}
}

View File

@ -2,29 +2,29 @@ import {Injectable, OnInit} from '@angular/core';
import {Post} from '../model/post';
import {ActivatedRoute, ParamMap, Router} from '@angular/router';
import 'rxjs/add/operator/filter';
import {Observable} from 'rxjs/Observable';
@Injectable()
export class StateService {
// this keeps track of which type is enabled / disabled
tagFilter: any = [];
private tagFilter: any = [];
private language: string;
constructor() {
}
/**
* Get the language currently set in the router.
*
* @param {ActivatedRoute} route
* @returns {Observable<string>}
*/
getLanguageFromRoute(route: ActivatedRoute): Observable<string> {
return route.paramMap.map((params: ParamMap) => {
const temp = params.get('language');
return temp;
});
}
// /**
// * Get the language currently set in the router.
// *
// * @param {ActivatedRoute} route
// * @returns {Observable<string>}
// */
// getLanguageFromRoute(route: ActivatedRoute): Observable<string> {
// return route.paramMap.map((params: ParamMap) => {
// const temp = params.get('language');
// return temp;
// });
// }
shouldDisplay(post: Post): boolean {
// check whether all filters are true or false: that case, just show everything
@ -48,10 +48,10 @@ export class StateService {
return true;
}
//check whether the post should be displayed
// check whether the post should be displayed
for (const tag of Object.keys(this.tagFilter)) {
if (post.tags.indexOf(tag) != -1 && this.tagFilter[tag] === true) {
//found the tag and its filter is enabled
// found the tag and its filter is enabled
return true;
}
}
@ -75,23 +75,22 @@ export class StateService {
}
}
setLanguage(language: string, route: ActivatedRoute, router: Router) {
console.log('setting language: '+language);
// // check out the current route
// route.pathFromRoot.forEach(path=>{
// console.log(path);
// console.log(path.routeConfig);
// });
router.navigate([language]);
/**
* Get the currently set language.
* @returns {string}
*/
getLanguage() {
return this.language;
}
// route.url.subscribe(segments => {
// console.log(segments);
// //now also do the children
// route.children.forEach(child => {
// child.url.subscribe(childsegment => {
// console.log(childsegment);
// });
// });
// });
setLanguage(language: string, route: ActivatedRoute, router: Router) {
console.log(`want to switch to: ${language} from ${this.language}`)
if (this.language !== language) {
console.log('setting language (triggers navigate): ' + language);
this.language = language;
router.navigate([language]);
} else {
console.log('setting language did nothing: no navigation.')
}
}
}

View File

@ -0,0 +1 @@
<p>Dit gaat over de eerste kast.</p>

View File

@ -1 +1,14 @@
{"created_timestamp": 1515094644.215065, "title": "cupboard", "tags":["project"]}
{
"created_timestamp": 1515094644.215065,
"title": {
"en": "Cupboard",
"nl": "De kast"
},
"tags": [
"project"
],
"languages": [
"nl",
"en"
]
}

View File

@ -1,8 +1,11 @@
<p>It's been on my mind for a while now to create an oldschool homepage. So, here it is. An homage to the old and tried
<p>It's been on my mind for a while now to create an oldschool homepage. So, here it is. An homage to the old and
tried
Web 1.0, whoever thought static web pages were done and dusted is <em>wrong</em>! This will be a collection of some
technical things I want to remind myself about so I don't have to look them up again and again, miscellaneous pictures
technical things I want to remind myself about so I don't have to look them up again and again, miscellaneous
pictures
of projects (in-progress or done) or anything that comes to mind I'd like to share on something other than the usual
social media suspects.</p>
<p>Besides, it's nice to have a minimalistic Angular2/Bootstrap playground to do some styling experiments. I'll probably update
<p>Besides, it's nice to have a minimalistic Angular2/Bootstrap playground to do some styling experiments. I'll
probably update
this thing once in a while. Maybe even use a database, wouldn't <em>that</em> be something...</p>

View File

@ -0,0 +1 @@
<p>Dit moet ik vertalen, de eerste post!</p>

View File

@ -1 +1,11 @@
{"created_timestamp": 1515094679.342938, "title": "Who said Web 1.0 was dead anyway?", "tags":["blog"]}
{
"created_timestamp": 1515094679.342938,
"title": {
"en": "Who said Web 1.0 was dead anyway?",
"nl": "Web 1.0 is niet dood joh!"
},
"tags": [
"blog"
],
"languages": ["nl", "en"]
}

View File

@ -0,0 +1 @@
<p>LXD is pretty cool kerels.</p>

View File

@ -1 +1,11 @@
{"created_timestamp": 1515094644.215333, "title": "some things about lxc in arch", "tags":["tech"]}
{
"created_timestamp": 1515094644.215333,
"title": {
"en": "Some things about LXD",
"nl": "LXD is cool!"
},
"tags": [
"tech"
],
"languages": ["en", "nl"]
}

View File

@ -0,0 +1 @@
<p>Dit is een test post.</p>

View File

@ -1,5 +1,15 @@
{
"created_timestamp": 1515095948.838848,
"title": "Test title",
"tags":["tech", "blog"]
"created_timestamp": 1515095948.838848,
"title": {
"en": "Test title",
"nl": "Test titel!"
},
"tags": [
"tech",
"blog"
],
"languages": [
"nl",
"en"
]
}

View File

@ -1 +1 @@
[{"info": {"created_timestamp": 1515094679.342938, "tags": ["blog"], "title": "Who said Web 1.0 was dead anyway?"}, "id": "first"}, {"info": {"created_timestamp": 1515094644.215065, "tags": ["project"], "title": "cupboard"}, "id": "cupboard1"}, {"info": {"created_timestamp": 1515095948.838848, "tags": ["tech", "blog"], "title": "Test title"}, "id": "test"}, {"info": {"created_timestamp": 1515094644.215333, "tags": ["tech"], "title": "some things about lxc in arch"}, "id": "lxdarch"}]
[{"id": "cupboard1", "info": {"created_timestamp": 1515094644.215065, "title": {"en": "Cupboard", "nl": "De kast"}, "tags": ["project"], "languages": ["nl", "en"]}}, {"id": "first", "info": {"created_timestamp": 1515094679.342938, "title": {"en": "Who said Web 1.0 was dead anyway?", "nl": "Web 1.0 is niet dood joh!"}, "tags": ["blog"], "languages": ["nl", "en"]}}, {"id": "lxdarch", "info": {"created_timestamp": 1515094644.215333, "title": {"en": "Some things about LXD", "nl": "LXD is cool!"}, "tags": ["tech"], "languages": ["en", "nl"]}}, {"id": "test", "info": {"created_timestamp": 1515095948.838848, "title": {"en": "Test title", "nl": "Test titel!"}, "tags": ["tech", "blog"], "languages": ["nl", "en"]}}]

View File

@ -25,7 +25,7 @@ for post in posts:
temp['info'] = d;
# have to write the 'modified date' in the info.json of the post if it's not there yet
if not d.has_key('created_timestamp'):
if 'created_timestamp' not in d:
d['created_timestamp'] = time.time()
# persist it in the json file itself
with open(infofile, 'w') as infooutfile: