├── src ├── sitemap │ └── .gitkeep ├── react-app-env.d.ts ├── tailwind.css ├── assets │ ├── certificate_assets │ │ ├── cert-body.png │ │ ├── projectpiker.css │ │ └── certificate.css │ ├── darkwave3.svg │ ├── lightwave3.svg │ ├── loginlightwave1.svg │ ├── darkwave1.svg │ ├── lightwave1.svg │ ├── darkwave2.svg │ └── lightwave2.svg ├── setupTests.ts ├── App.test.tsx ├── index.css ├── context │ ├── CertificateContext │ │ ├── CertificateReducer.ts │ │ ├── CertificateRouter.tsx │ │ └── CertificateProvider.tsx │ ├── ThemeContext │ │ ├── ThemeReducer.ts │ │ └── ThemeProvider.tsx │ ├── ProjectContext │ │ ├── ProjectRouter.tsx │ │ └── index.tsx │ └── AuthContext │ │ ├── AuthReducer.ts │ │ └── AuthProvider.tsx ├── router │ ├── route.tsx │ └── config.ts ├── reportWebVitals.ts ├── components │ ├── ProjectStat.tsx │ ├── Fork.tsx │ ├── ProjectDataTab.tsx │ ├── Spinner.tsx │ ├── ProjectInput │ │ ├── index.tsx │ │ ├── GitlabProjectInput.tsx │ │ ├── GithubProjectInput.tsx │ │ └── BitbucketProjectInput.tsx │ ├── DarkModeButton.tsx │ ├── Toast.ts │ ├── OpenPopup.ts │ ├── Footer.tsx │ ├── ProjectProgressBar │ │ ├── ProjectProgressBar.tsx │ │ └── ProjectProgressBar.module.css │ ├── Button.tsx │ ├── MicroLogin.tsx │ ├── GenerateCertificate.tsx │ ├── Header.tsx │ ├── CertificatePdf.tsx │ └── ProjectPicker.tsx ├── index.tsx ├── config.ts ├── App.tsx ├── logo.svg ├── pages │ ├── Main.tsx │ ├── VerifyCertificate.tsx │ ├── Login.tsx │ └── Certificate.tsx └── App.css ├── public ├── _redirects ├── favicon.ico ├── logo192.png ├── logo512.png ├── robots.txt ├── recievedToken.html ├── manifest.json └── index.html ├── .env.sample ├── .prettierignore ├── .husky └── pre-commit ├── .gitignore ├── tsconfig.json ├── .github ├── ISSUE_TEMPLATE │ ├── general_issue.md │ ├── feature_request.yml │ └── bug_report.yml ├── PULL_REQUEST_TEMPLATE.md └── workflows │ └── welcome-contributors.yml ├── package.json ├── tailwind.config.js ├── README.md └── CODE_OF_CONDUCT.md /src/sitemap/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/_redirects: -------------------------------------------------------------------------------- 1 | /* /index.html 200 -------------------------------------------------------------------------------- /.env.sample: -------------------------------------------------------------------------------- 1 | REACT_APP_API_BASE_URL=XXXXX 2 | -------------------------------------------------------------------------------- /src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | build 2 | node_modules 3 | tailwind.generated.css 4 | .github 5 | -------------------------------------------------------------------------------- /src/tailwind.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-certs/oc-frontend/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-certs/oc-frontend/HEAD/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-certs/oc-frontend/HEAD/public/logo512.png -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | 5 | npm run format && git add . 6 | -------------------------------------------------------------------------------- /src/assets/certificate_assets/cert-body.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-certs/oc-frontend/HEAD/src/assets/certificate_assets/cert-body.png -------------------------------------------------------------------------------- /src/setupTests.ts: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import "@testing-library/jest-dom"; 6 | -------------------------------------------------------------------------------- /src/App.test.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { render, screen } from "@testing-library/react"; 3 | import App from "./App"; 4 | 5 | test("renders learn react link", () => { 6 | render(); 7 | const linkElement = screen.getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | @import url("https://fonts.googleapis.com/css2?family=Roboto+Mono:ital,wght@0,100;0,200;0,300;0,400;1,100;1,200;1,300;1,400&display=swap"); 2 | 3 | * { 4 | margin: 0; 5 | padding: 0; 6 | box-sizing: border-box; 7 | /* color: #fff; */ 8 | } 9 | 10 | #root { 11 | /* display: flex; */ 12 | height: 100%; 13 | width: 100%; 14 | } 15 | -------------------------------------------------------------------------------- /src/assets/darkwave3.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/lightwave3.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/loginlightwave1.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/darkwave1.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/assets/lightwave1.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/assets/darkwave2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/assets/lightwave2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/context/CertificateContext/CertificateReducer.ts: -------------------------------------------------------------------------------- 1 | export const CertificateReducer = (state: any, action: any) => { 2 | switch (action.type) { 3 | case "GETPROJECTTOKEN": 4 | return { 5 | ...state, 6 | data: action.payload, 7 | }; 8 | case "GENERATECERTIFICATE": 9 | return { 10 | ...state, 11 | certificateData: action.payload, 12 | }; 13 | 14 | default: 15 | return { state }; 16 | } 17 | }; 18 | -------------------------------------------------------------------------------- /src/assets/certificate_assets/projectpiker.css: -------------------------------------------------------------------------------- 1 | .svg, 2 | .provider-logo { 3 | width: 114px; 4 | height: 114px; 5 | margin: 1em; 6 | } 7 | 8 | .circle-bg { 9 | fill: none; 10 | stroke-width: 10px; 11 | } 12 | 13 | .progress { 14 | fill: none; 15 | stroke-width: 10px; 16 | stroke-linecap: round; 17 | transform: rotate(-90deg); 18 | transform-origin: 50% 50%; 19 | stroke-dasharray: 360; 20 | stroke-dashoffset: 50; 21 | animation: progress-1 1s ease-out; 22 | } 23 | -------------------------------------------------------------------------------- /src/context/ThemeContext/ThemeReducer.ts: -------------------------------------------------------------------------------- 1 | import { defaultThemeType } from "./ThemeProvider"; 2 | 3 | export const ThemeReducer = (state: defaultThemeType, action: any) => { 4 | switch (action.type) { 5 | case "CHANGE": { 6 | localStorage.setItem("theme", action.payload); 7 | //console.log(action.payload); 8 | return { 9 | ...state, 10 | theme: action.payload, 11 | }; 12 | } 13 | 14 | default: 15 | return state; 16 | } 17 | }; 18 | -------------------------------------------------------------------------------- /src/router/route.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Routes, Route } from "react-router-dom"; 3 | import routerConfig from "./config"; 4 | 5 | interface RoutingProps {} 6 | 7 | export const Routing: React.FC = () => { 8 | return ( 9 | 10 | {routerConfig.map((Rut: any) => { 11 | return ( 12 | } /> 13 | ); 14 | })} 15 | 16 | ); 17 | }; 18 | -------------------------------------------------------------------------------- /src/reportWebVitals.ts: -------------------------------------------------------------------------------- 1 | import { ReportHandler } from "web-vitals"; 2 | 3 | const reportWebVitals = (onPerfEntry?: ReportHandler) => { 4 | if (onPerfEntry && onPerfEntry instanceof Function) { 5 | import("web-vitals").then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 6 | getCLS(onPerfEntry); 7 | getFID(onPerfEntry); 8 | getFCP(onPerfEntry); 9 | getLCP(onPerfEntry); 10 | getTTFB(onPerfEntry); 11 | }); 12 | } 13 | }; 14 | 15 | export default reportWebVitals; 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env 17 | .env.local 18 | .env.development.local 19 | .env.test.local 20 | .env.production.local 21 | 22 | npm-debug.log* 23 | yarn-debug.log* 24 | yarn-error.log* 25 | 26 | .firebaserc 27 | firebase.json 28 | .firebase 29 | .babelrc 30 | GenerateSiteMap.js 31 | generator.ts 32 | index.ts -------------------------------------------------------------------------------- /public/recievedToken.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Redirecting... 4 | 5 | 6 | 7 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/components/ProjectStat.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | type Props = { 4 | stat: any; 5 | title: string; 6 | className?: string; 7 | }; 8 | 9 | export default function ProjectStat({ stat, title, className }: Props) { 10 | return ( 11 |
14 |
15 |
{stat}
16 |

{title}

17 |
18 |
19 | ); 20 | } 21 | -------------------------------------------------------------------------------- /src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom"; 3 | import "./index.css"; 4 | import App from "./App"; 5 | import reportWebVitals from "./reportWebVitals"; 6 | 7 | ReactDOM.render( 8 | 9 | 10 | , 11 | document.getElementById("root") 12 | ); 13 | 14 | // If you want to start measuring performance in your app, pass a function 15 | // to log results (for example: reportWebVitals(console.log)) 16 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 17 | reportWebVitals(); 18 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "esModuleInterop": true, 8 | "allowSyntheticDefaultImports": true, 9 | "strict": true, 10 | "forceConsistentCasingInFileNames": true, 11 | "noFallthroughCasesInSwitch": true, 12 | "module": "esnext", 13 | "moduleResolution": "node", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "noEmit": true, 17 | "jsx": "react-jsx" 18 | }, 19 | "include": ["src"] 20 | } 21 | -------------------------------------------------------------------------------- /src/components/Fork.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { FaGithubAlt } from "react-icons/fa"; 3 | import { useLocation } from "react-router-dom"; 4 | 5 | interface ForkProps {} 6 | 7 | export const Fork: React.FC = () => { 8 | const location = useLocation(); 9 | return location.pathname !== "/certificate" ? ( 10 |
11 | 16 | Fork me on 17 | 18 | 19 |
20 | ) : null; 21 | }; 22 | -------------------------------------------------------------------------------- /src/components/ProjectDataTab.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | type Props = { 4 | children?: React.ReactNode; 5 | title: string; 6 | }; 7 | 8 | export default function ProjectDataTab({ children, title }: Props) { 9 | return ( 10 |
11 | 12 | {title} 13 | 14 |
15 |
{children}
16 |
17 |
18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /src/components/Spinner.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | const sizes = { 4 | "2": "h-2 w-2", 5 | "4": "h-4 w-4", 6 | }; 7 | 8 | export const Spinner: React.FC<{ size?: keyof typeof sizes }> = ({ 9 | size = "4", 10 | }) => { 11 | return ( 12 | 18 | 22 | 23 | ); 24 | }; 25 | -------------------------------------------------------------------------------- /src/config.ts: -------------------------------------------------------------------------------- 1 | export const __prod__ = process.env.NODE_ENV === "production"; 2 | export const logoDark = 3 | "https://user-images.githubusercontent.com/41825906/153617213-e956c616-4f4a-4d62-95af-2d4ac4d57942.png"; 4 | export const logoLight = 5 | "https://user-images.githubusercontent.com/55032900/156938066-090de099-4ec7-47eb-91fd-458b30586651.png"; 6 | export const clientId = process.env.REACT_APP_CLIENT_ID; 7 | export const clientSecret = process.env.REACT_APP_CLIENT_SECRET; 8 | export const redirectUri = process.env.REACT_APP_REDIRECT_URI; 9 | export const apiBaseUrl = __prod__ 10 | ? process.env.REACT_APP_API_BASE_URL 11 | : process.env.REACT_APP_API_BASE_URL_LOCAL; 12 | -------------------------------------------------------------------------------- /src/router/config.ts: -------------------------------------------------------------------------------- 1 | import Certificate from "../pages/Certificate"; 2 | import { Login } from "../pages/Login"; 3 | import { Main } from "../pages/Main"; 4 | import { VerifyCertificate } from "../pages/VerifyCertificate"; 5 | 6 | const RouterConfig = [ 7 | { 8 | path: "/login", 9 | Component: Login, 10 | }, 11 | { 12 | path: "/", 13 | Component: Main, 14 | }, 15 | { 16 | path: "/verifyCertificate", 17 | Component: VerifyCertificate, 18 | }, 19 | { 20 | path: "/certificate/:id", 21 | Component: Certificate, 22 | }, 23 | { 24 | path: "/certificate", 25 | Component: Certificate, 26 | }, 27 | ]; 28 | 29 | export default RouterConfig; 30 | -------------------------------------------------------------------------------- /src/context/ProjectContext/ProjectRouter.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext } from "react"; 2 | import ProjectContextProvider, { ProjectContext } from "."; 3 | import ProjectPicker from "../../components/ProjectPicker"; 4 | 5 | type Props = { 6 | children?: React.ReactNode; 7 | }; 8 | 9 | const ProjectRouterUtil = ({ children }: Props) => { 10 | const { projectData } = useContext(ProjectContext); 11 | return projectData ? : <>{children}; 12 | }; 13 | 14 | export default function ProjectRouter({ children }: Props) { 15 | return ( 16 | 17 | {children} 18 | 19 | ); 20 | } 21 | -------------------------------------------------------------------------------- /src/context/CertificateContext/CertificateRouter.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext } from "react"; 2 | import { CertificatePdf } from "../../components/CertificatePdf"; 3 | import CertificateContext, { CertificateProvider } from "./CertificateProvider"; 4 | 5 | type Props = { 6 | children?: React.ReactNode; 7 | }; 8 | const CertificateRouterUtil = ({ children }: Props) => { 9 | const { certificate } = useContext(CertificateContext); 10 | return certificate ? : <>{children}; 11 | }; 12 | 13 | export default function CertificateRouter(props: Props) { 14 | return ( 15 | 16 | 17 | 18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/general_issue.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: General issue 3 | about: Suggest an issue for this project 4 | title: "" 5 | labels: "" 6 | assignees: "" 7 | --- 8 | 9 | # Prerequisites: 10 | 11 | Please answer the following questions for yourself before submitting an issue. **YOU MAY DELETE THE PREREQUISITES SECTION.** 12 | 13 | 14 | 15 | - [ ] I checked to make sure that this issue has not already been filed. 16 | 17 | # Expected Behavior: 18 | 19 | Please describe the behavior you are expecting. 20 | 21 | # Current Behavior: 22 | 23 | What is the current behavior? 24 | 25 | # Solution: 26 | 27 | Please describe what will you do to solve this issue or your approach to solve this issue. 28 | 29 | # Screenshots (optional): 30 | -------------------------------------------------------------------------------- /src/components/ProjectInput/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext } from "react"; 2 | import AuthContext from "../../context/AuthContext/AuthProvider"; 3 | import BitbucketProjectInput from "./BitbucketProjectInput"; 4 | import GithubProjectInput from "./GithubProjectInput"; 5 | import GitlabProjectInput from "./GitlabProjectInput"; 6 | 7 | export default function ProjectInput() { 8 | const { isAuthenticated, user } = useContext(AuthContext); 9 | if (!isAuthenticated) { 10 | return null; 11 | } 12 | if (user.kind === "github") { 13 | return ; 14 | } 15 | if (user.kind === "gitlab") { 16 | return ; 17 | } 18 | if (user.kind === "bitbucket") { 19 | return ; 20 | } 21 | return null; 22 | } 23 | -------------------------------------------------------------------------------- /src/components/DarkModeButton.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext } from "react"; 2 | import ThemeContext from "../context/ThemeContext/ThemeProvider"; 3 | import { BsFillMoonStarsFill } from "react-icons/bs"; 4 | import { IoSunny } from "react-icons/io5"; 5 | 6 | const DarkModeButton = () => { 7 | const { theme, toggle } = useContext(ThemeContext); 8 | //console.log({ theme }); 9 | return ( 10 |
15 | {theme !== "dark" ? ( 16 | 17 | ) : ( 18 | 19 | )} 20 |
21 | ); 22 | }; 23 | 24 | export default DarkModeButton; 25 | -------------------------------------------------------------------------------- /src/context/CertificateContext/CertificateProvider.tsx: -------------------------------------------------------------------------------- 1 | import React, { createContext, useState } from "react"; 2 | 3 | export interface defaultState {} 4 | 5 | const initialState: any = {}; 6 | 7 | const CertificateContext = createContext(initialState); 8 | export default CertificateContext; 9 | 10 | interface CertificateProviderProps { 11 | children?: React.ReactNode; 12 | } 13 | 14 | export const CertificateProvider: React.FC = ({ 15 | children, 16 | }) => { 17 | const [certificate, setCertificate] = useState(null); 18 | 19 | return ( 20 | 28 | {children} 29 | 30 | ); 31 | }; 32 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "https://user-images.githubusercontent.com/41825906/153617213-e956c616-4f4a-4d62-95af-2d4ac4d57942.png", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "https://user-images.githubusercontent.com/41825906/153617213-e956c616-4f4a-4d62-95af-2d4ac4d57942.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "https://user-images.githubusercontent.com/41825906/153617213-e956c616-4f4a-4d62-95af-2d4ac4d57942.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/App.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import "./App.css"; 3 | import { BrowserRouter } from "react-router-dom"; 4 | import { Routing } from "./router/route"; 5 | import { AuthProvider } from "./context/AuthContext/AuthProvider"; 6 | import { Fork } from "./components/Fork"; 7 | import { ThemeProvider } from "./context/ThemeContext/ThemeProvider"; 8 | import { ToastContainer } from "react-toastify"; 9 | import "react-toastify/dist/ReactToastify.css"; 10 | import { Header } from "./components/Header"; 11 | import Footer from "./components/Footer"; 12 | import CertificateRouter from "./context/CertificateContext/CertificateRouter"; 13 | 14 | function App() { 15 | return ( 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 |