Browse Source

refactor

master
Milan Pässler 5 months ago
parent
commit
acc2425d2e

+ 0
- 3
.eslintignore View File

@@ -1,3 +0,0 @@
1
-dist/**
2
-dev/**
3
-tmp/**

+ 0
- 13
.eslintrc.js View File

@@ -1,13 +0,0 @@
1
-module.exports = {
2
-	"parser": "babel-eslint",
3
-	"extends": "eslint-config-standard",
4
-	"rules": {
5
-		"indent": ["error", "tab"],
6
-		"no-tabs": "off",
7
-		"semi": [2, "always"],
8
-		"no-extra-semi": 2,
9
-		"semi-spacing": [2, { "before": false, "after": true }],
10
-		"no-template-curly-in-string": "off"
11
-	},
12
-	"env": {"node": true, "browser": true, "worker": true}
13
-};

+ 0
- 5
.gitignore View File

@@ -1,5 +0,0 @@
1
-dist
2
-dev
3
-tmp
4
-node_modules
5
-yarn-error.log

+ 0
- 11
Dockerfile View File

@@ -1,11 +0,0 @@
1
-FROM node:latest
2
-RUN mkdir /app
3
-WORKDIR /app
4
-ADD . /app
5
-RUN npm i -g yarn
6
-RUN yarn
7
-RUN ./node_modules/.bin/gulp
8
-RUN apt-get update -y -qq; apt-get install nginx -y -qq
9
-RUN cp nginx.conf.dev.example /etc/nginx/nginx.conf
10
-RUN cp -r dist/ /usr/share/nginx/;
11
-CMD ["nginx", "-g", "daemon off;"]

+ 0
- 13
README.md View File

@@ -1,13 +0,0 @@
1
-# deepart.ai Frontend
2
-
3
-This repository contains the frontend for deepart.ai. It is used to present the project, display rendered images and collect input from the user.
4
-
5
-## Development
6
-
7
-You will need current versions of NodeJS, [the yarn package manager](https://yarnpkg.com/) and NGINX. Use the NGINX configuration provided and change the URL to the backend. 
8
-* Run `yarn` to install the dependencies required for the build process
9
-* Run `node_modules/.bin/gulp` to build the project
10
-* Run `node_modules/.bin/gulp watch` to let gulp watch for changes in the project and automatically rebuild
11
-* The output will be located in the `dist` directory
12
-
13
-* Make sure your NGINX version is greater than 1.13.9! *

+ 0
- 12
app/main.js View File

@@ -1,12 +0,0 @@
1
-'use strict';
2
-
3
-import { router } from './router';
4
-
5
-router.go(window.location.pathname);
6
-
7
-const sw = navigator.serviceWorker;
8
-if (sw) {
9
-	sw.register('/sw.js', {
10
-		scope: '/'
11
-	});
12
-}

BIN
app/placeholder.png View File


+ 0
- 5
app/router/index.js View File

@@ -1,5 +0,0 @@
1
-'use strict';
2
-
3
-export * from './router';
4
-export * from './register';
5
-

+ 0
- 10
app/router/register.js View File

@@ -1,10 +0,0 @@
1
-'use strict';
2
-
3
-import { router } from '../router';
4
-import * as routes from '../routes';
5
-
6
-router.route(/^.*$/, routes.header);
7
-router.route(/^\/?$/, routes.about);
8
-router.route(/^\/feed$/, routes.feed);
9
-router.route(/^\/gallery$/, routes.gallery);
10
-router.route(/^.*$/, routes.notfound);

+ 0
- 47
app/router/router.js View File

@@ -1,47 +0,0 @@
1
-'use strict';
2
-
3
-class Router {
4
-	constructor() {
5
-		this.routes = [];
6
-
7
-		window.onpopstate = (evt) => {
8
-			this.go(window.location.pathname);
9
-		};
10
-
11
-		document.onclick = (evt) => {
12
-			for (let el of evt['composedPath']()) {
13
-				if (el.href && el.href.startsWith(window.location.origin) && this.go(el.pathname)) {
14
-					evt.preventDefault();
15
-					return false;
16
-				}
17
-			}
18
-			return true;
19
-		};
20
-	}
21
-
22
-	go(path) {
23
-		let routes = this.routes.map(r => { return { route: r, match: r.path.exec(path) } }).filter(r => r.match);
24
-
25
-		if (!routes.length) return false;
26
-
27
-		history.pushState({}, '', path);
28
-
29
-		let self = this;
30
-		// returns a promise, which is truthy
31
-		return (async () => {
32
-			for (let { route, match } of routes) {
33
-				let res = await route.func(match);
34
-				if (res) break;
35
-			}
36
-		}) ();
37
-	}
38
-
39
-	route(path, func) {
40
-		this.routes.push({
41
-			path: path,
42
-			func: func
43
-		});
44
-	}
45
-}
46
-
47
-export const router = new Router();

+ 0
- 12
app/routes/about.js View File

@@ -1,12 +0,0 @@
1
-'use strict';
2
-
3
-import { render } from 'lit-html';
4
-import { tag } from '../util';
5
-import { about as aboutTemplate } from '../templates';
6
-
7
-export const about = async () => {
8
-	render(aboutTemplate(), tag('main'));
9
-	return true;
10
-};
11
-
12
-

+ 0
- 12
app/routes/feed.js View File

@@ -1,12 +0,0 @@
1
-'use strict';
2
-
3
-import { render } from 'lit-html';
4
-import { tag } from '../util';
5
-import { feed as feedTemplate } from '../templates';
6
-
7
-export const feed = async () => {
8
-	//render(feedTemplate(notes), tag('main'));
9
-	//return true;
10
-};
11
-
12
-

+ 0
- 111
app/routes/gallery.js View File

@@ -1,111 +0,0 @@
1
-'use strict';
2
-
3
-import { render } from 'lit-html';
4
-import { tag, cssClass, selAll, id, sleep } from '../util';
5
-import { gallery as galleryTemplate } from '../templates';
6
-
7
-export const gallery = async () => {
8
-	const apiUri = 'http://127.0.0.1:5000/api/';
9
-
10
-	const get = (path) => fetch(apiUri + path, {cache: "no-store"});
11
-
12
-	let nnId = '';
13
-	let images = [];
14
-	let data = {};
15
-	let j = 0;
16
-
17
-
18
-	const nextSet = async (selected) => {
19
-		render(galleryTemplate(images, true), tag('main'));
20
-		images = [];
21
-
22
-		let newId;
23
-		if (selected !== undefined) {
24
-			await get('answer/' + nnId + '/' + selected);
25
-			do {
26
-				newId = await get('get_latest_id').then(resp => resp.text());
27
-				await sleep(200);
28
-			} while (newId === nnId);
29
-			nnId = newId;
30
-		} else {
31
-			nnId = await get('get_latest_id').then(resp => resp.text());
32
-		}
33
-		data = await get('get_latest_data').then(resp => resp.json());
34
-
35
-		j = 0;
36
-		let size = 128;
37
-		let canvas = document.createElement('canvas');
38
-		canvas.height = size;
39
-		canvas.width = size;
40
-		let ctx = canvas.getContext('2d');
41
-		Object.keys(data).forEach((index) => {
42
-			let artwork = data[index];
43
-			ctx.clearRect(0, 0, size, size);
44
-			artwork['objects'].forEach((obj) => {
45
-				let first = obj['points'].shift();
46
-				let x = first['x'] * size;
47
-				let y = first['y'] * size;
48
-				let r = Math.round(first['r']*255);
49
-				let g = Math.round(first['g']*255);
50
-				let b = Math.round(first['b']*255);
51
-				ctx.fillStyle = `rgba(${r}, ${g}, ${b}, 1)`;
52
-				ctx.moveTo(x, y);
53
-				ctx.beginPath();
54
-				if (obj['radius']) {
55
-					let radius = obj['radius'] * size;
56
-					if (radius < 0) {
57
-						console.warn('oops, radius was < 0: ' + radius);
58
-					} else {
59
-						ctx.arc(x, y, radius, 0, 2 * Math.PI, false);
60
-					}
61
-				} else {
62
-					let second = obj['points'][0];
63
-					let x2 = second['x'] * size;
64
-					let y2 = second['y'] * size;
65
-					let r2 = Math.round(second['r']*255);
66
-					let g2 = Math.round(second['g']*255);
67
-					let b2 = Math.round(second['b']*255);
68
-					let grd = ctx.createLinearGradient(x, y, x2, y2);
69
-					grd.addColorStop(0, `rgba(${r}, ${g}, ${b}, 1)`);
70
-					grd.addColorStop(1, `rgba(${r2}, ${g2}, ${b2}, 1)`);
71
-					ctx.fillStyle = grd;
72
-					console.log(obj['points'].length);
73
-					obj['points'].forEach((point) => {
74
-						ctx.lineTo(point['x'] * size, point['y'] * size);
75
-					});
76
-				}
77
-				ctx.closePath();
78
-				ctx.fill();
79
-			});
80
-			images.push({
81
-				id: index,
82
-				url: canvas.toDataURL("image/png")
83
-			});
84
-		});
85
-
86
-		render(galleryTemplate(images), tag('main'));
87
-	}
88
-
89
-	await nextSet();
90
-
91
-	let i = 0;
92
-
93
-	cssClass('grid').onclick = (evt) => {
94
-		if (evt.target.tagName !== 'IMG') return;
95
-		let id = evt.target.getAttribute('data-id');
96
-		/*images[id].selected = ++i;
97
-		render(galleryTemplate(images), tag('main'));
98
-		i = 0;
99
-		let selectedId = images.filter(i => i.selected === 1)[0].id;*/
100
-		nextSet(id);
101
-	};
102
-
103
-	id('next').onclick = () => {
104
-		i = 0;
105
-		let selectedId = images.filter(i => i.selected === 1)[0].id;
106
-		nextSet(selectedId);
107
-	};
108
-
109
-	return true;
110
-};
111
-

+ 0
- 12
app/routes/header.js View File

@@ -1,12 +0,0 @@
1
-'use strict';
2
-
3
-import { render } from 'lit-html';
4
-import { tag } from '../util';
5
-import { header as headerTemplate } from '../templates';
6
-
7
-export const header = async () => {
8
-	render(headerTemplate(), tag('header'));
9
-	return false;
10
-};
11
-
12
-

+ 0
- 7
app/routes/index.js View File

@@ -1,7 +0,0 @@
1
-'use strict';
2
-
3
-export * from './header';
4
-export * from './about';
5
-export * from './gallery';
6
-export * from './feed';
7
-export * from './notfound';

+ 0
- 12
app/routes/notfound.js View File

@@ -1,12 +0,0 @@
1
-'use strict';
2
-
3
-import { render } from 'lit-html';
4
-import { tag } from '../util';
5
-import { notfound as notfoundTemplate } from '../templates';
6
-
7
-export const notfound = async () => {
8
-	render(notfoundTemplate(), tag('main'));
9
-	return true;
10
-};
11
-
12
-

+ 0
- 9
app/templates/feed.js View File

@@ -1,9 +0,0 @@
1
-'use strict';
2
-
3
-import { html } from 'lit-html';
4
-
5
-export const feed = (images) => html`
6
-	${images.map(image => html`
7
-		<img id="image-${image.id}" src="${image.url}">
8
-	`)}
9
-`;

+ 0
- 31
app/templates/gallery.js View File

@@ -1,31 +0,0 @@
1
-'use strict';
2
-
3
-import { html } from 'lit-html';
4
-
5
-export const gallery = (images, loading) => html`
6
-	<div class="container gallery">
7
-		<div class="grid">
8
-			${images.map(image => html`
9
-				<div class="image">
10
-					<img data-id="${image.id}" src="${image.url}">
11
-					${image.selected ? html`
12
-						<div class="selected">
13
-							<span>${image.selected}</span>
14
-						</div>
15
-					` : ''}
16
-				</div>
17
-			`)}
18
-		</div>
19
-	</div>
20
-	${loading ? html`
21
-		<div class="loading">
22
-			<div class="spinner"></div>
23
-		</div>
24
-	` : ''}
25
-	<div class="nav">
26
-		<div class="container">
27
-			<span>Select the image you like most</span>
28
-			<a id="next">next &rarr;</a>
29
-		</div>
30
-	</div>
31
-`;

+ 0
- 7
app/templates/index.js View File

@@ -1,7 +0,0 @@
1
-'use strict';
2
-
3
-export * from './header';
4
-export * from './about';
5
-export * from './gallery';
6
-export * from './feed';
7
-export * from './notfound';

+ 0
- 17
app/test.json View File

@@ -1,17 +0,0 @@
1
-[{ "objects": [
2
-{ "points": [
3
-{ "x": 0.1727069605634174, "y":0.2938186297533175, "r":0.6072802997831339, "g":0.7070856195443572, "b":0.328747493128542}, 
4
-{ "x": 0.834534709716035, "y":0.4790838730176238, "r":0.1839384892592466, "g":0.3150057714363551, "b":0.530200550767832}]}, 
5
-{ "points": [
6
-{ "x": 0.7028128824864439, "y":0.37338853853277376, "r":0.34705663392966657, "g":0.4626718483581611, "b":0.9316975958903573}, 
7
-{ "x": 0.9968856890116655, "y":0.42191242676440743, "r":0.8474157112554067, "g":0.12301865052026395, "b":0.06680346251937574}]}, 
8
-{ "points": [
9
-{ "x": 0.7145907584984006, "y":0.2558619087286895, "r":0.19983946106328743, "g":0.004981112104021634, "b":0.5524829644289931}, 
10
-{ "x": 0.7481266271627567, "y":0.09465811289937631, "r":0.2181874052314151, "g":0.010777328976116718, "b":0.08164538686580713}, 
11
-{ "x": 0.9196925402391931, "y":0.17973941598139265, "r":0.40044277713053045, "g":0.8088438484739763, "b":0.06272046034487111}, 
12
-{ "x": 0.2547628334548119, "y":0.3903890045677447, "r":0.10579509990576974, "g":0.07433816160278961, "b":0.11553917995773155}]}, 
13
-{ "points": [
14
-{ "x": 0.8896804894745697, "y":0.552054058685631, "r":0.2724616900004492, "g":0.23015247807544836, "b":0.5313836031496667}, 
15
-{ "x": 0.9563299781198908, "y":0.5268888216603523, "r":0.5045544034252369, "g":0.9639100903638727, "b":0.7242239500573145}]}, 
16
-{ "points": [
17
-{ "x": 0.7277520565512419, "y":0.06258703792372788, "r":0.6674900130914164, "g":0.6857541456240441, "b":0.22736196574847078}], "radius": 0.5}]}]

app/deepart.ai.png → deepart.ai.png View File


app/deepart.ai.svg → deepart.ai.svg View File


app/deepart.ai128.png → deepart.ai128.png View File


app/deepart.ai256.png → deepart.ai256.png View File


app/deepart.ai512.png → deepart.ai512.png View File


app/deepart.ai64.png → deepart.ai64.png View File


app/fonts/source-code-pro-v7-latin-500.woff → fonts/source-code-pro-v7-latin-500.woff View File


app/fonts/source-code-pro-v7-latin-500.woff2 → fonts/source-code-pro-v7-latin-500.woff2 View File


app/fonts/source-code-pro-v7-latin-700.woff → fonts/source-code-pro-v7-latin-700.woff View File


app/fonts/source-code-pro-v7-latin-700.woff2 → fonts/source-code-pro-v7-latin-700.woff2 View File


app/fonts/source-code-pro-v7-latin-regular.woff → fonts/source-code-pro-v7-latin-regular.woff View File


app/fonts/source-code-pro-v7-latin-regular.woff2 → fonts/source-code-pro-v7-latin-regular.woff2 View File


+ 0
- 128
gulpfile.js View File

@@ -1,128 +0,0 @@
1
-const gulp = require('gulp');
2
-const pump = require('pump');
3
-const rollupPluginUglify = require('rollup-plugin-uglify');
4
-const rollupPluginResolve = require('rollup-plugin-node-resolve');
5
-const rollup = require('rollup-stream');
6
-const loadGulpPlugins = require('gulp-load-plugins');
7
-const cleanCss = require('postcss-clean');
8
-const normalize = require('postcss-normalize');
9
-const importCss = require('postcss-import');
10
-const nested = require('postcss-nested');
11
-const autoprefixer = require('autoprefixer');
12
-const source = require('vinyl-source-stream');
13
-const { minify } = require('uglify-es');
14
-const { execSync } = require('child_process');
15
-const { readFileSync } = require('fs');
16
-
17
-const gulpPlugins = loadGulpPlugins();
18
-const browsers = ['>2% in DE'];
19
-
20
-function gitRevision () {
21
-	return execSync('git describe --tags --always --abbrev=7 --dirty', { cwd: __dirname }).toString().trim();
22
-}
23
-
24
-gulp.task('clean', (cb) => {
25
-	execSync('rm -rf dist/* dev/* tmp/*', { cwd: __dirname });
26
-	cb();
27
-});
28
-
29
-gulp.task('js', (cb) => {
30
-	pump([
31
-		rollup({
32
-			input: 'app/main.js',
33
-			format: 'iife',
34
-			plugins: [
35
-				rollupPluginResolve(),
36
-				rollupPluginUglify({
37
-					toplevel: true,
38
-					mangle: {
39
-						properties: {
40
-							builtins: false,
41
-							reserved: require('./node_modules/uglify-es/tools/domprops.json').concat([
42
-								'objects', 'points', 'radius'
43
-							]),
44
-							keep_quoted: true
45
-						}
46
-					},
47
-				}, minify)
48
-			]
49
-		}),
50
-		source('main.js'),
51
-		gulpPlugins.replace('\n', ''),
52
-		gulpPlugins.replace('\\n', ''),
53
-		gulpPlugins.replace('\t', ''),
54
-		gulpPlugins.replace('\\t', ''),
55
-		gulpPlugins.replace('__GIT_REVISION', gitRevision()),
56
-		gulpPlugins.replace('__BUILD_DATE', new Date().valueOf()),
57
-		gulp.dest('dist')
58
-	], cb);
59
-});
60
-
61
-gulp.task('sw', (cb) => {
62
-	pump([
63
-		rollup({
64
-			input: 'app/sw.js',
65
-			format: 'es',
66
-			plugins: [
67
-				rollupPluginUglify({
68
-					toplevel: true
69
-				}, minify)
70
-			]
71
-		}),
72
-		source('sw.js'),
73
-		gulpPlugins.replace('__BUILD_DATE', new Date().valueOf()),
74
-		gulp.dest('dist')
75
-	], cb);
76
-});
77
-
78
-gulp.task('css', (cb) => {
79
-	pump([
80
-		gulp.src('app/main.css'),
81
-		gulpPlugins.postcss([
82
-			normalize({
83
-				browsers: browsers
84
-			}),
85
-			autoprefixer({
86
-				browsers: browsers
87
-			}),
88
-			cleanCss()
89
-		]),
90
-		gulp.dest('tmp')
91
-	], cb);
92
-});
93
-
94
-gulp.task('copy', (cb) => {
95
-	pump([
96
-		gulp.src(['app/**', '!app/**/*.{html,css,js}', '!app/manifest.json'], { dot: true }),
97
-		gulp.dest('dist')
98
-	], cb);
99
-});
100
-
101
-gulp.task('html', (cb) => {
102
-	pump([
103
-		gulp.src('app/index.html'),
104
-		gulpPlugins.htmlmin({ collapseWhitespace: true }),
105
-		gulpPlugins.replace('${INLINE_CSS}', readFileSync('tmp/main.css')),
106
-		gulp.dest('dist')
107
-	], cb);
108
-});
109
-
110
-gulp.task('manifest', (cb) => {
111
-	pump([
112
-		gulp.src('app/manifest.json'),
113
-		gulpPlugins.jsonminify(),
114
-		gulp.dest('dist')
115
-	], cb);
116
-});
117
-
118
-gulp.task('dist', gulp.parallel('clean', 'copy', 'js', gulp.series('css', 'html'), 'manifest', 'sw'));
119
-
120
-gulp.task('watch', gulp.series('dist', () => {
121
-	gulp.watch('app/**/*.js', gulp.series('js', 'html', 'sw'));
122
-	gulp.watch('app/**/*.css', gulp.series('css', 'html', 'sw'));
123
-	gulp.watch('app/*.html', gulp.series('html', 'sw'));
124
-	gulp.watch('app/manifest.json', gulp.series('manifest', 'html', 'sw'));
125
-	gulp.watch('app/sw.js', gulp.series('html', 'sw'));
126
-}));
127
-
128
-gulp.task('default', gulp.series('dist'));

app/index.html → index.html View File

@@ -5,15 +5,15 @@
5 5
 		<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
6 6
 		<meta http-equiv="encoding" content="utf-8">
7 7
 		<meta name="Description" content="A social platform for minimalists.">
8
-		<link rel="manifest" href="/manifest.json"></link>
9
-		<link rel="icon" type="image/png" href="/deepart.ai128.png" sizes="128x128"></link>
10
-		<title>deepvoid</title>
11
-		<style>${INLINE_CSS}</style>
8
+		<link rel="manifest" href="manifest.json"></link>
9
+		<link rel="icon" type="image/png" href="deepart.ai128.png" sizes="128x128"></link>
10
+		<title>deepart.ai</title>
11
+		<link rel="stylesheet" href="main.css"></link>
12 12
 	</head>
13 13
 	<body>
14 14
 		<noscript>JavaScript is required to use the PWA!</noscript>
15 15
 		<header></header>
16 16
 		<main></main>
17
-		<script async src="/main.js"></script>
17
+		<script type="module" src="js/main.js"></script>
18 18
 	</body>
19 19
 </html>

+ 1
- 0
js/lit-html.js
File diff suppressed because it is too large
View File


app/templates/header.js → js/main.js View File

@@ -1,9 +1,16 @@
1 1
 'use strict';
2 2
 
3
-import { html } from 'lit-html';
3
+import { route, go } from './router.js';
4
+import { tag } from '../util.js';
5
+import { html, render } from './lit-html.js';
4 6
 
5
-export const header = () => html`
6
-	<a href="/" class="container">
7
+import { aboutRoute } from './routes/about.js';
8
+import { feedRoute } from './routes/feed.js';
9
+import { galleryRoute } from './routes/gallery.js';
10
+import { notfoundRoute } from './routes/notfound.js';
11
+
12
+export const headerTemplate = () => html`
13
+	<a href="#/" class="container">
7 14
 		<svg
8 15
 			 viewBox="0 0 12.7 12.7"
9 16
 			 height="48"
@@ -31,3 +38,19 @@ export const header = () => html`
31 38
 		<h1>deepart.ai</h1>
32 39
 	</a>
33 40
 `;
41
+render(headerTemplate(), tag('header'));
42
+
43
+route(/^\/$/, aboutRoute);
44
+route(/^\/feed$/, feedRoute);
45
+route(/^\/gallery$/, galleryRoute);
46
+route(/^.*$/, notfoundRoute);
47
+
48
+if (!window.location.hash.length) go('/');
49
+
50
+const sw = navigator.serviceWorker;
51
+if (sw) {
52
+	sw.register('/sw.js', {
53
+		scope: '/'
54
+	});
55
+}
56
+

+ 26
- 0
js/router.js View File

@@ -0,0 +1,26 @@
1
+'use strict';
2
+
3
+const routes = [];
4
+
5
+export const route = (pattern, handler) => {
6
+	routes.push({
7
+		pattern: pattern,
8
+		handler: handler
9
+	});
10
+};
11
+
12
+export const go = (dest) => {
13
+	window.location.hash = '#' + dest;
14
+};
15
+
16
+const handler = (dest) => {
17
+	for (let route of routes) {
18
+		const match = route.pattern.exec(dest);
19
+		if (!match) continue;
20
+		return route.handler(match.slice(1));
21
+	}
22
+};
23
+
24
+window.addEventListener('hashchange', evt => handler(window.location.hash.slice(1)));
25
+
26
+document.addEventListener("DOMContentLoaded", () => handler(window.location.hash.slice(1)));

app/templates/about.js → js/routes/about.js View File

@@ -1,22 +1,30 @@
1 1
 'use strict';
2 2
 
3
-import { html } from 'lit-html';
3
+import { html, render } from '../lit-html.js';
4
+import { tag } from '../util.js';
4 5
 
5
-export const about = (error) => html`
6
+const aboutTemplate = (error) => html`
6 7
 	<div class="container about">
7 8
 		<section>
8
-			<a href="/account">
9
+			<a href="#/account">
9 10
 				<h3>Sign up</h3>
10 11
 				<p>At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum. </p>
11 12
 			</a>
12
-			<a href="/gallery">
13
+			<a href="#/gallery">
13 14
 				<h3>Gallery</h3>
14 15
 				<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. </p>
15 16
 			</a>
16
-			<a href="/feed">
17
+			<a href="#/feed">
17 18
 				<h3>Feed</h3>
18 19
 				<p>Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium. </p>
19 20
 			</a>
20 21
 		</section>
21 22
 	</div>
22 23
 `;
24
+
25
+export const aboutRoute = () => {
26
+	render(aboutTemplate(), tag('main'));
27
+	return true;
28
+};
29
+
30
+

+ 17
- 0
js/routes/feed.js View File

@@ -0,0 +1,17 @@
1
+'use strict';
2
+
3
+import { html, render } from '../lit-html.js';
4
+import { tag } from '../util.js';
5
+
6
+const feedTemplate = (images) => html`
7
+	${images.map(image => html`
8
+		<img id="image-${image.id}" src="${image.url}">
9
+	`)}
10
+`;
11
+
12
+export const feedRoute = () => {
13
+	const notes = JSON.parse(localStorage.getItem('notes') || "[]")
14
+	render(feedTemplate(notes), tag('main'));
15
+};
16
+
17
+

+ 131
- 0
js/routes/gallery.js View File

@@ -0,0 +1,131 @@
1
+'use strict';
2
+
3
+import { html, render } from '../lit-html.js';
4
+import { tag, cssClass, selAll, id, sleep } from '../util.js';
5
+
6
+const size = 128;
7
+const canvas = document.createElement('canvas');
8
+const ctx = canvas.getContext('2d');
9
+canvas.height = size;
10
+canvas.width = size;
11
+
12
+const galleryTemplate = (images, loading) => html`
13
+	<div class="container gallery">
14
+		<div class="grid">
15
+			${images.map(image => html`
16
+				<div class="image">
17
+					<img data-id="${image.id}" src="${image.url}">
18
+					${image.selected ? html`
19
+						<div class="selected">
20
+							<span>${image.selected}</span>
21
+						</div>
22
+					` : ''}
23
+				</div>
24
+			`)}
25
+		</div>
26
+	</div>
27
+	${loading ? html`
28
+		<div class="loading">
29
+			<div class="spinner"></div>
30
+		</div>
31
+	` : ''}
32
+	<div class="nav">
33
+		<div class="container">
34
+			<span>Select the image you like most</span>
35
+			<a id="next">next &rarr;</a>
36
+		</div>
37
+	</div>
38
+`;
39
+
40
+const renderImage = (artwork) => {
41
+	ctx.clearRect(0, 0, size, size);
42
+	artwork['objects'].forEach((obj) => {
43
+		let first = obj['points'].shift();
44
+		let x = first['x'] * size;
45
+		let y = first['y'] * size;
46
+		let r = Math.round(first['r']*255);
47
+		let g = Math.round(first['g']*255);
48
+		let b = Math.round(first['b']*255);
49
+		ctx.fillStyle = `rgba(${r}, ${g}, ${b}, 1)`;
50
+		ctx.moveTo(x, y);
51
+		ctx.beginPath();
52
+		if (obj['radius']) {
53
+			let radius = obj['radius'] * size;
54
+			if (radius < 0) {
55
+				console.warn('oops, radius was < 0: ' + radius);
56
+			} else {
57
+				ctx.arc(x, y, radius, 0, 2 * Math.PI, false);
58
+			}
59
+		} else {
60
+			let second = obj['points'][0];
61
+			let x2 = second['x'] * size;
62
+			let y2 = second['y'] * size;
63
+			let r2 = Math.round(second['r']*255);
64
+			let g2 = Math.round(second['g']*255);
65
+			let b2 = Math.round(second['b']*255);
66
+			let grd = ctx.createLinearGradient(x, y, x2, y2);
67
+			grd.addColorStop(0, `rgba(${r}, ${g}, ${b}, 1)`);
68
+			grd.addColorStop(1, `rgba(${r2}, ${g2}, ${b2}, 1)`);
69
+			ctx.fillStyle = grd;
70
+			console.log(obj['points'].length);
71
+			obj['points'].forEach((point) => {
72
+				ctx.lineTo(point['x'] * size, point['y'] * size);
73
+			});
74
+		}
75
+		ctx.closePath();
76
+		ctx.fill();
77
+	});
78
+	return canvas.toDataURL("image/png");
79
+};
80
+
81
+export const galleryRoute = async () => {
82
+	const apiUri = '/api/';
83
+
84
+	const get = (path) => fetch(apiUri + path, {cache: "no-store"});
85
+
86
+	let nnId = '';
87
+	let data = {};
88
+
89
+	const nextSet = async (selected) => {
90
+		render(galleryTemplate([], true), tag('main'));
91
+
92
+		let newId;
93
+		if (selected !== undefined) {
94
+			await get('answer/' + nnId + '/' + selected);
95
+			do {
96
+				newId = await get('get_latest_id').then(resp => resp.text());
97
+				await sleep(200);
98
+			} while (newId === nnId);
99
+			nnId = newId;
100
+		} else {
101
+			nnId = await get('get_latest_id').then(resp => resp.text());
102
+		}
103
+		data = await get('get_latest_data').then(resp => resp.json());
104
+		let images = Object.keys(data).map(index => {
105
+			return {
106
+				id: index,
107
+				url: renderImage(data[index])
108
+			};
109
+		});
110
+		render(galleryTemplate(images), tag('main'));
111
+	};
112
+
113
+	await nextSet();
114
+
115
+	let i = 0;
116
+
117
+	cssClass('grid').onclick = (evt) => {
118
+		if (evt.target.tagName !== 'IMG') return;
119
+		let id = evt.target.getAttribute('data-id');
120
+		/*images[id].selected = ++i;
121
+		render(galleryTemplate(images), tag('main'));
122
+		i = 0;
123
+		let selectedId = images.filter(i => i.selected === 1)[0].id;*/
124
+		nextSet(id);
125
+	};
126
+
127
+	id('next').onclick = () => {
128
+		nextSet(0);
129
+	};
130
+};
131
+

app/templates/notfound.js → js/routes/notfound.js View File

@@ -1,11 +1,17 @@
1 1
 'use strict';
2 2
 
3
-import { html } from 'lit-html';
3
+import { html, render } from '../lit-html.js';
4
+import { tag } from '../util.js';
4 5
 
5
-export const notfound = () => html`
6
+const notfoundTemplate = () => html`
6 7
 	<div class="container">
7 8
 		<h1>What are you looking for?</h1>
8 9
 		<h3>The page you tried to access was not found. Did you make a spelling mistake?</h3>
9 10
 		<a href="/">Back to the home page</a>
10 11
 	</div>
11 12
 `;
13
+
14
+export const notfoundRoute = () => {
15
+	render(notfoundTemplate(), tag('main'));
16
+};
17
+

app/sw.js → js/sw.js View File

@@ -1,12 +1,35 @@
1 1
 'use strict';
2 2
 
3 3
 let preCache = [
4
-	'/',
5
-	'/main.js',
6
-	'/manifest.json',
7
-	'/fonts/source-code-pro-v7-latin-regular.woff2',
8
-	'/fonts/source-code-pro-v7-latin-500.woff2',
9
-	'/fonts/source-code-pro-v7-latin-700.woff2'
4
+	'./',
5
+	'./main.js',
6
+	'./manifest.json',
7
+	'./fonts/source-code-pro-v7-latin-regular.woff2',
8
+	'./fonts/source-code-pro-v7-latin-500.woff2',
9
+	'./fonts/source-code-pro-v7-latin-700.woff2',
10
+	'./deepart.ai.png',
11
+	'./deepart.ai.svg',
12
+	'./deepart.ai128.png',
13
+	'./deepart.ai256.png',
14
+	'./deepart.ai512.png',
15
+	'./deepart.ai64.png',
16
+	'./main.css',
17
+	'./main.js',
18
+	'./router.js',
19
+	'./routes/about.js',
20
+	'./routes/feed.js',
21
+	'./routes/gallery.js',
22
+	'./routes/header.js',
23
+	'./routes/index.js',
24
+	'./routes/notfound.js',
25
+	'./templates/about.js',
26
+	'./templates/feed.js',
27
+	'./templates/gallery.js',
28
+	'./templates/header.js',
29
+	'./templates/index.js',
30
+	'./templates/notfound.js',
31
+	'./util.js',
32
+	'./manifest.json'
10 33
 ];
11 34
 
12 35
 const CACHE = 'cache-${BUILD_DATE}';

app/util.js → js/util.js View File


app/main.css → main.css View File


app/manifest.json → manifest.json View File

@@ -1,7 +1,7 @@
1 1
 {
2 2
 	"name": "deepart.ai",
3 3
 	"short_name": "deepart.ai",
4
-	"start_url": "/",
4
+	"start_url": ".",
5 5
 	"icons": [
6 6
 		{
7 7
 			"src": "deepart.ai64.png",

+ 0
- 40
nginx.conf.dev.example View File

@@ -1,40 +0,0 @@
1
-worker_processes 1;
2
-
3
-events {
4
-	worker_connections 1024;
5
-}
6
-
7
-http {
8
-	charset UTF-8;
9
-	include mime.types;
10
-	default_type application/octet-stream;
11
-	sendfile on;
12
-	keepalive_timeout 65;
13
-	gzip on;
14
-	gzip_types text/plain text/xml text/css application/x-javascript application/json application/javascript;
15
-
16
-	access_log off;
17
-	log_not_found off;
18
-
19
-	server {
20
-		listen [::]:80 ipv6only=off;
21
-		return 301 https://$host$request_uri;
22
-	}
23
-
24
-	server {
25
-		listen 0.0.0.0:8080;
26
-
27
-		autoindex off;
28
-		index index.html;
29
-
30
-		location / {
31
-			root /usr/share/nginx/dist/;
32
-			try_files $uri $uri/ /index.html;
33
-		}
34
-
35
-		location /api {
36
-			proxy_pass http://backend:5000/api;
37
-		}
38
-	}
39
-}
40
-

+ 0
- 61
nginx.conf.prod.example View File

@@ -1,61 +0,0 @@
1
-worker_processes 1;
2
-
3
-events {
4
-	worker_connections 1024;
5
-}
6
-
7
-http {
8
-	charset UTF-8;
9
-	include mime.types;
10
-	default_type application/octet-stream;
11
-	sendfile on;
12
-	keepalive_timeout 65;
13
-	gzip on;
14
-	gzip_types text/plain text/xml text/css application/x-javascript application/json application/javascript;
15
-
16
-	ssl_dhparam /etc/ssl/dhparams.pem;
17
-	ssl_session_cache shared:SSL:10m;
18
-	ssl_session_timeout 10m;
19
-	ssl_session_tickets off;
20
-	ssl_prefer_server_ciphers on;
21
-	ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
22
-	ssl_ecdh_curve secp384r1;
23
-	resolver 8.8.8.8 8.8.4.4 valid=300s;
24
-	resolver_timeout 5s;
25
-
26
-	access_log off;
27
-	log_not_found off;
28
-
29
-	server {
30
-		listen [::]:80 ipv6only=off;
31
-		return 301 https://$host$request_uri;
32
-	}
33
-
34
-	server {
35
-		listen [::]:443 ssl http2 ipv6only=off;
36
-		server_name foo.bar;
37
-
38
-		ssl on;
39
-		ssl_certificate /etc/letsencrypt/live/foo.bar/fullchain.pem;
40
-		ssl_certificate_key /etc/letsencrypt/live/foo.bar/privkey.pem;
41
-		ssl_trusted_certificate /etc/letsencrypt/live/foo.bar/fullchain.pem;
42
-
43
-		add_header Strict-Transport-Security "max-age=63072000; preload; includeSubDomains";
44
-		add_header Cache-Control "max-age=604800";
45
-
46
-		root /srv/http/404;
47
-		autoindex off;
48
-		index index.html;
49
-
50
-		location / {
51
-			root /usr/share/nginx/dist/;
52
-			try_files $uri $uri/ /index.html;
53
-			http2_push "/main.js";
54
-		}
55
-
56
-		location /api/ {
57
-			proxy_pass https://foo.bar/api/;
58
-		}
59
-	}
60
-}
61
-

+ 0
- 37
package.json View File

@@ -1,37 +0,0 @@
1
-{
2
-  "name": "my-app",
3
-  "version": "1.0.0",
4
-  "scripts": {
5
-    "test": "gulp"
6
-  },
7
-  "author": "Milan Pässler",
8
-  "license": "AGPL-3.0",
9
-  "dependencies": {
10
-    "eslint": "^4.16.0",
11
-    "eslint-config-standard": "^11.0.0-beta.0",
12
-    "eslint-plugin-import": "^2.8.0",
13
-    "eslint-plugin-node": "^5.2.1",
14
-    "eslint-plugin-promise": "^3.6.0",
15
-    "eslint-plugin-standard": "^3.0.1",
16
-    "gulp": "gulpjs/gulp.git#4.0",
17
-    "gulp-autoprefixer": "^4.0.0",
18
-    "gulp-clean-css": "^3.9.0",
19
-    "gulp-htmlmin": "^4.0.0",
20
-    "gulp-jsonminify": "^1.0.0",
21
-    "gulp-load-plugins": "^1.5.0",
22
-    "gulp-postcss": "^7.0.0",
23
-    "gulp-replace": "^0.6.1",
24
-    "gulp-sourcemaps": "^2.6.1",
25
-    "lit-html": "^0.8.0",
26
-    "postcss-clean": "^1.1.0",
27
-    "postcss-import": "^11.1.0",
28
-    "postcss-nested": "^3.0.0",
29
-    "postcss-normalize": "^4.0.0",
30
-    "pump": "^1.0.2",
31
-    "rollup-plugin-node-resolve": "^3.0.0",
32
-    "rollup-plugin-uglify": "^2.0.1",
33
-    "rollup-stream": "^1.24.1",
34
-    "uglify-es": "^3.3.8",
35
-    "vinyl-source-stream": "^2.0.0"
36
-  }
37
-}

+ 63
- 0
sw.js View File

@@ -0,0 +1,63 @@
1
+'use strict';
2
+
3
+const CACHE = 'cache-v34';
4
+
5
+let preCache = [
6
+	'./',
7
+	'./js/',
8
+	'./js/lit-html.js',
9
+	'./js/main.js',
10
+	'./js/router.js',
11
+	'./js/sw.js',
12
+	'./js/util.js',
13
+	'./js/routes',
14
+	'./js/routes/about.js',
15
+	'./js/routes/notfound.js',
16
+	'./js/routes/gallery.js',
17
+	'./js/routes/feed.js',
18
+	'./deepart.ai128.png',
19
+	'./deepart.ai256.png',
20
+	'./deepart.ai512.png',
21
+	'./deepart.ai64.png',
22
+	'./deepart.ai.png',
23
+	'./deepart.ai.svg',
24
+	'./fonts/source-code-pro-v7-latin-500.woff',
25
+	'./fonts/source-code-pro-v7-latin-500.woff2',
26
+	'./fonts/source-code-pro-v7-latin-700.woff',
27
+	'./fonts/source-code-pro-v7-latin-700.woff2',
28
+	'./fonts/source-code-pro-v7-latin-regular.woff',
29
+	'./fonts/source-code-pro-v7-latin-regular.woff2',
30
+	'./manifest.json'
31
+];
32
+
33
+self.addEventListener('install', function (evt) {
34
+	self.skipWaiting();
35
+	evt.waitUntil(caches.open(CACHE).then(function (cache) {
36
+		cache.addAll(preCache);
37
+	}));
38
+});
39
+
40
+self.addEventListener('fetch', function (evt) {
41
+	evt.respondWith(fromCache(evt.request).then(function (match) {
42
+		if (match) {
43
+			return match;
44
+		} else {
45
+			return fetch(evt.request);
46
+		}
47
+	}));
48
+});
49
+
50
+self.addEventListener('activate', function (event) {
51
+	event.waitUntil(clients.claim());
52
+	event.waitUntil(clients.claim().then(function () {
53
+		return caches.keys().then(function (cacheNames) {
54
+			return Promise.all(cacheNames.filter(c => c !== CACHE).map(c => caches.delete(c)));
55
+		});
56
+	}));
57
+});
58
+
59
+function fromCache (request) {
60
+	return caches.open(CACHE).then(function (cache) {
61
+		return cache.match(request);
62
+	});
63
+}

+ 0
- 3843
yarn.lock
File diff suppressed because it is too large
View File


Loading…
Cancel
Save