diff --git a/assets/src/App.js b/assets/src/App.js index 640c1022..b670d09a 100644 --- a/assets/src/App.js +++ b/assets/src/App.js @@ -1,70 +1,71 @@ import React from "react"; import "./App.css" import SearchFilterFields from './pages/SearchFilterFields' import Footer from './components/layout/Footer' import About from "./pages/About" import Help from "./pages/Help" import DetailCard from "./components/DetailCard" import {Switch, Route } from "react-router-dom" import Container from '@material-ui/core/Container'; import Box from '@material-ui/core/Box' import Nav from "./components/layout/Nav" import { makeStyles } from '@material-ui/core/styles'; import Journal from "./components/Journal"; import DetailsCard from "./components/DetailCard"; const useStyles = makeStyles((theme) => ({ root: { flexGrow: 1, } })); function App () { const classes = useStyles(); return(
) } export default App \ No newline at end of file diff --git a/assets/src/Context.js b/assets/src/Context.js index 399566b8..40cf9472 100644 --- a/assets/src/Context.js +++ b/assets/src/Context.js @@ -1,130 +1,134 @@ import React, {useCallback, useState, useEffect} from "react" import { getListOfInstitution } from './services/requests/Institution' import { getListOfJournal } from "./services/requests/Journal" import { getListOfFunder } from "./services/requests/Funder" const Context = React.createContext() function ContextProvider ({children}) { //call the custom hook for listing field with api const [institList, setInstitList] = useState([]); const [journalList, setJournalList] = useState([]); const [funderList, setFunderList] = useState([]); const [institId, setInstitId] = React.useState(''); const [institName, setInstitName] = React.useState(''); const [journalId, setJournalId] = React.useState(''); const [journalName, setJournalName] = React.useState(''); const [funderId, setFunderId] = React.useState(''); const [funderName, setFunderName] = React.useState(''); - +const [url, setUrl] = React.useState(''); const getInstitListFromApi = useCallback(async () => { try { const response = await getListOfInstitution() setInstitList(response.data) } catch (error) { console.log(`error 700 from Get Institution- ${error.message}`) } }, []) const getJournalListFromApi = useCallback(async () => { try { const response = await getListOfJournal() setJournalList(response.data) } catch (error) { console.log(`error 700 from Get Institution- ${error.message}`) } }, []) const getFunderListFromApi = useCallback(async () => { try { const response = await getListOfFunder() setFunderList(response.data) } catch (error) { console.log(`error 700 from Get Funder- ${error.message}`) } }, []) useEffect(() => { getInstitListFromApi(), getJournalListFromApi(), getFunderListFromApi() }, []) //get the institution Id and update request array function getSelectedInstitId (name) { const updateArr = institList.map(item => { if(item.name === name) { console.log(item.id, item.name) const newItem = item.id const newItemName = item.name setInstitId(newItem) setInstitName(newItemName) return newItem } // return }) // return } //get the journal Id and update request array function getSelectedJournalId (name) { const updateArr = journalList.map(item => { if(item.name === name) { console.log(item.id, item.name) const newItem = item.id const newItemName = item.name setJournalId(newItem) setJournalName(newItemName) return } return }) return } //get the funder Id and update request array function getSelectedFunderId (name) { const updateArr = funderList.map(item => { if(item.name === name) { console.log(item.id, item.name) const newItem = item.id const newItemName = item.name setFunderId(newItem) setFunderName(newItemName) return } return }) return } return ( {children} ) } export {ContextProvider, Context} \ No newline at end of file diff --git a/assets/src/components/DetailCard.js b/assets/src/components/DetailCard.js index 4ed286b9..d0e44a7a 100644 --- a/assets/src/components/DetailCard.js +++ b/assets/src/components/DetailCard.js @@ -1,343 +1,356 @@ -import React, {useEffect} from "react" - +import React, {useContext,useEffect} from "react" +import {Context} from "../Context" import { makeStyles } from '@material-ui/core/styles'; import "./detailscard.css" import Typography from '@material-ui/core/Typography'; import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; import Card from '@material-ui/core/Card'; import CardActions from '@material-ui/core/CardActions'; import CardContent from '@material-ui/core/CardContent'; import Button from '@material-ui/core/Button'; import { HiLink } from "react-icons/hi"; import DoneIcon from '@material-ui/icons/Done'; import WarningIcon from '@material-ui/icons/Warning'; import "./termcard.css" import { BsUnlock } from "react-icons/bs"; import { GrDiamond } from "react-icons/gr"; import Chip from '@material-ui/core/Chip'; import ClearSharpIcon from '@material-ui/icons/ClearSharp'; - -// import { -// useHistory -// } from "react-router-dom"; - const useStyles = makeStyles((theme) => ({ root: { '& > *': { margin: theme.spacing(1), display: 'grid', }, flexGrow: 1, }, formControl: { margin: theme.spacing(1), width: 200, }, selectEmpty: { marginTop: theme.spacing(1), }, chip: { margin: 0.5, }, heading: { fontSize: theme.typography.pxToRem(15), fontWeight: theme.typography.fontWeightRegular, }, })); -function DetailsCard({details}) { - // const history = useHistory(); - // console.log(history) - // useEffect(() => { - // history.push({pathname:`/check`, search : `id=${details.id},name=${details.name}`}) - // }, []) - +function DetailsCard({details}) { + + const { getSelectedInstitId, + setUrl, + url + } + = useContext(Context) const classes = useStyles(); - + useEffect(() => { + setUrl(window.location.href) + },) if (details !== 'null') { - console.log(details) + + + // // setInstitName(details.name) return ( -
+
{details.end_year && Inactive! {details.starting_year &&

From {details.starting_year} to {details.end_year}

}
}

{details.name}

+ +
    {details.issn && details.issn.map(item => { return ( - - item.issn_type === 1 ? - -

    ISSN Print :{item.issn}

    + item.issn_type === "1" ? - : item.issn_type === 2 ? -

    ISSN Electronic: {item.issn}

    - :

    ISSN Other: {item.issn}

    +
  • Print ISSN: {item.issn}
  • + + : item.issn_type === "2" ? +
  • Electronic ISSN: {item.issn}
  • + + : item.issn_type === "3" ? +
  • Other ISSN: {item.issn}
  • + + :null ) })} - +
+
{details.publisher && details.publisher.map(item => { return
})}
{details.country && details.country.map(item => { return
{item.name}
; })} {!details.end_year &&
Since {details.starting_year}
}
{details.oa_status ?
{details.oa_status.status !== "UNKNOWN" ?
{ details.oa_status.status === "Gold" ?

Open Acces Status:

: details.oa_status.status === "Diamond" ? <> Open Acces Status: {/* {details.oa_status.status} */} :details.oa_status.status === "Full" ?

Open Acces Status:

:details.oa_status.status === "hybrid" ?

Open Acces Status:

:details.oa_status.status === "Green" ?

Open Acces Status:

:details.oa_status.status === "none" ?

Open Acces Status:

:null }
:null}
:null}
{details.language && details.language.map(item =>(

Language: {item.name}

)) } {details.doaj_seal &&
} {details.doaj_status &&
} {details.lockss &&
} {details.portico &&
} {details.nlch &&
} {details.qoam_av_score &&
}
{details.website ? :null} {details.oa_options ? :null} + {details.ror ? + + :null} + {details.fundref ? + + :null}
) } else { return null } } export default DetailsCard \ No newline at end of file diff --git a/assets/src/pages/SearchFilterFields.js b/assets/src/pages/SearchFilterFields.js index c543f099..003b1d1e 100644 --- a/assets/src/pages/SearchFilterFields.js +++ b/assets/src/pages/SearchFilterFields.js @@ -1,770 +1,1183 @@ import React, {useContext, useState, useEffect} from 'react'; import "./SearchFilterFields.css" import { makeStyles } from '@material-ui/core/styles'; import Button from '@material-ui/core/Button'; import FormControl from '@material-ui/core/FormControl'; import TextField from '@material-ui/core/TextField'; import Autocomplete from '@material-ui/lab/Autocomplete'; import { searchCondi, searchorganizationonly, searchjournalonly, searchInstitFunder, searchCondi3 } from '../services/requests/Condition' import {getJournal} from '../services/requests/Journal' import {getFunder} from '../services/requests/Funder' import {getInstitution} from '../services/requests/Institution' import Accordion from '@material-ui/core/Accordion'; import AccordionSummary from '@material-ui/core/AccordionSummary'; import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; import Typography from '@material-ui/core/Typography'; import AccordionDetails from '@material-ui/core/AccordionDetails'; import Grid from '@material-ui/core/Grid' import Box from '@material-ui/core/Box' import Container from '@material-ui/core/Container'; import {Context} from "../Context" import ResultCard from "../components/ResultCard" import DetailCard from "../components/DetailCard" import CircularProgress from '@material-ui/core/CircularProgress' +import Fab from '@material-ui/core/Fab' +import ShareIcon from '@material-ui/icons/Share' +import Dialog from '@material-ui/core/Dialog'; +import DialogActions from '@material-ui/core/DialogActions'; +import DialogContent from '@material-ui/core/DialogContent'; +import DialogContentText from '@material-ui/core/DialogContentText'; +import DialogTitle from '@material-ui/core/DialogTitle'; +import Slide from '@material-ui/core/Slide'; + + + import { - useHistory + useHistory,useLocation } from "react-router-dom"; +function useQuery() { + return new URLSearchParams(useLocation().search); +} +const Transition = React.forwardRef(function Transition(props, ref) { + return ; +}); + const useStyles = makeStyles((theme) => ({ root: { flexGrow: 1, }, // selectEmpty: { // marginTop: theme.spacing(2), // }, // card: { // width: '100%', // marginTop: "1rem", // }, chip: { margin: 0.5, }, // heading: { // fontSize: theme.typography.pxToRem(15), // fontWeight: theme.typography.fontWeightRegular, // }, })); export default function SearchFilterFields() { const history = useHistory(); + // const location = useLocation() + console.log(history) + let query = useQuery(); + const [open, setOpen] = React.useState(false); - const classes = useStyles(); //call the custom hook for listing field with api const { getSelectedInstitId, getSelectedJournalId, getSelectedFunderId, institList, journalList, funderList, institId, journalId, funderId, setInstitId, setJournalId, setFunderId, institName, journalName, funderName, + setFunderName, + setJournalName, + setInstitName, + setUrl, + url } = useContext(Context) //responses const [conditions, setConditions] = useState([]); const [details, setDetails] = useState([]); const [result, updateResult] = useState([]); const [loading, setLoading] = useState(false); + // const [url, setUrl] = useState(window.location.href); useEffect(() => { + setDetails('null') - }, []) + + //handle Url param + + console.log(history) + if (history.location.pathname === "/check") { + console.log("this an url to check") + setDetails('fromUrl') + // alert(query.get("institution")) + + + if (query.get("institution") && !query.get("funder") && !query.get("journal")){ + //get organizations conditions + // alert(`get api organization Condition only: ${institId}`) + //condtion type is not journal only = 1 + // Get the user + + const sendSearchInstitOnly = + async () => { + + try { + + + const resp = await searchorganizationonly(query.get("institution"),1) + console.log(resp.data) + setConditions(arr => [...arr, resp.data]) + + + + } catch (err) { + // Handle Error Here + console.error(err); + } + setLoading(false) + + + } + + console.log(details) + + const sendGetrequest = + async () => { + try { + const resp = await getInstitution(query.get("institution")) + // console.log(`instit name from api: ${resp.data.name}`) + // setInstitName(resp.data.name) + updateResult(arr => [...arr, resp.data]) + // if (details === "null") { + // setDetails(resp.data) + // } + // else { + // setDetails(prevArray => [...prevArray, resp.data]) + // } + } catch (err) { + // Handle Error Here + console.error(err); + } + + } + sendSearchInstitOnly().then( + sendGetrequest() + ) + history.push({pathname:`check`, search:`institution=${query.get("institution")}`}) + } + + else if (!query.get("institution") && !query.get("journal") && query.get("funder")){ + //get funder conditions + + // alert(`get api funder Condition only: ${funderId}`) + //condtion type is not journal only = 1 + + const sendSearchOrgaOnly = + async () => { + try { + const resp = await searchorganizationonly(query.get("funder"),1) + console.log(resp.data) + setConditions(arr => [...arr, resp.data]) + } catch (err) { + // Handle Error Here + console.error(err); + } + setLoading(false) + } + + const sendGetrequest = + async () => { + try { + const resp = await getFunder(query.get("funder")) + console.log(resp.data) + updateResult(arr => [...arr, resp.data]) + } catch (err) { + // Handle Error Here + console.error(err); + } + } + + sendSearchOrgaOnly().then( + sendGetrequest() + ) + history.push({pathname:`check`, search:`funder=${query.get("funder")}`}) + } + + else if (!query.get("funder") && !query.get("institution") && query.get("journal")){ + + //get journals conditions + // alert(`get api journal Condition only: ${journalId}`) + //condtion type is not institution only = 2 + //get journal detail + + const sendSearchJournalOnly = + async () => { + try { + const resp = await searchjournalonly(query.get("journal"),2) + console.log(resp.data) + setConditions(arr => [...arr, resp.data]) + // setConditions(arr => [...arr, resp.data]) + } catch (err) { + // Handle Error Here + console.error(err); + } + setLoading(false) + + } + + const sendGetrequest = + async () => { + try { + const resp = await getJournal(query.get("journal")) + console.log(resp.data) + updateResult(arr => [...arr, resp.data]) + } catch (err) { + // Handle Error Here + console.error(err); + } + + } + + sendSearchJournalOnly().then( + sendGetrequest() + ) + history.push({pathname:`check`, search:`journal=${query.get("journal")}`}) + } + else if (query.get("institution") && query.get("funder") && !query.get("journal")) { + + //alert(`get api Filter Conditions SET--> Journal: ${journalId} VS Institution: ${institId}`) + //condtion type journal/condition = 3 + const sendSearchCondi = + async () => { + try { + const resp = await searchInstitFunder(query.get("institution"), query.get("funder"), 1) + console.log(resp.data) + setConditions(arr => [...arr, resp.data]) + } catch (err) { + // Handle Error Here + console.error(err); + } + setLoading(false) + } + + const sendGetInstit = + async () => { + try { + const resp = await getInstitution(query.get("institution")) + console.log(resp.data) + // detailArray.push(resp.data) + // setDetails(detailArray) + updateResult(arr => [...arr, resp.data]) + + + + } catch (err) { + // Handle Error Here + console.error(err); + } + } + const sendGetFunder = + async () => { + try { + const resp = await getFunder(query.get("funder")) + console.log(resp.data) + + updateResult(arr => [...arr, resp.data]) + + } catch (err) { + // Handle Error Here + console.error(err); + } + + } + sendSearchCondi().then( + sendGetInstit().then(sendGetFunder()) + ) + + history.push({pathname:`check`, search: `institution=${query.get("institution")}&funder=${query.get("funder")}`}) + } + + else if (query.get("institution") && query.get("journal") && !query.get("funder")) { + + //alert(`get api Filter Conditions SET--> Journal: ${journalId} VS Institution: ${institId}`) + //condtion type journal/condition = 3 + const sendSearchCondi = + async () => { + try { + const resp = await searchCondi(query.get("journal"),query.get("institution")) + console.log(resp.data) + setConditions(arr => [...arr, resp.data]) + } catch (err) { + // Handle Error Here + console.error(err); + } + setLoading(false) + } + const sendGetInstit = + async () => { + try { + const resp = await getInstitution(query.get("institution")) + console.log(resp.data) + + updateResult(arr => [...arr, resp.data]) + + } catch (err) { + // Handle Error Here + console.error(err); + } + + } + const sendGetJournal = + async () => { + try { + const resp = await getJournal(query.get("journal")) + console.log(resp.data) + // detailArray.push(resp.data) + // setDetails(detailArray) + updateResult(arr => [...arr, resp.data]) + + + + } catch (err) { + // Handle Error Here + console.error(err); + } + } + + sendSearchCondi().then( + sendGetInstit().then(sendGetJournal) + ) + + history.push({pathname:`check`, search: `institution=${query.get("institution")}&journal=${query.get("journal")}`}) + } + + else if (!query.get("institution") && query.get("journal") && query.get("funder")) { + + // alert(`get api Filter Conditions SET--> Journal: ${journalId} VS Institution: ${funderId}`) + //condtion type journal/institution/funder conditions = 3 + + const sendGetCondi = + async () => { + try { + const resp = await searchCondi(query.get("journal"),query.get("funder")) + console.log(resp.data) + setConditions(arr => [...arr, resp.data]) + } catch (err) { + // Handle Error Here + console.error(err); + } + setLoading(false) + } + + const sendGetFunder = + async () => { + try { + const resp = await getFunder(query.get("funder")) + console.log(resp.data) + updateResult(arr => [...arr, resp.data]) + } catch (err) { + // Handle Error Here + console.error(err); + } + } + + const sendGetJournal = + async () => { + try { + const resp = await getJournal(query.get("journal")) + console.log(resp.data) + updateResult(arr => [...arr, resp.data]) + } catch (err) { + // Handle Error Here + console.error(err); + } + } + + + + sendGetCondi().then( + sendGetFunder().then( + sendGetJournal() + ) + ) + history.push({pathname:`check`, search: `funder=${query.get("funder")}&journal=${query.get("journal")}`}) + } + + else if (query.get("institution") && query.get("journal") && query.get("funder")) { + + // alert(`get api Filter Conditions SET--> Journal: ${journalId} VS Institution: ${funderId}`) + //condtion type journal/institution/funder conditions = 3 + console.log("main check !") + //(institution + journal) + const detailArray = [] + + const sendGetCondi = + async () => { + try { + const resp = await searchCondi3(query.get("institution"),query.get("journal"),query.get("funder")) + console.log(resp.data) + setConditions(arr => [...arr, resp.data]) + } catch (err) { + // Handle Error Here + console.error(err); + } + setLoading(false) + } + const sendGetInstit = + async () => { + try { + const resp = await getInstitution(query.get("institution")) + console.log(resp.data) + detailArray.push(resp.data) + updateResult(arr => [...arr, resp.data]) + + } catch (err) { + // Handle Error Here + console.error(err); + } + } + + const sendGetFunder = + async () => { + try { + const resp = await getFunder(query.get("funder")) + console.log(resp.data) + updateResult(arr => [...arr, resp.data]) + } catch (err) { + // Handle Error Here + console.error(err); + } + } + const sendGetJournal = + async () => { + try { + const resp = await getJournal(query.get("journal")) + console.log(resp.data) + updateResult(arr => [...arr, resp.data]) + } catch (err) { + // Handle Error Here + console.error(err); + } + } + + + //order requests + sendGetCondi() + sendGetInstit().then( + sendGetFunder() + ).then( + sendGetJournal() + ) + history.push({pathname:`check`, search: `institution=${query.get("institution")}&funder=${query.get("funder")}&journal=${query.get("journal")}`}) + + + } + + + + } + //set institution name + + }, []) + //set institution name + // clear teh usestate // const clear = () => { // setState((prev) => new Map(prev.clear())); // } - - + function handlShare(e) { - function handleInstit(e, newInputValue) { + setOpen(true) + navigator.clipboard.writeText(url) + +} +const handleClose = () => { + setOpen(false); +}; + function handleInstit(e, newInputValue) { + if (newInputValue){ getSelectedInstitId(newInputValue) return } + + // if (institName){ + // getSelectedInstitId(institName) + // return + + // } + setInstitId("") } function handleFunder(e, newInputValue) { console.log(newInputValue) if (newInputValue){ getSelectedFunderId(newInputValue) return } setFunderId("") } function handleJournal(e, newInputValue) { if (newInputValue){ getSelectedJournalId(newInputValue) return } setJournalId("") } function handleSubmit(e) { setLoading(true) e.preventDefault() //reset precedent results setConditions([]) setDetails([]) updateResult([]) if (!institId && !journalId && !funderId){ setLoading(false) } if (institId && !journalId && !funderId){ //get organizations conditions // alert(`get api organization Condition only: ${institId}`) //condtion type is not journal only = 1 // Get the user const sendSearchInstitOnly = async () => { try { const resp = await searchorganizationonly(institId,1) console.log(resp.data) setConditions(arr => [...arr, resp.data]) } catch (err) { // Handle Error Here console.error(err); } setLoading(false) } console.log(details) const sendGetrequest = async () => { try { const resp = await getInstitution(institId) console.log(resp.data) updateResult(arr => [...arr, resp.data]) // if (details === "null") { // setDetails(resp.data) // } // else { // setDetails(prevArray => [...prevArray, resp.data]) // } } catch (err) { // Handle Error Here console.error(err); } } sendSearchInstitOnly().then( sendGetrequest() ) - history.push({pathname:`/check/Instiution`, search : `id=${institId}`}) + history.push({pathname:`check`, search:`institution=${institId}`}) + } - + else if (!institId && !journalId && funderId){ //get funder conditions // alert(`get api funder Condition only: ${funderId}`) //condtion type is not journal only = 1 const sendSearchOrgaOnly = async () => { try { const resp = await searchorganizationonly(funderId,1) console.log(resp.data) setConditions(arr => [...arr, resp.data]) } catch (err) { // Handle Error Here console.error(err); } setLoading(false) } const sendGetrequest = async () => { try { const resp = await getFunder(funderId) console.log(resp.data) updateResult(arr => [...arr, resp.data]) } catch (err) { // Handle Error Here console.error(err); } } sendSearchOrgaOnly().then( sendGetrequest() ) - history.push({pathname:`/check/Funder`, search : `id=${funderId}`}) + history.push({pathname:`check`, search:`funder=${funderId}`}) } else if (!funderId && !institId && journalId){ //get journals conditions // alert(`get api journal Condition only: ${journalId}`) //condtion type is not institution only = 2 //get journal detail const sendSearchJournalOnly = async () => { try { const resp = await searchjournalonly(journalId,2) console.log(resp.data) setConditions(arr => [...arr, resp.data]) // setConditions(arr => [...arr, resp.data]) } catch (err) { // Handle Error Here console.error(err); } setLoading(false) } const sendGetrequest = async () => { try { const resp = await getJournal(journalId) console.log(resp.data) updateResult(arr => [...arr, resp.data]) } catch (err) { // Handle Error Here console.error(err); } } sendSearchJournalOnly().then( sendGetrequest() ) - history.push({pathname:`/check/Journal`, search : `id=${journalId}`}) + history.push({pathname:`check`, search:`journal=${journalId}`}) } else if (institId && funderId && !journalId) { //alert(`get api Filter Conditions SET--> Journal: ${journalId} VS Institution: ${institId}`) //condtion type journal/condition = 3 const sendSearchCondi = async () => { try { const resp = await searchInstitFunder(institId, funderId, 1) console.log(resp.data) setConditions(arr => [...arr, resp.data]) } catch (err) { // Handle Error Here console.error(err); } setLoading(false) } const sendGetInstit = async () => { try { const resp = await getInstitution(institId) console.log(resp.data) + //manage the order output // detailArray.push(resp.data) // setDetails(detailArray) updateResult(arr => [...arr, resp.data]) + + } catch (err) { // Handle Error Here console.error(err); } } const sendGetFunder = async () => { try { const resp = await getFunder(funderId) console.log(resp.data) updateResult(arr => [...arr, resp.data]) + } catch (err) { // Handle Error Here console.error(err); } } sendSearchCondi().then( sendGetInstit().then(sendGetFunder()) ) - history.push({pathname:`/check/Instit&Funder`, search : `id=${institId}&id=${funderId}`}) + history.push({pathname:`check`, search: `institution=${institId}&funder=${funderId}`}) } else if (institId && journalId && !funderId) { //alert(`get api Filter Conditions SET--> Journal: ${journalId} VS Institution: ${institId}`) //condtion type journal/condition = 3 const sendSearchCondi = async () => { try { const resp = await searchCondi(journalId,institId) console.log(resp.data) setConditions(arr => [...arr, resp.data]) } catch (err) { // Handle Error Here console.error(err); } setLoading(false) } - + const sendGetInstit = + async () => { + try { + const resp = await getInstitution(institId) + console.log(resp.data) + + updateResult(arr => [...arr, resp.data]) + + } catch (err) { + // Handle Error Here + console.error(err); + } + + } const sendGetJournal = async () => { try { const resp = await getJournal(journalId) console.log(resp.data) // detailArray.push(resp.data) // setDetails(detailArray) updateResult(arr => [...arr, resp.data]) - + } catch (err) { // Handle Error Here console.error(err); } } - const sendGetInstit = - async () => { - try { - const resp = await getInstitution(institId) - console.log(resp.data) - - updateResult(arr => [...arr, resp.data]) - - } catch (err) { - // Handle Error Here - console.error(err); - } - - } + sendSearchCondi().then( - sendGetJournal().then(sendGetInstit()) + sendGetInstit().then(sendGetJournal) ) - history.push({pathname:`/check/Instit&Journal`, search : `id=${institId}&id=${journalId}`}) + history.push({pathname:`check`, search: `institution=${institId}&journal=${journalId}`}) } else if (!institId && journalId && funderId) { // alert(`get api Filter Conditions SET--> Journal: ${journalId} VS Institution: ${funderId}`) //condtion type journal/institution/funder conditions = 3 const sendGetCondi = async () => { try { const resp = await searchCondi(journalId,funderId) console.log(resp.data) setConditions(arr => [...arr, resp.data]) } catch (err) { // Handle Error Here console.error(err); } setLoading(false) } + const sendGetFunder = + async () => { + try { + const resp = await getFunder(funderId) + console.log(resp.data) + updateResult(arr => [...arr, resp.data]) + } catch (err) { + // Handle Error Here + console.error(err); + } + } const sendGetJournal = async () => { try { const resp = await getJournal(journalId) console.log(resp.data) updateResult(arr => [...arr, resp.data]) } catch (err) { // Handle Error Here console.error(err); } } - const sendGetFunder = - async () => { - try { - const resp = await getFunder(funderId) - console.log(resp.data) - updateResult(arr => [...arr, resp.data]) - } catch (err) { - // Handle Error Here - console.error(err); - } - } + sendGetCondi().then( sendGetJournal().then( sendGetFunder() ) ) - history.push({pathname:`/check/Funder&Journal`, search : `id=${funderId}&id=${journalId}`}) + history.push({pathname:`check`, search: `funder=${funderId}&journal=${journalId}`}) } else if (institId && journalId && funderId) { // alert(`get api Filter Conditions SET--> Journal: ${journalId} VS Institution: ${funderId}`) //condtion type journal/institution/funder conditions = 3 console.log("main check !") //(institution + journal) const detailArray = [] const sendGetCondi = async () => { try { const resp = await searchCondi3(institId,journalId,funderId) console.log(resp.data) setConditions(arr => [...arr, resp.data]) } catch (err) { // Handle Error Here console.error(err); } setLoading(false) } - const sendGetJournal = - async () => { - try { - const resp = await getJournal(journalId) - console.log(resp.data) - updateResult(arr => [...arr, resp.data]) - } catch (err) { - // Handle Error Here - console.error(err); - } - } - const sendGetFunder = + + const sendGetInstit = async () => { try { - const resp = await getFunder(funderId) + const resp = await getInstitution(institId) console.log(resp.data) updateResult(arr => [...arr, resp.data]) + + } catch (err) { // Handle Error Here console.error(err); } } - const sendGetInstit = + const sendGetFunder = async () => { try { - const resp = await getInstitution(institId) + const resp = await getFunder(funderId) console.log(resp.data) - detailArray.push(resp.data) updateResult(arr => [...arr, resp.data]) - } catch (err) { // Handle Error Here console.error(err); } } - - - // sendGetCondi1().then(sendGetCondi2()) + const sendGetJournal = + async () => { + try { + const resp = await getJournal(journalId) + console.log(resp.data) + updateResult(arr => [...arr, resp.data]) + + } catch (err) { + // Handle Error Here + console.error(err); + } + } + + //order the request sendGetCondi() - sendGetJournal().then( - sendGetFunder().then( - sendGetInstit() - ) + sendGetInstit().then( + sendGetFunder() + ).then( + sendGetJournal() ) - history.push({pathname:`/check/Instit&Funder&Journal`, search : `id=${institId}&id=${funderId}&id=${journalId}`}) + history.push({pathname:`check`, search: `institution=${institId}&funder=${funderId}&journal=${journalId}`}) + } - - // alert(`Submit Institution: ID: ${institId} , Submit Funder: ${fund}, Submit Journal ID: ${journalId}`) } -// const conditionIdArray = [] -// conditions.map((item) =>( -// conditionIdArray.push(item.id) -// )) - -// console.log(conditionIdArray) - console.log(`all conditions SET: ${conditions}`) console.log(details) console.log(`Selected Institution ID: ${institId} , Selected Funder: ${funderId}, Selected Journal ID: ${journalId}`) function detailsResult() { - - - +console.log(details) +console.log(result) if (details !== 'null') { return (
- + } aria-controls="panel1a-content" id="panel1a-header" >

Selected option(s)

{result?.map(i => ( - - - {/* { journalId && - - - - } */} - {/* { institId && - - } - { funderId && - - } - - */} - ))}
) } } function conditionResults () { return (
{conditions?.map(i=> ( ))}
) } + + return (
option.name)} renderOption={(params) => ( {params} )} // getOptionLabel={(option) => option.name} // filterOptions={filterOptions} onInputChange={handleInstit} + // inputValue={institName} renderInput={(params) => ( )} + /> option.name)} renderOption={(params) => ( {params} )} onInputChange={handleFunder} renderInput={(params) => ( )} /> option.name)} renderOption={(params) => ( {params} )} onInputChange={handleJournal} renderInput={(params) => ( )} /> {!loading && } {loading && }
{detailsResult()} {conditionResults()} - + { history.location.pathname === "/check" && + + + + } + + {"Share your Result!"} + + + + {url} + + + + + + +
); } \ No newline at end of file diff --git a/django_api/admin.py b/django_api/admin.py index d98e271d..c819e02e 100644 --- a/django_api/admin.py +++ b/django_api/admin.py @@ -1,292 +1,374 @@ from django.contrib import admin +from django import forms from datetime import date from import_export.admin import ImportExportModelAdmin -from django.contrib.admin import TabularInline, SimpleListFilter +from django.contrib.admin import TabularInline +from django.contrib.admin import SimpleListFilter +from django.contrib.admin import RelatedOnlyFieldListFilter from django.utils.translation import gettext_lazy as _ #from inline_actions.admin import InlineActionsMixin #from inline_actions.admin import InlineActionsModelAdminMixin from django.shortcuts import render from django.http import HttpResponseRedirect from django.urls import reverse from django.utils.html import escape, mark_safe, format_html from .models import Country from .models import Language from .models import Issn from .models import Oa from .models import Publisher from .models import Journal from .models import Organization from .models import Version from .models import Licence from .models import Cost_factor_type from .models import Cost_factor from .models import Term from .models import ConditionType from .models import ConditionSet from .models import OrganizationCondition from .models import JournalCondition # Register your models here. +@admin.register(Issn) +class IssnAdmin(ImportExportModelAdmin): + list_filter = ('issn_type', ) + + +class IssnInline(admin.TabularInline): + model = Issn + readonly_fields = ('issn', 'issn_type',) + # This Inline is stricty read-only for the moment + def has_change_permission(self, request, obj=None): + return False + + def has_add_permission(self, request, obj=None): + return False + + def has_delete_permission(self, request, obj=None): + return False + @admin.register(Journal) class JournalAdmin(ImportExportModelAdmin): - list_display = ("id", "name", "journal_issns",) + list_display = ("id", "name", "get_journal_issns",) list_filter = ('publisher__name', 'oa_status') filter_horizontal = ('publisher', 'language', ) + inlines = (IssnInline, ) - def journal_issns(self, obj): - # TBD - pass + def get_journal_issns(self, obj): + return list(Issn.objects.filter(journal=obj)) + get_journal_issns.short_description = 'ISSNs' @admin.register(Language) class LanguageAdmin(ImportExportModelAdmin): pass @admin.register(Organization) class OrganizationAdmin(ImportExportModelAdmin): list_display = ("id", "name") list_filter = ('is_funder',) filter_horizontal = ('country', ) @admin.register(Version) class VersionAdmin(ImportExportModelAdmin): pass @admin.register(Country) class CountryAdmin(ImportExportModelAdmin): pass -@admin.register(Issn) -class IssnAdmin(ImportExportModelAdmin): - list_filter = ('issn_type', ) - - @admin.register(Oa) class OaAdmin(ImportExportModelAdmin): pass @admin.register(Publisher) class PublisherAdmin(ImportExportModelAdmin): list_display = ("id", "name") # Experimental: what will happen with 200+ countries in the database? list_filter = ('country__name', ) filter_horizontal = ('country', ) @admin.register(Term) class TermAdmin(ImportExportModelAdmin): list_filter = ('version', 'licence') filter_horizontal = ('version', 'cost_factor', 'licence', ) + # textarea input is better for comments + def get_form(self, request, obj=None, **kwargs): + kwargs['widgets'] = {'comment': forms.Textarea} + return super().get_form(request, obj, **kwargs) + @admin.register(ConditionType) class ConditionTypeAdmin(ImportExportModelAdmin): list_display = ("id", "condition_issuer") #class JournalConditionInline(InlineActionsMixin, TabularInline): class JournalConditionInline(TabularInline): model = JournalCondition extra = 1 inline_actions = ['connect_all_journals'] def connect_all_journals(self, request, obj, parent_obj=None): # Do stuff here, then return None to go to current view return None - connect_all_journals.short_description = ("Connect Condition Set with all Journals") + connect_all_journals.short_description = ("Connect Condition Set with some or all Journals") class OrganizationConditionInline(TabularInline): #class OrganizationConditionInline(InlineActionsMixin, TabularInline): model = OrganizationCondition extra = 1 def connect_with_all_journals(modeladmin, request, queryset): # print(request.POST) if request.POST.get('apply'): try: valid_from = date.fromisoformat(request.POST['valid_from']) valid_until = date.fromisoformat(request.POST['valid_until']) + issn_list = [x for x in request.POST['issn_list'].replace(',','\n',).replace(';','\n').replace(' ','\n').split('\n') if len(x) > 0] + print(issn_list) if valid_from > valid_until: raise ValueError # print((valid_from, valid_until)) - all_journals = Journal.objects.all() + if len(issn_list) == 0: + all_journals = Journal.objects.all() + else: + all_journals = Journal.objects.filter(issn__issn__in=issn_list).distinct() + print(all_journals) + print(len(issn_list), len(all_journals)) + all_journals =[] for condition_set in queryset: # print('-----------------') # print(condition_set) for j in all_journals: # print(j) # search for existing connections existing_connections = JournalCondition.objects.filter(journal=j, condition_set=condition_set, valid_from__lt=date.today(), valid_until__gt=date.today()) # print(existing_connections) if len(existing_connections) == 0: new_journal_condition = JournalCondition(journal=j, condition_set=condition_set, valid_from=valid_from, valid_until=valid_until) new_journal_condition.save() return None except ValueError: pass return render(request, 'admin/get_validity_dates.html', context={'queryset': queryset, 'objects': 'journals'}) connect_with_all_journals.short_description = 'Apply selected condition sets to all Journals' def connect_with_all_organizations(modeladmin, request, queryset): - # print(request.POST) if request.POST.get('apply'): try: valid_from = date.fromisoformat(request.POST['valid_from']) valid_until = date.fromisoformat(request.POST['valid_until']) if valid_from > valid_until: raise ValueError # print((valid_from, valid_until)) all_orgs = Organization.objects.all() for condition_set in queryset: # print('-----------------') # print(condition_set) for o in all_orgs: # print(o) # search for existing connections existing_connections = OrganizationCondition.objects.filter(organization=o, condition_set=condition_set, valid_from__lt=date.today(), valid_until__gt=date.today()) # print(existing_connections) if len(existing_connections) == 0: new_organization_condition = OrganizationCondition(organization=o, condition_set=condition_set, valid_from=valid_from, valid_until=valid_until) new_organization_condition.save() return None except ValueError: pass return render(request, 'admin/get_validity_dates.html', context={'queryset': queryset, 'objects': 'organizations'}) connect_with_all_organizations.short_description = 'Apply selected condition sets to all Organizations' +def end_validity(modeladmin, request, queryset): + # print(request.POST) + if request.POST.get('apply'): + try: + valid_until = date.fromisoformat(request.POST['date']) + print(valid_until) + + for x_condition in queryset: + x_condition.valid_until = valid_until + x_condition.save() + return None + + except ValueError: + pass + return render(request, 'admin/get_single_validity_date.html', + context={'queryset': queryset, 'limit': 'end', 'objects': 'selected journal-condition connections'}) + +end_validity.short_description = 'Set valid_until date' + + @admin.register(ConditionSet) class ConditionSetAdmin(ImportExportModelAdmin): # class ConditionSetAdmin(InlineActionsModelAdminMixin, ImportExportModelAdmin): list_display = ("id", "condition_type", "comment") search_fields = ['organization__name', 'journal__name', 'comment'] list_filter = ('condition_type', ) filter_horizontal = ('term', ) inlines = (OrganizationConditionInline, JournalConditionInline, ) actions = [connect_with_all_journals, connect_with_all_organizations] + # textarea input is better for comments + def get_form(self, request, obj=None, **kwargs): + kwargs['widgets'] = {'comment': forms.Textarea} + return super().get_form(request, obj, **kwargs) + class XConditionValidListFilter(SimpleListFilter): # Human-readable title which will be displayed in the # right admin sidebar just above the filter options. title = _('currently valid') # Parameter for the filter that will be used in the URL query. parameter_name = 'valid' def lookups(self, request, model_admin): """ Returns a list of tuples. The first element in each tuple is the coded value for the option that will appear in the URL query. The second element is the human-readable name for the option that will appear in the right sidebar. """ return ( ('true', _('True')), ('false', _('False')), ) def queryset(self, request, queryset): """ Returns the filtered queryset based on the value provided in the query string and retrievable via `self.value()`. """ # Compare the requested value (either '80s' or '90s') # to decide how to filter the queryset. if self.value() == 'true': return queryset.filter(valid_from__lte=date.today(), valid_until__gte=date.today()) if self.value() == 'false': return queryset.exclude(valid_from__lte=date.today(), valid_until__gte=date.today()) +class ConditionSetListDynamicFilter(SimpleListFilter): + title = _('condition sets (publisher-dependant)') + + parameter_name = 'condition_set' + + def lookups(self, request, model_admin): + if 'journal__publisher__name' in request.GET: + # A publisher name filter is in effect + journal_publisher_name = request.GET['journal__publisher__name'] + condition_sets = set([c.condition_set for c in model_admin.model.objects.all().filter(journal__publisher__name=journal_publisher_name)]) + else: + condition_sets = set([c.condition_set for c in model_admin.model.objects.all()]) + return [(s.id, str(s)) for s in condition_sets] + + def queryset(self, request, queryset): + if self.value(): + return queryset.filter(condition_set__id__exact=self.value()) + + @admin.register(OrganizationCondition) class OrganizationConditionAdmin(ImportExportModelAdmin): def link_to_conditionset(self, obj): link = reverse("admin:django_api_conditionset_change", args=[obj.condition_set.id]) return format_html(f'{obj.condition_set}') link_to_conditionset.short_description = 'Condition Set' #list_display = ("id", "organization_name", "condition_set", "valid_from", "valid_until") list_display = ("id", "organization_name", "link_to_conditionset", "valid_from", "valid_until") - list_filter = ('condition_set__condition_type', XConditionValidListFilter) + list_filter = ('condition_set__condition_type', XConditionValidListFilter, + ('condition_set', RelatedOnlyFieldListFilter)) def organization_name(self, obj): return obj.organization.name @admin.register(Licence) class LicenceAdmin(ImportExportModelAdmin): pass @admin.register(JournalCondition) class JournalConditionAdmin(ImportExportModelAdmin): def link_to_conditionset(self, obj): link = reverse("admin:django_api_conditionset_change", args=[obj.condition_set.id]) return format_html(f'{obj.condition_set}') link_to_conditionset.short_description = 'Condition Set' list_display = ("id", "journal_name", "link_to_conditionset", "valid_from", "valid_until") - list_filter = ('condition_set__condition_type', XConditionValidListFilter, 'journal__publisher__name') + list_filter = ('condition_set__condition_type', XConditionValidListFilter, + 'journal__publisher__name', + ConditionSetListDynamicFilter) + actions =(end_validity,) def journal_name(self, obj): return obj.journal.name # unsuccessful attempt # def formfield_for_foreignkey(self, db_field, request, **kwargs): # if db_field.name == "journal": # kwargs["queryset"] = Journal.objects.filter(publisher__name__in=Publisher.objects.order_by().values('name').distinct()) # return super().formfield_for_foreignkey(db_field, request, **kwargs) @admin.register(Cost_factor) class Cost_factorAdmin(ImportExportModelAdmin): list_display = ("id", "comment", "amount", "symbol") list_filter = ('cost_factor_type', 'symbol') + # textarea input is better for comments + def get_form(self, request, obj=None, **kwargs): + kwargs['widgets'] = {'comment': forms.Textarea} + return super().get_form(request, obj, **kwargs) + @admin.register(Cost_factor_type) class Cost_factor_typeAdmin(ImportExportModelAdmin): list_display = ("id", "name") diff --git a/django_api/migrations/0072_auto_20210811_1019.py b/django_api/migrations/0072_auto_20210811_1019.py new file mode 100644 index 00000000..9500ae6d --- /dev/null +++ b/django_api/migrations/0072_auto_20210811_1019.py @@ -0,0 +1,41 @@ +# Generated by Django 3.1.8 on 2021-08-11 08:19 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('django_api', '0071_journal_end_year'), + ] + + operations = [ + migrations.AlterModelOptions( + name='cost_factor', + options={'ordering': ('amount',)}, + ), + migrations.AlterModelOptions( + name='licence', + options={'ordering': ('name_or_abbrev',)}, + ), + migrations.RemoveField( + model_name='journal', + name='issn', + ), + migrations.AddField( + model_name='issn', + name='journal', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='django_api.journal'), + ), + migrations.AddField( + model_name='organization', + name='ir_name', + field=models.CharField(max_length=40, null=True, verbose_name='Institutional repository name'), + ), + migrations.AddField( + model_name='organization', + name='ir_url', + field=models.URLField(max_length=100, null=True, verbose_name='Institutional repository URL'), + ), + ] diff --git a/django_api/models.py b/django_api/models.py index c9f5a728..60cf1edb 100644 --- a/django_api/models.py +++ b/django_api/models.py @@ -1,227 +1,263 @@ from django.db import models from django.contrib.auth.models import User import datetime from django.utils.translation import gettext as _ # Ref: database_model_20210421_MB.drawio 21.04.2021 class Country(models.Model): name = models.CharField(verbose_name="Country name", max_length=120, null=True) iso_code = models.CharField(max_length=3, null=True) def __str__(self): return f"{self.name}" class Meta: ordering = ('name',) class Language(models.Model): name = models.CharField(verbose_name="Language name", max_length=120, null=True) iso_code = models.CharField(max_length=3, null=True) def __str__(self): return f"{self.name}" class Meta: ordering = ('name',) class Oa(models.Model): status = models.CharField(max_length=1000, null=True) description = models.CharField(max_length=1000, null=True) subscription = models.BooleanField(default=False) accepted_manuscript = models.BooleanField(default=False) apc = models.BooleanField(default=False) final_version = models.BooleanField(default=False) def __str__(self): return f"{self.status}" class Meta: ordering = ('-subscription',) class Publisher(models.Model): name = models.CharField(verbose_name="Publisher name", max_length=1000, null=True) city = models.CharField(max_length=100, null=True) state = models.CharField(max_length=3, null=True) country = models.ManyToManyField("Country") starting_year = models.IntegerField() website = models.URLField(max_length=1000) oa_policies = models.URLField(max_length=1000) def __str__(self): return f"{self.name}" class Meta: ordering = ('name',) + class Issn(models.Model): - PRINT = 1 - ELECTRONIC = 2 - OTHER = 3 + PRINT = '1' + ELECTRONIC = '2' + OTHER = '3' TYPE_CHOICES = ( (PRINT, 'Print'), (ELECTRONIC, 'Electronic'), (OTHER, 'Other'), ) + journal = models.ForeignKey("Journal", null=True, on_delete=models.CASCADE, related_name = "classIssn") #journal.classissn issn = models.CharField(max_length=9, null=False) issn_type = models.CharField( choices=TYPE_CHOICES, max_length=10, blank=True ) def __str__(self): - return f"{self.issn} ({dict(self.TYPE_CHOICES)[int(self.issn_type)]})" + return f"{self.issn} ({dict(self.TYPE_CHOICES)[self.issn_type]})" class Meta: ordering = ('issn',) class Journal(models.Model): name = models.CharField(verbose_name="Journal name", max_length=800, blank=True, null=True) # search journal with name name_short_iso_4 = models.CharField(max_length=300, blank=True, null=True) publisher = models.ManyToManyField(Publisher) website = models.URLField(max_length=300, blank=True, null=True) language = models.ManyToManyField(Language) - issn = models.ManyToManyField("Issn") # search journal with ISSN + # 2021-08-11: only one-to-many relationship between Journal and ISSN + # issn = models.ForeignKey("Issn", null=True, on_delete=models.CASCADE) oa_options = models.URLField(max_length=1000, blank=True, null=True) oa_status = models.ForeignKey("Oa", on_delete=models.CASCADE) starting_year = models.IntegerField(blank=True, null=True) end_year = models.IntegerField(blank=True, null=True) doaj_seal = models.BooleanField(default=False) doaj_status = models.BooleanField(default=False) lockss = models.BooleanField(default=False) nlch = models.BooleanField(default=False) portico = models.BooleanField(default=False) qoam_av_score = models.DecimalField(decimal_places=2, max_digits=5, blank=True, null=True) def __str__(self): return f"{self.name} from {self.website}" class Meta: ordering = ('name',) - - - class Organization(models.Model): name = models.CharField(verbose_name="Organization name", max_length=600, null=True) website = models.URLField(max_length=600, blank=True, null=True) country = models.ManyToManyField("Country") ror = models.CharField(max_length=255, blank=True, null=True) fundref = models.CharField(max_length=255, blank=True, null=True) starting_year = models.IntegerField(blank=True, null=True) is_funder = models.BooleanField(default=False) + ir_name = models.CharField(verbose_name="Institutional repository name", max_length=40, null=True) + ir_url = models.URLField(verbose_name="Institutional repository URL", max_length=100, null=True) def __str__(self): return f"{self.name}" class Meta: ordering = ('name',) class Version(models.Model): description = models.CharField(max_length=300, null=False) def __str__(self): return f"{self.description}" class Licence(models.Model): name_or_abbrev = models.CharField(max_length=300, null=False) website = models.URLField(max_length=600, null=True) + class Meta: + ordering = ('name_or_abbrev',) + def __str__(self): return f"{self.name_or_abbrev}" class Cost_factor_type(models.Model): name = models.CharField(max_length=300, null=False) def __str__(self): return f"{self.name}" class Cost_factor(models.Model): cost_factor_type = models.ForeignKey(Cost_factor_type, on_delete=models.CASCADE, blank=True, null=True) amount = models.IntegerField(null=False) symbol = models.CharField(max_length=10, null=False) comment = models.CharField(max_length=120, default="") + class Meta: + ordering = ('amount',) + def __str__(self): return f"{self.amount} {self.symbol}" class Term(models.Model): version = models.ManyToManyField(Version) cost_factor = models.ManyToManyField(Cost_factor) embargo_months = models.IntegerField(blank=True, null=True) ir_archiving = models.BooleanField(default=False) licence = models.ManyToManyField(Licence) comment = models.CharField(max_length=600, null=True) source = models.URLField(max_length=600, null=True) def __str__(self): - # TODO why does this break JSON uploads in the admin interface? - # return f"{self.id} about {';'.join([x.description for x in self.version.all()])} - {self.comment}" - return f"{self.id} - {self.comment}" + try: + # Maybe these fields should not allow NULL values? + if self.embargo_months is None: + embargo = 'no_' + else: + embargo = str(self.embargo_months) + + if self.comment is None: + comment = '' + else: + comment = str(self.comment) + + if self.source is None: + source = '' + else: + source = str(self.comment) + + term_data = (str(self.id), + ';'.join([str(x) for x in self.version.all()]), + ';'.join([str(x) for x in self.licence.all()]), + ';'.join([str(x) for x in self.cost_factor.all()]), + f'Archiving{str(self.ir_archiving)} {embargo}months', + comment,) + return ' - '.join(term_data) + except RecursionError: + # The JSON import in the admin module somehow throws a ValueError during the loading process + # probably due to incomplete information in the many2many relationships + # Then the error log apparently triggers a cascade of errors until + # the RecursionError level is hit. Falling back to a basic __str__ + # for the RecursionError seems to bypass the problem. + return f"[Term.__str__() error] {self.id} - {self.comment}" class Meta: - ordering = ('-ir_archiving','embargo_months', 'comment') + ordering = ('-ir_archiving', 'embargo_months', 'comment') class ConditionType(models.Model): condition_issuer = models.CharField(max_length=300, null=False) def __str__(self): return f"{self.condition_issuer}" class ConditionSet(models.Model): condition_type = models.ForeignKey(ConditionType, on_delete=models.CASCADE, blank=True, null=True) organization = models.ManyToManyField( Organization, through='OrganizationCondition', through_fields=('condition_set', 'organization') ) journal = models.ManyToManyField( Journal, through='JournalCondition', through_fields=('condition_set', 'journal') ) term = models.ManyToManyField(Term) comment = models.CharField(max_length=100, null=True, blank=True) def __str__(self): return f"{self.id} {self.condition_type}|{self.comment}" class Meta: ordering = ('-condition_type__pk','comment') class OrganizationCondition(models.Model): organization = models.ForeignKey(Organization, on_delete=models.CASCADE, blank=True, null=True) condition_set = models.ForeignKey(ConditionSet, on_delete=models.CASCADE, blank=True, null=True) valid_from = models.DateField(blank=True, null=True) valid_until = models.DateField(blank=True, null=True) def __str__(self): return f"{self.id} {self.organization}/{self.condition_set}" class JournalCondition(models.Model): journal = models.ForeignKey(Journal, on_delete=models.CASCADE, blank=True, null=True) condition_set = models.ForeignKey(ConditionSet, on_delete=models.CASCADE, blank=True, null=True) valid_from = models.DateField(blank=True, null=True) valid_until = models.DateField(blank=True, null=True) def __str__(self): return f"{self.id} {self.journal.name}/{self.condition_set}" diff --git a/django_api/serializers.py b/django_api/serializers.py index 224975a3..9ee7839d 100644 --- a/django_api/serializers.py +++ b/django_api/serializers.py @@ -1,128 +1,127 @@ from rest_framework import serializers from dj_rql.drf.serializers import RQLMixin from .models import * -class JournalSerializer(RQLMixin,serializers.ModelSerializer): - class Meta: - model = Journal - fields = '__all__' - depth = 4 - - class OrgaSerializer(RQLMixin,serializers.ModelSerializer): class Meta: model = Organization fields = '__all__' depth = 4 class TermSerializer(RQLMixin,serializers.ModelSerializer): class Meta: model = Term fields = '__all__' depth = 4 class ConditionSetSerializer(RQLMixin,serializers.ModelSerializer): term = TermSerializer(many=True, read_only=True) class Meta: model = ConditionSet # pre filter for rql # fields = ['id','condition_type','term','journal','organization'] # add for informations purpose fields = '__all__' depth = 4 class TermSerializer(RQLMixin,serializers.ModelSerializer): class Meta: model = Term fields = '__all__' depth = 2 class CountrySerializer(RQLMixin,serializers.ModelSerializer): class Meta: model = Country fields = '__all__' depth = 4 class LanguageSerializer(RQLMixin,serializers.ModelSerializer): class Meta: model = Language fields = '__all__' depth = 4 class IssnSerializer(RQLMixin,serializers.ModelSerializer): class Meta: model = Issn fields = '__all__' depth = 4 +class JournalSerializer(RQLMixin,serializers.ModelSerializer): + issn = IssnSerializer(source='classIssn', many=True) + class Meta: + model = Journal + fields = '__all__' + depth = 4 class OaSerializer(RQLMixin,serializers.ModelSerializer): class Meta: model = Oa fields = '__all__' depth = 4 class PublisherSerializer(RQLMixin,serializers.ModelSerializer): class Meta: model = Publisher fields = '__all__' depth = 4 class VersionSerializer(RQLMixin,serializers.ModelSerializer): class Meta: model = Version fields = '__all__' depth = 4 class LicenceSerializer(RQLMixin,serializers.ModelSerializer): class Meta: model = Licence fields = '__all__' depth = 4 class Cost_factor_typeSerializer(RQLMixin,serializers.ModelSerializer): class Meta: model = Cost_factor_type fields = '__all__' depth = 4 class Cost_factorSerializer(RQLMixin,serializers.ModelSerializer): class Meta: model = Cost_factor fields = '__all__' depth = 4 class ConditionTypeSerializer(RQLMixin,serializers.ModelSerializer): class Meta: model = ConditionType fields = '__all__' depth = 4 class OrganizationConditionSerializer(RQLMixin,serializers.ModelSerializer): class Meta: model = OrganizationCondition fields = '__all__' depth = 4 class JournalConditionSerializer(RQLMixin,serializers.ModelSerializer): class Meta: model = JournalCondition fields = '__all__' depth = 4 diff --git a/templates/admin/get_single_validity_date.html b/templates/admin/get_single_validity_date.html new file mode 100644 index 00000000..c3a8eed6 --- /dev/null +++ b/templates/admin/get_single_validity_date.html @@ -0,0 +1,21 @@ +{% extends "admin/base_site.html" %} + +{% block content %} + + +
+ {% csrf_token %} +

+ Enter the {{ limit }} date for the selected conditions: +

+ +
+ {% for obj in queryset %} + + {% endfor %} + + + + +
+{% endblock %} \ No newline at end of file diff --git a/templates/admin/get_validity_dates.html b/templates/admin/get_validity_dates.html index 423b39a4..89e8b2a5 100644 --- a/templates/admin/get_validity_dates.html +++ b/templates/admin/get_validity_dates.html @@ -1,25 +1,35 @@ {% extends "admin/base_site.html" %} {% block content %} +
{% csrf_token %}

Enter the validity dates for the selected conditions:

From:
Until:
+ {% if objects == 'journals' %} +

+ Applicable to the following ISSNs (leave blank for all journals): +

+ +
+ {% endif %} {% for obj in queryset %} {% endfor %}
{% endblock %} \ No newline at end of file