Skip to content

Commit

Permalink
feat: simplify destination handling
Browse files Browse the repository at this point in the history
Signed-off-by: John Molakvoæ <skjnldsv@protonmail.com>
  • Loading branch information
skjnldsv committed Aug 18, 2023
1 parent f914ded commit e783033
Show file tree
Hide file tree
Showing 7 changed files with 395 additions and 193 deletions.
98 changes: 64 additions & 34 deletions cypress/components/UploadPicker.cy.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
// dist file might not be built when running eslint only
// eslint-disable-next-line import/no-unresolved,n/no-missing-import
import { addNewFileMenuEntry } from '@nextcloud/files'
import { Folder, Permission, addNewFileMenuEntry, Entry } from '@nextcloud/files'
import { UploadPicker } from '../../dist/index.js'
import { generateRemoteUrl } from '@nextcloud/router'

describe('UploadPicker rendering', () => {
it('Renders default UploadPicker', () => {
Expand All @@ -13,30 +14,22 @@ describe('UploadPicker rendering', () => {

describe('NewFileMenu handling', () => {
const propsData = {
context: {
basename: 'Folder',
etag: '63071eedd82fe',
fileid: '56',
filename: '/Folder',
hasPreview: false,
lastmod: 1661410576,
mime: 'httpd/unix-directory',
month: '197001',
permissions: 'CKGWDR',
showShared: false,
size: 2610077102,
timestamp: 1661410,
type: 'dir',
},
destination: new Folder({
id: 56,
owner: 'user',
source: generateRemoteUrl('dav/files/user/Folder'),
permissions: Permission.ALL,
root: '/files/user',
}),
}
const entry = {
id: 'empty-file',
displayName: 'Create empty file',
templateName: 'New file',
iconClass: 'icon-file',
if: (fileInfo) => fileInfo.permissions.includes('CK'),
if: (folder: Folder) => (folder.permissions & Permission.CREATE) !== 0,
handler() {},
}
} as Entry

before(() => {
cy.spy(entry, 'handler')
Expand Down Expand Up @@ -86,9 +79,13 @@ describe('NewFileMenu handling', () => {
cy.get('.upload-picker__menu-entry').should('not.be.visible')

cy.get('@component').then((component) => {
component.setContext(
Object.assign({}, propsData.context, { permissions: 'GR' })
)
component.setDestination(new Folder({
id: 56,
owner: 'user',
source: generateRemoteUrl('dav/files/user/Folder'),
permissions: Permission.NONE,
root: '/files/user',
}))
})
cy.get('form .action-item__menutoggle')
.as('menuButton')
Expand All @@ -100,8 +97,20 @@ describe('NewFileMenu handling', () => {

describe('UploadPicker valid uploads', () => {
beforeEach(() => {
// Make sure we reset the destination
// so other tests do not interfere
const propsData = {
destination: new Folder({
id: 56,
owner: 'user',
source: generateRemoteUrl('dav/files/user'),
permissions: Permission.ALL,
root: '/files/user',
}),
}

// Mount picker
cy.mount(UploadPicker).as('uploadPicker')
cy.mount(UploadPicker, { propsData }).as('uploadPicker')

// Check and init aliases
cy.get('form input[type="file"]').as('input').should('exist')
Expand Down Expand Up @@ -196,7 +205,13 @@ describe('UploadPicker valid uploads', () => {

describe('Destination management', () => {
const propsData = {
destination: '/',
destination: new Folder({
id: 56,
owner: 'user',
source: generateRemoteUrl('dav/files/user'),
permissions: Permission.ALL,
root: '/files/user',
}),
}

it('Upload then changes the destination', () => {
Expand Down Expand Up @@ -228,9 +243,15 @@ describe('Destination management', () => {
})

cy.get('@component').then((component) => {
component.setDestination('/Photos')
component.setDestination(new Folder({
id: 56,
owner: 'user',
source: generateRemoteUrl('dav/files/user/Photos'),
permissions: Permission.ALL,
root: '/files/user',
}))
// Wait for prop propagation
expect(component.uploadManager.destination).to.equal('/Photos')
expect(component.uploadManager.root).to.have.string('/remote.php/dav/files/user/Photos')
})

cy.get('@input').attachFile({
Expand All @@ -253,7 +274,13 @@ describe('Destination management', () => {
describe('Root management', () => {
const propsData = {
root: null,
destination: '/',
destination: new Folder({
id: 56,
owner: 'user',
source: generateRemoteUrl('dav/files/user'),
permissions: Permission.ALL,
root: '/files/user',
}),
}

it('Upload then changes the root', () => {
Expand All @@ -280,21 +307,24 @@ describe('Root management', () => {

cy.wait('@upload').then((upload) => {
expect(upload.request.url).to.have.string(
'/remote.php/dav/files/user/image.jpg'
'/remote.php/dav/files/user/image.jpg',
)
})

cy.get('@component').then((component) => {
component.setRoot('dav/photos/admin/albums')
component.setDestination('/2022 Summer Vacations')
component.setDestination(new Folder({
id: 56,
owner: 'user',
source: generateRemoteUrl('dav/photos/user/albums/2022 Summer Vacations'),
permissions: Permission.ALL,
root: '/photos/user',
}))
// Wait for prop propagation
expect(component.uploadManager.root).to.match(
/dav\/photos\/admin\/albums$/i
)
expect(component.uploadManager.root).to.have.string('/remote.php/dav/photos/user/albums/2022 Summer Vacations')
})

// Intercept single upload
cy.intercept('PUT', '/remote.php/dav/photos/admin/albums/*/*', {
cy.intercept('PUT', '/remote.php/dav/photos/user/albums/*/*', {
statusCode: 201,
}).as('upload')

Expand All @@ -309,7 +339,7 @@ describe('Root management', () => {

cy.wait('@upload').then((upload) => {
expect(upload.request.url).to.have.string(
'/remote.php/dav/photos/admin/albums/2022%20Summer%20Vacations/image.jpg'
'/remote.php/dav/photos/user/albums/2022%20Summer%20Vacations/image.jpg',
)
})
})
Expand Down
2 changes: 1 addition & 1 deletion cypress/support/component-index.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<title>Components App</title>

<!-- Nextcloud customizations -->
<link href="https://gitcdn.link/cdn/nextcloud/server/master/apps/theming/css/default.css" rel="stylesheet" />
<link href="https://nextcloud.github.io/server/apps/theming/css/default.css" rel="stylesheet" />
<script type="text/javascript">
window.OC = {
webroot: '',
Expand Down
65 changes: 24 additions & 41 deletions lib/components/UploadPicker.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
class="upload-picker"
data-upload-picker>
<!-- New button -->
<NcButton v-if="newFileMenuEntries.length === 0"
<NcButton v-if="newFileMenuEntries && newFileMenuEntries.length === 0"
:disabled="disabled"
data-upload-picker-add
@click="onClick">
Expand Down Expand Up @@ -72,7 +72,7 @@
</template>

<script>
import { getNewFileMenuEntries } from '@nextcloud/files'
import { getNewFileMenuEntries, Folder } from '@nextcloud/files'
import { getUploader } from '../index.js'
import makeEta from 'simple-eta'
Expand All @@ -91,6 +91,8 @@ import { Status } from '../uploader.js'
import ActionIcon from './ActionIcon.vue'
import logger from '../utils/logger.js'
const uploadManager = getUploader()
export default {
name: 'UploadPicker',
components: {
Expand Down Expand Up @@ -118,15 +120,7 @@ export default {
default: false,
},
destination: {
type: String,
default: null,
},
root: {
type: String,
default: null,
},
context: {
type: Object,
type: Folder,
default: undefined,
},
},
Expand All @@ -140,8 +134,8 @@ export default {
eta: null,
timeLeft: '',
newFileMenuEntries: getNewFileMenuEntries(this.context),
uploadManager: getUploader(),
newFileMenuEntries: [],
uploadManager,
}
},
Expand All @@ -157,7 +151,7 @@ export default {
},
queue() {
return this.uploadManager.queue
return this.uploadManager?.queue
},
hasFailure() {
Expand All @@ -176,12 +170,12 @@ export default {
watch: {
/**
* If the context change, we need to refresh the menu
* If the destination change, we need to refresh the menu
*
* @param {FileInfo} context the current NewFileMenu context
* @param {FileInfo} destination the current NewFileMenu destination
*/
context(context) {
this.setContext(context)
destination(destination) {
this.setDestination(destination)
},
totalQueueSize(size) {
Expand All @@ -194,14 +188,6 @@ export default {
this.updateStatus()
},
destination(destination) {
this.setDestination(destination)
},
root(path) {
this.setRoot(path)
},
queue(queue, oldQueue) {
if (queue.length < oldQueue.length) {
this.$emit('uploaded', oldQueue.filter(upload => !queue.includes(upload)))
Expand All @@ -224,10 +210,11 @@ export default {
},
beforeMount() {
this.setDestination(this.destination)
this.setRoot(this.root)
this.setContext(this.context)
console.log('beforeMount', this.destination)
// Prevent init with wrong destination
if (this.destination) {
this.setDestination(this.destination)
}
logger.debug('UploadPicker initialised')
},
Expand Down Expand Up @@ -287,18 +274,14 @@ export default {
},
setDestination(destination) {
logger.debug(`Destination path set to ${destination}`)
this.uploadManager.destination = destination
},
setRoot(path) {
logger.debug(`Root path set to ${path}`)
this.uploadManager.root = path
},
if (!this.destination) {
logger.debug('Invalid destination')
return
}
setContext(context) {
logger.debug('Context changed to', context)
this.newFileMenuEntries = getNewFileMenuEntries(context)
logger.debug(`Destination set to ${destination}`)
this.uploadManager.destination = destination
this.newFileMenuEntries = getNewFileMenuEntries(destination)
},
},
}
Expand Down
25 changes: 14 additions & 11 deletions lib/upload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,29 +11,33 @@ export enum Status {
}
export class Upload {

private _path: string
private _source: string
private _isChunked: boolean
private _chunks: number

private _size: number
private _uploaded: number = 0
private _startTime: number = 0
private _uploaded = 0
private _startTime = 0

private _status: Status = Status.INITIALIZED
private _controller: AbortController
private _response: AxiosResponse|null = null

constructor(path: string, chunked: boolean = false, size: number) {
constructor(source: string, chunked = false, size: number) {
const chunks = getMaxChunksSize() > 0 ? Math.ceil(size / getMaxChunksSize()) : 1
this._path = path
this._source = source
this._isChunked = chunked && getMaxChunksSize() > 0 && chunks > 1
this._chunks = this._isChunked ? chunks : 1
this._size = size
this._controller = new AbortController()
}

get path(): string {
return this._path
return this._source
}

get source(): string {
return this._source
}

get isChunked(): boolean {
Expand All @@ -48,10 +52,6 @@ export class Upload {
return this._size
}

get uploaded(): number {
return this._uploaded
}

get startTime(): number {
return this._startTime
}
Expand All @@ -60,11 +60,14 @@ export class Upload {
this._response = response
}


get response(): AxiosResponse|null {
return this._response
}

get uploaded(): number {
return this._uploaded
}

/**
* Update the uploaded bytes of this upload
*/
Expand Down
Loading

0 comments on commit e783033

Please sign in to comment.