| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License") + you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.apache.openmeetings.web.user.record; |
| |
| import static org.apache.openmeetings.util.OmFileHelper.MP4_EXTENSION; |
| import static org.apache.openmeetings.util.OmFileHelper.getHumanSize; |
| import static org.apache.openmeetings.util.OmFileHelper.isRecordingExists; |
| import static org.apache.openmeetings.web.app.Application.getBean; |
| import static org.apache.openmeetings.web.app.WebSession.getUserId; |
| |
| import java.util.Arrays; |
| import java.util.Date; |
| import java.util.Iterator; |
| |
| import org.apache.openmeetings.db.dao.record.FlvRecordingDao; |
| import org.apache.openmeetings.db.dao.user.UserDao; |
| import org.apache.openmeetings.db.dto.file.RecordingContainerData; |
| import org.apache.openmeetings.db.entity.record.FlvRecording; |
| import org.apache.openmeetings.db.entity.record.FlvRecording.Status; |
| import org.apache.openmeetings.db.entity.user.Organisation; |
| import org.apache.openmeetings.db.entity.user.Organisation_Users; |
| import org.apache.openmeetings.web.app.WebSession; |
| import org.apache.openmeetings.web.common.AddFolderDialog; |
| import org.apache.openmeetings.web.common.ConfirmableAjaxLink; |
| import org.apache.openmeetings.web.common.UserPanel; |
| import org.apache.wicket.Component; |
| import org.apache.wicket.ajax.AjaxEventBehavior; |
| import org.apache.wicket.ajax.AjaxRequestTarget; |
| import org.apache.wicket.ajax.AjaxSelfUpdatingTimerBehavior; |
| import org.apache.wicket.extensions.markup.html.repeater.tree.DefaultNestedTree; |
| import org.apache.wicket.extensions.markup.html.repeater.tree.ITreeProvider; |
| import org.apache.wicket.extensions.markup.html.repeater.tree.content.Folder; |
| import org.apache.wicket.markup.html.WebMarkupContainer; |
| import org.apache.wicket.markup.html.basic.Label; |
| import org.apache.wicket.markup.repeater.RepeatingView; |
| import org.apache.wicket.markup.repeater.ReuseIfModelsEqualStrategy; |
| import org.apache.wicket.model.CompoundPropertyModel; |
| import org.apache.wicket.model.IModel; |
| import org.apache.wicket.model.Model; |
| import org.apache.wicket.util.time.Duration; |
| |
| import wicketdnd.DragSource; |
| import wicketdnd.DropTarget; |
| import wicketdnd.Location; |
| import wicketdnd.Operation; |
| import wicketdnd.Reject; |
| import wicketdnd.Transfer; |
| |
| public class RecordingsPanel extends UserPanel { |
| private static final long serialVersionUID = 1321258690447136958L; |
| private final WebMarkupContainer trees = new WebMarkupContainer("tree-container"); |
| private final WebMarkupContainer sizes = new WebMarkupContainer("sizes"); |
| private final VideoPlayer video = new VideoPlayer("video"); |
| private final VideoInfo info = new VideoInfo("info"); |
| private final IModel<FlvRecording> rm = new CompoundPropertyModel<FlvRecording>(new FlvRecording()); |
| private final IModel<String> homeSize = Model.of((String)null); |
| private final IModel<String> publicSize = Model.of((String)null); |
| private final RecordingErrorsDialog errorsDialog = new RecordingErrorsDialog("errors", Model.of((FlvRecording)null)); |
| private RecordingTree selected; |
| |
| public RecordingsPanel(String id) { |
| super(id); |
| rm.getObject().setFlvRecordingId(Long.MIN_VALUE); |
| final AddFolderDialog addFolder = new AddFolderDialog("addFolder", WebSession.getString(712)) { |
| private static final long serialVersionUID = 1L; |
| |
| @Override |
| protected void onSubmit(AjaxRequestTarget target) { |
| FlvRecording f = new FlvRecording(); |
| f.setFileName(getModelObject()); |
| f.setInsertedBy(getUserId()); |
| f.setInserted(new Date()); |
| f.setFolder(true); |
| f.setIsImage(false); |
| f.setIsPresentation(false); |
| f.setIsRecording(true); |
| FlvRecording p = rm.getObject(); |
| long parentId = p.getFlvRecordingId(); |
| if (p.isFolder()) { |
| f.setParentFileExplorerItemId(parentId); |
| } |
| f.setOwnerId(p.getOwnerId()); |
| f.setOrganization_id(p.getOrganization_id()); |
| getBean(FlvRecordingDao.class).update(f); |
| target.add(trees); //FIXME add correct refresh |
| } |
| }; |
| add(addFolder); |
| add(new WebMarkupContainer("create").add(new AjaxEventBehavior("onclick") { |
| private static final long serialVersionUID = 1L; |
| |
| @Override |
| protected void onEvent(AjaxRequestTarget target) { |
| addFolder.open(target); |
| } |
| })); |
| add(new WebMarkupContainer("refresh").add(new AjaxEventBehavior("onclick") { |
| private static final long serialVersionUID = 1L; |
| |
| @Override |
| protected void onEvent(AjaxRequestTarget target) { |
| target.add(trees); //FIXME add correct refresh |
| } |
| })); |
| ConfirmableAjaxLink trash = new ConfirmableAjaxLink("trash", 713) { |
| private static final long serialVersionUID = 1L; |
| |
| @Override |
| public void onClick(AjaxRequestTarget target) { |
| long id = rm.getObject().getFlvRecordingId(); |
| if (id > 0) { |
| getBean(FlvRecordingDao.class).delete(rm.getObject()); |
| } |
| target.add(trees); //FIXME add correct refresh |
| } |
| }; |
| trash.add(new WebMarkupContainer("drop-center").setOutputMarkupId(true)).add(new DropTarget(Operation.MOVE) { |
| private static final long serialVersionUID = 1L; |
| |
| @Override |
| public void onDrop(AjaxRequestTarget target, Transfer transfer, Location location) throws Reject { |
| FlvRecording r = transfer.getData(); |
| getBean(FlvRecordingDao.class).delete(r); |
| target.add(trees); //FIXME add correct refresh |
| } |
| }.dropCenter("span")); |
| add(trash/*.add(new WindowsTheme())*/); //TODO check theme here |
| RepeatingView treesView = new RepeatingView("tree"); |
| treesView.add(selected = new RecordingTree(treesView.newChildId(), new MyRecordingTreeProvider())); |
| treesView.add(new RecordingTree(treesView.newChildId(), new PublicRecordingTreeProvider(null, null))); |
| for (Organisation_Users ou : getBean(UserDao.class).get(getUserId()).getOrganisation_users()) { |
| Organisation o = ou.getOrganisation(); |
| treesView.add(new RecordingTree(treesView.newChildId(), new PublicRecordingTreeProvider(o.getOrganisation_id(), o.getName()))); |
| } |
| add(trees.add(treesView).setOutputMarkupId(true)); |
| updateSizes(); |
| add(sizes.add(new Label("homeSize", homeSize), new Label("publicSize", publicSize)).setOutputMarkupId(true)); |
| sizes.add(new AjaxSelfUpdatingTimerBehavior(Duration.seconds(30)) { |
| private static final long serialVersionUID = 1L; |
| |
| protected void onPostProcessTarget(AjaxRequestTarget target) { |
| updateSizes(); |
| } |
| }); |
| add(video, info, errorsDialog); |
| } |
| |
| private void updateSizes() { |
| RecordingContainerData sizeData = getBean(FlvRecordingDao.class).getRecordingContainerData(getUserId()); |
| if (sizeData != null) { |
| homeSize.setObject(getHumanSize(sizeData.getUserHomeSize())); |
| publicSize.setObject(getHumanSize(sizeData.getPublicFileSize())); |
| } |
| } |
| |
| //FIXME need to be generalized to use as Room files explorer |
| class RecordingTree extends DefaultNestedTree<FlvRecording> { |
| private static final long serialVersionUID = 2527395034256868022L; |
| |
| public RecordingTree(String id, ITreeProvider<FlvRecording> tp) { |
| super(id, tp); |
| setItemReuseStrategy(new ReuseIfModelsEqualStrategy()); |
| } |
| |
| @Override |
| protected Component newContentComponent(String id, IModel<FlvRecording> node) { |
| return new Folder<FlvRecording>(id, this, node) { |
| private static final long serialVersionUID = 1020976220467419084L; |
| |
| @Override |
| protected Component newLabelComponent(String id, final IModel<FlvRecording> lm) { |
| FlvRecording r = lm.getObject(); |
| Component result = r.isFolder() || r.getFlvRecordingId() < 1 ? new RecordingPanel(id, lm) : new RecordingItemPanel(id, lm, errorsDialog); |
| if (r.getFlvRecordingId() > 0) { |
| result.add(new DragSource(Operation.MOVE) { |
| private static final long serialVersionUID = 1L; |
| |
| @Override |
| public void onBeforeDrop(Component drag, Transfer transfer) throws Reject { |
| transfer.setData(lm.getObject()); |
| }; |
| |
| @Override |
| public void onAfterDrop(AjaxRequestTarget target, wicketdnd.Transfer transfer) { |
| transfer.setData(null); |
| } |
| }.drag("div")); |
| } |
| if (r.getFlvRecordingId() < 0 || r.isFolder()) { |
| result.add(new DropTarget(Operation.MOVE) { |
| private static final long serialVersionUID = 1L; |
| |
| @Override |
| public void onDrop(AjaxRequestTarget target, Transfer transfer, Location location) throws Reject { |
| FlvRecording p = lm.getObject(); |
| long pid = p.getFlvRecordingId(); |
| FlvRecording r = transfer.getData(); |
| r.setParentFileExplorerItemId(pid > 0 ? pid : null); |
| r.setOrganization_id(p.getOrganization_id()); |
| r.setOwnerId(p.getOwnerId()); |
| getBean(FlvRecordingDao.class).update(r); |
| target.add(trees); //FIXME add correct refresh |
| } |
| }.dropCenter("div")); |
| } |
| return result; |
| } |
| |
| @Override |
| protected boolean isSelected() { |
| return getModelObject().getFlvRecordingId() == rm.getObject().getFlvRecordingId(); |
| } |
| |
| @Override |
| protected boolean isClickable() { |
| return true; |
| } |
| |
| @Override |
| protected void onClick(AjaxRequestTarget target) { |
| FlvRecording r = getModelObject(); |
| FlvRecording _prev = rm.getObject(); |
| rm.setObject(r); |
| if (_prev != null) { |
| if (_prev.isFolder()) { |
| selected.updateBranch(_prev, target); |
| } else { |
| selected.updateNode(_prev, target); |
| } |
| } |
| selected = RecordingTree.this; |
| if (r.isFolder()) { |
| if (getState(r) == State.COLLAPSED) { |
| super.onClick(target); |
| } |
| updateBranch(r, target); |
| } else { |
| video.update(target, r); |
| info.update(target, r); |
| updateNode(r, target); |
| } |
| } |
| |
| private String getRecordingStyle(FlvRecording r, String def) { |
| String style; |
| if (r.getFlvRecordingId() == 0) { |
| style = "my-recordings om-icon"; |
| } else if (r.getFlvRecordingId() < 0) { |
| style = "public-recordings om-icon"; |
| } else if (r.isFolder()) { |
| style = def; |
| } else if (isRecordingExists(r.getFileHash() + MP4_EXTENSION)) { |
| style = "recording om-icon"; |
| } else if (Status.PROCESSING == r.getStatus()) { |
| style = "processing-recording om-icon"; |
| } else { |
| style = "broken-recording om-icon"; |
| } |
| return style; |
| } |
| |
| @Override |
| protected String getOtherStyleClass(FlvRecording r) { |
| String style = getRecordingStyle(r, super.getOtherStyleClass(r)); |
| if (isSelected()) { |
| style += " selected"; |
| } |
| return style; |
| } |
| |
| @Override |
| protected String getOpenStyleClass() { |
| return getRecordingStyle(getModelObject(), super.getOpenStyleClass()); |
| } |
| |
| @Override |
| protected String getClosedStyleClass() { |
| return getRecordingStyle(getModelObject(), super.getClosedStyleClass()); |
| } |
| |
| @Override |
| protected IModel<String> newLabelModel(IModel<FlvRecording> model) { |
| return Model.of(model.getObject().getFileName()); |
| } |
| }; |
| } |
| } |
| |
| class MyRecordingTreeProvider extends RecordingTreeProvider { |
| private static final long serialVersionUID = 1L; |
| |
| public Iterator<? extends FlvRecording> getRoots() { |
| FlvRecording r = new FlvRecording(); |
| r.setFlvRecordingId(0); |
| r.setFileName(WebSession.getString(860)); |
| r.setOwnerId(getUserId()); |
| return Arrays.asList(r).iterator(); |
| } |
| |
| public Iterator<? extends FlvRecording> getChildren(FlvRecording node) { |
| if (node.getFlvRecordingId() == 0) { |
| return getBean(FlvRecordingDao.class).getFlvRecordingRootByOwner(getUserId()).iterator(); |
| } else { |
| return super.getChildren(node); |
| } |
| } |
| } |
| |
| class PublicRecordingTreeProvider extends RecordingTreeProvider { |
| private static final long serialVersionUID = 5502610991599632079L; |
| private final Long orgId; |
| private final String name; |
| |
| public PublicRecordingTreeProvider(Long orgId, String name) { |
| this.orgId = orgId; |
| this.name = name; |
| } |
| |
| public Iterator<? extends FlvRecording> getRoots() { |
| FlvRecording r = new FlvRecording(); |
| r.setFlvRecordingId(orgId == null ? -1 : -orgId); |
| r.setOrganization_id(orgId); |
| r.setOwnerId(null); |
| String pub = WebSession.getString(861); |
| r.setFileName(orgId == null ? pub : String.format("%s (%s)", pub, name)); |
| return Arrays.asList(r).iterator(); |
| } |
| |
| public Iterator<? extends FlvRecording> getChildren(FlvRecording node) { |
| if (node.getFlvRecordingId() < 0) { |
| return getBean(FlvRecordingDao.class).getFlvRecordingRootByPublic(orgId).iterator(); |
| } else { |
| return super.getChildren(node); |
| } |
| } |
| } |
| |
| abstract class RecordingTreeProvider implements ITreeProvider<FlvRecording> { |
| private static final long serialVersionUID = 1L; |
| |
| public void detach() { |
| // TODO LDM should be used |
| } |
| |
| public boolean hasChildren(FlvRecording node) { |
| return node.getFlvRecordingId() <= 0 || node.isFolder(); |
| } |
| |
| public Iterator<? extends FlvRecording> getChildren(FlvRecording node) { |
| return getBean(FlvRecordingDao.class).getFlvRecordingByParent(node.getFlvRecordingId()).iterator(); |
| } |
| |
| public IModel<FlvRecording> model(FlvRecording object) { |
| // TODO LDM should be used |
| return Model.of(object); |
| } |
| |
| } |
| } |