Procházet zdrojové kódy

Add sorting to files list, trashbin and public files

tags/v7.0.0alpha2
Vincent Petry před 10 roky
rodič
revize
688f6162da

+ 4
- 1
apps/files/ajax/list.php Zobrazit soubor

@@ -17,8 +17,11 @@ $baseUrl = OCP\Util::linkTo('files', 'index.php') . '?dir=';

$permissions = $dirInfo->getPermissions();

$sortAttribute = isset( $_GET['sort'] ) ? $_GET['sort'] : 'name';
$sortDirection = isset( $_GET['sortdirection'] ) ? ($_GET['sortdirection'] === 'desc') : false;

// make filelist
$files = \OCA\Files\Helper::getFiles($dir);
$files = \OCA\Files\Helper::getFiles($dir, $sortAttribute, $sortDirection);

$data['directory'] = $dir;
$data['files'] = \OCA\Files\Helper::formatFileInfos($files);

+ 27
- 9
apps/files/css/files.css Zobrazit soubor

@@ -116,10 +116,29 @@ tr:hover span.extension {

table tr.mouseOver td { background-color:#eee; }
table th { height:24px; padding:0 8px; color:#999; }
table th .name {
position: absolute;
left: 55px;
top: 15px;
table th .columntitle {
display: inline-block;
padding: 15px;
width: 100%;
height: 50px;
box-sizing: border-box;
-moz-box-sizing: border-box;
vertical-align: middle;
}
table th .columntitle.name {
padding-left: 5px;
margin-left: 50px;
max-width: 300px;
}
/* hover effect on sortable column */
table th a.columntitle:hover {
background-color: #F0F0F0;
}
table th .sort-indicator {
width: 10px;
height: 8px;
margin-left: 10px;
display: inline-block;
}
table th, table td { border-bottom:1px solid #ddd; text-align:left; font-weight:normal; }
table td {
@@ -139,8 +158,11 @@ table th#headerName {
}
table th#headerSize, table td.filesize {
min-width: 48px;
padding: 0 16px;
text-align: right;
padding: 0;
}
table table td.filesize {
padding: 0 16px;
}
table th#headerDate, table td.date {
-moz-box-sizing: border-box;
@@ -197,10 +219,6 @@ table td.filename input.filename {
table td.filename a, table td.login, table td.logout, table td.download, table td.upload, table td.create, table td.delete { padding:3px 8px 8px 3px; }
table td.filename .nametext, .uploadtext, .modified { float:left; padding:14px 0; }

#modified {
position: absolute;
top: 15px;
}
.modified {
position: relative;
padding-left: 8px;

+ 120
- 19
apps/files/js/filelist.js Zobrazit soubor

@@ -11,6 +11,9 @@
/* global OC, t, n, FileList, FileActions, Files, FileSummary, BreadCrumb */
/* global dragOptions, folderDropOptions */
window.FileList = {
SORT_INDICATOR_ASC_CLASS: 'icon-triangle-s',
SORT_INDICATOR_DESC_CLASS: 'icon-triangle-n',

appName: t('files', 'Files'),
isEmpty: true,
useUndo:true,
@@ -45,18 +48,19 @@ window.FileList = {
_selectionSummary: null,

/**
* Compare two file info objects, sorting by
* folders first, then by name.
* Sort attribute
*/
_fileInfoCompare: function(fileInfo1, fileInfo2) {
if (fileInfo1.type === 'dir' && fileInfo2.type !== 'dir') {
return -1;
}
if (fileInfo1.type !== 'dir' && fileInfo2.type === 'dir') {
return 1;
}
return fileInfo1.name.localeCompare(fileInfo2.name);
},
_sort: 'name',

/**
* Sort direction: 'asc' or 'desc'
*/
_sortDirection: 'asc',

/**
* Sort comparator function for the current sort
*/
_sortComparator: null,

/**
* Initialize the file list and its components
@@ -76,6 +80,10 @@ window.FileList = {

this.fileSummary = this._createSummary();

this._sort = 'name';
this._sortDirection = 'asc';
this._sortComparator = this.Comparators.name;

this.breadcrumb = new BreadCrumb({
onClick: this._onClickBreadCrumb,
onDrop: _.bind(this._onDropOnBreadCrumb, this),
@@ -86,6 +94,8 @@ window.FileList = {

$('#controls').prepend(this.breadcrumb.$el);

this.$el.find('thead th .columntitle').click(_.bind(this._onClickHeader, this));

$(window).resize(function() {
// TODO: debounce this ?
var width = $(this).width();
@@ -236,6 +246,27 @@ window.FileList = {
return false;
},

/**
* Event handler when clicking on a table header
*/
_onClickHeader: function(e) {
var $target = $(e.target);
var sort;
if (!$target.is('a')) {
$target = $target.closest('a');
}
sort = $target.attr('data-sort');
if (sort) {
if (this._sort === sort) {
this.setSort(sort, (this._sortDirection === 'desc')?'asc':'desc');
}
else {
this.setSort(sort, 'asc');
}
this.reload();
}
},

/**
* Event handler when clicking on a bread crumb
*/
@@ -722,6 +753,27 @@ window.FileList = {
}
this.breadcrumb.setDirectory(this.getCurrentDirectory());
},
/**
* Sets the current sorting and refreshes the list
*
* @param sort sort attribute name
* @param direction sort direction, one of "asc" or "desc"
*/
setSort: function(sort, direction) {
var comparator = this.Comparators[sort] || this.Comparators.name;
this._sort = sort;
this._sortDirection = (direction === 'desc')?'desc':'asc';
this._sortComparator = comparator;
if (direction === 'desc') {
this._sortComparator = function(fileInfo1, fileInfo2) {
return -comparator(fileInfo1, fileInfo2);
};
}
this.$el.find('thead th .sort-indicator')
.removeClass(this.SORT_INDICATOR_ASC_CLASS + ' ' + this.SORT_INDICATOR_DESC_CLASS);
this.$el.find('thead th.column-' + sort + ' .sort-indicator')
.addClass(direction === 'desc' ? this.SORT_INDICATOR_DESC_CLASS : this.SORT_INDICATOR_ASC_CLASS);
},
/**
* @brief Reloads the file list using ajax call
*/
@@ -733,7 +785,9 @@ window.FileList = {
FileList._reloadCall = $.ajax({
url: Files.getAjaxUrl('list'),
data: {
dir : $('#dir').val()
dir: $('#dir').val(),
sort: FileList._sort,
sortdirection: FileList._sortDirection
},
error: function(result) {
FileList.reloadCallback(result);
@@ -859,7 +913,7 @@ window.FileList = {
*/
_findInsertionIndex: function(fileData) {
var index = 0;
while (index < this.files.length && this._fileInfoCompare(fileData, this.files[index]) > 0) {
while (index < this.files.length && this._sortComparator(fileData, this.files[index]) > 0) {
index++;
}
return index;
@@ -1218,15 +1272,15 @@ window.FileList = {
updateSelectionSummary: function() {
var summary = this._selectionSummary.summary;
if (summary.totalFiles === 0 && summary.totalDirs === 0) {
$('#headerName span.name').text(t('files','Name'));
$('#headerSize').text(t('files','Size'));
$('#modified').text(t('files','Modified'));
$('#headerName a.name>span:first').text(t('files','Name'));
$('#headerSize a>span:first').text(t('files','Size'));
$('#modified a>span:first').text(t('files','Modified'));
$('table').removeClass('multiselect');
$('.selectedActions').addClass('hidden');
}
else {
$('.selectedActions').removeClass('hidden');
$('#headerSize').text(OC.Util.humanFileSize(summary.totalSize));
$('#headerSize a>span:first').text(OC.Util.humanFileSize(summary.totalSize));
var selection = '';
if (summary.totalDirs > 0) {
selection += n('files', '%n folder', '%n folders', summary.totalDirs);
@@ -1237,8 +1291,8 @@ window.FileList = {
if (summary.totalFiles > 0) {
selection += n('files', '%n file', '%n files', summary.totalFiles);
}
$('#headerName span.name').text(selection);
$('#modified').text('');
$('#headerName a.name>span:first').text(selection);
$('#modified a>span:first').text('');
$('table').addClass('multiselect');
}
},
@@ -1529,6 +1583,7 @@ $(document).ready(function() {
targetDir = parseCurrentDirFromUrl();
}
if (targetDir) {
FileList.setSort('name', 'asc');
FileList.changeDirectory(targetDir, false);
}
};
@@ -1542,3 +1597,49 @@ $(document).ready(function() {
}, 0);
});

/**
* Sort comparators.
*/
FileList.Comparators = {
/**
* Compares two file infos by name, making directories appear
* first.
*
* @param fileInfo1 file info
* @param fileInfo2 file info
* @return -1 if the first file must appear before the second one,
* 0 if they are identify, 1 otherwise.
*/
name: function(fileInfo1, fileInfo2) {
if (fileInfo1.type === 'dir' && fileInfo2.type !== 'dir') {
return -1;
}
if (fileInfo1.type !== 'dir' && fileInfo2.type === 'dir') {
return 1;
}
return fileInfo1.name.localeCompare(fileInfo2.name);
},
/**
* Compares two file infos by size.
*
* @param fileInfo1 file info
* @param fileInfo2 file info
* @return -1 if the first file must appear before the second one,
* 0 if they are identify, 1 otherwise.
*/
size: function(fileInfo1, fileInfo2) {
return fileInfo1.size - fileInfo2.size;
},
/**
* Compares two file infos by timestamp.
*
* @param fileInfo1 file info
* @param fileInfo2 file info
* @return -1 if the first file must appear before the second one,
* 0 if they are identify, 1 otherwise.
*/
mtime: function(fileInfo1, fileInfo2) {
return fileInfo1.mtime - fileInfo2.mtime;
}
};


+ 52
- 3
apps/files/lib/helper.php Zobrazit soubor

@@ -69,6 +69,32 @@ class Helper
}
}

/**
* Comparator function to sort files by date
*
* @param \OCP\Files\FileInfo $a file
* @param \OCP\Files\FileInfo $b file
* @return int -1 if $a must come before $b, 1 otherwise
*/
public static function mtimeCmp($a, $b) {
$aTime = $a->getMTime();
$bTime = $b->getMTime();
return $aTime - $bTime;
}

/**
* Comparator function to sort files by size
*
* @param \OCP\Files\FileInfo $a file
* @param \OCP\Files\FileInfo $b file
* @return int -1 if $a must come before $b, 1 otherwise
*/
public static function sizeCmp($a, $b) {
$aSize = $a->getSize();
$bSize = $b->getSize();
return $aSize - $bSize;
}

/**
* Formats the file info to be returned as JSON to the client.
*
@@ -120,12 +146,35 @@ class Helper
* returns it as a sorted array of FileInfo.
*
* @param string $dir path to the directory
* @param string $sortAttribute attribute to sort on
* @param bool $sortDescending true for descending sort, false otherwise
* @return \OCP\Files\FileInfo[] files
*/
public static function getFiles($dir) {
public static function getFiles($dir, $sortAttribute = 'name', $sortDescending = false) {
$content = \OC\Files\Filesystem::getDirectoryContent($dir);

usort($content, array('\OCA\Files\Helper', 'fileCmp'));
return $content;
return self::sortFiles($content, $sortAttribute, $sortDescending);
}

/**
* Sort the given file info array
*
* @param \OCP\Files\FileInfo[] files to sort
* @param string $sortAttribute attribute to sort on
* @param bool $sortDescending true for descending sort, false otherwise
* @return \OCP\Files\FileInfo[] sorted files
*/
public static function sortFiles($files, $sortAttribute = 'name', $sortDescending = false) {
$sortFunc = 'fileCmp';
if ($sortAttribute === 'mtime') {
$sortFunc = 'mtimeCmp';
} else if ($sortAttribute === 'size') {
$sortFunc = 'sizeCmp';
}
usort($files, array('\OCA\Files\Helper', $sortFunc));
if ($sortDescending) {
$files = array_reverse($files);
}
return $files;
}
}

+ 7
- 5
apps/files/templates/index.php Zobrazit soubor

@@ -60,11 +60,11 @@
<table id="filestable" data-allow-public-upload="<?php p($_['publicUploadEnabled'])?>" data-preview-x="36" data-preview-y="36">
<thead>
<tr>
<th class="hidden" id='headerName'>
<th id='headerName' class="hidden column-name">
<div id="headerName-container">
<input type="checkbox" id="select_all" />
<label for="select_all"></label>
<span class="name"><?php p($l->t( 'Name' )); ?></span>
<a class="name sort columntitle" data-sort="name"><span><?php p($l->t( 'Name' )); ?></span><span class="sort-indicator"></span></a>
<span id="selectedActionsList" class="selectedActions">
<?php if($_['allowZipDownload']) : ?>
<a href="" class="download">
@@ -76,9 +76,11 @@
</span>
</div>
</th>
<th class="hidden" id="headerSize"><?php p($l->t('Size')); ?></th>
<th class="hidden" id="headerDate">
<span id="modified"><?php p($l->t( 'Modified' )); ?></span>
<th id="headerSize" class="hidden column-size">
<a class="size sort columntitle" data-sort="size"><span><?php p($l->t('Size')); ?></span><span class="sort-indicator"></span></a>
</th>
<th id="headerDate" class="hidden column-mtime">
<a id="modified" class="columntitle" data-sort="mtime"><span><?php p($l->t( 'Modified' )); ?></span><span class="sort-indicator"></span></a>
<?php if ($_['permissions'] & OCP\PERMISSION_DELETE): ?>
<span class="selectedActions"><a href="" class="delete-selected">
<?php p($l->t('Delete'))?>

+ 150
- 7
apps/files/tests/js/filelistSpec.js Zobrazit soubor

@@ -77,13 +77,17 @@ describe('FileList tests', function() {
// dummy table
// TODO: at some point this will be rendered by the FileList class itself!
'<table id="filestable">' +
'<thead><tr><th id="headerName" class="hidden">' +
'<thead><tr>' +
'<th id="headerName" class="hidden column-name">' +
'<input type="checkbox" id="select_all">' +
'<span class="name">Name</span>' +
'<a class="name columntitle" data-sort="name"><span>Name</span><span class="sort-indicator"></span></a>' +
'<span class="selectedActions hidden">' +
'<a href class="download">Download</a>' +
'<a href class="delete-selected">Delete</a></span>' +
'</th></tr></thead>' +
'</th>' +
'<th class="hidden column-size"><a class="columntitle" data-sort="size"><span class="sort-indicator"></span></a></th>' +
'<th class="hidden column-mtime"><a class="columntitle" data-sort="mtime"><span class="sort-indicator"></span></a></th>' +
'</tr></thead>' +
'<tbody id="fileList"></tbody>' +
'<tfoot></tfoot>' +
'</table>' +
@@ -926,7 +930,7 @@ describe('FileList tests', function() {
expect(fakeServer.requests.length).toEqual(1);
var url = fakeServer.requests[0].url;
var query = url.substr(url.indexOf('?') + 1);
expect(OC.parseQueryString(query)).toEqual({'dir': '/subdir'});
expect(OC.parseQueryString(query)).toEqual({'dir': '/subdir', sort: 'name', sortdirection: 'asc'});
fakeServer.respond();
expect($('#fileList tr').length).toEqual(4);
expect(FileList.findFileEl('One.txt').length).toEqual(1);
@@ -937,7 +941,7 @@ describe('FileList tests', function() {
expect(fakeServer.requests.length).toEqual(1);
var url = fakeServer.requests[0].url;
var query = url.substr(url.indexOf('?') + 1);
expect(OC.parseQueryString(query)).toEqual({'dir': '/anothersubdir'});
expect(OC.parseQueryString(query)).toEqual({'dir': '/anothersubdir', sort: 'name', sortdirection: 'asc'});
fakeServer.respond();
});
it('switches to root dir when current directory does not exist', function() {
@@ -1246,7 +1250,7 @@ describe('FileList tests', function() {
expect(_.pluck(FileList.getSelectedFiles(), 'name').length).toEqual(42);
});
it('Selecting files updates selection summary', function() {
var $summary = $('#headerName span.name');
var $summary = $('#headerName a.name>span:first');
expect($summary.text()).toEqual('Name');
FileList.findFileEl('One.txt').find('input:checkbox').click();
FileList.findFileEl('Three.pdf').find('input:checkbox').click();
@@ -1254,7 +1258,7 @@ describe('FileList tests', function() {
expect($summary.text()).toEqual('1 folder & 2 files');
});
it('Unselecting files hides selection summary', function() {
var $summary = $('#headerName span.name');
var $summary = $('#headerName a.name>span:first');
FileList.findFileEl('One.txt').find('input:checkbox').click().click();
expect($summary.text()).toEqual('Name');
});
@@ -1418,4 +1422,143 @@ describe('FileList tests', function() {
});
});
});
describe('Sorting files', function() {
it('Sorts by name by default', function() {
FileList.reload();
expect(fakeServer.requests.length).toEqual(1);
var url = fakeServer.requests[0].url;
var query = OC.parseQueryString(url.substr(url.indexOf('?') + 1));
expect(query.sort).toEqual('name');
expect(query.sortdirection).toEqual('asc');
});
it('Reloads file list with a different sort when clicking on column header of unsorted column', function() {
FileList.$el.find('.column-size .columntitle').click();
expect(fakeServer.requests.length).toEqual(1);
var url = fakeServer.requests[0].url;
var query = OC.parseQueryString(url.substr(url.indexOf('?') + 1));
expect(query.sort).toEqual('size');
expect(query.sortdirection).toEqual('asc');
});
it('Toggles sort direction when clicking on already sorted column', function() {
FileList.$el.find('.column-name .columntitle').click();
expect(fakeServer.requests.length).toEqual(1);
var url = fakeServer.requests[0].url;
var query = OC.parseQueryString(url.substr(url.indexOf('?') + 1));
expect(query.sort).toEqual('name');
expect(query.sortdirection).toEqual('desc');
});
it('Toggles the sort indicator when clicking on a column header', function() {
var ASC_CLASS = FileList.SORT_INDICATOR_ASC_CLASS;
var DESC_CLASS = FileList.SORT_INDICATOR_DESC_CLASS;
FileList.$el.find('.column-size .columntitle').click();
// moves triangle to size column
expect(
FileList.$el.find('.column-name .sort-indicator').hasClass(ASC_CLASS + ' ' + DESC_CLASS)
).toEqual(false);
expect(
FileList.$el.find('.column-size .sort-indicator').hasClass(ASC_CLASS)
).toEqual(true);

// click again on size column, reverses direction
FileList.$el.find('.column-size .columntitle').click();
expect(
FileList.$el.find('.column-size .sort-indicator').hasClass(DESC_CLASS)
).toEqual(true);

// click again on size column, reverses direction
FileList.$el.find('.column-size .columntitle').click();
expect(
FileList.$el.find('.column-size .sort-indicator').hasClass(ASC_CLASS)
).toEqual(true);

// click on mtime column, moves indicator there
FileList.$el.find('.column-mtime .columntitle').click();
expect(
FileList.$el.find('.column-size .sort-indicator').hasClass(ASC_CLASS + ' ' + DESC_CLASS)
).toEqual(false);
expect(
FileList.$el.find('.column-mtime .sort-indicator').hasClass(ASC_CLASS)
).toEqual(true);
});
it('Uses correct sort comparator when inserting files', function() {
testFiles.sort(FileList.Comparators.size);
// this will make it reload the testFiles with the correct sorting
FileList.$el.find('.column-size .columntitle').click();
expect(fakeServer.requests.length).toEqual(1);
fakeServer.requests[0].respond(
200,
{ 'Content-Type': 'application/json' },
JSON.stringify({
status: 'success',
data: {
files: testFiles,
permissions: 31
}
})
);
var newFileData = {
id: 999,
type: 'file',
name: 'new file.txt',
mimetype: 'text/plain',
size: 40001,
etag: '999'
};
FileList.add(newFileData);
expect(FileList.files.length).toEqual(5);
expect(FileList.$fileList.find('tr').length).toEqual(5);
expect(FileList.findFileEl('One.txt').index()).toEqual(0);
expect(FileList.findFileEl('somedir').index()).toEqual(1);
expect(FileList.findFileEl('Two.jpg').index()).toEqual(2);
expect(FileList.findFileEl('new file.txt').index()).toEqual(3);
expect(FileList.findFileEl('Three.pdf').index()).toEqual(4);
});
it('Uses correct reversed sort comparator when inserting files', function() {
testFiles.sort(FileList.Comparators.size);
testFiles.reverse();
// this will make it reload the testFiles with the correct sorting
FileList.$el.find('.column-size .columntitle').click();
expect(fakeServer.requests.length).toEqual(1);
fakeServer.requests[0].respond(
200,
{ 'Content-Type': 'application/json' },
JSON.stringify({
status: 'success',
data: {
files: testFiles,
permissions: 31
}
})
);
// reverse sort
FileList.$el.find('.column-size .columntitle').click();
fakeServer.requests[1].respond(
200,
{ 'Content-Type': 'application/json' },
JSON.stringify({
status: 'success',
data: {
files: testFiles,
permissions: 31
}
})
);
var newFileData = {
id: 999,
type: 'file',
name: 'new file.txt',
mimetype: 'text/plain',
size: 40001,
etag: '999'
};
FileList.add(newFileData);
expect(FileList.files.length).toEqual(5);
expect(FileList.$fileList.find('tr').length).toEqual(5);
expect(FileList.findFileEl('One.txt').index()).toEqual(4);
expect(FileList.findFileEl('somedir').index()).toEqual(3);
expect(FileList.findFileEl('Two.jpg').index()).toEqual(2);
expect(FileList.findFileEl('new file.txt').index()).toEqual(1);
expect(FileList.findFileEl('Three.pdf').index()).toEqual(0);
});
});
});

+ 4
- 1
apps/files_sharing/ajax/list.php Zobrazit soubor

@@ -47,6 +47,9 @@ if (isset($_GET['dir'])) {
$relativePath = $_GET['dir'];
}

$sortAttribute = isset( $_GET['sort'] ) ? $_GET['sort'] : 'name';
$sortDirection = isset( $_GET['sortdirection'] ) ? ($_GET['sortdirection'] === 'desc') : false;

$data = \OCA\Files_Sharing\Helper::setupFromToken($token, $relativePath, $password);

$linkItem = $data['linkItem'];
@@ -64,7 +67,7 @@ $data = array();
$baseUrl = OCP\Util::linkTo('files_sharing', 'index.php') . '?t=' . urlencode($token) . '&dir=';

// make filelist
$files = \OCA\Files\Helper::getFiles($dir);
$files = \OCA\Files\Helper::getFiles($dir, $sortAttribute, $sortDirection);

$formattedFiles = array();
foreach ($files as $file) {

+ 3
- 1
apps/files_trashbin/ajax/list.php Zobrazit soubor

@@ -4,11 +4,13 @@ OCP\JSON::checkLoggedIn();

// Load the files
$dir = isset( $_GET['dir'] ) ? $_GET['dir'] : '';
$sortAttribute = isset( $_GET['sort'] ) ? $_GET['sort'] : 'name';
$sortDirection = isset( $_GET['sortdirection'] ) ? ($_GET['sortdirection'] === 'desc') : false;
$data = array();

// make filelist
try {
$files = \OCA\Files_Trashbin\Helper::getTrashFiles($dir);
$files = \OCA\Files_Trashbin\Helper::getTrashFiles($dir, $sortAttribute, $sortDirection);
} catch (Exception $e) {
header("HTTP/1.0 404 Not Found");
exit();

+ 7
- 3
apps/files_trashbin/lib/helper.php Zobrazit soubor

@@ -8,11 +8,14 @@ class Helper
{
/**
* Retrieves the contents of a trash bin directory.
*
* @param string $dir path to the directory inside the trashbin
* or empty to retrieve the root of the trashbin
* @param string $sortAttribute attribute to sort on or empty to disable sorting
* @param bool $sortDescending true for descending sort, false otherwise
* @return \OCP\Files\FileInfo[]
*/
public static function getTrashFiles($dir){
public static function getTrashFiles($dir, $sortAttribute = '', $sortDescending = false){
$result = array();
$timestamp = null;
$user = \OCP\User::getUser();
@@ -57,8 +60,9 @@ class Helper
closedir($dirContent);
}

usort($result, array('\OCA\Files\Helper', 'fileCmp'));

if ($sortAttribute !== '') {
return \OCA\Files\Helper::sortFiles($result, $sortAttribute, $sortDescending);
}
return $result;
}


+ 8
- 8
apps/files_trashbin/templates/index.php Zobrazit soubor

@@ -12,22 +12,22 @@
<table id="filestable">
<thead>
<tr>
<th id='headerName'>
<th id='headerName' class="hidden column-name">
<div id="headerName-container">
<input type="checkbox" id="select_all" />
<label for="select_all"></label>
<span class='name'><?php p($l->t( 'Name' )); ?></span>
<span class='selectedActions'>
<input type="checkbox" id="select_all" />
<label for="select_all"></label>
<a class="name sort columntitle" data-sort="name"><span><?php p($l->t( 'Name' )); ?></span><span class="sort-indicator"></span></a>
<span id="selectedActionsList" class='selectedActions'>
<a href="" class="undelete">
<img class="svg" alt="<?php p($l->t( 'Restore' )); ?>"
src="<?php print_unescaped(OCP\image_path("core", "actions/history.svg")); ?>" />
<?php p($l->t('Restore'))?>
</a>
</span>
</span>
</div>
</th>
<th id="headerDate">
<span id="modified"><?php p($l->t( 'Deleted' )); ?></span>
<th id="headerDate" class="hidden column-mtime">
<a id="modified" class="columntitle" data-sort="mtime"><span><?php p($l->t( 'Deleted' )); ?></span><span class="sort-indicator"></span></a>
<span class="selectedActions">
<a href="" class="delete-selected">
<?php p($l->t('Delete'))?>

Načítá se…
Zrušit
Uložit