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