Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Budget Name </th>
<td mat-cell *matCellDef="let row">
{{row.name ? row.name : '-' }} <span *ngIf="row.childrenList?.length > 0" class="badge primary"
(click)="openChildBudgetDialog(row)"> Linked Budgets ({{ row?.childrenList?.length }}) </span>
{{row.name ? row.name : '-' }}
@if (row.childrenList?.length > 0) {
<span class="badge primary" (click)="openChildBudgetDialog(row)">
Linked Budgets ({{ row?.childrenList?.length }})
</span>
}
</td>
</ng-container>

Expand All @@ -28,7 +32,12 @@
<!-- Duration Column -->
<ng-container matColumnDef="duration">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Duration (Years) </th>
<td mat-cell *matCellDef="let row"> {{row.duration ? row.duration : '-' }} </td>
<td mat-cell *matCellDef="let row">
{{row.duration ? row.duration : '-' }}
@if (row.startYear && row.duration) {
({{ row.startYear }}-{{ row.startYear + row.duration - 1 }})
}
</td>
</ng-container>

<!-- actions Column -->
Expand All @@ -37,41 +46,37 @@
<td mat-cell *matCellDef="let row">
<div class="budget-btn-container" fxLayout="row" fxLayoutALign="start center" fxLayoutGap="10px">

<button color="primary" class="secondary-action" mat-mini-fab (click)="openCloneBudgetDialog(row)"
matTooltip="{{ 'BUDGET.VIEW-RECORD.ACTIONS.CLONE'| transloco }}" *ngIf="access('clone')">
<i class="fas fa-copy fa-sm"></i>
</button>

<button color="primary" class="secondary-action" mat-mini-fab
matTooltip="{{'BUDGET.VIEW-RECORD.ACTIONS.VIEW' | transloco}}" (click)="goToDetail(row.id!, 'view')"
*ngIf="access('view')">
<i class="fas fa-eye fa-sm"></i>
</button>
@if (access('clone')) {
<button color="primary" class="secondary-action" mat-mini-fab (click)="openCloneBudgetDialog(row)"
matTooltip="{{ 'BUDGET.VIEW-RECORD.ACTIONS.CLONE'| transloco }}">
<i class="fas fa-copy fa-sm"></i>
</button>
}

<button color="primary" mat-mini-fab matTooltip="{{ 'BUDGET.VIEW-RECORD.ACTIONS.EDIT' | transloco }}"
color="primary" (click)="goToDetail(row.id!, 'edit')" *ngIf="access('edit')">
<i class="fas fa-edit fa-sm"></i>
</button>
@if (access('view')) {
<button color="primary" class="secondary-action" mat-mini-fab
matTooltip="{{'BUDGET.VIEW-RECORD.ACTIONS.VIEW' | transloco}}" (click)="goToDetail(row.id!, 'view')">
<i class="fas fa-eye fa-sm"></i>
</button>
}

<!-- <button color="primary" class="secondary-action"
matTooltip="{{ 'BUDGET.VIEW-RECORD.ACTIONS.SHARE' | transloco }}" mat-mini-fab
(click)="openShareBudgetDialog(row)">
<i class="fas fa-share-alt fa-sm"></i>
</button> -->
@if (access('edit')) {
<button color="primary" mat-mini-fab matTooltip="{{ 'BUDGET.VIEW-RECORD.ACTIONS.EDIT' | transloco }}"
color="primary" (click)="goToDetail(row.id!, 'edit')">
<i class="fas fa-edit fa-sm"></i>
</button>
}

<button color="primary" class="delete-btn" matTooltip="Delete" mat-mini-fab
(click)="openShareBudgetDialog(row)">
<i class="fas fa-trash-alt fa-sm"></i>
</button>

<!-- Will only be true on parent since does not get cascaded down below. -->
<!-- <div class="budget-btn-container" style="float: right; text-align: right">
<button class="btn-promote" (click)="promote()">{{ 'BUDGET.VIEW-RECORD.PROMOTE' | transloco }}</button>
</div> -->
</div>
</td>
</ng-container>

<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>

<mat-paginator [pageSizeOptions]="[10, 25, 100]" aria-label="Select page of users"></mat-paginator>
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import { Component, EventEmitter, Input, Output, ViewChild } from '@angular/core';
import { MatTable, MatTableDataSource } from '@angular/material/table';
import { Component, Input, Output, EventEmitter, ViewChild, inject, signal, computed, effect } from '@angular/core';
import { MatTableDataSource } from '@angular/material/table';
import { MatPaginator } from '@angular/material/paginator';
import { MatDialog } from '@angular/material/dialog';
import { MatSort } from '@angular/material/sort';
import { Router } from '@angular/router';

import { SubSink } from 'subsink';
import { Observable, tap } from 'rxjs';

import { Budget, BudgetRecord } from '@app/model/finance/planning/budgets';

import { ShareBudgetModalComponent } from '../share-budget-modal/share-budget-modal.component';
Expand All @@ -18,57 +15,52 @@ import { ChildBudgetsModalComponent } from '../../modals/child-budgets-modal/chi
selector: 'app-budget-table',
templateUrl: './budget-table.component.html',
styleUrls: ['./budget-table.component.scss'],
standalone: true,
})

export class BudgetTableComponent {
private _router$$ = inject(Router);
private _dialog = inject(MatDialog);

private _sbS = new SubSink();

@Input() budgets$: Observable<{overview: BudgetRecord[], budgets: any[]}>;
// Convert Observable input to signal-based input
@Input() budgets: { overview: BudgetRecord[], budgets: any[] } = { overview: [], budgets: [] };

@Input() canPromote = false;
@Output() doPromote = new EventEmitter<void>();

@Output() doPromote: EventEmitter<void> = new EventEmitter();

dataSource = new MatTableDataSource();

dataSource = new MatTableDataSource<any>();
displayedColumns: string[] = ['name', 'status', 'startYear', 'duration', 'actions'];

@ViewChild(MatPaginator) paginator: MatPaginator;
@ViewChild('sort', { static: true }) sort: MatSort;
@ViewChild(MatPaginator) paginator!: MatPaginator;
@ViewChild('sort', { static: true }) sort!: MatSort;

overviewBudgets: BudgetRecord[] = [];
// Use computed to derive overviewBudgets from the input
overviewBudgets = computed(() => this.budgets.overview);

constructor(private _router$$: Router,
private _dialog: MatDialog,
) { }
constructor() {
// Effect to update dataSource when budgets change
effect(() => {
this.dataSource.data = this.budgets.budgets || [];
}, { allowSignalWrites: true });
}

ngOnInit(): void {
this._sbS.sink = this.budgets$.pipe(tap((o) => {
this.overviewBudgets = o.overview;
this.dataSource.data = o.budgets;
})).subscribe();
ngAfterViewInit(): void {
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
}

/**
* Checks whether the user has access to a certain feature.
*
* @TODO @IanOdhiambo9 - Please put proper access control architecture in place.
*/
access(requested:any)
{
* Checking whether the user has access to a certain feature.
*/
access(requested: any): boolean {
switch (requested) {
case 'view':
case 'clone':
return true; //budget.access.owner || budget.access.view || budget.access.edit;
case 'edit':
return true; // (budget.access.owner || budget.access.edit) && budget.status !== BudgetStatus.InUse && budget.status !== BudgetStatus.InUse;
default:
return false;
}
return false;
}

ngAfterViewInit(): void {
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
}

filterAccountRecords(event: Event) {
Expand All @@ -81,17 +73,17 @@ export class BudgetTableComponent {
}

promote() {
if (this.canPromote)
if (this.canPromote) {
this.doPromote.emit();
}
}

/** Open share screen to configure budget access. */
openShareBudgetDialog(parent: Budget | false): void
{
openShareBudgetDialog(parent: Budget | false): void {
this._dialog.open(ShareBudgetModalComponent, {
panelClass: 'no-pad-dialog',
width: '600px',
data: parent != null ? parent : false
data: parent !== null ? parent : false
});
}

Expand All @@ -100,18 +92,18 @@ export class BudgetTableComponent {
this._dialog.open(CreateBudgetModalComponent, {
height: 'fit-content',
width: '600px',
data: parent != null ? parent : false
data: parent !== null ? parent : false
});
}

openChildBudgetDialog(parent : Budget): void
{
let children: any = this.overviewBudgets.find((budget) => budget.budget.id === parent.id)!?.children;
children = children?.map((child) => child.budget)
openChildBudgetDialog(parent: Budget): void {
const children = this.overviewBudgets().find((budget) => budget.budget.id === parent.id)?.children;
const childBudgets = children?.map((child) => child.budget) || [];

this._dialog.open(ChildBudgetsModalComponent, {
height: 'fit-content',
minWidth: '600px',
data: {parent: parent, budgets: children}
data: { parent: parent, budgets: childBudgets }
});
}

Expand All @@ -120,10 +112,10 @@ export class BudgetTableComponent {
}

deleteBudget(budget: Budget) {

// Implementation would go here
}

translateStatus(status: number) {
translateStatus(status: number): string {
switch (status) {
case 1:
return 'BUDGET.STATUS.ACTIVE';
Expand All @@ -137,4 +129,4 @@ export class BudgetTableComponent {
return '';
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,12 @@
</kujali-finance-search-header-card>
</kujali-finance-toolbar>

<div *ngIf="showFilter" class="filter-section">
<!-- <kujali-invoices-filter (filterChanged)='fieldsFilter($event)'>
</kujali-invoices-filter> -->
<div *ngIf="showFilter()" class="filter-section">
<!-- Filter component would need signal-based refactor here -->
</div>

<div class="table-container">
<app-budget-table [budgets$]="allBudgets$"></app-budget-table>
<app-budget-table [attr.budgets]="allBudgets()"></app-budget-table>
</div>
</div>
</app-page>
Loading