From 592da9bd2a635f64b0d0e6c1c5eed101c3b667f9 Mon Sep 17 00:00:00 2001 From: Rishi Ghan Date: Thu, 1 Dec 2022 13:11:02 -0800 Subject: [PATCH 01/10] =?UTF-8?q?=F0=9F=94=A7=20Refactoring=20uncompressio?= =?UTF-8?q?n=20methods=20on=20client-side?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/client/actions/fileops.actions.tsx | 57 ++++++++++--------- .../components/ComicDetail/ComicDetail.tsx | 10 +++- .../ComicDetail/ComicVineDetails.tsx | 2 +- .../components/ComicDetail/RawFileDetails.tsx | 4 +- 4 files changed, 41 insertions(+), 32 deletions(-) diff --git a/src/client/actions/fileops.actions.tsx b/src/client/actions/fileops.actions.tsx index dded2b7..93f844a 100644 --- a/src/client/actions/fileops.actions.tsx +++ b/src/client/actions/fileops.actions.tsx @@ -256,35 +256,38 @@ export const fetchComicVineMatches = /** * This method is a proxy to `uncompressFullArchive` which uncompresses complete `rar` or `zip` archives * @param {string} path The path to the compressed archive - * @param {any} options Options object + * @param {any} options Options object * @returns {any} */ -export const extractComicArchive = (path: string, options: any) => async (dispatch) => { - const comicBookPages: string[] = []; - dispatch({ - type: IMS_COMIC_BOOK_ARCHIVE_EXTRACTION_CALL_IN_PROGRESS, - }); - const extractedComicBookArchive = await axios({ - method: "POST", - url: `${LIBRARY_SERVICE_BASE_URI}/uncompressFullArchive`, - headers: { - "Content-Type": "application/json; charset=utf-8", - }, - data: { - filePath: path, - }, - }); - map(extractedComicBookArchive.data, (page) => { - console.log(page); - const pageFilePath = removeLeadingPeriod(page); - const imagePath = encodeURI(`${LIBRARY_SERVICE_HOST}${pageFilePath}`); - comicBookPages.push(imagePath); - }); - dispatch({ - type: IMS_COMIC_BOOK_ARCHIVE_EXTRACTION_SUCCESS, - extractedComicBookArchive: comicBookPages, - }); -}; +export const extractComicArchive = + (path: string, options: any): any => async (dispatch) => { + const comicBookPages: string[] = []; + console.log(options); + dispatch({ + type: IMS_COMIC_BOOK_ARCHIVE_EXTRACTION_CALL_IN_PROGRESS, + }); + const extractedComicBookArchive = await axios({ + method: "POST", + url: `${LIBRARY_SERVICE_BASE_URI}/uncompressFullArchive`, + headers: { + "Content-Type": "application/json; charset=utf-8", + }, + data: { + filePath: path, + ...options, + }, + }); + map(extractedComicBookArchive.data, (page) => { + console.log(page); + const pageFilePath = removeLeadingPeriod(page); + const imagePath = encodeURI(`${LIBRARY_SERVICE_HOST}${pageFilePath}`); + comicBookPages.push(imagePath); + }); + dispatch({ + type: IMS_COMIC_BOOK_ARCHIVE_EXTRACTION_SUCCESS, + extractedComicBookArchive: comicBookPages, + }); + }; export const searchIssue = (query, options) => async (dispatch) => { dispatch({ diff --git a/src/client/components/ComicDetail/ComicDetail.tsx b/src/client/components/ComicDetail/ComicDetail.tsx index fa3ffc1..a88b575 100644 --- a/src/client/components/ComicDetail/ComicDetail.tsx +++ b/src/client/components/ComicDetail/ComicDetail.tsx @@ -74,7 +74,13 @@ export const ComicDetail = (data: ComicDetailProps): ReactElement => { const openModal = useCallback((filePath) => { setIsOpen(true); - dispatch(extractComicArchive(filePath)); + dispatch(extractComicArchive(filePath, { + type: "full", + purpose: "readComicBook", + imageResizeOptions: { + baseWidth: 275, + } + })); }, []); const afterOpenModal = useCallback((things) => { @@ -249,7 +255,7 @@ export const ComicDetail = (data: ComicDetailProps): ReactElement => { {/* raw file details */} -
+
{!isUndefined(rawFileDetails) && !isEmpty(rawFileDetails.cover) && ( <> diff --git a/src/client/components/ComicDetail/ComicVineDetails.tsx b/src/client/components/ComicDetail/ComicVineDetails.tsx index 27985c2..853157b 100644 --- a/src/client/components/ComicDetail/ComicVineDetails.tsx +++ b/src/client/components/ComicDetail/ComicVineDetails.tsx @@ -7,7 +7,7 @@ import Card from "../Carda"; export const ComicVineDetails = (props): ReactElement => { const { data, updatedAt } = props; return ( -
+
ComicVine Metadata
diff --git a/src/client/components/ComicDetail/RawFileDetails.tsx b/src/client/components/ComicDetail/RawFileDetails.tsx index 2f086fb..7db0d4f 100644 --- a/src/client/components/ComicDetail/RawFileDetails.tsx +++ b/src/client/components/ComicDetail/RawFileDetails.tsx @@ -7,7 +7,7 @@ export const RawFileDetails = (props): ReactElement => { const { rawFileDetails, inferredMetadata } = props.data; return ( <> -
+
Raw File Details
@@ -38,7 +38,7 @@ export const RawFileDetails = (props): ReactElement => {
-
+
{/* inferred metadata */}
Inferred Issue Metadata
-- 2.49.1 From 2ee0e85f92af46c683ccebd482e22230e9a3f10f Mon Sep 17 00:00:00 2001 From: Rishi Ghan Date: Fri, 2 Dec 2022 10:43:35 -0800 Subject: [PATCH 02/10] =?UTF-8?q?=E2=9C=8F=EF=B8=8F=20Refactoring?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/client/actions/fileops.actions.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/actions/fileops.actions.tsx b/src/client/actions/fileops.actions.tsx index 93f844a..2fea5e1 100644 --- a/src/client/actions/fileops.actions.tsx +++ b/src/client/actions/fileops.actions.tsx @@ -274,7 +274,7 @@ export const extractComicArchive = }, data: { filePath: path, - ...options, + options, }, }); map(extractedComicBookArchive.data, (page) => { -- 2.49.1 From 1efc56d88964991aac56938a93c20feb6776bcbb Mon Sep 17 00:00:00 2001 From: Rishi Ghan Date: Mon, 5 Dec 2022 11:04:49 -0800 Subject: [PATCH 03/10] =?UTF-8?q?=F0=9F=91=81=EF=B8=8F=20Updates=20to=20th?= =?UTF-8?q?e=20comic=20viewer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- src/client/actions/fileops.actions.tsx | 1 - src/client/assets/scss/App.scss | 4 + .../components/ComicDetail/ComicDetail.tsx | 33 ++++--- yarn.lock | 94 +++++++++++++------ 5 files changed, 90 insertions(+), 44 deletions(-) diff --git a/package.json b/package.json index 7dd5afc..d8433f2 100644 --- a/package.json +++ b/package.json @@ -65,7 +65,7 @@ "qs": "^6.10.5", "react": "^18.1.0", "react-collapsible": "^2.9.0", - "react-comic-viewer": "^0.3.5", + "react-comic-viewer": "^0.4.0", "react-day-picker": "^8.0.6", "react-dom": "^18.1.0", "react-fast-compare": "^3.2.0", diff --git a/src/client/actions/fileops.actions.tsx b/src/client/actions/fileops.actions.tsx index 2fea5e1..ee03372 100644 --- a/src/client/actions/fileops.actions.tsx +++ b/src/client/actions/fileops.actions.tsx @@ -278,7 +278,6 @@ export const extractComicArchive = }, }); map(extractedComicBookArchive.data, (page) => { - console.log(page); const pageFilePath = removeLeadingPeriod(page); const imagePath = encodeURI(`${LIBRARY_SERVICE_HOST}${pageFilePath}`); comicBookPages.push(imagePath); diff --git a/src/client/assets/scss/App.scss b/src/client/assets/scss/App.scss index a671b8a..1bc5cf6 100644 --- a/src/client/assets/scss/App.scss +++ b/src/client/assets/scss/App.scss @@ -356,6 +356,10 @@ pre { border-radius: 0.5rem; } +.comic-viewer { + border: 1px solid red; +} + // comicvine metadata .comicvine-metadata { background-color: #f2f1f9; diff --git a/src/client/components/ComicDetail/ComicDetail.tsx b/src/client/components/ComicDetail/ComicDetail.tsx index a88b575..0145c09 100644 --- a/src/client/components/ComicDetail/ComicDetail.tsx +++ b/src/client/components/ComicDetail/ComicDetail.tsx @@ -74,19 +74,21 @@ export const ComicDetail = (data: ComicDetailProps): ReactElement => { const openModal = useCallback((filePath) => { setIsOpen(true); - dispatch(extractComicArchive(filePath, { - type: "full", - purpose: "readComicBook", - imageResizeOptions: { - baseWidth: 275, - } - })); + dispatch( + extractComicArchive(filePath, { + type: "full", + purpose: "readComicBook", + imageResizeOptions: { + baseWidth: 1024, + }, + }), + ); }, []); const afterOpenModal = useCallback((things) => { // references are now sync'd and can be accessed. // subtitle.style.color = "#f00"; - console.log(things); + console.log("kolaveri", things); }, []); const closeModal = useCallback(() => { @@ -100,7 +102,7 @@ export const ComicDetail = (data: ComicDetailProps): ReactElement => { <>
- +

Searching for:

@@ -118,7 +120,9 @@ export const ComicDetail = (data: ComicDetailProps): ReactElement => { comicVineSearchResults, comicObjectId, }} - />) : (
+ /> + ) : ( +
{ visible={comicVineAPICallProgress} />
-
)} - ), +
+ )} + + ), }, - editComicBookMetadata: { content: () => , }, }; - // check for the availability of CV metadata const isComicBookMetadataAvailable = @@ -286,6 +290,7 @@ export const ComicDetail = (data: ComicDetailProps): ReactElement => { )} diff --git a/yarn.lock b/yarn.lock index 17e4121..42a1571 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1283,7 +1283,7 @@ dependencies: tslib "^2.0.0" -"@emotion/babel-plugin@^11.3.0", "@emotion/babel-plugin@^11.7.1": +"@emotion/babel-plugin@^11.7.1": version "11.9.2" resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.9.2.tgz#723b6d394c89fb2ef782229d92ba95a740576e95" integrity sha512-Pr/7HGH6H6yKgnVFNEj2MVlreu3ADqftqjqwUvDy/OJzKFgxKeTQ+eeUf20FOTuHVkDON2iNa25rAXVYtWJCjw== @@ -1317,28 +1317,45 @@ resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.8.0.tgz#bbbff68978fefdbe68ccb533bc8cbe1d1afb5413" integrity sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow== -"@emotion/is-prop-valid@^1.1.0", "@emotion/is-prop-valid@^1.1.1": +"@emotion/hash@^0.9.0": + version "0.9.0" + resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.9.0.tgz#c5153d50401ee3c027a57a177bc269b16d889cb7" + integrity sha512-14FtKiHhy2QoPIzdTcvh//8OyBlknNs2nXRwIhG904opCby3l+9Xaf/wuPvICBF0rc1ZCNBd3nKe9cd2mecVkQ== + +"@emotion/is-prop-valid@^1.1.0": version "1.1.3" resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-1.1.3.tgz#f0907a416368cf8df9e410117068e20fe87c0a3a" integrity sha512-RFg04p6C+1uO19uG8N+vqanzKqiM9eeV1LDOG3bmkYmuOj7NbKNlFC/4EZq5gnwAIlcC/jOT24f8Td0iax2SXA== dependencies: "@emotion/memoize" "^0.7.4" +"@emotion/is-prop-valid@^1.1.2": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-1.2.0.tgz#7f2d35c97891669f7e276eb71c83376a5dc44c83" + integrity sha512-3aDpDprjM0AwaxGE09bOPkNxHpBd+kA6jty3RnaEXdweX1DF1U3VQpPYb0g1IStAuK7SVQ1cy+bNBBKp4W3Fjg== + dependencies: + "@emotion/memoize" "^0.8.0" + "@emotion/memoize@^0.7.4", "@emotion/memoize@^0.7.5": version "0.7.5" resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.5.tgz#2c40f81449a4e554e9fc6396910ed4843ec2be50" integrity sha512-igX9a37DR2ZPGYtV6suZ6whr8pTFtyHL3K/oLUotxpSVO2ASaprmAe2Dkq7tBo7CRY7MMDrAa9nuQP9/YG8FxQ== -"@emotion/react@11.7.1": - version "11.7.1" - resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.7.1.tgz#3f800ce9b20317c13e77b8489ac4a0b922b2fe07" - integrity sha512-DV2Xe3yhkF1yT4uAUoJcYL1AmrnO5SVsdfvu+fBuS7IbByDeTVx9+wFmvx9Idzv7/78+9Mgx2Hcmr7Fex3tIyw== +"@emotion/memoize@^0.8.0": + version "0.8.0" + resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.8.0.tgz#f580f9beb67176fa57aae70b08ed510e1b18980f" + integrity sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA== + +"@emotion/react@11.9.0": + version "11.9.0" + resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.9.0.tgz#b6d42b1db3bd7511e7a7c4151dc8bc82e14593b8" + integrity sha512-lBVSF5d0ceKtfKCDQJveNAtkC7ayxpVlgOohLgXqRwqWr9bOf4TZAFFyIcNngnV6xK6X4x2ZeXq7vliHkoVkxQ== dependencies: "@babel/runtime" "^7.13.10" + "@emotion/babel-plugin" "^11.7.1" "@emotion/cache" "^11.7.1" - "@emotion/serialize" "^1.0.2" - "@emotion/sheet" "^1.1.0" - "@emotion/utils" "^1.0.0" + "@emotion/serialize" "^1.0.3" + "@emotion/utils" "^1.1.0" "@emotion/weak-memoize" "^0.2.5" hoist-non-react-statics "^3.3.1" @@ -1366,21 +1383,32 @@ "@emotion/utils" "^1.0.0" csstype "^3.0.2" -"@emotion/sheet@^1.1.0", "@emotion/sheet@^1.1.1": +"@emotion/serialize@^1.0.3": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.1.1.tgz#0595701b1902feded8a96d293b26be3f5c1a5cf0" + integrity sha512-Zl/0LFggN7+L1liljxXdsVSVlg6E/Z/olVWpfxUTxOAmi8NU7YoeWeLfi1RmnB2TATHoaWwIBRoL+FvAJiTUQA== + dependencies: + "@emotion/hash" "^0.9.0" + "@emotion/memoize" "^0.8.0" + "@emotion/unitless" "^0.8.0" + "@emotion/utils" "^1.2.0" + csstype "^3.0.2" + +"@emotion/sheet@^1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.1.1.tgz#015756e2a9a3c7c5f11d8ec22966a8dbfbfac787" integrity sha512-J3YPccVRMiTZxYAY0IOq3kd+hUP8idY8Kz6B/Cyo+JuXq52Ek+zbPbSQUrVQp95aJ+lsAW7DPL1P2Z+U1jGkKA== -"@emotion/styled@11.6.0": - version "11.6.0" - resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-11.6.0.tgz#9230d1a7bcb2ebf83c6a579f4c80e0664132d81d" - integrity sha512-mxVtVyIOTmCAkFbwIp+nCjTXJNgcz4VWkOYQro87jE2QBTydnkiYusMrRGFtzuruiGK4dDaNORk4gH049iiQuw== +"@emotion/styled@11.8.1": + version "11.8.1" + resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-11.8.1.tgz#856f6f63aceef0eb783985fa2322e2bf66d04e17" + integrity sha512-OghEVAYBZMpEquHZwuelXcRjRJQOVayvbmNR0zr174NHdmMgrNkLC6TljKC5h9lZLkN5WGrdUcrKlOJ4phhoTQ== dependencies: "@babel/runtime" "^7.13.10" - "@emotion/babel-plugin" "^11.3.0" - "@emotion/is-prop-valid" "^1.1.1" + "@emotion/babel-plugin" "^11.7.1" + "@emotion/is-prop-valid" "^1.1.2" "@emotion/serialize" "^1.0.2" - "@emotion/utils" "^1.0.0" + "@emotion/utils" "^1.1.0" "@emotion/stylis@^0.8.4": version "0.8.5" @@ -1392,11 +1420,21 @@ resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.5.tgz#77211291c1900a700b8a78cfafda3160d76949ed" integrity sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg== +"@emotion/unitless@^0.8.0": + version "0.8.0" + resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.8.0.tgz#a4a36e9cbdc6903737cd20d38033241e1b8833db" + integrity sha512-VINS5vEYAscRl2ZUDiT3uMPlrFQupiKgHz5AA4bCH1miKBg4qtwkim1qPmJj/4WG6TreYMY111rEFsjupcOKHw== + "@emotion/utils@^1.0.0", "@emotion/utils@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.1.0.tgz#86b0b297f3f1a0f2bdb08eeac9a2f49afd40d0cf" integrity sha512-iRLa/Y4Rs5H/f2nimczYmS5kFJEbpiVvgN3XVfZ022IYhuNA1IRSHEizcof88LtCTXtl9S2Cxt32KgaXEu72JQ== +"@emotion/utils@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.2.0.tgz#9716eaccbc6b5ded2ea5a90d65562609aab0f561" + integrity sha512-sn3WH53Kzpw8oQ5mgMmIzzyAaH2ZqFEbozVVBSYp538E06OSE6ytOp7pRAjNQR+Q/orwqdQYJSe2m3hCOeznkw== + "@emotion/weak-memoize@^0.2.5": version "0.2.5" resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz#8eed982e2ee6f7f4e44c253e12962980791efd46" @@ -15281,20 +15319,20 @@ react-collapsible@^2.9.0: resolved "https://registry.yarnpkg.com/react-collapsible/-/react-collapsible-2.10.0.tgz#57330f9f4f968a41ece49c651b56cf30f9a06d19" integrity sha512-kEVsmlFfXBMTCnU5gwIv19MdmPAhbIPzz5Er37TiJSzRKS0IHrqAKQyQeHEmtoGIQMTcVI46FzE4z3NlVTx77A== -react-comic-viewer@^0.3.5: - version "0.3.5" - resolved "https://registry.yarnpkg.com/react-comic-viewer/-/react-comic-viewer-0.3.5.tgz#ab5f9ba74a4aa2e748c29d11b43e40d2a042d9ba" - integrity sha512-xMjvu/JVJ821dYWOuOiZlEEMpgdmUeUtznoRjBlMaFi6WJI52V55/6E+ICg8VqROwiMwmWjp65rGhF1P8hlRLg== +react-comic-viewer@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/react-comic-viewer/-/react-comic-viewer-0.4.0.tgz#81e170c4d3924f3312171e3fc7d5d4485466c301" + integrity sha512-tdse0Vn6cJzEbFUZMlEBcY1LrH+LfCKodJInl5Y5lyIZyKARoejLrQNlJPnarvNcPW0qm6yQkYioaI56pq0U1w== dependencies: - "@emotion/react" "11.7.1" - "@emotion/styled" "11.6.0" + "@emotion/react" "11.9.0" + "@emotion/styled" "11.8.1" "@react-hook/window-size" "^3.0.7" "@rooks/use-did-update" "^4.10.0" "@rooks/use-outside-click-ref" "4.11.2" nanoid "^3.1.25" react-full-screen "1.1.0" react-icons "4.3.1" - react-swipeable "6.2.0" + react-swipeable "6.2.2" screenfull "^5.1.0" react-day-picker@^8.0.6: @@ -15534,10 +15572,10 @@ react-stickynode@^4.0.0: shallowequal "^1.0.0" subscribe-ui-event "^2.0.6" -react-swipeable@6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/react-swipeable/-/react-swipeable-6.2.0.tgz#057271cb7a6fb4af9d2a3f6d80ccdf33e2f64d47" - integrity sha512-nWQ8dEM8e/uswZLSIkXUsAnQmnX4MTcryOHBQIQYRMJFDpgDBSiVbKsz/BZVCIScF4NtJh16oyxwaNOepR6xSw== +react-swipeable@6.2.2: + version "6.2.2" + resolved "https://registry.yarnpkg.com/react-swipeable/-/react-swipeable-6.2.2.tgz#52ba570f3a7a90db7093094ec476f3d151f727d1" + integrity sha512-Oz7nSFrssvq2yvy05aNL3F+yBUqSvLsK6x1mu+rQFOpMdQVnt4izKt1vyjvvTb70q6GQOaSpaB6qniROW2MAzQ== react-syntax-highlighter@^15.4.5: version "15.5.0" -- 2.49.1 From 70e883dff3d234105b789c0a14beed18d8bb5791 Mon Sep 17 00:00:00 2001 From: Rishi Ghan Date: Tue, 6 Dec 2022 13:59:54 -0800 Subject: [PATCH 04/10] =?UTF-8?q?=F0=9F=96=BC=EF=B8=8F=20Added=20screensho?= =?UTF-8?q?ts=20from=20December=202022?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index 907f804..ac64779 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,16 @@ ThreeTwo! _aims to be_ a comic book curation app. [![Docker Image CI](https://github.com/rishighan/threetwo/actions/workflows/docker-image.yml/badge.svg)](https://github.com/rishighan/threetwo/actions/workflows/docker-image.yml) +###Screenshots + +![](https://raw.githubusercontent.com/rishighan/threetwo/rishighan-screenshots-dec-2022/Dashboard.png) + +![](https://raw.githubusercontent.com/rishighan/threetwo/rishighan-screenshots-dec-2022/Library.png) + +![](https://raw.githubusercontent.com/rishighan/threetwo/rishighan-screenshots-dec-2022/DC%2B%2B%20integration.png) + +![](https://raw.githubusercontent.com/rishighan/threetwo/rishighan-screenshots-dec-2022/ComicVine%20Matching.png) + ### 🦄 Early Development Support Channel -- 2.49.1 From 85f8532ccd01c8a8be9193673dc86d2ad1f185f5 Mon Sep 17 00:00:00 2001 From: Rishi Ghan Date: Tue, 6 Dec 2022 14:01:22 -0800 Subject: [PATCH 05/10] =?UTF-8?q?=E2=9C=8F=EF=B8=8F=20Fixed=20typo=20in=20?= =?UTF-8?q?README?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ac64779..1c67ba8 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ ThreeTwo! _aims to be_ a comic book curation app. [![Docker Image CI](https://github.com/rishighan/threetwo/actions/workflows/docker-image.yml/badge.svg)](https://github.com/rishighan/threetwo/actions/workflows/docker-image.yml) -###Screenshots +### Screenshots ![](https://raw.githubusercontent.com/rishighan/threetwo/rishighan-screenshots-dec-2022/Dashboard.png) -- 2.49.1 From f8aff2bb1b6f93dea2e722e10f501c23ce02a916 Mon Sep 17 00:00:00 2001 From: Rishi Ghan Date: Thu, 8 Dec 2022 11:06:56 -0800 Subject: [PATCH 06/10] =?UTF-8?q?=F0=9F=8F=97=EF=B8=8F=20Massive=20refacto?= =?UTF-8?q?r=20around=20archive=20uncompression=20for=20reading/analysis?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- src/client/actions/fileops.actions.tsx | 24 ++++++++----------- .../components/ComicDetail/ComicDetail.tsx | 2 +- .../ComicDetail/Tabs/ArchiveOperations.tsx | 10 +++++++- src/client/constants/action-types.ts | 2 ++ src/client/reducers/fileops.reducer.ts | 19 ++++++++++++++- 6 files changed, 41 insertions(+), 18 deletions(-) diff --git a/package.json b/package.json index d8433f2..3c1f1f0 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "pretty-bytes": "^5.6.0", "prop-types": "^15.8.1", "qs": "^6.10.5", - "react": "^18.1.0", + "react": "^18.2.0", "react-collapsible": "^2.9.0", "react-comic-viewer": "^0.4.0", "react-day-picker": "^8.0.6", diff --git a/src/client/actions/fileops.actions.tsx b/src/client/actions/fileops.actions.tsx index ee03372..457de36 100644 --- a/src/client/actions/fileops.actions.tsx +++ b/src/client/actions/fileops.actions.tsx @@ -36,7 +36,7 @@ import { CV_WEEKLY_PULLLIST_FETCHED, } from "../constants/action-types"; import { success } from "react-notification-system-redux"; -import { removeLeadingPeriod } from "../shared/utils/formatting.utils"; + import { isNil, map } from "lodash"; export async function walkFolder(path: string): Promise> { @@ -260,13 +260,12 @@ export const fetchComicVineMatches = * @returns {any} */ export const extractComicArchive = - (path: string, options: any): any => async (dispatch) => { - const comicBookPages: string[] = []; - console.log(options); + (path: string, options: any): any => + async (dispatch) => { dispatch({ type: IMS_COMIC_BOOK_ARCHIVE_EXTRACTION_CALL_IN_PROGRESS, }); - const extractedComicBookArchive = await axios({ + await axios({ method: "POST", url: `${LIBRARY_SERVICE_BASE_URI}/uncompressFullArchive`, headers: { @@ -277,17 +276,14 @@ export const extractComicArchive = options, }, }); - map(extractedComicBookArchive.data, (page) => { - const pageFilePath = removeLeadingPeriod(page); - const imagePath = encodeURI(`${LIBRARY_SERVICE_HOST}${pageFilePath}`); - comicBookPages.push(imagePath); - }); - dispatch({ - type: IMS_COMIC_BOOK_ARCHIVE_EXTRACTION_SUCCESS, - extractedComicBookArchive: comicBookPages, - }); }; +/** + * Description + * @param {any} query + * @param {any} options + * @returns {any} + */ export const searchIssue = (query, options) => async (dispatch) => { dispatch({ type: SS_SEARCH_IN_PROGRESS, diff --git a/src/client/components/ComicDetail/ComicDetail.tsx b/src/client/components/ComicDetail/ComicDetail.tsx index 0145c09..acab0a4 100644 --- a/src/client/components/ComicDetail/ComicDetail.tsx +++ b/src/client/components/ComicDetail/ComicDetail.tsx @@ -77,7 +77,7 @@ export const ComicDetail = (data: ComicDetailProps): ReactElement => { dispatch( extractComicArchive(filePath, { type: "full", - purpose: "readComicBook", + purpose: "reading", imageResizeOptions: { baseWidth: 1024, }, diff --git a/src/client/components/ComicDetail/Tabs/ArchiveOperations.tsx b/src/client/components/ComicDetail/Tabs/ArchiveOperations.tsx index c9655ed..2cf39ba 100644 --- a/src/client/components/ComicDetail/Tabs/ArchiveOperations.tsx +++ b/src/client/components/ComicDetail/Tabs/ArchiveOperations.tsx @@ -23,7 +23,15 @@ export const ArchiveOperations = (props): ReactElement => { const dispatch = useDispatch(); const unpackComicArchive = useCallback(() => { - dispatch(extractComicArchive(data.rawFileDetails.filePath)); + dispatch( + extractComicArchive(data.rawFileDetails.filePath, { + type: "full", + purpose: "analysis", + imageResizeOptions: { + baseWidth: 275, + }, + }), + ); }, []); // sliding panel config diff --git a/src/client/constants/action-types.ts b/src/client/constants/action-types.ts index a6be92d..f058853 100644 --- a/src/client/constants/action-types.ts +++ b/src/client/constants/action-types.ts @@ -81,6 +81,8 @@ export const IMS_COMIC_BOOK_ARCHIVE_EXTRACTION_CALL_IN_PROGRESS = export const IMS_COMIC_BOOK_ARCHIVE_EXTRACTION_CALL_FAILED = "IMS_COMIC_BOOK_ARCHIVE_EXTRACTION_CALL_FAILED"; +export const COMICBOOK_EXTRACTION_SUCCESS = "COMICBOOK_EXTRACTION_SUCCESS"; + // Image file stats export const IMG_ANALYSIS_CALL_IN_PROGRESS = "IMG_ANALYSIS_CALL_IN_PROGRESS"; export const IMG_ANALYSIS_DATA_FETCH_SUCCESS = diff --git a/src/client/reducers/fileops.reducer.ts b/src/client/reducers/fileops.reducer.ts index 2060797..3eb0b96 100644 --- a/src/client/reducers/fileops.reducer.ts +++ b/src/client/reducers/fileops.reducer.ts @@ -29,7 +29,11 @@ import { SS_SEARCH_FAILED, SS_SEARCH_RESULTS_FETCHED_SPECIAL, VOLUMES_FETCHED, + COMICBOOK_EXTRACTION_SUCCESS, } from "../constants/action-types"; +import { removeLeadingPeriod } from "../shared/utils/formatting.utils"; +import { LIBRARY_SERVICE_HOST } from "../constants/endpoints"; + const initialState = { IMSCallInProgress: false, IMGCallInProgress: false, @@ -157,6 +161,19 @@ function fileOpsReducer(state = initialState, action) { librarySearchResultCount: state.librarySearchResultCount + 1, }; } + + case COMICBOOK_EXTRACTION_SUCCESS: { + const comicBookPages: string[] = []; + map(action.result, (page) => { + const pageFilePath = removeLeadingPeriod(page); + const imagePath = encodeURI(`${LIBRARY_SERVICE_HOST}${pageFilePath}`); + comicBookPages.push(imagePath); + }); + return { + ...state, + extractedComicBookArchive: comicBookPages, + }; + } case LS_QUEUE_DRAINED: { console.log("drained", action); return { @@ -229,7 +246,7 @@ function fileOpsReducer(state = initialState, action) { volumes: action.data, SSCallInProgress: false, }; - + case SS_SEARCH_FAILED: { return { ...state, -- 2.49.1 From bf6f18c5d5ecdb17dd4a8efe936be2fb9b2282cb Mon Sep 17 00:00:00 2001 From: Rishi Ghan Date: Fri, 9 Dec 2022 12:17:45 -0800 Subject: [PATCH 07/10] =?UTF-8?q?=F0=9F=94=A7=20Tweaked=20state=20vars=20f?= =?UTF-8?q?or=20reading=20and=20analysis?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/ComicDetail/ComicDetail.tsx | 2 +- .../ComicDetail/Tabs/ArchiveOperations.tsx | 2 +- src/client/reducers/fileops.reducer.ts | 40 +++++++++++++------ 3 files changed, 29 insertions(+), 15 deletions(-) diff --git a/src/client/components/ComicDetail/ComicDetail.tsx b/src/client/components/ComicDetail/ComicDetail.tsx index acab0a4..66076eb 100644 --- a/src/client/components/ComicDetail/ComicDetail.tsx +++ b/src/client/components/ComicDetail/ComicDetail.tsx @@ -66,7 +66,7 @@ export const ComicDetail = (data: ComicDetailProps): ReactElement => { ); const extractedComicBook = useSelector( - (state: RootState) => state.fileOps.extractedComicBookArchive, + (state: RootState) => state.fileOps.extractedComicBookArchive.reading, ); const { comicObjectId } = useParams<{ comicObjectId: string }>(); diff --git a/src/client/components/ComicDetail/Tabs/ArchiveOperations.tsx b/src/client/components/ComicDetail/Tabs/ArchiveOperations.tsx index 2cf39ba..839dcdc 100644 --- a/src/client/components/ComicDetail/Tabs/ArchiveOperations.tsx +++ b/src/client/components/ComicDetail/Tabs/ArchiveOperations.tsx @@ -14,7 +14,7 @@ export const ArchiveOperations = (props): ReactElement => { (state: RootState) => state.fileOps.comicBookExtractionInProgress, ); const extractedComicBookArchive = useSelector( - (state: RootState) => state.fileOps.extractedComicBookArchive, + (state: RootState) => state.fileOps.extractedComicBookArchive.analysis, ); const imageAnalysisResult = useSelector((state: RootState) => { diff --git a/src/client/reducers/fileops.reducer.ts b/src/client/reducers/fileops.reducer.ts index 3eb0b96..2b3596b 100644 --- a/src/client/reducers/fileops.reducer.ts +++ b/src/client/reducers/fileops.reducer.ts @@ -46,7 +46,10 @@ const initialState = { isComicVineMetadataImportInProgress: false, comicVineMetadataImportError: {}, rawImportError: {}, - extractedComicBookArchive: [], + extractedComicBookArchive: { + reading: [], + analysis: [], + }, recentComics: [], wantedComics: [], libraryComics: [], @@ -135,13 +138,7 @@ function fileOpsReducer(state = initialState, action) { comicBookExtractionInProgress: true, }; } - case IMS_COMIC_BOOK_ARCHIVE_EXTRACTION_SUCCESS: { - return { - ...state, - extractedComicBookArchive: action.extractedComicBookArchive, - comicBookExtractionInProgress: false, - }; - } + case LOCATION_CHANGE: { return { ...state, @@ -164,15 +161,32 @@ function fileOpsReducer(state = initialState, action) { case COMICBOOK_EXTRACTION_SUCCESS: { const comicBookPages: string[] = []; - map(action.result, (page) => { + map(action.result.files, (page) => { const pageFilePath = removeLeadingPeriod(page); const imagePath = encodeURI(`${LIBRARY_SERVICE_HOST}${pageFilePath}`); comicBookPages.push(imagePath); }); - return { - ...state, - extractedComicBookArchive: comicBookPages, - }; + + switch (action.result.purpose) { + case "reading": + return { + ...state, + extractedComicBookArchive: { + reading: comicBookPages + }, + comicBookExtractionInProgress: false, + }; + + case "analysis": + return { + ...state, + extractedComicBookArchive: { + analysis: comicBookPages + }, + comicBookExtractionInProgress: false, + }; + } + } case LS_QUEUE_DRAINED: { console.log("drained", action); -- 2.49.1 From 0d41b57d18a0ba3fc2cc772e77d027db36001a8d Mon Sep 17 00:00:00 2001 From: Rishi Ghan Date: Wed, 21 Dec 2022 21:07:22 -0800 Subject: [PATCH 08/10] =?UTF-8?q?=F0=9F=8F=97=EF=B8=8F=20Refactor=20to=20s?= =?UTF-8?q?upport=20DC++=20and=20socket.io=20integration?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This refactor covers the following workflows: 1. Adding a comic from LOCG or ComicVine adds it to the wanted list 2. Downloading that comic from DC++ correctly adds download metadata to the corresponding comic object in mongo 3. Successful download triggers automatic import to library and cover extraction, metadata application --- src/client/actions/fileops.actions.tsx | 70 +++++++++---------- src/client/components/App.tsx | 47 +++++++++---- .../ComicDetail/AcquisitionPanel.tsx | 8 ++- .../components/ComicDetail/RawFileDetails.tsx | 2 +- src/client/components/Dashboard/Dashboard.tsx | 9 ++- src/client/components/Dashboard/PullList.tsx | 2 +- .../components/Dashboard/RecentlyImported.tsx | 10 +-- src/client/reducers/fileops.reducer.ts | 11 +-- src/client/shared/utils/metadata.utils.ts | 5 +- yarn.lock | 2 +- 10 files changed, 96 insertions(+), 70 deletions(-) diff --git a/src/client/actions/fileops.actions.tsx b/src/client/actions/fileops.actions.tsx index 457de36..bbe67e6 100644 --- a/src/client/actions/fileops.actions.tsx +++ b/src/client/actions/fileops.actions.tsx @@ -60,15 +60,6 @@ export async function walkFolder(path: string): Promise> { * @return the comic book metadata */ export const fetchComicBookMetadata = () => async (dispatch) => { - const extractionOptions = { - extractTarget: "cover", - targetExtractionFolder: "./userdata/covers", - extractionMode: "bulk", - paginationOptions: { - pageLimit: 25, - page: 1, - }, - }; dispatch({ type: LS_IMPORT_CALL_IN_PROGRESS, }); @@ -86,7 +77,7 @@ export const fetchComicBookMetadata = () => async (dispatch) => { dispatch({ type: LS_IMPORT, meta: { remote: true }, - data: { extractionOptions }, + data: {}, }); }; export const toggleImportQueueStatus = (options) => async (dispatch) => { @@ -136,21 +127,24 @@ export const getComicBooks = (options) => async (dispatch) => { * @returns Nothing. * @param payload */ -export const importToDB = (sourceName: string, payload?: any) => (dispatch) => { +export const importToDB = (sourceName: string, metadata?: any) => (dispatch) => { try { const comicBookMetadata = { - rawFileDetails: { - name: "", - }, - importStatus: { - isImported: true, - tagged: false, - matchedResult: { - score: "0", + importType: "new", + payload: { + rawFileDetails: { + name: "", }, - }, - sourcedMetadata: payload || null, - acquisition: { source: { wanted: true, name: sourceName } }, + importStatus: { + isImported: true, + tagged: false, + matchedResult: { + score: "0", + }, + }, + sourcedMetadata: metadata || null, + acquisition: { source: { wanted: true, name: sourceName } }, + } }; dispatch({ type: IMS_CV_METADATA_IMPORT_CALL_IN_PROGRESS, @@ -261,22 +255,22 @@ export const fetchComicVineMatches = */ export const extractComicArchive = (path: string, options: any): any => - async (dispatch) => { - dispatch({ - type: IMS_COMIC_BOOK_ARCHIVE_EXTRACTION_CALL_IN_PROGRESS, - }); - await axios({ - method: "POST", - url: `${LIBRARY_SERVICE_BASE_URI}/uncompressFullArchive`, - headers: { - "Content-Type": "application/json; charset=utf-8", - }, - data: { - filePath: path, - options, - }, - }); - }; + async (dispatch) => { + dispatch({ + type: IMS_COMIC_BOOK_ARCHIVE_EXTRACTION_CALL_IN_PROGRESS, + }); + await axios({ + method: "POST", + url: `${LIBRARY_SERVICE_BASE_URI}/uncompressFullArchive`, + headers: { + "Content-Type": "application/json; charset=utf-8", + }, + data: { + filePath: path, + options, + }, + }); + }; /** * Description diff --git a/src/client/components/App.tsx b/src/client/components/App.tsx index 2efa3e7..6446767 100644 --- a/src/client/components/App.tsx +++ b/src/client/components/App.tsx @@ -18,18 +18,22 @@ import { AirDCPPSocketContext, } from "../context/AirDCPPSocket"; import { isEmpty, isUndefined } from "lodash"; -import { AIRDCPP_DOWNLOAD_PROGRESS_TICK } from "../constants/action-types"; -import { useDispatch } from "react-redux"; +import { + AIRDCPP_DOWNLOAD_PROGRESS_TICK, + LS_SINGLE_IMPORT, +} from "../constants/action-types"; +import { useDispatch, useSelector } from "react-redux"; /** * Method that initializes an AirDC++ socket connection * 1. Initializes event listeners for download init, tick and complete events - * 2. Handles errors in case the connection to AirDC++ is not established or terminated - * @returns void + * 2. Handles errors in case the connection to AirDC++ is not established or terminated + * @returns void */ const AirDCPPSocketComponent = (): ReactElement => { const airDCPPConfiguration = useContext(AirDCPPSocketContext); const dispatch = useDispatch(); + useEffect(() => { const initializeAirDCPPEventListeners = async () => { if ( @@ -42,9 +46,7 @@ const AirDCPPSocketComponent = (): ReactElement => { "queue_bundle_added", async (data) => { console.log("JEMEN:", data); - - - } + }, ); // download tick listener await airDCPPConfiguration.airDCPPState.socket.addListener( @@ -62,9 +64,18 @@ const AirDCPPSocketComponent = (): ReactElement => { `queue`, "queue_bundle_status", async (bundleData) => { + let count = 0; if (bundleData.status.completed && bundleData.status.downloaded) { // dispatch the action for raw import, with the metadata - console.log("IM THE MAN UP IN THIS") + if (count < 1) { + console.log(`[AirDCPP]: Download complete.`); + dispatch({ + type: LS_SINGLE_IMPORT, + meta: { remote: true }, + data: bundleData, + }); + count += 1; + } } }, ); @@ -92,7 +103,10 @@ export const App = (): ReactElement => { } /> } /> - } /> + } + /> } /> } /> } /> @@ -105,9 +119,18 @@ export const App = (): ReactElement => { element={} /> } /> - } /> - } /> - } /> + } + /> + } + /> + } + />
diff --git a/src/client/components/ComicDetail/AcquisitionPanel.tsx b/src/client/components/ComicDetail/AcquisitionPanel.tsx index 97d0c3d..a6c8ec2 100644 --- a/src/client/components/ComicDetail/AcquisitionPanel.tsx +++ b/src/client/components/ComicDetail/AcquisitionPanel.tsx @@ -16,6 +16,7 @@ import ellipsize from "ellipsize"; import { Form, Field } from "react-final-form"; import { isEmpty, isNil, map } from "lodash"; import { AirDCPPSocketContext } from "../../context/AirDCPPSocket"; + interface IAcquisitionPanelProps { query: any; comicObjectId: any; @@ -96,9 +97,12 @@ export const AcquisitionPanel = ( (searchInstanceId, resultId, name, size, type) => { dispatch( downloadAirDCPPItem( - searchInstanceId, resultId, + searchInstanceId, + resultId, props.comicObjectId, - name, size, type, + name, + size, + type, airDCPPConfiguration.airDCPPState.socket, { username: `${airDCPPConfiguration.airDCPPState.settings.directConnect.client.host.username}`, diff --git a/src/client/components/ComicDetail/RawFileDetails.tsx b/src/client/components/ComicDetail/RawFileDetails.tsx index 7db0d4f..230a473 100644 --- a/src/client/components/ComicDetail/RawFileDetails.tsx +++ b/src/client/components/ComicDetail/RawFileDetails.tsx @@ -38,7 +38,7 @@ export const RawFileDetails = (props): ReactElement => {
-
+
{/* inferred metadata */}
Inferred Issue Metadata
diff --git a/src/client/components/Dashboard/Dashboard.tsx b/src/client/components/Dashboard/Dashboard.tsx index 4a724c7..77db77a 100644 --- a/src/client/components/Dashboard/Dashboard.tsx +++ b/src/client/components/Dashboard/Dashboard.tsx @@ -11,7 +11,7 @@ import { getComicBooks, } from "../../actions/fileops.actions"; import { getLibraryStatistics } from "../../actions/comicinfo.actions"; -import { isEmpty } from "lodash"; +import { isEmpty, isNil } from "lodash"; export const Dashboard = (): ReactElement => { const dispatch = useDispatch(); @@ -43,7 +43,7 @@ export const Dashboard = (): ReactElement => { }, []); const recentComics = useSelector( - (state: RootState) => state.fileOps.recentComics, + (state: RootState) => state.fileOps.recentComics ); const wantedComics = useSelector( (state: RootState) => state.fileOps.wantedComics, @@ -60,7 +60,7 @@ export const Dashboard = (): ReactElement => {

Dashboard

- {!isEmpty(recentComics) && !isEmpty(recentComics.docs) ? ( + {!isEmpty(recentComics) ? ( <> {/* Pull List */} @@ -74,9 +74,8 @@ export const Dashboard = (): ReactElement => { )} {/* Recent imports */} - {!isEmpty(recentComics) && ( - )} + {/* Volumes */} {!isEmpty(volumeGroups) && ( diff --git a/src/client/components/Dashboard/PullList.tsx b/src/client/components/Dashboard/PullList.tsx index 4b62d86..b00fe82 100644 --- a/src/client/components/Dashboard/PullList.tsx +++ b/src/client/components/Dashboard/PullList.tsx @@ -20,7 +20,7 @@ export const PullList = ({ issues }: PullListProps): ReactElement => { useEffect(() => { dispatch( getWeeklyPullList({ - startDate: "2022-11-15", + startDate: "2022-12-25", pageSize: "15", currentPage: "1", }), diff --git a/src/client/components/Dashboard/RecentlyImported.tsx b/src/client/components/Dashboard/RecentlyImported.tsx index ad784e2..b26b954 100644 --- a/src/client/components/Dashboard/RecentlyImported.tsx +++ b/src/client/components/Dashboard/RecentlyImported.tsx @@ -24,7 +24,6 @@ export const RecentlyImported = ({ 700: 2, 600: 2, }; - return ( <>
@@ -41,7 +40,7 @@ export const RecentlyImported = ({ columnClassName="recent-comics-column" > {map( - comicBookCovers.docs, + comicBookCovers, ( { _id, @@ -53,6 +52,7 @@ export const RecentlyImported = ({ }, idx, ) => { + console.log(comicvine); const { issueName, url } = determineCoverFile({ rawFileDetails, comicvine, @@ -64,7 +64,7 @@ export const RecentlyImported = ({ comicInfo, locg, }); - + console.log(name); const isComicBookMetadataAvailable = !isUndefined(comicvine) && !isUndefined(comicvine.volumeInformation); @@ -123,7 +123,7 @@ export const RecentlyImported = ({
{/* metadata card */} - {!isNil(name) ? ( + {!isNil(name) && (
@@ -138,7 +138,7 @@ export const RecentlyImported = ({
- ) : null} + )} ); }, diff --git a/src/client/reducers/fileops.reducer.ts b/src/client/reducers/fileops.reducer.ts index 2b3596b..cdbda61 100644 --- a/src/client/reducers/fileops.reducer.ts +++ b/src/client/reducers/fileops.reducer.ts @@ -88,7 +88,7 @@ function fileOpsReducer(state = initialState, action) { case IMS_RECENT_COMICS_FETCHED: return { ...state, - recentComics: action.data, + recentComics: action.data.docs, }; case IMS_WANTED_COMICS_FETCHED: return { @@ -153,9 +153,13 @@ function fileOpsReducer(state = initialState, action) { } case LS_COVER_EXTRACTED: { console.log("BASH", action); + if(state.recentComics.length === 5) { + state.recentComics.pop(); + } return { ...state, librarySearchResultCount: state.librarySearchResultCount + 1, + recentComics: [...state.recentComics, action.result.data.importResult] }; } @@ -172,7 +176,7 @@ function fileOpsReducer(state = initialState, action) { return { ...state, extractedComicBookArchive: { - reading: comicBookPages + reading: comicBookPages, }, comicBookExtractionInProgress: false, }; @@ -181,12 +185,11 @@ function fileOpsReducer(state = initialState, action) { return { ...state, extractedComicBookArchive: { - analysis: comicBookPages + analysis: comicBookPages, }, comicBookExtractionInProgress: false, }; } - } case LS_QUEUE_DRAINED: { console.log("drained", action); diff --git a/src/client/shared/utils/metadata.utils.ts b/src/client/shared/utils/metadata.utils.ts index 4130fe0..f32c325 100644 --- a/src/client/shared/utils/metadata.utils.ts +++ b/src/client/shared/utils/metadata.utils.ts @@ -67,7 +67,10 @@ export const determineCoverFile = (data) => { } }; -export const determineExternalMetadata = (metadataSource, source) => { +export const determineExternalMetadata = ( + metadataSource: string, + source: any +) => { switch (metadataSource) { case "comicvine": return { diff --git a/yarn.lock b/yarn.lock index 42a1571..404f961 100644 --- a/yarn.lock +++ b/yarn.lock @@ -15607,7 +15607,7 @@ react-transition-group@4.4.2, react-transition-group@^4.3.0: loose-envify "^1.4.0" prop-types "^15.6.2" -react@^18.1.0: +react@^18.2.0: version "18.2.0" resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5" integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ== -- 2.49.1 From d065225d8e530d5fe37ae8f363f1d22f5f7578db Mon Sep 17 00:00:00 2001 From: Rishi Ghan Date: Wed, 21 Dec 2022 21:17:38 -0800 Subject: [PATCH 09/10] =?UTF-8?q?=F0=9F=8F=97=EF=B8=8F=20Refactoring=20arc?= =?UTF-8?q?hive=20uncompression=20for=20"Read=20Comic"=20and=20"Analysis"?= =?UTF-8?q?=20user=20flows=20(#46)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 🔧 Refactoring uncompression methods on client-side * ✏️ Refactoring * 👁️ Updates to the comic viewer * 🖼️ Added screenshots from December 2022 * ✏️ Fixed typo in README * 🏗️ Massive refactor around archive uncompression for reading/analysis * 🔧 Tweaked state vars for reading and analysis * 🏗️ Refactor to support DC++ and socket.io integration This refactor covers the following workflows: 1. Adding a comic from LOCG or ComicVine adds it to the wanted list 2. Downloading that comic from DC++ correctly adds download metadata to the corresponding comic object in mongo 3. Successful download triggers automatic import to library and cover extraction, metadata application --- package.json | 2 +- src/client/actions/fileops.actions.tsx | 91 +++++++++---------- src/client/components/App.tsx | 47 +++++++--- .../ComicDetail/AcquisitionPanel.tsx | 8 +- .../components/ComicDetail/ComicDetail.tsx | 4 +- .../components/ComicDetail/RawFileDetails.tsx | 3 +- .../ComicDetail/Tabs/ArchiveOperations.tsx | 12 ++- src/client/components/Dashboard/Dashboard.tsx | 9 +- src/client/components/Dashboard/PullList.tsx | 2 +- .../components/Dashboard/RecentlyImported.tsx | 10 +- src/client/constants/action-types.ts | 2 + src/client/reducers/fileops.reducer.ts | 54 +++++++++-- src/client/shared/utils/metadata.utils.ts | 5 +- yarn.lock | 2 +- 14 files changed, 158 insertions(+), 93 deletions(-) diff --git a/package.json b/package.json index d8433f2..3c1f1f0 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "pretty-bytes": "^5.6.0", "prop-types": "^15.8.1", "qs": "^6.10.5", - "react": "^18.1.0", + "react": "^18.2.0", "react-collapsible": "^2.9.0", "react-comic-viewer": "^0.4.0", "react-day-picker": "^8.0.6", diff --git a/src/client/actions/fileops.actions.tsx b/src/client/actions/fileops.actions.tsx index ee03372..1c25dc0 100644 --- a/src/client/actions/fileops.actions.tsx +++ b/src/client/actions/fileops.actions.tsx @@ -36,7 +36,7 @@ import { CV_WEEKLY_PULLLIST_FETCHED, } from "../constants/action-types"; import { success } from "react-notification-system-redux"; -import { removeLeadingPeriod } from "../shared/utils/formatting.utils"; + import { isNil, map } from "lodash"; export async function walkFolder(path: string): Promise> { @@ -60,15 +60,6 @@ export async function walkFolder(path: string): Promise> { * @return the comic book metadata */ export const fetchComicBookMetadata = () => async (dispatch) => { - const extractionOptions = { - extractTarget: "cover", - targetExtractionFolder: "./userdata/covers", - extractionMode: "bulk", - paginationOptions: { - pageLimit: 25, - page: 1, - }, - }; dispatch({ type: LS_IMPORT_CALL_IN_PROGRESS, }); @@ -86,7 +77,7 @@ export const fetchComicBookMetadata = () => async (dispatch) => { dispatch({ type: LS_IMPORT, meta: { remote: true }, - data: { extractionOptions }, + data: {}, }); }; export const toggleImportQueueStatus = (options) => async (dispatch) => { @@ -136,21 +127,24 @@ export const getComicBooks = (options) => async (dispatch) => { * @returns Nothing. * @param payload */ -export const importToDB = (sourceName: string, payload?: any) => (dispatch) => { +export const importToDB = (sourceName: string, metadata?: any) => (dispatch) => { try { const comicBookMetadata = { - rawFileDetails: { - name: "", - }, - importStatus: { - isImported: true, - tagged: false, - matchedResult: { - score: "0", + importType: "new", + payload: { + rawFileDetails: { + name: "", }, - }, - sourcedMetadata: payload || null, - acquisition: { source: { wanted: true, name: sourceName } }, + importStatus: { + isImported: true, + tagged: false, + matchedResult: { + score: "0", + }, + }, + sourcedMetadata: metadata || null, + acquisition: { source: { wanted: true, name: sourceName } }, + } }; dispatch({ type: IMS_CV_METADATA_IMPORT_CALL_IN_PROGRESS, @@ -260,34 +254,31 @@ export const fetchComicVineMatches = * @returns {any} */ export const extractComicArchive = - (path: string, options: any): any => async (dispatch) => { - const comicBookPages: string[] = []; - console.log(options); - dispatch({ - type: IMS_COMIC_BOOK_ARCHIVE_EXTRACTION_CALL_IN_PROGRESS, - }); - const extractedComicBookArchive = await axios({ - method: "POST", - url: `${LIBRARY_SERVICE_BASE_URI}/uncompressFullArchive`, - headers: { - "Content-Type": "application/json; charset=utf-8", - }, - data: { - filePath: path, - options, - }, - }); - map(extractedComicBookArchive.data, (page) => { - const pageFilePath = removeLeadingPeriod(page); - const imagePath = encodeURI(`${LIBRARY_SERVICE_HOST}${pageFilePath}`); - comicBookPages.push(imagePath); - }); - dispatch({ - type: IMS_COMIC_BOOK_ARCHIVE_EXTRACTION_SUCCESS, - extractedComicBookArchive: comicBookPages, - }); - }; + (path: string, options: any): any => + async (dispatch) => { + dispatch({ + type: IMS_COMIC_BOOK_ARCHIVE_EXTRACTION_CALL_IN_PROGRESS, + }); + await axios({ + method: "POST", + url: `${LIBRARY_SERVICE_BASE_URI}/uncompressFullArchive`, + headers: { + "Content-Type": "application/json; charset=utf-8", + }, + data: { + filePath: path, + options, + }, + }); + }; + +/** + * Description + * @param {any} query + * @param {any} options + * @returns {any} + */ export const searchIssue = (query, options) => async (dispatch) => { dispatch({ type: SS_SEARCH_IN_PROGRESS, diff --git a/src/client/components/App.tsx b/src/client/components/App.tsx index 2efa3e7..6446767 100644 --- a/src/client/components/App.tsx +++ b/src/client/components/App.tsx @@ -18,18 +18,22 @@ import { AirDCPPSocketContext, } from "../context/AirDCPPSocket"; import { isEmpty, isUndefined } from "lodash"; -import { AIRDCPP_DOWNLOAD_PROGRESS_TICK } from "../constants/action-types"; -import { useDispatch } from "react-redux"; +import { + AIRDCPP_DOWNLOAD_PROGRESS_TICK, + LS_SINGLE_IMPORT, +} from "../constants/action-types"; +import { useDispatch, useSelector } from "react-redux"; /** * Method that initializes an AirDC++ socket connection * 1. Initializes event listeners for download init, tick and complete events - * 2. Handles errors in case the connection to AirDC++ is not established or terminated - * @returns void + * 2. Handles errors in case the connection to AirDC++ is not established or terminated + * @returns void */ const AirDCPPSocketComponent = (): ReactElement => { const airDCPPConfiguration = useContext(AirDCPPSocketContext); const dispatch = useDispatch(); + useEffect(() => { const initializeAirDCPPEventListeners = async () => { if ( @@ -42,9 +46,7 @@ const AirDCPPSocketComponent = (): ReactElement => { "queue_bundle_added", async (data) => { console.log("JEMEN:", data); - - - } + }, ); // download tick listener await airDCPPConfiguration.airDCPPState.socket.addListener( @@ -62,9 +64,18 @@ const AirDCPPSocketComponent = (): ReactElement => { `queue`, "queue_bundle_status", async (bundleData) => { + let count = 0; if (bundleData.status.completed && bundleData.status.downloaded) { // dispatch the action for raw import, with the metadata - console.log("IM THE MAN UP IN THIS") + if (count < 1) { + console.log(`[AirDCPP]: Download complete.`); + dispatch({ + type: LS_SINGLE_IMPORT, + meta: { remote: true }, + data: bundleData, + }); + count += 1; + } } }, ); @@ -92,7 +103,10 @@ export const App = (): ReactElement => { } /> } /> - } /> + } + /> } /> } /> } /> @@ -105,9 +119,18 @@ export const App = (): ReactElement => { element={} /> } /> - } /> - } /> - } /> + } + /> + } + /> + } + />
diff --git a/src/client/components/ComicDetail/AcquisitionPanel.tsx b/src/client/components/ComicDetail/AcquisitionPanel.tsx index 97d0c3d..a6c8ec2 100644 --- a/src/client/components/ComicDetail/AcquisitionPanel.tsx +++ b/src/client/components/ComicDetail/AcquisitionPanel.tsx @@ -16,6 +16,7 @@ import ellipsize from "ellipsize"; import { Form, Field } from "react-final-form"; import { isEmpty, isNil, map } from "lodash"; import { AirDCPPSocketContext } from "../../context/AirDCPPSocket"; + interface IAcquisitionPanelProps { query: any; comicObjectId: any; @@ -96,9 +97,12 @@ export const AcquisitionPanel = ( (searchInstanceId, resultId, name, size, type) => { dispatch( downloadAirDCPPItem( - searchInstanceId, resultId, + searchInstanceId, + resultId, props.comicObjectId, - name, size, type, + name, + size, + type, airDCPPConfiguration.airDCPPState.socket, { username: `${airDCPPConfiguration.airDCPPState.settings.directConnect.client.host.username}`, diff --git a/src/client/components/ComicDetail/ComicDetail.tsx b/src/client/components/ComicDetail/ComicDetail.tsx index 0145c09..66076eb 100644 --- a/src/client/components/ComicDetail/ComicDetail.tsx +++ b/src/client/components/ComicDetail/ComicDetail.tsx @@ -66,7 +66,7 @@ export const ComicDetail = (data: ComicDetailProps): ReactElement => { ); const extractedComicBook = useSelector( - (state: RootState) => state.fileOps.extractedComicBookArchive, + (state: RootState) => state.fileOps.extractedComicBookArchive.reading, ); const { comicObjectId } = useParams<{ comicObjectId: string }>(); @@ -77,7 +77,7 @@ export const ComicDetail = (data: ComicDetailProps): ReactElement => { dispatch( extractComicArchive(filePath, { type: "full", - purpose: "readComicBook", + purpose: "reading", imageResizeOptions: { baseWidth: 1024, }, diff --git a/src/client/components/ComicDetail/RawFileDetails.tsx b/src/client/components/ComicDetail/RawFileDetails.tsx index 7db0d4f..f2fa448 100644 --- a/src/client/components/ComicDetail/RawFileDetails.tsx +++ b/src/client/components/ComicDetail/RawFileDetails.tsx @@ -38,7 +38,8 @@ export const RawFileDetails = (props): ReactElement => {
-
+ +
{/* inferred metadata */}
Inferred Issue Metadata
diff --git a/src/client/components/ComicDetail/Tabs/ArchiveOperations.tsx b/src/client/components/ComicDetail/Tabs/ArchiveOperations.tsx index c9655ed..839dcdc 100644 --- a/src/client/components/ComicDetail/Tabs/ArchiveOperations.tsx +++ b/src/client/components/ComicDetail/Tabs/ArchiveOperations.tsx @@ -14,7 +14,7 @@ export const ArchiveOperations = (props): ReactElement => { (state: RootState) => state.fileOps.comicBookExtractionInProgress, ); const extractedComicBookArchive = useSelector( - (state: RootState) => state.fileOps.extractedComicBookArchive, + (state: RootState) => state.fileOps.extractedComicBookArchive.analysis, ); const imageAnalysisResult = useSelector((state: RootState) => { @@ -23,7 +23,15 @@ export const ArchiveOperations = (props): ReactElement => { const dispatch = useDispatch(); const unpackComicArchive = useCallback(() => { - dispatch(extractComicArchive(data.rawFileDetails.filePath)); + dispatch( + extractComicArchive(data.rawFileDetails.filePath, { + type: "full", + purpose: "analysis", + imageResizeOptions: { + baseWidth: 275, + }, + }), + ); }, []); // sliding panel config diff --git a/src/client/components/Dashboard/Dashboard.tsx b/src/client/components/Dashboard/Dashboard.tsx index 4a724c7..77db77a 100644 --- a/src/client/components/Dashboard/Dashboard.tsx +++ b/src/client/components/Dashboard/Dashboard.tsx @@ -11,7 +11,7 @@ import { getComicBooks, } from "../../actions/fileops.actions"; import { getLibraryStatistics } from "../../actions/comicinfo.actions"; -import { isEmpty } from "lodash"; +import { isEmpty, isNil } from "lodash"; export const Dashboard = (): ReactElement => { const dispatch = useDispatch(); @@ -43,7 +43,7 @@ export const Dashboard = (): ReactElement => { }, []); const recentComics = useSelector( - (state: RootState) => state.fileOps.recentComics, + (state: RootState) => state.fileOps.recentComics ); const wantedComics = useSelector( (state: RootState) => state.fileOps.wantedComics, @@ -60,7 +60,7 @@ export const Dashboard = (): ReactElement => {

Dashboard

- {!isEmpty(recentComics) && !isEmpty(recentComics.docs) ? ( + {!isEmpty(recentComics) ? ( <> {/* Pull List */} @@ -74,9 +74,8 @@ export const Dashboard = (): ReactElement => { )} {/* Recent imports */} - {!isEmpty(recentComics) && ( - )} + {/* Volumes */} {!isEmpty(volumeGroups) && ( diff --git a/src/client/components/Dashboard/PullList.tsx b/src/client/components/Dashboard/PullList.tsx index 4b62d86..b00fe82 100644 --- a/src/client/components/Dashboard/PullList.tsx +++ b/src/client/components/Dashboard/PullList.tsx @@ -20,7 +20,7 @@ export const PullList = ({ issues }: PullListProps): ReactElement => { useEffect(() => { dispatch( getWeeklyPullList({ - startDate: "2022-11-15", + startDate: "2022-12-25", pageSize: "15", currentPage: "1", }), diff --git a/src/client/components/Dashboard/RecentlyImported.tsx b/src/client/components/Dashboard/RecentlyImported.tsx index ad784e2..b26b954 100644 --- a/src/client/components/Dashboard/RecentlyImported.tsx +++ b/src/client/components/Dashboard/RecentlyImported.tsx @@ -24,7 +24,6 @@ export const RecentlyImported = ({ 700: 2, 600: 2, }; - return ( <>
@@ -41,7 +40,7 @@ export const RecentlyImported = ({ columnClassName="recent-comics-column" > {map( - comicBookCovers.docs, + comicBookCovers, ( { _id, @@ -53,6 +52,7 @@ export const RecentlyImported = ({ }, idx, ) => { + console.log(comicvine); const { issueName, url } = determineCoverFile({ rawFileDetails, comicvine, @@ -64,7 +64,7 @@ export const RecentlyImported = ({ comicInfo, locg, }); - + console.log(name); const isComicBookMetadataAvailable = !isUndefined(comicvine) && !isUndefined(comicvine.volumeInformation); @@ -123,7 +123,7 @@ export const RecentlyImported = ({
{/* metadata card */} - {!isNil(name) ? ( + {!isNil(name) && (
@@ -138,7 +138,7 @@ export const RecentlyImported = ({
- ) : null} + )} ); }, diff --git a/src/client/constants/action-types.ts b/src/client/constants/action-types.ts index a6be92d..f058853 100644 --- a/src/client/constants/action-types.ts +++ b/src/client/constants/action-types.ts @@ -81,6 +81,8 @@ export const IMS_COMIC_BOOK_ARCHIVE_EXTRACTION_CALL_IN_PROGRESS = export const IMS_COMIC_BOOK_ARCHIVE_EXTRACTION_CALL_FAILED = "IMS_COMIC_BOOK_ARCHIVE_EXTRACTION_CALL_FAILED"; +export const COMICBOOK_EXTRACTION_SUCCESS = "COMICBOOK_EXTRACTION_SUCCESS"; + // Image file stats export const IMG_ANALYSIS_CALL_IN_PROGRESS = "IMG_ANALYSIS_CALL_IN_PROGRESS"; export const IMG_ANALYSIS_DATA_FETCH_SUCCESS = diff --git a/src/client/reducers/fileops.reducer.ts b/src/client/reducers/fileops.reducer.ts index 2060797..cdbda61 100644 --- a/src/client/reducers/fileops.reducer.ts +++ b/src/client/reducers/fileops.reducer.ts @@ -29,7 +29,11 @@ import { SS_SEARCH_FAILED, SS_SEARCH_RESULTS_FETCHED_SPECIAL, VOLUMES_FETCHED, + COMICBOOK_EXTRACTION_SUCCESS, } from "../constants/action-types"; +import { removeLeadingPeriod } from "../shared/utils/formatting.utils"; +import { LIBRARY_SERVICE_HOST } from "../constants/endpoints"; + const initialState = { IMSCallInProgress: false, IMGCallInProgress: false, @@ -42,7 +46,10 @@ const initialState = { isComicVineMetadataImportInProgress: false, comicVineMetadataImportError: {}, rawImportError: {}, - extractedComicBookArchive: [], + extractedComicBookArchive: { + reading: [], + analysis: [], + }, recentComics: [], wantedComics: [], libraryComics: [], @@ -81,7 +88,7 @@ function fileOpsReducer(state = initialState, action) { case IMS_RECENT_COMICS_FETCHED: return { ...state, - recentComics: action.data, + recentComics: action.data.docs, }; case IMS_WANTED_COMICS_FETCHED: return { @@ -131,13 +138,7 @@ function fileOpsReducer(state = initialState, action) { comicBookExtractionInProgress: true, }; } - case IMS_COMIC_BOOK_ARCHIVE_EXTRACTION_SUCCESS: { - return { - ...state, - extractedComicBookArchive: action.extractedComicBookArchive, - comicBookExtractionInProgress: false, - }; - } + case LOCATION_CHANGE: { return { ...state, @@ -152,11 +153,44 @@ function fileOpsReducer(state = initialState, action) { } case LS_COVER_EXTRACTED: { console.log("BASH", action); + if(state.recentComics.length === 5) { + state.recentComics.pop(); + } return { ...state, librarySearchResultCount: state.librarySearchResultCount + 1, + recentComics: [...state.recentComics, action.result.data.importResult] }; } + + case COMICBOOK_EXTRACTION_SUCCESS: { + const comicBookPages: string[] = []; + map(action.result.files, (page) => { + const pageFilePath = removeLeadingPeriod(page); + const imagePath = encodeURI(`${LIBRARY_SERVICE_HOST}${pageFilePath}`); + comicBookPages.push(imagePath); + }); + + switch (action.result.purpose) { + case "reading": + return { + ...state, + extractedComicBookArchive: { + reading: comicBookPages, + }, + comicBookExtractionInProgress: false, + }; + + case "analysis": + return { + ...state, + extractedComicBookArchive: { + analysis: comicBookPages, + }, + comicBookExtractionInProgress: false, + }; + } + } case LS_QUEUE_DRAINED: { console.log("drained", action); return { @@ -229,7 +263,7 @@ function fileOpsReducer(state = initialState, action) { volumes: action.data, SSCallInProgress: false, }; - + case SS_SEARCH_FAILED: { return { ...state, diff --git a/src/client/shared/utils/metadata.utils.ts b/src/client/shared/utils/metadata.utils.ts index 4130fe0..f32c325 100644 --- a/src/client/shared/utils/metadata.utils.ts +++ b/src/client/shared/utils/metadata.utils.ts @@ -67,7 +67,10 @@ export const determineCoverFile = (data) => { } }; -export const determineExternalMetadata = (metadataSource, source) => { +export const determineExternalMetadata = ( + metadataSource: string, + source: any +) => { switch (metadataSource) { case "comicvine": return { diff --git a/yarn.lock b/yarn.lock index c4af02d..a11303c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -15607,7 +15607,7 @@ react-transition-group@4.4.2, react-transition-group@^4.3.0: loose-envify "^1.4.0" prop-types "^15.6.2" -react@^18.1.0: +react@^18.2.0: version "18.2.0" resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5" integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ== -- 2.49.1 From ce6653b5d789bd4b1db006c065da68b2b0dc6476 Mon Sep 17 00:00:00 2001 From: Rishi Ghan Date: Wed, 21 Dec 2022 21:49:12 -0800 Subject: [PATCH 10/10] =?UTF-8?q?=20=F0=9F=8F=97=EF=B8=8F=20=20Applying=20?= =?UTF-8?q?the=20refactor=20patc?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 4 +- src/client/actions/fileops.actions.tsx | 93 +++++++++---------- src/client/components/App.tsx | 49 +++++++--- .../ComicDetail/AcquisitionPanel.tsx | 10 +- .../components/ComicDetail/ComicDetail.tsx | 6 +- .../components/ComicDetail/RawFileDetails.tsx | 5 +- .../ComicDetail/Tabs/ArchiveOperations.tsx | 14 ++- src/client/components/Dashboard/Dashboard.tsx | 11 +-- src/client/components/Dashboard/PullList.tsx | 4 +- .../components/Dashboard/RecentlyImported.tsx | 13 ++- src/client/constants/action-types.ts | 4 +- src/client/reducers/fileops.reducer.ts | 56 ++++++++--- src/client/shared/utils/metadata.utils.ts | 7 +- 13 files changed, 170 insertions(+), 106 deletions(-) diff --git a/package.json b/package.json index d8433f2..ff95b58 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "pretty-bytes": "^5.6.0", "prop-types": "^15.8.1", "qs": "^6.10.5", - "react": "^18.1.0", + "react": "^18.2.0", "react-collapsible": "^2.9.0", "react-comic-viewer": "^0.4.0", "react-day-picker": "^8.0.6", @@ -182,4 +182,4 @@ "resolutions": { "@storybook/react/webpack": "^5" } -} +} \ No newline at end of file diff --git a/src/client/actions/fileops.actions.tsx b/src/client/actions/fileops.actions.tsx index ee03372..fb2098a 100644 --- a/src/client/actions/fileops.actions.tsx +++ b/src/client/actions/fileops.actions.tsx @@ -36,7 +36,7 @@ import { CV_WEEKLY_PULLLIST_FETCHED, } from "../constants/action-types"; import { success } from "react-notification-system-redux"; -import { removeLeadingPeriod } from "../shared/utils/formatting.utils"; + import { isNil, map } from "lodash"; export async function walkFolder(path: string): Promise> { @@ -60,15 +60,6 @@ export async function walkFolder(path: string): Promise> { * @return the comic book metadata */ export const fetchComicBookMetadata = () => async (dispatch) => { - const extractionOptions = { - extractTarget: "cover", - targetExtractionFolder: "./userdata/covers", - extractionMode: "bulk", - paginationOptions: { - pageLimit: 25, - page: 1, - }, - }; dispatch({ type: LS_IMPORT_CALL_IN_PROGRESS, }); @@ -86,7 +77,7 @@ export const fetchComicBookMetadata = () => async (dispatch) => { dispatch({ type: LS_IMPORT, meta: { remote: true }, - data: { extractionOptions }, + data: {}, }); }; export const toggleImportQueueStatus = (options) => async (dispatch) => { @@ -136,21 +127,24 @@ export const getComicBooks = (options) => async (dispatch) => { * @returns Nothing. * @param payload */ -export const importToDB = (sourceName: string, payload?: any) => (dispatch) => { +export const importToDB = (sourceName: string, metadata?: any) => (dispatch) => { try { const comicBookMetadata = { - rawFileDetails: { - name: "", - }, - importStatus: { - isImported: true, - tagged: false, - matchedResult: { - score: "0", + importType: "new", + payload: { + rawFileDetails: { + name: "", }, - }, - sourcedMetadata: payload || null, - acquisition: { source: { wanted: true, name: sourceName } }, + importStatus: { + isImported: true, + tagged: false, + matchedResult: { + score: "0", + }, + }, + sourcedMetadata: metadata || null, + acquisition: { source: { wanted: true, name: sourceName } }, + } }; dispatch({ type: IMS_CV_METADATA_IMPORT_CALL_IN_PROGRESS, @@ -260,34 +254,31 @@ export const fetchComicVineMatches = * @returns {any} */ export const extractComicArchive = - (path: string, options: any): any => async (dispatch) => { - const comicBookPages: string[] = []; - console.log(options); - dispatch({ - type: IMS_COMIC_BOOK_ARCHIVE_EXTRACTION_CALL_IN_PROGRESS, - }); - const extractedComicBookArchive = await axios({ - method: "POST", - url: `${LIBRARY_SERVICE_BASE_URI}/uncompressFullArchive`, - headers: { - "Content-Type": "application/json; charset=utf-8", - }, - data: { - filePath: path, - options, - }, - }); - map(extractedComicBookArchive.data, (page) => { - const pageFilePath = removeLeadingPeriod(page); - const imagePath = encodeURI(`${LIBRARY_SERVICE_HOST}${pageFilePath}`); - comicBookPages.push(imagePath); - }); - dispatch({ - type: IMS_COMIC_BOOK_ARCHIVE_EXTRACTION_SUCCESS, - extractedComicBookArchive: comicBookPages, - }); - }; + (path: string, options: any): any => + async (dispatch) => { + dispatch({ + type: IMS_COMIC_BOOK_ARCHIVE_EXTRACTION_CALL_IN_PROGRESS, + }); + await axios({ + method: "POST", + url: `${LIBRARY_SERVICE_BASE_URI}/uncompressFullArchive`, + headers: { + "Content-Type": "application/json; charset=utf-8", + }, + data: { + filePath: path, + options, + }, + }); + }; + +/** + * Description + * @param {any} query + * @param {any} options + * @returns {any} + */ export const searchIssue = (query, options) => async (dispatch) => { dispatch({ type: SS_SEARCH_IN_PROGRESS, @@ -358,4 +349,4 @@ export const analyzeImage = type: IMG_ANALYSIS_DATA_FETCH_SUCCESS, result: foo.data, }); - }; + }; \ No newline at end of file diff --git a/src/client/components/App.tsx b/src/client/components/App.tsx index 2efa3e7..1df28b4 100644 --- a/src/client/components/App.tsx +++ b/src/client/components/App.tsx @@ -18,18 +18,22 @@ import { AirDCPPSocketContext, } from "../context/AirDCPPSocket"; import { isEmpty, isUndefined } from "lodash"; -import { AIRDCPP_DOWNLOAD_PROGRESS_TICK } from "../constants/action-types"; -import { useDispatch } from "react-redux"; +import { + AIRDCPP_DOWNLOAD_PROGRESS_TICK, + LS_SINGLE_IMPORT, +} from "../constants/action-types"; +import { useDispatch, useSelector } from "react-redux"; /** * Method that initializes an AirDC++ socket connection * 1. Initializes event listeners for download init, tick and complete events - * 2. Handles errors in case the connection to AirDC++ is not established or terminated - * @returns void + * 2. Handles errors in case the connection to AirDC++ is not established or terminated + * @returns void */ const AirDCPPSocketComponent = (): ReactElement => { const airDCPPConfiguration = useContext(AirDCPPSocketContext); const dispatch = useDispatch(); + useEffect(() => { const initializeAirDCPPEventListeners = async () => { if ( @@ -42,9 +46,7 @@ const AirDCPPSocketComponent = (): ReactElement => { "queue_bundle_added", async (data) => { console.log("JEMEN:", data); - - - } + }, ); // download tick listener await airDCPPConfiguration.airDCPPState.socket.addListener( @@ -62,9 +64,18 @@ const AirDCPPSocketComponent = (): ReactElement => { `queue`, "queue_bundle_status", async (bundleData) => { + let count = 0; if (bundleData.status.completed && bundleData.status.downloaded) { // dispatch the action for raw import, with the metadata - console.log("IM THE MAN UP IN THIS") + if (count < 1) { + console.log(`[AirDCPP]: Download complete.`); + dispatch({ + type: LS_SINGLE_IMPORT, + meta: { remote: true }, + data: bundleData, + }); + count += 1; + } } }, ); @@ -92,7 +103,10 @@ export const App = (): ReactElement => { } /> } /> - } /> + } + /> } /> } /> } /> @@ -105,13 +119,22 @@ export const App = (): ReactElement => { element={} /> } /> - } /> - } /> - } /> + } + /> + } + /> + } + />
); }; -export default App; +export default App; \ No newline at end of file diff --git a/src/client/components/ComicDetail/AcquisitionPanel.tsx b/src/client/components/ComicDetail/AcquisitionPanel.tsx index 97d0c3d..f04fcde 100644 --- a/src/client/components/ComicDetail/AcquisitionPanel.tsx +++ b/src/client/components/ComicDetail/AcquisitionPanel.tsx @@ -16,6 +16,7 @@ import ellipsize from "ellipsize"; import { Form, Field } from "react-final-form"; import { isEmpty, isNil, map } from "lodash"; import { AirDCPPSocketContext } from "../../context/AirDCPPSocket"; + interface IAcquisitionPanelProps { query: any; comicObjectId: any; @@ -96,9 +97,12 @@ export const AcquisitionPanel = ( (searchInstanceId, resultId, name, size, type) => { dispatch( downloadAirDCPPItem( - searchInstanceId, resultId, + searchInstanceId, + resultId, props.comicObjectId, - name, size, type, + name, + size, + type, airDCPPConfiguration.airDCPPState.socket, { username: `${airDCPPConfiguration.airDCPPState.settings.directConnect.client.host.username}`, @@ -332,4 +336,4 @@ export const AcquisitionPanel = ( ); }; -export default AcquisitionPanel; +export default AcquisitionPanel; \ No newline at end of file diff --git a/src/client/components/ComicDetail/ComicDetail.tsx b/src/client/components/ComicDetail/ComicDetail.tsx index 0145c09..ca54014 100644 --- a/src/client/components/ComicDetail/ComicDetail.tsx +++ b/src/client/components/ComicDetail/ComicDetail.tsx @@ -66,7 +66,7 @@ export const ComicDetail = (data: ComicDetailProps): ReactElement => { ); const extractedComicBook = useSelector( - (state: RootState) => state.fileOps.extractedComicBookArchive, + (state: RootState) => state.fileOps.extractedComicBookArchive.reading, ); const { comicObjectId } = useParams<{ comicObjectId: string }>(); @@ -77,7 +77,7 @@ export const ComicDetail = (data: ComicDetailProps): ReactElement => { dispatch( extractComicArchive(filePath, { type: "full", - purpose: "readComicBook", + purpose: "reading", imageResizeOptions: { baseWidth: 1024, }, @@ -317,4 +317,4 @@ export const ComicDetail = (data: ComicDetailProps): ReactElement => { ); }; -export default ComicDetail; +export default ComicDetail; \ No newline at end of file diff --git a/src/client/components/ComicDetail/RawFileDetails.tsx b/src/client/components/ComicDetail/RawFileDetails.tsx index 7db0d4f..3455598 100644 --- a/src/client/components/ComicDetail/RawFileDetails.tsx +++ b/src/client/components/ComicDetail/RawFileDetails.tsx @@ -38,7 +38,8 @@ export const RawFileDetails = (props): ReactElement => {
-
+ +
{/* inferred metadata */}
Inferred Issue Metadata
@@ -93,4 +94,4 @@ RawFileDetails.propTypes = { }), }), }), -}; +}; \ No newline at end of file diff --git a/src/client/components/ComicDetail/Tabs/ArchiveOperations.tsx b/src/client/components/ComicDetail/Tabs/ArchiveOperations.tsx index c9655ed..ed15699 100644 --- a/src/client/components/ComicDetail/Tabs/ArchiveOperations.tsx +++ b/src/client/components/ComicDetail/Tabs/ArchiveOperations.tsx @@ -14,7 +14,7 @@ export const ArchiveOperations = (props): ReactElement => { (state: RootState) => state.fileOps.comicBookExtractionInProgress, ); const extractedComicBookArchive = useSelector( - (state: RootState) => state.fileOps.extractedComicBookArchive, + (state: RootState) => state.fileOps.extractedComicBookArchive.analysis, ); const imageAnalysisResult = useSelector((state: RootState) => { @@ -23,7 +23,15 @@ export const ArchiveOperations = (props): ReactElement => { const dispatch = useDispatch(); const unpackComicArchive = useCallback(() => { - dispatch(extractComicArchive(data.rawFileDetails.filePath)); + dispatch( + extractComicArchive(data.rawFileDetails.filePath, { + type: "full", + purpose: "analysis", + imageResizeOptions: { + baseWidth: 275, + }, + }), + ); }, []); // sliding panel config @@ -118,4 +126,4 @@ export const ArchiveOperations = (props): ReactElement => { ); }; -export default ArchiveOperations; +export default ArchiveOperations; \ No newline at end of file diff --git a/src/client/components/Dashboard/Dashboard.tsx b/src/client/components/Dashboard/Dashboard.tsx index 4a724c7..4978d23 100644 --- a/src/client/components/Dashboard/Dashboard.tsx +++ b/src/client/components/Dashboard/Dashboard.tsx @@ -11,7 +11,7 @@ import { getComicBooks, } from "../../actions/fileops.actions"; import { getLibraryStatistics } from "../../actions/comicinfo.actions"; -import { isEmpty } from "lodash"; +import { isEmpty, isNil } from "lodash"; export const Dashboard = (): ReactElement => { const dispatch = useDispatch(); @@ -43,7 +43,7 @@ export const Dashboard = (): ReactElement => { }, []); const recentComics = useSelector( - (state: RootState) => state.fileOps.recentComics, + (state: RootState) => state.fileOps.recentComics ); const wantedComics = useSelector( (state: RootState) => state.fileOps.wantedComics, @@ -60,7 +60,7 @@ export const Dashboard = (): ReactElement => {

Dashboard

- {!isEmpty(recentComics) && !isEmpty(recentComics.docs) ? ( + {!isEmpty(recentComics) ? ( <> {/* Pull List */} @@ -74,9 +74,8 @@ export const Dashboard = (): ReactElement => { )} {/* Recent imports */} - {!isEmpty(recentComics) && ( - )} + {/* Volumes */} {!isEmpty(volumeGroups) && ( @@ -95,4 +94,4 @@ export const Dashboard = (): ReactElement => { ); }; -export default Dashboard; +export default Dashboard; \ No newline at end of file diff --git a/src/client/components/Dashboard/PullList.tsx b/src/client/components/Dashboard/PullList.tsx index 4b62d86..f14f922 100644 --- a/src/client/components/Dashboard/PullList.tsx +++ b/src/client/components/Dashboard/PullList.tsx @@ -20,7 +20,7 @@ export const PullList = ({ issues }: PullListProps): ReactElement => { useEffect(() => { dispatch( getWeeklyPullList({ - startDate: "2022-11-15", + startDate: "2022-12-25", pageSize: "15", currentPage: "1", }), @@ -161,4 +161,4 @@ export const PullList = ({ issues }: PullListProps): ReactElement => { ); }; -export default PullList; +export default PullList; \ No newline at end of file diff --git a/src/client/components/Dashboard/RecentlyImported.tsx b/src/client/components/Dashboard/RecentlyImported.tsx index ad784e2..8b64b50 100644 --- a/src/client/components/Dashboard/RecentlyImported.tsx +++ b/src/client/components/Dashboard/RecentlyImported.tsx @@ -2,7 +2,6 @@ import React, { ReactElement } from "react"; import Card from "../Carda"; import { Link } from "react-router-dom"; import ellipsize from "ellipsize"; -import { escapePoundSymbol } from "../../shared/utils/formatting.utils"; import { isEmpty, isNil, isUndefined, map } from "lodash"; import { detectIssueTypes } from "../../shared/utils/tradepaperback.utils"; import Masonry from "react-masonry-css"; @@ -24,7 +23,6 @@ export const RecentlyImported = ({ 700: 2, 600: 2, }; - return ( <>
@@ -41,7 +39,7 @@ export const RecentlyImported = ({ columnClassName="recent-comics-column" > {map( - comicBookCovers.docs, + comicBookCovers, ( { _id, @@ -53,6 +51,7 @@ export const RecentlyImported = ({ }, idx, ) => { + console.log(comicvine); const { issueName, url } = determineCoverFile({ rawFileDetails, comicvine, @@ -64,7 +63,7 @@ export const RecentlyImported = ({ comicInfo, locg, }); - + console.log(name); const isComicBookMetadataAvailable = !isUndefined(comicvine) && !isUndefined(comicvine.volumeInformation); @@ -123,7 +122,7 @@ export const RecentlyImported = ({
{/* metadata card */} - {!isNil(name) ? ( + {!isNil(name) && (
@@ -138,7 +137,7 @@ export const RecentlyImported = ({
- ) : null} + )} ); }, @@ -146,4 +145,4 @@ export const RecentlyImported = ({ ); -}; +}; \ No newline at end of file diff --git a/src/client/constants/action-types.ts b/src/client/constants/action-types.ts index a6be92d..66449f3 100644 --- a/src/client/constants/action-types.ts +++ b/src/client/constants/action-types.ts @@ -81,6 +81,8 @@ export const IMS_COMIC_BOOK_ARCHIVE_EXTRACTION_CALL_IN_PROGRESS = export const IMS_COMIC_BOOK_ARCHIVE_EXTRACTION_CALL_FAILED = "IMS_COMIC_BOOK_ARCHIVE_EXTRACTION_CALL_FAILED"; +export const COMICBOOK_EXTRACTION_SUCCESS = "COMICBOOK_EXTRACTION_SUCCESS"; + // Image file stats export const IMG_ANALYSIS_CALL_IN_PROGRESS = "IMG_ANALYSIS_CALL_IN_PROGRESS"; export const IMG_ANALYSIS_DATA_FETCH_SUCCESS = @@ -135,4 +137,4 @@ export const SETTINGS_DB_FLUSH_SUCCESS = "SETTINGS_DB_FLUSH_SUCCESS"; // Metron Metadata export const METRON_DATA_FETCH_SUCCESS = "METRON_DATA_FETCH_SUCCESS"; export const METRON_DATA_FETCH_IN_PROGRESS = "METRON_DATA_FETCH_IN_PROGRESS"; -export const METRON_DATA_FETCH_ERROR = "METRON_DATA_FETCH_ERROR"; +export const METRON_DATA_FETCH_ERROR = "METRON_DATA_FETCH_ERROR"; \ No newline at end of file diff --git a/src/client/reducers/fileops.reducer.ts b/src/client/reducers/fileops.reducer.ts index 2060797..6efd6cb 100644 --- a/src/client/reducers/fileops.reducer.ts +++ b/src/client/reducers/fileops.reducer.ts @@ -29,7 +29,11 @@ import { SS_SEARCH_FAILED, SS_SEARCH_RESULTS_FETCHED_SPECIAL, VOLUMES_FETCHED, + COMICBOOK_EXTRACTION_SUCCESS, } from "../constants/action-types"; +import { removeLeadingPeriod } from "../shared/utils/formatting.utils"; +import { LIBRARY_SERVICE_HOST } from "../constants/endpoints"; + const initialState = { IMSCallInProgress: false, IMGCallInProgress: false, @@ -42,7 +46,10 @@ const initialState = { isComicVineMetadataImportInProgress: false, comicVineMetadataImportError: {}, rawImportError: {}, - extractedComicBookArchive: [], + extractedComicBookArchive: { + reading: [], + analysis: [], + }, recentComics: [], wantedComics: [], libraryComics: [], @@ -81,7 +88,7 @@ function fileOpsReducer(state = initialState, action) { case IMS_RECENT_COMICS_FETCHED: return { ...state, - recentComics: action.data, + recentComics: action.data.docs, }; case IMS_WANTED_COMICS_FETCHED: return { @@ -131,13 +138,7 @@ function fileOpsReducer(state = initialState, action) { comicBookExtractionInProgress: true, }; } - case IMS_COMIC_BOOK_ARCHIVE_EXTRACTION_SUCCESS: { - return { - ...state, - extractedComicBookArchive: action.extractedComicBookArchive, - comicBookExtractionInProgress: false, - }; - } + case LOCATION_CHANGE: { return { ...state, @@ -152,11 +153,44 @@ function fileOpsReducer(state = initialState, action) { } case LS_COVER_EXTRACTED: { console.log("BASH", action); + if(state.recentComics.length === 5) { + state.recentComics.pop(); + } return { ...state, librarySearchResultCount: state.librarySearchResultCount + 1, + recentComics: [...state.recentComics, action.result.data.importResult] }; } + + case COMICBOOK_EXTRACTION_SUCCESS: { + const comicBookPages: string[] = []; + map(action.result.files, (page) => { + const pageFilePath = removeLeadingPeriod(page); + const imagePath = encodeURI(`${LIBRARY_SERVICE_HOST}${pageFilePath}`); + comicBookPages.push(imagePath); + }); + + switch (action.result.purpose) { + case "reading": + return { + ...state, + extractedComicBookArchive: { + reading: comicBookPages, + }, + comicBookExtractionInProgress: false, + }; + + case "analysis": + return { + ...state, + extractedComicBookArchive: { + analysis: comicBookPages, + }, + comicBookExtractionInProgress: false, + }; + } + } case LS_QUEUE_DRAINED: { console.log("drained", action); return { @@ -229,7 +263,7 @@ function fileOpsReducer(state = initialState, action) { volumes: action.data, SSCallInProgress: false, }; - + case SS_SEARCH_FAILED: { return { ...state, @@ -249,4 +283,4 @@ function fileOpsReducer(state = initialState, action) { } } -export default fileOpsReducer; +export default fileOpsReducer; \ No newline at end of file diff --git a/src/client/shared/utils/metadata.utils.ts b/src/client/shared/utils/metadata.utils.ts index 4130fe0..f26f724 100644 --- a/src/client/shared/utils/metadata.utils.ts +++ b/src/client/shared/utils/metadata.utils.ts @@ -67,7 +67,10 @@ export const determineCoverFile = (data) => { } }; -export const determineExternalMetadata = (metadataSource, source) => { +export const determineExternalMetadata = ( + metadataSource: string, + source: any +) => { switch (metadataSource) { case "comicvine": return { @@ -87,4 +90,4 @@ export const determineExternalMetadata = (metadataSource, source) => { default: break; } -}; +}; \ No newline at end of file -- 2.49.1