renamed
@@ -0,0 +1,2 @@
|
||||
PORT=3001
|
||||
MONGODB_URI=mongodb+srv://admin:admin@cluster1.ciuxwxd.mongodb.net/personApp?retryWrites=true&w=majority
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"files": {
|
||||
"main.css": "/static/css/main.305410ed.css",
|
||||
"main.js": "/static/js/main.dde63dc0.js",
|
||||
"index.html": "/index.html",
|
||||
"main.305410ed.css.map": "/static/css/main.305410ed.css.map",
|
||||
"main.dde63dc0.js.map": "/static/js/main.dde63dc0.js.map"
|
||||
},
|
||||
"entrypoints": [
|
||||
"static/css/main.305410ed.css",
|
||||
"static/js/main.dde63dc0.js"
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 3.8 KiB |
@@ -0,0 +1 @@
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Web site created using create-react-app"/><link rel="apple-touch-icon" href="/logo192.png"/><link rel="manifest" href="/manifest.json"/><title>React App</title><script defer="defer" src="/static/js/main.dde63dc0.js"></script><link href="/static/css/main.305410ed.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
|
||||
|
After Width: | Height: | Size: 5.2 KiB |
|
After Width: | Height: | Size: 9.4 KiB |
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"short_name": "React App",
|
||||
"name": "Create React App Sample",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.ico",
|
||||
"sizes": "64x64 32x32 24x24 16x16",
|
||||
"type": "image/x-icon"
|
||||
},
|
||||
{
|
||||
"src": "logo192.png",
|
||||
"type": "image/png",
|
||||
"sizes": "192x192"
|
||||
},
|
||||
{
|
||||
"src": "logo512.png",
|
||||
"type": "image/png",
|
||||
"sizes": "512x512"
|
||||
}
|
||||
],
|
||||
"start_url": ".",
|
||||
"display": "standalone",
|
||||
"theme_color": "#000000",
|
||||
"background_color": "#ffffff"
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
# https://www.robotstxt.org/robotstxt.html
|
||||
User-agent: *
|
||||
Disallow:
|
||||
@@ -0,0 +1,2 @@
|
||||
.error{color:red}.error,.normal{background:#d3d3d3;border-radius:5px;border-style:solid;font-size:20px;margin-bottom:10px;padding:10px}.normal{color:green}
|
||||
/*# sourceMappingURL=main.305410ed.css.map*/
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"static/css/main.305410ed.css","mappings":"AAAA,OACE,SAOF,CACA,eAPE,kBAAqB,CAGrB,iBAAkB,CADlB,kBAAmB,CADnB,cAAe,CAIf,kBAAmB,CADnB,YAWF,CARA,QACE,WAOF","sources":["index.css"],"sourcesContent":[".error {\n color: red;\n background: lightgrey;\n font-size: 20px;\n border-style: solid;\n border-radius: 5px;\n padding: 10px;\n margin-bottom: 10px;\n}\n.normal {\n color: green;\n background: lightgrey;\n font-size: 20px;\n border-style: solid;\n border-radius: 5px;\n padding: 10px;\n margin-bottom: 10px;\n}\n"],"names":[],"sourceRoot":""}
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* @license React
|
||||
* react-dom.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* react-jsx-runtime.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* react.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* scheduler.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* @license React
|
||||
* react-dom.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* react-jsx-runtime.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* react.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* scheduler.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* @license React
|
||||
* react-dom.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* react-jsx-runtime.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* react.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* scheduler.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* @license React
|
||||
* react-dom.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* react-jsx-runtime.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* react.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* scheduler.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* @license React
|
||||
* react-dom.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* react-jsx-runtime.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* react.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* scheduler.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* @license React
|
||||
* react-dom.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* react-jsx-runtime.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* react.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* scheduler.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* @license React
|
||||
* react-dom.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* react-jsx-runtime.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* react.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* scheduler.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* @license React
|
||||
* react-dom.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* react-jsx-runtime.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* react.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* scheduler.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* @license React
|
||||
* react-dom.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* react-jsx-runtime.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* react.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* scheduler.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
@@ -0,0 +1,36 @@
|
||||
const mongoose = require("mongoose");
|
||||
|
||||
mongoose.set("strictQuery", false);
|
||||
const url = process.env.MONGODB_URI;
|
||||
|
||||
console.log("connecting to MongoDB");
|
||||
mongoose
|
||||
.connect(url)
|
||||
.then((res) => {
|
||||
console.log("connected to MongoDB");
|
||||
})
|
||||
.catch((err) => console.log("error connecting to MongoDB", err.message));
|
||||
|
||||
const personSchema = new mongoose.Schema({
|
||||
name: { type: String, minLength: 3 },
|
||||
number: {
|
||||
type: String,
|
||||
validate: {
|
||||
validator: function (v) {
|
||||
return /\d{2,3}-\d{5,25}/.test(v);
|
||||
},
|
||||
message: (props) => `${props.value} is not a valid phone number!`,
|
||||
},
|
||||
required: [true, "User phone number required"],
|
||||
},
|
||||
});
|
||||
|
||||
personSchema.set("toJSON", {
|
||||
transform: (document, returnedObject) => {
|
||||
returnedObject.id = returnedObject._id.toString();
|
||||
delete returnedObject._id;
|
||||
delete returnedObject.__v;
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = mongoose.model("Person", personSchema);
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"name": "p3exercise",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"start": "nodemon server.js"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"cors": "^2.8.5",
|
||||
"dotenv": "^16.1.4",
|
||||
"express": "^4.18.2",
|
||||
"mongoose": "^7.2.2",
|
||||
"morgan": "^1.10.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"nodemon": "^2.0.22"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
require("dotenv").config();
|
||||
const express = require("express");
|
||||
const cors = require("cors");
|
||||
const morgan = require("morgan");
|
||||
const Person = require("./models/person");
|
||||
|
||||
const app = express();
|
||||
|
||||
const errorHandler = (error, req, res, next) => {
|
||||
console.log(err.message);
|
||||
if (err.name === "CastError")
|
||||
return res.status(404).send({ error: "malformatted id" });
|
||||
else if (err.name === "ValidationError")
|
||||
return res.status(400).json({ error: err.message });
|
||||
next(err);
|
||||
};
|
||||
|
||||
morgan.token("type", function (req, res) {
|
||||
return String(JSON.stringify(req.body));
|
||||
});
|
||||
// middleware to deal with same origin
|
||||
app.use(cors());
|
||||
// middleware to allow express to deliver html
|
||||
// it is unclear to me why i cant just make a get method that deals with that
|
||||
app.use(express.static("build"));
|
||||
// transfprms it to jsontransfprms it to json
|
||||
app.use(express.json());
|
||||
// adding additional information on request
|
||||
app.use(
|
||||
morgan(":method :url :status :res[content-length] - :response-time ms :type")
|
||||
);
|
||||
app.use(errorHandler);
|
||||
|
||||
app.get("/api/persons", (req, res, next) => {
|
||||
Person.find({})
|
||||
.then((persons) => {
|
||||
res.json(persons);
|
||||
})
|
||||
.catch((err) => next(err));
|
||||
});
|
||||
/* currently not used
|
||||
const date = new Date();
|
||||
app.get("/api/info", (req, res) => {
|
||||
res.send(`Phonebook has info for ${data.length} persons <br />${date}`);
|
||||
});
|
||||
*/
|
||||
app.get("/api/persons/:id", (req, res, next) => {
|
||||
Person.findById(req.params.id)
|
||||
.then((person) => {
|
||||
if (person) res.json(person);
|
||||
else res.status(404).end();
|
||||
})
|
||||
.catch((err) => next(err));
|
||||
});
|
||||
app.post("/api/persons", (req, res, next) => {
|
||||
const body = req.body;
|
||||
const person = new Person({
|
||||
name: body.name,
|
||||
number: body.number,
|
||||
id: Math.floor(Math.random() * 1000),
|
||||
});
|
||||
person
|
||||
.save()
|
||||
.then((savedPerson) => {
|
||||
res.json(savedPerson);
|
||||
})
|
||||
.catch((err) => next(err));
|
||||
});
|
||||
app.put("/api/persons/:id", (req, res, next) => {
|
||||
const { name, number } = req.body;
|
||||
Person.findOneAndUpdate(
|
||||
{ id: req.params.id },
|
||||
{ name, number },
|
||||
{ new: true, runValidators: true, context: "query" }
|
||||
)
|
||||
.then((updatedPerson) => {
|
||||
res.json(updatedPerson);
|
||||
})
|
||||
.catch((err) => next(err));
|
||||
});
|
||||
app.delete("/api/persons/:id", (req, res, next) => {
|
||||
Person.findByIdAndRemove(req.params.id)
|
||||
.then((result) => {
|
||||
console.log("result:", result);
|
||||
res.status(204).end();
|
||||
})
|
||||
.catch((err) => next(err));
|
||||
});
|
||||
|
||||
const PORT = process.env.PORT || 3001;
|
||||
app.listen(PORT, () => {
|
||||
console.log(`Server running on port ${PORT}`);
|
||||
});
|
||||
@@ -0,0 +1,8 @@
|
||||
#! /usr/bin/bash
|
||||
|
||||
rm -r ./frontend/build
|
||||
echo -n "removed build from frontend"
|
||||
npm run build --prefix frontend
|
||||
echo -n "made new build"
|
||||
cp -r ./frontend/build ./backend
|
||||
echo -n "copied build to frontend"
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"files": {
|
||||
"main.css": "/static/css/main.305410ed.css",
|
||||
"main.js": "/static/js/main.dde63dc0.js",
|
||||
"index.html": "/index.html",
|
||||
"main.305410ed.css.map": "/static/css/main.305410ed.css.map",
|
||||
"main.dde63dc0.js.map": "/static/js/main.dde63dc0.js.map"
|
||||
},
|
||||
"entrypoints": [
|
||||
"static/css/main.305410ed.css",
|
||||
"static/js/main.dde63dc0.js"
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 3.8 KiB |
@@ -0,0 +1 @@
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Web site created using create-react-app"/><link rel="apple-touch-icon" href="/logo192.png"/><link rel="manifest" href="/manifest.json"/><title>React App</title><script defer="defer" src="/static/js/main.dde63dc0.js"></script><link href="/static/css/main.305410ed.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
|
||||
|
After Width: | Height: | Size: 5.2 KiB |
|
After Width: | Height: | Size: 9.4 KiB |
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"short_name": "React App",
|
||||
"name": "Create React App Sample",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.ico",
|
||||
"sizes": "64x64 32x32 24x24 16x16",
|
||||
"type": "image/x-icon"
|
||||
},
|
||||
{
|
||||
"src": "logo192.png",
|
||||
"type": "image/png",
|
||||
"sizes": "192x192"
|
||||
},
|
||||
{
|
||||
"src": "logo512.png",
|
||||
"type": "image/png",
|
||||
"sizes": "512x512"
|
||||
}
|
||||
],
|
||||
"start_url": ".",
|
||||
"display": "standalone",
|
||||
"theme_color": "#000000",
|
||||
"background_color": "#ffffff"
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
# https://www.robotstxt.org/robotstxt.html
|
||||
User-agent: *
|
||||
Disallow:
|
||||
@@ -0,0 +1,2 @@
|
||||
.error{color:red}.error,.normal{background:#d3d3d3;border-radius:5px;border-style:solid;font-size:20px;margin-bottom:10px;padding:10px}.normal{color:green}
|
||||
/*# sourceMappingURL=main.305410ed.css.map*/
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"static/css/main.305410ed.css","mappings":"AAAA,OACE,SAOF,CACA,eAPE,kBAAqB,CAGrB,iBAAkB,CADlB,kBAAmB,CADnB,cAAe,CAIf,kBAAmB,CADnB,YAWF,CARA,QACE,WAOF","sources":["index.css"],"sourcesContent":[".error {\n color: red;\n background: lightgrey;\n font-size: 20px;\n border-style: solid;\n border-radius: 5px;\n padding: 10px;\n margin-bottom: 10px;\n}\n.normal {\n color: green;\n background: lightgrey;\n font-size: 20px;\n border-style: solid;\n border-radius: 5px;\n padding: 10px;\n margin-bottom: 10px;\n}\n"],"names":[],"sourceRoot":""}
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* @license React
|
||||
* react-dom.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* react-jsx-runtime.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* react.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* scheduler.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"persons": [
|
||||
{
|
||||
"name": "dsdsd",
|
||||
"number": "sdsdsds",
|
||||
"id": 6
|
||||
},
|
||||
{
|
||||
"name": "dfadf",
|
||||
"number": "dafasdfa",
|
||||
"id": 7
|
||||
},
|
||||
{
|
||||
"name": "sdfadfadaf",
|
||||
"number": "adfadfadsf",
|
||||
"id": 9
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"name": "p1",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@testing-library/jest-dom": "^5.16.5",
|
||||
"@testing-library/react": "^13.4.0",
|
||||
"@testing-library/user-event": "^13.5.0",
|
||||
"axios": "^1.4.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-scripts": "5.0.1",
|
||||
"web-vitals": "^2.1.4"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
"build": "react-scripts build",
|
||||
"test": "react-scripts test",
|
||||
"eject": "react-scripts eject",
|
||||
"server": "npx json-server --port 3001 --watch db.json"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": [
|
||||
"react-app",
|
||||
"react-app/jest"
|
||||
]
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
],
|
||||
"development": [
|
||||
"last 1 chrome version",
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"json-serve": "^0.1.0"
|
||||
},
|
||||
"proxy": "http://localhost:3001"
|
||||
}
|
||||
|
After Width: | Height: | Size: 3.8 KiB |
@@ -0,0 +1,43 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta
|
||||
name="description"
|
||||
content="Web site created using create-react-app"
|
||||
/>
|
||||
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
|
||||
<!--
|
||||
manifest.json provides metadata used when your web app is installed on a
|
||||
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
||||
-->
|
||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
||||
<!--
|
||||
Notice the use of %PUBLIC_URL% in the tags above.
|
||||
It will be replaced with the URL of the `public` folder during the build.
|
||||
Only files inside the `public` folder can be referenced from the HTML.
|
||||
|
||||
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
||||
work correctly both with client-side routing and a non-root public URL.
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
-->
|
||||
<title>React App</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
<!--
|
||||
This HTML file is a template.
|
||||
If you open it directly in the browser, you will see an empty page.
|
||||
|
||||
You can add webfonts, meta tags, or analytics to this file.
|
||||
The build step will place the bundled scripts into the <body> tag.
|
||||
|
||||
To begin the development, run `npm start` or `yarn start`.
|
||||
To create a production bundle, use `npm run build` or `yarn build`.
|
||||
-->
|
||||
</body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 5.2 KiB |
|
After Width: | Height: | Size: 9.4 KiB |
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"short_name": "React App",
|
||||
"name": "Create React App Sample",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.ico",
|
||||
"sizes": "64x64 32x32 24x24 16x16",
|
||||
"type": "image/x-icon"
|
||||
},
|
||||
{
|
||||
"src": "logo192.png",
|
||||
"type": "image/png",
|
||||
"sizes": "192x192"
|
||||
},
|
||||
{
|
||||
"src": "logo512.png",
|
||||
"type": "image/png",
|
||||
"sizes": "512x512"
|
||||
}
|
||||
],
|
||||
"start_url": ".",
|
||||
"display": "standalone",
|
||||
"theme_color": "#000000",
|
||||
"background_color": "#ffffff"
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
# https://www.robotstxt.org/robotstxt.html
|
||||
User-agent: *
|
||||
Disallow:
|
||||
@@ -0,0 +1,44 @@
|
||||
import Persons from "./components/Persons";
|
||||
import Filter from "./components/Filter";
|
||||
import PersonForm from "./components/PersonForm";
|
||||
import Notification from "./components/Notification";
|
||||
import { useState, useEffect } from "react";
|
||||
import personServices from "./services/persons";
|
||||
|
||||
const App = () => {
|
||||
const [persons, setPersons] = useState([]);
|
||||
const [filter, setFilter] = useState("");
|
||||
const [message, setMessage] = useState(null);
|
||||
useEffect(() => {
|
||||
personServices.getAll().then((response) => setPersons(response.data));
|
||||
}, []);
|
||||
|
||||
function displayMessage(message, type = "normal") {
|
||||
setMessage({message,type});
|
||||
setTimeout(() => {
|
||||
setMessage(null);
|
||||
}, 5000);
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<h2>Phonebook</h2>
|
||||
<Notification message={message} />
|
||||
<Filter persons={persons} filter={filter} setFilter={setFilter} />
|
||||
<h2>add a new</h2>
|
||||
<PersonForm
|
||||
persons={persons}
|
||||
setPersons={setPersons}
|
||||
displayMessage={displayMessage}
|
||||
/>
|
||||
<h2>Numbers</h2>
|
||||
<Persons
|
||||
persons={persons.filter((el) =>
|
||||
el.name.toLowerCase().includes(filter.toLowerCase())
|
||||
)}
|
||||
setPersons={setPersons}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
||||
@@ -0,0 +1,19 @@
|
||||
function Course({ course }) {
|
||||
const total = course.parts.reduce((acc, curr) => acc + curr.exercises, 0);
|
||||
return (
|
||||
<>
|
||||
<h1>{course.name}</h1>
|
||||
<ul>
|
||||
{course.parts.map((c) => (
|
||||
<li key={c.id}>
|
||||
{c.name} {c.exercises}
|
||||
</li>
|
||||
))}
|
||||
<li>
|
||||
<b>total of</b> {total} <b>exercises</b>
|
||||
</li>
|
||||
</ul>
|
||||
</>
|
||||
);
|
||||
}
|
||||
export default Course;
|
||||
@@ -0,0 +1,12 @@
|
||||
function Filter({ filter, setFilter}) {
|
||||
function onFilter(e) {
|
||||
setFilter(e.target.value);
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
filter shown with <input value={filter} onChange={onFilter} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
export default Filter;
|
||||
@@ -0,0 +1,5 @@
|
||||
const Notification= ({message}) => {
|
||||
if (message === null) return null;
|
||||
return <div className={message.type}>{message.message}</div>;
|
||||
};
|
||||
export default Notification
|
||||
@@ -0,0 +1,60 @@
|
||||
import { useState } from "react";
|
||||
import personServices from "../services/persons";
|
||||
|
||||
function PersonForm({ persons, setPersons, displayMessage }) {
|
||||
const [newName, setNewName] = useState("");
|
||||
const [newNumber, setNewNumber] = useState("");
|
||||
|
||||
function onAddPerson(e) {
|
||||
e.preventDefault();
|
||||
const newPerson = { name: newName, number: newNumber };
|
||||
const id = persons.find((el) => el.name === newName)?.id;
|
||||
if (id) {
|
||||
personServices
|
||||
.update(id, newPerson)
|
||||
.then(() => {
|
||||
setPersons(
|
||||
persons.map((person) => (person.id !== id ? person : newPerson))
|
||||
);
|
||||
displayMessage("Number changed");
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err.message);
|
||||
displayMessage("Number has already been removed", "error");
|
||||
});
|
||||
} else {
|
||||
personServices
|
||||
.create(newPerson)
|
||||
.then(() => {
|
||||
setPersons([...persons, newPerson]);
|
||||
displayMessage("Person Added");
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error.response.data)
|
||||
displayMessage('Validation Error', "error");
|
||||
});
|
||||
}
|
||||
setNewName("");
|
||||
setNewNumber("");
|
||||
}
|
||||
|
||||
return (
|
||||
<form onSubmit={onAddPerson}>
|
||||
<div>
|
||||
name:{" "}
|
||||
<input value={newName} onChange={(e) => setNewName(e.target.value)} />
|
||||
</div>
|
||||
<div>
|
||||
number:{" "}
|
||||
<input
|
||||
value={newNumber}
|
||||
onChange={(e) => setNewNumber(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<button type="submit">add</button>
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
export default PersonForm;
|
||||
@@ -0,0 +1,20 @@
|
||||
import personServices from "../services/persons";
|
||||
|
||||
function Persons({ persons, setPersons }) {
|
||||
function onDelete(id) {
|
||||
personServices
|
||||
.remove(id)
|
||||
.then(setPersons(persons.filter((pred) => pred.id != id)));
|
||||
}
|
||||
return (
|
||||
<ul>
|
||||
{persons.map((person, index) => (
|
||||
<li key={index}>
|
||||
{person.name} {person.number}{" "}
|
||||
<button onClick={() => onDelete(person.id)}>delete</button>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
export default Persons;
|
||||
@@ -0,0 +1,18 @@
|
||||
.error {
|
||||
color: red;
|
||||
background: lightgrey;
|
||||
font-size: 20px;
|
||||
border-style: solid;
|
||||
border-radius: 5px;
|
||||
padding: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.normal {
|
||||
color: green;
|
||||
background: lightgrey;
|
||||
font-size: 20px;
|
||||
border-style: solid;
|
||||
border-radius: 5px;
|
||||
padding: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom/client'
|
||||
import './index.css'
|
||||
|
||||
import App from './App'
|
||||
|
||||
const notes = [
|
||||
{
|
||||
id: 1,
|
||||
content: 'HTML is easy',
|
||||
important: true
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
content: 'Browser can execute only JavaScript',
|
||||
important: false
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
content: 'GET and POST are the most important methods of HTTP protocol',
|
||||
important: true
|
||||
}
|
||||
]
|
||||
|
||||
ReactDOM.createRoot(document.getElementById('root')).render(
|
||||
<App notes={notes} />
|
||||
)
|
||||
@@ -0,0 +1,15 @@
|
||||
import axios from "axios";
|
||||
const baseUrl = "/api/persons/";
|
||||
|
||||
|
||||
const getAll = () => axios.get(baseUrl);
|
||||
const create = (newPerson) => axios.post(baseUrl, newPerson);
|
||||
const remove = (id) => axios.delete(baseUrl.concat(id.toString()));
|
||||
const update = (id, newPerson) => axios.put(`${baseUrl}${id}`, newPerson);
|
||||
|
||||
export default {
|
||||
getAll: getAll,
|
||||
create: create,
|
||||
remove: remove,
|
||||
update: update,
|
||||
};
|
||||
@@ -0,0 +1,78 @@
|
||||
import { useState } from "react";
|
||||
function Statistics({ good, bad, neutral }) {
|
||||
return (
|
||||
<div>
|
||||
<h1>statistics</h1>
|
||||
<ul>
|
||||
<StatisticsLine text={"good"} value={good} />
|
||||
<StatisticsLine text={"neutral"} value={neutral} />
|
||||
<StatisticsLine text={"bad"} value={bad} />
|
||||
<StatisticsLine text={"all"} value={bad + good + neutral} />
|
||||
<StatisticsLine
|
||||
text={"average"}
|
||||
value={(good - bad) / (good + bad + neutral)}
|
||||
/>
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function StatisticsLine({ text, value }) {
|
||||
return (
|
||||
<li>
|
||||
{text}: {value}
|
||||
</li>
|
||||
);
|
||||
}
|
||||
|
||||
function Anecdotes({ anecdotes, selected }) {
|
||||
return (
|
||||
<>
|
||||
<div>{anecdotes[selected]}</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
const App = () => {
|
||||
// save clicks of each button to its own state
|
||||
const [good, setGood] = useState(0);
|
||||
const [neutral, setNeutral] = useState(0);
|
||||
const [bad, setBad] = useState(0);
|
||||
const [selected, setSelected] = useState(0);
|
||||
const [votes, setVotes] = useState(new Array(7).fill(0));
|
||||
const anecdotes = [
|
||||
"If it hurts, do it more often.",
|
||||
"Adding manpower to a late software project makes it later!",
|
||||
"The first 90 percent of the code accounts for the first 10 percent of the development time...The remaining 10 percent of the code accounts for the other 90 percent of the development time.",
|
||||
"Any fool can write code that a computer can understand. Good programmers write code that humans can understand.",
|
||||
"Premature optimization is the root of all evil.",
|
||||
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.",
|
||||
"Programming without an extremely heavy use of console.log is same as if a doctor would refuse to use x-rays or blood tests when diagnosing patients.",
|
||||
"The only way to go fast, is to go well.",
|
||||
];
|
||||
|
||||
let highest = Math.max(...votes)
|
||||
function addVote() {
|
||||
let newVotes = [...votes];
|
||||
newVotes[selected] += 1;
|
||||
setVotes(newVotes);
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<h1>give feedback</h1>
|
||||
<button onClick={() => setGood(good + 1)}>good</button>
|
||||
<button onClick={() => setNeutral(neutral + 1)}>neutral</button>
|
||||
<button onClick={() => setBad(bad + 1)}>bad</button>
|
||||
<Statistics good={good} bad={bad} neutral={neutral} />
|
||||
<Anecdotes anecdotes={anecdotes} selected={selected} />
|
||||
<h1>has {votes[selected]} votes</h1>
|
||||
<button onClick={() => addVote()}>vote</button>
|
||||
<button onClick={() => setSelected(Math.floor(Math.random() * 7))}>
|
||||
next anecdote{" "}
|
||||
</button>
|
||||
<h1>Is the most liked</h1>
|
||||
<Anecdotes anecdotes={anecdotes} selected={Math.max(...votes)}/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
||||
@@ -0,0 +1,6 @@
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom/client'
|
||||
|
||||
import App from './App'
|
||||
|
||||
ReactDOM.createRoot(document.getElementById('root')).render(<App />)
|
||||
@@ -0,0 +1,16 @@
|
||||
#! /usr/bin/bash
|
||||
echo -n "1 for get All, 2 for get with id, 3 for create, 4 for delete "
|
||||
read action
|
||||
if [[ $action == 1 ]]; then
|
||||
curl http://localhost:3001/api/persons | json_pp -json_opt pretty,canonical
|
||||
elif [[ $action == 2 ]]; then
|
||||
echo -n "gib id "
|
||||
read id
|
||||
curl http://localhost:3001/api/persons/${id} | json_pp -json_opt pretty,canonical
|
||||
elif [[ $action == 3 ]]; then
|
||||
curl -H "Content-Type: application/json" -X POST -d '{"name":"xyz","number":"xyz"}' http://localhost:3001/api/persons | json_pp -json_opt pretty,canonical
|
||||
elif [[ $action == 4 ]]; then
|
||||
echo -n "gib id "
|
||||
read id
|
||||
curl -H "Content-Type: application/json" -X DELETE http://localhost:3001/api/persons/6482b803a270efb823a3cfb0 | json_pp -json_opt pretty,canonical
|
||||
fi
|
||||