diff --git a/zanata-war/src/main/java/org/zanata/webtrans/client/Application.java b/zanata-war/src/main/java/org/zanata/webtrans/client/Application.java index 2eb6d2c5a3..87c1e3767c 100644 --- a/zanata-war/src/main/java/org/zanata/webtrans/client/Application.java +++ b/zanata-war/src/main/java/org/zanata/webtrans/client/Application.java @@ -250,6 +250,11 @@ public static String getVersionFilesURL(WorkspaceId workspaceId) return getModuleParentBaseUrl() + "iteration/files/" + workspaceId.getProjectIterationId().getProjectSlug() + "/" + workspaceId.getProjectIterationId().getIterationSlug() + "/" + workspaceId.getLocaleId().getId(); } + public static String getFileDownloadURL(WorkspaceId workspaceId, String docId) + { + return getModuleParentBaseUrl() + "rest/file/translation/" + workspaceId.getProjectIterationId().getProjectSlug() + "/" + workspaceId.getProjectIterationId().getIterationSlug() + "/" + workspaceId.getLocaleId().getId() + "/po?docId=" + docId; + } + public static native void redirectToUrl(String url)/*-{ $wnd.location = url; }-*/; diff --git a/zanata-war/src/main/java/org/zanata/webtrans/client/presenter/DocumentListPresenter.java b/zanata-war/src/main/java/org/zanata/webtrans/client/presenter/DocumentListPresenter.java index 2f84f7000b..773bc9de16 100644 --- a/zanata-war/src/main/java/org/zanata/webtrans/client/presenter/DocumentListPresenter.java +++ b/zanata-war/src/main/java/org/zanata/webtrans/client/presenter/DocumentListPresenter.java @@ -32,6 +32,7 @@ import org.zanata.webtrans.client.events.DocumentSelectionEvent; import org.zanata.webtrans.client.events.DocumentSelectionHandler; import org.zanata.webtrans.client.events.DocumentStatsUpdatedEvent; +import org.zanata.webtrans.client.events.NotificationEvent; import org.zanata.webtrans.client.events.ProjectStatsUpdatedEvent; import org.zanata.webtrans.client.events.TransUnitUpdatedEvent; import org.zanata.webtrans.client.events.TransUnitUpdatedEventHandler; @@ -40,6 +41,7 @@ import org.zanata.webtrans.client.history.History; import org.zanata.webtrans.client.history.HistoryToken; import org.zanata.webtrans.client.resources.WebTransMessages; +import org.zanata.webtrans.client.rpc.CachingDispatchAsync; import org.zanata.webtrans.client.service.UserOptionsService; import org.zanata.webtrans.client.ui.DocumentNode; import org.zanata.webtrans.client.ui.HasStatsFilter; @@ -48,9 +50,13 @@ import org.zanata.webtrans.shared.model.DocumentInfo; import org.zanata.webtrans.shared.model.TransUnitUpdateInfo; import org.zanata.webtrans.shared.model.UserWorkspaceContext; +import org.zanata.webtrans.shared.model.WorkspaceId; +import org.zanata.webtrans.shared.rpc.DownloadAllFilesAction; +import org.zanata.webtrans.shared.rpc.NoOpResult; import com.allen_sauer.gwt.log.client.Log; import com.google.gwt.event.logical.shared.SelectionEvent; +import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.view.client.ListDataProvider; import com.google.gwt.view.client.SelectionChangeEvent; import com.google.gwt.view.client.SingleSelectionModel; @@ -67,6 +73,8 @@ public class DocumentListPresenter extends WidgetPresenter private ListDataProvider dataProvider; private HashMap nodes; + + private final CachingDispatchAsync dispatcher; /** * For quick lookup of document id by full path (including document name). @@ -100,9 +108,10 @@ public void setSelected(DocumentNode object, boolean selected) }; @Inject - public DocumentListPresenter(DocumentListDisplay display, EventBus eventBus, UserWorkspaceContext userworkspaceContext, final WebTransMessages messages, History history, UserOptionsService userOptionsService) + public DocumentListPresenter(DocumentListDisplay display, EventBus eventBus, CachingDispatchAsync dispatcher, UserWorkspaceContext userworkspaceContext, final WebTransMessages messages, History history, UserOptionsService userOptionsService) { super(display, eventBus); + this.dispatcher = dispatcher; this.userworkspaceContext = userworkspaceContext; this.messages = messages; this.history = history; @@ -375,4 +384,24 @@ public void onUserConfigChanged(UserConfigChangeEvent event) display.updatePageSize(userOptionsService.getConfigHolder().getState().getDocumentListPageSize()); } } + + @Override + public void downloadAllFiles() + { + WorkspaceId workspaceId = userworkspaceContext.getWorkspaceContext().getWorkspaceId(); + dispatcher.execute(new DownloadAllFilesAction(workspaceId.getProjectIterationId().getProjectSlug(), workspaceId.getProjectIterationId().getIterationSlug(), workspaceId.getLocaleId().getId()), new AsyncCallback() + { + @Override + public void onFailure(Throwable caught) + { + eventBus.fireEvent(new NotificationEvent(NotificationEvent.Severity.Warning, "Unable generate all files to download")); + } + + @Override + public void onSuccess(NoOpResult result) + { + eventBus.fireEvent(new NotificationEvent(NotificationEvent.Severity.Warning, "Loaded all files")); + } + }); + } } diff --git a/zanata-war/src/main/java/org/zanata/webtrans/client/ui/DocumentListTable.java b/zanata-war/src/main/java/org/zanata/webtrans/client/ui/DocumentListTable.java index 2110a97569..b6cdb41792 100644 --- a/zanata-war/src/main/java/org/zanata/webtrans/client/ui/DocumentListTable.java +++ b/zanata-war/src/main/java/org/zanata/webtrans/client/ui/DocumentListTable.java @@ -22,11 +22,12 @@ import java.util.Comparator; +import org.zanata.webtrans.client.Application; import org.zanata.webtrans.client.resources.WebTransMessages; import org.zanata.webtrans.client.ui.table.column.RemainingHoursColumn; +import org.zanata.webtrans.client.ui.table.column.StaticWidgetColumn; import org.zanata.webtrans.client.ui.table.column.StatisticColumn; -import org.zanata.webtrans.client.ui.table.column.TranslatedColumn; -import org.zanata.webtrans.client.ui.table.column.UntranslatedColumn; +import org.zanata.webtrans.shared.model.WorkspaceId; import com.google.gwt.cell.client.IconCellDecorator; import com.google.gwt.cell.client.TextCell; @@ -37,6 +38,7 @@ import com.google.gwt.user.cellview.client.ColumnSortEvent.ListHandler; import com.google.gwt.user.cellview.client.Header; import com.google.gwt.user.cellview.client.TextColumn; +import com.google.gwt.user.client.ui.Anchor; import com.google.gwt.view.client.ListDataProvider; import com.google.gwt.view.client.SingleSelectionModel; @@ -86,12 +88,12 @@ public void setStatsFilter(String option) private final StatisticColumn statisticColumn; private final RemainingHoursColumn remainingColumn; - private final TextColumn lastModifiedDateColumn; - private final TextColumn lastModifiedByColumn; + private final TextColumn lastModifiedColumn; + private final StaticWidgetColumn actionColumn; private final StatisticHeader statisticColumnHeader; - public DocumentListTable(final org.zanata.webtrans.client.resources.Resources images, final WebTransMessages messages, final ListDataProvider dataProvider, final SingleSelectionModel selectionModel) + public DocumentListTable(final org.zanata.webtrans.client.resources.Resources images, final WebTransMessages messages, final ListDataProvider dataProvider, final SingleSelectionModel selectionModel, final WorkspaceId workspaceId) { super(15, (CellTableResources) GWT.create(CellTableResources.class)); @@ -119,26 +121,32 @@ public String getValue(DocumentNode object) statisticColumn = new StatisticColumn(messages); remainingColumn = new RemainingHoursColumn(messages); - lastModifiedDateColumn = new TextColumn() + lastModifiedColumn = new TextColumn() { @Override public String getValue(DocumentNode object) { + String date = ""; if(object.getDocInfo().getLastChanged() != null) { - String date = DateTimeFormat.getFormat(PredefinedFormat.DATE_TIME_SHORT).format(object.getDocInfo().getLastChanged()); - return date; + date = DateTimeFormat.getFormat(PredefinedFormat.DATE_TIME_SHORT).format(object.getDocInfo().getLastChanged()); } - return ""; + + String modifiedBy = object.getDocInfo().getLastModifiedBy(); + + return modifiedBy + " " + date; } }; - - lastModifiedByColumn = new TextColumn() + + actionColumn = new StaticWidgetColumn() { @Override - public String getValue(DocumentNode object) + public Anchor getValue(DocumentNode object) { - return object.getDocInfo().getLastModifiedBy(); + Anchor anchor = new Anchor(".po"); + anchor.setHref(Application.getFileDownloadURL(workspaceId, object.getDocInfo().getName())); + + return anchor; } }; @@ -146,7 +154,7 @@ public String getValue(DocumentNode object) documentColumn.setSortable(true); statisticColumn.setSortable(true); remainingColumn.setSortable(true); - lastModifiedDateColumn.setSortable(true); + lastModifiedColumn.setSortable(true); addColumn(directoryColumn, messages.columnHeaderDirectory()); @@ -163,11 +171,11 @@ public String getValue(DocumentNode object) remainingColumn.setCellStyleNames("remainingCol"); addColumn(remainingColumn, messages.columnHeaderRemaining()); - lastModifiedDateColumn.setCellStyleNames("lastModifiedDateCol"); - addColumn(lastModifiedDateColumn, "Last Modified Date"); - - lastModifiedByColumn.setCellStyleNames("lastModifiedByCol"); - addColumn(lastModifiedByColumn, "Last Modified By"); + lastModifiedColumn.setCellStyleNames("lastModifiedCol"); + addColumn(lastModifiedColumn, "Last Modified"); + + // actionColumn.setCellStyleNames("actionCol"); + // addColumn(actionColumn, "Action"); addSorting(dataProvider); } @@ -224,6 +232,26 @@ public int compare(DocumentNode o1, DocumentNode o2) return o1.getDocInfo().getStats().getRemainingHours() > o2.getDocInfo().getStats().getRemainingHours() ? 1 : -1; } }); + + columnSortHandler.setComparator(lastModifiedColumn, new Comparator() + { + public int compare(DocumentNode o1, DocumentNode o2) + { + if (o1.getDocInfo().getLastChanged() == o2.getDocInfo().getLastChanged()) + { + return 0; + } + if (o1.getDocInfo().getLastChanged() == null) + { + return -1; + } + if (o2.getDocInfo().getLastChanged() == null) + { + return 1; + } + return o1.getDocInfo().getLastChanged().after(o2.getDocInfo().getLastChanged()) ? 1 : -1; + } + }); addColumnSortHandler(columnSortHandler); getColumnSortList().push(directoryColumn); } diff --git a/zanata-war/src/main/java/org/zanata/webtrans/client/view/DocumentListDisplay.java b/zanata-war/src/main/java/org/zanata/webtrans/client/view/DocumentListDisplay.java index d3e37c8b3b..30ba910fd5 100644 --- a/zanata-war/src/main/java/org/zanata/webtrans/client/view/DocumentListDisplay.java +++ b/zanata-war/src/main/java/org/zanata/webtrans/client/view/DocumentListDisplay.java @@ -67,6 +67,8 @@ interface Listener void fireFilterToken(String value); void fireDocumentSelection(DocumentInfo doc); + + void downloadAllFiles(); } void setThemes(String style); diff --git a/zanata-war/src/main/java/org/zanata/webtrans/client/view/DocumentListView.java b/zanata-war/src/main/java/org/zanata/webtrans/client/view/DocumentListView.java index bf7ce8c3be..7e93d30d55 100644 --- a/zanata-war/src/main/java/org/zanata/webtrans/client/view/DocumentListView.java +++ b/zanata-war/src/main/java/org/zanata/webtrans/client/view/DocumentListView.java @@ -28,8 +28,10 @@ import org.zanata.webtrans.client.ui.SearchField; import org.zanata.webtrans.client.ui.table.DocumentListPager; import org.zanata.webtrans.shared.model.DocumentInfo; +import org.zanata.webtrans.shared.model.UserWorkspaceContext; import com.google.gwt.core.client.GWT; +import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.logical.shared.HasSelectionHandlers; import com.google.gwt.event.logical.shared.SelectionEvent; import com.google.gwt.event.logical.shared.SelectionHandler; @@ -43,6 +45,7 @@ import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.LayoutPanel; +import com.google.gwt.user.client.ui.PushButton; import com.google.gwt.user.client.ui.RadioButton; import com.google.gwt.user.client.ui.Widget; import com.google.gwt.view.client.HasData; @@ -68,6 +71,9 @@ public class DocumentListView extends Composite implements DocumentListDisplay, @UiField RadioButton statsByMsg, statsByWord; + @UiField + PushButton downloadAllFiles; + @UiField(provided = true) DocumentListPager pager; @@ -75,14 +81,16 @@ public class DocumentListView extends Composite implements DocumentListDisplay, private final Resources resources; private final WebTransMessages messages; + private final UserWorkspaceContext userworkspaceContext; private ListDataProvider dataProvider; @Inject - public DocumentListView(Resources resources, WebTransMessages messages) + public DocumentListView(Resources resources, WebTransMessages messages, UserWorkspaceContext userworkspaceContext) { this.resources = resources; this.messages = messages; + this.userworkspaceContext = userworkspaceContext; dataProvider = new ListDataProvider(); @@ -92,6 +100,8 @@ public DocumentListView(Resources resources, WebTransMessages messages) initWidget(uiBinder.createAndBindUi(this)); + downloadAllFiles.setText("Download all files (zip)"); + caseSensitiveCheckBox.setTitle(messages.docListFilterCaseSensitiveDescription()); exactSearchCheckBox.setTitle(messages.docListFilterExactMatchDescription()); statsByMsg.setText(messages.byMessage()); @@ -173,6 +183,12 @@ public void onStatsByWordChange(ValueChangeEvent event) } } + @UiHandler("downloadAllFiles") + public void onDownloadAllFilesClick(ClickEvent event) + { + listener.downloadAllFiles(); + } + @Override public void setStatsFilter(String option) { @@ -208,7 +224,7 @@ public void updateFilter(boolean docFilterCaseSensitive, boolean docFilterExact, @Override public void renderTable(SingleSelectionModel selectionModel) { - documentListTable = new DocumentListTable(resources, messages, dataProvider, selectionModel); + documentListTable = new DocumentListTable(resources, messages, dataProvider, selectionModel, userworkspaceContext.getWorkspaceContext().getWorkspaceId()); dataProvider.addDataDisplay(documentListTable); documentListContainer.clear(); diff --git a/zanata-war/src/main/java/org/zanata/webtrans/client/view/DocumentListView.ui.xml b/zanata-war/src/main/java/org/zanata/webtrans/client/view/DocumentListView.ui.xml index 73a9efd260..6c87e10106 100644 --- a/zanata-war/src/main/java/org/zanata/webtrans/client/view/DocumentListView.ui.xml +++ b/zanata-war/src/main/java/org/zanata/webtrans/client/view/DocumentListView.ui.xml @@ -40,6 +40,15 @@ .listContainer { padding:10px; + margin-top:25px; + } + + .downloadAllFiles + { + width:130px; + margin-top:5px; + position:absolute; + right:5px; } @@ -67,12 +76,15 @@ - - - - - - + + + + + + + + + diff --git a/zanata-war/src/main/java/org/zanata/webtrans/server/rpc/DownloadAllFilesHandler.java b/zanata-war/src/main/java/org/zanata/webtrans/server/rpc/DownloadAllFilesHandler.java new file mode 100644 index 0000000000..51312b6196 --- /dev/null +++ b/zanata-war/src/main/java/org/zanata/webtrans/server/rpc/DownloadAllFilesHandler.java @@ -0,0 +1,97 @@ +/* + * Copyright 2010, Red Hat, Inc. and individual contributors as indicated by the + * @author tags. See the copyright.txt file in the distribution for a full + * listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + * + * This software is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this software; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF + * site: http://www.fsf.org. + */ +package org.zanata.webtrans.server.rpc; + +import net.customware.gwt.dispatch.server.ExecutionContext; +import net.customware.gwt.dispatch.shared.ActionException; + +import org.jboss.seam.ScopeType; +import org.jboss.seam.annotations.In; +import org.jboss.seam.annotations.Name; +import org.jboss.seam.annotations.Scope; +import org.jboss.seam.security.Identity; +import org.zanata.dao.ProjectIterationDAO; +import org.zanata.model.HProjectIteration; +import org.zanata.process.IterationZipFileBuildProcess; +import org.zanata.process.IterationZipFileBuildProcessHandle; +import org.zanata.process.ProcessHandle; +import org.zanata.security.ZanataIdentity; +import org.zanata.service.ProcessManagerService; +import org.zanata.webtrans.server.ActionHandlerFor; +import org.zanata.webtrans.shared.rpc.DownloadAllFilesAction; +import org.zanata.webtrans.shared.rpc.NoOpResult; + +/** + * + * @author Alex Eng aeng@redhat.com + * + */ +@Name("webtrans.gwt.DownloadAllFilesHandler") +@Scope(ScopeType.CONVERSATION) +@ActionHandlerFor(DownloadAllFilesAction.class) +public class DownloadAllFilesHandler extends AbstractActionHandler +{ + @In + private ZanataIdentity identity; + + @In + private ProcessManagerService processManagerServiceImpl; + + @In + private ProjectIterationDAO projectIterationDAO; + + + private ProcessHandle zipFilePrepHandle; + + @Override + public NoOpResult execute(DownloadAllFilesAction action, ExecutionContext context) throws ActionException + { + HProjectIteration version = projectIterationDAO.getBySlug(action.getProjectSlug(), action.getVersionSlug()); + if (identity.hasPermission(version, "download-all")) + { + if (this.zipFilePrepHandle != null && this.zipFilePrepHandle.isInProgress()) + { + // Cancel any other processes + this.zipFilePrepHandle.stop(); + } + + // Build a background process Handle + IterationZipFileBuildProcessHandle processHandle = new IterationZipFileBuildProcessHandle(); + this.zipFilePrepHandle = processHandle; + processHandle.setProjectSlug(action.getProjectSlug()); + processHandle.setIterationSlug(action.getVersionSlug()); + processHandle.setLocaleId(action.getLocaleId()); + processHandle.setInitiatingUserName(Identity.instance().getCredentials().getUsername()); + + // Fire the zip file building process and wait until it is ready to + // return + this.processManagerServiceImpl.startProcess(new IterationZipFileBuildProcess(), processHandle); + processHandle.waitUntilReady(); + } + + return new NoOpResult(); + } + + @Override + public void rollback(DownloadAllFilesAction action, NoOpResult result, ExecutionContext context) throws ActionException + { + } +} diff --git a/zanata-war/src/main/java/org/zanata/webtrans/shared/rpc/DownloadAllFilesAction.java b/zanata-war/src/main/java/org/zanata/webtrans/shared/rpc/DownloadAllFilesAction.java new file mode 100644 index 0000000000..5a226fd8f0 --- /dev/null +++ b/zanata-war/src/main/java/org/zanata/webtrans/shared/rpc/DownloadAllFilesAction.java @@ -0,0 +1,60 @@ +/* + * Copyright 2010, Red Hat, Inc. and individual contributors as indicated by the + * @author tags. See the copyright.txt file in the distribution for a full + * listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + * + * This software is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this software; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF + * site: http://www.fsf.org. + */ +package org.zanata.webtrans.shared.rpc; + +/** + * + * @author Alex Eng aeng@redhat.com + * + */ +public class DownloadAllFilesAction implements DispatchAction +{ + private static final long serialVersionUID = 1L; + + private String projectSlug, versionSlug, localeId; + @SuppressWarnings("unused") + private DownloadAllFilesAction() + { + } + + public DownloadAllFilesAction(String projectSlug, String versionSlug, String localeId) + { + this.projectSlug = projectSlug; + this.versionSlug = versionSlug; + this.localeId = localeId; + } + + public String getProjectSlug() + { + return projectSlug; + } + + public String getVersionSlug() + { + return versionSlug; + } + + public String getLocaleId() + { + return localeId; + } + +} diff --git a/zanata-war/src/main/resources/org/zanata/webtrans/public/Application.css b/zanata-war/src/main/resources/org/zanata/webtrans/public/Application.css index 0fbf46472f..8ae0f9f9b2 100644 --- a/zanata-war/src/main/resources/org/zanata/webtrans/public/Application.css +++ b/zanata-war/src/main/resources/org/zanata/webtrans/public/Application.css @@ -547,24 +547,15 @@ td.ApprovedStateDecoration div div div text-align:center; } -.DocumentListTable td.translatedCol { - font-weight:bold; - font-size:14px; - color:#006200; - text-align:center; -} - -.DocumentListTable td.untranslatedCol { +.DocumentListTable td.remainingCol { font-weight:bold; font-size:14px; - color:#818181; + color:#910000; text-align:center; } -.DocumentListTable td.remainingCol { - font-weight:bold; - font-size:14px; - color:#910000; +.DocumentListTable td.lastModifiedCol { + font-size:12px; text-align:center; } diff --git a/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/DocumentListPresenterTest.java b/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/DocumentListPresenterTest.java index 7b6cbd8483..797d28579e 100644 --- a/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/DocumentListPresenterTest.java +++ b/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/DocumentListPresenterTest.java @@ -38,6 +38,7 @@ import org.zanata.webtrans.client.history.History; import org.zanata.webtrans.client.history.HistoryToken; import org.zanata.webtrans.client.resources.WebTransMessages; +import org.zanata.webtrans.client.rpc.CachingDispatchAsync; import org.zanata.webtrans.client.service.UserOptionsService; import org.zanata.webtrans.client.ui.DocumentNode; import org.zanata.webtrans.client.view.DocumentListDisplay; @@ -73,6 +74,8 @@ public class DocumentListPresenterTest private UserWorkspaceContext mockUserWorkspaceContext; @Mock private UserOptionsService mockUserOptionsService; + @Mock + private CachingDispatchAsync mockDispatcher; private UserConfigHolder configHolder; @@ -99,7 +102,7 @@ public void beforeMethod() configHolder = new UserConfigHolder(); when(mockUserOptionsService.getConfigHolder()).thenReturn(configHolder); dataProviderList = new ArrayList(); - documentListPresenter = new DocumentListPresenter(mockDisplay, mockEventBus, mockUserWorkspaceContext, mockMessages, mockHistory, mockUserOptionsService); + documentListPresenter = new DocumentListPresenter(mockDisplay, mockEventBus, mockDispatcher, mockUserWorkspaceContext, mockMessages, mockHistory, mockUserOptionsService); } @Test