001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (C) Alkacon Software (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.gwt.client.CmsCoreProvider;
032import org.opencms.gwt.client.ui.CmsErrorDialog;
033import org.opencms.gwt.client.ui.input.upload.CmsFileInfo;
034import org.opencms.gwt.client.ui.input.upload.CmsFileInput;
035import org.opencms.gwt.client.ui.input.upload.I_CmsUploadButton;
036import org.opencms.gwt.client.ui.input.upload.I_CmsUploadButtonHandler;
037import org.opencms.gwt.shared.CmsUploadRestrictionInfo;
038
039import java.util.List;
040
041import com.google.common.base.Supplier;
042import com.google.gwt.core.client.GWT;
043import com.google.gwt.core.client.Scheduler;
044import com.google.gwt.dom.client.Style.Unit;
045import com.google.gwt.event.logical.shared.CloseHandler;
046import com.google.gwt.event.shared.HandlerRegistration;
047import com.google.gwt.user.client.Event;
048import com.google.gwt.user.client.rpc.AsyncCallback;
049import com.google.gwt.user.client.ui.PopupPanel;
050
051/**
052 * Default upload button handler which is used for the upload dialog.<p>
053 */
054public class CmsDialogUploadButtonHandler implements I_CmsUploadButtonHandler {
055
056    /** Handler registration for the user interaction detection. */
057    private static HandlerRegistration m_userInteractionCheckRegistration;
058
059    /** Records if user interaction has occurred. */
060    private static boolean m_userInteraction;
061
062    /** The upload button instance. */
063    private I_CmsUploadButton m_button;
064
065    /** The close handler for the upload dialog. */
066    private CloseHandler<PopupPanel> m_closeHandler;
067
068    /** The handler registration for the close handler of the dialog. */
069    private HandlerRegistration m_closeHandlerRegistration;
070
071    /** Factory for creating upload contexts. */
072    private Supplier<I_CmsUploadContext> m_contextFactory;
073
074    /** True if the the target folder should be treated as a root path. */
075    private boolean m_isTargetRootPath;
076
077    /** The post-create handler. **/
078    private String m_postCreateHandler;
079
080    /** The target folder for the upload dialog. */
081    private String m_targetFolder;
082
083    /** The upload dialog instance. */
084    private A_CmsUploadDialog m_uploadDialog;
085
086    /**
087     * Creates a new upload button handler.<p>
088     *
089     * @param contextFactory the context factory to use for upload contexts
090     */
091    public CmsDialogUploadButtonHandler(Supplier<I_CmsUploadContext> contextFactory) {
092
093        m_contextFactory = contextFactory;
094    }
095
096    /**
097     * Creates a new upload button handler.<p>
098     *
099     * @param contextFactory the context factory to use for upload contexts
100     * @param targetFolder the target folder
101     * @param isRootPath true fi the target folder is a root path
102     */
103    public CmsDialogUploadButtonHandler(
104        Supplier<I_CmsUploadContext> contextFactory,
105        String targetFolder,
106        boolean isRootPath) {
107
108        m_contextFactory = contextFactory;
109        m_targetFolder = targetFolder;
110        m_isTargetRootPath = isRootPath;
111    }
112
113    /**
114     * @see org.opencms.gwt.client.ui.input.upload.I_CmsUploadButtonHandler#initializeFileInput(org.opencms.gwt.client.ui.input.upload.CmsFileInput)
115     */
116    public void initializeFileInput(CmsFileInput fileInput) {
117
118        CmsUploadRestrictionInfo restriction = CmsCoreProvider.get().getUploadRestriction();
119
120        // Set up a repeating job (every 10s) to update the upload restriction info if user interaction was detected
121        // (which we detect in a native preview handler).
122        // We do all this here because we don't need it if no file input is ever initialized.
123        if (m_userInteractionCheckRegistration == null) {
124            Scheduler.get().scheduleFixedDelay(() -> {
125                if (m_userInteraction) {
126                    m_userInteraction = false;
127                    CmsCoreProvider.get();
128                    CmsCoreProvider.getService().loadUploadRestrictionInfo(
129                        new AsyncCallback<CmsUploadRestrictionInfo>() {
130
131                            @Override
132                            public void onFailure(Throwable caught) {
133
134                                CmsErrorDialog.handleException(caught);
135                            }
136
137                            @Override
138                            public void onSuccess(CmsUploadRestrictionInfo result) {
139
140                                CmsCoreProvider.get().setUploadRestrictionInfo(result);
141
142                            }
143                        });
144                }
145                return true;
146
147            }, 10000);
148            m_userInteractionCheckRegistration = Event.addNativePreviewHandler(event -> {
149                if ((event.getTypeInt() == Event.ONMOUSEMOVE)
150                    || (event.getTypeInt() == Event.ONTOUCHSTART)
151                    || (event.getTypeInt() == Event.ONKEYDOWN)
152                    || (event.getTypeInt() == Event.ONSCROLL)) {
153                    m_userInteraction = true;
154
155                }
156
157            });
158
159        }
160
161        if (m_targetFolder != null) {
162
163            String realTargetFolder = m_targetFolder;
164            if (!m_isTargetRootPath) {
165                realTargetFolder = CmsCoreProvider.get().addSiteRoot(m_targetFolder);
166            }
167
168            boolean enabled = restriction.isUploadEnabled(realTargetFolder);
169            m_button.setEnabled(enabled, "");
170            fileInput.setDisabled(!enabled);
171            String accept = restriction.getAcceptAttribute(realTargetFolder);
172            fileInput.setAccept(accept);
173        } else {
174            // CmsGwtLog.log("target folder is null");
175        }
176        // important to set font-size as inline style, as IE7 and IE8 will not accept it otherwise
177        fileInput.getElement().getStyle().setFontSize(200, Unit.PX);
178        fileInput.getElement().getStyle().setProperty("minHeight", "200px");
179        fileInput.setAllowMultipleFiles(true);
180        fileInput.setName("upload");
181        fileInput.addStyleName(
182            org.opencms.gwt.client.ui.css.I_CmsLayoutBundle.INSTANCE.uploadButton().uploadFileInput());
183    }
184
185    /**
186     * @see org.opencms.gwt.client.ui.input.upload.I_CmsUploadButtonHandler#onChange(org.opencms.gwt.client.ui.input.upload.CmsFileInput)
187     */
188    public void onChange(CmsFileInput fileInput) {
189
190        if (m_uploadDialog == null) {
191            try {
192                m_uploadDialog = GWT.create(CmsUploadDialogImpl.class);
193                I_CmsUploadContext context = m_contextFactory.get();
194                m_uploadDialog.setContext(context);
195                updateDialog();
196                // the current upload button is located outside the dialog, reinitialize it with a new button handler instance
197                m_button.reinitButton(
198                    new CmsDialogUploadButtonHandler(m_contextFactory, m_targetFolder, m_isTargetRootPath));
199            } catch (Exception e) {
200                CmsErrorDialog.handleException(
201                    new Exception(
202                        "Deserialization of dialog data failed. This may be caused by expired java-script resources, please clear your browser cache and try again.",
203                        e));
204                return;
205            }
206        }
207        m_uploadDialog.addFileInput(fileInput);
208        m_button.createFileInput();
209    }
210
211    /**
212     * Opens the upload dialog for the given file references.<p>
213     *
214     * @param files the file references
215     */
216    public void openDialogWithFiles(List<CmsFileInfo> files) {
217
218        if (m_uploadDialog == null) {
219            try {
220                m_uploadDialog = GWT.create(CmsUploadDialogImpl.class);
221                I_CmsUploadContext context = m_contextFactory.get();
222                m_uploadDialog.setContext(context);
223                updateDialog();
224                if (m_button != null) {
225                    // the current upload button is located outside the dialog, reinitialize it with a new button handler instance
226                    m_button.reinitButton(
227                        new CmsDialogUploadButtonHandler(m_contextFactory, m_targetFolder, m_isTargetRootPath));
228                }
229            } catch (Exception e) {
230                CmsErrorDialog.handleException(
231                    new Exception(
232                        "Deserialization of dialog data failed. This may be caused by expired java-script resources, please clear your browser cache and try again.",
233                        e));
234                return;
235            }
236        }
237        m_uploadDialog.addFiles(files);
238        if (m_button != null) {
239            m_button.createFileInput();
240        }
241    }
242
243    /**
244     * @see org.opencms.gwt.client.ui.input.upload.I_CmsUploadButtonHandler#setButton(org.opencms.gwt.client.ui.input.upload.I_CmsUploadButton)
245     */
246    public void setButton(I_CmsUploadButton button) {
247
248        m_button = button;
249    }
250
251    /**
252     * Sets the close handler for the dialog.<p>
253     *
254     * @param closeHandler the close handler
255     */
256    public void setCloseHandler(CloseHandler<PopupPanel> closeHandler) {
257
258        m_closeHandler = closeHandler;
259        updateDialog();
260
261    }
262
263    /**
264     * Chooses whether the target folder should be interpreted as a root path.<p>
265     *
266     * @param isTargetRootPath true if the target folder should be treated as a root path
267     */
268    public void setIsTargetRootPath(boolean isTargetRootPath) {
269
270        m_isTargetRootPath = isTargetRootPath;
271    }
272
273    /**
274     * Sets the post-create handler.
275     *
276     * @param postCreateHandler the post-create handler
277     */
278    public void setPostCreateHandler(String postCreateHandler) {
279
280        m_postCreateHandler = postCreateHandler;
281    }
282
283    /**
284     * Sets the upload target folder.<p>
285     *
286     * @param targetFolder the upload target folder
287     */
288    public void setTargetFolder(String targetFolder) {
289
290        m_targetFolder = targetFolder;
291        updateDialog();
292    }
293
294    /**
295     * Sets the upload dialog instance.<p>
296     *
297     * @param uploadDialog the upload dialog instance
298     */
299    public void setUploadDialog(A_CmsUploadDialog uploadDialog) {
300
301        m_uploadDialog = uploadDialog;
302    }
303
304    /**
305     * Updates the dialog with the current close handler and target folder.<p>
306     */
307    protected void updateDialog() {
308
309        if (m_uploadDialog != null) {
310            if ((m_closeHandler != null)) {
311                if (m_closeHandlerRegistration != null) {
312                    m_closeHandlerRegistration.removeHandler();
313                }
314                m_closeHandlerRegistration = m_uploadDialog.addCloseHandler(m_closeHandler);
315            }
316            if ((m_targetFolder != null)) {
317                m_uploadDialog.setTargetFolder(m_targetFolder);
318            }
319            m_uploadDialog.setPostCreateHandler(m_postCreateHandler);
320            m_uploadDialog.setIsTargetRootPath(m_isTargetRootPath);
321            m_uploadDialog.updateHandler();
322        }
323    }
324}