Compare commits

..

No commits in common. "master" and "angular.version" have entirely different histories.

778 changed files with 18967 additions and 35916 deletions

13
.editorconfig Normal file
View File

@ -0,0 +1,13 @@
# Editor configuration, see http://editorconfig.org
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
max_line_length = off
trim_trailing_whitespace = false

53
.gitignore vendored
View File

@ -1,27 +1,42 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. # See http://help.github.com/ignore-files/ for more about ignoring files.
# compiled output
/dist
/tmp
/out-tsc
# dependencies # dependencies
/node_modules /node_modules
/.pnp
.pnp.js
# testing # IDEs and editors
/coverage /.idea
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace
# production # IDE - VSCode
/build .vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
# misc # misc
/.sass-cache
/connect.lock
/coverage
/libpeerconnection.log
npm-debug.log
testem.log
/typings
# e2e
/e2e/*.js
/e2e/*.map
# System Files
.DS_Store .DS_Store
.env.local Thumbs.db
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*
*.lock
package-lock.json
.idea

3
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"python.linting.pylintEnabled": false
}

View File

@ -1,70 +1,31 @@
# Getting Started with Create React App # Homepage
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 1.1.2.
## Available Scripts ## Hey, you!
Use the <splitter/> tag for some 'read extra below the jump' posting.
In the project directory, you can run: ## Development server
### `yarn start` Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
Runs the app in the development mode.\ ## Code scaffolding
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
The page will reload if you make edits.\ Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|module`.
You will also see any lint errors in the console.
### `yarn test` ## Build
Launches the test runner in the interactive watch mode.\ Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `-prod` flag for a production build.
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
### `yarn build` ## Running unit tests
Builds the app for production to the `build` folder.\ Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
It correctly bundles React in production mode and optimizes the build for the best performance.
The build is minified and the filenames include the hashes.\ ## Running end-to-end tests
Your app is ready to be deployed!
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).
Before running the tests make sure you are serving the app via `ng serve`.
### `yarn eject` ## Further help
**Note: this is a one-way operation. Once you `eject`, you cant go back!** To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).
If you arent satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point youre on your own.
You dont have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldnt feel obligated to use this feature. However we understand that this tool wouldnt be useful if you couldnt customize it when you are ready for it.
## Learn More
You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
To learn React, check out the [React documentation](https://reactjs.org/).
### Code Splitting
This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting)
### Analyzing the Bundle Size
This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size)
### Making a Progressive Web App
This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app)
### Advanced Configuration
This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration)
### Deployment
This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment)
### `yarn build` fails to minify
This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify)

132
angular.json Normal file
View File

@ -0,0 +1,132 @@
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"homepage": {
"root": "",
"sourceRoot": "src",
"projectType": "application",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist",
"index": "src/index.html",
"main": "src/main.ts",
"tsConfig": "src/tsconfig.app.json",
"polyfills": "src/polyfills.ts",
"assets": [
"src/assets",
"src/favicon.ico"
],
"styles": [
"node_modules/bootstrap/scss/bootstrap.scss",
"src/styles.scss",
"node_modules/font-awesome/css/font-awesome.min.css"
],
"scripts": []
},
"configurations": {
"production": {
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"aot": true,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
]
}
}
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "homepage:build"
},
"configurations": {
"production": {
"browserTarget": "homepage:build:production"
}
}
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "homepage:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "src/test.ts",
"karmaConfig": "./karma.conf.js",
"polyfills": "src/polyfills.ts",
"tsConfig": "src/tsconfig.spec.json",
"scripts": [],
"styles": [
"node_modules/bootstrap/scss/bootstrap.scss",
"src/styles.scss",
"node_modules/font-awesome/css/font-awesome.min.css"
],
"assets": [
"src/assets",
"src/favicon.ico"
]
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"src/tsconfig.app.json",
"src/tsconfig.spec.json"
],
"exclude": []
}
}
}
},
"homepage-e2e": {
"root": "",
"sourceRoot": "",
"projectType": "application",
"architect": {
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
"options": {
"protractorConfig": "./protractor.conf.js",
"devServerTarget": "homepage:serve"
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"e2e/tsconfig.e2e.json"
],
"exclude": []
}
}
}
}
},
"defaultProject": "homepage",
"schematics": {
"@schematics/angular:component": {
"prefix": "app",
"styleext": "scss"
},
"@schematics/angular:directive": {
"prefix": "app"
}
}
}

9
deploy.sh Executable file
View File

@ -0,0 +1,9 @@
#!/bin/bash
# remove --no-aot, this helped to alleviate error of library, but not necessary in this version?
# ng build --prod --env=prod
ng build --prod
rsync -az -e ssh --progress --exclude dist/.git --delete dist/* root@nielandtnginx:/www/
# overwrite the local config with the remote config
# ssh disbiomewebserver mv /var/www/html/app/config/appconfig.remote.ts /var/www/html/app/config/appconfig.ts
# recompile everything
# ssh disbiomewebserver 'cd /var/www/html ; npm run tsc

53
design/assets/avatar.svg Normal file
View File

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 482.9 482.9" style="enable-background:new 0 0 482.9 482.9;" xml:space="preserve">
<g>
<g>
<path d="M239.7,260.2c0.5,0,1,0,1.6,0c0.2,0,0.4,0,0.6,0c0.3,0,0.7,0,1,0c29.3-0.5,53-10.8,70.5-30.5
c38.5-43.4,32.1-117.8,31.4-124.9c-2.5-53.3-27.7-78.8-48.5-90.7C280.8,5.2,262.7,0.4,242.5,0h-0.7c-0.1,0-0.3,0-0.4,0h-0.6
c-11.1,0-32.9,1.8-53.8,13.7c-21,11.9-46.6,37.4-49.1,91.1c-0.7,7.1-7.1,81.5,31.4,124.9C186.7,249.4,210.4,259.7,239.7,260.2z
M164.6,107.3c0-0.3,0.1-0.6,0.1-0.8c3.3-71.7,54.2-79.4,76-79.4h0.4c0.2,0,0.5,0,0.8,0c27,0.6,72.9,11.6,76,79.4
c0,0.3,0,0.6,0.1,0.8c0.1,0.7,7.1,68.7-24.7,104.5c-12.6,14.2-29.4,21.2-51.5,21.4c-0.2,0-0.3,0-0.5,0l0,0c-0.2,0-0.3,0-0.5,0
c-22-0.2-38.9-7.2-51.4-21.4C157.7,176.2,164.5,107.9,164.6,107.3z"/>
<path d="M446.8,383.6c0-0.1,0-0.2,0-0.3c0-0.8-0.1-1.6-0.1-2.5c-0.6-19.8-1.9-66.1-45.3-80.9c-0.3-0.1-0.7-0.2-1-0.3
c-45.1-11.5-82.6-37.5-83-37.8c-6.1-4.3-14.5-2.8-18.8,3.3c-4.3,6.1-2.8,14.5,3.3,18.8c1.7,1.2,41.5,28.9,91.3,41.7
c23.3,8.3,25.9,33.2,26.6,56c0,0.9,0,1.7,0.1,2.5c0.1,9-0.5,22.9-2.1,30.9c-16.2,9.2-79.7,41-176.3,41
c-96.2,0-160.1-31.9-176.4-41.1c-1.6-8-2.3-21.9-2.1-30.9c0-0.8,0.1-1.6,0.1-2.5c0.7-22.8,3.3-47.7,26.6-56
c49.8-12.8,89.6-40.6,91.3-41.7c6.1-4.3,7.6-12.7,3.3-18.8c-4.3-6.1-12.7-7.6-18.8-3.3c-0.4,0.3-37.7,26.3-83,37.8
c-0.4,0.1-0.7,0.2-1,0.3c-43.4,14.9-44.7,61.2-45.3,80.9c0,0.9,0,1.7-0.1,2.5c0,0.1,0,0.2,0,0.3c-0.1,5.2-0.2,31.9,5.1,45.3
c1,2.6,2.8,4.8,5.2,6.3c3,2,74.9,47.8,195.2,47.8s192.2-45.9,195.2-47.8c2.3-1.5,4.2-3.7,5.2-6.3
C447,415.5,446.9,388.8,446.8,383.6z"/>
</g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

754
design/drawing.svg Normal file
View File

@ -0,0 +1,754 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="210mm"
height="297mm"
viewBox="0 0 744.09448819 1052.3622047"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="drawing.svg">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.318381"
inkscape:cx="376.81707"
inkscape:cy="708.22257"
inkscape:document-units="px"
inkscape:current-layer="g4184"
showgrid="false"
inkscape:snap-bbox="true"
inkscape:object-nodes="true"
inkscape:window-width="1440"
inkscape:window-height="836"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:object-paths="true"
inkscape:snap-nodes="true"
inkscape:snap-global="false" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Top"
inkscape:groupmode="layer"
id="layer1"
style="display:inline"
sodipodi:insensitive="true">
<g
id="g4151"
transform="translate(60.689967,-62.629458)">
<text
sodipodi:linespacing="125%"
id="text4139"
y="124.03202"
x="179.80716"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:40px;line-height:125%;font-family:'Accanthis ADF Std';-inkscape-font-specification:'Accanthis ADF Std';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="124.03202"
x="179.80716"
id="tspan4141"
sodipodi:role="line">Joachim</tspan></text>
<text
sodipodi:linespacing="125%"
id="text4143"
y="124.03202"
x="321.03418"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:40px;line-height:125%;font-family:'Accanthis ADF Std';-inkscape-font-specification:'Accanthis ADF Std';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:90px;font-family:'Accanthis ADF Std';-inkscape-font-specification:'Accanthis ADF Std'"
y="124.03202"
x="321.03418"
id="tspan4145"
sodipodi:role="line">.</tspan></text>
<text
sodipodi:linespacing="125%"
id="text4147"
y="124.03202"
x="340.27786"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:40px;line-height:125%;font-family:'Accanthis ADF Std';-inkscape-font-specification:'Accanthis ADF Std';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:30px;font-family:'Accanthis ADF Std';-inkscape-font-specification:'Accanthis ADF Std'"
y="124.03202"
x="340.27786"
id="tspan4149"
sodipodi:role="line">Nielandt</tspan></text>
</g>
<g
id="g3547"
transform="matrix(0.67026034,0,0,0.67026034,126.98448,5.2324395)"
style="fill:#666666">
<g
transform="matrix(0.07424266,0,0,0.07424266,307.41701,114.36646)"
id="g4273"
style="fill:#666666">
<g
id="g4207"
style="fill:#666666">
<g
id="g4209"
style="fill:#666666">
<path
inkscape:connector-curvature="0"
d="m 387.79,439.815 c -5.824,-0.597 -11.093,3.755 -11.627,9.621 l -1.749,18.731 -117.184,-13.376 c -5.717,-0.704 -11.157,3.52 -11.819,9.387 -0.683,5.845 3.541,11.136 9.387,11.797 l 128,14.635 c 0.405,0.043 0.811,0.064 1.216,0.064 2.432,0 4.821,-0.832 6.72,-2.389 2.219,-1.792 3.627,-4.416 3.904,-7.275 l 2.773,-29.568 c 0.555,-5.867 -3.776,-11.073 -9.621,-11.627 z"
id="path4211"
style="fill:#666666" />
</g>
</g>
<g
id="g4213"
style="fill:#666666">
<g
id="g4215"
style="fill:#666666">
<path
inkscape:connector-curvature="0"
d="M 257.272,109.255 54.606,85.404 C 48.547,84.7 43.47,88.86 42.745,94.684 L 0.078,436.017 c -0.341,2.816 0.448,5.675 2.219,7.915 1.749,2.24 4.331,3.691 7.168,4.011 l 114.56,13.099 c 0.427,0.043 0.811,0.064 1.237,0.064 5.333,0 9.963,-4.011 10.581,-9.451 0.683,-5.845 -3.541,-11.136 -9.387,-11.797 L 22.606,427.975 62.627,107.826 254.776,130.439 c 6.101,0.789 11.179,-3.499 11.84,-9.344 0.704,-5.846 -3.498,-11.158 -9.344,-11.84 z"
id="path4217"
style="fill:#666666" />
</g>
</g>
<g
id="g4219"
style="fill:#666666">
<g
id="g4221"
style="fill:#666666">
<path
inkscape:connector-curvature="0"
d="m 370.211,99.143 c -4.16,-4.16 -10.923,-4.16 -15.083,0 l -53.333,53.333 c -4.16,4.16 -4.16,10.923 0,15.083 2.091,2.069 4.821,3.115 7.552,3.115 2.731,0 5.461,-1.045 7.531,-3.115 l 53.333,-53.333 c 4.16,-4.161 4.16,-10.923 0,-15.083 z"
id="path4223"
style="fill:#666666" />
</g>
</g>
<g
id="g4225"
style="fill:#666666">
<g
id="g4227"
style="fill:#666666">
<path
inkscape:connector-curvature="0"
d="M 511.928,436.039 469.262,94.705 c -0.725,-5.824 -6.101,-9.963 -11.84,-9.28 l -29.397,3.456 c -5.867,0.683 -10.048,5.995 -9.344,11.84 0.683,5.845 6.016,10.069 11.84,9.344 l 18.88,-2.219 40.021,320.107 -351.808,40.213 -30.016,-320.128 260.544,-30.635 c 5.867,-0.683 10.048,-5.995 9.344,-11.84 -0.683,-5.845 -6.101,-10.176 -11.84,-9.344 L 94.755,128.092 c -5.739,0.661 -9.899,5.803 -9.365,11.584 l 32,341.333 c 0.277,2.837 1.685,5.483 3.904,7.275 1.899,1.557 4.288,2.389 6.72,2.389 0.405,0 0.811,-0.021 1.195,-0.043 l 373.333,-42.667 c 2.837,-0.341 5.419,-1.771 7.168,-4.011 1.77,-2.239 2.581,-5.097 2.218,-7.913 z"
id="path4229"
style="fill:#666666" />
</g>
</g>
<g
id="g4231"
style="fill:#666666">
<g
id="g4233"
style="fill:#666666">
<path
inkscape:connector-curvature="0"
d="m 394.68,21.34 c -29.419,0 -53.333,23.936 -53.333,53.333 0,29.397 23.915,53.333 53.333,53.333 29.418,0 53.333,-23.936 53.333,-53.333 0,-29.397 -23.914,-53.333 -53.333,-53.333 z m 0,85.333 c -17.643,0 -32,-14.357 -32,-32 0,-17.643 14.357,-32 32,-32 17.643,0 32,14.357 32,32 0,17.643 -14.357,32 -32,32 z"
id="path4235"
style="fill:#666666" />
</g>
</g>
<g
id="g4237"
style="fill:#666666" />
<g
id="g4239"
style="fill:#666666" />
<g
id="g4241"
style="fill:#666666" />
<g
id="g4243"
style="fill:#666666" />
<g
id="g4245"
style="fill:#666666" />
<g
id="g4247"
style="fill:#666666" />
<g
id="g4249"
style="fill:#666666" />
<g
id="g4251"
style="fill:#666666" />
<g
id="g4253"
style="fill:#666666" />
<g
id="g4255"
style="fill:#666666" />
<g
id="g4257"
style="fill:#666666" />
<g
id="g4259"
style="fill:#666666" />
<g
id="g4261"
style="fill:#666666" />
<g
id="g4263"
style="fill:#666666" />
<g
id="g4265"
style="fill:#666666" />
</g>
<g
transform="matrix(0.07425577,0,0,0.07425577,350.47043,115.69155)"
id="g4350"
style="fill:#666666">
<g
id="g4306"
style="fill:#666666">
<g
id="g4308"
style="fill:#666666">
<path
inkscape:connector-curvature="0"
d="m 239.7,260.2 c 0.5,0 1,0 1.6,0 0.2,0 0.4,0 0.6,0 0.3,0 0.7,0 1,0 29.3,-0.5 53,-10.8 70.5,-30.5 38.5,-43.4 32.1,-117.8 31.4,-124.9 C 342.3,51.5 317.1,26 296.3,14.1 280.8,5.2 262.7,0.4 242.5,0 l -0.7,0 c -0.1,0 -0.3,0 -0.4,0 l -0.6,0 c -11.1,0 -32.9,1.8 -53.8,13.7 -21,11.9 -46.6,37.4 -49.1,91.1 -0.7,7.1 -7.1,81.5 31.4,124.9 17.4,19.7 41.1,30 70.4,30.5 z M 164.6,107.3 c 0,-0.3 0.1,-0.6 0.1,-0.8 3.3,-71.7 54.2,-79.4 76,-79.4 l 0.4,0 c 0.2,0 0.5,0 0.8,0 27,0.6 72.9,11.6 76,79.4 0,0.3 0,0.6 0.1,0.8 0.1,0.7 7.1,68.7 -24.7,104.5 -12.6,14.2 -29.4,21.2 -51.5,21.4 -0.2,0 -0.3,0 -0.5,0 l 0,0 c -0.2,0 -0.3,0 -0.5,0 -22,-0.2 -38.9,-7.2 -51.4,-21.4 -31.7,-35.6 -24.9,-103.9 -24.8,-104.5 z"
id="path4310"
style="fill:#666666" />
<path
inkscape:connector-curvature="0"
d="m 446.8,383.6 c 0,-0.1 0,-0.2 0,-0.3 0,-0.8 -0.1,-1.6 -0.1,-2.5 -0.6,-19.8 -1.9,-66.1 -45.3,-80.9 -0.3,-0.1 -0.7,-0.2 -1,-0.3 -45.1,-11.5 -82.6,-37.5 -83,-37.8 -6.1,-4.3 -14.5,-2.8 -18.8,3.3 -4.3,6.1 -2.8,14.5 3.3,18.8 1.7,1.2 41.5,28.9 91.3,41.7 23.3,8.3 25.9,33.2 26.6,56 0,0.9 0,1.7 0.1,2.5 0.1,9 -0.5,22.9 -2.1,30.9 -16.2,9.2 -79.7,41 -176.3,41 C 145.3,456 81.4,424.1 65.1,414.9 63.5,406.9 62.8,393 63,384 c 0,-0.8 0.1,-1.6 0.1,-2.5 0.7,-22.8 3.3,-47.7 26.6,-56 49.8,-12.8 89.6,-40.6 91.3,-41.7 6.1,-4.3 7.6,-12.7 3.3,-18.8 -4.3,-6.1 -12.7,-7.6 -18.8,-3.3 -0.4,0.3 -37.7,26.3 -83,37.8 -0.4,0.1 -0.7,0.2 -1,0.3 -43.4,14.9 -44.7,61.2 -45.3,80.9 0,0.9 0,1.7 -0.1,2.5 0,0.1 0,0.2 0,0.3 -0.1,5.2 -0.2,31.9 5.1,45.3 1,2.6 2.8,4.8 5.2,6.3 3,2 74.9,47.8 195.2,47.8 120.3,0 192.2,-45.9 195.2,-47.8 2.3,-1.5 4.2,-3.7 5.2,-6.3 5,-13.3 4.9,-40 4.8,-45.2 z"
id="path4312"
style="fill:#666666" />
</g>
</g>
<g
id="g4314"
style="fill:#666666" />
<g
id="g4316"
style="fill:#666666" />
<g
id="g4318"
style="fill:#666666" />
<g
id="g4320"
style="fill:#666666" />
<g
id="g4322"
style="fill:#666666" />
<g
id="g4324"
style="fill:#666666" />
<g
id="g4326"
style="fill:#666666" />
<g
id="g4328"
style="fill:#666666" />
<g
id="g4330"
style="fill:#666666" />
<g
id="g4332"
style="fill:#666666" />
<g
id="g4334"
style="fill:#666666" />
<g
id="g4336"
style="fill:#666666" />
<g
id="g4338"
style="fill:#666666" />
<g
id="g4340"
style="fill:#666666" />
<g
id="g4342"
style="fill:#666666" />
</g>
<g
transform="matrix(0.07045726,0,0,0.07045726,388.64746,115.85948)"
id="g3527"
style="fill:#666666">
<g
id="g3485"
style="fill:#666666">
<g
id="g3487"
style="fill:#666666">
<path
inkscape:connector-curvature="0"
d="m 498.255,367.242 c -1.282,-2.428 -3.566,-4.171 -6.246,-4.766 -0.676,-0.15 -54.965,-12.124 -124.16,-21.685 -0.097,-0.315 -0.163,-0.633 -0.296,-0.942 -30.509,-71.187 -40.612,-71.187 -46.04,-71.187 -6.543,0 -39.05,6.681 -65.514,12.362 l 0,-68.518 c 0.396,0 0.79,-0.031 1.181,-0.081 9.069,2.416 18.274,3.608 27.404,3.608 27.67,0 54.63,-10.857 74.872,-31.098 28.057,-28.058 38.081,-69.018 26.159,-106.895 -0.917,-2.917 -3.201,-5.201 -6.118,-6.118 -37.874,-11.919 -78.834,-1.898 -106.895,26.159 -4.367,4.368 -8.243,9.078 -11.722,14.01 C 257.391,84.394 244.866,58.121 224.321,37.576 190.415,3.672 140.923,-8.438 95.152,5.969 c -2.916,0.917 -5.199,3.201 -6.117,6.117 -14.407,45.771 -2.294,95.265 31.61,129.171 24.462,24.462 57.034,37.577 90.473,37.577 8.705,0 17.468,-0.912 26.164,-2.723 l 0,108.977 c -3.626,0.796 -6.846,1.507 -9.476,2.09 -19.576,-3.777 -51.799,-7.913 -62.657,2.943 l -17.155,17.157 -25.982,8.66 C 90.459,326.457 79.646,373.081 78.462,378.639 67.745,372.156 57.169,364.449 47,355.298 c -1.718,-1.547 -3.948,-2.403 -6.261,-2.403 -20.724,0 -28.078,10.084 -28.078,18.718 0,2.695 0,7.713 19.672,30.533 7.6,8.815 23.622,26.455 45.545,45.548 C 111.56,477.03 161.686,512 209.204,512 c 54.75,0 93.893,-11.517 122.475,-19.927 15.477,-4.554 27.703,-8.15 36.631,-8.15 28.524,0 83.448,-9.099 85.771,-9.486 3.225,-0.538 5.936,-2.72 7.151,-5.757 l 37.437,-93.592 c 1.02,-2.549 0.868,-5.418 -0.414,-7.846 z M 285.84,111.319 c 21.934,-21.934 53.445,-30.484 83.276,-22.896 7.588,29.829 -0.962,61.342 -22.896,83.276 -20.068,20.069 -48.149,28.892 -75.629,24.442 7.598,-12.588 18.283,-27.044 27.031,-31.418 4.622,-2.311 6.496,-7.933 4.185,-12.557 -2.312,-4.621 -7.936,-6.496 -12.557,-4.185 -10.934,5.467 -21.248,18.034 -28.899,29.368 -1.218,-24.303 7.756,-48.297 25.489,-66.03 z m -91.186,-3.335 c 24.55,16.367 33.412,50.107 33.551,50.651 0.006,0.025 0.018,0.047 0.025,0.072 -34.297,5.418 -69.302,-5.642 -94.348,-30.687 -27.787,-27.786 -38.433,-67.837 -28.369,-105.574 37.734,-10.057 77.788,0.581 105.574,28.369 24.252,24.251 35.438,57.846 31.202,91.091 -5.412,-13.719 -16.755,-35.832 -37.253,-49.496 -4.305,-2.87 -10.114,-1.705 -12.979,2.596 -2.867,4.299 -1.705,10.111 2.597,12.978 z M 96.713,382.808 c 2.307,-11.536 12.412,-42.843 31.219,-49.112 l 28.077,-9.359 c 1.378,-0.46 2.63,-1.234 3.658,-2.261 l 18.569,-18.569 c 4.598,-2.83 27.287,-1.694 47.853,2.409 1.277,0.254 2.595,0.241 3.864,-0.041 37.204,-8.267 78.515,-16.861 89.418,-18.29 5.419,5.973 17.071,28.485 26.907,50.371 -10.859,-1.348 -21.964,-2.611 -33.192,-3.734 -92.975,-9.301 -146.489,-1.275 -159.049,23.845 -2.518,5.037 -2.354,10.528 0.451,15.066 7.747,12.536 35.26,17.198 101.511,17.198 9.436,0 13.812,2.484 14.693,4.611 0.783,1.887 -0.203,4.916 -2.3,7.185 -4.784,2.847 -36.333,11.951 -81.773,9.093 -25.613,-1.615 -58.975,-7.447 -92.25,-23.882 1.147,-1.227 1.99,-2.764 2.344,-4.53 z m 349.109,73.997 c -14.424,2.27 -55.41,8.399 -77.512,8.399 -11.626,0 -24.992,3.932 -41.914,8.911 -27.49,8.089 -65.138,19.166 -117.192,19.166 -40.47,0 -85.094,-30.767 -115.402,-56.577 -32.273,-27.483 -54.244,-54.18 -60.838,-64.024 1.271,-0.355 2.861,-0.658 4.476,-0.85 50.935,44.267 110.251,56.154 151.395,58.264 42.498,2.182 83.891,-5.82 92.501,-14.427 7.698,-7.699 10.371,-18.907 6.65,-27.889 -2.501,-6.038 -9.982,-16.166 -31.987,-16.166 -58.305,0 -77.615,-4.05 -83.789,-7.225 5.922,-6.71 31.474,-22.289 139.013,-11.54 72.654,7.266 140.337,20.36 165.932,25.622 l -31.333,78.336 z"
id="path3489"
style="fill:#666666" />
</g>
</g>
<g
id="g3491"
style="fill:#666666" />
<g
id="g3493"
style="fill:#666666" />
<g
id="g3495"
style="fill:#666666" />
<g
id="g3497"
style="fill:#666666" />
<g
id="g3499"
style="fill:#666666" />
<g
id="g3501"
style="fill:#666666" />
<g
id="g3503"
style="fill:#666666" />
<g
id="g3505"
style="fill:#666666" />
<g
id="g3507"
style="fill:#666666" />
<g
id="g3509"
style="fill:#666666" />
<g
id="g3511"
style="fill:#666666" />
<g
id="g3513"
style="fill:#666666" />
<g
id="g3515"
style="fill:#666666" />
<g
id="g3517"
style="fill:#666666" />
<g
id="g3519"
style="fill:#666666" />
</g>
</g>
<flowRoot
xml:space="preserve"
id="flowRoot3646"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"><flowRegion
id="flowRegion3648"><rect
id="rect3650"
width="488.91382"
height="303.04578"
x="2424.3662"
y="567.48901" /></flowRegion><flowPara
id="flowPara3652"></flowPara></flowRoot> <path
style="fill:#999999;fill-rule:evenodd;stroke:#000000;stroke-width:0.99999988px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 172.79466,107.23444 0,-77.30686"
id="path3901"
inkscape:connector-curvature="0" />
<path
style="fill:#999999;fill-rule:evenodd;stroke:#000000;stroke-width:0.99999988px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 571.29983,107.23444 0,-77.30686"
id="path3901-3"
inkscape:connector-curvature="0" />
</g>
<g
inkscape:groupmode="layer"
id="layer3"
inkscape:label="Posts"
style="display:none">
<g
transform="translate(9.0999998e-7,4.7244096e-6)"
id="g3943">
<g
style="fill:#4d4d4d"
id="g3772-7"
transform="matrix(0.92947203,0,0,0.92947203,26.287452,474.93115)">
<flowRoot
xml:space="preserve"
id="flowRoot3654-1"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#4d4d4d;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
transform="translate(-2265.0055,-375.0117)"><flowRegion
id="flowRegion3656-3"><rect
style="fill:#4d4d4d"
id="rect3658-3"
width="401.03055"
height="415.17267"
x="2436.488"
y="595.77325" /></flowRegion><flowPara
id="flowPara3660-3"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.5px;font-family:'Accanthis ADF Std';-inkscape-font-specification:'Accanthis ADF Std';text-align:justify;text-anchor:start;fill:#4d4d4d">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur varius ullamcorper tellus, eu ultrices nisi volutpat vitae. Fusce sapien dolor, pharetra vel odio non, venenatis rutrum dolor. Phasellus gravida hendrerit ante eu tristique. Sed ut purus eget augue aliquam venenatis. Donec rutrum justo ut convallis vulputate. Ut et tempor est. Aliquam erat volutpat. Proin gravida purus quis condimentum laoreet. Praesent molestie sit amet arcu gravida vehicula. Duis ullamcorper fermentum semper. Donec posuere metus in ante egestas feugiat. Phasellus felis eros, sollicitudin sit amet risus vitae, ornare ultrices dolor. </flowPara><flowPara
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.5px;font-family:'Accanthis ADF Std';-inkscape-font-specification:'Accanthis ADF Std';text-align:justify;text-anchor:start;fill:#4d4d4d"
id="flowPara3768-8" /><flowPara
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.5px;font-family:'Accanthis ADF Std';-inkscape-font-specification:'Accanthis ADF Std';text-align:justify;text-anchor:start;fill:#4d4d4d"
id="flowPara3770-5">Fusce eu aliquam dui, sit amet condimentum ipsum. In sodales iaculis porttitor. Nam tincidunt maximus sem ac egestas.Fusce congue purus nisi, at ornare orci egestas ac. Donec auctor non diam at ornare. Etiam tortor nisl, ullamcorper quis orci ac, vehicula facilisis eros. Integer vitae posuere odio. Etiam risus arcu, ornare et elit ut, commodo consectetur diam. Maecenas non imperdiet metus. Sed vehicula dui ut semper sollicitudin. Quisque id rhoncus purus. Duis ut convallis nisi, sed feugiat ante. Suspendisse nec quam imperdiet, sagittis ipsum auctor, volutpat arcu. </flowPara><flowPara
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.5px;font-family:'Accanthis ADF Std';-inkscape-font-specification:'Accanthis ADF Std';text-align:justify;text-anchor:start;fill:#4d4d4d"
id="flowPara3670-1" /><flowPara
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.5px;font-family:'Accanthis ADF Std';-inkscape-font-specification:'Accanthis ADF Std';text-align:justify;text-anchor:start;fill:#4d4d4d"
id="flowPara3672-0">Nunc in est tincidunt est sodales imperdiet. Praesent vitae enim dapibus, convallis orci ac, lacinia libero. Pellentesque nec vehicula felis.Proin at ultricies tortor, at tempor ipsum. Vestibulum sit amet magna at odio mollis facilisis a eget erat. Integer rutrum dapibus sapien, et ultricies ligula vulputate bibendum. Nulla at faucibus libero, vitae tempus ipsum. Mauris bibendum enim ac eros imperdiet posuere. Pellentesque purus nisi, sodales et condimentum faucibus, viverra a mauris. Aliquam erat volutpat. Sed sit amet est sed ipsum pellentesque pharetra. Proin odio sem, rhoncus quis quam vitae, rhoncus accumsan massa. Aenean venenatis euismod ante, et iaculis ante dictum ut. Donec convallis sit amet urna et condimentum. Nunc tincidunt ligula vitae quam dignissim sagittis. Curabitur mollis tincidunt velit in mollis. Nam consequat ante quis urna hendrerit sollicitudin. Pellentesque auctor urna a nunc sagittis maximus.</flowPara><flowPara
id="flowPara3662-8"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.5px;font-family:'Accanthis ADF Std';-inkscape-font-specification:'Accanthis ADF Std';text-align:justify;text-anchor:start;fill:#4d4d4d" /><flowPara
id="flowPara3664-7"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.5px;font-family:'Accanthis ADF Std';-inkscape-font-specification:'Accanthis ADF Std';text-align:justify;text-anchor:start;fill:#4d4d4d" /><flowPara
id="flowPara3666-6"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.5px;font-family:'Accanthis ADF Std';-inkscape-font-specification:'Accanthis ADF Std';text-align:justify;text-anchor:start;fill:#4d4d4d" /><flowPara
id="flowPara3668-3"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.5px;font-family:'Accanthis ADF Std';-inkscape-font-specification:'Accanthis ADF Std';text-align:justify;text-anchor:start;fill:#4d4d4d" /></flowRoot> <text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#4d4d4d;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="268.04333"
y="207.14891"
id="text3691-5"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3693-0"
x="268.04333"
y="207.14891"
style="font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:25px;font-family:'Accanthis ADF Std';-inkscape-font-specification:'Accanthis ADF Std';fill:#4d4d4d">Titel van de post</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#4d4d4d;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="171.21529"
y="207.14891"
id="text3691-0-8"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3693-2-0"
x="171.21529"
y="207.14891"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.5px;font-family:'Accanthis ADF Std';-inkscape-font-specification:'Accanthis ADF Std';fill:#4d4d4d">12/02/1985</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;text-align:end;letter-spacing:0px;word-spacing:0px;text-anchor:end;fill:#4d4d4d;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="572.25153"
y="207.14891"
id="text3691-0-6-4"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3693-2-5-1"
x="572.25153"
y="207.14891"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.5px;font-family:'Accanthis ADF Std';-inkscape-font-specification:'Accanthis ADF Std';text-align:end;text-anchor:end;fill:#4d4d4d">(T)(P)</tspan></text>
</g>
<g
transform="translate(0.56364909,44.446712)"
id="g3878">
<g
id="g3772"
transform="matrix(0.92947203,0,0,0.92947203,25.723792,-9.3132083)">
<flowRoot
transform="translate(-2265.0055,-375.0117)"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="flowRoot3654"
xml:space="preserve"><flowRegion
id="flowRegion3656"><rect
y="595.77325"
x="2436.488"
height="415.17267"
width="401.03055"
id="rect3658" /></flowRegion><flowPara
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.5px;font-family:'Accanthis ADF Std';-inkscape-font-specification:'Accanthis ADF Std';text-align:justify;text-anchor:start"
id="flowPara3660">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur varius ullamcorper tellus, eu ultrices nisi volutpat vitae. Fusce sapien dolor, pharetra vel odio non, venenatis rutrum dolor. Phasellus gravida hendrerit ante eu tristique. Sed ut purus eget augue aliquam venenatis. Donec rutrum justo ut convallis vulputate. Ut et tempor est. Aliquam erat volutpat. Proin gravida purus quis condimentum laoreet. Praesent molestie sit amet arcu gravida vehicula. Duis ullamcorper fermentum semper. Donec posuere metus in ante egestas feugiat. Phasellus felis eros, sollicitudin sit amet risus vitae, ornare ultrices dolor. </flowPara><flowPara
id="flowPara3768"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.5px;font-family:'Accanthis ADF Std';-inkscape-font-specification:'Accanthis ADF Std';text-align:justify;text-anchor:start" /><flowPara
id="flowPara3770"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.5px;font-family:'Accanthis ADF Std';-inkscape-font-specification:'Accanthis ADF Std';text-align:justify;text-anchor:start">Fusce eu aliquam dui, sit amet condimentum ipsum. In sodales iaculis porttitor. Nam tincidunt maximus sem ac egestas.Fusce congue purus nisi, at ornare orci egestas ac. Donec auctor non diam at ornare. Etiam tortor nisl, ullamcorper quis orci ac, vehicula facilisis eros. Integer vitae posuere odio. Etiam risus arcu, ornare et elit ut, commodo consectetur diam. Maecenas non imperdiet metus. Sed vehicula dui ut semper sollicitudin. Quisque id rhoncus purus. Duis ut convallis nisi, sed feugiat ante. Suspendisse nec quam imperdiet, sagittis ipsum auctor, volutpat arcu. </flowPara><flowPara
id="flowPara3670"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.5px;font-family:'Accanthis ADF Std';-inkscape-font-specification:'Accanthis ADF Std';text-align:justify;text-anchor:start" /><flowPara
id="flowPara3672"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.5px;font-family:'Accanthis ADF Std';-inkscape-font-specification:'Accanthis ADF Std';text-align:justify;text-anchor:start">Nunc in est tincidunt est sodales imperdiet. Praesent vitae enim dapibus, convallis orci ac, lacinia libero. Pellentesque nec vehicula felis.Proin at ultricies tortor, at tempor ipsum. Vestibulum sit amet magna at odio mollis facilisis a eget erat. Integer rutrum dapibus sapien, et ultricies ligula vulputate bibendum. Nulla at faucibus libero, vitae tempus ipsum. Mauris bibendum enim ac eros imperdiet posuere. Pellentesque purus nisi, sodales et condimentum faucibus, viverra a mauris. Aliquam erat volutpat. Sed sit amet est sed ipsum pellentesque pharetra. Proin odio sem, rhoncus quis quam vitae, rhoncus accumsan massa. Aenean venenatis euismod ante, et iaculis ante dictum ut. Donec convallis sit amet urna et condimentum. Nunc tincidunt ligula vitae quam dignissim sagittis. Curabitur mollis tincidunt velit in mollis. Nam consequat ante quis urna hendrerit sollicitudin. Pellentesque auctor urna a nunc sagittis maximus.</flowPara><flowPara
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.5px;font-family:'Accanthis ADF Std';-inkscape-font-specification:'Accanthis ADF Std';text-align:justify;text-anchor:start"
id="flowPara3662" /><flowPara
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.5px;font-family:'Accanthis ADF Std';-inkscape-font-specification:'Accanthis ADF Std';text-align:justify;text-anchor:start"
id="flowPara3664" /><flowPara
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.5px;font-family:'Accanthis ADF Std';-inkscape-font-specification:'Accanthis ADF Std';text-align:justify;text-anchor:start"
id="flowPara3666" /><flowPara
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.5px;font-family:'Accanthis ADF Std';-inkscape-font-specification:'Accanthis ADF Std';text-align:justify;text-anchor:start"
id="flowPara3668" /></flowRoot> <text
sodipodi:linespacing="125%"
id="text3691"
y="207.14891"
x="268.04333"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:25px;font-family:'Accanthis ADF Std';-inkscape-font-specification:'Accanthis ADF Std'"
y="207.14891"
x="268.04333"
id="tspan3693"
sodipodi:role="line">Titel van de post</tspan></text>
<text
sodipodi:linespacing="125%"
id="text3691-0"
y="207.14891"
x="171.21529"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.5px;font-family:'Accanthis ADF Std';-inkscape-font-specification:'Accanthis ADF Std'"
y="207.14891"
x="171.21529"
id="tspan3693-2"
sodipodi:role="line">12/02/1985</tspan></text>
<text
sodipodi:linespacing="125%"
id="text3691-0-6"
y="207.14891"
x="572.25153"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;text-align:end;letter-spacing:0px;word-spacing:0px;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.5px;font-family:'Accanthis ADF Std';-inkscape-font-specification:'Accanthis ADF Std';text-align:end;text-anchor:end"
y="207.14891"
x="572.25153"
id="tspan3693-2-5"
sodipodi:role="line">(T)(P)</tspan></text>
</g>
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 172.23101,198.27823 0,372.49376"
id="path3861"
inkscape:connector-curvature="0" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 570.73618,198.27823 0,372.49376"
id="path3861-1"
inkscape:connector-curvature="0" />
</g>
</g>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:18.09488106px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="371.61295"
y="186.29254"
id="text3937-1"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3939-2"
x="371.61295"
y="186.29254"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:35px;font-family:'Accanthis ADF Std';-inkscape-font-specification:'Accanthis ADF Std';text-align:center;text-anchor:middle">Posts</tspan></text>
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 184.91649,194.23762 374.26151,0"
id="path4004"
inkscape:connector-curvature="0" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 184.91649,151.38048 374.26151,0"
id="path4004-2"
inkscape:connector-curvature="0" />
</g>
<g
style="display:inline"
inkscape:label="CV"
id="g4184"
inkscape:groupmode="layer">
<path
inkscape:connector-curvature="0"
id="path4266"
d="m 172.2843,249.71486 0,372.49376"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path4268"
d="m 571.54797,249.71486 0,372.49376"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<text
sodipodi:linespacing="125%"
id="text4270"
y="186.29254"
x="371.61295"
style="font-style:normal;font-weight:normal;font-size:18.09488106px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:35px;font-family:'Accanthis ADF Std';-inkscape-font-specification:'Accanthis ADF Std';text-align:center;text-anchor:middle"
y="186.29254"
x="371.61295"
id="tspan4272"
sodipodi:role="line">Curriculum Vitae</tspan></text>
<path
inkscape:connector-curvature="0"
id="path4274"
d="m 184.91649,194.23762 374.26151,0"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path4276"
d="m 184.91649,151.38048 374.26151,0"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<image
y="248.95815"
x="522.69983"
id="image4286"
xlink:href="data:image/png;base64,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
"
style="image-rendering:optimizeSpeed"
preserveAspectRatio="none"
height="46.688595"
width="46.688595" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:20.91934013px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="216.24274"
y="260.42645"
id="text4351"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan4353"
x="216.24274"
y="260.42645"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:13.07458782px;font-family:'Accanthis ADF Std';-inkscape-font-specification:'Accanthis ADF Std'">Universiteit Gent</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:15.20028877px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="466.82535"
y="259.28119"
id="text4351-8"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan4353-2"
x="466.82535"
y="259.28119"
style="font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:9.5001812px;font-family:'Accanthis ADF Std';-inkscape-font-specification:'Accanthis ADF Std'">2003/2010</tspan></text>
<flowRoot
xml:space="preserve"
id="flowRoot4425"
style="font-style:normal;font-weight:normal;font-size:15px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
transform="translate(-33.126129,-34.452713)"><flowRegion
id="flowRegion4427"><rect
id="rect4429"
width="296.98303"
height="76.316437"
x="249.50768"
y="321.51685"
style="font-size:15px" /></flowRegion><flowPara
id="flowPara4431"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10px;font-family:'Accanthis ADF Std';-inkscape-font-specification:'Accanthis ADF Std';text-align:justify;text-anchor:start">Some random text here random text here random text here random text here random text here random text here random text here random text here random text here</flowPara></flowRoot> <text
sodipodi:linespacing="125%"
id="text4270-5"
y="218.99983"
x="368.168"
style="font-style:normal;font-weight:normal;font-size:18.09488106px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:22.5px;font-family:'Accanthis ADF Std';-inkscape-font-specification:'Accanthis ADF Std';text-align:center;text-anchor:middle"
y="218.99983"
x="368.168"
id="tspan4272-6"
sodipodi:role="line">Education</tspan></text>
<flowRoot
xml:space="preserve"
id="flowRoot4425-6"
style="font-style:normal;font-weight:normal;font-size:15px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
transform="translate(-34.021377,-60.309751)"><flowRegion
id="flowRegion4427-8"><rect
id="rect4429-4"
width="294.70752"
height="25.496542"
x="249.50768"
y="321.51685"
style="font-size:15px" /></flowRegion><flowPara
id="flowPara4431-8"
style="font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10px;font-family:'Accanthis ADF Std';-inkscape-font-specification:'Accanthis ADF Std';text-align:justify;text-anchor:start">Master, computerwetenschappen - software ontwikkeling, cum laude</flowPara></flowRoot> <path
inkscape:connector-curvature="0"
id="path4274-7"
d="m 184.91649,226.09488 374.26151,0"
style="display:inline;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
</g>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="top lines option 2"
style="display:none">
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 172.54212,129.57044 399.01024,0"
id="path4159-7"
inkscape:connector-curvature="0" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 172.54212,74.927585 399.01024,0"
id="path4159-7-5"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 48 KiB

14
e2e/app.e2e-spec.ts Normal file
View File

@ -0,0 +1,14 @@
import { HomepagePage } from './app.po';
describe('homepage App', () => {
let page: HomepagePage;
beforeEach(() => {
page = new HomepagePage();
});
it('should display welcome message', () => {
page.navigateTo();
expect(page.getParagraphText()).toEqual('Welcome to app!!');
});
});

11
e2e/app.po.ts Normal file
View File

@ -0,0 +1,11 @@
import { browser, by, element } from 'protractor';
export class HomepagePage {
navigateTo() {
return browser.get('/');
}
getParagraphText() {
return element(by.css('app-root h1')).getText();
}
}

12
e2e/tsconfig.e2e.json Normal file
View File

@ -0,0 +1,12 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/e2e",
"module": "commonjs",
"target": "es5",
"types": [
"jasmine",
"node"
]
}
}

33
karma.conf.js Normal file
View File

@ -0,0 +1,33 @@
// Karma configuration file, see link for more information
// https://karma-runner.github.io/0.13/config/configuration-file.html
module.exports = function (config) {
config.set({
basePath: '',
frameworks: ['jasmine', '@angular-devkit/build-angular'],
plugins: [
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-coverage-istanbul-reporter'),
require('@angular-devkit/build-angular/plugins/karma')
],
client:{
clearContext: false // leave Jasmine Spec Runner output visible in browser
},
coverageIstanbulReporter: {
dir: require('path').join(__dirname, 'coverage'), reports: [ 'html', 'lcovonly' ],
fixWebpackSourcePaths: true
},
angularCli: {
environment: 'dev'
},
reporters: ['progress', 'kjhtml'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: false
});
};

49797
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,59 +1,60 @@
{ {
"name": "homepage-react", "name": "homepage",
"version": "0.1.0", "version": "0.0.0",
"license": "MIT",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
},
"private": true, "private": true,
"assets": [
"assets",
"favicon.ico"
],
"dependencies": { "dependencies": {
"@fortawesome/fontawesome-free": "^5.15.4", "@angular/animations": "^6.0.0",
"@fortawesome/fontawesome-svg-core": "^1.2.36", "@angular/common": "^6.0.0",
"@fortawesome/free-brands-svg-icons": "^5.15.4", "@angular/compiler": "^6.0.0",
"@fortawesome/free-regular-svg-icons": "^5.15.4", "@angular/core": "^6.0.0",
"@fortawesome/free-solid-svg-icons": "^5.15.4", "@angular/forms": "^6.0.0",
"@fortawesome/react-fontawesome": "^0.1.15", "@angular/http": "^6.0.0",
"@testing-library/jest-dom": "^5.11.4", "@angular/platform-browser": "^6.0.0",
"@testing-library/react": "^11.1.0", "@angular/platform-browser-dynamic": "^6.0.0",
"@testing-library/user-event": "^12.1.10", "@angular/router": "^6.0.0",
"bootstrap": "^5.1.0", "bootstrap": "^4.1.1",
"i18next": "^20.4.0", "core-js": "^2.5.6",
"react": "^17.0.2", "font-awesome": "^4.7.0",
"react-dom": "^17.0.2", "ngx-bootstrap": "^2.0.5",
"react-i18next": "^11.11.4", "npm": "^6.0.0",
"react-router-dom": "^5.2.0", "popper.js": "^1.14.3",
"react-scripts": "4.0.3", "rxjs": "^6.1.0",
"typescript": "^4.3.5", "rxjs-compat": "^6.1.0",
"web-vitals": "^1.0.1" "zone.js": "^0.8.26"
}, },
"devDependencies": { "devDependencies": {
"@types/jest": "^27.0.1", "@angular-devkit/build-angular": "~0.6.0",
"@types/node": "^16.6.1", "@angular/cli": "6.0.0",
"@types/react": "^17.0.18", "@angular/compiler-cli": "^6.0.0",
"@types/react-dom": "^17.0.9", "@angular/language-service": "^6.0.0",
"@types/react-router-dom": "^5.1.8", "@types/jasmine": "2.8.7",
"eslint": "^7.32.0", "@types/node": "^10.0.6",
"node-sass": "^6.0.1", "codelyzer": "~4.3.0",
"sass-loader": "^10.2.0" "jasmine-core": "~3.1.0",
}, "jasmine-spec-reporter": "^4.2.1",
"scripts": { "karma": "^2.0.2",
"start": "react-scripts start", "karma-chrome-launcher": "~2.2.0",
"build": "react-scripts build", "karma-cli": "~1.0.1",
"test": "react-scripts test", "karma-coverage-istanbul-reporter": "^1.4.2",
"eject": "react-scripts eject" "karma-jasmine": "^1.1.2",
}, "karma-jasmine-html-reporter": "^1.0.0",
"eslintConfig": { "node-sass": "^4.9.0",
"extends": [ "protractor": "~5.3.1",
"react-app", "ts-node": "~6.0.3",
"react-app/jest" "tslint": "~5.10.0",
] "typescript": "^2.7.2"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
} }
} }

28
protractor.conf.js Normal file
View File

@ -0,0 +1,28 @@
// Protractor configuration file, see link for more information
// https://github.com/angular/protractor/blob/master/lib/config.ts
const { SpecReporter } = require('jasmine-spec-reporter');
exports.config = {
allScriptsTimeout: 11000,
specs: [
'./e2e/**/*.e2e-spec.ts'
],
capabilities: {
'browserName': 'chrome'
},
directConnect: true,
baseUrl: 'http://localhost:4200/',
framework: 'jasmine',
jasmineNodeOpts: {
showColors: true,
defaultTimeoutInterval: 30000,
print: function() {}
},
onPrepare() {
require('ts-node').register({
project: 'e2e/tsconfig.e2e.json'
});
jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
}
};

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 12 KiB

View File

@ -1,3 +0,0 @@
<p>A nice benefit of having a blog that nobody reads is that you're free to not update it for three years on end. The typical reasons aside, there wasn't really anything project-wise to write about.</p>
<p>I had a recent reason to start looking into React, and this website provides a nice playground for quick implementations that touch on most of the necessary concepts. Hence, this revamp. No more Angular under the hood, but React as the driver. The rest stays nice and minimal, including a custom static database. In the end the conversion was a pleasant experience. Maybe I'll look into Clojurescript next, that always seems to be on top of my todo list.</p>

View File

@ -1,9 +0,0 @@
<p>Ideaal, een blog hebben dat niemand leest. Zo hoef je niemand teleurstellen wanneer je drie jaar geen updates
lanceert. Naast de typische redenen was er niets projectgerelateerd om over te schrijven, hoewel dat binnenkort
hopelijk wel verandert.</p>
<p>Ik had een recente reden om React te beginnen bekijken, en deze website is de perfecte speeltuin om snelle
implementaties te doen die toch de nodige concepten aanraken. Dus, een revamp. Geen Angular meer, maar React die de
interactie drijft. Voor de rest blijft de site mooi minimaal, inclusief de kleine custom static database.
Uiteindelijk was de conversie snel en aangenaam. Misschien moet ik Clojurescript toch eens bekijken als volgende
kandidaat. Die lijkt altijd bovenaan mijn todo list te staan.</p>

View File

@ -1,14 +0,0 @@
{
"created_timestamp": 1629446262.825442,
"languages": [
"nl",
"en"
],
"tags": [
"tech"
],
"title": {
"en": "A fresh set of clothes",
"nl": "Een nieuw kleedje"
}
}

View File

@ -1 +0,0 @@
[{"info": {"created_timestamp": 1529827943.7910142, "languages": ["nl", "en"], "title": {"en": "Long live the prototype!", "nl": "Lang leve het prototype!"}, "tags": ["project"]}, "id": "beamer"}, {"info": {"created_timestamp": 1526328948.8972409, "languages": ["nl", "en"], "title": {"en": "No more television!", "nl": "Geen televisie meer!"}, "tags": ["project"]}, "id": "beamerprototype"}, {"info": {"created_timestamp": 1515094679.342938, "languages": ["nl", "en"], "tags": ["blog"], "title": {"en": "Who said Web 1.0 was dead anyway?", "nl": "Omdat ik het Web 1.0 tijdperk gemist heb..."}}, "id": "first"}, {"info": {"created_timestamp": 1539198696.0825138, "languages": ["en", "nl"], "title": {"en": "An SVG firmament!", "nl": "Een SVG firmament!"}, "tags": ["tech"]}, "id": "hygsvg"}, {"info": {"created_timestamp": 1525895500.2597992, "languages": ["nl", "en"], "title": {"en": "Better together!", "nl": "Eindelijk samen!"}, "tags": ["project"]}, "id": "ikearefurbish"}, {"info": {"created_timestamp": 1522255558.864005, "languages": ["en", "nl"], "title": {"en": "Presentation of my PhD public defence", "nl": "Publieke doctoraatsverdediging - presentatie"}, "tags": ["tech"]}, "id": "phdpresentation"}, {"info": {"languages": ["nl", "en"], "created_timestamp": 1629446262.825442, "tags": ["tech"], "title": {"en": "A fresh set of clothes", "nl": "Een nieuw kleedje"}}, "id": "react"}]

View File

@ -1,43 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>Joachim Nielandt</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

View File

@ -1,25 +0,0 @@
{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "logo192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}

View File

@ -1,3 +0,0 @@
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:

View File

@ -0,0 +1,39 @@
import {NgModule} from '@angular/core';
import {RouterModule, Routes} from '@angular/router';
import {HomeComponent} from './components/home/home.component';
import {PostsComponent} from './components/posts/posts.component';
import {CvComponent} from './components/cv/cv.component';
import {RootComponent} from './components/root/root.component';
import {FullpostComponent} from './components/fullpost/fullpost.component';
import {ContactComponent} from './components/contact/contact.component';
const appRoutes: Routes = [
{
path: ':language',
component: RootComponent,
children: [
{path: 'home', component: HomeComponent},
{path: 'posts', component: PostsComponent},
{path: 'cv', component: CvComponent},
{path: 'contact', component: ContactComponent},
{path: 'post/:id', component: FullpostComponent},
{path: '', redirectTo: 'posts', pathMatch: 'full'},
// {path: '*', redirectTo: 'home', pathMatch: 'full'}
]
},
{ path: '', redirectTo: 'nl', pathMatch: 'full' },
]
;
@NgModule({
imports: [
RouterModule.forRoot(
appRoutes,
{enableTracing: true}) // <-- debugging purposes only )
],
exports: [
RouterModule
]
})
export class AppRoutingModule {
}

View File

@ -0,0 +1 @@
<router-outlet></router-outlet>

View File

@ -0,0 +1 @@

View File

@ -0,0 +1,32 @@
import { TestBed, async } from '@angular/core/testing';
import { AppComponent } from './app.component';
describe('AppComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
AppComponent
],
}).compileComponents();
}));
it('should create the app', async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
}));
it(`should have as title 'app'`, async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app.title).toEqual('app');
}));
it('should render title in a h1 tag', async(() => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('h1').textContent).toContain('Welcome to app!!');
}));
});

19
src/app/app.component.ts Normal file
View File

@ -0,0 +1,19 @@
import { Component, OnInit} from '@angular/core';
import 'rxjs/add/operator/switchMap';
import {ActivatedRoute} from '@angular/router';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
constructor() {
}
ngOnInit() {
}
}

53
src/app/app.module.ts Normal file
View File

@ -0,0 +1,53 @@
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
import { HomeComponent } from './components/home/home.component';
import { PostsComponent } from './components/posts/posts.component';
import { PostComponent } from './components/post/post.component';
import { DataloaderService } from 'app/services/dataloader.service';
import { HttpClientModule } from '@angular/common/http';
import { CvComponent } from './components/cv/cv.component';
import { PosttypepipePipe } from './pipes/posttypepipe.pipe';
import { TooltipModule } from 'ngx-bootstrap/tooltip';
import {SimpledatePipe} from './pipes/simpledate.pipe';
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';
import { ContactComponent } from './components/contact/contact.component';
import { RootComponent } from './components/root/root.component';
import { LanguagetoggleComponent } from './components/languagetoggle/languagetoggle.component';
import { FullpostComponent } from './components/fullpost/fullpost.component';
@NgModule({
declarations: [
AppComponent,
HomeComponent,
PostsComponent,
PostComponent,
CvComponent,
PosttypepipePipe,
SimpledatePipe,
PosttagComponent,
ContactComponent,
RootComponent,
LanguagetoggleComponent,
FullpostComponent
],
imports: [
BrowserModule,
AppRoutingModule,
HttpClientModule,
FormsModule,
TooltipModule.forRoot(),
ButtonsModule.forRoot()
],
providers: [DataloaderService, StateService],
bootstrap: [
AppComponent
]
})
export class AppModule { }

View File

@ -0,0 +1,65 @@
<div id="maincontactblock">
<div class="row">
<div class="col-md-12">
<div class="workaddress contactblock">
<app-languagetoggle [language]="'nl'">
<div class="row">
<div class="col-md-12 contactsubtitle">Werk adres</div>
<div class="col-md-6">Groep</div>
<div class="col-md-6">TELIN</div>
<div class="col-md-6">Straat</div>
<div class="col-md-6">St.Pietersnieuwstraat 41</div>
<div class="col-md-6">Stad</div>
<div class="col-md-6">Gent</div>
<div class="col-md-6">Postcode</div>
<div class="col-md-6">9000</div>
</div>
</app-languagetoggle>
<app-languagetoggle [language]="'en'">
<div class="row">
<div class="col-md-12 contactsubtitle">Work address</div>
<div class="col-md-6">Affiliation</div>
<div class="col-md-6">TELIN</div>
<div class="col-md-6">Street</div>
<div class="col-md-6">St.Pietersnieuwstraat 41</div>
<div class="col-md-6">City</div>
<div class="col-md-6">Ghent</div>
<div class="col-md-6">Postal code</div>
<div class="col-md-6">9000</div>
</div>
</app-languagetoggle>
</div>
</div>
<div class="col-md-12">
<div class="platforms contactblock">
<div class="row">
<div class="col-md-12 contactsubtitle">
<app-languagetoggle [language]="'nl'">
Platformen
</app-languagetoggle>
<app-languagetoggle [language]="'en'">
Platforms
</app-languagetoggle>
</div>
<div class="col-md-12 icons">
<div class="btn-group mx-auto" role="group">
<a target="_blank" href="https://www.linkedin.com/in/joachim-nielandt-5a01ba12/" title="LinkedIn">
<i class="fa fa-linkedin-square fa-fw fa-2x" aria-hidden="true"></i>
</a>
<a target="_blank" href="https://www.flickr.com/photos/countzukula/" title="Flickr">
<i class="fa fa-flickr fa-fw fa-2x" aria-hidden="true"></i>
</a>
<a target="_blank" href="https://tsuketoe.deviantart.com/" title="Deviantart">
<i class="fa fa-deviantart fa-fw fa-2x" aria-hidden="true"></i>
</a>
<a target="_blank" href="https://www.icheckmovies.com/profiles/countzukula/" title="iCheckMovies">
<i class="fa fa-check-square fa-fw fa-2x" aria-hidden="true"></i>
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,49 @@
.contactsubtitle {
font-size: 140%;
text-align: center;
border-bottom: 1px solid darkgray;
}
.contactblock > div {
padding: 0px 45px;
}
.workaddress .col-md-6:nth-child(even) {
text-align: right;
}
.workaddress .col-md-6 {
padding: 0px 20px;
}
.platforms {
margin-top: 20px;
.icons {
text-align: center;
margin-top: 10px;
i.fa-linkedin-square {
color: #0084bf;
}
i.fa-flickr {
color: #ff0084;
}
i.fa-deviantart {
color: #05cc47;
}
i.fa-check-square {
color: black;
}
a {
//padding: 0px 3px;
}
}
}

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ContactComponent } from './contact.component';
describe('ContactComponent', () => {
let component: ContactComponent;
let fixture: ComponentFixture<ContactComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ContactComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ContactComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,15 @@
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-contact',
templateUrl: './contact.component.html',
styleUrls: ['./contact.component.scss']
})
export class ContactComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}

View File

@ -0,0 +1,63 @@
<div class="experienceblock">
<app-languagetoggle [language]="'en'">
<div class="blocktitle">Experience</div>
</app-languagetoggle>
<app-languagetoggle [language]="'nl'">
<div class="blocktitle">Ervaring</div>
</app-languagetoggle>
<div class="blockcontent">
<div *ngFor="let experienceItem of getExperienceItems()" class="experience-item-block">
<div class="imgblock">
<img *ngIf="experienceItem.iconName != null" src="{{experienceItem.iconName}}" alt="..."
class="img-thumbnail img-fluid cv-item-thumbnail">
</div>
<div class="cvitem-text">
<div class="lead">
{{experienceItem.employer}}
</div>
<div class="font-italic">
{{experienceItem.fromYear}} - {{experienceItem.toYear}}
</div>
<div>
{{experienceItem.description}}
</div>
</div>
</div>
</div>
</div>
<div class="educationblock">
<app-languagetoggle [language]="'nl'">
<div class="blocktitle">Opleiding</div>
</app-languagetoggle>
<app-languagetoggle [language]="'en'">
<div class="blocktitle">Education</div>
</app-languagetoggle>
<div class="blockcontent">
<div *ngFor="let educationItem of getEducationItems()" class="experience-item-block">
<div class="imgblock">
<img *ngIf="educationItem.iconName != null" src="{{educationItem.iconName}}" alt="..."
class="img-thumbnail img-fluid cv-item-thumbnail">
</div>
<div class="cvitem-text">
<div class="firstline">
<div class="lead">
{{educationItem.employer}}
</div>
<div class="font-italic">
{{educationItem.fromYear}} - {{educationItem.toYear}}
</div>
</div>
<div class="font-italic">
{{educationItem.title}}
</div>
<div>
{{educationItem.description}}
</div>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,56 @@
.cv-item-thumbnail {
width: 90px;
}
.blocktitle {
text-align: center;
font-size: 150%;
border-bottom: 1px solid lightgrey;
margin: 0px 30px 0px 30px;
}
.experience-item-block {
display: flex;
margin-top: 15pt;
text-align: justify;
img {
border: none !important;
}
}
.educationblock, .experienceblock {
margin-bottom: 20px;
.blockcontent {
border-left: 1px solid black;
border-right: 1px solid black;
.imgblock {
flex: none;
width: 90pt;
}
}
}
.firstline {
display: flex;
align-items: flex-end;
.lead {
flex-grow: 1;
}
}
.blockcontent {
padding: 0px 30px 10px 30px;
margin-top: 30px;
}
.cvitem-text {
border-left: 1px solid lightgrey;
padding-left: 10pt;
flex-grow: 1;
}

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { CvComponent } from './cv.component';
describe('CvComponent', () => {
let component: CvComponent;
let fixture: ComponentFixture<CvComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ CvComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(CvComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should be created', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,175 @@
import {Component, OnInit} from '@angular/core';
import {CVTimeLineItem} from '../../model/educationitem';
import {StateService} from '../../services/state.service';
@Component({
selector: 'app-cv',
templateUrl: './cv.component.html',
styleUrls: ['./cv.component.scss']
})
export class CvComponent implements OnInit {
constructor(private stateService: StateService) {
}
ngOnInit() {
}
getEducationItems(): CVTimeLineItem[] {
const temp = [
new CVTimeLineItem()
.setLanguage('nl')
.setEmployer('Universiteit Gent')
.setTitle('Doctor in de ingenieurswetenschappen: computerwetenschappen')
.setDescription('Manuscript: "XPath-gebaseerde informatie-extractie" - informatie extraheren uit semi-gestructureerde documenten ' +
'zoals HTML, gebruik makend van XPath')
.setFromYear(2010)
.setToYear(2017)
.setIconName('assets/images/ugent-icon.png'),
new CVTimeLineItem()
.setLanguage('en')
.setEmployer('Ghent University')
.setTitle('Doctor of Computer Science Engineering')
.setDescription('Manuscript: "XPath-based information extraction" - extraction of information from semi-structured documents, such as ' +
'HTML, using XPath')
.setFromYear(2010)
.setToYear(2017)
.setIconName('assets/images/ugent-icon.png'),
new CVTimeLineItem()
.setLanguage('nl')
.setEmployer('Universiteit Gent')
.setTitle('Master, computerwetenschappen - software ontwikkeling, cum laude')
.setFromYear(2003)
.setToYear(2010)
.setIconName('assets/images/ugent-icon.png'),
new CVTimeLineItem()
.setLanguage('en')
.setEmployer('Ghent University')
.setTitle('Master, computer sciences - software engineering, cum laude')
.setFromYear(2003)
.setToYear(2010)
.setIconName('assets/images/ugent-icon.png'),
new CVTimeLineItem()
.setLanguage('nl')
.setEmployer('Leonardo Lyceum/Pestalozzi')
.setTitle('Latijn + Wetenschappen / Wiskunde')
.setFromYear(1999)
.setToYear(2003)
.setIconName('assets/images/pestalozzi-icon.png'),
new CVTimeLineItem()
.setLanguage('en')
.setEmployer('Leonardo Lyceum/Pestalozzi')
.setTitle('Latin + Sciences / Math')
.setFromYear(1999)
.setToYear(2003)
.setIconName('assets/images/pestalozzi-icon.png'),
new CVTimeLineItem()
.setLanguage('nl')
.setEmployer('Leonardo Lyceum Esemnegen')
.setTitle('Latijn')
.setFromYear(1997)
.setToYear(1999)
.setIconName('assets/images/zotvana.jpg'),
new CVTimeLineItem()
.setLanguage('en')
.setEmployer('Leonardo Lyceum Esemnegen')
.setTitle('Latin')
.setFromYear(1997)
.setToYear(1999)
.setIconName('assets/images/zotvana.jpg'),
];
const res = new Array<CVTimeLineItem>();
temp.forEach(value => {
if (value.language === this.stateService.getLanguage()) {
res.push(value);
}
});
return res;
}
getExperienceItems(): CVTimeLineItem[] {
const temp = [
new CVTimeLineItem()
.setLanguage('nl')
.setEmployer('imec / Universiteit Gent')
.setDescription('Postdoctoraal medewerker')
.setFromYear(2018)
.setFromMonth('oktober')
.setIconName('assets/images/imec-icon.png'),
new CVTimeLineItem()
.setLanguage('en')
.setEmployer('imec / Ghent University')
.setDescription('Postdoctoral associate')
.setFromYear(2018)
.setFromMonth('oct')
.setIconName('assets/images/imec-icon.png'),
new CVTimeLineItem()
.setLanguage('nl')
.setEmployer('Universiteit Gent')
.setDescription('Postdoctoraal onderzoeker')
.setFromYear(2017)
.setToYear(2018)
.setFromMonth('maart')
.setToMonth('oktober')
.setIconName('assets/images/ugent-icon.png'),
new CVTimeLineItem()
.setLanguage('en')
.setEmployer('Ghent University')
.setDescription('Postdoctoral researcher')
.setFromYear(2017)
.setFromMonth('mar')
.setToYear(2018)
.setToMonth('oct')
.setIconName('assets/images/ugent-icon.png'),
new CVTimeLineItem()
.setLanguage('nl')
.setEmployer('Universiteit Gent')
.setDescription('doctoraatstudent / assistent')
.setFromYear(2010)
.setToYear(2017)
.setIconName('assets/images/ugent-icon.png')
.setFromMonth('april').setToMonth('maart'),
new CVTimeLineItem()
.setLanguage('en')
.setEmployer('Ghent University')
.setDescription('PhD student / assistent')
.setFromYear(2010)
.setToYear(2017)
.setIconName('assets/images/ugent-icon.png')
.setFromMonth('apr').setToMonth('mar'),
new CVTimeLineItem()
.setLanguage('nl')
.setEmployer('Oxynade')
.setDescription('Software ontwikkelaar')
.setFromYear(2009)
.setToYear(2010)
.setIconName('assets/images/oxynade-icon.png')
.setFromMonth('november').setToMonth('april'),
new CVTimeLineItem()
.setLanguage('en')
.setEmployer('Oxynade')
.setDescription('Software developer')
.setFromYear(2009)
.setToYear(2010)
.setIconName('assets/images/oxynade-icon.png')
.setFromMonth('nov').setToMonth('apr')
];
const res = Array<CVTimeLineItem>();
temp.forEach(t => {
if (t.language === this.stateService.getLanguage()) {
res.push(t);
}
});
return res;
}
}

View File

@ -0,0 +1 @@
<app-post *ngIf="post !== undefined" [post]="post"></app-post>

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { FullpostComponent } from './fullpost.component';
describe('FullpostComponent', () => {
let component: FullpostComponent;
let fixture: ComponentFixture<FullpostComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ FullpostComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(FullpostComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,35 @@
import { Component, OnInit } from '@angular/core';
import {ActivatedRoute} from '@angular/router';
import {DataloaderService} from '../../services/dataloader.service';
import {Post} from '../../model/post';
import {StateService} from '../../services/state.service';
@Component({
selector: 'app-fullpost',
templateUrl: './fullpost.component.html',
styleUrls: ['./fullpost.component.scss']
})
export class FullpostComponent implements OnInit {
post: Post;
constructor(private route: ActivatedRoute, private dataloaderService: DataloaderService, private stateService: StateService) { }
ngOnInit() {
//get the id of the post from the route
this.route.paramMap.subscribe(params=>{
let id = params.get('id');
console.log('the fullpost component gets id: '+id);
//fetch the posts and make sure you get the right one
this.dataloaderService.getPosts().subscribe(posts => {
posts.forEach(post=>{
if(post.id === id) {
this.post = post;
}
});
});
});
}
}

View File

@ -0,0 +1,15 @@
<div class="panel panel-default">
<div class="panel-body text-center pageintro">
<app-languagetoggle [language]="'en'">
These pages are a mish-mash of things that I'd like to keep safe. Descriptions and photos of projects, so I don't
forget about them. Blog-style recollections of pieces of code, so I don't forget about them. Consider it a notepad
of some kind.
</app-languagetoggle>
<app-languagetoggle [language]="'nl'">
Deze web pagina's zijn een samenraapsel van verschillende dingen: notities over technische oplossingen die ik niet
opnieuw wil opzoeken, foto's en beschrijvingen van projecten die ik gedaan heb en nog zou willen doen, curriculum
vitae ... Kortom, alles wat je op een typische social media website zou vinden, maar dan in eigen beheer. Het is
ineens ook een excuus om wat met web technologie te prutsen, dat is altijd meegenomen.
</app-languagetoggle>
</div>
</div>

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { HomeComponent } from './home.component';
describe('HomeComponent', () => {
let component: HomeComponent;
let fixture: ComponentFixture<HomeComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ HomeComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(HomeComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should be created', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,17 @@
import { Component, OnInit } from '@angular/core';
import {ActivatedRoute, ParamMap} from '@angular/router';
import {StateService} from '../../services/state.service';
@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
constructor(private route: ActivatedRoute, private stateService: StateService) { }
ngOnInit() {
}
}

View File

@ -0,0 +1 @@
<ng-content *ngIf="show===true"></ng-content>

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { LanguagetoggleComponent } from './languagetoggle.component';
describe('LanguagetoggleComponent', () => {
let component: LanguagetoggleComponent;
let fixture: ComponentFixture<LanguagetoggleComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ LanguagetoggleComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(LanguagetoggleComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,55 @@
import {Component, Input, OnInit} from '@angular/core';
import {ActivatedRoute, NavigationEnd, Router} from '@angular/router';
import {StateService} from '../../services/state.service';
@Component({
selector: 'app-languagetoggle',
templateUrl: './languagetoggle.component.html',
styleUrls: ['./languagetoggle.component.scss']
})
export class LanguagetoggleComponent implements OnInit {
/**
* This is the language for which the component is defined. Typically, when the currently set language is equal to this variable,
* the component will be visible.
*/
@Input()
private language: string;
/**
* if this is set to true, the component will be visible
*/
show = false;
constructor(private router: Router, private route: ActivatedRoute, private stateService: StateService) {
}
ngOnInit() {
// start listening to the stateservice for language updates
this.stateService.getLanguageObservable().subscribe(val => {
console.log('language toggle gets a language update from state service: ' + val);
this.show = (this.language === val);
console.log(' after language update, show: ' + this.show);
});
}
private updateValues() {
const lang = this.stateService.getLanguage();
if (lang == null) {
console.log('languagetoggle: language is null from stateservice, ignoring');
return;
}
console.log('languagetoggle (' + this.language + ') gets lang: ' + lang);
if (lang === this.language) {
console.log('languagetoggle: showing the component ' + lang);
this.show = true;
} else {
console.log('languagetoggle: NOT showing the component ' + lang);
this.show = false;
}
console.log(`show: ${this.show }`);
}
}

View File

@ -0,0 +1,28 @@
<div class="post">
<div class="post-header">
<div class="post-date">
{{post.created_timestamp | simpledate}}
</div>
<div class="post-title">
<a routerLink="../post/{{post.id}}">{{getPostTitle()}}</a>
</div>
<div class="post-tags">
<div class="post-tag" *ngFor="let tag of post.tags">
<app-posttag [tag]=tag [class.highlight]="isActiveTag(tag)"></app-posttag>
</div>
</div>
</div>
<div class="post-body" #htmlcontainer></div>
<div class="more" *ngIf="shortVersion === true">
<a routerLink="../post/{{post.id}}">
<!--<i class="fa fa-file"></i>-->
<app-languagetoggle [language]="'en'">
> full post
</app-languagetoggle>
<app-languagetoggle [language]="'nl'">
> volle post
</app-languagetoggle>
</a>
</div>
</div>

View File

@ -0,0 +1,82 @@
//do the fonts
@import '../../../globals';
.post {
//font-family: $mainFont !important;
margin-top: 20px;
}
.post-header {
display: flex;
align-items: baseline;
margin: 0px 25px;
}
.post-title {
text-align: center;
flex-grow: 1;
font-size: 200%;
font-style: italic;
a {
color: #212529 !important;
}
}
.post-date {
flex-direction: row;
font-weight: bold;
font-style: italic;
}
.post-tags {
flex-direction: row-reverse;
}
.post-date, .post-tags {
display: flex;
align-items: flex-end;
width: 100px;
//need this to align the bottom of the texts with the bottom of the title text
//margin-bottom: 2px;
}
.post-body {
border-left: 1px solid black;
padding-left: 25px;
border-right: 1px solid black;
padding-right: 25px;
text-align: justify;
}
/**
This is a work-around for the innerHTML. Apparently, angular can style this is :host ::ng-deep is added. Fucked up.
*/
:host ::ng-deep .post-body p:last-child {
margin-bottom: 0px;
}
/**
Custom coloring for the links.
*/
:host ::ng-deep a {
color: darkorange;
}
.post-tag {
color: lightgrey;
.highlight {
color: grey;
}
}
.more {
border-left: 1px solid black;
border-right: 1px solid black;
padding-left: 25px;
padding-top: 10px;
}

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { PostComponent } from './post.component';
describe('PostComponent', () => {
let component: PostComponent;
let fixture: ComponentFixture<PostComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ PostComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(PostComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should be created', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,89 @@
import {Component, OnInit, Input, ViewChild, ElementRef} from '@angular/core';
import { Post } from 'app/model/post';
import { DataloaderService } from 'app/services/dataloader.service';
import {StateService} from '../../services/state.service';
@Component({
selector: 'app-post',
templateUrl: './post.component.html',
styleUrls: ['./post.component.scss']
})
export class PostComponent implements OnInit {
@Input() post: Post;
/**
* If this is set to true, the post component can reconfigure itself to display a short version. If false, it just shows the full version.
*/
@Input() canBeShort: boolean;
@ViewChild('htmlcontainer')
htmlContainer: ElementRef;
/**
* A variable that indicates whether the component is displaying a short or long version.
* @type {boolean}
*/
shortVersion = false;
/**
* Construct the PostComponent.
*
* @param {DataloaderService} dataloaderService
* @param {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);
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.setContent(content);
});
this.stateService.getLanguageObservable().subscribe(language => {
// change the content: language has been updated
this.dataloaderService.getFullHtml(this.post, language).subscribe(content => {
this.setContent(content);
});
});
console.log('PostComponent.ngOnInit is done.');
}
/**
* Set the content in a clever way: if the post component is set to a short version, this can fix that up.
* @param {String} content
*/
private setContent(content:String) {
if(this.canBeShort) {
const split = content.split("<splitter/>");
if(split.length==2) {
//only show the first one
this.htmlContainer.nativeElement.innerHTML = split[0];
this.shortVersion = true;
} else {
this.htmlContainer.nativeElement.innerHTML = content;
this.shortVersion = false;
}
} else {
this.htmlContainer.nativeElement.innerHTML = content;
this.shortVersion = false;
}
}
isActiveTag(tag: string): boolean {
return this.stateService.isActiveTag(tag);
}
getPostTitle() {
return this.post.title[this.stateService.getLanguage()];
}
}

View File

@ -0,0 +1,6 @@
<div [ngSwitch]="tag" [class.highlight]="highlight">
<ng-template [ngSwitchCase]= "'tech'"><i class="fa fa-microchip"></i></ng-template>
<ng-template [ngSwitchCase]= "'project'"><i class="fa fa-wrench"></i></ng-template>
<ng-template [ngSwitchCase]= "'blog'"><i class="fa fa-microphone"></i></ng-template>
<ng-template ngSwitchDefault><i class="fa fa-question-circle"></i></ng-template>
</div>

View File

@ -0,0 +1,3 @@
div {
margin-left: 8px;
}

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { PosttagComponent } from './posttag.component';
describe('PosttagComponent', () => {
let component: PosttagComponent;
let fixture: ComponentFixture<PosttagComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ PosttagComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(PosttagComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,21 @@
import {Component, Input, OnInit} from '@angular/core';
import {Post} from '../../../model/post';
import {StateService} from '../../../services/state.service';
@Component({
selector: 'app-posttag',
templateUrl: './posttag.component.html',
styleUrls: ['./posttag.component.scss']
})
export class PosttagComponent implements OnInit {
@Input() tag: string;
@Input() highlight: boolean;
constructor() {
}
ngOnInit() {
}
}

View File

@ -0,0 +1,12 @@
<div id="tag-filter-buttons-container">
<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 filteredPosts' [post]="post" [canBeShort] = true></app-post>
</div>

View File

@ -0,0 +1,25 @@
#tag-filter-buttons-container {
text-align: center;
margin-top: -16pt;
.btn.active {
color: grey;
}
.btn:hover {
color: darkorange;
}
.btn.active:hover {
color: darkgoldenrod;
}
.btn {
color: lightgrey;
background-color: white;
border: none;
padding: 0pt 3pt;
}
}

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { PostsComponent } from './posts.component';
describe('PostsComponent', () => {
let component: PostsComponent;
let fixture: ComponentFixture<PostsComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ PostsComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(PostsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should be created', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,112 @@
import {Component, OnDestroy, OnInit} from '@angular/core';
import {DataloaderService} from 'app/services/dataloader.service';
import {StateService} from '../../services/state.service';
import {Post} from '../../model/post';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/merge';
import 'rxjs/add/operator/concatMap';
import 'rxjs/add/observable/from';
import 'rxjs/add/operator/distinct';
@Component({
selector: 'app-posts',
templateUrl: './posts.component.html',
styleUrls: ['./posts.component.scss']
})
export class PostsComponent implements OnInit, OnDestroy {
allPosts: Post[];
filteredPosts: Post[];
tags = new Array<string>();
constructor(private dataloaderService: DataloaderService, private stateService: StateService) {
}
ngOnDestroy(): void {
// console.log('PostsComponent.ngOnDestroy called');
}
ngOnInit() {
// console.log('PostsComponent ngOnInit()');
// fetch the posts
const posts2 = this.dataloaderService.getPosts();
posts2.subscribe(p => {
this.allPosts = p;
//figure out the different tags so we can filter on them
const temptags = new Array<string>();
this.allPosts.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));
//do the first filtered update!
this.updateFilteredPosts(this.stateService.getLanguage());
});
console.log('PostsComponent ngOnInit() is done');
//we start listening to language changes
this.stateService.getLanguageObservable().subscribe(language => {
console.log('posts component needs to switch languages!');
this.updateFilteredPosts(language);
});
}
filterOnType(type: String): void {
}
/**
* Something happened and we need to update our filtering. This includes the tags or language changes. Afterwards, 'filteredPosts' should
* contain the new modified list of posts.
* @returns {Post[]}
*/
updateFilteredPosts(language: string) {
console.log('updating filtered posts for language ' + language);
const res = new Array<Post>();
if (this.allPosts == null) {
return res;
}
for (const post of this.allPosts) {
// 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(language) >= 0) {
res.push(post);
}
} else {
// console.log('we should not display this');
}
}
// sort the posts
console.log('sorting posts!');
res.sort((p1, p2) => {
console.log(p1.created_timestamp.getTime()+' '+p2.created_timestamp.getTime())
return p2.created_timestamp.getTime() - p1.created_timestamp.getTime();
});
//set the result! this will update the list of the /posts page
this.filteredPosts = res;
}
toggleTag(tag: string) {
this.stateService.toggleTag(tag);
this.updateFilteredPosts(this.stateService.getLanguage());
}
isActiveTag(tag: string): boolean {
return this.stateService.isActiveTag(tag);
}
}

View File

@ -0,0 +1,53 @@
<!--this is bootstrap super container-->
<div class="container-fluid">
<div class="row" id="namerow">
<div class="col-md-8 offset-md-2">
<div class="centercontents" id="topname" [class.active]="mousingOver === null">
<span class="display-1" id="first">Joachim</span><span id="dot">.</span><span id="last" class="display-1">Nielandt</span>
</div>
<div class="" id="highlightedlink" [class.active]="mousingOver !== null">
{{mousingOver}}
</div>
</div>
</div>
<!--the top menu... should be always visible, everywhere-->
<div class="row">
<div class="col-md-8 offset-md-2 centercontents">
<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('blog')" (mouseover)="mouseOver('Blog')"><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-heartbeat fa-fw fa-2x" aria-hidden="true"></i></a>
<a routerLink="contact" (mouseout)="mouseOut('contact')" (mouseover)="mouseOver('Contact')"><i
class="fa fa-address-card fa-fw fa-2x" aria-hidden="true"></i></a>
<a (click)="toggleLanguage()" (mouseout)="mouseOut('lang')"
(mouseover)="mouseOver('lang')"><i class="fa fa-language fa-fw fa-2x"
aria-hidden="true"></i></a>
</div>
</div>
</div>
<!--row-->
</div>
<div class="row">
<div class="col-md-8 offset-md-2">
<div class="pagetype">
{{pageType}}
</div>
</div>
</div>
<!--this shows the current route's content-->
<div class="row">
<div class="col-md-8 offset-md-2">
<router-outlet></router-outlet>
</div>
</div>
</div>

View File

@ -0,0 +1,84 @@
@import "../../../globals";
#namerow {
height: 66pt;
}
.centercontents {
text-align: center;
margin-left: auto;
margin-right: auto
}
#topname {
//font-family: $mainFont;
margin-top: 25px;
padding-bottom: 9px;
font-size: 80%;
color: lighten(black, 90%);
transition: font-size 0.15s ease, color 0.15s;
}
#topname.active {
font-size: 100%;
color: black;
transition: font-size 0.30s ease, color 0.15s;
}
#topname #first {
font-size: 250%
}
#topname #dot {
line-height: 20pt;
font-size: 600%;
}
#topname #last {
font-size: 150%;
}
#topmenubuttons, #topname {
//border-left: 1px solid black;
//border-right: 1px solid black;
}
//this is the row below the name, will use this for styling
.row.below-name {
}
.pagetype {
text-align: center;
font-size: 200%;
border-bottom: 1px solid black;
border-top: 1px solid black;
margin: 35px 30px 25px 30px;
}
#topmenubuttons {
a {
color: lightgrey;
}
a:hover {
color: darkorange;
}
}
#highlightedlink {
color: gray;
opacity: 0;
//background-color: aqua;
position: absolute;
width: 100%;
bottom: 0px;
left: 0px;
font-size: 89%;
text-align: center;
transition: opacity 0.5s ease-in-out;
}
#highlightedlink.active {
opacity: 1;
transition: opacity 0.5s ease-in-out;
}

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { RootComponent } from './root.component';
describe('RootComponent', () => {
let component: RootComponent;
let fixture: ComponentFixture<RootComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ RootComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(RootComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,115 @@
import {Component, OnInit} from '@angular/core';
import {ActivatedRoute, NavigationEnd, ParamMap, Router} from '@angular/router';
import {StateService} from '../../services/state.service';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/first';
@Component({
selector: 'app-root',
templateUrl: './root.component.html',
styleUrls: ['./root.component.scss']
})
export class RootComponent implements OnInit {
title = 'Joachim Homepage';
mousingOver: string = null;
pageType: string;
constructor(private router: Router, private route: ActivatedRoute, private stateService: StateService) {
}
ngOnInit() {
// 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)
// });
/**
* 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);
// }
// });
// set the service, we know that this route is the one we need for language changes (parameter), so we gotta keep track of it
this.stateService.setRootRoute(this.route);
// 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 = 'Blog';
} else if (this.router.url.endsWith('cv')) {
this.pageType = 'Curriculum Vitae';
} else if (this.router.url.endsWith('home')) {
this.pageType = 'Home';
} else if (this.router.url.endsWith('posts')) {
this.pageType = 'Blog';
} else if (this.router.url.indexOf("post")!=-1) {
this.pageType = 'Blog post';
} else if (this.router.url.indexOf("contact")!=-1) {
this.pageType = 'Contact';
} else {
this.pageType = 'Joa did something wrong...';
}
}
mouseOver(s: string) {
// console.log('mouseover!' + s);
// do some translation
let language = this.stateService.getLanguage();
if (s === 'lang') {
if (language === 'nl') {
this.mousingOver = 'Taal: Nederlands';
} else if (language = 'en') {
this.mousingOver = 'Language: English';
} else {
this.mousingOver = 'Language: Yaaarrrr matey!';
}
} else {
// default: use the passed string
this.mousingOver = s;
}
}
mouseOut(s: string) {
this.mousingOver = null;
}
toggleLanguage() {
console.log('toggleLanguage called');
if (this.stateService.getLanguage() === 'nl') {
console.log(' > toggle switched to en');
this.stateService.setLanguage('en', this.route, this.router);
this.mouseOver('lang');
} else if (this.stateService.getLanguage() === 'en') {
this.stateService.setLanguage('nl', this.route, this.router);
this.mouseOver('lang');
console.log(' > toggle switched to nl');
} else {
console.log(' > Could not toggle the language, pirates stole your tongue.');
}
}
}

View File

@ -0,0 +1,60 @@
export class CVTimeLineItem {
language: string;
employer: string;
fromYear: number;
toYear: number;
title: string;
description: string;
iconName: string;
fromMonth: string;
toMonth: string;
constructor() {
}
setIconName(iconName: string): CVTimeLineItem {
this.iconName = iconName;
return this;
}
setFromMonth(fromMonth: string) : CVTimeLineItem {
this.fromMonth = fromMonth;
return this;
}
setToMonth(toMonth: string) : CVTimeLineItem {
this.toMonth = toMonth;
return this;
}
setLanguage(language:string): CVTimeLineItem {
this.language = language;
return this;
}
setToYear(toYear: number): CVTimeLineItem {
this.toYear = toYear;
return this;
}
setFromYear(fromYear : number) : CVTimeLineItem {
this.fromYear = fromYear;
return this;
}
setDescription(description: string) : CVTimeLineItem {
this.description = description;
return this;
}
setEmployer(employer: string) : CVTimeLineItem {
this.employer = employer;
return this;
}
setTitle(title: string): CVTimeLineItem {
this.title = title;
return this;
}
}

13
src/app/model/post.ts Normal file
View File

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

View File

@ -0,0 +1,8 @@
import { PosttypepipePipe } from './posttypepipe.pipe';
describe('PosttypepipePipe', () => {
it('create an instance', () => {
const pipe = new PosttypepipePipe();
expect(pipe).toBeTruthy();
});
});

View File

@ -0,0 +1,13 @@
import { Pipe, PipeTransform } from '@angular/core';
import { Post } from 'app/model/post';
@Pipe({
name: 'posttypepipe'
})
export class PosttypepipePipe implements PipeTransform {
transform(posts: Post[], args?: any): any {
return posts.filter(post=>post.type == args);
}
}

View File

@ -0,0 +1,16 @@
import { Pipe, PipeTransform } from '@angular/core';
/*
* Raise the value exponentially
* Takes an exponent argument that defaults to 1.
* Usage:
* value | exponentialStrength:exponent
* Example:
* {{ 2 | exponentialStrength:10 }}
* formats to: 1024
*/
@Pipe({name: 'simpledate'})
export class SimpledatePipe implements PipeTransform {
transform(date: Date): string {
return date.toLocaleDateString();
}
}

View File

@ -0,0 +1,15 @@
import { TestBed, inject } from '@angular/core/testing';
import { DataloaderService } from './dataloader.service';
describe('DataloaderService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [DataloaderService]
});
});
it('should be created', inject([DataloaderService], (service: DataloaderService) => {
expect(service).toBeTruthy();
}));
});

View File

@ -0,0 +1,62 @@
import { Injectable } from '@angular/core';
import { Post } from '../model/post';
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 {
constructor(private http: HttpClient) { }
getPosts(): Observable<Post[]> {
return this.http.get('assets/posts.json').map(posts => {
const res: Post[] = [];
// fill it up
for (const index in posts) {
const post: any = posts[index];
// 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);
res.push(temp);
}
// console.log('these are the posts...');
// console.log(res);
return res;
});
}
/**
* 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
*/
getFullHtml(post: Post, language: string): Observable<String> {
const httpOptions = {
headers: new HttpHeaders({ 'Content-Type': 'text/html', 'Accept': 'text/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.');
}
}
}

View 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();
}));
});

View File

@ -0,0 +1,149 @@
import {Injectable, OnInit} from '@angular/core';
import {Post} from '../model/post';
import {ActivatedRoute, ParamMap, Router} from '@angular/router';
import 'rxjs/add/operator/filter';
@Injectable()
export class StateService {
// this keeps track of which type is enabled / disabled
private tagFilter: any = [];
private language: string;
private rootRoute: ActivatedRoute;
constructor(private router: Router) {
router.events.subscribe(event => {
// console.log('stateservice detects a route event!' + event);
});
}
// /**
// * 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 {
// console.log('state service url: ' + this.router.url);
// check whether all filters are true or false: that case, just show everything
let foundTrue = false;
let foundFalse = false;
for (const 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 (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
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];
}
}
/**
* Get the currently set language.
* @returns {string}
*/
getLanguage() {
return this.language;
}
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;
console.log('GOING TO NAVIGATE!');
console.log(this.rootRoute.url);
//ok, don't know how to do this cleanly... figure out 2 elements
//1: the language, we already know it
//2: the child path element, just get it from the rootroute
if (this.rootRoute.children.length !== 1) {
console.log('the root route has more than 1 child :/ NOT navigating now...');
console.log(this.rootRoute.children);
} else {
const childRoute = this.rootRoute.children[0];
// console.log('childroute: ' + childRoute.toString() + ' ' + childRoute.url.toString());
// console.log(childRoute);
const navigationpath = new Array<string>();
navigationpath.push(language);
childRoute.url.forEach(segments => {
// console.log('url segments');
// console.log(segments);
//add each of these segments to the navigation path
segments.forEach(s => navigationpath.push(s.path.toString()));
});
// console.log('OUR navigation path');
// console.log(navigationpath);
//actually navigate!
this.router.navigate(navigationpath);
}
this.rootRoute.pathFromRoot.forEach(p => console.log(p));
this.rootRoute.firstChild.fragment.subscribe(val => {
console.log('rootRoute.firstChild.fragment: ' + val);
});
// router.navigate([language]);
} else {
console.log('setting language did nothing: no navigation.')
}
}
getLanguageObservable() {
return this.rootRoute.paramMap.map(map => map.get('language'));
}
setRootRoute(route: ActivatedRoute) {
this.rootRoute = route;
this.rootRoute.paramMap.map(map => map.get('language')).filter(l => l !== null).subscribe(l => {
this.language = l;
console.log('stateservice updated its internal lang value to ' + this.language);
}
)
;
}
}

0
src/assets/.gitkeep Normal file
View File

View File

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Some files were not shown because too many files have changed in this diff Show More