186 lines
6.4 KiB
TypeScript
186 lines
6.4 KiB
TypeScript
import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core';
|
|
import { ActivatedRoute } from '@angular/router';
|
|
|
|
import { SelectItem } from 'primeng/api';
|
|
import { Table } from 'primeng/table';
|
|
|
|
import { Customer } from '../models/customer.model';
|
|
import * as fromCustomers from '../reducers';
|
|
import * as customerActions from '../actions/customer.actions';
|
|
import { globals, OperationalStatus } from '@app/shared/global';
|
|
|
|
import { BaseComp } from '@app/shared/base/base.component';
|
|
import { CustomerCacheService } from '@app/domain/services/customer-cache.service';
|
|
import { ListReturnCacheService } from '@app/domain/services/list-return-cache.service';
|
|
import { FilterDefinition, FilterChangeEvent } from '@app/shared/dynamic-filter/dynamic-filter.component';
|
|
|
|
@Component({
|
|
selector: 'agm-customer-list',
|
|
templateUrl: './customer-list.component.html',
|
|
styleUrls: ['./customer-list.component.css']
|
|
})
|
|
export class CustomerListComponent extends BaseComp implements OnInit, OnDestroy {
|
|
readonly CREATED = 'createdAt';
|
|
readonly ACTIVE = OperationalStatus.ACTIVE;
|
|
readonly BILLABLE = 'billable';
|
|
readonly PARTNER = 'partner';
|
|
readonly PARTNER_NAME = 'partnerName';
|
|
|
|
customers: Array<Customer>;
|
|
curCust: Customer;
|
|
|
|
@ViewChild("dt") dt: Table;
|
|
|
|
statuses: SelectItem[];
|
|
partners: SelectItem[];
|
|
cols: any[];
|
|
totalItems;
|
|
isSelfSignup = false;
|
|
|
|
searchAccordionOpen = sessionStorage.getItem('customers-list-accordion') === 'true';
|
|
private lastFiltersQuery: Record<string, any> | undefined;
|
|
private useCacheOnReturn = false;
|
|
cacheTtlSeconds: number;
|
|
customerFilterDefinitions: FilterDefinition[];
|
|
|
|
constructor(
|
|
private readonly route: ActivatedRoute,
|
|
private readonly customerCache: CustomerCacheService,
|
|
private readonly listReturnCache: ListReturnCacheService,
|
|
) {
|
|
super();
|
|
this.cacheTtlSeconds = Math.round(this.customerCache.getTtlMs() / 1000);
|
|
this.totalItems = { '=0': '', '=1': '1 ' + $localize`:@@customer:customer`.toLocaleLowerCase(), 'other': $localize`:@@total#Customers:Total: # customers` };
|
|
|
|
this.statuses = [
|
|
{ label: globals.all, value: null },
|
|
{ label: globals.active, value: true },
|
|
{ label: globals.notActive, value: false }
|
|
];
|
|
this.cols = [
|
|
{ field: "name", header: globals.name, filtered: true, filterMatchMode: 'contains' },
|
|
{ field: "username", header: globals.userName, filtered: true, filterMatchMode: 'contains' },
|
|
{ field: "contact", header: globals.contact },
|
|
{ field: "totalJobs", header: globals.jobs, width: '5%', filtered: false },
|
|
{ field: this.CREATED, header: globals.from, width: '6%' },
|
|
{ field: this.BILLABLE, header: "Billable", width: '9%' },
|
|
{ field: this.ACTIVE, header: globals.active, width: '9%' },
|
|
{ field: this.PARTNER_NAME, header: globals.partner, width: '9%' }
|
|
];
|
|
|
|
this.customerFilterDefinitions = [
|
|
{ key: 'name', label: globals.name, dataType: 'text' },
|
|
{ key: 'username', label: globals.userName, dataType: 'text' },
|
|
{ key: 'email', label: globals.email, dataType: 'text' },
|
|
{ key: 'contact', label: globals.contact, dataType: 'text' },
|
|
{ key: 'createdAt', label: globals.from, dataType: 'date-preset' },
|
|
];
|
|
}
|
|
|
|
ngOnInit() {
|
|
const saved = localStorage.getItem('isSelfSignup');
|
|
this.isSelfSignup = saved === 'true';
|
|
|
|
this.sub$ = this.store.select(fromCustomers.getAllCustomers).subscribe(customers => {
|
|
this.setCustomersAndPartners(customers);
|
|
});
|
|
|
|
this.sub$.add(this.store.select(fromCustomers.getSelectedCustomer).subscribe(cust => {
|
|
this.curCust = cust;
|
|
}));
|
|
|
|
this.useCacheOnReturn = this.listReturnCache.startVisit('customers');
|
|
const savedFilters = sessionStorage.getItem('customers-list-last-filters');
|
|
if (savedFilters) {
|
|
try {
|
|
this.lastFiltersQuery = JSON.parse(savedFilters);
|
|
} catch (_err) {
|
|
this.lastFiltersQuery = undefined;
|
|
}
|
|
}
|
|
this.store.dispatch(savedFilters
|
|
? new customerActions.Fetch({ filters: savedFilters, useCache: this.useCacheOnReturn })
|
|
: new customerActions.Fetch({ useCache: this.useCacheOnReturn })
|
|
);
|
|
}
|
|
|
|
private setCustomersAndPartners(customers: Customer[]) {
|
|
const filtered = this.isSelfSignup ? customers.filter(c => c.selfSignup) : customers;
|
|
this.customers = filtered.map(c => ({
|
|
...c,
|
|
partnerName: c.partner?.name || null
|
|
}));
|
|
this.partners = [
|
|
{ label: globals.all, value: null },
|
|
...customers
|
|
.filter(c => c.partner)
|
|
.map(c => c.partner.name)
|
|
.filter((v, i, a) => a.indexOf(v) === i)
|
|
.map(name => ({ label: name, value: name }))
|
|
];
|
|
}
|
|
|
|
onToggle(event: any): void {
|
|
this.isSelfSignup = event.checked;
|
|
localStorage.setItem('isSelfSignup', String(this.isSelfSignup));
|
|
this.store.select(fromCustomers.getAllCustomers).subscribe(customers => {
|
|
this.setCustomersAndPartners(customers);
|
|
});
|
|
}
|
|
|
|
onRowSelect(event) {
|
|
this.store.dispatch(new customerActions.Select(event.data));
|
|
}
|
|
|
|
onAccordionToggle(expanded: boolean) {
|
|
sessionStorage.setItem('customers-list-accordion', String(expanded));
|
|
}
|
|
|
|
updateCacheTtl(): void {
|
|
const ttlMs = this.customerCache.setTtlMs(Number(this.cacheTtlSeconds || 0) * 1000);
|
|
this.cacheTtlSeconds = Math.round(ttlMs / 1000);
|
|
}
|
|
|
|
onFiltersSubmit(event: FilterChangeEvent) {
|
|
const q = { ...event.query };
|
|
const filtersStr = JSON.stringify(q);
|
|
const prevFilters = sessionStorage.getItem('customers-list-last-filters');
|
|
if (filtersStr !== prevFilters) {
|
|
this.customerCache.invalidate();
|
|
this.useCacheOnReturn = false;
|
|
}
|
|
this.lastFiltersQuery = q;
|
|
sessionStorage.setItem('customers-list-last-filters', filtersStr);
|
|
this.store.dispatch(new customerActions.Fetch({ filters: filtersStr, useCache: this.useCacheOnReturn }));
|
|
}
|
|
|
|
get canEdit() {
|
|
return (this.curCust && this.curCust._id !== '0');
|
|
}
|
|
|
|
newCustomer() {
|
|
this.router.navigate(['customer', '0'], { relativeTo: this.route });
|
|
}
|
|
|
|
editCustomer() {
|
|
this.listReturnCache.markPending('customers');
|
|
this.router.navigate(['customer', this.curCust._id], { relativeTo: this.route });
|
|
}
|
|
|
|
deleteCustomer() {
|
|
if (!this.curCust) { return; }
|
|
this.confirmSvc.confirm({
|
|
message: globals.confirmDeleteThing.replace('#thing#', globals.customer),
|
|
accept: () => {
|
|
this.store.dispatch(new customerActions.Delete(this.curCust));
|
|
this.curCust = null;
|
|
}
|
|
});
|
|
}
|
|
|
|
ngOnDestroy() {
|
|
super.ngOnDestroy();
|
|
}
|
|
|
|
}
|