Worked on the add button + backend

This commit is contained in:
Daniel 2022-04-22 16:43:22 +04:30
parent f39baae69b
commit 9e72a0a2a7
11 changed files with 4093 additions and 65 deletions

View File

@ -1,16 +1,22 @@
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import './App.css'; import './styles/App.css';
import List from './componets/List'; import List from './componets/List';
import AddModal from './componets/AddModal';
function App() { function App() {
const [data, setData] = useState([]); const [data, setData] = useState([]);
const [isAdding, setIsAdding] = useState(false);
function exitAdding() {
setIsAdding(!isAdding)
}
useEffect(() => { useEffect(() => {
async function fetchData() { async function fetchData() {
const res = await fetch('/get'); const res = await fetch('/get');
const resJSON = await res.json(); const resJSON = await res.json();
console.log(resJSON) const Data = resJSON.sort((a, b) => { return b-a });
setData(resJSON); setData(Data);
} }
fetchData(); fetchData();
@ -21,31 +27,13 @@ function App() {
<div className="head"> <div className="head">
<input className="search" type="search" placeholder="Search bookmarks"/> <input className="search" type="search" placeholder="Search bookmarks"/>
<button className="search-btn"><span className="material-icons-outlined md-36">search</span></button> <button className="search-btn"><span className="material-icons-outlined md-36">search</span></button>
<button className="add-btn"><span className="material-icons-outlined md-36">add</span></button> <button className="add-btn"><span className="material-icons-outlined md-36" onClick={() => setIsAdding(true)}>add</span></button>
<button className="settings-btn"><span className="material-icons-outlined md-36">settings</span></button> <button className="settings-btn"><span className="material-icons-outlined md-36">settings</span></button>
</div> </div>
<List data={data} /> <List data={data} />
{isAdding ? <AddModal onExit={exitAdding} /> : null}
</div> </div>
); );
} }
export default App; export default App;
// fetch("/post", {
// // Adding method type
// method: "POST",
// // Adding body or contents to send
// body: JSON.stringify({
// name: "foo",
// title: "bar",
// link: liveinternet.ru,
// tag: Red
// }),
// // Adding headers to the request
// headers: {
// "Content-type": "application/json; charset=UTF-8"
// }
// });

View File

@ -0,0 +1,75 @@
import { useState } from 'react';
import '../styles/Modal.css';
const AddModal = ({onExit}) => {
const [name, setName] = useState('');
const [link, setLink] = useState('');
const [tag, setTag] = useState('');
function SetName(e) {
setName(e.target.value);
}
function SetLink(e) {
setLink(e.target.value);
}
function SetTag(e) {
setTag(e.target.value);
}
async function submitBookmark() {
if(name != '' && link != '' && tag != '') {
fetch("/post", {
// Adding method type
method: "POST",
// Adding body or contents to send
body: JSON.stringify({
name: name,
title: "foo",
link: link,
tag: tag
}),
// Adding headers to the request
headers: {
"Content-type": "application/json; charset=UTF-8"
}
});
onExit();
}
else {
alert('Please fill all fields...');
}
}
function abort(e) {
if (e.target.className == "overlay" || e.target.className == "cancel-btn") {
onExit();
}
}
return (
<div className='overlay' onClick={abort}>
<div className='box'>
<div className='modal-content'>
<h2>Add Bookmark</h2>
<h3>Name:</h3>
<input onChange={SetName} className="modal-input" type="search" placeholder="e.g. Example Tutorial"/>
<h3>Link:</h3>
<input onChange={SetLink} className="modal-input" type="search" placeholder="e.g. https://example.com/"/>
<h3>Tag:</h3>
<input onChange={SetTag} className="modal-input" type="search" placeholder="e.g. Tutorials"/>
<button onClick={submitBookmark} className="upload-btn"><span className="material-icons-outlined md-36">upload</span></button>
<button className="cancel-btn">Cancel</button>
</div>
</div>
</div>
)
}
export default AddModal

View File

@ -1,6 +1,6 @@
const List = ({data}) => { import '../styles/List.css';
console.log(data)
const List = ({data}) => {
return ( return (
<table className="table"> <table className="table">
<thead> <thead>
@ -14,13 +14,18 @@ const List = ({data}) => {
</thead> </thead>
<tbody> <tbody>
{data.map((e, i) => { {data.map((e, i) => {
try {
const url = new URL(e.link)
return <tr key={i}> return <tr key={i}>
<td>{i + 1}</td> <td>{i + 1}</td>
<td>{e.name}</td> <td>{e.name}</td>
<td>{e.title}</td> <td>{e.title}</td>
<td>{e.link}</td> <td><a href={e.link}>{url.hostname}</a></td>
<td>{e.tag}</td> <td>{e.tag}</td>
</tr> </tr>
} catch (e) {
console.log(e)
}
})} })}
</tbody> </tbody>
</table> </table>

View File

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import './index.css'; import './styles/index.css';
import App from './App'; import App from './App';
ReactDOM.render( ReactDOM.render(

View File

@ -12,25 +12,23 @@
.search { .search {
border-top-left-radius: 10px; border-top-left-radius: 10px;
border-bottom-left-radius: 10px; border-bottom-left-radius: 10px;
padding: 10px;
font-size: 1.5rem; font-size: 1.5rem;
padding-left: 10px;
width: 40%;
} }
.search-btn { .search-btn {
padding: 5px;
border-top-right-radius: 10px; border-top-right-radius: 10px;
border-bottom-right-radius: 10px; border-bottom-right-radius: 10px;
color: #1f2c38b6; color: #1f2c38b6;
} }
.settings-btn { .settings-btn {
padding: 5px;
border-radius: 10px; border-radius: 10px;
color: #1f2c38b6; color: #1f2c38b6;
} }
.add-btn { .add-btn {
padding: 5px;
border-radius: 10px; border-radius: 10px;
color: #1f2c38b6; color: #1f2c38b6;
margin-left: auto; margin-left: auto;
@ -42,23 +40,3 @@ textarea:focus, input:focus{
} }
.material-icons-outlined.md-36 { font-size: 36px; } .material-icons-outlined.md-36 { font-size: 36px; }
.table {
width: 100%;
text-align: left;
padding-top: 20px;
}
.table td {
font-size: 1.3rem;
padding: 5px;
}
.table th {
font-size: 1.6rem;
padding: 5px;
}
.table tbody tr:nth-of-type(2n-1) {
background-color:#273949;
}

View File

@ -0,0 +1,29 @@
.table {
width: 100%;
text-align: left;
padding-top: 20px;
}
.table td {
font-size: 1.3rem;
padding: 5px;
}
.table th {
font-size: 1.6rem;
padding: 5px;
}
.table tbody tr:nth-of-type(2n-1) {
background-color:#273949;
}
.table a {
text-decoration: none;
color: rgb(194, 193, 193);
font-size: 1rem;
}
.table a:hover {
text-decoration: underline;
}

View File

@ -0,0 +1,56 @@
.overlay {
position: absolute;
top: 0;
left: 0;
background-color: rgba(49, 64, 73, 0.781);
width: 100vw;
height: 100vh;
}
.box {
box-shadow: rgba(0, 0, 0, 0.19) 0px 10px 20px, rgba(0, 0, 0, 0.23) 0px 6px 6px; position: absolute;
top: 20%;
left: 20%;
background-color: #1b2e3f;
width: 60%;
height: 60%;
border-radius: 10px;
overflow-x: hidden;
overflow-y: auto;
}
.box h2 {
margin-top: -1px;
text-align: center;
}
.modal-content {
padding: 20px;
}
.modal-input {
border-radius: 10px;
padding: 10px;
font-size: 1.3rem;
width: 100%;
}
.upload-btn {
padding: 5px;
border-radius: 10px;
color: #1f2c38b6;
margin-top: 60px;
display: block;
margin-left: auto;
margin-right: auto;
}
.cancel-btn {
padding: 5px;
border-radius: 10px;
color: #1f2c38b6;
margin-top: 25px;
display: block;
margin-left: auto;
margin-right: auto;
}

File diff suppressed because it is too large Load Diff

View File

@ -4,12 +4,16 @@
"description": "The backend", "description": "The backend",
"main": "server.js", "main": "server.js",
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\" && exit 1" "dev": "nodemon server.js"
}, },
"author": "", "author": "",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"express": "^4.17.3", "express": "^4.17.3",
"mongodb": "^4.5.0" "mongodb": "^4.5.0",
"phantom": "^6.3.0"
},
"devDependencies": {
"nodemon": "^2.0.15"
} }
} }

View File

@ -1,6 +1,8 @@
const express = require('express'); const express = require('express');
const app = express(); const app = express();
const { MongoClient } = require('mongodb'); const { MongoClient } = require('mongodb');
const phantom = require('phantom');
const port = process.env.PORT || 3001; const port = process.env.PORT || 3001;
const uri = "mongodb://localhost:27017"; const uri = "mongodb://localhost:27017";
@ -14,9 +16,11 @@ app.get('/get', async (req, res) => {
res.send(data); res.send(data);
}); });
app.post('/post', (req, res) => { app.post('/post', async (req, res) => {
// insertDoc(req.body); const title = await getTitle(req.body.link);
console.log(req.body) req.body.title = title;
insertDoc(req.body);
}); });
async function insertDoc(doc) { async function insertDoc(doc) {
@ -26,8 +30,6 @@ async function insertDoc(doc) {
const database = client.db("sample_db"); const database = client.db("sample_db");
const list = database.collection("list"); const list = database.collection("list");
const result = await list.insertOne(doc); const result = await list.insertOne(doc);
console.log('DONE');
} }
catch(err) { catch(err) {
@ -59,6 +61,20 @@ async function getDoc() {
} }
} }
async function getTitle(url) {
const instance = await phantom.create();
const page = await instance.createPage();
await page.on('onResourceRequested', function(requestData) {
console.info('Requesting', requestData.url);
});
const status = await page.open(url);
const title = await page.property('title');
await instance.exit();
return title;
}
app.listen(port, () => { app.listen(port, () => {
console.log(`Success! running on port ${port}.`); console.log(`Success! running on port ${port}.`);
}); });