Skip to content

Commit cac33bf

Browse files
sonasijdvlioIscoRuta98billguo99jongbonga
authored
Merge new features to demo (#498)
* refactor(backend/tests): remove superfluous mocks (#473) * refactor(backend): use odmantic engine (#479) * rename(backend/setting): maximum list length * feat(backend): improve `GET` endpoint semantics The endpoint should receive the `wallet_id` as a query parameter and return the internal mongodb document id. * chore(backend): remove dead code * refactor(backend): use odmantic engine * fix(web-client): add issuers for servers (#482) * fix(web-client): add issuers for servers * Update web-client/src/environments/environment.palau-prod.ts Co-authored-by: Jean-Pierre de Villiers <[email protected]> Co-authored-by: Jean-Pierre de Villiers <[email protected]> * feat(web-client): Pull payment flag (#486) * feat(web-client): Add hidePullPayment flag. * style(web-client): run prettier * fix(web-client): Fix ESLint error. * style(web-client): run prettier * fix(web-client): Change auth_map type to Object type. (#485) * fix(web-client): Change auth_map type to Object type. * fix(web-client): Fix ESLint error. * feat(web-client): add auto logout (#481) * feat(web-client): add auto logout * feat(web-client): add ngZone for auto logout * refactor(web-client): remove redundant isLogin variable in auto logout * refactor(web-client): move auto logout to app component * refactor(web-client): remove autoLogOutService from logout-button * refactor(web-client): remove console log line in auto-logout service * feat(web-client): add environment flag for auto logout * fix(web-client): initialize localStorage lastAction for auto logout first * fix(web-client): pull payment minor text fixes (#491) * fix(cors): allow `localhost:4200` on staging (#492) * feat(web-client): bookmark management (#451) * fix(web-client): Update Pin Entry text for pull payment. (#497) * fix(web-client): Update Pin Entry text for pull payment. * style(web-client): run prettier. * fix(web-client): update prod feature flags (#499) * fix(web-client): update prod feature flags * fix(web-client): update prod feature flags Co-authored-by: Jean-Pierre de Villiers <[email protected]> Co-authored-by: Francisco Rutayebesibwa <[email protected]> Co-authored-by: Bill Guo <[email protected]> Co-authored-by: Jonathan Ngbonga <[email protected]>
1 parent 118f7cf commit cac33bf

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+745
-160
lines changed

backend-services/src/web_asgi/main.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,7 @@
2323

2424
origins = [str(app_settings.primary_origin)]
2525
if app_settings.staging_mode:
26-
origins.append("http://localhost:*")
27-
26+
origins.append("http://localhost:4200")
2827

2928
app = FastAPI()
3029
app.add_middleware(

web-client/package-lock.json

Lines changed: 117 additions & 134 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

web-client/package.json

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -38,24 +38,24 @@
3838
"@angular/platform-browser": "13.3.11",
3939
"@angular/platform-browser-dynamic": "13.3.11",
4040
"@angular/router": "13.3.11",
41-
"@awesome-cordova-plugins/core": "^6.1.0",
42-
"@awesome-cordova-plugins/printer": "^6.1.0",
43-
"@capacitor/app": "^4.1.0",
44-
"@capacitor/browser": "^4.0.1",
45-
"@capacitor/camera": "^4.1.3",
46-
"@capacitor/clipboard": "^4.0.1",
47-
"@capacitor/core": "^4.4.0",
48-
"@capacitor/haptics": "^4.0.1",
49-
"@capacitor/keyboard": "^4.0.1",
50-
"@capacitor/splash-screen": "^4.1.1",
51-
"@capacitor/status-bar": "^4.0.1",
41+
"@awesome-cordova-plugins/core": "^6.2.0",
42+
"@awesome-cordova-plugins/printer": "^6.2.0",
43+
"@capacitor/app": "^4.1.1",
44+
"@capacitor/browser": "^4.1.0",
45+
"@capacitor/camera": "^4.1.4",
46+
"@capacitor/clipboard": "^4.1.0",
47+
"@capacitor/core": "^4.6.1",
48+
"@capacitor/haptics": "^4.1.0",
49+
"@capacitor/keyboard": "^4.1.0",
50+
"@capacitor/splash-screen": "^4.1.2",
51+
"@capacitor/status-bar": "^4.1.1",
5252
"@datorama/akita": "^7.0.1",
5353
"@datorama/akita-ng-entity-service": "^7.0.0",
5454
"@datorama/akita-ng-router-store": "^7.0.0",
5555
"@fortawesome/angular-fontawesome": "^0.10.2",
5656
"@fortawesome/fontawesome-svg-core": "^6.2.0",
5757
"@fortawesome/free-solid-svg-icons": "^6.2.0",
58-
"@ionic/angular": "^6.3.2",
58+
"@ionic/angular": "^6.3.9",
5959
"@ionic/pwa-elements": "^3.1.1",
6060
"@msgpack/msgpack": "^2.7.2",
6161
"@ngneat/input-mask": "^5.0.1",
@@ -105,7 +105,7 @@
105105
"@angular/elements": "13.3.11",
106106
"@angular/language-service": "13.3.11",
107107
"@babel/core": "^7.19.6",
108-
"@capacitor/cli": "^4.4.0",
108+
"@capacitor/cli": "^4.6.1",
109109
"@compodoc/compodoc": "^1.1.19",
110110
"@datorama/akita-cli": "^6.1.1",
111111
"@datorama/akita-ngdevtools": "^7.0.0",

web-client/src/app/app-routing.module.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,13 @@ export const routes: Routes = [
120120
(m) => m.SearchWalletPageModule
121121
),
122122
},
123+
{
124+
path: 'bookmarks',
125+
loadChildren: () =>
126+
import('./views/bookmarks/bookmarks.module').then(
127+
(m) => m.BookmarksPageModule
128+
),
129+
},
123130
{
124131
path: 'pull',
125132
loadChildren: () =>

web-client/src/app/app.component.spec.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
22
import { TestBed, waitForAsync } from '@angular/core/testing';
3+
import { RouterTestingModule } from '@angular/router/testing';
34
import { AppComponent } from './app.component';
45

56
describe('AppComponent', () => {
67
beforeEach(waitForAsync(() => {
78
TestBed.configureTestingModule({
89
declarations: [AppComponent],
10+
imports: [RouterTestingModule],
911
schemas: [CUSTOM_ELEMENTS_SCHEMA],
1012
}).compileComponents();
1113
}));

web-client/src/app/app.component.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { Component } from '@angular/core';
22
import { SplashScreen } from '@capacitor/splash-screen';
33
import { Platform } from '@ionic/angular';
44
import { environment } from 'src/environments/environment';
5+
import { AutoLogoutService } from './services/auto-logout.service';
56
import { SetupService } from './state/setup';
67

78
@Component({
@@ -11,7 +12,11 @@ import { SetupService } from './state/setup';
1112
})
1213
export class AppComponent {
1314
logo: string | undefined;
14-
constructor(private platform: Platform, private setupService: SetupService) {
15+
constructor(
16+
private platform: Platform,
17+
private setupService: SetupService,
18+
private autoLogoutService: AutoLogoutService
19+
) {
1520
this.initializeApp();
1621
}
1722

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<ion-list lines="none">
2+
<ion-list-header>
3+
<ion-label color="primary">
4+
<h1 class="font-nasalization">Recipients list</h1>
5+
</ion-label>
6+
</ion-list-header>
7+
8+
<div *ngIf="bookmarkQuery.selectCount() | async; else empty">
9+
<ng-container *ngFor="let bookmark of bookmarkQuery.selectAll() | async">
10+
<ion-item class="app-item" *ngIf="bookmark?.id">
11+
<ion-icon slot="start" name="bookmark"></ion-icon>
12+
<ion-label>
13+
<h2 class="!font-black">{{ bookmark?.name }}</h2>
14+
<h6>{{ bookmark?.address }}</h6>
15+
</ion-label>
16+
<ion-buttons>
17+
<ion-button (click)="sendFund(bookmark.address)">
18+
<ion-icon slot="icon-only" name="cash"></ion-icon>
19+
</ion-button>
20+
<ion-button (click)="deleteBookmark(bookmark.id)">
21+
<ion-icon slot="icon-only" name="trash" color="danger"></ion-icon>
22+
</ion-button>
23+
</ion-buttons>
24+
</ion-item>
25+
</ng-container>
26+
</div>
27+
28+
<ng-template #empty>
29+
<div class="ion-padding-horizontal ion-text-center">
30+
<p>Your recipient list is empty</p>
31+
</div>
32+
</ng-template>
33+
</ion-list>

web-client/src/app/components/bookmark-list/bookmark-list.component.scss

Whitespace-only changes.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
2+
import { RouterTestingModule } from '@angular/router/testing';
3+
import { IonicModule } from '@ionic/angular';
4+
import { BookmarkListComponent } from './bookmark-list.component';
5+
6+
describe('BookmarkListComponent', () => {
7+
let component: BookmarkListComponent;
8+
let fixture: ComponentFixture<BookmarkListComponent>;
9+
10+
beforeEach(waitForAsync(() => {
11+
TestBed.configureTestingModule({
12+
declarations: [BookmarkListComponent],
13+
imports: [IonicModule.forRoot(), RouterTestingModule],
14+
}).compileComponents();
15+
16+
fixture = TestBed.createComponent(BookmarkListComponent);
17+
component = fixture.componentInstance;
18+
fixture.detectChanges();
19+
}));
20+
21+
it('should create', () => {
22+
expect(component).toBeTruthy();
23+
});
24+
});
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { Component, Input, OnInit } from '@angular/core';
2+
import { NavController } from '@ionic/angular';
3+
import { BookmarkQuery, BookmarkService } from 'src/app/state/bookmark';
4+
import { SwalHelper } from 'src/app/utils/notification/swal-helper';
5+
6+
@Component({
7+
selector: 'app-bookmark-list',
8+
templateUrl: './bookmark-list.component.html',
9+
styleUrls: ['./bookmark-list.component.scss'],
10+
})
11+
export class BookmarkListComponent implements OnInit {
12+
@Input() bookmarks = [];
13+
14+
constructor(
15+
public bookmarkQuery: BookmarkQuery,
16+
private bookmarkService: BookmarkService,
17+
private navCtrl: NavController,
18+
private notification: SwalHelper
19+
) {}
20+
21+
ngOnInit() {}
22+
23+
sendFund(address: string) {
24+
this.navCtrl.navigateForward('pay', {
25+
state: { address },
26+
});
27+
}
28+
29+
deleteBookmark(id: string) {
30+
this.notification.swal.fire({
31+
icon: 'warning',
32+
titleText: 'Delete bookmark',
33+
text: 'Are you sure you want to delete this bookmark?',
34+
showCancelButton: true,
35+
confirmButtonText: 'Yes',
36+
showLoaderOnConfirm: true,
37+
confirmButtonColor: 'var(--ion-color-primary)',
38+
cancelButtonColor: 'var(--ion-color-medium)',
39+
reverseButtons: true,
40+
preConfirm: async () => {
41+
await this.bookmarkService.deleteBookmark(id);
42+
},
43+
});
44+
}
45+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<ion-accordion-group class="app-item">
2+
<ion-accordion value="new">
3+
<ion-item slot="header" lines="none">
4+
<ion-icon slot="start" name="add-circle"></ion-icon>
5+
<ion-label>Add a recipient</ion-label>
6+
</ion-item>
7+
<div slot="content">
8+
<ion-list lines="none" class="p-0">
9+
<form
10+
id="form-bookmark"
11+
[formGroup]="bookmarkForm"
12+
(ngSubmit)="createBookmark(bookmarkForm)"
13+
>
14+
<ion-item>
15+
<ion-label position="stacked">Name</ion-label>
16+
<ion-input type="text" formControlName="name"></ion-input>
17+
</ion-item>
18+
<ion-item>
19+
<ion-label position="stacked">Address</ion-label>
20+
<ion-textarea
21+
class="px-0"
22+
type="text"
23+
formControlName="address"
24+
></ion-textarea>
25+
</ion-item>
26+
</form>
27+
</ion-list>
28+
<ion-button expand="full" class="m-0" type="submit" form="form-bookmark">
29+
Click to add new bookmark
30+
</ion-button>
31+
</div>
32+
</ion-accordion>
33+
</ion-accordion-group>

web-client/src/app/components/new-bookmark/new-bookmark.component.scss

Whitespace-only changes.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
2+
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
3+
import { IonicModule } from '@ionic/angular';
4+
import { NewBookmarkComponent } from './new-bookmark.component';
5+
6+
describe('NewBookmarkComponent', () => {
7+
let component: NewBookmarkComponent;
8+
let fixture: ComponentFixture<NewBookmarkComponent>;
9+
10+
beforeEach(waitForAsync(() => {
11+
TestBed.configureTestingModule({
12+
declarations: [NewBookmarkComponent],
13+
imports: [IonicModule.forRoot(), ReactiveFormsModule, FormsModule],
14+
}).compileComponents();
15+
16+
fixture = TestBed.createComponent(NewBookmarkComponent);
17+
component = fixture.componentInstance;
18+
fixture.detectChanges();
19+
}));
20+
21+
it('should create', () => {
22+
expect(component).toBeTruthy();
23+
});
24+
});
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { Component, OnInit } from '@angular/core';
2+
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
3+
import { BookmarkService } from 'src/app/state/bookmark';
4+
5+
@Component({
6+
selector: 'app-new-bookmark',
7+
templateUrl: './new-bookmark.component.html',
8+
styleUrls: ['./new-bookmark.component.scss'],
9+
})
10+
export class NewBookmarkComponent implements OnInit {
11+
bookmarkForm: FormGroup;
12+
13+
constructor(
14+
private bookmarkService: BookmarkService,
15+
private formBuilder: FormBuilder
16+
) {
17+
this.bookmarkForm = this.formBuilder.group({
18+
name: [
19+
'',
20+
Validators.compose([Validators.minLength(2), Validators.required]),
21+
],
22+
address: [
23+
'',
24+
Validators.compose([Validators.minLength(10), Validators.required]),
25+
],
26+
});
27+
}
28+
29+
ngOnInit() {}
30+
31+
async createBookmark(form: FormGroup) {
32+
form.markAllAsTouched();
33+
if (form.valid) {
34+
const { name, address } = form.value;
35+
await this.bookmarkService
36+
.createBookmark({ name, address })
37+
.then((success) => {
38+
if (success) {
39+
form.reset();
40+
}
41+
});
42+
}
43+
}
44+
}

web-client/src/app/components/pay-amount-form/pay-amount-form.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,6 @@
3838
shape="round"
3939
type="submit"
4040
[disabled]="!paymentForm.valid"
41-
>PAY
41+
>{{ buttonHeading }}
4242
</ion-button>
4343
</form>

web-client/src/app/components/pay-amount-form/pay-amount-form.component.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ export class PayAmountFormComponent implements OnInit, OnChanges {
4848
/** (Optional) Hook to set an initial amount value, if defined. */
4949
@Input() setInitialAmountValue?: string;
5050

51+
@Input() buttonHeading = 'PAY';
52+
5153
#paymentForm?: FormGroup;
5254

5355
constructor() {}

web-client/src/app/components/pin-entry/pin-entry.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<div class="inline-block w-auto m-auto">
33
<ion-icon name="lock-closed-outline" class="!text-5xl"></ion-icon>
44

5-
<h1 class="font-semibold font-nasalization">Enter Pin</h1>
5+
<h1 class="font-semibold font-nasalization">{{ titleHeading }}</h1>
66

77
<form [formGroup]="pinForm" (ngSubmit)="onSubmit()">
88
<div>

web-client/src/app/components/pin-entry/pin-entry.component.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ import { checkClass } from 'src/helpers/helpers';
1717
styleUrls: ['./pin-entry.component.scss'],
1818
})
1919
export class PinEntryComponent implements OnInit {
20+
@Input() titleHeading = '';
21+
2022
/** Emit the PIN confirmed by the user. */
2123
@Output() pinConfirmed = new EventEmitter<PinValue>();
2224

web-client/src/app/modules/shared/shared.module.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ import { NgxScannerQrcodeModule } from 'ngx-scanner-qrcode';
1111
import { ActionItemComponent } from 'src/app/components/action-item/action-item.component';
1212
import { AssetAccordionComponent } from 'src/app/components/asset-accordion/asset-accordion.component';
1313
import { BalanceSummaryCardComponent } from 'src/app/components/balance-summary-card/balance-summary-card.component';
14+
import { BookmarkListComponent } from 'src/app/components/bookmark-list/bookmark-list.component';
1415
import { LogoutButtonComponent } from 'src/app/components/logout-button/logout-button.component';
16+
import { NewBookmarkComponent } from 'src/app/components/new-bookmark/new-bookmark.component';
1517
import { ProfileCardHorizontalComponent } from 'src/app/components/profile-card-horizontal/profile-card-horizontal.component';
1618
import { SecurityQuestionsComponent } from 'src/app/components/security-questions/security-questions.component';
1719
import { AssetPipesModule } from 'src/app/pipes/asset-pipes.module';
@@ -24,6 +26,8 @@ import { AssetPipesModule } from 'src/app/pipes/asset-pipes.module';
2426
BalanceSummaryCardComponent,
2527
AssetAccordionComponent,
2628
LogoutButtonComponent,
29+
NewBookmarkComponent,
30+
BookmarkListComponent,
2731
],
2832
imports: [
2933
IonicModule,
@@ -48,6 +52,8 @@ import { AssetPipesModule } from 'src/app/pipes/asset-pipes.module';
4852
BalanceSummaryCardComponent,
4953
AssetAccordionComponent,
5054
LogoutButtonComponent,
55+
NewBookmarkComponent,
56+
BookmarkListComponent,
5157
NgxScannerQrcodeModule,
5258
],
5359
providers: [Printer],
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { HttpClientTestingModule } from '@angular/common/http/testing';
2+
import { TestBed } from '@angular/core/testing';
3+
import { RouterTestingModule } from '@angular/router/testing';
4+
import { AutoLogoutService } from './auto-logout.service';
5+
6+
describe('AutoLogoutService', () => {
7+
let service: AutoLogoutService;
8+
9+
beforeEach(() => {
10+
TestBed.configureTestingModule({
11+
imports: [HttpClientTestingModule, RouterTestingModule],
12+
});
13+
service = TestBed.inject(AutoLogoutService);
14+
});
15+
16+
it('should be created', () => {
17+
expect(service).toBeTruthy();
18+
});
19+
});

0 commit comments

Comments
 (0)