From 5c46c8d997189f4d36629af69ddae162dad1fb37 Mon Sep 17 00:00:00 2001 From: Francesco Mangiacrapa Date: Mon, 20 Feb 2017 10:42:17 +0000 Subject: [PATCH] Starting work on versioning #7006 git-svn-id: http://svn.d4science-ii.research-infrastructures.eu/gcube/trunk/portlets/user/workspace@142753 82a268e6-3cf1-43bd-a215-b396298e98cf --- .../view/version/VersioningInfoContainer.java | 496 ++++++++++++++++++ .../client/view/version/WindowVersioning.java | 291 ++++++++++ 2 files changed, 787 insertions(+) create mode 100644 src/main/java/org/gcube/portlets/user/workspace/client/view/version/VersioningInfoContainer.java create mode 100644 src/main/java/org/gcube/portlets/user/workspace/client/view/version/WindowVersioning.java diff --git a/src/main/java/org/gcube/portlets/user/workspace/client/view/version/VersioningInfoContainer.java b/src/main/java/org/gcube/portlets/user/workspace/client/view/version/VersioningInfoContainer.java new file mode 100644 index 0000000..f20c730 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspace/client/view/version/VersioningInfoContainer.java @@ -0,0 +1,496 @@ +package org.gcube.portlets.user.workspace.client.view.version; + +import java.util.Arrays; +import java.util.List; + +import org.gcube.portlets.user.workspace.client.AppController; +import org.gcube.portlets.user.workspace.client.event.FileVersioningEvent; +import org.gcube.portlets.user.workspace.client.interfaces.GXTFolderItemTypeEnum; +import org.gcube.portlets.user.workspace.client.model.FileModel; +import org.gcube.portlets.user.workspace.client.resources.Resources; +import org.gcube.portlets.user.workspace.client.view.windows.DialogConfirm; +import org.gcube.portlets.user.workspace.shared.WorkspaceTrashOperation; +import org.gcube.portlets.user.workspace.shared.WorkspaceVersioningOperation; + +import com.extjs.gxt.ui.client.Style.ButtonScale; +import com.extjs.gxt.ui.client.Style.HorizontalAlignment; +import com.extjs.gxt.ui.client.Style.IconAlign; +import com.extjs.gxt.ui.client.Style.Scroll; +import com.extjs.gxt.ui.client.event.ButtonEvent; +import com.extjs.gxt.ui.client.event.SelectionChangedEvent; +import com.extjs.gxt.ui.client.event.SelectionChangedListener; +import com.extjs.gxt.ui.client.event.SelectionListener; +import com.extjs.gxt.ui.client.store.GroupingStore; +import com.extjs.gxt.ui.client.store.ListStore; +import com.extjs.gxt.ui.client.store.Record; +import com.extjs.gxt.ui.client.widget.ContentPanel; +import com.extjs.gxt.ui.client.widget.LayoutContainer; +import com.extjs.gxt.ui.client.widget.MessageBox; +import com.extjs.gxt.ui.client.widget.button.Button; +import com.extjs.gxt.ui.client.widget.grid.ColumnConfig; +import com.extjs.gxt.ui.client.widget.grid.ColumnData; +import com.extjs.gxt.ui.client.widget.grid.ColumnModel; +import com.extjs.gxt.ui.client.widget.grid.Grid; +import com.extjs.gxt.ui.client.widget.grid.GridCellRenderer; +import com.extjs.gxt.ui.client.widget.grid.GroupingView; +import com.extjs.gxt.ui.client.widget.grid.filters.GridFilters; +import com.extjs.gxt.ui.client.widget.grid.filters.StringFilter; +import com.extjs.gxt.ui.client.widget.layout.FitLayout; +import com.extjs.gxt.ui.client.widget.menu.SeparatorMenuItem; +import com.extjs.gxt.ui.client.widget.toolbar.FillToolItem; +import com.extjs.gxt.ui.client.widget.toolbar.ToolBar; +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.ClickHandler; + +/** + * The Class VersioningInfoContainer. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Feb 17, 2017 + */ +public class VersioningInfoContainer extends LayoutContainer { + + private Grid grid; + private ContentPanel cp; + private GroupingStore store = new GroupingStore(); + private ListStore typeStoreOperation = new ListStore(); + //private GridDropTarget gridDropTarget; + private Button buttonDelete; + private Button buttonRestore; + private Button buttonRestoreAll; + private Button buttonEmptyTrash; + private FileModel fileVersioned; + + /** + * Instantiates a new versioning info container. + * + * @param file the versioning files + */ + public VersioningInfoContainer(FileModel file) { + + initContentPanel(); + initGrid(); + createToolBar(); + this.fileVersioned = file; + + activeButtonOnSelection(false); + //updateVersions(file); + } + + /** + * Inits the content panel. + */ + private void initContentPanel() { + setLayout(new FitLayout()); + getAriaSupport().setPresentation(true); + cp = new ContentPanel(); + cp.setHeaderVisible(false); + cp.setBodyBorder(true); + cp.setLayout(new FitLayout()); + cp.setButtonAlign(HorizontalAlignment.CENTER); + cp.setScrollMode(Scroll.AUTOY); + add(cp); + } + + /** + * Check selection. + * + * @return true, if successful + */ + private boolean checkSelection(){ + + if(grid.getSelectionModel().getSelectedItems().size()==0){ + MessageBox.info("Attention", "You must pick at least one item", null); + return false; + } + + return true; + } + + /** + * Creates the tool bar. + */ + private void createToolBar() { + + ToolBar bar = new ToolBar(); + + buttonRestore = new Button(WorkspaceVersioningOperation.RESTORE.getLabel(),Resources.getIconUndo()); + buttonRestore.setToolTip(WorkspaceVersioningOperation.RESTORE.getOperationDescription()); + buttonRestore.setScale(ButtonScale.SMALL); + buttonRestore.setIconAlign(IconAlign.TOP); + + buttonRestore.addSelectionListener(new SelectionListener() { + + @Override + public void componentSelected(ButtonEvent ce) { + + if(checkSelection()) + AppController.getEventBus().fireEvent(new FileVersioningEvent(WorkspaceVersioningOperation.RESTORE, grid.getSelectionModel().getSelectedItems().get(0))); + } + }); + + bar.add(buttonRestore); + + + buttonDelete = new Button(WorkspaceVersioningOperation.DELETE_PERMANENTLY.getLabel(),Resources.getIconDeleteItem()); + buttonDelete.setToolTip(WorkspaceVersioningOperation.DELETE_PERMANENTLY.getOperationDescription()); + buttonDelete.setScale(ButtonScale.SMALL); + buttonDelete.setIconAlign(IconAlign.TOP); + buttonDelete.addSelectionListener(new SelectionListener() { + + @Override + public void componentSelected(ButtonEvent ce) { + + if(checkSelection()) + AppController.getEventBus().fireEvent(new FileVersioningEvent(WorkspaceVersioningOperation.DELETE_PERMANENTLY, grid.getSelectionModel().getSelectedItems().get(0))); + + } + }); + + bar.add(buttonDelete); + + + bar.add(new SeparatorMenuItem()); + + buttonRestoreAll = new Button(WorkspaceVersioningOperation.DOWNLOAD.getLabel(),Resources.getIconRecycle()); + buttonRestoreAll.setToolTip(WorkspaceVersioningOperation.DOWNLOAD.getOperationDescription()); + buttonRestoreAll.setScale(ButtonScale.SMALL); + buttonRestoreAll.setIconAlign(IconAlign.TOP); + buttonRestoreAll.addSelectionListener(new SelectionListener() { + + @Override + public void componentSelected(ButtonEvent ce) { + + if(checkSelection()) + AppController.getEventBus().fireEvent(new FileVersioningEvent(WorkspaceVersioningOperation.DOWNLOAD, grid.getSelectionModel().getSelectedItems().get(0))); + } + }); + + bar.add(buttonRestoreAll); + + + buttonEmptyTrash = new Button(WorkspaceVersioningOperation.EMPTY_OLDER_VERSIONS.getLabel(),Resources.getTrashEmpty()); + buttonEmptyTrash.setToolTip(WorkspaceVersioningOperation.EMPTY_OLDER_VERSIONS.getOperationDescription()); + buttonEmptyTrash.setScale(ButtonScale.SMALL); + buttonEmptyTrash.setIconAlign(IconAlign.TOP); + buttonEmptyTrash.addSelectionListener(new SelectionListener() { + + @Override + public void componentSelected(ButtonEvent ce) { + +// if(checkSelection()) +// AppController.getEventBus().fireEvent(new FileVersioningEvent(WorkspaceVersioningOperation.EMPTY_OLDER_VERSIONS, null)); + + DialogConfirm box = new DialogConfirm(null, "Confirm Delete?", "Are you sure you want delete older versions of: "+ fileVersioned.getName()); + box.setModal(true); + box.center(); + box.getYesButton().addClickHandler(new ClickHandler() { + + @Override + public void onClick(ClickEvent event) { + + AppController.getEventBus().fireEvent(new FileVersioningEvent(WorkspaceVersioningOperation.EMPTY_OLDER_VERSIONS, fileVersioned)); + } + }); + } + }); + + bar.add(buttonEmptyTrash); + + + bar.add(new FillToolItem()); + + Button buttonRefresh = new Button(WorkspaceTrashOperation.REFRESH.getLabel(),Resources.getIconRefresh()); + buttonRefresh.setToolTip(WorkspaceTrashOperation.REFRESH.getOperationDescription()); + buttonRefresh.setScale(ButtonScale.SMALL); + buttonRefresh.setIconAlign(IconAlign.TOP); + buttonRefresh.addSelectionListener(new SelectionListener() { + + @Override + public void componentSelected(ButtonEvent ce) { + + AppController.getEventBus().fireEvent(new FileVersioningEvent(WorkspaceVersioningOperation.REFRESH, null)); + } + }); + + bar.add(buttonRefresh); + + + cp.setTopComponent(bar); + + } + + /** + * Inits the grid. + */ + public void initGrid() { + + //ColumnConfig icon = new ColumnConfig(FileGridModel.ICON, "", 25); + ColumnConfig name = createSortableColumnConfig(FileModel.NAME, FileModel.NAME, 200); + ColumnConfig type = createSortableColumnConfig(FileModel.TYPE, FileModel.TYPE, 80); + //ColumnConfig originalPath = createSortableColumnConfig(FileTrashedModel.STOREINFO.ORIGINALPATH.toString(), "Original Path", 200); + //ColumnConfig deleteDate = createSortableColumnConfig(FileTrashedModel.STOREINFO.DELETEDATE.toString(), "Deleted Date", 90); + //deleteDate.setDateTimeFormat(DateTimeFormat.getFormat("dd MMM hh:mm aaa yyyy")); + //ColumnConfig deleteUser = createSortableColumnConfig(FileTrashedModel.STOREINFO.DELETEUSER.toString(), "Deleted By", 150); + + //ColumnModel cm = new ColumnModel(Arrays.asList(icon, name, type, originalPath, deleteDate, deleteUser)); + + ColumnModel cm = new ColumnModel(Arrays.asList(name)); + + final ColumnModel columnModel = cm; + + grid = new Grid(this.store, cm); + + GroupingView view = new GroupingView(); + view.setShowGroupedColumn(false); + + this.grid.setView(view); + this.grid.setContextMenu(null); + + + GridCellRenderer folderRender = new GridCellRenderer() { + @Override + public String render(FileModel model, String property, ColumnData config, int rowIndex, int colIndex, ListStore store, Grid grid) { + String val = model.get(property); + String color = "black"; + + if(val != null && val.equals(GXTFolderItemTypeEnum.FOLDER.toString())){ +// color = "#EEC900"; + return "" + val + ""; + }else{ + if(val==null) + val = ""; + return "" + val + ""; + } + } + }; + + type.setRenderer(folderRender); + + GridFilters filters = new GridFilters(); + filters.setLocal(true); + + + StringFilter nameFilter = new StringFilter(FileModel.NAME); + StringFilter typeFilter = new StringFilter(FileModel.TYPE); + + //DateFilter dateFilter = new DateFilter(FileModel.STOREINFO.DELETEDATE.toString()); + + filters.addFilter(nameFilter); + filters.addFilter(typeFilter); + //filters.addFilter(dateFilter); + + grid.addPlugin(filters); + + grid.getSelectionModel().addSelectionChangedListener(new SelectionChangedListener() { + + @Override + public void selectionChanged(SelectionChangedEvent se) { + + boolean selection = grid.getSelectionModel().getSelectedItems().size()>0; + activeButtonOnSelection(selection); + } + }); + + grid.getView().setAutoFill(true); + grid.setBorders(true); + grid.setStripeRows(true); + grid.getView().setShowDirtyCells(false); + grid.setColumnLines(true); + grid.setColumnReordering(true); + grid.setStyleAttribute("borderTop", "none"); + cp.add(grid); + + + } + + + + /** + * Sets the panel size. + * + * @param width the width + * @param height the height + */ + public void setPanelSize(int width, int height) { + + if (width > 0 && height > 0 && grid != null) { + cp.setSize(width, height); + // grid.setSize(width, height); + } + } + + + + + + /** + * Update versions. + * + * @param versioningFiles the versioning files + */ + public void updateVersions(List versioningFiles) { + + store.removeAll(); + typeStoreOperation.removeAll(); + +// for (FileModel fileTrashedModel : trashFiles) { +// fileTrashedModel.setIcon(); +// } + + store.add(versioningFiles); + activeButtonsOnNotEmtpy(store.getModels().size()>0); + } + + /** + * Active buttons on not emtpy. + * + * @param isNotEmpty the is not empty + */ + private void activeButtonsOnNotEmtpy(boolean isNotEmpty) { + buttonRestoreAll.setEnabled(isNotEmpty); + buttonEmptyTrash.setEnabled(isNotEmpty); + } + + /** + * Active button on selection. + * + * @param bool the bool + */ + protected void activeButtonOnSelection(boolean bool) { + buttonDelete.setEnabled(bool); + buttonRestore.setEnabled(bool); + } + + /** + * Update store. + * + * @param store the store + */ + private void updateStore(ListStore store) { + + resetStore(); + this.grid.getStore().add(store.getModels()); + } + + /** + * Reset store. + */ + public void resetStore() { + this.grid.getStore().removeAll(); + } + + /** + * Creates the sortable column config. + * + * @param id the id + * @param name the name + * @param width the width + * @return the column config + */ + public ColumnConfig createSortableColumnConfig(String id, String name, + int width) { + ColumnConfig columnConfig = new ColumnConfig(id, name, width); + columnConfig.setSortable(true); + + return columnConfig; + } + + /** + * Sets the header title. + * + * @param title the new header title + */ + public void setHeaderTitle(String title) { + cp.setHeading(title); + // cp.layout(); + } + + /** + * Gets the file model by identifier. + * + * @param identifier the identifier + * @return the file model by identifier + */ + public FileModel getFileModelByIdentifier(String identifier){ + + return store.findModel(FileModel.IDENTIFIER, identifier); + + } + + /** + * Delete item. + * + * @param identifier (MANDATORY) + * @return true, if successful + */ + public boolean deleteItem(String identifier) { + + FileModel fileTarget = getFileModelByIdentifier(identifier); + + + if(fileTarget!=null){ + return deleteItem(fileTarget); + } + else + System.out.println("Delete Error: file target with " + identifier + " identifier not exist in store" ); + + return false; + } + + /** + * Delete item. + * + * @param fileTarget (MANDATORY) + * @return true, if successful + */ + private boolean deleteItem(FileModel fileTarget) { + + Record record = store.getRecord(fileTarget); + + if (record != null) { + + FileModel item = (FileModel) record.getModel(); + store.remove(item); + + return true; + } else + System.out.println("Record Error: file target with " + + fileTarget.getIdentifier() + + " identifier not exist in store"); + + activeButtonsOnNotEmtpy(store.getModels().size()>0); + + return false; + + } + + + /** + * Versioning items. + * + * @return the int + */ + public int versioningItems(){ + return store.getCount(); + } + + /** + * Gets the store. + * + * @return the store + */ + protected GroupingStore getStore() { + return store; + } + + /** + * Gets the cp. + * + * @return the cp + */ + public ContentPanel getCp() { + return cp; + } + +} \ No newline at end of file diff --git a/src/main/java/org/gcube/portlets/user/workspace/client/view/version/WindowVersioning.java b/src/main/java/org/gcube/portlets/user/workspace/client/view/version/WindowVersioning.java new file mode 100644 index 0000000..8f2a6b1 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspace/client/view/version/WindowVersioning.java @@ -0,0 +1,291 @@ +package org.gcube.portlets.user.workspace.client.view.version; + +import java.util.ArrayList; +import java.util.List; + +import org.gcube.portlets.user.workspace.client.AppController; +import org.gcube.portlets.user.workspace.client.ConstantsExplorer; +import org.gcube.portlets.user.workspace.client.event.UpdateWorkspaceSizeEvent; +import org.gcube.portlets.user.workspace.client.model.FileModel; +import org.gcube.portlets.user.workspace.client.resources.Resources; +import org.gcube.portlets.user.workspace.shared.WorkspaceVersioningOperation; + +import com.extjs.gxt.ui.client.Style.HorizontalAlignment; +import com.extjs.gxt.ui.client.Style.Scroll; +import com.extjs.gxt.ui.client.data.ModelData; +import com.extjs.gxt.ui.client.event.Listener; +import com.extjs.gxt.ui.client.store.Store; +import com.extjs.gxt.ui.client.store.StoreEvent; +import com.extjs.gxt.ui.client.widget.ContentPanel; +import com.extjs.gxt.ui.client.widget.Dialog; +import com.extjs.gxt.ui.client.widget.HorizontalPanel; +import com.extjs.gxt.ui.client.widget.Html; +import com.extjs.gxt.ui.client.widget.Label; +import com.extjs.gxt.ui.client.widget.Window; +import com.extjs.gxt.ui.client.widget.layout.FitLayout; +import com.extjs.gxt.ui.client.widget.toolbar.ToolBar; + + +/** + * The Class WindowVersioning. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Feb 17, 2017 + */ +public class WindowVersioning extends Window { + + private List versionedFile; + private VersioningInfoContainer versioningContainer; + private HorizontalPanel hpItemsNumber; + private Label labelItemsNumber = new Label(); + private FileModel fileVersioned; + + + /** + * Instantiates a new window versioning. + * + * @param fileVersioned the file versioned + */ + private WindowVersioning(FileModel fileVersioned) { + initAccounting(); + this.fileVersioned = fileVersioned; + //setIcon(Resources.getTrashFull()); //TODO + setHeading("Versions of: "+fileVersioned.getName()); + } + + /** + * This method is called only once. + */ + private void initAccounting() { + setLayout(new FitLayout()); + setSize(770, 400); + setResizable(true); + setMaximizable(true); + this.versioningContainer = new VersioningInfoContainer(fileVersioned); + add(versioningContainer); + + ToolBar toolBar = new ToolBar(); + hpItemsNumber = new HorizontalPanel(); + hpItemsNumber.setStyleAttribute("margin-left", "10px"); + hpItemsNumber.setHorizontalAlign(HorizontalAlignment.CENTER); + hpItemsNumber.add(labelItemsNumber); + toolBar.add(hpItemsNumber); + + setBottomComponent(toolBar); + addStoreListeners(); + } + + + /** + * Adds the store listeners. + */ + private void addStoreListeners() { + + versioningContainer.getStore().addListener(Store.Add, new Listener>(){ + + @Override + public void handleEvent(StoreEvent be) { + updateItemsNumber(storeSize()); + AppController.getEventBus().fireEvent(new UpdateWorkspaceSizeEvent()); + } + }); + + versioningContainer.getStore().addListener(Store.Remove, new Listener>(){ + + @Override + public void handleEvent(StoreEvent be) { + updateItemsNumber(storeSize()); + AppController.getEventBus().fireEvent(new UpdateWorkspaceSizeEvent()); + } + }); + + versioningContainer.getStore().addListener(Store.Clear, new Listener>(){ + + @Override + public void handleEvent(StoreEvent be) { + updateItemsNumber(storeSize()); + AppController.getEventBus().fireEvent(new UpdateWorkspaceSizeEvent()); + } + }); + + } + + /** + * Update items number. + * + * @param size the size + */ + public void updateItemsNumber(int size) { + if(size<=0) + labelItemsNumber.setText("No Items"); + else if(size==1) + labelItemsNumber.setText("1 Item"); + else if(size>1) + labelItemsNumber.setText(size +" Items"); + + hpItemsNumber.layout(); + } + + /** + * Sets the window title. + * + * @param title the new window title + */ + public void setWindowTitle(String title) { + this.setHeading(title); + + } + + /** + * Store size. + * + * @return -1 if store is null. The size otherwise + */ + private int storeSize(){ + + if(versioningContainer.getStore()!=null && versioningContainer.getStore().getModels()!=null){ + return versioningContainer.getStore().getModels().size(); + } + + return -1; + + } + + + /** + * Delete file from versioning. + * + * @param fileModelId the file model id + * @return true, if successful + */ + public boolean deleteFileFromVersioning(String fileModelId){ + boolean deleted = this.versioningContainer.deleteItem(fileModelId); + return deleted; + } + + + + /** + * Update versioning container. + * + * @param versioningFiles the versioning files + */ + public void updateVersioningContainer(List versioningFiles) { + + this.versioningContainer.resetStore(); + this.versionedFile = versioningFiles; + this.versioningContainer.updateVersions(versioningFiles); + } + + /** + * Execute operation on trash container. + * + * @param trashIds the trash ids + * @param operation the operation + */ + public void executeOperationOnVersioningContainer(List trashIds, WorkspaceVersioningOperation operation) { + + if(operation.equals(WorkspaceVersioningOperation.DELETE_PERMANENTLY)){ + this.mask("Deleting"); + deleteListItems(trashIds); + + }else if(operation.equals(WorkspaceVersioningOperation.RESTORE)){ + this.mask("Restoring"); + deleteListItems(trashIds); + } + + this.unmask(); + } + + /** + * Gets the versions of file. + * + * @return the versions of file + */ + public List getVersionsOfFile() { + return versionedFile; + } + + /** + * Delete list items. + * + * @param trashIds the trash ids + */ + private void deleteListItems(List trashIds){ + + for (String identifier : trashIds) { + this.versioningContainer.deleteItem(identifier); + } + + } + + /** + * Mask container. + * + * @param title the title + */ + public void maskContainer(String title){ + this.versioningContainer.mask(title, ConstantsExplorer.LOADINGSTYLE); + } + + /** + * Unmask container. + */ + public void unmaskContainer(){ + this.versioningContainer.unmask(); + } + + /** + * Show versioning error. + * + * @param operation the operation + * @param errors the errors + */ + public void showVersioningError(WorkspaceVersioningOperation operation, List errors){ + + if(errors!=null && errors.size()>0){ + + List fileNames = new ArrayList(errors.size()); + + //BUILDING NAMES + for (FileModel fileVersionModel : errors) { + + FileModel trashFile = versioningContainer.getFileModelByIdentifier(fileVersionModel.getIdentifier()); + fileNames.add(trashFile.getName()); + } + + String htmlError = "
Sorry an error occured on removing the "; + htmlError+=fileNames.size()>1?"items":"item"; + htmlError+=":
"; + + for (String fileName : fileNames) { + htmlError+="
- "+fileName; + } + + htmlError+="

"+"Try again later
"; + + Dialog dialog = new Dialog(); + dialog.setStyleAttribute("background-color", "#FAFAFA"); + dialog.setSize(380, 180); + dialog.setLayout(new FitLayout()); + dialog.setIcon(Resources.getIconInfo()); + dialog.setModal(true); + dialog.setHeading("Trash Errors"); + dialog.setButtons(Dialog.OK); + dialog.setHideOnButtonClick(true); + dialog.setButtonAlign(HorizontalAlignment.CENTER); +// dialog.setSize(200, 150); + + ContentPanel cp = new ContentPanel(); + cp.setHeaderVisible(false); + cp.setFrame(false); + cp.setScrollMode(Scroll.AUTOY); + cp.add(new Html(htmlError)); + dialog.add(cp); + dialog.show(); + + } + } + + +}