From f13f68ff2117fb3e5903c2c4dabd233458b742d3 Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Mon, 12 Sep 2022 18:33:24 -0700 Subject: [PATCH] TS migration WIP --- package-lock.json | 286 +++- package.json | 8 +- src/App.vue | 2 +- src/components/Photo.vue | 279 ++-- src/components/Timeline.vue | 1429 +++++++++-------- src/{main.js => main.ts} | 9 +- src/mixins/{UserConfig.js => UserConfig.ts} | 0 src/mixins/{constants.js => constants.ts} | 0 src/{router.js => router.ts} | 6 +- src/services/{DavClient.js => DavClient.ts} | 4 +- .../{DavRequests.js => DavRequests.ts} | 61 +- src/services/{FileUtils.js => FileUtils.ts} | 6 +- .../{NumberUtils.js => NumberUtils.ts} | 2 +- src/services/{Utils.js => Utils.ts} | 6 +- src/types.ts | 69 + src/vue-shims.d.ts | 10 + tsconfig.json | 13 + webpack.js | 16 + 18 files changed, 1271 insertions(+), 935 deletions(-) rename src/{main.js => main.ts} (87%) rename src/mixins/{UserConfig.js => UserConfig.ts} (100%) rename src/mixins/{constants.js => constants.ts} (100%) rename src/{router.js => router.ts} (92%) rename src/services/{DavClient.js => DavClient.ts} (89%) rename src/services/{DavRequests.js => DavRequests.ts} (79%) rename src/services/{FileUtils.js => FileUtils.ts} (95%) rename src/services/{NumberUtils.js => NumberUtils.ts} (94%) rename src/services/{Utils.js => Utils.ts} (66%) create mode 100644 src/types.ts create mode 100644 src/vue-shims.d.ts create mode 100644 tsconfig.json diff --git a/package-lock.json b/package-lock.json index ac1d6c98..f45c8b80 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,18 +1,21 @@ { "name": "memories", - "version": "0.0.0", + "version": "1.0.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "memories", - "version": "0.0.0", + "version": "1.0.1", "license": "agpl", "dependencies": { "@nextcloud/l10n": "^1.6.0", "@nextcloud/vue": "^6.0.0-beta.6", "path-posix": "^1.0.0", + "reflect-metadata": "^0.1.13", "vue": "^2.7.10", + "vue-class-component": "^7.2.6", + "vue-property-decorator": "^9.1.2", "vue-router": "^3.5.4", "vue-virtual-scroller": "^1.0.10", "webdav": "^4.11.0" @@ -22,7 +25,10 @@ "@nextcloud/browserslist-config": "^2.3.0", "@nextcloud/eslint-config": "^8.1.2", "@nextcloud/stylelint-config": "^2.2.0", - "@nextcloud/webpack-vue-config": "^5.3.0" + "@nextcloud/webpack-vue-config": "^5.3.0", + "@types/url-parse": "^1.4.8", + "ts-loader": "^9.3.1", + "typescript": "^4.8.3" }, "engines": { "node": ">=14.0.0", @@ -2583,6 +2589,12 @@ "@types/node": "*" } }, + "node_modules/@types/url-parse": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/@types/url-parse/-/url-parse-1.4.8.tgz", + "integrity": "sha512-zqqcGKyNWgTLFBxmaexGUKQyWqeG7HjXj20EuQJSJWwXe54BjX0ihIo5cJB9yAQzH8dNugJ9GvkBYMjPXs/PJw==", + "dev": true + }, "node_modules/@types/ws": { "version": "8.5.3", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", @@ -3450,7 +3462,6 @@ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, - "peer": true, "dependencies": { "fill-range": "^7.0.1" }, @@ -4706,7 +4717,6 @@ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz", "integrity": "sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ==", "dev": true, - "peer": true, "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -5803,7 +5813,6 @@ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dev": true, - "peer": true, "dependencies": { "to-regex-range": "^5.0.1" }, @@ -6283,8 +6292,7 @@ "version": "4.2.10", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "dev": true, - "peer": true + "dev": true }, "node_modules/grapheme-splitter": { "version": "1.0.4", @@ -7091,7 +7099,6 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, - "peer": true, "engines": { "node": ">=0.12.0" } @@ -7715,7 +7722,6 @@ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", "dev": true, - "peer": true, "dependencies": { "braces": "^3.0.2", "picomatch": "^2.3.1" @@ -8425,7 +8431,6 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, - "peer": true, "engines": { "node": ">=8.6" }, @@ -9110,6 +9115,11 @@ "node": ">=8" } }, + "node_modules/reflect-metadata": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" + }, "node_modules/regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", @@ -10490,7 +10500,6 @@ "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", "dev": true, - "peer": true, "engines": { "node": ">=6" } @@ -10625,7 +10634,6 @@ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, - "peer": true, "dependencies": { "is-number": "^7.0.0" }, @@ -10663,6 +10671,110 @@ "node": ">=8" } }, + "node_modules/ts-loader": { + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.3.1.tgz", + "integrity": "sha512-OkyShkcZTsTwyS3Kt7a4rsT/t2qvEVQuKCTg4LJmpj9fhFR7ukGdZwV6Qq3tRUkqcXtfGpPR7+hFKHCG/0d3Lw==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "enhanced-resolve": "^5.0.0", + "micromatch": "^4.0.0", + "semver": "^7.3.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "typescript": "*", + "webpack": "^5.0.0" + } + }, + "node_modules/ts-loader/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ts-loader/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/ts-loader/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/ts-loader/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/ts-loader/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ts-loader/node_modules/semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ts-loader/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/tsconfig-paths": { "version": "3.14.1", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", @@ -10741,6 +10853,19 @@ "node": ">= 0.6" } }, + "node_modules/typescript": { + "version": "4.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.3.tgz", + "integrity": "sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, "node_modules/unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", @@ -10973,6 +11098,14 @@ "csstype": "^3.1.0" } }, + "node_modules/vue-class-component": { + "version": "7.2.6", + "resolved": "https://registry.npmjs.org/vue-class-component/-/vue-class-component-7.2.6.tgz", + "integrity": "sha512-+eaQXVrAm/LldalI272PpDe3+i4mPis0ORiMYxF6Ae4hyuCh15W8Idet7wPUEs4N4YptgFHGys4UrgNQOMyO6w==", + "peerDependencies": { + "vue": "^2.0.0" + } + }, "node_modules/vue-color": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/vue-color/-/vue-color-2.8.1.tgz", @@ -11139,6 +11272,15 @@ "resolved": "https://registry.npmjs.org/vue-observe-visibility/-/vue-observe-visibility-0.4.6.tgz", "integrity": "sha512-xo0CEVdkjSjhJoDdLSvoZoQrw/H2BlzB5jrCBKGZNXN2zdZgMuZ9BKrxXDjNP2AxlcCoKc8OahI3F3r3JGLv2Q==" }, + "node_modules/vue-property-decorator": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/vue-property-decorator/-/vue-property-decorator-9.1.2.tgz", + "integrity": "sha512-xYA8MkZynPBGd/w5QFJ2d/NM0z/YeegMqYTphy7NJQXbZcuU6FC6AOdUAcy4SXP+YnkerC6AfH+ldg7PDk9ESQ==", + "peerDependencies": { + "vue": "*", + "vue-class-component": "*" + } + }, "node_modules/vue-resize": { "version": "0.4.5", "resolved": "https://registry.npmjs.org/vue-resize/-/vue-resize-0.4.5.tgz", @@ -13744,6 +13886,12 @@ "@types/node": "*" } }, + "@types/url-parse": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/@types/url-parse/-/url-parse-1.4.8.tgz", + "integrity": "sha512-zqqcGKyNWgTLFBxmaexGUKQyWqeG7HjXj20EuQJSJWwXe54BjX0ihIo5cJB9yAQzH8dNugJ9GvkBYMjPXs/PJw==", + "dev": true + }, "@types/ws": { "version": "8.5.3", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", @@ -14474,7 +14622,6 @@ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, - "peer": true, "requires": { "fill-range": "^7.0.1" } @@ -15468,7 +15615,6 @@ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz", "integrity": "sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ==", "dev": true, - "peer": true, "requires": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -16299,7 +16445,6 @@ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dev": true, - "peer": true, "requires": { "to-regex-range": "^5.0.1" } @@ -16666,8 +16811,7 @@ "version": "4.2.10", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "dev": true, - "peer": true + "dev": true }, "grapheme-splitter": { "version": "1.0.4", @@ -17257,8 +17401,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "peer": true + "dev": true }, "is-number-object": { "version": "1.0.7", @@ -17739,7 +17882,6 @@ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", "dev": true, - "peer": true, "requires": { "braces": "^3.0.2", "picomatch": "^2.3.1" @@ -18293,8 +18435,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "peer": true + "dev": true }, "pkg-dir": { "version": "4.2.0", @@ -18801,6 +18942,11 @@ "strip-indent": "^3.0.0" } }, + "reflect-metadata": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" + }, "regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", @@ -19883,8 +20029,7 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true, - "peer": true + "dev": true }, "terser": { "version": "5.14.2", @@ -19977,7 +20122,6 @@ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, - "peer": true, "requires": { "is-number": "^7.0.0" } @@ -20006,6 +20150,78 @@ "dev": true, "peer": true }, + "ts-loader": { + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.3.1.tgz", + "integrity": "sha512-OkyShkcZTsTwyS3Kt7a4rsT/t2qvEVQuKCTg4LJmpj9fhFR7ukGdZwV6Qq3tRUkqcXtfGpPR7+hFKHCG/0d3Lw==", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "enhanced-resolve": "^5.0.0", + "micromatch": "^4.0.0", + "semver": "^7.3.4" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "tsconfig-paths": { "version": "3.14.1", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", @@ -20071,6 +20287,12 @@ "mime-types": "~2.1.24" } }, + "typescript": { + "version": "4.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.3.tgz", + "integrity": "sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig==", + "dev": true + }, "unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", @@ -20259,6 +20481,12 @@ "csstype": "^3.1.0" } }, + "vue-class-component": { + "version": "7.2.6", + "resolved": "https://registry.npmjs.org/vue-class-component/-/vue-class-component-7.2.6.tgz", + "integrity": "sha512-+eaQXVrAm/LldalI272PpDe3+i4mPis0ORiMYxF6Ae4hyuCh15W8Idet7wPUEs4N4YptgFHGys4UrgNQOMyO6w==", + "requires": {} + }, "vue-color": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/vue-color/-/vue-color-2.8.1.tgz", @@ -20383,6 +20611,12 @@ "resolved": "https://registry.npmjs.org/vue-observe-visibility/-/vue-observe-visibility-0.4.6.tgz", "integrity": "sha512-xo0CEVdkjSjhJoDdLSvoZoQrw/H2BlzB5jrCBKGZNXN2zdZgMuZ9BKrxXDjNP2AxlcCoKc8OahI3F3r3JGLv2Q==" }, + "vue-property-decorator": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/vue-property-decorator/-/vue-property-decorator-9.1.2.tgz", + "integrity": "sha512-xYA8MkZynPBGd/w5QFJ2d/NM0z/YeegMqYTphy7NJQXbZcuU6FC6AOdUAcy4SXP+YnkerC6AfH+ldg7PDk9ESQ==", + "requires": {} + }, "vue-resize": { "version": "0.4.5", "resolved": "https://registry.npmjs.org/vue-resize/-/vue-resize-0.4.5.tgz", diff --git a/package.json b/package.json index c06f7872..15e922d8 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,10 @@ "@nextcloud/l10n": "^1.6.0", "@nextcloud/vue": "^6.0.0-beta.6", "path-posix": "^1.0.0", + "reflect-metadata": "^0.1.13", "vue": "^2.7.10", + "vue-class-component": "^7.2.6", + "vue-property-decorator": "^9.1.2", "vue-router": "^3.5.4", "vue-virtual-scroller": "^1.0.10", "webdav": "^4.11.0" @@ -52,6 +55,9 @@ "@nextcloud/browserslist-config": "^2.3.0", "@nextcloud/eslint-config": "^8.1.2", "@nextcloud/stylelint-config": "^2.2.0", - "@nextcloud/webpack-vue-config": "^5.3.0" + "@nextcloud/webpack-vue-config": "^5.3.0", + "@types/url-parse": "^1.4.8", + "ts-loader": "^9.3.1", + "typescript": "^4.8.3" } } diff --git a/src/App.vue b/src/App.vue index 9af5bf43..05d27eaa 100644 --- a/src/App.vue +++ b/src/App.vue @@ -45,7 +45,7 @@ } - diff --git a/src/components/Timeline.vue b/src/components/Timeline.vue index 6ae06e45..fb2760e9 100644 --- a/src/components/Timeline.vue +++ b/src/components/Timeline.vue @@ -91,15 +91,18 @@ - diff --git a/src/main.js b/src/main.ts similarity index 87% rename from src/main.js rename to src/main.ts index 87bd84fa..d0a28b24 100644 --- a/src/main.js +++ b/src/main.ts @@ -19,12 +19,13 @@ * along with this program. If not, see . * */ +import 'reflect-metadata' import Vue from 'vue' import VueVirtualScroller from 'vue-virtual-scroller' import 'vue-virtual-scroller/dist/vue-virtual-scroller.css' import { translate as t, translatePlural as n } from '@nextcloud/l10n' -import App from './App' +import App from './App.vue' import router from './router' // Adding translations to the whole app @@ -42,11 +43,11 @@ Vue.use(VueVirtualScroller) // original scripts are loaded from // https://github.com/nextcloud/server/blob/5bf3d1bb384da56adbf205752be8f840aac3b0c5/lib/private/legacy/template.php#L120-L122 window.addEventListener('DOMContentLoaded', () => { - if (!window.OCA.Files) { - window.OCA.Files = {} + if (!globalThis.OCA.Files) { + globalThis.OCA.Files = {} } // register unused client for the sidebar to have access to its parser methods - Object.assign(window.OCA.Files, { App: { fileList: { filesClient: OC.Files.getClient() } } }, window.OCA.Files) + Object.assign(globalThis.OCA.Files, { App: { fileList: { filesClient: globalThis.OC.Files.getClient() } } }, globalThis.OCA.Files) }) export default new Vue({ diff --git a/src/mixins/UserConfig.js b/src/mixins/UserConfig.ts similarity index 100% rename from src/mixins/UserConfig.js rename to src/mixins/UserConfig.ts diff --git a/src/mixins/constants.js b/src/mixins/constants.ts similarity index 100% rename from src/mixins/constants.js rename to src/mixins/constants.ts diff --git a/src/router.js b/src/router.ts similarity index 92% rename from src/router.js rename to src/router.ts index 14820b22..2ab4c4fb 100644 --- a/src/router.js +++ b/src/router.ts @@ -21,10 +21,10 @@ */ import { generateUrl } from '@nextcloud/router' + import { translate as t, translatePlural as n } from '@nextcloud/l10n' import Router from 'vue-router' import Vue from 'vue' - - const Timeline = () => import('./components/Timeline') + import Timeline from './components/Timeline.vue'; Vue.use(Router) @@ -43,7 +43,7 @@ mode: 'history', // if index.php is in the url AND we got this far, then it's working: // let's keep using index.php in the url - base: generateUrl('/apps/memories', ''), + base: generateUrl('/apps/memories'), linkActiveClass: 'active', routes: [ { diff --git a/src/services/DavClient.js b/src/services/DavClient.ts similarity index 89% rename from src/services/DavClient.js rename to src/services/DavClient.ts index a31324c6..37577bcc 100644 --- a/src/services/DavClient.js +++ b/src/services/DavClient.ts @@ -27,8 +27,8 @@ // Monkey business import * as rq from 'webdav/dist/node/request'; - rq.prepareRequestOptionsOld = rq.prepareRequestOptions.bind(rq); - rq.prepareRequestOptions = (function(requestOptions, context, userOptions) { + (rq).prepareRequestOptionsOld = rq.prepareRequestOptions.bind(rq); + (rq).prepareRequestOptions = (function(requestOptions, context, userOptions) { requestOptions.method = userOptions.method || requestOptions.method; return this.prepareRequestOptionsOld(requestOptions, context, userOptions); }).bind(rq); diff --git a/src/services/DavRequests.js b/src/services/DavRequests.ts similarity index 79% rename from src/services/DavRequests.js rename to src/services/DavRequests.ts index a9e1034c..7cb60520 100644 --- a/src/services/DavRequests.js +++ b/src/services/DavRequests.ts @@ -2,6 +2,7 @@ import { getCurrentUser } from '@nextcloud/auth' import { generateUrl } from '@nextcloud/router' import { genFileInfo } from './FileUtils' import client from './DavClient'; +import { IFileInfo } from '../types'; const props = ` @@ -23,11 +24,11 @@ const IMAGE_MIME_TYPES = [ /** * Get file infos for list of files given Ids - * @param {number[]} fileIds list of file ids - * @returns {Promise} list of file infos + * @param fileIds list of file ids + * @returns list of file infos */ -export async function getFiles(fileIds) { - const prefixPath = `/files/${getCurrentUser().uid}`; +export async function getFiles(fileIds: number[]): Promise { + const prefixPath = `/files/${getCurrentUser()!.uid}`; // IMPORTANT: if this isn't there, then a blank // returns EVERYTHING on the server! @@ -79,20 +80,19 @@ export async function getFiles(fileIds) { responseType: 'text', }; - let response = await client.getDirectoryContents('', options); + let response: any = await client.getDirectoryContents('', options); return response.data - .map(data => genFileInfo(data)) - .map(data => Object.assign({}, data, { filename: data.filename.replace(prefixPath, '') })); + .map((data: any) => genFileInfo(data)) + .map((data: any) => Object.assign({}, data, { filename: data.filename.replace(prefixPath, '') })); } /** * Get file infos for files in folder path - * @param {string} folderPath Path to folder - * @param {number} limit Max number of files to return - * @returns {Promise} list of file infos + * @param folderPath Path to folder + * @param limit Max number of files to return */ -export async function getFolderPreviewFileIds(folderPath, limit) { - const prefixPath = `/files/${getCurrentUser().uid}`; +export async function getFolderPreviewFileIds(folderPath: string, limit: number): Promise { + const prefixPath = `/files/${getCurrentUser()!.uid}`; const filter = IMAGE_MIME_TYPES.map(mime => ` @@ -141,10 +141,10 @@ export async function getFolderPreviewFileIds(folderPath, limit) { responseType: 'text', }; - let response = await client.getDirectoryContents('', options); + let response:any = await client.getDirectoryContents('', options); return response.data - .map(data => genFileInfo(data)) - .map(data => Object.assign({}, data, { + .map((data: any) => genFileInfo(data)) + .map((data: any) => Object.assign({}, data, { filename: data.filename.replace(prefixPath, ''), etag: data.etag.replace(/"/g, ''), // remove quotes })); @@ -153,22 +153,21 @@ export async function getFolderPreviewFileIds(folderPath, limit) { /** * Delete a single file * - * @param {string} path path to the file - * @returns {Promise} + * @param path path to the file */ -export async function deleteFile(path) { - const prefixPath = `/files/${getCurrentUser().uid}`; +export async function deleteFile(path: string) { + const prefixPath = `/files/${getCurrentUser()!.uid}`; return await client.deleteFile(`${prefixPath}${path}`); } /** * Delete all files in a given list of Ids * - * @param {number[]} fileIds list of file ids - * @returns {Promise>} list of file ids that were deleted + * @param fileIds list of file ids + * @returns list of file ids that were deleted */ -export async function deleteFilesByIds(fileIds) { - const delIds = new Set(); +export async function deleteFilesByIds(fileIds: number[]) { + const delIds = new Set(); const fileIdsSet = new Set(fileIds); if (fileIds.length === 0) { @@ -176,7 +175,7 @@ export async function deleteFilesByIds(fileIds) { } // Get files data - let fileInfos = []; + let fileInfos: any[] = []; try { fileInfos = await getFiles(fileIds.filter(f => f)); } catch (e) { @@ -185,7 +184,7 @@ export async function deleteFilesByIds(fileIds) { } // Run all promises together - const promises = []; + const promises: Promise[] = []; // Delete each file for (const fileInfo of fileInfos) { @@ -212,10 +211,9 @@ export async function deleteFilesByIds(fileIds) { /** * Download a file * - * @param {string[]} fileNames - The file's names - * @returns {Promise} + * @param fileNames - The file's names */ - export async function downloadFiles(fileNames) { + export async function downloadFiles(fileNames: string[]): Promise { const randomToken = Math.random().toString(36).substring(2) const params = new URLSearchParams() @@ -224,7 +222,7 @@ export async function deleteFilesByIds(fileIds) { const downloadURL = generateUrl(`/apps/files/ajax/download.php?${params}`) - window.location = `${downloadURL}downloadStartSecret=${randomToken}` + window.location.href = `${downloadURL}downloadStartSecret=${randomToken}` return new Promise((resolve) => { const waitForCookieInterval = setInterval( @@ -246,10 +244,9 @@ export async function deleteFilesByIds(fileIds) { /** * Download the files given by the fileIds - * @param {number[]} fileIds - * @returns {Promise} + * @param fileIds list of file ids */ -export async function downloadFilesByIds(fileIds) { +export async function downloadFilesByIds(fileIds: number[]) { if (fileIds.length === 0) { return; } diff --git a/src/services/FileUtils.js b/src/services/FileUtils.ts similarity index 95% rename from src/services/FileUtils.js rename to src/services/FileUtils.ts index 78f783d2..e47e1da7 100644 --- a/src/services/FileUtils.js +++ b/src/services/FileUtils.ts @@ -94,8 +94,8 @@ // finally sort by name return asc - ? fileInfo1[key]?.toString()?.localeCompare(fileInfo2[key].toString(), OC.getLanguage()) || 1 - : -fileInfo1[key]?.toString()?.localeCompare(fileInfo2[key].toString(), OC.getLanguage()) || -1 + ? fileInfo1[key]?.toString()?.localeCompare(fileInfo2[key].toString(), globalThis.OC.getLanguage()) || 1 + : -fileInfo1[key]?.toString()?.localeCompare(fileInfo2[key].toString(), globalThis.OC.getLanguage()) || -1 } const genFileInfo = function(obj) { @@ -123,7 +123,7 @@ return fileInfo } - const getPreviewUrl = function(fileid, etag) { + const getPreviewUrl = function(fileid: number, etag: string): string { return generateUrl(`/core/preview?fileId=${fileid}&c=${etag}&x=250&y=250&forceIcon=0&a=0`); } diff --git a/src/services/NumberUtils.js b/src/services/NumberUtils.ts similarity index 94% rename from src/services/NumberUtils.js rename to src/services/NumberUtils.ts index 5d7e5386..56e90729 100644 --- a/src/services/NumberUtils.js +++ b/src/services/NumberUtils.ts @@ -20,7 +20,7 @@ * */ - const isNumber = function(num) { + const isNumber = function(num: any) { if (!num) { return false } diff --git a/src/services/Utils.js b/src/services/Utils.ts similarity index 66% rename from src/services/Utils.js rename to src/services/Utils.ts index 2dda9e94..fb677048 100644 --- a/src/services/Utils.js +++ b/src/services/Utils.ts @@ -1,10 +1,10 @@ /** Get JS date object from dayId */ -export function dayIdToDate(dayId){ - return new Date(Number(dayId)*86400*1000); +export function dayIdToDate(dayId: number){ + return new Date(dayId*86400*1000); } /** Get month name from number */ -export function getMonthName(date) { +export function getMonthName(date: Date) { const dateTimeFormat = new Intl.DateTimeFormat('en-US', { month: 'short', timeZone: 'UTC', diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 00000000..172ba03a --- /dev/null +++ b/src/types.ts @@ -0,0 +1,69 @@ +export type IFileInfo = { + fileid: number; + filename: string; + etag: string; +} + +export type IDay = { + /** Day ID */ + dayid: number; + /** Number of photos in this day */ + count: number; + /** Set of rows in the day */ + rows?: Set; + /** List of photos for this day */ + detail?: IPhoto[]; + /** WebDAV fileInfos, fetched before viewer open */ + fileInfos?: IFileInfo[]; + /** Original fileIds from fileInfos */ + origFileIds?: Set; +} + +export type IPhoto = { + /** Nextcloud ID of file */ + fileid: number; + /** Etag from server */ + etag?: string; + /** Bit flags */ + flag: number; + /** Reference to day object */ + d?: IDay; + /** Video flag from server */ + isvideo?: boolean; + /** Favorite flag from server */ + isfavorite?: boolean; +} + +export type IRow = { + /** Vue Recycler identifier */ + id?: number; + /** Day ID */ + dayId: number; + /** Refrence to day object */ + day: IDay; + /** Whether this is a head row */ + head?: boolean; + /** [Head only] Title of the header */ + name?: string; + /** Main list of photo items */ + photos?: IPhoto[]; + /** Height in px of the row */ + size?: number; + /** Count of placeholders to create */ + pct?: number; +} + +export type ITick = { + /** Day ID */ + dayId: number; + /** Top row at this */ + top: number; + /** Static distance from top (for headers) */ + topS: number; + /** Count row distance from top (dynamic) */ + topC: number; + /** Text if any (e.g. year) */ + text?: string | number; + /** Whether this tick should be shown */ + s?: boolean; +} \ No newline at end of file diff --git a/src/vue-shims.d.ts b/src/vue-shims.d.ts new file mode 100644 index 00000000..98c4f9e4 --- /dev/null +++ b/src/vue-shims.d.ts @@ -0,0 +1,10 @@ +declare module "*.vue" { + import Vue from "vue" + export default Vue +} + +declare module '*.svg' { + import Vue, {VueConstructor} from 'vue'; + const content: VueConstructor; + export default content; +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000..71d2d0b5 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "lib": ["dom", "es2017"], + "target": "ESNext", + "module": "es2015", + "moduleResolution": "node", + "sourceMap": true, + "allowSyntheticDefaultImports": true, + "experimentalDecorators": true, + "emitDecoratorMetadata": true, + "jsx": "preserve" + } +} \ No newline at end of file diff --git a/webpack.js b/webpack.js index e5daa927..77df5769 100644 --- a/webpack.js +++ b/webpack.js @@ -1,3 +1,19 @@ const webpackConfig = require('@nextcloud/webpack-vue-config') +const path = require('path') + +webpackConfig.module.rules.push({ + test: /\.ts?$/, + loader: 'ts-loader', + exclude: /node_modules/, + options: { + appendTsSuffixTo: [/\.vue$/], + }, +}); +webpackConfig.resolve.extensions.push('.ts'); +webpackConfig.resolve.alias = { + 'vue$': 'vue/dist/vue.esm.js', +} +webpackConfig.entry.main = path.resolve(path.join('src', 'main')); +delete webpackConfig.optimization.splitChunks; module.exports = webpackConfig