Skip to content

Commit

Permalink
Add support for multiple quota sources
Browse files Browse the repository at this point in the history
This will hopefully simplify future integration with galaxyproject#10977
  • Loading branch information
davelopez committed Jan 7, 2022
1 parent 7d891b4 commit 34edc15
Show file tree
Hide file tree
Showing 6 changed files with 176 additions and 37 deletions.
11 changes: 10 additions & 1 deletion client/src/components/User/DiskUsage/DiskUsageSummary.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@
{{ errorMessage }}
</b-alert>
<div v-if="user">
<QuotaUsageSummary v-if="config.enable_quotas" :user="user" />
<div v-if="config.enable_quotas">
<QuotaUsageProvider v-slot="{ result: quotaUsages, loading: isLoadingUsage }">
<LoadingSpan v-if="isLoadingUsage" />
<QuotaUsageSummary v-else-if="quotaUsages" :quota-usages="quotaUsages" />
</QuotaUsageProvider>
</div>
<h2 v-else class="text-center my-3">
You're using <b>{{ getTotalDiskUsage(user) }}</b> of disk space.
</h2>
Expand All @@ -20,15 +25,19 @@
<script>
import _l from "utils/localization";
import { bytesToString } from "utils/utils";
import LoadingSpan from "components/LoadingSpan";
import CurrentUser from "components/providers/CurrentUser";
import ConfigProvider from "components/providers/ConfigProvider";
import QuotaUsageSummary from "components/User/DiskUsage/Quota/QuotaUsageSummary";
import { QuotaUsageProvider } from "./Quota/QuotaUsageProvider";
export default {
components: {
CurrentUser,
ConfigProvider,
QuotaUsageSummary,
QuotaUsageProvider,
LoadingSpan,
},
data() {
return {
Expand Down
48 changes: 48 additions & 0 deletions client/src/components/User/DiskUsage/Quota/QuotaUsageBar.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<template>
<div class="quota-usage-bar w-75 mx-auto my-5">
<h2 v-if="!isDefaultQuota">
<b>{{ quotaUsage.sourceLabel }}</b> storage source
</h2>
<h3>
<b>{{ quotaUsage.niceTotalDiskUsage }}</b> of {{ quotaUsage.niceQuota }} used
</h3>
<h5 v-if="quotaHasLimit">{{ quotaUsage.quotaPercent }}% of disk quota used</h5>
<b-progress :value="quotaUsage.quotaPercent" :variant="progressVariant" max="100" />
</div>
</template>

<script>
import _l from "utils/localization";
import { DEFAULT_QUOTA_SOURCE_LABEL } from "./model/QuotaUsage";
export default {
props: {
quotaUsage: {
type: Object,
required: true,
},
},
computed: {
/** @returns {Boolean} */
isDefaultQuota() {
return this.quotaUsage.sourceLabel === DEFAULT_QUOTA_SOURCE_LABEL;
},
/** @returns {Boolean} */
quotaHasLimit() {
return !this.quotaUsage.isUnlimited;
},
/** @returns {String} */
progressVariant() {
const percent = this.quotaUsage.quotaPercent;
if (percent < 50) {
return "success";
} else if (percent >= 50 && percent < 80) {
return "primary";
} else if (percent >= 80 && percent < 95) {
return "warning";
}
return "danger";
},
},
};
</script>
24 changes: 24 additions & 0 deletions client/src/components/User/DiskUsage/Quota/QuotaUsageProvider.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import axios from "axios";
import { SingleQueryProvider } from "components/providers/SingleQueryProvider";
import { getAppRoot } from "onload/loadConfig";
import { rethrowSimple } from "utils/simple-error";
import { QuotaUsage } from "./model";

// TODO: replace this with the proper provider and API call after
// https://github.com/galaxyproject/galaxy/pull/10977 is available

/**
* Fetches the disk usage by the user across all ObjectStores.
* @returns {Array<QuotaUsage>}
*/
async function fetchQuotaUsage() {
const url = `${getAppRoot()}api/users/current`;
try {
const { data } = await axios.get(url);
return [new QuotaUsage(data)];
} catch (e) {
rethrowSimple(e);
}
}

export const QuotaUsageProvider = SingleQueryProvider(fetchQuotaUsage);
58 changes: 22 additions & 36 deletions client/src/components/User/DiskUsage/Quota/QuotaUsageSummary.vue
Original file line number Diff line number Diff line change
@@ -1,62 +1,48 @@
<template>
<div class="quota-summary">
<h2 class="text-center mt-5">
You've got <b>{{ totalQuotaString }}</b> of disk quota.
</h2>
<h4 class="text-center mb-5">
{{ quotaDescriptionSummary }}
</h4>
<div class="text-center my-5">
<h2>
You've got <b>{{ totalQuotaString }}</b> of total disk quota.
</h2>
<h4>
{{ quotaDescriptionSummary }}
</h4>
</div>

<div class="w-75 mx-auto my-5">
<h3>
<b>{{ usedQuotaString }}</b> of {{ totalQuotaString }} used
</h3>
<h5>{{ usedQuotaPercent }}% of total disk quota used</h5>
<b-progress :value="usedQuotaPercent" :variant="progressVariant" max="100"></b-progress>
<div v-for="quotaUsage in quotaUsages" :key="quotaUsage.sourceLabel">
<QuotaUsageBar :quota-usage="quotaUsage" />
</div>
</div>
</template>

<script>
import _l from "utils/localization";
import { bytesToString } from "utils/utils";
import QuotaUsageBar from "./QuotaUsageBar";
export default {
components: {
QuotaUsageBar,
},
props: {
quotaUsage: {
type: Object,
quotaUsages: {
type: Array,
required: true,
},
},
data() {
return {
quotaDescriptionSummary: _l("This is the maximum disk space that you can use"),
quotaDescriptionSummary: _l(
"This is the maximum disk space that you can use across all your storage sources." +
" Unlimited storage sources are not taken into account"
),
};
},
computed: {
/** @returns {String} */
totalQuotaString() {
return this.quotaUsage.quota;
},
/** @returns {String} */
usedQuotaString() {
return bytesToString(this.quotaUsage.total_disk_usage, true);
},
/** @returns {float} */
usedQuotaPercent() {
return this.quotaUsage.quota_percent;
},
/** @returns {String} */
progressVariant() {
const percent = this.usedQuotaPercent;
if (percent < 50) {
return "success";
} else if (percent >= 50 && percent < 80) {
return "primary";
} else if (percent >= 80 && percent < 95) {
return "warning";
}
return "danger";
const totalQuota = this.quotaUsages.reduce((acc, item) => acc + item.quotaInBytes, 0);
return bytesToString(totalQuota, true);
},
},
};
Expand Down
71 changes: 71 additions & 0 deletions client/src/components/User/DiskUsage/Quota/model/QuotaUsage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { bytesToString } from "utils/utils";

export const DEFAULT_QUOTA_SOURCE_LABEL = "Default";

/**
* Contains information about quota usage for a particular ObjectStore.
*/
export class QuotaUsage {
constructor(data) {
this.data = data;
}

/**
* The name of the ObjectStore associated with the quota.
* @returns {String}
*/
get sourceLabel() {
return this.data.quota_source_label || DEFAULT_QUOTA_SOURCE_LABEL;
}

/**
* The maximum allowed disk usage in bytes.
* @returns {Number}
*/
get quotaInBytes() {
return this.data.quota_bytes;
}

/**
* The total amount of bytes used in this ObjectStore.
* @returns {Number}
*/
get totalDiskUsageInBytes() {
return this.data.total_disk_usage;
}

/**
* The percentage of used quota.
* @returns {Number}
*/
get quotaPercent() {
return this.data.quota_percent;
}

/**
* The maximum allowed disk usage as human readable size.
* @returns {String}
*/
get niceQuota() {
if (this.isUnlimited) {
return "unlimited";
}
return bytesToString(this.quotaInBytes, true);
}

/**
* The total amount of disk used in this ObjectStore as human readable size.
* @returns {String}
*/
get niceTotalDiskUsage() {
return bytesToString(this.totalDiskUsageInBytes, true);
}

/**
* Whether this ObjectStore has unlimited quota
* @returns {Boolean}
*/
get isUnlimited() {
return !this.quotaInBytes;
}
}
1 change: 1 addition & 0 deletions client/src/components/User/DiskUsage/Quota/model/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { QuotaUsage } from "./QuotaUsage";

0 comments on commit 34edc15

Please sign in to comment.