diff --git a/client/src/app/components/branches-table/branches-table.component.html b/client/src/app/components/branches-table/branches-table.component.html
index 6a59550ae..06767c945 100644
--- a/client/src/app/components/branches-table/branches-table.component.html
+++ b/client/src/app/components/branches-table/branches-table.component.html
@@ -54,7 +54,7 @@
(mouseleave)="isHovered.set(branch.name, false)"
>
- @if (!rowNode.node.children && isHovered.get(branch.name) && keycloakService.isLoggedIn()) {
+ @if (!rowNode.node.children && isHovered.get(branch.name) && isLoggedIn()) {
@if (branch.isPinned) {
diff --git a/client/src/app/components/branches-table/branches-table.component.ts b/client/src/app/components/branches-table/branches-table.component.ts
index 1a97cdd67..f77652026 100644
--- a/client/src/app/components/branches-table/branches-table.component.ts
+++ b/client/src/app/components/branches-table/branches-table.component.ts
@@ -22,7 +22,7 @@ import { DividerModule } from 'primeng/divider';
import { TooltipModule } from 'primeng/tooltip';
import { FormsModule } from '@angular/forms';
import { TimeAgoPipe } from '@app/pipes/time-ago.pipe';
-import { FILTER_OPTIONS_TOKEN, SearchTableService } from '@app/core/services/search-table.service';
+import { FILTER_OPTIONS_TOKEN, FilterOption, SearchTableService } from '@app/core/services/search-table.service';
import { TableFilterComponent } from '../table-filter/table-filter.component';
import { WorkflowRunStatusComponent } from '@app/components/workflow-run-status-component/workflow-run-status.component';
import { HighlightPipe } from '@app/pipes/highlight.pipe';
@@ -31,46 +31,61 @@ import { KeycloakService } from '@app/core/services/keycloak/keycloak.service';
import { provideTablerIcons, TablerIconComponent } from 'angular-tabler-icons';
import { IconExternalLink, IconFilterPlus, IconGitBranch, IconGitCommit, IconPinned, IconPinnedOff, IconShieldHalf, IconBrandGithub } from 'angular-tabler-icons/icons';
-type BranchInfoWithLink = BranchInfoDto & { link: string; lastCommitLink: string };
-
-const FILTER_OPTIONS = [
- { name: 'All Branches', filter: (branches: BranchInfoWithLink[]) => branches },
- { name: 'Default Branch', filter: (branches: BranchInfoWithLink[]) => branches.filter(branch => branch.isDefault) },
- { name: 'Protected Branches', filter: (branches: BranchInfoWithLink[]) => branches.filter(branch => branch.isProtected) },
- {
- name: 'Active Branches',
- filter: (branches: BranchInfoWithLink[]) =>
- branches.filter(branch => {
- const date = new Date(branch.updatedAt || '');
- const staleThreshold = new Date();
- staleThreshold.setDate(staleThreshold.getDate() - 30);
-
- return date >= staleThreshold;
- }),
- },
- {
- name: 'Last 7 Day',
- filter: (branches: BranchInfoWithLink[]) =>
- branches.filter(branch => {
- const date = new Date(branch.updatedAt || '');
- const staleThreshold = new Date();
- staleThreshold.setDate(staleThreshold.getDate() - 7);
-
- return date >= staleThreshold;
- }),
- },
- {
- name: 'Stale Branches',
- filter: (branches: BranchInfoWithLink[]) =>
- branches.filter(branch => {
- const date = new Date(branch.updatedAt || '');
- const staleThreshold = new Date();
- staleThreshold.setDate(staleThreshold.getDate() - 30);
-
- return date < staleThreshold;
- }),
- },
-];
+export type BranchInfoWithLink = BranchInfoDto & { link: string; lastCommitLink: string };
+
+export function createBranchFilterOptions(keycloakService: KeycloakService): FilterOption[] {
+ const isLoggedIn = keycloakService.isLoggedIn();
+ const githubPreferredUsername = isLoggedIn ? keycloakService.getPreferredUsername() : '';
+
+ const options: FilterOption[] = [
+ { name: 'All Branches', filter: (branches: BranchInfoWithLink[]) => branches },
+ { name: 'Default Branch', filter: (branches: BranchInfoWithLink[]) => branches.filter(branch => branch.isDefault) },
+ { name: 'Protected Branches', filter: (branches: BranchInfoWithLink[]) => branches.filter(branch => branch.isProtected) },
+ {
+ name: 'Active Branches',
+ filter: (branches: BranchInfoWithLink[]) =>
+ branches.filter(branch => {
+ const date = new Date(branch.updatedAt || '');
+ const staleThreshold = new Date();
+ staleThreshold.setDate(staleThreshold.getDate() - 30);
+
+ return date >= staleThreshold;
+ }),
+ },
+ {
+ name: 'Last 7 Day',
+ filter: (branches: BranchInfoWithLink[]) =>
+ branches.filter(branch => {
+ const date = new Date(branch.updatedAt || '');
+ const staleThreshold = new Date();
+ staleThreshold.setDate(staleThreshold.getDate() - 7);
+
+ return date >= staleThreshold;
+ }),
+ },
+ {
+ name: 'Stale Branches',
+ filter: (branches: BranchInfoWithLink[]) =>
+ branches.filter(branch => {
+ const date = new Date(branch.updatedAt || '');
+ const staleThreshold = new Date();
+ staleThreshold.setDate(staleThreshold.getDate() - 30);
+
+ return date < staleThreshold;
+ }),
+ },
+ ];
+
+ // Add the "Your Branches" filter option only if the user is logged in
+ if (isLoggedIn && githubPreferredUsername) {
+ options.splice(1, 0, {
+ name: 'Your Branches',
+ filter: (branches: BranchInfoWithLink[]) => branches.filter(branch => branch.updatedBy?.login?.toLowerCase() === githubPreferredUsername.toLowerCase()),
+ });
+ }
+
+ return options;
+}
@Component({
selector: 'app-branches-table',
@@ -97,7 +112,7 @@ const FILTER_OPTIONS = [
],
providers: [
SearchTableService,
- { provide: FILTER_OPTIONS_TOKEN, useValue: FILTER_OPTIONS },
+ { provide: FILTER_OPTIONS_TOKEN, useFactory: createBranchFilterOptions, deps: [KeycloakService] },
provideTablerIcons({ IconFilterPlus, IconPinnedOff, IconPinned, IconShieldHalf, IconBrandGithub, IconExternalLink, IconGitCommit, IconGitBranch }),
],
templateUrl: './branches-table.component.html',
@@ -108,7 +123,8 @@ export class BranchTableComponent {
messageService = inject(MessageService);
queryClient = inject(QueryClient);
searchTableService = inject(SearchTableService);
- keycloakService = inject(KeycloakService);
+ private keycloakService = inject(KeycloakService);
+ readonly isLoggedIn = computed(() => this.keycloakService.isLoggedIn());
treeTable = viewChild('table');
diff --git a/client/src/app/core/services/search-table.service.ts b/client/src/app/core/services/search-table.service.ts
index 725477858..34db0f9cf 100644
--- a/client/src/app/core/services/search-table.service.ts
+++ b/client/src/app/core/services/search-table.service.ts
@@ -4,7 +4,7 @@ import { TreeTable } from 'primeng/treetable';
import { UserProfile } from './keycloak/user-profile';
export type SearchTable = TreeTable | Table;
-type FilterOption = { name: string; filter: (prs: T[], userProfile?: UserProfile) => T[] };
+export type FilterOption = { name: string; filter: (prs: T[], userProfile?: UserProfile) => T[] };
export const FILTER_OPTIONS_TOKEN = new InjectionToken('filterOptions');
diff --git a/client/src/app/pages/branch-list/branch-list.spec.ts b/client/src/app/pages/branch-list/branch-list.spec.ts
index 7e17b35e3..d33c47082 100644
--- a/client/src/app/pages/branch-list/branch-list.spec.ts
+++ b/client/src/app/pages/branch-list/branch-list.spec.ts
@@ -2,6 +2,9 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
import { BranchListComponent } from './branch-list.component';
import { importProvidersFrom } from '@angular/core';
import { TestModule } from '@app/test.module';
+import { FILTER_OPTIONS_TOKEN, FilterOption } from '@app/core/services/search-table.service';
+import { KeycloakService } from '@app/core/services/keycloak/keycloak.service';
+import { BranchInfoWithLink } from '@app/components/branches-table/branches-table.component';
describe('Integration Test Branch List Page', () => {
let component: BranchListComponent;
@@ -10,7 +13,28 @@ describe('Integration Test Branch List Page', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [BranchListComponent],
- providers: [importProvidersFrom(TestModule)],
+ providers: [
+ importProvidersFrom(TestModule),
+ // Mock KeycloakService
+ {
+ provide: KeycloakService,
+ useValue: {
+ isLoggedIn: () => false,
+ getPreferredUsername: () => '',
+ },
+ },
+ // Provide FILTER_OPTIONS_TOKEN manually to match factory expectations
+ {
+ provide: FILTER_OPTIONS_TOKEN,
+ useFactory: (): FilterOption[] => [
+ {
+ name: 'All Branches',
+ filter: (branches: BranchInfoWithLink[]) => branches,
+ },
+ ],
+ deps: [KeycloakService],
+ },
+ ],
}).compileComponents();
fixture = TestBed.createComponent(BranchListComponent);