have the user accept an invitation (to avoid previews from stealing it)
This commit is contained in:
@@ -545,7 +545,6 @@ export default class HomeView extends Vue {
|
||||
});
|
||||
|
||||
await this.loadNewStarredProjectChanges();
|
||||
await this.checkOnboarding();
|
||||
|
||||
logger.debug("[HomeView] mounted() - component lifecycle completed", {
|
||||
timestamp: new Date().toISOString(),
|
||||
@@ -594,21 +593,6 @@ export default class HomeView extends Vue {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Watch for changes in the current activeDid
|
||||
* Reload settings when user switches identities
|
||||
*/
|
||||
async onActiveDidChanged(newDid: string | null, oldDid: string | null) {
|
||||
if (newDid !== oldDid) {
|
||||
// Re-initialize identity with new settings (loads settings internally)
|
||||
await this.initializeIdentity();
|
||||
} else {
|
||||
logger.debug(
|
||||
"[HomeView Settings Trace] 📍 DID unchanged, skipping re-initialization",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes user identity
|
||||
* - Retrieves existing DIDs
|
||||
@@ -713,13 +697,6 @@ export default class HomeView extends Vue {
|
||||
);
|
||||
this.isAnyFeedFilterOn = checkIsAnyFeedFilterOn(settings);
|
||||
|
||||
// Check onboarding status
|
||||
if (!settings.finishedOnboarding) {
|
||||
(this.$refs.onboardingDialog as OnboardingDialog).open(
|
||||
OnboardPage.Home,
|
||||
);
|
||||
}
|
||||
|
||||
// Check registration status if needed
|
||||
if (!this.isRegistered && this.activeDid) {
|
||||
try {
|
||||
@@ -762,6 +739,12 @@ export default class HomeView extends Vue {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (!settings.finishedOnboarding) {
|
||||
(this.$refs.onboardingDialog as OnboardingDialog).open(
|
||||
OnboardPage.Home,
|
||||
);
|
||||
}
|
||||
} catch (err: unknown) {
|
||||
logger.error("[HomeView Settings Trace] ❌ initializeIdentity() failed", {
|
||||
error: err instanceof Error ? err.message : String(err),
|
||||
@@ -963,20 +946,6 @@ export default class HomeView extends Vue {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if user needs onboarding using ultra-concise mixin utilities
|
||||
* Opens onboarding dialog if not completed
|
||||
*
|
||||
* @internal
|
||||
* Called by mounted()
|
||||
*/
|
||||
private async checkOnboarding() {
|
||||
const settings = await this.$accountSettings();
|
||||
if (!settings.finishedOnboarding) {
|
||||
(this.$refs.onboardingDialog as OnboardingDialog).open(OnboardPage.Home);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles errors during initialization
|
||||
* - Logs error to console and database
|
||||
|
||||
@@ -1,12 +1,39 @@
|
||||
<template>
|
||||
<QuickNav selected="Invite" />
|
||||
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
|
||||
<!-- Confirmation Dialog -->
|
||||
<div v-if="showConfirmation" class="text-center mt-8">
|
||||
<div class="bg-white rounded-lg shadow-lg p-6 max-w-md mx-auto">
|
||||
<h2 class="text-xl font-semibold mb-4">Accept Invitation</h2>
|
||||
<p class="mb-6 text-gray-700">
|
||||
You've received an invitation to connect. Would you like to accept it?
|
||||
</p>
|
||||
<div class="flex justify-center gap-4">
|
||||
<button
|
||||
class="px-6 py-2 bg-blue-500 text-white rounded hover:bg-blue-600 transition"
|
||||
@click="confirmInvite"
|
||||
>
|
||||
Accept
|
||||
</button>
|
||||
<button
|
||||
class="px-6 py-2 bg-gray-300 text-gray-700 rounded hover:bg-gray-400 transition"
|
||||
@click="cancelInvite"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Processing Spinner -->
|
||||
<div
|
||||
v-if="checkingInvite"
|
||||
v-else-if="checkingInvite"
|
||||
class="text-lg text-center font-light relative px-7"
|
||||
>
|
||||
<font-awesome icon="spinner" class="fa-spin-pulse" />
|
||||
</div>
|
||||
|
||||
<!-- Error/Manual Entry -->
|
||||
<div v-else class="text-center mt-4">
|
||||
<p>That invitation did not work.</p>
|
||||
<p class="mt-2">
|
||||
@@ -48,6 +75,7 @@ import { errorStringForLog } from "../libs/endorserServer";
|
||||
import { generateSaveAndActivateIdentity } from "../libs/util";
|
||||
import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin";
|
||||
import { createNotifyHelpers } from "@/utils/notify";
|
||||
import { logger } from "@/utils/logger";
|
||||
import {
|
||||
NOTIFY_INVITE_MISSING,
|
||||
NOTIFY_INVITE_PROCESSING_ERROR,
|
||||
@@ -101,6 +129,10 @@ export default class InviteOneAcceptView extends Vue {
|
||||
checkingInvite = true;
|
||||
/** User input for manual JWT entry */
|
||||
inputJwt = "";
|
||||
/** Show confirmation dialog */
|
||||
showConfirmation = false;
|
||||
/** JWT pending user confirmation */
|
||||
pendingJwtParameter = "";
|
||||
|
||||
/**
|
||||
* Component lifecycle hook that initializes invite processing
|
||||
@@ -110,7 +142,7 @@ export default class InviteOneAcceptView extends Vue {
|
||||
* 2. Retrieves account settings
|
||||
* 3. Ensures active DID exists or generates one
|
||||
* 4. Extracts JWT from URL path
|
||||
* 5. Processes invite automatically
|
||||
* 5. Shows confirmation dialog to user
|
||||
*
|
||||
* @throws Will not throw but logs errors
|
||||
* @emits Notifications on errors
|
||||
@@ -141,11 +173,33 @@ export default class InviteOneAcceptView extends Vue {
|
||||
(this.$route.params.jwt as string) ||
|
||||
(this.$route.query.jwt as string) ||
|
||||
"";
|
||||
await this.processInvite(jwt, false);
|
||||
|
||||
// Show confirmation dialog if JWT is present
|
||||
if (jwt) {
|
||||
this.pendingJwtParameter = jwt;
|
||||
this.showConfirmation = true;
|
||||
}
|
||||
this.checkingInvite = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirms and processes the pending invite
|
||||
*/
|
||||
async confirmInvite() {
|
||||
this.showConfirmation = false;
|
||||
await this.processInvite(this.pendingJwtParameter, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels the pending invite
|
||||
*/
|
||||
cancelInvite() {
|
||||
this.showConfirmation = false;
|
||||
this.pendingJwtParameter = "";
|
||||
this.checkingInvite = false;
|
||||
// Show error state (manual entry interface)
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes an invite JWT and/or text containing the invite
|
||||
*
|
||||
@@ -191,6 +245,7 @@ export default class InviteOneAcceptView extends Vue {
|
||||
|
||||
if (!jwt) {
|
||||
this.handleMissingJwt(notifyOnFailure);
|
||||
this.checkingInvite = false;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,8 +17,10 @@
|
||||
* - Custom notes
|
||||
* 3. Verifies the invite appears in the list
|
||||
* 4. Creates a new user with Ethr DID
|
||||
* 5. Accepts the invitation as the new user
|
||||
* 6. Verifies the connection is established
|
||||
* 5. Navigates to the invitation link
|
||||
* 6. Confirms the invitation in the acceptance dialog
|
||||
* 7. Accepts the invitation as the new user
|
||||
* 8. Verifies the connection is established
|
||||
*
|
||||
* Related Files:
|
||||
* - Frontend invite handling: src/libs/endorserServer.ts
|
||||
@@ -55,6 +57,10 @@ test('Check User 0 can invite someone', async ({ page }) => {
|
||||
await switchToUser(page, newDid);
|
||||
await page.goto(inviteLink as string);
|
||||
|
||||
// Wait for and click the Accept button in the confirmation dialog
|
||||
await expect(page.locator('button:has-text("Accept")')).toBeVisible();
|
||||
await page.locator('button:has-text("Accept")').click();
|
||||
|
||||
// Wait for the ContactNameDialog to appear before trying to fill the Name field
|
||||
await expect(page.getByPlaceholder('Name', { exact: true })).toBeVisible();
|
||||
await page.getByPlaceholder('Name', { exact: true }).fill(`My pal User #0`);
|
||||
|
||||
@@ -13,6 +13,8 @@ test('New offers for another user', async ({ page }) => {
|
||||
}
|
||||
|
||||
await page.getByTestId('closeOnboardingAndFinish').click();
|
||||
// Wait for onboarding dialog to fully close and settings to persist
|
||||
await expect(page.locator('.dialog-overlay')).toBeHidden({ timeout: 5000 });
|
||||
await expect(page.getByTestId('newDirectOffersActivityNumber')).toBeHidden();
|
||||
|
||||
// Become User Zero
|
||||
|
||||
Reference in New Issue
Block a user