+
+
+
+ {{ field.templateOptions?.label | translate }}
+
+ *
+
+
+
+
+
+
+
+ {{ validation.message | translate }}
+
+
+
+
+
+
+
+ {{field.asyncValidation.trigger}}
+
-
-
-
-
- {{ formElement.templateOptions?.label | translate }}
-
-
- {{selectElement?.label}}
-
-
-
-
-
+
+
+
+
+
-
+
-
- {{ formElement.templateOptions?.label | translate}}
+
+ {{ field.templateOptions?.label | translate}}
-
-
+
+
-
- {{formElement.templateOptions?.label | translate}}
+
+ {{field.templateOptions?.label | translate}}
-
-
+
+
+
+
+
diff --git a/src/app/components/common-forms/common-forms.component.scss b/src/app/components/common-forms/common-forms.component.scss
index b0571c0d2c..321eaf3dae 100644
--- a/src/app/components/common-forms/common-forms.component.scss
+++ b/src/app/components/common-forms/common-forms.component.scss
@@ -78,7 +78,6 @@
.item-label-stacked ion-input {
border-radius: 5px;
- margin-top: 16px;
padding-left: 16px !important;
padding-right: 16px !important;
font-size: 14px;
@@ -86,11 +85,11 @@
.cf-input-primary ion-input{
font-weight: bold;
- border: 1px solid map-get($colors, primary);
+ border: none;
--placeholder-opacity: 0.3 !important;
}
- .cf-input-error ion-input{
+ .cf-input-error{
border: 1px solid red;
}
@@ -186,4 +185,47 @@ ion-checkbox {
margin-right: 8px;
--background-checked: #{$blue} !important;
--border-color-checked: #{$blue} !important;
+}
+
+.merged-input-container {
+ border: 1px solid map-get($colors, primary);
+ display: flex;
+ flex: 1 1 auto;
+ border-radius: 6px;
+ .decorator {
+ display: inline-block;
+ max-width: 50px;
+ }
+ .custom {
+ display: inline-block;
+ }
+ ion-input{
+ border: none;
+ }
+ span{
+ font-size: 14px;
+ opacity: 0.7;
+ margin: auto;
+ }
+
+}
+
+.verification-btn{
+ text-align: center;
+ ion-button {
+ --background: #008840 !important;
+ }
+}
+
+.otp-validator{
+ padding-left: 8px;
+ padding-right: 8px;
+}
+
+.prefix{
+ padding-left: 8px;;
+}
+
+.required-star{
+ color: red;
}
\ No newline at end of file
diff --git a/src/app/components/common-forms/common-forms.component.ts b/src/app/components/common-forms/common-forms.component.ts
index 54e693d6cf..b6aee0f41f 100644
--- a/src/app/components/common-forms/common-forms.component.ts
+++ b/src/app/components/common-forms/common-forms.component.ts
@@ -1,192 +1,241 @@
-import { Component, Input, OnInit, Output, Inject, EventEmitter } from '@angular/core';
-import { FormGroup, FormBuilder, Validators } from '@angular/forms';
-
+import {Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output, SimpleChanges, QueryList, ViewChildren, AfterViewInit} from '@angular/core';
+import { FieldConfig, FieldConfigInputType, FieldConfigValidationType, FieldConfigOption, FieldConfigOptionsBuilder } from './field-config';
+import {FormBuilder, FormGroup, Validators, FormControl} from '@angular/forms';
+import {Subject, Subscription, Observable} from 'rxjs';
+import {distinctUntilChanged, map, scan, tap} from 'rxjs/operators';
import { CommonUtilService } from '@app/services/common-util.service';
-import { SharedPreferences } from 'sunbird-sdk';
-
-enum InputType {
- INPUT = 'input',
- CHECKBOX = 'checkbox',
- SELECT = 'select',
- LABEL = 'label'
-}
-
-enum ValidationType {
- REQUIRED = 'required',
- PATTERN = 'pattern',
- MINLENGTH = 'minLength',
- MAXLENGTH = 'maxLength'
-}
+import { ValueComparator } from './value-comparator';
@Component({
selector: 'app-common-forms',
templateUrl: './common-forms.component.html',
styleUrls: ['./common-forms.component.scss'],
})
-export class CommonFormsComponent implements OnInit {
-
-// template
-// value
-// value changes
-// submit
-// reset
-
- @Input() formList: any = [];
- @Output() onFormDataChange = new EventEmitter();
- @Output() onCommonFormInitialized = new EventEmitter()
-
- commonFormGroup: FormGroup;
- formInputTypes = InputType;
- formValidationTypes = ValidationType;
- appName = '';
-
+export class CommonFormsComponent implements OnInit, OnChanges, OnDestroy, AfterViewInit {
+ @Output() initialize = new EventEmitter();
+ @Output() finalize = new EventEmitter();
+ @Output() valueChanges = new EventEmitter();
+ @Output() statusChanges = new EventEmitter();
+ @Output() dataLoadStatus = new EventEmitter<'LOADING' | 'LOADED'>();
+ @Input() config;
+ @Input() dataLoadStatusDelegate = new Subject<'LOADING' | 'LOADED'>();
+ @ViewChildren('validationTrigger') validationTriggers: QueryList
;
+
+ formGroup: FormGroup;
+ FieldConfigInputType = FieldConfigInputType;
+ ValueComparator = ValueComparator;
+ optionsMap$: {[code: string]: Observable[]>} = {};
+ requiredFieldsMap: {[code: string]: boolean} = {};
+
+ private statusChangesSubscription: Subscription;
+ private valueChangesSubscription: Subscription;
+ private dataLoadStatusSinkSubscription: Subscription;
constructor(
- @Inject('SHARED_PREFERENCES') private sharedPreferences: SharedPreferences,
private formBuilder: FormBuilder,
- private commonUtilService: CommonUtilService,
- ) { }
+ private commonUtilService: CommonUtilService
+ ) {
+ if (!window['forms']) {
+ window['forms'] = [];
+ }
+ window['forms'].push(this);
+ }
+ ngOnDestroy(): void {
+ this.finalize.emit();
+ if (this.statusChangesSubscription) {
+ this.statusChangesSubscription.unsubscribe();
+ }
+ if (this.valueChangesSubscription) {
+ this.valueChangesSubscription.unsubscribe();
+ }
+ if (this.dataLoadStatusSinkSubscription) {
+ this.dataLoadStatusSinkSubscription.unsubscribe();
+ }
+ }
+ ngOnInit() {
+ }
+ ngOnChanges(changes: SimpleChanges): void {
+ if (changes['config']) {
+ if ((changes['config'].currentValue && changes['config'].firstChange) || changes['config'].previousValue !== changes['config'].currentValue) {
+ this.initializeForm();
+
+ changes['config'].currentValue.forEach((config: FieldConfig) => {
+ if (config.validations && config.validations.length) {
+ this.requiredFieldsMap[config.code] = !!config.validations.find(val => val.type === FieldConfigValidationType.REQUIRED);
+ }
+ if (!config.templateOptions) {
+ return;
+ }
+ if (!config.templateOptions.options) {
+ config.templateOptions.options = [];
+ }
+ if (this.isOptionsClosure(config.templateOptions.options)) {
+ this.optionsMap$[config.code] = (config.templateOptions.options as FieldConfigOptionsBuilder)(
+ this.formGroup.get(config.code) as FormControl,
+ this.formGroup.get(config.context) as FormControl,
+ () => this.dataLoadStatusDelegate.next('LOADING'),
+ () => this.dataLoadStatusDelegate.next('LOADED')
+ ) as any;
+ }
+ });
+ }
+ }
+ if (this.dataLoadStatusSinkSubscription) {
+ this.dataLoadStatusSinkSubscription.unsubscribe();
+ }
+ if (this.statusChangesSubscription) {
+ this.statusChangesSubscription.unsubscribe();
+ }
+ if (this.valueChangesSubscription) {
+ this.valueChangesSubscription.unsubscribe();
+ }
+ this.dataLoadStatusSinkSubscription = this.dataLoadStatusDelegate.pipe(
+ scan<'LOADING' | 'LOADED', { loadingCount: 0, loadedCount: 0 }>((acc, event) => {
+ if (event === 'LOADED') {
+ acc.loadedCount++;
+ return acc;
+ }
+ acc.loadingCount++;
+ return acc;
+ }, {loadingCount: 0, loadedCount: 0}),
+ map<{ loadingCount: 0, loadedCount: 0 }, 'LOADING' | 'LOADED'>((aggregates) => {
+ if (aggregates.loadingCount !== aggregates.loadedCount) {
+ return 'LOADING';
+ }
+ return 'LOADED';
+ }),
+ distinctUntilChanged(),
+ tap((result) => {
+ if (result === 'LOADING') {
+ this.dataLoadStatus.emit('LOADING');
+ } else {
+ this.dataLoadStatus.emit('LOADED');
+ }
+ })
+ ).subscribe();
+ this.statusChangesSubscription = this.formGroup.valueChanges.pipe(
+ tap((v) => {
+ this.statusChanges.emit({
+ isPristine: this.formGroup.pristine,
+ isDirty: this.formGroup.dirty,
+ isInvalid: this.formGroup.invalid,
+ isValid: this.formGroup.valid
+ });
+ })
+ ).subscribe();
+ this.valueChangesSubscription = this.formGroup.valueChanges.pipe(
+ tap((v) => {
+ this.valueChanges.emit(v);
+ })
+ ).subscribe();
+ }
- ngOnInit(): void {
- this.initilizeForm();
- this.sharedPreferences.getString('app_name').toPromise().then(value => {
- this.appName = value;
+ ngAfterViewInit() {
+ this.config.forEach(element => {
+ if ( element.asyncValidation && element.asyncValidation.asyncValidatorFactory && this.formGroup.get(element.code)) {
+ this.formGroup.get(element.code).setAsyncValidators(element.asyncValidation.asyncValidatorFactory(
+ element.asyncValidation.marker,
+ this.validationTriggers
+ ));
+ }
});
}
- initilizeForm() {
- if (!this.formList.length) {
+ onNestedFormFinalize(nestedFormGroup: FormGroup, fieldConfig: FieldConfig) {
+ if (!this.formGroup.get('children') || !this.formGroup.get(`children.${fieldConfig.code}`)) {
+ return;
+ }
+ (this.formGroup.get('children') as FormGroup).removeControl(fieldConfig.code);
+ if (!Object.keys((this.formGroup.get('children') as FormGroup).controls).length) {
+ this.formGroup.removeControl('children');
+ }
+ }
+ onNestedFormInitialize(nestedFormGroup: FormGroup, fieldConfig: FieldConfig) {
+ if (!this.formGroup.get('children')) {
+ this.formGroup.addControl('children', new FormGroup({}));
+ }
+ (this.formGroup.get('children') as FormGroup).addControl(fieldConfig.code, nestedFormGroup);
+ }
+ private initializeForm() {
+ if (!this.config.length) {
console.error('FORM LIST IS EMPTY');
return;
}
const formGroupData = {};
- this.formList.forEach((element: any, index) => {
- if (element.type !== this.formInputTypes.LABEL) {
+ this.config.forEach((element: any, index) => {
+ if (element.type !== FieldConfigInputType.LABEL) {
const formValueList = this.prepareFormValidationData(element, index);
formGroupData[element.code] = formValueList;
}
});
-
- this.commonFormGroup = this.formBuilder.group(formGroupData);
- setTimeout(() => {
- this.onCommonFormInitialized.emit(true);
- }, 100);
+ this.formGroup = this.formBuilder.group(formGroupData);
+ this.initialize.emit(this.formGroup);
}
-
- /**
- * @return [''/0/[]/false, Validator.required]
- */
- private prepareFormValidationData(element, index) {
+ private prepareFormValidationData(element: FieldConfig, index) {
const formValueList = [];
const validationList = [];
-
let defaultVal: any = '';
switch (element.type) {
- case this.formInputTypes.INPUT:
- defaultVal = element.templateOptions.type === 'number' ? 0 : '';
+ case FieldConfigInputType.INPUT:
+ defaultVal = element.templateOptions.type === 'number' ?
+ (element.default && Number.isInteger(element.default) ? element.default : 0) :
+ (element.default && (typeof element.default) === 'string' ? element.default : '');
break;
- case this.formInputTypes.SELECT:
- defaultVal = element.templateOptions.multiple ? [] : '';
+ case FieldConfigInputType.SELECT:
+ case FieldConfigInputType.NESTED_SELECT:
+ defaultVal = element.templateOptions.multiple ?
+ (element.default && Array.isArray(element.default) ? element.default : []) : (element.default || null);
break;
- case this.formInputTypes.CHECKBOX:
- defaultVal = false;
+ case FieldConfigInputType.CHECKBOX:
+ defaultVal = false || !!element.default;
break;
}
formValueList.push(defaultVal);
-
if (element.validations && element.validations.length) {
element.validations.forEach((data, i) => {
switch (data.type) {
- case this.formValidationTypes.REQUIRED:
- validationList.push(element.type === this.formInputTypes.CHECKBOX ? Validators.requiredTrue : Validators.required);
- if (this.formList[index].templateOptions && this.formList[index].templateOptions.label) {
- this.formList[index].templateOptions.label =
- this.commonUtilService.translateMessage(this.formList[index].templateOptions.label) + ' *';
+ case FieldConfigValidationType.REQUIRED:
+ if (element.type === FieldConfigInputType.CHECKBOX) {
+ validationList.push(Validators.requiredTrue);
+ } else if (element.type === FieldConfigInputType.SELECT || element.type === FieldConfigInputType.NESTED_SELECT) {
+ validationList.push((c) => {
+ if (element.templateOptions.multiple) {
+ return c.value && c.value.length ? null : 'error';
+ }
+ return !!c.value ? null : 'error';
+ });
+ } else {
+ validationList.push(Validators.required);
}
break;
- case this.formValidationTypes.PATTERN:
- validationList.push(Validators.pattern(element.validations[i].value));
+ case FieldConfigValidationType.PATTERN:
+ validationList.push(Validators.pattern(element.validations[i].value as string));
break;
- case this.formValidationTypes.MINLENGTH:
- validationList.push(Validators.minLength(element.validations[i].value));
+ case FieldConfigValidationType.MINLENGTH:
+ validationList.push(Validators.minLength(element.validations[i].value as number));
break;
- case this.formValidationTypes.MAXLENGTH:
- validationList.push(Validators.maxLength(element.validations[i].value));
+ case FieldConfigValidationType.MAXLENGTH:
+ validationList.push(Validators.maxLength(element.validations[i].value as number));
break;
}
});
}
-
formValueList.push(Validators.compose(validationList));
-
return formValueList;
}
- fetchInterfaceOption(fieldName) {
- return {
- header: this.commonUtilService.translateMessage(fieldName).toLocaleUpperCase(),
- cssClass: 'select-box',
- animated: false
- };
- }
-
- onInputChange(event) {
- setTimeout(() => {
- this.onFormDataChange.emit(this.commonFormGroup);
- }, 0);
+ isOptionsArray(options: any) {
+ return Array.isArray(options);
}
- initilizeInputData(data) {
- this.commonFormGroup.patchValue({[data.code]: data.value});
+ isOptionsClosure(options: any) {
+ return typeof options === 'function';
}
- initilizeFormData(data) {
- for (let index = 0; index < this.formList.length; index++) {
- const formDetails = this.formList[index];
- if (formDetails.code === data.code && formDetails.templateOptions && formDetails.templateOptions.link &&
- formDetails.templateOptions.link.label) {
- this.setFormData(index, data.path, data.value);
- }
-
- if (formDetails.code === data.code && formDetails.templateOptions && formDetails.templateOptions.options) {
- this.setFormData(index, data.path, data.value);
- }
- }
- }
-
- setFormData(index, path, value) {
- path.reduce((a, b, level) => {
- if (typeof a[b] === 'undefined' && level !== path.length - 1) {
- a[b] = {};
- return a[b];
- }
- if (level === path.length - 1) {
- a[b] = value;
- return value;
- }
- return a[b];
- }, this.formList[index]);
- console.log(this.formList[index]);
-}
-
- showInAppBrowser(url) {
- this.commonUtilService.openLink(url);
- }
-
- handleClick(event: MouseEvent) {
+ handleLinkClick(event: MouseEvent) {
if (event.target && event.target['hasAttribute'] && (event.target as HTMLAnchorElement).hasAttribute('href')) {
this.commonUtilService.openLink((event.target as HTMLAnchorElement).getAttribute('href'));
}
}
- checkDisableCondition(formElement) {
- if (formElement.templateOptions && formElement.templateOptions.prefill && formElement.templateOptions.prefill.length) {
- for (let index = 0; index < formElement.templateOptions.prefill.length; index++) {
- if (!(this.commonFormGroup.value[formElement.templateOptions.prefill[index].code]).length) {
- return true;
- }
- }
- }
- return false;
- }
-
}
+
diff --git a/src/app/components/common-forms/field-config.ts b/src/app/components/common-forms/field-config.ts
new file mode 100644
index 0000000000..d1835e2f0a
--- /dev/null
+++ b/src/app/components/common-forms/field-config.ts
@@ -0,0 +1,66 @@
+import { Observable } from 'rxjs';
+import { FormControl, AsyncValidatorFn } from '@angular/forms';
+import { QueryList } from '@angular/core';
+
+export enum FieldConfigInputType {
+ INPUT = 'input',
+ CHECKBOX = 'checkbox',
+ SELECT = 'select',
+ LABEL = 'label',
+ NESTED_SELECT = 'nested_select',
+ NESTED_GROUP = 'nested_group'
+}
+
+export enum FieldConfigValidationType {
+ REQUIRED = 'required',
+ MAXLENGTH = 'maxLength',
+ MINLENGTH = 'minLength',
+ PATTERN = 'pattern'
+}
+
+export type FieldConfigOptionsBuilder =
+ (control: FormControl, context?: FormControl, notifyLoading?: () => void, notifyLoaded?: () => void) =>
+ Observable[]> | Promise[]>;
+
+export type AsyncValidatorFactory = (marker: string, triggers: QueryList) => AsyncValidatorFn;
+
+export interface FieldConfigOption {
+ label: string;
+ value: T;
+ extras?: T;
+}
+
+export interface FieldConfigOptionAssociations {
+ [key: string]: FieldConfigOption[];
+}
+
+export interface FieldConfig {
+ code: string;
+ type: FieldConfigInputType | string;
+ default?: any;
+ context?: string;
+ children?: FieldConfig[];
+ templateOptions: {
+ type?: string,
+ label?: string,
+ placeHolder?: string,
+ prefix?: string,
+ multiple?: boolean,
+ hidden?: boolean,
+ options?: FieldConfigOption[] | FieldConfigOptionsBuilder | FieldConfigOptionAssociations,
+ labelHtml?: {
+ contents: string,
+ values: {[key: string]: string}
+ }
+ };
+ validations?: {
+ type: FieldConfigValidationType | string,
+ value?: string | boolean | number | RegExp,
+ message?: string
+ }[];
+ asyncValidation?: {
+ marker: string,
+ trigger?: string,
+ asyncValidatorFactory?: AsyncValidatorFactory
+ };
+}
diff --git a/src/app/components/common-forms/value-comparator.ts b/src/app/components/common-forms/value-comparator.ts
new file mode 100644
index 0000000000..9ea0200462
--- /dev/null
+++ b/src/app/components/common-forms/value-comparator.ts
@@ -0,0 +1,67 @@
+export class ValueComparator {
+ static valueComparator(v1, v2): boolean {
+ if (typeof v1 === 'object' && typeof v2 === 'object') {
+ return ObjectUtil.equals(v1, v2);
+ } else if (v1 === v2) {
+ return true;
+ } else if (!v1 && !v2) {
+ return true;
+ }
+ return false;
+ }
+}
+class ObjectUtil {
+ public static equals(a: any, b: any): boolean {
+ const countProps = (obj) => {
+ let count = 0;
+ for (const k in obj) {
+ if (obj.hasOwnProperty(k)) {
+ count++;
+ }
+ }
+ return count;
+ };
+ const objectEquals = (v1: any, v2: any) => {
+ if (typeof (v1) !== typeof (v2)) {
+ return false;
+ }
+ if (typeof (v1) === 'function') {
+ return v1.toString() === v2.toString();
+ }
+ if (v1 instanceof Object && v2 instanceof Object) {
+ if (countProps(v1) !== countProps(v2)) {
+ return false;
+ }
+ let r = true;
+ for (const k in v1) {
+ r = objectEquals(v1[k], v2[k]);
+ if (!r) {
+ return false;
+ }
+ }
+ return true;
+ } else {
+ return v1 === v2;
+ }
+ };
+ return objectEquals(a, b);
+ }
+ public static getPropDiff(newObj: {}, oldObj: {}): string[] {
+ return Object.keys(newObj).reduce((acc: string[], key) => {
+ if (ObjectUtil.equals(newObj[key], oldObj[key])) {
+ return acc;
+ }
+ acc.push(key);
+ return acc;
+ }, []);
+ }
+ public static getTruthyProps(obj: {}): string[] {
+ return Object.keys(obj).filter((key) => !!obj[key]);
+ }
+ public static toOrderedString(obj: {}): string {
+ return JSON.stringify(Object.keys(obj).sort().reduce<{}>((acc, k) => {
+ acc[k] = obj[k];
+ return acc;
+ }, {}));
+ }
+}
diff --git a/src/app/components/popups/account-recovery-id/account-recovery-id-popup.component.scss b/src/app/components/popups/account-recovery-id/account-recovery-id-popup.component.scss
index a63b61133a..a69c0326ee 100644
--- a/src/app/components/popups/account-recovery-id/account-recovery-id-popup.component.scss
+++ b/src/app/components/popups/account-recovery-id/account-recovery-id-popup.component.scss
@@ -31,7 +31,7 @@
}
.ar-header {
- background-color: map-get($colors, primary);
+ background-color: #{$blue};
color: map-get($colors, white);
padding: 16px 0;
}
@@ -43,4 +43,17 @@
.custom-shadow {
box-shadow: 0 -5px 5px -5px rgba(0, 0, 0, 0.2);
+}
+
+ion-button{
+ --background: #{$blue} !important;
+ color: map-get($colors, white);
+ --background-hover: #{$blue} !important;
+ --background-activated: #{$blue} !important;
+}
+
+ion-button[fill="outline"]{
+ --background: map-get($colors, white) !important;
+ color: #{$blue};
+ --border-color: #{$blue};
}
\ No newline at end of file
diff --git a/src/app/components/popups/edit-contact-details-popup/edit-contact-details-popup.component.scss b/src/app/components/popups/edit-contact-details-popup/edit-contact-details-popup.component.scss
index f8dead0916..8680110bc7 100644
--- a/src/app/components/popups/edit-contact-details-popup/edit-contact-details-popup.component.scss
+++ b/src/app/components/popups/edit-contact-details-popup/edit-contact-details-popup.component.scss
@@ -76,8 +76,22 @@
}
.ecd-header {
- background-color: map-get($colors, primary);
+ background-color: #{$blue};
color: map-get($colors, white);
padding: 16px 0;
}
+
+ ion-button{
+ --background: #{$blue} !important;
+ color: map-get($colors, white);
+ --background-hover: #{$blue} !important;
+ --background-activated: #{$blue} !important;
+ }
+
+ ion-button[fill="outline"]{
+ --background: map-get($colors, white) !important;
+ color: #{$blue};
+ --border-color: #{$blue};
+ }
+
}
diff --git a/src/app/components/popups/edit-contact-verify-popup/edit-contact-verify-popup.component.html b/src/app/components/popups/edit-contact-verify-popup/edit-contact-verify-popup.component.html
index e2ef704936..357ff8eb4e 100644
--- a/src/app/components/popups/edit-contact-verify-popup/edit-contact-verify-popup.component.html
+++ b/src/app/components/popups/edit-contact-verify-popup/edit-contact-verify-popup.component.html
@@ -1,8 +1,10 @@
+
- {{title}}
{{description}}
diff --git a/src/app/components/popups/edit-contact-verify-popup/edit-contact-verify-popup.component.scss b/src/app/components/popups/edit-contact-verify-popup/edit-contact-verify-popup.component.scss
index 176d8097bd..c7f2a6cb61 100644
--- a/src/app/components/popups/edit-contact-verify-popup/edit-contact-verify-popup.component.scss
+++ b/src/app/components/popups/edit-contact-verify-popup/edit-contact-verify-popup.component.scss
@@ -11,5 +11,29 @@
max-width: 45px;
}
}
+
+ .ecv-header {
+ background-color: #{$blue};
+ color: map-get($colors, white);
+ padding: 16px 0;
+ }
+
+ ion-button{
+ --background: #{$blue} !important;
+ color: map-get($colors, white);
+ --background-hover: #{$blue} !important;
+ --background-activated: #{$blue} !important;
+ }
+
+ ion-button[fill="outline"]{
+ --background: map-get($colors, white) !important;
+ color: #{$blue};
+ --border-color: #{$blue};
+ }
+
+ ion-button[fill="clear"]{
+ --background: map-get($colors, white) !important;
+ color: #{$blue};
+ }
}
diff --git a/src/app/profile/profile.page.html b/src/app/profile/profile.page.html
index 5a281e88c4..6d2f5ec2e2 100644
--- a/src/app/profile/profile.page.html
+++ b/src/app/profile/profile.page.html
@@ -178,6 +178,16 @@
+
+
{{'STATE' | translate }}:
+
{{selfDeclaredTeacherDetails?.state}}
+
+
+
+
{{'DISTRICT' | translate }}:
+
{{selfDeclaredTeacherDetails?.district}}
+
+
{{'SCHOOL_OR_ORG_NAME' | translate }}
{{selfDeclaredTeacherDetails?.schoolName}}
diff --git a/src/app/profile/profile.page.ts b/src/app/profile/profile.page.ts
index a4d08d7ef6..7a71c95c89 100644
--- a/src/app/profile/profile.page.ts
+++ b/src/app/profile/profile.page.ts
@@ -6,7 +6,15 @@ import {
IonRefresher,
} from '@ionic/angular';
import { generateInteractTelemetry } from '@app/app/telemetryutil';
-import { ContentCard, ContentType, MimeType, ProfileConstants, RouterLinks, ContentFilterConfig } from '@app/app/app.constant';
+import {
+ ContentCard,
+ ContentType,
+ MimeType,
+ ProfileConstants,
+ RouterLinks,
+ ContentFilterConfig,
+ Location as loc
+} from '@app/app/app.constant';
import { FormAndFrameworkUtilService } from '@app/services/formandframeworkutil.service';
import { AppGlobalService } from '@app/services/app-global-service.service';
import { CommonUtilService } from '@app/services/common-util.service';
@@ -31,7 +39,8 @@ import {
CourseCertificate,
SharedPreferences,
CertificateAlreadyDownloaded,
- NetworkError
+ NetworkError,
+ LocationSearchCriteria
} from 'sunbird-sdk';
import { Environment, InteractSubtype, InteractType, PageId, ID } from '@app/services/telemetry-constants';
import { ActivatedRoute, Router, NavigationExtras } from '@angular/router';
@@ -102,6 +111,8 @@ export class ProfilePage implements OnInit {
mappedTrainingCertificates: CourseCertificate[] = [];
isDefaultChannelProfile$: Observable
;
selfDeclaredTeacherDetails: any;
+ private stateList: any;
+
constructor(
@Inject('PROFILE_SERVICE') private profileService: ProfileService,
@Inject('AUTH_SERVICE') private authService: AuthService,
@@ -163,6 +174,7 @@ export class ProfilePage implements OnInit {
}
});
this.appName = await this.appVersion.getAppName();
+ this.stateList = await this.commonUtilService.getStateList();
}
ionViewWillEnter() {
@@ -980,16 +992,29 @@ export class ProfilePage implements OnInit {
});
}
- getSelfDeclaredTeacherDetails() {
+ async getSelfDeclaredTeacherDetails() {
this.selfDeclaredTeacherDetails = {
+ state: '',
+ district: '',
schoolName: '',
udiseId: '',
teacherId: ''
};
if (this.isCustodianOrgId && this.profile && this.profile.externalIds) {
+ let stateCode = '';
+ let districtCode = '';
+ let stateDetails;
+ let districtDetails;
+
this.profile.externalIds.forEach(ele => {
switch (ele.idType) {
+ case 'declared-state':
+ stateCode = ele.id;
+ break;
+ case 'declared-district':
+ districtCode = ele.id;
+ break;
case 'declared-school-name':
this.selfDeclaredTeacherDetails.schoolName = ele.id;
break;
@@ -1001,7 +1026,18 @@ export class ProfilePage implements OnInit {
break;
}
});
+ if (stateCode && this.stateList && this.stateList.length) {
+ stateDetails = this.stateList.find(state => state.code === stateCode);
+ this.selfDeclaredTeacherDetails.state = (stateDetails && stateDetails.name) || '';
+ }
+ if (stateDetails && stateDetails.id) {
+ const districtList = await this.commonUtilService.getDistrictList(stateDetails.id);
+ districtDetails = districtList.find(district => district.code === districtCode);
+ this.selfDeclaredTeacherDetails.district = (districtDetails && districtDetails.name) || '';
+ }
}
}
+
+
}
diff --git a/src/app/profile/self-declared-teacher-edit/self-declared-teacher-edit.page.html b/src/app/profile/self-declared-teacher-edit/self-declared-teacher-edit.page.html
index d1a064dc67..2c71271aa6 100644
--- a/src/app/profile/self-declared-teacher-edit/self-declared-teacher-edit.page.html
+++ b/src/app/profile/self-declared-teacher-edit/self-declared-teacher-edit.page.html
@@ -2,9 +2,12 @@
{{'PLEASE_PROVIDE_FOLLOWING_DETAILS' | translate}}
{{'UPDATE_DETAILS' | translate}}
- {{'ADD_EDIT_SELF_DECLARED_TEACHER_INFO' | translate}}
-
+
+
diff --git a/src/app/profile/self-declared-teacher-edit/self-declared-teacher-edit.page.ts b/src/app/profile/self-declared-teacher-edit/self-declared-teacher-edit.page.ts
index 9e04d497eb..6ec2b6e9bc 100644
--- a/src/app/profile/self-declared-teacher-edit/self-declared-teacher-edit.page.ts
+++ b/src/app/profile/self-declared-teacher-edit/self-declared-teacher-edit.page.ts
@@ -1,17 +1,45 @@
-import {Component, Inject, NgZone, ViewChild} from '@angular/core';
+import {Component, Inject, ViewChild} from '@angular/core';
import {
- LocationSearchCriteria, ProfileService,
- SharedPreferences, Profile, LocationSearchResult, CachedItemRequestSourceFrom, FormRequest, FormService, FrameworkService
+ LocationSearchCriteria,
+ ProfileService,
+ SharedPreferences,
+ LocationSearchResult,
+ CachedItemRequestSourceFrom,
+ FormRequest,
+ FormService,
+ FrameworkService,
+ AuditState,
+ CorrelationData,
+ TelemetryObject,
+ ServerProfile
} from 'sunbird-sdk';
import { Location as loc, PreferenceKey } from '../../../app/app.constant';
-import { AppHeaderService, CommonUtilService, AppGlobalService, ID, TelemetryGeneratorService, InteractType, Environment, InteractSubtype, PageId, ImpressionType } from '@app/services';
+import {
+ AppHeaderService,
+ CommonUtilService,
+ AppGlobalService,
+ ID,
+ TelemetryGeneratorService,
+ InteractType,
+ Environment,
+ InteractSubtype,
+ PageId,
+ ImpressionType,
+ AuditType,
+ CorReleationDataType
+} from '@app/services';
import { Router, ActivatedRoute } from '@angular/router';
import { Location } from '@angular/common';
import { Events, PopoverController } from '@ionic/angular';
-import { Subscription } from 'rxjs';
+import { Subscription, of, defer } from 'rxjs';
import { Platform } from '@ionic/angular';
import { CommonFormsComponent } from '@app/app/components/common-forms/common-forms.component';
import { SbPopoverComponent } from '@app/app/components/popups/sb-popover/sb-popover.component';
+import { FieldConfig, FieldConfigOptionsBuilder, FieldConfigOption } from '@app/app/components/common-forms/field-config';
+import { FormValidationAsyncFactory } from '@app/services/form-validation-async-factory/form-validation-async-factory';
+import { AppVersion } from '@ionic-native/app-version/ngx';
+import { FormControl } from '@angular/forms';
+import { distinctUntilChanged, switchMap, tap } from 'rxjs/operators';
@Component({
selector: 'app-self-declared-teacher-edit',
@@ -21,18 +49,22 @@ import { SbPopoverComponent } from '@app/app/components/popups/sb-popover/sb-pop
export class SelfDeclaredTeacherEditPage {
private formValue: any;
- private profile: any;
+ private profile: ServerProfile;
private initialExternalIds: any;
private backButtonFunc: Subscription;
private availableLocationDistrict: string;
private availableLocationState: string;
+ private loader: any
+ private latestFormValue: any;
+ private latestFormStatus: any;
+ private selectedStateCode: any;
editType = 'add';
isFormValid = false;
stateList: LocationSearchResult[] = [];
districtList: LocationSearchResult[] = [];
- teacherDetailsForm = [];
- formInitilized = false;
+ teacherDetailsForm: FieldConfig[] = [];
+ appName = '';
@ViewChild('commonForms') commonForms: CommonFormsComponent;
@@ -45,13 +77,13 @@ export class SelfDeclaredTeacherEditPage {
private commonUtilService: CommonUtilService,
private router: Router,
private location: Location,
- private appGlobalService: AppGlobalService,
private events: Events,
private platform: Platform,
- private ngZone: NgZone,
private activatedRoute: ActivatedRoute,
private popoverCtrl: PopoverController,
private telemetryGeneratorService: TelemetryGeneratorService,
+ private formValidationAsyncFactory: FormValidationAsyncFactory,
+ private appVersion: AppVersion
) {
const navigation = this.router.getCurrentNavigation();
if (navigation && navigation.extras && navigation.extras.state) {
@@ -75,7 +107,8 @@ export class SelfDeclaredTeacherEditPage {
);
}
- ionViewDidEnter() {
+ async ionViewDidEnter() {
+ this.appName = await this.appVersion.getAppName();
this.getTeacherDetailsFormApi();
}
@@ -85,7 +118,7 @@ export class SelfDeclaredTeacherEditPage {
from: CachedItemRequestSourceFrom.SERVER,
type: 'user',
subType: 'teacherDetails',
- action: 'submit',
+ action: 'submit_v2',
rootOrgId: rootOrgId || '*',
component: 'app'
};
@@ -97,13 +130,9 @@ export class SelfDeclaredTeacherEditPage {
}
if (formData && formData.form && formData.form.data) {
- const data = formData.form.data.fields;
- if (data.length) {
- this.formInitilized = false;
- setTimeout(() => {
- this.teacherDetailsForm = data;
- this.formInitilized = true;
- }, 100);
+ const formConfig = formData.form.data.fields;
+ if (formConfig.length) {
+ this.initializeFormData(formConfig, !!rootOrgId);
}
}
@@ -117,49 +146,96 @@ export class SelfDeclaredTeacherEditPage {
});
}
- async onCommonFormInitialized(event) {
- this.initializeFormData();
- if (!this.stateList || !this.stateList.length) {
- await this.getStates();
- }
- }
+ async initializeFormData(formConfig, formLoaded) {
+
+ this.teacherDetailsForm = formConfig.map((config: FieldConfig) => {
+ if (config.code === 'externalIds' && config.children) {
+ config.children = config.children.map((childConfig: FieldConfig) => {
+
+ if (childConfig.templateOptions['dataSrc'] && childConfig.templateOptions['dataSrc'].marker === 'LOCATION_LIST') {
+ if (childConfig.templateOptions['dataSrc'].params.id === 'state') {
+ let stateCode;
+ if (this.selectedStateCode) {
+ stateCode = this.selectedStateCode;
+ } else {
+ let stateDetails;
+ if (this.profile.externalIds && this.profile.externalIds.length) {
+ stateDetails = this.profile.externalIds.find(eId => eId.idType === childConfig.code);
+ }
+ stateCode = stateDetails && stateDetails.id;
+ }
+ childConfig.templateOptions.options = this.buildStateListClosure(stateCode);
+ } else if (childConfig.templateOptions['dataSrc'].params.id === 'district') {
+ let districtDetails;
+ if (this.profile.externalIds && this.profile.externalIds.length) {
+ districtDetails = this.profile.externalIds.find(eId => eId.idType === childConfig.code);
+ }
+ childConfig.templateOptions.options = this.buildDistrictListClosure(districtDetails && districtDetails.id, formLoaded);
+ }
+ return childConfig;
+ }
- initializeFormData() {
- if (this.profile && this.profile.externalIds && this.profile.externalIds.length) {
- this.initialExternalIds = {};
- this.profile.externalIds.forEach((externalData) => {
- this.teacherDetailsForm.forEach((formData) => {
- this.initialExternalIds[formData.code] = {
- name: this.commonUtilService.translateMessage(formData.templateOptions.label) || '',
- value: (this.initialExternalIds[formData.code] && this.initialExternalIds[formData.code].value) ?
- this.initialExternalIds[formData.code].value : '',
- };
- if (formData.code === externalData.idType) {
- this.commonForms.commonFormGroup.patchValue({
- [formData.code]: externalData.id
- });
- this.initialExternalIds[formData.code] = {
- name: formData.templateOptions.label || '',
- value: externalData.id
- };
+ if (childConfig.asyncValidation) {
+ if (childConfig.asyncValidation.marker === 'MOBILE_OTP_VALIDATION') {
+ childConfig.asyncValidation.asyncValidatorFactory =
+ this.formValidationAsyncFactory.mobileVerificationAsyncFactory(childConfig, this.profile);
+ } else if (childConfig.asyncValidation.marker === 'EMAIL_OTP_VALIDATION') {
+ childConfig.asyncValidation.asyncValidatorFactory =
+ this.formValidationAsyncFactory.emailVerificationAsyncFactory(childConfig, this.profile);
+ }
+ childConfig = this.assignDefaultValue(childConfig, formLoaded);
+ return childConfig;
}
+
+ this.assignDefaultValue(childConfig, formLoaded);
+
+ return childConfig;
});
- });
+ return config;
+ }
+
+ if (config.code === 'tnc') {
+ if (this.editType === 'edit') {
+ return undefined;
+ }
+ if (config.templateOptions && config.templateOptions.labelHtml &&
+ config.templateOptions.labelHtml.contents) {
+ config.templateOptions.labelHtml.values['$url'] = this.profile.tncLatestVersionUrl;
+ config.templateOptions.labelHtml.values['$appName'] = ' ' + this.appName + ' ';
+ return config;
+ }
+ return config;
+ }
+ return config;
+ }).filter((formData) => formData);
+
+ }
+
+ private assignDefaultValue(childConfig: FieldConfig, formLoaded) {
+ if (formLoaded) {
+ return;
}
- if (this.stateList && this.stateList.length && this.formValue.state) {
- const formStateList = [];
- this.stateList.forEach(stateData => {
- formStateList.push({ label: stateData.name, value: stateData.id });
- });
- this.commonForms.initilizeFormData({ code: 'state', path: ['templateOptions', 'options'], value: formStateList });
- this.commonForms.commonFormGroup.patchValue({
- state: this.formValue.state
+ if (this.profile.externalIds && this.profile.externalIds.length) {
+ this.profile.externalIds.forEach(eId => {
+ if (childConfig.code === eId.idType) {
+ childConfig.default = eId.id;
+ }
});
- this.getDistrict(this.formValue.state);
}
+
+ if (this.editType === 'add') {
+ if (childConfig.code === 'declared-phone') {
+ childConfig.default = this.profile['maskedPhone'];
+ }
+
+ if (childConfig.code === 'declared-email') {
+ childConfig.default = this.profile['maskedEmail'];
+ }
+ }
+ return childConfig;
}
- async checkLocationAvailability() {
+ private async checkLocationAvailability() {
let stateId;
let availableLocationData;
if (this.profile && this.profile['userLocations'] && this.profile['userLocations'].length) {
@@ -195,88 +271,6 @@ export class SelfDeclaredTeacherEditPage {
}
}
- async getStates() {
- const loader = await this.commonUtilService.getLoader();
- await loader.present();
- const req: LocationSearchCriteria = {
- from: CachedItemRequestSourceFrom.SERVER,
- filters: {
- type: loc.TYPE_STATE
- }
- };
- this.profileService.searchLocation(req).subscribe(async (success) => {
- const locations = success;
- this.ngZone.run(async () => {
- if (locations && Object.keys(locations).length) {
- this.stateList = locations;
-
- const formStateList = [];
- this.stateList.forEach(stateData => {
- formStateList.push({ label: stateData.name, value: stateData.id });
- });
-
- this.commonForms.initilizeFormData({ code: 'state', path: ['templateOptions', 'options'], value: formStateList });
-
- if ((this.formValue && this.formValue.state) || this.availableLocationState) {
- const state = this.stateList.find(s => (s.id === (this.formValue && this.formValue.state) || s.name === this.availableLocationState));
- this.commonForms.initilizeInputData({ code: 'state', value: state.id });
- if (state) {
- await this.getDistrict(state.id);
- }
- }
- } else {
- this.districtList = [];
- this.commonUtilService.showToast('NO_DATA_FOUND');
- }
- await loader.dismiss();
- });
- }, async (error) => {
- await loader.dismiss();
- });
- }
-
- async getDistrict(pid: string) {
- const loader = await this.commonUtilService.getLoader();
- await loader.present();
- const req: LocationSearchCriteria = {
- from: CachedItemRequestSourceFrom.SERVER,
- filters: {
- type: loc.TYPE_DISTRICT,
- parentId: pid
- }
- };
- this.profileService.searchLocation(req).subscribe(async (success) => {
- this.ngZone.run(async () => {
- if (success && Object.keys(success).length) {
- this.districtList = success;
-
- const formDistrictList = [];
- this.districtList.forEach(districtData => {
- formDistrictList.push({ label: districtData.name, value: districtData.id });
- });
- this.commonForms.initilizeFormData({ code: 'district', path: ['templateOptions', 'options'], value: formDistrictList });
-
- if (this.availableLocationDistrict) {
- const district = this.districtList.find(d => d.name === this.availableLocationDistrict);
- if (district) {
- this.commonForms.initilizeInputData({ code: 'district', value: district.id });
- } else {
- this.commonForms.initilizeInputData({ code: 'district', value: '' });
- }
- }
- await loader.dismiss();
- } else {
- this.availableLocationDistrict = '';
- await loader.dismiss();
- this.districtList = [];
- this.commonUtilService.showToast('NO_DATA_FOUND');
- }
- });
- }, async (error) => {
- await loader.dismiss();
- });
- }
-
async submit() {
if (!this.commonUtilService.networkInfo.isNetworkAvailable) {
this.commonUtilService.showToast('NEED_INTERNET_TO_CHANGE');
@@ -289,68 +283,75 @@ export class SelfDeclaredTeacherEditPage {
let telemetryValue;
try {
- if (!this.commonForms && !this.commonForms.commonFormGroup && !this.commonForms.commonFormGroup.value) {
+ if (!this.latestFormValue) {
this.commonUtilService.showToast('SOMETHING_WENT_WRONG');
return;
}
- const formValue = this.commonForms.commonFormGroup.value;
- const orgDetails: any = await this.frameworkService.searchOrganization({ filters: { locationIds: [formValue.state] } }).toPromise();
+ const formValue = this.latestFormValue.children.externalIds;
+ const selectdState = this.getStateIdFromCode(formValue['declared-state']);
+ const orgDetails: any = await this.frameworkService.searchOrganization({
+ filters: {
+ locationIds: [selectdState && selectdState.id],
+ isRootOrg: true
+ }
+ }).toPromise();
if (!orgDetails || !orgDetails.content || !orgDetails.content.length || !orgDetails.content[0].channel) {
this.commonUtilService.showToast('SOMETHING_WENT_WRONG');
return;
}
+
const rootOrgId = orgDetails.content[0].channel;
await loader.present();
- const stateCode = this.stateList.find(state => state.id === formValue.state).code;
- const districtCode = this.districtList.find(district => district.id === formValue.district).code;
const externalIds = this.removeExternalIdsOnStateChange(rootOrgId);
- this.teacherDetailsForm.forEach(formData => {
- if (formData.code !== 'state' && formData.code !== 'district') {
- // no externalIds declared
- if (!this.profile.externalIds || !this.profile.externalIds.length || !this.profile.externalIds.find(eid => {
- return eid.idType === formData.code;
- })) {
- if (formValue[formData.code]) {
+ this.teacherDetailsForm.forEach(config => {
+ if (config.code === 'externalIds' && config.children) {
+ config.children.forEach(formData => {
+
+ // no externalIds declared
+ if (!this.profile.externalIds || !this.profile.externalIds.length || !this.profile.externalIds.find(eid => {
+ return eid.idType === formData.code;
+ })) {
+ if (formValue[formData.code]) {
+ externalIds.push({
+ id: formValue[formData.code],
+ operation: 'add',
+ idType: formData.code,
+ provider: rootOrgId
+ });
+ return;
+ }
+ }
+
+ // externalIds declared but removed
+ if (!formValue[formData.code] && this.profile.externalIds && this.profile.externalIds.find(eid => {
+ return eid.idType === formData.code;
+ })) {
externalIds.push({
- id: formValue[formData.code],
- operation: 'add',
+ id: 'remove',
+ operation: 'remove',
idType: formData.code,
provider: rootOrgId
});
return;
}
- }
- // externalIds declared but removed
- if (!formValue[formData.code] && this.profile.externalIds && this.profile.externalIds.find(eid => {
- return eid.idType === formData.code;
- })) {
- externalIds.push({
- id: 'remove',
- operation: 'remove',
- idType: formData.code,
- provider: rootOrgId
- });
- return;
- }
-
- // external id declared and modified
- if (formValue[formData.code]) {
- externalIds.push({
- id: formValue[formData.code],
- operation: 'edit',
- idType: formData.code,
- provider: rootOrgId
- });
- }
+ // external id declared and modified
+ if (formValue[formData.code]) {
+ externalIds.push({
+ id: formValue[formData.code],
+ operation: 'edit',
+ idType: formData.code,
+ provider: rootOrgId
+ });
+ }
+ });
}
});
const req = {
userId: this.profile.userId,
- locationCodes: [stateCode, districtCode],
externalIds
};
@@ -364,6 +365,7 @@ export class SelfDeclaredTeacherEditPage {
this.generateTelemetryInteract(InteractType.SUBMISSION_SUCCESS, ID.TEACHER_DECLARATION, telemetryValue);
this.location.back();
if (this.editType === 'add') {
+ this.generateTncAudit();
this.showAddedSuccessfullPopup();
} else {
this.commonUtilService.showToast(this.commonUtilService.translateMessage('UPDATED_SUCCESSFULLY'));
@@ -377,19 +379,6 @@ export class SelfDeclaredTeacherEditPage {
}
}
- onFormDataChange(event) {
- if (event) {
- if (event.value && this.formValue && event.value.state !== this.formValue.state) {
- this.getTeacherDetailsFormApi(event.value.state);
- }
-
- if (event.value) {
- this.formValue = event.value;
- }
- this.isFormValid = event.valid;
- }
- }
-
async showAddedSuccessfullPopup() {
const confirm = await this.popoverCtrl.create({
component: SbPopoverComponent,
@@ -409,9 +398,6 @@ export class SelfDeclaredTeacherEditPage {
await confirm.present();
const { data } = await confirm.onDidDismiss();
- if (data && data.canDelete) {
- console.log(data);
- }
}
generateTelemetryInteract(type, id, value?) {
@@ -431,7 +417,7 @@ export class SelfDeclaredTeacherEditPage {
getUpdatedValues(formVal) {
const telemetryValue = [];
- this.profile.userLocations.forEach(ele => {
+ this.profile['userLocations'].forEach(ele => {
if (ele.type === 'state' && ele.id !== formVal.state) {
telemetryValue.push('State');
}
@@ -440,7 +426,6 @@ export class SelfDeclaredTeacherEditPage {
}
});
- console.log(this.initialExternalIds);
for (const data in this.initialExternalIds) {
if (data !== 'state' && data !== 'district' && this.initialExternalIds[data].value !== formVal[data]) {
telemetryValue.push(this.initialExternalIds[data].name);
@@ -466,4 +451,168 @@ export class SelfDeclaredTeacherEditPage {
return externalIds;
}
+ private generateTncAudit() {
+ const corRelationList: Array = [{ id: PageId.TEACHER_SELF_DECLARATION, type: CorReleationDataType.FROM_PAGE }];
+ const telemetryObject = new TelemetryObject(ID.DATA_SHARING, 'TnC', this.profile.tncLatestVersion);
+ this.telemetryGeneratorService.generateAuditTelemetry(
+ Environment.USER,
+ AuditState.AUDIT_UPDATED,
+ [],
+ AuditType.TNC_DATA_SHARING,
+ telemetryObject.id,
+ telemetryObject.type,
+ telemetryObject.version,
+ corRelationList
+ );
+ }
+
+ private buildStateListClosure(stateCode?): FieldConfigOptionsBuilder {
+ return (formControl: FormControl, _: FormControl, notifyLoading, notifyLoaded) => {
+ return defer(async () => {
+
+ const formStateList: FieldConfigOption[] = [];
+ let selectedState;
+
+ const loader = await this.commonUtilService.getLoader();
+ await loader.present();
+ const req: LocationSearchCriteria = {
+ from: CachedItemRequestSourceFrom.SERVER,
+ filters: {
+ type: loc.TYPE_STATE
+ }
+ };
+ try {
+ const locations = await this.profileService.searchLocation(req).toPromise();
+
+ if (locations && Object.keys(locations).length) {
+ this.stateList = locations;
+
+ this.stateList.forEach(stateData => {
+ formStateList.push({ label: stateData.name, value: stateData.code });
+ });
+
+ if (this.editType === 'add' && this.availableLocationState) {
+ selectedState = this.stateList.find(s =>
+ (s.name === this.availableLocationState)
+ );
+ }
+
+ setTimeout(() => {
+ formControl.patchValue(stateCode || (selectedState && selectedState.code) || null);
+ }, 0);
+
+ } else {
+ this.commonUtilService.showToast('NO_DATA_FOUND');
+ }
+ } catch (e) {
+ console.log(e);
+ } finally {
+ loader.dismiss();
+ }
+
+
+ return formStateList;
+ });
+ };
+ }
+
+ private buildDistrictListClosure(districtCode?, formLoaded?): FieldConfigOptionsBuilder {
+ return (formControl: FormControl, contextFormControl: FormControl, notifyLoading, notifyLoaded) => {
+ if (!contextFormControl) {
+ return of([]);
+ }
+
+ return contextFormControl.valueChanges.pipe(
+ distinctUntilChanged(),
+ tap(() => {
+ formControl.patchValue(null);
+ }),
+ switchMap((value) => {
+ return defer(async () => {
+ const formDistrictList: FieldConfigOption[] = [];
+ let selectedDistrict;
+
+ const loader = await this.commonUtilService.getLoader();
+ await loader.present();
+
+ const selectdState = this.getStateIdFromCode(contextFormControl.value);
+
+ const req: LocationSearchCriteria = {
+ from: CachedItemRequestSourceFrom.SERVER,
+ filters: {
+ type: loc.TYPE_DISTRICT,
+ parentId: selectdState && selectdState.id
+ }
+ };
+ try {
+ const districtList = await this.profileService.searchLocation(req).toPromise();
+
+ if (districtList && Object.keys(districtList).length) {
+ this.districtList = districtList;
+
+ this.districtList.forEach(districtData => {
+ formDistrictList.push({ label: districtData.name, value: districtData.code });
+ });
+
+ if (!formLoaded) {
+
+ if (this.editType === 'add' && this.availableLocationDistrict) {
+ selectedDistrict = this.districtList.find(s =>
+ (s.name === this.availableLocationDistrict)
+ );
+ }
+
+ setTimeout(() => {
+ formControl.patchValue(districtCode || (selectedDistrict && selectedDistrict.code) || null);
+ }, 0);
+ } else {
+ setTimeout(() => {
+ formControl.patchValue(null);
+ }, 0);
+ }
+
+ } else {
+ this.availableLocationDistrict = '';
+ this.districtList = [];
+ this.commonUtilService.showToast('NO_DATA_FOUND');
+ }
+ } catch (e) {
+ console.log(e);
+ } finally {
+ loader.dismiss();
+ }
+ return formDistrictList;
+ });
+ })
+ );
+ };
+ }
+
+ formValueChanges(event) {
+ this.latestFormValue = event;
+ if (event && event.children && event.children.externalIds) {
+ if (!this.selectedStateCode && event.children.externalIds['declared-state']) {
+ this.selectedStateCode = event.children.externalIds['declared-state'];
+ }
+ if (event.children.externalIds['declared-state'] && this.selectedStateCode && this.selectedStateCode !== event.children.externalIds['declared-state']) {
+ this.selectedStateCode = event.children.externalIds['declared-state'];
+ const selectedState = this.getStateIdFromCode(this.selectedStateCode);
+ this.getTeacherDetailsFormApi(selectedState && selectedState.id);
+ }
+ }
+ }
+
+ formStatusChanges(event) {
+ this.latestFormStatus = event;
+ this.isFormValid = event.isValid;
+ }
+
+ private getStateIdFromCode(code) {
+ if (this.stateList && this.stateList.length) {
+ const selectedState = this.stateList.find(state => state.code === code);
+ return selectedState;
+ }
+ return null;
+ }
+
}
diff --git a/src/app/profile/sub-profile-edit/sub-profile-edit.page.html b/src/app/profile/sub-profile-edit/sub-profile-edit.page.html
index 87c06ac7f7..700451dbf9 100644
--- a/src/app/profile/sub-profile-edit/sub-profile-edit.page.html
+++ b/src/app/profile/sub-profile-edit/sub-profile-edit.page.html
@@ -7,7 +7,11 @@
-