From 9dfd3b0c06c44d06fd00fec8e73b1120b6f1b134 Mon Sep 17 00:00:00 2001 From: Ege-Kaya Date: Sat, 29 May 2021 18:38:12 +0300 Subject: [PATCH 001/179] Added the random data api for creating new users when the specified user id is not in the list of users --- practice-app/app/app.py | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/practice-app/app/app.py b/practice-app/app/app.py index 13443547..e46769e6 100644 --- a/practice-app/app/app.py +++ b/practice-app/app/app.py @@ -62,8 +62,6 @@ def get_sport_types(): except: abort(500) - - @app.route('/api/v1.0/spectators/', methods=['GET']) def get_spectators(event_id): event = [event for event in events if event['eventId'] == event_id] @@ -74,12 +72,30 @@ def get_spectators(event_id): @app.route('/api/v1.0/events/', methods=['POST']) def apply_as_player(event_id): body = request.json - print(body) user_id = body["userId"] event = [event for event in events if event["eventId"] == event_id] user = [user for user in users if user["userId"] == user_id] - if len(event) == 0 or len(user) == 0: + if len(event) == 0: abort(404) + if len(user) == 0: + response = requests.get("https://randomapi.com/api/9fekfc0v?key=2UX0-XIT1-7DYM-WDBC") + json_data = response.json()["results"] + new_user = {"userId": user_id, + "nickname": json_data[0]["nickname"], + "firstName": json_data[0]["firstName"], + "lastName": json_data[0]["lastName"], + "biography": json_data[0]["biography"], + "age": json_data[0]["age"], + "avatar": json_data[0]["avatar"], + "location": json_data[0]["location"], + "favSports": json_data[0]["favSports"], + "badges": json_data[0]["badges"], + "privacy": json_data[0]["privacy"]} + print(new_user) + users.append(new_user) + user.append(new_user) + print(users) + event[0]["players"].append(user[0]["nickname"]) return jsonify({"eventId": event_id, "eventTitle": event[0]["title"], @@ -107,6 +123,5 @@ def create_equipment(): equipments.append(new_equipment) return jsonify({"equipment": new_equipment}), 201 - if __name__ == '__main__': app.run(debug=True) From 676f8570bde93ea83091eda1be14ff5d2c975015 Mon Sep 17 00:00:00 2001 From: Ege-Kaya Date: Sat, 29 May 2021 18:48:40 +0300 Subject: [PATCH 002/179] Added the random user data api to generate new users in case of non-existent users --- practice-app/app/app.py | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/practice-app/app/app.py b/practice-app/app/app.py index 526cd3e0..2a9e8eb3 100644 --- a/practice-app/app/app.py +++ b/practice-app/app/app.py @@ -103,12 +103,30 @@ def get_players(event_id): @app.route('/api/v1.0/events/', methods=['POST']) def apply_as_player(event_id): body = request.json - print(body) user_id = body["userId"] event = [event for event in events if event["eventId"] == event_id] user = [user for user in users if user["userId"] == user_id] - if len(event) == 0 or len(user) == 0: + if len(event) == 0: abort(404) + if len(user) == 0: + response = requests.get("https://randomapi.com/api/9fekfc0v?key=2UX0-XIT1-7DYM-WDBC") + json_data = response.json()["results"] + new_user = {"userId": user_id, + "nickname": json_data[0]["nickname"], + "firstName": json_data[0]["firstName"], + "lastName": json_data[0]["lastName"], + "biography": json_data[0]["biography"], + "age": json_data[0]["age"], + "avatar": json_data[0]["avatar"], + "location": json_data[0]["location"], + "favSports": json_data[0]["favSports"], + "badges": json_data[0]["badges"], + "privacy": json_data[0]["privacy"]} + print(new_user) + users.append(new_user) + user.append(new_user) + print(users) + event[0]["players"].append(user[0]["nickname"]) return jsonify({"eventId": event_id, "eventTitle": event[0]["title"], From 22c73e1bfa2618a3ec7d382fb634a3f48b9c412d Mon Sep 17 00:00:00 2001 From: ahmetnecipg <56501804+ahmetnecipg@users.noreply.github.com> Date: Sat, 29 May 2021 18:51:27 +0300 Subject: [PATCH 003/179] Update app.py equipments/ GET added --- practice-app/app/app.py | 47 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/practice-app/app/app.py b/practice-app/app/app.py index 2a9e8eb3..ab28c519 100644 --- a/practice-app/app/app.py +++ b/practice-app/app/app.py @@ -54,6 +54,53 @@ "link": "www.ismycomputeron.com" } ] +equipments2 = [ + { + "equipmentId": 1, + "ownerId": 1, + "title" : "Tennis shoes for sale!", + "content" : "I have a pair of shoes in good condition that i want to sell.", + "website name" : "letgo", + "link" : "letgo.com/245323", + "equipment type" : "Shoes" + + }, + { + "equipmentId": 2, + "ownerId": 1, + "title" : "Tennis rackets for sale!", + "content" : "I have a pair of shoes in good condition that i want to sell.", + "website name" : "letgo", + "link" : "letgo.com/245323", + "equipment type" : "Shoes" + } +] +headers = { + "x-rapidapi-key": "c4ab16012amsh73b5a257264eb3dp11ade4jsnb69ec0b79098", + "x-rapidapi-host" :"google-search3.p.rapidapi.com" +} + +@app.route('/api/v1.0/equipments//results', methods=['GET']) +def results(equipmentId): + equipment = [equipment for equipment in equipments2 if equipment['equipmentId'] == equipmentId] + if len(equipment) == 0: + abort(404) + title=equipment[0]['title'] + query = { + "q": equipment[0]['title'], + +} + response=requests.get("https://rapidapi.p.rapidapi.com/api/v1/search/" + urllib.parse.urlencode(query), headers=headers) + mapped=[{"description": j["description"],"link": j["link"], "title":j["title"]} for j in response.json()["results"]] + return jsonify(mapped), 200 +@app.route('/api/v1.0/equipments/', methods=['GET']) +def getEquipment(equipmentId): + equipment = [equipment for equipment in equipments2 if equipment['equipmentId'] == equipmentId] + if len(equipment) == 0: + abort(404) + return jsonify({'equipments': equipment[0]}) + + @app.route('/api/v1.0/', methods=['GET']) From 9d225c9f354a704d0d80a53ba97836198673bb12 Mon Sep 17 00:00:00 2001 From: ahmetnecipg <56501804+ahmetnecipg@users.noreply.github.com> Date: Sat, 29 May 2021 18:52:30 +0300 Subject: [PATCH 004/179] Update app.py --- practice-app/app/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/practice-app/app/app.py b/practice-app/app/app.py index ab28c519..d6e5e027 100644 --- a/practice-app/app/app.py +++ b/practice-app/app/app.py @@ -1,7 +1,7 @@ import requests from flask import Flask, jsonify, abort, request from datetime import datetime - +import urllib app = Flask(__name__) events = [ From de700f0bb47b710f15e8e5bc68e55f07fbb2098c Mon Sep 17 00:00:00 2001 From: Kerem Zaman Date: Sun, 30 May 2021 05:04:14 +0300 Subject: [PATCH 005/179] Refs #56 - Implement API endpoint for getting event by id --- practice-app/app/app.py | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/practice-app/app/app.py b/practice-app/app/app.py index d6e5e027..34f25eff 100644 --- a/practice-app/app/app.py +++ b/practice-app/app/app.py @@ -1,7 +1,7 @@ import requests from flask import Flask, jsonify, abort, request -from datetime import datetime import urllib +from datetime import datetime, timedelta app = Flask(__name__) events = [ @@ -101,6 +101,38 @@ def getEquipment(equipmentId): return jsonify({'equipments': equipment[0]}) +@app.route('/api/v1.0/events/', methods=['GET']) +def get_event(event_id): + try: + event = list(filter(lambda x: x['eventId'] == event_id, events))[0] + except IndexError: + abort(404) + covid_risk = False + + # assume event owners create event only in the country of their registration location + user_location = list(filter(lambda x: x['nickname'] == event['owner'], users))[0]['location'] + resp = requests.get('http://api.geonames.org/searchJSON', {'q': user_location, 'username': 'practice_app'}) + data = resp.json() + + if len(data['geonames']) > 0: + # get country name from location via geonames API + country = '-'.join(data['geonames'][0]['countryName'].split()).lower() + # set dates to fetch coronavirus cases + today = datetime.today() + to_date = str(today) + from_date = today - timedelta(days=3) + + resp = requests.get(f'https://api.covid19api.com/country/{country}/status/confirmed/live', + {'from': from_date, 'to_date': to_date}) + + covid_data = resp.json() + # if cases are increasing for 3 days in a row, set risk status true + if covid_data[-1]['Cases'] > covid_data[-2]['Cases'] > covid_data[-3]['Cases']: + covid_risk = True + + return jsonify({'events': event, + 'covid_risk_status': covid_risk, + 'current_cases': covid_data[-1]['Cases']}) @app.route('/api/v1.0/', methods=['GET']) From 438ce37f69a3fdd7608639f016f8c0531fa398bc Mon Sep 17 00:00:00 2001 From: Kerem Zaman Date: Sun, 30 May 2021 05:04:57 +0300 Subject: [PATCH 006/179] Fix URLS for get_players and apply_as_player --- practice-app/app/app.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/practice-app/app/app.py b/practice-app/app/app.py index 34f25eff..805238f6 100644 --- a/practice-app/app/app.py +++ b/practice-app/app/app.py @@ -170,7 +170,7 @@ def get_spectators(event_id): -@app.route('/api/v1.0/events/', methods=['GET']) +@app.route('/api/v1.0/events//players', methods=['GET']) def get_players(event_id): event = [event for event in events if event['eventId']==event_id] if len(event) == 0: @@ -179,7 +179,7 @@ def get_players(event_id): -@app.route('/api/v1.0/events/', methods=['POST']) +@app.route('/api/v1.0/events//players', methods=['POST']) def apply_as_player(event_id): body = request.json user_id = body["userId"] From 56db0117dfaf4453280464385ddf3f87d04cc660 Mon Sep 17 00:00:00 2001 From: Kerem Zaman Date: Sun, 30 May 2021 05:05:37 +0300 Subject: [PATCH 007/179] Fix typo in methods for equipment post --- practice-app/app/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/practice-app/app/app.py b/practice-app/app/app.py index 805238f6..e487aefa 100644 --- a/practice-app/app/app.py +++ b/practice-app/app/app.py @@ -224,7 +224,7 @@ def postSpectator(event_id): return jsonify({'spectators': event[0]["spectators"]}),201 -@app.route('/api/v1.0/equipments', method=['POST']) +@app.route('/api/v1.0/equipments', methods=['POST']) def create_equipment_post(): # Creates the equipment post if len(equipments) != 0: From de1feaf32f50171aa1252e3c1fc927d24be3a1d2 Mon Sep 17 00:00:00 2001 From: Kerem Zaman Date: Sun, 30 May 2021 05:06:06 +0300 Subject: [PATCH 008/179] Refs #48 - Update requirements.txt --- practice-app/app/requirements.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/practice-app/app/requirements.txt b/practice-app/app/requirements.txt index 094a0b68..873e7ba0 100644 --- a/practice-app/app/requirements.txt +++ b/practice-app/app/requirements.txt @@ -1,2 +1,3 @@ Flask==2.0.1 -gunicorn==20.1.0 \ No newline at end of file +gunicorn==20.1.0 +requests==2.25.1 \ No newline at end of file From 2054d1a00500f5e0d735ca7a6b0baaf3d00bc1d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Berkay=20D=C3=B6ner?= Date: Sun, 30 May 2021 20:05:28 +0300 Subject: [PATCH 009/179] get method for event search is added --- practice-app/app/app.py | 48 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/practice-app/app/app.py b/practice-app/app/app.py index e487aefa..3dedf9b5 100644 --- a/practice-app/app/app.py +++ b/practice-app/app/app.py @@ -2,7 +2,10 @@ from flask import Flask, jsonify, abort, request import urllib from datetime import datetime, timedelta +from math import cos, asin, sqrt, pi + app = Flask(__name__) +API_KEY = "AIzaSyD5TlVjboI-PWBYRI-dEznS3pmaflGr8Os" events = [ { @@ -10,7 +13,8 @@ "owner": "emre_gundogu", "title": "Tennis Game for Everyone", "content": "People who are looking for a tennis court can apply this event. Our court is for you if you are seeking for a clean and well-lit court.", - "location": "Bebek Tennis Club", + "location": "Etiler Tennis Club", + "coordinates": (41.0869173, 29.0321301), "date": "01.05.2021", "hours": "15.00", "sport": "Tennis", @@ -159,6 +163,48 @@ def get_weather(city, year, month, day): except: abort(500) + +def haversineDistance(lat1, lon1, lat2, lon2): + ## Calculates the Haversine Distance between two locations. + ## Available here:https://stackoverflow.com/questions/27928/calculate-distance-between-two-latitude-longitude-points-haversine-formula + p = pi/180 + a = 0.5 - cos((lat2-lat1)*p)/2 + cos(lat1*p) * cos(lat2*p) * (1-cos((lon2-lon1)*p))/2 + return 12742 * asin(sqrt(a)) + +@app.route('/api/v1.0/events', methods=['GET']) +def getNearbyEvents(): + useIP = request.args.get('ip') + address = request.args.get('address')##check, 400 + radius = request.args.get('radius') + eventType = request.args.get('sport') + ageRange = request.args.get('ageGroup') + skillLevel = request.args.get('skillLevel') + filterEmpty = request.args.get('empty') + filteredEvents = events + for argument in request.args: + print(argument) + if argument == 'address' or argument == 'radius' or argument =='ip': + continue + elif argument == "empty": + if request.args["empty"]=="true": + filteredEvents = list(filter(lambda event: len(event["players"])', methods=['GET']) From 5df4aa016d1e26bbba81c3d01d78ed705a94d469 Mon Sep 17 00:00:00 2001 From: dogukanakar Date: Sun, 30 May 2021 20:39:37 +0300 Subject: [PATCH 010/179] Create event pages and filter event added --- practice-app/web/src/App.js | 50 ++++++++++- .../web/src/components/FilterEventModal.js | 68 +++++++++++++++ practice-app/web/src/screens/CreateEvent.js | 69 ++++++++++++++++ practice-app/web/src/screens/Events.js | 82 +++++++++++++++---- 4 files changed, 247 insertions(+), 22 deletions(-) create mode 100644 practice-app/web/src/components/FilterEventModal.js create mode 100644 practice-app/web/src/screens/CreateEvent.js diff --git a/practice-app/web/src/App.js b/practice-app/web/src/App.js index 86c5fd57..bb1ad5f4 100644 --- a/practice-app/web/src/App.js +++ b/practice-app/web/src/App.js @@ -1,4 +1,4 @@ -import React from 'react' +import React, {useEffect, useState} from 'react' import Events from "./screens/Events"; import EventPage from "./screens/EventPage"; import { @@ -11,9 +11,11 @@ import { import Drawer from "@material-ui/core/Drawer"; import List from "@material-ui/core/List"; import ListItem from "@material-ui/core/ListItem"; -import {Divider, makeStyles, ListItemIcon, ListItemText} from "@material-ui/core"; +import {Divider, makeStyles, ListItemIcon, ListItemText, IconButton} from "@material-ui/core"; import SportsIcon from '@material-ui/icons/Sports'; import ShoppingCartIcon from '@material-ui/icons/ShoppingCart'; +import MenuIcon from '@material-ui/icons/Menu'; +import CreateEvent from "./screens/CreateEvent"; const drawerWidth = 240; @@ -43,17 +45,42 @@ const useStyles = makeStyles((theme) => ({ function App() { const classes = useStyles() - const history = useHistory(); + const [open, setOpen] = useState(false) + const [width, setWidth] = useState(window.innerWidth); + const handleWindowSizeChange = () => { + setWidth(window.innerWidth); + } + + useEffect(() => { + window.addEventListener('resize', handleWindowSizeChange); + return () => { + window.removeEventListener('resize', handleWindowSizeChange); + } + }, []); return ( + setOpen(true)} + edge="start" + style={{ + left:5, + top:5 + }} + > + + setOpen(false)} classes={{ paper: classes.drawerPaper, }} anchor="left" + variant={width >= 1450?"permanent":null} > {document.location.href="/events"}}> @@ -68,12 +95,27 @@ function App() { + + + {document.location.href="/create-event"}}> + + + + + + + {document.location.href="/create-equipment"}}> + + + + } + diff --git a/practice-app/web/src/components/FilterEventModal.js b/practice-app/web/src/components/FilterEventModal.js new file mode 100644 index 00000000..7c4812e6 --- /dev/null +++ b/practice-app/web/src/components/FilterEventModal.js @@ -0,0 +1,68 @@ +import React, {useState} from 'react' +import Dialog from '@material-ui/core/Dialog'; +import DialogActions from '@material-ui/core/DialogActions'; +import DialogContent from '@material-ui/core/DialogContent'; +import DialogContentText from '@material-ui/core/DialogContentText'; +import DialogTitle from '@material-ui/core/DialogTitle'; +import TextField from "@material-ui/core/TextField"; +import Button from "@material-ui/core/Button"; + +const fields = [ + "Age", + "Location", + "Location Range", + "Gender", + "Skill Level" +] + +export default function FilterEventModal(props){ + const [filter, setFilter] = useState({}) + const sendFilter = _=>{ + props.setFilter(filter) + props.handleClose() + } + const handleChange = e=>{ + const id = e.target.id + const value = e.target.value + const filters = {...filter} + if(value === "")filters[""+id] = undefined + else filters[""+id] = value + setFilter(filters) + } + return ( + + + Choose Filters + + + You can choose filters to search events. + + + { + fields.map(field=>( + + )) + } + + + + + + + + ) +} \ No newline at end of file diff --git a/practice-app/web/src/screens/CreateEvent.js b/practice-app/web/src/screens/CreateEvent.js new file mode 100644 index 00000000..6d4db3b5 --- /dev/null +++ b/practice-app/web/src/screens/CreateEvent.js @@ -0,0 +1,69 @@ +import React, {useEffect, useState} from 'react' +import Container from "@material-ui/core/Container"; +import SearchIcon from '@material-ui/icons/Search'; +import FilterListIcon from '@material-ui/icons/FilterList'; +import EventRow from '../components/EventRow' +import Table from '@material-ui/core/Table'; +import TableBody from '@material-ui/core/TableBody'; +import TableCell from '@material-ui/core/TableCell'; +import TableContainer from '@material-ui/core/TableContainer'; +import TableHead from '@material-ui/core/TableHead'; +import TableRow from '@material-ui/core/TableRow'; +import Paper from '@material-ui/core/Paper'; +import Grid from '@material-ui/core/Grid'; +import Button from '@material-ui/core/Button'; +import {useHistory} from "react-router-dom"; +import FilterEventModal from "../components/FilterEventModal"; +import TextField from "@material-ui/core/TextField"; + +const events = [ + { + eventId: 1, + owner: "emre_gundogu", + title: "Tennis Game for Everyone", + content: "People who are looking for a tennis court can apply this event. Our court is for you if you are seeking for a clean and well-lit court.", + location: "Bebek Tennis Club", + date: "01.05.2021", + hours: "15.00", + sport: "Tennis", + ageGroup: "Any age", + skillLevel: "Any level", + playerCapacity: "2", + spectatorCapacity: "8", + spectators: [], + players: [] + } +] + +const fields = [ + "Age", + "Location", + "Location Range", + "Gender", + "Skill Level" +] + +export default function CreateEvent() { + + return ( + + + { + fields.map(field=>( + + )) + } + + + ); +} + diff --git a/practice-app/web/src/screens/Events.js b/practice-app/web/src/screens/Events.js index e1c0c69b..e25a1c5b 100644 --- a/practice-app/web/src/screens/Events.js +++ b/practice-app/web/src/screens/Events.js @@ -1,9 +1,9 @@ -import React, {useState} from 'react' +import React, {useEffect, useState} from 'react' import Container from "@material-ui/core/Container"; import {InputAdornment, makeStyles, TextField} from "@material-ui/core"; import SearchIcon from '@material-ui/icons/Search'; +import FilterListIcon from '@material-ui/icons/FilterList'; import EventRow from '../components/EventRow' - import Table from '@material-ui/core/Table'; import TableBody from '@material-ui/core/TableBody'; import TableCell from '@material-ui/core/TableCell'; @@ -11,7 +11,10 @@ import TableContainer from '@material-ui/core/TableContainer'; import TableHead from '@material-ui/core/TableHead'; import TableRow from '@material-ui/core/TableRow'; import Paper from '@material-ui/core/Paper'; +import Grid from '@material-ui/core/Grid'; +import Button from '@material-ui/core/Button'; import {useHistory} from "react-router-dom"; +import FilterEventModal from "../components/FilterEventModal"; const events = [ { @@ -37,29 +40,67 @@ const useStyles = makeStyles({ }, }); +/* +* Filter +* { +* field: { +* range:[int,int], +* } +* } +* */ + export default function EventScreen() { + const [open, setOpen] = useState(false); + const [filter, setFilter] = useState({}); + const handleClose = () => { + setOpen(false); + }; const [text, setText] = useState("") const classes = useStyles(); const history = useHistory() + const [width, setWidth] = useState(window.innerWidth); + const handleWindowSizeChange = () => { + setWidth(window.innerWidth); + } + useEffect(() => { + window.addEventListener('resize', handleWindowSizeChange); + return () => { + window.removeEventListener('resize', handleWindowSizeChange); + } + }, []); + return ( - + -
- setText(e.target.value)} - InputProps={{ - startAdornment:( - - - - ) - }} - /> -
+ + 600?10:9}> + setText(e.target.value)} + InputProps={{ + startAdornment:( + + + + ) + }} + /> + + + + + + @@ -84,6 +125,11 @@ export default function EventScreen() {
+
); } From 817e117db9c6d15039da18755a4d2efa1169e556 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Berkay=20D=C3=B6ner?= Date: Sun, 30 May 2021 20:50:36 +0300 Subject: [PATCH 011/179] removed API key for security purposes --- practice-app/app/app.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/practice-app/app/app.py b/practice-app/app/app.py index 3dedf9b5..94b72005 100644 --- a/practice-app/app/app.py +++ b/practice-app/app/app.py @@ -5,7 +5,7 @@ from math import cos, asin, sqrt, pi app = Flask(__name__) -API_KEY = "AIzaSyD5TlVjboI-PWBYRI-dEznS3pmaflGr8Os" +API_KEY = "Google API Key" events = [ { @@ -163,7 +163,7 @@ def get_weather(city, year, month, day): except: abort(500) - + def haversineDistance(lat1, lon1, lat2, lon2): ## Calculates the Haversine Distance between two locations. ## Available here:https://stackoverflow.com/questions/27928/calculate-distance-between-two-latitude-longitude-points-haversine-formula From 9ef0cff0c5ee00ae75134f5e084ab3c4e159a044 Mon Sep 17 00:00:00 2001 From: Kerem Zaman Date: Tue, 1 Jun 2021 01:02:05 +0300 Subject: [PATCH 012/179] Refs #48 - Add postgresql image and configuration to docker-compose --- practice-app/database.env | 3 +++ practice-app/docker-compose.yml | 13 ++++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) create mode 100644 practice-app/database.env diff --git a/practice-app/database.env b/practice-app/database.env new file mode 100644 index 00000000..0a0eb625 --- /dev/null +++ b/practice-app/database.env @@ -0,0 +1,3 @@ +POSTGRES_USER=practice_user +POSTGRES_PASSWORD=-#My6o0dPa33W0rd#- +POSTGRES_DB=practiceapp_db \ No newline at end of file diff --git a/practice-app/docker-compose.yml b/practice-app/docker-compose.yml index f41a88f3..56ece373 100644 --- a/practice-app/docker-compose.yml +++ b/practice-app/docker-compose.yml @@ -5,8 +5,15 @@ services: ports: - "9000:9000" + database: + image: "postgres:latest" + env_file: + - database.env + ports: + - "5432:5432" + volumes: + - database-data:/var/lib/postgresql/data/ + volumes: - data: - cache: - analytics: + database-data: From 0ee15ca67a1d587639b601766da07560bdcf4524 Mon Sep 17 00:00:00 2001 From: ege-kaya <43046947+ege-kaya@users.noreply.github.com> Date: Tue, 1 Jun 2021 10:59:06 +0300 Subject: [PATCH 013/179] Worked on sqlalchemy integration, added a table for users and a dummy user entry --- practice-app/app/app.py | 55 +++++++++++++++++++++++++++++++++++------ 1 file changed, 47 insertions(+), 8 deletions(-) diff --git a/practice-app/app/app.py b/practice-app/app/app.py index c99dc8d8..bbdc2611 100644 --- a/practice-app/app/app.py +++ b/practice-app/app/app.py @@ -1,3 +1,7 @@ +from sqlalchemy import create_engine +from sqlalchemy import Column, String, Integer, BigInteger, ARRAY, Boolean +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.orm import sessionmaker import requests from flask import Flask, jsonify, abort, request from datetime import datetime @@ -27,13 +31,13 @@ { "userId": 1, "nickname": "emre_gundogu", - "firstName": "Emre", - "lastName": "Gundogu", + "first_name": "Emre", + "last_name": "Gundogu", "biography": "Hello, I am a 28 year-old football fan", - "age": "28", + "birth_year": "28", "avatar": "url_to_image", "location": "Istanbul", - "favSports": ["football", "basketball"], + "fav_sports": ["football", "basketball"], "badges": ["good_player", "serious"], "privacy": "public", } @@ -55,6 +59,41 @@ } ] +db = create_engine('postgresql://practice_user:#My6o0dPa33W0rd#-@localhost:5432/practiceapp_db') +base = declarative_base() + +class User(base): + __tablename__ = 'users' + + user_id = Column(BigInteger, primary_key=True) + nickname = Column(String) + first_name = Column(String) + last_name = Column(String) + biography = Column(String) + birth_year = Column(Integer) + avatar = Column(String) + location = Column(String) + fav_sport_1 = Column(String) + fav_sport_2 = Column(String) + fav_sport_3 = Column(String) + badge_1 = Column(String) + badge_2 = Column(String) + badge_3 = Column(String) + privacy = Column(Boolean) + +Session = sessionmaker(db) +session = Session() + +base.metadata.create_all(db) + +emre_gundogu = User(user_id=2, nickname="emre_gundogu", first_name="Emre", + last_name="Gundogu", biography="Hello, I am a 28 year-old football fan", + birth_year=1993, avatar="url_to_image", location="Istanbul", + fav_sport_1="football", fav_sport_2="basketball", badge_1="good_player", + badge_2="serious", privacy=True) + +session.add(emre_gundogu) +session.commit() @app.route('/api/v1.0/', methods=['GET']) def index(): @@ -113,13 +152,13 @@ def apply_as_player(event_id): json_data = response.json()["results"] new_user = {"userId": user_id, "nickname": json_data[0]["nickname"], - "firstName": json_data[0]["firstName"], - "lastName": json_data[0]["lastName"], + "first_name": json_data[0]["firstName"], + "last_name": json_data[0]["lastName"], "biography": json_data[0]["biography"], - "age": json_data[0]["age"], + "birth_year": json_data[0]["birth_year"], "avatar": json_data[0]["avatar"], "location": json_data[0]["location"], - "favSports": json_data[0]["favSports"], + "fav_sports": json_data[0]["favSports"], "badges": json_data[0]["badges"], "privacy": json_data[0]["privacy"]} print(new_user) From 0e4d4bdb46b1f58474582d5e44a2a60cb3fe6e11 Mon Sep 17 00:00:00 2001 From: ege-kaya <43046947+ege-kaya@users.noreply.github.com> Date: Tue, 1 Jun 2021 11:39:36 +0300 Subject: [PATCH 014/179] Finished postgresql and sqlalchemy integration --- practice-app/app/app.py | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/practice-app/app/app.py b/practice-app/app/app.py index 9f5dcea0..95361d5c 100644 --- a/practice-app/app/app.py +++ b/practice-app/app/app.py @@ -1,5 +1,5 @@ from sqlalchemy import create_engine -from sqlalchemy import Column, String, Integer, BigInteger, ARRAY, Boolean +from sqlalchemy import Column, String, Integer, BigInteger, Boolean from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker import requests @@ -142,7 +142,7 @@ def get_event(event_id): 'covid_risk_status': covid_risk, 'current_cases': covid_data[-1]['Cases']}) -db = create_engine('postgresql://practice_user:#My6o0dPa33W0rd#-@localhost:5432/practiceapp_db') +db = create_engine('postgresql://practice_user:-#My6o0dPa33W0rd#-@localhost:5432/practiceapp_db') base = declarative_base() class User(base): @@ -169,15 +169,6 @@ class User(base): base.metadata.create_all(db) -emre_gundogu = User(user_id=2, nickname="emre_gundogu", first_name="Emre", - last_name="Gundogu", biography="Hello, I am a 28 year-old football fan", - birth_year=1993, avatar="url_to_image", location="Istanbul", - fav_sport_1="football", fav_sport_2="basketball", badge_1="good_player", - badge_2="serious", privacy=True) - -session.add(emre_gundogu) -session.commit() - @app.route('/api/v1.0/', methods=['GET']) def index(): return jsonify({'message': 'hello world'}), 200 # mock message as an example @@ -286,10 +277,8 @@ def apply_as_player(event_id): "fav_sports": json_data[0]["favSports"], "badges": json_data[0]["badges"], "privacy": json_data[0]["privacy"]} - print(new_user) users.append(new_user) user.append(new_user) - print(users) event[0]["players"].append(user[0]["nickname"]) return jsonify({"eventId": event_id, From aadccbfb41fdbf16911f6500160cf8c330a07b24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Berkay=20D=C3=B6ner?= Date: Tue, 1 Jun 2021 12:48:09 +0300 Subject: [PATCH 015/179] post and event post table initialization is added --- practice-app/app/app.py | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/practice-app/app/app.py b/practice-app/app/app.py index 95361d5c..78e42c9c 100644 --- a/practice-app/app/app.py +++ b/practice-app/app/app.py @@ -1,6 +1,7 @@ from sqlalchemy import create_engine -from sqlalchemy import Column, String, Integer, BigInteger, Boolean +from sqlalchemy import Column, String, Integer, BigInteger, Boolean, MetaData, Date, Time, DateTime, Text from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.dialects.postgresql import ENUM, NUMRANGE, INT4RANGE, ARRAY from sqlalchemy.orm import sessionmaker import requests from flask import Flask, jsonify, abort, request @@ -164,6 +165,29 @@ class User(base): badge_3 = Column(String) privacy = Column(Boolean) +class post(base): + __abstract__ = True + __tablename__ = "post" + postID = Column(Integer,primary_key=True) + ownerID = Column(Integer,nullable=False) + content = Column(Text) + title = Column(String(100),nullable=False) + creationDate = Column(DateTime,nullable=False) + location = Column(String(200)) + +class eventpost(post): + __tablename__ = "eventpost" + eventDate = Column(Date,nullable=False) + eventHours = Column(Time,nullable=False) + eventSport = Column(String(30),nullable=False) + eventAgeGroup = Column(INT4RANGE) + eventPlayerCapacity = Column(Integer,nullable=False) + eventSpectatorCapacity = Column(Integer) + eventPlayers = Column(ARRAY(Integer)) + eventSpectators = Column(ARRAY(Integer)) + eventSkillLevel = Column(ENUM('Beginner', 'Preintermediate', 'Intermediate','Advanced','Expert', name='skill')) + eventCoordinates = Column(NUMRANGE, nullable=False) + Session = sessionmaker(db) session = Session() From b1d3b5c2c58b9821424bf121e848dc17de7d7a08 Mon Sep 17 00:00:00 2001 From: dogukanakar Date: Tue, 1 Jun 2021 14:21:49 +0300 Subject: [PATCH 016/179] openstreetmap location pick added --- practice-app/web/package.json | 1 + practice-app/web/src/App.js | 2 +- .../web/src/components/FilterEventModal.js | 27 ++++++++++++- practice-app/web/yarn.lock | 40 ++++++++++++++++++- 4 files changed, 65 insertions(+), 5 deletions(-) diff --git a/practice-app/web/package.json b/practice-app/web/package.json index bfb088c3..cf788edd 100644 --- a/practice-app/web/package.json +++ b/practice-app/web/package.json @@ -10,6 +10,7 @@ "@testing-library/user-event": "^12.1.10", "react": "^17.0.2", "react-dom": "^17.0.2", + "react-leaflet-location-picker": "^1.4.2", "react-router-dom": "^5.2.0", "react-scripts": "4.0.3", "web-vitals": "^1.0.1" diff --git a/practice-app/web/src/App.js b/practice-app/web/src/App.js index bb1ad5f4..70831f34 100644 --- a/practice-app/web/src/App.js +++ b/practice-app/web/src/App.js @@ -59,7 +59,7 @@ function App() { } }, []); return ( - + 1?[filter["Location"].split(",")]:[]):[], + onClick: point =>setLocation(point), + onRemove: point =>setLocation(undefined) + } + }; const sendFilter = _=>{ props.setFilter(filter) props.handleClose() } + console.log(pointMode) const handleChange = e=>{ const id = e.target.id const value = e.target.value @@ -29,6 +41,11 @@ export default function FilterEventModal(props){ else filters[""+id] = value setFilter(filters) } + const setLocation = l=>{ + const filters = {...filter} + filters["Location"] = l[0] + "," + l[1] + setFilter(filters) + } return ( @@ -37,7 +54,12 @@ export default function FilterEventModal(props){ You can choose filters to search events. - + { fields.map(field=>( Date: Wed, 2 Jun 2021 00:06:49 +0300 Subject: [PATCH 017/179] Refs #48 - Fix requirements.txt for sqlalchemy and connection string to connect to database container --- practice-app/app/app.py | 2 +- practice-app/app/requirements.txt | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/practice-app/app/app.py b/practice-app/app/app.py index 78e42c9c..ebc25668 100644 --- a/practice-app/app/app.py +++ b/practice-app/app/app.py @@ -143,7 +143,7 @@ def get_event(event_id): 'covid_risk_status': covid_risk, 'current_cases': covid_data[-1]['Cases']}) -db = create_engine('postgresql://practice_user:-#My6o0dPa33W0rd#-@localhost:5432/practiceapp_db') +db = create_engine('postgresql://practice_user:-#My6o0dPa33W0rd#-@database/practiceapp_db') base = declarative_base() class User(base): diff --git a/practice-app/app/requirements.txt b/practice-app/app/requirements.txt index 873e7ba0..95313491 100644 --- a/practice-app/app/requirements.txt +++ b/practice-app/app/requirements.txt @@ -1,3 +1,5 @@ Flask==2.0.1 gunicorn==20.1.0 -requests==2.25.1 \ No newline at end of file +requests==2.25.1 +SQLAlchemy==1.4.17 +psycopg2 \ No newline at end of file From ec433064c5d7c2a730b144ba149c1fbc7ab9114a Mon Sep 17 00:00:00 2001 From: Voursstrreds <56487501+Voursstrreds@users.noreply.github.com> Date: Wed, 2 Jun 2021 14:49:11 +0300 Subject: [PATCH 018/179] Database of equipment post is added. --- practice-app/app/app.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/practice-app/app/app.py b/practice-app/app/app.py index ebc25668..3a19a2ae 100644 --- a/practice-app/app/app.py +++ b/practice-app/app/app.py @@ -188,6 +188,12 @@ class eventpost(post): eventSkillLevel = Column(ENUM('Beginner', 'Preintermediate', 'Intermediate','Advanced','Expert', name='skill')) eventCoordinates = Column(NUMRANGE, nullable=False) +class equipmentpost(post): + __tablename__ = "equiomentpost" + equipmentType = Column(String(30), nullable=False) + websiteName = Column(String(50), nullable=False) + link = Column(String(200), nullable=False) + Session = sessionmaker(db) session = Session() From 72240ffbe57d4a63bab7c92138738fef28b33a7d Mon Sep 17 00:00:00 2001 From: Bengisu Ozaydin Date: Wed, 2 Jun 2021 17:57:14 +0300 Subject: [PATCH 019/179] Refs #59 - implemented post event API while making use of mapquest API --- practice-app/app/app.py | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/practice-app/app/app.py b/practice-app/app/app.py index 3a19a2ae..1573c4f4 100644 --- a/practice-app/app/app.py +++ b/practice-app/app/app.py @@ -97,7 +97,7 @@ def results(equipmentId): title=equipment[0]['title'] query = { "q": equipment[0]['title'], - + } response=requests.get("https://rapidapi.p.rapidapi.com/api/v1/search/" + urllib.parse.urlencode(query), headers=headers) mapped=[{"description": j["description"],"link": j["link"], "title":j["title"]} for j in response.json()["results"]] @@ -225,7 +225,7 @@ def get_weather(city, year, month, day): abort(500) def haversineDistance(lat1, lon1, lat2, lon2): - ## Calculates the Haversine Distance between two locations. + ## Calculates the Haversine Distance between two locations. ## Available here:https://stackoverflow.com/questions/27928/calculate-distance-between-two-latitude-longitude-points-haversine-formula p = pi/180 a = 0.5 - cos((lat2-lat1)*p)/2 + cos(lat1*p) * cos(lat2*p) * (1-cos((lon2-lon1)*p))/2 @@ -262,7 +262,7 @@ def getNearbyEvents(): lat = ipdata["location"]["lat"] lng = ipdata["location"]["lng"] print(lat, lng) - nearbyEvents = [event for event in filteredEvents if + nearbyEvents = [event for event in filteredEvents if haversineDistance(lat,lng,event["coordinates"][0], event["coordinates"][1])<=float(radius)] return jsonify(nearbyEvents) @@ -362,6 +362,31 @@ def create_equipment_post(): equipmentPost.append(new_equipment) return jsonify({"equipment": new_equipment}), 201 +@app.route('api/v1.0/events', methods=['POST']) +def create_event_post(): + event_id = len(events) == 0 ? 1 : events[-1]['eventId'] + 1 + location = request.json['location'] + new_event = { + "eventId": event_id, + "owner": request.json['ownerId'], + "title": request.json['title'], + "content": request.json['content'], + "location": location, + "date": request.json['date'], + "hours": request.json['hours'], + "sport": request.json['sport'], + "ageGroup": request.json['ageGroup'], + "skillLevel": request.json['skillLevel'], + "playerCapacity": request.json['playerCapacity'], + "spectatorCapacity": request.json['spectatorCapacity'], + "spectators": request.json['spectators'], + "players": request.json['players'] + } + events.append(new_event) + key = I4AusKojAMUPh2QSaXg9RTGqsM903dJ1 + response = requests.get("http://www.mapquestapi.com/geocoding/v1/address?key={}&location={}".format(key, location)) + latLng = response["results"][0]["locations"]["latLng"] + return jsonify({"event": new_event, "latLng": latLng}), 201 if __name__ == '__main__': app.run(debug=True) From 2b98b2a17aee0cc5da26c10c0a38266b0e0fbf41 Mon Sep 17 00:00:00 2001 From: omerarslnn Date: Wed, 2 Jun 2021 20:40:31 +0300 Subject: [PATCH 020/179] equipment search methods added --- .idea/.gitignore | 3 +++ .idea/2021SpringGroup2.iml | 8 +++++++ .idea/inspectionProfiles/Project_Default.xml | 6 +++++ .../inspectionProfiles/profiles_settings.xml | 6 +++++ .idea/misc.xml | 7 ++++++ .idea/modules.xml | 8 +++++++ .idea/vcs.xml | 6 +++++ practice-app/app/app.py | 23 +++++++++++++++++-- 8 files changed, 65 insertions(+), 2 deletions(-) create mode 100644 .idea/.gitignore create mode 100644 .idea/2021SpringGroup2.iml create mode 100644 .idea/inspectionProfiles/Project_Default.xml create mode 100644 .idea/inspectionProfiles/profiles_settings.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 00000000..26d33521 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/2021SpringGroup2.iml b/.idea/2021SpringGroup2.iml new file mode 100644 index 00000000..d0876a78 --- /dev/null +++ b/.idea/2021SpringGroup2.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 00000000..ac21435f --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 00000000..105ce2da --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 00000000..0b5770b6 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 00000000..9785b0d6 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 00000000..94a25f7f --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/practice-app/app/app.py b/practice-app/app/app.py index 1573c4f4..beb3b81d 100644 --- a/practice-app/app/app.py +++ b/practice-app/app/app.py @@ -71,7 +71,9 @@ "content" : "I have a pair of shoes in good condition that i want to sell.", "website name" : "letgo", "link" : "letgo.com/245323", - "equipment type" : "Shoes" + "equipmentType": "shoes", + "location": "Istanbul", + "sportType": "Tennis" }, { @@ -81,7 +83,9 @@ "content" : "I have a pair of shoes in good condition that i want to sell.", "website name" : "letgo", "link" : "letgo.com/245323", - "equipment type" : "Shoes" + "equipmentType": "racket", + "location": "Ankara", + "sportType": "Tennis" } ] headers = { @@ -388,5 +392,20 @@ def create_event_post(): latLng = response["results"][0]["locations"]["latLng"] return jsonify({"event": new_event, "latLng": latLng}), 201 +@app.route('/api/v1.0/search-equipment-type/', methods=['GET']) +def search_equipments_by_type(equipmentType): + equipment = [equipment for equipment in equipments2 if equipment['equipmentType'] == equipmentType] + if len(equipment) == 0: + abort(404) + return jsonify(equipment), 200 + + +@app.route('/api/v1.0/search-equipment-location/', methods=['GET']) +def search_equipments_by_location(location): + equipment = [equipment for equipment in equipments2 if equipment['location'] == location] + if len(equipment) == 0: + abort(404) + return jsonify(equipment), 200 + if __name__ == '__main__': app.run(debug=True) From ffaf27be913d86a5bfd984a844bf5551c47ea3ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Do=C4=9Fukan=20Akar?= <36790615+CenekSanzak@users.noreply.github.com> Date: Wed, 2 Jun 2021 22:08:56 +0300 Subject: [PATCH 021/179] Delete .idea directory --- .idea/.gitignore | 3 --- .idea/2021SpringGroup2.iml | 8 -------- .idea/inspectionProfiles/Project_Default.xml | 6 ------ .idea/inspectionProfiles/profiles_settings.xml | 6 ------ .idea/misc.xml | 7 ------- .idea/modules.xml | 8 -------- .idea/vcs.xml | 6 ------ 7 files changed, 44 deletions(-) delete mode 100644 .idea/.gitignore delete mode 100644 .idea/2021SpringGroup2.iml delete mode 100644 .idea/inspectionProfiles/Project_Default.xml delete mode 100644 .idea/inspectionProfiles/profiles_settings.xml delete mode 100644 .idea/misc.xml delete mode 100644 .idea/modules.xml delete mode 100644 .idea/vcs.xml diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 26d33521..00000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml diff --git a/.idea/2021SpringGroup2.iml b/.idea/2021SpringGroup2.iml deleted file mode 100644 index d0876a78..00000000 --- a/.idea/2021SpringGroup2.iml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml deleted file mode 100644 index ac21435f..00000000 --- a/.idea/inspectionProfiles/Project_Default.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml deleted file mode 100644 index 105ce2da..00000000 --- a/.idea/inspectionProfiles/profiles_settings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 0b5770b6..00000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index 9785b0d6..00000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 94a25f7f..00000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file From aa074428803dd2f3201d97004f97bfc07341734c Mon Sep 17 00:00:00 2001 From: berkaydoner Date: Wed, 2 Jun 2021 22:10:14 +0300 Subject: [PATCH 022/179] Refs #58 - separated database initalization code --- practice-app/app/app.py | 55 -------------------------------------- practice-app/app/dbinit.py | 55 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 55 deletions(-) create mode 100644 practice-app/app/dbinit.py diff --git a/practice-app/app/app.py b/practice-app/app/app.py index 78e42c9c..d2894ab7 100644 --- a/practice-app/app/app.py +++ b/practice-app/app/app.py @@ -1,8 +1,3 @@ -from sqlalchemy import create_engine -from sqlalchemy import Column, String, Integer, BigInteger, Boolean, MetaData, Date, Time, DateTime, Text -from sqlalchemy.ext.declarative import declarative_base -from sqlalchemy.dialects.postgresql import ENUM, NUMRANGE, INT4RANGE, ARRAY -from sqlalchemy.orm import sessionmaker import requests from flask import Flask, jsonify, abort, request import urllib @@ -143,56 +138,6 @@ def get_event(event_id): 'covid_risk_status': covid_risk, 'current_cases': covid_data[-1]['Cases']}) -db = create_engine('postgresql://practice_user:-#My6o0dPa33W0rd#-@localhost:5432/practiceapp_db') -base = declarative_base() - -class User(base): - __tablename__ = 'users' - - user_id = Column(BigInteger, primary_key=True) - nickname = Column(String) - first_name = Column(String) - last_name = Column(String) - biography = Column(String) - birth_year = Column(Integer) - avatar = Column(String) - location = Column(String) - fav_sport_1 = Column(String) - fav_sport_2 = Column(String) - fav_sport_3 = Column(String) - badge_1 = Column(String) - badge_2 = Column(String) - badge_3 = Column(String) - privacy = Column(Boolean) - -class post(base): - __abstract__ = True - __tablename__ = "post" - postID = Column(Integer,primary_key=True) - ownerID = Column(Integer,nullable=False) - content = Column(Text) - title = Column(String(100),nullable=False) - creationDate = Column(DateTime,nullable=False) - location = Column(String(200)) - -class eventpost(post): - __tablename__ = "eventpost" - eventDate = Column(Date,nullable=False) - eventHours = Column(Time,nullable=False) - eventSport = Column(String(30),nullable=False) - eventAgeGroup = Column(INT4RANGE) - eventPlayerCapacity = Column(Integer,nullable=False) - eventSpectatorCapacity = Column(Integer) - eventPlayers = Column(ARRAY(Integer)) - eventSpectators = Column(ARRAY(Integer)) - eventSkillLevel = Column(ENUM('Beginner', 'Preintermediate', 'Intermediate','Advanced','Expert', name='skill')) - eventCoordinates = Column(NUMRANGE, nullable=False) - -Session = sessionmaker(db) -session = Session() - -base.metadata.create_all(db) - @app.route('/api/v1.0/', methods=['GET']) def index(): return jsonify({'message': 'hello world'}), 200 # mock message as an example diff --git a/practice-app/app/dbinit.py b/practice-app/app/dbinit.py new file mode 100644 index 00000000..e2890c67 --- /dev/null +++ b/practice-app/app/dbinit.py @@ -0,0 +1,55 @@ +from sqlalchemy import create_engine +from sqlalchemy import Column, String, Integer, BigInteger, Boolean, MetaData, Date, Time, DateTime, Text +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.dialects.postgresql import ENUM, NUMRANGE, INT4RANGE, ARRAY +from sqlalchemy.orm import sessionmaker + +db = create_engine('postgresql://practice_user:-#My6o0dPa33W0rd#-@localhost:5432/practiceapp_db') +base = declarative_base() + +class User(base): + __tablename__ = 'users' + + user_id = Column(BigInteger, primary_key=True) + nickname = Column(String) + first_name = Column(String) + last_name = Column(String) + biography = Column(String) + birth_year = Column(Integer) + avatar = Column(String) + location = Column(String) + fav_sport_1 = Column(String) + fav_sport_2 = Column(String) + fav_sport_3 = Column(String) + badge_1 = Column(String) + badge_2 = Column(String) + badge_3 = Column(String) + privacy = Column(Boolean) + +class post(base): + __abstract__ = True + __tablename__ = "post" + postID = Column(Integer,primary_key=True) + ownerID = Column(Integer,nullable=False) + content = Column(Text) + title = Column(String(100),nullable=False) + creationDate = Column(DateTime,nullable=False) + location = Column(String(200)) + +class eventpost(post): + __tablename__ = "eventpost" + eventDate = Column(Date,nullable=False) + eventHours = Column(Time,nullable=False) + eventSport = Column(String(30),nullable=False) + eventAgeGroup = Column(INT4RANGE) + eventPlayerCapacity = Column(Integer,nullable=False) + eventSpectatorCapacity = Column(Integer) + eventPlayers = Column(ARRAY(Integer)) + eventSpectators = Column(ARRAY(Integer)) + eventSkillLevel = Column(ENUM('Beginner', 'Preintermediate', 'Intermediate','Advanced','Expert', name='skill')) + eventCoordinates = Column(NUMRANGE, nullable=False) + +Session = sessionmaker(db) +session = Session() + +base.metadata.create_all(db) \ No newline at end of file From c0c23bcbcc7770ed375727f361aecd43c2e2277b Mon Sep 17 00:00:00 2001 From: berkaydoner Date: Sat, 5 Jun 2021 17:25:44 +0300 Subject: [PATCH 023/179] Refs #58 - separated the composite type, added foreign key constraint --- practice-app/app/dbinit.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/practice-app/app/dbinit.py b/practice-app/app/dbinit.py index e2890c67..77fd5834 100644 --- a/practice-app/app/dbinit.py +++ b/practice-app/app/dbinit.py @@ -1,7 +1,8 @@ from sqlalchemy import create_engine -from sqlalchemy import Column, String, Integer, BigInteger, Boolean, MetaData, Date, Time, DateTime, Text -from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy import Column, String, Integer, BigInteger, Boolean, MetaData, Date, Time, DateTime, Text, Float +from sqlalchemy.ext.declarative import declarative_base, declared_attr from sqlalchemy.dialects.postgresql import ENUM, NUMRANGE, INT4RANGE, ARRAY +from sqlalchemy.sql.schema import ForeignKey from sqlalchemy.orm import sessionmaker db = create_engine('postgresql://practice_user:-#My6o0dPa33W0rd#-@localhost:5432/practiceapp_db') @@ -29,8 +30,10 @@ class User(base): class post(base): __abstract__ = True __tablename__ = "post" - postID = Column(Integer,primary_key=True) - ownerID = Column(Integer,nullable=False) + postID = Column(BigInteger,primary_key=True) + @declared_attr + def ownerID(cls): + return Column(BigInteger,ForeignKey("users.user_id"),nullable=False) content = Column(Text) title = Column(String(100),nullable=False) creationDate = Column(DateTime,nullable=False) @@ -47,7 +50,8 @@ class eventpost(post): eventPlayers = Column(ARRAY(Integer)) eventSpectators = Column(ARRAY(Integer)) eventSkillLevel = Column(ENUM('Beginner', 'Preintermediate', 'Intermediate','Advanced','Expert', name='skill')) - eventCoordinates = Column(NUMRANGE, nullable=False) + eventLatitude = Column(Float) + eventLongitude = Column(Float) Session = sessionmaker(db) session = Session() From 20a1faf871ec98a6ea40da2ed2179de0b49896ed Mon Sep 17 00:00:00 2001 From: ege-kaya <43046947+ege-kaya@users.noreply.github.com> Date: Sat, 5 Jun 2021 16:29:37 +0300 Subject: [PATCH 024/179] fixed two small syntax errors --- practice-app/Dockerfile | 4 ++-- practice-app/app/app.py | 4 ++-- practice-app/app/requirements.txt | 1 + 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/practice-app/Dockerfile b/practice-app/Dockerfile index 4dc26476..edb328b0 100644 --- a/practice-app/Dockerfile +++ b/practice-app/Dockerfile @@ -1,8 +1,8 @@ FROM python:3.6 ADD app/requirements.txt . -RUN pip install --upgrade pip -RUN pip install -r requirements.txt +RUN pip3 install --upgrade pip +RUN pip3 install -r requirements.txt ADD app/ /app WORKDIR / diff --git a/practice-app/app/app.py b/practice-app/app/app.py index 0923c018..bc916eeb 100644 --- a/practice-app/app/app.py +++ b/practice-app/app/app.py @@ -307,7 +307,7 @@ def create_equipment_post(): @app.route('api/v1.0/events', methods=['POST']) def create_event_post(): - event_id = len(events) == 0 ? 1 : events[-1]['eventId'] + 1 + event_id = 1 if len(events) == 0 else events[-1]['eventId'] + 1 location = request.json['location'] new_event = { "eventId": event_id, @@ -326,7 +326,7 @@ def create_event_post(): "players": request.json['players'] } events.append(new_event) - key = I4AusKojAMUPh2QSaXg9RTGqsM903dJ1 + key = "I4AusKojAMUPh2QSaXg9RTGqsM903dJ1" response = requests.get("http://www.mapquestapi.com/geocoding/v1/address?key={}&location={}".format(key, location)) latLng = response["results"][0]["locations"]["latLng"] return jsonify({"event": new_event, "latLng": latLng}), 201 diff --git a/practice-app/app/requirements.txt b/practice-app/app/requirements.txt index 95313491..10c60559 100644 --- a/practice-app/app/requirements.txt +++ b/practice-app/app/requirements.txt @@ -1,5 +1,6 @@ Flask==2.0.1 gunicorn==20.1.0 requests==2.25.1 +sqlalchemy SQLAlchemy==1.4.17 psycopg2 \ No newline at end of file From e9354ea5efb651ae89d88f22be1000b6abd9f984 Mon Sep 17 00:00:00 2001 From: berkaydoner Date: Sat, 5 Jun 2021 23:18:41 +0300 Subject: [PATCH 025/179] Separated API methods to different files --- practice-app/app/answer.py | 92 +++++++++++++ practice-app/app/block.py | 92 +++++++++++++ practice-app/app/comment.py | 92 +++++++++++++ practice-app/app/equipment.py | 161 +++++++++++++++++++++++ practice-app/app/event.py | 214 +++++++++++++++++++++++++++++++ practice-app/app/follow.py | 92 +++++++++++++ practice-app/app/notification.py | 92 +++++++++++++ practice-app/app/player.py | 130 +++++++++++++++++++ practice-app/app/spectator.py | 108 ++++++++++++++++ practice-app/app/user.py | 92 +++++++++++++ 10 files changed, 1165 insertions(+) create mode 100644 practice-app/app/answer.py create mode 100644 practice-app/app/block.py create mode 100644 practice-app/app/comment.py create mode 100644 practice-app/app/equipment.py create mode 100644 practice-app/app/event.py create mode 100644 practice-app/app/follow.py create mode 100644 practice-app/app/notification.py create mode 100644 practice-app/app/player.py create mode 100644 practice-app/app/spectator.py create mode 100644 practice-app/app/user.py diff --git a/practice-app/app/answer.py b/practice-app/app/answer.py new file mode 100644 index 00000000..7f44285c --- /dev/null +++ b/practice-app/app/answer.py @@ -0,0 +1,92 @@ +import requests +from flask import Flask, jsonify, abort, request +import urllib +from datetime import datetime, timedelta +from math import cos, asin, sqrt, pi + +app = Flask(__name__) +API_KEY = "Google API Key" + +events = [ + { + "eventId": 1, + "owner": "emre_gundogu", + "title": "Tennis Game for Everyone", + "content": "People who are looking for a tennis court can apply this event. Our court is for you if you are seeking for a clean and well-lit court.", + "location": "Etiler Tennis Club", + "coordinates": (41.0869173, 29.0321301), + "date": "01.05.2021", + "hours": "15.00", + "sport": "Tennis", + "ageGroup": "Any age", + "skillLevel": "Any level", + "playerCapacity": "2", + "spectatorCapacity": "8", + "spectators": [{"username":"zulfikar_tunc"}], + "players": [{"username":"zulfikar_tunc"}] + } +] + +users = [ + { + "userId": 1, + "nickname": "emre_gundogu", + "first_name": "Emre", + "last_name": "Gundogu", + "biography": "Hello, I am a 28 year-old football fan", + "birth_year": "28", + "avatar": "url_to_image", + "location": "Istanbul", + "fav_sports": ["football", "basketball"], + "badges": ["good_player", "serious"], + "privacy": "public", + } +] + +equipmentPost = [ + { + "postId": 1, + "ownerId": 1, + "content": "A nice ball", + "title": "Well-conditioned ball", + "creationDate": "29.05.2021", + "lastUpdateDate": "29.05.2021", + "numberOfClicks": 1, + "location": "İstanbul", + "equipmentType": "Ball", + "websiteName": "ismycomputeron", + "link": "www.ismycomputeron.com" + } +] +equipments2 = [ + { + "equipmentId": 1, + "ownerId": 1, + "title" : "Tennis shoes for sale!", + "content" : "I have a pair of shoes in good condition that i want to sell.", + "website name" : "letgo", + "link" : "letgo.com/245323", + "equipmentType": "shoes", + "location": "Istanbul", + "sportType": "Tennis" + + }, + { + "equipmentId": 2, + "ownerId": 1, + "title" : "Tennis rackets for sale!", + "content" : "I have a pair of shoes in good condition that i want to sell.", + "website name" : "letgo", + "link" : "letgo.com/245323", + "equipmentType": "racket", + "location": "Ankara", + "sportType": "Tennis" + } +] +headers = { + "x-rapidapi-key": "c4ab16012amsh73b5a257264eb3dp11ade4jsnb69ec0b79098", + "x-rapidapi-host" :"google-search3.p.rapidapi.com" +} + +if __name__ == '__main__': + app.run(debug=True) diff --git a/practice-app/app/block.py b/practice-app/app/block.py new file mode 100644 index 00000000..7f44285c --- /dev/null +++ b/practice-app/app/block.py @@ -0,0 +1,92 @@ +import requests +from flask import Flask, jsonify, abort, request +import urllib +from datetime import datetime, timedelta +from math import cos, asin, sqrt, pi + +app = Flask(__name__) +API_KEY = "Google API Key" + +events = [ + { + "eventId": 1, + "owner": "emre_gundogu", + "title": "Tennis Game for Everyone", + "content": "People who are looking for a tennis court can apply this event. Our court is for you if you are seeking for a clean and well-lit court.", + "location": "Etiler Tennis Club", + "coordinates": (41.0869173, 29.0321301), + "date": "01.05.2021", + "hours": "15.00", + "sport": "Tennis", + "ageGroup": "Any age", + "skillLevel": "Any level", + "playerCapacity": "2", + "spectatorCapacity": "8", + "spectators": [{"username":"zulfikar_tunc"}], + "players": [{"username":"zulfikar_tunc"}] + } +] + +users = [ + { + "userId": 1, + "nickname": "emre_gundogu", + "first_name": "Emre", + "last_name": "Gundogu", + "biography": "Hello, I am a 28 year-old football fan", + "birth_year": "28", + "avatar": "url_to_image", + "location": "Istanbul", + "fav_sports": ["football", "basketball"], + "badges": ["good_player", "serious"], + "privacy": "public", + } +] + +equipmentPost = [ + { + "postId": 1, + "ownerId": 1, + "content": "A nice ball", + "title": "Well-conditioned ball", + "creationDate": "29.05.2021", + "lastUpdateDate": "29.05.2021", + "numberOfClicks": 1, + "location": "İstanbul", + "equipmentType": "Ball", + "websiteName": "ismycomputeron", + "link": "www.ismycomputeron.com" + } +] +equipments2 = [ + { + "equipmentId": 1, + "ownerId": 1, + "title" : "Tennis shoes for sale!", + "content" : "I have a pair of shoes in good condition that i want to sell.", + "website name" : "letgo", + "link" : "letgo.com/245323", + "equipmentType": "shoes", + "location": "Istanbul", + "sportType": "Tennis" + + }, + { + "equipmentId": 2, + "ownerId": 1, + "title" : "Tennis rackets for sale!", + "content" : "I have a pair of shoes in good condition that i want to sell.", + "website name" : "letgo", + "link" : "letgo.com/245323", + "equipmentType": "racket", + "location": "Ankara", + "sportType": "Tennis" + } +] +headers = { + "x-rapidapi-key": "c4ab16012amsh73b5a257264eb3dp11ade4jsnb69ec0b79098", + "x-rapidapi-host" :"google-search3.p.rapidapi.com" +} + +if __name__ == '__main__': + app.run(debug=True) diff --git a/practice-app/app/comment.py b/practice-app/app/comment.py new file mode 100644 index 00000000..7f44285c --- /dev/null +++ b/practice-app/app/comment.py @@ -0,0 +1,92 @@ +import requests +from flask import Flask, jsonify, abort, request +import urllib +from datetime import datetime, timedelta +from math import cos, asin, sqrt, pi + +app = Flask(__name__) +API_KEY = "Google API Key" + +events = [ + { + "eventId": 1, + "owner": "emre_gundogu", + "title": "Tennis Game for Everyone", + "content": "People who are looking for a tennis court can apply this event. Our court is for you if you are seeking for a clean and well-lit court.", + "location": "Etiler Tennis Club", + "coordinates": (41.0869173, 29.0321301), + "date": "01.05.2021", + "hours": "15.00", + "sport": "Tennis", + "ageGroup": "Any age", + "skillLevel": "Any level", + "playerCapacity": "2", + "spectatorCapacity": "8", + "spectators": [{"username":"zulfikar_tunc"}], + "players": [{"username":"zulfikar_tunc"}] + } +] + +users = [ + { + "userId": 1, + "nickname": "emre_gundogu", + "first_name": "Emre", + "last_name": "Gundogu", + "biography": "Hello, I am a 28 year-old football fan", + "birth_year": "28", + "avatar": "url_to_image", + "location": "Istanbul", + "fav_sports": ["football", "basketball"], + "badges": ["good_player", "serious"], + "privacy": "public", + } +] + +equipmentPost = [ + { + "postId": 1, + "ownerId": 1, + "content": "A nice ball", + "title": "Well-conditioned ball", + "creationDate": "29.05.2021", + "lastUpdateDate": "29.05.2021", + "numberOfClicks": 1, + "location": "İstanbul", + "equipmentType": "Ball", + "websiteName": "ismycomputeron", + "link": "www.ismycomputeron.com" + } +] +equipments2 = [ + { + "equipmentId": 1, + "ownerId": 1, + "title" : "Tennis shoes for sale!", + "content" : "I have a pair of shoes in good condition that i want to sell.", + "website name" : "letgo", + "link" : "letgo.com/245323", + "equipmentType": "shoes", + "location": "Istanbul", + "sportType": "Tennis" + + }, + { + "equipmentId": 2, + "ownerId": 1, + "title" : "Tennis rackets for sale!", + "content" : "I have a pair of shoes in good condition that i want to sell.", + "website name" : "letgo", + "link" : "letgo.com/245323", + "equipmentType": "racket", + "location": "Ankara", + "sportType": "Tennis" + } +] +headers = { + "x-rapidapi-key": "c4ab16012amsh73b5a257264eb3dp11ade4jsnb69ec0b79098", + "x-rapidapi-host" :"google-search3.p.rapidapi.com" +} + +if __name__ == '__main__': + app.run(debug=True) diff --git a/practice-app/app/equipment.py b/practice-app/app/equipment.py new file mode 100644 index 00000000..de6a9a72 --- /dev/null +++ b/practice-app/app/equipment.py @@ -0,0 +1,161 @@ +import requests +from flask import Flask, jsonify, abort, request +import urllib +from datetime import datetime, timedelta +from math import cos, asin, sqrt, pi + +app = Flask(__name__) +API_KEY = "Google API Key" + +events = [ + { + "eventId": 1, + "owner": "emre_gundogu", + "title": "Tennis Game for Everyone", + "content": "People who are looking for a tennis court can apply this event. Our court is for you if you are seeking for a clean and well-lit court.", + "location": "Etiler Tennis Club", + "coordinates": (41.0869173, 29.0321301), + "date": "01.05.2021", + "hours": "15.00", + "sport": "Tennis", + "ageGroup": "Any age", + "skillLevel": "Any level", + "playerCapacity": "2", + "spectatorCapacity": "8", + "spectators": [{"username":"zulfikar_tunc"}], + "players": [{"username":"zulfikar_tunc"}] + } +] + +users = [ + { + "userId": 1, + "nickname": "emre_gundogu", + "first_name": "Emre", + "last_name": "Gundogu", + "biography": "Hello, I am a 28 year-old football fan", + "birth_year": "28", + "avatar": "url_to_image", + "location": "Istanbul", + "fav_sports": ["football", "basketball"], + "badges": ["good_player", "serious"], + "privacy": "public", + } +] + +equipmentPost = [ + { + "postId": 1, + "ownerId": 1, + "content": "A nice ball", + "title": "Well-conditioned ball", + "creationDate": "29.05.2021", + "lastUpdateDate": "29.05.2021", + "numberOfClicks": 1, + "location": "İstanbul", + "equipmentType": "Ball", + "websiteName": "ismycomputeron", + "link": "www.ismycomputeron.com" + } +] +equipments2 = [ + { + "equipmentId": 1, + "ownerId": 1, + "title" : "Tennis shoes for sale!", + "content" : "I have a pair of shoes in good condition that i want to sell.", + "website name" : "letgo", + "link" : "letgo.com/245323", + "equipmentType": "shoes", + "location": "Istanbul", + "sportType": "Tennis" + + }, + { + "equipmentId": 2, + "ownerId": 1, + "title" : "Tennis rackets for sale!", + "content" : "I have a pair of shoes in good condition that i want to sell.", + "website name" : "letgo", + "link" : "letgo.com/245323", + "equipmentType": "racket", + "location": "Ankara", + "sportType": "Tennis" + } +] +headers = { + "x-rapidapi-key": "c4ab16012amsh73b5a257264eb3dp11ade4jsnb69ec0b79098", + "x-rapidapi-host" :"google-search3.p.rapidapi.com" +} + +@app.route('/api/v1.0/equipments//results', methods=['GET']) +def results(equipmentId): + equipment = [equipment for equipment in equipments2 if equipment['equipmentId'] == equipmentId] + if len(equipment) == 0: + abort(404) + title=equipment[0]['title'] + query = { + "q": equipment[0]['title'], +} + + response=requests.get("https://rapidapi.p.rapidapi.com/api/v1/search/" + urllib.parse.urlencode(query), headers=headers) + mapped=[{"description": j["description"],"link": j["link"], "title":j["title"]} for j in response.json()["results"]] + return jsonify(mapped), 200 +@app.route('/api/v1.0/equipments/', methods=['GET']) +def getEquipment(equipmentId): + equipment = [equipment for equipment in equipments2 if equipment['equipmentId'] == equipmentId] + if len(equipment) == 0: + abort(404) + return jsonify({'equipments': equipment[0]}) + +@app.route('/api/v1.0/equipments', methods=['POST']) +def create_equipment_post(): + # Creates the equipment post + if len(equipmentPost) != 0: + new_equipment = { + "postId": equipmentPost[-1]['postId'] + 1, + "ownerId": request.json['ownerId'], + "content": request.json['content'], + "title": request.json['title'], + "creationDate": request.json["creationDate"], + "lastUpdateDate": request.json["lastUpdateDate"], + "numberOfClicks": request.json['numberOfClicks'], + "location": request.json["location"], + "equipmentType": request.json["equipmentType"], + "websiteName": request.json["websiteName"], + "link": request.json["link"] + } + else: + new_equipment = { + "postId": 1, + "ownerId": request.json['ownerId'], + "content": request.json['content'], + "title": request.json['title'], + "creationDate": request.json["creationDate"], + "lastUpdateDate": request.json["lastUpdateDate"], + "numberOfClicks": request.json['numberOfClicks'], + "location": request.json["location"], + "equipmentType": request.json["equipmentType"], + "websiteName": request.json["websiteName"], + "link": request.json["link"] + } + equipmentPost.append(new_equipment) + return jsonify({"equipment": new_equipment}), 201 + +@app.route('/api/v1.0/search-equipment-type/', methods=['GET']) +def search_equipments_by_type(equipmentType): + equipment = [equipment for equipment in equipments2 if equipment['equipmentType'] == equipmentType] + if len(equipment) == 0: + abort(404) + return jsonify(equipment), 200 + + +@app.route('/api/v1.0/search-equipment-location/', methods=['GET']) +def search_equipments_by_location(location): + equipment = [equipment for equipment in equipments2 if equipment['location'] == location] + if len(equipment) == 0: + abort(404) + return jsonify(equipment), 200 + +if __name__ == '__main__': + app.run(debug=True) diff --git a/practice-app/app/event.py b/practice-app/app/event.py new file mode 100644 index 00000000..4223fe1d --- /dev/null +++ b/practice-app/app/event.py @@ -0,0 +1,214 @@ +import requests +from flask import Flask, jsonify, abort, request +import urllib +from datetime import datetime, timedelta +from math import cos, asin, sqrt, pi + +app = Flask(__name__) +API_KEY = "Google API Key" + +events = [ + { + "eventId": 1, + "owner": "emre_gundogu", + "title": "Tennis Game for Everyone", + "content": "People who are looking for a tennis court can apply this event. Our court is for you if you are seeking for a clean and well-lit court.", + "location": "Etiler Tennis Club", + "coordinates": (41.0869173, 29.0321301), + "date": "01.05.2021", + "hours": "15.00", + "sport": "Tennis", + "ageGroup": "Any age", + "skillLevel": "Any level", + "playerCapacity": "2", + "spectatorCapacity": "8", + "spectators": [{"username":"zulfikar_tunc"}], + "players": [{"username":"zulfikar_tunc"}] + } +] + +users = [ + { + "userId": 1, + "nickname": "emre_gundogu", + "first_name": "Emre", + "last_name": "Gundogu", + "biography": "Hello, I am a 28 year-old football fan", + "birth_year": "28", + "avatar": "url_to_image", + "location": "Istanbul", + "fav_sports": ["football", "basketball"], + "badges": ["good_player", "serious"], + "privacy": "public", + } +] + +equipmentPost = [ + { + "postId": 1, + "ownerId": 1, + "content": "A nice ball", + "title": "Well-conditioned ball", + "creationDate": "29.05.2021", + "lastUpdateDate": "29.05.2021", + "numberOfClicks": 1, + "location": "İstanbul", + "equipmentType": "Ball", + "websiteName": "ismycomputeron", + "link": "www.ismycomputeron.com" + } +] +equipments2 = [ + { + "equipmentId": 1, + "ownerId": 1, + "title" : "Tennis shoes for sale!", + "content" : "I have a pair of shoes in good condition that i want to sell.", + "website name" : "letgo", + "link" : "letgo.com/245323", + "equipmentType": "shoes", + "location": "Istanbul", + "sportType": "Tennis" + + }, + { + "equipmentId": 2, + "ownerId": 1, + "title" : "Tennis rackets for sale!", + "content" : "I have a pair of shoes in good condition that i want to sell.", + "website name" : "letgo", + "link" : "letgo.com/245323", + "equipmentType": "racket", + "location": "Ankara", + "sportType": "Tennis" + } +] +headers = { + "x-rapidapi-key": "c4ab16012amsh73b5a257264eb3dp11ade4jsnb69ec0b79098", + "x-rapidapi-host" :"google-search3.p.rapidapi.com" +} + +@app.route('/api/v1.0/events/', methods=['GET']) +def get_event(event_id): + try: + event = list(filter(lambda x: x['eventId'] == event_id, events))[0] + except IndexError: + abort(404) + covid_risk = False + + # assume event owners create event only in the country of their registration location + user_location = list(filter(lambda x: x['nickname'] == event['owner'], users))[0]['location'] + resp = requests.get('http://api.geonames.org/searchJSON', {'q': user_location, 'username': 'practice_app'}) + data = resp.json() + + if len(data['geonames']) > 0: + # get country name from location via geonames API + country = '-'.join(data['geonames'][0]['countryName'].split()).lower() + # set dates to fetch coronavirus cases + today = datetime.today() + to_date = str(today) + from_date = today - timedelta(days=3) + + resp = requests.get(f'https://api.covid19api.com/country/{country}/status/confirmed/live', + {'from': from_date, 'to_date': to_date}) + + covid_data = resp.json() + # if cases are increasing for 3 days in a row, set risk status true + if covid_data[-1]['Cases'] > covid_data[-2]['Cases'] > covid_data[-3]['Cases']: + covid_risk = True + + return jsonify({'events': event, + 'covid_risk_status': covid_risk, + 'current_cases': covid_data[-1]['Cases']}) + +@app.route('/api/v1.0/sportTypes', methods=['GET']) +def get_sport_types(): + try: + response = requests.get("https://sports.api.decathlon.com/sports") + mapped = [{"name": j["attributes"]["name"], "description": j["attributes"]["description"], "icon": j["attributes"]["icon"]} for j in response.json()["data"] if j["attributes"]["decathlon_id"]!=None and j["attributes"]["parent_id"]==None] + return jsonify(mapped), 200 + except: + abort(500) + +@app.route('/api/v1.0/weather////', methods=['GET']) +def get_weather(city, year, month, day): + try: + response = requests.get("https://www.metaweather.com/api/location/search/?query=" + city) + id = response.json()[0]["woeid"] + result = requests.get("https://www.metaweather.com/api/location/" + str(id) + "/" + str(year) + "/" + str(month) + "/" + str(day)) + mapped = {key: result.json()[0][key] for key in ["humidity", "max_temp", "min_temp", "the_temp", "weather_state_name", "wind_speed"]} + return jsonify(mapped) + + except: + abort(500) + +def haversineDistance(lat1, lon1, lat2, lon2): + ## Calculates the Haversine Distance between two locations. + ## Available here:https://stackoverflow.com/questions/27928/calculate-distance-between-two-latitude-longitude-points-haversine-formula + p = pi/180 + a = 0.5 - cos((lat2-lat1)*p)/2 + cos(lat1*p) * cos(lat2*p) * (1-cos((lon2-lon1)*p))/2 + return 12742 * asin(sqrt(a)) + +@app.route('/api/v1.0/events', methods=['GET']) +def getNearbyEvents(): + useIP = request.args.get('ip') + address = request.args.get('address')##check, 400 + radius = request.args.get('radius') + eventType = request.args.get('sport') + ageRange = request.args.get('ageGroup') + skillLevel = request.args.get('skillLevel') + filterEmpty = request.args.get('empty') + filteredEvents = events + for argument in request.args: + print(argument) + if argument == 'address' or argument == 'radius' or argument =='ip': + continue + elif argument == "empty": + if request.args["empty"]=="true": + filteredEvents = list(filter(lambda event: len(event["players"])/players', methods=['GET']) +def get_players(event_id): + event = [event for event in events if event['eventId']==event_id] + if len(event) == 0: + abort(404) + return jsonify({'evetns': event[0]["events"]}) + +@app.route('/api/v1.0/events//players', methods=['POST']) +def apply_as_player(event_id): + body = request.json + user_id = body["userId"] + event = [event for event in events if event["eventId"] == event_id] + user = [user for user in users if user["userId"] == user_id] + if len(event) == 0: + abort(404) + if len(user) == 0: + response = requests.get("https://randomapi.com/api/9fekfc0v?key=2UX0-XIT1-7DYM-WDBC") + json_data = response.json()["results"] + new_user = {"userId": user_id, + "nickname": json_data[0]["nickname"], + "first_name": json_data[0]["firstName"], + "last_name": json_data[0]["lastName"], + "biography": json_data[0]["biography"], + "birth_year": json_data[0]["birth_year"], + "avatar": json_data[0]["avatar"], + "location": json_data[0]["location"], + "fav_sports": json_data[0]["favSports"], + "badges": json_data[0]["badges"], + "privacy": json_data[0]["privacy"]} + users.append(new_user) + user.append(new_user) + + event[0]["players"].append(user[0]["nickname"]) + return jsonify({"eventId": event_id, + "eventTitle": event[0]["title"], + "applicantId": user_id, + "applicantNickname": user[0]["nickname"], + "applicationServerTime": datetime.now().strftime("%d/%m/%Y %H:%M:%S")}), 201 + +if __name__ == '__main__': + app.run(debug=True) diff --git a/practice-app/app/spectator.py b/practice-app/app/spectator.py new file mode 100644 index 00000000..2107fdcf --- /dev/null +++ b/practice-app/app/spectator.py @@ -0,0 +1,108 @@ +import requests +from flask import Flask, jsonify, abort, request +import urllib +from datetime import datetime, timedelta +from math import cos, asin, sqrt, pi + +app = Flask(__name__) +API_KEY = "Google API Key" + +events = [ + { + "eventId": 1, + "owner": "emre_gundogu", + "title": "Tennis Game for Everyone", + "content": "People who are looking for a tennis court can apply this event. Our court is for you if you are seeking for a clean and well-lit court.", + "location": "Etiler Tennis Club", + "coordinates": (41.0869173, 29.0321301), + "date": "01.05.2021", + "hours": "15.00", + "sport": "Tennis", + "ageGroup": "Any age", + "skillLevel": "Any level", + "playerCapacity": "2", + "spectatorCapacity": "8", + "spectators": [{"username":"zulfikar_tunc"}], + "players": [{"username":"zulfikar_tunc"}] + } +] + +users = [ + { + "userId": 1, + "nickname": "emre_gundogu", + "first_name": "Emre", + "last_name": "Gundogu", + "biography": "Hello, I am a 28 year-old football fan", + "birth_year": "28", + "avatar": "url_to_image", + "location": "Istanbul", + "fav_sports": ["football", "basketball"], + "badges": ["good_player", "serious"], + "privacy": "public", + } +] + +equipmentPost = [ + { + "postId": 1, + "ownerId": 1, + "content": "A nice ball", + "title": "Well-conditioned ball", + "creationDate": "29.05.2021", + "lastUpdateDate": "29.05.2021", + "numberOfClicks": 1, + "location": "İstanbul", + "equipmentType": "Ball", + "websiteName": "ismycomputeron", + "link": "www.ismycomputeron.com" + } +] +equipments2 = [ + { + "equipmentId": 1, + "ownerId": 1, + "title" : "Tennis shoes for sale!", + "content" : "I have a pair of shoes in good condition that i want to sell.", + "website name" : "letgo", + "link" : "letgo.com/245323", + "equipmentType": "shoes", + "location": "Istanbul", + "sportType": "Tennis" + + }, + { + "equipmentId": 2, + "ownerId": 1, + "title" : "Tennis rackets for sale!", + "content" : "I have a pair of shoes in good condition that i want to sell.", + "website name" : "letgo", + "link" : "letgo.com/245323", + "equipmentType": "racket", + "location": "Ankara", + "sportType": "Tennis" + } +] +headers = { + "x-rapidapi-key": "c4ab16012amsh73b5a257264eb3dp11ade4jsnb69ec0b79098", + "x-rapidapi-host" :"google-search3.p.rapidapi.com" +} +@app.route('/api/v1.0/spectators/', methods=['GET']) +def get_spectators(event_id): + event = [event for event in events if event['eventId'] == event_id] + if len(event) == 0: + abort(404) + return jsonify({'spectators': event[0]["spectators"]}) + +@app.route('/api/v1.0/events//spectators', methods=['POST']) +def postSpectator(event_id): + event = [event for event in events if event['eventId'] == event_id] + if len(event) == 0: + abort(404) + r=requests.get("https://pipl.ir/v1/getPerson").json() + randomname=r['person']['personal']['name']+'_'+r['person']['personal']['last_name'] + event[0]["spectators"].append({"username":randomname}) + return jsonify({'spectators': event[0]["spectators"]}),201 + +if __name__ == '__main__': + app.run(debug=True) diff --git a/practice-app/app/user.py b/practice-app/app/user.py new file mode 100644 index 00000000..7f44285c --- /dev/null +++ b/practice-app/app/user.py @@ -0,0 +1,92 @@ +import requests +from flask import Flask, jsonify, abort, request +import urllib +from datetime import datetime, timedelta +from math import cos, asin, sqrt, pi + +app = Flask(__name__) +API_KEY = "Google API Key" + +events = [ + { + "eventId": 1, + "owner": "emre_gundogu", + "title": "Tennis Game for Everyone", + "content": "People who are looking for a tennis court can apply this event. Our court is for you if you are seeking for a clean and well-lit court.", + "location": "Etiler Tennis Club", + "coordinates": (41.0869173, 29.0321301), + "date": "01.05.2021", + "hours": "15.00", + "sport": "Tennis", + "ageGroup": "Any age", + "skillLevel": "Any level", + "playerCapacity": "2", + "spectatorCapacity": "8", + "spectators": [{"username":"zulfikar_tunc"}], + "players": [{"username":"zulfikar_tunc"}] + } +] + +users = [ + { + "userId": 1, + "nickname": "emre_gundogu", + "first_name": "Emre", + "last_name": "Gundogu", + "biography": "Hello, I am a 28 year-old football fan", + "birth_year": "28", + "avatar": "url_to_image", + "location": "Istanbul", + "fav_sports": ["football", "basketball"], + "badges": ["good_player", "serious"], + "privacy": "public", + } +] + +equipmentPost = [ + { + "postId": 1, + "ownerId": 1, + "content": "A nice ball", + "title": "Well-conditioned ball", + "creationDate": "29.05.2021", + "lastUpdateDate": "29.05.2021", + "numberOfClicks": 1, + "location": "İstanbul", + "equipmentType": "Ball", + "websiteName": "ismycomputeron", + "link": "www.ismycomputeron.com" + } +] +equipments2 = [ + { + "equipmentId": 1, + "ownerId": 1, + "title" : "Tennis shoes for sale!", + "content" : "I have a pair of shoes in good condition that i want to sell.", + "website name" : "letgo", + "link" : "letgo.com/245323", + "equipmentType": "shoes", + "location": "Istanbul", + "sportType": "Tennis" + + }, + { + "equipmentId": 2, + "ownerId": 1, + "title" : "Tennis rackets for sale!", + "content" : "I have a pair of shoes in good condition that i want to sell.", + "website name" : "letgo", + "link" : "letgo.com/245323", + "equipmentType": "racket", + "location": "Ankara", + "sportType": "Tennis" + } +] +headers = { + "x-rapidapi-key": "c4ab16012amsh73b5a257264eb3dp11ade4jsnb69ec0b79098", + "x-rapidapi-host" :"google-search3.p.rapidapi.com" +} + +if __name__ == '__main__': + app.run(debug=True) From 01ea292f59f9e476b7c20f2a3a81588bd190ee3b Mon Sep 17 00:00:00 2001 From: berkaydoner Date: Sun, 6 Jun 2021 00:06:28 +0300 Subject: [PATCH 026/179] added haversine distance formula as a postgresql function --- practice-app/app/dbinit.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/practice-app/app/dbinit.py b/practice-app/app/dbinit.py index 77fd5834..04251252 100644 --- a/practice-app/app/dbinit.py +++ b/practice-app/app/dbinit.py @@ -56,4 +56,20 @@ class eventpost(post): Session = sessionmaker(db) session = Session() -base.metadata.create_all(db) \ No newline at end of file +base.metadata.create_all(db) +### Creates Haversine distance formula in Postgresql, combines two sources: +# https://gist.github.com/carlzulauf/1724506, +# https://stackoverflow.com/questions/27928/calculate-distance-between-two-latitude-longitude-points-haversine-formula/21623206#21623206 ### +db.execute("""CREATE OR REPLACE FUNCTION public.haversineDistance(alat double precision, alng double precision, blat double precision, blng double precision) + RETURNS double precision AS + $BODY$ + SELECT asin( + sqrt(0.5- + cos(radians($3-$1))/2 + + (1-cos(radians($4-$2)))/2 * + cos(radians($1)) * + cos(radians($3)) + )) * 12742 AS distance; + $BODY$ + LANGUAGE sql IMMUTABLE + COST 100;""") \ No newline at end of file From 9cfb6241cfaa304dd2ea85b38a50be1d96f7cfeb Mon Sep 17 00:00:00 2001 From: berkaydoner Date: Sun, 6 Jun 2021 00:07:40 +0300 Subject: [PATCH 027/179] Changed filter methods to database queries. Added new filters: datetime, title content and age group. Also added sorting functionality. --- practice-app/app/event.py | 100 +++++++++++++++++++++++++++++--------- 1 file changed, 76 insertions(+), 24 deletions(-) diff --git a/practice-app/app/event.py b/practice-app/app/event.py index 4223fe1d..3312288f 100644 --- a/practice-app/app/event.py +++ b/practice-app/app/event.py @@ -1,12 +1,25 @@ import requests -from flask import Flask, jsonify, abort, request +from flask import Flask, jsonify, abort, request, make_response import urllib from datetime import datetime, timedelta +from sqlalchemy import create_engine +import re +from sqlalchemy.orm import sessionmaker +from sqlalchemy.ext.declarative import declared_attr +from sqlalchemy.sql.functions import func +from sqlalchemy import or_, and_ +from datetime import datetime, time, date from math import cos, asin, sqrt, pi +from dbinit import eventpost app = Flask(__name__) API_KEY = "Google API Key" +db = create_engine('postgresql://practice_user:-#My6o0dPa33W0rd#-@localhost:5432/practiceapp_db') + +Session = sessionmaker(db) +session = Session() + events = [ { "eventId": 1, @@ -142,47 +155,86 @@ def get_weather(city, year, month, day): except: abort(500) -def haversineDistance(lat1, lon1, lat2, lon2): - ## Calculates the Haversine Distance between two locations. - ## Available here:https://stackoverflow.com/questions/27928/calculate-distance-between-two-latitude-longitude-points-haversine-formula - p = pi/180 - a = 0.5 - cos((lat2-lat1)*p)/2 + cos(lat1*p) * cos(lat2*p) * (1-cos((lon2-lon1)*p))/2 - return 12742 * asin(sqrt(a)) - @app.route('/api/v1.0/events', methods=['GET']) def getNearbyEvents(): - useIP = request.args.get('ip') - address = request.args.get('address')##check, 400 + useIP = request.args.get('ip') + address = request.args.get('address') radius = request.args.get('radius') - eventType = request.args.get('sport') - ageRange = request.args.get('ageGroup') - skillLevel = request.args.get('skillLevel') - filterEmpty = request.args.get('empty') - filteredEvents = events + if useIP is None or not useIP in ["true", "false"]: + return make_response(jsonify({'error': 'Either true or false must be given as the useIP parameter.'}), 400) + if radius is None or not radius.isnumeric(): + return make_response(jsonify({'error': 'A numeric value must be given as the radius parameter.'}), 400) + if useIP=="false" and address is None: + return make_response(jsonify({'error': 'Either an address should be given or the IP address must be used.'}), 400) + query = session.query(eventpost) for argument in request.args: - print(argument) if argument == 'address' or argument == 'radius' or argument =='ip': continue elif argument == "empty": + if not request.args["empty"] in ["true","false"]: + return make_response(jsonify({'error': 'Empty argument must be true or false.'}), 400) if request.args["empty"]=="true": - filteredEvents = list(filter(lambda event: len(event["players"])= func.upper(eventpost.eventAgeGroup))) + elif argument == "dateBegin": + try: + datetime_begin_object = datetime.strptime(request.args["dateBegin"],'%Y-%m-%d %H:%M:%S') + datetime_end_object = datetime.strptime(request.args["dateEnd"], '%Y-%m-%d %H:%M:%S') + except ValueError: + return make_response(jsonify({'error': 'Date and time must be in format YYYY:MM:DD HH:MM:SS'}), 400) + query = query.filter(and_(func.date(datetime_begin_object.date())<=func.date(eventpost.eventDate), func.date(datetime_end_object.date())>=func.date(eventpost.eventDate))).\ + filter(and_(datetime_begin_object.time()<=eventpost.eventHours, datetime_end_object.time()>=eventpost.eventHours)) if useIP=="false": getParams = {'address':' '.join(str(address).split()),'key':API_KEY} addressData = requests.get("https://maps.googleapis.com/maps/api/geocode/json",params=getParams).json() + if addressData["status"]!="OK": + return make_response(jsonify({'error': 'Address was not found.'}), 404) lat = addressData["results"][0]["geometry"]["location"]["lat"] lng = addressData["results"][0]["geometry"]["location"]["lng"] else: getParams = {'key':API_KEY} ipdata = requests.post("https://www.googleapis.com/geolocation/v1/geolocate",params=getParams).json() + if "error" in ipdata: + return make_response(jsonify({'error': 'IP address is not valid.'}), 404) lat = ipdata["location"]["lat"] lng = ipdata["location"]["lng"] - print(lat, lng) - nearbyEvents = [event for event in filteredEvents if - haversineDistance(lat,lng,event["coordinates"][0], event["coordinates"][1])<=float(radius)] - return jsonify(nearbyEvents) + + eventList = [] + nearbyEvents = query.filter(func.haversineDistance(lat,lng,eventpost.eventLatitude,eventpost.eventLongitude)<=radius) + if not request.args.get("orderby") is None: + if not request.args["orderby"] in eventpost.__table__.columns.keys(): + return make_response(jsonify({'error': 'Order criterion is not a valid column name.'}), 400) + if not request.args.get("order") is None: + if not request.args["order"] in ["asc","desc"]: + return make_response(jsonify({'error': 'Order direction must be either asc or desc'}), 400) + if request.args["order"]=="asc": + nearbyEvents = nearbyEvents.order_by(getattr(eventpost,request.args["orderby"]).asc()) + else: + nearbyEvents = nearbyEvents.order_by(getattr(eventpost,request.args["orderby"]).desc()) + else: + nearbyEvents = nearbyEvents.order_by(getattr(eventpost,request.args["orderby"]).asc()) + nearbyEvents = nearbyEvents.all() + for i in nearbyEvents: + eventList.append({c.name: str(getattr(i, c.name)) for c in i.__table__.columns}) + return jsonify(eventList), 200 @app.route('api/v1.0/events', methods=['POST']) def create_event_post(): From b09d2cb2975c193737384e5a7e78b8d40e60a145 Mon Sep 17 00:00:00 2001 From: ahmetnecipg <56501804+ahmetnecipg@users.noreply.github.com> Date: Sun, 6 Jun 2021 00:56:40 +0300 Subject: [PATCH 028/179] Notification table added I added the notification database table by taking my teammates work reference --- practice-app/app/dbinit.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/practice-app/app/dbinit.py b/practice-app/app/dbinit.py index 77fd5834..f18bda82 100644 --- a/practice-app/app/dbinit.py +++ b/practice-app/app/dbinit.py @@ -52,8 +52,16 @@ class eventpost(post): eventSkillLevel = Column(ENUM('Beginner', 'Preintermediate', 'Intermediate','Advanced','Expert', name='skill')) eventLatitude = Column(Float) eventLongitude = Column(Float) - + +class notification(base): + __tablename__ = "notification" + ID = Column(Integer, primary_key=True) + date = Column(Date,nullable=False) + description = Column(String,nullable=False) + isRead = Column(Boolean,nullable=False) + recipientId = Column(Integer,nullable=False) + Session = sessionmaker(db) session = Session() -base.metadata.create_all(db) \ No newline at end of file +base.metadata.create_all(db) From 4e5787913a740dff7f01ff2e785ab251abd32d54 Mon Sep 17 00:00:00 2001 From: Bengisu Ozaydin Date: Sun, 6 Jun 2021 12:25:39 +0300 Subject: [PATCH 029/179] Refs #49 - Implemented equipment pages. --- practice-app/web/src/App.js | 7 + .../web/src/components/EquipmentRow.js | 19 +++ .../src/components/FilterEquipmentModal.js | 88 +++++++++++++ .../web/src/screens/CreateEquipment.js | 61 +++++++++ practice-app/web/src/screens/EquipmentPage.js | 11 ++ practice-app/web/src/screens/Equipments.js | 120 ++++++++++++++++++ 6 files changed, 306 insertions(+) create mode 100644 practice-app/web/src/components/EquipmentRow.js create mode 100644 practice-app/web/src/components/FilterEquipmentModal.js create mode 100644 practice-app/web/src/screens/CreateEquipment.js create mode 100644 practice-app/web/src/screens/EquipmentPage.js create mode 100644 practice-app/web/src/screens/Equipments.js diff --git a/practice-app/web/src/App.js b/practice-app/web/src/App.js index 70831f34..8f471d89 100644 --- a/practice-app/web/src/App.js +++ b/practice-app/web/src/App.js @@ -1,6 +1,8 @@ import React, {useEffect, useState} from 'react' import Events from "./screens/Events"; import EventPage from "./screens/EventPage"; +import Equipments from "./screens/Equipments"; +import EquipmentPage from "./screens/EquipmentPage"; import { Route, Switch, @@ -16,6 +18,7 @@ import SportsIcon from '@material-ui/icons/Sports'; import ShoppingCartIcon from '@material-ui/icons/ShoppingCart'; import MenuIcon from '@material-ui/icons/Menu'; import CreateEvent from "./screens/CreateEvent"; +import CreateEquipment from "./screens/CreateEquipment"; const drawerWidth = 240; @@ -116,6 +119,10 @@ function App() { + } + + + diff --git a/practice-app/web/src/components/EquipmentRow.js b/practice-app/web/src/components/EquipmentRow.js new file mode 100644 index 00000000..23ddbb47 --- /dev/null +++ b/practice-app/web/src/components/EquipmentRow.js @@ -0,0 +1,19 @@ +import React from 'react' +import TableCell from "@material-ui/core/TableCell"; +import TableRow from "@material-ui/core/TableRow"; + +export default function EquipmentRow(equipment){ + return( + + + + {equipment.equipmentType} + + {equipment.content} + {equipment.location} + {equipment.websiteName} + {equipment.link} + + + ) +} diff --git a/practice-app/web/src/components/FilterEquipmentModal.js b/practice-app/web/src/components/FilterEquipmentModal.js new file mode 100644 index 00000000..808cb48c --- /dev/null +++ b/practice-app/web/src/components/FilterEquipmentModal.js @@ -0,0 +1,88 @@ +import React, {useState} from 'react' +import Dialog from '@material-ui/core/Dialog'; +import DialogActions from '@material-ui/core/DialogActions'; +import DialogContent from '@material-ui/core/DialogContent'; +import DialogContentText from '@material-ui/core/DialogContentText'; +import DialogTitle from '@material-ui/core/DialogTitle'; +import TextField from "@material-ui/core/TextField"; +import Button from "@material-ui/core/Button"; +import LocationPicker from "react-leaflet-location-picker"; + +const fields = [ + "Type", + "Website Name", + "Link" +] + +export default function FilterEquipmentModal(props){ + const [filter, setFilter] = useState({}) + + const pointMode = { + banner: false, + control: { + values: filter["Location"]?(filter["Location"].split(",").length>1?[filter["Location"].split(",")]:[]):[], + onClick: point =>setLocation(point), + onRemove: point =>setLocation(undefined) + } + }; + const sendFilter = _=>{ + props.setFilter(filter) + props.handleClose() + } + console.log(pointMode) + const handleChange = e=>{ + const id = e.target.id + const value = e.target.value + const filters = {...filter} + if(value === "")filters[""+id] = undefined + else filters[""+id] = value + setFilter(filters) + } + const setLocation = l=>{ + const filters = {...filter} + filters["Location"] = l[0] + "," + l[1] + setFilter(filters) + } + return ( + + + Choose Filters + + + You can choose filters to search equipments. + + + { + fields.map(field=>( + + )) + } + + + + + + + + ) +} diff --git a/practice-app/web/src/screens/CreateEquipment.js b/practice-app/web/src/screens/CreateEquipment.js new file mode 100644 index 00000000..51b4131f --- /dev/null +++ b/practice-app/web/src/screens/CreateEquipment.js @@ -0,0 +1,61 @@ +import React, {useEffect, useState} from 'react' +import Container from "@material-ui/core/Container"; +import SearchIcon from '@material-ui/icons/Search'; +import FilterListIcon from '@material-ui/icons/FilterList'; +import EventRow from '../components/EventRow' +import Table from '@material-ui/core/Table'; +import TableBody from '@material-ui/core/TableBody'; +import TableCell from '@material-ui/core/TableCell'; +import TableContainer from '@material-ui/core/TableContainer'; +import TableHead from '@material-ui/core/TableHead'; +import TableRow from '@material-ui/core/TableRow'; +import Paper from '@material-ui/core/Paper'; +import Grid from '@material-ui/core/Grid'; +import Button from '@material-ui/core/Button'; +import {useHistory} from "react-router-dom"; +import FilterEventModal from "../components/FilterEventModal"; +import TextField from "@material-ui/core/TextField"; + +const equipments = [ + { + "postId": 1, + "ownerId": 1, + "content": "A nice ball", + "title": "Well-conditioned ball", + "creationDate": "29.05.2021", + "lastUpdateDate": "29.05.2021", + "numberOfClicks": 1, + "location": "İstanbul", + "equipmentType": "Ball", + "websiteName": "ismycomputeron", + "link": "www.ismycomputeron.com" + } +] + +const fields = [ + "Type", + "Website Name", + "Link" +] + +export default function CreateEquipment() { + return ( + + + { + fields.map(field=>( + + )) + } + + + ); +} diff --git a/practice-app/web/src/screens/EquipmentPage.js b/practice-app/web/src/screens/EquipmentPage.js new file mode 100644 index 00000000..b038b30d --- /dev/null +++ b/practice-app/web/src/screens/EquipmentPage.js @@ -0,0 +1,11 @@ +import React from 'react' +import {useParams} from 'react-router-dom' + +export default function Equipment(props){ + let {id} = useParams() + return( + + + + ) +} diff --git a/practice-app/web/src/screens/Equipments.js b/practice-app/web/src/screens/Equipments.js new file mode 100644 index 00000000..e4599848 --- /dev/null +++ b/practice-app/web/src/screens/Equipments.js @@ -0,0 +1,120 @@ +import React, {useEffect, useState} from 'react' +import Container from "@material-ui/core/Container"; +import {InputAdornment, makeStyles, TextField} from "@material-ui/core"; +import SearchIcon from '@material-ui/icons/Search'; +import FilterListIcon from '@material-ui/icons/FilterList'; +import EquipmentRow from '../components/EquipmentRow' +import Table from '@material-ui/core/Table'; +import TableBody from '@material-ui/core/TableBody'; +import TableCell from '@material-ui/core/TableCell'; +import TableContainer from '@material-ui/core/TableContainer'; +import TableHead from '@material-ui/core/TableHead'; +import TableRow from '@material-ui/core/TableRow'; +import Paper from '@material-ui/core/Paper'; +import Grid from '@material-ui/core/Grid'; +import Button from '@material-ui/core/Button'; +import {useHistory} from "react-router-dom"; +import FilterEquipmentModal from "../components/FilterEquipmentModal"; + +const equipments = [ + { + "postId": 1, + "ownerId": 1, + "content": "A nice ball", + "title": "Well-conditioned ball", + "creationDate": "29.05.2021", + "lastUpdateDate": "29.05.2021", + "numberOfClicks": 1, + "location": "İstanbul", + "equipmentType": "Ball", + "websiteName": "ismycomputeron", + "link": "www.ismycomputeron.com" + } +] + +const useStyles = makeStyles({ + table: { + minWidth: 650, + }, +}); + +export default function EquipmentScreen() { + const [open, setOpen] = useState(false); + const [filter, setFilter] = useState({}); + const handleClose = () => { + setOpen(false); + }; + const [text, setText] = useState("") + const classes = useStyles(); + const history = useHistory() + const [width, setWidth] = useState(window.innerWidth); + const handleWindowSizeChange = () => { + setWidth(window.innerWidth); + } + useEffect(() => { + window.addEventListener('resize', handleWindowSizeChange); + return () => { + window.removeEventListener('resize', handleWindowSizeChange); + } + }, []); + + return ( + + + + 600?10:9}> + setText(e.target.value)} + InputProps={{ + startAdornment:( + + + + ) + }} + /> + + + + + + + + + + Type + Content + Location + Website Name + Link + + + {equipments.map(equipment => ( + history.push("/equipment/"+equipment.postId)} + key={equipment.title} + {...equipment} + /> + ))} + +
+
+
+ +
+ ); +} From 1f49b35b9451763c01d8e4a074940180a1845074 Mon Sep 17 00:00:00 2001 From: Bengisu Ozaydin Date: Sun, 6 Jun 2021 13:32:12 +0300 Subject: [PATCH 030/179] Refs #49 - Small changes and fixes to equipments page. --- practice-app/app/app.py | 3 ++- practice-app/web/src/App.js | 1 - practice-app/web/src/components/EquipmentRow.js | 2 +- .../web/src/components/FilterEquipmentModal.js | 13 +++++++++++++ practice-app/web/src/screens/Equipments.js | 2 +- 5 files changed, 17 insertions(+), 4 deletions(-) diff --git a/practice-app/app/app.py b/practice-app/app/app.py index bc916eeb..f78b8db1 100644 --- a/practice-app/app/app.py +++ b/practice-app/app/app.py @@ -58,6 +58,7 @@ "link": "www.ismycomputeron.com" } ] + equipments2 = [ { "equipmentId": 1, @@ -69,7 +70,6 @@ "equipmentType": "shoes", "location": "Istanbul", "sportType": "Tennis" - }, { "equipmentId": 2, @@ -83,6 +83,7 @@ "sportType": "Tennis" } ] + headers = { "x-rapidapi-key": "c4ab16012amsh73b5a257264eb3dp11ade4jsnb69ec0b79098", "x-rapidapi-host" :"google-search3.p.rapidapi.com" diff --git a/practice-app/web/src/App.js b/practice-app/web/src/App.js index 8f471d89..53e0ec46 100644 --- a/practice-app/web/src/App.js +++ b/practice-app/web/src/App.js @@ -119,7 +119,6 @@ function App() { - } diff --git a/practice-app/web/src/components/EquipmentRow.js b/practice-app/web/src/components/EquipmentRow.js index 23ddbb47..00a017ea 100644 --- a/practice-app/web/src/components/EquipmentRow.js +++ b/practice-app/web/src/components/EquipmentRow.js @@ -9,7 +9,7 @@ export default function EquipmentRow(equipment){ {equipment.equipmentType} - {equipment.content} + {equipment.title} {equipment.location} {equipment.websiteName} {equipment.link} diff --git a/practice-app/web/src/components/FilterEquipmentModal.js b/practice-app/web/src/components/FilterEquipmentModal.js index 808cb48c..577059a5 100644 --- a/practice-app/web/src/components/FilterEquipmentModal.js +++ b/practice-app/web/src/components/FilterEquipmentModal.js @@ -73,6 +73,17 @@ export default function FilterEquipmentModal(props){ /> )) } +