src/app/shared/widgets/data-list/data-list.service.ts
constructor(_authHttp: HttpClient, _progressbarService: ProgressbarService, notificationService: CustomNotificationService, translateService: TranslateService, _columnService: DataListColumnsService, websocketService: WebsocketService, localstorageShownAttributesEntry: LocalStorageEntry, userService: UserService)
|
|||||||||||||||||||||||||||
Parameters :
|
Private _buildDataUrl | ||||||||||||||||||||||||||||||||||||||||||||
_buildDataUrl(queryString: string, locale: string, dataType: string, viewmode: string, virtualizationArgs: any, sortingArgs: ISortingExpression[], filteringArgs: IFilteringExpressionsTree, attributes: string[], pageIndex: number, force: boolean)
|
||||||||||||||||||||||||||||||||||||||||||||
Parameters :
Returns :
string
|
Public appendPaging | ||||||||||||
appendPaging(queryString: , virtualizationArgs: any, pageIndex: )
|
||||||||||||
Parameters :
Returns :
any
|
Public buildDataUrlWithOutPaging | ||||||||||||||||||||||||||||||||||||
buildDataUrlWithOutPaging(queryString: string, locale: string, dataType: string, viewmode: string, sortingArgs: ISortingExpression[], filteringArgs: IFilteringExpressionsTree, attributes: string[], force: boolean)
|
||||||||||||||||||||||||||||||||||||
Parameters :
Returns :
string
|
Public doMapData | |||||||||
doMapData(data: , isTree?: boolean)
|
|||||||||
Parameters :
Returns :
literal type
|
getStartIndex | ||||
getStartIndex(chunkSize: )
|
||||
Parameters :
Returns :
any
|
getTemplatedFilteredResults | ||||||||||||
getTemplatedFilteredResults(inputurl: , showProgressBar: boolean)
|
||||||||||||
Parameters :
Returns :
Observable<ResultResource>
|
Public initialize | |||||||||||||||||||||
initialize(grid: IgxGridBaseDirective, eagerLoading: boolean, configuration: DataListConfiguration, changeCallback: any, cdr: ChangeDetectorRef, dataType?: any)
|
|||||||||||||||||||||
Parameters :
Returns :
void
|
Public loadData | ||||||||||||||||||||||||||||||||||||
loadData(inputurl: string, locale: string, dataType: string, viewMode: string, attributes: string[], virtualizationArgs?: IForOfState, sortingArgs?: ISortingExpression[], filteringArgs?: IFilteringExpressionsTree, resetData?: boolean, cb?: (undefined) => void, force?: boolean)
|
||||||||||||||||||||||||||||||||||||
Parameters :
Returns :
any
|
Public mapData | ||||
mapData(data: )
|
||||
Parameters :
Returns :
literal type
|
Private mapFilterExpression | ||||||
mapFilterExpression(expression: IFilteringExpression)
|
||||||
Parameters :
Returns :
string
|
Private mapFilterTree | ||||||
mapFilterTree(tree: IFilteringExpressionsTree)
|
||||||
Parameters :
Returns :
string
|
Static mapFilterTypeValue | ||||||||
mapFilterTypeValue(condition: , fieldName: , value: )
|
||||||||
Parameters :
Returns :
any
|
Private mapMainAsset | ||||||
mapMainAsset(data: any)
|
||||||
Parameters :
Returns :
void
|
ngOnDestroy |
ngOnDestroy()
|
Returns :
void
|
Private prepareAndLoadData | |||||||||
prepareAndLoadData(reset: , force: )
|
|||||||||
Parameters :
Returns :
void
|
Public processData | ||||
processData(reset: )
|
||||
Parameters :
Returns :
void
|
Public processTileViewData | ||||
processTileViewData(virtualization: )
|
||||
Parameters :
Returns :
void
|
Public reloadGrid | ||||||||
reloadGrid(force: boolean)
|
||||||||
Parameters :
Returns :
void
|
Private reselectRows | |||||||||
reselectRows(data: any[], isTree: boolean)
|
|||||||||
Parameters :
Returns :
void
|
Public reset |
reset()
|
Returns :
void
|
Public sendRequest | ||||||||||||||||||
sendRequest(url: string, startIndex: number, pageIndex: number, endIndex: number, cb: )
|
||||||||||||||||||
Parameters :
Returns :
void
|
setDataType |
setDataType(dataType: string, reload: boolean)
|
Returns :
void
|
setEagerLimit | ||||||
setEagerLimit(eagerLimit: number)
|
||||||
Parameters :
Returns :
void
|
setNextPage | ||||||
setNextPage(getPage: boolean)
|
||||||
Parameters :
Returns :
void
|
setPageLimit | ||||||
setPageLimit(pageLimit: number)
|
||||||
Parameters :
Returns :
void
|
setViewmode | ||||||||||||
setViewmode(viewmode: string, reload: )
|
||||||||||||
Parameters :
Returns :
void
|
Public updateData | ||||||||||||||||||||||||
updateData(data: any, startIndex: number, force: , endIndex?: number, pageIndex?: number)
|
||||||||||||||||||||||||
Parameters :
Returns :
void
|
updateHierarchicalDataTotalCount |
updateHierarchicalDataTotalCount()
|
Returns :
void
|
Public updateLink | ||||||||||||||||
updateLink(link: string, loadData: boolean, force: boolean)
|
||||||||||||||||
Parameters :
Returns :
void
|
Private _cachedData |
_cachedData:
|
Type : any[]
|
Private _cdr |
_cdr:
|
Type : ChangeDetectorRef
|
Protected _data |
_data:
|
Type : BehaviorSubject<any[]>
|
Private _dataObservable |
_dataObservable:
|
Type : Observable<any[]>
|
Private _eagerLimit |
_eagerLimit:
|
Type : number
|
Private _getNextPage |
_getNextPage:
|
Type : boolean
|
Private _grid |
_grid:
|
Type : IgxGridBaseDirective
|
Private _link |
_link:
|
Type : string
|
Private _linkWithoutPaging |
_linkWithoutPaging:
|
Default value : new Subject<String>()
|
Private _pageLimit |
_pageLimit:
|
Type : number
|
Private _prevRequest |
_prevRequest:
|
Type : any
|
Private _products |
_products:
|
Type : string[]
|
Private _selectedLocale |
_selectedLocale:
|
Type : string
|
Private _unsubscribe |
_unsubscribe:
|
Default value : NgUnsubscribe.create()
|
Private _viewmode |
_viewmode:
|
Type : string
|
Public cacheId |
cacheId:
|
Type : string
|
Private changeCallback |
changeCallback:
|
Type : any
|
Public configuration |
configuration:
|
Type : DataListConfiguration
|
Public data |
data:
|
Type : Observable<any[]>
|
Public dataLoaded |
dataLoaded:
|
Default value : new Subject<any[]>()
|
Public dataTotalSubject |
dataTotalSubject:
|
Default value : new BehaviorSubject<number>(null)
|
Public dataType |
dataType:
|
Type : string
|
Private debounceSendRequest |
debounceSendRequest:
|
Type : Subject<any>
|
Default value : new Subject<any>()
|
Private inputLinkEvent |
inputLinkEvent:
|
Default value : new Subject<String>()
|
Private inputLinkEventObservable |
inputLinkEventObservable:
|
Default value : this.inputLinkEvent.asObservable()
|
Public isEagerLoading |
isEagerLoading:
|
Type : boolean
|
Default value : false
|
Public linkWithoutPaging |
linkWithoutPaging:
|
Default value : this._linkWithoutPaging.asObservable()
|
Public recommendedAttributes |
recommendedAttributes:
|
Default value : new BehaviorSubject<RecommendedAttributes>(
null
)
|
Private refreshSub |
refreshSub:
|
Public results |
results:
|
Type : Result[]
|
Public totalSubject |
totalSubject:
|
Default value : new BehaviorSubject<number>(null)
|
Private triggerSearchObs |
triggerSearchObs:
|
Default value : this.triggerSearchSubject.pipe(
filter(() => {
if (!this.configuration.languageSelection) {
return true;
}
return this.selectedLocale != null;
}),
//Debounce by 100ms to take the latest uri if multiple get inputted without every one starting a request
debounceTime(100),
takeUntil(this._unsubscribe)
)
|
Private triggerSearchSubject |
triggerSearchSubject:
|
Default value : new Subject<boolean>()
|
products | ||||
getproducts()
|
||||
setproducts(value: )
|
||||
Parameters :
Returns :
void
|
dataArray |
getdataArray()
|
viewmode |
getviewmode()
|
selectedLocale | ||||||
getselectedLocale()
|
||||||
setselectedLocale(locale: string)
|
||||||
Parameters :
Returns :
void
|
displayedAttributes |
getdisplayedAttributes()
|
cachedData |
getcachedData()
|
grid |
getgrid()
|
import {
debounceTime,
distinctUntilChanged,
filter,
map,
takeUntil,
tap,
} from "rxjs/operators";
import { ChangeDetectorRef, Injectable, isDevMode } from "@angular/core";
import { BehaviorSubject, Observable, Subject } from "rxjs";
import { HttpClient } from "@angular/common/http";
import {
DataListConfiguration,
RecommendedAttributes,
Result,
ResultResource,
} from "../interfaces/list.interfaces";
import { ProgressbarService } from "../../components/progressbar/progressbar.service";
import {
FilteringLogic,
IFilteringExpression,
IFilteringExpressionsTree,
IForOfState,
IgxGridBaseDirective,
IgxGridComponent,
ISortingExpression,
SortingDirection,
IgxHierarchicalGridComponent,
IgxForOfDirective,
} from "@infragistics/igniteui-angular";
import { ListComponentWidget } from "../list/list.component";
import * as uriTemplates_ from "uri-templates";
import { NgUnsubscribe } from "../../ng-unsubscribe";
import { DataListColumnsService } from "./data-list-columns.service";
import { CustomNotificationService } from "../../components/notification/customnotification.service";
import { TranslateService } from "@ngx-translate/core";
import { deepCopy } from "../../components/util";
import { WebsocketService } from "../../components/services/websocket.service";
import { UserService } from "../../components/user/user.service";
import { LocalStorageEntry } from "../../components/local-storage/local-storage.service";
import { ViewAttributeComponent } from "../../components/edit-attribute/view-attribute.component";
import { Attribute, Attributes } from "../../components/edit-attribute";
const uriTemplates = uriTemplates_;
declare let $;
export enum SortOrder {
ASC = "asc",
DESC = "desc",
NONE = "",
}
const EMPTY_STRING: string = "";
const TOOLBOX_EDIT_BAR_ACTIVE = { "@toolbox-edit-bar": "active" };
const TOOLBOX_ACTIVE_CONTEXT = {
"@toolbox-active-context": ["sequential", "bulk"],
};
export enum FILTER_OPERATION {
CONTAINS = "contains",
STARTS_WITH = "startswith",
ENDS_WITH = "endswith",
EQUALS = "eq",
DOES_NOT_EQUAL = "ne",
DOES_NOT_CONTAIN = "not contains",
GREATER_THAN = "gt",
LESS_THAN = "lt",
LESS_THAN_EQUAL = "le",
GREATER_THAN_EQUAL = "ge",
}
@Injectable()
export class DataListService {
private _unsubscribe = NgUnsubscribe.create();
public results: Result[];
private inputLinkEvent = new Subject<String>();
private inputLinkEventObservable = this.inputLinkEvent.asObservable();
protected _data: BehaviorSubject<any[]>;
private _cachedData: any[];
public totalSubject = new BehaviorSubject<number>(null);
public dataTotalSubject = new BehaviorSubject<number>(null);
public recommendedAttributes = new BehaviorSubject<RecommendedAttributes>(
null
);
private refreshSub;
// The list of productNos that is represented by the dataset in _data
private _products: string[];
private _linkWithoutPaging = new Subject<String>();
public linkWithoutPaging = this._linkWithoutPaging.asObservable();
private triggerSearchSubject = new Subject<boolean>();
private triggerSearchObs = this.triggerSearchSubject.pipe(
filter(() => {
if (!this.configuration.languageSelection) {
return true;
}
return this.selectedLocale != null;
}),
//Debounce by 100ms to take the latest uri if multiple get inputted without every one starting a request
debounceTime(100),
takeUntil(this._unsubscribe)
);
private _cdr: ChangeDetectorRef;
private _grid: IgxGridBaseDirective;
private changeCallback: any;
private _link: string;
private _selectedLocale: string;
public dataType: string;
private _viewmode: string;
private _prevRequest: any;
private _dataObservable: Observable<any[]>;
public data: Observable<any[]>;
public configuration: DataListConfiguration;
public isEagerLoading: boolean = false;
public cacheId: string;
private _pageLimit: number;
private _eagerLimit: number;
private _getNextPage: boolean;
private debounceSendRequest: Subject<any> = new Subject<any>();
public dataLoaded = new Subject<any[]>();
constructor(
protected _authHttp: HttpClient,
private _progressbarService: ProgressbarService,
private notificationService: CustomNotificationService,
private translateService: TranslateService,
private _columnService: DataListColumnsService,
private websocketService: WebsocketService,
private localstorageShownAttributesEntry: LocalStorageEntry,
private userService: UserService
) {
this._data = new BehaviorSubject<any[]>([]);
this._dataObservable = this._data
.asObservable()
.pipe(takeUntil(this._unsubscribe));
this.data = this._dataObservable;
}
public initialize(
grid: IgxGridBaseDirective,
eagerLoading: boolean,
configuration: DataListConfiguration,
changeCallback: any,
cdr: ChangeDetectorRef,
dataType?: any
) {
this._cdr = cdr;
this._grid = grid;
this.changeCallback = changeCallback;
this.configuration = configuration;
this.isEagerLoading = eagerLoading;
this.setDataType(dataType || this.configuration.dataType, false);
if (!configuration.dynamicColumnsFromData) {
this._columnService.columns
.pipe(takeUntil(this._unsubscribe))
.subscribe((cols) => {
if (this._link) {
this.reloadGrid();
}
});
}
this.debounceSendRequest
.pipe(takeUntil(this._unsubscribe), debounceTime(500))
.subscribe(([url, startIndex, pageIndex, endIndex, cb]) => {
if (url) {
this.sendRequest(url, startIndex, pageIndex, endIndex, cb);
}
});
this.triggerSearchObs.subscribe((force) => {
if (!this._link) {
return;
}
this.prepareAndLoadData(true, force);
});
}
set products(value) {
this._products = value;
}
get products() {
return this._products;
}
get dataArray(): any[] {
return this._data.value;
}
get viewmode(): string {
return this._viewmode;
}
setPageLimit(pageLimit: number) {
this._pageLimit = pageLimit;
}
setNextPage(getPage: boolean) {
this._getNextPage = getPage;
}
setEagerLimit(eagerLimit: number) {
this._eagerLimit = eagerLimit;
}
setDataType(dataType: string, reload: boolean) {
this.dataType = dataType;
if (reload) {
this.reloadGrid();
}
this._columnService.dataType = dataType;
}
setViewmode(viewmode: string, reload = true) {
this._viewmode = viewmode;
if (reload) {
this.reloadGrid();
}
}
get selectedLocale(): string {
return this._selectedLocale;
}
set selectedLocale(locale: string) {
this._selectedLocale = locale;
if (this._link) {
this.reloadGrid();
}
}
get displayedAttributes(): string[] {
return this._columnService.displayedAttributes;
}
get cachedData(): any[] {
return this._cachedData;
}
public updateLink(
link: string,
loadData: boolean = true,
force: boolean = false
) {
if (!link) {
this.reset();
return;
}
this._link = link;
if (loadData) {
this.triggerSearchSubject.next(force);
// this.prepareAndLoadData();
}
}
public reloadGrid(force: boolean = false) {
this.updateLink(this._link, true, force);
}
public reset() {
if (this._prevRequest) {
this._prevRequest.unsubscribe();
this._progressbarService.requestFinished();
}
if (this._data.value.length !== 0) {
this._grid.navigateTo(0, 0);
this._products = [];
this._link = null;
this._data.next([]);
if (this.changeCallback) {
this.changeCallback([]);
}
}
this._columnService.updateColumns([], true);
this._cachedData = null;
this._link = null;
this.totalSubject.next(null);
this.dataTotalSubject.next(null);
}
private prepareAndLoadData(reset = true, force = false) {
let chunkSize = this.isEagerLoading
? 0
: Math.ceil(this.grid.nativeElement.offsetHeight / this._grid.rowHeight);
let virtualization = {
chunkSize: chunkSize,
startIndex: this.getStartIndex(chunkSize),
};
this.loadData(
this._link,
this._selectedLocale,
this.dataType,
this._viewmode,
this.displayedAttributes,
virtualization,
this.isEagerLoading ? null : this._grid.sortingExpressions,
this.isEagerLoading ? null : this._grid.filteringExpressionsTree,
reset,
(data) => {
this.changeCallback(data);
},
force
);
}
public processData(reset) {
if (!this._link || this.isEagerLoading) {
return;
}
this.prepareAndLoadData(reset);
}
public processTileViewData(virtualization) {
this.loadData(
this._link,
this._selectedLocale,
this.dataType,
this._viewmode,
this.displayedAttributes,
virtualization,
this.isEagerLoading ? null : this._grid.sortingExpressions,
this.isEagerLoading ? null : this._grid.filteringExpressionsTree,
false,
(data) => {
this.changeCallback(data);
}
);
}
getTemplatedFilteredResults(
inputurl,
showProgressBar: boolean = true
): Observable<ResultResource> {
if (showProgressBar) {
this._progressbarService.addRequest();
}
return this._authHttp.get<any>(inputurl, {}).pipe(
debounceTime(400),
distinctUntilChanged(),
tap(
(res) => {
if (showProgressBar) {
this._progressbarService.requestFinished();
}
if (res.messages) {
res.messages.forEach((entry) => {
this.notificationService.fromResponse(entry);
});
}
return res;
},
(err) => {
if (showProgressBar) {
this._progressbarService.requestFinished();
}
}
),
map((res) => {
return <ResultResource>res;
})
);
}
public loadData(
inputurl: string,
locale: string,
dataType: string,
viewMode: string,
attributes: string[],
virtualizationArgs?: IForOfState,
sortingArgs?: ISortingExpression[],
filteringArgs?: IFilteringExpressionsTree,
resetData?: boolean,
cb?: (any) => void,
force?: boolean
): any {
const startIndex = virtualizationArgs.startIndex;
let endIndex = virtualizationArgs.chunkSize + startIndex;
let pageIndex: number;
let areAllItemsInCache = true;
if (resetData || this.isEagerLoading) {
let url = this._buildDataUrl(
inputurl,
locale,
dataType,
viewMode,
virtualizationArgs,
sortingArgs,
filteringArgs,
attributes,
startIndex,
force
);
this._progressbarService.addRequest();
if (this._prevRequest) {
this._prevRequest.unsubscribe();
this._progressbarService.requestFinished();
}
this._prevRequest = this._authHttp
.get<any>(url)
.pipe(
debounceTime(400),
tap(
(res) => {
this._progressbarService.requestFinished();
if (res.messages) {
res.messages.forEach((entry) => {
this.notificationService.fromResponse(entry);
});
}
if (res.emptyMessage) {
this.grid.resourceStrings.igx_grid_emptyGrid_message =
res.emptyMessage;
}
return res;
},
(err) => {
this._progressbarService.requestFinished();
}
),
map((res) => {
return <ResultResource>res;
})
)
.subscribe(
(data: any) => {
let mapped = this.mapData(data);
if (this.grid.selectedRows.length > 0) {
let selectedRows = deepCopy(this.grid.selectedRows);
let identifiers = mapped.data.map((row) => row.identifier);
let missingRows = selectedRows.filter(
(value) => -1 === identifiers.indexOf(value)
);
if (missingRows.length > 0) {
this.grid.deselectRows(missingRows);
}
}
this._prevRequest = null;
this.totalSubject.next(
data.customTotal ? data.customTotal : mapped.total
);
if (this.isEagerLoading) {
this._data.next(mapped.data);
} else {
if (
(this._grid instanceof IgxGridComponent ||
this._grid instanceof IgxHierarchicalGridComponent) &&
this._grid.totalItemCount != data.total
) {
this._grid.totalItemCount = data.total;
}
this._cachedData = new Array<any>(data["total"]).fill({
cache: true,
});
this.updateData(mapped.data, startIndex, false, endIndex);
this.dataTotalSubject.next(mapped.total);
this._cdr.detectChanges();
this._grid.cdr.detectChanges();
}
if (cb) {
cb(mapped.data);
}
this.dataLoaded.next(mapped.data);
if (this._columnService.summaries.length !== 0) {
this._grid.enableSummaries(this._columnService.summaries);
}
},
(err) => console.log("HTTP Error", err)
);
return;
}
if (this._grid instanceof IgxHierarchicalGridComponent) {
let limit = this.cachedData.length;
if (endIndex === limit - 1) {
endIndex = limit;
}
}
const data = this._cachedData.slice(startIndex, endIndex);
this._data.next(data);
if (cb) {
cb(data);
}
this._grid.cdr.markForCheck();
if (this._prevRequest) {
this._prevRequest.unsubscribe();
this._prevRequest = null;
this._progressbarService.requestFinished();
}
for (let i = startIndex; i < endIndex; i++) {
if (this._cachedData[i] === null || this._cachedData[i].cache) {
pageIndex = i;
areAllItemsInCache = false;
break;
}
}
if (!areAllItemsInCache) {
let url = this._buildDataUrl(
inputurl,
locale,
dataType,
viewMode,
virtualizationArgs,
sortingArgs,
filteringArgs,
attributes,
pageIndex
);
this.debounceSendRequest.next([url, startIndex, pageIndex, endIndex, cb]);
}
}
public sendRequest(
url: string,
startIndex: number,
pageIndex: number,
endIndex: number,
cb
) {
this._progressbarService.addRequest();
this._prevRequest = this._authHttp
.get<any>(url)
.pipe(
debounceTime(200),
distinctUntilChanged(),
map((res) => {
if (res.messages) {
res.messages.forEach((entry) => {
this.notificationService.fromResponse(entry);
});
}
return <ResultResource>res;
})
)
.subscribe(
(data: any) => {
this._progressbarService.requestFinished();
let mapped = this.mapData(data);
if (
(this._grid instanceof IgxGridComponent ||
this._grid instanceof IgxHierarchicalGridComponent) &&
this._grid.totalItemCount != data.total
) {
this._grid.totalItemCount = data.total;
}
this.updateData(mapped.data, startIndex, false, endIndex, pageIndex);
if (cb) {
cb(mapped.data);
}
this._cdr.detectChanges();
this._grid.cdr.detectChanges();
},
(err) => console.log("HTTP Error", err)
);
}
public updateData(
data: any,
startIndex: number,
force = false,
endIndex?: number,
pageIndex?: number
) {
if (force) {
this._cachedData = new Array(data.length).fill({ cache: true });
}
let cacheIndex = this._getNextPage && pageIndex ? pageIndex : startIndex;
if (data) {
for (let i = 0; i < data.length; i++) {
this._cachedData[i + cacheIndex] = data[i];
}
const cachedData = this._cachedData.slice(startIndex, endIndex);
this._data.next(cachedData);
}
}
updateHierarchicalDataTotalCount() {
if (
!this.isEagerLoading &&
this._grid instanceof IgxHierarchicalGridComponent
) {
this._grid.totalItemCount =
this._cachedData.length + this._grid.expansionStates.size;
}
}
public doMapData(data, isTree?: boolean): { total: number; data: any } {
if (data.messages) {
data.messages.forEach((entry) => {
this.notificationService.fromResponse(entry);
});
}
const total = data.total;
const typedData = data._embedded[data.type];
if (typedData[0]) {
// create a prototype object that will be shared between all
// rows loaded at this point. the prototype keeps track of
// all required #source and #value properties to reduce the
// required memory
const rowPrototype = Attributes.createRowPrototype();
for (const row of typedData) {
this.mapMainAsset(row);
Attributes.mapRowAttributes(row, rowPrototype);
}
this.reselectRows(typedData, isTree);
}
return { total, data: typedData };
}
public mapData(data): { total: number; data: any[] } {
if (this.refreshSub) {
this.refreshSub.unsubscribe();
this.refreshSub = null;
}
this.cacheId = data.cacheId || null;
if (this.cacheId) {
this.refreshSub = this.websocketService
.createSub(
`/topic/cache/${this.userService.currentUser}/${this.cacheId}/refreshed`
)
.pipe(takeUntil(this._unsubscribe))
.subscribe((data) => {
this.reloadGrid();
});
}
if (data.products) {
this._products = data.products;
} else {
this._products = null;
}
if (data.messages) {
data.messages.forEach((entry) => {
this.notificationService.fromResponse(entry);
});
}
const recommendedAttributes = data._embedded.recommendedAttributes;
if (recommendedAttributes) {
this.recommendedAttributes.next(recommendedAttributes);
}
const dynamicColumnsFromData = this._columnService.dynamicColumnsFromData;
if (dynamicColumnsFromData || data._embedded.forcedAttributes) {
const columns: any[] = data._embedded.columns || [];
const forceAttributes: any[] = data._embedded.forcedAttributes || [];
if (forceAttributes.length > 0) {
this._columnService.shownAttributes = forceAttributes;
if (this.localstorageShownAttributesEntry) {
this.localstorageShownAttributesEntry.value = JSON.stringify(
forceAttributes
);
}
}
if (dynamicColumnsFromData && columns.length === 0) {
const link = data?._links?.self?.href;
let message = `DataList is in dynamicColumnsFromData mode, but no columns were found in response`;
if (link) {
message += `, request url is ${link}`;
}
if (isDevMode()) {
console.error(message);
} else {
console.debug(message);
}
}
const update = [...columns];
forceAttributes.forEach((attribute) => {
let matchingColumn = update.find(
(column) => column.identifier === attribute.identifier
);
if (matchingColumn == null) {
// attributes forced to be displayed require a matching column definition
return;
}
// prefer using the column's description, if it is set
Object.assign(matchingColumn, attribute, {
description: matchingColumn.description || attribute.description,
});
});
this._columnService.updateColumns(update, true);
const groups = data._embedded.groups;
if (dynamicColumnsFromData && groups) {
this._columnService.updateGroups(groups, true);
}
}
return this.doMapData(data);
}
private mapMainAsset(data: any) {
if (!data.hasOwnProperty("_embedded")) {
return;
}
let embedded = data["_embedded"];
if (!embedded.hasOwnProperty("main-asset")) {
return;
}
let asset = embedded["main-asset"];
data["main-asset"] = asset;
asset.toString = function () {
return this._links.default.href;
};
asset.valueOf = function () {
return this._links.default.href;
};
}
private reselectRows(data: any[], isTree: boolean) {
const primaryKey = this.configuration.primaryKey;
const selectedData = this.grid.selectedRows;
if (primaryKey && selectedData.length !== 0) {
if (isTree) {
const gridData = this.grid.data;
data = [...data, ...gridData];
}
const dataIds = data.map((row) => row[primaryKey]);
const deselectRows = [];
selectedData.forEach((id) => {
if (dataIds.indexOf(id) === -1) {
deselectRows.push(id);
}
});
if (deselectRows.length !== 0) {
this.grid.deselectRows(deselectRows);
}
}
}
public appendPaging(queryString, virtualizationArgs: any, pageIndex) {
let queryParams =
queryString.indexOf("?") >= 0
? ListComponentWidget.QUERY_PARAMS_PAGING_CONTD
: ListComponentWidget.QUERY_PARAMS_PAGING_START;
queryString += queryParams;
let uriParams: any = {};
if (virtualizationArgs) {
uriParams.offset = this._getNextPage
? pageIndex
: virtualizationArgs.startIndex;
uriParams.limit = this.isEagerLoading
? this._eagerLimit
? this._eagerLimit
: "ALL"
: this._pageLimit || virtualizationArgs.chunkSize || 16;
}
let template = uriTemplates(queryString);
return template.fill(uriParams);
}
public buildDataUrlWithOutPaging(
queryString: string,
locale: string,
dataType: string,
viewmode: string,
sortingArgs: ISortingExpression[],
filteringArgs: IFilteringExpressionsTree,
attributes: string[],
force: boolean = false
): string {
let queryParams =
queryString.indexOf("?") >= 0
? ListComponentWidget.QUERY_PARAMS_CONTD
: ListComponentWidget.QUERY_PARAMS_START;
queryString =
queryString.indexOf("filter*") >= 0
? queryString
: queryString + queryParams;
let uriParams: any = {
viewmode,
type: dataType,
};
uriParams.attributes = attributes.map((identifier) =>
Attributes.fromField(identifier)
);
uriParams["data-locale"] = locale;
uriParams["type"] = dataType;
if (force) {
uriParams["force-reload"] = force;
}
let filter = EMPTY_STRING;
if (sortingArgs && sortingArgs.length > 0) {
let sorts = [];
sortingArgs.forEach((sort) => {
let sortingDirection: string;
switch (sort.dir) {
case SortingDirection.Asc:
sortingDirection = "asc";
break;
case SortingDirection.Desc:
sortingDirection = "desc";
break;
default:
sortingDirection = SortOrder.NONE;
}
if (sortingDirection == SortOrder.NONE) {
return;
}
sorts.push(sort.fieldName + ":" + sortingDirection);
});
uriParams.sort = sorts;
}
if (filteringArgs && filteringArgs.filteringOperands.length > 0) {
uriParams.filter = [this.mapFilterTree(filteringArgs)];
}
let template = uriTemplates(queryString);
return template.fill(uriParams);
}
private mapFilterTree(tree: IFilteringExpressionsTree): string {
let operator = tree.operator == FilteringLogic.And ? "and" : "or";
let filters = tree.filteringOperands
.map((operand) => {
if (DataListService.isExpressionsTree(operand)) {
return this.mapFilterTree(operand);
} else {
return this.mapFilterExpression(operand);
}
})
.join(",");
return `${operator}(${filters})`;
}
private mapFilterExpression(expression: IFilteringExpression): string {
let value = expression.searchVal;
let condition = expression.condition.name;
let fieldName = expression.fieldName;
return DataListService.mapFilterTypeValue(condition, fieldName, value);
}
private static isExpressionsTree(
operand: IFilteringExpressionsTree | IFilteringExpression
): operand is IFilteringExpressionsTree {
return operand.hasOwnProperty("operator");
}
private _buildDataUrl(
queryString: string,
locale: string,
dataType: string,
viewmode: string,
virtualizationArgs: any,
sortingArgs: ISortingExpression[],
filteringArgs: IFilteringExpressionsTree,
attributes: string[],
pageIndex: number,
force: boolean = false
): string {
const uriWithoutPaging = this.buildDataUrlWithOutPaging(
queryString,
locale,
dataType,
viewmode,
sortingArgs,
filteringArgs,
attributes,
force
);
this._linkWithoutPaging.next(uriWithoutPaging);
return this.appendPaging(uriWithoutPaging, virtualizationArgs, pageIndex);
}
getStartIndex(chunkSize) {
if (this.isEagerLoading) {
return 0;
}
if (this._grid instanceof IgxGridComponent) {
return this._grid.virtualizationState.startIndex;
} else {
let startIndex = this._grid.verticalScrollContainer.state.startIndex;
if (this._grid instanceof IgxHierarchicalGridComponent) {
if (startIndex > 0) {
let index = startIndex + this._grid.expansionStates.size;
let limit = this.cachedData.length - chunkSize;
return index < limit ? index : limit - 1;
} else {
return 0;
}
}
return startIndex;
}
}
static mapFilterTypeValue(condition, fieldName, value) {
let filterString;
switch (condition) {
case "object":
case "contains": {
filterString =
fieldName + ":" + FILTER_OPERATION.CONTAINS + ":" + '"' + value + '"';
break;
}
case "startsWith": {
filterString =
fieldName +
":" +
FILTER_OPERATION.STARTS_WITH +
":" +
'"' +
value +
'"';
break;
}
case "endsWith": {
filterString =
fieldName +
":" +
FILTER_OPERATION.ENDS_WITH +
":" +
'"' +
value +
'"';
break;
}
case "equals": {
filterString =
fieldName + ":" + FILTER_OPERATION.EQUALS + ":" + '"' + value + '"';
break;
}
case "doesNotEqual": {
filterString =
fieldName +
":" +
FILTER_OPERATION.DOES_NOT_EQUAL +
":" +
'"' +
value +
'"';
break;
}
case "doesNotContain": {
filterString =
fieldName +
":" +
FILTER_OPERATION.DOES_NOT_CONTAIN +
":" +
'"' +
value +
'"';
break;
}
case "greaterThan": {
filterString =
fieldName +
":" +
FILTER_OPERATION.GREATER_THAN +
":" +
'"' +
value +
'"';
break;
}
case "greaterThanOrEqualTo": {
filterString =
fieldName +
":" +
FILTER_OPERATION.GREATER_THAN_EQUAL +
":" +
'"' +
value +
'"';
break;
}
case "lessThan": {
filterString =
fieldName +
":" +
FILTER_OPERATION.LESS_THAN +
":" +
'"' +
value +
'"';
break;
}
case "lessThanOrEqualTo": {
filterString =
fieldName +
":" +
FILTER_OPERATION.LESS_THAN_EQUAL +
":" +
'"' +
value +
'"';
break;
}
case "empty": {
filterString =
fieldName + ":" + FILTER_OPERATION.EQUALS + ":" + '"' + value + '"';
break;
}
case "notEmpty": {
filterString =
fieldName +
":" +
FILTER_OPERATION.GREATER_THAN +
":" +
'"' +
value +
'"';
break;
}
case "null": {
filterString =
fieldName + ":" + FILTER_OPERATION.EQUALS + ":" + '"' + value + '"';
break;
}
case "notNull": {
filterString =
fieldName +
":" +
FILTER_OPERATION.DOES_NOT_EQUAL +
":" +
'"' +
value +
'"';
break;
}
}
return filterString;
}
public get grid() {
return this._grid;
}
ngOnDestroy(): void {
if (this._prevRequest) {
this._progressbarService.requestFinished();
this._prevRequest.unsubscribe();
}
this._unsubscribe.destroy();
}
}