Skelett till sidstruktur och sortering i filvy och filväljare implementerad

git-svn-id: svn://svn.dsv.su.se/scipro/scipro/trunk@234 73ecded7-942e-4092-bab0-0e58ef0ee984
This commit is contained in:
mpeters 2011-02-23 11:36:08 +00:00
parent 0878f1f40d
commit e61dbe58d2
14 changed files with 642 additions and 167 deletions

@ -25,7 +25,7 @@ import java.util.Date;
* @author vytautas racelis
* @author Martin Peters - mpeters@dsv.su.se
*/
public class FileDescription implements Serializable{
public class FileDescription implements Serializable, Comparable<FileDescription>{
private static final long serialVersionUID = 1L;
private String name;
@ -103,5 +103,16 @@ public class FileDescription implements Serializable{
throw new IllegalStateException("Tried to get hashCode fore FileDescription where identifier was not set");
return this.getIdentifier().hashCode();
}
@Override
public String toString(){
if(name != null)
return name;
else
return super.toString();
}
@Override
public int compareTo(FileDescription other) {
return this.name.compareToIgnoreCase(other.name);
}
}

@ -101,7 +101,7 @@ public interface FileRepository {
* @param path
* @return
*/
List<String> searchFolders(String path);
List<FolderDescription> searchFolders(String path);
/**
* Retrieve information for a single file
@ -143,4 +143,18 @@ public interface FileRepository {
* @return
*/
String getProjectRootPath(Long projectId);
/**
* Convenience method to sort folders according to the input parameters
* @param list
* @param sortOrder
* @param descending
*/
void sortFolderDescriptions(List<FolderDescription> list, SortOrder sortOrder);
/**
* Convenience method to sort files according to the input parameters
* @param list
* @param sortOrder
* @param descending
*/
void sortFileDescriptions(List<FileDescription> list, SortOrder sortOrder);
}

@ -24,6 +24,8 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import javax.jcr.ItemNotFoundException;
@ -165,7 +167,7 @@ public class FileRepositoryImpl implements FileRepository {
NodeIterator ni = node.getNodes();
while (ni.hasNext()) {
Node file = ni.nextNode();
if (isFile (file)) {
if( isFile(file) ) {
FileDescription desc = new FileDescription();
desc.setPath(file.getPath());
desc.setName(file.getName());
@ -185,11 +187,18 @@ public class FileRepositoryImpl implements FileRepository {
return result;
}
private boolean isFile(Node file) {
private boolean isFile(Node node) {
try {
return "nt:file".equals(file.getPrimaryNodeType().getName());
return "nt:file".equals(node.getPrimaryNodeType().getName());
} catch (RepositoryException e) {
throw new FileStorageException ("Error while checking for a file", e);
throw new FileStorageException ("Error while checking nodetype", e);
}
}
private boolean isFolder(Node node) {
try {
return "nt:folder".equals(node.getPrimaryNodeType().getName());
} catch (RepositoryException e) {
throw new FileStorageException ("Error while checking nodetype", e);
}
}
@ -230,8 +239,8 @@ public class FileRepositoryImpl implements FileRepository {
}
}
public List<String> searchFolders(String searchPath) {
List<String> result = new ArrayList<String>();
public List<FolderDescription> searchFolders(String searchPath) {
List<FolderDescription> result = new ArrayList<FolderDescription>();
try {
Session session = repositoryManager.getDefaultSession();
if (!session.getRootNode().hasNode(searchPath)) {
@ -241,8 +250,13 @@ public class FileRepositoryImpl implements FileRepository {
NodeIterator ni = node.getNodes();
while (ni.hasNext()) {
Node item = ni.nextNode();
if (!isFile(item)) {
result.add(item.getName());
if(isFolder(item)){
//System.out.println(item.getProperty("jcr:created").getDate());
FolderDescription tmp = new FolderDescription();
tmp.setName(item.getName());
tmp.setIdentifier(item.getIdentifier());
tmp.setCreated(item.getProperty("jcr:created").getDate().getTime());
result.add(tmp);
}
}
} catch (Exception e) {
@ -352,4 +366,173 @@ public class FileRepositoryImpl implements FileRepository {
String result = startId.toString() + "-" + endId.toString() + "/" + projectId.toString() +"/";
return result;
}
@Override
public void sortFolderDescriptions(List<FolderDescription> list,
SortOrder sortOrder) {
if(sortOrder == null){
Collections.sort(list, new FolderName(false));
}
else{
switch(sortOrder){
case NameDesc:
Collections.sort(list, new FolderName(true));
break;
case Created:
Collections.sort(list, new FolderCreated(false));
break;
case CreatedDesc:
Collections.sort(list, new FolderCreated(true));
break;
default:
Collections.sort(list, new FolderName(false));
break;
}
}
}
@Override
public void sortFileDescriptions(List<FileDescription> list,
SortOrder sortOrder) {
if(sortOrder == null){
Collections.sort(list);
}
else {
switch(sortOrder){
case NameDesc:
Collections.sort(list, new FileName(true));
break;
case Created:
Collections.sort(list, new FileCreated(false));
break;
case CreatedDesc:
Collections.sort(list, new FileCreated(true));
break;
case Size:
Collections.sort(list, new FileSize(false));
break;
case SizeDesc:
Collections.sort(list, new FileSize(true));
break;
case MimeType:
Collections.sort(list, new FileType(false));
break;
case MimeTypeDesc:
Collections.sort(list, new FileType(true));
break;
case User:
Collections.sort(list, new FileUser(false));
break;
case UserDesc:
Collections.sort(list, new FileUser(true));
break;
default:
Collections.sort(list, new FileName(false));
break;
}
}
}
private class FolderName implements Comparator<FolderDescription>{
final private boolean reversed;
public FolderName(boolean reversed){
this.reversed = reversed;
}
@Override
public int compare(FolderDescription o1, FolderDescription o2) {
int result = o1.getName().compareToIgnoreCase(o2.getName());
if(reversed)
return -result;
else
return result;
}
}
private class FolderCreated implements Comparator<FolderDescription>{
final private boolean reversed;
public FolderCreated(boolean reversed){
this.reversed = reversed;
}
@Override
public int compare(FolderDescription o1, FolderDescription o2) {
int result = o1.getCreated().compareTo(o2.getCreated());
if(reversed)
return -result;
else
return result;
}
}
private class FileName implements Comparator<FileDescription>{
final private boolean reversed;
public FileName(boolean reversed){
this.reversed = reversed;
}
@Override
public int compare(FileDescription o1, FileDescription o2) {
int result = o1.getName().compareToIgnoreCase(o2.getName());
if(reversed)
return -result;
else
return result;
}
}
private class FileCreated implements Comparator<FileDescription>{
final private boolean reversed;
public FileCreated(boolean reversed){
this.reversed = reversed;
}
@Override
public int compare(FileDescription o1, FileDescription o2) {
int result = o1.getLastModified().compareTo(o2.getLastModified());
if(reversed)
return -result;
else
return result;
}
}
private class FileSize implements Comparator<FileDescription>{
final private boolean reversed;
public FileSize(boolean reversed){
this.reversed = reversed;
}
@Override
public int compare(FileDescription o1, FileDescription o2) {
int result = o1.getSize().compareTo(o2.getSize());
if(reversed)
return -result;
else
return result;
}
}
private class FileType implements Comparator<FileDescription>{
final private boolean reversed;
public FileType(boolean reversed){
this.reversed = reversed;
}
@Override
public int compare(FileDescription o1, FileDescription o2) {
int result = o1.getMimeType().compareTo(o2.getMimeType());
if(reversed)
return -result;
else
return result;
}
}
private class FileUser implements Comparator<FileDescription>{
final private boolean reversed;
public FileUser(boolean reversed){
this.reversed = reversed;
}
@Override
public int compare(FileDescription o1, FileDescription o2) {
int result = o1.getUserId().compareTo(o2.getUserId());
if(reversed)
return -result;
else
return result;
}
}
}

@ -0,0 +1,81 @@
/*
* 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 se.su.dsv.scipro.repository;
import java.io.Serializable;
import java.util.Date;
/**
* http://www.xaloon.org
*
* @author vytautas racelis
* @author Martin Peters - mpeters@dsv.su.se
*/
public class FolderDescription implements Serializable, Comparable<FolderDescription> {
private static final long serialVersionUID = 1L;
private String name;
private Date created;
private String identifier;
public String getIdentifier() {
return identifier;
}
public void setIdentifier(String identifier) {
this.identifier = identifier;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getCreated() {
return created;
}
public void setCreated(Date date) {
created = date;
}
@Override
public boolean equals(Object other){
if(other == null)
return false;
if(!(other instanceof FolderDescription))
return false;
FolderDescription fDesc = (FolderDescription) other;
if(this.getIdentifier() == null || fDesc.getIdentifier() == null)
throw new IllegalStateException("Tried to check FolderDescription objects for equality where identifier was null");
if(!this.getIdentifier().equals(fDesc.identifier))
return false;
return true;
}
@Override
public int hashCode(){
if(this.getIdentifier() == null)
throw new IllegalStateException("Tried to get hashCode fore FolderDescription where identifier was not set");
return this.getIdentifier().hashCode();
}
@Override
public int compareTo(FolderDescription other) {
return this.getName().compareToIgnoreCase(other.getName());
}
}

@ -0,0 +1,7 @@
package se.su.dsv.scipro.repository;
public enum SortOrder {
Name, NameDesc, Created, CreatedDesc, Size, SizeDesc, MimeType, MimeTypeDesc, User, UserDesc
}

@ -1,47 +1,55 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"
xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd"
>
xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
<body>
<wicket:panel>
<div wicket:id="upLinkContainer">
<a href=# wicket:id="upLink">[..]</a>
</div>
<div wicket:id="listFolders">
<table>
<tr wicket:id="content">
<td style="width: 420px"><a href="#" wicket:id="folderLink"><span
wicket:id="name">name</span></a></td>
</tr>
</table>
</div>
<div wicket:id="listFiles">
<table>
<tr wicket:id="content">
<td style="width: 120px"><span wicket:id="size">name</span></td>
<td style="width: 220px"><span wicket:id="modified">name</span></td>
<td style="width: 420px"><span wicket:id="name">name</span></td>
<td><span wicket:id="mimeType">mimeType</span></td>
<td><span wicket:id="userId">userId</span></td>
<td><a href="#" wicket:id="preview">Preview</a></td>
<td style="width: 20px"><a href="#" wicket:id="select">Select</a></td>
</tr>
</table>
</div>
<span wicket:id="feedBack"></span>
<div wicket:id="listSelected">
<wicket:panel>
<table>
<thead>
<tr>
<th><a href=# wicket:id="sortName">Name</a></th>
<th><a href=# wicket:id="sortCreated">Created</a></th>
<th><a href=# wicket:id="sortSize">Size</a></th>
<th><a href=# wicket:id="sortType">Type</a></th>
<th><a href=# wicket:id="sortUser">User</a></th>
</tr>
</thead>
<tbody>
<tr>
<td><span wicket:id="upLinkContainer"><a href=# wicket:id="upLink">[..]</a></span></td>
</tr>
</tbody>
<tbody wicket:id="listFolders">
<tr wicket:id="content">
<td><a href="#" wicket:id="folderLink"><span
wicket:id="name">name</span></a></td>
<td><span wicket:id="created">created</span></td>
</tr>
</tbody>
<tbody wicket:id="listFiles">
<tr wicket:id="content">
<td><span wicket:id="name">name</span></td>
<td><span wicket:id="modified">name</span></td>
<td><span wicket:id="size">name</span></td>
<td><span wicket:id="mimeType">mimeType</span></td>
<td><span wicket:id="userId">userId</span></td>
<td><a href="#" wicket:id="preview">Preview</a></td>
<td><a href="#" wicket:id="select">Select</a></td>
</tr>
</tbody>
</table>
<span wicket:id="feedBack"></span>
<div wicket:id="listSelected">
<p>Selected: <span wicket:id="remaining"></span></p>
<p><a href=# wicket:id="clearSelection">Clear</a></p>
<table>
<tr wicket:id="content">
<td><span wicket:id="name">name</span></td>
<td><a href=# wicket:id="removeItem">X</a></td>
</tr>
</table>
</div>
</wicket:panel>
<tr wicket:id="content">
<td><span wicket:id="name">name</span></td>
<td><a href=# wicket:id="removeItem">X</a></td>
</tr>
</table>
</div>
</wicket:panel>
</body>
</html>

@ -3,8 +3,6 @@ package se.su.dsv.scipro.repository.components;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.ListIterator;
@ -23,14 +21,28 @@ import org.apache.wicket.model.util.ListModel;
import org.apache.wicket.spring.injection.annot.SpringBean;
import org.apache.wicket.util.resource.IResourceStream;
import se.su.dsv.scipro.SciProSession;
import se.su.dsv.scipro.data.dao.interfaces.ProjectDao;
import se.su.dsv.scipro.data.dao.interfaces.UserDao;
import se.su.dsv.scipro.data.dataobjects.Project;
import se.su.dsv.scipro.data.dataobjects.User;
import se.su.dsv.scipro.repository.FileDescription;
import se.su.dsv.scipro.repository.FileRepository;
import se.su.dsv.scipro.repository.FolderDescription;
import se.su.dsv.scipro.repository.SortOrder;
import se.su.dsv.scipro.security.auth.MetaDataActionStrategy;
import se.su.dsv.scipro.security.auth.roles.Roles;
public class FileChooser extends Panel {
private static final long serialVersionUID = 1L;
@SpringBean
protected FileRepository fileRepository;
@SpringBean
protected UserDao userDao;
@SpringBean
protected ProjectDao projectDao;
private String rootPath;
@ -43,50 +55,105 @@ public class FileChooser extends Panel {
private final int maxSelections;
private final boolean allowDuplicates;
private String currentAbsolutePath;
private SortOrder sortOrder = SortOrder.Name;
public FileChooser(String id, int maxSelections){
private String currentAbsolutePath;
public synchronized static FileChooser createProjectFileChooser(String id, int maxSelections, boolean allowDuplicates, Project project){
FileChooser result = new FileChooser(id, maxSelections, allowDuplicates);
result.rootPath = result.fileRepository.getProjectRootPath(project.getId());
result.init();
if(!result.projectDao.isPartOf(SciProSession.get().getUser(), project))
result.setEnabled(false);
return result;
}
public synchronized static FileChooser createRootFileChooser(String id, int maxSelections, boolean allowDuplicates){
FileChooser result = new FileChooser(id, maxSelections, allowDuplicates);
result.rootPath = result.fileRepository.getRepositoryRootPath();
result.init();
MetaDataActionStrategy.authorize(result, Roles.SYSADMIN, false);
return result;
}
protected FileChooser(String id, int maxSelections){
this(id, maxSelections, false);
}
public FileChooser(String id, int maxSelections, boolean allowDuplicates){
protected FileChooser(String id, int maxSelections, boolean allowDuplicates){
super(id);
this.maxSelections = maxSelections;
this.allowDuplicates = allowDuplicates;
rootPath = fileRepository.getRepositoryRootPath();
upLinkContainer = new WebMarkupContainer("upLinkContainer");
listFiles = new WebMarkupContainer("listFiles");
listFolders = new WebMarkupContainer("listFolders");
listSelected = new WebMarkupContainer("listSelected");
}
private void init(){
currentAbsolutePath = rootPath;
model = new ListModel<FileDescription>();
model.setObject(new ArrayList<FileDescription>(maxSelections));
this.setDefaultModel(model);
this.setDefaultModel(model);
upLinkContainer = new WebMarkupContainer("upLinkContainer");
upLinkContainer.setOutputMarkupId(true);
add(upLinkContainer);
listFiles = new WebMarkupContainer("listFiles");
add(upLinkContainer);
listFiles.setOutputMarkupId(true);
reloadFiles();
add(listFiles);
add(listFiles);
listFolders = new WebMarkupContainer("listFolders");
listFolders.setOutputMarkupId(true);
reloadFolders();
add(listFolders);
add(listFolders);
listSelected = new WebMarkupContainer("listSelected");
listSelected.setOutputMarkupId(true);
reloadSelected();
add(listSelected);
add(new FeedbackPanel("feedBack"));
//Add headers for sorting
add(getSortLink("sortName", SortOrder.Name, SortOrder.NameDesc, true));
add(getSortLink("sortCreated", SortOrder.Created, SortOrder.CreatedDesc, true));
add(getSortLink("sortSize", SortOrder.Size, SortOrder.SizeDesc, false));
add(getSortLink("sortType", SortOrder.MimeType, SortOrder.MimeTypeDesc, false));
add(getSortLink("sortUser", SortOrder.User, SortOrder.UserDesc, false));
add(new FeedbackPanel("feedBack"));
}
/**
* Get the choices performed by the user with the component
* @return
*/
public List<FileDescription> getChoices(){
return model.getObject();
}
private IndicatingAjaxFallbackLink<Void> getSortLink(final String id, final SortOrder sort, final SortOrder sortReversed, final boolean reloadFolders) {
IndicatingAjaxFallbackLink<Void> result = new IndicatingAjaxFallbackLink<Void>(id){
private static final long serialVersionUID = 1L;
@Override
public void onClick(AjaxRequestTarget target) {
if(sortOrder == sort)
sortOrder = sortReversed;
else
sortOrder = sort;
if(reloadFolders){
reloadFolders();
if(target != null)
target.addComponent(listFolders);
}
reloadFiles();
if(target != null)
target.addComponent(listFiles);
}
};
return result;
}
private void reloadSelected(){
listSelected.removeAll();
if(maxSelections > 1){
@ -174,18 +241,16 @@ public class FileChooser extends Panel {
upLinkContainer.add(upLink);
listFolders.removeAll();
List<String> items = fileRepository.searchFolders(currentAbsolutePath);
Collections.sort(items, new Comparator<String> () {
public int compare(String arg0, String arg1) {
return arg0.compareTo(arg1);
}
});
List<FolderDescription> items = fileRepository.searchFolders(currentAbsolutePath);
fileRepository.sortFolderDescriptions(items, sortOrder);
RepeatingView contents = new RepeatingView("content");
listFolders.add(contents);
for (final String folderName : items) {
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
for (final FolderDescription folderDescription : items) {
WebMarkupContainer inner = new WebMarkupContainer(contents.newChildId());
final String newAbsolutePath = currentAbsolutePath+folderName+"/";;
final String newAbsolutePath = currentAbsolutePath+folderDescription.getName()+"/";;
IndicatingAjaxFallbackLink<Void> link = new IndicatingAjaxFallbackLink<Void>("folderLink"){
private static final long serialVersionUID = 1L;
@ -203,8 +268,9 @@ public class FileChooser extends Panel {
}
};
link.add(new Label("name", folderName));
link.add(new Label("name", folderDescription.getName()));
inner.add(link);
inner.add(new Label("created", df.format(folderDescription.getCreated())));
contents.add(inner);
}
}
@ -213,13 +279,9 @@ public class FileChooser extends Panel {
private void reloadFiles() {
listFiles.removeAll();
List<FileDescription> items = fileRepository.searchFiles(currentAbsolutePath);
Collections.sort(items, new Comparator<FileDescription> () {
public int compare(FileDescription o1, FileDescription o2) {
return o2.getLastModified().compareTo(o1.getLastModified());
}
});
fileRepository.sortFileDescriptions(items, sortOrder);
RepeatingView contents = new RepeatingView("content");
listFiles.add(contents);
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@ -240,8 +302,11 @@ public class FileChooser extends Panel {
inner.add(new Label("size", fileRepository.formatBytes(desc.getSize())));
inner.add(new Label("mimeType", desc.getMimeType()));
String userId = "";
if(desc.getUserId() != null)
userId = desc.getUserId().toString();
if(desc.getUserId() != null){
User user = userDao.load(desc.getUserId());
if(user != null)
userId = user.toString();
}
inner.add(new Label("userId", userId));
IndicatingAjaxFallbackLink<Void> select = new IndicatingAjaxFallbackLink<Void>("select") {
private static final long serialVersionUID = 1L;

@ -8,7 +8,9 @@
</head>
<body>
<span wicket:id="projectFilePanel"></span>
<wicket:extend>
<div wicket:id="projectFilePanel"></div>
</wicket:extend>
</body>
</html>

@ -5,17 +5,18 @@ import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
import se.su.dsv.scipro.basepages.BasePage;
import se.su.dsv.scipro.basepages.MenuPage;
import se.su.dsv.scipro.data.dataobjects.Project;
import se.su.dsv.scipro.repository.FilePanelContainer;
import se.su.dsv.scipro.repository.components.FileChooser;
import se.su.dsv.scipro.repository.panels.ProjectFilePanel;
public class ProjectFilePage extends BasePage implements FilePanelContainer {
public class ProjectFilePage extends MenuPage implements FilePanelContainer {
public ProjectFilePage(PageParameters pp) {
super(pp);
add(new ProjectFilePanel("projectFilePanel", pp, this));
}
@Override

@ -8,7 +8,9 @@
</head>
<body>
<span wicket:id="sysAdminFilePanel"></span>
<wicket:extend>
<div wicket:id="sysAdminFilePanel"></div>
</wicket:extend>
</body>
</html>

@ -5,15 +5,17 @@ import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
import se.su.dsv.scipro.basepages.BasePage;
import se.su.dsv.scipro.basepages.MenuPage;
import se.su.dsv.scipro.repository.FilePanelContainer;
import se.su.dsv.scipro.repository.panels.SysAdminFilePanel;
public class SysAdminFilePage extends BasePage implements FilePanelContainer {
public class SysAdminFilePage extends MenuPage implements FilePanelContainer {
public SysAdminFilePage(PageParameters pp) {
super(pp);
add(new SysAdminFilePanel("sysAdminFilePanel", pp, this));
}
@Override

@ -9,58 +9,76 @@
<body>
<wicket:panel>
<div><span wicket:id="feedbackPanel">[Feedback goes here]</span></div>
<form wicket:id="ajax-simpleUpload">
<div><span wicket:id="feedbackPanel">[Feedback goes here]</span></div>
<form wicket:id="ajax-simpleUpload">
<p><label>Standard file upload</label> <input wicket:id="fileInput"
id="fileInput" type="file" /></p>
<p><label>Standard file upload</label> <input wicket:id="fileInput"
id="fileInput" type="file" /></p>
<span wicket:id="progress">[[ajax upload progressbar]]</span>
<p><input type="submit" value="Upload!" name="upload" /></p>
</form>
<div wicket:id="progress">[[ajax upload progressbar]]</div>
<p><input type="submit" value="Upload!" name="upload" /></p>
</form>
<!--<span wicket:id="multiUpload"></span>-->
<!--<span wicket:id="multiUpload"></span>-->
<form wicket:id="folderCreatonForm">
<form wicket:id="folderCreatonForm">
<p><label>Create folder:</label> <input
wicket:id="folderName" type="text" /></p>
<p><label"></label> <input type="submit" value="Create folder"
name="CreateFolder" /></p>
</form>
<p><label>Create folder:</label> <input wicket:id="folderName"
type="text" /></p>
<p><input type="submit" value="Create folder" name="CreateFolder" /></p>
</form>
<p><a href="#" wicket:id="up">..</a></p>
<div wicket:id="listFolders">
<table>
<tr wicket:id="content">
<td style="width: 20px"><a href="delete" wicket:id="delete"><span
wicket:id="deleteIcon" style="border: 1px;" /></a></td>
<td style="width: 420px"><a href="#" wicket:id="link"><span
wicket:id="name">name</span></a></td>
</tr>
</table>
</div>
<table>
<thead>
<tr>
<th></th>
<th><a href=# wicket:id="sortName">Name</a></th>
<th><a href=# wicket:id="sortCreated">Created</a></th>
<th><a href=# wicket:id="sortSize">Size</a></th>
<th><a href=# wicket:id="sortType">Content Type</a></th>
<th><!--Identifier--></th>
<th><a href=# wicket:id="sortUserId">User</a></th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td><a href="#" wicket:id="up">[..]</a></td>
</tr>
</tbody>
<tbody wicket:id="listFolders">
<div wicket:id="listFiles">
<table>
<tr wicket:id="content">
<td style="width: 20px"><a href="delete" wicket:id="delete"><span
wicket:id="deleteIcon" style="border: 1px;" /></a></td>
<td style="width: 120px"><span wicket:id="size">name</span></td>
<td style="width: 220px"><span wicket:id="modified">name</span></td>
<td style="width: 420px"><span wicket:id="name">name</span></td>
<td><span wicket:id="mimeType">mimeType</span></td>
<td><span wicket:id="uuid">uuid</span></td>
<td><span wicket:id="userId">userId</span></td>
<td><a href="#" wicket:id="preview">Preview</a></td>
<td style="width: 420px"><a href="#" wicket:id="download">Download</a></td>
</tr>
</table>
</div>
<tr wicket:id="content">
<td><a href="delete" wicket:id="delete"><span
wicket:id="deleteIcon" /></a></td>
<td><a href="#" wicket:id="link"><span wicket:id="name">name</span></a></td>
<td><span wicket:id="created"></span></td>
</tr>
</tbody>
<tbody wicket:id="listFiles">
<tr wicket:id="content">
<td><a href="delete" wicket:id="delete"><span
wicket:id="deleteIcon" /></a></td>
<td><span wicket:id="name">name</span></td>
<td><span wicket:id="modified">modified</span></td>
<td><span wicket:id="size">size</span></td>
<td><span wicket:id="mimeType">mimeType</span></td>
<td><span wicket:id="uuid">uuid</span></td>
<td><span wicket:id="userId">userId</span></td>
<td><a href="#" wicket:id="open">Open</a></td>
<td><a href="#" wicket:id="download">Download</a></td>
</tr>
</tbody>
</table>
</wicket:panel>
</body>
</html>

@ -2,8 +2,6 @@ package se.su.dsv.scipro.repository.panels;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import org.apache.commons.lang.StringUtils;
@ -30,14 +28,22 @@ import org.apache.wicket.spring.injection.annot.SpringBean;
import org.apache.wicket.util.lang.Bytes;
import org.apache.wicket.util.resource.IResourceStream;
import se.su.dsv.scipro.data.dao.interfaces.UserDao;
import se.su.dsv.scipro.data.dataobjects.User;
import se.su.dsv.scipro.repository.FileDescription;
import se.su.dsv.scipro.repository.FilePanelContainer;
import se.su.dsv.scipro.repository.FileRepository;
import se.su.dsv.scipro.repository.FolderDescription;
import se.su.dsv.scipro.repository.SortOrder;
import se.su.dsv.scipro.repository.util.FileStorageException;
public abstract class AbstractFilePanel extends Panel {
private static final long serialVersionUID = 7924867289001112027L;
@SpringBean
private UserDao userDao;
/**
* A reference to the page that holds the FilePanel, required to be able to
* link to this page statelessly
@ -70,6 +76,8 @@ public abstract class AbstractFilePanel extends Panel {
* can browse to) and that must not be traversed below, implemented by subclasses
*/
protected abstract String getBasePath();
private SortOrder sortOrder = null;
protected void init(final PageParameters pp) {
this.pp = pp;
@ -80,6 +88,10 @@ public abstract class AbstractFilePanel extends Panel {
relativePath = relativePath.replaceAll("\\.", "/");
absolutePath = absolutePath + relativePath;
}
//Check if the page had a sortorder specified via page parameters
if(pp.containsKey("s")){
sortOrder = pp.getAsEnum("s", SortOrder.class);
}
final FileUploadForm ajaxSimpleUploadForm = new FileUploadForm("ajax-simpleUpload", absolutePath, relativePath);
ajaxSimpleUploadForm.add(new UploadProgressBar("progress", ajaxSimpleUploadForm)); //TODO seems to be broken in some browsers like Chrome
@ -99,7 +111,18 @@ public abstract class AbstractFilePanel extends Panel {
final FolderCreationForm folderForm = new FolderCreationForm("folderCreatonForm", absolutePath, relativePath);
add(folderForm);
/*
* Add sorting on different parameters
*/
add(getSortLink("sortName", pp, sortOrder, SortOrder.Name, SortOrder.NameDesc));
add(getSortLink("sortCreated", pp, sortOrder, SortOrder.Created, SortOrder.CreatedDesc));
add(getSortLink("sortSize", pp, sortOrder, SortOrder.Size, SortOrder.SizeDesc));
add(getSortLink("sortType", pp, sortOrder, SortOrder.MimeType, SortOrder.MimeTypeDesc));
add(getSortLink("sortUserId", pp, sortOrder, SortOrder.User, SortOrder.UserDesc));
/*
* Add markup containers
*/
final WebMarkupContainer listFiles = new WebMarkupContainer("listFiles");
listFiles.setOutputMarkupId(true);
reloadFiles(absolutePath, listFiles);
@ -109,7 +132,7 @@ public abstract class AbstractFilePanel extends Panel {
listFolders.setOutputMarkupId(true);
reloadFolder(absolutePath, relativePath, listFolders);
add(listFolders);
boolean atBasePath = getBasePath().equalsIgnoreCase(absolutePath);
int lastSlash = relativePath.lastIndexOf("/");
if (lastSlash > 0)
@ -118,35 +141,50 @@ public abstract class AbstractFilePanel extends Panel {
pp.put("i", "");
add ((new BookmarkablePageLink<Void> ("up", fpc.getSurroundingPageClass(), pp)).setVisible(!atBasePath));
}
}
private BookmarkablePageLink<Void> getSortLink(String id, PageParameters pp, SortOrder current, SortOrder sortOn, SortOrder sortOnReversed){
PageParameters linkPP = (PageParameters) pp.clone();
if(current == sortOn)
linkPP.put("s", sortOnReversed);
else
linkPP.put("s", sortOn);
BookmarkablePageLink<Void> sortLink = new BookmarkablePageLink<Void>(id, fpc.getSurroundingPageClass(), linkPP);
return sortLink;
}
private void reloadFolder(final String absolutePath, final String relativePath, final WebMarkupContainer listFolders) {
listFolders.removeAll();
List<String> items = fileRepository.searchFolders(absolutePath);
Collections.sort(items, new Comparator<String> () {
public int compare(String arg0, String arg1) {
return arg0.compareTo(arg1);
}
});
List<FolderDescription> items = fileRepository.searchFolders(absolutePath);
// Collections.sort(items, new Comparator<FolderDescription> () {
//
// public int compare(FolderDescription arg0, FolderDescription arg1) {
// return arg0.compareTo(arg1);
// }
// });
fileRepository.sortFolderDescriptions(items, sortOrder);
RepeatingView contents = new RepeatingView("content");
listFolders.add(contents);
for (final String folderName : items) {
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
for (final FolderDescription folderDescription : items) {
WebMarkupContainer inner = new WebMarkupContainer(contents.newChildId());
final String linkPath = relativePath + ((!StringUtils.isEmpty(relativePath))?"/":"") + folderName;
final String linkPath = relativePath + ((!StringUtils.isEmpty(relativePath))?"/":"") + folderDescription.getName();
pp.put("i", linkPath.replaceAll ("/", "."));
BookmarkablePageLink<Void> link = new BookmarkablePageLink<Void>("link", fpc.getSurroundingPageClass(), pp);
link.add(new Label("name", folderName));
link.add(new Label("name", folderDescription.getName()));
inner.add(link);
inner.add(new Label("created", df.format(folderDescription.getCreated())));
AjaxFallbackLink<Void> delete = new AjaxFallbackLink<Void>("delete") {
private static final long serialVersionUID = 1L;
@Override
public void onClick(AjaxRequestTarget target) {
fileRepository.delete("/" + absolutePath + ((!StringUtils.isEmpty(relativePath))?"/":"") + folderName);
fileRepository.delete("/" + absolutePath + ((!StringUtils.isEmpty(relativePath))?"/":"") + folderDescription.getName());
reloadFolder(absolutePath, relativePath, listFolders);
target.addComponent(listFolders);
if(target != null)
target.addComponent(listFolders);
}
};
delete.add(new Label("deleteIcon", "X"));
@ -158,13 +196,19 @@ public abstract class AbstractFilePanel extends Panel {
private void reloadFiles(final String absolutePath, final WebMarkupContainer listFiles) {
listFiles.removeAll();
List<FileDescription> items = fileRepository.searchFiles(absolutePath);
Collections.sort(items, new Comparator<FileDescription> () {
public int compare(FileDescription o1, FileDescription o2) {
return o2.getLastModified().compareTo(o1.getLastModified());
}
});
// if(fileComparator == null)
// Collections.sort(items);
// else
// Collections.sort(items, fileComparator);
//// Collections.sort(items, new Comparator<FileDescription> () {
////
//// public int compare(FileDescription o1, FileDescription o2) {
//// return o2.getLastModified().compareTo(o1.getLastModified());
//// }
////
//// });
fileRepository.sortFileDescriptions(items, sortOrder);
RepeatingView contents = new RepeatingView("content");
listFiles.add(contents);
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@ -182,7 +226,7 @@ public abstract class AbstractFilePanel extends Panel {
new ResourceStreamRequestTarget(stream).setFileName(desc.getName()));
}
});
inner.add(new ResourceLink<Void>("preview", new WebResource(){
inner.add(new ResourceLink<Void>("open", new WebResource(){
private static final long serialVersionUID = 1L;
@Override
@ -194,10 +238,15 @@ public abstract class AbstractFilePanel extends Panel {
inner.add(new Label("modified", df.format(desc.getLastModified())));
inner.add(new Label("size", fileRepository.formatBytes(desc.getSize())));
inner.add(new Label("mimeType", desc.getMimeType()));
inner.add(new Label("uuid", desc.getIdentifier()));
Label uuid = new Label("uuid", desc.getIdentifier());
uuid.setVisible(false);
inner.add(uuid);
String userId = "";
if(desc.getUserId() != null)
userId = desc.getUserId().toString();
if(desc.getUserId() != null){
User user = userDao.load(desc.getUserId());
if(user != null)
userId = user.toString();
}
inner.add(new Label("userId", userId));
AjaxFallbackLink<Void> delete = new AjaxFallbackLink<Void>("delete") {
@ -207,7 +256,8 @@ public abstract class AbstractFilePanel extends Panel {
public void onClick(AjaxRequestTarget target) {
fileRepository.delete(desc.getPath());
reloadFiles(absolutePath, listFiles);
target.addComponent(listFiles);
if(target != null)
target.addComponent(listFiles);
}
};
@ -237,7 +287,16 @@ public abstract class AbstractFilePanel extends Panel {
@Override
protected void onSubmit() {
String uuid = null;
try {
setRedirect(true);
try {
if(folderName.getInput().contains(".")){
error("Character \".\" not allowed");
return;
}
if(folderName.getInput().contains("/")){
error("Character \"/\" not allowed");
return;
}
if(!folderPath.endsWith("/"))
uuid = fileRepository.findOrCreateFolder(folderPath + "/" + folderName.getInput());
else
@ -245,8 +304,7 @@ public abstract class AbstractFilePanel extends Panel {
} catch (FileStorageException e) {
e.printStackTrace();
}
setRedirect(true);
}
if (uuid != null) {
pp.put("i", relativePath.replaceAll("/", "."));
setResponsePage(fpc.getSurroundingPageClass(),pp);
@ -291,5 +349,28 @@ public abstract class AbstractFilePanel extends Panel {
setResponsePage(fpc.getSurroundingPageClass(), pp);
}
}
/*
private class SortOrderLink extends AjaxFallbackLink<Void>{
private FileDescriptionSortOrder fileOrder;
private FolderDescriptionSortOrder folderOrder;
public SortOrderLink(String id, FileDescriptionSortOrder fileOrder, FolderDescriptionSortOrder folderOrder) {
super(id);
this.fileOrder = fileOrder;
this.folderOrder = folderOrder;
}
@Override
public void onClick(AjaxRequestTarget target) {
if(fileSortOrder == fileOrder)
descending = !descending;
fileSortOrder = fileOrder;
//if(folderSortOrder != null && folderSortOrder == folderOrder)
folderSortOrder = folderOrder;
reloadFiles(absolutePath, listFiles);
if(target != null)
target.addComponent(listFiles);
}
}
*/
}

@ -39,7 +39,7 @@ public class RepositoryHelper {
if (result.hasNode(nodeStr)) {
result = result.getNode(nodeStr);
} else {
result = result.addNode(nodeStr);
result = result.addNode(nodeStr, "nt:folder");
}
}
session.save();
@ -90,7 +90,7 @@ public class RepositoryHelper {
* @return
* @throws Exception
*/
public static Node findOrCreateFolder(Session session, String[] path, Node rootNode) throws Exception {
public static synchronized Node findOrCreateFolder(Session session, String[] path, Node rootNode) throws Exception {
Node result = rootNode;
for (int i = 0; i < path.length; i++) {