diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b512c09
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+node_modules
\ No newline at end of file
diff --git a/README.md b/README.md
index 2e7dfae..6e05e80 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
-# Concrete Label
+# Collecting Labels
-## A tool for annotating concrete and visual poetry (as well as picture, images, etc)
+## A tool forked from [Concrete ๐ Label](https://git.xpub.nl/kamo/concrete-label) for annotating visual things in a collective way
-Working with NLTK for the analysis of text we noticed that the natural language toolkit lacks of something when it comes to the very materiality of the text: it ignores the layout, the shapes, the spaces as well all the other graphical information that a script may contains.
+This starts from the __Selection Process / Filter / Interface__ sub group for the SP16 at XPUB 2021/2022. The group is: Jian Kimberley Supi Kamo.
-Hence this is a little tool to annotate visual contents in order to be then processed by tools as NLTK
+On the [wiki page](https://pzwiki.wdka.nl/mediadesign/Selection_Process_/_Filter_/_Interface) there are more infos. This is a first test of crowdsourcing annotate an image, to collect different inputs as well as different point of views.
\ No newline at end of file
diff --git a/index.js b/index.js
new file mode 100644
index 0000000..219ca8f
--- /dev/null
+++ b/index.js
@@ -0,0 +1,68 @@
+// Dependencies declaration & setup
+
+// fs is for working with files, aka the JSON file we want to use to store our labels data
+const fs = require('fs');
+
+// express is for setting up the server and make it works when users do their things in the browser
+const express = require('express');
+const app = express();
+const path = require('path');
+
+// the port is setted in the etc/nginx/sites-enabled under the location /collecting-labels
+const port = 3124;
+
+// express middleware for working with JSON between the server (this) and the client (all the things in the public folder)
+app.use(express.urlencoded({ extended: true }));
+app.use(express.json());
+
+// serves the contents of the public folder as static resources
+// i.e. then you can access it using https://hub.xpub.nl/soupboat/collecting-labels as root
+app.use('/collecting-labels', express.static('public'))
+
+
+// we dont need this now because express automatically uses the index.html file in the /public folder
+// (still need to understand how to get a notification when someone connects, but maybe it is just a callbac to the app.use function of line 19whe
+
+// app.get('/collecting-labels', function(req, res) {
+// res.sendFile(path.join(__dirname, 'public', 'index.html'));
+// console.log('Someone connected!')
+// });
+
+
+// when a post request is made to the https://hub.xpub.nl/soupboat/collecting-labels url this function starts
+app.post('/collecting-labels', function(req, res) {
+
+ // with fs we read the file labels.json inside the public folder
+ // it is there because we then use the same file in the client for drawing all the labels stored in the server
+ // don't know if it is a good idea or not tho
+ // for now oke
+
+ // also: we need to check that the contents of the post request is what we want aka a label object, structured as we want ecc
+ // and not some other random thing, otherwise everything will break
+
+ fs.readFile('public/labels.json', function(err, data) {
+ if (err) throw err;
+ // parse a JSON out of the labels.json file
+ let storage = JSON.parse(data)
+
+ // insert the req.body (aka our label object) to the labels array present inside the labels.json file
+ storage.labels.push(req.body)
+
+ // overwrite the labels.json file with all the data
+ // this will not be efficient in the long term, but then we may switch to a proper database and not this scissor and glue thing
+ fs.writeFile('public/labels.json', JSON.stringify(storage), (err)=>{
+ if (err) throw err;
+ console.log('Data written to file');})
+ })
+
+ // reply to the client
+ // TODO: sayng oke everything worked nice
+ // for now it just echoes the incoming data
+ res.send(req.body)
+});
+
+
+ // listen to the port we defined at the beginning aka wait for clients to connect there
+app.listen(port, function() {
+ console.log(`๐งถ โ Collecting Labels on port ${port}!`)
+});
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..a7bc190
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,374 @@
+{
+ "name": "test-express",
+ "version": "1.0.0",
+ "lockfileVersion": 1,
+ "requires": true,
+ "dependencies": {
+ "accepts": {
+ "version": "1.3.7",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
+ "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
+ "requires": {
+ "mime-types": "~2.1.24",
+ "negotiator": "0.6.2"
+ }
+ },
+ "array-flatten": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
+ "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
+ },
+ "body-parser": {
+ "version": "1.19.0",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
+ "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==",
+ "requires": {
+ "bytes": "3.1.0",
+ "content-type": "~1.0.4",
+ "debug": "2.6.9",
+ "depd": "~1.1.2",
+ "http-errors": "1.7.2",
+ "iconv-lite": "0.4.24",
+ "on-finished": "~2.3.0",
+ "qs": "6.7.0",
+ "raw-body": "2.4.0",
+ "type-is": "~1.6.17"
+ }
+ },
+ "bytes": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
+ "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="
+ },
+ "content-disposition": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
+ "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==",
+ "requires": {
+ "safe-buffer": "5.1.2"
+ }
+ },
+ "content-type": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
+ "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
+ },
+ "cookie": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
+ "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg=="
+ },
+ "cookie-signature": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
+ "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
+ },
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "depd": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
+ "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
+ },
+ "destroy": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
+ "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
+ },
+ "ee-first": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
+ },
+ "encodeurl": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
+ "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
+ },
+ "escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
+ },
+ "etag": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+ "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
+ },
+ "express": {
+ "version": "4.17.1",
+ "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
+ "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==",
+ "requires": {
+ "accepts": "~1.3.7",
+ "array-flatten": "1.1.1",
+ "body-parser": "1.19.0",
+ "content-disposition": "0.5.3",
+ "content-type": "~1.0.4",
+ "cookie": "0.4.0",
+ "cookie-signature": "1.0.6",
+ "debug": "2.6.9",
+ "depd": "~1.1.2",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "finalhandler": "~1.1.2",
+ "fresh": "0.5.2",
+ "merge-descriptors": "1.0.1",
+ "methods": "~1.1.2",
+ "on-finished": "~2.3.0",
+ "parseurl": "~1.3.3",
+ "path-to-regexp": "0.1.7",
+ "proxy-addr": "~2.0.5",
+ "qs": "6.7.0",
+ "range-parser": "~1.2.1",
+ "safe-buffer": "5.1.2",
+ "send": "0.17.1",
+ "serve-static": "1.14.1",
+ "setprototypeof": "1.1.1",
+ "statuses": "~1.5.0",
+ "type-is": "~1.6.18",
+ "utils-merge": "1.0.1",
+ "vary": "~1.1.2"
+ }
+ },
+ "finalhandler": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
+ "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
+ "requires": {
+ "debug": "2.6.9",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "on-finished": "~2.3.0",
+ "parseurl": "~1.3.3",
+ "statuses": "~1.5.0",
+ "unpipe": "~1.0.0"
+ }
+ },
+ "forwarded": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
+ "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="
+ },
+ "fresh": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
+ "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
+ },
+ "http-errors": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
+ "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
+ "requires": {
+ "depd": "~1.1.2",
+ "inherits": "2.0.3",
+ "setprototypeof": "1.1.1",
+ "statuses": ">= 1.5.0 < 2",
+ "toidentifier": "1.0.0"
+ }
+ },
+ "iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "requires": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ }
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
+ },
+ "ipaddr.js": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
+ "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="
+ },
+ "media-typer": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+ "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
+ },
+ "merge-descriptors": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
+ "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
+ },
+ "methods": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+ "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
+ },
+ "mime": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
+ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
+ },
+ "mime-db": {
+ "version": "1.51.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz",
+ "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g=="
+ },
+ "mime-types": {
+ "version": "2.1.34",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz",
+ "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==",
+ "requires": {
+ "mime-db": "1.51.0"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+ },
+ "negotiator": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
+ "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
+ },
+ "on-finished": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
+ "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
+ "requires": {
+ "ee-first": "1.1.1"
+ }
+ },
+ "parseurl": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
+ },
+ "path-to-regexp": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
+ "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
+ },
+ "proxy-addr": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
+ "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
+ "requires": {
+ "forwarded": "0.2.0",
+ "ipaddr.js": "1.9.1"
+ }
+ },
+ "qs": {
+ "version": "6.7.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
+ "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ=="
+ },
+ "range-parser": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
+ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="
+ },
+ "raw-body": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz",
+ "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==",
+ "requires": {
+ "bytes": "3.1.0",
+ "http-errors": "1.7.2",
+ "iconv-lite": "0.4.24",
+ "unpipe": "1.0.0"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+ },
+ "safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+ },
+ "send": {
+ "version": "0.17.1",
+ "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz",
+ "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==",
+ "requires": {
+ "debug": "2.6.9",
+ "depd": "~1.1.2",
+ "destroy": "~1.0.4",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "fresh": "0.5.2",
+ "http-errors": "~1.7.2",
+ "mime": "1.6.0",
+ "ms": "2.1.1",
+ "on-finished": "~2.3.0",
+ "range-parser": "~1.2.1",
+ "statuses": "~1.5.0"
+ },
+ "dependencies": {
+ "ms": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+ "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
+ }
+ }
+ },
+ "serve-static": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz",
+ "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==",
+ "requires": {
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "parseurl": "~1.3.3",
+ "send": "0.17.1"
+ }
+ },
+ "setprototypeof": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
+ "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
+ },
+ "statuses": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
+ "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
+ },
+ "toidentifier": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
+ "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
+ },
+ "type-is": {
+ "version": "1.6.18",
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
+ "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
+ "requires": {
+ "media-typer": "0.3.0",
+ "mime-types": "~2.1.24"
+ }
+ },
+ "unpipe": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+ "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
+ },
+ "utils-merge": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
+ "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
+ },
+ "vary": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+ "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
+ }
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..82d9f56
--- /dev/null
+++ b/package.json
@@ -0,0 +1,14 @@
+{
+ "name": "test-express",
+ "version": "1.0.0",
+ "description": "Bla bla bla",
+ "main": "index.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "author": "",
+ "license": "ISC",
+ "dependencies": {
+ "express": "^4.17.1"
+ }
+}
diff --git a/public/.ipynb_checkpoints/index-checkpoint.html b/public/.ipynb_checkpoints/index-checkpoint.html
new file mode 100644
index 0000000..6f45083
--- /dev/null
+++ b/public/.ipynb_checkpoints/index-checkpoint.html
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Collecting Labels
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/public/.ipynb_checkpoints/labels-checkpoint.js b/public/.ipynb_checkpoints/labels-checkpoint.js
new file mode 100644
index 0000000..802ade1
--- /dev/null
+++ b/public/.ipynb_checkpoints/labels-checkpoint.js
@@ -0,0 +1,261 @@
+// Get the container to use as a canvas
+const container = document.getElementById("container");
+const editor = document.getElementById("editor");
+
+const textForm = document.getElementsByClassName("text-input")[0];
+const input = document.getElementById("input");
+const insert = document.getElementById("insert");
+const cancel = document.getElementById("cancel");
+
+// List of labels
+let labels = [];
+let labelsObj = [];
+
+let closing = false;
+
+// Start is where the mouse is pressed, End is where the mouse is released
+let startX;
+let startY;
+let endX;
+let endY;
+
+// Minimum size for the label to be created
+let minimumSizeX = 25;
+let minimumSizeY = 25;
+
+// Boolean for showing the editor during drawing
+let showEditor = false;
+
+// Store the coordinates and trigger the function
+container.addEventListener("mousedown", (e) => {
+ // Avoid inserting a new label if the user is clicking on a close button)
+ if (e.target.tagName !== "BUTTON" && e.target.tagName !== "INPUT") {
+ startX = e.x;
+ startY = e.y;
+
+ // activate the editor
+ showEditor = true;
+ editor.classList.add("show-editor");
+ }
+});
+
+container.addEventListener("mouseup", (e) => {
+ if (e.target.tagName !== "BUTTON" && e.target.tagName !== "INPUT") {
+ endX = e.x;
+ endY = e.y;
+
+ // disable the editor
+ showEditor = false;
+ editor.classList.remove("show-editor");
+ editor.style.width = 0;
+ editor.style.height = 0;
+
+ // draw label
+ drawLabel();
+ }
+});
+
+// Edit the editor box using transform instead of left / top in order to be more efficient
+// (but still with width and height ehm idk if this affects the performance a lot)
+// (and it is something we must care of because this event is called like every frame that the mouse is dragged)
+container.addEventListener("mousemove", (e) => {
+ if (showEditor) {
+ let minX = Math.min(startX, e.x);
+ let minY = Math.min(startY, e.y);
+
+ let maxX = Math.max(startX, e.x);
+ let maxY = Math.max(startY, e.y);
+
+ let width = maxX - minX;
+ let height = maxY - minY;
+
+ // Apply a different class when the sizes pass the minimum size
+ // (i don't know if is good made like this)
+ if (width > minimumSizeX && height > minimumSizeY) {
+ editor.classList.add("can-draw");
+ } else {
+ editor.classList.remove("can-draw");
+ }
+
+ editor.style.transform = `translate(${minX}px, ${minY}px)`;
+ editor.style.width = `${maxX - minX}px`;
+ editor.style.height = `${maxY - minY}px`;
+ }
+});
+
+// Check the mouse direction and create the Label
+// The origin points of the label (because is positioned with top left) are always the lowest x and y values
+// The width and height are the greater x and y values (because width and height cannot be negative)
+function drawLabel() {
+ let minX = Math.min(startX, endX);
+ let minY = Math.min(startY, endY);
+
+ let maxX = Math.max(startX, endX);
+ let maxY = Math.max(startY, endY);
+
+ let width = maxX - minX;
+ let height = maxY - minY;
+
+ if (width > minimumSizeX && height > minimumSizeY) {
+ // Create a label and push it into the array of labels
+ let temporaryLabel = createLabel(minX, minY, width, height, labels.length);
+ temporaryLabel.classList.add("temporary");
+ temporaryLabel.id = "temporary-label";
+ container.appendChild(temporaryLabel);
+
+ new Promise(function (resolve, reject) {
+ // then if the user click insert and there is a value in the input-- > resolve the promise and return the text input to create the label,
+ // if the user click cancel-- > reject the promise and don't create the label
+ textForm.classList.add("visible");
+
+ input.focus();
+
+ // Insert button
+ insert.addEventListener("click", (e) => {
+ e.preventDefault();
+ if (input.value) {
+ resolve();
+ }
+ });
+
+ // Cancel button
+ cancel.addEventListener("click", (e) => {
+ e.preventDefault();
+ textForm.classList.remove("visible");
+ reject("no input");
+ });
+ }).then(() => {
+ // Create the label
+ let label = createLabel(minX, minY, width, height, labels.length);
+
+ // Add the text input to the label
+ let text = document.createElement("p");
+ text.classList.add("label--text");
+ text.innerHTML = input.value;
+ label.appendChild(text);
+
+ let labelObj = {
+ position: {
+ x: minX,
+ y: minY,
+ },
+ size: {
+ width: width,
+ height: height,
+ },
+ index: labels.length,
+ text: input.value,
+ timestap: Date.now(),
+ userID: userID,
+ };
+
+ uploadLabel(labelObj);
+ labelsObj.push(labelObj);
+ labels.push(label);
+ container.appendChild(label);
+ createLabelTranscription(label);
+
+ // Reset the modal
+ input.value = "";
+ input.blur();
+ let tempLabel = document.getElementById("temporary-label");
+ container.removeChild(tempLabel);
+ textForm.classList.remove("visible");
+ });
+ }
+}
+
+// Create the label element
+function createLabel(x, y, width, height, index) {
+ let label = document.createElement("div");
+ label.classList.add("label");
+ label.style.left = `${x}px`;
+ label.style.top = `${y}px`;
+ label.style.width = `${width}px`;
+ label.style.height = `${height}px`;
+
+ // data attribute index maybe we will need it later maybe not
+ // with the index number of the label
+ label.setAttribute("data-index", index);
+
+ // Insert the number in the label
+ let labelNumber = document.createElement("p");
+ labelNumber.classList.add("label--number");
+ labelNumber.innerHTML = index + 1;
+ label.appendChild(labelNumber);
+
+ // Add a button for deleting the label
+ // TODO: reactive numbering oh no
+ let close = document.createElement("button");
+ close.classList.add("label--close");
+ close.innerHTML = "x";
+ close.addEventListener("click", (e) => {
+ label.remove();
+ });
+ label.appendChild(close);
+
+ return label;
+}
+
+const transcriptionPanel = document.getElementById("transcription-panel");
+const transcriptionList = transcriptionPanel.querySelector("ol");
+
+function createLabelTranscription(label) {
+ let transcription = document.createElement("li");
+ transcription.innerHTML = label.querySelector(".label--text").innerHTML;
+
+ transcriptionList.appendChild(transcription);
+}
+
+function uploadLabel(obj){
+
+ fetch('https://hub.xpub.nl/soupboat/collecting-labels/', {
+ method: 'POST', // or 'PUT'
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify(obj),
+ })
+ .then(response => response.json())
+ .then(data => {
+ console.log('Success:', data);
+ })
+ .catch((error) => {
+ console.error('Error:', error);
+ });
+}
+
+
+const load = document.getElementById('load-labels')
+load.addEventListener('click', (e)=>{
+ loadLabels()
+})
+
+function loadLabels(){
+
+ fetch("./labels.json")
+ .then((response) => {
+ return response.json();
+ })
+ .then((data) => {
+
+ data.labels.forEach((label, index) => {
+ let labelElement = createLabel(label.position.x, label.position.y, label.size.width, label.size.height, index)
+
+ // THIS IS TEMPORARY
+ labelElement.style.backgroundColor = `hsla(${Math.floor(label.userID/10000000000*255)}, 100%, 75%, 0.2)`
+
+ // Add the text input to the label
+ let text = document.createElement("p");
+ text.classList.add("label--text");
+ text.innerHTML = label.text;
+ labelElement.appendChild(text);
+
+ labelElement.classList.add('loaded')
+
+ container.appendChild(labelElement)
+ });
+
+
+})
+}
\ No newline at end of file
diff --git a/public/.ipynb_checkpoints/labels-checkpoint.json b/public/.ipynb_checkpoints/labels-checkpoint.json
new file mode 100644
index 0000000..107b6ae
--- /dev/null
+++ b/public/.ipynb_checkpoints/labels-checkpoint.json
@@ -0,0 +1,3 @@
+{
+ "labels": []
+}
\ No newline at end of file
diff --git a/session.js b/public/.ipynb_checkpoints/session-checkpoint.js
similarity index 100%
rename from session.js
rename to public/.ipynb_checkpoints/session-checkpoint.js
diff --git a/public/.ipynb_checkpoints/storedLabels-checkpoint.js b/public/.ipynb_checkpoints/storedLabels-checkpoint.js
new file mode 100644
index 0000000..e69de29
diff --git a/public/.ipynb_checkpoints/style-checkpoint.css b/public/.ipynb_checkpoints/style-checkpoint.css
new file mode 100644
index 0000000..83c7d71
--- /dev/null
+++ b/public/.ipynb_checkpoints/style-checkpoint.css
@@ -0,0 +1,270 @@
+html,
+body {
+ margin: 0;
+ font-family: Arial, Helvetica, sans-serif;
+ width: 100%;
+ overflow: hidden;
+}
+
+
+.test-form{
+ position: fixed;
+ top: 0;
+ left: 0;
+ z-index: 500;
+}
+
+#container {
+ width: 100%;
+ height: 100vh;
+ background-color: #fff;
+}
+
+#editor {
+ position: absolute;
+ display: none;
+ border: 1px solid white;
+ opacity: 0.5;
+ width: 0;
+ height: 0;
+ z-index: 100;
+}
+
+#editor.can-draw {
+ opacity: 1;
+}
+
+#editor.show-editor {
+ display: block;
+}
+
+.label {
+ position: absolute;
+ background-color: rgba(250, 99, 72, 0.2);
+ /* border: 1px solid currentColor; */
+ box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.2);
+
+ overflow: hidden;
+}
+
+.label.temporary {
+ background: none;
+ border: 1px dashed tomato;
+ box-shadow: none;
+}
+
+.label.temporary .label--number,
+.label.temporary .label--close {
+ display: none;
+}
+
+.label--number {
+ display: inline-block;
+ margin: 0;
+ padding: 0 4px;
+
+ user-select: none;
+
+ background-color: white;
+}
+
+.label--close {
+ position: absolute;
+ right: 0;
+
+ border: none;
+
+ padding: 0 4px;
+
+ font-size: 1rem;
+
+ background: none;
+ color: white;
+
+ cursor: pointer;
+}
+.label--text {
+ margin: 1ch 0;
+ padding: 0 1ch;
+
+ overflow: hidden;
+ width: 100%;
+ height: 100%;
+ text-overflow: ellipsis;
+ white-space: pre;
+}
+
+.text-input {
+ display: none;
+ position: absolute;
+ z-index: 200;
+ width: 100%;
+ height: 100vh;
+
+ justify-content: center;
+ align-items: center;
+
+ background-color: rgba(255, 99, 71, 0.95);
+}
+
+.text-input.visible {
+ display: flex;
+}
+
+.modal {
+ padding: 64px;
+}
+
+.modal input {
+ font-size: 1.5rem;
+ background: none;
+ border: none;
+ color: white;
+ border-bottom: 1px solid white;
+}
+
+.modal input:focus {
+ outline: none;
+ background-color: rgba(255, 255, 255, 0.25);
+}
+
+.text-input button {
+ color: white;
+ font-weight: bold;
+ background: none;
+ border: none;
+ cursor: pointer;
+ font-size: 1.5rem;
+}
+
+#cancel {
+ font-weight: normal;
+}
+
+.background-container {
+ position: absolute;
+ left: 50%;
+ top: 50%;
+ transform: translate(-50%, -50%);
+ display: flex;
+ flex-direction: column;
+}
+
+.background-container img {
+ max-width: 70w;
+ max-height: 70vh;
+ object-fit: contain;
+ user-select: none;
+ pointer-events: none;
+}
+
+.background-container img.visible {
+ display: initial;
+}
+
+.hidden {
+ display: none;
+}
+
+.info,
+.transcription {
+ position: absolute;
+ right: 0;
+ bottom: 0;
+ top: 0;
+ z-index: 50;
+
+ padding: 24px;
+ margin: 0;
+
+ width: 25%;
+ line-height: 1.6;
+
+ background-color: #111;
+ color: white;
+
+ transform: translateX(100%);
+ transition: transform 0.4s ease-out;
+}
+
+.transcription.active,
+.info.active {
+ transform: translateX(0);
+ transition: transform 0.6s ease-in;
+}
+
+.transcription .title,
+.info .title {
+ margin: 0;
+}
+
+.transcription ol {
+ padding: 0;
+ list-style-position: inside;
+ font-size: 1.125rem;
+}
+
+#show-info,
+#show-transcription,
+.close,
+button {
+ background: none;
+
+ display: inline-block;
+ min-width: 24px;
+ height: 24px;
+ border-radius: 24px;
+ padding: 0 4px;
+
+ border: 1px solid currentColor;
+
+ color: tomato;
+
+ cursor: pointer;
+}
+
+#show-transcription:hover,
+#show-info:hover {
+ border: 1px solid tomato;
+ background-color: tomato;
+ color: white;
+}
+
+.close {
+ position: absolute;
+ right: 24px;
+ top: 32px;
+ color: white;
+}
+
+#export-text:hover,
+.close:hover {
+ border: 1px solid white;
+ background-color: white;
+ color: #111;
+}
+
+#export-text {
+ color: white;
+}
+
+nav {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ z-index: 50;
+
+ padding: 24px;
+ text-align: right;
+
+ pointer-events: none;
+}
+
+nav > * {
+ pointer-events: all;
+}
+
+img.hidden {
+ display: none;
+}
diff --git a/assets/map_description_H.jpg b/public/assets/map_description_H.jpg
similarity index 100%
rename from assets/map_description_H.jpg
rename to public/assets/map_description_H.jpg
diff --git a/assets/map_description_V.jpg b/public/assets/map_description_V.jpg
similarity index 100%
rename from assets/map_description_V.jpg
rename to public/assets/map_description_V.jpg
diff --git a/index.html b/public/index.html
similarity index 89%
rename from index.html
rename to public/index.html
index 0d41d5b..6f45083 100644
--- a/index.html
+++ b/public/index.html
@@ -11,12 +11,12 @@
- Concrete Label
+ Collecting Labels
@@ -31,6 +31,7 @@
+