├── .gitignore ├── .vscode └── launch.json ├── APIdocs.yaml ├── Procfile ├── README.md ├── app.js ├── certlify png.png ├── config └── database.js ├── controllers ├── GeneratorVerificationMail.js ├── GetDashboard.js ├── PasswordResetMail.js ├── UserController.js ├── UserVerificationMail.js ├── addEligibleUsers.js ├── createCert.js ├── generate.js ├── mailer.js └── manage.js ├── designs ├── Manage.png ├── collectors.png ├── dasboard.png ├── landing page.png ├── login page.png └── sign up.png ├── imgs ├── IMG-20200923-WA0214.svg ├── Screenshot (1730).png ├── Sunkanmi's Certificate.png ├── arrow.svg ├── certlify svg.svg ├── diploma (1).svg ├── diploma (2).svg ├── diploma (3).svg ├── diploma.svg ├── hero-dsc-about-unilag.png ├── icon.png ├── search.svg └── user.svg ├── manifest.json ├── models ├── links.js └── users.js ├── out ├── FontSizer.js.html ├── fonts │ ├── OpenSans-Bold-webfont.eot │ ├── OpenSans-Bold-webfont.svg │ ├── OpenSans-Bold-webfont.woff │ ├── OpenSans-BoldItalic-webfont.eot │ ├── OpenSans-BoldItalic-webfont.svg │ ├── OpenSans-BoldItalic-webfont.woff │ ├── OpenSans-Italic-webfont.eot │ ├── OpenSans-Italic-webfont.svg │ ├── OpenSans-Italic-webfont.woff │ ├── OpenSans-Light-webfont.eot │ ├── OpenSans-Light-webfont.svg │ ├── OpenSans-Light-webfont.woff │ ├── OpenSans-LightItalic-webfont.eot │ ├── OpenSans-LightItalic-webfont.svg │ ├── OpenSans-LightItalic-webfont.woff │ ├── OpenSans-Regular-webfont.eot │ ├── OpenSans-Regular-webfont.svg │ └── OpenSans-Regular-webfont.woff ├── global.html ├── index.html ├── main.js.html ├── scripts │ ├── linenumber.js │ └── prettify │ │ ├── Apache-License-2.0.txt │ │ ├── lang-css.js │ │ └── prettify.js └── styles │ ├── jsdoc-default.css │ ├── prettify-jsdoc.css │ └── prettify-tomorrow.css ├── package-lock.json ├── package.json ├── routes ├── addEligibleUsers.js ├── allviews.js ├── createCert.js ├── dashboard.js ├── generate.js ├── manage.js └── userRoutes.js └── views ├── 404-page.html ├── certificate-gen.html ├── certificator.html ├── dashboard.html ├── debug.log ├── emailverify.html ├── forgot-email.html ├── imgs ├── DSC copy.png ├── Group 297.png ├── Group 298-edit.png ├── Group 298.png ├── Group 298.svg ├── IMG-20200923-WA0214.svg ├── Icon svg.svg ├── Sunkanmi's Certificate.png ├── arrow.svg ├── badge.svg ├── certlify svg.svg ├── code logo.jpg ├── copy.svg ├── diploma (1).svg ├── diploma (2).svg ├── diploma (3).svg ├── diploma.svg ├── hero-dsc-about-unilag.png ├── icon.png ├── mark-github-512.png ├── search.svg ├── share-icons │ ├── facebook.svg │ ├── twitter.svg │ └── whatsapp.svg ├── share.svg ├── tutorial.png ├── tutorial2.png ├── user.svg └── warning.svg ├── index.html ├── login.html ├── manage.html ├── manifest.json ├── password-reset.html ├── signup.html ├── site.webmanifest ├── src ├── css │ ├── animations.css │ ├── certificate-gen.css │ ├── certificate.css │ ├── dashboard.css │ ├── fonts │ │ ├── Apache License.txt │ │ ├── OpenSans-Bold.ttf │ │ ├── OpenSans-BoldItalic.ttf │ │ ├── OpenSans-ExtraBold.ttf │ │ ├── OpenSans-ExtraBoldItalic.ttf │ │ ├── OpenSans-Italic.ttf │ │ ├── OpenSans-Light.ttf │ │ ├── OpenSans-LightItalic.ttf │ │ ├── OpenSans-Regular.ttf │ │ ├── OpenSans-Semibold.ttf │ │ ├── OpenSans-SemiboldItalic.ttf │ │ └── open-sans.zip │ ├── footer.css │ ├── loader.css │ ├── main.css │ ├── manage-func.css │ ├── manage.css │ ├── share.css │ └── signup.css └── js │ ├── FontPicker.js │ ├── FontSizer.js │ ├── canvas.js │ ├── generator.js │ ├── main.js │ └── sw-install.js └── sw.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Launch Chrome", 9 | "request": "launch", 10 | "type": "pwa-chrome", 11 | "url": "http://localhost:8080", 12 | "webRoot": "${workspaceFolder}" 13 | }, 14 | { 15 | "type": "pwa-chrome", 16 | "request": "launch", 17 | "name": "Open index.html", 18 | "file": "c:\\xampp\\htdocs\\cert\\index.html" 19 | } 20 | ] 21 | } -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | web: node app.js -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 | 5 | ## The application is live at [certlify.com](https://certlify.com) 6 | 7 | ## Developer Section 8 | 9 | ### 💻 System Requirements 10 | * Any Operating System (ie. MacOS X, Linux, Windows) 11 | * Any IDE with nodejs installed on your system(ie. VSCode etc), a good text editor would do too(ie. Sublime). You can install nodejs [here](https://nodejs.org). 12 | * A little knowledge of NodeJs 13 | * Hands to code ✋🤚 14 | * A brain to think 🧠 15 | 16 | ### Getting started/Usage Guide 17 | 18 | #### 1. Clone The Repo 19 | ```sh 20 | $ git clone https://github.com/DSC-Unilag/cert.git 21 | $ cd cert 22 | ``` 23 | 24 | #### 2. Get Requirements 25 | ```sh 26 | $ npm install 27 | ``` 28 | 29 | #### 3. Configure Environment Variables 30 | The application uses mongoDB, and this requires a connection string. Open the config folder and edit the database.js file with your details. 31 | To enable mailing, configure the email and emailpass property of the database.js file 32 | 33 | #### 4. Running The Application 34 | ```sh 35 | $ npm run dev 36 | ``` 37 | 38 | #### 5. Using The Application 39 | Open chrome and go to 40 | ```sh 41 | http://localhost:3333/ 42 | ``` 43 | 44 | ### :heart: Found this project useful? 45 | If you found this project useful or you like what you see, then please consider giving it a :star: on Github and sharing it with your friends via social media. 46 | 47 | ### Api documentation 48 | 49 | To view the api documentation, visit [editor.swagger.io](https://app.swaggerhub.com/apis-docs/DSC-cert-gen/certificate-generator/1.0.0). Setup the project locally to test 50 | 51 | ## 🤓 Contributors 52 | * **Zubs** 53 | * **WiseMrMusa** 54 | * **geektutor** 55 | * **bolubee101** 56 | * **sunkanmii** 57 | * **[Ibrahim Salami](https://www.behance.net/ibrahimsalami)** 58 | * **Lateefah** 59 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | 3 | // For when we create our apis 4 | const cors = require("cors"); 5 | const mongoose = require("mongoose"); 6 | const session = require("express-session"); 7 | 8 | // For session Storage 9 | const MongoStore = require("connect-mongo")(session); 10 | const config = require("./config/database"); 11 | let configuration = process.env.DATABASE || config.database; 12 | const Links = require("./models/links"); 13 | const User = require("./models/users"); 14 | var jwt = require("jsonwebtoken"); 15 | let secret = process.env.SECRET || config.secret; 16 | // connect to database 17 | mongoose.connect(configuration, { 18 | useNewUrlParser: true, 19 | useUnifiedTopology: true, 20 | }); 21 | 22 | const db = mongoose.connection; 23 | db.on("error", console.error.bind(console, "connection error:")); 24 | db.once("open", function () { 25 | console.log("mongodb connection established"); 26 | }); 27 | 28 | // initialize app 29 | const app = express(); 30 | 31 | // middlewares 32 | app.use( 33 | session({ 34 | secret: process.env.SECRET || config.secret, 35 | store: new MongoStore({ mongooseConnection: db }), 36 | resave: false, 37 | saveUninitialized: false, 38 | }) 39 | ); 40 | 41 | app.use(cors()); 42 | app.use(express.static(__dirname + "/views")); 43 | app.use(express.json({ limit: "10mb" })); 44 | 45 | // Auth (User) Routes 46 | const userRoutes = require("./routes/userRoutes"); 47 | app.use("/api", userRoutes); 48 | 49 | const dashboard = require("./routes/dashboard"); 50 | app.use("/api", dashboard); 51 | 52 | const manage = require("./routes/manage"); 53 | app.use("/api", manage); 54 | 55 | const createCert = require("./routes/createCert"); 56 | app.use("/api", createCert); 57 | 58 | const addnew = require("./routes/addEligibleUsers"); 59 | app.use("/api", addnew) 60 | 61 | const generate = require("./routes/generate"); 62 | app.use("/api", generate); 63 | 64 | app.get('/signup', (req, res) => { 65 | res.sendFile(__dirname + "/views/signup.html"); 66 | }); 67 | app.get("/dashboard", (req, res) => { 68 | if (!req.session.email && !req.session.anon) { 69 | return res.redirect("/login"); 70 | } 71 | res.sendFile(__dirname + "/views/dashboard.html"); 72 | }) 73 | app.get("/login", (req, res) => { 74 | res.sendFile(__dirname + "/views/login.html"); 75 | }) 76 | app.get("/manage", (req, res) => { 77 | if (!req.session.email && !req.session.anon) { 78 | return res.redirect("/login"); 79 | } else { 80 | if (req.query.link) { 81 | Links.findOne({ link: req.query.link }, function (err, cert) { 82 | if (cert) { 83 | if (cert.issuer == req.session.email) { 84 | res.sendFile(__dirname + "/views/manage.html"); 85 | } else { 86 | res.status(401) 87 | res.redirect("/login"); 88 | } 89 | } else { 90 | res.sendFile(__dirname + "/views/404-page.html"); 91 | } 92 | }) 93 | 94 | } else { 95 | res.sendFile(__dirname + "/views/404-page.html"); 96 | } 97 | 98 | } 99 | }) 100 | 101 | app.get("/createcertificate", (req, res) => { 102 | if (!req.session.email && !req.session.anon) { 103 | return res.redirect("/login"); 104 | } 105 | res.sendFile(__dirname + "/views/certificate-gen.html"); 106 | }) 107 | 108 | app.get("/certificate/:link", (req, res) => { 109 | let link = req.params.link 110 | req.session.link = link; 111 | Links.findOne({ link: req.params.link }, (err, cert) => { 112 | if (cert) { 113 | res.status(200); 114 | return res.sendFile(__dirname + "/views/emailverify.html"); 115 | } else { 116 | res.sendFile(__dirname + "/views/404-page.html"); 117 | } 118 | }) 119 | 120 | }) 121 | app.get("/certify/:jwt", (req, res) => { 122 | let token = req.params.jwt 123 | jwt.verify(token, secret, function (err, data) { 124 | if (err) { 125 | res.sendFile(__dirname + "/views/404-page.html"); 126 | } else { 127 | req.session.generator = data.email; 128 | req.session.link = data.link; 129 | res.sendFile(__dirname + "/views/certificator.html") 130 | } 131 | }); 132 | }) 133 | app.get("/verify/:jwt", (req, res) => { 134 | let token = req.params.jwt 135 | jwt.verify(token, secret, function (err, data) { 136 | if (err) { 137 | res.sendFile(__dirname + "/views/404-page.html"); 138 | } else { 139 | User.findOne({ email: data.email }, function (err, user) { 140 | if (user) { 141 | user.confirmed = true; 142 | user.save((err) => { 143 | if (err) console.log(err) 144 | else { 145 | req.session.email = data.email; 146 | res.redirect("/dashboard") 147 | } 148 | }) 149 | } else { 150 | res.sendFile(__dirname + "/views/404-page.html"); 151 | } 152 | 153 | }) 154 | 155 | } 156 | }); 157 | }) 158 | app.get('/logout', (req, res) => { 159 | if (req.session) { 160 | req.session.destroy(err => { 161 | if (err) { 162 | res.status(400) 163 | res.json({ 164 | status: false, 165 | message: "unable to logout" 166 | }) 167 | } else { 168 | if (req.accepts('html')) { 169 | res.redirect("/login") 170 | } else if (req.accepts('json')) { 171 | res.json({ 172 | status: true, 173 | message: "logout successful" 174 | }) 175 | } 176 | 177 | } 178 | }); 179 | } else { 180 | res.redirect("/login") 181 | } 182 | 183 | }) 184 | 185 | 186 | app.get('/emailrecovery',(req,res)=>{ 187 | res.sendFile(__dirname+ "/views/forgot-email.html") 188 | }) 189 | 190 | app.get('/passwordupdate',(req,res)=>{ 191 | if(!req.query.jwt){ 192 | return res.sendFile(__dirname + "/views/404-page.html"); 193 | } 194 | let token=req.query.jwt; 195 | jwt.verify(token, secret, function (err, data) { 196 | if(err) return res.sendFile(__dirname + "/views/404-page.html"); 197 | return res.sendFile(__dirname+ "/views/password-reset.html") 198 | }) 199 | 200 | }) 201 | 202 | app.get('*', (req, res) => { 203 | res.status(404); 204 | 205 | if (req.accepts('html')) { 206 | return res.sendFile(__dirname + "/views/404-page.html"); 207 | } else if (req.accepts('json')) { 208 | res.send({ 209 | status: false, 210 | message: "endpoin not found" 211 | }); 212 | return; 213 | } 214 | }); 215 | 216 | 217 | const PORT = process.env.PORT || 3333; 218 | 219 | let server=app.listen(PORT, () => { 220 | console.log(`server running on port ${PORT}`); 221 | }); 222 | server.on('clientError', (err, socket) => { 223 | console.error(err); 224 | socket.end('HTTP/1.1 400 Bad Request\r\n\r\n'); 225 | }); -------------------------------------------------------------------------------- /certlify png.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSC-Unilag/certlify/191b602c82c8721e8d5d9afe56eee8bc7452c920/certlify png.png -------------------------------------------------------------------------------- /config/database.js: -------------------------------------------------------------------------------- 1 | // This should be your own database url 2 | module.exports = { 3 | database: 4 | "mongodb://localhost:27017/?readPreference=primary&appname=MongoDB%20Compass%20Community&ssl=false", 5 | secret: "secret-key", 6 | rounds:10, 7 | email:"", 8 | emailpass:"", 9 | sendgridkey:"" 10 | }; 11 | -------------------------------------------------------------------------------- /controllers/GetDashboard.js: -------------------------------------------------------------------------------- 1 | const User = require("../models/users"); 2 | const Links = require("../models/links"); 3 | 4 | // controller to serve the dashboard data for a logged in user 5 | let dashboard = (req, res) => { 6 | let email 7 | if (req.session.email) { 8 | email = req.session.email 9 | } else { 10 | email = req.session.anon 11 | } 12 | 13 | if (email) { 14 | 15 | User.findOne({ email }, function (err, user) { 16 | let data = {} 17 | if (user) { 18 | data.name = user.name 19 | data.certificateUrls = user.certificateUrls 20 | data.certs = []; 21 | let links = user.certificateUrls 22 | 23 | Links.find({ 24 | link: { $in: links } 25 | }, function (err, docs) { 26 | // come back to do this like a normal human 27 | for (i in docs) { 28 | data.certs[i] = {}; 29 | data.certs[i].name = docs[i].name 30 | data.certs[i].link = docs[i].link 31 | data.certs[i].thumb = docs[i].thumb 32 | data.certs[i].boundary = docs[i].boundary 33 | } 34 | res.json(data); 35 | }); 36 | 37 | } else { 38 | 39 | res.status(401) 40 | res.json({ 41 | status: false, 42 | message: "Unregistered user" 43 | }) 44 | } 45 | }) 46 | } else { 47 | res.status(401) 48 | res.json({ 49 | status: false, 50 | message: "user not signed in" 51 | }) 52 | } 53 | 54 | } 55 | module.exports = dashboard; -------------------------------------------------------------------------------- /controllers/addEligibleUsers.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Here I define functions to be used in my routes again, seems like man's just doing the same things over and over 4 | 5 | */ 6 | 7 | // Bring in the links model 8 | const Link= require("../models/links"); 9 | 10 | // Load dependencies 11 | var fs = require('fs'); 12 | const csv = require("csvtojson"); 13 | const multer = require("multer"); 14 | const path = require('path'); 15 | 16 | // This is as used in the last project 17 | const storage = multer.diskStorage({ 18 | destination: function(req, file, cb) { 19 | cb(null, __dirname); 20 | }, 21 | 22 | // By default, multer removes file extensions so let's add them back 23 | filename: function(req, file, cb) { 24 | cb(null, req.session.email+ path.extname(file.originalname)); 25 | } 26 | }); 27 | 28 | const upload = multer({ storage: storage }).single('FileUpload'); 29 | 30 | // This gets the users from the csv file to the json to be stored in the mongoDB database 31 | const addEligibleUsers = (req, res) => { 32 | 33 | // An easy way to know the function works, let it log something 34 | // console.log("started") 35 | 36 | // The real upload part 37 | upload(req,res,function (err){ 38 | 39 | // We have to be sure there's no error, so we check to be safe 40 | if (err instanceof multer.MulterError) { 41 | console.log("multer error") 42 | throw err 43 | } else if (err) { 44 | throw err 45 | } else { 46 | 47 | // Set save location and format 48 | const csvFilePath=__dirname+`/${req.session.email}.csv` 49 | fs.readFile(csvFilePath,'utf8', function(err, data) { 50 | let newcase=data.replace(/email/i,"email"); 51 | newcase=newcase.replace(/name/i,"name"); 52 | fs.writeFile(csvFilePath,newcase , function (err) { 53 | csv() 54 | .fromFile(csvFilePath) // Converts the csv file to json 55 | .then((users) => { 56 | // console.log(users); 57 | fs.unlink(csvFilePath, (err) => { 58 | if (err) throw err; 59 | }); 60 | Link.findOne({ link:req.params.link }, (err, cert) => { 61 | 62 | // We see if there's actually a certificate to collect, yunno, it only makes sense 63 | if (cert) { 64 | 65 | // You must be logged in to upload eligible users 66 | if (cert.issuer == req.session.email) { 67 | 68 | // Deal with each user in the uploaded csv 69 | for (i in users) { 70 | 71 | // This is set to true on collection of the certificate 72 | users[i].status = false; 73 | if(users[i].name){ 74 | users[i].status = true; 75 | } 76 | 77 | // Should a user row not have email 78 | if (!users[i].email) { 79 | res.status(400) 80 | return res.json({ 81 | status: false, 82 | message: "check the format of your csv file" 83 | }) 84 | } 85 | } 86 | 87 | // Since each user row has been verified to contain email, they're eligible to get the certificate 88 | 89 | cert.eligibleUsers =cert.eligibleUsers.concat(users); 90 | 91 | // Now after all is said and done, saving now would make sense 92 | cert.save((err) => { 93 | if (err) { 94 | console.log(err); 95 | res.status(400) 96 | res.json({ 97 | status: false, 98 | message: "check the format of your csv file" 99 | }) 100 | } else { 101 | // console.log("done") 102 | res.status(201) 103 | res.json({ 104 | status: true, 105 | message: "successfully added eligible users" 106 | }) 107 | } 108 | }) 109 | } else { 110 | res.status(401); 111 | res.json({ 112 | status:false, 113 | message:"unauthorized access" 114 | }) 115 | } 116 | } else { 117 | res.status(404) 118 | res.json({ 119 | status:false, 120 | message:"certificate does not exist" 121 | }) 122 | } 123 | }) 124 | }) 125 | }) 126 | }); 127 | } 128 | }) 129 | } 130 | 131 | module.exports.addNew = addEligibleUsers; 132 | -------------------------------------------------------------------------------- /controllers/createCert.js: -------------------------------------------------------------------------------- 1 | // Load all dependencies 2 | const User = require("../models/users"); 3 | var uniqid = require('uniqid'); 4 | const Link = require("../models/links"); 5 | if(process.env.CLOUDINARY_URL){ 6 | var cloudinary=require("cloudinary").v2 7 | } 8 | 9 | let certificate = (req, res) => { 10 | if (!req.session.email&&!req.session.anon) { 11 | res.status(401) 12 | res.json({ 13 | status: false, 14 | message: "user not logged in" 15 | }) 16 | } else { 17 | let link = uniqid() 18 | req.session.link = link; 19 | User.findOne({ email: req.session.email||req.session.anon }, function (err, user) { 20 | if (!user) { 21 | res.status(401) 22 | res.json({ 23 | status: false, 24 | message: "Unregistered User" 25 | }) 26 | } else { 27 | user.certificateUrls.push(link); 28 | user.save((err) => { 29 | if (err) throw err 30 | else { 31 | if(process.env.CLOUDINARY_URL){ 32 | cloudinary.uploader.upload(req.body.src,(error,result)=>{ 33 | let cert = new Link({ 34 | issuer: req.session.email||req.session.anon, 35 | name: req.body.name, 36 | link: link, 37 | src:result.url, 38 | thumb:req.body.thumb, 39 | boundary: req.body.boundary, 40 | }) 41 | cert.save(function (err, doc) { 42 | if (err) return console.error(err); 43 | res.json({ 44 | status: true, 45 | message: "certificate created", 46 | link: req.hostname + "/certificate/" + link, 47 | url:link 48 | }) 49 | }); 50 | }) 51 | }else{ 52 | let cert = new Link({ 53 | issuer: req.session.email||req.session.anon, 54 | name: req.body.name, 55 | link: link, 56 | src:req.body.src, 57 | thumb:req.body.thumb, 58 | boundary: req.body.boundary, 59 | }) 60 | cert.save(function (err, doc) { 61 | if (err) return console.error(err); 62 | res.json({ 63 | status: true, 64 | message: "certificate created", 65 | link: req.hostname + "/certificate/" + link, 66 | url:link 67 | }) 68 | }); 69 | } 70 | } 71 | }) 72 | } 73 | }) 74 | } 75 | } 76 | 77 | module.exports = certificate; 78 | -------------------------------------------------------------------------------- /controllers/mailer.js: -------------------------------------------------------------------------------- 1 | const nodemailer = require("nodemailer"); 2 | const config = require("../config/database"); 3 | 4 | var transporter = nodemailer.createTransport({ 5 | service:"SES", 6 | host: "email-smtp.us-east-1.amazonaws.com", 7 | port: 587, 8 | secure: true, 9 | auth: { 10 | user: process.env.SES_USER || config.email, 11 | pass: process.env.SES_PASS || config.emailpass, 12 | }, 13 | }); 14 | let sendMail = (mailOptions) => { 15 | transporter.sendMail(mailOptions, function (err, response) { 16 | if (err) console.log(err); 17 | }); 18 | } 19 | 20 | module.exports=sendMail -------------------------------------------------------------------------------- /controllers/manage.js: -------------------------------------------------------------------------------- 1 | const Links = require("../models/links"); 2 | 3 | let getCollectors=(req,res)=>{ 4 | if (!req.session.email&&!req.session.anon){ 5 | res.status(401); 6 | return res.json({ 7 | status:false, 8 | message:"user not logged in" 9 | }) 10 | } 11 | req.session.link=req.params.link 12 | Links.findOne({ link:req.params.link }, function (err, cert) { 13 | if(cert){ 14 | if(cert.issuer==req.session.email||cert.issuer==req.session.anon){ 15 | res.json({ 16 | status:true, 17 | collectors:cert.eligibleUsers 18 | }); 19 | }else{ 20 | res.status(401) 21 | res.json({ 22 | status:false, 23 | message:"Unauthorized access" 24 | }); 25 | } 26 | }else{ 27 | res.status(404) 28 | res.json({ 29 | status:false, 30 | message:"certificate not found" 31 | }) 32 | } 33 | }) 34 | } 35 | 36 | let details=(req,res)=>{ 37 | if (!req.session.email&&!req.session.anon){ 38 | res.status(401) 39 | return res.json({ 40 | status:false, 41 | message:"user not logged in" 42 | }) 43 | } 44 | Links.findOne({ link:req.params.link}, function (err, cert) { 45 | if(cert){ 46 | if(cert.issuer==req.session.email){ 47 | res.json({ 48 | status:true, 49 | name:cert.name, 50 | src:cert.src, 51 | link:req.params.link, 52 | share:req.hostname + "/certificate/" + req.params.link, 53 | boundary:cert.boundary 54 | }); 55 | }else{ 56 | res.status(401) 57 | res.json({ 58 | status:false, 59 | message:"Unauthorized access" 60 | }); 61 | } 62 | }else{ 63 | res.status(404) 64 | res.json({ 65 | status:false, 66 | message:"certificate not found" 67 | }) 68 | } 69 | }) 70 | } 71 | 72 | let update=(req,res)=>{ 73 | if (!req.session.email){ 74 | res.status(404) 75 | return res.json({ 76 | status:false, 77 | message:"user not logged in" 78 | }) 79 | } 80 | req.session.link=req.params.link 81 | 82 | let boundary=req.body.boundaries; 83 | Links.findOne({ link:req.params.link}, function (err, cert) { 84 | if(cert){ 85 | if(cert.issuer==req.session.email){ 86 | cert.boundary=boundary; 87 | cert.save((err)=>{ 88 | if (err) throw err; 89 | res.json({ 90 | status:true, 91 | message:"certificate successfully updated" 92 | }) 93 | }) 94 | }else{ 95 | res.status(401) 96 | res.json({ 97 | status:false, 98 | message:"Unauthorized access" 99 | }); 100 | } 101 | }else{ 102 | res.status(404) 103 | res.json({ 104 | status:false, 105 | message:"certificate not found" 106 | }) 107 | } 108 | }) 109 | } 110 | 111 | module.exports.getCollectors=getCollectors; 112 | module.exports.details=details; 113 | module.exports.update=update; -------------------------------------------------------------------------------- /designs/Manage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSC-Unilag/certlify/191b602c82c8721e8d5d9afe56eee8bc7452c920/designs/Manage.png -------------------------------------------------------------------------------- /designs/collectors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSC-Unilag/certlify/191b602c82c8721e8d5d9afe56eee8bc7452c920/designs/collectors.png -------------------------------------------------------------------------------- /designs/dasboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSC-Unilag/certlify/191b602c82c8721e8d5d9afe56eee8bc7452c920/designs/dasboard.png -------------------------------------------------------------------------------- /designs/landing page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSC-Unilag/certlify/191b602c82c8721e8d5d9afe56eee8bc7452c920/designs/landing page.png -------------------------------------------------------------------------------- /designs/login page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSC-Unilag/certlify/191b602c82c8721e8d5d9afe56eee8bc7452c920/designs/login page.png -------------------------------------------------------------------------------- /designs/sign up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSC-Unilag/certlify/191b602c82c8721e8d5d9afe56eee8bc7452c920/designs/sign up.png -------------------------------------------------------------------------------- /imgs/IMG-20200923-WA0214.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /imgs/Screenshot (1730).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSC-Unilag/certlify/191b602c82c8721e8d5d9afe56eee8bc7452c920/imgs/Screenshot (1730).png -------------------------------------------------------------------------------- /imgs/Sunkanmi's Certificate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSC-Unilag/certlify/191b602c82c8721e8d5d9afe56eee8bc7452c920/imgs/Sunkanmi's Certificate.png -------------------------------------------------------------------------------- /imgs/arrow.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /imgs/certlify svg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | FY 17 | CERTL 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /imgs/diploma (1).svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /imgs/diploma (2).svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /imgs/diploma (3).svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /imgs/diploma.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /imgs/hero-dsc-about-unilag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSC-Unilag/certlify/191b602c82c8721e8d5d9afe56eee8bc7452c920/imgs/hero-dsc-about-unilag.png -------------------------------------------------------------------------------- /imgs/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSC-Unilag/certlify/191b602c82c8721e8d5d9afe56eee8bc7452c920/imgs/icon.png -------------------------------------------------------------------------------- /imgs/search.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /imgs/user.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Certlify", 3 | "short_name": "Certlify", 4 | "start_url": "views/src/index.html", 5 | "background_color": "#3498DC", 6 | "theme_color": "#34495E", 7 | "orientation": "any", 8 | "display": "standalone", 9 | 10 | "icons": [{ 11 | "src": "imgs/icon.png", 12 | "type": "image/png", 13 | "sizes": "512x512" 14 | }], 15 | 16 | "dir": "ltr", 17 | "lang": "en-US", 18 | "description": "", 19 | "scope": "./", 20 | "screenshots": [{ 21 | "src": "" 22 | }], 23 | "related_applications": [{ 24 | "platform": "play", 25 | "url": "", 26 | "id": "" 27 | }], 28 | "prefer_related_applications": true 29 | } -------------------------------------------------------------------------------- /models/links.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | const uniqueValidator = require("mongoose-unique-validator"); 3 | 4 | // UserSchema 5 | const Schema = mongoose.Schema; 6 | 7 | const boundarySchema = new Schema({ 8 | bottom: Array, 9 | left: Array, 10 | right: Array, 11 | fontsize: Number, 12 | fontfamily:String, 13 | color: String, 14 | }); 15 | 16 | const eligibleUser = new Schema({ 17 | email: { 18 | type: String, 19 | sparse: true 20 | }, 21 | name: String, 22 | status: Boolean, 23 | }); 24 | 25 | const linkSchema = new Schema({ 26 | issuer:String, 27 | name:String, 28 | src:String, 29 | thumb:String, 30 | link: { 31 | type: String, 32 | required: true, 33 | unique: true, 34 | }, 35 | boundary: [boundarySchema], 36 | eligibleUsers: [eligibleUser], 37 | }); 38 | 39 | // uniqueValidator plugin for presave validation of unique fields. Check the docs for more details 40 | linkSchema.plugin(uniqueValidator); 41 | let Link = mongoose.model("link", linkSchema); 42 | 43 | module.exports = Link; 44 | -------------------------------------------------------------------------------- /models/users.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | const uniqueValidator = require("mongoose-unique-validator"); 3 | 4 | // UserSchema 5 | const Schema = mongoose.Schema; 6 | 7 | const UserSchema = new Schema({ 8 | 9 | // The name would be the name of the body or organization issuing certificates. It doesn't matter much for those that want to generate certificate. 10 | name: { 11 | type: String, 12 | }, 13 | email: { 14 | type: String, 15 | unique: true, 16 | }, 17 | passwordhash: { 18 | type: String, 19 | }, 20 | profilePicture:String, 21 | certificateUrls: [String], 22 | confirmed:{ 23 | type:Boolean, 24 | default:false 25 | } 26 | }); 27 | 28 | // uniqueValidator plugin for presave validation of unique fields. Check the docs for more details 29 | UserSchema.plugin(uniqueValidator); 30 | let User = mongoose.model("User", UserSchema); 31 | 32 | module.exports = User; 33 | -------------------------------------------------------------------------------- /out/FontSizer.js.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | JSDoc: Source: FontSizer.js 6 | 7 | 8 | 9 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 |

Source: FontSizer.js

21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 |
29 |
/**
30 |  * Increases font size value by 1
31 |  */
32 | function increaseValue() {
33 |     var value = Number(document.getElementById('number').value);
34 |     value = isNaN(value) ? 0 : value;
35 |     value++;
36 |     document.getElementById('number').value = value;
37 |    // let width = document.getElementById('container').offsetWidth;
38 |     //let height = width / rat;
39 |     boundary.fontsize = value / rat;
40 |     mark();
41 |     console.log(value);
42 | }
43 | 
44 | /**
45 |  * Decreases font size value by 1
46 |  */
47 | function decreaseValue() {
48 |     var value = Number(document.getElementById('number').value);
49 |     value = isNaN(value) ? 0 : value;
50 |     value < 1 ? value = 1 : '';
51 |     value--;
52 |     document.getElementById('number').value = value;
53 |     //let width = document.getElementById('container').offsetWidth;
54 |   //  let height = width / rat;
55 |     boundary.fontsize = value / rat;
56 |     mark();
57 |     console.log(value);
58 | }
59 | 
60 | /**
61 |  * Sets the font to the user selected font
62 |  */
63 | function newfont() {
64 |     var value = Number(document.getElementById('number').value);
65 |     let width = document.getElementById('container').offsetWidth;
66 |     let height = width / rat;
67 |     boundary.fontsize = value / height;
68 |     mark();
69 | }
70 |
71 |
72 | 73 | 74 | 75 | 76 |
77 | 78 | 81 | 82 |
83 | 84 |
85 | Documentation generated by JSDoc 3.6.6 on Sat Oct 31 2020 22:42:09 GMT+0100 (West Africa Standard Time) 86 |
87 | 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /out/fonts/OpenSans-Bold-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSC-Unilag/certlify/191b602c82c8721e8d5d9afe56eee8bc7452c920/out/fonts/OpenSans-Bold-webfont.eot -------------------------------------------------------------------------------- /out/fonts/OpenSans-Bold-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSC-Unilag/certlify/191b602c82c8721e8d5d9afe56eee8bc7452c920/out/fonts/OpenSans-Bold-webfont.woff -------------------------------------------------------------------------------- /out/fonts/OpenSans-BoldItalic-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSC-Unilag/certlify/191b602c82c8721e8d5d9afe56eee8bc7452c920/out/fonts/OpenSans-BoldItalic-webfont.eot -------------------------------------------------------------------------------- /out/fonts/OpenSans-BoldItalic-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSC-Unilag/certlify/191b602c82c8721e8d5d9afe56eee8bc7452c920/out/fonts/OpenSans-BoldItalic-webfont.woff -------------------------------------------------------------------------------- /out/fonts/OpenSans-Italic-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSC-Unilag/certlify/191b602c82c8721e8d5d9afe56eee8bc7452c920/out/fonts/OpenSans-Italic-webfont.eot -------------------------------------------------------------------------------- /out/fonts/OpenSans-Italic-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSC-Unilag/certlify/191b602c82c8721e8d5d9afe56eee8bc7452c920/out/fonts/OpenSans-Italic-webfont.woff -------------------------------------------------------------------------------- /out/fonts/OpenSans-Light-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSC-Unilag/certlify/191b602c82c8721e8d5d9afe56eee8bc7452c920/out/fonts/OpenSans-Light-webfont.eot -------------------------------------------------------------------------------- /out/fonts/OpenSans-Light-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSC-Unilag/certlify/191b602c82c8721e8d5d9afe56eee8bc7452c920/out/fonts/OpenSans-Light-webfont.woff -------------------------------------------------------------------------------- /out/fonts/OpenSans-LightItalic-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSC-Unilag/certlify/191b602c82c8721e8d5d9afe56eee8bc7452c920/out/fonts/OpenSans-LightItalic-webfont.eot -------------------------------------------------------------------------------- /out/fonts/OpenSans-LightItalic-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSC-Unilag/certlify/191b602c82c8721e8d5d9afe56eee8bc7452c920/out/fonts/OpenSans-LightItalic-webfont.woff -------------------------------------------------------------------------------- /out/fonts/OpenSans-Regular-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSC-Unilag/certlify/191b602c82c8721e8d5d9afe56eee8bc7452c920/out/fonts/OpenSans-Regular-webfont.eot -------------------------------------------------------------------------------- /out/fonts/OpenSans-Regular-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSC-Unilag/certlify/191b602c82c8721e8d5d9afe56eee8bc7452c920/out/fonts/OpenSans-Regular-webfont.woff -------------------------------------------------------------------------------- /out/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | JSDoc: Home 6 | 7 | 8 | 9 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 |

Home

21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |

30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 |
51 | 52 | 55 | 56 |
57 | 58 |
59 | Documentation generated by JSDoc 3.6.6 on Sat Oct 31 2020 22:42:09 GMT+0100 (West Africa Standard Time) 60 |
61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /out/main.js.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | JSDoc: Source: main.js 6 | 7 | 8 | 9 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 |

Source: main.js

21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 |
29 |
/**
 30 |  *  Loader container element 
 31 |  */
 32 | const containerLoad = document.querySelector(".loader");
 33 | 
 34 | /**
 35 |  * collectors modal element when "Collectors" button is clicked
 36 |  */
 37 | const modal = document.querySelector(".collectors-modal");
 38 | 
 39 | /**
 40 |  * Hides Loader
 41 |  */
 42 | function HideLoader() {
 43 |     containerLoad.classList.toggle("zero-opacity");
 44 |     setTimeout(() => {
 45 |         containerLoad.classList.toggle("hide");
 46 |     }, 350);
 47 | }
 48 | 
 49 | /**
 50 |  * Shows loader
 51 |  */
 52 | function ShowLoader() {
 53 |     containerLoad.classList.toggle("zero-opacity");
 54 |     containerLoad.classList.toggle("hide");
 55 | }
 56 | 
 57 | /**
 58 |  *  
 59 |  */
 60 | function CopyToClipBoard() {
 61 |     let copyText = document.querySelector("#link");
 62 | 
 63 |     copyText.select();
 64 |     copyText.setSelectionRange(0, 99999); /*For mobile devices*/
 65 | 
 66 |     document.execCommand("copy");
 67 | 
 68 |     alert("Copied Successfully!");
 69 | }
 70 | 
 71 | /**
 72 |  * Hides loader when page has finished rendering.
 73 |  * @type {Window}
 74 |  */
 75 | window.onload = function(){
 76 |     HideLoader();
 77 | }
 78 | 
 79 | /**
 80 |  * Toggles collectors modal to display/hide.
 81 |  */
 82 | function ToggleModal(){
 83 |     modal.classList.toggle("hide");
 84 | }
85 |
86 |
87 | 88 | 89 | 90 | 91 |
92 | 93 | 96 | 97 |
98 | 99 |
100 | Documentation generated by JSDoc 3.6.6 on Sat Oct 31 2020 22:42:09 GMT+0100 (West Africa Standard Time) 101 |
102 | 103 | 104 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /out/scripts/linenumber.js: -------------------------------------------------------------------------------- 1 | /*global document */ 2 | (() => { 3 | const source = document.getElementsByClassName('prettyprint source linenums'); 4 | let i = 0; 5 | let lineNumber = 0; 6 | let lineId; 7 | let lines; 8 | let totalLines; 9 | let anchorHash; 10 | 11 | if (source && source[0]) { 12 | anchorHash = document.location.hash.substring(1); 13 | lines = source[0].getElementsByTagName('li'); 14 | totalLines = lines.length; 15 | 16 | for (; i < totalLines; i++) { 17 | lineNumber++; 18 | lineId = `line${lineNumber}`; 19 | lines[i].id = lineId; 20 | if (lineId === anchorHash) { 21 | lines[i].className += ' selected'; 22 | } 23 | } 24 | } 25 | })(); 26 | -------------------------------------------------------------------------------- /out/scripts/prettify/lang-css.js: -------------------------------------------------------------------------------- 1 | PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\f\r ]+/,null," \t\r\n "]],[["str",/^"(?:[^\n\f\r"\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*"/,null],["str",/^'(?:[^\n\f\r'\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*'/,null],["lang-css-str",/^url\(([^"')]*)\)/i],["kwd",/^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\w-]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*)\s*:/i],["com",/^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//],["com", 2 | /^(?:<\!--|--\>)/],["lit",/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],["lit",/^#[\da-f]{3,6}/i],["pln",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i],["pun",/^[^\s\w"']+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[["kwd",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[["str",/^[^"')]+/]]),["css-str"]); 3 | -------------------------------------------------------------------------------- /out/styles/jsdoc-default.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'Open Sans'; 3 | font-weight: normal; 4 | font-style: normal; 5 | src: url('../fonts/OpenSans-Regular-webfont.eot'); 6 | src: 7 | local('Open Sans'), 8 | local('OpenSans'), 9 | url('../fonts/OpenSans-Regular-webfont.eot?#iefix') format('embedded-opentype'), 10 | url('../fonts/OpenSans-Regular-webfont.woff') format('woff'), 11 | url('../fonts/OpenSans-Regular-webfont.svg#open_sansregular') format('svg'); 12 | } 13 | 14 | @font-face { 15 | font-family: 'Open Sans Light'; 16 | font-weight: normal; 17 | font-style: normal; 18 | src: url('../fonts/OpenSans-Light-webfont.eot'); 19 | src: 20 | local('Open Sans Light'), 21 | local('OpenSans Light'), 22 | url('../fonts/OpenSans-Light-webfont.eot?#iefix') format('embedded-opentype'), 23 | url('../fonts/OpenSans-Light-webfont.woff') format('woff'), 24 | url('../fonts/OpenSans-Light-webfont.svg#open_sanslight') format('svg'); 25 | } 26 | 27 | html 28 | { 29 | overflow: auto; 30 | background-color: #fff; 31 | font-size: 14px; 32 | } 33 | 34 | body 35 | { 36 | font-family: 'Open Sans', sans-serif; 37 | line-height: 1.5; 38 | color: #4d4e53; 39 | background-color: white; 40 | } 41 | 42 | a, a:visited, a:active { 43 | color: #0095dd; 44 | text-decoration: none; 45 | } 46 | 47 | a:hover { 48 | text-decoration: underline; 49 | } 50 | 51 | header 52 | { 53 | display: block; 54 | padding: 0px 4px; 55 | } 56 | 57 | tt, code, kbd, samp { 58 | font-family: Consolas, Monaco, 'Andale Mono', monospace; 59 | } 60 | 61 | .class-description { 62 | font-size: 130%; 63 | line-height: 140%; 64 | margin-bottom: 1em; 65 | margin-top: 1em; 66 | } 67 | 68 | .class-description:empty { 69 | margin: 0; 70 | } 71 | 72 | #main { 73 | float: left; 74 | width: 70%; 75 | } 76 | 77 | article dl { 78 | margin-bottom: 40px; 79 | } 80 | 81 | article img { 82 | max-width: 100%; 83 | } 84 | 85 | section 86 | { 87 | display: block; 88 | background-color: #fff; 89 | padding: 12px 24px; 90 | border-bottom: 1px solid #ccc; 91 | margin-right: 30px; 92 | } 93 | 94 | .variation { 95 | display: none; 96 | } 97 | 98 | .signature-attributes { 99 | font-size: 60%; 100 | color: #aaa; 101 | font-style: italic; 102 | font-weight: lighter; 103 | } 104 | 105 | nav 106 | { 107 | display: block; 108 | float: right; 109 | margin-top: 28px; 110 | width: 30%; 111 | box-sizing: border-box; 112 | border-left: 1px solid #ccc; 113 | padding-left: 16px; 114 | } 115 | 116 | nav ul { 117 | font-family: 'Lucida Grande', 'Lucida Sans Unicode', arial, sans-serif; 118 | font-size: 100%; 119 | line-height: 17px; 120 | padding: 0; 121 | margin: 0; 122 | list-style-type: none; 123 | } 124 | 125 | nav ul a, nav ul a:visited, nav ul a:active { 126 | font-family: Consolas, Monaco, 'Andale Mono', monospace; 127 | line-height: 18px; 128 | color: #4D4E53; 129 | } 130 | 131 | nav h3 { 132 | margin-top: 12px; 133 | } 134 | 135 | nav li { 136 | margin-top: 6px; 137 | } 138 | 139 | footer { 140 | display: block; 141 | padding: 6px; 142 | margin-top: 12px; 143 | font-style: italic; 144 | font-size: 90%; 145 | } 146 | 147 | h1, h2, h3, h4 { 148 | font-weight: 200; 149 | margin: 0; 150 | } 151 | 152 | h1 153 | { 154 | font-family: 'Open Sans Light', sans-serif; 155 | font-size: 48px; 156 | letter-spacing: -2px; 157 | margin: 12px 24px 20px; 158 | } 159 | 160 | h2, h3.subsection-title 161 | { 162 | font-size: 30px; 163 | font-weight: 700; 164 | letter-spacing: -1px; 165 | margin-bottom: 12px; 166 | } 167 | 168 | h3 169 | { 170 | font-size: 24px; 171 | letter-spacing: -0.5px; 172 | margin-bottom: 12px; 173 | } 174 | 175 | h4 176 | { 177 | font-size: 18px; 178 | letter-spacing: -0.33px; 179 | margin-bottom: 12px; 180 | color: #4d4e53; 181 | } 182 | 183 | h5, .container-overview .subsection-title 184 | { 185 | font-size: 120%; 186 | font-weight: bold; 187 | letter-spacing: -0.01em; 188 | margin: 8px 0 3px 0; 189 | } 190 | 191 | h6 192 | { 193 | font-size: 100%; 194 | letter-spacing: -0.01em; 195 | margin: 6px 0 3px 0; 196 | font-style: italic; 197 | } 198 | 199 | table 200 | { 201 | border-spacing: 0; 202 | border: 0; 203 | border-collapse: collapse; 204 | } 205 | 206 | td, th 207 | { 208 | border: 1px solid #ddd; 209 | margin: 0px; 210 | text-align: left; 211 | vertical-align: top; 212 | padding: 4px 6px; 213 | display: table-cell; 214 | } 215 | 216 | thead tr 217 | { 218 | background-color: #ddd; 219 | font-weight: bold; 220 | } 221 | 222 | th { border-right: 1px solid #aaa; } 223 | tr > th:last-child { border-right: 1px solid #ddd; } 224 | 225 | .ancestors, .attribs { color: #999; } 226 | .ancestors a, .attribs a 227 | { 228 | color: #999 !important; 229 | text-decoration: none; 230 | } 231 | 232 | .clear 233 | { 234 | clear: both; 235 | } 236 | 237 | .important 238 | { 239 | font-weight: bold; 240 | color: #950B02; 241 | } 242 | 243 | .yes-def { 244 | text-indent: -1000px; 245 | } 246 | 247 | .type-signature { 248 | color: #aaa; 249 | } 250 | 251 | .name, .signature { 252 | font-family: Consolas, Monaco, 'Andale Mono', monospace; 253 | } 254 | 255 | .details { margin-top: 14px; border-left: 2px solid #DDD; } 256 | .details dt { width: 120px; float: left; padding-left: 10px; padding-top: 6px; } 257 | .details dd { margin-left: 70px; } 258 | .details ul { margin: 0; } 259 | .details ul { list-style-type: none; } 260 | .details li { margin-left: 30px; padding-top: 6px; } 261 | .details pre.prettyprint { margin: 0 } 262 | .details .object-value { padding-top: 0; } 263 | 264 | .description { 265 | margin-bottom: 1em; 266 | margin-top: 1em; 267 | } 268 | 269 | .code-caption 270 | { 271 | font-style: italic; 272 | font-size: 107%; 273 | margin: 0; 274 | } 275 | 276 | .source 277 | { 278 | border: 1px solid #ddd; 279 | width: 80%; 280 | overflow: auto; 281 | } 282 | 283 | .prettyprint.source { 284 | width: inherit; 285 | } 286 | 287 | .source code 288 | { 289 | font-size: 100%; 290 | line-height: 18px; 291 | display: block; 292 | padding: 4px 12px; 293 | margin: 0; 294 | background-color: #fff; 295 | color: #4D4E53; 296 | } 297 | 298 | .prettyprint code span.line 299 | { 300 | display: inline-block; 301 | } 302 | 303 | .prettyprint.linenums 304 | { 305 | padding-left: 70px; 306 | -webkit-user-select: none; 307 | -moz-user-select: none; 308 | -ms-user-select: none; 309 | user-select: none; 310 | } 311 | 312 | .prettyprint.linenums ol 313 | { 314 | padding-left: 0; 315 | } 316 | 317 | .prettyprint.linenums li 318 | { 319 | border-left: 3px #ddd solid; 320 | } 321 | 322 | .prettyprint.linenums li.selected, 323 | .prettyprint.linenums li.selected * 324 | { 325 | background-color: lightyellow; 326 | } 327 | 328 | .prettyprint.linenums li * 329 | { 330 | -webkit-user-select: text; 331 | -moz-user-select: text; 332 | -ms-user-select: text; 333 | user-select: text; 334 | } 335 | 336 | .params .name, .props .name, .name code { 337 | color: #4D4E53; 338 | font-family: Consolas, Monaco, 'Andale Mono', monospace; 339 | font-size: 100%; 340 | } 341 | 342 | .params td.description > p:first-child, 343 | .props td.description > p:first-child 344 | { 345 | margin-top: 0; 346 | padding-top: 0; 347 | } 348 | 349 | .params td.description > p:last-child, 350 | .props td.description > p:last-child 351 | { 352 | margin-bottom: 0; 353 | padding-bottom: 0; 354 | } 355 | 356 | .disabled { 357 | color: #454545; 358 | } 359 | -------------------------------------------------------------------------------- /out/styles/prettify-jsdoc.css: -------------------------------------------------------------------------------- 1 | /* JSDoc prettify.js theme */ 2 | 3 | /* plain text */ 4 | .pln { 5 | color: #000000; 6 | font-weight: normal; 7 | font-style: normal; 8 | } 9 | 10 | /* string content */ 11 | .str { 12 | color: #006400; 13 | font-weight: normal; 14 | font-style: normal; 15 | } 16 | 17 | /* a keyword */ 18 | .kwd { 19 | color: #000000; 20 | font-weight: bold; 21 | font-style: normal; 22 | } 23 | 24 | /* a comment */ 25 | .com { 26 | font-weight: normal; 27 | font-style: italic; 28 | } 29 | 30 | /* a type name */ 31 | .typ { 32 | color: #000000; 33 | font-weight: normal; 34 | font-style: normal; 35 | } 36 | 37 | /* a literal value */ 38 | .lit { 39 | color: #006400; 40 | font-weight: normal; 41 | font-style: normal; 42 | } 43 | 44 | /* punctuation */ 45 | .pun { 46 | color: #000000; 47 | font-weight: bold; 48 | font-style: normal; 49 | } 50 | 51 | /* lisp open bracket */ 52 | .opn { 53 | color: #000000; 54 | font-weight: bold; 55 | font-style: normal; 56 | } 57 | 58 | /* lisp close bracket */ 59 | .clo { 60 | color: #000000; 61 | font-weight: bold; 62 | font-style: normal; 63 | } 64 | 65 | /* a markup tag name */ 66 | .tag { 67 | color: #006400; 68 | font-weight: normal; 69 | font-style: normal; 70 | } 71 | 72 | /* a markup attribute name */ 73 | .atn { 74 | color: #006400; 75 | font-weight: normal; 76 | font-style: normal; 77 | } 78 | 79 | /* a markup attribute value */ 80 | .atv { 81 | color: #006400; 82 | font-weight: normal; 83 | font-style: normal; 84 | } 85 | 86 | /* a declaration */ 87 | .dec { 88 | color: #000000; 89 | font-weight: bold; 90 | font-style: normal; 91 | } 92 | 93 | /* a variable name */ 94 | .var { 95 | color: #000000; 96 | font-weight: normal; 97 | font-style: normal; 98 | } 99 | 100 | /* a function name */ 101 | .fun { 102 | color: #000000; 103 | font-weight: bold; 104 | font-style: normal; 105 | } 106 | 107 | /* Specify class=linenums on a pre to get line numbering */ 108 | ol.linenums { 109 | margin-top: 0; 110 | margin-bottom: 0; 111 | } 112 | -------------------------------------------------------------------------------- /out/styles/prettify-tomorrow.css: -------------------------------------------------------------------------------- 1 | /* Tomorrow Theme */ 2 | /* Original theme - https://github.com/chriskempson/tomorrow-theme */ 3 | /* Pretty printing styles. Used with prettify.js. */ 4 | /* SPAN elements with the classes below are added by prettyprint. */ 5 | /* plain text */ 6 | .pln { 7 | color: #4d4d4c; } 8 | 9 | @media screen { 10 | /* string content */ 11 | .str { 12 | color: #718c00; } 13 | 14 | /* a keyword */ 15 | .kwd { 16 | color: #8959a8; } 17 | 18 | /* a comment */ 19 | .com { 20 | color: #8e908c; } 21 | 22 | /* a type name */ 23 | .typ { 24 | color: #4271ae; } 25 | 26 | /* a literal value */ 27 | .lit { 28 | color: #f5871f; } 29 | 30 | /* punctuation */ 31 | .pun { 32 | color: #4d4d4c; } 33 | 34 | /* lisp open bracket */ 35 | .opn { 36 | color: #4d4d4c; } 37 | 38 | /* lisp close bracket */ 39 | .clo { 40 | color: #4d4d4c; } 41 | 42 | /* a markup tag name */ 43 | .tag { 44 | color: #c82829; } 45 | 46 | /* a markup attribute name */ 47 | .atn { 48 | color: #f5871f; } 49 | 50 | /* a markup attribute value */ 51 | .atv { 52 | color: #3e999f; } 53 | 54 | /* a declaration */ 55 | .dec { 56 | color: #f5871f; } 57 | 58 | /* a variable name */ 59 | .var { 60 | color: #c82829; } 61 | 62 | /* a function name */ 63 | .fun { 64 | color: #4271ae; } } 65 | /* Use higher contrast and text-weight for printable form. */ 66 | @media print, projection { 67 | .str { 68 | color: #060; } 69 | 70 | .kwd { 71 | color: #006; 72 | font-weight: bold; } 73 | 74 | .com { 75 | color: #600; 76 | font-style: italic; } 77 | 78 | .typ { 79 | color: #404; 80 | font-weight: bold; } 81 | 82 | .lit { 83 | color: #044; } 84 | 85 | .pun, .opn, .clo { 86 | color: #440; } 87 | 88 | .tag { 89 | color: #006; 90 | font-weight: bold; } 91 | 92 | .atn { 93 | color: #404; } 94 | 95 | .atv { 96 | color: #060; } } 97 | /* Style */ 98 | /* 99 | pre.prettyprint { 100 | background: white; 101 | font-family: Consolas, Monaco, 'Andale Mono', monospace; 102 | font-size: 12px; 103 | line-height: 1.5; 104 | border: 1px solid #ccc; 105 | padding: 10px; } 106 | */ 107 | 108 | /* Specify class=linenums on a pre to get line numbering */ 109 | ol.linenums { 110 | margin-top: 0; 111 | margin-bottom: 0; } 112 | 113 | /* IE indents via margin-left */ 114 | li.L0, 115 | li.L1, 116 | li.L2, 117 | li.L3, 118 | li.L4, 119 | li.L5, 120 | li.L6, 121 | li.L7, 122 | li.L8, 123 | li.L9 { 124 | /* */ } 125 | 126 | /* Alternate shading for lines */ 127 | li.L1, 128 | li.L3, 129 | li.L5, 130 | li.L7, 131 | li.L9 { 132 | /* */ } 133 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "general-certificates", 3 | "version": "1.0.0", 4 | "description": "A general certificate issuer", 5 | "main": "app.js", 6 | "scripts": { 7 | "dev": "nodemon app", 8 | "start": "node app" 9 | }, 10 | "author": "DSC-Unilag", 11 | "license": "ISC", 12 | "dependencies": { 13 | "@sendgrid/mail": "^7.4.0", 14 | "aws-sdk": "^2.814.0", 15 | "bcryptjs": "^2.4.3", 16 | "cloudinary": "^1.23.0", 17 | "connect-mongo": "^3.2.0", 18 | "cors": "^2.8.5", 19 | "csvtojson": "^2.0.10", 20 | "express": "^4.17.1", 21 | "express-session": "^1.17.1", 22 | "font-picker": "^3.5.1", 23 | "jsonwebtoken": "^8.5.1", 24 | "mongodb": "^3.6.2", 25 | "mongoose": "^5.10.6", 26 | "mongoose-unique-validator": "^2.0.3", 27 | "multer": "^1.4.2", 28 | "nodemailer": "^6.4.16", 29 | "nodemon": "^2.0.6", 30 | "swagger-jsdoc": "^4.2.0", 31 | "swagger-ui-express": "^4.1.4", 32 | "uniqid": "^5.2.0" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /routes/addEligibleUsers.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const addEligibleUsers = require('../controllers/addEligibleUsers'); 3 | 4 | const router = express.Router(); 5 | 6 | router.use(express.urlencoded({ extended: true })); 7 | router.use(express.json()); 8 | 9 | router.post('/addeligibleusers/:link', addEligibleUsers.addNew); 10 | 11 | module.exports = router; 12 | -------------------------------------------------------------------------------- /routes/allviews.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | 3 | const router = express.Router(); 4 | 5 | router.use(express.urlencoded({ extended: true })); 6 | router.use(express.json()); 7 | 8 | router.get('/signup', (req,res)=>{ 9 | res.sendFile(__dirname+"/views/signup.html"); 10 | }); 11 | router.get("/dashboard",(req,res)=>{ 12 | res.sendFile(__dirname+"/views/dashboard.html"); 13 | }) 14 | 15 | module.exports = router; 16 | -------------------------------------------------------------------------------- /routes/createCert.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const createCert = require('../controllers/createCert'); 3 | 4 | const router = express.Router(); 5 | 6 | router.use(express.urlencoded({ extended: true })); 7 | router.use(express.json()); 8 | 9 | router.post("/createcert",createCert); 10 | 11 | module.exports=router; 12 | 13 | -------------------------------------------------------------------------------- /routes/dashboard.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const GetDashboard = require('../controllers/GetDashboard'); 3 | 4 | const router = express.Router(); 5 | 6 | router.use(express.urlencoded({ extended: true })); 7 | router.use(express.json()); 8 | 9 | router.get('/getdashboard', GetDashboard); 10 | 11 | module.exports = router; -------------------------------------------------------------------------------- /routes/generate.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const generate = require('../controllers/generate'); 3 | const router = express.Router(); 4 | 5 | router.use(express.urlencoded({ extended: true })); 6 | router.use(express.json()); 7 | 8 | router.get("/name",generate.name); 9 | router.post("/generate/:link",generate.emailverification); 10 | router.get("/details",generate.details); 11 | router.post("/certgenerate",generate.generate); 12 | module.exports=router; -------------------------------------------------------------------------------- /routes/manage.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const manage = require('../controllers/manage'); 3 | 4 | const router = express.Router(); 5 | 6 | router.use(express.urlencoded({ extended: true })); 7 | router.use(express.json()); 8 | 9 | router.get("/manage/:link/getcollectors",manage.getCollectors) 10 | router.get("/manage/:link/details",manage.details) 11 | router.post("/manage/:link/update",manage.update) 12 | 13 | module.exports=router; -------------------------------------------------------------------------------- /routes/userRoutes.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const UserController = require('../controllers/UserController'); 3 | 4 | const router = express.Router(); 5 | 6 | router.use(express.urlencoded({ extended: true })); 7 | router.use(express.json()); 8 | 9 | //router.get('/register', UserController.getRegister); 10 | 11 | /** 12 | * swagger 13 | * /register: 14 | * post: 15 | * description: Endpoint to Register Users 16 | * requestBody: 17 | * required:true 18 | * content: 19 | * application/json: 20 | * schema: 21 | * type:object 22 | * required: 23 | * - name 24 | * - email 25 | * - password 26 | * responses: 27 | * '200': 28 | * description: A successful response 29 | */ 30 | router.post('/register', UserController.register); 31 | 32 | // router.get('/login', UserController.getLogin); 33 | router.post('/login', UserController.login); 34 | // cater for anonymous users 35 | router.get("/anon",UserController.anon); 36 | // check the login status of a user; 37 | router.get("/status",UserController.status); 38 | router.get("/logout",UserController.logout); 39 | router.post("/emailer",UserController.userverification); 40 | router.post("/emailrecovery",UserController.emailrecovery); 41 | router.post("/passwordupdate/:jwt",UserController.passwordupdate); 42 | module.exports = router; -------------------------------------------------------------------------------- /views/404-page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 14 | 15 | 16 | Certlify 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | 45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 | 54 |
55 | 56 |
57 | 58 |
59 | 60 |

4

61 | certificate image 62 |

4

63 |
64 |
65 |
66 |
67 | 68 |
69 |
70 |
71 | 72 |
73 |

Page Not Found

74 |

We suggest you return to homepage while we fix the problem

75 | Return to Homepage 76 |
77 | 78 |
79 | 80 | 85 | 86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 | 96 | 97 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /views/certificator.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 14 | 15 | 16 | Generate Certificate 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 | 53 |
54 |
55 | 56 | user icon 57 | 58 | 59 | 60 | 65 | 66 | 76 | 77 |
78 |

79 |
80 |
81 | 82 |
83 |
84 |

Enter Bearers name

85 |

Hi there! Who is this certificate being issued to?

86 | 87 |
88 | 90 | 91 |

92 | 95 |
96 |
97 | 106 |
107 | 109 |
110 |
111 |
112 | 113 | 125 | 126 | 127 | 152 | 153 | 154 | 155 | -------------------------------------------------------------------------------- /views/dashboard.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 14 | 15 | 16 | Dashboard 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 | 51 |
52 |
53 | 54 | user icon 55 | 56 |
57 | 58 | 59 |
60 | 61 | 62 | 63 | 68 | 69 | 81 | 82 |
83 |
84 | 85 |
86 |
87 |
88 | 89 |
90 | 91 | 92 |
93 | 94 | 95 | 140 | 141 | 142 | 143 | -------------------------------------------------------------------------------- /views/debug.log: -------------------------------------------------------------------------------- 1 | [1004/154731.181:ERROR:crash_report_database_win.cc(428)] unexpected header 2 | [1004/155745.223:ERROR:crash_report_database_win.cc(428)] unexpected header 3 | [1004/155745.652:ERROR:crash_report_database_win.cc(428)] unexpected header 4 | [1004/160232.101:ERROR:crash_report_database_win.cc(428)] unexpected header 5 | -------------------------------------------------------------------------------- /views/emailverify.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 14 | 15 | 16 | Certlify 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 | 49 |
50 |
51 | 52 | user icon 53 | 54 | 55 | 56 | 61 | 62 | 71 | 72 |
73 |

74 |
75 |
76 | 77 |
78 |
79 |

Enter Email address

80 |

Hi there! Please enter the email address recognized by your issuer

81 | 82 |
83 | 85 | 86 |

87 | 90 |
91 |
92 |
93 | 95 | 110 | 111 | 160 | 161 | 162 | 163 | -------------------------------------------------------------------------------- /views/forgot-email.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 14 | 15 | 16 | Email recovery 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | 55 | 56 |
57 | 58 |
59 |
60 |

Enter your email to recover password

61 |
62 | 64 | 65 | 68 |
69 |
70 |
71 |
72 |

73 | Want to contribute? 74 | 75 | github logo 76 | 77 |

78 |

Built by dsc unilag

80 |

81 |
82 | 83 | 84 | 110 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /views/imgs/DSC copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSC-Unilag/certlify/191b602c82c8721e8d5d9afe56eee8bc7452c920/views/imgs/DSC copy.png -------------------------------------------------------------------------------- /views/imgs/Group 297.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSC-Unilag/certlify/191b602c82c8721e8d5d9afe56eee8bc7452c920/views/imgs/Group 297.png -------------------------------------------------------------------------------- /views/imgs/Group 298-edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSC-Unilag/certlify/191b602c82c8721e8d5d9afe56eee8bc7452c920/views/imgs/Group 298-edit.png -------------------------------------------------------------------------------- /views/imgs/Group 298.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSC-Unilag/certlify/191b602c82c8721e8d5d9afe56eee8bc7452c920/views/imgs/Group 298.png -------------------------------------------------------------------------------- /views/imgs/Group 298.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /views/imgs/IMG-20200923-WA0214.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /views/imgs/Icon svg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /views/imgs/Sunkanmi's Certificate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSC-Unilag/certlify/191b602c82c8721e8d5d9afe56eee8bc7452c920/views/imgs/Sunkanmi's Certificate.png -------------------------------------------------------------------------------- /views/imgs/arrow.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /views/imgs/badge.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /views/imgs/certlify svg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | FY 17 | CERTL 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /views/imgs/code logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSC-Unilag/certlify/191b602c82c8721e8d5d9afe56eee8bc7452c920/views/imgs/code logo.jpg -------------------------------------------------------------------------------- /views/imgs/copy.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /views/imgs/diploma (1).svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /views/imgs/diploma (2).svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /views/imgs/diploma (3).svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /views/imgs/diploma.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /views/imgs/hero-dsc-about-unilag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSC-Unilag/certlify/191b602c82c8721e8d5d9afe56eee8bc7452c920/views/imgs/hero-dsc-about-unilag.png -------------------------------------------------------------------------------- /views/imgs/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSC-Unilag/certlify/191b602c82c8721e8d5d9afe56eee8bc7452c920/views/imgs/icon.png -------------------------------------------------------------------------------- /views/imgs/mark-github-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSC-Unilag/certlify/191b602c82c8721e8d5d9afe56eee8bc7452c920/views/imgs/mark-github-512.png -------------------------------------------------------------------------------- /views/imgs/search.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /views/imgs/share-icons/facebook.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /views/imgs/share-icons/twitter.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /views/imgs/share-icons/whatsapp.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /views/imgs/share.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /views/imgs/tutorial.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSC-Unilag/certlify/191b602c82c8721e8d5d9afe56eee8bc7452c920/views/imgs/tutorial.png -------------------------------------------------------------------------------- /views/imgs/tutorial2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSC-Unilag/certlify/191b602c82c8721e8d5d9afe56eee8bc7452c920/views/imgs/tutorial2.png -------------------------------------------------------------------------------- /views/imgs/user.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /views/imgs/warning.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /views/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 14 | 15 | 16 | Certlify 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 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 | 72 |
73 | 74 |
75 | 76 | certificate image 77 | 78 |
79 |
80 |
81 |
82 | 83 |
84 |
85 |
86 | 87 |
88 |

Welcome to the Certlify! 89 |
90 | Certificates on the go. 91 |

92 |

Easily upload and generate certificates at your convenience, anywhere and anytime with just your email 📧.

93 |

Click on the button below to get started!

94 | 95 | Get Started 96 |
97 |
98 | 99 |
100 |

101 | Want to contribute? 102 | 103 | github logo 104 | 105 |

106 |

Built by dsc unilag

107 |

108 |
109 | 110 | 111 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /views/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 14 | 15 | 16 | Login 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | 55 | 56 |
57 | 58 |
59 |
60 |

Login

61 |

Hi there! Kindly enter your login details

62 | 63 |
64 | 66 | 68 | 69 |

70 | 73 |
74 | 75 | 78 |

forgot password? Password recovery

79 |

Don't have an account? Sign up

80 |
81 |
82 | 83 |
84 |

85 | Want to contribute? 86 | 87 | github logo 88 | 89 |

90 |

Built by dsc unilag

91 |

92 |
93 | 94 | 135 | 136 | 137 | 166 | 167 | 168 | 169 | -------------------------------------------------------------------------------- /views/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Certlify", 3 | "short_name": "Certlify", 4 | "start_url": "index.html", 5 | "background_color": "#3498DC", 6 | "theme_color": "#34495E", 7 | "orientation": "any", 8 | "display": "standalone", 9 | 10 | "icons": [{ 11 | "src": "imgs/icon.png", 12 | "type": "image/png", 13 | "sizes": "512x512" 14 | }], 15 | 16 | "dir": "ltr", 17 | "lang": "en-US", 18 | "description": "", 19 | "scope": "./", 20 | "screenshots": [{ 21 | "src": "" 22 | }], 23 | "related_applications": [{ 24 | "platform": "play", 25 | "url": "", 26 | "id": "" 27 | }], 28 | "prefer_related_applications": true 29 | } -------------------------------------------------------------------------------- /views/password-reset.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 14 | 15 | 16 | Password Reset 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | 55 | 56 |
57 | 58 |
59 |
60 |

Enter your new password

61 |
62 | 64 | 66 | 67 | 70 |
71 |
72 |
73 |
74 |

75 | Want to contribute? 76 | 77 | github logo 78 | 79 |

80 |

Built by dsc unilag

81 |

82 |
83 | 84 | 85 | 132 | 133 | 134 | 135 | 136 | -------------------------------------------------------------------------------- /views/signup.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 14 | 15 | 16 | Sign Up 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | 55 | 56 |
57 | 58 |
59 |
60 |

Sign up

61 |

Hi there! Kindly enter the following details to create an account

62 | 63 |
64 | 66 | 67 | 69 | 71 | 73 | 74 | 77 |
78 |

Already have an account? Login

79 |
80 |
81 |
82 |

83 | Want to contribute? 84 | 85 | github logo 86 | 87 |

88 |

Built by dsc unilag

89 |

90 |
91 | 92 | 93 | 144 | 145 | 159 | 160 | 161 | 162 | -------------------------------------------------------------------------------- /views/site.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Certlify", 3 | "short_name": "Certlify", 4 | "icons": [ 5 | { 6 | "src": "imgs/icon.png", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | }, 10 | { 11 | "src": "imgs/icon.png", 12 | "sizes": "512x512", 13 | "type": "image/png" 14 | } 15 | ], 16 | "theme_color": "#ffffff", 17 | "background_color": "#ffffff", 18 | "start_url": "index.html", 19 | "display": "standalone" 20 | } -------------------------------------------------------------------------------- /views/src/css/animations.css: -------------------------------------------------------------------------------- 1 | @keyframes wobble { 2 | 0% { 3 | border-top-left-radius: 40% 80%; 4 | border-top-right-radius: 40% 30%; 5 | border-bottom-left-radius: 60% 30%; 6 | border-bottom-right-radius: 20% 90%; 7 | } 8 | 9 | 25% { 10 | border-top-left-radius: 45% 75%; 11 | border-top-right-radius: 45% 25%; 12 | border-bottom-left-radius: 65% 25%; 13 | border-bottom-right-radius: 25% 85%; 14 | } 15 | 16 | 50% { 17 | border-top-left-radius: 50% 70%; 18 | border-top-right-radius: 50% 20%; 19 | border-bottom-left-radius: 70% 20%; 20 | border-bottom-right-radius: 30% 80%; 21 | } 22 | 23 | 75% { 24 | border-top-left-radius: 45% 75%; 25 | border-top-right-radius: 45% 25%; 26 | border-bottom-left-radius: 55% 25%; 27 | border-bottom-right-radius: 25% 85%; 28 | } 29 | 30 | 100% { 31 | border-top-left-radius: 40% 80%; 32 | border-top-right-radius: 40% 30%; 33 | border-bottom-left-radius: 60% 30%; 34 | border-bottom-right-radius: 20% 90%; 35 | } 36 | } 37 | 38 | @keyframes change-color { 39 | 0% { 40 | background-color: #488af7; 41 | } 42 | 43 | 25% { 44 | background-color: #6da1f5; 45 | } 46 | 47 | 50%{ 48 | background-color: gold; 49 | } 50 | 51 | 75%{ 52 | background-color: #f54d3e; 53 | } 54 | 55 | 100% { 56 | background-color: #488af7; 57 | } 58 | } 59 | 60 | @keyframes rotate { 61 | 100% { 62 | transform: rotate(360deg); 63 | } 64 | } 65 | 66 | @keyframes move-in-out-1 { 67 | 0% { 68 | top: -1rem; 69 | } 70 | 71 | 50% { 72 | top: 2rem; 73 | } 74 | 75 | 100% { 76 | top: -1rem; 77 | } 78 | } 79 | 80 | @keyframes move-in-out-2 { 81 | 0% { 82 | right: -1rem; 83 | } 84 | 85 | 50% { 86 | right: 2rem; 87 | } 88 | 89 | 100% { 90 | right: -1rem; 91 | } 92 | } 93 | 94 | @keyframes move-in-out-3 { 95 | 0% { 96 | right: 3rem; 97 | } 98 | 99 | 50% { 100 | right: -1rem; 101 | } 102 | 103 | 100% { 104 | right: 3rem; 105 | } 106 | } 107 | 108 | @keyframes move-in-out-4 { 109 | 0% { 110 | top: 3rem; 111 | } 112 | 113 | 50% { 114 | top: -1rem; 115 | } 116 | 117 | 100% { 118 | top: 3rem; 119 | } 120 | } 121 | 122 | @keyframes fade-out{ 123 | 100%{ 124 | opacity: 0; 125 | } 126 | } -------------------------------------------------------------------------------- /views/src/css/certificate-gen.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'Nunito', Verdana, sans-serif; 3 | src: url("./fonts/OpenSans-Regular.ttf"); 4 | } 5 | 6 | * { 7 | font-family: 'Nunito', Verdana, sans-serif; 8 | margin: 0; 9 | padding: 0; 10 | box-sizing: border-box; 11 | font-size: 1rem; 12 | scroll-behavior: smooth; 13 | } 14 | 15 | html, 16 | body { 17 | color: #098dff; 18 | font-size: 1rem; 19 | line-height: 1.5; 20 | letter-spacing: 0.12rem; 21 | word-spacing: 0.16rem; 22 | } 23 | 24 | body { 25 | display: grid; 26 | position: relative; 27 | width: 100%; 28 | height: -webkit-fill-available; 29 | grid-template-columns: 100%; 30 | grid-template-rows: auto auto; 31 | justify-content: center; 32 | } 33 | 34 | /* Custom Scroll-bar */ 35 | ::-webkit-scrollbar { 36 | width: 1.2rem; 37 | } 38 | 39 | ::-webkit-scrollbar-track { 40 | box-shadow: inset 0 0 7px lightgrey; 41 | border-radius: 2rem; 42 | transition: all 90ms ease-in; 43 | 44 | } 45 | 46 | ::-webkit-scrollbar-thumb { 47 | background-color: #4285F4; 48 | border-radius: 2rem; 49 | transition: all 90ms ease-in; 50 | } 51 | 52 | ::-webkit-scrollbar-thumb:hover { 53 | background-color: #2262c7; 54 | } 55 | 56 | main { 57 | display: grid; 58 | position: relative; 59 | width: 100%; 60 | grid-template-columns: 100%; 61 | grid-template-rows: auto auto; 62 | justify-items: center; 63 | } 64 | 65 | main span { 66 | display: flex; 67 | position: relative; 68 | justify-content: center; 69 | align-items: center; 70 | width: 45%; 71 | } 72 | 73 | main span img { 74 | width: 100%; 75 | height: auto; 76 | } 77 | 78 | header { 79 | display: grid; 80 | grid-template-columns: 100%; 81 | grid-template-rows: auto auto; 82 | justify-content: center; 83 | align-items: center; 84 | margin-bottom: 1.5rem; 85 | } 86 | 87 | header span { 88 | display: flex; 89 | flex-wrap: wrap; 90 | justify-content: center; 91 | align-items: center; 92 | height: 6.7rem; 93 | } 94 | 95 | header .logo img { 96 | width: 20rem; 97 | position: relative; 98 | z-index: -1; 99 | bottom: 4.5rem; 100 | left: 0.2rem; 101 | } 102 | 103 | header .section-links { 104 | width: 100%; 105 | display: flex; 106 | justify-content: end; 107 | align-items: center; 108 | justify-self: center; 109 | transition: all 400ms ease-in; 110 | } 111 | 112 | ul { 113 | display: grid; 114 | width: 100%; 115 | align-items: end; 116 | grid-template-rows: 100%; 117 | justify-content: end; 118 | } 119 | 120 | ul li { 121 | list-style-type: none; 122 | justify-self: center; 123 | display: flex; 124 | width: 9rem; 125 | height: 5rem; 126 | text-align: center; 127 | justify-content: center; 128 | align-items: flex-end; 129 | } 130 | 131 | ul li a { 132 | width: 100%; 133 | text-decoration: none; 134 | transition: all 80ms ease-in; 135 | } 136 | 137 | header .section-links ul li a:hover { 138 | color: #fbbf09; 139 | } 140 | 141 | header .section-links ul li a:focus { 142 | color: #daa916; 143 | } 144 | 145 | header .section-links ul li a:active { 146 | color: #eed487; 147 | } 148 | 149 | header .section-links ul { 150 | justify-self: end; 151 | } 152 | 153 | header .section-links ul li a { 154 | padding: 0.8rem; 155 | font-size: 1.1rem; 156 | } 157 | 158 | header .section-links ul .gen-cert { 159 | position: relative; 160 | } 161 | 162 | header .section-links ul li .active-cert { 163 | background-color: #FBBC04; 164 | width: 11rem; 165 | height: 0.2rem; 166 | position: absolute; 167 | border: none; 168 | bottom: 0.3rem; 169 | right: 0; 170 | left: 2rem; 171 | } 172 | 173 | main .landing-page-section { 174 | display: grid; 175 | height: auto; 176 | text-align: center; 177 | justify-items: center; 178 | align-items: center; 179 | grid-template-columns: auto; 180 | grid-template-rows: 7rem 3rem 2rem 7rem; 181 | } 182 | 183 | main .landing-page-section h1 { 184 | font-weight: 600; 185 | font-size: 1.13rem; 186 | color: #4285F4; 187 | } 188 | 189 | 190 | main .landing-page-section p { 191 | text-align: center; 192 | font-size: 0.9rem; 193 | font-weight: 600; 194 | padding: 0.3rem; 195 | color: black; 196 | align-self: start; 197 | } 198 | 199 | a { 200 | text-decoration: none; 201 | color: #098dff; 202 | cursor: pointer; 203 | } 204 | 205 | .landing-page-section a, 206 | .sign-log { 207 | display: flex; 208 | justify-content: center; 209 | align-items: center; 210 | box-shadow: 1px 4px 5px lightgrey; 211 | border: none; 212 | color: white; 213 | width: 12.25rem; 214 | height: 2.5rem; 215 | background-color: #4285F4; 216 | transition: 300ms all ease-in; 217 | } 218 | 219 | .sign-log { 220 | width: 85%; 221 | margin-top: 1rem; 222 | cursor: pointer; 223 | } 224 | 225 | .landing-page-section a:hover, 226 | .sign-log:hover { 227 | background-color: #619bf7; 228 | } 229 | 230 | .landing-page-section a:focus, 231 | .sign-log:focus { 232 | background-color: #1f74fc; 233 | } 234 | 235 | .landing-page-section a:active, 236 | .sign-log:active { 237 | background-color: #2e7eff; 238 | cursor: wait; 239 | } 240 | 241 | input { 242 | width: 85%; 243 | height: 3rem; 244 | border: 1.7px solid #4285F4; 245 | padding-left: 1.5rem; 246 | margin-bottom: 1rem; 247 | border-radius: 0.3rem; 248 | font-size: 0.9rem; 249 | } 250 | 251 | /* Generated cert link */ 252 | 253 | 254 | .sign-page-section { 255 | display: grid; 256 | justify-items: center; 257 | align-content: center; 258 | grid-template-columns: minmax(3rem, 100%); 259 | grid-template-rows: auto auto auto auto auto auto; 260 | } 261 | 262 | .sign-page-section p { 263 | color: #707070; 264 | margin: 1rem 0; 265 | text-align: center; 266 | width: 100%; 267 | } 268 | 269 | .sign-page-section form { 270 | display: grid; 271 | justify-items: center; 272 | align-content: center; 273 | grid-template-columns: minmax(auto, 60rem) 50%; 274 | grid-template-rows: auto auto; 275 | margin: 0.1rem 0rem 2rem 0rem; 276 | } 277 | 278 | 279 | 280 | .sign-page-section .form-input { 281 | grid-template-columns: minmax(auto, 60rem); 282 | } 283 | 284 | .sign-page-section h1 { 285 | font-size: 1.5rem; 286 | text-align: center; 287 | width: 100%; 288 | font-weight: bolder; 289 | } 290 | 291 | .sign-page-section .second-text { 292 | text-align: center; 293 | padding: 1rem; 294 | width: 100%; 295 | } 296 | 297 | #email-input .icon { 298 | margin: 0.2rem 0.5rem; 299 | } 300 | 301 | #generate { 302 | display: flex; 303 | flex-wrap: wrap; 304 | justify-content: center; 305 | margin: 5rem 0rem; 306 | } 307 | 308 | /* 309 | ellispse curve code 310 | */ 311 | 312 | .ellipse-curve { 313 | width: 15rem; 314 | position: fixed; 315 | overflow: hidden; 316 | z-index: -1; 317 | bottom: -7rem; 318 | right: 0; 319 | transform: rotate(25deg); 320 | height: 15rem; 321 | display: inline-block; 322 | } 323 | 324 | .top-left { 325 | transform: rotate(223deg); 326 | top: -7.8rem; 327 | left: -9.5rem; 328 | } 329 | 330 | .first-line, 331 | .second-line, 332 | .third-line { 333 | width: 23.25rem; 334 | height: 27rem; 335 | position: absolute; 336 | overflow: hidden; 337 | border-top-left-radius: 65% 80%; 338 | border-bottom-left-radius: 35% 20%; 339 | } 340 | 341 | .first-line { 342 | border: 1px solid #0F9D58; 343 | } 344 | 345 | .second-line { 346 | border: 1px solid #4285F4; 347 | top: 1.5rem; 348 | } 349 | 350 | .third-line { 351 | border: 1px solid #FBBC04; 352 | top: 3rem; 353 | } 354 | 355 | .custom-cir { 356 | width: 3rem; 357 | height: 3rem; 358 | background-color: aliceblue; 359 | position: absolute; 360 | border-radius: 50%; 361 | right: 0rem; 362 | z-index: -3; 363 | bottom: 1rem; 364 | } 365 | 366 | .cir-left { 367 | right: 0rem; 368 | left: 0; 369 | bottom: 11rem; 370 | } 371 | 372 | .custom-ellipse { 373 | position: absolute; 374 | z-index: -3; 375 | background-color: aliceblue; 376 | width: 22rem; 377 | height: 22rem; 378 | border-top-left-radius: 40% 80%; 379 | border-top-right-radius: 40% 30%; 380 | border-bottom-left-radius: 60% 30%; 381 | border-bottom-right-radius: 20% 90%; 382 | } 383 | 384 | #password-message, 385 | #email-message { 386 | color: red; 387 | display: none; 388 | } 389 | 390 | footer { 391 | display: flex; 392 | justify-content: flex-start; 393 | margin-top: 1.5rem; 394 | padding-left: 1.5rem; 395 | align-items: center; 396 | width: 100%; 397 | height: 2rem; 398 | } 399 | 400 | footer a { 401 | width: 3rem; 402 | text-decoration: none; 403 | } 404 | 405 | footer a img { 406 | width: 100%; 407 | height: auto; 408 | } 409 | 410 | @media screen and (min-width: 40rem) { 411 | header #logo img { 412 | bottom: 4rem; 413 | } 414 | } 415 | 416 | @media screen and (min-width: 45rem) { 417 | main span img { 418 | width: 60%; 419 | } 420 | 421 | .sign-page-section form { 422 | width: 50rem; 423 | } 424 | 425 | .sign-page-section #email-input { 426 | grid-template-columns: minmax(auto, 60rem) 50%; 427 | justify-content: center; 428 | } 429 | 430 | #regenerate { 431 | width: 24rem; 432 | justify-self: center; 433 | } 434 | } 435 | 436 | @media screen and (min-width: 62.3125rem) { 437 | main span img { 438 | width: 15rem; 439 | } 440 | 441 | .sign-page-section form { 442 | width: 55.125rem; 443 | } 444 | } -------------------------------------------------------------------------------- /views/src/css/certificate.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'Nunito', Verdana, sans-serif; 3 | src: url("./fonts/OpenSans-Regular.ttf"); 4 | } 5 | 6 | * { 7 | font-family: 'Nunito', Verdana, sans-serif; 8 | margin: 0; 9 | padding: 0; 10 | box-sizing: border-box; 11 | scroll-behavior: smooth; 12 | } 13 | 14 | html, 15 | body { 16 | color: #098dff; 17 | font-size: 1rem; 18 | line-height: 1.5; 19 | letter-spacing: 0.12rem; 20 | word-spacing: 0.16rem; 21 | display: flex; 22 | flex-direction: column; 23 | } 24 | 25 | ::-webkit-scrollbar { 26 | width: 1.3rem; 27 | } 28 | 29 | ::-webkit-scrollbar-track { 30 | box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3); 31 | } 32 | 33 | ::-webkit-scrollbar-thumb { 34 | background-color: #fbbc04; 35 | border-radius: 1.5rem; 36 | transition: 90ms all ease-in; 37 | } 38 | 39 | ::-webkit-scrollbar-thumb:hover { 40 | background-color: #ae8407; 41 | } 42 | 43 | header { 44 | background-color: #098dff; 45 | display: flex; 46 | flex-direction: column; 47 | align-self: center; 48 | justify-content: space-between; 49 | width: 100%; 50 | height: 100px; 51 | padding-left: 10%; 52 | padding-right: 10%; 53 | } 54 | .images { 55 | display: flex; 56 | justify-content: space-between; 57 | align-items: center; 58 | } 59 | 60 | header #profile-image { 61 | display: flex; 62 | justify-content: flex-end; 63 | align-items: center; 64 | width: 100%; 65 | height: 100px; 66 | } 67 | 68 | header #profile-image img { 69 | align-self: center; 70 | width: 2.8rem; 71 | height: auto; 72 | border-radius: 50%; 73 | border: 1px solid; 74 | } 75 | #certificate-header { 76 | margin-top: 10px; 77 | font-size: 20px; 78 | text-align: center; 79 | } 80 | #upload-div { 81 | display: flex; 82 | justify-content: center; 83 | align-items: center; 84 | width: 60vw; 85 | max-width: 600px; 86 | height: 40vw; 87 | max-height: 400px; 88 | border: 1px dashed #4285f4; 89 | opacity: 1; 90 | } 91 | #file { 92 | display: none; 93 | } 94 | .upload-style { 95 | width: 70%; 96 | height: 40px; 97 | color: white; 98 | text-align: center; 99 | font-size: 10px; 100 | background: #4285f4 0% 0% no-repeat padding-box; 101 | border-radius: 7px; 102 | opacity: 1; 103 | } 104 | .main-upload { 105 | display: flex; 106 | height: auto; 107 | width: 100%; 108 | flex-direction: row; 109 | justify-content: center; 110 | } 111 | #container { 112 | display:none; 113 | width: 60%; 114 | margin: auto; 115 | display: flex; 116 | flex-direction: column; 117 | justify-content: center; 118 | align-items: center; 119 | } 120 | 121 | .controls { 122 | display: flex; 123 | justify-content: center; 124 | } 125 | 126 | .button { 127 | width: 100px; 128 | padding: 7px; 129 | text-align: center; 130 | border: 1px solid #4285f4; 131 | border-radius: 7px; 132 | margin: 4px; 133 | } 134 | 135 | .left-panel { 136 | display: flex; 137 | flex-direction: column; 138 | margin-top: 4px; 139 | margin-right:10px; 140 | } 141 | .format { 142 | display: flex; 143 | flex-direction: row; 144 | justify-content: space-between; 145 | margin-top: 4px; 146 | } 147 | 148 | .right-panel { 149 | position: relative; 150 | height:auto; 151 | display: flex; 152 | margin-left: 10px; 153 | } 154 | .stick { 155 | position: relative; 156 | border: 0.2px solid black; 157 | width: 0px; 158 | height: 70px; 159 | background-color: black; 160 | margin-left: 4px; 161 | opacity: 0.43; 162 | } 163 | .stack { 164 | display: flex; 165 | flex-direction: column; 166 | align-items: center; 167 | font-size: 8px; 168 | } 169 | .dropbtn { 170 | background: #9cbff9 0% 0% no-repeat padding-box; 171 | padding: 10px; 172 | width: 100px; 173 | font-size: 12px; 174 | border-radius: 5px; 175 | opacity: 1; 176 | } 177 | .dropbtn:hover, 178 | .dropbtn:focus { 179 | background-color: skyblue; 180 | } 181 | #myInput { 182 | box-sizing: border-box; 183 | font-size: 16px; 184 | padding: 10px 15px 10px 40px; 185 | border: 1px solid skyblue; 186 | border-bottom: 1px solid #ddd; 187 | } 188 | #myInput:focus { 189 | outline: 3px solid #ddd; 190 | } 191 | .dropdown { 192 | position: relative; 193 | display: inline-block; 194 | } 195 | .dropdown-content { 196 | display: none; 197 | position: absolute; 198 | background-color: #f6f6f6; 199 | min-width: 230px; 200 | border: 1px solid #ddd; 201 | z-index: 1; 202 | } 203 | .dropdown-content a { 204 | color: #16449b; 205 | padding: 5px 10px; 206 | font-size: 10px; 207 | text-decoration: none; 208 | display: block; 209 | } 210 | #myDropdown { 211 | height: 20vh; 212 | overflow: scroll; 213 | } 214 | .dropdown-content a:hover { 215 | background-color: #f1f1f1; 216 | } 217 | .show { 218 | display: block; 219 | } 220 | .hide{ 221 | display:none; 222 | } 223 | 224 | form { 225 | display: flex; 226 | flex-direction: row; 227 | } 228 | 229 | .value-button { 230 | position: relative; 231 | display: inline-block; 232 | border: 1px solid #ddd; 233 | margin: 0px; 234 | width: 40px; 235 | height: auto; 236 | text-align: center; 237 | vertical-align: middle; 238 | padding: 11px 0; 239 | background: #9cbff9 0% 0% no-repeat padding-box; 240 | border-radius: 0px 5px 5px 0px; 241 | opacity: 1; 242 | -webkit-touch-callout: none; 243 | -webkit-user-select: none; 244 | -khtml-user-select: none; 245 | -moz-user-select: none; 246 | -ms-user-select: none; 247 | user-select: none; 248 | } 249 | 250 | .value-button:hover { 251 | cursor: pointer; 252 | } 253 | 254 | form #decrease { 255 | margin-right: -4px; 256 | border-radius: 8px 0 0 8px; 257 | } 258 | 259 | form #increase { 260 | margin-left: -4px; 261 | border-radius: 0 8px 8px 0; 262 | } 263 | 264 | form #input-wrap { 265 | margin: 0px; 266 | padding: 0px; 267 | } 268 | 269 | input#number { 270 | text-align: center; 271 | position: relative; 272 | border: none; 273 | border-top: 1px solid #ddd; 274 | border-bottom: 1px solid #ddd; 275 | margin: 0px; 276 | width: 40px; 277 | height: auto; 278 | } 279 | 280 | input[type="number"]::-webkit-inner-spin-button, 281 | input[type="number"]::-webkit-outer-spin-button { 282 | -webkit-appearance: none; 283 | margin: 0; 284 | } 285 | -------------------------------------------------------------------------------- /views/src/css/fonts/OpenSans-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSC-Unilag/certlify/191b602c82c8721e8d5d9afe56eee8bc7452c920/views/src/css/fonts/OpenSans-Bold.ttf -------------------------------------------------------------------------------- /views/src/css/fonts/OpenSans-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSC-Unilag/certlify/191b602c82c8721e8d5d9afe56eee8bc7452c920/views/src/css/fonts/OpenSans-BoldItalic.ttf -------------------------------------------------------------------------------- /views/src/css/fonts/OpenSans-ExtraBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSC-Unilag/certlify/191b602c82c8721e8d5d9afe56eee8bc7452c920/views/src/css/fonts/OpenSans-ExtraBold.ttf -------------------------------------------------------------------------------- /views/src/css/fonts/OpenSans-ExtraBoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSC-Unilag/certlify/191b602c82c8721e8d5d9afe56eee8bc7452c920/views/src/css/fonts/OpenSans-ExtraBoldItalic.ttf -------------------------------------------------------------------------------- /views/src/css/fonts/OpenSans-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSC-Unilag/certlify/191b602c82c8721e8d5d9afe56eee8bc7452c920/views/src/css/fonts/OpenSans-Italic.ttf -------------------------------------------------------------------------------- /views/src/css/fonts/OpenSans-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSC-Unilag/certlify/191b602c82c8721e8d5d9afe56eee8bc7452c920/views/src/css/fonts/OpenSans-Light.ttf -------------------------------------------------------------------------------- /views/src/css/fonts/OpenSans-LightItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSC-Unilag/certlify/191b602c82c8721e8d5d9afe56eee8bc7452c920/views/src/css/fonts/OpenSans-LightItalic.ttf -------------------------------------------------------------------------------- /views/src/css/fonts/OpenSans-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSC-Unilag/certlify/191b602c82c8721e8d5d9afe56eee8bc7452c920/views/src/css/fonts/OpenSans-Regular.ttf -------------------------------------------------------------------------------- /views/src/css/fonts/OpenSans-Semibold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSC-Unilag/certlify/191b602c82c8721e8d5d9afe56eee8bc7452c920/views/src/css/fonts/OpenSans-Semibold.ttf -------------------------------------------------------------------------------- /views/src/css/fonts/OpenSans-SemiboldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSC-Unilag/certlify/191b602c82c8721e8d5d9afe56eee8bc7452c920/views/src/css/fonts/OpenSans-SemiboldItalic.ttf -------------------------------------------------------------------------------- /views/src/css/fonts/open-sans.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSC-Unilag/certlify/191b602c82c8721e8d5d9afe56eee8bc7452c920/views/src/css/fonts/open-sans.zip -------------------------------------------------------------------------------- /views/src/css/footer.css: -------------------------------------------------------------------------------- 1 | footer { 2 | position: relative; 3 | display: flex; 4 | justify-content: center; 5 | align-items: center; 6 | width: 100%; 7 | height: auto; 8 | } 9 | 10 | footer p { 11 | color: #BBBBBB; 12 | display: flex; 13 | justify-content: center; 14 | align-items: center; 15 | flex-wrap: wrap; 16 | left: 1.5rem; 17 | flex-grow: 1; 18 | } 19 | 20 | footer .empty { 21 | width: 10%; 22 | } 23 | 24 | footer .built-by { 25 | width: 25%; 26 | display: grid; 27 | grid-template-columns: auto; 28 | grid-template-rows: 1.5rem auto; 29 | } 30 | 31 | footer .built-by a { 32 | justify-self: center; 33 | position: relative; 34 | left: 2.7rem; 35 | top: -1rem; 36 | width: 1rem; 37 | height: auto; 38 | display: inline-block; 39 | } 40 | 41 | footer .contribute { 42 | position: relative; 43 | width: 10%; 44 | z-index: -1; 45 | top: 8.6rem; 46 | right: 1rem; 47 | padding-left: 1rem; 48 | left: 0; 49 | text-align: center; 50 | font-size: 0.6rem; 51 | } 52 | 53 | footer p span { 54 | position: relative; 55 | } 56 | 57 | footer p span img { 58 | position: absolute; 59 | width: 16.4rem; 60 | height: auto; 61 | top: 1rem; 62 | right: -5.7rem; 63 | z-index: -1; 64 | } 65 | 66 | @media screen and (min-width:40rem) { 67 | footer { 68 | justify-content: space-between; 69 | } 70 | 71 | footer .empty { 72 | width: 10%; 73 | } 74 | } -------------------------------------------------------------------------------- /views/src/css/loader.css: -------------------------------------------------------------------------------- 1 | .loader { 2 | display: flex; 3 | justify-content: center; 4 | position: fixed; 5 | background: white; 6 | align-items: center; 7 | width: 100%; 8 | height: 100%; 9 | z-index: 4; 10 | cursor: progress; 11 | } 12 | 13 | .loader .container-for-loader { 14 | display: inline-block; 15 | width: 4rem; 16 | height: 4rem; 17 | position: relative; 18 | transform: rotate(0deg); 19 | animation: rotate 2.5s linear infinite; 20 | } 21 | 22 | .loader .large-circle { 23 | display: inline-block; 24 | position: relative; 25 | width: 4rem; 26 | height: 4rem; 27 | border-radius: 50%; 28 | background-color: #488af7; 29 | z-index: 9; 30 | box-shadow: 0px 0.5px 3px lightgrey; 31 | animation: change-color 4s ease-in infinite; 32 | } 33 | 34 | .loader .inner-circle { 35 | width: 2rem; 36 | height: 2rem; 37 | margin: 0; 38 | position: absolute; 39 | background-color: #6ba3ff; 40 | z-index: 1; 41 | border-radius: 50%; 42 | right: 0; 43 | display: inline-block; 44 | } 45 | 46 | .loader div:nth-child(2) { 47 | top: -1rem; 48 | right: 2rem; 49 | animation: change-color-gold 4s ease infinite, move-in-out-1 3s 300ms linear infinite; 50 | } 51 | 52 | .loader div:nth-child(3) { 53 | right: -1rem; 54 | background-color: #ffda70; 55 | animation: change-color-red 4s ease infinite, move-in-out-2 3s 300ms linear infinite; 56 | } 57 | 58 | .loader div:nth-child(4) { 59 | top: 2rem; 60 | right: 3rem; 61 | background-color: #7bd393; 62 | animation: change-color-blue 4s ease infinite, move-in-out-3 3s 300ms linear infinite; 63 | } 64 | 65 | .loader div:nth-child(5) { 66 | top: 3rem; 67 | background-color: #e9665b; 68 | animation: change-color-green 4s ease infinite, move-in-out-4 3s 300ms linear infinite; 69 | } 70 | 71 | .hide{ 72 | display: none !important; 73 | } 74 | 75 | .zero-opacity{ 76 | animation: fade-out 0.4s forwards; 77 | } -------------------------------------------------------------------------------- /views/src/css/main.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'Nunito', Verdana, sans-serif; 3 | src: url("./fonts/OpenSans-Regular.ttf"); 4 | } 5 | 6 | * { 7 | font-family: 'Nunito', Verdana, sans-serif; 8 | margin: 0; 9 | padding: 0; 10 | box-sizing: border-box; 11 | font-size: 1rem; 12 | scroll-behavior: smooth; 13 | 14 | } 15 | 16 | html, 17 | body { 18 | color: #098dff; 19 | font-size: 1rem; 20 | line-height: 1.5; 21 | letter-spacing: 0.12rem; 22 | word-spacing: 0.16rem; 23 | } 24 | 25 | body { 26 | display: grid; 27 | position: relative; 28 | width: 100%; 29 | height: auto; 30 | grid-template-columns: 100%; 31 | grid-template-rows: auto auto minmax(4.5rem, auto); 32 | justify-content: center; 33 | align-content: center; 34 | } 35 | 36 | /* Custom Scroll-bar */ 37 | ::-webkit-scrollbar { 38 | width: 1.2rem; 39 | } 40 | 41 | ::-webkit-scrollbar-track { 42 | box-shadow: inset 0 0 7px lightgrey; 43 | border-radius: 2rem; 44 | transition: all 90ms ease-in; 45 | } 46 | 47 | ::-webkit-scrollbar-thumb { 48 | background-color: #4285F4; 49 | border-radius: 2rem; 50 | transition: all 90ms ease-in; 51 | } 52 | 53 | ::-webkit-scrollbar-thumb:hover { 54 | background-color: #2262c7; 55 | } 56 | 57 | main { 58 | display: grid; 59 | position: relative; 60 | width: 100%; 61 | grid-template-columns: 100%; 62 | grid-template-rows: 11rem auto; 63 | justify-items: center; 64 | } 65 | 66 | main span { 67 | display: flex; 68 | position: relative; 69 | justify-content: center; 70 | align-items: center; 71 | width: 45%; 72 | } 73 | 74 | main span img { 75 | width: 90%; 76 | height: auto; 77 | margin: 0rem 0.5rem; 78 | } 79 | 80 | header { 81 | display: grid; 82 | grid-template-columns: 100%; 83 | justify-content: center; 84 | align-items: center; 85 | margin: 1.5rem 0; 86 | } 87 | 88 | header span { 89 | display: flex; 90 | flex-wrap: wrap; 91 | justify-content: center; 92 | align-items: center; 93 | height: 6.7rem; 94 | } 95 | 96 | header .logo img { 97 | width: 10rem; 98 | position: relative; 99 | z-index: -1; 100 | bottom: -0.5rem; 101 | left: 0.2rem; 102 | } 103 | 104 | main .landing-page-section { 105 | display: grid; 106 | height: auto; 107 | text-align: center; 108 | justify-items: center; 109 | align-items: center; 110 | grid-template-columns: auto; 111 | grid-template-rows: minmax(6rem, auto) minmax(3rem, auto) minmax(4rem, auto) minmax(4rem, auto) 3rem; 112 | } 113 | 114 | main .landing-page-section h1 { 115 | font-weight: 600; 116 | font-size: 1.13rem; 117 | color: #4285F4; 118 | } 119 | main .landing-page-section h1 i{ 120 | margin-top: 0.3rem; 121 | display: inline-block; 122 | } 123 | main .landing-page-section p { 124 | margin: 0.5rem 0; 125 | text-align: center; 126 | font-size: 0.9rem; 127 | font-weight: 600; 128 | padding: 0.3rem; 129 | color: black; 130 | align-self: start; 131 | } 132 | 133 | a { 134 | text-decoration: none; 135 | color: #098dff; 136 | cursor: pointer; 137 | } 138 | 139 | .landing-page-section a, 140 | .sign-log, 141 | #return-home { 142 | display: flex; 143 | justify-content: center; 144 | align-items: center; 145 | box-shadow: 1px 4px 5px lightgrey; 146 | border: none; 147 | color: white; 148 | width: 12.25rem; 149 | height: 2.5rem; 150 | background-color: #4285F4; 151 | transition: 300ms all ease-in; 152 | } 153 | 154 | main span .four-opor { 155 | font-size: 44vw; 156 | text-shadow: -7px 3px 1px gold; 157 | } 158 | 159 | #return-home { 160 | margin-top: 7rem; 161 | width: 15.65rem; 162 | } 163 | 164 | .sign-log { 165 | width: 85%; 166 | margin-top: 1rem; 167 | } 168 | 169 | .landing-page-section a:hover, 170 | .sign-log:hover, 171 | #return-home:hover { 172 | background-color: #619bf7; 173 | } 174 | 175 | .landing-page-section a:focus, 176 | .sign-log:focus, 177 | #return-home:focus { 178 | background-color: #1f74fc; 179 | } 180 | 181 | .landing-page-section a:active, 182 | .sign-log:active, 183 | #return-home:active { 184 | background-color: #2e7eff; 185 | } 186 | 187 | input { 188 | width: 85%; 189 | height: 3rem; 190 | border: 1.7px solid #4285F4; 191 | padding-left: 0.3rem; 192 | margin-bottom: 1rem; 193 | border-radius: 0.3rem; 194 | font-size: 0.9rem; 195 | } 196 | 197 | .sign-page-section { 198 | display: flex; 199 | flex-wrap: wrap; 200 | justify-content: center; 201 | align-items: center; 202 | } 203 | 204 | .sign-page-section p { 205 | color: #707070; 206 | margin: 1rem 0; 207 | text-align: center; 208 | width: 100%; 209 | } 210 | 211 | .sign-page-section form { 212 | display: flex; 213 | flex-wrap: wrap; 214 | justify-content: center; 215 | align-items: center; 216 | margin: 0.1rem 0rem 2rem 0rem; 217 | } 218 | 219 | .sign-page-section h1 { 220 | font-size: 1.5rem; 221 | text-align: center; 222 | width: 100%; 223 | font-weight: bolder; 224 | } 225 | 226 | .sign-page-section .second-text { 227 | text-align: center; 228 | padding: 1rem; 229 | width: 100%; 230 | } 231 | 232 | /* 233 | ellispse curve code 234 | */ 235 | 236 | .ellipse-curve { 237 | width: 15rem; 238 | position: fixed; 239 | overflow: hidden; 240 | z-index: -1; 241 | bottom: -7rem; 242 | right: 0; 243 | transform: rotate(25deg); 244 | height: 15rem; 245 | display: inline-block; 246 | } 247 | 248 | .top-left { 249 | transform: rotate(223deg); 250 | top: -7.8rem; 251 | left: -9.5rem; 252 | } 253 | 254 | .first-line, 255 | .second-line, 256 | .third-line { 257 | width: 23.25rem; 258 | height: 27rem; 259 | position: absolute; 260 | overflow: hidden; 261 | border-top-left-radius: 65% 80%; 262 | border-bottom-left-radius: 35% 20%; 263 | } 264 | 265 | .first-line { 266 | border: 1px solid #0F9D58; 267 | } 268 | 269 | .second-line { 270 | border: 1px solid #4285F4; 271 | top: 1.5rem; 272 | } 273 | 274 | .third-line { 275 | border: 1px solid #FBBC04; 276 | top: 3rem; 277 | } 278 | 279 | .custom-cir { 280 | width: 3rem; 281 | height: 3rem; 282 | background-color: #e1effb; 283 | position: absolute; 284 | border-radius: 50%; 285 | right: 0rem; 286 | z-index: -3; 287 | bottom: 1rem; 288 | } 289 | 290 | .cir-left { 291 | right: 0rem; 292 | left: 0; 293 | bottom: 11rem; 294 | } 295 | 296 | .custom-ellipse { 297 | position: absolute; 298 | z-index: -3; 299 | background-color: #e1effb; 300 | width: 20rem; 301 | height: 23rem; 302 | border-top-left-radius: 40% 80%; 303 | border-top-right-radius: 40% 30%; 304 | border-bottom-left-radius: 60% 30%; 305 | border-bottom-right-radius: 20% 90%; 306 | bottom: -79px; 307 | animation: 6.5s wobble infinite ease; 308 | } 309 | 310 | footer { 311 | display: flex; 312 | justify-content: flex-start; 313 | margin-top: 1.5rem; 314 | /* padding-left: 1.5rem; */ 315 | align-items: center; 316 | width: 100%; 317 | height: 2rem; 318 | } 319 | 320 | footer a { 321 | width: 3rem; 322 | text-decoration: none; 323 | } 324 | 325 | footer a img { 326 | width: 2.1rem; 327 | height: auto; 328 | } 329 | 330 | @media screen and (min-width: 40rem) { 331 | header #logo img { 332 | bottom: 4rem; 333 | } 334 | 335 | main span .four-opor { 336 | font-size: 15.5rem; 337 | } 338 | 339 | .custom-ellipse { 340 | width: 23.5rem; 341 | height: 25.5rem; 342 | bottom: -110px; 343 | } 344 | } 345 | 346 | @media screen and (min-width: 45rem) { 347 | main span img { 348 | width: 11rem; 349 | margin: 0rem 1rem; 350 | } 351 | 352 | .sign-page-section form { 353 | width: 50rem; 354 | } 355 | } 356 | 357 | @media screen and (min-width: 62.3125rem) { 358 | main span img { 359 | width: 15rem; 360 | } 361 | 362 | .sign-page-section form { 363 | width: 55.125rem; 364 | } 365 | } -------------------------------------------------------------------------------- /views/src/css/share.css: -------------------------------------------------------------------------------- 1 | .share-container{ 2 | display: none; 3 | border: 2.9px solid #4285f4; 4 | box-shadow: 1px 3px 7px grey; 5 | margin-top: 0.9rem; 6 | border-radius: 8%; 7 | height: 0; 8 | transition: all 300ms ease-out; 9 | } 10 | .share-container, .share-wrapper{ 11 | width: 15rem; 12 | position: relative; 13 | top: -0.1rem; 14 | align-items: center; 15 | flex-wrap: wrap; 16 | justify-content: center; 17 | } 18 | .share-wrapper a{ 19 | width: 100%; 20 | display: flex; 21 | flex-wrap: nowrap; 22 | border-bottom: 1px solid #4285f4; 23 | padding: 0.8rem; 24 | box-shadow: none; 25 | justify-content: center; 26 | } 27 | .share-wrapper a span{ 28 | margin: 0; 29 | width: 1.5rem; 30 | border-radius: 50%; 31 | } 32 | .share-wrapper a span img{ 33 | width: 100%; 34 | height: auto; 35 | margin-right: 1.2rem; 36 | box-shadow: none; 37 | } 38 | .share-wrapper::after { 39 | content: ""; 40 | position: absolute; 41 | top: -17.8%; 42 | transform: rotate(180deg); 43 | left: 48.5%; 44 | margin-left: -5px; 45 | border-width: 0.8rem; 46 | border-style: solid; 47 | border-color: #4285f4 transparent transparent transparent; 48 | } 49 | .increase-height{ 50 | display: flex; 51 | height: 10rem; 52 | } 53 | 54 | .icons-author a{ 55 | box-shadow: none; 56 | text-decoration: underline; 57 | } 58 | @media screen and (min-width: 40rem) { 59 | .share-wrapper{ 60 | flex-wrap: nowrap; 61 | } 62 | .share-container{ 63 | grid-area: 3 / 1 / 4 / 3; 64 | right: -5.1rem; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /views/src/css/signup.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'Nunito', Verdana, sans-serif; 3 | src: url("./fonts/OpenSans-Regular.ttf"); 4 | } 5 | 6 | * { 7 | font-family: 'Nunito', Verdana, sans-serif; 8 | margin: 0; 9 | padding: 0; 10 | box-sizing: border-box; 11 | font-size: 1rem; 12 | scroll-behavior: smooth; 13 | } 14 | 15 | html, 16 | body { 17 | color: #098dff; 18 | font-size: 1rem; 19 | line-height: 1.5; 20 | letter-spacing: 0.12rem; 21 | word-spacing: 0.16rem; 22 | } 23 | 24 | body { 25 | display: grid; 26 | position: relative; 27 | width: 100%; 28 | height: -webkit-fill-available; 29 | grid-template-columns: 100%; 30 | grid-template-rows: auto auto; 31 | justify-content: center; 32 | } 33 | 34 | /* Custom Scroll-bar */ 35 | ::-webkit-scrollbar { 36 | width: 1.2rem; 37 | } 38 | 39 | ::-webkit-scrollbar-track { 40 | box-shadow: inset 0 0 7px lightgrey; 41 | border-radius: 2rem; 42 | transition: all 90ms ease-in; 43 | 44 | } 45 | 46 | ::-webkit-scrollbar-thumb { 47 | background-color: #4285F4; 48 | border-radius: 2rem; 49 | transition: all 90ms ease-in; 50 | } 51 | 52 | ::-webkit-scrollbar-thumb:hover { 53 | background-color: #2262c7; 54 | } 55 | 56 | main { 57 | display: grid; 58 | position: relative; 59 | width: 100%; 60 | grid-template-columns: 100%; 61 | grid-template-rows: auto auto; 62 | justify-items: center; 63 | } 64 | 65 | main span { 66 | display: flex; 67 | position: relative; 68 | justify-content: center; 69 | align-items: center; 70 | width: 45%; 71 | } 72 | 73 | main span img { 74 | width: 100%; 75 | height: auto; 76 | } 77 | 78 | header { 79 | display: grid; 80 | grid-template-columns: 100%; 81 | grid-template-rows: auto auto; 82 | justify-content: center; 83 | align-items: center; 84 | margin-bottom: 1.5rem; 85 | } 86 | 87 | header span { 88 | display: flex; 89 | flex-wrap: wrap; 90 | justify-content: center; 91 | align-items: center; 92 | height: 6.7rem; 93 | position: relative; 94 | top: 5.5rem; 95 | z-index: -3; 96 | } 97 | 98 | header .logo img { 99 | width: 10rem; 100 | position: relative; 101 | z-index: -1; 102 | bottom: 4.5rem; 103 | left: 0.2rem; 104 | } 105 | 106 | header .section-links { 107 | width: 100%; 108 | display: flex; 109 | justify-content: end; 110 | align-items: center; 111 | justify-self: center; 112 | transition: all 400ms ease-in; 113 | } 114 | 115 | ul { 116 | display: grid; 117 | width: 100%; 118 | align-items: end; 119 | grid-template-rows: 100%; 120 | justify-content: end; 121 | } 122 | 123 | ul li { 124 | list-style-type: none; 125 | justify-self: center; 126 | display: flex; 127 | width: 9rem; 128 | height: 5rem; 129 | text-align: center; 130 | justify-content: center; 131 | align-items: flex-end; 132 | } 133 | 134 | ul li a { 135 | width: 100%; 136 | text-decoration: none; 137 | transition: all 80ms ease-in; 138 | } 139 | 140 | header .section-links ul li a:hover { 141 | color: #fbbf09; 142 | } 143 | 144 | header .section-links ul li a:focus { 145 | color: #daa916; 146 | } 147 | 148 | header .section-links ul li a:active { 149 | color: #eed487; 150 | } 151 | 152 | header .section-links ul { 153 | justify-self: end; 154 | } 155 | 156 | header .section-links ul li a { 157 | padding: 0.8rem; 158 | font-size: 1.1rem; 159 | } 160 | 161 | header .section-links ul .gen-cert { 162 | position: relative; 163 | } 164 | 165 | header .section-links ul li .active-cert { 166 | background-color: #FBBC04; 167 | width: 11rem; 168 | height: 0.2rem; 169 | position: absolute; 170 | border: none; 171 | bottom: 0.3rem; 172 | right: 0; 173 | left: 2rem; 174 | } 175 | 176 | main .landing-page-section { 177 | display: grid; 178 | height: auto; 179 | text-align: center; 180 | justify-items: center; 181 | align-items: center; 182 | grid-template-columns: auto; 183 | grid-template-rows: 7rem 3rem 2rem 7rem; 184 | } 185 | 186 | main .landing-page-section h1 { 187 | font-weight: 600; 188 | font-size: 1.13rem; 189 | color: #4285F4; 190 | } 191 | 192 | 193 | main .landing-page-section p { 194 | text-align: center; 195 | font-size: 0.9rem; 196 | font-weight: 600; 197 | padding: 0.3rem; 198 | color: black; 199 | align-self: start; 200 | } 201 | 202 | a { 203 | text-decoration: none; 204 | color: #098dff; 205 | cursor: pointer; 206 | } 207 | 208 | .landing-page-section a, 209 | .sign-log { 210 | display: flex; 211 | justify-content: center; 212 | align-items: center; 213 | box-shadow: 1px 4px 5px lightgrey; 214 | border: none; 215 | color: white; 216 | width: 12.25rem; 217 | height: 2.5rem; 218 | background-color: #4285F4; 219 | transition: 300ms all ease-in; 220 | } 221 | 222 | .sign-log { 223 | width: 85%; 224 | margin-top: 1rem; 225 | cursor: pointer; 226 | } 227 | 228 | .landing-page-section a:hover, 229 | .sign-log:hover { 230 | background-color: #619bf7; 231 | } 232 | 233 | .landing-page-section a:focus, 234 | .sign-log:focus { 235 | background-color: #1f74fc; 236 | } 237 | 238 | .landing-page-section a:active, 239 | .sign-log:active { 240 | background-color: #2e7eff; 241 | cursor: wait; 242 | } 243 | 244 | input { 245 | width: 85%; 246 | height: 3rem; 247 | border: 1.7px solid #4285F4; 248 | padding-left: 1.5rem; 249 | margin-bottom: 1rem; 250 | border-radius: 0.3rem; 251 | font-size: 0.9rem; 252 | } 253 | 254 | /* Generated cert link */ 255 | 256 | 257 | .sign-page-section { 258 | display: grid; 259 | justify-items: center; 260 | align-content: center; 261 | grid-template-columns: minmax(3rem, 100%); 262 | grid-template-rows: auto auto auto auto auto auto; 263 | } 264 | 265 | .sign-page-section p { 266 | color: #707070; 267 | margin: 1rem 0; 268 | text-align: center; 269 | width: 100%; 270 | } 271 | 272 | .sign-page-section form { 273 | display: grid; 274 | justify-items: center; 275 | align-content: center; 276 | grid-template-columns: minmax(auto, 60rem) 50%; 277 | grid-template-rows: auto auto; 278 | margin: 0.1rem 0rem 2rem 0rem; 279 | } 280 | 281 | .sign-page-section .form-input { 282 | grid-template-columns: minmax(auto, 60rem); 283 | } 284 | 285 | .sign-page-section h1 { 286 | font-size: 1.5rem; 287 | text-align: center; 288 | width: 100%; 289 | font-weight: bolder; 290 | } 291 | 292 | .sign-page-section .second-text { 293 | text-align: center; 294 | padding: 1rem; 295 | width: 100%; 296 | } 297 | 298 | #email-input .icon { 299 | margin: 0.2rem 0.5rem; 300 | } 301 | 302 | #generate{ 303 | display: flex; 304 | flex-wrap: wrap; 305 | justify-content: center; 306 | margin: 5rem 0rem; 307 | } 308 | 309 | /* 310 | ellispse curve code 311 | */ 312 | 313 | .ellipse-curve { 314 | width: 15rem; 315 | position: fixed; 316 | overflow: hidden; 317 | z-index: -1; 318 | bottom: -7rem; 319 | right: 0; 320 | transform: rotate(25deg); 321 | height: 15rem; 322 | display: inline-block; 323 | } 324 | 325 | .top-left { 326 | transform: rotate(223deg); 327 | top: -7.8rem; 328 | left: -9.5rem; 329 | } 330 | 331 | .first-line, 332 | .second-line, 333 | .third-line { 334 | width: 23.25rem; 335 | height: 27rem; 336 | position: absolute; 337 | overflow: hidden; 338 | border-top-left-radius: 65% 80%; 339 | border-bottom-left-radius: 35% 20%; 340 | } 341 | 342 | .first-line { 343 | border: 1px solid #0F9D58; 344 | } 345 | 346 | .second-line { 347 | border: 1px solid #4285F4; 348 | top: 1.5rem; 349 | } 350 | 351 | .third-line { 352 | border: 1px solid #FBBC04; 353 | top: 3rem; 354 | } 355 | 356 | .custom-cir { 357 | width: 3rem; 358 | height: 3rem; 359 | background-color: aliceblue; 360 | position: absolute; 361 | border-radius: 50%; 362 | right: 0rem; 363 | z-index: -3; 364 | bottom: 1rem; 365 | } 366 | 367 | .cir-left { 368 | right: 0rem; 369 | left: 0; 370 | bottom: 11rem; 371 | } 372 | 373 | .custom-ellipse { 374 | position: absolute; 375 | z-index: -3; 376 | background-color: aliceblue; 377 | width: 22rem; 378 | height: 22rem; 379 | border-top-left-radius: 40% 80%; 380 | border-top-right-radius: 40% 30%; 381 | border-bottom-left-radius: 60% 30%; 382 | border-bottom-right-radius: 20% 90%; 383 | } 384 | 385 | #password-message, 386 | #email-message { 387 | color: red; 388 | display: none; 389 | } 390 | 391 | footer { 392 | display: flex; 393 | justify-content: flex-start; 394 | margin-top: 1.5rem; 395 | align-items: center; 396 | width: 100%; 397 | height: 2rem; 398 | } 399 | 400 | footer a { 401 | width: 3rem; 402 | text-decoration: none; 403 | } 404 | 405 | footer a img { 406 | width: 2.1rem; 407 | height: auto; 408 | } 409 | 410 | @media screen and (min-width: 40rem) { 411 | header #logo img { 412 | bottom: 4rem; 413 | } 414 | } 415 | 416 | @media screen and (min-width: 45rem) { 417 | main span img { 418 | width: 60%; 419 | } 420 | 421 | .sign-page-section form { 422 | width: 50rem; 423 | } 424 | 425 | #regenerate { 426 | width: 24rem; 427 | justify-self: center; 428 | } 429 | } 430 | 431 | @media screen and (min-width: 62.3125rem) { 432 | main span img { 433 | width: 15rem; 434 | } 435 | 436 | .sign-page-section form { 437 | width: 55.125rem; 438 | } 439 | } 440 | -------------------------------------------------------------------------------- /views/src/js/FontSizer.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Increases font size value by 1 3 | */ 4 | function increaseValue() { 5 | var value = Number(document.getElementById('number').value); 6 | value = isNaN(value) ? 0 : value; 7 | value++; 8 | document.getElementById('number').value = value; 9 | let width = document.getElementById('container').offsetWidth; 10 | //let height = width / rat; 11 | boundary.fontsize = value / width; 12 | mark(); 13 | } 14 | 15 | /** 16 | * Decreases font size value by 1 17 | */ 18 | function decreaseValue() { 19 | var value = Number(document.getElementById('number').value); 20 | value = isNaN(value) ? 0 : value; 21 | value < 1 ? value = 1 : ''; 22 | value--; 23 | document.getElementById('number').value = value; 24 | let width = document.getElementById('container').offsetWidth; 25 | // let height = width / rat; 26 | boundary.fontsize = value / width; 27 | mark(); 28 | } 29 | 30 | /** 31 | * Sets the font to the user selected font 32 | */ 33 | function newfont() { 34 | var value = Number(document.getElementById('number').value); 35 | let width = document.getElementById('container').offsetWidth; 36 | // let height = width / rat; 37 | boundary.fontsize = value / width; 38 | mark(); 39 | } -------------------------------------------------------------------------------- /views/src/js/generator.js: -------------------------------------------------------------------------------- 1 | 2 | let data = {}; 3 | let boundary = {}; 4 | let img = new Image(); 5 | 6 | 7 | var person 8 | // On start, the canvas is drawn, and the various event listeners for the boundary selectors are initializes 9 | function start() { 10 | rat = img.width / img.height; 11 | let done = document.getElementById("done"); 12 | done.addEventListener('click', function () { 13 | if (document.getElementById("holdername").value) { 14 | done.style.display="none"; 15 | setTimeout(() => { 16 | done.style.display="block"; 17 | }, 5000); 18 | let name = { name: document.getElementById("holdername").value } 19 | var xhttp = new XMLHttpRequest(); 20 | xhttp.open("POST", "/api/certgenerate", false); 21 | xhttp.setRequestHeader("Content-Type", "application/json"); 22 | xhttp.onreadystatechange = function () { 23 | if (this.readyState == 4 && this.status == 200) { 24 | person = document.getElementById("holdername").value 25 | check(); 26 | document.getElementById("holdername").readOnly=true; 27 | }else if(this.readyState == 4 && this.status == 409) { 28 | person = document.getElementById("holdername").value 29 | check(); 30 | document.getElementById("holdername").readOnly=true; 31 | } 32 | }; 33 | xhttp.send(JSON.stringify(name)); 34 | 35 | } 36 | }) 37 | } 38 | img.onload = start; 39 | 40 | function check() { 41 | if (boundary.right && boundary.left && boundary.bottom) { 42 | let width = img.width; 43 | let center = (boundary.left[0] * width + boundary.right[0] * width) / 2 44 | document.getElementById("canvas").innerHTML = `` 45 | let canvas = document.getElementById("my_canvas"); 46 | let ctx = canvas.getContext("2d"); 47 | ctx.imageSmoothingEnabled = false; 48 | ctx.drawImage(img, 0, 0, canvas.width, canvas.height); 49 | ctx.font = `${boundary.fontsize * width}px ${boundary.fontfamily}`; 50 | ctx.fillStyle = boundary.color; 51 | ctx.textAlign = "center"; 52 | ctx.fillText(person, center, boundary.bottom[1] * (width / rat)); 53 | 54 | var imgData = canvas.toDataURL("image/jpeg", 1.0); 55 | const pdf = new jsPDF({ 56 | orientation: "landscape", 57 | unit: "px", 58 | format: [canvas.width, canvas.height] 59 | }); 60 | 61 | pdf.addImage(imgData, 'JPEG', 0, 0, canvas.width, canvas.height); 62 | pdf.save(`${person}.pdf`); 63 | window.location.href = "/"; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /views/src/js/main.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Loader container element 3 | */ 4 | const containerLoad = document.querySelector(".loader"); 5 | 6 | /** 7 | * collectors modal element when "Collectors" button is clicked 8 | */ 9 | const modal = document.querySelector(".collectors-modal"); 10 | 11 | /** 12 | * csv modal class 13 | */ 14 | const csv_modal = document.querySelector(".edit-cert-section"); 15 | 16 | /** 17 | * Share section wrapper 18 | */ 19 | const share_wrapper = document.querySelector(".share-container"); 20 | 21 | /** 22 | * Icons used in share container wrapper. 23 | */ 24 | const icons_author = document.querySelector(".icons-author"); 25 | /** 26 | * Hides Loader 27 | */ 28 | function HideLoader() { 29 | containerLoad.classList.toggle("zero-opacity"); 30 | setTimeout(() => { 31 | containerLoad.classList.toggle("hide"); 32 | }, 350); 33 | } 34 | 35 | /** 36 | * Shows loader 37 | */ 38 | function ShowLoader() { 39 | containerLoad.classList.toggle("zero-opacity"); 40 | containerLoad.classList.toggle("hide"); 41 | } 42 | 43 | /** 44 | * Copy text to clipboard. 45 | */ 46 | function CopyToClipBoard() { 47 | let copyText = document.querySelector("#link"); 48 | 49 | copyText.select(); 50 | copyText.setSelectionRange(0, 99999); /*For mobile devices*/ 51 | 52 | document.execCommand("copy"); 53 | 54 | alert("Copied Successfully!"); 55 | } 56 | 57 | /** 58 | * Hides loader when page has finished rendering. 59 | * @type {Window} 60 | */ 61 | window.onload = function(){ 62 | HideLoader(); 63 | } 64 | 65 | /** 66 | * Toggles collectors modal to display/hide. 67 | */ 68 | function ToggleModal(){ 69 | modal.classList.toggle("hide"); 70 | } 71 | 72 | /** 73 | * Toggles CSV modal to display/hide. 74 | */ 75 | function ToggleCSVModal(){ 76 | csv_modal.classList.toggle("hide"); 77 | document.getElementById("error").innerHTML = "" 78 | } 79 | 80 | /** 81 | * Change collected status color text. 82 | */ 83 | function collectedStatusColor(){ 84 | let statusEles = document.querySelectorAll(".collected-status"); 85 | 86 | statusEles.forEach(ele => { 87 | if(ele.textContent.localeCompare("Collected") === 0){ 88 | ele.classList.add("color-green"); 89 | } 90 | else{ 91 | ele.classList.add("color-red"); 92 | } 93 | }); 94 | } 95 | 96 | 97 | /* 98 | * Toggle share wrapper. 99 | */ 100 | function OpenWrapper(){ 101 | share_wrapper.classList.toggle("increase-height"); 102 | icons_author.classList.toggle("hide"); 103 | } -------------------------------------------------------------------------------- /views/src/js/sw-install.js: -------------------------------------------------------------------------------- 1 | if ('serviceWorker' in navigator) { 2 | window.addEventListener("load", () => { 3 | navigator.serviceWorker.register("sw.js") 4 | .then(reg => { 5 | console.log(`Service worker registrated: ${reg}`); 6 | }) 7 | .catch(err => { 8 | console.log(`Service worker registration error: ${err}`); 9 | }) 10 | }) 11 | } else { 12 | console.log(`Service worker not supported`); 13 | } -------------------------------------------------------------------------------- /views/sw.js: -------------------------------------------------------------------------------- 1 | const files = [ 2 | './.', 3 | '/imgs/.', 4 | '/imgs/diploma.svg', 5 | '/imgs/arrow.svg', 6 | '/imgs/hero-dsc-about-unilag.png', 7 | '/imgs/icon.png', 8 | '/imgs/IMG-20200923-WA0214.svg', 9 | '/imgs/search.svg', 10 | '/imgs/user.svg', 11 | '/index.html', 12 | '/views/src/js/.', 13 | '/views/src/css/.', 14 | '/views/src/css/fonts/OpenSans-Regular.ttf', 15 | '/views/src/css/main.css' 16 | ]; 17 | 18 | const fileVersion = 'v1'; 19 | 20 | self.addEventListener("install", event => { 21 | self.skipWaiting(); 22 | 23 | event.waitUntil( 24 | caches.open(fileVersion) 25 | .then(cache => { 26 | return cache.addAll(files) 27 | }) 28 | .catch(err => { 29 | console.log(`Error occurred while installing: ${err}`); 30 | }) 31 | ) 32 | }) 33 | 34 | self.addEventListener("activate", event => { 35 | console.log(`Service worker activating.`); 36 | 37 | const cacheWhiteList = [fileVersion]; 38 | 39 | event.waitUntil( 40 | caches.keys().then(cacheNames => { 41 | return Promise.all( 42 | cacheNames.map(cacheName => { 43 | if (cacheWhiteList.indexOf(cacheName) === -1) { 44 | console.log(`Deleting cache: ${cacheName}`); 45 | return caches.delete(cacheName); 46 | } 47 | }) 48 | ) 49 | }) 50 | ) 51 | }) 52 | 53 | /** 54 | * 55 | */ 56 | self.addEventListener('fetch', function (event) { 57 | event.respondWith( 58 | caches.match(event.request).then(function (response) { 59 | return response || fetch(event.request); 60 | }), 61 | ); 62 | }); --------------------------------------------------------------------------------