From 211b076d2b3820746ef0b058fd5233a8fd6b7718 Mon Sep 17 00:00:00 2001 From: tanshu Date: Thu, 21 Jan 2021 08:01:59 +0530 Subject: [PATCH] Compliance list now shows next hearing date Search added to case list Export added to compliance and cause list --- luthor/luthor/routers/compliance_list.py | 1 + luthor/luthor/schemas/compliance_list.py | 7 ++++ .../cases/case-list/case-list-datasource.ts | 31 ++++++++++++-- .../cases/case-list/case-list.component.html | 16 ++------ .../cases/case-list/case-list.component.ts | 17 +++++--- .../app/cause-list/cause-list-datasource.ts | 2 +- .../app/cause-list/cause-list.component.html | 3 ++ .../app/cause-list/cause-list.component.ts | 40 +++++++++++++++++++ .../compliance-list.component.html | 9 +++++ .../compliance-list.component.ts | 32 ++++++++++++++- .../app/compliance-list/compliance-list.ts | 2 + 11 files changed, 137 insertions(+), 23 deletions(-) diff --git a/luthor/luthor/routers/compliance_list.py b/luthor/luthor/routers/compliance_list.py index 407f8d6..c125d36 100644 --- a/luthor/luthor/routers/compliance_list.py +++ b/luthor/luthor/routers/compliance_list.py @@ -54,6 +54,7 @@ def case_info(item: Case) -> List[schemas.ComplianceList]: title=item.title, proceedings=h.proceedings if h.proceedings is not None else "", complianceDate=h.compliance_date, + nextHearingDate=h.next_hearing_date, ) for h in item.hearings if h.compliance_date is not None and h.compliance_done is False diff --git a/luthor/luthor/schemas/compliance_list.py b/luthor/luthor/schemas/compliance_list.py index 9bdd801..4f83bc6 100644 --- a/luthor/luthor/schemas/compliance_list.py +++ b/luthor/luthor/schemas/compliance_list.py @@ -15,6 +15,7 @@ class ComplianceList(BaseModel): title: str proceedings: str compliance_date: date + next_hearing_date: date class Config: anystr_strip_whitespace = True @@ -26,3 +27,9 @@ class ComplianceList(BaseModel): if isinstance(value, date): return value return datetime.strptime(value, "%d-%b-%Y").date() + + @validator("next_hearing_date", pre=True) + def parse_next_hearing_date(cls, value): + if isinstance(value, date): + return value + return datetime.strptime(value, "%d-%b-%Y").date() diff --git a/otis/src/app/cases/case-list/case-list-datasource.ts b/otis/src/app/cases/case-list/case-list-datasource.ts index 1ad33e9..567e512 100644 --- a/otis/src/app/cases/case-list/case-list-datasource.ts +++ b/otis/src/app/cases/case-list/case-list-datasource.ts @@ -8,31 +8,54 @@ import { Case } from '../../core/case'; export class CaseListDataSource extends DataSource { private dataValues: Case[] = []; - private data: Observable = new Observable(); - constructor(public d: Observable, private paginator?: MatPaginator) { + private searchValues = ''; + private data: Observable; + private search: Observable; + constructor( + public d: Observable, + public s: Observable, + private paginator?: MatPaginator, + ) { super(); this.data = d.pipe(tap((x) => (this.dataValues = x))); + this.search = s.pipe(tap((x) => (this.searchValues = x))); } connect(): Observable { - const dataMutations: (Observable | EventEmitter)[] = [this.data]; + const dataMutations: (Observable | Observable | EventEmitter)[] = [ + this.data, + this.search, + ]; if (this.paginator) { dataMutations.push((this.paginator as MatPaginator).page); } return merge(...dataMutations) .pipe( + map(() => this.getFilteredData([...this.dataValues])), tap((x: Case[]) => { if (this.paginator) { this.paginator.length = x.length; } }), ) - .pipe(map((x: Case[]) => this.getPagedData(this.dataValues))); + .pipe(map((x: Case[]) => this.getPagedData(x))); } disconnect() {} + private getFilteredData(data: Case[]): Case[] { + return this.searchValues.split(' ').reduce( + (p: Case[], c: string) => + p.filter((x) => { + const accountString = `${x.caseSource.prefix}-${x.officeFileNumber} ${x.courtCaseNumber} ${x.year} ${x.title} + ${x.docketNumber} ${x.remarks}`.toLowerCase(); + return accountString.indexOf(c) !== -1; + }), + Object.assign([], data), + ); + } + private getPagedData(data: Case[]) { if (this.paginator === undefined) { return data; diff --git a/otis/src/app/cases/case-list/case-list.component.html b/otis/src/app/cases/case-list/case-list.component.html index af12d84..24c2d27 100644 --- a/otis/src/app/cases/case-list/case-list.component.html +++ b/otis/src/app/cases/case-list/case-list.component.html @@ -23,6 +23,10 @@ + + Search + + @@ -48,12 +52,6 @@ {{ row.courtCaseNumber }} - - - Connected Case - {{ row.caseConnectedWith }} - - Forum @@ -78,12 +76,6 @@ {{ row.courtStatus?.name }} - - - Office Status - {{ row.officeStatus?.name }} - - Remarks diff --git a/otis/src/app/cases/case-list/case-list.component.ts b/otis/src/app/cases/case-list/case-list.component.ts index 56c2b1a..efc934f 100644 --- a/otis/src/app/cases/case-list/case-list.component.ts +++ b/otis/src/app/cases/case-list/case-list.component.ts @@ -3,7 +3,7 @@ import { FormBuilder, FormControl, FormGroup } from '@angular/forms'; import { MatPaginator } from '@angular/material/paginator'; import { ActivatedRoute } from '@angular/router'; import { Observable } from 'rxjs'; -import { distinctUntilChanged, startWith, switchMap, tap } from 'rxjs/operators'; +import { debounceTime, distinctUntilChanged, startWith, switchMap, tap } from 'rxjs/operators'; import { Case } from '../../core/case'; import { CaseSource } from '../../core/case-source'; @@ -21,18 +21,17 @@ export class CaseListComponent implements OnInit { form: FormGroup; caseSources: CaseSource[] = []; list: Observable = new Observable(); - dataSource: CaseListDataSource = new CaseListDataSource(this.list); + search: Observable; + dataSource: CaseListDataSource; /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ displayedColumns = [ 'officeFileNumber', 'title', 'courtCaseNumber', - 'caseConnectedWith', 'court', 'appearOnBehalfOf', 'nextHearingDate', 'courtStatus', - 'officeStatus', 'remarks', 'receiptDate', ]; @@ -41,7 +40,14 @@ export class CaseListComponent implements OnInit { // Create form this.form = this.fb.group({ caseSource: '', + search: '', }); + this.search = (this.form.get('search') as FormControl).valueChanges.pipe( + startWith(''), + debounceTime(150), + distinctUntilChanged(), + ); + this.dataSource = new CaseListDataSource(this.list, this.search); } ngOnInit() { @@ -50,6 +56,7 @@ export class CaseListComponent implements OnInit { this.caseSources = data.caseSources; this.form.setValue({ caseSource: '08efc7cc-e4a1-4d24-bcba-58ca9bc29994', + search: '', }); this.list = (this.form.get('caseSource') as FormControl).valueChanges.pipe( startWith('08efc7cc-e4a1-4d24-bcba-58ca9bc29994'), @@ -57,7 +64,7 @@ export class CaseListComponent implements OnInit { switchMap((x) => this.ser.list(x)), ); }); - this.dataSource = new CaseListDataSource(this.list, this.paginator); + this.dataSource = new CaseListDataSource(this.list, this.search, this.paginator); } nextHearingDate(row: Case): string { diff --git a/otis/src/app/cause-list/cause-list-datasource.ts b/otis/src/app/cause-list/cause-list-datasource.ts index 3659adf..6bb30d6 100644 --- a/otis/src/app/cause-list/cause-list-datasource.ts +++ b/otis/src/app/cause-list/cause-list-datasource.ts @@ -7,7 +7,7 @@ import { map, tap } from 'rxjs/operators'; import { Case } from '../core/case'; export class CauseListDatasource extends DataSource { - private dataValues: Case[] = []; + public dataValues: Case[] = []; private data: Observable = new Observable(); constructor(public d: Observable, private paginator?: MatPaginator) { super(); diff --git a/otis/src/app/cause-list/cause-list.component.html b/otis/src/app/cause-list/cause-list.component.html index a16fb5f..e4ae623 100644 --- a/otis/src/app/cause-list/cause-list.component.html +++ b/otis/src/app/cause-list/cause-list.component.html @@ -36,6 +36,9 @@ + diff --git a/otis/src/app/cause-list/cause-list.component.ts b/otis/src/app/cause-list/cause-list.component.ts index e7418ef..1942ac5 100644 --- a/otis/src/app/cause-list/cause-list.component.ts +++ b/otis/src/app/cause-list/cause-list.component.ts @@ -108,4 +108,44 @@ export class CauseListComponent implements OnInit { finishDate: moment(formModel.finishDate).format('DD-MMM-YYYY'), }); } + + exportCsv() { + const csvData = new Blob([this.toCsv(this.dataSource.dataValues)], { + type: 'text/csv;charset=utf-8;', + }); + const link = document.createElement('a'); + link.href = window.URL.createObjectURL(csvData); + link.setAttribute('download', 'cause-list.csv'); + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + } + + toCsv(data: Case[]): string { + const header = [ + 'File No.', + 'Title', + 'Court Case Number', + 'Forum', + 'Court / Item Number', + 'Bench', + 'Proceedings', + 'Next Hearing', + 'On Behalf of', + 'Other Hearings', + 'Remarks', + ]; + const csv = data.map( + (row) => + `${row.caseSource.prefix}-${row.officeFileNumber}\t${row.title}\t${row.courtCaseNumber}\t${ + row.court?.name + }\t${this.courtNumber(row)} / ${this.itemNumber(row)}\t${this.bench( + row, + )}\t${this.proceedings(row)}\t${this.nextHearingDate(row)}\t${ + row.appearOnBehalfOf + }\t${this.otherHearingDates(row)}\t${row.remarks}`, + ); + csv.unshift(header.join('\t')); + return csv.join('\r\n'); + } } diff --git a/otis/src/app/compliance-list/compliance-list.component.html b/otis/src/app/compliance-list/compliance-list.component.html index ba7c503..cd23f77 100644 --- a/otis/src/app/compliance-list/compliance-list.component.html +++ b/otis/src/app/compliance-list/compliance-list.component.html @@ -1,6 +1,9 @@ Compliances + @@ -30,6 +33,12 @@ {{ row.complianceDate }} + + + Next Hearing Date + {{ row.nextHearingDate }} + + diff --git a/otis/src/app/compliance-list/compliance-list.component.ts b/otis/src/app/compliance-list/compliance-list.component.ts index b13ae93..da1158d 100644 --- a/otis/src/app/compliance-list/compliance-list.component.ts +++ b/otis/src/app/compliance-list/compliance-list.component.ts @@ -4,6 +4,8 @@ import { MatPaginator } from '@angular/material/paginator'; import { ActivatedRoute, Router } from '@angular/router'; import * as moment from 'moment'; +import { Case } from '../core/case'; + import { ComplianceList } from './compliance-list'; import { ComplianceListDatasource } from './compliance-list-datasource'; @@ -17,7 +19,13 @@ export class ComplianceListComponent implements OnInit { info: ComplianceList[] = []; dataSource: ComplianceListDatasource = new ComplianceListDatasource(this.info); /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ - displayedColumns = ['officeFileNumber', 'title', 'proceedings', 'complianceDate']; + displayedColumns = [ + 'officeFileNumber', + 'title', + 'proceedings', + 'complianceDate', + 'nextHearingDate', + ]; constructor(private route: ActivatedRoute) {} @@ -29,4 +37,26 @@ export class ComplianceListComponent implements OnInit { this.dataSource = new ComplianceListDatasource(this.info, this.paginator); }); } + + exportCsv() { + const csvData = new Blob([this.toCsv(this.info)], { + type: 'text/csv;charset=utf-8;', + }); + const link = document.createElement('a'); + link.href = window.URL.createObjectURL(csvData); + link.setAttribute('download', 'cause-list.csv'); + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + } + + toCsv(data: ComplianceList[]): string { + const header = ['File No.', 'Title', 'Proceedings', 'Next Hearing', 'Compliance Date']; + const csv = data.map( + (row) => + `${row.officeFileNumber}\t${row.title}\t${row.proceedings}\t${row.nextHearingDate}\t${row.complianceDate}`, + ); + csv.unshift(header.join('\t')); + return csv.join('\r\n'); + } } diff --git a/otis/src/app/compliance-list/compliance-list.ts b/otis/src/app/compliance-list/compliance-list.ts index a23e93c..76e3800 100644 --- a/otis/src/app/compliance-list/compliance-list.ts +++ b/otis/src/app/compliance-list/compliance-list.ts @@ -6,6 +6,7 @@ export class ComplianceList { title: string; proceedings: string; complianceDate: string; + nextHearingDate: string; public constructor(init?: Partial) { this.id = ''; @@ -15,6 +16,7 @@ export class ComplianceList { this.title = ''; this.proceedings = ''; this.complianceDate = ''; + this.nextHearingDate = ''; Object.assign(this, init); } }