mirror of
https://github.com/bitwarden/browser.git
synced 2025-01-04 18:37:45 +01:00
[SM-589][SM-592] Remove router reuse hack (#4913)
* Remove router reuse hack * Add AuthGuard * Change to distinctUntilChanged * Extract show logic
This commit is contained in:
parent
2b95c786d8
commit
7736a981e7
@ -6602,5 +6602,8 @@
|
|||||||
"example": "14"
|
"example": "14"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"dismiss": {
|
||||||
|
"message": "Dismiss"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,4 @@
|
|||||||
<details
|
<details #details class="tw-rounded-sm tw-bg-background-alt tw-text-main" (toggle)="toggle()" open>
|
||||||
*ngIf="visible"
|
|
||||||
#details
|
|
||||||
class="tw-rounded-sm tw-bg-background-alt tw-text-main"
|
|
||||||
(toggle)="toggle()"
|
|
||||||
open
|
|
||||||
>
|
|
||||||
<summary class="tw-list-none tw-p-2 tw-px-4">
|
<summary class="tw-list-none tw-p-2 tw-px-4">
|
||||||
<div class="tw-flex tw-select-none tw-items-center tw-gap-4">
|
<div class="tw-flex tw-select-none tw-items-center tw-gap-4">
|
||||||
<i class="bwi bwi-dashboard tw-text-3xl tw-text-primary-500" aria-hidden="true"></i>
|
<i class="bwi bwi-dashboard tw-text-3xl tw-text-primary-500" aria-hidden="true"></i>
|
||||||
@ -29,9 +23,9 @@
|
|||||||
type="button"
|
type="button"
|
||||||
class="tw-ml-auto tw-block"
|
class="tw-ml-auto tw-block"
|
||||||
[ngClass]="{ 'tw-invisible': !isComplete }"
|
[ngClass]="{ 'tw-invisible': !isComplete }"
|
||||||
(click)="dismiss()"
|
(click)="dismiss.emit()"
|
||||||
>
|
>
|
||||||
Dismiss
|
{{ "dismiss" | i18n }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</details>
|
</details>
|
||||||
|
@ -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";
|
import { OnboardingTaskComponent } from "./onboarding-task.component";
|
||||||
|
|
||||||
@ -6,17 +6,15 @@ import { OnboardingTaskComponent } from "./onboarding-task.component";
|
|||||||
selector: "sm-onboarding",
|
selector: "sm-onboarding",
|
||||||
templateUrl: "./onboarding.component.html",
|
templateUrl: "./onboarding.component.html",
|
||||||
})
|
})
|
||||||
export class OnboardingComponent implements AfterContentInit {
|
export class OnboardingComponent {
|
||||||
@ContentChildren(OnboardingTaskComponent) tasks: QueryList<OnboardingTaskComponent>;
|
@ContentChildren(OnboardingTaskComponent) tasks: QueryList<OnboardingTaskComponent>;
|
||||||
@Input() title: string;
|
@Input() title: string;
|
||||||
|
|
||||||
|
@Output() dismiss = new EventEmitter<void>();
|
||||||
|
|
||||||
protected open = true;
|
protected open = true;
|
||||||
protected visible = false;
|
protected visible = false;
|
||||||
|
|
||||||
ngAfterContentInit() {
|
|
||||||
this.visible = !this.isComplete;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected get amountCompleted(): number {
|
protected get amountCompleted(): number {
|
||||||
return this.tasks.filter((task) => task.completed).length;
|
return this.tasks.filter((task) => task.completed).length;
|
||||||
}
|
}
|
||||||
@ -32,8 +30,4 @@ export class OnboardingComponent implements AfterContentInit {
|
|||||||
protected toggle() {
|
protected toggle() {
|
||||||
this.open = !this.open;
|
this.open = !this.open;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected dismiss() {
|
|
||||||
this.visible = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
</sm-header>
|
</sm-header>
|
||||||
|
|
||||||
<div *ngIf="view$ | async as view; else spinner">
|
<div *ngIf="view$ | async as view; else spinner">
|
||||||
<sm-onboarding [title]="'getStarted' | i18n">
|
<sm-onboarding [title]="'getStarted' | i18n" *ngIf="showOnboarding" (dismiss)="hideOnboarding()">
|
||||||
<sm-onboarding-task
|
<sm-onboarding-task
|
||||||
[title]="'createServiceAccount' | i18n"
|
[title]="'createServiceAccount' | i18n"
|
||||||
(click)="openServiceAccountDialog()"
|
(click)="openServiceAccountDialog()"
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Component, OnDestroy, OnInit } from "@angular/core";
|
import { Component, OnDestroy, OnInit } from "@angular/core";
|
||||||
import { ActivatedRoute, Router } from "@angular/router";
|
import { ActivatedRoute } from "@angular/router";
|
||||||
import {
|
import {
|
||||||
map,
|
map,
|
||||||
Observable,
|
Observable,
|
||||||
@ -8,7 +8,8 @@ import {
|
|||||||
takeUntil,
|
takeUntil,
|
||||||
combineLatest,
|
combineLatest,
|
||||||
startWith,
|
startWith,
|
||||||
distinct,
|
distinctUntilChanged,
|
||||||
|
take,
|
||||||
} from "rxjs";
|
} from "rxjs";
|
||||||
|
|
||||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||||
@ -56,11 +57,11 @@ type Tasks = {
|
|||||||
})
|
})
|
||||||
export class OverviewComponent implements OnInit, OnDestroy {
|
export class OverviewComponent implements OnInit, OnDestroy {
|
||||||
private destroy$: Subject<void> = new Subject<void>();
|
private destroy$: Subject<void> = new Subject<void>();
|
||||||
private prevShouldReuseRoute: any;
|
|
||||||
private tableSize = 10;
|
private tableSize = 10;
|
||||||
private organizationId: string;
|
private organizationId: string;
|
||||||
protected organizationName: string;
|
protected organizationName: string;
|
||||||
protected userIsAdmin: boolean;
|
protected userIsAdmin: boolean;
|
||||||
|
protected showOnboarding = false;
|
||||||
|
|
||||||
protected view$: Observable<{
|
protected view$: Observable<{
|
||||||
allProjects: ProjectListView[];
|
allProjects: ProjectListView[];
|
||||||
@ -72,7 +73,6 @@ export class OverviewComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
private router: Router,
|
|
||||||
private projectService: ProjectService,
|
private projectService: ProjectService,
|
||||||
private secretService: SecretService,
|
private secretService: SecretService,
|
||||||
private serviceAccountService: ServiceAccountService,
|
private serviceAccountService: ServiceAccountService,
|
||||||
@ -80,19 +80,12 @@ export class OverviewComponent implements OnInit, OnDestroy {
|
|||||||
private organizationService: OrganizationService,
|
private organizationService: OrganizationService,
|
||||||
private platformUtilsService: PlatformUtilsService,
|
private platformUtilsService: PlatformUtilsService,
|
||||||
private i18nService: I18nService
|
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() {
|
ngOnInit() {
|
||||||
const orgId$ = this.route.params.pipe(
|
const orgId$ = this.route.params.pipe(
|
||||||
map((p) => p.organizationId),
|
map((p) => p.organizationId),
|
||||||
distinct()
|
distinctUntilChanged()
|
||||||
);
|
);
|
||||||
|
|
||||||
orgId$
|
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 {
|
ngOnDestroy(): void {
|
||||||
this.router.routeReuseStrategy.shouldReuseRoute = this.prevShouldReuseRoute;
|
|
||||||
this.destroy$.next();
|
this.destroy$.next();
|
||||||
this.destroy$.complete();
|
this.destroy$.complete();
|
||||||
}
|
}
|
||||||
@ -245,4 +247,8 @@ export class OverviewComponent implements OnInit, OnDestroy {
|
|||||||
this.i18nService.t("valueCopied", this.i18nService.t("value"))
|
this.i18nService.t("valueCopied", this.i18nService.t("value"))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected hideOnboarding() {
|
||||||
|
this.showOnboarding = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { NgModule } from "@angular/core";
|
import { NgModule } from "@angular/core";
|
||||||
import { RouterModule, Routes } from "@angular/router";
|
import { RouterModule, Routes } from "@angular/router";
|
||||||
|
|
||||||
|
import { AuthGuard } from "@bitwarden/angular/auth/guards/auth.guard";
|
||||||
import { Organization } from "@bitwarden/common/models/domain/organization";
|
import { Organization } from "@bitwarden/common/models/domain/organization";
|
||||||
import { OrganizationPermissionsGuard } from "@bitwarden/web-vault/app/organizations/guards/org-permissions.guard";
|
import { OrganizationPermissionsGuard } from "@bitwarden/web-vault/app/organizations/guards/org-permissions.guard";
|
||||||
import { buildFlaggedRoute } from "@bitwarden/web-vault/app/oss-routing.module";
|
import { buildFlaggedRoute } from "@bitwarden/web-vault/app/oss-routing.module";
|
||||||
@ -19,7 +20,7 @@ const routes: Routes = [
|
|||||||
buildFlaggedRoute("secretsManager", {
|
buildFlaggedRoute("secretsManager", {
|
||||||
path: ":organizationId",
|
path: ":organizationId",
|
||||||
component: LayoutComponent,
|
component: LayoutComponent,
|
||||||
canActivate: [OrganizationPermissionsGuard, SMGuard],
|
canActivate: [AuthGuard, OrganizationPermissionsGuard, SMGuard],
|
||||||
data: {
|
data: {
|
||||||
organizationPermissions: (org: Organization) => org.canAccessSecretsManager,
|
organizationPermissions: (org: Organization) => org.canAccessSecretsManager,
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user