Skip to content

Commit

Permalink
Merge pull request #41346 from nextcloud/fix/files/quota-warning
Browse files Browse the repository at this point in the history
  • Loading branch information
skjnldsv authored Dec 5, 2023
2 parents f0108cb + f89ef39 commit 788fc78
Show file tree
Hide file tree
Showing 23 changed files with 132 additions and 31 deletions.
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 <christoph@winzerhof-wurst.at>
*
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 <christoph@winzerhof-wurst.at>
*
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 <christoph@winzerhof-wurst.at>
*
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 <christoph@winzerhof-wurst.at>
*
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

0 comments on commit 788fc78

Please sign in to comment.