浏览代码

Add filters to partner table

master
Adwaith Rao 3 年前
父节点
当前提交
031fa413e9
共有 5 个文件被更改,包括 186 次插入54 次删除
  1. +48
    -18
      src/app/dashboard/table/table.component.html
  2. +34
    -14
      src/app/dashboard/table/table.component.scss
  3. +102
    -20
      src/app/dashboard/table/table.component.ts
  4. +1
    -1
      src/app/services/partner-profile.service.ts
  5. +1
    -1
      src/shared

+ 48
- 18
src/app/dashboard/table/table.component.html 查看文件

@@ -1,6 +1,7 @@
<div class="subpage"> <div class="subpage">
<header class="main-header"> <header class="main-header">
<h2> All Partners <ng-container *ngIf="userData">({{ userData.length }})</ng-container> </h2>
<h2> All Partners <ng-container *ngIf="userData">({{ userData.length }})</ng-container>
</h2>
</header> </header>


<div class="card"> <div class="card">
@@ -11,7 +12,8 @@
<input type="text" placeholder="Partner name" [(ngModel)]="searchText" (input)="getFilteredData()"> <input type="text" placeholder="Partner name" [(ngModel)]="searchText" (input)="getFilteredData()">
<label> Search </label> <label> Search </label>
</div> </div>
<button class="button" (click)="shouldHaveImplementationData = !shouldHaveImplementationData; getFilteredData()">
<button class="button"
(click)="shouldHaveImplementationData = !shouldHaveImplementationData; getFilteredData()">
<ng-container *ngIf="!shouldHaveImplementationData"> <ng-container *ngIf="!shouldHaveImplementationData">
Partners with implmentation data Partners with implmentation data
</ng-container> </ng-container>
@@ -19,46 +21,72 @@
Show all Partners Show all Partners
</ng-container> </ng-container>
</button> </button>
<button class="button" (click)="showExportOptions = true"> <img src="assets/export.svg" alt=""> Export </button>
<button class="button" (click)="showExportOptions = true"> <img src="assets/export.svg" alt=""> Export
</button>
<button class="button"> <img src="assets/filter.svg" alt=""> Filter </button> <button class="button"> <img src="assets/filter.svg" alt=""> Filter </button>
</div> </div>


<div class="filter-row">
<div class="explainer">Filters:</div>
<ng-select [items]="communities" [multiple]="true" [closeOnSelect]="false" bindLabel="name" bindValue="name"
placeholder="Communities" (change)="getFilteredData()" [(ngModel)]="filteredCommunities">
</ng-select>
<ng-select [items]="countries" [multiple]="true" [closeOnSelect]="false" bindLabel="name" bindValue="name"
placeholder="Countries" (change)="getFilteredData()" [(ngModel)]="filteredCountries">
</ng-select>
<ng-select *ngIf="filteredCountries.includes('India')" [items]="states" [multiple]="true"
[closeOnSelect]="false" bindLabel="name" bindValue="name" placeholder="States"
(change)="updateDistricts($event)" [(ngModel)]="filteredStates">
</ng-select>
<ng-select *ngIf="filteredCountries.includes('India') && districts.length > 0" [items]="districts"
[multiple]="true" [closeOnSelect]="false" bindLabel="name" bindValue="name" placeholder="Districts"
(change)="getFilteredData()" [(ngModel)]="filteredDistricts">
</ng-select>
<ng-select [items]="partnerTypes" [multiple]="true" [closeOnSelect]="false" placeholder="Types"
(change)="getFilteredData()" [(ngModel)]="filteredPartnerTypes">
</ng-select>
</div>

<ng-container *ngIf="showExportOptions"> <ng-container *ngIf="showExportOptions">
<div class="export-options"> <div class="export-options">


<div class="sub-options" *ngIf="shouldHaveImplementationData"> <div class="sub-options" *ngIf="shouldHaveImplementationData">
<header> <header>
<h5>Select Data Type</h5> <h5>Select Data Type</h5>
</header>
</header>
<div> <div>
<span>Profile Data</span> <span>Profile Data</span>
<div class="radioButton" [ngClass]="{'active' : isProfileData}" (click) = "isProfileData = true; isImplementationData=false; isBothData=false" ></div>
<div class="radioButton" [ngClass]="{'active' : isProfileData}"
(click)="isProfileData = true; isImplementationData=false; isBothData=false"></div>
</div> </div>
<div> <div>
<span>Implementation Data</span> <span>Implementation Data</span>
<div class="radioButton" [ngClass]="{'active' : isImplementationData}" (click) = "isImplementationData= true; isProfileData=false; isBothData=false" ></div>
<div class="radioButton" [ngClass]="{'active' : isImplementationData}"
(click)="isImplementationData= true; isProfileData=false; isBothData=false"></div>
</div> </div>
<div> <div>
<span>Both</span> <span>Both</span>
<div class="radioButton" [ngClass]="{'active' : isBothData}" (click)="isBothData = true; isProfileData = false; isImplementationData=false"></div>
<div class="radioButton" [ngClass]="{'active' : isBothData}"
(click)="isBothData = true; isProfileData = false; isImplementationData=false"></div>
</div> </div>
</div> </div>
<header> <header>
<h5> Export as </h5> <h5> Export as </h5>
</header> </header>
<div class="options">
<button (click) ="exportProfileData('CSV')" class="button"> CSV </button>
<button (click) ="exportProfileData('XLSX')" class="button"> Excel </button>
<div class="options">
<button (click)="exportProfileData('CSV')" class="button"> CSV </button>
<button (click)="exportProfileData('XLSX')" class="button"> Excel </button>
</div> </div>
</div> </div>


</ng-container> </ng-container>


<section class="table"> <section class="table">
<header> <header>
<div class="col"> <input type="checkbox" [checked]="isAllInputChecked()" (change)="selectAllPartner()"> Select </div>
<div class="col"> <input type="checkbox" [checked]="isAllInputChecked()" (change)="selectAllPartner()">
Select </div>
<div class="col"> Name </div> <div class="col"> Name </div>
<div class="col"> Primary Disctrict &amp; State </div> <div class="col"> Primary Disctrict &amp; State </div>
<div class="col"> Type </div> <div class="col"> Type </div>
@@ -68,14 +96,15 @@
</header> </header>
<section class="data"> <section class="data">
<div class="row" *ngFor="let partner of tempUserData"> <div class="row" *ngFor="let partner of tempUserData">
<div class="col"> <input type="checkbox" [checked]="isInputChecked(partner)" (change)="selectPartner(partner)"> </div>
<div class="col"> <input type="checkbox" [checked]="isInputChecked(partner)"
(change)="selectPartner(partner)"> </div>
<div class="col" (click)="showPartnerDetails(partner)"> <div class="col" (click)="showPartnerDetails(partner)">
{{ partner.organizationBasicInfo.name }} {{ partner.organizationBasicInfo.name }}
</div> </div>
<div class="col" (click)="showPartnerDetails(partner)"> <div class="col" (click)="showPartnerDetails(partner)">
{{ partner.detailedProfile.district }}, {{ partner.detailedProfile.state }} {{ partner.detailedProfile.district }}, {{ partner.detailedProfile.state }}
</div> </div>
<div class="col" (click)="showPartnerDetails(partner)">
<div class="col" (click)="showPartnerDetails(partner)">
{{ partner.organizationBasicInfo.type }} {{ partner.organizationBasicInfo.type }}
</div> </div>
<div class="col"> <div class="col">
@@ -88,12 +117,13 @@
<div class="col"> <div class="col">
<div> {{ partner.primaryContact.name }} </div> <div> {{ partner.primaryContact.name }} </div>
<a href="mailTo:{{partner.primaryContact.email}}"> {{ partner.primaryContact.email }} </a> <a href="mailTo:{{partner.primaryContact.email}}"> {{ partner.primaryContact.email }} </a>
<a href="tel:{{partner.primaryContact.contactNumber}}"> {{ partner.primaryContact.contactNumber }} </a>
<a href="tel:{{partner.primaryContact.contactNumber}}"> {{ partner.primaryContact.contactNumber
}} </a>
</div> </div>
</div>
</div>
<div class="row" *ngIf="userData.length > tempUserData.length"> <div class="row" *ngIf="userData.length > tempUserData.length">
<button class="button" (click)="loadMore()"> Load More </button> <button class="button" (click)="loadMore()"> Load More </button>
</div>
</div>
</section> </section>
</section> </section>




+ 34
- 14
src/app/dashboard/table/table.component.scss 查看文件

@@ -27,6 +27,23 @@
} }
} }


.filter-row {
padding: 5px 15px;
display: flex;
align-items: center;

.explainer {
flex-basis: 150px;
font-style: italic;
color: silver;
}

ng-select {
flex-grow: 1;
margin: 0 5px;
}
}

.card { .card {
position: relative; position: relative;


@@ -71,7 +88,7 @@


.sub-options { .sub-options {


div{
div {
margin: 3px 0; margin: 3px 0;
display: flex; display: flex;
align-items: center; align-items: center;
@@ -81,12 +98,12 @@
color: var(--input-border); color: var(--input-border);




span{
span {
width: 85%; width: 85%;
} }
} }
.radioButton{
.radioButton {
border: 2px solid var(--input-border); border: 2px solid var(--input-border);
width: 15px; width: 15px;
height: 15px; height: 15px;
@@ -94,7 +111,7 @@
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
&::before { &::before {
content: ''; content: '';
display: block; display: block;
@@ -103,18 +120,18 @@
border-radius: inherit; border-radius: inherit;
background-color: white; background-color: white;
} }
&.active { &.active {
border-color: var(--input-border); border-color: var(--input-border);
&::before { &::before {
background-color: var(--input-border); background-color: var(--input-border);
} }
} }
} }
} }


button { button {
border: 2px solid var(--input-border); border: 2px solid var(--input-border);
@@ -126,7 +143,7 @@
font-weight: 500; font-weight: 500;
} }


} }


.table { .table {
@@ -135,13 +152,14 @@
line-height: 1.8; line-height: 1.8;
letter-spacing: 0.5px; letter-spacing: 0.5px;


header, .row {
header,
.row {
display: flex; display: flex;
flex-wrap: nowrap; flex-wrap: nowrap;
align-items: center; align-items: center;
padding: 0 10px; padding: 0 10px;


.col {
.col {
width: calc(100% / 7); width: calc(100% / 7);
font-size: 14px; font-size: 14px;


@@ -149,7 +167,9 @@
margin-right: 5px; margin-right: 5px;
} }


p, a, &>div {
p,
a,
&>div {
display: block; display: block;
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
@@ -175,7 +195,7 @@


&:nth-child(5) { &:nth-child(5) {
width: 100px; width: 100px;
}
}
} }
} }




+ 102
- 20
src/app/dashboard/table/table.component.ts 查看文件

@@ -3,6 +3,9 @@ import { PartnerProfileService } from '../../services/partner-profile.service';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import * as Papa from 'papaparse'; import * as Papa from 'papaparse';
import * as XLSX from 'xlsx' import * as XLSX from 'xlsx'
import { UserData, UserDataOption } from 'src/shared/structure/user';
import { COUNTRIES, STATES, COMMUNITIES } from 'src/shared/data/form-options';
import { PartnerType, PARTNER_MAPPING } from 'src/shared/data/partner-mapping';


type exportType = "CSV" | "XLSX"; type exportType = "CSV" | "XLSX";


@@ -13,16 +16,28 @@ type exportType = "CSV" | "XLSX";
}) })


export class TableComponent implements OnInit { export class TableComponent implements OnInit {
userData: Array<any> = [];
tempUserData: Array<any> = [];
userData: Array<UserData> = [];
tempUserData: Array<UserData> = [];
showExportOptions: boolean = false; showExportOptions: boolean = false;
shouldHaveImplementationData: boolean = false; shouldHaveImplementationData: boolean = false;
searchText: string = ''; searchText: string = '';
selectedPartnerList: Array<any> = [];
selectedPartnerList: Array<UserData> = [];
isProfileData: boolean = true; isProfileData: boolean = true;
isImplementationData: boolean = false; isImplementationData: boolean = false;
isBothData: boolean = false; isBothData: boolean = false;


communities = COMMUNITIES;
countries = COUNTRIES;
states = STATES;
districts: Array<UserDataOption> = [];
partnerTypes = [PartnerType.ENABLER, PartnerType.IMPLEMENTER, PartnerType.PROVIDER];

filteredCommunities: Array<string> = [];
filteredCountries: Array<string> = [];
filteredStates: Array<string> = [];
filteredDistricts: Array<string> = [];
filteredPartnerTypes: Array<PartnerType> = [];

exportData: Array<any> = []; exportData: Array<any> = [];
exportSurveyCtoData: Array<any> = []; exportSurveyCtoData: Array<any> = [];


@@ -35,33 +50,100 @@ export class TableComponent implements OnInit {
this.getFilteredData(); this.getFilteredData();
} }


updateDistricts(states: Array<{ districts: Array<UserDataOption> }>) {
console.log(states);
this.districts = states.map(state => state.districts).flat();
this.getFilteredData();
}

getFilteredData() { getFilteredData() {
this.partnerProfileService.getPartnersData().then((data: any) => {
this.partnerProfileService.getPartnersData().then((data) => {
this.userData = data; this.userData = data;


if (this.shouldHaveImplementationData) {
this.userData = this.userData.filter(user => {
return (user.surveyCtoData.hiiData && user.surveyCtoData.hiiData.length > 0) ||
const searchText = this.searchText.toLowerCase().trim();

const filteredCommunitySet = new Set(this.filteredCommunities);
const filteredCountrySet = new Set(this.filteredCountries);
const filteredStateSet = new Set(this.filteredStates);
const filteredDistrictSet = new Set(this.filteredDistricts);
const filteredPartnerTypeSet = new Set(this.filteredPartnerTypes);

this.userData = this.userData.filter(user => {

if (this.shouldHaveImplementationData) {
const hasImplementationData = (user.surveyCtoData.hiiData && user.surveyCtoData.hiiData.length > 0) ||
(user.surveyCtoData.spData && user.surveyCtoData.spData.length > 0) || (user.surveyCtoData.spData && user.surveyCtoData.spData.length > 0) ||
(user.surveyCtoData.spSchemeData && user.surveyCtoData.spSchemeData.length > 0) (user.surveyCtoData.spSchemeData && user.surveyCtoData.spSchemeData.length > 0)
});
}


if (this.searchText) {
this.userData = this.userData.filter(user => {
return user.organizationBasicInfo.name && user.organizationBasicInfo.name.toLowerCase().trim().includes(this.searchText.toLowerCase().trim());
})
}
if (!hasImplementationData) {
return false;
}
}

if (filteredCommunitySet.size > 0) {
const communitiesForUser = user.detailedProfile.communities.map(community => community.name);
const hasCommunities = communitiesForUser.some(community => filteredCommunitySet.has(community));

if (!hasCommunities) {
return false;
}
}

if (filteredCountrySet.size > 0) {
const countriesForUser = user.detailedProfile.branchLocationCountries.map(country => country.name).concat(user.detailedProfile.partnerLocation);
const hasCountries = countriesForUser.some(country => filteredCountrySet.has(country));

if (!hasCountries) {
return false;
}
}

if (filteredStateSet.size > 0) {
const statesForUser = user.detailedProfile.states.map(state => state.name).concat(user.detailedProfile.state);
const hasStates = statesForUser.some(state => filteredStateSet.has(state));

if (!hasStates) {
return false;
}
}

if (filteredDistrictSet.size > 0) {
const districtsForUser = user.detailedProfile.districts.map(district => district.name).concat(user.detailedProfile.district);
const hasDistricts = districtsForUser.some(district => filteredDistrictSet.has(district));

if (!hasDistricts) {
return false;
}
}

if (filteredPartnerTypeSet.size > 0) {
const partnerTypeOfUser = PARTNER_MAPPING.find(mapping => mapping.portalId === user.portalId)?.type;
const hasPartnerType = partnerTypeOfUser && filteredPartnerTypeSet.has(partnerTypeOfUser);

if (!hasPartnerType) {
return false;
}
}


if (this.searchText) {
const hasSearchText = (!!user.organizationBasicInfo.name && user.organizationBasicInfo.name.toLowerCase().trim().includes(searchText));

if (!hasSearchText) {
return false;
}
}

return true;
});


this.partialLoad(this.userData.slice(0, 100)) this.partialLoad(this.userData.slice(0, 100))


console.log(this.userData);
}, (e) => console.log(e)); }, (e) => console.log(e));
} }


partialLoad(data: Array<any>) {
partialLoad(data: Array<UserData>) {
this.tempUserData = data; this.tempUserData = data;
console.log(this.tempUserData);
} }


loadMore() { loadMore() {
@@ -174,9 +256,9 @@ export class TableComponent implements OnInit {
"SP Name": spData.name, "SP Name": spData.name,
"SP Status": spData.status, "SP Status": spData.status,
'SP Reason Name': spData.reasonName, 'SP Reason Name': spData.reasonName,
"SP Female Number" : spData.femaleNo ? spData.femaleNo : '' ,
"SP Male Number" : spData.maleNo ? spData.maleNo : '',
"Tg Number" : spData.tgNo ? spData.tgNo : '',
"SP Female Number": spData.femaleNo ? spData.femaleNo : '',
"SP Male Number": spData.maleNo ? spData.maleNo : '',
"Tg Number": spData.tgNo ? spData.tgNo : '',
"SP TotalAggregation": spData.totalAggregation, "SP TotalAggregation": spData.totalAggregation,
"SP OtherRemarks": spData.otherRemarks, "SP OtherRemarks": spData.otherRemarks,
"SP RelevantDocuments": spData.relevantDocuments, "SP RelevantDocuments": spData.relevantDocuments,


+ 1
- 1
src/app/services/partner-profile.service.ts 查看文件

@@ -17,7 +17,7 @@ export class PartnerProfileService {
) { } ) { }


async getPartnersData() { async getPartnersData() {
return lastValueFrom(this.http.get(BASE_URL + '/user-data/?token=' + localStorage.getItem('token')));
return lastValueFrom(this.http.get<Array<UserData>>(BASE_URL + '/user-data/?token=' + localStorage.getItem('token')));
} }


async updatePartnerData(userData: UserData) { async updatePartnerData(userData: UserData) {


+ 1
- 1
src/shared

@@ -1 +1 @@
Subproject commit 98e1875b53e2b1612bd350141f86bf38866a5221
Subproject commit 6e14e2b89a7d2191840dc6a74d1322288e75af30

正在加载...
取消
保存