dashboard/components/form/ResourceQuota/NamespaceRow.vue

159 lines
3.7 KiB
Vue

<script>
import Select from '@/components/form/Select';
import UnitInput from '@/components/form/UnitInput';
import PercentageBar from '@/components/PercentageBar';
import { formatSi, parseSi } from '@/utils/units';
import { ROW_COMPUTED } from './shared';
export default {
components: {
Select, PercentageBar, UnitInput
},
props: {
mode: {
type: String,
required: true,
},
types: {
type: Array,
default: () => []
},
type: {
type: String,
required: true
},
value: {
type: Object,
default: () => {
return {};
}
},
namespace: {
type: Object,
default: () => {
return {};
}
},
projectResourceQuotaLimits: {
type: Object,
default: () => {
return {};
}
},
namespaceResourceQuotaLimits: {
type: Array,
default: () => {
return [];
}
},
defaultResourceQuotaLimits: {
type: Object,
default: () => {
return {};
}
}
},
mounted() {
this.update(this.defaultResourceQuotaLimits[this.type]);
},
computed: {
...ROW_COMPUTED,
limitValue() {
return parseSi(this.projectResourceQuotaLimits[this.type]);
},
siOptions() {
return {
maxExponent: this.typeOption.inputExponent,
minExponent: this.typeOption.inputExponent,
increment: this.typeOption.increment,
};
},
namespaceLimits() {
return this.namespaceResourceQuotaLimits
.filter(resourceQuota => resourceQuota[this.type] && resourceQuota.id !== this.namespace.id)
.map(resourceQuota => parseSi(resourceQuota[this.type], this.siOptions));
},
namespaceContribution() {
return this.namespaceLimits.reduce((sum, limit) => sum + limit, 0);
},
totalContribution() {
return this.namespaceContribution + parseSi(this.value.limit[this.type] || '0', this.siOptions);
},
percentageUsed() {
return Math.min(this.totalContribution * 100 / this.projectLimit, 100);
},
projectLimit() {
return parseSi(this.projectResourceQuotaLimits[this.type] || 0, this.siOptions);
},
max() {
return this.projectLimit - this.namespaceContribution;
},
slices() {
const out = [];
this.namespaceLimits.forEach((limit, i) => {
const lastValue = i > 0 ? this.namespaceLimits[i - 1] : 0;
const sliceTotal = lastValue + limit;
out.push(sliceTotal * 100 / this.projectLimit);
});
return out;
}
},
methods: {
update(newValue) {
const parsedNewValue = parseSi(newValue, this.siOptions) || 0;
const min = Math.max(parsedNewValue, 0);
const max = Math.min(min, this.max);
const value = formatSi(max, this.siOptions);
this.$emit('input', this.type, value);
}
},
};
</script>
<template>
<div v-if="typeOption" class="row">
<Select
class="mr-10"
:mode="mode"
:value="type"
:disabled="true"
:options="types"
/>
<div class="resource-availability mr-10">
<PercentageBar class="percentage-bar" :value="percentageUsed" :slices="slices" :color-stops="{'100': '--primary'}" />
</div>
<UnitInput
:value="value.limit[type]"
:mode="mode"
:placeholder="typeOption.placeholder"
:increment="typeOption.increment"
:input-exponent="typeOption.inputExponent"
:base-unit="typeOption.baseUnit"
:output-modifier="true"
@input="update"
/>
</div>
</template>
<style lang='scss' scoped>
.resource-availability {
align-self: center;
}
.row {
display: flex;
flex-direction: row;
justify-content: space-evenly;
& > * {
width: 100%;
}
}
</style>