diff --git a/src/main/java/org/catrobat/jira/timesheet/rest/TimesheetRest.java b/src/main/java/org/catrobat/jira/timesheet/rest/TimesheetRest.java
index 5659814..b764a2f 100644
--- a/src/main/java/org/catrobat/jira/timesheet/rest/TimesheetRest.java
+++ b/src/main/java/org/catrobat/jira/timesheet/rest/TimesheetRest.java
@@ -1182,7 +1182,7 @@ public Response updateTotalTargetHours(@Context HttpServletRequest request, @Pat
return Response.status(Response.Status.UNAUTHORIZED).entity(e.getMessage()).build();
}
- Response response = permissionService.checkUserPermission();
+ Response response = permissionService.checkRootPermission();
if (response != null)
return response;
@@ -1201,6 +1201,36 @@ public Response updateTotalTargetHours(@Context HttpServletRequest request, @Pat
}
}
+ @POST
+ @Path("updateSubtractedHours/{hours}")
+ public Response updateSubtractedHours(@Context HttpServletRequest request, @PathParam("hours") int hours){
+ ApplicationUser user;
+
+ try {
+ user = permissionService.checkIfUserExists();
+ } catch (PermissionException e) {
+ return Response.status(Response.Status.UNAUTHORIZED).entity(e.getMessage()).build();
+ }
+
+ Response response = permissionService.checkRootPermission();
+ if (response != null)
+ return response;
+
+ try{
+ Timesheet sheet = sheetService.getTimesheetByUser(user.getKey());
+
+ if(sheet != null) {
+ sheet.setHoursDeducted(hours);
+ sheet.save();
+ }
+
+ return Response.ok(new JsonTimesheet(sheet)).build();
+ }
+ catch (ServiceException e){
+ return Response.status(Response.Status.CONFLICT).entity(e.getMessage()).build();
+ }
+ }
+
@DELETE
@Path("deleteLecture")
@Consumes(MediaType.APPLICATION_JSON)
diff --git a/src/main/java/org/catrobat/jira/timesheet/rest/json/JsonTimesheet.java b/src/main/java/org/catrobat/jira/timesheet/rest/json/JsonTimesheet.java
index 94baf04..bfe6159 100644
--- a/src/main/java/org/catrobat/jira/timesheet/rest/json/JsonTimesheet.java
+++ b/src/main/java/org/catrobat/jira/timesheet/rest/json/JsonTimesheet.java
@@ -51,7 +51,7 @@ public final class JsonTimesheet {
@JsonDeserialize(using = DateAndTimeDeserialize.class)
private Date latestEntryDate;
@XmlElement
- private int targetHourPractice;
+ private int targetHoursRemaining;
@XmlElement
private int targetHours;
@XmlElement
@@ -71,16 +71,18 @@ public final class JsonTimesheet {
public JsonTimesheet(Timesheet timesheet) {
this.timesheetID = timesheet.getID();
this.userKey = timesheet.getUserKey();
- this.lectures = timesheet.getLectures();
- this.reason = timesheet.getReason();
- this.latestEntryDate = timesheet.getLatestEntryBeginDate();
- this.targetHourPractice = timesheet.getHoursCompleted();
+ this.displayName = timesheet.getDisplayName();
+ this.state = timesheet.getState();
+
this.targetHours = timesheet.getTargetHours();
- this.targetHoursCompleted = timesheet.getHoursCompleted();
+ this.lectures = timesheet.getLectures();
this.targetHoursRemoved = timesheet.getHoursDeducted();
- this.state = timesheet.getState();
- this.displayName = timesheet.getDisplayName();
+ this.reason = timesheet.getReason();
+
+ this.targetHoursCompleted = timesheet.getHoursCompleted() - this.targetHoursRemoved;
+ this.targetHoursRemaining = this.targetHours - this.targetHoursCompleted;
+ this.latestEntryDate = timesheet.getLatestEntryBeginDate();
if (timesheet.firstEntry() != null) {
this.firstEntryDate = timesheet.firstEntry().getBeginDate();
}
@@ -133,12 +135,12 @@ public void setLatestEntryDate(Date latestEntryDate) {
this.latestEntryDate = latestEntryDate;
}
- public int getTargetHourPractice() {
- return targetHourPractice;
+ public int getTargetHoursRemaining() {
+ return targetHoursRemaining;
}
- public void setTargetHourPractice(int targetHourPractice) {
- this.targetHourPractice = targetHourPractice;
+ public void setTargetHoursRemaining(int targetHoursRemaining) {
+ this.targetHoursRemaining = targetHoursRemaining;
}
@@ -203,7 +205,7 @@ public boolean equals(Object o) {
if (latestEntryDate != that.latestEntryDate) {
return false;
}
- if (targetHourPractice != that.targetHourPractice) {
+ if (targetHoursRemaining != that.targetHoursRemaining) {
return false;
}
if (targetHours != that.targetHours) {
@@ -231,7 +233,7 @@ public int hashCode() {
result = 31 * result + lectures.hashCode();
result = 31 * result + reason.hashCode();
//result = 31 * result + latestEntryDate.hashCode();
- result = 31 * result + targetHourPractice;
+ result = 31 * result + targetHoursRemaining;
result = 31 * result + targetHours;
result = 31 * result + targetHoursCompleted;
result = 31 * result + targetHoursRemoved;
diff --git a/src/main/java/org/catrobat/jira/timesheet/rest/json/JsonUserInformation.java b/src/main/java/org/catrobat/jira/timesheet/rest/json/JsonUserInformation.java
index 95581a4..d4caa50 100644
--- a/src/main/java/org/catrobat/jira/timesheet/rest/json/JsonUserInformation.java
+++ b/src/main/java/org/catrobat/jira/timesheet/rest/json/JsonUserInformation.java
@@ -57,11 +57,10 @@ public JsonUserInformation (Timesheet timesheet) {
this.state = timesheet.getState();
this.latestEntryDate = timesheet.getLatestEntryBeginDate();
- this.remainingHours = (timesheet.getTargetHours() - timesheet.getHoursCompleted()
- + timesheet.getHoursDeducted());
this.targetTotalHours = timesheet.getTargetHours();
+ this.totalHours = timesheet.getHoursCompleted() - timesheet.getHoursDeducted();
+ this.remainingHours = this.targetTotalHours - this.totalHours;
- this.totalHours = timesheet.getHoursCompleted();
this.email = ComponentAccessor.getUserManager().getUserByKey(timesheet.getUserKey()).getEmailAddress();
this.timesheetID = timesheet.getID();
diff --git a/src/main/resources/css/timesheet.css b/src/main/resources/css/timesheet.css
index 2a9537b..64e4d39 100644
--- a/src/main/resources/css/timesheet.css
+++ b/src/main/resources/css/timesheet.css
@@ -215,3 +215,14 @@ code {
color: forestgreen;
margin-left: 6px;
}
+
+#edit-subtracted-hours{
+ cursor: pointer;
+ margin-left: 6px;
+}
+
+#submit-subtracted-hours{
+ cursor: pointer;
+ color: forestgreen;
+ margin-left: 6px;
+}
diff --git a/src/main/resources/js/timesheet.js b/src/main/resources/js/timesheet.js
index a670e50..d6b8ba8 100644
--- a/src/main/resources/js/timesheet.js
+++ b/src/main/resources/js/timesheet.js
@@ -94,13 +94,14 @@ AJS.toInit(function () {
timesheetID: existingTimesheetData.timesheetID,
lectures: lectures,
reason: AJS.$("#timesheet-substract-hours-text").val(),
- targetHourPractice: toFixed(AJS.$("#timesheet-hours-practical").val(), 2),
- targetHours: AJS.$("#timesheet-hours-text").val(),
- targetHoursCompleted: toFixed(AJS.$("#timesheet-hours-practical").val() - AJS.$("#timesheet-hours-substract").val(), 2),
+ targetHourPractice: toFixed(AJS.$("#timesheet-finished-hours").val(), 2),
+ targetHours: AJS.$("#timesheet-target-hours").val(),
+ targetHoursCompleted: toFixed(AJS.$("#timesheet-finished-hours").val() - AJS.$("#timesheet-hours-substract").val(), 2),
targetHoursRemoved: toFixed(AJS.$("#timesheet-hours-substract").val(), 2),
firstEntryDate: existingTimesheetData.firstEntryDate,
latestEntryDate: existingTimesheetData.latestEntryDate,
- state: existingTimesheetData.state
+ state: existingTimesheetData.state,
+ targetHoursRemaining: existingTimesheetData.targetHoursRemaining
};
var timesheetUpdated = AJS.$.ajax({
@@ -235,7 +236,7 @@ function projectedFinishDate(timesheetData, entryData) {
var entries = entryData[0];
var rem = timesheet.targetHours - timesheet.targetHoursCompleted + timesheet.targetHoursRemoved;
if (rem <= 0) {
- AJS.$("#timesheet-finish-date").val(new Date().toLocaleDateString("en-US"));
+ AJS.$("#timesheet-projected-finish").val(new Date().toLocaleDateString("en-US"));
return;
// already finished...
}
@@ -249,14 +250,14 @@ function projectedFinishDate(timesheetData, entryData) {
}
}
if(sumLast30Days === 0) {
- AJS.$("#timesheet-finish-date").val("Not enough entries to compute");
+ AJS.$("#timesheet-projected-finish").val("Not enough entries to compute");
return;
}
var hoursLast30Days = sumLast30Days / (1000 * 60 * 60);
var remDays = rem * 30 / hoursLast30Days;
var finishDate = new Date();
finishDate.setDate(finishDate.getDate() + remDays);
- AJS.$("#timesheet-finish-date").val(finishDate.toLocaleDateString("en-US"));
+ AJS.$("#timesheet-projected-finish").val(finishDate.toLocaleDateString("en-US"));
}
function setOwnerLabel(timesheet) {
diff --git a/src/main/resources/js/timesheet/functions.js b/src/main/resources/js/timesheet/functions.js
index 07254fe..74de93e 100644
--- a/src/main/resources/js/timesheet/functions.js
+++ b/src/main/resources/js/timesheet/functions.js
@@ -67,29 +67,27 @@ function calculateTime(timesheetData) {
function initTimesheetInformationValues(timesheetData) {
+ var remaining_hours_rounded = toFixed(timesheetData.targetHoursRemaining, 2)
+ var finished_hours_rounded = toFixed(timesheetData.targetHoursCompleted, 2)
var target_hours_rounded = toFixed(timesheetData.targetHours, 2);
- var hours_done_rounded = toFixed(timesheetData.targetHoursCompleted, 2)
- + toFixed(timesheetData.targetHoursRemoved, 2);
- setProgressBar(target_hours_rounded, hours_done_rounded);
+ setProgressBar(target_hours_rounded, finished_hours_rounded);
- AJS.$("#timesheet-hours-text").val(target_hours_rounded);
- AJS.$("#timesheet-hours-ects").val(timesheetData.ects);
- AJS.$("#timesheet-hours-practical").val(toFixed(calculateTime(timesheetData), 2));
-
- AJS.$("#timesheet-hours-remain").val(toFixed(timesheetData.targetHours
- - AJS.$("#timesheet-hours-practical").val() - timesheetData.targetHoursRemoved, 2));
+ AJS.$("#timesheet-remaining-hours").val(remaining_hours_rounded);
+ AJS.$("#timesheet-finished-hours").val(finished_hours_rounded);
+ AJS.$("#timesheet-target-hours").val(target_hours_rounded);
+ AJS.$("#timesheet-subtracted-hours").val(toFixed(timesheetData.targetHoursRemoved, 2));
+ AJS.$("#timesheet-subtracted-hours-text").val(timesheetData.reason);
AJS.$("#edit-total-hours").on("click", function (e) {
- AJS.$("#timesheet-hours-text").removeAttr("disabled");
+ AJS.$("#timesheet-target-hours").removeAttr("disabled");
AJS.$("#submit-total-hours").css("visibility" , "visible");
});
AJS.$("#submit-total-hours").on("click", function (e) {
console.log("submitting new total hours");
var value;
- AJS.$("#timesheet-hours-text").val() === "" ? value = 0 : value = AJS.$("#timesheet-hours-text").val();
-
+ AJS.$("#timesheet-target-hours").val() === "" ? value = 0 : value = AJS.$("#timesheet-target-hours").val();
AJS.$.ajax({
url : restBaseUrl + "updateTotalTargetHours/" + value,
type : "POST",
@@ -104,12 +102,53 @@ function initTimesheetInformationValues(timesheetData) {
updateCurrentTimesheetData(data);
updateProgressBar();
- updateTimesheetInformationValues(timesheetData_);
+ initTimesheetInformationValues(timesheetData_);
- AJS.$("#timesheet-hours-text").attr("disabled", "disabled");
+ AJS.$("#timesheet-target-hours").attr("disabled", "disabled");
AJS.$("#submit-total-hours").css("visibility" , "hidden");
},
- fail : function (err) {
+ error : function (err) {
+ AJS.messages.error({
+ title : "Error",
+ body : "Reason: " + err.responseText,
+ fadeout: true,
+ delay: 3000,
+ duration: 3000
+ })
+ }
+ });
+ });
+
+ AJS.$("#edit-subtracted-hours").on("click", function (e) {
+ AJS.$("#timesheet-subtracted-hours").removeAttr("disabled");
+ AJS.$("#submit-subtracted-hours").css("visibility" , "visible");
+ });
+
+ AJS.$("#submit-subtracted-hours").on("click", function (e) {
+ console.log("submitting new subtracted hours");
+ var value;
+ AJS.$("#timesheet-subtracted-hours").val() === "" ? value = 0 : value = AJS.$("#timesheet-subtracted-hours").val();
+
+ AJS.$.ajax({
+ url : restBaseUrl + "updateSubtractedHours/" + value,
+ type : "POST",
+ success : function (data) {
+ AJS.messages.success({
+ title : "Success",
+ body :"
Your data has been updated",
+ fadeout: true,
+ delay: 3000,
+ duration: 3000
+ });
+
+ updateCurrentTimesheetData(data);
+ updateProgressBar();
+ initTimesheetInformationValues(timesheetData_);
+
+ AJS.$("#timesheet-subtracted-hours").attr("disabled", "disabled");
+ AJS.$("#submit-subtracted-hours").css("visibility" , "hidden");
+ },
+ error : function (err) {
AJS.messages.error({
title : "Error",
body : "Reason: " + err.responseText,
@@ -121,6 +160,9 @@ function initTimesheetInformationValues(timesheetData) {
});
});
+ AJS.$("#timesheet-target-hours").attr("disabled", "disabled");
+ AJS.$("#timesheet-subtracted-hours").attr("disabled", "disabled");
+
AJS.$("#lectures-container").empty();
var lectures = timesheetData.lectures;
var splitted = lectures.split("@/@");
@@ -154,38 +196,9 @@ function initTimesheetInformationValues(timesheetData) {
showLectureDeletionDialog(data);
});
- if (isAdmin) {
- AJS.$("#substractTimesheetHours").empty();
- AJS.$("#substractTimesheetHours").append("