001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.ade.upload.client.ui; 029 030import org.opencms.ade.upload.client.I_CmsUploadContext; 031import org.opencms.ade.upload.client.Messages; 032import org.opencms.ade.upload.client.ui.css.I_CmsLayoutBundle; 033import org.opencms.ade.upload.client.ui.css.I_CmsLayoutBundle.I_CmsUploadCss; 034import org.opencms.gwt.client.CmsCoreProvider; 035import org.opencms.gwt.client.rpc.CmsRpcAction; 036import org.opencms.gwt.client.ui.CmsErrorDialog; 037import org.opencms.gwt.client.ui.CmsList; 038import org.opencms.gwt.client.ui.CmsListItem; 039import org.opencms.gwt.client.ui.CmsListItemWidget; 040import org.opencms.gwt.client.ui.CmsListItemWidget.Background; 041import org.opencms.gwt.client.ui.CmsLoadingAnimation; 042import org.opencms.gwt.client.ui.CmsNotification; 043import org.opencms.gwt.client.ui.CmsNotification.Type; 044import org.opencms.gwt.client.ui.CmsPopup; 045import org.opencms.gwt.client.ui.CmsPushButton; 046import org.opencms.gwt.client.ui.CmsScrollPanel; 047import org.opencms.gwt.client.ui.CmsToggleButton; 048import org.opencms.gwt.client.ui.CmsVirusReport; 049import org.opencms.gwt.client.ui.FontOpenCms; 050import org.opencms.gwt.client.ui.I_CmsButton; 051import org.opencms.gwt.client.ui.I_CmsListItem; 052import org.opencms.gwt.client.ui.css.I_CmsConstantsBundle; 053import org.opencms.gwt.client.ui.input.CmsCheckBox; 054import org.opencms.gwt.client.ui.input.upload.CmsFileInfo; 055import org.opencms.gwt.client.ui.input.upload.CmsFileInput; 056import org.opencms.gwt.client.ui.input.upload.CmsUploadButton; 057import org.opencms.gwt.client.ui.input.upload.CmsUploadProgressInfo; 058import org.opencms.gwt.client.ui.input.upload.CmsUploader; 059import org.opencms.gwt.client.ui.input.upload.I_CmsUploadButton; 060import org.opencms.gwt.client.ui.input.upload.I_CmsUploadDialog; 061import org.opencms.gwt.client.util.CmsChangeHeightAnimation; 062import org.opencms.gwt.client.util.CmsDomUtil; 063import org.opencms.gwt.shared.CmsListInfoBean; 064import org.opencms.gwt.shared.CmsUploadFileBean; 065import org.opencms.gwt.shared.CmsUploadProgessInfo; 066import org.opencms.gwt.shared.CmsUploadRestrictionInfo; 067import org.opencms.gwt.shared.I_CmsUploadConstants; 068import org.opencms.gwt.shared.rpc.I_CmsUploadService; 069import org.opencms.gwt.shared.rpc.I_CmsUploadServiceAsync; 070import org.opencms.util.CmsStringUtil; 071import org.opencms.util.CmsUUID; 072 073import java.util.ArrayList; 074import java.util.Arrays; 075import java.util.Collections; 076import java.util.HashMap; 077import java.util.HashSet; 078import java.util.List; 079import java.util.Map; 080import java.util.Set; 081import java.util.stream.Collectors; 082 083import com.google.common.base.Supplier; 084import com.google.gwt.core.client.GWT; 085import com.google.gwt.core.client.Scheduler; 086import com.google.gwt.core.client.Scheduler.ScheduledCommand; 087import com.google.gwt.dom.client.Style.Display; 088import com.google.gwt.dom.client.Style.Unit; 089import com.google.gwt.event.dom.client.ClickEvent; 090import com.google.gwt.event.dom.client.ClickHandler; 091import com.google.gwt.event.logical.shared.CloseEvent; 092import com.google.gwt.event.logical.shared.CloseHandler; 093import com.google.gwt.event.shared.HandlerRegistration; 094import com.google.gwt.json.client.JSONArray; 095import com.google.gwt.json.client.JSONObject; 096import com.google.gwt.json.client.JSONParser; 097import com.google.gwt.json.client.JSONString; 098import com.google.gwt.json.client.JSONValue; 099import com.google.gwt.user.client.Command; 100import com.google.gwt.user.client.Timer; 101import com.google.gwt.user.client.rpc.AsyncCallback; 102import com.google.gwt.user.client.rpc.ServiceDefTarget; 103import com.google.gwt.user.client.ui.FlowPanel; 104import com.google.gwt.user.client.ui.FormPanel; 105import com.google.gwt.user.client.ui.HTML; 106import com.google.gwt.user.client.ui.PopupPanel; 107import com.google.gwt.user.client.ui.UIObject; 108import com.google.gwt.user.client.ui.Widget; 109 110/** 111 * Provides an upload dialog.<p> 112 * 113 * @since 8.0.0 114 */ 115public abstract class A_CmsUploadDialog extends CmsPopup implements I_CmsUploadDialog { 116 117 /** The minimal height of the content wrapper. */ 118 private static final int MIN_CONTENT_HEIGHT = 110; 119 120 /** Text metrics key. */ 121 private static final String TM_FILE_UPLOAD_LIST = "FileUploadList"; 122 123 /** The interval for updating the progress information in milliseconds. */ 124 private static final int UPDATE_PROGRESS_INTERVALL = 1000; 125 126 /** The upload context. */ 127 protected I_CmsUploadContext m_context; 128 129 /** The drag and drop message. */ 130 protected HTML m_dragAndDropMessage; 131 132 /** The scroll panel. */ 133 protected CmsScrollPanel m_scrollPanel; 134 135 /** The uploaded file names. */ 136 protected List<String> m_uploadedFiles; 137 138 /** Signals that the upload dialog was canceled. */ 139 boolean m_canceled; 140 141 /** True if the target folder is given as a root path. */ 142 boolean m_isTargetRootPath; 143 144 /** Stores all files that were added. */ 145 private Map<String, CmsFileInfo> m_allFiles; 146 147 /** Signals that the client currently loading. */ 148 private boolean m_clientLoading; 149 150 /** The close handler. */ 151 private CloseHandler<PopupPanel> m_closeHandler; 152 153 /** The sum of all file sizes. */ 154 private long m_contentLength; 155 156 /** A flow panel with a dynamic height. */ 157 private FlowPanel m_contentWrapper; 158 159 /** The user information text widget. */ 160 private HTML m_dialogInfo; 161 162 /** The list of file item widgets. */ 163 private CmsList<I_CmsListItem> m_fileList; 164 165 /** The list of filenames that should be unziped on the server. */ 166 private List<String> m_filesToUnzip; 167 168 /** The Map of files to upload. */ 169 private Map<String, CmsFileInfo> m_filesToUpload; 170 171 /** Stores the content height of the selection dialog. */ 172 private int m_firstContentHeight; 173 174 /** Stores the height of the user information text widget of the selection dialog. */ 175 private int m_firstInfoHeight; 176 177 /** Stores the height of the summary. */ 178 private int m_firstSummaryHeight; 179 180 /** A local reference to the default gwt CSS. */ 181 private org.opencms.gwt.client.ui.css.I_CmsLayoutBundle m_gwtCss = org.opencms.gwt.client.ui.css.I_CmsLayoutBundle.INSTANCE; 182 183 /** The close handler registration. */ 184 private HandlerRegistration m_handlerReg; 185 186 /** Stores the list items of all added files. */ 187 private Map<String, CmsListItem> m_listItems; 188 189 /** A panel for showing client loading. */ 190 private FlowPanel m_loadingPanel; 191 192 /** A timer to delay the loading animation. */ 193 private Timer m_loadingTimer; 194 195 /** The main panel. */ 196 private FlowPanel m_mainPanel; 197 198 /** The OK button. */ 199 private CmsPushButton m_okButton; 200 201 /** The post-create handler. */ 202 private String m_postCreateHandler; 203 204 /** The progress bar for the upload process. */ 205 private CmsUploadProgressInfo m_progressInfo; 206 207 /** The names of restricted upload files. */ 208 private Set<String> m_restricted = new HashSet<>(); 209 210 /** Signals whether the selection is done or not. */ 211 private boolean m_selectionDone; 212 213 /** The user information text widget. */ 214 private HTML m_selectionSummary; 215 216 /** The target folder to upload the selected files. */ 217 private String m_targetFolder; 218 219 /** The timer for updating the progress. */ 220 private Timer m_updateProgressTimer = new Timer() { 221 222 /** 223 * @see com.google.gwt.user.client.Timer#run() 224 */ 225 @Override 226 public void run() { 227 228 updateProgress(); 229 } 230 }; 231 232 /** The upload button of this dialog. */ 233 private I_CmsUploadButton m_uploadButton; 234 235 /** The upload service instance. */ 236 private I_CmsUploadServiceAsync m_uploadService; 237 238 /** 239 * Default constructor.<p> 240 */ 241 public A_CmsUploadDialog() { 242 243 super(Messages.get().key(Messages.GUI_UPLOAD_DIALOG_TITLE_1)); 244 245 I_CmsLayoutBundle.INSTANCE.uploadCss().ensureInjected(); 246 setModal(true); 247 setGlassEnabled(true); 248 catchNotifications(); 249 setWidth(CmsPopup.DEFAULT_WIDTH); 250 251 // create a map that stores all files (upload, existing, invalid) 252 m_allFiles = new HashMap<String, CmsFileInfo>(); 253 // create a map the holds all the list items for the selection dialog 254 m_listItems = new HashMap<String, CmsListItem>(); 255 m_filesToUnzip = new ArrayList<String>(); 256 m_fileList = new CmsList<I_CmsListItem>(); 257 m_fileList.truncate(TM_FILE_UPLOAD_LIST, CmsPopup.DEFAULT_WIDTH - 50); 258 259 // initialize a map that stores all the files that should be uploaded 260 m_filesToUpload = new HashMap<String, CmsFileInfo>(); 261 262 // create the main panel 263 m_mainPanel = new FlowPanel(); 264 265 // add the user info to the main panel 266 m_dialogInfo = new HTML(); 267 m_dialogInfo.addStyleName(I_CmsLayoutBundle.INSTANCE.uploadCss().dialogInfo()); 268 m_mainPanel.add(m_dialogInfo); 269 m_scrollPanel = GWT.create(CmsScrollPanel.class); 270 m_scrollPanel.getElement().getStyle().setPropertyPx("minHeight", MIN_CONTENT_HEIGHT); 271 m_scrollPanel.addStyleName(I_CmsLayoutBundle.INSTANCE.uploadCss().mainContentWidget()); 272 m_scrollPanel.addStyleName(m_gwtCss.generalCss().cornerAll()); 273 m_mainPanel.add(m_scrollPanel); 274 // add the content wrapper 275 m_contentWrapper = new FlowPanel(); 276 m_contentWrapper.add(m_fileList); 277 m_scrollPanel.add(m_contentWrapper); 278 279 m_selectionSummary = new HTML(); 280 m_selectionSummary.addStyleName(I_CmsLayoutBundle.INSTANCE.uploadCss().summary()); 281 m_mainPanel.add(m_selectionSummary); 282 283 // set the main panel as content of the popup 284 setMainContent(m_mainPanel); 285 286 addCloseHandler(new CloseHandler<PopupPanel>() { 287 288 /** 289 * @see com.google.gwt.event.logical.shared.CloseHandler#onClose(com.google.gwt.event.logical.shared.CloseEvent) 290 */ 291 public void onClose(CloseEvent<PopupPanel> e) { 292 293 if (m_context != null) { 294 m_context.onUploadFinished(m_uploadedFiles); 295 } 296 } 297 }); 298 299 // create and add the "OK", "Cancel" and upload button 300 createButtons(); 301 } 302 303 /** 304 * @see org.opencms.gwt.client.ui.CmsPopup#addCloseHandler(com.google.gwt.event.logical.shared.CloseHandler) 305 */ 306 @Override 307 public HandlerRegistration addCloseHandler(CloseHandler<PopupPanel> handler) { 308 309 m_closeHandler = handler; 310 m_handlerReg = super.addCloseHandler(handler); 311 return m_handlerReg; 312 } 313 314 /** 315 * Creates a bean that can be used for the list item widget.<p> 316 * 317 * @param file the info to create the bean for 318 * 319 * @return a list info bean 320 */ 321 public abstract CmsListInfoBean createInfoBean(CmsFileInfo file); 322 323 /** 324 * Returns the massage for too large files.<p> 325 * 326 * @param file the file 327 * 328 * @return the message 329 */ 330 public abstract String getFileSizeTooLargeMessage(CmsFileInfo file); 331 332 /** 333 * Returns <code>true</code> if the file is too large, <code>false</code> otherwise.<p> 334 * 335 * @param cmsFileInfo the file to check 336 * 337 * @return <code>true</code> if the file is too large, <code>false</code> otherwise 338 */ 339 public abstract boolean isTooLarge(CmsFileInfo cmsFileInfo); 340 341 /** 342 * Loads and shows this dialog.<p> 343 */ 344 public void loadAndShow() { 345 346 // enable or disable the OK button 347 if (getFilesToUpload().isEmpty()) { 348 disableOKButton(Messages.get().key(Messages.GUI_UPLOAD_NOTIFICATION_NO_FILES_0)); 349 setDragAndDropMessage(); 350 } else { 351 enableOKButton(); 352 removeDragAndDropMessage(); 353 } 354 m_uploadedFiles = null; 355 // set the user info 356 displayDialogInfo(Messages.get().key(Messages.GUI_UPLOAD_INFO_SELECTION_0), false); 357 // set the selection summary 358 updateSummary(); 359 360 // add a upload button 361 m_uploadButton.createFileInput(); 362 363 // show the popup 364 if (!isShowing()) { 365 Scheduler.get().scheduleDeferred(new ScheduledCommand() { 366 367 /** 368 * @see com.google.gwt.core.client.Scheduler.ScheduledCommand#execute() 369 */ 370 public void execute() { 371 372 setContentWrapperHeight(); 373 center(); 374 } 375 }); 376 } 377 center(); 378 } 379 380 /** 381 * @see org.opencms.gwt.client.ui.input.upload.I_CmsUploadDialog#parseResponse(java.lang.String) 382 */ 383 public void parseResponse(String results) { 384 385 cancelUpdateProgress(); 386 stopLoadingAnimation(); 387 388 if ((!m_canceled) && CmsStringUtil.isNotEmptyOrWhitespaceOnly(results)) { 389 JSONObject jsonObject = JSONParser.parseStrict(results).isObject(); 390 boolean success = jsonObject.get(I_CmsUploadConstants.KEY_SUCCESS).isBoolean().booleanValue(); 391 // If the upload is done so fast that we did not receive any progress information, then 392 // the content length is unknown. For that reason take the request size to show how 393 // much bytes were uploaded. 394 double size = jsonObject.get(I_CmsUploadConstants.KEY_REQUEST_SIZE).isNumber().doubleValue(); 395 long requestSize = Double.valueOf(size).longValue(); 396 if (m_contentLength == 0) { 397 m_contentLength = requestSize; 398 } 399 if (success) { 400 m_uploadedFiles = new ArrayList<String>(); 401 List<String> uploadedFileIds = new ArrayList<String>(); 402 displayDialogInfo( 403 org.opencms.gwt.client.Messages.get().key( 404 org.opencms.gwt.client.Messages.GUI_UPLOAD_INFO_FINISHING_0), 405 false); 406 JSONValue uploadedFilesVal = jsonObject.get(I_CmsUploadConstants.KEY_UPLOADED_FILE_NAMES); 407 JSONValue uploadHook = jsonObject.get(I_CmsUploadConstants.KEY_UPLOAD_HOOK); 408 JSONValue uploadedFileIdsVal = jsonObject.get(I_CmsUploadConstants.KEY_UPLOADED_FILES); 409 JSONArray uploadedFileIdsArray = uploadedFileIdsVal.isArray(); 410 411 String hookUri = null; 412 if ((uploadHook != null) && (uploadHook.isString() != null)) { 413 hookUri = uploadHook.isString().stringValue(); 414 if (uploadedFileIdsArray != null) { 415 for (int i = 0; i < uploadedFileIdsArray.size(); i++) { 416 JSONString entry = uploadedFileIdsArray.get(i).isString(); 417 if (entry != null) { 418 uploadedFileIds.add(entry.stringValue()); 419 } 420 } 421 } 422 } 423 if (uploadedFileIds.size() == 0) { 424 // no files uploaded, probably because of virus scanner - don't show upload hook dialog 425 hookUri = null; 426 } 427 JSONArray uploadedFilesArray = uploadedFilesVal.isArray(); 428 if (uploadedFilesArray != null) { 429 for (int i = 0; i < uploadedFilesArray.size(); i++) { 430 JSONString entry = uploadedFilesArray.get(i).isString(); 431 if (entry != null) { 432 m_uploadedFiles.add(entry.stringValue()); 433 } 434 } 435 } 436 Map<String, List<String>> viruses = CmsVirusReport.getVirusWarnings(jsonObject); 437 final I_CmsUploadContext context = m_context; 438 final String finalHookUri = hookUri; 439 m_progressInfo.finish(); 440 if (!viruses.isEmpty()) { 441 m_context = null; 442 hide(); 443 CmsPopup virusPopup = CmsVirusReport.createPopup(viruses, () -> { 444 if (finalHookUri != null) { 445 openHookDialog(uploadedFileIds, finalHookUri, context); 446 } else { 447 context.onUploadFinished(m_uploadedFiles); 448 } 449 }); 450 virusPopup.center(); 451 } else { 452 if (hookUri != null) { 453 // Set the context to be null so that it isn't called when the upload dialog closed; 454 // we want it to be called when the upload property dialog is closed instead.<p> 455 m_context = null; 456 openHookDialog(uploadedFileIds, hookUri, context); 457 } 458 closeOnSuccess(); 459 } 460 } else { 461 String message = jsonObject.get(I_CmsUploadConstants.KEY_MESSAGE).isString().stringValue(); 462 String stacktrace = jsonObject.get(I_CmsUploadConstants.KEY_STACKTRACE).isString().stringValue(); 463 showErrorReport(message, stacktrace); 464 } 465 } 466 } 467 468 /** 469 * Sets the upload context.<p> 470 * 471 * @param context the new upload context 472 */ 473 public void setContext(I_CmsUploadContext context) { 474 475 if (context != null) { 476 m_context = new I_CmsUploadContext() { 477 478 @Override 479 public void onUploadFinished(List<String> uploadedFiles) { 480 481 context.onUploadFinished(uploadedFiles); 482 } 483 }; 484 485 } else { 486 m_context = context; 487 } 488 } 489 490 /** 491 * Sets the boolean flag to control whether the target folder is interpreted as a root path.<p> 492 * 493 * @param isTargetRootPath true if the target folder should be treated as a root path 494 */ 495 public void setIsTargetRootPath(boolean isTargetRootPath) { 496 497 m_isTargetRootPath = isTargetRootPath; 498 } 499 500 /** 501 * Sets the post-create handler. 502 * 503 * @param postCreateHandler the post-create handler 504 */ 505 public void setPostCreateHandler(String postCreateHandler) { 506 507 m_postCreateHandler = postCreateHandler; 508 } 509 510 /** 511 * Sets the target folder.<p> 512 * 513 * @param target the target folder to set 514 */ 515 public void setTargetFolder(String target) { 516 517 m_targetFolder = target; 518 setCaption(Messages.get().key(Messages.GUI_UPLOAD_DIALOG_TITLE_1, m_targetFolder)); 519 } 520 521 /** 522 * Shows the error report.<p> 523 * 524 * @param message the message to show 525 * @param stacktrace the stacktrace to show 526 */ 527 public void showErrorReport(final String message, final String stacktrace) { 528 529 if (!m_canceled) { 530 CmsErrorDialog errDialog = new CmsErrorDialog(message, stacktrace); 531 if (m_handlerReg != null) { 532 m_handlerReg.removeHandler(); 533 } 534 if (m_closeHandler != null) { 535 errDialog.addCloseHandler(m_closeHandler); 536 } 537 hide(); 538 errDialog.center(); 539 } 540 } 541 542 /** 543 * Executes the submit action.<p> 544 */ 545 public void submit() { 546 547 // create a JsArray containing the files to upload 548 List<CmsFileInfo> filesToUpload = new ArrayList<CmsFileInfo>(getFilesToUpload().values()); 549 Collections.sort(filesToUpload, CmsFileInfo.INFO_COMPARATOR); 550 551 CmsUploader uploader = new CmsUploader(); 552 uploader.uploadFiles( 553 getUploadUri(), 554 getTargetFolder(), 555 m_isTargetRootPath, 556 getPostCreateHandler(), 557 filesToUpload, 558 getFilesToUnzip(false), 559 false, 560 this); 561 } 562 563 /** 564 * Updates the button handler. 565 */ 566 public void updateHandler() { 567 568 CmsDialogUploadButtonHandler handler = new CmsDialogUploadButtonHandler( 569 () -> m_context, 570 m_targetFolder, 571 m_isTargetRootPath); 572 handler.setUploadDialog(this); 573 m_uploadButton.reinitButton(handler); 574 } 575 576 /** 577 * Updates the file summary.<p> 578 */ 579 public abstract void updateSummary(); 580 581 /** 582 * Adds the given file input field to this dialog.<p> 583 * 584 * @param fileInput the file input field to add 585 */ 586 protected void addFileInput(CmsFileInput fileInput) { 587 588 // add the files selected by the user to the list of files to upload 589 if (fileInput != null) { 590 addFiles(Arrays.asList(fileInput.getFiles())); 591 } else { 592 loadAndShow(); 593 } 594 } 595 596 /** 597 * Adds the given file input field to this dialog.<p> 598 * 599 * @param fileInfos the file info objects 600 */ 601 protected void addFiles(List<CmsFileInfo> fileInfos) { 602 603 if (fileInfos != null) { 604 for (CmsFileInfo file : fileInfos) { 605 606 // store all files 607 m_allFiles.put(file.getFileName(), file); 608 CmsUploadRestrictionInfo restriction = CmsCoreProvider.get().getUploadRestriction(); 609 610 String targetRootPath = getTargetRootPath(); 611 boolean restricted = !restriction.isUploadEnabled(targetRootPath) 612 || !restriction.checkTypeAllowed(targetRootPath, file.getFileSuffix()); 613 if (restricted) { 614 m_restricted.add(file.getFileName()); 615 } 616 617 // add those files to the list of files to upload that potential candidates 618 if (!isTooLarge(file) && !restricted) { 619 m_filesToUpload.put(file.getFileName(), file); 620 } 621 622 // remove those files from the list to upload that were previously unchecked by the user 623 if ((m_listItems.get(file.getFileName()) != null) 624 && (m_listItems.get(file.getFileName()).getCheckBox() != null) 625 && !m_listItems.get(file.getFileName()).getCheckBox().isChecked()) { 626 m_filesToUpload.remove(file.getFileName()); 627 } 628 } 629 630 // now rebuild the list: handle all files 631 m_fileList.clearList(); 632 List<String> sortedFileNames = new ArrayList<String>(m_allFiles.keySet()); 633 Collections.sort(sortedFileNames, String.CASE_INSENSITIVE_ORDER); 634 for (String filename : sortedFileNames) { 635 CmsFileInfo file = m_allFiles.get(filename); 636 addFileToList(file, false, false, isTooLarge(file), m_restricted.contains(file.getFileName())); 637 } 638 doResize(); 639 } 640 loadAndShow(); 641 } 642 643 /** 644 * Cancels the upload progress timer.<p> 645 */ 646 protected void cancelUpdateProgress() { 647 648 m_updateProgressTimer.cancel(); 649 } 650 651 /** 652 * Cancels the upload.<p> 653 */ 654 protected void cancelUpload() { 655 656 m_canceled = true; 657 cancelUpdateProgress(); 658 659 CmsRpcAction<Boolean> callback = new CmsRpcAction<Boolean>() { 660 661 /** 662 * @see org.opencms.gwt.client.rpc.CmsRpcAction#execute() 663 */ 664 @Override 665 public void execute() { 666 667 getUploadService().cancelUpload(this); 668 } 669 670 /** 671 * @see org.opencms.gwt.client.rpc.CmsRpcAction#onResponse(java.lang.Object) 672 */ 673 @Override 674 protected void onResponse(Boolean result) { 675 676 hide(); 677 } 678 }; 679 callback.execute(); 680 } 681 682 /** 683 * Creates the loading animation HTML and adds is to the content wrapper.<p> 684 * 685 * @param msg the message to display below the animation 686 */ 687 protected void createLoadingAnimation(String msg) { 688 689 m_clientLoading = true; 690 if (m_loadingPanel != null) { 691 m_loadingPanel.removeFromParent(); 692 } 693 m_loadingPanel = new FlowPanel(); 694 m_loadingPanel.addStyleName( 695 org.opencms.gwt.client.ui.css.I_CmsLayoutBundle.INSTANCE.uploadButton().loadingPanel()); 696 m_loadingPanel.addStyleName(m_gwtCss.generalCss().cornerAll()); 697 698 CmsLoadingAnimation animationDiv = new CmsLoadingAnimation(); 699 animationDiv.addStyleName( 700 org.opencms.gwt.client.ui.css.I_CmsLayoutBundle.INSTANCE.uploadButton().loadingAnimation()); 701 m_loadingPanel.add(animationDiv); 702 703 HTML messageDiv = new HTML(); 704 messageDiv.addStyleName(org.opencms.gwt.client.ui.css.I_CmsLayoutBundle.INSTANCE.uploadButton().loadingText()); 705 messageDiv.setHTML(msg); 706 m_loadingPanel.add(messageDiv); 707 708 m_contentWrapper.add(m_loadingPanel); 709 doResize(); 710 } 711 712 /** 713 * Disables the OK button.<p> 714 * 715 * @param disabledReason the reason for disabling the OK button 716 */ 717 protected void disableOKButton(String disabledReason) { 718 719 m_okButton.disable(disabledReason); 720 } 721 722 /** 723 * Required to be called when the content has changed.<p> 724 */ 725 protected void doResize() { 726 727 m_scrollPanel.onResizeDescendant(); 728 } 729 730 /** 731 * Enables the OK button.<p> 732 */ 733 protected void enableOKButton() { 734 735 m_okButton.enable(); 736 } 737 738 /** 739 * Returns the contentLength.<p> 740 * 741 * @return the contentLength 742 */ 743 protected long getContentLength() { 744 745 return m_contentLength; 746 } 747 748 /** 749 * Returns the contentWrapper.<p> 750 * 751 * @return the contentWrapper 752 */ 753 protected FlowPanel getContentWrapper() { 754 755 return m_contentWrapper; 756 } 757 758 /** 759 * Returns the list of file names that have to unziped.<p> 760 * 761 * @param all <code>true</code> if the returned list should contain those filenames that 762 * are not inside the map of files to upload. <code>false</code> only those filenames are 763 * returned that are also inside the map of files to upload 764 * 765 * @return the list of file names that have to unziped 766 */ 767 protected List<String> getFilesToUnzip(boolean all) { 768 769 if (!all) { 770 List<String> result = new ArrayList<String>(); 771 for (String fileName : m_filesToUnzip) { 772 if (m_filesToUpload.keySet().contains(fileName)) { 773 result.add(fileName); 774 } 775 } 776 return result; 777 } 778 return m_filesToUnzip; 779 } 780 781 /** 782 * Returns the filesToUpload.<p> 783 * 784 * @return the filesToUpload 785 */ 786 protected Map<String, CmsFileInfo> getFilesToUpload() { 787 788 return m_filesToUpload; 789 } 790 791 /** 792 * Returns "files" or "file" depending on the files to upload.<p> 793 * 794 * @return "files" or "file" depending on the files to upload 795 */ 796 protected String getFileText() { 797 798 if (m_filesToUpload.size() == 1) { 799 return org.opencms.gwt.client.Messages.get().key( 800 org.opencms.gwt.client.Messages.GUI_UPLOAD_FILES_SINGULAR_0); 801 } 802 return org.opencms.gwt.client.Messages.get().key(org.opencms.gwt.client.Messages.GUI_UPLOAD_FILES_PLURAL_0); 803 } 804 805 /** 806 * Gets the post-create handler. 807 * 808 * @return the post-create handler 809 */ 810 protected String getPostCreateHandler() { 811 812 return m_postCreateHandler; 813 } 814 815 /** 816 * Returns the resource type name for a given filename.<p> 817 * 818 * @param file the file info 819 * 820 * @return the resource type name 821 */ 822 protected String getResourceType(CmsFileInfo file) { 823 824 return CmsCoreProvider.get().getResourceType(file); 825 } 826 827 /** 828 * Returns the targetFolder.<p> 829 * 830 * @return the targetFolder 831 */ 832 protected String getTargetFolder() { 833 834 return m_targetFolder; 835 } 836 837 /** 838 * Returns the upload service instance.<p> 839 * 840 * @return the upload service instance 841 */ 842 protected I_CmsUploadServiceAsync getUploadService() { 843 844 if (m_uploadService == null) { 845 m_uploadService = GWT.create(I_CmsUploadService.class); 846 String serviceUrl = CmsCoreProvider.get().link("org.opencms.ade.upload.CmsUploadService.gwt"); 847 ((ServiceDefTarget)m_uploadService).setServiceEntryPoint(serviceUrl); 848 } 849 return m_uploadService; 850 } 851 852 /** 853 * Returns the upload JSP uri.<p> 854 * 855 * @return the upload JSP uri 856 */ 857 protected String getUploadUri() { 858 859 return CmsCoreProvider.get().link(I_CmsUploadConstants.UPLOAD_ACTION_JSP_URI); 860 } 861 862 /** 863 * Inserts a hidden form into.<p> 864 * 865 * @param form the form to insert 866 */ 867 protected void insertUploadForm(FormPanel form) { 868 869 form.getElement().getStyle().setDisplay(Display.NONE); 870 m_contentWrapper.add(form); 871 } 872 873 /** 874 * The action that is executed if the user clicks on the OK button.<p> 875 * 876 * If the selection dialog is currently shown the selected files are checked 877 * otherwise the upload is triggered.<p> 878 */ 879 protected void onOkClick() { 880 881 if (!m_selectionDone) { 882 checkSelection(); 883 } else { 884 commit(); 885 } 886 } 887 888 /** 889 * Required to be called when the content has changed.<p> 890 */ 891 protected void onResize() { 892 893 m_scrollPanel.onResize(); 894 } 895 896 /** 897 * Decides how to go on depending on the information of the server response.<p> 898 * 899 * Shows a warning if there is another upload process active (inside the same session).<p> 900 * 901 * Otherwise if the list of files to upload contains already existent resources on the VFS or if there 902 * are files selected that have invalid file names the overwrite dialog is shown.<p> 903 * 904 * Only if there is no other upload process running and none of the selected files 905 * is already existent on the VFS the upload is triggered.<p> 906 * 907 * @param result the bean that contains the information to evaluate 908 */ 909 protected void proceedWorkflow(CmsUploadFileBean result) { 910 911 if (result.isActive()) { 912 m_okButton.enable(); 913 CmsNotification.get().send(Type.WARNING, Messages.get().key(Messages.GUI_UPLOAD_NOTIFICATION_RUNNING_0)); 914 } else { 915 if (!result.getExistingResourceNames().isEmpty() 916 || !result.getInvalidFileNames().isEmpty() 917 || !result.getExistingDeletedFileNames().isEmpty()) { 918 showOverwriteDialog(result); 919 } else { 920 commit(); 921 } 922 } 923 } 924 925 /** 926 * Removes the drag and drop message.<p> 927 */ 928 protected void removeDragAndDropMessage() { 929 930 if (m_dragAndDropMessage != null) { 931 m_dragAndDropMessage.removeFromParent(); 932 m_dragAndDropMessage = null; 933 getContentWrapper().getElement().getStyle().clearBackgroundColor(); 934 } 935 } 936 937 /** 938 * Sets the contentLength.<p> 939 * 940 * @param contentLength the contentLength to set 941 */ 942 protected void setContentLength(long contentLength) { 943 944 m_contentLength = contentLength; 945 } 946 947 /** 948 * Execute to set the content wrapper height.<p> 949 */ 950 protected void setContentWrapperHeight() { 951 952 // set the max height of the content panel 953 int fixedContent = 0; 954 if (m_dialogInfo.isVisible()) { 955 fixedContent += m_dialogInfo.getOffsetHeight(); 956 } 957 if (m_selectionSummary.isVisible()) { 958 fixedContent += m_selectionSummary.getOffsetHeight(); 959 } 960 m_scrollPanel.getElement().getStyle().setPropertyPx("maxHeight", getAvailableHeight(fixedContent)); 961 doResize(); 962 } 963 964 /** 965 * Displays the 'use drag and drop' / 'no drag and drop available' message.<p> 966 */ 967 protected void setDragAndDropMessage() { 968 969 if (m_dragAndDropMessage == null) { 970 m_dragAndDropMessage = new HTML(); 971 m_dragAndDropMessage.setStyleName(I_CmsLayoutBundle.INSTANCE.uploadCss().dragAndDropMessage()); 972 m_dragAndDropMessage.setText(Messages.get().key(Messages.GUI_UPLOAD_DRAG_AND_DROP_DISABLED_0)); 973 } 974 getContentWrapper().add(m_dragAndDropMessage); 975 getContentWrapper().getElement().getStyle().setBackgroundColor( 976 I_CmsConstantsBundle.INSTANCE.css().notificationErrorBg()); 977 doResize(); 978 } 979 980 /** 981 * Sets the HTML of the selection summary.<p> 982 * 983 * @param html the HTML to set as String 984 */ 985 protected void setSummaryHTML(String html) { 986 987 m_selectionSummary.setHTML(html); 988 } 989 990 /** 991 * Retrieves the progress information from the server.<p> 992 */ 993 protected void updateProgress() { 994 995 CmsRpcAction<CmsUploadProgessInfo> callback = new CmsRpcAction<CmsUploadProgessInfo>() { 996 997 /** 998 * @see org.opencms.gwt.client.rpc.CmsRpcAction#execute() 999 */ 1000 @Override 1001 public void execute() { 1002 1003 getUploadService().getUploadProgressInfo(this); 1004 } 1005 1006 /** 1007 * @see org.opencms.gwt.client.rpc.CmsRpcAction#onFailure(java.lang.Throwable) 1008 */ 1009 @Override 1010 public void onFailure(Throwable t) { 1011 1012 super.onFailure(t); 1013 cancelUpdateProgress(); 1014 } 1015 1016 /** 1017 * @see org.opencms.gwt.client.rpc.CmsRpcAction#onResponse(java.lang.Object) 1018 */ 1019 @Override 1020 protected void onResponse(CmsUploadProgessInfo result) { 1021 1022 updateProgressBar(result); 1023 } 1024 }; 1025 callback.execute(); 1026 } 1027 1028 /** 1029 * Updates the progress bar.<p> 1030 * 1031 * @param info the progress info 1032 */ 1033 protected void updateProgressBar(CmsUploadProgessInfo info) { 1034 1035 switch (info.getState()) { 1036 case notStarted: 1037 break; 1038 case running: 1039 m_progressInfo.setProgress(info); 1040 stopLoadingAnimation(); 1041 break; 1042 case finished: 1043 m_progressInfo.finish(); 1044 displayDialogInfo( 1045 org.opencms.gwt.client.Messages.get().key( 1046 org.opencms.gwt.client.Messages.GUI_UPLOAD_INFO_FINISHING_0), 1047 false); 1048 startLoadingAnimation( 1049 org.opencms.gwt.client.Messages.get().key( 1050 org.opencms.gwt.client.Messages.GUI_UPLOAD_INFO_CREATING_RESOURCES_0), 1051 1500); 1052 break; 1053 default: 1054 break; 1055 } 1056 } 1057 1058 /** 1059 * Adds a click handler for the given check box.<p> 1060 * 1061 * @param check the check box 1062 * @param unzipWidget the un-zip check box 1063 * @param file the file 1064 */ 1065 private void addClickHandlerToCheckBox(final CmsCheckBox check, final Widget unzipWidget, final CmsFileInfo file) { 1066 1067 check.addClickHandler(new ClickHandler() { 1068 1069 /** 1070 * @see com.google.gwt.event.dom.client.ClickHandler#onClick(com.google.gwt.event.dom.client.ClickEvent) 1071 */ 1072 public void onClick(ClickEvent event) { 1073 1074 // add or remove the file from the list of files to upload 1075 if (check.isChecked()) { 1076 getFilesToUpload().put(file.getFileName(), file); 1077 if (unzipWidget != null) { 1078 enableUnzip(unzipWidget); 1079 } 1080 } else { 1081 getFilesToUpload().remove(file.getFileName()); 1082 if (unzipWidget != null) { 1083 disableUnzip(unzipWidget); 1084 } 1085 } 1086 1087 // disable or enable the OK button 1088 if (getFilesToUpload().isEmpty()) { 1089 disableOKButton(Messages.get().key(Messages.GUI_UPLOAD_NOTIFICATION_NO_FILES_0)); 1090 } else { 1091 enableOKButton(); 1092 } 1093 1094 // update summary 1095 updateSummary(); 1096 1097 } 1098 1099 /** 1100 * Disables the 'unzip' button 1101 * 1102 * @param unzip the unzip button 1103 */ 1104 private void disableUnzip(Widget unzip) { 1105 1106 ((CmsToggleButton)unzip).setEnabled(false); 1107 } 1108 1109 /** 1110 * Enables the 'unzip' button 1111 * 1112 * @param unzip the unzip button 1113 */ 1114 private void enableUnzip(Widget unzip) { 1115 1116 ((CmsToggleButton)unzip).setEnabled(true); 1117 } 1118 }); 1119 } 1120 1121 /** 1122 * Adds a file to the list.<p> 1123 * 1124 * @param file the file to add 1125 * @param invalid signals if the filename is invalid 1126 * @param existingDeleted in case of existing files marked as deleted 1127 * @param isTooLarge signals if the file size limit is exceeded 1128 * @param forbiddenType true if the file has a forbidden type 1129 */ 1130 private void addFileToList( 1131 final CmsFileInfo file, 1132 boolean invalid, 1133 boolean existingDeleted, 1134 boolean isTooLarge, 1135 boolean forbiddenType) { 1136 1137 CmsListInfoBean infoBean = createInfoBean(file); 1138 CmsListItemWidget listItemWidget = new CmsListItemWidget(infoBean); 1139 listItemWidget.setIcon(CmsCoreProvider.get().getResourceTypeIcon(file)); 1140 CmsCheckBox check = new CmsCheckBox(); 1141 check.setChecked(false); 1142 if (!invalid && !isTooLarge && !existingDeleted && !forbiddenType) { 1143 if (file.getFileSize() == 0) { 1144 check.setChecked(false); 1145 } 1146 check.setChecked(m_filesToUpload.containsKey(file.getFileName())); 1147 check.setTitle(file.getFileName()); 1148 if (!m_selectionDone && file.getFileName().toLowerCase().endsWith(".zip")) { 1149 final Widget unzip = createUnzipCheckBox(file); 1150 addClickHandlerToCheckBox(check, unzip, file); 1151 listItemWidget.addButton(unzip); 1152 } else { 1153 addClickHandlerToCheckBox(check, null, file); 1154 } 1155 } else if (forbiddenType) { 1156 String message = Messages.get().key(Messages.GUI_UPLOAD_RESTRICTED_0); 1157 check.disable(message); 1158 listItemWidget.setBackground(Background.RED); 1159 listItemWidget.setSubtitleLabel(message); 1160 } else if (existingDeleted) { 1161 // is invalid 1162 String message = Messages.get().key(Messages.GUI_UPLOAD_FILE_EXISTING_DELETED_1, file.getFileName()); 1163 check.disable(message); 1164 listItemWidget.setBackground(Background.RED); 1165 listItemWidget.setSubtitleLabel(message); 1166 } else if (isTooLarge) { 1167 String message = getFileSizeTooLargeMessage(file); 1168 check.disable(message); 1169 listItemWidget.setBackground(Background.RED); 1170 listItemWidget.setSubtitleLabel(message); 1171 } else { 1172 // is invalid 1173 String message = Messages.get().key( 1174 Messages.GUI_UPLOAD_FILE_INVALID_NAME_2, 1175 file.getFileName(), 1176 CmsUploadButton.formatBytes(file.getFileSize())); 1177 check.disable(message); 1178 listItemWidget.setBackground(Background.RED); 1179 listItemWidget.setSubtitleLabel(message); 1180 } 1181 1182 CmsListItem listItem = new CmsListItem(check, listItemWidget); 1183 m_fileList.addItem(listItem); 1184 m_listItems.put(file.getFileName(), listItem); 1185 doResize(); 1186 } 1187 1188 /** 1189 * Changes the height of the content wrapper so that the dialog finally has the 1190 * same height that the dialog has when the min height is set on the selection screen.<p> 1191 */ 1192 private void changeHeight() { 1193 1194 int firstHeight = MIN_CONTENT_HEIGHT + m_firstInfoHeight + m_firstSummaryHeight + 2; 1195 int currentHeight = CmsDomUtil.getCurrentStyleInt(m_mainPanel.getElement(), CmsDomUtil.Style.height); 1196 int targetHeight = firstHeight - m_dialogInfo.getOffsetHeight() - m_selectionSummary.getOffsetHeight(); 1197 if (currentHeight > firstHeight) { 1198 CmsChangeHeightAnimation.change(m_scrollPanel.getElement(), targetHeight, new Command() { 1199 1200 public void execute() { 1201 1202 doResize(); 1203 } 1204 }, 750); 1205 } 1206 } 1207 1208 /** 1209 * Before the upload data is effectively submited we have to check 1210 * for already existent resources in the VFS.<p> 1211 * 1212 * Executes the RPC call that checks the VFS for existing resources. 1213 * Passes the response object to a method that evaluates the result.<p> 1214 */ 1215 private void checkSelection() { 1216 1217 m_okButton.disable(Messages.get().key(Messages.GUI_UPLOAD_BUTTON_OK_DISABLE_CHECKING_0)); 1218 1219 if (!m_selectionDone) { 1220 m_firstContentHeight = CmsDomUtil.getCurrentStyleInt(m_scrollPanel.getElement(), CmsDomUtil.Style.height); 1221 m_firstInfoHeight = m_dialogInfo.getOffsetHeight(); 1222 m_firstSummaryHeight = m_selectionSummary.getOffsetHeight(); 1223 } 1224 1225 CmsRpcAction<CmsUploadFileBean> callback = new CmsRpcAction<CmsUploadFileBean>() { 1226 1227 /** 1228 * @see org.opencms.gwt.client.rpc.CmsRpcAction#execute() 1229 */ 1230 @Override 1231 public void execute() { 1232 1233 List<String> filesToCheck = new ArrayList<String>(getFilesToUpload().keySet()); 1234 filesToCheck.removeAll(getFilesToUnzip(false)); 1235 getUploadService().checkUploadFiles(filesToCheck, getTargetFolder(), m_isTargetRootPath, this); 1236 } 1237 1238 /** 1239 * @see org.opencms.gwt.client.rpc.CmsRpcAction#onResponse(java.lang.Object) 1240 */ 1241 @Override 1242 protected void onResponse(CmsUploadFileBean result) { 1243 1244 proceedWorkflow(result); 1245 } 1246 }; 1247 callback.execute(); 1248 } 1249 1250 /** 1251 * Closes the dialog after a delay.<p> 1252 */ 1253 private void closeOnSuccess() { 1254 1255 Timer closeTimer = new Timer() { 1256 1257 /** 1258 * @see com.google.gwt.user.client.Timer#run() 1259 */ 1260 @Override 1261 public void run() { 1262 1263 A_CmsUploadDialog.this.hide(); 1264 } 1265 }; 1266 closeTimer.schedule(1500); 1267 } 1268 1269 /** 1270 * Calls the submit action if there are any files selected for upload.<p> 1271 */ 1272 private void commit() { 1273 1274 m_selectionDone = true; 1275 if (!m_filesToUpload.isEmpty()) { 1276 m_okButton.disable(Messages.get().key(Messages.GUI_UPLOAD_BUTTON_OK_DISABLE_UPLOADING_0)); 1277 if (m_uploadButton instanceof UIObject) { 1278 ((UIObject)m_uploadButton).getElement().getStyle().setDisplay(Display.NONE); 1279 } 1280 showProgress(); 1281 submit(); 1282 } 1283 } 1284 1285 /** 1286 * Creates the "OK", the "Cancel" and the "Upload" button.<p> 1287 */ 1288 private void createButtons() { 1289 1290 addDialogClose(new Command() { 1291 1292 public void execute() { 1293 1294 cancelUpload(); 1295 } 1296 }); 1297 1298 CmsPushButton cancelButton = new CmsPushButton(); 1299 cancelButton.setTitle(org.opencms.gwt.client.Messages.get().key(org.opencms.gwt.client.Messages.GUI_CANCEL_0)); 1300 cancelButton.setText(org.opencms.gwt.client.Messages.get().key(org.opencms.gwt.client.Messages.GUI_CANCEL_0)); 1301 cancelButton.setSize(I_CmsButton.Size.medium); 1302 cancelButton.setUseMinWidth(true); 1303 cancelButton.addClickHandler(new ClickHandler() { 1304 1305 /** 1306 * @see com.google.gwt.event.dom.client.ClickHandler#onClick(com.google.gwt.event.dom.client.ClickEvent) 1307 */ 1308 public void onClick(ClickEvent event) { 1309 1310 cancelUpload(); 1311 } 1312 }); 1313 addButton(cancelButton); 1314 1315 m_okButton = new CmsPushButton(); 1316 m_okButton.setTitle(org.opencms.gwt.client.Messages.get().key(org.opencms.gwt.client.Messages.GUI_OK_0)); 1317 m_okButton.setText(org.opencms.gwt.client.Messages.get().key(org.opencms.gwt.client.Messages.GUI_OK_0)); 1318 m_okButton.setSize(I_CmsButton.Size.medium); 1319 m_okButton.setUseMinWidth(true); 1320 m_okButton.addClickHandler(new ClickHandler() { 1321 1322 /** 1323 * @see com.google.gwt.event.dom.client.ClickHandler#onClick(com.google.gwt.event.dom.client.ClickEvent) 1324 */ 1325 public void onClick(ClickEvent event) { 1326 1327 onOkClick(); 1328 } 1329 }); 1330 addButton(m_okButton); 1331 1332 CmsDialogUploadButtonHandler buttonHandler = new CmsDialogUploadButtonHandler( 1333 new Supplier<I_CmsUploadContext>() { 1334 1335 public I_CmsUploadContext get() { 1336 1337 return m_context; 1338 } 1339 }); 1340 buttonHandler.setUploadDialog(this); 1341 // add a new upload button 1342 CmsUploadButton uploadButton = new CmsUploadButton(buttonHandler); 1343 uploadButton.addStyleName(I_CmsLayoutBundle.INSTANCE.uploadCss().uploadDialogButton()); 1344 uploadButton.setText(Messages.get().key(Messages.GUI_UPLOAD_BUTTON_ADD_FILES_0)); 1345 addButton(uploadButton); 1346 m_uploadButton = uploadButton; 1347 } 1348 1349 /** 1350 * Creates the unzip checkbox.<p> 1351 * 1352 * @param file the file to create the checkbox for 1353 * 1354 * @return the unzip checkbox 1355 */ 1356 private Widget createUnzipCheckBox(final CmsFileInfo file) { 1357 1358 final CmsToggleButton unzip = new CmsToggleButton(); 1359 I_CmsUploadCss uploadCss = I_CmsLayoutBundle.INSTANCE.uploadCss(); 1360 String caption = Messages.get().key(Messages.GUI_UNZIP_BUTTON_TEXT_0); 1361 unzip.setUpFace(caption, uploadCss.unzipButtonUpFace()); 1362 unzip.setDownFace(caption, uploadCss.unzipButtonDownFace()); 1363 unzip.addStyleName(uploadCss.unzipButton()); 1364 unzip.addStyleName(org.opencms.gwt.client.ui.css.I_CmsLayoutBundle.INSTANCE.listItemWidgetCss().permaVisible()); 1365 unzip.setDown(getFilesToUnzip(true).contains(file.getFileName())); 1366 if (!m_filesToUpload.containsKey(file.getFileName())) { 1367 unzip.disable(Messages.get().key(Messages.GUI_UPLOAD_FILE_NOT_SELECTED_0)); 1368 } 1369 unzip.addClickHandler(new ClickHandler() { 1370 1371 /** 1372 * @see com.google.gwt.event.dom.client.ClickHandler#onClick(com.google.gwt.event.dom.client.ClickEvent) 1373 */ 1374 public void onClick(ClickEvent event) { 1375 1376 // add or remove the file from the list of files to upload 1377 if (unzip.isDown()) { 1378 getFilesToUnzip(true).add(file.getFileName()); 1379 } else { 1380 getFilesToUnzip(true).remove(file.getFileName()); 1381 } 1382 } 1383 }); 1384 return unzip; 1385 } 1386 1387 /** 1388 * Sets the user info.<p> 1389 * 1390 * @param msg the message to display 1391 * @param warning signals whether the message should be a warning or nor 1392 */ 1393 private void displayDialogInfo(String msg, boolean warning) { 1394 1395 StringBuffer buffer = new StringBuffer(64); 1396 if (!warning) { 1397 buffer.append("<p class=\""); 1398 buffer.append(org.opencms.gwt.client.ui.css.I_CmsLayoutBundle.INSTANCE.uploadButton().dialogMessage()); 1399 buffer.append("\">"); 1400 buffer.append(msg); 1401 buffer.append("</p>"); 1402 } else { 1403 buffer.append(FontOpenCms.WARNING.getHtml(32, I_CmsConstantsBundle.INSTANCE.css().colorWarning())); 1404 buffer.append("<p class=\""); 1405 buffer.append(org.opencms.gwt.client.ui.css.I_CmsLayoutBundle.INSTANCE.uploadButton().warningMessage()); 1406 buffer.append("\">"); 1407 buffer.append(msg); 1408 buffer.append("</p>"); 1409 } 1410 m_dialogInfo.setHTML(buffer.toString()); 1411 } 1412 1413 /** 1414 * Gets the target root path. 1415 * 1416 * @return the target root path 1417 */ 1418 private String getTargetRootPath() { 1419 1420 if (m_isTargetRootPath) { 1421 return m_targetFolder; 1422 } else { 1423 return CmsCoreProvider.get().addSiteRoot(m_targetFolder); 1424 } 1425 } 1426 1427 /** 1428 * Helper method to upload the hook dialog after an upload. 1429 * 1430 * @param uploadedFileIds the uploaded file ids 1431 * @param hookUri the hook URI 1432 * @param context the upload context 1433 */ 1434 private void openHookDialog(List<String> uploadedFileIds, String hookUri, final I_CmsUploadContext context) { 1435 1436 CloseHandler<PopupPanel> closeHandler; 1437 closeHandler = new CloseHandler<PopupPanel>() { 1438 1439 public void onClose(CloseEvent<PopupPanel> event) { 1440 1441 if (context != null) { 1442 List<CmsUUID> actualIds = uploadedFileIds.stream().map(id -> new CmsUUID(id)).collect( 1443 Collectors.toList()); 1444 // post-upload hook may rename files 1445 CmsCoreProvider.getVfsService().getSitePaths(actualIds, new AsyncCallback<List<String>>() { 1446 1447 @Override 1448 public void onFailure(Throwable caught) {} 1449 1450 @Override 1451 public void onSuccess(List<String> result) { 1452 1453 for (int i = 0; i < result.size(); i++) { 1454 String path = result.get(i); 1455 if (path.startsWith(m_targetFolder)) { 1456 result.set(i, path.substring(m_targetFolder.length())); 1457 } 1458 } 1459 context.onUploadFinished(result); 1460 } 1461 }); 1462 } 1463 } 1464 }; 1465 1466 String title = Messages.get().key(Messages.GUI_UPLOAD_HOOK_DIALOG_TITLE_0); 1467 CmsUploadHookDialog.openDialog(title, hookUri, uploadedFileIds, closeHandler); 1468 } 1469 1470 /** 1471 * Removes all widgets from the content wrapper.<p> 1472 */ 1473 private void removeContent() { 1474 1475 m_contentWrapper.clear(); 1476 doResize(); 1477 } 1478 1479 /** 1480 * Sets the height for the content so that the dialog finally has the same height 1481 * as the dialog has on the selection screen.<p> 1482 */ 1483 private void setHeight() { 1484 1485 int infoDiff = m_firstInfoHeight - m_dialogInfo.getOffsetHeight(); 1486 int summaryDiff = m_firstSummaryHeight - m_selectionSummary.getOffsetHeight(); 1487 int height = m_firstContentHeight + infoDiff + summaryDiff; 1488 m_scrollPanel.getElement().getStyle().setHeight(height, Unit.PX); 1489 m_scrollPanel.getElement().getStyle().clearProperty("minHeight"); 1490 m_scrollPanel.getElement().getStyle().clearProperty("maxHeight"); 1491 doResize(); 1492 } 1493 1494 /** 1495 * Shows the overwrite dialog.<p> 1496 * 1497 * @param infoBean the info bean containing the existing and invalid file names 1498 */ 1499 private void showOverwriteDialog(CmsUploadFileBean infoBean) { 1500 1501 // update the dialog 1502 m_selectionDone = true; 1503 m_okButton.enable(); 1504 if (infoBean.getInvalidFileNames().isEmpty() && infoBean.getExistingDeletedFileNames().isEmpty()) { 1505 displayDialogInfo(Messages.get().key(Messages.GUI_UPLOAD_INFO_OVERWRITE_0), true); 1506 } else { 1507 displayDialogInfo(Messages.get().key(Messages.GUI_UPLOAD_INFO_INVALID_0), true); 1508 } 1509 if (m_uploadButton instanceof UIObject) { 1510 ((UIObject)m_uploadButton).getElement().getStyle().setDisplay(Display.NONE); 1511 } 1512 // clear the list 1513 m_fileList.clearList(); 1514 1515 // handle existing files 1516 List<String> existings = new ArrayList<String>(infoBean.getExistingResourceNames()); 1517 Collections.sort(existings, String.CASE_INSENSITIVE_ORDER); 1518 for (String filename : existings) { 1519 addFileToList(m_filesToUpload.get(filename), false, false, false, false); 1520 } 1521 1522 // handle the invalid files 1523 List<String> invalids = new ArrayList<String>(infoBean.getInvalidFileNames()); 1524 Collections.sort(invalids, String.CASE_INSENSITIVE_ORDER); 1525 for (String filename : invalids) { 1526 addFileToList(m_filesToUpload.get(filename), true, false, false, false); 1527 m_filesToUpload.remove(filename); 1528 } 1529 1530 // handle the invalid files 1531 List<String> existingDeleted = new ArrayList<String>(infoBean.getExistingDeletedFileNames()); 1532 Collections.sort(existingDeleted, String.CASE_INSENSITIVE_ORDER); 1533 for (String filename : existingDeleted) { 1534 addFileToList(m_filesToUpload.get(filename), false, true, false, false); 1535 m_filesToUpload.remove(filename); 1536 } 1537 1538 // set the height of the content 1539 setHeight(); 1540 } 1541 1542 /** 1543 * Starts the upload progress bar.<p> 1544 */ 1545 private void showProgress() { 1546 1547 removeContent(); 1548 displayDialogInfo( 1549 org.opencms.gwt.client.Messages.get().key(org.opencms.gwt.client.Messages.GUI_UPLOAD_INFO_UPLOADING_0), 1550 false); 1551 m_selectionSummary.removeFromParent(); 1552 List<String> files = new ArrayList<String>(getFilesToUpload().keySet()); 1553 Collections.sort(files, String.CASE_INSENSITIVE_ORDER); 1554 m_progressInfo = new CmsUploadProgressInfo(files); 1555 m_progressInfo.setContentLength(m_contentLength); 1556 m_contentWrapper.add(m_progressInfo); 1557 m_updateProgressTimer.scheduleRepeating(UPDATE_PROGRESS_INTERVALL); 1558 startLoadingAnimation(Messages.get().key(Messages.GUI_UPLOAD_CLIENT_LOADING_0), 0); 1559 setHeight(); 1560 changeHeight(); 1561 } 1562 1563 /** 1564 * Starts the loading animation.<p> 1565 * 1566 * Used while client is loading files from hard disk into memory.<p> 1567 * 1568 * @param msg the message that should be displayed below the loading animation (can also be HTML as String) 1569 * @param delayMillis the delay to start the animation with 1570 */ 1571 private void startLoadingAnimation(final String msg, int delayMillis) { 1572 1573 m_loadingTimer = new Timer() { 1574 1575 @Override 1576 public void run() { 1577 1578 createLoadingAnimation(msg); 1579 } 1580 }; 1581 if (delayMillis > 0) { 1582 m_loadingTimer.schedule(delayMillis); 1583 } else { 1584 m_loadingTimer.run(); 1585 } 1586 } 1587 1588 /** 1589 * Stops the client loading animation.<p> 1590 */ 1591 private void stopLoadingAnimation() { 1592 1593 if (m_loadingTimer != null) { 1594 m_loadingTimer.cancel(); 1595 } 1596 if (m_clientLoading) { 1597 m_contentWrapper.remove(m_loadingPanel); 1598 doResize(); 1599 m_clientLoading = false; 1600 } 1601 } 1602}