Skip to content

Commit

Permalink
Merge pull request #1972 from owncloud/default-sort
Browse files Browse the repository at this point in the history
Add default client side sort
  • Loading branch information
Lukas Hirt authored Sep 19, 2019
2 parents 3823838 + 3879e1d commit a3b0d4a
Show file tree
Hide file tree
Showing 6 changed files with 153 additions and 5 deletions.
66 changes: 66 additions & 0 deletions apps/files/src/fileSortFunctions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/**
* Compare two strings to provide a natural sort
* @param a first string to compare
* @param b second string to compare
* @return -1 if b comes before a, 1 if a comes before b
* or 0 if the strings are identical
*/
function _chunkify (t) {
// Adapted from http://my.opera.com/GreyWyvern/blog/show.dml/1671288
const tz = []; let x = 0; let y = -1; let n = 0; let c

while (x < t.length) {
c = t.charAt(x)
// only include the dot in strings
const m = ((!n && c === '.') || (c >= '0' && c <= '9'))
if (m !== n) {
// next chunk
y++
tz[y] = ''
n = m
}
tz[y] += c
x++
}
return tz
}

function _naturalSortCompare (a, b) {
const aa = _chunkify(a)
const bb = _chunkify(b)
let x, aNum, bNum

for (x = 0; aa[x] && bb[x]; x++) {
if (aa[x] !== bb[x]) {
aNum = Number(aa[x])
bNum = Number(bb[x])
// note: == is correct here
// eslint-disable-next-line eqeqeq
if (aNum == aa[x] && bNum == bb[x]) {
return aNum - bNum
} else {
// Forcing 'en' locale to match the server-side locale which is
// always 'en'.
//
// Note: This setting isn't supported by all browsers but for the ones
// that do there will be more consistency between client-server sorting
return aa[x].localeCompare(bb[x], 'en')
}
}
}
return aa.length - bb.length
}

function name (fileInfo1, fileInfo2) {
if (fileInfo1.type === 'folder' && fileInfo2.type !== 'folder') {
return -1
}
if (fileInfo1.type !== 'folder' && fileInfo2.type === 'folder') {
return 1
}
return _naturalSortCompare(fileInfo1.name, fileInfo2.name)
}

export const fileSortFunctions = {
name
}
7 changes: 3 additions & 4 deletions apps/files/src/store/getters.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { fileSortFunctions } from '../fileSortFunctions.js'

export default {
inProgress: state => {
return state.inProgress
Expand Down Expand Up @@ -42,10 +44,7 @@ export default {
}
// respect filename filter for local 'search' in open folder
return !(state.searchTermFilter && !file.name.toLowerCase().includes(state.searchTermFilter.toLowerCase()))
}).sort(function (a, b) {
return a.name.localeCompare(b.name, undefined, { sensitivity: 'base' })
}
)
}).sort(fileSortFunctions[state.fileSortMode])
},
filesTotalSize: (state, getters) => {
let totalSize = 0
Expand Down
1 change: 1 addition & 0 deletions apps/files/src/store/state.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export default {
files: [],
filesSearched: [],
fileFilter: fileFilters,
fileSortMode: 'name',
selected: [],
inProgress: [],
searchTermGlobal: '',
Expand Down
50 changes: 50 additions & 0 deletions tests/acceptance/features/webUIFiles/sort.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
Feature: Filter files/folders

As a user
I would like to sort files/folders
So that I can make the file/folder list more clear

Background:
Given user "user1" has been created with default attributes
And user "user1" has logged in using the webUI
And the user has created folder "test_sort"
And the user has created the following folders
| entry_name |
| test_sort/a |
| test_sort/a 文件 |
| test_sort/10 |
| test_sort/1 |
| test_sort/2 |
| test_sort/z |
And the user has created the following files
| entry_name |
| test_sort/a.txt |
| test_sort/a space.txt |
| test_sort/a space (2).txt |
| test_sort/a space 文件 |
| test_sort/a space 文件夹 |
| test_sort/b1.txt |
| test_sort/b2.txt |
| test_sort/b10.txt |
| test_sort/z.txt |

Scenario: Folders are listed before files alphabetically by default and sorted using natural sort
When the user has browsed to the files page
Then these resources should be listed in the folder "test_sort" on the webUI
| entry_name |
| a |
| a 文件 |
| 1 |
| 2 |
| 10 |
| z |
| a.txt |
| a space.txt |
| a space (2).txt |
| a space 文件 |
| a space 文件夹 |
| b1.txt |
| b2.txt |
| b10.txt |
| z.txt |

19 changes: 18 additions & 1 deletion tests/acceptance/helpers/webdavHelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,23 @@ exports.createFolder = function (user, folderName) {
davPath,
{ method: 'MKCOL', headers: headers }
)
.then(res => httpHelper.checkStatus(res, 'Could not create the folder.'))
.then(res => httpHelper.checkStatus(res, `Could not create the folder "${folderName}" for user "${user}".`))
.then(res => res.text())
}
/**
* Create a file using webDAV api.
*
* @param {string} user
* @param {string} fileName
* @param {string} contents
*/
exports.createFile = function (user, fileName, contents = '') {
const headers = httpHelper.createAuthHeader(user)
const davPath = exports.createDavPath(user, fileName)
return fetch(
davPath,
{ method: 'PUT', headers: headers, body: contents }
)
.then(res => httpHelper.checkStatus(res, `Could not create the file "${fileName}" for user "${user}".`))
.then(res => res.text())
}
15 changes: 15 additions & 0 deletions tests/acceptance/stepDefinitions/filesContext.js
Original file line number Diff line number Diff line change
Expand Up @@ -459,3 +459,18 @@ Then('file/folder {string} should be listed in shared-with-others page on the we
client.page.sharedWithOthersPage().navigateAndWaitTillLoaded()
return client.page.FilesPageElement.filesList().waitForFileVisible(filename)
})
Given('the user has created file {string}', function (fileName) {
return webdav.createFile(client.globals.currentUser, fileName, '')
})
Given('the user has created the following folders', function (entryList) {
entryList.rows().forEach(entry => {
webdav.createFolder(client.globals.currentUser, entry[0])
})
return client
})
Given('the user has created the following files', function (entryList) {
entryList.rows().forEach(entry => {
webdav.createFile(client.globals.currentUser, entry[0])
})
return client
})

0 comments on commit a3b0d4a

Please sign in to comment.