web/satellite: migrate EditProjectDetails component to use SFC composition api
Change-Id: If799efb9cbbdbfe5f269df0c555e47b3d767052a
This commit is contained in:
parent
9622ae67fa
commit
599baf947e
@ -198,8 +198,8 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Vue, Prop } from 'vue-property-decorator';
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
|
||||
import { Dimensions, Memory, Size } from '@/utils/bytesSize';
|
||||
import { PROJECTS_ACTIONS } from '@/store/modules/projects';
|
||||
@ -212,446 +212,433 @@ import {
|
||||
import { MetaUtils } from '@/utils/meta';
|
||||
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { useNotify, useRouter, useStore } from '@/utils/hooks';
|
||||
|
||||
import VButton from '@/components/common/VButton.vue';
|
||||
|
||||
// @vue/component
|
||||
@Component({
|
||||
components: {
|
||||
VButton,
|
||||
},
|
||||
})
|
||||
export default class EditProjectDetails extends Vue {
|
||||
@Prop({ default: Dimensions.TB })
|
||||
public activeStorageMeasurement: string;
|
||||
@Prop({ default: Dimensions.TB })
|
||||
public activeBandwidthMeasurement: string;
|
||||
const store = useStore();
|
||||
const notify = useNotify();
|
||||
const router = useRouter();
|
||||
|
||||
public isNameEditing = false;
|
||||
public isDescriptionEditing = false;
|
||||
public isStorageLimitEditing = false;
|
||||
public isBandwidthLimitEditing = false;
|
||||
public isPaidTier = false;
|
||||
public nameValue = '';
|
||||
public descriptionValue = '';
|
||||
public nameLength: number = MAX_NAME_LENGTH;
|
||||
public descriptionLength: number = MAX_DESCRIPTION_LENGTH;
|
||||
public storageLimitValue = 0;
|
||||
public bandwidthLimitValue = 0;
|
||||
const analytics: AnalyticsHttpApi = new AnalyticsHttpApi();
|
||||
|
||||
private readonly analytics: AnalyticsHttpApi = new AnalyticsHttpApi();
|
||||
const activeStorageMeasurement = ref<string>(Dimensions.TB);
|
||||
const activeBandwidthMeasurement = ref<string>(Dimensions.TB);
|
||||
const isNameEditing = ref<boolean>(false);
|
||||
const isDescriptionEditing = ref<boolean>(false);
|
||||
const isStorageLimitEditing = ref<boolean>(false);
|
||||
const isBandwidthLimitEditing = ref<boolean>(false);
|
||||
const isPaidTier = ref<boolean>(false);
|
||||
const nameValue = ref<string>('');
|
||||
const descriptionValue = ref<string>('');
|
||||
const nameLength = ref<number>(MAX_NAME_LENGTH);
|
||||
const descriptionLength = ref<number>(MAX_DESCRIPTION_LENGTH);
|
||||
const storageLimitValue = ref<number>(0);
|
||||
const bandwidthLimitValue = ref<number>(0);
|
||||
|
||||
/**
|
||||
* Returns selected project from store.
|
||||
*/
|
||||
public get storedProject(): Project {
|
||||
return this.$store.getters.selectedProject;
|
||||
/**
|
||||
* Returns selected project from store.
|
||||
*/
|
||||
const storedProject = computed((): Project => {
|
||||
return store.getters.selectedProject;
|
||||
});
|
||||
|
||||
/**
|
||||
* Returns current limits from store.
|
||||
*/
|
||||
const currentLimits = computed((): ProjectLimits => {
|
||||
return store.state.projectsModule.currentLimits;
|
||||
});
|
||||
|
||||
/**
|
||||
* Returns displayed project description on UI.
|
||||
*/
|
||||
const displayedDescription = computed((): string => {
|
||||
return storedProject.value.description ?
|
||||
storedProject.value.description :
|
||||
'No description yet. Please enter some information if any.';
|
||||
});
|
||||
|
||||
/**
|
||||
* Returns formatted limit amount.
|
||||
*/
|
||||
const bandwidthLimitFormatted = computed((): string => {
|
||||
return formattedValue(new Size(currentLimits.value.bandwidthLimit, 2));
|
||||
});
|
||||
|
||||
const storageLimitFormatted = computed((): string => {
|
||||
return formattedValue(new Size(currentLimits.value.storageLimit, 2));
|
||||
});
|
||||
|
||||
/**
|
||||
* Returns formatted limit amount.
|
||||
*/
|
||||
const bandwidthLimitMeasurement = computed((): string => {
|
||||
return new Size(currentLimits.value.bandwidthLimit, 2).formattedBytes;
|
||||
});
|
||||
|
||||
const storageLimitMeasurement = computed((): string => {
|
||||
return new Size(currentLimits.value.storageLimit, 2).formattedBytes;
|
||||
});
|
||||
|
||||
/**
|
||||
* Returns current input character limit.
|
||||
*/
|
||||
const bandwidthCharLimit = computed((): number => {
|
||||
if (activeBandwidthMeasurement.value === Dimensions.GB) {
|
||||
return 5;
|
||||
} else {
|
||||
return 2;
|
||||
}
|
||||
});
|
||||
|
||||
const storageCharLimit = computed((): number => {
|
||||
if (activeStorageMeasurement.value === Dimensions.GB) {
|
||||
return 5;
|
||||
} else {
|
||||
return 2;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Returns the current measurement that is being input.
|
||||
*/
|
||||
const storageMeasurementFormatted = computed((): string => {
|
||||
if (isStorageLimitEditing.value) {
|
||||
return activeStorageMeasurement.value;
|
||||
} else {
|
||||
return new Size(currentLimits.value.storageLimit, 2).label;
|
||||
}
|
||||
});
|
||||
|
||||
const bandwidthMeasurementFormatted = computed((): string => {
|
||||
if (isBandwidthLimitEditing.value) {
|
||||
return activeBandwidthMeasurement.value;
|
||||
} else {
|
||||
return new Size(currentLimits.value.bandwidthLimit, 2).label;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Gets current default limit for paid accounts.
|
||||
*/
|
||||
const paidBandwidthLimit = computed((): number => {
|
||||
if (activeBandwidthMeasurement.value === Dimensions.GB) {
|
||||
return toGB(getLimitValue(MetaUtils.getMetaContent('default-paid-bandwidth-limit')));
|
||||
} else {
|
||||
return getLimitValue(MetaUtils.getMetaContent('default-paid-bandwidth-limit'));
|
||||
}
|
||||
});
|
||||
|
||||
const paidStorageLimit = computed((): number => {
|
||||
if (activeStorageMeasurement.value === Dimensions.GB) {
|
||||
return toGB(getLimitValue(MetaUtils.getMetaContent('default-paid-storage-limit')));
|
||||
} else {
|
||||
return getLimitValue(MetaUtils.getMetaContent('default-paid-storage-limit'));
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Triggers on name input.
|
||||
*/
|
||||
function onNameInput(event: Event): void {
|
||||
const target = event.target as HTMLInputElement;
|
||||
if (target.value.length < MAX_NAME_LENGTH) {
|
||||
nameValue.value = target.value;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lifecycle hook after initial render.
|
||||
* Fetches project limits and paid tier status.
|
||||
*/
|
||||
public async mounted(): Promise<void> {
|
||||
if (!this.$store.getters.selectedProject.id) {
|
||||
return;
|
||||
}
|
||||
nameValue.value = target.value.slice(0, MAX_NAME_LENGTH);
|
||||
}
|
||||
|
||||
if (this.$store.state.usersModule.user.paidTier) {
|
||||
this.isPaidTier = true;
|
||||
}
|
||||
|
||||
try {
|
||||
await this.$store.dispatch(PROJECTS_ACTIONS.GET_LIMITS, this.$store.getters.selectedProject.id);
|
||||
} catch (error) {
|
||||
this.$notify.error(error.message, AnalyticsErrorEventSource.EDIT_PROJECT_DETAILS);
|
||||
}
|
||||
/**
|
||||
* Triggers on description input.
|
||||
*/
|
||||
function onDescriptionInput(event: Event): void {
|
||||
const target = event.target as HTMLInputElement;
|
||||
if (target.value.length < MAX_DESCRIPTION_LENGTH) {
|
||||
descriptionValue.value = target.value;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns current limits from store.
|
||||
*/
|
||||
public get currentLimits(): ProjectLimits {
|
||||
return this.$store.state.projectsModule.currentLimits;
|
||||
}
|
||||
descriptionValue.value = target.value.slice(0, MAX_DESCRIPTION_LENGTH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns displayed project description on UI.
|
||||
*/
|
||||
public get displayedDescription(): string {
|
||||
return this.storedProject.description ?
|
||||
this.storedProject.description :
|
||||
'No description yet. Please enter some information if any.';
|
||||
}
|
||||
/**
|
||||
* Convert value from GB to TB
|
||||
*/
|
||||
function toTB(limitValue: number): number {
|
||||
return limitValue / 1000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers on name input.
|
||||
*/
|
||||
public onNameInput(event: Event): void {
|
||||
const target = event.target as HTMLInputElement;
|
||||
if (target.value.length < MAX_NAME_LENGTH) {
|
||||
this.nameValue = target.value;
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Convert value from TB to GB
|
||||
*/
|
||||
function toGB(limitValue: number): number {
|
||||
return limitValue * 1000;
|
||||
}
|
||||
|
||||
this.nameValue = target.value.slice(0, MAX_NAME_LENGTH);
|
||||
}
|
||||
/**
|
||||
* Get limit numeric value separated from included measurement
|
||||
*/
|
||||
function getLimitValue(limit: string): number {
|
||||
return parseInt(limit.split(' ')[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers on description input.
|
||||
*/
|
||||
public onDescriptionInput(event: Event): void {
|
||||
const target = event.target as HTMLInputElement;
|
||||
if (target.value.length < MAX_DESCRIPTION_LENGTH) {
|
||||
this.descriptionValue = target.value;
|
||||
return;
|
||||
}
|
||||
|
||||
this.descriptionValue = target.value.slice(0, MAX_DESCRIPTION_LENGTH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns formatted limit amount.
|
||||
*/
|
||||
public get bandwidthLimitFormatted(): string {
|
||||
return this.formattedValue(new Size(this.currentLimits.bandwidthLimit, 2));
|
||||
}
|
||||
|
||||
public get storageLimitFormatted(): string {
|
||||
return this.formattedValue(new Size(this.currentLimits.storageLimit, 2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns formatted limit amount.
|
||||
*/
|
||||
public get bandwidthLimitMeasurement(): string {
|
||||
return new Size(this.currentLimits.bandwidthLimit, 2).formattedBytes;
|
||||
}
|
||||
|
||||
public get storageLimitMeasurement(): string {
|
||||
return new Size(this.currentLimits.storageLimit, 2).formattedBytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns current input character limit.
|
||||
*/
|
||||
public get bandwidthCharLimit(): number {
|
||||
|
||||
if (this.activeBandwidthMeasurement === Dimensions.GB) {
|
||||
return 5;
|
||||
} else {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
public get storageCharLimit(): number {
|
||||
|
||||
if (this.activeStorageMeasurement === Dimensions.GB) {
|
||||
return 5;
|
||||
} else {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current measurement that is being input.
|
||||
*/
|
||||
public get storageMeasurementFormatted(): string {
|
||||
if (this.isStorageLimitEditing) {
|
||||
return this.activeStorageMeasurement;
|
||||
} else {
|
||||
return new Size(this.currentLimits.storageLimit, 2).label;
|
||||
}
|
||||
}
|
||||
|
||||
public get bandwidthMeasurementFormatted(): string {
|
||||
if (this.isBandwidthLimitEditing) {
|
||||
return this.activeBandwidthMeasurement;
|
||||
} else {
|
||||
return new Size(this.currentLimits.bandwidthLimit, 2).label;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets current default limit for paid accounts.
|
||||
*/
|
||||
public get paidBandwidthLimit(): number {
|
||||
if (this.activeBandwidthMeasurement === Dimensions.GB) {
|
||||
return this.toGB(this.getLimitValue(MetaUtils.getMetaContent('default-paid-bandwidth-limit')));
|
||||
} else {
|
||||
return this.getLimitValue(MetaUtils.getMetaContent('default-paid-bandwidth-limit'));
|
||||
}
|
||||
}
|
||||
|
||||
public get paidStorageLimit(): number {
|
||||
if (this.activeStorageMeasurement === Dimensions.GB) {
|
||||
return this.toGB(this.getLimitValue(MetaUtils.getMetaContent('default-paid-storage-limit')));
|
||||
} else {
|
||||
return this.getLimitValue(MetaUtils.getMetaContent('default-paid-storage-limit'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert value from GB to TB
|
||||
*/
|
||||
public toTB(limitValue: number): number {
|
||||
return limitValue / 1000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert value from TB to GB
|
||||
*/
|
||||
public toGB(limitValue: number): number {
|
||||
return limitValue * 1000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get limit numeric value separated from included measurement
|
||||
*/
|
||||
public getLimitValue(limit: string): number {
|
||||
return parseInt(limit.split(' ')[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if measurement unit is currently active.
|
||||
*/
|
||||
public isActiveStorageUnit(isTB: boolean): boolean {
|
||||
if (isTB) {
|
||||
return this.activeStorageMeasurement === Dimensions.TB;
|
||||
} else {
|
||||
return this.activeStorageMeasurement === Dimensions.GB;
|
||||
}
|
||||
}
|
||||
|
||||
public isActiveBandwidthUnit(isTB: boolean): boolean {
|
||||
if (isTB) {
|
||||
return this.activeBandwidthMeasurement === Dimensions.TB;
|
||||
} else {
|
||||
return this.activeBandwidthMeasurement === Dimensions.GB;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles the current active unit, and makes input value measurement conversion.
|
||||
*/
|
||||
public toggleStorageMeasurement(isTB: boolean): void {
|
||||
|
||||
if (isTB) {
|
||||
this.activeStorageMeasurement = Dimensions.TB;
|
||||
this.storageLimitValue = this.toTB(this.storageLimitValue);
|
||||
} else {
|
||||
this.activeStorageMeasurement = Dimensions.GB;
|
||||
this.storageLimitValue = this.toGB(this.storageLimitValue);
|
||||
}
|
||||
}
|
||||
|
||||
public toggleBandwidthMeasurement(isTB: boolean): void {
|
||||
if (isTB) {
|
||||
this.activeBandwidthMeasurement = Dimensions.TB;
|
||||
this.bandwidthLimitValue = this.toTB(this.bandwidthLimitValue);
|
||||
} else {
|
||||
this.activeBandwidthMeasurement = Dimensions.GB;
|
||||
this.bandwidthLimitValue = this.toGB(this.bandwidthLimitValue);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers on limit input.
|
||||
Limits the input value based on default max limit and character limit.
|
||||
*/
|
||||
public onStorageLimitInput(event: Event): void {
|
||||
const target = event.target as HTMLInputElement;
|
||||
const paidStorageCharLimit = this.paidStorageLimit.toString().length;
|
||||
|
||||
if (target.value.length > paidStorageCharLimit) {
|
||||
const formattedLimit = target.value.slice(0, paidStorageCharLimit);
|
||||
this.storageLimitValue = parseInt(formattedLimit);
|
||||
} else if (parseInt(target.value) > this.paidStorageLimit) {
|
||||
this.storageLimitValue = this.paidStorageLimit;
|
||||
} else {
|
||||
this.storageLimitValue = parseInt(target.value);
|
||||
}
|
||||
}
|
||||
|
||||
public onBandwidthLimitInput(event: Event): void {
|
||||
const target = event.target as HTMLInputElement;
|
||||
const paidBandwidthCharLimit = this.paidBandwidthLimit.toString().length;
|
||||
|
||||
if (target.value.length > paidBandwidthCharLimit) {
|
||||
const formattedLimit = target.value.slice(0, paidBandwidthCharLimit);
|
||||
this.bandwidthLimitValue = parseInt(formattedLimit);
|
||||
} else if (parseInt(target.value) > this.paidBandwidthLimit) {
|
||||
this.bandwidthLimitValue = this.paidBandwidthLimit;
|
||||
} else {
|
||||
this.bandwidthLimitValue = parseInt(target.value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats value to needed form and returns it.
|
||||
*/
|
||||
private formattedValue(value: Size): string {
|
||||
switch (value.label) {
|
||||
case Dimensions.Bytes:
|
||||
case Dimensions.KB:
|
||||
return '0';
|
||||
default:
|
||||
return `${value.formattedBytes.replace(/\\.0+$/, '')} ${value.label}`;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates project name.
|
||||
*/
|
||||
public async onSaveNameButtonClick(): Promise<void> {
|
||||
try {
|
||||
const updatedProject = new ProjectFields(this.nameValue, '');
|
||||
updatedProject.checkName();
|
||||
|
||||
await this.$store.dispatch(PROJECTS_ACTIONS.UPDATE_NAME, updatedProject);
|
||||
} catch (error) {
|
||||
this.$notify.error(error.message, AnalyticsErrorEventSource.EDIT_PROJECT_DETAILS);
|
||||
return;
|
||||
}
|
||||
|
||||
this.toggleNameEditing();
|
||||
this.analytics.eventTriggered(AnalyticsEvent.PROJECT_NAME_UPDATED);
|
||||
await this.$notify.success('Project name updated successfully!');
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates project description.
|
||||
*/
|
||||
public async onSaveDescriptionButtonClick(): Promise<void> {
|
||||
try {
|
||||
const updatedProject = new ProjectFields('', this.descriptionValue);
|
||||
await this.$store.dispatch(PROJECTS_ACTIONS.UPDATE_DESCRIPTION, updatedProject);
|
||||
} catch (error) {
|
||||
this.$notify.error(error.message, AnalyticsErrorEventSource.EDIT_PROJECT_DETAILS);
|
||||
return;
|
||||
}
|
||||
|
||||
this.toggleDescriptionEditing();
|
||||
this.analytics.eventTriggered(AnalyticsEvent.PROJECT_DESCRIPTION_UPDATED);
|
||||
await this.$notify.success('Project description updated successfully!');
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates project storage limit.
|
||||
*/
|
||||
public async onSaveStorageLimitButtonClick(): Promise<void> {
|
||||
try {
|
||||
let storageLimitValue = this.storageLimitValue;
|
||||
|
||||
if (this.activeStorageMeasurement === Dimensions.GB) {
|
||||
storageLimitValue = storageLimitValue * Number(Memory.GB);
|
||||
} else if (this.activeStorageMeasurement === Dimensions.TB) {
|
||||
storageLimitValue = storageLimitValue * Number(Memory.TB);
|
||||
}
|
||||
|
||||
const updatedProject = new ProjectLimits(0, 0, storageLimitValue);
|
||||
await this.$store.dispatch(PROJECTS_ACTIONS.UPDATE_STORAGE_LIMIT, updatedProject);
|
||||
} catch (error) {
|
||||
this.$notify.error(error.message, AnalyticsErrorEventSource.EDIT_PROJECT_DETAILS);
|
||||
return;
|
||||
}
|
||||
|
||||
this.toggleStorageLimitEditing();
|
||||
this.analytics.eventTriggered(AnalyticsEvent.PROJECT_STORAGE_LIMIT_UPDATED);
|
||||
await this.$notify.success('Project storage limit updated successfully!');
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates project bandwidth limit.
|
||||
*/
|
||||
public async onSaveBandwidthLimitButtonClick(): Promise<void> {
|
||||
try {
|
||||
let bandwidthLimitValue = this.bandwidthLimitValue;
|
||||
|
||||
if (this.activeBandwidthMeasurement === Dimensions.GB) {
|
||||
bandwidthLimitValue = bandwidthLimitValue * Number(Memory.GB);
|
||||
} else if (this.activeBandwidthMeasurement === Dimensions.TB) {
|
||||
bandwidthLimitValue = bandwidthLimitValue * Number(Memory.TB);
|
||||
}
|
||||
|
||||
const updatedProject = new ProjectLimits(bandwidthLimitValue);
|
||||
await this.$store.dispatch(PROJECTS_ACTIONS.UPDATE_BANDWIDTH_LIMIT, updatedProject);
|
||||
} catch (error) {
|
||||
this.$notify.error(error.message, AnalyticsErrorEventSource.EDIT_PROJECT_DETAILS);
|
||||
return;
|
||||
}
|
||||
|
||||
this.toggleBandwidthLimitEditing();
|
||||
this.analytics.eventTriggered(AnalyticsEvent.PROJECT_BANDWIDTH_LIMIT_UPDATED);
|
||||
await this.$notify.success('Project bandwidth limit updated successfully!');
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles project name editing state.
|
||||
*/
|
||||
public toggleNameEditing(): void {
|
||||
this.isNameEditing = !this.isNameEditing;
|
||||
this.nameValue = this.storedProject.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles project description editing state.
|
||||
*/
|
||||
public toggleDescriptionEditing(): void {
|
||||
this.isDescriptionEditing = !this.isDescriptionEditing;
|
||||
this.descriptionValue = this.storedProject.description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles project storage limit editing state.
|
||||
*/
|
||||
public toggleStorageLimitEditing(): void {
|
||||
|
||||
const storageLimitUnit = new Size(this.currentLimits.storageLimit, 2).label;
|
||||
|
||||
if (this.$store.state.usersModule.user.paidTier) {
|
||||
this.isStorageLimitEditing = !this.isStorageLimitEditing;
|
||||
|
||||
if (this.activeStorageMeasurement === Dimensions.TB && storageLimitUnit !== Dimensions.TB) {
|
||||
this.storageLimitValue = this.toTB(parseInt(this.storageLimitMeasurement));
|
||||
} else if (this.activeStorageMeasurement === Dimensions.GB && storageLimitUnit !== Dimensions.GB) {
|
||||
this.storageLimitValue = parseInt(this.storageLimitMeasurement);
|
||||
} else {
|
||||
this.storageLimitValue = parseInt(this.storageLimitMeasurement);
|
||||
}
|
||||
this.activeStorageMeasurement = this.storageMeasurementFormatted;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles project bandwidth limit editing state.
|
||||
*/
|
||||
public toggleBandwidthLimitEditing(): void {
|
||||
const bandwidthLimitUnit = new Size(this.currentLimits.bandwidthLimit, 2).label;
|
||||
|
||||
if (this.$store.state.usersModule.user.paidTier) {
|
||||
this.isBandwidthLimitEditing = !this.isBandwidthLimitEditing;
|
||||
|
||||
if (this.activeBandwidthMeasurement === Dimensions.TB && bandwidthLimitUnit !== Dimensions.TB) {
|
||||
this.bandwidthLimitValue = this.toTB(parseInt(this.bandwidthLimitMeasurement));
|
||||
} else if (this.activeBandwidthMeasurement === Dimensions.GB && bandwidthLimitUnit !== Dimensions.GB) {
|
||||
this.bandwidthLimitValue = parseInt(this.bandwidthLimitMeasurement);
|
||||
} else {
|
||||
this.bandwidthLimitValue = parseInt(this.bandwidthLimitMeasurement);
|
||||
}
|
||||
this.activeBandwidthMeasurement = this.bandwidthMeasurementFormatted;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirects to previous route.
|
||||
*/
|
||||
public onBackClick(): void {
|
||||
const PREVIOUS_ROUTE_NUMBER = -1;
|
||||
|
||||
this.$router.go(PREVIOUS_ROUTE_NUMBER);
|
||||
/**
|
||||
* Check if measurement unit is currently active.
|
||||
*/
|
||||
function isActiveStorageUnit(isTB: boolean): boolean {
|
||||
if (isTB) {
|
||||
return activeStorageMeasurement.value === Dimensions.TB;
|
||||
} else {
|
||||
return activeStorageMeasurement.value === Dimensions.GB;
|
||||
}
|
||||
}
|
||||
|
||||
function isActiveBandwidthUnit(isTB: boolean): boolean {
|
||||
if (isTB) {
|
||||
return activeBandwidthMeasurement.value === Dimensions.TB;
|
||||
} else {
|
||||
return activeBandwidthMeasurement.value === Dimensions.GB;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles the current active unit, and makes input value measurement conversion.
|
||||
*/
|
||||
function toggleStorageMeasurement(isTB: boolean): void {
|
||||
if (isTB) {
|
||||
activeStorageMeasurement.value = Dimensions.TB;
|
||||
storageLimitValue.value = toTB(storageLimitValue.value);
|
||||
} else {
|
||||
activeStorageMeasurement.value = Dimensions.GB;
|
||||
storageLimitValue.value = toGB(storageLimitValue.value);
|
||||
}
|
||||
}
|
||||
|
||||
function toggleBandwidthMeasurement(isTB: boolean): void {
|
||||
if (isTB) {
|
||||
activeBandwidthMeasurement.value = Dimensions.TB;
|
||||
bandwidthLimitValue.value = toTB(bandwidthLimitValue.value);
|
||||
} else {
|
||||
activeBandwidthMeasurement.value = Dimensions.GB;
|
||||
bandwidthLimitValue.value = toGB(bandwidthLimitValue.value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers on limit input.
|
||||
Limits the input value based on default max limit and character limit.
|
||||
*/
|
||||
function onStorageLimitInput(event: Event): void {
|
||||
const target = event.target as HTMLInputElement;
|
||||
const paidStorageCharLimit = paidStorageLimit.value.toString().length;
|
||||
|
||||
if (target.value.length > paidStorageCharLimit) {
|
||||
const formattedLimit = target.value.slice(0, paidStorageCharLimit);
|
||||
storageLimitValue.value = parseInt(formattedLimit);
|
||||
} else if (parseInt(target.value) > paidStorageLimit.value) {
|
||||
storageLimitValue.value = paidStorageLimit.value;
|
||||
} else {
|
||||
storageLimitValue.value = parseInt(target.value);
|
||||
}
|
||||
}
|
||||
|
||||
function onBandwidthLimitInput(event: Event): void {
|
||||
const target = event.target as HTMLInputElement;
|
||||
const paidBandwidthCharLimit = paidBandwidthLimit.value.toString().length;
|
||||
|
||||
if (target.value.length > paidBandwidthCharLimit) {
|
||||
const formattedLimit = target.value.slice(0, paidBandwidthCharLimit);
|
||||
bandwidthLimitValue.value = parseInt(formattedLimit);
|
||||
} else if (parseInt(target.value) > paidBandwidthLimit.value) {
|
||||
bandwidthLimitValue.value = paidBandwidthLimit.value;
|
||||
} else {
|
||||
bandwidthLimitValue.value = parseInt(target.value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats value to needed form and returns it.
|
||||
*/
|
||||
function formattedValue(value: Size): string {
|
||||
switch (value.label) {
|
||||
case Dimensions.Bytes:
|
||||
case Dimensions.KB:
|
||||
return '0';
|
||||
default:
|
||||
return `${value.formattedBytes.replace(/\\.0+$/, '')} ${value.label}`;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates project name.
|
||||
*/
|
||||
async function onSaveNameButtonClick(): Promise<void> {
|
||||
try {
|
||||
const updatedProject = new ProjectFields(nameValue.value, '');
|
||||
updatedProject.checkName();
|
||||
|
||||
await store.dispatch(PROJECTS_ACTIONS.UPDATE_NAME, updatedProject);
|
||||
} catch (error) {
|
||||
notify.error(error.message, AnalyticsErrorEventSource.EDIT_PROJECT_DETAILS);
|
||||
return;
|
||||
}
|
||||
|
||||
toggleNameEditing();
|
||||
analytics.eventTriggered(AnalyticsEvent.PROJECT_NAME_UPDATED);
|
||||
await notify.success('Project name updated successfully!');
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates project description.
|
||||
*/
|
||||
async function onSaveDescriptionButtonClick(): Promise<void> {
|
||||
try {
|
||||
const updatedProject = new ProjectFields('', descriptionValue.value);
|
||||
await store.dispatch(PROJECTS_ACTIONS.UPDATE_DESCRIPTION, updatedProject);
|
||||
} catch (error) {
|
||||
notify.error(error.message, AnalyticsErrorEventSource.EDIT_PROJECT_DETAILS);
|
||||
return;
|
||||
}
|
||||
|
||||
toggleDescriptionEditing();
|
||||
analytics.eventTriggered(AnalyticsEvent.PROJECT_DESCRIPTION_UPDATED);
|
||||
await notify.success('Project description updated successfully!');
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates project storage limit.
|
||||
*/
|
||||
async function onSaveStorageLimitButtonClick(): Promise<void> {
|
||||
try {
|
||||
let storageLimit = storageLimitValue.value;
|
||||
|
||||
if (activeStorageMeasurement.value === Dimensions.GB) {
|
||||
storageLimit = storageLimit * Number(Memory.GB);
|
||||
} else if (activeStorageMeasurement.value === Dimensions.TB) {
|
||||
storageLimit = storageLimit * Number(Memory.TB);
|
||||
}
|
||||
|
||||
const updatedProject = new ProjectLimits(0, 0, storageLimit);
|
||||
await store.dispatch(PROJECTS_ACTIONS.UPDATE_STORAGE_LIMIT, updatedProject);
|
||||
} catch (error) {
|
||||
notify.error(error.message, AnalyticsErrorEventSource.EDIT_PROJECT_DETAILS);
|
||||
return;
|
||||
}
|
||||
|
||||
toggleStorageLimitEditing();
|
||||
analytics.eventTriggered(AnalyticsEvent.PROJECT_STORAGE_LIMIT_UPDATED);
|
||||
await notify.success('Project storage limit updated successfully!');
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates project bandwidth limit.
|
||||
*/
|
||||
async function onSaveBandwidthLimitButtonClick(): Promise<void> {
|
||||
try {
|
||||
let bandwidthLimit = bandwidthLimitValue.value;
|
||||
|
||||
if (activeBandwidthMeasurement.value === Dimensions.GB) {
|
||||
bandwidthLimit = bandwidthLimit * Number(Memory.GB);
|
||||
} else if (activeBandwidthMeasurement.value === Dimensions.TB) {
|
||||
bandwidthLimit = bandwidthLimit * Number(Memory.TB);
|
||||
}
|
||||
|
||||
const updatedProject = new ProjectLimits(bandwidthLimit);
|
||||
await store.dispatch(PROJECTS_ACTIONS.UPDATE_BANDWIDTH_LIMIT, updatedProject);
|
||||
} catch (error) {
|
||||
notify.error(error.message, AnalyticsErrorEventSource.EDIT_PROJECT_DETAILS);
|
||||
return;
|
||||
}
|
||||
|
||||
toggleBandwidthLimitEditing();
|
||||
analytics.eventTriggered(AnalyticsEvent.PROJECT_BANDWIDTH_LIMIT_UPDATED);
|
||||
await notify.success('Project bandwidth limit updated successfully!');
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles project name editing state.
|
||||
*/
|
||||
function toggleNameEditing(): void {
|
||||
isNameEditing.value = !isNameEditing.value;
|
||||
nameValue.value = storedProject.value.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles project description editing state.
|
||||
*/
|
||||
function toggleDescriptionEditing(): void {
|
||||
isDescriptionEditing.value = !isDescriptionEditing.value;
|
||||
descriptionValue.value = storedProject.value.description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles project storage limit editing state.
|
||||
*/
|
||||
function toggleStorageLimitEditing(): void {
|
||||
const storageLimitUnit = new Size(currentLimits.value.storageLimit, 2).label;
|
||||
|
||||
if (store.state.usersModule.user.paidTier) {
|
||||
isStorageLimitEditing.value = !isStorageLimitEditing.value;
|
||||
|
||||
if (activeStorageMeasurement.value === Dimensions.TB && storageLimitUnit !== Dimensions.TB) {
|
||||
storageLimitValue.value = toTB(parseInt(storageLimitMeasurement.value));
|
||||
} else if (activeStorageMeasurement.value === Dimensions.GB && storageLimitUnit !== Dimensions.GB) {
|
||||
storageLimitValue.value = parseInt(storageLimitMeasurement.value);
|
||||
} else {
|
||||
storageLimitValue.value = parseInt(storageLimitMeasurement.value);
|
||||
}
|
||||
activeStorageMeasurement.value = storageMeasurementFormatted.value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles project bandwidth limit editing state.
|
||||
*/
|
||||
function toggleBandwidthLimitEditing(): void {
|
||||
const bandwidthLimitUnit = new Size(currentLimits.value.bandwidthLimit, 2).label;
|
||||
|
||||
if (store.state.usersModule.user.paidTier) {
|
||||
isBandwidthLimitEditing.value = !isBandwidthLimitEditing.value;
|
||||
|
||||
if (activeBandwidthMeasurement.value === Dimensions.TB && bandwidthLimitUnit !== Dimensions.TB) {
|
||||
bandwidthLimitValue.value = toTB(parseInt(bandwidthLimitMeasurement.value));
|
||||
} else if (activeBandwidthMeasurement.value === Dimensions.GB && bandwidthLimitUnit !== Dimensions.GB) {
|
||||
bandwidthLimitValue.value = parseInt(bandwidthLimitMeasurement.value);
|
||||
} else {
|
||||
bandwidthLimitValue.value = parseInt(bandwidthLimitMeasurement.value);
|
||||
}
|
||||
activeBandwidthMeasurement.value = bandwidthMeasurementFormatted.value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirects to previous route.
|
||||
*/
|
||||
function onBackClick(): void {
|
||||
const PREVIOUS_ROUTE_NUMBER = -1;
|
||||
router.go(PREVIOUS_ROUTE_NUMBER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lifecycle hook after initial render.
|
||||
* Fetches project limits and paid tier status.
|
||||
*/
|
||||
onMounted(async (): Promise<void> => {
|
||||
if (!store.getters.selectedProject.id) return;
|
||||
|
||||
if (store.state.usersModule.user.paidTier) {
|
||||
isPaidTier.value = true;
|
||||
}
|
||||
|
||||
try {
|
||||
await store.dispatch(PROJECTS_ACTIONS.GET_LIMITS, store.getters.selectedProject.id);
|
||||
} catch (error) {
|
||||
notify.error(error.message, AnalyticsErrorEventSource.EDIT_PROJECT_DETAILS);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@ -819,7 +806,6 @@ export default class EditProjectDetails extends Vue {
|
||||
height: 8px;
|
||||
background: #f5f6fa;
|
||||
outline: none;
|
||||
transition: 0.2s;
|
||||
transition: opacity 0.2s;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
|
@ -4,8 +4,7 @@
|
||||
import Vuex from 'vuex';
|
||||
import { createLocalVue, shallowMount } from '@vue/test-utils';
|
||||
|
||||
import { ProjectsApiMock } from '../mock/api/projects';
|
||||
|
||||
import { ProjectsApiMock } from '@/../tests/unit/mock/api/projects';
|
||||
import { makeProjectsModule } from '@/store/modules/projects';
|
||||
import { NotificatorPlugin } from '@/utils/plugins/notificator';
|
||||
|
@ -4,8 +4,7 @@
|
||||
import Vuex from 'vuex';
|
||||
import { createLocalVue, shallowMount } from '@vue/test-utils';
|
||||
|
||||
import { ProjectsApiMock } from '../mock/api/projects';
|
||||
|
||||
import { ProjectsApiMock } from '@/../tests/unit/mock/api/projects';
|
||||
import { makeProjectsModule, PROJECTS_MUTATIONS } from '@/store/modules/projects';
|
||||
import { Project, ProjectLimits } from '@/types/projects';
|
||||
import { NotificatorPlugin } from '@/utils/plugins/notificator';
|
@ -1,17 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`CreateProject.vue renders correctly 1`] = `
|
||||
<div class="create-project">
|
||||
<div class="create-project__container">
|
||||
<div class="create-project__container__image-container"><img src="@/../static/images/project/createProject.png" alt="create project" class="create-project__container__image-container__img"></div>
|
||||
<h2 aria-roledescription="title" class="create-project__container__title">Create a Project</h2>
|
||||
<vinput-stub additionallabel="Up To 20 Characters" currentlimit="0" islimitshown="true" initvalue="" label="Project Name" placeholder="Enter Project Name" height="48px" width="100%" error="" maxsymbols="20" roledescription="input-container" class="full-input"></vinput-stub>
|
||||
<vinput-stub additionallabel="Optional" currentlimit="0" islimitshown="true" ismultiline="true" initvalue="" label="Description" placeholder="Enter Project Description" height="100px" width="100%" error="" maxsymbols="100" roledescription="input-container" class="full-input"></vinput-stub>
|
||||
<div class="create-project__container__button-container">
|
||||
<vbutton-stub label="Cancel" width="210px" height="48px" on-press="function () { [native code] }" is-transparent="true" class="create-project__container__button-container__cancel"></vbutton-stub>
|
||||
<vbutton-stub label="Create Project +" width="210px" height="48px" on-press="function () { [native code] }" is-disabled="true"></vbutton-stub>
|
||||
</div>
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
`;
|
@ -1,119 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`EditProjectDetails.vue editing description works correctly 1`] = `
|
||||
<div class="project-details">
|
||||
<div class="project-details__wrapper">
|
||||
<p class="project-details__wrapper__back"><- Back</p>
|
||||
<div class="project-details__wrapper__container">
|
||||
<h1 class="project-details__wrapper__container__title">Project Details</h1>
|
||||
<p class="project-details__wrapper__container__label">Name</p>
|
||||
<div class="project-details__wrapper__container__name-area">
|
||||
<p class="project-details__wrapper__container__name-area__name">new name</p>
|
||||
<vbutton-stub label="Edit" width="64px" height="28px" on-press="function () { [native code] }" is-white="true"></vbutton-stub>
|
||||
</div>
|
||||
<!---->
|
||||
<p class="project-details__wrapper__container__label">Description</p>
|
||||
<!---->
|
||||
<div class="project-details__wrapper__container__description-editing"><input placeholder="Enter a description for your project" class="project-details__wrapper__container__description-editing__input"> <span class="project-details__wrapper__container__description-editing__limit">4/100</span>
|
||||
<vbutton-stub label="Save" width="66px" height="30px" on-press="function () { [native code] }" class="project-details__wrapper__container__description-editing__save-button"></vbutton-stub>
|
||||
</div>
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`EditProjectDetails.vue editing description works correctly 2`] = `
|
||||
<div class="project-details">
|
||||
<div class="project-details__wrapper">
|
||||
<p class="project-details__wrapper__back"><- Back</p>
|
||||
<div class="project-details__wrapper__container">
|
||||
<h1 class="project-details__wrapper__container__title">Project Details</h1>
|
||||
<p class="project-details__wrapper__container__label">Name</p>
|
||||
<div class="project-details__wrapper__container__name-area">
|
||||
<p class="project-details__wrapper__container__name-area__name">new name</p>
|
||||
<vbutton-stub label="Edit" width="64px" height="28px" on-press="function () { [native code] }" is-white="true"></vbutton-stub>
|
||||
</div>
|
||||
<!---->
|
||||
<p class="project-details__wrapper__container__label">Description</p>
|
||||
<div class="project-details__wrapper__container__description-area">
|
||||
<p class="project-details__wrapper__container__description-area__description">new description</p>
|
||||
<vbutton-stub label="Edit" width="64px" height="28px" on-press="function () { [native code] }" class="" is-white="true"></vbutton-stub>
|
||||
</div>
|
||||
<!---->
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`EditProjectDetails.vue editing name works correctly 1`] = `
|
||||
<div class="project-details">
|
||||
<div class="project-details__wrapper">
|
||||
<p class="project-details__wrapper__back"><- Back</p>
|
||||
<div class="project-details__wrapper__container">
|
||||
<h1 class="project-details__wrapper__container__title">Project Details</h1>
|
||||
<p class="project-details__wrapper__container__label">Name</p>
|
||||
<!---->
|
||||
<div class="project-details__wrapper__container__name-editing"><input placeholder="Enter a name for your project" class="project-details__wrapper__container__name-editing__input"> <span class="project-details__wrapper__container__name-editing__limit">4/20</span>
|
||||
<vbutton-stub label="Save" width="66px" height="30px" on-press="function () { [native code] }" class="project-details__wrapper__container__name-editing__save-button"></vbutton-stub>
|
||||
</div>
|
||||
<p class="project-details__wrapper__container__label">Description</p>
|
||||
<div class="project-details__wrapper__container__description-area">
|
||||
<p class="project-details__wrapper__container__description-area__description">test</p>
|
||||
<vbutton-stub label="Edit" width="64px" height="28px" on-press="function () { [native code] }" is-white="true"></vbutton-stub>
|
||||
</div>
|
||||
<!---->
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`EditProjectDetails.vue editing name works correctly 2`] = `
|
||||
<div class="project-details">
|
||||
<div class="project-details__wrapper">
|
||||
<p class="project-details__wrapper__back"><- Back</p>
|
||||
<div class="project-details__wrapper__container">
|
||||
<h1 class="project-details__wrapper__container__title">Project Details</h1>
|
||||
<p class="project-details__wrapper__container__label">Name</p>
|
||||
<div class="project-details__wrapper__container__name-area">
|
||||
<p class="project-details__wrapper__container__name-area__name">new name</p>
|
||||
<vbutton-stub label="Edit" width="64px" height="28px" on-press="function () { [native code] }" class="" is-white="true"></vbutton-stub>
|
||||
</div>
|
||||
<!---->
|
||||
<p class="project-details__wrapper__container__label">Description</p>
|
||||
<div class="project-details__wrapper__container__description-area">
|
||||
<p class="project-details__wrapper__container__description-area__description">test</p>
|
||||
<vbutton-stub label="Edit" width="64px" height="28px" on-press="function () { [native code] }" is-white="true"></vbutton-stub>
|
||||
</div>
|
||||
<!---->
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`EditProjectDetails.vue renders correctly 1`] = `
|
||||
<div class="project-details">
|
||||
<div class="project-details__wrapper">
|
||||
<p class="project-details__wrapper__back"><- Back</p>
|
||||
<div class="project-details__wrapper__container">
|
||||
<h1 class="project-details__wrapper__container__title">Project Details</h1>
|
||||
<p class="project-details__wrapper__container__label">Name</p>
|
||||
<div class="project-details__wrapper__container__name-area">
|
||||
<p class="project-details__wrapper__container__name-area__name">test</p>
|
||||
<vbutton-stub label="Edit" width="64px" height="28px" on-press="function () { [native code] }" is-white="true"></vbutton-stub>
|
||||
</div>
|
||||
<!---->
|
||||
<p class="project-details__wrapper__container__label">Description</p>
|
||||
<div class="project-details__wrapper__container__description-area">
|
||||
<p class="project-details__wrapper__container__description-area__description">test</p>
|
||||
<vbutton-stub label="Edit" width="64px" height="28px" on-press="function () { [native code] }" is-white="true"></vbutton-stub>
|
||||
</div>
|
||||
<!---->
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
Loading…
Reference in New Issue
Block a user