web/satellite: migrated Vue 2 to Vue 3

Finally migrated web/satellite UI to use Vue 3.

Issue:
https://github.com/storj/storj/issues/5862

Change-Id: I609e2332142b9092d6efeb2d4b931e34cce846cc
This commit is contained in:
Vitalii 2023-05-16 15:09:46 +03:00 committed by Storj Robot
parent 958d8676d0
commit ace0ef89a2
184 changed files with 7641 additions and 5656 deletions

View File

@ -424,7 +424,7 @@ func (server *Server) appHandler(w http.ResponseWriter, r *http.Request) {
"frame-src 'self' *.stripe.com https://www.google.com/recaptcha/ https://recaptcha.google.com/recaptcha/ https://hcaptcha.com *.hcaptcha.com",
"img-src 'self' data: blob: *.tardigradeshare.io *.storjshare.io",
// Those are hashes of charts custom tooltip inline styles. They have to be updated if styles are updated.
"style-src 'unsafe-hashes' 'sha256-7mY2NKmZ4PuyjGUa4FYC5u36SxXdoUM/zxrlr3BEToo=' 'sha256-PRTMwLUW5ce9tdiUrVCGKqj6wPeuOwGogb1pmyuXhgI=' 'sha256-kwpt3lQZ21rs4cld7/uEm9qI5yAbjYzx+9FGm/XmwNU=' 'self' https://hcaptcha.com *.hcaptcha.com",
"style-src 'unsafe-hashes' 'sha256-7mY2NKmZ4PuyjGUa4FYC5u36SxXdoUM/zxrlr3BEToo=' 'sha256-PRTMwLUW5ce9tdiUrVCGKqj6wPeuOwGogb1pmyuXhgI=' 'sha256-kwpt3lQZ21rs4cld7/uEm9qI5yAbjYzx+9FGm/XmwNU=' 'sha256-Qf4xqtNKtDLwxce6HLtD5Y6BWpOeR7TnDpNSo+Bhb3s=' 'self' https://hcaptcha.com *.hcaptcha.com",
"media-src 'self' blob: *.tardigradeshare.io *.storjshare.io",
}

View File

@ -81,11 +81,13 @@ module.exports = {
'vue/html-button-has-type': ['error'],
'vue/no-unused-properties': ['warn'],
'vue/no-unused-refs': ['warn'],
'vue/no-unused-vars': ['warn'],
'vue/no-useless-v-bind': ['warn'],
'vue/no-useless-template-attributes': ['off'], // TODO: fix later
'vue/no-multiple-template-root': ['off'], // it's possible to have multiple roots in template in Vue 3
'vue/no-unregistered-components': ['warn', { ignorePatterns: ['router-link', 'router-view'] }],
'vue/no-undef-components': ['warn', { ignorePatterns: ['router-link', 'router-view'] }],
'storj/vue/require-annotation': 'warn',

View File

@ -11,4 +11,10 @@ module.exports = {
'^.+\\.svg$': '<rootDir>/tests/unit/mock/svgTransform.js',
},
modulePathIgnorePatterns: ['<rootDir>/tests/unit/ignore'],
moduleFileExtensions: [
'js',
'ts',
'json',
'vue',
],
};

File diff suppressed because it is too large Load Diff

View File

@ -13,66 +13,62 @@
"test": "vue-cli-service test:unit"
},
"dependencies": {
"@apollo/client": "3.7.2",
"@hcaptcha/vue-hcaptcha": "0.3.2",
"aws-sdk": "2.1128.0",
"bip39": "3.0.4",
"@apollo/client": "3.7.14",
"@hcaptcha/vue3-hcaptcha": "1.2.1",
"aws-sdk": "2.1377.0",
"bip39": "3.1.0",
"chart.js": "4.2.1",
"core-js": "3.22.4",
"core-js": "3.30.2",
"graphql": "15.3.0",
"pinia": "2.0.23",
"pretty-bytes": "5.6.0",
"qrcode": "1.5.0",
"qrcode": "1.5.3",
"stream-browserify": "3.0.0",
"stripe": "8.215.0",
"util": "0.12.4",
"vue": "2.7.10",
"vue-fragment": "1.6.0",
"vue-recaptcha": "1.3.0",
"vue-router": "3.5.3",
"vue2-datepicker": "3.10.4"
"util": "0.12.5",
"vue": "3.3.2",
"vue-datepicker-next": "1.0.3",
"vue-router": "4.2.0"
},
"devDependencies": {
"@types/filesystem": "0.0.32",
"@types/jest": "27.5.0",
"@types/jest": "27.5.2",
"@types/node": "16.18.14",
"@types/qrcode": "1.4.2",
"@types/vue2-datepicker": "3.3.1",
"@typescript-eslint/eslint-plugin": "5.22.0",
"@typescript-eslint/parser": "5.22.0",
"@vue/cli-plugin-babel": "5.0.4",
"@vue/cli-plugin-eslint": "5.0.4",
"@vue/cli-plugin-typescript": "5.0.4",
"@vue/cli-plugin-unit-jest": "5.0.4",
"@vue/cli-service": "5.0.4",
"@vue/eslint-config-typescript": "10.0.0",
"@vue/test-utils": "1.3.0",
"@vue/vue2-jest": "27.0.0",
"@types/qrcode": "1.5.0",
"@typescript-eslint/eslint-plugin": "5.59.5",
"@typescript-eslint/parser": "5.59.5",
"@vue/cli-plugin-babel": "5.0.8",
"@vue/cli-plugin-eslint": "5.0.8",
"@vue/cli-plugin-typescript": "5.0.8",
"@vue/cli-plugin-unit-jest": "5.0.8",
"@vue/cli-service": "5.0.8",
"@vue/eslint-config-typescript": "11.0.3",
"@vue/test-utils": "2.3.2",
"@vue/vue3-jest": "27.0.0",
"babel-core": "7.0.0-bridge.0",
"babel-jest": "27.5.1",
"compression-webpack-plugin": "9.2.0",
"eslint": "8.14.0",
"eslint": "8.40.0",
"eslint-import-resolver-custom-alias": "1.3.0",
"eslint-import-resolver-typescript": "2.7.1",
"eslint-plugin-import": "2.26.0",
"eslint-import-resolver-typescript": "3.5.5",
"eslint-plugin-import": "2.27.5",
"eslint-plugin-storj": "0.0.2",
"eslint-plugin-vue": "8.7.1",
"eslint-plugin-vue": "9.12.0",
"jest": "27.5.1",
"jest-fetch-mock": "3.0.3",
"postcss-html": "1.4.1",
"sass": "1.51.0",
"sass-loader": "12.6.0",
"stylelint": "14.8.2",
"stylelint-config-standard": "25.0.0",
"stylelint-config-standard-scss": "3.0.0",
"postcss-html": "1.5.0",
"sass": "1.62.1",
"sass-loader": "13.2.2",
"stylelint": "15.6.1",
"stylelint-config-standard": "33.0.0",
"stylelint-config-standard-scss": "9.0.0",
"stylelint-config-standard-vue": "1.0.0",
"stylelint-scss": "4.2.0",
"ts-jest": "27.1.4",
"typescript": "4.6.4",
"vue-eslint-parser": "9.0.3",
"stylelint-scss": "5.0.0",
"ts-jest": "27.1.5",
"typescript": "4.9.5",
"vue-eslint-parser": "9.2.1",
"vue-svg-loader": "0.17.0-beta.2",
"vue-template-compiler": "2.7.10",
"webpack-bundle-analyzer": "4.5.0"
"webpack-bundle-analyzer": "4.8.0"
},
"postcss": {
"plugins": {

View File

@ -31,7 +31,7 @@ const isLoading = ref<boolean>(true);
/**
* Indicates whether an error page should be shown in place of the router view.
*/
const isErrorPageShown = computed((): boolean => {
const isErrorPageShown = computed<boolean>((): boolean => {
return appStore.state.error.visible;
});

View File

@ -157,6 +157,7 @@
</template>
<script setup lang="ts">
import { computed, onBeforeUnmount, onMounted, ref } from 'vue';
import { useRouter } from 'vue-router';
import AccessGrantsHeader from './AccessGrantsHeader.vue';
@ -165,7 +166,7 @@ import { AccessGrant } from '@/types/accessGrants';
import { AnalyticsHttpApi } from '@/api/analytics';
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
import { AccessType } from '@/types/createAccessGrant';
import { useNotify, useRouter } from '@/utils/hooks';
import { useNotify } from '@/utils/hooks';
import { useAccessGrantsStore } from '@/store/modules/accessGrantsStore';
import { useProjectsStore } from '@/store/modules/projectsStore';
import { useAppStore } from '@/store/modules/appStore';
@ -298,7 +299,7 @@ function accessGrantClick(): void {
trackPageVisit(RouteConfig.AccessGrants.with(RouteConfig.CreateAccessModal).path);
router.push({
name: RouteConfig.CreateAccessModal.name,
params: { accessType: AccessType.AccessGrant },
query: { accessType: AccessType.AccessGrant },
});
}
@ -310,7 +311,7 @@ function s3Click(): void {
trackPageVisit(RouteConfig.AccessGrants.with(RouteConfig.CreateAccessModal).path);
router.push({
name: RouteConfig.CreateAccessModal.name,
params: { accessType: AccessType.S3 },
query: { accessType: AccessType.S3 },
});
}
@ -322,7 +323,7 @@ function cliClick(): void {
trackPageVisit(RouteConfig.AccessGrants.with(RouteConfig.CreateAccessModal).path);
router.push({
name: RouteConfig.CreateAccessModal.name,
params: { accessType: AccessType.APIKey },
query: { accessType: AccessType.APIKey },
});
}
@ -364,7 +365,7 @@ onBeforeUnmount(() => {
border-radius: 10px;
min-width: 175px;
@media screen and (max-width: 930px) {
@media screen and (width <= 930px) {
width: 100%;
}
}
@ -413,7 +414,7 @@ onBeforeUnmount(() => {
&__cli-credentials {
@include grant-flow-card;
@media screen and (max-width: 370px) {
@media screen and (width <= 370px) {
.access-grants__flows-area__button-container {
flex-direction: column;
@ -471,7 +472,7 @@ onBeforeUnmount(() => {
.access-grants-items {
padding-bottom: 55px;
@media screen and (max-width: 1150px) {
@media screen and (width <= 1150px) {
margin-top: -45px;
}

View File

@ -2,48 +2,45 @@
// See LICENSE for copying information.
<template>
<fragment>
<th
class="align-left"
@mouseover="mouseOver(AccessGrantsOrderBy.NAME)"
@mouseleave="mouseLeave"
@click="sortBy(AccessGrantsOrderBy.NAME)"
>
<span class="header__item">
<span>Name</span>
<span :class="{ invisible: nameSortData.isHidden }">
<a v-if="nameSortData.isDesc" class="arrow">
<desc-icon />
</a>
<a v-else class="arrow">
<asc-icon />
</a>
</span>
<th
class="align-left"
@mouseover="mouseOver(AccessGrantsOrderBy.NAME)"
@mouseleave="mouseLeave"
@click="sortBy(AccessGrantsOrderBy.NAME)"
>
<span class="header__item">
<span>Name</span>
<span :class="{ invisible: nameSortData.isHidden }">
<a v-if="nameSortData.isDesc" class="arrow">
<desc-icon />
</a>
<a v-else class="arrow">
<asc-icon />
</a>
</span>
</th>
<th
class="align-left"
@mouseover="mouseOver(AccessGrantsOrderBy.CREATED_AT)"
@mouseleave="mouseLeave"
@click="sortBy(AccessGrantsOrderBy.CREATED_AT)"
>
<span class="header__item">
<span>Date Created</span>
<span :class="{ invisible: dateSortData.isHidden }">
<a v-if="dateSortData.isDesc" class="arrow">
<desc-icon />
</a>
<a v-else class="arrow">
<asc-icon />
</a>
</span>
</span>
</th>
<th
class="align-left"
@mouseover="mouseOver(AccessGrantsOrderBy.CREATED_AT)"
@mouseleave="mouseLeave"
@click="sortBy(AccessGrantsOrderBy.CREATED_AT)"
>
<span class="header__item">
<span>Date Created</span>
<span :class="{ invisible: dateSortData.isHidden }">
<a v-if="dateSortData.isDesc" class="arrow">
<desc-icon />
</a>
<a v-else class="arrow">
<asc-icon />
</a>
</span>
</th>
</fragment>
</span>
</th>
</template>
<script setup lang="ts">
import { Fragment } from 'vue-fragment';
import { computed, ref } from 'vue';
import { useNotify } from '@/utils/hooks';

View File

@ -6,15 +6,17 @@
:item="itemToRender"
:on-click="onClick"
>
<th slot="options" v-click-outside="closeDropdown" class="grant-item__functional options overflow-visible" @click.stop="openDropdown">
<dots-icon />
<div v-if="isDropdownOpen" class="grant-item__functional__dropdown">
<div class="grant-item__functional__dropdown__item" @click.stop="onDeleteClick">
<delete-icon />
<p class="grant-item__functional__dropdown__item__label">Delete Access</p>
<template #options>
<th v-click-outside="closeDropdown" class="grant-item__functional options overflow-visible" @click.stop="openDropdown">
<dots-icon />
<div v-if="isDropdownOpen" class="grant-item__functional__dropdown">
<div class="grant-item__functional__dropdown__item" @click.stop="onDeleteClick">
<delete-icon />
<p class="grant-item__functional__dropdown__item__label">Delete Access</p>
</div>
</div>
</div>
</th>
</th>
</template>
</table-item>
</template>
@ -124,7 +126,7 @@ async function onDeleteClick(): Promise<void> {
max-width: 25rem;
}
@media screen and (max-width: 940px) {
@media screen and (width <= 940px) {
:deep(th) {
max-width: 10rem;

View File

@ -48,7 +48,6 @@
/>
<EnterPassphraseStep
v-if="step === CreateAccessStep.EnterMyPassphrase"
:is-new-passphrase="false"
:on-back="() => setStep(CreateAccessStep.AccessEncryption)"
:on-continue="() => setStep(CreateAccessStep.ConfirmDetails)"
:passphrase="enteredPassphrase"
@ -57,7 +56,7 @@
/>
<EnterPassphraseStep
v-if="step === CreateAccessStep.EnterNewPassphrase"
:is-new-passphrase="true"
is-new-passphrase
:on-back="() => setStep(CreateAccessStep.AccessEncryption)"
:on-continue="() => setStep(CreateAccessStep.ConfirmDetails)"
:passphrase="enteredPassphrase"
@ -107,10 +106,11 @@
</template>
<script setup lang="ts">
import { computed, onMounted, reactive, ref } from 'vue';
import { computed, onMounted, ref } from 'vue';
import { generateMnemonic } from 'bip39';
import { useRoute, useRouter } from 'vue-router';
import { useNotify, useRouter } from '@/utils/hooks';
import { useNotify } from '@/utils/hooks';
import { RouteConfig } from '@/router';
import {
AccessType,
@ -146,8 +146,8 @@ const bucketsStore = useBucketsStore();
const agStore = useAccessGrantsStore();
const appStore = useAppStore();
const projectsStore = useProjectsStore();
const nativeRouter = useRouter();
const router = reactive(nativeRouter);
const router = useRouter();
const route = useRoute();
const notify = useNotify();
const initPermissions = [
@ -467,12 +467,12 @@ async function createCLIAccess(): Promise<void> {
try {
await agStore.getAccessGrants(FIRST_PAGE, projectID);
} catch (error) {
await notify.error(`Unable to fetch Access Grants. ${error.message}`, AnalyticsErrorEventSource.CREATE_AG_MODAL);
notify.error(`Unable to fetch Access Grants. ${error.message}`, AnalyticsErrorEventSource.CREATE_AG_MODAL);
}
let permissionsMsg = {
'type': 'SetPermission',
'buckets': selectedBuckets.value,
'buckets': JSON.stringify(selectedBuckets.value),
'apiKey': cleanAPIKey.secret,
'isDownload': selectedPermissions.value.includes(Permission.Read),
'isUpload': selectedPermissions.value.includes(Permission.Write),
@ -618,8 +618,8 @@ async function setLastStep(): Promise<void> {
}
onMounted(async () => {
if (router.currentRoute.params.accessType) {
selectedAccessTypes.value.push(router.currentRoute.params.accessType as AccessType);
if (route.query.accessType) {
selectedAccessTypes.value.push(route.query.accessType as AccessType);
}
setWorker();
@ -641,7 +641,7 @@ onMounted(async () => {
flex-direction: column;
position: relative;
@media screen and (max-width: 460px) {
@media screen and (width <= 460px) {
width: 280px;
padding: 16px;
}
@ -652,7 +652,7 @@ onMounted(async () => {
padding-bottom: 16px;
border-bottom: 1px solid var(--c-grey-2);
@media screen and (max-width: 460px) {
@media screen and (width <= 460px) {
flex-direction: column;
align-items: flex-start;
}
@ -666,7 +666,7 @@ onMounted(async () => {
color: var(--c-black);
text-align: left;
@media screen and (max-width: 460px) {
@media screen and (width <= 460px) {
margin: 10px 0 0;
}
}
@ -674,10 +674,7 @@ onMounted(async () => {
&__blur {
position: absolute;
left: 0;
right: 0;
bottom: 0;
top: 0;
inset: 0;
background-color: rgb(0 0 0 / 10%);
border-radius: 10px;
}

View File

@ -37,7 +37,7 @@ const props = withDefaults(defineProps<{
column-gap: 16px;
display: flex;
@media screen and (max-width: 460px) {
@media screen and (width <= 460px) {
flex-direction: column-reverse;
column-gap: unset;
row-gap: 10px;

View File

@ -140,14 +140,13 @@ function onOneYearClick(): void {
top: 100%;
left: 0;
display: flex;
align-items: center;
cursor: default;
@media screen and (max-width: 600px) {
@media screen and (width <= 600px) {
left: -90px;
}
@media screen and (max-width: 460px) {
@media screen and (width <= 460px) {
flex-direction: column;
width: 320px;
left: -78px;
@ -158,7 +157,7 @@ function onOneYearClick(): void {
padding-left: 0;
margin-top: 0;
@media screen and (max-width: 460px) {
@media screen and (width <= 460px) {
columns: 2;
width: 100%;
}
@ -170,6 +169,7 @@ function onOneYearClick(): void {
color: var(--c-grey-8);
cursor: pointer;
white-space: nowrap;
line-height: 33px;
&:hover {
font-weight: bold;

View File

@ -76,7 +76,7 @@ const props = withDefaults(defineProps<{
filter: none;
transform: rotate(-180deg);
@media screen and (max-width: 530px) {
@media screen and (width <= 530px) {
left: unset;
right: -5px;
}
@ -95,7 +95,7 @@ const props = withDefaults(defineProps<{
height: 10px;
margin-bottom: -3px;
@media screen and (max-width: 530px) {
@media screen and (width <= 530px) {
margin-right: 245px;
}
}

View File

@ -161,7 +161,7 @@ const props = withDefaults(defineProps<{
filter: none;
transform: rotate(-180deg);
@media screen and (max-width: 460px) {
@media screen and (width <= 460px) {
left: unset;
right: -83px;
}
@ -180,7 +180,7 @@ const props = withDefaults(defineProps<{
height: 10px;
margin-bottom: -3px;
@media screen and (max-width: 460px) {
@media screen and (width <= 460px) {
margin-right: 88px;
}
}

View File

@ -150,10 +150,7 @@ function onCopy(): void {
&__blur {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
inset: 0;
display: flex;
align-items: center;
justify-content: center;

View File

@ -63,8 +63,9 @@
<script setup lang="ts">
import { computed, ref } from 'vue';
import { useRouter } from 'vue-router';
import { useNotify, useRouter } from '@/utils/hooks';
import { useNotify } from '@/utils/hooks';
import { AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
import { Download } from '@/utils/download';
import { AnalyticsHttpApi } from '@/api/analytics';

View File

@ -190,7 +190,7 @@ function isSelectedOption(option: PassphraseOption): boolean {
align-items: flex-start;
margin-top: 16px;
@media screen and (max-width: 460px) {
@media screen and (width <= 460px) {
flex-direction: column;
}
@ -198,7 +198,7 @@ function isSelectedOption(option: PassphraseOption): boolean {
min-width: 32px;
margin-right: 16px;
@media screen and (max-width: 460px) {
@media screen and (width <= 460px) {
margin: 0 0 16px;
}
}

View File

@ -69,8 +69,9 @@
<script setup lang="ts">
import { ref, computed } from 'vue';
import { useRouter } from 'vue-router';
import { useNotify, useRouter } from '@/utils/hooks';
import { useNotify } from '@/utils/hooks';
import { AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
import { Download } from '@/utils/download';
import { AnalyticsHttpApi } from '@/api/analytics';

View File

@ -57,7 +57,7 @@ import VInput from '@/components/common/VInput.vue';
const props = withDefaults(defineProps<{
isProjectPassphrase?: boolean;
isNewPassphrase: boolean;
isNewPassphrase?: boolean;
info: string;
passphrase: string;
setPassphrase: (value: string) => void;
@ -65,6 +65,7 @@ const props = withDefaults(defineProps<{
onContinue: () => void;
}>(), {
isProjectPassphrase: false,
isNewPassphrase: false,
});
const isPassphraseSaved = ref<boolean>(false);

View File

@ -76,8 +76,9 @@
<script setup lang="ts">
import { ref } from 'vue';
import { useRouter } from 'vue-router';
import { useNotify, useRouter } from '@/utils/hooks';
import { useNotify } from '@/utils/hooks';
import { AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
import { Download } from '@/utils/download';
import { AnalyticsHttpApi } from '@/api/analytics';

View File

@ -100,11 +100,12 @@
<script setup lang="ts">
import { computed, onMounted } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { User } from '@/types/users';
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
import { MODALS } from '@/utils/constants/appStatePopUps';
import { useNotify, useRouter } from '@/utils/hooks';
import { useNotify } from '@/utils/hooks';
import { useLoading } from '@/composables/useLoading';
import { Duration } from '@/utils/time';
import { useUsersStore } from '@/store/modules/usersStore';
@ -121,6 +122,7 @@ const configStore = useConfigStore();
const projectsStore = useProjectsStore();
const notify = useNotify();
const router = useRouter();
const route = useRoute();
const { isLoading, withLoading } = useLoading();
/**
@ -141,7 +143,7 @@ const userDuration = computed((): Duration | null => {
* Returns whether we're on the settings page on the all projects dashboard.
*/
const isOnAllDashboardSettings = computed((): boolean => {
return router.currentRoute.path.includes(RouteConfig.AccountSettings.path);
return route.path.includes(RouteConfig.AccountSettings.path);
});
/**
@ -258,7 +260,7 @@ onMounted(() => {
grid-template-columns: 1fr 1fr 1fr;
align-items: center;
@media screen and (max-width: 500px) {
@media screen and (width <= 500px) {
display: flex;
flex-direction: column;
align-items: flex-start;
@ -286,7 +288,7 @@ onMounted(() => {
justify-content: flex-end;
gap: 5px;
@media screen and (max-width: 500px) {
@media screen and (width <= 500px) {
width: 100%;
justify-content: flex-start;
}

View File

@ -355,7 +355,7 @@ onMounted(() => {
word-break: break-all;
}
@media screen and (max-width: 1300px) {
@media screen and (width <= 1300px) {
.settings {
@ -376,7 +376,7 @@ onMounted(() => {
}
}
@media screen and (max-height: 825px) {
@media screen and (height <= 825px) {
.settings {
height: 535px;
@ -396,7 +396,7 @@ onMounted(() => {
}
}
@media screen and (max-width: 650px) {
@media screen and (width <= 650px) {
.settings__secondary-container__change-password__text-container {
margin: 0;
@ -408,7 +408,7 @@ onMounted(() => {
}
}
@media screen and (max-width: 460px) {
@media screen and (width <= 460px) {
.settings__edit-profile,
.settings__secondary-container__change-password,

View File

@ -40,14 +40,15 @@
</template>
<script setup lang="ts">
import { computed, onMounted, reactive } from 'vue';
import { computed, onMounted } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { RouteConfig } from '@/router';
import { AnalyticsHttpApi } from '@/api/analytics';
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
import { APP_STATE_DROPDOWNS } from '@/utils/constants/appStatePopUps';
import { NavigationLink } from '@/types/navigation';
import { useNotify, useRouter } from '@/utils/hooks';
import { useNotify } from '@/utils/hooks';
import { useBillingStore } from '@/store/modules/billingStore';
import { useAppStore } from '@/store/modules/appStore';
import { useConfigStore } from '@/store/modules/configStore';
@ -58,8 +59,8 @@ const billingStore = useBillingStore();
const configStore = useConfigStore();
const projectsStore = useProjectsStore();
const notify = useNotify();
const nativeRouter = useRouter();
const router = reactive(nativeRouter);
const router = useRouter();
const route = useRoute();
const analytics: AnalyticsHttpApi = new AnalyticsHttpApi();
@ -81,7 +82,7 @@ const isBalanceDropdownShown = computed((): boolean => {
* Returns whether we're on the settings/billing page on the all projects dashboard.
*/
const isOnAllDashboardSettings = computed((): boolean => {
return router.currentRoute.path.includes(RouteConfig.AccountSettings.path);
return route.path.includes(RouteConfig.AccountSettings.path);
});
/**
@ -99,7 +100,7 @@ const baseAccountRoute = computed((): NavigationLink => {
* Whether current route name contains term.
*/
function routeHas(term: string): boolean {
return !!router.currentRoute.name?.toLowerCase().includes(term);
return (route.name as string).toLowerCase().includes(term);
}
/**
@ -116,7 +117,7 @@ function closeDropdown(): void {
*/
function routeToOverview(): void {
const overviewPath = baseAccountRoute.value.with(RouteConfig.Billing).with(RouteConfig.BillingOverview).path;
if (router.currentRoute.path !== overviewPath) {
if (route.path !== overviewPath) {
analytics.pageVisit(overviewPath);
router.push(overviewPath);
}
@ -124,7 +125,7 @@ function routeToOverview(): void {
function routeToPaymentMethods(): void {
const payMethodsPath = baseAccountRoute.value.with(RouteConfig.Billing).with(RouteConfig.BillingPaymentMethods).path;
if (router.currentRoute.path !== payMethodsPath) {
if (route.path !== payMethodsPath) {
analytics.pageVisit(payMethodsPath);
router.push(payMethodsPath);
}
@ -132,7 +133,7 @@ function routeToPaymentMethods(): void {
function routeToBillingHistory(): void {
const billingPath = baseAccountRoute.value.with(RouteConfig.Billing).with(RouteConfig.BillingHistory).path;
if (router.currentRoute.path !== billingPath) {
if (route.path !== billingPath) {
analytics.pageVisit(billingPath);
router.push(billingPath);
}
@ -140,7 +141,7 @@ function routeToBillingHistory(): void {
function routeToCoupons(): void {
const couponsPath = baseAccountRoute.value.with(RouteConfig.Billing).with(RouteConfig.BillingCoupons).path;
if (router.currentRoute.path !== couponsPath) {
if (route.path !== couponsPath) {
analytics.pageVisit(couponsPath);
router.push(couponsPath);
}
@ -159,7 +160,7 @@ onMounted(async (): Promise<void> => {
try {
await billingStore.getBalance();
} catch (error) {
await notify.error(error.message, AnalyticsErrorEventSource.BILLING_AREA);
notify.error(error.message, AnalyticsErrorEventSource.BILLING_AREA);
}
});
</script>
@ -384,7 +385,7 @@ onMounted(async (): Promise<void> => {
margin-left: 10px;
}
@media only screen and (max-width: 625px) {
@media only screen and (width <= 625px) {
.account-billing-area__header__div {
margin-right: -24px;

View File

@ -2,14 +2,10 @@
// See LICENSE for copying information.
<template>
<v-fragment>
<th class="align-left">DATE</th>
<th class="align-left">STATUS</th>
<th class="align-left">AMOUNT</th>
<th class="align-left">DOWNLOAD</th>
</v-fragment>
<th class="align-left">DATE</th>
<th class="align-left">STATUS</th>
<th class="align-left">AMOUNT</th>
<th class="align-left">DOWNLOAD</th>
</template>
<script setup lang="ts">
import { Fragment as VFragment } from 'vue-fragment';
</script>
<script setup lang="ts"></script>

View File

@ -18,34 +18,30 @@
</p>
</div>
</th>
<v-fragment>
<th class="align-left data tablet-laptop">
<p class="date">
<span><Calendar /></span>
<span>{{ item.formattedStart }}</span>
</p>
</th>
<th class="align-left data tablet-laptop">
<p class="status">
<span v-if="item.status === 'paid'"> <CheckIcon class="checkmark" /> </span>
<span>{{ item.formattedStatus }}</span>
</p>
</th>
<th class="align-left data tablet-laptop">
<p>
{{ centsToDollars(item.amount) }}
</p>
</th>
<th class="align-left data tablet-laptop">
<a :href="item.link" target="_blank" rel="noreferrer noopener" download>Invoice PDF</a>
</th>
</v-fragment>
<th class="align-left data tablet-laptop">
<p class="date">
<span><Calendar /></span>
<span>{{ item.formattedStart }}</span>
</p>
</th>
<th class="align-left data tablet-laptop">
<p class="status">
<span v-if="item.status === 'paid'"> <CheckIcon class="checkmark" /> </span>
<span>{{ item.formattedStatus }}</span>
</p>
</th>
<th class="align-left data tablet-laptop">
<p>
{{ centsToDollars(item.amount) }}
</p>
</th>
<th class="align-left data tablet-laptop">
<a :href="item.link" target="_blank" rel="noreferrer noopener" download>Invoice PDF</a>
</th>
</tr>
</template>
<script setup lang="ts">
import { Fragment as VFragment } from 'vue-fragment';
import { centsToDollars } from '@/utils/strings';
import { PaymentsHistoryItem, PaymentsHistoryItemStatus } from '@/types/payments';
import { AnalyticsHttpApi } from '@/api/analytics';
@ -110,7 +106,7 @@ function downloadInvoice() {
}
}
@media only screen and (max-width: 425px) {
@media only screen and (width <= 425px) {
.mobile {
display: table-cell;
@ -121,7 +117,7 @@ function downloadInvoice() {
}
}
@media only screen and (min-width: 426px) {
@media only screen and (width >= 426px) {
.tablet-laptop {
display: table-cell;

View File

@ -109,7 +109,7 @@ const couponCodeBillingUIEnabled = computed((): boolean => {
* Opens Add Coupon modal.
*/
function toggleCreateModal(): void {
if (!couponCodeBillingUIEnabled) {
if (!couponCodeBillingUIEnabled.value) {
return;
}
analytics.eventTriggered(AnalyticsEvent.APPLY_NEW_COUPON_CLICKED);
@ -242,7 +242,7 @@ onMounted(async () => {
}
}
@media only screen and (max-width: 768px) {
@media only screen and (width <= 768px) {
.coupon-area__wrapper {
flex-direction: column;

View File

@ -90,6 +90,7 @@
<script setup lang="ts">
import { computed, onMounted, ref } from 'vue';
import { useRouter } from 'vue-router';
import { centsToDollars } from '@/utils/strings';
import { RouteConfig } from '@/router';
@ -97,7 +98,7 @@ import { SHORT_MONTHS_NAMES } from '@/utils/constants/date';
import { AccountBalance } from '@/types/payments';
import { AnalyticsHttpApi } from '@/api/analytics';
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
import { useNotify, useRouter } from '@/utils/hooks';
import { useNotify } from '@/utils/hooks';
import { useBillingStore } from '@/store/modules/billingStore';
import { useProjectsStore } from '@/store/modules/projectsStore';
@ -163,7 +164,7 @@ function routeToPaymentMethods(): void {
function balanceClicked(): void {
router.push({
name: RouteConfig.Account.with(RouteConfig.Billing).with(RouteConfig.BillingPaymentMethods).name,
params: { action: hasZeroCoins.value ? 'add tokens' : 'token history' },
query: { action: hasZeroCoins.value ? 'add tokens' : 'token history' },
});
}
@ -190,7 +191,7 @@ onMounted(async () => {
isDataFetching.value = false;
const rawDate = new Date();
let currentYear = rawDate.getFullYear();
const currentYear = rawDate.getFullYear();
currentDate.value = `${SHORT_MONTHS_NAMES[rawDate.getMonth()]} ${currentYear}`;
});
</script>
@ -224,11 +225,11 @@ onMounted(async () => {
gap: 10px;
margin-top: 20px;
@media screen and (max-width: 786px) {
@media screen and (width <= 786px) {
grid-template-columns: 1fr 1fr;
}
@media screen and (max-width: 425px) {
@media screen and (width <= 425px) {
grid-template-columns: auto;
}
}
@ -274,7 +275,7 @@ onMounted(async () => {
top: 5px;
left: 86px;
@media screen and (max-width: 635px) {
@media screen and (width <= 635px) {
top: 5px;
left: -21px;
}
@ -294,7 +295,7 @@ onMounted(async () => {
&:after {
left: 50%;
@media screen and (max-width: 635px) {
@media screen and (width <= 635px) {
left: 90%;
}

View File

@ -177,8 +177,9 @@
</template>
<script setup lang="ts">
import { computed, nextTick, onMounted, reactive, ref } from 'vue';
import { computed, nextTick, onMounted, ref } from 'vue';
import QRCode from 'qrcode';
import { useRoute, useRouter } from 'vue-router';
import {
CreditCard,
@ -188,7 +189,7 @@ import {
import { RouteConfig } from '@/router';
import { AnalyticsHttpApi } from '@/api/analytics';
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
import { useNotify, useRouter } from '@/utils/hooks';
import { useNotify } from '@/utils/hooks';
import { useUsersStore } from '@/store/modules/usersStore';
import { useBillingStore } from '@/store/modules/billingStore';
import { useAppStore } from '@/store/modules/appStore';
@ -233,8 +234,8 @@ const usersStore = useUsersStore();
const appStore = useAppStore();
const projectsStore = useProjectsStore();
const notify = useNotify();
const nativeRouter = useRouter();
const router = reactive(nativeRouter);
const router = useRouter();
const route = useRoute();
const emit = defineEmits(['toggleIsLoading', 'toggleIsLoaded', 'cancel']);
@ -485,7 +486,7 @@ function paginationController(i: number, limit: number): void {
}
onMounted((): void => {
if (router.currentRoute.params.action === 'token history') {
if (route.query.action === 'token history') {
showTransactionsTable();
}
});
@ -645,10 +646,7 @@ $align: center;
.edit_payment_method {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
inset: 0;
z-index: 100;
background: rgb(27 37 51 / 75%);
display: $flex;
@ -927,7 +925,7 @@ $align: center;
text-overflow: ellipsis;
overflow: hidden;
@media screen and (max-width: 375px) {
@media screen and (width <= 375px) {
width: 16rem;
}
}

View File

@ -2,49 +2,46 @@
// See LICENSE for copying information.
<template>
<fragment>
<th @click="sortFunction('date')">
<div class="th-content">
<span>DATE</span>
<VerticalArrows
:is-active="arrowController.date"
:direction="dateSortDirection"
/>
</div>
</th>
<th>
<div class="th-content">
<span>TRANSACTION</span>
</div>
</th>
<th @click="sortFunction('amount')">
<div class="th-content">
<span>AMOUNT(USD)</span>
<VerticalArrows
:is-active="arrowController.amount"
:direction="amountSortDirection"
/>
</div>
</th>
<th @click="sortFunction('status')">
<div class="th-content">
<span>STATUS</span>
<VerticalArrows
:is-active="arrowController.status"
:direction="statusSortDirection"
/>
</div>
</th>
<th class="laptop">
<div class="th-content">
<span>DETAILS</span>
</div>
</th>
</fragment>
<th @click="sortFunction('date')">
<div class="th-content">
<span>DATE</span>
<VerticalArrows
:is-active="arrowController.date"
:direction="dateSortDirection"
/>
</div>
</th>
<th>
<div class="th-content">
<span>TRANSACTION</span>
</div>
</th>
<th @click="sortFunction('amount')">
<div class="th-content">
<span>AMOUNT(USD)</span>
<VerticalArrows
:is-active="arrowController.amount"
:direction="amountSortDirection"
/>
</div>
</th>
<th @click="sortFunction('status')">
<div class="th-content">
<span>STATUS</span>
<VerticalArrows
:is-active="arrowController.status"
:direction="statusSortDirection"
/>
</div>
</th>
<th class="laptop">
<div class="th-content">
<span>DETAILS</span>
</div>
</th>
</template>
<script setup lang="ts">
import { Fragment } from 'vue-fragment';
import { ref } from 'vue';
import { SortDirection } from '@/types/common';
@ -97,7 +94,7 @@ function sortFunction(key): void {
text-align: left;
}
@media screen and (max-width: 1024px) and (min-width: 426px) {
@media screen and (width <= 1024px) and (width >= 426px) {
.laptop {
display: none;

View File

@ -343,7 +343,7 @@ function toggleDetailedInfo(): void {
text-align: right;
}
@media only screen and (max-width: 1040px) {
@media only screen and (width <= 1040px) {
.price-per-month {
display: none;
@ -364,7 +364,7 @@ function toggleDetailedInfo(): void {
}
}
@media only screen and (max-width: 768px) {
@media only screen and (width <= 768px) {
.usage-charges-item-container__detailed-info-container__content-area__period-container,
.period-header {
@ -372,7 +372,7 @@ function toggleDetailedInfo(): void {
}
}
@media only screen and (max-width: 625px) {
@media only screen and (width <= 625px) {
.usage-charges-item-container__detailed-info-container__content-area__usage-container,
.usage-header {

View File

@ -92,12 +92,13 @@
<script setup lang="ts">
import { computed, onMounted, ref } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { Wallet } from '@/types/payments';
import { AnalyticsHttpApi } from '@/api/analytics';
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
import { MODALS } from '@/utils/constants/appStatePopUps';
import { useNotify, useRouter } from '@/utils/hooks';
import { useNotify } from '@/utils/hooks';
import { useBillingStore } from '@/store/modules/billingStore';
import { useAppStore } from '@/store/modules/appStore';
@ -113,6 +114,7 @@ const appStore = useAppStore();
const billingStore = useBillingStore();
const notify = useNotify();
const router = useRouter();
const route = useRoute();
const analytics: AnalyticsHttpApi = new AnalyticsHttpApi();
@ -177,7 +179,7 @@ onMounted(async (): Promise<void> => {
await getWallet();
// check if user navigated here from Billing overview screen
if (router.currentRoute.params.action !== 'add tokens') {
if (route.query.action !== 'add tokens') {
return;
}
// user clicked 'Add Funds' on Billing overview screen.

View File

@ -27,46 +27,42 @@
</div>
</th>
<fragment>
<th class="align-left data tablet-laptop">
<p>{{ item.timestamp.toLocaleDateString('en-US', {day:'numeric', month:'short', year:'numeric'}) }}</p>
</th>
<th class="align-left data tablet-laptop">
<p>Deposit on {{ item.formattedType }}</p>
<p class="laptop">{{ item.wallet }}</p>
</th>
<th class="align-left data tablet-laptop">
<p>{{ item.timestamp.toLocaleDateString('en-US', {day:'numeric', month:'short', year:'numeric'}) }}</p>
</th>
<th class="align-left data tablet-laptop">
<p>Deposit on {{ item.formattedType }}</p>
<p class="laptop">{{ item.wallet }}</p>
</th>
<th class="align-right data tablet-laptop">
<p v-if="item.type === 'storjscan'">{{ item.amount.value }}</p>
<p v-else>{{ item.received.value }}</p>
</th>
<th class="align-right data tablet-laptop">
<p v-if="item.type === 'storjscan'">{{ item.amount.value }}</p>
<p v-else>{{ item.received.value }}</p>
</th>
<th class="align-left data tablet-laptop">
<div class="status">
<span
class="status__dot" :class="{
pending: item.status === 'pending',
confirmed: item.status === 'confirmed',
rejected: item.status === 'rejected'
}"
/>
<span class="status__text">{{ item.formattedStatus }}</span>
</div>
</th>
<th class="align-left data tablet-laptop">
<div class="status">
<span
class="status__dot" :class="{
pending: item.status === 'pending',
confirmed: item.status === 'confirmed',
rejected: item.status === 'rejected'
}"
/>
<span class="status__text">{{ item.formattedStatus }}</span>
</div>
</th>
<th class="align-left data laptop">
<a
v-if="item.link" class="download-link" target="_blank"
rel="noopener noreferrer" :href="item.link"
>View on {{ item.linkName }}</a>
</th>
</fragment>
<th class="align-left data laptop">
<a
v-if="item.link" class="download-link" target="_blank"
rel="noopener noreferrer" :href="item.link"
>View on {{ item.linkName }}</a>
</th>
</tr>
</template>
<script setup lang="ts">
import { Fragment } from 'vue-fragment';
import { NativePaymentHistoryItem } from '@/types/payments';
import { useResize } from '@/composables/resize';
@ -149,7 +145,7 @@ function goToTxn() {
}
}
@media only screen and (max-width: 425px) {
@media only screen and (width <= 425px) {
.mobile {
display: table-cell;
@ -161,7 +157,7 @@ function goToTxn() {
}
}
@media only screen and (min-width: 426px) {
@media only screen and (width >= 426px) {
.tablet-laptop {
display: table-cell;
@ -172,14 +168,14 @@ function goToTxn() {
}
}
@media only screen and (max-width: 1024px) and (min-width: 426px) {
@media only screen and (width <= 1024px) and (width >= 426px) {
.laptop {
display: none;
}
}
@media only screen and (min-width: 1024px) {
@media only screen and (width >= 1024px) {
.laptop {
display: table-cell;

View File

@ -49,8 +49,8 @@
<script setup lang="ts">
import { computed } from 'vue';
import { useRouter } from 'vue-router';
import { useRouter } from '@/utils/hooks';
import { useObjectBrowserStore } from '@/store/modules/objectBrowserStore';
const obStore = useObjectBrowserStore();

View File

@ -194,6 +194,7 @@
<script setup lang="ts">
import { computed, onBeforeMount, reactive, ref } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import FileBrowserHeader from './FileBrowserHeader.vue';
import FileEntry from './FileEntry.vue';
@ -203,7 +204,7 @@ import BreadCrumbs from './BreadCrumbs.vue';
import { AnalyticsHttpApi } from '@/api/analytics';
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
import { RouteConfig } from '@/router';
import { useNotify, useRouter } from '@/utils/hooks';
import { useNotify } from '@/utils/hooks';
import { Bucket } from '@/types/buckets';
import { MODALS } from '@/utils/constants/appStatePopUps';
import { BrowserObject, useObjectBrowserStore } from '@/store/modules/objectBrowserStore';
@ -224,8 +225,8 @@ const bucketsStore = useBucketsStore();
const appStore = useAppStore();
const obStore = useObjectBrowserStore();
const nativeRouter = useRouter();
const router = reactive(nativeRouter);
const router = useRouter();
const route = useRoute();
const notify = useNotify();
const folderInput = ref<HTMLInputElement>();
@ -234,6 +235,10 @@ const fileInput = ref<HTMLInputElement>();
const fetchingFilesSpinner = ref<boolean>(false);
const isUploadDropDownShown = ref<boolean>(false);
const isBannerShown = ref<boolean>(true);
/**
* Retrieve the pathMatch from the current route.
*/
const routePath = ref(calculateRoutePath());
const NUMBER_OF_DISPLAYED_OBJECTS = 1000;
const analytics: AnalyticsHttpApi = new AnalyticsHttpApi();
@ -362,11 +367,6 @@ const folders = computed((): BrowserObject[] => {
return files.value.filter((f) => f.type === 'folder');
});
/**
* Retrieve the pathMatch from the current route.
*/
const routePath = ref(calculateRoutePath());
/**
* Returns bucket name from store.
*/
@ -382,11 +382,11 @@ function closeBanner(): void {
}
function calculateRoutePath(): string {
let pathMatch = router.currentRoute.params.pathMatch;
let pathMatch = route.params.pathMatch;
pathMatch = Array.isArray(pathMatch)
? pathMatch.join('/') + '/'
: pathMatch;
return pathMatch;
return pathMatch || '';
}
async function onBack(): Promise<void> {
@ -542,7 +542,7 @@ onBeforeMount(async () => {
obStore.getObjectCount(),
]);
} catch (err) {
await notify.error(err.message, AnalyticsErrorEventSource.FILE_BROWSER_LIST_CALL);
notify.error(err.message, AnalyticsErrorEventSource.FILE_BROWSER_LIST_CALL);
}
// remove the spinner after files have been fetched
@ -556,12 +556,12 @@ onBeforeMount(async () => {
}
.hide-mobile {
@media screen and (max-width: 550px) {
@media screen and (width <= 550px) {
display: none;
}
}
@media screen and (max-width: 550px) {
@media screen and (width <= 550px) {
// hide size, upload date columns on mobile screens
:deep(.data:not(:nth-child(2))) {
@ -606,7 +606,7 @@ onBeforeMount(async () => {
svg {
width: 300px;
@media screen and (max-width: 425px) {
@media screen and (width <= 425px) {
width: unset;
}
}
@ -796,7 +796,7 @@ onBeforeMount(async () => {
align-items: center;
margin: 1.5em 0;
@media screen and (max-width: 768px) {
@media screen and (width <= 768px) {
flex-direction: column;
justify-content: flex-start;
align-items: flex-start;
@ -809,7 +809,7 @@ onBeforeMount(async () => {
line-height: 1.2;
word-break: break-all;
@media screen and (max-width: 768px) {
@media screen and (width <= 768px) {
margin-bottom: 0.5rem;
}
}

View File

@ -2,95 +2,92 @@
// See LICENSE for copying information.
<template>
<fragment>
<th
class="align-left"
@mouseover="mouseOver('name')"
@mouseleave="mouseLeave"
@click="sortBy('name')"
>
<span class="header__item">
<span>Name</span>
<span :class="{ invisible: nameSortData.isHidden }">
<a v-if="nameSortData.isDesc" class="arrow">
<desc-icon />
</a>
<a v-else class="arrow">
<asc-icon />
</a>
</span>
<th
class="align-left"
@mouseover="mouseOver('name')"
@mouseleave="mouseLeave"
@click="sortBy('name')"
>
<span class="header__item">
<span>Name</span>
<span :class="{ invisible: nameSortData.isHidden }">
<a v-if="nameSortData.isDesc" class="arrow">
<desc-icon />
</a>
<a v-else class="arrow">
<asc-icon />
</a>
</span>
</th>
<th
class="align-left"
@mouseover="mouseOver('size')"
@mouseleave="mouseLeave"
@click="sortBy('size')"
>
<span class="header__item">
<span>Size</span>
<span :class="{ invisible: sizeSortData.isHidden }">
<a v-if="sizeSortData.isDesc" class="arrow">
<desc-icon />
</a>
<a v-else class="arrow">
<asc-icon />
</a>
</span>
</span>
</th>
<th
class="align-left"
@mouseover="mouseOver('size')"
@mouseleave="mouseLeave"
@click="sortBy('size')"
>
<span class="header__item">
<span>Size</span>
<span :class="{ invisible: sizeSortData.isHidden }">
<a v-if="sizeSortData.isDesc" class="arrow">
<desc-icon />
</a>
<a v-else class="arrow">
<asc-icon />
</a>
</span>
</th>
<th
class="align-left"
@mouseover="mouseOver('date')"
@mouseleave="mouseLeave"
@click="sortBy('date')"
>
<span class="header__item">
<span>Upload Date</span>
<span :class="{ invisible: dateSortData.isHidden }">
<a v-if="dateSortData.isDesc" class="arrow">
<desc-icon />
</a>
<a v-else class="arrow">
<asc-icon />
</a>
</span>
</span>
</th>
<th
class="align-left"
@mouseover="mouseOver('date')"
@mouseleave="mouseLeave"
@click="sortBy('date')"
>
<span class="header__item">
<span>Upload Date</span>
<span :class="{ invisible: dateSortData.isHidden }">
<a v-if="dateSortData.isDesc" class="arrow">
<desc-icon />
</a>
<a v-else class="arrow">
<asc-icon />
</a>
</span>
</th>
<th class="header__functional overflow-visible" @click.stop="deleteSelectedDropdown">
<delete-icon v-if="filesToDelete" />
<div v-if="isDropdownDisplayed" class="header__functional__dropdown">
<div class="header__functional__dropdown__item">
<div class="delete-confirmation">
<p class="delete-confirmation__text">
Are you sure?
</p>
<div class="delete-confirmation__options">
<span
class="delete-confirmation__options__item yes"
@click.stop="confirmDeleteSelection"
>
<span><delete-icon /></span>
<span>Yes</span>
</span>
</span>
</th>
<th class="header__functional overflow-visible" @click.stop="deleteSelectedDropdown">
<delete-icon v-if="filesToDelete" />
<div v-if="isDropdownDisplayed" class="header__functional__dropdown">
<div class="header__functional__dropdown__item">
<div class="delete-confirmation">
<p class="delete-confirmation__text">
Are you sure?
</p>
<div class="delete-confirmation__options">
<span
class="delete-confirmation__options__item yes"
@click.stop="confirmDeleteSelection"
>
<span><delete-icon /></span>
<span>Yes</span>
</span>
<span
class="delete-confirmation__options__item no"
@click.stop="cancelDeleteSelection"
>
<span><close-icon /></span>
<span>No</span>
</span>
</div>
<span
class="delete-confirmation__options__item no"
@click.stop="cancelDeleteSelection"
>
<span><close-icon /></span>
<span>No</span>
</span>
</div>
</div>
</div>
</th>
</fragment>
</div>
</th>
</template>
<script setup lang="ts">
import { Fragment } from 'vue-fragment';
import { computed, ref } from 'vue';
import { useObjectBrowserStore } from '@/store/modules/objectBrowserStore';

View File

@ -12,53 +12,55 @@
:item-type="fileType"
@selectClicked="selectFile"
>
<th slot="options" v-click-outside="closeDropdown" class="file-entry__functional options overflow-visible" @click.stop="openDropdown">
<div
v-if="loadingSpinner()"
class="spinner-border"
role="status"
/>
<dots-icon v-else />
<div v-if="dropdownOpen" class="file-entry__functional__dropdown">
<div class="file-entry__functional__dropdown__item" @click.stop="openModal">
<preview-icon />
<p class="file-entry__functional__dropdown__item__label">Preview</p>
</div>
<template #options>
<th v-click-outside="closeDropdown" class="file-entry__functional options overflow-visible" @click.stop="openDropdown">
<div
v-if="loadingSpinner"
class="spinner-border"
role="status"
/>
<dots-icon v-else />
<div v-if="dropdownOpen" class="file-entry__functional__dropdown">
<div class="file-entry__functional__dropdown__item" @click.stop="openModal">
<preview-icon />
<p class="file-entry__functional__dropdown__item__label">Preview</p>
</div>
<div class="file-entry__functional__dropdown__item" @click.stop="download">
<download-icon />
<p class="file-entry__functional__dropdown__item__label">Download</p>
</div>
<div class="file-entry__functional__dropdown__item" @click.stop="download">
<download-icon />
<p class="file-entry__functional__dropdown__item__label">Download</p>
</div>
<div class="file-entry__functional__dropdown__item" @click.stop="share">
<share-icon />
<p class="file-entry__functional__dropdown__item__label">Share</p>
</div>
<div class="file-entry__functional__dropdown__item" @click.stop="share">
<share-icon />
<p class="file-entry__functional__dropdown__item__label">Share</p>
</div>
<div v-if="!deleteConfirmation" class="file-entry__functional__dropdown__item" @click.stop="confirmDeletion">
<delete-icon />
<p class="file-entry__functional__dropdown__item__label">Delete</p>
</div>
<div v-else class="file-entry__functional__dropdown__item confirmation">
<div class="delete-confirmation">
<p class="delete-confirmation__text">
Are you sure?
</p>
<div class="delete-confirmation__options">
<span class="delete-confirmation__options__item yes" @click.stop="finalDelete">
<span><delete-icon /></span>
<span>Yes</span>
</span>
<div v-if="!deleteConfirmation" class="file-entry__functional__dropdown__item" @click.stop="confirmDeletion">
<delete-icon />
<p class="file-entry__functional__dropdown__item__label">Delete</p>
</div>
<div v-else class="file-entry__functional__dropdown__item confirmation">
<div class="delete-confirmation">
<p class="delete-confirmation__text">
Are you sure?
</p>
<div class="delete-confirmation__options">
<span class="delete-confirmation__options__item yes" @click.stop="finalDelete">
<span><delete-icon /></span>
<span>Yes</span>
</span>
<span class="delete-confirmation__options__item no" @click.stop="cancelDeletion">
<span><close-icon /></span>
<span>No</span>
</span>
<span class="delete-confirmation__options__item no" @click.stop="cancelDeletion">
<span><close-icon /></span>
<span>No</span>
</span>
</div>
</div>
</div>
</div>
</div>
</th>
</th>
</template>
</table-item>
<table-item
v-else-if="fileTypeIsFolder"
@ -70,49 +72,52 @@
item-type="folder"
@selectClicked="selectFile"
>
<th slot="options" v-click-outside="closeDropdown" class="file-entry__functional options overflow-visible" @click.stop="openDropdown">
<div
v-if="loadingSpinner()"
class="spinner-border"
role="status"
/>
<dots-icon v-else />
<div v-if="dropdownOpen" class="file-entry__functional__dropdown">
<template #options>
<th v-click-outside="closeDropdown" class="file-entry__functional options overflow-visible" @click.stop="openDropdown">
<div
v-if="!deleteConfirmation" class="file-entry__functional__dropdown__item"
@click.stop="confirmDeletion"
>
<delete-icon />
<p class="file-entry__functional__dropdown__item__label">Delete</p>
</div>
<div v-else class="file-entry__functional__dropdown__item confirmation">
<div class="delete-confirmation">
<p class="delete-confirmation__text">
Are you sure?
</p>
<div class="delete-confirmation__options">
<span class="delete-confirmation__options__item yes" @click.stop="finalDelete">
<span><delete-icon /></span>
<span>Yes</span>
</span>
v-if="loadingSpinner"
class="spinner-border"
role="status"
/>
<dots-icon v-else />
<div v-if="dropdownOpen" class="file-entry__functional__dropdown">
<div
v-if="!deleteConfirmation" class="file-entry__functional__dropdown__item"
@click.stop="confirmDeletion"
>
<delete-icon />
<p class="file-entry__functional__dropdown__item__label">Delete</p>
</div>
<div v-else class="file-entry__functional__dropdown__item confirmation">
<div class="delete-confirmation">
<p class="delete-confirmation__text">
Are you sure?
</p>
<div class="delete-confirmation__options">
<span class="delete-confirmation__options__item yes" @click.stop="finalDelete">
<span><delete-icon /></span>
<span>Yes</span>
</span>
<span class="delete-confirmation__options__item no" @click.stop="cancelDeletion">
<span><close-icon /></span>
<span>No</span>
</span>
<span class="delete-confirmation__options__item no" @click.stop="cancelDeletion">
<span><close-icon /></span>
<span>No</span>
</span>
</div>
</div>
</div>
</div>
</div>
</th>
</th>
</template>
</table-item>
</template>
<script setup lang="ts">
import { computed, ref } from 'vue';
import { useRouter } from 'vue-router';
import prettyBytes from 'pretty-bytes';
import { useNotify, useRouter } from '@/utils/hooks';
import { useNotify } from '@/utils/hooks';
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
import { MODALS } from '@/utils/constants/appStatePopUps';
import { BrowserObject, useObjectBrowserStore } from '@/store/modules/objectBrowserStore';
@ -233,6 +238,15 @@ const fileTypeIsFile = computed((): boolean => {
return props.file.type === 'file';
});
/**
* Return a boolean signifying whether the current file/folder is in the process of being deleted, therefore a spinner shoud be shown.
*/
const loadingSpinner = computed((): boolean => {
return obStore.state.filesToBeDeleted.some(
(file) => file.Key === props.file.Key,
);
});
/**
* Open the modal for the current file.
*/
@ -242,15 +256,6 @@ function openModal(): void {
obStore.closeDropdown();
}
/**
* Return a boolean signifying whether the current file/folder is in the process of being deleted, therefore a spinner shoud be shown.
*/
function loadingSpinner(): boolean {
return Boolean(obStore.state.filesToBeDeleted.find(
(file) => file === props.file,
));
}
/**
* Select the current file/folder whether it be a click, click + shiftKey, click + metaKey or ctrlKey, or unselect the rest.
*/
@ -270,8 +275,8 @@ function selectFile(event: KeyboardEvent): void {
setSelectedFile(isSelectedFile);
}
function openFolder(): void {
router.push(link.value);
async function openFolder(): Promise<void> {
await router.push(link.value);
obStore.clearAllSelectedFiles();
emit('onUpdate');
}
@ -481,7 +486,7 @@ function cancelDeletion(): void {
position: relative;
cursor: pointer;
@media screen and (max-width: 550px) {
@media screen and (width <= 550px) {
padding: 0 10px;
width: unset;
}
@ -566,7 +571,7 @@ function cancelDeletion(): void {
}
}
@media screen and (max-width: 550px) {
@media screen and (width <= 550px) {
// hide size, upload date columns on mobile screens
:deep(.data:not(:nth-child(2))) {
@ -602,14 +607,14 @@ function cancelDeletion(): void {
max-width: 26rem;
}
@media screen and (max-width: 940px) {
@media screen and (width <= 940px) {
:deep(th) {
max-width: 15rem;
}
}
@media screen and (max-width: 650px) {
@media screen and (width <= 650px) {
:deep(th) {
max-width: 10rem;

View File

@ -96,7 +96,7 @@ function openManageModal(): void {
font-family: 'font_regular', sans-serif;
margin-bottom: 21px;
@media screen and (max-width: 400px) {
@media screen and (width <= 400px) {
flex-direction: column-reverse;
}
@ -105,7 +105,7 @@ function openManageModal(): void {
align-items: center;
margin-right: 15px;
@media screen and (max-width: 600px) {
@media screen and (width <= 600px) {
flex-direction: column;
align-items: flex-start;
}
@ -117,7 +117,7 @@ function openManageModal(): void {
&__labels {
margin-left: 16px;
@media screen and (max-width: 600px) {
@media screen and (width <= 600px) {
margin: 10px 0 0;
}
@ -140,7 +140,7 @@ function openManageModal(): void {
display: flex;
align-items: center;
@media screen and (max-width: 400px) {
@media screen and (width <= 400px) {
width: 100%;
justify-content: space-between;
margin-bottom: 10px;

View File

@ -64,12 +64,12 @@
</template>
<script setup lang="ts">
import { computed, reactive, ref } from 'vue';
import { computed, ref } from 'vue';
import { useRoute } from 'vue-router';
import { RouteConfig } from '@/router';
import { AnalyticsHttpApi } from '@/api/analytics';
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
import { useRouter } from '@/utils/hooks';
import { useBillingStore } from '@/store/modules/billingStore';
import VInput from '@/components/common/VInput.vue';
@ -79,8 +79,7 @@ import VButton from '@/components/common/VButton.vue';
import CheckIcon from '@/../static/images/common/validCheck.svg';
const billingStore = useBillingStore();
const nativeRouter = useRouter();
const router = reactive(nativeRouter);
const route = useRoute();
const showValidationMessage = ref<boolean>(false);
const isCodeValid = ref<boolean>(false);
@ -94,7 +93,7 @@ const analytics = new AnalyticsHttpApi();
* Signup view requires some unique styling and element text.
*/
const isSignupView = computed((): boolean => {
return router.currentRoute.name === RouteConfig.Register.name;
return route.name === RouteConfig.Register.name;
});
/**
@ -198,7 +197,7 @@ async function couponCheck(): Promise<void> {
margin-top: 30px;
column-gap: 20px;
@media screen and (max-width: 650px) {
@media screen and (width <= 650px) {
flex-direction: column;
column-gap: unset;
row-gap: 20px;

View File

@ -29,10 +29,7 @@ import LoaderImage from '@/../static/images/common/loadIcon.svg';
justify-content: center;
align-items: center;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
inset: 0;
background-color: #fff;
&__spinner {
@ -53,10 +50,7 @@ import LoaderImage from '@/../static/images/common/loadIcon.svg';
&__icon {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
inset: 0;
margin: auto;
}
}

View File

@ -49,11 +49,12 @@
</template>
<script setup lang="ts">
import { computed, onBeforeUnmount, onMounted, reactive, ref } from 'vue';
import { computed, onBeforeUnmount, onMounted, ref } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { AuthHttpApi } from '@/api/auth';
import { RouteConfig } from '@/router';
import { useNotify, useRouter } from '@/utils/hooks';
import { useNotify } from '@/utils/hooks';
import VButton from '@/components/common/VButton.vue';
@ -68,8 +69,8 @@ const props = withDefaults(defineProps<{
showManualActivationMsg: true,
});
const nativeRouter = useRouter();
const router = reactive(nativeRouter);
const router = useRouter();
const route = useRoute();
const notify = useNotify();
const auth: AuthHttpApi = new AuthHttpApi();
@ -79,7 +80,7 @@ const secondsToWait = ref<number>(30);
const intervalId = ref<ReturnType<typeof setInterval>>();
const userEmail = computed((): string => {
return props.email || router.currentRoute.query.email.toString();
return props.email || route.query.email?.toString() || '';
});
/**
@ -154,10 +155,7 @@ onBeforeUnmount(() => {
padding: 0 20px;
box-sizing: border-box;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
inset: 0;
overflow-y: scroll;
&__logo-wrapper {
@ -254,7 +252,7 @@ onBeforeUnmount(() => {
}
}
@media screen and (max-width: 750px) {
@media screen and (width <= 750px) {
.register-success-area__container {
width: 100%;

View File

@ -36,7 +36,7 @@
</template>
<script setup lang="ts">
import { computed, VueConstructor } from 'vue';
import { computed, Component } from 'vue';
import VTableCheckbox from '@/components/common/VTableCheckbox.vue';
import BucketGuide from '@/components/objects/BucketGuide.vue';
@ -82,7 +82,7 @@ const props = withDefaults(defineProps<{
const emit = defineEmits(['selectClicked']);
const icons = new Map<string, VueConstructor>([
const icons = new Map<string, Component>([
['locked', TableLockedIcon],
['bucket', ColorBucketIcon],
['folder', ColorFolderIcon],

View File

@ -276,7 +276,7 @@ async function prevPage(): Promise<void> {
line-height: 22px;
}
@media only screen and (max-width: 550px) {
@media only screen and (width <= 550px) {
&.index:not(.selected),
&.jumper {

View File

@ -117,7 +117,7 @@ function toggleSelector() {
&__label {
margin-right: 10px;
@media only screen and (max-width: 768px) {
@media only screen and (width <= 768px) {
display: none;
}
}

View File

@ -83,7 +83,7 @@ watch(() => props.dashboardRef, () => {
border-radius: 10px;
box-shadow: 0 7px 20px rgba(0 0 0 / 15%);
@media screen and (max-width: 450px) {
@media screen and (width <= 450px) {
flex-direction: column;
align-items: flex-start;
row-gap: 10px;
@ -136,7 +136,7 @@ watch(() => props.dashboardRef, () => {
cursor: pointer;
flex-shrink: 0;
@media screen and (max-width: 450px) {
@media screen and (width <= 450px) {
position: absolute;
right: 20px;
top: 20px;

View File

@ -50,7 +50,7 @@
</template>
<script setup lang="ts">
import { computed, VueConstructor } from 'vue';
import { computed, Component } from 'vue';
import WhitePlusIcon from '@/../static/images/common/plusWhite.svg';
import AddCircleIcon from '@/../static/images/common/addCircle.svg';
@ -106,7 +106,7 @@ const props = withDefaults(defineProps<{
onPress: () => {},
});
const icons = new Map<string, VueConstructor>([
const icons = new Map<string, Component>([
['copy', CopyIcon],
['check', CheckIcon],
['download', DownloadIcon],
@ -120,7 +120,7 @@ const icons = new Map<string, VueConstructor>([
['add', WhitePlusIcon],
]);
const iconComponent = computed((): VueConstructor | undefined => icons.get(props.icon.toLowerCase()));
const iconComponent = computed((): Component | undefined => icons.get(props.icon.toLowerCase()));
const containerClassName = computed((): string => {
if (props.isDisabled) return 'disabled';

View File

@ -2,18 +2,21 @@
// See LICENSE for copying information.
<template>
<DatePicker
<VueDatePicker
aria-roledescription="datepicker"
:open="true"
:inline="true"
:value="date"
:editable="false"
:clearable="false"
:append-to-body="false"
popup-class="picker"
:popup-style="{position: 'relative', left: 0, top: 0}"
@change="onDatePick"
/>
</template>
<script setup lang="ts">
import DatePicker from 'vue2-datepicker';
import VueDatePicker from 'vue-datepicker-next';
const props = withDefaults(defineProps<{
onDatePick?: (date: Date) => void;
@ -23,88 +26,3 @@ const props = withDefaults(defineProps<{
date: () => new Date(),
});
</script>
<style scoped lang="scss">
@import '~vue2-datepicker/scss/index';
.picker,
.mx-datepicker {
width: 100%;
cursor: default;
}
.mx-calendar {
width: 100%;
}
.mx-date-row {
height: 40px;
}
.mx-table th {
color: var(--c-grey-4);
}
.mx-table-date .cell.not-current-month {
color: var(--c-grey-5);
}
.mx-calendar-content .cell {
font-size: 12px;
line-height: 18px;
color: #000;
}
.mx-calendar-content .cell.in-range {
color: #000;
background-color: var(--c-blue-1);
border-radius: 999px;
}
.mx-calendar-content .cell.active {
background-color: var(--c-blue-3);
border-radius: 999px;
}
.mx-calendar-content {
height: unset;
}
.mx-btn-current-month,
.mx-btn-current-year {
pointer-events: none;
font-family: 'font_medium', sans-serif;
font-size: 14px;
line-height: 20px;
color: #000;
}
.mx-btn:hover {
border-color: #000;
color: #000;
}
.mx-btn-icon-double-right,
.mx-btn-icon-double-left {
display: none;
}
.mx-icon-left:before,
.mx-icon-right:before {
width: 20px;
height: 20px;
border-width: 4px 0 0 4px;
}
@media screen and (max-width: 768px) {
.mx-range-wrapper {
flex-direction: column;
}
.mx-calendar + .mx-calendar {
border-left: none;
border-top: 1px solid #e8e8e8;
}
}
</style>

View File

@ -2,19 +2,22 @@
// See LICENSE for copying information.
<template>
<DatePicker
<VueDatePicker
aria-roledescription="datepicker"
range
:open="isOpen"
:inline="true"
:value="dateRange"
:editable="false"
:clearable="false"
:append-to-body="false"
popup-class="picker"
:popup-style="{position: 'relative', left: 0, top: 0}"
@change="onDatePick"
/>
</template>
<script setup lang="ts">
import DatePicker from 'vue2-datepicker';
import VueDatePicker from 'vue-datepicker-next';
const props = withDefaults(defineProps<{
isOpen?: boolean;
@ -28,18 +31,26 @@ const props = withDefaults(defineProps<{
</script>
<style lang="scss">
@import '~vue2-datepicker/scss/index';
@import 'vue-datepicker-next/index.css';
.mx-input-wrapper {
display: none;
}
.mx-datepicker-popup {
box-shadow: unset;
}
.mx-calendar {
width: 100%;
}
.picker,
.mx-datepicker,
.mx-range-wrapper {
width: 100%;
border: none;
border-radius: 8px;
cursor: default;
}
.mx-calendar {
width: 100%;
}
@ -58,11 +69,11 @@ const props = withDefaults(defineProps<{
.mx-calendar-content .cell {
font-size: 12px;
line-height: 18px;
color: #000;
color: var(--c-black);
}
.mx-calendar-content .cell.in-range {
color: #000;
color: var(--c-black);
background-color: var(--c-blue-1);
border-radius: 999px;
}
@ -82,12 +93,12 @@ const props = withDefaults(defineProps<{
font-family: 'font_medium', sans-serif;
font-size: 14px;
line-height: 20px;
color: #000;
color: var(--c-black);
}
.mx-btn:hover {
border-color: #000;
color: #000;
border-color: var(--c-black);
color: var(--c-black);
}
.mx-btn-icon-double-right,
@ -102,7 +113,7 @@ const props = withDefaults(defineProps<{
border-width: 4px 0 0 4px;
}
@media screen and (max-width: 768px) {
@media screen and (width <= 768px) {
.range-selection__popup {
width: 320px !important;

View File

@ -70,7 +70,7 @@ defineExpose({ clearSearch });
}
}
@media screen and (max-width: 1150px) {
@media screen and (width <= 1150px) {
.header-container {
flex-direction: column;

View File

@ -69,7 +69,7 @@ onMounted((): void => {
box-shadow: 0 0 32px rgb(0 0 0 / 4%);
margin: 0 24px;
@media screen and (max-width: 400px) {
@media screen and (width <= 400px) {
margin: 0;
}

View File

@ -10,6 +10,8 @@
</template>
<script setup lang="ts">
import { Teleport } from 'vue';
import VLoader from '@/components/common/VLoader.vue';
</script>

View File

@ -31,7 +31,7 @@
</template>
<script setup lang="ts">
import { computed, onMounted, ref, watch } from 'vue';
import { computed, onMounted, ref } from 'vue';
import { OnPageClickCallback, Page } from '@/types/pagination';
import { useLoading } from '@/composables/useLoading';
@ -49,7 +49,7 @@ const props = withDefaults(defineProps<{
totalPageCount?: number;
}>(), {
totalPageCount: 0,
onPageClickCallback: () => () => {},
onPageClickCallback: () => (_: number) => Promise.resolve(),
});
const { withLoading } = useLoading();
@ -120,7 +120,7 @@ function populatePagesArray(): void {
pagesArray.value.push(new Page(i, onPageClick));
}
if (isPagesTotalOffBlocks) {
if (isPagesTotalOffBlocks.value) {
firstBlockPages.value = pagesArray.value.slice();
middleBlockPages.value = [];
lastBlockPages.value = [];
@ -131,13 +131,6 @@ function populatePagesArray(): void {
reorganizePageBlocks();
}
/**
* Method after total page count change.
*/
const onPageCountChange = watch(() => props.totalPageCount, (): void => {
resetPageIndex();
});
function setBlocksIfCurrentInFirstBlock(): void {
firstBlockPages.value = pagesArray.value.slice(0, 3);
middleBlockPages.value = [];
@ -184,7 +177,7 @@ async function onPageClick(page: number): Promise<void> {
*/
async function nextPage(): Promise<void> {
await withLoading(async () => {
if (isLastPage) {
if (isLastPage.value) {
return;
}
@ -199,7 +192,7 @@ async function nextPage(): Promise<void> {
*/
async function prevPage(): Promise<void> {
await withLoading(async () => {
if (isFirstPage) {
if (isFirstPage.value) {
return;
}
@ -209,39 +202,28 @@ async function prevPage(): Promise<void> {
});
}
/**
* resetPageIndex sets current selected page as first and rebuilds page blocks after.
*/
function resetPageIndex(): void {
pagesArray.value = [];
firstBlockPages.value = [];
setCurrentPage(1);
populatePagesArray();
}
/**
* reorganizePageBlocks changes pages blocks organization depends of
* current selected page index.
*/
function reorganizePageBlocks(): void {
if (isPagesTotalOffBlocks) {
if (isPagesTotalOffBlocks.value) {
return;
}
if (isCurrentInFirstBlock) {
if (isCurrentInFirstBlock.value) {
setBlocksIfCurrentInFirstBlock();
return;
}
if (!isCurrentInFirstBlock && !isCurrentInLastBlock) {
if (!isCurrentInFirstBlock.value && !isCurrentInLastBlock.value) {
setBlocksIfCurrentInMiddleBlock();
return;
}
if (isCurrentInLastBlock) {
if (isCurrentInLastBlock.value) {
setBlocksIfCurrentInLastBlock();
}
}

View File

@ -102,7 +102,7 @@ defineExpose({ clearSearch });
background-position: top 16px right 16px;
}
@media screen and (max-width: 1150px) {
@media screen and (width <= 1150px) {
.common-search-input {
width: 100% !important;

View File

@ -66,7 +66,7 @@ defineExpose({ clearSearch });
background-size: 22px 22px;
background-position: top 8px left 14px;
@media screen and (max-width: 1150px) {
@media screen and (width <= 1150px) {
width: 100%;
}
}

View File

@ -86,7 +86,7 @@ const emit = defineEmits(['selectAllClicked']);
background: var(--c-block-gray);
text-transform: uppercase;
@media screen and (max-width: 550px) {
@media screen and (width <= 550px) {
display: none;
}
@ -109,7 +109,7 @@ const emit = defineEmits(['selectAllClicked']);
font-size: 1rem;
border-top: solid 1px var(--c-grey-2);
@media screen and (max-width: 550px) {
@media screen and (width <= 550px) {
border-top: none;
border-bottom: solid 1px var(--c-grey-2);
}
@ -146,12 +146,12 @@ const emit = defineEmits(['selectAllClicked']);
border-bottom-left-radius: 12px;
border-bottom-right-radius: 12px;
@media screen and (max-width: 550px) {
@media screen and (width <= 550px) {
border-top: none;
}
}
@media screen and (max-width: 970px) {
@media screen and (width <= 970px) {
tbody tr > .data p {
max-width: 25rem;
@ -161,14 +161,14 @@ const emit = defineEmits(['selectAllClicked']);
}
}
@media screen and (max-width: 870px) {
@media screen and (width <= 870px) {
tbody tr > .data p {
max-width: 20rem;
}
}
@media screen and (max-width: 550px) {
@media screen and (width <= 550px) {
.select {
display: none;
@ -179,28 +179,28 @@ const emit = defineEmits(['selectAllClicked']);
}
}
@media screen and (max-width: 660px) {
@media screen and (width <= 660px) {
tbody tr > .data p {
max-width: 15rem;
}
}
@media screen and (max-width: 550px) {
@media screen and (width <= 550px) {
tbody tr > .data p {
max-width: 15rem;
}
}
@media screen and (max-width: 440px) {
@media screen and (width <= 440px) {
tbody tr > .data p {
max-width: 10rem;
}
}
@media screen and (max-width: 350px) {
@media screen and (width <= 350px) {
tbody tr > .data p {
max-width: 8rem;

View File

@ -12,7 +12,7 @@
</template>
<script setup lang="ts">
import { computed, VueConstructor } from 'vue';
import { computed, Component } from 'vue';
import { ShareButtonConfig, ShareOptions } from '@/types/browser';
@ -29,7 +29,7 @@ import EmailIcon from '@/../static/images/objects/email.svg';
const props = defineProps<{ link: string; }>();
const images: Record<string, VueConstructor> = {
const images: Record<string, Component> = {
[ShareOptions.Reddit]: RedditIcon,
[ShareOptions.Facebook]: FacebookIcon,
[ShareOptions.Twitter]: TwitterIcon,

View File

@ -13,7 +13,6 @@
</template>
<script setup lang="ts">
import { MODALS } from '@/utils/constants/appStatePopUps';
import { RouteConfig } from '@/router';
import { AnalyticsHttpApi } from '@/api/analytics';
import { useAppStore } from '@/store/modules/appStore';
@ -30,7 +29,7 @@ const analytics: AnalyticsHttpApi = new AnalyticsHttpApi();
*/
function onCloseClick(): void {
analytics.pageVisit(RouteConfig.Account.with(RouteConfig.Billing).path);
appStore.updateActiveModal(MODALS.addCoupon);
appStore.removeActiveModal();
}
</script>
@ -39,7 +38,7 @@ function onCloseClick(): void {
width: 500px;
padding: 32px;
@media screen and (max-width: 650px) {
@media screen and (width <= 650px) {
width: unset;
padding: 24px;
}

View File

@ -65,12 +65,10 @@
<script setup lang='ts'>
import { computed, ref } from 'vue';
import { RouteConfig } from '@/router';
import { EmailInput } from '@/types/EmailInput';
import { Validator } from '@/utils/validation';
import { AnalyticsHttpApi } from '@/api/analytics';
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
import { MODALS } from '@/utils/constants/appStatePopUps';
import { useNotify } from '@/utils/hooks';
import { useUsersStore } from '@/store/modules/usersStore';
import { useProjectMembersStore } from '@/store/modules/projectMembersStore';
@ -129,10 +127,6 @@ const isButtonActive = computed((): boolean => {
return false;
});
const registerPath = computed((): string => {
return location.host + RouteConfig.Register.path;
});
function setInput(index: number, str: string) {
resetFormErrors(index);
inputs.value[index].value = str;
@ -247,7 +241,7 @@ function deleteInput(index: number): void {
* Closes modal.
*/
function closeModal(): void {
appStore.updateActiveModal(MODALS.addTeamMember);
appStore.removeActiveModal();
}
/**
@ -266,7 +260,7 @@ function resetFormErrors(index: number): void {
width: 346px;
padding: 32px;
@media screen and (max-width: 460px) {
@media screen and (width <= 460px) {
width: 280px;
padding: 16px;
}
@ -278,7 +272,7 @@ function resetFormErrors(index: number): void {
margin-bottom: 16px;
border-bottom: 1px solid var(--c-grey-2);
@media screen and (max-width: 460px) {
@media screen and (width <= 460px) {
flex-direction: column;
align-items: flex-start;
}
@ -292,7 +286,7 @@ function resetFormErrors(index: number): void {
color: var(--c-black);
text-align: left;
@media screen and (max-width: 460px) {
@media screen and (width <= 460px) {
margin: 10px 0 0;
}
}
@ -366,7 +360,7 @@ function resetFormErrors(index: number): void {
margin-top: 10px;
width: 100%;
@media screen and (max-width: 500px) {
@media screen and (width <= 500px) {
flex-direction: column-reverse;
column-gap: unset;
row-gap: 10px;

View File

@ -77,7 +77,6 @@ import QRCode from 'qrcode';
import { Wallet } from '@/types/payments';
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
import { MODALS } from '@/utils/constants/appStatePopUps';
import { useNotify } from '@/utils/hooks';
import { useBillingStore } from '@/store/modules/billingStore';
import { useAppStore } from '@/store/modules/appStore';
@ -105,7 +104,7 @@ const wallet = computed((): Wallet => {
* Closes create project prompt modal.
*/
function closeModal(): void {
appStore.updateActiveModal(MODALS.addTokenFunds);
appStore.removeActiveModal();
}
/**

View File

@ -8,7 +8,7 @@
</template>
<script setup lang="ts">
import { computed } from 'vue';
import { Component, computed } from 'vue';
import { useAppStore } from '@/store/modules/appStore';
@ -17,8 +17,7 @@ const appStore = useAppStore();
/**
* Indicates the current active modal.
*/
const activeModal = computed((): unknown | null => {
// modal could be of VueConstructor type or Object (for composition api components).
const activeModal = computed((): Component | null => {
return appStore.state.activeModal;
});
</script>

View File

@ -63,13 +63,13 @@
<script setup lang="ts">
import { ref } from 'vue';
import { useRouter } from 'vue-router';
import { AuthHttpApi } from '@/api/auth';
import { RouteConfig } from '@/router';
import { AnalyticsHttpApi } from '@/api/analytics';
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
import { MODALS } from '@/utils/constants/appStatePopUps';
import { useNotify, useRouter } from '@/utils/hooks';
import { useNotify } from '@/utils/hooks';
import { useConfigStore } from '@/store/modules/configStore';
import { useAppStore } from '@/store/modules/appStore';
@ -199,7 +199,7 @@ async function onUpdateClick(): Promise<void> {
* Closes popup.
*/
function closeModal(): void {
appStore.updateActiveModal(MODALS.changePassword);
appStore.removeActiveModal();
}
</script>
@ -213,16 +213,16 @@ function closeModal(): void {
box-sizing: border-box;
min-width: 550px;
@media screen and (max-width: 600px) {
@media screen and (width <= 600px) {
min-width: 475px;
padding: 48px 24px;
}
@media screen and (max-width: 530px) {
@media screen and (width <= 530px) {
min-width: 420px;
}
@media screen and (max-width: 470px) {
@media screen and (width <= 470px) {
min-width: unset;
}
@ -231,7 +231,7 @@ function closeModal(): void {
align-items: center;
margin-bottom: 20px;
@media screen and (max-width: 600px) {
@media screen and (width <= 600px) {
svg {
display: none;
@ -245,7 +245,7 @@ function closeModal(): void {
color: #384b65;
margin: 0 0 0 32px;
@media screen and (max-width: 600px) {
@media screen and (width <= 600px) {
font-size: 24px;
line-height: 28px;
margin: 0;
@ -260,7 +260,7 @@ function closeModal(): void {
margin-top: 32px;
column-gap: 20px;
@media screen and (max-width: 600px) {
@media screen and (width <= 600px) {
flex-direction: column-reverse;
column-gap: unset;
row-gap: 10px;
@ -278,7 +278,7 @@ function closeModal(): void {
margin-bottom: 15px;
}
@media screen and (max-width: 600px) {
@media screen and (width <= 600px) {
:deep(.password-strength-container) {
width: unset;

View File

@ -336,7 +336,7 @@ onMounted(() => {
padding: 32px;
font-family: 'font_regular', sans-serif;
@media screen and (max-width: 375px) {
@media screen and (width <= 375px) {
padding: 32px 16px;
}
@ -369,7 +369,7 @@ onMounted(() => {
column-gap: 16px;
&__wrap {
@media screen and (max-width: 475px) {
@media screen and (width <= 475px) {
width: calc(50% - 8px);
}
@ -404,7 +404,7 @@ onMounted(() => {
width: 100px;
border-radius: 8px 0 0 8px;
@media screen and (max-width: 475px) {
@media screen and (width <= 475px) {
padding-right: 0;
width: calc(100% - 54px);
}

View File

@ -55,15 +55,15 @@
<script setup lang="ts">
import { computed, onMounted, ref } from 'vue';
import { useRouter } from 'vue-router';
import { RouteConfig } from '@/router';
import { AnalyticsHttpApi } from '@/api/analytics';
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
import { useNotify, useRouter } from '@/utils/hooks';
import { useNotify } from '@/utils/hooks';
import { Validator } from '@/utils/validation';
import { AccessGrant, EdgeCredentials } from '@/types/accessGrants';
import { LocalData } from '@/utils/localData';
import { MODALS } from '@/utils/constants/appStatePopUps';
import { useAppStore } from '@/store/modules/appStore';
import { useAccessGrantsStore } from '@/store/modules/accessGrantsStore';
import { useBucketsStore, FILE_BROWSER_AG_NAME } from '@/store/modules/bucketsStore';
@ -215,7 +215,7 @@ async function onCreate(): Promise<void> {
'isList': false,
'isDelete': false,
'notAfter': inOneHour.toISOString(),
'buckets': [],
'buckets': JSON.stringify([]),
'apiKey': apiKey.value,
});
@ -281,7 +281,7 @@ function setBucketName(name: string): void {
* Closes create bucket modal.
*/
function closeModal(): void {
appStore.updateActiveModal(MODALS.createBucket);
appStore.removeActiveModal();
}
/**
@ -334,7 +334,7 @@ onMounted(async (): Promise<void> => {
flex-direction: column;
max-width: 350px;
@media screen and (max-width: 615px) {
@media screen and (width <= 615px) {
padding: 30px 20px;
}
@ -405,7 +405,7 @@ onMounted(async (): Promise<void> => {
margin-top: 16px;
column-gap: 20px;
@media screen and (max-width: 600px) {
@media screen and (width <= 600px) {
margin-top: 20px;
column-gap: unset;
row-gap: 8px;

View File

@ -61,6 +61,7 @@
<script setup lang="ts">
import { ref } from 'vue';
import { useRouter } from 'vue-router';
import { RouteConfig } from '@/router';
import { ProjectFields } from '@/types/projects';
@ -68,7 +69,7 @@ import { LocalData } from '@/utils/localData';
import { AnalyticsHttpApi } from '@/api/analytics';
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
import { MODALS } from '@/utils/constants/appStatePopUps';
import { useNotify, useRouter } from '@/utils/hooks';
import { useNotify } from '@/utils/hooks';
import { useUsersStore } from '@/store/modules/usersStore';
import { useAppStore } from '@/store/modules/appStore';
import { useBucketsStore } from '@/store/modules/bucketsStore';
@ -145,7 +146,7 @@ async function onCreateProjectClick(): Promise<void> {
selectCreatedProject();
await notify.success('Project created successfully!');
notify.success('Project created successfully!');
isLoading.value = false;
closeModal();
@ -171,7 +172,7 @@ function selectCreatedProject(): void {
* Closes create project modal.
*/
function closeModal(): void {
appStore.updateActiveModal(MODALS.createProject);
appStore.removeActiveModal();
}
</script>
@ -184,7 +185,7 @@ function closeModal(): void {
flex-direction: column;
font-family: 'font_regular', sans-serif;
@media screen and (max-width: 550px) {
@media screen and (width <= 550px) {
width: calc(100% - 48px);
padding: 54px 24px 32px;
}
@ -193,7 +194,7 @@ function closeModal(): void {
max-height: 154px;
max-width: 118px;
@media screen and (max-width: 550px) {
@media screen and (width <= 550px) {
max-height: 77px;
max-width: 59px;
}
@ -207,7 +208,7 @@ function closeModal(): void {
margin-top: 40px;
text-align: center;
@media screen and (max-width: 550px) {
@media screen and (width <= 550px) {
margin-top: 16px;
font-size: 24px;
line-height: 31px;
@ -231,7 +232,7 @@ function closeModal(): void {
margin-top: 30px;
column-gap: 20px;
@media screen and (max-width: 550px) {
@media screen and (width <= 550px) {
margin-top: 20px;
column-gap: unset;
row-gap: 8px;
@ -263,7 +264,7 @@ function closeModal(): void {
margin-top: 20px;
}
@media screen and (max-width: 550px) {
@media screen and (width <= 550px) {
:deep(.add-label) {
display: none;

View File

@ -44,7 +44,6 @@ const appStore = useAppStore();
* Closes this modal and opens upgrade account modal.
*/
function onClick(): void {
appStore.updateActiveModal(MODALS.createProjectPrompt);
appStore.updateActiveModal(MODALS.upgradeAccount);
}
@ -52,7 +51,7 @@ function onClick(): void {
* Closes create project prompt modal.
*/
function closeModal(): void {
appStore.updateActiveModal(MODALS.createProjectPrompt);
appStore.removeActiveModal();
}
</script>
@ -65,12 +64,12 @@ function closeModal(): void {
flex-direction: column;
font-family: 'font_regular', sans-serif;
@media screen and (max-width: 768px) {
@media screen and (width <= 768px) {
width: unset;
padding: 54px 24px 65px;
}
@media screen and (max-width: 450px) {
@media screen and (width <= 450px) {
padding: 54px 12px 32px;
}
@ -78,7 +77,7 @@ function closeModal(): void {
max-height: 154px;
max-width: 118px;
@media screen and (max-width: 450px) {
@media screen and (width <= 450px) {
max-height: 127px;
max-width: 97px;
}
@ -92,7 +91,7 @@ function closeModal(): void {
margin-top: 40px;
text-align: center;
@media screen and (max-width: 450px) {
@media screen and (width <= 450px) {
margin-top: 24px;
font-size: 24px;
line-height: 31px;
@ -107,7 +106,7 @@ function closeModal(): void {
color: #354049;
margin: 15px 0 45px;
@media screen and (max-width: 450px) {
@media screen and (width <= 450px) {
margin: 10px 0 24px;
font-size: 14px;
line-height: 20px;
@ -119,7 +118,7 @@ function closeModal(): void {
justify-content: center;
width: 256px;
@media screen and (max-width: 768px) {
@media screen and (width <= 768px) {
width: 224px;
}
}

View File

@ -112,7 +112,7 @@ async function onDelete(): Promise<void> {
flex-direction: column;
font-family: 'font_regular', sans-serif;
@media screen and (max-width: 500px) {
@media screen and (width <= 500px) {
width: unset;
}
@ -158,7 +158,7 @@ async function onDelete(): Promise<void> {
align-items: center;
column-gap: 16px;
@media screen and (max-width: 500px) {
@media screen and (width <= 500px) {
column-gap: unset;
row-gap: 10px;
flex-direction: column-reverse;

View File

@ -34,7 +34,6 @@ import { computed, onMounted, ref } from 'vue';
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
import { AnalyticsHttpApi } from '@/api/analytics';
import { AccessGrant, EdgeCredentials } from '@/types/accessGrants';
import { MODALS } from '@/utils/constants/appStatePopUps';
import { useNotify } from '@/utils/hooks';
import { useAppStore } from '@/store/modules/appStore';
import { useAccessGrantsStore } from '@/store/modules/accessGrantsStore';
@ -98,7 +97,7 @@ async function onDelete(): Promise<void> {
'isList': true,
'isDelete': true,
'notAfter': inOneHour.toISOString(),
'buckets': [name.value],
'buckets': JSON.stringify([name.value]),
'apiKey': apiKey.value,
});
@ -184,7 +183,7 @@ function onChangeName(value: string): void {
* Closes modal.
*/
function closeModal(): void {
appStore.updateActiveModal(MODALS.deleteBucket);
appStore.removeActiveModal();
}
/**
@ -208,7 +207,7 @@ onMounted(() => {
background-color: #fff;
max-width: 480px;
@media screen and (max-width: 700px) {
@media screen and (width <= 700px) {
padding: 45px;
}

View File

@ -45,7 +45,6 @@ import { ref } from 'vue';
import { DisableMFARequest } from '@/types/users';
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
import { MODALS } from '@/utils/constants/appStatePopUps';
import { useNotify } from '@/utils/hooks';
import { useUsersStore } from '@/store/modules/usersStore';
import { useAppStore } from '@/store/modules/appStore';
@ -72,7 +71,7 @@ const mfaInput = ref<ConfirmMFAInput & ClearInput>();
* Closes disable MFA modal.
*/
function closeModal(): void {
appStore.updateActiveModal(MODALS.disableMFA);
appStore.removeActiveModal();
}
/**
@ -127,7 +126,7 @@ async function disable(): Promise<void> {
align-items: center;
font-family: 'font_regular', sans-serif;
@media screen and (max-width: 550px) {
@media screen and (width <= 550px) {
padding: 48px 24px;
}
@ -139,7 +138,7 @@ async function disable(): Promise<void> {
color: #000;
margin: 0 0 30px;
@media screen and (max-width: 550px) {
@media screen and (width <= 550px) {
font-size: 24px;
line-height: 28px;
margin-bottom: 15px;
@ -153,7 +152,7 @@ async function disable(): Promise<void> {
color: #000;
margin: 0 0 45px;
@media screen and (max-width: 550px) {
@media screen and (width <= 550px) {
font-size: 14px;
line-height: 18px;
margin-bottom: 20px;
@ -202,7 +201,7 @@ async function disable(): Promise<void> {
margin-top: 30px;
column-gap: 15px;
@media screen and (max-width: 550px) {
@media screen and (width <= 550px) {
flex-direction: column-reverse;
column-gap: unset;
row-gap: 10px;

View File

@ -44,7 +44,6 @@ import { computed, reactive, ref } from 'vue';
import { UpdatedUser } from '@/types/users';
import { AnalyticsHttpApi } from '@/api/analytics';
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
import { MODALS } from '@/utils/constants/appStatePopUps';
import { useNotify } from '@/utils/hooks';
import { useUsersStore } from '@/store/modules/usersStore';
import { useAppStore } from '@/store/modules/appStore';
@ -90,14 +89,14 @@ async function onUpdateClick(): Promise<void> {
try {
await userStore.updateUser(userInfo);
} catch (error) {
await notify.error(error.message, AnalyticsErrorEventSource.EDIT_PROFILE_MODAL);
notify.error(error.message, AnalyticsErrorEventSource.EDIT_PROFILE_MODAL);
return;
}
analytics.eventTriggered(AnalyticsEvent.PROFILE_UPDATED);
await notify.success('Account info successfully updated!');
notify.success('Account info successfully updated!');
closeModal();
}
@ -106,7 +105,7 @@ async function onUpdateClick(): Promise<void> {
* Closes modal.
*/
function closeModal(): void {
appStore.updateActiveModal(MODALS.editProfile);
appStore.removeActiveModal();
}
</script>
@ -120,15 +119,15 @@ function closeModal(): void {
min-width: 530px;
box-sizing: border-box;
@media screen and (max-width: 580px) {
@media screen and (width <= 580px) {
min-width: 450px;
}
@media screen and (max-width: 500px) {
@media screen and (width <= 500px) {
min-width: unset;
}
@media screen and (max-width: 400px) {
@media screen and (width <= 400px) {
padding: 24px;
}
@ -137,7 +136,7 @@ function closeModal(): void {
align-items: center;
margin-bottom: 30px;
@media screen and (max-width: 400px) {
@media screen and (width <= 400px) {
margin-bottom: 0;
}
@ -151,7 +150,7 @@ function closeModal(): void {
background: #e8eaf2;
margin-right: 20px;
@media screen and (max-width: 400px) {
@media screen and (width <= 400px) {
display: none;
}
@ -179,7 +178,7 @@ function closeModal(): void {
margin-top: 40px;
column-gap: 20px;
@media screen and (max-width: 400px) {
@media screen and (width <= 400px) {
flex-direction: column-reverse;
column-gap: unset;
row-gap: 10px;

View File

@ -54,13 +54,12 @@
<script setup lang="ts">
import { computed, onMounted, ref } from 'vue';
import { useNotify, useRouter } from '@/utils/hooks';
import { useNotify } from '@/utils/hooks';
import { Duration } from '@/utils/time';
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
import { useUsersStore } from '@/store/modules/usersStore';
import { useAppStore } from '@/store/modules/appStore';
import { useLoading } from '@/composables/useLoading';
import { RouteConfig } from '@/router';
import VButton from '@/components/common/VButton.vue';
import VModal from '@/components/common/VModal.vue';
@ -71,7 +70,6 @@ import Icon from '@/../static/images/session/inactivityTimer.svg';
const appStore = useAppStore();
const usersStore = useUsersStore();
const notify = useNotify();
const router = useRouter();
const { isLoading, withLoading } = useLoading();
const sessionDuration = ref<Duration | null>(null);
@ -146,7 +144,7 @@ function onClose(): void {
gap: 20px;
margin: 20px 0;
@media screen and (max-width: 500px) {
@media screen and (width <= 500px) {
flex-direction: column;
align-items: flex-start;
gap: 10px;
@ -186,7 +184,7 @@ function onClose(): void {
display: flex;
gap: 16px;
@media screen and (max-width: 500px) {
@media screen and (width <= 500px) {
flex-direction: column-reverse;
}

View File

@ -82,7 +82,6 @@ import { computed, onMounted, ref } from 'vue';
import { AnalyticsHttpApi } from '@/api/analytics';
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
import { MODALS } from '@/utils/constants/appStatePopUps';
import { useNotify } from '@/utils/hooks';
import { useUsersStore } from '@/store/modules/usersStore';
import { useAppStore } from '@/store/modules/appStore';
@ -142,7 +141,7 @@ function showEnable(): void {
* Closes enable MFA modal.
*/
function closeModal(): void {
appStore.updateActiveModal(MODALS.enableMFA);
appStore.removeActiveModal();
}
/**
@ -212,7 +211,7 @@ onMounted(async (): Promise<void> => {
align-items: center;
font-family: 'font_regular', sans-serif;
@media screen and (max-width: 550px) {
@media screen and (width <= 550px) {
padding: 48px 24px;
}
@ -224,7 +223,7 @@ onMounted(async (): Promise<void> => {
color: #000;
margin: 0 0 30px;
@media screen and (max-width: 550px) {
@media screen and (width <= 550px) {
font-size: 24px;
line-height: 28px;
margin-bottom: 15px;
@ -238,7 +237,7 @@ onMounted(async (): Promise<void> => {
color: #000;
margin: 0 0 45px;
@media screen and (max-width: 550px) {
@media screen and (width <= 550px) {
font-size: 14px;
line-height: 18px;
margin-bottom: 20px;
@ -254,7 +253,7 @@ onMounted(async (): Promise<void> => {
align-items: center;
width: calc(100% - 50px);
@media screen and (max-width: 550px) {
@media screen and (width <= 550px) {
padding: 15px;
width: calc(100% - 30px);
}
@ -267,7 +266,7 @@ onMounted(async (): Promise<void> => {
color: #000;
margin: 0 0 30px;
@media screen and (max-width: 550px) {
@media screen and (width <= 550px) {
margin-bottom: 15px;
}
}
@ -289,7 +288,7 @@ onMounted(async (): Promise<void> => {
height: 200px !important;
width: 200px !important;
@media screen and (max-width: 550px) {
@media screen and (width <= 550px) {
height: unset !important;
width: 100% !important;
}
@ -333,7 +332,7 @@ onMounted(async (): Promise<void> => {
margin-top: 30px;
column-gap: 20px;
@media screen and (max-width: 550px) {
@media screen and (width <= 550px) {
flex-direction: column-reverse;
column-gap: unset;
row-gap: 10px;

View File

@ -45,14 +45,12 @@
</template>
<script setup lang="ts">
import { reactive, ref } from 'vue';
import { ref } from 'vue';
import AccessEncryptionIcon from '../../../static/images/accessGrants/newCreateFlow/accessEncryption.svg';
import { AnalyticsHttpApi } from '@/api/analytics';
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
import { RouteConfig } from '@/router';
import { useRouter } from '@/utils/hooks';
import { useAppStore } from '@/store/modules/appStore';
import { useBucketsStore } from '@/store/modules/bucketsStore';
import { MODALS } from '@/utils/constants/appStatePopUps';
@ -63,8 +61,6 @@ import VButton from '@/components/common/VButton.vue';
const bucketsStore = useBucketsStore();
const appStore = useAppStore();
const nativeRouter = useRouter();
const router = reactive(nativeRouter);
const analytics: AnalyticsHttpApi = new AnalyticsHttpApi();
@ -153,7 +149,7 @@ function setPassphrase(value: string): void {
margin-top: 31px;
width: 100%;
@media screen and (max-width: 500px) {
@media screen and (width <= 500px) {
flex-direction: column-reverse;
column-gap: unset;
row-gap: 20px;

View File

@ -32,7 +32,6 @@
<script setup lang="ts">
import { computed } from 'vue';
import { MODALS } from '@/utils/constants/appStatePopUps';
import { useUsersStore } from '@/store/modules/usersStore';
import { useAppStore } from '@/store/modules/appStore';
@ -53,7 +52,7 @@ const userMFARecoveryCodes = computed((): string[] => {
* Closes modal.
*/
function closeModal(): void {
appStore.updateActiveModal(MODALS.mfaRecovery);
appStore.removeActiveModal();
}
</script>
@ -67,7 +66,7 @@ function closeModal(): void {
align-items: center;
font-family: 'font_regular', sans-serif;
@media screen and (max-width: 550px) {
@media screen and (width <= 550px) {
padding: 48px 24px;
}
@ -79,7 +78,7 @@ function closeModal(): void {
color: #000;
margin: 0 0 30px;
@media screen and (max-width: 550px) {
@media screen and (width <= 550px) {
font-size: 24px;
line-height: 28px;
margin-bottom: 15px;
@ -103,7 +102,7 @@ function closeModal(): void {
margin: 0 0 30px;
max-width: 485px;
@media screen and (max-width: 550px) {
@media screen and (width <= 550px) {
font-size: 14px;
line-height: 18px;
margin-bottom: 15px;

View File

@ -34,7 +34,7 @@ const analytics: AnalyticsHttpApi = new AnalyticsHttpApi();
*/
function onCloseClick(): void {
analytics.eventTriggered(AnalyticsEvent.COUPON_CODE_APPLIED);
appStore.updateActiveModal(MODALS.newBillingAddCoupon);
appStore.removeActiveModal();
}
</script>
@ -44,7 +44,7 @@ function onCloseClick(): void {
padding: 32px;
font-family: 'font_regular', sans-serif;
@media screen and (max-width: 650px) {
@media screen and (width <= 650px) {
width: unset;
padding: 24px;
}

View File

@ -76,6 +76,7 @@
<script setup lang="ts">
import { ref } from 'vue';
import { useRouter } from 'vue-router';
import { RouteConfig } from '@/router';
import { ProjectFields } from '@/types/projects';
@ -83,7 +84,7 @@ import { LocalData } from '@/utils/localData';
import { AnalyticsHttpApi } from '@/api/analytics';
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
import { MODALS } from '@/utils/constants/appStatePopUps';
import { useNotify, useRouter } from '@/utils/hooks';
import { useNotify } from '@/utils/hooks';
import { useUsersStore } from '@/store/modules/usersStore';
import { useProjectMembersStore } from '@/store/modules/projectMembersStore';
import { useAppStore } from '@/store/modules/appStore';
@ -254,7 +255,7 @@ function closeModal(): void {
}
}
@media screen and (max-width: 550px) {
@media screen and (width <= 550px) {
width: calc(100% - 48px);
padding: 54px 24px 32px;
}
@ -274,7 +275,7 @@ function closeModal(): void {
justify-content: space-between;
column-gap: 20px;
@media screen and (max-width: 550px) {
@media screen and (width <= 550px) {
column-gap: unset;
row-gap: 8px;
flex-direction: column-reverse;
@ -305,7 +306,7 @@ function closeModal(): void {
margin-top: 20px;
}
@media screen and (max-width: 550px) {
@media screen and (width <= 550px) {
:deep(.add-label) {
display: none;

View File

@ -41,7 +41,6 @@
import { computed, ref } from 'vue';
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
import { MODALS } from '@/utils/constants/appStatePopUps';
import { useNotify } from '@/utils/hooks';
import { useAppStore } from '@/store/modules/appStore';
import { BrowserObject, useObjectBrowserStore } from '@/store/modules/objectBrowserStore';
@ -94,7 +93,7 @@ const createFolderEnabled = computed((): boolean => {
* Close the NewFolderModal.
*/
function close(): void {
appStore.updateActiveModal(MODALS.newFolder);
appStore.removeActiveModal();
}
/**
@ -144,7 +143,7 @@ async function createFolder(): Promise<void> {
flex-direction: column;
font-family: 'font_regular', sans-serif;
@media screen and (max-width: 450px) {
@media screen and (width <= 450px) {
width: 320px;
}
@ -165,7 +164,7 @@ async function createFolder(): Promise<void> {
margin-top: 30px;
column-gap: 20px;
@media screen and (max-width: 550px) {
@media screen and (width <= 550px) {
margin-top: 20px;
column-gap: unset;
row-gap: 8px;

View File

@ -118,7 +118,6 @@ import { computed, onBeforeMount, ref, watch } from 'vue';
import prettyBytes from 'pretty-bytes';
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
import { MODALS } from '@/utils/constants/appStatePopUps';
import { useNotify } from '@/utils/hooks';
import { BrowserObject, useObjectBrowserStore } from '@/store/modules/objectBrowserStore';
import { useAppStore } from '@/store/modules/appStore';
@ -274,7 +273,7 @@ function download(): void {
* Close the current opened file details modal.
*/
function closeModal(): void {
appStore.updateActiveModal(MODALS.objectDetails);
appStore.removeActiveModal();
}
/**
@ -282,7 +281,7 @@ function closeModal(): void {
*/
async function copy(): Promise<void> {
await navigator.clipboard.writeText(objectLink.value);
await notify.success('Link copied successfully.');
notify.success('Link copied successfully.');
copyText.value = 'Copied!';
setTimeout(() => {
@ -323,24 +322,24 @@ watch(filePath, () => {
width: 1140px;
max-width: 1140px;
@media screen and (max-width: 1200px) {
@media screen and (width <= 1200px) {
width: 800px;
max-width: 800px;
}
@media screen and (max-width: 900px) {
@media screen and (width <= 900px) {
width: 600px;
max-width: 600px;
}
@media screen and (max-width: 660px) {
@media screen and (width <= 660px) {
flex-direction: column-reverse;
width: calc(100vw - 50px);
min-width: calc(100vw - 50px);
max-width: calc(100vw - 50px);
}
@media screen and (max-width: 400px) {
@media screen and (width <= 400px) {
width: calc(100vw - 20px);
min-width: calc(100vw - 20px);
max-width: calc(100vw - 20px);
@ -354,12 +353,12 @@ watch(filePath, () => {
align-items: center;
justify-content: center;
@media screen and (max-width: 900px) {
@media screen and (width <= 900px) {
width: 60%;
max-width: 60%;
}
@media screen and (max-width: 660px) {
@media screen and (width <= 660px) {
width: 100%;
min-width: 100%;
max-width: 100%;
@ -368,7 +367,7 @@ watch(filePath, () => {
border-radius: 0 0 10px 10px;
}
@media screen and (max-width: 500px) {
@media screen and (width <= 500px) {
min-height: 30vh;
}
}
@ -383,19 +382,19 @@ watch(filePath, () => {
align-items: flex-start;
align-self: flex-start;
@media screen and (max-width: 900px) {
@media screen and (width <= 900px) {
width: 40%;
max-width: 40%;
}
@media screen and (max-width: 660px) {
@media screen and (width <= 660px) {
width: 100%;
min-width: 100%;
max-width: 100%;
padding-bottom: 0;
}
@media screen and (max-width: 400px) {
@media screen and (width <= 400px) {
padding: 64px 20px 0;
}
@ -429,17 +428,17 @@ watch(filePath, () => {
align-items: center;
width: 100%;
@media screen and (max-width: 1200px) {
@media screen and (width <= 1200px) {
flex-direction: column;
align-items: flex-start;
}
@media screen and (max-width: 660px) {
@media screen and (width <= 660px) {
flex-direction: row;
align-items: center;
}
@media screen and (max-width: 400px) {
@media screen and (width <= 400px) {
flex-direction: column;
align-items: flex-start;
}

View File

@ -59,13 +59,13 @@
<script setup lang="ts">
import { computed, ref } from 'vue';
import { useRouter } from 'vue-router';
import { RouteConfig } from '@/router';
import { AnalyticsHttpApi } from '@/api/analytics';
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
import { Bucket } from '@/types/buckets';
import { MODALS } from '@/utils/constants/appStatePopUps';
import { useNotify, useRouter } from '@/utils/hooks';
import { useNotify } from '@/utils/hooks';
import { useAppStore } from '@/store/modules/appStore';
import { useBucketsStore } from '@/store/modules/bucketsStore';
import { useProjectsStore } from '@/store/modules/projectsStore';
@ -161,7 +161,7 @@ async function onContinue(): Promise<void> {
function closeModal(): void {
if (isLoading.value) return;
appStore.updateActiveModal(MODALS.openBucket);
appStore.removeActiveModal();
}
/**
@ -244,7 +244,7 @@ function setPassphrase(value: string): void {
margin-top: 31px;
width: 100%;
@media screen and (max-width: 500px) {
@media screen and (width <= 500px) {
flex-direction: column-reverse;
column-gap: unset;
row-gap: 20px;

View File

@ -79,10 +79,11 @@
<script setup lang="ts">
import { computed, ref, watch } from 'vue';
import { useRouter } from 'vue-router';
import { RouteConfig } from '@/router';
import { PricingPlanInfo, PricingPlanType } from '@/types/common';
import { useNotify, useRouter } from '@/utils/hooks';
import { useNotify } from '@/utils/hooks';
import { useUsersStore } from '@/store/modules/usersStore';
import { useBillingStore } from '@/store/modules/billingStore';
import { useAppStore } from '@/store/modules/appStore';

View File

@ -50,22 +50,19 @@
</template>
<script setup lang="ts">
import { computed, onMounted, ref } from 'vue';
import { computed } from 'vue';
import { useRouter } from 'vue-router';
import { RouteConfig } from '@/router';
import { AnalyticsHttpApi } from '@/api/analytics';
import { Project } from '@/types/projects';
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
import { useNotify, useRouter } from '@/utils/hooks';
import { LocalData } from '@/utils/localData';
import { MODALS } from '@/utils/constants/appStatePopUps';
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
import { useNotify } from '@/utils/hooks';
import { useAppStore } from '@/store/modules/appStore';
import { useProjectsStore } from '@/store/modules/projectsStore';
import { useProjectMembersStore } from '@/store/modules/projectMembersStore';
import { useConfigStore } from '@/store/modules/configStore';
import VLoader from '@/components/common/VLoader.vue';
import VInput from '@/components/common/VInput.vue';
import VModal from '@/components/common/VModal.vue';
import VButton from '@/components/common/VButton.vue';
@ -112,11 +109,11 @@ async function onRemove(): Promise<void> {
await pmStore.deleteProjectMembers(projectsStore.state.selectedProject.id);
await setProjectState();
} catch (error) {
await notify.error(`Error while deleting users from projectMembers. ${error.message}`, AnalyticsErrorEventSource.PROJECT_MEMBERS_HEADER);
notify.error(`Error while deleting users from projectMembers. ${error.message}`, AnalyticsErrorEventSource.PROJECT_MEMBERS_HEADER);
return;
}
await notify.success('Members were successfully removed from project');
notify.success('Members were successfully removed from project');
pmStore.setSearchQuery('');
closeModal();
}
@ -125,7 +122,7 @@ async function onRemove(): Promise<void> {
* Closes remove team member modal.
*/
function closeModal(): void {
appStore.updateActiveModal(MODALS.removeTeamMember);
appStore.removeActiveModal();
}
</script>
@ -137,7 +134,7 @@ function closeModal(): void {
flex-direction: column;
max-width: 350px;
@media screen and (max-width: 615px) {
@media screen and (width <= 615px) {
padding: 30px 20px;
}
@ -207,7 +204,7 @@ function closeModal(): void {
margin-top: 16px;
column-gap: 20px;
@media screen and (max-width: 600px) {
@media screen and (width <= 600px) {
margin-top: 20px;
column-gap: unset;
row-gap: 8px;

View File

@ -44,7 +44,6 @@ import { computed, onMounted, ref } from 'vue';
import { AccessGrant, EdgeCredentials } from '@/types/accessGrants';
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
import { MODALS } from '@/utils/constants/appStatePopUps';
import { useNotify } from '@/utils/hooks';
import { useAppStore } from '@/store/modules/appStore';
import { useAccessGrantsStore } from '@/store/modules/accessGrantsStore';
@ -193,7 +192,7 @@ function setWorker(): void {
function closeModal(): void {
if (isLoading.value) return;
appStore.updateActiveModal(MODALS.shareBucket);
appStore.removeActiveModal();
}
onMounted(async () => {
@ -211,7 +210,7 @@ onMounted(async () => {
padding: 50px;
max-width: 470px;
@media screen and (max-width: 430px) {
@media screen and (width <= 430px) {
padding: 20px;
}
@ -247,7 +246,7 @@ onMounted(async () => {
margin-top: 32px;
width: 100%;
@media screen and (max-width: 430px) {
@media screen and (width <= 430px) {
flex-direction: column-reverse;
column-gap: unset;
row-gap: 15px;
@ -274,7 +273,7 @@ onMounted(async () => {
max-width: 340px;
width: 100%;
@media screen and (max-width: 430px) {
@media screen and (width <= 430px) {
max-width: 210px;
}
}

View File

@ -42,7 +42,6 @@
<script setup lang="ts">
import { computed, onMounted, ref } from 'vue';
import { MODALS } from '@/utils/constants/appStatePopUps';
import { useNotify } from '@/utils/hooks';
import { useAppStore } from '@/store/modules/appStore';
import { useObjectBrowserStore } from '@/store/modules/objectBrowserStore';
@ -94,7 +93,7 @@ async function onCopy(): Promise<void> {
function closeModal(): void {
if (isLoading.value) return;
appStore.updateActiveModal(MODALS.shareObject);
appStore.removeActiveModal();
}
/**
@ -119,7 +118,7 @@ onMounted(async (): Promise<void> => {
padding: 50px;
max-width: 470px;
@media screen and (max-width: 430px) {
@media screen and (width <= 430px) {
padding: 20px;
}
@ -155,7 +154,7 @@ onMounted(async (): Promise<void> => {
margin-top: 32px;
width: 100%;
@media screen and (max-width: 430px) {
@media screen and (width <= 430px) {
flex-direction: column-reverse;
column-gap: unset;
row-gap: 15px;
@ -182,7 +181,7 @@ onMounted(async (): Promise<void> => {
max-width: 340px;
width: 100%;
@media screen and (max-width: 430px) {
@media screen and (width <= 430px) {
max-width: 210px;
}
}

View File

@ -110,7 +110,7 @@ function closeModal(): void {
margin-top: 31px;
width: 100%;
@media screen and (max-width: 500px) {
@media screen and (width <= 500px) {
flex-direction: column-reverse;
column-gap: unset;
row-gap: 20px;

View File

@ -37,11 +37,11 @@
</template>
<script setup lang="ts">
import { reactive, ref } from 'vue';
import { ref } from 'vue';
import { generateMnemonic } from 'bip39';
import { useRoute, useRouter } from 'vue-router';
import { useNotify, useRouter } from '@/utils/hooks';
import { MODALS } from '@/utils/constants/appStatePopUps';
import { useNotify } from '@/utils/hooks';
import { RouteConfig } from '@/router';
import { EdgeCredentials } from '@/types/accessGrants';
import { useAppStore } from '@/store/modules/appStore';
@ -69,8 +69,8 @@ enum CreatePassphraseOption {
const bucketsStore = useBucketsStore();
const appStore = useAppStore();
const notify = useNotify();
const nativeRouter = useRouter();
const router = reactive(nativeRouter);
const router = useRouter();
const route = useRoute();
const generatedPassphrase = generateMnemonic();
@ -99,7 +99,7 @@ function setOption(option: CreatePassphraseOption): void {
* Closes modal.
*/
function closeModal(): void {
appStore.updateActiveModal(MODALS.createProjectPassphrase);
appStore.removeActiveModal();
}
/**
@ -146,7 +146,7 @@ async function onContinue(): Promise<void> {
}
if (activeStep.value === CreateProjectPassphraseStep.Success) {
if (router.currentRoute.name === RouteConfig.OverviewStep.name) {
if (route.name === RouteConfig.OverviewStep.name) {
router.push(RouteConfig.ProjectDashboard.path);
}
@ -179,7 +179,7 @@ function onCancelOrBack(): void {
padding: 32px;
font-family: 'font_regular', sans-serif;
@media screen and (max-width: 615px) {
@media screen and (width <= 615px) {
padding: 30px 20px;
}
}

View File

@ -31,7 +31,6 @@
<script setup lang="ts">
import { useNotify } from '@/utils/hooks';
import { MODALS } from '@/utils/constants/appStatePopUps';
import { useAppStore } from '@/store/modules/appStore';
import { useBucketsStore } from '@/store/modules/bucketsStore';
@ -52,7 +51,7 @@ const notify = useNotify();
*/
function onClear(): void {
bucketsStore.clearS3Data();
appStore.updateActiveModal(MODALS.manageProjectPassphrase);
appStore.removeActiveModal();
notify.success('Passphrase was cleared successfully');
}
</script>
@ -81,7 +80,7 @@ function onClear(): void {
column-gap: 16px;
width: 100%;
@media screen and (max-width: 530px) {
@media screen and (width <= 530px) {
column-gap: unset;
flex-direction: column-reverse;
row-gap: 15px;

View File

@ -47,7 +47,6 @@ const appStore = useAppStore();
* Starts create new passphrase flow.
*/
function onNext(): void {
appStore.updateActiveModal(MODALS.manageProjectPassphrase);
appStore.updateActiveModal(MODALS.createProjectPassphrase);
}
</script>
@ -76,7 +75,7 @@ function onNext(): void {
column-gap: 16px;
width: 100%;
@media screen and (max-width: 530px) {
@media screen and (width <= 530px) {
column-gap: unset;
flex-direction: column-reverse;
row-gap: 15px;

View File

@ -37,7 +37,6 @@
import { computed, onMounted, ref } from 'vue';
import { useNotify } from '@/utils/hooks';
import { MODALS } from '@/utils/constants/appStatePopUps';
import { ManageProjectPassphraseStep } from '@/types/managePassphrase';
import { useAppStore } from '@/store/modules/appStore';
@ -111,7 +110,7 @@ function setManageOptions(): void {
* Closes modal.
*/
function closeModal(): void {
appStore.updateActiveModal(MODALS.manageProjectPassphrase);
appStore.removeActiveModal();
}
onMounted(() => {
@ -123,7 +122,7 @@ onMounted(() => {
.modal {
padding: 32px;
@media screen and (max-width: 615px) {
@media screen and (width <= 615px) {
padding: 30px 20px;
}

View File

@ -43,7 +43,6 @@
import { ref } from 'vue';
import { useNotify } from '@/utils/hooks';
import { MODALS } from '@/utils/constants/appStatePopUps';
import { EdgeCredentials } from '@/types/accessGrants';
import { useAppStore } from '@/store/modules/appStore';
import { useBucketsStore } from '@/store/modules/bucketsStore';
@ -92,7 +91,7 @@ async function onSwitch(): Promise<void> {
bucketsStore.setPromptForPassphrase(false);
notify.success('Passphrase was switched successfully');
appStore.updateActiveModal(MODALS.manageProjectPassphrase);
appStore.removeActiveModal();
}
</script>
@ -124,7 +123,7 @@ async function onSwitch(): Promise<void> {
border-top: 1px solid var(--c-grey-2);
width: 100%;
@media screen and (max-width: 530px) {
@media screen and (width <= 530px) {
column-gap: unset;
flex-direction: column-reverse;
row-gap: 15px;

View File

@ -31,10 +31,11 @@
<script setup lang="ts">
import { ref } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
import { RouteConfig } from '@/router';
import { useNotify, useRouter } from '@/utils/hooks';
import { useNotify } from '@/utils/hooks';
import { useBillingStore } from '@/store/modules/billingStore';
import { useUsersStore } from '@/store/modules/usersStore';
import { useProjectsStore } from '@/store/modules/projectsStore';
@ -53,6 +54,7 @@ const billingStore = useBillingStore();
const projectsStore = useProjectsStore();
const notify = useNotify();
const router = useRouter();
const route = useRoute();
const props = defineProps<{
setSuccess: () => void;
@ -91,11 +93,11 @@ async function addCardToDB(token: string): Promise<void> {
// We fetch User one more time to update their Paid Tier status.
await usersStore.getUser();
if (router.currentRoute.name === RouteConfig.ProjectDashboard.name) {
if (route.name === RouteConfig.ProjectDashboard.name) {
await projectsStore.getProjectLimits(projectsStore.state.selectedProject.id);
}
if (router.currentRoute.path.includes(RouteConfig.Billing.path) || router.currentRoute.path.includes(RouteConfig.Billing2.path)) {
if (route.path.includes(RouteConfig.Billing.path) || route.path.includes(RouteConfig.Billing2.path)) {
await billingStore.getCreditCards();
}
@ -104,7 +106,7 @@ async function addCardToDB(token: string): Promise<void> {
loading.value = false;
props.setSuccess();
} catch (error) {
await notify.error(error.message, AnalyticsErrorEventSource.UPGRADE_ACCOUNT_MODAL);
notify.error(error.message, AnalyticsErrorEventSource.UPGRADE_ACCOUNT_MODAL);
loading.value = false;
}
}

View File

@ -110,11 +110,11 @@ onMounted(async (): Promise<void> => {
max-width: 482px;
font-family: 'font_regular', sans-serif;
@media screen and (max-width: 600px) {
@media screen and (width <= 600px) {
max-width: 350px;
}
@media screen and (max-width: 470px) {
@media screen and (width <= 470px) {
max-width: 280px;
}

View File

@ -12,10 +12,10 @@
</template>
<script setup lang="ts">
import Vue, { VueConstructor } from 'vue';
import { Component } from 'vue';
const props = defineProps<{
icon?: VueConstructor<Vue>;
icon?: Component;
title: string;
}>();
</script>
@ -25,7 +25,7 @@ const props = defineProps<{
padding: 32px;
font-family: 'font_bold', sans-serif;
@media screen and (max-width: 350px) {
@media screen and (width <= 350px) {
padding: 32px 16px;
}
@ -36,7 +36,7 @@ const props = defineProps<{
margin-bottom: 16px;
border-bottom: 1px solid var(--c-grey-2);
@media screen and (max-width: 690px) {
@media screen and (width <= 690px) {
display: none;
}

View File

@ -121,7 +121,7 @@ onBeforeMount(() => {
&__column {
&:first-of-type {
@media screen and (max-width: 690px) {
@media screen and (width <= 690px) {
display: none;
}
}

View File

@ -70,7 +70,7 @@ const props = defineProps<{
align-items: center;
column-gap: 16px;
@media screen and (max-width: 520px) {
@media screen and (width <= 520px) {
flex-direction: column;
column-gap: unset;
row-gap: 16px;

View File

@ -53,6 +53,7 @@
<script setup lang="ts">
import { computed, ref } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { User } from '@/types/users';
import { RouteConfig } from '@/router';
@ -60,7 +61,7 @@ import { AuthHttpApi } from '@/api/auth';
import { AnalyticsHttpApi } from '@/api/analytics';
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
import { APP_STATE_DROPDOWNS, MODALS } from '@/utils/constants/appStatePopUps';
import { useNotify, useRouter } from '@/utils/hooks';
import { useNotify } from '@/utils/hooks';
import { useABTestingStore } from '@/store/modules/abTestingStore';
import { useUsersStore } from '@/store/modules/usersStore';
import { useProjectMembersStore } from '@/store/modules/projectMembersStore';
@ -85,6 +86,7 @@ import TierBadgeFree from '@/../static/images/navigation/tierBadgeFree.svg';
import TierBadgePro from '@/../static/images/navigation/tierBadgePro.svg';
const router = useRouter();
const route = useRoute();
const notify = useNotify();
const configStore = useConfigStore();
@ -149,7 +151,7 @@ function onUpgrade(): void {
function navigateToBilling(): void {
closeDropdown();
if (router.currentRoute.path.includes(RouteConfig.Billing.path)) return;
if (route.path.includes(RouteConfig.Billing.path)) return;
router.push(RouteConfig.Account.with(RouteConfig.Billing).with(RouteConfig.BillingOverview).path);
analytics.pageVisit(RouteConfig.Account.with(RouteConfig.Billing).with(RouteConfig.BillingOverview).path);
@ -186,10 +188,10 @@ async function onLogout(): Promise<void> {
]);
try {
analytics.eventTriggered(AnalyticsEvent.LOGOUT_CLICKED);
await analytics.eventTriggered(AnalyticsEvent.LOGOUT_CLICKED);
await auth.logout();
} catch (error) {
await notify.error(error.message, AnalyticsErrorEventSource.NAVIGATION_ACCOUNT_AREA);
notify.error(error.message, AnalyticsErrorEventSource.NAVIGATION_ACCOUNT_AREA);
}
}
@ -408,7 +410,7 @@ function closeDropdown(): void {
}
}
@media screen and (max-width: 1280px) and (min-width: 500px) {
@media screen and (width <= 1280px) and (width >= 500px) {
.account-area__wrap {
padding: 10px 0;

View File

@ -164,6 +164,7 @@
<script setup lang="ts">
import { computed, ref } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { AuthHttpApi } from '@/api/auth';
import { AnalyticsHttpApi } from '@/api/analytics';
@ -174,7 +175,7 @@ import { User } from '@/types/users';
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
import { LocalData } from '@/utils/localData';
import { MODALS } from '@/utils/constants/appStatePopUps';
import { useNotify, useRouter } from '@/utils/hooks';
import { useNotify } from '@/utils/hooks';
import { useABTestingStore } from '@/store/modules/abTestingStore';
import { useUsersStore } from '@/store/modules/usersStore';
import { useProjectMembersStore } from '@/store/modules/projectMembersStore';
@ -237,6 +238,7 @@ const projectsStore = useProjectsStore();
const obStore = useObjectBrowserStore();
const router = useRouter();
const route = useRoute();
const notify = useNotify();
const analytics: AnalyticsHttpApi = new AnalyticsHttpApi();
@ -267,7 +269,7 @@ const projects = computed((): Project[] => {
* Indicates if current route is objects view.
*/
const isBucketsView = computed((): boolean => {
return router.currentRoute.path.includes(RouteConfig.BucketsManagement.path);
return route.path.includes(RouteConfig.BucketsManagement.path);
});
/**
@ -300,7 +302,7 @@ function onLogoClick(): void {
return;
}
if (router.currentRoute.name === RouteConfig.ProjectDashboard.name) {
if (route.name === RouteConfig.ProjectDashboard.name) {
return;
}
@ -406,7 +408,7 @@ async function onProjectSelected(projectID: string): Promise<void> {
projectsStore.getProjectLimits(projectID),
]);
} catch (error) {
await notify.error(`Unable to select project. ${error.message}`, AnalyticsErrorEventSource.MOBILE_NAVIGATION);
notify.error(`Unable to select project. ${error.message}`, AnalyticsErrorEventSource.MOBILE_NAVIGATION);
}
}
@ -414,7 +416,7 @@ async function onProjectSelected(projectID: string): Promise<void> {
* Route to projects list page.
*/
function onProjectsLinkClick(): void {
if (router.currentRoute.name !== RouteConfig.ProjectsList.name) {
if (route.name !== RouteConfig.ProjectsList.name) {
analytics.pageVisit(RouteConfig.ProjectsList.path);
analytics.eventTriggered(AnalyticsEvent.MANAGE_PROJECTS_CLICKED);
router.push(RouteConfig.ProjectsList.path);
@ -427,7 +429,7 @@ function onProjectsLinkClick(): void {
* Route to create project page.
*/
function onCreateLinkClick(): void {
if (router.currentRoute.name !== RouteConfig.CreateProject.name) {
if (route.name !== RouteConfig.CreateProject.name) {
analytics.eventTriggered(AnalyticsEvent.CREATE_NEW_CLICKED);
const user: User = usersStore.state.user;
@ -457,7 +459,7 @@ function onUpgrade(): void {
*/
function navigateToBilling(): void {
isOpened.value = false;
if (router.currentRoute.path.includes(RouteConfig.Billing.path)) return;
if (route.path.includes(RouteConfig.Billing.path)) return;
let link = RouteConfig.Account.with(RouteConfig.Billing);
if (configStore.state.config.newBillingScreen) {
@ -501,7 +503,7 @@ async function onLogout(): Promise<void> {
analytics.eventTriggered(AnalyticsEvent.LOGOUT_CLICKED);
await auth.logout();
} catch (error) {
await notify.error(error.message, AnalyticsErrorEventSource.MOBILE_NAVIGATION);
notify.error(error.message, AnalyticsErrorEventSource.MOBILE_NAVIGATION);
}
}
</script>

View File

@ -80,13 +80,13 @@
</template>
<script setup lang="ts">
import { computed, onBeforeUnmount, onMounted, reactive, ref } from 'vue';
import { computed, onBeforeUnmount, onMounted, ref } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { AnalyticsHttpApi } from '@/api/analytics';
import { RouteConfig } from '@/router';
import { NavigationLink } from '@/types/navigation';
import { APP_STATE_DROPDOWNS } from '@/utils/constants/appStatePopUps';
import { useRouter } from '@/utils/hooks';
import { useAppStore } from '@/store/modules/appStore';
import { useConfigStore } from '@/store/modules/configStore';
@ -108,8 +108,8 @@ import ArrowIcon from '@/../static/images/navigation/arrowExpandRight.svg';
const configStore = useConfigStore();
const appStore = useAppStore();
const nativeRouter = useRouter();
const router = reactive(nativeRouter);
const router = useRouter();
const route = useRoute();
const TWENTY_PIXELS = 20;
const analytics: AnalyticsHttpApi = new AnalyticsHttpApi();
@ -167,7 +167,7 @@ function onLogoClick(): void {
return;
}
if (router.currentRoute.name === RouteConfig.ProjectDashboard.name) {
if (route.name === RouteConfig.ProjectDashboard.name) {
return;
}
@ -461,7 +461,7 @@ onBeforeUnmount(() => {
color: var(--c-blue-3);
}
@media screen and (max-width: 1280px) {
@media screen and (width <= 1280px) {
.navigation-area {
min-width: unset;

View File

@ -63,7 +63,8 @@
</template>
<script setup lang="ts">
import { computed, reactive, ref } from 'vue';
import { computed, ref } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { AnalyticsHttpApi } from '@/api/analytics';
import { RouteConfig } from '@/router';
@ -72,7 +73,7 @@ import { LocalData } from '@/utils/localData';
import { Project } from '@/types/projects';
import { User } from '@/types/users';
import { APP_STATE_DROPDOWNS, MODALS } from '@/utils/constants/appStatePopUps';
import { useNotify, useRouter } from '@/utils/hooks';
import { useNotify } from '@/utils/hooks';
import { useUsersStore } from '@/store/modules/usersStore';
import { useProjectMembersStore } from '@/store/modules/projectMembersStore';
import { useBillingStore } from '@/store/modules/billingStore';
@ -100,8 +101,8 @@ const userStore = useUsersStore();
const projectsStore = useProjectsStore();
const configStore = useConfigStore();
const notify = useNotify();
const nativeRouter = useRouter();
const router = reactive(nativeRouter);
const router = useRouter();
const route = useRoute();
const FIRST_PAGE = 1;
const analytics: AnalyticsHttpApi = new AnalyticsHttpApi();
@ -122,7 +123,7 @@ const style = computed((): Record<string, string> => {
* Indicates if current route is onboarding tour.
*/
const isOnboardingTour = computed((): boolean => {
return router.currentRoute.path.includes(RouteConfig.OnboardingTour.path);
return route.path.includes(RouteConfig.OnboardingTour.path);
});
/**
@ -157,7 +158,7 @@ const selectedProject = computed((): Project => {
* Indicates if current route is objects view.
*/
const isBucketsView = computed((): boolean => {
return router.currentRoute.path.includes(RouteConfig.Buckets.path);
return route.path.includes(RouteConfig.Buckets.path);
});
/**
@ -219,7 +220,7 @@ async function onProjectSelected(projectID: string): Promise<void> {
return;
}
if (router.currentRoute.name === RouteConfig.ProjectDashboard.name) {
if (route.name === RouteConfig.ProjectDashboard.name) {
const now = new Date();
const past = new Date();
past.setDate(past.getDate() - 30);
@ -240,7 +241,7 @@ async function onProjectSelected(projectID: string): Promise<void> {
return;
}
if (router.currentRoute.name === RouteConfig.AccessGrants.name) {
if (route.name === RouteConfig.AccessGrants.name) {
try {
await agStore.getAccessGrants(FIRST_PAGE, projectID);
} catch (error) {
@ -250,7 +251,7 @@ async function onProjectSelected(projectID: string): Promise<void> {
return;
}
if (router.currentRoute.name === RouteConfig.Team.name) {
if (route.name === RouteConfig.Team.name) {
try {
await pmStore.getProjectMembers(FIRST_PAGE, selectedProject.value.id);
} catch (error) {
@ -270,7 +271,7 @@ function closeDropdown(): void {
* Route to projects list page.
*/
function onProjectsLinkClick(): void {
if (router.currentRoute.name !== RouteConfig.ProjectsList.name) {
if (route.name !== RouteConfig.ProjectsList.name) {
analytics.pageVisit(RouteConfig.ProjectsList.path);
analytics.eventTriggered(AnalyticsEvent.MANAGE_PROJECTS_CLICKED);
router.push(RouteConfig.ProjectsList.path);
@ -301,7 +302,7 @@ function onManagePassphraseClick(): void {
* Route to create project page.
*/
function onCreateLinkClick(): void {
if (router.currentRoute.name !== RouteConfig.CreateProject.name) {
if (route.name !== RouteConfig.CreateProject.name) {
analytics.eventTriggered(AnalyticsEvent.CREATE_NEW_CLICKED);
const user: User = userStore.state.user;
@ -526,7 +527,7 @@ function onCreateLinkClick(): void {
}
}
@media screen and (max-width: 1280px) and (min-width: 500px) {
@media screen and (width <= 1280px) and (width >= 500px) {
.project-selection__selected {
padding: 10px 0;

View File

@ -42,7 +42,7 @@
</template>
<script setup lang="ts">
import { reactive } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { AnalyticsHttpApi } from '@/api/analytics';
import { AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
@ -50,7 +50,6 @@ import { RouteConfig } from '@/router';
import { User } from '@/types/users';
import { AccessType } from '@/types/createAccessGrant';
import { MODALS } from '@/utils/constants/appStatePopUps';
import { useRouter } from '@/utils/hooks';
import { useUsersStore } from '@/store/modules/usersStore';
import { useAppStore } from '@/store/modules/appStore';
import { useProjectsStore } from '@/store/modules/projectsStore';
@ -64,8 +63,8 @@ import UploadInWebIcon from '@/../static/images/navigation/uploadInWeb.svg';
const appStore = useAppStore();
const usersStore = useUsersStore();
const projectsStore = useProjectsStore();
const nativeRouter = useRouter();
const router = reactive(nativeRouter);
const router = useRouter();
const route = useRoute();
const props = withDefaults(defineProps<{
closeDropdowns?: () => void;
@ -85,7 +84,7 @@ function navigateToCreateAG(): void {
analytics.pageVisit(RouteConfig.AccessGrants.with(RouteConfig.CreateAccessModal).path);
router.push({
name: RouteConfig.CreateAccessModal.name,
params: { accessType: AccessType.AccessGrant },
query: { accessType: AccessType.AccessGrant },
}).catch(() => {return;});
}
@ -99,7 +98,7 @@ function navigateToAccessGrantS3(): void {
analytics.pageVisit(RouteConfig.AccessGrants.with(RouteConfig.CreateAccessModal).path);
router.push({
name: RouteConfig.CreateAccessModal.name,
params: { accessType: AccessType.S3 },
query: { accessType: AccessType.S3 },
}).catch(() => {return;});
}
@ -119,7 +118,7 @@ function navigateToBuckets(): void {
function navigateToCLIFlow(): void {
analytics.eventTriggered(AnalyticsEvent.UPLOAD_USING_CLI_CLICKED);
props.closeDropdowns();
appStore.setOnboardingBackRoute(router.currentRoute.path);
appStore.setOnboardingBackRoute(route.path);
analytics.pageVisit(RouteConfig.OnboardingTour.with(RouteConfig.OnbCLIStep.with(RouteConfig.AGName)).path);
router.push({ name: RouteConfig.AGName.name });
}
@ -128,7 +127,7 @@ function navigateToCLIFlow(): void {
* Redirects to create access grant screen.
*/
function navigateToNewProject(): void {
if (router.currentRoute.name !== RouteConfig.CreateProject.name) {
if (route.name !== RouteConfig.CreateProject.name) {
analytics.eventTriggered(AnalyticsEvent.NEW_PROJECT_CLICKED);
const user: User = usersStore.state.user;

View File

@ -36,20 +36,19 @@
</template>
<script setup lang="ts">
import { computed, onMounted, reactive, ref } from 'vue';
import { computed, onMounted, ref } from 'vue';
import { useRoute } from 'vue-router';
import { DelayedNotification } from '@/types/DelayedNotification';
import { useNotificationsStore } from '@/store/modules/notificationsStore';
import { useConfigStore } from '@/store/modules/configStore';
import { RouteConfig } from '@/router';
import { useRouter } from '@/utils/hooks';
import CloseIcon from '@/../static/images/notifications/close.svg';
const configStore = useConfigStore();
const notificationsStore = useNotificationsStore();
const nativeRouter = useRouter();
const router = reactive(nativeRouter);
const route = useRoute();
const props = withDefaults(defineProps<{
notification: DelayedNotification;
@ -64,8 +63,8 @@ const isClassActive = ref<boolean>(false);
*/
const settingsRoute = computed((): string => {
if (
router.currentRoute.path.includes(RouteConfig.AllProjectsDashboard.path)
|| router.currentRoute.path.includes(RouteConfig.AccountSettings.path)
route.path.includes(RouteConfig.AllProjectsDashboard.path)
|| route.path.includes(RouteConfig.AccountSettings.path)
) {
return RouteConfig.AccountSettings.with(RouteConfig.Settings2).path;
}
@ -84,8 +83,8 @@ const requestURL = computed((): string => {
* Returns whether we are not on a settings page.
*/
const notOnSettingsPage = computed((): boolean => {
return router.currentRoute.name !== RouteConfig.Settings.name
&& router.currentRoute.name !== RouteConfig.Settings2.name;
return route.name !== RouteConfig.Settings.name
&& route.name !== RouteConfig.Settings2.name;
});
/**

View File

@ -17,17 +17,16 @@
</template>
<script setup lang="ts">
import { reactive } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { RouteConfig } from '@/router';
import { useRouter } from '@/utils/hooks';
import { useAppStore } from '@/store/modules/appStore';
import VBanner from '@/components/common/VBanner.vue';
const appStore = useAppStore();
const nativeRouter = useRouter();
const router = reactive(nativeRouter);
const router = useRouter();
const route = useRoute();
const props = defineProps<{
dashboardRef: HTMLElement
@ -39,7 +38,7 @@ const props = defineProps<{
function redirectToSettingsPage(): void {
onCloseClick();
if (router.currentRoute.path.includes(RouteConfig.AllProjectsDashboard.path)) {
if (route.path.includes(RouteConfig.AllProjectsDashboard.path)) {
router.push(RouteConfig.AccountSettings.with(RouteConfig.Settings2).path);
return;
}

View File

@ -13,15 +13,14 @@
</template>
<script setup lang="ts">
import Vue, { VueConstructor } from 'vue';
import { Component } from 'vue';
import CloseIcon from '@/../static/images/notifications/closeSmall.svg';
const props = defineProps<{
wordingBold: string;
wording: string;
notificationIcon: VueConstructor<Vue>;
notificationIcon: Component;
warningNotification: boolean;
onCloseClick: () => void;
}>();

Some files were not shown because too many files have changed in this diff Show More