# <center>17^th^ July, 2019</center> ###### tags: `Daily Internship Documentation` --- ## 11^th^ Day of Internship ## Summary Today I finish the conversion value for the temperature display from Celsius to Fahrenheit. And then I re-integrate the pages with Aldy's and Thariq's pages. --- ## Documentation ### 1. Dashboard Page #### 1.1 dashboard.page.ts 1. Change router with navController. **(line 7)** 2. Import API service. **(line 8)** 3. Safe the device id into preference. **(line 71)** 4. Check email preference for login session. **(line 76)** 5. Modify all router methods with navCtrl. **(line 129-142)** 6. Aldy Updates the trackButton feature to login and parse the track status in the user database. **(line 148-162)** 7. Aldy adds checkLogin feature to check the login status of the user before activate trackButton feature or go to reportProblem page. **(line 195-240)** 8. Aldy adds checkSession feature that will be called everytime trackButton and report problem is called. **(line 242-281)** ```htmlmixed= import { StaticVariable } from './../../classes/StaticVariable/static-variable'; import { Component, OnInit } from '@angular/core'; import { HttpClient } from '@angular/common/http' import { HostListener } from "@angular/core"; import { DeviceDetectorService } from 'ngx-device-detector'; import { PreferenceManagerService } from '../../services/PreferenceManager/preference-manager.service'; import { NavController, AlertController } from '@ionic/angular'; import { DispenserAPIService } from 'src/app/services/DispenserAPI/dispenser-api.service'; @Component({ selector: 'app-dashboard', templateUrl: './dashboard.page.html', styleUrls: ['./dashboard.page.scss'], }) export class DashboardPage implements OnInit { private device_id: string; //variables for dispenser picture public url_dispenser_picture: string; //variables for device detector private isDesktopType: boolean; //variables for screen & item resolution public screenHeight: any; public screenWidth: any; public headerHeight: any; public contentHeight: any; public pageLeft: any; public jellyfishIconTop: any; public jellyfishIconLeft: any; //Variable for tracking progress public trackIsActive: boolean = false; public hasReportSubmitted: boolean = false; deviceInfo = null; constructor( private http:HttpClient, private deviceDetector: DeviceDetectorService, private pref: PreferenceManagerService, private navCtrl: NavController, private alertCtrl: AlertController, private api: DispenserAPIService) { } async ngOnInit() { this.detectDevice(); if(this.isDesktopType) this.adjustDynamicDesktopScreen(); else this.adjustDynamicMobileScreen(); // check if preference is not build yet await this.checkPrefFirstTime(); await this.setAPIsData(); ///////////////////////////////// // this is for testing only await this.pref.saveData(StaticVariable.KEY__DEVICE_ID, "MA_05_01"); // await this.pref.saveData(StaticVariable.KEY__SESSION_ID, "ntust.smartcampus@gmail.com"); //////////////////////////////// // get the device ID this.device_id = await this.pref.getData(StaticVariable.KEY__DEVICE_ID); // check if user has report something let email = await this.pref.getData(StaticVariable.KEY__SESSION_ID); if (email !== "" || email !== null || email !== undefined) { this.hasReportSubmitted = await this.api.checkAnyReportSubmitted(email, this.device_id); } } private detectDevice() { this.isDesktopType = this.deviceDetector.isDesktop(); } private getDesktopScreenSize(){ this.screenHeight = window.innerHeight; this.screenWidth = this.screenHeight/16 * 9; } private getMobileScreenSize(){ this.screenHeight = window.innerHeight; this.screenWidth = window.innerWidth; } private adjustScreen(){ if((!this.isDesktopType) && (window.innerHeight < window.innerWidth)){ this.headerHeight = this.screenHeight * 0.6; this.contentHeight = this.screenHeight * 0.4; }else{ this.headerHeight = this.screenHeight * 0.7; this.contentHeight = this.screenHeight * 0.3; } this.pageLeft = window.innerWidth/2 - this.screenWidth/2; this.jellyfishIconTop = this.headerHeight - 60; this.jellyfishIconLeft = this.screenWidth/2 - 60; } private adjustDynamicDesktopScreen(){ this.getDesktopScreenSize(); this.adjustScreen(); } private adjustDynamicMobileScreen() { this.getMobileScreenSize(); this.adjustScreen(); } @HostListener('window:resize', ['$event']) onresize() { if(this.isDesktopType) this.adjustDynamicDesktopScreen(); else this.adjustDynamicMobileScreen(); } /** * Methods for routing to another page */ goToDetailedInformation(){ this.navCtrl.navigateForward(['detailed-information']); } goToMaintenanceRecords(){ this.navCtrl.navigateForward(['maintenance-records']); } goToNearbyDispenser () { this.navCtrl.navigateForward(['nearby']); } goToMaintenanceProgress() { this.navCtrl.navigateForward(['mt-progress']); } /** * Methods for button status is on or off */ async trackButton(){ // check login first, return true if login is true if (await this.checkLogin()) { // act the active to if(!this.trackIsActive) this.trackIsActive = true; else this.trackIsActive = false; let email = await this.pref.getData(StaticVariable.KEY__SESSION_ID); await this.api.wantUpdateTrack(this.device_id, email, this.trackIsActive); } } async goToReportProblem(){ // check login first, return true if login is true if (await this.checkLogin()) { this.navCtrl.navigateForward(['report-problem']); } } /** * Check First Time Prefference */ async checkPrefFirstTime () { // in here check the first time when app opened let a = await this.pref.getData(StaticVariable.KEY__CHECK_PREF_CREATED); if (a === null || a === undefined) { // create some first await this.pref.saveData(StaticVariable.KEY__CHECK_PREF_CREATED, true); await this.pref.saveData(StaticVariable.KEY__LAST_DATE, new Date()); await this.pref.saveData(StaticVariable.KEY__LAST_PAGE, ""); await this.pref.saveData(StaticVariable.KEY__DEVICE_ID, ""); await this.pref.saveData(StaticVariable.KEY__SESSION_ID, ""); } } async setAPIsData(){ this.url_dispenser_picture = await this.api.getDispenserPictureUrlOnly(this.device_id); } async checkLogin () { // check if there any session ID let checkData = await this.checkSession(); let returnValue = false; // if the data is not present or empty if (!checkData) { // create alert to choose login or not let loginAlert = await this.alertCtrl.create({ mode: 'ios', header: 'Log In Required', message: 'You need to login first in order to report a problem or track dispenser status, please click the Log In button below.', buttons: [ { text: 'Cancel', role: 'cancel', handler: () => { console.log('Cancel clicked'); } }, { text: 'Log In', handler: () => { // direct the user to login page this.navCtrl.navigateForward(['login']); console.log('Log In clicked'); } } ] }); // display the alert controller loginAlert.present(); } else { // return true if login process is done returnValue = true; } return returnValue; } async checkSession() { // check session ID and date let nowDate = new Date(); let lastDate = new Date(await this.pref.getData(StaticVariable.KEY__LAST_DATE)); let difDate = nowDate.getTime() - lastDate.getTime(); // check if there any session ID let checkData = await this.pref.getData(StaticVariable.KEY__SESSION_ID); let currentPage = "dashboard"; // check in console // console.log(nowDate); // console.log(lastDate); // console.log(difDate); // console.log(await this.pref.getData(StaticVariable.KEY__SESSION_ID)); if (checkData === "" || checkData === null) { return false; } else if (difDate > StaticVariable.SESSION_TIMEOUT) { // remove the session ID from preference this.pref.removeData(StaticVariable.KEY__SESSION_ID); // save the name of page this.pref.saveData(StaticVariable.KEY__LAST_PAGE, currentPage); return false; } else if (!checkData && difDate <= StaticVariable.SESSION_TIMEOUT) { // save new Date this.pref.saveData(StaticVariable.KEY__LAST_DATE, nowDate); return true; } } } ``` #### 1.2 dashboard.page.html 1. Aldy adds function to go to nearby dispenser page in the nearby dispenser button. **(line 49)** 2. Aldy modify the report-status part to become adaptive when there is a report or not. **(line 57-62)** ```htmlmixed= <ion-header no-border [style.height.px]="headerHeight" [style.width.px]="screenWidth" [style.left.px]="pageLeft" position="absolute"> <div class="background-image" [ngStyle]="{'background-image': 'url(' + url_dispenser_picture + ')'}"> <div class="overlay"> <div class="logo"> <img src="assets/dashboard/acuo_logo.png"> </div> <!--More button for dropdown options--> <span class="dropdown" style="float: right;"> <button class="ripple dropbtn"> <ion-icon name="more" size="large"></ion-icon> <div class="dropdown-content"> <button class="more-button" (click)="goToMaintenanceRecords()">Maintenance records</button> <button class="more-button" (click)="goToDetailedInformation()">Detailed information</button> </div> </button> </span> <!--Star button for tracking feature--> <span> <button class="ripple header-button" (click)="trackButton()"> <ion-icon name="star" size="large" *ngIf="trackIsActive == true"></ion-icon> <ion-icon name="star-outline" size="large" *ngIf="trackIsActive == false"></ion-icon> </button> </span> <div class="jellyfish-icon" [style.top.px]="jellyfishIconTop" [style.left.px]="jellyfishIconLeft"> <img alt="avatar" src="assets/dashboard/jellyfishIcon.png"> </div> </div> </div> </ion-header> <ion-content [style.height.px]="contentHeight" [style.width.px]="screenWidth" [style.left.px]="pageLeft" position="absolute"> <div class="content-button-space"> <!--Report Dispenser button--> <span class="content-button"> <button class="ripple full-button" (click)="goToReportProblem()"> <ion-icon name="warning" size="large"></ion-icon> <p>Report dispenser</p> </button> </span> <!--Nearby Dispenser button--> <span class="content-button"> <button class="ripple full-button" (click)="goToNearbyDispenser()"> <ion-icon name="pin" size="large"></ion-icon> <p>Nearby dispenser</p> </button> </span> </div> <div class="report-status transparent" *ngIf="!hasReportSubmitted"> No Report Problem </div> <div class="report-status" *ngIf="hasReportSubmitted" (click)="goToMaintenanceProgress()"> View maintenance progress > </div> </ion-content> ``` #### 1.3 dashboard.page.scss 1. Aldy adds *.transparent* class. **(line 85-86)** ```htmlmixed= //======================= // Header Part CSS //======================= .background-image, .overlay{ height: 100%; width: 100%; } .background-image{ position: relative; background-repeat: no-repeat; background-size: cover; background-position: center center; } .overlay { z-index: 1; background-color: rgba($color: #000000, $alpha: 0.5); } .jellyfish-icon{ position: relative; height: 120px; width: 120px; border-radius: 50px; } .logo{ position: absolute; top: 20px; } .header-button{ position: relative; background-color: transparent; top: 20px; right: 20px; float: right; height:40px; width: 40px; color: white; } .logo { height: 50px; width: 90px; left: 33px; } //======================= // Content Part CSS //======================= .content-button-space{ position: relative; height:65%; width: 100%; } .content-button{ position: relative; top: 0px; left: 0px; float: left; height:100%; width: 50%; text-align: center; color: black; } .full-button{ position: relative; background-color: transparent; height: 100%; width: 100%; } .report-status{ position: relative; text-align: center; height: 35%; bottom: 0px; border-top: 1px solid #e9e9e9; padding: 30px; } .transparent { color: rgba($color: #000000, $alpha: 0.5) } //============================= // CSS properties Configuration //============================= /* Ripple effect */ .ripple { background-position: center; transition: background 0.8s; } .ripple:hover { background:transparent radial-gradient(circle, transparent 1%, white 1%) center/15000%; } .ripple:active { color: #D3D3D3; transition: background 0s; } //Pressed effect .pressed:active { transform: translateY(4px); } //button button{ outline: none; } //Dropdown button configuration .dropbtn { background-color: transparent; border: none; color: white; } .dropdown { top: 20px; right: 20px; position: relative; display: inline-block; } .dropdown-content { position: absolute; display: none; right: 0; border: none; background-color: #f9f9f9; min-width: 180px; box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2); z-index: 1; border-radius: 8px; } .dropdown-content .more-button { color: black; padding: 20px; top: 30%; height: 50px; text-decoration: none; display: block; border-bottom: black; text-align: center; } .more-button{ border-radius: 8px; background-color: white; width: 100%; } .dropdown-content .more-button:hover {background-color: #f1f1f1;} .dropdown:hover .dropdown-content { display: block; } ``` --- ### 2. Detailed Information Page #### 2.1 detailed-information.page.ts 1. Remove displayFahrenheit and displayCelsius variables. 2. Add isToggleActive boolean variable to store the value of the temperature toggle button. **(line 55-56)** 3. Add value rounding function to round the Fahrenheit values to be displayed in the temperature display. **(line 152-154)** 4. Create functions to change the toggle value and set the temperature value to be displayed is in Celsius or Fahrenheit. **(line 163-177)** ```htmlmixed= import { StaticVariable } from './../../classes/StaticVariable/static-variable'; import { Component, OnInit } from '@angular/core'; import { HttpClient } from '@angular/common/http' import { HostListener } from "@angular/core"; import { DeviceDetectorService } from 'ngx-device-detector'; import { PreferenceManagerService } from '../../services/PreferenceManager/preference-manager.service'; import { NavController, AlertController } from '@ionic/angular'; import { DispenserAPIService } from 'src/app/services/DispenserAPI/dispenser-api.service'; @Component({ selector: 'app-dashboard', templateUrl: './dashboard.page.html', styleUrls: ['./dashboard.page.scss'], }) export class DashboardPage implements OnInit { private device_id: string; //variables for dispenser picture public url_dispenser_picture: string; //variables for device detector private isDesktopType: boolean; //variables for screen & item resolution public screenHeight: any; public screenWidth: any; public headerHeight: any; public contentHeight: any; public pageLeft: any; public jellyfishIconTop: any; public jellyfishIconLeft: any; //Variable for tracking progress public trackIsActive: boolean = false; public hasReportSubmitted: boolean = false; deviceInfo = null; constructor( private http:HttpClient, private deviceDetector: DeviceDetectorService, private pref: PreferenceManagerService, private navCtrl: NavController, private alertCtrl: AlertController, private api: DispenserAPIService) { } async ngOnInit() { this.detectDevice(); if(this.isDesktopType) this.adjustDynamicDesktopScreen(); else this.adjustDynamicMobileScreen(); // check if preference is not build yet await this.checkPrefFirstTime(); await this.setAPIsData(); ///////////////////////////////// // this is for testing only await this.pref.saveData(StaticVariable.KEY__DEVICE_ID, "MA_05_01"); // await this.pref.saveData(StaticVariable.KEY__SESSION_ID, "ntust.smartcampus@gmail.com"); //////////////////////////////// // get the device ID this.device_id = await this.pref.getData(StaticVariable.KEY__DEVICE_ID); // check if user has report something let email = await this.pref.getData(StaticVariable.KEY__SESSION_ID); if (email !== "" || email !== null || email !== undefined) { this.hasReportSubmitted = await this.api.checkAnyReportSubmitted(email, this.device_id); } } private detectDevice() { this.isDesktopType = this.deviceDetector.isDesktop(); } private getDesktopScreenSize(){ this.screenHeight = window.innerHeight; this.screenWidth = this.screenHeight/16 * 9; } private getMobileScreenSize(){ this.screenHeight = window.innerHeight; this.screenWidth = window.innerWidth; } private adjustScreen(){ if((!this.isDesktopType) && (window.innerHeight < window.innerWidth)){ this.headerHeight = this.screenHeight * 0.6; this.contentHeight = this.screenHeight * 0.4; }else{ this.headerHeight = this.screenHeight * 0.7; this.contentHeight = this.screenHeight * 0.3; } this.pageLeft = window.innerWidth/2 - this.screenWidth/2; this.jellyfishIconTop = this.headerHeight - 60; this.jellyfishIconLeft = this.screenWidth/2 - 60; } private adjustDynamicDesktopScreen(){ this.getDesktopScreenSize(); this.adjustScreen(); } private adjustDynamicMobileScreen() { this.getMobileScreenSize(); this.adjustScreen(); } @HostListener('window:resize', ['$event']) onresize() { if(this.isDesktopType) this.adjustDynamicDesktopScreen(); else this.adjustDynamicMobileScreen(); } /** * Methods for routing to another page */ goToDetailedInformation(){ this.navCtrl.navigateForward(['detailed-information']); } goToMaintenanceRecords(){ this.navCtrl.navigateForward(['maintenance-records']); } goToNearbyDispenser () { this.navCtrl.navigateForward(['nearby']); } goToMaintenanceProgress() { this.navCtrl.navigateForward(['mt-progress']); } /** * Methods for button status is on or off */ async trackButton(){ // check login first, return true if login is true if (await this.checkLogin()) { // act the active to if(!this.trackIsActive) this.trackIsActive = true; else this.trackIsActive = false; let email = await this.pref.getData(StaticVariable.KEY__SESSION_ID); await this.api.wantUpdateTrack(this.device_id, email, this.trackIsActive); } } async goToReportProblem(){ // check login first, return true if login is true if (await this.checkLogin()) { this.navCtrl.navigateForward(['report-problem']); } } /** * Check First Time Prefference */ async checkPrefFirstTime () { // in here check the first time when app opened let a = await this.pref.getData(StaticVariable.KEY__CHECK_PREF_CREATED); if (a === null || a === undefined) { // create some first await this.pref.saveData(StaticVariable.KEY__CHECK_PREF_CREATED, true); await this.pref.saveData(StaticVariable.KEY__LAST_DATE, new Date()); await this.pref.saveData(StaticVariable.KEY__LAST_PAGE, ""); await this.pref.saveData(StaticVariable.KEY__DEVICE_ID, ""); await this.pref.saveData(StaticVariable.KEY__SESSION_ID, ""); } } async setAPIsData(){ this.url_dispenser_picture = await this.api.getDispenserPictureUrlOnly(this.device_id); } async checkLogin () { // check if there any session ID let checkData = await this.checkSession(); let returnValue = false; // if the data is not present or empty if (!checkData) { // create alert to choose login or not let loginAlert = await this.alertCtrl.create({ mode: 'ios', header: 'Log In Required', message: 'You need to login first in order to report a problem or track dispenser status, please click the Log In button below.', buttons: [ { text: 'Cancel', role: 'cancel', handler: () => { console.log('Cancel clicked'); } }, { text: 'Log In', handler: () => { // direct the user to login page this.navCtrl.navigateForward(['login']); console.log('Log In clicked'); } } ] }); // display the alert controller loginAlert.present(); } else { // return true if login process is done returnValue = true; } return returnValue; } async checkSession() { // check session ID and date let nowDate = new Date(); let lastDate = new Date(await this.pref.getData(StaticVariable.KEY__LAST_DATE)); let difDate = nowDate.getTime() - lastDate.getTime(); // check if there any session ID let checkData = await this.pref.getData(StaticVariable.KEY__SESSION_ID); let currentPage = "dashboard"; // check in console // console.log(nowDate); // console.log(lastDate); // console.log(difDate); // console.log(await this.pref.getData(StaticVariable.KEY__SESSION_ID)); if (checkData === "" || checkData === null) { return false; } else if (difDate > StaticVariable.SESSION_TIMEOUT) { // remove the session ID from preference this.pref.removeData(StaticVariable.KEY__SESSION_ID); // save the name of page this.pref.saveData(StaticVariable.KEY__LAST_PAGE, currentPage); return false; } else if (!checkData && difDate <= StaticVariable.SESSION_TIMEOUT) { // save new Date this.pref.saveData(StaticVariable.KEY__LAST_DATE, nowDate); return true; } } } ``` #### 2.2 detailed-information.page.html 1. Replaced the variable to be displayed with displayColdTemp. **(line 54)** 2. Replaced the variable to be displayed with displayWarmTemp. **(line 62)** 3. Replaced the variable to be displayed with displayHotTemp. **(line 70)** ```htmlmixed= <ion-header no-border [style.height.px]="headerHeight" [style.width.px]="screenWidth" [style.left.px]="pageLeft" position="absolute"> <div class="background-image" [ngStyle]="{'background-image': 'url(' + url_dispenser_picture + ')'}"> <div class="overlay"> <div class="logo"> <img src="assets/dashboard/acuo_logo.png"> </div> <!--More button for dropdown options--> <span class="dropdown" style="float: right;"> <button class="ripple dropbtn"> <ion-icon name="more" size="large"></ion-icon> <div class="dropdown-content"> <button class="more-button" (click)="goToMaintenanceRecords()">Maintenance records</button> <button class="more-button" (click)="goToDetailedInformation()">Detailed information</button> </div> </button> </span> <!--Star button for tracking feature--> <span> <button class="ripple header-button" (click)="trackButton()"> <ion-icon name="star" size="large" *ngIf="trackIsActive == true"></ion-icon> <ion-icon name="star-outline" size="large" *ngIf="trackIsActive == false"></ion-icon> </button> </span> <div class="jellyfish-icon" [style.top.px]="jellyfishIconTop" [style.left.px]="jellyfishIconLeft"> <img alt="avatar" src="assets/dashboard/jellyfishIcon.png"> </div> </div> </div> </ion-header> <ion-content [style.height.px]="contentHeight" [style.width.px]="screenWidth" [style.left.px]="pageLeft" position="absolute"> <div class="content-button-space"> <!--Report Dispenser button--> <span class="content-button"> <button class="ripple full-button" (click)="goToReportProblem()"> <ion-icon name="warning" size="large"></ion-icon> <p>Report dispenser</p> </button> </span> <!--Nearby Dispenser button--> <span class="content-button"> <button class="ripple full-button" (click)="goToNearbyDispenser()"> <ion-icon name="pin" size="large"></ion-icon> <p>Nearby dispenser</p> </button> </span> </div> <div class="report-status transparent" *ngIf="!hasReportSubmitted"> No Report Problem </div> <div class="report-status" *ngIf="hasReportSubmitted" (click)="goToMaintenanceProgress()"> View maintenance progress > </div> </ion-content> ``` #### 2.3 detailed-information.page.scss There isn't any change with the scss part. --- ## Result This is the result of "Detailed Information" final back end: ![](https://i.imgur.com/BwPBQnW.gif)