From 4f29471b653ea52db4f5417fb6cc84619796c4b7 Mon Sep 17 00:00:00 2001 From: SALEH Date: Thu, 9 May 2024 23:52:38 +0300 Subject: [PATCH 1/7] Preparing packages and connections installing some packages & set up database connection --- package-lock.json | 227 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 2 + 2 files changed, 229 insertions(+) diff --git a/package-lock.json b/package-lock.json index 6fd9de3..d1ec906 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,15 +10,38 @@ "dependencies": { "cookie-parser": "~1.4.4", "debug": "~2.6.9", + "dotenv": "^16.4.5", "ejs": "^3.1.9", "express": "^4.18.2", "http-errors": "~1.6.3", + "mongoose": "^8.3.4", "morgan": "~1.9.1" }, "devDependencies": { "nodemon": "^3.0.1" } }, + "node_modules/@mongodb-js/saslprep": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.6.tgz", + "integrity": "sha512-jqTTXQ46H8cAxmXBu8wm1HTSIMBMrIcoVrsjdQkKdMBj3il/fSCgWyya4P2I1xjPBl69mw+nRphrPlcIqBd20Q==", + "dependencies": { + "sparse-bitfield": "^3.0.3" + } + }, + "node_modules/@types/webidl-conversions": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", + "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==" + }, + "node_modules/@types/whatwg-url": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.4.tgz", + "integrity": "sha512-lXCmTWSHJvf0TRSO58nm978b8HJ/EdsSsEKLd3ODHFjo+3VGAyyTp4v50nWvwtzBxSMQrVOK7tcuN0zGPLICMw==", + "dependencies": { + "@types/webidl-conversions": "*" + } + }, "node_modules/abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -195,6 +218,14 @@ "node": ">=8" } }, + "node_modules/bson": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-6.7.0.tgz", + "integrity": "sha512-w2IquM5mYzYZv6rs3uN2DZTOBe2a0zXLj53TGDqwF4l6Sz/XsISrisXOJihArF9+BZ6Cq/GjVht7Sjfmri7ytQ==", + "engines": { + "node": ">=16.20.1" + } + }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -385,6 +416,17 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -823,6 +865,14 @@ "node": ">=10" } }, + "node_modules/kareem": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.6.3.tgz", + "integrity": "sha512-C3iHfuGUXK2u8/ipq9LfjFfXFxAZMQJJq7vLS45r3D9Y2xQ/m4S8zaR4zMLFWh9AsNPXmcFfUDhTEO8UIC/V6Q==", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -843,6 +893,11 @@ "node": ">= 0.6" } }, + "node_modules/memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==" + }, "node_modules/merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", @@ -897,6 +952,86 @@ "node": "*" } }, + "node_modules/mongodb": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.5.0.tgz", + "integrity": "sha512-Fozq68InT+JKABGLqctgtb8P56pRrJFkbhW0ux+x1mdHeyinor8oNzJqwLjV/t5X5nJGfTlluxfyMnOXNggIUA==", + "dependencies": { + "@mongodb-js/saslprep": "^1.1.5", + "bson": "^6.4.0", + "mongodb-connection-string-url": "^3.0.0" + }, + "engines": { + "node": ">=16.20.1" + }, + "peerDependencies": { + "@aws-sdk/credential-providers": "^3.188.0", + "@mongodb-js/zstd": "^1.1.0", + "gcp-metadata": "^5.2.0", + "kerberos": "^2.0.1", + "mongodb-client-encryption": ">=6.0.0 <7", + "snappy": "^7.2.2", + "socks": "^2.7.1" + }, + "peerDependenciesMeta": { + "@aws-sdk/credential-providers": { + "optional": true + }, + "@mongodb-js/zstd": { + "optional": true + }, + "gcp-metadata": { + "optional": true + }, + "kerberos": { + "optional": true + }, + "mongodb-client-encryption": { + "optional": true + }, + "snappy": { + "optional": true + }, + "socks": { + "optional": true + } + } + }, + "node_modules/mongodb-connection-string-url": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.0.tgz", + "integrity": "sha512-t1Vf+m1I5hC2M5RJx/7AtxgABy1cZmIPQRMXw+gEIPn/cZNF3Oiy+l0UIypUwVB5trcWHq3crg2g3uAR9aAwsQ==", + "dependencies": { + "@types/whatwg-url": "^11.0.2", + "whatwg-url": "^13.0.0" + } + }, + "node_modules/mongoose": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.3.4.tgz", + "integrity": "sha512-ckBaBzKgtWgCalW/LPkcBsR3wKCOYEJ9jLFPmYCYV7TLStpETY757ELx8/1stL11+6HxLLVffawBffXzd0Y7YA==", + "dependencies": { + "bson": "^6.5.0", + "kareem": "2.6.3", + "mongodb": "6.5.0", + "mpath": "0.9.0", + "mquery": "5.0.0", + "ms": "2.1.3", + "sift": "17.1.3" + }, + "engines": { + "node": ">=16.20.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mongoose" + } + }, + "node_modules/mongoose/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, "node_modules/morgan": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.9.1.tgz", @@ -912,6 +1047,46 @@ "node": ">= 0.8.0" } }, + "node_modules/mpath": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", + "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mquery": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz", + "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==", + "dependencies": { + "debug": "4.x" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/mquery/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/mquery/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, "node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -1062,6 +1237,14 @@ "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", "dev": true }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "engines": { + "node": ">=6" + } + }, "node_modules/qs": { "version": "6.11.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", @@ -1288,6 +1471,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/sift": { + "version": "17.1.3", + "resolved": "https://registry.npmjs.org/sift/-/sift-17.1.3.tgz", + "integrity": "sha512-Rtlj66/b0ICeFzYTuNvX/EF1igRbbnGSvEyT79McoZa/DeGhMyC5pWKOEsZKnpkqtSeovd5FL/bjHWC3CIIvCQ==" + }, "node_modules/simple-update-notifier": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", @@ -1300,6 +1488,14 @@ "node": ">=10" } }, + "node_modules/sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", + "dependencies": { + "memory-pager": "^1.0.2" + } + }, "node_modules/statuses": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", @@ -1352,6 +1548,17 @@ "nodetouch": "bin/nodetouch.js" } }, + "node_modules/tr46": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", + "integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==", + "dependencies": { + "punycode": "^2.3.0" + }, + "engines": { + "node": ">=14" + } + }, "node_modules/type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", @@ -1394,6 +1601,26 @@ "node": ">= 0.8" } }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-url": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-13.0.0.tgz", + "integrity": "sha512-9WWbymnqj57+XEuqADHrCJ2eSXzn8WXIW/YSGaZtb2WKAInQ6CHfaUUcTyyver0p8BDg5StLQq8h1vtZuwmOig==", + "dependencies": { + "tr46": "^4.1.1", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", diff --git a/package.json b/package.json index 4c3762d..23c7f50 100644 --- a/package.json +++ b/package.json @@ -8,9 +8,11 @@ "dependencies": { "cookie-parser": "~1.4.4", "debug": "~2.6.9", + "dotenv": "^16.4.5", "ejs": "^3.1.9", "express": "^4.18.2", "http-errors": "~1.6.3", + "mongoose": "^8.3.4", "morgan": "~1.9.1" }, "devDependencies": { From d97e8a6f5ae886f5a0bcefc8bcb14a04b189b8cf Mon Sep 17 00:00:00 2001 From: SALEH Date: Thu, 9 May 2024 23:52:56 +0300 Subject: [PATCH 2/7] Preparing packages and connections installing some packages & set up database connection --- .env | 1 + app.js | 23 +++++++++++++++++++++-- models/URL_Model.js | 12 ++++++++++++ 3 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 .env create mode 100644 models/URL_Model.js diff --git a/.env b/.env new file mode 100644 index 0000000..86b095f --- /dev/null +++ b/.env @@ -0,0 +1 @@ +mongoURI = 'mongodb+srv://Scorpion:Ayhaga12345%2A%23@demo.nelp36k.mongodb.net/URL_Shortner?retryWrites=true&w=majority&appName=Demo' \ No newline at end of file diff --git a/app.js b/app.js index 04be2f9..162db7f 100644 --- a/app.js +++ b/app.js @@ -3,8 +3,10 @@ const express = require('express'); const path = require('path'); const cookieParser = require('cookie-parser'); const logger = require('morgan'); - +const mongoose = require('mongoose'); const indexRouter = require('./routes/index'); +require('dotenv').config(); + const app = express(); @@ -17,14 +19,31 @@ app.use(express.json()); app.use(express.urlencoded({ extended: false })); app.use(cookieParser()); app.use(express.static(path.join(__dirname, 'public'))); - app.use('/', indexRouter); + + + +//Database Connection +const mongoURI = process.env.mongoURI +mongoose.connect(mongoURI) + .then(() => { + console.log("Connected Successfully to the Database.") + app.listen(3000) + }) + .catch((err) => { + console.log(err) + }) + + + // catch 404 and forward to error handler app.use(function (req, res, next) { next(createError(404)); }); + + // error handler app.use(function (err, req, res, next) { // set locals, only providing error in development diff --git a/models/URL_Model.js b/models/URL_Model.js new file mode 100644 index 0000000..059ba94 --- /dev/null +++ b/models/URL_Model.js @@ -0,0 +1,12 @@ +const mongoose = require('mongoose') + +const Schema = mongoose.Schema + +const URLSchema = new Schema({ + long: { type: String, required: true, minLentgh: 5 }, + alias: { type: String, required: true, minLentgh: 5 } +}, { timestamps: true }) + +URL = mongoose.model('URL', URLSchema) + +module.exports = URL; \ No newline at end of file From 4be7f2767ffa886c2eea8976b4391be140d3287e Mon Sep 17 00:00:00 2001 From: SALEH Date: Fri, 10 May 2024 00:00:44 +0300 Subject: [PATCH 3/7] Update table based on Databse & Save submitted data to the Database --- routes/index.js | 30 ++++++++++++++++++++++++++++-- views/index.ejs | 23 +++++++++++------------ 2 files changed, 39 insertions(+), 14 deletions(-) diff --git a/routes/index.js b/routes/index.js index 5890929..d52b33e 100644 --- a/routes/index.js +++ b/routes/index.js @@ -1,8 +1,34 @@ const router = require('express').Router(); +const URL = require('../models/URL_Model'); + /* GET home page. */ -router.get('/', function (req, res, next) { - res.render('index', { title: 'Express' }); +router.get('/', (req, res) => { + URL.find() + .then((links) => { + res.render('index', { title: 'Express', links }); + }) + .catch((err) => { + res.render('error', { error: "Failed to load home page" }) + }) + }); + +/* Save the data coming from the form in the Database */ +router.post('/', (req, res) => { + + const long = req.body.urlInput + const alias = req.body.aliasInput + const url = new URL({ long, alias }) + url.save() + .then(() => { + res.redirect('/') + console.log("Link added successfully to the Database.") + }) + .catch((err) => { + res.render('error', { error: "Failed to save data to the database" }) + }) +}) + module.exports = router; diff --git a/views/index.ejs b/views/index.ejs index bd9b3f6..5fa0a49 100644 --- a/views/index.ejs +++ b/views/index.ejs @@ -75,18 +75,17 @@ Original URL Shortened URL - - https://github.com/cat-backend-nodejs/nodejs-roadmap - http://localhost:3000/nodejs - - - https://stackoverflow.com/users/11936196/seif-el-din-sweilam - http://localhost:3000/stackoverflow - - - https://drive.google.com/drive/u/1/folders/1bpiBKNBd9n0Z79wrZvHVT1KyA9OBROLx - http://localhost:3000/himym - + <% for (link of links){%> + + + <%=link.long%> + + + + http://localhost:3000/<%=link.alias%> + + + <%}%> From 02e6020349a71822b1ddbff32aecaf049edeaaee Mon Sep 17 00:00:00 2001 From: SALEH Date: Fri, 10 May 2024 00:06:22 +0300 Subject: [PATCH 4/7] Use MVC pattern & remove styling to separate file --- controllers/URL_controllers.js | 65 ++++++++++++++++++++++++++++++++++ public/style.css | 47 ++++++++++++++++++++++++ routes/index.js | 28 ++------------- views/index.ejs | 50 +------------------------- 4 files changed, 116 insertions(+), 74 deletions(-) create mode 100644 controllers/URL_controllers.js create mode 100644 public/style.css diff --git a/controllers/URL_controllers.js b/controllers/URL_controllers.js new file mode 100644 index 0000000..b34eb2a --- /dev/null +++ b/controllers/URL_controllers.js @@ -0,0 +1,65 @@ +const URL = require('../models/URL_Model'); + + +/* GET home page. */ +const get_home = (req, res) => { + URL.find() + .then((links) => { + res.render('index', { title: 'Express', links }); + }) + .catch((err) => { + res.render('error', { error: "Failed to load home page" }) + }) + +} + + +/* Save the data coming from the form in the Database */ +const post_data = (req, res) => { + + const long = req.body.urlInput + const alias = req.body.aliasInput + const url = new URL({ long, alias }) + url.save() + .then(() => { + res.redirect('/') + console.log("Link added successfully to the Database.") + }) + .catch((err) => { + res.render('error', { error: "Failed to save data to the database" }) + }) +} + + +/* Redirecting the user when clicking the short link */ +const get_redirect = (req, res) => { + const alias = req.params.alias + URL.findOne({ alias }) + .then((link) => { + console.log(link) + if (link) { + res.redirect(`${link.long}`) + } else { + res.render('error', { error: "Invalid alias" }) + } + }) + .catch((err) => { + res.render('error', { error: "Failed to redirect" }) + }) +} + + +/* Deleting URL from Database */ +const delete_link = (req, res) => { + const alias = req.body.alias + URL.deleteOne({ alias }) + .then(() => { + res.status(200).json("Done") + }) + .catch((err) => { + console.log(err) + res.render('error', { error: "Failed to delete the item" }) + }) +} + +module.exports = { get_home, post_data } \ No newline at end of file diff --git a/public/style.css b/public/style.css new file mode 100644 index 0000000..89f5aa5 --- /dev/null +++ b/public/style.css @@ -0,0 +1,47 @@ +body { + font-family: Arial, sans-serif; + margin: 0; + padding: 20px; +} + +h1 { + text-align: center; +} + +.form-container { + margin-bottom: 20px; +} + +.form-container input[type="text"] { + width: 300px; + height: 30px; + padding: 5px; + font-size: 14px; +} + +.form-container input[type="submit"] { + height: 30px; + padding: 5px 15px; + font-size: 14px; + background-color: #4CAF50; + color: white; + border: none; + cursor: pointer; +} + +table { + border-collapse: collapse; + width: 100%; +} + +th, +td { + padding: 8px; + text-align: left; + border-bottom: 1px solid #ddd; +} + +th { + background-color: #4CAF50; + color: white; +} \ No newline at end of file diff --git a/routes/index.js b/routes/index.js index d52b33e..9b85dad 100644 --- a/routes/index.js +++ b/routes/index.js @@ -1,34 +1,12 @@ const router = require('express').Router(); -const URL = require('../models/URL_Model'); +const controller = require('../controllers/URL_controllers') /* GET home page. */ -router.get('/', (req, res) => { - URL.find() - .then((links) => { - res.render('index', { title: 'Express', links }); - }) - .catch((err) => { - res.render('error', { error: "Failed to load home page" }) - }) - -}); +router.get('/', controller.get_home); /* Save the data coming from the form in the Database */ -router.post('/', (req, res) => { - - const long = req.body.urlInput - const alias = req.body.aliasInput - const url = new URL({ long, alias }) - url.save() - .then(() => { - res.redirect('/') - console.log("Link added successfully to the Database.") - }) - .catch((err) => { - res.render('error', { error: "Failed to save data to the database" }) - }) -}) +router.post('/', controller.post_data) module.exports = router; diff --git a/views/index.ejs b/views/index.ejs index 5fa0a49..5a39935 100644 --- a/views/index.ejs +++ b/views/index.ejs @@ -5,55 +5,7 @@ URL Shortener App - + From 960a97925256cc0f565575246389fb7320743dee Mon Sep 17 00:00:00 2001 From: SALEH Date: Fri, 10 May 2024 00:12:03 +0300 Subject: [PATCH 5/7] Add delete button, redirect req handler and update error view --- .gitignore | 3 +- controllers/URL_controllers.js | 2 +- routes/index.js | 10 ++++++- views/error.ejs | 53 ++++++++++++++++++++++++++++++++-- views/index.ejs | 28 ++++++++++++++++-- 5 files changed, 87 insertions(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index 40b878d..3ec544c 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -node_modules/ \ No newline at end of file +node_modules/ +.env \ No newline at end of file diff --git a/controllers/URL_controllers.js b/controllers/URL_controllers.js index b34eb2a..a78698e 100644 --- a/controllers/URL_controllers.js +++ b/controllers/URL_controllers.js @@ -62,4 +62,4 @@ const delete_link = (req, res) => { }) } -module.exports = { get_home, post_data } \ No newline at end of file +module.exports = { get_home, post_data, get_redirect, delete_link } \ No newline at end of file diff --git a/routes/index.js b/routes/index.js index 9b85dad..b08e6d7 100644 --- a/routes/index.js +++ b/routes/index.js @@ -1,7 +1,6 @@ const router = require('express').Router(); const controller = require('../controllers/URL_controllers') - /* GET home page. */ router.get('/', controller.get_home); @@ -9,4 +8,13 @@ router.get('/', controller.get_home); /* Save the data coming from the form in the Database */ router.post('/', controller.post_data) + +/* Redirecting the user when clicking the short link */ +router.get('/:alias', controller.get_redirect) + + +/* Deleting URL from Database */ +router.delete('/', controller.delete_link) + + module.exports = router; diff --git a/views/error.ejs b/views/error.ejs index 7cf94ed..7769500 100644 --- a/views/error.ejs +++ b/views/error.ejs @@ -1,3 +1,50 @@ -

<%= message %>

-

<%= error.status %>

-
<%= error.stack %>
+ + + + + + + Error Page + + + + +
+

Error

+ <% if (error) { %> +

+ <%= error %> +

+ <% } else { %> +

Oops! Something went wrong.

+ <% } %> +
+ + + \ No newline at end of file diff --git a/views/index.ejs b/views/index.ejs index 5a39935..c2f2582 100644 --- a/views/index.ejs +++ b/views/index.ejs @@ -12,7 +12,7 @@

URL Shortener

-
+ @@ -27,6 +27,7 @@ Original URL Shortened URL + <% for (link of links){%> @@ -36,12 +37,33 @@ http://localhost:3000/<%=link.alias%> + <%}%>
- - + \ No newline at end of file From 84e9590136c7f4c6f15a466a9a6e026a7136c3d6 Mon Sep 17 00:00:00 2001 From: SALEH Date: Fri, 10 May 2024 00:15:06 +0300 Subject: [PATCH 6/7] Remove .env from tracking --- .env | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .env diff --git a/.env b/.env deleted file mode 100644 index 86b095f..0000000 --- a/.env +++ /dev/null @@ -1 +0,0 @@ -mongoURI = 'mongodb+srv://Scorpion:Ayhaga12345%2A%23@demo.nelp36k.mongodb.net/URL_Shortner?retryWrites=true&w=majority&appName=Demo' \ No newline at end of file From 969d002186d707196314c816e696986e781cdc49 Mon Sep 17 00:00:00 2001 From: Saleh Enab <101309575+Saleh-enab@users.noreply.github.com> Date: Wed, 15 May 2024 21:49:09 +0300 Subject: [PATCH 7/7] Update README.md --- README.md | 44 ++++++++++++++++++-------------------------- 1 file changed, 18 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 595dc02..72b802a 100644 --- a/README.md +++ b/README.md @@ -1,46 +1,38 @@ # URL Shortener App -This is starter code for URL Shortener Project. +## Overview -Fork this repository and use the given files to start with. +The URL Shortener App is a web service that converts long website addresses into shorter, more manageable links. This makes URLs easier to share and remember. -## Idea +## Features -A URL shortener website is a service that converts long website addresses into shorter, more manageable links. Users input a lengthy URL, and the website generates a condensed version, making it easier to share and remember. +- **URL Shortening**: Users can input a lengthy URL, and the app will generate a shorter version. -## Interface +- **Custom Aliases**: Users can provide a custom alias for their shortened URL, or let the app generate a random one. -The application interface consists of one page which contains: +- **Redirection**: Accessing the short URL redirects the user to the original long URL. -* A form to shorten the URL, which takes two inputs: - - the long version of the url - - the alias of the url (defaults to a random string) -* A table which contains the previously shortened URLs. +- **404 Error Handling**: If a non-existent short URL is accessed, a 404 error page is displayed. -## Short URLs +- **URL Management**: A table on the main page lists all previously shortened URLs for easy reference. -The short URLs are written in this form: +## Short URL Format + +The short URLs are structured as follows: ``` + http://localhost:3000/{alias} + ``` -## Application Logic -* When a client tries to access the short URL, they should be redirected to the original long URL. -* If the client accesses a URL which doesn't exist, a `404` error should be displayed. -* There's no required authentication or authorization to generate short URLs. +## Usage -## Project Criteria +1\. **Submit URL**: Enter a long URL and optionally an alias in the provided form. -- [ ] The application runs locally without any crashes -- [ ] The application logic is implemented correctly -- [ ] The application uses server-side rendering -- [ ] The application uses a MongoDB database +2\. **Generate Short URL**: Submit the form to create a shortened URL. -## Project Evaluation (50 pts.) +3\. **Access Short URL**: Use the short URL to be redirected to the original long URL. -* Project Completeness (25 pts.) -* Clean Code and Modulation (15 pts.) -* Descriptive Git Commit Messages (10 pts.) -* Nice touches (5 pts. bonus) \ No newline at end of file +4\. **Error Handling**: Encounter a 404 error if a short URL does not exist in the database.