├── .dockerignore ├── public ├── _redirects ├── robots.txt ├── favicon.ico ├── logo192.png ├── manifest.json └── index.html ├── .babelrc ├── src ├── pages │ ├── Journal │ │ ├── Journal.css │ │ └── Journal.js │ ├── index.js │ ├── Home.js │ └── Manifesto │ │ ├── Manifesto.css │ │ └── Manifesto.js ├── graphql │ ├── mutation │ │ ├── LOGOUT.js │ │ ├── deleteJournal.js │ │ ├── login.js │ │ ├── register.js │ │ ├── createJournal.js │ │ └── updateJournal.js │ └── queries │ │ ├── GET_USER.js │ │ ├── getAllJournals.js │ │ └── getFullJournalByISSN.js ├── utils │ └── toErrorMap.js ├── components │ ├── marginals │ │ ├── Loader │ │ │ ├── Spinner.js │ │ │ └── Spinner.css │ │ ├── shared │ │ │ ├── Layout.js │ │ │ ├── SectionLayout.js │ │ │ └── PolicyContainer.js │ │ ├── index.js │ │ ├── Search │ │ │ └── Search.js │ │ ├── Navbar │ │ │ ├── Navbar.js │ │ │ └── styles.js │ │ ├── Footer │ │ │ ├── styles.js │ │ │ └── Footer.js │ │ └── Error │ │ │ ├── error.css │ │ │ └── Error.js │ ├── Authentication │ │ ├── FormSuccess.js │ │ ├── Login │ │ │ ├── validateLoginInfo.js │ │ │ ├── LoginForm.js │ │ │ ├── styles.js │ │ │ └── Login.js │ │ ├── User-Profile │ │ │ ├── Logout.js │ │ │ ├── styles.js │ │ │ └── useprofile.js │ │ ├── Signup │ │ │ ├── validateInfo.js │ │ │ ├── Form.js │ │ │ └── SignUp.js │ │ └── styles.js │ ├── index.js │ ├── Journals │ │ ├── Journal.js │ │ ├── useFetch.js │ │ ├── styles.js │ │ └── JournalList.js │ ├── Pagination │ │ └── Pagination.js │ ├── Landing │ │ ├── Header │ │ │ ├── Header.js │ │ │ └── Header.css │ │ └── LandingSection │ │ │ ├── LandingSection.js │ │ │ └── styles.js │ ├── JournalDetails │ │ ├── styles.js │ │ └── Details.js │ ├── AddJournal │ │ ├── styles.js │ │ └── AddJournal.js │ └── EditJournal │ │ └── Edit.js ├── config │ └── content │ │ ├── index.js │ │ ├── signup.js │ │ ├── navbar.js │ │ ├── footer.js │ │ ├── landingpage.js │ │ └── manifesto.js ├── index.js ├── context │ ├── types.js │ ├── DataContext.js │ └── reducer.js ├── index.css └── App.js ├── logo.webp ├── Dockerfile ├── .prettierrc ├── .github ├── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md ├── workflows │ └── docker-image.yml └── PULL_REQUEST_TEMPLATE.md ├── LICENSE ├── .eslintrc ├── package.json ├── README.md └── .gitignore /.dockerignore: -------------------------------------------------------------------------------- 1 | /node_modules -------------------------------------------------------------------------------- /public/_redirects: -------------------------------------------------------------------------------- 1 | /* /index.html 200 -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-react"] 3 | } 4 | -------------------------------------------------------------------------------- /src/pages/Journal/Journal.css: -------------------------------------------------------------------------------- 1 | .journal-padding{ 2 | padding-top: 7em; 3 | } -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /logo.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeisscience/journal-policy-tracker-frontend/HEAD/logo.webp -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeisscience/journal-policy-tracker-frontend/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeisscience/journal-policy-tracker-frontend/HEAD/public/logo192.png -------------------------------------------------------------------------------- /src/pages/index.js: -------------------------------------------------------------------------------- 1 | export { default as Journal } from './Journal/Journal'; 2 | export { default as Manifesto } from './Manifesto/Manifesto'; 3 | export { default as Home } from './Home'; 4 | -------------------------------------------------------------------------------- /src/graphql/mutation/LOGOUT.js: -------------------------------------------------------------------------------- 1 | import { gql } from '@apollo/client'; 2 | 3 | const LOGOUT = gql` 4 | mutation Mutation { 5 | logout 6 | } 7 | `; 8 | 9 | export default LOGOUT; 10 | -------------------------------------------------------------------------------- /src/utils/toErrorMap.js: -------------------------------------------------------------------------------- 1 | export const toErrorMap = (errors) => { 2 | const errorMap = {}; 3 | errors.forEach(({ field, message }) => { 4 | errorMap[field] = message; 5 | }); 6 | 7 | return errorMap; 8 | }; 9 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:16 2 | ENV NODE_ENV development 3 | WORKDIR /usr/src/frontend 4 | 5 | COPY package.json . 6 | COPY yarn.lock . 7 | RUN yarn 8 | COPY . . 9 | 10 | RUN yarn build 11 | 12 | 13 | EXPOSE 3000 14 | CMD ["yarn", "start"] -------------------------------------------------------------------------------- /src/graphql/mutation/deleteJournal.js: -------------------------------------------------------------------------------- 1 | import { gql } from '@apollo/client'; 2 | 3 | const DELETE_JOURNAL = gql` 4 | mutation DeleteJournal($issnToDelete: String!) { 5 | deleteJournal(issnToDelete: $issnToDelete) 6 | } 7 | `; 8 | 9 | export default DELETE_JOURNAL; 10 | -------------------------------------------------------------------------------- /src/components/marginals/Loader/Spinner.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import './Spinner.css'; 4 | 5 | function Spinner() { 6 | return ( 7 |
8 |
9 |
10 | ); 11 | } 12 | 13 | export default Spinner; 14 | -------------------------------------------------------------------------------- /src/graphql/queries/GET_USER.js: -------------------------------------------------------------------------------- 1 | import { gql } from '@apollo/client'; 2 | 3 | const GET_USER = gql` 4 | query GetCurrentUser { 5 | getCurrentUser { 6 | id 7 | fullName 8 | username 9 | email 10 | role 11 | createdAt 12 | updatedAt 13 | } 14 | } 15 | `; 16 | 17 | export default GET_USER; 18 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 100, 3 | "trailingComma": "all", 4 | "tabWidth": 2, 5 | "semi": true, 6 | "singleQuote": true, 7 | "arrowParens": "always", 8 | "bracketSpacing": true, 9 | "endOfLine": "auto", 10 | "proseWrap": "preserve", 11 | "quoteProps": "as-needed", 12 | "jsxBracketSameLine": false, 13 | "jsxSingleQuote": true 14 | } 15 | -------------------------------------------------------------------------------- /src/config/content/index.js: -------------------------------------------------------------------------------- 1 | // Landing Page 2 | export { default as landingpage } from './landingpage'; 3 | // Footer 4 | export { default as footer } from './footer'; 5 | // Manifesto 6 | export { default as manifesto } from './manifesto'; 7 | // Navbar 8 | export { default as navbar } from './navbar'; 9 | // Signup 10 | export { default as signup } from './signup'; 11 | -------------------------------------------------------------------------------- /src/graphql/mutation/login.js: -------------------------------------------------------------------------------- 1 | import { gql } from '@apollo/client'; 2 | 3 | const LOGIN = gql` 4 | mutation Login($userInfo: LoginInput!) { 5 | login(userInfo: $userInfo) { 6 | errors { 7 | field 8 | message 9 | } 10 | user { 11 | email 12 | fullName 13 | id 14 | username 15 | } 16 | } 17 | } 18 | `; 19 | 20 | export default LOGIN; 21 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import { BrowserRouter as Router, Route } from 'react-router-dom'; 5 | import App from './App'; 6 | 7 | ReactDOM.render( 8 | 9 | 10 | 11 | 12 | , 13 | document.getElementById('root'), 14 | ); 15 | -------------------------------------------------------------------------------- /src/graphql/mutation/register.js: -------------------------------------------------------------------------------- 1 | import { gql } from '@apollo/client'; 2 | 3 | const REGISTER = gql` 4 | mutation Register($userInfo: RegisterInput!) { 5 | register(userInfo: $userInfo) { 6 | errors { 7 | field 8 | message 9 | } 10 | user { 11 | id 12 | fullName 13 | username 14 | email 15 | createdAt 16 | updatedAt 17 | } 18 | } 19 | } 20 | `; 21 | 22 | export default REGISTER; 23 | -------------------------------------------------------------------------------- /src/components/marginals/shared/Layout.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable arrow-body-style */ 2 | /* eslint-disable react/function-component-definition */ 3 | import React from 'react'; 4 | import styled from 'styled-components'; 5 | import Navbar from '../Navbar/Navbar'; 6 | 7 | const Layout = styled.div` 8 | position: relative; 9 | width: full; 10 | `; 11 | 12 | export default ({ children }) => { 13 | return ( 14 | 15 | 16 | {children} 17 | 18 | ); 19 | }; 20 | -------------------------------------------------------------------------------- /src/components/marginals/shared/SectionLayout.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from 'styled-components'; 3 | 4 | const SectionContainer = styled.div` 5 | min-height: 100vh; 6 | padding-top: 3rem; 7 | padding-bottom: 5rem; 8 | background-color: #efeff0; 9 | overflow-x: hidden; 10 | overflow-y: hidden; 11 | height: auto; 12 | `; 13 | 14 | function Section({ children }) { 15 | return {children}; 16 | } 17 | 18 | export default Section; 19 | -------------------------------------------------------------------------------- /src/components/Authentication/FormSuccess.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable arrow-body-style */ 2 | /* eslint-disable jsx-a11y/img-redundant-alt */ 3 | /* eslint-disable react/function-component-definition */ 4 | import React from 'react'; 5 | 6 | const FormSuccess = () => { 7 | return ( 8 |
9 |

We have received your request!

10 | success-image 11 |
12 | ); 13 | }; 14 | 15 | export default FormSuccess; 16 | -------------------------------------------------------------------------------- /src/components/index.js: -------------------------------------------------------------------------------- 1 | export * from './marginals'; 2 | 3 | export { default as AddJournal } from './AddJournal/AddJournal'; 4 | export { default as Auth } from './Authentication/Signup/Form'; 5 | export { default as Login } from './Authentication/Login/LoginForm'; 6 | export { default as Header } from './Landing/Header/Header'; 7 | export { default as LandingSection } from './Landing/LandingSection/LandingSection'; 8 | export { default as Journals } from './Journals/Journal'; 9 | export { default as JournalDetails } from './JournalDetails/Details'; 10 | -------------------------------------------------------------------------------- /src/components/Journals/Journal.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | /* eslint-disable arrow-body-style */ 3 | /* eslint-disable react/function-component-definition */ 4 | import React from 'react'; 5 | import JournalList from './JournalList'; 6 | import { JContainer, Head, Container } from './styles'; 7 | 8 | const Journal = () => { 9 | return ( 10 | 11 | 12 | Journals 13 | 14 | 15 | 16 | ); 17 | }; 18 | 19 | export default Journal; 20 | -------------------------------------------------------------------------------- /src/components/marginals/index.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/no-cycle */ 2 | 3 | export { default as Footer } from './Footer/Footer'; 4 | export { default as Navbar } from './Navbar/Navbar'; 5 | export { default as SearchBar } from './Search/Search'; 6 | export { default as Layout } from './shared/Layout'; 7 | export { default as SectionLayout } from './shared/SectionLayout'; 8 | export { default as PolicyContainer } from './shared/PolicyContainer'; 9 | export { default as Error } from './Error/Error'; 10 | export { default as Loader } from './Loader/Spinner'; 11 | -------------------------------------------------------------------------------- /src/graphql/queries/getAllJournals.js: -------------------------------------------------------------------------------- 1 | import { gql } from '@apollo/client'; 2 | 3 | const GET_ALL_JOURNALS = gql` 4 | query GetAllJournals($currentPageNumber: Int!, $limitValue: Int!) { 5 | getAllJournals(currentPageNumber: $currentPageNumber, limitValue: $limitValue) { 6 | journals { 7 | id 8 | title 9 | url 10 | issn 11 | domainName 12 | createdAt 13 | updatedAt 14 | createdBy 15 | } 16 | totalJournals 17 | } 18 | } 19 | `; 20 | 21 | export default GET_ALL_JOURNALS; 22 | -------------------------------------------------------------------------------- /src/components/Authentication/Login/validateLoginInfo.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable prefer-const */ 2 | export default function validateLoginInfo(values) { 3 | let errors = {}; 4 | 5 | if (!values.email) { 6 | errors.email = 'Email required'; 7 | } else if (!/\S+@\S+\.\S+/.test(values.email)) { 8 | errors.email = 'Email address is invalid'; 9 | } 10 | 11 | if (!values.password) { 12 | errors.password = 'Password required'; 13 | } else if (values.password.length < 6) { 14 | errors.password = 'Password needs to be 6 characters or more'; 15 | } 16 | 17 | return errors; 18 | } 19 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /src/components/Authentication/User-Profile/Logout.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | /* eslint-disable react/button-has-type */ 3 | import React from 'react'; 4 | import { useMutation } from '@apollo/client'; 5 | import LOGOUT from '../../../graphql/mutation/LOGOUT'; 6 | 7 | function Logout() { 8 | const [logout, { data, error }] = useMutation(LOGOUT); 9 | 10 | const handlelogout = async (event) => { 11 | logout({}); 12 | }; 13 | 14 | return ( 15 | <> 16 |
Logout
17 | 18 | 19 | ); 20 | } 21 | 22 | export default Logout; 23 | -------------------------------------------------------------------------------- /src/context/types.js: -------------------------------------------------------------------------------- 1 | export const SEARCH_RESULTS = 'SEARCH_RESULTS'; 2 | export const SEARCH = 'SEARCH'; 3 | export const CURRENT_PAGE = 'CURRENT_PAGE'; 4 | export const POSTS = 'POSTS'; 5 | export const SET_TITLE = 'SET_TITLE'; 6 | export const SET_TOPIC = 'SET_TOPIC'; 7 | export const SET_ISSN = 'SET_ISSN'; 8 | export const SET_LINK = 'SET_LINK'; 9 | export const SET_POLICY = 'SET_POLICY'; 10 | export const SET_DATAAVAIL = 'SET_DATAAVAIL'; 11 | export const SET_DATASHARED = 'SET_DATASHARED'; 12 | export const SET_PEERREVIEW = 'SET_PEERREVIEW'; 13 | export const SET_ENFORCED = 'SET_ENFORCED'; 14 | export const SET_EVIDENCE = 'SET_EVIDENCE'; 15 | export const POLICYTITLE = 'POLICYTITLE'; 16 | -------------------------------------------------------------------------------- /src/components/marginals/Loader/Spinner.css: -------------------------------------------------------------------------------- 1 | .spinner { 2 | display: flex; 3 | justify-content: center; 4 | align-items: center; 5 | } 6 | 7 | .lds-dual-ring { 8 | display: inline-block; 9 | width: 64px; 10 | height: 64px; 11 | } 12 | .lds-dual-ring:after { 13 | content: ' '; 14 | display: block; 15 | width: 46px; 16 | height: 46px; 17 | margin: 1px; 18 | border-radius: 50%; 19 | border: 5px solid #5101d1; 20 | border-color: #5101d1 transparent #5101d1 transparent; 21 | animation: lds-dual-ring 1.2s linear infinite; 22 | } 23 | @keyframes lds-dual-ring { 24 | 0% { 25 | transform: rotate(0deg); 26 | } 27 | 100% { 28 | transform: rotate(360deg); 29 | } 30 | } -------------------------------------------------------------------------------- /src/graphql/queries/getFullJournalByISSN.js: -------------------------------------------------------------------------------- 1 | import { gql } from '@apollo/client'; 2 | 3 | const GET_ALL_JOURNAL_DETAILS = gql` 4 | query GetJournalByISSN($issn: String!) { 5 | getJournalByISSN(issn: $issn) { 6 | id 7 | title 8 | url 9 | issn 10 | domainName 11 | policies { 12 | title 13 | firstYear 14 | lastYear 15 | policyType 16 | isDataAvailabilityStatementPublished 17 | isDataShared 18 | isDataPeerReviewed 19 | enforced 20 | enforcedEvidence 21 | } 22 | createdAt 23 | updatedAt 24 | createdBy 25 | } 26 | } 27 | `; 28 | 29 | export default GET_ALL_JOURNAL_DETAILS; 30 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | --- 8 | 9 | Thank you for taking the time to file a Feature Request report. 10 | 11 | **Is your feature request related to a problem? Please describe.** 12 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 13 | 14 | **Describe the solution you'd like** 15 | A clear and concise description of what you want to happen. 16 | 17 | **Describe alternatives you've considered** 18 | A clear and concise description of any alternative solutions or features you've considered. 19 | 20 | **Additional context** 21 | Add any other context or screenshots about the feature request here. 22 | -------------------------------------------------------------------------------- /src/graphql/mutation/createJournal.js: -------------------------------------------------------------------------------- 1 | import { gql } from '@apollo/client'; 2 | 3 | const CREATE_JOURNAL = gql` 4 | mutation CreateJournal($journalToCreate: JournalInput!) { 5 | createJournal(journalToCreate: $journalToCreate) { 6 | journal { 7 | id 8 | title 9 | url 10 | issn 11 | domainName 12 | policies { 13 | title 14 | firstYear 15 | lastYear 16 | policyType 17 | isDataAvailabilityStatementPublished 18 | isDataShared 19 | isDataPeerReviewed 20 | enforced 21 | enforcedEvidence 22 | } 23 | createdAt 24 | updatedAt 25 | createdBy 26 | } 27 | } 28 | } 29 | `; 30 | 31 | export default CREATE_JOURNAL; 32 | -------------------------------------------------------------------------------- /src/graphql/mutation/updateJournal.js: -------------------------------------------------------------------------------- 1 | import { gql } from '@apollo/client'; 2 | 3 | const UPDATE_JOURNAL = gql` 4 | mutation UpdateJournal($issnToUpdate: String!, $newJournalDetails: JournalInput!) { 5 | updateJournal(issnToUpdate: $issnToUpdate, newJournalDetails: $newJournalDetails) { 6 | journal { 7 | id 8 | title 9 | url 10 | issn 11 | domainName 12 | createdAt 13 | updatedAt 14 | createdBy 15 | policies { 16 | title 17 | firstYear 18 | lastYear 19 | policyType 20 | isDataAvailabilityStatementPublished 21 | isDataShared 22 | isDataPeerReviewed 23 | enforced 24 | enforcedEvidence 25 | } 26 | } 27 | } 28 | } 29 | `; 30 | 31 | export default UPDATE_JOURNAL; 32 | -------------------------------------------------------------------------------- /src/config/content/signup.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable max-len */ 2 | export default { 3 | head: 'Welcome to Code Is Science', 4 | head2: 'Welcome back, please log in to your account', 5 | labelUsername: 'Enter your username', 6 | labelEmail: 'Enter your email', 7 | labelPassword: 'Enter your password', 8 | labelPassword2: 'Confirm your password', 9 | button: 'Sign Up', 10 | buttonLogin: 'Login', 11 | login: 'Already have an account? Login', 12 | logo: { 13 | src: 'https://res.cloudinary.com/dh6j2zoog/image/upload/v1655702059/CiS/logo_ch4fzv.png', 14 | alt: 'Form Image', 15 | }, 16 | img: { 17 | src: 'https://res.cloudinary.com/dh6j2zoog/image/upload/v1656711379/CiS/branding-and-marketing-for-product-of-startup-business_wdzfmj.png', 18 | alt: 'spaceship', 19 | }, 20 | formHead: 'Scientific Code Should Be Open', 21 | }; 22 | -------------------------------------------------------------------------------- /.github/workflows/docker-image.yml: -------------------------------------------------------------------------------- 1 | name: Docker Image CI 2 | 3 | on: 4 | push: 5 | branches: [ "development" ] 6 | pull_request: 7 | branches: [ "development" ] 8 | 9 | jobs: 10 | 11 | build: 12 | 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - uses: actions/checkout@v3 17 | - name: DockerHub Login 18 | env: 19 | DOCKER_USER: ${{ secrets.DOCKER_USERNAME_PADMAJA }} 20 | DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD_PADMAJA }} 21 | run: | 22 | docker login -u $DOCKER_USER -p $DOCKER_PASSWORD 23 | 24 | - name: Build the Docker Image 25 | run: docker build -t codeisscience/journal-policy-tracker-frontend:$(date +%d.%b.%Y_%a_%H) . 26 | 27 | - name: Push the Docker Image to DockerHub 28 | run: docker push codeisscience/journal-policy-tracker-frontend:$(date +%d.%b.%Y_%a_%H) 29 | -------------------------------------------------------------------------------- /src/components/marginals/shared/PolicyContainer.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable arrow-body-style */ 2 | /* eslint-disable react/function-component-definition */ 3 | import React from 'react'; 4 | import styled from 'styled-components'; 5 | 6 | const PolicyContainer = styled.div` 7 | width: 65%; 8 | margin: 0px auto 0px auto; 9 | background-color: #ffff; 10 | padding: 2rem 3rem; 11 | border: 5px; 12 | border-radius: 8px; 13 | align-self: center; 14 | justify-self: center; 15 | @media (max-width: 1300px) { 16 | width: 78%; 17 | padding: 2rem 4rem; 18 | } 19 | @media (max-width: 800px) { 20 | width: 85%; 21 | padding: 1.4rem 2rem; 22 | } 23 | @media (max-width: 600px) { 24 | width: 88%; 25 | padding: 1.5rem 1.5rem; 26 | } 27 | `; 28 | 29 | export default ({ children }) => { 30 | return {children}; 31 | }; 32 | -------------------------------------------------------------------------------- /src/components/Authentication/Signup/validateInfo.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable prefer-const */ 2 | export default function validateInfo(values) { 3 | let errors = {}; 4 | 5 | if (!values.username.trim()) { 6 | errors.username = 'Username required'; 7 | } 8 | 9 | if (!values.email) { 10 | errors.email = 'Email required'; 11 | } else if (!/\S+@\S+\.\S+/.test(values.email)) { 12 | errors.email = 'Email address is invalid'; 13 | } 14 | 15 | if (!values.password) { 16 | errors.password = 'Password required'; 17 | } else if (values.password.length < 6) { 18 | errors.password = 'Password needs to be 6 characters or more'; 19 | } 20 | 21 | if (!values.password2) { 22 | errors.password2 = 'Password is required'; 23 | } else if (values.password2 !== values.password) { 24 | errors.password2 = 'Passwords do not match'; 25 | } 26 | 27 | return errors; 28 | } 29 | -------------------------------------------------------------------------------- /src/pages/Home.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Header, LandingSection } from '../components'; 3 | import '../components/Landing/Header/Header.css'; 4 | import { useGlobalContext } from '../context/DataContext'; 5 | 6 | function Home() { 7 | const { 8 | search, 9 | searchResults, 10 | setSearch, 11 | posts, 12 | filteredData, 13 | setFilteredData, 14 | wordEntered, 15 | setWordEntered, 16 | handleFilter, 17 | } = useGlobalContext(); 18 | return ( 19 |
20 |
31 | 32 |
33 | ); 34 | } 35 | 36 | export default Home; 37 | -------------------------------------------------------------------------------- /src/components/Pagination/Pagination.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable jsx-a11y/click-events-have-key-events */ 2 | /* eslint-disable jsx-a11y/no-static-element-interactions */ 3 | /* eslint-disable jsx-a11y/anchor-is-valid */ 4 | /* eslint-disable no-plusplus */ 5 | /* eslint-disable react/function-component-definition */ 6 | import React from 'react'; 7 | 8 | const Pagination = ({ postsPerPage, totalPosts, paginate }) => { 9 | const pageNumbers = []; 10 | 11 | for (let i = 1; i <= Math.ceil(totalPosts / postsPerPage); i++) { 12 | pageNumbers.push(i); 13 | } 14 | 15 | return ( 16 | 27 | ); 28 | }; 29 | 30 | export default Pagination; 31 | -------------------------------------------------------------------------------- /src/components/Landing/Header/Header.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | import React from 'react'; 3 | import './Header.css'; 4 | import { Button, Jumbotron } from 'react-bootstrap'; 5 | import Container from 'react-bootstrap/Container'; 6 | import { Link } from 'react-router-dom'; 7 | import { SearchBar } from '../../marginals'; 8 | 9 | function Header({ 10 | posts, 11 | filteredData, 12 | setFilteredData, 13 | wordEntered, 14 | setWordEntered, 15 | handleFilter, 16 | }) { 17 | return ( 18 |
19 | 20 | {/* */} 28 | 29 | 30 | 31 | 32 |
33 | ); 34 | } 35 | 36 | export default Header; 37 | -------------------------------------------------------------------------------- /src/pages/Journal/Journal.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | /* eslint-disable arrow-body-style */ 3 | /* eslint-disable react/function-component-definition */ 4 | import React, { useReducer } from 'react'; 5 | import { useQuery } from '@apollo/client'; 6 | import { Journals } from '../../components'; 7 | import { Container } from '../../components/Journals/styles'; 8 | import GET_ALL_JOURNALS from '../../graphql/queries/getAllJournals'; 9 | import reducer from '../../context/reducer'; 10 | 11 | const Journal = () => { 12 | const initialState = { 13 | currentPage: 1, 14 | postsPerPage: 5, 15 | }; 16 | 17 | const [state] = useReducer(reducer, initialState); 18 | 19 | const { loading } = useQuery(GET_ALL_JOURNALS, { 20 | variables: { currentPageNumber: state.currentPage, limitValue: state.postsPerPage }, 21 | fetchPolicy: 'network-only', 22 | }); 23 | 24 | if (loading) { 25 | return

loading...

; 26 | } 27 | return ( 28 | 29 | 30 | 31 | ); 32 | }; 33 | 34 | export default Journal; 35 | -------------------------------------------------------------------------------- /src/components/Authentication/User-Profile/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const Heading = styled.h1` 4 | font-size: 1.8rem; 5 | color: #ec8d20; 6 | `; 7 | 8 | export const Card = styled.h1` 9 | box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2); 10 | max-width: 500px; 11 | margin: auto; 12 | margin-top: 20px; 13 | text-align: center; 14 | font-family: arial; 15 | padding: 2rem; 16 | `; 17 | 18 | export const Title = styled.p` 19 | color: grey; 20 | font-size: 18px; 21 | `; 22 | export const H1 = styled.h1` 23 | color: grey; 24 | font-size: 1.3rem; 25 | `; 26 | 27 | export const ButtonLogout = styled.button` 28 | border: none; 29 | outline: 0; 30 | display: inline-block; 31 | padding: 8px; 32 | color: white; 33 | background-color: #000; 34 | text-align: center; 35 | cursor: pointer; 36 | width: 100%; 37 | font-size: 18px; 38 | `; 39 | 40 | // a { 41 | // text-decoration: none; 42 | // /* font-size: 22px; */ 43 | // color: black; 44 | // } 45 | 46 | // button:hover, a:hover { 47 | // opacity: 0.7; 48 | // } 49 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | --- 8 | 9 | Thank you for taking the time to file a Bug report. 10 | 11 | **Describe the bug** 12 | A clear and concise description of what the bug is. 13 | 14 | **To Reproduce** 15 | Steps to reproduce the behavior: 16 | 17 | 1. Go to '...' 18 | 2. Click on '....' 19 | 3. Scroll down to '....' 20 | 4. See error 21 | 22 | **Expected behavior** 23 | A clear and concise description of what you expected to happen. 24 | 25 | **Screenshots** 26 | If applicable, add screenshots to help explain your problem. 27 | 28 | **Desktop (please complete the following information):** 29 | 30 | - OS: [e.g. iOS] 31 | - Browser [e.g. chrome, safari] 32 | - Version [e.g. 22] 33 | 34 | **Smartphone (please complete the following information):** 35 | 36 | - Device: [e.g. iPhone6] 37 | - OS: [e.g. iOS8.1] 38 | - Browser [e.g. stock browser, safari] 39 | - Version [e.g. 22] 40 | 41 | **Additional context** 42 | Add any other context about the problem here. 43 | -------------------------------------------------------------------------------- /src/components/marginals/Search/Search.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable arrow-body-style */ 2 | /* eslint-disable jsx-a11y/anchor-is-valid */ 3 | /* eslint-disable react/jsx-key */ 4 | /* eslint-disable no-unused-vars */ 5 | import React, { useState } from 'react'; 6 | // import { FiSearch } from 'react-icons/fi'; 7 | import { Link } from 'react-router-dom'; 8 | import '../../../index.css'; 9 | 10 | function SearchBar({ 11 | posts, 12 | filteredData, 13 | setFilteredData, 14 | wordEntered, 15 | setWordEntered, 16 | handleFilter, 17 | }) { 18 | return ( 19 |
20 |
21 | 22 |
23 | 24 | {filteredData.length !== 0 && ( 25 |
26 | {filteredData.map((value, key) => ( 27 | 28 |

{value.title}

29 | 30 | ))} 31 |
32 | )} 33 |
34 | ); 35 | } 36 | 37 | export default SearchBar; 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Code is Science 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/components/Authentication/Signup/Form.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable max-len */ 2 | /* eslint-disable import/extensions */ 3 | /* eslint-disable react/jsx-no-bind */ 4 | /* eslint-disable react/function-component-definition */ 5 | /* eslint-disable react/jsx-no-useless-fragment */ 6 | import React, { useState } from 'react'; 7 | import FormSignup from './SignUp'; 8 | import FormSuccess from '../FormSuccess'; 9 | import { FormContainer, FormContentLeft, FormImg, RightH2, Logo } from '../styles.js'; 10 | import { signup } from '../../../config/content'; 11 | 12 | const Form = () => { 13 | const [isSubmitted, setIsSubmitted] = useState(false); 14 | 15 | function submitForm() { 16 | setIsSubmitted(true); 17 | } 18 | return ( 19 | <> 20 | 21 | {!isSubmitted ? : } 22 | 23 | 24 | {signup.formHead} 25 | 26 | 27 | 28 | 29 | ); 30 | }; 31 | 32 | export default Form; 33 | -------------------------------------------------------------------------------- /src/components/Authentication/Login/LoginForm.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable max-len */ 2 | /* eslint-disable import/extensions */ 3 | /* eslint-disable react/jsx-no-bind */ 4 | /* eslint-disable react/function-component-definition */ 5 | /* eslint-disable react/jsx-no-useless-fragment */ 6 | import React, { useState } from 'react'; 7 | import FormLogin from './Login'; 8 | import FormSuccess from '../FormSuccess'; 9 | import { FormContainer, FormContentLeft, FormImg, RightH2, Logo } from '../styles'; 10 | import { signup } from '../../../config/content'; 11 | 12 | const LoginForm = () => { 13 | const [isSubmitted, setIsSubmitted] = useState(false); 14 | 15 | function submitForm() { 16 | setIsSubmitted(true); 17 | } 18 | return ( 19 | <> 20 | 21 | {!isSubmitted ? : } 22 | 23 | 24 | {signup.formHead} 25 | 26 | 27 | 28 | 29 | ); 30 | }; 31 | 32 | export default LoginForm; 33 | -------------------------------------------------------------------------------- /src/components/Journals/useFetch.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | /* eslint-disable arrow-body-style */ 3 | import { useState, useEffect } from 'react'; 4 | 5 | const useFetch = (url) => { 6 | const [journalFetch, setJournalFetch] = useState(null); 7 | const [isPending, setIsPending] = useState(true); 8 | const [error, setError] = useState(null); 9 | 10 | useEffect(() => { 11 | const abortCont = new AbortController(); 12 | 13 | fetch(url, { signal: abortCont.signal }) 14 | .then((res) => { 15 | if (!res.ok) { 16 | throw Error('could not fetch the data for that resource'); 17 | } 18 | return res.json(); 19 | }) 20 | .then((data) => { 21 | setJournalFetch(data); 22 | setIsPending(false); 23 | setError(null); 24 | }) 25 | .catch((err) => { 26 | if (err.name === 'AbortError') { 27 | console.log('fetch aborted'); 28 | } else { 29 | setError(err.message); 30 | setIsPending(false); 31 | } 32 | }); 33 | 34 | return () => abortCont.abort(); 35 | }, [url]); 36 | 37 | return { journalFetch, isPending, error }; 38 | }; 39 | 40 | export default useFetch; 41 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "extends": ["airbnb", "airbnb/hooks", "plugin:react/recommended", "prettier"], 4 | "plugins": ["react", "prettier"], 5 | "env": { 6 | "browser": true, 7 | "jest": true, 8 | "node": true, 9 | "es6": true 10 | }, 11 | "globals": { 12 | "Atomics": "readonly", 13 | "SharedBufferArray": "readonly" 14 | }, 15 | "parser": "@babel/eslint-parser", 16 | "parserOptions": { 17 | "ecmaVersion": 2020, 18 | "sourceType": "module", 19 | "ecmaFeatures": { "jsx": true }, 20 | "allowImportExportEverywhere": false, 21 | "codeFrame": false 22 | }, 23 | "settings": { 24 | "react": { 25 | "pragma": "React", 26 | "version": "detect" 27 | } 28 | }, 29 | "rules": { 30 | "max-len": ["error", { "code": 100 }], 31 | "prefer-promise-reject-errors": ["off"], 32 | "react/jsx-filename-extension": ["off"], 33 | "no-return-assign": ["off"], 34 | "react/prop-types": 0, 35 | "import/prefer-default-export": 0, 36 | "no-use-before-define": 0, 37 | "click-events-have-key-events": 0, 38 | "no-static-element-interactions": 0, 39 | "prefer-destructuring": 1, 40 | "react/display-name": 0, 41 | "func-names": 0 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/config/content/navbar.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable max-len */ 2 | import { faBars, faXmark } from '@fortawesome/free-solid-svg-icons'; 3 | 4 | export default { 5 | title: 'Navbar', 6 | logo: { 7 | src: 'https://res.cloudinary.com/dh6j2zoog/image/upload/v1662665526/CiS/code-is-science-model-2-light_zaohia.png', 8 | alt: 'Code Is Science', 9 | }, 10 | icon: faBars, 11 | icon2: faXmark, 12 | navItems: [ 13 | { 14 | id: 'home', 15 | name: 'Home', 16 | link: '/home', 17 | }, 18 | { 19 | id: 'journal', 20 | name: 'Journals', 21 | link: '/journal', 22 | }, 23 | { 24 | id: 'addjournal', 25 | name: 'Add Journal', 26 | link: '/addjournal', 27 | }, 28 | { 29 | id: 'profile', 30 | name: 'Profile', 31 | link: '/profile', 32 | }, 33 | // { 34 | // id: 'manifesto', 35 | // name: 'Manifesto', 36 | // link: '/manifesto', 37 | // }, 38 | // { 39 | // id: 'contact', 40 | // name: 'Contact', 41 | // link: '/contact', 42 | // }, 43 | { 44 | id: 'signup', 45 | name: 'Signup', 46 | link: '/signup', 47 | }, 48 | { 49 | id: 'login', 50 | name: null, 51 | link: '/login', 52 | }, 53 | { 54 | id: 'policy', 55 | name: null, 56 | link: '/policy/:id', 57 | }, 58 | ], 59 | }; 60 | -------------------------------------------------------------------------------- /src/components/marginals/Navbar/Navbar.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | 3 | // Libraries 4 | import { Link } from 'react-router-dom'; 5 | import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; 6 | 7 | // Assets 8 | import { navbar } from '../../../config/content'; 9 | 10 | // Styles 11 | import { Nav, Logo, Menu, Button, Items } from './styles'; 12 | 13 | function Navbar() { 14 | // const { search, setSearch } = useGlobalContext(); 15 | const [isOpen, setIsOpen] = useState(false); 16 | 17 | return ( 18 | 43 | ); 44 | } 45 | 46 | export default Navbar; 47 | -------------------------------------------------------------------------------- /src/pages/Manifesto/Manifesto.css: -------------------------------------------------------------------------------- 1 | .manifesto { 2 | text-align: center; 3 | padding: 5em; 4 | color: #3d9dd9; 5 | } 6 | 7 | .manifesto h1 { 8 | font-size: 4em; 9 | } 10 | 11 | .manifesto-header { 12 | margin-bottom: 5em; 13 | display : flex; 14 | align-items: center; 15 | } 16 | .manifesto-padding{ 17 | padding-top: 8.7em; 18 | } 19 | .manifesto-section-one h1, 20 | h1 { 21 | color: #3d9dd9; 22 | } 23 | 24 | .manifesto-text { 25 | font-size: 1.4em; 26 | } 27 | 28 | .manifesto-support { 29 | margin : 10px; 30 | display: flex; 31 | justify-content: center; 32 | } 33 | 34 | .manifesto-support h1 { 35 | text-align: center; 36 | margin : 15px; 37 | } 38 | 39 | .manifesto-support p, 40 | img { 41 | padding-top: 1em; 42 | padding-bottom: 1em; 43 | } 44 | 45 | .manifesto-support img { 46 | margin: 1em auto; 47 | } 48 | 49 | .manifesto-support-points { 50 | display: flex; 51 | flex-direction: column; 52 | align-items: center; 53 | justify-content: flex-start; 54 | background-color: aliceblue; 55 | border-radius: 20px; 56 | margin: 20px; 57 | } 58 | 59 | .manifesto-contact a { 60 | display: block; 61 | text-decoration: none; 62 | margin: 10px; 63 | } 64 | 65 | .manifesto-contribute { 66 | display: flex; 67 | justify-content : center; 68 | padding : 30px; 69 | margin : 0px auto; 70 | } 71 | 72 | .manifesto-contribute li { 73 | line-height: 25px; 74 | } 75 | 76 | @media only screen and (max-width: 768px){ 77 | .manifesto{ 78 | padding:0px; 79 | } 80 | .manifesto-header { 81 | margin-bottom: 0; 82 | } 83 | .manifesto-header .imgContainer{ 84 | display: none; 85 | } 86 | } -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Poppins&display=swap'); 2 | 3 | * { 4 | box-sizing: border-box; 5 | margin: 0; 6 | padding-top: 1px; 7 | font-family: 'Poppins', sans-serif; 8 | } 9 | 10 | html, 11 | body { 12 | max-width: 100vw; 13 | min-height: 100vh; 14 | } 15 | 16 | .App { 17 | width: 100%; 18 | height: 100vh; 19 | } 20 | 21 | .container{ 22 | position: relative; 23 | } 24 | 25 | .searchInputs { 26 | margin-top: 105px; 27 | display: flex; 28 | } 29 | 30 | .search input { 31 | background-color: white; 32 | border: 0; 33 | border-radius: 2px; 34 | border-top-right-radius: 0px; 35 | border-bottom-right-radius: 0px; 36 | font-size: 18px; 37 | padding: 15px; 38 | height: 30px; 39 | width: 80%; 40 | margin: 0px auto 0px auto; 41 | } 42 | 43 | .searchIcon { 44 | height: 60px; 45 | width: 50px; 46 | background-color: white; 47 | display: grid; 48 | place-items: center; 49 | } 50 | 51 | input:focus { 52 | outline: none; 53 | } 54 | .searchIcon svg { 55 | font-size: 35px; 56 | } 57 | 58 | .dataResult { 59 | margin-top: 5px; 60 | width: 100%; 61 | height: 200px; 62 | background-color: white; 63 | box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px; 64 | overflow: hidden; 65 | overflow-y: auto; 66 | } 67 | 68 | .dataResult::-webkit-scrollbar { 69 | display: none; 70 | } 71 | 72 | .dataResult .dataItem { 73 | width: 100%; 74 | height: 50px; 75 | display: flex; 76 | align-items: center; 77 | color: black; 78 | } 79 | 80 | .dataItem p { 81 | margin-left: 10px; 82 | } 83 | a { 84 | text-decoration: none; 85 | } 86 | a:link { text-decoration: none; } 87 | 88 | #clearBtn { 89 | cursor: pointer; 90 | } 91 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | # Pull Request Template 2 | 3 | ## Description 4 | 5 | Please include a summary of the change. Please also include relevant motivation and context. List any dependencies that are required for this change. 6 | 7 | Fixes # (issue) 8 | 9 | ## Type of change 10 | 11 | Please delete options that are not relevant. 12 | 13 | - [ ] Bug fix (non-breaking change which fixes an issue). 14 | - [ ] New feature (non-breaking change which adds functionality). 15 | - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected). 16 | - [ ] This change requires a documentation update. 17 | 18 | ## How Has This Been Tested? 19 | 20 | Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration 21 | 22 | ## Additional Context (Please include any Screenshots/gifs if relevant) 23 | 24 | ... 25 | 26 | ## Checklist: 27 | 28 | - [ ] My code follows the style guidelines of this project. 29 | - [ ] I have performed a self-review of my own code. 30 | - [ ] I have made corresponding changes to the documentation. 31 | - [ ] I have added corresponding tests. 32 | - [ ] Any dependent changes have been merged and published in downstream modules. 33 | - [ ] I have signed the commit message to agree to Developer Certificate of Origin (DCO) (to certify that you wrote or otherwise have the right to submit your contribution to the project.) by adding "--signoff" to my git commit command. 34 | 35 | 36 | -------------------------------------------------------------------------------- /src/components/Landing/LandingSection/LandingSection.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable max-len */ 2 | import React from 'react'; 3 | 4 | // Assets 5 | import { landingpage } from '../../../config/content'; 6 | 7 | // Styles 8 | import { 9 | SectionOne, 10 | CardContainer, 11 | Card, 12 | ImageHeader, 13 | Para1, 14 | SectionTwo, 15 | Div2, 16 | Div3, 17 | Para, 18 | Image2, 19 | SectionOH1, 20 | SectionTH2, 21 | SectionOH2, 22 | Para2, 23 | } from './styles'; 24 | 25 | function LandingSection() { 26 | return ( 27 | <> 28 | 29 | {landingpage.section1.head} 30 | 31 | {landingpage.section1.content.map(({ id, subhead, para, link }) => ( 32 | 33 | 34 | {subhead} 35 | {para} 36 | 37 | ))} 38 | 39 | 40 | 41 | 42 | 43 | {landingpage.section2.head} 44 | {landingpage.section2.para} 45 | 46 | 47 | 48 | 49 | 50 | 51 | {landingpage.section3.head} 52 | {landingpage.section3.para} 53 | 54 | 55 | 56 | 57 | ); 58 | } 59 | 60 | export default LandingSection; 61 | -------------------------------------------------------------------------------- /src/components/marginals/Footer/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const FooterContainer = styled.div` 4 | width: 100%; 5 | left: 0; 6 | bottom: 0; 7 | text-align: center; 8 | `; 9 | 10 | export const SecondaryContainer = styled.div` 11 | display: grid; 12 | width: 100%; 13 | background-color: #16213e; 14 | justify-content: center; 15 | `; 16 | 17 | export const UpperDiv = styled.div` 18 | width: 100%; 19 | display: grid; 20 | grid-template-columns: repeat(4, minmax(100px, 1fr)); 21 | padding-top: 2rem; 22 | gap: 8rem; 23 | @media (max-width: 990px) { 24 | grid-template-columns: repeat(2, minmax(100px, 1fr)); 25 | gap: 1.5rem 10rem; 26 | } 27 | @media (max-width: 484px) { 28 | grid-template-columns: repeat(1, minmax(100px, 1fr)); 29 | gap: 1.5rem 10rem; 30 | } 31 | `; 32 | 33 | export const Logo = styled.img` 34 | width: 4rem; 35 | height: auto; 36 | `; 37 | 38 | export const LinksContainer = styled.div` 39 | display: flex; 40 | flex-direction: column; 41 | text-align: left; 42 | `; 43 | 44 | export const Heading2 = styled.h1` 45 | font-size: 1.3rem; 46 | margin-bottom: 1rem; 47 | color: #e8e9ea; 48 | `; 49 | 50 | export const NoStyleNav = styled.a` 51 | no-underline 52 | mt-2 53 | `; 54 | 55 | export const Heading3 = styled.p` 56 | font-size: 0.875rem; 57 | color: #bdc3c7; 58 | margin-bottom: 0.5rem; 59 | `; 60 | 61 | export const SocialDiv = styled.div` 62 | display: flex; 63 | gap: 5px; 64 | `; 65 | 66 | export const SocialLogo = styled.img` 67 | width: 100%; 68 | `; 69 | 70 | export const LowerDiv = styled.div` 71 | background: #16213e; 72 | color: #fff; 73 | text-align: center; 74 | padding: 3rem 0rem 3rem 0; 75 | `; 76 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 15 | 16 | 25 | Code is Science 26 | 27 | 28 | 29 | 30 |
31 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /src/components/marginals/Error/error.css: -------------------------------------------------------------------------------- 1 | .fundo{ 2 | animation: scales 3s alternate infinite; 3 | transform-origin: center; 4 | } 5 | .pao-baixo{ 6 | animation: rotatepao 14s cubic-bezier(.1,.49,.41,.97) infinite; 7 | transform-origin: center; 8 | } 9 | .pao-cima{ 10 | animation: rotatepao 7s 1s cubic-bezier(.1,.49,.41,.97) infinite; 11 | transform-origin: center; 12 | } 13 | .olhos{animation: olhos 2s alternate infinite; 14 | transform-origin: center; 15 | } 16 | 17 | .left-sparks{animation: left-sparks 4s alternate infinite; 18 | transform-origin: 150px 156px; 19 | } 20 | 21 | .right-sparks{animation: left-sparks 4s alternate infinite; 22 | transform-origin: 310px 150px; 23 | } 24 | 25 | .olhos{animation: olhos 2s alternate infinite; 26 | transform-origin: center; 27 | } 28 | @keyframes scales{ 29 | from { transform: scale(0.98)} 30 | to{ transform: scale(1)} 31 | } 32 | 33 | @keyframes rotatepao{ 34 | 0% { transform: rotate(0deg)} 35 | 50% , 60%{ transform: rotate(-20deg)} 36 | 100%{ transform: rotate(0deg) } 37 | 38 | } 39 | 40 | @keyframes olhos{ 41 | 0%{ 42 | transform: rotateX(0deg); 43 | } 44 | 100%{ 45 | transform: rotateX(30deg); 46 | } 47 | } 48 | 49 | @keyframes left-sparks{ 50 | 0%{ 51 | opacity: 0; 52 | } 53 | 54 | } 55 | 56 | 57 | .main{ 58 | 59 | min-height: 600px; 60 | margin: 0px auto; 61 | width: auto; 62 | max-width: 460px; 63 | display: flex; 64 | align-items: center; 65 | justify-content: center; 66 | } 67 | 68 | .path { 69 | stroke-dasharray: 300; 70 | stroke-dashoffset: 300; 71 | animation: dash 4s alternate infinite; 72 | } 73 | 74 | @keyframes dash{ 75 | 0%, 30%{ 76 | fill: 4B4B62; 77 | stroke-dashoffset: 0; 78 | } 79 | 80%,100%{ 80 | fill: transparent; 81 | stroke-dashoffset: -200; 82 | } 83 | 84 | 85 | } -------------------------------------------------------------------------------- /src/components/Authentication/User-Profile/useprofile.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable react/button-has-type */ 2 | /* eslint-disable jsx-a11y/anchor-is-valid */ 3 | /* eslint-disable max-len */ 4 | /* eslint-disable import/order */ 5 | /* eslint-disable jsx-a11y/alt-text */ 6 | /* eslint-disable react/self-closing-comp */ 7 | /* eslint-disable no-unused-vars */ 8 | import React, { useEffect, useState } from 'react'; 9 | import { useQuery, useMutation } from '@apollo/client'; 10 | import GET_USER from '../../../graphql/queries/GET_USER'; 11 | import Logout from './Logout'; 12 | import { SectionLayout } from '../../marginals'; 13 | import { Container } from 'react-bootstrap'; 14 | import LOGOUT from '../../../graphql/mutation/LOGOUT'; 15 | import { useHistory } from 'react-router'; 16 | import { Heading, Card, Title, ButtonLogout, H1 } from './styles'; 17 | import { FormInputBtn } from '../styles'; 18 | 19 | function Profile() { 20 | const { data } = useQuery(GET_USER); 21 | const [logout, { data1, error }] = useMutation(LOGOUT); 22 | 23 | const [user, setUser] = useState(''); 24 | 25 | const history = useHistory(); 26 | 27 | useEffect(() => { 28 | if (data) { 29 | setUser(data.getCurrentUser); 30 | } 31 | }, [setUser, data]); 32 | 33 | const handlelogout = async (event) => { 34 | logout({}); 35 | history.push('/signup'); 36 | }; 37 | 38 | return ( 39 | 40 | 41 | User Profile 42 | 43 | 44 |

Name: {user.fullName}

45 |

Username: {user.username}

46 | {user.role} 47 |

Email: {user.email}

48 | Logout 49 |
50 |
51 |
52 | ); 53 | } 54 | 55 | export default Profile; 56 | -------------------------------------------------------------------------------- /src/components/Landing/Header/Header.css: -------------------------------------------------------------------------------- 1 | .header { 2 | background-image: url('https://res.cloudinary.com/dh6j2zoog/image/upload/v1655702025/CiS/bg_jhdw6s.png'); 3 | height: 550px; 4 | background-size: 150vw; 5 | background-repeat: no-repeat; 6 | position: relative; 7 | } 8 | 9 | .header button { 10 | color: #fff; 11 | background-color: #f29422; 12 | font-size: 18px; 13 | border-radius: 30px; 14 | padding: 20px; 15 | border: none; 16 | margin-top: 20em; 17 | margin-left: calc(((100% - 270px) / 3) * 2); 18 | } 19 | 20 | .header button:hover { 21 | background-color: #3d9dd9; 22 | transform: scale(1.02); 23 | } 24 | 25 | @media screen and (max-width: 1162px) { 26 | .header button { 27 | margin-top: 15em; 28 | font-size: 16px; 29 | } 30 | .header { 31 | height: 400px; 32 | } 33 | } 34 | 35 | @media screen and (max-width: 880px) { 36 | .header button { 37 | margin-top: 12em; 38 | font-size: 16px; 39 | } 40 | .header { 41 | height: 300px; 42 | } 43 | } 44 | 45 | @media screen and (max-width: 695px) { 46 | .header button { 47 | margin-top: 10em; 48 | font-size: 16px; 49 | } 50 | .header { 51 | height: 250px; 52 | } 53 | } 54 | 55 | @media screen and (max-width: 551px) { 56 | .header button { 57 | margin-top: 8em; 58 | font-size: 14px; 59 | margin-left: 12em; 60 | } 61 | .header { 62 | height: 190px; 63 | } 64 | } 65 | 66 | @media screen and (max-width: 423px) { 67 | .header button { 68 | margin-top: 8em; 69 | font-size: 12px; 70 | margin-left: 10em; 71 | } 72 | .header { 73 | height: 180px; 74 | } 75 | } 76 | 77 | @media screen and (max-width: 382px) { 78 | .header button { 79 | margin-top: 5em; 80 | font-size: 12px; 81 | margin-left: 9em; 82 | } 83 | .header { 84 | height: 150px; 85 | } 86 | } 87 | 88 | @media screen and (max-width: 301px) { 89 | .header button { 90 | margin-top: 4em; 91 | font-size: 8px; 92 | margin-left: 14em; 93 | } 94 | .header { 95 | height: 120px; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/components/marginals/Navbar/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const Button = styled.button` 4 | display: none; 5 | border: none; 6 | font-size: 20px; 7 | flex-direction: column; 8 | cursor: pointer; 9 | color: #3d9dd9; 10 | background: transparent; 11 | margin-right: 2rem; 12 | @media (max-width: 1032px) { 13 | display: flex; 14 | } 15 | `; 16 | 17 | export const MenuLink = styled.a` 18 | padding: 1rem 2rem; 19 | cursor: pointer; 20 | text-align: center; 21 | text-decoration: none; 22 | color: #67bc98; 23 | transition: all 0.3s ease-in; 24 | font-size: 0.9rem; 25 | &:hover { 26 | color: #7b7fda; 27 | } 28 | `; 29 | 30 | export const Nav = styled.div` 31 | padding: 0; 32 | z-index: 99; 33 | display: flex; 34 | justify-content: space-between; 35 | align-items: center; 36 | flex-wrap: wrap; 37 | background: #1f4690; 38 | position: relative; 39 | top: 0; 40 | left: 0; 41 | right: 0; 42 | box-shadow: 2px 1px 12px 2px #3d9dd9; 43 | `; 44 | 45 | export const Logo = styled.img` 46 | width: 9rem; 47 | margin-left: 2rem; 48 | 49 | @media only screen and (min-width:578px) and (max-width: 768px) { 50 | width: 7rem !important; 51 | } 52 | 53 | @media only screen and (max-width: 576px) { 54 | width: 5rem;} 55 | 56 | 57 | `; 58 | 59 | export const Menu = styled.div` 60 | display: flex; 61 | justify-content: space-between; 62 | align-items: center; 63 | position: relative; 64 | @media (max-width: 1032px) { 65 | overflow: hidden; 66 | flex-direction: column; 67 | max-height: ${({ isOpen }) => (isOpen ? '300px' : '0')}; 68 | transition: max-height 0.1s ease-in; 69 | width: 100%; 70 | gap: 1rem; 71 | margin-bottom: 0.7rem; 72 | } 73 | `; 74 | 75 | export const Items = styled.li` 76 | text-decoration: none; 77 | list-style: none; 78 | color: white; 79 | font-weight: 500; 80 | padding: 0 10px; 81 | margin: 0 10px; 82 | cursor: pointer; 83 | text-transform: capitalize; 84 | :hover { 85 | color: #eae3d2; 86 | } 87 | `; 88 | -------------------------------------------------------------------------------- /src/context/DataContext.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | /* eslint-disable max-len */ 3 | /* eslint-disable no-unused-vars */ 4 | /* eslint-disable react/jsx-no-constructed-context-values */ 5 | /* eslint-disable react/react-in-jsx-scope */ 6 | /* eslint-disable arrow-body-style */ 7 | /* eslint-disable react/function-component-definition */ 8 | 9 | import { React, createContext, useState, useEffect, useContext, useReducer } from 'react'; 10 | import { BrowserRouter as useHistory } from 'react-router-dom'; 11 | import reducer from './reducer'; 12 | 13 | const initialState = { 14 | // JournalList 15 | searchResults: [], 16 | search: '', 17 | currentPage: 1, 18 | postsPerPage: 5, 19 | posts: [], 20 | title: '', 21 | topic: '', 22 | issn: '', 23 | link: '', 24 | policy: 'NUMBER_ONE', 25 | dataavail: false, 26 | datashared: false, 27 | peerreview: false, 28 | enforced: 'YES', 29 | evidence: '', 30 | policyTitle: '', 31 | }; 32 | 33 | const DataContext = createContext({}); 34 | 35 | const DataProvider = ({ children }) => { 36 | const [state, dispatch] = useReducer(reducer, initialState); 37 | return ( 38 | 59 | {children} 60 | 61 | ); 62 | }; 63 | 64 | // custom hook 65 | const useGlobalContext = () => { 66 | return useContext(DataContext); 67 | }; 68 | 69 | export { DataContext, DataProvider, useGlobalContext }; 70 | -------------------------------------------------------------------------------- /src/config/content/footer.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/no-unresolved */ 2 | import { faTwitter, faGithub, faSlack } from '@fortawesome/free-brands-svg-icons'; 3 | import { faEnvelope } from '@fortawesome/free-solid-svg-icons'; 4 | 5 | export default { 6 | img: { 7 | src: 'https://res.cloudinary.com/dh6j2zoog/image/upload/v1655702085/CiS/rocket_vkcatz.png', 8 | alt: 'Code Is Science', 9 | }, 10 | copyright: 'Copyright © {{ new Date().getFullYear() }} Code is Science', 11 | col1: { 12 | head: 'Useful Links', 13 | links: [ 14 | { 15 | id: 1, 16 | sub: 'Contribute', 17 | link: 'https://github.com/codeisscience', 18 | }, 19 | { 20 | id: 2, 21 | sub: 'Manifesto', 22 | link: 'https://codeisscience.github.io/manifesto/manifesto.html', 23 | }, 24 | { 25 | id: 3, 26 | sub: 'Code of Conduct', 27 | link: '/home', 28 | }, 29 | ], 30 | }, 31 | col2: { 32 | head: 'Resources', 33 | links: [ 34 | { 35 | id: 1, 36 | sub: 'Authors', 37 | link: '/home', 38 | }, 39 | { 40 | id: 2, 41 | sub: 'Open Science', 42 | link: '/home', 43 | }, 44 | { 45 | id: 3, 46 | sub: 'Contributors', 47 | link: '/home', 48 | }, 49 | ], 50 | }, 51 | socials: { 52 | head: 'Contact Us', 53 | links: [ 54 | { 55 | id: 1, 56 | icon: faEnvelope, 57 | head: 'Email', 58 | link: 'mailto:contact@codeisscience.com', 59 | color: 'white', 60 | }, 61 | { 62 | id: 2, 63 | icon: faTwitter, 64 | head: 'Twitter', 65 | link: 'https://twitter.com/codeisscience', 66 | color: '#00acee', 67 | }, 68 | { 69 | id: 3, 70 | icon: faGithub, 71 | head: 'Github', 72 | link: 'https://github.com/codeisscience', 73 | color: 'black', 74 | }, 75 | { 76 | id: 4, 77 | icon: faSlack, 78 | head: 'Slack', 79 | link: '', 80 | color: '#e01e5a', 81 | }, 82 | ], 83 | }, 84 | }; 85 | -------------------------------------------------------------------------------- /src/components/marginals/Footer/Footer.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable max-len */ 2 | import React from 'react'; 3 | 4 | // Libraries 5 | import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; 6 | 7 | // Assets 8 | import { footer } from '../../../config/content'; 9 | 10 | // Styles 11 | import { 12 | FooterContainer, 13 | SecondaryContainer, 14 | UpperDiv, 15 | Logo, 16 | LinksContainer, 17 | Heading2, 18 | Heading3, 19 | NoStyleNav, 20 | SocialDiv, 21 | LowerDiv, 22 | } from './styles'; 23 | 24 | function Footer() { 25 | return ( 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | {footer.col1.head} 35 | {footer.col1.links.map(({ id, sub, link }) => ( 36 | 37 | {sub} 38 | 39 | ))} 40 | 41 | 42 | 43 | {footer.col2.head} 44 | {footer.col2.links.map(({ id, sub, link }) => ( 45 | 46 | {sub} 47 | 48 | ))} 49 | 50 | 51 | 52 | {footer.socials.head} 53 |
54 | {footer.socials.links.map(({ id, icon, link }) => ( 55 | 56 | 57 | 58 | 59 | 60 | ))} 61 |
62 |
63 |
64 |
65 | Copyright © {new Date().getFullYear()} Code is Science 66 |
67 | ); 68 | } 69 | 70 | export default Footer; 71 | -------------------------------------------------------------------------------- /src/context/reducer.js: -------------------------------------------------------------------------------- 1 | import { 2 | SEARCH, 3 | SEARCH_RESULTS, 4 | CURRENT_PAGE, 5 | POSTS, 6 | SET_TITLE, 7 | SET_TOPIC, 8 | SET_ISSN, 9 | SET_LINK, 10 | SET_POLICY, 11 | SET_DATAAVAIL, 12 | SET_DATASHARED, 13 | SET_PEERREVIEW, 14 | SET_ENFORCED, 15 | SET_EVIDENCE, 16 | POLICYTITLE, 17 | } from './types'; 18 | 19 | const reducer = (state, action) => { 20 | switch (action.type) { 21 | case SEARCH_RESULTS: 22 | return { 23 | ...state, 24 | searchResults: action.payload, 25 | }; 26 | case SEARCH: 27 | return { 28 | ...state, 29 | search: action.payload, 30 | }; 31 | case CURRENT_PAGE: 32 | return { 33 | ...state, 34 | currentPage: action.payload, 35 | }; 36 | case POSTS: 37 | return { 38 | ...state, 39 | posts: action.payload, 40 | }; 41 | case SET_TITLE: 42 | return { 43 | ...state, 44 | title: action.payload, 45 | }; 46 | case SET_TOPIC: 47 | return { 48 | ...state, 49 | topic: action.payload, 50 | }; 51 | case SET_ISSN: 52 | return { 53 | ...state, 54 | issn: action.payload, 55 | }; 56 | case SET_LINK: 57 | return { 58 | ...state, 59 | link: action.payload, 60 | }; 61 | case SET_POLICY: 62 | return { 63 | ...state, 64 | policy: action.payload, 65 | }; 66 | case SET_DATAAVAIL: 67 | return { 68 | ...state, 69 | dataavail: action.payload, 70 | }; 71 | case SET_DATASHARED: 72 | return { 73 | ...state, 74 | datashared: action.payload, 75 | }; 76 | case SET_PEERREVIEW: 77 | return { 78 | ...state, 79 | peerreview: action.payload, 80 | }; 81 | case SET_ENFORCED: 82 | return { 83 | ...state, 84 | enforced: action.payload, 85 | }; 86 | case SET_EVIDENCE: 87 | return { 88 | ...state, 89 | evidence: action.payload, 90 | }; 91 | case POLICYTITLE: 92 | return { 93 | ...state, 94 | policyTitle: action.payload, 95 | }; 96 | 97 | default: 98 | return state; 99 | } 100 | }; 101 | 102 | export default reducer; 103 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable array-callback-return */ 2 | /* eslint-disable no-alert */ 3 | /* eslint-disable react-hooks/exhaustive-deps */ 4 | /* eslint-disable arrow-body-style */ 5 | /* eslint-disable max-len */ 6 | /* eslint-disable no-unused-vars */ 7 | import { React } from 'react'; 8 | 9 | // Libraries 10 | import ReactDOM from 'react-dom'; 11 | import { BrowserRouter as Router, Switch, Route, Redirect, useHistory } from 'react-router-dom'; 12 | import { ApolloClient, InMemoryCache, ApolloProvider, HttpLink, from } from '@apollo/client'; 13 | import { format } from 'date-fns'; 14 | import { onError } from '@apollo/client/link/error'; 15 | // import * as dotenv from 'dotenv'; 16 | 17 | // Styles 18 | import './index.css'; 19 | import 'bootstrap/dist/css/bootstrap.min.css'; 20 | 21 | // Components 22 | import Profile from './components/Authentication/User-Profile/useprofile'; 23 | import { Journal, Manifesto, Home } from './pages'; 24 | import { Footer, Auth, Header, Login, JournalDetails, AddJournal, Layout } from './components'; 25 | import Navbar from './components/marginals/Navbar/Navbar'; 26 | import Edit from './components/EditJournal/Edit'; 27 | 28 | // Context 29 | import { DataProvider } from './context/DataContext'; 30 | 31 | // React-Apollo setup 32 | 33 | const client = new ApolloClient({ 34 | uri: process.env.REACT_APP_PUBLIC_API_URL, 35 | credentials: 'include', 36 | cache: new InMemoryCache(), 37 | }); 38 | 39 | function App() { 40 | return ( 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 |