forked from EVOgeek/Vmeda.Online
		
	MOBILE-3565 core: Migrate some core classes
This commit is contained in:
		
							parent
							
								
									1e979b57bb
								
							
						
					
					
						commit
						811bb39781
					
				
							
								
								
									
										352
									
								
								src/app/classes/delegate.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										352
									
								
								src/app/classes/delegate.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,352 @@ | |||||||
|  | // (C) Copyright 2015 Moodle Pty Ltd.
 | ||||||
|  | //
 | ||||||
|  | // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||||
|  | // you may not use this file except in compliance with the License.
 | ||||||
|  | // You may obtain a copy of the License at
 | ||||||
|  | //
 | ||||||
|  | //     http://www.apache.org/licenses/LICENSE-2.0
 | ||||||
|  | //
 | ||||||
|  | // Unless required by applicable law or agreed to in writing, software
 | ||||||
|  | // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||||
|  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||||
|  | // See the License for the specific language governing permissions and
 | ||||||
|  | // limitations under the License.
 | ||||||
|  | 
 | ||||||
|  | import { CoreSites } from '@services/sites'; | ||||||
|  | import { CoreEvents, CoreEventsProvider } from '@services/events'; | ||||||
|  | import { CoreSite } from '@classes/site'; | ||||||
|  | import { CoreLogger } from '@singletons/logger'; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Superclass to help creating delegates | ||||||
|  |  */ | ||||||
|  | export class CoreDelegate { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Logger instance. | ||||||
|  |      */ | ||||||
|  |     protected logger: CoreLogger; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * List of registered handlers. | ||||||
|  |      */ | ||||||
|  |     protected handlers: { [s: string]: CoreDelegateHandler } = {}; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * List of registered handlers enabled for the current site. | ||||||
|  |      */ | ||||||
|  |     protected enabledHandlers: { [s: string]: CoreDelegateHandler } = {}; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Default handler | ||||||
|  |      */ | ||||||
|  |     protected defaultHandler: CoreDelegateHandler; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Time when last updateHandler functions started. | ||||||
|  |      */ | ||||||
|  |     protected lastUpdateHandlersStart: number; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Feature prefix to check is feature is enabled or disabled in site. | ||||||
|  |      * This check is only made if not false. Override on the subclass or override isFeatureDisabled function. | ||||||
|  |      */ | ||||||
|  |     protected featurePrefix: string; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Name of the property to be used to index the handlers. By default, the handler's name will be used. | ||||||
|  |      * If your delegate uses a Moodle component name to identify the handlers, please override this property. | ||||||
|  |      * E.g. CoreCourseModuleDelegate uses 'modName' to index the handlers. | ||||||
|  |      */ | ||||||
|  |     protected handlerNameProperty = 'name'; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Set of promises to update a handler, to prevent doing the same operation twice. | ||||||
|  |      */ | ||||||
|  |     protected updatePromises: {[siteId: string]: {[name: string]: Promise<any>}} = {}; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Whether handlers have been initialized. | ||||||
|  |      */ | ||||||
|  |     protected handlersInitialized = false; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Promise to wait for handlers to be initialized. | ||||||
|  |      */ | ||||||
|  |     protected handlersInitPromise: Promise<any>; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Function to resolve the handlers init promise. | ||||||
|  |      */ | ||||||
|  |     protected handlersInitResolve: (value?: any) => void; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Constructor of the Delegate. | ||||||
|  |      * | ||||||
|  |      * @param delegateName Delegate name used for logging purposes. | ||||||
|  |      * @param listenSiteEvents Whether to update the handler when a site event occurs (login, site updated, ...). | ||||||
|  |      */ | ||||||
|  |     constructor(delegateName: string, listenSiteEvents?: boolean) { | ||||||
|  |         this.logger = CoreLogger.getInstance(delegateName); | ||||||
|  | 
 | ||||||
|  |         this.handlersInitPromise = new Promise((resolve): void => { | ||||||
|  |             this.handlersInitResolve = resolve; | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         if (listenSiteEvents) { | ||||||
|  |             // Update handlers on this cases.
 | ||||||
|  |             CoreEvents.instance.on(CoreEventsProvider.LOGIN, this.updateHandlers.bind(this)); | ||||||
|  |             CoreEvents.instance.on(CoreEventsProvider.SITE_UPDATED, this.updateHandlers.bind(this)); | ||||||
|  |             CoreEvents.instance.on(CoreEventsProvider.SITE_PLUGINS_LOADED, this.updateHandlers.bind(this)); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Execute a certain function in a enabled handler. | ||||||
|  |      * If the handler isn't found or function isn't defined, call the same function in the default handler. | ||||||
|  |      * | ||||||
|  |      * @param handlerName The handler name. | ||||||
|  |      * @param fnName Name of the function to execute. | ||||||
|  |      * @param params Parameters to pass to the function. | ||||||
|  |      * @return Function returned value or default value. | ||||||
|  |      */ | ||||||
|  |     protected executeFunctionOnEnabled(handlerName: string, fnName: string, params?: any[]): any { | ||||||
|  |         return this.execute(this.enabledHandlers[handlerName], fnName, params); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Execute a certain function in a handler. | ||||||
|  |      * If the handler isn't found or function isn't defined, call the same function in the default handler. | ||||||
|  |      * | ||||||
|  |      * @param handlerName The handler name. | ||||||
|  |      * @param fnName Name of the function to execute. | ||||||
|  |      * @param params Parameters to pass to the function. | ||||||
|  |      * @return Function returned value or default value. | ||||||
|  |      */ | ||||||
|  |     protected executeFunction(handlerName: string, fnName: string, params?: any[]): any { | ||||||
|  |         return this.execute(this.handlers[handlerName], fnName, params); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Execute a certain function in a handler. | ||||||
|  |      * If the handler isn't found or function isn't defined, call the same function in the default handler. | ||||||
|  |      * | ||||||
|  |      * @param handler The handler. | ||||||
|  |      * @param fnName Name of the function to execute. | ||||||
|  |      * @param params Parameters to pass to the function. | ||||||
|  |      * @return Function returned value or default value. | ||||||
|  |      */ | ||||||
|  |     private execute(handler: any, fnName: string, params?: any[]): any { | ||||||
|  |         if (handler && handler[fnName]) { | ||||||
|  |             return handler[fnName].apply(handler, params); | ||||||
|  |         } else if (this.defaultHandler && this.defaultHandler[fnName]) { | ||||||
|  |             return this.defaultHandler[fnName].apply(this.defaultHandler, params); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Get a handler. | ||||||
|  |      * | ||||||
|  |      * @param handlerName The handler name. | ||||||
|  |      * @param enabled Only enabled, or any. | ||||||
|  |      * @return Handler. | ||||||
|  |      */ | ||||||
|  |     protected getHandler(handlerName: string, enabled: boolean = false): CoreDelegateHandler { | ||||||
|  |         return enabled ? this.enabledHandlers[handlerName] : this.handlers[handlerName]; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Gets the handler full name for a given name. This is useful when the handlerNameProperty is different than "name". | ||||||
|  |      * E.g. blocks are indexed by blockName. If you call this function passing the blockName it will return the name. | ||||||
|  |      * | ||||||
|  |      * @param name Name used to indentify the handler. | ||||||
|  |      * @return Full name of corresponding handler. | ||||||
|  |      */ | ||||||
|  |     getHandlerName(name: string): string { | ||||||
|  |         const handler = this.getHandler(name, true); | ||||||
|  | 
 | ||||||
|  |         if (!handler) { | ||||||
|  |             return ''; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return handler.name; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Check if function exists on a handler. | ||||||
|  |      * | ||||||
|  |      * @param handlerName The handler name. | ||||||
|  |      * @param fnName Name of the function to execute. | ||||||
|  |      * @param onlyEnabled If check only enabled handlers or all. | ||||||
|  |      * @return Function returned value or default value. | ||||||
|  |      */ | ||||||
|  |     protected hasFunction(handlerName: string, fnName: string, onlyEnabled: boolean = true): any { | ||||||
|  |         const handler = onlyEnabled ? this.enabledHandlers[handlerName] : this.handlers[handlerName]; | ||||||
|  | 
 | ||||||
|  |         return handler && handler[fnName]; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Check if a handler name has a registered handler (not necessarily enabled). | ||||||
|  |      * | ||||||
|  |      * @param name The handler name. | ||||||
|  |      * @param enabled Only enabled, or any. | ||||||
|  |      * @return If the handler is registered or not. | ||||||
|  |      */ | ||||||
|  |     hasHandler(name: string, enabled: boolean = false): boolean { | ||||||
|  |         return enabled ? typeof this.enabledHandlers[name] !== 'undefined' : typeof this.handlers[name] !== 'undefined'; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Check if a time belongs to the last update handlers call. | ||||||
|  |      * This is to handle the cases where updateHandlers don't finish in the same order as they're called. | ||||||
|  |      * | ||||||
|  |      * @param time Time to check. | ||||||
|  |      * @return Whether it's the last call. | ||||||
|  |      */ | ||||||
|  |     isLastUpdateCall(time: number): boolean { | ||||||
|  |         if (!this.lastUpdateHandlersStart) { | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return time == this.lastUpdateHandlersStart; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Register a handler. | ||||||
|  |      * | ||||||
|  |      * @param handler The handler delegate object to register. | ||||||
|  |      * @return True when registered, false if already registered. | ||||||
|  |      */ | ||||||
|  |     registerHandler(handler: CoreDelegateHandler): boolean { | ||||||
|  |         const key = handler[this.handlerNameProperty] || handler.name; | ||||||
|  | 
 | ||||||
|  |         if (typeof this.handlers[key] !== 'undefined') { | ||||||
|  |             this.logger.log(`Handler '${handler[this.handlerNameProperty]}' already registered`); | ||||||
|  | 
 | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         this.logger.log(`Registered handler '${handler[this.handlerNameProperty]}'`); | ||||||
|  |         this.handlers[key] = handler; | ||||||
|  | 
 | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Update the handler for the current site. | ||||||
|  |      * | ||||||
|  |      * @param handler The handler to check. | ||||||
|  |      * @param time Time this update process started. | ||||||
|  |      * @return Resolved when done. | ||||||
|  |      */ | ||||||
|  |     protected updateHandler(handler: CoreDelegateHandler, time: number): Promise<void> { | ||||||
|  |         const siteId = CoreSites.instance.getCurrentSiteId(); | ||||||
|  |         const currentSite = CoreSites.instance.getCurrentSite(); | ||||||
|  |         let promise; | ||||||
|  | 
 | ||||||
|  |         if (this.updatePromises[siteId] && this.updatePromises[siteId][handler.name]) { | ||||||
|  |             // There's already an update ongoing for this handler, return the promise.
 | ||||||
|  |             return this.updatePromises[siteId][handler.name]; | ||||||
|  |         } else if (!this.updatePromises[siteId]) { | ||||||
|  |             this.updatePromises[siteId] = {}; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (!CoreSites.instance.isLoggedIn()) { | ||||||
|  |             promise = Promise.reject(null); | ||||||
|  |         } else if (this.isFeatureDisabled(handler, currentSite)) { | ||||||
|  |             promise = Promise.resolve(false); | ||||||
|  |         } else { | ||||||
|  |             promise = Promise.resolve(handler.isEnabled()); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // Checks if the handler is enabled.
 | ||||||
|  |         this.updatePromises[siteId][handler.name] = promise.catch(() => { | ||||||
|  |             return false; | ||||||
|  |         }).then((enabled: boolean) => { | ||||||
|  |             // Check that site hasn't changed since the check started.
 | ||||||
|  |             if (CoreSites.instance.getCurrentSiteId() === siteId) { | ||||||
|  |                 const key = handler[this.handlerNameProperty] || handler.name; | ||||||
|  | 
 | ||||||
|  |                 if (enabled) { | ||||||
|  |                     this.enabledHandlers[key] = handler; | ||||||
|  |                 } else { | ||||||
|  |                     delete this.enabledHandlers[key]; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         }).finally(() => { | ||||||
|  |             // Update finished, delete the promise.
 | ||||||
|  |             delete this.updatePromises[siteId][handler.name]; | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         return this.updatePromises[siteId][handler.name]; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Check if feature is enabled or disabled in the site, depending on the feature prefix and the handler name. | ||||||
|  |      * | ||||||
|  |      * @param handler Handler to check. | ||||||
|  |      * @param site Site to check. | ||||||
|  |      * @return Whether is enabled or disabled in site. | ||||||
|  |      */ | ||||||
|  |     protected isFeatureDisabled(handler: CoreDelegateHandler, site: CoreSite): boolean { | ||||||
|  |         return typeof this.featurePrefix != 'undefined' && site.isFeatureDisabled(this.featurePrefix + handler.name); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Update the handlers for the current site. | ||||||
|  |      * | ||||||
|  |      * @return Resolved when done. | ||||||
|  |      */ | ||||||
|  |     protected updateHandlers(): Promise<void> { | ||||||
|  |         const promises = [], | ||||||
|  |             now = Date.now(); | ||||||
|  | 
 | ||||||
|  |         this.logger.debug('Updating handlers for current site.'); | ||||||
|  | 
 | ||||||
|  |         this.lastUpdateHandlersStart = now; | ||||||
|  | 
 | ||||||
|  |         // Loop over all the handlers.
 | ||||||
|  |         for (const name in this.handlers) { | ||||||
|  |             promises.push(this.updateHandler(this.handlers[name], now)); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return Promise.all(promises).then(() => { | ||||||
|  |             return true; | ||||||
|  |         }, () => { | ||||||
|  |             // Never reject.
 | ||||||
|  |             return true; | ||||||
|  |         }).then(() => { | ||||||
|  | 
 | ||||||
|  |             // Verify that this call is the last one that was started.
 | ||||||
|  |             if (this.isLastUpdateCall(now)) { | ||||||
|  |                 this.handlersInitialized = true; | ||||||
|  |                 this.handlersInitResolve(); | ||||||
|  | 
 | ||||||
|  |                 this.updateData(); | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Update handlers Data. | ||||||
|  |      * Override this function to update handlers data. | ||||||
|  |      */ | ||||||
|  |     updateData(): any { | ||||||
|  |         // To be overridden.
 | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export interface CoreDelegateHandler { | ||||||
|  |     /** | ||||||
|  |      * Name of the handler, or name and sub context (AddonMessages, AddonMessages:blockContact, ...). | ||||||
|  |      * This name will be used to check if the feature is disabled. | ||||||
|  |      */ | ||||||
|  |     name: string; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Whether or not the handler is enabled on a site level. | ||||||
|  |      * @return Whether or not the handler is enabled on a site level. | ||||||
|  |      */ | ||||||
|  |     isEnabled(): boolean | Promise<boolean>; | ||||||
|  | } | ||||||
							
								
								
									
										33
									
								
								src/app/classes/error.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								src/app/classes/error.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,33 @@ | |||||||
|  | // (C) Copyright 2015 Moodle Pty Ltd.
 | ||||||
|  | //
 | ||||||
|  | // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||||
|  | // you may not use this file except in compliance with the License.
 | ||||||
|  | // You may obtain a copy of the License at
 | ||||||
|  | //
 | ||||||
|  | //     http://www.apache.org/licenses/LICENSE-2.0
 | ||||||
|  | //
 | ||||||
|  | // Unless required by applicable law or agreed to in writing, software
 | ||||||
|  | // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||||
|  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||||
|  | // See the License for the specific language governing permissions and
 | ||||||
|  | // limitations under the License.
 | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Base Error class. | ||||||
|  |  * | ||||||
|  |  * The native Error class cannot be extended in Typescript without restoring the prototype chain, extend this | ||||||
|  |  * class instead. | ||||||
|  |  * | ||||||
|  |  * @see https://stackoverflow.com/questions/41102060/typescript-extending-error-class
 | ||||||
|  |  */ | ||||||
|  | export class CoreError extends Error { | ||||||
|  | 
 | ||||||
|  |     constructor(message?: string) { | ||||||
|  |         super(message); | ||||||
|  | 
 | ||||||
|  |         // Fix prototype chain: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html#support-for-newtarget
 | ||||||
|  |         this.name = new.target.name; | ||||||
|  |         Object.setPrototypeOf(this, new.target.prototype); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
							
								
								
									
										77
									
								
								src/app/classes/interceptor.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								src/app/classes/interceptor.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,77 @@ | |||||||
|  | // (C) Copyright 2015 Moodle Pty Ltd.
 | ||||||
|  | //
 | ||||||
|  | // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||||
|  | // you may not use this file except in compliance with the License.
 | ||||||
|  | // You may obtain a copy of the License at
 | ||||||
|  | //
 | ||||||
|  | //     http://www.apache.org/licenses/LICENSE-2.0
 | ||||||
|  | //
 | ||||||
|  | // Unless required by applicable law or agreed to in writing, software
 | ||||||
|  | // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||||
|  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||||
|  | // See the License for the specific language governing permissions and
 | ||||||
|  | // limitations under the License.
 | ||||||
|  | 
 | ||||||
|  | import { Injectable } from '@angular/core'; | ||||||
|  | import { HttpInterceptor, HttpHandler, HttpRequest } from '@angular/common/http'; | ||||||
|  | import { Observable } from 'rxjs'; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Interceptor for Http calls. Adds the header 'Content-Type'='application/x-www-form-urlencoded' | ||||||
|  |  * and serializes the parameters if needed. | ||||||
|  |  */ | ||||||
|  | @Injectable() | ||||||
|  | export class CoreInterceptor implements HttpInterceptor { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Serialize an object to be used in a request. | ||||||
|  |      * | ||||||
|  |      * @param obj Object to serialize. | ||||||
|  |      * @param addNull Add null values to the serialized as empty parameters. | ||||||
|  |      * @return Serialization of the object. | ||||||
|  |      */ | ||||||
|  |     static serialize(obj: any, addNull?: boolean): string { | ||||||
|  |         let query = ''; | ||||||
|  |         let fullSubName; | ||||||
|  |         let subValue; | ||||||
|  |         let innerObj; | ||||||
|  | 
 | ||||||
|  |         for (const name in obj) { | ||||||
|  |             const value = obj[name]; | ||||||
|  | 
 | ||||||
|  |             if (value instanceof Array) { | ||||||
|  |                 for (let i = 0; i < value.length; ++i) { | ||||||
|  |                     subValue = value[i]; | ||||||
|  |                     fullSubName = name + '[' + i + ']'; | ||||||
|  |                     innerObj = {}; | ||||||
|  |                     innerObj[fullSubName] = subValue; | ||||||
|  |                     query += this.serialize(innerObj) + '&'; | ||||||
|  |                 } | ||||||
|  |             } else if (value instanceof Object) { | ||||||
|  |                 for (const subName in value) { | ||||||
|  |                     subValue = value[subName]; | ||||||
|  |                     fullSubName = name + '[' + subName + ']'; | ||||||
|  |                     innerObj = {}; | ||||||
|  |                     innerObj[fullSubName] = subValue; | ||||||
|  |                     query += this.serialize(innerObj) + '&'; | ||||||
|  |                 } | ||||||
|  |             } else if (addNull || (typeof value != 'undefined' && value !== null)) { | ||||||
|  |                 query += encodeURIComponent(name) + '=' + encodeURIComponent(value) + '&'; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return query.length ? query.substr(0, query.length - 1) : query; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     intercept(req: HttpRequest<any>, next: HttpHandler): Observable<any> { | ||||||
|  |         // Add the header and serialize the body if needed.
 | ||||||
|  |         const newReq = req.clone({ | ||||||
|  |             headers: req.headers.set('Content-Type', 'application/x-www-form-urlencoded'), | ||||||
|  |             body: typeof req.body == 'object' && String(req.body) != '[object File]' ? | ||||||
|  |                 CoreInterceptor.serialize(req.body) : req.body | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         // Pass on the cloned request instead of the original request.
 | ||||||
|  |         return next.handle(newReq); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										98
									
								
								src/app/classes/native-to-angular-http.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								src/app/classes/native-to-angular-http.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,98 @@ | |||||||
|  | // (C) Copyright 2015 Moodle Pty Ltd.
 | ||||||
|  | //
 | ||||||
|  | // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||||
|  | // you may not use this file except in compliance with the License.
 | ||||||
|  | // You may obtain a copy of the License at
 | ||||||
|  | //
 | ||||||
|  | //     http://www.apache.org/licenses/LICENSE-2.0
 | ||||||
|  | //
 | ||||||
|  | // Unless required by applicable law or agreed to in writing, software
 | ||||||
|  | // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||||
|  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||||
|  | // See the License for the specific language governing permissions and
 | ||||||
|  | // limitations under the License.
 | ||||||
|  | 
 | ||||||
|  | import { HttpResponse as AngularHttpResponse, HttpHeaders } from '@angular/common/http'; | ||||||
|  | import { HTTPResponse as NativeHttpResponse } from '@ionic-native/http'; | ||||||
|  | 
 | ||||||
|  | const HTTP_STATUS_MESSAGES = { | ||||||
|  |     100: 'Continue', | ||||||
|  |     101: 'Switching Protocol', | ||||||
|  |     102: 'Processing', | ||||||
|  |     103: 'Early Hints', | ||||||
|  |     200: 'OK', | ||||||
|  |     201: 'Created', | ||||||
|  |     202: 'Accepted', | ||||||
|  |     203: 'Non-Authoritative Information', | ||||||
|  |     204: 'No Content', | ||||||
|  |     205: 'Reset Content', | ||||||
|  |     206: 'Partial Content', | ||||||
|  |     207: 'Multi-Status', | ||||||
|  |     208: 'Already Reported', | ||||||
|  |     226: 'IM Used', | ||||||
|  |     300: 'Multiple Choice', | ||||||
|  |     301: 'Moved Permanently', | ||||||
|  |     302: 'Found', | ||||||
|  |     303: 'See Other', | ||||||
|  |     304: 'Not Modified', | ||||||
|  |     305: 'Use Proxy', | ||||||
|  |     306: 'unused', | ||||||
|  |     307: 'Temporary Redirect', | ||||||
|  |     308: 'Permanent Redirect', | ||||||
|  |     400: 'Bad Request', | ||||||
|  |     401: 'Unauthorized', | ||||||
|  |     402: 'Payment Required', | ||||||
|  |     403: 'Forbidden', | ||||||
|  |     404: 'Not Found', | ||||||
|  |     405: 'Method Not Allowed', | ||||||
|  |     406: 'Not Acceptable', | ||||||
|  |     407: 'Proxy Authentication Required', | ||||||
|  |     408: 'Request Timeout', | ||||||
|  |     409: 'Conflict', | ||||||
|  |     410: 'Gone', | ||||||
|  |     411: 'Length Required', | ||||||
|  |     412: 'Precondition Failed', | ||||||
|  |     413: 'Payload Too Large', | ||||||
|  |     414: 'URI Too Long', | ||||||
|  |     415: 'Unsupported Media Type', | ||||||
|  |     416: 'Range Not Satisfiable', | ||||||
|  |     417: 'Expectation Failed', | ||||||
|  |     418: 'I\'m a teapot', | ||||||
|  |     421: 'Misdirected Request', | ||||||
|  |     422: 'Unprocessable Entity', | ||||||
|  |     423: 'Locked', | ||||||
|  |     424: 'Failed Dependency', | ||||||
|  |     425: 'Too Early', | ||||||
|  |     426: 'Upgrade Required', | ||||||
|  |     428: 'Precondition Required', | ||||||
|  |     429: 'Too Many Requests', | ||||||
|  |     431: 'Request Header Fields Too Large', | ||||||
|  |     451: 'Unavailable For Legal Reasons', | ||||||
|  |     500: 'Internal Server Error', | ||||||
|  |     501: 'Not Implemented', | ||||||
|  |     502: 'Bad Gateway', | ||||||
|  |     503: 'Service Unavailable', | ||||||
|  |     504: 'Gateway Timeout', | ||||||
|  |     505: 'HTTP Version Not Supported', | ||||||
|  |     506: 'Variant Also Negotiates', | ||||||
|  |     507: 'Insufficient Storage', | ||||||
|  |     508: 'Loop Detected', | ||||||
|  |     510: 'Not Extended', | ||||||
|  |     511: 'Network Authentication Required', | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Class that adapts a Cordova plugin http response to an Angular http response. | ||||||
|  |  */ | ||||||
|  | export class CoreNativeToAngularHttpResponse<T> extends AngularHttpResponse<T> { | ||||||
|  | 
 | ||||||
|  |     constructor(protected nativeResponse: NativeHttpResponse) { | ||||||
|  |         super({ | ||||||
|  |             body: nativeResponse.data, | ||||||
|  |             headers: new HttpHeaders(nativeResponse.headers), | ||||||
|  |             status: nativeResponse.status, | ||||||
|  |             statusText: HTTP_STATUS_MESSAGES[nativeResponse.status] || '', | ||||||
|  |             url: nativeResponse.url || '' | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										143
									
								
								src/app/classes/queue-runner.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										143
									
								
								src/app/classes/queue-runner.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,143 @@ | |||||||
|  | // (C) Copyright 2015 Moodle Pty Ltd.
 | ||||||
|  | //
 | ||||||
|  | // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||||
|  | // you may not use this file except in compliance with the License.
 | ||||||
|  | // You may obtain a copy of the License at
 | ||||||
|  | //
 | ||||||
|  | //     http://www.apache.org/licenses/LICENSE-2.0
 | ||||||
|  | //
 | ||||||
|  | // Unless required by applicable law or agreed to in writing, software
 | ||||||
|  | // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||||
|  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||||
|  | // See the License for the specific language governing permissions and
 | ||||||
|  | // limitations under the License.
 | ||||||
|  | 
 | ||||||
|  | import { CoreUtils, PromiseDefer } from '@services/utils/utils'; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Function to add to the queue. | ||||||
|  |  */ | ||||||
|  | export type CoreQueueRunnerFunction<T> = (...args: any[]) => T | Promise<T>; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Queue item. | ||||||
|  |  */ | ||||||
|  | export type CoreQueueRunnerItem<T = any> = { | ||||||
|  |     /** | ||||||
|  |      * Item ID. | ||||||
|  |      */ | ||||||
|  |     id: string; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Function to execute. | ||||||
|  |      */ | ||||||
|  |     fn: CoreQueueRunnerFunction<T>; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Deferred with a promise resolved/rejected with the result of the function. | ||||||
|  |      */ | ||||||
|  |     deferred: PromiseDefer<T>; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Options to pass to add item. | ||||||
|  |  */ | ||||||
|  | export type CoreQueueRunnerAddOptions = { | ||||||
|  |     /** | ||||||
|  |      * Whether to allow having multiple entries with same ID in the queue. | ||||||
|  |      */ | ||||||
|  |     allowRepeated?: boolean; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * A queue to prevent having too many concurrent executions. | ||||||
|  |  */ | ||||||
|  | export class CoreQueueRunner { | ||||||
|  |     protected queue: {[id: string]: CoreQueueRunnerItem} = {}; | ||||||
|  |     protected orderedQueue: CoreQueueRunnerItem[] = []; | ||||||
|  |     protected numberRunning = 0; | ||||||
|  | 
 | ||||||
|  |     constructor(protected maxParallel: number = 1) { } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Get unique ID. | ||||||
|  |      * | ||||||
|  |      * @param id ID. | ||||||
|  |      * @return Unique ID. | ||||||
|  |      */ | ||||||
|  |     protected getUniqueId(id: string): string { | ||||||
|  |         let newId = id; | ||||||
|  |         let num = 1; | ||||||
|  | 
 | ||||||
|  |         do { | ||||||
|  |             newId = id + '-' + num; | ||||||
|  |             num++; | ||||||
|  |         } while (newId in this.queue); | ||||||
|  | 
 | ||||||
|  |         return newId; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Process next item in the queue. | ||||||
|  |      * | ||||||
|  |      * @return Promise resolved when next item has been treated. | ||||||
|  |      */ | ||||||
|  |     protected async processNextItem(): Promise<void> { | ||||||
|  |         if (!this.orderedQueue.length || this.numberRunning >= this.maxParallel) { | ||||||
|  |             // Queue is empty or max number of parallel runs reached, stop.
 | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         const item = this.orderedQueue.shift(); | ||||||
|  |         this.numberRunning++; | ||||||
|  | 
 | ||||||
|  |         try { | ||||||
|  |             const result = await item.fn(); | ||||||
|  | 
 | ||||||
|  |             item.deferred.resolve(result); | ||||||
|  |         } catch (error) { | ||||||
|  |             item.deferred.reject(error); | ||||||
|  |         } finally { | ||||||
|  |             delete this.queue[item.id]; | ||||||
|  |             this.numberRunning--; | ||||||
|  | 
 | ||||||
|  |             this.processNextItem(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Add an item to the queue. | ||||||
|  |      * | ||||||
|  |      * @param id ID. | ||||||
|  |      * @param fn Function to call. | ||||||
|  |      * @param options Options. | ||||||
|  |      * @return Promise resolved when the function has been executed. | ||||||
|  |      */ | ||||||
|  |     run<T>(id: string, fn: CoreQueueRunnerFunction<T>, options?: CoreQueueRunnerAddOptions): Promise<T> { | ||||||
|  |         options = options || {}; | ||||||
|  | 
 | ||||||
|  |         if (id in this.queue) { | ||||||
|  |             if (!options.allowRepeated) { | ||||||
|  |                 // Item already in queue, return its promise.
 | ||||||
|  |                 return this.queue[id].deferred.promise; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             id = this.getUniqueId(id); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // Add the item in the queue.
 | ||||||
|  |         const item = { | ||||||
|  |             id, | ||||||
|  |             fn, | ||||||
|  |             deferred: CoreUtils.instance.promiseDefer<T>(), | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         this.queue[id] = item; | ||||||
|  |         this.orderedQueue.push(item); | ||||||
|  | 
 | ||||||
|  |         // Process next item if we haven't reached the max yet.
 | ||||||
|  |         this.processNextItem(); | ||||||
|  | 
 | ||||||
|  |         return item.deferred.promise; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										2057
									
								
								src/app/classes/site.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2057
									
								
								src/app/classes/site.ts
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1027
									
								
								src/app/classes/sqlitedb.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1027
									
								
								src/app/classes/sqlitedb.ts
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -12,9 +12,32 @@ | |||||||
| // See the License for the specific language governing permissions and
 | // See the License for the specific language governing permissions and
 | ||||||
| // limitations under the License.
 | // limitations under the License.
 | ||||||
| 
 | 
 | ||||||
| import { Injector } from '@angular/core'; | import { Injector, NgZone as NgZoneService } from '@angular/core'; | ||||||
|  | import { HttpClient } from '@angular/common/http'; | ||||||
| 
 | 
 | ||||||
| import { SplashScreen as SplashScreenPlugin } from '@ionic-native/splash-screen/ngx'; | import { Platform as PlatformService } from '@ionic/angular'; | ||||||
|  | 
 | ||||||
|  | import { Clipboard as ClipboardService } from '@ionic-native/clipboard/ngx'; | ||||||
|  | import { Diagnostic as DiagnosticService } from '@ionic-native/diagnostic/ngx'; | ||||||
|  | import { Device as DeviceService } from '@ionic-native/device/ngx'; | ||||||
|  | import { File as FileService } from '@ionic-native/file/ngx'; | ||||||
|  | import { FileOpener as FileOpenerService } from '@ionic-native/file-opener/ngx'; | ||||||
|  | import { FileTransfer as FileTransferService } from '@ionic-native/file-transfer/ngx'; | ||||||
|  | import { Geolocation as GeolocationService } from '@ionic-native/geolocation/ngx'; | ||||||
|  | import { Globalization as GlobalizationService } from '@ionic-native/globalization/ngx'; | ||||||
|  | import { InAppBrowser as InAppBrowserService } from '@ionic-native/in-app-browser/ngx'; | ||||||
|  | import { Keyboard as KeyboardService } from '@ionic-native/keyboard/ngx'; | ||||||
|  | import { LocalNotifications as LocalNotificationsService } from '@ionic-native/local-notifications/ngx'; | ||||||
|  | import { Network as NetworkService } from '@ionic-native/network/ngx'; | ||||||
|  | import { Push as PushService } from '@ionic-native/push/ngx'; | ||||||
|  | import { QRScanner as QRScannerService } from '@ionic-native/qr-scanner/ngx'; | ||||||
|  | import { StatusBar as StatusBarService } from '@ionic-native/status-bar/ngx'; | ||||||
|  | import { SplashScreen as SplashScreenService } from '@ionic-native/splash-screen/ngx'; | ||||||
|  | import { SQLite as SQLiteService } from '@ionic-native/sqlite/ngx'; | ||||||
|  | import { WebIntent as WebIntentService } from '@ionic-native/web-intent/ngx'; | ||||||
|  | import { Zip as ZipService } from '@ionic-native/zip/ngx'; | ||||||
|  | 
 | ||||||
|  | import { TranslateService } from '@ngx-translate/core'; | ||||||
| 
 | 
 | ||||||
| import { CoreSingletonsFactory, CoreInjectionToken, CoreSingletonClass } from '@classes/singletons-factory'; | import { CoreSingletonsFactory, CoreInjectionToken, CoreSingletonClass } from '@classes/singletons-factory'; | ||||||
| 
 | 
 | ||||||
| @ -39,4 +62,31 @@ export function makeSingleton<Service>(injectionToken: CoreInjectionToken<Servic | |||||||
|     return factory.makeSingleton(injectionToken); |     return factory.makeSingleton(injectionToken); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export class SplashScreen extends makeSingleton(SplashScreenPlugin) {} | // Convert ionic-native services to singleton.
 | ||||||
|  | export class Clipboard extends makeSingleton(ClipboardService) {} | ||||||
|  | export class Device extends makeSingleton(DeviceService) {} | ||||||
|  | export class Diagnostic extends makeSingleton(DiagnosticService) {} | ||||||
|  | export class File extends makeSingleton(FileService) {} | ||||||
|  | export class FileOpener extends makeSingleton(FileOpenerService) {} | ||||||
|  | export class FileTransfer extends makeSingleton(FileTransferService) {} | ||||||
|  | export class Geolocation extends makeSingleton(GeolocationService) {} | ||||||
|  | export class Globalization extends makeSingleton(GlobalizationService) {} | ||||||
|  | export class InAppBrowser extends makeSingleton(InAppBrowserService) {} | ||||||
|  | export class Keyboard extends makeSingleton(KeyboardService) {} | ||||||
|  | export class LocalNotifications extends makeSingleton(LocalNotificationsService) {} | ||||||
|  | export class Network extends makeSingleton(NetworkService) {} | ||||||
|  | export class Push extends makeSingleton(PushService) {} | ||||||
|  | export class QRScanner extends makeSingleton(QRScannerService) {} | ||||||
|  | export class StatusBar extends makeSingleton(StatusBarService) {} | ||||||
|  | export class SplashScreen extends makeSingleton(SplashScreenService) {} | ||||||
|  | export class SQLite extends makeSingleton(SQLiteService) {} | ||||||
|  | export class WebIntent extends makeSingleton(WebIntentService) {} | ||||||
|  | export class Zip extends makeSingleton(ZipService) {} | ||||||
|  | 
 | ||||||
|  | // Convert some Angular and Ionic injectables to singletons.
 | ||||||
|  | export class NgZone extends makeSingleton(NgZoneService) {} | ||||||
|  | export class Http extends makeSingleton(HttpClient) {} | ||||||
|  | export class Platform extends makeSingleton(PlatformService) {} | ||||||
|  | 
 | ||||||
|  | // Convert external libraries injectables.
 | ||||||
|  | export class Translate extends makeSingleton(TranslateService) {} | ||||||
|  | |||||||
| @ -43,6 +43,7 @@ | |||||||
|         ] |         ] | ||||||
|       } |       } | ||||||
|     ], |     ], | ||||||
|  |     "no-angle-bracket-type-assertion": false, | ||||||
|     "no-console": [ |     "no-console": [ | ||||||
|       true, |       true, | ||||||
|       "debug", |       "debug", | ||||||
| @ -58,12 +59,15 @@ | |||||||
|     ], |     ], | ||||||
|     "no-non-null-assertion": true, |     "no-non-null-assertion": true, | ||||||
|     "no-redundant-jsdoc": true, |     "no-redundant-jsdoc": true, | ||||||
|  |     "no-shadowed-variable": false, | ||||||
|     "no-switch-case-fall-through": true, |     "no-switch-case-fall-through": true, | ||||||
|  |     "no-unused-expression": false, | ||||||
|     "no-var-requires": false, |     "no-var-requires": false, | ||||||
|     "object-literal-key-quotes": [ |     "object-literal-key-quotes": [ | ||||||
|       true, |       true, | ||||||
|       "as-needed" |       "as-needed" | ||||||
|     ], |     ], | ||||||
|  |     "prefer-for-of": false, | ||||||
|     "quotemark": [ |     "quotemark": [ | ||||||
|       true, |       true, | ||||||
|       "single" |       "single" | ||||||
| @ -104,7 +108,8 @@ | |||||||
|       "options": [ |       "options": [ | ||||||
|         "ban-keywords", |         "ban-keywords", | ||||||
|         "check-format", |         "check-format", | ||||||
|         "allow-pascal-case" |         "allow-pascal-case", | ||||||
|  |         "allow-leading-underscore" | ||||||
|       ] |       ] | ||||||
|     }, |     }, | ||||||
|     "whitespace": { |     "whitespace": { | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user