Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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 @@ -76,8 +76,8 @@ <h4 class="header-text ms-2">Edit View: {{ view.name }}</h4>
<div class="add-margin">
<div>
<mat-form-field>
<mat-label>Status</mat-label>
<mat-select
placeholder="Status"
[(ngModel)]="view.status"
name="viewStatus"
(selectionChange)="saveViewStatus()"
Expand Down Expand Up @@ -129,7 +129,7 @@ <h4 class="header-text ms-2">Edit View: {{ view.name }}</h4>
</button>
</mat-menu>
<mat-menu #viewAppTemplates="matMenu">
@for (t of applicationTemplates; track t) {
@for (t of applicationTemplates; track t.id) {
<button mat-menu-item (click)="addViewApplication(t)">
{{ t.name }}
</button>
Expand Down Expand Up @@ -157,7 +157,7 @@ <h4 class="header-text ms-2">Edit View: {{ view.name }}</h4>
Add New Team
</button>
</div>
@for (teamContainer of teams; track teamContainer) {
@for (teamContainer of teams; track teamContainer.team.id) {
<mat-expansion-panel
[expanded]="
currentTeam !== undefined &&
Expand All @@ -168,6 +168,9 @@ <h4 class="header-text ms-2">Edit View: {{ view.name }}</h4>
<mat-expansion-panel-header>
<mat-panel-title>
{{ teamContainer.name }}
@if (view.defaultTeamId === teamContainer.team.id) {
<span class="default-badge">DEFAULT</span>
}
</mat-panel-title>
</mat-expansion-panel-header>
<div class="d-flex">
Expand All @@ -190,11 +193,11 @@ <h4 class="header-text ms-2">Edit View: {{ view.name }}</h4>
</span>
</div>
<mat-form-field>
<mat-label>Team Name (required)</mat-label>
<input
id="teamName{{ teamContainer.team.id }}"
matInput
[formControl]="teamNameFormControl"
placeholder="Team Name"
(change)="
saveTeamName(
$event.target.value,
Expand Down Expand Up @@ -304,44 +307,61 @@ <h4 class="header-text ms-2">Edit View: {{ view.name }}</h4>
}
@if (staged.length !== 0) {
<div
class="top-button d-flex justify-content-end align-items-center"
class="top-button d-flex justify-content-end align-items-start"
>
<mat-list>
@for (playerFile of staged; track playerFile) {
<mat-list-item>
{{ playerFile.file.name }}
<div>
<button
mat-icon-button
(click)="removeFile(playerFile)"
>
<mat-icon
style="transform: scale(0.85)"
svgIcon="ic_clear_black_24px"
></mat-icon>
</button>
</div>
</mat-list-item>
<div class="staged-files-list">
@for (playerFile of staged; track playerFile.file.name) {
<div class="staged-file-item">
<button
mat-icon-button
(click)="removeFile(playerFile)"
title="Remove file"
>
<mat-icon
class="mdi-24px"
fontIcon="mdi-delete"
[ngStyle]="{'color': 'var(--mat-sys-primary)'}"
></mat-icon>
</button>
<span class="file-name">{{ playerFile.file.name }}</span>
</div>
}
</div>
<div class="d-flex flex-column">
<div class="d-flex align-items-center">
<mat-checkbox
color="primary"
[(ngModel)]="selectAllTeamsForFile"
(change)="toggleAllTeamsForFile($event.checked)"
class="me-3"
>
Select All Teams
</mat-checkbox>
<mat-form-field id="teamSelect">
<mat-label>Select Teams</mat-label>
<mat-select multiple [(ngModel)]="teamsForFile" (selectionChange)="onTeamsForFileChange()">
@for (teamWrapper of teams; track teamWrapper.team.id) {
<mat-option [value]="teamWrapper.team.id">{{
teamWrapper.team.name
}}</mat-option>
}
</mat-select>
</mat-form-field>
<button
mat-stroked-button
(click)="uploadFile()"
class="ms-3"
style="height: 35px"
[disabled]="teamsForFile.length === 0"
>
Save Changes and Upload File
Comment thread
sei-awelle marked this conversation as resolved.
Outdated
</button>
</div>
@if (teamsForFile.length === 0) {
<div class="team-warning">
At least one team must be selected
</div>
}
</mat-list>
<div>
<mat-form-field id="teamSelect">
<mat-label>Select Teams</mat-label>
<mat-select multiple [(ngModel)]="teamsForFile">
@for (teamWrapper of teams; track teamWrapper) {
<mat-option [value]="teamWrapper.team.id">{{
teamWrapper.team.name
}}</mat-option>
}
</mat-select>
</mat-form-field>
<button
mat-stroked-button
(click)="uploadFile()"
style="height: 35px"
>
Upload File
</button>
@if (uploading) {
<mat-progress-bar
mode="determinate"
Expand All @@ -353,7 +373,7 @@ <h4 class="header-text ms-2">Edit View: {{ view.name }}</h4>
}
</div>
</div>
@for (viewFile of viewFiles; track viewFile) {
@for (viewFile of viewFiles; track viewFile.id) {
<mat-expansion-panel
[expanded]="
currentFile !== undefined && viewFile.id === currentFile.id
Expand All @@ -372,23 +392,38 @@ <h4 class="header-text ms-2">Edit View: {{ view.name }}</h4>
</mat-panel-title>
</mat-expansion-panel-header>
<div>
<div class="d-flex justify-content-around">
<mat-form-field id="teamSelect" style="width: 600px">
<mat-label>Teams with Permission to View</mat-label>
<mat-select
multiple
[ngModel]="viewFile.teamIds"
(selectionChange)="
teamsForFileUpdated($event, viewFile)
"
<div class="d-flex flex-column align-items-center">
<div class="d-flex align-items-center">
<mat-checkbox
color="primary"
[checked]="isAllTeamsSelected(viewFile)"
(change)="toggleAllTeamsForViewFile($event.checked, viewFile)"
class="me-3"
>
@for (teamWrapper of teams; track teamWrapper) {
<mat-option [value]="teamWrapper.team.id">{{
teamWrapper.team.name
}}</mat-option>
}
</mat-select>
</mat-form-field>
Select All Teams
</mat-checkbox>
<mat-form-field id="teamSelect" style="width: 600px">
<mat-label>Teams with Permission to View</mat-label>
<mat-select
multiple
[ngModel]="viewFile.teamIds"
(selectionChange)="
teamsForFileUpdated($event, viewFile)
"
>
@for (teamWrapper of teams; track teamWrapper.team.id) {
<mat-option [value]="teamWrapper.team.id">{{
teamWrapper.team.name
}}</mat-option>
}
</mat-select>
</mat-form-field>
</div>
@if (viewFile.teamIds && viewFile.teamIds.length === 0) {
<div class="team-warning">
At least one team must be selected
</div>
}
</div>
<div class="d-flex justify-content-around">
<button
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,42 @@
.view-info-container {
margin-left: 20%;
}

.staged-files-list {
display: flex;
flex-direction: column;
gap: 8px;
}

.staged-file-item {
display: flex;
align-items: center;
gap: 8px;
padding: 4px 0;

.file-name {
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}

.default-badge {
display: inline-block;
padding: 2px 8px;
margin-left: 8px;
font-size: 11px;
font-weight: 600;
text-transform: uppercase;
border-radius: 4px;
background-color: var(--mat-sys-primary-container);
color: var(--mat-sys-on-primary-container);
}

.team-warning {
color: var(--mat-sys-error);
font-size: 12px;
margin-top: 4px;
font-weight: 500;
}
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ export class AdminViewEditComponent implements OnInit {

public staged: PlayerFile[];
public teamsForFile: string[];
public selectAllTeamsForFile: boolean;
public uploadProgess: number;
public uploading: boolean;
public viewFiles: FileModel[];
Expand Down Expand Up @@ -490,6 +491,30 @@ export class AdminViewEditComponent implements OnInit {
this.staged = this.staged.filter((f) => f.file.name !== file.file.name);
}

/**
* Toggles selection of all teams for file upload
*
* @param checked: Whether all teams should be selected
*/
toggleAllTeamsForFile(checked: boolean) {
if (checked) {
this.teamsForFile = this.teams.map(t => t.team.id);
} else {
this.teamsForFile = [];
}
}

/**
* Handles manual changes to team selection
* Unchecks "Select All" if not all teams are selected
*/
onTeamsForFileChange() {
const allTeamIds = this.teams.map(t => t.team.id);
const allSelected = allTeamIds.length === this.teamsForFile.length &&
allTeamIds.every(id => this.teamsForFile.includes(id));
this.selectAllTeamsForFile = allSelected;
}

/**
* Returns a link to the download endpoint for a particular file
*/
Expand Down Expand Up @@ -649,11 +674,59 @@ export class AdminViewEditComponent implements OnInit {
* @param file The file to update the teams for
*/
teamsForFileUpdated(event: any, file: FileModel) {
file.teamIds = event.value;
const newTeamIds = event.value;

// Update local state to reflect selection
file.teamIds = newTeamIds || [];

// Only save to server if at least one team is selected
if (!newTeamIds || newTeamIds.length === 0) {
return;
}

this.fileService
.updateFile(file.id, file.name, file.teamIds, null)
.pipe(take(1))
.subscribe();
.subscribe({
error: (err) => {
console.error('Error updating file teams:', err);
}
});
}

/**
* Checks if all teams are selected for a given file
* @param file The file to check
*/
isAllTeamsSelected(file: FileModel): boolean {
if (!file.teamIds || !this.teams) {
return false;
}
const allTeamIds = this.teams.map(t => t.team.id);
return allTeamIds.length === file.teamIds.length &&
allTeamIds.every(id => file.teamIds.includes(id));
}

/**
* Toggles selection of all teams for a specific file
* @param checked Whether all teams should be selected
* @param file The file to update
*/
toggleAllTeamsForViewFile(checked: boolean, file: FileModel) {
if (checked) {
file.teamIds = this.teams.map(t => t.team.id);
this.fileService
.updateFile(file.id, file.name, file.teamIds, null)
.pipe(take(1))
.subscribe({
error: (err) => {
console.error('Error updating file teams:', err);
}
});
} else {
// Allow clearing teams in UI, but don't save until at least one team is selected
file.teamIds = [];
}
}

/**
Expand Down
Loading
Loading