Skip to content

Commit

Permalink
Merge pull request #46 from CSCI-GA-2820-FA23-001/32_setup_ui_and_bdd
Browse files Browse the repository at this point in the history
32 setup UI and bdd
  • Loading branch information
WYB929 authored Nov 21, 2023
2 parents dec802f + 4002ad4 commit 1fd6799
Show file tree
Hide file tree
Showing 15 changed files with 618 additions and 30 deletions.
5 changes: 1 addition & 4 deletions service/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,10 +253,7 @@ def paginate(cls, page_index=1, page_size=10, rec_type=None):
if rec_type:
qry = qry.filter(cls.recommendation_type == rec_type)

paginated_recommendations = qry.paginate(
page=page_index, per_page=page_size, error_out=False
)
return paginated_recommendations.items
return qry.paginate(page=page_index, per_page=page_size, error_out=False)

@classmethod
def find(cls, recommendation_id: int):
Expand Down
30 changes: 16 additions & 14 deletions service/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,8 @@ def healthcheck():
######################################################################
@app.route("/")
def index():
"""Root URL response"""
app.logger.info("Request for Root URL")
return (
jsonify(
name="Recommendation Demo REST API Service",
version="1.0",
# paths=url_for("list_recommendations", _external=True),
),
status.HTTP_200_OK,
)
"""Base URL for our service"""
return app.send_static_file("index.html")


######################################################################
Expand All @@ -64,13 +56,23 @@ def list_recommendations():
f"Invalid recommendation type: '{rec_type}'.",
)

recommendations = Recommendation.paginate(
paginated_recommendations = Recommendation.paginate(
page_index=page_index, page_size=page_size, rec_type=type_value
)

results = [recommendation.serialize() for recommendation in recommendations]
app.logger.info("Returning %d recommendations", len(results))
return jsonify(results), status.HTTP_200_OK
results = {
"page": paginated_recommendations.page,
"per_page": paginated_recommendations.per_page,
"total": paginated_recommendations.total,
"pages": paginated_recommendations.pages,
"items": [
recommendation.serialize()
for recommendation in paginated_recommendations.items
],
}

app.logger.info("Returning %d recommendations", len(results["items"]))
return results, status.HTTP_200_OK


######################################################################
Expand Down
11 changes: 11 additions & 0 deletions service/static/css/blue_bootstrap.min.css

Large diffs are not rendered by default.

11 changes: 11 additions & 0 deletions service/static/css/cerulean_bootstrap.min.css

Large diffs are not rendered by default.

11 changes: 11 additions & 0 deletions service/static/css/darkly_bootstrap.min.css

Large diffs are not rendered by default.

11 changes: 11 additions & 0 deletions service/static/css/flatly_bootstrap.min.css

Large diffs are not rendered by default.

11 changes: 11 additions & 0 deletions service/static/css/slate_bootstrap.min.css

Large diffs are not rendered by default.

Binary file added service/static/images/newapp-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
189 changes: 189 additions & 0 deletions service/static/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
<!DOCTYPE html>
<html>

<head>
<title>Recommendation Demo RESTful Service</title>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="static/images/newapp-icon.png">
<link rel="stylesheet" href="static/css/cerulean_bootstrap.min.css">
</head>

<body>
<div class="container">
<div class="page-header">
<h1>Recommendation Demo RESTful Service</h1>
</div>

<!-- Flash Message -->
<div class="table-responsive">
<table class="table">
<tr>
<td>Status:</td>
<td><span id="flash_message"></span></td>
</tr>
</table>
</div>

<!-- FORM -->
<div class="col-md-12" id="form_data">
<h3>Create, Retrieve, Update, and Delete a Recommendation:</h3>
<div class="well">
<div class="form-horizontal">
<div class="form-group">
<label class="control-label col-sm-2" for="rec_id">Recommendation ID:</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="rec_id"
placeholder="Enter ID of Recommendation">
</div>
<div class="col-sm-4">
<button type="submit" class="btn btn-primary" id="retrieve-btn">Retrieve</button>
<button type="submit" class="btn btn-danger" id="delete-btn">Delete</button>
</div>
</div>
</div> <!-- form horizontal -->

<div class="form-horizontal">

<!-- SOURCE ITEM ID -->
<div class="form-group">
<label class="control-label col-sm-2" for="src_item_id">Source Item ID:</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="src_item_id"
placeholder="Enter Source Item ID for Recommendation">
</div>
</div>

<!-- TARGET ITEM ID -->
<div class="form-group">
<label class="control-label col-sm-2" for="tgt_item_id">Target Item ID:</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="tgt_item_id"
placeholder="Enter Target Item ID for Recommendation">
</div>
</div>

<!-- TYPE -->
<div class="form-group">
<label class="control-label col-sm-2" for="rec_type">Type:</label>
<div class="col-sm-10">
<select class="form-control" id="rec_type">
<option value="UNKNOWN" selected>Unknown</option>
<option value="UP_SELL">Up Sell</option>
<option value="CROSS_SELL">Cross Sell</option>
<option value="ACCESSORY">Accessory</option>
<option value="COMPLEMENTARY">Complementary</option>
<option value="SUBSTITUTE">Substitute</option>
</select>
</div>
</div>

<!-- STATUS -->
<div class="form-group">
<label class="control-label col-sm-2" for="rec_status">Status:</label>
<div class="col-sm-10">
<select class="form-control" id="rec_status">
<option value="UNKNOWN" selected>Unknown</option>
<option value="VALID">Valid</option>
<option value="OUT_OF_STOCK">Out of Stock</option>
<option value="DEPRECATED">Deprecated</option>
</select>
</div>
</div>

<!-- WEIGHT -->
<div class="form-group">
<label class="control-label col-sm-2" for="rec_weight">Weight:</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="rec_weight"
placeholder="Enter Weight Between 0 and 1 for Recommendation">
</div>
</div>

<!-- LIKES -->
<div class="form-group">
<label class="control-label col-sm-2" for="num_of_likes">Number of Likes:</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="num_of_likes"
placeholder="Enter Number of Likes for Recommendation" value="0">
</div>
</div>

<!-- SUBMIT BUTTONS -->
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-primary" id="search-btn">Search</button>
<button type="submit" class="btn btn-primary" id="clear-btn">Clear</button>
<button type="submit" class="btn btn-success" id="create-btn">Create</button>
<button type="submit" class="btn btn-warning" id="update-btn">Update</button>
</div>
</div>
</div> <!-- form horizontal -->
</div> <!-- end well -->
</div> <!-- end Form -->

<!-- Search Results -->
<div class="table-responsive col-md-12" id="search_results">
<table class="table table-striped">
<thead>
<tr>
<!--
style="border-right: 1px dashed #000;"
-->
<th class="col-md-1">ID</th>
<th class="col-md-1">Source</th>
<th class="col-md-1">Target</th>
<th class="col-md-1">Type</th>
<th class="col-md-1">Status</th>
<th class="col-md-1">Weight</th>
<th class="col-md-1">Likes</th>
<th class="col-md-2">Created Time</th>
<th class="col-md-2">Updated Time</th>
</tr>
</thead>
</table>
</div>

<!-- Pagination Controls -->
<div class="col-md-12" style="text-align: center;">
<div class="table-responsive">
<table class="table">
<tr>
<td><span id="search_summary"></span></td>
</tr>
</table>
</div>
<div class="form-group">
<label class="control-label" for="page_size">Item per page:</label>
<select id="page_size">
<option value="5" selected>5</option>
<option value="10">10</option>
<option value="20">20</option>
<option value="50">50</option>
</select>
</div>
<div class="form-group">
<label class="control-label" for="page_index">Page index:</label>
<input type="text" class="form-control" id="page_index" value="1"
style="display: inline-block; width: 60px;">
</div>
</div>

<footer>
<br><br>
<p>&copy; NYU DevOps Company 2023</p>
</footer>

</div> <!-- container -->

<script type="text/javascript" src="static/js/jquery-3.6.0.min.js"></script>
<script type="text/javascript" src="static/js/bootstrap.min.js"></script>

<!-- YOUR REST API -->
<script type="text/javascript" src="static/js/rest_api.js"></script>
<script type="text/javascript" src="static/js/form_validation.js"></script>

</body>

</html>
7 changes: 7 additions & 0 deletions service/static/js/bootstrap.min.js

Large diffs are not rendered by default.

73 changes: 73 additions & 0 deletions service/static/js/form_validation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
$(function () {
var regexForPositive = /^[1-9]\d*$/; // positive number without leading zeros

var lastPage = '';
$('#page_index').on('input', function () {
var value = $(this).val();
if (regexForPositive.test(value) || value === '') {
lastPage = value;
} else {
alert("Invalid Input");
$(this).val(lastPage);
}
});


var regexForInt = /^(0|[1-9][0-9]*)$/; // natural number without leading zeros

var lastId = '';
$('#rec_id').on('input', function () {
var value = $(this).val();
if (regexForInt.test(value) || value === '') {
lastId = value;
} else {
alert("Invalid Input");
$(this).val(lastId);
}
});

var lastSrcId = '';
$('#src_item_id').on('input', function () {
var value = $(this).val();
if (regexForInt.test(value) || value === '') {
lastSrcId = value;
} else {
alert("Invalid Input");
$(this).val(lastSrcId);
}
});

var lastTgtId = '';
$('#tgt_item_id').on('input', function () {
var value = $(this).val();
if (regexForInt.test(value) || value === '') {
lastTgtId = value;
} else {
alert("Invalid Input");
$(this).val(lastTgtId);
}
});

var lastLikes = '';
$('#num_of_likes').on('input', function () {
var value = $(this).val();
if (regexForInt.test(value) || value === '') {
lastLikes = value;
} else {
alert("Invalid Input");
$(this).val(lastLikes);
}
});

var regexForWeight = /^(0(?:\.\d*)?|1(?:\.0*)?)$/; // decimal between 0 and 1 without leading zeros
var lastWeight = '';
$('#rec_weight').on('input', function () {
var value = $(this).val();
if (regexForWeight.test(value) || value === '') {
lastWeight = value;
} else {
alert("Invalid Input");
$(this).val(lastWeight);
}
});
});
2 changes: 2 additions & 0 deletions service/static/js/jquery-3.6.0.min.js

Large diffs are not rendered by default.

Loading

0 comments on commit 1fd6799

Please sign in to comment.