Merge branch 'spencer/datatable-component' into 'master'
Refactor data tables into presentational components. See merge request grassrootseconomics/cic-staff-client!40
This commit is contained in:
		
						commit
						61be98662e
					
				
							
								
								
									
										30
									
								
								src/app/components/components.module.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								src/app/components/components.module.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,30 @@
 | 
			
		||||
import { NgModule } from '@angular/core';
 | 
			
		||||
import { CommonModule } from '@angular/common';
 | 
			
		||||
import { TransactionsDatatableComponent } from './datatables/transactions-datatable/transactions-datatable.component';
 | 
			
		||||
import { MatFormFieldModule } from '@angular/material/form-field';
 | 
			
		||||
import { MatSelectModule } from '@angular/material/select';
 | 
			
		||||
import { MatSortModule } from '@angular/material/sort';
 | 
			
		||||
import { MatTableModule } from '@angular/material/table';
 | 
			
		||||
import { MatRippleModule } from '@angular/material/core';
 | 
			
		||||
import { MatPaginatorModule } from '@angular/material/paginator';
 | 
			
		||||
import { SharedModule } from '@app/shared/shared.module';
 | 
			
		||||
import { MatIconModule } from '@angular/material/icon';
 | 
			
		||||
import { MatButtonModule } from '@angular/material/button';
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
  declarations: [TransactionsDatatableComponent],
 | 
			
		||||
  exports: [TransactionsDatatableComponent],
 | 
			
		||||
  imports: [
 | 
			
		||||
    CommonModule,
 | 
			
		||||
    MatFormFieldModule,
 | 
			
		||||
    MatSelectModule,
 | 
			
		||||
    MatSortModule,
 | 
			
		||||
    MatTableModule,
 | 
			
		||||
    MatRippleModule,
 | 
			
		||||
    MatPaginatorModule,
 | 
			
		||||
    SharedModule,
 | 
			
		||||
    MatIconModule,
 | 
			
		||||
    MatButtonModule,
 | 
			
		||||
  ],
 | 
			
		||||
})
 | 
			
		||||
export class ComponentsModule {}
 | 
			
		||||
@ -0,0 +1,107 @@
 | 
			
		||||
<div *ngIf="transactions" class="card mt-1">
 | 
			
		||||
  <div class="card-header">
 | 
			
		||||
    <div class="row">
 | 
			
		||||
      <mat-form-field appearance="outline">
 | 
			
		||||
        <mat-label> TRANSACTION TYPE </mat-label>
 | 
			
		||||
        <mat-select
 | 
			
		||||
          id="transferSelect"
 | 
			
		||||
          [(value)]="transactionsType"
 | 
			
		||||
          (selectionChange)="filterTransactions()"
 | 
			
		||||
        >
 | 
			
		||||
          <mat-option value="all">ALL TRANSFERS</mat-option>
 | 
			
		||||
          <mat-option *ngFor="let transactionType of transactionsTypes" [value]="transactionType">
 | 
			
		||||
            {{ transactionType | uppercase }}
 | 
			
		||||
          </mat-option>
 | 
			
		||||
        </mat-select>
 | 
			
		||||
      </mat-form-field>
 | 
			
		||||
      <button
 | 
			
		||||
        mat-raised-button
 | 
			
		||||
        color="primary"
 | 
			
		||||
        type="button"
 | 
			
		||||
        class="btn btn-outline-primary ml-auto mr-2"
 | 
			
		||||
        (click)="downloadCsv(transactions, 'transactions')"
 | 
			
		||||
      >
 | 
			
		||||
        EXPORT
 | 
			
		||||
      </button>
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
 | 
			
		||||
  <div class="card-body">
 | 
			
		||||
    <mat-form-field appearance="outline">
 | 
			
		||||
      <mat-label> Filter </mat-label>
 | 
			
		||||
      <input
 | 
			
		||||
        matInput
 | 
			
		||||
        type="text"
 | 
			
		||||
        (keyup)="doTransactionFilter($event.target.value)"
 | 
			
		||||
        placeholder="Filter"
 | 
			
		||||
      />
 | 
			
		||||
      <mat-icon matSuffix>search</mat-icon>
 | 
			
		||||
    </mat-form-field>
 | 
			
		||||
 | 
			
		||||
    <table
 | 
			
		||||
      mat-table
 | 
			
		||||
      class="mat-elevation-z10"
 | 
			
		||||
      [dataSource]="transactionsDataSource"
 | 
			
		||||
      matSort
 | 
			
		||||
      matSortActive="created"
 | 
			
		||||
      #TransactionTableSort="matSort"
 | 
			
		||||
      matSortDirection="asc"
 | 
			
		||||
      matSortDisableClear
 | 
			
		||||
    >
 | 
			
		||||
      <ng-container matColumnDef="sender">
 | 
			
		||||
        <th mat-header-cell *matHeaderCellDef mat-sort-header>Sender</th>
 | 
			
		||||
        <td mat-cell *matCellDef="let transaction">
 | 
			
		||||
          {{ transaction?.sender?.vcard.fn[0].value || transaction.from }}
 | 
			
		||||
        </td>
 | 
			
		||||
      </ng-container>
 | 
			
		||||
 | 
			
		||||
      <ng-container matColumnDef="recipient">
 | 
			
		||||
        <th mat-header-cell *matHeaderCellDef mat-sort-header>Recipient</th>
 | 
			
		||||
        <td mat-cell *matCellDef="let transaction">
 | 
			
		||||
          {{ transaction?.recipient?.vcard.fn[0].value || transaction.to }}
 | 
			
		||||
        </td>
 | 
			
		||||
      </ng-container>
 | 
			
		||||
 | 
			
		||||
      <ng-container matColumnDef="value">
 | 
			
		||||
        <th mat-header-cell *matHeaderCellDef mat-sort-header>Value</th>
 | 
			
		||||
        <td mat-cell *matCellDef="let transaction">
 | 
			
		||||
          <span *ngIf="transaction.type == 'transaction'"
 | 
			
		||||
            >{{ transaction?.value | tokenRatio }} {{ tokenSymbol | uppercase }}</span
 | 
			
		||||
          >
 | 
			
		||||
          <span *ngIf="transaction.type == 'conversion'"
 | 
			
		||||
            >{{ transaction?.toValue | tokenRatio }} {{ tokenSymbol | uppercase }}</span
 | 
			
		||||
          >
 | 
			
		||||
        </td>
 | 
			
		||||
      </ng-container>
 | 
			
		||||
 | 
			
		||||
      <ng-container matColumnDef="created">
 | 
			
		||||
        <th mat-header-cell *matHeaderCellDef mat-sort-header>Created</th>
 | 
			
		||||
        <td mat-cell *matCellDef="let transaction">
 | 
			
		||||
          {{ transaction?.tx.timestamp | unixDate }}
 | 
			
		||||
        </td>
 | 
			
		||||
      </ng-container>
 | 
			
		||||
 | 
			
		||||
      <ng-container matColumnDef="type">
 | 
			
		||||
        <th mat-header-cell *matHeaderCellDef mat-sort-header>TYPE</th>
 | 
			
		||||
        <td mat-cell *matCellDef="let transaction">
 | 
			
		||||
          <span class="badge badge-success badge-pill"> {{ transaction?.type }} </span>
 | 
			
		||||
        </td>
 | 
			
		||||
      </ng-container>
 | 
			
		||||
 | 
			
		||||
      <tr mat-header-row *matHeaderRowDef="transactionsDisplayedColumns"></tr>
 | 
			
		||||
      <tr
 | 
			
		||||
        mat-row
 | 
			
		||||
        *matRowDef="let transaction; columns: transactionsDisplayedColumns"
 | 
			
		||||
        matRipple
 | 
			
		||||
        (click)="viewTransaction(transaction)"
 | 
			
		||||
      ></tr>
 | 
			
		||||
    </table>
 | 
			
		||||
 | 
			
		||||
    <mat-paginator
 | 
			
		||||
      #TransactionTablePaginator="matPaginator"
 | 
			
		||||
      [pageSize]="transactionsDefaultPageSize"
 | 
			
		||||
      [pageSizeOptions]="transactionsPageSizeOptions"
 | 
			
		||||
      showFirstLastButtons
 | 
			
		||||
    ></mat-paginator>
 | 
			
		||||
  </div>
 | 
			
		||||
</div>
 | 
			
		||||
@ -0,0 +1,24 @@
 | 
			
		||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
 | 
			
		||||
 | 
			
		||||
import { TransactionsDatatableComponent } from './transactions-datatable.component';
 | 
			
		||||
 | 
			
		||||
describe('TransactionsDatatableComponent', () => {
 | 
			
		||||
  let component: TransactionsDatatableComponent;
 | 
			
		||||
  let fixture: ComponentFixture<TransactionsDatatableComponent>;
 | 
			
		||||
 | 
			
		||||
  beforeEach(async () => {
 | 
			
		||||
    await TestBed.configureTestingModule({
 | 
			
		||||
      declarations: [TransactionsDatatableComponent],
 | 
			
		||||
    }).compileComponents();
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  beforeEach(() => {
 | 
			
		||||
    fixture = TestBed.createComponent(TransactionsDatatableComponent);
 | 
			
		||||
    component = fixture.componentInstance;
 | 
			
		||||
    fixture.detectChanges();
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  it('should create', () => {
 | 
			
		||||
    expect(component).toBeTruthy();
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
@ -0,0 +1,92 @@
 | 
			
		||||
import {
 | 
			
		||||
  Component,
 | 
			
		||||
  OnInit,
 | 
			
		||||
  ChangeDetectionStrategy,
 | 
			
		||||
  ViewChild,
 | 
			
		||||
  Input,
 | 
			
		||||
  ChangeDetectorRef,
 | 
			
		||||
  Output,
 | 
			
		||||
  EventEmitter,
 | 
			
		||||
} from '@angular/core';
 | 
			
		||||
import { MatTableDataSource } from '@angular/material/table';
 | 
			
		||||
import { MatPaginator } from '@angular/material/paginator';
 | 
			
		||||
import { MatSort } from '@angular/material/sort';
 | 
			
		||||
import { Transaction } from '@app/_models';
 | 
			
		||||
import { exportCsv } from '@app/_helpers';
 | 
			
		||||
import {TokenService, TransactionService, UserService} from '@app/_services';
 | 
			
		||||
import {first} from 'rxjs/operators';
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'app-transactions-datatable',
 | 
			
		||||
  templateUrl: './transactions-datatable.component.html',
 | 
			
		||||
  styleUrls: ['./transactions-datatable.component.scss'],
 | 
			
		||||
  changeDetection: ChangeDetectionStrategy.OnPush,
 | 
			
		||||
})
 | 
			
		||||
export class TransactionsDatatableComponent implements OnInit {
 | 
			
		||||
  @Input() transactions: Array<Transaction>;
 | 
			
		||||
 | 
			
		||||
  @Output() viewTx: EventEmitter<any> = new EventEmitter<any>();
 | 
			
		||||
 | 
			
		||||
  transactionsDataSource: MatTableDataSource<any>;
 | 
			
		||||
  transactionsDisplayedColumns: Array<string> = ['sender', 'recipient', 'value', 'created', 'type'];
 | 
			
		||||
  transactionsDefaultPageSize: number = 10;
 | 
			
		||||
  transactionsPageSizeOptions: Array<number> = [10, 20, 50, 100];
 | 
			
		||||
  @ViewChild('TransactionTablePaginator', { static: true }) transactionTablePaginator: MatPaginator;
 | 
			
		||||
  @ViewChild('TransactionTableSort', { static: true }) transactionTableSort: MatSort;
 | 
			
		||||
  transactionsType: string = 'all';
 | 
			
		||||
  transactionsTypes: Array<string>;
 | 
			
		||||
  tokenSymbol: string;
 | 
			
		||||
 | 
			
		||||
  constructor(
 | 
			
		||||
    private cdr: ChangeDetectorRef,
 | 
			
		||||
    private tokenService: TokenService,
 | 
			
		||||
    private transactionService: TransactionService,
 | 
			
		||||
    private userService: UserService,
 | 
			
		||||
  ) {}
 | 
			
		||||
 | 
			
		||||
  async ngOnInit(): Promise<void> {
 | 
			
		||||
    await this.tokenService.init();
 | 
			
		||||
    await this.transactionService.init();
 | 
			
		||||
    await this.userService.init();
 | 
			
		||||
    this.userService
 | 
			
		||||
      .getTransactionTypes()
 | 
			
		||||
      .pipe(first())
 | 
			
		||||
      .subscribe((res) => (this.transactionsTypes = res));
 | 
			
		||||
    this.tokenService.load.subscribe(async (status: boolean) => {
 | 
			
		||||
      if (status) {
 | 
			
		||||
        this.tokenSymbol = await this.tokenService.getTokenSymbol();
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
    if (this.transactions) {
 | 
			
		||||
      this.transactionsDataSource = new MatTableDataSource<any>(this.transactions);
 | 
			
		||||
      this.transactionsDataSource.paginator = this.transactionTablePaginator;
 | 
			
		||||
      this.transactionsDataSource.sort = this.transactionTableSort;
 | 
			
		||||
      this.cdr.detectChanges();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  viewTransaction(transaction): void {
 | 
			
		||||
    this.viewTx.emit(transaction);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  doTransactionFilter(value: string): void {
 | 
			
		||||
    this.transactionsDataSource.filter = value.trim().toLocaleLowerCase();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  filterTransactions(): void {
 | 
			
		||||
    if (this.transactionsType === 'all') {
 | 
			
		||||
      this.transactionService.transactionsSubject.subscribe((transactions) => {
 | 
			
		||||
        this.transactionsDataSource.data = transactions;
 | 
			
		||||
        this.transactions = transactions;
 | 
			
		||||
      });
 | 
			
		||||
    } else {
 | 
			
		||||
      this.transactionsDataSource.data = this.transactions.filter(
 | 
			
		||||
        (transaction) => transaction.type + 's' === this.transactionsType
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  downloadCsv(data: any, filename: string): void {
 | 
			
		||||
    exportCsv(data, filename);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -333,6 +333,13 @@
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
<!--      <div *ngIf="account && transactions !== undefined">-->
 | 
			
		||||
<!--        <app-transactions-datatable-->
 | 
			
		||||
<!--          [transactions]="transactions"-->
 | 
			
		||||
<!--          (viewTx)="transaction = $event"-->
 | 
			
		||||
<!--        ></app-transactions-datatable>-->
 | 
			
		||||
<!--      </div>-->
 | 
			
		||||
 | 
			
		||||
      <mat-tab-group *ngIf="account" dynamicHeight mat-align-tabs="start">
 | 
			
		||||
        <mat-tab label="Transactions">
 | 
			
		||||
          <app-transaction-details
 | 
			
		||||
 | 
			
		||||
@ -23,6 +23,7 @@ import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
 | 
			
		||||
import { ReactiveFormsModule } from '@angular/forms';
 | 
			
		||||
import { AccountSearchComponent } from './account-search/account-search.component';
 | 
			
		||||
import { MatSnackBarModule } from '@angular/material/snack-bar';
 | 
			
		||||
import { ComponentsModule } from '@app/components/components.module';
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
  declarations: [
 | 
			
		||||
@ -51,6 +52,7 @@ import { MatSnackBarModule } from '@angular/material/snack-bar';
 | 
			
		||||
    MatProgressSpinnerModule,
 | 
			
		||||
    ReactiveFormsModule,
 | 
			
		||||
    MatSnackBarModule,
 | 
			
		||||
    ComponentsModule,
 | 
			
		||||
  ],
 | 
			
		||||
})
 | 
			
		||||
export class AccountsModule {}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user