Skip to content

Commit

Permalink
Merge pull request #252 from fcampise/main
Browse files Browse the repository at this point in the history
Track 2: Doc updates to Sprint 3, Added Sprint 4
  • Loading branch information
fcampise authored Apr 21, 2024
2 parents 17170fb + d106aa0 commit a127bc7
Show file tree
Hide file tree
Showing 13 changed files with 338 additions and 38 deletions.
40 changes: 2 additions & 38 deletions Track_2_ToDo_App/Sprint-03 - Database Integration/README.md
Original file line number Diff line number Diff line change
@@ -1,47 +1,11 @@
# Sprint 3: Database Integration
⏲️ _Est. time to complete: 60 min._ ⏲️

## 🎯 Here is what you will learn
- Understanding of the concept of persistent storage
- Add persistent storage to your web app from Sprint 2 to store tasks in a database

## 📈 Outcomes:
- Evolve app from Sprint 2 to persist data between sessions using a database for storage


## 🎓 Know Before You Start
- [ ] \< **to-do**: XX Presentation #1\>
- [ ] \< **to-do**: XX Presentation #2\>

## 📚 Features
In this sprint you will be taking the web application from Sprint 2 and adding in the ability to store tasks into a database to persist any changes that are made. This will allow users to access their tasks from any device with internet connectivity and not have to worry about concurrent users.

- **📕Feature 1: Shift task storage to database**
- **📖User Story 1: Convert file storage to database storage** - As a user, I would like to have my tasks stored in a database so that I can access them from any device with internet connectivity and not have to worry about concurrent users.


## 🏆 Actions Needed to Complete Sprint

1. [ ] Implement the **📖 Convert file storage to database storage** user story.
<details>
<summary>click here to get more details around how to implement this user story</summary>
<details>
<summary>🔒 Acceptance Criteria</summary>

- **Description** - As a user, I would like to have my tasks stored in a database so that I can access them from any device with internet connectivity and not have to worry about concurrent users.

- **Acceptance Criteria:**
- The application should store the tasks in a database instead of a file.
</details>
<details>
<summary>🎓Know before you start</summary>
- The following resources/videos will help you get a better understanding of some of the basic Python concepts that you will use to complete this user story.
- TBD
</details>
**📕Feature: Shift task storage to database**
1. [**📖 Convert file storage to database storage**](/Track_2_ToDo_App/Sprint-03%20-%20Database%20Integration/Features%201%20-%20Shift%20task%20storage%20to%20database/User%20Story%201%20-%20Move%20from%20File%20Storage%20to%20database.md)

**📢 Still need additional help?** - follow this [**step-by-step guide**](./Features%201%20-%20Shift%20task%20storage%20to%20database/User%20Story%201%20-%20Move%20from%20File%20Storage%20to%20database.md) <br/>
</details><br/>


<br/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
# User Story: Voice Enabled Task Addition - Step-by-Step
⏲️ _Est. time to complete: 30 min._ ⏲️

## User Story

*As a user, I want to add tasks to the web app using voice commands, so I can quickly input tasks without typing.*

## 🎯Acceptance Criteria:
- The web app should integrate a voice recognition system for task input.
- Users should be able to activate voice input through a designated button or command.
- The system should accurately transcribe voice commands into text for task creation.
- The interface should look something like this (note the arrow shows the addition of the voice button):

![Voice Button](/Track_2_ToDo_App/Sprint-04%20-%20Voice%20To%20Text/images/App_With_Voice_Button.png)

## 🎓Know Before You Start
no resources at this time

## 📋Steps

In order to complete this user story you will need to complete the following tasks

### Open Visual Studio Code
Open Visual Studio Code and open the source code the folder with your completed solution from the previous user story. If you prefer you can use the starting reference application from [here](/Track_2_ToDo_App/Sprint-03%20-%20Database%20Integration/src/app-s03-f01-us01/)

<br/>

### Add Voice Recognition to the Web App

> [!NOTE]
> **💻 Note for Mac M1 Users** - If you are using a Mac M1 device, please note that you will need to use Chrome or Safari as the voice-to-text mechanism used here is not supported in Edge on Mac M1 devices.
#### 1. Update user interface to include voice recognition button
We are going to use the Web Speech API to add voice recognition to the web app. This API is built into modern web browsers and allows you to interact via your voice.

In order to do this, we must update the add functionality in the web app by replacing the code for the form `<form action="/add>...</form>` in your `index.html` file:

```html
<form action="/add" method="post" class="my-4">
<div class="form-group">
<label for="todo">Add a to-do:</label>
<input type="text" name="todo" class="form-control">
</div>
<button type="submit" class="btn btn-primary">Add</button>
</form>
```

with the following code:

```html
<form action="/add" method="post" class="my-4">
<div class="form-group">
<br />
</div>
<span class="input-group-text">
<input type="text" id="todo" name="todo" class="form-control" placeholder="Add a new task">

<button type="button" class="btn btn-outline-secondary" onclick="captureVoice()">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-mic" viewBox="0 0 16 16">
<path d="M3.5 6.5A.5.5 0 0 1 4 7v1a4 4 0 0 0 8 0V7a.5.5 0 0 1 1 0v1a5 5 0 0 1-4.5 4.975V15h3a.5.5 0 0 1 0 1h-7a.5.5 0 0 1 0-1h3v-2.025A5 5 0 0 1 3 8V7a.5.5 0 0 1 .5-.5"></path>
<path d="M10 8a2 2 0 1 1-4 0V3a2 2 0 1 1 4 0zM8 0a3 3 0 0 0-3 3v5a3 3 0 0 0 6 0V3a3 3 0 0 0-3-3"></path>
</svg>
<span class="visually-hidden" title="Use Microphone"></span>
</button>
<button type="submit" class="btn btn-success">Add</button>
</span>
</form>
```

This code adds a button to the form that will allow the user to activate the microphone and speak their task. The `captureVoice()` function will be covered in the next step.

<br/>

#### 2. Add Javascript to support voice recognition
You will now need to create a Javascript file to help with the automation of capturing the voice from the browser. Create a new file called `app.js` in the `static/js` folder of your application. If these folders do not exist you will need to create them first. Add the following code to the `app.js` file:

```javascript
document.addEventListener("DOMContentLoaded", function() {
const nameInput = document.getElementById("todo");

//add javascript to support speech recognition for the todo input field
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
const recognition = new SpeechRecognition();
recognition.continuous = false;
recognition.lang = "en-US";
recognition.interimResults = false;

window.captureVoice = function() {
recognition.start();
nameInput.value = "Your microphone is activated, speak to record voice";
};

recognition.onresult = function(event) {
const transcript = event.results[0][0].transcript;
const recognizedText = transcript.endsWith('.') ? transcript.slice(0, -1) : transcript;
nameInput.value = recognizedText;
};

recognition.onspeechend = function() {
recognition.stop();
};

recognition.onnomatch = function(event) {
nameInput.value = "I didn't recognize that prompt.";
};

recognition.onerror = function(event) {
nameInput.value = "Error occurred in recognition: " + event.error;
};
});
```

This code will add the necessary Javascript to the web app to allow the user to activate the microphone and speak their task. The `captureVoice()` function will start the speech recognition process, and the `recognition.onresult` function will capture the voice input and display it in the input field. The `recognition.onspeechend` function will stop the speech recognition process when the user stops speaking. The `recognition.onnomatch` and `recognition.onerror` functions will handle errors that may occur during the speech recognition process.

<br/>

#### 3. Link the Javascript file to the HTML document
Link the Javascript file to the HTML document by adding the following code to the `<head>` tag in your `index.html` file.

```html
<script src="{{ url_for('static', filename='js/app.js') }}"></script>
```

<br/>

#### 4. Run the Application
Now you can test the voice recognition feature by running the web app and clicking on the microphone button. Speak a task into the microphone and see it appear in the input field. Click the "Add" button to add the task to the list. The App should look something like this (note the arrow shows the addition of the voice button):

![Voice Button](/Track_2_ToDo_App/Sprint-04%20-%20Voice%20To%20Text/images/App_With_Voice_Button.png)

<br/>
🎉 Congratulations! You have now added voice recognition to your web app, allowing users to add tasks via voice commands. This feature will provide a convenient way for users to input tasks without typing.

<br/>

> [!NOTE]
> 📄For the full source code for this exercise please see [here](/Track_2_ToDo_App/Sprint-04%20-%20Voice%20To%20Text/src/app-s04-f01-us01/).
<br/>

[🔼 Back **Workshop** Instructions ](/Track_2_ToDo_App/Workshop-Format.md) | [🔼 Back to **Hackathon** Sprint 4 ](/Track_2_ToDo_App/Sprint-04%20-%20Voice%20To%20Text/README.md) | [**◀ Previous user story** (in previous sprint)](/Track_2_ToDo_App/Sprint-03%20-%20Database%20Integration/Features%201%20-%20Shift%20task%20storage%20to%20database/User%20Story%201%20-%20Move%20from%20File%20Storage%20to%20database.md) | [**Next user story** (in next sprint) ▶](/Track_2_ToDo_App/Sprint-05%20-%20Advanced%20AI%20recommendations/Feature%201%20-%20Get%20Generative%20AI%20recommendation/User%20Story%201%20-%20Get%20Gen%20AI%20recommendation.md)
13 changes: 13 additions & 0 deletions Track_2_ToDo_App/Sprint-04 - Voice To Text/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Sprint 4: Adding in Voice to Text
⏲️ _Est. time to complete: 60 min._ ⏲️

In this sprint you will be taking the web application from Sprint 2 and adding in the ability to store tasks into a database to persist any changes that are made. This will allow users to access their tasks from any device with internet connectivity and not have to worry about concurrent users.

**📕Feature: Shift task storage to database**
1. [**📖 Convert file storage to database storage**](/Track_2_ToDo_App/Sprint-03%20-%20Database%20Integration/Features%201%20-%20Shift%20task%20storage%20to%20database/User%20Story%201%20-%20Move%20from%20File%20Storage%20to%20database.md)



<br/>

[🔼 Hackathon Home Page ](/Track_2_ToDo_App/README.md) | [◀ Previous Sprint](/Track_2_ToDo_App/Sprint-03%20-%20Database%20Integration/README.md) | [Next sprint ▶](/Track_2_ToDo_App/Sprint-05%20-%20Advanced%20AI%20recommendations/README.md)
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
###############################################################################
## Sprint 3: Database Integration
## Feature 1: Add Voice
## User Story 1: Add Voice to Text
###############################################################################
import os
from flask import Flask, render_template, request, redirect, url_for, g
from database import db, Todo

app = Flask(__name__)
basedir = os.path.abspath(os.path.dirname(__file__)) # Get the directory of the this file
todo_file = os.path.join(basedir, 'todo_list.txt') # Create the path to the to-do list file using the directory
app.config["SQLALCHEMY_DATABASE_URI"] = 'sqlite:///' + os.path.join(basedir, 'todos.db')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db.init_app(app)

with app.app_context():
db.create_all()

@app.before_request
def load_data_to_g():
todos = Todo.query.all()
g.todos = todos
g.todo = None

@app.route("/")
def index():
return render_template("index.html", todo_list=g.todos)

@app.route("/add", methods=["POST"])
def add_todo():
# Get the data from the form
todo = Todo(
name=request.form["todo"],
)
# Add the new ToDo to the list
db.session.add(todo)
db.session.commit()

# Add the new ToDo to the list
return redirect(url_for('index'))

# Delete a ToDo
@app.route('/remove/<int:id>', methods=["POST"])
def remove_todo(id):
db.session.delete(Todo.query.filter_by(id=id).first())
db.session.commit()
return redirect(url_for('index'))

if __name__ == "__main__":
app.run(debug=True)
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import Integer, String, Boolean, func
from sqlalchemy.orm import DeclarativeBase

class Base(DeclarativeBase):
pass

db = SQLAlchemy(model_class=Base)

class Todo(db.Model):
id = db.Column(Integer, primary_key=True)
name = db.Column(String(100), nullable=False)

def __str__(self):
return self.name
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
body {
background-color: f0f0f0; /* light grey */
color: darkslategray; /* default font color */
font-family: Arial, sans-serif;
background-image: url("../images/Designer02.jpeg");
background-repeat: no-repeat;
background-position: center;
background-size:cover;
}

h1 {
color: darkgray; /* font for the h1 header*/
}

.list-group-item {
color: #333; /* dark grey */
}


Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
document.addEventListener("DOMContentLoaded", function() {
const nameInput = document.getElementById("todo");

//add javascript to support speech recognition for the todo input field
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
const recognition = new SpeechRecognition();
recognition.continuous = false;
recognition.lang = "en-US";
recognition.interimResults = false;

window.captureVoice = function() {
recognition.start();
nameInput.value = "Your microphone is activated, speak to record voice";
};

recognition.onresult = function(event) {
const transcript = event.results[0][0].transcript;
const recognizedText = transcript.endsWith('.') ? transcript.slice(0, -1) : transcript;
nameInput.value = recognizedText;
};

recognition.onspeechend = function() {
recognition.stop();
};

recognition.onnomatch = function(event) {
nameInput.value = "I didn't recognize that prompt.";
};

recognition.onerror = function(event) {
nameInput.value = "Error occurred in recognition: " + event.error;
};
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<!DOCTYPE html>
<html>
<head>
<title>My To-Do List</title>
<link rel="icon" type="image/png" href="{{ url_for('static', filename='images/favicon.ico') }}">
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
<script src="{{ url_for('static', filename='js/app.js') }}"></script>
</head>
<body>
<div class="container">
<br/>
<br/>
<div class="h-100 p-5 bg-body-tertiary border rounded-3">
<h1>My To-Do List</h1>
</div>
<br />
<div class="row">
<div class="col-12">
<form method="post">
<ol class="list-group">
{% for todo in g.todos %}
<li id="task-{{ todo.id }}" data-id="{{ todo.id }}" class="list-group-item d-flex justify-content-between">
<div class="task">
<div class="title" id="title-{{ todo.id }}">{{ todo.name }}</div>
</div>
<span>
<button type="submit" class="btn btn-danger" formaction="{{ url_for('remove_todo', id=todo.id) }}">Remove</button>
</span>
</li>
{% endfor %}
</ol>
</form> </div>
<div class="row">
<div class="col-6">
<form action="/add" method="post" class="my-4">
<div class="form-group">
<br />
</div>
<span class="input-group-text">
<input type="text" id="todo" name="todo" class="form-control" placeholder="Add a new task">

<button type="button" class="btn btn-outline-secondary" onclick="captureVoice()">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-mic" viewBox="0 0 16 16">
<path d="M3.5 6.5A.5.5 0 0 1 4 7v1a4 4 0 0 0 8 0V7a.5.5 0 0 1 1 0v1a5 5 0 0 1-4.5 4.975V15h3a.5.5 0 0 1 0 1h-7a.5.5 0 0 1 0-1h3v-2.025A5 5 0 0 1 3 8V7a.5.5 0 0 1 .5-.5"></path>
<path d="M10 8a2 2 0 1 1-4 0V3a2 2 0 1 1 4 0zM8 0a3 3 0 0 0-3 3v5a3 3 0 0 0 6 0V3a3 3 0 0 0-3-3"></path>
</svg>
<span class="visually-hidden" title="Use Microphone"></span>
</button>
<button type="submit" class="btn btn-success">Add</button>
</span>
</form>

</div>
</div>
</div>
</body>
</html>
Loading

0 comments on commit a127bc7

Please sign in to comment.