Skip to content

Commit

Permalink
πŸ¦”πŸ— ↣ Data retrieval for #16, #17 is looking good
Browse files Browse the repository at this point in the history
  • Loading branch information
Gizmotronn committed Nov 16, 2022
1 parent bcb49a8 commit 74ec010
Show file tree
Hide file tree
Showing 12 changed files with 260 additions and 22 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ build
.build
/build

venv
.venv
/.venv
/venv

cache
/cache
./cache
Expand Down
Empty file added instance/database.db
Empty file.
26 changes: 15 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,16 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@supabase/supabase-js": "^1.35.2",
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^13.1.1",
"@testing-library/user-event": "^13.5.0",
"react": "^18.0.0",
"react-dom": "^18.0.0",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4",
"@everipedia/wagmi-magic-connector": "^0.7.1",
"@magic-ext/oauth": "^4.0.0",
"@magiclabs/ui": "^0.24.2",
"@openzeppelin/contracts": "^4.7.3",
"@stripe/react-stripe-js": "^1.14.1",
"@stripe/stripe-js": "^1.42.0",
"@supabase/supabase-js": "^1.35.2",
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^13.1.1",
"@testing-library/user-event": "^13.5.0",
"@thirdweb-dev/contracts": "^3.1.11",
"@thirdweb-dev/react": "^3",
"@thirdweb-dev/sdk": "^3",
Expand All @@ -32,18 +28,25 @@
"next-router": "^1.3.6",
"node-forge": "^1.3.1",
"node-sass": "^7.0.3",
"react": "^18.0.0",
"react-bootstrap": "^2.5.0",
"react-dom": "^18.0.0",
"react-icons": "^4.6.0",
"react-router-dom": "5.2.1",
"react-scripts": "5.0.1",
"semantic-ui-css": "^2.5.0",
"semantic-ui-react": "^2.1.3",
"stripe": "^10.15.0",
"styled-components": "^5.3.6",
"wagmi": "^0.7.8"
"wagmi": "^0.7.8",
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
"eject": "react-scripts eject",
"start-api": "cd server && .venv/bin/flask run"
},
"eslintConfig": {
"extends": [
Expand All @@ -67,5 +70,6 @@
"autoprefixer": "^10.4.4",
"postcss": "^8.4.12",
"tailwindcss": "^3.0.24"
}
},
"proxy": "http://localhost:5000"
}
2 changes: 2 additions & 0 deletions server/.flaskenv
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
FLASK_APP=app.py
FLASK_ENV=development
75 changes: 75 additions & 0 deletions server/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
from flask import Flask, jsonify, request
import time
import requests
import psycopg2

# App & Data configuration =====>
app = Flask(__name__)
DATABASE_URL = "postgresql://postgres:[email protected]:5432/postgres"
connection = psycopg2.connect(DATABASE_URL)

# Table configuration =====>
CREATE_ROOMS_TABLE = (
"CREATE TABLE IF NOT EXISTS rooms (id SERIAL PRIMARY KEY, name TEXT);"
)

CREATE_TEMPS_TABLE = """CREATE TABLE IF NOT EXISTS temperatures (room_id INTEGER, temperature REAL, date TIMESTAMP, FOREIGN KEY(room_id) REFERENCES rooms(id) ON DELETE CASCADE);"""

INSERT_ROOM_RETURN_ID = "INSERT INTO rooms (name) VALUES (%s) RETURNING id;"

CREATE_PLANETS_TABLE = ( # If the planet table doesn't exist on Supabase
"CREATE TABLE IF NOT EXISTS planets (planetId INTEGER PRIMARY KEY, profileId TEXT, planetName TEXT);"
) # Would be a good idea to double check that this configuration is aligned with https://skinetics.notion.site/Inventory-what-goes-where-1fb9b1e776c048ed9a9b5c1ff1def491

INSERT_PLANET_RETURN_ID = "INSERT INTO users (profileId) VALUES (%s) RETURNING id;"

CREATE_PLANETSDEMO_TABLE = ( # Demo table that is to test out the post request from flask to `add_planet` decorator
"CREATE TABLE IF NOT EXISTS planetsdemo (planetId SERIAL PRIMARY KEY, name TEXT, moons INTEGER);"
)
INSERT_PLANETSDEMO = "INSERT INTO planetsdemo (name, moons) VALUES (%s, %s);"

@app.route('/time')
def get_time():
return {'time': time.time()}

@app.route('/planets')
def planet():
planets = [{'name': 'Mars', 'moons': 2}, {'name': 'Earth', 'moons': 1}]
return jsonify({'planets' : planets})

# Example, working POST request to Supabase
@app.post("/api/room") # Post request to create a new room
def create_room():
data = request.get_json() # dict of data from post request
name = data["name"]
with connection: # Start connection to db
with connection.cursor() as cursor: # Object to manipulate entries in db
cursor.execute(CREATE_ROOMS_TABLE)
cursor.execute(INSERT_ROOM_RETURN_ID, (name,)) # Insert room & retrieve id
room_id = cursor.fetchone()[0] # access first column ([0])
return {"id" : room_id, "message": f"Room {name} created."}, 201

@app.post('/add_planets')
def add_planets():
data = request.get_json()
planetId = data['planetId'] # is this the primary key, or is it something else?
#profileId = data['profileId'] # Magic id -> will be retrieved from the user id (if they have a magic account attached, otherwise use their supabase profile id)
planetName = data['name'] # Other potential properties -> address, tokenId, holder (foreign key to user/profile ID), etc

with connection:
with connection.cursor() as cursor: # object to manipulate entries in database
cursor.execute(CREATE_PLANETS_TABLE)
cursor.execute(INSERT_PLANET_RETURN_ID, (planetId,)) # Insert planet & retrieve ID
planet_id = cursor.fetchone()[0] # access first column ([0])
return {"id" : planet_id, "message": f"User {planetId} created."}, 201

@app.post('/add_planet')
def add_planet():
data = request.get_json()
name = data['name']
moons = data['moons']

with connection:
with connection.cursor() as cursor:
cursor.execute(CREATE_PLANETSDEMO_TABLE)
cursor.execute(INSERT_PLANETSDEMO, (name, moons))
2 changes: 2 additions & 0 deletions server/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
flask
python-dotenv
4 changes: 3 additions & 1 deletion src/App.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { useEffect, useState } from 'react';
import './App.css';

// Auth component imports
import { supabase } from './supabaseClient'
import Auth from './components/Auth';
import Account from './components/Account';
Expand All @@ -22,4 +24,4 @@ function App() {
);
}

export default App;
export default App;
24 changes: 23 additions & 1 deletion src/components/Account.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,34 @@ import { useState, useEffect } from "react"
import { supabase } from "../supabaseClient"
import Avatar from './Avatar';

// Styling imports =====>
import { Container } from "semantic-ui-react";

// API/data imports =====>
import { Planets } from "./api/Planets";
import { PlanetForm } from "./api/PlanetForm";

const Account = ( { session } ) => {
// Authentication settings
const [loading, setLoading] = useState(true)
const [username, setUsername] = useState(null)
const [website, setWebsite] = useState(null)
const [avatar_url, setAvatarUrl] = useState(null)

useEffect(() => {
getProfile()
}, [session])
}, [session]) // Update whenever session (from Supabase) changes

// Call second flask app
const [planets, setPlanets] = useState([]);

useEffect(() => {
fetch('/planets').then(response => response.json().then(data => {
setPlanets(data.planets);
}));
}, []); // Also pass in the authentication settings to Flask via POST

// Get profile information from Supabase postgres
const getProfile = async () => {
try {
setLoading(true)
Expand Down Expand Up @@ -107,6 +125,10 @@ const Account = ( { session } ) => {
</div>
</form>
)}
<Container>
<Planets planets={planets} />
<PlanetForm />
</Container>
</div>
)
}
Expand Down
35 changes: 35 additions & 0 deletions src/components/api/PlanetForm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React, {useState} from "react";
import { Button, Form, Input } from 'semantic-ui-react';

export const PlanetForm = () => {
const [name, setName] = useState('');
const [moons, setMoons] = useState(0);

return (
<Form>
<Form.Field>
<Input placeholder='planet title' value={name} onChange={ e => setName(e.target.value)} />
</Form.Field>
<Form.Field>
<Input placeholder='planet moons' value={moons} onChange={ e => setMoons(e.target.value)} />
</Form.Field>
<Form.Field>
<Button onClick={async () => {
const planet = {name, moons}; // Update this to match the properties in `./server/app.py` & in Supabase
const response = await fetch('/add_planet', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(planet),
});
if (response.ok) {
console.log('response worked');
}
}}>
Submit
</Button>
</Form.Field>
</Form>
)
}
21 changes: 21 additions & 0 deletions src/components/api/Planets.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from "react";
import { List, Header, Rating } from "semantic-ui-react";

export const Planets = ({ planets }) => {
return (
<List>
{planets.map(planet => {
return (
<List.Item key={planet.name}>
<Header>{planet.name}</Header>
<br />
<Header>Moons: {planet.moons}</Header>
<Rating rating={planet.moons} maxRating='5' disabled/>
<br />
<br />
</List.Item>
)
})}
</List>
)
}
1 change: 1 addition & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import 'semantic-ui-css/semantic.min.css';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
Expand Down
Loading

0 comments on commit 74ec010

Please sign in to comment.