-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a basic registry viewer for Blockchain Social Network (BSN)
- Loading branch information
Showing
9 changed files
with
348 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
import { DataSource } from '@angular/cdk/collections'; | ||
import { MatPaginator } from '@angular/material/paginator'; | ||
import { MatSort } from '@angular/material/sort'; | ||
import { map } from 'rxjs/operators'; | ||
import { Observable, of as observableOf, merge } from 'rxjs'; | ||
|
||
// TODO: Replace this with your own data model type | ||
export interface TableItem { | ||
name: string; | ||
id: number; | ||
} | ||
|
||
// TODO: replace this with real data from your application | ||
const EXAMPLE_DATA: TableItem[] = [ | ||
{id: 1, name: 'Hydrogen'}, | ||
{id: 2, name: 'Helium'}, | ||
{id: 3, name: 'Lithium'}, | ||
{id: 4, name: 'Beryllium'}, | ||
{id: 5, name: 'Boron'}, | ||
{id: 6, name: 'Carbon'}, | ||
{id: 7, name: 'Nitrogen'}, | ||
{id: 8, name: 'Oxygen'}, | ||
{id: 9, name: 'Fluorine'}, | ||
{id: 10, name: 'Neon'}, | ||
{id: 11, name: 'Sodium'}, | ||
{id: 12, name: 'Magnesium'}, | ||
{id: 13, name: 'Aluminum'}, | ||
{id: 14, name: 'Silicon'}, | ||
{id: 15, name: 'Phosphorus'}, | ||
{id: 16, name: 'Sulfur'}, | ||
{id: 17, name: 'Chlorine'}, | ||
{id: 18, name: 'Argon'}, | ||
{id: 19, name: 'Potassium'}, | ||
{id: 20, name: 'Calcium'}, | ||
]; | ||
|
||
/** | ||
* Data source for the Table view. This class should | ||
* encapsulate all logic for fetching and manipulating the displayed data | ||
* (including sorting, pagination, and filtering). | ||
*/ | ||
export class TableDataSource extends DataSource<TableItem> { | ||
data: TableItem[] = EXAMPLE_DATA; | ||
paginator: MatPaginator | undefined; | ||
sort: MatSort | undefined; | ||
|
||
constructor() { | ||
super(); | ||
} | ||
|
||
/** | ||
* Connect this data source to the table. The table will only update when | ||
* the returned stream emits new items. | ||
* @returns A stream of the items to be rendered. | ||
*/ | ||
connect(): Observable<TableItem[]> { | ||
if (this.paginator && this.sort) { | ||
// Combine everything that affects the rendered data into one update | ||
// stream for the data-table to consume. | ||
return merge(observableOf(this.data), this.paginator.page, this.sort.sortChange) | ||
.pipe(map(() => { | ||
return this.getPagedData(this.getSortedData([...this.data ])); | ||
})); | ||
} else { | ||
throw Error('Please set the paginator and sort on the data source before connecting.'); | ||
} | ||
} | ||
|
||
/** | ||
* Called when the table is being destroyed. Use this function, to clean up | ||
* any open connections or free any held resources that were set up during connect. | ||
*/ | ||
disconnect(): void {} | ||
|
||
/** | ||
* Paginate the data (client-side). If you're using server-side pagination, | ||
* this would be replaced by requesting the appropriate data from the server. | ||
*/ | ||
private getPagedData(data: TableItem[]): TableItem[] { | ||
if (this.paginator) { | ||
const startIndex = this.paginator.pageIndex * this.paginator.pageSize; | ||
return data.splice(startIndex, this.paginator.pageSize); | ||
} else { | ||
return data; | ||
} | ||
} | ||
|
||
/** | ||
* Sort the data (client-side). If you're using server-side sorting, | ||
* this would be replaced by requesting the appropriate data from the server. | ||
*/ | ||
private getSortedData(data: TableItem[]): TableItem[] { | ||
if (!this.sort || !this.sort.active || this.sort.direction === '') { | ||
return data; | ||
} | ||
|
||
return data.sort((a, b) => { | ||
const isAsc = this.sort?.direction === 'asc'; | ||
switch (this.sort?.active) { | ||
case 'name': return compare(a.name, b.name, isAsc); | ||
case 'id': return compare(+a.id, +b.id, isAsc); | ||
default: return 0; | ||
} | ||
}); | ||
} | ||
} | ||
|
||
/** Simple sort comparator for example ID/Name columns (for client-side sorting). */ | ||
function compare(a: string | number, b: string | number, isAsc: boolean): number { | ||
return (a < b ? -1 : 1) * (isAsc ? 1 : -1); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,52 @@ | ||
<p>registries works!</p> | ||
<h1>Registries</h1> | ||
|
||
<h3>Highlighted</h3> | ||
|
||
<mat-card appearance="outlined"> | ||
<mat-card-header> | ||
<mat-card-title>Blockchain Social Network (BSN)</mat-card-title> | ||
<mat-card-subtitle>Stellar blockchain data registry</mat-card-subtitle> | ||
</mat-card-header> | ||
<mat-card-actions> | ||
<button (click)="openRegistry('bsn')" mat-button>Open</button> | ||
</mat-card-actions> | ||
</mat-card> | ||
<br> | ||
<mat-card appearance="outlined"> | ||
<mat-card-header> | ||
<mat-card-title>Liberstad CC</mat-card-title> | ||
<mat-card-subtitle>Crypto Company Registry</mat-card-subtitle> | ||
</mat-card-header> | ||
<mat-card-actions> | ||
<button mat-button>Open</button> | ||
</mat-card-actions> | ||
</mat-card> | ||
|
||
<h3>All registries</h3> | ||
|
||
<div class="mat-elevation-z8"> | ||
<table mat-table class="full-width-table" matSort aria-label="Elements"> | ||
<!-- Id Column --> | ||
<ng-container matColumnDef="id"> | ||
<th mat-header-cell *matHeaderCellDef mat-sort-header>Id</th> | ||
<td mat-cell *matCellDef="let row">{{row.id}}</td> | ||
</ng-container> | ||
|
||
<!-- Name Column --> | ||
<ng-container matColumnDef="name"> | ||
<th mat-header-cell *matHeaderCellDef mat-sort-header>Name</th> | ||
<td mat-cell *matCellDef="let row">{{row.name}}</td> | ||
</ng-container> | ||
|
||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr> | ||
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> | ||
</table> | ||
|
||
<mat-paginator #paginator | ||
[length]="dataSource.data.length" | ||
[pageIndex]="0" | ||
[pageSize]="10" | ||
[pageSizeOptions]="[5, 10, 20]" | ||
aria-label="Select page"> | ||
</mat-paginator> | ||
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
.full-width-table { | ||
width: 100%; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,23 +1,25 @@ | ||
import { ComponentFixture, TestBed } from '@angular/core/testing'; | ||
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing'; | ||
import { NoopAnimationsModule } from '@angular/platform-browser/animations'; | ||
|
||
import { RegistriesComponent } from './registries.component'; | ||
|
||
describe('RegistriesComponent', () => { | ||
describe('TableComponent', () => { | ||
let component: RegistriesComponent; | ||
let fixture: ComponentFixture<RegistriesComponent>; | ||
|
||
beforeEach(async () => { | ||
await TestBed.configureTestingModule({ | ||
imports: [RegistriesComponent] | ||
}) | ||
.compileComponents(); | ||
beforeEach(waitForAsync(() => { | ||
TestBed.configureTestingModule({ | ||
imports: [NoopAnimationsModule] | ||
}).compileComponents(); | ||
})); | ||
|
||
beforeEach(() => { | ||
fixture = TestBed.createComponent(RegistriesComponent); | ||
component = fixture.componentInstance; | ||
fixture.detectChanges(); | ||
}); | ||
|
||
it('should create', () => { | ||
it('should compile', () => { | ||
expect(component).toBeTruthy(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,39 @@ | ||
import { Component } from '@angular/core'; | ||
import { AfterViewInit, Component, ViewChild } from '@angular/core'; | ||
import { MatTableModule, MatTable } from '@angular/material/table'; | ||
import { MatPaginatorModule, MatPaginator } from '@angular/material/paginator'; | ||
import { MatSortModule, MatSort } from '@angular/material/sort'; | ||
import { TableDataSource, TableItem } from './registries-datasource'; | ||
import { MatCardModule } from '@angular/material/card'; | ||
import { MatButtonModule } from '@angular/material/button'; | ||
import { Router } from '@angular/router'; | ||
|
||
@Component({ | ||
selector: 'app-registries', | ||
standalone: true, | ||
imports: [], | ||
templateUrl: './registries.component.html', | ||
styleUrl: './registries.component.scss' | ||
styleUrl: './registries.component.scss', | ||
standalone: true, | ||
imports: [MatButtonModule, MatCardModule, MatTableModule, MatPaginatorModule, MatSortModule] | ||
}) | ||
export class RegistriesComponent { | ||
export class RegistriesComponent implements AfterViewInit { | ||
@ViewChild(MatPaginator) paginator!: MatPaginator; | ||
@ViewChild(MatSort) sort!: MatSort; | ||
@ViewChild(MatTable) table!: MatTable<TableItem>; | ||
dataSource = new TableDataSource(); | ||
|
||
/** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ | ||
displayedColumns = ['id', 'name']; | ||
|
||
constructor(private router: Router) { | ||
|
||
} | ||
|
||
ngAfterViewInit(): void { | ||
this.dataSource.sort = this.sort; | ||
this.dataSource.paginator = this.paginator; | ||
this.table.dataSource = this.dataSource; | ||
} | ||
|
||
openRegistry(registry: string) { | ||
this.router.navigate(['registries', registry]); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
<h1>Registry: Blockchain Social Network (BSN)</h1> | ||
|
||
<p> | ||
Updated: {{updated | date: 'medium'}} | ||
</p> | ||
|
||
|
||
<mat-list> | ||
<div mat-subheader>Tokens</div> | ||
@for (token of tokens; track token) { | ||
<mat-list-item> | ||
<mat-icon matListItemIcon>folder</mat-icon> | ||
<div matListItemTitle>{{token.name}}</div> | ||
<div matListItemLine>{{token.short}}</div> | ||
</mat-list-item> | ||
} | ||
<mat-divider></mat-divider> | ||
<div mat-subheader>Sources</div> | ||
@for (source of sources; track source) { | ||
<mat-list-item> | ||
<mat-icon matListItemIcon>note</mat-icon> | ||
<div matListItemTitle>{{source.name}}</div> | ||
<div matListItemLine>{{source.short}}</div> | ||
</mat-list-item> | ||
} | ||
<div mat-subheader>Accounts</div> | ||
@for (account of accounts; track account) { | ||
<mat-list-item> | ||
<mat-icon matListItemIcon>note</mat-icon> | ||
<div matListItemTitle>{{account.short}}</div> | ||
<div matListItemLine> | ||
@for (tag of account.tags; track tag) { | ||
{{tag.id}}, | ||
} | ||
</div> | ||
</mat-list-item> | ||
} | ||
</mat-list> |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
import { AfterViewInit, Component, ViewChild } from '@angular/core'; | ||
import { MatTableModule, MatTable } from '@angular/material/table'; | ||
import { MatPaginatorModule, MatPaginator } from '@angular/material/paginator'; | ||
import { MatSortModule, MatSort } from '@angular/material/sort'; | ||
import { MatCardModule } from '@angular/material/card'; | ||
import { MatButtonModule } from '@angular/material/button'; | ||
import { Router } from '@angular/router'; | ||
import { MatListModule } from '@angular/material/list'; | ||
import { MatIconModule } from '@angular/material/icon'; | ||
import { MatDividerModule } from '@angular/material/divider'; | ||
import { DatePipe } from '@angular/common'; | ||
import { MatTooltipModule } from '@angular/material/tooltip'; | ||
|
||
export interface Section { | ||
name: string; | ||
updated: Date; | ||
} | ||
|
||
@Component({ | ||
selector: 'app-registry', | ||
templateUrl: './registry.component.html', | ||
styleUrl: './registry.component.scss', | ||
standalone: true, | ||
imports: [MatButtonModule, | ||
MatListModule, | ||
MatIconModule, | ||
DatePipe, | ||
MatDividerModule, | ||
MatCardModule, MatTableModule, | ||
MatTooltipModule, | ||
MatPaginatorModule, MatSortModule] | ||
}) | ||
export class RegistryComponent implements AfterViewInit { | ||
|
||
tokens: any[] = [ | ||
|
||
]; | ||
|
||
sources: any[] = [ | ||
|
||
]; | ||
|
||
accounts: any[] = [ | ||
|
||
]; | ||
|
||
|
||
updated: any; | ||
|
||
constructor(private router: Router) { | ||
|
||
} | ||
|
||
ngAfterViewInit(): void { | ||
|
||
} | ||
|
||
shorten(str: string) { | ||
return str.substring(0, 5) + '...' + str.substring(str.length - 5); | ||
} | ||
|
||
async ngOnInit() { | ||
var request = await fetch("https://bsn.mtla.me/json"); | ||
|
||
if (request.ok) { | ||
var data = await request.json(); | ||
|
||
this.updated = data.createDate; | ||
|
||
this.tokens = data.knownTokens.map((token: { split: (arg0: string) => [any, any]; }) => { | ||
const [name, id] = token.split("-"); | ||
return { id, name, short: this.shorten(id) }; | ||
}); | ||
|
||
this.sources = data.usedSources.map((token: { split: (arg0: string) => [any, any]; }) => { | ||
const [name, id] = token.split("-"); | ||
return { id, name, short: this.shorten(id) }; | ||
}); | ||
|
||
this.accounts = Object.entries(data.accounts).map(([id, accountData]: [string, any]) => { | ||
return { | ||
id, | ||
short: this.shorten(id), | ||
balances: accountData.balances, | ||
tags: accountData.tags ? Object.entries(accountData.tags).map(([tag, value]: [string, any]) => { | ||
return { id: tag, value }; | ||
}) | ||
: [] | ||
}; | ||
}); | ||
} | ||
} | ||
} |