application skeleton

MOHEMM-Q3-DEV-LATEST
Sultan Khan 7 years ago
parent 62f2cfcda3
commit 48a4360ac1

@ -2,8 +2,11 @@ import { NgModule } from '@angular/core';
import { PreloadAllModules, RouterModule, Routes } from '@angular/router';
const routes: Routes = [
{ path: '', redirectTo: 'home', pathMatch: 'full' },
{ path: 'home', loadChildren: './home/home.module#HomePageModule' },
{ path: '', redirectTo: 'authentication/login', pathMatch: 'full' },
{
path: 'authentication', loadChildren: './authentication/authentication.module#AuthenticationPageModule',
data: { preload: true, delay: 1000 }
}
];
@NgModule({

@ -1,3 +1,83 @@
<ion-app>
<ion-router-outlet></ion-router-outlet>
</ion-app>
<!-- <ion-nav [root]="rootPage" #mycontent swipeBackEnabled="false"></ion-nav> -->
<ion-app [dir]="direction">
<ion-split-pane>
<!-- <ion-menu persistent="true" id="leftMenu" class="menu"
side="left" *ngIf="direction==='ltr'" >
<ion-content class="sidebar-menu">
<div class="header-div">
<div class="centerDiv">
<p class="TxtPlace">{{"home.hello" | translate}}, {{User_name_Emp}}</p>
<div> <img src="{{user_image}}" class="profileImg" ></div>
</div>
</div>
<ion-list>
<button class="menu-item" ion-item menuClose ion-item (click)="goToWorkListPage()" >
<img width="30" src="../assets/imgs/bell.png" item-left >
{{"home.worklist" | translate }}
<ion-badge item-end>{{notBadge}}</ion-badge>
</button>
<button class="menu-item" ion-item menuClose ion-item (click)="goToProfile()" >
<img width="30" src="../assets/imgs/username.png" item-left >
{{"userProfile.title" | translate }}
</button>
<button class="menu-item" ion-item menuClose ion-item (click)="logout()" >
<img width="30" src="../assets/imgs/signout.png" item-left >
{{"home.logout" | translate }}
</button>
</ion-list>
<div class="menuFooter">
<div> <img src="{{companyUrl}}" class="CompanyImg" ></div>
<p class="companyTxt">{{companyDesc}}</p>
</div>
</ion-content>
</ion-menu>
<ion-menu persistent="true" id="rightMenu" class="menu"
side="right" *ngIf="direction==='rtl'" >
<ion-content class="sidebar-menu">
<div class="header-div">
<div class="centerDiv">
<p class="TxtPlace">{{"home.hello" | translate}}, {{User_name_Emp}}</p>
<div> <img src="{{user_image}}" class="profileImg" ></div>
</div>
</div>
<ion-list>
<button class="menu-item" ion-item menuClose ion-item (click)="goToWorkListPage()" >
<img width="30" src="../assets/imgs/bell.png" item-left >
{{"home.worklist" | translate }}
<ion-badge item-end>{{notBadge}}</ion-badge>
</button>
<button class="menu-item" ion-item menuClose ion-item (click)="goToProfile()" >
<img width="30" src="../assets/imgs/username.png" item-left >
{{"userProfile.title" | translate }}
</button>
<button class="menu-item" ion-item menuClose ion-item (click)="logout()" >
<img width="30" src="../assets/imgs/signout.png" item-left >
{{"home.logout" | translate }}
</button>
</ion-list>
<div class="menuFooter">
<div> <img src="{{companyUrl}}" class="CompanyImg" ></div>
<p class="companyTxt">{{companyDesc}}</p>
</div>
</ion-content>
</ion-menu> -->
<ion-router-outlet main></ion-router-outlet>
</ion-split-pane>
</ion-app>

@ -1,26 +1,36 @@
import { Component } from '@angular/core';
import { Platform } from '@ionic/angular';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { Component, OnInit, ViewChild, AfterViewInit } from '@angular/core';
import { Platform, Events, MenuController } from '@ionic/angular';
import { StatusBar } from '@ionic-native/status-bar/ngx';
import { TranslatorService } from './hmg-common/services/translator/translator.service';
import { CommonService } from './hmg-common/services/common/common.service';
import { AuthenticationService } from './hmg-common/services/authentication/authentication.service';
import { AuthenticatedUser } from './hmg-common/services/authentication/models/authenticated-user';
import { TabsBarComponent } from './hmg-common/ui/tabs-bar/tabs-bar.component';
import { KeyboardService } from './hmg-common/services/keyboard/keyboard.service';
import { Router, RouteConfigLoadStart, RouteConfigLoadEnd, NavigationStart, NavigationEnd, NavigationCancel } from '@angular/router';
import { LazyLoadingService } from './hmg-common/services/lazy-loading/lazy-loading.service';
@Component({
selector: 'app-root',
templateUrl: 'app.component.html'
selector: 'app-root',
styleUrls: ['./app.component.scss'],
templateUrl: 'app.component.html'
})
export class AppComponent {
constructor(
private platform: Platform,
private splashScreen: SplashScreen,
private statusBar: StatusBar
) {
this.initializeApp();
}
export class AppComponent implements OnInit, AfterViewInit {
// rootPage:any = LoginPage;
// @ViewChild(Nav) nav: Nav;
menuList:any=[];
User_name_Emp:string="";
user_image:string="";
menuSide:string="left";
notBadge:number;
companyUrl:string="../assets/imgs/CS.png";
companyDesc:string="Powered By Cloud Solutions";
public direction = 'ltr';
ngOnInit(){
}
ngAfterViewInit(){
initializeApp() {
this.platform.ready().then(() => {
this.statusBar.styleDefault();
this.splashScreen.hide();
});
}
}
}

@ -1,18 +1,26 @@
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouteReuseStrategy } from '@angular/router';
import { HmgCommonModule } from './hmg-common/hmg-common.module';
import { IonicModule, IonicRouteStrategy } from '@ionic/angular';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { StatusBar } from '@ionic-native/status-bar/ngx';
import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
@NgModule({
declarations: [AppComponent],
entryComponents: [],
imports: [BrowserModule, IonicModule.forRoot(), AppRoutingModule],
imports: [
BrowserModule,
BrowserAnimationsModule,
IonicModule.forRoot({
hardwareBackButton: true
}),
AppRoutingModule,
HmgCommonModule
],
providers: [
StatusBar,
SplashScreen,

@ -0,0 +1,28 @@
<ion-header>
<ion-toolbar>
<nav-buttons [navigate]="false" (backClick)="onRejectClicked()" ></nav-buttons>
<ion-title>{{ 'general,usage-agreement' | translate}}</ion-title>
</ion-toolbar>
</ion-header>
<ion-content padding>
<scroll-content>
<ion-grid>
<ion-row *ngIf="agreementContent" class="ion-justify-content-center">
<ion-col [size]="11">
<div class="html-container" [innerHTML]="agreementContent | safeHtml"> </div>
</ion-col>
</ion-row>
</ion-grid>
<page-trailer [small]="true"></page-trailer>
</scroll-content>
<footer>
<ion-grid>
<ion-row class="ion-justify-content-center">
<ion-col [size]="10" [sizeLg]="8" [sizeXl]="6" no-padding>
<ion-button (click)="onAcceptClicked()" expand="block">{{ 'general,accept' | translate}}</ion-button>
</ion-col>
</ion-row>
</ion-grid>
</footer>
</ion-content>

@ -0,0 +1,9 @@
.agreement_area{
width: 100%;
height: 80%;
}
.html-container {
width: 96%;
padding: 2%;
}

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { AgreementComponent } from './agreement.component';
describe('AgreementComponent', () => {
let component: AgreementComponent;
let fixture: ComponentFixture<AgreementComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ AgreementComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(AgreementComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

@ -0,0 +1,76 @@
import { Component, OnInit } from '@angular/core';
import { TranslatorService } from 'src/app/hmg-common/services/translator/translator.service';
import { CommonService } from 'src/app/hmg-common/services/common/common.service';
import { AgreementService } from './service/agreement.service';
import { CheckUserAgreementResponse } from './service/models/check-user-agreement.response';
import { GetUserAgreementResponse } from './service/models/get-user-agreement.response';
import { AuthenticationService } from 'src/app/hmg-common/services/authentication/authentication.service';
@Component({
selector: 'app-agreement',
templateUrl: './agreement.component.html',
styleUrls: ['./agreement.component.scss']
})
export class AgreementComponent implements OnInit {
public agreementContent: string;
constructor(
public ts: TranslatorService,
public cs: CommonService,
public agreementService: AgreementService,
public auth: AuthenticationService
) { }
ngOnInit() {
this.checkUserAgreement();
}
checkUserAgreement() {
this.agreementService.checkUserAgreement(
() => {
this.checkUserAgreement();
}, this.ts.trPK('general', 'retry')).subscribe((result: CheckUserAgreementResponse) => {
if (this.cs.validResponse(result)) {
if (result.IsPatientAlreadyAgreed) {
this.auth.setUserAgreed(true);
this.cs.openHome();
} else {
this.getUserAgreement();
}
}
});
}
private getUserAgreement() {
this.agreementService.getAgreement(
() => {
this.getUserAgreement();
}, this.ts.trPK('general', 'retry')).subscribe((result: GetUserAgreementResponse) => {
if (this.cs.validResponse(result)) {
this.agreementContent = result.UserAgreementContent;
}
});
}
public onAcceptClicked() {
this.agreementService.addUserAgreement(
() => {
this.onAcceptClicked();
}, this.ts.trPK('general', 'retry')).subscribe((result: GetUserAgreementResponse) => {
if (this.cs.validResponse(result)) {
this.auth.setUserAgreed(true);
this.cs.openHome();
}
});
}
public onRejectClicked() {
this.auth.clearUser().subscribe(success => {
this.cs.openHome();
});
}
}

@ -0,0 +1,12 @@
import { TestBed } from '@angular/core/testing';
import { AgreementService } from './agreement.service';
describe('AgreementService', () => {
beforeEach(() => TestBed.configureTestingModule({}));
it('should be created', () => {
const service: AgreementService = TestBed.get(AgreementService);
expect(service).toBeTruthy();
});
});

@ -0,0 +1,53 @@
import { Injectable } from '@angular/core';
import { ConnectorService } from 'src/app/hmg-common/services/connector/connector.service';
import { CheckUserAgreementRequest } from './models/check-user-agreement.request';
import { AuthenticationService } from 'src/app/hmg-common/services/authentication/authentication.service';
import { Observable } from 'rxjs';
import { CheckUserAgreementResponse } from './models/check-user-agreement.response';
import { Request } from 'src/app/hmg-common/services/models/request';
import { GetUserAgreementResponse } from './models/get-user-agreement.response';
import { AddUserAgreementRequest } from './models/add-user-agreement.request';
@Injectable({
providedIn: 'root'
})
export class AgreementService {
public static checkAgreementURL = 'Services/Patients.svc/REST/CheckForUsageAgreement';
public static getAgreementURL = 'Services/Patients.svc/REST/GetUsageAgreementText';
public static addAgreementURL = 'Services/Patients.svc/REST/AddUsageAgreement';
constructor(
public con: ConnectorService,
public auth: AuthenticationService
) {
}
public checkUserAgreement(onError: any, errorLabel: string): Observable<CheckUserAgreementResponse> {
const request = new CheckUserAgreementRequest();
request.Region = 1;
this.auth.authenticateRequest(request);
request.TokenID = '';
return this.con.post(AgreementService.checkAgreementURL, request, onError, errorLabel);
}
public getAgreement(onError: any, errorLabel: string): Observable<GetUserAgreementResponse> {
const request = new Request();
this.auth.setPublicFields(request);
request.TokenID = '';
return this.con.post(AgreementService.getAgreementURL, request, onError, errorLabel);
}
public addUserAgreement(onError: any, errorLabel: string): Observable<GetUserAgreementResponse> {
const request = new AddUserAgreementRequest();
request.Region = 1;
this.auth.authenticateRequest(request);
request.TokenID = '';
return this.con.post(AgreementService.addAgreementURL, request, onError, errorLabel);
}
}

@ -0,0 +1,5 @@
import { Request } from 'src/app/hmg-common/services/models/request';
export class AddUserAgreementRequest extends Request {
Region: number; // 1
}

@ -0,0 +1,5 @@
import { Request } from 'src/app/hmg-common/services/models/request';
export class CheckUserAgreementRequest extends Request {
Region: number; // 1
}

@ -0,0 +1,5 @@
import { Response } from 'src/app/hmg-common/services/models/response';
export class CheckUserAgreementResponse extends Response {
IsPatientAlreadyAgreed: boolean;
}

@ -0,0 +1,5 @@
import { Response } from 'src/app/hmg-common/services/models/response';
export class GetUserAgreementResponse extends Response {
UserAgreementContent: string;
}

@ -0,0 +1,72 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { Routes, RouterModule } from '@angular/router';
import { IonicModule } from '@ionic/angular';
import { AuthenticationPage } from './authentication.page';
import { LoginComponent } from './login/login.component';
import { ForgotComponent } from './forgot/forgot.component';
import { HmgCommonModule } from '../hmg-common/hmg-common.module';
import { SelectButtonModule } from 'primeng/selectbutton';
import { AgreementComponent } from './agreement/agreement.component';
import { FingerprintAIO } from '@ionic-native/fingerprint-aio/ngx';
import { Device } from '@ionic-native/device/ngx';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { SearchableOptionsModule } from '../hmg-common/ui/searchable-select/searchable-options.module';
import { MobileNumberModule } from 'src/app/hmg-common/ui/mobile-number/mobile-number.module';
import { SmsdialogPageModule } from 'src/app/hmg-common/ui/smsdialog/smsdialog.module';
import { SmsPageModule } from 'src/app/hmg-common/ui/sms/sms.module';
const routes: Routes = [
{
path: '',
component: AuthenticationPage,
children: [
{
path: 'login',
component: LoginComponent
},
{
path: 'forgot',
component: ForgotComponent
},
{
path: 'agreement',
component: AgreementComponent
}
]
}
];
@NgModule({
imports: [
CommonModule,
FormsModule,
SmsdialogPageModule,
SmsPageModule,
IonicModule,
RouterModule.forChild(routes),
HmgCommonModule,
SearchableOptionsModule,
SelectButtonModule,
MobileNumberModule
],
declarations: [
AuthenticationPage,
LoginComponent,
ForgotComponent,
AgreementComponent,
],
providers:[
FingerprintAIO,
Device,
SplashScreen
]
})
export class AuthenticationPageModule { }

@ -0,0 +1,14 @@
<!--
<ion-content>
<ion-router-outlet></ion-router-outlet>
</ion-content>
<div class="hub">
<router-outlet></router-outlet>
</div>
-->
<ion-content>
<ion-router-outlet></ion-router-outlet>
</ion-content>

@ -0,0 +1,27 @@
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { AuthenticationPage } from './authentication.page';
describe('AuthenticationPage', () => {
let component: AuthenticationPage;
let fixture: ComponentFixture<AuthenticationPage>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ AuthenticationPage ],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(AuthenticationPage);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

@ -0,0 +1,15 @@
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-authentication',
templateUrl: './authentication.page.html',
styleUrls: ['./authentication.page.scss'],
})
export class AuthenticationPage implements OnInit {
constructor() { }
ngOnInit() {
}
}

@ -0,0 +1,37 @@
<ion-header>
<ion-toolbar>
<nav-buttons ></nav-buttons>
<ion-title>{{'login,forgot-id' | translate}}</ion-title>
</ion-toolbar>
</ion-header>
<ion-content padding>
<scroll-content>
<ion-grid>
<ion-row class="ion-justify-content-center">
<ion-col center [size]="11">
<p> {{ 'login,forgot-desc'| translate}}</p>
</ion-col>
</ion-row>
<!-- international mobile number-->
<ion-row class="ion-justify-content-center">
<ion-col [size]="11">
<international-mobile (changed)="countryCodeChanged($event)"></international-mobile>
</ion-col>
</ion-row>
</ion-grid>
<page-trailer [small]="true"></page-trailer>
</scroll-content>
<footer>
<ion-grid>
<ion-row class="ion-justify-content-center">
<ion-col [size]="10" [sizeLg]="8" [sizeXl]="6" no-padding>
<ion-button (click)="onForgot()" [disabled]="!isValidForm()" expand="block">
{{'general,submit' | translate}} </ion-button>
</ion-col>
</ion-row>
</ion-grid>
</footer>
</ion-content>

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ForgotComponent } from './forgot.component';
describe('ForgotComponent', () => {
let component: ForgotComponent;
let fixture: ComponentFixture<ForgotComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ForgotComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ForgotComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

@ -0,0 +1,115 @@
import { Component, OnInit, ViewChild, ChangeDetectorRef, OnDestroy } from '@angular/core';
import { CommonService } from 'src/app/hmg-common/services/common/common.service';
import { AuthenticationService } from 'src/app/hmg-common/services/authentication/authentication.service';
import { Router } from '@angular/router';
import { AlertController } from '@ionic/angular';
import { TranslatorService } from 'src/app/hmg-common/services/translator/translator.service';
import { CheckUserAuthenticationRequest } from 'src/app/hmg-common/services/authentication/models/check-user-auth.request';
import { CheckUserAuthenticationResponse } from 'src/app/hmg-common/services/authentication/models/check-user-auth.response';
import { CheckActivationCodeRequest } from 'src/app/hmg-common/services/authentication/models/check-activation-code.request';
import { SmsReaderService } from 'src/app/hmg-common/services/sms/sms-reader.service';
import { ForgotFileIDResponse } from '../../hmg-common/services/authentication/models/forgot-File-ID.response';
import { InternationalMobileComponent } from 'src/app/hmg-common/ui/mobile-number/international-mobile/international-mobile.component';
import { CountryCode } from 'src/app/hmg-common/ui/mobile-number/international-mobile/models/country-code.model';
@Component({
selector: 'app-forgot',
templateUrl: './forgot.component.html',
styleUrls: ['./forgot.component.scss']
})
export class ForgotComponent implements OnInit,OnDestroy {
public countryCode: CountryCode;
@ViewChild(InternationalMobileComponent) internationlMobile: InternationalMobileComponent;
constructor(
public cs: CommonService,
public authService: AuthenticationService,
public router: Router,
public alertController: AlertController,
public ts: TranslatorService,
public smsService: SmsReaderService,
public changeDetector: ChangeDetectorRef
) {
}
ngOnInit() {
}
ngOnDestroy(): void {
this.smsService.stopSMSMonitoring();
}
public onForgot() {
this.sendSMSForForgotPassword();
}
public countryCodeChanged(countryCode: CountryCode) {
this.countryCode = countryCode;
}
public isValidForm() {
return (this.countryCode && this.countryCode.isValid);
}
private checkUserResult: CheckUserAuthenticationResponse;
private sendSMSForForgotPassword() {
const request = new CheckUserAuthenticationRequest();
request.PatientMobileNumber = this.countryCode.number;
request.ZipCode = CountryCode.localCode(this.countryCode.code);
this.authService.sendSMSForForgotFileNumber(
request,
() => {
this.sendSMSForForgotPassword();
}, this.ts.trPK('general', 'ok')).subscribe((result: CheckUserAuthenticationResponse) => {
if (this.cs.validResponse(result)) {
this.checkUserResult = result;
if (result.isSMSSent) {
this.startReceivingSMS();
this.presentSMSPasswordDialog();
}
}
});
}
private startReceivingSMS() {
this.smsService.startSMSMonitoring((code) => {
this.cs.dismissSMSDialog().subscribe(cleared => {
this.checkActivationCode(code);
});
});
}
public presentSMSPasswordDialog() {
this.cs.presentSMSPasswordDialog(
(code: string) => {
this.checkActivationCode(code);
});
}
private checkActivationCode(readedCode?) {
const request = new CheckActivationCodeRequest();
request.LogInTokenID = this.checkUserResult.LogInTokenID;
request.PatientOutSA = this.checkUserResult.PatientOutSA ? 1 : 0;
request.PatientMobileNumber = this.countryCode.number;
request.ZipCode = CountryCode.localCode(this.countryCode.code);
request.activationCode = readedCode;
this.authService.forgotFileIdActivation(request,
() => {
this.presentSMSPasswordDialog();
}, this.ts.trPK('general', 'retry')).subscribe((result: ForgotFileIDResponse) => {
if (this.cs.validResponse(result)) {
this.smsService.stopSMSMonitoring();
this.cs.presentAlert(result.ReturnMessage);
}
});
}
}

@ -0,0 +1,47 @@
<ion-content padding>
<ion-grid class="customGrid">
<ion-row>
<ion-col class="colPad">
<ion-img class="centerDiv" src="../assets/imgs/CS.png"></ion-img>
</ion-col>
</ion-row>
<ion-row>
<ion-col>
<P class="pageTitle text-caps">{{'login,title' | translate}}</P>
</ion-col>
</ion-row>
</ion-grid>
<ion-item>
<img class="item-icon" src="assets/imgs/username.png" item-start />
<ion-label>{{'login,userName' | translate}}</ion-label>
<ion-input required type="text" [(ngModel)]="memberLogin.P_USER_NAME">
</ion-input>
</ion-item>
<ion-item>
<img class="item-icon" src="assets/imgs/password.png" item-start />
<ion-label>{{'login,password' | translate}}</ion-label>
<ion-input required type="password" [(ngModel)]="memberLogin.P_PASSWORD">
</ion-input>
</ion-item>
<div class="centerDiv signupDiv" *ngIf="isAppleStore==true">
<a (click)="signUp()">{{ts.trPK('login','signup')}}</a>
</div>
<div class="gridDiv">
<button class="gridBtn" ion-button (click)="changeLanguage(2)">English</button>
<button class="gridBtn arTxt" ion-button (click)="changeLanguage(1)">عربي</button>
</div>
<ion-footer>
<div class="centerDiv">
<button ion-button (click)="http_call()">{{ts.trPK('login','login')}}</button>
</div>
<br/>
<div class="centerDiv">
<a (click)="forgetPasswordPage()">{{ts.trPK('login','forgot-password')}}</a>
</div>
</ion-footer>
</ion-content>

@ -0,0 +1,77 @@
.signupDiv{
font-size: 14px;
}
.customGrid{
margin-bottom: 20px;
}
ion-item.item.item-block.item-md.item-input,
ion-item.item.item-block.item-ios.item-input{
padding: 0px;
margin-bottom: 10px;
}
ion-col.colPad.col {
padding-top: 20px;
}
ion-img{
width: 170px;
height: 170px;
background:var(--light);
}
.gridDiv{
width: 100%;
height: 40px;
margin-top: 20px;
// margin-bottom: 10px;
font-size: 14px;
// @include ltr(){
// padding-left: 16px;
// padding-right: 0;
// }
// @include rtl(){
// padding-right: 16px;
// padding-left: 0;
// // margin-bottom: 5px;
// }
button.gridBtn.button.button-md, button.gridBtn.button.button-ios, button.gridBtn.button.button{
font-family: var(--fontFamilyLightEN) !important;
min-width: auto;
// @include ltr(){
// float: left;
// border-radius: 2px 0px 0px 2px;
// font-family:$fontFamilyBoldEN !important;
// color:$customnavy;
// }
// @include rtl(){
// float: right;
// border-radius: 0px 2px 2px 0px ;
// color:$darkgray;
// }
margin: 0px;
padding: 0px;
border: 1px solid var(--cusgray);
box-shadow: none;
-webkit-box-shadow:none;
-moz-box-shadow: none;
background: var(--light);
width: 50%;
}
button.arTxt.button.button-md, button.arTxt.button.button-ios, button.arTxt.button.button{
// @include rtl(){
// float: right;
// color:$customnavy !important;
// font-family:$fontFamilyIOSAR !important;
// font-weight: bold;
// border-radius: 2px 0px 0px 2px !important;
// }
// @include ltr(){
// float: left;
// color:$darkgray !important;
// font-family: $fontFamilyIOSAR !important;
// border-radius: 0px 2px 2px 0px !important;
// }
}
}

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { LoginComponent } from './login.component';
describe('LoginComponent', () => {
let component: LoginComponent;
let fixture: ComponentFixture<LoginComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ LoginComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(LoginComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

@ -0,0 +1,476 @@
import { Component, OnInit, ViewChild, ChangeDetectorRef, NgZone, OnDestroy } from '@angular/core';
import { CommonService } from 'src/app/hmg-common/services/common/common.service';
import { AuthenticationService } from 'src/app/hmg-common/services/authentication/authentication.service';
import { Router } from '@angular/router';
import { AlertController } from '@ionic/angular';
import { TranslatorService } from 'src/app/hmg-common/services/translator/translator.service';
import { CheckUserAuthenticationRequest } from 'src/app/hmg-common/services/authentication/models/check-user-auth.request';
import { CheckUserAuthenticationResponse } from 'src/app/hmg-common/services/authentication/models/check-user-auth.response';
import { CheckActivationCodeRequest } from 'src/app/hmg-common/services/authentication/models/check-activation-code.request';
import { CheckActivationCodeResponse } from 'src/app/hmg-common/services/authentication/models/check-activation-code.response';
import { SmsReaderService } from 'src/app/hmg-common/services/sms/sms-reader.service';
import { AuthenticatedUser } from 'src/app/hmg-common/services/authentication/models/authenticated-user';
import { PATIENT_TYPE } from 'src/app/hmg-common/services/models/patient.type';
import { FingerprintAIO } from '@ionic-native/fingerprint-aio/ngx';
import { GetLoginInfoRequest } from 'src/app/hmg-common/services/authentication/models/get-login-info.request';
import { GetLoginInfoResponse } from 'src/app/hmg-common/services/authentication/models/get-login-info.response';
import { Device } from '@ionic-native/device/ngx';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { CountryCode } from 'src/app/hmg-common/ui/mobile-number/international-mobile/models/country-code.model';
import { SMSService } from 'src/app/hmg-common/ui/sms/service/smsservice';
@Component({
selector: 'login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.scss']
})
export class LoginComponent implements OnInit, OnDestroy {
appLang:number=1;
isExpired:boolean =false;
isSupportAr:boolean=false;
isAppleStore:boolean=false;
memberLogin: any = {};
constructor(
public cs: CommonService,
public authService: AuthenticationService,
public router: Router,
public alertController: AlertController,
public ts: TranslatorService,
public smsService: SmsReaderService,
private faio: FingerprintAIO,
public ngZone: NgZone,
public device: Device,
public splash: SplashScreen
) {
}
ngOnInit() {
//this.setIdPattern();
setTimeout(() => {
this.checkIfLoggedInBefore();
// this.splash.hide();
}, 100);
}
ngOnDestroy(): void {
this.backClicked();
}
private checkIfLoggedInBefore() {
this.cs.startLoading();
// check if user logged in before
this.authService.loadAuthenticatedUser().subscribe((user: AuthenticatedUser) => {
if (user) {
this.startBiometricLogin(user);
} else {
this.hideSplashScreen(true);
}
});
}
private hideSplashScreen(stopLoading = false) {
// this.splash.hide();
if (stopLoading) {
this.cs.stopLoading();
}
}
private startBiometricLogin(user: AuthenticatedUser) {
this.faio.isAvailable().then((options) => {
this.hideSplashScreen(true);
if (user.biometricEnabled) {
// ask if login with face or finger
this.cs.presentConfirmDialog(
this.ts.trPK('login', options),
() => this.presentBiometricDialog(user),
() => { }
);
} else {
// ask to enable biometric
this.getPermissionToActivateBiometric(user);
}
}, () => {
this.hideSplashScreen(true);
});
}
private getPermissionToActivateBiometric(user: AuthenticatedUser) {
this.cs.presentConfirmDialog(
this.ts.trPK('login', 'enable-biometric'),
() => {
user['biometricEnabled'] = true;
this.authService.updateLoggedInUser(user).subscribe((success: boolean) => {
this.presentBiometricDialog(user);
});
},
() => { }
);
}
/*
activate biometric login for this user
*/
private getMobileInfo(user: AuthenticatedUser) {
this.authService.getLoginInfo(new GetLoginInfoRequest(user), () => {
}, this.ts.trPK('general', 'ok')).subscribe((result: GetLoginInfoResponse) => {
if (this.cs.validResponse(result)) {
if (!result.SMSLoginRequired) {
this.loginTokenID = result.LogInTokenID;
this.patientOutSA = result.PatientOutSA;
this.initializeForAuthentictedUser(user);
// sms for register the biometric
if (result.isSMSSent) {
this.startListeneingForSMS(this.ts.trPK('general', 'enter-sms-enable-biometric'));
} else {
this.checkActivationCode();
}
}
}
});
}
private initializeForAuthentictedUser(user: AuthenticatedUser) {
this.ngZone.run(() => {
this.isMobileFingerPrint = true;
this.FingerPrintPatientIdentificationID = user.IdentificationNo;
this.mobileNumber = user.MobileNumber;
this.zipCode = CountryCode.localCode(user.ZipCode);
});
}
private presentBiometricDialog(user) {
this.faio.show({
clientId: 'Fingerprint Authetnciation',
clientSecret: 'Ate343_9347lajF', // Only necessary for Android
disableBackup: true, // Only for Android(optional)
localizedFallbackTitle: this.ts.trPK('login', 'use-pin'), // Only for iOS
localizedReason: this.ts.trPK('login', 'auth-please') // Only for iOS
}).then((result: any) => {
// this.checkActivationCode();
this.getMobileInfo(user);
}).catch((error: any) => console.log(error));
}
/**
we need holders here since the country code maybe is not loaded yet for automatic login
*/
private mobileNumber: string;
private zipCode: string;
public onLogin() {
this.checkUserAuthentication();
}
public loginWithMyAccount() {
// this.loginWithTamer();
this.loginWithTamer();
}
/*
TODO to be removed later
*/
public loginWithEnas() {
alert('you are doing slient login width enas account ');
const user = new AuthenticatedUser();
user.PatientID = 862616;
user.PatientTypeID = PATIENT_TYPE.PERMANENT;
user.PatientOutSA = false;
user.TokenID = '@dm!n';
user.ProjectID = 0;
user.NationalityID = '2300948375';
user.MobileNo = user.MobileNumber = '554355126';
user.ZipCode = '+966';
user.Address = 'riyadh';
user.FirstName = 'MOHAMED';
user.MiddleName = 'yaghi';
user.LastName = 'mohammed';
user.Age = 30;
user.agreed = true;
const birthDate = new Date();
birthDate.setFullYear(birthDate.getFullYear() - 29);
user.DateofBirth = this.cs.convertISODateToJsonDate(this.cs.getDateISO(birthDate));
user.Email = 'Mohamed.Afifi@cloudsolution-sa.com';
user.PatientName = 'enas yaghi';
this.authService.updateLoggedInUser(user).subscribe(done => {
this.authService.startIdleMonitoring();
this.cs.openHome();
});
}
public loginWithVaccineUser() {
alert('you are doing slient login width vaccine account ');
const user = new AuthenticatedUser();
user.PatientID = 862616; // user with vaccines in dev
user.PatientTypeID = PATIENT_TYPE.PERMANENT;
user.PatientOutSA = false;
user.TokenID = '@dm!n';
user.NationalityID = '2300948375';
user.MobileNo = user.MobileNumber = '554355126';
user.ProjectID = 0;
user.ZipCode = '+966';
user.Address = 'riyadh';
user.FirstName = 'MOHAMED';
user.MiddleName = 'yaghi';
user.LastName = 'mohammed';
user.Age = 30;
user.agreed = true;
const birthDate = new Date();
birthDate.setFullYear(birthDate.getFullYear() - 29);
user.DateofBirth = this.cs.convertISODateToJsonDate(this.cs.getDateISO(birthDate));
user.Email = 'minna.barry@cloudsolution-sa.com';
user.PatientName = 'enas yaghi';
this.authService.updateLoggedInUser(user).subscribe(done => {
this.authService.startIdleMonitoring();
this.cs.openHome();
});
}
public loginWithEyeMeasureUser() {
alert('you are doing slient login width eye measurements user account ');
const user = new AuthenticatedUser();
user.PatientID = 873010;
user.PatientTypeID = PATIENT_TYPE.PERMANENT;
user.PatientOutSA = false;
user.TokenID = '@dm!n';
user.NationalityID = '2302581828';
user.ProjectID = 0;
user.MobileNo = user.MobileNumber = '555333541';
user.ZipCode = '+966';
user.Address = 'riyadh';
user.FirstName = 'eye';
user.MiddleName = 'user';
user.LastName = 'measurment';
user.Age = 30;
user.agreed = true;
const birthDate = new Date();
birthDate.setFullYear(birthDate.getFullYear() - 29);
user.DateofBirth = this.cs.convertISODateToJsonDate(this.cs.getDateISO(birthDate));
user.Email = 'sultan.khan@hmg.local';
user.PatientName = 'eye user';
this.authService.updateLoggedInUser(user).subscribe(done => {
this.authService.startIdleMonitoring();
this.cs.openHome();
});
}
/*
TODO login with mr rwaid
*/
public loginWithRwaid() {
alert('you are doing slient login width mr: rwaid account');
const user = new AuthenticatedUser();
// tamer with eye measurments 1231755
user.PatientID = 1018977;
user.PatientTypeID = PATIENT_TYPE.PERMANENT;
user.ProjectID = 0;
user.PatientOutSA = false;
user.TokenID = '@dm!n';
user.NationalityID = '1001242559';
user.MobileNo = user.MobileNumber = '545156035';
user.ZipCode = '+966';
user.Address = 'riyadh';
user.FirstName = 'rwaid';
user.MiddleName = 'el mallah';
user.LastName = 'mohammed';
user.Age = 30;
user.agreed = true;
const birthDate = new Date();
birthDate.setFullYear(birthDate.getFullYear() - 29);
user.DateofBirth = this.cs.convertISODateToJsonDate(this.cs.getDateISO(birthDate));
user.Email = 'mohamed.afifi@cloudsolution-sa.com';
user.PatientName = 'rwaid al mallah';
this.authService.updateLoggedInUser(user).subscribe(done => {
this.authService.startIdleMonitoring();
this.cs.openHome();
});
}
public loginWithTamer() {
alert('you are doing slient login width tamer account');
const user = new AuthenticatedUser();
user.PatientID = 1231755;
user.PatientTypeID = PATIENT_TYPE.PERMANENT;
user.ProjectID = 0;
user.PatientOutSA = false;
user.TokenID = '@dm!n';
user.NationalityID = '1001242559';
user.MobileNo = user.MobileNumber = '537503378';
user.ZipCode = '+966';
user.Address = 'riyadh';
user.FirstName = 'tamer';
user.MiddleName = 'faneshah';
user.LastName = 'faneshah';
user.Age = 30;
user.agreed = true;
const birthDate = new Date();
birthDate.setFullYear(birthDate.getFullYear() - 29);
user.DateofBirth = this.cs.convertISODateToJsonDate(this.cs.getDateISO(birthDate));
user.Email = 'mohamed.afifi@cloudsolution-sa.com';
user.PatientName = 'tamer fneshah';
this.authService.updateLoggedInUser(user).subscribe(done => {
this.authService.startIdleMonitoring();
this.cs.openHome();
});
}
private startListeneingForSMS(title?: string) {
this.startReceivingSMS();
//this.presentSMSPasswordDialog(title);
}
private checkUserAuthentication() {
const request = new CheckUserAuthenticationRequest();
request.PatientMobileNumber = this.mobileNumber;
request.ZipCode = this.zipCode;
request.isRegister = false;
request.TokenID = '';
this.authService.checkUserAuthentication(
request,
() => {
}, this.ts.trPK('general', 'ok')).subscribe((result: CheckUserAuthenticationResponse) => {
if (this.cs.validResponse(result)) {
this.loginTokenID = result.LogInTokenID;
this.patientOutSA = result.PatientOutSA;
this.isMobileFingerPrint = false;
this.FingerPrintPatientIdentificationID = '';
if (result.isSMSSent) {
this.startListeneingForSMS();
} else {
this.smsService.stopSMSMonitoring();
this.checkActivationCode();
}
}
});
}
public backClicked() {
this.smsService.stopSMSMonitoring();
}
private startReceivingSMS() {
// this.smsModal.presentModal();
// this.smsService.startSMSMonitoring((code) => {
// this.smsModal.dismiss;
// this.global_code = code;
// SMSService.code = this.global_code;
// this.checkActivationCode(code);
// this.cs.dismissSMSDialog().subscribe(cleared => {
// this.checkActivationCode(code);
// });
// });
}
public presentSMSPasswordDialog(title?: string) {
this.cs.presentSMSPasswordDialog(
(code: string) => {
this.checkActivationCode(code);
}, null, title);
}
private patientOutSA: boolean;
private loginTokenID: string;
private isMobileFingerPrint: boolean;
private FingerPrintPatientIdentificationID: string;
private checkActivationCode(readedCode?) {
const request = new CheckActivationCodeRequest();
request.IsMobileFingerPrint = this.isMobileFingerPrint;
request.FingerPrintPatientIdentificationID = this.FingerPrintPatientIdentificationID;
request.LogInTokenID = this.loginTokenID;
request.PatientOutSA = this.patientOutSA ? 1 : 0;
request.activationCode = readedCode || '0000';
request.IsSilentLogin = !readedCode;
request.PatientMobileNumber = this.mobileNumber;
request.ZipCode = this.zipCode;
// request.SearchType = this.loginType;
// if (this.loginType === LoginComponent.IDENTIFCIATION_LOGIN_TYPE) {
// request.PatientIdentificationID = this.id;
// request.PatientID = 0;
// } else {
// request.PatientID = Number(this.id);
// request.PatientIdentificationID = '';
// }
request.isRegister = false;
// this.authService.checkActivationCode(
// request,
// () => {
// //this.presentSMSPasswordDialog();
// this.smsModal.presentModal();
// }, this.ts.trPK('general', 'retry')).subscribe((result: CheckActivationCodeResponse) => {
// if (this.cs.validResponse(result)) {
// if (this.cs.hasData(result.List)) {
// this.smsService.stopSMSMonitoring();
// this.checkIfUserAgreedBefore(result);
// }
// }
// });
}
private checkIfUserAgreedBefore(result: CheckActivationCodeResponse) {
this.authService.setAuthenticatedUser(result).subscribe(() => {
if (this.authService.isAgreedBefore()) {
this.cs.openHome();
} else {
this.cs.openAgreement();
}
});
}
private checkUserAgreement() {
}
public signOut() {
// this.cs.presentConfirmDialog(this.ts.trPK('login', 'sign-out'),
// () => {
// this.authService.clearUser().subscribe(success => {
// this.id = null;
// if (this.countryCode) {
// this.internationlMobile.setMobileNumber(this.countryCode.code, null);
// }
// });
// });
}
public openForgotID() {
this.cs.openUserForgot();
}
public onDismiss()
{
// this.global_code = SMSService.code;
//this.checkActivationCode(this.global_code);
}
public onCancelled()
{
console.log("Modal pop up cancelled");
}
}

@ -0,0 +1,39 @@
import { RouteReuseStrategy, DetachedRouteHandle, ActivatedRouteSnapshot } from '@angular/router';
/*
default is to resuse except for one with destroy
*/
export class CustomReuseStrategy implements RouteReuseStrategy {
handlers: { [key: string]: DetachedRouteHandle } = {};
shouldDetach(route: ActivatedRouteSnapshot): boolean {
console.log('CustomReuseStrategy:shouldDetach', route);
return true;
}
store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void {
console.log('CustomReuseStrategy:store', route, handle);
this.handlers[route.routeConfig.path] = handle;
}
shouldAttach(route: ActivatedRouteSnapshot): boolean {
console.log('CustomReuseStrategy:shouldAttach', route);
return !!route.routeConfig && !!this.handlers[route.routeConfig.path];
}
retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle {
console.log('CustomReuseStrategy:retrieve', route);
if (!route.routeConfig) {
return null;
}
return this.handlers[route.routeConfig.path];
}
shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
console.log('CustomReuseStrategy:shouldReuseRoute', future, curr);
return future.routeConfig === curr.routeConfig;
}
}

@ -0,0 +1,13 @@
import { HmgCommonModule } from './hmg-common.module';
describe('HmgCommonModule', () => {
let hmgCommonModule: HmgCommonModule;
beforeEach(() => {
hmgCommonModule = new HmgCommonModule();
});
it('should create an instance', () => {
expect(hmgCommonModule).toBeTruthy();
});
});

@ -0,0 +1,248 @@
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';
import { Globalization } from '@ionic-native/globalization/ngx';
import { NumberRangeComponent } from './ui/number-range/number-range.component';
import { IonicModule } from '@ionic/angular';
import { CommonModule } from '@angular/common';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { SSpacerComponent } from './ui/spacer/s-spacer/s-spacer.component';
import { MSpacerComponent } from './ui/spacer/m-spacer/m-spacer.component';
import { LSpacerComponent } from './ui/spacer/l-spacer/l-spacer.component';
import { ImagesSliderComponent } from './ui/images-slider/images-slider.component';
import { InfoDialogComponent } from './ui/info-dialog/info-dialog.component';
import { SelectComponent } from './ui/select/select.component';
import { ConnectorService } from './services/connector/connector.service';
import { TranslatorService } from './services/translator/translator.service';
import { FaceAvatarComponent } from './ui/face-avatar/face-avatar.component';
import { DividerComponent } from './ui/divider/divider.component';
import { NavButtonsComponent } from './ui/nav-buttons/nav-buttons.component';
import { SharedDataService } from './services/shared-data-service/shared-data.service';
import { TranslatePipe } from './pipes/translate/translate.pipe';
import { DatePipeTransform } from './pipes/date/date.pipe';
import { AlertControllerService } from './ui/alert/alert-controller.service';
import { DateTimePipe } from './pipes/date-time/date-time.pipe';
import { ThemeableBrowser } from '@ionic-native/themeable-browser/ngx';
import { LaunchNavigator } from '@ionic-native/launch-navigator/ngx';
import { SafeHtmlPipe } from './pipes/safe-html/safe-html.pipe';
import { BackButtonComponent } from './ui/back-button/back-button.component';
import { IfDatePipe } from './pipes/date/if-date.pipe';
import { DynamicTableComponent } from './ui/dynamic-table/dynamic-table.component';
import { EmptyFieldPipe } from './pipes/empty-field/empty-field.pipe';
import { TimePipe } from './pipes/time/time.pipe';
import { KeysPipe } from './pipes/keys/keys.pipe';
import { SegmentContentComponent } from './ui/segment-content/segment-content.component';
import { GraphComponent } from './ui/graph/graph.component';
import { NgxChartsModule } from '@swimlane/ngx-charts';
import { ExpandableComponent } from './ui/expandable/expandable.component';
import { ProjectsService } from './services/projects/projects.service';
import { NationalityService } from './services/nationality/nationality.service';
import { FileUploaderComponent } from './ui/file-uploader/file-uploader.component';
import { Device } from '@ionic-native/device/ngx';
import { NativeStorage } from '@ionic-native/native-storage/ngx';
import { ProgressLoadingService } from './ui/progressLoading/progress-loading.service';
import { BarChartComponent } from './ui/bar-chart/bar-chart.component';
import { DonutChartComponent } from './ui/donut-chart/donut-chart.component';
import { UserLocalNotificationService } from './services/user-local-notification/user-local-notification.service';
import { LocalNotifications } from '@ionic-native/local-notifications/ngx';
import { EmailComponent } from './ui/email/email.component';
import { Badge } from '@ionic-native/badge/ngx';
import { Push } from '@ionic-native/push/ngx';
import { PushService } from './services/push/push.service';
import { LifeCycleService } from './services/life-cycle/life-cycle.service';
import { HmgBrowserService } from './services/hmg-browser/hmg-browser.service';
import { GuidService } from './services/guid/guid.service';
import { TabsBarComponent } from './ui/tabs-bar/tabs-bar.component';
import { PageTrailerComponent } from './ui/spacer/page-trailer/page-trailer.component';
import { GeofencingService } from './services/geofencing/geofencing.service';
import { BackgroundGeolocation } from '@ionic-native/background-geolocation/ngx';
import { ButtonComponent } from './ui/button/button.component';
import { ToolbarButtonComponent } from './ui/toolbar-button/toolbar-button.component';
import { ListboxModule } from 'primeng/listbox';
import { GenderSelectComponent } from './ui/gender-select/gender-select.component';
import { DateSelectComponent } from './ui/date-select/date-select.component';
import { ToggleButtonComponent } from './ui/toggle-button/toggle-button.component';
import { Footer } from 'primeng/components/common/shared';
import { FooterComponent } from './ui/footer/footer.component';
import { ScrollContentComponent } from './ui/scroll-content/scroll-content.component';
import { ScrollSegmentContentComponent } from './ui/scroll-segment-content/scroll-segment-content.component';
import { Keyboard } from '@ionic-native/keyboard/ngx';
import { KeyboardService } from './services/keyboard/keyboard.service';
import { DevicePermissionsService } from './services/device-permissions/device-permissions.service';
import { SegmentsComponent } from './ui/segments/segments.component';
import { BarcodeScanner } from '@ionic-native/barcode-scanner/ngx';
import { AccordionComponent } from './ui/accordion/accordion.component';
import { AccordionTabComponent } from './ui/accordion/accordion-tab/accordion-tab.component';
import { TwoOptionSelectComponent } from './ui/two-option-select/two-option-select.component';
import { HMGPreloadingStrategyLoading } from './services/preloading-strategy/hmg-preloading-strategy-loading';
import { HMGPreloadingStrategy } from './services/preloading-strategy/hmg-preloading-strategy.1';
import { LazyLoadingService } from './services/lazy-loading/lazy-loading.service';
import { RefresherComponent } from './ui/refresher/refresher.component';
import { SendEmailComponent } from './ui/send-email/send-email.component';
import { EmptyDataComponent } from './ui/empty-data/empty-data.component';
import { Diagnostic } from '@ionic-native/diagnostic/ngx';
import { DetailButtonComponent } from './ui/detail-button/detail-button.component';
import { RouterModule } from '@angular/router';
import { HeaderButtonComponent } from './ui/header-button/header-button.component';
import { CallNumber } from '@ionic-native/call-number/ngx';
import { AppRate } from '@ionic-native/app-rate/ngx';
import { RatingService } from './services/rating/rating.service';
import { InAppBrowser } from '@ionic-native/in-app-browser/ngx';
import { RateService } from './services/rate/rate.service';
import { PaymentComponent } from './ui/payment/payment.component';
import { PaymentService } from './ui/payment/service/payment.service';
@NgModule({
imports: [
CommonModule,
FormsModule,
RouterModule,
IonicModule,
HttpClientModule,
NgxChartsModule,
ListboxModule
],
declarations: [
NumberRangeComponent,
SSpacerComponent,
MSpacerComponent,
LSpacerComponent,
ImagesSliderComponent,
InfoDialogComponent,
SelectComponent,
FaceAvatarComponent,
DividerComponent,
NavButtonsComponent,
TranslatePipe,
DatePipeTransform,
DateTimePipe,
SafeHtmlPipe,
BackButtonComponent,
IfDatePipe,
DynamicTableComponent,
EmptyFieldPipe,
TimePipe,
KeysPipe,
SegmentContentComponent,
GraphComponent,
ExpandableComponent,
FileUploaderComponent,
BarChartComponent,
DonutChartComponent,
EmailComponent,
TabsBarComponent,
PageTrailerComponent,
ButtonComponent,
ToolbarButtonComponent,
GenderSelectComponent,
DateSelectComponent,
ToggleButtonComponent,
ScrollContentComponent,
FooterComponent,
ScrollSegmentContentComponent,
SegmentsComponent,
SegmentsComponent,
AccordionComponent,
AccordionTabComponent,
TwoOptionSelectComponent,
RefresherComponent,
SendEmailComponent,
EmptyDataComponent,
DetailButtonComponent,
HeaderButtonComponent,
PaymentComponent
],
exports: [
NumberRangeComponent,
SSpacerComponent,
MSpacerComponent,
LSpacerComponent,
ImagesSliderComponent,
InfoDialogComponent,
SelectComponent,
FaceAvatarComponent,
DividerComponent,
NavButtonsComponent,
DatePipeTransform,
TranslatePipe,
DateTimePipe,
SafeHtmlPipe,
IfDatePipe,
DynamicTableComponent,
EmptyFieldPipe,
TimePipe,
KeysPipe,
SegmentContentComponent,
GraphComponent,
FileUploaderComponent,
BarChartComponent,
DonutChartComponent,
EmailComponent,
TabsBarComponent,
PageTrailerComponent,
ButtonComponent,
ToolbarButtonComponent,
GenderSelectComponent,
DateSelectComponent,
ToggleButtonComponent,
ScrollContentComponent,
FooterComponent,
ScrollSegmentContentComponent,
SegmentsComponent,
AccordionComponent,
AccordionTabComponent,
TwoOptionSelectComponent,
RefresherComponent,
SendEmailComponent,
EmptyDataComponent,
DetailButtonComponent,
HeaderButtonComponent,
PaymentComponent
],
providers: [
ConnectorService,
TranslatorService,
Globalization,
SharedDataService,
AlertControllerService,
ThemeableBrowser,
LaunchNavigator,
ProjectsService,
NationalityService,
Device,
NativeStorage,
ProgressLoadingService,
PushService,
UserLocalNotificationService,
LocalNotifications,
Badge,
Push,
LifeCycleService,
HmgBrowserService,
GuidService,
BackgroundGeolocation,
GeofencingService,
Keyboard,
KeyboardService,
Diagnostic,
DevicePermissionsService,
BarcodeScanner,
LazyLoadingService,
HMGPreloadingStrategy,
HMGPreloadingStrategyLoading,
Diagnostic,
CallNumber,
AppRate,
RatingService,
InAppBrowser,
RateService,
PaymentService
]
})
export class HmgCommonModule { }

@ -0,0 +1,8 @@
import { DateTimePipe } from './date-time.pipe';
describe('DateTimePipe', () => {
it('create an instance', () => {
const pipe = new DateTimePipe();
expect(pipe).toBeTruthy();
});
});

@ -0,0 +1,26 @@
import { Pipe, PipeTransform } from '@angular/core';
import { CommonService } from '../../services/common/common.service';
@Pipe({
name: 'dateTime'
})
export class DateTimePipe implements PipeTransform {
constructor(
public cs: CommonService
) {
}
transform(value: any, args?: any): any {
if (value) {
return this.cs.evaluteDate(value, true);
}
return null;
}
public evaluteDate(dateStr: string): string {
const utc = parseInt(dateStr.substring(6, dateStr.length - 2), 10);
const appoDate = new Date(utc);
return appoDate.toLocaleString();
}
}

@ -0,0 +1,8 @@
import { DatePipe } from './date.pipe';
describe('DatePipe', () => {
it('create an instance', () => {
const pipe = new DatePipe();
expect(pipe).toBeTruthy();
});
});

@ -0,0 +1,26 @@
import { Pipe, PipeTransform } from '@angular/core';
import { CommonService } from '../../services/common/common.service';
import { DatePipe } from '@angular/common';
@Pipe({
name: 'date'
})
export class DatePipeTransform implements PipeTransform {
constructor(
public cs: CommonService
) {
}
transform(value: any, args?: any): any {
if (value) {
return this.cs.evaluteDate(value);
// return super.transform(value, 'dd/MMM/yyyy');
}
return null;
}
}

@ -0,0 +1,8 @@
import { IfDatePipe } from './if-date.pipe';
describe('IfDatePipe', () => {
it('create an instance', () => {
const pipe = new IfDatePipe();
expect(pipe).toBeTruthy();
});
});

@ -0,0 +1,30 @@
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'ifDate'
})
export class IfDatePipe implements PipeTransform {
transform(value: any, args?: any): any {
if (value) {
if (typeof value === 'string') {
return this.evaluteDate(value);
}
}
return value;
}
public evaluteDate(str: string): string {
const isDate = str.substring(1, 5);
if (isDate && (isDate.toLocaleLowerCase() === 'date')) {
const utc = parseInt(str.substring(6, str.length - 2), 10);
const appoDate = new Date(utc);
return appoDate.toLocaleDateString();
} else {
return str;
}
}
}

@ -0,0 +1,8 @@
import { EmptyFieldPipe } from './empty-field.pipe';
describe('EmptyFieldPipe', () => {
it('create an instance', () => {
const pipe = new EmptyFieldPipe();
expect(pipe).toBeTruthy();
});
});

@ -0,0 +1,12 @@
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'emptyField'
})
export class EmptyFieldPipe implements PipeTransform {
transform(value: any, args?: any): any {
return value ? value : '-';
}
}

@ -0,0 +1,8 @@
import { KeysPipe } from './keys.pipe';
describe('KeysPipe', () => {
it('create an instance', () => {
const pipe = new KeysPipe();
expect(pipe).toBeTruthy();
});
});

@ -0,0 +1,19 @@
import { Pipe, PipeTransform } from '@angular/core';
import { CommonService } from '../../services/common/common.service';
@Pipe({
name: 'keys'
})
export class KeysPipe implements PipeTransform {
constructor(
public cs: CommonService
) {
}
transform(obj: any, args?: any): any[] {
return this.cs.keysInObject(obj);
}
}

@ -0,0 +1,8 @@
import { SafeHtmlPipe } from './safe-html.pipe';
describe('SafeHtmlPipe', () => {
it('create an instance', () => {
const pipe = new SafeHtmlPipe();
expect(pipe).toBeTruthy();
});
});

@ -0,0 +1,20 @@
import { Pipe, PipeTransform } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
@Pipe({
name: 'safeHtml'
})
export class SafeHtmlPipe implements PipeTransform {
constructor(private sanitizer: DomSanitizer) { }
transform(html, sanitize: any = true) {
if (sanitize) {
html = html.replace(new RegExp('\n', 'g'), '<br>');
return this.sanitizer.bypassSecurityTrustHtml(html);
} else {
return html.replace(new RegExp('\n', 'g'), '<br>');
}
}
}

@ -0,0 +1,8 @@
import { TimePipe } from './time.pipe';
describe('TimePipe', () => {
it('create an instance', () => {
const pipe = new TimePipe();
expect(pipe).toBeTruthy();
});
});

@ -0,0 +1,24 @@
import { Pipe, PipeTransform } from "@angular/core";
import { CommonService } from "../../services/common/common.service";
@Pipe({
name: "time"
})
export class TimePipe implements PipeTransform {
constructor(public cs: CommonService) { }
transform(value: any): any {
if (value) {
const dateTime = this.cs.evaluteDateAsObject(value);
return this.cs.localizeTime(dateTime);
// return this.evaluteTime(value);
}
return null;
}
public evaluteTime(dateStr: string): string {
const utc = parseInt(dateStr.substring(6, dateStr.length - 2), 10);
const appoDate = new Date(utc);
return appoDate.toLocaleTimeString();
}
}

@ -0,0 +1,8 @@
import { TranslatePipe } from './translate.pipe';
describe('TranslatePipe', () => {
it('create an instance', () => {
const pipe = new TranslatePipe();
expect(pipe).toBeTruthy();
});
});

@ -0,0 +1,19 @@
import { Pipe, PipeTransform } from '@angular/core';
import { TranslatorService } from '../../services/translator/translator.service';
@Pipe({
name: 'translate'
})
export class TranslatePipe implements PipeTransform {
constructor(public translator: TranslatorService) {
}
transform(value: string, arg1?: any): any {
if (value) {
return this.translator.trInline(value);
}
return '';
}
}

@ -0,0 +1,12 @@
import { TestBed } from '@angular/core/testing';
import { AuthenticationService } from './authentication.service';
describe('AuthenticationService', () => {
beforeEach(() => TestBed.configureTestingModule({}));
it('should be created', () => {
const service: AuthenticationService = TestBed.get(AuthenticationService);
expect(service).toBeTruthy();
});
});

@ -0,0 +1,614 @@
import { Injectable } from '@angular/core';
import { Request } from '../models/request';
import { TranslatorService } from '../translator/translator.service';
import { ConnectorService } from '../connector/connector.service';
import { Observable, throwError } from 'rxjs';
import { CheckPatientRegisterationRequest } from './models/check-patient-registeration.request';
import { LoginRequest } from './models/login.request';
import { Response } from '../models/response';
import { AuthenticatedUser } from './models/authenticated-user';
import { CommonService } from '../common/common.service';
import { CheckUserAuthenticationRequest } from './models/check-user-auth.request';
import { CheckActivationCodeRequest } from './models/check-activation-code.request';
import { CheckUserAuthenticationResponse } from './models/check-user-auth.response';
import { CheckActivationCodeResponse } from './models/check-activation-code.response';
import { NativeStorage } from '@ionic-native/native-storage/ngx';
import { CheckRegisterationCodeRequest } from './models/check-registeration-code.request';
import { RegisterInformationRequest } from './models/register-information.request';
import { ForgotFileIDResponse } from './models/forgot-File-ID.response';
import { EmailRequest } from '../models/email-request';
import { EmailInput } from '../../ui/email/models/email-input';
import { UserLocalNotificationService } from '../user-local-notification/user-local-notification.service';
import { GetLoginInfoRequest } from './models/get-login-info.request';
import { GetLoginInfoResponse } from './models/get-login-info.response';
import { analyzeAndValidateNgModules } from '@angular/compiler';
import { Events } from '@ionic/angular';
import { InternationalMobileComponent } from '../../ui/mobile-number/international-mobile/international-mobile.component';
@Injectable({
providedIn: 'root'
})
export class AuthenticationService {
public static MOBILE_USER = 102;
/* login methods */
public static loginURL = 'Services/Authentication.svc/REST/CheckPatientAuthentication';
public static checkUserAuthURL = 'Services/Authentication.svc/REST/CheckPatientAuthentication';
public static activationCodeURL = 'Services/Authentication.svc/REST/CheckActivationCode';
public static getLoginInfoURL = 'Services/Authentication.svc/REST/GetMobileLoginInfo';
/* register methods */
public static checkPatientForRegisterationURL = 'Services/Authentication.svc/REST/CheckPatientForRegisteration';
public static sendSmsForRegisterURL = 'Services/Authentication.svc/REST/SendSMSForPatientRegisteration';
public static registerTempUserURL = 'Services/Authentication.svc/REST/RegisterTempPatientWithoutSMS';
public static sendSMSForgotFileNoURL = 'Services/Authentication.svc/REST/SendPatientIDSMSByMobileNumber';
public static forgotFileIDURL = 'Services/Authentication.svc/REST/CheckActivationCodeForSendFileNo';
public static user: AuthenticatedUser;
public static LOGIN_EVENT = 'user-login-event';
public static FAMILY_LOGIN_EVENT = 'family-login-event';
public static AUTHENTICATED_USER_KEY = 'save-authenticated-user';
// private static user: AuthenticatedUser;
constructor(
public con: ConnectorService,
public cs: CommonService,
public ts: TranslatorService,
public nativeStorage: NativeStorage,
public localNotifications: UserLocalNotificationService,
private events: Events
) { }
public authenticateRequest(request: Request, automaticLogin = true): Request {
this.setPublicFields(request);
const user = this.getAuthenticatedUser();
if (user) {
/*user with eye prescriptions*/
request.PatientID = user.PatientID;
request.TokenID = user.TokenID;
request.PatientOutSA = user.PatientOutSA ? 1 : 0;
request.PatientTypeID = user.PatientTypeID;
if (AuthenticationService.requireRelogin) {
this.sessionTimeOutDialog();
}
} else {
this.cs.userNeedToReLogin();
}
/*
else {
if (automaticLogin) {
this.cs.openUserLogin();
}
}
*/
return request;
}
public setPublicFields(request: Request): Request {
request.VersionID = 3.6;
request.Channel = 3;
request.LanguageID = TranslatorService.getCurrentLanguageCode();
request.IPAdress = '10.10.10.10';
request.SessionID = 'any thing'; // ??? required for not authorized login funny
request.isDentalAllowedBackend = false;
return request;
}
public authenticateAndSetPersonalInformation(request: EmailRequest, examinationInfo?: any): EmailRequest {
// if not authenticated will be redirected to login
this.authenticateRequest(request);
const user = this.getAuthenticatedUser();
if (user) {
request.To = user.Email;
request.DateofBirth = user.DateofBirth;
request.PatientIditificationNum = user.PatientIdentificationNo;
request.PatientMobileNumber = user.MobileNo;
request.PatientName = user.PatientName;
request.PatientOutSA = user.PatientOutSA ? 1 : 0;
request.PatientTypeID = user.PatientTypeID;
if (examinationInfo) {
if (examinationInfo.SetupID) { request.SetupID = examinationInfo.SetupID; }
if (examinationInfo.ProjectName) { request.ProjectName = examinationInfo.ProjectName; }
if (examinationInfo.ClinicName) { request.ClinicName = examinationInfo.ClinicDescription; }
if (examinationInfo.DoctorName) { request.DoctorName = examinationInfo.DoctorName; }
if (examinationInfo.ProjectID) { request.ProjectID = examinationInfo.ProjectID; }
if (examinationInfo.InvoiceNo) { request.InvoiceNo = examinationInfo.InvoiceNo; }
if (examinationInfo.OrderDate) {
request.OrderDate = this.cs.getDateISO(this.cs.evaluteDateAsObject(examinationInfo.OrderDate));
}
}
}
return request;
}
public getAuthenticatedRequest(login = true): Request {
const request = new Request();
this.authenticateRequest(request, login);
return request;
}
public getPublicRequest(): Request {
const request = new Request();
this.setPublicFields(request);
return request;
}
public login(request: LoginRequest, onError: any, errorLabel: string): Observable<Response> {
request.PatientID = 0;
request.TokenID = '';
request.isDentalAllowedBackend = false;
request.isRegister = false;
return this.con.post(AuthenticationService.loginURL, request, onError, errorLabel);
}
public isAuthenticated(): boolean {
return AuthenticationService.user != null;
}
public isAuthenticatedFamilyMember(): boolean {
if ( AuthenticationService.user != null ) {
return AuthenticationService.user.familyMember;
}
return false;
}
/**
* this fucntion load from user information if he logged in before
* and save user into memory and local storage
* disable notifications for previous user if new user logged in with different user
*
*
* info:
* 1- user stored in local storage without token
* @param result check activation code result
*/
public setAuthenticatedUser(result: CheckActivationCodeResponse): Observable<boolean> {
return Observable.create(observer => {
this.loadAuthenticatedUser().subscribe((loadedUser: AuthenticatedUser) => {
AuthenticationService.requireRelogin = false;
this.startIdleMonitoring();
const user = this.updateAuthenticatedUser(result, loadedUser);
/* we store in hd without token but with token in memory*/
this.saveUserInStorage(user).subscribe((success: boolean) => {
AuthenticationService.user = user;
this.publishUserChangeEvent();
observer.next(true);
observer.complete();
});
});
});
}
public resetAuthenticatedUser(user: AuthenticatedUser ) {
AuthenticationService.user = user;
AuthenticationService.requireRelogin = false;
this.startIdleMonitoring();
this.publishUserChangeEvent();
}
public setAuthenticatedMemberFamilyUser(result: CheckActivationCodeResponse) {
const authUser = new AuthenticatedUser();
AuthenticationService.requireRelogin = false;
this.startIdleMonitoring();
const user = this.updateAuthenticatedUser(result, authUser);
user["familyMember"] = true;
user.familyMember = true;
// user["hello"]= "ok";
/* we store in hd without token but with token in memory*/
AuthenticationService.user = user;
this.publishFamilyMemeberUserChangeEvent();
}
public updateLoggedInUser(newUser: AuthenticatedUser): Observable<boolean> {
return Observable.create(observer => {
/* we store in hd without token but with token in memory*/
this.saveUserInStorage(newUser).subscribe((success: boolean) => {
AuthenticationService.requireRelogin = false;
AuthenticationService.user = newUser;
this.publishUserChangeEvent();
observer.next(success);
observer.complete();
});
});
}
public setDeviceToken(token: string) {
const user = this.getAuthenticatedUser();
if (user) {
user.deviceToken = token;
this.updateLoggedInUser(user).subscribe((success: boolean) => {
// console.log('token stored:' + token);
});
}
}
public registerTempUser(request: RegisterInformationRequest, onError: any, errorLabel: string)
: Observable<CheckActivationCodeResponse> {
this.setPublicFields(request);
request.TokenID = '';
return this.con.post(AuthenticationService.registerTempUserURL, request, onError, errorLabel);
}
public getLoginInfo(request: GetLoginInfoRequest, onError: any, errorLabel: string)
: Observable<GetLoginInfoResponse> {
this.setPublicFields(request);
return this.con.post(AuthenticationService.getLoginInfoURL, request, onError, errorLabel);
}
/**
*update new authenticated user from previously stored and loaded user
*/
private updateAuthenticatedUser(result: CheckActivationCodeResponse, loadedUser: AuthenticatedUser): AuthenticatedUser {
const user = result.List[0];
if (loadedUser) {
// only if same user we fetch previous settings
if (loadedUser.PatientID === user.PatientID) {
user.agreed = loadedUser.agreed;
user.biometricEnabled = loadedUser.biometricEnabled;
} else {
this.localNotifications.deleteAllNotifications();
}
}
if (user.FirstName && user.LastName) {
user.PatientName = user.FirstName + ' ' + user.LastName;
}
user.IdentificationNo = user.PatientIdentificationNo;
/*
since suliman al habib has no support now for international phone number we do this woraround
*/
if (user.PatientOutSA) {
user.ZipCode = InternationalMobileComponent.EMIRATE_DIAL_CODE;
} else {
user.ZipCode = InternationalMobileComponent.SAUDI_DIAL_CODE;
}
user.Email = this.isRealEmail(user.EmailAddress) ? user.EmailAddress : null;
user.MobileNumber = user.MobileNumber.substr(1, user.MobileNumber.length - 1);
user.MobileNo = user.MobileNumber;
user.PatientOutSA = result.PatientOutSA;
user.PatientTypeID = result.PatientType;
user.TokenID = result.AuthenticationTokenID;
return user;
}
public isRealEmail(email: string): boolean {
return EmailInput.isValidEmail(email);
}
public isAuthenticatedUserHasRealEmail(): boolean {
const user = this.getAuthenticatedUser();
return user ? this.isRealEmail(user.Email) : false;
}
public setUserAgreed(agreed: boolean) {
const user = this.getAuthenticatedUser();
if (user) {
user.agreed = agreed;
// user['agreed'] = agreed;
this.saveUserInStorage(user).subscribe(result => {
});
} else {
}
}
public isAgreedBefore(): boolean {
const user = this.getAuthenticatedUser();
if (user) {
return (user.agreed != null) ? user.agreed : false;
} else {
return false;
}
}
/**
* we store in localstorage without token but we keep it in the static member
*/
private saveUserInStorage(user: AuthenticatedUser): Observable<boolean> {
return Observable.create(observer => {
if (user) {
const TokenID = user.TokenID;
user.TokenID = null;
this.nativeStorage.setItem(AuthenticationService.AUTHENTICATED_USER_KEY, user)
.then(
() => {
user.TokenID = TokenID;
observer.next(true);
observer.complete();
},
error => {
user.TokenID = TokenID;
observer.next(false);
observer.complete();
}
);
} else {
observer.next(false);
observer.complete();
}
});
}
/**
* signout
*clear user session and storage information
*/
public clearUser(): Observable<boolean> {
this.clearUserSession();
return Observable.create(observer => {
this.publishUserChangeEvent();
this.nativeStorage.remove(AuthenticationService.AUTHENTICATED_USER_KEY).then(
() => {
observer.next(true);
observer.complete();
},
() => {
observer.next(false);
observer.complete();
});
});
}
private publishUserChangeEvent() {
this.events.publish(AuthenticationService.LOGIN_EVENT, this.getAuthenticatedUser(), Date.now());
}
private publishFamilyMemeberUserChangeEvent() {
this.events.publish(AuthenticationService.FAMILY_LOGIN_EVENT, this.getAuthenticatedUser(), Date.now());
}
public clearUserSession() {
AuthenticationService.user = null;
}
public loadAuthenticatedUser(): Observable<AuthenticatedUser> {
return Observable.create(observer => {
this.nativeStorage.getItem(AuthenticationService.AUTHENTICATED_USER_KEY)
.then(
(user) => {
observer.next(user);
observer.complete();
},
error => {
observer.next(null);
observer.complete();
}
);
});
}
// TODO you should read from local storage and update static member
public getAuthenticatedUser(): AuthenticatedUser {
/*
if (AuthenticationService.requireRelogin) {
this.sessionTimeOutDialog();
return new AuthenticatedUser();
} else {
return AuthenticationService.user;
}
*/
return AuthenticationService.user;
}
public checkUserAuthentication(request: CheckUserAuthenticationRequest, onError: any, errorLabel: string)
: Observable<CheckUserAuthenticationResponse> {
this.setPublicFields(request);
return this.con.post(AuthenticationService.checkUserAuthURL, request, onError, errorLabel);
}
public checkActivationCode(request: CheckActivationCodeRequest, onError: any, errorLabel: string)
: Observable<CheckActivationCodeResponse> {
this.setPublicFields(request);
return this.con.post(AuthenticationService.activationCodeURL, request, onError, errorLabel);
}
/*
client side:
id no , mobile no , zip code
*/
public checkPatientForRegisteration(request: CheckPatientRegisterationRequest, onError: any, errorLabel: string)
: Observable<Response> {
this.setPublicFields(request);
request.TokenID = '';
request.PatientID = 0;
request.isRegister = false;
return this.con.post(AuthenticationService.checkPatientForRegisterationURL, request, onError, errorLabel);
}
/*
client side:
id no , mobile no , zip code
*/
public sendSmsForPatientRegisteration(request: CheckPatientRegisterationRequest, onError: any, errorLabel: string)
: Observable<CheckUserAuthenticationResponse> {
this.setPublicFields(request);
request.TokenID = '';
request.PatientID = 0;
request.isRegister = false;
return this.con.post(AuthenticationService.sendSmsForRegisterURL, request, onError, errorLabel);
}
public checkRegisterationActivationCode(request: CheckRegisterationCodeRequest, onError: any, errorLabel: string)
: Observable<Response> {
this.setPublicFields(request);
return this.con.post(AuthenticationService.activationCodeURL, request, onError, errorLabel);
}
public sendSMSForForgotFileNumber(request: CheckUserAuthenticationRequest, onError: any, errorLabel: string)
: Observable<CheckUserAuthenticationResponse> {
this.setPublicFields(request);
request.TokenID = '';
request.PatientIdentificationID = '';
request.PatientID = 0;
request.SearchType = 2;
request.isRegister = false;
return this.con.post(AuthenticationService.sendSMSForgotFileNoURL, request, onError, errorLabel);
}
public forgotFileIdActivation(request: CheckActivationCodeRequest, onError: any, errorLabel: string)
: Observable<ForgotFileIDResponse> {
this.setPublicFields(request);
request.TokenID = '';
request.PatientIdentificationID = '';
request.PatientID = 0;
request.SearchType = 2;
request.isRegister = false;
return this.con.post(AuthenticationService.forgotFileIDURL, request, onError, errorLabel);
}
public isSAUDIIDValid(id: string): boolean {
if (!id) {
return false;
}
try {
id = id.toString();
id = id.trim();
const returnValue = Number(id);
let sum = 0;
if (returnValue > 0) {
const type = Number(id.charAt(0));
if (id.length !== 10) {
return false;
}
if (type !== 2 && type !== 1) {
return false;
}
for (let i = 0; i < 10; i++) {
if ((i % 2) === 0) {
const a = id.charAt(i);
const x = Number(a) * 2;
let b = x.toString();
if (b.length === 1) {
b = '0' + b;
}
sum += Number(b.charAt(0)) + Number(b.charAt(1));
} else {
sum += Number(id.charAt(i));
}
}
return ((sum % 10) === 0);
}
} catch (err) {
}
return false;
}
public checkUserHasEmailDialog(): Observable<void> {
return Observable.create(observer => {
if (this.isAuthenticatedUserHasRealEmail()) {
const message = this.ts.trPK('general', 'send-email')
.replace('[0]', this.getAuthenticatedUser().EmailAddress || this.getAuthenticatedUser().Email);
this.cs.presentConfirmDialog(message,
() => {
observer.next();
observer.complete();
});
} else {
this.cs.presentConfirmDialog(this.ts.trPK('login', 'enter-email'),
() => {
this.cs.openPatientProfile();
observer.complete();
});
}
});
}
/*
user session timeout after idle for 20 Minute
*/
private static requireRelogin = false;
public static monitorInterval_M = 20 * 60 * 1000;
// public static monitorInterval_M = 15 * 1000;
private static timerID;
private stopIdleTimer() {
if (AuthenticationService.timerID) {
clearTimeout(AuthenticationService.timerID);
}
}
private sessionTimeOutDialog() {
this.cs.presentConfirmDialog(this.ts.trPK('general', 'idle-relogin'), () => {
this.cs.openUserLogin();
});
}
/*
reset and start idling interval
*/
private detectIdle() {
this.stopIdleTimer();
AuthenticationService.timerID = setTimeout(() => {
if (AuthenticationService.user) {
AuthenticationService.requireRelogin = true;
this.clearUserSession();
this.publishUserChangeEvent();
this.sessionTimeOutDialog();
this.cs.openHome();
}
}, AuthenticationService.monitorInterval_M);
}
private registerDocumentEvents(events: string[], handler: any) {
for (const event of events) {
document.addEventListener(event, handler);
}
}
private static eventsRegistered = false;
public startIdleMonitoring() {
if (!AuthenticationService.eventsRegistered) {
AuthenticationService.eventsRegistered = true;
// every time we have and event
this.registerDocumentEvents(['mousedown', 'touchstart', 'click', 'keyup'], () => {
// if user still logged in and session not expired
if (AuthenticationService.user && !AuthenticationService.requireRelogin) {
// reset and start idling timer
this.detectIdle();
}
});
}
}
}

@ -0,0 +1,46 @@
export class PatientUserModel {
Address: string;
Age: number;
BloodGroup: string;
CreatedBy: number;
DHCCPatientRefID: string;
DateofBirth: string;
EmailAddress: string;
EmergencyContactName: string;
EmergencyContactNo: string;
EmployeeID: string;
ExpiryDate: string;
FaxNumber: string;
FirstName: string;
FirstNameN: string;
Gender: number;
GenderDescription: string;
IsEmailAlertRequired: boolean;
IsHmgEmployee: boolean;
IsSMSAlertRequired: boolean;
LastName: string;
LastNameN: string;
MemberID: string;
MiddleName: string;
MiddleNameN: string;
MobileNumber: string;
NationalityID: string;
OutSA: number;
POBox: string;
PatientID: number;
PatientIdentificationNo: string;
PatientIdentificationType: number;
PatientPayType: number;
PatientType: number;
PhoneOffice: string;
PhoneResi: string;
PreferredLanguage: string;
ProjectID: number;
RHFactor: any;
ReceiveHealthSummaryReport: boolean;
RelationshipID: number;
SetupID: string;
Status: number;
ZipCode: string;
}

@ -0,0 +1,17 @@
import { PatientUserModel } from './PatientUserModel';
import { TestBed } from '@angular/core/testing';
export class AuthenticatedUser extends PatientUserModel {
PatientName: string;
TokenID: string;
MobileNo: string;
Email: string;
PatientOutSA: boolean;
PatientTypeID: number;
agreed: boolean;
IdentificationNo: string;
deviceToken: string;
biometricEnabled: boolean;
ProjectID: number;
familyMember: boolean;
}

@ -0,0 +1,15 @@
import { Request } from '../../models/request';
export class CheckActivationCodeRequest extends Request {
FingerPrintPatientIdentificationID?: string ; // ""
IsMobileFingerPrint?: boolean; // false
ForRegisteration?: boolean;
LogInTokenID: string ; // null if not exist
PatientIdentificationID: string ;
PatientMobileNumber: string;
SearchType?: number ; // 1 for id , 2 for file no
activationCode: string ; // "0000" if sms activation is not required
isRegister: boolean;
ZipCode: string;
IsSilentLogin: boolean;
}

@ -0,0 +1,10 @@
import { Response } from '../../models/response';
import { PatientUserModel } from './PatientUserModel';
import { AuthenticatedUser } from './authenticated-user';
export class CheckActivationCodeResponse extends Response {
List: AuthenticatedUser[];
AuthenticationTokenID: string;
PatientOutSA: boolean;
PatientType: number;
}

@ -0,0 +1,9 @@
import { Request } from '../../models/request';
export class CheckPatientRegisterationRequest extends Request {
PatientIdentificationID: string; // "iqama"
PatientMobileNumber: string; // "phone without start 0"
TokenID: string; // should be empty ""
ZipCode: string; // "966 or 971"
isRegister: boolean;
}

@ -0,0 +1,12 @@
import { Request } from '../../models/request';
export class CheckRegisterationCodeRequest extends Request {
ForRegisteration: boolean;
LogInTokenID: string; // null if not exist
PatientIdentificationID: string;
PatientMobileNumber: string;
SearchType: number; // 1 for id , 2 for file no
activationCode: string; // "0000" if sms activation is not required
isRegister: boolean;
ZipCode: string;
}

@ -0,0 +1,10 @@
import { Request } from '../../models/request';
export class CheckUserAuthenticationRequest extends Request {
PatientIdentificationID: string; // id
PatientMobileNumber: string; // phone number
ZipCode: string;
SearchType: number; // 1 for id , 2 for file no
isRegister: boolean; // false
LogInTokenID?: string;
}

@ -0,0 +1,13 @@
import { Response } from '../../models/response';
export class CheckUserAuthenticationResponse extends Response {
PatientHasFile: boolean;
PatientOutSA: boolean;
PatientType: number;
ProjectIDOut: number;
SMSLoginRequired: boolean;
VerificationCode: string;
hasFile: boolean;
isSMSSent: boolean;
LogInTokenID: string;
}

@ -0,0 +1,5 @@
import { Response } from '../../models/response';
export class ForgotFileIDResponse extends Response {
ReturnMessage: string;
}

@ -0,0 +1,30 @@
import { Request } from '../../models/request';
import { AuthenticatedUser } from './authenticated-user';
import { CountryCode } from 'src/app/hmg-common/ui/mobile-number/international-mobile/models/country-code.model';
export class GetLoginInfoRequest extends Request {
NationalID: string;
MobileNo: string;
DeviceToken: string;
PatientID: number;
ProjectOutSA: boolean;
LoginType: number; // 2 by patient id , 1 by identification number
ZipCode: string;
PatientMobileNumber: string; // same as mobileNO,
SearchType: number; // 2
PatientIdentificationID: string // ""
isRegister: boolean; // false
constructor(user: AuthenticatedUser) {
super();
this.NationalID = user.IdentificationNo;
this.MobileNo = this.PatientMobileNumber = user.MobileNo;
this.DeviceToken = user.deviceToken;
this.PatientID = user.PatientID;
this.ProjectOutSA = user.PatientOutSA ;
this.LoginType = 2;
this.ZipCode = CountryCode.localCode( user.ZipCode);
this.SearchType = 2;
this.PatientIdentificationID = '';
this.isRegister = false;
}
}

@ -0,0 +1,8 @@
import { Response } from '../../models/response';
export class GetLoginInfoResponse extends Response {
SMSLoginRequired: boolean;
isSMSSent: boolean;
LogInTokenID: string;
PatientOutSA: boolean;
}

@ -0,0 +1,12 @@
import { Request } from '../../models/request';
export class LoginRequest extends Request {
PatientID: number; // 0
PatientIdentificationID: string; // "2401412511"
PatientMobileNumber: string; // "537753536"
SearchType: number; // 1 for iqama 2 for file number
TokenID: string; // ""
ZipCode: string; // "966"
// isDentalAllowedBackend: false
isRegister: boolean; // false
}

@ -0,0 +1,16 @@
export class RegisterInformationPatientModel {
FirstName: string;
MiddleName: string;
LastName: string;
StrDateofBirth: string; // ison date
TempValue: true;
DateofBirth: string; // backend format
Gender: number;
NationalityID: string;
ProjectID: number;
MobileNumber: string;
PatientIdentificationType: number;
PatientIdentificationNo: string;
PatientOutSA: boolean;
}

@ -0,0 +1,33 @@
import { Request } from '../../models/request';
import { RegisterInformationPatientModel } from './register-information-patient.model';
export class RegisterInformationRequest extends Request {
activationCode: string;
LogInTokenID: string;
PatientIdentificationID: string;
PatientMobileNumber: string;
ProjectID: number;
Patientobject = new RegisterInformationPatientModel();
constructor() {
super();
this.Patientobject.TempValue = true;
}
public setName(first: string, middle: string, last: string) {
this.Patientobject.FirstName = first;
this.Patientobject.MiddleName = middle;
this.Patientobject.LastName = last;
}
public setBirthDate(birthDateISO: string, birthDateJSON: string) {
this.Patientobject.StrDateofBirth = birthDateISO;
this.Patientobject.DateofBirth = birthDateJSON;
}
public setGender(gender: number) {
this.Patientobject.Gender = gender;
}
}

@ -0,0 +1,12 @@
import { TestBed } from '@angular/core/testing';
import { AutoConnectService } from './auto-connect.service';
describe('AutoConnectService', () => {
beforeEach(() => TestBed.configureTestingModule({}));
it('should be created', () => {
const service: AutoConnectService = TestBed.get(AutoConnectService);
expect(service).toBeTruthy();
});
});

@ -0,0 +1,204 @@
import { ConnectorService } from '../connector/connector.service'
import { AuthenticationService } from '../authentication/authentication.service'
import { CredentialWifiRequest } from './models/credential-wifi.request'
import { CredentialWifiResponse } from './models/credential-wifi.response'
import { Injectable } from '@angular/core';
import { Platform } from '@ionic/angular';
import { Observable } from 'rxjs';
import { CommonService } from '../common/common.service';
import { AuthenticatedUser } from '../authentication/models/authenticated-user'
import { AlertControllerService } from 'src/app/hmg-common/ui/alert/alert-controller.service';
import { TranslatorService } from 'src/app/hmg-common/services/translator/translator.service';
declare var WifiWizard2: any;
@Injectable({
providedIn: 'root'
})
export class AutoConnectService {
passWord: any;
userName: any;
public buttons: any[]
public static credentialInfoWifi = 'Services/Patients.svc/REST/Hmg_SMS_Get_By_ProjectID_And_PatientID';
constructor(
public con: ConnectorService,
public authService: AuthenticationService,
public cs: CommonService,
public platform: Platform,
public ts: TranslatorService
) { }
public getCredentialWifiService(patientID: any, projectID: any, onError: any): Observable<CredentialWifiResponse> {
//const request = this.authService.getAuthenticatedRequest();
const request = new CredentialWifiRequest();
request.PatientID = patientID;
request.ProjectID = projectID;
// request.SetupID= '91877';
return this.con.post(AutoConnectService.credentialInfoWifi, request, onError);
}
/*
call service to get Password and Name
call plugin to connected
if connected then open url
*/
public getCredentialWifi(buttons) {
this.buttons = buttons;
const authUser = this.authService.getAuthenticatedUser();
this.getCredentialWifiService(authUser.PatientID, authUser.ProjectID, () => { }).subscribe((result: any) => {
if (this.cs.validResponse(result)) {
if (this.cs.hasData(result.Hmg_SMS_Get_By_ProjectID_And_PatientIDList)) {
//get the password and userNmae
// send it to url
this.passWord = result.Hmg_SMS_Get_By_ProjectID_And_PatientIDList[0].Password;
this.userName = result.Hmg_SMS_Get_By_ProjectID_And_PatientIDList[0].UserName;
this.scanWifi();
}
}
});
}
public async scanWifi() {
// this.platform.ready().then(() => {
if (this.platform.is("ios")) {
//check avaliable ssid
this.checkConnected();
} //end if iOS
else if (this.platform.is("android")) {
// alert("Android");
try {
let result = await WifiWizard2.scan()
let resultList = result;
for (let i = 0; i < resultList.length; i++) {
let ssid = resultList[i].SSID;
if (ssid == "CS-Guest") {
// alert("ssid " + ssid);
i = resultList.length; // to stop the loop
} // if ssid == cs-guest
} // for loop
this.checkConnected();
} catch (e) {
//alert( 'Error to Scan: '+ e );
// this.alertService.presentConfirm(
// this.ts.trPK('general', 'info'),
// this.ts.trPK('error', 'scan-wifi'),
// this.ts.trPK('general', 'ok'), () => {
// this.alertService.dismiss();
// }
// );
this.cs.presentAcceptDialog(this.ts.trPK('error', 'scan-wifi'), () => { })
}
//
} //end if Android
//});
}
public async checkConnected() {
try {
let result = await WifiWizard2.getConnectedSSID()
if (result == "CS-Guest") {
// alert('WIFI SSID '+ result);
this.disconnectNetwork();
} else {
this.startConnected();
}
} catch (e) {
alert('Error to display WIFI SSID: ' + e);
// conneted to local HMG
this.startConnected();
}
}
public async startConnected() {
alert(" startConnected ");
try {
let result;
if (this.platform.is("ios")) {
result = await WifiWizard2.iOSConnectNetwork("CS-Guest")
} else if (this.platform.is("android")) {
result = await WifiWizard2.connect("CS-Guest", false, false)
}
alert('conected: ' + result);
this.buttons[5][5].title = 'home,auto-connected-wifi';
//let url="http://192.168.104.251/guest/HMG-Guest.php?_browser=1&cmd=login&essid=CS-Guest&apname=CS_AP_9&apgroup=CloudSolutons%20AP%20Group&url=http%3A%2F%2Fwww%2Emsftconnecttest%2Ecom%252Fredirect&Name=6200&Pass=7809";
let url = "http://192.168.104.251/guest/HMG-Guest.php?_browser=1&cmd=login&essid=CS-Guest&apname=CS_AP_9&apgroup=CloudSolutons%20AP%20Group&url=http%3A%2F%2Fwww%2Emsftconnecttest%2Ecom%252Fredirect&Name=" + this.userName + "&Pass=" + this.passWord + "";
setTimeout(() => {
this.cs.openBrowser(url);
}, 2 * 1000);
} catch (e) {
//display error for check the avaliable Wifi
// alert( 'Error to connected: '+ e );
// this.alertService.presentConfirm(
// this.ts.trPK('general', 'info'),
// this.ts.trPK('error', 'connect-Wifi'),
// this.ts.trPK('general', 'ok'), () => {
// this.alertService.dismiss();
// }
// );
this.cs.presentAcceptDialog(this.ts.trPK('error', 'connect-Wifi'), () => { });
}
}
public async disconnectNetwork() {
try {
let result;
if (this.platform.is("ios")) {
result = await WifiWizard2.iOSDisconnectNetwork("CS-Guest")
} else if (this.platform.is("android")) {
result = await WifiWizard2.disconnect("CS-Guest")
}
this.buttons[5][5].title = 'home,auto-wifi';
alert('Succssful Disconected ' + result);
} catch (e) {
//display error for check the avaliable Wifi
// alert( 'Error to connected: '+ e );
// this.alertService.presentConfirm(
// this.ts.trPK('general', 'info'),
// this.ts.trPK('error', 'disconnect-Wifi'),
// this.ts.trPK('general', 'ok'), () => {
// this.alertService.dismiss();
// }
// );
this.cs.presentAcceptDialog(this.ts.trPK('error', 'disconnect-Wifi'), () => { })
}
}
}

@ -0,0 +1,6 @@
export class CredentialWifiModel{
UserName:number;
Password:number;
}

@ -0,0 +1,7 @@
import { Request } from 'src/app/hmg-common/services/models/request';
export class CredentialWifiRequest extends Request {
PatientID: number;
ProjectID:number;
SetupID:String;
}

@ -0,0 +1,6 @@
import { Response } from 'src/app/hmg-common/services/models/response';
import { CredentialWifiModel } from './credential-wifi.modal';
export class CredentialWifiResponse extends Response {
List_PatientCredentialWifi: CredentialWifiModel[];
}

@ -0,0 +1,638 @@
import { Injectable } from '@angular/core';
import { NavController, ToastController, LoadingController, AlertController, Platform } from '@ionic/angular';
import { Router } from '@angular/router';
import { TranslatorService } from '../translator/translator.service';
import { AlertControllerService } from '../../ui/alert/alert-controller.service';
import { Response } from '../models/response';
import { Location } from '@angular/common';
import { ThemeableBrowser } from '@ionic-native/themeable-browser/ngx';
import { BrowserConfig } from './models/browser-config';
import { LaunchNavigator, LaunchNavigatorOptions } from '@ionic-native/launch-navigator/ngx';
import { Device } from '@ionic-native/device/ngx';
@Injectable({
providedIn: 'root'
})
export class CommonService {
private progressLoaders: any[] = [];
private loadingProgress: any;
constructor(
public nav: NavController,
public router: Router,
public location: Location,
public ts: TranslatorService,
public loadingController: LoadingController,
public toastController: ToastController,
public alertController: AlertControllerService,
public alertControllerIonic: AlertController,
public themeableBrowser: ThemeableBrowser,
public launchNavigation: LaunchNavigator,
public platform: Platform,
public device: Device
) { }
public back() {
// this.location.back();
this.nav.goBack();
}
public round(value: number, decimal: number): string {
const valueStr = value.toString();
const dotIndex = valueStr.indexOf('.');
if (dotIndex >= 0) {
return valueStr.toString().substr(0, dotIndex + decimal);
} else {
return value.toString();
}
}
public toastPK(page: string, key: string) {
this.toast(this.ts.trPK(page, key));
}
async toast(message: string) {
const toast = await this.toastController.create({
message: message,
showCloseButton: true,
position: 'middle',
duration: 2000,
closeButtonText: this.ts.trPK('general', 'done')
});
toast.present();
}
async startLoading() {
this.stopLoading();
const loader = await this.loadingController.create({
spinner: 'bubbles',
duration: 30000,
message: this.ts.trPK('error', 'wait'),
translucent: true
});
this.progressLoaders.push(loader);
return await loader.present();
}
public mobileNumber(number: string) {
return number.substr(1, number.length - 1);
}
public testFunction() {
}
public stopLoading() {
/*
loading progress must be implemented
as synchronous
*/
setTimeout(() => {
for (const loader of this.progressLoaders) {
loader.dismiss();
}
this.progressLoaders = [];
}, 1000);
}
public presentAlert(message: string) {
this.alertDialog(null, this.ts.trPK('general', 'ok'), this.ts.trPK('general', 'alert'), message);
}
public presentConfirmDialog(message: string, onAccept: any, onCancel: any) {
this.confirmAlertDialog(onAccept, this.ts.trPK('general', 'ok'),
null, this.ts.trPK('general', 'cancel'),
this.ts.trPK('general', 'confirm'), message);
}
async presentConfirmDialogOld(message: string, onAccept: any, onCancel: any) {
this.alertController.presentConfirm(
this.ts.trPK('general', 'confirm'),
message,
this.ts.trPK('general', 'ok'),
() => {
this.alertController.dismiss();
onAccept();
},
() => {
this.alertController.dismiss();
onCancel();
}
);
}
public presentAcceptDialog(message: string, onAccept: any) {
this.alertDialog(onAccept, this.ts.trPK('general', 'ok'), this.ts.trPK('general', 'confirm'), message);
}
async presentAcceptDialogOld(message: string, onAccept: any) {
this.alertController.presentConfirm(
this.ts.trPK('general', 'confirm'),
message,
this.ts.trPK('general', 'ok'),
() => {
this.alertController.dismiss();
onAccept();
}
);
}
public confirmBackDialogOld(message: string) {
this.alertController.presentConfirm(
this.ts.trPK('general', 'info'),
message,
this.ts.trPK('general', 'ok'),
() => {
this.back();
this.alertController.dismiss();
}
);
}
public confirmBackDialog(message: string) {
this.alertDialog(
() => {
this.back();
},
this.ts.trPK('general', 'ok'), this.ts.trPK('general', 'info'), message);
}
public showErrorMessageDialogOld(onClick: any, okLabel: string, message: string) {
this.alertController.presentConfirm(
this.ts.trPK('general', 'alert'),
message, okLabel, () => {
if (onClick) {
onClick();
}
this.alertController.dismiss();
}
);
}
public showErrorMessageDialog(onClick: any, okLabel: string, message: string) {
this.alertDialog(onClick, okLabel, this.ts.trPK('general', 'alert'), message);
}
public showConnectionErrorDialogOld(onClick: any, okLabel: string) {
this.alertController.presentConfirm(
this.ts.trPK('general', 'alert'),
this.ts.trPK('error', 'conn'),
okLabel, () => {
if (onClick) {
onClick();
}
this.alertController.dismiss();
}
);
}
public showConnectionErrorDialog(onClick: any, okLabel: string) {
this.alertDialog(onClick, okLabel, this.ts.trPK('general', 'alert'), this.ts.trPK('error', 'conn'));
}
async confirmAlertDialog(onAccept: any, acceptLabel: string, onCancel: any, cancelLabel: string, title: string, message: string) {
this.clearAllAlerts();
const alert = await this.alertControllerIonic.create({
header: this.ts.trPK('general', 'confirm'),
message: message,
buttons: [
{
text: cancelLabel,
role: 'cancel',
handler: () => {
if (onCancel) {
onCancel();
}
this.alertControllerIonic.dismiss();
}
}, {
text: acceptLabel,
handler: () => {
if (onAccept) {
onAccept();
}
this.alertControllerIonic.dismiss();
}
}
]
});
// this.alerts.push(alert);
await alert.present();
}
async alertDialog(onAccept: any, acceptLabel: string, title: string, message: string) {
this.clearAllAlerts();
const alert = await this.alertControllerIonic.create({
header: title,
message: message,
buttons: [
{
text: acceptLabel,
handler: () => {
if (onAccept) {
onAccept();
}
this.alertControllerIonic.dismiss();
}
}
]
});
// this.alerts.push(alert);
await alert.present();
}
private alerts: any[] = [];
public clearAllAlerts() {
/*
for (const alert of this.alerts) {
this.alertControllerIonic.dismiss(alert);
}
*/
this.alerts = [];
}
public getDeviceInfo(): string {
if (this.platform.is('mobile')) {
const os = this.platform.is('ios') ? 'Iphone' : 'android';
return os + ' - ' + this.device.platform + ' - ' + this.device.version + ' , ' + this.device.manufacturer;
} else {
return navigator.userAgent;
}
}
public getDeviceType(): string {
if (this.platform.is('mobile')) {
return 'Mobile ' + (this.platform.is('ios') ? 'Iphone' : 'android');
} else {
return 'Desktop';
}
}
public validResponse(result: Response): boolean {
if (result.MessageStatus === 1) {
return true;
} else if (result.MessageStatus === 2) {
return this.hasData(result['SameClinicApptList']);
}
return false;
}
public openBrowser(url: string) {
// const browser: ThemeableBrowserObject =
this.themeableBrowser.create(url, '_blank', BrowserConfig.OPTIONS);
}
public imageFromBase64(base64: string) {
return 'data:image/jpeg;base64,' + base64;
}
public openLocation(lat: number, lng: number) {
this.launchNavigation.navigate([lat, lng]).then(
() => { },
() => { this.failedToOpenMap(); }
);
}
private failedToOpenMap() {
this.alertController.presentConfirm(
this.ts.trPK('general', 'alert'),
this.ts.trPK('error', 'map'),
this.ts.trPK('general', 'ok'),
() => {
this.alertController.dismiss();
}
);
}
public evaluteDate(dateStr: string): string {
if (dateStr) {
const utc = parseInt(dateStr.substring(6, dateStr.length - 2), 10);
if (utc) {
const appoDate = new Date(utc);
if ((appoDate instanceof Date) && !isNaN(appoDate.getTime())) {
return appoDate.toLocaleDateString();
}
}
}
return dateStr;
}
public evaluteDateAsObject(dateStr: string): Date {
if (dateStr) {
const utc = parseInt(dateStr.substring(6, dateStr.length - 2), 10);
return new Date(utc);
}
return null;
}
public getDateISO(date: Date): string {
return date.getFullYear().toString() + '-' +
this.trailerZero(date.getMonth() + 1) + '-' +
this.trailerZero(date.getDate());
}
public getTodayISO(): string {
return this.getDateISO(new Date());
}
public getTimeISO(date: Date): string {
return this.trailerZero(date.getHours()) + ':' +
this.trailerZero(date.getMinutes()) + ':00';
}
public getDateTimeISO(date: Date): string {
return this.getDateISO(date) + ' ' + this.getTimeISO(date);
}
public getDateTimeISOFromString(dateStr: string): string {
const date = this.evaluteDateAsObject(dateStr);
return this.getDateTimeISO(date) + ' ' + this.getTimeISO(date);
}
public getCurrentTimeISO(): string {
return this.getTimeISO(new Date());
}
private trailerZero(value: number): string {
const str = value.toString();
return (str.length > 1) ? str : ('0' + str);
}
public hasData(array: any[]): boolean {
return array != null && array.length > 0;
}
public extractNumber(message: string): string {
if (message != null && message.length > 0) {
let startIndex = null;
let endIndex = message.length - 1;
for (let i = 0; i < message.length; i++) {
const code = message.charCodeAt(i);
if (this.inNumberRange(code)) {
if (!startIndex) {
startIndex = i;
}
} else {
if (startIndex) {
endIndex = i;
break;
}
}
}
return startIndex ? message.substring(startIndex, endIndex) : '';
}
return null;
}
public inNumberRange(targetCode: number): boolean {
const minDigit = '0'.charCodeAt(0);
const maxDigit = '9'.charCodeAt(0);
return (targetCode >= minDigit && targetCode <= maxDigit);
}
public enterPage() {
}
/*
open calls
*/
public openAppointments() {
this.nav.navigateForward(['/eservices/appointments/home']);
// this.router.navigateByUrl('/eservices/appointments/home');
}
public openHome() {
this.nav.navigateRoot(['/home']);
// this.nav.navigateByUrl('/home');
}
public reload(url: string, from: string) {
console.log('force reload called from:' + from);
// window.location.reload();
location.href = url;
}
public navigateRoot(url: string) {
this.nav.navigateRoot([url]);
}
public navigateForward(url: string) {
this.nav.navigateForward([url]);
}
public navigateBack(url: string) {
this.nav.navigateBack([url]);
}
public openEservices() {
this.nav.navigateForward(['/eservices/home']);
// this.router.navigateByUrl('/eservices/home');
}
public openBookings() {
this.nav.navigateForward(['/eservices/booking/home']);
// this.router.navigateByUrl('/eservices/bookings');
}
public openAppointmentDetails() {
this.nav.navigateForward(['/eservices/appointments/detials']);
// this.router.navigateByUrl('/eservices/appointments/detials');
}
public openApprovals() {
this.nav.navigateForward(['/eservices/approvals']);
// this.router.navigateByUrl('/eservices/approvals');
}
public openPrescriptions() {
this.nav.navigateForward(['/eservices/prescriptions']);
// this.router.navigateByUrl('/eservices/prescriptions');
}
public openPrescriptionReports() {
this.nav.navigateForward(['/eservices/prescriptions/reports']);
// this.router.navigateByUrl('/eservices/prescriptions/reports');
}
public openPrescriptionPharmaciesList() {
this.nav.navigateForward(['/eservices/prescriptions/reports/pharmacies']);
// this.router.navigateByUrl('/eservices/prescriptions/reports/pharmacies');
}
public openDoctorSchedule() {
this.nav.navigateForward(['/eservices/doctors/schedule']);
// this.router.navigateByUrl('/eservices/appointments/doctor-schedule');
}
public openRadiology() {
this.nav.navigateForward(['/eservices/radiology']);
// this.router.navigateByUrl('/eservices/radiology');
}
public openRadiologyReport() {
this.nav.navigateForward(['/eservices/radiology/report']);
// this.router.navigateByUrl('/eservices/radiology/report');
}
public openMyDoctors() {
this.nav.navigateForward(['/eservices/doctors']);
}
public openDoctorProfile() {
this.nav.navigateForward(['/eservices/doctors/profile']);
}
public openBookingCalendar() {
this.nav.navigateForward(['/eservices/doctors/calendar']);
}
public openLabOrders() {
this.nav.navigateForward(['/eservices/lab']);
// this.router.navigateByUrl('/eservices/lab');
}
public openLabResult() {
this.nav.navigateForward(['/eservices/lab/result']);
// this.router.navigateByUrl('/eservices/lab/result');
}
public openEyePrescriptions() {
this.nav.navigateForward(['/eservices/eye']);
}
public openEyeMeasurments() {
this.nav.navigateForward(['/eservices/eye/measurments']);
}
public openBloodSugarGraph() {
this.nav.navigateForward(['/eservices/tracker/blood-sugar/graph']);
}
public openBloodSugarAdd() {
this.nav.navigateForward(['/eservices/tracker/blood-sugar/add']);
}
public openBloodPressureAdd() {
this.nav.navigateForward(['/eservices/tracker/blood-pressure/add']);
}
public openBloodSugarRHMD() {
this.nav.navigateForward(['/eservices/tracker/blood-sugar/rhmd']);
}
public openBloodSugarRHMDBL() {
this.nav.navigateForward(['/eservices/tracker/blood-sugar/rhmd-bl']);
}
public openBloodSugarRHMDBLE() {
this.nav.navigateForward(['/eservices/tracker/blood-sugar/rhmd-ble']);
}
public openBloodPressureGraph() {
this.nav.navigateForward(['/eservices/tracker/blood-pressure/graph']);
}
public openWeightAdd() {
this.nav.navigateForward(['/eservices/tracker/weight/add']);
}
public openWeightGraph() {
this.nav.navigateForward(['/eservices/tracker/weight/graph']);
}
public openBookingDoctorsList() {
this.nav.navigateForward(['/eservices/booking/doctors-list']);
}
public openBookingDentalComplains() {
this.nav.navigateForward(['/eservices/booking/dental-complains']);
}
public openDocResponseDetail() {
this.nav.navigateForward(['/eservices/doc-response/response-detail']);
}
public openInsurCardDetail() {
this.nav.navigateForward(['/eservices/insur-cards/card-detail']);
}
public openUserAgreement() {
this.nav.navigateForward(['/eservices/month-report/user-agreement']);
}
public openChildVaccineHome() {
this.nav.navigateForward(['/eservices/child-vaccine/home']);
}
public openChildVaccineVaccineList() {
this.nav.navigateForward(['/eservices/child-vaccine/vaccine-list']);
}
public openChildVaccineAddChild() {
this.nav.navigateForward(['/eservices/child-vaccine/add-child']);
}
public openChildVaccineChildList() {
this.nav.navigateForward(['/eservices/child-vaccine/child-list']);
}
public openAskDocRequest() {
this.nav.navigateForward(['/eservices/ask-doc/ask-doc-request']);
}
public openNewMedReport() {
this.nav.navigateForward(['/eservices/med-report/new-med-report']);
}
public openUserLogin() {
console.log('now open login');
this.nav.navigateForward(['/authentication/login']);
}
public openAgreement() {
this.nav.navigateForward(['/authentication/agreement']);
}
public openUserRegister() {
this.nav.navigateForward(['/authentication/register']);
}
public openUserForgot() {
this.nav.navigateForward(['/authentication/forgot']);
}
public openFeedback() {
this.nav.navigateForward(['/feedback/home']);
}
public openFeedbackStatusDetails() {
this.nav.navigateForward(['/feedback/status-details']);
}
public navigateTo(url: string) {
this.nav.navigateForward([url]);
}
}

@ -0,0 +1,12 @@
import { TestBed } from '@angular/core/testing';
import { CommonService } from './common.service';
describe('CommonService', () => {
beforeEach(() => TestBed.configureTestingModule({}));
it('should be created', () => {
const service: CommonService = TestBed.get(CommonService);
expect(service).toBeTruthy();
});
});

File diff suppressed because it is too large Load Diff

@ -0,0 +1,64 @@
import { ThemeableBrowserOptions } from '@ionic-native/themeable-browser/ngx';
export class BrowserConfig {
public static OPTIONS: ThemeableBrowserOptions = {
statusbar: {
color: '#ffffffff'
},
toolbar: {
height: 44,
color: '#f0f0f0ff'
},
title: {
color: '#003264ff',
showPageTitle: true
},
backButton: {
image: 'back',
imagePressed: 'back_pressed',
align: 'left',
event: 'backPressed'
},
forwardButton: {
image: 'forward',
imagePressed: 'forward_pressed',
align: 'left',
event: 'forwardPressed'
},
closeButton: {
image: 'close',
imagePressed: 'close_pressed',
align: 'left',
event: 'closePressed'
},
customButtons: [
{
image: 'share',
imagePressed: 'share_pressed',
align: 'right',
event: 'sharePressed'
}
],
menu: {
image: 'menu',
imagePressed: 'menu_pressed',
title: 'Test',
cancel: 'Cancel',
align: 'right',
items: [
{
event: 'helloPressed',
label: 'Hello World!'
},
{
event: 'testPressed',
label: 'Test!'
}
]
},
backButtonCanClose: true,
clearcache: true,
clearsessioncache: true,
disallowoverscroll: 'yes'
};
}

@ -0,0 +1,7 @@
import { Component } from '@angular/core';
export class InputData {
value: any;
values: any [];
}

@ -0,0 +1,12 @@
import { TestBed } from '@angular/core/testing';
import { ConnectorService } from './connector.service';
describe('ConnectorService', () => {
beforeEach(() => TestBed.configureTestingModule({}));
it('should be created', () => {
const service: ConnectorService = TestBed.get(ConnectorService);
expect(service).toBeTruthy();
});
});

@ -0,0 +1,148 @@
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders, HttpErrorResponse } from '@angular/common/http';
import { Observable, throwError, TimeoutError } from 'rxjs';
import { catchError, retry, tap, timeout } from 'rxjs/operators';
import { CommonService } from '../common/common.service';
import { Response } from '../models/response';
@Injectable({
providedIn: 'root'
})
export class ConnectorService {
/*
connection configuration settings
*/
static httpOptions = {
headers: new HttpHeaders({ 'Content-Type': 'application/json' })
};
public static retryTimes = 0;
public static timeOut = 30 * 1000;
// public static host = 'http://10.50.100.113:6060/'; // development service
// public static host = 'https://hmgwebservices.com/';
public static host = 'http://10.50.100.198:6060/'; // development service
/* public static host = 'http://10.200.204.101:6060/'; // video conference development
public static host = 'http://10.50.100.198:6060/';
public static host = 'http://10.50.100.198:6060/'; // development service
public static host = 'http://10.50.100.198:4040/'; // UAT service
public static host = 'http://10.50.100.198:4444/'; // production service
public static host = 'http://10.50.100.113:4040/'; // UAT service
public static host = 'http://10.50.100.113:4444/'; // production service
*/
/*
end of connection configuration
*/
constructor(
public httpClient: HttpClient,
public cs: CommonService
) { }
public post(service: string, data: any, onError: any, errorLabel?: string): Observable<any> {
this.cs.startLoading();
return this.httpClient.post<any>(ConnectorService.host + service, data, ConnectorService.httpOptions)
.pipe(
timeout(ConnectorService.timeOut),
retry(ConnectorService.retryTimes),
tap(
res => this.handleResponse(res, onError, errorLabel),
error => this.handleError(error, onError, errorLabel)
)
);
}
public postNoLoad(service: string, data: any, onError: any): Observable<any> {
return this.httpClient.post<any>(ConnectorService.host + service, data, ConnectorService.httpOptions)
.pipe(
retry(ConnectorService.retryTimes),
tap(() => { }, () => { })
);
}
// absolute url connection
public postToken(service: string, data: any, onError: any, errorLabel?: string): Observable<any> {
this.cs.startLoading();
return this.httpClient.post<any>(service, data, ConnectorService.httpOptions)
.pipe(
timeout(ConnectorService.timeOut),
retry(ConnectorService.retryTimes),
tap(res => this.handleResponse(res, onError, errorLabel),
error => this.handleError(error, onError, errorLabel)
)
);
}
public get(service: string, data: any, onError: any, errorLabel?: string): Observable<any> {
this.cs.startLoading();
return this.httpClient.get(service, ConnectorService.httpOptions)
.pipe(
timeout(ConnectorService.timeOut),
retry(ConnectorService.retryTimes),
tap(res => this.handleResponse(res, onError, errorLabel),
error => this.handleError(error, onError, errorLabel)
)
);
}
/*
load local json data and convert it to corresponding model
resourceURL such as 'assets/config.json'
*/
public getLocalResrouce(resourceURL: string): Observable<any> {
return this.httpClient.get(resourceURL);
}
/*
public validResponse(result: Response): boolean {
// error type == 2 means you have error
if (result.MessageStatus === 1) {
return true;
} else if (result.MessageStatus === 2) {
return this.cs.hasData(result['SameClinicApptList']);
}
return false;
}
*/
public handleError(error: any, onError: any, errorLabel: string) {
this.cs.stopLoading();
if (error instanceof TimeoutError) {
this.cs.showConnectionTimeout(onError, errorLabel);
} else {
this.cs.showConnectionErrorDialog(onError, errorLabel);
}
}
public handleResponse(result: Response, onError: any, errorLabel: string) {
this.cs.stopLoading();
if (!this.cs.validResponse(result)) {
// not authorized
if (result.ErrorType === 2) {
// this.cs.userNeedToReLogin();
} else {
this.cs.showErrorMessageDialog(onError, errorLabel, result.ErrorEndUserMessage);
}
}
}
public getURLText(url: string, onError: any, errorLabel?: string): Observable<any> {
this.cs.startLoading();
return this.httpClient.get(url)
.pipe(
timeout(ConnectorService.timeOut),
retry(ConnectorService.retryTimes),
tap(res => {
this.cs.stopLoading();
if (!res) {
this.cs.showConnectionErrorDialog(onError, errorLabel);
}
},
error => this.handleError(error, onError, errorLabel)
)
);
}
}

@ -0,0 +1,12 @@
import { TestBed } from '@angular/core/testing';
import { DevicePermissionsService } from './device-permissions.service';
describe('DevicePermissionsService', () => {
beforeEach(() => TestBed.configureTestingModule({}));
it('should be created', () => {
const service: DevicePermissionsService = TestBed.get(DevicePermissionsService);
expect(service).toBeTruthy();
});
});

@ -0,0 +1,104 @@
import { Injectable } from '@angular/core';
import { Diagnostic } from '@ionic-native/diagnostic/ngx';
import { CommonService } from 'src/app/hmg-common/services/common/common.service';
import { Observable } from 'rxjs';
import { SubjectSubscriber } from 'rxjs/internal/Subject';
@Injectable({
providedIn: 'root'
})
export class DevicePermissionsService {
public static granted = 'granted';
public camera;
public mic;
public storage;
public onSucess;
public onerror;
constructor(public diagnostic: Diagnostic,
public cs: CommonService) { }
public requestCameraPermission(camera: boolean, mic: boolean, storage: boolean): Observable<boolean> {
this.camera = camera;
this.mic = mic;
this.storage = storage;
return Observable.create( observer => {
this.requestCamera( observer);
});
}
public requestCamera(observer: any) {
this.diagnostic.isCameraAvailable().then((isAvailable) => {
if (isAvailable) {
if ( this.mic ) {
this.requestMicophonePermission(observer);
} else {
this.observerDone(observer, true);
}
} else {
this.diagnostic.requestCameraAuthorization(false).then((value) => {
// alert( JSON.stringify(value));
if (value.toLowerCase() === DevicePermissionsService.granted) {
if ( this.mic ) {
this.requestMicophonePermission(observer);
} else {
this.observerDone(observer, true);
}
} else {
this.cameraError(observer);
}
});
}
}, () => {
this.observerDone(observer, false);
});
}
private cameraError(observer) {
this.cs.presentConfirmDialog('camera permission required', () => {
this.requestCamera(observer);
}, () => {
this.observerDone(observer, false);
});
}
private requestMicophonePermission(observer: any) {
this.diagnostic.isMicrophoneAuthorized().then((isAvailable) => {
if (isAvailable) {
this.observerDone(observer, true);
} else {
this.diagnostic.requestMicrophoneAuthorization().then((value) => {
if (value.toLowerCase() === DevicePermissionsService.granted) {
this.observerDone(observer, true);
} else {
this.micError(observer);
}
});
}
}, () => {
this.observerDone(observer, false);
});
// // Checks microphone permissions
}
private micError(observer) {
this.cs.presentConfirmDialog('Michrophone permission required', () => {
this.requestMicophonePermission(observer);
}, () => {
this.observerDone(observer, false);
});
}
private observerDone (observer: any, success: boolean ) {
observer.next( success ) ;
observer.complete();
}
}

@ -0,0 +1,12 @@
import { TestBed } from '@angular/core/testing';
import { GeofencingService } from './geofencing.service';
describe('GeofencingService', () => {
beforeEach(() => TestBed.configureTestingModule({}));
it('should be created', () => {
const service: GeofencingService = TestBed.get(GeofencingService);
expect(service).toBeTruthy();
});
});

@ -0,0 +1,446 @@
import { Injectable } from '@angular/core';
import { BackgroundGeolocation, BackgroundGeolocationEvents } from '@ionic-native/background-geolocation/ngx';
import { BackgroundGeolocationConfig, BackgroundGeolocationResponse } from '@ionic-native/background-geolocation/ngx';
import { UserLocalNotificationService } from '../user-local-notification/user-local-notification.service';
import { Platform } from '@ionic/angular';
import { LocationModel } from './models/location.model';
import { ConnectorService } from '../connector/connector.service';
import { NativeStorage } from '@ionic-native/native-storage/ngx';
import { AuthenticationService } from '../authentication/authentication.service';
import { ZoneModel } from './models/zone.model';
import { CommonService } from '../common/common.service';
import { InsertLocationRequest } from './models/insert-location.request';
import { GeoUserModel } from './models/geo-user.model';
import { TranslatorService } from '../translator/translator.service';
export enum zoneState {
out = 0, enter = 1, exit = 2, in = 3
}
@Injectable({
providedIn: 'root'
})
export class GeofencingService {
public static ZONES_KEY = 'geofencing-zones';
public static USER_DATA_KEY = 'geofencing-user-data';
public static GEO_STATUS_KEY = 'geofencing-status';
public static zonesUrl = 'Services/Patients.svc/REST/GeoF_GetAllPoints';
public static loggingUrl = 'Services/Patients.svc/rest/GeoF_InsertPatientFileInfo';
private zonesList: ZoneModel [];
private userData: GeoUserModel;
private isPaused: boolean;
private debug: boolean;
locations: any [];
constructor(
private backgroundGeolocation: BackgroundGeolocation,
public notif: UserLocalNotificationService,
public platform: Platform,
public con: ConnectorService,
public auth: AuthenticationService,
public storage: NativeStorage,
public cs: CommonService,
public authService: AuthenticationService,
public ts: TranslatorService,
) {
this.debug = false;
}
/*
* logs location on server.
*/
private logLocation(id: number, type: number, userData: GeoUserModel, zone: ZoneModel) {
this.toast('logging location..');
this.setNotification('Logging location ' , 'location id: ' + id + ' type: ' + type);
const req = new InsertLocationRequest();
req.PointsID = id;
req.GeoType = type;
req.PatientID = userData.PatientID;
req.PatientOutSA = userData.PatientOutSA;
this.auth.setPublicFields(req);
this.con.postNoLoad(GeofencingService.loggingUrl, req, () => {
zone.pendingRequest = type; // failed to log, setup pending request
this.storeZones(this.zonesList);
this.log('pending request from onError');
this.setNotification('Pending request from onError', 'zone: ' + zone.Description + ' request type: ' + type);
}).subscribe((response) => {
if (this.cs.validResponse(response)) {
this.setNotification('Log success' , 'location id: ' + id + ' patientID: ' + userData.PatientID);
this.log('logged successfuly');
zone.pendingRequest = zoneState.out; // cancel pending requests if any
} else {
zone.pendingRequest = type; // failed to log, setup pending request
this.log('pending request from invalid');
this.setNotification('Pending request from invalid', 'zone: ' + zone.Description + ' request type: ' + type);
}
this.storeZones(this.zonesList);
});
}
/*
* Requests geofence zones list
*/
private requestZones() {
const req = this.auth.getPublicRequest();
this.con.postNoLoad(GeofencingService.zonesUrl, req, _ => { // TODO: handle error
}).subscribe((response: any) => {
if (this.cs.validResponse(response)) {
if (this.cs.hasData(response.GeoF_PointsList)) {
// update zonelist if it doesnt exist or if the server has an updated one
if (!this.cs.hasData(this.zonesList) || (this.zonesList.length !== response.GeoF_PointsList.length)) {
this.log('setting new zone list');
this.zonesList = response.GeoF_PointsList;
for (const zone of this.zonesList) {
zone.in = false;
}
this.log('storing zones');
this.storeZones(this.zonesList);
}
}
}
});
}
/*
* Store zones list in local storage
*/
public async storeZones(zones: ZoneModel []) {
return await this.storage.setItem(GeofencingService.ZONES_KEY, zones);
}
/*
* Retrieve and set list of zones from local storage
*/
public async setZones() {
try {
const data = await this.storage.getItem(GeofencingService.ZONES_KEY);
if (this.cs.hasData(data)) {
this.zonesList = data;
} else {
this.requestZones(); // zones list not stored in local storage
}
} catch {
this.requestZones(); // zones list not stored in local storage
}
}
public async storeUserData(user: GeoUserModel) {
return await this.storage.setItem(GeofencingService.USER_DATA_KEY, user);
}
/*
* Retrieve and set user data from local storage
*/
public async setUserFromStorage() {
const data = await this.storage.getItem(GeofencingService.USER_DATA_KEY);
if (data) {
this.userData = data;
} else {
this.userData = null;
}
}
/*
// turns location tracking on. Sets geo user data and zones list
*/
public async turnTrackingOn(patientID?: number, outSa?: number): Promise<boolean> {
this.toast('turning tracking on');
// set zones list from storage
await this.setZones();
// update zone list from server
this.requestZones();
// Set user data
if (patientID) {
this.userData = new GeoUserModel;
this.userData.PatientID = patientID;
this.userData.PatientOutSA = outSa;
} else if (!this.userData) {
try {
await this.setUserFromStorage();
} catch {
return false;
}
}
this.userData.isTrackingOn = true;
this.storeUserData(this.userData);
this.startTracking();
return true;
}
/*
// turns location tracking off. Stops background tracking
*/
public turnTrackingOff() {
this.toast('turning tracking off');
this.stopTracking();
if (this.userData) {
this.userData.isTrackingOn = false;
this.storeUserData(this.userData);
} else {
this.setUserFromStorage().then(() => {
this.userData.isTrackingOn = false;
this.storeUserData(this.userData);
});
}
}
/*
// Check if geofencing service is enabled
*/
public async isTrackingEnabled(): Promise<boolean> {
// if (this.userData) {
// return this.userData.isTrackingOn;
// } else {
try {
await this.setUserFromStorage();
if (this.userData) {
return this.userData.isTrackingOn;
} else {
return false;
}
} catch {
throw false;
}
// }
}
/*
// setup and start background gelocation plugin
*/
public startTracking() {
const config: BackgroundGeolocationConfig = {
desiredAccuracy: 10000, // HIGH_ACCURACY = 1 // low = 10000
stationaryRadius: 20, // 20
distanceFilter: 10, // 10
debug: false, // enable this hear sounds for background-geolocation life-cycle.
stopOnTerminate: false, // enable this to clear background location settings when the app terminates
// startOnBoot: true,
// Android options
notificationsEnabled: false,
interval: 60000, // interval vars for improved battery life
fastestInterval: 120000,
activitiesInterval: 10000,
startForeground: false,
notificationTitle: 'Running in the background',
notificationText: '',
// IOS options
saveBatteryOnBackground: false
};
this.backgroundGeolocation.configure(config)
.then((location: BackgroundGeolocationResponse) => {
});
this.backgroundGeolocation.on(BackgroundGeolocationEvents.location)
.subscribe((location: BackgroundGeolocationResponse) => {
this.reportLocation(location);
});
this.backgroundGeolocation.on(BackgroundGeolocationEvents.stationary)
.subscribe((location: BackgroundGeolocationResponse) => {
this.reportLocation(location);
});
this.storage.getItem(GeofencingService.GEO_STATUS_KEY).then(status => {
if (!status) {
this.backgroundGeolocation.start();
this.storage.setItem(GeofencingService.GEO_STATUS_KEY, true);
}
}).catch(() => {
this.toast('turning geofencing on');
this.backgroundGeolocation.start();
this.storage.setItem(GeofencingService.GEO_STATUS_KEY, true);
});
}
/*
// Helper to startTracking()
*/
private async reportLocation(location: BackgroundGeolocationResponse) {
// Check if zones and user is set
if (!this.userData) {
await this.setUserFromStorage();
}
if (!this.cs.hasData(this.zonesList)) {
await this.setZones();
}
if (this.platform.is('ios')) {
this.backgroundGeolocation.startTask().then((taskKey) => {
this.checklocationInZones(location, this.zonesList, this.userData);
this.backgroundGeolocation.endTask(taskKey);
});
} else {
this.checklocationInZones(location, this.zonesList, this.userData);
}
this.storeZones(this.zonesList);
}
/*
// stops background geoloacation plugin tracking
*/
public stopTracking() {
this.toast('Stop Tracking' );
this.storage.setItem(GeofencingService.GEO_STATUS_KEY, false);
this.backgroundGeolocation.stop().then(value => {
// this.toast('Stop Tracking value returned: ' + value);
});
}
/*
// Checks if given location triggers any zone events (enter, exit) for all zones, and pauses the service if
// the location was far from all zones
*/
private checklocationInZones(location: BackgroundGeolocationResponse, zones: ZoneModel [], user: GeoUserModel) {
this.printLocation(location, 'check location in zones');
let currentMinDist = 9999999;
for (const zone of zones) {
const userLocation = new LocationModel(location.latitude, location.longitude);
const event = this.checkLocationInZone(userLocation, zone);
const currentDistance = this.distanceFromZone(userLocation, zone);
currentMinDist = (currentMinDist > currentDistance ? currentDistance : currentMinDist);
if (zone.GEOF_ID === 16) {
this.log(zone.Description);
this.log('zone state: ' + zone.in + ' pending: ' + zone.pendingRequest + 'current event: ' + event);
}
if (event === zoneState.in) {
zone.in = true;
}
// send enter request
if (event === zoneState.enter ||
(event === zoneState.in && zone.pendingRequest === zoneState.enter)) {
zone.in = true;
this.setNotification('Enter ZONE ' + zone.Description, 'location lat: ' + location.latitude + ' lng: ' + location.longitude);
this.log('enter Zone' + zone.Description + ' ' + 'location: ' + location.latitude + ',' + location.longitude);
this.logLocation(zone.GEOF_ID, zoneState.enter, user, zone);
}
// send exit request
if (event === zoneState.exit ||
(event === zoneState.out && zone.pendingRequest === zoneState.exit)) {
zone.in = false;
this.setNotification('Exit ZONE ' + zone.Description, 'location lat: ' + location.latitude + ' lng: ' + location.longitude);
this.log('exit Zone' + zone.Description + ' ' + 'location: ' + location.latitude + ',' + location.longitude);
this.logLocation(zone.GEOF_ID, zoneState.exit, user, zone);
}
}
const minDist = this.toDecimalDegrees(5000); // minimum distance location needs to be to all zones to pause service
const maxDist = this.toDecimalDegrees(10000); // Max distance used to have a factor between 0-1
if (currentMinDist >= minDist) {
const currentDis = (currentMinDist > maxDist ? maxDist : currentMinDist);
this.pauseService((currentDis - minDist) / (maxDist - minDist));
}
}
/*
// Checks the state of given location for the given zone
*/
private checkLocationInZone(userLocation: LocationModel, zone: ZoneModel): zoneState {
const isIn = this.isPointInZone(userLocation.lng, userLocation.lat, zone.Longitude,
zone.Latitude, this.toDecimalDegrees(zone.Radius));
if (isIn === false && zone.in === true) {
return zoneState.exit;
}
if (isIn === true && zone.in === false) {
return zoneState.enter;
}
if (isIn) {
return zoneState.in;
}
return zoneState.out;
}
/*
// calculates the distance between given location and given zone
*/
private distanceFromZone(userLocation: LocationModel, zone: ZoneModel): number {
return this.distance(userLocation.lng, userLocation.lat, zone.Longitude, zone.Latitude);
}
/*
// checks if a point p is in a circular zone with center z and radius r
*/
public isPointInZone(xp, yp, xz, yz, r): boolean {
return this.distance(xp, yp, xz, yz) < r;
}
/*
// Measures distance between two points
*/
public distance(xp, yp, xz, yz): number {
return Math.sqrt(Math.pow(Math.abs(xp - xz), 2) + Math.pow(Math.abs(yp - yz) , 2));
}
/*
// Convert meters to decimal degrees
*/
public toDecimalDegrees(meters: number) {
return meters / 1000 / 111.32;
}
/*
// Pauses tracking service for a time multiplied by given factor
*/
public pauseService(factor: number) {
if (!this.isPaused) {
this.stopTracking();
this.isPaused = true;
// time to pause min=120 sec max=1800 sec
const time = (1680000 * factor); // time in milliseconds
this.setNotification('pausing tracking service', 'Pause for ' + time + ' FYI factor is: ' + factor);
setTimeout(() => {
this.startTracking();
this.isPaused = false;
this.setNotification('resuming tracking service', 'Paused for ' + time + ' FYI factor is: ' + factor);
}, time);
}
}
public startGeoFromHome() {
if (this.cs.isCordova()) {
this.isTrackingEnabled().then((result) => {
if (result) {
this.turnTrackingOff();
this.turnTrackingOn();
}
}).catch(() => {
// first time login, setup geofencing
// local storage should reset when user logs out
if (this.authService.isAuthenticated()) {
const user = this.authService.getAuthenticatedUser();
this.turnTrackingOff();
this.cs.presentConfirmDialog(this.ts.trPK('settings', 'enable-geo'), () => {
this.turnTrackingOn(user.PatientID, +user.PatientOutSA);
}, () => {
this.turnTrackingOn(user.PatientID, +user.PatientOutSA);
this.turnTrackingOff();
});
}
});
}
}
// ---------- TESTING FUNCTIONS -------------- //
public setNotification(title: string, text: string) {
if (this.debug) {
const date = new Date();
date.setSeconds(date.getSeconds() + 2);
this.notif.createNotification(title, text, date, 'geofencing');
}
}
public printLocation(location: BackgroundGeolocationResponse, source: string) {
if (this.debug) {
console.log('-------------------------------------------------------------');
console.log(source);
console.log(this.zonesList);
console.log(location);
console.log('location: ' + location.latitude + ', ' + location.longitude);
}
}
public printAllLocations() {
if (this.debug) {
this.backgroundGeolocation.getLocations().then(locations => {
console.log(locations);
});
}
}
public log(msg: string) {
if (this.debug) {
console.log(msg);
}
}
public toast(msg: string) {
if (this.debug) {
this.cs.toast(msg);
}
}
}

@ -0,0 +1,5 @@
export class GeoUserModel {
PatientID: number;
PatientOutSA: number;
isTrackingOn: boolean;
}

@ -0,0 +1,6 @@
import { Request } from 'src/app/hmg-common/services/models/request';
export class InsertLocationRequest extends Request {
PointsID: number;
GeoType: number; // 1 enter 2 exit
}

@ -0,0 +1,8 @@
export class LocationModel {
lat: number;
lng: number;
constructor(lat: number, lng: number, radius?: number, name?: string) {
this.lat = lat;
this.lng = lng;
}
}

@ -0,0 +1,17 @@
import { zoneState } from '../geofencing.service';
export class ZoneModel {
CreatedBy?: number;
CreatedOn?: string;
Description: string;
DescriptionN?: string;
GEOF_ID?: number;
IsCity?: boolean;
Latitude: string;
Longitude: string;
ProjectID?: number;
Radius: number;
Type?: number;
in: boolean;
pendingRequest: zoneState;
}

@ -0,0 +1,12 @@
import { TestBed } from '@angular/core/testing';
import { GuidService } from './guid.service';
describe('GuidService', () => {
beforeEach(() => TestBed.configureTestingModule({}));
it('should be created', () => {
const service: GuidService = TestBed.get(GuidService);
expect(service).toBeTruthy();
});
});

@ -0,0 +1,25 @@
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class GuidService {
constructor() { }
public generate(): string {
let result = '';
let i: string;
for ( let j = 0; j < 32; j++) {
if (j == 8 || j == 12 || j == 16 || j == 20)
{
result = result + '-';
}
i = Math.floor(Math.random() * 16).toString(16).toUpperCase();
result = result + i;
}
return result;
}
}

@ -0,0 +1,12 @@
import { TestBed } from '@angular/core/testing';
import { HmgBrowserService } from './hmg-browser.service';
describe('HmgBrowserService', () => {
beforeEach(() => TestBed.configureTestingModule({}));
it('should be created', () => {
const service: HmgBrowserService = TestBed.get(HmgBrowserService);
expect(service).toBeTruthy();
});
});

@ -0,0 +1,101 @@
import { Injectable } from '@angular/core';
import { ThemeableBrowser, ThemeableBrowserOptions, ThemeableBrowserObject } from '@ionic-native/themeable-browser/ngx';
import { Platform } from '@ionic/angular';
@Injectable({
providedIn: 'root'
})
export class HmgBrowserService {
static options: ThemeableBrowserOptions = {
statusbar: {
color: '#ffffffff'
},
toolbar: {
height: 44,
color: '#f0f0f0ff'
},
title: {
color: '#60686b',
showPageTitle: true
},
backButton: {
image: 'back',
imagePressed: 'back_pressed',
align: 'left',
event: 'backPressed'
},
forwardButton: {
image: 'forward',
imagePressed: 'forward_pressed',
align: 'left',
event: 'forwardPressed'
},
closeButton: {
image: 'close',
imagePressed: 'close_pressed',
align: 'left',
event: 'closePressed'
},
/*
customButtons: [
{
image: 'share',
imagePressed: 'share_pressed',
align: 'right',
event: 'sharePressed'
}
],
menu: {
image: 'menu',
imagePressed: 'menu_pressed',
title: 'Test',
cancel: 'Cancel',
align: 'right',
items: [
{
event: 'helloPressed',
label: 'Hello World!'
},
{
event: 'testPressed',
label: 'Test!'
}
]
},
*/
backButtonCanClose: true
};
private browser: ThemeableBrowserObject;
constructor(
private themeableBrowser: ThemeableBrowser,
private platform: Platform
) { }
public registerBack(event: any) {
this.registerEvent('backPressed', event);
}
public registerClose(event: any) {
this.registerEvent('closePressed', event);
}
private registerEvent(eventName: string, event: any) {
if (this.browser) {
this.browser.on(eventName).subscribe((data: any) => {
if (event) {
event();
}
});
}
}
public openURLThemable(url: string) {
this.platform.ready().then(() => {
this.browser = this.themeableBrowser.create(url, '_blank', HmgBrowserService.options);
});
}
}

@ -0,0 +1,4 @@
export class KeyboardStatusModel {
constructor ( public opened: boolean ) {
}
}

@ -0,0 +1,12 @@
import { TestBed } from '@angular/core/testing';
import { KeyboardService } from './keyboard.service';
describe('KeyboardService', () => {
beforeEach(() => TestBed.configureTestingModule({}));
it('should be created', () => {
const service: KeyboardService = TestBed.get(KeyboardService);
expect(service).toBeTruthy();
});
});

@ -0,0 +1,56 @@
import { Injectable, AfterViewInit } from "@angular/core";
import { Events, Platform } from "@ionic/angular";
import { CommonService } from "../common/common.service";
import { Keyboard } from "@ionic-native/keyboard/ngx";
import { KeyboardStatusModel } from "./keyboard-status.model";
@Injectable({
providedIn: "root"
})
export class KeyboardService {
public static KEYBOARD_STATUS = "keyboard-status-event";
public static keyboardOpened = false;
public static isOpened() {
return KeyboardService.keyboardOpened;
}
constructor(
public events: Events,
public cs: CommonService,
public keyboard: Keyboard,
public platform: Platform
) {}
public watchKeyboard() {
this.platform.ready().then(() => {
window.addEventListener('keyboardDidHide', () => {
this.publishEvent(false);
});
window.addEventListener('keyboardDidShow', () => {
this.publishEvent(true);
});
/*
this.keyboard.onKeyboardHide().subscribe( (observer) => {
});
this.keyboard.onKeyboardHide().subscribe(() => {
this.publishEvent(false);
});
this.keyboard.onKeyboardShow().subscribe(() => {
this.publishEvent(true);
});
*/
});
}
private publishEvent(opened: boolean) {
KeyboardService.keyboardOpened = opened;
this.events.publish(
KeyboardService.KEYBOARD_STATUS,
new KeyboardStatusModel(opened)
);
}
}

@ -0,0 +1,12 @@
import { TestBed } from '@angular/core/testing';
import { LazyLoadingService } from './lazy-loading.service';
describe('LazyLoadingService', () => {
beforeEach(() => TestBed.configureTestingModule({}));
it('should be created', () => {
const service: LazyLoadingService = TestBed.get(LazyLoadingService);
expect(service).toBeTruthy();
});
});

@ -0,0 +1,78 @@
import { Injectable } from "@angular/core";
import { CommonService } from "../common/common.service";
import {
Router,
RouteConfigLoadStart,
RouteConfigLoadEnd
} from "@angular/router";
import { Route } from "@angular/compiler/src/core";
import { TranslatorService } from "../translator/translator.service";
@Injectable({
providedIn: "root"
})
export class LazyLoadingService {
private static id = "splash-screen-custom";
private modulesCount = 5;
private loadedModulesCount = 0;
private isPresented = false;
constructor(public ts: TranslatorService, public router: Router) {
this.startSplashScreen();
}
monitorLazyLoading(modulesCount: number, debug = false) {
this.modulesCount = modulesCount;
this.loadedModulesCount = 0;
this.router.events.subscribe(event => {
if (event instanceof RouteConfigLoadStart) {
//console.log('start:' + event.route.path);
this.startSplashScreen();
} else if (event instanceof RouteConfigLoadEnd) {
//console.log('end:' + event.route.path);
if (++this.loadedModulesCount >= this.modulesCount) {
this.dismiss();
}
if ( debug ) {
console.log('module:' + event.route.path + ' lazy modules:' + this.loadedModulesCount);
}
}
});
}
public startSplashScreen() {
if (!this.isPresented) {
this.isPresented = true;
document.body.appendChild(this.createSplashScreen());
this.disableEventsPropagation();
}
}
private disableEventsPropagation() {
const view = document.getElementById(LazyLoadingService.id);
view.addEventListener("click", e => {
e.stopImmediatePropagation();
});
}
public dismiss() {
// this.isPresented = false;
const element = document.getElementById(LazyLoadingService.id);
if (element) {
element.remove();
}
}
private innerTemplate(message: string): string {
return " <div class='splash' ></div> " + " <p>" + message + "</p>";
}
private createSplashScreen() {
const elemDiv = document.createElement("div");
elemDiv.id = LazyLoadingService.id;
elemDiv.className = "splash-screen-page";
//elemDiv.innerHTML = this.innerTemplate(this.ts.trPK('general', 'loading'));
return elemDiv;
}
}

@ -0,0 +1,12 @@
import { TestBed } from '@angular/core/testing';
import { LifeCycleService } from './life-cycle.service';
describe('LifeCycleService', () => {
beforeEach(() => TestBed.configureTestingModule({}));
it('should be created', () => {
const service: LifeCycleService = TestBed.get(LifeCycleService);
expect(service).toBeTruthy();
});
});

@ -0,0 +1,34 @@
import { Injectable } from '@angular/core';
import { Router, NavigationEnd, NavigationStart } from '@angular/router';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class LifeCycleService {
constructor(
public router: Router
) { }
public pageRevisited(pageName: string): Observable<boolean> {
return Observable.create(observer => {
this.router.events.subscribe((val) => {
if (this.isSamePage(val, pageName)) {
observer.next(true);
observer.complete();
}
});
});
}
private isSamePage(val: any, pageName: string) {
if (val instanceof NavigationEnd) {
const lastIndex = val.urlAfterRedirects.lastIndexOf('/');
const currentPageName = val.urlAfterRedirects.substr(lastIndex + 1);
return currentPageName === pageName;
}
return false;
}
}

@ -0,0 +1,9 @@
import { Request } from './request';
export class AppointmentRequest extends Request{
public AppointmentNo: number;
public setAppointment(no: number) {
this.AppointmentNo = no;
}
}

@ -0,0 +1,19 @@
import { Request } from './request';
export class EmailRequest extends Request {
DoctorName: string;
ProjectName: string;
ClinicName: string; // personal information
ProjectID: number;
DateofBirth: string; // json date personal information
PatientIditificationNum: string;
PatientMobileNumber: string;
PatientName: string;
PatientOutSA: number;
PatientTypeID: number;
To: string; // user email
SetupID: string;
OrderDate: string; // iso date
InvoiceNo: string;
}

@ -0,0 +1,9 @@
export class ExaminationInfo {
ProjectName: string;
ClinicName: string;
DoctorName: string;
ProjectID: string;
OrderDate: string;
}

@ -0,0 +1,5 @@
// tslint:disable-next-line:class-name
export enum GENDER_TYPE {
MAN = 1,
WOMAN = 2
}

@ -0,0 +1,4 @@
export enum PATIENT_POSITION {
INSIDE_KSA = 0,
OUTSIDE_KSA = 1
}

@ -0,0 +1,4 @@
export enum PATIENT_TYPE {
TEMPORARILY = 0,
PERMANENT = 1
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save