diff --git a/app/pages/rovers/pickers/pickers.component.css b/app/pages/rovers/pickers/pickers.component.css index 4ecf5a8..dbee1c7 100644 --- a/app/pages/rovers/pickers/pickers.component.css +++ b/app/pages/rovers/pickers/pickers.component.css @@ -12,18 +12,21 @@ GridLayout { DatePicker, Label, Segmentedbar { opacity: 0.9; - width: 90%; + width: 95%; } DatePicker { color: #282a2a; } +.desc Label { + padding: 0 8 0 8; +} + Label { background-color: #282a2a; border-radius: 10 10 0 0; color: #BCBCBC; - padding: 8; } SegmentedBar { @@ -42,5 +45,5 @@ Button { background-color: #282a2a; border-radius: 20; color: #E8EAEB; - width: 90%; + width: 95%; } \ No newline at end of file diff --git a/app/pages/rovers/pickers/pickers.component.html b/app/pages/rovers/pickers/pickers.component.html index 778e140..a27da57 100644 --- a/app/pages/rovers/pickers/pickers.component.html +++ b/app/pages/rovers/pickers/pickers.component.html @@ -1,6 +1,6 @@ - + - + - - + + + + + + + + - - + + + - + diff --git a/app/pages/rovers/pickers/pickers.component.ts b/app/pages/rovers/pickers/pickers.component.ts index 122f4aa..febf773 100644 --- a/app/pages/rovers/pickers/pickers.component.ts +++ b/app/pages/rovers/pickers/pickers.component.ts @@ -1,4 +1,8 @@ +/* Angular */ +import { Component } from "@angular/core"; import { RouterExtensions } from "nativescript-angular/router"; + +/* NativeScript MOdules */ import { isAndroid } from "tns-core-modules/platform"; import { Page } from "tns-core-modules/ui/page"; import { DatePicker } from "tns-core-modules/ui/date-picker"; @@ -7,7 +11,9 @@ import { SegmentedBar, SegmentedBarItem } from "tns-core-modules/ui/segmented-bar"; -import { Component } from "@angular/core"; + +/* Shared */ +import { RoverPhotosService } from "../../../services/rover.service"; @Component({ selector: "cosmos-pickers", @@ -20,6 +26,11 @@ export class PickersComponent { selectedRover: string; desc: string = ""; allowedRange: string = ""; + manifest_obj: any; + + curiosity_obj = {}; + opportunity_obj = {}; + spirit_obj = {}; private _today: Date; private _day: number; @@ -30,17 +41,39 @@ export class PickersComponent { private _datePicker: DatePicker; private _stackList: StackLayout; private _stackDate: StackLayout; + private _segbar: SegmentedBar; public mySegmentedBarItems: Array; - constructor(private _page: Page, private _router: RouterExtensions) { + constructor(private _page: Page, private _router: RouterExtensions, private _roverService: RoverPhotosService) { + this._today = new Date(); // temp + + this._roverService.getCuriosityManifest().subscribe(manifest => { + this.curiosity_obj = manifest; + this.manifest_obj = this.curiosity_obj; + + const date = new Date(this.manifest_obj.photo_manifest.max_date); // last known date with photos (Curiosity) + this._today = date; + + this.adjustDatePickerForSelectedRover(this._today); // initial date set to max_date (last known date with photos) + }) + + this._roverService.getOpportunityManifest().subscribe(manifest => { + this.opportunity_obj = manifest; + }) + + this._roverService.getSpiritManifest().subscribe(manifest => { + this.spirit_obj = manifest; + }) + + this.mySegmentedBarItems = []; for (let i = 0; i < 3; i++) { const item = new SegmentedBarItem(); if (i === 0) { - item.title = "Opportunity"; - } else if (i === 1) { item.title = "Curiosity"; + } else if (i === 1) { + item.title = "Opportunity"; } else if (i === 2) { item.title = "Spirit"; } @@ -54,19 +87,14 @@ export class PickersComponent { // as only Spirit rover is requiring to change the min-max date // out of range the temp solution is to remove Spirit if (android.os.Build.VERSION.SDK_INT > 21) { - this.rovers = ["Opportunity", "Curiosity", "Spirit"]; + this.rovers = ["Curiosity", "Opportunity", "Spirit"]; } else { - this.rovers = ["Opportunity", "Curiosity"]; + this.rovers = ["Curiosity", "Opportunity"]; } } else { // iOS - this.rovers = ["Opportunity", "Curiosity", "Spirit"]; + this.rovers = ["Curiosity", "Opportunity", "Spirit"]; } - - const date = new Date(); - date.setDate(date.getDate() - 2); - - this._today = date; } goToPhotos() { @@ -83,6 +111,7 @@ export class PickersComponent { // remember the chosen date & rover on navigation backwards this.selectedRover = this.rovers[this._selectedIndex].toLowerCase(); this._today = new Date(this._year, this._month - 1, this._day + 1); // e.g. new Date(2018, 4 + 1, 9); + console.log(`goToPhotos this.selectedRover ${this.selectedRover}`); // TODO use this to change the default loaded rover console.log(`goToPhotos this_today: ${this._today}`); } @@ -122,8 +151,8 @@ export class PickersComponent { /* SegmentedBar logic START */ onSegmentedbarLoaded(args) { - let segbar = args.object; - segbar.selectedIndex = 1; + this._segbar = args.object as SegmentedBar; + // this._segbar.selectedIndex = 1; } onSelectedIndexChange(args) { @@ -137,8 +166,7 @@ export class PickersComponent { /* DatePicker logic START */ onDatePickerLoaded(args) { - this._datePicker = args.object; - this.adjustDatePickerForSelectedRover(this._today); + this._datePicker = args.object as DatePicker; } onDayChanged(args) { @@ -158,47 +186,31 @@ export class PickersComponent { if (this.selectedRover && this._datePicker) { switch (this.selectedRover.toLowerCase()) { case "opportunity": - this._datePicker.minDate = new Date(2004, 0, 26); - this._datePicker.maxDate = new Date(2018, 4 + 1, 9); - - // intial values for picker date and for the queryParams - this._datePicker.year = today.getUTCFullYear(); - this._year = this._datePicker.year; - this._datePicker.month = today.getUTCMonth() + 1; - this._month = this._datePicker.month; - this._datePicker.day = today.getUTCDate(); - this._day = this._datePicker.day; - - this.allowedRange = "Active: January 26th 2004 - June 9th 2018"; this.desc = " Opportunity (MER-B), Mars Exploration Rover, launched on July 7, 2003 and landed on January 25, 2004. Opportunity surpassed the previous records for longevity at 5,352 sols (5498 Earth days from landing to mission end; 15 Earth years or 8 Martian years) and covered a total distance of 40.25 km (25.01 mi). The rover sent its last status on 10 June 2018 when a global 2018 Mars dust storm blocked the sunlight needed to recharge its batteries. After hundreds of attempts to reactivate the rover, NASA declared the mission complete on February 13, 2019."; + + this.manifest_obj = this.opportunity_obj; + + this._datePicker.minDate = new Date(2004, 0, 26); + this._datePicker.maxDate = new Date(this.manifest_obj.photo_manifest.max_date); + this._datePicker.date = new Date(this.manifest_obj.photo_manifest.max_date); // initial and max allowed date (where photos actually exists) break; case "curiosity": - this._datePicker.minDate = new Date(2012, 6 + 1, 6); - this._datePicker.maxDate = new Date(); - - this._datePicker.year = today.getUTCFullYear(); - this._year = this._datePicker.year; - this._datePicker.month = today.getUTCMonth() + 1; - this._month = this._datePicker.month; - this._datePicker.day = today.getUTCDate(); - this._day = this._datePicker.day; - - this.allowedRange = "Active: August 7th 2007 - Present"; this.desc = "Curiosity of the Mars Science Laboratory (MSL) mission by NASA, was launched November 26, 2011 and landed at the Aeolis Palus plain near Aeolis Mons (informally 'Mount Sharp') in Gale Crater on August 6, 2012. The Curiosity rover is still operational as of July 23, 2019."; + + this.manifest_obj = this.curiosity_obj; + + this._datePicker.minDate = new Date(2004, 0, 26); + this._datePicker.maxDate = new Date(this.manifest_obj.photo_manifest.max_date); + this._datePicker.date = new Date(this.manifest_obj.photo_manifest.max_date); // initial and max allowed date (where photos actually exists) break; case "spirit": - this._datePicker.minDate = new Date(2004, 0, 5); - this._datePicker.maxDate = new Date(2010, 1 + 1, 21); - - this._datePicker.year = 2008; - this._year = this._datePicker.year; - this._datePicker.month = 6; - this._month = this._datePicker.month; - this._datePicker.day = 2; - this._day = this._datePicker.day; - - this.allowedRange = "Active: January 5th 2004 - March 21th 2010"; this.desc = "Spirit (MER-A), Mars Exploration Rover, launched on June 10, 2003, and landed on January 4, 2004. Nearly 6 years after the original mission limit, Spirit had covered a total distance of 7.73 km (4.80 mi) but its wheels became trapped in sand. The last communication received from the rover was on March 22, 2010, and NASA ceased attempts to re-establish communication on May 25, 2011."; + + this.manifest_obj = this.spirit_obj; + + this._datePicker.minDate = new Date(2004, 0, 26); + this._datePicker.maxDate = new Date(this.manifest_obj.photo_manifest.max_date); + this._datePicker.date = new Date(this.manifest_obj.photo_manifest.max_date); // initial and max allowed date (where photos actually exists) break; default: break; diff --git a/app/services/rover.service.ts b/app/services/rover.service.ts index 9f28e24..62ac4fb 100644 --- a/app/services/rover.service.ts +++ b/app/services/rover.service.ts @@ -17,10 +17,56 @@ export class RoverPhotosService { API_URL_START: string; API_URL_DATE: string; + API_MANIFEST_CURIOSITY: any; + API_MANIFEST_SPIRIT: any; + API_MANIFEST_OPPORTUNITY: any; + /* + Mission Manifest + + A mission manifest is available for each Rover at /manifests/rover_name. + This manifest will list details of the Rover's mission to help narrow down photo queries to the API. + The information in the manifest includes: + + Key Description + name Name of the Rover + landing_date The Rover's landing date on Mars + launch_date The Rover's launch date from Earth + status The Rover's mission status + max_sol The most recent Martian sol from which photos exist + max_date The most recent Earth date from which photos exist + total_photos Number of photos taken by that Rover + + */ + constructor(private _http: HttpClient) { this.API_URL_START = "https://api.nasa.gov/mars-photos/api/v1/rovers/"; this.API_URL_DATE = "/photos?earth_date="; this.NASA_API_KEY = getApiKey(); + + this.API_MANIFEST_CURIOSITY = "https://api.nasa.gov/mars-photos/api/v1/manifests/Curiosity?api_key=" + getApiKey(); + this.API_MANIFEST_SPIRIT = "https://api.nasa.gov/mars-photos/api/v1/manifests/Spirit?api_key=" + getApiKey(); + this.API_MANIFEST_OPPORTUNITY = "https://api.nasa.gov/mars-photos/api/v1/manifests/Opportunity?api_key=" + getApiKey(); + } + + getCuriosityManifest() { + return this._http.get(this.API_MANIFEST_CURIOSITY) + .pipe(map(data => { + return data; + })); + } + + getOpportunityManifest() { + return this._http.get(this.API_MANIFEST_OPPORTUNITY) + .pipe(map(data => { + return data; + })); + } + + getSpiritManifest() { + return this._http.get(this.API_MANIFEST_SPIRIT) + .pipe(map(data => { + return data; + })); } getPhotosWithDateAndPageIndex(rover: string, year: number, month: number, day: number, pageIndex: number) { diff --git a/package.json b/package.json index 9e8ef31..cd74d73 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,10 @@ "readme": "NativeScript Application", "repository": "", "nativescript": { - "id": "org.nativescript.curiosity" + "id": "org.nativescript.curiosity", + "tns-android": { + "version": "6.3.1" + } }, "dependencies": { "@angular/animations": "~8.2.0", @@ -16,17 +19,17 @@ "@angular/platform-browser": "~8.2.0", "@angular/platform-browser-dynamic": "~8.2.0", "@angular/router": "~8.2.0", - "nativescript-angular": "~8.2.1", + "nativescript-angular": "~8.20.4", "nativescript-app-center": "~1.0.3", "nativescript-cardview": "~3.2.0", - "nativescript-permissions": "~1.3.6", - "nativescript-plugin-firebase": "~10.0.0", + "nativescript-permissions": "~1.3.8", + "nativescript-plugin-firebase": "~10.3.3", "nativescript-social-share": "~1.5.2", "nativescript-theme-core": "~1.0.6", - "nativescript-ui-sidedrawer": "~7.0.2", + "nativescript-ui-sidedrawer": "~8.0.0", "reflect-metadata": "~0.1.13", "rxjs": "^6.3.3", - "tns-core-modules": "~6.1.1", + "tns-core-modules": "~6.3.2", "zone.js": "^0.9.1" }, "devDependencies": { @@ -39,8 +42,8 @@ "mocha": "~5.2.0", "mochawesome": "~3.1.2", "nativescript-dev-appium": "next", - "nativescript-dev-webpack": "~1.2.0", - "tns-platform-declarations": "~6.1.1", + "nativescript-dev-webpack": "~1.4.1", + "tns-platform-declarations": "~6.3.2", "tslint": "~5.19.0", "typescript": "~3.5.3" }, diff --git a/webpack.config.js b/webpack.config.js index 43c3d92..532fb64 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -7,6 +7,7 @@ const { nsReplaceBootstrap } = require("nativescript-dev-webpack/transformers/ns const { nsReplaceLazyLoader } = require("nativescript-dev-webpack/transformers/ns-replace-lazy-loader"); const { nsSupportHmrNg } = require("nativescript-dev-webpack/transformers/ns-support-hmr-ng"); const { getMainModulePath } = require("nativescript-dev-webpack/utils/ast-utils"); +const { getNoEmitOnErrorFromTSConfig, getCompilerOptionsFromTSConfig } = require("nativescript-dev-webpack/utils/tsconfig-utils"); const CleanWebpackPlugin = require("clean-webpack-plugin"); const CopyWebpackPlugin = require("copy-webpack-plugin"); const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer"); @@ -51,14 +52,36 @@ module.exports = env => { unitTesting, // --env.unitTesting verbose, // --env.verbose snapshotInDocker, // --env.snapshotInDocker - skipSnapshotTools // --env.skipSnapshotTools + skipSnapshotTools, // --env.skipSnapshotTools + compileSnapshot // --env.compileSnapshot } = env; + const useLibs = compileSnapshot; const isAnySourceMapEnabled = !!sourceMap || !!hiddenSourceMap; const externals = nsWebpack.getConvertedExternals(env.externals); const appFullPath = resolve(projectRoot, appPath); - const appResourcesFullPath = resolve(projectRoot, appResourcesPath); const tsConfigName = "tsconfig.tns.json"; + const tsConfigPath = join(__dirname, tsConfigName); + const hasRootLevelScopedModules = nsWebpack.hasRootLevelScopedModules({ projectDir: projectRoot }); + const hasRootLevelScopedAngular = nsWebpack.hasRootLevelScopedAngular({ projectDir: projectRoot }); + let coreModulesPackageName = "tns-core-modules"; + const alias = { + '~': appFullPath + }; + + const compilerOptions = getCompilerOptionsFromTSConfig(tsConfigPath); + if (hasRootLevelScopedModules) { + coreModulesPackageName = "@nativescript/core"; + alias["tns-core-modules"] = coreModulesPackageName; + nsWebpack.processTsPathsForScopedModules({ compilerOptions }); + } + + if (hasRootLevelScopedAngular) { + alias["nativescript-angular"] = "@nativescript/angular"; + nsWebpack.processTsPathsForScopedAngular({ compilerOptions }); + } + + const appResourcesFullPath = resolve(projectRoot, appResourcesPath); const entryModule = `${nsWebpack.getEntryModule(appFullPath, platform)}.ts`; const entryPath = `.${sep}${entryModule}`; const entries = { bundle: entryPath }; @@ -95,10 +118,11 @@ module.exports = env => { hostReplacementPaths: nsWebpack.getResolver([platform, "tns"]), platformTransformers: ngCompilerTransformers.map(t => t(() => ngCompilerPlugin, resolve(appFullPath, entryModule), projectRoot)), mainPath: join(appFullPath, entryModule), - tsConfigPath: join(__dirname, tsConfigName), + tsConfigPath, skipCodeGeneration: !aot, sourceMap: !!isAnySourceMapEnabled, - additionalLazyModuleResources: additionalLazyModuleResources + additionalLazyModuleResources: additionalLazyModuleResources, + compilerOptions: { paths: compilerOptions.paths } }); let sourceMapFilename = nsWebpack.getSourceMapFilename(hiddenSourceMap, __dirname, dist); @@ -109,6 +133,8 @@ module.exports = env => { itemsToClean.push(`${join(projectRoot, "platforms", "android", "app", "build", "configurations", "nativescript-android-snapshot")}`); } + const noEmitOnErrorFromTSConfig = getNoEmitOnErrorFromTSConfig(join(projectRoot, tsConfigName)); + nsWebpack.processAppComponents(appComponents, platform); const config = { mode: production ? "production" : "development", @@ -136,14 +162,12 @@ module.exports = env => { extensions: [".ts", ".js", ".scss", ".css"], // Resolve {N} system modules from tns-core-modules modules: [ - resolve(__dirname, "node_modules/tns-core-modules"), + resolve(__dirname, `node_modules/${coreModulesPackageName}`), resolve(__dirname, "node_modules"), - "node_modules/tns-core-modules", + `node_modules/${coreModulesPackageName}`, "node_modules", ], - alias: { - '~': appFullPath - }, + alias, symlinks: true }, resolveLoader: { @@ -160,6 +184,7 @@ module.exports = env => { devtool: hiddenSourceMap ? "hidden-source-map" : (sourceMap ? "inline-source-map" : "none"), optimization: { runtimeChunk: "single", + noEmitOnErrors: noEmitOnErrorFromTSConfig, splitChunks: { cacheGroups: { vendor: { @@ -222,19 +247,24 @@ module.exports = env => { { test: /\.html$|\.xml$/, use: "raw-loader" }, - // tns-core-modules reads the app.css and its imports using css-loader { test: /[\/|\\]app\.css$/, use: [ "nativescript-dev-webpack/style-hot-loader", - { loader: "css-loader", options: { url: false } } + { + loader: "nativescript-dev-webpack/css2json-loader", + options: { useForImports: true } + } ] }, { test: /[\/|\\]app\.scss$/, use: [ "nativescript-dev-webpack/style-hot-loader", - { loader: "css-loader", options: { url: false } }, + { + loader: "nativescript-dev-webpack/css2json-loader", + options: { useForImports: true } + }, "sass-loader" ] }, @@ -311,7 +341,8 @@ module.exports = env => { projectRoot, webpackConfig: config, snapshotInDocker, - skipSnapshotTools + skipSnapshotTools, + useLibs })); }