diff options
author | muhamedsalih-tw <104364298+muhamedsalih-tw@users.noreply.github.com> | 2022-11-17 05:45:39 +0530 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-11-17 00:15:39 +0000 |
commit | d9502c7516bc2d4ae467c6ea8a2e4816b0885f37 (patch) | |
tree | b339c587a5529ac26d52cfc12d9972a8a00255e6 /src/stores | |
parent | Transform JSX components to TSX (#755) (diff) | |
download | ferdium-app-d9502c7516bc2d4ae467c6ea8a2e4816b0885f37.tar.gz ferdium-app-d9502c7516bc2d4ae467c6ea8a2e4816b0885f37.tar.zst ferdium-app-d9502c7516bc2d4ae467c6ea8a2e4816b0885f37.zip |
Transfrom workspace components to ts (#775)
Diffstat (limited to 'src/stores')
-rw-r--r-- | src/stores/AppStore.ts | 2 | ||||
-rw-r--r-- | src/stores/FeaturesStore.ts | 2 | ||||
-rw-r--r-- | src/stores/GlobalErrorStore.ts | 27 | ||||
-rw-r--r-- | src/stores/RecipesStore.ts | 10 | ||||
-rw-r--r-- | src/stores/RequestStore.ts | 3 | ||||
-rw-r--r-- | src/stores/ServicesStore.ts | 10 | ||||
-rw-r--r-- | src/stores/UserStore.ts | 17 | ||||
-rw-r--r-- | src/stores/lib/CachedRequest.ts (renamed from src/stores/lib/CachedRequest.js) | 49 | ||||
-rw-r--r-- | src/stores/lib/Request.ts (renamed from src/stores/lib/Request.js) | 106 |
9 files changed, 115 insertions, 111 deletions
diff --git a/src/stores/AppStore.ts b/src/stores/AppStore.ts index aab279e59..2db90bfa0 100644 --- a/src/stores/AppStore.ts +++ b/src/stores/AppStore.ts | |||
@@ -494,7 +494,7 @@ export default class AppStore extends TypedStore { | |||
494 | ), | 494 | ), |
495 | ); | 495 | ); |
496 | 496 | ||
497 | await clearAppCache._promise; | 497 | await clearAppCache.promise; |
498 | 498 | ||
499 | await sleep(ms('1s')); | 499 | await sleep(ms('1s')); |
500 | 500 | ||
diff --git a/src/stores/FeaturesStore.ts b/src/stores/FeaturesStore.ts index ed0c6c17b..5f43ccf84 100644 --- a/src/stores/FeaturesStore.ts +++ b/src/stores/FeaturesStore.ts | |||
@@ -45,7 +45,7 @@ export default class FeaturesStore extends TypedStore { | |||
45 | this._monitorLoginStatus.bind(this), | 45 | this._monitorLoginStatus.bind(this), |
46 | ]); | 46 | ]); |
47 | 47 | ||
48 | await this.featuresRequest._promise; | 48 | await this.featuresRequest.promise; |
49 | setTimeout(this._setupFeatures.bind(this), 1); | 49 | setTimeout(this._setupFeatures.bind(this), 1); |
50 | } | 50 | } |
51 | 51 | ||
diff --git a/src/stores/GlobalErrorStore.ts b/src/stores/GlobalErrorStore.ts index c42e9a4af..be86563d0 100644 --- a/src/stores/GlobalErrorStore.ts +++ b/src/stores/GlobalErrorStore.ts | |||
@@ -1,4 +1,5 @@ | |||
1 | import { observable, action, makeObservable } from 'mobx'; | 1 | import { observable, action, makeObservable } from 'mobx'; |
2 | import { Response } from 'electron'; | ||
2 | import { Actions } from '../actions/lib/actions'; | 3 | import { Actions } from '../actions/lib/actions'; |
3 | import { ApiInterface } from '../api'; | 4 | import { ApiInterface } from '../api'; |
4 | import { Stores } from '../@types/stores.types'; | 5 | import { Stores } from '../@types/stores.types'; |
@@ -11,12 +12,8 @@ interface Message { | |||
11 | message?: string; | 12 | message?: string; |
12 | status?: number; | 13 | status?: number; |
13 | }; | 14 | }; |
14 | request?: { | 15 | request?: Request; |
15 | result: any; | 16 | response?: Response; |
16 | wasExecuted: any; | ||
17 | method: any; | ||
18 | }; | ||
19 | response?: any; | ||
20 | server?: any; | 17 | server?: any; |
21 | info?: any; | 18 | info?: any; |
22 | url?: string; | 19 | url?: string; |
@@ -28,7 +25,7 @@ export default class GlobalErrorStore extends TypedStore { | |||
28 | 25 | ||
29 | @observable messages: Message[] = []; | 26 | @observable messages: Message[] = []; |
30 | 27 | ||
31 | @observable response: object = {}; | 28 | @observable response: Response = {} as Response; |
32 | 29 | ||
33 | // TODO: Get rid of the @ts-ignores in this function. | 30 | // TODO: Get rid of the @ts-ignores in this function. |
34 | constructor(stores: Stores, api: ApiInterface, actions: Actions) { | 31 | constructor(stores: Stores, api: ApiInterface, actions: Actions) { |
@@ -85,21 +82,15 @@ export default class GlobalErrorStore extends TypedStore { | |||
85 | } | 82 | } |
86 | } | 83 | } |
87 | 84 | ||
88 | @action _handleRequests = async (request: { | 85 | @action _handleRequests = async (request: Request): Promise<void> => { |
89 | isError: any; | ||
90 | error: { json: () => object | PromiseLike<object> }; | ||
91 | result: any; | ||
92 | wasExecuted: any; | ||
93 | _method: any; | ||
94 | }): Promise<void> => { | ||
95 | if (request.isError) { | 86 | if (request.isError) { |
96 | this.error = request.error; | 87 | this.error = request.error; |
97 | 88 | ||
98 | if (request.error.json) { | 89 | if (request.error && request.error.json) { |
99 | try { | 90 | try { |
100 | this.response = await request.error.json(); | 91 | this.response = await request.error.json(); |
101 | } catch { | 92 | } catch { |
102 | this.response = {}; | 93 | this.response = {} as Response; |
103 | } | 94 | } |
104 | if (this.error?.status === 401) { | 95 | if (this.error?.status === 401) { |
105 | window['ferdium'].stores.app.authRequestFailed = true; | 96 | window['ferdium'].stores.app.authRequestFailed = true; |
@@ -111,8 +102,8 @@ export default class GlobalErrorStore extends TypedStore { | |||
111 | request: { | 102 | request: { |
112 | result: request.result, | 103 | result: request.result, |
113 | wasExecuted: request.wasExecuted, | 104 | wasExecuted: request.wasExecuted, |
114 | method: request._method, | 105 | method: request.method, |
115 | }, | 106 | } as Request, |
116 | error: this.error, | 107 | error: this.error, |
117 | response: this.response, | 108 | response: this.response, |
118 | server: window['ferdium'].stores.settings.app.server, | 109 | server: window['ferdium'].stores.settings.app.server, |
diff --git a/src/stores/RecipesStore.ts b/src/stores/RecipesStore.ts index 25304e97c..07f1343f8 100644 --- a/src/stores/RecipesStore.ts +++ b/src/stores/RecipesStore.ts | |||
@@ -74,8 +74,8 @@ export default class RecipesStore extends TypedStore { | |||
74 | 74 | ||
75 | // Actions | 75 | // Actions |
76 | async _install({ recipeId }): Promise<Recipe> { | 76 | async _install({ recipeId }): Promise<Recipe> { |
77 | const recipe = await this.installRecipeRequest.execute(recipeId)._promise; | 77 | const recipe = await this.installRecipeRequest.execute(recipeId).promise; |
78 | await this.allRecipesRequest.invalidate({ immediately: true })._promise; | 78 | await this.allRecipesRequest.invalidate({ immediately: true }).promise; |
79 | 79 | ||
80 | return recipe; | 80 | return recipe; |
81 | } | 81 | } |
@@ -128,7 +128,7 @@ export default class RecipesStore extends TypedStore { | |||
128 | const update = updates[i]; | 128 | const update = updates[i]; |
129 | 129 | ||
130 | this.actions.recipe.install({ recipeId: update }); | 130 | this.actions.recipe.install({ recipeId: update }); |
131 | await this.installRecipeRequest._promise; | 131 | await this.installRecipeRequest.promise; |
132 | 132 | ||
133 | this.installRecipeRequest.reset(); | 133 | this.installRecipeRequest.reset(); |
134 | 134 | ||
@@ -158,10 +158,10 @@ export default class RecipesStore extends TypedStore { | |||
158 | debug(`Recipe ${recipeId} is not installed, trying to install it`); | 158 | debug(`Recipe ${recipeId} is not installed, trying to install it`); |
159 | 159 | ||
160 | const recipe = await this.installRecipeRequest.execute(recipeId) | 160 | const recipe = await this.installRecipeRequest.execute(recipeId) |
161 | ._promise; | 161 | .promise; |
162 | if (recipe) { | 162 | if (recipe) { |
163 | await this.allRecipesRequest.invalidate({ immediately: true }) | 163 | await this.allRecipesRequest.invalidate({ immediately: true }) |
164 | ._promise; | 164 | .promise; |
165 | router.push(`/settings/services/add/${recipeId}`); | 165 | router.push(`/settings/services/add/${recipeId}`); |
166 | } else { | 166 | } else { |
167 | router.push('/settings/recipes'); | 167 | router.push('/settings/recipes'); |
diff --git a/src/stores/RequestStore.ts b/src/stores/RequestStore.ts index 279615e50..807f2d126 100644 --- a/src/stores/RequestStore.ts +++ b/src/stores/RequestStore.ts | |||
@@ -37,6 +37,9 @@ export default class RequestStore extends TypedStore { | |||
37 | ); | 37 | ); |
38 | 38 | ||
39 | this.registerReactions([this._autoRetry.bind(this)]); | 39 | this.registerReactions([this._autoRetry.bind(this)]); |
40 | |||
41 | this.userInfoRequest = {} as CachedRequest; | ||
42 | this.servicesRequest = {} as CachedRequest; | ||
40 | } | 43 | } |
41 | 44 | ||
42 | async setup(): Promise<void> { | 45 | async setup(): Promise<void> { |
diff --git a/src/stores/ServicesStore.ts b/src/stores/ServicesStore.ts index 74810b81f..4fdd9d5ad 100644 --- a/src/stores/ServicesStore.ts +++ b/src/stores/ServicesStore.ts | |||
@@ -477,7 +477,7 @@ export default class ServicesStore extends TypedStore { | |||
477 | : this._cleanUpTeamIdAndCustomUrl(recipeId, serviceData); | 477 | : this._cleanUpTeamIdAndCustomUrl(recipeId, serviceData); |
478 | 478 | ||
479 | const response = await this.createServiceRequest.execute(recipeId, data) | 479 | const response = await this.createServiceRequest.execute(recipeId, data) |
480 | ._promise; | 480 | .promise; |
481 | 481 | ||
482 | this.allServicesRequest.patch(result => { | 482 | this.allServicesRequest.patch(result => { |
483 | if (!result) return; | 483 | if (!result) return; |
@@ -536,7 +536,7 @@ export default class ServicesStore extends TypedStore { | |||
536 | 536 | ||
537 | const newData = serviceData; | 537 | const newData = serviceData; |
538 | if (serviceData.iconFile) { | 538 | if (serviceData.iconFile) { |
539 | await request._promise; | 539 | await request.promise; |
540 | 540 | ||
541 | newData.iconUrl = request.result.data.iconUrl; | 541 | newData.iconUrl = request.result.data.iconUrl; |
542 | newData.hasCustomUploadedIcon = true; | 542 | newData.hasCustomUploadedIcon = true; |
@@ -562,7 +562,7 @@ export default class ServicesStore extends TypedStore { | |||
562 | ); | 562 | ); |
563 | }); | 563 | }); |
564 | 564 | ||
565 | await request._promise; | 565 | await request.promise; |
566 | this.actionStatus = request.result.status; | 566 | this.actionStatus = request.result.status; |
567 | 567 | ||
568 | if (service.isEnabled) { | 568 | if (service.isEnabled) { |
@@ -596,7 +596,7 @@ export default class ServicesStore extends TypedStore { | |||
596 | remove(result, (c: Service) => c.id === serviceId); | 596 | remove(result, (c: Service) => c.id === serviceId); |
597 | }); | 597 | }); |
598 | 598 | ||
599 | await request._promise; | 599 | await request.promise; |
600 | this.actionStatus = request.result.status; | 600 | this.actionStatus = request.result.status; |
601 | } | 601 | } |
602 | 602 | ||
@@ -637,7 +637,7 @@ export default class ServicesStore extends TypedStore { | |||
637 | @action async _clearCache({ serviceId }) { | 637 | @action async _clearCache({ serviceId }) { |
638 | this.clearCacheRequest.reset(); | 638 | this.clearCacheRequest.reset(); |
639 | const request = this.clearCacheRequest.execute(serviceId); | 639 | const request = this.clearCacheRequest.execute(serviceId); |
640 | await request._promise; | 640 | await request.promise; |
641 | } | 641 | } |
642 | 642 | ||
643 | @action _setIsActive(service: Service, state: boolean): void { | 643 | @action _setIsActive(service: Service, state: boolean): void { |
diff --git a/src/stores/UserStore.ts b/src/stores/UserStore.ts index c5e67c966..6c8f8f20b 100644 --- a/src/stores/UserStore.ts +++ b/src/stores/UserStore.ts | |||
@@ -187,7 +187,7 @@ export default class UserStore extends TypedStore { | |||
187 | 187 | ||
188 | // Actions | 188 | // Actions |
189 | @action async _login({ email, password }): Promise<void> { | 189 | @action async _login({ email, password }): Promise<void> { |
190 | const authToken = await this.loginRequest.execute(email, password)._promise; | 190 | const authToken = await this.loginRequest.execute(email, password).promise; |
191 | this._setUserData(authToken); | 191 | this._setUserData(authToken); |
192 | 192 | ||
193 | this.stores.router.push('/'); | 193 | this.stores.router.push('/'); |
@@ -209,6 +209,8 @@ export default class UserStore extends TypedStore { | |||
209 | plan, | 209 | plan, |
210 | currency, | 210 | currency, |
211 | }): Promise<void> { | 211 | }): Promise<void> { |
212 | // TODO - [TS DEBT] Need to find a way proper to implement promise's then and catch in request class | ||
213 | // @ts-ignore | ||
212 | const authToken = await this.signupRequest.execute({ | 214 | const authToken = await this.signupRequest.execute({ |
213 | firstname, | 215 | firstname, |
214 | lastname, | 216 | lastname, |
@@ -231,14 +233,14 @@ export default class UserStore extends TypedStore { | |||
231 | @action async _retrievePassword({ email }): Promise<void> { | 233 | @action async _retrievePassword({ email }): Promise<void> { |
232 | const request = this.passwordRequest.execute(email); | 234 | const request = this.passwordRequest.execute(email); |
233 | 235 | ||
234 | await request._promise; | 236 | await request.promise; |
235 | this.actionStatus = request.result.status || []; | 237 | this.actionStatus = request.result.status || []; |
236 | } | 238 | } |
237 | 239 | ||
238 | @action async _invite({ invites }): Promise<void> { | 240 | @action async _invite({ invites }): Promise<void> { |
239 | const data = invites.filter(invite => invite.email !== ''); | 241 | const data = invites.filter(invite => invite.email !== ''); |
240 | 242 | ||
241 | const response = await this.inviteRequest.execute(data)._promise; | 243 | const response = await this.inviteRequest.execute(data).promise; |
242 | 244 | ||
243 | this.actionStatus = response.status || []; | 245 | this.actionStatus = response.status || []; |
244 | 246 | ||
@@ -251,8 +253,7 @@ export default class UserStore extends TypedStore { | |||
251 | @action async _update({ userData }): Promise<void> { | 253 | @action async _update({ userData }): Promise<void> { |
252 | if (!this.isLoggedIn) return; | 254 | if (!this.isLoggedIn) return; |
253 | 255 | ||
254 | const response = await this.updateUserInfoRequest.execute(userData) | 256 | const response = await this.updateUserInfoRequest.execute(userData).promise; |
255 | ._promise; | ||
256 | 257 | ||
257 | this.getUserInfoRequest.patch(() => response.data); | 258 | this.getUserInfoRequest.patch(() => response.data); |
258 | this.actionStatus = response.status || []; | 259 | this.actionStatus = response.status || []; |
@@ -299,7 +300,7 @@ export default class UserStore extends TypedStore { | |||
299 | data: service, | 300 | data: service, |
300 | }); | 301 | }); |
301 | // eslint-disable-next-line no-await-in-loop | 302 | // eslint-disable-next-line no-await-in-loop |
302 | await this.stores.services.createServiceRequest._promise; | 303 | await this.stores.services.createServiceRequest.promise; |
303 | } | 304 | } |
304 | 305 | ||
305 | this.isImportLegacyServicesExecuting = false; | 306 | this.isImportLegacyServicesExecuting = false; |
@@ -349,7 +350,7 @@ export default class UserStore extends TypedStore { | |||
349 | if (this.isLoggedIn) { | 350 | if (this.isLoggedIn) { |
350 | let data; | 351 | let data; |
351 | try { | 352 | try { |
352 | data = await this.getUserInfoRequest.execute()._promise; | 353 | data = await this.getUserInfoRequest.execute().promise; |
353 | } catch { | 354 | } catch { |
354 | return; | 355 | return; |
355 | } | 356 | } |
@@ -406,7 +407,7 @@ export default class UserStore extends TypedStore { | |||
406 | 407 | ||
407 | async _migrateUserLocale(): Promise<void> { | 408 | async _migrateUserLocale(): Promise<void> { |
408 | try { | 409 | try { |
409 | await this.getUserInfoRequest._promise; | 410 | await this.getUserInfoRequest.promise; |
410 | } catch { | 411 | } catch { |
411 | return; | 412 | return; |
412 | } | 413 | } |
diff --git a/src/stores/lib/CachedRequest.js b/src/stores/lib/CachedRequest.ts index a6dd47f7d..25cc365e2 100644 --- a/src/stores/lib/CachedRequest.js +++ b/src/stores/lib/CachedRequest.ts | |||
@@ -3,29 +3,33 @@ import { isEqual, remove } from 'lodash'; | |||
3 | import Request from './Request'; | 3 | import Request from './Request'; |
4 | 4 | ||
5 | export default class CachedRequest extends Request { | 5 | export default class CachedRequest extends Request { |
6 | _apiCalls = []; | 6 | _apiCalls: any[] = []; |
7 | 7 | ||
8 | _isInvalidated = true; | 8 | _isInvalidated = true; |
9 | 9 | ||
10 | execute(...callArgs) { | 10 | execute(...callArgs): this { |
11 | // Do not continue if this request is already loading | 11 | // Do not continue if this request is already loading |
12 | if (this._isWaitingForResponse) return this; | 12 | if (this.isWaitingForResponse) { |
13 | return this; | ||
14 | } | ||
13 | 15 | ||
14 | // Very simple caching strategy -> only continue if the call / args changed | 16 | // Very simple caching strategy -> only continue if the call / args changed |
15 | // or the request was invalidated manually from outside | 17 | // or the request was invalidated manually from outside |
16 | const existingApiCall = this._findApiCall(callArgs); | 18 | const existingApiCall = this._findApiCall(callArgs); |
17 | 19 | ||
18 | // Invalidate if new or different api call will be done | 20 | // Invalidate if new or different api call will be done |
19 | if (existingApiCall && existingApiCall !== this._currentApiCall) { | 21 | if (existingApiCall && existingApiCall !== this.currentApiCall) { |
20 | this._isInvalidated = true; | 22 | this._isInvalidated = true; |
21 | this._currentApiCall = existingApiCall; | 23 | this.currentApiCall = existingApiCall; |
22 | } else if (!existingApiCall) { | 24 | } else if (!existingApiCall) { |
23 | this._isInvalidated = true; | 25 | this._isInvalidated = true; |
24 | this._currentApiCall = this._addApiCall(callArgs); | 26 | this.currentApiCall = this._addApiCall(callArgs); |
25 | } | 27 | } |
26 | 28 | ||
27 | // Do not continue if this request is not invalidated (see above) | 29 | // Do not continue if this request is not invalidated (see above) |
28 | if (!this._isInvalidated) return this; | 30 | if (!this._isInvalidated) { |
31 | return this; | ||
32 | } | ||
29 | 33 | ||
30 | // This timeout is necessary to avoid warnings from mobx | 34 | // This timeout is necessary to avoid warnings from mobx |
31 | // regarding triggering actions as side-effect of getters | 35 | // regarding triggering actions as side-effect of getters |
@@ -41,18 +45,18 @@ export default class CachedRequest extends Request { | |||
41 | ); | 45 | ); |
42 | 46 | ||
43 | // Issue api call & save it as promise that is handled to update the results of the operation | 47 | // Issue api call & save it as promise that is handled to update the results of the operation |
44 | this._promise = new Promise(resolve => { | 48 | this.promise = new Promise(resolve => { |
45 | this._api[this._method](...callArgs) | 49 | this.api[this.method](...callArgs) |
46 | .then(result => { | 50 | .then(result => { |
47 | setTimeout( | 51 | setTimeout( |
48 | action(() => { | 52 | action(() => { |
49 | this.result = result; | 53 | this.result = result; |
50 | if (this._currentApiCall) this._currentApiCall.result = result; | 54 | if (this.currentApiCall) this.currentApiCall.result = result; |
51 | this.isExecuting = false; | 55 | this.isExecuting = false; |
52 | this.isError = false; | 56 | this.isError = false; |
53 | this.wasExecuted = true; | 57 | this.wasExecuted = true; |
54 | this._isInvalidated = false; | 58 | this._isInvalidated = false; |
55 | this._isWaitingForResponse = false; | 59 | this.isWaitingForResponse = false; |
56 | this._triggerHooks(); | 60 | this._triggerHooks(); |
57 | resolve(result); | 61 | resolve(result); |
58 | }), | 62 | }), |
@@ -68,7 +72,7 @@ export default class CachedRequest extends Request { | |||
68 | this.isExecuting = false; | 72 | this.isExecuting = false; |
69 | this.isError = true; | 73 | this.isError = true; |
70 | this.wasExecuted = true; | 74 | this.wasExecuted = true; |
71 | this._isWaitingForResponse = false; | 75 | this.isWaitingForResponse = false; |
72 | this._triggerHooks(); | 76 | this._triggerHooks(); |
73 | // reject(error); | 77 | // reject(error); |
74 | }), | 78 | }), |
@@ -78,26 +82,27 @@ export default class CachedRequest extends Request { | |||
78 | ); | 82 | ); |
79 | }); | 83 | }); |
80 | 84 | ||
81 | this._isWaitingForResponse = true; | 85 | this.isWaitingForResponse = true; |
82 | return this; | 86 | return this; |
83 | } | 87 | } |
84 | 88 | ||
85 | // eslint-disable-next-line unicorn/no-object-as-default-parameter | 89 | static defaultOptions = { immediately: false }; |
86 | invalidate(options = { immediately: false }) { | 90 | |
91 | invalidate(options = CachedRequest.defaultOptions): this { | ||
87 | this._isInvalidated = true; | 92 | this._isInvalidated = true; |
88 | if (options.immediately && this._currentApiCall) { | 93 | if (options.immediately && this.currentApiCall) { |
89 | return this.execute(...this._currentApiCall.args); | 94 | return this.execute(...this.currentApiCall.args); |
90 | } | 95 | } |
91 | return this; | 96 | return this; |
92 | } | 97 | } |
93 | 98 | ||
94 | patch(modify) { | 99 | patch(modify): Promise<this> { |
95 | return new Promise(resolve => { | 100 | return new Promise(resolve => { |
96 | setTimeout( | 101 | setTimeout( |
97 | action(() => { | 102 | action(() => { |
98 | const override = modify(this.result); | 103 | const override = modify(this.result); |
99 | if (override !== undefined) this.result = override; | 104 | if (override !== undefined) this.result = override; |
100 | if (this._currentApiCall) this._currentApiCall.result = this.result; | 105 | if (this.currentApiCall) this.currentApiCall.result = this.result; |
101 | resolve(this); | 106 | resolve(this); |
102 | }), | 107 | }), |
103 | 0, | 108 | 0, |
@@ -105,17 +110,17 @@ export default class CachedRequest extends Request { | |||
105 | }); | 110 | }); |
106 | } | 111 | } |
107 | 112 | ||
108 | removeCacheForCallWith(...args) { | 113 | removeCacheForCallWith(...args: any): void { |
109 | remove(this._apiCalls, c => isEqual(c.args, args)); | 114 | remove(this._apiCalls, c => isEqual(c.args, args)); |
110 | } | 115 | } |
111 | 116 | ||
112 | _addApiCall(args) { | 117 | _addApiCall(args: any) { |
113 | const newCall = { args, result: null }; | 118 | const newCall = { args, result: null }; |
114 | this._apiCalls.push(newCall); | 119 | this._apiCalls.push(newCall); |
115 | return newCall; | 120 | return newCall; |
116 | } | 121 | } |
117 | 122 | ||
118 | _findApiCall(args) { | 123 | _findApiCall(args: any) { |
119 | return this._apiCalls.find(c => isEqual(c.args, args)); | 124 | return this._apiCalls.find(c => isEqual(c.args, args)); |
120 | } | 125 | } |
121 | } | 126 | } |
diff --git a/src/stores/lib/Request.js b/src/stores/lib/Request.ts index 60c943a42..f9424ac99 100644 --- a/src/stores/lib/Request.js +++ b/src/stores/lib/Request.ts | |||
@@ -1,16 +1,18 @@ | |||
1 | import { observable, action, computed, makeObservable } from 'mobx'; | 1 | import { observable, action, computed, makeObservable } from 'mobx'; |
2 | import { isEqual } from 'lodash/fp'; | 2 | import { isEqual } from 'lodash/fp'; |
3 | 3 | ||
4 | type Hook = (request: Request) => void; | ||
5 | |||
4 | export default class Request { | 6 | export default class Request { |
5 | static _hooks = []; | 7 | static _hooks: Hook[] = []; |
6 | 8 | ||
7 | static registerHook(hook) { | 9 | static registerHook(hook: Hook) { |
8 | Request._hooks.push(hook); | 10 | Request._hooks.push(hook); |
9 | } | 11 | } |
10 | 12 | ||
11 | @observable result = null; | 13 | @observable result: any = null; |
12 | 14 | ||
13 | @observable error = null; | 15 | @observable error: any = null; |
14 | 16 | ||
15 | @observable isExecuting = false; | 17 | @observable isExecuting = false; |
16 | 18 | ||
@@ -18,43 +20,47 @@ export default class Request { | |||
18 | 20 | ||
19 | @observable wasExecuted = false; | 21 | @observable wasExecuted = false; |
20 | 22 | ||
21 | @action _reset() { | 23 | promise: any = Promise; |
22 | this.error = null; | ||
23 | this.result = null; | ||
24 | this.isExecuting = false; | ||
25 | this.isError = false; | ||
26 | this.wasExecuted = false; | ||
27 | this._isWaitingForResponse = false; | ||
28 | this._promise = Promise; | ||
29 | 24 | ||
30 | return this; | 25 | protected api: any = {}; |
31 | } | ||
32 | 26 | ||
33 | _promise = Promise; | 27 | method = ''; |
34 | 28 | ||
35 | _api = {}; | 29 | protected isWaitingForResponse = false; |
36 | 30 | ||
37 | _method = ''; | 31 | protected currentApiCall: any = null; |
38 | 32 | ||
39 | _isWaitingForResponse = false; | 33 | retry = () => this.reload(); |
40 | 34 | ||
41 | _currentApiCall = null; | 35 | reset = () => this._reset(); |
42 | 36 | ||
43 | constructor(api, method) { | 37 | constructor(api, method) { |
44 | makeObservable(this); | 38 | makeObservable(this); |
45 | 39 | ||
46 | this._api = api; | 40 | this.api = api; |
47 | this._method = method; | 41 | this.method = method; |
42 | } | ||
43 | |||
44 | @action _reset(): this { | ||
45 | this.error = null; | ||
46 | this.result = null; | ||
47 | this.isExecuting = false; | ||
48 | this.isError = false; | ||
49 | this.wasExecuted = false; | ||
50 | this.isWaitingForResponse = false; | ||
51 | this.promise = Promise; | ||
52 | |||
53 | return this; | ||
48 | } | 54 | } |
49 | 55 | ||
50 | execute(...callArgs) { | 56 | execute(...callArgs: any[]): this { |
51 | // Do not continue if this request is already loading | 57 | // Do not continue if this request is already loading |
52 | if (this._isWaitingForResponse) return this; | 58 | if (this.isWaitingForResponse) return this; |
53 | 59 | ||
54 | if (!this._api[this._method]) { | 60 | if (!this.api[this.method]) { |
55 | throw new Error( | 61 | throw new Error( |
56 | `Missing method <${this._method}> on api object:`, | 62 | `Missing method <${this.method}> on api object:`, |
57 | this._api, | 63 | this.api, |
58 | ); | 64 | ); |
59 | } | 65 | } |
60 | 66 | ||
@@ -68,18 +74,18 @@ export default class Request { | |||
68 | ); | 74 | ); |
69 | 75 | ||
70 | // Issue api call & save it as promise that is handled to update the results of the operation | 76 | // Issue api call & save it as promise that is handled to update the results of the operation |
71 | this._promise = new Promise((resolve, reject) => { | 77 | this.promise = new Promise((resolve, reject) => { |
72 | this._api[this._method](...callArgs) | 78 | this.api[this.method](...callArgs) |
73 | .then(result => { | 79 | .then(result => { |
74 | setTimeout( | 80 | setTimeout( |
75 | action(() => { | 81 | action(() => { |
76 | this.error = null; | 82 | this.error = null; |
77 | this.result = result; | 83 | this.result = result; |
78 | if (this._currentApiCall) this._currentApiCall.result = result; | 84 | if (this.currentApiCall) this.currentApiCall.result = result; |
79 | this.isExecuting = false; | 85 | this.isExecuting = false; |
80 | this.isError = false; | 86 | this.isError = false; |
81 | this.wasExecuted = true; | 87 | this.wasExecuted = true; |
82 | this._isWaitingForResponse = false; | 88 | this.isWaitingForResponse = false; |
83 | this._triggerHooks(); | 89 | this._triggerHooks(); |
84 | resolve(result); | 90 | resolve(result); |
85 | }), | 91 | }), |
@@ -95,7 +101,7 @@ export default class Request { | |||
95 | this.isExecuting = false; | 101 | this.isExecuting = false; |
96 | this.isError = true; | 102 | this.isError = true; |
97 | this.wasExecuted = true; | 103 | this.wasExecuted = true; |
98 | this._isWaitingForResponse = false; | 104 | this.isWaitingForResponse = false; |
99 | this._triggerHooks(); | 105 | this._triggerHooks(); |
100 | reject(error); | 106 | reject(error); |
101 | }), | 107 | }), |
@@ -105,51 +111,49 @@ export default class Request { | |||
105 | ); | 111 | ); |
106 | }); | 112 | }); |
107 | 113 | ||
108 | this._isWaitingForResponse = true; | 114 | this.isWaitingForResponse = true; |
109 | this._currentApiCall = { args: callArgs, result: null }; | 115 | this.currentApiCall = { args: callArgs, result: null }; |
110 | return this; | 116 | return this; |
111 | } | 117 | } |
112 | 118 | ||
113 | reload() { | 119 | reload(): this { |
114 | const args = this._currentApiCall ? this._currentApiCall.args : []; | 120 | const args = this.currentApiCall ? this.currentApiCall.args : []; |
115 | this.error = null; | 121 | this.error = null; |
116 | return this.execute(...args); | 122 | return this.execute(...args); |
117 | } | 123 | } |
118 | 124 | ||
119 | retry = () => this.reload(); | 125 | isExecutingWithArgs(...args: any[]): boolean { |
120 | |||
121 | isExecutingWithArgs(...args) { | ||
122 | return ( | 126 | return ( |
123 | this.isExecuting && | 127 | this.isExecuting && |
124 | this._currentApiCall && | 128 | this.currentApiCall && |
125 | isEqual(this._currentApiCall.args, args) | 129 | isEqual(this.currentApiCall.args, args) |
126 | ); | 130 | ); |
127 | } | 131 | } |
128 | 132 | ||
129 | @computed get isExecutingFirstTime() { | 133 | @computed get isExecutingFirstTime(): boolean { |
130 | return !this.wasExecuted && this.isExecuting; | 134 | return !this.wasExecuted && this.isExecuting; |
131 | } | 135 | } |
132 | 136 | ||
133 | /* eslint-disable unicorn/no-thenable */ | 137 | /* eslint-disable unicorn/no-thenable */ |
134 | then(...args) { | 138 | then(...args: any[]) { |
135 | if (!this._promise) | 139 | if (!this.promise) |
136 | throw new Error( | 140 | throw new Error( |
137 | 'You have to call Request::execute before you can access it as promise', | 141 | 'You have to call Request::execute before you can access it as promise', |
138 | ); | 142 | ); |
139 | return this._promise.then(...args); | 143 | return this.promise.then(...args); |
140 | } | 144 | } |
141 | 145 | ||
142 | catch(...args) { | 146 | catch(...args: any[]) { |
143 | if (!this._promise) | 147 | if (!this.promise) |
144 | throw new Error( | 148 | throw new Error( |
145 | 'You have to call Request::execute before you can access it as promise', | 149 | 'You have to call Request::execute before you can access it as promise', |
146 | ); | 150 | ); |
147 | return this._promise.catch(...args); | 151 | return this.promise.catch(...args); |
148 | } | 152 | } |
149 | 153 | ||
150 | _triggerHooks() { | 154 | _triggerHooks(): void { |
151 | for (const hook of Request._hooks) hook(this); | 155 | for (const hook of Request._hooks) { |
156 | hook(this); | ||
157 | } | ||
152 | } | 158 | } |
153 | |||
154 | reset = () => this._reset(); | ||
155 | } | 159 | } |