diff --git a/javascript/apps/taiga/src/app/modules/project/data-access/+state/effects/project.effects.ts b/javascript/apps/taiga/src/app/modules/project/data-access/+state/effects/project.effects.ts
index 35077edb9..07b79d70e 100644
--- a/javascript/apps/taiga/src/app/modules/project/data-access/+state/effects/project.effects.ts
+++ b/javascript/apps/taiga/src/app/modules/project/data-access/+state/effects/project.effects.ts
@@ -305,6 +305,7 @@ export class ProjectEffects {
'project',
project.id,
project.slug,
+ 'overview',
]);
}
}
diff --git a/javascript/apps/taiga/src/app/modules/project/data-access/guards/project-invitation.guard.ts b/javascript/apps/taiga/src/app/modules/project/data-access/guards/project-invitation.guard.ts
index 7be0034a8..1a4784376 100644
--- a/javascript/apps/taiga/src/app/modules/project/data-access/guards/project-invitation.guard.ts
+++ b/javascript/apps/taiga/src/app/modules/project/data-access/guards/project-invitation.guard.ts
@@ -103,7 +103,12 @@ export const ProjectInvitationGuard = (route: ActivatedRouteSnapshot) => {
}),
tap((project) => {
if (project) {
- void router.navigate(['/project', project.id, project.slug]);
+ void router.navigate([
+ '/project',
+ project.id,
+ project.slug,
+ 'overview',
+ ]);
}
return EMPTY;
})
diff --git a/javascript/apps/taiga/src/app/modules/project/feature-kanban/project-feature-kanban.component.ts b/javascript/apps/taiga/src/app/modules/project/feature-kanban/project-feature-kanban.component.ts
index c3b108648..8909c4083 100644
--- a/javascript/apps/taiga/src/app/modules/project/feature-kanban/project-feature-kanban.component.ts
+++ b/javascript/apps/taiga/src/app/modules/project/feature-kanban/project-feature-kanban.component.ts
@@ -9,7 +9,7 @@
import { Location, CommonModule } from '@angular/common';
import { ChangeDetectionStrategy, Component, ViewChild } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
-import { Router } from '@angular/router';
+import { ActivatedRoute, Router } from '@angular/router';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { concatLatestFrom } from '@ngrx/effects';
import { Store } from '@ngrx/store';
@@ -28,15 +28,7 @@ import {
Status,
Workflow,
} from '@taiga/data';
-import {
- combineLatest,
- filter,
- map,
- merge,
- pairwise,
- startWith,
- take,
-} from 'rxjs';
+import { combineLatest, filter, map, merge, pairwise, take } from 'rxjs';
import * as ProjectActions from '~/app/modules/project/data-access/+state/actions/project.actions';
import {
selectCurrentProject,
@@ -138,6 +130,7 @@ export class ProjectFeatureKanbanComponent {
private wsService: WsService,
private permissionService: PermissionsService,
private router: Router,
+ private route: ActivatedRoute,
private appService: AppService,
private location: Location,
public shortcutsService: ShortcutsService,
@@ -169,11 +162,7 @@ export class ProjectFeatureKanbanComponent {
);
this.state.connect(
'showStoryDetail',
- this.routeHistoryService.urlChanged.pipe(
- map((it) => it.url),
- startWith(this.router.url),
- map((url) => url.includes('/stories/'))
- )
+ this.route.data.pipe(map((data) => !!data.stories))
);
this.state.connect(
@@ -211,7 +200,12 @@ export class ProjectFeatureKanbanComponent {
concatLatestFrom(() => this.project$.pipe(filterNil()))
)
.subscribe(([, project]) => {
- void this.router.navigate(['project', project.id, project.slug]);
+ void this.router.navigate([
+ 'project',
+ project.id,
+ project.slug,
+ 'overview',
+ ]);
this.appService.toastNotification({
message: 'lost_kanban_access',
diff --git a/javascript/apps/taiga/src/app/modules/project/feature-navigation/components/project-navigation-menu/project-navigation-menu.component.html b/javascript/apps/taiga/src/app/modules/project/feature-navigation/components/project-navigation-menu/project-navigation-menu.component.html
index af1abff30..862f63a37 100644
--- a/javascript/apps/taiga/src/app/modules/project/feature-navigation/components/project-navigation-menu/project-navigation-menu.component.html
+++ b/javascript/apps/taiga/src/app/modules/project/feature-navigation/components/project-navigation-menu/project-navigation-menu.component.html
@@ -22,7 +22,7 @@
(focusout)="out()"
[attr.data-text]="'project'"
[class.active-dialog]="dialog.type === 'project'"
- [routerLink]="['/project', project.id, project.slug]">
+ [routerLink]="['/project', project.id, project.slug, 'overview']">
+ [routerLink]="['/project', project.id, project.slug, 'overview']">
{{ project.name }}
+ [routerLink]="['/project', project.id, project.slug, 'overview']">
{{ project.name }}
{
component: ProjectNavigationSettingsComponent,
imports: [getTranslocoModule(), RouterTestingModule],
declareComponent: false,
- mocks: [RouteHistoryService],
- providers: [
- mockProvider(ProjectNavigationComponent, {
- animationEvents$,
- }),
- {
- provide: ActivatedRoute,
- useValue: {
- fragment,
- snapshot: {
- params: {
- id: projectId,
- slug: projectName,
- },
- },
- },
- },
- ],
+ mocks: [RouteHistoryService, Router],
});
beforeEach(() => {
spectator = createComponent({
+ providers: [
+ mockProvider(ProjectNavigationComponent, {
+ animationEvents$,
+ }),
+ {
+ provide: ActivatedRoute,
+ useValue: {
+ fragment,
+ snapshot: {
+ params: {
+ id: projectId,
+ slug: projectName,
+ },
+ data: {
+ settings: true,
+ },
+ },
+ },
+ },
+ ],
detectChanges: false,
});
spectator.component.project = ProjectMockFactory();
@@ -70,6 +73,7 @@ describe('ProjectSettingsComponent', () => {
spectator.component.getRouter = jest
.fn()
.mockReturnValue({ url: '/router' });
+ spectator.component.isSettings = jest.fn().mockReturnValue(false);
const routeHistory =
spectator.inject(RouteHistoryService);
@@ -88,6 +92,7 @@ describe('ProjectSettingsComponent', () => {
spectator.component.getRouter = jest
.fn()
.mockReturnValue({ url: '/router' });
+ spectator.component.isSettings = jest.fn().mockReturnValue(false);
const routeHistory =
spectator.inject(RouteHistoryService);
@@ -106,21 +111,22 @@ describe('ProjectSettingsComponent', () => {
spectator.component.getRouter = jest
.fn()
.mockReturnValue({ url: '/router' });
+ spectator.component.isSettings = jest.fn().mockReturnValue(true);
const routeHistory =
spectator.inject(RouteHistoryService);
routeHistory.getPreviousUrl.mockReturnValue('');
- spectator.component.getRouter = jest
- .fn()
- .mockReturnValue({ url: '/settings' });
+ spectator.component.getRouter = jest.fn().mockReturnValue({
+ url: `/settings`,
+ });
spectator.detectChanges();
spectator.component.getHistoryNav();
expect(spectator.component.previousUrl).toEqual(
- `/project/${projectId}/${projectName}`
+ `/project/${projectId}/${projectName}/overview`
);
});
});
diff --git a/javascript/apps/taiga/src/app/modules/project/feature-navigation/components/project-navigation-settings/project-navigation-settings.component.ts b/javascript/apps/taiga/src/app/modules/project/feature-navigation/components/project-navigation-settings/project-navigation-settings.component.ts
index f658068ad..e4a51ef70 100644
--- a/javascript/apps/taiga/src/app/modules/project/feature-navigation/components/project-navigation-settings/project-navigation-settings.component.ts
+++ b/javascript/apps/taiga/src/app/modules/project/feature-navigation/components/project-navigation-settings/project-navigation-settings.component.ts
@@ -19,7 +19,7 @@ import {
Output,
ViewChild,
} from '@angular/core';
-import { ActivatedRoute, Router, RouterModule } from '@angular/router';
+import { ActivatedRoute, Router, RouterModule, ActivatedRouteSnapshot } from '@angular/router';
import { TRANSLOCO_SCOPE, TranslocoDirective } from '@ngneat/transloco';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { TuiSvgModule } from '@taiga-ui/core';
@@ -100,10 +100,12 @@ export class ProjectNavigationSettingsComponent implements OnInit {
public getHistoryNav() {
this.previousUrl =
this.routeHistory.getPreviousUrl() || this.getRouter().url;
- if (this.previousUrl.includes('/settings')) {
+ if (this.previousUrl.includes('/settings') && this.isSettings()) {
const id: string = this.route.snapshot.params.id;
- const slug: string = this.route.snapshot.params.slug;
- this.previousUrl = `/project/${id}/${slug}`;
+ const slug: string =
+ this.route.snapshot.params.slug ||
+ (this.route.snapshot.data.project as Project).slug;
+ this.previousUrl = `/project/${id}/${slug}/overview`;
}
}
@@ -122,4 +124,14 @@ export class ProjectNavigationSettingsComponent implements OnInit {
public getRouter() {
return this.router;
}
+
+ public isSettings() {
+ const getActiveRoute = (
+ route: ActivatedRouteSnapshot
+ ): ActivatedRouteSnapshot => {
+ return route.firstChild ? getActiveRoute(route.firstChild) : route;
+ };
+ const active = getActiveRoute(this.route.snapshot);
+ return !!active.data.settings;
+ }
}
diff --git a/javascript/apps/taiga/src/app/modules/project/feature-navigation/project-feature-navigation.component.spec.ts b/javascript/apps/taiga/src/app/modules/project/feature-navigation/project-feature-navigation.component.spec.ts
index 208e79fb2..9981441c9 100644
--- a/javascript/apps/taiga/src/app/modules/project/feature-navigation/project-feature-navigation.component.spec.ts
+++ b/javascript/apps/taiga/src/app/modules/project/feature-navigation/project-feature-navigation.component.spec.ts
@@ -8,7 +8,7 @@
import { CommonModule } from '@angular/common';
import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from '@angular/core';
-import { Router } from '@angular/router';
+import { ActivatedRoute, Router } from '@angular/router';
import {
createComponentFactory,
mockProvider,
@@ -28,12 +28,6 @@ describe('ProjectNavigationComponent', () => {
imports: [CommonModule, getTranslocoModule()],
schemas: [NO_ERRORS_SCHEMA],
mocks: [LocalStorageService],
- providers: [
- mockProvider(Router, {
- events: events$,
- url: '/settings',
- }),
- ],
shallow: true,
overrideComponents: [
[
@@ -50,6 +44,22 @@ describe('ProjectNavigationComponent', () => {
beforeEach(() => {
spectator = createComponent({
+ providers: [
+ mockProvider(Router, {
+ events: events$,
+ url: '/settings',
+ }),
+ {
+ provide: ActivatedRoute,
+ useValue: {
+ snapshot: {
+ data: {
+ settings: true,
+ },
+ },
+ },
+ },
+ ],
detectChanges: false,
});
diff --git a/javascript/apps/taiga/src/app/modules/project/feature-navigation/project-feature-navigation.component.ts b/javascript/apps/taiga/src/app/modules/project/feature-navigation/project-feature-navigation.component.ts
index 94d60208e..6021e530f 100644
--- a/javascript/apps/taiga/src/app/modules/project/feature-navigation/project-feature-navigation.component.ts
+++ b/javascript/apps/taiga/src/app/modules/project/feature-navigation/project-feature-navigation.component.ts
@@ -26,7 +26,7 @@ import {
Input,
OnInit,
} from '@angular/core';
-import { Router } from '@angular/router';
+import { ActivatedRoute, Router } from '@angular/router';
import { RxState } from '@rx-angular/state';
import { Project } from '@taiga/data';
import { Subject } from 'rxjs';
@@ -203,25 +203,16 @@ export class ProjectNavigationComponent implements OnInit, AfterViewInit {
constructor(
private el: ElementRef,
private localStorage: LocalStorageService,
- private router: Router
+ private router: Router,
+ private route: ActivatedRoute
) {}
public ngOnInit() {
this.collapsed = !!LocalStorageService.get('projectnav-collapsed');
this.router.events.subscribe(() => {
- !this.router.url.includes('/settings')
- ? (this.showProjectSettings = false)
- : (this.showProjectSettings = true);
+ this.showProjectSettings = this.isSettings();
});
- this.showProjectSettings = this.router.isActive(
- this.router.createUrlTree(['project', this.project.id, 'settings']),
- {
- paths: 'subset',
- queryParams: 'ignored',
- fragment: 'ignored',
- matrixParams: 'ignored',
- }
- );
+ this.showProjectSettings = this.isSettings();
}
public ngAfterViewInit() {
@@ -229,6 +220,10 @@ export class ProjectNavigationComponent implements OnInit, AfterViewInit {
this.updateBlockSize(size);
}
+ public isSettings() {
+ return !!this.route.snapshot.data.settings;
+ }
+
public calcBlockSize() {
const el = this.el.nativeElement as HTMLElement;
const header = getComputedStyle(el).getPropertyValue('--header-height');
diff --git a/javascript/apps/taiga/src/app/modules/project/feature-shell/project-feature-shell-routing.module.ts b/javascript/apps/taiga/src/app/modules/project/feature-shell/project-feature-shell-routing.module.ts
index b8f963ab0..0faff9bdd 100644
--- a/javascript/apps/taiga/src/app/modules/project/feature-shell/project-feature-shell-routing.module.ts
+++ b/javascript/apps/taiga/src/app/modules/project/feature-shell/project-feature-shell-routing.module.ts
@@ -27,6 +27,10 @@ const routes: Routes = [
import(
'~/app/modules/project/feature-view-setter/project-feature-view-setter.module'
).then((m) => m.ProjectFeatureViewSetterModule),
+ canDeactivate: [CanDeactivateGuard],
+ data: {
+ kanban: true,
+ },
},
{
path: 'kanban',
@@ -35,6 +39,9 @@ const routes: Routes = [
'~/app/modules/project/feature-view-setter/project-feature-view-setter.module'
).then((m) => m.ProjectFeatureViewSetterModule),
canDeactivate: [CanDeactivateGuard],
+ data: {
+ kanban: true,
+ },
},
{
path: ':slug/stories/:storyRef',
@@ -43,6 +50,9 @@ const routes: Routes = [
'~/app/modules/project/feature-view-setter/project-feature-view-setter.module'
).then((m) => m.ProjectFeatureViewSetterModule),
canDeactivate: [CanDeactivateGuard],
+ data: {
+ stories: true,
+ },
},
{
path: 'stories/:storyRef',
@@ -51,6 +61,9 @@ const routes: Routes = [
'~/app/modules/project/feature-view-setter/project-feature-view-setter.module'
).then((m) => m.ProjectFeatureViewSetterModule),
canDeactivate: [CanDeactivateGuard],
+ data: {
+ stories: true,
+ },
},
{
path: ':slug/settings',
@@ -58,6 +71,9 @@ const routes: Routes = [
import(
'~/app/modules/project/settings/feature-settings/feature-settings.module'
).then((m) => m.ProjectSettingsFeatureSettingsModule),
+ data: {
+ settings: true,
+ },
resolve: {
project: ProjectAdminResolver,
},
@@ -68,23 +84,32 @@ const routes: Routes = [
import(
'~/app/modules/project/settings/feature-settings/feature-settings.module'
).then((m) => m.ProjectSettingsFeatureSettingsModule),
+ data: {
+ settings: true,
+ },
resolve: {
project: ProjectAdminResolver,
},
},
{
- path: '',
+ path: 'overview',
loadChildren: () =>
import(
'~/app/modules/project/feature-overview/project-feature-overview.module'
).then((m) => m.ProjectFeatureOverviewModule),
+ data: {
+ overview: true,
+ },
},
{
- path: ':slug',
+ path: ':slug/overview',
loadChildren: () =>
import(
'~/app/modules/project/feature-overview/project-feature-overview.module'
).then((m) => m.ProjectFeatureOverviewModule),
+ data: {
+ overview: true,
+ },
},
],
},
diff --git a/javascript/apps/taiga/src/app/modules/project/feature-shell/project-feature-shell.component.ts b/javascript/apps/taiga/src/app/modules/project/feature-shell/project-feature-shell.component.ts
index adc4524b2..5ad78b2d0 100644
--- a/javascript/apps/taiga/src/app/modules/project/feature-shell/project-feature-shell.component.ts
+++ b/javascript/apps/taiga/src/app/modules/project/feature-shell/project-feature-shell.component.ts
@@ -7,14 +7,14 @@
*/
import { animate, style, transition, trigger } from '@angular/animations';
-import { Location, CommonModule } from '@angular/common';
+import { CommonModule } from '@angular/common';
import {
AfterViewInit,
ChangeDetectorRef,
Component,
OnDestroy,
} from '@angular/core';
-import { Router, RouterOutlet } from '@angular/router';
+import { Router, RouterOutlet, ActivatedRoute, ActivatedRouteSnapshot } from '@angular/router';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { Store } from '@ngrx/store';
import { RxState } from '@rx-angular/state';
@@ -113,8 +113,8 @@ export class ProjectFeatureShellComponent implements OnDestroy, AfterViewInit {
showBannerOnRevoke: boolean;
}>,
private userStorageService: UserStorageService,
- private location: Location,
private router: Router,
+ private route: ActivatedRoute,
private appService: AppService
) {
this.watchProject();
@@ -133,17 +133,46 @@ export class ProjectFeatureShellComponent implements OnDestroy, AfterViewInit {
.pipe(distinctUntilChanged((prev, curr) => prev.id === curr.id));
this.state.hold(project$, (project) => {
- const url = window.location.href;
- const newUrl = `project/${project.id}/${project.slug}`;
-
- if (
- !url.includes('/kanban') &&
- !url.includes('/stories') &&
- !url.includes('/settings') &&
- !url.endsWith(newUrl) // location go when the url doesn't match
- ) {
- this.location.go(newUrl);
+ const getActiveRoute = (
+ route: ActivatedRouteSnapshot
+ ): ActivatedRouteSnapshot => {
+ return route.firstChild ? getActiveRoute(route.firstChild) : route;
+ };
+ const active = getActiveRoute(this.route.snapshot);
+ const needRedirect = active.params.slug !== project.slug;
+
+ if (needRedirect) {
+ const isKanban = !!active.data.kanban;
+ const isOverview =
+ !!active.data.overview &&
+ active.routeConfig?.component?.name ===
+ 'ProjectFeatureOverviewComponent';
+ const isSettings = !!active.data.settings;
+
+ if (isKanban) {
+ void this.router.navigate(
+ [`project/${project.id}/${project.slug}/kanban`],
+ { replaceUrl: true }
+ );
+ } else if (isOverview) {
+ void this.router.navigate(
+ [`project/${project.id}/${project.slug}/overview`],
+ { replaceUrl: true }
+ );
+ } else if (isSettings) {
+ void this.router.navigate(
+ [
+ `project/${project.id}/${project.slug}/settings/${
+ this.router.url.includes('/settings/members')
+ ? 'members'
+ : 'permissions'
+ }`,
+ ],
+ { replaceUrl: true }
+ );
+ }
}
+
this.subscribedProject = project.id;
this.unsubscribeFromProjectEvents();
this.wsService
diff --git a/javascript/apps/taiga/src/app/modules/project/feature-view-setter/project-feature-view-setter.component.ts b/javascript/apps/taiga/src/app/modules/project/feature-view-setter/project-feature-view-setter.component.ts
index 6d0dbdd00..2cf1d00e4 100644
--- a/javascript/apps/taiga/src/app/modules/project/feature-view-setter/project-feature-view-setter.component.ts
+++ b/javascript/apps/taiga/src/app/modules/project/feature-view-setter/project-feature-view-setter.component.ts
@@ -10,14 +10,21 @@ import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
+ DestroyRef,
OnDestroy,
ViewChild,
ViewContainerRef,
inject,
} from '@angular/core';
-import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { Store } from '@ngrx/store';
-import { distinctUntilChanged, filter, map, pairwise, startWith } from 'rxjs';
+import {
+ distinctUntilChanged,
+ filter,
+ map,
+ pairwise,
+ startWith,
+ combineLatest,
+} from 'rxjs';
import { RouteHistoryService } from '~/app/shared/route-history/route-history.service';
import { StoryDetailActions } from '../story-detail/data-access/+state/actions/story-detail.actions';
import {
@@ -26,11 +33,16 @@ import {
} from '../story-detail/data-access/+state/selectors/story-detail.selectors';
import { ProjectFeatureStoryWrapperFullViewModule } from '../feature-story-wrapper-full-view/project-feature-story-wrapper-full-view.module';
-import { filterFalsy, filterNil } from '~/app/shared/utils/operators';
-import { Router } from '@angular/router';
+import { filterNil } from '~/app/shared/utils/operators';
+import {
+ ActivatedRoute,
+ ActivatedRouteSnapshot,
+ Router,
+} from '@angular/router';
import { RxState } from '@rx-angular/state';
-import { StoryDetail, StoryView } from '@taiga/data';
import { CommonModule } from '@angular/common';
+import { StoryDetail, StoryView, Project, Story } from '@taiga/data';
+import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
interface ProjectFeatureViewSetterComponentState {
storyView: StoryView;
@@ -40,7 +52,12 @@ interface ProjectFeatureViewSetterComponentState {
url: string;
}
-@UntilDestroy()
+interface StoryParams {
+ id: Project['id'];
+ slug: Project['slug'];
+ storyRef: Story['ref'];
+}
+
@Component({
selector: 'tg-project-feature-view-setter',
templateUrl: './project-feature-view-setter.component.html',
@@ -61,9 +78,11 @@ export class ProjectFeatureViewSetterComponent implements OnDestroy {
) as RxState;
public model$ = this.state.select();
+ private destroyRef = inject(DestroyRef);
constructor(
private router: Router,
+ private route: ActivatedRoute,
private store: Store,
private routerHistory: RouteHistoryService,
private cd: ChangeDetectorRef
@@ -73,25 +92,16 @@ export class ProjectFeatureViewSetterComponent implements OnDestroy {
this.state.connect(
'url',
this.routerHistory.urlChanged.pipe(
- untilDestroyed(this),
+ takeUntilDestroyed(this.destroyRef),
map(({ url }) => url),
startWith(this.router.url),
distinctUntilChanged()
)
);
+
this.state.connect(
'isKanban',
- this.state.select('url').pipe(map((url) => url.includes('kanban')))
- );
-
- this.state.hold(
- this.state.select('url').pipe(
- map((url) => url.includes('/stories')),
- filterFalsy()
- ),
- () => {
- this.fetchStory();
- }
+ this.state.select('url').pipe(map((url) => url.endsWith('/kanban')))
);
this.state.hold(
@@ -110,32 +120,49 @@ export class ProjectFeatureViewSetterComponent implements OnDestroy {
this.store.dispatch(StoryDetailActions.leaveStoryDetail());
}
);
+
+ combineLatest([
+ this.state.select('url'),
+ this.route.data,
+ this.route.params,
+ ])
+ .pipe(takeUntilDestroyed(this.destroyRef))
+ .subscribe(([url, data, params]) => {
+ if (!url.endsWith('/kanban') && !!data.stories) {
+ const storyParams = params as StoryParams;
+ const needRedirect = params.slug !== (data.project as Project).slug;
+ if (needRedirect) {
+ void this.router.navigate(
+ [
+ `project/${storyParams.id}/${
+ (data.project as Project).slug
+ }/stories/${storyParams.storyRef}`,
+ ],
+ { replaceUrl: true }
+ );
+ }
+ this.fetchStory(storyParams);
+ }
+ });
}
public ngOnDestroy() {
this.store.dispatch(StoryDetailActions.leaveStoryDetail());
}
- private fetchStory() {
- const params = this.getUrlParams();
+ public getActiveRoute(route: ActivatedRouteSnapshot): ActivatedRouteSnapshot {
+ return route.firstChild ? this.getActiveRoute(route.firstChild) : route;
+ }
+ private fetchStory(params: StoryParams) {
this.store.dispatch(
StoryDetailActions.initStory({
- projectId: params.projectId,
+ projectId: params.id,
storyRef: params.storyRef,
})
);
}
- private getUrlParams() {
- const url = window.location.href;
-
- return {
- projectId: url.match(/(?<=\/project\/)[^/]+/)![0],
- storyRef: +url.match(/(?<=\/stories\/)[^/]+/)![0],
- };
- }
-
private async loadKanban(viewContainerRef: ViewContainerRef) {
const { ProjectFeatureViewSetterKanbanComponent } = await import(
'./project-feature-view-setter.component-kanban.component'
diff --git a/javascript/apps/taiga/src/app/shared/navigation/navigation-projects/navigation-projects.component.html b/javascript/apps/taiga/src/app/shared/navigation/navigation-projects/navigation-projects.component.html
index 40ce4dda8..bd2e25805 100644
--- a/javascript/apps/taiga/src/app/shared/navigation/navigation-projects/navigation-projects.component.html
+++ b/javascript/apps/taiga/src/app/shared/navigation/navigation-projects/navigation-projects.component.html
@@ -34,7 +34,7 @@
let i = index
"
tuiOption
- [routerLink]="['/project', project.id, project.slug]"
+ [routerLink]="['/project', project.id, project.slug, 'overview']"
role="menuitem"
href="#"
class="project">
diff --git a/javascript/apps/taiga/src/app/shared/project-card/project-card.component.html b/javascript/apps/taiga/src/app/shared/project-card/project-card.component.html
index ef3eb5042..e307b2e9c 100644
--- a/javascript/apps/taiga/src/app/shared/project-card/project-card.component.html
+++ b/javascript/apps/taiga/src/app/shared/project-card/project-card.component.html
@@ -42,7 +42,7 @@
[name]="project.name">
diff --git a/javascript/apps/taiga/src/app/shared/projects-dropdown/projects-dropdown.component.html b/javascript/apps/taiga/src/app/shared/projects-dropdown/projects-dropdown.component.html
index 15c9ecbb3..5d7bfcbe6 100644
--- a/javascript/apps/taiga/src/app/shared/projects-dropdown/projects-dropdown.component.html
+++ b/javascript/apps/taiga/src/app/shared/projects-dropdown/projects-dropdown.component.html
@@ -58,7 +58,12 @@
class="project-data"
role="menuitem"
routerLinkActive
- [routerLink]="['/project', project.id, project.slug]">
+ [routerLink]="[
+ '/project',
+ project.id,
+ project.slug,
+ 'overview'
+ ]">