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
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ <h2 mat-dialog-title align="center">Add Evidence</h2>

<mat-dialog-content class="config-content">
<app-team-selector
[allTeams]="allTeams"
[(selectedTeams)]="selectedTeams"
[teamGroups]="teamGroups"
[allTeams]="teamSelection.allTeams()"
[selectedTeams]="selectedTeams"
[teamGroups]="teamSelection.teamGroups()"
(selectedTeamsChange)="onSelectedTeamsChange($event)"
[type]="'add-evidence-config'">
</app-team-selector>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Component, inject, ChangeDetectionStrategy } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef, MatDialogModule } from '@angular/material/dialog';
import { EvidenceEntry, EvidenceStore } from '../../model/evidence-store';
import { TeamGroups } from '../../model/types';
import { TeamSelectionService } from '../../service/team-selection.service';
import { MatIconModule } from '@angular/material/icon';
import { MatTooltipModule } from '@angular/material/tooltip';
import { MatButtonModule } from '@angular/material/button';
Expand All @@ -16,8 +16,6 @@ import { TeamSelectorComponent } from '../team-selector/team-selector.component'

export interface AddEvidenceModalData {
activityUuid: string;
allTeams: string[];
teamGroups: TeamGroups;
}

@Component({
Expand All @@ -42,10 +40,9 @@ export interface AddEvidenceModalData {
export class AddEvidenceModalComponent {
dialogRef = inject<MatDialogRef<AddEvidenceModalComponent>>(MatDialogRef);
data = inject<AddEvidenceModalData>(MAT_DIALOG_DATA);
readonly teamSelection = inject(TeamSelectionService);

activityUuid: string;
allTeams: string[];
teamGroups: TeamGroups;

// Form fields
selectedTeams: string[] = [];
Expand All @@ -66,8 +63,7 @@ export class AddEvidenceModalComponent {
const data = this.data;

this.activityUuid = data.activityUuid;
this.allTeams = data.allTeams;
this.teamGroups = data.teamGroups || {};
this.selectedTeams = [...this.teamSelection.effectiveTeams()];
}

onSelectedTeamsChange(teams: string[]): void {
Expand Down
11 changes: 10 additions & 1 deletion src/app/component/evidence-panel/evidence-panel.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
} from '@angular/core';
import { EvidenceEntry } from '../../model/evidence-store';
import { LoaderService } from '../../service/loader/data-loader.service';
import { TeamSelectionService } from '../../service/team-selection.service';
import { MatIconModule } from '@angular/material/icon';
import { MatExpansionModule } from '@angular/material/expansion';
import { DatePipe } from '@angular/common';
Expand All @@ -21,6 +22,7 @@ import { DatePipe } from '@angular/common';
})
export class EvidencePanelComponent implements OnChanges {
private loader = inject(LoaderService);
private teamSelection = inject(TeamSelectionService);

@Input() activityUuid: string = '';
@Input() expanded: boolean = false;
Expand Down Expand Up @@ -53,16 +55,23 @@ export class EvidencePanelComponent implements OnChanges {

this.evidenceEntries = evidenceStore.getEvidence(this.activityUuid);

const effectiveTeams = new Set(this.teamSelection.effectiveTeams());

// Group evidence entries by team name
for (const entry of this.evidenceEntries) {
for (const teamName of entry.teams) {
if (!effectiveTeams.has(teamName)) continue;
if (!this.evidenceByTeam.has(teamName)) {
this.evidenceByTeam.set(teamName, []);
}
this.evidenceByTeam.get(teamName)!.push(entry);
}
}

this.teamsWithEvidence = Array.from(this.evidenceByTeam.keys());
// Evidence entries can be entered in any order. Display the teams using the
// configured order, while omitting teams without evidence for this activity.
this.teamsWithEvidence = this.teamSelection
.effectiveTeams()
.filter(teamName => this.evidenceByTeam.has(teamName));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -256,9 +256,10 @@ <h3>Individual Activities</h3>
<!-- Teams -->
<app-team-selector
[allTeams]="allTeams"
[selectedTeams]="config().selectedTeams"
(selectedTeamsChange)="onTeamsChanged($event)"
[teamGroups]="teamGroups"></app-team-selector>
[selectedTeams]="selectedTeams"
(selectedTeamsChange)="onSelectedTeamsChange($event)"
[teamGroups]="teamGroups">
</app-team-selector>

<mat-divider></mat-divider>
</mat-dialog-content>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { MatButtonToggleModule } from '@angular/material/button-toggle';

export interface ReportConfigModalData {
config: ReportConfig;
selectedTeams: string[];
allActivities: Activity[];
allTeams: string[];
allDimensions: string[];
Expand All @@ -31,6 +32,11 @@ export interface ReportConfigModalData {
teamGroups: TeamGroups;
}

export interface ReportConfigModalResult {
config: ReportConfig;
selectedTeams: string[];
}

@Component({
selector: 'app-report-config-modal',
templateUrl: './report-config-modal.component.html',
Expand All @@ -57,11 +63,12 @@ export class ReportConfigModalComponent {

config = signal<ReportConfig>(JSON.parse(JSON.stringify({})));
allActivities: Activity[];
allTeams: string[];
allTeams: string[] = [];
allDimensions: string[];
allSubdimensions: string[];
allProgressTitles: ProgressTitle[];
teamGroups: TeamGroups;
teamGroups: TeamGroups = {};
selectedTeams: string[] = [];
activitySearchQuery = signal('');
maxWordCap: number = MAX_DESCRIPTION_WORD_CAP;

Expand All @@ -86,11 +93,12 @@ export class ReportConfigModalComponent {
// Deep copy config to avoid mutating the original until save
this.config.set(JSON.parse(JSON.stringify(data.config)));
this.allActivities = data.allActivities;
this.allTeams = data.allTeams;
this.allTeams = [...data.allTeams];
this.allDimensions = data.allDimensions;
this.allSubdimensions = data.allSubdimensions;
this.allProgressTitles = data.allProgressTitles || [];
this.teamGroups = data.teamGroups || {};
this.teamGroups = { ...data.teamGroups };
this.selectedTeams = [...data.selectedTeams];
}

setColumnGrouping(grouping: ColumnGrouping): void {
Expand Down Expand Up @@ -172,13 +180,13 @@ export class ReportConfigModalComponent {
});
}

onTeamsChanged(teams: string[]): void {
this.config.update(c => ({ ...c, selectedTeams: teams }));
onSelectedTeamsChange(teams: string[]): void {
this.selectedTeams = teams;
}

// --- Actions ---
onSave(): void {
this.dialogRef.close(this.config());
this.dialogRef.close({ config: this.config(), selectedTeams: this.selectedTeams });
}

onCancel(): void {
Expand Down
39 changes: 21 additions & 18 deletions src/app/component/team-selector/team-selector.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,42 +21,45 @@ export class TeamSelectorComponent {

@Output() selectedTeamsChange = new EventEmitter<string[]>();

selectedGroupName: string = '';

isTeamSelected(team: string): boolean {
return this.selectedTeams.includes(team);
}

toggleTeam(team: string): void {
const idx = this.selectedTeams.indexOf(team);
if (idx >= 0) {
this.selectedTeams.splice(idx, 1);
const teams = [...this.selectedTeams];
const index = teams.indexOf(team);
if (index >= 0) {
teams.splice(index, 1);
} else {
this.selectedTeams.push(team);
teams.push(team);
}
this.selectedGroupName = '';
this.selectedTeamsChange.emit([...this.selectedTeams]);
this.selectedTeamsChange.emit(teams);
}

selectAllTeams(): void {
this.selectedTeams = [...this.allTeams];
this.selectedGroupName = '';
this.selectedTeamsChange.emit([...this.selectedTeams]);
this.selectedTeamsChange.emit([...this.allTeams]);
}

deselectAllTeams(): void {
this.selectedTeams = [];
this.selectedGroupName = '';
this.selectedTeamsChange.emit([...this.selectedTeams]);
this.selectedTeamsChange.emit([]);
}

get groupNames(): string[] {
return Object.keys(this.teamGroups);
return Object.keys(this.teamGroups).filter(group => this.teamGroups[group].length > 0);
}

selectGroup(group: string): void {
this.selectedTeams = [...(this.teamGroups[group] || [])];
this.selectedGroupName = group;
this.selectedTeamsChange.emit([...this.selectedTeams]);
this.selectedTeamsChange.emit([...(this.teamGroups[group] || [])]);
}

get selectedGroupName(): string {
const selected = new Set(this.selectedTeams);
for (const group of this.groupNames) {
const teams = this.teamGroups[group];
if (teams.length === selected.size && teams.every(team => selected.has(team))) {
return group;
}
}
return '';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@
margin-left: 0.5rem;
}

.selectable-list .item-actions button {
margin-left: 0.25rem;
}

.selectable-list .edit-hint {
font-weight: normal;
font-size: 0.8em;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,21 @@ <h2>{{ title }}</h2>
<span>{{ name }}</span>
}
@if (editMode) {
<span>
<span class="item-actions">
<button
mat-icon-button
[disabled]="items.indexOf(name) === 0"
(click)="moveItemUp(name); $event.stopPropagation()"
title="Move {{ name }} up">
<mat-icon>arrow_upward</mat-icon>
</button>
<button
mat-icon-button
[disabled]="items.indexOf(name) === items.length - 1"
(click)="moveItemDown(name); $event.stopPropagation()"
title="Move {{ name }} down">
<mat-icon>arrow_downward</mat-icon>
</button>
<button mat-icon-button (click)="startEditItem(name)" title="Rename {{ name }}">
<mat-icon class="material-icons-outlined">edit</mat-icon>
</button>
Expand Down
16 changes: 16 additions & 0 deletions src/app/component/teams-groups-editor/selectable-list.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ import { FormsModule } from '@angular/forms';
import { MatIconModule } from '@angular/material/icon';
import { MatButtonModule } from '@angular/material/button';

export type MoveDirection = 'up' | 'down';

export interface MoveItemEvent {
name: string;
direction: MoveDirection;
}

@Component({
selector: 'app-selectable-list',
templateUrl: './selectable-list.component.html',
Expand All @@ -35,6 +42,7 @@ export class SelectableListComponent {
@Output() save = new EventEmitter<void>();
@Output() renameItem = new EventEmitter<{ oldName: string; newName: string }>();
@Output() deleteItem = new EventEmitter<string>();
@Output() moveItem = new EventEmitter<MoveItemEvent>();
@Output() relationshipToggle = new EventEmitter<string>();
@Output() editModeChange = new EventEmitter<boolean>();

Expand Down Expand Up @@ -102,4 +110,12 @@ export class SelectableListComponent {
this.onItemClicked(this.items[index - 1]);
}
}

moveItemUp(name: string): void {
this.moveItem.emit({ name, direction: 'up' });
}

moveItemDown(name: string): void {
this.moveItem.emit({ name, direction: 'down' });
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
(addItem)="onAddGroup()"
(renameItem)="onRenameGroup($event)"
(deleteItem)="onDeleteGroup($event)"
(moveItem)="onMoveGroup($event)"
(editModeChange)="onGroupsEditModeChange($event)"
(relationshipToggle)="onTeamGroupToggle(selectedTeam, $event)"
(save)="onSave()"
Expand All @@ -31,6 +32,7 @@
(addItem)="onAddTeam()"
(renameItem)="onRenameTeam($event)"
(deleteItem)="onDeleteTeam($event)"
(moveItem)="onMoveTeam($event)"
(editModeChange)="onTeamsEditModeChange($event)"
(relationshipToggle)="onTeamGroupToggle($event, selectedGroup)"
(save)="onSave()"
Expand Down
Loading
Loading