Add api documentation with flasger
This commit is contained in:
166
app.py
166
app.py
@@ -1,8 +1,30 @@
|
|||||||
from flask import Flask, render_template, g, redirect, request, url_for
|
from flask import Flask, jsonify, render_template, g, redirect, request, url_for
|
||||||
|
from flasgger import Swagger
|
||||||
import sqlite3
|
import sqlite3
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
|
template = {
|
||||||
|
"swagger": "2.0",
|
||||||
|
"info": {
|
||||||
|
"title": "WorkoutTracker API",
|
||||||
|
"description": "API for tracking topsets of workouts",
|
||||||
|
"contact": {
|
||||||
|
"responsibleOrganization": "ME",
|
||||||
|
"responsibleDeveloper": "Me",
|
||||||
|
"email": "me@me.com",
|
||||||
|
"url": "www.me.com",
|
||||||
|
},
|
||||||
|
"version": "0.0.1"
|
||||||
|
},
|
||||||
|
"schemes": [
|
||||||
|
"http",
|
||||||
|
"https"
|
||||||
|
],
|
||||||
|
"operationId": "getmyData"
|
||||||
|
}
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
swagger = Swagger(app, template=template)
|
||||||
|
|
||||||
DATABASE = 'workout.db'
|
DATABASE = 'workout.db'
|
||||||
|
|
||||||
@@ -25,11 +47,35 @@ def query_db(query, args=(), one=False):
|
|||||||
|
|
||||||
@app.route("/")
|
@app.route("/")
|
||||||
def dashboard():
|
def dashboard():
|
||||||
|
"""Dashboard page
|
||||||
|
Displays stats and a list of all people and there rep maxes for each exercise
|
||||||
|
---
|
||||||
|
tags:
|
||||||
|
- Dashboard
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: A list of all people and there rep maxes for each exercise
|
||||||
|
"""
|
||||||
return render_template('index.html')
|
return render_template('index.html')
|
||||||
|
|
||||||
|
|
||||||
@app.route("/person/<int:person_id>")
|
@app.route("/person/<int:person_id>")
|
||||||
def display_workouts_for_person(person_id):
|
def display_workouts_for_person(person_id):
|
||||||
|
"""Display all workouts for a person
|
||||||
|
Displays stats and a list of all people and there rep maxes for each exercise
|
||||||
|
---
|
||||||
|
tags:
|
||||||
|
- Person
|
||||||
|
parameters:
|
||||||
|
- name: person_id
|
||||||
|
in: path
|
||||||
|
type: number
|
||||||
|
required: true
|
||||||
|
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: A list of all people and there rep maxes for each exercise
|
||||||
|
"""
|
||||||
person = query_db('SELECT * FROM Person WHERE PersonId=?',
|
person = query_db('SELECT * FROM Person WHERE PersonId=?',
|
||||||
[person_id], one=True)
|
[person_id], one=True)
|
||||||
|
|
||||||
@@ -77,8 +123,23 @@ def display_workouts_for_person(person_id):
|
|||||||
return render_template('workouts.html', person_id=person_id, person=person, workouts=transformed_workouts, exercises=exercises)
|
return render_template('workouts.html', person_id=person_id, person=person, workouts=transformed_workouts, exercises=exercises)
|
||||||
|
|
||||||
|
|
||||||
@app.route("/person/<int:person_id>/new_workout")
|
@app.route("/person/<int:person_id>/workout", methods=['POST'])
|
||||||
def new_workout_for_person(person_id):
|
def new_workout_for_person(person_id):
|
||||||
|
"""Create new workout
|
||||||
|
Creates a workout with current date and then redirects to newly created workout
|
||||||
|
---
|
||||||
|
tags:
|
||||||
|
- Workout
|
||||||
|
parameters:
|
||||||
|
- name: person_id
|
||||||
|
in: path
|
||||||
|
type: number
|
||||||
|
required: true
|
||||||
|
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: View of newly created workout
|
||||||
|
"""
|
||||||
person = query_db('SELECT * FROM Person WHERE PersonId=?',
|
person = query_db('SELECT * FROM Person WHERE PersonId=?',
|
||||||
[person_id], one=True)
|
[person_id], one=True)
|
||||||
|
|
||||||
@@ -98,6 +159,24 @@ def new_workout_for_person(person_id):
|
|||||||
|
|
||||||
@app.route("/person/<int:person_id>/workout/<int:workout_id>")
|
@app.route("/person/<int:person_id>/workout/<int:workout_id>")
|
||||||
def show_workout_for_person(person_id, workout_id):
|
def show_workout_for_person(person_id, workout_id):
|
||||||
|
"""Display a workout
|
||||||
|
Displays a selected workout with options to edit/delete existing and add new topsets
|
||||||
|
---
|
||||||
|
tags:
|
||||||
|
- Workout
|
||||||
|
parameters:
|
||||||
|
- name: person_id
|
||||||
|
in: path
|
||||||
|
type: number
|
||||||
|
required: true
|
||||||
|
- name: workout_id
|
||||||
|
in: path
|
||||||
|
type: number
|
||||||
|
required: true
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: A list of topsets in a selected workout
|
||||||
|
"""
|
||||||
workout_info = query_db("""
|
workout_info = query_db("""
|
||||||
SELECT
|
SELECT
|
||||||
P.Name,
|
P.Name,
|
||||||
@@ -134,6 +213,25 @@ def show_workout_for_person(person_id, workout_id):
|
|||||||
|
|
||||||
@app.route("/person/<int:person_id>/workout/<int:workout_id>/delete", methods=['GET', 'DELETE'])
|
@app.route("/person/<int:person_id>/workout/<int:workout_id>/delete", methods=['GET', 'DELETE'])
|
||||||
def delete_workout_from_person(person_id, workout_id):
|
def delete_workout_from_person(person_id, workout_id):
|
||||||
|
"""Delete workout
|
||||||
|
Deletes selected workout completed by a person
|
||||||
|
---
|
||||||
|
tags:
|
||||||
|
- Workout
|
||||||
|
parameters:
|
||||||
|
- name: person_id
|
||||||
|
in: path
|
||||||
|
type: number
|
||||||
|
required: true
|
||||||
|
- name: workout_id
|
||||||
|
in: path
|
||||||
|
type: number
|
||||||
|
required: true
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: Redirect to workouts list page for person
|
||||||
|
"""
|
||||||
|
|
||||||
workout_info = query_db("""
|
workout_info = query_db("""
|
||||||
SELECT
|
SELECT
|
||||||
P.Name,
|
P.Name,
|
||||||
@@ -158,6 +256,28 @@ def delete_workout_from_person(person_id, workout_id):
|
|||||||
|
|
||||||
@app.route("/person/<int:person_id>/workout/<int:workout_id>/topset/<int:topset_id>", methods=['GET', 'POST'])
|
@app.route("/person/<int:person_id>/workout/<int:workout_id>/topset/<int:topset_id>", methods=['GET', 'POST'])
|
||||||
def show_topset_from_workout_for_person(person_id, workout_id, topset_id):
|
def show_topset_from_workout_for_person(person_id, workout_id, topset_id):
|
||||||
|
"""Display/Create new top set
|
||||||
|
Displays stats and a list of all people and there rep maxes for each exercise
|
||||||
|
---
|
||||||
|
tags:
|
||||||
|
- Topset
|
||||||
|
parameters:
|
||||||
|
- name: person_id
|
||||||
|
in: path
|
||||||
|
type: number
|
||||||
|
required: true
|
||||||
|
- name: workout_id
|
||||||
|
in: path
|
||||||
|
type: number
|
||||||
|
required: true
|
||||||
|
- name: topset_id
|
||||||
|
in: path
|
||||||
|
type: number
|
||||||
|
required: true
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: A list of topsets in a selected workout
|
||||||
|
"""
|
||||||
topset = query_db("""
|
topset = query_db("""
|
||||||
SELECT
|
SELECT
|
||||||
P.Name,
|
P.Name,
|
||||||
@@ -190,11 +310,29 @@ def show_topset_from_workout_for_person(person_id, workout_id, topset_id):
|
|||||||
|
|
||||||
return redirect(url_for('show_workout_for_person', person_id=person_id, workout_id=workout_id))
|
return redirect(url_for('show_workout_for_person', person_id=person_id, workout_id=workout_id))
|
||||||
|
|
||||||
return render_template('topset.html', topset=topset, exercises=query_db('select * from Excercise'))
|
return render_template('topset.html', person_id=person_id, workout_id=workout_id, topset_id=topset_id, topset=topset, exercises=query_db('select * from Excercise'))
|
||||||
|
|
||||||
|
|
||||||
@app.route("/person/<int:person_id>/workout/<int:workout_id>/topset", methods=['POST'])
|
@app.route("/person/<int:person_id>/workout/<int:workout_id>/topset", methods=['POST'])
|
||||||
def add_topset_to_workout_for_person(person_id, workout_id):
|
def add_topset_to_workout_for_person(person_id, workout_id):
|
||||||
|
"""Add top set to workout
|
||||||
|
Add a topset to a workout completed by a person
|
||||||
|
---
|
||||||
|
tags:
|
||||||
|
- Topset
|
||||||
|
parameters:
|
||||||
|
- name: person_id
|
||||||
|
in: path
|
||||||
|
type: number
|
||||||
|
required: true
|
||||||
|
- name: workout_id
|
||||||
|
in: path
|
||||||
|
type: number
|
||||||
|
required: true
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: A list of topsets in a selected workout
|
||||||
|
"""
|
||||||
workout_info = query_db("""
|
workout_info = query_db("""
|
||||||
SELECT
|
SELECT
|
||||||
P.Name,
|
P.Name,
|
||||||
@@ -223,6 +361,28 @@ def add_topset_to_workout_for_person(person_id, workout_id):
|
|||||||
|
|
||||||
@app.route("/person/<int:person_id>/workout/<int:workout_id>/topset/<int:topset_id>/delete", methods=['GET', 'DELETE'])
|
@app.route("/person/<int:person_id>/workout/<int:workout_id>/topset/<int:topset_id>/delete", methods=['GET', 'DELETE'])
|
||||||
def delete_topset_from_workout_for_person(person_id, workout_id, topset_id):
|
def delete_topset_from_workout_for_person(person_id, workout_id, topset_id):
|
||||||
|
"""Delete top set
|
||||||
|
Add a topset to a workout completed by a person
|
||||||
|
---
|
||||||
|
tags:
|
||||||
|
- Topset
|
||||||
|
parameters:
|
||||||
|
- name: person_id
|
||||||
|
in: path
|
||||||
|
type: number
|
||||||
|
required: true
|
||||||
|
- name: workout_id
|
||||||
|
in: path
|
||||||
|
type: number
|
||||||
|
required: true
|
||||||
|
- name: topset_id
|
||||||
|
in: path
|
||||||
|
type: number
|
||||||
|
required: true
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: A list of topsets in a selected workout
|
||||||
|
"""
|
||||||
topset = query_db("""
|
topset = query_db("""
|
||||||
SELECT
|
SELECT
|
||||||
P.Name,
|
P.Name,
|
||||||
|
|||||||
@@ -36,10 +36,25 @@
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
|
<a href="/apidocs">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
aria-hidden="true" role="img" id="footer-icon-name" class="w-6 h-6"
|
||||||
|
preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256">
|
||||||
|
<path fill="#85EA2D"
|
||||||
|
d="M127.999 249.895c-67.215 0-121.9-54.68-121.9-121.896C6.1 60.782 60.785 6.102 128 6.102c67.214 0 121.899 54.685 121.899 121.9c0 67.214-54.685 121.893-121.9 121.893Z">
|
||||||
|
</path>
|
||||||
|
<path fill="#173647"
|
||||||
|
d="M127.999 12.202c63.954 0 115.797 51.842 115.797 115.797c0 63.952-51.843 115.797-115.797 115.797c-63.952 0-115.797-51.845-115.797-115.797S64.047 12.202 127.999 12.202m0-12.202C57.419 0 0 57.42 0 127.999s57.42 127.998 127.999 127.998S256 198.577 256 128C256 57.419 198.578 0 127.999 0Z">
|
||||||
|
</path>
|
||||||
|
<path fill="#173647"
|
||||||
|
d="M80.598 86.619c-.394 4.38.146 8.909-.146 13.338c-.345 4.431-.887 8.811-1.773 13.192c-1.23 6.25-5.12 10.976-10.482 14.914c10.436 6.793 11.616 17.324 12.304 28.006c.345 5.76.197 11.567.788 17.276c.443 4.429 2.165 5.562 6.745 5.708c1.87.048 3.786 0 5.956 0v13.683c-13.535 2.313-24.708-1.525-27.467-12.992c-.887-4.184-1.478-8.467-1.673-12.798c-.297-4.578.195-9.155-.148-13.732c-.985-12.553-2.61-16.785-14.618-17.376v-15.602a23.714 23.714 0 0 1 2.608-.443c6.596-.345 9.4-2.364 10.828-8.86c.69-3.641 1.084-7.333 1.23-11.074c.494-7.136.297-14.42 1.525-21.507C67.997 68.163 74.3 63.24 84.785 62.65c2.952-.149 5.955 0 9.35 0v13.98c-1.427.1-2.658.294-3.937.294c-8.515-.297-8.96 2.607-9.6 9.695Zm16.39 32.386h-.196c-4.923-.245-9.155 3.593-9.403 8.515c-.246 4.972 3.592 9.206 8.515 9.45h.59c4.875.296 9.056-3.447 9.352-8.319v-.491c.1-4.971-3.886-9.055-8.857-9.155Zm30.862 0c-4.774-.148-8.763 3.593-8.909 8.318c0 .297 0 .543.051.837c0 5.365 3.641 8.812 9.155 8.812c5.414 0 8.812-3.544 8.812-9.106c-.051-5.366-3.646-8.91-9.109-8.86Zm31.602 0c-5.02-.1-9.206 3.89-9.352 8.91a9.03 9.03 0 0 0 9.055 9.054h.1c4.528.788 9.106-3.592 9.402-8.858c.243-4.874-4.186-9.106-9.205-9.106Zm43.363.737c-5.711-.245-8.567-2.164-9.992-7.581a54.874 54.874 0 0 1-1.624-10.582c-.395-6.596-.346-13.241-.789-19.837c-1.033-15.651-12.352-21.114-28.794-18.41V76.92c2.607 0 4.626 0 6.645.049c3.495.048 6.153 1.379 6.496 5.268c.345 3.543.345 7.136.69 10.73c.692 7.139 1.083 14.372 2.314 21.41c1.085 5.809 5.07 10.14 10.04 13.684c-8.71 5.857-11.27 14.223-11.714 23.626c-.245 6.448-.394 12.944-.736 19.443c-.297 5.905-2.362 7.824-8.318 7.972c-1.674.05-3.298.198-5.169.297v13.93c3.495 0 6.694.196 9.892 0c9.942-.592 15.947-5.415 17.918-15.063a125.582 125.582 0 0 0 1.476-16.045c.343-4.923.297-9.894.788-14.766c.737-7.63 4.232-10.78 11.862-11.27c.739-.1 1.427-.246 2.118-.492v-15.604c-1.282-.149-2.17-.295-3.103-.346Z">
|
||||||
|
</path>
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
<a href="https://github.com/GabePope/WorkoutTracker"
|
<a href="https://github.com/GabePope/WorkoutTracker"
|
||||||
class="ml-6 block text-slate-400 hover:text-slate-500 dark:hover:text-slate-300"><span
|
class="ml-6 block text-slate-400 hover:text-slate-500 dark:hover:text-slate-300"><span
|
||||||
class="sr-only">Workout Tracker on GitHub</span><svg viewBox="0 0 16 16" class="w-5 h-5"
|
class="sr-only">Workout Tracker on GitHub</span><svg viewBox="0 0 16 16" class="w-6 h-6"
|
||||||
fill="currentColor" aria-hidden="true">
|
fill="black" aria-hidden="true">
|
||||||
<path
|
<path
|
||||||
d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z">
|
d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z">
|
||||||
</path>
|
</path>
|
||||||
|
|||||||
@@ -9,7 +9,8 @@
|
|||||||
<h3 class="text-xl font-bold text-gray-900 mb-2">{{ topset['Name'] }}</h3>
|
<h3 class="text-xl font-bold text-gray-900 mb-2">{{ topset['Name'] }}</h3>
|
||||||
<span class="text-base font-normal text-gray-500">{{ topset['StartDate'] }}</span>
|
<span class="text-base font-normal text-gray-500">{{ topset['StartDate'] }}</span>
|
||||||
</div>
|
</div>
|
||||||
<a href="#" class="text-sm font-medium text-cyan-600 hover:bg-gray-100 rounded-lg inline-flex items-center p-2">
|
<a href="{{ url_for('delete_topset_from_workout_for_person', person_id=person_id, workout_id=workout_id, topset_id=topset_id)}}"
|
||||||
|
class="text-sm font-medium text-cyan-600 hover:bg-gray-100 rounded-lg inline-flex items-center p-2">
|
||||||
Delete topset
|
Delete topset
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -9,9 +9,13 @@
|
|||||||
<h3 class="text-xl font-bold text-gray-900 mb-2">{{ workout_info['Name'] }}</h3>
|
<h3 class="text-xl font-bold text-gray-900 mb-2">{{ workout_info['Name'] }}</h3>
|
||||||
<span class="text-base font-normal text-gray-500">{{ workout_info['StartDate'] }}</span>
|
<span class="text-base font-normal text-gray-500">{{ workout_info['StartDate'] }}</span>
|
||||||
</div>
|
</div>
|
||||||
<a href="#" class="text-sm font-medium text-cyan-600 hover:bg-gray-100 rounded-lg inline-flex items-center p-2">
|
<form action="{{ url_for('delete_workout_from_person', person_id=person_id, workout_id=workout_id) }}"
|
||||||
Delete workout
|
method="delete">
|
||||||
</a>
|
<button
|
||||||
|
class="sm:inline-flex text-white bg-cyan-600 hover:bg-cyan-700 focus:ring-4 focus:ring-cyan-200 font-medium rounded-lg text-sm px-5 py-2.5 text-center items-center mt-6"
|
||||||
|
type="submit">Delete
|
||||||
|
workout</button>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -54,20 +54,27 @@
|
|||||||
class="text-sm font-medium text-cyan-600 hover:bg-gray-100 rounded-lg inline-flex items-center p-2">
|
class="text-sm font-medium text-cyan-600 hover:bg-gray-100 rounded-lg inline-flex items-center p-2">
|
||||||
Edit
|
Edit
|
||||||
</a>
|
</a>
|
||||||
<a href="{{ url_for('delete_workout_from_person', person_id=person_id, workout_id=w['workout_id'])}}"
|
|
||||||
class="text-sm font-medium text-cyan-600 hover:bg-gray-100 rounded-lg inline-flex items-center p-2">
|
<form
|
||||||
Delete
|
action="{{ url_for('delete_workout_from_person', person_id=person_id, workout_id=w['workout_id']) }}"
|
||||||
</a>
|
method="delete" class="inline">
|
||||||
|
<button
|
||||||
|
class="text-sm font-medium text-cyan-600 hover:bg-gray-100 rounded-lg inline-flex items-center p-2"
|
||||||
|
type="submit">Delete</button>
|
||||||
|
</form>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<a href=" {{ url_for('new_workout_for_person', person_id=person_id) }}"
|
|
||||||
class="sm:inline-flex text-white bg-cyan-600 hover:bg-cyan-700 focus:ring-4 focus:ring-cyan-200 font-medium rounded-lg text-sm px-5 py-2.5 text-center items-center mt-6">
|
<form action="{{ url_for('new_workout_for_person', person_id=person_id) }}" method="post">
|
||||||
New workout
|
<button
|
||||||
</a>
|
class="sm:inline-flex text-white bg-cyan-600 hover:bg-cyan-700 focus:ring-4 focus:ring-cyan-200 font-medium rounded-lg text-sm px-5 py-2.5 text-center items-center mt-6">New
|
||||||
|
workout</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user