Skip to content

Commit

Permalink
Merge pull request #19 from 42-Heilbronn/14-remove-missing-feedbacks-…
Browse files Browse the repository at this point in the history
…after-request-or-duration

14 remove missing feedbacks after request or duration
  • Loading branch information
eschirni authored Sep 20, 2023
2 parents 58c6a65 + 58b50d7 commit e1f2ea4
Show file tree
Hide file tree
Showing 8 changed files with 184 additions and 32 deletions.
22 changes: 21 additions & 1 deletion backend/src/api/feedback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ pub fn init(cfg: &mut web::ServiceConfig) {
.service(
web::resource("/{feedback_id}/info").route(web::get().to(evaluation_feedback_info)),
)
.service(web::resource("/{feedback_id}/ignore").route(web::post().to(ignore_feedback)))
.service(web::resource("/{feedback_id}").route(web::post().to(post_feedback))),
);
}
Expand All @@ -41,7 +42,11 @@ async fn missing_feedback(id: Identity, db: web::Data<Database>) -> Result<HttpR
let missing_feedback = db
.get_missing_evaluation_feedbacks_from_user(user_id)
.await?;
log::debug!("for user: {}, found feedbacks {:?}", user_id, missing_feedback);
log::debug!(
"for user: {}, found feedbacks {:?}",
user_id,
missing_feedback
);
let missing_feedback: Vec<FeedbackListEntry> = missing_feedback
.into_iter()
.map(|(feedback, evaluation)| FeedbackListEntry {
Expand Down Expand Up @@ -155,3 +160,18 @@ async fn post_feedback(
db.update_evaluation_feedback(feedback).await?;
Ok(HttpResponse::Ok().finish())
}

async fn ignore_feedback(
id: Identity,
db: web::Data<Database>,
feedback_id: web::Path<i32>
) -> Result<HttpResponse, ApiError> {
let user_id: i32 = id.id().unwrap().parse::<i32>().unwrap();
let mut feedback = db.get_evaluation_feedback(*feedback_id).await?;
if user_id.ne(&feedback.user_id) | feedback.feedback.is_some() {
return Err(ApiError::Unauthorized);
}
feedback.feedback_at = Some(chrono::Utc::now().naive_utc());
db.update_evaluation_feedback(feedback).await?;
Ok(HttpResponse::Ok().finish())
}
4 changes: 2 additions & 2 deletions backend/src/db/action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,9 @@ impl Database {
) -> anyhow::Result<Vec<(EvaluationFeedback, Evaluation)>> {
let feedback = evaluation_feedback::table
.inner_join(evaluation::table)
// .filter(evaluation::begin_at.le(Utc::now().naive_utc() - chrono::Duration::minutes(15)))
.filter(evaluation::begin_at.ge(Utc::now().naive_utc() - chrono::Duration::weeks(2)))
.filter(evaluation_feedback::user_id.eq(user_id))
.filter(evaluation_feedback::feedback.is_null())
.filter(evaluation_feedback::feedback_at.is_null())
.get_results(&mut self.pool.get().await?)
.await?;
Ok(feedback)
Expand Down
69 changes: 59 additions & 10 deletions frontend/chrome/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ class EvalInfo
this.peer = peer; //peer object from get request
this.eval_slot; //the eval slot element created
this.popup; //the popup element created
this.ignore; //the ignore popup created
}
}

Expand Down Expand Up @@ -51,13 +52,16 @@ function create_eval(id)

eval.innerHTML = `
<div class="project-item-text"></div>
<div class="project-item-actions"><a href="#">Give Feedback</a></div>`; //not just a, because that's also how intra42 does it
<div class="project-item-actions"><a class="missing-user" href="#" title="Skip feeback?"><span class="iconf-delete-2-1"></span></a><a href="#">Give Feedback</a></div>`;
eval.firstElementChild.innerText = `Please submit honest feedback for your eval with ${peer_name}`;
eval.lastElementChild.firstElementChild.addEventListener("click", function() {showPopup(id)});

eval.lastElementChild.lastElementChild.addEventListener("click", function() {showPopup(id)});
eval.lastElementChild.firstElementChild.addEventListener("click", function() {showIgnore(id)});

eval_list.appendChild(eval);
evals.get(id).eval_slot = eval;
create_popup(id, res.fields, res.evaluation.corrector);
create_ignore(id);
});
}

Expand All @@ -66,20 +70,20 @@ function create_popup(id, content, corrector)
{
let popup = document.createElement('div');

popup.style = "position: fixed; width: 100%; height: 100%; top: 0; left: 0; background: rgba(0,0,0,0.5); z-index: 9999; display: flex; justify-content: center; align-items: center;";
popup.style = "position: fixed; width: 100%; height: 100%; top: 0; left: 0; background: rgba(0,0,0,0.5); z-index: 9999; display: flex; justify-content: center; align-items: center; visibility: hidden;";
popup.innerHTML = `
<form style="padding: 20px; width: 400px; border-radius: 8px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2); display: flex; flex-direction: column; gap: 20px; position: relative;">
<span class="iconf-delete-2-1" style="position: absolute; top: 20px; right: 20px; color: red; cursor: pointer;"></span>
<h1></h1>
<h1 style="text-align: left;"></h1>
<div style="display: flex; flex-direction: column; gap: 10px;"></div>
<span class="btn btn-primary" style="margin: 0 auto; border-radius: 5px; font-size: 17px; padding: 6px 18px;">Submit</span>
</form>`;

popup.firstElementChild.classList.add("container-item");
if (corrector == intra_name)
popup.firstElementChild.firstElementChild.nextElementSibling.innerText = `🔊 Feedback for ${evals.get(id).peer.team} 🔊`;
popup.firstElementChild.firstElementChild.nextElementSibling.innerText = `Feedback for ${evals.get(id).peer.team}`;
else
popup.firstElementChild.firstElementChild.nextElementSibling.innerText = `🔊 Feedback for ${corrector} 🔊`;
popup.firstElementChild.firstElementChild.nextElementSibling.innerText = `Feedback for ${corrector}`;

content.forEach(element => {
if (element.data_type.Range != null)
Expand All @@ -92,7 +96,6 @@ function create_popup(id, content, corrector)
popup.firstElementChild.lastElementChild.addEventListener("click", function() {submitForm(id)});

document.body.appendChild(popup);
popup.style.visibility = "hidden";
evals.get(id).popup = popup;
}

Expand Down Expand Up @@ -151,6 +154,29 @@ function create_textarea(content, content_div)
content_div.appendChild(textarea);
}

function create_ignore(id)
{
let popup = document.createElement('div');

popup.style = "position: fixed; width: 100%; height: 100%; top: 0; left: 0; background: rgba(0,0,0,0.5); z-index: 9999; display: flex; justify-content: center; align-items: center; visibility: hidden;";
popup.innerHTML = `
<div class="modal-dialog">
<h4 style="margin-top: 0px; padding-top: 0px;">Are you sure you don't want to submit any feedback?</h4>
<div class="modal-footer" style="padding-bottom: 0px;">
<span class="btn btn-default">Cancel</span>
<span class="btn btn-danger">Submit no feedback</span>
</div>
</div>`;

popup.firstElementChild.classList.add("container-item");

popup.firstElementChild.lastElementChild.firstElementChild.addEventListener("click", function() {showIgnore(id)});
popup.firstElementChild.lastElementChild.lastElementChild.addEventListener("click", function() {ignoreFeedback(id)});

document.body.appendChild(popup);
evals.get(id).ignore = popup;
}

//creates, hides or shows popup
function showPopup(id)
{
Expand All @@ -160,6 +186,14 @@ function showPopup(id)
evals.get(id).popup.style.visibility = "hidden";
}

function showIgnore(id)
{
if (evals.get(id).ignore.style.visibility == "hidden")
evals.get(id).ignore.style.visibility = "visible";
else
evals.get(id).ignore.style.visibility = "hidden";
}

//extracts and POSTs data to the server
//slider values will be converted to integers
//deletes all the elements afterwards
Expand All @@ -179,8 +213,23 @@ function submitForm(id)

chrome.runtime.sendMessage({uri :`/feedback/${id}`, form: data}).then(function (res)
{
evals.get(id).eval_slot.remove();
evals.get(id).popup.remove();
evals.delete(id);
finishFeedback(id);
});
}

function ignoreFeedback(id)
{
chrome.runtime.sendMessage({uri :`/feedback/${id}/ignore`}).then(function (res)
{
finishFeedback(id);
});
}

//clears everything connected to a feedback element saved in evals
function finishFeedback(id)
{
evals.get(id).eval_slot.remove();
evals.get(id).popup.remove();
evals.get(id).ignore.remove();
evals.delete(id);
}
2 changes: 1 addition & 1 deletion frontend/chrome/manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"manifest_version": 3,
"name": "True Feedback",
"version": "1.1",
"version": "1.2",
"description": "Private feedback for evaluations on intra.42.fr",

"icons": {
Expand Down
15 changes: 15 additions & 0 deletions frontend/chrome/requests.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
return get_missing(sendResponse);
else if (request.uri.endsWith("info"))
return get_details(request.uri, sendResponse);
else if (request.uri.endsWith("/ignore"))
return send_ignore(request.uri, sendResponse);
else if (request.uri.startsWith("/feedback"))
return send_feedback(request.uri, request.form, sendResponse);
console.log(request);
Expand All @@ -35,6 +37,19 @@ function get_details(uri, sendResponse)
return true;
}

function send_ignore(uri, sendResponse)
{
fetch(`${SERVER_IP}${uri}`, {
method: "POST",
body: JSON.stringify({ }),
headers: {
"Content-type": "application/json; charset=UTF-8"
}
})
.then(sendResponse(null));
return true;
}

function send_feedback(uri, data, sendResponse)
{
fetch(`${SERVER_IP}${uri}`, {
Expand Down
69 changes: 59 additions & 10 deletions frontend/firefox/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ class EvalInfo
this.peer = peer; //peer object from get request
this.eval_slot; //the eval slot element created
this.popup; //the popup element created
this.ignore; //the ignore popup created
}
}

Expand Down Expand Up @@ -51,13 +52,16 @@ function create_eval(id)

eval.innerHTML = `
<div class="project-item-text"></div>
<div class="project-item-actions"><a href="#">Give Feedback</a></div>`; //not just a, because that's also how intra42 does it
<div class="project-item-actions"><a class="missing-user" href="#" title="Skip feeback?"><span class="iconf-delete-2-1"></span></a><a href="#">Give Feedback</a></div>`;
eval.firstElementChild.innerText = `Please submit honest feedback for your eval with ${peer_name}`;
eval.lastElementChild.firstElementChild.addEventListener("click", function() {showPopup(id)});

eval.lastElementChild.lastElementChild.addEventListener("click", function() {showPopup(id)});
eval.lastElementChild.firstElementChild.addEventListener("click", function() {showIgnore(id)});

eval_list.appendChild(eval);
evals.get(id).eval_slot = eval;
create_popup(id, res.fields, res.evaluation.corrector);
create_ignore(id);
});
}

Expand All @@ -66,20 +70,20 @@ function create_popup(id, content, corrector)
{
let popup = document.createElement('div');

popup.style = "position: fixed; width: 100%; height: 100%; top: 0; left: 0; background: rgba(0,0,0,0.5); z-index: 9999; display: flex; justify-content: center; align-items: center;";
popup.style = "position: fixed; width: 100%; height: 100%; top: 0; left: 0; background: rgba(0,0,0,0.5); z-index: 9999; display: flex; justify-content: center; align-items: center; visibility: hidden;";
popup.innerHTML = `
<form style="padding: 20px; width: 400px; border-radius: 8px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2); display: flex; flex-direction: column; gap: 20px; position: relative;">
<span class="iconf-delete-2-1" style="position: absolute; top: 20px; right: 20px; color: red; cursor: pointer;"></span>
<h1></h1>
<h1 style="text-align: left;"></h1>
<div style="display: flex; flex-direction: column; gap: 10px;"></div>
<span class="btn btn-primary" style="margin: 0 auto; border-radius: 5px; font-size: 17px; padding: 6px 18px;">Submit</span>
</form>`;

popup.firstElementChild.classList.add("container-item");
if (corrector == intra_name)
popup.firstElementChild.firstElementChild.nextElementSibling.innerText = `🔊 Feedback for ${evals.get(id).peer.team} 🔊`;
popup.firstElementChild.firstElementChild.nextElementSibling.innerText = `Feedback for ${evals.get(id).peer.team}`;
else
popup.firstElementChild.firstElementChild.nextElementSibling.innerText = `🔊 Feedback for ${corrector} 🔊`;
popup.firstElementChild.firstElementChild.nextElementSibling.innerText = `Feedback for ${corrector}`;

content.forEach(element => {
if (element.data_type.Range != null)
Expand All @@ -92,7 +96,6 @@ function create_popup(id, content, corrector)
popup.firstElementChild.lastElementChild.addEventListener("click", function() {submitForm(id)});

document.body.appendChild(popup);
popup.style.visibility = "hidden";
evals.get(id).popup = popup;
}

Expand Down Expand Up @@ -151,6 +154,29 @@ function create_textarea(content, content_div)
content_div.appendChild(textarea);
}

function create_ignore(id)
{
let popup = document.createElement('div');

popup.style = "position: fixed; width: 100%; height: 100%; top: 0; left: 0; background: rgba(0,0,0,0.5); z-index: 9999; display: flex; justify-content: center; align-items: center; visibility: hidden;";
popup.innerHTML = `
<div class="modal-dialog">
<h4 style="margin-top: 0px; padding-top: 0px;">Are you sure you don't want to submit any feedback?</h4>
<div class="modal-footer" style="padding-bottom: 0px;">
<span class="btn btn-default">Cancel</span>
<span class="btn btn-danger">Submit no feedback</span>
</div>
</div>`;

popup.firstElementChild.classList.add("container-item");

popup.firstElementChild.lastElementChild.firstElementChild.addEventListener("click", function() {showIgnore(id)});
popup.firstElementChild.lastElementChild.lastElementChild.addEventListener("click", function() {ignoreFeedback(id)});

document.body.appendChild(popup);
evals.get(id).ignore = popup;
}

//creates, hides or shows popup
function showPopup(id)
{
Expand All @@ -160,6 +186,14 @@ function showPopup(id)
evals.get(id).popup.style.visibility = "hidden";
}

function showIgnore(id)
{
if (evals.get(id).ignore.style.visibility == "hidden")
evals.get(id).ignore.style.visibility = "visible";
else
evals.get(id).ignore.style.visibility = "hidden";
}

//extracts and POSTs data to the server
//slider values will be converted to integers
//deletes all the elements afterwards
Expand All @@ -179,8 +213,23 @@ function submitForm(id)

browser.runtime.sendMessage({uri :`/feedback/${id}`, form: data}).then(function (res)
{
evals.get(id).eval_slot.remove();
evals.get(id).popup.remove();
evals.delete(id);
finishFeedback(id);
});
}

function ignoreFeedback(id)
{
browser.runtime.sendMessage({uri :`/feedback/${id}/ignore`}).then(function (res)
{
finishFeedback(id);
});
}

//clears everything connected to a feedback element saved in evals
function finishFeedback(id)
{
evals.get(id).eval_slot.remove();
evals.get(id).popup.remove();
evals.get(id).ignore.remove();
evals.delete(id);
}
19 changes: 11 additions & 8 deletions frontend/firefox/manifest.json
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
{
"manifest_version": 3,
"name": "True Feedback",
"version": "1.1",
"version": "1.2",
"description": "Private feedback for evaluations on intra.42.fr",

"browser_specific_settings": {
"gecko": {
"id": "[email protected]",
"strict_min_version": "109.0",
"update_url": "https://dev01.playground.extension.cdn.42heilbronn.de/update.json"
}
},
"icons": {
"48": "icons/48.png",
"96": "icons/96.png"
},

"host_permissions": [
"https://dev01.playground.extension.42heilbronn.de/*",
"https://*.intra.42.fr/*"
"https://*.intra.42.fr/*"
],

"content_scripts": [
{
"matches": ["https://profile.intra.42.fr/*"],
Expand All @@ -26,8 +30,7 @@
"run_at": "document_end"
}
],

"background": {
"scripts": ["requests.js"]
}
}
}
}
Loading

0 comments on commit e1f2ea4

Please sign in to comment.