Compare commits
18 Commits
dcpp-socke
...
vite-build
| Author | SHA1 | Date | |
|---|---|---|---|
| 7eb87b066f | |||
| 084ef3c07a | |||
| 020e5e9528 | |||
| a4adfd3e79 | |||
| 30ef01ff03 | |||
| 45bcb4102d | |||
| bcd53b3ad0 | |||
| f32feacca4 | |||
| 0b0f4681d4 | |||
| 8fb6118b50 | |||
| b12849efda | |||
| fb2c969c00 | |||
| b929840a96 | |||
| d437fddd1a | |||
| 8dd68e9d54 | |||
|
|
a8b52d0ac6 | ||
| 719ebe7c6e | |||
| df1fbc7dd3 |
17
.babelrc
17
.babelrc
@@ -1,17 +0,0 @@
|
|||||||
{
|
|
||||||
"presets": [
|
|
||||||
"@babel/preset-env",
|
|
||||||
"@babel/preset-react",
|
|
||||||
"@babel/preset-typescript"
|
|
||||||
],
|
|
||||||
"plugins": [
|
|
||||||
"@babel/transform-runtime",
|
|
||||||
"@babel/plugin-proposal-class-properties",
|
|
||||||
"@babel/plugin-syntax-top-level-await"
|
|
||||||
],
|
|
||||||
"env": {
|
|
||||||
"production": {
|
|
||||||
"presets": ["minify"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
1
funding.yml
Normal file
1
funding.yml
Normal file
@@ -0,0 +1 @@
|
|||||||
|
github: [rishighan]
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
<script type="module" src="/src/client/index.tsx"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
96
package.json
96
package.json
@@ -5,15 +5,10 @@
|
|||||||
"main": "server/index.js",
|
"main": "server/index.js",
|
||||||
"typings": "server/index.js",
|
"typings": "server/index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "webpack --mode production",
|
"build": "vite build",
|
||||||
"start": "npm run build && npm run server",
|
"dev": "rimraf dist && npm run build && vite",
|
||||||
"client": "webpack serve --mode development --devtool inline-source-map --hot",
|
"prod": "npm run build && vite",
|
||||||
"server": "tsc -p tsconfig.server.json && node server/",
|
"docs": "jsdoc -c jsdoc.json"
|
||||||
"dev": "concurrently \"nodemon\" \"npm run client\"",
|
|
||||||
"server-dev": "nodemon",
|
|
||||||
"docs": "jsdoc -c jsdoc.json",
|
|
||||||
"storybook": "start-storybook -p 6006",
|
|
||||||
"build-storybook": "build-storybook"
|
|
||||||
},
|
},
|
||||||
"author": "Rishi Ghan",
|
"author": "Rishi Ghan",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -24,53 +19,46 @@
|
|||||||
"@dnd-kit/sortable": "^5.0.0",
|
"@dnd-kit/sortable": "^5.0.0",
|
||||||
"@dnd-kit/utilities": "^3.2.0",
|
"@dnd-kit/utilities": "^3.2.0",
|
||||||
"@fortawesome/fontawesome-free": "^6.1.1",
|
"@fortawesome/fontawesome-free": "^6.1.1",
|
||||||
"@parcel/config-default": "^2.6.0",
|
|
||||||
"@redux-devtools/extension": "^3.2.2",
|
"@redux-devtools/extension": "^3.2.2",
|
||||||
|
"@rollup/plugin-node-resolve": "^15.0.1",
|
||||||
"@tanstack/react-table": "^8.5.11",
|
"@tanstack/react-table": "^8.5.11",
|
||||||
"@types/mime-types": "^2.1.0",
|
"@types/mime-types": "^2.1.0",
|
||||||
"@types/react": "^17.0.3",
|
"@types/react": "^17.0.3",
|
||||||
"@types/react-dom": "^17.0.2",
|
"@types/react-dom": "^17.0.2",
|
||||||
"@types/react-redux": "^7.1.16",
|
"@types/react-redux": "^7.1.16",
|
||||||
"@types/react-router-dom": "^5.1.7",
|
"@types/react-router-dom": "^5.1.7",
|
||||||
"@types/sharp": "^0.28.0",
|
|
||||||
"@types/socket.io": "^3.0.2",
|
"@types/socket.io": "^3.0.2",
|
||||||
"@types/socket.io-client": "^3.0.0",
|
"@types/socket.io-client": "^3.0.0",
|
||||||
"airdcpp-apisocket": "^2.4.4",
|
"@vitejs/plugin-react": "^3.1.0",
|
||||||
"array-sort-by": "^1.2.1",
|
"airdcpp-apisocket": "2.4.5-beta.1",
|
||||||
"axios": "^0.27.2",
|
"axios": "^0.27.2",
|
||||||
"axios-rate-limit": "^1.3.0",
|
"axios-rate-limit": "^1.3.0",
|
||||||
"axios-simple-cache-adapter": "^1.1.0",
|
"axios-simple-cache-adapter": "^1.1.0",
|
||||||
"babel-polyfill": "^6.26.0",
|
"babel-polyfill": "^6.26.0",
|
||||||
"babel-preset-minify": "^0.5.2",
|
"babel-preset-minify": "^0.5.2",
|
||||||
"better-docs": "^2.7.2",
|
"better-docs": "^2.7.2",
|
||||||
"comlink-loader": "^2.0.0",
|
|
||||||
"compromise": "^13.11.3",
|
|
||||||
"compromise-dates": "^2.2.1",
|
|
||||||
"compromise-numbers": "^1.4.0",
|
|
||||||
"compromise-sentences": "^0.3.0",
|
|
||||||
"date-fns": "^2.28.0",
|
"date-fns": "^2.28.0",
|
||||||
"dayjs": "^1.10.6",
|
"dayjs": "^1.10.6",
|
||||||
"ellipsize": "^0.1.0",
|
"ellipsize": "^0.1.0",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"fastest-validator": "^1.11.0",
|
|
||||||
"filename-parser": "^1.0.2",
|
"filename-parser": "^1.0.2",
|
||||||
"final-form": "^4.20.2",
|
"final-form": "^4.20.2",
|
||||||
"final-form-arrays": "^3.0.2",
|
"final-form-arrays": "^3.0.2",
|
||||||
"html-to-text": "^8.1.0",
|
"html-to-text": "^8.1.0",
|
||||||
"jsdoc": "^3.6.10",
|
"jsdoc": "^3.6.10",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"opds-extra": "^3.0.9",
|
"node-sass": "npm:sass",
|
||||||
"pretty-bytes": "^5.6.0",
|
"pretty-bytes": "^5.6.0",
|
||||||
"prop-types": "^15.8.1",
|
"prop-types": "^15.8.1",
|
||||||
"qs": "^6.10.5",
|
"qs": "^6.10.5",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-collapsible": "^2.9.0",
|
"react-collapsible": "^2.9.0",
|
||||||
"react-comic-viewer": "^0.4.0",
|
"react-comic-viewer": "^0.4.0",
|
||||||
"react-day-picker": "^8.0.6",
|
"react-day-picker": "^8.6.0",
|
||||||
"react-dom": "^18.1.0",
|
"react-dom": "^18.1.0",
|
||||||
"react-fast-compare": "^3.2.0",
|
"react-fast-compare": "^3.2.0",
|
||||||
"react-final-form": "^6.5.9",
|
"react-final-form": "^6.5.9",
|
||||||
"react-final-form-arrays": "^3.1.3",
|
"react-final-form-arrays": "^3.1.4",
|
||||||
"react-loader-spinner": "^4.0.0",
|
"react-loader-spinner": "^4.0.0",
|
||||||
"react-masonry-css": "^1.0.16",
|
"react-masonry-css": "^1.0.16",
|
||||||
"react-modal": "^3.15.1",
|
"react-modal": "^3.15.1",
|
||||||
@@ -78,21 +66,20 @@
|
|||||||
"react-router": "^6.2.2",
|
"react-router": "^6.2.2",
|
||||||
"react-router-dom": "^6.2.2",
|
"react-router-dom": "^6.2.2",
|
||||||
"react-select": "^5.3.2",
|
"react-select": "^5.3.2",
|
||||||
"react-select-async-paginate": "^0.6.1",
|
"react-select-async-paginate": "^0.7.2",
|
||||||
"react-slick": "^0.29.0",
|
"react-slick": "^0.29.0",
|
||||||
"react-sliding-pane": "^7.1.0",
|
"react-sliding-pane": "^7.1.0",
|
||||||
"react-stickynode": "^4.0.0",
|
"react-stickynode": "^4.1.0",
|
||||||
"react-textarea-autosize": "^8.3.4",
|
"react-textarea-autosize": "^8.3.4",
|
||||||
"reapop": "^4.0.5",
|
"reapop": "^4.2.1",
|
||||||
"redux-first-history": "^5.0.9",
|
"redux-first-history": "^5.1.1",
|
||||||
"redux-socket.io-middleware": "^1.0.4",
|
"redux-socket.io-middleware": "^1.0.4",
|
||||||
"redux-thunk": "^2.4.1",
|
"redux-thunk": "^2.4.2",
|
||||||
"sharp": "^0.30.5",
|
|
||||||
"slick-carousel": "^1.8.1",
|
"slick-carousel": "^1.8.1",
|
||||||
"socket.io-client": "^4.3.2",
|
"socket.io-client": "^4.3.2",
|
||||||
"styled-components": "^5.3.5",
|
"styled-components": "^5.3.5",
|
||||||
"threetwo-ui-typings": "^1.0.14",
|
"threetwo-ui-typings": "^1.0.14",
|
||||||
"voca": "^1.4.0",
|
"vite-plugin-html": "^3.2.0",
|
||||||
"websocket": "^1.0.34",
|
"websocket": "^1.0.34",
|
||||||
"ws": "^7.5.3",
|
"ws": "^7.5.3",
|
||||||
"xml2js": "^0.4.23",
|
"xml2js": "^0.4.23",
|
||||||
@@ -103,22 +90,9 @@
|
|||||||
"@babel/core": "^7.13.10",
|
"@babel/core": "^7.13.10",
|
||||||
"@babel/plugin-syntax-top-level-await": "^7.14.5",
|
"@babel/plugin-syntax-top-level-await": "^7.14.5",
|
||||||
"@babel/plugin-transform-runtime": "^7.13.15",
|
"@babel/plugin-transform-runtime": "^7.13.15",
|
||||||
"@babel/preset-env": "^7.13.10",
|
"@babel/preset-env": "^7.20.2",
|
||||||
"@babel/preset-react": "^7.12.13",
|
"@babel/preset-react": "^7.18.6",
|
||||||
"@babel/preset-typescript": "^7.13.0",
|
"@babel/preset-typescript": "^7.13.0",
|
||||||
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.7",
|
|
||||||
"@storybook/addon-actions": "^6.5.9",
|
|
||||||
"@storybook/addon-essentials": "^6.5.9",
|
|
||||||
"@storybook/addon-interactions": "^6.5.9",
|
|
||||||
"@storybook/addon-links": "^6.5.9",
|
|
||||||
"@storybook/builder-webpack4": "^6.5.9",
|
|
||||||
"@storybook/builder-webpack5": "^6.5.9",
|
|
||||||
"@storybook/manager-webpack4": "^6.5.9",
|
|
||||||
"@storybook/manager-webpack5": "^6.5.9",
|
|
||||||
"@storybook/preset-scss": "^1.0.3",
|
|
||||||
"@storybook/react": "^6.5.9",
|
|
||||||
"@storybook/testing-library": "^0.0.13",
|
|
||||||
"@teamsupercell/typings-for-css-modules-loader": "^2.5.1",
|
|
||||||
"@tsconfig/node14": "^1.0.0",
|
"@tsconfig/node14": "^1.0.0",
|
||||||
"@types/express": "^4.17.8",
|
"@types/express": "^4.17.8",
|
||||||
"@types/jest": "^26.0.20",
|
"@types/jest": "^26.0.20",
|
||||||
@@ -129,19 +103,11 @@
|
|||||||
"@types/react-redux": "^7.1.16",
|
"@types/react-redux": "^7.1.16",
|
||||||
"@typescript-eslint/eslint-plugin": "^4.17.0",
|
"@typescript-eslint/eslint-plugin": "^4.17.0",
|
||||||
"@typescript-eslint/parser": "^4.17.0",
|
"@typescript-eslint/parser": "^4.17.0",
|
||||||
"awesome-typescript-loader": "^5.2.1",
|
|
||||||
"babel-eslint": "^10.0.0",
|
"babel-eslint": "^10.0.0",
|
||||||
"babel-loader": "^8.2.2",
|
|
||||||
"babel-plugin-transform-class-properties": "^6.24.1",
|
|
||||||
"body-parser": "^1.19.0",
|
"body-parser": "^1.19.0",
|
||||||
"buffer": "^6.0.3",
|
"bulma": "^0.9.4",
|
||||||
"bulma": "^0.9.3",
|
|
||||||
"clean-webpack-plugin": "^1.0.0",
|
|
||||||
"comlink": "^4.3.0",
|
"comlink": "^4.3.0",
|
||||||
"compromise-strict": "^0.0.2",
|
|
||||||
"concurrently": "^4.0.0",
|
"concurrently": "^4.0.0",
|
||||||
"copy-webpack-plugin": "^9.0.1",
|
|
||||||
"css-loader": "^5.1.2",
|
|
||||||
"eslint": "^7.22.0",
|
"eslint": "^7.22.0",
|
||||||
"eslint-config-airbnb": "^18.2.1",
|
"eslint-config-airbnb": "^18.2.1",
|
||||||
"eslint-config-airbnb-base": "^14.2.1",
|
"eslint-config-airbnb-base": "^14.2.1",
|
||||||
@@ -152,34 +118,16 @@
|
|||||||
"eslint-plugin-prettier": "^3.3.1",
|
"eslint-plugin-prettier": "^3.3.1",
|
||||||
"eslint-plugin-react": "^7.22.0",
|
"eslint-plugin-react": "^7.22.0",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"file-loader": "^6.2.0",
|
|
||||||
"fs-extra": "^9.1.0",
|
|
||||||
"html-webpack-plugin": "^5.3.1",
|
|
||||||
"http-response-stream": "^1.0.9",
|
|
||||||
"image-webpack-loader": "^8.1.0",
|
|
||||||
"install": "^0.13.0",
|
"install": "^0.13.0",
|
||||||
"jest": "^26.6.3",
|
"jest": "^26.6.3",
|
||||||
"mini-css-extract-plugin": "^1.4.1",
|
|
||||||
"node-sass": "^7.0.1",
|
|
||||||
"nodemon": "^1.17.3",
|
"nodemon": "^1.17.3",
|
||||||
"npm": "^8.11.0",
|
"npm": "^8.11.0",
|
||||||
"prettier": "^2.2.1",
|
"prettier": "^2.2.1",
|
||||||
"react-refresh": "^0.14.0",
|
"react-refresh": "^0.14.0",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.3",
|
||||||
"sass-loader": "^11.0.1",
|
"sass": "^1.58.1",
|
||||||
"source-map-loader": "^0.2.4",
|
|
||||||
"string-similarity": "^4.0.4",
|
|
||||||
"style-loader": "^2.0.0",
|
|
||||||
"tslint": "^6.1.3",
|
"tslint": "^6.1.3",
|
||||||
"typescript": "^4.2.3",
|
"typescript": "^4.2.3",
|
||||||
"url-loader": "^1.0.1",
|
"vite": "^4.1.1"
|
||||||
"webpack": "^5.73.0",
|
|
||||||
"webpack-bundle-analyzer": "^4.4.2",
|
|
||||||
"webpack-cli": "^4.6.0",
|
|
||||||
"webpack-dev-server": "^4.7.4",
|
|
||||||
"webpack-merge": "^5.7.3"
|
|
||||||
},
|
|
||||||
"resolutions": {
|
|
||||||
"@storybook/react/webpack": "^5"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 15 KiB |
@@ -4,7 +4,10 @@ import {
|
|||||||
PriorityEnum,
|
PriorityEnum,
|
||||||
SearchResponse,
|
SearchResponse,
|
||||||
} from "threetwo-ui-typings";
|
} from "threetwo-ui-typings";
|
||||||
import { LIBRARY_SERVICE_BASE_URI, SEARCH_SERVICE_BASE_URI } from "../constants/endpoints";
|
import {
|
||||||
|
LIBRARY_SERVICE_BASE_URI,
|
||||||
|
SEARCH_SERVICE_BASE_URI,
|
||||||
|
} from "../constants/endpoints";
|
||||||
import {
|
import {
|
||||||
AIRDCPP_SEARCH_RESULTS_ADDED,
|
AIRDCPP_SEARCH_RESULTS_ADDED,
|
||||||
AIRDCPP_SEARCH_RESULTS_UPDATED,
|
AIRDCPP_SEARCH_RESULTS_UPDATED,
|
||||||
@@ -18,6 +21,8 @@ import {
|
|||||||
IMS_COMIC_BOOK_DB_OBJECT_FETCHED,
|
IMS_COMIC_BOOK_DB_OBJECT_FETCHED,
|
||||||
AIRDCPP_TRANSFERS_FETCHED,
|
AIRDCPP_TRANSFERS_FETCHED,
|
||||||
LIBRARY_ISSUE_BUNDLES,
|
LIBRARY_ISSUE_BUNDLES,
|
||||||
|
AIRDCPP_SOCKET_CONNECTED,
|
||||||
|
AIRDCPP_SOCKET_DISCONNECTED,
|
||||||
} from "../constants/action-types";
|
} from "../constants/action-types";
|
||||||
import { isNil } from "lodash";
|
import { isNil } from "lodash";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
@@ -32,16 +37,34 @@ function sleep(ms: number): Promise<NodeJS.Timeout> {
|
|||||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const toggleAirDCPPSocketConnectionStatus =
|
||||||
|
(status: String, payload?: any) => async (dispatch) => {
|
||||||
|
switch (status) {
|
||||||
|
case "connected":
|
||||||
|
dispatch({
|
||||||
|
type: AIRDCPP_SOCKET_CONNECTED,
|
||||||
|
data: payload,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "disconnected":
|
||||||
|
dispatch({
|
||||||
|
type: AIRDCPP_SOCKET_DISCONNECTED,
|
||||||
|
data: payload,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
console.log("Can't set AirDC++ socket status.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
export const search =
|
export const search =
|
||||||
(data: SearchData, ADCPPSocket: any, credentials: any) =>
|
(data: SearchData, ADCPPSocket: any, credentials: any) =>
|
||||||
async (dispatch) => {
|
async (dispatch) => {
|
||||||
try {
|
try {
|
||||||
if (!ADCPPSocket.isConnected()) {
|
if (!ADCPPSocket.isConnected()) {
|
||||||
await ADCPPSocket.connect(
|
await ADCPPSocket();
|
||||||
credentials.username,
|
|
||||||
credentials.password,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
const instance: SearchInstance = await ADCPPSocket.post("search");
|
const instance: SearchInstance = await ADCPPSocket.post("search");
|
||||||
dispatch({
|
dispatch({
|
||||||
@@ -114,21 +137,20 @@ export const search =
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const downloadAirDCPPItem =
|
export const downloadAirDCPPItem =
|
||||||
(searchInstanceId: Number,
|
(
|
||||||
|
searchInstanceId: Number,
|
||||||
resultId: String,
|
resultId: String,
|
||||||
comicObjectId: String,
|
comicObjectId: String,
|
||||||
name: String, size: Number, type: any,
|
name: String,
|
||||||
|
size: Number,
|
||||||
|
type: any,
|
||||||
ADCPPSocket: any,
|
ADCPPSocket: any,
|
||||||
credentials: any,
|
credentials: any,
|
||||||
): void =>
|
): void =>
|
||||||
async (dispatch) => {
|
async (dispatch) => {
|
||||||
try {
|
try {
|
||||||
if (!ADCPPSocket.isConnected()) {
|
if (!ADCPPSocket.isConnected()) {
|
||||||
await ADCPPSocket.connect(
|
await ADCPPSocket.connect();
|
||||||
`${credentials.username}`,
|
|
||||||
`${credentials.password}`,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
let bundleDBImportResult = {};
|
let bundleDBImportResult = {};
|
||||||
const downloadResult = await ADCPPSocket.post(
|
const downloadResult = await ADCPPSocket.post(
|
||||||
@@ -162,7 +184,6 @@ export const downloadAirDCPPItem =
|
|||||||
comicBookDetail: bundleDBImportResult.data,
|
comicBookDetail: bundleDBImportResult.data,
|
||||||
IMS_inProgress: false,
|
IMS_inProgress: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw error;
|
throw error;
|
||||||
@@ -174,11 +195,7 @@ export const getBundlesForComic =
|
|||||||
async (dispatch) => {
|
async (dispatch) => {
|
||||||
try {
|
try {
|
||||||
if (!ADCPPSocket.isConnected()) {
|
if (!ADCPPSocket.isConnected()) {
|
||||||
await ADCPPSocket.connect(
|
await ADCPPSocket.connect();
|
||||||
`${credentials.username}`,
|
|
||||||
`${credentials.password}`,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
const comicObject = await axios({
|
const comicObject = await axios({
|
||||||
method: "POST",
|
method: "POST",
|
||||||
@@ -192,7 +209,8 @@ export const getBundlesForComic =
|
|||||||
});
|
});
|
||||||
// get only the bundles applicable for the comic
|
// get only the bundles applicable for the comic
|
||||||
if (comicObject.data.acquisition.directconnect) {
|
if (comicObject.data.acquisition.directconnect) {
|
||||||
const filteredBundles = comicObject.data.acquisition.directconnect.downloads.map(
|
const filteredBundles =
|
||||||
|
comicObject.data.acquisition.directconnect.downloads.map(
|
||||||
async ({ bundleId }) => {
|
async ({ bundleId }) => {
|
||||||
return await ADCPPSocket.get(`queue/bundles/${bundleId}`);
|
return await ADCPPSocket.get(`queue/bundles/${bundleId}`);
|
||||||
},
|
},
|
||||||
@@ -211,11 +229,7 @@ export const getTransfers =
|
|||||||
(ADCPPSocket: any, credentials: any) => async (dispatch) => {
|
(ADCPPSocket: any, credentials: any) => async (dispatch) => {
|
||||||
try {
|
try {
|
||||||
if (!ADCPPSocket.isConnected()) {
|
if (!ADCPPSocket.isConnected()) {
|
||||||
await ADCPPSocket.connect(
|
await ADCPPSocket.connect();
|
||||||
`${credentials.username}`,
|
|
||||||
`${credentials.password}`,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
const bundles = await ADCPPSocket.get("queue/bundles/1/85", {});
|
const bundles = await ADCPPSocket.get("queue/bundles/1/85", {});
|
||||||
if (!isNil(bundles)) {
|
if (!isNil(bundles)) {
|
||||||
@@ -234,7 +248,6 @@ export const getTransfers =
|
|||||||
type: LIBRARY_ISSUE_BUNDLES,
|
type: LIBRARY_ISSUE_BUNDLES,
|
||||||
issue_bundles,
|
issue_bundles,
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw err;
|
throw err;
|
||||||
|
|||||||
@@ -307,7 +307,7 @@ export const searchIssue = (query, options) => async (dispatch) => {
|
|||||||
case "globalSearchBar":
|
case "globalSearchBar":
|
||||||
dispatch({
|
dispatch({
|
||||||
type: SS_SEARCH_RESULTS_FETCHED_SPECIAL,
|
type: SS_SEARCH_RESULTS_FETCHED_SPECIAL,
|
||||||
data: response.data.body,
|
data: response.data.hits,
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
@import "../../../../node_modules/bulma/bulma.sass";
|
@import "/node_modules/bulma/bulma.sass";
|
||||||
$fa-font-path: "~@fortawesome/fontawesome-free/webfonts";
|
$fa-font-path: "/node_modules/@fortawesome/fontawesome-free/webfonts";
|
||||||
@import "../../../../node_modules/@fortawesome/fontawesome-free/scss/fontawesome.scss";
|
@import "/node_modules/@fortawesome/fontawesome-free/scss/fontawesome.scss";
|
||||||
@import "../../../../node_modules/@fortawesome/fontawesome-free/scss/regular.scss";
|
@import "/node_modules/@fortawesome/fontawesome-free/scss/regular.scss";
|
||||||
@import "../../../../node_modules/@fortawesome/fontawesome-free/scss/solid.scss";
|
@import "/node_modules/@fortawesome/fontawesome-free/scss/solid.scss";
|
||||||
$bg-color: yellow;
|
$bg-color: yellow;
|
||||||
$border-color: red;
|
$border-color: red;
|
||||||
|
|
||||||
@@ -62,6 +62,10 @@ pre {
|
|||||||
margin-left: -300px;
|
margin-left: -300px;
|
||||||
min-width: 500px;
|
min-width: 500px;
|
||||||
}
|
}
|
||||||
|
.airdcpp-status {
|
||||||
|
min-width: 300px;
|
||||||
|
line-height: 1.7rem;
|
||||||
|
}
|
||||||
body {
|
body {
|
||||||
background: #454a59;
|
background: #454a59;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -167,7 +167,7 @@ export const AcquisitionPanel = (
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<span className="icon is-small">
|
<span className="icon is-small">
|
||||||
<img src="/img/airdcpp_logo.svg" />
|
<img src="/src/client/assets/img/airdcpp_logo.svg" />
|
||||||
</span>
|
</span>
|
||||||
<span className="airdcpp-text">Search on AirDC++</span>
|
<span className="airdcpp-text">Search on AirDC++</span>
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ export const PullList = ({ issues }: PullListProps): ReactElement => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
dispatch(
|
dispatch(
|
||||||
getWeeklyPullList({
|
getWeeklyPullList({
|
||||||
startDate: "2022-12-25",
|
startDate: "2023-1-25",
|
||||||
pageSize: "15",
|
pageSize: "15",
|
||||||
currentPage: "1",
|
currentPage: "1",
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -83,14 +83,14 @@ export const RecentlyImported = ({
|
|||||||
{/* Raw file presence */}
|
{/* Raw file presence */}
|
||||||
{isNil(rawFileDetails) && (
|
{isNil(rawFileDetails) && (
|
||||||
<span className="icon custom-icon is-small has-text-danger mr-2">
|
<span className="icon custom-icon is-small has-text-danger mr-2">
|
||||||
<img src="/img/missing-file.svg" />
|
<img src="/src/client/img/missing-file.svg" />
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
{/* ComicInfo.xml presence */}
|
{/* ComicInfo.xml presence */}
|
||||||
{!isNil(comicInfo) && !isEmpty(comicInfo) && (
|
{!isNil(comicInfo) && !isEmpty(comicInfo) && (
|
||||||
<span className="icon custom-icon is-small has-text-danger">
|
<span className="icon custom-icon is-small has-text-danger">
|
||||||
<img
|
<img
|
||||||
src="/img/comicinfoxml.svg"
|
src="/src/client/img/comicinfoxml.svg"
|
||||||
alt={"ComicInfo.xml file detected."}
|
alt={"ComicInfo.xml file detected."}
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
@@ -99,8 +99,8 @@ export const RecentlyImported = ({
|
|||||||
{isComicBookMetadataAvailable && (
|
{isComicBookMetadataAvailable && (
|
||||||
<span className="icon custom-icon">
|
<span className="icon custom-icon">
|
||||||
<img
|
<img
|
||||||
src="/img/cvlogo.svg"
|
src="/src/client/assets/img/cvlogo.svg"
|
||||||
alt={"ComicInfo.xml file detected."}
|
alt={"ComicVine metadata detected."}
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -82,12 +82,12 @@ export const WantedComicsList = ({
|
|||||||
{/* comicVine metadata presence */}
|
{/* comicVine metadata presence */}
|
||||||
{isComicBookMetadataAvailable && (
|
{isComicBookMetadataAvailable && (
|
||||||
<span className="icon custom-icon">
|
<span className="icon custom-icon">
|
||||||
<img src="/img/cvlogo.svg" />
|
<img src="/src/client/assets/img/cvlogo.svg" />
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
{!isEmpty(locg) && (
|
{!isEmpty(locg) && (
|
||||||
<span className="icon custom-icon">
|
<span className="icon custom-icon">
|
||||||
<img src="/img/locglogo.svg" />
|
<img src="/src/client/img/locglogo.svg" />
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
{/* Issue type */}
|
{/* Issue type */}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ export const SearchBar = (data: ISearchBarProps): ReactElement => {
|
|||||||
from: 0,
|
from: 0,
|
||||||
},
|
},
|
||||||
type: "volumeName",
|
type: "volumeName",
|
||||||
trigger: "globalSearchBar"
|
trigger: "globalSearchBar",
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -51,7 +51,6 @@ export const SearchBar = (data: ISearchBarProps): ReactElement => {
|
|||||||
<i className="fa-solid fa-magnifying-glass"></i>
|
<i className="fa-solid fa-magnifying-glass"></i>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{!isEmpty(searchResults) ? (
|
{!isEmpty(searchResults) ? (
|
||||||
<div
|
<div
|
||||||
className="columns box is-multiline"
|
className="columns box is-multiline"
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import { useDispatch, useSelector } from "react-redux";
|
|||||||
import { searchIssue } from "../../actions/fileops.actions";
|
import { searchIssue } from "../../actions/fileops.actions";
|
||||||
import ellipsize from "ellipsize";
|
import ellipsize from "ellipsize";
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component that tabulates the contents of the user's ThreeTwo Library.
|
* Component that tabulates the contents of the user's ThreeTwo Library.
|
||||||
*
|
*
|
||||||
@@ -20,9 +19,10 @@ export const Library = (): ReactElement => {
|
|||||||
const searchResults = useSelector(
|
const searchResults = useSelector(
|
||||||
(state: RootState) => state.fileOps.libraryComics,
|
(state: RootState) => state.fileOps.libraryComics,
|
||||||
);
|
);
|
||||||
const searchError = useSelector(
|
const searchError = useSelector((state: RootState) => {
|
||||||
(state: RootState) => state.fileOps.librarySearchError,
|
console.log(state);
|
||||||
);
|
return state.fileOps.librarySearchError;
|
||||||
|
});
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
dispatch(
|
dispatch(
|
||||||
@@ -36,7 +36,7 @@ export const Library = (): ReactElement => {
|
|||||||
from: 0,
|
from: 0,
|
||||||
},
|
},
|
||||||
type: "all",
|
type: "all",
|
||||||
trigger: "libraryPage"
|
trigger: "libraryPage",
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -89,7 +89,8 @@ export const Library = (): ReactElement => {
|
|||||||
const WantedStatus = ({ value }) => {
|
const WantedStatus = ({ value }) => {
|
||||||
return !value ? <span className="tag is-info is-light">Wanted</span> : null;
|
return !value ? <span className="tag is-info is-light">Wanted</span> : null;
|
||||||
};
|
};
|
||||||
const columns = useMemo(() => [
|
const columns = useMemo(
|
||||||
|
() => [
|
||||||
{
|
{
|
||||||
header: "Comic Metadata",
|
header: "Comic Metadata",
|
||||||
footer: 1,
|
footer: 1,
|
||||||
@@ -99,7 +100,7 @@ export const Library = (): ReactElement => {
|
|||||||
id: "fileDetails",
|
id: "fileDetails",
|
||||||
minWidth: 400,
|
minWidth: 400,
|
||||||
accessorKey: "_source",
|
accessorKey: "_source",
|
||||||
cell: info => {
|
cell: (info) => {
|
||||||
return <MetadataPanel data={info.getValue()} />;
|
return <MetadataPanel data={info.getValue()} />;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -108,7 +109,7 @@ export const Library = (): ReactElement => {
|
|||||||
accessorKey: "_source.sourcedMetadata.comicInfo",
|
accessorKey: "_source.sourcedMetadata.comicInfo",
|
||||||
align: "center",
|
align: "center",
|
||||||
minWidth: 250,
|
minWidth: 250,
|
||||||
cell: info =>
|
cell: (info) =>
|
||||||
!isEmpty(info.getValue()) ? (
|
!isEmpty(info.getValue()) ? (
|
||||||
<ComicInfoXML data={info.getValue()} />
|
<ComicInfoXML data={info.getValue()} />
|
||||||
) : (
|
) : (
|
||||||
@@ -122,9 +123,8 @@ export const Library = (): ReactElement => {
|
|||||||
columns: [
|
columns: [
|
||||||
{
|
{
|
||||||
header: "Publisher",
|
header: "Publisher",
|
||||||
accessorKey:
|
accessorKey: "_source.sourcedMetadata.comicvine.volumeInformation",
|
||||||
"_source.sourcedMetadata.comicvine.volumeInformation",
|
cell: (info) => {
|
||||||
cell: info => {
|
|
||||||
return (
|
return (
|
||||||
!isNil(info.getValue()) && (
|
!isNil(info.getValue()) && (
|
||||||
<h6 className="is-size-7 has-text-weight-bold">
|
<h6 className="is-size-7 has-text-weight-bold">
|
||||||
@@ -137,15 +137,19 @@ export const Library = (): ReactElement => {
|
|||||||
{
|
{
|
||||||
header: "Something",
|
header: "Something",
|
||||||
accessorKey: "_source.acquisition.source.wanted",
|
accessorKey: "_source.acquisition.source.wanted",
|
||||||
cell: info => {
|
cell: (info) => {
|
||||||
!isUndefined(info.getValue()) ?
|
!isUndefined(info.getValue()) ? (
|
||||||
<WantedStatus value={info.getValue().toString()} /> : "Nothing";
|
<WantedStatus value={info.getValue().toString()} />
|
||||||
|
) : (
|
||||||
|
"Nothing"
|
||||||
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}
|
},
|
||||||
], []);
|
],
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pagination control that fetches the next x (pageSize) items
|
* Pagination control that fetches the next x (pageSize) items
|
||||||
@@ -173,7 +177,6 @@ export const Library = (): ReactElement => {
|
|||||||
);
|
);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pagination control that fetches the previous x (pageSize) items
|
* Pagination control that fetches the previous x (pageSize) items
|
||||||
* based on the y (pageIndex) offset from the ThreeTwo Elasticsearch index
|
* based on the y (pageIndex) offset from the ThreeTwo Elasticsearch index
|
||||||
@@ -199,7 +202,7 @@ export const Library = (): ReactElement => {
|
|||||||
from,
|
from,
|
||||||
},
|
},
|
||||||
type: "all",
|
type: "all",
|
||||||
trigger: "libraryPage"
|
trigger: "libraryPage",
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -229,7 +232,8 @@ export const Library = (): ReactElement => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
): <div className="columns">
|
) : (
|
||||||
|
<div className="columns">
|
||||||
<div className="column is-two-thirds">
|
<div className="column is-two-thirds">
|
||||||
<article className="message is-link">
|
<article className="message is-link">
|
||||||
<div className="message-body">
|
<div className="message-body">
|
||||||
@@ -247,7 +251,8 @@ export const Library = (): ReactElement => {
|
|||||||
)}
|
)}
|
||||||
</pre>
|
</pre>
|
||||||
</div>
|
</div>
|
||||||
</div> }
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,21 +1,31 @@
|
|||||||
import React from "react";
|
import React, { useContext } from "react";
|
||||||
import { SearchBar } from "./GlobalSearchBar/SearchBar";
|
import { SearchBar } from "./GlobalSearchBar/SearchBar";
|
||||||
import { DownloadProgressTick } from "./ComicDetail/DownloadProgressTick";
|
import { DownloadProgressTick } from "./ComicDetail/DownloadProgressTick";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import { isUndefined } from "lodash";
|
import { isUndefined } from "lodash";
|
||||||
|
import { format, fromUnixTime } from "date-fns";
|
||||||
|
|
||||||
const Navbar: React.FunctionComponent = (props) => {
|
const Navbar: React.FunctionComponent = (props) => {
|
||||||
const downloadProgressTick = useSelector(
|
const downloadProgressTick = useSelector(
|
||||||
(state: RootState) => state.airdcpp.downloadProgressData,
|
(state: RootState) => state.airdcpp.downloadProgressData,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const airDCPPSocketConnectionStatus = useSelector(
|
||||||
|
(state: RootState) => state.airdcpp.isAirDCPPSocketConnected,
|
||||||
|
);
|
||||||
|
const airDCPPSessionInfo = useSelector(
|
||||||
|
(state: RootState) => state.airdcpp.airDCPPSessionInfo,
|
||||||
|
);
|
||||||
|
const socketDisconnectionReason = useSelector(
|
||||||
|
(state: RootState) => state.airdcpp.socketDisconnectionReason,
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
<nav className="navbar is-fixed-top">
|
<nav className="navbar is-fixed-top">
|
||||||
<div className="navbar-brand">
|
<div className="navbar-brand">
|
||||||
<Link to="/" className="navbar-item">
|
<Link to="/" className="navbar-item">
|
||||||
<img
|
<img
|
||||||
src="/img/threetwo.svg"
|
src="/src/client/assets/img/threetwo.svg"
|
||||||
alt="ThreeTwo! A comic book curator"
|
alt="ThreeTwo! A comic book curator"
|
||||||
width="112"
|
width="112"
|
||||||
height="28"
|
height="28"
|
||||||
@@ -72,25 +82,65 @@ const Navbar: React.FunctionComponent = (props) => {
|
|||||||
<div className="navbar-item has-dropdown is-hoverable">
|
<div className="navbar-item has-dropdown is-hoverable">
|
||||||
<a className="navbar-link is-arrowless">
|
<a className="navbar-link is-arrowless">
|
||||||
<i className="fa-solid fa-download"></i>
|
<i className="fa-solid fa-download"></i>
|
||||||
{downloadProgressTick && (
|
{downloadProgressTick && <div className="pulsating-circle"></div>}
|
||||||
<div className="pulsating-circle"></div>
|
|
||||||
)}
|
|
||||||
</a>
|
</a>
|
||||||
{!isUndefined(downloadProgressTick) ? (
|
{!isUndefined(downloadProgressTick) ? (
|
||||||
<div className="navbar-dropdown download-progress-meter">
|
<div className="navbar-dropdown is-right">
|
||||||
<a className="navbar-item">
|
<a className="navbar-item">
|
||||||
<DownloadProgressTick data={downloadProgressTick} />
|
<DownloadProgressTick data={downloadProgressTick} />
|
||||||
</a>
|
</a> </div>
|
||||||
</div>
|
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
{/* AirDC++ socket connection status */}
|
{/* AirDC++ socket connection status */}
|
||||||
<div className="navbar-item has-dropdown is-hoverable">
|
<div className="navbar-item has-dropdown is-hoverable">
|
||||||
<a className="navbar-link is-arrowless">
|
{airDCPPSocketConnectionStatus ? (
|
||||||
|
<>
|
||||||
|
<a className="navbar-link is-arrowless has-text-success">
|
||||||
<i className="fa-solid fa-bolt"></i>
|
<i className="fa-solid fa-bolt"></i>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
<div className="navbar-dropdown pt-4 pr-2 pl-2 is-right airdcpp-status">
|
||||||
|
{/* AirDC++ Session Information */}
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Last login was{" "}
|
||||||
|
<span className="tag">
|
||||||
|
{format(
|
||||||
|
fromUnixTime(airDCPPSessionInfo.user.last_login),
|
||||||
|
"dd MMMM, yyyy",
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
<hr className="navbar-divider" />
|
||||||
|
<p>
|
||||||
|
<span className="tag has-text-success">
|
||||||
|
{airDCPPSessionInfo.user.username}
|
||||||
|
</span>
|
||||||
|
connected to{" "}
|
||||||
|
<span className="tag has-text-success">
|
||||||
|
{airDCPPSessionInfo.system_info.client_version}
|
||||||
|
</span>{" "}
|
||||||
|
with session ID{" "}
|
||||||
|
<span className="tag has-text-success">
|
||||||
|
{airDCPPSessionInfo.session_id}
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{/* <pre>{JSON.stringify(airDCPPSessionInfo, null, 2)}</pre> */}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<a className="navbar-link is-arrowless has-text-danger">
|
||||||
|
<i className="fa-solid fa-bolt"></i>
|
||||||
|
</a>
|
||||||
|
<div className="navbar-dropdown pr-2 pl-2 is-right">
|
||||||
|
<pre>
|
||||||
|
{JSON.stringify(socketDisconnectionReason, null, 2)}
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="navbar-item has-dropdown is-hoverable is-mega">
|
<div className="navbar-item has-dropdown is-hoverable is-mega">
|
||||||
<div className="navbar-link flex">Blog</div>
|
<div className="navbar-link flex">Blog</div>
|
||||||
|
|||||||
@@ -115,6 +115,8 @@ export const AIRDCPP_FILE_DOWNLOAD_COMPLETED =
|
|||||||
export const LS_SINGLE_IMPORT = "LS_SINGLE_IMPORT";
|
export const LS_SINGLE_IMPORT = "LS_SINGLE_IMPORT";
|
||||||
export const AIRDCPP_BUNDLES_FETCHED = "AIRDCPP_BUNDLES_FETCHED";
|
export const AIRDCPP_BUNDLES_FETCHED = "AIRDCPP_BUNDLES_FETCHED";
|
||||||
export const AIRDCPP_DOWNLOAD_PROGRESS_TICK = "AIRDCPP_DOWNLOAD_PROGRESS_TICK";
|
export const AIRDCPP_DOWNLOAD_PROGRESS_TICK = "AIRDCPP_DOWNLOAD_PROGRESS_TICK";
|
||||||
|
export const AIRDCPP_SOCKET_CONNECTED = "AIRDCPP_SOCKET_CONNECTED";
|
||||||
|
export const AIRDCPP_SOCKET_DISCONNECTED = "AIRDCPP_SOCKET_DISCONNECTED";
|
||||||
|
|
||||||
// Transfers
|
// Transfers
|
||||||
export const AIRDCPP_TRANSFERS_FETCHED = "AIRDCPP_TRANSFERS_FETCHED";
|
export const AIRDCPP_TRANSFERS_FETCHED = "AIRDCPP_TRANSFERS_FETCHED";
|
||||||
|
|||||||
@@ -11,68 +11,68 @@ export const hostURIBuilder = (options: Record<string, string>): string => {
|
|||||||
|
|
||||||
export const CORS_PROXY_SERVER_URI = hostURIBuilder({
|
export const CORS_PROXY_SERVER_URI = hostURIBuilder({
|
||||||
protocol: "http",
|
protocol: "http",
|
||||||
host: process.env.UNDERLYING_HOSTNAME || "localhost",
|
host: import.meta.env.UNDERLYING_HOSTNAME || "localhost",
|
||||||
port: "8050",
|
port: "8050",
|
||||||
apiPath: "/",
|
apiPath: "/",
|
||||||
});
|
});
|
||||||
|
|
||||||
export const COMICVINE_SERVICE_URI = hostURIBuilder({
|
export const COMICVINE_SERVICE_URI = hostURIBuilder({
|
||||||
protocol: "http",
|
protocol: "http",
|
||||||
host: process.env.UNDERLYING_HOSTNAME || "localhost",
|
host: import.meta.env.UNDERLYING_HOSTNAME || "localhost",
|
||||||
port: "3080",
|
port: "3080",
|
||||||
apiPath: "/api/comicvine",
|
apiPath: "/api/comicvine",
|
||||||
});
|
});
|
||||||
|
|
||||||
export const METRON_SERVICE_URI = hostURIBuilder({
|
export const METRON_SERVICE_URI = hostURIBuilder({
|
||||||
protocol: "http",
|
protocol: "http",
|
||||||
host: process.env.UNDERLYING_HOSTNAME || "localhost",
|
host: import.meta.env.UNDERLYING_HOSTNAME || "localhost",
|
||||||
port: "3080",
|
port: "3080",
|
||||||
apiPath: "/api/metron",
|
apiPath: "/api/metron",
|
||||||
});
|
});
|
||||||
|
|
||||||
export const API_BASE_URI = hostURIBuilder({
|
export const API_BASE_URI = hostURIBuilder({
|
||||||
protocol: "http",
|
protocol: "http",
|
||||||
host: process.env.UNDERLYING_HOSTNAME || "localhost",
|
host: import.meta.env.UNDERLYING_HOSTNAME || "localhost",
|
||||||
port: "8050",
|
port: "8050",
|
||||||
apiPath: "/api",
|
apiPath: "/api",
|
||||||
});
|
});
|
||||||
|
|
||||||
export const LIBRARY_SERVICE_HOST = hostURIBuilder({
|
export const LIBRARY_SERVICE_HOST = hostURIBuilder({
|
||||||
protocol: "http",
|
protocol: "http",
|
||||||
host: process.env.UNDERLYING_HOSTNAME || "localhost",
|
host: import.meta.env.UNDERLYING_HOSTNAME || "localhost",
|
||||||
port: "3000",
|
port: "3000",
|
||||||
apiPath: ``,
|
apiPath: ``,
|
||||||
});
|
});
|
||||||
export const LIBRARY_SERVICE_BASE_URI = hostURIBuilder({
|
export const LIBRARY_SERVICE_BASE_URI = hostURIBuilder({
|
||||||
protocol: "http",
|
protocol: "http",
|
||||||
host: process.env.UNDERLYING_HOSTNAME || "localhost",
|
host: import.meta.env.UNDERLYING_HOSTNAME || "localhost",
|
||||||
port: "3000",
|
port: "3000",
|
||||||
apiPath: "/api/library",
|
apiPath: "/api/library",
|
||||||
});
|
});
|
||||||
export const SEARCH_SERVICE_BASE_URI = hostURIBuilder({
|
export const SEARCH_SERVICE_BASE_URI = hostURIBuilder({
|
||||||
protocol: "http",
|
protocol: "http",
|
||||||
host: process.env.UNDERLYING_HOSTNAME || "localhost",
|
host: import.meta.env.UNDERLYING_HOSTNAME || "localhost",
|
||||||
port: "3000",
|
port: "3000",
|
||||||
apiPath: "/api/search",
|
apiPath: "/api/search",
|
||||||
});
|
});
|
||||||
|
|
||||||
export const SETTINGS_SERVICE_BASE_URI = hostURIBuilder({
|
export const SETTINGS_SERVICE_BASE_URI = hostURIBuilder({
|
||||||
protocol: "http",
|
protocol: "http",
|
||||||
host: process.env.UNDERLYING_HOSTNAME || "localhost",
|
host: import.meta.env.UNDERLYING_HOSTNAME || "localhost",
|
||||||
port: "3000",
|
port: "3000",
|
||||||
apiPath: "/api/settings",
|
apiPath: "/api/settings",
|
||||||
});
|
});
|
||||||
|
|
||||||
export const IMAGETRANSFORMATION_SERVICE_BASE_URI = hostURIBuilder({
|
export const IMAGETRANSFORMATION_SERVICE_BASE_URI = hostURIBuilder({
|
||||||
protocol: "http",
|
protocol: "http",
|
||||||
host: process.env.UNDERLYING_HOSTNAME || "localhost",
|
host: import.meta.env.UNDERLYING_HOSTNAME || "localhost",
|
||||||
port: "3000",
|
port: "3000",
|
||||||
apiPath: "/api/imagetransformation",
|
apiPath: "/api/imagetransformation",
|
||||||
});
|
});
|
||||||
|
|
||||||
export const SOCKET_BASE_URI = hostURIBuilder({
|
export const SOCKET_BASE_URI = hostURIBuilder({
|
||||||
protocol: "ws",
|
protocol: "ws",
|
||||||
host: process.env.UNDERLYING_HOSTNAME || "localhost",
|
host: import.meta.env.UNDERLYING_HOSTNAME || "localhost",
|
||||||
port: "3001",
|
port: "3001",
|
||||||
apiPath: `/`,
|
apiPath: `/`,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import { isEmpty, isUndefined } from "lodash";
|
import { isEmpty, isUndefined } from "lodash";
|
||||||
import React, { createContext, useEffect, useState } from "react";
|
import React, { createContext, useEffect, useState } from "react";
|
||||||
import { useDispatch, useSelector } from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
|
import { toggleAirDCPPSocketConnectionStatus } from "../actions/airdcpp.actions";
|
||||||
import { getSettings } from "../actions/settings.actions";
|
import { getSettings } from "../actions/settings.actions";
|
||||||
|
|
||||||
import AirDCPPSocket from "../services/DcppSearchService";
|
import AirDCPPSocket from "../services/DcppSearchService";
|
||||||
|
|
||||||
const AirDCPPSocketContextProvider = ({ children }) => {
|
const AirDCPPSocketContextProvider = ({ children }) => {
|
||||||
@@ -51,15 +53,35 @@ const AirDCPPSocketContextProvider = ({ children }) => {
|
|||||||
client: { host },
|
client: { host },
|
||||||
},
|
},
|
||||||
} = configuration;
|
} = configuration;
|
||||||
|
|
||||||
const initializedAirDCPPSocket = new AirDCPPSocket({
|
const initializedAirDCPPSocket = new AirDCPPSocket({
|
||||||
protocol: `${host.protocol}`,
|
protocol: `${host.protocol}`,
|
||||||
hostname: `${host.hostname}:${host.port}`,
|
hostname: `${host.hostname}:${host.port}`,
|
||||||
|
username: `${host.username}`,
|
||||||
|
password: `${host.password}`,
|
||||||
});
|
});
|
||||||
const socketConnectionInformation = await initializedAirDCPPSocket.connect(
|
|
||||||
`${host.username}`,
|
// connect and disconnect handlers
|
||||||
`${host.password}`,
|
initializedAirDCPPSocket.onConnected = (sessionInfo) => {
|
||||||
true,
|
dispatch(toggleAirDCPPSocketConnectionStatus("connected", sessionInfo));
|
||||||
|
};
|
||||||
|
initializedAirDCPPSocket.onDisconnected = async (
|
||||||
|
reason,
|
||||||
|
code,
|
||||||
|
wasClean,
|
||||||
|
) => {
|
||||||
|
dispatch(
|
||||||
|
toggleAirDCPPSocketConnectionStatus("disconnected", {
|
||||||
|
reason,
|
||||||
|
code,
|
||||||
|
wasClean,
|
||||||
|
}),
|
||||||
);
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const socketConnectionInformation = await initializedAirDCPPSocket.connect();
|
||||||
|
|
||||||
|
// update the state with the new socket connection information
|
||||||
persistSettings({
|
persistSettings({
|
||||||
...airDCPPState,
|
...airDCPPState,
|
||||||
airDCPPState: {
|
airDCPPState: {
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import {
|
|||||||
AIRDCPP_BUNDLES_FETCHED,
|
AIRDCPP_BUNDLES_FETCHED,
|
||||||
AIRDCPP_TRANSFERS_FETCHED,
|
AIRDCPP_TRANSFERS_FETCHED,
|
||||||
LIBRARY_ISSUE_BUNDLES,
|
LIBRARY_ISSUE_BUNDLES,
|
||||||
|
AIRDCPP_SOCKET_CONNECTED,
|
||||||
|
AIRDCPP_SOCKET_DISCONNECTED,
|
||||||
} from "../constants/action-types";
|
} from "../constants/action-types";
|
||||||
import { LOCATION_CHANGE } from "redux-first-history";
|
import { LOCATION_CHANGE } from "redux-first-history";
|
||||||
import { isNil, isUndefined } from "lodash";
|
import { isNil, isUndefined } from "lodash";
|
||||||
@@ -24,6 +26,9 @@ const initialState = {
|
|||||||
downloadFileStatus: {},
|
downloadFileStatus: {},
|
||||||
bundles: [],
|
bundles: [],
|
||||||
transfers: [],
|
transfers: [],
|
||||||
|
isAirDCPPSocketConnected: false,
|
||||||
|
airDCPPSessionInfo: {},
|
||||||
|
socketDisconnectionReason: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
function airdcppReducer(state = initialState, action) {
|
function airdcppReducer(state = initialState, action) {
|
||||||
@@ -95,8 +100,23 @@ function airdcppReducer(state = initialState, action) {
|
|||||||
...state,
|
...state,
|
||||||
transfers: action.bundles,
|
transfers: action.bundles,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
case AIRDCPP_SOCKET_CONNECTED:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
isAirDCPPSocketConnected: true,
|
||||||
|
airDCPPSessionInfo: action.data,
|
||||||
|
};
|
||||||
|
|
||||||
|
case AIRDCPP_SOCKET_DISCONNECTED:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
isAirDCPPSocketConnected: false,
|
||||||
|
socketDisconnectionReason: action.data,
|
||||||
|
};
|
||||||
case LOCATION_CHANGE:
|
case LOCATION_CHANGE:
|
||||||
return {
|
return {
|
||||||
|
...state,
|
||||||
searchResults: [],
|
searchResults: [],
|
||||||
isAirDCPPSearchInProgress: false,
|
isAirDCPPSearchInProgress: false,
|
||||||
searchInfo: null,
|
searchInfo: null,
|
||||||
@@ -105,7 +125,6 @@ function airdcppReducer(state = initialState, action) {
|
|||||||
bundleDBImportResult: null,
|
bundleDBImportResult: null,
|
||||||
// bundles: [],
|
// bundles: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -233,7 +233,7 @@ function fileOpsReducer(state = initialState, action) {
|
|||||||
case SS_SEARCH_RESULTS_FETCHED_SPECIAL: {
|
case SS_SEARCH_RESULTS_FETCHED_SPECIAL: {
|
||||||
const foo = [];
|
const foo = [];
|
||||||
if (!isUndefined(action.data.hits)) {
|
if (!isUndefined(action.data.hits)) {
|
||||||
map(action.data.hits.hits, ({ _source }) => {
|
map(action.data.hits, ({ _source }) => {
|
||||||
foo.push(_source);
|
foo.push(_source);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ class AirDCPPSocket {
|
|||||||
}
|
}
|
||||||
const options = {
|
const options = {
|
||||||
url: `${socketProtocol}://${configuration.hostname}/api/v1/`,
|
url: `${socketProtocol}://${configuration.hostname}/api/v1/`,
|
||||||
autoReconnect: false,
|
autoReconnect: true,
|
||||||
reconnectInterval: 5,
|
reconnectInterval: 5,
|
||||||
logLevel: "verbose",
|
logLevel: "verbose",
|
||||||
ignoredListenerEvents: [
|
ignoredListenerEvents: [
|
||||||
@@ -18,6 +18,8 @@ class AirDCPPSocket {
|
|||||||
"hash_statistics",
|
"hash_statistics",
|
||||||
"hub_counts_updated",
|
"hub_counts_updated",
|
||||||
],
|
],
|
||||||
|
username: `${configuration.username}`,
|
||||||
|
password: `${configuration.password}`,
|
||||||
};
|
};
|
||||||
const AirDCPPSocketInstance = Socket(options, window.WebSocket as any);
|
const AirDCPPSocketInstance = Socket(options, window.WebSocket as any);
|
||||||
return AirDCPPSocketInstance;
|
return AirDCPPSocketInstance;
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ function sleep(ms: number): Promise<NodeJS.Timeout> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const search = async (data: SearchData) => {
|
export const search = async (data: SearchData) => {
|
||||||
await SocketService.connect("admin", "password");
|
await SocketService.connect();
|
||||||
const instance: SearchInstance = await SocketService.post("search");
|
const instance: SearchInstance = await SocketService.post("search");
|
||||||
const unsubscribe = await SocketService.addListener(
|
const unsubscribe = await SocketService.addListener(
|
||||||
"search",
|
"search",
|
||||||
|
|||||||
@@ -30,12 +30,12 @@ app.use(bodyParser.urlencoded({ extended: true }));
|
|||||||
// REGISTER ROUTES
|
// REGISTER ROUTES
|
||||||
// all of the routes will be prefixed with /api
|
// all of the routes will be prefixed with /api
|
||||||
const routes: Router[] = Object.values(router);
|
const routes: Router[] = Object.values(router);
|
||||||
app.use("/api", routes);
|
// app.use("/api", routes);
|
||||||
|
|
||||||
// Send index.html on root request
|
// Send index.html on root request
|
||||||
app.use(express.static("dist"));
|
// app.use(express.static("dist"));
|
||||||
app.use(express.static("public"));
|
// app.use(express.static("public"));
|
||||||
|
|
||||||
app.listen(port);
|
// app.listen(port);
|
||||||
|
|
||||||
console.log(`Server is listening on ${port}`);
|
// console.log(`Server is listening on ${port}`);
|
||||||
|
|||||||
@@ -2,19 +2,21 @@
|
|||||||
"extends": "@tsconfig/node14/tsconfig.json",
|
"extends": "@tsconfig/node14/tsconfig.json",
|
||||||
"$schema": "https://json.schemastore.org/tsconfig",
|
"$schema": "https://json.schemastore.org/tsconfig",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"allowSyntheticDefaultImports": true,
|
"target": "ESNext",
|
||||||
"noImplicitAny": false,
|
"useDefineForClassFields": true,
|
||||||
"target": "es2019",
|
"lib": ["DOM", "DOM.Iterable", "ESNext"],
|
||||||
"jsx": "react",
|
"allowJs": false,
|
||||||
"module": "commonjs",
|
|
||||||
"sourceMap": true,
|
|
||||||
"outDir": "./dist/",
|
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
|
"esModuleInterop": false,
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"strict": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleResolution": "Node",
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"lib": ["dom", "dom.iterable", "esnext", "webworker"],
|
"isolatedModules": true,
|
||||||
"baseUrl": ".",
|
"noEmit": true,
|
||||||
"esModuleInterop": true,
|
"jsx": "react-jsx"
|
||||||
"strict": true
|
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
"eslint.workingDirectories": [
|
"eslint.workingDirectories": [
|
||||||
|
|||||||
22
vite.config.js
Normal file
22
vite.config.js
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import react from "@vitejs/plugin-react";
|
||||||
|
import { nodeResolve } from "@rollup/plugin-node-resolve";
|
||||||
|
import { defineConfig } from "vite";
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
publicDir: "public",
|
||||||
|
base: "",
|
||||||
|
build: "esnext",
|
||||||
|
plugins: [
|
||||||
|
nodeResolve({
|
||||||
|
// browser: true
|
||||||
|
exportConditions: ["node"],
|
||||||
|
}),
|
||||||
|
react({
|
||||||
|
// Use React plugin in all *.jsx and *.tsx files
|
||||||
|
include: "**/*.{jsx,tsx}",
|
||||||
|
babel: {
|
||||||
|
plugins: ["babel-plugin-styled-components"],
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
});
|
||||||
@@ -1,128 +0,0 @@
|
|||||||
const path = require("path");
|
|
||||||
const HtmlWebpackPlugin = require("html-webpack-plugin");
|
|
||||||
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
|
|
||||||
const webpack = require("webpack");
|
|
||||||
const outputDirectory = "dist";
|
|
||||||
const BundleAnalyzerPlugin =
|
|
||||||
require("webpack-bundle-analyzer").BundleAnalyzerPlugin;
|
|
||||||
const ReactRefreshWebpackPlugin = require("@pmmmwh/react-refresh-webpack-plugin");
|
|
||||||
const CopyPlugin = require("copy-webpack-plugin");
|
|
||||||
|
|
||||||
module.exports = (_, argv) => {
|
|
||||||
const mode = argv.mode;
|
|
||||||
const isDevelopment = mode === "development";
|
|
||||||
return {
|
|
||||||
entry: ["babel-polyfill", "./src/client/index.tsx"],
|
|
||||||
output: {
|
|
||||||
path: path.resolve(__dirname, outputDirectory),
|
|
||||||
filename: "./js/[name].bundle.js",
|
|
||||||
},
|
|
||||||
devtool: "source-map",
|
|
||||||
stats: {
|
|
||||||
children: true,
|
|
||||||
},
|
|
||||||
experiments: {
|
|
||||||
topLevelAwait: true,
|
|
||||||
},
|
|
||||||
module: {
|
|
||||||
rules: [
|
|
||||||
{
|
|
||||||
test: /\.worker\.(js|ts)$/i,
|
|
||||||
use: [
|
|
||||||
{
|
|
||||||
loader: "comlink-loader",
|
|
||||||
options: {
|
|
||||||
singleton: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: [/\.js?$/, /\.jsx?$/, /\.tsx?$/],
|
|
||||||
use: [
|
|
||||||
{
|
|
||||||
loader: "babel-loader",
|
|
||||||
options: {
|
|
||||||
plugins: [
|
|
||||||
isDevelopment && require("react-refresh/babel"),
|
|
||||||
].filter(Boolean),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
exclude: /node_modules/,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
enforce: "pre",
|
|
||||||
test: /\.js$/,
|
|
||||||
loader: "source-map-loader",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.css$/i,
|
|
||||||
use: ["style-loader", "css-loader"],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.s[ac]ss$/i,
|
|
||||||
use: [
|
|
||||||
// Creates `style` nodes from JS strings
|
|
||||||
"style-loader",
|
|
||||||
// Translates CSS into CommonJS
|
|
||||||
"css-loader",
|
|
||||||
// Compiles Sass to CSS
|
|
||||||
"sass-loader",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.(png|jpg|jpeg|gif|svg|woff|woff2|ttf|eot)$/i,
|
|
||||||
use: [
|
|
||||||
"file-loader?hash=sha512&digest=hex&name=img/[contenthash].[ext]",
|
|
||||||
"image-webpack-loader?bypassOnDebug&optipng.optimizationLevel=7&gifsicle.interlaced=false",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
resolve: {
|
|
||||||
extensions: ["*", ".ts", ".tsx", ".js", ".jsx", ".json"],
|
|
||||||
aliasFields: ["browser", "browser.esm"],
|
|
||||||
},
|
|
||||||
mode: process.env.NODE_ENV,
|
|
||||||
devServer: {
|
|
||||||
hot: true,
|
|
||||||
port: 3050,
|
|
||||||
open: true,
|
|
||||||
proxy: {
|
|
||||||
"/api/**": {
|
|
||||||
target: "http://localhost:8050",
|
|
||||||
secure: false,
|
|
||||||
changeOrigin: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
optimization: {
|
|
||||||
usedExports: false,
|
|
||||||
},
|
|
||||||
plugins: [
|
|
||||||
// new BundleAnalyzerPlugin(),
|
|
||||||
new CopyPlugin({
|
|
||||||
patterns: [{ from: "./src/client/assets/img/", to: "img/" }],
|
|
||||||
options: {
|
|
||||||
concurrency: 100,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
isDevelopment && new ReactRefreshWebpackPlugin(),
|
|
||||||
new HtmlWebpackPlugin({
|
|
||||||
template: "./public/index.html",
|
|
||||||
favicon: "./public/favicon.ico",
|
|
||||||
title: "express-typescript-react",
|
|
||||||
}),
|
|
||||||
new webpack.DefinePlugin({
|
|
||||||
"process.env.UNDERLYING_HOSTNAME": JSON.stringify(
|
|
||||||
process.env.UNDERLYING_HOSTNAME,
|
|
||||||
),
|
|
||||||
}),
|
|
||||||
new MiniCssExtractPlugin({
|
|
||||||
filename: "./css/[name].css",
|
|
||||||
chunkFilename: "./css/[id].css",
|
|
||||||
}),
|
|
||||||
].filter(Boolean),
|
|
||||||
};
|
|
||||||
};
|
|
||||||
Reference in New Issue
Block a user