diff --git a/package.json b/package.json index 2231e7b..b3183cf 100644 --- a/package.json +++ b/package.json @@ -50,6 +50,7 @@ "react-dom": "^17.0.1", "react-fast-compare": "^3.2.0", "react-final-form": "^6.5.3", + "react-select": "^4.3.1", "react-sliding-pane": "^7.0.0", "react-spinners": "^0.11.0", "react-table": "^7.7.0", diff --git a/src/client/actions/airdcpp.actions.tsx b/src/client/actions/airdcpp.actions.tsx index 89e01fa..5e05092 100644 --- a/src/client/actions/airdcpp.actions.tsx +++ b/src/client/actions/airdcpp.actions.tsx @@ -55,6 +55,10 @@ export const search = (data: SearchData) => async (dispatch) => { "search_result_updated", async (groupedResult) => { // ...update properties of the existing result in the UI + dispatch({ + type: AIRDCPP_SEARCH_RESULTS_RECEIVED, + groupedResult, + }); }, instance.id, ); @@ -67,12 +71,7 @@ export const search = (data: SearchData) => async (dispatch) => { async (searchInfo) => { await sleep(5000); - // The search can now be considered to be "complete" - dispatch({ - type: AIRDCPP_HUB_SEARCHES_SENT, - searchInfo, - instance, - }); + // Check the number of received results (in real use cases we should know that even without calling the API) const currentInstance = await SocketService.get( @@ -82,7 +81,13 @@ export const search = (data: SearchData) => async (dispatch) => { // ...nothing was received, show an informative message to the user } + // The search can now be considered to be "complete" // If there's an "in progress" indicator in the UI, that could also be disabled here + dispatch({ + type: AIRDCPP_HUB_SEARCHES_SENT, + searchInfo, + instance, + }); }, instance.id, ); diff --git a/src/client/components/ComicDetail.tsx b/src/client/components/ComicDetail.tsx index 26dc90e..deb9cc9 100644 --- a/src/client/components/ComicDetail.tsx +++ b/src/client/components/ComicDetail.tsx @@ -6,6 +6,7 @@ import ComicVineSearchForm from "./ComicVineSearchForm"; import AcquisitionPanel from "./AcquisitionPanel"; import DownloadsPanel from "./DownloadsPanel"; import SlidingPane from "react-sliding-pane"; +import Select from "react-select"; import { css } from "@emotion/react"; import "react-sliding-pane/dist/react-sliding-pane.css"; @@ -37,7 +38,6 @@ type ComicDetailProps = {}; export const ComicDetail = ({}: ComicDetailProps): ReactElement => { const [page, setPage] = useState(1); const [visible, setVisible] = useState(false); - const [isActionDropdownCollapsed, collapseActionDropdown] = useState(false); const comicVineSearchResults = useSelector( (state: RootState) => state.comicInfo.searchResults, @@ -54,8 +54,6 @@ export const ComicDetail = ({}: ComicDetailProps): ReactElement => { const { comicObjectId } = useParams<{ comicObjectId: string }>(); const dispatch = useDispatch(); - const toggleActionDropdown = () => - collapseActionDropdown(!isActionDropdownCollapsed); useEffect(() => { dispatch(getComicBookDetailById(comicObjectId)); @@ -251,13 +249,30 @@ export const ComicDetail = ({}: ComicDetailProps): ReactElement => { imagePath = comicBookDetailData.sourcedMetadata.comicvine.image.small_url; comicBookTitle = comicBookDetailData.sourcedMetadata.comicvine.name; } + + // actions menu options and handler + const actionOptions = [ + { value: "match-on-comic-vine", label: "Match on Comic Vine" }, + { value: "edit-metdata", label: "Edit Metadata" }, + { value: "delete-comic", label: "Delete Comic" }, + ]; + const handleActionSelection = (action) => { + switch (action.value) { + case "match-on-comic-vine": + openDrawerWithCVMatches(); + break; + default: + console.log("No valid action selected."); + break; + } + }; return (
{!isNil(comicBookDetailData) && !isEmpty(comicBookDetailData) && ( <>

{comicBookTitle}

-
+
{ />
{/* raw file details */} -
+
{!isNil(comicBookDetailData.rawFileDetails) && ( <> @@ -279,63 +294,21 @@ export const ComicDetail = ({}: ComicDetailProps): ReactElement => { updatedAt={comicBookDetailData.updatedAt} /> )} - {/* action dropdown */} -
toggleActionDropdown()} - onFocus={() => toggleActionDropdown()} - > -
- -
- -
+
+ {/* action dropdown */} +
+