Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions apps/dav/lib/Connector/Sabre/QuotaPlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,8 @@ public function checkQuota($path, $length = null) {
$parentPath = '';
}
$req = $this->server->httpRequest;

// If chunked upload
if ($req->getHeader('OC-Chunked')) {
$info = \OC_FileChunking::decodeName($newName);
$chunkHandler = $this->getFileChunking($info);
Expand All @@ -202,6 +204,10 @@ public function checkQuota($path, $length = null) {
// use target file name for free space check in case of shared files
$path = rtrim($parentPath, '/') . '/' . $info['name'];
}

// Strip any duplicate slashes
$path = str_replace('//', '/', $path);

$freeSpace = $this->getFreeSpace($path);
if ($freeSpace >= 0 && $length > $freeSpace) {
if (isset($chunkHandler)) {
Expand Down
18 changes: 18 additions & 0 deletions apps/files/src/components/NavigationQuota.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { showError } from '@nextcloud/dialogs'
import { subscribe } from '@nextcloud/event-bus'
import { translate } from '@nextcloud/l10n'
import axios from '@nextcloud/axios'

import ChartPie from 'vue-material-design-icons/ChartPie.vue'
import NcAppNavigationItem from '@nextcloud/vue/dist/Components/NcAppNavigationItem.js'
import NcProgressBar from '@nextcloud/vue/dist/Components/NcProgressBar.js'
Expand Down Expand Up @@ -86,6 +87,13 @@ export default {
subscribe('files:node:updated', this.throttleUpdateStorageStats)
},

mounted() {
// Warn the user if the available storage is 0 on page load
if (this.storageStats?.free <= 0) {
this.showStorageFullWarning()
}
},

methods: {
// From user input
debounceUpdateStorageStats: debounce(200, function(event) {
Expand Down Expand Up @@ -113,6 +121,12 @@ export default {
if (!response?.data?.data) {
throw new Error('Invalid storage stats')
}

// Warn the user if the available storage changed from > 0 to 0
if (this.storageStats?.free > 0 && response.data.data?.free <= 0) {
this.showStorageFullWarning()
}

this.storageStats = response.data.data
} catch (error) {
logger.error('Could not refresh storage stats', { error })
Expand All @@ -125,6 +139,10 @@ export default {
}
},

showStorageFullWarning() {
showError(this.t('files', 'Your storage is full, files can not be updated or synced anymore!'))
},

t: translate,
},
}
Expand Down
65 changes: 64 additions & 1 deletion apps/files/src/views/FilesList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
<!-- Current folder breadcrumbs -->
<BreadCrumbs :path="dir" @reload="fetchContent">
<template #actions>
<!-- Sharing button -->
<NcButton v-if="canShare && filesListWidth >= 512"
:aria-label="shareButtonLabel"
:class="{ 'files-list__header-share-button--shared': shareButtonType }"
Expand All @@ -37,11 +38,27 @@
<ShareVariantIcon v-else :size="20" />
</template>
</NcButton>

<!-- Disabled upload button -->
<NcButton v-if="!canUpload || isQuotaExceeded"
:aria-label="cantUploadLabel"
:title="cantUploadLabel"
class="files-list__header-upload-button--disabled"
:disabled="true"
type="secondary">
<template #icon>
<PlusIcon :size="20" />
</template>
{{ t('files', 'Add') }}
</NcButton>

<!-- Uploader -->
<UploadPicker v-if="currentFolder && canUpload"
<UploadPicker v-else-if="currentFolder"
:content="dirContents"
:destination="currentFolder"
:multiple="true"
class="files-list__header-upload-button"
@failed="onUploadFail"
@uploaded="onUpload" />
</template>
</BreadCrumbs>
Expand Down Expand Up @@ -110,6 +127,8 @@ import { Folder, Node, Permission } from '@nextcloud/files'
import { getCapabilities } from '@nextcloud/capabilities'
import { join, dirname } from 'path'
import { orderBy } from 'natural-orderby'
import { Parser } from 'xml2js'
import { showError } from '@nextcloud/dialogs'
import { translate, translatePlural } from '@nextcloud/l10n'
import { Type } from '@nextcloud/sharing'
import { UploadPicker } from '@nextcloud/upload'
Expand All @@ -122,6 +141,7 @@ import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
import NcEmptyContent from '@nextcloud/vue/dist/Components/NcEmptyContent.js'
import NcIconSvgWrapper from '@nextcloud/vue/dist/Components/NcIconSvgWrapper.js'
import NcLoadingIcon from '@nextcloud/vue/dist/Components/NcLoadingIcon.js'
import PlusIcon from 'vue-material-design-icons/Plus.vue'
import ShareVariantIcon from 'vue-material-design-icons/ShareVariant.vue'
import ViewGridIcon from 'vue-material-design-icons/ViewGrid.vue'

Expand Down Expand Up @@ -155,6 +175,7 @@ export default defineComponent({
NcEmptyContent,
NcIconSvgWrapper,
NcLoadingIcon,
PlusIcon,
ShareVariantIcon,
UploadPicker,
ViewGridIcon,
Expand Down Expand Up @@ -360,6 +381,15 @@ export default defineComponent({
canUpload() {
return this.currentFolder && (this.currentFolder.permissions & Permission.CREATE) !== 0
},
isQuotaExceeded() {
return this.currentFolder?.attributes?.['quota-available-bytes'] === 0
},
cantUploadLabel() {
if (this.isQuotaExceeded) {
return this.t('files', 'Your have used your space quota and cannot upload files anymore')
}
return this.t('files', 'You don’t have permission to upload or create files here')
},

/**
* Check if current folder has share permissions
Expand Down Expand Up @@ -488,6 +518,39 @@ export default defineComponent({
}
},

async onUploadFail(upload: Upload) {
const status = upload.response?.status || 0

// Check known status codes
if (status === 507) {
showError(this.t('files', 'Not enough free space'))
return
} else if (status === 404 || status === 409) {
showError(this.t('files', 'Target folder does not exist any more'))
return
} else if (status === 403) {
showError(this.t('files', 'Operation is blocked by access control'))
return
} else if (status !== 0) {
showError(this.t('files', 'Error when assembling chunks, status code {status}', { status }))
return
}

// Else we try to parse the response error message
try {
const parser = new Parser({ trim: true, explicitRoot: false })
const response = await parser.parseStringPromise(upload.response?.data)
const message = response['s:message'][0] as string
if (typeof message === 'string' && message.trim() !== '') {
// Unfortunatly, the server message is not translated
showError(this.t('files', 'Error during upload: {message}', { message }))
return
}
} catch (error) {}

showError(this.t('files', 'Unknown error during upload'))
},

openSharingSidebar() {
if (window?.OCA?.Files?.Sidebar?.setActiveTab) {
window.OCA.Files.Sidebar.setActiveTab('sharing')
Expand Down
4 changes: 2 additions & 2 deletions dist/core-common.js

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions dist/core-common.js.LICENSE.txt
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@

/*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh <https://feross.org/opensource> */

/*! safe-buffer. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */

/**
* @copyright 2021 Christoph Wurst <[email protected]>
*
Expand Down
2 changes: 1 addition & 1 deletion dist/core-common.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dist/files-init.js

Large diffs are not rendered by default.

2 changes: 0 additions & 2 deletions dist/files-init.js.LICENSE.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
/*! safe-buffer. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */

/**
* @copyright 2019 Christoph Wurst <[email protected]>
*
Expand Down
2 changes: 1 addition & 1 deletion dist/files-init.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dist/files-main.js

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions dist/files-main.js.LICENSE.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
* @license MIT
*/

/*! http://mths.be/fromcodepoint v0.1.0 by @mathias */

/**
* @copyright 2019 Christoph Wurst <[email protected]>
*
Expand Down
2 changes: 1 addition & 1 deletion dist/files-main.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dist/settings-users-8351.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/settings-users-8351.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dist/settings-vue-settings-apps-users-management.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/settings-vue-settings-apps-users-management.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dist/settings-vue-settings-personal-info.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/settings-vue-settings-personal-info.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dist/systemtags-init.js

Large diffs are not rendered by default.

2 changes: 0 additions & 2 deletions dist/systemtags-init.js.LICENSE.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
/*! safe-buffer. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */

/**
* @copyright 2019 Christoph Wurst <[email protected]>
*
Expand Down
2 changes: 1 addition & 1 deletion dist/systemtags-init.js.map

Large diffs are not rendered by default.

21 changes: 17 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,8 @@
"vuedraggable": "^2.24.3",
"vuex": "^3.6.2",
"vuex-router-sync": "^5.0.0",
"webdav": "^5.3.1"
"webdav": "^5.3.1",
"xml2js": "^0.6.2"
},
"devDependencies": {
"@babel/node": "^7.22.10",
Expand Down