satellite/{analytics, web}: segment ui error tracking implemented
Implemented UI error tracking. We use satellite analytics service to track the fact that UI error occurred and send minimal info to Segment (not Hubspot). We send only the fact that UI error occurred and the place where this error occurred. Extended notificator plugin error function to include the place where error occurred. I made the place argument nullable to be always explicitly provided (build fails if place is not provided). If place is not null then error event is triggered in the background. Issue: https://github.com/storj/storj-private/issues/107 Change-Id: I7d129fb29629979f5be6ff5dea37ad19b1a2397e
This commit is contained in:
parent
7f2dfaa394
commit
5d727becb4
@ -74,6 +74,7 @@ const (
|
||||
eventProjectMembersInviteSent = "Project Members Invite Sent"
|
||||
eventProjectMemberAdded = "Project Member Added"
|
||||
eventProjectMemberDeleted = "Project Member Deleted"
|
||||
eventError = "UI error occurred"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -123,7 +124,7 @@ func NewService(log *zap.Logger, config Config, satelliteName string) *Service {
|
||||
eventCopyToClipboardClicked, eventCreateAccessGrantClicked, eventCreateS3CredentialsClicked, eventKeysForCLIClicked,
|
||||
eventSeePaymentsClicked, eventEditPaymentMethodClicked, eventUsageDetailedInfoClicked, eventAddNewPaymentMethodClicked,
|
||||
eventApplyNewCouponClicked, eventCreditCardRemoved, eventCouponCodeApplied, eventInvoiceDownloaded, eventCreditCardAddedFromBilling,
|
||||
eventStorjTokenAddedFromBilling, eventAddFundsClicked, eventProjectMembersInviteSent} {
|
||||
eventStorjTokenAddedFromBilling, eventAddFundsClicked, eventProjectMembersInviteSent, eventError} {
|
||||
service.clientEvents[name] = true
|
||||
}
|
||||
|
||||
@ -372,6 +373,24 @@ func (service *Service) TrackEvent(eventName string, userID uuid.UUID, email str
|
||||
})
|
||||
}
|
||||
|
||||
// TrackErrorEvent sends an arbitrary error event associated with user ID to Segment.
|
||||
// It is used for tracking occurrences of client-side errors.
|
||||
func (service *Service) TrackErrorEvent(userID uuid.UUID, email string, source string) {
|
||||
if !service.config.Enabled {
|
||||
return
|
||||
}
|
||||
|
||||
props := segment.NewProperties()
|
||||
props.Set("email", email)
|
||||
props.Set("source", source)
|
||||
|
||||
service.enqueueMessage(segment.Track{
|
||||
UserId: userID.String(),
|
||||
Event: service.satelliteName + " " + eventError,
|
||||
Properties: props,
|
||||
})
|
||||
}
|
||||
|
||||
// TrackLinkEvent sends an arbitrary event and link associated with user ID to Segment.
|
||||
// It is used for tracking occurrences of client-side events.
|
||||
func (service *Service) TrackLinkEvent(eventName string, userID uuid.UUID, email, link string) {
|
||||
|
@ -36,8 +36,9 @@ func NewAnalytics(log *zap.Logger, service *console.Service, a *analytics.Servic
|
||||
}
|
||||
|
||||
type eventTriggeredBody struct {
|
||||
EventName string `json:"eventName"`
|
||||
Link string `json:"link"`
|
||||
EventName string `json:"eventName"`
|
||||
Link string `json:"link"`
|
||||
ErrorEventSource string `json:"errorEventSource"`
|
||||
}
|
||||
|
||||
type pageVisitBody struct {
|
||||
@ -65,7 +66,10 @@ func (a *Analytics) EventTriggered(w http.ResponseWriter, r *http.Request) {
|
||||
a.serveJSONError(w, http.StatusUnauthorized, err)
|
||||
return
|
||||
}
|
||||
if et.Link != "" {
|
||||
|
||||
if et.ErrorEventSource != "" {
|
||||
a.analytics.TrackErrorEvent(user.ID, user.Email, et.ErrorEventSource)
|
||||
} else if et.Link != "" {
|
||||
a.analytics.TrackLinkEvent(et.EventName, user.ID, user.Email, et.Link)
|
||||
} else {
|
||||
a.analytics.TrackEvent(et.EventName, user.ID, user.Email)
|
||||
|
@ -2,6 +2,7 @@
|
||||
// See LICENSE for copying information.
|
||||
|
||||
import { HttpClient } from '@/utils/httpClient';
|
||||
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
/**
|
||||
* AnalyticsHttpApi is a console Analytics API.
|
||||
@ -78,4 +79,31 @@ export class AnalyticsHttpApi {
|
||||
console.error('Could not notify satellite about ' + pageName + ' event occurrence (most likely blocked by browser).');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to notify the satellite about error events that occur.
|
||||
* Does not throw any errors so that expected UI behavior is not interrupted if the API call fails.
|
||||
*
|
||||
* @param source - place where event happened
|
||||
*/
|
||||
public async errorEventTriggered(source: AnalyticsErrorEventSource): Promise<void> {
|
||||
try {
|
||||
const path = `${this.ROOT_PATH}/event`;
|
||||
const body = {
|
||||
eventName: AnalyticsEvent.UI_ERROR,
|
||||
};
|
||||
|
||||
if (source) {
|
||||
body['errorEventSource'] = source;
|
||||
}
|
||||
|
||||
const response = await this.http.post(path, JSON.stringify(body));
|
||||
if (response.ok) {
|
||||
return;
|
||||
}
|
||||
console.error(`Attempted to notify Satellite that UI error occurred here: ${source}. Got bad response status code: ${response.status}`);
|
||||
} catch (error) {
|
||||
console.error(`Could not notify satellite about UI error here: ${source} (most likely blocked by browser).`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -229,7 +229,7 @@ import { ACCESS_GRANTS_ACTIONS } from '@/store/modules/accessGrants';
|
||||
import { AccessGrant, AccessGrantsOrderBy } from '@/types/accessGrants';
|
||||
import { SortDirection } from '@/types/common';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
import AccessGrantsItem from '@/components/accessGrants/AccessGrantsItem.vue';
|
||||
import AccessGrantsItem2 from '@/components/accessGrants/AccessGrantsItem2.vue';
|
||||
@ -301,7 +301,7 @@ export default class AccessGrants extends Vue {
|
||||
await this.$store.dispatch(FETCH, this.FIRST_PAGE);
|
||||
this.areGrantsFetching = false;
|
||||
} catch (error) {
|
||||
await this.$notify.error(`Unable to fetch Access Grants. ${error.message}`);
|
||||
await this.$notify.error(`Unable to fetch Access Grants. ${error.message}`, AnalyticsErrorEventSource.ACCESS_GRANTS_PAGE);
|
||||
}
|
||||
}
|
||||
/**
|
||||
@ -326,7 +326,7 @@ export default class AccessGrants extends Vue {
|
||||
try {
|
||||
await this.$store.dispatch(FETCH, index);
|
||||
} catch (error) {
|
||||
await this.$notify.error(`Unable to fetch Access Grants. ${error.message}`);
|
||||
await this.$notify.error(`Unable to fetch Access Grants. ${error.message}`, AnalyticsErrorEventSource.ACCESS_GRANTS_PAGE);
|
||||
}
|
||||
}
|
||||
/**
|
||||
@ -340,7 +340,7 @@ export default class AccessGrants extends Vue {
|
||||
try {
|
||||
await this.$store.dispatch(FETCH, this.FIRST_PAGE);
|
||||
} catch (error) {
|
||||
await this.$notify.error(`Unable to fetch Access Grants. ${error.message}`);
|
||||
await this.$notify.error(`Unable to fetch Access Grants. ${error.message}`, AnalyticsErrorEventSource.ACCESS_GRANTS_PAGE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -388,7 +388,7 @@ export default class AccessGrants extends Vue {
|
||||
try {
|
||||
await this.$store.dispatch(FETCH, 1);
|
||||
} catch (error) {
|
||||
await this.$notify.error(`Unable to fetch accesses: ${error.message}`);
|
||||
await this.$notify.error(`Unable to fetch accesses: ${error.message}`, AnalyticsErrorEventSource.ACCESS_GRANTS_PAGE);
|
||||
}
|
||||
}
|
||||
public get deleteButtonLabel(): string {
|
||||
|
@ -99,6 +99,7 @@ import { Component, Vue } from 'vue-property-decorator';
|
||||
import { MetaUtils } from '@/utils/meta';
|
||||
import { ACCESS_GRANTS_ACTIONS } from '@/store/modules/accessGrants';
|
||||
import { AccessGrant } from '@/types/accessGrants';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
import VButton from '@/components/common/VButton.vue';
|
||||
|
||||
@ -129,14 +130,14 @@ export default class ConfirmDeletePopup extends Vue {
|
||||
await this.$store.dispatch(ACCESS_GRANTS_ACTIONS.DELETE);
|
||||
await this.$notify.success(`Access Grant deleted successfully`);
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.CONFIRM_DELETE_AG_MODAL);
|
||||
}
|
||||
|
||||
try {
|
||||
await this.$store.dispatch(ACCESS_GRANTS_ACTIONS.FETCH, this.FIRST_PAGE);
|
||||
await this.$store.dispatch(ACCESS_GRANTS_ACTIONS.CLEAR_SELECTION);
|
||||
} catch (error) {
|
||||
await this.$notify.error(`Unable to fetch Access Grants. ${error.message}`);
|
||||
await this.$notify.error(`Unable to fetch Access Grants. ${error.message}`, AnalyticsErrorEventSource.CONFIRM_DELETE_AG_MODAL);
|
||||
}
|
||||
|
||||
this.$emit('reset-pagination');
|
||||
|
@ -60,6 +60,7 @@ import { Component, Vue } from 'vue-property-decorator';
|
||||
|
||||
import { ACCESS_GRANTS_ACTIONS } from '@/store/modules/accessGrants';
|
||||
import { AccessGrant } from '@/types/accessGrants';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
import VButton from '@/components/common/VButton.vue';
|
||||
import VInput from '@/components/common/VInput.vue';
|
||||
@ -75,10 +76,11 @@ import CloseCrossIcon from '@/../static/images/common/closeCross.svg';
|
||||
},
|
||||
})
|
||||
export default class ConfirmDeletePopup extends Vue {
|
||||
private readonly FIRST_PAGE: number = 1;
|
||||
private isLoading = false;
|
||||
private confirmedInput = '';
|
||||
|
||||
private readonly FIRST_PAGE: number = 1;
|
||||
|
||||
/**
|
||||
* sets Comfirmed Input property to the given value.
|
||||
*/
|
||||
@ -98,14 +100,14 @@ export default class ConfirmDeletePopup extends Vue {
|
||||
await this.$store.dispatch(ACCESS_GRANTS_ACTIONS.DELETE);
|
||||
await this.$notify.success(`Access Grant deleted successfully`);
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.CONFIRM_DELETE_AG_MODAL);
|
||||
}
|
||||
|
||||
try {
|
||||
await this.$store.dispatch(ACCESS_GRANTS_ACTIONS.FETCH, this.FIRST_PAGE);
|
||||
await this.$store.dispatch(ACCESS_GRANTS_ACTIONS.CLEAR_SELECTION);
|
||||
} catch (error) {
|
||||
await this.$notify.error(`Unable to fetch Access Grants. ${error.message}`);
|
||||
await this.$notify.error(`Unable to fetch Access Grants. ${error.message}`, AnalyticsErrorEventSource.CONFIRM_DELETE_AG_MODAL);
|
||||
}
|
||||
|
||||
this.$emit('resetPagination');
|
||||
|
@ -32,8 +32,7 @@ import CloseCrossIcon from '@/../static/images/common/closeCross.svg';
|
||||
},
|
||||
})
|
||||
export default class CreateAccessGrant extends Vue {
|
||||
|
||||
public readonly analytics: AnalyticsHttpApi = new AnalyticsHttpApi();
|
||||
private readonly analytics: AnalyticsHttpApi = new AnalyticsHttpApi();
|
||||
|
||||
/**
|
||||
* Closes popup.
|
||||
|
@ -36,7 +36,7 @@
|
||||
import { Component, Vue, Prop } from 'vue-property-decorator';
|
||||
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { AccessGrant } from '@/types/accessGrants';
|
||||
import { ACCESS_GRANTS_ACTIONS } from '@/store/modules/accessGrants';
|
||||
import { BUCKET_ACTIONS } from '@/store/modules/buckets';
|
||||
@ -68,9 +68,10 @@ export default class CreateAccessModal extends Vue {
|
||||
@Prop({ default: 'Default' })
|
||||
private readonly defaultType: string;
|
||||
|
||||
private accessGrantStep = 'create';
|
||||
private readonly analytics: AnalyticsHttpApi = new AnalyticsHttpApi();
|
||||
public areBucketNamesFetching = true;
|
||||
public areKeysVisible = false;
|
||||
|
||||
private readonly analytics: AnalyticsHttpApi = new AnalyticsHttpApi();
|
||||
private readonly FIRST_PAGE = 1;
|
||||
|
||||
/**
|
||||
@ -93,7 +94,7 @@ export default class CreateAccessModal extends Vue {
|
||||
*/
|
||||
private passphrase = '';
|
||||
private accessName = '';
|
||||
public areBucketNamesFetching = true;
|
||||
private accessGrantStep = 'create';
|
||||
|
||||
/**
|
||||
* Created Access Grant
|
||||
@ -117,7 +118,7 @@ export default class CreateAccessModal extends Vue {
|
||||
await this.$store.dispatch(BUCKET_ACTIONS.FETCH_ALL_BUCKET_NAMES);
|
||||
this.areBucketNamesFetching = false;
|
||||
} catch (error) {
|
||||
await this.$notify.error(`Unable to fetch all bucket names. ${error.message}`);
|
||||
await this.$notify.error(`Unable to fetch all bucket names. ${error.message}`, AnalyticsErrorEventSource.CREATE_AG_MODAL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -149,7 +150,7 @@ export default class CreateAccessModal extends Vue {
|
||||
public setWorker(): void {
|
||||
this.worker = this.$store.state.accessGrantsModule.accessGrantsWebWorker;
|
||||
this.worker.onerror = (error: ErrorEvent) => {
|
||||
this.$notify.error(error.message);
|
||||
this.$notify.error(error.message, AnalyticsErrorEventSource.CREATE_AG_MODAL);
|
||||
};
|
||||
}
|
||||
|
||||
@ -174,6 +175,7 @@ export default class CreateAccessModal extends Vue {
|
||||
try {
|
||||
await this.$store.dispatch(PROJECTS_ACTIONS.CREATE_DEFAULT_PROJECT);
|
||||
} catch (error) {
|
||||
this.$notify.error(error.message, AnalyticsErrorEventSource.CREATE_AG_MODAL);
|
||||
this.isLoading = false;
|
||||
return;
|
||||
}
|
||||
@ -184,14 +186,14 @@ export default class CreateAccessModal extends Vue {
|
||||
try {
|
||||
cleanAPIKey = await this.$store.dispatch(ACCESS_GRANTS_ACTIONS.CREATE, this.accessName);
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.CREATE_AG_MODAL);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await this.$store.dispatch(ACCESS_GRANTS_ACTIONS.FETCH, this.FIRST_PAGE);
|
||||
} catch (error) {
|
||||
await this.$notify.error(`Unable to fetch Access Grants. ${error.message}`);
|
||||
await this.$notify.error(`Unable to fetch Access Grants. ${error.message}`, AnalyticsErrorEventSource.CREATE_AG_MODAL);
|
||||
|
||||
this.isLoading = false;
|
||||
}
|
||||
@ -213,7 +215,9 @@ export default class CreateAccessModal extends Vue {
|
||||
|
||||
const grantEvent: MessageEvent = await new Promise(resolve => this.worker.onmessage = resolve);
|
||||
if (grantEvent.data.error) {
|
||||
throw new Error(grantEvent.data.error);
|
||||
await this.$notify.error(grantEvent.data.error, AnalyticsErrorEventSource.CREATE_AG_MODAL);
|
||||
this.isLoading = false;
|
||||
return;
|
||||
}
|
||||
this.restrictedKey = grantEvent.data.value;
|
||||
|
||||
@ -232,7 +236,7 @@ export default class CreateAccessModal extends Vue {
|
||||
|
||||
const accessEvent: MessageEvent = await new Promise(resolve => this.worker.onmessage = resolve);
|
||||
if (accessEvent.data.error) {
|
||||
await this.$notify.error(accessEvent.data.error);
|
||||
await this.$notify.error(accessEvent.data.error, AnalyticsErrorEventSource.CREATE_AG_MODAL);
|
||||
this.isLoading = false;
|
||||
return;
|
||||
}
|
||||
@ -250,7 +254,7 @@ export default class CreateAccessModal extends Vue {
|
||||
|
||||
this.areKeysVisible = true;
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.CREATE_AG_MODAL);
|
||||
}
|
||||
} else {
|
||||
await this.analytics.eventTriggered(AnalyticsEvent.API_ACCESS_CREATED);
|
||||
|
@ -214,7 +214,7 @@ import { Component, Vue, Prop } from 'vue-property-decorator';
|
||||
import { ACCESS_GRANTS_ACTIONS } from '@/store/modules/accessGrants';
|
||||
import { AccessGrant } from '@/types/accessGrants';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
import VButton from '@/components/common/VButton.vue';
|
||||
import BucketsSelection from '@/components/accessGrants/permissions/BucketsSelection.vue';
|
||||
@ -353,7 +353,7 @@ export default class CreateForm extends Vue {
|
||||
public encryptClickAction(): void {
|
||||
let mappedList = this.accessGrantList.map((key) => (key.name));
|
||||
if (mappedList.includes(this.accessName)) {
|
||||
this.$notify.error(`validation: An API Key with this name already exists in this project, please use a different name`);
|
||||
this.$notify.error(`validation: An API Key with this name already exists in this project, please use a different name`, AnalyticsErrorEventSource.CREATE_AG_FORM);
|
||||
return;
|
||||
} else if (!this.checkedTypes.includes('api')) {
|
||||
// emit event here
|
||||
|
@ -152,7 +152,8 @@ export default class CreatePassphraseStep extends Vue {
|
||||
public setWorker(): void {
|
||||
this.worker = this.$store.state.accessGrantsModule.accessGrantsWebWorker;
|
||||
this.worker.onerror = (error: ErrorEvent) => {
|
||||
this.$notify.error(error.message);
|
||||
// we pass null because we don't use this flow anymore. It will be removed entirely soon.
|
||||
this.$notify.error(error.message, null);
|
||||
};
|
||||
}
|
||||
|
||||
@ -199,7 +200,8 @@ export default class CreatePassphraseStep extends Vue {
|
||||
|
||||
const accessEvent: MessageEvent = await new Promise(resolve => this.worker.onmessage = resolve);
|
||||
if (accessEvent.data.error) {
|
||||
await this.$notify.error(accessEvent.data.error);
|
||||
// we pass null because we don't use this flow anymore. It will be removed entirely soon.
|
||||
await this.$notify.error(accessEvent.data.error, null);
|
||||
this.isLoading = false;
|
||||
|
||||
return;
|
||||
|
@ -111,7 +111,8 @@ export default class EnterPassphraseStep extends Vue {
|
||||
|
||||
const accessEvent: MessageEvent = await new Promise(resolve => this.worker.onmessage = resolve);
|
||||
if (accessEvent.data.error) {
|
||||
await this.$notify.error(accessEvent.data.error);
|
||||
// we pass null because we don't use this flow anymore. It will be removed entirely soon.
|
||||
await this.$notify.error(accessEvent.data.error, null);
|
||||
this.isLoading = false;
|
||||
|
||||
return;
|
||||
@ -140,7 +141,8 @@ export default class EnterPassphraseStep extends Vue {
|
||||
public setWorker(): void {
|
||||
this.worker = this.$store.state.accessGrantsModule.accessGrantsWebWorker;
|
||||
this.worker.onerror = (error: ErrorEvent) => {
|
||||
this.$notify.error(error.message);
|
||||
// we pass null because we don't use this flow anymore. It will be removed entirely soon.
|
||||
this.$notify.error(error.message, null);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -224,7 +224,8 @@ export default class GatewayStep extends Vue {
|
||||
|
||||
this.areKeysVisible = true;
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
// we pass null because we don't use this flow anymore. It will be removed entirely soon.
|
||||
await this.$notify.error(error.message, null);
|
||||
}
|
||||
|
||||
this.isLoading = false;
|
||||
|
@ -113,7 +113,8 @@ export default class NameStep extends Vue {
|
||||
try {
|
||||
createdAccessGrant = await this.$store.dispatch(ACCESS_GRANTS_ACTIONS.CREATE, this.name);
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
// we pass null because we don't use this flow anymore. It will be removed entirely soon.
|
||||
await this.$notify.error(error.message, null);
|
||||
this.isLoading = false;
|
||||
|
||||
return;
|
||||
@ -125,7 +126,8 @@ export default class NameStep extends Vue {
|
||||
try {
|
||||
await this.$store.dispatch(ACCESS_GRANTS_ACTIONS.FETCH, this.FIRST_PAGE);
|
||||
} catch (error) {
|
||||
await this.$notify.error(`Unable to fetch Access Grants. ${error.message}`);
|
||||
// we pass null because we don't use this flow anymore. It will be removed entirely soon.
|
||||
await this.$notify.error(`Unable to fetch Access Grants. ${error.message}`, null);
|
||||
|
||||
this.isLoading = false;
|
||||
}
|
||||
|
@ -129,7 +129,8 @@ export default class PermissionsStep extends Vue {
|
||||
|
||||
this.areBucketNamesFetching = false;
|
||||
} catch (error) {
|
||||
await this.$notify.error(`Unable to fetch all bucket names. ${error.message}`);
|
||||
// we pass null because we don't use this flow anymore. It will be removed entirely soon.
|
||||
await this.$notify.error(`Unable to fetch all bucket names. ${error.message}`, null);
|
||||
}
|
||||
|
||||
this.isLoading = false;
|
||||
@ -151,7 +152,8 @@ export default class PermissionsStep extends Vue {
|
||||
public setWorker(): void {
|
||||
this.worker = this.$store.state.accessGrantsModule.accessGrantsWebWorker;
|
||||
this.worker.onerror = (error: ErrorEvent) => {
|
||||
this.$notify.error(error.message);
|
||||
// we pass null because we don't use this flow anymore. It will be removed entirely soon.
|
||||
this.$notify.error(error.message, null);
|
||||
};
|
||||
}
|
||||
|
||||
@ -166,7 +168,8 @@ export default class PermissionsStep extends Vue {
|
||||
try {
|
||||
await this.setPermissions();
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
// we pass null because we don't use this flow anymore. It will be removed entirely soon.
|
||||
await this.$notify.error(error.message, null);
|
||||
this.isLoading = false;
|
||||
|
||||
return;
|
||||
@ -195,7 +198,8 @@ export default class PermissionsStep extends Vue {
|
||||
try {
|
||||
await this.setPermissions();
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
// we pass null because we don't use this flow anymore. It will be removed entirely soon.
|
||||
await this.$notify.error(error.message, null);
|
||||
this.isLoading = false;
|
||||
|
||||
return;
|
||||
|
@ -88,6 +88,7 @@ import { Component, Vue } from 'vue-property-decorator';
|
||||
import { USER_ACTIONS } from '@/store/modules/users';
|
||||
import { User } from '@/types/users';
|
||||
import { APP_STATE_MUTATIONS } from '@/store/mutationConstants';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
import VButton from '@/components/common/VButton.vue';
|
||||
|
||||
@ -126,7 +127,7 @@ export default class SettingsArea extends Vue {
|
||||
await this.$store.dispatch(USER_ACTIONS.GENERATE_USER_MFA_SECRET);
|
||||
this.toggleEnableMFAModal();
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.ACCOUNT_SETTINGS_AREA);
|
||||
}
|
||||
|
||||
this.isLoading = false;
|
||||
@ -144,7 +145,7 @@ export default class SettingsArea extends Vue {
|
||||
await this.$store.dispatch(USER_ACTIONS.GENERATE_USER_MFA_RECOVERY_CODES);
|
||||
this.toggleMFACodesModal();
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.ACCOUNT_SETTINGS_AREA);
|
||||
}
|
||||
|
||||
this.isLoading = false;
|
||||
|
@ -96,6 +96,7 @@ import { PAYMENTS_ACTIONS } from '@/store/modules/payments';
|
||||
import { AccountBalance } from '@/types/payments';
|
||||
import { APP_STATE_ACTIONS } from '@/utils/constants/actionNames';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
import PeriodSelection from '@/components/account/billing/depositAndBillingHistory/PeriodSelection.vue';
|
||||
import SmallDepositHistory from '@/components/account/billing/depositAndBillingHistory/SmallDepositHistory.vue';
|
||||
@ -142,7 +143,7 @@ export default class BillingArea extends Vue {
|
||||
|
||||
this.isBalanceFetching = false;
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.BILLING_AREA);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,7 @@ import { Component, Vue } from 'vue-property-decorator';
|
||||
|
||||
import { PaymentsHistoryItem, PaymentsHistoryItemType } from '@/types/payments';
|
||||
import { PAYMENTS_ACTIONS } from '@/store/modules/payments';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
import BillingHistoryHeader from '@/components/account/billing/billingTabs/BillingHistoryHeader.vue';
|
||||
import BillingHistoryItem from '@/components/account/billing/billingTabs/BillingHistoryItem.vue';
|
||||
@ -45,8 +46,7 @@ const {
|
||||
},
|
||||
})
|
||||
|
||||
export default class BillingArea extends Vue {
|
||||
|
||||
export default class BillingHistory extends Vue {
|
||||
mounted(): void {
|
||||
this.fetchHistory();
|
||||
}
|
||||
@ -55,7 +55,7 @@ export default class BillingArea extends Vue {
|
||||
try {
|
||||
await this.$store.dispatch(GET_PAYMENTS_HISTORY);
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.BILLING_HISTORY_TAB);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,5 @@ import { Fragment } from 'vue-fragment';
|
||||
Fragment,
|
||||
},
|
||||
})
|
||||
export default class BillingHistoryHeader extends Vue {
|
||||
}
|
||||
export default class BillingHistoryHeader extends Vue {}
|
||||
</script>
|
||||
|
@ -52,7 +52,7 @@ import { Component, Vue } from 'vue-property-decorator';
|
||||
import { PAYMENTS_ACTIONS } from '@/store/modules/payments';
|
||||
import { Coupon } from '@/types/payments';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { APP_STATE_MUTATIONS } from '@/store/mutationConstants';
|
||||
|
||||
import VLoader from '@/components/common/VLoader.vue';
|
||||
@ -77,7 +77,7 @@ export default class Coupons extends Vue {
|
||||
await this.$store.dispatch(PAYMENTS_ACTIONS.GET_COUPON);
|
||||
this.isCouponFetching = false;
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.BILLING_COUPONS_TAB);
|
||||
this.isCouponFetching = false;
|
||||
}
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ import { AccountBalance , ProjectUsageAndCharges } from '@/types/payments';
|
||||
import { PAYMENTS_ACTIONS } from '@/store/modules/payments';
|
||||
import { PROJECTS_ACTIONS } from '@/store/modules/projects';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
import UsageAndChargesItem2 from '@/components/account/billing/estimatedCostsAndCredits/UsageAndChargesItem2.vue';
|
||||
import VButton from '@/components/common/VButton.vue';
|
||||
@ -126,6 +126,7 @@ export default class BillingArea extends Vue {
|
||||
try {
|
||||
await this.$store.dispatch(PROJECTS_ACTIONS.FETCH);
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.BILLING_OVERVIEW_TAB);
|
||||
this.isDataFetching = false;
|
||||
return;
|
||||
}
|
||||
@ -135,7 +136,7 @@ export default class BillingArea extends Vue {
|
||||
|
||||
this.isDataFetching = false;
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.BILLING_OVERVIEW_TAB);
|
||||
this.isDataFetching = false;
|
||||
}
|
||||
|
||||
|
@ -192,7 +192,7 @@ import { PAYMENTS_ACTIONS } from '@/store/modules/payments';
|
||||
import { RouteConfig } from '@/router';
|
||||
import { MetaUtils } from '@/utils/meta';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
import VButton from '@/components/common/VButton.vue';
|
||||
import VLoader from '@/components/common/VLoader.vue';
|
||||
@ -305,7 +305,7 @@ export default class PaymentMethods extends Vue {
|
||||
this.transactionCount = this.nativePaymentHistoryItems.length;
|
||||
this.displayedHistory = this.nativePaymentHistoryItems.slice(0,this.pageSize);
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.BILLING_PAYMENT_METHODS_TAB);
|
||||
} finally {
|
||||
this.nativePayIsLoading = false;
|
||||
}
|
||||
@ -326,7 +326,7 @@ export default class PaymentMethods extends Vue {
|
||||
try {
|
||||
await QRCode.toCanvas(this.$refs.canvas, this.wallet.address);
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.BILLING_PAYMENT_METHODS_TAB);
|
||||
}
|
||||
}
|
||||
|
||||
@ -336,7 +336,7 @@ export default class PaymentMethods extends Vue {
|
||||
await this.$notify.success('Default payment card updated');
|
||||
this.isChangeDefaultPaymentModalOpen = false;
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.BILLING_PAYMENT_METHODS_TAB);
|
||||
}
|
||||
}
|
||||
|
||||
@ -347,12 +347,12 @@ export default class PaymentMethods extends Vue {
|
||||
this.analytics.eventTriggered(AnalyticsEvent.CREDIT_CARD_REMOVED);
|
||||
await this.$notify.success('Credit card removed');
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.BILLING_PAYMENT_METHODS_TAB);
|
||||
}
|
||||
this.isRemovePaymentMethodsModalOpen = false;
|
||||
|
||||
} else {
|
||||
this.$notify.error('You cannot delete the default payment method.');
|
||||
this.$notify.error('You cannot delete the default payment method.', AnalyticsErrorEventSource.BILLING_PAYMENT_METHODS_TAB);
|
||||
}
|
||||
}
|
||||
|
||||
@ -377,7 +377,7 @@ export default class PaymentMethods extends Vue {
|
||||
// We fetch User one more time to update their Paid Tier status.
|
||||
await this.$store.dispatch(USER_ACTIONS.GET);
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.BILLING_PAYMENT_METHODS_TAB);
|
||||
|
||||
this.$emit('toggleIsLoading');
|
||||
|
||||
@ -388,7 +388,7 @@ export default class PaymentMethods extends Vue {
|
||||
try {
|
||||
await this.$store.dispatch(GET_CREDIT_CARDS);
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.BILLING_PAYMENT_METHODS_TAB);
|
||||
this.$emit('toggleIsLoading');
|
||||
}
|
||||
|
||||
|
@ -56,7 +56,7 @@ import { Component, Vue } from 'vue-property-decorator';
|
||||
import { PAYMENTS_ACTIONS } from '@/store/modules/payments';
|
||||
import { Coupon, CouponDuration } from '@/types/payments';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { APP_STATE_MUTATIONS } from '@/store/mutationConstants';
|
||||
|
||||
import VButton from '@/components/common/VButton.vue';
|
||||
@ -87,7 +87,7 @@ export default class CouponArea extends Vue {
|
||||
await this.$store.dispatch(PAYMENTS_ACTIONS.GET_COUPON);
|
||||
this.isCouponFetching = false;
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.BILLING_COUPON_AREA);
|
||||
}
|
||||
}
|
||||
|
||||
@ -138,7 +138,7 @@ export default class CouponArea extends Vue {
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
return date.toLocaleDateString('en-US', { month: 'long', day: 'numeric', year: 'numeric' });
|
||||
}
|
||||
|
||||
|
@ -31,6 +31,7 @@ import { RouteConfig } from '@/router';
|
||||
import { PAYMENTS_ACTIONS } from '@/store/modules/payments';
|
||||
import { PaymentsHistoryItem, PaymentsHistoryItemType } from '@/types/payments';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
import PaymentsItem from '@/components/account/billing/depositAndBillingHistory/PaymentsItem.vue';
|
||||
import SortingHeader from '@/components/account/billing/depositAndBillingHistory/SortingHeader.vue';
|
||||
@ -61,7 +62,7 @@ export default class DetailedHistory extends Vue {
|
||||
|
||||
this.isDataFetching = false;
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.BILLING_PAYMENTS_HISTORY);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,6 +35,7 @@ import { RouteConfig } from '@/router';
|
||||
import { PAYMENTS_ACTIONS } from '@/store/modules/payments';
|
||||
import { APP_STATE_ACTIONS } from '@/utils/constants/actionNames';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
import DatePickerIcon from '@/../static/images/account/billing/datePicker.svg';
|
||||
import SelectedIcon from '@/../static/images/account/billing/selected.svg';
|
||||
@ -137,7 +138,7 @@ export default class PeriodSelection extends Vue {
|
||||
try {
|
||||
await this.$store.dispatch(PAYMENTS_ACTIONS.GET_PROJECT_USAGE_AND_CHARGES_PREVIOUS_ROLLUP);
|
||||
} catch (error) {
|
||||
await this.$notify.error(`Unable to fetch project charges. ${error.message}`);
|
||||
await this.$notify.error(`Unable to fetch project charges. ${error.message}`, AnalyticsErrorEventSource.BILLING_PERIODS_SELECTION);
|
||||
}
|
||||
}
|
||||
|
||||
@ -148,7 +149,7 @@ export default class PeriodSelection extends Vue {
|
||||
try {
|
||||
await this.$store.dispatch(PAYMENTS_ACTIONS.GET_PROJECT_USAGE_AND_CHARGES_CURRENT_ROLLUP);
|
||||
} catch (error) {
|
||||
await this.$notify.error(`Unable to fetch project charges. ${error.message}`);
|
||||
await this.$notify.error(`Unable to fetch project charges. ${error.message}`, AnalyticsErrorEventSource.BILLING_PERIODS_SELECTION);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -34,8 +34,8 @@ import PaymentsItem from '@/components/account/billing/depositAndBillingHistory/
|
||||
},
|
||||
})
|
||||
export default class SmallDepositHistory extends Vue {
|
||||
|
||||
private readonly analytics: AnalyticsHttpApi = new AnalyticsHttpApi();
|
||||
|
||||
/**
|
||||
* Changes location to deposit history route.
|
||||
*/
|
||||
|
@ -31,6 +31,7 @@ import { PAYMENTS_ACTIONS } from '@/store/modules/payments';
|
||||
import { PROJECTS_ACTIONS } from '@/store/modules/projects';
|
||||
import { ProjectUsageAndCharges } from '@/types/payments';
|
||||
import { MONTHS_NAMES } from '@/utils/constants/date';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
import VLoader from '@/components/common/VLoader.vue';
|
||||
import UsageAndChargesItem from '@/components/account/billing/estimatedCostsAndCredits/UsageAndChargesItem.vue';
|
||||
@ -54,6 +55,7 @@ export default class EstimatedCostsAndCredits extends Vue {
|
||||
await this.$store.dispatch(PROJECTS_ACTIONS.FETCH);
|
||||
} catch (error) {
|
||||
this.isDataFetching = false;
|
||||
this.$notify.error(error.message, AnalyticsErrorEventSource.BILLING_ESTIMATED_COSTS_AND_CREDITS);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -62,7 +64,7 @@ export default class EstimatedCostsAndCredits extends Vue {
|
||||
|
||||
this.isDataFetching = false;
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.BILLING_ESTIMATED_COSTS_AND_CREDITS);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,7 @@ import { RouteConfig } from '@/router';
|
||||
import { PAYMENTS_ACTIONS } from '@/store/modules/payments';
|
||||
import { USER_ACTIONS } from '@/store/modules/users';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
import StripeCardInput from '@/components/account/billing/paymentMethods/StripeCardInput.vue';
|
||||
|
||||
@ -59,7 +60,7 @@ export default class AddCardForm extends Vue {
|
||||
// We fetch User one more time to update their Paid Tier status.
|
||||
await this.$store.dispatch(USER_ACTIONS.GET);
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.BILLING_ADD_STRIPE_CC_FORM);
|
||||
|
||||
this.$emit('toggleIsLoading');
|
||||
|
||||
@ -70,7 +71,7 @@ export default class AddCardForm extends Vue {
|
||||
try {
|
||||
await this.$store.dispatch(GET_CREDIT_CARDS);
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.BILLING_ADD_STRIPE_CC_FORM);
|
||||
this.$emit('toggleIsLoading');
|
||||
}
|
||||
|
||||
|
@ -12,8 +12,7 @@ import { Component, Vue } from 'vue-property-decorator';
|
||||
|
||||
// @vue/component
|
||||
@Component
|
||||
export default class AddStorjForm extends Vue {
|
||||
}
|
||||
export default class AddStorjForm extends Vue {}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
@ -28,8 +28,7 @@ import StorjLarge from '@/../static/images/billing/storj-icon-large.svg';
|
||||
StorjLarge,
|
||||
},
|
||||
})
|
||||
export default class AddTokenCard extends Vue {
|
||||
}
|
||||
export default class AddTokenCard extends Vue {}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
@ -96,7 +96,7 @@ import { Component, Vue } from 'vue-property-decorator';
|
||||
import { APP_STATE_MUTATIONS } from '@/store/mutationConstants';
|
||||
import { Wallet } from '@/types/payments';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { PAYMENTS_ACTIONS } from '@/store/modules/payments';
|
||||
|
||||
import VButton from '@/components/common/VButton.vue';
|
||||
@ -168,7 +168,7 @@ export default class AddTokenCardNative extends Vue {
|
||||
// wallet claimed; open token modal
|
||||
this.onAddTokensClick();
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.BILLING_STORJ_TOKEN_CONTAINER);
|
||||
}
|
||||
this.isLoading = false;
|
||||
}
|
||||
|
@ -12,6 +12,7 @@
|
||||
import { Component, Prop, Vue } from 'vue-property-decorator';
|
||||
|
||||
import { PAYMENTS_ACTIONS } from '@/store/modules/payments';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
const {
|
||||
CLEAR_CARDS_SELECTION,
|
||||
@ -39,7 +40,7 @@ export default class CardDialog extends Vue {
|
||||
try {
|
||||
await this.$store.dispatch(MAKE_CARD_DEFAULT, this.cardId);
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.BILLING_CC_DIALOG);
|
||||
}
|
||||
}
|
||||
|
||||
@ -51,7 +52,7 @@ export default class CardDialog extends Vue {
|
||||
await this.$store.dispatch(REMOVE_CARD, this.cardId);
|
||||
await this.$notify.success('Credit card removed');
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.BILLING_CC_DIALOG);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -88,6 +88,7 @@ import { Component, Vue } from 'vue-property-decorator';
|
||||
import { PAYMENTS_ACTIONS } from '@/store/modules/payments';
|
||||
import { CreditCard } from '@/types/payments';
|
||||
import { PaymentMethodsBlockState } from '@/utils/constants/billingEnums';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
import AddCardForm from '@/components/account/billing/paymentMethods/AddCardForm.vue';
|
||||
import AddStorjForm from '@/components/account/billing/paymentMethods/AddStorjForm.vue';
|
||||
@ -134,7 +135,7 @@ export default class PaymentMethods extends Vue {
|
||||
|
||||
this.areCardsFetching = false;
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.BILLING_PAYMENT_METHODS);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,7 @@ import { Component, Prop, Vue } from 'vue-property-decorator';
|
||||
|
||||
import { MetaUtils } from '@/utils/meta';
|
||||
import { LoadScript } from '@/utils/loadScript';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
interface StripeResponse {
|
||||
error: string
|
||||
@ -47,7 +48,7 @@ export default class StripeCardInput extends Vue {
|
||||
*/
|
||||
private stripe: any; // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
|
||||
/**
|
||||
/**
|
||||
* Stripe initialization.
|
||||
*/
|
||||
private async initStripe() {
|
||||
@ -56,7 +57,7 @@ export default class StripeCardInput extends Vue {
|
||||
this.stripe = window['Stripe'](stripePublicKey);
|
||||
|
||||
if (!this.stripe) {
|
||||
await this.$notify.error('Unable to initialize stripe');
|
||||
await this.$notify.error('Unable to initialize stripe', AnalyticsErrorEventSource.BILLING_STRIPE_CARD_INPUT);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -64,7 +65,7 @@ export default class StripeCardInput extends Vue {
|
||||
const elements = this.stripe.elements();
|
||||
|
||||
if (!elements) {
|
||||
await this.$notify.error('Unable to instantiate elements');
|
||||
await this.$notify.error('Unable to instantiate elements', AnalyticsErrorEventSource.BILLING_STRIPE_CARD_INPUT);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -72,7 +73,7 @@ export default class StripeCardInput extends Vue {
|
||||
this.cardElement = elements.create('card');
|
||||
|
||||
if (!this.cardElement) {
|
||||
await this.$notify.error('Unable to create card');
|
||||
await this.$notify.error('Unable to create card', AnalyticsErrorEventSource.BILLING_STRIPE_CARD_INPUT);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -92,11 +93,12 @@ export default class StripeCardInput extends Vue {
|
||||
* Stripe library loading and initialization.
|
||||
*/
|
||||
public async mounted(): Promise<void> {
|
||||
if (!window['Stripe']){
|
||||
if (!window['Stripe']) {
|
||||
const script = new LoadScript('https://js.stripe.com/v3/',
|
||||
() => { this.initStripe(); },
|
||||
() => { this.$notify.error('Stripe library not loaded');
|
||||
script.remove(); },
|
||||
() => { this.$notify.error('Stripe library not loaded', AnalyticsErrorEventSource.BILLING_STRIPE_CARD_INPUT);
|
||||
script.remove();
|
||||
},
|
||||
);
|
||||
|
||||
return;
|
||||
@ -117,7 +119,7 @@ export default class StripeCardInput extends Vue {
|
||||
}
|
||||
|
||||
if (result.token.card.funding === 'prepaid') {
|
||||
await this.$notify.error('Prepaid cards are not supported');
|
||||
await this.$notify.error('Prepaid cards are not supported', AnalyticsErrorEventSource.BILLING_STRIPE_CARD_INPUT);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -144,7 +146,7 @@ export default class StripeCardInput extends Vue {
|
||||
try {
|
||||
await this.stripe.createToken(this.cardElement).then(this.onStripeResponse);
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.BILLING_STRIPE_CARD_INPUT);
|
||||
}
|
||||
|
||||
this.isLoading = false;
|
||||
|
@ -1,13 +0,0 @@
|
||||
// Copyright (C) 2022 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
<template>
|
||||
<div class="form-container" />
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Vue } from 'vue-property-decorator';
|
||||
|
||||
export default class TokenDepositSelection2 extends Vue {
|
||||
}
|
||||
</script>
|
@ -206,10 +206,10 @@ import BreadCrumbs from './BreadCrumbs.vue';
|
||||
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { BrowserFile } from '@/types/browser';
|
||||
import { AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { RouteConfig } from '@/router';
|
||||
import { APP_STATE_MUTATIONS } from '@/store/mutationConstants';
|
||||
import { useRouter, useStore } from '@/utils/hooks';
|
||||
import { useNotify, useRouter, useStore } from '@/utils/hooks';
|
||||
import eventBus from '@/utils/eventBus';
|
||||
|
||||
import VButton from '@/components/common/VButton.vue';
|
||||
@ -223,6 +223,7 @@ import BlackArrowHide from '@/../static/images/common/BlackArrowHide.svg';
|
||||
|
||||
const store = useStore();
|
||||
const router = useRouter();
|
||||
const notify = useNotify();
|
||||
|
||||
const folderInput = ref<HTMLInputElement>(null);
|
||||
const fileInput = ref<HTMLInputElement>(null);
|
||||
@ -337,7 +338,7 @@ onBeforeMount(async () => {
|
||||
if (!bucket.value) {
|
||||
const path = RouteConfig.Buckets.with(RouteConfig.BucketsManagement).path;
|
||||
|
||||
await analytics.pageVisit(path);
|
||||
analytics.pageVisit(path);
|
||||
await router.push(path);
|
||||
|
||||
return;
|
||||
@ -348,12 +349,13 @@ onBeforeMount(async () => {
|
||||
|
||||
if (!routePath.value) {
|
||||
try {
|
||||
await analytics.pageVisit(`${store.state.files.browserRoot}${path.value}`);
|
||||
await router.push({
|
||||
path: `${store.state.files.browserRoot}${path.value}`,
|
||||
});
|
||||
analytics.pageVisit(`${store.state.files.browserRoot}${path.value}`);
|
||||
} catch (err) {
|
||||
await list('');
|
||||
analytics.errorEventTriggered(AnalyticsErrorEventSource.FILE_BROWSER);
|
||||
}
|
||||
}
|
||||
|
||||
@ -414,18 +416,23 @@ function cancelUpload(fileName: string): void {
|
||||
* Call the list method from the store, which will trigger a re-render and fetch all files under the current path passed in as an argument.
|
||||
*/
|
||||
async function list(path: string): Promise<void> {
|
||||
await store.dispatch('files/list', path, {
|
||||
root: true,
|
||||
});
|
||||
try {
|
||||
await store.dispatch('files/list', path, {
|
||||
root: true,
|
||||
});
|
||||
} catch (error) {
|
||||
notify.error(error.message, AnalyticsErrorEventSource.FILE_BROWSER);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the operating system's file system for file upload.
|
||||
*/
|
||||
async function buttonFileUpload(): Promise<void> {
|
||||
await analytics.eventTriggered(AnalyticsEvent.UPLOAD_FILE_CLICKED);
|
||||
const fileInputElement = fileInput.value as HTMLInputElement;
|
||||
fileInputElement.showPicker();
|
||||
analytics.eventTriggered(AnalyticsEvent.UPLOAD_FILE_CLICKED);
|
||||
closeUploadDropdown();
|
||||
}
|
||||
|
||||
@ -433,9 +440,9 @@ async function buttonFileUpload(): Promise<void> {
|
||||
* Open the operating system's file system for folder upload.
|
||||
*/
|
||||
async function buttonFolderUpload(): Promise<void> {
|
||||
await analytics.eventTriggered(AnalyticsEvent.UPLOAD_FOLDER_CLICKED);
|
||||
const folderInputElement = folderInput.value as HTMLInputElement;
|
||||
folderInputElement.showPicker();
|
||||
analytics.eventTriggered(AnalyticsEvent.UPLOAD_FOLDER_CLICKED);
|
||||
closeUploadDropdown();
|
||||
}
|
||||
|
||||
@ -457,8 +464,8 @@ function closeUploadDropdown(): void {
|
||||
* Redirects to buckets list view.
|
||||
*/
|
||||
async function goToBuckets(): Promise<void> {
|
||||
await analytics.pageVisit(RouteConfig.Buckets.with(RouteConfig.BucketsManagement).path);
|
||||
await router.push(RouteConfig.Buckets.with(RouteConfig.BucketsManagement).path).catch(err => {});
|
||||
analytics.pageVisit(RouteConfig.Buckets.with(RouteConfig.BucketsManagement).path);
|
||||
await onRouteChange();
|
||||
}
|
||||
</script>
|
||||
|
@ -111,6 +111,7 @@ import prettyBytes from 'pretty-bytes';
|
||||
import type { BrowserFile } from '@/types/browser';
|
||||
import { APP_STATE_MUTATIONS } from '@/store/mutationConstants';
|
||||
import { useNotify, useRouter, useStore } from '@/utils/hooks';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
import TableItem from '@/components/common/TableItem.vue';
|
||||
|
||||
@ -401,7 +402,7 @@ function download(): void {
|
||||
store.dispatch('files/download', props.file);
|
||||
notify.warning('Do not share download link with other people. If you want to share this data better use "Share" option.');
|
||||
} catch (error) {
|
||||
notify.error('Can not download your file');
|
||||
notify.error('Can not download your file', AnalyticsErrorEventSource.FILE_BROWSER_ENTRY);
|
||||
}
|
||||
|
||||
store.dispatch('files/closeDropdown');
|
||||
@ -427,7 +428,12 @@ async function finalDelete(): Promise<void> {
|
||||
(props.file.type === 'file') ? await store.dispatch('files/delete', params) : store.dispatch('files/deleteFolder', params);
|
||||
|
||||
// refresh the files displayed
|
||||
await store.dispatch('files/list');
|
||||
try {
|
||||
await store.dispatch('files/list');
|
||||
} catch (error) {
|
||||
notify.error(error.message, AnalyticsErrorEventSource.FILE_BROWSER_ENTRY);
|
||||
}
|
||||
|
||||
store.dispatch('files/removeFileFromToBeDeleted', props.file);
|
||||
deleteConfirmation.value = false;
|
||||
}
|
||||
|
@ -68,6 +68,8 @@ import { Component, Vue } from 'vue-property-decorator';
|
||||
|
||||
import { RouteConfig } from '@/router';
|
||||
import { PAYMENTS_ACTIONS } from '@/store/modules/payments';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
import VInput from '@/components/common/VInput.vue';
|
||||
import ValidationMessage from '@/components/common/ValidationMessage.vue';
|
||||
@ -88,11 +90,11 @@ export default class AddCouponCodeInput extends Vue {
|
||||
private showValidationMessage = false;
|
||||
private errorMessage = '';
|
||||
private isCodeValid = false;
|
||||
|
||||
private couponCode = '';
|
||||
|
||||
private showConfirmMessage = false;
|
||||
|
||||
private readonly analytics = new AnalyticsHttpApi();
|
||||
|
||||
/**
|
||||
* Signup view requires some unque styling and element text.
|
||||
*/
|
||||
@ -129,6 +131,7 @@ export default class AddCouponCodeInput extends Vue {
|
||||
this.errorMessage = error.message;
|
||||
this.isCodeValid = false;
|
||||
this.showValidationMessage = true;
|
||||
this.analytics.errorEventTriggered(AnalyticsErrorEventSource.BILLING_APPLY_COUPON_CODE_INPUT);
|
||||
|
||||
return;
|
||||
} finally {
|
||||
|
@ -32,6 +32,8 @@
|
||||
import { Component, Vue } from 'vue-property-decorator';
|
||||
|
||||
import { PAYMENTS_ACTIONS } from '@/store/modules/payments';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
import VInput from '@/components/common/VInput.vue';
|
||||
import ValidationMessage from '@/components/common/ValidationMessage.vue';
|
||||
@ -52,6 +54,8 @@ export default class NewBillingAddCouponCodeInput extends Vue {
|
||||
private couponCode = '';
|
||||
private isLoading = false;
|
||||
|
||||
private readonly analytics = new AnalyticsHttpApi();
|
||||
|
||||
public setCouponCode(value: string): void {
|
||||
this.couponCode = value;
|
||||
}
|
||||
@ -72,6 +76,7 @@ export default class NewBillingAddCouponCodeInput extends Vue {
|
||||
this.errorMessage = error.message;
|
||||
this.isCodeValid = false;
|
||||
this.showValidationMessage = true;
|
||||
this.analytics.errorEventTriggered(AnalyticsErrorEventSource.BILLING_APPLY_COUPON_CODE_INPUT);
|
||||
} finally {
|
||||
this.isLoading = false;
|
||||
}
|
||||
|
@ -140,7 +140,7 @@ export default class RegistrationSuccess extends Vue {
|
||||
try {
|
||||
await this.auth.resendEmail(email);
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, null);
|
||||
}
|
||||
|
||||
this.startResendEmailCountdown();
|
||||
|
@ -30,6 +30,7 @@ import { Component, Vue } from 'vue-property-decorator';
|
||||
|
||||
import { PROJECTS_ACTIONS } from '@/store/modules/projects';
|
||||
import { MetaUtils } from '@/utils/meta';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
import VLoader from '@/components/common/VLoader.vue';
|
||||
|
||||
@ -55,6 +56,7 @@ export default class ProjectInfoBar extends Vue {
|
||||
|
||||
this.isDataFetching = false;
|
||||
} catch (error) {
|
||||
this.$notify.error(error.message, AnalyticsErrorEventSource.PROJECT_INFO_BAR);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -134,7 +134,7 @@ import { APP_STATE_MUTATIONS } from '@/store/mutationConstants';
|
||||
import { USER_ACTIONS } from '@/store/modules/users';
|
||||
import { MetaUtils } from '@/utils/meta';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
import VModal from '@/components/common/VModal.vue';
|
||||
import VLoader from '@/components/common/VLoader.vue';
|
||||
@ -183,7 +183,7 @@ export default class AddPaymentMethodModal extends Vue {
|
||||
try {
|
||||
await this.$refs.stripeCardInput.onSubmit();
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.UPGRADE_ACCOUNT_MODAL);
|
||||
}
|
||||
this.isLoading = false;
|
||||
}
|
||||
@ -211,7 +211,7 @@ export default class AddPaymentMethodModal extends Vue {
|
||||
await this.analytics.eventTriggered(AnalyticsEvent.MODAL_ADD_CARD);
|
||||
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.UPGRADE_ACCOUNT_MODAL);
|
||||
}
|
||||
|
||||
this.isLoading = false;
|
||||
|
@ -88,7 +88,7 @@ import { PM_ACTIONS } from '@/utils/constants/actionNames';
|
||||
import { Validator } from '@/utils/validation';
|
||||
import { APP_STATE_MUTATIONS } from '@/store/mutationConstants';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
import VButton from '@/components/common/VButton.vue';
|
||||
import VModal from '@/components/common/VModal.vue';
|
||||
@ -177,7 +177,7 @@ export default class AddTeamMemberModal extends Vue {
|
||||
}
|
||||
|
||||
if (emailArray.includes(this.$store.state.usersModule.email)) {
|
||||
await this.$notify.error(`Error during adding project members. You can't add yourself to the project`);
|
||||
await this.$notify.error(`Error during adding project members. You can't add yourself to the project`, AnalyticsErrorEventSource.ADD_PROJECT_MEMBER_MODAL);
|
||||
this.isLoading = false;
|
||||
|
||||
return;
|
||||
@ -186,7 +186,7 @@ export default class AddTeamMemberModal extends Vue {
|
||||
try {
|
||||
await this.$store.dispatch(PM_ACTIONS.ADD, emailArray);
|
||||
} catch (error) {
|
||||
await this.$notify.error(`Error during adding project members. ${error.message}`);
|
||||
await this.$notify.error(`Error during adding project members. ${error.message}`, AnalyticsErrorEventSource.ADD_PROJECT_MEMBER_MODAL);
|
||||
this.isLoading = false;
|
||||
|
||||
return;
|
||||
@ -199,7 +199,7 @@ export default class AddTeamMemberModal extends Vue {
|
||||
try {
|
||||
await this.$store.dispatch(PM_ACTIONS.FETCH, this.FIRST_PAGE);
|
||||
} catch (error) {
|
||||
await this.$notify.error(`Unable to fetch project members. ${error.message}`);
|
||||
await this.$notify.error(`Unable to fetch project members. ${error.message}`, AnalyticsErrorEventSource.ADD_PROJECT_MEMBER_MODAL);
|
||||
}
|
||||
|
||||
this.closeModal();
|
||||
|
@ -72,6 +72,7 @@ import { Component, Vue } from 'vue-property-decorator';
|
||||
|
||||
import { APP_STATE_MUTATIONS } from '@/store/mutationConstants';
|
||||
import { Wallet } from '@/types/payments';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
import VButton from '@/components/common/VButton.vue';
|
||||
import VModal from '@/components/common/VModal.vue';
|
||||
@ -89,7 +90,6 @@ import InfoIcon from '@/../static/images/payments/infoIcon.svg';
|
||||
},
|
||||
})
|
||||
export default class AddTokenFundsModal extends Vue {
|
||||
|
||||
public $refs!: {
|
||||
canvas: HTMLCanvasElement;
|
||||
};
|
||||
@ -105,7 +105,7 @@ export default class AddTokenFundsModal extends Vue {
|
||||
try {
|
||||
await QRCode.toCanvas(this.$refs.canvas, this.wallet.address);
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.ADD_TOKEN_FUNDS_MODAL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -68,7 +68,7 @@ import { AuthHttpApi } from '@/api/auth';
|
||||
import { Validator } from '@/utils/validation';
|
||||
import { RouteConfig } from '@/router';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { APP_STATE_MUTATIONS } from '@/store/mutationConstants';
|
||||
|
||||
import PasswordStrength from '@/components/common/PasswordStrength.vue';
|
||||
@ -172,13 +172,14 @@ export default class ChangePasswordModal extends Vue {
|
||||
}
|
||||
|
||||
if (hasError) {
|
||||
this.analytics.errorEventTriggered(AnalyticsErrorEventSource.CHANGE_PASSWORD_MODAL);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await this.auth.changePassword(this.oldPassword, this.newPassword);
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.CHANGE_PASSWORD_MODAL);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -190,7 +191,7 @@ export default class ChangePasswordModal extends Vue {
|
||||
this.$router.push(RouteConfig.Login.path);
|
||||
}, DELAY_BEFORE_REDIRECT);
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.CHANGE_PASSWORD_MODAL);
|
||||
}
|
||||
|
||||
this.analytics.eventTriggered(AnalyticsEvent.PASSWORD_CHANGED);
|
||||
|
@ -68,6 +68,7 @@ import { PROJECTS_ACTIONS } from '@/store/modules/projects';
|
||||
import { ProjectFields } from '@/types/projects';
|
||||
import { LocalData } from '@/utils/localData';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
import VLoader from '@/components/common/VLoader.vue';
|
||||
import VInput from '@/components/common/VInput.vue';
|
||||
@ -130,6 +131,7 @@ export default class CreateProjectModal extends Vue {
|
||||
} catch (error) {
|
||||
this.isLoading = false;
|
||||
this.nameError = error.message;
|
||||
this.analytics.errorEventTriggered(AnalyticsErrorEventSource.CREATE_PROJECT_MODAL);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -138,6 +140,7 @@ export default class CreateProjectModal extends Vue {
|
||||
const createdProject = await this.$store.dispatch(PROJECTS_ACTIONS.CREATE, project);
|
||||
this.createdProjectId = createdProject.id;
|
||||
} catch (error) {
|
||||
this.$notify.error(error.message, AnalyticsErrorEventSource.CREATE_PROJECT_MODAL);
|
||||
this.isLoading = false;
|
||||
|
||||
return;
|
||||
|
@ -33,7 +33,7 @@ import { Component, Vue } from 'vue-property-decorator';
|
||||
|
||||
import { APP_STATE_MUTATIONS } from '@/store/mutationConstants';
|
||||
import { OBJECTS_ACTIONS } from '@/store/modules/objects';
|
||||
import { AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { ACCESS_GRANTS_ACTIONS } from '@/store/modules/accessGrants';
|
||||
import { AccessGrant, EdgeCredentials } from '@/types/accessGrants';
|
||||
@ -101,7 +101,7 @@ export default class DeleteBucketModal extends Vue {
|
||||
|
||||
const grantEvent: MessageEvent = await new Promise(resolve => this.worker.onmessage = resolve);
|
||||
if (grantEvent.data.error) {
|
||||
await this.$notify.error(grantEvent.data.error);
|
||||
await this.$notify.error(grantEvent.data.error, AnalyticsErrorEventSource.DELETE_BUCKET_MODAL);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -118,7 +118,7 @@ export default class DeleteBucketModal extends Vue {
|
||||
|
||||
const accessGrantEvent: MessageEvent = await new Promise(resolve => this.worker.onmessage = resolve);
|
||||
if (accessGrantEvent.data.error) {
|
||||
await this.$notify.error(accessGrantEvent.data.error);
|
||||
await this.$notify.error(accessGrantEvent.data.error, AnalyticsErrorEventSource.DELETE_BUCKET_MODAL);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -130,7 +130,7 @@ export default class DeleteBucketModal extends Vue {
|
||||
this.analytics.eventTriggered(AnalyticsEvent.BUCKET_DELETED);
|
||||
await this.fetchBuckets();
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.DELETE_BUCKET_MODAL);
|
||||
return;
|
||||
} finally {
|
||||
this.isLoading = false;
|
||||
@ -146,7 +146,7 @@ export default class DeleteBucketModal extends Vue {
|
||||
try {
|
||||
await this.$store.dispatch(BUCKET_ACTIONS.FETCH, page);
|
||||
} catch (error) {
|
||||
await this.$notify.error(`Unable to fetch buckets. ${error.message}`);
|
||||
await this.$notify.error(`Unable to fetch buckets. ${error.message}`, AnalyticsErrorEventSource.DELETE_BUCKET_MODAL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -156,7 +156,7 @@ export default class DeleteBucketModal extends Vue {
|
||||
public setWorker(): void {
|
||||
this.worker = this.$store.state.accessGrantsModule.accessGrantsWebWorker;
|
||||
this.worker.onerror = (error: ErrorEvent) => {
|
||||
this.$notify.error(error.message);
|
||||
this.$notify.error(error.message, AnalyticsErrorEventSource.DELETE_BUCKET_MODAL);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -46,6 +46,7 @@ import { Component, Vue } from 'vue-property-decorator';
|
||||
import { USER_ACTIONS } from '@/store/modules/users';
|
||||
import { DisableMFARequest } from '@/types/users';
|
||||
import { APP_STATE_MUTATIONS } from '@/store/mutationConstants';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
import ConfirmMFAInput from '@/components/account/mfa/ConfirmMFAInput.vue';
|
||||
import VButton from '@/components/common/VButton.vue';
|
||||
@ -114,7 +115,7 @@ export default class DisableMFAModal extends Vue {
|
||||
|
||||
this.closeModal();
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.DISABLE_MFA_MODAL);
|
||||
this.isError = true;
|
||||
}
|
||||
|
||||
|
@ -44,7 +44,7 @@ import { Component, Vue } from 'vue-property-decorator';
|
||||
import { USER_ACTIONS } from '@/store/modules/users';
|
||||
import { UpdatedUser } from '@/types/users';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { APP_STATE_MUTATIONS } from '@/store/mutationConstants';
|
||||
|
||||
import VModal from '@/components/common/VModal.vue';
|
||||
@ -88,7 +88,7 @@ export default class EditProfileModal extends Vue {
|
||||
try {
|
||||
await this.$store.dispatch(USER_ACTIONS.UPDATE, this.userInfo);
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.EDIT_PROFILE_MODAL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ import { Component, Vue } from 'vue-property-decorator';
|
||||
import { USER_ACTIONS } from '@/store/modules/users';
|
||||
import { APP_STATE_MUTATIONS } from '@/store/mutationConstants';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
import ConfirmMFAInput from '@/components/account/mfa/ConfirmMFAInput.vue';
|
||||
import VButton from '@/components/common/VButton.vue';
|
||||
@ -118,7 +118,11 @@ export default class EnableMFAModal extends Vue {
|
||||
* Renders QR code.
|
||||
*/
|
||||
public async mounted(): Promise<void> {
|
||||
await QRCode.toCanvas(this.$refs.canvas, this.qrLink);
|
||||
try {
|
||||
await QRCode.toCanvas(this.$refs.canvas, this.qrLink);
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.ENABLE_MFA_MODAL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -140,10 +144,13 @@ export default class EnableMFAModal extends Vue {
|
||||
* Toggles view to MFA Recovery Codes state.
|
||||
*/
|
||||
public async showCodes(): Promise<void> {
|
||||
await this.$store.dispatch(USER_ACTIONS.GENERATE_USER_MFA_RECOVERY_CODES);
|
||||
|
||||
this.isEnable = false;
|
||||
this.isCodes = true;
|
||||
try {
|
||||
await this.$store.dispatch(USER_ACTIONS.GENERATE_USER_MFA_RECOVERY_CODES);
|
||||
this.isEnable = false;
|
||||
this.isCodes = true;
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.ENABLE_MFA_MODAL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -169,7 +176,7 @@ export default class EnableMFAModal extends Vue {
|
||||
this.analytics.eventTriggered(AnalyticsEvent.MFA_ENABLED);
|
||||
await this.$notify.success('MFA was enabled successfully');
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.ENABLE_MFA_MODAL);
|
||||
this.isError = true;
|
||||
}
|
||||
|
||||
|
@ -42,6 +42,7 @@ import { Component, Vue } from 'vue-property-decorator';
|
||||
|
||||
import { BrowserFile } from '@/types/browser';
|
||||
import { APP_STATE_MUTATIONS } from '@/store/mutationConstants';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
import VModal from '@/components/common/VModal.vue';
|
||||
import VButton from '@/components/common/VButton.vue';
|
||||
@ -139,7 +140,7 @@ export default class NewFolderModal extends Vue {
|
||||
this.createFolderName.trim(),
|
||||
);
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.CREATE_FOLDER_MODAL);
|
||||
}
|
||||
|
||||
this.createFolderName = '';
|
||||
|
@ -119,6 +119,7 @@ import prettyBytes from 'pretty-bytes';
|
||||
|
||||
import { BrowserFile } from '@/types/browser';
|
||||
import { APP_STATE_MUTATIONS } from '@/store/mutationConstants';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
import VModal from '@/components/common/VModal.vue';
|
||||
import VButton from '@/components/common/VButton.vue';
|
||||
@ -140,7 +141,6 @@ export default class ObjectDetailsModal extends Vue {
|
||||
public objectMapUrl = '';
|
||||
public objectPreviewUrl = '';
|
||||
public previewAndMapFailed = false;
|
||||
|
||||
public objectLink = '';
|
||||
public copyText = 'Copy Link';
|
||||
|
||||
@ -286,7 +286,7 @@ export default class ObjectDetailsModal extends Vue {
|
||||
this.$store.dispatch('files/download', this.file);
|
||||
this.$notify.warning('Do not share download link with other people. If you want to share this data better use "Share" option.');
|
||||
} catch (error) {
|
||||
this.$notify.error('Can not download your file');
|
||||
this.$notify.error('Can not download your file', AnalyticsErrorEventSource.OBJECT_DETAILS_MODAL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -57,6 +57,7 @@ import { AccessGrant, EdgeCredentials } from '@/types/accessGrants';
|
||||
import { ACCESS_GRANTS_ACTIONS } from '@/store/modules/accessGrants';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { PROJECTS_ACTIONS } from '@/store/modules/projects';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
import VModal from '@/components/common/VModal.vue';
|
||||
import VInput from '@/components/common/VInput.vue';
|
||||
@ -98,6 +99,7 @@ export default class OpenBucketModal extends Vue {
|
||||
|
||||
if (!this.passphrase) {
|
||||
this.enterError = 'Passphrase can\'t be empty';
|
||||
this.analytics.errorEventTriggered(AnalyticsErrorEventSource.OPEN_BUCKET_MODAL);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -111,8 +113,8 @@ export default class OpenBucketModal extends Vue {
|
||||
this.closeModal();
|
||||
this.analytics.pageVisit(RouteConfig.Buckets.with(RouteConfig.UploadFile).path);
|
||||
await this.$router.push(RouteConfig.Buckets.with(RouteConfig.UploadFile).path);
|
||||
} catch (e) {
|
||||
await this.$notify.error(e.message);
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.OPEN_BUCKET_MODAL);
|
||||
this.isLoading = false;
|
||||
}
|
||||
}
|
||||
@ -184,7 +186,7 @@ export default class OpenBucketModal extends Vue {
|
||||
public setWorker(): void {
|
||||
this.worker = this.$store.state.accessGrantsModule.accessGrantsWebWorker;
|
||||
this.worker.onerror = (error: ErrorEvent) => {
|
||||
this.$notify.error(error.message);
|
||||
this.$notify.error(error.message, AnalyticsErrorEventSource.OPEN_BUCKET_MODAL);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -43,6 +43,7 @@ import { ACCESS_GRANTS_ACTIONS } from '@/store/modules/accessGrants';
|
||||
import { PROJECTS_ACTIONS } from '@/store/modules/projects';
|
||||
import { MetaUtils } from '@/utils/meta';
|
||||
import { AccessGrant, EdgeCredentials } from '@/types/accessGrants';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
import VModal from '@/components/common/VModal.vue';
|
||||
import VLoader from '@/components/common/VLoader.vue';
|
||||
@ -118,7 +119,7 @@ export default class ShareBucketModal extends Vue {
|
||||
const grantEvent: MessageEvent = await new Promise(resolve => this.worker.onmessage = resolve);
|
||||
const grantData = grantEvent.data;
|
||||
if (grantData.error) {
|
||||
await this.$notify.error(grantData.error);
|
||||
await this.$notify.error(grantData.error, AnalyticsErrorEventSource.SHARE_BUCKET_MODAL);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -136,7 +137,7 @@ export default class ShareBucketModal extends Vue {
|
||||
const event: MessageEvent = await new Promise(resolve => this.worker.onmessage = resolve);
|
||||
const data = event.data;
|
||||
if (data.error) {
|
||||
await this.$notify.error(data.error);
|
||||
await this.$notify.error(data.error, AnalyticsErrorEventSource.SHARE_BUCKET_MODAL);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -150,7 +151,7 @@ export default class ShareBucketModal extends Vue {
|
||||
|
||||
this.link = `${linksharingURL}/${credentials.accessKeyId}/${path}`;
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.SHARE_BUCKET_MODAL);
|
||||
} finally {
|
||||
this.isLoading = false;
|
||||
}
|
||||
@ -162,7 +163,7 @@ export default class ShareBucketModal extends Vue {
|
||||
public setWorker(): void {
|
||||
this.worker = this.$store.state.accessGrantsModule.accessGrantsWebWorker;
|
||||
this.worker.onerror = (error: ErrorEvent) => {
|
||||
this.$notify.error(error.message);
|
||||
this.$notify.error(error.message, AnalyticsErrorEventSource.SHARE_BUCKET_MODAL);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -67,6 +67,7 @@ import { AccessGrant, EdgeCredentials } from '@/types/accessGrants';
|
||||
import { OBJECTS_ACTIONS, OBJECTS_MUTATIONS } from '@/store/modules/objects';
|
||||
import { PROJECTS_ACTIONS } from '@/store/modules/projects';
|
||||
import { MetaUtils } from '@/utils/meta';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
import VModal from '@/components/common/VModal.vue';
|
||||
import VButton from '@/components/common/VButton.vue';
|
||||
@ -174,7 +175,7 @@ function setWorker(): void {
|
||||
worker.value = store.state.accessGrantsModule.accessGrantsWebWorker;
|
||||
if (worker.value) {
|
||||
worker.value.onerror = (error: ErrorEvent) => {
|
||||
notify.error(error.message);
|
||||
notify.error(error.message, AnalyticsErrorEventSource.CREATE_PROJECT_LEVEL_PASSPHRASE_MODAL);
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -184,8 +185,7 @@ function setWorker(): void {
|
||||
*/
|
||||
async function setAccess(): Promise<void> {
|
||||
if (!worker.value) {
|
||||
notify.error('Worker is not defined');
|
||||
return;
|
||||
throw new Error('Worker is not defined');
|
||||
}
|
||||
|
||||
if (!apiKey.value) {
|
||||
@ -289,8 +289,8 @@ async function onContinue(): Promise<void> {
|
||||
store.dispatch(OBJECTS_ACTIONS.SET_PASSPHRASE, passphrase.value);
|
||||
|
||||
activeStep.value = CreateProjectPassphraseStep.Success;
|
||||
} catch (e) {
|
||||
await notify.error(e.message);
|
||||
} catch (error) {
|
||||
await notify.error(error.message, AnalyticsErrorEventSource.CREATE_PROJECT_LEVEL_PASSPHRASE_MODAL);
|
||||
} finally {
|
||||
isLoading.value = false;
|
||||
}
|
||||
|
@ -37,7 +37,6 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
|
||||
import { APP_STATE_MUTATIONS } from '@/store/mutationConstants';
|
||||
@ -47,6 +46,7 @@ import { AccessGrant, EdgeCredentials } from '@/types/accessGrants';
|
||||
import { OBJECTS_ACTIONS, OBJECTS_MUTATIONS } from '@/store/modules/objects';
|
||||
import { PROJECTS_ACTIONS } from '@/store/modules/projects';
|
||||
import { MetaUtils } from '@/utils/meta';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
import VButton from '@/components/common/VButton.vue';
|
||||
import VInput from '@/components/common/VInput.vue';
|
||||
@ -102,7 +102,7 @@ function setWorker(): void {
|
||||
worker.value = store.state.accessGrantsModule.accessGrantsWebWorker;
|
||||
if (worker.value) {
|
||||
worker.value.onerror = (error: ErrorEvent) => {
|
||||
notify.error(error.message);
|
||||
notify.error(error.message, AnalyticsErrorEventSource.SWITCH_PROJECT_LEVEL_PASSPHRASE_MODAL);
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -112,8 +112,7 @@ function setWorker(): void {
|
||||
*/
|
||||
async function setAccess(): Promise<void> {
|
||||
if (!worker.value) {
|
||||
notify.error('Worker is not defined');
|
||||
return;
|
||||
throw new Error('Worker is not defined');
|
||||
}
|
||||
|
||||
if (!apiKey.value) {
|
||||
@ -193,8 +192,8 @@ async function onSwitch(): Promise<void> {
|
||||
|
||||
notify.success('Passphrase was switched successfully');
|
||||
store.commit(APP_STATE_MUTATIONS.TOGGLE_MANAGE_PROJECT_PASSPHRASE_MODAL_SHOWN);
|
||||
} catch (e) {
|
||||
await notify.error(e.message);
|
||||
} catch (error) {
|
||||
await notify.error(error.message, AnalyticsErrorEventSource.SWITCH_PROJECT_LEVEL_PASSPHRASE_MODAL);
|
||||
} finally {
|
||||
isLoading.value = false;
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ import { ACCESS_GRANTS_ACTIONS } from '@/store/modules/accessGrants';
|
||||
import { BUCKET_ACTIONS } from '@/store/modules/buckets';
|
||||
import { OBJECTS_ACTIONS } from '@/store/modules/objects';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { APP_STATE_MUTATIONS } from '@/store/mutationConstants';
|
||||
import { MetaUtils } from '@/utils/meta';
|
||||
import { PAYMENTS_ACTIONS } from '@/store/modules/payments';
|
||||
@ -138,7 +138,7 @@ export default class AccountArea extends Vue {
|
||||
this.analytics.eventTriggered(AnalyticsEvent.LOGOUT_CLICKED);
|
||||
await this.auth.logout();
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.NAVIGATION_ACCOUNT_AREA);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -176,7 +176,7 @@ import { NavigationLink } from '@/types/navigation';
|
||||
import { Project } from '@/types/projects';
|
||||
import { User } from '@/types/users';
|
||||
import { APP_STATE_ACTIONS, NOTIFICATION_ACTIONS, PM_ACTIONS } from '@/utils/constants/actionNames';
|
||||
import { AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { LocalData } from '@/utils/localData';
|
||||
import { MetaUtils } from '@/utils/meta';
|
||||
import { AB_TESTING_ACTIONS } from '@/store/modules/abTesting';
|
||||
@ -386,8 +386,9 @@ export default class MobileNavigation extends Vue {
|
||||
try {
|
||||
await this.$store.dispatch(PROJECTS_ACTIONS.FETCH);
|
||||
await this.$store.dispatch(PROJECTS_ACTIONS.GET_LIMITS, this.$store.getters.selectedProject.id);
|
||||
this.isLoading = false;
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.MOBILE_NAVIGATION);
|
||||
} finally {
|
||||
this.isLoading = false;
|
||||
}
|
||||
}
|
||||
@ -416,7 +417,7 @@ export default class MobileNavigation extends Vue {
|
||||
await this.$store.dispatch(BUCKET_ACTIONS.FETCH, this.FIRST_PAGE);
|
||||
await this.$store.dispatch(PROJECTS_ACTIONS.GET_LIMITS, this.$store.getters.selectedProject.id);
|
||||
} catch (error) {
|
||||
await this.$notify.error(`Unable to select project. ${error.message}`);
|
||||
await this.$notify.error(`Unable to select project. ${error.message}`, AnalyticsErrorEventSource.MOBILE_NAVIGATION);
|
||||
}
|
||||
}
|
||||
|
||||
@ -489,7 +490,7 @@ export default class MobileNavigation extends Vue {
|
||||
this.analytics.eventTriggered(AnalyticsEvent.LOGOUT_CLICKED);
|
||||
await this.auth.logout();
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.MOBILE_NAVIGATION);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { RouteConfig } from '@/router';
|
||||
import { APP_STATE_ACTIONS, PM_ACTIONS } from '@/utils/constants/actionNames';
|
||||
import { PROJECTS_ACTIONS } from '@/store/modules/projects';
|
||||
import { AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { LocalData } from '@/utils/localData';
|
||||
import { PAYMENTS_ACTIONS } from '@/store/modules/payments';
|
||||
import { ACCESS_GRANTS_ACTIONS } from '@/store/modules/accessGrants';
|
||||
@ -127,8 +127,9 @@ export default class ProjectSelection extends Vue {
|
||||
try {
|
||||
await this.$store.dispatch(PROJECTS_ACTIONS.FETCH);
|
||||
await this.$store.dispatch(PROJECTS_ACTIONS.GET_LIMITS, this.$store.getters.selectedProject.id);
|
||||
this.isLoading = false;
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.NAVIGATION_PROJECT_SELECTION);
|
||||
} finally {
|
||||
this.isLoading = false;
|
||||
}
|
||||
}
|
||||
@ -174,7 +175,7 @@ export default class ProjectSelection extends Vue {
|
||||
this.$store.dispatch(BUCKET_ACTIONS.FETCH, this.FIRST_PAGE),
|
||||
]);
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.NAVIGATION_PROJECT_SELECTION);
|
||||
}
|
||||
|
||||
return;
|
||||
@ -184,7 +185,7 @@ export default class ProjectSelection extends Vue {
|
||||
try {
|
||||
await this.$store.dispatch(ACCESS_GRANTS_ACTIONS.FETCH, this.FIRST_PAGE);
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.NAVIGATION_PROJECT_SELECTION);
|
||||
}
|
||||
|
||||
return;
|
||||
@ -194,7 +195,7 @@ export default class ProjectSelection extends Vue {
|
||||
try {
|
||||
await this.$store.dispatch(PM_ACTIONS.FETCH, this.FIRST_PAGE);
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.NAVIGATION_PROJECT_SELECTION);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ import { ACCESS_GRANTS_ACTIONS } from '@/store/modules/accessGrants';
|
||||
import { PROJECTS_ACTIONS } from '@/store/modules/projects';
|
||||
import { MetaUtils } from '@/utils/meta';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { BUCKET_ACTIONS } from '@/store/modules/buckets';
|
||||
|
||||
import BucketCreationGeneratePassphrase from '@/components/objects/BucketCreationGeneratePassphrase.vue';
|
||||
@ -74,7 +74,7 @@ export default class BucketCreation extends Vue {
|
||||
try {
|
||||
await this.createBucketAndNavigate();
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.BUCKET_CREATION_FLOW);
|
||||
}
|
||||
|
||||
this.isLoading = false;
|
||||
@ -98,7 +98,7 @@ export default class BucketCreation extends Vue {
|
||||
public setWorker(): void {
|
||||
this.worker = this.$store.state.accessGrantsModule.accessGrantsWebWorker;
|
||||
this.worker.onerror = (error: ErrorEvent) => {
|
||||
this.$notify.error(error.message);
|
||||
this.$notify.error(error.message, AnalyticsErrorEventSource.BUCKET_CREATION_FLOW);
|
||||
};
|
||||
}
|
||||
|
||||
@ -114,8 +114,8 @@ export default class BucketCreation extends Vue {
|
||||
this.setWorker();
|
||||
await this.setAccess();
|
||||
await this.createBucketAndNavigate();
|
||||
} catch (e) {
|
||||
await this.$notify.error(e.message);
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.BUCKET_CREATION_FLOW);
|
||||
} finally {
|
||||
this.isLoading = false;
|
||||
}
|
||||
@ -135,7 +135,7 @@ export default class BucketCreation extends Vue {
|
||||
try {
|
||||
await this.$store.dispatch(ACCESS_GRANTS_ACTIONS.DELETE_BY_NAME_AND_PROJECT_ID, this.FILE_BROWSER_AG_NAME);
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.BUCKET_CREATION_FLOW);
|
||||
}
|
||||
}
|
||||
|
||||
@ -146,7 +146,7 @@ export default class BucketCreation extends Vue {
|
||||
try {
|
||||
await this.$store.dispatch(BUCKET_ACTIONS.FETCH, page);
|
||||
} catch (error) {
|
||||
await this.$notify.error(`Unable to fetch buckets. ${error.message}`);
|
||||
await this.$notify.error(`Unable to fetch buckets. ${error.message}`, AnalyticsErrorEventSource.BUCKET_CREATION_FLOW);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -120,6 +120,8 @@ import { Component, Prop, Vue } from 'vue-property-decorator';
|
||||
import { generateMnemonic } from 'bip39';
|
||||
|
||||
import { Download } from '@/utils/download';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
import VButton from '@/components/common/VButton.vue';
|
||||
import VInput from '@/components/common/VInput.vue';
|
||||
@ -165,6 +167,8 @@ export default class GeneratePassphrase extends Vue {
|
||||
public isSavingConfirmed = false;
|
||||
public isCheckboxError = false;
|
||||
|
||||
private readonly analytics = new AnalyticsHttpApi();
|
||||
|
||||
public setSavingConfirmation(value: boolean): void {
|
||||
this.isSavingConfirmed = value;
|
||||
}
|
||||
@ -189,6 +193,7 @@ export default class GeneratePassphrase extends Vue {
|
||||
public onDownloadClick(): void {
|
||||
if (!this.passphrase) {
|
||||
this.enterError = 'Can\'t be empty!';
|
||||
this.analytics.errorEventTriggered(AnalyticsErrorEventSource.BUCKET_CREATION_PASSPHRASE_STEP);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -224,12 +229,14 @@ export default class GeneratePassphrase extends Vue {
|
||||
public async onNextButtonClick(): Promise<void> {
|
||||
if (!this.passphrase) {
|
||||
this.enterError = 'Can\'t be empty!';
|
||||
this.analytics.errorEventTriggered(AnalyticsErrorEventSource.BUCKET_CREATION_PASSPHRASE_STEP);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.isSavingConfirmed) {
|
||||
this.isCheckboxError = true;
|
||||
this.analytics.errorEventTriggered(AnalyticsErrorEventSource.BUCKET_CREATION_PASSPHRASE_STEP);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -56,6 +56,7 @@ import { Validator } from '@/utils/validation';
|
||||
import { LocalData } from '@/utils/localData';
|
||||
import { BUCKET_ACTIONS } from '@/store/modules/buckets';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
import VInput from '@/components/common/VInput.vue';
|
||||
import VButton from '@/components/common/VButton.vue';
|
||||
@ -86,8 +87,8 @@ export default class BucketCreationNameStep extends Vue {
|
||||
try {
|
||||
await this.$store.dispatch(BUCKET_ACTIONS.FETCH_ALL_BUCKET_NAMES);
|
||||
this.name = this.allBucketNames.length > 0 ? '' : 'demo-bucket';
|
||||
} catch (e) {
|
||||
await this.$notify.error(e.message);
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.BUCKET_CREATION_NAME_STEP);
|
||||
} finally {
|
||||
this.isLoading = false;
|
||||
}
|
||||
@ -105,10 +106,13 @@ export default class BucketCreationNameStep extends Vue {
|
||||
* Sets bucket name from input.
|
||||
*/
|
||||
public onNextButtonClick(): void {
|
||||
if (!this.isBucketNameValid(this.name)) return;
|
||||
if (!this.isBucketNameValid(this.name)) {
|
||||
this.analytics.errorEventTriggered(AnalyticsErrorEventSource.BUCKET_CREATION_NAME_STEP);
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.allBucketNames.includes(this.name)) {
|
||||
this.$notify.error('Bucket with this name already exists');
|
||||
this.$notify.error('Bucket with this name already exists', AnalyticsErrorEventSource.BUCKET_CREATION_NAME_STEP);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -74,7 +74,7 @@ import { BucketPage } from '@/types/buckets';
|
||||
import { RouteConfig } from '@/router';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { useNotify, useRouter, useStore } from '@/utils/hooks';
|
||||
import { AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
import VTable from '@/components/common/VTable.vue';
|
||||
import BucketItem from '@/components/objects/BucketItem.vue';
|
||||
@ -162,7 +162,7 @@ async function fetchBuckets(page = 1): Promise<void> {
|
||||
try {
|
||||
await store.dispatch(BUCKET_ACTIONS.FETCH, page);
|
||||
} catch (error) {
|
||||
await notify.error(`Unable to fetch buckets. ${error.message}`);
|
||||
await notify.error(`Unable to fetch buckets. ${error.message}`, AnalyticsErrorEventSource.BUCKET_TABLE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -178,7 +178,7 @@ async function searchBuckets(searchQuery: string): Promise<void> {
|
||||
try {
|
||||
await store.dispatch(BUCKET_ACTIONS.FETCH, 1);
|
||||
} catch (error) {
|
||||
await notify.error(`Unable to fetch buckets: ${error.message}`);
|
||||
await notify.error(`Unable to fetch buckets: ${error.message}`, AnalyticsErrorEventSource.BUCKET_TABLE);
|
||||
}
|
||||
|
||||
searchLoading.value = false;
|
||||
|
@ -27,6 +27,7 @@ import { LocalData } from '@/utils/localData';
|
||||
import { BUCKET_ACTIONS } from '@/store/modules/buckets';
|
||||
import { BucketPage } from '@/types/buckets';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
import EncryptionBanner from '@/components/objects/EncryptionBanner.vue';
|
||||
import BucketsTable from '@/components/objects/BucketsTable.vue';
|
||||
@ -84,7 +85,7 @@ export default class BucketsView extends Vue {
|
||||
await this.$router.push(RouteConfig.Buckets.with(RouteConfig.BucketCreation).path);
|
||||
}
|
||||
} catch (error) {
|
||||
await this.$notify.error(`Failed to setup Buckets view. ${error.message}`);
|
||||
await this.$notify.error(`Failed to setup Buckets view. ${error.message}`, AnalyticsErrorEventSource.BUCKET_PAGE);
|
||||
} finally {
|
||||
this.isLoading = false;
|
||||
}
|
||||
@ -97,7 +98,7 @@ export default class BucketsView extends Vue {
|
||||
try {
|
||||
await this.$store.dispatch(BUCKET_ACTIONS.FETCH, page);
|
||||
} catch (error) {
|
||||
await this.$notify.error(`Unable to fetch buckets. ${error.message}`);
|
||||
await this.$notify.error(`Unable to fetch buckets. ${error.message}`, AnalyticsErrorEventSource.BUCKET_PAGE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ import { RouteConfig } from '@/router';
|
||||
import { ACCESS_GRANTS_ACTIONS } from '@/store/modules/accessGrants';
|
||||
import { PROJECTS_ACTIONS } from '@/store/modules/projects';
|
||||
import { AccessGrant, EdgeCredentials } from '@/types/accessGrants';
|
||||
import { AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { MetaUtils } from '@/utils/meta';
|
||||
import { Bucket } from '@/types/buckets';
|
||||
|
||||
@ -97,7 +97,11 @@ export default class UploadFile extends Vue {
|
||||
accessKey: this.edgeCredentials.accessKeyId,
|
||||
secretKey: this.edgeCredentials.secretKey,
|
||||
});
|
||||
await this.$store.dispatch('files/list', '');
|
||||
try {
|
||||
await this.$store.dispatch('files/list', '');
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.UPLOAD_FILE_VIEW);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -113,7 +117,7 @@ export default class UploadFile extends Vue {
|
||||
|
||||
return `${this.linksharingURL}/s/${creds.accessKeyId}/${path}`;
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.UPLOAD_FILE_VIEW);
|
||||
|
||||
return '';
|
||||
}
|
||||
@ -137,7 +141,7 @@ export default class UploadFile extends Vue {
|
||||
|
||||
return `${this.linksharingURL}/${credentials.accessKeyId}/${path}`;
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.UPLOAD_FILE_VIEW);
|
||||
|
||||
return '';
|
||||
}
|
||||
@ -149,7 +153,7 @@ export default class UploadFile extends Vue {
|
||||
public setWorker(): void {
|
||||
this.worker = this.$store.state.accessGrantsModule.accessGrantsWebWorker;
|
||||
this.worker.onerror = (error: ErrorEvent) => {
|
||||
this.$notify.error(error.message);
|
||||
this.$notify.error(error.message, AnalyticsErrorEventSource.UPLOAD_FILE_VIEW);
|
||||
};
|
||||
}
|
||||
|
||||
@ -171,7 +175,7 @@ export default class UploadFile extends Vue {
|
||||
const grantEvent: MessageEvent = await new Promise(resolve => this.worker.onmessage = resolve);
|
||||
const grantData = grantEvent.data;
|
||||
if (grantData.error) {
|
||||
await this.$notify.error(grantData.error);
|
||||
await this.$notify.error(grantData.error, AnalyticsErrorEventSource.UPLOAD_FILE_VIEW);
|
||||
|
||||
return new EdgeCredentials();
|
||||
}
|
||||
@ -198,7 +202,7 @@ export default class UploadFile extends Vue {
|
||||
const event: MessageEvent = await new Promise(resolve => this.worker.onmessage = resolve);
|
||||
const data = event.data;
|
||||
if (data.error) {
|
||||
await this.$notify.error(data.error);
|
||||
await this.$notify.error(data.error, AnalyticsErrorEventSource.UPLOAD_FILE_VIEW);
|
||||
|
||||
return new EdgeCredentials();
|
||||
}
|
||||
|
@ -12,14 +12,12 @@
|
||||
info="Start uploading files in the browser and instantly see how your data gets distributed over the Storj network around the world."
|
||||
button-label="Continue in web ->"
|
||||
:on-click="onUploadInBrowserClick"
|
||||
:is-disabled="isLoading"
|
||||
/>
|
||||
<OverviewContainer
|
||||
title="Start with Uplink CLI"
|
||||
info="The Uplink CLI is a command-line interface tool which allows you to upload and download files from the network, manage permissions and share files."
|
||||
button-label="Continue in cli ->"
|
||||
:on-click="onUplinkCLIClick"
|
||||
:is-disabled="isLoading"
|
||||
/>
|
||||
</div>
|
||||
<p class="overview-area__skip-button" @click="onSkip">
|
||||
@ -47,7 +45,6 @@ import OverviewContainer from '@/components/onboardingTour/steps/common/Overview
|
||||
},
|
||||
})
|
||||
export default class OverviewStep extends Vue {
|
||||
public isLoading = false;
|
||||
public projectDashboardPath = RouteConfig.ProjectDashboard.path;
|
||||
public titleLabel = '';
|
||||
|
||||
@ -88,31 +85,19 @@ export default class OverviewStep extends Vue {
|
||||
* Holds button click logic.
|
||||
* Redirects to next step (creating access grant).
|
||||
*/
|
||||
public async onUplinkCLIClick(): Promise<void> {
|
||||
if (this.isLoading) return;
|
||||
|
||||
this.isLoading = true;
|
||||
|
||||
await this.analytics.linkEventTriggered(AnalyticsEvent.PATH_SELECTED, 'CLI');
|
||||
public onUplinkCLIClick(): void {
|
||||
this.$router.push(RouteConfig.OnboardingTour.with(RouteConfig.CLIStep).with(RouteConfig.AGName).path);
|
||||
this.analytics.linkEventTriggered(AnalyticsEvent.PATH_SELECTED, 'CLI');
|
||||
this.analytics.pageVisit(RouteConfig.OnboardingTour.with(RouteConfig.CLIStep).with(RouteConfig.AGName).path);
|
||||
await this.$router.push(RouteConfig.OnboardingTour.with(RouteConfig.CLIStep).with(RouteConfig.AGName).path);
|
||||
|
||||
this.isLoading = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirects to buckets page.
|
||||
*/
|
||||
public async onUploadInBrowserClick(): Promise<void> {
|
||||
if (this.isLoading) return;
|
||||
|
||||
this.isLoading = true;
|
||||
|
||||
await this.analytics.linkEventTriggered(AnalyticsEvent.PATH_SELECTED, 'Continue in Browser');
|
||||
public onUploadInBrowserClick(): void {
|
||||
this.$router.push(RouteConfig.Buckets.path).catch(() => {return; });
|
||||
this.analytics.linkEventTriggered(AnalyticsEvent.PATH_SELECTED, 'Continue in Browser');
|
||||
this.analytics.pageVisit(RouteConfig.Buckets.path);
|
||||
await this.$router.push(RouteConfig.Buckets.path).catch(() => {return; });
|
||||
|
||||
this.isLoading = false;
|
||||
}
|
||||
|
||||
private get satelliteName(): string {
|
||||
|
@ -32,6 +32,7 @@ import { AccessGrant } from '@/types/accessGrants';
|
||||
import { ACCESS_GRANTS_ACTIONS } from '@/store/modules/accessGrants';
|
||||
import { APP_STATE_MUTATIONS } from '@/store/mutationConstants';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
import CLIFlowContainer from '@/components/onboardingTour/steps/common/CLIFlowContainer.vue';
|
||||
import VInput from '@/components/common/VInput.vue';
|
||||
@ -81,6 +82,7 @@ export default class AGName extends Vue {
|
||||
|
||||
if (!this.name) {
|
||||
this.errorMessage = 'Access Grant name can\'t be empty';
|
||||
this.analytics.errorEventTriggered(AnalyticsErrorEventSource.ONBOARDING_NAME_STEP);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -92,7 +94,8 @@ export default class AGName extends Vue {
|
||||
createdAccessGrant = await this.$store.dispatch(ACCESS_GRANTS_ACTIONS.CREATE, this.name);
|
||||
|
||||
await this.$notify.success('New clean access grant was generated successfully.');
|
||||
} catch {
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.ONBOARDING_NAME_STEP);
|
||||
return;
|
||||
} finally {
|
||||
this.isLoading = false;
|
||||
@ -125,4 +128,4 @@ export default class AGName extends Vue {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
@ -44,7 +44,7 @@ import { Component, Vue } from 'vue-property-decorator';
|
||||
import { RouteConfig } from '@/router';
|
||||
import { BUCKET_ACTIONS } from '@/store/modules/buckets';
|
||||
import { APP_STATE_MUTATIONS } from '@/store/mutationConstants';
|
||||
import { AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
|
||||
import CLIFlowContainer from '@/components/onboardingTour/steps/common/CLIFlowContainer.vue';
|
||||
@ -96,7 +96,7 @@ export default class AGPermissions extends Vue {
|
||||
|
||||
this.areBucketNamesFetching = false;
|
||||
} catch (error) {
|
||||
await this.$notify.error(`Unable to fetch all bucket names. ${error.message}`);
|
||||
await this.$notify.error(`Unable to fetch all bucket names. ${error.message}`, AnalyticsErrorEventSource.ONBOARDING_PERMISSIONS_STEP);
|
||||
}
|
||||
|
||||
this.isLoading = false;
|
||||
@ -109,7 +109,7 @@ export default class AGPermissions extends Vue {
|
||||
public setWorker(): void {
|
||||
this.worker = this.$store.state.accessGrantsModule.accessGrantsWebWorker;
|
||||
this.worker.onerror = (error: ErrorEvent) => {
|
||||
this.$notify.error(error.message);
|
||||
this.$notify.error(error.message, AnalyticsErrorEventSource.ONBOARDING_PERMISSIONS_STEP);
|
||||
};
|
||||
}
|
||||
|
||||
@ -138,7 +138,7 @@ export default class AGPermissions extends Vue {
|
||||
|
||||
await this.$notify.success('Restrictions were set successfully.');
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.ONBOARDING_PERMISSIONS_STEP);
|
||||
return;
|
||||
} finally {
|
||||
this.isLoading = false;
|
||||
|
@ -67,6 +67,7 @@ import { PROJECTS_ACTIONS } from '@/store/modules/projects';
|
||||
import { ProjectFields } from '@/types/projects';
|
||||
import { LocalData } from '@/utils/localData';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
import VLoader from '@/components/common/VLoader.vue';
|
||||
import VButton from '@/components/common/VButton.vue';
|
||||
@ -136,6 +137,7 @@ export default class NewProjectPopup extends Vue {
|
||||
} catch (error) {
|
||||
this.isLoading = false;
|
||||
this.nameError = error.message;
|
||||
this.analytics.errorEventTriggered(AnalyticsErrorEventSource.CREATE_PROJECT_MODAL);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -144,6 +146,7 @@ export default class NewProjectPopup extends Vue {
|
||||
const createdProject = await this.$store.dispatch(PROJECTS_ACTIONS.CREATE, project);
|
||||
this.createdProjectId = createdProject.id;
|
||||
} catch (error) {
|
||||
this.$notify.error(error.message, AnalyticsErrorEventSource.CREATE_PROJECT_MODAL);
|
||||
this.isLoading = false;
|
||||
|
||||
return;
|
||||
|
@ -210,6 +210,7 @@ import {
|
||||
ProjectFields, ProjectLimits,
|
||||
} from '@/types/projects';
|
||||
import { MetaUtils } from '@/utils/meta';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
import VButton from '@/components/common/VButton.vue';
|
||||
|
||||
@ -220,7 +221,6 @@ import VButton from '@/components/common/VButton.vue';
|
||||
},
|
||||
})
|
||||
export default class EditProjectDetails extends Vue {
|
||||
|
||||
@Prop({ default: Dimensions.TB })
|
||||
public activeStorageMeasurement: string;
|
||||
@Prop({ default: Dimensions.TB })
|
||||
@ -261,7 +261,7 @@ export default class EditProjectDetails extends Vue {
|
||||
try {
|
||||
await this.$store.dispatch(PROJECTS_ACTIONS.GET_LIMITS, this.$store.getters.selectedProject.id);
|
||||
} catch (error) {
|
||||
return;
|
||||
this.$notify.error(error.message, AnalyticsErrorEventSource.EDIT_PROJECT_DETAILS);
|
||||
}
|
||||
}
|
||||
|
||||
@ -443,7 +443,6 @@ export default class EditProjectDetails extends Vue {
|
||||
}
|
||||
|
||||
public toggleBandwidthMeasurement(isTB: boolean): void {
|
||||
|
||||
if (isTB) {
|
||||
this.activeBandwidthMeasurement = Dimensions.TB;
|
||||
this.bandwidthLimitValue = this.toTB(this.bandwidthLimitValue);
|
||||
@ -508,6 +507,7 @@ export default class EditProjectDetails extends Vue {
|
||||
|
||||
await this.$store.dispatch(PROJECTS_ACTIONS.UPDATE_NAME, updatedProject);
|
||||
} catch (error) {
|
||||
this.$notify.error(error.message, AnalyticsErrorEventSource.EDIT_PROJECT_DETAILS);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -523,6 +523,7 @@ export default class EditProjectDetails extends Vue {
|
||||
const updatedProject = new ProjectFields('', this.descriptionValue);
|
||||
await this.$store.dispatch(PROJECTS_ACTIONS.UPDATE_DESCRIPTION, updatedProject);
|
||||
} catch (error) {
|
||||
this.$notify.error(error.message, AnalyticsErrorEventSource.EDIT_PROJECT_DETAILS);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -546,6 +547,7 @@ export default class EditProjectDetails extends Vue {
|
||||
const updatedProject = new ProjectLimits(0, 0, storageLimitValue);
|
||||
await this.$store.dispatch(PROJECTS_ACTIONS.UPDATE_STORAGE_LIMIT, updatedProject);
|
||||
} catch (error) {
|
||||
this.$notify.error(error.message, AnalyticsErrorEventSource.EDIT_PROJECT_DETAILS);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -569,6 +571,7 @@ export default class EditProjectDetails extends Vue {
|
||||
const updatedProject = new ProjectLimits(bandwidthLimitValue);
|
||||
await this.$store.dispatch(PROJECTS_ACTIONS.UPDATE_BANDWIDTH_LIMIT, updatedProject);
|
||||
} catch (error) {
|
||||
this.$notify.error(error.message, AnalyticsErrorEventSource.EDIT_PROJECT_DETAILS);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -25,6 +25,7 @@ import { BUCKET_ACTIONS } from '@/store/modules/buckets';
|
||||
import { PAYMENTS_ACTIONS } from '@/store/modules/payments';
|
||||
import { PM_ACTIONS } from '@/utils/constants/actionNames';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
import ProjectUsage from '@/components/project/usage/ProjectUsage.vue';
|
||||
import ProjectSummary from '@/components/project/summary/ProjectSummary.vue';
|
||||
@ -69,7 +70,7 @@ export default class ProjectDashboard extends Vue {
|
||||
|
||||
this.isSummaryDataFetching = false;
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.PROJECT_DASHBOARD_PAGE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -189,6 +189,7 @@ import { Dimensions, Size } from '@/utils/bytesSize';
|
||||
import { ChartUtils } from '@/utils/chart';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { LocalData } from '@/utils/localData';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
import VLoader from '@/components/common/VLoader.vue';
|
||||
import InfoContainer from '@/components/project/newProjectDashboard/InfoContainer.vue';
|
||||
@ -258,9 +259,8 @@ export default class NewProjectDashboard extends Vue {
|
||||
await this.$store.dispatch(PROJECTS_ACTIONS.FETCH_DAILY_DATA, { since: past, before: now });
|
||||
await this.$store.dispatch(PROJECTS_ACTIONS.GET_LIMITS, this.$store.getters.selectedProject.id);
|
||||
await this.$store.dispatch(PAYMENTS_ACTIONS.GET_PROJECT_USAGE_AND_CHARGES_CURRENT_ROLLUP);
|
||||
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.PROJECT_DASHBOARD_PAGE);
|
||||
} finally {
|
||||
this.isDataFetching = false;
|
||||
}
|
||||
@ -272,7 +272,7 @@ export default class NewProjectDashboard extends Vue {
|
||||
|
||||
this.areBucketsFetching = false;
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.PROJECT_DASHBOARD_PAGE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -349,7 +349,7 @@ export default class NewProjectDashboard extends Vue {
|
||||
try {
|
||||
await this.$store.dispatch(PROJECTS_ACTIONS.FETCH_DAILY_DATA, { since, before });
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.PROJECT_DASHBOARD_PAGE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
import { Component, Vue } from 'vue-property-decorator';
|
||||
|
||||
import { PROJECTS_ACTIONS } from '@/store/modules/projects';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
import UsageArea from '@/components/project/usage/UsageArea.vue';
|
||||
|
||||
@ -50,7 +51,7 @@ export default class ProjectUsage extends Vue {
|
||||
|
||||
this.isDataFetching = false;
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.PROJECT_USAGE_CONTAINER);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -59,7 +59,7 @@ import { LocalData } from '@/utils/localData';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { APP_STATE_MUTATIONS } from '@/store/mutationConstants';
|
||||
import { User } from '@/types/users';
|
||||
import { AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
import ProjectsListItem from '@/components/projectsList/ProjectsListItem.vue';
|
||||
import VTable from '@/components/common/VTable.vue';
|
||||
@ -97,7 +97,7 @@ export default class Projects extends Vue {
|
||||
|
||||
this.areProjectsFetching = false;
|
||||
} catch (error) {
|
||||
await this.$notify.error(`Unable to fetch owned projects. ${error.message}`);
|
||||
await this.$notify.error(`Unable to fetch owned projects. ${error.message}`, AnalyticsErrorEventSource.PROJECTS_LIST);
|
||||
}
|
||||
}
|
||||
|
||||
@ -110,7 +110,7 @@ export default class Projects extends Vue {
|
||||
try {
|
||||
await this.$store.dispatch(FETCH_OWNED, this.currentPageNumber);
|
||||
} catch (error) {
|
||||
await this.$notify.error(`Unable to fetch owned projects. ${error.message}`);
|
||||
await this.$notify.error(`Unable to fetch owned projects. ${error.message}`, AnalyticsErrorEventSource.PROJECTS_LIST);
|
||||
}
|
||||
}
|
||||
|
||||
@ -155,7 +155,7 @@ export default class Projects extends Vue {
|
||||
this.analytics.pageVisit(RouteConfig.EditProjectDetails.path);
|
||||
await this.$router.push(RouteConfig.EditProjectDetails.path);
|
||||
} catch (error) {
|
||||
await this.$notify.error(`Unable to select project. ${error.message}`);
|
||||
await this.$notify.error(`Unable to select project. ${error.message}`, AnalyticsErrorEventSource.PROJECTS_LIST);
|
||||
}
|
||||
|
||||
this.isLoading = false;
|
||||
|
@ -87,6 +87,7 @@ import { Project } from '@/types/projects';
|
||||
import { PM_ACTIONS } from '@/utils/constants/actionNames';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { APP_STATE_MUTATIONS } from '@/store/mutationConstants';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
import VInfo from '@/components/common/VInfo.vue';
|
||||
import VHeader from '@/components/common/VHeader.vue';
|
||||
@ -170,7 +171,7 @@ export default class HeaderArea extends Vue {
|
||||
await this.$store.dispatch(PM_ACTIONS.DELETE);
|
||||
await this.setProjectState();
|
||||
} catch (error) {
|
||||
await this.$notify.error(`Error while deleting users from projectMembers. ${error.message}`);
|
||||
await this.$notify.error(`Error while deleting users from projectMembers. ${error.message}`, AnalyticsErrorEventSource.PROJECT_MEMBERS_HEADER);
|
||||
this.isDeleteClicked = false;
|
||||
|
||||
return;
|
||||
@ -190,7 +191,7 @@ export default class HeaderArea extends Vue {
|
||||
try {
|
||||
await this.$store.dispatch(PM_ACTIONS.FETCH, this.FIRST_PAGE);
|
||||
} catch (error) {
|
||||
await this.$notify.error(`Unable to fetch project members. ${error.message}`);
|
||||
await this.$notify.error(`Unable to fetch project members. ${error.message}`, AnalyticsErrorEventSource.PROJECT_MEMBERS_HEADER);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -55,6 +55,7 @@ import {
|
||||
ProjectMemberOrderBy,
|
||||
} from '@/types/projectMembers';
|
||||
import { PM_ACTIONS } from '@/utils/constants/actionNames';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
import VLoader from '@/components/common/VLoader.vue';
|
||||
import HeaderArea from '@/components/team/HeaderArea.vue';
|
||||
@ -95,7 +96,7 @@ export default class ProjectMembersArea extends Vue {
|
||||
|
||||
this.areMembersFetching = false;
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.PROJECT_MEMBERS_PAGE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -169,7 +170,7 @@ export default class ProjectMembersArea extends Vue {
|
||||
try {
|
||||
await this.$store.dispatch(FETCH, index);
|
||||
} catch (error) {
|
||||
this.$notify.error(`Unable to fetch project members. ${error.message}`);
|
||||
this.$notify.error(`Unable to fetch project members. ${error.message}`, AnalyticsErrorEventSource.PROJECT_MEMBERS_PAGE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -184,7 +185,7 @@ export default class ProjectMembersArea extends Vue {
|
||||
try {
|
||||
await this.$store.dispatch(FETCH, this.FIRST_PAGE);
|
||||
} catch (error) {
|
||||
await this.$notify.error(`Unable to fetch project members. ${error.message}`);
|
||||
await this.$notify.error(`Unable to fetch project members. ${error.message}`, AnalyticsErrorEventSource.PROJECT_MEMBERS_PAGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import S3, { CommonPrefix } from 'aws-sdk/clients/s3';
|
||||
|
||||
import { StoreModule } from '@/types/store';
|
||||
import { APP_STATE_MUTATIONS } from '@/store/mutationConstants';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
const listCache = new Map();
|
||||
|
||||
@ -507,9 +508,9 @@ export const makeFilesModule = (): FilesModule => ({
|
||||
} catch (error) {
|
||||
const limitExceededError = 'storage limit exceeded';
|
||||
if (error.message.includes(limitExceededError)) {
|
||||
dispatch('error', `Error: ${limitExceededError}`, { root:true });
|
||||
dispatch('error', { message: `Error: ${limitExceededError}`, source: AnalyticsErrorEventSource.OBJECT_UPLOAD_ERROR }, { root: true });
|
||||
} else {
|
||||
dispatch('error', error.message, { root:true });
|
||||
dispatch('error', { message: error.message, source: AnalyticsErrorEventSource.OBJECT_UPLOAD_ERROR }, { root: true });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,9 +7,12 @@ import { DelayedNotification } from '@/types/DelayedNotification';
|
||||
import { NOTIFICATION_ACTIONS } from '@/utils/constants/actionNames';
|
||||
import { NOTIFICATION_TYPES } from '@/utils/constants/notification';
|
||||
import { StoreModule } from '@/types/store';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
export class NotificationsState {
|
||||
public notificationQueue: DelayedNotification[] = [];
|
||||
public analytics: AnalyticsHttpApi = new AnalyticsHttpApi();
|
||||
}
|
||||
|
||||
interface NotificationsContext {
|
||||
@ -17,6 +20,11 @@ interface NotificationsContext {
|
||||
commit: (string, ...unknown) => void
|
||||
}
|
||||
|
||||
interface ErrorPayload {
|
||||
message: string,
|
||||
source: AnalyticsErrorEventSource | null,
|
||||
}
|
||||
|
||||
export function makeNotificationsModule(): StoreModule<NotificationsState, NotificationsContext> {
|
||||
return {
|
||||
state: new NotificationsState(),
|
||||
@ -66,7 +74,6 @@ export function makeNotificationsModule(): StoreModule<NotificationsState, Notif
|
||||
},
|
||||
// Commits mutation for adding info notification
|
||||
[NOTIFICATION_ACTIONS.NOTIFY]: function ({ commit }: NotificationsContext, message: string): void {
|
||||
|
||||
const notification = new DelayedNotification(
|
||||
() => commit(NOTIFICATION_MUTATIONS.DELETE, notification.id),
|
||||
NOTIFICATION_TYPES.NOTIFICATION,
|
||||
@ -76,11 +83,15 @@ export function makeNotificationsModule(): StoreModule<NotificationsState, Notif
|
||||
commit(NOTIFICATION_MUTATIONS.ADD, notification);
|
||||
},
|
||||
// Commits mutation for adding error notification
|
||||
[NOTIFICATION_ACTIONS.ERROR]: function ({ commit }: NotificationsContext, message: string): void {
|
||||
[NOTIFICATION_ACTIONS.ERROR]: function ({ commit, state }: NotificationsContext, payload: ErrorPayload): void {
|
||||
if (payload.source) {
|
||||
state.analytics.errorEventTriggered(payload.source);
|
||||
}
|
||||
|
||||
const notification = new DelayedNotification(
|
||||
() => commit(NOTIFICATION_MUTATIONS.DELETE, notification.id),
|
||||
NOTIFICATION_TYPES.ERROR,
|
||||
message,
|
||||
payload.message,
|
||||
);
|
||||
|
||||
commit(NOTIFICATION_MUTATIONS.ADD, notification);
|
||||
|
@ -7,6 +7,7 @@ import { setContext } from '@apollo/client/link/context';
|
||||
import { onError } from '@apollo/client/link/error';
|
||||
|
||||
import { AuthHttpApi } from '@/api/auth';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
/**
|
||||
* Satellite url.
|
||||
@ -32,19 +33,19 @@ const authLink = setContext((_, { headers }) => {
|
||||
*/
|
||||
const errorLink = onError(({ graphQLErrors, networkError }) => {
|
||||
if (graphQLErrors?.length) {
|
||||
Vue.prototype.$notify.error(graphQLErrors.join('\n'));
|
||||
Vue.prototype.$notify.error(graphQLErrors.join('\n'), AnalyticsErrorEventSource.OVERALL_GRAPHQL_ERROR);
|
||||
}
|
||||
|
||||
if (networkError) {
|
||||
const nError = (networkError as ServerError);
|
||||
if (nError.statusCode === 401) {
|
||||
new AuthHttpApi().logout();
|
||||
Vue.prototype.$notify.error('Session token expired');
|
||||
Vue.prototype.$notify.error('Session token expired', AnalyticsErrorEventSource.OVERALL_SESSION_EXPIRED_ERROR);
|
||||
setTimeout(() => {
|
||||
window.location.href = window.location.origin + '/login';
|
||||
}, 3000);
|
||||
} else {
|
||||
nError.result && Vue.prototype.$notify.error(nError.result.error);
|
||||
nError.result && Vue.prototype.$notify.error(nError.result.error, AnalyticsErrorEventSource.OVERALL_GRAPHQL_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2019 Storj Labs, Inc.
|
||||
// Copyright (C) 2022 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
// Make sure these event names match up with the client-side event names in satellite/analytics/service.go
|
||||
@ -53,5 +53,67 @@ export enum AnalyticsEvent {
|
||||
STORJ_TOKEN_ADDED_FROM_BILLING = 'Storj Token Added From Billing',
|
||||
ADD_FUNDS_CLICKED = 'Add Funds Clicked',
|
||||
PROJECT_MEMBERS_INVITE_SENT = 'Project Members Invite Sent',
|
||||
|
||||
UI_ERROR = 'UI error occurred',
|
||||
}
|
||||
|
||||
export enum AnalyticsErrorEventSource {
|
||||
ACCESS_GRANTS_PAGE = 'Access grants page',
|
||||
ACCOUNT_SETTINGS_AREA = 'Account settings area',
|
||||
BILLING_HISTORY_TAB = 'Billing history tab',
|
||||
BILLING_COUPONS_TAB = 'Billing coupons tab',
|
||||
BILLING_OVERVIEW_TAB = 'Billing overview tab',
|
||||
BILLING_PAYMENT_METHODS_TAB = 'Billing payment methods tab',
|
||||
BILLING_PAYMENT_METHODS = 'Billing payment methods',
|
||||
BILLING_COUPON_AREA = 'Billing coupon area',
|
||||
BILLING_APPLY_COUPON_CODE_INPUT = 'Billing apply coupon code input',
|
||||
BILLING_PAYMENTS_HISTORY = 'Billing payments history',
|
||||
BILLING_PERIODS_SELECTION = 'Billing periods selection',
|
||||
BILLING_ESTIMATED_COSTS_AND_CREDITS = 'Billing estimated costs and credits',
|
||||
BILLING_ADD_STRIPE_CC_FORM = 'Billing add stripe CC form',
|
||||
BILLING_STRIPE_CARD_INPUT = 'Billing stripe card input',
|
||||
BILLING_AREA = 'Billing area',
|
||||
BILLING_STORJ_TOKEN_CONTAINER = 'Billing STORJ token container',
|
||||
BILLING_CC_DIALOG = 'Billing credit card dialog',
|
||||
CREATE_AG_MODAL = 'Create access grant modal',
|
||||
CONFIRM_DELETE_AG_MODAL = 'Confirm delete access grant modal',
|
||||
CREATE_AG_FORM = 'Create access grant form',
|
||||
FILE_BROWSER = 'File browser',
|
||||
FILE_BROWSER_ENTRY = 'File browser entry',
|
||||
PROJECT_INFO_BAR = 'Project info bar',
|
||||
CREATE_PROJECT_LEVEL_PASSPHRASE_MODAL = 'Create project level passphrase modal',
|
||||
SWITCH_PROJECT_LEVEL_PASSPHRASE_MODAL = 'Switch project level passphrase modal',
|
||||
UPGRADE_ACCOUNT_MODAL = 'Upgrade account modal',
|
||||
ADD_PROJECT_MEMBER_MODAL = 'Add project member modal',
|
||||
ADD_TOKEN_FUNDS_MODAL = 'Add token funds modal',
|
||||
CHANGE_PASSWORD_MODAL = 'Change password modal',
|
||||
CREATE_PROJECT_MODAL = 'Create project modal',
|
||||
DELETE_BUCKET_MODAL = 'Delete bucket modal',
|
||||
ENABLE_MFA_MODAL = 'Enable MFA modal',
|
||||
DISABLE_MFA_MODAL = 'Disable MFA modal',
|
||||
EDIT_PROFILE_MODAL = 'Edit profile modal',
|
||||
CREATE_FOLDER_MODAL = 'Create folder modal',
|
||||
OBJECT_DETAILS_MODAL = 'Object details modal',
|
||||
OPEN_BUCKET_MODAL = 'Open bucket modal',
|
||||
SHARE_BUCKET_MODAL = 'Share bucket modal',
|
||||
NAVIGATION_ACCOUNT_AREA = 'Navigation account area',
|
||||
NAVIGATION_PROJECT_SELECTION = 'Navigation project selection',
|
||||
MOBILE_NAVIGATION = 'Mobile navigation',
|
||||
BUCKET_CREATION_FLOW = 'Bucket creation flow',
|
||||
BUCKET_CREATION_PASSPHRASE_STEP = 'Bucket creation passphrase step',
|
||||
BUCKET_CREATION_NAME_STEP = 'Bucket creation name step',
|
||||
BUCKET_TABLE = 'Bucket table',
|
||||
BUCKET_PAGE = 'Bucket page',
|
||||
UPLOAD_FILE_VIEW = 'Upload file view',
|
||||
OBJECT_UPLOAD_ERROR = 'Object upload error',
|
||||
ONBOARDING_NAME_STEP = 'Onboarding name step',
|
||||
ONBOARDING_PERMISSIONS_STEP = 'Onboarding permissions step',
|
||||
PROJECT_DASHBOARD_PAGE = 'Project dashboard page',
|
||||
PROJECT_USAGE_CONTAINER = 'Project usage container',
|
||||
EDIT_PROJECT_DETAILS = 'Edit project details',
|
||||
PROJECTS_LIST = 'Projects list',
|
||||
PROJECT_MEMBERS_HEADER = 'Project members page header',
|
||||
PROJECT_MEMBERS_PAGE = 'Project members page',
|
||||
OVERALL_APP_WRAPPER_ERROR = 'Overall app wrapper error',
|
||||
OVERALL_GRAPHQL_ERROR = 'Overall graphQL error',
|
||||
OVERALL_SESSION_EXPIRED_ERROR = 'Overall session expired error',
|
||||
}
|
||||
|
@ -1,13 +0,0 @@
|
||||
// Copyright (C) 2020 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
export enum AddingPaymentState {
|
||||
ADD_CARD = 1,
|
||||
ADD_STORJ,
|
||||
}
|
||||
|
||||
export enum AddingStorjState {
|
||||
DEFAULT = 1,
|
||||
VERIFYING,
|
||||
VERIFIED,
|
||||
}
|
@ -2,9 +2,10 @@
|
||||
// See LICENSE for copying information.
|
||||
|
||||
import { NOTIFICATION_ACTIONS } from '@/utils/constants/actionNames';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
interface Dispatcher {
|
||||
dispatch(key:string, message:string)
|
||||
dispatch(key: string, payload: string | object)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -17,8 +18,8 @@ export class Notificator {
|
||||
await this.store.dispatch(NOTIFICATION_ACTIONS.SUCCESS, message);
|
||||
}
|
||||
|
||||
public async error(message: string): Promise<void> {
|
||||
await this.store.dispatch(NOTIFICATION_ACTIONS.ERROR, message);
|
||||
public async error(message: string, source: AnalyticsErrorEventSource | null): Promise<void> {
|
||||
await this.store.dispatch(NOTIFICATION_ACTIONS.ERROR, { message, source });
|
||||
}
|
||||
|
||||
public async notify(message: string): Promise<void> {
|
||||
|
@ -118,7 +118,7 @@ export default class ActivateAccount extends Vue {
|
||||
await this.auth.resendEmail(this.email);
|
||||
this.isResendSuccessShown = true;
|
||||
} catch (error) {
|
||||
this.$notify.error(error.message);
|
||||
this.$notify.error(error.message, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -163,7 +163,7 @@ export default class Authorize extends Vue {
|
||||
} catch (error) {
|
||||
if (!(error instanceof ErrorUnauthorized)) {
|
||||
await this.$store.dispatch(APP_STATE_ACTIONS.CHANGE_STATE, AppState.ERROR);
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, null);
|
||||
}
|
||||
|
||||
const query = new URLSearchParams(this.oauthData).toString();
|
||||
@ -180,12 +180,12 @@ export default class Authorize extends Vue {
|
||||
await this.$store.dispatch(ACCESS_GRANTS_ACTIONS.STOP_ACCESS_GRANTS_WEB_WORKER);
|
||||
await this.$store.dispatch(ACCESS_GRANTS_ACTIONS.SET_ACCESS_GRANTS_WEB_WORKER);
|
||||
} catch (error) {
|
||||
await this.$notify.error(`Unable to set access grants wizard. ${error.message}`);
|
||||
await this.$notify.error(`Unable to set access grants wizard. ${error.message}`, null);
|
||||
return;
|
||||
}
|
||||
|
||||
this.worker = this.$store.state.accessGrantsModule.accessGrantsWebWorker;
|
||||
this.worker.onerror = (error: ErrorEvent) => this.$notify.error(error.message);
|
||||
this.worker.onerror = (error: ErrorEvent) => this.$notify.error(error.message, null);
|
||||
}
|
||||
|
||||
private async verifyClientConfiguration(): Promise<void> {
|
||||
@ -310,7 +310,7 @@ export default class Authorize extends Vue {
|
||||
const event: MessageEvent = await new Promise(resolve => this.worker.onmessage = resolve);
|
||||
|
||||
if (event.data.error) {
|
||||
await this.$notify.error(event.data.error);
|
||||
await this.$notify.error(event.data.error, null);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -89,6 +89,7 @@ import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import eventBus from '@/utils/eventBus';
|
||||
import { ABTestValues } from '@/types/abtesting';
|
||||
import { AB_TESTING_ACTIONS } from '@/store/modules/abTesting';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
import ProjectInfoBar from '@/components/infoBars/ProjectInfoBar.vue';
|
||||
import BillingNotification from '@/components/notifications/BillingNotification.vue';
|
||||
@ -241,7 +242,7 @@ export default class DashboardArea extends Vue {
|
||||
|
||||
if (!(error instanceof ErrorUnauthorized)) {
|
||||
await this.$store.dispatch(APP_STATE_ACTIONS.CHANGE_STATE, AppState.ERROR);
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.OVERALL_APP_WRAPPER_ERROR);
|
||||
}
|
||||
|
||||
setTimeout(async () => await this.$router.push(RouteConfig.Login.path), 1000);
|
||||
@ -253,26 +254,26 @@ export default class DashboardArea extends Vue {
|
||||
await this.$store.dispatch(ACCESS_GRANTS_ACTIONS.STOP_ACCESS_GRANTS_WEB_WORKER);
|
||||
await this.$store.dispatch(ACCESS_GRANTS_ACTIONS.SET_ACCESS_GRANTS_WEB_WORKER);
|
||||
} catch (error) {
|
||||
await this.$notify.error(`Unable to set access grants wizard. ${error.message}`);
|
||||
await this.$notify.error(`Unable to set access grants wizard. ${error.message}`, AnalyticsErrorEventSource.OVERALL_APP_WRAPPER_ERROR);
|
||||
}
|
||||
|
||||
try {
|
||||
const couponType = await this.$store.dispatch(SETUP_ACCOUNT);
|
||||
if (couponType === CouponType.NoCoupon) {
|
||||
await this.$notify.error(`The coupon code was invalid, and could not be applied to your account`);
|
||||
await this.$notify.error(`The coupon code was invalid, and could not be applied to your account`, AnalyticsErrorEventSource.OVERALL_APP_WRAPPER_ERROR);
|
||||
}
|
||||
|
||||
if (couponType === CouponType.SignupCoupon) {
|
||||
await this.$notify.success(`The coupon code was added successfully`);
|
||||
}
|
||||
} catch (error) {
|
||||
await this.$notify.error(`Unable to setup account. ${error.message}`);
|
||||
await this.$notify.error(`Unable to setup account. ${error.message}`, AnalyticsErrorEventSource.OVERALL_APP_WRAPPER_ERROR);
|
||||
}
|
||||
|
||||
try {
|
||||
await this.$store.dispatch(GET_CREDIT_CARDS);
|
||||
} catch (error) {
|
||||
await this.$notify.error(`Unable to get credit cards. ${error.message}`);
|
||||
await this.$notify.error(`Unable to get credit cards. ${error.message}`, AnalyticsErrorEventSource.OVERALL_APP_WRAPPER_ERROR);
|
||||
}
|
||||
|
||||
let projects: Project[] = [];
|
||||
@ -292,6 +293,7 @@ export default class DashboardArea extends Vue {
|
||||
|
||||
await this.$store.dispatch(APP_STATE_ACTIONS.CHANGE_STATE, AppState.LOADED);
|
||||
} catch (error) {
|
||||
this.$notify.error(error.message, AnalyticsErrorEventSource.OVERALL_APP_WRAPPER_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -333,7 +335,7 @@ export default class DashboardArea extends Vue {
|
||||
await this.$store.dispatch(USER_ACTIONS.GENERATE_USER_MFA_RECOVERY_CODES);
|
||||
this.toggleMFARecoveryModal();
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.OVERALL_APP_WRAPPER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
@ -468,7 +470,7 @@ export default class DashboardArea extends Vue {
|
||||
try {
|
||||
LocalData.setSessionExpirationDate(await this.auth.refreshSession());
|
||||
} catch (error) {
|
||||
await this.$notify.error((error instanceof ErrorUnauthorized) ? 'Your session was timed out.' : error.message);
|
||||
await this.$notify.error((error instanceof ErrorUnauthorized) ? 'Your session was timed out.' : error.message, AnalyticsErrorEventSource.OVERALL_SESSION_EXPIRED_ERROR);
|
||||
await this.handleInactive();
|
||||
this.isSessionRefreshing = false;
|
||||
return;
|
||||
@ -499,7 +501,7 @@ export default class DashboardArea extends Vue {
|
||||
} catch (error) {
|
||||
if (error instanceof ErrorUnauthorized) return;
|
||||
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, AnalyticsErrorEventSource.OVERALL_SESSION_EXPIRED_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -204,7 +204,7 @@ export default class ForgotPassword extends Vue {
|
||||
*/
|
||||
public onCaptchaError(): void {
|
||||
this.captchaResponseToken = '';
|
||||
this.$notify.error('The captcha encountered an error. Please try again.');
|
||||
this.$notify.error('The captcha encountered an error. Please try again.', null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -226,7 +226,7 @@ export default class ForgotPassword extends Vue {
|
||||
await this.auth.forgotPassword(this.email, this.captchaResponseToken);
|
||||
await this.$notify.success('Please look for instructions in your email');
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, null);
|
||||
}
|
||||
|
||||
this.$refs.captcha?.reset();
|
||||
|
@ -437,7 +437,7 @@ export default class Login extends Vue {
|
||||
|
||||
if (this.isMFARequired) {
|
||||
if (error instanceof ErrorBadRequest || error instanceof ErrorUnauthorized) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, null);
|
||||
}
|
||||
|
||||
this.isMFAError = true;
|
||||
@ -451,7 +451,7 @@ export default class Login extends Vue {
|
||||
return;
|
||||
}
|
||||
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, null);
|
||||
this.isLoading = false;
|
||||
return;
|
||||
}
|
||||
|
@ -201,7 +201,7 @@ export default class ResetPassword extends Vue {
|
||||
return;
|
||||
}
|
||||
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, null);
|
||||
}
|
||||
|
||||
this.isLoading = false;
|
||||
|
@ -414,7 +414,7 @@ export default class RegisterArea extends Vue {
|
||||
const config = require('@/views/registration/registrationViewConfig.json');
|
||||
this.viewConfig = this.user.partner && config[this.user.partner] ? config[this.user.partner] : config['default'];
|
||||
} catch (e) {
|
||||
this.$notify.error('No configuration file for registration page.');
|
||||
this.$notify.error('No configuration file for registration page.', null);
|
||||
}
|
||||
}
|
||||
|
||||
@ -595,7 +595,7 @@ export default class RegisterArea extends Vue {
|
||||
*/
|
||||
public onCaptchaError(): void {
|
||||
this.captchaResponseToken = '';
|
||||
this.$notify.error('The captcha encountered an error. Please try again.');
|
||||
this.$notify.error('The captcha encountered an error. Please try again.', null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -704,12 +704,12 @@ export default class RegisterArea extends Vue {
|
||||
}
|
||||
|
||||
if (this.user.partner.length > 100) {
|
||||
this.$notify.error('Partner must be less than or equal to 100 characters');
|
||||
this.$notify.error('Partner must be less than or equal to 100 characters', null);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.user.signupPromoCode.length > 100) {
|
||||
this.$notify.error('Promo code must be less than or equal to 100 characters');
|
||||
this.$notify.error('Promo code must be less than or equal to 100 characters', null);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -776,7 +776,7 @@ export default class RegisterArea extends Vue {
|
||||
|
||||
await this.detectBraveBrowser() ? await this.$router.push(braveSuccessPath) : window.location.href = nonBraveSuccessPath;
|
||||
} catch (error) {
|
||||
await this.$notify.error(error.message);
|
||||
await this.$notify.error(error.message, null);
|
||||
}
|
||||
|
||||
this.$refs.captcha?.reset();
|
||||
|
@ -27,6 +27,7 @@ import { AppState } from '@/utils/constants/appStateEnum';
|
||||
import { NotificatorPlugin } from '@/utils/plugins/notificator';
|
||||
import { makeABTestingModule } from '@/store/modules/abTesting';
|
||||
import DashboardArea from '@/views/DashboardArea.vue';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
|
||||
const localVue = createLocalVue();
|
||||
localVue.use(Vuex);
|
||||
@ -65,6 +66,7 @@ localVue.use(new NotificatorPlugin(store));
|
||||
describe('Dashboard', () => {
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
jest.spyOn(AnalyticsHttpApi.prototype, 'errorEventTriggered').mockImplementation(() => Promise.resolve());
|
||||
});
|
||||
|
||||
it('renders correctly when data is loading', () => {
|
||||
|
Loading…
Reference in New Issue
Block a user