Skip to content

Commit d156166

Browse files
committed
fix(features/home): network action default value
Fix the default value for network action by removing the extra space, and ensure the default_values_list_text field is handled if it's missing in the response. Fix the issue where the button color doesn't change on the network action detail page when it is disabled. Remove the unused ActionsDialogComponent.
1 parent c70d5dc commit d156166

File tree

12 files changed

+19
-488
lines changed

12 files changed

+19
-488
lines changed

src/app/features/home/details/actions/action-details/action-details.page.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,14 @@
3333
<div class="price-number">{{ price$ | async }} NUM</div>
3434
</div>
3535

36-
<button
36+
<ion-button
3737
type="submit"
38-
class="custom-button"
38+
shape="round"
3939
[disabled]="!form.form.valid"
4040
(click)="performAction(form.model)"
4141
>
4242
{{ title$ | async | uppercase }}
43-
</button>
43+
</ion-button>
4444
</ion-footer>
4545
</ng-container>
4646

src/app/features/home/details/actions/action-details/action-details.page.scss

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -72,28 +72,6 @@ ion-footer {
7272
font-weight: 700;
7373
}
7474
}
75-
76-
.custom-button {
77-
padding: 16px 20px;
78-
background-color: #3880ff;
79-
color: white;
80-
border: none;
81-
border-radius: 37px;
82-
cursor: pointer;
83-
white-space: nowrap;
84-
overflow: hidden;
85-
text-overflow: ellipsis;
86-
font-size: 13px;
87-
font-style: normal;
88-
font-weight: 600;
89-
line-height: normal;
90-
letter-spacing: 0.26px;
91-
text-transform: uppercase;
92-
93-
&:hover {
94-
background-color: #0056b3;
95-
}
96-
}
9775
}
9876

9977
ion-spinner {

src/app/features/home/details/actions/action-details/action-details.page.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,9 @@ export class ActionDetailsPage {
123123
const formModel: any = {};
124124

125125
for (const param of params)
126-
formModel[param.name_text] = param.default_values_list_text[0] || '';
126+
formModel[param.name_text] = param.default_values_list_text?.length
127+
? param.default_values_list_text[0].trim()
128+
: '';
127129

128130
return formModel;
129131
}
@@ -140,10 +142,11 @@ export class ActionDetailsPage {
140142
key: param.name_text,
141143
type: 'select',
142144
templateOptions: {
143-
options: param.default_values_list_text.map(value => ({
144-
label: value,
145-
value: value,
146-
})),
145+
options:
146+
param.default_values_list_text?.map(value => ({
147+
label: value.trim(),
148+
value: value.trim(),
149+
})) ?? [],
147150
placeholder: param.placeholder_text,
148151
disabled: !param.user_input_boolean,
149152
required: !isOptional,
Lines changed: 3 additions & 279 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,12 @@
11
import { Component } from '@angular/core';
2-
import { MatDialog } from '@angular/material/dialog';
3-
import { MatSnackBar } from '@angular/material/snack-bar';
42
import { ActivatedRoute, Router } from '@angular/router';
5-
import { Browser } from '@capacitor/browser';
6-
import { TranslocoService } from '@ngneat/transloco';
7-
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
8-
import { combineLatest, forkJoin, iif, of } from 'rxjs';
9-
import { catchError, concatMap, first, map, take, tap } from 'rxjs/operators';
10-
import { ActionsDialogComponent } from '../../../../shared/actions/actions-dialog/actions-dialog.component';
3+
import { UntilDestroy } from '@ngneat/until-destroy';
4+
import { catchError } from 'rxjs/operators';
115
import {
126
Action,
137
ActionsService,
148
} from '../../../../shared/actions/service/actions.service';
15-
import { OrderHistoryService } from '../../../../shared/actions/service/order-history.service';
16-
import { BlockingActionService } from '../../../../shared/blocking-action/blocking-action.service';
17-
import { DiaBackendAuthService } from '../../../../shared/dia-backend/auth/dia-backend-auth.service';
18-
import { DiaBackendSeriesRepository } from '../../../../shared/dia-backend/series/dia-backend-series-repository.service';
19-
import {
20-
DiaBackendStoreService,
21-
NetworkAppOrder,
22-
} from '../../../../shared/dia-backend/store/dia-backend-store.service';
23-
import { DiaBackendWalletService } from '../../../../shared/dia-backend/wallet/dia-backend-wallet.service';
249
import { ErrorService } from '../../../../shared/error/error.service';
25-
import { OrderDetailDialogComponent } from '../../../../shared/order-detail-dialog/order-detail-dialog.component';
26-
import { ProofRepository } from '../../../../shared/repositories/proof/proof-repository.service';
27-
import { browserToolbarColor } from '../../../../utils/constants';
28-
import {
29-
VOID$,
30-
isNonNullable,
31-
} from '../../../../utils/rx-operators/rx-operators';
32-
import { InformationSessionService } from '../information/session/information-session.service';
3310

3411
@UntilDestroy()
3512
@Component({
@@ -42,270 +19,17 @@ export class ActionsPage {
4219
.getActions$()
4320
.pipe(catchError((err: unknown) => this.errorService.toastError$(err)));
4421

45-
private readonly id$ = this.route.paramMap.pipe(
46-
map(params => params.get('id')),
47-
isNonNullable()
48-
);
49-
5022
constructor(
5123
private readonly router: Router,
5224
private readonly actionsService: ActionsService,
5325
private readonly errorService: ErrorService,
54-
private readonly translocoService: TranslocoService,
55-
private readonly blockingActionService: BlockingActionService,
56-
private readonly route: ActivatedRoute,
57-
private readonly authService: DiaBackendAuthService,
58-
private readonly snackBar: MatSnackBar,
59-
private readonly dialog: MatDialog,
60-
private readonly storeService: DiaBackendStoreService,
61-
private readonly orderHistoryService: OrderHistoryService,
62-
private readonly diaBackendStoreService: DiaBackendStoreService,
63-
private readonly diaBackendSeriesRepository: DiaBackendSeriesRepository,
64-
private readonly diaBackendWalletService: DiaBackendWalletService,
65-
private readonly informationSessionService: InformationSessionService,
66-
private readonly proofRepository: ProofRepository
26+
private readonly route: ActivatedRoute
6727
) {}
6828

69-
canPerformAction$(action: Action) {
70-
if (action.title_text === 'List in CaptureClub') {
71-
/*
72-
Workaround:
73-
Currently there isn't a simple way to check whether an asset is listed in
74-
CaptureClub or not. So I first query List all Products API with
75-
associated_id parameter set to the assets cid. And then use list series
76-
API and check through all nested collections. See discussion here
77-
https://app.asana.com/0/0/1201558520076805/1201995911008176/f
78-
*/
79-
return this.id$.pipe(
80-
concatMap(cid =>
81-
forkJoin([
82-
this.diaBackendStoreService.listAllProducts$({
83-
associated_id: cid,
84-
service_name: 'CaptureClub',
85-
}),
86-
of(cid),
87-
])
88-
),
89-
concatMap(([response, cid]) => {
90-
if (response.count > 0) {
91-
throw new Error(
92-
this.translocoService.translate('message.hasListedInCaptureApp')
93-
);
94-
}
95-
return of(cid);
96-
}),
97-
concatMap(async cid => {
98-
let currentOffset = 0;
99-
const limit = 100;
100-
while (true) {
101-
const response = await this.diaBackendSeriesRepository
102-
.fetchAll$({ offset: currentOffset, limit })
103-
.toPromise();
104-
const listedAsSeries = response.results.some(serie =>
105-
serie.collections.some(collection =>
106-
collection.assets.some(asset => asset.cid === cid)
107-
)
108-
);
109-
if (listedAsSeries) {
110-
throw new Error(
111-
this.translocoService.translate('message.hasListedInCaptureApp')
112-
);
113-
}
114-
if (response.next == null) {
115-
break;
116-
}
117-
currentOffset += response.results.length;
118-
}
119-
return VOID$;
120-
}),
121-
take(1)
122-
);
123-
}
124-
return VOID$;
125-
}
126-
127-
openActionDialog$(action: Action) {
128-
return combineLatest([
129-
this.actionsService.getParams$(action.params_list_custom_param1 ?? []),
130-
this.authService.token$,
131-
this.id$,
132-
]).pipe(
133-
first(),
134-
concatMap(([params, token, id]) => {
135-
const dialogRef = this.dialog.open<ActionsDialogComponent>(
136-
ActionsDialogComponent,
137-
{
138-
disableClose: true,
139-
data: {
140-
action: action,
141-
params: params,
142-
},
143-
}
144-
);
145-
return dialogRef.afterClosed().pipe(
146-
isNonNullable(),
147-
concatMap(data =>
148-
of({
149-
networkApp: action.network_app_id_text,
150-
actionArgs: { ...data, token: token, cid: id },
151-
} as CreateOrderInput)
152-
)
153-
);
154-
})
155-
);
156-
}
157-
158-
openOrderDialog$(orderStatus: NetworkAppOrder) {
159-
const dialogRef = this.dialog.open<OrderDetailDialogComponent>(
160-
OrderDetailDialogComponent,
161-
{
162-
disableClose: true,
163-
data: orderStatus,
164-
width: '80%',
165-
}
166-
);
167-
return dialogRef.afterClosed().pipe(
168-
isNonNullable(),
169-
concatMap((orderId: string) => of(orderId))
170-
);
171-
}
172-
173-
createOrder$(appName: string, actionArgs: any) {
174-
return this.storeService.createNetworkAppOrder(appName, actionArgs).pipe(
175-
catchError((err: unknown) =>
176-
this.errorService.toastDiaBackendError$(err)
177-
),
178-
isNonNullable()
179-
);
180-
}
181-
182-
confirmOrder$(id: string) {
183-
return this.storeService.confirmNetworkAppOrder(id).pipe(
184-
catchError((err: unknown) =>
185-
this.errorService.toastDiaBackendError$(err)
186-
),
187-
isNonNullable()
188-
);
189-
}
190-
191-
createOrderHistory$(networkAppOrder: NetworkAppOrder) {
192-
return this.id$.pipe(
193-
first(),
194-
isNonNullable(),
195-
concatMap(cid =>
196-
this.orderHistoryService.createOrderHistory$(networkAppOrder, cid)
197-
),
198-
catchError((err: unknown) => {
199-
return this.errorService.toastError$(err);
200-
})
201-
);
202-
}
203-
204-
redirectToExternalUrl(url: string, orderId: string) {
205-
this.id$
206-
.pipe(
207-
first(),
208-
isNonNullable(),
209-
tap(cid =>
210-
Browser.open({
211-
url: `${url}?cid=${cid}&order_id=${orderId}`,
212-
toolbarColor: browserToolbarColor,
213-
})
214-
),
215-
catchError((err: unknown) => {
216-
return this.errorService.toastError$(err);
217-
}),
218-
untilDestroyed(this)
219-
)
220-
.subscribe();
221-
}
222-
223-
removeCapture() {
224-
if (this.informationSessionService.activatedDetailedCapture) {
225-
this.informationSessionService.activatedDetailedCapture.proof$.subscribe(
226-
proof => {
227-
if (proof) {
228-
this.proofRepository.remove(proof);
229-
this.router.navigate(['/home']);
230-
}
231-
}
232-
);
233-
}
234-
}
235-
23629
performAction(action: Action) {
23730
this.router.navigate(['action-details'], {
23831
relativeTo: this.route,
23932
state: action,
24033
});
24134
}
242-
243-
doAction(action: Action) {
244-
this.blockingActionService
245-
.run$(this.canPerformAction$(action))
246-
.pipe(
247-
catchError((err: unknown) => {
248-
return this.errorService.toastError$(err);
249-
}),
250-
concatMap(() => this.openActionDialog$(action)),
251-
concatMap(createOrderInput =>
252-
this.blockingActionService.run$(
253-
forkJoin([
254-
this.createOrder$(
255-
createOrderInput.networkApp,
256-
createOrderInput.actionArgs
257-
),
258-
// To display "Insufficient NUM" in order confirmation dialog,
259-
// we need to sync asset wallet balance if the action cost NUM.
260-
iif(
261-
() => action.action_cost_number > 0,
262-
this.diaBackendWalletService.syncAssetWalletBalance$(),
263-
VOID$
264-
),
265-
])
266-
)
267-
),
268-
concatMap(([orderStatus, _]) => this.openOrderDialog$(orderStatus)),
269-
concatMap(orderId =>
270-
this.blockingActionService.run$(this.confirmOrder$(orderId))
271-
),
272-
tap(networkAppOrder => {
273-
/*
274-
Workaround:
275-
Create a order history record only if the total cost is > 0 to prevent race condition
276-
between app creating the order history record v.s. bubble workflow checking whether a
277-
record already exists and if not create a new one, especially for network actions that
278-
don't require any cost (and hence backend calls the webhook immediately). See
279-
https://dt42-numbers.slack.com/archives/C0323488MEJ/p1648006014291339
280-
*/
281-
if (Number(networkAppOrder.total_cost) !== 0) {
282-
this.createOrderHistory$(networkAppOrder).subscribe();
283-
}
284-
}),
285-
tap(() => {
286-
this.snackBar.open(
287-
this.translocoService.translate('message.sentSuccessfully')
288-
);
289-
}),
290-
tap(networkAppOrder => {
291-
if (action.ext_action_destination_text) {
292-
this.redirectToExternalUrl(
293-
action.ext_action_destination_text,
294-
networkAppOrder.id
295-
);
296-
}
297-
}),
298-
tap(() => {
299-
if (action.hide_capture_after_execution_boolean ?? false)
300-
this.removeCapture();
301-
}),
302-
untilDestroyed(this)
303-
)
304-
.subscribe();
305-
}
306-
}
307-
308-
interface CreateOrderInput {
309-
networkApp: string;
310-
actionArgs: any;
31135
}

0 commit comments

Comments
 (0)