Skip to content

Commit

Permalink
Add Blocks Management
Browse files Browse the repository at this point in the history
  • Loading branch information
sondreb committed Aug 24, 2024
1 parent 10556bd commit ba4ff18
Show file tree
Hide file tree
Showing 14 changed files with 217 additions and 36 deletions.
6 changes: 6 additions & 0 deletions app/src/app/app.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,12 @@ export const routes: Routes = [
title: 'Protocol Handler',
data: { hide: true, icon: 'search' },
},
{
path: 'settings/blocks',
loadComponent: () => import('./settings/blocks/blocks.component').then((c) => c.BlocksComponent),
title: 'Blocks',
data: { hide: true, icon: 'block' },
},
{
path: 'tree',
loadComponent: () => import('./tree/tree.component').then((c) => c.TreeComponent),
Expand Down
14 changes: 14 additions & 0 deletions app/src/app/app.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { ProtocolService } from './protocol.service';
import { ProfileService } from './profile.service';
import { HashService } from './hash.service';
import { MatSnackBar } from '@angular/material/snack-bar';
import { ConnectionService } from './connection.service';

export interface AppState {
selectedAccount: string;
Expand Down Expand Up @@ -58,6 +59,8 @@ export class AppService {

profile = inject(ProfileService);

connection = inject(ConnectionService);

protocol = inject(ProtocolService);

snackBar = inject(MatSnackBar);
Expand Down Expand Up @@ -264,13 +267,24 @@ export class AppService {
// Load the user profile.
await this.profile.openCurrentUserProfile(this.account().did);

// Load user and app data.
await this.loadAppData();

this.initialized.set(true);

this.loading.set(false);

this.firstTimeInitialization();
}

private async loadAppData() {
console.log('Loading app data...');
// Loads the connections and blocks, used by various app and services on Ariton.
await this.connection.initialize();

console.log('App data loaded.');
}

/** Only run when the hash bundle has changed (updated app) */
async firstTimeInitialization() {
// If the previous bundle hash is the same as the current, we don't need to re-register.
Expand Down
26 changes: 23 additions & 3 deletions app/src/app/connection.service.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { inject, Injectable } from '@angular/core';
import { inject, Injectable, signal } from '@angular/core';
import { IdentityService } from './identity.service';
import { protocolDefinition as connectionDefinition } from '../protocols/connection';
import { Record } from '@web5/api';
import { RecordEntry } from './data';
import { connect } from '../../node_modules/undici-types/api.d';
import { DwnDateSort } from '@web5/agent';

export interface ConnectionData {
Expand All @@ -23,6 +24,10 @@ export interface ConnectionBlockEntry extends RecordEntry<ConnectionBlockData> {
export class ConnectionService {
identity = inject(IdentityService);

blocks = signal<ConnectionBlockEntry[]>([]);

connections = signal<ConnectionEntry[]>([]);

constructor() {}

/** Creates a connection entry that opens up a trust line between identities. */
Expand Down Expand Up @@ -51,6 +56,15 @@ export class ConnectionService {
} as ConnectionEntry;
}

/** Loads the connections and blocks */
async initialize() {
const blocks = await this.loadBlocks();
this.blocks.set(blocks);

const connections = await this.loadConnections();
this.connections.set(connections);
}

async request(data: any) {
// Create a new connection that is sent to external DWN.
// We save a local copy to see our outgoing connection requests.
Expand All @@ -75,6 +89,12 @@ export class ConnectionService {
} as ConnectionEntry;
}

async deleteBlock(entry: any) {
await entry.record.delete();
entry.record.send(this.identity.did);
this.blocks.update((list) => [...list.filter((n) => n.id !== entry.id)]);
}

async block(did: string) {
const data = {
did: did,
Expand Down Expand Up @@ -151,7 +171,7 @@ export class ConnectionService {
}

async loadBlocks() {
const list: ConnectionEntry[] = [];
const list: ConnectionBlockEntry[] = [];

const { records } = await this.identity.web5.dwn.records.query({
message: {
Expand All @@ -166,7 +186,7 @@ export class ConnectionService {

for (let record of records!) {
const data = await record.data.json();
let notifiationEvent: ConnectionEntry = { record, data, id: record.id };
let notifiationEvent: ConnectionBlockEntry = { record, data, id: record.id };
list.push(notifiationEvent);
}

Expand Down
26 changes: 13 additions & 13 deletions app/src/app/notifications/notifications.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -40,34 +40,34 @@ <h1>Notifications</h1>
</mat-card-title> -->
</mat-card-header>
<mat-card-content>
@for(notification of notifications(); track notification) {
@for(entry of notifications(); track entry) {
<mat-card class="card-notification" appearance="outlined">
<mat-card-header>
<mat-icon class="card-icon" inline="true" mat-card-avatar>{{ notification.data.icon }}</mat-icon>
<mat-card-title>{{ notification.data.title }}</mat-card-title>
<mat-card-subtitle>App: {{ notification.data.app }} ({{ '2024-08-22 12:00' | ago }})</mat-card-subtitle>
<mat-icon class="card-icon" inline="true" mat-card-avatar>{{ entry.data.icon }}</mat-icon>
<mat-card-title>{{ entry.data.title }}</mat-card-title>
<mat-card-subtitle>App: {{ entry.data.app }} ({{ '2024-08-22 12:00' | ago }})</mat-card-subtitle>
</mat-card-header>
<mat-card-content>
@if (notification.data.app === 'Friends') {
@if (entry.data.app === 'Friends') {
<!-- <app-profile-card [did]="notification.record.author">
<button mat-flat-button>CONFIRM</button>
<button mat-button>DELETE</button>
</app-profile-card> -->
<div class="notification-description">{{ notification.data.description }}</div>
<div class="notification-description">{{ entry.data.description }}</div>

<!--
TODO: Use the record.author, not from data. From data is for temporary prototyping.
<app-profile-header [did]="notification.record.author"> -->
<app-profile-header [did]="notification.data.author"></app-profile-header>
} @else if(notification.data.app === 'Connect') {
<div class="notification-description">{{ notification.data.description }}</div>
<app-profile-header [did]="notification.record.author"></app-profile-header>
<app-profile-header [did]="entry.data.author"></app-profile-header>
} @else if(entry.data.app === 'Connect') {
<div class="notification-description">{{ entry.data.description }}</div>
<app-profile-header [did]="entry.record.author"></app-profile-header>
}
</mat-card-content>
<mat-card-actions>
<button mat-flat-button (click)="accept(notification)">ACCEPT</button>
<button mat-button (click)="deleteNotification(notification)">DELETE</button>
<button mat-button (click)="block(notification)">BLOCK</button>
<button mat-flat-button (click)="accept(entry)">ACCEPT</button>
<button mat-button (click)="deleteNotification(entry)">DELETE</button>
<button mat-button (click)="block(entry)">BLOCK</button>
</mat-card-actions>
</mat-card>
}
Expand Down
19 changes: 0 additions & 19 deletions app/src/app/notifications/notifications.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,21 +44,12 @@ export class NotificationsComponent {

notifications = signal<NotificationEvent[]>([]);

blocks = signal<ConnectionEntry[]>([]);

connections = signal<ConnectionEntry[]>([]);

constructor() {
this.layout.resetActions();

effect(async () => {
if (this.app.initialized()) {
await this.loadNotifications();
await this.loadConnections();
await this.loadBlocks();

console.log('Blocks:', this.blocks());
console.log('Connections:', this.connections());
}
});
}
Expand Down Expand Up @@ -173,16 +164,6 @@ export class NotificationsComponent {
this.notifications.set(notifications);
}

async loadConnections() {
const records = await this.connection.loadConnections();
this.connections.set(records);
}

async loadBlocks() {
const records = await this.connection.loadBlocks();
this.blocks.set(records);
}

async enableNotifications() {
console.log('Notifications enabled');
this.sendNotification('Hello World');
Expand Down
23 changes: 23 additions & 0 deletions app/src/app/settings/blocks/blocks.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<h1>Blocks Management</h1>

<mat-card class="notifications-card">
<mat-card-header> </mat-card-header>
<mat-card-content>
@for(entry of service.blocks(); track entry) {
<mat-card class="card-notification" appearance="outlined">
<!-- <mat-card-header>
<mat-icon class="card-icon" inline="true" mat-card-avatar></mat-icon>
<mat-card-title>{{ entry.data }}</mat-card-title>
<mat-card-subtitle>{{ entry.record.dateCreated | ago }}</mat-card-subtitle>
</mat-card-header> -->
<mat-card-content>
{{ entry.data.did }}
</mat-card-content>
<mat-card-actions>
<button mat-flat-button [routerLink]="['/profile', entry.data.did]">VIEW PROFILE</button>
<button mat-button (click)="deleteBlock(entry)">DELETE</button>
</mat-card-actions>
</mat-card>
}
</mat-card-content>
</mat-card>
30 changes: 30 additions & 0 deletions app/src/app/settings/blocks/blocks.component.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
.card-icon {
font-size: 3em;
}

.card-notification {
margin-bottom: 1em;
}

.notifications-title {
display: flex;
width: 100%;
}

:host {
display: flex;
flex-direction: column;
align-items: center;
}

.notifications-card {
max-width: 600px;
width: 100%;
}

.card-notification mat-card-actions button {
width: 100%;
}
.notification-description {
margin-bottom: 1em;
}
23 changes: 23 additions & 0 deletions app/src/app/settings/blocks/blocks.component.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { BlocksComponent } from './blocks.component';

describe('BlocksComponent', () => {
let component: BlocksComponent;
let fixture: ComponentFixture<BlocksComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [BlocksComponent]
})
.compileComponents();

fixture = TestBed.createComponent(BlocksComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
38 changes: 38 additions & 0 deletions app/src/app/settings/blocks/blocks.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Component, effect, inject, signal } from '@angular/core';
import { ConnectionService } from '../../connection.service';
import { AppService } from '../../app.service';
import { CommonModule } from '@angular/common';
import { MatCardModule } from '@angular/material/card';
import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';
import { RouterModule } from '@angular/router';
import { AgoPipe } from '../../shared/pipes/ago.pipe';

@Component({
selector: 'app-blocks',
standalone: true,
imports: [AgoPipe, CommonModule, MatCardModule, MatButtonModule, MatIconModule, RouterModule],
templateUrl: './blocks.component.html',
styleUrl: './blocks.component.scss',
})
export class BlocksComponent {
service = inject(ConnectionService);

app = inject(AppService);

constructor() {
// effect(async () => {
// if (this.app.initialized()) {
// }
// });
}

// async load() {
// const blocks = await this.service.loadBlocks();
// this.blocks.set(blocks);
// }

deleteBlock(entry: any) {
this.service.deleteBlock(entry);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<p>connections works!</p>
Empty file.
23 changes: 23 additions & 0 deletions app/src/app/settings/connections/connections.component.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { ConnectionsComponent } from './connections.component';

describe('ConnectionsComponent', () => {
let component: ConnectionsComponent;
let fixture: ComponentFixture<ConnectionsComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [ConnectionsComponent]
})
.compileComponents();

fixture = TestBed.createComponent(ConnectionsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
12 changes: 12 additions & 0 deletions app/src/app/settings/connections/connections.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Component } from '@angular/core';

@Component({
selector: 'app-connections',
standalone: true,
imports: [],
templateUrl: './connections.component.html',
styleUrl: './connections.component.scss'
})
export class ConnectionsComponent {

}
12 changes: 11 additions & 1 deletion app/src/app/settings/settings.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,17 @@ <h1>Settings</h1>
<button mat-flat-button (click)="toggleDebug()">Toggle debug</button>

<mat-nav-list>
<div mat-subheader>Other Actions</div>
<div mat-subheader>Actions</div>

<a mat-list-item [routerLink]="['connections']">
<mat-icon matListItemIcon>connect_without_contact</mat-icon>
Manage Connections
</a>

<a mat-list-item [routerLink]="['blocks']">
<mat-icon matListItemIcon>block</mat-icon>
Manage Blocks
</a>

<a mat-list-item [routerLink]="['handler']">
<mat-icon matListItemIcon>search</mat-icon>
Expand Down

0 comments on commit ba4ff18

Please sign in to comment.