diff --git a/Mohem/src/app/app-routing.module.ts b/Mohem/src/app/app-routing.module.ts index 80ad7002..42c149de 100644 --- a/Mohem/src/app/app-routing.module.ts +++ b/Mohem/src/app/app-routing.module.ts @@ -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({ diff --git a/Mohem/src/app/app.component.html b/Mohem/src/app/app.component.html index 13b96776..ed86517c 100644 --- a/Mohem/src/app/app.component.html +++ b/Mohem/src/app/app.component.html @@ -1,3 +1,83 @@ - - - + + + + + + + + + + + \ No newline at end of file diff --git a/Mohem/src/app/app.component.scss b/Mohem/src/app/app.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/Mohem/src/app/app.component.ts b/Mohem/src/app/app.component.ts index c0a8a233..b517eacd 100644 --- a/Mohem/src/app/app.component.ts +++ b/Mohem/src/app/app.component.ts @@ -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(); - }); - } + } } diff --git a/Mohem/src/app/app.module.ts b/Mohem/src/app/app.module.ts index 23c4e847..ff360cf4 100644 --- a/Mohem/src/app/app.module.ts +++ b/Mohem/src/app/app.module.ts @@ -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, diff --git a/Mohem/src/app/authentication/agreement/agreement.component.html b/Mohem/src/app/authentication/agreement/agreement.component.html new file mode 100644 index 00000000..03b2a285 --- /dev/null +++ b/Mohem/src/app/authentication/agreement/agreement.component.html @@ -0,0 +1,28 @@ + + + + {{ 'general,usage-agreement' | translate}} + + + + + + + + +
+
+
+
+ +
+ +
\ No newline at end of file diff --git a/Mohem/src/app/authentication/agreement/agreement.component.scss b/Mohem/src/app/authentication/agreement/agreement.component.scss new file mode 100644 index 00000000..389579c4 --- /dev/null +++ b/Mohem/src/app/authentication/agreement/agreement.component.scss @@ -0,0 +1,9 @@ +.agreement_area{ + width: 100%; + height: 80%; +} + +.html-container { + width: 96%; + padding: 2%; +} \ No newline at end of file diff --git a/Mohem/src/app/authentication/agreement/agreement.component.spec.ts b/Mohem/src/app/authentication/agreement/agreement.component.spec.ts new file mode 100644 index 00000000..ba35ec0e --- /dev/null +++ b/Mohem/src/app/authentication/agreement/agreement.component.spec.ts @@ -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; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ AgreementComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(AgreementComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/authentication/agreement/agreement.component.ts b/Mohem/src/app/authentication/agreement/agreement.component.ts new file mode 100644 index 00000000..ea0eba1c --- /dev/null +++ b/Mohem/src/app/authentication/agreement/agreement.component.ts @@ -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(); + }); + } + + + +} diff --git a/Mohem/src/app/authentication/agreement/service/agreement.service.spec.ts b/Mohem/src/app/authentication/agreement/service/agreement.service.spec.ts new file mode 100644 index 00000000..40cca2a5 --- /dev/null +++ b/Mohem/src/app/authentication/agreement/service/agreement.service.spec.ts @@ -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(); + }); +}); diff --git a/Mohem/src/app/authentication/agreement/service/agreement.service.ts b/Mohem/src/app/authentication/agreement/service/agreement.service.ts new file mode 100644 index 00000000..b0a61f25 --- /dev/null +++ b/Mohem/src/app/authentication/agreement/service/agreement.service.ts @@ -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 { + 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 { + 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 { + const request = new AddUserAgreementRequest(); + request.Region = 1; + this.auth.authenticateRequest(request); + request.TokenID = ''; + return this.con.post(AgreementService.addAgreementURL, request, onError, errorLabel); + } +} + diff --git a/Mohem/src/app/authentication/agreement/service/models/add-user-agreement.request.ts b/Mohem/src/app/authentication/agreement/service/models/add-user-agreement.request.ts new file mode 100644 index 00000000..63132b81 --- /dev/null +++ b/Mohem/src/app/authentication/agreement/service/models/add-user-agreement.request.ts @@ -0,0 +1,5 @@ +import { Request } from 'src/app/hmg-common/services/models/request'; + +export class AddUserAgreementRequest extends Request { + Region: number; // 1 +} diff --git a/Mohem/src/app/authentication/agreement/service/models/check-user-agreement.request.ts b/Mohem/src/app/authentication/agreement/service/models/check-user-agreement.request.ts new file mode 100644 index 00000000..171dc392 --- /dev/null +++ b/Mohem/src/app/authentication/agreement/service/models/check-user-agreement.request.ts @@ -0,0 +1,5 @@ +import { Request } from 'src/app/hmg-common/services/models/request'; + +export class CheckUserAgreementRequest extends Request { + Region: number; // 1 +} diff --git a/Mohem/src/app/authentication/agreement/service/models/check-user-agreement.response.ts b/Mohem/src/app/authentication/agreement/service/models/check-user-agreement.response.ts new file mode 100644 index 00000000..d133e4f2 --- /dev/null +++ b/Mohem/src/app/authentication/agreement/service/models/check-user-agreement.response.ts @@ -0,0 +1,5 @@ +import { Response } from 'src/app/hmg-common/services/models/response'; + +export class CheckUserAgreementResponse extends Response { + IsPatientAlreadyAgreed: boolean; +} diff --git a/Mohem/src/app/authentication/agreement/service/models/get-user-agreement.response.ts b/Mohem/src/app/authentication/agreement/service/models/get-user-agreement.response.ts new file mode 100644 index 00000000..e4e919c5 --- /dev/null +++ b/Mohem/src/app/authentication/agreement/service/models/get-user-agreement.response.ts @@ -0,0 +1,5 @@ +import { Response } from 'src/app/hmg-common/services/models/response'; + +export class GetUserAgreementResponse extends Response { + UserAgreementContent: string; +} diff --git a/Mohem/src/app/authentication/authentication.module.ts b/Mohem/src/app/authentication/authentication.module.ts new file mode 100644 index 00000000..ec3ac30b --- /dev/null +++ b/Mohem/src/app/authentication/authentication.module.ts @@ -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 { } diff --git a/Mohem/src/app/authentication/authentication.page.html b/Mohem/src/app/authentication/authentication.page.html new file mode 100644 index 00000000..be09efff --- /dev/null +++ b/Mohem/src/app/authentication/authentication.page.html @@ -0,0 +1,14 @@ + + + + + + diff --git a/Mohem/src/app/authentication/authentication.page.scss b/Mohem/src/app/authentication/authentication.page.scss new file mode 100644 index 00000000..e69de29b diff --git a/Mohem/src/app/authentication/authentication.page.spec.ts b/Mohem/src/app/authentication/authentication.page.spec.ts new file mode 100644 index 00000000..5a216506 --- /dev/null +++ b/Mohem/src/app/authentication/authentication.page.spec.ts @@ -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; + + 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(); + }); +}); diff --git a/Mohem/src/app/authentication/authentication.page.ts b/Mohem/src/app/authentication/authentication.page.ts new file mode 100644 index 00000000..cf85a9a4 --- /dev/null +++ b/Mohem/src/app/authentication/authentication.page.ts @@ -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() { + } + +} diff --git a/Mohem/src/app/authentication/forgot/forgot.component.html b/Mohem/src/app/authentication/forgot/forgot.component.html new file mode 100644 index 00000000..10daa70b --- /dev/null +++ b/Mohem/src/app/authentication/forgot/forgot.component.html @@ -0,0 +1,37 @@ + + + + {{'login,forgot-id' | translate}} + + + + + + + + +

{{ 'login,forgot-desc'| translate}}

+
+
+ + + + + + + + +
+ +
+
+ + + + + {{'general,submit' | translate}} + + + +
+
\ No newline at end of file diff --git a/Mohem/src/app/authentication/forgot/forgot.component.scss b/Mohem/src/app/authentication/forgot/forgot.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/Mohem/src/app/authentication/forgot/forgot.component.spec.ts b/Mohem/src/app/authentication/forgot/forgot.component.spec.ts new file mode 100644 index 00000000..e0cba717 --- /dev/null +++ b/Mohem/src/app/authentication/forgot/forgot.component.spec.ts @@ -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; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ForgotComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ForgotComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/authentication/forgot/forgot.component.ts b/Mohem/src/app/authentication/forgot/forgot.component.ts new file mode 100644 index 00000000..8b7f7e30 --- /dev/null +++ b/Mohem/src/app/authentication/forgot/forgot.component.ts @@ -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); + } + }); + + } + + +} diff --git a/Mohem/src/app/authentication/login/login.component.html b/Mohem/src/app/authentication/login/login.component.html new file mode 100644 index 00000000..2ff2cd15 --- /dev/null +++ b/Mohem/src/app/authentication/login/login.component.html @@ -0,0 +1,47 @@ + + + + + + + + + + +

{{'login,title' | translate}}

+
+
+
+ + + + {{'login,userName' | translate}} + + + + + + + {{'login,password' | translate}} + + + + + +
+ + +
+ +
+ +
+
+ +
+
+ \ No newline at end of file diff --git a/Mohem/src/app/authentication/login/login.component.scss b/Mohem/src/app/authentication/login/login.component.scss new file mode 100644 index 00000000..d0b80bd5 --- /dev/null +++ b/Mohem/src/app/authentication/login/login.component.scss @@ -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; + + // } + } + } + + diff --git a/Mohem/src/app/authentication/login/login.component.spec.ts b/Mohem/src/app/authentication/login/login.component.spec.ts new file mode 100644 index 00000000..d6d85a84 --- /dev/null +++ b/Mohem/src/app/authentication/login/login.component.spec.ts @@ -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; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ LoginComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(LoginComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/authentication/login/login.component.ts b/Mohem/src/app/authentication/login/login.component.ts new file mode 100644 index 00000000..73647d97 --- /dev/null +++ b/Mohem/src/app/authentication/login/login.component.ts @@ -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"); + } +} diff --git a/Mohem/src/app/hmg-common/custom-reuse.strategy.ts b/Mohem/src/app/hmg-common/custom-reuse.strategy.ts new file mode 100644 index 00000000..d99a5474 --- /dev/null +++ b/Mohem/src/app/hmg-common/custom-reuse.strategy.ts @@ -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; + } +} diff --git a/Mohem/src/app/hmg-common/hmg-common.module.spec.ts b/Mohem/src/app/hmg-common/hmg-common.module.spec.ts new file mode 100644 index 00000000..4b28be6c --- /dev/null +++ b/Mohem/src/app/hmg-common/hmg-common.module.spec.ts @@ -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(); + }); +}); diff --git a/Mohem/src/app/hmg-common/hmg-common.module.ts b/Mohem/src/app/hmg-common/hmg-common.module.ts new file mode 100644 index 00000000..efc962c2 --- /dev/null +++ b/Mohem/src/app/hmg-common/hmg-common.module.ts @@ -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 { } + + + + diff --git a/Mohem/src/app/hmg-common/pipes/date-time/date-time.pipe.spec.ts b/Mohem/src/app/hmg-common/pipes/date-time/date-time.pipe.spec.ts new file mode 100644 index 00000000..f43d9e8f --- /dev/null +++ b/Mohem/src/app/hmg-common/pipes/date-time/date-time.pipe.spec.ts @@ -0,0 +1,8 @@ +import { DateTimePipe } from './date-time.pipe'; + +describe('DateTimePipe', () => { + it('create an instance', () => { + const pipe = new DateTimePipe(); + expect(pipe).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/pipes/date-time/date-time.pipe.ts b/Mohem/src/app/hmg-common/pipes/date-time/date-time.pipe.ts new file mode 100644 index 00000000..71825edc --- /dev/null +++ b/Mohem/src/app/hmg-common/pipes/date-time/date-time.pipe.ts @@ -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(); + } + +} diff --git a/Mohem/src/app/hmg-common/pipes/date/date.pipe.spec.ts b/Mohem/src/app/hmg-common/pipes/date/date.pipe.spec.ts new file mode 100644 index 00000000..10b10f5f --- /dev/null +++ b/Mohem/src/app/hmg-common/pipes/date/date.pipe.spec.ts @@ -0,0 +1,8 @@ +import { DatePipe } from './date.pipe'; + +describe('DatePipe', () => { + it('create an instance', () => { + const pipe = new DatePipe(); + expect(pipe).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/pipes/date/date.pipe.ts b/Mohem/src/app/hmg-common/pipes/date/date.pipe.ts new file mode 100644 index 00000000..842b149e --- /dev/null +++ b/Mohem/src/app/hmg-common/pipes/date/date.pipe.ts @@ -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; + } + + +} + diff --git a/Mohem/src/app/hmg-common/pipes/date/if-date.pipe.spec.ts b/Mohem/src/app/hmg-common/pipes/date/if-date.pipe.spec.ts new file mode 100644 index 00000000..e7b619d0 --- /dev/null +++ b/Mohem/src/app/hmg-common/pipes/date/if-date.pipe.spec.ts @@ -0,0 +1,8 @@ +import { IfDatePipe } from './if-date.pipe'; + +describe('IfDatePipe', () => { + it('create an instance', () => { + const pipe = new IfDatePipe(); + expect(pipe).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/pipes/date/if-date.pipe.ts b/Mohem/src/app/hmg-common/pipes/date/if-date.pipe.ts new file mode 100644 index 00000000..497c6ff9 --- /dev/null +++ b/Mohem/src/app/hmg-common/pipes/date/if-date.pipe.ts @@ -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; + } + } + + +} diff --git a/Mohem/src/app/hmg-common/pipes/empty-field/empty-field.pipe.spec.ts b/Mohem/src/app/hmg-common/pipes/empty-field/empty-field.pipe.spec.ts new file mode 100644 index 00000000..e90e46cb --- /dev/null +++ b/Mohem/src/app/hmg-common/pipes/empty-field/empty-field.pipe.spec.ts @@ -0,0 +1,8 @@ +import { EmptyFieldPipe } from './empty-field.pipe'; + +describe('EmptyFieldPipe', () => { + it('create an instance', () => { + const pipe = new EmptyFieldPipe(); + expect(pipe).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/pipes/empty-field/empty-field.pipe.ts b/Mohem/src/app/hmg-common/pipes/empty-field/empty-field.pipe.ts new file mode 100644 index 00000000..e9ea151d --- /dev/null +++ b/Mohem/src/app/hmg-common/pipes/empty-field/empty-field.pipe.ts @@ -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 : '-'; + } + +} diff --git a/Mohem/src/app/hmg-common/pipes/keys/keys.pipe.spec.ts b/Mohem/src/app/hmg-common/pipes/keys/keys.pipe.spec.ts new file mode 100644 index 00000000..9232fbfd --- /dev/null +++ b/Mohem/src/app/hmg-common/pipes/keys/keys.pipe.spec.ts @@ -0,0 +1,8 @@ +import { KeysPipe } from './keys.pipe'; + +describe('KeysPipe', () => { + it('create an instance', () => { + const pipe = new KeysPipe(); + expect(pipe).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/pipes/keys/keys.pipe.ts b/Mohem/src/app/hmg-common/pipes/keys/keys.pipe.ts new file mode 100644 index 00000000..dc2c001e --- /dev/null +++ b/Mohem/src/app/hmg-common/pipes/keys/keys.pipe.ts @@ -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); + } + +} diff --git a/Mohem/src/app/hmg-common/pipes/safe-html/safe-html.pipe.spec.ts b/Mohem/src/app/hmg-common/pipes/safe-html/safe-html.pipe.spec.ts new file mode 100644 index 00000000..a1904fc7 --- /dev/null +++ b/Mohem/src/app/hmg-common/pipes/safe-html/safe-html.pipe.spec.ts @@ -0,0 +1,8 @@ +import { SafeHtmlPipe } from './safe-html.pipe'; + +describe('SafeHtmlPipe', () => { + it('create an instance', () => { + const pipe = new SafeHtmlPipe(); + expect(pipe).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/pipes/safe-html/safe-html.pipe.ts b/Mohem/src/app/hmg-common/pipes/safe-html/safe-html.pipe.ts new file mode 100644 index 00000000..d1209ebd --- /dev/null +++ b/Mohem/src/app/hmg-common/pipes/safe-html/safe-html.pipe.ts @@ -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'), '
'); + return this.sanitizer.bypassSecurityTrustHtml(html); + } else { + return html.replace(new RegExp('\n', 'g'), '
'); + } + } + +} diff --git a/Mohem/src/app/hmg-common/pipes/time/time.pipe.spec.ts b/Mohem/src/app/hmg-common/pipes/time/time.pipe.spec.ts new file mode 100644 index 00000000..c6d58571 --- /dev/null +++ b/Mohem/src/app/hmg-common/pipes/time/time.pipe.spec.ts @@ -0,0 +1,8 @@ +import { TimePipe } from './time.pipe'; + +describe('TimePipe', () => { + it('create an instance', () => { + const pipe = new TimePipe(); + expect(pipe).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/pipes/time/time.pipe.ts b/Mohem/src/app/hmg-common/pipes/time/time.pipe.ts new file mode 100644 index 00000000..2c367964 --- /dev/null +++ b/Mohem/src/app/hmg-common/pipes/time/time.pipe.ts @@ -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(); + } +} diff --git a/Mohem/src/app/hmg-common/pipes/translate/translate.pipe.spec.ts b/Mohem/src/app/hmg-common/pipes/translate/translate.pipe.spec.ts new file mode 100644 index 00000000..888cfa85 --- /dev/null +++ b/Mohem/src/app/hmg-common/pipes/translate/translate.pipe.spec.ts @@ -0,0 +1,8 @@ +import { TranslatePipe } from './translate.pipe'; + +describe('TranslatePipe', () => { + it('create an instance', () => { + const pipe = new TranslatePipe(); + expect(pipe).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/pipes/translate/translate.pipe.ts b/Mohem/src/app/hmg-common/pipes/translate/translate.pipe.ts new file mode 100644 index 00000000..0de0775e --- /dev/null +++ b/Mohem/src/app/hmg-common/pipes/translate/translate.pipe.ts @@ -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 ''; + } + +} diff --git a/Mohem/src/app/hmg-common/services/authentication/authentication.service.spec.ts b/Mohem/src/app/hmg-common/services/authentication/authentication.service.spec.ts new file mode 100644 index 00000000..91a1e97e --- /dev/null +++ b/Mohem/src/app/hmg-common/services/authentication/authentication.service.spec.ts @@ -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(); + }); +}); diff --git a/Mohem/src/app/hmg-common/services/authentication/authentication.service.ts b/Mohem/src/app/hmg-common/services/authentication/authentication.service.ts new file mode 100644 index 00000000..0a70b492 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/authentication/authentication.service.ts @@ -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 { + 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 { + + 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 { + 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 { + this.setPublicFields(request); + request.TokenID = ''; + return this.con.post(AuthenticationService.registerTempUserURL, request, onError, errorLabel); + } + + public getLoginInfo(request: GetLoginInfoRequest, onError: any, errorLabel: string) + : Observable { + 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 { + + 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 { + 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 { + 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 { + this.setPublicFields(request); + return this.con.post(AuthenticationService.checkUserAuthURL, request, onError, errorLabel); + } + + public checkActivationCode(request: CheckActivationCodeRequest, onError: any, errorLabel: string) + : Observable { + 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 { + 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 { + 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 { + this.setPublicFields(request); + return this.con.post(AuthenticationService.activationCodeURL, request, onError, errorLabel); + } + + public sendSMSForForgotFileNumber(request: CheckUserAuthenticationRequest, onError: any, errorLabel: string) + : Observable { + 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 { + 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 { + + 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(); + } + }); + } + + } + + + + +} + + diff --git a/Mohem/src/app/hmg-common/services/authentication/models/PatientUserModel.ts b/Mohem/src/app/hmg-common/services/authentication/models/PatientUserModel.ts new file mode 100644 index 00000000..dddfa041 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/authentication/models/PatientUserModel.ts @@ -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; + +} diff --git a/Mohem/src/app/hmg-common/services/authentication/models/authenticated-user.ts b/Mohem/src/app/hmg-common/services/authentication/models/authenticated-user.ts new file mode 100644 index 00000000..8c17a3e4 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/authentication/models/authenticated-user.ts @@ -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; +} diff --git a/Mohem/src/app/hmg-common/services/authentication/models/check-activation-code.request.ts b/Mohem/src/app/hmg-common/services/authentication/models/check-activation-code.request.ts new file mode 100644 index 00000000..6a68265f --- /dev/null +++ b/Mohem/src/app/hmg-common/services/authentication/models/check-activation-code.request.ts @@ -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; +} diff --git a/Mohem/src/app/hmg-common/services/authentication/models/check-activation-code.response.ts b/Mohem/src/app/hmg-common/services/authentication/models/check-activation-code.response.ts new file mode 100644 index 00000000..2ce565f3 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/authentication/models/check-activation-code.response.ts @@ -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; +} diff --git a/Mohem/src/app/hmg-common/services/authentication/models/check-patient-registeration.request.ts b/Mohem/src/app/hmg-common/services/authentication/models/check-patient-registeration.request.ts new file mode 100644 index 00000000..8968bdde --- /dev/null +++ b/Mohem/src/app/hmg-common/services/authentication/models/check-patient-registeration.request.ts @@ -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; +} diff --git a/Mohem/src/app/hmg-common/services/authentication/models/check-registeration-code.request.ts b/Mohem/src/app/hmg-common/services/authentication/models/check-registeration-code.request.ts new file mode 100644 index 00000000..412ab906 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/authentication/models/check-registeration-code.request.ts @@ -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; +} diff --git a/Mohem/src/app/hmg-common/services/authentication/models/check-user-auth.request.ts b/Mohem/src/app/hmg-common/services/authentication/models/check-user-auth.request.ts new file mode 100644 index 00000000..5121f239 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/authentication/models/check-user-auth.request.ts @@ -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; +} diff --git a/Mohem/src/app/hmg-common/services/authentication/models/check-user-auth.response.ts b/Mohem/src/app/hmg-common/services/authentication/models/check-user-auth.response.ts new file mode 100644 index 00000000..e7e942f0 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/authentication/models/check-user-auth.response.ts @@ -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; +} diff --git a/Mohem/src/app/hmg-common/services/authentication/models/forgot-File-ID.response.ts b/Mohem/src/app/hmg-common/services/authentication/models/forgot-File-ID.response.ts new file mode 100644 index 00000000..11e1b53f --- /dev/null +++ b/Mohem/src/app/hmg-common/services/authentication/models/forgot-File-ID.response.ts @@ -0,0 +1,5 @@ +import { Response } from '../../models/response'; + +export class ForgotFileIDResponse extends Response { + ReturnMessage: string; +} diff --git a/Mohem/src/app/hmg-common/services/authentication/models/get-login-info.request.ts b/Mohem/src/app/hmg-common/services/authentication/models/get-login-info.request.ts new file mode 100644 index 00000000..a7ec111c --- /dev/null +++ b/Mohem/src/app/hmg-common/services/authentication/models/get-login-info.request.ts @@ -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; + } +} \ No newline at end of file diff --git a/Mohem/src/app/hmg-common/services/authentication/models/get-login-info.response.ts b/Mohem/src/app/hmg-common/services/authentication/models/get-login-info.response.ts new file mode 100644 index 00000000..8377746f --- /dev/null +++ b/Mohem/src/app/hmg-common/services/authentication/models/get-login-info.response.ts @@ -0,0 +1,8 @@ +import { Response } from '../../models/response'; + +export class GetLoginInfoResponse extends Response { + SMSLoginRequired: boolean; + isSMSSent: boolean; + LogInTokenID: string; + PatientOutSA: boolean; +} \ No newline at end of file diff --git a/Mohem/src/app/hmg-common/services/authentication/models/login.request.ts b/Mohem/src/app/hmg-common/services/authentication/models/login.request.ts new file mode 100644 index 00000000..5d6b3511 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/authentication/models/login.request.ts @@ -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 +} diff --git a/Mohem/src/app/hmg-common/services/authentication/models/register-information-patient.model.ts b/Mohem/src/app/hmg-common/services/authentication/models/register-information-patient.model.ts new file mode 100644 index 00000000..1e8fd2e5 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/authentication/models/register-information-patient.model.ts @@ -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; +} diff --git a/Mohem/src/app/hmg-common/services/authentication/models/register-information.request.ts b/Mohem/src/app/hmg-common/services/authentication/models/register-information.request.ts new file mode 100644 index 00000000..722f7137 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/authentication/models/register-information.request.ts @@ -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; + } +} diff --git a/Mohem/src/app/hmg-common/services/auto-connect/auto-connect.service.spec.ts b/Mohem/src/app/hmg-common/services/auto-connect/auto-connect.service.spec.ts new file mode 100644 index 00000000..ca191fd1 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/auto-connect/auto-connect.service.spec.ts @@ -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(); + }); +}); \ No newline at end of file diff --git a/Mohem/src/app/hmg-common/services/auto-connect/auto-connect.service.ts b/Mohem/src/app/hmg-common/services/auto-connect/auto-connect.service.ts new file mode 100644 index 00000000..5225bf0f --- /dev/null +++ b/Mohem/src/app/hmg-common/services/auto-connect/auto-connect.service.ts @@ -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 { + //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'), () => { }) + + } + + } + +} \ No newline at end of file diff --git a/Mohem/src/app/hmg-common/services/auto-connect/models/credential-wifi.modal.ts b/Mohem/src/app/hmg-common/services/auto-connect/models/credential-wifi.modal.ts new file mode 100644 index 00000000..4e558f19 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/auto-connect/models/credential-wifi.modal.ts @@ -0,0 +1,6 @@ +export class CredentialWifiModel{ + + UserName:number; + Password:number; + +} \ No newline at end of file diff --git a/Mohem/src/app/hmg-common/services/auto-connect/models/credential-wifi.request.ts b/Mohem/src/app/hmg-common/services/auto-connect/models/credential-wifi.request.ts new file mode 100644 index 00000000..f9f37431 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/auto-connect/models/credential-wifi.request.ts @@ -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; +} \ No newline at end of file diff --git a/Mohem/src/app/hmg-common/services/auto-connect/models/credential-wifi.response.ts b/Mohem/src/app/hmg-common/services/auto-connect/models/credential-wifi.response.ts new file mode 100644 index 00000000..84bc7c48 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/auto-connect/models/credential-wifi.response.ts @@ -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[]; +} diff --git a/Mohem/src/app/hmg-common/services/common/common.service.copy.txt b/Mohem/src/app/hmg-common/services/common/common.service.copy.txt new file mode 100644 index 00000000..5ee5d7d9 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/common/common.service.copy.txt @@ -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]); + } + + +} diff --git a/Mohem/src/app/hmg-common/services/common/common.service.spec.ts b/Mohem/src/app/hmg-common/services/common/common.service.spec.ts new file mode 100644 index 00000000..e2b75483 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/common/common.service.spec.ts @@ -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(); + }); +}); diff --git a/Mohem/src/app/hmg-common/services/common/common.service.ts b/Mohem/src/app/hmg-common/services/common/common.service.ts new file mode 100644 index 00000000..5788c677 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/common/common.service.ts @@ -0,0 +1,1244 @@ +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, DatePipe } 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"; +import { ProgressLoadingService } from "../../ui/progressLoading/progress-loading.service"; +import { Observable, throwError } from "rxjs"; +import { SharedDataService } from "../shared-data-service/shared-data.service"; +import { Badge } from "@ionic-native/badge/ngx"; +import { LifeCycleService } from "../life-cycle/life-cycle.service"; +import { Diagnostic } from '@ionic-native/diagnostic/ngx'; +import { CallNumber } from '@ionic-native/call-number/ngx'; +import { InAppBrowser } from '@ionic-native/in-app-browser/ngx'; + + + +@Injectable({ + providedIn: "root" +}) +export class CommonService { + + public static months_en_long = [ + "January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December" + ]; + public static months_en = [ + "Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dec" + ]; + public static months_ar = [ + "يناير", + "فبراير", + "مارس", + "أبريل", + "مايو", + "يونيو", + "يوليو", + "أغسطس", + "سبتمبر", + "أكتوبر", + "نوفمبر", + "ديسمبر" + ]; + + private progressLoaders: any[] = []; + private loadingProgress: any; + constructor( + public nav: NavController, + public router: Router, + public location: Location, + public ts: TranslatorService, + public loadingController: LoadingController, + public progressLoadingService: ProgressLoadingService, + public toastController: ToastController, + public alertController: AlertControllerService, + public alertControllerIonic: AlertController, + public themeableBrowser: ThemeableBrowser, + public launchNavigation: LaunchNavigator, + public platform: Platform, + public device: Device, + public sharedService: SharedDataService, + public badge: Badge, + public lifeCycle: LifeCycleService, + public diagnostic: Diagnostic, + public callNumber: CallNumber, + public iab: InAppBrowser + ) { } + + public back() { + // this.nav.pop(); + this.nav.back({ + animated: true, + animationDirection: "back" + }); + } + + 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", "close") + }); + toast.present(); + } + + private loaderIsActive = false; + async startLoadingOld() { + 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 startLoading() { + /*this.stopLoading(small); + this.progressLoadingService.presentLoading( this.ts.trPK("general", "loading") , small ); + */ + this.stopLoading(); + this.progressLoadingService.presentLoading(this.ts.trPK("general", "loading")); + } + + public mobileNumber(number: string) { + return number.substr(1, number.length - 1); + } + public testFunction() { } + + public stopLoading() { + this.progressLoadingService.dismiss(); + } + + public presentAlert(message: string, onAccept?: any) { + this.alertDialog( + () => { + if (onAccept) { + onAccept(); + } + }, + 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"), + onCancel, + this.ts.trPK("general", "cancel"), + this.ts.trPK("general", "confirm"), + message + ); + } + + public presentAcceptDialog(message: string, onAccept: any) { + this.alertDialog( + onAccept, + this.ts.trPK("general", "ok"), + this.ts.trPK("general", "confirm"), + message + ); + } + + public confirmBackDialog(message: string) { + this.alertDialog( + () => { + this.back(); + }, + this.ts.trPK("general", "ok"), + this.ts.trPK("general", "info"), + message + ); + } + public confirmNotAllowedDialog() { + this.openHome(); + this.alertDialog( + () => { + }, + this.ts.trPK("general", "ok"), + this.ts.trPK("general", "info"), + this.ts.trPK("general", "not-allowed") + ); + } + + public showErrorMessageDialog( + onClick: any, + okLabel: string, + message: string + ) { + this.alertDialog( + onClick, + okLabel, + this.ts.trPK("general", "alert"), + message + ); + } + + public userNeedToReLogin() { + this.presentConfirmDialog(this.ts.trPK("general", "relogin"), () => { + this.openUserLogin(); + }); + } + + public showConnectionErrorDialog(onClick: any, okLabel: string) { + this.alertDialog( + onClick, + okLabel, + this.ts.trPK("general", "alert"), + this.ts.trPK("error", "conn") + ); + } + + public showConnectionTimeout(onClick: any, okLabel: string) { + this.alertDialog( + onClick, + okLabel, + this.ts.trPK("general", "alert"), + this.ts.trPK("error", "timeout") + ); + } + + 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", + cssClass: 'cancel-button', + handler: () => { + if (onCancel) { + onCancel(); + } + this.alertControllerIonic.dismiss(); + } + }, + { + text: acceptLabel, + handler: () => { + if (onAccept) { + onAccept(); + } + this.alertControllerIonic.dismiss(); + } + } + ] + }); + // this.alerts.push(alert); + await alert.present(); + } + + async confirmAlertDialogPrimarySecondary( + onPrimary: any, + primaryLabel: string, + onSecondary: any, + secondaryLabel: string, + title: string, + message: string + ) { + this.clearAllAlerts(); + const alert = await this.alertControllerIonic.create({ + header: this.ts.trPK("general", "confirm"), + message: message, + buttons: [ + { + text: primaryLabel, + handler: () => { + onPrimary(); + this.alertControllerIonic.dismiss(); + } + }, + { + text: secondaryLabel, + handler: () => { + onSecondary(); + this.alertControllerIonic.dismiss(); + } + } + ] + }); + 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(); + } + + async loginAlertDialog(acceptLabel: string, title: string, message: string) { + this.clearAllAlerts(); + const alert = await this.alertControllerIonic.create({ + header: title, + message: message, + backdropDismiss: false, + buttons: [ + { + text: acceptLabel, + handler: () => { + this.openUserLogin(); + this.alertControllerIonic.dismiss(); + } + } + ] + }); + // this.alerts.push(alert); + await alert.present(); + } + + public clearAllAlerts() { + // custom solutions because of async issue + const alerts = document.getElementsByTagName("ion-alert"); + for (let i = 0; i < alerts.length; i++) { + const alert = alerts[i]; + alert.parentNode.removeChild(alert); + } + } + + 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, onExit?, onFaild?, onSuccess?, successURLS?: string[]) { + console.log(url); + if (this.isCordova()) { + this.openBrowserInApp(url, onExit, onFaild, onSuccess, successURLS); + } else { + this.openBrowserHtml(url, onExit, onFaild, onSuccess); + } + } + + private openBrowserHtml(url, onExit?, onFaild?, onSuccess?) { + + const browser = window.open(url, '_blank', 'location=no'); + browser.addEventListener('loadstart', () => { + }); + + browser.addEventListener('loaderror', () => { + if (onFaild) { + onFaild(); + } + }); + browser.addEventListener('loadstop', () => { + if (onSuccess) { + onSuccess(); + } + }); + + } + + private openBrowserInApp(url: string, onExit?, onFaild?, onSuccess?, successURLS?: string[]) { + this.platform.ready().then(() => { + const browser = this.iab.create(url, '_blank', 'closebuttoncolor=#60686b,hidenavigationbuttons=yes,hideurlbar=yes,zoom=no'); + + // browser.executeScript(...); + + // browser.insertCSS(...); + browser.on('loaderror').subscribe(event => { + if (onFaild) { + onFaild(); + } + browser.close(); + }); + + + /* + browser.on('loadstop').subscribe(event => { + // browser.insertCSS({ code: 'body{color: white;}' }); + if (onSuccess) { + onSuccess(); + } + }); + */ + + browser.on('exit').subscribe(event => { + if (onExit) { + onExit(); + } + }); + + browser.on('loadstart').subscribe(event => { + + if ( successURLS ) { + successURLS.forEach((successURL, index) => { + if (event.url && (event.url.indexOf(successURL) >= 0)) { + // alert('load start found success url'); + browser.close(); + if (onSuccess) { + onSuccess(); + } + } + }); + } + }); + + }); + } + + + + + public imageFromBase64(base64: string) { + return "data:image/jpeg;base64," + base64; + } + + public openLocation(lat: number, lng: number) { + this.platform.ready().then(() => { + this.launchNavigation.navigate([lat, lng]).then( + () => { }, + err => { + // this.failedToOpenMap(); + window.open('https://maps.google.com/?q=' + lat + ',' + lng); + } + ); + }); + } + private failedToOpenMap() { + this.presentAlert(this.ts.trPK("error", "map")); + + } + + public localizeTime(date: Date) { + if (!(date.getHours() == 0 && date.getMinutes() == 0)) { + let h = date.getHours() % 12 || 12; + let hStr = h < 10 ? "0" + h : h; // leading 0 at the left for 1 digit hours + const m = date.getMinutes(); + let mStr = m < 10 ? "0" + m : m; + return hStr + ":" + mStr + (date.getHours() < 12 ? " AM" : " PM"); + } + return ""; + } + + public localizeDate(date: Date, time = false) { + const lng = TranslatorService.getCurrentLanguageName(); + let dateStr; + if (lng === TranslatorService.AR) { + dateStr = CommonService.months_ar[date.getMonth()] + ' ' + date.getDate() + ' ' + date.getFullYear(); + } else { + dateStr = CommonService.months_en[date.getMonth()] + ' ' + date.getDate() + ',' + date.getFullYear(); + } + + return time ? dateStr + ' ' + this.localizeTime(date) : dateStr; + } + + public localizeMonth(monthIndex) { + const lng = TranslatorService.getCurrentLanguageName(); + if (lng === TranslatorService.AR) { + return CommonService.months_ar[monthIndex]; + } else { + return CommonService.months_en[monthIndex]; + } + } + + public evaluteDate(dateStr: string, time = false): string { + if (dateStr) { + const utc = parseInt(dateStr.substring(6, dateStr.length - 2), 10); + if (utc) { + const date = new Date(utc); + if (date instanceof Date && !isNaN(date.getTime())) { + // return this.datePipe.transform( appoDate, 'dd-MM-yyyy'); + return this.localizeDate(date, time); + } + } + } + return dateStr; + } + + public evaluateDateShort(dateStr: string): string { + const date = this.evaluteDateAsObject(dateStr); + if (date) { + return date.getMonth() + 1 + "/" + date.getFullYear().toString().substr(2); + } else { + return '--'; + } + } + public convertISODateToJsonDate(isoDate: string): string { + return "/Date(" + Date.parse(isoDate) + ")/"; + } + public convertDateToJsonDate(date: Date): string { + return "/Date(" + date.getTime() + ")/"; + } + + /* + date iso format + and time is 24 format hh:mm:ss + */ + public convertIsoDateToObject(isoDate: string, isoTime: string): Date { + const date = new Date(isoDate); + const parts = isoTime.split(':'); + if (this.hasData(parts)) { + // remove if numbers start with 0 + let hrsStr = parts[0]; + let msStr = parts[1]; + hrsStr = hrsStr[0] == '0' ? hrsStr.substr(1) : hrsStr; + msStr = msStr[0] == '0' ? msStr.substr(1) : msStr; + date.setHours(Number(hrsStr)); + date.setMinutes(Number(msStr)); + } + return date; + } + public evaluateDateWithTimeZoneOffset(dateStr: string): Date { + if (dateStr) { + const utc = parseInt(dateStr.substring(6, dateStr.length - 2), 10); + let date = new Date(utc); + let timezoneOffset: number = date.getTimezoneOffset() * 60000; + date.setTime(date.getTime() + timezoneOffset); + return date; + } + return null + } + + 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() { } + + private smsAlertDialog = null; + public presentSMSPasswordDialog( + onAccept: any, + smsCode?: string, + title?: string + ) { + this.dismissSMSDialog().subscribe(removed => { + this.createSMSPAsswordDialog(onAccept, smsCode, title); + }); + } + async createSMSPAsswordDialog( + onAccept: any, + smsCode?: string, + title?: string + ) { + this.smsAlertDialog = await this.alertControllerIonic.create({ + header: title || this.ts.trPK("general", "enter-sms-code"), + inputs: [ + { + name: "sms", + type: "number", + value: smsCode, + placeholder: this.ts.trPK("general", "enter-sms") + } + ], + buttons: [ + { + text: this.ts.trPK("general", "cancel"), + role: "cancel", + cssClass: 'cancel-button', + handler: () => { } + }, + { + text: this.ts.trPK("general", "ok"), + handler: data => { + onAccept(data.sms); + } + } + ] + }); + + await this.smsAlertDialog.present(); + } + + public getStartOfDay(date: Date): Date { + date.setHours(0, 0, 0, 0); + return date; + } + + public dismissSMSDialog(): Observable { + return Observable.create(observer => { + this.alertControllerIonic.getTop().then( + () => { + this.alertControllerIonic.dismiss().then( + () => { + observer.next(true); + observer.complete(); + }, + () => { + observer.next(false); + observer.complete(); + } + ); + }, + () => { + observer.next(false); + observer.complete(); + } + ); + }); + } + + public getStartOfToday(): number { + const date = new Date(); + date.setHours(0, 0, 0, 0); + return date.getTime(); + } + + public getGraphSeries( + xLabels: string[], + data: number[], + title: string, + color: string, + fill = false + ): any { + return { + labels: xLabels, + datasets: [ + { + label: title, + data: data, + fill: fill, + borderColor: color, + backgroundColor: color + } + ] + }; + } + public getGraphDataSet(title: string, data: number[], color: string, fill = false) { + return { + label: title, + data: data, + fill: fill, + borderColor: color, + backgroundColor: color + }; + } + public getGraphMultiSeries(xLabels: string[], datasets: any[]): any { + return { + labels: xLabels, + datasets: datasets + }; + } + + public get2SeriesMultiGraphData(dataList: any[], value1Key, title1, value2Key, title2, labels: string[]) { + const series1: number[] = []; + const series2: number[] = []; + + for (const data of dataList) { + series1.push(data[value1Key]); + series2.push(data[value2Key]); + } + + const dataSets = [ + this.getGraphDataSet(this.ts.trInline(title1), series1, '#d12026'), + this.getGraphDataSet(this.ts.trInline(title2), series2, '#60686b') + ]; + return this.getGraphMultiSeries(labels, dataSets); + } + + async setBadge(count: number) { + this.platform.ready().then(() => { + if (count > 0) { + this.badge.set(count); + } else { + this.badge.clear(); + } + }); + } + + public isHtml5VideoSupported(): boolean { + const v = document.createElement("video"); + if (v.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"')) { + return true; + } + if (v.canPlayType('video/ogg; codecs="theora, vorbis"')) { + return true; + } + if (v.canPlayType('video/webm; codecs="vp8, vorbis"')) { + return true; + } + return false; + } + + public isCordova(): boolean { + return this.platform.is("cordova"); + } + + public pageRevisited(pageName: string): Observable { + return this.lifeCycle.pageRevisited(pageName); + } + + /* + open calls + */ + + public static APPOINTMENTS_URLS = ["/eservices/appointments/home", "/eservices/appointments/home-page"]; + public openAppointments() { + this.alternateNavigate(CommonService.APPOINTMENTS_URLS, "appointments-home"); + } + + public openAppointmentsRoot() { + this.alternateNavigate( + ["/eservices/appointments/home", "/eservices/appointments/home-page"], + "appo-home", + true + ); + } + + public static HOME_URL = ["/home", "/home-page"]; + public openHome() { + this.alternateNavigate(CommonService.HOME_URL, "home-open", true); + } + + 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 navigateByURL(url: string) { + this.router.navigateByUrl(url); + // this.router.navigateByUrl([url); + } + + public navigateForward(url: string) { + this.nav.navigateForward([url]); + } + public navigateBack(url: string) { + this.nav.navigateBack([url]); + } + public static ESERVICES_URL = "/eservices/home"; + public openEservices() { + this.nav.navigateForward([CommonService.ESERVICES_URL]); + // this.router.navigateByUrl('/eservices/home'); + } + public openBookings() { + this.nav.navigateForward(["/eservices/doctors/search"]); + } + public static APPOINTMENTS_DETAILS = ["/eservices/appointments/details", "/eservices/appointments/details-page"]; + public openAppointmentDetails() { + this.alternateNavigate(CommonService.APPOINTMENTS_DETAILS, 'appointment-details'); + } + + public openCheckInAppointments() { + this.nav.navigateForward('/eservices/appointments/check-in'); + } + + private alternateNavigate(paths: string[], key: string, root = false) { + let url: string; + if (localStorage.getItem(key) === "yes") { + localStorage.setItem(key, "no"); + url = paths[0]; + } else { + localStorage.setItem(key, "yes"); + url = paths[1]; + } + if (root) { + this.nav.navigateRoot([url]); + } else { + this.nav.navigateForward([url]); + } + } + + public openConference() { + // alert("openConference"); + this.alternateNavigate( + ["/video-conference/call", "/video-conference/call-push"], + "conference-push" + ); + } + public openCamera() { + this.nav.navigateForward(["/video-conference/camera"]); + } + + public openVitalSigns() { + this.nav.navigateForward(["/eservices/vital-signs/home"]); + } + public openVitalSignsDetails() { + this.nav.navigateForward(["/eservices/vital-signs/details"]); + } + public openWeatherForcast() { + this.nav.navigateForward(["/weather-forecast"]); + } + + public openApprovals() { + this.nav.navigateForward(["/eservices/approvals"]); + // this.router.navigateByUrl('/eservices/approvals'); + } + public openPrescriptions() { + this.nav.navigateForward(["/eservices/prescriptions/home"]); + // 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 openConverterCalculationPage() { + console.log("opening page"); + this.nav.navigateForward(["/converters/converters-calculation/home"]); + } + public openDoctorSchedule() { + this.nav.navigateForward(["/eservices/doctors/schedule"]); + // this.router.navigateByUrl('/eservices/appointments/doctor-schedule'); + } + + public openRadiologyExaminations() { + this.nav.navigateForward(["/eservices/radiology/examinations"]); + // this.router.navigateByUrl('/eservices/radiology'); + } + public openAllergies() { + this.nav.navigateForward(["/eservices/allergies"]); + } + public openRadiologyReport() { + this.nav.navigateForward(["/eservices/radiology/report"]); + // this.router.navigateByUrl('/eservices/radiology/report'); + } + public openRadiologyReports() { + this.nav.navigateForward(["/eservices/radiology/reports"]); + // 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/orders"]); + // 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 static BLOOD_PRESSURE = ["/eservices/tracker/blood-pressure", "/eservices/tracker/blood-pressure-home"]; + public openBloodPressure() { + // this.alternateNavigate( CommonService.BLOOD_PRESSURE , 'blood-pressure-home'); + this.nav.navigateForward(["/eservices/tracker/blood-pressure"]); + } + + public openBloodSugar() { + // this.alternateNavigate( CommonService.BLOOD_PRESSURE , 'blood-pressure-home'); + this.nav.navigateForward(["/eservices/tracker/blood-sugar"]); + } + + 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 openDoctorsList() { + this.nav.navigateForward(["/eservices/doctors/doctors-list"]); + } + public openBookingDentalComplains() { + this.nav.navigateForward(["/eservices/doctors/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.alternateNavigate(["/eservices/child-vaccine/child-list", + "/eservices/child-vaccine/child-vacc-list"], 'child-vaccine-child-list'); + // this.nav.navigateForward(["/eservices/child-vaccine/child-list"]); + } + + public openChildVaccineLogin() { + this.nav.navigateForward(["/eservices/child-vaccine/login"]); + } + + public openAskDocRequest() { + this.nav.navigateForward(["/eservices/ask-doc/ask-doc-request"]); + } + + public openNewMedReport() { + this.nav.navigateForward(["/eservices/med-report/new-med-report"]); + } + + public openUserLogin() { + // this.nav.navigateForward(['/authentication/login']); + this.nav.navigateRoot(["/authentication/home"]); + } + + public openAgreement() { + this.nav.navigateForward(["/authentication/agreement"]); + } + public openUserRegister() { + this.nav.navigateForward(["/authentication/register"]); + } + public openUserRegisterInformation() { + this.nav.navigateForward(["/authentication/register-information"]); + } + public openUserForgot() { + this.nav.navigateForward(["/authentication/forgot"]); + } + + public openFeedback() { + this.nav.navigateForward(["/feedback/home"]); + } + public openFeedbackStatusDetails() { + this.nav.navigateForward(["/feedback/status-details"]); + } + public openReferralDetails() { + this.nav.navigateForward(["/ereferral/referral-details"]); + } + public loadReferralHome() { + this.nav.navigateForward(["/home"]); + } + public openH2OUpdateUser() { + this.nav.navigateForward(["/h2o/register"]); + } + + public openH2OHome() { + this.nav.navigateForward(["/h2o/home"]); + } + + public openH2OSMS() { + this.nav.navigateForward(["/h2o/sms"]); + } + + public openH2oLogin() { + this.nav.navigateForward(["/h2o/login"]); + } + + public openBloodDonationRegister() { + this.nav.navigateForward(["/blood-donation/home"]); + } + + public openBloodDonationLogin() { + this.nav.navigateForward(["/blood-donation/blood-donation-login"]); + } + public openNews() { + this.nav.navigateForward(["/news"]); + } + public openLocations() { + this.nav.navigateForward(["/locations"]); + } + + public openNotificationDetails() { + this.alternateNavigate( + [ + "/eservices/notifications/detail", + "/eservices/notifications/detail-push" + ], + "notification-push" + ); + } + public static NOTIFICATIONS_URL = "/eservices/notifications/center"; + public openNotifications() { + this.navigateForward(CommonService.NOTIFICATIONS_URL); + } + + public static FAMILY_FILES = "/eservices/family-files/home"; + public openFamilyFiles() { + this.nav.navigateForward([CommonService.FAMILY_FILES]); + } + + public openPatientProfile() { + this.nav.navigateForward(["/eservices/patient-profile"]); + } + + + public navigateTo(url: string) { + this.nav.navigateForward([url]); + } + + public keysInObject(obj): any[] { + const keys: any = []; + if (obj != null) { + for (const key in obj) { + keys.push(key); + } + } + return keys.length > 0 ? keys : null; + } + + public keysCountInObject(obj): number { + let count = 0; + if (obj != null) { + for (const key in obj) { + count++; + } + } + + return count; + } + + public checkBlueTooth(feedback: any) { + this.platform.ready().then(() => { + + this.diagnostic.getBluetoothState() + .then((state) => { + if (state == this.diagnostic.bluetoothState.POWERED_ON) { + feedback(); + } else { + this.presentAlert(this.ts.trPK('bluetooth', 'start')); + } + }).catch(e => { + this.presentAlert(this.ts.trPK('bluetooth', 'start')) + }); + }); + + } + + public callPhoneNumber(phoneNumber: string) { + this.platform.ready().then(() => { + if (this.isCordova()) { + this.callNumber.callNumber(phoneNumber, true) + .then(res => { }).catch(err => { }); + } else { + window.open('tel:' + phoneNumber); + // this.presentAlert(this.ts.trPK('error', 'call')); + } + }); + } + +} diff --git a/Mohem/src/app/hmg-common/services/common/models/browser-config.ts b/Mohem/src/app/hmg-common/services/common/models/browser-config.ts new file mode 100644 index 00000000..8cb6822b --- /dev/null +++ b/Mohem/src/app/hmg-common/services/common/models/browser-config.ts @@ -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' + }; +} diff --git a/Mohem/src/app/hmg-common/services/common/models/input-data.ts b/Mohem/src/app/hmg-common/services/common/models/input-data.ts new file mode 100644 index 00000000..376cad35 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/common/models/input-data.ts @@ -0,0 +1,7 @@ +import { Component } from '@angular/core'; + + +export class InputData { + value: any; + values: any []; +} diff --git a/Mohem/src/app/hmg-common/services/connector/connector.service.spec.ts b/Mohem/src/app/hmg-common/services/connector/connector.service.spec.ts new file mode 100644 index 00000000..9b175357 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/connector/connector.service.spec.ts @@ -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(); + }); +}); diff --git a/Mohem/src/app/hmg-common/services/connector/connector.service.ts b/Mohem/src/app/hmg-common/services/connector/connector.service.ts new file mode 100644 index 00000000..2cb40649 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/connector/connector.service.ts @@ -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 { + + this.cs.startLoading(); + return this.httpClient.post(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 { + return this.httpClient.post(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 { + this.cs.startLoading(); + return this.httpClient.post(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 { + 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 { + 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 { + 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) + ) + ); + } +} diff --git a/Mohem/src/app/hmg-common/services/device-permissions/device-permissions.service.spec.ts b/Mohem/src/app/hmg-common/services/device-permissions/device-permissions.service.spec.ts new file mode 100644 index 00000000..d379841a --- /dev/null +++ b/Mohem/src/app/hmg-common/services/device-permissions/device-permissions.service.spec.ts @@ -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(); + }); +}); diff --git a/Mohem/src/app/hmg-common/services/device-permissions/device-permissions.service.ts b/Mohem/src/app/hmg-common/services/device-permissions/device-permissions.service.ts new file mode 100644 index 00000000..f8b19616 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/device-permissions/device-permissions.service.ts @@ -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 { + 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(); + } +} diff --git a/Mohem/src/app/hmg-common/services/geofencing/geofencing.service.spec.ts b/Mohem/src/app/hmg-common/services/geofencing/geofencing.service.spec.ts new file mode 100644 index 00000000..e4a9d164 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/geofencing/geofencing.service.spec.ts @@ -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(); + }); +}); diff --git a/Mohem/src/app/hmg-common/services/geofencing/geofencing.service.ts b/Mohem/src/app/hmg-common/services/geofencing/geofencing.service.ts new file mode 100644 index 00000000..ec86cfb1 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/geofencing/geofencing.service.ts @@ -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 { + 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 { + // 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); + } + } +} diff --git a/Mohem/src/app/hmg-common/services/geofencing/models/geo-user.model.ts b/Mohem/src/app/hmg-common/services/geofencing/models/geo-user.model.ts new file mode 100644 index 00000000..fb3a17f3 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/geofencing/models/geo-user.model.ts @@ -0,0 +1,5 @@ +export class GeoUserModel { + PatientID: number; + PatientOutSA: number; + isTrackingOn: boolean; +} diff --git a/Mohem/src/app/hmg-common/services/geofencing/models/insert-location.request.ts b/Mohem/src/app/hmg-common/services/geofencing/models/insert-location.request.ts new file mode 100644 index 00000000..d85177a5 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/geofencing/models/insert-location.request.ts @@ -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 +} diff --git a/Mohem/src/app/hmg-common/services/geofencing/models/location.model.ts b/Mohem/src/app/hmg-common/services/geofencing/models/location.model.ts new file mode 100644 index 00000000..2bcd2035 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/geofencing/models/location.model.ts @@ -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; + } +} diff --git a/Mohem/src/app/hmg-common/services/geofencing/models/zone.model.ts b/Mohem/src/app/hmg-common/services/geofencing/models/zone.model.ts new file mode 100644 index 00000000..52c5e443 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/geofencing/models/zone.model.ts @@ -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; +} diff --git a/Mohem/src/app/hmg-common/services/guid/guid.service.spec.ts b/Mohem/src/app/hmg-common/services/guid/guid.service.spec.ts new file mode 100644 index 00000000..6c585846 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/guid/guid.service.spec.ts @@ -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(); + }); +}); diff --git a/Mohem/src/app/hmg-common/services/guid/guid.service.ts b/Mohem/src/app/hmg-common/services/guid/guid.service.ts new file mode 100644 index 00000000..e9bbb6eb --- /dev/null +++ b/Mohem/src/app/hmg-common/services/guid/guid.service.ts @@ -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; + } + +} diff --git a/Mohem/src/app/hmg-common/services/hmg-browser/hmg-browser.service.spec.ts b/Mohem/src/app/hmg-common/services/hmg-browser/hmg-browser.service.spec.ts new file mode 100644 index 00000000..23f3edc6 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/hmg-browser/hmg-browser.service.spec.ts @@ -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(); + }); +}); diff --git a/Mohem/src/app/hmg-common/services/hmg-browser/hmg-browser.service.ts b/Mohem/src/app/hmg-common/services/hmg-browser/hmg-browser.service.ts new file mode 100644 index 00000000..a901e164 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/hmg-browser/hmg-browser.service.ts @@ -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); + }); + } + + + +} diff --git a/Mohem/src/app/hmg-common/services/keyboard/keyboard-status.model.ts b/Mohem/src/app/hmg-common/services/keyboard/keyboard-status.model.ts new file mode 100644 index 00000000..62c8122c --- /dev/null +++ b/Mohem/src/app/hmg-common/services/keyboard/keyboard-status.model.ts @@ -0,0 +1,4 @@ +export class KeyboardStatusModel { + constructor ( public opened: boolean ) { + } +} \ No newline at end of file diff --git a/Mohem/src/app/hmg-common/services/keyboard/keyboard.service.spec.ts b/Mohem/src/app/hmg-common/services/keyboard/keyboard.service.spec.ts new file mode 100644 index 00000000..1c856717 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/keyboard/keyboard.service.spec.ts @@ -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(); + }); +}); diff --git a/Mohem/src/app/hmg-common/services/keyboard/keyboard.service.ts b/Mohem/src/app/hmg-common/services/keyboard/keyboard.service.ts new file mode 100644 index 00000000..027b0d58 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/keyboard/keyboard.service.ts @@ -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) + ); + } +} diff --git a/Mohem/src/app/hmg-common/services/lazy-loading/lazy-loading.service.spec.ts b/Mohem/src/app/hmg-common/services/lazy-loading/lazy-loading.service.spec.ts new file mode 100644 index 00000000..235c20b1 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/lazy-loading/lazy-loading.service.spec.ts @@ -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(); + }); +}); diff --git a/Mohem/src/app/hmg-common/services/lazy-loading/lazy-loading.service.ts b/Mohem/src/app/hmg-common/services/lazy-loading/lazy-loading.service.ts new file mode 100644 index 00000000..073e5883 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/lazy-loading/lazy-loading.service.ts @@ -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 "
" + "

" + message + "

"; + } + 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; + } +} diff --git a/Mohem/src/app/hmg-common/services/life-cycle/life-cycle.service.spec.ts b/Mohem/src/app/hmg-common/services/life-cycle/life-cycle.service.spec.ts new file mode 100644 index 00000000..e227f9e2 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/life-cycle/life-cycle.service.spec.ts @@ -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(); + }); +}); diff --git a/Mohem/src/app/hmg-common/services/life-cycle/life-cycle.service.ts b/Mohem/src/app/hmg-common/services/life-cycle/life-cycle.service.ts new file mode 100644 index 00000000..308d0419 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/life-cycle/life-cycle.service.ts @@ -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 { + 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; + } +} diff --git a/Mohem/src/app/hmg-common/services/models/appointment-request.ts b/Mohem/src/app/hmg-common/services/models/appointment-request.ts new file mode 100644 index 00000000..1d2bd14c --- /dev/null +++ b/Mohem/src/app/hmg-common/services/models/appointment-request.ts @@ -0,0 +1,9 @@ +import { Request } from './request'; + +export class AppointmentRequest extends Request{ + public AppointmentNo: number; + + public setAppointment(no: number) { + this.AppointmentNo = no; + } +} diff --git a/Mohem/src/app/hmg-common/services/models/email-request.ts b/Mohem/src/app/hmg-common/services/models/email-request.ts new file mode 100644 index 00000000..e14cdca1 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/models/email-request.ts @@ -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; + +} diff --git a/Mohem/src/app/hmg-common/services/models/examination-info.ts b/Mohem/src/app/hmg-common/services/models/examination-info.ts new file mode 100644 index 00000000..c5e29905 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/models/examination-info.ts @@ -0,0 +1,9 @@ + +export class ExaminationInfo { + ProjectName: string; + ClinicName: string; + DoctorName: string; + ProjectID: string; + OrderDate: string; +} + diff --git a/Mohem/src/app/hmg-common/services/models/gender.type.ts b/Mohem/src/app/hmg-common/services/models/gender.type.ts new file mode 100644 index 00000000..5af23108 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/models/gender.type.ts @@ -0,0 +1,5 @@ +// tslint:disable-next-line:class-name +export enum GENDER_TYPE { + MAN = 1, + WOMAN = 2 +} diff --git a/Mohem/src/app/hmg-common/services/models/patient.position.type.ts b/Mohem/src/app/hmg-common/services/models/patient.position.type.ts new file mode 100644 index 00000000..dbe5d386 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/models/patient.position.type.ts @@ -0,0 +1,4 @@ +export enum PATIENT_POSITION { + INSIDE_KSA = 0, + OUTSIDE_KSA = 1 +} diff --git a/Mohem/src/app/hmg-common/services/models/patient.type.ts b/Mohem/src/app/hmg-common/services/models/patient.type.ts new file mode 100644 index 00000000..e07e11c5 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/models/patient.type.ts @@ -0,0 +1,4 @@ +export enum PATIENT_TYPE { + TEMPORARILY = 0, + PERMANENT = 1 +} diff --git a/Mohem/src/app/hmg-common/services/models/request.ts b/Mohem/src/app/hmg-common/services/models/request.ts new file mode 100644 index 00000000..d88b96f0 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/models/request.ts @@ -0,0 +1,18 @@ +export class Request { + public ClinicID: number; + public PatientOutSA: number; + public PatientID: number; + public ProjectID: number; + public LanguageID: number; + public IPAdress: string; + public VersionID: number; + public Channel: number; + public PatientTypeID: number; + public isDentalAllowedBackend: boolean; + public IsIrisPrescription: boolean; + public TokenID: string; + public SessionID: string; + public PatientIdentificationID: string; + public PatientMobileNumber: string; + public BookedBy?: number; +} diff --git a/Mohem/src/app/hmg-common/services/models/response.ts b/Mohem/src/app/hmg-common/services/models/response.ts new file mode 100644 index 00000000..cd054b8f --- /dev/null +++ b/Mohem/src/app/hmg-common/services/models/response.ts @@ -0,0 +1,17 @@ +export class Response { + public LanguageID?: number; + public ErrorCode; + public ErrorEndUserMessage; + public ErrorMessage; + public ErrorType: number; + public FoodCategory: number; + public IsAuthenticated: boolean; + public IsRegister: boolean; + /* + 1 success + 2 error + */ + public MessageStatus: number; + public SuccessMsg; + +} diff --git a/Mohem/src/app/hmg-common/services/models/toggle.ts b/Mohem/src/app/hmg-common/services/models/toggle.ts new file mode 100644 index 00000000..58ab0d8c --- /dev/null +++ b/Mohem/src/app/hmg-common/services/models/toggle.ts @@ -0,0 +1,14 @@ +export class Toggle { + public value: boolean; + constructor(value: boolean) { + this.value = value; + } + + public switch() { + this.value = !this.value; + } + + public show() { + this.value = true; + } +} diff --git a/Mohem/src/app/hmg-common/services/nationality/models/nationalites.response.ts b/Mohem/src/app/hmg-common/services/nationality/models/nationalites.response.ts new file mode 100644 index 00000000..d5ca7f42 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/nationality/models/nationalites.response.ts @@ -0,0 +1,7 @@ +import { Response } from 'src/app/hmg-common/services/models/response'; + +import { NationalityModel } from './nationallity.model'; + +export class NationalitiesResponse extends Response { + ListNationality: NationalityModel[]; +} diff --git a/Mohem/src/app/hmg-common/services/nationality/models/nationallity.model.ts b/Mohem/src/app/hmg-common/services/nationality/models/nationallity.model.ts new file mode 100644 index 00000000..9856c368 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/nationality/models/nationallity.model.ts @@ -0,0 +1,4 @@ +export class NationalityModel { + ID: string; + Name: string; +} diff --git a/Mohem/src/app/hmg-common/services/nationality/nationality.service.spec.ts b/Mohem/src/app/hmg-common/services/nationality/nationality.service.spec.ts new file mode 100644 index 00000000..310aff6c --- /dev/null +++ b/Mohem/src/app/hmg-common/services/nationality/nationality.service.spec.ts @@ -0,0 +1,12 @@ +import { TestBed } from '@angular/core/testing'; + +import { NationalityService } from './nationality.service'; + +describe('NationalityService', () => { + beforeEach(() => TestBed.configureTestingModule({})); + + it('should be created', () => { + const service: NationalityService = TestBed.get(NationalityService); + expect(service).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/services/nationality/nationality.service.ts b/Mohem/src/app/hmg-common/services/nationality/nationality.service.ts new file mode 100644 index 00000000..9664d993 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/nationality/nationality.service.ts @@ -0,0 +1,77 @@ +import { Injectable } from '@angular/core'; +import { AuthenticationService } from '../authentication/authentication.service'; +import { ConnectorService } from '../connector/connector.service'; +import { CommonService } from '../common/common.service'; +import { Observable } from 'rxjs'; +import { NationalitiesResponse } from './models/nationalites.response'; +import { NationalityModel } from './models/nationallity.model'; +import { OptionModel } from 'src/app/hmg-common/ui/searchable-select/option.model'; + +@Injectable({ + providedIn: 'root' +}) +export class NationalityService { + + public static nationalities = 'Services/Lists.svc/REST/GetNationality'; + + private static cachedNationalities: NationalitiesResponse; + private static cachedNationalitiesOptions: OptionModel []; + + constructor( + public authService: AuthenticationService, + public con: ConnectorService, + public cs: CommonService + ) { } + + + public getNationalites(onError: any, errorLabel: string): Observable { + + return Observable.create(observer => { + // get from cache + if (NationalityService.cachedNationalities) { + observer.next(NationalityService.cachedNationalities); + observer.complete(); + } else { + // get from backend + const request = this.authService.getPublicRequest(); + this.con.post(NationalityService.nationalities, request, onError, errorLabel).subscribe((result) => { + this.saveNationalities(result); + observer.next(result); + observer.complete(); + }); + } + }); + } + + private saveNationalities(result: NationalitiesResponse) { + if (this.cs.validResponse(result)) { + if (this.cs.hasData(result.ListNationality)) { + NationalityService.cachedNationalities = result; + NationalityService.cachedNationalitiesOptions = this.getNationalitesOptions( result.ListNationality ); + } + } + } + + public cleanCache() { + NationalityService.cachedNationalities = null; + NationalityService.cachedNationalitiesOptions = null; + } + + private getNationalitesOptions( nationalites: NationalityModel []): OptionModel [] { + const nationalitiesOptions = []; + for ( const nationality of nationalites ) { + nationalitiesOptions.push( new OptionModel(nationality.Name, nationality)); + } + return nationalitiesOptions; + } + + public getCashedNationalitesOptions(): OptionModel [] { + if ( NationalityService.cachedNationalitiesOptions ) { + return NationalityService.cachedNationalitiesOptions; + } else { + return []; + } + } + + +} diff --git a/Mohem/src/app/hmg-common/services/preloading-strategy/hmg-preloading-strategy-loading.ts b/Mohem/src/app/hmg-common/services/preloading-strategy/hmg-preloading-strategy-loading.ts new file mode 100644 index 00000000..0b60f98e --- /dev/null +++ b/Mohem/src/app/hmg-common/services/preloading-strategy/hmg-preloading-strategy-loading.ts @@ -0,0 +1,45 @@ +import { Route, PreloadingStrategy, Router, RouteConfigLoadStart, RouteConfigLoadEnd } from "@angular/router"; +import { Observable, timer, of } from "rxjs"; +import { Injectable } from "@angular/core"; +import { flatMap } from 'rxjs/operators'; +import { CommonService } from '../common/common.service'; +import { Platform } from '@ionic/angular'; + + +@Injectable() +export class HMGPreloadingStrategyLoading implements PreloadingStrategy { + constructor( + public cs: CommonService, + public router: Router + ) { + //this.monitorModulesLazyLoading(); + } + + /* + show progress when loading lazy module starts + by monitoring router event + */ + public monitorModulesLazyLoading() { + return; + this.router.events.subscribe(event => { + if (event instanceof RouteConfigLoadStart) { + if (!event.route.data) { + this.cs.startLoading(); + } + } else if (event instanceof RouteConfigLoadEnd) { + this.cs.stopLoading(); + } + }); + } + + + preload(route: Route, load: Function): Observable { + console.log('loading route:' + route.path ); + this.cs.startLoading(); + const loadedModule = load(); + this.cs.stopLoading(); + return loadedModule; + } + + +} diff --git a/Mohem/src/app/hmg-common/services/preloading-strategy/hmg-preloading-strategy.1.ts b/Mohem/src/app/hmg-common/services/preloading-strategy/hmg-preloading-strategy.1.ts new file mode 100644 index 00000000..32df3aa4 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/preloading-strategy/hmg-preloading-strategy.1.ts @@ -0,0 +1,45 @@ +import { Route, PreloadingStrategy, Router, RouteConfigLoadStart, RouteConfigLoadEnd } from "@angular/router"; +import { Observable, timer, of } from "rxjs"; +import { Injectable } from "@angular/core"; +import { flatMap } from 'rxjs/operators'; +import { CommonService } from '../common/common.service'; +import { Platform } from '@ionic/angular'; + + +@Injectable() +export class HMGPreloadingStrategy implements PreloadingStrategy { + constructor( + public cs: CommonService, + public router: Router + ) { + //this.monitorModulesLazyLoading(); + } + + /* + show progress when loading lazy module starts + by monitoring router event + */ + public monitorModulesLazyLoading() { + this.router.events.subscribe(event => { + if (event instanceof RouteConfigLoadStart) { + if (!event.route.data) { + this.cs.startLoading(); + } + } else if (event instanceof RouteConfigLoadEnd) { + this.cs.stopLoading(); + } + }); + } + + + preload(route: Route, load: Function): Observable { + if (route.data && route.data.preload) { + // console.log('preloading lazy :' + route.path + ' after :' + (route.data.delay || 0)); + return timer(route.data.delay || 0).pipe(flatMap(() => { + // console.log('loading lazy :' + route.path); + return load(); + })); + } + return of(null); + } +} diff --git a/Mohem/src/app/hmg-common/services/projects/models/clinic.model.ts b/Mohem/src/app/hmg-common/services/projects/models/clinic.model.ts new file mode 100644 index 00000000..4a399326 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/projects/models/clinic.model.ts @@ -0,0 +1,4 @@ +export class ClinicModel { + ClinicDescription: string; + ClinicID: number; +} diff --git a/Mohem/src/app/hmg-common/services/projects/models/clinics.response.ts b/Mohem/src/app/hmg-common/services/projects/models/clinics.response.ts new file mode 100644 index 00000000..af5c3642 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/projects/models/clinics.response.ts @@ -0,0 +1,8 @@ +import { Response } from 'src/app/hmg-common/services/models/response'; +import { ClinicModel } from './clinic.model'; + +export class ClinicsResponse extends Response { + ListClinicCentralized: ClinicModel []; + public DentalClinicID: number; + public ISMobileAppDentalAllow: boolean; +} diff --git a/Mohem/src/app/hmg-common/services/projects/models/project.model.ts b/Mohem/src/app/hmg-common/services/projects/models/project.model.ts new file mode 100644 index 00000000..4ac0f524 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/projects/models/project.model.ts @@ -0,0 +1,17 @@ + +import { Component } from '@angular/core'; + +export class ProjectModel { + ID: number; + Desciption: string; + PhoneNumber: string; + Latitude: string; + Longitude: string; + IsActive: boolean; + LegalName: string; // en + LegalNameN: string; // ar + MainProjectID: number; + Name: string; + SetupID: string; + UsingInDoctorApp: boolean; +} diff --git a/Mohem/src/app/hmg-common/services/projects/models/projects.response.ts b/Mohem/src/app/hmg-common/services/projects/models/projects.response.ts new file mode 100644 index 00000000..1fa002b0 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/projects/models/projects.response.ts @@ -0,0 +1,8 @@ +import { Response } from 'src/app/hmg-common/services/models/response'; +import { ProjectModel } from './project.model'; + +import { Component } from '@angular/core'; + +export class ProjectsResponse extends Response { + ListProject: ProjectModel[]; +} diff --git a/Mohem/src/app/hmg-common/services/projects/projects.service.spec.ts b/Mohem/src/app/hmg-common/services/projects/projects.service.spec.ts new file mode 100644 index 00000000..1713a581 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/projects/projects.service.spec.ts @@ -0,0 +1,12 @@ +import { TestBed } from '@angular/core/testing'; + +import { ProjectsService } from './projects.service'; + +describe('ProjectsService', () => { + beforeEach(() => TestBed.configureTestingModule({})); + + it('should be created', () => { + const service: ProjectsService = TestBed.get(ProjectsService); + expect(service).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/services/projects/projects.service.ts b/Mohem/src/app/hmg-common/services/projects/projects.service.ts new file mode 100644 index 00000000..5c92a339 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/projects/projects.service.ts @@ -0,0 +1,138 @@ +import { Injectable } from '@angular/core'; +import { ClinicsResponse } from './models/clinics.response'; +import { ProjectsResponse } from './models/projects.response'; +import { AuthenticationService } from '../authentication/authentication.service'; +import { ConnectorService } from '../connector/connector.service'; +import { CommonService } from '../common/common.service'; +import { Observable } from 'rxjs'; +import { ProjectModel } from './models/project.model'; +import { ClinicModel } from './models/clinic.model'; +import { OptionModel } from 'src/app/hmg-common/ui/searchable-select/option.model'; + +@Injectable({ + providedIn: 'root' +}) +export class ProjectsService { + + + public static clinics = 'Services/lists.svc/REST/GetClinicCentralized'; + public static searchByClinicId = 'Services/Doctors.svc/REST/SearchDoctorsByTime'; + public static projects = 'Services/Lists.svc/REST/GetProject'; + + private static cachedClinics: ClinicsResponse; + private static cachedClinicsOptions: OptionModel []; + private static cachedProjects: ProjectsResponse; + private static cachedProjectsOptions: OptionModel []; + + constructor( + public authService: AuthenticationService, + public con: ConnectorService, + public cs: CommonService + ) { } + + public getClinics(onError: any, errorLabel: string): Observable { + + return Observable.create(observer => { + // get from cache + if (ProjectsService.cachedClinics) { + observer.next(ProjectsService.cachedClinics); + observer.complete(); + } else { + // get from backend + const request = this.authService.getPublicRequest(); + this.con.post(ProjectsService.clinics, request, onError, errorLabel).subscribe((result) => { + this.saveClinics(result); + observer.next(result); + observer.complete(); + }); + } + }); + } + + private saveClinics(result: ClinicsResponse) { + if (this.cs.validResponse(result)) { + if (this.cs.hasData(result.ListClinicCentralized)) { + ProjectsService.cachedClinics = result; + ProjectsService.cachedClinicsOptions = this.getClinicsOptions( result.ListClinicCentralized ); + } + } + } + + + + public getProjects(onError: any, errorLabel: string): Observable { + + return Observable.create(observer => { + // get from cache + if (ProjectsService.cachedProjects) { + observer.next(ProjectsService.cachedProjects); + observer.complete(); + } else { + // get from backend + // const request = this.authService.getAuthenticatedRequest(); + const request = this.authService.getPublicRequest(); + + this.con.post(ProjectsService.projects, request, onError, errorLabel).subscribe((result) => { + this.saveProejcts(result); + observer.next(result); + observer.complete(); + }); + } + }); + } + + + private saveProejcts(result: ProjectsResponse) { + if (this.cs.validResponse(result)) { + if (this.cs.hasData(result.ListProject)) { + ProjectsService.cachedProjects = result; + ProjectsService.cachedProjectsOptions = this.getProjectsOptions( result.ListProject); + } + } + } + + + public findProject(projectId: number): ProjectModel { + if (ProjectsService.cachedProjects) { + for (const proj of ProjectsService.cachedProjects.ListProject) { + if (projectId === proj.ID) { + return proj; + } + } + } + return null; + } + + public cleanCache() { + ProjectsService.cachedClinics = null; + ProjectsService.cachedClinicsOptions = null; + ProjectsService.cachedProjects = null; + ProjectsService.cachedProjectsOptions = null; + } + + private getClinicsOptions( clinics: ClinicModel []): OptionModel [] { + const clinicsOptions = []; + for ( const clinic of clinics ) { + clinicsOptions.push( new OptionModel(clinic.ClinicDescription, clinic)); + } + return clinicsOptions; + } + + public getCachedClinicsOptions( ): OptionModel [] { + return ProjectsService.cachedClinicsOptions ? ProjectsService.cachedClinicsOptions : []; + } + + private getProjectsOptions( projects: ProjectModel []): OptionModel [] { + const projectsOptions = []; + for ( const project of projects ) { + projectsOptions.push( new OptionModel(project.Desciption, project)); + } + return projectsOptions; + } + public getCachedProjectsOptions( ): OptionModel [] { + return ProjectsService.cachedProjectsOptions ? ProjectsService.cachedProjectsOptions : []; + } + + +} + diff --git a/Mohem/src/app/hmg-common/services/push/models/notification.model.ts b/Mohem/src/app/hmg-common/services/push/models/notification.model.ts new file mode 100644 index 00000000..d99b372b --- /dev/null +++ b/Mohem/src/app/hmg-common/services/push/models/notification.model.ts @@ -0,0 +1,33 @@ +export class NotificationModel { + public static SHARED_DATA = 'notification_model'; + public static TYPE_APPOINTMENT = 1; + public static TYPE_VIDEO = 2; + public static TYPE_IMAGE = 3; + public static TYPE_CONFERENCE = 4; + ChannelID: number; + CreatedOn: string; // json date + DeviceToken: string; + DeviceType: string; // Android , IOS + Id: number; + IsQueue: boolean; + IsQueueOn: string; // json date + IsRead: boolean; + IsReadOn: string; // json date + IsSent: boolean; + IsSentOn: string; // json date + Message: string; // show message + MessageType: string; // type [ "text" , "video" , "image"] + /* + is number if coming form push notification [TYPE_APPOINTMENT , TYPE_VIDEO , TYPE_IMAGE ] + and string description if coming from notification center + */ + NotificationType: number; + PatientID: number; + ProjectID: number; + ProjectOutSA: boolean; + RecordId: number; + VideoURL: string; + MessageTypeData: string; // url for image , video + count: number; + AppointmentNo: number; +} diff --git a/Mohem/src/app/hmg-common/services/push/models/register-authenticated-user.request.ts b/Mohem/src/app/hmg-common/services/push/models/register-authenticated-user.request.ts new file mode 100644 index 00000000..0e23d6ec --- /dev/null +++ b/Mohem/src/app/hmg-common/services/push/models/register-authenticated-user.request.ts @@ -0,0 +1,11 @@ +import { Request } from '../../models/request'; +import { RegisterNormalUserRequest } from './register-normal-user.request'; + +export class RegisterAuthenticatedUserRequest extends RegisterNormalUserRequest { + PatientMobileNumber: string; + NationalID: string; + Gender: number; + PatientID: number; + LoginType: number; + MACAddress: string; // '00:00:00:00:00:00' +} diff --git a/Mohem/src/app/hmg-common/services/push/models/register-normal-user.request.ts b/Mohem/src/app/hmg-common/services/push/models/register-normal-user.request.ts new file mode 100644 index 00000000..6f221070 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/push/models/register-normal-user.request.ts @@ -0,0 +1,7 @@ +import { Request } from '../../models/request'; + +export class RegisterNormalUserRequest extends Request { + ChannelID: number; + DeviceToken: string; + DeviceType: string; // Device.platform +} diff --git a/Mohem/src/app/hmg-common/services/push/models/session.model.ts b/Mohem/src/app/hmg-common/services/push/models/session.model.ts new file mode 100644 index 00000000..fca4d182 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/push/models/session.model.ts @@ -0,0 +1,8 @@ +export class SessionModel { + public static SHARED_DATA = 'session_model'; + sessionId: string; + token: string; + constructor(sessionId: string) { + this.sessionId = sessionId; + } +} diff --git a/Mohem/src/app/hmg-common/services/push/push.service.spec.ts b/Mohem/src/app/hmg-common/services/push/push.service.spec.ts new file mode 100644 index 00000000..935c5f06 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/push/push.service.spec.ts @@ -0,0 +1,12 @@ +import { TestBed } from '@angular/core/testing'; + +import { PushService } from './push.service'; + +describe('PushService', () => { + beforeEach(() => TestBed.configureTestingModule({})); + + it('should be created', () => { + const service: PushService = TestBed.get(PushService); + expect(service).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/services/push/push.service.ts b/Mohem/src/app/hmg-common/services/push/push.service.ts new file mode 100644 index 00000000..9e55d481 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/push/push.service.ts @@ -0,0 +1,209 @@ +import { Injectable, NgZone } from '@angular/core'; +import { Push, PushObject, PushOptions } from '@ionic-native/push/ngx'; +import { CommonService } from '../common/common.service'; +import { TranslatorService } from '../translator/translator.service'; +import { NotificationModel } from './models/notification.model'; +import { SharedDataService } from '../shared-data-service/shared-data.service'; +import { ConnectorService } from '../connector/connector.service'; +import { Response } from '../models/response'; +import { RegisterAuthenticatedUserRequest } from './models/register-authenticated-user.request'; +import { Platform, Events } from '@ionic/angular'; +import { RegisterNormalUserRequest } from './models/register-normal-user.request'; +import { AuthenticationService } from '../authentication/authentication.service'; +// import { AppointmentModel } from 'src/app/eservices/appointments/service/models/appointment.model'; +import { SessionModel } from './models/session.model'; +import { AuthenticatedUser } from '../authentication/models/authenticated-user'; +// import { NotificationsCenterService } from 'src/app/eservices/notifications-center/service/notifications-center.service'; +// import { NotificationsComponent } from 'src/app/eservices/notifications-center/notifications/notifications.component'; + + +@Injectable({ + providedIn: 'root' +}) +export class PushService { + private static notLoggedInUserURL = 'Services/MobileNotifications.svc/REST/PushNotification_InsertPatientDeviceInformation'; + private static loggedInUserURL = 'Services/MobileNotifications.svc/REST/Insert_PatientMobileDeviceInfo'; + + public static CHANNEL_ID = '815750722565'; + constructor( + public push: Push, + public cs: CommonService, + public ts: TranslatorService, + public sharedService: SharedDataService, + public con: ConnectorService, + private platform: Platform, + private authService: AuthenticationService, + public ngZone: NgZone, + // public notifyService: NotificationsCenterService, + public events: Events + + ) { } + + public startReceiving() { + this.processStartReceiving(); + } + private processStartReceiving() { + if (this.cs.isCordova()) { + this.stopNotifications(() => { + this.push.hasPermission() + .then((res: any) => { + if (res.isEnabled) { + this.createChannel(); + } else { + this.cs.presentAlert(this.ts.trPK('push', 'no-permiss')); + } + }); + }); + } + } + + private createChannel() { + // Create a channel (Android O and above). You'll need to provide the id, description and importance properties. + this.push.createChannel({ + id: PushService.CHANNEL_ID, + description: 'HMG push notifications', + importance: 3 + }).then(() => { + this.initialize(); + }); + } + + private initialize() { + const options: PushOptions = { + android: { + senderID: PushService.CHANNEL_ID, + sound: true, + forceShow: true + }, + ios: { + alert: true, + badge: true, + sound: true + }, + windows: {}, + browser: { + pushServiceURL: 'http://push.api.phonegap.com/v1/push' + } + }; + const pushObject: PushObject = this.push.init(options); + pushObject.on('notification').subscribe((notification: any) => { + this.processNotification(notification); + }); + + pushObject.on('registration').subscribe((data: any) => { + this.registerInBackend(data); + }); + + pushObject.on('error').subscribe(error => console.error('Error with Push plugin', error)); + + } + + private processNotification(data: any) { + const notification = new NotificationModel(); + this.cs.setBadge(data.additionalData.badgenumber - 1); + notification.Id = data.additionalData.msgID ? data.additionalData.msgID : data.additionalData.notfID; + notification.count = data.count; + notification.Message = data.message; + notification.AppointmentNo = data.additionalData.AppointmentNo; + notification.ProjectID = data.additionalData.ProjectID; + notification.NotificationType = data.title; + this.processNotificationType(notification, data); + } + + private processNotificationType(notification: NotificationModel, data: any) { + this.setAsReadNotification(notification); + const type = Number(data.additionalData.NotificationType); + if (type === NotificationModel.TYPE_APPOINTMENT) { + this.sharedService.setSharedData(notification, NotificationModel.SHARED_DATA); + this.ngZone.run(() => this.cs.openAppointmentDetails()); + } else if (type === NotificationModel.TYPE_CONFERENCE) { + const session = data.additionalData.sessionId; + // console.log('session Id Recieved>>>>>'+ session); + this.sharedService.setSharedData( new SessionModel(session) , SessionModel.SHARED_DATA); + this.ngZone.run( () => this.cs.openConference() ); + } else { + if (type === NotificationModel.TYPE_VIDEO) { + notification.MessageType = 'video'; + notification.MessageTypeData = data.additionalData.videoUrl; + } else if (type === NotificationModel.TYPE_IMAGE) { + notification.MessageType = 'image'; + notification.MessageTypeData = data.additionalData.picture; + } else { + notification.MessageType = 'text'; + } + this.sharedService.setSharedData(notification, NotificationModel.SHARED_DATA); + this.ngZone.run(async () => this.cs.openNotificationDetails()); + } + } + + private setAsReadNotification(notification: NotificationModel) { + notification.IsRead = true; + // this.notifyService.setNotificationRead(notification, () => { + // }).subscribe((result: Response) => { + // if (this.cs.validResponse(result)) { + // this.events.publish( NotificationsCenterService.NOTIFICATIONS_COUNT_EVENT, notification.count); + // } + // }); + + + } + public stopNotifications(done: any) { + // Delete a channel (Android O and above) + if (this.cs.isCordova()) { + this.push.deleteChannel(PushService.CHANNEL_ID).then(() => { + done(); + }); + } + } + + private registerInBackend(data: any) { + if (this.authService.isAuthenticated()) { + this.registerAuthenticatedUser(data.registrationId); + } else { + this.registerNotAuthenticatedUser(data.registrationId); + } + } + + + private registerAuthenticatedUser(deviceToken: any) { + const request = new RegisterAuthenticatedUserRequest(); + this.authService.authenticateRequest(request); + request.DeviceToken = deviceToken; + request.DeviceType = this.getDeviceType(); + const user = this.authService.getAuthenticatedUser(); + request.PatientMobileNumber = user.MobileNo; + request.NationalID = user.IdentificationNo; + request.Gender = user.Gender; + request.PatientID = user.PatientID; + request.PatientOutSA = user.PatientOutSA ? 1 : 0; + request.LoginType = user.biometricEnabled ? 2 : 1; // 1 sms , 2 touch id + request.MACAddress = '00:00:00:00:00:00'; + return this.con.postNoLoad(PushService.loggedInUserURL, request + , () => { }).subscribe((result: Response) => { + if (this.cs.validResponse(result)) { + this.authService.setDeviceToken(deviceToken); + } + }); + } + + + private registerNotAuthenticatedUser(deviceToken: any) { + const request = new RegisterNormalUserRequest(); + this.authService.setPublicFields(request); + request.ChannelID = request.Channel; + request.DeviceToken = deviceToken; + request.DeviceType = this.getDeviceType(); + return this.con.postNoLoad(PushService.notLoggedInUserURL, request + , () => { }).subscribe((result: Response) => { + if (this.cs.validResponse(result)) { + console.log('device token:' + deviceToken); + } + }); + } + + private getDeviceType(): string { + return this.platform.is('ios') ? 'Iphone' : 'Android'; + } + + +} diff --git a/Mohem/src/app/hmg-common/services/rate/rate.service.spec.ts b/Mohem/src/app/hmg-common/services/rate/rate.service.spec.ts new file mode 100644 index 00000000..b10a8287 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/rate/rate.service.spec.ts @@ -0,0 +1,12 @@ +import { TestBed } from '@angular/core/testing'; + +import { RateService } from './rate.service'; + +describe('RateService', () => { + beforeEach(() => TestBed.configureTestingModule({})); + + it('should be created', () => { + const service: RateService = TestBed.get(RateService); + expect(service).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/services/rate/rate.service.ts b/Mohem/src/app/hmg-common/services/rate/rate.service.ts new file mode 100644 index 00000000..8fbec2e6 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/rate/rate.service.ts @@ -0,0 +1,96 @@ +import { Injectable } from '@angular/core'; +import { TranslatorService } from '../translator/translator.service'; +import { CommonService } from '../common/common.service'; +import { Platform } from '@ionic/angular'; +import { AppRate } from '@ionic-native/app-rate/ngx'; + +@Injectable({ + providedIn: 'root' +}) +export class RateService { + public static done = 'done'; + private static app = 'full-app-rate'; + + constructor( + public ts: TranslatorService, + public cs: CommonService, + public platform: Platform, + public appRate: AppRate + ) { + + } + + public rateFeature(ratedFeedBack?: any , featureKey: string = RateService.app , delay: number = 2000) { + if (this.isRated(featureKey)) { + if (ratedFeedBack) { + ratedFeedBack(true); + } + } else { + setTimeout( () => { + this.startRating(featureKey, ratedFeedBack); + }, delay); + } + } + + private startRating(featureKey: string, ratedFeedBack?: any) { + if (this.cs.isCordova()) { + this.platform.ready().then(() => { + this.appRate.preferences = { + displayAppName: this.ts.trPK('general', 'app-name'), + promptAgainForEachNewVersion: true, + inAppReview: true, + storeAppURL: { + ios: 'com.ejada.hmg', + android: 'market://details?id=com.ejada.hmg', + }, + customLocale: this.getCustomLocals(), + callbacks: { + handleNegativeFeedback: () => { + this.setAsRated(featureKey); + this.cs.openFeedback(); + }, + onButtonClicked: (buttonIndex) => { + // when user click rate + if (buttonIndex == 3) { + this.setAsRated(featureKey); + if (ratedFeedBack) { + ratedFeedBack(true); + } + } + } + } + }; + this.appRate.promptForRating(true); + }); + + } else { + + } + + } + + private getCustomLocals() { + return { + title: this.ts.trPK('rate', 'mind'), + message: this.ts.trPK('rate', 'thanks'), + cancelButtonLabel: this.ts.trPK('rate', 'cancel'), + laterButtonLabel: this.ts.trPK('rate', 'later'), + rateButtonLabel: this.ts.trPK('rate', 'rate'), + yesButtonLabel: this.ts.trPK('rate', 'yes'), + noButtonLabel: this.ts.trPK('rate', 'not'), + appRatePromptTitle: this.ts.trPK('rate', 'like'), + feedbackPromptTitle: this.ts.trPK('rate', 'feedback'), + }; + } + private setAsRated(featureKey: string) { + localStorage.setItem(featureKey, RateService.done); + } + + public isRated(featureKey: string = RateService.app) { + return localStorage.getItem(featureKey) == RateService.done; + } + + public removeRate(featureKey: string = RateService.app) { + return localStorage.removeItem(featureKey); + } +} diff --git a/Mohem/src/app/hmg-common/services/rating/rating.service.spec.ts b/Mohem/src/app/hmg-common/services/rating/rating.service.spec.ts new file mode 100644 index 00000000..1a90bc18 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/rating/rating.service.spec.ts @@ -0,0 +1,12 @@ +import { TestBed } from '@angular/core/testing'; + +import { RatingService } from './rating.service'; + +describe('RatingService', () => { + beforeEach(() => TestBed.configureTestingModule({})); + + it('should be created', () => { + const service: RatingService = TestBed.get(RatingService); + expect(service).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/services/rating/rating.service.ts b/Mohem/src/app/hmg-common/services/rating/rating.service.ts new file mode 100644 index 00000000..c0803342 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/rating/rating.service.ts @@ -0,0 +1,26 @@ +import { Injectable } from '@angular/core'; +import { AppRate } from '@ionic-native/app-rate/ngx'; + +@Injectable({ + providedIn: 'root' +}) +export class RatingService { + + constructor(private appRate: AppRate) { + + } + + + public rate() { + + // set certain preferences + this.appRate.preferences.storeAppURL = { + ios: 'com.ejada.hmg', + android: 'market://details?id=com.ejada.hmg' + }; + + this.appRate.promptForRating(true); + + } + +} diff --git a/Mohem/src/app/hmg-common/services/shared-data-service/shared-data.service.spec.ts b/Mohem/src/app/hmg-common/services/shared-data-service/shared-data.service.spec.ts new file mode 100644 index 00000000..eba5e761 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/shared-data-service/shared-data.service.spec.ts @@ -0,0 +1,12 @@ +import { TestBed } from '@angular/core/testing'; + +import { SharedDataService } from './shared-data.service'; + +describe('SharedDataService', () => { + beforeEach(() => TestBed.configureTestingModule({})); + + it('should be created', () => { + const service: SharedDataService = TestBed.get(SharedDataService); + expect(service).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/services/shared-data-service/shared-data.service.ts b/Mohem/src/app/hmg-common/services/shared-data-service/shared-data.service.ts new file mode 100644 index 00000000..312e3859 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/shared-data-service/shared-data.service.ts @@ -0,0 +1,36 @@ +import { Injectable } from '@angular/core'; + +@Injectable({ + providedIn: 'root' +}) +export class SharedDataService { + + public static data: any[] = []; + constructor() { } + /*public getSharedData(key: string) { + return SharedDataService.data[key]; + } + */ + public getSharedData(key: string, remove = true) { + const selectedData = SharedDataService.data[key]; + if (remove) { + this.removeData(key); + } + return selectedData; + } + public setSharedData(data: any, key: string) { + SharedDataService.data[key] = data; + } + public clearAll() { + SharedDataService.data = []; + } + public removeData(key: string) { + delete SharedDataService.data[key]; + } + + public showAll() { + for (const v of SharedDataService.data) { + console.log(v); + } + } +} diff --git a/Mohem/src/app/hmg-common/services/sms/sms-reader.service.spec.ts b/Mohem/src/app/hmg-common/services/sms/sms-reader.service.spec.ts new file mode 100644 index 00000000..574724d8 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/sms/sms-reader.service.spec.ts @@ -0,0 +1,12 @@ +import { TestBed } from '@angular/core/testing'; + +import { SmsReaderService } from './sms-reader.service'; + +describe('SmsReaderService', () => { + beforeEach(() => TestBed.configureTestingModule({})); + + it('should be created', () => { + const service: SmsReaderService = TestBed.get(SmsReaderService); + expect(service).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/services/sms/sms-reader.service.ts b/Mohem/src/app/hmg-common/services/sms/sms-reader.service.ts new file mode 100644 index 00000000..fe58ad35 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/sms/sms-reader.service.ts @@ -0,0 +1,84 @@ +import { Injectable } from '@angular/core'; +import { Platform } from '@ionic/angular'; +import { CommonService } from '../common/common.service'; + +declare var SMS; + +@Injectable({ + providedIn: 'root' +}) +export class SmsReaderService { + + private sms: any; + private lastCode: string; + private features: string [] = ['hmg', 'للحبيب']; + constructor( + public platform: Platform, + public cs: CommonService + ) { + this.sms = new SMS(); + } + + /* + start listengin for incoming sms from hmg service + */ + public startSMSMonitoring(onRead: any) { + if (this.cs.isCordova()) { + this.platform.ready().then(() => { + this.lastCode = null; + if (this.platform.is('android')) { + this.startRecieving(onRead); + } + }); + } + } + + public stopSMSMonitoring() { + if (this.cs.isCordova()) { + this.platform.ready().then(() => { + this.lastCode = null; + if (this.platform.is('android')) { + this.sms.stopReciever(); + } + }); + } + } + + /* + the sms plugin some times notify for same message many times + */ + private startRecieving(onRead: any) { + this.platform.ready().then(() => { + this.platform.ready().then(() => { + this.sms.startReciever( + (body: string, address) => { /* got message */ + + if (this.isTargetMessage(body)) { + const code = this.cs.extractNumber(body); + if (code && (code !== this.lastCode)) { + onRead(code); + this.lastCode = code; + } + } + } + , + () => { /* reciever error*/ }); + }); + }); + + } + + private isTargetMessage(body: string): boolean { + if ( body ) { + const lowerBody = body.toLowerCase(); + for ( const feature of this.features ){ + if ( lowerBody.indexOf(feature) >= 0 ) { + return true; + } + } + } + return false; + } + + +} diff --git a/Mohem/src/app/hmg-common/services/translator/Translation.ts b/Mohem/src/app/hmg-common/services/translator/Translation.ts new file mode 100644 index 00000000..5a0cda4a --- /dev/null +++ b/Mohem/src/app/hmg-common/services/translator/Translation.ts @@ -0,0 +1,12 @@ +export class Translation { + public page: string; + public key: string; + + constructor(page: string, key: string) { + this.page = page; + this.key = key; + } + public isValid(): boolean { + return this.page != null && this.key != null; + } +} diff --git a/Mohem/src/app/hmg-common/services/translator/translator.service.spec.ts b/Mohem/src/app/hmg-common/services/translator/translator.service.spec.ts new file mode 100644 index 00000000..fb83a0d4 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/translator/translator.service.spec.ts @@ -0,0 +1,12 @@ +import { TestBed } from '@angular/core/testing'; + +import { TranslatorService } from './translator.service'; + +describe('TranslatorService', () => { + beforeEach(() => TestBed.configureTestingModule({})); + + it('should be created', () => { + const service: TranslatorService = TestBed.get(TranslatorService); + expect(service).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/services/translator/translator.service.ts b/Mohem/src/app/hmg-common/services/translator/translator.service.ts new file mode 100644 index 00000000..ae9559b3 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/translator/translator.service.ts @@ -0,0 +1,201 @@ +import { Injectable } from '@angular/core'; +import { Platform, Events } from '@ionic/angular'; +import { Globalization } from '@ionic-native/globalization/ngx'; +import { Translation } from './Translation'; +import { HttpClient } from '@angular/common/http'; +import { NativeStorage } from '@ionic-native/native-storage/ngx'; + +@Injectable({ + providedIn: 'root' +}) +export class TranslatorService { + + public static LNG_KEY = 'current-language'; + public static EN = 'en'; + public static EN_US = 'en-us'; + public static AR = 'ar'; + public static CURRENT_LANGUAGE = TranslatorService.AR; + public static CHANGE_EVENT = 'language-changed-event'; + private static translations: any; + constructor( + private platform: Platform, + private glob: Globalization, + private httpClient: HttpClient, + private nativeStorage: NativeStorage, + private events: Events + ) { + } + + + public static getCurrentLanguageCode(): number { + switch (TranslatorService.CURRENT_LANGUAGE) { + case TranslatorService.EN: + return 2; + case TranslatorService.AR: + return 1; + default: + return 2; + } + } + + public static getCurrentDirection(): string { + return TranslatorService.getCurrentLanguageName() === TranslatorService.AR ? 'rtl' : 'ltr'; + } + + public async getCurrentSystemLanguageName() { + const lng = await this.glob.getPreferredLanguage(); + if (lng && lng.value) { + return lng.value.toLowerCase(); + } else { + return TranslatorService.EN_US; + } + } + + public static getCurrentLanguageName(): string { + return TranslatorService.CURRENT_LANGUAGE; + } + private isLoaded(): boolean { + return TranslatorService.translations != null; + } + + /* + load system translation files + */ + private loadTranslationAssetNative(onSuccess: any) { + this.httpClient.get('assets/localization/i18n.json').subscribe(data => { + TranslatorService.translations = data; + if (data) { + if (!this.isSystemLanguageSupported()) { + this.setCurrentLanguageToDefault(); + } + if (onSuccess) { + onSuccess(); + } + } + }); + } + + private isSystemLanguageSupported(): boolean { + for (const lng of TranslatorService.translations.SUPPORTED_LANGUAGES) { + if (TranslatorService.CURRENT_LANGUAGE === lng) { + return true; + } + } + return false; + } + + /* + get current system prefered language + */ + public loadResourcesNative(onSuccess: any) { + this.platform.ready().then(() => { + this.glob.getPreferredLanguage().then(res => { + const lang = res.value.split('-')[0]; + TranslatorService.CURRENT_LANGUAGE = lang; + this.loadTranslationAssetNative(onSuccess); + }).catch(err => { + this.setCurrentLanguageToDefault(); + this.loadTranslationAssetNative(onSuccess); + }); + }); + } + + + + private loadTranslationAsset(onSuccess: any) { + this.httpClient.get('assets/localization/i18n.json').subscribe(data => { + TranslatorService.translations = data; + if (data) { + if (onSuccess) { + onSuccess(); + } + } + }); + } + + public loadResources(onSuccess: any) { + this.platform.ready().then(() => { + this.nativeStorage.getItem(TranslatorService.LNG_KEY).then((previousLanguage: string) => { + TranslatorService.CURRENT_LANGUAGE = previousLanguage; + this.loadTranslationAsset(onSuccess); + }, () => { + this.setCurrentLanguageToDefault(); + this.loadTranslationAsset(onSuccess); + }); + + }); + } + + /* + translate key depend on current prefered language + */ + public translate(trans: Translation): string { + if (this.isLoaded()) { + const page = TranslatorService.translations[trans.page]; + if (page) { + const word = page[trans.key]; + if (word) { + return word[TranslatorService.CURRENT_LANGUAGE]; + } + } + } + return ''; + } + + private isValidTranslation(trans: Translation): boolean { + if (trans != null) { + return trans.isValid(); + } + return false; + } + /* + shortcut for translate + */ + public tr(trans: Translation): string { + return this.translate(trans); + } + + /* + translate with page and key + */ + public trPK(page: string, key: string): string { + return this.translate(new Translation(page, key)); + } + + public trInline(pageKey: string): string { + if (pageKey) { + const parts = pageKey.split(','); + if (parts.length === 2) { + return this.trPK(parts[0].trim(), parts[1].trim()); + } + } else { + return ''; + } + } + + private setCurrentLanguageToDefault() { + TranslatorService.CURRENT_LANGUAGE = TranslatorService.AR; + } + public setCurrentLanguage(language: string) { + TranslatorService.CURRENT_LANGUAGE = language; + this.events.publish(TranslatorService.CHANGE_EVENT); + this.nativeStorage.setItem(TranslatorService.LNG_KEY, language).then(() => { + }, () => { }); + } + + + public switchLanguage() { + + this.nativeStorage.getItem(TranslatorService.LNG_KEY).then((previousLanguage: string) => { + this.setCurrentLanguage(this.getNextLanguage(previousLanguage)); + }, () => { + this.setCurrentLanguage(this.getNextLanguage(TranslatorService.CURRENT_LANGUAGE)); + }); + } + + private getNextLanguage(currentLanguage: string) { + return (currentLanguage === TranslatorService.EN) ? TranslatorService.AR : TranslatorService.EN; + } +} + + diff --git a/Mohem/src/app/hmg-common/services/user-local-notification/user-local-notification.service.spec.ts b/Mohem/src/app/hmg-common/services/user-local-notification/user-local-notification.service.spec.ts new file mode 100644 index 00000000..f2573dd9 --- /dev/null +++ b/Mohem/src/app/hmg-common/services/user-local-notification/user-local-notification.service.spec.ts @@ -0,0 +1,12 @@ +import { TestBed } from '@angular/core/testing'; + +import { UserLocalNotificationService } from './user-local-notification.service'; + +describe('UserLocalNotificationService', () => { + beforeEach(() => TestBed.configureTestingModule({})); + + it('should be created', () => { + const service: UserLocalNotificationService = TestBed.get(UserLocalNotificationService); + expect(service).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/services/user-local-notification/user-local-notification.service.ts b/Mohem/src/app/hmg-common/services/user-local-notification/user-local-notification.service.ts new file mode 100644 index 00000000..9a7fcbdb --- /dev/null +++ b/Mohem/src/app/hmg-common/services/user-local-notification/user-local-notification.service.ts @@ -0,0 +1,97 @@ +import { Injectable } from '@angular/core'; +import { LocalNotifications, ILocalNotification } from '@ionic-native/local-notifications/ngx'; + +export interface UserLocalData { + [key: string]: any; +} + +@Injectable({ + providedIn: 'root' +}) + +export class UserLocalNotificationService { + + public static STORAGE_KEY = 'notifications'; + constructor( + public localNotification: LocalNotifications, + ) { } + + public async requestNotificationPermission(): Promise { + const hasPermission = await this.checkNotificationPermission(); + if (!hasPermission) { + return await this.localNotification.requestPermission(); + } else { + return true; + } + } + + public async checkNotificationPermission(): Promise { + return await this.localNotification.hasPermission(); + } + + public async cancelCategoryNotifications(category: string) { + const notifications = await this.localNotification.getAll(); + for (const notification of notifications) { + const parsedData = JSON.parse(notification.data); + const notifCategory = parsedData['category']; + if (notifCategory === category) { + await this.localNotification.cancel(notification.id); + } + } + } + + public async isCategoryExist(category: string) { + const notifications = await this.localNotification.getAll(); + for (const notification of notifications) { + const parsedData = JSON.parse(notification.data); + const notifCategory = parsedData['category']; + // alert( 'notifCategory:' + notifCategory + ' category:' + category); + if (notifCategory === category) { + return true; + } + } + return false; + } + + public createNotification(title: string, text: string, date: Date, + category: string) { + const notifID = this.generateNotificationID(); + this.scheduleNotification(notifID, title, text, date, category); + } + + private scheduleNotification(notifId: number, title: string, text: string, + date: Date, category: string) { + this.localNotification.on('click').subscribe(notification => { + this.localNotification.clear(notification.id); + }); + this.localNotification.schedule({ + id: notifId, + title: title, + text: text, + trigger: {at: date}, + data : {'category': category}, + }); + } + + public deleteAllNotifications() { + this.localNotification.clearAll(); + this.localNotification.cancelAll(); + } + + public cancelNotification(notifID: number) { + this.localNotification.cancel(notifID); + } + + public clearTriggeredNotifications() { + this.localNotification.clearAll(); + } + + private generateNotificationID(): number { + return Date.now() + Math.floor(Math.random() * (1000 - 1) + 1); + } + + public async getNotifications(): Promise { + const notifs = await this.localNotification.getAll(); + return notifs; + } +} diff --git a/Mohem/src/app/hmg-common/ui/accordion/accordion-tab/accordion-tab.component.html b/Mohem/src/app/hmg-common/ui/accordion/accordion-tab/accordion-tab.component.html new file mode 100644 index 00000000..78ca3172 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/accordion/accordion-tab/accordion-tab.component.html @@ -0,0 +1,27 @@ + + + + +
+ + +

{{header}}

+
+ +

{{header}}
{{subHeader}}

+
+
+
+
+ + + + + + + + +
\ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/accordion/accordion-tab/accordion-tab.component.scss b/Mohem/src/app/hmg-common/ui/accordion/accordion-tab/accordion-tab.component.scss new file mode 100644 index 00000000..1870ffd4 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/accordion/accordion-tab/accordion-tab.component.scss @@ -0,0 +1,72 @@ +.header { + width: 100%; +} + +.grid { + padding-top: 0; +} + +.tab-header { + padding: 0; + margin: 0; + border-color: #e2e2e2; + border-style: solid; + border-width: 0cm 0cm 0.02cm 0cm; + padding-top: 0.2cm; + padding-bottom: 0.2cm; +} + +.icon { + + height: 0.9cm; + display: inline; + vertical-align: middle; + margin-left: 0.1cm; + margin-right: 0.1cm; + float: left; +} + +.left { + float: left; +} + +.right { + float: right; +} + +.title { + margin: 0; + margin-top: 0.2cm; + margin-left: 0.2cm; + margin-right: 0.2cm; + color: var(--ion-color-primary); + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden !important; + font-size: 0.36cm; + width: 78%; + +} + +.title-subtitle { + margin: 0; + margin-top: 0.2cm; + margin-left: 0.2cm; + margin-right: 0.2cm; + color: var(--ion-color-primary); + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden !important; + font-size: 0.36cm; + width: 78%; + +} +.innerheader h6 { + margin: 0em !important; +} + +h6 +{ + margin: 0em !important; +} + diff --git a/Mohem/src/app/hmg-common/ui/accordion/accordion-tab/accordion-tab.component.spec.ts b/Mohem/src/app/hmg-common/ui/accordion/accordion-tab/accordion-tab.component.spec.ts new file mode 100644 index 00000000..daf96201 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/accordion/accordion-tab/accordion-tab.component.spec.ts @@ -0,0 +1,27 @@ +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AccordionTabPage } from './accordion-tab.page'; + +describe('AccordionTabPage', () => { + let component: AccordionTabPage; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ AccordionTabPage ], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(AccordionTabPage); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/ui/accordion/accordion-tab/accordion-tab.component.ts b/Mohem/src/app/hmg-common/ui/accordion/accordion-tab/accordion-tab.component.ts new file mode 100644 index 00000000..e5ecb449 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/accordion/accordion-tab/accordion-tab.component.ts @@ -0,0 +1,50 @@ +import { Component, OnInit, Output, EventEmitter, Input, Host } from '@angular/core'; +import { AccordionComponent } from '../accordion.component'; +import { TranslatorService } from 'src/app/hmg-common/services/translator/translator.service'; + +@Component({ + selector: 'accordion-tab', + templateUrl: './accordion-tab.component.html', + styleUrls: ['./accordion-tab.component.scss'], +}) +export class AccordionTabComponent implements OnInit { + + private id: number; + public show = false; + public direction = 'ltr'; + @Input() header: string; + @Input() subHeader: string; + @Input() cache = true; + @Input() color = 'primary'; + @Output() selected = new EventEmitter(); + + // will be initialized by parent using @ContentChildren + private accordion: AccordionComponent; + constructor( + public ts: TranslatorService + ) { + } + + ngOnInit() { + this.direction = TranslatorService.getCurrentDirection(); + } + + public setVisibility(show: boolean) { + this.show = show; + } + + public setAccordion(accordion: AccordionComponent) { + this.accordion = accordion; + } + + public onClick() { + this.setVisibility(!this.show); + if (this.show) { + if (this.accordion) { + this.accordion.tabClicked(this); + } + } + + } + +} diff --git a/Mohem/src/app/hmg-common/ui/accordion/accordion.component.html b/Mohem/src/app/hmg-common/ui/accordion/accordion.component.html new file mode 100644 index 00000000..cb366b31 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/accordion/accordion.component.html @@ -0,0 +1,2 @@ + + diff --git a/Mohem/src/app/hmg-common/ui/accordion/accordion.component.scss b/Mohem/src/app/hmg-common/ui/accordion/accordion.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/Mohem/src/app/hmg-common/ui/accordion/accordion.component.spec.ts b/Mohem/src/app/hmg-common/ui/accordion/accordion.component.spec.ts new file mode 100644 index 00000000..053cb349 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/accordion/accordion.component.spec.ts @@ -0,0 +1,27 @@ +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AccordionPage } from './accordion.page'; + +describe('AccordionPage', () => { + let component: AccordionPage; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ AccordionPage ], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(AccordionPage); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/ui/accordion/accordion.component.ts b/Mohem/src/app/hmg-common/ui/accordion/accordion.component.ts new file mode 100644 index 00000000..7837e849 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/accordion/accordion.component.ts @@ -0,0 +1,53 @@ +import { Component, OnInit, ViewChildren, QueryList, Input, AfterViewInit, ContentChildren, AfterContentInit, OnDestroy } from '@angular/core'; +import { AccordionTabComponent } from './accordion-tab/accordion-tab.component'; + +@Component({ + selector: 'accordion', + templateUrl: './accordion.component.html', + styleUrls: ['./accordion.component.scss'], +}) +export class AccordionComponent implements OnInit, AfterContentInit, OnDestroy { + @ContentChildren(AccordionTabComponent) tabs !: QueryList; + @Input() activeIndex: number; + private destroyed = false; + constructor() { } + + ngOnInit() { + + } + + ngOnDestroy(): void { + this.destroyed = true; + } + ngAfterContentInit() { + this.tabs.notifyOnChanges(); + this.tabs.changes.subscribe(() => { + this.processChildren(); + }); + this.processChildren(); + } + + private processChildren() { + // this.tabs.notifyOnChanges(); + this.tabs.forEach((item: AccordionTabComponent, index) => { + item.setAccordion(this); + if (index === this.activeIndex) { + setTimeout(() => { + if (!this.destroyed) { + item.setVisibility(true); + } + }, 200); + } + }); + } + + public tabClicked(clickedTab: AccordionTabComponent) { + this.tabs.forEach((tab: AccordionTabComponent) => { + if (tab !== clickedTab) { + tab.setVisibility(false); + } else { + } + }); + } + +} diff --git a/Mohem/src/app/hmg-common/ui/alert/alert-controller.service.spec.ts b/Mohem/src/app/hmg-common/ui/alert/alert-controller.service.spec.ts new file mode 100644 index 00000000..c0cd7c6a --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/alert/alert-controller.service.spec.ts @@ -0,0 +1,12 @@ +import { TestBed } from '@angular/core/testing'; + +import { AlertControllerService } from './alert-controller.service'; + +describe('AlertControllerService', () => { + beforeEach(() => TestBed.configureTestingModule({})); + + it('should be created', () => { + const service: AlertControllerService = TestBed.get(AlertControllerService); + expect(service).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/ui/alert/alert-controller.service.ts b/Mohem/src/app/hmg-common/ui/alert/alert-controller.service.ts new file mode 100644 index 00000000..34c3db87 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/alert/alert-controller.service.ts @@ -0,0 +1,78 @@ +import { Injectable } from '@angular/core'; + +@Injectable({ + providedIn: 'root' +}) +export class AlertControllerService { + + private static id = 'custom-confirm-dialog'; + constructor() { } + + + public presentConfirm(title: string, message: string, okLabel: string, onConfirm: any, onCancel?: any) { + this.dismiss(); + document.body.appendChild(this.createDialog(title, message, okLabel)); + this.registerEvents(onConfirm, onCancel); + } + + public dismiss() { + const element = document.getElementById(AlertControllerService.id); + if (element) { + element.remove(); + } + } + + private registerEvents(onConfirm: any, onCancel?: any) { + const okButton = document.getElementById('alert-dialog-ok'); + + okButton.addEventListener('click', (e) => { + if (onConfirm) { + onConfirm(); + } + e.stopImmediatePropagation(); + }); + + const cancelButton = document.getElementById('alert-dialog-cancel'); + cancelButton.addEventListener('click', (e) => { + + if (onCancel) { + onCancel(); + } else { + this.dismiss(); + } + e.stopImmediatePropagation(); + }); + + const dialog = document.getElementById(AlertControllerService.id); + dialog.addEventListener('click', (e) => { + this.dismiss(); + e.stopImmediatePropagation(); + }); + } + + private innerTemplate(title: string, message: string, okLabel: string) { + + const template = + // tslint:disable-next-line:quotemark + "
" + "

" + title + "

" + + // tslint:disable-next-line:quotemark + "

" + message + "

" + "
" + + // tslint:disable-next-line:quotemark + " " + " " + "
" + "
"; + + return template; + } + + private createDialog(title: string, message: string, okLabel: string) { + const elemDiv = document.createElement('div'); + elemDiv.id = AlertControllerService.id; + elemDiv.className = 'alert-dialog-page'; + elemDiv.innerHTML = this.innerTemplate(title, message, okLabel); + return elemDiv; + + } + +} + diff --git a/Mohem/src/app/hmg-common/ui/back-button/back-button.component.html b/Mohem/src/app/hmg-common/ui/back-button/back-button.component.html new file mode 100644 index 00000000..a533286a --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/back-button/back-button.component.html @@ -0,0 +1,3 @@ +

+ back-button works! +

diff --git a/Mohem/src/app/hmg-common/ui/back-button/back-button.component.scss b/Mohem/src/app/hmg-common/ui/back-button/back-button.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/Mohem/src/app/hmg-common/ui/back-button/back-button.component.spec.ts b/Mohem/src/app/hmg-common/ui/back-button/back-button.component.spec.ts new file mode 100644 index 00000000..021c1fb3 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/back-button/back-button.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { BackButtonComponent } from './back-button.component'; + +describe('BackButtonComponent', () => { + let component: BackButtonComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ BackButtonComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(BackButtonComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/ui/back-button/back-button.component.ts b/Mohem/src/app/hmg-common/ui/back-button/back-button.component.ts new file mode 100644 index 00000000..debcd64a --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/back-button/back-button.component.ts @@ -0,0 +1,15 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'app-back-button', + templateUrl: './back-button.component.html', + styleUrls: ['./back-button.component.scss'] +}) +export class BackButtonComponent implements OnInit { + + constructor() { } + + ngOnInit() { + } + +} diff --git a/Mohem/src/app/hmg-common/ui/bar-chart/bar-chart.component.html b/Mohem/src/app/hmg-common/ui/bar-chart/bar-chart.component.html new file mode 100644 index 00000000..cbdaa351 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/bar-chart/bar-chart.component.html @@ -0,0 +1,12 @@ +
+ + +
diff --git a/Mohem/src/app/hmg-common/ui/bar-chart/bar-chart.component.scss b/Mohem/src/app/hmg-common/ui/bar-chart/bar-chart.component.scss new file mode 100644 index 00000000..a087838c --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/bar-chart/bar-chart.component.scss @@ -0,0 +1,4 @@ +.canvas-container-coordinates{ + width:100%; + height:500px ; +} \ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/bar-chart/bar-chart.component.spec.ts b/Mohem/src/app/hmg-common/ui/bar-chart/bar-chart.component.spec.ts new file mode 100644 index 00000000..c4d89509 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/bar-chart/bar-chart.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { BarChartComponent } from './bar-chart.component'; + +describe('BarChartComponent', () => { + let component: BarChartComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ BarChartComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(BarChartComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/ui/bar-chart/bar-chart.component.ts b/Mohem/src/app/hmg-common/ui/bar-chart/bar-chart.component.ts new file mode 100644 index 00000000..721378f5 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/bar-chart/bar-chart.component.ts @@ -0,0 +1,28 @@ +import { Component, OnInit, Input } from '@angular/core'; + +@Component({ + selector: 'bar-chart', + templateUrl: './bar-chart.component.html', + styleUrls: ['./bar-chart.component.scss'] +}) +export class BarChartComponent implements OnInit { + view: any[] = [0, 0]; + + // options + showXAxis = true; + showYAxis = true; + gradient = false; + showLegend = false; + showXAxisLabel = true; + showYAxisLabel = true; + xAxisLabel = ''; + colorScheme = { + domain: ['#3880ff'] + }; + + @Input() data: any[] ; + constructor() { } + + ngOnInit() { + } +} diff --git a/Mohem/src/app/hmg-common/ui/button/button.component.html b/Mohem/src/app/hmg-common/ui/button/button.component.html new file mode 100644 index 00000000..4beff4a7 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/button/button.component.html @@ -0,0 +1,19 @@ + + + + +
+ +

{{title}}

+
+ + +
+
\ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/button/button.component.scss b/Mohem/src/app/hmg-common/ui/button/button.component.scss new file mode 100644 index 00000000..7ef033f0 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/button/button.component.scss @@ -0,0 +1,62 @@ +.custom-button { + width: 96%; + margin-left: 2%; + margin-right: 2%; + height: 4cm; + box-shadow: 0px 0px 8px 2px #d5d5d5ab; + background: white; + margin-bottom: 0.3cm; + border-color: #ececec; + border-style: solid; + border-width: 0.02cm; +} + +.custom-button:hover { + -webkit-box-shadow: 0px 0px 8px 2px #d1212747;; + -moz-box-shadow: 0px 0px 8px 2px #d1212747;; + box-shadow: 0px 0px 8px 2px #d1212747;; +} + + + +.icon{ + margin-top: 0.7cm; + margin-left: 27%; + margin-right: 27%; + width: 46%; + -o-object-fit: contain; + object-fit: contain; + max-height: 2.4cm; +} + + +.title { + margin: 0; + padding: 0; + margin-top: .1cm; + margin-left: 6%; + margin-right: 6%; + width: 88%; + text-align: center; + font-size: 0.38cm; + color: var(--ion-color-secondary); +} + +.overlay { + background: white; + opacity: 0.6; + position: absolute; + left: 0; + right: 0; + width: 100%; + bottom: 0; + top: 0; + height: 100%; + z-index: 10; +} + +@media (orientation: landscape) { + .custom-button { + height: 4.5cm; + } +} \ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/button/button.component.spec.ts b/Mohem/src/app/hmg-common/ui/button/button.component.spec.ts new file mode 100644 index 00000000..fec87372 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/button/button.component.spec.ts @@ -0,0 +1,27 @@ +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ButtonPage } from './button.page'; + +describe('ButtonPage', () => { + let component: ButtonPage; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ButtonPage ], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ButtonPage); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/ui/button/button.component.ts b/Mohem/src/app/hmg-common/ui/button/button.component.ts new file mode 100644 index 00000000..8f8ffc13 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/button/button.component.ts @@ -0,0 +1,80 @@ +import { Component, OnInit, Input, Output, EventEmitter, Directive, ElementRef, HostListener } from '@angular/core'; +import { ButtonSettings } from './models/button-settingsl'; +import { TranslatorService } from '../../services/translator/translator.service'; + +@Component({ + selector: 'app-button', + templateUrl: './button.component.html', + styleUrls: ['./button.component.scss'], +}) +export class ButtonComponent implements OnInit { + + @Input() icon: string; + @Input() title: string; + @Output() trigger = new EventEmitter(); + @Input() settings: ButtonSettings; + public direction: string; + public style: any; + @Input() disabled = false; + constructor( + public ts: TranslatorService + ) { + + } + + ngOnInit() { + this.direction = TranslatorService.getCurrentDirection(); + if (this.settings) { + this.style = + { + 'border-top-left-radius': this.isEnabled(this.settings.topLeft), + 'border-top-right-radius': this.isEnabled(this.settings.topRight), + 'border-bottom-right-radius': this.isEnabled(this.settings.bottomRight), + 'border-bottom-left-radius': this.isEnabled(this.settings.bottomLeft) + }; + } + + /* + const element = document.getElementById('modal'); + element.addEventListener('click', e => { + e.stopImmediatePropagation(); + }); + */ + } + + private isEnabled(enabled: boolean): string { + return enabled ? '30px' : '0px'; + } + public onClicked() { + if (!this.disabled) { + this.trigger.emit(); + } + } + + +} + +@Directive({ selector: '[modal]' }) +export class Modal implements OnInit { + + constructor(private elRef: ElementRef) { } + + ngOnInit() { + console.log(' on initialization'); + //this.elRef.nativeElement.addEventListener('mouseenter', this.onMouseEnter); + } + + ngOnDestroy() { + // this.elRef.nativeElement.removeEventListener('mouseenter', this.onMouseEnter); + } + + onMouseEnter() { + // alert("Don't touch my bacon!") + } + + @HostListener('click', ['$event']) + onClick(event: any) { + alert('click'); + // event.preventPropagation(); + } +} diff --git a/Mohem/src/app/hmg-common/ui/button/models/button-settingsl.ts b/Mohem/src/app/hmg-common/ui/button/models/button-settingsl.ts new file mode 100644 index 00000000..f7ff026b --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/button/models/button-settingsl.ts @@ -0,0 +1,10 @@ +export class ButtonSettings { + constructor( + public topLeft = true, + public topRight = true, + public bottomLeft = true, + public bottomRight = true + ) { + + } +} \ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/date-select/date-select.component.html b/Mohem/src/app/hmg-common/ui/date-select/date-select.component.html new file mode 100644 index 00000000..63107c7a --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/date-select/date-select.component.html @@ -0,0 +1,10 @@ +
+ {{title}} + + + + + + + +
diff --git a/Mohem/src/app/hmg-common/ui/date-select/date-select.component.scss b/Mohem/src/app/hmg-common/ui/date-select/date-select.component.scss new file mode 100644 index 00000000..95be26ab --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/date-select/date-select.component.scss @@ -0,0 +1,8 @@ +ion-label{ + margin-left:0.3cm; +} + +.select-date-container { + margin-top: 0.4cm; + +} \ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/date-select/date-select.component.spec.ts b/Mohem/src/app/hmg-common/ui/date-select/date-select.component.spec.ts new file mode 100644 index 00000000..73326ea7 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/date-select/date-select.component.spec.ts @@ -0,0 +1,27 @@ +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { DateSelectPage } from './date-select.page'; + +describe('DateSelectPage', () => { + let component: DateSelectPage; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ DateSelectPage ], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(DateSelectPage); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/ui/date-select/date-select.component.ts b/Mohem/src/app/hmg-common/ui/date-select/date-select.component.ts new file mode 100644 index 00000000..7ef182c4 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/date-select/date-select.component.ts @@ -0,0 +1,22 @@ +import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; +import { TranslatorService } from '../../services/translator/translator.service'; + +@Component({ + selector: 'date-select', + templateUrl: './date-select.component.html', + styleUrls: ['./date-select.component.scss'], +}) +export class DateSelectComponent implements OnInit { + + selectedDate: string; + @Output() select = new EventEmitter(); + @Input() title; + constructor(public tr: TranslatorService) { } + + ngOnInit() {} + + public selectDate() { + this.select.emit(this.selectedDate); + } + +} diff --git a/Mohem/src/app/hmg-common/ui/detail-button/detail-button.component.html b/Mohem/src/app/hmg-common/ui/detail-button/detail-button.component.html new file mode 100644 index 00000000..b4e8f97c --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/detail-button/detail-button.component.html @@ -0,0 +1,6 @@ + + + {{title}} + + + \ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/detail-button/detail-button.component.scss b/Mohem/src/app/hmg-common/ui/detail-button/detail-button.component.scss new file mode 100644 index 00000000..924bb2c6 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/detail-button/detail-button.component.scss @@ -0,0 +1,7 @@ +.icon { + width: 1.5cm; +} + +.arrow { + width: 0.4cm; +} \ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/detail-button/detail-button.component.spec.ts b/Mohem/src/app/hmg-common/ui/detail-button/detail-button.component.spec.ts new file mode 100644 index 00000000..848332eb --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/detail-button/detail-button.component.spec.ts @@ -0,0 +1,27 @@ +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { DetailButtonPage } from './detail-button.page'; + +describe('DetailButtonPage', () => { + let component: DetailButtonPage; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ DetailButtonPage ], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(DetailButtonPage); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/ui/detail-button/detail-button.component.ts b/Mohem/src/app/hmg-common/ui/detail-button/detail-button.component.ts new file mode 100644 index 00000000..d76eacf0 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/detail-button/detail-button.component.ts @@ -0,0 +1,30 @@ +import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; +import { CommonService } from '../../services/common/common.service'; +import { TranslatorService } from '../../services/translator/translator.service'; + +@Component({ + selector: 'detail-button', + templateUrl: './detail-button.component.html', + styleUrls: ['./detail-button.component.scss'], +}) +export class DetailButtonComponent implements OnInit { + + @Input() src: string; + @Input() title: string; + @Output() click = new EventEmitter(); + public direction; + + constructor( + public cs: CommonService, + public ts: TranslatorService + ) { } + + ngOnInit() { + this.direction = TranslatorService.getCurrentDirection(); + } + + public onClick(event: any) { + this.click.emit(event); + } + +} diff --git a/Mohem/src/app/hmg-common/ui/divider/divider.component.html b/Mohem/src/app/hmg-common/ui/divider/divider.component.html new file mode 100644 index 00000000..75db751a --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/divider/divider.component.html @@ -0,0 +1 @@ +
\ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/divider/divider.component.scss b/Mohem/src/app/hmg-common/ui/divider/divider.component.scss new file mode 100644 index 00000000..c68e95a2 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/divider/divider.component.scss @@ -0,0 +1,8 @@ +.divider { + width: 96%; + margin-left: 2%; + margin-right: 2%; + height: 0.04cm; + background-color: rgba(0, 0, 0, 0.2); + float: left; +} \ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/divider/divider.component.spec.ts b/Mohem/src/app/hmg-common/ui/divider/divider.component.spec.ts new file mode 100644 index 00000000..47b4fd34 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/divider/divider.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { DividerComponent } from './divider.component'; + +describe('DividerComponent', () => { + let component: DividerComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ DividerComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(DividerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/ui/divider/divider.component.ts b/Mohem/src/app/hmg-common/ui/divider/divider.component.ts new file mode 100644 index 00000000..f563bdcd --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/divider/divider.component.ts @@ -0,0 +1,15 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'divider', + templateUrl: './divider.component.html', + styleUrls: ['./divider.component.scss'] +}) +export class DividerComponent implements OnInit { + + constructor() { } + + ngOnInit() { + } + +} diff --git a/Mohem/src/app/hmg-common/ui/donut-chart/donut-chart.component.html b/Mohem/src/app/hmg-common/ui/donut-chart/donut-chart.component.html new file mode 100644 index 00000000..543a0cd8 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/donut-chart/donut-chart.component.html @@ -0,0 +1,14 @@ +
+ + +
diff --git a/Mohem/src/app/hmg-common/ui/donut-chart/donut-chart.component.scss b/Mohem/src/app/hmg-common/ui/donut-chart/donut-chart.component.scss new file mode 100644 index 00000000..72eecc07 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/donut-chart/donut-chart.component.scss @@ -0,0 +1,4 @@ +.canvas-container-coordinates { + width:100%; + height:500px; +} \ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/donut-chart/donut-chart.component.spec.ts b/Mohem/src/app/hmg-common/ui/donut-chart/donut-chart.component.spec.ts new file mode 100644 index 00000000..8c299a9e --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/donut-chart/donut-chart.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { DonutChartComponent } from './donut-chart.component'; + +describe('DonutChartComponent', () => { + let component: DonutChartComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ DonutChartComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(DonutChartComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/ui/donut-chart/donut-chart.component.ts b/Mohem/src/app/hmg-common/ui/donut-chart/donut-chart.component.ts new file mode 100644 index 00000000..2167a12a --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/donut-chart/donut-chart.component.ts @@ -0,0 +1,23 @@ +import { Component, OnInit, Input } from '@angular/core'; + +@Component({ + selector: 'donut-chart', + templateUrl: './donut-chart.component.html', + styleUrls: ['./donut-chart.component.scss'] +}) +export class DonutChartComponent implements OnInit { + + // options + @Input() legend = true; + @Input() arcWidth = 0.25; + @Input() colorScheme = { + domain: ['#3880ff' , '#ccdeff'] + }; + @Input() data: any[] ; + view = [0, 0]; + constructor() { } + + ngOnInit() { + } + +} diff --git a/Mohem/src/app/hmg-common/ui/dynamic-table/dynamic-table.component.html b/Mohem/src/app/hmg-common/ui/dynamic-table/dynamic-table.component.html new file mode 100644 index 00000000..ab4d9c67 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/dynamic-table/dynamic-table.component.html @@ -0,0 +1,28 @@ + + +

{{title | translate}}

+ + + + + +

{{header | translate}}

+
+
+ + + + +

{{ dataObject[prop] | ifDate }}

+
+ +
+ + + + +

{{ 'general,empty'| translate }}

+
+
+ +
\ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/dynamic-table/dynamic-table.component.scss b/Mohem/src/app/hmg-common/ui/dynamic-table/dynamic-table.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/Mohem/src/app/hmg-common/ui/dynamic-table/dynamic-table.component.spec.ts b/Mohem/src/app/hmg-common/ui/dynamic-table/dynamic-table.component.spec.ts new file mode 100644 index 00000000..7d64e4fb --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/dynamic-table/dynamic-table.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { DynamicTableComponent } from './dynamic-table.component'; + +describe('DynamicTableComponent', () => { + let component: DynamicTableComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ DynamicTableComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(DynamicTableComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/ui/dynamic-table/dynamic-table.component.ts b/Mohem/src/app/hmg-common/ui/dynamic-table/dynamic-table.component.ts new file mode 100644 index 00000000..70882e6b --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/dynamic-table/dynamic-table.component.ts @@ -0,0 +1,38 @@ +import { Component, OnInit, Input } from '@angular/core'; + +@Component({ + selector: 'dynamic-table', + templateUrl: './dynamic-table.component.html', + styleUrls: ['./dynamic-table.component.scss'] +}) +export class DynamicTableComponent implements OnInit { + @Input() objectsArray: any[]; + @Input() properties: string[]; + @Input() headers: string[]; + @Input() title: string; + @Input() validValuesOnly = false; + constructor() { } + + ngOnInit() { + + } + + /* + row is valid if has no integer with 0 value + */ + public isValidRow(objectData: any): boolean { + + if (this.validValuesOnly) { + for (const property of this.properties) { + const value = objectData[property]; + if (typeof value === 'number') { + if (value === 0) { + return false; + } + } + } + } + return true; + } + +} diff --git a/Mohem/src/app/hmg-common/ui/email/email.component.html b/Mohem/src/app/hmg-common/ui/email/email.component.html new file mode 100644 index 00000000..b2e5d366 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/email/email.component.html @@ -0,0 +1,4 @@ + + {{ 'general,email' | translate}} + + \ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/email/email.component.scss b/Mohem/src/app/hmg-common/ui/email/email.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/Mohem/src/app/hmg-common/ui/email/email.component.spec.ts b/Mohem/src/app/hmg-common/ui/email/email.component.spec.ts new file mode 100644 index 00000000..f435ad93 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/email/email.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { EmailComponent } from './email.component'; + +describe('EmailComponent', () => { + let component: EmailComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ EmailComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(EmailComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/ui/email/email.component.ts b/Mohem/src/app/hmg-common/ui/email/email.component.ts new file mode 100644 index 00000000..6211c7b7 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/email/email.component.ts @@ -0,0 +1,25 @@ +import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; +import { CommonService } from '../../services/common/common.service'; +import { EmailInput } from './models/email-input'; + +@Component({ + selector: 'app-email', + templateUrl: './email.component.html', + styleUrls: ['./email.component.scss'] +}) +export class EmailComponent implements OnInit { + + @Input() value: EmailInput; + @Output() emailEntered = new EventEmitter(); + constructor( + public cs: CommonService + ) { } + + ngOnInit() { + } + + public triggerValue() { + this.emailEntered.emit(this.value); + } + +} diff --git a/Mohem/src/app/hmg-common/ui/email/models/email-input.ts b/Mohem/src/app/hmg-common/ui/email/models/email-input.ts new file mode 100644 index 00000000..148c44af --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/email/models/email-input.ts @@ -0,0 +1,25 @@ +export class EmailInput { + public email: string; + + public static isValidEmail(email: string) { + if (!EmailInput.isTempEmail(email)) { + const parts: string[] = email.split('@'); + if (parts.length === 2) { + return parts[1].indexOf('.') > 0; + } + } + return false; + } + + private static isTempEmail(email: string) { + if (email === null || email.length <= 0) { return true; } + if (email.indexOf('unknown') >= 0) { return true; } + if (email.indexOf('A@A.com') >= 0) { return true; } + return false; + } + + public isValid() { + return EmailInput.isValidEmail(this.email); + } + +} diff --git a/Mohem/src/app/hmg-common/ui/empty-data/empty-data.component.html b/Mohem/src/app/hmg-common/ui/empty-data/empty-data.component.html new file mode 100644 index 00000000..6989fe5c --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/empty-data/empty-data.component.html @@ -0,0 +1,9 @@ + + + + +

{{'general,empty' | translate}}

+
+
+
+
\ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/empty-data/empty-data.component.scss b/Mohem/src/app/hmg-common/ui/empty-data/empty-data.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/Mohem/src/app/hmg-common/ui/empty-data/empty-data.component.spec.ts b/Mohem/src/app/hmg-common/ui/empty-data/empty-data.component.spec.ts new file mode 100644 index 00000000..df72c8f4 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/empty-data/empty-data.component.spec.ts @@ -0,0 +1,27 @@ +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { EmptyDataPage } from './empty-data.page'; + +describe('EmptyDataPage', () => { + let component: EmptyDataPage; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ EmptyDataPage ], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(EmptyDataPage); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/ui/empty-data/empty-data.component.ts b/Mohem/src/app/hmg-common/ui/empty-data/empty-data.component.ts new file mode 100644 index 00000000..d539711c --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/empty-data/empty-data.component.ts @@ -0,0 +1,14 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'empty-data', + templateUrl: './empty-data.component.html', + styleUrls: ['./empty-data.component.scss'], +}) +export class EmptyDataComponent implements OnInit { + + constructor() { } + + ngOnInit() {} + +} diff --git a/Mohem/src/app/hmg-common/ui/expandable/expandable.component.html b/Mohem/src/app/hmg-common/ui/expandable/expandable.component.html new file mode 100644 index 00000000..f0c7a765 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/expandable/expandable.component.html @@ -0,0 +1,3 @@ +
+ +
\ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/expandable/expandable.component.scss b/Mohem/src/app/hmg-common/ui/expandable/expandable.component.scss new file mode 100644 index 00000000..90f57920 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/expandable/expandable.component.scss @@ -0,0 +1,3 @@ +.exp_container{ + +} \ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/expandable/expandable.component.spec.ts b/Mohem/src/app/hmg-common/ui/expandable/expandable.component.spec.ts new file mode 100644 index 00000000..591a0015 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/expandable/expandable.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ExpandableComponent } from './expandable.component'; + +describe('ExpandableComponent', () => { + let component: ExpandableComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ExpandableComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ExpandableComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/ui/expandable/expandable.component.ts b/Mohem/src/app/hmg-common/ui/expandable/expandable.component.ts new file mode 100644 index 00000000..e8314b92 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/expandable/expandable.component.ts @@ -0,0 +1,15 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'app-expandable', + templateUrl: './expandable.component.html', + styleUrls: ['./expandable.component.scss'] +}) +export class ExpandableComponent implements OnInit { + + constructor() { } + + ngOnInit() { + } + +} diff --git a/Mohem/src/app/hmg-common/ui/face-avatar/face-avatar.component.html b/Mohem/src/app/hmg-common/ui/face-avatar/face-avatar.component.html new file mode 100644 index 00000000..42c35f66 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/face-avatar/face-avatar.component.html @@ -0,0 +1,13 @@ + + + + + +
+ +
+
+
\ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/face-avatar/face-avatar.component.scss b/Mohem/src/app/hmg-common/ui/face-avatar/face-avatar.component.scss new file mode 100644 index 00000000..017b91a7 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/face-avatar/face-avatar.component.scss @@ -0,0 +1,7 @@ +.face-avatar { + width: 100%; + + background-position: center !important; + background-size: contain !important; + background-repeat: no-repeat !important; +} \ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/face-avatar/face-avatar.component.spec.ts b/Mohem/src/app/hmg-common/ui/face-avatar/face-avatar.component.spec.ts new file mode 100644 index 00000000..429ce546 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/face-avatar/face-avatar.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { FaceAvatarComponent } from './face-avatar.component'; + +describe('FaceAvatarComponent', () => { + let component: FaceAvatarComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ FaceAvatarComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(FaceAvatarComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/ui/face-avatar/face-avatar.component.ts b/Mohem/src/app/hmg-common/ui/face-avatar/face-avatar.component.ts new file mode 100644 index 00000000..4e99ec0c --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/face-avatar/face-avatar.component.ts @@ -0,0 +1,23 @@ +import { Component, OnInit, Output, EventEmitter } from '@angular/core'; +import { Input } from '@angular/core'; +@Component({ + selector: 'face-avatar', + templateUrl: './face-avatar.component.html', + styleUrls: ['./face-avatar.component.scss'] +}) +export class FaceAvatarComponent implements OnInit { + + @Input() image: string; + @Input() height = '2.8cm'; + @Output() error: EventEmitter = new EventEmitter(); + + constructor() { } + + ngOnInit() { + } + + public failedToLoadImage() { + this.error.emit(); + } + +} diff --git a/Mohem/src/app/hmg-common/ui/file-uploader/file-uploader.component.html b/Mohem/src/app/hmg-common/ui/file-uploader/file-uploader.component.html new file mode 100644 index 00000000..5e4d2dac --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/file-uploader/file-uploader.component.html @@ -0,0 +1,13 @@ + + + + {{'general,select-attachment' | translate}} + + +
+ +

{{file.name}}

+

+
+
\ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/file-uploader/file-uploader.component.scss b/Mohem/src/app/hmg-common/ui/file-uploader/file-uploader.component.scss new file mode 100644 index 00000000..56325173 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/file-uploader/file-uploader.component.scss @@ -0,0 +1,5 @@ +.uploader-icons img{ + width: .7cm; + height: .6cm; + vertical-align: middle; +} \ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/file-uploader/file-uploader.component.spec.ts b/Mohem/src/app/hmg-common/ui/file-uploader/file-uploader.component.spec.ts new file mode 100644 index 00000000..fc21b866 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/file-uploader/file-uploader.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { FileUploaderComponent } from './file-uploader.component'; + +describe('FileUploaderComponent', () => { + let component: FileUploaderComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ FileUploaderComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(FileUploaderComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/ui/file-uploader/file-uploader.component.ts b/Mohem/src/app/hmg-common/ui/file-uploader/file-uploader.component.ts new file mode 100644 index 00000000..77483e15 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/file-uploader/file-uploader.component.ts @@ -0,0 +1,100 @@ +import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; +import { CommonService } from 'src/app/hmg-common/services/common/common.service'; +import { TranslatorService } from 'src/app/hmg-common/services/translator/translator.service'; +import { AlertController } from '@ionic/angular'; + + +export interface CustomWindow extends Window { + File: any; + FileReader: any; +} +declare let window: CustomWindow; + +@Component({ + selector: 'file-uploader', + templateUrl: './file-uploader.component.html', + styleUrls: ['./file-uploader.component.scss'] +}) +export class FileUploaderComponent implements OnInit { + @Input() multiupload = false; + @Input() attachmentname = 'attachment-loader'; + public attachmentData: string; + @Input() maxFileSize = 10 * 1024 * 1024; + @Output() fileSelected = new EventEmitter(); + public inputFiles: any = []; + public attachmentImg = 'assets/icon/attachment.png'; + public deleteImg = 'assets/icon/delete.png'; + constructor( + public cs: CommonService, + public ts: TranslatorService, + public alertController: AlertController + ) { + } + + ngOnInit() { + } + + + public loadAttachment(changeEvent) { + const fileInput = this.getFileElement(); + if (this.isFileSupported()) { + if (fileInput.files != null && fileInput.files.length > 0) { + const file = fileInput.files[0]; + const reader = new FileReader(); + if (file.size <= this.maxFileSize) { + reader.onload = (data) => { + if (this.multiupload) { + this.inputFiles.push({name: file.name, data: data.target['result']}); + } else { + this.inputFiles = [{name: file.name, data: data.target['result']}]; + } + this.fileSelected.emit( { + name: file.name , + data: data.target['result'], + inputFiles: this.inputFiles + }); + }; + reader.readAsDataURL(file); + } else { + this.attachmentData = null; + changeEvent.target.value = ''; // remove current selection + this.showFileExceededMaxSize(); + } + } else { + this.attachmentData = null; + } + } + } + + private isFileSupported() { + return (window.FileReader && window.File); + } + + private showFileExceededMaxSize() { + this.cs.presentConfirmDialog( + this.ts.trPK('general', 'large-file'), + () => { + this.openFile(); + }, + () => { + } + ); + } + + private getFileElement(): HTMLInputElement { + return document.getElementById(this.attachmentname) as HTMLInputElement; + } + + public openFile() { + const fileInput = this.getFileElement(); + fileInput.click(); + } + private deleteFiles(index: number) { + this.inputFiles.splice(index, 1); + this.fileSelected.emit( { + name: null, + data: '', + inputFiles: this.inputFiles + }); + } +} diff --git a/Mohem/src/app/hmg-common/ui/footer/footer.component.html b/Mohem/src/app/hmg-common/ui/footer/footer.component.html new file mode 100644 index 00000000..49d8bec9 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/footer/footer.component.html @@ -0,0 +1,3 @@ +
+ +
\ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/footer/footer.component.scss b/Mohem/src/app/hmg-common/ui/footer/footer.component.scss new file mode 100644 index 00000000..e488bc4c --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/footer/footer.component.scss @@ -0,0 +1,15 @@ +.footer-area{ + position: fixed; + left: 0; + height: 1.5cm; + width: 100%; + overflow: hidden; +} + +.keyboard-closed { + bottom: 2.5cm; +} + +.keyboard-opened { + bottom: 0.1cm; +} diff --git a/Mohem/src/app/hmg-common/ui/footer/footer.component.spec.ts b/Mohem/src/app/hmg-common/ui/footer/footer.component.spec.ts new file mode 100644 index 00000000..8e7dd291 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/footer/footer.component.spec.ts @@ -0,0 +1,27 @@ +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { FooterPage } from './footer.page'; + +describe('FooterPage', () => { + let component: FooterPage; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ FooterPage ], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(FooterPage); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/ui/footer/footer.component.ts b/Mohem/src/app/hmg-common/ui/footer/footer.component.ts new file mode 100644 index 00000000..a870ddd8 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/footer/footer.component.ts @@ -0,0 +1,34 @@ +import { Component, OnInit } from '@angular/core'; +import { KeyboardService } from '../../services/keyboard/keyboard.service'; +import { Events, Platform } from '@ionic/angular'; +import { KeyboardStatusModel } from '../../services/keyboard/keyboard-status.model'; + +@Component({ + selector: 'footer', + templateUrl: './footer.component.html', + styleUrls: ['./footer.component.scss'], +}) +export class FooterComponent implements OnInit { + + public keyboardOpened = false; + constructor( + public events: Events, + public keyboardService: KeyboardService, + public platform: Platform + ) { } + + + ngOnInit() { + this.platform.ready().then(() => { + this.keyboardOpened = KeyboardService.keyboardOpened; + this.monitorKeyboardChange(); + }); + } + + private monitorKeyboardChange() { + this.events.subscribe ( KeyboardService.KEYBOARD_STATUS , ( status: KeyboardStatusModel) => { + this.keyboardOpened = status.opened; + }); + } + +} diff --git a/Mohem/src/app/hmg-common/ui/gender-select/gender-select.component.html b/Mohem/src/app/hmg-common/ui/gender-select/gender-select.component.html new file mode 100644 index 00000000..58a34411 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/gender-select/gender-select.component.html @@ -0,0 +1,13 @@ + + + {{ 'body,select.gender' | translate }} + + + + {{ 'body,female' | translate }} + + + {{ 'body,male' | translate }} + + + \ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/gender-select/gender-select.component.scss b/Mohem/src/app/hmg-common/ui/gender-select/gender-select.component.scss new file mode 100644 index 00000000..5bd75bc9 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/gender-select/gender-select.component.scss @@ -0,0 +1,24 @@ +ion-button{ + --background: var(--ion-color-light); + --color: var(--ion-color-primary); +} +.selected-button { + --background: var(--ion-color-secondary); + --color: var(--ion-color-light); + --background-activated: var(--ion-color-secondary); + --background-focused: var(--ion-color-secondary); + --color-activated: var(--ion-color-light); + --color-focused: var(--ion-color-light); +} + +ion-label{ + margin-left: 0.3cm; + margin-top:0.4cm; +} + + + .form-item { + margin-top: 0.2cm !important; + } + + \ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/gender-select/gender-select.component.spec.ts b/Mohem/src/app/hmg-common/ui/gender-select/gender-select.component.spec.ts new file mode 100644 index 00000000..59a7da3b --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/gender-select/gender-select.component.spec.ts @@ -0,0 +1,27 @@ +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { GenderSelectPage } from './gender-select.page'; + +describe('GenderSelectPage', () => { + let component: GenderSelectPage; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ GenderSelectPage ], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(GenderSelectPage); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/ui/gender-select/gender-select.component.ts b/Mohem/src/app/hmg-common/ui/gender-select/gender-select.component.ts new file mode 100644 index 00000000..91f6a14d --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/gender-select/gender-select.component.ts @@ -0,0 +1,36 @@ +import { Component, OnInit, Output, EventEmitter, Input } from '@angular/core'; + +@Component({ + selector: 'gender-select', + templateUrl: './gender-select.component.html', + styleUrls: ['./gender-select.component.scss'], +}) +export class GenderSelectComponent implements OnInit { + + @Input() isFemale = false; + @Input() isMale = false; + value: number; + @Output() selected = new EventEmitter(); + + constructor() { + } + + select(cond: boolean) { + if (cond) { + this.isFemale = true; + this.isMale = false; + this.value = 2; + this.selected.emit(this.value); + } else { + this.isFemale = false; + this.isMale = true; + this.value = 1; + this.selected.emit(this.value); + + } + } + ngOnInit() { + + } + +} diff --git a/Mohem/src/app/hmg-common/ui/graph/graph.component.html b/Mohem/src/app/hmg-common/ui/graph/graph.component.html new file mode 100644 index 00000000..2d1a6edf --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/graph/graph.component.html @@ -0,0 +1,24 @@ +
+ + + +
diff --git a/Mohem/src/app/hmg-common/ui/graph/graph.component.scss b/Mohem/src/app/hmg-common/ui/graph/graph.component.scss new file mode 100644 index 00000000..23da3b15 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/graph/graph.component.scss @@ -0,0 +1,6 @@ +.canvas-container-coordinates{ + max-height: 83%; + min-height: 78%; + max-width: 100%; + margin-top: 2%; +} \ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/graph/graph.component.spec.ts b/Mohem/src/app/hmg-common/ui/graph/graph.component.spec.ts new file mode 100644 index 00000000..3300b39e --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/graph/graph.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { GraphComponent } from './graph.component'; + +describe('GraphComponent', () => { + let component: GraphComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ GraphComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(GraphComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/ui/graph/graph.component.ts b/Mohem/src/app/hmg-common/ui/graph/graph.component.ts new file mode 100644 index 00000000..d3187a63 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/graph/graph.component.ts @@ -0,0 +1,44 @@ +import { Component, OnInit, Input } from '@angular/core'; +import * as shape from 'd3-shape'; +import * as d3 from 'd3'; +import { TranslatorService } from 'src/app/hmg-common/services/translator/translator.service'; + +@Component({ + selector: 'graph', + templateUrl: './graph.component.html', + styleUrls: ['./graph.component.scss'] +}) +export class GraphComponent implements OnInit { + + view: any[] = [0, 0]; + + // options + showXAxis = true; + showYAxis = true; + gradient = true; + showLegend = false; + showXAxisLabel = true; + xAxisLabel = 'Number'; + showYAxisLabel = true; + yAxisLabel = 'Color Value'; + curve = shape.curveNatural; + // curve = shape.curveLinear; + // curve = shape.curveBasis; + // curve = shape.curveBundle.beta(1.0); + timeline = true; + legendTitle = ''; + + colorScheme = { + domain: ['#3880ff' , '#5AA454' , '#A10A28', '#C7B42C', '#AAAAAA'] + }; + + @Input() data: any[] ; + constructor( + public ts: TranslatorService + ) { } + + ngOnInit() { + } + + public selected(event: any) { } +} diff --git a/Mohem/src/app/hmg-common/ui/header-button/header-button.component.html b/Mohem/src/app/hmg-common/ui/header-button/header-button.component.html new file mode 100644 index 00000000..b4eeceea --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/header-button/header-button.component.html @@ -0,0 +1,7 @@ + +
+ +

{{title}}

+
+
+ diff --git a/Mohem/src/app/hmg-common/ui/header-button/header-button.component.scss b/Mohem/src/app/hmg-common/ui/header-button/header-button.component.scss new file mode 100644 index 00000000..26ba86e8 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/header-button/header-button.component.scss @@ -0,0 +1,65 @@ +.email-ios { + position: fixed; + width: 1cm; + height: 1.2cm; + top: 0; + padding: 0; + margin: 0; +} + + +.email-ios img { + padding: 0; + margin: 0; + width: 60%; + margin-top: 0.1cm; + margin-left: 20%; + margin-right: 20%; +} + +.email-ios p { + font-size: 0.26cm; + color: var(--ion-color-primary); + padding: 0; + margin: 0; + font-weight: bold; + text-align: center; +} + +.right { + right: 0.3cm; + +} + +.left { + left: 0.3cm; +} + + +.email-android { + position: fixed; + width: 1cm; + height: 1.5cm; + top: 0; + padding: 0; + margin: 0; +} + + +.email-android img { + padding: 0; + margin: 0; + width: 70%; + margin-top: 0.2cm; + margin-left: 15%; + margin-right: 15%; +} + +.email-android p { + font-size: 0.28cm; + color: var(--ion-color-primary); + padding: 0; + margin: 0; + font-weight: bold; + text-align: center; +} diff --git a/Mohem/src/app/hmg-common/ui/header-button/header-button.component.spec.ts b/Mohem/src/app/hmg-common/ui/header-button/header-button.component.spec.ts new file mode 100644 index 00000000..c7348564 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/header-button/header-button.component.spec.ts @@ -0,0 +1,27 @@ +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { HeaderButtonPage } from './header-button.page'; + +describe('HeaderButtonPage', () => { + let component: HeaderButtonPage; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ HeaderButtonPage ], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(HeaderButtonPage); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/ui/header-button/header-button.component.ts b/Mohem/src/app/hmg-common/ui/header-button/header-button.component.ts new file mode 100644 index 00000000..3d1b6d3a --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/header-button/header-button.component.ts @@ -0,0 +1,64 @@ +import { Component, OnInit, Output, EventEmitter, OnDestroy, Input } from '@angular/core'; +import { TranslatorService } from '../../services/translator/translator.service'; +import { Platform, NavController } from '@ionic/angular'; +import { Router, NavigationEnd } from '@angular/router'; +import { Subscription } from 'rxjs'; + +@Component({ + selector: 'header-button', + templateUrl: './header-button.component.html', + styleUrls: ['./header-button.component.scss'], +}) +export class HeaderButtonComponent implements OnInit { + + public static IOS = 'ios'; + public static ANDROID = 'android'; + @Input() image: string; + @Input() title: string; + @Output() triggered = new EventEmitter(); + public hide = false; + public direction: string; + public os = HeaderButtonComponent.IOS; + public class = ''; + public routerSubscription: Subscription; + constructor( + public ts: TranslatorService, + public platform: Platform, + public router: Router + ) { + this.direction = TranslatorService.getCurrentDirection(); + } + + ngOnInit() { + this.platform.ready().then(() => { + this.os = this.platform.is('ios') ? HeaderButtonComponent.IOS : HeaderButtonComponent.ANDROID; + this.setClass(); + }); + + this.routerSubscription = this.router.events.subscribe((val) => { + // see also + if (val instanceof NavigationEnd) { + this.setClass('fadeOut'); + } + }); + + } + + public onClick() { + this.triggered.emit(); + } + + public setClass(destroyEffect?: string) { + if (this.direction === 'ltr') { + this.class = 'email-' + this.os + ' ' + (destroyEffect ? destroyEffect : 'slideInRight') + ' right'; + } else { + this.class = 'email-' + this.os + ' ' + (destroyEffect ? destroyEffect : 'slideInLeft') + ' left'; + } + } + + public ngOnDestroy(): void { + if (this.routerSubscription) { + this.routerSubscription.unsubscribe(); + } + } +} diff --git a/Mohem/src/app/hmg-common/ui/image-modal/image-modal.module.ts b/Mohem/src/app/hmg-common/ui/image-modal/image-modal.module.ts new file mode 100644 index 00000000..97cb109a --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/image-modal/image-modal.module.ts @@ -0,0 +1,29 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { FormsModule } from '@angular/forms'; +import { Routes, RouterModule } from '@angular/router'; +import { HmgCommonModule } from 'src/app/hmg-common/hmg-common.module'; +import { IonicModule } from '@ionic/angular'; +import { ImageModalPage } from './image-modal.page'; +import {ImageModalComponent} from './image-modal/image-modal.component'; +const routes: Routes = [ + { + path: '', + component: ImageModalPage + } +]; + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + IonicModule, + HmgCommonModule + ], + declarations: [ImageModalPage, ImageModalComponent], + exports: [ImageModalPage, ImageModalComponent], + entryComponents: [ + ImageModalPage + ] +}) +export class ImageModalModule {} diff --git a/Mohem/src/app/hmg-common/ui/image-modal/image-modal.page.html b/Mohem/src/app/hmg-common/ui/image-modal/image-modal.page.html new file mode 100644 index 00000000..0dcf7736 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/image-modal/image-modal.page.html @@ -0,0 +1,4 @@ + + + + diff --git a/Mohem/src/app/hmg-common/ui/image-modal/image-modal.page.scss b/Mohem/src/app/hmg-common/ui/image-modal/image-modal.page.scss new file mode 100644 index 00000000..798ea6e3 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/image-modal/image-modal.page.scss @@ -0,0 +1,11 @@ +.image{ + margin: auto; + position: relative; + top: 0; + bottom: 0; + left: 0; + right: 0; + width: 100%; + height: 100%; + object-fit: contain; +} diff --git a/Mohem/src/app/hmg-common/ui/image-modal/image-modal.page.spec.ts b/Mohem/src/app/hmg-common/ui/image-modal/image-modal.page.spec.ts new file mode 100644 index 00000000..8c91a567 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/image-modal/image-modal.page.spec.ts @@ -0,0 +1,27 @@ +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ImageModalPage } from './image-modal.page'; + +describe('ImageModalPage', () => { + let component: ImageModalPage; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ImageModalPage ], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ImageModalPage); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/ui/image-modal/image-modal.page.ts b/Mohem/src/app/hmg-common/ui/image-modal/image-modal.page.ts new file mode 100644 index 00000000..ed353683 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/image-modal/image-modal.page.ts @@ -0,0 +1,56 @@ +import { Component, OnInit, Input } from "@angular/core"; +import { ModalController } from "@ionic/angular"; +import { SharedDataService } from '../../services/shared-data-service/shared-data.service'; +import { ImageModal } from './image-modal/image.modal'; +@Component({ + selector: "app-image-modal", + templateUrl: "./image-modal.page.html", + styleUrls: ["./image-modal.page.scss"] +}) +export class ImageModalPage implements OnInit { + public tempImage = "assets/icon/no-image.jpg"; + @Input() imageName = this.tempImage; + public scaling: any; + public scale: any = 1; + public startDistance: any; + constructor( + public sharedService: SharedDataService + ) { } + + ngOnInit() { + this.imageName = this.sharedService.getSharedData(ImageModal.SHARED_DATA).image; + } + + + zoomStart(e: any) { + if (e.touches.length === 2) { + this.scaling = true; + this.pinchStart(e); + } + } + zoomMove(e: any) { + if (this.scaling) { + this.pinchMove(e); + } + } + pinchStart(e: any) { + this.startDistance = this.getDistance(e); + } + pinchMove(e: any) { + const dis = this.getDistance(e); + if (this.startDistance <= dis) { + const scale = this.scale += (.02); + e.currentTarget.style.transform = "scale(" + scale + "," + scale + ")"; + } else { + const scale = this.scale -= (.02); + e.currentTarget.style.transform = "scale(" + scale + "," + scale + ")"; + } + } + + getDistance(e: any) { + const dis = Math.hypot( + e.touches[0].pageX - e.touches[1].pageX, + e.touches[0].pageY - e.touches[1].pageY); + return dis; + } +} diff --git a/Mohem/src/app/hmg-common/ui/image-modal/image-modal/image-modal.component.html b/Mohem/src/app/hmg-common/ui/image-modal/image-modal/image-modal.component.html new file mode 100644 index 00000000..640be264 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/image-modal/image-modal/image-modal.component.html @@ -0,0 +1,3 @@ + + + diff --git a/Mohem/src/app/hmg-common/ui/image-modal/image-modal/image-modal.component.scss b/Mohem/src/app/hmg-common/ui/image-modal/image-modal/image-modal.component.scss new file mode 100644 index 00000000..3ed84246 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/image-modal/image-modal/image-modal.component.scss @@ -0,0 +1,31 @@ + .expand { + position: absolute; + left: 0; + right: 0; + bottom: 0; + top:0; + padding: 0; + margin:0; + z-index: 100; + + } + + .full { + width: 100%; + height: 100%; + } + + .expand-image { + width: 100%; + height: 100%; + padding: 0.1cm; + background-image: url("/assets/icon/_expand_frame-512.png"); + background-position: center; + background-size: 100% 100%; + background-repeat: no-repeat; + } + + .no-image { + width: 100%; + height: 100%; + } \ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/image-modal/image-modal/image-modal.component.spec.ts b/Mohem/src/app/hmg-common/ui/image-modal/image-modal/image-modal.component.spec.ts new file mode 100644 index 00000000..8c91a567 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/image-modal/image-modal/image-modal.component.spec.ts @@ -0,0 +1,27 @@ +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ImageModalPage } from './image-modal.page'; + +describe('ImageModalPage', () => { + let component: ImageModalPage; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ImageModalPage ], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ImageModalPage); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/ui/image-modal/image-modal/image-modal.component.ts b/Mohem/src/app/hmg-common/ui/image-modal/image-modal/image-modal.component.ts new file mode 100644 index 00000000..f75f4eae --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/image-modal/image-modal/image-modal.component.ts @@ -0,0 +1,52 @@ +import { Component, OnInit, Input } from "@angular/core"; +import { ModalController } from "@ionic/angular"; +import { ImageModalPage } from "../image-modal.page"; +import { SharedDataService } from "src/app/hmg-common/services/shared-data-service/shared-data.service"; +import { ImageModal } from "./image.modal"; +@Component({ + selector: "image-modal", + templateUrl: "./image-modal.component.html", + styleUrls: ["./image-modal.component.scss"] +}) +export class ImageModalComponent implements OnInit { + + public image: string; + public loadingError = false; + constructor( + public modalController: ModalController, + public sharedService: SharedDataService + ) {} + ngOnInit() {} + @Input() set src(src: string) { + this.image = src; + } + get src(): string { + return this.image; + } + + public onClick() { + this.openModal(this.image); + } + + public async openModal(img) { + this.sharedService.setSharedData(new ImageModal(this.image), ImageModal.SHARED_DATA); + const modal = await this.modalController.create({ + component: ImageModalPage + }); + modal.cssClass = this.get_orientation(img); //'modal-image-viewer'; + await modal.present(); + } + + public onError() {} + public get_orientation(src: any) { + const img = new Image(); + img.src = src; + const width = img.width; + const height = img.height; + if (width > height) { + return "modal-image-viewer-landscape"; + } else { + return "modal-image-viewer-portrait"; + } + } +} diff --git a/Mohem/src/app/hmg-common/ui/image-modal/image-modal/image.modal.ts b/Mohem/src/app/hmg-common/ui/image-modal/image-modal/image.modal.ts new file mode 100644 index 00000000..995c3fa3 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/image-modal/image-modal/image.modal.ts @@ -0,0 +1,8 @@ +export class ImageModal { + public static SHARED_DATA = 'image-modal-shared-data'; + constructor( + public image: string + ) { + + } +} \ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/images-slider/images-slider.component.html b/Mohem/src/app/hmg-common/ui/images-slider/images-slider.component.html new file mode 100644 index 00000000..78310b3b --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/images-slider/images-slider.component.html @@ -0,0 +1,2 @@ + + diff --git a/Mohem/src/app/hmg-common/ui/images-slider/images-slider.component.scss b/Mohem/src/app/hmg-common/ui/images-slider/images-slider.component.scss new file mode 100644 index 00000000..a8365878 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/images-slider/images-slider.component.scss @@ -0,0 +1,4 @@ +.full-width{ + width: 100%; + height: auto; +} \ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/images-slider/images-slider.component.spec.ts b/Mohem/src/app/hmg-common/ui/images-slider/images-slider.component.spec.ts new file mode 100644 index 00000000..478ddda9 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/images-slider/images-slider.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ImagesSliderComponent } from './images-slider.component'; + +describe('ImagesSliderComponent', () => { + let component: ImagesSliderComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ImagesSliderComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ImagesSliderComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/ui/images-slider/images-slider.component.ts b/Mohem/src/app/hmg-common/ui/images-slider/images-slider.component.ts new file mode 100644 index 00000000..e893695b --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/images-slider/images-slider.component.ts @@ -0,0 +1,48 @@ +import { Component, OnInit, Input } from '@angular/core'; + +@Component({ + selector: 'images-slider', + templateUrl: './images-slider.component.html', + styleUrls: ['./images-slider.component.scss'] +}) +export class ImagesSliderComponent implements OnInit { + + @Input() url: string; + + @Input() count: number; + + + @Input() interval = 1000; + + public src: string; + private index = 0; + constructor() { } + + ngOnInit() { + this.setNextImage(); + if (this.isValid()) { + setInterval(() => { + this.setNextImage(); + }, this.interval); + } + } + + private setNextImage() { + this.src = this.url + this.nextIndex() + '.png'; + } + private isValid() { + if (this.count && this.url) { + return this.count > 0; + } + return false; + } + + + private nextIndex(): number { + this.index = (this.index + 1) >= this.count ? 0 : this.index + 1; + return this.index; + } + +} + + diff --git a/Mohem/src/app/hmg-common/ui/info-dialog/info-dialog.component.html b/Mohem/src/app/hmg-common/ui/info-dialog/info-dialog.component.html new file mode 100644 index 00000000..f95279a9 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/info-dialog/info-dialog.component.html @@ -0,0 +1,25 @@ + + + + + + + +

{{title}}

+
+ +

+ {{description}} +

+ + + + + + {{ts.trPK('general','hide')}} + + + + + +
\ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/info-dialog/info-dialog.component.scss b/Mohem/src/app/hmg-common/ui/info-dialog/info-dialog.component.scss new file mode 100644 index 00000000..d625ac25 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/info-dialog/info-dialog.component.scss @@ -0,0 +1,16 @@ +.container { + position: fixed; + width: 100%; + left: 0; + right: 0; + top: 0; + bottom: 0; + height: 100%; + z-index: 100; +} + +.p-area{ + width: 100%; + text-align: center; + +} \ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/info-dialog/info-dialog.component.spec.ts b/Mohem/src/app/hmg-common/ui/info-dialog/info-dialog.component.spec.ts new file mode 100644 index 00000000..1eb698e0 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/info-dialog/info-dialog.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { InfoDialogComponent } from './info-dialog.component'; + +describe('InfoDialogComponent', () => { + let component: InfoDialogComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ InfoDialogComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(InfoDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/ui/info-dialog/info-dialog.component.ts b/Mohem/src/app/hmg-common/ui/info-dialog/info-dialog.component.ts new file mode 100644 index 00000000..4e95c44b --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/info-dialog/info-dialog.component.ts @@ -0,0 +1,26 @@ +import { Component, OnInit, Input } from '@angular/core'; +import { CommonService } from '../../services/common/common.service'; +import { TranslatorService } from '../../services/translator/translator.service'; +import { Toggle } from '../../services/models/toggle'; + +@Component({ + selector: 'info-dialog', + templateUrl: './info-dialog.component.html', + styleUrls: ['./info-dialog.component.scss'] +}) +export class InfoDialogComponent implements OnInit { + + @Input() icon: string; + @Input() title: string; + @Input() description: string; + @Input() toggle: Toggle; + constructor(public cs: CommonService, public ts: TranslatorService) { + } + + public isVisible() { + return this.toggle ? this.toggle.value : false; + } + ngOnInit() { + } + +} diff --git a/Mohem/src/app/hmg-common/ui/mobile-number/international-mobile/international-mobile.component.html b/Mohem/src/app/hmg-common/ui/mobile-number/international-mobile/international-mobile.component.html new file mode 100644 index 00000000..2b5a09db --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/mobile-number/international-mobile/international-mobile.component.html @@ -0,0 +1,40 @@ + + + +

{{ 'login,enter-mobile' |translate }}

+
+
+ + + + + + + + + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/mobile-number/international-mobile/international-mobile.component.scss b/Mohem/src/app/hmg-common/ui/mobile-number/international-mobile/international-mobile.component.scss new file mode 100644 index 00000000..3f8adf5a --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/mobile-number/international-mobile/international-mobile.component.scss @@ -0,0 +1,25 @@ + +.small-ion-select { + max-width: 100% !important; + min-width: 2cm !important; + --padding-start : 0; + --padding-end : 0; +} +.large-ion-select { + max-width: 100% !important; + min-width: 100% !important; + --padding-start : 0; + --padding-end : 0; + text-align: center; +} +.grid-no-padding { + --ion-grid-padding: 0px; + --ion-grid-padding-xs: 0px; + --ion-grid-padding-sm: 0px; + --ion-grid-padding-md: 0px; + --ion-grid-padding-lg: 0px; + --ion-grid-padding-xl: 0px; +} +.column-no-padding { + padding: 0; +} diff --git a/Mohem/src/app/hmg-common/ui/mobile-number/international-mobile/international-mobile.component.spec.ts b/Mohem/src/app/hmg-common/ui/mobile-number/international-mobile/international-mobile.component.spec.ts new file mode 100644 index 00000000..57822d64 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/mobile-number/international-mobile/international-mobile.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { InternationalMobileComponent } from './international-mobile.component'; + +describe('InternationalMobileComponent', () => { + let component: InternationalMobileComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ InternationalMobileComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(InternationalMobileComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/ui/mobile-number/international-mobile/international-mobile.component.ts b/Mohem/src/app/hmg-common/ui/mobile-number/international-mobile/international-mobile.component.ts new file mode 100644 index 00000000..1367825e --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/mobile-number/international-mobile/international-mobile.component.ts @@ -0,0 +1,205 @@ +import { Component, OnInit, Input, Output, EventEmitter, ChangeDetectorRef, ViewChild } from '@angular/core'; +import { CountryCode } from './models/country-code.model'; +import { OptionModel } from 'src/app/hmg-common/ui/searchable-select/option.model'; +import { InputData } from 'src/app/hmg-common/services/common/models/input-data'; +import { CommonService } from 'src/app/hmg-common/services/common/common.service'; +import { TranslatorService } from 'src/app/hmg-common/services/translator/translator.service'; +import { ConnectorService } from 'src/app/hmg-common/services/connector/connector.service'; +import { SelectComponent } from '../../select/select.component'; +import { SearchableSelectComponent } from '../../searchable-select/searchable-select/searchable-select.component'; + +@Component({ + selector: 'international-mobile', + templateUrl: './international-mobile.component.html', + styleUrls: ['./international-mobile.component.scss'] +}) +export class InternationalMobileComponent implements OnInit { + public static SAUDI_DIAL_CODE = '+966'; + public static SAUDI_CODE = 'SA'; + public static EMIRATE_DIAL_CODE = '+971'; + public static EMIRATE_CODE = 'AE'; + + public static sharedCodes: CountryCode[]; + public static sharedOptions: OptionModel[]; + public mobileNumber: InputData = new InputData(); + @Output() changed = new EventEmitter(); + public selectedDialCode: string; + public selectedDialCodePattern: string; + public number: string; + public numberMax: number; + public numberPattern: string; + public numberPlaceholder: string; + public selectedCountryCode: string; + public codes: CountryCode[]; + public options: OptionModel[]; + private dataLoaded = false; + private phoneSetProgramatically = false; + @ViewChild( SearchableSelectComponent) searchableSelectComponent: SearchableSelectComponent; + constructor( + public cs: CommonService, + public ts: TranslatorService, + public con: ConnectorService, + public changeDetector: ChangeDetectorRef + ) { } + + ngOnInit() { + this.numberPlaceholder = 'Mobile'; + if (InternationalMobileComponent.sharedCodes) { + this.codes = InternationalMobileComponent.sharedCodes; + this.options = InternationalMobileComponent.sharedOptions; + this.initializeOptions(); + this.selectDefaultCountry(); + } else { + this.cs.startLoading(); + this.con.getLocalResrouce('assets/data/select/country-code.json').subscribe(result => { + InternationalMobileComponent.sharedCodes = result.codes; + this.codes = result.codes; + this.initializeOptions(); + this.selectDefaultCountry(); + this.cs.stopLoading(); + }); + } + } + + private initializeOptions() { + InternationalMobileComponent.sharedOptions = []; + for ( const code of this.codes ){ + InternationalMobileComponent.sharedOptions.push ( new OptionModel(code.name, code)); + } + this.options = InternationalMobileComponent.sharedOptions; + } + + private selectDefaultCountry() { + setTimeout(() => { + this.dataLoaded = true; + this.selectedCountryCode = InternationalMobileComponent.SAUDI_CODE; + // this.changeDetector.detectChanges(); + this.countrySelected(); + }, 40); + } + private findCountryByDialCode(targetCode: string) { + for (const code of this.codes) { + if (targetCode === code.code) { + return code; + } + } + return null; + } + private findCountryByCountryCode(targetCode: string) { + for (const code of this.codes) { + if (targetCode === code.countryCode) { + return code; + } + } + return null; + } + + /* + the country code selected + */ + public countrySelected() { + const country = this.findCountryByCountryCode(this.selectedCountryCode); + this.setSelectedDialCodePattern(country.code); + this.selectedDialCode = country.code; + this.number = null; + this.updateNumberUI(country); + this.searchableSelectComponent.setDefault( country.name); + } + + public optionSelected(option: OptionModel) { + const country = this.findCountryByCountryCode( option.data.countryCode); + this.setSelectedDialCodePattern(country.code); + this.selectedDialCode = country.code; + this.number = null; + this.updateNumberUI(country); + } + + public optionCanceled() { + // this.selectDefaultCountry(); + } + + private setSelectedDialCodePattern(code: string) { + let length = code.length - 1; + length = length < 1 ? 1 : length; + this.selectedDialCodePattern = '^[+]([0-9]{' + length + '})'; + } + /* + the dial code selected + */ + public codeSelected() { + if (this.phoneSetProgramatically) { + this.phoneSetProgramatically = false; + } else { + this.number = null; + } + + const country = this.findCountryByDialCode(this.selectedDialCode); + // update the country only if the country is different + if (country.countryCode !== this.selectedCountryCode) { + this.selectedCountryCode = country.countryCode; + } + + this.trigerInformation(this.findCountryByDialCode(this.selectedDialCode)); + } + + /* + the input phone number entered by user + */ + public numberChanged() { + this.trigerInformation(this.findCountryByDialCode(this.selectedDialCode)); + } + + private updateNumberUI(country: CountryCode) { + this.numberPlaceholder = country.pattern || this.ts.trPK('general', 'mobile'); + if (country.maxLength) { + this.numberMax = country.maxLength; + this.numberPattern = '([0-9]{' + (this.numberMax) + '})'; + } else { + this.numberMax = country.maxLength || 15; + this.numberPattern = '([0-9]{3,15})'; + } + } + + private trigerInformation(country: CountryCode) { + if (country) { + /* update ui */ + this.updateNumberUI(country); + /* trigger information */ + country.number = this.number; + country.isValid = this.isValid(country); + this.changed.emit(this.number ? country : null); + } + } + + public isValid(country: CountryCode) { + return this.number != null && this.isValidLength(country); + } + + private isValidLength(country: CountryCode) { + if (country.maxLength) { + return this.number.toString().length === country.maxLength; + } else { + return this.number.toString().length > 0; + } + } + + /* + code must start with + + */ + public setMobileNumber(code, number) { + setTimeout(() => { + if (!this.dataLoaded) { + this.setMobileNumber(code, number); + } else { + this.phoneSetProgramatically = true; + this.number = number; + this.selectedDialCode = code; + this.setSelectedDialCodePattern(code); + const country = this.findCountryByDialCode(code); + this.updateNumberUI(country); + this.searchableSelectComponent.setDefault( country.name); + } + }, 50); + } + +} diff --git a/Mohem/src/app/hmg-common/ui/mobile-number/international-mobile/models/country-code.model.ts b/Mohem/src/app/hmg-common/ui/mobile-number/international-mobile/models/country-code.model.ts new file mode 100644 index 00000000..a48fbc48 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/mobile-number/international-mobile/models/country-code.model.ts @@ -0,0 +1,34 @@ +export class CountryCode { + name: string; + /* starts with + */ + code: string; + countryCode: string; + maxLength: number; + minLength: number; + pattern: string; + number?: string; + isValid?: boolean; + + /* + return number without + + */ + public static localNumber(code: string, number: string): string { + if (code && number) { + return CountryCode.localCode(code) + number; + } else { + return ''; + } + } + + /* + remove start + + */ + public static localCode(code: string): string { + if (code) { + return code.substr(1, code.length - 1); + } else { + return ''; + } + } + +} diff --git a/Mohem/src/app/hmg-common/ui/mobile-number/mobile-number.module.ts b/Mohem/src/app/hmg-common/ui/mobile-number/mobile-number.module.ts new file mode 100644 index 00000000..1ef7fbce --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/mobile-number/mobile-number.module.ts @@ -0,0 +1,37 @@ +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 { MobileNumberPage } from './mobile-number.page'; +import { InternationalMobileComponent } from './international-mobile/international-mobile.component'; +import { HmgCommonModule } from '../../hmg-common.module'; +import { SearchableOptionsModule } from '../searchable-select/searchable-options.module'; + +const routes: Routes = [ + { + path: '', + component: MobileNumberPage + } +]; + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + IonicModule, + RouterModule.forChild(routes), + HmgCommonModule, + SearchableOptionsModule + ], + declarations: [ + MobileNumberPage, + InternationalMobileComponent + ], + exports: [ + InternationalMobileComponent + ] +}) +export class MobileNumberModule {} diff --git a/Mohem/src/app/hmg-common/ui/mobile-number/mobile-number.page.html b/Mohem/src/app/hmg-common/ui/mobile-number/mobile-number.page.html new file mode 100644 index 00000000..e7c25461 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/mobile-number/mobile-number.page.html @@ -0,0 +1,9 @@ + + + mobileNumber + + + + + + diff --git a/Mohem/src/app/hmg-common/ui/mobile-number/mobile-number.page.scss b/Mohem/src/app/hmg-common/ui/mobile-number/mobile-number.page.scss new file mode 100644 index 00000000..e69de29b diff --git a/Mohem/src/app/hmg-common/ui/mobile-number/mobile-number.page.spec.ts b/Mohem/src/app/hmg-common/ui/mobile-number/mobile-number.page.spec.ts new file mode 100644 index 00000000..74fcd577 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/mobile-number/mobile-number.page.spec.ts @@ -0,0 +1,27 @@ +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { MobileNumberPage } from './mobile-number.page'; + +describe('MobileNumberPage', () => { + let component: MobileNumberPage; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ MobileNumberPage ], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(MobileNumberPage); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/ui/mobile-number/mobile-number.page.ts b/Mohem/src/app/hmg-common/ui/mobile-number/mobile-number.page.ts new file mode 100644 index 00000000..d07d0729 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/mobile-number/mobile-number.page.ts @@ -0,0 +1,15 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'app-mobile-number', + templateUrl: './mobile-number.page.html', + styleUrls: ['./mobile-number.page.scss'], +}) +export class MobileNumberPage implements OnInit { + + constructor() { } + + ngOnInit() { + } + +} diff --git a/Mohem/src/app/hmg-common/ui/nav-buttons/nav-buttons.component.html b/Mohem/src/app/hmg-common/ui/nav-buttons/nav-buttons.component.html new file mode 100644 index 00000000..2b618a0e --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/nav-buttons/nav-buttons.component.html @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/nav-buttons/nav-buttons.component.scss b/Mohem/src/app/hmg-common/ui/nav-buttons/nav-buttons.component.scss new file mode 100644 index 00000000..b2fe3562 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/nav-buttons/nav-buttons.component.scss @@ -0,0 +1,3 @@ +.float-left{ + float: left; +} \ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/nav-buttons/nav-buttons.component.spec.ts b/Mohem/src/app/hmg-common/ui/nav-buttons/nav-buttons.component.spec.ts new file mode 100644 index 00000000..51d36e8a --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/nav-buttons/nav-buttons.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { NavButtonsComponent } from './nav-buttons.component'; + +describe('NavButtonsComponent', () => { + let component: NavButtonsComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ NavButtonsComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(NavButtonsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/ui/nav-buttons/nav-buttons.component.ts b/Mohem/src/app/hmg-common/ui/nav-buttons/nav-buttons.component.ts new file mode 100644 index 00000000..05370d39 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/nav-buttons/nav-buttons.component.ts @@ -0,0 +1,67 @@ +import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; +import { CommonService } from 'src/app/hmg-common/services/common/common.service'; +import { Platform } from '@ionic/angular'; +import { TranslatorService } from '../../services/translator/translator.service'; +import { BackButtonEventDetail } from '@ionic/core'; + + +@Component({ + selector: 'nav-buttons', + templateUrl: './nav-buttons.component.html', + styleUrls: ['./nav-buttons.component.scss'] +}) +export class NavButtonsComponent implements OnInit { + + @Input() enableBack = true; + @Input() enableMenu = false; + @Input() navigate = true; + @Output() backClick = new EventEmitter(); + @Output() menuClick = new EventEmitter(); + @Input() forwardLink: string; + @Input() backLink: string; + + public direction: string; + public isIOS: boolean; + constructor( + public cs: CommonService, + public platform: Platform, + ) { + } + + ngOnInit() { + this.platform.ready().then(() => { + this.isIOS = this.platform.is('ios'); + this.direction = TranslatorService.getCurrentDirection(); + + this.platform.backButton.subscribeWithPriority(0 , () => { + this.backButtonClicked({}); + }); + + }); + } + + public backButtonClicked(event) { + // tslint:disable-next-line:no-console + if (this.forwardLink) { + if (this.navigate) { + this.cs.navigateForward(this.forwardLink); + } + } else if (this.backLink) { + this.backClick.emit([event]); + if (this.navigate) { + this.cs.navigateBack(this.backLink); + } + } else { + this.backClick.emit([event]); + if (this.navigate) { + this.cs.back(); + } + } + } + + + public onMenuClicked() { + this.menuClick.emit(); + } + +} diff --git a/Mohem/src/app/hmg-common/ui/number-range/input-value.ts b/Mohem/src/app/hmg-common/ui/number-range/input-value.ts new file mode 100644 index 00000000..a65999c8 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/number-range/input-value.ts @@ -0,0 +1,7 @@ +export class InputValue { + public value: number; + constructor(value: number) { + this.value = value; + } + +} diff --git a/Mohem/src/app/hmg-common/ui/number-range/number-range.component.html b/Mohem/src/app/hmg-common/ui/number-range/number-range.component.html new file mode 100644 index 00000000..24b9ec62 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/number-range/number-range.component.html @@ -0,0 +1,16 @@ + + + + +{{title}} + + + + + + + + + diff --git a/Mohem/src/app/hmg-common/ui/number-range/number-range.component.scss b/Mohem/src/app/hmg-common/ui/number-range/number-range.component.scss new file mode 100644 index 00000000..131b32e7 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/number-range/number-range.component.scss @@ -0,0 +1,10 @@ +ion-range { + --bar-height: 0.2cm; + --bar-border-radius: 0.5cm; + --knob-background: var(--ion-color-secondary); +} +.range-text{ + border: 1px solid #cecbcb; + text-align: center; + border-radius: 5px; +} \ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/number-range/number-range.component.spec.ts b/Mohem/src/app/hmg-common/ui/number-range/number-range.component.spec.ts new file mode 100644 index 00000000..164b2a4e --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/number-range/number-range.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { NumberRangeComponent } from './number-range.component'; + +describe('NumberRangeComponent', () => { + let component: NumberRangeComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ NumberRangeComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(NumberRangeComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/ui/number-range/number-range.component.ts b/Mohem/src/app/hmg-common/ui/number-range/number-range.component.ts new file mode 100644 index 00000000..98bc5f28 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/number-range/number-range.component.ts @@ -0,0 +1,41 @@ +import { Component, OnInit, Input } from '@angular/core'; +import { InputValue } from './input-value'; + +@Component({ + selector: 'number-range', + templateUrl: './number-range.component.html', + styleUrls: ['./number-range.component.scss'] +}) +export class NumberRangeComponent implements OnInit { + + @Input() public input: InputValue; + @Input() public min: number = Number.MIN_SAFE_INTEGER; + @Input() public max: number = Number.MAX_SAFE_INTEGER; + @Input() public step = 1; + + @Input() public title: string; + public minLength: number; + public maxLength: number; + + + @Input() public value: number; + constructor() { } + + ngOnInit() { + if (this.input) { + const lMin = this.min.toString().length; + const lMax = this.max.toString().length; + this.minLength = Math.min(lMin, lMax); + this.maxLength = Math.max(lMin, lMax); + } + } + + + public onChange() { + if (this.input) { + this.input.value = this.input.value >= this.max ? this.max : this.input.value; + this.input.value = this.input.value <= this.min ? this.min : this.input.value; + } + } + +} diff --git a/Mohem/src/app/hmg-common/ui/payment/payment.component.html b/Mohem/src/app/hmg-common/ui/payment/payment.component.html new file mode 100644 index 00000000..ea7e2ddd --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/payment/payment.component.html @@ -0,0 +1,33 @@ + + + + + + + + + + + {{ method.title | translate }} + + + + + + + + + + + +
+
+ + + + {{'general,cancel' | translate}} + + + + +
\ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/payment/payment.component.scss b/Mohem/src/app/hmg-common/ui/payment/payment.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/Mohem/src/app/hmg-common/ui/payment/payment.component.spec.ts b/Mohem/src/app/hmg-common/ui/payment/payment.component.spec.ts new file mode 100644 index 00000000..1ff39bb8 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/payment/payment.component.spec.ts @@ -0,0 +1,27 @@ +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { PaymentPage } from './payment.page'; + +describe('PaymentPage', () => { + let component: PaymentPage; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ PaymentPage ], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(PaymentPage); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/ui/payment/payment.component.ts b/Mohem/src/app/hmg-common/ui/payment/payment.component.ts new file mode 100644 index 00000000..f120edb1 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/payment/payment.component.ts @@ -0,0 +1,94 @@ +import { Component, OnInit, Input, Output, EventEmitter } 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 { SharedDataService } from 'src/app/hmg-common/services/shared-data-service/shared-data.service'; +import { PaymentService } from './service/payment.service'; +import { PayRequestInfo } from './service/models/pay-request.info'; +import { PaymentInfoModel } from './service/models/payment-info.model'; +import { PaymentValidationResponse } from './service/models/payment-validation.response'; + +@Component({ + selector: 'payment', + templateUrl: './payment.component.html', + styleUrls: ['./payment.component.scss'], +}) +export class PaymentComponent implements OnInit { + + + public methods = [ + { + icon: 'visa', + title: 'payment,visa', + method: PaymentService.VISA + }, + { + icon: 'sadad', + title: 'payment,sadad', + method: PaymentService.SADAD + }, + { + icon: 'mada', + title: 'payment,mada', + method: PaymentService.MADA + }, + { + icon: 'mastercard', + title: 'payment,mastercard', + method: PaymentService.MASTERCARD + }, + { + icon: 'instalment', + title: 'payment,instalment', + method: PaymentService.INSTALMENT + } + ]; + + @Output() success = new EventEmitter(); + @Output() faild = new EventEmitter(); + @Output() cancel = new EventEmitter(); + public orderDescription: string; + public amount: number; + private requestInfo: PayRequestInfo; + constructor( + public ts: TranslatorService, + public cs: CommonService, + public paymentService: PaymentService, + public sharedData: SharedDataService + ) { } + + ngOnInit() { + + } + + @Input() set payRequestInfo(payRequestInfo: PayRequestInfo) { + this.requestInfo = payRequestInfo; + this.amount = payRequestInfo.amount; + this.orderDescription = payRequestInfo.orderDescription; + } + + get payRequestInfo(): PayRequestInfo { + return this.requestInfo; + } + + + public openPayment(method: string) { + /*this.paymentService.openPayment(this.amount, method, this.orderDescription).subscribe((success) => { + if (success) { + this.success.emit(this.requestInfo.data); + } else { + this.faild.emit(); + } + }); + */ + } + + public onComplete(info: PaymentInfoModel) { + + } + + public onCancel() { + this.cancel.emit(); + } + + +} diff --git a/Mohem/src/app/hmg-common/ui/payment/service/models/pay-request.info.ts b/Mohem/src/app/hmg-common/ui/payment/service/models/pay-request.info.ts new file mode 100644 index 00000000..3109cb0c --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/payment/service/models/pay-request.info.ts @@ -0,0 +1,6 @@ +export class PayRequestInfo { + public static SHARED_DATA = 'pay-request-info-shared'; + amount: number; + orderDescription: string; + data: any; +} \ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/payment/service/models/payment-info.model.ts b/Mohem/src/app/hmg-common/ui/payment/service/models/payment-info.model.ts new file mode 100644 index 00000000..16dffe1b --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/payment/service/models/payment-info.model.ts @@ -0,0 +1,9 @@ +export class PaymentInfoModel { + transactionId: string; + amount: number; + + constructor(amount: number, transactionId: string){ + this.transactionId = transactionId; + this.amount = amount; + } +} diff --git a/Mohem/src/app/hmg-common/ui/payment/service/models/payment-validation.request.ts b/Mohem/src/app/hmg-common/ui/payment/service/models/payment-validation.request.ts new file mode 100644 index 00000000..734f1ec5 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/payment/service/models/payment-validation.request.ts @@ -0,0 +1,9 @@ +import { Request } from 'src/app/hmg-common/services/models/request'; + +export class PaymentValidationRequest extends Request { + MerchantModuleSessionID: string; + PayOneProject: number ; // 0 + PayOneService: number; // 4 + LanguageID: number; + +} diff --git a/Mohem/src/app/hmg-common/ui/payment/service/models/payment-validation.response.ts b/Mohem/src/app/hmg-common/ui/payment/service/models/payment-validation.response.ts new file mode 100644 index 00000000..76e3e5d7 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/payment/service/models/payment-validation.response.ts @@ -0,0 +1,8 @@ +import { Response } from 'src/app/hmg-common/services/models/response'; + +export class PaymentValidationResponse extends Response { + public static SHARED_DATA = 'payment_validation_shared'; + Amount: number; + Merchant_Reference: string; + Response_Message: string; +} \ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/payment/service/payment.service.payfort.txt b/Mohem/src/app/hmg-common/ui/payment/service/payment.service.payfort.txt new file mode 100644 index 00000000..1e65b50c --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/payment/service/payment.service.payfort.txt @@ -0,0 +1,100 @@ +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; +import { PaymentInfoModel } from './models/payment-info.model'; +import { PaymentValidationRequest } from './models/payment-validation.request'; +import { PaymentValidationResponse } from './models/payment-validation.response'; +import { CommonService } from 'src/app/hmg-common/services/common/common.service'; +import { ConnectorService } from 'src/app/hmg-common/services/connector/connector.service'; +import { AuthenticationService } from 'src/app/hmg-common/services/authentication/authentication.service'; +import { GuidService } from 'src/app/hmg-common/services/guid/guid.service'; +import { TranslatorService } from 'src/app/hmg-common/services/translator/translator.service'; + +@Injectable({ + providedIn: 'root' +}) +export class PaymentService { + + public static MADA = 'MADA'; + public static MASTERCARD = 'MASTERCARD'; + public static SADAD = 'SADAD '; + public static VISA = 'VISA'; + public static INSTALMENT = 'INSTALMENT'; + public static validateURL = 'Services/PayFort_Serv.svc/REST/GetRequestStatusByRequestID'; + private static SERVICE_URL = 'https://hmgwebservices.com/PayFortWeb/pages/SendPayFortRequest.aspx'; + + constructor( + public cs: CommonService, + public ts: TranslatorService, + public con: ConnectorService, + public authService: AuthenticationService, + public guid: GuidService + ) { } + + + public validatePayment(transactionID: string, onError: any, errorLabel: string): Observable { + const request = new PaymentValidationRequest(); + request.ClientRequestID = transactionID; + // this.authService.authenticateRequest(request); + return this.con.post(PaymentService.validateURL, request, onError, errorLabel); + } + + + public openPayment(amount: number, method: string, orderDesc: string, ): Observable { + return Observable.create(observer => { + const transactionID = this.guid.generate(); + this.cs.openBrowser( this.generateURL( amount, method, orderDesc, transactionID) , + () => this.notifyCallerDone(observer, true) , + () => this.notifyCallerDone(observer, false) ); + // this.hmgBrowser.registerBack(() => this.notifyCaller(observer, amount, transactionID)); + // this.hmgBrowser.registerClose(() => this.notifyCaller(observer, amount, transactionID)); + }); + } + + private notifyCaller(observer: any, amount: number, transactionID: string) { + observer.next(new PaymentInfoModel(amount, transactionID)) ; + observer.complete(); + } + + private notifyCallerDone(observer: any,done: boolean) { + observer.next( done) ; + observer.complete(); + } + + private generateURL( amount: number, method: string, orderDesc: string, transactionID: string): string { + let form = this.getForm(); + const user = this.authService.getAuthenticatedUser(); + if (user) { + form = form.replace('EMAIL_VALUE', user.Email || user.EmailAddress); + } + form = form.replace('AMOUNT_VALUE', (amount || 0 ).toString()); + form = form.replace('METHOD_VALUE', method); + form = form.replace('ORDER_DESCRIPTION_VALUE', orderDesc); + form = form.replace('ORDER_ID_VALUE', transactionID); + form = form.replace('SERVICE_URL_VALUE', PaymentService.SERVICE_URL); + console.log(form); + const base64URL = 'data:text/html;base64,' + btoa(form); + console.log(base64URL); + return base64URL; + } + + public getForm(): string { + return ' ' + + '' + + '' + + '
' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '
' + + '' + + '' + + ''; + } +} diff --git a/Mohem/src/app/hmg-common/ui/payment/service/payment.service.spec.ts b/Mohem/src/app/hmg-common/ui/payment/service/payment.service.spec.ts new file mode 100644 index 00000000..97018b11 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/payment/service/payment.service.spec.ts @@ -0,0 +1,12 @@ +import { TestBed } from '@angular/core/testing'; + +import { PaymentService } from './payment.service'; + +describe('PaymentService', () => { + beforeEach(() => TestBed.configureTestingModule({})); + + it('should be created', () => { + const service: PaymentService = TestBed.get(PaymentService); + expect(service).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/ui/payment/service/payment.service.ts b/Mohem/src/app/hmg-common/ui/payment/service/payment.service.ts new file mode 100644 index 00000000..d97cebb4 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/payment/service/payment.service.ts @@ -0,0 +1,110 @@ +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; +import { PaymentInfoModel } from './models/payment-info.model'; +import { PaymentValidationRequest } from './models/payment-validation.request'; +import { PaymentValidationResponse } from './models/payment-validation.response'; +import { CommonService } from 'src/app/hmg-common/services/common/common.service'; +import { ConnectorService } from 'src/app/hmg-common/services/connector/connector.service'; +import { AuthenticationService } from 'src/app/hmg-common/services/authentication/authentication.service'; +import { GuidService } from 'src/app/hmg-common/services/guid/guid.service'; +import { TranslatorService } from 'src/app/hmg-common/services/translator/translator.service'; + +import { Response } from 'src/app/hmg-common/services/models/response'; + +@Injectable({ + providedIn: 'root' +}) +export class PaymentService { + + public static MADA = 'MADA'; + public static MASTERCARD = 'MASTERCARD'; + public static SADAD = 'SADAD '; + public static VISA = 'VISA'; + public static INSTALMENT = 'INSTALMENT'; + private static SERVICE_URL = 'https://hmgwebservices.com/PayOneDev/Pay_Request.aspx'; + public static paymentStatusURL = 'Services/PayOne.svc/REST/PayOneGetRequestsByProjectServiceAndItem'; + + constructor( + public cs: CommonService, + public ts: TranslatorService, + public con: ConnectorService, + public authService: AuthenticationService, + public guid: GuidService + ) { } + + public getPaymentLanguageID(): number { + return TranslatorService.getCurrentLanguageName() == 'en' ? 1 : 0; + } + + public getPaymentStatus(transactionID: string, onError: any, errorLabel: string): + Observable { + const request = new PaymentValidationRequest(); + request.MerchantModuleSessionID = transactionID; + request.PayOneProject = 0; + request.PayOneService = 4; + request.LanguageID = this.getPaymentLanguageID(); + this.authService.authenticateRequest(request); + return this.con.postNoLoad(PaymentService.paymentStatusURL, request, onError); + } + + public openPayment(amount: number, transactionID: string, orderDesc: string): Observable { + return Observable.create(observer => { + // const transactionID = this.guid.generate(); + this.cs.openBrowser(this.generateURL(amount, orderDesc, transactionID), + () => this.notifyCallerDone(observer, true), + () => this.notifyCallerDone(observer, false), + () => this.notifyCallerDone(observer, true), + ['success' ]); + // this.hmgBrowser.registerBack(() => this.notifyCaller(observer, amount, transactionID)); + // this.hmgBrowser.registerClose(() => this.notifyCaller(observer, amount, transactionID)); + }); + } + + private notifyCaller(observer: any, amount: number, transactionID: string) { + observer.next(new PaymentInfoModel(amount, transactionID)); + observer.complete(); + } + + private notifyCallerDone(observer: any, done: boolean) { + observer.next(done); + observer.complete(); + } + + private generateURL(amount: number, orderDesc: string, transactionID: string): string { + let form = this.getForm(); + const user = this.authService.getAuthenticatedUser(); + if (user) { + form = form.replace('EMAIL_VALUE', user.Email || user.EmailAddress); + } + form = form.replace('AMOUNT_VALUE', (amount || 0).toString()); + form = form.replace('ORDER_DESCRIPTION_VALUE', orderDesc); + form = form.replace('SESSION_ID_VALUE', transactionID); + form = form.replace('REQUEST_ID_VALUE', transactionID); + form = form.replace('PROJECT_ID_VALUE', 'ENTED'); + form = form.replace('SERVICE_URL_VALUE', PaymentService.SERVICE_URL); + console.log(form); + const base64URL = 'data:text/html;base64,' + btoa(form); + console.log(base64URL); + return base64URL; + } + + public getForm(): string { + return ' ' + + '' + + '' + + '
' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '
' + + '' + + '' + + ''; + } +} diff --git a/Mohem/src/app/hmg-common/ui/progressLoading/progress-loading.service.spec.ts b/Mohem/src/app/hmg-common/ui/progressLoading/progress-loading.service.spec.ts new file mode 100644 index 00000000..f435846c --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/progressLoading/progress-loading.service.spec.ts @@ -0,0 +1,12 @@ +import { TestBed } from '@angular/core/testing'; + +import { ProgressLoadingService } from './progress-loading.service'; + +describe('ProgressLoadingService', () => { + beforeEach(() => TestBed.configureTestingModule({})); + + it('should be created', () => { + const service: ProgressLoadingService = TestBed.get(ProgressLoadingService); + expect(service).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/ui/progressLoading/progress-loading.service.ts b/Mohem/src/app/hmg-common/ui/progressLoading/progress-loading.service.ts new file mode 100644 index 00000000..690e8c69 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/progressLoading/progress-loading.service.ts @@ -0,0 +1,91 @@ +import { Injectable } from '@angular/core'; +import { Platform } from '@ionic/angular'; + +@Injectable({ + providedIn: 'root' +}) +export class ProgressLoadingService { + + private static id = 'custom-progress-loader'; + private static idSmall = 'custom-progress-loader-small'; + private static isPresented = false; + constructor( + public platform: Platform + ) { } + + + public presentLoading(message: string) { + // this.dismiss(); + if ( !ProgressLoadingService.isPresented ) { + ProgressLoadingService.isPresented = true; + document.body.appendChild( this.createLoader(message)); + this.disableEventsPropagation(); + } + } + + private enableBackButton(enable: boolean ) { + + if ( enable ) { + // take full controll + this.platform.backButton.subscribeWithPriority(1 , () => { + alert('progress loading 0'); + }); + } + } + private disableEventsPropagation() { + const view = document.getElementById( ProgressLoadingService.id); + + view.addEventListener('click', (e) => { + e.stopImmediatePropagation(); + }); + } + + public dismiss() { + ProgressLoadingService.isPresented = false; + const element = document.getElementById( ProgressLoadingService.id ); + if (element) { + element.remove(); + } + } + + private innerTemplate(message: string) { + + const template = + // tslint:disable-next-line:quotemark + "
" + + "" + + "

" + message + "

" + "
"; + + return template; + } + + private createLoader(message: string) { + const elemDiv = document.createElement('div'); + elemDiv.id = ProgressLoadingService.id; + elemDiv.className = 'progress-loading-page'; + elemDiv.innerHTML = this.innerTemplate(message); + return elemDiv; + + } + + + + private createLoaderSmall(message: string) { + const elemDiv = document.createElement('div'); + elemDiv.id = ProgressLoadingService.idSmall; + elemDiv.className = 'progress-loading-page-small'; + elemDiv.innerHTML = this.innerTemplateSmall(message); + return elemDiv; + + } + + + private innerTemplateSmall(message: string) { + + const template = + // tslint:disable-next-line:quotemark + "" ; + + return template; + } +} diff --git a/Mohem/src/app/hmg-common/ui/refresher/refresher.component.html b/Mohem/src/app/hmg-common/ui/refresher/refresher.component.html new file mode 100644 index 00000000..28c4366c --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/refresher/refresher.component.html @@ -0,0 +1,13 @@ + + + + + + + diff --git a/Mohem/src/app/hmg-common/ui/refresher/refresher.component.scss b/Mohem/src/app/hmg-common/ui/refresher/refresher.component.scss new file mode 100644 index 00000000..cccdc89f --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/refresher/refresher.component.scss @@ -0,0 +1,25 @@ +.slider { + position: fixed; + /*background-image: url(/assets/icon/arrow-down.png); + background-repeat: repeat-y; + background-size: contain; + */ + left: 45%; + top: 1.3cm; + width: 10%; + z-index: 500; +} + +.spinner { + position: absolute; + bottom: 0; + left:0; + right: 0; + width: 100%; +} + + +ion-refresher { + z-index: 600; + background-color: rgba(255,255,255,0.7); +} \ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/refresher/refresher.component.spec.ts b/Mohem/src/app/hmg-common/ui/refresher/refresher.component.spec.ts new file mode 100644 index 00000000..d69ae4e6 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/refresher/refresher.component.spec.ts @@ -0,0 +1,27 @@ +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { RefresherPage } from './refresher.page'; + +describe('RefresherPage', () => { + let component: RefresherPage; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ RefresherPage ], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(RefresherPage); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/ui/refresher/refresher.component.ts b/Mohem/src/app/hmg-common/ui/refresher/refresher.component.ts new file mode 100644 index 00000000..7c083e04 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/refresher/refresher.component.ts @@ -0,0 +1,146 @@ +import { Component, OnInit, OnDestroy, HostListener, Input, EventEmitter, Output } from '@angular/core'; +import { TranslatorService } from '../../services/translator/translator.service'; +import { CommonService } from '../../services/common/common.service'; + +@Component({ + selector: 'refresher', + templateUrl: './refresher.component.html', + styleUrls: ['./refresher.component.scss'], +}) +export class RefresherComponent implements OnInit, OnDestroy { + + private mouseMove = 'mousemove'; + private touchMove = 'touchmove'; + + /* + area which you can drag 0.2 from screen height + */ + @Input() maxSlidingHeightRatio = 0.15; + private maxSlidingHeight = 200; + /* + top area form screen where you can start drag + */ + @Input() maxStargDragRatio = 0.1; + private startDragAreaHeight = 200; + + private startX = 0; + private startY = 0; + + private height = 0; + private isDown = false; + + @Output() refresh = new EventEmitter(); + + constructor( + public ts: TranslatorService, + public cs: CommonService + ) { + + // this.initialize(this.getScreenHeight()); + } + + ngOnInit() { + } + + private initialize(screenHeight: number) { + this.startDragAreaHeight = screenHeight * this.maxStargDragRatio; + this.maxSlidingHeight = screenHeight * this.maxSlidingHeightRatio; + } + + /* click events*/ + @HostListener('document:mousedown', ['$event']) + @HostListener('document:touchstart', ['$event']) + onTouchDown(e) { + // this.processDownEvent(e.pageX || e.touches[0].pageX, e.pageY || e.touches[0].pageY); + } + + @HostListener('document:mouseup', ['$event']) + @HostListener('document:touchend', ['$event']) + @HostListener('document:touchcancel', ['$event']) + onTouchUp(e) { + // this.processOnTouchEnd(); + } + + /* move events */ + @HostListener('document:mousemove', ['$event']) + @HostListener('document:touchmove', ['$event']) + onTouchMove(e) { + // this.processMoveEvent(e.pageX || e.touches[0].pageX, e.pageY || e.touches[0].pageY); + } + + /* + screen resize + */ + @HostListener('window:resize', ['$event']) + onResize(event) { + // this.initialize(event.target.innerHeight); + } + + + private processOnTouchEnd() { + // if dragged more than 80% from the maxh drag height + if ( (this.height / this.maxSlidingHeight) >= 0.8 ) { + this.triggerRefresh(); + } + this.height = 0; + this.isDown = false; + } + + private triggerRefresh( ) { +// to be compatible with ion-refresher + this.refresh.emit( { + target: { + complete : () => {} + } + }); + } + + public triggerIonRefresh(event) { + // to be compatible with ion-refresher + this.refresh.emit(event); + } + /* + check if you start dragging from the top of the page + */ + private inStartDragArea(y: number): boolean { + return y <= this.startDragAreaHeight; + } + + private processMoveEvent(x: number, y: number) { + if (this.isDown) { + let yDiff = (y - this.startY); + const slidingFactor = (y - this.startY) / this.maxSlidingHeight; + yDiff = Math.max(0, yDiff); + this.height = Math.min(yDiff, this.maxSlidingHeight); + } + } + + private processDownEvent(x: number, y: number) { + if (this.inStartDragArea(y)) { + this.isDown = true; + this.height = 0; + this.startX = x; + this.startY = y; + } + } + + private getScreenWidth = function () { + return window.innerWidth + || document.documentElement.clientWidth + || document.body.clientWidth; + + } + + private getScreenHeight() { + return window.innerHeight + || document.documentElement.clientHeight + || document.body.clientHeight; + + } + + ngOnDestroy(): void { + } + + + +} diff --git a/Mohem/src/app/hmg-common/ui/scroll-content/scroll-content.component.html b/Mohem/src/app/hmg-common/ui/scroll-content/scroll-content.component.html new file mode 100644 index 00000000..65bca1cb --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/scroll-content/scroll-content.component.html @@ -0,0 +1,5 @@ +
+ + +
\ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/scroll-content/scroll-content.component.scss b/Mohem/src/app/hmg-common/ui/scroll-content/scroll-content.component.scss new file mode 100644 index 00000000..54af94c8 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/scroll-content/scroll-content.component.scss @@ -0,0 +1,22 @@ +.scroll-area{ + position: fixed; + top: 1.8cm; + left: 0; + width: 100%; + bottom: 4cm; + overflow: auto; + overflow-x: hidden; +} + +.full-view { + width: 100%; + height: 100%; +} + +.keyboard-closed { + bottom: 4cm; +} + +.keyboard-opened { + bottom: 1.5cm; +} \ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/scroll-content/scroll-content.component.spec.ts b/Mohem/src/app/hmg-common/ui/scroll-content/scroll-content.component.spec.ts new file mode 100644 index 00000000..8161bb78 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/scroll-content/scroll-content.component.spec.ts @@ -0,0 +1,27 @@ +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ScrollContentPage } from './scroll-content.page'; + +describe('ScrollContentPage', () => { + let component: ScrollContentPage; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ScrollContentPage ], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ScrollContentPage); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/ui/scroll-content/scroll-content.component.ts b/Mohem/src/app/hmg-common/ui/scroll-content/scroll-content.component.ts new file mode 100644 index 00000000..b30cb900 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/scroll-content/scroll-content.component.ts @@ -0,0 +1,36 @@ +import { Component, OnInit, Input } from '@angular/core'; +import { KeyboardService } from '../../services/keyboard/keyboard.service'; +import { Events, Platform } from '@ionic/angular'; +import { KeyboardStatusModel } from '../../services/keyboard/keyboard-status.model'; + +@Component({ + selector: 'scroll-content', + templateUrl: './scroll-content.component.html', + styleUrls: ['./scroll-content.component.scss'], +}) +export class ScrollContentComponent implements OnInit { + + + public keyboardOpened = false; + @Input() fullView = false; + constructor( + public events: Events, + public keyboardService: KeyboardService, + public platform: Platform + ) { } + + + ngOnInit() { + this.platform.ready().then(() => { + this.keyboardOpened = KeyboardService.keyboardOpened; + this.monitorKeyboardChange(); + }); + } + + private monitorKeyboardChange() { + this.events.subscribe(KeyboardService.KEYBOARD_STATUS, (status: KeyboardStatusModel) => { + this.keyboardOpened = status.opened; + }); + } + +} diff --git a/Mohem/src/app/hmg-common/ui/scroll-segment-content/scroll-segment-content.component.html b/Mohem/src/app/hmg-common/ui/scroll-segment-content/scroll-segment-content.component.html new file mode 100644 index 00000000..80ea7584 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/scroll-segment-content/scroll-segment-content.component.html @@ -0,0 +1,3 @@ +
+ +
\ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/scroll-segment-content/scroll-segment-content.component.scss b/Mohem/src/app/hmg-common/ui/scroll-segment-content/scroll-segment-content.component.scss new file mode 100644 index 00000000..47d41c78 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/scroll-segment-content/scroll-segment-content.component.scss @@ -0,0 +1,27 @@ +.scroll-segment-area { + position: fixed; + top: 2.5cm; + left: 0; + width: 100%; + bottom: 4cm; + overflow: auto; + overflow-x: hidden; +} + + +.ios { + top: 3.3cm; +} + +.md { + top: 3.3cm; +} + + +.keyboard-closed { + bottom: 4cm; +} + +.keyboard-opened { + bottom: 1.5cm; +} \ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/scroll-segment-content/scroll-segment-content.component.spec.ts b/Mohem/src/app/hmg-common/ui/scroll-segment-content/scroll-segment-content.component.spec.ts new file mode 100644 index 00000000..e87040c2 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/scroll-segment-content/scroll-segment-content.component.spec.ts @@ -0,0 +1,27 @@ +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ScrollSegmentContentPage } from './scroll-segment-content.page'; + +describe('ScrollSegmentContentPage', () => { + let component: ScrollSegmentContentPage; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ScrollSegmentContentPage ], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ScrollSegmentContentPage); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/ui/scroll-segment-content/scroll-segment-content.component.ts b/Mohem/src/app/hmg-common/ui/scroll-segment-content/scroll-segment-content.component.ts new file mode 100644 index 00000000..f9212149 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/scroll-segment-content/scroll-segment-content.component.ts @@ -0,0 +1,46 @@ +import { Component, OnInit } from '@angular/core'; +import { Platform, Events } from '@ionic/angular'; +import { KeyboardService } from '../../services/keyboard/keyboard.service'; +import { KeyboardStatusModel } from '../../services/keyboard/keyboard-status.model'; + +@Component({ + selector: 'scroll-segment-content', + templateUrl: './scroll-segment-content.component.html', + styleUrls: ['./scroll-segment-content.component.scss'], +}) +export class ScrollSegmentContentComponent implements OnInit { + + + public keyboardOpened = false; + public className = ''; + + constructor( + public events: Events, + public keyboardService: KeyboardService, + public platform: Platform + ) { } + + ngOnInit() { + this.platform.ready().then(() => { + this.setClassName( ); + this.monitorKeyboardChange(); + }); + } + + private monitorKeyboardChange() { + this.events.subscribe(KeyboardService.KEYBOARD_STATUS, (status: KeyboardStatusModel) => { + this.setClassName ( ); + }); + } + + private setClassName () { + this.keyboardOpened = KeyboardService.keyboardOpened; + if ( this.platform.is('ios')) { + this.className = 'scroll-segment-area ios zoomIn ' + ( this.keyboardOpened ? 'keyboard-opened' : 'keyboard-closed' ); + } else { + this.className = 'scroll-segment-area md zoomIn ' + ( this.keyboardOpened ? 'keyboard-opened' : 'keyboard-closed' ); + } + } + + +} diff --git a/Mohem/src/app/hmg-common/ui/searchable-select/option.model.ts b/Mohem/src/app/hmg-common/ui/searchable-select/option.model.ts new file mode 100644 index 00000000..facdebe3 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/searchable-select/option.model.ts @@ -0,0 +1,6 @@ +export class OptionModel { + public static SHARED_DATA = 'options-shared-data'; + constructor ( public label: string, public data: any) { + + } +} \ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/searchable-select/searchable-options.module.ts b/Mohem/src/app/hmg-common/ui/searchable-select/searchable-options.module.ts new file mode 100644 index 00000000..7d2dfbc2 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/searchable-select/searchable-options.module.ts @@ -0,0 +1,38 @@ +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 { SearchableOptionsPage } from './searchable-options.page'; +import { HmgCommonModule } from 'src/app/hmg-common/hmg-common.module'; +import { SearchableSelectComponent } from './searchable-select/searchable-select.component'; + +const routes: Routes = [ + { + path: '', + component: SearchableOptionsPage + } +]; + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + IonicModule, + HmgCommonModule + ], + declarations: [ + SearchableOptionsPage, + SearchableSelectComponent + ], + exports: [ + SearchableOptionsPage, + SearchableSelectComponent + ], + entryComponents: [ + SearchableOptionsPage + ] +}) +export class SearchableOptionsModule { } diff --git a/Mohem/src/app/hmg-common/ui/searchable-select/searchable-options.page.html b/Mohem/src/app/hmg-common/ui/searchable-select/searchable-options.page.html new file mode 100644 index 00000000..50ccc0f8 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/searchable-select/searchable-options.page.html @@ -0,0 +1,46 @@ + + + {{ 'general,search' | translate}} + + + + + + + + + + + + + + + + {{option.label}} + + + + + + + {{ 'general,no-match' | translate}} + + + + + + + + + {{'general,cancel' | translate }} + + + + {{'general,ok' |translate}} + + + +
+
\ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/searchable-select/searchable-options.page.scss b/Mohem/src/app/hmg-common/ui/searchable-select/searchable-options.page.scss new file mode 100644 index 00000000..5a28739d --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/searchable-select/searchable-options.page.scss @@ -0,0 +1,48 @@ + +/* +custom searchable list +*/ + +.searchable-list { + width: 100%; + height: 100%; + z-index: 100001; +} + +.buttons { + position: absolute; + left: 0; + right: 0; + width: 100%; + height: 1.3cm; + bottom: 0.3cm; + padding: 0; +} +.scrollable { + width: 100%; + overflow-y: auto; + position: absolute; + left: 0; + right: 0; + width: 100%; + bottom: 1.7cm; + top: 1.5cm; + padding-bottom: 0; + margin-bottom: 0; +} + +.no-padding { + margin-top: 0cm; + padding:0; + margin: 0; + --padding-start: 0; + --padding-end: 0; + --padding-top: 0; + --padding-bottom: 0; +} + + +.no-data { + width: 100%; + text-align: center; +} \ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/searchable-select/searchable-options.page.spec.ts b/Mohem/src/app/hmg-common/ui/searchable-select/searchable-options.page.spec.ts new file mode 100644 index 00000000..a08c4835 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/searchable-select/searchable-options.page.spec.ts @@ -0,0 +1,27 @@ +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SearchableOptionsPage } from './searchable-options.page'; + +describe('SearchableOptionsPage', () => { + let component: SearchableOptionsPage; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ SearchableOptionsPage ], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(SearchableOptionsPage); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/ui/searchable-select/searchable-options.page.ts b/Mohem/src/app/hmg-common/ui/searchable-select/searchable-options.page.ts new file mode 100644 index 00000000..573b7c87 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/searchable-select/searchable-options.page.ts @@ -0,0 +1,76 @@ +import { Component, OnInit } from '@angular/core'; +import { SharedDataService } from 'src/app/hmg-common/services/shared-data-service/shared-data.service'; +import { CommonService } from 'src/app/hmg-common/services/common/common.service'; +import { TranslatorService } from 'src/app/hmg-common/services/translator/translator.service'; +import { ModalController } from '@ionic/angular'; +import { OptionModel } from './option.model'; + +@Component({ + selector: 'app-searchable-options', + templateUrl: './searchable-options.page.html', + styleUrls: ['./searchable-options.page.scss'], +}) +export class SearchableOptionsPage implements OnInit { + + + public options: OptionModel[] ; + public selectedOption: OptionModel; + public searchField: string; + constructor( + public cs: CommonService, + public ts: TranslatorService, + public modalController: ModalController, + public sharedData: SharedDataService) { } + + ngOnInit() { + this.options = this.sharedData.getSharedData(OptionModel.SHARED_DATA, true); + this.cs.stopLoading(); + } + + public searchFieldChanged() { + // this.selectedOption = null; + } + + public matches(option: OptionModel): boolean { + if (this.searchField) { + if (option.label) { + return option.label.toLowerCase().indexOf(this.searchField.toLowerCase()) >= 0; + } else { + return false; + } + } else { + return true; + } + } + + public noMatch(): boolean { + for (const option of this.options) { + if (this.matches(option)) { + return false; + } + } + return true; + } + + public optionSelected(option) { + this.selectedOption = option; + } + public selectionChanged(event) { + // console.log (event); + } + + public cancelSelection() { + // this.showList = false; + this.modalController.dismiss({ + 'selection': null + }); + } + public submitSelection() { + this.modalController.dismiss({ + 'selection': this.selectedOption + }); + + } + + +} diff --git a/Mohem/src/app/hmg-common/ui/searchable-select/searchable-select/searchable-select.component.html b/Mohem/src/app/hmg-common/ui/searchable-select/searchable-select/searchable-select.component.html new file mode 100644 index 00000000..7b12b6e9 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/searchable-select/searchable-select/searchable-select.component.html @@ -0,0 +1,24 @@ + + + + + +

{{title}}

+
+ +

{{placeHolder}}

+

{{selectedOption.label}}

+
+ +
+
+ + + + +

+ {{selectedOption ? selectedOption.label : placeHolder }}

+ +
+
\ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/searchable-select/searchable-select/searchable-select.component.scss b/Mohem/src/app/hmg-common/ui/searchable-select/searchable-select/searchable-select.component.scss new file mode 100644 index 00000000..206f1465 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/searchable-select/searchable-select/searchable-select.component.scss @@ -0,0 +1,70 @@ + +/* +custom searchable list +*/ + +.title { + padding-left: 0.2cm; + padding-right: 0.2cm; + white-space: nowrap; + font-size: 18px; +} +.info { + text-align: right; + overflow: hidden; + color: var(--ion-color-primary); +} +.info-container { + overflow: initial !important; +} + +.line-text { + text-overflow: ellipsis; + white-space: nowrap; + +} + + +.centred-info-contianer { + position: absolute; + left: 0; + right: 0%; + padding-bottom: 0.6cm; + +} + + +.centered-icon-right { + width: 19px; + height: 19px; + margin-left: 9px; +} + +.centered-info-right { + overflow: hidden; + color: var(--ion-color-primary); + text-align: center; + margin-left: auto; + margin-right: auto; + font-size: 0.41cm; + padding-top: 0; + padding-bottom: 0; + +} + +.centered-icon-left { + width: 19px; + height: 19px; + margin-right: 9px; +} + +.centered-info-left { + overflow: hidden; + color: var(--ion-color-primary); + text-align: center; + margin-left: auto; + margin-right: auto; + font-size: 0.41cm; + padding-top: 0; + padding-bottom: 0; +} \ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/searchable-select/searchable-select/searchable-select.component.spec.ts b/Mohem/src/app/hmg-common/ui/searchable-select/searchable-select/searchable-select.component.spec.ts new file mode 100644 index 00000000..d8d6b4c6 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/searchable-select/searchable-select/searchable-select.component.spec.ts @@ -0,0 +1,27 @@ +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SearchableSelectPage } from './searchable-select.page'; + +describe('SearchableSelectPage', () => { + let component: SearchableSelectPage; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ SearchableSelectPage ], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(SearchableSelectPage); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/ui/searchable-select/searchable-select/searchable-select.component.ts b/Mohem/src/app/hmg-common/ui/searchable-select/searchable-select/searchable-select.component.ts new file mode 100644 index 00000000..4c9bf63d --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/searchable-select/searchable-select/searchable-select.component.ts @@ -0,0 +1,129 @@ +import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; +import { ModalController } from '@ionic/angular'; +import { OptionModel } from '../option.model'; +import { CommonService } from 'src/app/hmg-common/services/common/common.service'; +import { SharedDataService } from 'src/app/hmg-common/services/shared-data-service/shared-data.service'; +import { TranslatorService } from 'src/app/hmg-common/services/translator/translator.service'; +import { SearchableOptionsPage } from '../searchable-options.page'; + +@Component({ + selector: 'searchable-select', + templateUrl: './searchable-select.component.html', + styleUrls: ['./searchable-select.component.scss'] +}) +export class SearchableSelectComponent implements OnInit { + @Input() default: string; + @Input() title: string; + @Input() progress = false; + @Input() placeHolder: string; + @Output() selected = new EventEmitter(); + @Output() canceled = new EventEmitter(); + @Input() options: OptionModel[] = []; + + public selectedOption: OptionModel; + public finalSelection: any; + public searchField: string; + public showList = false; + public direction: string; + private isOpened = false; + constructor( + public cs: CommonService, + public ts: TranslatorService, + public modalController: ModalController, + public sharedData: SharedDataService) { } + + ngOnInit() { + this.direction = TranslatorService.getCurrentDirection(); + this.setDefault(this.default); + } + + public searchFieldChanged() { + // this.selectedOption = null; + } + + public matches(option: OptionModel): boolean { + if (this.searchField) { + if (option.label) { + return option.label.toLowerCase().indexOf(this.searchField.toLowerCase()) >= 0; + } else { + return false; + } + } else { + return true; + } + } + + public noMatch(): boolean { + for (const option of this.options) { + if (this.matches(option)) { + return false; + } + } + return true; + } + + public optionSelected(option) { + this.selectedOption = option; + } + public selectionChanged(event) { + // console.log (event); + } + + public cancelSelection() { + this.showList = false; + } + public submitSelection() { + this.finalSelection = this.selectedOption; + this.selected.emit(this.finalSelection); + this.showList = false; + } + + + public showOptions() { + if (this.cs.hasData(this.options)) { + if (this.progress) { + this.cs.startLoading(); + } + this.closePage(); + this.showOptionsModal(); + } else { + this.cs.presentAlert(this.ts.trPK('general', 'empty')); + } + } + + private closePage() { + this.modalController.getTop().then( ( top: HTMLIonModalElement)=> { + if ( top) { + top.dismiss(); + } + }); + } + + async showOptionsModal() { + this.sharedData.setSharedData(this.options, OptionModel.SHARED_DATA); + // Create a modal using MyModalComponent with some initial data + const modal = await this.modalController.create({ + component: SearchableOptionsPage, + componentProps: {} + }); + modal.cssClass = 'modal-list'; + await modal.present(); + const { data } = await modal.onDidDismiss(); + if (data && data.selection) { + this.selectedOption = data.selection; + if (this.selectedOption) { + this.selected.emit(this.selectedOption); + } else { + this.canceled.emit(); + } + } else { + this.canceled.emit(); + } + } + + public setDefault(selection: string) { + if (selection) { + this.selectedOption = new OptionModel(selection, null); + } + } +} diff --git a/Mohem/src/app/hmg-common/ui/segment-content/segment-content.component.html b/Mohem/src/app/hmg-common/ui/segment-content/segment-content.component.html new file mode 100644 index 00000000..8916f9e2 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/segment-content/segment-content.component.html @@ -0,0 +1,10 @@ + +
+ + + +
\ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/segment-content/segment-content.component.scss b/Mohem/src/app/hmg-common/ui/segment-content/segment-content.component.scss new file mode 100644 index 00000000..81cc06e4 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/segment-content/segment-content.component.scss @@ -0,0 +1,11 @@ +.segment-scroll-area { + position: fixed; + width: 100%; + bottom: 0; + left: 0; + right: 0; + overflow-y: scroll; + top: 3.3cm; + --padding-top: 0; + --offset-top: 0; +} \ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/segment-content/segment-content.component.spec.ts b/Mohem/src/app/hmg-common/ui/segment-content/segment-content.component.spec.ts new file mode 100644 index 00000000..2e16ed57 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/segment-content/segment-content.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SegmentContentComponent } from './segment-content.component'; + +describe('SegmentContentComponent', () => { + let component: SegmentContentComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ SegmentContentComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(SegmentContentComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/ui/segment-content/segment-content.component.ts b/Mohem/src/app/hmg-common/ui/segment-content/segment-content.component.ts new file mode 100644 index 00000000..f29dd564 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/segment-content/segment-content.component.ts @@ -0,0 +1,15 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'segment-content', + templateUrl: './segment-content.component.html', + styleUrls: ['./segment-content.component.scss'] +}) +export class SegmentContentComponent implements OnInit { + + constructor() { } + + ngOnInit() { + } + +} diff --git a/Mohem/src/app/hmg-common/ui/segments/segment.model.ts b/Mohem/src/app/hmg-common/ui/segments/segment.model.ts new file mode 100644 index 00000000..4cd3c6ff --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/segments/segment.model.ts @@ -0,0 +1,5 @@ +export class SegmentButton { + constructor(public title: string, public id: string) { + + } +} \ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/segments/segments.component.html b/Mohem/src/app/hmg-common/ui/segments/segments.component.html new file mode 100644 index 00000000..f6fa1185 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/segments/segments.component.html @@ -0,0 +1,8 @@ + + + +
{{ button.title | translate}}
+
+
+
\ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/segments/segments.component.scss b/Mohem/src/app/hmg-common/ui/segments/segments.component.scss new file mode 100644 index 00000000..1de38a40 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/segments/segments.component.scss @@ -0,0 +1,113 @@ +.column { + padding-left: 0; + padding-right: 0; +} + +.gird-no-padding { + --ion-grid-padding: 0px; +} + +/* +if you want to add it outside the ion-content to allow +ion-refresher to working perfectly inside ion-content +*/ +.floating { + position: fixed; + top: 1.2cm; + left: 0; + right: 0; + z-index: 10; + background: white; +} + +.no-padding-top{ + --padding-top: 0 !important; +} +.button { + padding: 0; + margin: 0; + height: 1.1cm; + background-color: rgba(255, 255, 255, 0); + border-bottom-width: 0.02cm; + border-bottom-style: solid; + color: var(--ion-color-primary); + text-align: center; + padding-top: .35cm; + font-size: 0.37cm; +} + + +.normal { + color:var(--ion-color-primary); + background-color: rgba(255, 255, 255, 0); + border-bottom-color: var(--ion-color-medium); +} + +.pressed { + color:var(--ion-color-secondary); + background-color: rgba(255, 255, 255, 0); + border-bottom-color: var(--ion-color-secondary); + font-weight: bold; + -webkit-border-top-left-radius: 10px; + -webkit-border-top-right-radius: 10px; + -moz-border-radius-topleft: 10px; + -moz-border-radius-topright: 10px; + border-top-left-radius: 10px; + border-top-right-radius: 10px; + + -webkit-animation-name: ripple; + animation-name: ripple; + -webkit-animation-duration: 07s; + animation-duration: 0.7s; + -webkit-animation-fill-mode: both; + animation-fill-mode: both; + animation-iteration-count: 1; + + /* + + -webkit-animation-name: bounceIn; + animation-name: bounceIn; + -webkit-animation-duration: .75s; + animation-duration: .75s; + -webkit-animation-duration: 1s; + animation-duration: 1s; + -webkit-animation-fill-mode: both; + animation-fill-mode: both; + */ +} + + + +.ripple-effect { + -webkit-animation-name: ripple; + animation-name: ripple; + -webkit-animation-duration: 1s; + animation-duration: 1s; + -webkit-animation-fill-mode: both; + animation-fill-mode: both; + animation-iteration-count: 1; +} + +@-webkit-keyframes ripple { + 0% { + background-color: rgba(209,32,38,0.5); + color: white; + } + + 100% { + background-color: rgba(255, 255, 255, 0); + color: var(--ion-color-secondary); + } +} + +@keyframes ripple { + 0% { + background-color: rgba(209,32,38,0.5); + color: white; + } + + 100% { + background-color: rgba(255, 255, 255, 0); + color:var(--ion-color-secondary); + } +} diff --git a/Mohem/src/app/hmg-common/ui/segments/segments.component.spec.ts b/Mohem/src/app/hmg-common/ui/segments/segments.component.spec.ts new file mode 100644 index 00000000..2369f8eb --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/segments/segments.component.spec.ts @@ -0,0 +1,27 @@ +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SegmentsPage } from './segments.page'; + +describe('SegmentsPage', () => { + let component: SegmentsPage; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ SegmentsPage ], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(SegmentsPage); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/ui/segments/segments.component.ts b/Mohem/src/app/hmg-common/ui/segments/segments.component.ts new file mode 100644 index 00000000..3c6c2102 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/segments/segments.component.ts @@ -0,0 +1,75 @@ +import { Component, OnInit, Input, Output, EventEmitter, OnDestroy } from '@angular/core'; +import { CommonService } from '../../services/common/common.service'; +import { TranslatorService } from '../../services/translator/translator.service'; +import { SegmentButton } from './segment.model'; +import { Subscription } from 'rxjs'; +import { Router, NavigationEnd } from '@angular/router'; + +@Component({ + selector: 'segments', + templateUrl: './segments.component.html', + styleUrls: ['./segments.component.scss'], +}) +export class SegmentsComponent implements OnInit, OnDestroy { + + @Input() buttons: SegmentButton[]; + @Output() changed = new EventEmitter(); + @Input() floating = false; + public activeSegment: string; + public hide = false; + private routerSubscription: Subscription; + constructor( + public cs: CommonService, + public ts: TranslatorService, + private router: Router + ) { } + + ngOnInit() { + if (this.floating) { + this.routerSubscription = this.router.events.subscribe((val) => { + // see also + if (val instanceof NavigationEnd) { + this.hide = true; + } + }); + } + } + + public ngOnDestroy(): void { + if (this.routerSubscription) { + this.routerSubscription.unsubscribe(); + } + } + + + @Input() set active(active: string) { + if (active) { + this.activeSegment = active; + this.emitEvent(active); + } + + } + get active(): string { + return this.activeSegment; + } + public onClick(button: SegmentButton) { + if (button.id !== this.active) { + this.active = button.id; + this.emitEvent(button.id); + } + } + + private emitEvent(id: string) { + this.changed.emit({ + detail: { + value: id + } + }); + } + + public setActive(active: string) { + this.activeSegment = active; + this.emitEvent(active); + } + +} diff --git a/Mohem/src/app/hmg-common/ui/select/model/select.model.ts b/Mohem/src/app/hmg-common/ui/select/model/select.model.ts new file mode 100644 index 00000000..cac6ce14 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/select/model/select.model.ts @@ -0,0 +1,8 @@ +import { Translation } from '../../../services/translator/Translation'; + +export class SelectModel { + public title: Translation; + public value: any ; + public selected = false; + public optionalValue?: any; +} diff --git a/Mohem/src/app/hmg-common/ui/select/model/selection.ts b/Mohem/src/app/hmg-common/ui/select/model/selection.ts new file mode 100644 index 00000000..f32b27bc --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/select/model/selection.ts @@ -0,0 +1,15 @@ +export class Selection { + + public value: any; + public optionalValue: any; + public show = false; + constructor( ) { + } + + public refresh() { + this.show = false; + setTimeout( () => { + this.show = true; + }, 100); + } +} diff --git a/Mohem/src/app/hmg-common/ui/select/select.component.html b/Mohem/src/app/hmg-common/ui/select/select.component.html new file mode 100644 index 00000000..8007ebe0 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/select/select.component.html @@ -0,0 +1,9 @@ + + {{title}} + + + {{ ts.tr(option.title) }} + + \ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/select/select.component.scss b/Mohem/src/app/hmg-common/ui/select/select.component.scss new file mode 100644 index 00000000..e37ea818 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/select/select.component.scss @@ -0,0 +1,10 @@ +.options-select { + /* max-width: 70% !important;*/ +} + +.alert-button-group:first-child { + color: white !important; + background-color: var(--ion-color-secondary) !important; + background: var(--ion-color-secondary) !important; + + } \ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/select/select.component.spec.ts b/Mohem/src/app/hmg-common/ui/select/select.component.spec.ts new file mode 100644 index 00000000..b1cd6f84 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/select/select.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SelectComponent } from './select.component'; + +describe('SelectComponent', () => { + let component: SelectComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ SelectComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(SelectComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/ui/select/select.component.ts b/Mohem/src/app/hmg-common/ui/select/select.component.ts new file mode 100644 index 00000000..69007c02 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/select/select.component.ts @@ -0,0 +1,46 @@ +import { Component, OnInit, Output, EventEmitter } from '@angular/core'; +import { TranslatorService } from '../../services/translator/translator.service'; +import { ConnectorService } from '../../services/connector/connector.service'; +import { Input } from '@angular/core'; +import { SelectModel } from './model/select.model'; +import { Selection } from './model/selection'; + +@Component({ + selector: 'options-select', + templateUrl: './select.component.html', + styleUrls: ['./select.component.scss'] +}) +export class SelectComponent implements OnInit { + + @Input() title: string; + @Input() placeHolder: string; + @Input() dataPath: string; + @Output() changed = new EventEmitter(); + public options: SelectModel[] = []; + /* + hold the output selection value + */ + @Input() value: Selection; + constructor( + public ts: TranslatorService, + public cs: ConnectorService) { + } + + ngOnInit() { + this.cs.getLocalResrouce(this.dataPath).subscribe(data => { + if (this.value.value == null ) { + const defValue = data['default']; + if (defValue) { + this.value.value = defValue; + } + } + this.options = data['options']; + }); + } + + public optionSelected() { + this.changed.emit( this.value.value); + } + +} + diff --git a/Mohem/src/app/hmg-common/ui/send-email/send-email.component.html b/Mohem/src/app/hmg-common/ui/send-email/send-email.component.html new file mode 100644 index 00000000..a6281487 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/send-email/send-email.component.html @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/send-email/send-email.component.scss b/Mohem/src/app/hmg-common/ui/send-email/send-email.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/Mohem/src/app/hmg-common/ui/send-email/send-email.component.spec.ts b/Mohem/src/app/hmg-common/ui/send-email/send-email.component.spec.ts new file mode 100644 index 00000000..66c1421a --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/send-email/send-email.component.spec.ts @@ -0,0 +1,27 @@ +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SendEmailPage } from './send-email.page'; + +describe('SendEmailPage', () => { + let component: SendEmailPage; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ SendEmailPage ], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(SendEmailPage); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/ui/send-email/send-email.component.ts b/Mohem/src/app/hmg-common/ui/send-email/send-email.component.ts new file mode 100644 index 00000000..cf970bec --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/send-email/send-email.component.ts @@ -0,0 +1,25 @@ +import { Component, OnInit, Output, EventEmitter, OnDestroy } from '@angular/core'; +import { TranslatorService } from '../../services/translator/translator.service'; +import { Platform, NavController } from '@ionic/angular'; +import { Router, NavigationEnd } from '@angular/router'; +import { Subscription } from 'rxjs'; + +@Component({ + selector: 'send-email', + templateUrl: './send-email.component.html', + styleUrls: ['./send-email.component.scss'] +}) +export class SendEmailComponent implements OnInit { + @Output() triggered = new EventEmitter(); + constructor( + ) { + } + + ngOnInit() { + } + + public onClick() { + this.triggered.emit(); + } + +} diff --git a/Mohem/src/app/hmg-common/ui/sms/service/model/SmsModel.ts b/Mohem/src/app/hmg-common/ui/sms/service/model/SmsModel.ts new file mode 100644 index 00000000..44632da2 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/sms/service/model/SmsModel.ts @@ -0,0 +1,5 @@ +export class SMSPopModel { + CountryCode: string; + MobileNo: string; + IdentificationNo: string; +} diff --git a/Mohem/src/app/hmg-common/ui/sms/service/model/send-activation.response.ts b/Mohem/src/app/hmg-common/ui/sms/service/model/send-activation.response.ts new file mode 100644 index 00000000..56ece053 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/sms/service/model/send-activation.response.ts @@ -0,0 +1,6 @@ +import { Response } from 'src/app/hmg-common/services/models/response'; + +export class SendValidationResponse extends Response { + LogInTokenID: string; + isSMSSent: boolean; +} diff --git a/Mohem/src/app/hmg-common/ui/sms/service/model/user-details.request.ts b/Mohem/src/app/hmg-common/ui/sms/service/model/user-details.request.ts new file mode 100644 index 00000000..9ab38dde --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/sms/service/model/user-details.request.ts @@ -0,0 +1,31 @@ +import { Request } from 'src/app/hmg-common/services/models/request'; + +export class UserDetailsRequest extends Request { + IdentificationNo: string; + MobileNumber: string; + ActivityID: string; + DOB: string; // "/Date(928108800000)/" + Email: string; + FirstName: string; + Gender: string; + Height: number; + IsHeightInCM: boolean; // true + isNotificationOn: boolean; + IsWeightInKG: boolean; + LastName: string; + MiddleName: string; + OldIdentificationNo: string; + OldMobileNumber: string; + Weight: number; + ZipCode: string; + isTermsAndConditionsChecked: boolean; // trueCellNumber: "568201087" + Channel: number; + IPAdress: string; + LanguageID: number; + PatientIdentificationID : string; + PatientMobileNumber: string; + SessionID: string; + VersionID: number; + isDentalAllowedBackend: boolean; + CellNumber: string; +} diff --git a/Mohem/src/app/hmg-common/ui/sms/service/model/validation.request.ts b/Mohem/src/app/hmg-common/ui/sms/service/model/validation.request.ts new file mode 100644 index 00000000..de81b911 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/sms/service/model/validation.request.ts @@ -0,0 +1,6 @@ +import { Request } from 'src/app/hmg-common/services/models/request'; + +export class ValidationRequest extends Request { + LogInTokenID: string; + VerificationCode: string; +} diff --git a/Mohem/src/app/hmg-common/ui/sms/service/smsservice.ts b/Mohem/src/app/hmg-common/ui/sms/service/smsservice.ts new file mode 100644 index 00000000..42be9586 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/sms/service/smsservice.ts @@ -0,0 +1,57 @@ +import { Injectable } from '@angular/core'; +import { UserDetailsRequest } from './model/user-details.request'; +import { AuthenticationService } from 'src/app/hmg-common/services/authentication/authentication.service'; +import { ConnectorService } from 'src/app/hmg-common/services/connector/connector.service'; +import { UserLocalNotificationService } from 'src/app/hmg-common/services/user-local-notification/user-local-notification.service'; +import { Observable } from 'rxjs'; +import { Response } from 'src/app/hmg-common/services/models/response'; +import { TranslatorService } from 'src/app/hmg-common/services/translator/translator.service'; +import { ValidationRequest } from './model/validation.request'; +import { SendValidationResponse } from './model/send-activation.response'; + +@Injectable({ + providedIn: 'root' +}) +export class SMSService { + + public static sendActivation = 'Services/H2ORemainder.svc/REST/H2O_SendActivationCode'; + public static validateActivation = 'Services/H2ORemainder.svc/REST/H2O_ValidateActivationCode'; + public static sendBloodDonationSMS = 'services/PatientVarification.svc/REST/SendSMSForRegisteration'; + public static modal_success : boolean = false; + public static code : string = ""; + public static mobile_number : string = ""; + public static country_code : string = ""; + public static national_id : string = ""; + + constructor( + public con: ConnectorService, + public auth: AuthenticationService, + public notifications: UserLocalNotificationService, + public ts: TranslatorService + ) { + } + + public sendActivationCode(url: string,id: string, cellno: string, zip: string, onError: any, errorLabel: string) + : Observable { + const request = new UserDetailsRequest(); + request.MobileNumber = cellno; + request.ZipCode = zip; + request.IdentificationNo = id; + request.PatientMobileNumber = cellno; + request.CellNumber = cellno; + request.PatientIdentificationID = id; + request.PatientMobileNumber = cellno; + + this.auth.setPublicFields(request); + return this.con.post(url, request, onError, errorLabel); + } + + public validateActivationCode(token: string, code: string, onError: any, errorLabel: string) + : Observable { + const request = new ValidationRequest(); + request.LogInTokenID = token; + request.VerificationCode = code; + this.auth.setPublicFields(request); + return this.con.post(SMSService.validateActivation, request, onError, errorLabel); + } +} diff --git a/Mohem/src/app/hmg-common/ui/sms/sms-pop/sms-pop.component.html b/Mohem/src/app/hmg-common/ui/sms/sms-pop/sms-pop.component.html new file mode 100644 index 00000000..e69de29b diff --git a/Mohem/src/app/hmg-common/ui/sms/sms-pop/sms-pop.component.scss b/Mohem/src/app/hmg-common/ui/sms/sms-pop/sms-pop.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/Mohem/src/app/hmg-common/ui/sms/sms-pop/sms-pop.component.spec.ts b/Mohem/src/app/hmg-common/ui/sms/sms-pop/sms-pop.component.spec.ts new file mode 100644 index 00000000..aad4a1e9 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/sms/sms-pop/sms-pop.component.spec.ts @@ -0,0 +1,27 @@ +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SmsModalPage } from './sms-modal.page'; + +describe('SmsModalPage', () => { + let component: SmsModalPage; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ SmsModalPage ], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(SmsModalPage); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/ui/sms/sms-pop/sms-pop.component.ts b/Mohem/src/app/hmg-common/ui/sms/sms-pop/sms-pop.component.ts new file mode 100644 index 00000000..14bc2f59 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/sms/sms-pop/sms-pop.component.ts @@ -0,0 +1,69 @@ +import { Component, OnInit , Input, Output, EventEmitter } from '@angular/core'; +import { ModalController } from '@ionic/angular'; +import { SmsPage} from '../sms.page'; +import { SMSService } from '../service/smsservice'; +import { SMSPopModel } from 'src/app/hmg-common/ui/sms/service/model/SmsModel'; +import { SharedDataService } from "src/app/hmg-common/services/shared-data-service/shared-data.service"; +@Component({ + selector: 'sms-pop', + templateUrl: './sms-pop.component.html', + styleUrls: ['./sms-pop.component.scss'], +}) +export class SmsPopComponent implements OnInit { + + countr_code: string; + mobile_no: string; + id_number : string; + private dialoginfo = new SMSPopModel(); + @Output() dismiss = new EventEmitter(); + @Output() cancelled = new EventEmitter(); + constructor( + public modalController: ModalController, + public sharedData: SharedDataService) { + } + + ngOnInit() { + SMSService.modal_success = false; + } + + ngAfterViewInit() { + } + + public async presentModal() { + // this.dialoginfo = this.sharedData.getSharedData( "smsdata",true); + // this.countr_code = this.dialoginfo.CountryCode; + // this.mobile_no = this.dialoginfo.MobileNo; + // this.id_number = this.dialoginfo.IdentificationNo; + const modal = await this.modalController.create({ + component: SmsPage, + backdropDismiss : false + // componentProps: { + // id : this.id_number, + // mobile : this.mobile_no, + // c_code : this.countr_code + // } + }); + modal.cssClass = 'sms-modal'; + modal.onDidDismiss().then((d: any) => this.handleModalDismiss(d)); + return await modal.present(); + } + + + public dismissModal() + { + this.dismiss.emit(); + } + +handleModalDismiss = ({ data }) => { + if (SMSService.modal_success == false) { + // alert that user cancelled + this.cancelled.emit(); + } else { + //save the data + this.dismiss.emit(); + + } + + +} +} diff --git a/Mohem/src/app/hmg-common/ui/sms/sms.module.ts b/Mohem/src/app/hmg-common/ui/sms/sms.module.ts new file mode 100644 index 00000000..1ce4e789 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/sms/sms.module.ts @@ -0,0 +1,38 @@ +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 { HmgCommonModule } from 'src/app/hmg-common/hmg-common.module'; +import { SmsPage } from './sms.page'; +import { SmsPopComponent } from './sms-pop/sms-pop.component'; + +const routes: Routes = [ + { + path: '', + component: SmsPage + } +]; + + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + IonicModule, + RouterModule.forChild(routes), + HmgCommonModule + ], + declarations: [ + SmsPage, + SmsPopComponent + ], + exports: [ + SmsPage, + SmsPopComponent + ], + entryComponents: [ + SmsPage + ] +}) +export class SmsPageModule {} diff --git a/Mohem/src/app/hmg-common/ui/sms/sms.page.html b/Mohem/src/app/hmg-common/ui/sms/sms.page.html new file mode 100644 index 00000000..ac32038f --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/sms/sms.page.html @@ -0,0 +1,51 @@ + + + {{'sms,title' | translate}} + + + + + + + + + + + + +
{{ 'home,verification-code-text'| translate}}
+
+ +
{{mobile}}
+
+
+ + + {{ 'h2o,verification_message' | translate}} + + + + + + + {{ 'h2o,validation_message' | translate}} + + + {{displayTime}} + + + + +

{{'h2o,code_failure' | translate}}

+
+ + {{'h2o,resend' | translate}} + +
+ + + {{'general,submit' | translate}} + + +
+
\ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/sms/sms.page.scss b/Mohem/src/app/hmg-common/ui/sms/sms.page.scss new file mode 100644 index 00000000..50dddfce --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/sms/sms.page.scss @@ -0,0 +1,30 @@ +.input-label{ + +} + +.input-label-strong{ + font-weight: bold; +} + +.sms_code{ + margin: 0px; +} + +.timer-body{ + margin-top: 10px; +} + +.input_bottom{ + border-bottom: 0.5px solid gray; +} + +.resend-coloumn{ + text-align: end; +} +.footer-bar{ + height: 0.4cm; +} + +.bottom-grid{ + margin-top: 0.3cm; +} \ No newline at end of file diff --git a/Mohem/src/app/home/home.page.spec.ts b/Mohem/src/app/hmg-common/ui/sms/sms.page.spec.ts similarity index 63% rename from Mohem/src/app/home/home.page.spec.ts rename to Mohem/src/app/hmg-common/ui/sms/sms.page.spec.ts index a7ed5e51..a37333e1 100644 --- a/Mohem/src/app/home/home.page.spec.ts +++ b/Mohem/src/app/hmg-common/ui/sms/sms.page.spec.ts @@ -1,22 +1,22 @@ import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { HomePage } from './home.page'; +import { SmsPage } from './sms.page'; -describe('HomePage', () => { - let component: HomePage; - let fixture: ComponentFixture; +describe('SmsPage', () => { + let component: SmsPage; + let fixture: ComponentFixture; beforeEach(async(() => { TestBed.configureTestingModule({ - declarations: [ HomePage ], + declarations: [ SmsPage ], schemas: [CUSTOM_ELEMENTS_SCHEMA], }) - .compileComponents(); + .compileComponents(); })); beforeEach(() => { - fixture = TestBed.createComponent(HomePage); + fixture = TestBed.createComponent(SmsPage); component = fixture.componentInstance; fixture.detectChanges(); }); diff --git a/Mohem/src/app/hmg-common/ui/sms/sms.page.ts b/Mohem/src/app/hmg-common/ui/sms/sms.page.ts new file mode 100644 index 00000000..fc7242ca --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/sms/sms.page.ts @@ -0,0 +1,193 @@ +import { Component, OnInit } from '@angular/core'; +import { SMSService } from './service/smsservice'; +import { ModalController, NavParams } from '@ionic/angular'; +import { CommonService } from 'src/app/hmg-common/services/common/common.service'; +import { TranslatorService } from 'src/app/hmg-common/services/translator/translator.service'; +import { Response } from 'src/app/hmg-common/services/models/response'; +import { SmsReaderService } from 'src/app/hmg-common/services/sms/sms-reader.service'; +// import { UserDetailsModel } from 'src/app/h2o/service/models/user-details.model'; +// import { SendValidationResponse } from 'src/app/h2o/service/models/send-activation.response'; +import { SharedDataService } from 'src/app/hmg-common/services/shared-data-service/shared-data.service'; +import { CountryCode } from 'src/app/hmg-common/ui/mobile-number/international-mobile/models/country-code.model'; +import { SmsPopComponent } from './sms-pop/sms-pop.component'; +import { AlertController } from '@ionic/angular'; + +@Component({ + selector: 'sms-pop-page', + templateUrl: './sms.page.html', + styleUrls: ['./sms.page.scss'], +}) +export class SmsPage implements OnInit { + public timeInSeconds : number ; + public time : number; + public runTimer : boolean; + public static SHARED_DATA = 'h2o-login-details'; + public hasStarted : boolean; + public countryCode: CountryCode; + public hasFinished : boolean; + public remainingTime : number; + public displayTime : string = ""; + // public userData: UserDetailsModel; + public mobile : string; + public country_code : string; + public id : string; + public MobileNumber : string; + public token : string; + public resend : boolean = false; + public smc_code : any; + constructor(public cs: CommonService, + public ts: TranslatorService, + public alertController: AlertController, + public smsService: SmsReaderService, + public sharedData: SharedDataService, + private modalCtrl:ModalController, + private navParams: NavParams, + public smsservice: SMSService) { + this.initTimer(); + this.startTimer(); + + // this.smsservice.sendActivationCode(this.id, this.mobile, + // this.country_code, () => { }, + // this.ts.trPK('general', 'ok')).subscribe((result: SendValidationResponse) => { + // if (this.cs.validResponse(result)) { + // if (result.isSMSSent) { + // } else { + // this.stopSMSMonitoring(); + // } + // } else { + // this.stopSMSMonitoring(); + // } + // }); + } + + ngOnInit() { + } + + + closeModal() + { + this.modalCtrl.dismiss(); + } + + cancelModal() { + this.modalCtrl.dismiss({ cancelled: true }); + } + + initTimer() { + if (!this.timeInSeconds) { + this.timeInSeconds = 60; + } + this.time = this.timeInSeconds; + this.runTimer = false; + this.hasStarted = false; + this.hasFinished = false; + this.remainingTime = this.timeInSeconds; + this.displayTime = this.getSecondsAsDigitalClock(this.remainingTime); + } + + startTimer() { + this.runTimer = true; + this.hasStarted = true; + this.resend = false; + this.timerTick(); + } + + pauseTimer() { + this.runTimer = false; + } + + resumeTimer() { + this.startTimer(); + } + + timerTick() { + setTimeout(() => { + if (!this.runTimer) { return; } + this.remainingTime--; + this.displayTime = this.getSecondsAsDigitalClock(this.remainingTime); + if (this.remainingTime > 0) { + this.timerTick(); + } + else { + this.hasFinished = true; + this.resend = true; + } + }, 1000); + } + + getSecondsAsDigitalClock(inputSeconds: number) { + var sec_num = parseInt(inputSeconds.toString(), 10); // don't forget the second param + var hours = Math.floor(sec_num / 3600); + var minutes = Math.floor((sec_num - (hours * 3600)) / 60); + var seconds = sec_num - (hours * 3600) - (minutes * 60); + var hoursString = ''; + var minutesString = ''; + var secondsString = ''; + hoursString = (hours < 10) ? "0" + hours : hours.toString(); + minutesString = (minutes < 10) ? "0" + minutes : minutes.toString(); + secondsString = (seconds < 10) ? "0" + seconds : seconds.toString(); + return minutesString + ':' + secondsString; + } + + validate() + { + //this.checkSMSActivationCode(this.smc_code); + SMSService.code = this.smc_code; + this.stopSMSMonitoring(); + this.modalCtrl.dismiss(); + SMSService.modal_success = true; + } + + async presentAlert() { + const alert = await this.alertController.create({ + header: 'Alert', + message: 'Incorrect OTP, Please enter correct OTP.', + buttons: ['OK'] + }); + + await alert.present(); + } + + private checkSMSActivationCode(smsCode: string) { + this.smsservice.validateActivationCode(this.token, smsCode, + () => {}, this.ts.trPK('settings', 'incorrect_otp')).subscribe((result: Response) => { + if (this.cs.validResponse(result)) { + } + }); + } + + public stopSMSMonitoring() { + this.smsService.stopSMSMonitoring(); + } + + public ResendOTP() + { + this.id= SMSService.national_id; + this.mobile= SMSService.mobile_number; + this.country_code= SMSService.country_code; + console.log(this.id); + console.log(this.mobile); + console.log(this.country_code); + + let zip =this.country_code; + // if (this.country_code.indexOf('+') !== -1) { + // zip = this.country_code.substring(this.country_code.indexOf('+') + 1); + // } + // this.smsservice.sendActivationCode(SMSService.sendBloodDonationSMS,this.id, this.mobile, + // zip, () => { }, + // this.ts.trPK('general', 'ok')).subscribe((result: SendValidationResponse) => { + // if (this.cs.validResponse(result)) { + // if (result.isSMSSent) { + // this.initTimer(); + // this.startTimer(); + // } else { + // this.stopSMSMonitoring(); + // } + // } else { + // this.stopSMSMonitoring(); + // } + // }); + } + + +} diff --git a/Mohem/src/app/hmg-common/ui/smsdialog/service/model/SmsDialogModel.ts b/Mohem/src/app/hmg-common/ui/smsdialog/service/model/SmsDialogModel.ts new file mode 100644 index 00000000..43626d79 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/smsdialog/service/model/SmsDialogModel.ts @@ -0,0 +1,5 @@ +export class SMSDialogModel { + CountryCode: string; + MobileNo: string; + IdentificationNo: string; +} diff --git a/Mohem/src/app/hmg-common/ui/smsdialog/service/model/send-activation.response.ts b/Mohem/src/app/hmg-common/ui/smsdialog/service/model/send-activation.response.ts new file mode 100644 index 00000000..56ece053 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/smsdialog/service/model/send-activation.response.ts @@ -0,0 +1,6 @@ +import { Response } from 'src/app/hmg-common/services/models/response'; + +export class SendValidationResponse extends Response { + LogInTokenID: string; + isSMSSent: boolean; +} diff --git a/Mohem/src/app/hmg-common/ui/smsdialog/service/model/user-details.request.ts b/Mohem/src/app/hmg-common/ui/smsdialog/service/model/user-details.request.ts new file mode 100644 index 00000000..0c1d7bcb --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/smsdialog/service/model/user-details.request.ts @@ -0,0 +1,22 @@ +import { Request } from 'src/app/hmg-common/services/models/request'; + +export class UserDetailsRequest extends Request { + IdentificationNo: string; + MobileNumber: string; + ActivityID: string; + DOB: string; // "/Date(928108800000)/" + Email: string; + FirstName: string; + Gender: string; + Height: number; + IsHeightInCM: boolean; // true + isNotificationOn: boolean; + IsWeightInKG: boolean; + LastName: string; + MiddleName: string; + OldIdentificationNo: string; + OldMobileNumber: string; + Weight: number; + ZipCode: string; + isTermsAndConditionsChecked: boolean; // true +} diff --git a/Mohem/src/app/hmg-common/ui/smsdialog/service/model/validation.request.ts b/Mohem/src/app/hmg-common/ui/smsdialog/service/model/validation.request.ts new file mode 100644 index 00000000..de81b911 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/smsdialog/service/model/validation.request.ts @@ -0,0 +1,6 @@ +import { Request } from 'src/app/hmg-common/services/models/request'; + +export class ValidationRequest extends Request { + LogInTokenID: string; + VerificationCode: string; +} diff --git a/Mohem/src/app/hmg-common/ui/smsdialog/service/smsdialogservice.ts b/Mohem/src/app/hmg-common/ui/smsdialog/service/smsdialogservice.ts new file mode 100644 index 00000000..a37ab47d --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/smsdialog/service/smsdialogservice.ts @@ -0,0 +1,47 @@ +import { Injectable } from '@angular/core'; +import { UserDetailsRequest } from './model/user-details.request'; +import { AuthenticationService } from 'src/app/hmg-common/services/authentication/authentication.service'; +import { ConnectorService } from 'src/app/hmg-common/services/connector/connector.service'; +import { UserLocalNotificationService } from 'src/app/hmg-common/services/user-local-notification/user-local-notification.service'; +import { Observable } from 'rxjs'; +import { Response } from 'src/app/hmg-common/services/models/response'; +import { TranslatorService } from 'src/app/hmg-common/services/translator/translator.service'; +import { ValidationRequest } from './model/validation.request'; +import { SendValidationResponse } from './model/send-activation.response'; + +@Injectable({ + providedIn: 'root' +}) +export class SMSDialogService { + + public static sendActivation = 'Services/H2ORemainder.svc/REST/H2O_SendActivationCode'; + public static validateActivation = 'Services/H2ORemainder.svc/REST/H2O_ValidateActivationCode'; + public static modal_success : boolean = false; + + constructor( + public con: ConnectorService, + public auth: AuthenticationService, + public notifications: UserLocalNotificationService, + public ts: TranslatorService + ) { + } + + public sendActivationCode(id: string, cellno: string, zip: string, onError: any, errorLabel: string) + : Observable { + const request = new UserDetailsRequest(); + request.MobileNumber = cellno; + request.ZipCode = zip; + request.IdentificationNo = id; + this.auth.setPublicFields(request); + return this.con.post(SMSDialogService.sendActivation, request, onError, errorLabel); + } + + public validateActivationCode(token: string, code: string, onError: any, errorLabel: string) + : Observable { + const request = new ValidationRequest(); + request.LogInTokenID = token; + request.VerificationCode = code; + this.auth.setPublicFields(request); + return this.con.post(SMSDialogService.validateActivation, request, onError, errorLabel); + } +} diff --git a/Mohem/src/app/hmg-common/ui/smsdialog/sms-modal/sms-modal.component.html b/Mohem/src/app/hmg-common/ui/smsdialog/sms-modal/sms-modal.component.html new file mode 100644 index 00000000..e69de29b diff --git a/Mohem/src/app/hmg-common/ui/smsdialog/sms-modal/sms-modal.component.scss b/Mohem/src/app/hmg-common/ui/smsdialog/sms-modal/sms-modal.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/Mohem/src/app/hmg-common/ui/smsdialog/sms-modal/sms-modal.component.spec.ts b/Mohem/src/app/hmg-common/ui/smsdialog/sms-modal/sms-modal.component.spec.ts new file mode 100644 index 00000000..aad4a1e9 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/smsdialog/sms-modal/sms-modal.component.spec.ts @@ -0,0 +1,27 @@ +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SmsModalPage } from './sms-modal.page'; + +describe('SmsModalPage', () => { + let component: SmsModalPage; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ SmsModalPage ], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(SmsModalPage); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/ui/smsdialog/sms-modal/sms-modal.component.ts b/Mohem/src/app/hmg-common/ui/smsdialog/sms-modal/sms-modal.component.ts new file mode 100644 index 00000000..1bc16f50 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/smsdialog/sms-modal/sms-modal.component.ts @@ -0,0 +1,63 @@ +import { Component, OnInit , Input, Output, EventEmitter } from '@angular/core'; +import { ModalController } from '@ionic/angular'; +import { SmsdialogPage} from '../smsdialog.page'; +import { SMSDialogService } from '../service/smsdialogservice'; +import { SMSDialogModel } from 'src/app/hmg-common/ui/smsdialog/service/model/SmsDialogModel'; +import { SharedDataService } from "src/app/hmg-common/services/shared-data-service/shared-data.service"; +@Component({ + selector: 'sms-modal', + templateUrl: './sms-modal.component.html', + styleUrls: ['./sms-modal.component.scss'], +}) +export class SmsModalComponent implements OnInit { + + countr_code: string; + mobile_no: string; + id_number : string; + private dialoginfo = new SMSDialogModel(); + @Output() dismiss = new EventEmitter(); + @Output() cancelled = new EventEmitter(); + constructor( + public modalController: ModalController, + public sharedData: SharedDataService) { + } + + ngOnInit() { + SMSDialogService.modal_success = false; + } + + ngAfterViewInit() { + } + + public async presentModal() { + this.dialoginfo = this.sharedData.getSharedData( "smsdata",true); + this.countr_code = this.dialoginfo.CountryCode; + this.mobile_no = this.dialoginfo.MobileNo; + this.id_number = this.dialoginfo.IdentificationNo; + const modal = await this.modalController.create({ + component: SmsdialogPage, + backdropDismiss : true, + componentProps: { + id : this.id_number, + mobile : this.mobile_no, + c_code : this.countr_code + } + }); + modal.cssClass = 'sms-modal'; + modal.onDidDismiss().then((d: any) => this.handleModalDismiss(d)); + return await modal.present(); + } + +handleModalDismiss = ({ data }) => { + if (SMSDialogService.modal_success == false) { + // alert that user cancelled + this.cancelled.emit(); + } else { + //save the data + this.dismiss.emit(); + + } + + +} +} diff --git a/Mohem/src/app/hmg-common/ui/smsdialog/smsdialog.module.ts b/Mohem/src/app/hmg-common/ui/smsdialog/smsdialog.module.ts new file mode 100644 index 00000000..74d63486 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/smsdialog/smsdialog.module.ts @@ -0,0 +1,40 @@ +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 { SmsdialogPage } from './smsdialog.page'; +import { HmgCommonModule } from 'src/app/hmg-common/hmg-common.module'; +import { SmsModalComponent } from './sms-modal/sms-modal.component'; + + +const routes: Routes = [ + { + path: '', + component: SmsdialogPage + } +]; + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + IonicModule, + RouterModule.forChild(routes), + HmgCommonModule + ], + declarations: [ + SmsdialogPage, + SmsModalComponent + ], + exports: [ + SmsdialogPage, + SmsModalComponent + ], + entryComponents: [ + SmsdialogPage + ] +}) +export class SmsdialogPageModule {} diff --git a/Mohem/src/app/hmg-common/ui/smsdialog/smsdialog.page.html b/Mohem/src/app/hmg-common/ui/smsdialog/smsdialog.page.html new file mode 100644 index 00000000..1dcde399 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/smsdialog/smsdialog.page.html @@ -0,0 +1,38 @@ + + + {{'sms,title' | translate}} + + + + + + + + {{ 'h2o,verification_message' | translate}} + + + + + + + {{ 'h2o,validation_message' | translate}} + + + {{displayTime}} + + + + +

{{'h2o,code_failure' | translate}}

+
+ + {{'h2o,resend' | translate}} + +
+ + + {{'general,submit' | translate}} + + +
+
\ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/smsdialog/smsdialog.page.scss b/Mohem/src/app/hmg-common/ui/smsdialog/smsdialog.page.scss new file mode 100644 index 00000000..50dddfce --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/smsdialog/smsdialog.page.scss @@ -0,0 +1,30 @@ +.input-label{ + +} + +.input-label-strong{ + font-weight: bold; +} + +.sms_code{ + margin: 0px; +} + +.timer-body{ + margin-top: 10px; +} + +.input_bottom{ + border-bottom: 0.5px solid gray; +} + +.resend-coloumn{ + text-align: end; +} +.footer-bar{ + height: 0.4cm; +} + +.bottom-grid{ + margin-top: 0.3cm; +} \ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/smsdialog/smsdialog.page.spec.ts b/Mohem/src/app/hmg-common/ui/smsdialog/smsdialog.page.spec.ts new file mode 100644 index 00000000..ac247bc4 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/smsdialog/smsdialog.page.spec.ts @@ -0,0 +1,27 @@ +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SmsdialogPage } from './smsdialog.page'; + +describe('SmsdialogPage', () => { + let component: SmsdialogPage; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ SmsdialogPage ], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(SmsdialogPage); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/ui/smsdialog/smsdialog.page.ts b/Mohem/src/app/hmg-common/ui/smsdialog/smsdialog.page.ts new file mode 100644 index 00000000..24cc3e4f --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/smsdialog/smsdialog.page.ts @@ -0,0 +1,187 @@ +import { Component, OnInit } from '@angular/core'; +import { SMSDialogService } from './service/smsdialogservice'; +import { ModalController } from '@ionic/angular'; +import { CommonService } from 'src/app/hmg-common/services/common/common.service'; +import { TranslatorService } from 'src/app/hmg-common/services/translator/translator.service'; +import { Response } from 'src/app/hmg-common/services/models/response'; +import { SmsReaderService } from 'src/app/hmg-common/services/sms/sms-reader.service'; +// import { UserDetailsModel } from 'src/app/h2o/service/models/user-details.model'; +// import { SendValidationResponse } from 'src/app/h2o/service/models/send-activation.response'; +import { SharedDataService } from 'src/app/hmg-common/services/shared-data-service/shared-data.service'; +import { CountryCode } from 'src/app/hmg-common/ui/mobile-number/international-mobile/models/country-code.model'; +import { SmsModalComponent } from './sms-modal/sms-modal.component'; +import { AlertController } from '@ionic/angular'; + +@Component({ + selector: 'app-smsdialog', + templateUrl: './smsdialog.page.html', + styleUrls: ['./smsdialog.page.scss'], +}) +export class SmsdialogPage implements OnInit { + public timeInSeconds : number ; + public time : number; + public runTimer : boolean; + public static SHARED_DATA = 'h2o-login-details'; + public hasStarted : boolean; + public countryCode: CountryCode; + public hasFinished : boolean; + public remainingTime : number; + public displayTime : string = ""; + // public userData: UserDetailsModel; + public mobile : string; + public country_code : string; + public id : string; + public MobileNumber : string; + public token : string; + public resend : boolean = false; + public smc_code : any; + constructor(public cs: CommonService, + public ts: TranslatorService, + public alertController: AlertController, + public smsService: SmsReaderService, + public sharedData: SharedDataService, + private modalCtrl:ModalController, + // private navParams: NavParams, + public smsservice: SMSDialogService) { + // this.country_code = this.navParams.get("c_code"); + // this.MobileNumber = this.navParams.get('mobile'); + // this.mobile = this.navParams.get('mobile'); + // this.id = this.navParams.get('id'); + // this.smsservice.sendActivationCode(this.id, this.mobile, + // this.country_code, () => { }, + // this.ts.trPK('general', 'ok')).subscribe((result: SendValidationResponse) => { + // if (this.cs.validResponse(result)) { + // if (result.isSMSSent) { + // this.token = result.LogInTokenID; + // this.initTimer(); + // this.startTimer(); + // } else { + // this.stopSMSMonitoring(); + // } + // } else { + // this.stopSMSMonitoring(); + // } + // }); + } + + ngOnInit() { + } + + closeModal() + { + this.modalCtrl.dismiss(); + } + + cancelModal() { + this.modalCtrl.dismiss({ cancelled: true }); + } + + initTimer() { + if (!this.timeInSeconds) { + this.timeInSeconds = 60; + } + this.time = this.timeInSeconds; + this.runTimer = false; + this.hasStarted = false; + this.hasFinished = false; + this.remainingTime = this.timeInSeconds; + this.displayTime = this.getSecondsAsDigitalClock(this.remainingTime); + } + + startTimer() { + this.runTimer = true; + this.hasStarted = true; + this.resend = false; + this.timerTick(); + } + + pauseTimer() { + this.runTimer = false; + } + + resumeTimer() { + this.startTimer(); + } + + timerTick() { + setTimeout(() => { + if (!this.runTimer) { return; } + this.remainingTime--; + this.displayTime = this.getSecondsAsDigitalClock(this.remainingTime); + if (this.remainingTime > 0) { + this.timerTick(); + } + else { + this.hasFinished = true; + this.resend = true; + } + }, 1000); + } + + getSecondsAsDigitalClock(inputSeconds: number) { + var sec_num = parseInt(inputSeconds.toString(), 10); // don't forget the second param + var hours = Math.floor(sec_num / 3600); + var minutes = Math.floor((sec_num - (hours * 3600)) / 60); + var seconds = sec_num - (hours * 3600) - (minutes * 60); + var hoursString = ''; + var minutesString = ''; + var secondsString = ''; + hoursString = (hours < 10) ? "0" + hours : hours.toString(); + minutesString = (minutes < 10) ? "0" + minutes : minutes.toString(); + secondsString = (seconds < 10) ? "0" + seconds : seconds.toString(); + return minutesString + ':' + secondsString; + } + + validate() + { + this.checkSMSActivationCode(this.smc_code); + } + + public presentSMSPasswordDialog() { + + } + + async presentAlert() { + const alert = await this.alertController.create({ + header: 'Alert', + message: 'Incorrect OTP, Please enter correct OTP.', + buttons: ['OK'] + }); + + await alert.present(); + } + + private checkSMSActivationCode(smsCode: string) { + this.smsservice.validateActivationCode(this.token, smsCode, + () => {}, this.ts.trPK('settings', 'incorrect_otp')).subscribe((result: Response) => { + if (this.cs.validResponse(result)) { + this.stopSMSMonitoring(); + this.modalCtrl.dismiss(); + SMSDialogService.modal_success = true; + } + }); + } + + public stopSMSMonitoring() { + this.smsService.stopSMSMonitoring(); + } + + public ResendOTP() + { + // this.smsservice.sendActivationCode(this.id, this.mobile, + // this.country_code, () => { }, + // this.ts.trPK('general', 'ok')).subscribe((result: SendValidationResponse) => { + // if (this.cs.validResponse(result)) { + // if (result.isSMSSent) { + // this.initTimer(); + // this.startTimer(); + // } else { + // this.stopSMSMonitoring(); + // } + // } else { + // this.stopSMSMonitoring(); + // } + // }); + } + +} diff --git a/Mohem/src/app/hmg-common/ui/spacer/l-spacer/l-spacer.component.html b/Mohem/src/app/hmg-common/ui/spacer/l-spacer/l-spacer.component.html new file mode 100644 index 00000000..f7250666 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/spacer/l-spacer/l-spacer.component.html @@ -0,0 +1 @@ +
\ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/spacer/l-spacer/l-spacer.component.scss b/Mohem/src/app/hmg-common/ui/spacer/l-spacer/l-spacer.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/Mohem/src/app/hmg-common/ui/spacer/l-spacer/l-spacer.component.spec.ts b/Mohem/src/app/hmg-common/ui/spacer/l-spacer/l-spacer.component.spec.ts new file mode 100644 index 00000000..d62d4baa --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/spacer/l-spacer/l-spacer.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { LSpacerComponent } from './l-spacer.component'; + +describe('LSpacerComponent', () => { + let component: LSpacerComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ LSpacerComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(LSpacerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/ui/spacer/l-spacer/l-spacer.component.ts b/Mohem/src/app/hmg-common/ui/spacer/l-spacer/l-spacer.component.ts new file mode 100644 index 00000000..83050ee4 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/spacer/l-spacer/l-spacer.component.ts @@ -0,0 +1,15 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'l-spacer', + templateUrl: './l-spacer.component.html', + styleUrls: ['./l-spacer.component.scss'] +}) +export class LSpacerComponent implements OnInit { + + constructor() { } + + ngOnInit() { + } + +} diff --git a/Mohem/src/app/hmg-common/ui/spacer/m-spacer/m-spacer.component.html b/Mohem/src/app/hmg-common/ui/spacer/m-spacer/m-spacer.component.html new file mode 100644 index 00000000..976eb573 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/spacer/m-spacer/m-spacer.component.html @@ -0,0 +1 @@ +
\ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/spacer/m-spacer/m-spacer.component.scss b/Mohem/src/app/hmg-common/ui/spacer/m-spacer/m-spacer.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/Mohem/src/app/hmg-common/ui/spacer/m-spacer/m-spacer.component.spec.ts b/Mohem/src/app/hmg-common/ui/spacer/m-spacer/m-spacer.component.spec.ts new file mode 100644 index 00000000..27999bfe --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/spacer/m-spacer/m-spacer.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { MSpacerComponent } from './m-spacer.component'; + +describe('MSpacerComponent', () => { + let component: MSpacerComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ MSpacerComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(MSpacerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/ui/spacer/m-spacer/m-spacer.component.ts b/Mohem/src/app/hmg-common/ui/spacer/m-spacer/m-spacer.component.ts new file mode 100644 index 00000000..4b02675e --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/spacer/m-spacer/m-spacer.component.ts @@ -0,0 +1,15 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'm-spacer', + templateUrl: './m-spacer.component.html', + styleUrls: ['./m-spacer.component.scss'] +}) +export class MSpacerComponent implements OnInit { + + constructor() { } + + ngOnInit() { + } + +} diff --git a/Mohem/src/app/hmg-common/ui/spacer/page-trailer/page-trailer.component.html b/Mohem/src/app/hmg-common/ui/spacer/page-trailer/page-trailer.component.html new file mode 100644 index 00000000..36c0d032 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/spacer/page-trailer/page-trailer.component.html @@ -0,0 +1,2 @@ +
+
\ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/spacer/page-trailer/page-trailer.component.scss b/Mohem/src/app/hmg-common/ui/spacer/page-trailer/page-trailer.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/Mohem/src/app/hmg-common/ui/spacer/page-trailer/page-trailer.component.spec.ts b/Mohem/src/app/hmg-common/ui/spacer/page-trailer/page-trailer.component.spec.ts new file mode 100644 index 00000000..0adc2383 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/spacer/page-trailer/page-trailer.component.spec.ts @@ -0,0 +1,27 @@ +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { PageTrailerPage } from './page-trailer.page'; + +describe('PageTrailerPage', () => { + let component: PageTrailerPage; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ PageTrailerPage ], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(PageTrailerPage); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/ui/spacer/page-trailer/page-trailer.component.ts b/Mohem/src/app/hmg-common/ui/spacer/page-trailer/page-trailer.component.ts new file mode 100644 index 00000000..0709a2c4 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/spacer/page-trailer/page-trailer.component.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, Input } from '@angular/core'; + +@Component({ + selector: 'page-trailer', + templateUrl: './page-trailer.component.html', + styleUrls: ['./page-trailer.component.scss'], +}) +export class PageTrailerComponent implements OnInit { + + @Input() small = false; + constructor() { } + + ngOnInit() {} + +} diff --git a/Mohem/src/app/hmg-common/ui/spacer/s-spacer/s-spacer.component.html b/Mohem/src/app/hmg-common/ui/spacer/s-spacer/s-spacer.component.html new file mode 100644 index 00000000..c080c55b --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/spacer/s-spacer/s-spacer.component.html @@ -0,0 +1 @@ +
\ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/spacer/s-spacer/s-spacer.component.scss b/Mohem/src/app/hmg-common/ui/spacer/s-spacer/s-spacer.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/Mohem/src/app/hmg-common/ui/spacer/s-spacer/s-spacer.component.spec.ts b/Mohem/src/app/hmg-common/ui/spacer/s-spacer/s-spacer.component.spec.ts new file mode 100644 index 00000000..7b3c6621 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/spacer/s-spacer/s-spacer.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SSpacerComponent } from './s-spacer.component'; + +describe('SSpacerComponent', () => { + let component: SSpacerComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ SSpacerComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(SSpacerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/ui/spacer/s-spacer/s-spacer.component.ts b/Mohem/src/app/hmg-common/ui/spacer/s-spacer/s-spacer.component.ts new file mode 100644 index 00000000..4ebd8d34 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/spacer/s-spacer/s-spacer.component.ts @@ -0,0 +1,15 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 's-spacer', + templateUrl: './s-spacer.component.html', + styleUrls: ['./s-spacer.component.scss'] +}) +export class SSpacerComponent implements OnInit { + + constructor() { } + + ngOnInit() { + } + +} diff --git a/Mohem/src/app/hmg-common/ui/tabs-bar/tabs-bar.component.html b/Mohem/src/app/hmg-common/ui/tabs-bar/tabs-bar.component.html new file mode 100644 index 00000000..928ddea6 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/tabs-bar/tabs-bar.component.html @@ -0,0 +1,49 @@ + +
+ +
+
+

{{ 'home,home' | translate }}

+
+ + +
+
+

{{ 'family,family' | translate}}

+
+ + + +
+ + +
+
+

+ {{ 'eservices,medical-file' | translate}} +

+
+
+ + + +
+
+
+

+ {{ 'notifications,notifications' | translate}}

+
{{ notificationsCount}}
+
+ + + +
+
+

{{ 'general,arabic-change' | translate}}

+

{{ 'general,english-change' | translate}}

+
+
+
\ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/tabs-bar/tabs-bar.component.scss b/Mohem/src/app/hmg-common/ui/tabs-bar/tabs-bar.component.scss new file mode 100644 index 00000000..a6d12401 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/tabs-bar/tabs-bar.component.scss @@ -0,0 +1,190 @@ +.tabs-container-full{ + width: 100%; + height: 1.4cm; + background-color: white; + position: fixed; + bottom: 0; + left:0; + right: 0; +} + +.tabs-container-partial{ + width: 72%; + margin-left: 28%; + height: 1.4cm; + background-color: white; + position: fixed; + bottom: 0; + left: 0; + right: 0; +} + +.tab-button { + width: 18%; + float: left; + border-top-style: solid; + border-top-width: 0.02cm; + border-top-color: var(--ion-color-medium); +} + + +.tab-button-selected { + border-top-color: var(--ion-color-secondary); + -webkit-animation-name: bounceIn; + animation-name: bounceIn; + -webkit-animation-duration: .75s; + animation-duration: .75s; + -webkit-animation-duration: 1s; + animation-duration: 1s; + -webkit-animation-fill-mode: both; + animation-fill-mode: both; +} + + + +/* +.tab-button:hover { + border-top-width: 0.1cm; + border-top-color: #d12026; +} +*/ + +.tab-button .icon { + padding: 0; + float: left; + height: .9cm; + width: 100%; + background-position: center !important; + background-size: contain !important; + background-repeat: no-repeat !important; +} + +.home-icon { + background-image: url(/assets/icon/tabs/home.png); +} +.home-selected { + background-image: url(/assets/icon/tabs/home-selected.png); +} + +.family-icon { + background-image: url(/assets/icon/tabs/family.png); +} +.family-selected { + background-image: url(/assets/icon/tabs/family-selected.png); +} +.notifications-icon { + background-image: url(/assets/icon/tabs/notifications.png); +} +.notifications-selected { + background-image: url(/assets/icon/tabs/notifications-selected.png); +} + +.file-icon { + background-image: url(/assets/icon/tabs/file.png); +} +.file-selected { + background-image: url(/assets/icon/tabs/file-selected.png); +} +.en-icon { + background-image: url(/assets/icon/tabs/en.png); +} +.ar-icon { + background-image: url(/assets/icon/tabs/ar.png); +} + + +.tab-button .title { + width: 100%; + margin-top: 0cm; + color: var(--ion-color-primary); + text-align: center; + font-size: 0.3cm; + white-space: nowrap; + float: left; +} +.title-selected{ + font-weight: bolder !important; + font-size: 0.33cm !important; +} + + /*mobile Landscape */ + @media only screen + and (min-device-height: 0px) + and (max-device-height: 515px) + and (orientation: landscape) { + + } + + +/* +medical button +*/ + +.medial-file-temp-space{ + width: 28%; + float: left; + height: 100%; +} + + .medical-button{ + position: absolute; + margin-left: 36%; + margin-right: 36%; + width: 28%; + bottom: 0cm; + background: transparent; +} + +.medical-button-selected{ + -webkit-animation-name: bounceIn; + animation-name: bounceIn; + -webkit-animation-duration: .75s; + animation-duration: .75s; + -webkit-animation-duration: 1s; + animation-duration: 1s; + -webkit-animation-fill-mode: both; + animation-fill-mode: both; + +} + +.medical-button .icon { + float: left; + height: 2cm; + width: 100%; + background-position: center !important; + background-size: contain !important; + background-repeat: no-repeat !important; +} + +.medical-button .title { + padding: 0; + margin: 0; + width: 100%; + margin-top: 0; + color: var(--ion-color-primary); + text-align: center; + font-size: 0.3cm; + white-space: nowrap; + float: left; + padding: 0; + margin-bottom: 0.1cm; +} + +.notifications-count { + position: absolute; + right: 18%; + top: 0.1cm; + background-color: var( --ion-color-secondary); + width: 0.55cm; + height: 0.55cm; + font-size: 0.32cm; + color: white; + text-align: center; + border-radius: solid; + border-color: var( --ion-color-secondary); + border-style: solid; + border-radius: 50%; + opacity: 0.9; + padding-top: 0.03cm; + +} \ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/tabs-bar/tabs-bar.component.spec.ts b/Mohem/src/app/hmg-common/ui/tabs-bar/tabs-bar.component.spec.ts new file mode 100644 index 00000000..977cb50a --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/tabs-bar/tabs-bar.component.spec.ts @@ -0,0 +1,27 @@ +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TabsBarPage } from './tabs-bar.page'; + +describe('TabsBarPage', () => { + let component: TabsBarPage; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ TabsBarPage ], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(TabsBarPage); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/ui/tabs-bar/tabs-bar.component.ts b/Mohem/src/app/hmg-common/ui/tabs-bar/tabs-bar.component.ts new file mode 100644 index 00000000..d02c3d77 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/tabs-bar/tabs-bar.component.ts @@ -0,0 +1,234 @@ +import { Component, OnInit, Input } from '@angular/core'; +import { CommonService } from 'src/app/hmg-common/services/common/common.service'; +import { TranslatorService } from 'src/app/hmg-common/services/translator/translator.service'; +import { Platform, Events } from '@ionic/angular'; +import { isMonday } from 'date-fns'; +import { Router, NavigationEnd } from '@angular/router'; +import { NativeStorage } from '@ionic-native/native-storage/ngx'; +// import { HomePage } from 'src/app/home/home.page'; +import { NationalityService } from '../../services/nationality/nationality.service'; +import { ProjectsService } from '../../services/projects/projects.service'; +import { KeyboardService } from '../../services/keyboard/keyboard.service'; +import { KeyboardStatusModel } from '../../services/keyboard/keyboard-status.model'; +// import { NotificationsComponent } from 'src/app/eservices/notifications-center/notifications/notifications.component'; +import { AuthenticationService } from '../../services/authentication/authentication.service'; +// import { NotificationsCenterService } from 'src/app/eservices/notifications-center/service/notifications-center.service'; + +@Component({ + selector: 'tabs-bar', + templateUrl: './tabs-bar.component.html', + styleUrls: ['./tabs-bar.component.scss'], +}) +export class TabsBarComponent implements OnInit { + + + private static fullClass = 'tabs-container-full slideInUpSlow'; + private static partialClass = 'tabs-container-partial slideInUpSlow'; + + private static home = 'home'; + private static family = 'family'; + private static notifications = 'notifications'; + private static file = 'file'; + private static language = 'language'; + + public show = true; + public isMenuOpened = false; + public showClass = TabsBarComponent.fullClass; + public active: string; + public currentLanguage: string; + public notificationsCount: number; + public keyboardOpened = false; + public showMedicalFile = true; + constructor( + public cs: CommonService, + public ts: TranslatorService, + public platform: Platform, + public router: Router, + public nativeStorage: NativeStorage, + public events: Events, + public projectsService: ProjectsService, + public nationalityService: NationalityService, + public keyboardService: KeyboardService + ) { } + + private isSplitPanelAlwaysOpened = false; + ngOnInit() { + this.platform.ready().then(() => { + this.monitorKeyboardChange(); + this.monitorNotificationsChange(); + this.monitorSizeChange(); + this.monitUrlChange(); + this.monitorFamilyMemberLogin(); + this.currentLanguage = TranslatorService.getCurrentLanguageName(); + // this.enableMedicalFile(); + }); + } + + /* + show medical file after a while + because of it's red color is itense with the splash screen + */ + private enableMedicalFile() { + this.showMedicalFile = false; + setTimeout(() => this.showMedicalFile = true, 500); + } + /* + hide the tabs bar when keyboard is opened + */ + private monitorKeyboardChange() { + this.keyboardOpened = KeyboardService.keyboardOpened; + this.events.subscribe(KeyboardService.KEYBOARD_STATUS, (status: KeyboardStatusModel) => { + this.keyboardOpened = status.opened; + }); + } + + /* + if main user logged in with family member we + remove notifications count + */ + private monitorFamilyMemberLogin() { + this.events.subscribe(AuthenticationService.FAMILY_LOGIN_EVENT, (user) => { + this.notificationsCount = null; + }); + } + + + + + /* + change take partial or full width on different devices + */ + private monitorSizeChange() { + this.platform.resize.subscribe(() => { + this.onResize(); + }); + this.onResize(); + } + + /* + monitor notifications count update form + 1- notifications center when user read new message + 2- home dash board + 3- push notifications + */ + private monitorNotificationsChange() { + + // this.events.subscribe(NotificationsCenterService.NOTIFICATIONS_COUNT_EVENT, (count: number) => { + // this.notificationsCount = count; + // this.cs.setBadge(count); + // }); + } + + /* + update selected icons based on navigation + */ + private monitUrlChange() { + this.router.events.subscribe((val) => { + if (val instanceof NavigationEnd) { + if (this.matchesURL(val, CommonService.HOME_URL, TabsBarComponent.home)) { + this.cs.openHome(); + } else if (this.matchesURL(val, [CommonService.NOTIFICATIONS_URL], TabsBarComponent.notifications)) { + this.cs.openNotifications(); + } else if (this.matchesURL(val, [CommonService.ESERVICES_URL], TabsBarComponent.file)) { + this.cs.openEservices(); + } else if (this.matchesURL(val, [CommonService.FAMILY_FILES], TabsBarComponent.family)) { + this.cs.openFamilyFiles(); + } + } + }); + + } + private matchesURL(val: NavigationEnd, targets: string[], targetActive: string) { + for (const target of targets) { + if (val.urlAfterRedirects === target) { + if (this.active !== targetActive) { + this.active = targetActive; + return true; + } + } + } + return false; + } + private fixedOpendLastTime = false; + private onResize() { + // if splitpanel always fixed opened + this.isSplitPanelAlwaysOpened = this.platform.width() >= 992; + setTimeout(() => { + if (this.isSplitPanelAlwaysOpened) { + this.isMenuOpened = true; + this.fixedOpendLastTime = true; + this.processTablet(true); + } else { + // this.processMobile( false); + if (this.fixedOpendLastTime) { + this.fixedOpendLastTime = false; + this.processMobile(false); + } else { + this.processMobile(this.isMenuOpened); + } + } + }, 100); + + } + + public menuOpened(opened: boolean) { + this.platform.ready().then(() => { + if (this.isSplitPanelAlwaysOpened) { + this.processTablet(opened); + } else { + this.processMobile(opened); + } + }); + } + + + private processMobile(opened: boolean) { + this.isMenuOpened = opened; + this.show = !opened; + this.showClass = TabsBarComponent.fullClass; + } + + public processTablet(opened: boolean) { + this.show = true; + this.showClass = TabsBarComponent.partialClass; + } + + + + public onClick(name: string) { + this.active = name; + switch (this.active) { + case TabsBarComponent.home: + this.cs.openHome(); + break; + case TabsBarComponent.family: + this.cs.openFamilyFiles(); + break; + case TabsBarComponent.notifications: + this.cs.openNotifications(); + break; + case TabsBarComponent.file: + this.cs.openEservices(); + break; + case TabsBarComponent.language: + this.switchLanguage(); + break; + } + } + + private switchLanguage() { + this.nationalityService.cleanCache(); + this.projectsService.cleanCache(); + this.ts.switchLanguage(); + /* + this.cs.presentConfirmDialog(this.ts.trPK('general', 'switch-lng'), () => { + this.nationalityService.cleanCache(); + this.projectsService.cleanCache(); + this.ts.switchLanguage(); + }); + */ + } + + + +} diff --git a/Mohem/src/app/hmg-common/ui/toggle-button/toggle-button.component.html b/Mohem/src/app/hmg-common/ui/toggle-button/toggle-button.component.html new file mode 100644 index 00000000..283d025b --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/toggle-button/toggle-button.component.html @@ -0,0 +1,6 @@ + + + {{ title}} + + \ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/toggle-button/toggle-button.component.scss b/Mohem/src/app/hmg-common/ui/toggle-button/toggle-button.component.scss new file mode 100644 index 00000000..59ffc228 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/toggle-button/toggle-button.component.scss @@ -0,0 +1,24 @@ + +.normal-button { + --background: white; + background-color: white; + --background-activated: var(--ion-color-light); + --background-focused: var(--ion-color-light); + border-color: var(--ion-color-primary); + color: var(--ion-color-primary); + font-size: 0.35cm; +} +.pressed-button { + --background: var(--ion-color-light); + --background-activated: var(--ion-color-light); + --background-focused: var(--ion-color-light); + background-color: var(--ion-color-light); + border-color: transparent !important; + border-color: #efefef; + font-weight: bold; +} + +.toggle-icon { + margin-right: 0.2cm; + margin-left: 0.2cm; +} \ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/toggle-button/toggle-button.component.spec.ts b/Mohem/src/app/hmg-common/ui/toggle-button/toggle-button.component.spec.ts new file mode 100644 index 00000000..b3156665 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/toggle-button/toggle-button.component.spec.ts @@ -0,0 +1,27 @@ +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ToggleButtonPage } from './toggle-button.page'; + +describe('ToggleButtonPage', () => { + let component: ToggleButtonPage; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ToggleButtonPage ], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ToggleButtonPage); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/ui/toggle-button/toggle-button.component.ts b/Mohem/src/app/hmg-common/ui/toggle-button/toggle-button.component.ts new file mode 100644 index 00000000..5e8587b7 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/toggle-button/toggle-button.component.ts @@ -0,0 +1,22 @@ +import { Component, OnInit, EventEmitter, Output, Input } from '@angular/core'; + +@Component({ + selector: 'toggle-button', + templateUrl: './toggle-button.component.html', + styleUrls: ['./toggle-button.component.scss'], +}) +export class ToggleButtonComponent implements OnInit { + + @Input() title: string; + @Output() toggled = new EventEmitter(); + public pressed = false; + constructor() { } + + ngOnInit() {} + + public onClicked() { + this.pressed = ! this.pressed; + this.toggled.emit(this.pressed); + } + +} diff --git a/Mohem/src/app/hmg-common/ui/toolbar-button/toolbar-button.component.html b/Mohem/src/app/hmg-common/ui/toolbar-button/toolbar-button.component.html new file mode 100644 index 00000000..d78d9c3f --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/toolbar-button/toolbar-button.component.html @@ -0,0 +1,6 @@ + + +
{{title}}
+ +
+
\ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/toolbar-button/toolbar-button.component.scss b/Mohem/src/app/hmg-common/ui/toolbar-button/toolbar-button.component.scss new file mode 100644 index 00000000..ee04138d --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/toolbar-button/toolbar-button.component.scss @@ -0,0 +1,18 @@ +.icon { + width: 0.7cm; +} + +.toolbar-button-android { + position: absolute; + right: 0.2cm; + top: 0.3cm; +} +.toolbar-button-ios { + position: absolute; + right: 0.2cm; +} + +.title { + margin-right: 0.2cm; + font-size: 0.46cm; +} \ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/toolbar-button/toolbar-button.component.spec.ts b/Mohem/src/app/hmg-common/ui/toolbar-button/toolbar-button.component.spec.ts new file mode 100644 index 00000000..22286897 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/toolbar-button/toolbar-button.component.spec.ts @@ -0,0 +1,27 @@ +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ToolbarButtonPage } from './toolbar-button.page'; + +describe('ToolbarButtonPage', () => { + let component: ToolbarButtonPage; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ToolbarButtonPage ], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ToolbarButtonPage); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/ui/toolbar-button/toolbar-button.component.ts b/Mohem/src/app/hmg-common/ui/toolbar-button/toolbar-button.component.ts new file mode 100644 index 00000000..9b1aee60 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/toolbar-button/toolbar-button.component.ts @@ -0,0 +1,27 @@ +import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; +import { Platform } from '@ionic/angular'; + +@Component({ + selector: 'toolbar-button', + templateUrl: './toolbar-button.component.html', + styleUrls: ['./toolbar-button.component.scss'], +}) +export class ToolbarButtonComponent implements OnInit { + @Output() click = new EventEmitter(); + @Input() title; + @Input() icon; + public style = 'toolbar-button-android' ; + constructor( + private platform: Platform + ) { } + + ngOnInit() { + this.platform.ready().then( () => { + this.style = this.platform.is('ios') ? 'toolbar-button-ios' : 'toolbar-button-android' ; + }); + } + + public onClick() { + this.click.emit(); + } +} diff --git a/Mohem/src/app/hmg-common/ui/two-option-select/two-option-select.component.html b/Mohem/src/app/hmg-common/ui/two-option-select/two-option-select.component.html new file mode 100644 index 00000000..565802b6 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/two-option-select/two-option-select.component.html @@ -0,0 +1,13 @@ + + + {{ label }} + + + + {{ option1 }} + + + {{ option2 }} + + + \ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/two-option-select/two-option-select.component.scss b/Mohem/src/app/hmg-common/ui/two-option-select/two-option-select.component.scss new file mode 100644 index 00000000..5ef01806 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/two-option-select/two-option-select.component.scss @@ -0,0 +1,25 @@ +ion-button{ + --background: var(--ion-color-light); + --color: var(--ion-color-primary); +} +.selected-button { + --background: var(--ion-color-secondary); + --color: var(--ion-color-light); + --background-activated: var(--ion-color-secondary); + --background-focused: var(--ion-color-secondary); + --color-activated: var(--ion-color-light); + --color-focused: var(--ion-color-light); +} + +ion-label{ + margin-left: 0.3cm; + margin-top:0.1cm; +} + + + .form-item { + margin-top: 0 !important; + padding-top: 0 !important; + } + + \ No newline at end of file diff --git a/Mohem/src/app/hmg-common/ui/two-option-select/two-option-select.component.spec.ts b/Mohem/src/app/hmg-common/ui/two-option-select/two-option-select.component.spec.ts new file mode 100644 index 00000000..50145a57 --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/two-option-select/two-option-select.component.spec.ts @@ -0,0 +1,27 @@ +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TwoOptionSelectPage } from './two-option-select.page'; + +describe('TwoOptionSelectPage', () => { + let component: TwoOptionSelectPage; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ TwoOptionSelectPage ], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(TwoOptionSelectPage); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Mohem/src/app/hmg-common/ui/two-option-select/two-option-select.component.ts b/Mohem/src/app/hmg-common/ui/two-option-select/two-option-select.component.ts new file mode 100644 index 00000000..a654059a --- /dev/null +++ b/Mohem/src/app/hmg-common/ui/two-option-select/two-option-select.component.ts @@ -0,0 +1,38 @@ +import { Component, OnInit, Output, EventEmitter, Input } from '@angular/core'; + +@Component({ + selector: 'two-option-select', + templateUrl: './two-option-select.component.html', + styleUrls: ['./two-option-select.component.scss'], +}) +export class TwoOptionSelectComponent implements OnInit { + + @Input() isOption1 = false; + @Input() isOption2 = false; + @Input() option1: string; + @Input() option2: string; + @Input() label: string; + value: number; + @Output() selected = new EventEmitter(); + + constructor() { + } + + select(cond: boolean) { + if (cond) { + this.isOption1 = true; + this.isOption2 = false; + this.value = 1; + this.selected.emit(this.value); + } else { + this.isOption1 = false; + this.isOption2 = true; + this.value = 2; + this.selected.emit(this.value); + } + } + ngOnInit() { + + } + +} diff --git a/Mohem/src/app/home/home.module.ts b/Mohem/src/app/home/home.module.ts deleted file mode 100644 index 3ccd41c8..00000000 --- a/Mohem/src/app/home/home.module.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { IonicModule } from '@ionic/angular'; -import { FormsModule } from '@angular/forms'; -import { RouterModule } from '@angular/router'; - -import { HomePage } from './home.page'; - -@NgModule({ - imports: [ - CommonModule, - FormsModule, - IonicModule, - RouterModule.forChild([ - { - path: '', - component: HomePage - } - ]) - ], - declarations: [HomePage] -}) -export class HomePageModule {} diff --git a/Mohem/src/app/home/home.page.html b/Mohem/src/app/home/home.page.html deleted file mode 100644 index 570ede79..00000000 --- a/Mohem/src/app/home/home.page.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - Ionic Blank - - - - - -
- The world is your oyster. -

If you get lost, the docs will be your guide.

-
-
diff --git a/Mohem/src/app/home/home.page.scss b/Mohem/src/app/home/home.page.scss deleted file mode 100644 index 8b137891..00000000 --- a/Mohem/src/app/home/home.page.scss +++ /dev/null @@ -1 +0,0 @@ - diff --git a/Mohem/src/app/home/home.page.ts b/Mohem/src/app/home/home.page.ts deleted file mode 100644 index 83522d59..00000000 --- a/Mohem/src/app/home/home.page.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Component } from '@angular/core'; - -@Component({ - selector: 'app-home', - templateUrl: 'home.page.html', - styleUrls: ['home.page.scss'], -}) -export class HomePage { - - constructor() {} - -} diff --git a/Mohem/src/assets/font/GE_SS_TWO_MEDIUM.OTF b/Mohem/src/assets/font/GE_SS_TWO_MEDIUM.OTF new file mode 100644 index 00000000..ff4a1bfa Binary files /dev/null and b/Mohem/src/assets/font/GE_SS_TWO_MEDIUM.OTF differ diff --git a/Mohem/src/assets/font/GE_SS_Two_Bold.otf b/Mohem/src/assets/font/GE_SS_Two_Bold.otf new file mode 100644 index 00000000..da99274a Binary files /dev/null and b/Mohem/src/assets/font/GE_SS_Two_Bold.otf differ diff --git a/Mohem/src/assets/font/GE_SS_Two_Light.otf b/Mohem/src/assets/font/GE_SS_Two_Light.otf new file mode 100644 index 00000000..60ea874e Binary files /dev/null and b/Mohem/src/assets/font/GE_SS_Two_Light.otf differ diff --git a/Mohem/src/assets/font/WorkSans-Bold.otf b/Mohem/src/assets/font/WorkSans-Bold.otf new file mode 100644 index 00000000..44de98b0 Binary files /dev/null and b/Mohem/src/assets/font/WorkSans-Bold.otf differ diff --git a/Mohem/src/assets/font/WorkSans-Light.otf b/Mohem/src/assets/font/WorkSans-Light.otf new file mode 100644 index 00000000..be5e0ac4 Binary files /dev/null and b/Mohem/src/assets/font/WorkSans-Light.otf differ diff --git a/Mohem/src/assets/font/WorkSans-Medium.otf b/Mohem/src/assets/font/WorkSans-Medium.otf new file mode 100644 index 00000000..42964a18 Binary files /dev/null and b/Mohem/src/assets/font/WorkSans-Medium.otf differ diff --git a/Mohem/src/assets/font/WorkSans-Regular.otf b/Mohem/src/assets/font/WorkSans-Regular.otf new file mode 100644 index 00000000..c04386eb Binary files /dev/null and b/Mohem/src/assets/font/WorkSans-Regular.otf differ diff --git a/Mohem/src/assets/font/WorkSans-SemiBold.otf b/Mohem/src/assets/font/WorkSans-SemiBold.otf new file mode 100644 index 00000000..3f4d1791 Binary files /dev/null and b/Mohem/src/assets/font/WorkSans-SemiBold.otf differ diff --git a/Mohem/src/assets/imgs/CS.png b/Mohem/src/assets/imgs/CS.png new file mode 100644 index 00000000..4b351a40 Binary files /dev/null and b/Mohem/src/assets/imgs/CS.png differ diff --git a/Mohem/src/assets/imgs/E.png b/Mohem/src/assets/imgs/E.png new file mode 100644 index 00000000..bb3f63cd Binary files /dev/null and b/Mohem/src/assets/imgs/E.png differ diff --git a/Mohem/src/assets/imgs/M.png b/Mohem/src/assets/imgs/M.png new file mode 100644 index 00000000..d4b49bd5 Binary files /dev/null and b/Mohem/src/assets/imgs/M.png differ diff --git a/Mohem/src/assets/imgs/S.png b/Mohem/src/assets/imgs/S.png new file mode 100644 index 00000000..40389e3f Binary files /dev/null and b/Mohem/src/assets/imgs/S.png differ diff --git a/Mohem/src/assets/imgs/accrual.png b/Mohem/src/assets/imgs/accrual.png new file mode 100644 index 00000000..4b1fda5a Binary files /dev/null and b/Mohem/src/assets/imgs/accrual.png differ diff --git a/Mohem/src/assets/imgs/accu.png b/Mohem/src/assets/imgs/accu.png new file mode 100644 index 00000000..9fba524b Binary files /dev/null and b/Mohem/src/assets/imgs/accu.png differ diff --git a/Mohem/src/assets/imgs/accubalance.png b/Mohem/src/assets/imgs/accubalance.png new file mode 100644 index 00000000..120dd488 Binary files /dev/null and b/Mohem/src/assets/imgs/accubalance.png differ diff --git a/Mohem/src/assets/imgs/actionHistory.png b/Mohem/src/assets/imgs/actionHistory.png new file mode 100644 index 00000000..74288eb2 Binary files /dev/null and b/Mohem/src/assets/imgs/actionHistory.png differ diff --git a/Mohem/src/assets/imgs/arrownew.png b/Mohem/src/assets/imgs/arrownew.png new file mode 100644 index 00000000..c9c2c41f Binary files /dev/null and b/Mohem/src/assets/imgs/arrownew.png differ diff --git a/Mohem/src/assets/imgs/attachment.png b/Mohem/src/assets/imgs/attachment.png new file mode 100644 index 00000000..d744d520 Binary files /dev/null and b/Mohem/src/assets/imgs/attachment.png differ diff --git a/Mohem/src/assets/imgs/attend.png b/Mohem/src/assets/imgs/attend.png new file mode 100644 index 00000000..0238025d Binary files /dev/null and b/Mohem/src/assets/imgs/attend.png differ diff --git a/Mohem/src/assets/imgs/bell.png b/Mohem/src/assets/imgs/bell.png new file mode 100644 index 00000000..6873246b Binary files /dev/null and b/Mohem/src/assets/imgs/bell.png differ diff --git a/Mohem/src/assets/imgs/cancel.png b/Mohem/src/assets/imgs/cancel.png new file mode 100644 index 00000000..0d419f29 Binary files /dev/null and b/Mohem/src/assets/imgs/cancel.png differ diff --git a/Mohem/src/assets/imgs/changepass.png b/Mohem/src/assets/imgs/changepass.png new file mode 100644 index 00000000..01cd8528 Binary files /dev/null and b/Mohem/src/assets/imgs/changepass.png differ diff --git a/Mohem/src/assets/imgs/delete.png b/Mohem/src/assets/imgs/delete.png new file mode 100644 index 00000000..30baf04a Binary files /dev/null and b/Mohem/src/assets/imgs/delete.png differ diff --git a/Mohem/src/assets/imgs/deletegray.png b/Mohem/src/assets/imgs/deletegray.png new file mode 100644 index 00000000..5910584c Binary files /dev/null and b/Mohem/src/assets/imgs/deletegray.png differ diff --git a/Mohem/src/assets/imgs/details.png b/Mohem/src/assets/imgs/details.png new file mode 100644 index 00000000..fc13a16a Binary files /dev/null and b/Mohem/src/assets/imgs/details.png differ diff --git a/Mohem/src/assets/imgs/documents.png b/Mohem/src/assets/imgs/documents.png new file mode 100644 index 00000000..cac8c829 Binary files /dev/null and b/Mohem/src/assets/imgs/documents.png differ diff --git a/Mohem/src/assets/imgs/edit.png b/Mohem/src/assets/imgs/edit.png new file mode 100644 index 00000000..1feb1005 Binary files /dev/null and b/Mohem/src/assets/imgs/edit.png differ diff --git a/Mohem/src/assets/imgs/file.png b/Mohem/src/assets/imgs/file.png new file mode 100644 index 00000000..1807fe70 Binary files /dev/null and b/Mohem/src/assets/imgs/file.png differ diff --git a/Mohem/src/assets/imgs/folder.png b/Mohem/src/assets/imgs/folder.png new file mode 100644 index 00000000..ba445c81 Binary files /dev/null and b/Mohem/src/assets/imgs/folder.png differ diff --git a/Mohem/src/assets/imgs/info.png b/Mohem/src/assets/imgs/info.png new file mode 100644 index 00000000..cdd4f7fc Binary files /dev/null and b/Mohem/src/assets/imgs/info.png differ diff --git a/Mohem/src/assets/imgs/language.png b/Mohem/src/assets/imgs/language.png new file mode 100644 index 00000000..be15b74f Binary files /dev/null and b/Mohem/src/assets/imgs/language.png differ diff --git a/Mohem/src/assets/imgs/logo.png b/Mohem/src/assets/imgs/logo.png new file mode 100644 index 00000000..80f631d7 Binary files /dev/null and b/Mohem/src/assets/imgs/logo.png differ diff --git a/Mohem/src/assets/imgs/more.png b/Mohem/src/assets/imgs/more.png new file mode 100644 index 00000000..ad56785f Binary files /dev/null and b/Mohem/src/assets/imgs/more.png differ diff --git a/Mohem/src/assets/imgs/more1.png b/Mohem/src/assets/imgs/more1.png new file mode 100644 index 00000000..f64da40f Binary files /dev/null and b/Mohem/src/assets/imgs/more1.png differ diff --git a/Mohem/src/assets/imgs/moving.gif b/Mohem/src/assets/imgs/moving.gif new file mode 100644 index 00000000..95e0fadc Binary files /dev/null and b/Mohem/src/assets/imgs/moving.gif differ diff --git a/Mohem/src/assets/imgs/no-wifi.png b/Mohem/src/assets/imgs/no-wifi.png new file mode 100644 index 00000000..b958b859 Binary files /dev/null and b/Mohem/src/assets/imgs/no-wifi.png differ diff --git a/Mohem/src/assets/imgs/noData.png b/Mohem/src/assets/imgs/noData.png new file mode 100644 index 00000000..a19748ca Binary files /dev/null and b/Mohem/src/assets/imgs/noData.png differ diff --git a/Mohem/src/assets/imgs/password.png b/Mohem/src/assets/imgs/password.png new file mode 100644 index 00000000..882a7ce0 Binary files /dev/null and b/Mohem/src/assets/imgs/password.png differ diff --git a/Mohem/src/assets/imgs/profile.png b/Mohem/src/assets/imgs/profile.png new file mode 100644 index 00000000..8413eaa4 Binary files /dev/null and b/Mohem/src/assets/imgs/profile.png differ diff --git a/Mohem/src/assets/imgs/profile1.png b/Mohem/src/assets/imgs/profile1.png new file mode 100644 index 00000000..4cdd64a0 Binary files /dev/null and b/Mohem/src/assets/imgs/profile1.png differ diff --git a/Mohem/src/assets/imgs/signout.png b/Mohem/src/assets/imgs/signout.png new file mode 100644 index 00000000..30d747d4 Binary files /dev/null and b/Mohem/src/assets/imgs/signout.png differ diff --git a/Mohem/src/assets/imgs/username.png b/Mohem/src/assets/imgs/username.png new file mode 100644 index 00000000..24f8dc7a Binary files /dev/null and b/Mohem/src/assets/imgs/username.png differ diff --git a/Mohem/src/assets/imgs/vacationrule.png b/Mohem/src/assets/imgs/vacationrule.png new file mode 100644 index 00000000..4626f84c Binary files /dev/null and b/Mohem/src/assets/imgs/vacationrule.png differ diff --git a/Mohem/src/assets/imgs/view.png b/Mohem/src/assets/imgs/view.png new file mode 100644 index 00000000..ed946356 Binary files /dev/null and b/Mohem/src/assets/imgs/view.png differ diff --git a/Mohem/src/assets/js/sms.js b/Mohem/src/assets/js/sms.js new file mode 100644 index 00000000..ee3c83af --- /dev/null +++ b/Mohem/src/assets/js/sms.js @@ -0,0 +1,28 @@ +var SMS = function () { + + this.isSupported = function () { + return SMSReceive != null; + } + + this.startReciever = function (success, failure) { + SMSReceive.startWatch(function() { + console.log('smsreceive: watching started'); + document.addEventListener('onSMSArrive', function(e) { + console.log('onSMSArrive()'); + var IncomingSMS = e.data; + success(IncomingSMS.body , IncomingSMS.address); + }); + }, + function() {}); + + } + + this.stopReciever = function () { + SMSReceive.stopWatch(function() { + console.log('smsreceive: watching stopped'); + }, function() { + console.log('smsreceive: failed to stop watching'); + }); + } + +} \ No newline at end of file diff --git a/Mohem/src/assets/localization/i18n.json b/Mohem/src/assets/localization/i18n.json new file mode 100644 index 00000000..6853e73a --- /dev/null +++ b/Mohem/src/assets/localization/i18n.json @@ -0,0 +1,635 @@ +{ + "SUPPORTED_LANGUAGES": [ + "en", + "ar", + "fr" + ], +"login": { + "login": { + "en": "Login", + "ar": "الدخول" + }, + "login-type": { + "en": "Login Type", + "ar": "نوع الدخول" + }, + "register": { + "en": "Register", + "ar": "التسجيل" + }, + "sign-out": { + "en": "Are you sure you want to Sign Out", + "ar": "هل أنت متأكد من إغلاق الحساب" + }, + "forgot-id": { + "en": "Forgot Patient ID", + "ar": "نسيت رقم الملف" + }, + "forgot-password": { + "en": "Forgot Password", + "ar": "نسيت كلمة المرور" + }, + "password": { + "en": "Password", + "ar": "كلمه السر" + }, + "forgot-your-id": { + "en": "Forgot Your Patient ID", + "ar": "هل نسيت رقم ملف المريض" + }, + "forgot-desc": { + "en": "Enter your mobile number to receive your patient file number via SMS", + "ar": "أدخل رقم جوالك لاستلام رقم الملف الخاص بك عن طريق الرسائل النصية" + }, + "enter-email": { + "en": "Please you need to enter your email", + "ar": "لو سمحت أدخل البريد الإلكتروني الخاص بك" + }, + "enable-biometric": { + "en": "Do you want to use biometric sensors to ease your login", + "ar": "هل ترغب في استخدام أجهزة الاستشعار البصمة لتسهيل تسجيل دخولك" + }, + "face": { + "en": "Do you want to login with face recognition", + "ar": "هل تود الدخول ببصمة الوجة" + }, + "finger": { + "en": "Do you want to login with finger print", + "ar": "هل تود الدخول ببصمة الإصبع" + }, + "signout": { + "en": "Sign Out", + "ar": "تسجيل خروج" + }, + "find-us": { + "en": "Find us on social", + "ar": "تواصل معنا" + }, + "login-register": { + "en": "Login / Register", + "ar": "دخول / تسجيل" + }, + "id-or-file": { + "en": "ID or File No", + "ar": "هوية أو رقم الملف" + }, + "national-id-or-iqama": { + "en": "National ID or Iqama", + "ar": "رقم الهوية أو الإقامة" + } +}, +"general": { + "birth_date": { + "en": "Birth Date", + "ar": "تاريخ الميلاد" + }, + "alert": { + "en": "Alert", + "ar": "تنبية" + }, + "details": { + "en": "Details", + "ar": "التفاصيل" + }, + "title": { + "en": "Title", + "ar": "العنوان" + }, + "info": { + "en": "Information", + "ar": "معلومات" + }, + "reset": { + "en": "Reset", + "ar": "إعادة تعيين" + }, + "ok": { + "en": "Ok", + "ar": "موافق" + }, + "confirm": { + "en": "Confirm", + "ar": "تأكيد" + }, + "cancel": { + "en": "Cancel", + "ar": "إلغاء" + }, + "done": { + "en": "Done", + "ar": "تم" + }, + "close": { + "en": "Close", + "ar": "إغلق" + }, + "back": { + "en": "Back", + "ar": "رجوع" + }, + "about": { + "en": "About", + "ar": "عن" + }, + "hide": { + "en": "Hide", + "ar": "إخفي" + }, + "select-only": { + "en": "Select", + "ar": "إختر" + }, + "select": { + "en": "Please select", + "ar": "إختر لو سمحت" + }, + "need": { + "en": "You need", + "ar": "أنت تحتاج" + }, + "hospital.location": { + "en": "Hospital Location", + "ar": "مكان المستشفي" + }, + "complaint": { + "en": "Raise Complaint", + "ar": "إرفع شكوي" + }, + "retry": { + "en": "Retry", + "ar": "أعد" + }, + "cart": { + "en": "Add to cart", + "ar": "أضف للسلة" + }, + "reminder": { + "en": "Add Reminder", + "ar": "أضف تذكير" + }, + "cancel-reminder": { + "en": "Cancel Reminder", + "ar": "الغي تذكير" + }, + "send-copy": { + "en": "Send Copy", + "ar": "أرسل نسخة" + }, + "personal-info": { + "en": "Personal Information", + "ar": "البيانات الشخصية" + }, + "qualification": { + "en": "Qualifications", + "ar": "المؤهلات" + }, + "nationality": { + "en": "Nationality", + "ar": "الجنسية" + }, + "empty": { + "en": "Sorry no data avaiable", + "ar": "لا يوجد بيانات" + }, + "no-match": { + "en": "Sorry no match", + "ar": "لا توجد نتيجة" + }, + "home": { + "en": "Home", + "ar": "الرئيسية" + }, + "date": { + "en": "Date", + "ar": "التاريخ" + }, + "num": { + "en": "No", + "ar": "الرقم" + }, + "time": { + "en": "Time", + "ar": "االوقت" + }, + "week": { + "en": "Week", + "ar": "أسبوع" + }, + "weeks": { + "en": "Weeks", + "ar": "أسابيع" + }, + "month": { + "en": "Month", + "ar": "شهر" + }, + "year": { + "en": "Year", + "ar": "سنة" + }, + "delete": { + "en": "Delete", + "ar": "إحذف" + }, + "add": { + "en": "Add", + "ar": "أضف" + }, + "edit": { + "en": "Edit", + "ar": "تعديل" + }, + "measure-unit": { + "en": "Measure unit", + "ar": "وحدة القياس" + }, + "measure-time": { + "en": "Measure time", + "ar": "وقت القياس" + }, + "save": { + "en": "Save", + "ar": "إحفظ" + }, + "success": { + "en": "Done successfully", + "ar": "تم بنجاح" + }, + "other": { + "en": "Other", + "ar": "أخري" + }, + "provide-missing": { + "en": "Please provide required information", + "ar": "لو سمحت قم بإدخال البيانات المطلوبة" + }, + "type": { + "en": "Type", + "ar": "النوع" + }, + "location": { + "en": "Location", + "ar": "المكان" + }, + "sequence": { + "en": "Sequence", + "ar": "رقم" + }, + "status": { + "en": "Status", + "ar": "الحالة" + }, + "scan": { + "en": "Scan", + "ar": "إبحث" + }, + "stop": { + "en": "Stop", + "ar": "توقف" + }, + "stop-connection": { + "en": "Stop Connection", + "ar": "وقف الإتصال" + }, + "remove-measure": { + "en": "Are you sure you want to remove this measure", + "ar": "هل متأكد تريد حذف عذة القراءة" + }, + "optional": { + "en": "Optional", + "ar": "خياري" + }, + "search": { + "en": "Search", + "ar": "إبحث" + }, + "advanced-search": { + "en": "Advanced Search", + "ar": "بحث متقدم" + }, + "email": { + "en": "Email", + "ar": "البريد الالكتروني" + }, + "filter": { + "en": "Filter", + "ar": "تفضيل" + }, + "first-name": { + "en": "First Name", + "ar": "الاسم الأول" + }, + "middle-name": { + "en": "Middle Name", + "ar": "إسم الوالد" + }, + "last-name": { + "en": "Last Name", + "ar": "إسم العائلة" + }, + "subject": { + "en": "Subject", + "ar": "موضوع" + }, + "message": { + "en": "Message", + "ar": "رسالة" + }, + "attachment": { + "en": "Attachment", + "ar": "مرفق" + }, + "select-attachment": { + "en": "Select Attachment", + "ar": "إختر مرفق" + }, + "large-file": { + "en": "Kindly select smaller file", + "ar": "لو سمحت إختر ملف أصغر" + }, + "open": { + "en": "Open", + "ar": "إفتح" + }, + "submit": { + "en": "Submit", + "ar": "أرسل" + }, + "enter-sms-code": { + "en": "Enter verification code", + "ar": "أدخل رقم التعريف" + }, + "enter-sms-enable-biometric": { + "en": "Enter verification for biometric", + "ar": "أدخل رقم التفعيل للبصمة" + }, + "enter-sms": { + "en": "Enter sms ", + "ar": "أدخل رقم الرسالة" + }, + "no-need": { + "en": "No Need", + "ar": "لا حاجة" + }, + "search-citeria": { + "en": "Select search criteria", + "ar": "إختر كيفية البحث" + }, + "search-by-complaint": { + "en": "Chaif Complaint Number", + "ar": "رقم الشكوي" + }, + "complaint-num": { + "en": "Complaint No", + "ar": "رقم الشكوي" + }, + "search-by-file": { + "en": "File Number", + "ar": "رقم الملف" + }, + "search-by-id": { + "en": "Identification Number", + "ar": "رقم الإقامة" + }, + "enter-complaint-no": { + "en": "Enter Chaif Complaint Number", + "ar": "أدخل رقم الشكوي" + }, + "enter-file-no": { + "en": "Enter File Number", + "ar": "أدخل رقم الملف" + }, + "file-no": { + "en": "File Number", + "ar": "رقم الملف" + }, + "enter-id-no": { + "en": "Enter Identification Number", + "ar": "أدخل رقم الإقامة أو الهوية" + }, + "id-no": { + "en": "Identification Number", + "ar": "رقم الإقامة أو الهوية" + }, + "enter-national-id": { + "en": "Enter National ID", + "ar": "أدخل رقم الهوية" + }, + "national-id": { + "en": "National ID", + "ar": "رقم الهوية" + }, + "enter-iqama-no": { + "en": "Enter ID Number", + "ar": "أدخل رقم الإقامة" + }, + "iqama-no": { + "en": "ID Number", + "ar": "رقم الإقامة" + }, + "complaint-no": { + "en": "Complaint No", + "ar": "رقم الشكوي" + }, + "number": { + "en": "Number", + "ar": "الرقم" + }, + "accept": { + "en": "Accept", + "ar": "موافق" + }, + "decline": { + "en": "Decline", + "ar": "أرفض" + }, + "usage-agreement": { + "en": "Usage Agreement", + "ar": "إتفاق الإستخدام" + }, + "loading": { + "en": "Loading ...", + "ar": "يتم التحميل ..." + }, + "email-sent": { + "en": "Email sent successfully", + "ar": "تم إرسال نسخة إلي البريد الإلكتروني" + }, + "send-email": { + "en": "Do you want to send copy of this examination to your personal email
[0]", + "ar": "هل تريد إرسال نسخة من هذا الاختبار إلى بريدك الإلكتروني الشخصي
[0]" + }, + "relogin": { + "en": "You need to login to use this service", + "ar": "تحتاج إلي الدخول لحسابك من أجل إستخدام هذة الخدمة" + }, + "idle-relogin": { + "en": "Your session has expired kindly relogin to use this service ", + "ar": "انتهت صلاحية جلستك يرجى التفضل بإعادة الدخول لإستخدام هذه الخدمة" + }, + "select-type": { + "en": "Select One", + "ar": "اختر فئة" + }, + "from": { + "en": "From", + "ar": "من" + }, + "to": { + "en": "To", + "ar": "الى" + }, + "result": { + "en": "Result", + "ar": "النتيجة" + }, + "select-date": { + "en": "Select Date", + "ar": "إختر ميعاد" + }, + "normal": { + "en": "Normal", + "ar": "عادي" + }, + "use-pin": { + "en": "Use Pin", + "ar": "إستخدم الرقم التعريفي" + }, + "auth-please": { + "en": "Please Authenticated", + "ar": "عرف نفسك" + }, + "dial-code": { + "en": "Dial Code", + "ar": "كود الإتصال" + }, + "country": { + "en": "Country", + "ar": "الدولة" + }, + "settings": { + "en": "Settings", + "ar": "إعدادات" + }, + "about-app": { + "en": "About the app", + "ar": "عن التطبيق" + }, + "mobile": { + "en": "Mobile No", + "ar": "رقم الجوال" + }, + "english": { + "en": "English", + "ar": "الإنجليزية" + }, + "english-change": { + "en": "الإنجليزية", + "ar": "English" + }, + "arabic": { + "en": "Arabic", + "ar": "العربية" + }, + "arabic-change": { + "en": "العربية", + "ar": "Arabic" + }, + "switch-lng": { + "en": "Do you want to change current language", + "ar": "هل تريد تغيير اللغة" + }, + "show-more": { + "en": "Show More >", + "ar": "عرض المزيد >" + }, + "read-less": { + "en": "Read Less <", + "ar": "قراءة أقل <" + }, + "read-more": { + "en": "Read More >", + "ar": "اقرأ المزيد >" + }, + "more":{ + "en": "More...", + "ar": "أكثر..." + }, + "send-email-short": { + "en": "Email", + "ar": "بريد" + }, + "hi": { + "en": "HI", + "ar": "مرحبا" + }, + "blood-type": { + "en": "blood type", + "ar": "فصيلة الدم" + }, + "sync-success": { + "en": "Data Synced Successfully", + "ar": "تمت مزامنة البيانات بنجاح" + }, + "already-synced": { + "en": "Latest data already synced", + "ar": "أحدث البيانات المتزامنة بالفعل" + }, + "weekly": { + "en": "Weekly", + "ar": "أسبوعي" + }, + "monthly": { + "en": "Monthly", + "ar": "شهريا" + }, + "yearly": { + "en": "Yearly", + "ar": "سنوي" + }, + "report-view": { + "en": "Report View", + "ar": "عرض تقرير" + }, + "graph-view": { + "en": "Graph View", + "ar": "عرض الرسم البياني" + }, + "distance-covered": { + "en": "Distance covered in KMs", + "ar": "المسافة المقطوعة بالكيلومترات" + }, + "steps-covered": { + "en": "Steps covered", + "ar": "الخطوات المغطاة" + }, + "hours-asleep": { + "en": "Time asleep in hours", + "ar": "الوقت نائم في ساعات" + }, + "bad": { + "en": "Bad", + "ar": "سيئ" + }, + "poor": { + "en": "Poor", + "ar": "ضعيف" + }, + "acceptable": { + "en": "Acceptable", + "ar": "مقبول" + }, + "good": { + "en": "Good", + "ar": "جيد" + }, + "excellent": { + "en": "Excellent", + "ar": "ممتاز" + }, + "not-allowed": { + "en": "User has no permissions", + "ar": "المستخدم ليس لدية صلاحيات" + } +} +} \ No newline at end of file diff --git a/Mohem/src/global.scss b/Mohem/src/global.scss index 95b74f55..6543a146 100644 --- a/Mohem/src/global.scss +++ b/Mohem/src/global.scss @@ -9,3 +9,4 @@ @import '~@ionic/angular/css/text-alignment.css'; @import '~@ionic/angular/css/text-transformation.css'; @import '~@ionic/angular/css/flex-utils.css'; +@import "theme/styles.scss"; diff --git a/Mohem/src/icon/favicon.ico b/Mohem/src/icon/favicon.ico new file mode 100644 index 00000000..d76fa29d Binary files /dev/null and b/Mohem/src/icon/favicon.ico differ diff --git a/Mohem/src/imgs/CS.png b/Mohem/src/imgs/CS.png new file mode 100644 index 00000000..4b351a40 Binary files /dev/null and b/Mohem/src/imgs/CS.png differ diff --git a/Mohem/src/imgs/E.png b/Mohem/src/imgs/E.png new file mode 100644 index 00000000..bb3f63cd Binary files /dev/null and b/Mohem/src/imgs/E.png differ diff --git a/Mohem/src/imgs/M.png b/Mohem/src/imgs/M.png new file mode 100644 index 00000000..d4b49bd5 Binary files /dev/null and b/Mohem/src/imgs/M.png differ diff --git a/Mohem/src/imgs/S.png b/Mohem/src/imgs/S.png new file mode 100644 index 00000000..40389e3f Binary files /dev/null and b/Mohem/src/imgs/S.png differ diff --git a/Mohem/src/imgs/accrual.png b/Mohem/src/imgs/accrual.png new file mode 100644 index 00000000..4b1fda5a Binary files /dev/null and b/Mohem/src/imgs/accrual.png differ diff --git a/Mohem/src/imgs/accu.png b/Mohem/src/imgs/accu.png new file mode 100644 index 00000000..9fba524b Binary files /dev/null and b/Mohem/src/imgs/accu.png differ diff --git a/Mohem/src/imgs/accubalance.png b/Mohem/src/imgs/accubalance.png new file mode 100644 index 00000000..120dd488 Binary files /dev/null and b/Mohem/src/imgs/accubalance.png differ diff --git a/Mohem/src/imgs/actionHistory.png b/Mohem/src/imgs/actionHistory.png new file mode 100644 index 00000000..74288eb2 Binary files /dev/null and b/Mohem/src/imgs/actionHistory.png differ diff --git a/Mohem/src/imgs/arrownew.png b/Mohem/src/imgs/arrownew.png new file mode 100644 index 00000000..c9c2c41f Binary files /dev/null and b/Mohem/src/imgs/arrownew.png differ diff --git a/Mohem/src/imgs/attachment.png b/Mohem/src/imgs/attachment.png new file mode 100644 index 00000000..d744d520 Binary files /dev/null and b/Mohem/src/imgs/attachment.png differ diff --git a/Mohem/src/imgs/attend.png b/Mohem/src/imgs/attend.png new file mode 100644 index 00000000..0238025d Binary files /dev/null and b/Mohem/src/imgs/attend.png differ diff --git a/Mohem/src/imgs/bell.png b/Mohem/src/imgs/bell.png new file mode 100644 index 00000000..6873246b Binary files /dev/null and b/Mohem/src/imgs/bell.png differ diff --git a/Mohem/src/imgs/cancel.png b/Mohem/src/imgs/cancel.png new file mode 100644 index 00000000..0d419f29 Binary files /dev/null and b/Mohem/src/imgs/cancel.png differ diff --git a/Mohem/src/imgs/changepass.png b/Mohem/src/imgs/changepass.png new file mode 100644 index 00000000..01cd8528 Binary files /dev/null and b/Mohem/src/imgs/changepass.png differ diff --git a/Mohem/src/imgs/delete.png b/Mohem/src/imgs/delete.png new file mode 100644 index 00000000..30baf04a Binary files /dev/null and b/Mohem/src/imgs/delete.png differ diff --git a/Mohem/src/imgs/deletegray.png b/Mohem/src/imgs/deletegray.png new file mode 100644 index 00000000..5910584c Binary files /dev/null and b/Mohem/src/imgs/deletegray.png differ diff --git a/Mohem/src/imgs/details.png b/Mohem/src/imgs/details.png new file mode 100644 index 00000000..fc13a16a Binary files /dev/null and b/Mohem/src/imgs/details.png differ diff --git a/Mohem/src/imgs/documents.png b/Mohem/src/imgs/documents.png new file mode 100644 index 00000000..cac8c829 Binary files /dev/null and b/Mohem/src/imgs/documents.png differ diff --git a/Mohem/src/imgs/edit.png b/Mohem/src/imgs/edit.png new file mode 100644 index 00000000..1feb1005 Binary files /dev/null and b/Mohem/src/imgs/edit.png differ diff --git a/Mohem/src/imgs/file.png b/Mohem/src/imgs/file.png new file mode 100644 index 00000000..1807fe70 Binary files /dev/null and b/Mohem/src/imgs/file.png differ diff --git a/Mohem/src/imgs/folder.png b/Mohem/src/imgs/folder.png new file mode 100644 index 00000000..ba445c81 Binary files /dev/null and b/Mohem/src/imgs/folder.png differ diff --git a/Mohem/src/imgs/info.png b/Mohem/src/imgs/info.png new file mode 100644 index 00000000..cdd4f7fc Binary files /dev/null and b/Mohem/src/imgs/info.png differ diff --git a/Mohem/src/imgs/language.png b/Mohem/src/imgs/language.png new file mode 100644 index 00000000..be15b74f Binary files /dev/null and b/Mohem/src/imgs/language.png differ diff --git a/Mohem/src/imgs/logo.png b/Mohem/src/imgs/logo.png new file mode 100644 index 00000000..80f631d7 Binary files /dev/null and b/Mohem/src/imgs/logo.png differ diff --git a/Mohem/src/imgs/more.png b/Mohem/src/imgs/more.png new file mode 100644 index 00000000..ad56785f Binary files /dev/null and b/Mohem/src/imgs/more.png differ diff --git a/Mohem/src/imgs/more1.png b/Mohem/src/imgs/more1.png new file mode 100644 index 00000000..f64da40f Binary files /dev/null and b/Mohem/src/imgs/more1.png differ diff --git a/Mohem/src/imgs/moving.gif b/Mohem/src/imgs/moving.gif new file mode 100644 index 00000000..95e0fadc Binary files /dev/null and b/Mohem/src/imgs/moving.gif differ diff --git a/Mohem/src/imgs/no-wifi.png b/Mohem/src/imgs/no-wifi.png new file mode 100644 index 00000000..b958b859 Binary files /dev/null and b/Mohem/src/imgs/no-wifi.png differ diff --git a/Mohem/src/imgs/noData.png b/Mohem/src/imgs/noData.png new file mode 100644 index 00000000..a19748ca Binary files /dev/null and b/Mohem/src/imgs/noData.png differ diff --git a/Mohem/src/imgs/password.png b/Mohem/src/imgs/password.png new file mode 100644 index 00000000..882a7ce0 Binary files /dev/null and b/Mohem/src/imgs/password.png differ diff --git a/Mohem/src/imgs/profile.png b/Mohem/src/imgs/profile.png new file mode 100644 index 00000000..8413eaa4 Binary files /dev/null and b/Mohem/src/imgs/profile.png differ diff --git a/Mohem/src/imgs/profile1.png b/Mohem/src/imgs/profile1.png new file mode 100644 index 00000000..4cdd64a0 Binary files /dev/null and b/Mohem/src/imgs/profile1.png differ diff --git a/Mohem/src/imgs/signout.png b/Mohem/src/imgs/signout.png new file mode 100644 index 00000000..30d747d4 Binary files /dev/null and b/Mohem/src/imgs/signout.png differ diff --git a/Mohem/src/imgs/username.png b/Mohem/src/imgs/username.png new file mode 100644 index 00000000..24f8dc7a Binary files /dev/null and b/Mohem/src/imgs/username.png differ diff --git a/Mohem/src/imgs/vacationrule.png b/Mohem/src/imgs/vacationrule.png new file mode 100644 index 00000000..4626f84c Binary files /dev/null and b/Mohem/src/imgs/vacationrule.png differ diff --git a/Mohem/src/imgs/view.png b/Mohem/src/imgs/view.png new file mode 100644 index 00000000..ed946356 Binary files /dev/null and b/Mohem/src/imgs/view.png differ diff --git a/Mohem/src/index.html b/Mohem/src/index.html index d2eb084a..2150180d 100644 --- a/Mohem/src/index.html +++ b/Mohem/src/index.html @@ -12,7 +12,7 @@ - + diff --git a/Mohem/src/theme/common.scss b/Mohem/src/theme/common.scss new file mode 100644 index 00000000..1e29a128 --- /dev/null +++ b/Mohem/src/theme/common.scss @@ -0,0 +1,2 @@ +//All pages SCSS imported here +@import "./common/style.scss"; diff --git a/Mohem/src/theme/styles.scss b/Mohem/src/theme/styles.scss new file mode 100644 index 00000000..2d0a32a1 --- /dev/null +++ b/Mohem/src/theme/styles.scss @@ -0,0 +1,708 @@ + + +// $font-family-base: "WorkSans-Regular" !default; +body{ + :root[dir="rtl"]{ + font-family: var(--fontFamilyIOSAR) !important; + } + :root[dir="ltr"]{ + font-family: var(--fontFamilyMediumEN) !important; + } + } + input, textarea, p ,label,div{ + font-size: 16px; + :root[dir="rtl"]{ + font-family: var(--fontFamilyIOSAR) !important; + } + :root[dir="ltr"]{ + font-family: var(--fontFamilyLightEN) !important; + } + } + h1, h2,h3, button { + :root[dir="rtl"]{ + font-family: var(--fontFamilyIOSAR) !important; + } + :root[dir="ltr"]{ + font-family: var(--fontFamilyMediumEN) !important; +} + + } + + +.tipsPadding{ + padding: 0px 10px; +} +.profileDiv{ + margin: 5px auto !important; +} +.profileImg{ + width: 90px; + height: 90px; + display: inline-flex; + background: transparent; + -webkit-border-radius:50% !important; + -moz-border-radius:50% !important; + border-radius: 50% !important; + // margin:0 auto 40px; + img{ + -webkit-border-radius:50% !important; + -moz-border-radius:50% !important; + border-radius: 50% !important; + width: 90px; + height: 90px; + } + //box-shadow: 0px 0px 0px 10px #8c8c8c; + + +} +.loaderGif{ + background: transparent !important; + width:100px; + height: 100px; +} +.loading-md .loading-wrapper, +.loading-ios .loading-wrapper{ + background: transparent !important; + box-shadow: none; + -webkit-box-shadow:none; + -moz-box-shadow: none; + width: 150px; +} +.loading-md ,.loading-ios { + ion-backdrop{ + background-color: #8c8c8c !important; + } +} + +/***********change header color***************/ +.headerBtn{ + background-color: transparent; +} +.headerImg{ + width: 36px; +} + +/***************/ +.attachImg{ + max-width: 30px; + width: 30px; +} +img.attachImg { + max-width: 30px; + width: 30px; +} +.attachImgBtn{ + background-color: transparent; +} +.toolbar-title,.toolbar-title-md,.toolbar-title-ios{ + color:(--light); + font-size: 18px; +} +ion-header ion-icon.back-button-icon.icon { + color: (--light); + font-size: 25px; +} +ion-header ion-icon.icon.icon-ios.ion-ios-back{ + font-size: 25px; +} +ion-header ion-icon.icon.icon-md.ion-md-back, +ion-header ion-icon.icon.icon-md.ion-md-search, +ion-header ion-icon.icon.icon-ios.ion-ios-search{ + color: (--light); + font-size: 18px; +} + +button.disable-hover.item-button.button.button-md.button-clear.button-clear-md , +button.disable-hover.item-button.button.button-ios.button-clear.button-clear-ios{ + background: transparent; + font-size: 16px; + color:(--darkgray); +} +button.item-button.button.button-md.button-clear.button-clear-md, +button.item-button.button.button-ios.button-clear.button-clear-ios { + background: transparent; + font-size: 16px; + color:(--darkgray); +} +ion-header ion-icon.icon.icon-md.ion-md-close, +ion-header ion-icon.icon.icon-ios.ion-ios-close{ + color: (--light); +} +ion-header ion-icon.icon.icon-md.ion-md-add, +ion-header ion-icon.icon.icon-ios.ion-ios-add{ + color: (--light); +} + ion-icon.icon.icon-md.ion-md-search, + ion-icon.icon.icon-ios.ion-ios-search{ + color: (--darkgray); +} +.toolbar-background { + background: (--primary); + background: -moz-linear-gradient(45deg, (--primary) 0%, (--secondary) 36%,(--secondary) 59%, (--customnavy) 100%); + background: -webkit-linear-gradient(45deg, (--primary) 0%, (--secondary) 36%,(--secondary) 59%, (--customnavy) 100%); + background: linear-gradient(45deg, (--primary) 0%, (--secondary) 36%,(--secondary) 59%, (--customnavy) 100%); + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='var(--primary)', endColorstr='--var(customnavy)',GradientType=1 ); +} +/***************button bckground***************/ +a{ + color:var(--primary); +} +.button,.button-md, button-ios{ + background:(--customnavy); + white-space: normal; +// background: $primary; +// background: -moz-linear-gradient(45deg, $primary 0%, $secondary 36%, $secondary 59%, $customnavy 100%); +// background: -webkit-linear-gradient(45deg, $primary 0%,$secondary 36%,$secondary 59%,$customnavy 100%); +// background: linear-gradient(45deg, $primary 0%,$secondary 36%,$secondary 59%,$customnavy 100%); +// filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='$primary', endColorstr='$customnavy',GradientType=1 ); +color:var(--light); +text-transform: capitalize; +min-width: 200px; +min-height: 45px; +} +.iconButton{ + min-width: auto; + min-height: auto; +} +/*********select style************/ +ion-item.item.item-block.item-md.item-select.ng-touched, +ion-item.item.item-block.item-ios.item-select.ng-touched, +ion-item.item.item-block.item-md.item-datetime.ng-touched, +ion-item.item.item-block.item-ios.item-datetime.ng-touched { + border-bottom: 2px solid var(--danger); +} + +ion-item.item.item-block.item-md.item-select.ng-touched.input-has-value.item-input-has-value, +ion-item.item.item-block.item-ios.item-select.ng-touched.input-has-value.item-input-has-value, +ion-item.item.item-block.item-md.item-datetime.ng-touched.input-has-value.item-input-has-value, +ion-item.item.item-block.item-ios.item-datetime.ng-touched.input-has-value.item-input-has-value { + border-bottom: 0px; +} +/********center element****************/ +.centerDiv{ + margin:auto; + text-align: center; + display: block; + .button,.button-md, button-ios{ + min-width: 200px; + } + .iconButton{ + min-width: auto; + min-height: auto; + } +} +/***********item icon************/ +.item-icon{ + width:25px; + height:25px; +} +/**********text format**********/ +p.text-caps{ + text-transform: uppercase; +} +.boldTxt,p.boldTxt,.boldTxt>label { + :root[dir="ltr"]{ + font-family: var(--fontFamilyBoldEN) !important; + } + :root[dir="rtl"]{ + font-family: var(--fontFamilyIOSAR) !important; + font-weight: bold; + } +} +.boldTxtNav,p.boldTxtNav,.boldTxtNav>label { + color: var(--customnavy); + :root[dir="ltr"]{ + font-family: var(--fontFamilyBoldEN) !important; + } + :root[dir="rtl"]{ + font-family: var(--fontFamilyIOSAR) !important; + font-weight: bold; + } +} +ion-label.boldTxtNav.label.label-md,ion-label.boldTxtNav.label.label-ios{ + // font-weight: bold; + color:var(--customnavy); + :root[dir="ltr"]{ + font-family: var(--fontFamilySemiBoldEN) !important; + } + :root[dir="rtl"]{ + font-family: var(--fontFamilyIOSAR) !important; + font-weight: bold; + } + +} +/******* label stacked***********/ +.label-md[stacked], .label-ios[stacked] { +font-size: 16px; +} +/**********input **************/ +input.text-input.text-input-md, +input.text-input.text-input-ios{ + font-size: 16px; + :root[dir="ltr"]{ + text-align: left; + } + :root[dir="rtl"]{ + text-align: right; + } +} +ion-datetime.datetime.datetime-md.ng-valid.ng-dirty.ng-touched, +ion-datetime.datetime.datetime-ios.ng-valid.ng-dirty.ng-touched { + direction: ltr !important; + text-align: left !important; +} +/**********background************/ +.gray-bg{ + background-color:var(--gray); + margin-top: 10px; +} +/***************select and alert ************/ +.alert-md .alert-head,.alert-ios .alert-head{ + background-color:var(--grayBG); + color: var(--light); +} +/********profile grid************/ +// .profile-grid{ +// .col{ +// text-align: center; +// } +// } +/**********card**********/ +ion-card ,ion-card-md ,ion-card-ios { + box-shadow: black; + // background-color: #99999938; + -webkit-border-top-left-radius: 10px !important; + -webkit-border-top-right-radius: 10px !important; + -moz-border-radius-topleft: 10px !important; + -moz-border-radius-topright: 10px !important; + border-top-left-radius: 10px !important; + border-top-right-radius: 10px !important; + +} +ion-card-header{ + padding: 0px 10px !important; + color: var(--light) !important; + -webkit-border-top-left-radius: 10px; + -webkit-border-top-right-radius: 10px; + -moz-border-radius-topleft: 10px; + -moz-border-radius-topright: 10px; + border-top-left-radius: 10px; + border-top-right-radius: 10px; + background: var(--grayBG); + .hrTitle{ + white-space: normal; + padding: 5px; + padding-top: 12px; + width:85%; + min-height: 45px; + @media screen and (max-width: var(--break-big)) { + width: 80%; + } + @media screen and (max-width: var(--break-small)) { + width: 74%; + } + + :root[dir="ltr"]{ + float:left; + } + :root[dir="rtl"]{ + float:right; + } + line-height: 1.2; + } + .button,.button-md, button-ios{ + background: transparent; + box-shadow: none; + -webkit-box-shadow:none; + -moz-box-shadow: none; + min-width: auto; + padding: 0px !important; + margin:0px 5px !important; + :root[dir="ltr"]{ + float:right; + } + :root[dir="rtl"]{ + float:left; + } + } +} +ion-col.colBold,ion-col.colBold>label{ + // font-weight: bold; + color:var(--customnavy); + :root[dir="ltr"]{ + font-family: var(--fontFamilyBoldEN) !important; + } + :root[dir="rtl"]{ + font-family: var(--fontFamilyIOSAR) !important; + font-weight: bold; + } + font-size: 15px; +} +// .boldTxt{ +// font-weight: bold; +// } +// p.boldTxt{ +// font-weight: bold; +// } +/**********button grid***********/ +// .gridBtn{ + +// height: auto; +// min-height: 35px !important; +// padding: 10px; +// font-size: 12px; +// white-space: normal; +// } +// button.gridBtn.button.button-md, +// button.gridBtn.button.button-ios, +// button.gridBtn.button.button +// { +// width: 90%; +// } +// .gridBtnCol{ +// text-align: center; +// } +// .btnGrid{ + +// padding:0px; +// } +/*****************dynamic form*******************/ +.daynamicForm-Label{ + font-size: 16px; + // margin-left: 15px; + color: var(--customnavy); + display: block; + overflow: hidden; + -webkit-box-flex: 1; + -webkit-flex: 1; + -ms-flex: 1; + flex: 1; + /* font-size: inherit; */ + // text-overflow: ellipsis; + // white-space: nowrap; + white-space: normal; + // padding-top: 10px; + padding: 5px 0px; + margin: 10px auto; + :root[dir="ltr"]{ + font-family: var(--fontFamilySemiBoldEN) !important; + } + :root[dir="rtl"]{ + font-family: var(--fontFamilyIOSAR) !important; + font-weight: bold; + } + +} +img.flipImg{ + :root[dir="rtl"]{ + -webkit-transform: scaleX(-1); + transform: scaleX(-1); + } + } + +.daynamicForm-Input{ + width: 100%; + border: none; + border-bottom: var(--gray) solid 1px; + border-radius: 0px; + // margin-left: 10px; + // text-align: right; + color: var(--dark); + font-size: 15px; + padding: 6px 0px; + +} + + +.daynamicForm-Button{ + background:var(--customnavy); + white-space: normal; + // background: $primary; + // background: -moz-linear-gradient(45deg, $primary 0%, $secondary 36%, $secondary 59%, $customnavy 100%); + // background: -webkit-linear-gradient(45deg, $primary 0%,$secondary 36%,$secondary 59%,$customnavy 100%); + // background: linear-gradient(45deg, $primary 0%,$secondary 36%,$secondary 59%,$customnavy 100%); + // filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='$primary', endColorstr='$customnavy',GradientType=1 ); + color:var(--light); + text-transform: capitalize; + min-width: 200px; + min-height: 45px; + + + font-weight: 500; + + border: none; + border-radius: 2px; + -ms-flex: 1; + flex: 1; + font-size: 14px; + padding: 0 1.1em; + margin: 0.4rem 0.2rem; + justify-content: center; +} + +.custom-button-element{ + //margin-top: 10px; + margin: 10px auto; + text-align: center; +} +.daynamicForm-DateTime{ + color: var(--dark); + font-size: 15px; + border: none; + font-weight: 400; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + width: 100%; + padding: 6px 0px; + background: var(--light); + border-bottom: var(--cusgray) solid 1px; + border-radius: 0px; + -webkit-appearance: none; + -moz-appearance: none; + text-indent: 1px; + box-shadow: none; + -webkit-box-shadow:none; + -moz-box-shadow: none; +} +.daynamicForm-DateTime:after{ + width: 0; + height: 0; + border-left: 6px solid transparent; + border-right: 6px solid transparent; + border-top: 6px solid #999; + border-radius: 0px; + position: absolute; + top: 40%; + :root[dir="ltr"]{ + right: 5px; + } + :root[dir="rtl"]{ + left: 5px; + } + content: ""; + z-index: 98; + +} +.daynamicForm-Select{ + color: var(--dark); + font-size: 15px; + // background: url(http://i62.tinypic.com/15xvbd5.png) no-repeat 96% 0; + // background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiP…AgICAgPC9nPgogICAgICAgICAgICA8L2c+CiAgICAgICAgPC9nPgogICAgPC9nPgo8L3N2Zz4=), -webkit-gradient(linear, left bottom, left top, color-stop(50%, rgba(0, 0, 0, 0.12)), color-stop(50%, rgba(0, 0, 0, 0.12))); + // background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiP…AgICAgPC9nPgogICAgICAgICAgICA8L2c+CiAgICAgICAgPC9nPgogICAgPC9nPgo8L3N2Zz4=), linear-gradient(to top, rgba(0, 0, 0, 0.12) 50%, rgba(0, 0, 0, 0.12) 50%); + // background-size: 96% 0; + // background-repeat: no-repeat; + border: none; + font-weight: 400; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + width: 100%; + padding: 6px 0px; + background-color: var(--light); + border-bottom: var(--cusgray) solid 1px; + border-radius: 0px; + -webkit-appearance: none; + -moz-appearance: none; + text-indent: 1px; + // text-overflow: ''; + box-shadow: none; + -webkit-box-shadow:none; + -moz-box-shadow: none; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + + :root[dir="ltr"]{ + background-image: linear-gradient(45deg, transparent 50%, #999 50%), linear-gradient(135deg, #999 50%, transparent 50%), linear-gradient(to right, #ffffff, #ffffff); + background-position: calc(100% - 14px) calc(1em + 2px), calc(100% - 8px) calc(1em + 2px), 100% 0; + background-size: 6px 6px, 6px 6px, 2.9em 2.9em; + background-repeat: no-repeat; + padding-right: 20px; + } + :root[dir="rtl"]{ + background-image: linear-gradient(-135deg, #999 50%, transparent 50%),linear-gradient(-45deg, transparent 50%, #999 50%), linear-gradient(to right, #ffffff, #ffffff); + background-position: calc(1em - 10px) calc(100% - 8px), calc(1em - 4px) calc(100% - 8px), 0 100%; + background-size: 6px 6px, 6px 6px, 2.9em 2.9em; + background-repeat: no-repeat; + padding-left: 20px; + } +} + +.daynamicForm-Select:after{ + width: 0; + height: 0; + border-radius: 0px; + border-left: 6px solid transparent; + border-right: 6px solid transparent; + border-top: 6px solid #999; + position: absolute; + top: 40%; + :root[dir="ltr"]{ + right: 5px; + } + :root[dir="rtl"]{ + left: 5px; + } + content: ""; + z-index: 98; + +} +.requiredClass::before{ + content:"* "; +} +.requiredClassElm{ + border-bottom:2px solid var(--danger); +} + +textarea:disabled, input:disabled ,.daynamicForm-Select:disabled, .daynamicForm-DateTime:disabled{ + background: rgba(204, 204, 204, 0.11); +} +div.daynamicForm-DateTime.disabled{ + background: rgba(204, 204, 204, 0.11); +} + +.iconButton{ + + background: transparent; + -webkit-box-shadow:none; +-moz-box-shadow: none; +box-shadow: none; +} +.imgSize{ +width: 22px; +height: 22px; +-webkit-box-shadow:none; +-moz-box-shadow: none; +box-shadow: none; +} +/************footer****************/ +ion-footer { +padding:15px 0px; +background-color: var(--light) !important; +border: 0px !important; +box-shadow: none !important; +-webkit-box-shadow:none; +-moz-box-shadow: none; +} +.footer-md::before,.footer-ios::before{ + background-color: var(--light) !important; + background-image:none; + border: 0px !important; + box-shadow: none !important; + -webkit-box-shadow:none; +-moz-box-shadow: none; +} +/*************progress bar****************/ +.progcontainer { + margin: auto; + text-align: center; + width: 100%; + min-height: 100px; +} +.cusprogressbar { + counter-reset: step; + padding: 0px; +} +.cusprogressbar li { + list-style-type: none; + width: 33.333%; + :root[dir="ltr"]{ + float: left; + } + :root[dir="rtl"]{ + float: right; + } + font-size: 12px; + position: relative; + text-align: center; + color: var(--darkgray); + :root[dir="ltr"]{ + font-family:var(--fontFamilySemiBoldEN); + } + :root[dir="rtl"]{ + font-family: var(--fontFamilyIOSAR); + font-weight: bold; + } +} +.cusprogressbar li:before { + width: 40px; + height: 40px; + content: counter(step); + color: var(--light); + counter-increment: step; + line-height: 40px; + border: 0px; + background-color: var(--grayBG); + display: block; + text-align: center; + margin: 0 auto 10px auto; + border-radius: 50%; +} +.cusprogressbar li:after { + width: 100%; + height: 2px; + content: ''; + position: absolute; + background-color: var(--cusgray); + top: 20px; + :root[dir="ltr"]{ + left: -50%; + } + :root[dir="rtl"]{ + right: -50%; + } + + z-index: -1; +} +.cusprogressbar li:first-child:after { + content: none; +} +.cusprogressbar li.active { + color: var(--custgreen); +} +.cusprogressbar li.active:before { + background-color: var(--custgreen); +} +//.cusprogressbar li.active + li:after { + // background-color: #55b776; + //color: $custgreen; +//} +/**************badge **********************/ +.badge-md,.badge-ios { + color: #fff; + background-color: #327eff; + background: red; + border-radius: 50% !important; + min-width: 30px; + min-height: 30px; + line-height: 2; +} +/**********no data div***********/ +div.no-dataDiv{ +.row { + border-bottom: 1px solid; + border-color:var(--cusgray); + } +h4 { +font-size: 2.2rem; +text-align: center; +color: var(--dark); + +} +.empty-data { + font-size: 10.2em; + display: block; + margin: .2em auto 0; + color: var(--custgreen); + } +} + +.toast-md .toast-message,.toast-ios .toast-message { + background-color: var(--secondary); +} +/*************picker style*********************/ + .picker-md .picker-opt,.picker-ios .picker-opt{ + font-size: 18px; + } + .picker-md .picker-col,.picker-ios .picker-col { + padding: 0px 2px !important; +} diff --git a/Mohem/src/theme/variables.scss b/Mohem/src/theme/variables.scss index 4b39b39f..9cf23aec 100644 --- a/Mohem/src/theme/variables.scss +++ b/Mohem/src/theme/variables.scss @@ -1,77 +1,123 @@ -// Ionic Variables and Theming. For more info, please see: -// http://ionicframework.com/docs/theming/ +@font-face { + font-family: WorkSans-Light; + src: url('../assets/font/WorkSans-Light.otf'); +} +@font-face { + font-family: GE_SS_TWO_MEDIUM; + src: url('../assets/font/GE_SS_TWO_MEDIUM.otf'); +} +@font-face { + font-family: WorkSans-Medium; + src: url('../assets/font/WorkSans-Medium.otf'); +} +@font-face { + font-family: GE_SS_Two_Light; + src: url('../assets/font/GE_SS_Two_Light.otf'); +} +@font-face { + font-family: WorkSans-Regular; + src: url('../assets/font/WorkSans-Regular.otf'); +} +@font-face { + font-family: GE_SS_Two_Bold; + src: url('../assets/font/GE_SS_Two_Bold.otf'); +} +@font-face { + font-family: WorkSans-SemiBold; + src: url('../assets/font/WorkSans-SemiBold.otf'); +} +@font-face { + font-family: GE_SS_Two_Bold; + src: url('../assets/font/GE_SS_Two_Bold.otf'); +} +@font-face { + font-family: WorkSans-Bold; + src: url('../assets/font/WorkSans-Bold.otf'); +} -/** Ionic CSS Variables **/ :root { - /** primary **/ - --ion-color-primary: #3880ff; - --ion-color-primary-rgb: 56, 128, 255; - --ion-color-primary-contrast: #ffffff; - --ion-color-primary-contrast-rgb: 255, 255, 255; - --ion-color-primary-shade: #3171e0; - --ion-color-primary-tint: #4c8dff; - - /** secondary **/ - --ion-color-secondary: #0cd1e8; - --ion-color-secondary-rgb: 12, 209, 232; - --ion-color-secondary-contrast: #ffffff; - --ion-color-secondary-contrast-rgb: 255, 255, 255; - --ion-color-secondary-shade: #0bb8cc; - --ion-color-secondary-tint: #24d6ea; - - /** tertiary **/ - --ion-color-tertiary: #7044ff; - --ion-color-tertiary-rgb: 112, 68, 255; - --ion-color-tertiary-contrast: #ffffff; - --ion-color-tertiary-contrast-rgb: 255, 255, 255; - --ion-color-tertiary-shade: #633ce0; - --ion-color-tertiary-tint: #7e57ff; - - /** success **/ - --ion-color-success: #10dc60; - --ion-color-success-rgb: 16, 220, 96; - --ion-color-success-contrast: #ffffff; - --ion-color-success-contrast-rgb: 255, 255, 255; - --ion-color-success-shade: #0ec254; - --ion-color-success-tint: #28e070; +$break-small: 450px; +$break-big:565px; +//$break-large: 1200px; +$fontFamilyLightEN:'WorkSans-Light'; +$fontFamilyLightAR:'GE_SS_Two_Light'; +$fontFamilyRegularEN:'WorkSans-Regular'; +$fontFamilyRegularAR:'GE_SS_TWO_MEDIUM'; +$fontFamilyMediumEN:'WorkSans-Regular'; +$fontFamilyMediumAR:'GE_SS_TWO_MEDIUM'; +$fontFamilyBoldEN:'WorkSans-Bold'; +$fontFamilyBoldAR:'GE_SS_Two_Bold'; +$fontFamilySemiBoldEN:'WorkSans-SemiBold'; +$fontFamilySemiBoldAR:'GE_SS_Two_Bold'; +$fontFamilyIOSAR:-apple-system, "Helvetica Neue", "Roboto", sans-serif; +$fontFamilyAndroidAR:"Roboto", "Helvetica Neue", sans-serif; + $primary: #3ac1f1; + $secondary: #19a163; + $danger: #f53d3d; + $customnavy: #1a586d; + $light: #ffffff; + $dark: #000000; + $gray: #e4e5e7; + $custgreen: #209a83; + $cusgray:#d9d9d9; + $darkgray:#7F8C8D; + $grayBG:#acacac; - /** warning **/ - --ion-color-warning: #ffce00; - --ion-color-warning-rgb: 255, 206, 0; - --ion-color-warning-contrast: #ffffff; - --ion-color-warning-contrast-rgb: 255, 255, 255; - --ion-color-warning-shade: #e0b500; - --ion-color-warning-tint: #ffd31a; + $font-family-base: $fontFamilyMediumEN !default; + $font-family-ios-base: $fontFamilyMediumEN !default; + $font-family-md-base:$fontFamilyMediumEN !default; - /** danger **/ - --ion-color-danger: #f04141; - --ion-color-danger-rgb: 245, 61, 61; - --ion-color-danger-contrast: #ffffff; - --ion-color-danger-contrast-rgb: 255, 255, 255; - --ion-color-danger-shade: #d33939; - --ion-color-danger-tint: #f25454; + // ion-app.ios { + // font-family: -apple-system, "Helvetica Neue", "Roboto", sans-serif; + // font-size: 1.4rem; + // background-color: #fff; + // } + + // ion-app.md { + // font-family: "Roboto", "Helvetica Neue", sans-serif; + // font-size: 1.4rem; + // background-color: #fff; + // } - /** dark **/ - --ion-color-dark: #222428; - --ion-color-dark-rgb: 34, 34, 34; - --ion-color-dark-contrast: #ffffff; - --ion-color-dark-contrast-rgb: 255, 255, 255; - --ion-color-dark-shade: #1e2023; - --ion-color-dark-tint: #383a3e; - - /** medium **/ - --ion-color-medium: #989aa2; - --ion-color-medium-rgb: 152, 154, 162; - --ion-color-medium-contrast: #ffffff; - --ion-color-medium-contrast-rgb: 255, 255, 255; - --ion-color-medium-shade: #86888f; - --ion-color-medium-tint: #a2a4ab; - - /** light **/ - --ion-color-light: #f4f5f8; - --ion-color-light-rgb: 244, 244, 244; - --ion-color-light-contrast: #000000; - --ion-color-light-contrast-rgb: 0, 0, 0; - --ion-color-light-shade: #d7d8da; - --ion-color-light-tint: #f5f6f9; -} + $text-input-md-highlight-color:$primary; + $text-input-ios-highlight-color:$primary; + + $label-md-text-color-focused:$primary; + $label-ios-text-color-focused:$primary; + + $alert-md-button-text-color:$primary; + $alert-ios-button-text-color:$primary; + + $alert-md-input-border-color-focused:$primary; + $alert-ios-checkbox-background-color-on:$primary; + $alert-ios-checkbox-border-color-on:$primary; + + $checkbox-md-icon-background-color-on:$primary; + $checkbox-ios-background-color-on:$primary; + $checkbox-md-icon-border-color-on:$primary; + + $toggle-ios-background-color-on:$primary; + $toggle-md-active-color:$primary; + + $radio-md-color-on:$primary; + $radio-ios-color-on:$primary; + + $button-ios-background-color:$primary; + + $picker-md-button-text-color:$primary; + $picker-md-option-selected-color:$primary; + $picker-ios-button-text-color:$primary; + + $range-md-bar-active-background-color:$primary; + $range-ios-bar-active-background-color:$primary; + $text-input-ios-highlight-color:$primary; + + + $loading-md-spinner-color:$primary; + + + $text-input-highlight-color-invalid:$danger; + $text-input-ios-highlight-color-invalid:$danger; + $text-input-md-highlight-color-invalid:$danger; + $text-input-ios-show-focus-highlight: true; + } \ No newline at end of file