Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { UsageComponent } from './pages/usage/usage.component';
import { TeamsComponent } from './pages/teams/teams.component';
import { RoadmapComponent } from './pages/roadmap/roadmap.component';
import { SettingsComponent } from './pages/settings/settings.component';
import { ReportComponent } from './pages/report/report.component';

const routes: Routes = [
{ path: '', component: CircularHeatmapComponent },
Expand All @@ -24,6 +25,7 @@ const routes: Routes = [
{ path: 'userday', component: UserdayComponent },
{ path: 'roadmap', component: RoadmapComponent },
{ path: 'settings', component: SettingsComponent },
{ path: 'report', component: ReportComponent },
];

@NgModule({
Expand Down
6 changes: 6 additions & 0 deletions src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { ReactiveFormsModule, FormsModule } from '@angular/forms';
import { MatToolbarModule } from '@angular/material/toolbar';
import { MatMenuModule } from '@angular/material/menu';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
Expand Down Expand Up @@ -31,6 +32,8 @@ import { ProgressSliderComponent } from './component/progress-slider/progress-sl
import { KpiComponent } from './component/kpi/kpi.component';
import { MatDialogModule, MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { TeamsGroupsEditorModule } from './component/teams-groups-editor/teams-groups-editor.module';
import { ReportComponent } from './pages/report/report.component';
import { ReportConfigModalComponent } from './component/report-config-modal/report-config-modal.component';

@NgModule({
declarations: [
Expand All @@ -55,6 +58,8 @@ import { TeamsGroupsEditorModule } from './component/teams-groups-editor/teams-g
ProgressSliderComponent,
KpiComponent,
SettingsComponent,
ReportComponent,
ReportConfigModalComponent,
],
imports: [
BrowserModule,
Expand All @@ -64,6 +69,7 @@ import { TeamsGroupsEditorModule } from './component/teams-groups-editor/teams-g
MatDialogModule,
ReactiveFormsModule,
MatToolbarModule,
MatMenuModule,
FormsModule,
HttpClientModule,
TeamsGroupsEditorModule,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
.config-content {
max-height: 70vh;
overflow-y: auto;
padding: 0 40px;
background-color: var(--background-primary);
}

mat-dialog-title{
font-size:20px;
}

.config-section {
padding: 16px 0;
}

.config-row {
display: flex;
align-items: center;
gap: 12px;
margin-bottom: 12px;
margin-top: 12px;
}

.config-row-label {
font-size: 0.95em;
white-space: nowrap;
}

.slider-row {
flex-direction: column;
align-items: flex-start;
gap: 4px;
}

.word-cap-slider {
width: 100%;
}

.config-section h3 {
margin: 0 0 4px 0;
font-size: 1.1em;
font-weight: 500;
}

.config-hint {
margin: 0 0 12px 0;
font-size: 0.85em;
color: var(--text-secondary);
}

.select-all-actions {
display: flex;
gap: 8px;
margin-bottom: 8px;
}

.checkbox-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 8px;
}

.search-field {
width: 80%;
margin-bottom: 8px;
}

.activity-list {
display: flex;
flex-direction: column;
gap: 4px;
max-height: 300px;
overflow-y: auto;
padding: 4px 0;
border: 1px solid var(--text-tertiary);
border-radius: 4px;
padding: 8px;
}

.activity-checkbox-label {
display: flex;
flex-direction: column;
}

.activity-name {
font-weight: 500;
}

.activity-meta {
font-size: 0.8em;
color: var(--text-secondary);
}

mat-divider {
margin: 4px 0;
}

.column-toggle {
border-radius: 999px;
padding: 2px;
border: 1px solid var(--text-tertiary);
background: var(--background-secondary);
}

/* buttons */
.column-toggle .mat-button-toggle {
border-radius: 999px;
border: none;
padding: 0 16px;
color: var(--text-secondary);
background: transparent;
}

/* selected */
.column-toggle .mat-button-toggle-checked {
background: var(--primary-color);
color: var(--text-on-primary);
box-shadow: 0 2px 6px rgba(0,0,0,0.25);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
<h2 mat-dialog-title align="center">Report Configuration</h2>

<mat-dialog-content class="config-content">
<!-- Display Configuration -->
<div class="config-section">
<h3>Display Configuration</h3>

<div class="config-row">
<span class="config-row-label">Column Grouping:</span>
<mat-button-toggle-group
class="column-toggle"
[value]="config.columnGrouping"
(change)="setColumnGrouping($event.value)">
<mat-button-toggle value="byProgress">By Progress Stage</mat-button-toggle>
<mat-button-toggle value="byTeam">By Team</mat-button-toggle>
</mat-button-toggle-group>
</div>

<mat-checkbox [checked]="config.showDescription" (change)="toggleAttribute('showDescription')">
Show Description
</mat-checkbox>

<div class="config-row slider-row" *ngIf="config.showDescription">
<span class="config-row-label"
>Description Word Cap: <strong>{{ config.descriptionWordCap }}</strong></span
>
<mat-slider
class="word-cap-slider"
min="5"
[max]="maxWordCap"
step="5"
thumbLabel
[displayWith]="wordCapLabel"
[value]="config.descriptionWordCap"
(input)="onWordCapChange($event)">
</mat-slider>
</div>
</div>

<mat-divider></mat-divider>

<!-- Teams -->
<div class="config-section">
<h3>Teams</h3>
<p class="config-hint">Select which teams to include in the report.</p>
<div class="select-all-actions">
<button mat-button color="primary" (click)="selectAllTeams()">Select All</button>
<button mat-button (click)="deselectAllTeams()">Deselect All</button>
<button
*ngIf="groupNames.length > 0"
mat-stroked-button
[matMenuTriggerFor]="groupMenu"
class="group-dropdown-btn">
<mat-icon>group</mat-icon>
Select Group
<mat-icon>arrow_drop_down</mat-icon>
</button>
<mat-menu #groupMenu="matMenu">
<button mat-menu-item *ngFor="let group of groupNames" (click)="selectGroup(group)">
{{ group }}
</button>
</mat-menu>
</div>
<div class="checkbox-grid">
<mat-checkbox
*ngFor="let team of allTeams"
[checked]="isTeamSelected(team)"
(change)="toggleTeam(team)">
{{ team }}
</mat-checkbox>
</div>
</div>

<mat-divider></mat-divider>

<!-- Dimensions -->
<div class="config-section">
<h3>Dimensions</h3>
<p class="config-hint">Uncheck dimensions to exclude all their activities.</p>
<div class="checkbox-grid">
<mat-checkbox
*ngFor="let dim of allDimensions"
[checked]="!isDimensionExcluded(dim)"
(change)="toggleDimension(dim)">
{{ dim }}
</mat-checkbox>
</div>
</div>

<mat-divider></mat-divider>

<!-- Subdimensions -->
<div class="config-section">
<h3>Subdimensions</h3>
<p class="config-hint">Uncheck subdimensions to exclude their activities.</p>
<div class="checkbox-grid subdimension-grid">
<mat-checkbox
*ngFor="let subdim of allSubdimensions"
[checked]="!isSubdimensionExcluded(subdim)"
(change)="toggleSubdimension(subdim)">
{{ subdim }}
</mat-checkbox>
</div>
</div>

<mat-divider></mat-divider>

<!-- Individual Activities -->
<div class="config-section">
<h3>Individual Activities</h3>
<p class="config-hint">Search and uncheck individual activities to exclude them.</p>
<mat-form-field appearance="outline" class="search-field">
<mat-label>Search activities or dimensions</mat-label>
<input matInput [(ngModel)]="activitySearchQuery" placeholder="Type to filter..." />
<mat-icon matSuffix>search</mat-icon>
</mat-form-field>
<div class="activity-list">
<mat-checkbox
*ngFor="let activity of filteredActivities"
[checked]="!isActivityExcluded(activity.uuid)"
(change)="toggleActivity(activity.uuid)">
<span class="activity-checkbox-label">
<span class="activity-name">{{ activity.name }}</span>
<span class="activity-meta">{{ activity.dimension }} · Level {{ activity.level }}</span>
</span>
</mat-checkbox>
</div>
</div>

<mat-divider></mat-divider>
</mat-dialog-content>

<mat-dialog-actions align="end">
<button mat-button (click)="onCancel()">Cancel</button>
<button mat-raised-button color="primary" (click)="onSave()">
Save Configuration and Generate Report
</button>
</mat-dialog-actions>
Loading