import { Injectable, Inject, InjectionToken } from '@angular/core'; import { BomConfig } from './bom-config.interface'; //export const FOR_ROOT_OPTIONS_TOKEN = new InjectionToken(''); export const MODULE_CONFIG = new InjectionToken(''); @Injectable({ providedIn: "root" }) export class ConfigService { hybris: { cartApiUrl: string; token: string; addresses: string; paymentdetails: string; userInfo: string; updatePaymentMethod: string; orders: string; carts: string; cartShippingAddress: string; cartUCAddress: string; cartPaymentMethod: string; cartShippingMethods: string; cartTaxInfo: string; shippingAccounts: string; promoCode: string; deleteCode: string; }; arrowUrl: string = ''; apiUrl: string; apiCoreUrl: string; apiUrlWithoutVersion: string; signalRUrl: string; private apiVersion: string = '/bom/v2'; private apiCoreBase: string = '/bom-api'; isLocal: boolean = false; region: string = 'NAC'; readonly defaultCurrency: string = 'USD'; userSelectedCurrency: string = null; // The maximum number of milliseconds to wait for the conversion API to respond readonly currencyConversionMaxWait: number = 10000; readonly uiBlockingApiRequestTimeout: number = 3000; readonly ACCESS_TOKEN_STORAGE_KEY = 'accessToken'; readonly REFRESH_TOKEN_STORAGE_KEY = 'refreshToken'; readonly ARROW_COM_KEY = 'arrowcom'; readonly ARROW_KEY = 'arrow'; readonly MY_ARROW_KEY = 'myarrow'; // The current top level domain "com", "de" etc. topDomain: string = ''; websiteLang: string = 'en'; // "Local Storage" key for Sockets Client ID clientIdLocalStorageKey: string = 'socketsClientId'; readonly MAX_LENGTH_BOM_NAME: number = 200; private readonly TOP_DOMAIN_MATCH = '{topDomain}'; private readonly BASE_CONFIG = window['BOM_BASE_URLS']; private readonly BOM_TOOL_OVERRIDES = window['BOM_TOOL_OVERRIDES']; urls: any = { analytics: { register: '/trx/interaction/register', checkout: '/trx/cart/checkout', sendQuote: '/trx/quote/send', columnMapping: '/trx/column_mapping/result', firstLoad: '/trx/elfirstload/elfirstload', addAllItemsToCart: '/trx/elBomCart/elBomCart', addOneItemToCart: '/trx/elPartCart/elPartCart' } }; private config: BomConfig; constructor(@Inject(MODULE_CONFIG) config: any) { //constructor(@Inject(FOR_ROOT_OPTIONS_TOKEN) config: BomConfig){ this.config = config; const domain = window.location.hostname; this.isLocal = domain === 'localhost' || domain === 'bom.arrow.com'; this.applyUrlOverrides(domain); if (!this.BASE_CONFIG) { const hybrisApi = this.config.apis.hybris; const bomApi = this.config.apis.bom; this.BASE_CONFIG = { baseHybrisCartApiUrl: hybrisApi ? `https://${hybrisApi.subdomain}.${hybrisApi.domain}/${hybrisApi.path}` : '', baseApiUrl: `https://${bomApi.subdomain}.${bomApi.domain}`, baseMyProjectsApiUrl: '' // This is only for arrow.com where this.BASE_CONFIG is always defined }; } this.initializeTopLevelDomain(); this.setWebsiteLang(); if (this.getTarget() === 'arrowcom') { this.userSelectedCurrency = this._getCurrency('arrowcurrency', 'isocode') || this.defaultCurrency; } else { // Will be set in view.component.ts file } } private initializeTopLevelDomain(): void { const domain = window.location.hostname.split('.').pop(); this.topDomain = domain === 'localhost' ? 'com' : domain; this.hybris = { cartApiUrl: this.BASE_CONFIG.baseHybrisCartApiUrl + '/arrowwebservices/v2/arrow/', token: 'token', addresses: 'users/current/addresses', paymentdetails: 'users/current/paymentdetails', userInfo: 'b2busers?fields=FULL', updatePaymentMethod: 'users/current/updatePaymentMethod', orders: 'users/current/orders', carts: 'carts', cartShippingAddress: 'addresses/delivery', cartUCAddress: 'addresses/ucaddress', cartPaymentMethod: 'paymentdetails', cartShippingMethods: 'shippingMethods', cartTaxInfo: 'taxInfo', shippingAccounts: 'users/current/shippingAccounts', promoCode: 'vouchers', deleteCode: 'users/current/carts' }; this.apiUrlWithoutVersion = this.BASE_CONFIG.baseApiUrl.replace( this.TOP_DOMAIN_MATCH, this.topDomain ); this.apiUrl = this.apiUrlWithoutVersion + this.apiVersion; this.apiCoreUrl = this.apiUrlWithoutVersion + this.apiCoreBase; // TODO: This 'may' work for .Net Core SignalR Server and latest SignalR Client //this.signalRUrl = '/bomhub'; // TODO: this works for non-Core ASP Net server and JQuery based SinalR Client. // Results in http://bom.arrow.com/bom/bomhub this.signalRUrl = this.apiUrlWithoutVersion + '/bom/bomhub'; // This is for us when we're developing if (this.isLocal) { switch (this.getTarget()) { case this.ARROW_COM_KEY: this.arrowUrl = 'https://qa.arrow.com'; break; case this.MY_ARROW_KEY: this.arrowUrl = 'https://qa-my.arrow.com'; break; default: break; } } } /** * Retrieve currency based on arrowcurrency cookie. * @param name Name of required cookie. * @param value Name of value within the cookie. */ private _getCurrency(name: string, value: string): string { const _cookie: string = this.getCookie(name); let arr: string[]; if (_cookie) arr = _cookie.split(/[&=]/g); return _cookie ? arr[arr.indexOf(value) + 1] : undefined; } getDomain(): string { let hostname = location.hostname; const index = hostname.search(/\w+\.\w+$/); hostname = hostname.slice(index); return hostname; } getRoute(reqPath: string): string { let path = ''; switch (reqPath) { case 'login': path = '/login'; break; case 'register': path = '/register'; break; case 'cart': path = '/cart'; break; case 'maw-cart': path = '/cart'; break; case 'maw-quote': path = '/quotes'; break; default: throw new Error(`Unknown path ${reqPath}`); } if (this.isArrowcom() && this.getDomain() === 'arrow.com') { path = `/${this.getCookie('website#lang') || '/en'}${path}`; } return path; } setWebsiteLang(): void { let lang = this.getCookie('website#lang'); if (lang) lang = lang.toLowerCase(); this.websiteLang = `${lang || '/en'}`; } /** * Where is this app hosted? (e.g. models, myarrow etc.) */ getTarget(): string { return this.config.target; } isArrowcom(): boolean { return this.getTarget() !== this.MY_ARROW_KEY; } isMyArrow(): boolean { return this.getTarget() === this.MY_ARROW_KEY; } getAccessToken(): string { return localStorage.getItem(this.ACCESS_TOKEN_STORAGE_KEY); } getRefreshToken() { return localStorage.getItem(this.REFRESH_TOKEN_STORAGE_KEY); } //TODO: All getApi methods build the string in the same way, we can abstract this into a generic function getCartApi(): string { const api = this.config.apis.cart; const protocol = api.protocol ? api.protocol + '://' : 'https://'; const subDomain = api.subdomain ? api.subdomain + '.' : ''; const domain = api.domain; const port = api.port ? ':' + api.port : ''; const path = api.path ? '/' + api.path : ''; return protocol + subDomain + domain + port + path; } getUserApi(): string { const api = this.config.apis.user ? this.config.apis.user : {}; const protocol = api.protocol ? api.protocol + '://' : 'https://'; const subDomain = api.subdomain ? api.subdomain + '.' : ''; const domain = api.domain; const port = api.port ? ':' + api.port : ''; const path = api.path ? '/' + api.path : ''; return protocol + subDomain + domain + port + path; } getMyProjectsApi(): string { return this.BASE_CONFIG.baseMyProjectsApiUrl; } getSecurityApi(): string { const api = this.config.apis.security ? this.config.apis.security : {}; const protocol = api.protocol ? api.protocol + '://' : 'https://'; const subDomain = api.subdomain ? api.subdomain + '.' : ''; const domain = api.domain; const port = api.port ? ':' + api.port : ''; const path = api.path ? '/' + api.path : ''; return protocol + subDomain + domain + port + path; } private applyUrlOverrides(domain: string): void { if (this.BOM_TOOL_OVERRIDES) { try { const overrides = JSON.parse(this.BOM_TOOL_OVERRIDES); const oForDomain = overrides[domain]; if (oForDomain && oForDomain.urls) { for (const urlKey in oForDomain.urls) { if (this.BASE_CONFIG.hasOwnProperty(urlKey)) { console.log( `Applying Url Override. urlKey: ${urlKey} ` + ` | previous: ${this.BASE_CONFIG[urlKey]} | new: ${oForDomain.urls[urlKey]}` ); this.BASE_CONFIG[urlKey] = oForDomain.urls[urlKey]; } else { console.log(`NOT applying URL override. urlKey "${urlKey}"`); } } } } catch (err) { console.error( `Parsing/importing overrides failed | error: ${err} ` + `| BOM_TOOL_OVERRIDES: ${this.BOM_TOOL_OVERRIDES}` ); } } } // TODO: Use get cookie function from utils after fixing circular dependency private getCookie(cookieName: string): string { const regExp = new RegExp( `(?:(?:^|.*;\\s*)${cookieName}\\s*\\=\\s*([^;]*).*$)|^.*$` ); return document.cookie.replace(regExp, '$1'); } getSocketsClientId() { return localStorage.getItem(this.clientIdLocalStorageKey); } shouldUseSignalR() { const useSignalR = localStorage.getItem("useSignalR"); // return useSignalR === "true" || useSignalR === "1" || false; // TODO: uncomment to use socket.io by default. return !(useSignalR === "false" || useSignalR === "0"); // TODO: uncomment to use SignalR by default, when there is no localStorage key. } }