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