Fairoj : sales pd product config in user reg and smart pd field visit ques added

This commit is contained in:
venbatechnologies@gmail.com 2020-12-30 16:32:36 +05:30
parent 047ca76dbb
commit 6f0886ec76
16 changed files with 427 additions and 25 deletions

View File

@ -130,13 +130,23 @@
</mat-card>
</div>
<div fxFlex.xs="100" fxFlex.sm="100" fxFlex.md="60" fxFlex.lg="70" fxFlex.xl="70" class="content-data" *ngFor="let master of pdMasterData">
<div fxLayout="row">
<div fxFlex="100" align="right">
<div fxLayout="row" fxLayoutAlign="flex-end" fxLayoutGap="68px" fxLayoutGap.xs="8px">
<!-- ENABLING THE FAB COPY LINK IMAGE CAPTURE AND VIDEO CALL BUTTON FOR TELE PD -->
<div fxLayout="column">
<app-speed-dial-fab fxFlex="30" class="fab-group" *ngIf="master.fk_pd_type == '2'" [options]="FabOptions" (fabClick)="fabAction($event,master)"></app-speed-dial-fab>
</div>
<!-- END OF COPY LINK IMAGE CAPTURE AND VIDEO CALL BUTTON FOR TELE PD -->
<div align="right">
<button *ngIf="master.fk_pd_type == '2'"
mat-raised-button mat-icon-button class="mr-1 mb-1 hover-icon" type="button" (click)="confirmFieldVisit()"
matTooltip="Is Field visit done ?" matTooltipPosition="above" >
<mat-icon>how_to_reg</mat-icon>
</button>
<button *ngIf="master.fk_pd_type == '2'" mat-stroked-button class="mr-1 mb-1" color="primary" (click)="uploadRecordedVideo()">
<mat-icon>videocam</mat-icon>&nbsp;
<strong>Upload</strong>
</button>
<span> <button *ngIf="master.fk_pd_type == '2'"
<!-- <span> <button *ngIf="master.fk_pd_type == '2'"
mat-raised-button mat-icon-button class="mr-1 mb-1 hover-icon" type="button" (click)="copyCusURL()"
matTooltip="Copy Customer Image Recapture Link" matTooltipPosition="above" >
<mat-icon>link</mat-icon>
@ -149,7 +159,7 @@
<button *ngIf="master.fk_pd_type == '2'" mat-stroked-button class="mr-1 mb-1" color="primary" (click)="openCusImages()">
<mat-icon>collections</mat-icon>&nbsp;
<strong>Customer Images</strong>
</button>
</button> -->
<!-- <span matTooltip="{{!videoplayback.enableBtn ? 'Recorded video is available after the PD is completed' : 'Play Recorded Video'}}" matTooltipPosition="above"> -->
<button *ngIf="master.fk_pd_type == '3' || master.fk_pd_type == '2'" mat-stroked-button matTooltip="Play Recorded Video" matTooltipPosition="above" class="mr-1 mb-1" color="primary" (click)="openPlayer()" [disabled]="!videoplayback.enableBtn">
<mat-icon>play_circle_filled</mat-icon>&nbsp;

View File

@ -23,6 +23,7 @@ import { PdTrigerService } from 'app/personal-discussion/pd-service/pd-triger.se
import { VideoPlayerComponent } from 'app/video-chat/video-player/video-player.component';
import { PdVisitTimeComponent } from '../pd-visit-time/pd-visit-time.component';
import { UploadVideoComponent } from 'app/quality-check/upload-video/upload-video.component';
import { DecisionDialogComponent } from 'app/shared/decision-dialog/decision-dialog.component';
@Component({
selector: 'app-qc-view',
@ -64,6 +65,37 @@ export class QcViewComponent implements OnInit, OnDestroy {
pdCollectedDocument:any=[];
pd_QC_Rating: Number;
videoplayback: any = {enableBtn:true,url:null};
FabOptions = {
icon:'collections',
placeholder:"Customer Images",
buttons: [
{
icon: 'link',
placeholder:'Copy Customer Image Recapture Link',
btnValue:'copy_cus_images_link'
},
{
icon: 'description',
placeholder:'Send Customer Image Recapture Link via SMS',
btnValue:'send_cus_images_link'
},
{
icon: 'collections',
placeholder:'Open Customer Images',
btnValue:'open_cus_images'
},
// {
// icon: 'room'
// },
// {
// icon: 'lightbulb_outline'
// },
// {
// icon: 'lock'
// }
]
};
constructor(notifier:NotifierService,private dialog: MatDialog,private _fb: FormBuilder,
private _qc: QcService,private route: ActivatedRoute,private router: Router, private QcListComponent: QcListComponent,private pdService:PdTrigerService) {
this.notifier=notifier
@ -369,6 +401,19 @@ export class QcViewComponent implements OnInit, OnDestroy {
this.notifier.notify('info','Customer Image Recapture link copied');
}
fabAction(event,master) {
console.log(event);
event = event.btnValue
if(event == 'open_cus_images') {
this.openCusImages()
}
if(event == 'send_cus_images_link') {
this.onClickSmsLink(master)
}
if(event == 'copy_cus_images_link') {
this.copyCusURL()
}
}
onClickSmsLink(master){
console.log('SMS',master);
let param={
@ -385,6 +430,10 @@ export class QcViewComponent implements OnInit, OnDestroy {
if(res['dataStatus']){
this.notifier.notify("info","SMS Sent Successfully")
}
else{
let msg = res.hasOwnProperty('msg') ? res.msg : "Something Went wrong";
this.notifier.notify("warning",msg)
}
})
}
openPlayer(){
@ -418,6 +467,43 @@ export class QcViewComponent implements OnInit, OnDestroy {
// maxWidth:'75vw'
})
}
confirmFieldVisit() {
// minimum 1 button required for this reusable dialog
let params = {title : "PD Visit", message:"Is Field visit done for this PD ?", buttons:["Yes","No"]}
const dialogRef = this.dialog.open(DecisionDialogComponent,{
minWidth:'30%',
disableClose:false,
data:params
// maxWidth:'75vw'
})
dialogRef.afterClosed().subscribe(res=>{
console.log(res)
let param = ''
if(res && res.toLowerCase() == 'yes') {
param = '1'
}
else if(res && res.toLowerCase() == 'no') {
param = '0'
}
if(param) {
this.updateFieldVisitStatus(param)
}
})
}
updateFieldVisitStatus(field_visit_done) {
let params = {is_field_visit_done:field_visit_done, "pd_id":this.viewID,random_string:this.masterRandomString}
this._qc.pdReviewStatusUpdate(params).subscribe(res=>{
if(res['dataStatus']) {
this.notifier.notify("success","Updated Successfully")
}
else{
this.notifier.notify("warning","Something went wrong")
}
},err=>{
this.notifier.notify("error","Network Error")
})
}
// getVideoUrl(pd_id,randomStr){
// let params = {"pd_id":pd_id,"random_string":randomStr}
// this.pdService.getRecordedPlaybackUrl(params).subscribe(result=>{

View File

@ -0,0 +1,52 @@
import {
animate,
keyframes,
query,
stagger,
state,
style,
transition,
trigger
} from '@angular/animations';
export const speedDialFabAnimations = [
trigger('fabToggler', [
state('inactive', style({
transform: 'rotate(0deg)'
})),
state('active', style({
transform: 'rotate(225deg)'
})),
transition('* <=> *', animate('200ms cubic-bezier(0.4, 0.0, 0.2, 1)')),
]),
trigger('speedDialStagger', [
transition('* => *', [
query(':enter', style({ opacity: 0 }), {optional: true}),
query(':enter', stagger('40ms',
[
animate('200ms cubic-bezier(0.4, 0.0, 0.2, 1)',
keyframes(
[
style({opacity: 0, transform: 'translateY(10px)'}),
style({opacity: 1, transform: 'translateY(0)'}),
]
)
)
]
), {optional: true}),
query(':leave',
animate('200ms cubic-bezier(0.4, 0.0, 0.2, 1)',
keyframes([
style({opacity: 1}),
style({opacity: 0}),
])
), {optional: true}
)
])
])
];

View File

@ -0,0 +1,26 @@
<div id="fab-dismiss"
*ngIf="fabTogglerState==='active'"
(click)="onToggleFab()">
</div>
<div class="fab-container">
<button mat-icon-button mat-raised-button class="fab-toggler mr-1 mb-1 hover-icon" color="optblue"
(click)="onToggleFab()" [matTooltip]="options.placeholder" matTooltipPosition="above">
<!-- <i class="material-icons" [@fabToggler]="{value: fabTogglerState}">link</i> -->
<mat-icon [@fabToggler]="{value: fabTogglerState}">{{options.icon}}</mat-icon>
</button>
<div [@speedDialStagger]="buttons.length">
<button *ngFor="let btn of buttons" (click)="onBtnClick(btn)"
mat-mini-fab
class="fab-secondary mr-1 mb-1 hover-icon"
color="secondary"
[matTooltip]="btn.placeholder" matTooltipPosition="above">
<mat-icon>{{btn.icon}}</mat-icon>
</button>
</div>
</div>
<!-- <button *ngIf="master.fk_pd_type == '3'"
mat-raised-button mat-icon-button class="mr-1 mb-1 hover-icon" type="button" (click)="copyCusURL(master.random_string)"
matTooltip="Copy Customer Link" matTooltipPosition="above">
<mat-icon>link</mat-icon>
</button> -->

View File

@ -0,0 +1,50 @@
.fab-container {
position: absolute;
// top: 1%;
// right: 35%;
z-index: 100;
display: flex;
flex-direction: column;
align-items: center;
> div {
display: flex;
flex-direction: row;
align-items: center;
// margin-top: 5px;
// margin-top: 5px;
position: absolute;
right: 67px;
// top: -13px;
button {
// margin-top: 17px;
background: #cfdd49;
margin-left:10px;
}
}
}
@media(max-width:580px) {
.fab-container {
> div {
flex-direction: column !important;
right: 0px;
top: 53px;
}
}
}
.fab-toggler {
float: right;
z-index: 100;
}
#fab-dismiss {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 99;
}

View File

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

View File

@ -0,0 +1,42 @@
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
import { speedDialFabAnimations } from './speed-dial-fab.animations';
@Component({
selector: 'app-speed-dial-fab',
templateUrl: './speed-dial-fab.component.html',
styleUrls: ['./speed-dial-fab.component.scss'],
animations: speedDialFabAnimations
})
export class SpeedDialFabComponent implements OnInit {
@Input() options;
@Output() fabClick = new EventEmitter()
buttons = [];
fabTogglerState = 'inactive';
constructor() { }
ngOnInit() {
const maxButtons = 6;
if (this.options.buttons.length > maxButtons) {
this.options.buttons.splice(5, this.options.buttons.length - maxButtons);
}
}
showItems() {
this.fabTogglerState = 'active';
this.buttons = this.options.buttons;
}
hideItems() {
this.fabTogglerState = 'inactive';
this.buttons = [];
}
onToggleFab() {
this.buttons.length ? this.hideItems() : this.showItems();
}
onBtnClick(btnValue) {
this.fabClick.emit(btnValue)
}
}

View File

@ -109,6 +109,7 @@ import { QcCusImagesComponent } from './qc-cus-images/qc-cus-images.component';
import { PdVisitTimeComponent } from './qc-list/pd-visit-time/pd-visit-time.component';
import { UploadVideoComponent } from './upload-video/upload-video.component'
import { MatVideoModule } from 'mat-video';
import { SpeedDialFabComponent } from './qc-list/qc-view/speed-dial-fab/speed-dial-fab.component';
// import { PdfViewerModule } from 'ng2-pdf-viewer';
@ -184,7 +185,7 @@ const customNotifierOptions: NotifierOptions = {
AngularSplitModule.forRoot(),
MatVideoModule
],
declarations: [QualityCheckComponent,QcListComponent, QcViewComponent, QcStartComponent, QcPdReportComponent,DialogChangeCurrentVenrsion, QcReviewComponent, ModelEditPdReportComponent, NumberToWordsPipe, QcNewComponent, QcCusImagesComponent, PdVisitTimeComponent, UploadVideoComponent],
declarations: [QualityCheckComponent,QcListComponent, QcViewComponent, QcStartComponent, QcPdReportComponent,DialogChangeCurrentVenrsion, QcReviewComponent, ModelEditPdReportComponent, NumberToWordsPipe, QcNewComponent, QcCusImagesComponent, PdVisitTimeComponent, UploadVideoComponent,SpeedDialFabComponent],
entryComponents: [PdVisitTimeComponent,PdAllocationComponent, SmartPdAllocationComponent, SchedulePdComponent, EditPdApplicantComponent, EditPdMasterComponent,DialogChangeCurrentVenrsion, QcReviewComponent, ModelEditPdReportComponent, InitiateAdditionalPdComponent,QcNewComponent,
BusinessAssetsInfoComponent,
ClientInfoComponent,

View File

@ -108,7 +108,7 @@ export class UserService {
let data: any = '';
if (cognitousers != '' && cognitousers !== undefined) {
//console.log(users);
// console.log(users);
let aws_name :any;
let updateby:any;
let createdby:any;
@ -188,6 +188,9 @@ export class UserService {
};
//console.log(roles);
formData.append('records',JSON.stringify(records));
if(users.hasOwnProperty('user_config') && users.user_config) {
formData.append('user_config',JSON.stringify(users.user_config));
}
formData.append('roles',JSON.stringify(({ "user_role": users.role.role_id})));
formData.append('profilepic',users.userpic);
formData.append('pdofficer',JSON.stringify(pdofficer));
@ -236,6 +239,9 @@ export class UserService {
return this.http.get<any>(apiurl + 'getListOfLenders');
}
getEntityPreferences(entity_id){
return this.http.get(apiurl+'getEntityPreferences/'+entity_id)
}
}

View File

@ -162,6 +162,19 @@
</mat-card-content>
</mat-card>
</div>
<mat-card *ngIf="regForm.controls['user_config']">
<mat-card-title>Configurations</mat-card-title><hr/>
<mat-card-content>
<mat-form-field dividerColor="primary" class="ml-xs mr-xs" style="width: 50%;">
<mat-select multiple placeholder="Sales Products" [formControl]="regForm.get('user_config')['controls']['salespd_products']" [disabled] = "productsList.length == 0">
<mat-option *ngFor="let pd of productsList" [value]="pd.product_id" >
{{pd.product_name}}
</mat-option>
</mat-select>
<mat-error align="end" *ngIf="regForm.get('user_config')['controls']['salespd_products'].hasError('required')">Sales Products required</mat-error>
</mat-form-field>
</mat-card-content>
</mat-card>
</div>
</mat-card-content>
<hr>

View File

@ -63,6 +63,7 @@ export class RegisterComponent implements OnInit {
entity_for_branch: any;
branchList: any;
enableBranch: boolean=false;
productsList: any = [];
constructor(
private router: Router, public fb: FormBuilder, public AWS: AwsService, private cd: ChangeDetectorRef
,private elementRef: ElementRef,public users:UserService,notifier:NotifierService) {
@ -94,13 +95,16 @@ export class RegisterComponent implements OnInit {
pdteam:[null],
pdtype:[null],
fk_lender_branch_id:[null]
});
this.userupdate();
}
addUserConfigControls() {
return this.fb.group({
salespd_products:['',Validators.compose([Validators.required])]
})
}
regdata() {
this.users.entityType().subscribe(res => {
this.types = res;
@ -119,7 +123,14 @@ export class RegisterComponent implements OnInit {
// this.checktype(this.types[0]);
// }
// });
this.callrole(1,this.types[0],'');
this.users.entitiesDetails().subscribe(res=>{
this.entitiesDetails = res;
if(this.entitiesDetails.dataStatus == true){
this.entitiesDetails = this.entitiesDetails.records;
this.callrole(this.types[0].entity_type_id,this.types[0],'');
}
})
}
});
this.users.City().subscribe(res => {
@ -148,15 +159,6 @@ export class RegisterComponent implements OnInit {
this.pdType = this.pdType.records.filter(pdty=>pdty.isactive ==1);
}
});
this.users.entitiesDetails().subscribe(res=>{
this.entitiesDetails = res;
if(this.entitiesDetails.dataStatus == true){
this.entitiesDetails = this.entitiesDetails.records;
}
})
this.users.getLenderDetails().subscribe(res=>{
this.entity_for_branch=res
if(this.entity_for_branch.dataStatus == true){
@ -280,6 +282,7 @@ console.log("cog",userData,this.usersData)
this.getBranch(flag);
}
getBranch(flag?){
this.checkUserConfigAvail()
if(this.regForm.value.role != null && (this.regForm.value.role.role_name == "Branch Credit" || this.regForm.value.role.role_name == "Branch Sales") && this.regForm.value.lenVenName != null){
console.log(this.regForm.value.role,this.entity_for_branch,this.regForm.value.lenVenName);
if(this.entity_for_branch.length > 0){
@ -316,6 +319,27 @@ getBranch(flag?){
this.City = this.Cities.filter(city=>city.fk_state_id == e.value.state_id);
}
checkUserConfigAvail() {
console.log(this.types[0].entity_type_id,this.regForm.value.lenVenName)
if(this.types[0].entity_type_id == '2' && this.regForm.value.lenVenName.short_name == 'MWISE') {
this.regForm.addControl('user_config',this.addUserConfigControls())
this.users.getEntityPreferences(this.regForm.value.lenVenName.entity_id).subscribe(res=>{
if(res['dataStatus']) {
this.productsList = res['records'].salespd_products
if (this.users.localUserId != '' && this.users.localUserId != null && this.users.localUserId !== undefined && this.users.localUserId.user_config) {
this.regForm.get('user_config')['controls']['salespd_products'].setValue(this.users.localUserId.user_config.salespd_products)
}
else {
this.regForm.get('user_config')['controls']['salespd_products'].setValue(this.productsList.map(item=>item.product_id))
}
}
})
console.log(this.regForm.value)
}
else {
this.regForm.removeControl('user_config')
}
}
userupdate() {
@ -336,7 +360,9 @@ getBranch(flag?){
this.entitiesDetails = this.entitiesDetails.records.filter(ent=>ent.isactive ==1);
let entitiy = this.entitiesDetails.filter(ent=>this.usersData.fk_entity_id == ent.entity_id)[0];
this.regForm.controls['lenVenName'].setValue(entitiy);
this.callrole(2,this.types[0],this.usersData);
this.checkUserConfigAvail()
}
else{
this.callrole(2,this.types[0],this.usersData);

View File

@ -0,0 +1,14 @@
<h2 mat-dialog-title>{{data.title}}</h2>
<mat-dialog-content>
<div fxFlex="100">
<p align="center">
{{data.message}}
</p>
</div>
</mat-dialog-content>
<mat-dialog-actions align="end" >
<button mat-raised-button color="primary" (click)="updateString(data.buttons[0])"><strong>{{data.buttons[0]}}</strong></button>
<button mat-raised-button *ngIf="data.buttons[1]" (click)="updateString(data.buttons[1])"><strong> {{data.buttons[1]}} </strong></button>
</mat-dialog-actions>

View File

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

View File

@ -0,0 +1,20 @@
import { Component, Inject, OnInit } from '@angular/core';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';
@Component({
selector: 'app-decision-dialog',
templateUrl: './decision-dialog.component.html',
styleUrls: ['./decision-dialog.component.scss']
})
export class DecisionDialogComponent implements OnInit {
constructor(@Inject(MAT_DIALOG_DATA) public data:any, private dialogRef:MatDialogRef<DecisionDialogComponent>) { }
ngOnInit() {
console.log(this.data);
}
updateString(result) {
this.dialogRef.close(result)
}
}

View File

@ -8,10 +8,12 @@ import { RatingComponent} from './rating/rating.component';
import { NumbersOnlyDirective } from './numbers-only/numbers-only.directive';
import { ForMobileNumbersDirective } from './for-mobile-numbers/for-mobile-numbers.directive';
import { ProgressSpineerDialogComponent } from './progress-spineer-dialog/progress-spineer-dialog.component';
import { MatProgressSpinnerModule } from '@angular/material';
import { MatButtonModule, MatDialogModule, MatProgressSpinnerModule } from '@angular/material';
import { DecisionDialogComponent } from './decision-dialog/decision-dialog.component';
import { CommonModule } from '@angular/common';
@NgModule({
entryComponents:[ProgressSpineerDialogComponent],
entryComponents:[ProgressSpineerDialogComponent,DecisionDialogComponent],
declarations: [
AccordionAnchorDirective,
AccordionLinkDirective,
@ -20,9 +22,10 @@ import { MatProgressSpinnerModule } from '@angular/material';
RatingComponent,
NumbersOnlyDirective,
ForMobileNumbersDirective,
ProgressSpineerDialogComponent
ProgressSpineerDialogComponent,
DecisionDialogComponent
],
imports:[MatProgressSpinnerModule],
imports:[MatProgressSpinnerModule,MatDialogModule,CommonModule,MatButtonModule],
exports: [
AccordionAnchorDirective,
AccordionLinkDirective,
@ -31,7 +34,10 @@ import { MatProgressSpinnerModule } from '@angular/material';
RatingComponent,
NumbersOnlyDirective,
ForMobileNumbersDirective,
ProgressSpineerDialogComponent
ProgressSpineerDialogComponent,
DecisionDialogComponent,
CommonModule,
MatButtonModule
],
providers: [ MenuItems, HorizontalMenuItems ]
})