Add api documentation with flasger

This commit is contained in:
Peter Stockings
2022-07-19 19:55:11 +10:00
parent 07f19b38c6
commit 6e1f164ba9
5 changed files with 204 additions and 17 deletions

166
app.py
View File

@@ -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 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__)
swagger = Swagger(app, template=template)
DATABASE = 'workout.db'
@@ -25,11 +47,35 @@ def query_db(query, args=(), one=False):
@app.route("/")
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')
@app.route("/person/<int: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_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)
@app.route("/person/<int:person_id>/new_workout")
@app.route("/person/<int:person_id>/workout", methods=['POST'])
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_id], one=True)
@@ -98,6 +159,24 @@ def new_workout_for_person(person_id):
@app.route("/person/<int:person_id>/workout/<int: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("""
SELECT
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'])
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("""
SELECT
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'])
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("""
SELECT
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 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'])
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("""
SELECT
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'])
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("""
SELECT
P.Name,

View File

@@ -36,10 +36,25 @@
</a>
</div>
<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"
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"
fill="currentColor" aria-hidden="true">
class="sr-only">Workout Tracker on GitHub</span><svg viewBox="0 0 16 16" class="w-6 h-6"
fill="black" aria-hidden="true">
<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">
</path>

View File

@@ -9,7 +9,8 @@
<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>
</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
</a>
</div>

View File

@@ -9,9 +9,13 @@
<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>
</div>
<a href="#" class="text-sm font-medium text-cyan-600 hover:bg-gray-100 rounded-lg inline-flex items-center p-2">
Delete workout
</a>
<form action="{{ url_for('delete_workout_from_person', person_id=person_id, workout_id=workout_id) }}"
method="delete">
<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>

View File

@@ -54,20 +54,27 @@
class="text-sm font-medium text-cyan-600 hover:bg-gray-100 rounded-lg inline-flex items-center p-2">
Edit
</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">
Delete
</a>
<form
action="{{ url_for('delete_workout_from_person', person_id=person_id, workout_id=w['workout_id']) }}"
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>
</tr>
{% endfor %}
</tbody>
</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">
New workout
</a>
<form action="{{ url_for('new_workout_for_person', person_id=person_id) }}" method="post">
<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">New
workout</button>
</form>
</div>
</div>
</div>