migrating to mongodb, adding blog, adding project links and tracked and much more

This commit is contained in:
ngn 2023-05-27 21:16:21 +03:00
parent b67709a215
commit 2d2aea83a1
17 changed files with 900 additions and 127 deletions

View File

@ -1,78 +0,0 @@
const fs = require("fs");
class Database {
constructor() {
this.path = "db.json";
this.json = {};
this.read();
}
write() {
fs.writeFileSync(this.path, JSON.stringify(this.json));
}
read() {
try {
const data = fs.readFileSync(this.path, "utf8");
this.json = JSON.parse(data);
} catch (error) {
return;
}
}
find_all(key, check, ...args) {
try {
const ret = [];
for (const d of this.json[key]) {
if (check(d, ...args)) {
ret.push(d);
}
}
return ret;
} catch (error) {
return false;
}
}
find(key, check, ...args) {
try {
for (const d of this.json[key]) {
if (check(d, ...args)) {
return d;
}
}
return false;
} catch (error) {
return false;
}
}
get(key) {
const res = this.json[key]
if(res===undefined)
return []
return res
}
push(key, data) {
try {
this.json[key].push(data);
} catch (error) {
this.json[key] = [];
this.json[key].push(data);
}
this.write();
}
pop(key, data) {
try {
const indx = this.json[key].indexOf(data);
this.json[key].splice(indx, 1);
} catch (error) {
return;
}
this.write();
}
}
module.exports = Database;

View File

@ -1,31 +1,21 @@
const express = require("express"); const express = require("express");
const fs = require("fs"); const {gimmeToken} = require("./util.js")
const Database = require("./db"); const { MongoClient } = require("mongodb");
require("dotenv").config()
const app = express(); const app = express();
const db = new Database();
app.use(express.json()); app.use(express.json());
app.use(express.urlencoded({ extended: false })); app.use(express.urlencoded({ extended: false }));
function gimmeToken() { const client = new MongoClient(process.env.DATABASE);
var result = "" const PASS = process.env.PASS
var characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
var charactersLength = characters.length
for ( var i = 0; i < 32; i++ ) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}
return result;
}
let TOKEN = gimmeToken(); let TOKEN = gimmeToken();
const PASS = fs.readFileSync("pass", "utf-8")
/* /*
* error: 0 -> no error * error: 0 -> no error
* error: 1 -> parameter error * error: 1 -> parameter error
* error: 2 -> auth error * error: 2 -> auth error
* * error: 3 -> not found error
*/ */
// PATH: /api/login // PATH: /api/login
@ -62,7 +52,7 @@ app.get("/logout", (req,res)=>{
// PATH: /api/add_project // PATH: /api/add_project
// METHOD: GET // METHOD: GET
// PARAMETERS: token, name, desc, url // PARAMETERS: token, name, desc, url
app.get("/add_project", (req, res) => { app.get("/add_project", async (req, res) => {
let token = req.query.token; let token = req.query.token;
let name = req.query.name; let name = req.query.name;
let desc = req.query.desc; let desc = req.query.desc;
@ -79,14 +69,18 @@ app.get("/add_project", (req, res) => {
if (token !== TOKEN) if (token !== TOKEN)
return res.json({error: 2}) return res.json({error: 2})
db.push("projects", {"name":name, "desc":desc, "url":url}) await client.connect()
const db = await client.db("ngn13")
const col = await db.collection("projects")
await col.insertOne({"name":name, "desc":desc, "url":url, "click":0})
await client.close()
res.json({error: 0}) res.json({error: 0})
}); });
// PATH: /api/add_resource // PATH: /api/add_resource
// METHOD: GET // METHOD: GET
// PARAMETERS: token, name, tags, url // PARAMETERS: token, name, tags, url
app.get("/add_resource", (req, res) => { app.get("/add_resource", async (req, res) => {
let token = req.query.token; let token = req.query.token;
let name = req.query.name; let name = req.query.name;
let tags = req.query.tags; let tags = req.query.tags;
@ -103,24 +97,116 @@ app.get("/add_resource", (req, res) => {
if (token !== TOKEN) if (token !== TOKEN)
return res.json({error: 2}) return res.json({error: 2})
db.push("resources", {"name":name, "tags":tags.split(","), "url":url}) await client.connect()
const db = await client.db("ngn13")
const col = await db.collection("resources")
await col.insertOne({"name":name, "tags":tags.split(","), "url":url})
await client.close()
res.json({error: 0}) res.json({error: 0})
}); });
// PATH: /api/get_projects // PATH: /api/get_projects
// METHOD: GET // METHOD: GET
// PARAMETERS: NONE // PARAMETERS: NONE
app.get("/get_projects", (req, res) => { app.get("/get_projects", async (req, res) => {
let projects = db.get("projects") await client.connect()
res.json({error: 0, projects:projects}) const db = await client.db("ngn13")
const col = await db.collection("projects")
const array = await col.find().toArray()
await client.close()
res.json({error: 0, projects:array})
}); });
// PATH: /api/get_resources // PATH: /api/get_resources
// METHOD: GET // METHOD: GET
// PARAMETERS: NONE // PARAMETERS: NONE
app.get("/get_resources", (req, res) => { app.get("/get_resources", async (req, res) => {
let resources = db.get("resources") await client.connect()
res.json({error: 0, resources:resources}) const db = await client.db("ngn13")
const col = await db.collection("resources")
const array = await col.find().toArray()
await client.close()
res.json({error: 0, resources:array})
});
// PATH: /api/add_post
// METHOD: POST
// PARAMETERS: token, title, author, content
app.post("/add_post", async (req, res) => {
let token = req.body.token;
let title = req.body.title;
let author = req.body.author;
let content = req.body.content;
if (
token === undefined ||
title === undefined ||
author === undefined ||
content === undefined
)
return res.json({error: 1})
if (token !== TOKEN)
return res.json({error: 2})
await client.connect()
const db = await client.db("ngn13")
const col = await db.collection("posts")
await col.insertOne({
"title":title,
"author":author,
"date": new Date().toLocaleDateString(),
"content":content
})
await client.close()
res.json({error: 0})
});
// PATH: /api/get_posts
// METHOD: POST
// PARAMETERS: NONE
app.get("/get_posts", async (req, res) => {
await client.connect()
const db = await client.db("ngn13")
const col = await db.collection("posts")
const array = await col.find().toArray()
await client.close()
let newarray = []
for(let i = 0;i<array.length;i++){
newarray.push({
"title":array[i]["title"],
"desc":array[i]["content"]["en"].substring(0, 140) + "...",
"info":`${array[i]["author"]} | ${array[i]["date"]}`
})
}
res.json({error: 0, posts:newarray})
});
// PATH: /api/get_post
// METHOD: POST
// PARAMETERS: id
app.get("/get_post", async (req, res) => {
let id = req.query.id;
await client.connect()
const db = await client.db("ngn13")
const col = await db.collection("posts")
const array = await col.find().toArray()
await client.close()
for(let i = 0;i<array.length;i++){
if(array[i]["title"].toLowerCase().replaceAll(" ", "")===id){
return res.json({error: 0, post:{
"title": array[i]["title"],
"info": `${array[i]["author"]} | ${array[i]["date"]}`,
"content": array[i]["content"],
}})
}
}
res.json({error: 3})
}); });
// PATH: /api/ping // PATH: /api/ping

12
api/util.js Normal file
View File

@ -0,0 +1,12 @@
function gimmeToken() {
var result = ""
var characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
var charactersLength = characters.length
for ( var i = 0; i < 32; i++ ) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}
return result;
}
module.exports = {gimmeToken}

View File

@ -7,7 +7,7 @@
<NavbarLink :out="false" url="/">Home</NavbarLink> <NavbarLink :out="false" url="/">Home</NavbarLink>
<NavbarLink :out="false" url="/projects">Projects</NavbarLink> <NavbarLink :out="false" url="/projects">Projects</NavbarLink>
<NavbarLink :out="false" url="/resources">Resources</NavbarLink> <NavbarLink :out="false" url="/resources">Resources</NavbarLink>
<!--<NavbarLink :out="false" url="/stats">Stats</NavbarLink>--> <NavbarLink :out="false" url="/blog">Blog</NavbarLink>
<NavbarLink :out="true" url="http://github.com/ngn13/ngn13.fun">Source</NavbarLink> <NavbarLink :out="true" url="http://github.com/ngn13/ngn13.fun">Source</NavbarLink>
</div> </div>
</nav> </nav>

89
components/NewPost.vue Normal file
View File

@ -0,0 +1,89 @@
<template>
<main>
<h1>Add New Post</h1>
<div class="textareas">
<Input :keyup="function() { }" id="title" placeholder="Post Title" type="text"/>
<Input :keyup="function() { }" id="author" placeholder="Author" type="text"/>
</div>
<div class="textareas">
<textarea nor name="contenten" id="contenten" cols="30" rows="10" placeholder="Content (EN)"></textarea>
<textarea name="contenttr" id="contenttr" cols="30" rows="10" placeholder="Content (TR)"></textarea>
</div>
<Button :click="click">Post</Button>
</main>
</template>
<script>
import axios from 'axios';
import Input from './Input.vue';
import Button from './Button.vue';
export default {
methods: {
async click(e) {
const title = document.getElementById("title").value
const author = document.getElementById("author").value
const contenten = document.getElementById("contenten").value
const contenttr = document.getElementById("contenttr").value
const token = localStorage.getItem("token")
const res = await axios.post("/api/add_post", {
token: token,
title: title,
author: author,
content: {
tr: contenttr,
en: contenten
},
})
if(res.data["error"]!==0)
return alert("Error!")
alert("Post added!")
location.reload()
}
},
}
</script>
<style scoped>
h1{
color: var(--white);
font-size: 50px;
margin-bottom: 20px;
text-align: center;
}
textarea{
width: 500px;
font-size: 15px;
padding: 20px;
border-radius: 20px;
background: var(--dark-two);
border: none;
color: white;
outline: none;
resize: vertical;
height: 200px;
transition: .4s;
}
.textareas {
flex-direction: row;
display: flex;
gap: 20px;
}
textarea:focus {
box-shadow: var(--def-shadow);
}
main{
background-color: var(--dark-three);
padding: 50px;
margin-top: 50px;
display: flex;
flex-direction: column;
gap: 20px;
align-items: center;
justify-content: center;
}
</style>

0
components/Post.vue Normal file
View File

View File

@ -0,0 +1,42 @@
<template>
<nuxt-link :to="url">
<h1>{{ title }}</h1>
<p>{{ info }}</p>
<h2>{{ desc }}</h2>
</nuxt-link>
</template>
<script>
export default {
props: ["title", "desc", "info", "url"],
}
</script>
<style scoped>
a{
padding: 30px;
color: white;
background: var(--dark-two);
cursor: pointer;
text-decoration: none;
transition: .4s;
width: 70%;
}
a:hover{
box-shadow: var(--def-shadow);
}
h1{
font-size: 40px;
margin-bottom: 5px;
animation-name: colorAnimation;
animation-iteration-count: infinite;
animation-duration: 10s;
text-shadow: none;
}
h2{
margin-top: 10px;
}
</style>

36
links/index.js Normal file
View File

@ -0,0 +1,36 @@
const express = require("express");
const { MongoClient } = require("mongodb");
require("dotenv").config()
const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
const client = new MongoClient(process.env.DATABASE);
app.get("/:id", async (req,res)=>{
const id = req.params.id
await client.connect()
const db = await client.db("ngn13")
const col = await db.collection("projects")
const projects = await col.find().toArray()
console.log(projects)
for(let i=0; i<projects.length;i++){
if(projects[i]["name"].toLowerCase().replaceAll(" ", "")===id){
res.redirect(projects[i]["url"])
await col.updateOne({name:projects[i]["name"]}, {"$set": {"click": projects[i]["click"]+1}})
return await client.close()
}
}
await client.close()
return res.redirect("/projects")
})
export default {
path: "/l",
handler: app,
};

View File

@ -10,11 +10,15 @@ export default {
{ hid: "description", name: "description", content: "" }, { hid: "description", name: "description", content: "" },
{ name: "format-detection", content: "telephone=no" }, { name: "format-detection", content: "telephone=no" },
{ hid: "og:title", content: "[ngn]" }, { hid: "og:title", content: "[ngn]" },
{ hid: "og:description", content: "ngn's (very cool) personal website" }, { hid: "og:description", content: "personal website of ngn | read my blogs, check out my projects, discover cool resources" },
{ hid: "og:url", content: "https://ngn13.fun" }, { hid: "og:url", content: "https://ngn13.fun" },
{ name: "theme-color", content: "#0c16d1", "data-react-helmet":"true"}, { name: "theme-color", content: "#141414", "data-react-helmet":"true"},
], ],
link: [{ rel: "stylesheet", href: "https://unpkg.com/boxicons@2.1.4/css/boxicons.min.css" }]
link: [
{ rel: "stylesheet", href: "https://unpkg.com/boxicons@2.1.4/css/boxicons.min.css" },
{ rel: "stylesheet", href: "https://cdn.jsdelivr.net/gh/lipis/flag-icons@6.6.6/css/flag-icons.min.css" }
]
}, },
css: ["@/static/global.css"], css: ["@/static/global.css"],
plugins: [], plugins: [],
@ -27,5 +31,6 @@ export default {
build: {}, build: {},
serverMiddleware: { serverMiddleware: {
"/api": "~/api", "/api": "~/api",
"/l": "~/links",
}, },
}; };

293
package-lock.json generated
View File

@ -1,22 +1,25 @@
{ {
"name": "my-website", "name": "my-website",
"version": "1.0.0", "version": "2.2.0",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "my-website", "name": "my-website",
"version": "1.0.0", "version": "2.2.0",
"dependencies": { "dependencies": {
"@nuxtjs/axios": "^5.13.6", "@nuxtjs/axios": "^5.13.6",
"core-js": "^3.25.3", "core-js": "^3.25.3",
"dompurify": "^3.0.3",
"dotenv": "^16.0.3",
"express": "^4.18.2", "express": "^4.18.2",
"marked": "^5.0.3",
"mongodb": "^5.5.0",
"nuxt": "^2.15.8", "nuxt": "^2.15.8",
"vue": "^2.7.10", "vue": "^2.7.10",
"vue-server-renderer": "^2.7.10", "vue-server-renderer": "^2.7.10",
"vue-template-compiler": "^2.7.10" "vue-template-compiler": "^2.7.10"
}, }
"devDependencies": {}
}, },
"node_modules/@ampproject/remapping": { "node_modules/@ampproject/remapping": {
"version": "2.2.1", "version": "2.2.1",
@ -3412,6 +3415,11 @@
"source-map": "^0.6.1" "source-map": "^0.6.1"
} }
}, },
"node_modules/@types/webidl-conversions": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
"integrity": "sha512-xTE1E+YF4aWPJJeUzaZI5DRntlkY3+BCVJi0axFptnjGmAoWxkyREIh/XMrfxVLejwQxMCfDXdICo0VLxThrog=="
},
"node_modules/@types/webpack": { "node_modules/@types/webpack": {
"version": "4.41.33", "version": "4.41.33",
"resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.33.tgz", "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.33.tgz",
@ -3443,6 +3451,15 @@
"node": ">= 8" "node": ">= 8"
} }
}, },
"node_modules/@types/whatwg-url": {
"version": "8.2.2",
"resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.2.tgz",
"integrity": "sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==",
"dependencies": {
"@types/node": "*",
"@types/webidl-conversions": "*"
}
},
"node_modules/@vue/babel-helper-vue-jsx-merge-props": { "node_modules/@vue/babel-helper-vue-jsx-merge-props": {
"version": "1.4.0", "version": "1.4.0",
"resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-1.4.0.tgz", "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-1.4.0.tgz",
@ -4642,6 +4659,14 @@
"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
} }
}, },
"node_modules/bson": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/bson/-/bson-5.3.0.tgz",
"integrity": "sha512-ukmCZMneMlaC5ebPHXIkP8YJzNl5DC41N5MAIvKDqLggdao342t4McltoJBQfQya/nHBWAcSsYRqlXPoQkTJag==",
"engines": {
"node": ">=14.20.1"
}
},
"node_modules/buffer": { "node_modules/buffer": {
"version": "6.0.3", "version": "6.0.3",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
@ -6036,6 +6061,11 @@
"url": "https://github.com/fb55/domhandler?sponsor=1" "url": "https://github.com/fb55/domhandler?sponsor=1"
} }
}, },
"node_modules/dompurify": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.0.3.tgz",
"integrity": "sha512-axQ9zieHLnAnHh0sfAamKYiqXMJAVwu+LM/alQ7WDagoWessyWvMSFyW65CqF3owufNu8HBcE4cM2Vflu7YWcQ=="
},
"node_modules/domutils": { "node_modules/domutils": {
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz", "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz",
@ -8781,6 +8811,17 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/marked": {
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/marked/-/marked-5.0.3.tgz",
"integrity": "sha512-KUONa43Uk74uUNWMxh6lfaNYmSAsRMiDAaX8QBCCRVXzEufR0zX6T33vrGbvTnQLL02ungDM3KSzZtO+chJaHg==",
"bin": {
"marked": "bin/marked.js"
},
"engines": {
"node": ">= 18"
}
},
"node_modules/md5.js": { "node_modules/md5.js": {
"version": "1.3.5", "version": "1.3.5",
"resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
@ -8827,6 +8868,12 @@
"node": ">=4.3.0 <5.0.0 || >=5.10" "node": ">=4.3.0 <5.0.0 || >=5.10"
} }
}, },
"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==",
"optional": true
},
"node_modules/merge-descriptors": { "node_modules/merge-descriptors": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
@ -9066,6 +9113,78 @@
"mkdirp": "bin/cmd.js" "mkdirp": "bin/cmd.js"
} }
}, },
"node_modules/mongodb": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-5.5.0.tgz",
"integrity": "sha512-XgrkUgAAdfnZKQfk5AsYL8j7O99WHd4YXPxYxnh8dZxD+ekYWFRA3JktUsBnfg+455Smf75/+asoU/YLwNGoQQ==",
"dependencies": {
"bson": "^5.3.0",
"mongodb-connection-string-url": "^2.6.0",
"socks": "^2.7.1"
},
"engines": {
"node": ">=14.20.1"
},
"optionalDependencies": {
"saslprep": "^1.0.3"
},
"peerDependencies": {
"@aws-sdk/credential-providers": "^3.201.0",
"mongodb-client-encryption": ">=2.3.0 <3",
"snappy": "^7.2.2"
},
"peerDependenciesMeta": {
"@aws-sdk/credential-providers": {
"optional": true
},
"mongodb-client-encryption": {
"optional": true
},
"snappy": {
"optional": true
}
}
},
"node_modules/mongodb-connection-string-url": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.6.0.tgz",
"integrity": "sha512-WvTZlI9ab0QYtTYnuMLgobULWhokRjtC7db9LtcVfJ+Hsnyr5eo6ZtNAt3Ly24XZScGMelOcGtm7lSn0332tPQ==",
"dependencies": {
"@types/whatwg-url": "^8.2.1",
"whatwg-url": "^11.0.0"
}
},
"node_modules/mongodb-connection-string-url/node_modules/tr46": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz",
"integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==",
"dependencies": {
"punycode": "^2.1.1"
},
"engines": {
"node": ">=12"
}
},
"node_modules/mongodb-connection-string-url/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/mongodb-connection-string-url/node_modules/whatwg-url": {
"version": "11.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz",
"integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==",
"dependencies": {
"tr46": "^3.0.0",
"webidl-conversions": "^7.0.0"
},
"engines": {
"node": ">=12"
}
},
"node_modules/move-concurrently": { "node_modules/move-concurrently": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
@ -11777,6 +11896,18 @@
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
}, },
"node_modules/saslprep": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz",
"integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==",
"optional": true,
"dependencies": {
"sparse-bitfield": "^3.0.3"
},
"engines": {
"node": ">=6"
}
},
"node_modules/schema-utils": { "node_modules/schema-utils": {
"version": "2.7.1", "version": "2.7.1",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz",
@ -12039,6 +12170,15 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/smart-buffer": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
"integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
"engines": {
"node": ">= 6.0.0",
"npm": ">= 3.0.0"
}
},
"node_modules/snapdragon": { "node_modules/snapdragon": {
"version": "0.8.2", "version": "0.8.2",
"resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz",
@ -12219,6 +12359,24 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/socks": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz",
"integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==",
"dependencies": {
"ip": "^2.0.0",
"smart-buffer": "^4.2.0"
},
"engines": {
"node": ">= 10.13.0",
"npm": ">= 3.0.0"
}
},
"node_modules/socks/node_modules/ip": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz",
"integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ=="
},
"node_modules/sort-keys": { "node_modules/sort-keys": {
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz",
@ -12287,6 +12445,15 @@
"integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==",
"deprecated": "See https://github.com/lydell/source-map-url#deprecated" "deprecated": "See https://github.com/lydell/source-map-url#deprecated"
}, },
"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==",
"optional": true,
"dependencies": {
"memory-pager": "^1.0.2"
}
},
"node_modules/split-string": { "node_modules/split-string": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
@ -17315,6 +17482,11 @@
"source-map": "^0.6.1" "source-map": "^0.6.1"
} }
}, },
"@types/webidl-conversions": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
"integrity": "sha512-xTE1E+YF4aWPJJeUzaZI5DRntlkY3+BCVJi0axFptnjGmAoWxkyREIh/XMrfxVLejwQxMCfDXdICo0VLxThrog=="
},
"@types/webpack": { "@types/webpack": {
"version": "4.41.33", "version": "4.41.33",
"resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.33.tgz", "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.33.tgz",
@ -17345,6 +17517,15 @@
} }
} }
}, },
"@types/whatwg-url": {
"version": "8.2.2",
"resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.2.tgz",
"integrity": "sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==",
"requires": {
"@types/node": "*",
"@types/webidl-conversions": "*"
}
},
"@vue/babel-helper-vue-jsx-merge-props": { "@vue/babel-helper-vue-jsx-merge-props": {
"version": "1.4.0", "version": "1.4.0",
"resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-1.4.0.tgz", "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-1.4.0.tgz",
@ -18276,6 +18457,11 @@
"update-browserslist-db": "^1.0.10" "update-browserslist-db": "^1.0.10"
} }
}, },
"bson": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/bson/-/bson-5.3.0.tgz",
"integrity": "sha512-ukmCZMneMlaC5ebPHXIkP8YJzNl5DC41N5MAIvKDqLggdao342t4McltoJBQfQya/nHBWAcSsYRqlXPoQkTJag=="
},
"buffer": { "buffer": {
"version": "6.0.3", "version": "6.0.3",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
@ -19302,6 +19488,11 @@
"domelementtype": "^2.3.0" "domelementtype": "^2.3.0"
} }
}, },
"dompurify": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.0.3.tgz",
"integrity": "sha512-axQ9zieHLnAnHh0sfAamKYiqXMJAVwu+LM/alQ7WDagoWessyWvMSFyW65CqF3owufNu8HBcE4cM2Vflu7YWcQ=="
},
"domutils": { "domutils": {
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz", "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz",
@ -21355,6 +21546,11 @@
"object-visit": "^1.0.0" "object-visit": "^1.0.0"
} }
}, },
"marked": {
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/marked/-/marked-5.0.3.tgz",
"integrity": "sha512-KUONa43Uk74uUNWMxh6lfaNYmSAsRMiDAaX8QBCCRVXzEufR0zX6T33vrGbvTnQLL02ungDM3KSzZtO+chJaHg=="
},
"md5.js": { "md5.js": {
"version": "1.3.5", "version": "1.3.5",
"resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
@ -21392,6 +21588,12 @@
"readable-stream": "^2.0.1" "readable-stream": "^2.0.1"
} }
}, },
"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==",
"optional": true
},
"merge-descriptors": { "merge-descriptors": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
@ -21580,6 +21782,50 @@
"minimist": "^1.2.6" "minimist": "^1.2.6"
} }
}, },
"mongodb": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-5.5.0.tgz",
"integrity": "sha512-XgrkUgAAdfnZKQfk5AsYL8j7O99WHd4YXPxYxnh8dZxD+ekYWFRA3JktUsBnfg+455Smf75/+asoU/YLwNGoQQ==",
"requires": {
"bson": "^5.3.0",
"mongodb-connection-string-url": "^2.6.0",
"saslprep": "^1.0.3",
"socks": "^2.7.1"
}
},
"mongodb-connection-string-url": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.6.0.tgz",
"integrity": "sha512-WvTZlI9ab0QYtTYnuMLgobULWhokRjtC7db9LtcVfJ+Hsnyr5eo6ZtNAt3Ly24XZScGMelOcGtm7lSn0332tPQ==",
"requires": {
"@types/whatwg-url": "^8.2.1",
"whatwg-url": "^11.0.0"
},
"dependencies": {
"tr46": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz",
"integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==",
"requires": {
"punycode": "^2.1.1"
}
},
"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=="
},
"whatwg-url": {
"version": "11.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz",
"integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==",
"requires": {
"tr46": "^3.0.0",
"webidl-conversions": "^7.0.0"
}
}
}
},
"move-concurrently": { "move-concurrently": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
@ -23454,6 +23700,15 @@
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
}, },
"saslprep": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz",
"integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==",
"optional": true,
"requires": {
"sparse-bitfield": "^3.0.3"
}
},
"schema-utils": { "schema-utils": {
"version": "2.7.1", "version": "2.7.1",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz",
@ -23666,6 +23921,11 @@
"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
"integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="
}, },
"smart-buffer": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
"integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg=="
},
"snapdragon": { "snapdragon": {
"version": "0.8.2", "version": "0.8.2",
"resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz",
@ -23811,6 +24071,22 @@
} }
} }
}, },
"socks": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz",
"integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==",
"requires": {
"ip": "^2.0.0",
"smart-buffer": "^4.2.0"
},
"dependencies": {
"ip": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz",
"integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ=="
}
}
},
"sort-keys": { "sort-keys": {
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz",
@ -23867,6 +24143,15 @@
"resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz",
"integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==" "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw=="
}, },
"sparse-bitfield": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz",
"integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==",
"optional": true,
"requires": {
"memory-pager": "^1.0.2"
}
},
"split-string": { "split-string": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",

View File

@ -1,6 +1,6 @@
{ {
"name": "my-website", "name": "my-website",
"version": "2.1.0", "version": "2.2.0",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "nuxt", "dev": "nuxt",
@ -11,7 +11,11 @@
"dependencies": { "dependencies": {
"@nuxtjs/axios": "^5.13.6", "@nuxtjs/axios": "^5.13.6",
"core-js": "^3.25.3", "core-js": "^3.25.3",
"dompurify": "^3.0.3",
"dotenv": "^16.0.3",
"express": "^4.18.2", "express": "^4.18.2",
"marked": "^5.0.3",
"mongodb": "^5.5.0",
"nuxt": "^2.15.8", "nuxt": "^2.15.8",
"vue": "^2.7.10", "vue": "^2.7.10",
"vue-server-renderer": "^2.7.10", "vue-server-renderer": "^2.7.10",

178
pages/blog/_id/index.vue Normal file
View File

@ -0,0 +1,178 @@
<template>
<div class="all">
<Navbar />
<Header>
<glitch class="title">{{ post.title }}</glitch>
<p>{{ post.info }}</p>
</Header>
<div class="postcontain">
<div class="lang">
<button v-if="lang==='en'" class="bl bs">EN <span class="fi fi-gb"></span></button>
<button v-on:click="toggle_lang" v-else class="bl">EN <span class="fi fi-gb"></span></button>
<button v-if="lang==='tr'" class="br bs">TR <span class="fi fi-tr"></span></button>
<button v-on:click="toggle_lang" v-else class="br">TR <span class="fi fi-tr"></span></button>
</div>
<main class="postself" v-if="lang==='en'" v-html="en"></main>
<main class="postself" v-else v-html="tr"></main>
</div>
</div>
</template>
<script>
import Navbar from "../../../components/Navbar.vue";
import Header from "../../../components/Header.vue";
import axios from "axios";
import * as DOMPurify from "dompurify";
import marked from "marked";
export default {
head() {
return {
title: "[ngn] | " + this.post.title,
meta: [
{
hid: "description",
name: "description",
content: "read my blog posts"
}
]
};
},
methods: {
toggle_lang(){
this.lang = this.lang==="tr" ? "en" : "tr"
localStorage.setItem("lang", this.lang)
}
},
data() {
return {
post: {},
lang: "",
en: "",
tr: "",
}
},
async created() {
const res = await axios.get(`/api/get_post?id=${this.$route.params.id}`)
if (res.data["error"] === 3)
return this.$router.push({ path: "/blog" })
this.post = res.data["post"]
this.en = DOMPurify.sanitize(marked.parse(this.post["content"]["en"]))
this.tr = DOMPurify.sanitize(marked.parse(this.post["content"]["tr"]))
this.lang = localStorage.getItem("lang")!==undefined&&(localStorage.getItem("lang")==="tr"||localStorage.getItem("lang")==="en") ? localStorage.getItem("lang") : "en"
}
}
</script>
<style scoped>
glitch {
font-size: 80px;
}
p {
font-size: 30px;
}
span{
width: 30px;
border-radius: 5px;
}
.info {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
}
.lang {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
margin-top: 20px;
}
button{
padding: 10px 30px 10px 30px;
font-size: 20px;
background-color: var(--dark-two);
border: none;
cursor: pointer;
color: white
}
.bs{
background-color: var(--dark-three);
}
.bl{
border-radius: 15px 0px 0px 0px;
}
.br{
border-radius: 0px 15px 0px 0px;
}
.postcontain{
padding: 50px;
}
.postself {
text-align: left;
font-size: 30px;
color: white;
padding: 20px 40px 70px 40px;
line-height: 40px;
border-radius: 15px;
background-color: var(--dark-three);
}
</style>
<style>
.postself code {
background: var(--dark-two);
border-radius: 5px;
font-size: 18px;
padding: 5px;
font-style: italic;
}
.postself h1{
margin-top: 70px;
margin-bottom: 20px;
}
.postself h2{
margin-top: 60px;
margin-bottom: 20px;
}
.postself h3{
margin-top: 50px;
margin-bottom: 20px;
}
.postself h4{
margin-top: 40px;
margin-bottom: 20px;
}
.postself h5{
margin-top: 60px;
margin-bottom: 30px;
}
.postself a{
animation-name: colorAnimation;
animation-iteration-count: infinite;
animation-duration: 10s;
text-shadow: none;
}
li{
list-style-type: none;
}
</style>

91
pages/blog/index.vue Normal file
View File

@ -0,0 +1,91 @@
<template>
<div>
<Navbar />
<Header>
<glitch>/dev/</glitch>blog
</Header>
<div class="blogs">
<Input :keyup="keyup" placeholder="Search post" type="text"/>
<PostPreview v-for="post in posts" :key="post" :title="post.title" :desc="post.desc" :info="post.info" :url="post.url">
{{ post.desc }}
</PostPreview>
</div>
<NewPost v-if="logged"/>
</div>
</template>
<script>
import Navbar from "../../components/Navbar.vue";
import Header from "../../components/Header.vue";
import NewPost from "../../components/NewPost.vue";
import PostPreview from "../../components/PostPreview.vue";
import axios from "axios";
export default {
head() {
return {
title: "[ngn] | blog",
meta: [
{
hid: "description",
name: "description",
content: "read my blog posts"
}
]
};
},
data() {
return {
logged: false,
posts: [],
all: []
};
},
mounted: async function () {
if (localStorage.getItem("token"))
this.logged = true;
const res = await axios.get("/api/get_posts");
let array = res.data["posts"]
let newarray = []
for(let i=0;i<array.length;i++){
newarray.push({
title: array[i].title,
desc: array[i].desc,
info: array[i].info,
url: `/blog/${array[i].title.toLowerCase().replaceAll(" ", "")}`
})
}
this.posts = newarray;
this.all = newarray;
},
methods: {
keyup(e) {
let val = e.target.value
// search looks at name and info
this.posts = []
for(let i = 0; i < this.all.length; i++){
if(this.all[i].title.toLowerCase().includes(val.toLowerCase()))
this.posts.push(this.all[i])
else if(this.all[i].info.toLowerCase().includes(val.toLowerCase()))
this.posts.push(this.all[i])
}
}
},
}
</script>
<style scoped>
.blogs {
padding: 50px;
gap: 35px;
display: flex;
flex-direction: column;
gap: 30px;
align-items: center;
}
</style>

View File

@ -16,25 +16,28 @@
<br> <br>
electronics electronics
<br> <br>
gaming
<br>
simply: everything about computers! simply: everything about computers!
</h2> </h2>
</Card> </Card>
<Card> <Card>
<h1>👉 Checkout my socials</h1> <h1>👉 Contact me</h1>
<h2>Here you can find my socials for following platforms:</h2> <h2>You can contact me on the following platforms:</h2>
<br>
<a href="https://discord.com/users/568131907368386565"><i class='bx bxl-discord-alt'></i> Discord</a> <a href="https://discord.com/users/568131907368386565"><i class='bx bxl-discord-alt'></i> Discord</a>
<br> <br>
<a href="https://github.com/ngn13"><i class='bx bxl-github'></i> Github</a> <a href="https://github.com/ngn13"><i class='bx bxl-github'></i> Github</a>
<br> <br>
<a href="https://www.reddit.com/user/_ngn"><i class='bx bxl-reddit'></i> Reddit</a> <a href="mailto:ngn13proton@proton.me"><i class='bx bxl-mastodon'></i> Mail</a>
<br> <br>
<a href="https://fosstodon.org/@ngn"><i class='bx bxl-mastodon'></i> Fosstodon</a> <h2>or private message me on </h2>
<a><i>[matrix]</i> @ngn:matrix.ngn13.fun</a>
</Card> </Card>
</div> </div>
<Logout v-if="logged"/> <Logout v-if="logged"/>
<div class="version"> <div class="version">
<p>v2.1</p> <p>v2.2</p>
</div> </div>
</div> </div>
</template> </template>
@ -53,7 +56,7 @@ export default {
{ {
hid: "description", hid: "description",
name: "description", name: "description",
content: "ngn's Personal Website | Home Page" content: "homepage of my website"
} }
] ]
} }
@ -84,6 +87,9 @@ export default {
font-size: 15px; font-size: 15px;
} }
i{
font-style: normal;
}
@media only screen and (max-width: 1076px) { @media only screen and (max-width: 1076px) {
.info { .info {

View File

@ -6,7 +6,8 @@
</Header> </Header>
<div class="projects"> <div class="projects">
<ProjectList v-for="project in projects" :key="project"> <ProjectList v-for="project in projects" :key="project">
<Project v-for="p in project" :key="p" :name="p.name" :desc="p.desc" :url="p.url"/> <Project v-if="logged" v-for="p in project" :key="p" :name="`${p.name} (${p.click})`" :desc="p.desc" :url="p.url"/>
<Project v-if="!logged" v-for="p in project" :key="p" :name="p.name" :desc="p.desc" :url="p.url"/>
</ProjectList> </ProjectList>
</div> </div>
<NewProject v-if="logged"/> <NewProject v-if="logged"/>
@ -22,12 +23,12 @@ import axios from "axios";
export default { export default {
head() { head() {
return { return {
title: "[ngn]", title: "[ngn] | projects",
meta: [ meta: [
{ {
hid: "description", hid: "description",
name: "description", name: "description",
content: "ngn's Personal Website | Projects Page" content: "check out my projects"
} }
] ]
} }
@ -49,7 +50,12 @@ export default {
let project = [] let project = []
for(let i = 0; i<all.length; i++){ for(let i = 0; i<all.length; i++){
if(project.length!==3) if(project.length!==3)
project.push(all[i]) project.push({
name: all[i]["name"],
desc: all[i]["desc"],
click: all[i]["click"],
url: `/l/${all[i]["name"].toLowerCase().replaceAll(" ", "")}`
})
else{ else{
projects.push(project) projects.push(project)
project = [] project = []
@ -66,10 +72,9 @@ export default {
<style> <style>
.projects{ .projects{
margin-top: 20px; padding: 50px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
padding-bottom: 30px;
} }
@media only screen and (max-width: 1121px) { @media only screen and (max-width: 1121px) {

View File

@ -19,6 +19,18 @@ import Input from '../components/Input.vue';
import NewResource from '../components/NewResource.vue'; import NewResource from '../components/NewResource.vue';
export default { export default {
head() {
return {
title: "[ngn] | resources",
meta: [
{
hid: "description",
name: "description",
content: "discover new resources"
}
]
}
},
data() { data() {
return { return {
header: "resources", header: "resources",