diff --git a/web/satellite/src/components/objects/UploadCancelPopup.vue b/web/satellite/src/components/objects/UploadCancelPopup.vue
new file mode 100644
index 000000000..45a49e946
--- /dev/null
+++ b/web/satellite/src/components/objects/UploadCancelPopup.vue
@@ -0,0 +1,134 @@
+// Copyright (C) 2021 Storj Labs, Inc.
+// See LICENSE for copying information.
+
+
+
+
+
+
+
+
+
+
diff --git a/web/satellite/src/components/objects/UploadFile.vue b/web/satellite/src/components/objects/UploadFile.vue
index e970ebde0..5eca6ff9e 100644
--- a/web/satellite/src/components/objects/UploadFile.vue
+++ b/web/satellite/src/components/objects/UploadFile.vue
@@ -7,6 +7,7 @@
+
@@ -14,6 +15,8 @@
import { FileBrowser } from 'browser';
import { Component, Vue } from 'vue-property-decorator';
+import UploadCancelPopup from '@/components/objects/UploadCancelPopup.vue';
+
import { AnalyticsHttpApi } from '@/api/analytics';
import { RouteConfig } from '@/router';
import { ACCESS_GRANTS_ACTIONS } from '@/store/modules/accessGrants';
@@ -24,6 +27,7 @@ import { MetaUtils } from '@/utils/meta';
@Component({
components: {
FileBrowser,
+ UploadCancelPopup,
},
})
export default class UploadFile extends Vue {
@@ -124,6 +128,13 @@ export default class UploadFile extends Vue {
};
}
+ /**
+ * Indicates if upload cancel popup is visible.
+ */
+ public get isCancelUploadPopupVisible(): boolean {
+ return this.$store.state.appStateModule.appState.isUploadCancelPopupVisible;
+ }
+
/**
* Generates public access key.
*/
diff --git a/web/satellite/src/router/index.ts b/web/satellite/src/router/index.ts
index 0448034c9..7e83c32b7 100644
--- a/web/satellite/src/router/index.ts
+++ b/web/satellite/src/router/index.ts
@@ -36,6 +36,7 @@ import ProjectsList from '@/components/projectsList/ProjectsList.vue';
import ProjectMembersArea from '@/components/team/ProjectMembersArea.vue';
import store from '@/store';
+import { OBJECTS_ACTIONS } from '@/store/modules/objects';
import { NavigationLink } from '@/types/navigation';
const DashboardArea = () => import('@/views/DashboardArea.vue');
@@ -180,11 +181,6 @@ export const router = new Router({
name: RouteConfig.ProjectDashboard.name,
component: ProjectDashboard,
},
- {
- path: RouteConfig.Root.path,
- name: 'default',
- component: ProjectDashboard,
- },
{
path: RouteConfig.Users.path,
name: RouteConfig.Users.name,
@@ -347,6 +343,7 @@ export const router = new Router({
children: [
{
path: '*',
+ name: RouteConfig.UploadFile.name,
component: UploadFile,
},
],
@@ -363,7 +360,12 @@ export const router = new Router({
],
});
-router.beforeEach((to, from, next) => {
+router.beforeEach(async (to, from, next) => {
+ if (from.name === RouteConfig.UploadFile.name && !store.state.appStateModule.appState.isUploadCancelPopupVisible) {
+ const areUploadsInProgress: boolean = await store.dispatch(OBJECTS_ACTIONS.CHECK_ONGOING_UPLOADS, to.path);
+ if (areUploadsInProgress) return;
+ }
+
if (navigateToDefaultSubTab(to.matched, RouteConfig.Account)) {
next(RouteConfig.Account.with(RouteConfig.Billing).path);
@@ -394,12 +396,6 @@ router.beforeEach((to, from, next) => {
return;
}
- if (to.name === 'default') {
- next(RouteConfig.ProjectDashboard.path);
-
- return;
- }
-
next();
});
@@ -424,7 +420,6 @@ router.afterEach(({ name }, from) => {
* if our route is a tab and has no sub tab route - we will navigate to default subtab.
* F.E. /account/ -> /account/billing/;
* @param routes - array of RouteRecord from vue-router
- * @param next - callback to process next route
* @param tabRoute - tabNavigator route
*/
function navigateToDefaultSubTab(routes: RouteRecord[], tabRoute: NavigationLink): boolean {
diff --git a/web/satellite/src/store/modules/appState.ts b/web/satellite/src/store/modules/appState.ts
index 56daf4faa..49f936dad 100644
--- a/web/satellite/src/store/modules/appState.ts
+++ b/web/satellite/src/store/modules/appState.ts
@@ -23,11 +23,11 @@ export const appStateModule = {
isPeriodsDropdownShown: false,
isDeleteProjectPopupShown: false,
isDeleteAccountPopupShown: false,
- isSortProjectMembersByPopupShown: false,
isSuccessfulRegistrationShown: false,
isEditProfilePopupShown: false,
isChangePasswordPopupShown: false,
isPaymentSelectionShown: false,
+ isUploadCancelPopupVisible: false,
},
satelliteName: '',
partneredSatellites: new Array(),
@@ -79,10 +79,6 @@ export const appStateModule = {
[APP_STATE_MUTATIONS.TOGGLE_DELETE_ACCOUNT_DROPDOWN](state: any): void {
state.appState.isDeleteAccountPopupShown = !state.appState.isDeleteAccountPopupShown;
},
- // Mutation changing 'sort project members by' popup visibility.
- [APP_STATE_MUTATIONS.TOGGLE_SORT_PM_BY_DROPDOWN](state: any): void {
- state.appState.isSortProjectMembersByPopupShown = !state.appState.isSortProjectMembersByPopupShown;
- },
// Mutation changing 'successful registration' area visibility.
[APP_STATE_MUTATIONS.TOGGLE_SUCCESSFUL_REGISTRATION](state: any): void {
state.appState.isSuccessfulRegistrationShown = !state.appState.isSuccessfulRegistrationShown;
@@ -93,6 +89,9 @@ export const appStateModule = {
[APP_STATE_MUTATIONS.TOGGLE_EDIT_PROFILE_POPUP](state: any): void {
state.appState.isEditProfilePopupShown = !state.appState.isEditProfilePopupShown;
},
+ [APP_STATE_MUTATIONS.TOGGLE_UPLOAD_CANCEL_POPUP](state: any): void {
+ state.appState.isUploadCancelPopupVisible = !state.appState.isUploadCancelPopupVisible;
+ },
[APP_STATE_MUTATIONS.SHOW_SET_DEFAULT_PAYMENT_METHOD_POPUP](state: any, id: string): void {
state.appState.setDefaultPaymentMethodID = id;
},
@@ -110,7 +109,6 @@ export const appStateModule = {
state.appState.isAvailableBalanceDropdownShown = false;
state.appState.isPeriodsDropdownShown = false;
state.appState.isPaymentSelectionShown = false;
- state.appState.isSortProjectMembersByPopupShown = false;
},
[APP_STATE_MUTATIONS.CHANGE_STATE](state: any, newFetchState: AppState): void {
state.appState.fetchState = newFetchState;
@@ -218,13 +216,6 @@ export const appStateModule = {
commit(APP_STATE_MUTATIONS.TOGGLE_DELETE_ACCOUNT_DROPDOWN);
},
- [APP_STATE_ACTIONS.TOGGLE_SORT_PM_BY_DROPDOWN]: function ({commit, state}: any): void {
- if (!state.appState.isSortProjectMembersByPopupShown) {
- commit(APP_STATE_MUTATIONS.CLOSE_ALL);
- }
-
- commit(APP_STATE_MUTATIONS.TOGGLE_SORT_PM_BY_DROPDOWN);
- },
[APP_STATE_ACTIONS.TOGGLE_SUCCESSFUL_REGISTRATION]: function ({commit, state}: any): void {
if (!state.appState.isSuccessfulRegistrationShown) {
commit(APP_STATE_MUTATIONS.CLOSE_ALL);
@@ -235,6 +226,9 @@ export const appStateModule = {
[APP_STATE_ACTIONS.TOGGLE_CHANGE_PASSWORD_POPUP]: function ({commit}: any): void {
commit(APP_STATE_MUTATIONS.TOGGLE_CHANGE_PASSWORD_POPUP);
},
+ [APP_STATE_ACTIONS.TOGGLE_UPLOAD_CANCEL_POPUP]: function ({commit}: any): void {
+ commit(APP_STATE_MUTATIONS.TOGGLE_UPLOAD_CANCEL_POPUP);
+ },
[APP_STATE_ACTIONS.TOGGLE_EDIT_PROFILE_POPUP]: function ({commit}: any): void {
commit(APP_STATE_MUTATIONS.TOGGLE_EDIT_PROFILE_POPUP);
},
diff --git a/web/satellite/src/store/modules/objects.ts b/web/satellite/src/store/modules/objects.ts
index dd1919309..599800187 100644
--- a/web/satellite/src/store/modules/objects.ts
+++ b/web/satellite/src/store/modules/objects.ts
@@ -5,6 +5,7 @@ import S3, { Bucket } from 'aws-sdk/clients/s3';
import { StoreModule } from '@/store';
import { GatewayCredentials } from '@/types/accessGrants';
+import { APP_STATE_ACTIONS } from '@/utils/constants/actionNames';
export const OBJECTS_ACTIONS = {
CLEAR: 'clearObjects',
@@ -17,6 +18,7 @@ export const OBJECTS_ACTIONS = {
FETCH_BUCKETS: 'fetchBuckets',
CREATE_BUCKET: 'createBucket',
DELETE_BUCKET: 'deleteBucket',
+ CHECK_ONGOING_UPLOADS: 'checkOngoingUploads',
};
export const OBJECTS_MUTATIONS = {
@@ -28,6 +30,7 @@ export const OBJECTS_MUTATIONS = {
SET_BUCKETS: 'setBuckets',
SET_FILE_COMPONENT_BUCKET_NAME: 'setFileComponentBucketName',
SET_PASSPHRASE: 'setPassphrase',
+ SET_LEAVE_ROUTE: 'setLeaveRoute',
};
const {
@@ -39,6 +42,7 @@ const {
SET_BUCKETS,
SET_PASSPHRASE,
SET_FILE_COMPONENT_BUCKET_NAME,
+ SET_LEAVE_ROUTE,
} = OBJECTS_MUTATIONS;
export class ObjectsState {
@@ -49,6 +53,7 @@ export class ObjectsState {
public bucketsList: Bucket[] = [];
public passphrase: string = '';
public fileComponentBucketName: string = '';
+ public leaveRoute: string = '';
}
/**
@@ -85,6 +90,9 @@ export function makeObjectsModule(): StoreModule {
[SET_FILE_COMPONENT_BUCKET_NAME](state: ObjectsState, bucketName: string) {
state.fileComponentBucketName = bucketName;
},
+ [SET_LEAVE_ROUTE](state: ObjectsState, leaveRoute: string) {
+ state.leaveRoute = leaveRoute;
+ },
[CLEAR](state: ObjectsState) {
state.apiKey = '';
state.passphrase = '';
@@ -129,9 +137,19 @@ export function makeObjectsModule(): StoreModule {
Bucket: name,
}).promise();
},
- clearObjects: function ({commit}: any): void {
+ clearObjects: function({commit}: any): void {
commit(CLEAR);
},
+ checkOngoingUploads: function({commit, dispatch, rootState}: any, leaveRoute: string): boolean {
+ if (!rootState.files.uploading.length) {
+ return false;
+ }
+
+ commit(SET_LEAVE_ROUTE, leaveRoute);
+ dispatch(APP_STATE_ACTIONS.TOGGLE_UPLOAD_CANCEL_POPUP, null, {root: true});
+
+ return true;
+ },
},
};
}
diff --git a/web/satellite/src/store/mutationConstants.ts b/web/satellite/src/store/mutationConstants.ts
index 52a542e06..28fceda9e 100644
--- a/web/satellite/src/store/mutationConstants.ts
+++ b/web/satellite/src/store/mutationConstants.ts
@@ -21,11 +21,11 @@ export const APP_STATE_MUTATIONS = {
TOGGLE_FREE_CREDITS_DROPDOWN: 'TOGGLE_FREE_CREDITS_DROPDOWN',
TOGGLE_AVAILABLE_BALANCE_DROPDOWN: 'TOGGLE_AVAILABLE_BALANCE_DROPDOWN',
TOGGLE_PERIODS_DROPDOWN: 'TOGGLE_PERIODS_DROPDOWN',
- TOGGLE_SORT_PM_BY_DROPDOWN: 'TOGGLE_SORT_PM_BY_DROPDOWN',
TOGGLE_SUCCESSFUL_REGISTRATION: 'TOGGLE_SUCCESSFUL_REGISTRATION',
TOGGLE_SUCCESSFUL_PROJECT_CREATION_POPUP: 'TOGGLE_SUCCESSFUL_PROJECT_CREATION_POPUP',
TOGGLE_EDIT_PROFILE_POPUP: 'TOGGLE_EDIT_PROFILE_POPUP',
TOGGLE_CHANGE_PASSWORD_POPUP: 'TOGGLE_CHANGE_PASSWORD_POPUP',
+ TOGGLE_UPLOAD_CANCEL_POPUP: 'TOGGLE_UPLOAD_CANCEL_POPUP',
SHOW_DELETE_PAYMENT_METHOD_POPUP: 'SHOW_DELETE_PAYMENT_METHOD_POPUP',
SHOW_SET_DEFAULT_PAYMENT_METHOD_POPUP: 'SHOW_SET_DEFAULT_PAYMENT_METHOD_POPUP',
CLOSE_ALL: 'CLOSE_ALL',
diff --git a/web/satellite/src/utils/constants/actionNames.ts b/web/satellite/src/utils/constants/actionNames.ts
index f38837d35..55297a3f1 100644
--- a/web/satellite/src/utils/constants/actionNames.ts
+++ b/web/satellite/src/utils/constants/actionNames.ts
@@ -13,11 +13,11 @@ export const APP_STATE_ACTIONS = {
TOGGLE_PERIODS_DROPDOWN: 'togglePeriodsDropdown',
TOGGLE_DEL_PROJ: 'toggleDeleteProjectPopup',
TOGGLE_DEL_ACCOUNT: 'toggleDeleteAccountPopup',
- TOGGLE_SORT_PM_BY_DROPDOWN: 'toggleSortProjectMembersByPopup',
TOGGLE_SUCCESSFUL_REGISTRATION: 'TOGGLE_SUCCESSFUL_REGISTRATION',
TOGGLE_SUCCESSFUL_PROJECT_CREATION_POPUP: 'toggleSuccessfulProjectCreationPopup',
TOGGLE_EDIT_PROFILE_POPUP: 'toggleEditProfilePopup',
TOGGLE_CHANGE_PASSWORD_POPUP: 'toggleChangePasswordPopup',
+ TOGGLE_UPLOAD_CANCEL_POPUP: 'toggleUploadCancelPopup',
SHOW_SET_DEFAULT_PAYMENT_METHOD_POPUP: 'showSetDefaultPaymentMethodPopup',
CLOSE_SET_DEFAULT_PAYMENT_METHOD_POPUP: 'closeSetDefaultPaymentMethodPopup',
SHOW_DELETE_PAYMENT_METHOD_POPUP: 'showDeletePaymentMethodPopup',
diff --git a/web/satellite/static/images/objects/cancelWarning.svg b/web/satellite/static/images/objects/cancelWarning.svg
new file mode 100644
index 000000000..05d7114be
--- /dev/null
+++ b/web/satellite/static/images/objects/cancelWarning.svg
@@ -0,0 +1,4 @@
+