mirror of
https://github.com/sbondCo/Watcharr.git
synced 2026-08-07 07:14:44 +00:00
Replace axios with native Fetch API & some maintenance
This commit is contained in:
@@ -1 +1,3 @@
|
|||||||
engine-strict=true
|
engine-strict=true
|
||||||
|
ignore-scripts=true
|
||||||
|
min-release-age=14
|
||||||
|
|||||||
@@ -2,6 +2,20 @@
|
|||||||
|
|
||||||
These changes are awaiting release:
|
These changes are awaiting release:
|
||||||
|
|
||||||
|
## Changed
|
||||||
|
|
||||||
|
- HTTP Requests: Replace `axios` with `Fetch`.
|
||||||
|
|
||||||
|
## Fixed
|
||||||
|
|
||||||
|
- Login: Display error when request to get available auth providers fails.
|
||||||
|
- Removed some legacy code that still thought there was a `store.watchedList`.
|
||||||
|
|
||||||
|
## Maintenance
|
||||||
|
|
||||||
|
- Package.json: Use exact version for all packages.
|
||||||
|
- .npmrc: Enable `ignore-scripts` (still on npm 11) and set `min-release-age=14`.
|
||||||
|
|
||||||
# [4.1.1] - 2026-07-26T02:00:00Z
|
# [4.1.1] - 2026-07-26T02:00:00Z
|
||||||
|
|
||||||
## Fixed
|
## Fixed
|
||||||
|
|||||||
Generated
+62
-172
@@ -9,29 +9,28 @@
|
|||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
"license": "GPL-3.0-only",
|
"license": "GPL-3.0-only",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^1.9.0",
|
"blurhash": "2.0.5",
|
||||||
"blurhash": "^2.0.5",
|
"papaparse": "5.4.1"
|
||||||
"papaparse": "^5.4.1"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@sveltejs/adapter-node": "^5.2.12",
|
"@sveltejs/adapter-node": "5.2.12",
|
||||||
"@sveltejs/kit": "^2.21.0",
|
"@sveltejs/kit": "2.21.0",
|
||||||
"@types/papaparse": "^5.3.15",
|
"@types/papaparse": "5.3.15",
|
||||||
"@typescript-eslint/eslint-plugin": "^8.32.1",
|
"@typescript-eslint/eslint-plugin": "8.32.1",
|
||||||
"@typescript-eslint/parser": "^8.32.1",
|
"@typescript-eslint/parser": "8.32.1",
|
||||||
"@vite-pwa/sveltekit": "^0.6.6",
|
"@vite-pwa/sveltekit": "0.6.6",
|
||||||
"eslint": "^8.57.0",
|
"eslint": "8.57.0",
|
||||||
"eslint-config-prettier": "^10.1.2",
|
"eslint-config-prettier": "10.1.2",
|
||||||
"eslint-plugin-svelte": "^2.45.1",
|
"eslint-plugin-svelte": "2.45.1",
|
||||||
"prettier": "^3.4.2",
|
"prettier": "3.4.2",
|
||||||
"prettier-plugin-svelte": "^3.4.0",
|
"prettier-plugin-svelte": "3.4.0",
|
||||||
"sass": "^1.97.3",
|
"sass": "1.97.3",
|
||||||
"svelte": "^5.17.3",
|
"svelte": "5.17.3",
|
||||||
"svelte-check": "^4.1.3",
|
"svelte-check": "4.1.3",
|
||||||
"svelte-eslint-parser": "^0.42.0",
|
"svelte-eslint-parser": "0.42.0",
|
||||||
"svelte-preprocess": "^6.0.3",
|
"svelte-preprocess": "6.0.3",
|
||||||
"typescript": "^5.8.3",
|
"typescript": "5.8.3",
|
||||||
"vite": "^6.3.5"
|
"vite": "6.3.5"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@ampproject/remapping": {
|
"node_modules/@ampproject/remapping": {
|
||||||
@@ -2112,22 +2111,24 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@eslint/js": {
|
"node_modules/@eslint/js": {
|
||||||
"version": "8.57.1",
|
"version": "8.57.0",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz",
|
||||||
"integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==",
|
"integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@humanwhocodes/config-array": {
|
"node_modules/@humanwhocodes/config-array": {
|
||||||
"version": "0.13.0",
|
"version": "0.11.14",
|
||||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz",
|
||||||
"integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==",
|
"integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==",
|
||||||
"deprecated": "Use @eslint/config-array instead",
|
"deprecated": "Use @eslint/config-array instead",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@humanwhocodes/object-schema": "^2.0.3",
|
"@humanwhocodes/object-schema": "^2.0.2",
|
||||||
"debug": "^4.3.1",
|
"debug": "^4.3.1",
|
||||||
"minimatch": "^3.0.5"
|
"minimatch": "^3.0.5"
|
||||||
},
|
},
|
||||||
@@ -2136,20 +2137,22 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": {
|
"node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": {
|
||||||
"version": "1.1.11",
|
"version": "1.1.16",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.16.tgz",
|
||||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
"integrity": "sha512-IDw48K2/2kRkg9LdJxurvq3lV3aBgq0REY89duEqFRthjlPdXHKMj7EnQOXVckxzgisinf3nHfrcE2FufFLXMw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"balanced-match": "^1.0.0",
|
"balanced-match": "^1.0.0",
|
||||||
"concat-map": "0.0.1"
|
"concat-map": "0.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@humanwhocodes/config-array/node_modules/minimatch": {
|
"node_modules/@humanwhocodes/config-array/node_modules/minimatch": {
|
||||||
"version": "3.1.2",
|
"version": "3.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
|
||||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
"integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"brace-expansion": "^1.1.7"
|
"brace-expansion": "^1.1.7"
|
||||||
},
|
},
|
||||||
@@ -2175,7 +2178,8 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz",
|
||||||
"integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==",
|
"integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==",
|
||||||
"deprecated": "Use @eslint/object-schema instead",
|
"deprecated": "Use @eslint/object-schema instead",
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"license": "BSD-3-Clause"
|
||||||
},
|
},
|
||||||
"node_modules/@jridgewell/gen-mapping": {
|
"node_modules/@jridgewell/gen-mapping": {
|
||||||
"version": "0.3.8",
|
"version": "0.3.8",
|
||||||
@@ -3332,10 +3336,11 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/@vite-pwa/sveltekit": {
|
"node_modules/@vite-pwa/sveltekit": {
|
||||||
"version": "0.6.7",
|
"version": "0.6.6",
|
||||||
"resolved": "https://registry.npmjs.org/@vite-pwa/sveltekit/-/sveltekit-0.6.7.tgz",
|
"resolved": "https://registry.npmjs.org/@vite-pwa/sveltekit/-/sveltekit-0.6.6.tgz",
|
||||||
"integrity": "sha512-geeRgOiFr4RdW4JHIshOTsa8OqX4P+aJtudnKjuxzpmHy44bo4o18OWM1iXc4qXBJCxCw+3yTttyJsdmHXG/sA==",
|
"integrity": "sha512-f08xlcfZyaXgytl05hUtCLih7Vr8zOk/E4eE/UK71M+sEGk+y+vUyTuR8td8KQalpf1Begb8XkxAkV7iUj2a0g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"kolorist": "^1.8.0",
|
"kolorist": "^1.8.0",
|
||||||
"tinyglobby": "^0.2.9"
|
"tinyglobby": "^0.2.9"
|
||||||
@@ -3349,7 +3354,7 @@
|
|||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@sveltejs/kit": "^1.3.1 || ^2.0.1",
|
"@sveltejs/kit": "^1.3.1 || ^2.0.1",
|
||||||
"@vite-pwa/assets-generator": "^0.2.6",
|
"@vite-pwa/assets-generator": "^0.2.6",
|
||||||
"vite-plugin-pwa": ">=0.21.1 <1"
|
"vite-plugin-pwa": ">=0.20.5 <1"
|
||||||
},
|
},
|
||||||
"peerDependenciesMeta": {
|
"peerDependenciesMeta": {
|
||||||
"@vite-pwa/assets-generator": {
|
"@vite-pwa/assets-generator": {
|
||||||
@@ -3489,11 +3494,6 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"peer": true
|
"peer": true
|
||||||
},
|
},
|
||||||
"node_modules/asynckit": {
|
|
||||||
"version": "0.4.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
|
||||||
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
|
|
||||||
},
|
|
||||||
"node_modules/at-least-node": {
|
"node_modules/at-least-node": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
|
||||||
@@ -3520,17 +3520,6 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/axios": {
|
|
||||||
"version": "1.9.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.9.0.tgz",
|
|
||||||
"integrity": "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"follow-redirects": "^1.15.6",
|
|
||||||
"form-data": "^4.0.0",
|
|
||||||
"proxy-from-env": "^1.1.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/axobject-query": {
|
"node_modules/axobject-query": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
|
||||||
@@ -3802,17 +3791,6 @@
|
|||||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/combined-stream": {
|
|
||||||
"version": "1.0.8",
|
|
||||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
|
||||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
|
||||||
"dependencies": {
|
|
||||||
"delayed-stream": "~1.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 0.8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/commander": {
|
"node_modules/commander": {
|
||||||
"version": "2.20.3",
|
"version": "2.20.3",
|
||||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
||||||
@@ -4030,14 +4008,6 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/delayed-stream": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
|
||||||
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=0.4.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/detect-libc": {
|
"node_modules/detect-libc": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
|
||||||
@@ -4304,17 +4274,18 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint": {
|
"node_modules/eslint": {
|
||||||
"version": "8.57.1",
|
"version": "8.57.0",
|
||||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz",
|
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz",
|
||||||
"integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==",
|
"integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==",
|
||||||
"deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.",
|
"deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/eslint-utils": "^4.2.0",
|
"@eslint-community/eslint-utils": "^4.2.0",
|
||||||
"@eslint-community/regexpp": "^4.6.1",
|
"@eslint-community/regexpp": "^4.6.1",
|
||||||
"@eslint/eslintrc": "^2.1.4",
|
"@eslint/eslintrc": "^2.1.4",
|
||||||
"@eslint/js": "8.57.1",
|
"@eslint/js": "8.57.0",
|
||||||
"@humanwhocodes/config-array": "^0.13.0",
|
"@humanwhocodes/config-array": "^0.11.14",
|
||||||
"@humanwhocodes/module-importer": "^1.0.1",
|
"@humanwhocodes/module-importer": "^1.0.1",
|
||||||
"@nodelib/fs.walk": "^1.2.8",
|
"@nodelib/fs.walk": "^1.2.8",
|
||||||
"@ungap/structured-clone": "^1.2.0",
|
"@ungap/structured-clone": "^1.2.0",
|
||||||
@@ -4388,22 +4359,23 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint-plugin-svelte": {
|
"node_modules/eslint-plugin-svelte": {
|
||||||
"version": "2.46.1",
|
"version": "2.45.1",
|
||||||
"resolved": "https://registry.npmjs.org/eslint-plugin-svelte/-/eslint-plugin-svelte-2.46.1.tgz",
|
"resolved": "https://registry.npmjs.org/eslint-plugin-svelte/-/eslint-plugin-svelte-2.45.1.tgz",
|
||||||
"integrity": "sha512-7xYr2o4NID/f9OEYMqxsEQsCsj4KaMy4q5sANaKkAb6/QeCjYFxRmDm2S3YC3A3pl1kyPZ/syOx/i7LcWYSbIw==",
|
"integrity": "sha512-mYAKNDRji0YWl7o00KQi0enREcrtzcN7xwK/8lwk5uLRoKLjzPXc+WjngsYpPV35I3AF7UlXc1+JfyNMJS+njA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/eslint-utils": "^4.4.0",
|
"@eslint-community/eslint-utils": "^4.4.0",
|
||||||
"@jridgewell/sourcemap-codec": "^1.4.15",
|
"@jridgewell/sourcemap-codec": "^1.4.15",
|
||||||
"eslint-compat-utils": "^0.5.1",
|
"eslint-compat-utils": "^0.5.1",
|
||||||
"esutils": "^2.0.3",
|
"esutils": "^2.0.3",
|
||||||
"known-css-properties": "^0.35.0",
|
"known-css-properties": "^0.34.0",
|
||||||
"postcss": "^8.4.38",
|
"postcss": "^8.4.38",
|
||||||
"postcss-load-config": "^3.1.4",
|
"postcss-load-config": "^3.1.4",
|
||||||
"postcss-safe-parser": "^6.0.0",
|
"postcss-safe-parser": "^6.0.0",
|
||||||
"postcss-selector-parser": "^6.1.0",
|
"postcss-selector-parser": "^6.1.0",
|
||||||
"semver": "^7.6.2",
|
"semver": "^7.6.2",
|
||||||
"svelte-eslint-parser": "^0.43.0"
|
"svelte-eslint-parser": "^0.42.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^14.17.0 || >=16.0.0"
|
"node": "^14.17.0 || >=16.0.0"
|
||||||
@@ -4413,34 +4385,7 @@
|
|||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"eslint": "^7.0.0 || ^8.0.0-0 || ^9.0.0-0",
|
"eslint": "^7.0.0 || ^8.0.0-0 || ^9.0.0-0",
|
||||||
"svelte": "^3.37.0 || ^4.0.0 || ^5.0.0"
|
"svelte": "^3.37.0 || ^4.0.0 || ^5.0.0-next.191"
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"svelte": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/eslint-plugin-svelte/node_modules/svelte-eslint-parser": {
|
|
||||||
"version": "0.43.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/svelte-eslint-parser/-/svelte-eslint-parser-0.43.0.tgz",
|
|
||||||
"integrity": "sha512-GpU52uPKKcVnh8tKN5P4UZpJ/fUDndmq7wfsvoVXsyP+aY0anol7Yqo01fyrlaWGMFfm4av5DyrjlaXdLRJvGA==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"eslint-scope": "^7.2.2",
|
|
||||||
"eslint-visitor-keys": "^3.4.3",
|
|
||||||
"espree": "^9.6.1",
|
|
||||||
"postcss": "^8.4.39",
|
|
||||||
"postcss-scss": "^4.0.9"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/ota-meshi"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"svelte": "^3.37.0 || ^4.0.0 || ^5.0.0"
|
|
||||||
},
|
},
|
||||||
"peerDependenciesMeta": {
|
"peerDependenciesMeta": {
|
||||||
"svelte": {
|
"svelte": {
|
||||||
@@ -4738,25 +4683,6 @@
|
|||||||
"integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==",
|
"integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/follow-redirects": {
|
|
||||||
"version": "1.15.9",
|
|
||||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz",
|
|
||||||
"integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==",
|
|
||||||
"funding": [
|
|
||||||
{
|
|
||||||
"type": "individual",
|
|
||||||
"url": "https://github.com/sponsors/RubenVerborgh"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">=4.0"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"debug": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/for-each": {
|
"node_modules/for-each": {
|
||||||
"version": "0.3.3",
|
"version": "0.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
|
||||||
@@ -4767,19 +4693,6 @@
|
|||||||
"is-callable": "^1.1.3"
|
"is-callable": "^1.1.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/form-data": {
|
|
||||||
"version": "4.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz",
|
|
||||||
"integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==",
|
|
||||||
"dependencies": {
|
|
||||||
"asynckit": "^0.4.0",
|
|
||||||
"combined-stream": "^1.0.8",
|
|
||||||
"mime-types": "^2.1.12"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/fs-extra": {
|
"node_modules/fs-extra": {
|
||||||
"version": "9.1.0",
|
"version": "9.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
|
||||||
@@ -5809,10 +5722,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/known-css-properties": {
|
"node_modules/known-css-properties": {
|
||||||
"version": "0.35.0",
|
"version": "0.34.0",
|
||||||
"resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.35.0.tgz",
|
"resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.34.0.tgz",
|
||||||
"integrity": "sha512-a/RAk2BfKk+WFGhhOCAYqSiFLc34k8Mt/6NWRI4joER0EYUzXIcFivjjnoD3+XU1DggLn/tZc3DOAgke7l8a4A==",
|
"integrity": "sha512-tBECoUqNFbyAY4RrbqsBQqDFpGXAEbdD5QKr8kACx3+rnArmuuR22nKQWKazvp07N9yjTyDZaw/20UIH8tL9DQ==",
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/kolorist": {
|
"node_modules/kolorist": {
|
||||||
"version": "1.8.0",
|
"version": "1.8.0",
|
||||||
@@ -5963,25 +5877,6 @@
|
|||||||
"url": "https://github.com/sponsors/jonschlinkert"
|
"url": "https://github.com/sponsors/jonschlinkert"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/mime-db": {
|
|
||||||
"version": "1.52.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
|
||||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 0.6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/mime-types": {
|
|
||||||
"version": "2.1.35",
|
|
||||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
|
||||||
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
|
||||||
"dependencies": {
|
|
||||||
"mime-db": "1.52.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 0.6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/minimatch": {
|
"node_modules/minimatch": {
|
||||||
"version": "9.0.5",
|
"version": "9.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
|
||||||
@@ -6425,11 +6320,6 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/proxy-from-env": {
|
|
||||||
"version": "1.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
|
||||||
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
|
|
||||||
},
|
|
||||||
"node_modules/punycode": {
|
"node_modules/punycode": {
|
||||||
"version": "2.3.1",
|
"version": "2.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
||||||
|
|||||||
+20
-21
@@ -14,29 +14,28 @@
|
|||||||
"format": "prettier --write ."
|
"format": "prettier --write ."
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@sveltejs/adapter-node": "^5.2.12",
|
"@sveltejs/adapter-node": "5.2.12",
|
||||||
"@sveltejs/kit": "^2.21.0",
|
"@sveltejs/kit": "2.21.0",
|
||||||
"@types/papaparse": "^5.3.15",
|
"@types/papaparse": "5.3.15",
|
||||||
"@typescript-eslint/eslint-plugin": "^8.32.1",
|
"@typescript-eslint/eslint-plugin": "8.32.1",
|
||||||
"@typescript-eslint/parser": "^8.32.1",
|
"@typescript-eslint/parser": "8.32.1",
|
||||||
"@vite-pwa/sveltekit": "^0.6.6",
|
"@vite-pwa/sveltekit": "0.6.6",
|
||||||
"eslint": "^8.57.0",
|
"eslint": "8.57.0",
|
||||||
"eslint-config-prettier": "^10.1.2",
|
"eslint-config-prettier": "10.1.2",
|
||||||
"eslint-plugin-svelte": "^2.45.1",
|
"eslint-plugin-svelte": "2.45.1",
|
||||||
"prettier": "^3.4.2",
|
"prettier": "3.4.2",
|
||||||
"prettier-plugin-svelte": "^3.4.0",
|
"prettier-plugin-svelte": "3.4.0",
|
||||||
"sass": "^1.97.3",
|
"sass": "1.97.3",
|
||||||
"svelte": "^5.17.3",
|
"svelte": "5.17.3",
|
||||||
"svelte-check": "^4.1.3",
|
"svelte-check": "4.1.3",
|
||||||
"svelte-eslint-parser": "^0.42.0",
|
"svelte-eslint-parser": "0.42.0",
|
||||||
"svelte-preprocess": "^6.0.3",
|
"svelte-preprocess": "6.0.3",
|
||||||
"typescript": "^5.8.3",
|
"typescript": "5.8.3",
|
||||||
"vite": "^6.3.5"
|
"vite": "6.3.5"
|
||||||
},
|
},
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^1.9.0",
|
"blurhash": "2.0.5",
|
||||||
"blurhash": "^2.0.5",
|
"papaparse": "5.4.1"
|
||||||
"papaparse": "^5.4.1"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,14 +3,10 @@
|
|||||||
import Modal from "@/lib/Modal.svelte";
|
import Modal from "@/lib/Modal.svelte";
|
||||||
import Spinner from "@/lib/Spinner.svelte";
|
import Spinner from "@/lib/Spinner.svelte";
|
||||||
import { notify } from "@/lib/util/notify";
|
import { notify } from "@/lib/util/notify";
|
||||||
import {
|
import { JobStatus, type GetJobResponse } from "@/types";
|
||||||
JobStatus,
|
|
||||||
type GetJobResponse,
|
|
||||||
type JobCreatedResponse,
|
|
||||||
} from "@/types";
|
|
||||||
import axios from "axios";
|
|
||||||
import { onDestroy, onMount } from "svelte";
|
import { onDestroy, onMount } from "svelte";
|
||||||
import { store } from "@/store.svelte";
|
import { req } from "./util/api";
|
||||||
|
import { ReqerError } from "./util/fetch";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
modalTitle: string;
|
modalTitle: string;
|
||||||
@@ -46,7 +42,7 @@
|
|||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
console.error("startSync failed!", err);
|
console.error("startSync failed!", err);
|
||||||
step = "errored";
|
step = "errored";
|
||||||
jobFailError = err?.response ? err?.response?.data?.error : String(err);
|
jobFailError = ReqerError.getMsg(err, "Starting sync failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,13 +59,13 @@
|
|||||||
let seqfailedJobReqs = 0;
|
let seqfailedJobReqs = 0;
|
||||||
while (step === "job-running") {
|
while (step === "job-running") {
|
||||||
try {
|
try {
|
||||||
const r = await axios.get<GetJobResponse>(`/job/${jobId}`);
|
const r = await req.get<GetJobResponse>(`/job/${jobId}`);
|
||||||
console.log("jobWatcher: Got job data:", r.data);
|
console.log("jobWatcher: Got job data:", r);
|
||||||
latestJobStatus = r.data;
|
latestJobStatus = r;
|
||||||
currentTask = r.data?.currentTask;
|
currentTask = r?.currentTask;
|
||||||
if (r.data?.status === JobStatus.DONE) {
|
if (r?.status === JobStatus.DONE) {
|
||||||
step = "done";
|
step = "done";
|
||||||
} else if (r.data?.status === JobStatus.CANCELLED) {
|
} else if (r?.status === JobStatus.CANCELLED) {
|
||||||
step = "errored";
|
step = "errored";
|
||||||
}
|
}
|
||||||
// If we get here without erroring, we can reset it to 0.
|
// If we get here without erroring, we can reset it to 0.
|
||||||
@@ -94,31 +90,6 @@
|
|||||||
}
|
}
|
||||||
await new Promise((r) => setTimeout(r, 1000));
|
await new Promise((r) => setTimeout(r, 1000));
|
||||||
}
|
}
|
||||||
if (step !== "modal-closing") {
|
|
||||||
// Update our watched list
|
|
||||||
const nid = notify({
|
|
||||||
text: "Fetching updated watched list.",
|
|
||||||
type: "loading",
|
|
||||||
});
|
|
||||||
try {
|
|
||||||
const w = await axios.get("/watched");
|
|
||||||
if (w?.data?.length > 0) {
|
|
||||||
store.watchedList = w.data;
|
|
||||||
}
|
|
||||||
notify({
|
|
||||||
id: nid,
|
|
||||||
text: "Fetched updated watched list.",
|
|
||||||
type: "success",
|
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
console.error("jobWatcher: Getting updated watched list failed!", err);
|
|
||||||
notify({
|
|
||||||
id: nid,
|
|
||||||
text: "Getting updated watched list failed!",
|
|
||||||
type: "error",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function modalClose() {
|
function modalClose() {
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import axios from "axios";
|
|
||||||
import DropDown from "./DropDown.svelte";
|
import DropDown from "./DropDown.svelte";
|
||||||
import type { DropDownItem, TMDBRegions } from "@/types";
|
import type { DropDownItem, TMDBRegions } from "@/types";
|
||||||
import Error from "./Error.svelte";
|
import Error from "./Error.svelte";
|
||||||
|
import { req } from "./util/api";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
selectedCountry?: string;
|
selectedCountry?: string;
|
||||||
@@ -16,10 +16,10 @@
|
|||||||
onChange,
|
onChange,
|
||||||
}: Props = $props();
|
}: Props = $props();
|
||||||
|
|
||||||
let mappedCountries: DropDownItem[] = $state();
|
let mappedCountries: DropDownItem[] = $state([]);
|
||||||
|
|
||||||
async function getCountries() {
|
async function getCountries() {
|
||||||
const c = (await axios.get(`/content/regions`)).data as TMDBRegions;
|
const c = await req.get<TMDBRegions>(`/content/regions`);
|
||||||
mappedCountries = c.results
|
mappedCountries = c.results
|
||||||
.map((cc) => {
|
.map((cc) => {
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -2,11 +2,11 @@
|
|||||||
import type { ContentType, PublicUser, WatchedStatus } from "@/types";
|
import type { ContentType, PublicUser, WatchedStatus } from "@/types";
|
||||||
import HorizontalList from "../HorizontalList.svelte";
|
import HorizontalList from "../HorizontalList.svelte";
|
||||||
import Modal from "../Modal.svelte";
|
import Modal from "../Modal.svelte";
|
||||||
import axios from "axios";
|
|
||||||
import Spinner from "../Spinner.svelte";
|
import Spinner from "../Spinner.svelte";
|
||||||
import Error from "../Error.svelte";
|
import Error from "../Error.svelte";
|
||||||
import Icon from "../Icon.svelte";
|
import Icon from "../Icon.svelte";
|
||||||
import { watchedStatuses } from "../util/helpers";
|
import { watchedStatuses } from "../util/helpers";
|
||||||
|
import { req } from "../util/api";
|
||||||
|
|
||||||
interface FollowThoughts {
|
interface FollowThoughts {
|
||||||
followedUser: PublicUser;
|
followedUser: PublicUser;
|
||||||
@@ -26,11 +26,9 @@
|
|||||||
let modalShownFor: FollowThoughts | undefined = $state(undefined);
|
let modalShownFor: FollowThoughts | undefined = $state(undefined);
|
||||||
|
|
||||||
async function getFollowsThoughts() {
|
async function getFollowsThoughts() {
|
||||||
return (
|
return await req.get<FollowThoughts[]>(
|
||||||
await axios.get<FollowThoughts[]>(
|
`/follow/thoughts/${mediaType}/${mediaId}`,
|
||||||
`/follow/thoughts/${mediaType}/${mediaId}`,
|
);
|
||||||
)
|
|
||||||
).data;
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { onMount } from "svelte";
|
import { onMount } from "svelte";
|
||||||
import Modal from "../Modal.svelte";
|
import Modal from "../Modal.svelte";
|
||||||
import axios from "axios";
|
|
||||||
import type { TrustedHeaderAuthLogoutDetailsResponse } from "@/types";
|
import type { TrustedHeaderAuthLogoutDetailsResponse } from "@/types";
|
||||||
import Spinner from "../Spinner.svelte";
|
import Spinner from "../Spinner.svelte";
|
||||||
import { clearWatcharrData } from ".";
|
import { clearWatcharrData } from ".";
|
||||||
import { goto } from "$app/navigation";
|
import { goto } from "$app/navigation";
|
||||||
|
import { req } from "../util/api";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
@@ -18,10 +18,10 @@
|
|||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
try {
|
try {
|
||||||
const r = await axios.get<TrustedHeaderAuthLogoutDetailsResponse>(
|
const r = await req.get<TrustedHeaderAuthLogoutDetailsResponse>(
|
||||||
"/auth/proxy_logout_details",
|
"/auth/proxy_logout_details",
|
||||||
);
|
);
|
||||||
logoutUrl = r?.data?.logoutUrl;
|
logoutUrl = r?.logoutUrl;
|
||||||
if (!logoutUrl?.toLowerCase()?.startsWith("http")) {
|
if (!logoutUrl?.toLowerCase()?.startsWith("http")) {
|
||||||
// If no protocol in logoutUrl, set https
|
// If no protocol in logoutUrl, set https
|
||||||
logoutUrl = `https://${logoutUrl}`;
|
logoutUrl = `https://${logoutUrl}`;
|
||||||
|
|||||||
@@ -6,12 +6,13 @@
|
|||||||
ArrRequestStatus,
|
ArrRequestStatus,
|
||||||
ContentType,
|
ContentType,
|
||||||
} from "@/types";
|
} from "@/types";
|
||||||
import axios from "axios";
|
|
||||||
import { onMount } from "svelte";
|
import { onMount } from "svelte";
|
||||||
import Icon from "../Icon.svelte";
|
import Icon from "../Icon.svelte";
|
||||||
import tooltip from "../actions/tooltip";
|
import tooltip from "../actions/tooltip";
|
||||||
import { msToAmountsOfTime } from "../util/helpers";
|
import { msToAmountsOfTime } from "../util/helpers";
|
||||||
import { notify } from "../util/notify";
|
import { notify } from "../util/notify";
|
||||||
|
import { req } from "../util/api";
|
||||||
|
import { ReqerError } from "../util/fetch";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
type: ContentType;
|
type: ContentType;
|
||||||
@@ -48,11 +49,11 @@
|
|||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const resp = await axios.get<ArrInfoResponse>(
|
const resp = await req.get<ArrInfoResponse>(
|
||||||
`/arr/${type === "movie" ? "rad" : "son"}/info/${existingRequest.id}`,
|
`/arr/${type === "movie" ? "rad" : "son"}/info/${existingRequest.id}`,
|
||||||
);
|
);
|
||||||
if (resp?.data) {
|
if (resp) {
|
||||||
info = resp.data;
|
info = resp;
|
||||||
if (info.hasFile) {
|
if (info.hasFile) {
|
||||||
status = "available";
|
status = "available";
|
||||||
} else {
|
} else {
|
||||||
@@ -61,8 +62,9 @@
|
|||||||
}
|
}
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
if (
|
if (
|
||||||
err?.response?.status === 404 &&
|
ReqerError.withBody(err) &&
|
||||||
err?.response?.data?.error === "request deleted"
|
err.response?.status === 404 &&
|
||||||
|
err.body.error === "request deleted"
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -80,13 +82,13 @@
|
|||||||
console.warn("getStatus called before existingRequest exists.");
|
console.warn("getStatus called before existingRequest exists.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const statusResp = await axios.get<ArrDetailsResponse>(
|
const statusResp = await req.getWhole<ArrDetailsResponse>(
|
||||||
`/arr/${type === "movie" ? "rad" : "son"}/status/${existingRequest.serverName}/${existingRequest.arrId}`,
|
`/arr/${type === "movie" ? "rad" : "son"}/status/${existingRequest.serverName}/${existingRequest.arrId}`,
|
||||||
);
|
);
|
||||||
if (statusResp.status === 204) {
|
if (statusResp.status === 204) {
|
||||||
status = "requested";
|
status = "requested";
|
||||||
} else if (statusResp?.data) {
|
} else if (statusResp.body) {
|
||||||
status = statusResp.data;
|
status = statusResp.body;
|
||||||
const estMs =
|
const estMs =
|
||||||
new Date(status.estimatedCompletionTime).getTime() -
|
new Date(status.estimatedCompletionTime).getTime() -
|
||||||
new Date(Date.now()).getTime();
|
new Date(Date.now()).getTime();
|
||||||
@@ -119,19 +121,19 @@
|
|||||||
|
|
||||||
async function lookForExisting() {
|
async function lookForExisting() {
|
||||||
try {
|
try {
|
||||||
const existingRequestResp = await axios.get<ArrRequestResponse>(
|
const existingRequestResp = await req.get<ArrRequestResponse>(
|
||||||
`/arr/${type === "movie" ? "rad" : "son"}/request/${tmdbId}`,
|
`/arr/${type === "movie" ? "rad" : "son"}/request/${tmdbId}`,
|
||||||
);
|
);
|
||||||
if (existingRequestResp?.data && existingRequestResp?.data?.arrId) {
|
if (existingRequestResp && existingRequestResp.arrId) {
|
||||||
existingRequest = existingRequestResp?.data;
|
existingRequest = existingRequestResp;
|
||||||
getInfo();
|
getInfo();
|
||||||
} else if (existingRequestResp?.data) {
|
} else if (existingRequestResp) {
|
||||||
// If no arrId, use status in request (pending, denied, etc)
|
// If no arrId, use status in request (pending, denied, etc)
|
||||||
console.log(
|
console.log(
|
||||||
"No arrId in request resp.. using request status for btn status if set.",
|
"No arrId in request resp.. using request status for btn status if set.",
|
||||||
);
|
);
|
||||||
if (existingRequestResp?.data?.status) {
|
if (existingRequestResp.status) {
|
||||||
status = existingRequestResp?.data?.status;
|
status = existingRequestResp.status;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import axios from "axios";
|
|
||||||
import Modal from "../Modal.svelte";
|
import Modal from "../Modal.svelte";
|
||||||
import type {
|
import type {
|
||||||
ArrRequestResponse,
|
ArrRequestResponse,
|
||||||
@@ -11,6 +10,7 @@
|
|||||||
import DropDown from "../DropDown.svelte";
|
import DropDown from "../DropDown.svelte";
|
||||||
import Setting from "../settings/Setting.svelte";
|
import Setting from "../settings/Setting.svelte";
|
||||||
import Spinner from "../Spinner.svelte";
|
import Spinner from "../Spinner.svelte";
|
||||||
|
import { req } from "../util/api";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
content: Media;
|
content: Media;
|
||||||
@@ -35,9 +35,9 @@
|
|||||||
async function getServers() {
|
async function getServers() {
|
||||||
try {
|
try {
|
||||||
inputsDisabled = true;
|
inputsDisabled = true;
|
||||||
const r = await axios.get("/arr/rad");
|
const r = await req.get<RadarrSettingsPublicResponseResult[]>("/arr/rad");
|
||||||
if (r.data?.length > 0) {
|
if (r?.length > 0) {
|
||||||
servarrs = r.data;
|
servarrs = r;
|
||||||
selectedServarrIndex = 0;
|
selectedServarrIndex = 0;
|
||||||
} else {
|
} else {
|
||||||
notify({ text: "No servers found", type: "error" });
|
notify({ text: "No servers found", type: "error" });
|
||||||
@@ -53,8 +53,8 @@
|
|||||||
async function getConfig(name: string) {
|
async function getConfig(name: string) {
|
||||||
try {
|
try {
|
||||||
inputsDisabled = true;
|
inputsDisabled = true;
|
||||||
const r = await axios.get<RadarrTestResponse>(`/arr/rad/config/${name}`);
|
const r = await req.get<RadarrTestResponse>(`/arr/rad/config/${name}`);
|
||||||
selectedServerCfg = r.data;
|
selectedServerCfg = r;
|
||||||
inputsDisabled = false;
|
inputsDisabled = false;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("Failed to get config!", err);
|
console.error("Failed to get config!", err);
|
||||||
@@ -89,7 +89,7 @@
|
|||||||
notify({ id: nid, text: "No Root Folder Found", type: "error" });
|
notify({ id: nid, text: "No Root Folder Found", type: "error" });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const resp = await axios.post<ArrRequestResponse>(
|
const resp = await req.post<ArrRequestResponse>(
|
||||||
`/arr/rad/request${approveMode && originalRequest ? `/approve/${originalRequest.id}` : ""}`,
|
`/arr/rad/request${approveMode && originalRequest ? `/approve/${originalRequest.id}` : ""}`,
|
||||||
{
|
{
|
||||||
serverName: server.name,
|
serverName: server.name,
|
||||||
@@ -103,9 +103,9 @@
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
addRequestRunning = false;
|
addRequestRunning = false;
|
||||||
if (resp.data) {
|
if (resp) {
|
||||||
notify({ id: nid, text: "Request complete", type: "success" });
|
notify({ id: nid, text: "Request complete", type: "success" });
|
||||||
onClose(resp.data);
|
onClose(resp);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("content request failed!", err);
|
console.error("content request failed!", err);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import axios from "axios";
|
import { req } from "../util/api";
|
||||||
import Modal from "../Modal.svelte";
|
import Modal from "../Modal.svelte";
|
||||||
import type {
|
import type {
|
||||||
ArrRequestResponse,
|
ArrRequestResponse,
|
||||||
@@ -51,9 +51,9 @@
|
|||||||
async function getServers() {
|
async function getServers() {
|
||||||
try {
|
try {
|
||||||
inputsDisabled = true;
|
inputsDisabled = true;
|
||||||
const r = await axios.get("/arr/son");
|
const r = await req.get<SonarrSettingsPublicResponseResult[]>("/arr/son");
|
||||||
if (r.data?.length > 0) {
|
if (r.length > 0) {
|
||||||
servarrs = r.data;
|
servarrs = r;
|
||||||
selectedServarrIndex = 0;
|
selectedServarrIndex = 0;
|
||||||
} else {
|
} else {
|
||||||
notify({ text: "No servers found", type: "error" });
|
notify({ text: "No servers found", type: "error" });
|
||||||
@@ -69,8 +69,8 @@
|
|||||||
async function getConfig(name: string) {
|
async function getConfig(name: string) {
|
||||||
try {
|
try {
|
||||||
inputsDisabled = true;
|
inputsDisabled = true;
|
||||||
const r = await axios.get<SonarrTestResponse>(`/arr/son/config/${name}`);
|
const r = await req.get<SonarrTestResponse>(`/arr/son/config/${name}`);
|
||||||
selectedServerCfg = r.data;
|
selectedServerCfg = r;
|
||||||
inputsDisabled = false;
|
inputsDisabled = false;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("Failed to get config!", err);
|
console.error("Failed to get config!", err);
|
||||||
@@ -105,7 +105,7 @@
|
|||||||
notify({ id: nid, text: "No Root Folder Found", type: "error" });
|
notify({ id: nid, text: "No Root Folder Found", type: "error" });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const resp = await axios.post(
|
const resp = await req.post<ArrRequestResponse>(
|
||||||
`/arr/son/request${approveMode && originalRequest ? `/approve/${originalRequest.id}` : ""}`,
|
`/arr/son/request${approveMode && originalRequest ? `/approve/${originalRequest.id}` : ""}`,
|
||||||
{
|
{
|
||||||
serverName: server.name,
|
serverName: server.name,
|
||||||
@@ -128,9 +128,9 @@
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
addRequestRunning = false;
|
addRequestRunning = false;
|
||||||
if (resp?.data) {
|
if (resp) {
|
||||||
notify({ id: nid, text: "Request complete", type: "success" });
|
notify({ id: nid, text: "Request complete", type: "success" });
|
||||||
onClose(resp.data);
|
onClose(resp);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("content request failed!", err);
|
console.error("content request failed!", err);
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
WatchedSeason,
|
WatchedSeason,
|
||||||
WatchedStatus,
|
WatchedStatus,
|
||||||
} from "@/types";
|
} from "@/types";
|
||||||
import axios from "axios";
|
import { req } from "../util/api";
|
||||||
import Spinner from "@/lib/Spinner.svelte";
|
import Spinner from "@/lib/Spinner.svelte";
|
||||||
import Error from "@/lib/Error.svelte";
|
import Error from "@/lib/Error.svelte";
|
||||||
import SeasonsListEpisode from "./SeasonsListEpisode.svelte";
|
import SeasonsListEpisode from "./SeasonsListEpisode.svelte";
|
||||||
@@ -45,15 +45,18 @@
|
|||||||
async function sdr(seasonNum: number) {
|
async function sdr(seasonNum: number) {
|
||||||
const wid = watchedItem?.id;
|
const wid = watchedItem?.id;
|
||||||
console.debug("SeasonList: sdr: Called.", tvId, seasonNum, wid);
|
console.debug("SeasonList: sdr: Called.", tvId, seasonNum, wid);
|
||||||
const resp = await axios.get(`/content/tv/${tvId}/season/${seasonNum}`, {
|
const resp = await req.getWhole<TMDBSeasonDetails>(
|
||||||
params: {
|
`/content/tv/${tvId}/season/${seasonNum}`,
|
||||||
watchedId: wid,
|
{
|
||||||
|
params: {
|
||||||
|
watchedId: wid,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
);
|
||||||
try {
|
try {
|
||||||
if (wid) {
|
if (wid) {
|
||||||
// If we sent a watched id, expect a 'watcharr-lastviewedseason-saved' header in the response.
|
// If we sent a watched id, expect a 'watcharr-lastviewedseason-saved' header in the response.
|
||||||
const hVal = resp.headers["watcharr-lastviewedseason-saved"];
|
const hVal = resp.headers.get("watcharr-lastviewedseason-saved");
|
||||||
if (hVal) {
|
if (hVal) {
|
||||||
lastViewedSeasonChanged(wid, seasonNum);
|
lastViewedSeasonChanged(wid, seasonNum);
|
||||||
} else {
|
} else {
|
||||||
@@ -72,7 +75,7 @@
|
|||||||
err,
|
err,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return resp.data as TMDBSeasonDetails;
|
return resp.body;
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleStatusClick(
|
function handleStatusClick(
|
||||||
|
|||||||
+18
-17
@@ -1,6 +1,7 @@
|
|||||||
import axios from "axios";
|
import { req } from "../util/api";
|
||||||
import { notify } from "../util/notify";
|
import { notify } from "../util/notify";
|
||||||
import type {
|
import type {
|
||||||
|
Activity,
|
||||||
Watched,
|
Watched,
|
||||||
WatchedEpisodeAddResponse,
|
WatchedEpisodeAddResponse,
|
||||||
WatchedSeasonAddResponse,
|
WatchedSeasonAddResponse,
|
||||||
@@ -28,17 +29,17 @@ export async function updateWatchedSeason(
|
|||||||
}
|
}
|
||||||
const nid = notify({ text: `Saving`, type: "loading" });
|
const nid = notify({ text: `Saving`, type: "loading" });
|
||||||
try {
|
try {
|
||||||
const r = await axios.post<WatchedSeasonAddResponse>(`/watched/season`, {
|
const r = await req.post<WatchedSeasonAddResponse>(`/watched/season`, {
|
||||||
watchedId: watchedItem.id,
|
watchedId: watchedItem.id,
|
||||||
seasonNumber: seasonNumber,
|
seasonNumber: seasonNumber,
|
||||||
status: opts.status,
|
status: opts.status,
|
||||||
rating: opts.rating,
|
rating: opts.rating,
|
||||||
});
|
});
|
||||||
watchedItem.watchedSeasons = r.data.watchedSeasons;
|
watchedItem.watchedSeasons = r.watchedSeasons;
|
||||||
if (watchedItem.activity && watchedItem.activity?.length > 0) {
|
if (watchedItem.activity && watchedItem.activity?.length > 0) {
|
||||||
watchedItem.activity.push(r.data.addedActivity);
|
watchedItem.activity.push(r.addedActivity);
|
||||||
} else {
|
} else {
|
||||||
watchedItem.activity = [r.data.addedActivity];
|
watchedItem.activity = [r.addedActivity];
|
||||||
}
|
}
|
||||||
notify({ id: nid, text: `Saved!`, type: "success" });
|
notify({ id: nid, text: `Saved!`, type: "success" });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -50,15 +51,15 @@ export async function updateWatchedSeason(
|
|||||||
export async function removeWatchedSeason(watchedItem: Watched, id: number) {
|
export async function removeWatchedSeason(watchedItem: Watched, id: number) {
|
||||||
const nid = notify({ text: `Removing`, type: "loading" });
|
const nid = notify({ text: `Removing`, type: "loading" });
|
||||||
try {
|
try {
|
||||||
const r = await axios.delete(`/watched/season/${id}`);
|
const r = await req.delete<Activity>(`/watched/season/${id}`);
|
||||||
watchedItem.watchedSeasons = watchedItem.watchedSeasons?.filter(
|
watchedItem.watchedSeasons = watchedItem.watchedSeasons?.filter(
|
||||||
(s) => s.id !== id,
|
(s) => s.id !== id,
|
||||||
);
|
);
|
||||||
if (r.data) {
|
if (r) {
|
||||||
if (watchedItem.activity && watchedItem.activity?.length > 0) {
|
if (watchedItem.activity && watchedItem.activity?.length > 0) {
|
||||||
watchedItem.activity.push(r.data);
|
watchedItem.activity.push(r);
|
||||||
} else {
|
} else {
|
||||||
watchedItem.activity = [r.data];
|
watchedItem.activity = [r];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
notify({ id: nid, text: `Removed!`, type: "success" });
|
notify({ id: nid, text: `Removed!`, type: "success" });
|
||||||
@@ -80,21 +81,21 @@ export async function updateWatchedEpisode(
|
|||||||
}
|
}
|
||||||
const nid = notify({ text: `Saving`, type: "loading" });
|
const nid = notify({ text: `Saving`, type: "loading" });
|
||||||
try {
|
try {
|
||||||
const r = await axios.post<WatchedEpisodeAddResponse>(`/watched/episode`, {
|
const r = await req.post<WatchedEpisodeAddResponse>(`/watched/episode`, {
|
||||||
watchedId: watchedItem.id,
|
watchedId: watchedItem.id,
|
||||||
seasonNumber,
|
seasonNumber,
|
||||||
episodeNumber,
|
episodeNumber,
|
||||||
status: opts.status,
|
status: opts.status,
|
||||||
rating: opts.rating,
|
rating: opts.rating,
|
||||||
});
|
});
|
||||||
watchedItem.watchedEpisodes = r.data.watchedEpisodes;
|
watchedItem.watchedEpisodes = r.watchedEpisodes;
|
||||||
if (watchedItem.activity && watchedItem.activity?.length > 0) {
|
if (watchedItem.activity && watchedItem.activity?.length > 0) {
|
||||||
watchedItem.activity.push(r.data.addedActivity);
|
watchedItem.activity.push(r.addedActivity);
|
||||||
} else {
|
} else {
|
||||||
watchedItem.activity = [r.data.addedActivity];
|
watchedItem.activity = [r.addedActivity];
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const epHookResp = r?.data?.episodeStatusChangedHookResponse;
|
const epHookResp = r?.episodeStatusChangedHookResponse;
|
||||||
if (epHookResp && Object.keys(epHookResp).length > 0) {
|
if (epHookResp && Object.keys(epHookResp).length > 0) {
|
||||||
if (epHookResp.errors && epHookResp.errors.length > 0) {
|
if (epHookResp.errors && epHookResp.errors.length > 0) {
|
||||||
console.error(
|
console.error(
|
||||||
@@ -148,15 +149,15 @@ export async function updateWatchedEpisode(
|
|||||||
export async function removeWatchedEpisode(watchedItem: Watched, id: number) {
|
export async function removeWatchedEpisode(watchedItem: Watched, id: number) {
|
||||||
const nid = notify({ text: `Removing`, type: "loading" });
|
const nid = notify({ text: `Removing`, type: "loading" });
|
||||||
try {
|
try {
|
||||||
const r = await axios.delete(`/watched/episode/${id}`);
|
const r = await req.delete<Activity>(`/watched/episode/${id}`);
|
||||||
watchedItem.watchedEpisodes = watchedItem.watchedEpisodes?.filter(
|
watchedItem.watchedEpisodes = watchedItem.watchedEpisodes?.filter(
|
||||||
(s) => s.id !== id,
|
(s) => s.id !== id,
|
||||||
);
|
);
|
||||||
if (r.data) {
|
if (r.data) {
|
||||||
if (watchedItem.activity && watchedItem.activity?.length > 0) {
|
if (watchedItem.activity && watchedItem.activity?.length > 0) {
|
||||||
watchedItem.activity.push(r.data);
|
watchedItem.activity.push(r);
|
||||||
} else {
|
} else {
|
||||||
watchedItem.activity = [r.data];
|
watchedItem.activity = [r];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
notify({ id: nid, text: `Removed!`, type: "success" });
|
notify({ id: nid, text: `Removed!`, type: "success" });
|
||||||
|
|||||||
@@ -5,9 +5,8 @@
|
|||||||
import SettingsList from "../settings/SettingsList.svelte";
|
import SettingsList from "../settings/SettingsList.svelte";
|
||||||
import ColorSelector from "../ColorSelector.svelte";
|
import ColorSelector from "../ColorSelector.svelte";
|
||||||
import { notify } from "../util/notify";
|
import { notify } from "../util/notify";
|
||||||
import axios from "axios";
|
import { req } from "../util/api";
|
||||||
import type { Tag, TagAddRequest } from "@/types";
|
import type { Tag, TagAddRequest } from "@/types";
|
||||||
import { get } from "svelte/store";
|
|
||||||
import { onMount } from "svelte";
|
import { onMount } from "svelte";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@@ -54,15 +53,13 @@
|
|||||||
}
|
}
|
||||||
const nid = notify({ text: "Creating Tag", type: "loading" });
|
const nid = notify({ text: "Creating Tag", type: "loading" });
|
||||||
try {
|
try {
|
||||||
const resp = await axios.post<Tag>("/tag", {
|
const resp = await req.post<Tag>("/tag", {
|
||||||
name: tagName,
|
name: tagName,
|
||||||
color: textColor,
|
color: textColor,
|
||||||
bgColor,
|
bgColor,
|
||||||
} as TagAddRequest);
|
} as TagAddRequest);
|
||||||
console.log("addTag: Tag was created", resp.data);
|
console.log("addTag: Tag was created", resp);
|
||||||
// const _tags = get(tags);
|
store.tags.push(resp);
|
||||||
store.tags.push(resp.data);
|
|
||||||
// tags.update((t) => t);
|
|
||||||
notify({ id: nid, text: "Tag Created!", type: "success" });
|
notify({ id: nid, text: "Tag Created!", type: "success" });
|
||||||
onClose();
|
onClose();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -80,17 +77,16 @@
|
|||||||
}
|
}
|
||||||
const nid = notify({ text: "Modifying Tag", type: "loading" });
|
const nid = notify({ text: "Modifying Tag", type: "loading" });
|
||||||
try {
|
try {
|
||||||
const resp = await axios.put<Tag>(`/tag/${existingTag!.id}`, {
|
const resp = await req.put<Tag>(`/tag/${existingTag!.id}`, {
|
||||||
name: tagName,
|
name: tagName,
|
||||||
color: textColor,
|
color: textColor,
|
||||||
bgColor,
|
bgColor,
|
||||||
} as TagAddRequest);
|
} as TagAddRequest);
|
||||||
console.log("updateTag: Tag was edited", resp.data);
|
console.log("updateTag: Tag was edited", resp);
|
||||||
existingTag!.name = tagName;
|
existingTag!.name = tagName;
|
||||||
existingTag!.color = textColor;
|
existingTag!.color = textColor;
|
||||||
existingTag!.bgColor = bgColor;
|
existingTag!.bgColor = bgColor;
|
||||||
// Doesn't update `updatedAt`... may need to in the future if we need to sort by it, etc
|
// Doesn't update `updatedAt`... may need to in the future if we need to sort by it, etc
|
||||||
// tags.update((t) => t);
|
|
||||||
notify({ id: nid, text: "Tag Modified!", type: "success" });
|
notify({ id: nid, text: "Tag Modified!", type: "success" });
|
||||||
onClose();
|
onClose();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|||||||
@@ -1,15 +1,11 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { store } from "@/store.svelte";
|
import { store } from "@/store.svelte";
|
||||||
import Modal from "../Modal.svelte";
|
import Modal from "../Modal.svelte";
|
||||||
import Setting from "../settings/Setting.svelte";
|
|
||||||
import SettingsList from "../settings/SettingsList.svelte";
|
|
||||||
import ColorSelector from "../ColorSelector.svelte";
|
|
||||||
import { notify } from "../util/notify";
|
import { notify } from "../util/notify";
|
||||||
import axios from "axios";
|
import type { Tag as TagT } from "@/types";
|
||||||
import type { Tag as TagT, TagAddRequest } from "@/types";
|
|
||||||
import { get } from "svelte/store";
|
|
||||||
import Tag from "./Tag.svelte";
|
import Tag from "./Tag.svelte";
|
||||||
import { onMount } from "svelte";
|
import { onMount } from "svelte";
|
||||||
|
import { req } from "../util/api";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
tag: TagT;
|
tag: TagT;
|
||||||
@@ -30,28 +26,10 @@
|
|||||||
deleteDisabled = true;
|
deleteDisabled = true;
|
||||||
const nid = notify({ text: "Deleting Tag", type: "loading" });
|
const nid = notify({ text: "Deleting Tag", type: "loading" });
|
||||||
try {
|
try {
|
||||||
const resp = await axios.delete(`/tag/${tag.id}`);
|
const resp = await req.delete(`/tag/${tag.id}`);
|
||||||
console.log("deleteTag: Tag was deleted", resp.data);
|
console.log("deleteTag: Tag was deleted", resp);
|
||||||
// 1. Remove tag from store.
|
// Remove tag from store.
|
||||||
// const _tags = get(tags);
|
|
||||||
// store.tags.update((t) => t);
|
|
||||||
store.tags = store.tags.filter((t) => t.id !== tag.id);
|
store.tags = store.tags.filter((t) => t.id !== tag.id);
|
||||||
// tags.update(() => newList);
|
|
||||||
// 2. Remove tag from all watched entries in store.
|
|
||||||
try {
|
|
||||||
for (let i = 0; i < store.watchedList.length; i++) {
|
|
||||||
const wi = store.watchedList[i];
|
|
||||||
if (wi.tags && wi.tags.length > 0) {
|
|
||||||
wi.tags = wi.tags.filter((t) => t.id !== tag.id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// watchedList.update(() => wList);
|
|
||||||
} catch (err) {
|
|
||||||
console.error(
|
|
||||||
"deleteTag: Failed to remove tags from watched entries:",
|
|
||||||
err,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
notify({ id: nid, text: "Tag Deleted!", type: "success" });
|
notify({ id: nid, text: "Tag Deleted!", type: "success" });
|
||||||
onClose();
|
onClose();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -63,7 +41,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
// Sort of prevent accidental clickage, wait 3s after opening modal before enabling delete btn.
|
// Sort of prevent accidental clickage, wait 3s after opening modal
|
||||||
|
// before enabling delete btn.
|
||||||
deleteDisabled = true;
|
deleteDisabled = true;
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
deleteDisabled = false;
|
deleteDisabled = false;
|
||||||
|
|||||||
+5
-5
@@ -1,4 +1,4 @@
|
|||||||
import axios from "axios";
|
import { req } from "../util/api";
|
||||||
import { notify } from "../util/notify";
|
import { notify } from "../util/notify";
|
||||||
import type { Tag } from "@/types";
|
import type { Tag } from "@/types";
|
||||||
|
|
||||||
@@ -15,10 +15,10 @@ export async function tagWatched(
|
|||||||
});
|
});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return await axios
|
return await req
|
||||||
.post(`/watched/${watchedId}/tag/${tag.id}`)
|
.post(`/watched/${watchedId}/tag/${tag.id}`)
|
||||||
.then((resp) => {
|
.then((resp) => {
|
||||||
console.log("tagWatched: Status:", resp.status);
|
console.log("tagWatched: Success.", resp);
|
||||||
notify({ id: nid, text: `Tagged!`, type: "success" });
|
notify({ id: nid, text: `Tagged!`, type: "success" });
|
||||||
return true;
|
return true;
|
||||||
})
|
})
|
||||||
@@ -42,10 +42,10 @@ export async function untagWatched(
|
|||||||
});
|
});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return await axios
|
return await req
|
||||||
.delete(`/watched/${watchedId}/tag/${tag.id}`)
|
.delete(`/watched/${watchedId}/tag/${tag.id}`)
|
||||||
.then((resp) => {
|
.then((resp) => {
|
||||||
console.log("untagWatched: Status:", resp.status);
|
console.log("untagWatched: Success.", resp);
|
||||||
notify({ id: nid, text: `Untagged!`, type: "success" });
|
notify({ id: nid, text: `Untagged!`, type: "success" });
|
||||||
return true;
|
return true;
|
||||||
})
|
})
|
||||||
|
|||||||
+44
-51
@@ -13,8 +13,9 @@ import {
|
|||||||
type ActivityUpdateRequest,
|
type ActivityUpdateRequest,
|
||||||
type Activity,
|
type Activity,
|
||||||
type SupportedMedia,
|
type SupportedMedia,
|
||||||
|
type ServerFeatures,
|
||||||
} from "@/types";
|
} from "@/types";
|
||||||
import axios from "axios";
|
import { Reqer, ReqerError } from "./fetch";
|
||||||
import { notify, unNotify } from "./notify";
|
import { notify, unNotify } from "./notify";
|
||||||
import { browser } from "$app/environment";
|
import { browser } from "$app/environment";
|
||||||
const { MODE } = import.meta.env;
|
const { MODE } = import.meta.env;
|
||||||
@@ -27,6 +28,9 @@ export const baseURL =
|
|||||||
: "/api";
|
: "/api";
|
||||||
console.log("api: baseURL constructed:", baseURL);
|
console.log("api: baseURL constructed:", baseURL);
|
||||||
|
|
||||||
|
export const req = new Reqer(baseURL, true);
|
||||||
|
export const noAuthReq = new Reqer(baseURL, false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Options for our internal updateWatched func.
|
* Options for our internal updateWatched func.
|
||||||
*/
|
*/
|
||||||
@@ -71,7 +75,7 @@ async function _updateWatched(
|
|||||||
if (typeof letCountAsPlay !== "undefined") {
|
if (typeof letCountAsPlay !== "undefined") {
|
||||||
obj.letCountAsPlay = letCountAsPlay;
|
obj.letCountAsPlay = letCountAsPlay;
|
||||||
}
|
}
|
||||||
const resp = await axios.put<WatchedUpdateResponse>(
|
const resp = await req.put<WatchedUpdateResponse>(
|
||||||
`/watched/${wEntry.id}`,
|
`/watched/${wEntry.id}`,
|
||||||
obj,
|
obj,
|
||||||
);
|
);
|
||||||
@@ -79,14 +83,14 @@ async function _updateWatched(
|
|||||||
if (rating) wEntry.rating = rating;
|
if (rating) wEntry.rating = rating;
|
||||||
if (typeof thoughts !== "undefined") wEntry.thoughts = thoughts;
|
if (typeof thoughts !== "undefined") wEntry.thoughts = thoughts;
|
||||||
if (typeof pinned !== "undefined") wEntry.pinned = pinned;
|
if (typeof pinned !== "undefined") wEntry.pinned = pinned;
|
||||||
if (resp?.data?.newActivity && resp?.data?.newActivity?.id) {
|
if (resp?.newActivity && resp?.newActivity?.id) {
|
||||||
if (wEntry.activity && wEntry.activity.length > 0) {
|
if (wEntry.activity && wEntry.activity.length > 0) {
|
||||||
wEntry.activity.push(resp.data.newActivity);
|
wEntry.activity.push(resp.newActivity);
|
||||||
} else {
|
} else {
|
||||||
wEntry.activity = [resp.data.newActivity];
|
wEntry.activity = [resp.newActivity];
|
||||||
}
|
}
|
||||||
// If new activity counts as play, increment plays for local state.
|
// If new activity counts as play, increment plays for local state.
|
||||||
if (resp.data.newActivity.countAsPlay) {
|
if (resp.newActivity.countAsPlay) {
|
||||||
if (wEntry.plays) {
|
if (wEntry.plays) {
|
||||||
wEntry.plays++;
|
wEntry.plays++;
|
||||||
} else {
|
} else {
|
||||||
@@ -133,22 +137,22 @@ export async function updateWatched(
|
|||||||
|
|
||||||
// Add new watched item
|
// Add new watched item
|
||||||
notify({ id: nid, text: `Adding`, type: "loading" });
|
notify({ id: nid, text: `Adding`, type: "loading" });
|
||||||
let req: WatchedAddRequest = {
|
let reqBody: WatchedAddRequest = {
|
||||||
contentType: opts.contentType,
|
contentType: opts.contentType,
|
||||||
status: opts.status,
|
status: opts.status,
|
||||||
rating: opts.rating,
|
rating: opts.rating,
|
||||||
};
|
};
|
||||||
if (opts.contentType === "movie" || opts.contentType === "tv") {
|
if (opts.contentType === "movie" || opts.contentType === "tv") {
|
||||||
req.tmdbId = opts.contentId;
|
reqBody.tmdbId = opts.contentId;
|
||||||
} else if (opts.contentType === "game") {
|
} else if (opts.contentType === "game") {
|
||||||
req.igdbId = opts.contentId;
|
reqBody.igdbId = opts.contentId;
|
||||||
} else {
|
} else {
|
||||||
throw "invalid contentType";
|
throw "invalid contentType";
|
||||||
}
|
}
|
||||||
const resp = await axios.post<Watched>("/watched", req);
|
const resp = await req.post<Watched>("/watched", reqBody);
|
||||||
console.log("Added watched:", resp.data);
|
console.log("Added watched:", resp);
|
||||||
notify({ id: nid, text: `Added!`, type: "success" });
|
notify({ id: nid, text: `Added!`, type: "success" });
|
||||||
return resp.data;
|
return resp;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("updateWatched: Failed!", err);
|
console.error("updateWatched: Failed!", err);
|
||||||
notify({ id: nid, text: `Failed!`, type: "error" });
|
notify({ id: nid, text: `Failed!`, type: "error" });
|
||||||
@@ -165,8 +169,8 @@ export async function removeWatched(id: number): Promise<boolean> {
|
|||||||
console.log("removeWatched: Removing:", id);
|
console.log("removeWatched: Removing:", id);
|
||||||
const nid = notify({ text: "Removing", type: "loading" });
|
const nid = notify({ text: "Removing", type: "loading" });
|
||||||
try {
|
try {
|
||||||
const resp = await axios.delete(`/watched/${id}`);
|
const resp = await req.delete(`/watched/${id}`);
|
||||||
console.log("removeWatched: Removed resp:", resp.data);
|
console.log("removeWatched: Removed resp:", resp);
|
||||||
notify({ id: nid, text: "Removed!", type: "success" });
|
notify({ id: nid, text: "Removed!", type: "success" });
|
||||||
return true;
|
return true;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -183,7 +187,7 @@ export async function updateActivity(
|
|||||||
const nid = notify({ text: "Updating", type: "loading" });
|
const nid = notify({ text: "Updating", type: "loading" });
|
||||||
console.debug("updateActivity:", activity, date);
|
console.debug("updateActivity:", activity, date);
|
||||||
try {
|
try {
|
||||||
const resp = await axios.put(`/activity/${activity.id}`, {
|
const resp = await req.putWhole(`/activity/${activity.id}`, {
|
||||||
customDate: date.toISOString(),
|
customDate: date.toISOString(),
|
||||||
} as ActivityUpdateRequest);
|
} as ActivityUpdateRequest);
|
||||||
console.log("updateActivity: Response status:", resp.status);
|
console.log("updateActivity: Response status:", resp.status);
|
||||||
@@ -201,7 +205,7 @@ export async function updateActivity(
|
|||||||
export async function removeActivity(activityId: number): Promise<boolean> {
|
export async function removeActivity(activityId: number): Promise<boolean> {
|
||||||
const nid = notify({ text: "Deleting", type: "loading" });
|
const nid = notify({ text: "Deleting", type: "loading" });
|
||||||
try {
|
try {
|
||||||
await axios.delete("/activity/" + activityId);
|
await req.delete("/activity/" + activityId);
|
||||||
console.log("removeActivity: Removed:", activityId);
|
console.log("removeActivity: Removed:", activityId);
|
||||||
notify({ id: nid, text: "Deleted!", type: "success" });
|
notify({ id: nid, text: "Deleted!", type: "success" });
|
||||||
return true;
|
return true;
|
||||||
@@ -219,9 +223,11 @@ export async function contentExistsOnJellyfin(
|
|||||||
): Promise<JellyfinFoundContent | undefined> {
|
): Promise<JellyfinFoundContent | undefined> {
|
||||||
try {
|
try {
|
||||||
if (Number(store.userInfo?.type) == UserType.Jellyfin) {
|
if (Number(store.userInfo?.type) == UserType.Jellyfin) {
|
||||||
const resp = await axios.get(`/jellyfin/${type}/${name}/${tmdbId}`);
|
const resp = await req.get<JellyfinFoundContent>(
|
||||||
console.log("contentExistsOnJellyfin response:", resp.data);
|
`/jellyfin/${type}/${name}/${tmdbId}`,
|
||||||
return resp.data as JellyfinFoundContent;
|
);
|
||||||
|
console.log("contentExistsOnJellyfin response:", resp);
|
||||||
|
return resp;
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
@@ -241,14 +247,12 @@ export function updateUserSetting<K extends keyof UserSettings>(
|
|||||||
}
|
}
|
||||||
const originalValue = store.userSettings[name];
|
const originalValue = store.userSettings[name];
|
||||||
const nid = notify({ type: "loading", text: "Updating" });
|
const nid = notify({ type: "loading", text: "Updating" });
|
||||||
axios
|
req
|
||||||
.post("/user/update", { [name]: value })
|
.post("/user/update", { [name]: value })
|
||||||
.then((r) => {
|
.then(() => {
|
||||||
if (r.status === 200) {
|
if (store.userSettings) store.userSettings[name] = value;
|
||||||
if (store.userSettings) store.userSettings[name] = value;
|
notify({ id: nid, type: "success", text: "Updated" });
|
||||||
notify({ id: nid, type: "success", text: "Updated" });
|
if (typeof done !== "undefined") done();
|
||||||
if (typeof done !== "undefined") done();
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.error("Failed to update user setting", err);
|
console.error("Failed to update user setting", err);
|
||||||
@@ -264,18 +268,14 @@ export function changeUserPassword(
|
|||||||
done?: (errMsg?: string) => void,
|
done?: (errMsg?: string) => void,
|
||||||
) {
|
) {
|
||||||
const nid = notify({ type: "loading", text: "Changing Password" });
|
const nid = notify({ type: "loading", text: "Changing Password" });
|
||||||
axios
|
req
|
||||||
.post("/auth/change_password", { oldPassword, newPassword })
|
.post("/auth/change_password", { oldPassword, newPassword })
|
||||||
.then((r) => {
|
.then(() => {
|
||||||
if (r.status === 200) {
|
notify({ id: nid, type: "success", text: "Password Changed" });
|
||||||
notify({ id: nid, type: "success", text: "Password Changed" });
|
if (typeof done !== "undefined") done();
|
||||||
if (typeof done !== "undefined") done();
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
const errMsg = err?.response?.data?.error
|
const errMsg = ReqerError.getMsg(err, "Couldn't Change Password");
|
||||||
? err.response.data.error
|
|
||||||
: "Couldn't Change Password";
|
|
||||||
console.error(
|
console.error(
|
||||||
"Change Password Form - Failed to change password on the server",
|
"Change Password Form - Failed to change password on the server",
|
||||||
err,
|
err,
|
||||||
@@ -290,9 +290,9 @@ export function changeUserPassword(
|
|||||||
*/
|
*/
|
||||||
export async function getServerFeatures() {
|
export async function getServerFeatures() {
|
||||||
try {
|
try {
|
||||||
const f = await axios.get("/features");
|
const f = await req.get<ServerFeatures>("/features");
|
||||||
if (f?.data) {
|
if (f) {
|
||||||
store.serverFeatures = f.data;
|
store.serverFeatures = f;
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("getServerFeatures failed!", err);
|
console.error("getServerFeatures failed!", err);
|
||||||
@@ -301,11 +301,11 @@ export async function getServerFeatures() {
|
|||||||
|
|
||||||
export async function followUser(id: number) {
|
export async function followUser(id: number) {
|
||||||
const nid = notify({ text: `Following`, type: "loading" });
|
const nid = notify({ text: `Following`, type: "loading" });
|
||||||
axios
|
req
|
||||||
.post(`/follow/${id}`)
|
.post<Follow>(`/follow/${id}`)
|
||||||
.then((resp) => {
|
.then((resp) => {
|
||||||
console.log("Followed:", resp.data);
|
console.log("Followed:", resp);
|
||||||
store.follows.push(resp.data as Follow);
|
store.follows.push(resp);
|
||||||
notify({ id: nid, text: `Followed!`, type: "success" });
|
notify({ id: nid, text: `Followed!`, type: "success" });
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
@@ -316,10 +316,10 @@ export async function followUser(id: number) {
|
|||||||
|
|
||||||
export async function unfollowUser(id: number) {
|
export async function unfollowUser(id: number) {
|
||||||
const nid = notify({ text: `Unfollowing`, type: "loading" });
|
const nid = notify({ text: `Unfollowing`, type: "loading" });
|
||||||
axios
|
req
|
||||||
.delete(`/follow/${id}`)
|
.delete(`/follow/${id}`)
|
||||||
.then((resp) => {
|
.then((resp) => {
|
||||||
console.log("Unfollowed:", resp.data);
|
console.log("Unfollowed:", resp);
|
||||||
store.follows = store.follows.filter((fo) => fo.followedUser.id != id);
|
store.follows = store.follows.filter((fo) => fo.followedUser.id != id);
|
||||||
notify({ id: nid, text: `Unfollowed!`, type: "success" });
|
notify({ id: nid, text: `Unfollowed!`, type: "success" });
|
||||||
})
|
})
|
||||||
@@ -328,10 +328,3 @@ export async function unfollowUser(id: number) {
|
|||||||
notify({ id: nid, text: "Failed To Unfollow!", type: "error" });
|
notify({ id: nid, text: "Failed To Unfollow!", type: "error" });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* For use with routes that don't require authentication (eg login/register)
|
|
||||||
*/
|
|
||||||
export const noAuthAxios = axios.create({
|
|
||||||
baseURL: baseURL,
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -0,0 +1,330 @@
|
|||||||
|
import { goto } from "$app/navigation";
|
||||||
|
import { clearWatcharrData } from "../logout";
|
||||||
|
import { notify } from "./notify";
|
||||||
|
|
||||||
|
type ReqerParams = any;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request config, extending upon base RequestInit.
|
||||||
|
*/
|
||||||
|
export interface ReqerConfig extends RequestInit {
|
||||||
|
/**
|
||||||
|
* URL Parameters.
|
||||||
|
*
|
||||||
|
* Example: `{ page: 1 }` will become &page=1 on the requests final url.
|
||||||
|
*/
|
||||||
|
params?: ReqerParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
type ReqerConfigWithoutMethod = Omit<ReqerConfig, "method">;
|
||||||
|
|
||||||
|
export class ReqerError extends Error {
|
||||||
|
constructor(
|
||||||
|
public message: string,
|
||||||
|
public body?: any,
|
||||||
|
public response?: Response,
|
||||||
|
) {
|
||||||
|
super(message);
|
||||||
|
this.name = "ReqerError";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If err is a ReqerError.
|
||||||
|
*/
|
||||||
|
static isReqerError(err: any) {
|
||||||
|
return err instanceof ReqerError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If err is a ReqerError and has a `body`.
|
||||||
|
*/
|
||||||
|
static withBody(
|
||||||
|
err: any,
|
||||||
|
): err is ReqerError & Required<Pick<ReqerError, "body">> {
|
||||||
|
return this.isReqerError(err) && err.body;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get error message from an error.
|
||||||
|
*
|
||||||
|
* If `err` is a ReqerError, use message from that instance, which can be
|
||||||
|
* the error returned from response body. Otherwise, standard error message
|
||||||
|
* is returned if one is availble.
|
||||||
|
*
|
||||||
|
* `act` should be the action that failed. It will be combined with the
|
||||||
|
* error message to create one readable string of `action: err`.
|
||||||
|
*/
|
||||||
|
static getMsg(err: any, act: string): string {
|
||||||
|
// If response body has `error` property, is is a standard error
|
||||||
|
// object that the Watcharr server returns. We don't want to return
|
||||||
|
// a raw `body` if there is no expected `error` property incase it is
|
||||||
|
// a random html error page or whatever (its better to show a pretty
|
||||||
|
// error whenever possible, debugging errors are always in console),
|
||||||
|
// if there is no `error`, we try the `err.message`.
|
||||||
|
let msg = "You've encountered an extremely unguarded error!";
|
||||||
|
if (ReqerError.withBody(err) && err.body.error) {
|
||||||
|
msg = err.body.error;
|
||||||
|
} else if (err.message) {
|
||||||
|
msg = err.message;
|
||||||
|
}
|
||||||
|
return `${act}: ${msg}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reqer request response object.
|
||||||
|
* The *Whole functions return this whole object, which includes
|
||||||
|
* request details (like status), along with the response body.
|
||||||
|
*/
|
||||||
|
export interface ReqerResponse<T> {
|
||||||
|
/**
|
||||||
|
* Parsed body.
|
||||||
|
*/
|
||||||
|
body: T;
|
||||||
|
/**
|
||||||
|
* Response status code.
|
||||||
|
*/
|
||||||
|
status: number;
|
||||||
|
/**
|
||||||
|
* Response headers.
|
||||||
|
*/
|
||||||
|
headers: Headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple Fetch API wrapper.
|
||||||
|
*
|
||||||
|
* Throws when response.status is not 2xx.
|
||||||
|
*
|
||||||
|
* Has nice `get`, `post`, etc methods that simply return response body. Along
|
||||||
|
* with their `*Whole` counterpart methods that return a `ReqerResponse` object
|
||||||
|
* for more involved logic that needs to look at status code or headers.
|
||||||
|
*/
|
||||||
|
export class Reqer {
|
||||||
|
constructor(
|
||||||
|
/**
|
||||||
|
* BaseURL for all requests.
|
||||||
|
*/
|
||||||
|
private baseUrl: string,
|
||||||
|
/**
|
||||||
|
* If the requests should add an Authorization header
|
||||||
|
* with users Watcharr token.
|
||||||
|
*/
|
||||||
|
private watcharrAuthed: boolean,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
private buildBaseUrl(b: string): string {
|
||||||
|
if (!b.endsWith("/")) {
|
||||||
|
b += "/";
|
||||||
|
}
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
private buildUrlPath(p: string): string {
|
||||||
|
// Removes any slashes or "." from start of path.
|
||||||
|
return p.replace(/^[.\/\\]+/, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
private buildUrl(p: string, params?: ReqerParams): URL {
|
||||||
|
try {
|
||||||
|
// URL builds the url string "properly", but I don't want that for
|
||||||
|
// this use case, so we are pre-processing the path and baseUrl to
|
||||||
|
// skirt the relative resolving of the paths.
|
||||||
|
// See: https://developer.mozilla.org/en-US/docs/Web/API/URL_API/Resolving_relative_references
|
||||||
|
const url = new URL(
|
||||||
|
this.buildUrlPath(p),
|
||||||
|
this.buildBaseUrl(this.baseUrl),
|
||||||
|
);
|
||||||
|
if (params && typeof params === "object") {
|
||||||
|
for (const k in params) {
|
||||||
|
if (!Object.hasOwn(params, k)) continue;
|
||||||
|
const el = params[k];
|
||||||
|
if (el) {
|
||||||
|
// We use append on url.searchParams instead of
|
||||||
|
// overwriting it with a new object incase it has any
|
||||||
|
// existing params parsed from the `p`ath.
|
||||||
|
url.searchParams.append(k, String(el));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return url;
|
||||||
|
} catch (err) {
|
||||||
|
console.error("reqer->buildUrl: Failed!", err);
|
||||||
|
throw new ReqerError("building request url failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private prepareRequestBody(
|
||||||
|
data: any,
|
||||||
|
headers: Headers,
|
||||||
|
): BodyInit | undefined {
|
||||||
|
if (!data) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The browser can handle these.
|
||||||
|
if (
|
||||||
|
data instanceof FormData ||
|
||||||
|
data instanceof Blob ||
|
||||||
|
data instanceof URLSearchParams ||
|
||||||
|
data instanceof ArrayBuffer ||
|
||||||
|
ArrayBuffer.isView(data)
|
||||||
|
) {
|
||||||
|
return data as BodyInit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Already encoded, so return it as is.
|
||||||
|
if (typeof data === "string") {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stringify json.
|
||||||
|
headers.append("Content-Type", "application/json");
|
||||||
|
return JSON.stringify(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async parseResponseBody(res: Response) {
|
||||||
|
const contentType = res.headers.get("Content-Type");
|
||||||
|
if (!contentType) {
|
||||||
|
throw new ReqerError("response has no content-type", res);
|
||||||
|
}
|
||||||
|
if (contentType.includes("application/json")) {
|
||||||
|
return await res.json();
|
||||||
|
} else if (contentType.includes("text/plain")) {
|
||||||
|
return await res.text();
|
||||||
|
}
|
||||||
|
throw new ReqerError("response includes an unsupported content-type", res);
|
||||||
|
}
|
||||||
|
|
||||||
|
async do<T>(p: string, cfg?: ReqerConfig): Promise<ReqerResponse<T>> {
|
||||||
|
try {
|
||||||
|
const headers = new Headers(cfg?.headers);
|
||||||
|
|
||||||
|
if (this.watcharrAuthed) {
|
||||||
|
const token = localStorage.getItem("token");
|
||||||
|
if (!token) {
|
||||||
|
console.error("No token, going to login.");
|
||||||
|
goto("/login?again=1");
|
||||||
|
throw new ReqerError("No auth token found");
|
||||||
|
}
|
||||||
|
headers.append("Authorization", token);
|
||||||
|
}
|
||||||
|
|
||||||
|
const reqBody = this.prepareRequestBody(cfg?.body, headers);
|
||||||
|
|
||||||
|
const res = await fetch(this.buildUrl(p, cfg?.params), {
|
||||||
|
...cfg,
|
||||||
|
body: reqBody,
|
||||||
|
headers,
|
||||||
|
});
|
||||||
|
|
||||||
|
let resBody = await this.parseResponseBody(res);
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
throw new ReqerError(
|
||||||
|
`request failed with ${res.status} ${res.statusText}`,
|
||||||
|
resBody,
|
||||||
|
res,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
body: resBody,
|
||||||
|
status: res.status,
|
||||||
|
headers: res.headers,
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Reqer->do: Errored!", err);
|
||||||
|
if (err instanceof ReqerError) {
|
||||||
|
if (this.watcharrAuthed && err.response?.status === 401) {
|
||||||
|
console.error("Recieved 401 response, going to login.");
|
||||||
|
notify({ text: "Request Authorization Failed!", type: "error" });
|
||||||
|
clearWatcharrData();
|
||||||
|
goto("/login?again=1");
|
||||||
|
}
|
||||||
|
throw err;
|
||||||
|
} else if (err instanceof Error) {
|
||||||
|
throw new ReqerError(err.message);
|
||||||
|
}
|
||||||
|
throw new ReqerError("request failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GET request, returning parsed response body.
|
||||||
|
*/
|
||||||
|
async get<T>(p: string, cfg?: ReqerConfigWithoutMethod): Promise<T> {
|
||||||
|
return (await this.do<T>(p, { ...cfg, method: "GET" })).body;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same as `get()`, except the whole ReqerResponse object is returned.
|
||||||
|
*/
|
||||||
|
async getWhole<T>(
|
||||||
|
p: string,
|
||||||
|
cfg?: ReqerConfigWithoutMethod,
|
||||||
|
): Promise<ReqerResponse<T>> {
|
||||||
|
return await this.do<T>(p, { ...cfg, method: "GET" });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POST request, returning parsed response body.
|
||||||
|
*/
|
||||||
|
async post<T>(
|
||||||
|
p: string,
|
||||||
|
data?: any,
|
||||||
|
cfg?: Omit<ReqerConfigWithoutMethod, "body">,
|
||||||
|
): Promise<T> {
|
||||||
|
return (await this.do<T>(p, { ...cfg, method: "POST", body: data })).body;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same as `post()`, except the whole ReqerResponse object is returned.
|
||||||
|
*/
|
||||||
|
async postWhole<T>(
|
||||||
|
p: string,
|
||||||
|
data?: any,
|
||||||
|
cfg?: Omit<ReqerConfigWithoutMethod, "body">,
|
||||||
|
): Promise<ReqerResponse<T>> {
|
||||||
|
return await this.do<T>(p, { ...cfg, method: "POST", body: data });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PUT request, returning parsed response body.
|
||||||
|
*/
|
||||||
|
async put<T>(
|
||||||
|
p: string,
|
||||||
|
data?: any,
|
||||||
|
cfg?: ReqerConfigWithoutMethod,
|
||||||
|
): Promise<T> {
|
||||||
|
return (await this.do<T>(p, { ...cfg, method: "PUT", body: data })).body;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same as `put()`, except the whole ReqerResponse object is returned.
|
||||||
|
*/
|
||||||
|
async putWhole<T>(
|
||||||
|
p: string,
|
||||||
|
data?: any,
|
||||||
|
cfg?: ReqerConfigWithoutMethod,
|
||||||
|
): Promise<ReqerResponse<T>> {
|
||||||
|
return await this.do<T>(p, { ...cfg, method: "PUT", body: data });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DELETE request, returning parsed response body.
|
||||||
|
*/
|
||||||
|
async delete<T>(p: string, cfg?: ReqerConfigWithoutMethod): Promise<T> {
|
||||||
|
return (await this.do<T>(p, { ...cfg, method: "DELETE" })).body;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same as `delete()`, except the whole ReqerResponse object is returned.
|
||||||
|
*/
|
||||||
|
async deleteWhole<T>(
|
||||||
|
p: string,
|
||||||
|
cfg?: ReqerConfigWithoutMethod,
|
||||||
|
): Promise<ReqerResponse<T>> {
|
||||||
|
return await this.do<T>(p, { ...cfg, method: "DELETE" });
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
import type { PaginationResponse } from "@/types";
|
import type { PaginationResponse } from "@/types";
|
||||||
import type { AxiosResponse, GenericAbortSignal } from "axios";
|
|
||||||
|
|
||||||
export enum PaginatedLoaderRunFnAction {
|
export enum PaginatedLoaderRunFnAction {
|
||||||
// Reset state before running fn. Simplifies running a clean request.
|
// Reset state before running fn. Simplifies running a clean request.
|
||||||
@@ -14,9 +13,7 @@ export enum PaginatedLoaderRunFnAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function paginatedLoader<T, U>(
|
export default function paginatedLoader<T, U>(
|
||||||
fn: (
|
fn: (sig: AbortSignal) => Promise<PaginationResponse<T, U> | undefined>,
|
||||||
sig: GenericAbortSignal,
|
|
||||||
) => Promise<AxiosResponse<PaginationResponse<T, U>, any> | undefined>,
|
|
||||||
) {
|
) {
|
||||||
let reqController = new AbortController();
|
let reqController = new AbortController();
|
||||||
|
|
||||||
@@ -102,20 +99,20 @@ export default function paginatedLoader<T, U>(
|
|||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
state.page = resp.data.page;
|
state.page = resp.page;
|
||||||
state.pageMax = resp.data.totalPages;
|
state.pageMax = resp.totalPages;
|
||||||
console.debug(
|
console.debug(
|
||||||
`%cpaginatedLoader->runFn: Loaded Page=${state.page} Max=${state.pageMax}`,
|
`%cpaginatedLoader->runFn: Loaded Page=${state.page} Max=${state.pageMax}`,
|
||||||
logStyle,
|
logStyle,
|
||||||
);
|
);
|
||||||
if (!resp.data.results || resp.data.results.length <= 0) {
|
if (!resp.results || resp.results.length <= 0) {
|
||||||
state.reqLoading = false;
|
state.reqLoading = false;
|
||||||
console.warn("loadWatchedList: No results.");
|
console.warn("loadWatchedList: No results.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
state.data.push(...resp.data.results);
|
state.data.push(...resp.results);
|
||||||
state.data = state.data;
|
state.data = state.data;
|
||||||
state.meta = resp.data.meta;
|
state.meta = resp.meta;
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
if (err?.code === "ERR_CANCELED") {
|
if (err?.code === "ERR_CANCELED") {
|
||||||
console.warn("loadWatchedList: Cancelled, not showing error.");
|
console.warn("loadWatchedList: Cancelled, not showing error.");
|
||||||
|
|||||||
+14
-13
@@ -1,4 +1,9 @@
|
|||||||
import { noAuthAxios } from "./api";
|
import { Reqer } from "./fetch";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For requests outbound to `plex.tv`.
|
||||||
|
*/
|
||||||
|
const plexTvReq = new Reqer("https://plex.tv/api/v2", false);
|
||||||
|
|
||||||
interface Plex {
|
interface Plex {
|
||||||
win: Window;
|
win: Window;
|
||||||
@@ -104,11 +109,11 @@ export async function plexPinPoll(
|
|||||||
const doPoll = async () => {
|
const doPoll = async () => {
|
||||||
try {
|
try {
|
||||||
console.debug("plexPinPoll");
|
console.debug("plexPinPoll");
|
||||||
const r = await noAuthAxios.get(`https://plex.tv/api/v2/pins/${pin.id}`, {
|
const r = await plexTvReq.get<any>(`/pins/${pin.id}`, {
|
||||||
headers: { ...headers, code: pin.code },
|
headers: { ...headers, code: pin.code },
|
||||||
});
|
});
|
||||||
if (r.data?.authToken) {
|
if (r?.authToken) {
|
||||||
done(undefined, r.data.authToken);
|
done(undefined, r.authToken);
|
||||||
win.close();
|
win.close();
|
||||||
} else if (win?.closed) {
|
} else if (win?.closed) {
|
||||||
done(new Error("Plex popup closed before login completed"));
|
done(new Error("Plex popup closed before login completed"));
|
||||||
@@ -124,13 +129,9 @@ export async function plexPinPoll(
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function getPlexPin(headers: Record<string, string>): Promise<PlexPin> {
|
async function getPlexPin(headers: Record<string, string>): Promise<PlexPin> {
|
||||||
const r = await noAuthAxios.post(
|
const r = await plexTvReq.post<any>(`/pins?strong=true`, undefined, {
|
||||||
`https://plex.tv/api/v2/pins?strong=true`,
|
headers: headers,
|
||||||
undefined,
|
});
|
||||||
{
|
console.debug("getPlexPin:", r);
|
||||||
headers: headers,
|
return { id: r.id, code: r.code };
|
||||||
},
|
|
||||||
);
|
|
||||||
console.debug("getPlexPin:", r.data);
|
|
||||||
return { id: r.data.id, code: r.data.code };
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,9 +11,16 @@
|
|||||||
import FollowingMenu from "@/lib/nav/FollowingMenu.svelte";
|
import FollowingMenu from "@/lib/nav/FollowingMenu.svelte";
|
||||||
import SortMenu from "@/lib/nav/SortMenu.svelte";
|
import SortMenu from "@/lib/nav/SortMenu.svelte";
|
||||||
import TagMenu from "@/lib/tag/TagMenu.svelte";
|
import TagMenu from "@/lib/tag/TagMenu.svelte";
|
||||||
|
import { req } from "@/lib/util/api";
|
||||||
import { isTouch } from "@/lib/util/helpers";
|
import { isTouch } from "@/lib/util/helpers";
|
||||||
import { store, defaultSort } from "@/store.svelte";
|
import { store, defaultSort } from "@/store.svelte";
|
||||||
import axios from "axios";
|
import type {
|
||||||
|
ServerFeatures,
|
||||||
|
Follow,
|
||||||
|
PrivateUser,
|
||||||
|
Tag,
|
||||||
|
UserSettings,
|
||||||
|
} from "@/types";
|
||||||
import { onMount } from "svelte";
|
import { onMount } from "svelte";
|
||||||
interface Props {
|
interface Props {
|
||||||
children?: import("svelte").Snippet;
|
children?: import("svelte").Snippet;
|
||||||
@@ -101,31 +108,32 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function getInitialData() {
|
async function getInitialData() {
|
||||||
if (localStorage.getItem("token")) {
|
if (!localStorage.getItem("token")) {
|
||||||
const [u, s, f, fo, ts] = await Promise.all([
|
console.warn("getInitialData: No token found, redirecting to login!");
|
||||||
axios.get("/user"),
|
|
||||||
axios.get("/user/settings"),
|
|
||||||
axios.get("/features"),
|
|
||||||
axios.get("/follow"),
|
|
||||||
axios.get("/tag"),
|
|
||||||
]);
|
|
||||||
if (u?.data) {
|
|
||||||
store.userInfo = u.data;
|
|
||||||
}
|
|
||||||
if (s?.data) {
|
|
||||||
store.userSettings = s.data;
|
|
||||||
}
|
|
||||||
if (f?.data) {
|
|
||||||
store.serverFeatures = f.data;
|
|
||||||
}
|
|
||||||
if (fo?.data) {
|
|
||||||
store.follows = fo.data;
|
|
||||||
}
|
|
||||||
if (ts?.data) {
|
|
||||||
store.tags = ts.data;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
goto("/login?again=1");
|
goto("/login?again=1");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const [u, s, f, fo, ts] = await Promise.all([
|
||||||
|
req.get<PrivateUser>("/user"),
|
||||||
|
req.get<UserSettings>("/user/settings"),
|
||||||
|
req.get<ServerFeatures>("/features"),
|
||||||
|
req.get<Follow[]>("/follow"),
|
||||||
|
req.get<Tag[]>("/tag"),
|
||||||
|
]);
|
||||||
|
if (u) {
|
||||||
|
store.userInfo = u;
|
||||||
|
}
|
||||||
|
if (s) {
|
||||||
|
store.userSettings = s;
|
||||||
|
}
|
||||||
|
if (f) {
|
||||||
|
store.serverFeatures = f;
|
||||||
|
}
|
||||||
|
if (fo) {
|
||||||
|
store.follows = fo;
|
||||||
|
}
|
||||||
|
if (ts) {
|
||||||
|
store.tags = ts;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,47 +1,3 @@
|
|||||||
export const prerender = false;
|
export const prerender = false;
|
||||||
export const ssr = false;
|
export const ssr = false;
|
||||||
export const csr = true;
|
export const csr = true;
|
||||||
|
|
||||||
import { goto } from "$app/navigation";
|
|
||||||
import axios from "axios";
|
|
||||||
import { baseURL } from "@/lib/util/api";
|
|
||||||
import { notify } from "@/lib/util/notify";
|
|
||||||
import { clearWatcharrData } from "@/lib/logout";
|
|
||||||
|
|
||||||
axios.interceptors.request.use(
|
|
||||||
(config) => {
|
|
||||||
if (!config.baseURL) {
|
|
||||||
config.baseURL = baseURL;
|
|
||||||
|
|
||||||
// Only want to set auth header if requesting to our backend.
|
|
||||||
const token = localStorage.getItem("token");
|
|
||||||
// Don't require token check if going to auth route (login/register)
|
|
||||||
if (!token && !config.url?.includes("/auth")) {
|
|
||||||
console.error("No token, going to login. Endpoint:", config.url);
|
|
||||||
goto("/login?again=1");
|
|
||||||
throw new axios.Cancel("No auth token found");
|
|
||||||
}
|
|
||||||
config.headers.set("Authorization", token);
|
|
||||||
}
|
|
||||||
|
|
||||||
return config;
|
|
||||||
},
|
|
||||||
(error) => {
|
|
||||||
return Promise.reject(error);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
axios.interceptors.response.use(
|
|
||||||
(response) => {
|
|
||||||
return response;
|
|
||||||
},
|
|
||||||
(error) => {
|
|
||||||
if (error.response?.status === 401) {
|
|
||||||
console.error("Recieved 401 response, going to login.");
|
|
||||||
notify({ text: "Request Authorization Failed!", type: "error" });
|
|
||||||
clearWatcharrData();
|
|
||||||
goto("/login?again=1");
|
|
||||||
}
|
|
||||||
return Promise.reject(error);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|||||||
@@ -5,11 +5,11 @@
|
|||||||
import Poster from "@/lib/poster/Poster.svelte";
|
import Poster from "@/lib/poster/Poster.svelte";
|
||||||
import PosterList from "@/lib/poster/PosterList.svelte";
|
import PosterList from "@/lib/poster/PosterList.svelte";
|
||||||
import Spinner from "@/lib/Spinner.svelte";
|
import Spinner from "@/lib/Spinner.svelte";
|
||||||
|
import { req } from "@/lib/util/api";
|
||||||
import infScroll from "@/lib/util/infScroll";
|
import infScroll from "@/lib/util/infScroll";
|
||||||
import paginatedLoader from "@/lib/util/paginatedLoader.svelte";
|
import paginatedLoader from "@/lib/util/paginatedLoader.svelte";
|
||||||
import { clearActiveFilters, store } from "@/store.svelte";
|
import { clearActiveFilters, store } from "@/store.svelte";
|
||||||
import type { Media } from "@/types";
|
import { type Media, type PaginationResponse } from "@/types";
|
||||||
import axios, { type GenericAbortSignal } from "axios";
|
|
||||||
import { onDestroy, untrack } from "svelte";
|
import { onDestroy, untrack } from "svelte";
|
||||||
|
|
||||||
const scroll = infScroll({ callback: onScrollToBottom });
|
const scroll = infScroll({ callback: onScrollToBottom });
|
||||||
@@ -23,13 +23,13 @@
|
|||||||
...store.sortAndFiltersForQueryParams,
|
...store.sortAndFiltersForQueryParams,
|
||||||
});
|
});
|
||||||
|
|
||||||
async function load(signal: GenericAbortSignal) {
|
async function load(signal: AbortSignal) {
|
||||||
console.debug("load: loadParams:", nextLoadParams);
|
console.debug("load: loadParams:", nextLoadParams);
|
||||||
if (nextLoadParams.page === dataLoader.state.page) {
|
if (nextLoadParams.page === dataLoader.state.page) {
|
||||||
console.warn("load: Already on this page, not loading it again!");
|
console.warn("load: Already on this page, not loading it again!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const r = await axios.get(`/watched`, {
|
const r = await req.get<PaginationResponse<Media, undefined>>(`/watched`, {
|
||||||
params: nextLoadParams,
|
params: nextLoadParams,
|
||||||
signal,
|
signal,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,11 +3,10 @@
|
|||||||
import Spinner from "@/lib/Spinner.svelte";
|
import Spinner from "@/lib/Spinner.svelte";
|
||||||
import RequestMovie from "@/lib/request/RequestMovie.svelte";
|
import RequestMovie from "@/lib/request/RequestMovie.svelte";
|
||||||
import RequestShow from "@/lib/request/RequestShow.svelte";
|
import RequestShow from "@/lib/request/RequestShow.svelte";
|
||||||
import { baseURL } from "@/lib/util/api";
|
import { baseURL, req } from "@/lib/util/api";
|
||||||
import { toRelativeDate } from "@/lib/util/helpers";
|
import { toRelativeDate } from "@/lib/util/helpers";
|
||||||
import { notify } from "@/lib/util/notify";
|
import { notify } from "@/lib/util/notify";
|
||||||
import { type ArrRequestResponse, type Media } from "@/types";
|
import { type ArrRequestResponse, type Media } from "@/types";
|
||||||
import axios from "axios";
|
|
||||||
|
|
||||||
let allRequests: ArrRequestResponse[] | undefined = $state();
|
let allRequests: ArrRequestResponse[] | undefined = $state();
|
||||||
let showBeingApproved: Media | undefined = $state();
|
let showBeingApproved: Media | undefined = $state();
|
||||||
@@ -16,8 +15,7 @@
|
|||||||
|
|
||||||
async function getRequests() {
|
async function getRequests() {
|
||||||
try {
|
try {
|
||||||
allRequests = (await axios.get<ArrRequestResponse[]>(`/arr/request/`))
|
allRequests = await req.get<ArrRequestResponse[]>(`/arr/request/`);
|
||||||
.data;
|
|
||||||
if (allRequests?.length > 0) {
|
if (allRequests?.length > 0) {
|
||||||
allRequests = allRequests?.sort((a, b) => {
|
allRequests = allRequests?.sort((a, b) => {
|
||||||
if (b.status === "PENDING") return 1;
|
if (b.status === "PENDING") return 1;
|
||||||
@@ -33,7 +31,7 @@
|
|||||||
|
|
||||||
async function deny(r: ArrRequestResponse) {
|
async function deny(r: ArrRequestResponse) {
|
||||||
try {
|
try {
|
||||||
await axios.post(`/arr/request/deny/${r.id}`);
|
await req.post(`/arr/request/deny/${r.id}`);
|
||||||
getRequests();
|
getRequests();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("Failed to deny request!", err);
|
console.error("Failed to deny request!", err);
|
||||||
@@ -44,13 +42,13 @@
|
|||||||
async function approve(r: ArrRequestResponse) {
|
async function approve(r: ArrRequestResponse) {
|
||||||
console.debug("Approving request:", r);
|
console.debug("Approving request:", r);
|
||||||
if (r.content.type === "tv") {
|
if (r.content.type === "tv") {
|
||||||
showBeingApproved = (
|
showBeingApproved = await req.get<Media>(
|
||||||
await axios.get<Media>(`/content/tv/${r.content.tmdbId}`)
|
`/content/tv/${r.content.tmdbId}`,
|
||||||
).data;
|
);
|
||||||
} else if (r.content.type === "movie") {
|
} else if (r.content.type === "movie") {
|
||||||
movieBeingApproved = (
|
movieBeingApproved = await req.get<Media>(
|
||||||
await axios.get<Media>(`/content/movie/${r.content.tmdbId}`)
|
`/content/movie/${r.content.tmdbId}`,
|
||||||
).data;
|
);
|
||||||
} else {
|
} else {
|
||||||
notify({
|
notify({
|
||||||
type: "error",
|
type: "error",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Spinner from "@/lib/Spinner.svelte";
|
import Spinner from "@/lib/Spinner.svelte";
|
||||||
import axios, { type GenericAbortSignal } from "axios";
|
import { req } from "@/lib/util/api";
|
||||||
import Poster from "@/lib/poster/Poster.svelte";
|
import Poster from "@/lib/poster/Poster.svelte";
|
||||||
import PageTitle from "@/lib/generic/PageTitle.svelte";
|
import PageTitle from "@/lib/generic/PageTitle.svelte";
|
||||||
import MediaTypeFilter from "@/lib/search/MediaTypeFilter.svelte";
|
import MediaTypeFilter from "@/lib/search/MediaTypeFilter.svelte";
|
||||||
@@ -14,6 +14,7 @@
|
|||||||
SearchType,
|
SearchType,
|
||||||
type DiscoverRequest,
|
type DiscoverRequest,
|
||||||
type Media,
|
type Media,
|
||||||
|
type PaginationResponse,
|
||||||
} from "@/types";
|
} from "@/types";
|
||||||
import { page } from "$app/state";
|
import { page } from "$app/state";
|
||||||
import { afterNavigate, goto } from "$app/navigation";
|
import { afterNavigate, goto } from "$app/navigation";
|
||||||
@@ -40,13 +41,13 @@
|
|||||||
filter: discoverFilter,
|
filter: discoverFilter,
|
||||||
});
|
});
|
||||||
|
|
||||||
async function load(signal: GenericAbortSignal) {
|
async function load(signal: AbortSignal) {
|
||||||
console.debug("load: loadParams:", nextLoadParams);
|
console.debug("load: loadParams:", nextLoadParams);
|
||||||
if (nextLoadParams.page === dataLoader.state.page) {
|
if (nextLoadParams.page === dataLoader.state.page) {
|
||||||
console.warn("load: Already on this page, not loading it again!");
|
console.warn("load: Already on this page, not loading it again!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const r = await axios.get(`/discover`, {
|
const r = await req.get<PaginationResponse<Media, undefined>>(`/discover`, {
|
||||||
params: nextLoadParams,
|
params: nextLoadParams,
|
||||||
signal,
|
signal,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,12 +2,11 @@
|
|||||||
import Spinner from "@/lib/Spinner.svelte";
|
import Spinner from "@/lib/Spinner.svelte";
|
||||||
import HorizontalList from "@/lib/HorizontalList.svelte";
|
import HorizontalList from "@/lib/HorizontalList.svelte";
|
||||||
import { type Media, type WatchedStatus } from "@/types";
|
import { type Media, type WatchedStatus } from "@/types";
|
||||||
import axios from "axios";
|
|
||||||
import Activity from "@/lib/Activity.svelte";
|
import Activity from "@/lib/Activity.svelte";
|
||||||
import Title from "@/lib/content/Title.svelte";
|
import Title from "@/lib/content/Title.svelte";
|
||||||
import Error from "@/lib/Error.svelte";
|
import Error from "@/lib/Error.svelte";
|
||||||
import FollowedThoughts from "@/lib/content/FollowedThoughts.svelte";
|
import FollowedThoughts from "@/lib/content/FollowedThoughts.svelte";
|
||||||
import { removeWatched, updateWatched } from "@/lib/util/api.js";
|
import { req, updateWatched } from "@/lib/util/api.js";
|
||||||
import tooltip from "@/lib/actions/tooltip.js";
|
import tooltip from "@/lib/actions/tooltip.js";
|
||||||
import Icon from "@/lib/Icon.svelte";
|
import Icon from "@/lib/Icon.svelte";
|
||||||
import AddToTagButton from "@/lib/tag/AddToTagButton.svelte";
|
import AddToTagButton from "@/lib/tag/AddToTagButton.svelte";
|
||||||
@@ -43,8 +42,7 @@
|
|||||||
if (!data.gameId) {
|
if (!data.gameId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const resp = (await axios.get(`/game/${data.gameId}`)).data as Media;
|
game = await req.get<Media>(`/game/${data.gameId}`);
|
||||||
game = resp;
|
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
game = undefined;
|
game = undefined;
|
||||||
pageError = err;
|
pageError = err;
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
type Media,
|
type Media,
|
||||||
type WatchedStatus,
|
type WatchedStatus,
|
||||||
} from "@/types";
|
} from "@/types";
|
||||||
import axios from "axios";
|
import { req } from "@/lib/util/api";
|
||||||
import { onDestroy } from "svelte";
|
import { onDestroy } from "svelte";
|
||||||
import papa from "papaparse";
|
import papa from "papaparse";
|
||||||
import Status from "@/lib/Status.svelte";
|
import Status from "@/lib/Status.svelte";
|
||||||
@@ -479,11 +479,11 @@
|
|||||||
rList = rList;
|
rList = rList;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const resp = await axios.post<ImportResponse>("/import", item);
|
const resp = await req.post<ImportResponse>("/import", item);
|
||||||
return new Promise((res, rej) => {
|
return new Promise((res, rej) => {
|
||||||
if (resp.data.type === ImportResponseType.IMPORT_MULTI) {
|
if (resp.type === ImportResponseType.IMPORT_MULTI) {
|
||||||
console.log("Import found multiple responses for content", resp.data);
|
console.log("Import found multiple responses for content", resp);
|
||||||
let results = resp.data.results;
|
let results = resp.results;
|
||||||
if (!results || results.length <= 0) {
|
if (!results || results.length <= 0) {
|
||||||
item.state = ImportResponseType.IMPORT_NOTFOUND;
|
item.state = ImportResponseType.IMPORT_NOTFOUND;
|
||||||
rList = rList;
|
rList = rList;
|
||||||
@@ -521,9 +521,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
} else if (resp.data.type === ImportResponseType.IMPORT_SUCCESS) {
|
} else if (resp.type === ImportResponseType.IMPORT_SUCCESS) {
|
||||||
item.state = ImportResponseType.IMPORT_SUCCESS;
|
item.state = ImportResponseType.IMPORT_SUCCESS;
|
||||||
const w = resp.data.watchedEntry;
|
const w = resp.watchedEntry;
|
||||||
if (w) {
|
if (w) {
|
||||||
const release = w.media?.releaseDate;
|
const release = w.media?.releaseDate;
|
||||||
if (release) item.year = new Date(Date.parse(release)).getFullYear();
|
if (release) item.year = new Date(Date.parse(release)).getFullYear();
|
||||||
@@ -533,7 +533,7 @@
|
|||||||
rList = rList;
|
rList = rList;
|
||||||
res(0);
|
res(0);
|
||||||
} else {
|
} else {
|
||||||
item.state = resp.data.type;
|
item.state = resp.type;
|
||||||
rList = rList;
|
rList = rList;
|
||||||
res(0);
|
res(0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,29 +6,29 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import JobWatcherModal from "@/lib/JobWatcherModal.svelte";
|
import JobWatcherModal from "@/lib/JobWatcherModal.svelte";
|
||||||
import Setting from "@/lib/settings/Setting.svelte";
|
import Setting from "@/lib/settings/Setting.svelte";
|
||||||
|
import { req } from "@/lib/util/api";
|
||||||
import { notify } from "@/lib/util/notify";
|
import { notify } from "@/lib/util/notify";
|
||||||
import { store } from "@/store.svelte";
|
import { store } from "@/store.svelte";
|
||||||
import type { JobCreatedResponse } from "@/types";
|
import type { JobCreatedResponse } from "@/types";
|
||||||
import axios from "axios";
|
|
||||||
|
|
||||||
let modalOpen = $state(false);
|
let modalOpen = $state(false);
|
||||||
let traktUsername = $state("");
|
let traktUsername = $state("");
|
||||||
let traktApiKey = $state("");
|
let traktApiKey = $state("");
|
||||||
|
|
||||||
async function startJob(): Promise<{ jobId: string } | undefined> {
|
async function startJob(): Promise<{ jobId: string } | undefined> {
|
||||||
const r = await axios.post<JobCreatedResponse>("/import/trakt", {
|
const r = await req.post<JobCreatedResponse>("/import/trakt", {
|
||||||
username: traktUsername,
|
username: traktUsername,
|
||||||
apiKey: traktApiKey.trim(),
|
apiKey: traktApiKey.trim(),
|
||||||
});
|
});
|
||||||
console.log("startSync: Response:", r.data);
|
console.log("startSync: Response:", r);
|
||||||
if (!r.data.jobId) {
|
if (!r?.jobId) {
|
||||||
notify({
|
notify({
|
||||||
type: "error",
|
type: "error",
|
||||||
text: "No job id was returned! Cannot watch job, if it even started.",
|
text: "No job id was returned! Cannot watch job, if it even started.",
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return { jobId: r.data.jobId };
|
return { jobId: r.jobId };
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -3,11 +3,10 @@
|
|||||||
import Spinner from "@/lib/Spinner.svelte";
|
import Spinner from "@/lib/Spinner.svelte";
|
||||||
import tooltip from "@/lib/actions/tooltip.js";
|
import tooltip from "@/lib/actions/tooltip.js";
|
||||||
import UserAvatar from "@/lib/img/UserAvatar.svelte";
|
import UserAvatar from "@/lib/img/UserAvatar.svelte";
|
||||||
import { followUser, unfollowUser } from "@/lib/util/api.js";
|
import { followUser, req, unfollowUser } from "@/lib/util/api.js";
|
||||||
import { clearActiveFilters, store } from "@/store.svelte.js";
|
import { clearActiveFilters, store } from "@/store.svelte.js";
|
||||||
import type { Media, PublicUser } from "@/types.js";
|
import type { Media, PaginationResponse, PublicUser } from "@/types.js";
|
||||||
import axios, { type GenericAbortSignal } from "axios";
|
import { onDestroy, untrack } from "svelte";
|
||||||
import { onDestroy, onMount, untrack } from "svelte";
|
|
||||||
import paginatedLoader, {
|
import paginatedLoader, {
|
||||||
PaginatedLoaderRunFnAction,
|
PaginatedLoaderRunFnAction,
|
||||||
} from "@/lib/util/paginatedLoader.svelte.js";
|
} from "@/lib/util/paginatedLoader.svelte.js";
|
||||||
@@ -43,7 +42,7 @@
|
|||||||
...store.sortAndFiltersForQueryParams,
|
...store.sortAndFiltersForQueryParams,
|
||||||
});
|
});
|
||||||
|
|
||||||
async function load(signal: GenericAbortSignal) {
|
async function load(signal: AbortSignal) {
|
||||||
console.debug("load: loadParams:", nextLoadParams);
|
console.debug("load: loadParams:", nextLoadParams);
|
||||||
if (nextLoadParams.page === dataLoader.state.page) {
|
if (nextLoadParams.page === dataLoader.state.page) {
|
||||||
console.warn("load: Already on this page, not loading it again!");
|
console.warn("load: Already on this page, not loading it again!");
|
||||||
@@ -53,10 +52,13 @@
|
|||||||
console.warn("load: Missing id or username!");
|
console.warn("load: Missing id or username!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const r = await axios.get(`/watched/${meta.id}/${meta.username}`, {
|
const r = await req.get<PaginationResponse<Media, undefined>>(
|
||||||
params: nextLoadParams,
|
`/watched/${meta.id}/${meta.username}`,
|
||||||
signal,
|
{
|
||||||
});
|
params: nextLoadParams,
|
||||||
|
signal,
|
||||||
|
},
|
||||||
|
);
|
||||||
scroll.dataLoaded();
|
scroll.dataLoaded();
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@@ -87,8 +89,9 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
async function getPublicUser() {
|
async function getPublicUser() {
|
||||||
return (await axios.get(`/user/public/${meta.id}/${meta.username}`))
|
return await req.get<PublicUser>(
|
||||||
.data as PublicUser;
|
`/user/public/${meta.id}/${meta.username}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function follow() {
|
async function follow() {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
userHasPermission,
|
userHasPermission,
|
||||||
} from "@/lib/util/helpers";
|
} from "@/lib/util/helpers";
|
||||||
import { UserPermission, type ManagedUser } from "@/types";
|
import { UserPermission, type ManagedUser } from "@/types";
|
||||||
import axios from "axios";
|
import { req } from "@/lib/util/api";
|
||||||
import EditUserModal from "./modals/EditUserModal.svelte";
|
import EditUserModal from "./modals/EditUserModal.svelte";
|
||||||
import UserTypeIcon from "@/lib/user/UserTypeIcon.svelte";
|
import UserTypeIcon from "@/lib/user/UserTypeIcon.svelte";
|
||||||
import Error from "@/lib/Error.svelte";
|
import Error from "@/lib/Error.svelte";
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
let editingUser: ManagedUser | undefined;
|
let editingUser: ManagedUser | undefined;
|
||||||
|
|
||||||
async function getUsers() {
|
async function getUsers() {
|
||||||
allUsers = (await axios.get(`/server/users`)).data as ManagedUser[];
|
allUsers = await req.get<ManagedUser[]>(`/server/users`);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -4,10 +4,11 @@
|
|||||||
import Modal from "@/lib/Modal.svelte";
|
import Modal from "@/lib/Modal.svelte";
|
||||||
import Setting from "@/lib/settings/Setting.svelte";
|
import Setting from "@/lib/settings/Setting.svelte";
|
||||||
import SettingsList from "@/lib/settings/SettingsList.svelte";
|
import SettingsList from "@/lib/settings/SettingsList.svelte";
|
||||||
|
import { req } from "@/lib/util/api";
|
||||||
|
import { ReqerError } from "@/lib/util/fetch";
|
||||||
import { userHasPermission } from "@/lib/util/helpers";
|
import { userHasPermission } from "@/lib/util/helpers";
|
||||||
import { notify } from "@/lib/util/notify";
|
import { notify } from "@/lib/util/notify";
|
||||||
import { UserPermission, UserType, type ManagedUser } from "@/types";
|
import { UserPermission, UserType, type ManagedUser } from "@/types";
|
||||||
import axios from "axios";
|
|
||||||
|
|
||||||
interface UpdateUserRequest {
|
interface UpdateUserRequest {
|
||||||
permissions?: number;
|
permissions?: number;
|
||||||
@@ -44,20 +45,15 @@
|
|||||||
if (changedType) {
|
if (changedType) {
|
||||||
toUpdate["type"] = user.type;
|
toUpdate["type"] = user.type;
|
||||||
}
|
}
|
||||||
const res = await axios.post(`/server/users/${user.id}`, toUpdate);
|
await req.post(`/server/users/${user.id}`, toUpdate);
|
||||||
if (res.status === 200) {
|
notify({
|
||||||
notify({
|
type: "success",
|
||||||
type: "success",
|
text: "Changes saved!",
|
||||||
text: "Changes saved!",
|
});
|
||||||
});
|
onClose();
|
||||||
onClose();
|
|
||||||
}
|
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
console.error("Failed to save user!", err);
|
console.error("Failed to save user!", err);
|
||||||
error = `Failed to save`;
|
error = ReqerError.getMsg(err, "Failed to save");
|
||||||
if (err?.response?.data?.error) {
|
|
||||||
error = err.response.data.error;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,11 +2,7 @@
|
|||||||
import PersonPoster from "@/lib/poster/PersonPoster.svelte";
|
import PersonPoster from "@/lib/poster/PersonPoster.svelte";
|
||||||
import Spinner from "@/lib/Spinner.svelte";
|
import Spinner from "@/lib/Spinner.svelte";
|
||||||
import HorizontalList from "@/lib/HorizontalList.svelte";
|
import HorizontalList from "@/lib/HorizontalList.svelte";
|
||||||
import {
|
import { contentExistsOnJellyfin, req, updateWatched } from "@/lib/util/api";
|
||||||
contentExistsOnJellyfin,
|
|
||||||
removeWatched,
|
|
||||||
updateWatched,
|
|
||||||
} from "@/lib/util/api";
|
|
||||||
import { store } from "@/store.svelte";
|
import { store } from "@/store.svelte";
|
||||||
import type {
|
import type {
|
||||||
Media,
|
Media,
|
||||||
@@ -14,7 +10,6 @@
|
|||||||
TMDBContentCreditsCrew,
|
TMDBContentCreditsCrew,
|
||||||
WatchedStatus,
|
WatchedStatus,
|
||||||
} from "@/types";
|
} from "@/types";
|
||||||
import axios from "axios";
|
|
||||||
import { getTopCrew } from "@/lib/util/helpers.js";
|
import { getTopCrew } from "@/lib/util/helpers.js";
|
||||||
import Activity from "@/lib/Activity.svelte";
|
import Activity from "@/lib/Activity.svelte";
|
||||||
import Title from "@/lib/content/Title.svelte";
|
import Title from "@/lib/content/Title.svelte";
|
||||||
@@ -52,11 +47,9 @@
|
|||||||
if (!data.movieId) {
|
if (!data.movieId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const resp = (
|
const resp = await req.get<Media>(`/content/movie/${data.movieId}`, {
|
||||||
await axios.get(`/content/movie/${data.movieId}`, {
|
params: { region: store.userSettings?.country },
|
||||||
params: { region: store.userSettings?.country },
|
});
|
||||||
})
|
|
||||||
).data as Media;
|
|
||||||
if (resp) {
|
if (resp) {
|
||||||
if (resp.name && resp.ids.tmdb) {
|
if (resp.name && resp.ids.tmdb) {
|
||||||
contentExistsOnJellyfin("movie", resp.name, resp.ids.tmdb).then(
|
contentExistsOnJellyfin("movie", resp.name, resp.ids.tmdb).then(
|
||||||
@@ -79,8 +72,9 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
async function getMovieCredits() {
|
async function getMovieCredits() {
|
||||||
const credits = (await axios.get(`/content/movie/${data.movieId}/credits`))
|
const credits = await req.get<
|
||||||
.data as TMDBContentCredits & { topCrew: TMDBContentCreditsCrew[] };
|
TMDBContentCredits & { topCrew: TMDBContentCreditsCrew[] }
|
||||||
|
>(`/content/movie/${data.movieId}/credits`);
|
||||||
if (credits.crew?.length > 0) {
|
if (credits.crew?.length > 0) {
|
||||||
credits.topCrew = getTopCrew(credits.crew);
|
credits.topCrew = getTopCrew(credits.crew);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
PersonCreditsResponse,
|
PersonCreditsResponse,
|
||||||
PersonDetailsResponse,
|
PersonDetailsResponse,
|
||||||
} from "@/types";
|
} from "@/types";
|
||||||
import axios from "axios";
|
import { req } from "@/lib/util/api.js";
|
||||||
import Checkbox from "@/lib/Checkbox.svelte";
|
import Checkbox from "@/lib/Checkbox.svelte";
|
||||||
import Icon from "@/lib/Icon.svelte";
|
import Icon from "@/lib/Icon.svelte";
|
||||||
import PageBackdrop from "@/lib/generic/PageBackdrop.svelte";
|
import PageBackdrop from "@/lib/generic/PageBackdrop.svelte";
|
||||||
@@ -53,16 +53,13 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function getPerson(id: number) {
|
async function getPerson(id: number) {
|
||||||
return (await axios.get<PersonDetailsResponse>(`/content/person/${id}`))
|
return await req.get<PersonDetailsResponse>(`/content/person/${id}`);
|
||||||
.data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function updatePersonCredits() {
|
async function updatePersonCredits() {
|
||||||
credits = (
|
credits = await req.get<PersonCreditsResponse>(
|
||||||
await axios.get<PersonCreditsResponse>(
|
`/content/person/${data.personId}/credits`,
|
||||||
`/content/person/${data.personId}/credits`,
|
);
|
||||||
)
|
|
||||||
).data;
|
|
||||||
credits.credits = credits.credits?.filter(
|
credits.credits = credits.credits?.filter(
|
||||||
(v, i, a) => a.findIndex((t) => t.ids.tmdb === v.ids.tmdb) === i,
|
(v, i, a) => a.findIndex((t) => t.ids.tmdb === v.ids.tmdb) === i,
|
||||||
); // remove duplicate entries. If an actor has multiple roles in a single movie, it would otherwise show up multiple times
|
); // remove duplicate entries. If an actor has multiple roles in a single movie, it would otherwise show up multiple times
|
||||||
|
|||||||
@@ -6,11 +6,10 @@
|
|||||||
import Setting from "@/lib/settings/Setting.svelte";
|
import Setting from "@/lib/settings/Setting.svelte";
|
||||||
import Stat from "@/lib/stats/Stat.svelte";
|
import Stat from "@/lib/stats/Stat.svelte";
|
||||||
import Stats from "@/lib/stats/Stats.svelte";
|
import Stats from "@/lib/stats/Stats.svelte";
|
||||||
import { updateUserSetting } from "@/lib/util/api";
|
import { req, updateUserSetting } from "@/lib/util/api";
|
||||||
import { getOrdinalSuffix, monthsShort } from "@/lib/util/helpers";
|
import { getOrdinalSuffix, monthsShort } from "@/lib/util/helpers";
|
||||||
import { store } from "@/store.svelte";
|
import { store } from "@/store.svelte";
|
||||||
import { UserType, type Image, type Profile } from "@/types";
|
import { UserType, type Image, type Profile } from "@/types";
|
||||||
import axios from "axios";
|
|
||||||
import { notify } from "@/lib/util/notify";
|
import { notify } from "@/lib/util/notify";
|
||||||
import UserAvatar from "@/lib/img/UserAvatar.svelte";
|
import UserAvatar from "@/lib/img/UserAvatar.svelte";
|
||||||
import PwChangeModal from "@/routes/(app)/profile/modals/PwChangeModal.svelte";
|
import PwChangeModal from "@/routes/(app)/profile/modals/PwChangeModal.svelte";
|
||||||
@@ -19,6 +18,7 @@
|
|||||||
import RatingSetting from "@/lib/rating/RatingSetting.svelte";
|
import RatingSetting from "@/lib/rating/RatingSetting.svelte";
|
||||||
import { toggleTheme } from "@/lib/util/theme";
|
import { toggleTheme } from "@/lib/util/theme";
|
||||||
import ExportListModal from "./modals/ExportListModal.svelte";
|
import ExportListModal from "./modals/ExportListModal.svelte";
|
||||||
|
import { ReqerError } from "@/lib/util/fetch";
|
||||||
|
|
||||||
let user = $derived(store.userInfo);
|
let user = $derived(store.userInfo);
|
||||||
let settings = $derived(store.userSettings);
|
let settings = $derived(store.userSettings);
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
let plexSyncModalOpen = $state(false);
|
let plexSyncModalOpen = $state(false);
|
||||||
|
|
||||||
async function getProfile() {
|
async function getProfile() {
|
||||||
return (await axios.get(`/profile`)).data as Profile;
|
return await req.get<Profile>(`/profile`);
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatDate(d: Date) {
|
function formatDate(d: Date) {
|
||||||
@@ -55,7 +55,7 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const nid = notify({ text: "Updating Bio", type: "loading" });
|
const nid = notify({ text: "Updating Bio", type: "loading" });
|
||||||
axios
|
req
|
||||||
.post("/user/bio", { newBio: newBio })
|
.post("/user/bio", { newBio: newBio })
|
||||||
.then(() => {
|
.then(() => {
|
||||||
if (user) {
|
if (user) {
|
||||||
@@ -66,7 +66,7 @@
|
|||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
notify({
|
notify({
|
||||||
id: nid,
|
id: nid,
|
||||||
text: err?.response?.data?.error ?? "Failed to update bio",
|
text: ReqerError.getMsg(err, "Failed to update bio"),
|
||||||
type: "error",
|
type: "error",
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -79,19 +79,13 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const nid = notify({ text: "Uploading avatar", type: "loading" });
|
const nid = notify({ text: "Uploading avatar", type: "loading" });
|
||||||
axios
|
const fd = new FormData();
|
||||||
.postForm(
|
fd.append("avatar", files[0]);
|
||||||
"/user/avatar",
|
req
|
||||||
{ avatar: files[0] },
|
.post<Image>("/user/avatar", fd)
|
||||||
{
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "multipart/form-data",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.then((r) => {
|
.then((r) => {
|
||||||
if (user) {
|
if (user) {
|
||||||
user.avatar = r.data as Image;
|
user.avatar = r;
|
||||||
notify({ id: nid, text: "Avatar Uploaded", type: "success" });
|
notify({ id: nid, text: "Avatar Uploaded", type: "success" });
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -99,7 +93,7 @@
|
|||||||
console.error("uploading avatar failed", err);
|
console.error("uploading avatar failed", err);
|
||||||
notify({
|
notify({
|
||||||
id: nid,
|
id: nid,
|
||||||
text: err?.response?.data?.error ?? "Failed to upload avatar",
|
text: ReqerError.getMsg(err, "Failed to upload avatar"),
|
||||||
type: "error",
|
type: "error",
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Modal from "@/lib/Modal.svelte";
|
import Modal from "@/lib/Modal.svelte";
|
||||||
|
import { req } from "@/lib/util/api";
|
||||||
import { notify } from "@/lib/util/notify";
|
import { notify } from "@/lib/util/notify";
|
||||||
import axios from "axios";
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
@@ -13,9 +13,9 @@
|
|||||||
const nid = notify({ text: "Exporting", type: "loading" });
|
const nid = notify({ text: "Exporting", type: "loading" });
|
||||||
try {
|
try {
|
||||||
// We re-fetch, to ensure data we export is up to date.
|
// We re-fetch, to ensure data we export is up to date.
|
||||||
const r = await axios.get("/watched");
|
const r = await req.get<any>("/watched");
|
||||||
console.log(r.data);
|
console.log(r);
|
||||||
if (!r.data || r.data?.length <= 0) {
|
if (!r || r?.length <= 0) {
|
||||||
notify({
|
notify({
|
||||||
id: nid,
|
id: nid,
|
||||||
text: "Can't export an empty watch list!",
|
text: "Can't export an empty watch list!",
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const file = new Blob([JSON.stringify(r.data, undefined, 2)], {
|
const file = new Blob([JSON.stringify(r, undefined, 2)], {
|
||||||
type: "application/json",
|
type: "application/json",
|
||||||
});
|
});
|
||||||
const a = document.createElement("a");
|
const a = document.createElement("a");
|
||||||
|
|||||||
@@ -11,9 +11,8 @@
|
|||||||
type GetJobResponse,
|
type GetJobResponse,
|
||||||
type JobCreatedResponse,
|
type JobCreatedResponse,
|
||||||
} from "@/types";
|
} from "@/types";
|
||||||
import axios from "axios";
|
|
||||||
import { onDestroy, onMount } from "svelte";
|
import { onDestroy, onMount } from "svelte";
|
||||||
import { store } from "@/store.svelte";
|
import { req } from "@/lib/util/api";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
type?: "jellyfin" | "plex";
|
type?: "jellyfin" | "plex";
|
||||||
@@ -30,16 +29,16 @@
|
|||||||
|
|
||||||
async function startSync() {
|
async function startSync() {
|
||||||
try {
|
try {
|
||||||
const r = await axios.get<JobCreatedResponse>(
|
const r = await req.get<JobCreatedResponse>(
|
||||||
type === "jellyfin" ? "/jellyfin/sync" : "/plex/sync",
|
type === "jellyfin" ? "/jellyfin/sync" : "/plex/sync",
|
||||||
);
|
);
|
||||||
console.log("startSync: Response:", r.data);
|
console.log("startSync: Response:", r);
|
||||||
if (!r.data.jobId) {
|
if (!r.jobId) {
|
||||||
step = "errored";
|
step = "errored";
|
||||||
console.error("startSync: No jobId returned!");
|
console.error("startSync: No jobId returned!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
jobId = r.data.jobId;
|
jobId = r.jobId;
|
||||||
step = "job-running";
|
step = "job-running";
|
||||||
startJobWatcher();
|
startJobWatcher();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -61,13 +60,13 @@
|
|||||||
let seqfailedJobReqs = 0;
|
let seqfailedJobReqs = 0;
|
||||||
while (step === "job-running") {
|
while (step === "job-running") {
|
||||||
try {
|
try {
|
||||||
const r = await axios.get<GetJobResponse>(`/job/${jobId}`);
|
const r = await req.get<GetJobResponse>(`/job/${jobId}`);
|
||||||
console.log("jobWatcher: Got job data:", r.data);
|
console.log("jobWatcher: Got job data:", r);
|
||||||
latestJobStatus = r.data;
|
latestJobStatus = r;
|
||||||
currentTask = r.data?.currentTask;
|
currentTask = r?.currentTask;
|
||||||
if (r.data?.status === JobStatus.DONE) {
|
if (r?.status === JobStatus.DONE) {
|
||||||
step = "done";
|
step = "done";
|
||||||
} else if (r.data?.status === JobStatus.CANCELLED) {
|
} else if (r?.status === JobStatus.CANCELLED) {
|
||||||
step = "errored";
|
step = "errored";
|
||||||
}
|
}
|
||||||
// If we get here without erroring, we can reset it to 0.
|
// If we get here without erroring, we can reset it to 0.
|
||||||
@@ -92,31 +91,6 @@
|
|||||||
}
|
}
|
||||||
await new Promise((r) => setTimeout(r, 1000));
|
await new Promise((r) => setTimeout(r, 1000));
|
||||||
}
|
}
|
||||||
if (step !== "modal-closing") {
|
|
||||||
// Update our watched list
|
|
||||||
const nid = notify({
|
|
||||||
text: "Fetching updated watched list.",
|
|
||||||
type: "loading",
|
|
||||||
});
|
|
||||||
try {
|
|
||||||
const w = await axios.get("/watched");
|
|
||||||
if (w?.data?.length > 0) {
|
|
||||||
store.watchedList = w.data;
|
|
||||||
}
|
|
||||||
notify({
|
|
||||||
id: nid,
|
|
||||||
text: "Fetched updated watched list.",
|
|
||||||
type: "success",
|
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
console.error("jobWatcher: Getting updated watched list failed!", err);
|
|
||||||
notify({
|
|
||||||
id: nid,
|
|
||||||
text: "Getting updated watched list failed!",
|
|
||||||
type: "error",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function modalClose() {
|
function modalClose() {
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { goto } from "$app/navigation";
|
import { goto } from "$app/navigation";
|
||||||
|
import { req } from "@/lib/util/api";
|
||||||
import { notify } from "@/lib/util/notify";
|
import { notify } from "@/lib/util/notify";
|
||||||
import { store } from "@/store.svelte";
|
import { store } from "@/store.svelte";
|
||||||
import { UserPermission } from "@/types";
|
import { UserPermission } from "@/types";
|
||||||
import axios from "axios";
|
|
||||||
|
|
||||||
let page = $state(0);
|
let page = $state(0);
|
||||||
let adminToken: string | undefined = $state();
|
let adminToken: string | undefined = $state();
|
||||||
|
|
||||||
function generateAdminToken() {
|
function generateAdminToken() {
|
||||||
axios
|
req
|
||||||
.get("/auth/admin_token")
|
.get("/auth/admin_token")
|
||||||
.then(() => {
|
.then(() => {
|
||||||
page = 1;
|
page = 1;
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
console.error("useAdminToken: No admin token provided!");
|
console.error("useAdminToken: No admin token provided!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
axios
|
req
|
||||||
.post("/auth/admin_token", { token: adminToken })
|
.post("/auth/admin_token", { token: adminToken })
|
||||||
.then(() => {
|
.then(() => {
|
||||||
notify({ type: "success", text: "You now have admin!" });
|
notify({ type: "success", text: "You now have admin!" });
|
||||||
@@ -35,10 +35,7 @@
|
|||||||
goto("/");
|
goto("/");
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.error(
|
console.error("Failed to use admin token", err);
|
||||||
"Failed to use admin token",
|
|
||||||
err?.response?.data?.error || err,
|
|
||||||
);
|
|
||||||
notify({ type: "error", text: "Failed to use admin token!" });
|
notify({ type: "error", text: "Failed to use admin token!" });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { page } from "$app/state";
|
import { page } from "$app/state";
|
||||||
import { afterNavigate, goto } from "$app/navigation";
|
import { afterNavigate, goto } from "$app/navigation";
|
||||||
import axios, { type GenericAbortSignal } from "axios";
|
import { req } from "@/lib/util/api.js";
|
||||||
import Poster from "@/lib/poster/Poster.svelte";
|
import Poster from "@/lib/poster/Poster.svelte";
|
||||||
import PosterList from "@/lib/poster/PosterList.svelte";
|
import PosterList from "@/lib/poster/PosterList.svelte";
|
||||||
import { store } from "@/store.svelte.js";
|
import { store } from "@/store.svelte.js";
|
||||||
@@ -11,6 +11,7 @@
|
|||||||
MediaTypeE,
|
MediaTypeE,
|
||||||
SearchType,
|
SearchType,
|
||||||
type Media,
|
type Media,
|
||||||
|
type PaginationResponse,
|
||||||
type PublicUser,
|
type PublicUser,
|
||||||
type SearchRequest,
|
type SearchRequest,
|
||||||
type SearchResponseMeta,
|
type SearchResponseMeta,
|
||||||
@@ -55,7 +56,7 @@
|
|||||||
preferMyList: preferMyList,
|
preferMyList: preferMyList,
|
||||||
});
|
});
|
||||||
|
|
||||||
async function load(signal: GenericAbortSignal) {
|
async function load(signal: AbortSignal) {
|
||||||
console.debug("load: loadParams:", nextLoadParams);
|
console.debug("load: loadParams:", nextLoadParams);
|
||||||
if (nextLoadParams.page === dataLoader.state.page) {
|
if (nextLoadParams.page === dataLoader.state.page) {
|
||||||
console.warn("load: Already on this page, not loading it again!");
|
console.warn("load: Already on this page, not loading it again!");
|
||||||
@@ -65,10 +66,13 @@
|
|||||||
console.warn("load: There is no search query!");
|
console.warn("load: There is no search query!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const r = await axios.get(`/search`, {
|
const r = await req.get<PaginationResponse<Media, SearchResponseMeta>>(
|
||||||
params: nextLoadParams,
|
`/search`,
|
||||||
signal,
|
{
|
||||||
});
|
params: nextLoadParams,
|
||||||
|
signal,
|
||||||
|
},
|
||||||
|
);
|
||||||
scroll.dataLoaded();
|
scroll.dataLoaded();
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@@ -95,8 +99,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function searchUsers(query: string) {
|
async function searchUsers(query: string) {
|
||||||
return (await axios.get(`/user/search`, { params: { q: query } }))
|
return await req.get<PublicUser[]>(`/user/search`, {
|
||||||
.data as PublicUser[];
|
params: { q: query },
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
|
|||||||
@@ -8,13 +8,12 @@
|
|||||||
ServerConfig,
|
ServerConfig,
|
||||||
SonarrSettings,
|
SonarrSettings,
|
||||||
} from "@/types";
|
} from "@/types";
|
||||||
import axios from "axios";
|
|
||||||
import SonarrModal from "./modals/SonarrModal.svelte";
|
import SonarrModal from "./modals/SonarrModal.svelte";
|
||||||
import SettingsList from "@/lib/settings/SettingsList.svelte";
|
import SettingsList from "@/lib/settings/SettingsList.svelte";
|
||||||
import Setting from "@/lib/settings/Setting.svelte";
|
import Setting from "@/lib/settings/Setting.svelte";
|
||||||
import SettingButton from "@/lib/settings/SettingButton.svelte";
|
import SettingButton from "@/lib/settings/SettingButton.svelte";
|
||||||
import RadarrModal from "./modals/RadarrModal.svelte";
|
import RadarrModal from "./modals/RadarrModal.svelte";
|
||||||
import { getServerFeatures } from "@/lib/util/api";
|
import { getServerFeatures, req } from "@/lib/util/api";
|
||||||
import Stats from "@/lib/stats/Stats.svelte";
|
import Stats from "@/lib/stats/Stats.svelte";
|
||||||
import Error from "@/lib/Error.svelte";
|
import Error from "@/lib/Error.svelte";
|
||||||
import Stat from "@/lib/stats/Stat.svelte";
|
import Stat from "@/lib/stats/Stat.svelte";
|
||||||
@@ -44,7 +43,7 @@
|
|||||||
let useEmbyDisabled = $state(false);
|
let useEmbyDisabled = $state(false);
|
||||||
|
|
||||||
async function getServerConfig() {
|
async function getServerConfig() {
|
||||||
serverConfig = (await axios.get(`/server/config`)).data as ServerConfig;
|
serverConfig = await req.get<ServerConfig>(`/server/config`);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function updateServerConfig<K extends keyof ServerConfig>(
|
export function updateServerConfig<K extends keyof ServerConfig>(
|
||||||
@@ -64,13 +63,13 @@
|
|||||||
if (name === "PLEX_HOST") {
|
if (name === "PLEX_HOST") {
|
||||||
ep = "/server/config/plex_host";
|
ep = "/server/config/plex_host";
|
||||||
}
|
}
|
||||||
axios
|
req
|
||||||
.post(ep, { key: name, value: value })
|
.postWhole<any>(ep, { key: name, value: value })
|
||||||
.then((r) => {
|
.then((r) => {
|
||||||
if (r.status === 200) {
|
if (r.status === 200) {
|
||||||
serverConfig![name] = value;
|
serverConfig![name] = value;
|
||||||
notify({ id: nid, type: "success", text: "Updated" });
|
notify({ id: nid, type: "success", text: "Updated" });
|
||||||
if (typeof done !== "undefined") done(r?.data);
|
if (typeof done !== "undefined") done(r?.body);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
@@ -93,7 +92,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function getServerStats() {
|
async function getServerStats() {
|
||||||
return (await axios.get("/server/stats")).data as ServerStats;
|
return await req.get<ServerStats>("/server/stats");
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,8 @@
|
|||||||
RadarrSettings,
|
RadarrSettings,
|
||||||
RadarrTestResponse,
|
RadarrTestResponse,
|
||||||
} from "@/types";
|
} from "@/types";
|
||||||
import axios from "axios";
|
import { req } from "@/lib/util/api";
|
||||||
|
import { ReqerError } from "@/lib/util/fetch";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
servarr: RadarrSettings;
|
servarr: RadarrSettings;
|
||||||
@@ -22,7 +23,7 @@
|
|||||||
|
|
||||||
let { servarr = $bindable(), isEditing, onClose }: Props = $props();
|
let { servarr = $bindable(), isEditing, onClose }: Props = $props();
|
||||||
|
|
||||||
let error: string = $state();
|
let error: string | undefined = $state();
|
||||||
let formDisabled = $state(false);
|
let formDisabled = $state(false);
|
||||||
|
|
||||||
let qualityProfiles: DropDownItem[] = $state([]);
|
let qualityProfiles: DropDownItem[] = $state([]);
|
||||||
@@ -42,14 +43,14 @@
|
|||||||
async function getSettingsData() {
|
async function getSettingsData() {
|
||||||
try {
|
try {
|
||||||
formDisabled = true;
|
formDisabled = true;
|
||||||
const res = await axios.post<RadarrTestResponse>("/arr/rad/test", {
|
const res = await req.post<RadarrTestResponse>("/arr/rad/test", {
|
||||||
host: servarr.host,
|
host: servarr.host,
|
||||||
key: servarr.key,
|
key: servarr.key,
|
||||||
});
|
});
|
||||||
qualityProfiles = res.data.qualityProfiles.map((d) => {
|
qualityProfiles = res.qualityProfiles.map((d) => {
|
||||||
return { id: d.id, value: d.name };
|
return { id: d.id, value: d.name };
|
||||||
});
|
});
|
||||||
rootFolders = res.data.rootFolders.map((d) => {
|
rootFolders = res.rootFolders.map((d) => {
|
||||||
return { id: d.id, value: d.path };
|
return { id: d.id, value: d.path };
|
||||||
});
|
});
|
||||||
formDisabled = false;
|
formDisabled = false;
|
||||||
@@ -91,43 +92,33 @@
|
|||||||
if (!error) {
|
if (!error) {
|
||||||
console.log(servarr);
|
console.log(servarr);
|
||||||
try {
|
try {
|
||||||
const res = await axios.post(
|
await req.post(`/arr/rad/${isEditing ? "edit" : "add"}`, servarr);
|
||||||
`/arr/rad/${isEditing ? "edit" : "add"}`,
|
notify({
|
||||||
servarr,
|
type: "success",
|
||||||
);
|
text: isEditing ? "Changes saved!" : "Server added successfully!",
|
||||||
if (res.status === 200) {
|
});
|
||||||
notify({
|
onClose();
|
||||||
type: "success",
|
|
||||||
text: isEditing ? "Changes saved!" : "Server added successfully!",
|
|
||||||
});
|
|
||||||
onClose();
|
|
||||||
}
|
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
console.error("Failed to save server!", err);
|
console.error("Failed to save server!", err);
|
||||||
error = `Failed to ${isEditing ? "edit" : "add"}`;
|
error = ReqerError.getMsg(
|
||||||
if (err?.response?.data?.error) {
|
err,
|
||||||
error = err.response.data.error;
|
`Failed to ${isEditing ? "edit" : "add"}`,
|
||||||
}
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function remove() {
|
async function remove() {
|
||||||
try {
|
try {
|
||||||
const res = await axios.post(`/arr/rad/rm/${servarr.name}`);
|
await req.post(`/arr/rad/rm/${servarr.name}`);
|
||||||
if (res.status === 200) {
|
notify({
|
||||||
notify({
|
type: "success",
|
||||||
type: "success",
|
text: "Removed server",
|
||||||
text: "Removed server",
|
});
|
||||||
});
|
onClose();
|
||||||
onClose();
|
|
||||||
}
|
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
console.error("Failed to remove server!", err);
|
console.error("Failed to remove server!", err);
|
||||||
error = `Failed to remove`;
|
error = ReqerError.getMsg(err, "Failed to remove");
|
||||||
if (err?.response?.data?.error) {
|
|
||||||
error = err.response.data.error;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
run(() => {
|
run(() => {
|
||||||
|
|||||||
@@ -12,7 +12,8 @@
|
|||||||
SonarrSettings,
|
SonarrSettings,
|
||||||
SonarrTestResponse,
|
SonarrTestResponse,
|
||||||
} from "@/types";
|
} from "@/types";
|
||||||
import axios from "axios";
|
import { req } from "@/lib/util/api";
|
||||||
|
import { ReqerError } from "@/lib/util/fetch";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
servarr: SonarrSettings;
|
servarr: SonarrSettings;
|
||||||
@@ -44,17 +45,17 @@
|
|||||||
async function getSettingsData() {
|
async function getSettingsData() {
|
||||||
try {
|
try {
|
||||||
formDisabled = true;
|
formDisabled = true;
|
||||||
const res = await axios.post<SonarrTestResponse>("/arr/son/test", {
|
const res = await req.post<SonarrTestResponse>("/arr/son/test", {
|
||||||
host: servarr.host,
|
host: servarr.host,
|
||||||
key: servarr.key,
|
key: servarr.key,
|
||||||
});
|
});
|
||||||
qualityProfiles = res.data.qualityProfiles.map((d) => {
|
qualityProfiles = res.qualityProfiles.map((d) => {
|
||||||
return { id: d.id, value: d.name };
|
return { id: d.id, value: d.name };
|
||||||
});
|
});
|
||||||
languageProfiles = res.data.languageProfiles.map((d) => {
|
languageProfiles = res.languageProfiles.map((d) => {
|
||||||
return { id: d.id, value: d.name };
|
return { id: d.id, value: d.name };
|
||||||
});
|
});
|
||||||
rootFolders = res.data.rootFolders.map((d) => {
|
rootFolders = res.rootFolders.map((d) => {
|
||||||
return { id: d.id, value: d.path };
|
return { id: d.id, value: d.path };
|
||||||
});
|
});
|
||||||
formDisabled = false;
|
formDisabled = false;
|
||||||
@@ -99,43 +100,33 @@
|
|||||||
if (!error) {
|
if (!error) {
|
||||||
console.log(servarr);
|
console.log(servarr);
|
||||||
try {
|
try {
|
||||||
const res = await axios.post(
|
await req.post(`/arr/son/${isEditing ? "edit" : "add"}`, servarr);
|
||||||
`/arr/son/${isEditing ? "edit" : "add"}`,
|
notify({
|
||||||
servarr,
|
type: "success",
|
||||||
);
|
text: isEditing ? "Changes saved!" : "Server added successfully!",
|
||||||
if (res.status === 200) {
|
});
|
||||||
notify({
|
onClose();
|
||||||
type: "success",
|
|
||||||
text: isEditing ? "Changes saved!" : "Server added successfully!",
|
|
||||||
});
|
|
||||||
onClose();
|
|
||||||
}
|
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
console.error("Failed to save server!", err);
|
console.error("Failed to save server!", err);
|
||||||
error = `Failed to ${isEditing ? "edit" : "add"}`;
|
error = ReqerError.getMsg(
|
||||||
if (err?.response?.data?.error) {
|
err,
|
||||||
error = err.response.data.error;
|
`Failed to ${isEditing ? "edit" : "add"}`,
|
||||||
}
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function remove() {
|
async function remove() {
|
||||||
try {
|
try {
|
||||||
const res = await axios.post(`/arr/son/rm/${servarr.name}`);
|
await req.post(`/arr/son/rm/${servarr.name}`);
|
||||||
if (res.status === 200) {
|
notify({
|
||||||
notify({
|
type: "success",
|
||||||
type: "success",
|
text: "Removed server",
|
||||||
text: "Removed server",
|
});
|
||||||
});
|
onClose();
|
||||||
onClose();
|
|
||||||
}
|
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
console.error("Failed to remove server!", err);
|
console.error("Failed to remove server!", err);
|
||||||
error = `Failed to remove`;
|
error = ReqerError.getMsg(err, "Failed to remove");
|
||||||
if (err?.response?.data?.error) {
|
|
||||||
error = err.response.data.error;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
run(() => {
|
run(() => {
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { run } from "svelte/legacy";
|
|
||||||
|
|
||||||
import Modal from "@/lib/Modal.svelte";
|
import Modal from "@/lib/Modal.svelte";
|
||||||
import Spinner from "@/lib/Spinner.svelte";
|
import Spinner from "@/lib/Spinner.svelte";
|
||||||
import Setting from "@/lib/settings/Setting.svelte";
|
import Setting from "@/lib/settings/Setting.svelte";
|
||||||
@@ -8,7 +6,7 @@
|
|||||||
import { toRelativeTime } from "@/lib/util/helpers";
|
import { toRelativeTime } from "@/lib/util/helpers";
|
||||||
import { notify } from "@/lib/util/notify";
|
import { notify } from "@/lib/util/notify";
|
||||||
import type { AllTasksResponse } from "@/types";
|
import type { AllTasksResponse } from "@/types";
|
||||||
import axios from "axios";
|
import { req } from "@/lib/util/api";
|
||||||
import { onMount } from "svelte";
|
import { onMount } from "svelte";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@@ -23,8 +21,8 @@
|
|||||||
|
|
||||||
async function getAllTasks() {
|
async function getAllTasks() {
|
||||||
try {
|
try {
|
||||||
const res = await axios.get<AllTasksResponse[]>("/task/");
|
const res = await req.get<AllTasksResponse[]>("/task/");
|
||||||
taskSchedule = res.data?.sort((a, b) => {
|
taskSchedule = res?.sort((a, b) => {
|
||||||
if (a.name < b.name) {
|
if (a.name < b.name) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -47,7 +45,7 @@
|
|||||||
const nid = notify({ type: "loading", text: "Updating.." });
|
const nid = notify({ type: "loading", text: "Updating.." });
|
||||||
try {
|
try {
|
||||||
formDisabled = true;
|
formDisabled = true;
|
||||||
const res = await axios.put(`/task/${name}`, { seconds });
|
const res = await req.putWhole(`/task/${name}`, { seconds });
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
notify({ id: nid, type: "success", text: "Schedule updated." });
|
notify({ id: nid, type: "success", text: "Schedule updated." });
|
||||||
getAllTasks();
|
getAllTasks();
|
||||||
|
|||||||
@@ -5,9 +5,9 @@
|
|||||||
import Spinner from "@/lib/Spinner.svelte";
|
import Spinner from "@/lib/Spinner.svelte";
|
||||||
import Setting from "@/lib/settings/Setting.svelte";
|
import Setting from "@/lib/settings/Setting.svelte";
|
||||||
import SettingsList from "@/lib/settings/SettingsList.svelte";
|
import SettingsList from "@/lib/settings/SettingsList.svelte";
|
||||||
|
import { req } from "@/lib/util/api";
|
||||||
import { notify } from "@/lib/util/notify";
|
import { notify } from "@/lib/util/notify";
|
||||||
import type { ServerConfigByName, TrustedHeaderAuthSetting } from "@/types";
|
import type { ServerConfigByName, TrustedHeaderAuthSetting } from "@/types";
|
||||||
import axios from "axios";
|
|
||||||
import { onMount } from "svelte";
|
import { onMount } from "svelte";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@@ -29,13 +29,13 @@
|
|||||||
async function getHeaderCfg() {
|
async function getHeaderCfg() {
|
||||||
try {
|
try {
|
||||||
loadingCfg = true;
|
loadingCfg = true;
|
||||||
const res = await axios.get<ServerConfigByName<TrustedHeaderAuthSetting>>(
|
const res = await req.get<ServerConfigByName<TrustedHeaderAuthSetting>>(
|
||||||
"/server/config",
|
"/server/config",
|
||||||
{
|
{
|
||||||
params: { s: "HEADER_AUTH" },
|
params: { s: "HEADER_AUTH" },
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
headerCfg = res.data.value;
|
headerCfg = res.value;
|
||||||
loadingCfg = false;
|
loadingCfg = false;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("getHeaderCfg failed!", err);
|
console.error("getHeaderCfg failed!", err);
|
||||||
@@ -53,7 +53,7 @@
|
|||||||
text: "Saving..",
|
text: "Saving..",
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
await axios.post("/server/config", headerCfg, {
|
await req.post("/server/config", headerCfg, {
|
||||||
params: { s: "HEADER_AUTH" },
|
params: { s: "HEADER_AUTH" },
|
||||||
});
|
});
|
||||||
notify({
|
notify({
|
||||||
|
|||||||
@@ -2,9 +2,10 @@
|
|||||||
import Modal from "@/lib/Modal.svelte";
|
import Modal from "@/lib/Modal.svelte";
|
||||||
import Setting from "@/lib/settings/Setting.svelte";
|
import Setting from "@/lib/settings/Setting.svelte";
|
||||||
import SettingsList from "@/lib/settings/SettingsList.svelte";
|
import SettingsList from "@/lib/settings/SettingsList.svelte";
|
||||||
|
import { req } from "@/lib/util/api";
|
||||||
|
import { ReqerError } from "@/lib/util/fetch";
|
||||||
import { notify } from "@/lib/util/notify";
|
import { notify } from "@/lib/util/notify";
|
||||||
import type { TwitchSettings } from "@/types";
|
import type { TwitchSettings } from "@/types";
|
||||||
import axios from "axios";
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
cfg?: TwitchSettings;
|
cfg?: TwitchSettings;
|
||||||
@@ -36,20 +37,15 @@
|
|||||||
// if no error set from checkForm func, continue
|
// if no error set from checkForm func, continue
|
||||||
if (!error) {
|
if (!error) {
|
||||||
try {
|
try {
|
||||||
const res = await axios.post(`/game/config`, cfg);
|
await req.post(`/game/config`, cfg);
|
||||||
if (res.status === 200) {
|
notify({
|
||||||
notify({
|
type: "success",
|
||||||
type: "success",
|
text: "Changes saved!",
|
||||||
text: "Changes saved!",
|
});
|
||||||
});
|
onClose();
|
||||||
onClose();
|
|
||||||
}
|
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
console.error("Failed to save twitch cfg!", err);
|
console.error("Failed to save twitch cfg!", err);
|
||||||
error = `Failed to save`;
|
error = ReqerError.getMsg(err, "Failed to save");
|
||||||
if (err?.response?.data?.error) {
|
|
||||||
error = err.response.data.error;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,13 +8,13 @@
|
|||||||
import Spinner from "@/lib/Spinner.svelte";
|
import Spinner from "@/lib/Spinner.svelte";
|
||||||
import CreateTagModal from "@/lib/tag/CreateTagModal.svelte";
|
import CreateTagModal from "@/lib/tag/CreateTagModal.svelte";
|
||||||
import Tag from "@/lib/tag/Tag.svelte";
|
import Tag from "@/lib/tag/Tag.svelte";
|
||||||
|
import { req } from "@/lib/util/api";
|
||||||
import infScroll from "@/lib/util/infScroll";
|
import infScroll from "@/lib/util/infScroll";
|
||||||
import paginatedLoader, {
|
import paginatedLoader, {
|
||||||
PaginatedLoaderRunFnAction,
|
PaginatedLoaderRunFnAction,
|
||||||
} from "@/lib/util/paginatedLoader.svelte";
|
} from "@/lib/util/paginatedLoader.svelte";
|
||||||
import { clearActiveFilters, store } from "@/store.svelte.js";
|
import { clearActiveFilters, store } from "@/store.svelte.js";
|
||||||
import type { Media } from "@/types";
|
import type { Media, PaginationResponse } from "@/types";
|
||||||
import axios, { type GenericAbortSignal } from "axios";
|
|
||||||
import { onDestroy, untrack } from "svelte";
|
import { onDestroy, untrack } from "svelte";
|
||||||
|
|
||||||
let meta = $derived.by(() => {
|
let meta = $derived.by(() => {
|
||||||
@@ -36,7 +36,7 @@
|
|||||||
...store.sortAndFiltersForQueryParams,
|
...store.sortAndFiltersForQueryParams,
|
||||||
});
|
});
|
||||||
|
|
||||||
async function load(signal: GenericAbortSignal) {
|
async function load(signal: AbortSignal) {
|
||||||
console.debug("load: loadParams:", nextLoadParams);
|
console.debug("load: loadParams:", nextLoadParams);
|
||||||
if (nextLoadParams.page === dataLoader.state.page) {
|
if (nextLoadParams.page === dataLoader.state.page) {
|
||||||
console.warn("load: Already on this page, not loading it again!");
|
console.warn("load: Already on this page, not loading it again!");
|
||||||
@@ -46,10 +46,13 @@
|
|||||||
console.warn("load: Missing tag id!");
|
console.warn("load: Missing tag id!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const r = await axios.get(`/tag/${meta.tagId}/watched`, {
|
const r = await req.get<PaginationResponse<Media, undefined>>(
|
||||||
params: nextLoadParams,
|
`/tag/${meta.tagId}/watched`,
|
||||||
signal,
|
{
|
||||||
});
|
params: nextLoadParams,
|
||||||
|
signal,
|
||||||
|
},
|
||||||
|
);
|
||||||
scroll.dataLoaded();
|
scroll.dataLoaded();
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
import Title from "@/lib/content/Title.svelte";
|
import Title from "@/lib/content/Title.svelte";
|
||||||
import {
|
import {
|
||||||
contentExistsOnJellyfin,
|
contentExistsOnJellyfin,
|
||||||
removeWatched,
|
req,
|
||||||
updateWatched,
|
updateWatched,
|
||||||
type UpdateWatchedOptions,
|
type UpdateWatchedOptions,
|
||||||
} from "@/lib/util/api";
|
} from "@/lib/util/api";
|
||||||
@@ -23,7 +23,6 @@
|
|||||||
TMDBContentCreditsCrew,
|
TMDBContentCreditsCrew,
|
||||||
WatchedStatus,
|
WatchedStatus,
|
||||||
} from "@/types";
|
} from "@/types";
|
||||||
import axios from "axios";
|
|
||||||
import RequestShow from "@/lib/request/RequestShow.svelte";
|
import RequestShow from "@/lib/request/RequestShow.svelte";
|
||||||
import FollowedThoughts from "@/lib/content/FollowedThoughts.svelte";
|
import FollowedThoughts from "@/lib/content/FollowedThoughts.svelte";
|
||||||
import ArrRequestButton from "@/lib/request/ArrRequestButton.svelte";
|
import ArrRequestButton from "@/lib/request/ArrRequestButton.svelte";
|
||||||
@@ -57,11 +56,9 @@
|
|||||||
if (!data.tvId) {
|
if (!data.tvId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const resp = (
|
const resp = await req.get<Media>(`/content/tv/${data.tvId}`, {
|
||||||
await axios.get(`/content/tv/${data.tvId}`, {
|
params: { region: store.userSettings?.country },
|
||||||
params: { region: store.userSettings?.country },
|
});
|
||||||
})
|
|
||||||
).data as Media;
|
|
||||||
if (resp) {
|
if (resp) {
|
||||||
if (resp.name && resp.ids.tmdb) {
|
if (resp.name && resp.ids.tmdb) {
|
||||||
contentExistsOnJellyfin("tv", resp.name, resp.ids.tmdb).then(
|
contentExistsOnJellyfin("tv", resp.name, resp.ids.tmdb).then(
|
||||||
@@ -84,8 +81,9 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
async function getTvCredits() {
|
async function getTvCredits() {
|
||||||
const credits = (await axios.get(`/content/tv/${data.tvId}/credits`))
|
const credits = await req.get<
|
||||||
.data as TMDBContentCredits & { topCrew: TMDBContentCreditsCrew[] };
|
TMDBContentCredits & { topCrew: TMDBContentCreditsCrew[] }
|
||||||
|
>(`/content/tv/${data.tvId}/credits`);
|
||||||
if (credits.crew?.length > 0) {
|
if (credits.crew?.length > 0) {
|
||||||
credits.topCrew = getTopCrew(credits.crew);
|
credits.topCrew = getTopCrew(credits.crew);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,9 +3,10 @@
|
|||||||
import { page } from "$app/state";
|
import { page } from "$app/state";
|
||||||
import Icon from "@/lib/Icon.svelte";
|
import Icon from "@/lib/Icon.svelte";
|
||||||
import { type AvailableAuthProviders } from "@/types";
|
import { type AvailableAuthProviders } from "@/types";
|
||||||
import { noAuthAxios } from "@/lib/util/api";
|
import { noAuthReq } from "@/lib/util/api";
|
||||||
import { onMount } from "svelte";
|
import { onMount } from "svelte";
|
||||||
import { notify, unNotify } from "@/lib/util/notify";
|
import { notify, unNotify } from "@/lib/util/notify";
|
||||||
|
import { ReqerError } from "@/lib/util/fetch";
|
||||||
|
|
||||||
let error: string | undefined = $state();
|
let error: string | undefined = $state();
|
||||||
let login = $state(true);
|
let login = $state(true);
|
||||||
@@ -31,27 +32,46 @@
|
|||||||
noAuto = true;
|
noAuto = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
noAuthAxios.get<AvailableAuthProviders>("/auth/available").then((r) => {
|
processAvailableLoginMethods();
|
||||||
if (r?.data) {
|
|
||||||
if (r.data.isInSetup) {
|
|
||||||
console.log("Server is in setup.. navigating to web setup page.");
|
|
||||||
goto("/setup");
|
|
||||||
}
|
|
||||||
availableProviders = r.data.available;
|
|
||||||
apHeader = availableProviders?.includes("header");
|
|
||||||
apPlex = availableProviders?.includes("plex");
|
|
||||||
signupEnabled = r.data.signupEnabled;
|
|
||||||
useEmby = r.data.useEmby;
|
|
||||||
if (r.data.headerAuthAutoLogin && !noAuto) {
|
|
||||||
console.log(
|
|
||||||
"handling headerAuthAutoLogin.. calling proxyLogin automatically now.",
|
|
||||||
);
|
|
||||||
proxyLogin(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get and process available login methods.
|
||||||
|
*/
|
||||||
|
async function processAvailableLoginMethods() {
|
||||||
|
let r: AvailableAuthProviders;
|
||||||
|
try {
|
||||||
|
r = await noAuthReq.get<AvailableAuthProviders>("/auth/available");
|
||||||
|
} catch {
|
||||||
|
notify({
|
||||||
|
type: "error",
|
||||||
|
time: 10000,
|
||||||
|
text: "Failed to get available login methods",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!r) {
|
||||||
|
console.log("AvailableAuth: no response data");
|
||||||
|
}
|
||||||
|
if (r.isInSetup) {
|
||||||
|
console.log(
|
||||||
|
"AvailableAuth: Server is in setup.. navigating to web setup page.",
|
||||||
|
);
|
||||||
|
goto("/setup");
|
||||||
|
}
|
||||||
|
availableProviders = r.available;
|
||||||
|
apHeader = availableProviders?.includes("header");
|
||||||
|
apPlex = availableProviders?.includes("plex");
|
||||||
|
signupEnabled = r.signupEnabled;
|
||||||
|
useEmby = r.useEmby;
|
||||||
|
if (r.headerAuthAutoLogin && !noAuto) {
|
||||||
|
console.log(
|
||||||
|
"AvailableAuth: handling headerAuthAutoLogin.. calling proxyLogin automatically now.",
|
||||||
|
);
|
||||||
|
proxyLogin(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function handleLogin(ev: SubmitEvent) {
|
function handleLogin(ev: SubmitEvent) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
const fd = new FormData(ev.target! as HTMLFormElement);
|
const fd = new FormData(ev.target! as HTMLFormElement);
|
||||||
@@ -69,15 +89,15 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
const nid = notify({ text: "Logging in", type: "loading" });
|
const nid = notify({ text: "Logging in", type: "loading" });
|
||||||
noAuthAxios
|
noAuthReq
|
||||||
.post(`/auth${login ? `/${customAuthEP}` : "/register"}`, {
|
.post(`/auth${login ? `/${customAuthEP}` : "/register"}`, {
|
||||||
username: user,
|
username: user,
|
||||||
password: pass,
|
password: pass,
|
||||||
})
|
})
|
||||||
.then((resp) => {
|
.then((resp: any) => {
|
||||||
if (resp.data?.token) {
|
if (resp?.token) {
|
||||||
console.log("Received token... logging in.");
|
console.log("Received token... logging in.");
|
||||||
localStorage.setItem("token", resp.data.token);
|
localStorage.setItem("token", resp.token);
|
||||||
if (useEmby) {
|
if (useEmby) {
|
||||||
localStorage.setItem("useEmby", "1");
|
localStorage.setItem("useEmby", "1");
|
||||||
} else {
|
} else {
|
||||||
@@ -88,11 +108,7 @@
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
if (err.response) {
|
error = ReqerError.getMsg(err, "Login failed");
|
||||||
error = err.response.data.error;
|
|
||||||
} else {
|
|
||||||
error = err.message;
|
|
||||||
}
|
|
||||||
unNotify(nid);
|
unNotify(nid);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -111,26 +127,22 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const nid = notify({ text: "Logging in", type: "loading" });
|
const nid = notify({ text: "Logging in", type: "loading" });
|
||||||
noAuthAxios
|
noAuthReq
|
||||||
.post("/auth/plex", {
|
.post("/auth/plex", {
|
||||||
token,
|
token,
|
||||||
clientIdentifier: p.clientId,
|
clientIdentifier: p.clientId,
|
||||||
})
|
})
|
||||||
.then((resp) => {
|
.then((resp: any) => {
|
||||||
if (resp.data?.token) {
|
if (resp?.token) {
|
||||||
console.log("Received token... logging in.");
|
console.log("Received token... logging in.");
|
||||||
localStorage.setItem("token", resp.data.token);
|
localStorage.setItem("token", resp.token);
|
||||||
goto("/");
|
goto("/");
|
||||||
notify({ id: nid, text: `Welcome!`, type: "success" });
|
notify({ id: nid, text: `Welcome!`, type: "success" });
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.error("plexLogin: Fail", err);
|
console.error("plexLogin: Fail", err);
|
||||||
if (err.response) {
|
error = ReqerError.getMsg(err, "Login failed");
|
||||||
error = err.response.data.error;
|
|
||||||
} else {
|
|
||||||
error = err.message;
|
|
||||||
}
|
|
||||||
notify({ id: nid, text: `Failed!`, type: "error" });
|
notify({ id: nid, text: `Failed!`, type: "error" });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -142,22 +154,18 @@
|
|||||||
|
|
||||||
function proxyLogin(auto = false) {
|
function proxyLogin(auto = false) {
|
||||||
const nid = notify({ text: "Logging in", type: "loading" });
|
const nid = notify({ text: "Logging in", type: "loading" });
|
||||||
noAuthAxios
|
noAuthReq
|
||||||
.post(`/auth/proxy`)
|
.post(`/auth/proxy`)
|
||||||
.then((resp) => {
|
.then((resp: any) => {
|
||||||
if (resp.data?.token) {
|
if (resp?.token) {
|
||||||
console.log("Received token... logging in.");
|
console.log("Received token... logging in.");
|
||||||
localStorage.setItem("token", resp.data.token);
|
localStorage.setItem("token", resp.token);
|
||||||
goto("/");
|
goto("/");
|
||||||
notify({ id: nid, text: `Welcome!`, type: "success" });
|
notify({ id: nid, text: `Welcome!`, type: "success" });
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
if (err.response) {
|
error = ReqerError.getMsg(err, "Login failed");
|
||||||
error = err.response.data.error;
|
|
||||||
} else {
|
|
||||||
error = err.message;
|
|
||||||
}
|
|
||||||
if (auto) {
|
if (auto) {
|
||||||
notify({
|
notify({
|
||||||
id: nid,
|
id: nid,
|
||||||
|
|||||||
@@ -1,22 +1,21 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { preventDefault } from "svelte/legacy";
|
|
||||||
|
|
||||||
import { goto } from "$app/navigation";
|
import { goto } from "$app/navigation";
|
||||||
import type { AvailableAuthProviders } from "@/types";
|
import type { AvailableAuthProviders } from "@/types";
|
||||||
import { noAuthAxios } from "@/lib/util/api";
|
|
||||||
import { onMount } from "svelte";
|
import { onMount } from "svelte";
|
||||||
import { notify, unNotify } from "@/lib/util/notify";
|
import { notify, unNotify } from "@/lib/util/notify";
|
||||||
|
import { noAuthReq } from "@/lib/util/api";
|
||||||
|
import { ReqerError } from "@/lib/util/fetch";
|
||||||
|
|
||||||
let error: string = $state();
|
let error: string | undefined = $state();
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
if (localStorage.getItem("token")) {
|
if (localStorage.getItem("token")) {
|
||||||
goto("/");
|
goto("/");
|
||||||
}
|
}
|
||||||
|
|
||||||
noAuthAxios.get<AvailableAuthProviders>("/auth/available").then((r) => {
|
noAuthReq.get<AvailableAuthProviders>("/auth/available").then((r) => {
|
||||||
if (r?.data) {
|
if (r) {
|
||||||
if (!r?.data?.isInSetup) {
|
if (!r.isInSetup) {
|
||||||
console.log("Server not in setup.. navigating to login page.");
|
console.log("Server not in setup.. navigating to login page.");
|
||||||
goto("/login");
|
goto("/login");
|
||||||
}
|
}
|
||||||
@@ -25,6 +24,7 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
function handleLogin(ev: SubmitEvent) {
|
function handleLogin(ev: SubmitEvent) {
|
||||||
|
ev.preventDefault();
|
||||||
const fd = new FormData(ev.target! as HTMLFormElement);
|
const fd = new FormData(ev.target! as HTMLFormElement);
|
||||||
const user = fd.get("username");
|
const user = fd.get("username");
|
||||||
const pass = fd.get("password");
|
const pass = fd.get("password");
|
||||||
@@ -35,25 +35,21 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
const nid = notify({ text: "Setting Up Admin User", type: "loading" });
|
const nid = notify({ text: "Setting Up Admin User", type: "loading" });
|
||||||
noAuthAxios
|
noAuthReq
|
||||||
.post("/setup/create_admin", {
|
.post<any>("/setup/create_admin", {
|
||||||
username: user,
|
username: user,
|
||||||
password: pass,
|
password: pass,
|
||||||
})
|
})
|
||||||
.then((resp) => {
|
.then((resp) => {
|
||||||
if (resp.data?.token) {
|
if (resp.token) {
|
||||||
console.log("Received token... logging in.");
|
console.log("Received token... logging in.");
|
||||||
localStorage.setItem("token", resp.data.token);
|
localStorage.setItem("token", resp.token);
|
||||||
goto("/");
|
goto("/");
|
||||||
notify({ id: nid, text: `Welcome ${user}!`, type: "success" });
|
notify({ id: nid, text: `Welcome ${user}!`, type: "success" });
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
if (err.response) {
|
error = ReqerError.getMsg(err, "Setting up user failed");
|
||||||
error = err.response.data.error;
|
|
||||||
} else {
|
|
||||||
error = err.message;
|
|
||||||
}
|
|
||||||
unNotify(nid);
|
unNotify(nid);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -74,7 +70,7 @@
|
|||||||
<span class="error">{error}!</span>
|
<span class="error">{error}!</span>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<form onsubmit={preventDefault(handleLogin)}>
|
<form onsubmit={handleLogin}>
|
||||||
<label for="username">Username</label>
|
<label for="username">Username</label>
|
||||||
<input type="text" name="username" placeholder="Username" />
|
<input type="text" name="username" placeholder="Username" />
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -131,7 +131,7 @@ export const store = {
|
|||||||
/**
|
/**
|
||||||
* Return our `activeSort` and `activeFilters` in an object
|
* Return our `activeSort` and `activeFilters` in an object
|
||||||
* that is in the correct format for our get watched page
|
* that is in the correct format for our get watched page
|
||||||
* requests (object that is given to axios for query params).
|
* http requests.
|
||||||
*/
|
*/
|
||||||
get sortAndFiltersForQueryParams() {
|
get sortAndFiltersForQueryParams() {
|
||||||
return _store.sortAndFiltersForQueryParams;
|
return _store.sortAndFiltersForQueryParams;
|
||||||
|
|||||||
Reference in New Issue
Block a user