Skip to content

Commit

Permalink
Merge pull request #11150 from Recherche-Data-Gouv/10304-add-move-dat…
Browse files Browse the repository at this point in the history
…averse-collection

Allow collections to be moved in the superuser dashboard
  • Loading branch information
ofahimIQSS authored Jan 23, 2025
2 parents 24143fd + bff877b commit bf1e3f8
Show file tree
Hide file tree
Showing 13 changed files with 432 additions and 99 deletions.
5 changes: 5 additions & 0 deletions doc/release-notes/10304-add-move-dataverse-collection.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
### Move a collection from the dashboard

In addition to the api [Move a Dataverse Collection](https://guides.dataverse.org/en/latest/admin/dataverses-datasets.html#move-a-dataverse-collection), it is now possible for a Dataverse administrator to move a collection from the Dataverse dashboard.

For more information, see #10304.
2 changes: 2 additions & 0 deletions src/main/java/edu/harvard/iq/dataverse/Dataset.java
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@
query = "SELECT o FROM Dataset o WHERE o.creator.id=:creatorId"),
@NamedQuery(name = "Dataset.findByReleaseUserId",
query = "SELECT o FROM Dataset o WHERE o.releaseUser.id=:releaseUserId"),
@NamedQuery(name = "Dataset.countAll",
query = "SELECT COUNT(ds) FROM Dataset ds")
})

/*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1092,4 +1092,12 @@ public List<String> getVersionStates(long id) {
}
}

/**
* Returns the total number of Datasets.
* @return the number of datasets in the database
*/
public long getDatasetCount() {
return em.createNamedQuery("Dataset.countAll", Long.class).getSingleResult();
}

}
3 changes: 2 additions & 1 deletion src/main/java/edu/harvard/iq/dataverse/Dataverse.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@
@NamedQuery(name = "Dataverse.findByReleaseUserId", query="select object(o) from Dataverse as o where o.releaseUser.id =:releaseUserId order by o.name"),
@NamedQuery(name = "Dataverse.filterByAlias", query="SELECT dv FROM Dataverse dv WHERE LOWER(dv.alias) LIKE :alias order by dv.alias"),
@NamedQuery(name = "Dataverse.filterByAliasNameAffiliation", query="SELECT dv FROM Dataverse dv WHERE (LOWER(dv.alias) LIKE :alias) OR (LOWER(dv.name) LIKE :name) OR (LOWER(dv.affiliation) LIKE :affiliation) order by dv.alias"),
@NamedQuery(name = "Dataverse.filterByName", query="SELECT dv FROM Dataverse dv WHERE LOWER(dv.name) LIKE :name order by dv.alias")
@NamedQuery(name = "Dataverse.filterByName", query="SELECT dv FROM Dataverse dv WHERE LOWER(dv.name) LIKE :name order by dv.alias"),
@NamedQuery(name = "Dataverse.countAll", query = "SELECT COUNT(dv) FROM Dataverse dv")
})
@Entity
@Table(indexes = {@Index(columnList="defaultcontributorrole_id")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1219,4 +1219,12 @@ public void disableStorageQuota(StorageQuota storageQuota) {
em.flush();
}
}

/**
* Returns the total number of Dataverses
* @return the number of dataverse in the database
*/
public long getDataverseCount() {
return em.createNamedQuery("Dataverse.countAll", Long.class).getSingleResult();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,11 @@
import jakarta.faces.view.ViewScoped;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import jakarta.servlet.http.HttpServletRequest;

@ViewScoped
@Named("DashboardDatamovePage")
public class DashboardDatamovePage implements java.io.Serializable {
@Named("DashboardMoveDatasetPage")
public class DashboardMoveDatasetPage implements java.io.Serializable {

@Inject
DataverseSession session;
Expand All @@ -49,11 +47,8 @@ public class DashboardDatamovePage implements java.io.Serializable {
DataverseServiceBean dataverseService;
@Inject
SettingsWrapper settingsWrapper;

@PersistenceContext(unitName = "VDCNet-ejbPU")
private EntityManager em;

private static final Logger logger = Logger.getLogger(DashboardDatamovePage.class.getCanonicalName());
private static final Logger logger = Logger.getLogger(DashboardMoveDatasetPage.class.getCanonicalName());

private AuthenticatedUser authUser = null;

Expand Down Expand Up @@ -122,18 +117,18 @@ public String init() {

FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_INFO,
BundleUtil.getStringFromBundle("dashboard.card.datamove.manage"),
BundleUtil.getStringFromBundle("dashboard.card.datamove.message", Arrays.asList(settingsWrapper.getGuidesBaseUrl(), settingsWrapper.getGuidesVersion()))));
BundleUtil.getStringFromBundle("dashboard.card.move.dataset.manage"),
BundleUtil.getStringFromBundle("dashboard.move.dataset.message", Arrays.asList(settingsWrapper.getGuidesBaseUrl(), settingsWrapper.getGuidesVersion()))));
return null;
}

public void move(){
Dataset ds = selectedSourceDataset;
String dsPersistentId = ds!=null?ds.getGlobalId().asString():null;
String srcAlias = ds!=null?ds.getOwner().getAlias():null;
String dsPersistentId = ds != null ? ds.getGlobalId().asString() : null;
String srcAlias = ds != null ? ds.getOwner().getAlias() : null;

Dataverse target = selectedDestinationDataverse;
String dstAlias = target!=null?target.getAlias():null;
String dstAlias = target != null ? target.getAlias() : null;

if (ds == null || target == null) {
// Move only works if both inputs are correct
Expand All @@ -148,9 +143,9 @@ public void move(){

// construct arguments for message
List<String> arguments = new ArrayList<>();
arguments.add(ds!=null?ds.getDisplayName():"-");
arguments.add(dsPersistentId!=null?dsPersistentId:"-");
arguments.add(target!=null?target.getName():"-");
arguments.add(ds != null ? ds.getDisplayName() : "-");
arguments.add(dsPersistentId != null ? dsPersistentId : "-");
arguments.add(target != null ? target.getName() : "-");

// copied logic from Datasets API move
//Command requires Super user - it will be tested by the command
Expand All @@ -163,7 +158,7 @@ public void move(){

logger.info("Moved " + dsPersistentId + " from " + srcAlias + " to " + dstAlias);

JsfHelper.addSuccessMessage(BundleUtil.getStringFromBundle("dashboard.card.datamove.message.success", arguments));
JsfHelper.addSuccessMessage(BundleUtil.getStringFromBundle("dashboard.move.dataset.message.success", arguments));
}
catch (CommandException e) {
logger.log(Level.SEVERE,"Unable to move "+ dsPersistentId + " from " + srcAlias + " to " + dstAlias, e);
Expand All @@ -172,25 +167,20 @@ public void move(){
String guidesBaseUrl = settingsWrapper.getGuidesBaseUrl();
String version = settingsWrapper.getGuidesVersion();
// Suggest using the API to force the move.
arguments.add(BundleUtil.getStringFromBundle("dashboard.card.datamove.dataset.command.error.unforced.suggestForce", Arrays.asList(guidesBaseUrl, version)));
arguments.add(BundleUtil.getStringFromBundle("dashboard.move.dataset.command.error.unforced.suggestForce", Arrays.asList(guidesBaseUrl, version)));
} else {
String emptyStringNoDetails = "";
arguments.add(emptyStringNoDetails);
}
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_ERROR,
BundleUtil.getStringFromBundle("dashboard.card.datamove.message.failure.summary"),
BundleUtil.getStringFromBundle("dashboard.card.datamove.message.failure.details", arguments)));
BundleUtil.getStringFromBundle("dashboard.move.dataset.message.failure.summary"),
BundleUtil.getStringFromBundle("dashboard.move.dataset.message.failure.details", arguments)));
}
}

public String getDataverseCount() {
long count = em.createQuery("SELECT count(dv) FROM Dataverse dv", Long.class).getSingleResult();
return NumberFormat.getInstance().format(count);
}

public String getDatasetCount() {
long count = em.createQuery("SELECT count(ds) FROM Dataset ds", Long.class).getSingleResult();
long count = datasetService.getDatasetCount();
return NumberFormat.getInstance().format(count);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
package edu.harvard.iq.dataverse.dashboard;

import edu.harvard.iq.dataverse.Dataverse;
import edu.harvard.iq.dataverse.DataverseServiceBean;
import edu.harvard.iq.dataverse.DataverseSession;
import edu.harvard.iq.dataverse.EjbDataverseEngine;
import edu.harvard.iq.dataverse.PermissionsWrapper;
import edu.harvard.iq.dataverse.SettingsWrapper;
import edu.harvard.iq.dataverse.authorization.users.AuthenticatedUser;
import edu.harvard.iq.dataverse.engine.command.DataverseRequest;
import edu.harvard.iq.dataverse.engine.command.exception.CommandException;
import edu.harvard.iq.dataverse.engine.command.impl.MoveDataverseCommand;
import edu.harvard.iq.dataverse.util.BundleUtil;
import edu.harvard.iq.dataverse.util.JsfHelper;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import jakarta.ejb.EJB;
import jakarta.faces.application.FacesMessage;
import jakarta.faces.component.UIInput;
import jakarta.faces.context.FacesContext;
import jakarta.faces.view.ViewScoped;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import jakarta.servlet.http.HttpServletRequest;

@ViewScoped
@Named("DashboardMoveDataversePage")
public class DashboardMoveDataversePage implements java.io.Serializable {

@Inject
DataverseSession session;
@Inject
PermissionsWrapper permissionsWrapper;
@EJB
EjbDataverseEngine commandEngine;
@EJB
DataverseServiceBean dataverseService;
@Inject
SettingsWrapper settingsWrapper;

private static final Logger logger = Logger.getLogger(DashboardMoveDataversePage.class.getCanonicalName());

private AuthenticatedUser authUser = null;

// source dataverse

public UIInput getSelectedSourceDataverseMenu() {
return selectedSourceDataverseMenu;
}

public void setSelectedSourceDataverseMenu(UIInput selectedSourceDataverseMenu) {
this.selectedSourceDataverseMenu = selectedSourceDataverseMenu;
}

UIInput selectedSourceDataverseMenu;

public Dataverse getSelectedSourceDataverse() {
return selectedSourceDataverse;
}

public void setSelectedSourceDataverse(Dataverse selectedSourceDataverse) {
this.selectedSourceDataverse = selectedSourceDataverse;
}

private Dataverse selectedSourceDataverse;

// destination dataverse

public UIInput getSelectedDataverseMenu() {
return selectedDataverseMenu;
}

public void setSelectedDataverseMenu(UIInput selectedDataverseMenu) {
this.selectedDataverseMenu = selectedDataverseMenu;
}

UIInput selectedDataverseMenu;

public Dataverse getSelectedDestinationDataverse() {
return selectedDestinationDataverse;
}

public void setSelectedDestinationDataverse(Dataverse selectedDestinationDataverse) {
this.selectedDestinationDataverse = selectedDestinationDataverse;
}

private Dataverse selectedDestinationDataverse;

public List<Dataverse> completeSelectedDataverse(String query) {
return dataverseService.filterByAliasQuery(query);
}

public String init() {

if ((session.getUser() != null) && (session.getUser().isAuthenticated()) && (session.getUser().isSuperuser())) {
authUser = (AuthenticatedUser) session.getUser();
// initialize components, if any need it
} else {
return permissionsWrapper.notAuthorized();
// redirect to login OR give some type of ‘you must be logged in' message
}

FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_INFO,
BundleUtil.getStringFromBundle("dashboard.move.dataverse.message.summary"),
BundleUtil.getStringFromBundle("dashboard.move.dataverse.message.detail", Arrays.asList(settingsWrapper.getGuidesBaseUrl(), settingsWrapper.getGuidesVersion()))));
return null;
}

public void move(){
Dataverse dvSource = selectedSourceDataverse;
String srcAlias = dvSource != null ? dvSource.getAlias() : null;

Dataverse target = selectedDestinationDataverse;
String dstAlias = target != null ? target.getAlias() : null;

if (dvSource == null || target == null) {
// Move only works if both inputs are correct
// But if these inputs are required, we should never get here
// Since we never get here, we aren't bothering to move this English to the bundle.
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage("Please specify all fields"));
return;
}

// construct arguments for message
List<String> arguments = new ArrayList<>();
arguments.add(dvSource != null ? dvSource.getName() : "-");
arguments.add(target != null ? target.getName() : "-");

// copied logic from Dataverse API move
//Command requires Super user - it will be tested by the command
try {
HttpServletRequest httpServletRequest = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
DataverseRequest dataverseRequest = new DataverseRequest(authUser, httpServletRequest);
commandEngine.submit(new MoveDataverseCommand(
dataverseRequest, dvSource, target, false
));

logger.info("Moved " + srcAlias + " to " + dstAlias);

JsfHelper.addSuccessMessage(BundleUtil.getStringFromBundle("dashboard.move.dataverse.message.success", arguments));
}
catch (CommandException e) {
logger.log(Level.SEVERE,"Unable to move "+ srcAlias + " to " + dstAlias, e);
arguments.add(e.getLocalizedMessage());
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_ERROR,
BundleUtil.getStringFromBundle("dashboard.move.dataverse.message.failure.summary"),
BundleUtil.getStringFromBundle("dashboard.move.dataverse.message.failure.details", arguments)));
}
}

public String getDataverseCount() {
long count = dataverseService.getDataverseCount();
return NumberFormat.getInstance().format(count);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import edu.harvard.iq.dataverse.DatasetLock;
import edu.harvard.iq.dataverse.Dataverse;
import edu.harvard.iq.dataverse.Guestbook;
import edu.harvard.iq.dataverse.authorization.DataverseRole;
import edu.harvard.iq.dataverse.authorization.Permission;
import edu.harvard.iq.dataverse.authorization.users.AuthenticatedUser;
import edu.harvard.iq.dataverse.engine.command.AbstractVoidCommand;
Expand All @@ -27,7 +26,6 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
Expand Down Expand Up @@ -72,13 +70,13 @@ public void executeImpl(CommandContext ctxt) throws CommandException {

// validate the move makes sense
if (moved.getOwner().equals(destination)) {
throw new IllegalCommandException(BundleUtil.getStringFromBundle("dashboard.card.datamove.dataset.command.error.targetDataverseSameAsOriginalDataverse"), this);
throw new IllegalCommandException(BundleUtil.getStringFromBundle("dashboard.move.dataset.command.error.targetDataverseSameAsOriginalDataverse"), this);
}

// if dataset is published make sure that its target is published

if (moved.isReleased() && !destination.isReleased()){
throw new IllegalCommandException(BundleUtil.getStringFromBundle("dashboard.card.datamove.dataset.command.error.targetDataverseUnpublishedDatasetPublished", Arrays.asList(destination.getDisplayName())), this);
throw new IllegalCommandException(BundleUtil.getStringFromBundle("dashboard.move.dataset.command.error.targetDataverseUnpublishedDatasetPublished", Arrays.asList(destination.getDisplayName())), this);
}

//if the datasets guestbook is not contained in the new dataverse then remove it
Expand Down Expand Up @@ -130,10 +128,10 @@ public void executeImpl(CommandContext ctxt) throws CommandException {
if (removeGuestbook || removeLinkDs) {
StringBuilder errorString = new StringBuilder();
if (removeGuestbook) {
errorString.append(BundleUtil.getStringFromBundle("dashboard.card.datamove.dataset.command.error.unforced.datasetGuestbookNotInTargetDataverse"));
errorString.append(BundleUtil.getStringFromBundle("dashboard.move.dataset.command.error.unforced.datasetGuestbookNotInTargetDataverse"));
}
if (removeLinkDs) {
errorString.append(BundleUtil.getStringFromBundle("dashboard.card.datamove.dataset.command.error.unforced.linkedToTargetDataverseOrOneOfItsParents"));
errorString.append(BundleUtil.getStringFromBundle("dashboard.move.dataset.command.error.unforced.linkedToTargetDataverseOrOneOfItsParents"));
}
throw new UnforcedCommandException(errorString.toString(), this);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import edu.harvard.iq.dataverse.Template;
import edu.harvard.iq.dataverse.authorization.Permission;
import edu.harvard.iq.dataverse.authorization.users.AuthenticatedUser;
import edu.harvard.iq.dataverse.batch.util.LoggingUtil;
import edu.harvard.iq.dataverse.engine.command.AbstractVoidCommand;
import edu.harvard.iq.dataverse.engine.command.CommandContext;
import edu.harvard.iq.dataverse.engine.command.DataverseRequest;
Expand All @@ -20,14 +19,12 @@
import edu.harvard.iq.dataverse.engine.command.exception.IllegalCommandException;
import edu.harvard.iq.dataverse.engine.command.exception.PermissionException;
import edu.harvard.iq.dataverse.util.BundleUtil;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Logger;
import org.apache.solr.client.solrj.SolrServerException;

/**
* A command to move a {@link Dataverse} between two {@link Dataverse}s.
Expand Down
Loading

0 comments on commit bf1e3f8

Please sign in to comment.