diff --git a/components/Books.js b/components/Books.js index c3b0ce8..06a7f46 100644 --- a/components/Books.js +++ b/components/Books.js @@ -1,45 +1,34 @@ -import React from "react"; +import { useState, Fragment } from "react"; import Swal from "sweetalert2"; import { host } from "../utils/constants"; import { withSession } from "../hooks/withSession"; import { signIn } from "next-auth/react"; import ChangeIdentifier from "./ChangeIdentifier"; -class Books extends React.Component { - /** - * @param {Object} props - * @constructor - */ - constructor(props) { - super(props); - this.state = { - option: "gb", - bookid: "", - email: "", - show: true, - loader: false, - isDuplicate: false, - isValidIdentifier: true, - IATitle: "", - IAIdentifier: "", - inputDisabled: false, - }; - this.onSubmit = this.onSubmit.bind(this); - } +function Books(props) { + const session = props.session && props.session.data; + + const [state, setState] = useState({ + option: "gb", + bookid: "", + email: "", + show: true, + loader: false, + isDuplicate: false, + isValidIdentifier: true, + IATitle: "", + IAIdentifier: "", + inputDisabled: false, + }); /** * Change the `option` state when user selects a different library * @param {Object} event */ - handleChange = (event) => { - this.setState({ + const handleChange = (event) => { + setState({ + ...state, option: event.target.value, - bookid: "", - isDuplicate: false, - isValidIdentifier: true, - IATitle: "", - IAIdentifier: "", - inputDisabled: false, }); }; @@ -47,9 +36,9 @@ class Books extends React.Component { * Change the example when user selects a different library * @return {String} */ - showExample = () => { + const showExample = () => { let url = ""; - switch (this.state.option) { + switch (state.option) { case "gb": url = "https://books.google.co.in/books?id=At46AQAAMAAJ"; break; @@ -71,7 +60,7 @@ class Books extends React.Component { * Makes a request from Google Books API based on the entered book Id * If the book Id is not valid the request resolves with an error message */ - validateGoogleBook = (enteredId) => { + const validateGoogleBook = (enteredId) => { let googleUrl = `https://www.googleapis.com/books/v1/volumes/${enteredId}`; fetch(googleUrl) .then((response) => response.json()) @@ -81,7 +70,8 @@ class Books extends React.Component { } else if (details.error) { alert("Please give a valid volume ID."); } else { - this.setState({ + setState({ + ...state, bookid: details.id, bookTitle: details.volumeInfo.title, bookAuthors: details.volumeInfo.authors, @@ -95,8 +85,9 @@ class Books extends React.Component { }); }; - onResetButtonClicked = () => { - this.setState({ + const onResetButtonClicked = () => { + setState({ + ...state, isDuplicate: false, isValidIdentifier: true, inputDisabled: false, @@ -105,15 +96,16 @@ class Books extends React.Component { }); }; - onSwalClosed = () => { - this.setState({ + const onSwalClosed = () => { + setState({ + ...state, inputDisabled: false, IAIdentifier: "", IATitle: "", }); }; - renderContent = (option) => { + const renderContent = (option) => { switch (option) { case "gb": return ( @@ -129,10 +121,10 @@ class Books extends React.Component { name="bookid" type="text" required - disabled={this.state.inputDisabled} + disabled={state.inputDisabled} placeholder="At46AQAAMAAJ" onChange={(event) => - this.setState({ bookid: event.target.value }) + setState({ ...state, bookid: event.target.value }) } aria-describedby="bid" /> @@ -150,9 +142,9 @@ class Books extends React.Component { type="text" id="bookid" name="bookid" - disabled={this.state.inputDisabled} + disabled={state.inputDisabled} onChange={(event) => - this.setState({ bookid: event.target.value }) + setState({ ...state, bookid: event.target.value }) } required placeholder="http://www.panjabdigilib.org/webuser/searches/displayPage.jsp?ID=9073&page=1&CategoryID=1&Searched=" @@ -174,10 +166,10 @@ class Books extends React.Component { id="bookid" name="bookid" type="text" - disabled={this.state.inputDisabled} + disabled={state.inputDisabled} placeholder="249146214" onChange={(event) => - this.setState({ bookid: event.target.value }) + setState({ ...state, bookid: event.target.value }) } required aria-describedby="bid" @@ -188,14 +180,14 @@ class Books extends React.Component { } }; - isPDLValidUrl = (urlString) => { + const isPDLValidUrl = (urlString) => { var urlPattren = new RegExp( "((http|https)\\:\\/\\/)(www.)?(panjabdigilib\\.org\\/webuser\\/searches\\/displayPage\\.jsp\\?ID\\=)([0-9]*)(\\&page\\=)([0-9]*)(\\&CategoryID\\=)([0-9]*)(\\&Searched\\=)([a-zA-Z0-9@:%._+~#?&//=]*)" ); return urlPattren.test(urlString); }; - onSubmit = (event, userName) => { + const onSubmit = (event, userName) => { event.preventDefault(); if (!userName || userName === "") { @@ -203,7 +195,8 @@ class Books extends React.Component { return; } - this.setState({ + setState({ + ...state, loader: true, isDuplicate: false, isValidIdentifier: true, @@ -211,26 +204,25 @@ class Books extends React.Component { let url = ""; const isAlphanumericLess50 = /^(?=.*[a-zA-Z])(?=.*[0-9])[a-zA-Z0-9]{1,50}$/; - switch (this.state.option) { + switch (state.option) { case "gb": - url = `${host}/check?bookid=${this.state.bookid}&option=${ - this.state.option + - (this.state.email ? "&email=" + this.state.email : "") - }&userName=${userName}&IAtitle=${this.state.IAIdentifier}`; + url = `${host}/check?bookid=${state.bookid}&option=${ + state.option + (state.email ? "&email=" + state.email : "") + }&userName=${userName}&IAtitle=${state.IAIdentifier}`; fetch(url) .then((response) => response.json()) .then(async (response) => { - this.setState({ - loader: false, - }); + setState({ ...state, loader: false }); if (response.isDuplicate) { - this.setState({ + setState({ + ...state, isDuplicate: true, IATitle: response.titleInIA, inputDisabled: true, }); } else if (!isAlphanumericLess50.test(response.IAIdentifier)) { - this.setState({ + setState({ + ...state, isValidIdentifier: false, IATitle: response.IAIdentifier, inputDisabled: true, @@ -246,7 +238,7 @@ class Books extends React.Component { allowEscapeKey: false, allowOutsideClick: false, showCloseButton: true, - onClose: this.onSwalClosed, + onClose: onSwalClosed, title: 'Just a few more steps...', html: `
    ` + @@ -254,11 +246,8 @@ class Books extends React.Component { `
  1. Enter the captcha.
  2. ` + `
  3. Enter the URL below (https://books.googleusercontent.com/books/content?req=xxx)
  4. `, }); - if (url && typeof url !== "object") { - this.setState({ - loader: true, - }); + setState({ ...state, loader: true }); fetch(`${host}/download`, { body: JSON.stringify({ url: url, @@ -272,9 +261,7 @@ class Books extends React.Component { }) .then((response) => response.json()) .then((response) => { - this.setState({ - loader: false, - }); + setState({ ...state, loader: false }); if (response.error) Swal("Error!", response.message, "error"); else Swal("Voila!", response.message, "success"); @@ -285,49 +272,30 @@ class Books extends React.Component { }); break; - // case "obp": - // const IDobp = this.state.bookid; - // const categoryObp = ""; - // url = `/check?bookid=${IDobp}&option=${ - // this.state.option + - // (this.state.email ? "&email=" + this.state.email : "") - // }&categoryID=${categoryObp}`; - // fetch(url) - // .then((res) => res.json()) - // .then((response) => { - // this.setState({ - // loader: false, - // }); - // if (response.error) Swal("Error!", response.message, "error"); - // else Swal("Voila!", response.message, "success"); - // }); - // break; - case "pn": - if (this.isPDLValidUrl(this.state.bookid)) { - const searchParams = new URL(this.state.bookid).searchParams; + if (isPDLValidUrl(state.bookid)) { + const searchParams = new URL(state.bookid).searchParams; const ID = searchParams.get("ID"); const categoryID = searchParams.get("CategoryID"); url = `${host}/check?bookid=${ID}&option=${ - this.state.option + - (this.state.email ? "&email=" + this.state.email : "") + state.option + (state.email ? "&email=" + state.email : "") }&categoryID=${categoryID}&userName=${userName}&IAtitle=${ - this.state.IAIdentifier + state.IAIdentifier }`; fetch(url) .then((res) => res.json()) .then((response) => { - this.setState({ - loader: false, - }); + setState({ ...state, loader: false }); if (response.isDuplicate) { - this.setState({ + setState({ + ...state, isDuplicate: true, IATitle: response.titleInIA, inputDisabled: true, }); } else if (!isAlphanumericLess50.test(response.IAIdentifier)) { - this.setState({ + setState({ + ...state, isValidIdentifier: false, IATitle: response.IAIdentifier, inputDisabled: true, @@ -338,32 +306,29 @@ class Books extends React.Component { } }); } else { - this.setState({ - loader: false, - }); + setState({ ...state, loader: false }); Swal("Opps...", "Enter a valid URL", "error"); } break; case "trove": - url = `${host}/check?bookid=${this.state.bookid}&option=${ - this.state.option + - (this.state.email ? "&email=" + this.state.email : "") - }&userName=${userName}&IAtitle=${this.state.IAIdentifier}`; + url = `${host}/check?bookid=${state.bookid}&option=${ + state.option + (state.email ? "&email=" + state.email : "") + }&userName=${userName}&IAtitle=${state.IAIdentifier}`; fetch(url) .then((res) => res.json()) .then((response) => { - this.setState({ - loader: false, - }); + setState({ ...state, loader: false }); if (response.isDuplicate) { - this.setState({ + setState({ + ...state, isDuplicate: true, IATitle: response.titleInIA, inputDisabled: true, }); } else if (!isAlphanumericLess50.test(response.IAIdentifier)) { - this.setState({ + setState({ + ...state, isValidIdentifier: false, IATitle: response.IAIdentifier, inputDisabled: true, @@ -376,133 +341,125 @@ class Books extends React.Component { } }; - render() { - const { data: session } = this.props.session; - return ( - -
    -

    Book Uploader Bot

    -
    - - Upload books, newspapers, magazines etc. from public libraries to - Internet Archive - + return ( + +
    +

    Book Uploader Bot

    +
    + + Upload books, newspapers, magazines etc. from public libraries to + Internet Archive + +
    +
    onSubmit(e, session.user.name)}> +
    +

    1. Select a library

    +
    - this.onSubmit(e, session.user.name)}> -
    -

    1. Select a library

    - -
    -
    - {this.renderContent(this.state.option)} -
    - {this.state.isDuplicate ? ( - - A file with this identifier{" "} - - (https://archive.org/{this.state.IATitle}) - {" "} - already exists at Internet Archive. Please enter a different - identifier to proceed. - - } - inputPlaceholder="Enter unique file identifier" - onIdentifierChange={(event) => - this.setState({ IAIdentifier: event.target.value }) - } - /> - ) : null} +
    {renderContent(state.option)}
    + {state.isDuplicate ? ( + + A file with this identifier{" "} + + (https://archive.org/{state.IATitle}) + {" "} + already exists at Internet Archive. Please enter a different + identifier to proceed. + + } + inputPlaceholder="Enter unique file identifier" + onIdentifierChange={(event) => + setState({ ...state, IAIdentifier: event.target.value }) + } + /> + ) : null} - {this.state.isValidIdentifier === false ? ( - - The file you want to upload with title -{" "} - {this.state.IATitle} either contains special characters or - exceeds 50 characters in length. Please provide an - identifier that consists only of letters (A-Z) and numbers - (0-9). - - } - inputPlaceholder="Enter a valid Identifier that is less than 50 characters and Alphanumeric" - onIdentifierChange={(event) => - this.setState({ IAIdentifier: event.target.value }) - } - /> - ) : null} + {state.isValidIdentifier === false ? ( + + The file you want to upload with title - {state.IATitle}{" "} + either contains special characters or exceeds 50 characters in + length. Please provide an identifier that consists only of + letters (A-Z) and numbers (0-9). + + } + inputPlaceholder="Enter a valid Identifier that is less than 50 characters and Alphanumeric" + onIdentifierChange={(event) => + setState({ ...state, IAIdentifier: event.target.value }) + } + /> + ) : null} - {session && ( -
    -
    - + {state.isDuplicate === true || + state.isValidIdentifier === false ? ( + - {this.state.isDuplicate === true || - this.state.isValidIdentifier === false ? ( - - ) : null} -
    + ) : null}
    - )} - {!session && ( -
    -
    - - Upload restricted. Login with Wikimedia Account to continue. - -
    - +
    + )} + {!session && ( +
    +
    + + Upload restricted. Login with Wikimedia Account to continue. +
    - )} - - {this.state.loader ? ( -
    - - Fetching information. Please wait.. - -
    { + e.preventDefault(); + signIn("wikimedia"); + }} > -
    -
    + + Login with Wikimedia +
    - ) : null} -
    - - ); - } + )} + + {state.loader ? ( +
    + + Fetching information. Please wait.. + +
    +
    +
    +
    + ) : null} +
    + + ); } const BooksWithSession = withSession(Books); diff --git a/hooks/withSession.js b/hooks/withSession.js index 710a686..1e0f229 100644 --- a/hooks/withSession.js +++ b/hooks/withSession.js @@ -3,7 +3,7 @@ import { useSession } from "next-auth/react"; export const withSession = (Component) => (props) => { const session = useSession(); - if (Component.prototype.render) { + if (Component) { return ; } }; diff --git a/pages/api/auth/[...nextauth].js b/pages/api/auth/[...nextauth].js index ce47fd1..7af4623 100644 --- a/pages/api/auth/[...nextauth].js +++ b/pages/api/auth/[...nextauth].js @@ -7,8 +7,17 @@ export const authOptions = { providers: [ WikimediaProvider({ clientId: process.env.WIKIMEDIA_CLIENT_ID, - clientSecret: process.env.WIKIMEDIA_CLIENT_SECRET - }) + clientSecret: process.env.WIKIMEDIA_CLIENT_SECRET, + token: + "https://meta.wikimedia.beta.wmflabs.org/w/rest.php/oauth2/access_token", + userinfo: + "https://meta.wikimedia.beta.wmflabs.org/w/rest.php/oauth2/resource/profile", + authorization: { + url: + "https://meta.wikimedia.beta.wmflabs.org/w/rest.php/oauth2/authorize", + params: { scope: "" }, + }, + }), ], session: { jwt: true, diff --git a/pages/index.js b/pages/index.js index d736e90..2c6635e 100644 --- a/pages/index.js +++ b/pages/index.js @@ -1,5 +1,6 @@ import Header from "../components/Header"; import Books from "../components/Books"; + const init = () => (