Merged changes from master.

This commit is contained in:
kououken 2019-02-16 12:21:29 -08:00
commit c864d4dd5a
8 changed files with 70 additions and 7 deletions

View file

@ -1,5 +1,5 @@
# reimbursinator # reimbursinator
Open source expense management solution An open source expense management solution, written in python.
Daniel Dupriest, Logan Miller, Jack, Joe Arriaga, Preston, Rupika, Liang Shuaiyi Daniel Dupriest, Logan Miller, Jack, Joe Arriaga, Preston, Rupika, Liang Shuaiyi

View file

@ -166,6 +166,17 @@ def reports(request):
return JsonResponse(report_set) return JsonResponse(report_set)
def user_owns_report(user, report):
"""
Returns true if the specified user is owner of the report.
report -- ID of the report to check.
"""
report_to_check = Report.objects.filter(id=report)
if len(report_to_check) < 1:
return False
return report_to_check[0].user_id == user
@api_view(['GET', 'PUT', 'DELETE']) @api_view(['GET', 'PUT', 'DELETE'])
def report_detail(request, report_pk): def report_detail(request, report_pk):
""" """
@ -174,6 +185,10 @@ def report_detail(request, report_pk):
report_pk -- ID of the report to carry out the action on. report_pk -- ID of the report to carry out the action on.
""" """
# Check that the user owns the report
if not user_owns_report(user=request.user, report=report_pk):
return JsonResponse({"message": "Current user does not own the specified report."}, status=401)
# GET: Retrieves a json representation of the specified report # GET: Retrieves a json representation of the specified report
if request.method == 'GET': if request.method == 'GET':
data = get_report(report_pk) data = get_report(report_pk)
@ -203,6 +218,18 @@ def report_detail(request, report_pk):
r.delete() r.delete()
return JsonResponse({"message": "Deleted report: {0}.".format(title)}) return JsonResponse({"message": "Deleted report: {0}.".format(title)})
def user_owns_section(user, section):
"""
Returns true if the specified user is owner of the section.
section -- ID of the section to check.
"""
section_to_check = Section.objects.filter(id=section)
if len(section_to_check) < 1:
return False
report_to_check = section_to_check[0].report_id
return report_to_check.user_id == user
@api_view(['PUT']) @api_view(['PUT'])
def section(request, report_pk, section_pk): def section(request, report_pk, section_pk):
""" """
@ -210,6 +237,10 @@ def section(request, report_pk, section_pk):
section_pk -- Section for which the data should be updated. section_pk -- Section for which the data should be updated.
""" """
# Check that the user owns the report
if not user_owns_section(user=request.user, section=section_pk):
return JsonResponse({"message": "Current user does not own the specified section."}, status=401)
for key in request.data: for key in request.data:
# get the matching field object # get the matching field object
update = Field.objects.get(section_id=section_pk, field_name=key) update = Field.objects.get(section_id=section_pk, field_name=key)

Binary file not shown.

View file

@ -8,6 +8,7 @@
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.min.js" integrity="sha384-B0UglyR+jN6CkvvICOB2joaf5I4l3gm9GU6Hc1og6Ls7i6U/mkkaduKaBhlAXv9k" crossorigin="anonymous"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.min.js" integrity="sha384-B0UglyR+jN6CkvvICOB2joaf5I4l3gm9GU6Hc1og6Ls7i6U/mkkaduKaBhlAXv9k" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/classlist/1.2.20171210/classList.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/classlist/1.2.20171210/classList.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>
<link rel="shortcut icon" href="img/favicon.ico"> <link rel="shortcut icon" href="img/favicon.ico">
<title>Reimbursinator</title> <title>Reimbursinator</title>
</head> </head>

View file

@ -97,6 +97,18 @@ function createFormGroup(sectionIdStr, field) {
formGroup.appendChild(div); formGroup.appendChild(div);
break; break;
case "date": case "date":
input.type = "date";
input.placeholder = "mm-dd-yyyy";
if (field.value === "None") {
input.value = "";
} else {
input.value = field.value;
}
input.classList.add("form-control");
formGroup.appendChild(label);
div.appendChild(input)
formGroup.appendChild(div);
break;
case "string": case "string":
input.type = "text"; input.type = "text";
input.value = field.value; input.value = field.value;
@ -107,7 +119,11 @@ function createFormGroup(sectionIdStr, field) {
break; break;
case "decimal": case "decimal":
input.type = "text"; input.type = "text";
if (field.value === "0.00") {
input.value = "";
} else {
input.value = field.value; input.value = field.value;
}
input.classList.add("form-control"); input.classList.add("form-control");
input.pattern = "\\d+(\\.\\d{2})?"; input.pattern = "\\d+(\\.\\d{2})?";
formGroup.appendChild(label); formGroup.appendChild(label);
@ -116,7 +132,11 @@ function createFormGroup(sectionIdStr, field) {
break; break;
case "integer": case "integer":
input.type = "number"; input.type = "number";
if (field.value === 0) {
input.value = "";
} else {
input.value = field.value; input.value = field.value;
}
input.classList.add("form-control"); input.classList.add("form-control");
input.step = 1; input.step = 1;
input.min = 0; input.min = 0;
@ -430,6 +450,16 @@ if (newReportForm) {
}); });
} }
document.addEventListener("input", function(event) {
if (event.target.type === "date") {
if (!moment(event.target.value, "YYYY-MM-DD", true).isValid()) {
event.target.setCustomValidity("Invalid date format");
} else {
event.target.setCustomValidity("");
}
}
});
document.addEventListener("submit", function(event) { document.addEventListener("submit", function(event) {
if (event.target.classList.contains("section-form")) { if (event.target.classList.contains("section-form")) {
event.preventDefault(); event.preventDefault();

View file

@ -25,7 +25,7 @@
<form class="form" autocomplete="off"> <form class="form" autocomplete="off">
<div class="form-group"> <div class="form-group">
<label for="email">Email:</label> <label for="email">Email:</label>
<input class="form-control" id="email" type="email" name="email" required> <input class="form-control" id="email" type="email" name="email" autofocus required>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="password">Password:</label> <label for="password">Password:</label>

View file

@ -8,6 +8,7 @@
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.min.js" integrity="sha384-B0UglyR+jN6CkvvICOB2joaf5I4l3gm9GU6Hc1og6Ls7i6U/mkkaduKaBhlAXv9k" crossorigin="anonymous"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.min.js" integrity="sha384-B0UglyR+jN6CkvvICOB2joaf5I4l3gm9GU6Hc1og6Ls7i6U/mkkaduKaBhlAXv9k" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/classlist/1.2.20171210/classList.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/classlist/1.2.20171210/classList.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>
<link rel="shortcut icon" href="img/favicon.ico"> <link rel="shortcut icon" href="img/favicon.ico">
<title>Reimbursinator</title> <title>Reimbursinator</title>
</head> </head>
@ -47,7 +48,7 @@
<form class="form new-report-form" autocomplete="off"> <form class="form new-report-form" autocomplete="off">
<div class="form-group"> <div class="form-group">
<label for="title">Report title:</label> <label for="title">Report title:</label>
<input type="text" class="form-control" name="title" id="title"> <input type="text" class="form-control" name="title" id="title" autofocus>
</div> </div>
<button type="submit" class="btn btn-primary" data-toggle="modal" data-target="#newReportModal">Create</button> <button type="submit" class="btn btn-primary" data-toggle="modal" data-target="#newReportModal">Create</button>
</form> </form>

View file

@ -25,7 +25,7 @@
<form class="form signup" autocomplete="off" action="index.html"> <form class="form signup" autocomplete="off" action="index.html">
<div class="form-group"> <div class="form-group">
<label for="email">Email:</label> <label for="email">Email:</label>
<input class="form-control" type="email" id="email" pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,3}$" oninput="validateEmail(this);" required> <input class="form-control" type="email" id="email" pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,3}$" oninput="validateEmail(this);" autofocus required>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="first_name">First Name:</label> <label for="first_name">First Name:</label>