# <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:
