diff --git a/apps/web/src/locales/en/messages.json b/apps/web/src/locales/en/messages.json index 829a3e2230c..2773efc17f7 100644 --- a/apps/web/src/locales/en/messages.json +++ b/apps/web/src/locales/en/messages.json @@ -6602,5 +6602,8 @@ "example": "14" } } + }, + "dismiss": { + "message": "Dismiss" } } diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/overview/onboarding.component.html b/bitwarden_license/bit-web/src/app/secrets-manager/overview/onboarding.component.html index 5aa57b087dc..5c25b4cae71 100644 --- a/bitwarden_license/bit-web/src/app/secrets-manager/overview/onboarding.component.html +++ b/bitwarden_license/bit-web/src/app/secrets-manager/overview/onboarding.component.html @@ -1,10 +1,4 @@ -
+
@@ -29,9 +23,9 @@ type="button" class="tw-ml-auto tw-block" [ngClass]="{ 'tw-invisible': !isComplete }" - (click)="dismiss()" + (click)="dismiss.emit()" > - Dismiss + {{ "dismiss" | i18n }}
diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/overview/onboarding.component.ts b/bitwarden_license/bit-web/src/app/secrets-manager/overview/onboarding.component.ts index 06e5761b3d0..3fb4bcb32e5 100644 --- a/bitwarden_license/bit-web/src/app/secrets-manager/overview/onboarding.component.ts +++ b/bitwarden_license/bit-web/src/app/secrets-manager/overview/onboarding.component.ts @@ -1,4 +1,4 @@ -import { AfterContentInit, Component, ContentChildren, Input, QueryList } from "@angular/core"; +import { Component, ContentChildren, EventEmitter, Input, Output, QueryList } from "@angular/core"; import { OnboardingTaskComponent } from "./onboarding-task.component"; @@ -6,17 +6,15 @@ import { OnboardingTaskComponent } from "./onboarding-task.component"; selector: "sm-onboarding", templateUrl: "./onboarding.component.html", }) -export class OnboardingComponent implements AfterContentInit { +export class OnboardingComponent { @ContentChildren(OnboardingTaskComponent) tasks: QueryList; @Input() title: string; + @Output() dismiss = new EventEmitter(); + protected open = true; protected visible = false; - ngAfterContentInit() { - this.visible = !this.isComplete; - } - protected get amountCompleted(): number { return this.tasks.filter((task) => task.completed).length; } @@ -32,8 +30,4 @@ export class OnboardingComponent implements AfterContentInit { protected toggle() { this.open = !this.open; } - - protected dismiss() { - this.visible = false; - } } diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/overview/overview.component.html b/bitwarden_license/bit-web/src/app/secrets-manager/overview/overview.component.html index e5106b10c5c..a53ede221c0 100644 --- a/bitwarden_license/bit-web/src/app/secrets-manager/overview/overview.component.html +++ b/bitwarden_license/bit-web/src/app/secrets-manager/overview/overview.component.html @@ -3,7 +3,7 @@
- + = new Subject(); - private prevShouldReuseRoute: any; private tableSize = 10; private organizationId: string; protected organizationName: string; protected userIsAdmin: boolean; + protected showOnboarding = false; protected view$: Observable<{ allProjects: ProjectListView[]; @@ -72,7 +73,6 @@ export class OverviewComponent implements OnInit, OnDestroy { constructor( private route: ActivatedRoute, - private router: Router, private projectService: ProjectService, private secretService: SecretService, private serviceAccountService: ServiceAccountService, @@ -80,19 +80,12 @@ export class OverviewComponent implements OnInit, OnDestroy { private organizationService: OrganizationService, private platformUtilsService: PlatformUtilsService, private i18nService: I18nService - ) { - /** - * We want to remount the `sm-onboarding` component on route change. - * The component only toggles its visibility on init and on user dismissal. - */ - this.prevShouldReuseRoute = this.router.routeReuseStrategy.shouldReuseRoute; - this.router.routeReuseStrategy.shouldReuseRoute = () => false; - } + ) {} ngOnInit() { const orgId$ = this.route.params.pipe( map((p) => p.organizationId), - distinct() + distinctUntilChanged() ); orgId$ @@ -136,10 +129,19 @@ export class OverviewComponent implements OnInit, OnDestroy { }; }) ); + + // Refresh onboarding status when orgId changes by fetching the first value from view$. + orgId$ + .pipe( + switchMap(() => this.view$.pipe(take(1))), + takeUntil(this.destroy$) + ) + .subscribe((view) => { + this.showOnboarding = Object.values(view.tasks).includes(false); + }); } ngOnDestroy(): void { - this.router.routeReuseStrategy.shouldReuseRoute = this.prevShouldReuseRoute; this.destroy$.next(); this.destroy$.complete(); } @@ -245,4 +247,8 @@ export class OverviewComponent implements OnInit, OnDestroy { this.i18nService.t("valueCopied", this.i18nService.t("value")) ); } + + protected hideOnboarding() { + this.showOnboarding = false; + } } diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/sm-routing.module.ts b/bitwarden_license/bit-web/src/app/secrets-manager/sm-routing.module.ts index 21f8acb3d90..961c910ea59 100644 --- a/bitwarden_license/bit-web/src/app/secrets-manager/sm-routing.module.ts +++ b/bitwarden_license/bit-web/src/app/secrets-manager/sm-routing.module.ts @@ -1,6 +1,7 @@ import { NgModule } from "@angular/core"; import { RouterModule, Routes } from "@angular/router"; +import { AuthGuard } from "@bitwarden/angular/auth/guards/auth.guard"; import { Organization } from "@bitwarden/common/models/domain/organization"; import { OrganizationPermissionsGuard } from "@bitwarden/web-vault/app/organizations/guards/org-permissions.guard"; import { buildFlaggedRoute } from "@bitwarden/web-vault/app/oss-routing.module"; @@ -19,7 +20,7 @@ const routes: Routes = [ buildFlaggedRoute("secretsManager", { path: ":organizationId", component: LayoutComponent, - canActivate: [OrganizationPermissionsGuard, SMGuard], + canActivate: [AuthGuard, OrganizationPermissionsGuard, SMGuard], data: { organizationPermissions: (org: Organization) => org.canAccessSecretsManager, },