| @@ -2349,6 +2349,22 @@ | |||
| } | |||
| } | |||
| }, | |||
| "@progress/kendo-angular-pager": { | |||
| "version": "2.0.0", | |||
| "resolved": "https://registry.npmjs.org/@progress/kendo-angular-pager/-/kendo-angular-pager-2.0.0.tgz", | |||
| "integrity": "sha512-Q6ZyK8Xvk77rc2PhvRyRS53G/gN0GA9zzBs++KNs3MmOaKQNNggtvgne+fstEhNrY1R9nO53CzMlqYs8i+dH7w==", | |||
| "requires": { | |||
| "@progress/kendo-schematics": "^1.2.0", | |||
| "tslib": "^1.9.0" | |||
| }, | |||
| "dependencies": { | |||
| "tslib": { | |||
| "version": "1.14.1", | |||
| "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", | |||
| "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" | |||
| } | |||
| } | |||
| }, | |||
| "@progress/kendo-angular-pdf-export": { | |||
| "version": "3.0.0", | |||
| "resolved": "https://registry.npmjs.org/@progress/kendo-angular-pdf-export/-/kendo-angular-pdf-export-3.0.0.tgz", | |||
| @@ -29,28 +29,29 @@ | |||
| "@progress/kendo-angular-common": "^2.0.0", | |||
| "@progress/kendo-angular-dateinputs": "^5.1.0", | |||
| "@progress/kendo-angular-dialog": "^5.0.0", | |||
| "@progress/kendo-angular-dropdowns": "^5.1.0", | |||
| "@progress/kendo-angular-dropdowns": "^5.0.0", | |||
| "@progress/kendo-angular-editor": "^2.0.1", | |||
| "@progress/kendo-angular-excel-export": "^4.0.0", | |||
| "@progress/kendo-angular-grid": "^5.0.3", | |||
| "@progress/kendo-angular-icons": "^0.4.2", | |||
| "@progress/kendo-angular-indicators": "^1.0.0", | |||
| "@progress/kendo-angular-inputs": "^7.1.2", | |||
| "@progress/kendo-angular-intl": "^3.1.0", | |||
| "@progress/kendo-angular-inputs": "^7.0.0", | |||
| "@progress/kendo-angular-intl": "^3.0.0", | |||
| "@progress/kendo-angular-l10n": "^3.0.0", | |||
| "@progress/kendo-angular-label": "^3.0.1", | |||
| "@progress/kendo-angular-layout": "6", | |||
| "@progress/kendo-angular-menu": "^3.0.0", | |||
| "@progress/kendo-angular-navigation": "^1.0.0", | |||
| "@progress/kendo-angular-notification": "^3.0.0", | |||
| "@progress/kendo-angular-pager": "^2.0.0", | |||
| "@progress/kendo-angular-pdf-export": "^3.0.0", | |||
| "@progress/kendo-angular-popup": "^4.0.0", | |||
| "@progress/kendo-angular-progressbar": "^2.0.0", | |||
| "@progress/kendo-angular-toolbar": "^4.0.0", | |||
| "@progress/kendo-angular-treeview": "^5.1.0", | |||
| "@progress/kendo-angular-treeview": "^5.0.0", | |||
| "@progress/kendo-angular-upload": "^7.1.0", | |||
| "@progress/kendo-data-query": "^1.5.4", | |||
| "@progress/kendo-drawing": "^1.9.4", | |||
| "@progress/kendo-drawing": "^1.5.12", | |||
| "@progress/kendo-licensing": "^1.0.2", | |||
| "@progress/kendo-svg-icons": "^0.1.2", | |||
| "@progress/kendo-theme-default": "latest", | |||
| @@ -23,6 +23,7 @@ import {PayInComponent} from './pay-in/pay-in.component'; | |||
| import {PeopleAddComponent} from './people-add/people-add.component'; | |||
| import {SettingsComponent} from './settings/settings.component'; | |||
| import {ProfileComponent} from './profile/profile.component'; | |||
| import {ListAllPeopleComponent} from './list-all-people/list-all-people.component'; | |||
| const routes: Routes = [ | |||
| @@ -49,7 +50,7 @@ const routes: Routes = [ | |||
| {path : 'reward-unpaid', component: RewardUnpaidComponent, canActivate: [AuthGuard] }, | |||
| {path : 'pay-in', component: PayInComponent, canActivate: [AuthGuard] }, | |||
| {path : 'lender-uploads', component: LenderUploadsComponent, canActivate: [AuthGuard] }, | |||
| {path : 'list-all-people', component: LenderUploadsComponent, canActivate: [AuthGuard] }, | |||
| {path : 'list-all-people', component: ListAllPeopleComponent, canActivate: [AuthGuard] }, | |||
| {path : 'people-add', component: PeopleAddComponent, canActivate: [AuthGuard] }, | |||
| {path : 'profile', component: ProfileComponent, canActivate: [AuthGuard] }, | |||
| {path : 'profile/:id', component: ProfileComponent, canActivate: [AuthGuard] }, | |||
| @@ -86,6 +86,10 @@ import { MessageBoxComponent } from './message-box/message-box.component'; | |||
| import { UserProfileComponent } from './profile/user-profile/user-profile.component'; | |||
| import { AdminProfileComponent } from './profile/admin-profile/admin-profile.component'; | |||
| import { ChangePasswordComponent } from './profile/change-password/change-password.component'; | |||
| import { ProgressBarModule } from '@progress/kendo-angular-progressbar'; | |||
| import { PagerModule } from '@progress/kendo-angular-pager'; | |||
| @@ -174,7 +178,9 @@ import { ChangePasswordComponent } from './profile/change-password/change-passwo | |||
| ExcelExportModule, | |||
| EditorModule, | |||
| UploadModule, | |||
| FileSelectModule | |||
| FileSelectModule, | |||
| ProgressBarModule, | |||
| PagerModule | |||
| ], | |||
| providers: [ | |||
| MenuService, | |||
| @@ -73,4 +73,5 @@ export class ListAllLoansComponent implements OnInit { | |||
| this.router.navigate(['/edit-loan/' + event.dataItem.Id]); | |||
| } | |||
| } | |||
| @@ -1 +1,33 @@ | |||
| <p>list-all-people works!</p> | |||
| <div class="workarea"> | |||
| <kendo-datapager | |||
| [style.width.%]="100" | |||
| [pageSize]="pageSize" | |||
| [skip]="skip" | |||
| [total]="total" | |||
| (pageChange)="onPageChange($event)"> | |||
| </kendo-datapager> | |||
| <bkp-divider-shadow-bottom></bkp-divider-shadow-bottom> | |||
| <div class="container"> | |||
| <div class="row justify-content-center"> | |||
| <div class="col-sm-12 text-center"> | |||
| <kendo-textbox class='search-people' (valueChange)="onFilterPeople($event)"></kendo-textbox> | |||
| </div> | |||
| </div> | |||
| <div class="row justify-content-center"> | |||
| <div class="col-sm-3 text-center" *ngFor="let p of displayedPeople"> | |||
| <app-people-card [PeopleId]="p.Id"></app-people-card> | |||
| </div> | |||
| </div> | |||
| <div class="vertical-spacer"></div> | |||
| </div> | |||
| <kendo-datapager | |||
| class="bottom-pager" | |||
| [style.width.%]="100" | |||
| [pageSize]="pageSize" | |||
| [skip]="skip" | |||
| [total]="total" | |||
| (pageChange)="onPageChange($event)"> | |||
| </kendo-datapager> | |||
| </div> | |||
| @@ -0,0 +1,30 @@ | |||
| div.workarea{ | |||
| height: calc(100vh - 48px); | |||
| position:relative; | |||
| } | |||
| kendo-multicolumncombobox{ | |||
| width:600px; | |||
| } | |||
| .contact-image { | |||
| width: 22px; | |||
| height: 22px; | |||
| margin-right: 8px; | |||
| border-radius: 50%; | |||
| } | |||
| .search-people{ | |||
| width: 600px; | |||
| margin-bottom: 2px; | |||
| } | |||
| .bottom-pager { | |||
| position: fixed; | |||
| bottom: 0px; | |||
| } | |||
| .vertical-spacer{ | |||
| height: 150px; | |||
| } | |||
| @@ -1,4 +1,10 @@ | |||
| import { Component, OnInit } from '@angular/core'; | |||
| import {Component, OnInit, ViewChild} from '@angular/core'; | |||
| import {PeopleModel, RelevantPeopleModel} from '../models/people.model'; | |||
| import {PeopleService} from '../service/people.service'; | |||
| import {AuthService} from '../service/auth.service'; | |||
| import {ClonerService} from '../service/clone.service'; | |||
| import {ComboBoxComponent, PopupSettings, VirtualizationSettings} from '@progress/kendo-angular-dropdowns'; | |||
| import { PageChangeEvent } from '@progress/kendo-angular-pager'; | |||
| @Component({ | |||
| selector: 'app-list-all-people', | |||
| @@ -7,9 +13,63 @@ import { Component, OnInit } from '@angular/core'; | |||
| }) | |||
| export class ListAllPeopleComponent implements OnInit { | |||
| constructor() { } | |||
| private AllPeople: PeopleModel[] = []; | |||
| public filteredPeople: PeopleModel[] = []; | |||
| public displayedPeople: PeopleModel[] = []; | |||
| public personSelected: PeopleModel; | |||
| public skip = 0; | |||
| public pageSize = 12; | |||
| public total = 0; | |||
| constructor(private ps: PeopleService, private auth: AuthService, private dcs: ClonerService) { } | |||
| ngOnInit(): void { | |||
| this.ps.getPeopleList('').subscribe( | |||
| resp => { | |||
| this.AllPeople = resp.List; | |||
| this.onFilterPeople(''); | |||
| } | |||
| ); | |||
| } | |||
| public onFilterPeople(hint: string): void { | |||
| if ( hint === undefined || hint.length === 0 ) { | |||
| this.filteredPeople = this.AllPeople.slice(0); | |||
| }else { | |||
| this.filteredPeople = this.AllPeople.filter( | |||
| v => v.Display.toLowerCase().includes(hint.toLowerCase()) | |||
| ); | |||
| } | |||
| this.skip = 0 ; | |||
| this.total = this.filteredPeople.length; | |||
| this.loadDisplayedPeople(); | |||
| } | |||
| public onPeopleSelected(people: PeopleModel): void { | |||
| if ( people !== undefined ) { | |||
| this.filteredPeople = []; | |||
| this.filteredPeople.push(people); | |||
| }else{ | |||
| this.filteredPeople = this.AllPeople.slice(0); | |||
| } | |||
| this.loadDisplayedPeople(); | |||
| } | |||
| public getContactImageUrl(contactId: string): string { | |||
| return this.auth.getUrl('avatar/' + contactId); | |||
| } | |||
| public onPageChange(e: PageChangeEvent): void { | |||
| this.skip = e.skip; | |||
| this.pageSize = e.take; | |||
| this.loadDisplayedPeople(); | |||
| } | |||
| private loadDisplayedPeople(): void { | |||
| this.displayedPeople = this.filteredPeople.slice(this.skip, this.skip + this.pageSize); | |||
| this.total = this.filteredPeople.length; | |||
| } | |||
| } | |||
| @@ -13,14 +13,14 @@ | |||
| (close)="rebuildPeopleMap($event)"> | |||
| <ng-template kendoMultiSelectItemTemplate let-dataItem> | |||
| <img class="contact-image" [src]="getContactImageUrl(dataItem.Id)" /> | |||
| <span>{{ dataItem.First +' ' + dataItem.Last}}</span> | |||
| <span>{{ dataItem.Display}}</span> | |||
| </ng-template> | |||
| </kendo-multiselect> | |||
| <div class="container"> | |||
| <div class="row clientCardContainer justify-content-center"> | |||
| <div *ngFor="let v of this.Loan.Client" class="col-sm-9"> | |||
| <app-people-card [peopleId]="v.Id"></app-people-card> | |||
| <app-people-card [PeopleId]="v.Id"></app-people-card> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| @@ -40,7 +40,7 @@ | |||
| <div class="container"> | |||
| <div class="row brokerCardContainer justify-content-center"> | |||
| <div *ngFor="let v of this.Loan.Broker" class="col-sm-9"> | |||
| <app-people-card [peopleId]="v.Id"></app-people-card> | |||
| <app-people-card [PeopleId]="v.Id"></app-people-card> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| @@ -62,7 +62,7 @@ | |||
| <div class="container"> | |||
| <div class="row beneficiaryCardContainer justify-content-center"> | |||
| <div *ngFor="let v of this.Loan.OtherRewarder, let idx=index" class="col-sm-4"> | |||
| <app-people-card [peopleId]="v.Id"></app-people-card> | |||
| <app-people-card [PeopleId]="v.Id"></app-people-card> | |||
| <kendo-combobox [name]="'beneficiary_'+idx" [data]="roles" [allowCustom]="true" [(ngModel)]="role[v.Id]" | |||
| class="beneficiaryRole" required="true"> </kendo-combobox> | |||
| </div> | |||
| @@ -42,7 +42,7 @@ export const mainMenuItems: any[] = [ | |||
| text: 'People', | |||
| icon: 'user', | |||
| items: [ | |||
| { text: 'Add ', icon: 'plus', url: './#profile/start-new-people' }, | |||
| { text: 'Add ', icon: 'plus', url: './#people-add' }, | |||
| { text: 'List All', fa: faIdCard , url: './#list-all-people'}, | |||
| ] | |||
| }, | |||
| @@ -18,9 +18,7 @@ export class BrokerModel{ | |||
| public Organization: string | |||
| ){} | |||
| public toPeopleModel(): PeopleModel{ | |||
| return new PeopleModel( this.Id, this.First, this.Last, this.Middle, this.Title, this.Display, this.Nick ); | |||
| } | |||
| public static EmptyNew(): BrokerModel { | |||
| return new BrokerModel('', '', '', '', '', '', '', | |||
| @@ -29,7 +27,11 @@ export class BrokerModel{ | |||
| public static getFromUserAndExtra(u: PeopleModel, ex: UserExtraModel): BrokerModel { | |||
| return new BrokerModel( | |||
| u.Id, u.First, u.Last, u.Middle, u.Title, u.Display, u.Nick, ex.Login, ex.Enabled, ex.BSB, ex.ACC, ex.License, ex.Organization | |||
| u.Id, u.First, u.Last, u.Middle, u.Title, u.Display, u.Nick, ex.Login, u.Enabled, ex.BSB, ex.ACC, ex.License, ex.Organization | |||
| ); | |||
| } | |||
| public toPeopleModel(): PeopleModel{ | |||
| return new PeopleModel( this.Id, this.First, this.Last, this.Middle, this.Title, this.Display, this.Nick, this.Enabled ); | |||
| } | |||
| } | |||
| @@ -133,7 +133,7 @@ export class LoanModel { | |||
| this.Client = []; | |||
| v.forEach((c) => { | |||
| this.Client.push( | |||
| new PeopleModel(c.Id, c.First, c.Last, c.Middle, c.Title, c.Display, c.Nick) | |||
| new PeopleModel(c.Id, c.First, c.Last, c.Middle, c.Title, c.Display, c.Nick, c.Enabled) | |||
| ); | |||
| }); | |||
| } | |||
| @@ -142,7 +142,7 @@ export class LoanModel { | |||
| this.OtherRewarder = []; | |||
| v.forEach((c) => { | |||
| this.OtherRewarder.push( | |||
| new PeopleModel(c.Id, c.First, c.Last, c.Middle, c.Title, c.Display, c.Nick) | |||
| new PeopleModel(c.Id, c.First, c.Last, c.Middle, c.Title, c.Display, c.Nick, c.Enabled) | |||
| ); | |||
| }); | |||
| } | |||
| @@ -151,7 +151,7 @@ export class LoanModel { | |||
| this.Broker = []; | |||
| v.forEach((b => { | |||
| this.Broker.push(new BrokerModel( | |||
| b.Id, b.First, b.Last, b.Middle, b.Title, b.Display, b.Nick, b.Login, b.Enaabled, b.BSB, b.ACC, b.License, b.Organization | |||
| b.Id, b.First, b.Last, b.Middle, b.Title, b.Display, b.Nick, b.Login, b.Enabled, b.BSB, b.ACC, b.License, b.Organization | |||
| ) | |||
| ); | |||
| })); | |||
| @@ -161,7 +161,7 @@ export class LoanModel { | |||
| this.RewardPeople = []; | |||
| v.forEach((c) => { | |||
| this.RewardPeople.push( | |||
| new PeopleModel(c.Id, c.First, c.Last, c.Middle, c.Title, c.Display, c.Nick) | |||
| new PeopleModel(c.Id, c.First, c.Last, c.Middle, c.Title, c.Display, c.Nick, c.Enabled) | |||
| ); | |||
| }); | |||
| } | |||
| @@ -10,6 +10,7 @@ export class PeopleModel{ | |||
| public Title: string, | |||
| public Display: string, | |||
| public Nick: string, | |||
| public Enabled: boolean, | |||
| ){} | |||
| get FullName(): string { | |||
| @@ -21,7 +22,7 @@ export class PeopleModel{ | |||
| } | |||
| public static EmptyNew(): PeopleModel { | |||
| return new PeopleModel('', '', '', '', '', '', '' ); | |||
| return new PeopleModel('', '', '', '', '', '', '', false ); | |||
| } | |||
| public Copy(ppl: PeopleModel): void { | |||
| @@ -32,6 +33,7 @@ export class PeopleModel{ | |||
| this.Title = ppl.Title; | |||
| this.Display = ppl.Display; | |||
| this.Nick = ppl.Nick; | |||
| this.Enabled = ppl.Enabled; | |||
| } | |||
| public Clear(): void { | |||
| @@ -42,6 +44,7 @@ export class PeopleModel{ | |||
| this.Title = ''; | |||
| this.Display = ''; | |||
| this.Nick = ''; | |||
| this.Enabled = false; | |||
| } | |||
| } | |||
| @@ -4,7 +4,6 @@ export class UserExtraModel { | |||
| public ACC: string; | |||
| public License: string; | |||
| public Organization: string; | |||
| public Enabled: boolean; | |||
| public Login: string; | |||
| public Role?: string; | |||
| @@ -18,7 +17,6 @@ export class UserExtraModel { | |||
| rt.ACC = ''; | |||
| rt.License = ''; | |||
| rt.Organization = ''; | |||
| rt.Enabled = false; | |||
| rt.Login = ''; | |||
| rt.Role = ''; | |||
| return rt; | |||
| @@ -29,9 +27,17 @@ export class UserExtraModel { | |||
| this.ACC = ''; | |||
| this.License = ''; | |||
| this.Organization = ''; | |||
| this.Enabled = false; | |||
| this.Login = ''; | |||
| this.Role = ''; | |||
| } | |||
| public Copy(payload: Partial<UserExtraModel>): void { | |||
| this.BSB = payload.BSB; | |||
| this.ACC = payload.ACC; | |||
| this.License = payload.License; | |||
| this.Organization = payload.Organization; | |||
| this.Login = payload.Login; | |||
| this.Role = payload.Role; | |||
| } | |||
| } | |||
| @@ -1 +1 @@ | |||
| <p>people-add works!</p> | |||
| <app-profile [PeopleId]="'start-new-people'"></app-profile> | |||
| @@ -1,9 +1,24 @@ | |||
| <div class="contact" > | |||
| <div class="k-hbox"> | |||
| <kendo-avatar [shape]="'circle'" [imageSrc]="photoURL()"></kendo-avatar> | |||
| <div> | |||
| <h5>{{ contact.Nick }} </h5> | |||
| <p>{{ contact.Title }} {{ contact.First}} {{ contact.Last}}</p> | |||
| <div class="outer-div"> | |||
| <div class="inner-div"> | |||
| <div class="front"> | |||
| <div class="front__bkg-photo" [ngStyle]="{'background-image': bgPhoto() }"></div> | |||
| <div class="front__face-photo" [ngStyle]="{'background-image': photoURL() }"> | |||
| </div> | |||
| <div class="front__text"> | |||
| <h3 class="front__text-header">{{contact.Display}} </h3> | |||
| <p class="front__text-para"><i class="fas fa-map-marker-alt front-icons"></i>{{UserExtra.Role}} | |||
| <kendo-icon *ngIf="!contact.Enabled" [name]="'close-circle'" [themeColor]="'error'" class="k-badge-icon"></kendo-icon> | |||
| <kendo-icon *ngIf="contact.Enabled" [name]="'check-circle'" [themeColor]="'success'" class="k-badge-icon"></kendo-icon> | |||
| </p> | |||
| </div> | |||
| </div> | |||
| <div class="back"> | |||
| <div class="social-media-wrapper"> | |||
| <button kendoButton (click)="onButtonClick()" look="outline" icon="edit">Edit</button> | |||
| <button #enabled *ngIf="contact.Id.length > 10" kendoButton (selectedChange)="onSelectedChange($event)" look="outline" icon="tick" | |||
| [toggleable]="true" [selected]="contact.Enabled" | |||
| >Enable</button> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| @@ -11,3 +11,245 @@ div.contact { | |||
| div.contact:hover { | |||
| box-shadow: rgba(149, 157, 165, 0.2) 0px 8px 24px; | |||
| } | |||
| app-people-card{ | |||
| border-radius: 10px; | |||
| margin: 10px 10px; | |||
| } | |||
| $black: #071011; | |||
| $backcolor: #ecdfaf; | |||
| $white: #fff; | |||
| $red: tomato; | |||
| $standard: 10px; | |||
| $card-height: 200px; | |||
| $card-width: 330px; | |||
| .background { | |||
| position: absolute; | |||
| top: 0; | |||
| left: 0; | |||
| height: 100vh; | |||
| width: 100vw; | |||
| background: url("https://images.unsplash.com/photo-1447433589675-4aaa569f3e05?ixlib=rb-0.3.5&s=4222852e25e0f57d9485f7889957e99a&auto=format&fit=crop&w=2000&q=80"); | |||
| background-size: cover; | |||
| background: #ccc; | |||
| background-position: 0 50%; | |||
| background: #DEB493; | |||
| &:after { | |||
| content: ""; | |||
| position: absolute; | |||
| top: 0; | |||
| left: 0; | |||
| height: 100%; | |||
| width: 100%; | |||
| background: rgba(0, 0, 0, 0); | |||
| } | |||
| } | |||
| .outer-div, | |||
| .inner-div { | |||
| height: $card-height; | |||
| max-width: $card-width; | |||
| margin: 0 auto; | |||
| position: relative; | |||
| } | |||
| .outer-div { | |||
| perspective: 900px; | |||
| perspective-origin: 50% calc(50% - 18em); | |||
| } | |||
| .inner-div { | |||
| margin: $standard * 5 auto; | |||
| border-radius: 5px; | |||
| font-weight: 400; | |||
| color: $black; | |||
| font-size: 1rem; | |||
| text-align: center; | |||
| transition: all 0.6s cubic-bezier(0.8, -0.4, 0.2, 1.7); | |||
| transform-style: preserve-3d; | |||
| &:hover .social-icon { | |||
| opacity: 1; | |||
| top: 0; | |||
| } | |||
| &:hover .front__face-photo, | |||
| &:hover .front__footer { | |||
| opacity: 0; | |||
| } | |||
| } | |||
| .outer-div:hover .inner-div { | |||
| transform: rotateY(180deg); | |||
| } | |||
| .front, | |||
| .back { | |||
| position: relative; | |||
| top: 0; | |||
| left: 0; | |||
| overflow:hidden; | |||
| backface-visibility: hidden; | |||
| } | |||
| .front { | |||
| cursor: pointer; | |||
| height: 100%; | |||
| background: $white; | |||
| backface-visibility: hidden; | |||
| border-radius: 5px; | |||
| box-shadow: 0 15px 10px -10px rgba(0, 0, 0, 0.5), 0 1px 4px rgba(0, 0, 0, 0.3), | |||
| 0 0 40px rgba(0, 0, 0, 0.1) inset; | |||
| } | |||
| .front__bkg-photo { | |||
| position: relative; | |||
| height: 80px; | |||
| width: $card-width; | |||
| background-size: cover; | |||
| backface-visibility: hidden; | |||
| overflow: hidden; | |||
| border-top-right-radius: 5px; | |||
| border-top-left-radius: 5px; | |||
| &:after { | |||
| content: ""; | |||
| position: absolute; | |||
| top: 0; | |||
| left: 0; | |||
| height: 100%; | |||
| width: 100%; | |||
| } | |||
| } | |||
| .front__face-photo { | |||
| position: relative; | |||
| top: -60px; | |||
| height: 120px; | |||
| width: 120px; | |||
| margin: 0 auto; | |||
| border-radius: 50%; | |||
| border: 5px solid $white; | |||
| background-size: contain; | |||
| backface-visibility: hidden; | |||
| overflow: hidden; | |||
| transition: all 0.6s cubic-bezier(0.8, -0.4, 0.2, 1.7); | |||
| z-index: 3; | |||
| } | |||
| .front__text { | |||
| position: relative; | |||
| top: -55px; | |||
| margin: 0 auto; | |||
| font-family: "Montserrat"; | |||
| font-size: 18px; | |||
| backface-visibility: hidden; | |||
| .front__text-header { | |||
| font-weight: 700; | |||
| font-family: "Oswald"; | |||
| text-transform: uppercase; | |||
| font-size: 20px; | |||
| } | |||
| .front__text-para { | |||
| position: relative; | |||
| top: -5px; | |||
| color: #000; | |||
| font-size: 14px; | |||
| letter-spacing: 0.4px; | |||
| font-weight: 400; | |||
| font-family: "Montserrat", sans-serif; | |||
| } | |||
| .front-icons { | |||
| position: relative; | |||
| top: 0; | |||
| font-size: 14px; | |||
| margin-right: 6px; | |||
| color: gray; | |||
| } | |||
| .front__text-hover { | |||
| position: relative; | |||
| top: 10px; | |||
| font-size: 10px; | |||
| color: $red; | |||
| backface-visibility: hidden; | |||
| font-weight: 700; | |||
| text-transform: uppercase; | |||
| letter-spacing: .4px; | |||
| border: 2px solid $red; | |||
| padding: 8px 15px; | |||
| border-radius: 30px; | |||
| background: $red; | |||
| color: $white; | |||
| } | |||
| } | |||
| .back { | |||
| transform: rotateY(180deg); | |||
| position: absolute; | |||
| top: 0; | |||
| left: 0; | |||
| height: 100%; | |||
| width: 100%; | |||
| background-color: $backcolor; | |||
| border-radius: 5px; | |||
| display: flex; | |||
| flex-direction: row; | |||
| justify-content: center; | |||
| align-items: center; | |||
| } | |||
| .social-media-wrapper { | |||
| font-size: 36px; | |||
| .social-icon { | |||
| position: relative; | |||
| top: 20px; | |||
| margin-left: 5px; | |||
| margin-right: 5px; | |||
| opacity: 0; | |||
| color: #fff; | |||
| transition: all 0.4s cubic-bezier(0.3, 0.7, 0.1, 1.9); | |||
| } | |||
| .social-icon:nth-child(1) { | |||
| transition-delay: 0.6s; | |||
| } | |||
| .social-icon:nth-child(2) { | |||
| transition-delay: 0.7s; | |||
| } | |||
| .social-icon:nth-child(3) { | |||
| transition-delay: 0.8s; | |||
| } | |||
| .social-icon:nth-child(4) { | |||
| transition-delay: 0.9s; | |||
| } | |||
| } | |||
| .fab { | |||
| position: relative; | |||
| top: 0; | |||
| left: 0; | |||
| transition: all 200ms ease-in-out; | |||
| } | |||
| .fab:hover { | |||
| top: -5px; | |||
| } | |||
| @@ -1,7 +1,11 @@ | |||
| import {Component, Input, OnInit} from '@angular/core'; | |||
| import {Component, Input, OnInit, ViewChild} from '@angular/core'; | |||
| import {PeopleModel} from '../models/people.model'; | |||
| import {PeopleService} from '../service/people.service'; | |||
| import {AuthService} from '../service/auth.service'; | |||
| import {Button} from '@progress/kendo-angular-buttons'; | |||
| import {Router} from '@angular/router'; | |||
| import {UserExtraModel} from '../models/user-extra.model'; | |||
| import {BadgeAlign} from '@progress/kendo-angular-indicators'; | |||
| @Component({ | |||
| selector: 'app-people-card', | |||
| @@ -10,22 +14,62 @@ import {AuthService} from '../service/auth.service'; | |||
| }) | |||
| export class PeopleCardComponent implements OnInit { | |||
| @Input() peopleId: string; | |||
| public contact: PeopleModel = new PeopleModel('', '', '', '', '', '', ''); | |||
| constructor(private ps: PeopleService, private auth: AuthService) { } | |||
| @Input() PeopleId: string; | |||
| @ViewChild('enabled', {static: true}) enabled: Button; | |||
| public contact: PeopleModel = new PeopleModel('', '', '', '', '', '', '' , false); | |||
| public UserExtra: UserExtraModel = UserExtraModel.EmptyNew(); | |||
| public badgeAlign: BadgeAlign = { vertical: 'bottom', horizontal: 'end' }; | |||
| constructor(private ps: PeopleService, private auth: AuthService, private router: Router) { } | |||
| ngOnInit(): void { | |||
| this.ps.getPeopleById(this.peopleId).subscribe( | |||
| this.ps.getPeopleById(this.PeopleId).subscribe( | |||
| resp => { | |||
| this.contact = new PeopleModel(resp.Id, resp.First, resp.Last, resp.Middle, resp.Title, resp.Display, resp.Nick, resp.Enabled); | |||
| } | |||
| ); | |||
| this.ps.getPeopleExtraById(this.PeopleId).subscribe( | |||
| resp => { | |||
| this.contact = new PeopleModel(resp.Id, resp.First, resp.Last, resp.Middle, resp.Title, resp.Display, resp.Nick); | |||
| // console.log(this.contact); | |||
| this.UserExtra.Copy(resp); | |||
| } | |||
| ); | |||
| } | |||
| photoURL(): string { | |||
| if (this.contact === undefined ) { return ''; } | |||
| const url = this.auth.getUrl('avatar/') + this.contact.Id; | |||
| const url = 'url(' + this.auth.getUrl('avatar/') + this.contact.Id + ')'; | |||
| return url; | |||
| } | |||
| public bgPhoto(): string { | |||
| if ( !this.contact.Enabled ){ | |||
| return 'url("../../assets/img/bg-disabled-card.jpg")'; | |||
| } | |||
| switch (this.UserExtra.Role) { | |||
| case 'broker': | |||
| return 'url("../../assets/img/bg-client-card.jpg")'; | |||
| case 'user': | |||
| return 'url("../../assets/img/bg-user-card.jpg")'; | |||
| case 'people': | |||
| return 'url("../../assets/img/bg-broker-card.jpg")'; | |||
| case 'admin': | |||
| return 'url("../../assets/img/bg-admin-card.jpg")'; | |||
| } | |||
| } | |||
| public onButtonClick(): void { | |||
| this.router.navigate(['/profile/' + this.contact.Id]); | |||
| } | |||
| public onSelectedChange(e: boolean): void { | |||
| this.ps.enableUser(e, this.PeopleId).subscribe( | |||
| resp => { | |||
| this.contact.Enabled = resp; | |||
| }); | |||
| } | |||
| } | |||
| @@ -138,7 +138,8 @@ export class PeopleSelectComponent implements OnInit, ControlValueAccessor { | |||
| ppl.Middle, | |||
| ppl.Title, | |||
| ppl.Display, | |||
| ppl.Nick | |||
| ppl.Nick, | |||
| ppl.Enabled | |||
| ); | |||
| console.log('got search result ', person); | |||
| this.searchResult.push(person); // make sure it's available for selection, thus proper display | |||
| @@ -46,7 +46,7 @@ | |||
| <ng-container > | |||
| <fieldset class="k-form-fieldset"> | |||
| <kendo-formfield> | |||
| <kendo-label [for]="First" text="First Name (only Admin can change)"></kendo-label> | |||
| <kendo-label [for]="First" text="First Name "></kendo-label> | |||
| <kendo-textbox kendoTextBox #First name="First" [(ngModel)]="People.First" | |||
| > </kendo-textbox> | |||
| <kendo-formerror>First name is required</kendo-formerror> | |||
| @@ -54,7 +54,7 @@ | |||
| <div class="vertical-spacer"></div> | |||
| <kendo-formfield> | |||
| <kendo-label [for]="Last" text="Last Name (only Admin can change)"></kendo-label> | |||
| <kendo-label [for]="Last" text="Last Name "></kendo-label> | |||
| <kendo-textbox kendoTextBox #Last name="Last" [(ngModel)]="People.Last" | |||
| ></kendo-textbox> | |||
| <kendo-formerror>Last Name is required</kendo-formerror> | |||
| @@ -70,6 +70,13 @@ | |||
| </kendo-formfield> | |||
| <div class="vertical-spacer"></div> | |||
| <kendo-formfield> | |||
| Enable <kendo-switch name="Enabled" [(ngModel)]="People.Enabled" | |||
| > </kendo-switch> Disable | |||
| </kendo-formfield> | |||
| <div class="vertical-spacer"></div> | |||
| </fieldset> | |||
| </ng-container> | |||
| <div class="k-form-buttons k-buttons-end"> | |||
| @@ -46,15 +46,19 @@ | |||
| <div *ngIf="showPassword" class="col-sm-12"> | |||
| <div class="vertical-spacer" ><hr></div> | |||
| <app-change-password #changePassword [PeopleId]="People.Id" ></app-change-password> | |||
| <div *ngIf="showAdminTool" class="admin-panel dangerous" [ngStyle]="{'height.px': deleteHeight}"> | |||
| </div> | |||
| <div *ngIf="showAdminTool" class="col-sm-12"> | |||
| <div class="admin-panel dangerous" [ngStyle]="{'height.px': deleteHeight}"> | |||
| <div class="admin-label"> | |||
| <kendo-switch | |||
| <kendo-switch *ngIf="countDownNumber<=0" | |||
| [(ngModel)]="warnDelete" | |||
| [ngModelOptions]="{standalone: true}" | |||
| (valueChange)="onWarnDelete($event)" | |||
| ></kendo-switch> Remove this person | |||
| ></kendo-switch> <span *ngIf="countDownNumber<=0"> Remove this person </span> | |||
| <kendo-progressbar style="width:100%" *ngIf="countDownNumber>0" [label]="label" | |||
| [value]="countDownNumber"></kendo-progressbar> | |||
| </div> | |||
| <kendo-icon *ngIf="warnDelete" name="exception" [size]="'large'"></kendo-icon> | |||
| <span *ngIf="warnDelete"> You confirm to delete EVERY-thing related to this person </span> | |||
| <button *ngIf="warnDelete" kendoButton class="k-button " | |||
| @@ -45,6 +45,13 @@ export class ProfileComponent implements OnInit { | |||
| // delete entire people | |||
| public warnDelete = false; | |||
| public deleteHeight = 25; | |||
| private countDownNumber = -1; | |||
| private timer = null; | |||
| public label = { | |||
| visible: false, | |||
| position: 'start', | |||
| format: 'percent' | |||
| }; | |||
| // | |||
| public isValidPeople = true; | |||
| public isValidBroker = true; | |||
| @@ -103,13 +110,7 @@ export class ProfileComponent implements OnInit { | |||
| private setUserExtra(resp: UserExtraModel): void { | |||
| this.isValidBroker = resp.License !== ''; | |||
| this.UserExtra.BSB = resp.BSB; | |||
| this.UserExtra.ACC = resp.ACC; | |||
| this.UserExtra.License = resp.License; | |||
| this.UserExtra.Organization = resp.Organization; | |||
| this.UserExtra.Enabled = resp.Enabled; | |||
| this.UserExtra.Login = resp.Login; | |||
| this.UserExtra.Role = resp.Role; | |||
| this.UserExtra.Copy(resp); | |||
| this.role = this.UserExtra.Role; | |||
| } | |||
| @@ -129,16 +130,15 @@ export class ProfileComponent implements OnInit { | |||
| this.showUser = ['user', 'broker', 'admin'].includes(this.role); | |||
| this.showBroker = ['broker'].includes(this.role); | |||
| this.showAdmin = ['admin'].includes(this.role); | |||
| this.showPassword = true; | |||
| this.showPassword = this.showUser; | |||
| }else{ | |||
| this.showAdminTool = false; | |||
| this.showUser = ['user', 'broker', 'admin'].includes(this.role); | |||
| this.showBroker = ['broker'].includes(this.role); | |||
| this.showAdmin = ['admin'].includes(this.role); | |||
| this.showPassword = ['user', 'broker', 'admin'].includes(this.role);; | |||
| this.showPassword = ['user', 'broker', 'admin'].includes(this.role); | |||
| } | |||
| console.log( 'check pass', this); | |||
| } | |||
| private resetShowHide(): void { | |||
| @@ -158,7 +158,6 @@ export class ProfileComponent implements OnInit { | |||
| } | |||
| public onNewPeopleCreated(ppl: PeopleModel): void { | |||
| console.log(this.People); | |||
| this.updateShowHide(); | |||
| } | |||
| @@ -235,8 +234,27 @@ export class ProfileComponent implements OnInit { | |||
| if (status) { | |||
| this.deleteHeight = 100; | |||
| this.countDown(); | |||
| }else{ | |||
| this.deleteHeight = 30; | |||
| } | |||
| } | |||
| private countDown(): void { | |||
| if ( ! this.timer ) { | |||
| clearTimeout(this.timer); | |||
| this.timer = null; | |||
| } | |||
| this.countDownNumber = 100; | |||
| this.timer = setInterval(() => { | |||
| this.countDownNumber --; | |||
| if ( this.countDownNumber <= 0 ){ | |||
| clearTimeout(this.timer); | |||
| this.timer = null; | |||
| this.warnDelete = false; | |||
| this.deleteHeight = 30; | |||
| } | |||
| }, 100); // 3ms, total 300ms = 5 seconds | |||
| } | |||
| } | |||
| @@ -19,13 +19,6 @@ | |||
| </kendo-formfield> | |||
| <div class="vertical-spacer"></div> | |||
| <kendo-formfield *ngIf="showAdmin "> | |||
| <label class="k-label">Allow Login | |||
| <input type="checkbox" name="enabled" kendoCheckBox formControlName="Enabled"/> | |||
| </label> | |||
| </kendo-formfield> | |||
| <div class="vertical-spacer"></div> | |||
| </fieldset> | |||
| </ng-container> | |||
| <div class="k-form-buttons k-buttons-end" *ngIf="showSubmit()"> | |||
| @@ -36,25 +36,21 @@ export class UserProfileComponent implements OnInit { | |||
| this.People.Id = this.auth.loggedIn.User.Id; | |||
| this.UserExtra = this.auth.loggedIn.UserExtra; | |||
| } | |||
| console.log(this); | |||
| this.UserForm = new FormGroup({ | |||
| Login: new FormControl({value: this.UserExtra.Login, disabled: ! this.showAdmin }, | |||
| [Validators.required, Validators.email], | |||
| [asyncValidatorLoginAvailable(this.auth, this.UserExtra.Login)] ), | |||
| Enabled: new FormControl({value: this.UserExtra.Enabled, disabled: this.isCurrentUser}), | |||
| [asyncValidatorLoginAvailable(this.auth, this.UserExtra.Login)] ) | |||
| }); | |||
| } | |||
| public save(): void { | |||
| const ex = new UserExtraModel(this.UserExtra); | |||
| ex.Login = this.UserForm.get('Login').value; | |||
| ex.Enabled = this.UserForm.get('Enabled').value; | |||
| this.http.post<UserExtraModel>(this.auth.getUrl('user/' + this.People.Id), ex).subscribe( | |||
| resp => { | |||
| if ( resp.Login === ex.Login && resp.Enabled === ex.Enabled) { | |||
| if ( resp.Login === ex.Login) { | |||
| this.UserExtra.Login = resp.Login; | |||
| this.UserExtra.Enabled = resp.Enabled; | |||
| this.msgBox.Show('Successfully Changed'); | |||
| }else{ | |||
| this.msgBox.Show('Login not Changed: ' + resp ); | |||
| @@ -33,7 +33,9 @@ export class AuthService { | |||
| sfm.session, | |||
| sfm.sessionExpire, | |||
| sfm.role, | |||
| new PeopleModel(sfm.User.Id, sfm.User.First, sfm.User.Last, sfm.User.Middle, sfm.User.Title, sfm.User.Display, sfm.User.Nick) | |||
| new PeopleModel( | |||
| sfm.User.Id, sfm.User.First, sfm.User.Last, sfm.User.Middle, | |||
| sfm.User.Title, sfm.User.Display, sfm.User.Nick, sfm.User.Enabled) | |||
| ); | |||
| if ( sfm.UserExtra !== undefined ) { | |||
| @@ -75,7 +77,8 @@ export class AuthService { | |||
| responseData.User.Middle, | |||
| responseData.User.Title, | |||
| responseData.User.Display, | |||
| responseData.User.Nick | |||
| responseData.User.Nick, | |||
| responseData.User.Enabled, | |||
| ); | |||
| if (responseData.UserExtra !== undefined ) { | |||
| @@ -72,4 +72,8 @@ export class PeopleService { | |||
| return this.http.delete<UserExtraModel>(this.auth.getUrl('broker/' + id), {}); | |||
| } | |||
| public enableUser(enable: boolean, id: string): Observable<boolean> { | |||
| return this.http.post<boolean>(this.auth.getUrl('user-enable/' + id), enable); | |||
| } | |||
| } | |||