From f04641986d63d157366c16fef0e92ed102ceda31 Mon Sep 17 00:00:00 2001 From: Rishi Ghan Date: Wed, 8 Sep 2021 22:52:00 -0700 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=A7=20Various=20fixes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker-compose.yml | 2 +- package.json | 10 ++-- src/client/assets/scss/App.scss | 8 ++- src/client/components/AcquisitionPanel.tsx | 15 ++++- src/client/components/Carda.tsx | 4 +- src/client/components/ComicDetail.tsx | 12 +++- src/client/components/RecentlyImported.tsx | 11 +++- .../shared/utils/tradepaperback.utils.ts | 34 +++++++++++ src/client/shared/utils/trainingData.json | 14 +++++ yarn.lock | 59 +++++++++++++++---- 10 files changed, 145 insertions(+), 24 deletions(-) create mode 100644 src/client/shared/utils/tradepaperback.utils.ts create mode 100644 src/client/shared/utils/trainingData.json diff --git a/docker-compose.yml b/docker-compose.yml index 5b4adca..c8f4d1c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,4 +1,4 @@ -version: "3.7" +version: "3.3" services: threetwo: diff --git a/package.json b/package.json index 93170e0..ec42243 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,10 @@ "calibre-opds": "^1.0.7", "chokidar": "^3.5.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", "dayjs": "^1.10.6", "ellipsize": "^0.1.0", "event-stream": "^4.0.1", @@ -44,6 +48,7 @@ "fs-extra": "^9.1.0", "http-response-stream": "^1.0.7", "jsdoc": "^3.6.7", + "ml-classify-text": "^2.0.0", "opds-extra": "^3.0.9", "pretty-bytes": "^5.6.0", "react": "^17.0.1", @@ -98,10 +103,7 @@ "bulma": "^0.9.3", "clean-webpack-plugin": "^1.0.0", "comlink": "^4.3.0", - "compromise": "^13.10.5", - "compromise-dates": "^2.0.1", - "compromise-numbers": "^1.2.0", - "compromise-sentences": "^0.2.0", + "compromise-strict": "^0.0.2", "concurrently": "^4.0.0", "connected-react-router": "^6.9.1", "css-loader": "^5.1.2", diff --git a/src/client/assets/scss/App.scss b/src/client/assets/scss/App.scss index 618fe11..dab2aef 100644 --- a/src/client/assets/scss/App.scss +++ b/src/client/assets/scss/App.scss @@ -76,7 +76,13 @@ $border-color: red; } } .card-content { - padding: 1rem; + .card-title { + margin-bottom: 0.2rem; + } + .cv-icon, i { + margin: 4px 4px 4px 0; + } + padding: 0.5rem 1rem; } } .card-container { diff --git a/src/client/components/AcquisitionPanel.tsx b/src/client/components/AcquisitionPanel.tsx index dcc71b4..8d7b0fa 100644 --- a/src/client/components/AcquisitionPanel.tsx +++ b/src/client/components/AcquisitionPanel.tsx @@ -110,8 +110,8 @@ export const AcquisitionPanel = ( )} {/* AirDC++ results */} -
- {!isNil(airDCPPSearchResults) && !isEmpty(airDCPPSearchResults) && ( +
+ {!isNil(airDCPPSearchResults) && !isEmpty(airDCPPSearchResults) ? ( @@ -182,6 +182,17 @@ export const AcquisitionPanel = ( })}
+ ) : ( +
+
+
+ Searching via AirDC++ is still in{" "} + alpha. Some searches may take arbitrarily long, + or may not work at all. Searches from ADCS hubs are more + reliable than NMDCS ones. +
+
+
)}
diff --git a/src/client/components/Carda.tsx b/src/client/components/Carda.tsx index 5d783cf..ca5b027 100644 --- a/src/client/components/Carda.tsx +++ b/src/client/components/Carda.tsx @@ -32,7 +32,9 @@ const renderCard = (props): ReactElement => {
{props.hasDetails && (
- {isNil(props.title) ? "No Name" : props.title} +
+ {isNil(props.title) ? "No Name" : props.title} +
{props.children}
)} diff --git a/src/client/components/ComicDetail.tsx b/src/client/components/ComicDetail.tsx index d4f2f07..f17b806 100644 --- a/src/client/components/ComicDetail.tsx +++ b/src/client/components/ComicDetail.tsx @@ -16,6 +16,7 @@ import { isEmpty, isUndefined, isNil } from "lodash"; import { RootState } from "threetwo-ui-typings"; import { fetchComicVineMatches } from "../actions/fileops.actions"; import { getComicBookDetailById } from "../actions/comicinfo.actions"; +import { detectTradePaperbacks } from "../shared/utils/tradepaperback.utils"; import dayjs from "dayjs"; const prettyBytes = require("pretty-bytes"); @@ -115,11 +116,17 @@ export const ComicDetail = ({}: ComicDetailProps): ReactElement => {
- Total issues in this volume:{" "} + Total issues in this volume: { comicBookDetailData.sourcedMetadata.comicvine .volumeInformation.count_of_issues } + {JSON.stringify( + detectTradePaperbacks( + comicBookDetailData.sourcedMetadata.comicvine + .volumeInformation.description, + ), + )}
@@ -274,6 +281,9 @@ export const ComicDetail = ({}: ComicDetailProps): ReactElement => { }), }; + // Determine which cover image to use: + // 1. from the locally imported, non-CV-scraped version, or + // 2. from the CV-scraped version let imagePath = ""; let comicBookTitle = ""; if (!isNil(comicBookDetailData.rawFileDetails)) { diff --git a/src/client/components/RecentlyImported.tsx b/src/client/components/RecentlyImported.tsx index 8e04ca1..df9ce7e 100644 --- a/src/client/components/RecentlyImported.tsx +++ b/src/client/components/RecentlyImported.tsx @@ -39,7 +39,16 @@ export const RecentlyImported = ({ imageUrl={imagePath} hasDetails title={comicName ? titleElement : null} - > + > + {!isNil(sourcedMetadata.comicvine) && ( +
+ + + + +
+ )} + ); })} diff --git a/src/client/shared/utils/tradepaperback.utils.ts b/src/client/shared/utils/tradepaperback.utils.ts new file mode 100644 index 0000000..5bf742b --- /dev/null +++ b/src/client/shared/utils/tradepaperback.utils.ts @@ -0,0 +1,34 @@ +import Classifier from "ml-classify-text"; + +export const detectTradePaperbacks = (deck: string): any => { + const classifier = new Classifier({ nGramMin: 2, nGramMax: 2 }); + const positiveTPBIdentifiers = [ + "trade paperbacks", + "TPB", + "paperback", + "hardcover", + "collects the following issues", + "collected issues", + "collecting the issues", + "collecting the following issues", + "collected editions", + ]; + const negativeTPBIdentifiers = ["mini-series"]; + + classifier.train(positiveTPBIdentifiers, "Possibly a trade paperback"); + classifier.train(negativeTPBIdentifiers, "Not a trade paperback"); + if (deck) { + + console.log("DEC", deck); + const predictions = classifier.predict(deck); + + if (predictions.length) { + predictions.forEach((prediction) => { + console.log(`${prediction.label} (${prediction.confidence})`); + return prediction; + }); + } else { + console.log("No predictions returned."); + } + } +}; diff --git a/src/client/shared/utils/trainingData.json b/src/client/shared/utils/trainingData.json new file mode 100644 index 0000000..0897e1d --- /dev/null +++ b/src/client/shared/utils/trainingData.json @@ -0,0 +1,14 @@ +[ + {"phrase": "Twelve issue mini-series.", "result": {"not_a_paperback": 1}}, + {"phrase": "Trade paperback collecting Jean Grey #7-11.", "result": {"paperback": 1}}, + {"phrase": "Trade paperback collecting Iron Fist #6-7 & 73-77", "result": {"paperback ": 1}}, + {"phrase": "Collected Editions", "result": {"paperback": 1}}, + {"phrase": "Six issue mini-series.", "result": {"not_a_paperback": 1}}, + {"phrase": "Four issue mini-series.", "result": {"not_a_paperback": 1}}, + {"phrase": "Seventy-two issue digital prequel to the Injustice 2 video game.", "result": {"not_a_paperback": 1}}, + {"phrase": "Total issues in this volume:50", "result": {"paperback": 1}}, + {"phrase": "Five issue mini-series.", "result": {"not_a_paperback": 1}}, + {"phrase": "Digital mini-series.", "result": {"not_a_paperback": 1}}, + {"phrase": "Six issue mini-series.", "result": {"not_a_paperback": 1}}, + {"phrase": "Six issue mini-series.", "result": {"not_a_paperback": 1}} + ] \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index ec52264..1bf3363 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3605,6 +3605,13 @@ character-parser@^2.1.1: dependencies: is-regex "^1.0.3" +chevrotain@7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/chevrotain/-/chevrotain-7.0.3.tgz#f9621971a726eba804f7763edace2183d157c5d7" + integrity sha512-G634q7M5EiqNNv+0MKcQES2jmqabbi4PvUDpzjG2t+i1XQFaMCz0o8BZ8lbQbZex4RqkzJ3pOy+UwNLFlQm4eg== + dependencies: + regexp-to-ast "0.5.0" + chokidar@^2.1.8: version "2.1.8" resolved "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz" @@ -3968,27 +3975,34 @@ compression@^1.7.4: safe-buffer "5.1.2" vary "~1.1.2" -compromise-dates@^2.0.1: +compromise-dates@^2.2.1: version "2.2.1" - resolved "https://registry.npmjs.org/compromise-dates/-/compromise-dates-2.2.1.tgz" + resolved "https://registry.yarnpkg.com/compromise-dates/-/compromise-dates-2.2.1.tgz#c04d22f1f95850e5ce8b0ab225b1671639207369" integrity sha512-mtdK67DR4EvowLLh0YJ3aMxMtKXDViQBJTNNdHI5ck+DVhCCd7rYnNcwC2eSES+3tup1JB9+InOzmvyEuFyjLQ== dependencies: spacetime "6.16.0" spacetime-holiday "0.1.0" -compromise-numbers@^1.2.0: +compromise-numbers@^1.4.0: version "1.4.0" - resolved "https://registry.npmjs.org/compromise-numbers/-/compromise-numbers-1.4.0.tgz" + resolved "https://registry.yarnpkg.com/compromise-numbers/-/compromise-numbers-1.4.0.tgz#22e545923243333bc1e8a2e82da2e922afb50400" integrity sha512-3ceRpwZIWduVSMYn54ET1ELdI7bvXQk42uDwxffxiJBxgKCwcCfVbiLuTG62cI+qTHchwLDh4vp9i3WARXROFQ== -compromise-sentences@^0.2.0: - version "0.2.0" - resolved "https://registry.npmjs.org/compromise-sentences/-/compromise-sentences-0.2.0.tgz" - integrity sha512-GiXGHoVz4Q9QdooAcNEhsXqcTw2lfxIdgjLJYLszyt2bJKXZTJIhH5DT9tixpbzIWeRTQAJdC+/CRVkqAyL2pA== +compromise-sentences@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/compromise-sentences/-/compromise-sentences-0.3.0.tgz#61d34039323155bc20dad10f24340daaabf86e26" + integrity sha512-L6d5PXmmyPyWRMoJURYOM0yILhtV37zCOy9ZW8Xd6KgY+2qQBTwuokekaGL9MDpSH3/grRDL+AHKytYpGrTEmA== -compromise@^13.10.5: +compromise-strict@^0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/compromise-strict/-/compromise-strict-0.0.2.tgz#e4bf4cc386e8795c6408d3606ebb2cd31cab9fbd" + integrity sha512-1ApkPa6kjmyS1ZFhDRZgttDcnVv+Ci8U0kIIsxRBLCN0vautyPm6FROvBwoLimlU3pgIH3hMIpdNdVfe2yj3Gw== + dependencies: + chevrotain "7.0.3" + +compromise@^13.11.3: version "13.11.3" - resolved "https://registry.npmjs.org/compromise/-/compromise-13.11.3.tgz" + resolved "https://registry.yarnpkg.com/compromise/-/compromise-13.11.3.tgz#3f6b687fbefdbd1ef674f263f6e5c06b29c324d9" integrity sha512-oKYButHtXcDyEe2et5XlniFWyFTpDOy3z7zB501EEgTN9xeZHIib1Xq4AOSJw6HCZmwGHh1nx3MGy/MbGHFtWQ== dependencies: efrt-unpack "2.2.0" @@ -4843,7 +4857,7 @@ ee-first@1.1.1: efrt-unpack@2.2.0: version "2.2.0" - resolved "https://registry.npmjs.org/efrt-unpack/-/efrt-unpack-2.2.0.tgz" + resolved "https://registry.yarnpkg.com/efrt-unpack/-/efrt-unpack-2.2.0.tgz#b05dbec0fb8cb346a27840e00c969df9c72fee52" integrity sha512-9xUSSj7qcUxz+0r4X3+bwUNttEfGfK5AH+LVa1aTpqdAfrN5VhROYCfcF+up4hp5OL7IUKcZJJrzAGipQRDoiQ== electron-to-chromium@^1.3.723: @@ -8947,6 +8961,13 @@ mkdirp@^1.0.3, mkdirp@^1.0.4: resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== +ml-classify-text@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ml-classify-text/-/ml-classify-text-2.0.0.tgz#932bee8bf3a7adbe3f6259136f77c57672fa6ad0" + integrity sha512-1+8kc07uZoat5Q8gbdYBjwuvNPDTwvt8t9+ZL7CHVErbKD3w95rnCcsmJWJcz9LWWjP2pMlgolgzKCiZklc2MA== + dependencies: + xregexp "^4.3.0" + moment@^2.14.1, moment@^2.22.1, moment@^2.29.1: version "2.29.1" resolved "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz" @@ -11232,6 +11253,11 @@ regexp-clone@1.0.0, regexp-clone@^1.0.0: resolved "https://registry.npmjs.org/regexp-clone/-/regexp-clone-1.0.0.tgz" integrity sha512-TuAasHQNamyyJ2hb97IuBEif4qBHGjPHBS64sZwytpLEqtBQ1gPJTnOaQ6qmpET16cK14kkjbazl6+p0RRv0yw== +regexp-to-ast@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/regexp-to-ast/-/regexp-to-ast-0.5.0.tgz#56c73856bee5e1fef7f73a00f1473452ab712a24" + integrity sha512-tlbJqcMHnPKI9zSrystikWKwHkBqu2a/Sgw01h3zFjvYrMxEDYHzzoMZnUrbIfpTFEsoRnnviOXNCzFiSc54Qw== + regexp.prototype.flags@^1.2.0, regexp.prototype.flags@^1.3.1: version "1.3.1" resolved "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz" @@ -12150,12 +12176,12 @@ source-map@^0.7.3, source-map@~0.7.2: spacetime-holiday@0.1.0: version "0.1.0" - resolved "https://registry.npmjs.org/spacetime-holiday/-/spacetime-holiday-0.1.0.tgz" + resolved "https://registry.yarnpkg.com/spacetime-holiday/-/spacetime-holiday-0.1.0.tgz#e680d17e0ac26e36b2101ee4ac40eb642b6d31d4" integrity sha512-rYIpSDbHnznZRstUrmYYFAaruW8e96t+1JfS0b6qMiAAQ2DrkLKc8oMotAAkB9qMTUwXXf5bIkdTHfP434uitQ== spacetime@6.16.0: version "6.16.0" - resolved "https://registry.npmjs.org/spacetime/-/spacetime-6.16.0.tgz" + resolved "https://registry.yarnpkg.com/spacetime/-/spacetime-6.16.0.tgz#f213963392eafc380716c3857b23251de87db97f" integrity sha512-mkuniNOp6ssfPyJidj81tb54zKxK4vEKPTmcUsC/NEGIF8S07ppoSotdg6numT1/26rthQYmdxMY/M5a9WeJVQ== sparse-bitfield@^3.0.3: @@ -13984,6 +14010,13 @@ xpath@^0.0.32: resolved "https://registry.npmjs.org/xpath/-/xpath-0.0.32.tgz" integrity sha512-rxMJhSIoiO8vXcWvSifKqhvV96GjiD5wYb8/QHdoRyQvraTpp4IEv944nhGausZZ3u7dhQXteZuZbaqfpB7uYw== +xregexp@^4.3.0: + version "4.4.1" + resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-4.4.1.tgz#c84a88fa79e9ab18ca543959712094492185fe65" + integrity sha512-2u9HwfadaJaY9zHtRRnH6BY6CQVNQKkYm3oLtC9gJXXzfsbACg5X5e4EZZGVAH+YIfa+QA9lsFQTTe3HURF3ag== + dependencies: + "@babel/runtime-corejs3" "^7.12.1" + xregexp@^5.0.2: version "5.0.2" resolved "https://registry.npmjs.org/xregexp/-/xregexp-5.0.2.tgz"