task_21363 #1

Closed
francesco.mangiacrapa wants to merge 53 commits from task_21363 into master
16 changed files with 539 additions and 174 deletions
Showing only changes of commit fdbf2d3a76 - Show all commits

View File

@ -5,6 +5,8 @@ All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [v1.0.0-SNAPSHOT] - 2021-06-15
## [v1.0.0-SNAPSHOT] - 2022-04-04
First Release
- [#21363] Implemented the ckan-content-moderator-widget
- [#20650] Provided moderator skills to Catalogue Moderator(s)
- [#23108] Provided Moderation facility accessible to Catalogue Editor/Admin (only) in read only mode

View File

@ -15,11 +15,12 @@ import com.google.gwt.user.client.rpc.AsyncCallback;
public class CkanContentModeratorCheckConfig {
private int configurationLoaded = 0;
private static final int CONFIGURATION_EXPECTED = 2;
private static final int CONFIGURATION_EXPECTED = 3;
private int MAX_RETRY_ON_LOADING_CONFIG = 20;
private int attemptLC = 0;
private Boolean contentModerationEnabled = null;
private Boolean moderatorRoleAssigned = null;
private Boolean existsMyItemInModeration = null;
/**
* Instantiates a new ckan content moderator check config.
@ -32,6 +33,7 @@ public class CkanContentModeratorCheckConfig {
* Check configs.
*
* @param whenDone the when done
* @param reloadGCatConfig the reload G cat config
* @throws Exception the exception
*/
public void checkConfigs(final Command whenDone, boolean reloadGCatConfig) throws Exception {
@ -39,8 +41,8 @@ public class CkanContentModeratorCheckConfig {
configurationLoaded = 0;
attemptLC = 0;
CkanContentModeratorWidgetController.contentModeratorService
.isModerationEnabled(reloadGCatConfig, new AsyncCallback<Boolean>() {
CkanContentModeratorWidgetController.contentModeratorService.isModerationEnabled(reloadGCatConfig,
new AsyncCallback<Boolean>() {
@Override
public void onFailure(Throwable caught) {
@ -52,7 +54,7 @@ public class CkanContentModeratorCheckConfig {
@Override
public void onSuccess(Boolean result) {
incrementConfigurationLoaded();
GWT.log("isContentModeratorEnabled: "+result);
GWT.log("isContentModeratorEnabled: " + result);
contentModerationEnabled = result;
}
});
@ -70,12 +72,31 @@ public class CkanContentModeratorCheckConfig {
@Override
public void onSuccess(Boolean result) {
incrementConfigurationLoaded();
GWT.log("isModeratorRoleAssigned: "+result);
GWT.log("isModeratorRoleAssigned: " + result);
moderatorRoleAssigned = result;
}
});
CkanContentModeratorWidgetController.contentModeratorService
.existsMyItemInModeration(new AsyncCallback<Boolean>() {
@Override
public void onFailure(Throwable caught) {
existsMyItemInModeration = false;
incrementConfigurationLoaded();
}
@Override
public void onSuccess(Boolean result) {
incrementConfigurationLoaded();
GWT.log("existsMyItemInModeration: " + result);
existsMyItemInModeration = result;
}
});
if (whenDone != null) {
final Timer timer = new Timer() {
@ -83,9 +104,10 @@ public class CkanContentModeratorCheckConfig {
@Override
public void run() {
attemptLC++;
GWT.log("checking configuration loaded, attempt "+attemptLC+" of "+MAX_RETRY_ON_LOADING_CONFIG);
GWT.log("checking configuration loaded, attempt " + attemptLC + " of "
+ MAX_RETRY_ON_LOADING_CONFIG);
boolean configsLoaded = getConfigurationLoaded() == CONFIGURATION_EXPECTED;
GWT.log("configsLoaded: "+configsLoaded);
GWT.log("configsLoaded: " + configsLoaded);
if (configsLoaded) {
GWT.log("ContentModeratorCheckConfig loaded correclty");
whenDone.execute();
@ -159,4 +181,18 @@ public class CkanContentModeratorCheckConfig {
}
/**
* Checks if is exists my item in moderation.
*
* @return the boolean
* @throws Exception the exception
*/
public Boolean isExistsMyItemInModeration() throws Exception {
if (existsMyItemInModeration == null)
throw new Exception(
"Please, first check if the content moderation is enabled in this context by calling checkContentModeratorConfiguration");
return existsMyItemInModeration;
}
}

View File

@ -57,25 +57,28 @@ public interface CkanContentModeratorService extends RemoteService {
* Gets the list items for status.
*
* @param theStatus the the status
* @param limit the limit
* @param offset the offset
* @param limit the limit
* @param restrictedToLoggedInUser the restricted to logged in user
* @return the list items for status
* @throws Exception the exception
*/
public List<CatalogueDataset> getListItemsForStatus(ItemStatus theStatus, int limit, int offset) throws Exception;
public List<CatalogueDataset> getListItemsForStatus(ItemStatus theStatus, int offset, int limit,
boolean restrictedToLoggedInUser) throws Exception;
/**
* Gets the data for status.
*
* @param status the status
* @param startIndex the start index
* @param lenght the lenght
* @param serverIndex the server index
* @param offset the offset
* @param limit the limit
* @param serverStartIndex the server start index
* @param restrictedToLoggedInUser the restricted to logged in user
* @return the data for status
* @throws Exception the exception
* @par@Override am lenght the lenght
*/
SearchedData getDataForStatus(ItemStatus status, int startIndex, int lenght, int serverIndex) throws Exception;
public SearchedData getDataForStatus(ItemStatus status, int offset, int limit, int serverStartIndex,
boolean restrictedToLoggedInUser) throws Exception;
/**
* Approve item.
@ -85,7 +88,7 @@ public interface CkanContentModeratorService extends RemoteService {
* @return the operation report
* @throws Exception the exception
*/
OperationReport approveItem(List<String> itemNames, String moderatorMessage) throws Exception;
public OperationReport approveItem(List<String> itemNames, String moderatorMessage) throws Exception;
/**
* Gets the CMS roles for user in the context.
@ -93,7 +96,7 @@ public interface CkanContentModeratorService extends RemoteService {
* @return the CMS roles for user in the context
* @throws Exception the exception
*/
ModerationUserRole getCMSRolesForUserInTheContext() throws Exception;
public ModerationUserRole getCMSRolesForUserInTheContext() throws Exception;
/**
* Checks if is moderation enabled.
@ -101,13 +104,22 @@ public interface CkanContentModeratorService extends RemoteService {
* @param reloadConfig the reload config
* @return the boolean
*/
Boolean isModerationEnabled(boolean reloadConfig);
public Boolean isModerationEnabled(boolean reloadConfig);
/**
* Checks if is moderator role assigned.
*
* @return true, if is moderator role assigned
* @throws Exception
* @return true, if is moderat@Override or role assigned
* @throws Exception the exception
*/
Boolean isModeratorRoleAssigned() throws Exception;
public Boolean isModeratorRoleAssigned() throws Exception;
/**
* Exists my item in moderation.
*
* @return true if the user has at least one item moderatorated or in
* moderation.
* @throws Exception the exception
*/
public Boolean existsMyItemInModeration() throws Exception;
}

View File

@ -34,26 +34,28 @@ public interface CkanContentModeratorServiceAsync {
* Gets the list items for status.
*
* @param theStatus the the status
* @param limit the limit
* @param offset the offset
* @param limit the limit
* @param restrictedToLoggedInUser the restricted to logged in user
* @param callback the callback
* @return the list items for status
*/
void getListItemsForStatus(ItemStatus theStatus, int limit, int offset,
void getListItemsForStatus(ItemStatus theStatus, int offset, int limit, boolean restrictedToLoggedInUser,
AsyncCallback<List<CatalogueDataset>> callback);
/**
* Gets the data for status.
*
* @param status the status
* @param startIndex the start index
* @param lenght the lenght
* @param serverIndex the server index
* @param offset the offset
* @param limit the limit
* @param serverStartIndex the server start index
* @param restrictedToLoggedInUser the restricted to logged in user
* @param asyncCallback the async callback
* @return the data for status
*/
void getDataForStatus(ItemStatus status, int startIndex, int lenght, int serverIndex,
AsyncCallback<SearchedData> asyncCallback);
void getDataForStatus(ItemStatus status, int offset, int limit, int serverStartIndex,
boolean restrictedToLoggedInUser, AsyncCallback<SearchedData> asyncCallback);
/**
* Approve item.
@ -104,4 +106,13 @@ public interface CkanContentModeratorServiceAsync {
*/
void isModeratorRoleAssigned(AsyncCallback<Boolean> callback);
/**
* Exists my item in moderation.
*
* @param callback the callback
* @return true if the user has at least one item moderatorated or in
* moderation.
*/
void existsMyItemInModeration(AsyncCallback<Boolean> callback);
}

View File

@ -3,7 +3,7 @@ package org.gcube.portlets.widgets.ckancontentmoderator.client;
import org.gcube.datacatalogue.utillibrary.shared.ItemStatus;
import org.gcube.portlets.widgets.ckancontentmoderator.client.ui.table.ItemsTable.DISPLAY_FIELD;
import com.google.gwt.user.client.Command;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.ui.ComplexPanel;
/**
@ -23,10 +23,12 @@ public class CkanContentModeratorWidget {
* @param status the status
* @param displayFields the display fields
* @param sortByField the sort by field
* @param readOnlyMode the read only mode is true if the Moderator Role is not assigned
* @param restrictDataToLoggedInUser the restrict data to logged in user
*/
public CkanContentModeratorWidget(ItemStatus status, DISPLAY_FIELD[] displayFields, DISPLAY_FIELD sortByField,
Command onConfigurationLoaded) {
cmsController = new CkanContentModeratorWidgetController(status, displayFields, sortByField);
public CkanContentModeratorWidget(ItemStatus status, DISPLAY_FIELD[] displayFields, DISPLAY_FIELD sortByField, boolean readOnlyMode, boolean restrictDataToLoggedInUser) {
GWT.log("CkanContentModeratorWidget called. ReadOnlyMode: "+readOnlyMode);
cmsController = new CkanContentModeratorWidgetController(status, displayFields, sortByField, readOnlyMode, restrictDataToLoggedInUser);
}

View File

@ -59,21 +59,37 @@ public class CkanContentModeratorWidgetController {
private HashMap<String, CkanShowItemFrame> mapOfItemsTabDisplayed = new HashMap<String, CkanShowItemFrame>();
private boolean readOnlyMode;
/**
* Instantiates a new ckan content moderator widget.
*
* @param status the status
* @param displayFields the display fields
* @param sortByField the sort by field
* @param readOnlyMode the read only mode
* @param restrictDataToLoggedInUser
*/
public CkanContentModeratorWidgetController(ItemStatus status, DISPLAY_FIELD[] displayFields,
DISPLAY_FIELD sortByField) {
DISPLAY_FIELD sortByField, boolean readOnlyMode, boolean restrictDataToLoggedInUser) {
toolbar = new ContentModeratorToolbar(eventBus, status);
howeView = new HomeView(eventBus, status, displayFields, sortByField);
// GWT.log("***************** HARD CODED READONLY ********************** ");
// readOnlyMode = true;
// restrictDataToLoggedInUser = readOnlyMode;
howeView = new HomeView(eventBus, status, displayFields, sortByField, readOnlyMode, restrictDataToLoggedInUser);
mainTabPanel.addHomeWidget(howeView.getPanel());
mainPanel.add(toolbar);
mainPanel.add(infoPanel);
mainPanel.add(mainTabPanel);
this.readOnlyMode = readOnlyMode;
howeView.hideUpdateStatusAction(readOnlyMode);
howeView.hideSelectableRow(readOnlyMode);
bindEvents();
}
@ -92,12 +108,13 @@ public class CkanContentModeratorWidgetController {
// if items selected are > 0 then shows button "Update status as.."
howeView.setVisibleUpdateStatusAction(items.size() > 0);
if(howeView.getDisplayingItemStatus().equals(ItemStatus.APPROVED)) {
GWT.log("The Item Status displayed is "+ItemStatus.APPROVED +" hiding update status actions");
if (howeView.getDisplayingItemStatus().equals(ItemStatus.APPROVED)) {
GWT.log("The Item Status displayed is " + ItemStatus.APPROVED
+ " hiding update status actions");
howeView.setVisibleUpdateStatusAction(false);
}
//If an action updated the item status we reloading it
// If an action updated the item status we reloading it
reloadItemsDisplayedInTab();
}
}
@ -117,11 +134,6 @@ public class CkanContentModeratorWidgetController {
csif.instanceFrame(clickedDataset.getUrl());
mainTabPanel.addTab(clickedDataset.getTitle(), csif);
mapOfItemsTabDisplayed.put(clickedDataset.getUrl(), csif);
// CkanInternalFramePanel cfp = new CkanInternalFramePanel(eventBus);
// cfp.instanceFrame(clickedDataset.getUrl());
// mainTabPanel.addTab(clickedDataset.getTitle(), cfp);
}
}
}
@ -207,6 +219,9 @@ public class CkanContentModeratorWidgetController {
});
}
/**
* Reload items displayed in tab.
*/
private void reloadItemsDisplayedInTab() {
for (String datasetURL : mapOfItemsTabDisplayed.keySet()) {
@ -215,6 +230,12 @@ public class CkanContentModeratorWidgetController {
}
}
/**
* Show message.
*
* @param msg the msg
* @param alertType the alert type
*/
private void showMessage(String msg, AlertType alertType) {
final Alert alert = new Alert(msg);
@ -245,4 +266,13 @@ public class CkanContentModeratorWidgetController {
return mainPanel;
}
/**
* Checks if is read only mode.
*
* @return true, if is read only mode
*/
public boolean isReadOnlyMode() {
return readOnlyMode;
}
}

View File

@ -1,22 +1,22 @@
package org.gcube.portlets.widgets.ckancontentmoderator.client;
import com.google.gwt.core.client.EntryPoint;
/**
* Entry point classes define <code>onModuleLoad()</code>.
*/
public class CkanContentModeratorWidgetEntryPoint implements EntryPoint {
/**
* The message displayed to the user when the server cannot be reached or
* returns an error.
*/
private static final String SERVER_ERROR = "An error occurred while "
+ "attempting to contact the server. Please check your network " + "connection and try again.";
/**
* This is the entry point method.
*/
public void onModuleLoad() {
}
}
//package org.gcube.portlets.widgets.ckancontentmoderator.client;
//
//import com.google.gwt.core.client.EntryPoint;
//
///**
// * Entry point classes define <code>onModuleLoad()</code>.
// */
//public class CkanContentModeratorWidgetEntryPoint implements EntryPoint {
// /**
// * The message displayed to the user when the server cannot be reached or
// * returns an error.
// */
// private static final String SERVER_ERROR = "An error occurred while "
// + "attempting to contact the server. Please check your network " + "connection and try again.";
//
// /**
// * This is the entry point method.
// */
// public void onModuleLoad() {
// }
//
//}

View File

@ -13,4 +13,6 @@ public class ContentModeratorWidgetConstants {
public static int ITEMS_PER_PAGE = 10;
public static int ITEM_START_INDEX = 0;
public static String CKAN_FIELD_NAME_AUTHOR_MAIL = "author_email";
}

View File

@ -7,12 +7,13 @@
font-weight: bold;
}
.asBar {
background-color: none !important;
.as_simple_link {
background: none;
border: none;
}
</ui:style>
<g:HTMLPanel>
<b:AlertBlock close="false" addStyleNames="{style.asBar}" ui:field="alertBlockNav">
<b:AlertBlock close="false" addStyleNames="as_simple_link" ui:field="alertBlockNav">
<b:Button ui:field="button_reload" title="Reload the page" type="LINK">Reload</b:Button>
</b:AlertBlock>
<g:HTMLPanel ui:field="panel_container">

View File

@ -19,6 +19,7 @@ import com.google.gwt.core.client.GWT;
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.user.cellview.client.SimplePager;
import com.google.gwt.user.cellview.client.SimplePager.TextLocation;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTML;
@ -54,6 +55,7 @@ public class ContentModeratorPaginatedView {
private ItemStatus itemStatus;
private int serverStartIndex;
private HandlerManager eventBus;
private boolean restrictDataToLoggedInUser;
/**
* Instantiates a new content moderator paginated view.
@ -62,10 +64,12 @@ public class ContentModeratorPaginatedView {
* @param theStatus the the status
* @param displayFields the display fields
* @param sortByField the sort by field
* @param restrictDataToLoggedInUser the restrict data to logged in user
*/
public ContentModeratorPaginatedView(HandlerManager eventbus, ItemStatus theStatus, DISPLAY_FIELD[] displayFields,
DISPLAY_FIELD sortByField) {
DISPLAY_FIELD sortByField, boolean restrictDataToLoggedInUser) {
this.itemStatus = theStatus;
this.restrictDataToLoggedInUser = restrictDataToLoggedInUser;
this.initClassFirstRangeChanged = true;
this.eventBus = eventbus;
itemsTable = new ItemsTable<CatalogueDataset>(eventbus, displayFields, sortByField);
@ -237,7 +241,7 @@ public class ContentModeratorPaginatedView {
+ ", serverIndex:" + serverIndex + "]");
CkanContentModeratorWidgetController.contentModeratorService.getDataForStatus(status, offset, limit,
serverIndex, new AsyncCallback<SearchedData>() {
serverIndex, restrictDataToLoggedInUser, new AsyncCallback<SearchedData>() {
@Override
public void onSuccess(SearchedData result) {
@ -317,4 +321,13 @@ public class ContentModeratorPaginatedView {
}
public void hideSelectableRow(boolean bool) {
Element tableEl = itemsTable.getCellTable().getElement();
if (bool)
tableEl.addClassName("hide_checkbox");
else
tableEl.removeClassName("hide_checkbox");
}
}

View File

@ -36,6 +36,7 @@ import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.Widget;
@ -73,6 +74,9 @@ public class HomeView extends Composite {
@UiField
Button permanentlyDelete;
@UiField
HorizontalPanel updateStatusActionPanel;
private ScrollPanel confirmPanelContainer = new ScrollPanel();
private List<NavLink> setStatusOptions = new ArrayList<NavLink>();
@ -82,6 +86,8 @@ public class HomeView extends Composite {
private HandlerManager eventBus;
private LoadingPanel actionInProgressLoader = new LoadingPanel(new HTML("Performing action..."));
private boolean readOnlyMode;
private boolean restrictDataToLoggedInUser;
/**
* The Interface HomeViewUiBinder.
@ -100,13 +106,18 @@ public class HomeView extends Composite {
* @param status the status
* @param displayFields the display fields
* @param sortByField the sort by field
* @param readOnlyMode the read only mode
* @param restrictDataToLoggedInUser the restrict data to logged in user
*/
public HomeView(HandlerManager eventBus, ItemStatus status, DISPLAY_FIELD[] displayFields,
DISPLAY_FIELD sortByField) {
DISPLAY_FIELD sortByField, boolean readOnlyMode, boolean restrictDataToLoggedInUser) {
initWidget(uiBinder.createAndBindUi(this));
setDisplayingWithStatus(status);
this.eventBus = eventBus;
paginatedView = new ContentModeratorPaginatedView(eventBus, status, displayFields, sortByField);
this.readOnlyMode = readOnlyMode;
this.restrictDataToLoggedInUser = restrictDataToLoggedInUser;
paginatedView = new ContentModeratorPaginatedView(eventBus, status, displayFields, sortByField,
restrictDataToLoggedInUser);
cmsPanel.addToCenter(paginatedView.getCellPanel());
cmsPanel.addToBottom(paginatedView.getPagerPanel());
panelContainer.add(cmsPanel.getPanel());
@ -130,13 +141,20 @@ public class HomeView extends Composite {
}
/**
* Show action loader.
*
* @param showActionInProgress the show action in progress
*/
private void showActionLoader(boolean showActionInProgress) {
GWT.log("Show action in progress: "+showActionInProgress);
GWT.log("Show action in progress: " + showActionInProgress);
actionLoaderPanel.setVisible(showActionInProgress);
}
/**
* Sets the status options according to item status selected
* Sets the status options according to item status selected.
*
* @param selectedStatus the new status options
*/
private void setStatusOptions(ItemStatus selectedStatus) {
@ -148,16 +166,16 @@ public class HomeView extends Composite {
navLink.setVisible(false);
}
//Hiding the changing REJECT -> APPROVED
//One item REJECT must be only updated to return to PENDING status
if(selectedStatus.equals(ItemStatus.REJECTED)) {
// Hiding the changing REJECT -> APPROVED
// One item REJECT must be only updated to return to PENDING status
if (selectedStatus.equals(ItemStatus.REJECTED)) {
if (navLink.getText().trim().equals(ItemStatus.APPROVED.getLabel())) {
navLink.setVisible(false);
}
}
//Hiding the changing of any status from the APPROVED
if(selectedStatus.equals(ItemStatus.APPROVED)) {
// Hiding the changing of any status from the APPROVED
if (selectedStatus.equals(ItemStatus.APPROVED)) {
navLink.setVisible(false);
}
@ -343,7 +361,8 @@ public class HomeView extends Composite {
showActionLoader(true);
List<String> listDatasetNames = UtilFunct.toListDatasetNames(doActionCMS.getListSelectItems());
CkanContentModeratorWidgetController.contentModeratorService.permanentlyDelete(listDatasetNames, new AsyncCallback<OperationReport>() {
CkanContentModeratorWidgetController.contentModeratorService.permanentlyDelete(listDatasetNames,
new AsyncCallback<OperationReport>() {
@Override
public void onFailure(Throwable caught) {
@ -374,13 +393,14 @@ public class HomeView extends Composite {
if (errorCount > 0) {
msg += " <br/>Error occurred on deleting permanently " + errorCount + " item/s:";
for (String key : result.getErrorMapItems().keySet()) {
msg += "<br/> "+ key+". Error: "+ result.getErrorMapItems().get(key);
msg += "<br/> " + key + ". Error: " + result.getErrorMapItems().get(key);
}
alert = AlertType.WARNING;
}
eventBus.fireEvent(new SelectItemsWithItemStatusEvent(displayingItemStatus, msg, alert));
eventBus.fireEvent(
new SelectItemsWithItemStatusEvent(displayingItemStatus, msg, alert));
}
});
@ -457,7 +477,7 @@ public class HomeView extends Composite {
if (errorCount > 0) {
msg += " <br/>Error occurred on updating status to " + errorCount + " item/s:";
for (String key : result.getErrorMapItems().keySet()) {
msg += "<br/> "+ key+". Error: "+ result.getErrorMapItems().get(key);
msg += "<br/> " + key + ". Error: " + result.getErrorMapItems().get(key);
}
alert = AlertType.WARNING;
@ -512,7 +532,7 @@ public class HomeView extends Composite {
if (errorCount > 0) {
msg += " <br/>Error occurred on approving " + errorCount + " item/s:";
for (String key : result.getErrorMapItems().keySet()) {
msg += "<br/> "+ key+". Error: "+ result.getErrorMapItems().get(key);
msg += "<br/> " + key + ". Error: " + result.getErrorMapItems().get(key);
}
alert = AlertType.WARNING;
@ -554,10 +574,9 @@ public class HomeView extends Composite {
boolean isPermanentlyDelete = doActionCMSView.isPermanentlyDelete();
if(isPermanentlyDelete) {
if (isPermanentlyDelete) {
msg += " deleted permanently from Catalogue";
}
else {
} else {
msg += " moved to " + toStatus + " status.";
}
}
@ -566,7 +585,7 @@ public class HomeView extends Composite {
if (errorCount > 0) {
msg += " <br/>Error occurred on rejecting " + errorCount + " item/s:";
for (String key : result.getErrorMapItems().keySet()) {
msg += "<br/> "+ key+". Error: "+ result.getErrorMapItems().get(key);
msg += "<br/> " + key + ". Error: " + result.getErrorMapItems().get(key);
}
alert = AlertType.WARNING;
@ -584,8 +603,49 @@ public class HomeView extends Composite {
}
}
/**
* Gets the displaying item status.
*
* @return the displaying item status
*/
public ItemStatus getDisplayingItemStatus() {
return displayingItemStatus;
}
/**
* Hide update status action.
*
* @param readOnlyMode the read only mode
*/
public void hideUpdateStatusAction(boolean readOnlyMode) {
updateStatusActionPanel.setVisible(!readOnlyMode);
}
/**
* Hide selectable row.
*
* @param bool the bool
*/
public void hideSelectableRow(boolean bool) {
paginatedView.hideSelectableRow(bool);
}
/**
* Checks if is read only mode.
*
* @return true, if is read only mode
*/
public boolean isReadOnlyMode() {
return readOnlyMode;
}
/**
* Checks if is restrict data to logged in user.
*
* @return true, if is restrict data to logged in user
*/
public boolean isRestrictDataToLoggedInUser() {
return restrictDataToLoggedInUser;
}
}

View File

@ -42,7 +42,7 @@
<b:Heading ui:field="pageHeader" size="4"
addStyleNames="{style.headinghome}">Items with status: </b:Heading>
<g:HorizontalPanel
addStyleNames="{style.font-size-14}">
addStyleNames="{style.font-size-14}" ui:field="updateStatusActionPanel">
<b:CheckBox ui:field="cbSelectAll"
addStyleNames="{style.margin-left-5}"></b:CheckBox>
<b:Nav>

View File

@ -22,8 +22,17 @@
vertical-align: middle !important;
}
.hide_checkbox input[type="checkbox"] {
display: none;
}
/***** WS EXPLORER DOCK PANEL - CENTER FLOW PANEL *****/
.we-dock-center-panel {
overflow-y: auto !important;
/* border: 1px solid #DDD; */
}
.as_simple_link {
background: none;
border: none;
}

View File

@ -7,11 +7,14 @@ import java.util.Map;
import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.datacatalogue.utillibrary.gcat.GCatCaller;
import org.gcube.datacatalogue.utillibrary.server.DataCatalogueImpl;
import org.gcube.datacatalogue.utillibrary.server.cms.CatalogueContentModeratorSystem;
import org.gcube.datacatalogue.utillibrary.shared.ItemStatus;
import org.gcube.datacatalogue.utillibrary.shared.jackan.model.CkanDataset;
import org.gcube.portlets.widgets.ckancontentmoderator.client.CkanContentModeratorService;
import org.gcube.portlets.widgets.ckancontentmoderator.client.ContentModeratorWidgetConstants;
import org.gcube.portlets.widgets.ckancontentmoderator.server.CkanContentModeratorUtil.QUERY_OPERATOR;
import org.gcube.portlets.widgets.ckancontentmoderator.shared.CMSUserRole;
import org.gcube.portlets.widgets.ckancontentmoderator.shared.CatalogueDataset;
import org.gcube.portlets.widgets.ckancontentmoderator.shared.ModerationUserRole;
@ -73,6 +76,63 @@ public class CkanContentModeratorServiceImpl extends RemoteServiceServlet implem
return isCatalogueModerator;
}
/**
* Exists my item in moderation.
*
* @return true if the user has at least one item moderatorated or in
* moderation.
* @throws Exception the exception
*/
@Override
public Boolean existsMyItemInModeration() throws Exception {
LOG.info("called existsMyItemInModeration");
try {
/*
* if(!GcubeContextUtil.isWithinPortal()) {
* LOG.warn("#### DEV MODE ENABLED #######"); boolean defaultValue = true;
* LOG.info("DEV MODE: existsMyItemInModeration returning: " + defaultValue);
* return defaultValue; }
*/
String scope = setContexts();
DataCatalogueImpl catalogueImpl = CatalogueCMSFactory.getFactory().getCatalogueImplPerScope(scope);
GCubeUser user = GcubeContextUtil.getCurrentUser(getThreadLocalRequest());
String valueOfQueryEmails = CkanContentModeratorUtil.userQueryForEmails(user, QUERY_OPERATOR.OR);
/// BUILDING MODERATION_STATUS QUERY
String system_cm_prefix = GCatCaller.MODERATOR_ITEM_STATUS_FIELD_NAME;
StringBuilder queryValuesBuilder = new StringBuilder();
// QUERYING AUTHOR_MAIL MUST BE IN LIST OF EMAIL
queryValuesBuilder
.append(ContentModeratorWidgetConstants.CKAN_FIELD_NAME_AUTHOR_MAIL + ":" + valueOfQueryEmails);
queryValuesBuilder.append(" AND ");
// QUERYING THE ITEM MUST HAVE THE MODERATIONS STATUS
queryValuesBuilder.append("extras_" + system_cm_prefix + ":*");
Map<String, String> query = new HashMap<String, String>(1);
query.put("q", queryValuesBuilder.toString());
String listItems = catalogueImpl.performQuery(query);
LOG.debug("query returned items: " + listItems);
boolean haveItemInModeration = false;
if (listItems != null && !listItems.isEmpty()) {
haveItemInModeration = true;
}
LOG.info("existsMyItemInModeration returning: " + haveItemInModeration);
return haveItemInModeration;
} catch (Exception e) {
LOG.error("Error occured on checking existsMyItemInModeration, so returning false", e);
return false;
}
}
/**
* Gets the CMS roles for user in the context.
*
@ -111,19 +171,31 @@ public class CkanContentModeratorServiceImpl extends RemoteServiceServlet implem
* @param theStatus the the status
* @param offset the offset
* @param limit the limit
* @param restrictedToLoggedInUser if true restricts the list of items to logged
* in user
* @return the list items for status
* @throws Exception the exception
*/
@Override
public List<CatalogueDataset> getListItemsForStatus(ItemStatus theStatus, int offset, int limit) throws Exception {
LOG.info("called getListItemsForStatus with [status: " + theStatus + ", offset: " + offset + "], [limit: "
+ limit + "]");
public List<CatalogueDataset> getListItemsForStatus(ItemStatus theStatus, int offset, int limit,
boolean restrictedToLoggedInUser) throws Exception {
LOG.info("called getListItemsForStatus with [status: " + theStatus + ", offset: " + offset + ", limit: " + limit
+ ", restrictedToLoggedInUser: " + restrictedToLoggedInUser + "]");
List<CatalogueDataset> datasetList = null;
try {
String scope = setContexts();
DataCatalogueImpl catalogueImpl = CatalogueCMSFactory.getFactory().getCatalogueImplPerScope(scope);
CatalogueContentModeratorSystem cmsInstance = catalogueImpl.getCatalogueContentModerator();
List<CkanDataset> datasets = cmsInstance.getListItemsForStatus(theStatus, limit, offset);
Map<String, String> filters = null;
if (restrictedToLoggedInUser) {
filters = new HashMap<String, String>(1);
GCubeUser user = GcubeContextUtil.getCurrentUser(getThreadLocalRequest());
String valueOfQueryEmails = CkanContentModeratorUtil.userQueryForEmails(user, QUERY_OPERATOR.OR);
filters.put(ContentModeratorWidgetConstants.CKAN_FIELD_NAME_AUTHOR_MAIL, valueOfQueryEmails);
}
List<CkanDataset> datasets = cmsInstance.getListItemsForStatus(theStatus, limit, offset, filters);
if (datasets != null) {
int size = datasets.size();
datasetList = new ArrayList<CatalogueDataset>(size);
@ -306,8 +378,8 @@ public class CkanContentModeratorServiceImpl extends RemoteServiceServlet implem
* @throws Exception the exception
*/
@Override
public SearchedData getDataForStatus(ItemStatus status, int offset, int limit, int serverStartIndex)
throws Exception {
public SearchedData getDataForStatus(ItemStatus status, int offset, int limit, int serverStartIndex,
boolean restrictedToLoggedInUser) throws Exception {
LOG.info("called getDataForStatus [status: " + status + ", offset: " + offset + ", limit: " + limit
+ ", serverIndex: " + serverStartIndex);
@ -315,16 +387,25 @@ public class CkanContentModeratorServiceImpl extends RemoteServiceServlet implem
int searchStartIndex = offset;
CatalogueContentModeratorSystem cmsInstance = CatalogueCMSFactory.getFactory().getCMSPerScope(scope);
SearchedData searchedData = new SearchedData(offset, limit, searchStartIndex, false);
long totalItemsForStatus = cmsInstance.countListItemsForStatus(status);
Map<String, String> filters = null;
if (restrictedToLoggedInUser) {
filters = new HashMap<String, String>(1);
GCubeUser user = GcubeContextUtil.getCurrentUser(getThreadLocalRequest());
String valueOfQueryEmails = CkanContentModeratorUtil.userQueryForEmails(user, QUERY_OPERATOR.OR);
filters.put(ContentModeratorWidgetConstants.CKAN_FIELD_NAME_AUTHOR_MAIL, valueOfQueryEmails);
}
long totalItemsForStatus = cmsInstance.countListItemsForStatus(status, filters);
LOG.info("totalItemsForStatus " + status + " are : " + totalItemsForStatus);
List<CatalogueDataset> listDataset = new ArrayList<CatalogueDataset>();
try {
LOG.debug("getListItemsForStatus with searchStartIndex: " + searchStartIndex + ", limit: " + limit);
listDataset = getListItemsForStatus(status, searchStartIndex, limit);
listDataset = getListItemsForStatus(status, searchStartIndex, limit, restrictedToLoggedInUser);
} catch (Exception e) {
String error = "Error occurred on getting items for status: " + status;
LOG.error(error, e);
throw new Exception(error+". Cause: "+e.getMessage());
throw new Exception(error + ". Cause: " + e.getMessage());
}
int listDatasetSize = listDataset.size();

View File

@ -0,0 +1,102 @@
package org.gcube.portlets.widgets.ckancontentmoderator.server;
import java.util.ArrayList;
import java.util.List;
import org.gcube.vomanagement.usermanagement.model.Email;
import org.gcube.vomanagement.usermanagement.model.GCubeUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The Class CkanContentModeratorUtil.
*
* @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it
*
* Apr 6, 2022
*/
public class CkanContentModeratorUtil {
private static Logger LOG = LoggerFactory.getLogger(CkanContentModeratorUtil.class);
public static enum QUERY_OPERATOR {
AND, OR
}
/**
* User query for emails.
*
* @param user the user
* @return the string representing the value of the query for filtering for User
* Mails
* @throws Exception the exception
*/
public static String userQueryForEmails(GCubeUser user, QUERY_OPERATOR operator) throws Exception {
LOG.debug("userQueryForEmails called for user {}", user);
List<Email> listServerEmails = user.getEmailAddresses();
LOG.debug("List server mails: {}", listServerEmails);
List<String> emailsAddresses = new ArrayList<String>();
boolean notFoundMail = listServerEmails == null || listServerEmails.isEmpty();
if (notFoundMail) {
LOG.warn("No list mail found in " + GCubeUser.class.getSimpleName() + " getEmailAddresses()");
String mail = user.getEmail();
LOG.debug("Read mail: " + mail);
if (mail != null && !mail.isEmpty()) {
LOG.info("Email found in " + GCubeUser.class.getSimpleName() + " getEmail()");
emailsAddresses.add(mail);
}
} else {
for (Email email : listServerEmails) {
emailsAddresses.add(email.getEmail());
}
}
LOG.info("Email/s found for user {} is/are: {}", user.getUsername(), emailsAddresses);
if (emailsAddresses.isEmpty()) {
throw new Exception("No email found for user: " + user.getUsername());
}
if (operator == null)
operator = QUERY_OPERATOR.OR;
StringBuilder queryMails = new StringBuilder();
String queryOperator = operator.name();
// BUILDING EMAILS QUERY
int numberOfEmails = emailsAddresses.size();
String theQuery = "";
// case 1 email address
if (numberOfEmails == 1) {
theQuery = "'" + emailsAddresses.get(0) + "'";
} else {
// case N > 1 email addresses
for (int i = 0; i < emailsAddresses.size() - 1; i++) {
String email = emailsAddresses.get(i);
if (i == 0) {
// opening the query and adding first email address
queryMails.append("('" + email + "'");
} else {
// adding the operator and the email address
queryMails.append(" " + queryOperator + " '" + email + "'");
}
}
theQuery = queryMails.toString();
// to be sure that endsWith Operator
if (!theQuery.endsWith(queryOperator)) {
theQuery += " " + queryOperator + " ";
}
// adding last email address and closing the query
theQuery += "'" + emailsAddresses.get(numberOfEmails - 1) + "')";
}
return theQuery;
}
}

View File

@ -2,14 +2,16 @@ package org.gcube.portlets.widgets.ckancontentmoderator.server;
import static org.junit.Assert.fail;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.datacatalogue.utillibrary.server.cms.CatalogueContentModeratorSystem;
import org.gcube.datacatalogue.utillibrary.shared.ItemStatus;
import org.gcube.datacatalogue.utillibrary.shared.jackan.model.CkanDataset;
import org.junit.Test;
import org.gcube.portlets.widgets.ckancontentmoderator.client.ContentModeratorWidgetConstants;
import org.slf4j.LoggerFactory;
public class CkanContentModeratorServiceTest {
@ -33,7 +35,9 @@ public class CkanContentModeratorServiceTest {
ItemStatus itemStatus = ItemStatus.PENDING;
try {
CatalogueContentModeratorSystem cms = CatalogueCMSFactory.getFactory().getCMSPerScope(scope);
List<CkanDataset> items = cms.getListItemsForStatus(itemStatus, 20, 0);
Map<String, String> filters = new HashMap<String, String>(1);
filters.put(ContentModeratorWidgetConstants.CKAN_FIELD_NAME_AUTHOR_MAIL, "francesco.mangiacrapa@isti.cnr.it");
List<CkanDataset> items = cms.getListItemsForStatus(itemStatus, 20, 0, filters);
int i = 0;
System.out.println("Datasets with status "+itemStatus+" are: "+items.size());
for (CkanDataset ckanDataset : items) {