Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added Jeremy_Kracy/Database/RelationalDatabase.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions Jeremy_Kracy/Database/data.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[{"Record ID":2279,"Name":"Kalila Badrock","Cell Phone":"813-953-0689","Work Phone":"469-669-0547","Email":"[email protected]","Address":"0 Stoughton Place","Basic Widget Order":30,"Advanced Widget Order":58,"Protection Plan":true},
{"Record ID":7488,"Name":"Merrily Burds","Cell Phone":"711-916-0235","Work Phone":"469-980-1811","Email":"[email protected]","Address":"752 Hanover Pass","Basic Widget Order":34,"Advanced Widget Order":94,"Protection Plan":false},
{"Record ID":2926,"Name":"Adrian Orae","Cell Phone":"497-393-4258","Work Phone":"609-701-0442","Email":"[email protected]","Address":"692 Randy Park","Basic Widget Order":89,"Advanced Widget Order":10,"Protection Plan":false},
{"Record ID":7788,"Name":"Penni Lethabridge","Cell Phone":"938-905-6654","Work Phone":"453-269-0061","Email":"[email protected]","Address":"5 New Castle Court","Basic Widget Order":87,"Advanced Widget Order":100,"Protection Plan":false},
{"Record ID":9357,"Name":"Missy Dinning","Cell Phone":"804-660-7935","Work Phone":"203-577-4126","Email":"[email protected]","Address":"007 Larry Court","Basic Widget Order":21,"Advanced Widget Order":73,"Protection Plan":false},
{"Record ID":9333,"Name":"Ronica Thorne","Cell Phone":"529-483-3697","Work Phone":"236-451-5815","Email":"[email protected]","Address":"26 High Crossing Place","Basic Widget Order":56,"Advanced Widget Order":95,"Protection Plan":true},
{"Record ID":3172,"Name":"Margit Marquis","Cell Phone":"539-728-5606","Work Phone":"885-138-8678","Email":"[email protected]","Address":"149 Barby Crossing","Basic Widget Order":74,"Advanced Widget Order":52,"Protection Plan":true},
{"Record ID":3326,"Name":"Travis Lathe","Cell Phone":"228-622-7391","Work Phone":"319-631-4135","Email":"[email protected]","Address":"2 Gateway Park","Basic Widget Order":92,"Advanced Widget Order":100,"Protection Plan":true},
{"Record ID":2206,"Name":"Chalmers Vedyashkin","Cell Phone":"334-958-5613","Work Phone":"268-547-1288","Email":"[email protected]","Address":"1 Dexter Hill","Basic Widget Order":16,"Advanced Widget Order":25,"Protection Plan":false},
{"Record ID":8769,"Name":"Ripley Chant","Cell Phone":"549-606-8500","Work Phone":"583-341-3201","Email":"[email protected]","Address":"5 Lighthouse Bay Crossing","Basic Widget Order":24,"Advanced Widget Order":87,"Protection Plan":true}]
36 changes: 36 additions & 0 deletions Jeremy_Kracy/Database/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import json


def read_in(file_name):
file = open(file_name, 'r')
data = json.load(file)

print('CREATE TABLE Customer_Information (\n'
'Email varchar(50) NOT NULL,\n'
'Name varchar(50),\n'
'Cell_Phone varchar(10),\n'
'Work_Phone varchar(10),\n'
'Address varchar(50),\n'
'PRIMARY KEY (Email)\n'

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What was your thought process in deciding what primary key to use for Customer_Information table? And what kind of relationship do you anticipate between the two tables (Customer_Information and Order_Information)?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I decided to use the customer's email as the primary key in the Customer_Information table, because it seemed to be the best characteristic to use as an identifier. I think of other account based services that will reject accounts if the email used is already taken by a different account. That was the idea I was going for with that. I anticipate a one-to-many relationship for Customer_Information and Order_Information. This would allow 1 customer to have multiple orders, while ensuring each order only corresponds to one customer.

').\n')
print('CREATE TABLE Order_Information (\n'
'Record_ID int NOT NULL,\n'
'Basic_Widget_Order int,\n'
'Advanced_Widget_Order int,\n'
'Protection Plan BOOLEAN,\n'
'Email varchar(50) NOT NULL,\n'
'PRIMARY KEY (Record_ID),\n'
'FOREIGN KEY (Email) REFERENCES Customer_Information(Email)\n'
').\n')

for i in data:
print('INSERT INTO CUSTOMER_INFORMATION (Email, Name, Cell_Phone, Work_Phone, Address)\n'
'VALUES ({}, {}, {}, {}, {})\n'.format(i['Email'], i['Name'], i['Cell Phone'], i['Work Phone'], i['Address']))

print('INSERT INTO Order_Information (Record_ID, Basic_Widget_Order, Advanced_Widget_Order, Protection_Plan, Email)\n'
'VALUES ({}, {}, {}, {}, {})\n'.format(i['Record ID'], i['Basic Widget Order'], i['Advanced Widget Order'], i['Protection Plan'], i['Email']))

if __name__ == '__main__':

read_in('data.json')

67 changes: 67 additions & 0 deletions Jeremy_Kracy/WebPage/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<link rel="icon" type="image/png" href="profile pic.png">
<link rel="stylesheet" href="mystyle.css">
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
<body>

<div style="background:#097524" class="jumbotron">
<h1 class="text-white">Jeremy Kracy, LLC</h1>
<p class="text-white">Author: Jeremy Kracy</p>
</div>

<div id="after_submit"></div>
<form id="contact_form" action="" onsubmit="sConsole(event)" enctype="multipart/form-data">
<div class="row">
<div class="col px-sm-4">
<label class="required" for="name">Your name:</label><br />
<input id="name" class="input" name="name" type="text" value="" size="30" /><br />
<span id="name_validation" class="error_message"></span>
</div>
</div>
<div class="row">
<div class="col px-sm-4">
<label class="required" for="email">Your email:</label><br />
<input id="email" class="input" name="email" type="text" value="" size="30" /><br />
<span id="email_validation" class="error_message"></span>
</div>
</div>
<div class="row">
<div class="col px-sm-4">
<label class="required" for="message">Your message:</label><br />
<textarea id="message" class="input" name="message" rows="7" cols="30"></textarea><br />
<span id="message_validation" class="error_message"></span>
</div>
</div>
<div class="col px-sm-2">
<div class="g-recaptcha" data-sitekey="6LdwoaEaAAAAANI_ZCSKM_sMK_wYc_OfUW1B-xtL"></div>
</div>
<br/>
<div class="col px-sm-2">
<input id="submit_button" type="submit" value="Submit form" />
</div>
</form>

<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
</body>
</head>
</html>

<script type: "text/javascript">
function sConsole(event) {
event.preventDefault();
var name = document.getElementById("name");
var email = document.getElementById("email");
var message = document.getElementById("message");
console.log(name.value);
console.log(email.value);
console.log(message.value);
}
</script>
21 changes: 21 additions & 0 deletions Jeremy_Kracy/WebPage/mystyle.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
label {
font-weight: bold;
font-size: 16px;
}

#submit_button {
background-color: #097524;
height: 30px;
width: 20%;
color: #FFFFFF;
font-weight: bold;
}

input, textarea {
background-color: #D3D3D3;
color: #2F4F4F;
width: 250px;
margin-bottom: 10px;
box-shadow: 5px 5px 2px 2px #696969;
}

Binary file added Jeremy_Kracy/WebPage/profile pic.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions Jeremy_Kracy/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Jeremy Kracy

## Frontend Challenge
I am not very experienced with webpage design. I do have a bit of experience working with html and css, but nothing extensive. I decided to use the bootstrap framework to design the layout on the webpage. I implemented the reCaptcha using the link referenced on the challenge instructions.

## Backend Challenge
I am not very experienced when it comes to working with APIs or designing them. I decided to use node.js with a mongoDB atlas cloud database to store my data. I used the mongoose extension to interact with my database.

## Database Challenge
I was most confident going into this challenge, because it is something I have done before. I am confident in my ability to make good decisions in regards to database design. I chose to use python for this assignment, because of how simple it is to work with .json files in python.
8 changes: 8 additions & 0 deletions Jeremy_Kracy/restAPI/api/models/number.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
const mongoose = require('mongoose');

const dataSchema = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
data: [{type: Number, required: true }]
});

module.exports = mongoose.model('Data', dataSchema);
108 changes: 108 additions & 0 deletions Jeremy_Kracy/restAPI/api/routes/data.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
const express = require('express');
const router = express.Router();
const mongoose = require('mongoose');

const Data = require('../models/number');

router.get('/', (req, res, next) => {
Data.find()
.select('data _id')
.exec()
.then(docs => {
res.status(200).json(docs);
})
.catch(err => {
console.log(err);
res.status(500).json({
error: err
})
});
});

router.get('/:dataId', (req, res, next) => {
const id = req.params.dataId;
Data.findById(id)
.select('data _id')
.exec()
.then(doc => {
if(doc) {
res.status(200).json(doc);
} else {
res.status(404).json({
message: "No valid entry for provided ID"
});
}
})
.catch(err => {
console.log(err);
res.status(500).json({
error: err
})
});
});


router.post('/', (req, res, next) => {
const data = new Data({
_id: new mongoose.Types.ObjectId(),
data: req.body.data
});
console.log(data.data.length);
if(data.data.length === 500){
data.save()
.then(result => {
console.log(result);
console.log(result.data.length);

res.status(201).json({

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How did you decide on 201 here?

Copy link
Author

@RawToaster RawToaster Apr 12, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I used the 201 status code to verify that a new object was created in the database using that POST request. This is in line with my understanding of the "201 Created" code.

message: 'Data created',
created: result,
request: {
type: 'GET',
url: 'http://localhost:3000/data/' + result._id
}
});
})
.catch(err => {
console.log(err);
res.status(500).json({
error: err
});
});
} else {
res.status(500).json({
error: 'Object list is not 500 objects in length'
});
}

});

router.patch('/:dataId', (req, res, next) => {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you tell me how did you decide to use patch here? As in what purpose does it serve given the context of the problem you're solving.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My intention with the use of patch was to allow a user to update any given array in the database with new information without having to create an entirely new object in the database. I imagine a user would use a get request to attain the available array IDs, and use this information in a patch call to update the desired array.

const id = req.params.dataId;
if(req.body.data.length === 500) {
Data.updateOne({_id: id }, {$set: {data: req.body.data}})
.exec()
.then(doc => {
console.log(doc);
res.status(200).json({
data: doc,
request: {
type: 'GET',
url: 'http://localhost:3000/data/' + id
}
});
})
.catch(err => {
console.log(err);
res.status(500).json({
error: err
});
});
} else {
res.status(500).json({
error: 'Object list is not 500 objects in length OR data is invalid'
});
}
});

module.exports = router;
44 changes: 44 additions & 0 deletions Jeremy_Kracy/restAPI/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
const express = require('express');
const app = express();
const morgan = require('morgan');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');


const dataRoutes = require('./api/routes/data');

mongoose.connect('mongodb+srv://HeadstormChallenge:[email protected]/myFirstDatabase?retryWrites=true&w=majority');

app.use(morgan('dev'));
app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());

app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', '*');
if(req.method === 'OPTIONS') {
res.header('Access-Control-Allow-Methods', 'PUT, POST, PATCH');
return res.status(200).json({});
}
next();
});

// Routes to handle requests
app.use('/data', dataRoutes);

app.use((req, res, next) => {
const error = new Error('Not Found');
error.status = 404;
next(error);
});

app.use((error, req, res, next) => {
res.status(error.status || 500);
res.json({
error: {
message: error.message
}
});
});

module.exports = app;
5 changes: 5 additions & 0 deletions Jeremy_Kracy/restAPI/nodemon.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"env": {
"MONGO_ATLAS_PW": "headstorm"
}
}
Loading