Skip to content

Commit

Permalink
Merge pull request #97 from ItsDang/set_climbs
Browse files Browse the repository at this point in the history
Set climbs
  • Loading branch information
lemeryfertitta authored Sep 12, 2024
2 parents 4809bbd + 97fdcfe commit 2f351ca
Show file tree
Hide file tree
Showing 4 changed files with 212 additions and 3 deletions.
41 changes: 41 additions & 0 deletions climbdex/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,3 +154,44 @@ def api_save_ascent(
except Exception as e:
logging.error(f"Error in save_ascent: {str(e)}", exc_info=True)
return flask.jsonify({"error": str(e)}), 500

@blueprint.route("/api/v1/climbs", methods=["POST"])
@ValidateParameters(parameter_error)
def api_climbs(
board: str = Json(),
layout_id: int = Json(),
name: str = Json(),
description: str = Json(),
is_draft: bool = Json(),
frames: str = Json(),
angle: int = Json(),
):
if angle == -1:
angle = None

try:
login_cookie = flask.request.cookies.get(f"{board}_login")
if not login_cookie:
return flask.jsonify({"error": "Login required"}), 401

login_info = flask.json.loads(login_cookie)
token = login_info["token"]
setter_id = login_info["user_id"]

result = boardlib.api.aurora.save_climb(
board=board,
token=token,
layout_id=layout_id,
setter_id=setter_id,
name=name,
description=description,
is_draft=is_draft,
frames=frames,
frames_count=1,
frames_pace=0,
angle=angle,
)
return flask.jsonify(result)
except Exception as e:
logging.error(f"Error in api_climbs: {str(e)}", exc_info=True)
return flask.jsonify({"error": str(e)}), 500
95 changes: 95 additions & 0 deletions climbdex/static/js/climbCreation.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,40 @@ function getFrames() {
return frames.join("");
}

function resetHolds() {
const circles = document.getElementsByTagNameNS(
"http://www.w3.org/2000/svg",
"circle"
);
for (const circle of circles) {
circle.setAttribute("stroke-opacity", 0.0);
circle.setAttribute("stroke", "black");
}
}

document.addEventListener('DOMContentLoaded', function () {
// Reset log modal on show
const setModal = document.getElementById('div-set-modal');
setModal.addEventListener('show.bs.modal', function () {
document.getElementById('name').value = '';
document.getElementById('description').value = '';
document.getElementById('draft').checked = true;
document.getElementById('final').checked = false;
document.getElementById('No matching').checked = true;
document.getElementById('matching').checked = false;
document.getElementById("select-angle").value = -1;
document.getElementById('button-publish-climb').disabled = false;
});
});

document.getElementById('button-publish-climb').addEventListener('click', function () {
this.disabled = true; // Disable the button to prevent multiple submissions
});

document
.getElementById("button-reset-holds")
.addEventListener("click", resetHolds);

document
.getElementById("button-illuminate")
.addEventListener("click", function () {
Expand All @@ -42,6 +76,67 @@ document
illuminateClimb(board, bluetoothPacket);
});

document
.getElementById("button-publish-climb")
.addEventListener("click", function () {
const urlParams = new URLSearchParams(window.location.search);
const board = urlParams.get("board");
const layout_id = parseInt(urlParams.get("layout"));
const name = document.getElementById("name").value;
const is_matching = document.querySelector('input[name="is_matching"]:checked').id === "matching";
const hasDescription = document.getElementById("description").value != "";
const description = (is_matching ? "" : "No matching.") + (hasDescription ? " " : "") + document.getElementById("description").value;
const is_draft = document.querySelector('input[name="is_draft"]:checked').id === "draft";
const frames = getFrames();
const angle = parseInt(document.getElementById("select-angle").value);

const data = {
board: board,
layout_id: layout_id,
name: name,
description: description,
is_draft: is_draft,
frames: frames,
angle: angle,
};

fetch("/api/v1/climbs", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
})
.then((response) => {
if (!response.ok) {
throw new Error("Network response was not ok " + response.statusText);
}
return response.json();
})
.then((data) => {
const successAlert = document.querySelector(".alert-success");
successAlert.style.display = "block";

setTimeout(() => {
successAlert.style.display = "none";
const setModal = document.getElementById("div-set-modal");
const modalInstance = bootstrap.Modal.getInstance(setModal);
if (modalInstance) {
modalInstance.hide();
}
}, 3000);
})
.catch((error) => {
console.error("Error:", error);
const errorAlert = document.querySelector(".alert-danger");
errorAlert.style.display = "block";

setTimeout(() => {
errorAlert.style.display = "none";
}, 3000);
});
});

const backAnchor = document.getElementById("anchor-back");
backAnchor.href = location.origin;
if (document.referrer) {
Expand Down
76 changes: 73 additions & 3 deletions climbdex/templates/climbCreation.html.j2
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
overflow: auto;
}
</style>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"
integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL"
crossorigin="anonymous"></script>
</head>

<body>
Expand All @@ -33,14 +36,81 @@
</svg>
</button>
</div>
<div class="d-grid mt-3">
<button class="btn btn-warning" type="button" id="button-reset-holds">Reset Holds</button>
</div>
{% if login_cookie %}
<div class="d-grid mt-3">
<button id="button-set-climb" class="btn btn-primary position-relative" href="#" data-bs-toggle="modal" data-bs-target="#div-set-modal" type="button">
Publish
</button>
</div>
{% endif %}
</div>
</div>
</div>
<div class="row justify-content-md-center mt-3">
{% include 'footer.html.j2' %}
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"
integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL"
crossorigin="anonymous"></script>

<!-- Set Climb Modal -->
<div class="modal fade" id="div-set-modal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Publish a boulder:</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form id="ratingForm">
<div class="mb-3 pt-3">
<textarea class="form-control" id="name" rows="1" placeholder="Name"></textarea>
</div>
<div class="mb-3 pt-3">
<textarea class="form-control" id="description" rows="3" placeholder="Description (optional)"></textarea>
</div>
<div class="btn-group mb-3 d-flex" role="group">
<input class="btn-check" type="radio" name="is_draft" id="draft" value="draft" autocomplete="off"
checked>
<label class="btn btn-outline-primary flex-fill" for="draft">Draft</label>
<input class="btn-check" type="radio" name="is_draft" id="final" value="final" autocomplete="off">
<label class="btn btn-outline-primary flex-fill" for="final">Final</label>
</div>
<div class="btn-group mb-3 d-flex" role="group">
<input class="btn-check" type="radio" name="is_matching" id="No matching" value="No matching" autocomplete="off"
checked>
<label class="btn btn-outline-primary flex-fill" for="No matching">No matching</label>

<input class="btn-check" type="radio" name="is_matching" id="matching" value="matching" autocomplete="off">
<label class="btn btn-outline-primary flex-fill" for="matching">Matching</label>
</div>
<div class="input-group mb-3">
<span class="input-group-text">Angle</span>
<select class="form-select" id="select-angle" name="angle">
<option value="-1" >None</option>
{% for angle_option in angles %}
<option value="{{ angle_option[0] }}">
{{ angle_option[0] }}
</option>
{% endfor %}
</select>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" id="button-publish-climb">Publish</button>
</div>
<div class="alter-settings alert alert-success" role="alert">
Boulder published successfully!
</div>
<div class="alter-settings alert alert-danger" role="alert">
An error occurred, please try again later.
</div>
</div>
</div>
</div>

<script src="{{url_for('static', filename='js/common.js')}}"></script>
<script src="{{url_for('static', filename='js/bluetooth.js')}}"></script>
<script src="{{url_for('static', filename='js/climbCreation.js')}}"></script>
Expand Down
3 changes: 3 additions & 0 deletions climbdex/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ def create():
colors = climbdex.db.get_data(board_name, "colors", {"layout_id": layout_id})
app_url = boardlib.api.aurora.WEB_HOSTS[board_name]
placement_positions = get_placement_positions(board_name, layout_id, size_id)
login_cookie = flask.request.cookies.get(f"{board_name}_login")
return flask.render_template(
"climbCreation.html.j2",
app_url=app_url,
Expand All @@ -101,6 +102,8 @@ def create():
colors=colors,
led_colors=get_led_colors(board_name, layout_id),
placement_positions=placement_positions,
angles=climbdex.db.get_data(board_name, "angles", {"layout_id": layout_id}),
login_cookie=login_cookie,
**get_draw_board_kwargs(board_name, layout_id, size_id, set_ids),
)

Expand Down

0 comments on commit 2f351ca

Please sign in to comment.