Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix deletion of selected files in trashbin #30993

Merged
merged 3 commits into from
Jun 8, 2018
Merged

Fix deletion of selected files in trashbin #30993

merged 3 commits into from
Jun 8, 2018

Conversation

sharidas
Copy link
Contributor

@sharidas sharidas commented Apr 3, 2018

When files were selected all, and later
selective files were opted for deletion,
the deletion was not happening. The reason
for this behaviour is filenames are passed
through ajax as seen in ui. Where as that
is not the case. This change helps to fix it.

Signed-off-by: Sujith H [email protected]

Description

The filenames passed in the ajax were the files seen in UI. But that is not the case with trashbin files. This change fixes the issue.

Related Issue

#30942

Motivation and Context

The filenames passed in the ajax were the files seen in UI. But that is not the case with trashbin files. This change fixes the issue.

How Has This Been Tested?

  • Create 2 files. And delete them.
  • Select all and then change the decision to select only one. Delete the file. The file is deleted.
  • The same experiment is repeated with multiple files. And the files were deleted.

Screenshots (if appropriate):

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • All new and existing tests passed.

@sharidas sharidas self-assigned this Apr 3, 2018
@sharidas sharidas requested a review from PVince81 April 3, 2018 13:18
/*
The getSelectedFiles gives the file name as it is seen in UI.
But the fact is filenames are storead as filename.dxxxxx. This
change helps to extract exact filename.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the filenames are stored like this because you can have multiple files in trashbin with the same name from different deletions. we need to use the suffixed name when talking to the server so I doubt that this approach can work correctly

@codecov
Copy link

codecov bot commented Apr 3, 2018

Codecov Report

Merging #30993 into master will not change coverage.
The diff coverage is n/a.

Impacted file tree graph

@@            Coverage Diff            @@
##             master   #30993   +/-   ##
=========================================
  Coverage     62.91%   62.91%           
  Complexity    18424    18424           
=========================================
  Files          1156     1156           
  Lines         69184    69184           
  Branches       1260     1260           
=========================================
  Hits          43527    43527           
  Misses        25288    25288           
  Partials        369      369
Flag Coverage Δ Complexity Δ
#javascript 52.39% <ø> (ø) 0 <ø> (ø) ⬇️
#phpunit 64.12% <ø> (ø) 18424 <ø> (ø) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update b08fce1...c1b1a0c. Read the comment docs.

filesFromAttribute.push(trSelectedFiles[i].getAttribute('data-file'));
}
if (files !== filesFromAttribute) {
files = filesFromAttribute;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@PVince81 This change gives the suffixed name i.e if the file name is a.txt, then the data passed to server will be of the form a.txt.dxxxxxxx. While testing with single and multiple files, I was able to see files getting deleted from trashbin. Also verified files getting deleted from files_trashbin/files. Yes you are right, the issue was caused because suffixed filenames were not passed to the server.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, makes sense.

@PVince81
Copy link
Contributor

PVince81 commented Apr 3, 2018

next up is adjusting unit tests.

you can run them with make test-js-debug and if you need the browser for stepping with a debugger, open "http://localhost:9876/debug.html" (white page) and open the browser console

@phil-davis
Copy link
Contributor

phil-davis commented Apr 4, 2018

Selected delete in trashbin works with this code (manual test).

Selected restore does not work. I expect the same sort of code changes are needed for the code that runs when the "Restore" button is clicked.

(also see recent comment in issue - #30942 (comment) )

@sharidas
Copy link
Contributor Author

sharidas commented Apr 6, 2018

I have updated the change for restore issue. Will be looking into the unit tests.

@phil-davis
Copy link
Contributor

@sharidas webUI tests for this are available. See the 2nd commit in #31024

The 2 new scenarios fail against current master, and pass when your code is included - good.

Please include those tests in this PR. You will need to rebase this PR up to current master (to get the recent webUI test methods that are used). Then cherry-pick that commit c736a07 into this PR and push it up to GitHub.

@phil-davis
Copy link
Contributor

I realized that I can add the test commit myself to this PR, so I have done that.

@phil-davis
Copy link
Contributor

@PVince81 unit tests and webUI acceptance tests have been added here.
Ready for review.

for (var i = 0; i < trSelectedFiles.length; i++) {
filesFromAttribute.push(trSelectedFiles[i].getAttribute('data-file'));
}
if (files !== filesFromAttribute) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure this comparison is accurate as it might be comparing only the pointer reference and not the contents. Please use a clearer approach for this check.

for (var i = 0; i < trSelectedFiles.length; i++) {
filesFromAttribute.push(trSelectedFiles[i].getAttribute('data-file'));
}
if (files !== filesFromAttribute) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

duplicate code from above, please move to common method

@phil-davis
Copy link
Contributor

@PVince81 I refactored that. And also, _onClickDeleteSelected and _onClickRestoreSelected are specifically in the trashbin JS code, and they are only called to work on selected files, so they can always work on the data-file attribute. There is no need to ever do _.pluck(this.getSelectedFiles(), 'name') and so that removes the need for any comparison of the 2 things (that you commented above.

@sharidas
Copy link
Contributor Author

sharidas commented Apr 6, 2018

@phil-davis Even I was having same thought when asked to move the changes to common function. The _pluck(this.getSelectedFiles(), 'name' can be safely removed and no more comparison required.

@@ -171,7 +186,7 @@
};
}
else {
files = _.pluck(this.getSelectedFiles(), 'name');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that I understand this PR better, I'm a bit puzzled that the "name" attribute doesn't contain the combined name because the name displayed in the UI is supposed to be "displayName". Maybe that's another bug or regression.

An alternative and potentially better fix would be to adjust this class' elementToFile() to add another attribute on the object containing the combined name.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did acceptance and JS tests here, and just did a bit of refactoring of the JavaScript code because I thought it looked easy enough and would get this PR finished.

Now that there are classes and attributes and objects to be massaged, I will leave it to someone with real JavaScript coding skills :) @sharidas ?

At least there is a good set of JS unit tests and webUI acceptance tests, so you now easily know if a refactoring breaks some "important" behavior.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The name attribute does contain the compound name (tested on master):
image

and the "data-file" does contain the compound name, so I don't see the difference that the fix brings in regard to the name:
image

@sharidas was there something else ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem happens when user select all and the unselect(s) from the list. In my case I tried select all.

  1. The files I had in the trash were a.txt and b.txt. Now I unselected b.txt. Next tried to delete a.txt. Below is the screenshot where name has only a.txt:
    notworking

  2. Without selecting select all, and if I select specifically a file: a.txt the name becomes:
    working

I guess @PVince81 the second option, right?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, then maybe the selection logic in "apps/files/js/filelist.js" has a general bug and we should rather fix it there instead of working it around in the trashbin list

this will need more debugging in the selection events

@@ -50,6 +50,29 @@ So that I can recover accidentally deleted files/folders in ownCloud
But the file "data.zip" should not be listed in the files page on the webUI
And the folder "simple-folder" should not be listed in the files page on the webUI

Scenario: Select all except for some trashbin files and restore them in a batch
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@phil-davis can you add a case where you delete two entries with the same name ?
basically create a folder "test", then deleted it, then another "test", delete it. they'd appear as two entries.
internally they have names with the timestamp appended (test.dXXXXXXX) but visually they look the same

Copy link
Contributor

@phil-davis phil-davis Apr 6, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That will take more work. We have realized this before, but not yet done code to handle it in webUI tests. At the moment the webUI tests do things to file rows (on file page, favorites page, trashbin...) by finding the row with the matching displayed file name.

On favorites and trashbin you can have multiple files in the list with the same name. Currently we have not made code that lets you refer to "the second file called lorem.txt". And then it needs a way to say you want "the lorem.txt that came from folder f1", and that would look in the hover text on trashbin or favorites to see what the "real" location of the file is (which is something that users can do to distinguish which is the file they want to action).

That is not going to happen overnight. i raised issue #31038

@sharidas
Copy link
Contributor Author

sharidas commented Apr 9, 2018

Searched till 9.1.1 version. And this is broken in version 9.1.1.

@PVince81
Copy link
Contributor

PVince81 commented Apr 9, 2018

so version 9.1.0 was fine ? any changes ? git bisect will tell you

@sharidas
Copy link
Contributor Author

sharidas commented Apr 9, 2018

Didn't bisected further. But I have my new finding as follows:
When the page loads it populates the files based on an ajax request
http://localhost/index.php/apps/files_trashbin/ajax/list.php?dir=%2F&sort=mtime&sortdirection=desc
The return of the list.php https://github.com/owncloud/core/blob/master/apps/files_trashbin/ajax/list.php provides file name without extension. So when exact filenames are getting populated, in the file listed in UI, would also cause not to get the real file name with extension .dxxxx.
Hence I made a change in the master branch locally, to have another field lets say realname. And then just modifying the call to _.pluck() by giving argument as realname. Even that helps solve the issue.
With the code flow I don't suspect the getSelectedFiles() in the filelist.js from trashbin app. I still believe without breaking the code flow, we can introduce a new field, realname which would help the UI know what's the real name of the file in FS and what is the name to display. I will post the PR updated. Which would help to understand what I am trying to convey.

@PVince81
Copy link
Contributor

PVince81 commented Apr 9, 2018

Introducing "realname" is likely just a workaround for the real issue.
I suspect that the real issue is inside of getSelectedFiles() and the selection logic. So while it might work it around here it might defer the issue to a later point.

/**
* Event handler for when selecting/deselecting all files
*/
_onClickSelectAll: function(e) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Override selectAll in trashbin. So The only difference between files/js/filelist.js and this filelist.js is from https://github.com/owncloud/core/pull/30993/files#diff-5016b1abbde02ec31bb639507f64d604R170 to https://github.com/owncloud/core/pull/30993/files#diff-5016b1abbde02ec31bb639507f64d604R176
i.e, addition of line:

this.files[i].name = this.files[i].name + '.d' +
          Math.floor(this.files[i].mtime/1000);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks better, need to find a way to prevent that much code duplication, could be done by introducing a new smaller method that can be overridden

Copy link
Contributor

@PVince81 PVince81 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems we're getting closer and now I understand the actual problem better

name of the files, i.e make the filenames real so that
its appended with '.d' + mtime/1000
*/
this.files[i].name = this.files[i].name + '.d' +
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not good as this would overwrite the existing data structure contents and will cause side effects

you need to make a copy of the file data, only replace the name there, not in the original array

/**
* Event handler for when selecting/deselecting all files
*/
_onClickSelectAll: function(e) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks better, need to find a way to prevent that much code duplication, could be done by introducing a new smaller method that can be overridden

@sharidas sharidas force-pushed the trashbin-fix branch 2 times, most recently from 09af122 to 4e6423b Compare June 7, 2018 16:50
Any change to trashbinFiles will not have any change to this.files
*/
var trashbinFiles = [];
this.files.forEach((v, i) => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have a better way to achieve a copy of this.file update the name or does this look ok? Got this snippet while searching. This change does achieve the goal to not update this.files.

@@ -704,15 +704,16 @@
/**
* Event handler for when selecting/deselecting all files
*/
_onClickSelectAll: function(e) {
_onClickSelectAll: function(e, modifiedFiles) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Beware, the function is called from a jQuery event and I'm not sure whether the second param could have arbitrary values. Please double check.

Please update the JSDoc of the function

Copy link
Contributor

@PVince81 PVince81 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Solution looks great, some small tweak, see comment :-)

PVince81
PVince81 previously approved these changes Jun 8, 2018
@phil-davis
Copy link
Contributor

@PVince81 @sharidas time to merge and backport?
It will be nice to have this little fix in 10.0.9

* Check if there are no arbitrary keys that got into
* modifiedFiles, which can cause irregular behaviours.
*/
if (modifiedFiles && (modifiedFiles.length === this.files.length)) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tried to verify at least the keys in modifiedFiles are same as this.files. Hope this check should be sufficient. If the keys are not same then immediate fall back to this.files is made at https://github.com/owncloud/core/pull/30993/files#diff-dafefd9519924bec4efa9f5af4af8e68R729

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comparing length doesn't guarantee that both arrays aren't the same and this approach looks like a hack

please find a more elegant way to solve this

@PVince81 PVince81 dismissed their stale review June 8, 2018 13:48

many changes, need re-review

sharidas and others added 3 commits June 8, 2018 20:01
The file selection process provides the result
which has file name that doesn't match with the
same in the filesystem. This is with reference
to the trashbin. So lets say user tries to selectall,
the value in this.files doesn't give the name
which can be passed to the ajax request to delete
or undelete for later actions. So the purpose
of this change is to check if the selector is
from trashbin, if so adjust the filename as
filename + '.d' + mtime/1000.

Signed-off-by: Sujith H <[email protected]>
@sharidas
Copy link
Contributor Author

sharidas commented Jun 8, 2018

Backport PR: #31700

Copy link
Contributor

@PVince81 PVince81 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@phil-davis phil-davis merged commit a46b5e6 into master Jun 8, 2018
@phil-davis phil-davis deleted the trashbin-fix branch June 8, 2018 15:09
@PVince81 PVince81 modified the milestones: development, QA Jun 13, 2018
@lock
Copy link

lock bot commented Jul 31, 2019

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@lock lock bot locked as resolved and limited conversation to collaborators Jul 31, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants