Skip to content

Commit

Permalink
Create quota information component, add to account page (#11287)
Browse files Browse the repository at this point in the history
* Create quota information component, add to account page
  • Loading branch information
AlexAndBear authored Jul 30, 2024
1 parent 0fed190 commit cfb122f
Show file tree
Hide file tree
Showing 7 changed files with 137 additions and 81 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Enhancement: Add quota information to account page

We've added a new section to the account page that displays the users current quota usage.

https://github.com/owncloud/web/pull/11287

79 changes: 79 additions & 0 deletions packages/web-runtime/src/components/Account/QuotaInformation.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<template>
<div class="quota-information oc-flex oc-flex-bottom">
<oc-icon name="hard-drive-2" size="small" fill-type="line" class="oc-mr-xs" />
<div>
<p class="oc-my-rm">
<span class="quota-information-text" v-text="personalStorageDetailsLabel" />
</p>
<oc-progress
v-if="limitedPersonalStorage"
class="quota-information-progress-bar"
:value="quotaUsagePercent"
:max="100"
size="small"
:variation="quotaProgressVariant"
/>
</div>
</div>
</template>

<script lang="ts">
import { computed, defineComponent, PropType, unref } from 'vue'
import { Quota } from '@ownclouders/web-client/graph/generated'
import { filesize } from 'filesize'
import { useGettext } from 'vue3-gettext'
export default defineComponent({
name: 'QuotaInformation',
props: {
quota: {
type: Object as PropType<Quota>,
required: true,
default: () => undefined as Quota // FIXME: hack because vue doesn't detect type
}
},
setup(props) {
const { $gettext } = useGettext()
const limitedPersonalStorage = computed(() => {
return props.quota.total !== 0
})
const quotaUsagePercent = computed(() => {
return parseFloat(((props.quota.used / props.quota.total) * 100).toFixed(2))
})
const personalStorageDetailsLabel = computed(() => {
const total = props.quota.total || 0
const used = props.quota.used || 0
return total
? $gettext('%{used} of %{total} used (%{percentage}%)', {
used: filesize(used),
total: filesize(total),
percentage: (unref(quotaUsagePercent) || 0).toString()
})
: $gettext('%{used} used', {
used: filesize(used),
total: filesize(total)
})
})
const quotaProgressVariant = computed(() => {
if ((unref(quotaUsagePercent) || 0) < 80) {
return 'primary'
}
if ((unref(quotaUsagePercent) || 0) < 90) {
return 'warning'
}
return 'danger'
})
return {
quotaUsagePercent,
personalStorageDetailsLabel,
limitedPersonalStorage,
quotaProgressVariant
}
}
})
</script>
59 changes: 8 additions & 51 deletions packages/web-runtime/src/components/Topbar/UserMenu.vue
Original file line number Diff line number Diff line change
Expand Up @@ -70,24 +70,11 @@
<span class="profile-info-wrapper" :class="{ 'oc-py-xs': !user.mail }">
<span class="oc-display-block" v-text="user.displayName" />
<span v-if="user.mail" class="oc-text-small" v-text="user.mail" />
<div v-if="quotaEnabled" class="storage-wrapper oc-flex oc-flex-bottom oc-mt-xs">
<oc-icon name="hard-drive-2" size="small" fill-type="line" class="oc-mr-xs" />
<div>
<p class="oc-my-rm">
<span
class="storage-wrapper-quota oc-text-small"
v-text="personalStorageDetailsLabel"
/>
</p>
<oc-progress
v-if="limitedPersonalStorage"
:value="quotaUsagePercent"
:max="100"
size="small"
:variation="quotaProgressVariant"
/>
</div>
</div>
<quota-information
v-if="quotaEnabled"
:quota="quota"
class="oc-text-small oc-mt-xs"
/>
</span>
</li>
<li>
Expand Down Expand Up @@ -125,7 +112,6 @@
<script lang="ts">
import { storeToRefs } from 'pinia'
import { defineComponent, ComponentPublicInstance, computed, unref } from 'vue'
import { filesize } from 'filesize'
import {
useRoute,
useSpacesStore,
Expand All @@ -135,8 +121,10 @@ import {
useAuthService
} from '@ownclouders/web-pkg'
import { OcDrop } from 'design-system/src/components'
import QuotaInformation from '../Account/QuotaInformation.vue'
export default defineComponent({
components: { QuotaInformation },
setup() {
const route = useRoute()
const userStore = useUserStore()
Expand Down Expand Up @@ -182,38 +170,8 @@ export default defineComponent({
onPremisesSamAccountName() {
return this.user?.onPremisesSamAccountName
},
personalStorageDetailsLabel() {
const total = this.quota.total || 0
const used = this.quota.used || 0
return total
? this.$gettext('%{used} of %{total} used (%{percentage}%)', {
used: filesize(used),
total: filesize(total),
percentage: (this.quotaUsagePercent || 0).toString()
})
: this.$gettext('%{used} used', {
used: filesize(used),
total: filesize(total)
})
},
limitedPersonalStorage() {
return this.quota.total !== 0
},
quotaEnabled() {
return !!this.quota
},
quotaUsagePercent() {
return parseFloat(((this.quota.used / this.quota.total) * 100).toFixed(2))
},
quotaProgressVariant() {
if ((this.quotaUsagePercent || 0) < 80) {
return 'primary'
}
if ((this.quotaUsagePercent || 0) < 90) {
return 'warning'
}
return 'danger'
}
},
mounted() {
Expand Down Expand Up @@ -256,8 +214,7 @@ export default defineComponent({
}
}
&.profile-info-wrapper,
&.storage-wrapper {
&.profile-info-wrapper {
gap: var(--oc-space-medium);
min-height: 3rem;
}
Expand Down
15 changes: 14 additions & 1 deletion packages/web-runtime/src/pages/account.vue
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@
<span v-else v-text="$gettext('No email has been set up')" />
</dd>
</div>
<div v-if="!!quota" class="account-page-info-quota oc-mb oc-width-1-2@m oc-width-1-1@s">
<dt class="oc-text-normal oc-text-muted" v-text="$gettext('Personal storage')" />
<dd data-testid="quota">
<quota-information :quota="quota" class="oc-mt-xs" />
</dd>
</div>
<div class="account-page-info-groups oc-mb oc-width-1-2@m oc-width-1-1@s">
<dt class="oc-text-normal oc-text-muted" v-text="$gettext('Group memberships')" />
<dd data-testid="group-names">
Expand Down Expand Up @@ -219,10 +225,12 @@ import { supportedLanguages } from '../defaults'
import { User } from '@ownclouders/web-client/graph/generated'
import { isEmpty } from 'lodash-es'
import { call } from '@ownclouders/web-client'
import QuotaInformation from '../components/Account/QuotaInformation.vue'
export default defineComponent({
name: 'AccountPage',
components: {
QuotaInformation,
AppLoadingSpinner,
GdprExport,
ExtensionPreference,
Expand Down Expand Up @@ -254,6 +262,10 @@ export default defineComponent({
const { user } = storeToRefs(userStore)
const quota = computed(() => {
return spacesStore.personalSpace?.spaceQuota
})
const showGdprExport = computed(() => {
return (
authStore.userContextReady &&
Expand Down Expand Up @@ -539,7 +551,8 @@ export default defineComponent({
loadAccountBundleTask,
loadGraphUserTask,
loadValuesListTask,
showEditPasswordModal
showEditPasswordModal,
quota
}
},
computed: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,11 @@ exports[`User Menu component > when quota and no email is set > renders a naviga
<li data-v-08f1b1e7="" class="profile-info-wrapper oc-pl-s">
<avatar-image-stub data-v-08f1b1e7="" width="32" userid="einstein" user-name="Albert Einstein"></avatar-image-stub> <span data-v-08f1b1e7="" class="profile-info-wrapper oc-py-xs"><span data-v-08f1b1e7="" class="oc-display-block">Albert Einstein</span>
<!--v-if-->
<div data-v-08f1b1e7="" class="storage-wrapper oc-flex oc-flex-bottom oc-mt-xs">
<oc-icon-stub data-v-08f1b1e7="" name="hard-drive-2" size="small" fill-type="line" class="oc-mr-xs"></oc-icon-stub>
<div data-v-08f1b1e7="">
<p data-v-08f1b1e7="" class="oc-my-rm"><span data-v-08f1b1e7="" class="storage-wrapper-quota oc-text-small">300 B of 1 kB used (30%)</span></p>
<oc-progress-stub data-v-08f1b1e7="" max="100" size="small" variation="primary" value="30"></oc-progress-stub>
<div data-v-08f1b1e7="" class="quota-information oc-flex oc-flex-bottom oc-text-small oc-mt-xs">
<oc-icon-stub name="hard-drive-2" size="small" fill-type="line" class="oc-mr-xs"></oc-icon-stub>
<div>
<p class="oc-my-rm"><span class="quota-information-text">300 B of 1 kB used (30%)</span></p>
<oc-progress-stub class="quota-information-progress-bar" max="100" size="small" variation="primary" value="30"></oc-progress-stub>
</div>
</div></span>
</li>
Expand Down Expand Up @@ -98,11 +98,11 @@ exports[`User Menu component > when quota is above 80% and below 90% > renders a
<oc-list-stub data-v-08f1b1e7="" class="user-menu-list">
<li data-v-08f1b1e7="" class="profile-info-wrapper oc-pl-s">
<avatar-image-stub data-v-08f1b1e7="" width="32" userid="einstein" user-name="Albert Einstein"></avatar-image-stub> <span data-v-08f1b1e7="" class="profile-info-wrapper"><span data-v-08f1b1e7="" class="oc-display-block">Albert Einstein</span> <span data-v-08f1b1e7="" class="oc-text-small">test@test.de</span>
<div data-v-08f1b1e7="" class="storage-wrapper oc-flex oc-flex-bottom oc-mt-xs">
<oc-icon-stub data-v-08f1b1e7="" name="hard-drive-2" size="small" fill-type="line" class="oc-mr-xs"></oc-icon-stub>
<div data-v-08f1b1e7="">
<p data-v-08f1b1e7="" class="oc-my-rm"><span data-v-08f1b1e7="" class="storage-wrapper-quota oc-text-small">810 B of 1 kB used (81%)</span></p>
<oc-progress-stub data-v-08f1b1e7="" max="100" size="small" variation="warning" value="81"></oc-progress-stub>
<div data-v-08f1b1e7="" class="quota-information oc-flex oc-flex-bottom oc-text-small oc-mt-xs">
<oc-icon-stub name="hard-drive-2" size="small" fill-type="line" class="oc-mr-xs"></oc-icon-stub>
<div>
<p class="oc-my-rm"><span class="quota-information-text">810 B of 1 kB used (81%)</span></p>
<oc-progress-stub class="quota-information-progress-bar" max="100" size="small" variation="warning" value="81"></oc-progress-stub>
</div>
</div></span>
</li>
Expand Down Expand Up @@ -131,11 +131,11 @@ exports[`User Menu component > when quota is above 90% > renders a danger quota
<oc-list-stub data-v-08f1b1e7="" class="user-menu-list">
<li data-v-08f1b1e7="" class="profile-info-wrapper oc-pl-s">
<avatar-image-stub data-v-08f1b1e7="" width="32" userid="einstein" user-name="Albert Einstein"></avatar-image-stub> <span data-v-08f1b1e7="" class="profile-info-wrapper"><span data-v-08f1b1e7="" class="oc-display-block">Albert Einstein</span> <span data-v-08f1b1e7="" class="oc-text-small">test@test.de</span>
<div data-v-08f1b1e7="" class="storage-wrapper oc-flex oc-flex-bottom oc-mt-xs">
<oc-icon-stub data-v-08f1b1e7="" name="hard-drive-2" size="small" fill-type="line" class="oc-mr-xs"></oc-icon-stub>
<div data-v-08f1b1e7="">
<p data-v-08f1b1e7="" class="oc-my-rm"><span data-v-08f1b1e7="" class="storage-wrapper-quota oc-text-small">910 B of 1 kB used (91%)</span></p>
<oc-progress-stub data-v-08f1b1e7="" max="100" size="small" variation="danger" value="91"></oc-progress-stub>
<div data-v-08f1b1e7="" class="quota-information oc-flex oc-flex-bottom oc-text-small oc-mt-xs">
<oc-icon-stub name="hard-drive-2" size="small" fill-type="line" class="oc-mr-xs"></oc-icon-stub>
<div>
<p class="oc-my-rm"><span class="quota-information-text">910 B of 1 kB used (91%)</span></p>
<oc-progress-stub class="quota-information-progress-bar" max="100" size="small" variation="danger" value="91"></oc-progress-stub>
</div>
</div></span>
</li>
Expand Down Expand Up @@ -164,11 +164,11 @@ exports[`User Menu component > when quota is below 80% > renders a primary quota
<oc-list-stub data-v-08f1b1e7="" class="user-menu-list">
<li data-v-08f1b1e7="" class="profile-info-wrapper oc-pl-s">
<avatar-image-stub data-v-08f1b1e7="" width="32" userid="einstein" user-name="Albert Einstein"></avatar-image-stub> <span data-v-08f1b1e7="" class="profile-info-wrapper"><span data-v-08f1b1e7="" class="oc-display-block">Albert Einstein</span> <span data-v-08f1b1e7="" class="oc-text-small">test@test.de</span>
<div data-v-08f1b1e7="" class="storage-wrapper oc-flex oc-flex-bottom oc-mt-xs">
<oc-icon-stub data-v-08f1b1e7="" name="hard-drive-2" size="small" fill-type="line" class="oc-mr-xs"></oc-icon-stub>
<div data-v-08f1b1e7="">
<p data-v-08f1b1e7="" class="oc-my-rm"><span data-v-08f1b1e7="" class="storage-wrapper-quota oc-text-small">300 B of 1 kB used (30%)</span></p>
<oc-progress-stub data-v-08f1b1e7="" max="100" size="small" variation="primary" value="30"></oc-progress-stub>
<div data-v-08f1b1e7="" class="quota-information oc-flex oc-flex-bottom oc-text-small oc-mt-xs">
<oc-icon-stub name="hard-drive-2" size="small" fill-type="line" class="oc-mr-xs"></oc-icon-stub>
<div>
<p class="oc-my-rm"><span class="quota-information-text">300 B of 1 kB used (30%)</span></p>
<oc-progress-stub class="quota-information-progress-bar" max="100" size="small" variation="primary" value="30"></oc-progress-stub>
</div>
</div></span>
</li>
Expand Down Expand Up @@ -197,10 +197,10 @@ exports[`User Menu component > when quota is not defined > renders no percentag
<oc-list-stub data-v-08f1b1e7="" class="user-menu-list">
<li data-v-08f1b1e7="" class="profile-info-wrapper oc-pl-s">
<avatar-image-stub data-v-08f1b1e7="" width="32" userid="einstein" user-name="Albert Einstein"></avatar-image-stub> <span data-v-08f1b1e7="" class="profile-info-wrapper"><span data-v-08f1b1e7="" class="oc-display-block">Albert Einstein</span> <span data-v-08f1b1e7="" class="oc-text-small">test@test.de</span>
<div data-v-08f1b1e7="" class="storage-wrapper oc-flex oc-flex-bottom oc-mt-xs">
<oc-icon-stub data-v-08f1b1e7="" name="hard-drive-2" size="small" fill-type="line" class="oc-mr-xs"></oc-icon-stub>
<div data-v-08f1b1e7="">
<p data-v-08f1b1e7="" class="oc-my-rm"><span data-v-08f1b1e7="" class="storage-wrapper-quota oc-text-small">910 B used</span></p>
<div data-v-08f1b1e7="" class="quota-information oc-flex oc-flex-bottom oc-text-small oc-mt-xs">
<oc-icon-stub name="hard-drive-2" size="small" fill-type="line" class="oc-mr-xs"></oc-icon-stub>
<div>
<p class="oc-my-rm"><span class="quota-information-text">910 B used</span></p>
<!--v-if-->
</div>
</div></span>
Expand Down Expand Up @@ -230,10 +230,10 @@ exports[`User Menu component > when quota is unlimited > renders no percentag of
<oc-list-stub data-v-08f1b1e7="" class="user-menu-list">
<li data-v-08f1b1e7="" class="profile-info-wrapper oc-pl-s">
<avatar-image-stub data-v-08f1b1e7="" width="32" userid="einstein" user-name="Albert Einstein"></avatar-image-stub> <span data-v-08f1b1e7="" class="profile-info-wrapper"><span data-v-08f1b1e7="" class="oc-display-block">Albert Einstein</span> <span data-v-08f1b1e7="" class="oc-text-small">test@test.de</span>
<div data-v-08f1b1e7="" class="storage-wrapper oc-flex oc-flex-bottom oc-mt-xs">
<oc-icon-stub data-v-08f1b1e7="" name="hard-drive-2" size="small" fill-type="line" class="oc-mr-xs"></oc-icon-stub>
<div data-v-08f1b1e7="">
<p data-v-08f1b1e7="" class="oc-my-rm"><span data-v-08f1b1e7="" class="storage-wrapper-quota oc-text-small">300 B used</span></p>
<div data-v-08f1b1e7="" class="quota-information oc-flex oc-flex-bottom oc-text-small oc-mt-xs">
<oc-icon-stub name="hard-drive-2" size="small" fill-type="line" class="oc-mr-xs"></oc-icon-stub>
<div>
<p class="oc-my-rm"><span class="quota-information-text">300 B used</span></p>
<!--v-if-->
</div>
</div></span>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ exports[`account page > account information section > displays basic user inform
<dt data-v-f2ac0579="" class="oc-text-normal oc-text-muted">Email</dt>
<dd data-v-f2ac0579="">some-email</dd>
</div>
<!--v-if-->
<div data-v-f2ac0579="" class="account-page-info-groups oc-mb oc-width-1-2@m oc-width-1-1@s">
<dt data-v-f2ac0579="" class="oc-text-normal oc-text-muted">Group memberships</dt>
<dd data-v-f2ac0579="" data-testid="group-names"><span data-v-f2ac0579="" data-testid="group-names-empty">You are not part of any group</span></dd>
Expand Down
2 changes: 1 addition & 1 deletion tests/e2e/support/objects/account/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import util from 'util'
import config from '../../../config'

const accountMenuButton = '.oc-topbar-avatar'
const quotaValue = '.storage-wrapper-quota'
const quotaValue = '.quota-information-text'
const accountManageButton = '#oc-topbar-account-manage'
const infoValue = '.account-page-info-%s dd'
const requestExportButton = '[data-testid="request-export-btn"]'
Expand Down

0 comments on commit cfb122f

Please sign in to comment.