blob: 683c8ec971149227f7962ef885d9227258d4c3d0 [file] [log] [blame]
/*
* 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);
}
}
}