From cdf10497b6380c0a6209ec69123f6db615f4b16c Mon Sep 17 00:00:00 2001 From: ngadzheva Date: Wed, 24 Jan 2024 00:37:39 +0200 Subject: [PATCH] Build after cache expiration time fix --- docs/main.js | 2 +- docs/main.js.map | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/main.js b/docs/main.js index 47be870..ba602a0 100644 --- a/docs/main.js +++ b/docs/main.js @@ -471,7 +471,7 @@ let CacheService = class CacheService { } getItems(key) { const cachedData = this.getCachedData(key); - const notExpired = cachedData.filter(data => new Date(Date.parse(data.expiration)) <= new Date()); + const notExpired = cachedData.filter(data => new Date(Date.parse(data.expiration)) >= new Date()); return notExpired; } getCachedData(key) { diff --git a/docs/main.js.map b/docs/main.js.map index 620ce8c..fd872df 100644 --- a/docs/main.js.map +++ b/docs/main.js.map @@ -1 +1 @@ -{"version":3,"file":"main.js","mappings":"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","sources":["./src/app/app.component.ts","./src/app/app.module.ts","./src/app/app.routing.ts","./src/app/config/cache.config.ts","./src/app/current-conditions/current-conditions.component.ts","./src/app/forecasts-list/forecasts-list.component.ts","./src/app/main-page/main-page.component.ts","./src/app/min-max-temperature/min-max-temperature.component.ts","./src/app/services/cache-service.ts","./src/app/services/location.service.ts","./src/app/services/weather.service.ts","./src/app/ui-tabs/click-stop-propagation.directive.ts","./src/app/ui-tabs/ui-tab-item/ui-tab-item.component.ts","./src/app/ui-tabs/ui-tabs.component.ts","./src/app/ui-tabs/ui-tabs.module.ts","./src/app/utils/with-unsubscribe.ts","./src/app/zipcode-entry/zipcode-entry.component.ts","./src/environments/environment.ts","./src/main.ts","./src/app/app.component.css","./src/app/current-conditions/current-conditions.component.css","./src/app/forecasts-list/forecasts-list.component.css","./src/app/ui-tabs/ui-tab-item/ui-tab-item.component.css","./src/app/ui-tabs/ui-tabs.component.css"],"sourcesContent":["import { Component } from '@angular/core';\r\n\r\n@Component({\r\n selector: 'app-root',\r\n templateUrl: './app.component.html',\r\n styleUrls: ['./app.component.css']\r\n})\r\nexport class AppComponent {\r\n\r\n constructor() {\r\n\r\n }\r\n}\r\n","import { BrowserModule } from '@angular/platform-browser';\r\nimport { NgModule } from '@angular/core';\r\nimport { FormsModule } from '@angular/forms';\r\nimport { RouterModule } from '@angular/router';\r\nimport { HttpClientModule } from '@angular/common/http';\r\nimport { ServiceWorkerModule } from '@angular/service-worker';\r\n\r\nimport { AppComponent } from './app.component';\r\nimport { ZipcodeEntryComponent } from './zipcode-entry/zipcode-entry.component';\r\nimport { ForecastsListComponent } from './forecasts-list/forecasts-list.component';\r\nimport { CurrentConditionsComponent } from './current-conditions/current-conditions.component';\r\nimport { MainPageComponent } from './main-page/main-page.component';\r\nimport { MinMaxTemperatureComponent } from './min-max-temperature/min-max-temperature.component';\r\nimport { LocationService } from './services/location.service';\r\nimport { WeatherService } from './services/weather.service';\r\nimport { routing } from './app.routing';\r\nimport { environment } from '../environments/environment';\r\nimport { UITabsModule } from './ui-tabs/ui-tabs.module';\r\n\r\n@NgModule({\r\n declarations: [\r\n AppComponent,\r\n ZipcodeEntryComponent,\r\n ForecastsListComponent,\r\n CurrentConditionsComponent,\r\n MainPageComponent,\r\n MinMaxTemperatureComponent\r\n ],\r\n imports: [\r\n BrowserModule,\r\n FormsModule,\r\n HttpClientModule,\r\n RouterModule,\r\n UITabsModule,\r\n routing,\r\n ServiceWorkerModule.register('/ngsw-worker.js', { enabled: environment.production })\r\n ],\r\n providers: [LocationService, WeatherService],\r\n bootstrap: [AppComponent]\r\n})\r\nexport class AppModule { }\r\n","import { ModuleWithProviders } from '@angular/core';\r\nimport { Routes, RouterModule } from '@angular/router';\r\nimport { ForecastsListComponent } from './forecasts-list/forecasts-list.component';\r\nimport { MainPageComponent } from './main-page/main-page.component';\r\n\r\nconst appRoutes: Routes = [\r\n {\r\n path: '', component: MainPageComponent\r\n },\r\n {\r\n path: 'forecast/:zipcode', component: ForecastsListComponent\r\n }\r\n];\r\nexport const routing: ModuleWithProviders = RouterModule.forRoot(appRoutes, {});\r\n","export enum CACHE_KEYS {\r\n CURRENT_CONDITIONS = 'current',\r\n FORECAST = 'forecast'\r\n};\r\n\r\n// Cache expiration time in miliseconds\r\nexport const CACHE_EXPIRATION_TIME = 2 * 60 * 60 * 1000;\r\n","import { Component, inject, Signal } from '@angular/core';\r\nimport { Router } from '@angular/router';\r\nimport { takeUntil } from 'rxjs/operators';\r\n\r\nimport { ConditionsAndZip } from '../conditions-and-zip.type';\r\nimport { WeatherService } from '../services/weather.service';\r\nimport { Action, LocationService } from '../services/location.service';\r\nimport { CacheService } from '../services/cache-service';\r\nimport { CACHE_KEYS } from '../config/cache.config';\r\nimport { WithUnsubscribe } from '../utils/with-unsubscribe';\r\n\r\n@Component({\r\n selector: 'app-current-conditions',\r\n templateUrl: './current-conditions.component.html',\r\n styleUrls: ['./current-conditions.component.css']\r\n})\r\nexport class CurrentConditionsComponent extends WithUnsubscribe() {\r\n\r\n private weatherService = inject(WeatherService);\r\n private router = inject(Router);\r\n private cacheService = inject(CacheService);\r\n protected locationService = inject(LocationService);\r\n protected currentConditionsByZip: Signal = this.weatherService.getCurrentConditions();\r\n\r\n constructor() {\r\n super();\r\n\r\n // Subscribe to the locations observable and listen for its events\r\n this.locationService.getLocation().pipe(\r\n takeUntil(this.unsubscribe$)\r\n ).subscribe((location) => {\r\n if (location.action === Action.ADD) {\r\n if (!this.currentConditionsByZip().find(conditions => conditions.zip === location.zipcode))\r\n this.weatherService.addCurrentConditions(location.zipcode);\r\n } else if (location.action === Action.REMOVE) {\r\n const { zipcode } = location;\r\n\r\n this.weatherService.removeCurrentConditions(zipcode);\r\n // Remove the location from the cache as well\r\n this.cacheService.removeItem(CACHE_KEYS.CURRENT_CONDITIONS, zipcode);\r\n this.cacheService.removeItem(CACHE_KEYS.FORECAST, zipcode);\r\n }\r\n });\r\n\r\n // Load the locations after we have\r\n // subscribed to the location observable\r\n this.locationService.loadLocations();\r\n }\r\n\r\n showForecast(zipcode : string){\r\n this.router.navigate(['/forecast', zipcode])\r\n }\r\n\r\n // Remove location from the list by the index\r\n // of the tab which close button is clicked\r\n removeLocation(index: number) {\r\n this.locationService.removeLocation(index);\r\n }\r\n\r\n // Helper method for setting the zipcode to the url hash\r\n extractHash(tabTitle?: string) {\r\n const matches = tabTitle?.match(/\\(([^)]+)\\)/);\r\n\r\n return matches ? matches[1] : '';\r\n }\r\n}\r\n","import { Component } from '@angular/core';\r\nimport { Location } from '@angular/common';\r\nimport { ActivatedRoute } from '@angular/router';\r\nimport { takeUntil } from 'rxjs/operators';\r\n\r\nimport { Forecast } from './forecast.type';\r\nimport { WeatherService } from '../services/weather.service';\r\nimport { CacheService } from '../services/cache-service';\r\nimport { CACHE_KEYS } from '../config/cache.config';\r\nimport { WithUnsubscribe } from '../utils/with-unsubscribe';\r\n\r\n@Component({\r\n selector: 'app-forecasts-list',\r\n templateUrl: './forecasts-list.component.html',\r\n styleUrls: ['./forecasts-list.component.css']\r\n})\r\nexport class ForecastsListComponent extends WithUnsubscribe() {\r\n\r\n zipcode: string;\r\n forecast?: Forecast;\r\n\r\n constructor(\r\n protected weatherService: WeatherService,\r\n route : ActivatedRoute,\r\n private cacheService: CacheService,\r\n private location: Location\r\n ) {\r\n super();\r\n\r\n this.zipcode = route.snapshot.params['zipcode'];\r\n this.loadForecast();\r\n }\r\n\r\n goBack() {\r\n this.location.back();\r\n }\r\n\r\n /**\r\n * Helper method for fetching the 5-day forecast weather\r\n * First, we check for stored forecast in the cache\r\n * If it is available, we use it for initializing forecast\r\n * Otherwise, we fetch the udpated forecast from the API and update the cache\r\n */\r\n private loadForecast() {\r\n const cachedForecast = this.cacheService.getItem(CACHE_KEYS.FORECAST, this.zipcode);\r\n\r\n if (cachedForecast) {\r\n this.forecast = cachedForecast.data as Forecast;\r\n } else {\r\n this.weatherService.getForecast(this.zipcode).pipe(\r\n takeUntil(this.unsubscribe$)\r\n ).subscribe(data => {\r\n this.forecast = data;\r\n\r\n this.cacheService.setItem(CACHE_KEYS.FORECAST, { id: this.zipcode, data });\r\n });\r\n }\r\n }\r\n}\r\n","import { Component } from '@angular/core';\r\n\r\n@Component({\r\n selector: 'app-main-page',\r\n templateUrl: './main-page.component.html'\r\n})\r\nexport class MainPageComponent {\r\n\r\n}\r\n","import { Component, Input } from '@angular/core';\r\n\r\n@Component({\r\n selector: 'app-min-max-temperature',\r\n templateUrl: './min-max-temperature.component.html'\r\n})\r\nexport class MinMaxTemperatureComponent {\r\n @Input() min?: number;\r\n @Input() max?: number;\r\n @Input() withHyphen: boolean = false;\r\n}\r\n","import { Injectable } from '@angular/core';\r\n\r\nimport { CACHE_EXPIRATION_TIME } from '../config/cache.config';\r\n\r\nexport interface CacheData {\r\n id: string;\r\n data: unknown;\r\n expiration: Date | string;\r\n}\r\n\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class CacheService {\r\n /**\r\n * Stores items into browser's local storage with expiration date\r\n * @param key - the key with wich the data will be accessed from the local storage\r\n * @param value - the data which we will store\r\n */\r\n setItem(key: string, data: Pick) {\r\n const cachedData = this.getCachedData(key);\r\n\r\n const currentTime = new Date().getTime();\r\n const dataWithExpiration: CacheData = { ...data, expiration: new Date(currentTime + CACHE_EXPIRATION_TIME) };\r\n\r\n cachedData.push(dataWithExpiration);\r\n \r\n localStorage.setItem(key, JSON.stringify(cachedData));\r\n }\r\n\r\n /**\r\n * Retrieves items from browser's local storage by given key and id\r\n * - If there is some data stored under the given key:\r\n * - Checks whether the data is not expired and needs refresh\r\n * @param key - the key with which data will be searched in the local storage\r\n * @returns the cached data if it is not expired, otherwise, returns null\r\n */\r\n getItem(key: string, id: string): CacheData | undefined {\r\n const cachedData: CacheData[] = this.getItems(key);\r\n const cachedItem: CacheData | undefined = cachedData.find(data => data.id === id);\r\n\r\n return cachedItem;\r\n }\r\n\r\n /**\r\n * Removes item from local storage by key\r\n * @param key - the key with which the data we want to remove is stored in local storage\r\n */\r\n removeItem(key: string, id: string) {\r\n const cachedData = this.getCachedData(key);\r\n const updatedData = cachedData.filter(data => data.id !== id);\r\n \r\n localStorage.setItem(key, JSON.stringify(updatedData));\r\n }\r\n\r\n getItems(key: string): CacheData[] {\r\n const cachedData: CacheData[] = this.getCachedData(key);\r\n const notExpired = cachedData.filter(data => new Date(Date.parse(data.expiration as string)) <= new Date());\r\n\r\n return notExpired;\r\n }\r\n\r\n private getCachedData(key: string): CacheData[] {\r\n return JSON.parse(localStorage.getItem(key) ?? '[]');\r\n }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { Subject } from 'rxjs';\r\n\r\nexport const LOCATIONS : string = 'locations';\r\n\r\nexport enum Action { ADD, REMOVE };\r\n\r\ninterface LocationProps {\r\n action: Action;\r\n zipcode: string;\r\n}\r\n\r\n@Injectable()\r\nexport class LocationService {\r\n\r\n locations : string[] = [];\r\n // Subject for locations changes\r\n private location$ = new Subject();\r\n\r\n constructor() {\r\n let locString = localStorage.getItem(LOCATIONS);\r\n if (locString)\r\n this.locations = JSON.parse(locString);\r\n }\r\n\r\n loadLocations() {\r\n for (let loc of this.locations) {\r\n // Emit add event\r\n this.location$.next({ action: Action.ADD, zipcode: loc });\r\n }\r\n }\r\n\r\n addLocation(zipcode : string) {\r\n // If the location is already added, do not duplicate it\r\n if (this.locations.includes(zipcode)) {\r\n return;\r\n }\r\n\r\n this.locations.push(zipcode);\r\n localStorage.setItem(LOCATIONS, JSON.stringify(this.locations));\r\n\r\n // Emit add event\r\n this.location$.next({ action: Action.ADD, zipcode });\r\n }\r\n\r\n removeLocation(index : number) {\r\n const zipcode = this.locations[index];\r\n \r\n if (index !== -1){\r\n this.locations.splice(index, 1);\r\n localStorage.setItem(LOCATIONS, JSON.stringify(this.locations));\r\n\r\n // Emit remove event\r\n this.location$.next({ action: Action.REMOVE, zipcode });\r\n }\r\n }\r\n\r\n // Export the location subject as observable\r\n // in order to be able to subscribe for the updates\r\n getLocation() {\r\n return this.location$.asObservable();\r\n }\r\n}\r\n","import { Injectable, Signal, signal } from '@angular/core';\r\nimport { HttpClient } from '@angular/common/http';\r\nimport { Observable } from 'rxjs';\r\nimport { takeUntil } from 'rxjs/operators';\r\n\r\nimport { CurrentConditions } from '../current-conditions/current-conditions.type';\r\nimport { ConditionsAndZip } from '../conditions-and-zip.type';\r\nimport { Forecast } from '../forecasts-list/forecast.type';\r\nimport { CacheService } from './cache-service';\r\nimport { CACHE_KEYS } from '../config/cache.config';\r\nimport { WithUnsubscribe } from '../utils/with-unsubscribe';\r\n\r\n\r\n@Injectable()\r\nexport class WeatherService extends WithUnsubscribe() {\r\n\r\n static URL = 'https://api.openweathermap.org/data/2.5';\r\n static APPID = '5a4b2d457ecbef9eb2a71e480b947604';\r\n static ICON_URL = 'https://raw.githubusercontent.com/udacity/Sunshine-Version-2/sunshine_master/app/src/main/res/drawable-hdpi/';\r\n private currentConditions = signal([]);\r\n private cachedConditions;\r\n\r\n constructor(private http: HttpClient, private cacheService: CacheService) {\r\n super();\r\n\r\n // If there is some cached data, we fetch it and\r\n // initialize the currentConditions array with it\r\n this.cachedConditions = this.cacheService.getItems(CACHE_KEYS.CURRENT_CONDITIONS);\r\n\r\n if (this.cachedConditions) {\r\n this.cachedConditions.forEach(cache => {\r\n this.currentConditions.update(conditions => {\r\n const cachedData = {\r\n zip: cache.id,\r\n data: cache.data as CurrentConditions\r\n };\r\n\r\n return [...conditions, cachedData];\r\n });\r\n });\r\n }\r\n }\r\n\r\n addCurrentConditions(zipcode: string): void {\r\n // We first check for cached conditions\r\n const cachedZipConditions = this.cachedConditions.find(conditions => conditions.id === zipcode);\r\n\r\n // If there are already saved conditions in the cache for the given zipcode,\r\n // we use them for updating the currentConditions array\r\n // Otherwise, we fetch the current conditions from the API and update the cache\r\n if (cachedZipConditions) {\r\n this.currentConditions.update(conditions => [...conditions, { zip: zipcode, data: cachedZipConditions.data as CurrentConditions }]);\r\n } else {\r\n // Here we make a request to get the current conditions data from the API. Note the use of backticks and an expression to insert the zipcode\r\n this.http.get(`${WeatherService.URL}/weather?zip=${zipcode},us&units=imperial&APPID=${WeatherService.APPID}`)\r\n .pipe(takeUntil(this.unsubscribe$))\r\n .subscribe(data => {\r\n this.currentConditions.update(conditions => [...conditions, { zip: zipcode, data }]);\r\n this.cacheService.setItem(CACHE_KEYS.CURRENT_CONDITIONS, { id: zipcode, data });\r\n });\r\n }\r\n }\r\n\r\n removeCurrentConditions(zipcode: string) {\r\n this.currentConditions.update(conditions => {\r\n for (let i in conditions) {\r\n if (conditions[i].zip == zipcode)\r\n conditions.splice(+i, 1);\r\n }\r\n return conditions;\r\n });\r\n }\r\n\r\n getCurrentConditions(): Signal {\r\n return this.currentConditions.asReadonly();\r\n }\r\n\r\n getForecast(zipcode: string): Observable {\r\n // Here we make a request to get the forecast data from the API. Note the use of backticks and an expression to insert the zipcode\r\n return this.http.get(`${WeatherService.URL}/forecast/daily?zip=${zipcode},us&units=imperial&cnt=5&APPID=${WeatherService.APPID}`);\r\n }\r\n\r\n getWeatherIcon(id: number): string {\r\n if (id >= 200 && id <= 232)\r\n return WeatherService.ICON_URL + 'art_storm.png';\r\n else if (id >= 501 && id <= 511)\r\n return WeatherService.ICON_URL + 'art_rain.png';\r\n else if (id === 500 || (id >= 520 && id <= 531))\r\n return WeatherService.ICON_URL + 'art_light_rain.png';\r\n else if (id >= 600 && id <= 622)\r\n return WeatherService.ICON_URL + 'art_snow.png';\r\n else if (id >= 801 && id <= 804)\r\n return WeatherService.ICON_URL + 'art_clouds.png';\r\n else if (id === 741 || id === 761)\r\n return WeatherService.ICON_URL + 'art_fog.png';\r\n else\r\n return WeatherService.ICON_URL + 'art_clear.png';\r\n }\r\n}\r\n","import { Directive, HostListener } from '@angular/core';\r\n \r\n@Directive({\r\n selector: '[click-stop-propagation]'\r\n})\r\nexport class ClickStopPropagation\r\n{\r\n @HostListener('click', ['$event'])\r\n public onClick(event: any): void\r\n {\r\n event.stopPropagation();\r\n }\r\n}","import { Component, EventEmitter, Input, Output } from '@angular/core';\r\n\r\n@Component({\r\n selector: 'app-ui-tab-item',\r\n templateUrl: './ui-tab-item.component.html',\r\n styleUrls: ['./ui-tab-item.component.css']\r\n})\r\nexport class UITabItemComponent {\r\n @Input() tabTitle?: string;\r\n @Output() closeTab = new EventEmitter();\r\n\r\n active = false;\r\n}\r\n","import { AfterContentChecked, Component, ContentChildren, Input, QueryList } from '@angular/core';\r\nimport { ActivatedRoute, Router } from '@angular/router';\r\n\r\nimport { UITabItemComponent } from './ui-tab-item/ui-tab-item.component';\r\n\r\n\r\n@Component({\r\n selector: 'app-ui-tabs',\r\n templateUrl: './ui-tabs.component.html',\r\n styleUrls: ['./ui-tabs.component.css']\r\n})\r\nexport class UITabsComponent implements AfterContentChecked {\r\n @Input() extractHash!: (key?: string) => string;\r\n @ContentChildren(UITabItemComponent) tabs!: QueryList;\r\n activeTab?: UITabItemComponent;\r\n\r\n constructor(private route: ActivatedRoute, private router: Router) { }\r\n\r\n ngAfterContentChecked() {\r\n // Set the last active tab using the url hash\r\n // If there is no hash, activate the first tab\r\n if (this.route.snapshot.fragment && this.tabs.length > 0) {\r\n const fragment = this.route.snapshot.fragment;\r\n this.activeTab = this.tabs.find(tab => this.extractHash(tab.tabTitle) === fragment);\r\n\r\n this.setActiveTab();\r\n } else {\r\n this.activeTab = this.tabs.first;\r\n\r\n this.setActiveTab();\r\n this.setActiveTabHash();\r\n }\r\n }\r\n\r\n removeTab(tabIndex: number) {\r\n const tab = this.tabs.get(tabIndex);\r\n\r\n // Emit the tab index to remove\r\n // the corresponding location as well\r\n tab?.closeTab.emit(tabIndex);\r\n\r\n const wasActive = tab?.active;\r\n\r\n // If the removed tab was active\r\n // we set the previous one or the next one\r\n // (if it was the first tab) to active\r\n if (wasActive) {\r\n // If it was the only tab, remove the hash from the url\r\n if (this.tabs.length === 1) {\r\n this.router.navigateByUrl('/');\r\n }\r\n\r\n this.activeTab = this.tabs.get(tabIndex > 0 ? tabIndex - 1 : tabIndex + 1);\r\n\r\n this.setActiveTab();\r\n this.setActiveTabHash();\r\n }\r\n }\r\n\r\n // Activate the current tab and show its content\r\n selectTab(tab: UITabItemComponent) {\r\n this.tabs.forEach((tab) => {\r\n tab.active = false;\r\n });\r\n\r\n this.activeTab = tab;\r\n\r\n this.setActiveTab();\r\n this.setActiveTabHash();\r\n }\r\n\r\n // Helper method for remembering the selected tab with a hash in the url\r\n private setActiveTabHash() {\r\n if (this.activeTab) {\r\n this.router.navigateByUrl('#' + this.extractHash(this.activeTab.tabTitle));\r\n }\r\n }\r\n\r\n private setActiveTab() {\r\n if (this.activeTab) {\r\n this.activeTab.active = true;\r\n }\r\n }\r\n}\r\n","import { NgModule } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\n\r\nimport { UITabItemComponent } from './ui-tab-item/ui-tab-item.component';\r\nimport { UITabsComponent } from './ui-tabs.component';\r\nimport { ClickStopPropagation } from './click-stop-propagation.directive';\r\n\r\n@NgModule({\r\n declarations: [\r\n UITabsComponent,\r\n UITabItemComponent,\r\n ClickStopPropagation\r\n ],\r\n imports: [CommonModule],\r\n exports: [UITabsComponent, UITabItemComponent]\r\n})\r\nexport class UITabsModule { }","import { OnDestroy } from \"@angular/core\";\r\nimport { Subject } from \"rxjs\";\r\n\r\nexport function WithUnsubscribe() {\r\n return class Base implements OnDestroy {\r\n protected unsubscribe$ = new Subject();\r\n\r\n ngOnDestroy(): void {\r\n this.unsubscribe$.next();\r\n this.unsubscribe$.complete();\r\n }\r\n }\r\n}\r\n","import { Component } from '@angular/core';\r\n\r\nimport { LocationService } from '../services/location.service';\r\n\r\n@Component({\r\n selector: 'app-zipcode-entry',\r\n templateUrl: './zipcode-entry.component.html'\r\n})\r\nexport class ZipcodeEntryComponent {\r\n\r\n constructor(private locationService : LocationService) { }\r\n\r\n addLocation(zipcode: HTMLInputElement) {\r\n this.locationService.addLocation(zipcode.value);\r\n zipcode.value = '';\r\n }\r\n\r\n}\r\n","// The file contents for the current environment will overwrite these during build.\r\n// The build system defaults to the dev environment which uses `environment.ts`, but if you do\r\n// `ng build --env=prod` then `environment.prod.ts` will be used instead.\r\n// The list of which env maps to which file can be found in `.angular-cli.json`.\r\n\r\nexport const environment = {\r\n production: false\r\n};\r\n","import { enableProdMode } from '@angular/core';\r\nimport { platformBrowserDynamic } from '@angular/platform-browser-dynamic';\r\n\r\nimport { AppModule } from './app/app.module';\r\nimport { environment } from './environments/environment';\r\n\r\nif (environment.production) {\r\n enableProdMode();\r\n}\r\n\r\nplatformBrowserDynamic().bootstrapModule(AppModule);\r\n","// Imports\nvar ___CSS_LOADER_API_SOURCEMAP_IMPORT___ = require(\"../../node_modules/css-loader/dist/runtime/sourceMaps.js\");\nvar ___CSS_LOADER_API_IMPORT___ = require(\"../../node_modules/css-loader/dist/runtime/api.js\");\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, ``, \"\",{\"version\":3,\"sources\":[],\"names\":[],\"mappings\":\"\",\"sourceRoot\":\"\"}]);\n// Exports\nmodule.exports = ___CSS_LOADER_EXPORT___.toString();\n","// Imports\nvar ___CSS_LOADER_API_SOURCEMAP_IMPORT___ = require(\"../../../node_modules/css-loader/dist/runtime/sourceMaps.js\");\nvar ___CSS_LOADER_API_IMPORT___ = require(\"../../../node_modules/css-loader/dist/runtime/api.js\");\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, `.wrapper {\r\n display: flex;\r\n width: 100%;\r\n justify-content: flex-start;\r\n}\r\n\r\n.flex {\r\n display: flex;\r\n justify-content: space-between;\r\n}\r\n`, \"\",{\"version\":3,\"sources\":[\"webpack://./src/app/current-conditions/current-conditions.component.css\"],\"names\":[],\"mappings\":\"AAAA;EACE,aAAa;EACb,WAAW;EACX,2BAA2B;AAC7B;;AAEA;EACE,aAAa;EACb,8BAA8B;AAChC\",\"sourcesContent\":[\".wrapper {\\r\\n display: flex;\\r\\n width: 100%;\\r\\n justify-content: flex-start;\\r\\n}\\r\\n\\r\\n.flex {\\r\\n display: flex;\\r\\n justify-content: space-between;\\r\\n}\\r\\n\"],\"sourceRoot\":\"\"}]);\n// Exports\nmodule.exports = ___CSS_LOADER_EXPORT___.toString();\n","// Imports\nvar ___CSS_LOADER_API_SOURCEMAP_IMPORT___ = require(\"../../../node_modules/css-loader/dist/runtime/sourceMaps.js\");\nvar ___CSS_LOADER_API_IMPORT___ = require(\"../../../node_modules/css-loader/dist/runtime/api.js\");\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, `.icon {\r\n width: 45px;\r\n height: 45px;\r\n position: absolute;\r\n right: 20px;\r\n top: -2px;\r\n}\r\n`, \"\",{\"version\":3,\"sources\":[\"webpack://./src/app/forecasts-list/forecasts-list.component.css\"],\"names\":[],\"mappings\":\"AAAA;EACE,WAAW;EACX,YAAY;EACZ,kBAAkB;EAClB,WAAW;EACX,SAAS;AACX\",\"sourcesContent\":[\".icon {\\r\\n width: 45px;\\r\\n height: 45px;\\r\\n position: absolute;\\r\\n right: 20px;\\r\\n top: -2px;\\r\\n}\\r\\n\"],\"sourceRoot\":\"\"}]);\n// Exports\nmodule.exports = ___CSS_LOADER_EXPORT___.toString();\n","// Imports\nvar ___CSS_LOADER_API_SOURCEMAP_IMPORT___ = require(\"../../../../node_modules/css-loader/dist/runtime/sourceMaps.js\");\nvar ___CSS_LOADER_API_IMPORT___ = require(\"../../../../node_modules/css-loader/dist/runtime/api.js\");\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, `.body {\r\n width: 600px;\r\n height: 300px;\r\n border: 1px solid black;\r\n padding: 25px;\r\n}`, \"\",{\"version\":3,\"sources\":[\"webpack://./src/app/ui-tabs/ui-tab-item/ui-tab-item.component.css\"],\"names\":[],\"mappings\":\"AAAA;IACI,YAAY;IACZ,aAAa;IACb,uBAAuB;IACvB,aAAa;AACjB\",\"sourcesContent\":[\".body {\\r\\n width: 600px;\\r\\n height: 300px;\\r\\n border: 1px solid black;\\r\\n padding: 25px;\\r\\n}\"],\"sourceRoot\":\"\"}]);\n// Exports\nmodule.exports = ___CSS_LOADER_EXPORT___.toString();\n","// Imports\nvar ___CSS_LOADER_API_SOURCEMAP_IMPORT___ = require(\"../../../node_modules/css-loader/dist/runtime/sourceMaps.js\");\nvar ___CSS_LOADER_API_IMPORT___ = require(\"../../../node_modules/css-loader/dist/runtime/api.js\");\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, `.tab {\r\n display: flex;\r\n list-style: none;\r\n padding: 0;\r\n margin: 0;\r\n overflow-x: auto;\r\n width: 600px;\r\n}\r\n\r\n.title.active {\r\n border-bottom: 5px solid lightblue;\r\n}\r\n\r\n.title {\r\n background-color: #617aa0;\r\n color: white;\r\n padding: 15px;\r\n border: 1px solid black;\r\n width: -moz-fit-content;\r\n width: fit-content;\r\n margin-right: 15px;\r\n flex-shrink: 0;\r\n}\r\n\r\n.title:hover {\r\n cursor: pointer;\r\n}\r\n\r\n.close {\r\n cursor: pointer;\r\n color: white;\r\n margin-left: 15px;\r\n}`, \"\",{\"version\":3,\"sources\":[\"webpack://./src/app/ui-tabs/ui-tabs.component.css\"],\"names\":[],\"mappings\":\"AAAA;IACI,aAAa;IACb,gBAAgB;IAChB,UAAU;IACV,SAAS;IACT,gBAAgB;IAChB,YAAY;AAChB;;AAEA;IACI,kCAAkC;AACtC;;AAEA;IACI,yBAAyB;IACzB,YAAY;IACZ,aAAa;IACb,uBAAuB;IACvB,uBAAkB;IAAlB,kBAAkB;IAClB,kBAAkB;IAClB,cAAc;AAClB;;AAEA;IACI,eAAe;AACnB;;AAEA;IACI,eAAe;IACf,YAAY;IACZ,iBAAiB;AACrB\",\"sourcesContent\":[\".tab {\\r\\n display: flex;\\r\\n list-style: none;\\r\\n padding: 0;\\r\\n margin: 0;\\r\\n overflow-x: auto;\\r\\n width: 600px;\\r\\n}\\r\\n\\r\\n.title.active {\\r\\n border-bottom: 5px solid lightblue;\\r\\n}\\r\\n\\r\\n.title {\\r\\n background-color: #617aa0;\\r\\n color: white;\\r\\n padding: 15px;\\r\\n border: 1px solid black;\\r\\n width: fit-content;\\r\\n margin-right: 15px;\\r\\n flex-shrink: 0;\\r\\n}\\r\\n\\r\\n.title:hover {\\r\\n cursor: pointer;\\r\\n}\\r\\n\\r\\n.close {\\r\\n cursor: pointer;\\r\\n color: white;\\r\\n margin-left: 15px;\\r\\n}\"],\"sourceRoot\":\"\"}]);\n// Exports\nmodule.exports = ___CSS_LOADER_EXPORT___.toString();\n"],"names":["Component","AppComponent","constructor","_","__decorate","selector","template","__NG_CLI_RESOURCE__0","BrowserModule","NgModule","FormsModule","RouterModule","HttpClientModule","ServiceWorkerModule","ZipcodeEntryComponent","ForecastsListComponent","CurrentConditionsComponent","MainPageComponent","MinMaxTemperatureComponent","LocationService","WeatherService","routing","environment","UITabsModule","AppModule","declarations","imports","register","enabled","production","providers","bootstrap","appRoutes","path","component","forRoot","CACHE_KEYS","CACHE_EXPIRATION_TIME","inject","Router","takeUntil","Action","CacheService","WithUnsubscribe","weatherService","router","cacheService","locationService","currentConditionsByZip","getCurrentConditions","getLocation","pipe","unsubscribe$","subscribe","location","action","ADD","find","conditions","zip","zipcode","addCurrentConditions","REMOVE","removeCurrentConditions","removeItem","CURRENT_CONDITIONS","FORECAST","loadLocations","showForecast","navigate","removeLocation","index","extractHash","tabTitle","matches","match","Location","ActivatedRoute","route","snapshot","params","loadForecast","goBack","back","cachedForecast","getItem","forecast","data","getForecast","setItem","id","Input","withHyphen","Injectable","key","cachedData","getCachedData","currentTime","Date","getTime","dataWithExpiration","expiration","push","localStorage","JSON","stringify","getItems","cachedItem","updatedData","filter","notExpired","parse","providedIn","Subject","LOCATIONS","locations","location$","locString","loc","next","addLocation","includes","splice","asObservable","signal","HttpClient","URL","_3","APPID","_4","ICON_URL","http","currentConditions","cachedConditions","forEach","cache","update","cachedZipConditions","get","WeatherService_1","i","asReadonly","getWeatherIcon","_5","Directive","HostListener","ClickStopPropagation","onClick","event","stopPropagation","args","EventEmitter","Output","UITabItemComponent","closeTab","active","ContentChildren","UITabsComponent","ngAfterContentChecked","fragment","tabs","length","activeTab","tab","setActiveTab","first","setActiveTabHash","removeTab","tabIndex","emit","wasActive","navigateByUrl","selectTab","CommonModule","exports","Base","ngOnDestroy","complete","value","enableProdMode","platformBrowserDynamic","bootstrapModule"],"sourceRoot":"webpack:///","x_google_ignoreList":[]} \ No newline at end of file +{"version":3,"file":"main.js","mappings":"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","sources":["./src/app/app.component.ts","./src/app/app.module.ts","./src/app/app.routing.ts","./src/app/config/cache.config.ts","./src/app/current-conditions/current-conditions.component.ts","./src/app/forecasts-list/forecasts-list.component.ts","./src/app/main-page/main-page.component.ts","./src/app/min-max-temperature/min-max-temperature.component.ts","./src/app/services/cache-service.ts","./src/app/services/location.service.ts","./src/app/services/weather.service.ts","./src/app/ui-tabs/click-stop-propagation.directive.ts","./src/app/ui-tabs/ui-tab-item/ui-tab-item.component.ts","./src/app/ui-tabs/ui-tabs.component.ts","./src/app/ui-tabs/ui-tabs.module.ts","./src/app/utils/with-unsubscribe.ts","./src/app/zipcode-entry/zipcode-entry.component.ts","./src/environments/environment.ts","./src/main.ts","./src/app/app.component.css","./src/app/current-conditions/current-conditions.component.css","./src/app/forecasts-list/forecasts-list.component.css","./src/app/ui-tabs/ui-tab-item/ui-tab-item.component.css","./src/app/ui-tabs/ui-tabs.component.css"],"sourcesContent":["import { Component } from '@angular/core';\r\n\r\n@Component({\r\n selector: 'app-root',\r\n templateUrl: './app.component.html',\r\n styleUrls: ['./app.component.css']\r\n})\r\nexport class AppComponent {\r\n\r\n constructor() {\r\n\r\n }\r\n}\r\n","import { BrowserModule } from '@angular/platform-browser';\r\nimport { NgModule } from '@angular/core';\r\nimport { FormsModule } from '@angular/forms';\r\nimport { RouterModule } from '@angular/router';\r\nimport { HttpClientModule } from '@angular/common/http';\r\nimport { ServiceWorkerModule } from '@angular/service-worker';\r\n\r\nimport { AppComponent } from './app.component';\r\nimport { ZipcodeEntryComponent } from './zipcode-entry/zipcode-entry.component';\r\nimport { ForecastsListComponent } from './forecasts-list/forecasts-list.component';\r\nimport { CurrentConditionsComponent } from './current-conditions/current-conditions.component';\r\nimport { MainPageComponent } from './main-page/main-page.component';\r\nimport { MinMaxTemperatureComponent } from './min-max-temperature/min-max-temperature.component';\r\nimport { LocationService } from './services/location.service';\r\nimport { WeatherService } from './services/weather.service';\r\nimport { routing } from './app.routing';\r\nimport { environment } from '../environments/environment';\r\nimport { UITabsModule } from './ui-tabs/ui-tabs.module';\r\n\r\n@NgModule({\r\n declarations: [\r\n AppComponent,\r\n ZipcodeEntryComponent,\r\n ForecastsListComponent,\r\n CurrentConditionsComponent,\r\n MainPageComponent,\r\n MinMaxTemperatureComponent\r\n ],\r\n imports: [\r\n BrowserModule,\r\n FormsModule,\r\n HttpClientModule,\r\n RouterModule,\r\n UITabsModule,\r\n routing,\r\n ServiceWorkerModule.register('/ngsw-worker.js', { enabled: environment.production })\r\n ],\r\n providers: [LocationService, WeatherService],\r\n bootstrap: [AppComponent]\r\n})\r\nexport class AppModule { }\r\n","import { ModuleWithProviders } from '@angular/core';\r\nimport { Routes, RouterModule } from '@angular/router';\r\nimport { ForecastsListComponent } from './forecasts-list/forecasts-list.component';\r\nimport { MainPageComponent } from './main-page/main-page.component';\r\n\r\nconst appRoutes: Routes = [\r\n {\r\n path: '', component: MainPageComponent\r\n },\r\n {\r\n path: 'forecast/:zipcode', component: ForecastsListComponent\r\n }\r\n];\r\nexport const routing: ModuleWithProviders = RouterModule.forRoot(appRoutes, {});\r\n","export enum CACHE_KEYS {\r\n CURRENT_CONDITIONS = 'current',\r\n FORECAST = 'forecast'\r\n};\r\n\r\n// Cache expiration time in miliseconds\r\nexport const CACHE_EXPIRATION_TIME = 2 * 60 * 60 * 1000;\r\n","import { Component, inject, Signal } from '@angular/core';\r\nimport { Router } from '@angular/router';\r\nimport { takeUntil } from 'rxjs/operators';\r\n\r\nimport { ConditionsAndZip } from '../conditions-and-zip.type';\r\nimport { WeatherService } from '../services/weather.service';\r\nimport { Action, LocationService } from '../services/location.service';\r\nimport { CacheService } from '../services/cache-service';\r\nimport { CACHE_KEYS } from '../config/cache.config';\r\nimport { WithUnsubscribe } from '../utils/with-unsubscribe';\r\n\r\n@Component({\r\n selector: 'app-current-conditions',\r\n templateUrl: './current-conditions.component.html',\r\n styleUrls: ['./current-conditions.component.css']\r\n})\r\nexport class CurrentConditionsComponent extends WithUnsubscribe() {\r\n\r\n private weatherService = inject(WeatherService);\r\n private router = inject(Router);\r\n private cacheService = inject(CacheService);\r\n protected locationService = inject(LocationService);\r\n protected currentConditionsByZip: Signal = this.weatherService.getCurrentConditions();\r\n\r\n constructor() {\r\n super();\r\n\r\n // Subscribe to the locations observable and listen for its events\r\n this.locationService.getLocation().pipe(\r\n takeUntil(this.unsubscribe$)\r\n ).subscribe((location) => {\r\n if (location.action === Action.ADD) {\r\n if (!this.currentConditionsByZip().find(conditions => conditions.zip === location.zipcode))\r\n this.weatherService.addCurrentConditions(location.zipcode);\r\n } else if (location.action === Action.REMOVE) {\r\n const { zipcode } = location;\r\n\r\n this.weatherService.removeCurrentConditions(zipcode);\r\n // Remove the location from the cache as well\r\n this.cacheService.removeItem(CACHE_KEYS.CURRENT_CONDITIONS, zipcode);\r\n this.cacheService.removeItem(CACHE_KEYS.FORECAST, zipcode);\r\n }\r\n });\r\n\r\n // Load the locations after we have\r\n // subscribed to the location observable\r\n this.locationService.loadLocations();\r\n }\r\n\r\n showForecast(zipcode : string){\r\n this.router.navigate(['/forecast', zipcode])\r\n }\r\n\r\n // Remove location from the list by the index\r\n // of the tab which close button is clicked\r\n removeLocation(index: number) {\r\n this.locationService.removeLocation(index);\r\n }\r\n\r\n // Helper method for setting the zipcode to the url hash\r\n extractHash(tabTitle?: string) {\r\n const matches = tabTitle?.match(/\\(([^)]+)\\)/);\r\n\r\n return matches ? matches[1] : '';\r\n }\r\n}\r\n","import { Component } from '@angular/core';\r\nimport { Location } from '@angular/common';\r\nimport { ActivatedRoute } from '@angular/router';\r\nimport { takeUntil } from 'rxjs/operators';\r\n\r\nimport { Forecast } from './forecast.type';\r\nimport { WeatherService } from '../services/weather.service';\r\nimport { CacheService } from '../services/cache-service';\r\nimport { CACHE_KEYS } from '../config/cache.config';\r\nimport { WithUnsubscribe } from '../utils/with-unsubscribe';\r\n\r\n@Component({\r\n selector: 'app-forecasts-list',\r\n templateUrl: './forecasts-list.component.html',\r\n styleUrls: ['./forecasts-list.component.css']\r\n})\r\nexport class ForecastsListComponent extends WithUnsubscribe() {\r\n\r\n zipcode: string;\r\n forecast?: Forecast;\r\n\r\n constructor(\r\n protected weatherService: WeatherService,\r\n route : ActivatedRoute,\r\n private cacheService: CacheService,\r\n private location: Location\r\n ) {\r\n super();\r\n\r\n this.zipcode = route.snapshot.params['zipcode'];\r\n this.loadForecast();\r\n }\r\n\r\n goBack() {\r\n this.location.back();\r\n }\r\n\r\n /**\r\n * Helper method for fetching the 5-day forecast weather\r\n * First, we check for stored forecast in the cache\r\n * If it is available, we use it for initializing forecast\r\n * Otherwise, we fetch the udpated forecast from the API and update the cache\r\n */\r\n private loadForecast() {\r\n const cachedForecast = this.cacheService.getItem(CACHE_KEYS.FORECAST, this.zipcode);\r\n\r\n if (cachedForecast) {\r\n this.forecast = cachedForecast.data as Forecast;\r\n } else {\r\n this.weatherService.getForecast(this.zipcode).pipe(\r\n takeUntil(this.unsubscribe$)\r\n ).subscribe(data => {\r\n this.forecast = data;\r\n\r\n this.cacheService.setItem(CACHE_KEYS.FORECAST, { id: this.zipcode, data });\r\n });\r\n }\r\n }\r\n}\r\n","import { Component } from '@angular/core';\r\n\r\n@Component({\r\n selector: 'app-main-page',\r\n templateUrl: './main-page.component.html'\r\n})\r\nexport class MainPageComponent {\r\n\r\n}\r\n","import { Component, Input } from '@angular/core';\r\n\r\n@Component({\r\n selector: 'app-min-max-temperature',\r\n templateUrl: './min-max-temperature.component.html'\r\n})\r\nexport class MinMaxTemperatureComponent {\r\n @Input() min?: number;\r\n @Input() max?: number;\r\n @Input() withHyphen: boolean = false;\r\n}\r\n","import { Injectable } from '@angular/core';\r\n\r\nimport { CACHE_EXPIRATION_TIME } from '../config/cache.config';\r\n\r\nexport interface CacheData {\r\n id: string;\r\n data: unknown;\r\n expiration: Date | string;\r\n}\r\n\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class CacheService {\r\n /**\r\n * Stores items into browser's local storage with expiration date\r\n * @param key - the key with wich the data will be accessed from the local storage\r\n * @param value - the data which we will store\r\n */\r\n setItem(key: string, data: Pick) {\r\n const cachedData = this.getCachedData(key);\r\n\r\n const currentTime = new Date().getTime();\r\n const dataWithExpiration: CacheData = { ...data, expiration: new Date(currentTime + CACHE_EXPIRATION_TIME) };\r\n\r\n cachedData.push(dataWithExpiration);\r\n \r\n localStorage.setItem(key, JSON.stringify(cachedData));\r\n }\r\n\r\n /**\r\n * Retrieves items from browser's local storage by given key and id\r\n * - If there is some data stored under the given key:\r\n * - Checks whether the data is not expired and needs refresh\r\n * @param key - the key with which data will be searched in the local storage\r\n * @returns the cached data if it is not expired, otherwise, returns null\r\n */\r\n getItem(key: string, id: string): CacheData | undefined {\r\n const cachedData: CacheData[] = this.getItems(key);\r\n const cachedItem: CacheData | undefined = cachedData.find(data => data.id === id);\r\n\r\n return cachedItem;\r\n }\r\n\r\n /**\r\n * Removes item from local storage by key\r\n * @param key - the key with which the data we want to remove is stored in local storage\r\n */\r\n removeItem(key: string, id: string) {\r\n const cachedData = this.getCachedData(key);\r\n const updatedData = cachedData.filter(data => data.id !== id);\r\n \r\n localStorage.setItem(key, JSON.stringify(updatedData));\r\n }\r\n\r\n getItems(key: string): CacheData[] {\r\n const cachedData: CacheData[] = this.getCachedData(key);\r\n const notExpired = cachedData.filter(data => new Date(Date.parse(data.expiration as string)) >= new Date());\r\n\r\n return notExpired;\r\n }\r\n\r\n private getCachedData(key: string): CacheData[] {\r\n return JSON.parse(localStorage.getItem(key) ?? '[]');\r\n }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { Subject } from 'rxjs';\r\n\r\nexport const LOCATIONS : string = 'locations';\r\n\r\nexport enum Action { ADD, REMOVE };\r\n\r\ninterface LocationProps {\r\n action: Action;\r\n zipcode: string;\r\n}\r\n\r\n@Injectable()\r\nexport class LocationService {\r\n\r\n locations : string[] = [];\r\n // Subject for locations changes\r\n private location$ = new Subject();\r\n\r\n constructor() {\r\n let locString = localStorage.getItem(LOCATIONS);\r\n if (locString)\r\n this.locations = JSON.parse(locString);\r\n }\r\n\r\n loadLocations() {\r\n for (let loc of this.locations) {\r\n // Emit add event\r\n this.location$.next({ action: Action.ADD, zipcode: loc });\r\n }\r\n }\r\n\r\n addLocation(zipcode : string) {\r\n // If the location is already added, do not duplicate it\r\n if (this.locations.includes(zipcode)) {\r\n return;\r\n }\r\n\r\n this.locations.push(zipcode);\r\n localStorage.setItem(LOCATIONS, JSON.stringify(this.locations));\r\n\r\n // Emit add event\r\n this.location$.next({ action: Action.ADD, zipcode });\r\n }\r\n\r\n removeLocation(index : number) {\r\n const zipcode = this.locations[index];\r\n \r\n if (index !== -1){\r\n this.locations.splice(index, 1);\r\n localStorage.setItem(LOCATIONS, JSON.stringify(this.locations));\r\n\r\n // Emit remove event\r\n this.location$.next({ action: Action.REMOVE, zipcode });\r\n }\r\n }\r\n\r\n // Export the location subject as observable\r\n // in order to be able to subscribe for the updates\r\n getLocation() {\r\n return this.location$.asObservable();\r\n }\r\n}\r\n","import { Injectable, Signal, signal } from '@angular/core';\r\nimport { HttpClient } from '@angular/common/http';\r\nimport { Observable } from 'rxjs';\r\nimport { takeUntil } from 'rxjs/operators';\r\n\r\nimport { CurrentConditions } from '../current-conditions/current-conditions.type';\r\nimport { ConditionsAndZip } from '../conditions-and-zip.type';\r\nimport { Forecast } from '../forecasts-list/forecast.type';\r\nimport { CacheService } from './cache-service';\r\nimport { CACHE_KEYS } from '../config/cache.config';\r\nimport { WithUnsubscribe } from '../utils/with-unsubscribe';\r\n\r\n\r\n@Injectable()\r\nexport class WeatherService extends WithUnsubscribe() {\r\n\r\n static URL = 'https://api.openweathermap.org/data/2.5';\r\n static APPID = '5a4b2d457ecbef9eb2a71e480b947604';\r\n static ICON_URL = 'https://raw.githubusercontent.com/udacity/Sunshine-Version-2/sunshine_master/app/src/main/res/drawable-hdpi/';\r\n private currentConditions = signal([]);\r\n private cachedConditions;\r\n\r\n constructor(private http: HttpClient, private cacheService: CacheService) {\r\n super();\r\n\r\n // If there is some cached data, we fetch it and\r\n // initialize the currentConditions array with it\r\n this.cachedConditions = this.cacheService.getItems(CACHE_KEYS.CURRENT_CONDITIONS);\r\n\r\n if (this.cachedConditions) {\r\n this.cachedConditions.forEach(cache => {\r\n this.currentConditions.update(conditions => {\r\n const cachedData = {\r\n zip: cache.id,\r\n data: cache.data as CurrentConditions\r\n };\r\n\r\n return [...conditions, cachedData];\r\n });\r\n });\r\n }\r\n }\r\n\r\n addCurrentConditions(zipcode: string): void {\r\n // We first check for cached conditions\r\n const cachedZipConditions = this.cachedConditions.find(conditions => conditions.id === zipcode);\r\n\r\n // If there are already saved conditions in the cache for the given zipcode,\r\n // we use them for updating the currentConditions array\r\n // Otherwise, we fetch the current conditions from the API and update the cache\r\n if (cachedZipConditions) {\r\n this.currentConditions.update(conditions => [...conditions, { zip: zipcode, data: cachedZipConditions.data as CurrentConditions }]);\r\n } else {\r\n // Here we make a request to get the current conditions data from the API. Note the use of backticks and an expression to insert the zipcode\r\n this.http.get(`${WeatherService.URL}/weather?zip=${zipcode},us&units=imperial&APPID=${WeatherService.APPID}`)\r\n .pipe(takeUntil(this.unsubscribe$))\r\n .subscribe(data => {\r\n this.currentConditions.update(conditions => [...conditions, { zip: zipcode, data }]);\r\n this.cacheService.setItem(CACHE_KEYS.CURRENT_CONDITIONS, { id: zipcode, data });\r\n });\r\n }\r\n }\r\n\r\n removeCurrentConditions(zipcode: string) {\r\n this.currentConditions.update(conditions => {\r\n for (let i in conditions) {\r\n if (conditions[i].zip == zipcode)\r\n conditions.splice(+i, 1);\r\n }\r\n return conditions;\r\n });\r\n }\r\n\r\n getCurrentConditions(): Signal {\r\n return this.currentConditions.asReadonly();\r\n }\r\n\r\n getForecast(zipcode: string): Observable {\r\n // Here we make a request to get the forecast data from the API. Note the use of backticks and an expression to insert the zipcode\r\n return this.http.get(`${WeatherService.URL}/forecast/daily?zip=${zipcode},us&units=imperial&cnt=5&APPID=${WeatherService.APPID}`);\r\n }\r\n\r\n getWeatherIcon(id: number): string {\r\n if (id >= 200 && id <= 232)\r\n return WeatherService.ICON_URL + 'art_storm.png';\r\n else if (id >= 501 && id <= 511)\r\n return WeatherService.ICON_URL + 'art_rain.png';\r\n else if (id === 500 || (id >= 520 && id <= 531))\r\n return WeatherService.ICON_URL + 'art_light_rain.png';\r\n else if (id >= 600 && id <= 622)\r\n return WeatherService.ICON_URL + 'art_snow.png';\r\n else if (id >= 801 && id <= 804)\r\n return WeatherService.ICON_URL + 'art_clouds.png';\r\n else if (id === 741 || id === 761)\r\n return WeatherService.ICON_URL + 'art_fog.png';\r\n else\r\n return WeatherService.ICON_URL + 'art_clear.png';\r\n }\r\n}\r\n","import { Directive, HostListener } from '@angular/core';\r\n \r\n@Directive({\r\n selector: '[click-stop-propagation]'\r\n})\r\nexport class ClickStopPropagation\r\n{\r\n @HostListener('click', ['$event'])\r\n public onClick(event: any): void\r\n {\r\n event.stopPropagation();\r\n }\r\n}","import { Component, EventEmitter, Input, Output } from '@angular/core';\r\n\r\n@Component({\r\n selector: 'app-ui-tab-item',\r\n templateUrl: './ui-tab-item.component.html',\r\n styleUrls: ['./ui-tab-item.component.css']\r\n})\r\nexport class UITabItemComponent {\r\n @Input() tabTitle?: string;\r\n @Output() closeTab = new EventEmitter();\r\n\r\n active = false;\r\n}\r\n","import { AfterContentChecked, Component, ContentChildren, Input, QueryList } from '@angular/core';\r\nimport { ActivatedRoute, Router } from '@angular/router';\r\n\r\nimport { UITabItemComponent } from './ui-tab-item/ui-tab-item.component';\r\n\r\n\r\n@Component({\r\n selector: 'app-ui-tabs',\r\n templateUrl: './ui-tabs.component.html',\r\n styleUrls: ['./ui-tabs.component.css']\r\n})\r\nexport class UITabsComponent implements AfterContentChecked {\r\n @Input() extractHash!: (key?: string) => string;\r\n @ContentChildren(UITabItemComponent) tabs!: QueryList;\r\n activeTab?: UITabItemComponent;\r\n\r\n constructor(private route: ActivatedRoute, private router: Router) { }\r\n\r\n ngAfterContentChecked() {\r\n // Set the last active tab using the url hash\r\n // If there is no hash, activate the first tab\r\n if (this.route.snapshot.fragment && this.tabs.length > 0) {\r\n const fragment = this.route.snapshot.fragment;\r\n this.activeTab = this.tabs.find(tab => this.extractHash(tab.tabTitle) === fragment);\r\n\r\n this.setActiveTab();\r\n } else {\r\n this.activeTab = this.tabs.first;\r\n\r\n this.setActiveTab();\r\n this.setActiveTabHash();\r\n }\r\n }\r\n\r\n removeTab(tabIndex: number) {\r\n const tab = this.tabs.get(tabIndex);\r\n\r\n // Emit the tab index to remove\r\n // the corresponding location as well\r\n tab?.closeTab.emit(tabIndex);\r\n\r\n const wasActive = tab?.active;\r\n\r\n // If the removed tab was active\r\n // we set the previous one or the next one\r\n // (if it was the first tab) to active\r\n if (wasActive) {\r\n // If it was the only tab, remove the hash from the url\r\n if (this.tabs.length === 1) {\r\n this.router.navigateByUrl('/');\r\n }\r\n\r\n this.activeTab = this.tabs.get(tabIndex > 0 ? tabIndex - 1 : tabIndex + 1);\r\n\r\n this.setActiveTab();\r\n this.setActiveTabHash();\r\n }\r\n }\r\n\r\n // Activate the current tab and show its content\r\n selectTab(tab: UITabItemComponent) {\r\n this.tabs.forEach((tab) => {\r\n tab.active = false;\r\n });\r\n\r\n this.activeTab = tab;\r\n\r\n this.setActiveTab();\r\n this.setActiveTabHash();\r\n }\r\n\r\n // Helper method for remembering the selected tab with a hash in the url\r\n private setActiveTabHash() {\r\n if (this.activeTab) {\r\n this.router.navigateByUrl('#' + this.extractHash(this.activeTab.tabTitle));\r\n }\r\n }\r\n\r\n private setActiveTab() {\r\n if (this.activeTab) {\r\n this.activeTab.active = true;\r\n }\r\n }\r\n}\r\n","import { NgModule } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\n\r\nimport { UITabItemComponent } from './ui-tab-item/ui-tab-item.component';\r\nimport { UITabsComponent } from './ui-tabs.component';\r\nimport { ClickStopPropagation } from './click-stop-propagation.directive';\r\n\r\n@NgModule({\r\n declarations: [\r\n UITabsComponent,\r\n UITabItemComponent,\r\n ClickStopPropagation\r\n ],\r\n imports: [CommonModule],\r\n exports: [UITabsComponent, UITabItemComponent]\r\n})\r\nexport class UITabsModule { }","import { OnDestroy } from \"@angular/core\";\r\nimport { Subject } from \"rxjs\";\r\n\r\nexport function WithUnsubscribe() {\r\n return class Base implements OnDestroy {\r\n protected unsubscribe$ = new Subject();\r\n\r\n ngOnDestroy(): void {\r\n this.unsubscribe$.next();\r\n this.unsubscribe$.complete();\r\n }\r\n }\r\n}\r\n","import { Component } from '@angular/core';\r\n\r\nimport { LocationService } from '../services/location.service';\r\n\r\n@Component({\r\n selector: 'app-zipcode-entry',\r\n templateUrl: './zipcode-entry.component.html'\r\n})\r\nexport class ZipcodeEntryComponent {\r\n\r\n constructor(private locationService : LocationService) { }\r\n\r\n addLocation(zipcode: HTMLInputElement) {\r\n this.locationService.addLocation(zipcode.value);\r\n zipcode.value = '';\r\n }\r\n\r\n}\r\n","// The file contents for the current environment will overwrite these during build.\r\n// The build system defaults to the dev environment which uses `environment.ts`, but if you do\r\n// `ng build --env=prod` then `environment.prod.ts` will be used instead.\r\n// The list of which env maps to which file can be found in `.angular-cli.json`.\r\n\r\nexport const environment = {\r\n production: false\r\n};\r\n","import { enableProdMode } from '@angular/core';\r\nimport { platformBrowserDynamic } from '@angular/platform-browser-dynamic';\r\n\r\nimport { AppModule } from './app/app.module';\r\nimport { environment } from './environments/environment';\r\n\r\nif (environment.production) {\r\n enableProdMode();\r\n}\r\n\r\nplatformBrowserDynamic().bootstrapModule(AppModule);\r\n","// Imports\nvar ___CSS_LOADER_API_SOURCEMAP_IMPORT___ = require(\"../../node_modules/css-loader/dist/runtime/sourceMaps.js\");\nvar ___CSS_LOADER_API_IMPORT___ = require(\"../../node_modules/css-loader/dist/runtime/api.js\");\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, ``, \"\",{\"version\":3,\"sources\":[],\"names\":[],\"mappings\":\"\",\"sourceRoot\":\"\"}]);\n// Exports\nmodule.exports = ___CSS_LOADER_EXPORT___.toString();\n","// Imports\nvar ___CSS_LOADER_API_SOURCEMAP_IMPORT___ = require(\"../../../node_modules/css-loader/dist/runtime/sourceMaps.js\");\nvar ___CSS_LOADER_API_IMPORT___ = require(\"../../../node_modules/css-loader/dist/runtime/api.js\");\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, `.wrapper {\r\n display: flex;\r\n width: 100%;\r\n justify-content: flex-start;\r\n}\r\n\r\n.flex {\r\n display: flex;\r\n justify-content: space-between;\r\n}\r\n`, \"\",{\"version\":3,\"sources\":[\"webpack://./src/app/current-conditions/current-conditions.component.css\"],\"names\":[],\"mappings\":\"AAAA;EACE,aAAa;EACb,WAAW;EACX,2BAA2B;AAC7B;;AAEA;EACE,aAAa;EACb,8BAA8B;AAChC\",\"sourcesContent\":[\".wrapper {\\r\\n display: flex;\\r\\n width: 100%;\\r\\n justify-content: flex-start;\\r\\n}\\r\\n\\r\\n.flex {\\r\\n display: flex;\\r\\n justify-content: space-between;\\r\\n}\\r\\n\"],\"sourceRoot\":\"\"}]);\n// Exports\nmodule.exports = ___CSS_LOADER_EXPORT___.toString();\n","// Imports\nvar ___CSS_LOADER_API_SOURCEMAP_IMPORT___ = require(\"../../../node_modules/css-loader/dist/runtime/sourceMaps.js\");\nvar ___CSS_LOADER_API_IMPORT___ = require(\"../../../node_modules/css-loader/dist/runtime/api.js\");\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, `.icon {\r\n width: 45px;\r\n height: 45px;\r\n position: absolute;\r\n right: 20px;\r\n top: -2px;\r\n}\r\n`, \"\",{\"version\":3,\"sources\":[\"webpack://./src/app/forecasts-list/forecasts-list.component.css\"],\"names\":[],\"mappings\":\"AAAA;EACE,WAAW;EACX,YAAY;EACZ,kBAAkB;EAClB,WAAW;EACX,SAAS;AACX\",\"sourcesContent\":[\".icon {\\r\\n width: 45px;\\r\\n height: 45px;\\r\\n position: absolute;\\r\\n right: 20px;\\r\\n top: -2px;\\r\\n}\\r\\n\"],\"sourceRoot\":\"\"}]);\n// Exports\nmodule.exports = ___CSS_LOADER_EXPORT___.toString();\n","// Imports\nvar ___CSS_LOADER_API_SOURCEMAP_IMPORT___ = require(\"../../../../node_modules/css-loader/dist/runtime/sourceMaps.js\");\nvar ___CSS_LOADER_API_IMPORT___ = require(\"../../../../node_modules/css-loader/dist/runtime/api.js\");\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, `.body {\r\n width: 600px;\r\n height: 300px;\r\n border: 1px solid black;\r\n padding: 25px;\r\n}`, \"\",{\"version\":3,\"sources\":[\"webpack://./src/app/ui-tabs/ui-tab-item/ui-tab-item.component.css\"],\"names\":[],\"mappings\":\"AAAA;IACI,YAAY;IACZ,aAAa;IACb,uBAAuB;IACvB,aAAa;AACjB\",\"sourcesContent\":[\".body {\\r\\n width: 600px;\\r\\n height: 300px;\\r\\n border: 1px solid black;\\r\\n padding: 25px;\\r\\n}\"],\"sourceRoot\":\"\"}]);\n// Exports\nmodule.exports = ___CSS_LOADER_EXPORT___.toString();\n","// Imports\nvar ___CSS_LOADER_API_SOURCEMAP_IMPORT___ = require(\"../../../node_modules/css-loader/dist/runtime/sourceMaps.js\");\nvar ___CSS_LOADER_API_IMPORT___ = require(\"../../../node_modules/css-loader/dist/runtime/api.js\");\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, `.tab {\r\n display: flex;\r\n list-style: none;\r\n padding: 0;\r\n margin: 0;\r\n overflow-x: auto;\r\n width: 600px;\r\n}\r\n\r\n.title.active {\r\n border-bottom: 5px solid lightblue;\r\n}\r\n\r\n.title {\r\n background-color: #617aa0;\r\n color: white;\r\n padding: 15px;\r\n border: 1px solid black;\r\n width: -moz-fit-content;\r\n width: fit-content;\r\n margin-right: 15px;\r\n flex-shrink: 0;\r\n}\r\n\r\n.title:hover {\r\n cursor: pointer;\r\n}\r\n\r\n.close {\r\n cursor: pointer;\r\n color: white;\r\n margin-left: 15px;\r\n}`, \"\",{\"version\":3,\"sources\":[\"webpack://./src/app/ui-tabs/ui-tabs.component.css\"],\"names\":[],\"mappings\":\"AAAA;IACI,aAAa;IACb,gBAAgB;IAChB,UAAU;IACV,SAAS;IACT,gBAAgB;IAChB,YAAY;AAChB;;AAEA;IACI,kCAAkC;AACtC;;AAEA;IACI,yBAAyB;IACzB,YAAY;IACZ,aAAa;IACb,uBAAuB;IACvB,uBAAkB;IAAlB,kBAAkB;IAClB,kBAAkB;IAClB,cAAc;AAClB;;AAEA;IACI,eAAe;AACnB;;AAEA;IACI,eAAe;IACf,YAAY;IACZ,iBAAiB;AACrB\",\"sourcesContent\":[\".tab {\\r\\n display: flex;\\r\\n list-style: none;\\r\\n padding: 0;\\r\\n margin: 0;\\r\\n overflow-x: auto;\\r\\n width: 600px;\\r\\n}\\r\\n\\r\\n.title.active {\\r\\n border-bottom: 5px solid lightblue;\\r\\n}\\r\\n\\r\\n.title {\\r\\n background-color: #617aa0;\\r\\n color: white;\\r\\n padding: 15px;\\r\\n border: 1px solid black;\\r\\n width: fit-content;\\r\\n margin-right: 15px;\\r\\n flex-shrink: 0;\\r\\n}\\r\\n\\r\\n.title:hover {\\r\\n cursor: pointer;\\r\\n}\\r\\n\\r\\n.close {\\r\\n cursor: pointer;\\r\\n color: white;\\r\\n margin-left: 15px;\\r\\n}\"],\"sourceRoot\":\"\"}]);\n// Exports\nmodule.exports = ___CSS_LOADER_EXPORT___.toString();\n"],"names":["Component","AppComponent","constructor","_","__decorate","selector","template","__NG_CLI_RESOURCE__0","BrowserModule","NgModule","FormsModule","RouterModule","HttpClientModule","ServiceWorkerModule","ZipcodeEntryComponent","ForecastsListComponent","CurrentConditionsComponent","MainPageComponent","MinMaxTemperatureComponent","LocationService","WeatherService","routing","environment","UITabsModule","AppModule","declarations","imports","register","enabled","production","providers","bootstrap","appRoutes","path","component","forRoot","CACHE_KEYS","CACHE_EXPIRATION_TIME","inject","Router","takeUntil","Action","CacheService","WithUnsubscribe","weatherService","router","cacheService","locationService","currentConditionsByZip","getCurrentConditions","getLocation","pipe","unsubscribe$","subscribe","location","action","ADD","find","conditions","zip","zipcode","addCurrentConditions","REMOVE","removeCurrentConditions","removeItem","CURRENT_CONDITIONS","FORECAST","loadLocations","showForecast","navigate","removeLocation","index","extractHash","tabTitle","matches","match","Location","ActivatedRoute","route","snapshot","params","loadForecast","goBack","back","cachedForecast","getItem","forecast","data","getForecast","setItem","id","Input","withHyphen","Injectable","key","cachedData","getCachedData","currentTime","Date","getTime","dataWithExpiration","expiration","push","localStorage","JSON","stringify","getItems","cachedItem","updatedData","filter","notExpired","parse","providedIn","Subject","LOCATIONS","locations","location$","locString","loc","next","addLocation","includes","splice","asObservable","signal","HttpClient","URL","_3","APPID","_4","ICON_URL","http","currentConditions","cachedConditions","forEach","cache","update","cachedZipConditions","get","WeatherService_1","i","asReadonly","getWeatherIcon","_5","Directive","HostListener","ClickStopPropagation","onClick","event","stopPropagation","args","EventEmitter","Output","UITabItemComponent","closeTab","active","ContentChildren","UITabsComponent","ngAfterContentChecked","fragment","tabs","length","activeTab","tab","setActiveTab","first","setActiveTabHash","removeTab","tabIndex","emit","wasActive","navigateByUrl","selectTab","CommonModule","exports","Base","ngOnDestroy","complete","value","enableProdMode","platformBrowserDynamic","bootstrapModule"],"sourceRoot":"webpack:///","x_google_ignoreList":[]} \ No newline at end of file