Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

3609 large guestbooks #4057

Merged
merged 16 commits into from
Aug 22, 2017
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
4eb80d1
Reimplemented the download-guestbook-responses-as-CSV to use streaming.
landreev Aug 8, 2017
0dfe288
Further improved the performance of the guestbook-responses page, by …
landreev Aug 9, 2017
38af5c9
Finalized (hopefully) reworking of the view-and-download of collected…
landreev Aug 10, 2017
9b3fff0
fixed a small bug; changed the help message on the results page; bump…
landreev Aug 10, 2017
39fa4d5
Merge branch 'develop' into 3609-large-guestbooks
mheppler Aug 11, 2017
e3588d3
Cleaned up layout of various buttons, popups and text in Manage Datas…
mheppler Aug 14, 2017
a2b3b55
Cleaned up layout of warning msg in Guestbook Responses pgs. [ref #3609]
mheppler Aug 14, 2017
e940814
Edits to Guestbook messaging + warning [ref: #3609]
dlmurphy Aug 14, 2017
32be0cb
Made the guestbook-responses page viewable only to users with the edi…
landreev Aug 14, 2017
9dc46ae
Returned View Responses button to Guestbook pg. [ref #3609]
mheppler Aug 14, 2017
b05a026
Some extra cleanup/streamlining of code for #3609.
landreev Aug 15, 2017
e869900
add script to insert many guestbook responses #3609
pdurbin Aug 15, 2017
f5d1b53
Cleaned up layout of Preview Guestbook popup on dataset pg. [ref #3609]
mheppler Aug 15, 2017
fd5c44c
added the settings section in the configuration guide explaining how …
landreev Aug 15, 2017
51d408a
made some fields that didn't need to be public private. (#3609)
landreev Aug 15, 2017
bbf405a
move script to more semantic location #3609
pdurbin Aug 15, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions scripts/issues/3845/insert-guestbook-responses.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
-- select * from guestbookresponse;
--for i in {0..2000}; do psql dataverse_db -f scripts/issues/3845/insert-guestbook-responses.sh; done
-- id | downloadtype | email | institution | name | position | responsetime | sessionid | authenticateduser_id | datafile_id | dataset_id | datasetversion_id | guestbook_id
insert into guestbookresponse values (default, 1, null, null, null, null, null, null, null, 104, 103, null, 2);
19 changes: 13 additions & 6 deletions src/main/java/Bundle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -1057,7 +1057,8 @@ dataset.manageGuestbooks.tab.action.btn.copy=Copy
dataset.manageGuestbooks.tab.action.btn.enable=Enable
dataset.manageGuestbooks.tab.action.btn.disable=Disable
dataset.manageGuestbooks.tab.action.btn.edit=Edit
dataset.manageGuestbooks.tab.action.btn.viewCollectedData=View Collected Data
dataset.manageGuestbooks.tab.action.btn.preview=Preview
dataset.manageGuestbooks.tab.action.btn.viewCollectedData=View Responses
dataset.manageGuestbooks.tab.action.btn.delete=Delete
dataset.manageGuestbooks.tab.action.btn.delete.dialog.header=Delete Guestbook
dataset.manageGuestbooks.tab.action.btn.delete.dialog.tip=Are you sure you want to delete this guestbook? You cannot undelete a guestbook.
Expand All @@ -1076,13 +1077,20 @@ dataset.manageGuestbooks.message.enableSuccess=The guestbook has been enabled.
dataset.manageGuestbooks.message.enableFailure=The guestbook could not be enabled.
dataset.manageGuestbooks.message.disableSuccess=The guestbook has been disabled.
dataset.manageGuestbooks.message.disableFailure=The guestbook could not be disabled.
dataset.manageGuestbooks.tip.title=Manage Dataset Guestbooks
dataset.manageGuestbooks.tip.downloadascsv=Click \"Download All Responses\" to download all collected guestbook responses for this dataverse, as a CSV file. To navigate and analyze your collected responses, we recommend importing this CSV file into Excel, Google Sheets or similar software.
dataset.guestbooksResponses.dataset=Dataset
dataset.guestbooksResponses.date=Date
dataset.guestbooksResponses.type=Type
dataset.guestbooksResponses.file=File
dataset.guestbooksResponses.tip.title=Guestbook Responses
dataset.guestbooksResponses.count.responses={0} {0, choice, 0#Responses|1#Response|2#Responses}
dataset.guestbooksResponses.count.toofresults={0} to {1} of {2} {2, choice, 0#Responses|1#Response|2#Responses}
dataset.guestbooksResponses.tip.downloadascsv=Click \"Download Responses\" to download all collected responses for this guestbook, as a CSV file. To navigate and analyze your collected responses, we recommend importing this CSV file into Excel, Google Sheets or similar software.
dataset.guestbooksResponses.tooManyResponses.message=Note: this guestbook has too many responses to display on this page. Only the most recent {0} responses are shown below. Click \"Download Responses\" to download all collected responses ({1} total) as a CSV file.

# guestbook-responses.xhtml
dataset.guestbookResponses.pageTitle=View Guestbook Responses
dataset.guestbookResponses.pageTitle=Guestbook Responses

# guestbook.xhtml

Expand All @@ -1091,10 +1099,9 @@ dataset.manageGuestbooks.guestbook.name.tip=Enter a unique name for this Guestbo
dataset.manageGuestbooks.guestbook.dataCollected=Data Collected
dataset.manageGuestbooks.guestbook.dataCollected.description=Dataverse account information that will be collected when a user downloads a file. Check the ones that will be required.
dataset.manageGuestbooks.guestbook.customQuestions=Custom Questions
dataset.manageGuestbooks.guestbook.requiredCustomQuestions=Required Custom Questions
dataset.manageGuestbooks.guestbook.optionalCustomQuestions=Optional Custom Questions
dataset.manageGuestbooks.guestbook.requiredAccountInformation=Required Account Information
dataset.manageGuestbooks.guestbook.optionalAccountInformation=Optional Account Information
dataset.manageGuestbooks.guestbook.accountInformation=Account Information
dataset.manageGuestbooks.guestbook.required=(Required)
dataset.manageGuestbooks.guestbook.optional=(Optional)
dataset.manageGuestbooks.guestbook.customQuestions.description=Create your own questions to have users provide more than their account information when they download a file. Questions can be required or optional and answers can be text or multiple choice.
dataset.manageGuestbooks.guestbook.customQuestions.questionType=Question Type
dataset.manageGuestbooks.guestbook.customQuestions.questionText=Question Text
Expand Down
360 changes: 278 additions & 82 deletions src/main/java/edu/harvard/iq/dataverse/GuestbookResponseServiceBean.java

Large diffs are not rendered by default.

75 changes: 63 additions & 12 deletions src/main/java/edu/harvard/iq/dataverse/GuestbookResponsesPage.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,16 @@
*/
package edu.harvard.iq.dataverse;

import edu.harvard.iq.dataverse.engine.command.impl.UpdateDataverseCommand;
import static edu.harvard.iq.dataverse.util.JsfHelper.JH;
import edu.harvard.iq.dataverse.util.SystemConfig;
import java.util.List;
import java.util.logging.Logger;
import javax.ejb.EJB;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.view.ViewScoped;
import javax.inject.Inject;
import javax.inject.Named;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
Expand All @@ -20,6 +26,7 @@
@ViewScoped
@Named("guestbookResponsesPage")
public class GuestbookResponsesPage implements java.io.Serializable {
private static final Logger logger = Logger.getLogger(GuestbookResponsesPage.class.getCanonicalName());

@EJB
GuestbookServiceBean guestbookService;
Expand All @@ -30,6 +37,12 @@ public class GuestbookResponsesPage implements java.io.Serializable {
@EJB
DataverseServiceBean dvService;

@EJB
SystemConfig systemConfig;

@Inject
PermissionsWrapper permissionsWrapper;

private Long guestbookId;

private Long dataverseId;
Expand All @@ -49,7 +62,7 @@ public void setRedirectString(String redirectString) {
this.redirectString = redirectString;
}

private List<GuestbookResponse> responses;
/*private List<GuestbookResponse> responses;*/
private List<Object[]> responsesAsArray;

public List<Object[]> getResponsesAsArray() {
Expand All @@ -60,14 +73,55 @@ public void setResponsesAsArray(List<Object[]> responsesAsArray) {
this.responsesAsArray = responsesAsArray;
}

public void init() {
public String init() {
guestbook = guestbookService.find(guestbookId);
dataverse = dvService.find(dataverseId);
if(guestbook != null){
responsesAsArray = guestbookResponseService.findArrayByGuestbookIdAndDataverseId(guestbookId, dataverseId);

if (dataverse == null || guestbook == null) {
return permissionsWrapper.notFound();
}

if (!permissionsWrapper.canIssueCommand(dataverse, UpdateDataverseCommand.class)) {
return permissionsWrapper.notAuthorized();
}

guestbook.setResponseCount(guestbookResponseService.findCountByGuestbookId(guestbookId, dataverseId));

logger.info("Guestbook responses count: " + guestbook.getResponseCount());
responsesAsArray = guestbookResponseService.findArrayByGuestbookIdAndDataverseId(guestbookId, dataverseId, systemConfig.getGuestbookResponsesPageDisplayLimit());

FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO,
JH.localize("dataset.guestbooksResponses.tip.title"),
JH.localize("dataset.guestbooksResponses.tip.downloadascsv")));

return null;
}

private String getFileName(){
// The fix below replaces any spaces in the name of the dataverse with underscores;
// without it, the filename was chopped off (by the browser??), and the user
// was getting the file name "Foo", instead of "Foo and Bar in Social Sciences.csv". -- L.A.
return dataverse.getName().replace(' ', '_') + "_" + guestbook.getId() + "_GuestbookReponses.csv";
}

public void streamResponsesByDataverseAndGuestbook(){
FacesContext ctx = FacesContext.getCurrentInstance();
HttpServletResponse response = (HttpServletResponse) ctx.getExternalContext().getResponse();
response.setContentType("text/comma-separated-values");
String fileNameString = "attachment;filename=" + getFileName();
response.setHeader("Content-Disposition", fileNameString);
try {
ServletOutputStream out = response.getOutputStream();
guestbookResponseService.streamResponsesByDataverseIdAndGuestbookId(out, dataverseId, guestbookId);
out.flush();
ctx.responseComplete();
} catch (Exception e) {
logger.warning("Failed to stream collected guestbook responses for guestbook " + guestbookId + ", dataverse "+dataverseId);
}
}

/*
The methods below have been replaced with the "streamResponsesByDataverseAndGuestbook()", above -- L.A.
public void downloadResponsesByDataverseAndGuestbook(){
FacesContext ctx = FacesContext.getCurrentInstance();
HttpServletResponse response = (HttpServletResponse) ctx.getExternalContext().getResponse();
Expand All @@ -84,12 +138,9 @@ public void downloadResponsesByDataverseAndGuestbook(){
} catch (Exception e) {

}
}
}


private String getFileName(){
return dataverse.getName() + "_GuestbookReponses.csv";
}

private final String SEPARATOR = ",";
private final String END_OF_LINE = "\n";

Expand Down Expand Up @@ -132,7 +183,7 @@ private String convertResponsesToTabDelimited(List<Object[]> guestbookResponses)
}

return sb.toString();
}
} */

public Dataverse getDataverse() {
return dataverse;
Expand Down Expand Up @@ -167,12 +218,12 @@ public void setGuestbook(Guestbook guestbook) {
this.guestbook = guestbook;
}

public List<GuestbookResponse> getResponses() {
/*public List<GuestbookResponse> getResponses() {
return responses;
}

public void setResponses(List<GuestbookResponse> responses) {
this.responses = responses;
}
}*/

}
78 changes: 53 additions & 25 deletions src/main/java/edu/harvard/iq/dataverse/ManageGuestbooksPage.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
@ViewScoped
@Named
public class ManageGuestbooksPage implements java.io.Serializable {
private static final Logger logger = Logger.getLogger(ManageGuestbooksPage.class.getCanonicalName());

@EJB
DataverseServiceBean dvService;
Expand Down Expand Up @@ -80,6 +81,11 @@ public String init() {
Long totalResponses = guestbookResponseService.findCountAll(dataverseId);
if(totalResponses.intValue() > 0){
displayDownloadAll = true;
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_INFO,
JH.localize("dataset.manageGuestbooks.tip.title"),
JH.localize("dataset.manageGuestbooks.tip.downloadascsv")));

}

dvpage.setDataverse(dataverse);
Expand Down Expand Up @@ -109,6 +115,8 @@ public String init() {
return null;
}

/*
replaced by the "streamResponsesByDataverse(), below
public void downloadResponsesByDataverse(){
FacesContext ctx = FacesContext.getCurrentInstance();
HttpServletResponse response = (HttpServletResponse) ctx.getExternalContext().getResponse();
Expand All @@ -124,31 +132,8 @@ public void downloadResponsesByDataverse(){
} catch (Exception e) {

}
}

public void downloadResponsesByDataverseAndGuestbook(){
FacesContext ctx = FacesContext.getCurrentInstance();
HttpServletResponse response = (HttpServletResponse) ctx.getExternalContext().getResponse();
response.setContentType("text/comma-separated-values");
String fileNameString = "attachment;filename=" + getFileName();
response.setHeader("Content-Disposition", fileNameString);
//selectedGuestbook
String converted = convertResponsesToCommaDelimited(guestbookResponseService.findArrayByDataverseIdAndGuestbookId(dataverseId, selectedGuestbook.getId()));
try {
ServletOutputStream out = response.getOutputStream();
out.write(converted.getBytes());
out.flush();
ctx.responseComplete();
} catch (Exception e) {

}
}

private String getFileName(){
return dataverse.getName() + "_GuestbookReponses.csv";
}

private final String SEPARATOR = ",";
}*/
/*private final String SEPARATOR = ",";
private final String END_OF_LINE = "\n";


Expand Down Expand Up @@ -189,9 +174,52 @@ private String convertResponsesToCommaDelimited(List<Object[]> guestbookResponse
sb.append(END_OF_LINE);
}
return sb.toString();
}*/

public void streamResponsesByDataverse(){
FacesContext ctx = FacesContext.getCurrentInstance();
HttpServletResponse response = (HttpServletResponse) ctx.getExternalContext().getResponse();
response.setContentType("text/comma-separated-values");
String fileNameString = "attachment;filename=" + getFileName();
response.setHeader("Content-Disposition", fileNameString);
try {
ServletOutputStream out = response.getOutputStream();
guestbookResponseService.streamResponsesByDataverseIdAndGuestbookId(out, dataverseId, null);
out.flush();
ctx.responseComplete();
} catch (Exception e) {
logger.warning("Failed to stream collected guestbook responses for dataverse "+dataverseId);
}
}

/* This method does not appear to be needed; the ManageGuestbooksPage does not
offer to download collected responses by dataverse and guestbook...
(that is done from the guestbook-responses page)
public void downloadResponsesByDataverseAndGuestbook(){
FacesContext ctx = FacesContext.getCurrentInstance();
HttpServletResponse response = (HttpServletResponse) ctx.getExternalContext().getResponse();
response.setContentType("text/comma-separated-values");
String fileNameString = "attachment;filename=" + getFileName();
response.setHeader("Content-Disposition", fileNameString);
//selectedGuestbook
String converted = convertResponsesToCommaDelimited(guestbookResponseService.findArrayByDataverseIdAndGuestbookId(dataverseId, selectedGuestbook.getId()));
try {
ServletOutputStream out = response.getOutputStream();
out.write(converted.getBytes());
out.flush();
ctx.responseComplete();
} catch (Exception e) {

}
}*/

private String getFileName(){
// The fix below replaces any spaces in the name of the dataverse with underscores;
// without it, the filename was chopped off (by the browser??), and the user
// was getting the file name "Foo", instead of "Foo and Bar in Social Sciences.csv". -- L.A.
return dataverse.getName().replace(' ', '_') + "_GuestbookReponses.csv";
}

public void deleteGuestbook() {
if (selectedGuestbook != null) {
guestbooks.remove(selectedGuestbook);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public String getPageFromContext() {
// that we don't want, so we filter through a list of paramters we do allow
// @todo verify what needs to be in this list of available parameters (for example do we want to repeat searches when you login?
List<String> acceptableParameters = new ArrayList<>();
acceptableParameters.addAll(Arrays.asList("id", "alias", "version", "q", "ownerId", "persistentId", "versionId", "datasetId", "selectedFileIds", "mode", "dataverseId", "fileId", "datasetVersionId"));
acceptableParameters.addAll(Arrays.asList("id", "alias", "version", "q", "ownerId", "persistentId", "versionId", "datasetId", "selectedFileIds", "mode", "dataverseId", "fileId", "datasetVersionId", "guestbookId"));

if (req.getParameterMap() != null) {
StringBuilder queryString = new StringBuilder();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,10 @@ Whether Harvesting (OAI) service is enabled
NavbarAboutUrl,

// Option to override multiple guides with a single url
NavbarGuidesUrl;
NavbarGuidesUrl,

// Limit on how many guestbook entries to display on the guestbook-responses page:
GuestbookResponsesPageDisplayLimit;


@Override
Expand Down
21 changes: 21 additions & 0 deletions src/main/java/edu/harvard/iq/dataverse/util/SystemConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ public class SystemConfig {

private static final String JVM_TIMER_SERVER_OPTION = "dataverse.timerServer";

private static final long DEFAULT_GUESTBOOK_RESPONSES_DISPLAY_LIMIT = 5000L;

public String getVersion() {
return getVersion(false);
}
Expand Down Expand Up @@ -405,6 +407,25 @@ public int getMultipleUploadFilesLimit() {
return defaultMultipleUploadFilesLimit;
}

public long getGuestbookResponsesPageDisplayLimit() {
String limitSetting = settingsService.getValueForKey(SettingsServiceBean.Key.GuestbookResponsesPageDisplayLimit);

Long limit = null;
if (limitSetting != null && !limitSetting.equals("")) {
try {
limit = new Long(limitSetting);
} catch (NumberFormatException nfe) {
limit = null;
}
}

if (limit != null) {
return limit.longValue();
}

return DEFAULT_GUESTBOOK_RESPONSES_DISPLAY_LIMIT;
}

public long getUploadLogoSizeLimit(){
return 500000;
}
Expand Down
Loading