Skip to content
Snippets Groups Projects
Commit 55d67880 authored by Martin Staehr's avatar Martin Staehr
Browse files

#95 adding ability for student to see portfolio entries based on visibility

parent 27184ede
No related branches found
No related tags found
No related merge requests found
Showing
with 368 additions and 88 deletions
......@@ -74,7 +74,7 @@ public class SubmissionController implements ISubmission, HasProgress {
//
String request = String.join(" ", requestCommand.trim(),
//String request = "INSERT INTO "+
"fullsubmissions (`id`, `version`, `groupId`, `text`, `projectName`, `fileRole`, `visibility`) VALUES (?,?,?,?,?,?,?);");
"fullsubmissions (`id`, `version`, `groupId`, `text`, `projectName`, `fileRole`, `userEmail`, `visibility`) VALUES (?,?,?,?,?,?,?,?);");
connection.connect();
// build and execute request
......@@ -83,6 +83,7 @@ public class SubmissionController implements ISubmission, HasProgress {
fullSubmissionPostRequest.getText(),
fullSubmissionPostRequest.getProjectName(),
fullSubmissionPostRequest.getFileRole().toString(),
fullSubmissionPostRequest.getUserEMail(),
fullSubmissionPostRequest.getVisibility().toString()
);
......@@ -97,7 +98,23 @@ public class SubmissionController implements ISubmission, HasProgress {
@Override
public FullSubmission getFullSubmission(String fullSubmissionId) {
return getFullSubmission(fullSubmissionId, 0);
// establish connection
connection.connect();
FullSubmission fullSubmission = null;
// build and execute request
String request = "SELECT * FROM fullsubmissions WHERE id = ?;";
VereinfachtesResultSet rs = connection.issueSelectStatement(request, fullSubmissionId);
if (rs.next()) {
// save submission
fullSubmission = getFullSubmissionFromResultSet(rs);
}
connection.close();
return fullSubmission;
}
@Override
......@@ -122,8 +139,35 @@ public class SubmissionController implements ISubmission, HasProgress {
return fullSubmission;
}
public List<FullSubmission> getPersonalSubmissions(User user, Project project, FileRole fileRole) {
List<FullSubmission> fullSubmissionList = null;
connection.connect();
String request = "SELECT * FROM fullsubmissions WHERE userEmail = ? AND projectName= ? AND fileRole = ?;";
VereinfachtesResultSet rs = connection.issueSelectStatement(request, user.getEmail(), project.getName(), fileRole);
while (rs.next()) {
if (fullSubmissionList == null) {
fullSubmissionList = new ArrayList<>();
}
fullSubmissionList.add(getFullSubmissionFromResultSet(rs));
}
connection.close();
return fullSubmissionList;
}
public FullSubmission getFullSubmissionBy(int groupId, Project project, FileRole fileRole) {
return getFullSubmissionBy(groupId, project, fileRole, 0);
FullSubmission fullSubmission = null;
connection.connect();
String request = "SELECT * FROM fullsubmissions WHERE groupId = ? AND projectName= ? AND fileRole = ?;";
VereinfachtesResultSet rs = connection.issueSelectStatement(request, groupId, project.getName(), fileRole);
if (rs.next()) {
fullSubmission = getFullSubmissionFromResultSet(rs);
}
connection.close();
return fullSubmission;
}
public FullSubmission getFullSubmissionBy(int groupId, Project project, FileRole fileRole, Integer version) {
......@@ -141,6 +185,30 @@ public class SubmissionController implements ISubmission, HasProgress {
return fullSubmission;
}
public List<FullSubmission> getGroupSubmissions(Project project, int groupId, FileRole fileRole, Visibility visibility) {
List<FullSubmission> fullSubmissionList = new ArrayList<>();
connection.connect();
String query = "SELECT * FROM fullsubmissions WHERE groupId = ? AND projectName= ? AND fileRole = ? and visibility = ?;";
VereinfachtesResultSet rs = connection.issueSelectStatement(query, groupId, project.getName(), fileRole.name(), visibility.name());
while (rs.next()) {
fullSubmissionList.add(getFullSubmissionFromResultSet(rs));
}
return fullSubmissionList;
}
public List<FullSubmission> getPublicSubmissions(Project project, FileRole fileRole) {
List<FullSubmission> fullSubmissionList = new ArrayList<>();
connection.connect();
String query = "SELECT * FROM fullsubmissions WHERE projectName= ? AND fileRole = ? and visibility = ?;";
VereinfachtesResultSet rs = connection.issueSelectStatement(query, project.getName(), fileRole.name(), Visibility.PUBLIC.name());
while (rs.next()) {
fullSubmissionList.add(getFullSubmissionFromResultSet(rs));
}
return fullSubmissionList;
}
public String getFullSubmissionId(Integer groupId, Project project, FileRole fileRole) {
return getFullSubmissionId(groupId, project, fileRole, 0);
}
......
......@@ -5,6 +5,7 @@ import unipotsdam.gf.modules.annotation.model.Category;
import unipotsdam.gf.modules.assessment.controller.model.Categories;
import unipotsdam.gf.modules.fileManagement.FileManagementService;
import unipotsdam.gf.modules.fileManagement.FileRole;
import unipotsdam.gf.modules.group.GroupDAO;
import unipotsdam.gf.modules.project.Project;
import unipotsdam.gf.modules.submission.controller.SubmissionController;
import unipotsdam.gf.modules.submission.model.FullSubmission;
......@@ -62,6 +63,8 @@ public class SubmissionService {
@Inject
private FileManagementService fileManagementService;
@Inject
private GroupDAO groupDAO;
@POST
@Path("/full")
......@@ -241,4 +244,41 @@ public class SubmissionService {
return Response.ok(visibilityButtonTextHashMap).build();
}
@GET
@Path("portfolio")
@Produces(MediaType.APPLICATION_JSON)
public Response getPortfolioEntries(@Context HttpServletRequest req, @QueryParam("projectName") String projectName, @QueryParam("visibility") Visibility visibility) {
String userEmail;
try {
userEmail = gfContexts.getUserEmail(req);
} catch (IOException e) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity("userEmail not found in context").build();
}
Project project = new Project(projectName);
User user = new User(userEmail);
int groupId = groupDAO.getMyGroupId(user, project);
List<FullSubmission> fullSubmissionList = new ArrayList<>();
switch (visibility) {
case DOCENT:
break;
case GROUP:
fullSubmissionList = submissionController.getGroupSubmissions(project, groupId, FileRole.PORTFOLIO, visibility);
break;
case PUBLIC:
fullSubmissionList = submissionController.getPublicSubmissions(project, FileRole.PORTFOLIO);
break;
case PERSONAL:
fullSubmissionList = submissionController.getPersonalSubmissions(user, project, FileRole.PORTFOLIO);
}
if (fullSubmissionList.isEmpty()) {
return Response.status(Response.Status.NOT_FOUND).entity("No portfolio entries found").build();
}
return Response.ok(fullSubmissionList).build();
}
}
......@@ -30,6 +30,7 @@
<!-- css - upload-unstructured -->
<link rel="stylesheet" type="text/css" href="../taglibs/css/unstructured-upload.css">
<link rel="stylesheet" type="text/css" href="../taglibs/css/visibilityButton.css">
<script src="../taglibs/js/utility.js"></script>
<!-- js - unstructuredUpload -->
......@@ -37,6 +38,8 @@
<!-- js - unstructuredRest -->
<script src="../taglibs/js/unstructuredRest.js"></script>
<script src="../taglibs/js/visibilityButton.js"></script>
<!-- jsrender -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jsrender/1.0.3/jsrender.min.js"></script>
......@@ -57,10 +60,15 @@
<main>
<div class="row group">
<div class="col span_content span_l_of_2">
<div id="templateResult"></div>
<script id="visibilityTemplate" type="text/x-jsrender">
<div id="headerTemplateResult"></div>
<script id="headerTemplate" type="text/x-jsrender">
<div></div>
<h2>{{:header}} anlegen</h2>
</script>
<div id="visibilityTemplateResult"></div>
<script id="visibilityTemplate" type="text/x-jsrender">
<div></div>
{{if fileRole == "Portfolio"}}
<div class="dropdown">
<button class="dropbtn btn btn-primary" onclick="dropDownClick()">Sichtbarkeit: {{:currentVisibility.buttonText}}
......@@ -68,7 +76,7 @@
</button>
<div class="dropdown-content" id="myDropdown">
{{for possibleVisibilities}}
<a id={{:name}} onclick='visibilityDropDownClicked("{{:name}}")'>{{:buttonText}}</a>
<a id={{:name}} onclick='changeButtonText("{{:name}}")'>{{:buttonText}}</a>
{{/for}}
</div>
</div>
......
.creation-information {
float: right;
display: inline-flex;
}
let projectName;
let possibleVisibilities = [];
let currentVisibility;
$(document).ready(function () {
projectName = $('#projectName').html().trim();
setupVisibilityButton();
});
function setupVisibilityButton() {
getVisibilities(true, function (response) {
Object.entries(response).forEach(([name, buttonText]) => {
possibleVisibilities[name] = {name: name, buttonText: buttonText};
});
currentVisibility = possibleVisibilities['PERSONAL'];
let data = {};
data.possibleVisibilities = Object.values(possibleVisibilities);
data.currentVisibility = currentVisibility;
let tmpl = $.templates("#visibilityTemplate");
let html = tmpl.render(data);
$("#visibilityTemplateResult").html(html);
fillPortfolioEntries();
});
}
function fillPortfolioEntries() {
let queryParams = {
projectName: projectName,
visibility: currentVisibility.name
};
getPortfolioSubmissions(queryParams, function (response) {
let data = {};
data.scriptBegin = '<script>';
data.scriptEnd = '</script>';
for (let element of response) {
element.scriptBegin = data.scriptBegin;
element.scriptEnd = data.scriptEnd;
element.timestamp = new Date(element.timestamp).toLocaleString();
}
data.submissionList = response;
data.error = response.error;
let tmpl = $.templates("#portfolioTemplate");
let html = tmpl.render(data);
$("#portfolioTemplateResult").html(html);
});
}
function visibilityButtonPressed(pressedButton) {
changeButtonText(pressedButton, fillPortfolioEntries);
}
\ No newline at end of file
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%--<%@ taglib uri="../taglibs/gemeinsamForschen.tld" prefix="chat" %>--%>
<!DOCTYPE html>
<html>
<head>
<jsp:include page="../taglibs/omniDependencies.jsp">
<jsp:param name="hierarchy" value="1"/>
</jsp:include>
<jsp:include page="../taglibs/quillJsDependencies.jsp"/>
<link rel="stylesheet" type="text/css" href="../taglibs/css/visibilityButton.css">
<link rel="stylesheet" type="text/css" href="css/show-portfolio.css">
<!-- js - jQuery ui position -->
<script src="../libs/jquery/jqueryUI.js" type="text/javascript"></script>
<!-- jsrender -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jsrender/1.0.3/jsrender.min.js"></script>
<!-- js - unstructuredRest -->
<script src="../taglibs/js/unstructuredRest.js"></script>
<script src="js/portfolio.js"></script>
<script src="../taglibs/js/visibilityButton.js"></script>
</head>
<body>
<div id="flex-wrapper">
<jsp:include page="../taglibs/Menu.jsp">
<jsp:param name="hierarchy" value="1"/>
</jsp:include>
<main>
<div class="row group">
<h1>E-Portfolio</h1>
<div id="visibilityTemplateResult"></div>
<script id="visibilityTemplate" type="text/x-jsrender">
<div></div>
<h4>Wähle, welche Beiträge du sehen möchtest</h4>
<div class="dropdown">
<button class="dropbtn btn btn-primary" onclick="dropDownClick()">{{:currentVisibility.buttonText}}
<i class="fa fa-caret-down"></i>
</button>
<div class="dropdown-content" id="myDropdown">
{{for possibleVisibilities}}
<a id={{:name}} onclick='visibilityButtonPressed("{{:name}}")'>{{:buttonText}}</a>
{{/for}}
</div>
</div>
</script>
<h3>Einträge</h3>
<div id="portfolioTemplateResult"></div>
<script id="portfolioTemplate" type="text/x-jsrender">
<div></div>
{{for submissionList}}
<br/>
<div id="editor-{{:id}}"></div>
{{:scriptBegin}}
new Quill('#editor-{{:id}}', {
theme: 'snow',
readOnly: true,
"modules": {
"toolbar": false
}
}).setContents({{:text}});
{{:scriptEnd}}
<h4 class="creation-information">{{:userEmail}} - {{:timestamp}}</h4>
<br/>
{{/for}}
{{if error}}
<h1>Keine Einträge gefunden</h1>
{{/if}}
</script>
</div> <!-- flex wrapper -->
</main>
<jsp:include page="../taglibs/footer.jsp"/>
</body>
</html>
......@@ -25,6 +25,10 @@
<a class="nav-link"
href="<%= hierarchyLevel%>project/overview-docent.jsp">Projekte</a>
<% } %>
<% if (projectName != null) {%>
<a class="nav-link"
href="<%=hierarchyLevel%>portfolio/show-portfolio.jsp?projectName=<%=projectName%>">E-Portfolio</a>
<% } %>
<!--<a class="nav-link" href="<%= hierarchyLevel%>profile/profile.jsp?">Profil</a>-->
</div>
<div class="nav-group-right">
......
......@@ -70,43 +70,4 @@ label.error {
color: red;
}
.flex .container-fluid {
flex: 1;
}
.dropbtn {
cursor: pointer;
outline: none;
padding: 14px 16px;
font-family: inherit;
margin: 0;
}
.dropdown-content {
display: none;
position: absolute;
background-color: #f9f9f9;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
z-index: 1;
}
.dropdown-content a {
float: none;
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
text-align: left;
}
.dropdown-content a:hover {
background-color: #ddd;
}
.show {
display: block;
}
.flex .container-fluid {
flex: 1;
}
.dropbtn {
cursor: pointer;
outline: none;
padding: 14px 16px;
font-family: inherit;
margin: 0;
}
.dropdown-content {
display: none;
position: absolute;
background-color: #f9f9f9;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
z-index: 1;
}
.dropdown-content a {
float: none;
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
text-align: left;
cursor: pointer;
}
.dropdown-content a:hover {
background-color: #ddd;
}
.show {
display: block;
}
......@@ -161,11 +161,8 @@ function getAnnotationCategories(callback) {
})
}
function getVisibilities(callback) {
if (personal == null) {
personal = false;
}
let url = baseSubmissionUrl + "visibilities/personal/" + $('#personal').html().trim();
function getVisibilities(personal, callback) {
let url = baseSubmissionUrl + "visibilities/personal/" + personal;
$.ajax({
url: url,
type: "GET",
......@@ -178,4 +175,25 @@ function getVisibilities(callback) {
console.log("error loading visibilities");
}
})
}
function getPortfolioSubmissions(queryParams, callback) {
let url = baseSubmissionUrl + "portfolio?" + $.param({
projectName: queryParams.projectName,
visibility: queryParams.visibility
});
$.ajax({
url: url,
type: "GET",
dataType: "json",
success: function (response) {
// handle the response
callback(response);
},
error: function () {
let response = [];
response.error = true;
callback(response);
}
})
}
\ No newline at end of file
......@@ -11,6 +11,8 @@ let possibleVisibilities = [];
$(document).ready(function () {
fileRole = $('#fileRole').html().trim();
let personalString = $("#personal").html().trim();
personal = personalString.toUpperCase() === 'TRUE';
setupPageContent();
if (!personal) {
getMyGroupId(function (groupId) {
......@@ -75,11 +77,9 @@ $(document).ready(function () {
});
function setupPageContent() {
let personalString = $("#personal").html().trim();
personal = personalString.toUpperCase() === 'TRUE';
getVisibilities(function (response) {
populateHeaderTemplate();
getVisibilities(personal, function (response) {
Object.entries(response).forEach(([name, buttonText]) => {
possibleVisibilities[name] = {name: name, buttonText: buttonText};
});
......@@ -92,43 +92,20 @@ function setupPageContent() {
});
}
function populateHeaderTemplate() {
let data = {};
data.header = fileRole === "Portfolio" ? "Portfolio-Eintrag" : fileRole;
let tmpl = $.templates("#headerTemplate");
let html = tmpl.render(data);
$("#headerTemplateResult").html(html);
}
function populateTextFields() {
let data = {};
data.header = fileRole === "Portfolio" ? "Portfolio-Eintrag" : fileRole;
data.fileRole = fileRole;
data.possibleVisibilities = Object.values(possibleVisibilities);
data.currentVisibility = currentVisibility;
let tmpl = $.templates("#visibilityTemplate");
let html = tmpl.render(data);
$("#templateResult").html(html);
$("#visibilityTemplateResult").html(html);
}
function visibilityDropDownClicked(clickedItem) {
let dropBtn = $('.dropbtn');
let oldText = dropBtn.html();
let oldVisibility = currentVisibility;
currentVisibility = possibleVisibilities[clickedItem];
let newText = oldText.replace(oldVisibility.buttonText, currentVisibility.buttonText);
dropBtn.html(newText);
}
function dropDownClick() {
$('#myDropdown').toggleClass('show');
}
// close dropdown after clicking
window.onclick = function (e) {
if (fileRole === 'Portfolio') {
if (!e.target.matches('.dropbtn') && !e.target.matches('.fa-caret-down')) {
var myDropdown = document.getElementById("myDropdown");
if (myDropdown.classList.contains('show')) {
myDropdown.classList.remove('show');
}
}
}
};
function changeButtonText(clickedItem, callback) {
let dropBtn = $('.dropbtn');
let oldText = dropBtn.html();
let oldVisibility = currentVisibility;
currentVisibility = possibleVisibilities[clickedItem];
let newText = oldText.replace(oldVisibility.buttonText, currentVisibility.buttonText);
dropBtn.html(newText);
if (callback) {
callback();
}
}
function dropDownClick() {
$('#myDropdown').toggleClass('show');
}
// close dropdown after clicking
window.onclick = function (e) {
if (!e.target.matches('.dropbtn') && !e.target.matches('.fa-caret-down')) {
let myDropdown = document.getElementById("myDropdown");
if (myDropdown && myDropdown.classList.contains('show')) {
myDropdown.classList.remove('show');
}
}
};
\ No newline at end of file
......@@ -42,13 +42,13 @@ import static org.junit.Assert.assertTrue;
public class ActivityFlowTest {
private final ArrayList<User> students = new ArrayList<>();
private final Project project = factory.manufacturePojo(Project.class);
@Rule
public MockitoRule mockitoRule = MockitoJUnit.rule();
/**
* Utility to creaty dummy data for students
*/
PodamFactory factory = new PodamFactoryImpl();
@Rule
public MockitoRule mockitoRule = MockitoJUnit.rule();
private final Project project = factory.manufacturePojo(Project.class);
private final User teacher = factory.manufacturePojo(User.class);
@Inject
Management management;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment