Skip to content

Commit 5757a8f

Browse files
authored
Merge pull request #333 from red-kite-solutions/global-project-filter
Global project filter
2 parents e8ce79a + 81eda23 commit 5757a8f

24 files changed

+722
-484
lines changed

packages/frontend/stalker-app/src/app/layouts/default/default.module.ts

+6-4
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,18 @@ import { RouterModule } from '@angular/router';
2727
import { NgxFileDropModule } from 'ngx-file-drop';
2828
import { CreateUserComponent } from '../../modules/admin/create-user/create-user.component';
2929
import { SettingsComponent } from '../../modules/admin/settings/settings.component';
30+
import { FindingsModule } from '../../modules/findings/findings.module';
31+
import { JobExecutionDetailComponent } from '../../modules/jobs/job-executions/job-execution-detail.component';
3032
import { JobLogsSummaryComponent } from '../../modules/jobs/job-executions/job-execution-logs-summary.component';
3133
import { EditProjectsComponent } from '../../modules/projects/edit-projects/edit-projects.component';
3234
import { AvatarComponent } from '../../shared/components/avatar/avatar.component';
33-
import { SharedModule } from '../../shared/shared.module';
34-
import { SpinnerButtonComponent } from '../../shared/widget/spinner-button/spinner-button.component';
35-
import { FindingsModule } from '../../modules/findings/findings.module';
36-
import { JobExecutionDetailComponent } from '../../modules/jobs/job-executions/job-execution-detail.component';
35+
import { HeaderComponent } from '../../shared/components/header/header.component';
3736
import { JobLogsComponent } from '../../shared/components/job-logs/job-logs.component';
3837
import { AppHeaderComponent } from '../../shared/components/page-header/page-header.component';
3938
import { PanelSectionModule } from '../../shared/components/panel-section/panel-section.module';
39+
import { SharedModule } from '../../shared/shared.module';
4040
import { CodeEditorComponent } from '../../shared/widget/code-editor/code-editor.component';
41+
import { SpinnerButtonComponent } from '../../shared/widget/spinner-button/spinner-button.component';
4142
import { DefaultComponent } from './default.component';
4243

4344
@NgModule({
@@ -49,6 +50,7 @@ import { DefaultComponent } from './default.component';
4950
JobExecutionDetailComponent,
5051
],
5152
imports: [
53+
HeaderComponent,
5254
CommonModule,
5355
RouterModule,
5456
SharedModule,

packages/frontend/stalker-app/src/app/layouts/unauthenticated/unauthenticated.module.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@ import { NgModule } from '@angular/core';
33
import { MatSidenavModule } from '@angular/material/sidenav';
44
import { RouterModule } from '@angular/router';
55
import { AuthModule } from '../../modules/auth/auth.module';
6+
import { HeaderComponent } from '../../shared/components/header/header.component';
67
import { SharedModule } from '../../shared/shared.module';
78
import { UnauthenticatedComponent } from './unauthenticated.component';
89

910
@NgModule({
1011
declarations: [UnauthenticatedComponent],
11-
imports: [CommonModule, RouterModule, MatSidenavModule, SharedModule, AuthModule],
12+
imports: [HeaderComponent, CommonModule, RouterModule, MatSidenavModule, SharedModule, AuthModule],
1213
})
1314
export class UnauthenticatedModule {}

packages/frontend/stalker-app/src/app/modules/dashboard/latest-jobs/latest-jobs.component.ts

+19-3
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
import { CommonModule } from '@angular/common';
22
import { Component } from '@angular/core';
3+
import { MatButtonModule } from '@angular/material/button';
34
import { MatListModule } from '@angular/material/list';
45
import { RouterModule } from '@angular/router';
5-
import { map } from 'rxjs';
6+
import { map, switchMap } from 'rxjs';
67
import { JobExecutionsService } from '../../../api/jobs/job-executions/job-executions.service';
8+
import { globalProjectFilter$ } from '../../../utils/global-project-filter';
79
import { JobLogsSummaryComponent } from '../../jobs/job-executions/job-execution-logs-summary.component';
810
import { JobStateComponent } from '../../jobs/job-executions/job-execution-state.component';
911

1012
@Component({
1113
standalone: true,
1214
selector: 'latest-jobs',
13-
imports: [CommonModule, MatListModule, RouterModule, JobStateComponent, JobLogsSummaryComponent],
15+
imports: [CommonModule, MatListModule, RouterModule, JobStateComponent, JobLogsSummaryComponent, MatButtonModule],
1416
styleUrls: ['../metric-styling.scss'],
1517
template: `<span class="metric-title" i18n="Latest jobs|Latest jobs that ran">Latest jobs</span>
1618
<mat-list class="metric-list">
@@ -23,10 +25,24 @@ import { JobStateComponent } from '../../jobs/job-executions/job-execution-state
2325
</span>
2426
</mat-list-item>
2527
}
28+
29+
<mat-list-item>
30+
@if ((jobs$ | async)?.length === 0) {
31+
<span i18n="No executions yet. Start by|No executions yet. Start by">No executions yet. Start by</span>
32+
<a mat-button color="primary" routerLink="/domains" i18n="Adding a domain|Adding a domain">adding domains</a
33+
><span>?</span>
34+
}
35+
</mat-list-item>
2636
</mat-list>`,
2737
})
2838
export class LatestJobs {
29-
public jobs$ = this.jobsService.getJobExecutions(0, 10).pipe(map((x) => x.items));
39+
public jobs$ = globalProjectFilter$.pipe(
40+
switchMap((project) => {
41+
const filters: any = {};
42+
if (project) filters.project = project.id;
43+
return this.jobsService.getJobExecutions(0, 10, filters).pipe(map((x) => x.items));
44+
})
45+
);
3046

3147
constructor(private jobsService: JobExecutionsService) {}
3248
}

packages/frontend/stalker-app/src/app/modules/dashboard/metric-styling.scss

+4
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,7 @@
1919
}
2020
}
2121
}
22+
23+
a {
24+
padding: 0;
25+
}

packages/frontend/stalker-app/src/app/modules/dashboard/number-of-domains-metric/number-of-domains-metric.component.ts

+9-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { CommonModule } from '@angular/common';
22
import { Component } from '@angular/core';
3-
import { map } from 'rxjs';
3+
import { map, switchMap } from 'rxjs';
44
import { DomainsService } from '../../../api/domains/domains.service';
5+
import { globalProjectFilter$ } from '../../../utils/global-project-filter';
56
import { SimpleMetric } from '../simple-metric/simple-metric.component';
67

78
@Component({
@@ -11,7 +12,13 @@ import { SimpleMetric } from '../simple-metric/simple-metric.component';
1112
imports: [CommonModule, SimpleMetric],
1213
})
1314
export class NumberOfDomainsMetric {
14-
public value$ = this.domainService.getPage(0, 1).pipe(map((x) => `${x.totalRecords}`));
15+
public value$ = globalProjectFilter$.pipe(
16+
switchMap((project) => {
17+
const projects = [];
18+
if (project) projects.push(project.id);
19+
return this.domainService.getPage(0, 1, { projects }).pipe(map((x) => `${x.totalRecords}`));
20+
})
21+
);
1522

1623
public get name() {
1724
return $localize`:Number of domains|:Number of domains`;

packages/frontend/stalker-app/src/app/modules/dashboard/number-of-hosts-metric/number-of-hosts-metric.component.ts

+9-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { CommonModule } from '@angular/common';
22
import { Component } from '@angular/core';
3-
import { map } from 'rxjs';
3+
import { map, switchMap } from 'rxjs';
44
import { HostsService } from '../../../api/hosts/hosts.service';
5+
import { globalProjectFilter$ } from '../../../utils/global-project-filter';
56
import { SimpleMetric } from '../simple-metric/simple-metric.component';
67

78
@Component({
@@ -11,7 +12,13 @@ import { SimpleMetric } from '../simple-metric/simple-metric.component';
1112
template: `<simple-metric [value]="value$ | async" [title]="name"></simple-metric>`,
1213
})
1314
export class NumberOfHostsMetric {
14-
public value$ = this.hostService.getPage(0, 1).pipe(map((x) => `${x.totalRecords}`));
15+
public value$ = globalProjectFilter$.pipe(
16+
switchMap((project) => {
17+
const projects = [];
18+
if (project) projects.push(project.id);
19+
return this.hostService.getPage(0, 1, { projects }).pipe(map((x) => `${x.totalRecords}`));
20+
})
21+
);
1522

1623
public get name() {
1724
return $localize`:Number of hosts|:Number of hosts`;

packages/frontend/stalker-app/src/app/modules/domains/list-domains/list-domains.component.ts

+19-5
Original file line numberDiff line numberDiff line change
@@ -20,25 +20,30 @@ import { DomainsService } from '../../../api/domains/domains.service';
2020
import { ProjectsService } from '../../../api/projects/projects.service';
2121
import { TagsService } from '../../../api/tags/tags.service';
2222
import { ProjectCellComponent } from '../../../shared/components/project-cell/project-cell.component';
23+
import { SharedModule } from '../../../shared/shared.module';
2324
import { Domain } from '../../../shared/types/domain/domain.interface';
2425
import { HttpStatus } from '../../../shared/types/http-status.type';
2526
import { Page } from '../../../shared/types/page.type';
27+
import { ProjectSummary } from '../../../shared/types/project/project.summary';
28+
import { Tag } from '../../../shared/types/tag.type';
2629
import {
2730
ElementMenuItems,
2831
FilteredPaginatedTableComponent,
2932
} from '../../../shared/widget/filtered-paginated-table/filtered-paginated-table.component';
30-
import { BlockedPillTagComponent } from '../../../shared/widget/pill-tag/blocked-pill-tag.component';
31-
import { SharedModule } from '../../../shared/shared.module';
32-
import { ProjectSummary } from '../../../shared/types/project/project.summary';
33-
import { Tag } from '../../../shared/types/tag.type';
3433
import {
3534
TABLE_FILTERS_SOURCE_INITAL_FILTERS,
3635
TableFilters,
3736
TableFiltersSource,
3837
TableFiltersSourceBase,
3938
} from '../../../shared/widget/filtered-paginated-table/table-filters-source';
4039
import { TableFormatComponent } from '../../../shared/widget/filtered-paginated-table/table-format/table-format.component';
40+
import { BlockedPillTagComponent } from '../../../shared/widget/pill-tag/blocked-pill-tag.component';
4141
import { defaultNewTimeMs } from '../../../shared/widget/pill-tag/new-pill-tag.component';
42+
import {
43+
getGlobalProjectFilter,
44+
globalProjectFilter$,
45+
hasGlobalProjectFilter,
46+
} from '../../../utils/global-project-filter';
4247
import { DomainsInteractionsService } from '../domains-interactions.service';
4348

4449
@Component({
@@ -91,7 +96,13 @@ export class ListDomainsComponent {
9196
tags$ = this.tagsService.getAllTags().pipe(shareReplay(1));
9297

9398
private refresh$ = new BehaviorSubject(null);
94-
dataSource$ = combineLatest([this.filtersSource.debouncedFilters$, this.projects$, this.tags$, this.refresh$]).pipe(
99+
dataSource$ = combineLatest([
100+
this.filtersSource.debouncedFilters$,
101+
this.projects$,
102+
this.tags$,
103+
this.refresh$,
104+
globalProjectFilter$,
105+
]).pipe(
95106
switchMap(([{ dateRange, filters, pagination }, projects, tags]) => {
96107
return this.domainsService.getPage(
97108
pagination?.page || 0,
@@ -201,6 +212,9 @@ export class ListDomainsComponent {
201212
break;
202213
}
203214
}
215+
216+
if (hasGlobalProjectFilter()) includedProjects.push(getGlobalProjectFilter()?.id);
217+
204218
if (includedTags.length) filterObject['tags'] = includedTags;
205219
if (includedDomains.length) filterObject['domains'] = includedDomains;
206220
if (includedHosts.length) filterObject['hosts'] = includedHosts;

packages/frontend/stalker-app/src/app/modules/hosts/list-hosts/list-hosts.component.ts

+20-7
Original file line numberDiff line numberDiff line change
@@ -16,29 +16,34 @@ import { Title } from '@angular/platform-browser';
1616
import { RouterModule } from '@angular/router';
1717
import { ToastrService } from 'ngx-toastr';
1818
import { BehaviorSubject, combineLatest, map, shareReplay, switchMap, tap } from 'rxjs';
19+
import { HostsService } from '../../../api/hosts/hosts.service';
1920
import { ProjectsService } from '../../../api/projects/projects.service';
2021
import { TagsService } from '../../../api/tags/tags.service';
2122
import { ProjectCellComponent } from '../../../shared/components/project-cell/project-cell.component';
23+
import { SharedModule } from '../../../shared/shared.module';
24+
import { Host } from '../../../shared/types/host/host.interface';
25+
import { HttpStatus } from '../../../shared/types/http-status.type';
2226
import { Page } from '../../../shared/types/page.type';
2327
import { ProjectSummary } from '../../../shared/types/project/project.summary';
28+
import { Tag } from '../../../shared/types/tag.type';
2429
import {
2530
ElementMenuItems,
2631
FilteredPaginatedTableComponent,
2732
} from '../../../shared/widget/filtered-paginated-table/filtered-paginated-table.component';
28-
import { BlockedPillTagComponent } from '../../../shared/widget/pill-tag/blocked-pill-tag.component';
29-
import { HostsService } from '../../../api/hosts/hosts.service';
30-
import { SharedModule } from '../../../shared/shared.module';
31-
import { Host } from '../../../shared/types/host/host.interface';
32-
import { HttpStatus } from '../../../shared/types/http-status.type';
33-
import { Tag } from '../../../shared/types/tag.type';
3433
import {
3534
TABLE_FILTERS_SOURCE_INITAL_FILTERS,
3635
TableFilters,
3736
TableFiltersSource,
3837
TableFiltersSourceBase,
3938
} from '../../../shared/widget/filtered-paginated-table/table-filters-source';
4039
import { TableFormatComponent } from '../../../shared/widget/filtered-paginated-table/table-format/table-format.component';
40+
import { BlockedPillTagComponent } from '../../../shared/widget/pill-tag/blocked-pill-tag.component';
4141
import { defaultNewTimeMs } from '../../../shared/widget/pill-tag/new-pill-tag.component';
42+
import {
43+
getGlobalProjectFilter,
44+
globalProjectFilter$,
45+
hasGlobalProjectFilter,
46+
} from '../../../utils/global-project-filter';
4247
import { HostsInteractionsService } from '../hosts-interactions.service';
4348

4449
@Component({
@@ -90,7 +95,12 @@ export class ListHostsComponent {
9095
tags$ = this.tagsService.getAllTags().pipe(shareReplay(1));
9196

9297
private refresh$ = new BehaviorSubject(null);
93-
dataSource$ = combineLatest([this.filtersSource.debouncedFilters$, this.tags$, this.refresh$]).pipe(
98+
dataSource$ = combineLatest([
99+
this.filtersSource.debouncedFilters$,
100+
this.tags$,
101+
this.refresh$,
102+
globalProjectFilter$,
103+
]).pipe(
94104
switchMap(([{ dateRange, filters, pagination }, tags]) => {
95105
return this.hostsService.getPage(
96106
pagination?.page || 0,
@@ -199,6 +209,9 @@ export class ListHostsComponent {
199209
break;
200210
}
201211
}
212+
213+
if (hasGlobalProjectFilter()) projects.push(getGlobalProjectFilter()?.id);
214+
202215
if (includedTags?.length) filterObject['tags'] = includedTags;
203216
if (domains?.length) filterObject['domains'] = domains;
204217
if (hosts?.length) filterObject['hosts'] = hosts;

packages/frontend/stalker-app/src/app/modules/ports/list-ports/list-ports.component.ts

+19-6
Original file line numberDiff line numberDiff line change
@@ -15,28 +15,33 @@ import { Title } from '@angular/platform-browser';
1515
import { RouterModule } from '@angular/router';
1616
import { ToastrService } from 'ngx-toastr';
1717
import { BehaviorSubject, combineLatest, map, shareReplay, switchMap, tap } from 'rxjs';
18+
import { PortsService } from '../../../api/ports/ports.service';
1819
import { ProjectsService } from '../../../api/projects/projects.service';
1920
import { TagsService } from '../../../api/tags/tags.service';
2021
import { ProjectCellComponent } from '../../../shared/components/project-cell/project-cell.component';
22+
import { SharedModule } from '../../../shared/shared.module';
2123
import { Page } from '../../../shared/types/page.type';
24+
import { Port } from '../../../shared/types/ports/port.interface';
2225
import { ProjectSummary } from '../../../shared/types/project/project.summary';
26+
import { Tag } from '../../../shared/types/tag.type';
2327
import {
2428
ElementMenuItems,
2529
FilteredPaginatedTableComponent,
2630
} from '../../../shared/widget/filtered-paginated-table/filtered-paginated-table.component';
27-
import { BlockedPillTagComponent } from '../../../shared/widget/pill-tag/blocked-pill-tag.component';
28-
import { PortsService } from '../../../api/ports/ports.service';
29-
import { SharedModule } from '../../../shared/shared.module';
30-
import { Port } from '../../../shared/types/ports/port.interface';
31-
import { Tag } from '../../../shared/types/tag.type';
3231
import {
3332
TABLE_FILTERS_SOURCE_INITAL_FILTERS,
3433
TableFilters,
3534
TableFiltersSource,
3635
TableFiltersSourceBase,
3736
} from '../../../shared/widget/filtered-paginated-table/table-filters-source';
3837
import { TableFormatComponent } from '../../../shared/widget/filtered-paginated-table/table-format/table-format.component';
38+
import { BlockedPillTagComponent } from '../../../shared/widget/pill-tag/blocked-pill-tag.component';
3939
import { defaultNewTimeMs } from '../../../shared/widget/pill-tag/new-pill-tag.component';
40+
import {
41+
getGlobalProjectFilter,
42+
globalProjectFilter$,
43+
hasGlobalProjectFilter,
44+
} from '../../../utils/global-project-filter';
4045
import { PortsInteractionsService } from '../ports-interactions.service';
4146

4247
@Component({
@@ -86,7 +91,12 @@ export class ListPortsComponent {
8691
allTags$ = this.tagsService.getAllTags().pipe(shareReplay(1));
8792

8893
private refresh$ = new BehaviorSubject(null);
89-
public ports$ = combineLatest([this.filtersSource.debouncedFilters$, this.allTags$, this.refresh$]).pipe(
94+
public ports$ = combineLatest([
95+
this.filtersSource.debouncedFilters$,
96+
this.allTags$,
97+
this.refresh$,
98+
globalProjectFilter$,
99+
]).pipe(
90100
switchMap(([{ filters, dateRange, pagination }, tags]) => {
91101
return this.portsService.getPage<Port>(
92102
pagination?.page ?? 0,
@@ -193,6 +203,9 @@ export class ListPortsComponent {
193203
break;
194204
}
195205
}
206+
207+
if (hasGlobalProjectFilter()) projects.push(getGlobalProjectFilter()?.id);
208+
196209
if (includedTags?.length) filterObject['tags'] = includedTags;
197210
if (ports?.length) filterObject['ports'] = ports;
198211
if (hosts?.length) filterObject['hosts'] = hosts;

0 commit comments

Comments
 (0)