Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file.
13 changes: 3 additions & 10 deletions samples/web-app-cosmosdb-nosql-api/python/scripts/deploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,7 @@ RANDOM_SUFFIX=$(echo $RANDOM)
NEW_DB_NAME="vacationplanner_${RANDOM_SUFFIX}"
AZURECOSMOSDB_DATABASENAME=$NEW_DB_NAME
AZURECOSMOSDB_CONTAINERNAME="activities_${RANDOM_SUFFIX}"
AURECOSMOSDB_PARTITION_KEY="/partitionKey"

# Start azure CLI local mode session
az login

# Change the current directory to the script's directory
#cd "$CURRENT_DIR" || exit
AURECOSMOSDB_PARTITION_KEY="/username"

# Validates if the resource group exists in the subscription, if not creates it
echo "Checking if resource group [$RESOURCE_GROUP_NAME] exists..."
Expand Down Expand Up @@ -118,14 +112,13 @@ zip -r "$ZIPFILE" app.py cosmosdb_client.py static templates requirements.txt

# Deploy the web app
echo "Deploying web app [$WEB_APP_NAME] with zip file [$ZIPFILE]..."
echo "Using az webapp deploy command for LocalStack emulator environment."
az webapp deploy \
--resource-group $RESOURCE_GROUP_NAME \
--name $WEB_APP_NAME \
--src-path ${ZIPFILE} \
--type zip \
--async true \
--debug \
--verbose 1>/dev/null
--async true

# Remove the zip package of the web app
if [ -f "$ZIPFILE" ]; then
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#!/bin/bash

# Variables
# Check resource group
az group show \
--name local-rg \
Expand Down
10 changes: 0 additions & 10 deletions samples/web-app-cosmosdb-nosql-api/python/src/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,15 +110,5 @@ def delete(activity_id: str):

return redirect(url_for('index'))

@app.route('/edit/<string:activity_id>', methods=['POST'])
def edit(activity_id: str):
new_text = request.form.get('new_text')

if new_text:
logger.info(f"Updating ID {activity_id} with activity: {new_text}")
get_cosmos().update_document_activity(activity_id, username, new_text)

return redirect(url_for('index'))

if __name__ == '__main__':
app.run(debug=True)
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,16 @@ def update_document_activity(self, activity_id: str, username: str, new_text: st
logger.warning(f"Update failed: {e}")

def delete_document_by_id(self, doc_id: str, username: str):
self.ensure_initialized()

try:
self.container.delete_item(item=doc_id, partition_key=username)
except exceptions.CosmosResourceNotFoundError:
pass
doc_to_delete = self.container.read_item(item=doc_id, partition_key=[username])
self.container.delete_item(item=doc_to_delete, partition_key=[username])
except exceptions.CosmosResourceNotFoundError as e:
logger.warning(f"Cosmos resource with doc_id {doc_id} and username {username} was not found")
raise e
except exceptions.CosmosHttpResponseError as e:
raise e
except Exception as e:
logger.info(f"DELETE METHOD CRASHED: Error Type: {type(e).__name__}, Message: {e}")
raise e
118 changes: 25 additions & 93 deletions samples/web-app-cosmosdb-nosql-api/python/src/templates/index.html
Original file line number Diff line number Diff line change
@@ -1,54 +1,3 @@
<!--- <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vacation Planner</title>
<link rel="stylesheet" href="{{ url_for('static', filename='bootstrap/css/bootstrap.min.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
<link rel="icon" type="image/x-icon" href="{{ url_for('static', filename='favicon.ico') }}">
</head>
<body style="background: linear-gradient(135deg, #fff 0%, #a2d4f7 100%); min-height: 100vh;">
<div class="container py-4 my-5 bg-white bg-opacity-75 rounded-4 shadow-lg" style="max-width:480px;">
<img src="{{ url_for('static', filename='summer_banner.jpg') }}" alt="Summer Banner" class="img-fluid rounded mb-3 w-100" style="max-height:180px; object-fit:cover;">
<h1 class="display-9 fw-bold sea-title mb-4">Vacation Planner</h1>
<form method="post" class="sea-form mb-4" style="max-width: 520px; margin: 0 auto;">
<div style="display: flex; width: 100%;">
<input type="text" name="activity" class="form-control sea-input" placeholder="Enter a vacation activity..." required>
<button type="submit" class="sea-btn">Add</button>
</div>
</form>
<div class="table-responsive" style="width: 100%;">
<table class="table sea-table align-middle" style="width: 100%; margin: 0;">
<thead>
<tr>
<th class="text-start">Activity</th>
<th class="text-start align-middle action-col" style="width: 90px;">Action</th>
</tr>
</thead>
<tbody>
{% for activity in activities %}
<tr>
<td class="text-start">{{ activity[1] }}</td>
<td class="text-start align-middle action-col" style="width: 90px;">
<form method="post" action="{{ url_for('delete', activity_id=activity[0]) }}" class="d-inline">
<input type="hidden" name="row_id" value="{{ activity[0] }}">
<button type="submit" class="sea-btn" style="width: 90px;">Delete</button>
</form>
</td>
</tr>
{% else %}
<tr>
<td colspan="2" class="text-center text-muted fst-italic">No vacation plans yet!</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</body>
</html> --->


<!DOCTYPE html>
<html lang="en">
<head>
Expand All @@ -59,15 +8,17 @@ <h1 class="display-9 fw-bold sea-title mb-4">Vacation Planner</h1>
<link rel="icon" type="image/x-icon" href="{{ url_for('static', filename='favicon.ico') }}">
</head>
<body style="background: linear-gradient(135deg, #fff 0%, #a2d4f7 100%); min-height: 100vh;">
<div class="container py-4 my-5 bg-white bg-opacity-75 rounded-4 shadow-lg" style="max-width:520px;">
<div class="container py-4 my-5 bg-white bg-opacity-75 rounded-4 shadow-lg" style="max-width:600px;">
<img src="{{ url_for('static', filename='summer_banner.jpg') }}" alt="Summer Banner" class="img-fluid rounded mb-3 w-100" style="max-height:180px; object-fit:cover;">

<h1 class="display-9 fw-bold sea-title mb-4 text-center">Vacation Planner</h1>

<form method="post" class="sea-form mb-4">
<div class="d-flex w-100">
<input type="text" name="activity" class="form-control sea-input" placeholder="Enter a vacation activity..." required>
<button type="submit" class="sea-btn ms-2">Add</button>
<form method="post" action="{{ url_for('index') }}" class="sea-form mb-4" style="max-width: 600px; margin: 0 auto;">
<div style="display: flex; width: 100%;">
<input type="hidden" name="row_id" value="{{ edit_id or '' }}">
<input id="activityInput" type="text" name="activity" class="form-control sea-input"
placeholder="Enter a vacation activity..." value="{{ edit_activity or '' }}" required autofocus>
<button type="submit" class="sea-btn ms-2">{{ 'Update' if edit_id else 'Add' }}</button>
</div>
</form>

Expand All @@ -76,36 +27,23 @@ <h1 class="display-9 fw-bold sea-title mb-4 text-center">Vacation Planner</h1>
<thead>
<tr>
<th class="text-start">Activity</th>
<th class="text-end" style="width: 160px;">Actions</th>
<th class="text-center align-middle" style="width: 220px;" colspan="2">Action</th>
</tr>
</thead>
<tbody>
{% for activity in activities %}
<tr>
<td class="text-start">
<span id="display-{{ activity[0] }}">{{ activity[1] }}</span>

<form id="edit-form-{{ activity[0] }}" method="post" action="{{ url_for('edit', activity_id=activity[0]) }}" class="d-none">
<div class="input-group input-group-sm">
<input type="text" name="new_text" class="form-control" value="{{ activity[1] }}" required>
<button type="submit" class="btn btn-success btn-sm">Save</button>
<button type="button" class="btn btn-secondary btn-sm" onclick="toggleEdit('{{ activity[0] }}')">✕</button>
</div>
<td class="text-start">{{ activity[1] }}</td>

<td class="text-start align-middle p-1" style="width: 110px;">
<form method="post" action="{{ url_for('delete', activity_id=activity[0]) }}" class="d-inline">
<button type="submit" class="sea-btn" style="width: 90px; font-size: 0.9rem;">Delete</button>
</form>
</td>
<td class="text-end">
<div id="actions-{{ activity[0] }}">
<button type="button" class="btn btn-sm btn-outline-primary" onclick="toggleEdit('{{ activity[0] }}')">Edit</button>

<form method="post" action="{{ url_for('delete', activity_id=activity[0]) }}" class="d-inline">
<button type="submit" class="btn btn-sm btn-outline-danger">Delete</button>
</form>
</div>
</td>
</tr>
{% else %}
<tr>
<td colspan="2" class="text-center text-muted fst-italic py-4">No vacation plans yet!</td>
<td colspan="3" class="text-center text-muted fst-italic py-4">No vacation plans yet!</td>
</tr>
{% endfor %}
</tbody>
Expand All @@ -114,24 +52,18 @@ <h1 class="display-9 fw-bold sea-title mb-4 text-center">Vacation Planner</h1>
</div>

<script>
function toggleEdit(id) {
const displaySpan = document.getElementById(`display-${id}`);
const editForm = document.getElementById(`edit-form-${id}`);
const actionButtons = document.getElementById(`actions-${id}`);

if (editForm.classList.contains('d-none')) {
// Switch to Edit Mode
editForm.classList.remove('d-none');
displaySpan.classList.add('d-none');
actionButtons.classList.add('d-none');
// Auto-focus logic for the input field
(function () {
const input = document.getElementById('activityInput');
if (!input) return;
if (input.value && input.value.length > 0) {
input.focus();
const len = input.value.length;
input.setSelectionRange(len, len);
} else {
// Switch back to Display Mode
editForm.class
editForm.classList.add('d-none');
displaySpan.classList.remove('d-none');
actionButtons.classList.remove('d-none');
input.focus();
}
}
})();
</script>
</body>
</html>
</html>
Loading