diff --git a/.gitignore b/.gitignore index 64834ca..de49cd7 100755 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .cache/ .vscode/ dist/ -node_modules/ \ No newline at end of file +node_modules/ +.* \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 37a566f..1ba2ce6 100755 --- a/package-lock.json +++ b/package-lock.json @@ -5,33 +5,50 @@ "requires": true, "dependencies": { "@babel/runtime": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.3.4.tgz", - "integrity": "sha512-IvfvnMdSaLBateu0jfsYIpZTxAc2cKEXEMiezGGN75QcBcecDUKd3PgLAncT0oOgxKy8dd8hrJKj9MfzgfZd6g==", + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.4.2.tgz", + "integrity": "sha512-7Bl2rALb7HpvXFL7TETNzKSAeBVCPHELzc0C//9FCxN8nsiueWSJBqaF+2oIJScyILStASR/Cx5WMkXGYTiJFA==", "dev": true, "requires": { - "regenerator-runtime": "^0.12.0" + "regenerator-runtime": "^0.13.2" } }, "@hibas123/secure-file-wrapper": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/@hibas123/secure-file-wrapper/-/secure-file-wrapper-2.3.1.tgz", - "integrity": "sha512-AwseTodeEvKnYWXudJbw3SiJX6aLI7l78tWgd+5gRF7zlhXBqquqhiViM6bJZdQqki0223Zv+Zbi3kALbnVHaQ==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@hibas123/secure-file-wrapper/-/secure-file-wrapper-2.4.0.tgz", + "integrity": "sha512-YNFsivgp/6XAooepaTicW21VKmAqso/5vR28V3RzRRcCPVfRWu9gsNPNTLpFRJ7wypyF5+nAb2U00VJmDypSTg==", "requires": { - "cross-fetch": "^3.0.0", + "@hibas123/utils": "^2.0.0", + "cross-fetch": "^3.0.1", "uuid": "^3.3.2" + }, + "dependencies": { + "cross-fetch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.0.1.tgz", + "integrity": "sha512-qWtpgBAF8ioqBOddRD+pHhrdzm/UWOArkrlIU7c08DlNbOxo5GfUbSY2vr90ZypWf0raW+HNN1F38pi5CEOjiQ==", + "requires": { + "node-fetch": "2.3.0", + "whatwg-fetch": "3.0.0" + } + } } }, + "@hibas123/utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@hibas123/utils/-/utils-2.0.0.tgz", + "integrity": "sha512-kczMJvwLGqUgnFamxtPJjb7V+C5tKHc3dtgKYaCQexbzwQ44VNlwTngYNK7izRA5HfD0N+abAGA0IoBMDmKDpg==" + }, "@types/lodash": { - "version": "4.14.121", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.121.tgz", - "integrity": "sha512-ORj7IBWj13iYufXt/VXrCNMbUuCTJfhzme5kx9U/UtcIPdJYuvPDUAlHlbNhz/8lKCLy9XGIZnGrqXOtQbPGoQ==", + "version": "4.14.122", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.122.tgz", + "integrity": "sha512-9IdED8wU93ty8gP06ninox+42SBSJHp2IAamsSYMUY76mshRTeUsid/gtbl8ovnOwy8im41ib4cxTiIYMXGKew==", "dev": true }, "@types/lodash.clonedeep": { - "version": "4.5.5", - "resolved": "https://registry.npmjs.org/@types/lodash.clonedeep/-/lodash.clonedeep-4.5.5.tgz", - "integrity": "sha512-TBEia6gB1KDpKcxldeLlacbTrNDZcRh5wIPRG98yWrzF8ItyZGr5qQSsWbIBPnzhngBqYnwNvvImzSDuBRig2w==", + "version": "4.5.6", + "resolved": "https://registry.npmjs.org/@types/lodash.clonedeep/-/lodash.clonedeep-4.5.6.tgz", + "integrity": "sha512-cE1jYr2dEg1wBImvXlNtp0xDoS79rfEdGozQVgliDZj1uERH4k+rmEMTudP9b4VQ8O6nRb5gPqft0QzEQGMQgA==", "dev": true, "requires": { "@types/lodash": "*" @@ -1413,13 +1430,14 @@ "dev": true }, "copy-webpack-plugin": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-5.0.0.tgz", - "integrity": "sha512-iiDj+8nnZeW/i8vYJ3+ABSZkOefJnDYIGLojiZKKFDvf1wcEInABXH1+hN7axQMn04qvJxKjgVOee0e14XPtCg==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-5.0.2.tgz", + "integrity": "sha512-7nC7EynPrnBTtBwwbG1aTqrfNS1aTb9eEjSmQDqFtKAsJrR3uDb+pCDIFT2LzhW+SgGJxQcYzThrmXzzZ720uw==", "dev": true, "requires": { "cacache": "^11.3.1", "find-cache-dir": "^2.0.0", + "glob-parent": "^3.1.0", "globby": "^7.1.1", "is-glob": "^4.0.0", "loader-utils": "^1.1.0", @@ -1532,32 +1550,30 @@ "integrity": "sha1-/aGedh/Ad+Af+/3G6f38WeiAbNg=" }, "css-loader": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-2.1.0.tgz", - "integrity": "sha512-MoOu+CStsGrSt5K2OeZ89q3Snf+IkxRfAIt9aAKg4piioTrhtP1iEFPu+OVn3Ohz24FO6L+rw9UJxBILiSBw5Q==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-2.1.1.tgz", + "integrity": "sha512-OcKJU/lt232vl1P9EEDamhoO9iKY3tIjY5GU+XDLblAykTdgs6Ux9P1hTHve8nFKy5KPpOXOsVI/hIwi3841+w==", "dev": true, "requires": { - "icss-utils": "^4.0.0", - "loader-utils": "^1.2.1", - "lodash": "^4.17.11", - "postcss": "^7.0.6", + "camelcase": "^5.2.0", + "icss-utils": "^4.1.0", + "loader-utils": "^1.2.3", + "normalize-path": "^3.0.0", + "postcss": "^7.0.14", "postcss-modules-extract-imports": "^2.0.0", - "postcss-modules-local-by-default": "^2.0.3", - "postcss-modules-scope": "^2.0.0", + "postcss-modules-local-by-default": "^2.0.6", + "postcss-modules-scope": "^2.1.0", "postcss-modules-values": "^2.0.0", "postcss-value-parser": "^3.3.0", "schema-utils": "^1.0.0" - } - }, - "css-selector-tokenizer": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.1.tgz", - "integrity": "sha512-xYL0AMZJ4gFzJQsHUKa5jiWWi2vH77WVNg7JYRyewwj6oPh4yb/y6Y9ZCw9dsj/9UauMhtuxR+ogQd//EdEVNA==", - "dev": true, - "requires": { - "cssesc": "^0.1.0", - "fastparse": "^1.1.1", - "regexpu-core": "^1.0.0" + }, + "dependencies": { + "camelcase": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.2.0.tgz", + "integrity": "sha512-IXFsBS2pC+X0j0N/GE7Dm7j3bsEBp+oTpb7F50dwEVX7rf3IgwO9XatnegTsDtniKCUtEJH4fSU6Asw7uoVLfQ==", + "dev": true + } } }, "css-what": { @@ -1567,9 +1583,9 @@ "dev": true }, "cssesc": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-0.1.0.tgz", - "integrity": "sha1-yBSQPkViM3GgR3tAEJqq++6t27Q=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", "dev": true }, "currently-unhandled": { @@ -2329,12 +2345,6 @@ "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", "dev": true }, - "fastparse": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz", - "integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==", - "dev": true - }, "faye-websocket": { "version": "0.10.0", "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", @@ -3500,9 +3510,9 @@ } }, "hoek": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", - "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==", + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-6.1.2.tgz", + "integrity": "sha512-6qhh/wahGYZHFSFw12tBbJw5fsAhhwrrG/y3Cs0YMTv2WzMnL0oLPnQJjv1QJvEfylRSOFuP+xCu+tdx0tD16Q==", "dev": true }, "homedir-polyfill": { @@ -3686,12 +3696,12 @@ "dev": true }, "icss-utils": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.0.0.tgz", - "integrity": "sha512-bA/xGiwWM17qjllIs9X/y0EjsB7e0AV08F3OL8UPsoNkNRibIuu8f1eKTnQ8QO1DteKKTxTUAn+IEWUToIwGOA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.0.tgz", + "integrity": "sha512-3DEun4VOeMvSczifM3F2cKQrDQ5Pj6WKhkOq6HD4QTnDUAq8MQRxy5TX6Sy1iY6WPBe4gQ3p5vTECjbIkglkkQ==", "dev": true, "requires": { - "postcss": "^7.0.5" + "postcss": "^7.0.14" } }, "idb": { @@ -3748,6 +3758,12 @@ "repeating": "^2.0.0" } }, + "indexes-of": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", + "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", + "dev": true + }, "indexof": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", @@ -4080,14 +4096,14 @@ "dev": true }, "joi": { - "version": "11.4.0", - "resolved": "https://registry.npmjs.org/joi/-/joi-11.4.0.tgz", - "integrity": "sha512-O7Uw+w/zEWgbL6OcHbyACKSj0PkQeUgmehdoXVSxt92QFCq4+1390Rwh5moI2K/OgC7D8RHRZqHZxT2husMJHA==", + "version": "14.3.1", + "resolved": "https://registry.npmjs.org/joi/-/joi-14.3.1.tgz", + "integrity": "sha512-LQDdM+pkOrpAn4Lp+neNIFV3axv1Vna3j38bisbQhETPMANYRbFJFUyOZcOClYvM/hppMhGWuKSFEK9vjrB+bQ==", "dev": true, "requires": { - "hoek": "4.x.x", + "hoek": "6.x.x", "isemail": "3.x.x", - "topo": "2.x.x" + "topo": "3.x.x" } }, "js-base64": { @@ -4118,12 +4134,6 @@ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", "dev": true }, - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", - "dev": true - }, "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", @@ -4816,6 +4826,11 @@ "lower-case": "^1.1.1" } }, + "node-fetch": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.3.0.tgz", + "integrity": "sha512-MOd8pV3fxENbryESLgVIeaGKrdl+uaYhCSSVkjeOb/31/njTpcis5aWfdqgNlHIrKOLRbMnfPINPOML2CIFeXA==" + }, "node-forge": { "version": "0.7.5", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.5.tgz", @@ -5410,9 +5425,9 @@ "dev": true }, "postcss": { - "version": "7.0.13", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.13.tgz", - "integrity": "sha512-h8SY6kQTd1wISHWjz+E6cswdhMuyBZRb16pSTv3W4zYZ3/YbyWeJdNUeOXB5IdZqE1U76OUEjjjqsC3z2f3hVg==", + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", + "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -5478,24 +5493,24 @@ } }, "postcss-modules-local-by-default": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-2.0.4.tgz", - "integrity": "sha512-WvuSaTKXUqYJbnT7R3YrsNrHv/C5vRfr5VglS4bFOk0MYT4CLBfc/xgExA+x2RftlYgiBDvWmVs191Xv8S8gZQ==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-2.0.6.tgz", + "integrity": "sha512-oLUV5YNkeIBa0yQl7EYnxMgy4N6noxmiwZStaEJUSe2xPMcdNc8WmBQuQCx18H5psYbVxz8zoHk0RAAYZXP9gA==", "dev": true, "requires": { - "css-selector-tokenizer": "^0.7.0", "postcss": "^7.0.6", + "postcss-selector-parser": "^6.0.0", "postcss-value-parser": "^3.3.1" } }, "postcss-modules-scope": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.0.1.tgz", - "integrity": "sha512-7+6k9c3/AuZ5c596LJx9n923A/j3nF3ormewYBF1RrIQvjvjXe1xE8V8A1KFyFwXbvnshT6FBZFX0k/F1igneg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.1.0.tgz", + "integrity": "sha512-91Rjps0JnmtUB0cujlc8KIKCsJXWjzuxGeT/+Q2i2HXKZ7nBUeF9YQTZZTNvHVoNYj1AthsjnGLtqDUE0Op79A==", "dev": true, "requires": { - "css-selector-tokenizer": "^0.7.0", - "postcss": "^7.0.6" + "postcss": "^7.0.6", + "postcss-selector-parser": "^6.0.0" } }, "postcss-modules-values": { @@ -5508,6 +5523,17 @@ "postcss": "^7.0.6" } }, + "postcss-selector-parser": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz", + "integrity": "sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg==", + "dev": true, + "requires": { + "cssesc": "^3.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + }, "postcss-value-parser": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", @@ -5531,9 +5557,9 @@ } }, "pretty-bytes": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-4.0.2.tgz", - "integrity": "sha1-sr+C5zUNZcbDOqlaqlpPYyf2HNk=", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.1.0.tgz", + "integrity": "sha512-wa5+qGVg9Yt7PB6rYm3kXlKzgzgivYTLRandezh43jjRqgyDyP+9YxfJpJiLs9yKD1WeU8/OvtToWpW7255FtA==", "dev": true }, "pretty-error": { @@ -5871,16 +5897,10 @@ "strip-indent": "^1.0.1" } }, - "regenerate": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", - "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", - "dev": true - }, "regenerator-runtime": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz", - "integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg==", + "version": "0.13.2", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.2.tgz", + "integrity": "sha512-S/TQAZJO+D3m9xeN1WTI8dLKBBiRgXBlTJvbWjCThHWZj9EvHK70Ff50/tYj2J/fvBY6JtFVwRuazHN2E7M9BA==", "dev": true }, "regex-not": { @@ -5893,32 +5913,6 @@ "safe-regex": "^1.1.0" } }, - "regexpu-core": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz", - "integrity": "sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=", - "dev": true, - "requires": { - "regenerate": "^1.2.1", - "regjsgen": "^0.2.0", - "regjsparser": "^0.1.4" - } - }, - "regjsgen": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", - "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", - "dev": true - }, - "regjsparser": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", - "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", - "dev": true, - "requires": { - "jsesc": "~0.5.0" - } - }, "relateurl": { "version": "0.2.7", "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", @@ -7055,12 +7049,12 @@ } }, "topo": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/topo/-/topo-2.0.2.tgz", - "integrity": "sha1-zVYVdSU5BXwNwEkaYhw7xvvh0YI=", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/topo/-/topo-3.0.3.tgz", + "integrity": "sha512-IgpPtvD4kjrJ7CRA3ov2FhWQADwv+Tdqbsf1ZnPUSAtCJ9e1Z44MmoSGDXGk4IppoZA7jd/QRkNddlLJWlUZsQ==", "dev": true, "requires": { - "hoek": "4.x.x" + "hoek": "6.x.x" } }, "toposort": { @@ -7196,9 +7190,9 @@ "dev": true }, "typescript": { - "version": "3.3.3333", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.3.3333.tgz", - "integrity": "sha512-JjSKsAfuHBE/fB2oZ8NxtRTk5iGcg6hkYXMnZ3Wc+b2RSqejEqTaem11mHASMnFilHrax3sLK0GDzcJrekZYLw==", + "version": "3.3.4000", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.3.4000.tgz", + "integrity": "sha512-jjOcCZvpkl2+z7JFn0yBOoLQyLoIkNZAs/fYJkUG6VKy6zLPHJGfQJYFHzibB6GJaF/8QrcECtlQ5cpvRHSMEA==", "dev": true }, "ua-parser-js": { @@ -7225,6 +7219,11 @@ } } }, + "uikit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/uikit/-/uikit-3.0.3.tgz", + "integrity": "sha512-Z73TXlnfJCAXczg5mFCZSTwR0Ii1wW2fZumfIR8G1x1x4SyKHpkU0JCZDoIryYFMu1gSpvy5hZiXk3t4i5tTlw==" + }, "union-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", @@ -7260,6 +7259,12 @@ } } }, + "uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", + "dev": true + }, "unique-filename": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", @@ -7606,9 +7611,9 @@ } }, "webpack-cli": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.2.3.tgz", - "integrity": "sha512-Ik3SjV6uJtWIAN5jp5ZuBMWEAaP5E4V78XJ2nI+paFPh8v4HPSwo/myN0r29Xc/6ZKnd2IdrAlpSgNOu2CDQ6Q==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.3.0.tgz", + "integrity": "sha512-t1M7G4z5FhHKJ92WRKwZ1rtvi7rHc0NZoZRbSkol0YKl4HvcC8+DsmGDmK7MmZxHSAetHagiOsjOB6MmzC2TUw==", "dev": true, "requires": { "chalk": "^2.4.1", @@ -7621,7 +7626,7 @@ "loader-utils": "^1.1.0", "supports-color": "^5.5.0", "v8-compile-cache": "^2.0.2", - "yargs": "^12.0.4" + "yargs": "^12.0.5" }, "dependencies": { "ansi-regex": { @@ -7640,9 +7645,9 @@ } }, "camelcase": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz", - "integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.2.0.tgz", + "integrity": "sha512-IXFsBS2pC+X0j0N/GE7Dm7j3bsEBp+oTpb7F50dwEVX7rf3IgwO9XatnegTsDtniKCUtEJH4fSU6Asw7uoVLfQ==", "dev": true }, "chalk": { @@ -8066,168 +8071,168 @@ } }, "workbox-background-sync": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/workbox-background-sync/-/workbox-background-sync-4.0.0.tgz", - "integrity": "sha512-U8hCVqF1m/xaQnRVI4N3eRK9sQwlEH6C5BGORwVs4jBTf1bfo3EDUR2K1qhkWdGgRKBWQfSb2YHVBrxlpt6z8g==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/workbox-background-sync/-/workbox-background-sync-4.1.1.tgz", + "integrity": "sha512-z8iKAx7f3cfQpGaRrrl2CpP4dGe+vHk05vJbzscwA7e1K8vyNl6zALBtIyyAvEZzMsofsiGEZqt2g/8CfyfQ5g==", "dev": true, "requires": { - "workbox-core": "^4.0.0" + "workbox-core": "^4.1.1" } }, "workbox-broadcast-update": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/workbox-broadcast-update/-/workbox-broadcast-update-4.0.0.tgz", - "integrity": "sha512-xnnhXdgKU5OLFzc4v6n12O0iX+I4IxEZ2zV9xEQiUXCRWh/8gEcyXFdPK7Tayj5C3NwN1wrQgpSCJ5FBwVr63Q==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/workbox-broadcast-update/-/workbox-broadcast-update-4.1.1.tgz", + "integrity": "sha512-gq83a8F6ESQobfltaxzoUTz0mEpTOsXHmy9Po9kKMT1UjXTWh/4NDF3HwQYaxJckOER9NITB3BuoXlXr3tI8aA==", "dev": true, "requires": { - "workbox-core": "^4.0.0" + "workbox-core": "^4.1.1" } }, "workbox-build": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/workbox-build/-/workbox-build-4.0.0.tgz", - "integrity": "sha512-xWz4I1ZGVWQpgBq+Q8xsFF0fdHkVM+8N+uoPm+XCujmYlhxry+f87c49Yp/DcV1mHr6YIqcA5lnZu0ix77iacg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/workbox-build/-/workbox-build-4.1.1.tgz", + "integrity": "sha512-+QRtNFKDq7RlIpigsh26joUNoEN+c3pQ+yT8Rs29RtpM50S1nKggFUQY0HoRvN7tzvuzIgxCrx3osxOQ8hmj7Q==", "dev": true, "requires": { - "@babel/runtime": "^7.0.0", - "common-tags": "^1.4.0", + "@babel/runtime": "^7.3.4", + "common-tags": "^1.8.0", "fs-extra": "^4.0.2", - "glob": "^7.1.2", - "joi": "^11.1.1", + "glob": "^7.1.3", + "joi": "^14.3.1", "lodash.template": "^4.4.0", - "pretty-bytes": "^4.0.2", - "stringify-object": "^3.2.2", + "pretty-bytes": "^5.1.0", + "stringify-object": "^3.3.0", "strip-comments": "^1.0.2", - "workbox-background-sync": "^4.0.0", - "workbox-broadcast-update": "^4.0.0", - "workbox-cacheable-response": "^4.0.0", - "workbox-core": "^4.0.0", - "workbox-expiration": "^4.0.0", - "workbox-google-analytics": "^4.0.0", - "workbox-navigation-preload": "^4.0.0", - "workbox-precaching": "^4.0.0", - "workbox-range-requests": "^4.0.0", - "workbox-routing": "^4.0.0", - "workbox-strategies": "^4.0.0", - "workbox-streams": "^4.0.0", - "workbox-sw": "^4.0.0", - "workbox-window": "^4.0.0" + "workbox-background-sync": "^4.1.1", + "workbox-broadcast-update": "^4.1.1", + "workbox-cacheable-response": "^4.1.1", + "workbox-core": "^4.1.1", + "workbox-expiration": "^4.1.1", + "workbox-google-analytics": "^4.1.1", + "workbox-navigation-preload": "^4.1.1", + "workbox-precaching": "^4.1.1", + "workbox-range-requests": "^4.1.1", + "workbox-routing": "^4.1.1", + "workbox-strategies": "^4.1.1", + "workbox-streams": "^4.1.1", + "workbox-sw": "^4.1.1", + "workbox-window": "^4.1.1" } }, "workbox-cacheable-response": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/workbox-cacheable-response/-/workbox-cacheable-response-4.0.0.tgz", - "integrity": "sha512-cT3b1iotdV5+rYZKnAWvo3D8UAgfuN2HWuf+WuNC1YR0tnGmFAOX8shfEV9DZmnzxDgY8cOcOCK8PSf5uCaGBg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/workbox-cacheable-response/-/workbox-cacheable-response-4.1.1.tgz", + "integrity": "sha512-uc1zkeidJgAMXHvUbspKJt3NzXHAcb5D+7sX6HrCZIMneS4ZxMvdB86giIR3bveV4PaOssqIYVrWUJvIehK/NA==", "dev": true, "requires": { - "workbox-core": "^4.0.0" + "workbox-core": "^4.1.1" } }, "workbox-core": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-4.0.0.tgz", - "integrity": "sha512-FRoOUuJBl7COTwvGO5FC9k0VyYGv/LkjVqgVwKk9MXQn/Xi+bvGDcqSVF7qfT+sJ6Ffcr/V+dVMpoZAE/X5e+g==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-4.1.1.tgz", + "integrity": "sha512-RbzMWnDW7UvfstwOs8ERDFTH6zr7akm4wIbIednFs1TnAvZbN3gpIBoEv53kaMr0uMYDSXI2KxaLmmz9WX1PXA==", "dev": true }, "workbox-expiration": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/workbox-expiration/-/workbox-expiration-4.0.0.tgz", - "integrity": "sha512-j0h8H8hmSd+Sh9qSlmC1JwViRdxtzbdjuH32qmkYgXDGXwMprV6QU2kQ51J+7Dhm10OdQ64RGfGjbe7bjgzDuw==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/workbox-expiration/-/workbox-expiration-4.1.1.tgz", + "integrity": "sha512-N/fbypqCbFrrKDhVnTyGXhkFTgjA8aRUydkxCpgJM1ajf7udQYD4XWTQxXosPJC2UVsa2/kPCBYFQOQ1Fu/2TA==", "dev": true, "requires": { - "workbox-core": "^4.0.0" + "workbox-core": "^4.1.1" } }, "workbox-google-analytics": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/workbox-google-analytics/-/workbox-google-analytics-4.0.0.tgz", - "integrity": "sha512-WjZM3frkuCYQUmq8uICzpt+3NnjKhO/GEV+EOqRJgZMfZfmFxMUHbUKi3I/8TXWLigWJbtv/mh4zh0OtFX+vKw==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/workbox-google-analytics/-/workbox-google-analytics-4.1.1.tgz", + "integrity": "sha512-ByZYHv61u4dFQXQAXZZ1bNgcJ45yA85C8OAlSDGwqOuv72dZoybG3EMtJo/0ChO6irxWI1pictF2pTW7JxcCkQ==", "dev": true, "requires": { - "workbox-background-sync": "^4.0.0", - "workbox-core": "^4.0.0", - "workbox-routing": "^4.0.0", - "workbox-strategies": "^4.0.0" + "workbox-background-sync": "^4.1.1", + "workbox-core": "^4.1.1", + "workbox-routing": "^4.1.1", + "workbox-strategies": "^4.1.1" } }, "workbox-navigation-preload": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/workbox-navigation-preload/-/workbox-navigation-preload-4.0.0.tgz", - "integrity": "sha512-G2sDCrekZUNFxkBSAcYQHkUbVMJwhkdVFqnCYxmeTiBzOILokVsghmr90CQ4m98gcqc+P4GoMMc+196jN9r+SA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/workbox-navigation-preload/-/workbox-navigation-preload-4.1.1.tgz", + "integrity": "sha512-U+QEpcOgakBFZ6Aiv438DTvkZQX518qxfu280kEPZnFU88wIFBAK9V4MmJcoX60fk1INTD//YnfSxI0cLy1N+g==", "dev": true, "requires": { - "workbox-core": "^4.0.0" + "workbox-core": "^4.1.1" } }, "workbox-precaching": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-4.0.0.tgz", - "integrity": "sha512-juI7N+Rj2/CWU3FXedcDLdjzqvRMpkaQsdsfAxBii5017bivw3Dve/kf4qXePccD2hJ973vKY2F7EJRUos8JvA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-4.1.1.tgz", + "integrity": "sha512-GuoBH85MzVpzmF8c5Sql1i9HYdOqcpRDdNPLrIkWEfuvURO5M/jT+cGcyfFq35Xo7xRb4kE79H4hnF3EnCkFRw==", "dev": true, "requires": { - "workbox-core": "^4.0.0" + "workbox-core": "^4.1.1" } }, "workbox-range-requests": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/workbox-range-requests/-/workbox-range-requests-4.0.0.tgz", - "integrity": "sha512-zymg51V1kZAXrzRNNS+da9nnDKdrOfkV/hoYYr0H174c5gIuT3mcwJFr27AhdTrP7wdEMtWFwlOFMyv99lQxTQ==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/workbox-range-requests/-/workbox-range-requests-4.1.1.tgz", + "integrity": "sha512-i9i7tRTcXveCJdi4lK7XstgHweTwkqEGR7GPauYIDGAZplWrxDOAOUDSvkH8ibOxEgO6f0VFhyYY6fPB6u+oSA==", "dev": true, "requires": { - "workbox-core": "^4.0.0" + "workbox-core": "^4.1.1" } }, "workbox-routing": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-4.0.0.tgz", - "integrity": "sha512-NCo/S4E/MGi0LPC54pAQEKncWbV7Px5NtB4pWpq1RES2nLisS9SwA/7RnaESk9XpCFt4K788soQOKGzbTcQFdQ==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-4.1.1.tgz", + "integrity": "sha512-slOb+2Nfn8V3fG/TtN0c0k4OOyuwLSnZUv+zyZeJafSU3MrQPC58bPeG7HOZZDwoQAsBG9VSukjRDFR0F1lXKg==", "dev": true, "requires": { - "workbox-core": "^4.0.0" + "workbox-core": "^4.1.1" } }, "workbox-strategies": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-4.0.0.tgz", - "integrity": "sha512-837Mk734rhNaqsD1uwWuDjoDddnkfaHWQMyCmBwUzsFb4UnRdInLH9SNIXDm6LgkDjKcoEdKAbp6336De60wLg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-4.1.1.tgz", + "integrity": "sha512-ejmRqmjwn9DYsl1QVZkRb1V/iaBzhsh3YwJelfXQk68JpB36WjwY9csFQ2gSvlLCCg3d4MVFFxKfmHVyVnhwAA==", "dev": true, "requires": { - "workbox-core": "^4.0.0" + "workbox-core": "^4.1.1" } }, "workbox-streams": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/workbox-streams/-/workbox-streams-4.0.0.tgz", - "integrity": "sha512-q9HE8r3BoLBZFAj5FWOhVnjcfmQ+lMaUxZS4FK259xeYDTF9wfo8cxN+inJyCeX6nq6jbWo7XWqGlXV88vaFfg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/workbox-streams/-/workbox-streams-4.1.1.tgz", + "integrity": "sha512-6TKC4rrvnjbLpWtgHIYWjWS28h0SqSWogkJIKC1f/6MjJCmi2qM7PYJwXR0/t8lJVZj61ujVSulZ92XQmy3GhQ==", "dev": true, "requires": { - "workbox-core": "^4.0.0" + "workbox-core": "^4.1.1" } }, "workbox-sw": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/workbox-sw/-/workbox-sw-4.0.0.tgz", - "integrity": "sha512-lVSNtzOPbycn8pSuNtfroT+lXNBry8sUL1494cURIZE1MMFcxCZRv/718LoKIBeJnRYBKa/sXO2GXLzssHX15w==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/workbox-sw/-/workbox-sw-4.1.1.tgz", + "integrity": "sha512-3nQFWFyG1W21x7TUVBsobrLoFDEy7ck/3nx2W1I3c+DhLCIu7B+IAnQVdefK+oRju5fIDWwOQ63fok8Uz7E/Gw==", "dev": true }, "workbox-webpack-plugin": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/workbox-webpack-plugin/-/workbox-webpack-plugin-4.0.0.tgz", - "integrity": "sha512-J1FGWnOcLySCcV9V0t8bIQKTxrQy4OoIT9aBMjnapwPPFJqFcCmxhnU3ozhJDhZh5nrFzE9gbO16yyMs3DQC6g==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/workbox-webpack-plugin/-/workbox-webpack-plugin-4.1.1.tgz", + "integrity": "sha512-Fygc8qrh/IOeJeZ4NETs9arYtJEwcO0Yy7JRkX5DSOHCSkWHxOX1ryazAcK0ACyMJOQuU9zJVmx+mnn0zqYKtA==", "dev": true, "requires": { "@babel/runtime": "^7.0.0", "json-stable-stringify": "^1.0.1", - "workbox-build": "^4.0.0" + "workbox-build": "^4.1.1" } }, "workbox-window": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/workbox-window/-/workbox-window-4.0.0.tgz", - "integrity": "sha512-gdLzP/L0vu5Gi3pdUYtVNmg0yE7OriEuYZBoLt8AYoILXh6cta9WsWHKQ0/pXfmEmZywr4Dfu0qkLLvc9VlZGQ==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/workbox-window/-/workbox-window-4.1.1.tgz", + "integrity": "sha512-KadE/DdNY1f6Va3MMOSigheLSgNxWHV/K/iDHnLMpo2EBGVpfwRCOuEwJNHlWA3G5WdpZlyTmtShf/5Mbb6dNg==", "dev": true, "requires": { - "workbox-core": "^4.0.0" + "workbox-core": "^4.1.1" } }, "worker-farm": { diff --git a/package.json b/package.json index 0210eb6..8ca0551 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@hibas123/securenotes2", - "version": "1.0.0", + "version": "2.0.0-alpha.1", "description": "", "main": "index.js", "scripts": { @@ -13,7 +13,8 @@ "author": "Fabian Stamm ", "license": "MIT", "dependencies": { - "@hibas123/secure-file-wrapper": "^2.3.1", + "@hibas123/secure-file-wrapper": "^2.4.0", + "@hibas123/utils": "^2.0.0", "aes-js": "^3.1.2", "crypto-js": "^3.1.9-1", "feather-icons": "^4.19.0", @@ -23,13 +24,14 @@ "lodash.clonedeep": "^4.5.0", "mini.css": "^3.0.1", "secure-file-wrapper": "git+https://git.stamm.me/OpenServer/OSSecureFileWrapper.git", + "uikit": "^3.0.3", "uuid": "^3.3.2" }, "devDependencies": { - "@types/lodash.clonedeep": "^4.5.5", + "@types/lodash.clonedeep": "^4.5.6", "@types/uuid": "^3.4.4", - "copy-webpack-plugin": "^5.0.0", - "css-loader": "^2.1.0", + "copy-webpack-plugin": "^5.0.2", + "css-loader": "^2.1.1", "file-loader": "^3.0.1", "html-webpack-plugin": "^3.2.0", "mini-css-extract-plugin": "^0.5.0", @@ -39,13 +41,13 @@ "sass-loader": "^7.1.0", "style-loader": "^0.23.1", "ts-loader": "^5.3.0", - "typescript": "^3.3.3333", + "typescript": "^3.3.4000", "webpack": "^4.29.6", "webpack-bundle-analyzer": "^3.1.0", - "webpack-cli": "^3.2.3", + "webpack-cli": "^3.3.0", "webpack-dev-server": "^3.2.1", "webpack-visualizer-plugin": "^0.1.11", - "workbox-webpack-plugin": "^4.0.0", + "workbox-webpack-plugin": "^4.1.1", "worker-loader": "^2.0.0" } -} +} \ No newline at end of file diff --git a/public/manifest.json b/public/manifest.json index 6bb75a5..f7ec668 100755 --- a/public/manifest.json +++ b/public/manifest.json @@ -3,7 +3,10 @@ "name": "Secure Notes", "decription": "A place to store your notes securly", "share_target": { - "action": "/#/share", + "url_template": "/#/share?title={title}&text={text}&url={url}", + "method": "GET", + "enctype": "application/x-www-form-urlencoded", + "action": "/", "params": { "title": "title", "text": "text", diff --git a/public/serviceworker.js b/public/serviceworker.js new file mode 100644 index 0000000..8e22bc1 --- /dev/null +++ b/public/serviceworker.js @@ -0,0 +1,121 @@ +function log(...params) { + console.log.apply(this, [...["%c[SW]: %c", "color: #f4b942;", "color:unset;"], ...params]) +} + +const CACHE = "offline"; + +let precacheFiles = [ + "/", + "/main.js", + "/main.css", + "/serviceworker.js" +] + +//Install stage sets up the cache-array to configure pre-cache content +self.addEventListener('install', (evt) => { + log('The service worker is being installed.'); + evt.waitUntil(precache().then(() => { + log('Skip waiting on install'); + }).catch(log).then(() => self.skipWaiting())); +}); + +//allow sw to control of current page +self.addEventListener('activate', (event) => { + log('Claiming clients for current page'); + return self.clients.claim(); +}); + +self.addEventListener('message', (event) => { + if (event.data === "clear_cache") { + log("Clearing cache"); + caches.delete(CACHE); + } + + if (event.data === "update_index") { + log("Updating index"); + event.waitUntil(caches.open(CACHE).then((cache) => { + return cache.addAll(["/", "/index.html"]).then(() => { + event.ports[0].postMessage("reload"); + }); + })) + } +}); + +var Types; +(function (Types) { + Types[Types["CACHE"] = 0] = "CACHE"; + Types[Types["NOCACHE"] = 1] = "NOCACHE"; + Types[Types["REFRESH"] = 2] = "REFRESH"; +})(Types || (Types = {})); + +let rules = [ + { + match: (url) => { + return url.indexOf("/api/") >= 0; + }, + type: Types.NOCACHE + }, + { + match: (url) => { + return url.indexOf("/version_hash") >= 0; + }, + type: Types.NOCACHE + }, + { + match: () => { + return true; + }, + type: Types.REFRESH + } +] + +self.addEventListener('fetch', (evt) => { + if (evt.request.method != 'GET') return; // Dont care about POST requests + let rule = rules.find(rule => rule.match(evt.request.url)); + evt.respondWith((async () => { + log("Cache:", Types[rule.type]); + switch (rule.type) { + case Types.CACHE: + return fromCache(evt.request); + case Types.REFRESH: + return refresh(evt.request).then(r => { + evt.waitUntil(r.refresh.catch(_ => { })); + return r.result; + }); + case Types.NOCACHE: + return fetch(evt.request); + } + })()); +}); + +async function fromCache(request) { + let cache = await caches.open(CACHE); + let matching = await cache.match(request); + if (matching) + return matching + + let res = await fetch(request.clone()); + await cache.put(request, res); + return await cache.match(request); +} + +async function refresh(request) { + let cache = await caches.open(CACHE); + let web = fetch(request.clone()).then(res => { + return cache.put(request, res).then(() => { + return cache.match(request); + }) + }) + let matching = await cache.match(request); + + return { + result: matching ? matching : web, + refresh: web + } +} + +function precache() { + return caches.open(CACHE).then(function (cache) { + return cache.addAll(precacheFiles); + }); +} \ No newline at end of file diff --git a/src/components/AddButton.tsx b/src/components/AddButton.tsx index 05b2e65..e8d5458 100755 --- a/src/components/AddButton.tsx +++ b/src/components/AddButton.tsx @@ -1,7 +1,6 @@ import { h } from "preact"; import "./add_button.scss"; import Plus from "feather-icons/dist/icons/plus.svg"; - export default function AddButton({ onClick }: { onClick: () => void }) { return } \ No newline at end of file diff --git a/src/components/App.tsx b/src/components/App.tsx index e54ce1e..15cd6a7 100755 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -2,11 +2,13 @@ import { Router } from "./Routing"; import { h } from "preact"; import NotificationsComponent from "./notifications"; import { ModalComponent } from "./modals/Modal"; +import { Footer } from "./Footer"; export default function App() { return
+
} \ No newline at end of file diff --git a/src/components/Footer.tsx b/src/components/Footer.tsx new file mode 100644 index 0000000..1ce28fe --- /dev/null +++ b/src/components/Footer.tsx @@ -0,0 +1,70 @@ +import { h, Component } from "preact"; +import Notes from "../notes"; +import Refresh from "feather-icons/dist/icons/refresh-cw.svg"; +import "./footer.scss"; +import Notifications from "../notifications"; + +export class Footer extends Component<{}, { synced: boolean, syncing: boolean }> { + constructor(props) { + super(props); + this.state = { synced: false, syncing: false }; + this.onSyncedChange = this.onSyncedChange.bind(this); + this.onSyncChange = this.onSyncChange.bind(this); + } + + async componentWillMount() { + Notes.syncedObservable.subscribe(this.onSyncedChange); + Notes.syncObservable.subscribe(this.onSyncChange); + this.setState({ synced: await Notes.isSynced() }) + } + + componentWillUnmount() { + Notes.syncedObservable.unsubscribe(this.onSyncedChange); + Notes.syncObservable.unsubscribe(this.onSyncChange); + } + + onSyncChange(state: boolean) { + console.log("sync", state); + this.setState({ syncing: state }) + } + + onSyncedChange(state: boolean) { + console.log("synced", state); + this.setState({ synced: state }) + } + + onSyncClick() { + Notes.sync().then(() => { + Notifications.sendInfo("Finished Synchronisation"); + }) + } + + render() { + let extrac = ""; + let color; + let text; + if (this.state.syncing) { + color = "orange"; + text = "syncing"; + extrac = "reloading" + } else { + if (this.state.synced) { + color = "green"; + text = "synced"; + } else { + color = "red"; + text = "not synced"; + } + } + return + } + +} \ No newline at end of file diff --git a/src/components/Routing.tsx b/src/components/Routing.tsx index 85678be..c22b924 100755 --- a/src/components/Routing.tsx +++ b/src/components/Routing.tsx @@ -12,14 +12,14 @@ export class Router extends Component<{}, { next?: JSX.Element, current: JSX.Ele } componentWillMount() { - Navigation.pageObservable.subscribe(this.onChange, true) + Navigation.pageObservable.subscribe(this.onChange) } componentWillUnmount() { Navigation.pageObservable.unsubscribe(this.onChange) } - onChange([page]: JSX.Element[]) { + onChange(page: JSX.Element) { this.setState({ next: page, current: this.state.next || this.state.current }); } @@ -42,7 +42,7 @@ export class Router extends Component<{}, { next?: JSX.Element, current: JSX.Ele {this.state.next} } - return
+ return
this.mounted = elm}> {this.state.current}
diff --git a/src/components/footer.scss b/src/components/footer.scss new file mode 100644 index 0000000..75e2477 --- /dev/null +++ b/src/components/footer.scss @@ -0,0 +1,19 @@ +.reloading { animation: turner 1s infinite linear } + +@keyframes turner{ + from{ transform: rotate(0deg) } + to { transform: rotate(360deg) } +} + +footer { + z-index: 128; + position: fixed; + bottom: 0; + left: 0; + right: 0; + + display: flex; + justify-content: space-between; + + padding: calc(0.9 * var(--universal-padding)) !important; +} \ No newline at end of file diff --git a/src/components/modals/InputModal.tsx b/src/components/modals/InputModal.tsx index 1e1b2b5..4a899f2 100755 --- a/src/components/modals/InputModal.tsx +++ b/src/components/modals/InputModal.tsx @@ -23,7 +23,7 @@ export class InputModal extends Modal { render() { return -
+
{ this.input = elm @@ -47,41 +47,4 @@ export class InputModal extends Modal { getComponent() { return } -} - - -// export class InputModal extends Component<{ title: string, fieldname: string, type: "text" | "password", onResult: (result) => void }, {}> { -// input: HTMLInputElement; -// rand: string; -// constructor(props) { -// super(props); -// this.rand = Math.random().toString(); -// } - -// componentWillUnmount() { -// if (this.input) -// this.input.value = ""; -// } - -// render() { -// return this.props.onResult(null)}> -//
-// -// { -// this.input = elm -// if (this.input) -// setTimeout(() => this.input.focus(), 0) -// }} type={this.props.type} id={this.rand} placeholder={this.props.fieldname} onKeyDown={evt => { -// if (evt.keyCode === 13) { -// this.props.onResult(this.input.value) -// } -// }} /> -//
-// -//
-//
-//
-// } -// } \ No newline at end of file +} \ No newline at end of file diff --git a/src/components/modals/Modal.tsx b/src/components/modals/Modal.tsx index c8d4f86..86e4d28 100644 --- a/src/components/modals/Modal.tsx +++ b/src/components/modals/Modal.tsx @@ -1,9 +1,10 @@ -import Observable from "../../helper/observable"; +import { Observable } from "@hibas123/utils"; import { h, Component } from "preact"; +import CloseIcon from "feather-icons/dist/icons/x.svg"; export default abstract class Modal { // Static - private static modalObservableServer = new Observable<{ modal: Modal, close: boolean }>(false); + private static modalObservableServer = new Observable<{ modal: Modal, close: boolean }>(); public static modalObservable = Modal.modalObservableServer.getPublicApi(); @@ -11,9 +12,12 @@ export default abstract class Modal { // Private private onResult: (result: T | null) => void; + private closeOnResult: boolean; // Protected protected result(value: T | null) { + if (this.closeOnResult) + this.close() if (this.onResult) this.onResult(value); } @@ -32,7 +36,8 @@ export default abstract class Modal { * * Call close when successful */ - public async getResult() { + public async getResult(close = true) { + this.closeOnResult = close; this.show(); return new Promise((yes) => this.onResult = yes); } @@ -65,7 +70,12 @@ export default abstract class Modal { } }}>
-

{this.props.modal.title}

+
+

{this.props.modal.title}

+

+ this.props.modal.result(null)} width={undefined} height={undefined} style="height:calc(1rem * var(--heading-ratio) * var(--heading-ratio))" /> +

+
{this.props.children}
@@ -74,62 +84,24 @@ export default abstract class Modal { } - -// export default abstract class Modal extends Component<{}, S> { - - -// // Abstract -// protected abstract renderChilds(): JSX.Element; -// protected abstract title: string; - - - -// render() { -// return -// } -// } - export class ModalComponent extends Component<{}, { modal: Modal | undefined, component: JSX.Element | undefined }>{ constructor(props) { super(props); this.onModal = this.onModal.bind(this); } - onModal([{ modal, close }]: { modal: Modal, close: boolean }[]) { + onModal({ modal, close }: { modal: Modal, close: boolean }) { if (!close && this.state.modal !== modal) { this.setState({ modal: modal, component: modal.getComponent() }) } else { - if (this.state.modal === modal) // Only close if the same + if (this.state.modal === modal && close) // Only close if the same this.setState({ modal: undefined, component: undefined }) } } componentWillMount() { - Modal.modalObservable.subscribe(this.onModal, true); + Modal.modalObservable.subscribe(this.onModal); } componentWillUnmount() { diff --git a/src/components/modals/YesNoModal.tsx b/src/components/modals/YesNoModal.tsx index 35caaa4..7ccb5e0 100755 --- a/src/components/modals/YesNoModal.tsx +++ b/src/components/modals/YesNoModal.tsx @@ -28,7 +28,7 @@ export class YesNoModal extends Modal { render() { return -
+
- //
const close = () => { window.removeEventListener("click", close); @@ -142,7 +137,6 @@ export default class VaultsPage extends Page { let delete_modal = new YesNoModal("Delete Vault? Cannot be undone!"); let result = await delete_modal.getResult(); - delete_modal.close(); if (result) { Notes.deleteVault(vault.id).then(() => { this.updateVaults(); @@ -157,7 +151,10 @@ export default class VaultsPage extends Page { Notes.forgetVaultKey(vault.id); }}> + delete_key = ; } @@ -219,14 +216,16 @@ export default class VaultsPage extends Page {this.state.modal} {this.state.context} +
+ +

Navigation.setPage("/")}>Your vaults:

+ +
this.addButtonClick()} />
- -

Your vaults:

-
{elms}
diff --git a/src/components/routing.scss b/src/components/routing.scss index b79d604..b58a3dc 100755 --- a/src/components/routing.scss +++ b/src/components/routing.scss @@ -6,9 +6,13 @@ width: 100%; overflow: auto; background: var(--back-color); + padding-bottom: 40px; } .transition_slidein { + position: absolute; + top: 0; + left: 0; animation-name: slidein; animation-duration: 0.3s; z-index: 64; diff --git a/src/helper/indexeddb.ts b/src/helper/indexeddb.ts index 6232187..d3b9ba3 100755 --- a/src/helper/indexeddb.ts +++ b/src/helper/indexeddb.ts @@ -1,4 +1,4 @@ -import Lock from "./lock"; +import { Lock } from "@hibas123/utils"; import { DB, openDb, Transaction } from "idb"; diff --git a/src/helper/lock.ts b/src/helper/lock.ts deleted file mode 100755 index 13b927b..0000000 --- a/src/helper/lock.ts +++ /dev/null @@ -1,36 +0,0 @@ -export type Release = { release: () => void }; -export default class Lock { - private _locked: boolean = false; - get locked() { - return this._locked; - } - private toCome: (() => void)[] = []; - - constructor() { - this.release = this.release.bind(this); - } - - async getLock(): Promise { - if (!this._locked) return { release: this.lock() }; - else { - return new Promise((resolve) => { - this.toCome.push(() => { - resolve({ release: this.lock() }); - }) - }) - } - } - - private lock() { - this._locked = true; - return this.release; - } - - private async release() { - if (this.toCome.length > 0) { - this.toCome.shift()(); - } else { - this._locked = false; - } - } -} diff --git a/src/helper/observable.ts b/src/helper/observable.ts deleted file mode 100755 index d867060..0000000 --- a/src/helper/observable.ts +++ /dev/null @@ -1,46 +0,0 @@ -export type ObserverCallback = (data: T[]) => void; - -export default class Observable { - private subscriber: { callback: ObserverCallback, one: boolean }[] = []; - private events: T[] = []; - private timeout = undefined; - - constructor(private collect: boolean = true, private collect_intervall: number = 100) { } - - getPublicApi() { - return { - subscribe: (callback: ObserverCallback, one: boolean = false) => { - let oldcb = this.subscriber.find(e => e.callback === callback); - if (oldcb) - oldcb.one = one - else - this.subscriber.push({ callback, one }) - }, - unsubscribe: (callback: ObserverCallback) => { - let idx = this.subscriber.findIndex(e => e.callback === callback); - if (idx >= 0) { - this.subscriber.splice(idx, 1); - } - } - } - } - - send(data: T) { - if (!this.collect) - this.subscriber.forEach(e => e.callback([data])); - else { - this.events.push(data); - if (!this.timeout) { - this.timeout = setTimeout(() => { - this.subscriber.forEach(cb => { - if (cb.one) - this.events.forEach(e => cb.callback([e])); - else - cb.callback(this.events) - }); - this.timeout = 0; - }, this.collect_intervall); - } - } - } -} \ No newline at end of file diff --git a/src/index.html b/src/index.html index 6a0b90f..6f9c186 100755 --- a/src/index.html +++ b/src/index.html @@ -6,20 +6,17 @@ - + - + - - - - - + + @@ -30,13 +27,33 @@
diff --git a/src/index.tsx b/src/index.tsx index 124df3a..8f9192f 100755 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,8 +1,12 @@ +window.debug = {}; + import { h, render } from 'preact'; import App from './components/App'; -import "mini.css/src/flavors/mini-dark.scss" -// import "mini.css/src/flavors/mini-default.scss" +// import "mini.css/src/flavors/mini-dark.scss" +import "mini.css/src/flavors/mini-default.scss" +import "uikit"; +import "uikit/dist/css/uikit.css" import "./index.scss" import Navigation from './navigation'; import VaultsPage from './components/routes/vaults/Vaults'; diff --git a/src/navigation.ts b/src/navigation.ts index 9de8368..1d1bee9 100755 --- a/src/navigation.ts +++ b/src/navigation.ts @@ -1,4 +1,4 @@ -import Observable from "./helper/observable"; +import { Observable } from "@hibas123/utils"; import { Page, PageProps } from "./page"; import { h, VNode } from "preact"; @@ -27,7 +27,7 @@ function parseQuery(query: string) { export default class Navigation { private static _pages: Map = new Map(); private static _page: { route: string, page: JSX.Element }; - private static pageObservableServer = new Observable(false); + private static pageObservableServer = new Observable(); public static pageObservable = Navigation.pageObservableServer.getPublicApi(); private static _state: { [key: string]: any }; private static _hidden_state: { [key: string]: any }; @@ -52,13 +52,14 @@ export default class Navigation { } public static setPage(route: string, state?: { [key: string]: string }, hidden?: { [key: string]: string }, replace?: boolean) { + if (!state) state = {}; let component = Navigation._pages.get(route); if (!component && route !== "/404") { Navigation.setPage("/404", { route, key: "404" }) } else { if (!Navigation.page || Navigation.page.route !== route || JSON.stringify(state) !== JSON.stringify(Navigation._state) || JSON.stringify(Navigation._hidden_state) !== JSON.stringify(hidden)) { let s = ""; - if (state) { + if (Object.keys(state).length > 0) { s = "?" + serializQuery(state) } let newhash = "#" + route + s; @@ -92,6 +93,7 @@ export default class Navigation { Navigation._state = state; Navigation._hidden_state = hidden; Navigation._page = { page, route }; + console.log(route, state, hidden); Navigation.pageObservableServer.send(page); } } @@ -142,4 +144,6 @@ export default class Navigation { }) Navigation.onHashChange(undefined); } -} \ No newline at end of file +} + +window.debug.navigation = Navigation; \ No newline at end of file diff --git a/src/notes.ts b/src/notes.ts index 7d13878..7e23056 100644 --- a/src/notes.ts +++ b/src/notes.ts @@ -1,6 +1,5 @@ -import Observable from "./helper/observable"; import * as config from "../config.json" -import Lock from "./helper/lock" +import { Lock, Observable } from "@hibas123/utils" import SecureFile, { IFile } from "@hibas123/secure-file-wrapper"; import * as b64 from "./helper/base64" @@ -33,9 +32,7 @@ export interface ViewNote extends BaseNote { __value: string; } -// import * as AES from "crypto-js/aes" import * as aesjs from "aes-js"; -// import { } from "js-sha512" import { sha256 } from "js-sha256" import clonedeep = require("lodash.clonedeep"); import * as uuidv4 from "uuid/v4" @@ -87,11 +84,16 @@ export interface IVault { deleteNote(id: string): Promise; } +const awaitTimeout = (ms: number) => new Promise(resolve => setTimeout(resolve, ms)); + class NotesProvider { - private notesObservableServer = new Observable(true) + private notesObservableServer = new Observable() public notesObservable = this.notesObservableServer.getPublicApi() - private syncObservableServer = new Observable(true) + private syncObservableServer = new Observable() + /** + * Will send false once finished and true on start + */ public syncObservable = this.syncObservableServer.getPublicApi() private database = new IDB("notes", ["notes", "oplog"]); @@ -110,6 +112,18 @@ class NotesProvider { private generalEncryption: Uint8Array = undefined; + private syncedObservableServer = new Observable(); + public syncedObservable = this.syncedObservableServer.getPublicApi(); + + public async isSynced() { + return (await this.oplogDB.getAll()).length <= 0 + } + + private _name; + public get name() { + return this._name; + } + loginRequired() { return !localStorage.getItem("refreshtoken") || !this.generalEncryption; } @@ -123,6 +137,8 @@ class NotesProvider { let res = await req.json(); if (!res.error) { localStorage.setItem("refreshtoken", res.token); + localStorage.setItem("name", res.profile.name); + this._name = res.profile.name; let kb = this.passwordToKey(res.profile.enc_key); localStorage.setItem("enc_key", b64.encode(kb)); this.generalEncryption = kb @@ -133,7 +149,7 @@ class NotesProvider { constructor(public readonly baseurl = "") { this._secureFile = new SecureFile(config.secure_file_server); - this._secureFile.jwtObservable.subscribe(async ([callback]) => { + this._secureFile.jwtObservable.subscribe(async (callback) => { let jwt = await this.getJWT(); callback(jwt); }) @@ -142,6 +158,7 @@ class NotesProvider { if (key) { this.generalEncryption = b64.decode(key) } + this._name = localStorage.getItem("name"); } public async start() { @@ -150,8 +167,10 @@ class NotesProvider { this.sync().then(() => next); }, 30000) } - - return this.apiLockRls.then(lock => lock.release()).then(() => { this.sync() }).then(() => next()) + this.syncedObservableServer.send((await this.oplogDB.getAll()).length <= 0); + let prs = this.apiLockRls.then(lock => lock.release()); + prs.then(() => awaitTimeout(5000)).then(() => this.sync()).then(() => next()); + return prs; } private async getJWT() { @@ -182,11 +201,13 @@ class NotesProvider { window.location.reload(); } - private async sync() { + async sync() { const lock = await this.syncLock.getLock() const log = (...message: any[]) => { console.log("[SYNC]: ", ...message) } + + this.syncObservableServer.send(true); log("Start") try { log("Fetching"); @@ -351,10 +372,11 @@ class NotesProvider { await this.oplogDB.delete(id); } log("Stats", stats); + this.syncedObservableServer.send((await this.oplogDB.getAll()).length <= 0) } finally { log("Finished") lock.release() - this.syncObservableServer.send(null); + this.syncObservableServer.send(false); } } @@ -464,6 +486,7 @@ class NotesProvider { type, values }) + this.syncedObservableServer.send(false); await this.oplogDB.set(note_id, oplog, tx); } diff --git a/src/notifications.ts b/src/notifications.ts index 9820a7c..a8765a2 100644 --- a/src/notifications.ts +++ b/src/notifications.ts @@ -1,4 +1,4 @@ -import Observable from "./helper/observable"; +import { Observable } from "@hibas123/utils"; export enum MessageType { INFO, @@ -8,7 +8,7 @@ export enum MessageType { } export default class Notifications { - private static messageObservableServer = new Observable<{ message: string, type: MessageType }>(false) + private static messageObservableServer = new Observable<{ message: string, type: MessageType }>() public static messageObservable = Notifications.messageObservableServer.getPublicApi() diff --git a/src/types.d.ts b/src/types.d.ts index f32dc64..668e49e 100755 --- a/src/types.d.ts +++ b/src/types.d.ts @@ -1,2 +1,13 @@ -// import { Component } from "preact"; -declare module "*.svg"; \ No newline at end of file +declare module "*.svg" { + const SVG: (props: { + width?: number | undefined + height?: number | undefined + onClick?: (evt: MouseEvent) => void; + style?: string; + }) => JSX.Element; + export default SVG; +} + +interface Window { + debug: any; +} \ No newline at end of file diff --git a/webpack.config.js b/webpack.config.js index 2b0ebb4..c6e7ccf 100755 --- a/webpack.config.js +++ b/webpack.config.js @@ -25,7 +25,7 @@ module.exports = { public: url.parse(config.callback_url).hostname }, plugins: [ - new CopyWebpackPlugin([{ from: "public", to: "public" }]), + new CopyWebpackPlugin([{ from: "public" }]), new HtmlWebpackPlugin({ title: 'SecureNotes', template: "./src/index.html" @@ -39,29 +39,29 @@ module.exports = { openAnalyzer: false }), new Visualizer(), - // new WorkboxPlugin.GenerateSW({ - // swDest: "sw.js", - // importWorkboxFrom: 'local', - // clientsClaim: true, - // // importsDirectory: "/dist", - // directoryIndex: 'index.html', - // ignoreUrlParametersMatching: [/./], - // runtimeCaching: [{ - // urlPattern: /images/, - // handler: 'cacheFirst', - // options: { - // cacheName: 'images', - // expiration: { - // maxEntries: 1000, - // //Recheck after 30 Days - // maxAgeSeconds: 30 * 24 * 60 * 60 + // new WorkboxPlugin.GenerateSW({ + // swDest: "sw.js", + // importWorkboxFrom: 'local', + // clientsClaim: true, + // // importsDirectory: "/dist", + // directoryIndex: 'index.html', + // ignoreURLParametersMatching: [/./], + // runtimeCaching: [{ + // urlPattern: /images/, + // handler: 'CacheFirst', + // options: { + // cacheName: 'images', + // expiration: { + // maxEntries: 1000, + // //Recheck after 30 Days + // maxAgeSeconds: 30 * 24 * 60 * 60 + // }, // }, - // }, - // }, { - // urlPattern: /api/, - // handler: 'networkOnly' - // }] - // }) + // }, { + // urlPattern: /api/, + // handler: 'NetworkOnly' + // }] + // }) ], entry: "./src/index.tsx", // Enable sourcemaps for debugging webpack's output. @@ -80,7 +80,7 @@ module.exports = { test: /\.(png|jpg)$/, loader: "file-loader", }, { - test: /\.scss$/, + test: /\.(scss|css)$/, use: [ "style-loader", // creates style nodes from JS strings MiniCssExtractPlugin.loader,