1
1
import { Component } from '@angular/core' ;
2
- import { MatDialog } from '@angular/material/dialog' ;
3
- import { MatSnackBar } from '@angular/material/snack-bar' ;
4
2
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' ;
11
5
import {
12
6
Action ,
13
7
ActionsService ,
14
8
} 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' ;
24
9
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' ;
33
10
34
11
@UntilDestroy ( )
35
12
@Component ( {
@@ -42,270 +19,17 @@ export class ActionsPage {
42
19
. getActions$ ( )
43
20
. pipe ( catchError ( ( err : unknown ) => this . errorService . toastError$ ( err ) ) ) ;
44
21
45
- private readonly id$ = this . route . paramMap . pipe (
46
- map ( params => params . get ( 'id' ) ) ,
47
- isNonNullable ( )
48
- ) ;
49
-
50
22
constructor (
51
23
private readonly router : Router ,
52
24
private readonly actionsService : ActionsService ,
53
25
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
67
27
) { }
68
28
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
-
236
29
performAction ( action : Action ) {
237
30
this . router . navigate ( [ 'action-details' ] , {
238
31
relativeTo : this . route ,
239
32
state : action ,
240
33
} ) ;
241
34
}
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 ;
311
35
}
0 commit comments