ngx-firebase-cms
Version:
Angular Content Management System using Google Firebase (Authentication, Storage & Firestore)
200 lines • 15.2 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
import { Component, Input } from '@angular/core';
import { getInterpolation } from '../../service/helper.service';
import { Router, ActivatedRoute } from '@angular/router';
export class TableComponent {
/**
* @param {?} router
* @param {?} route
*/
constructor(router, route) {
this.router = router;
this.route = route;
this.headers = [];
this.fullData = [];
this.displayData = [];
this.tableLoading = true;
this.noPerPage = 10;
this.listOfSearchValue = [];
this.filterList = {};
}
/**
* @param {?} value
* @return {?}
*/
set data(value) {
this.fullData = value;
this.displayData = value;
this.tableLoading = false;
this.getFilterList();
}
/**
* @return {?}
*/
ngOnInit() {
}
/* Filtering & Sorting */
/**
* @return {?}
*/
getFilterList() {
/** @type {?} */
let filterKeys = this.headers.filter((/**
* @param {?} res
* @return {?}
*/
res => res['canFilter'])).map((/**
* @param {?} res
* @return {?}
*/
res => res['key']));
filterKeys.forEach((/**
* @param {?} key
* @return {?}
*/
key => {
this.filterList[key] = this.fullData.map((/**
* @param {?} res
* @return {?}
*/
res => res[key])).filter((/**
* @param {?} value
* @param {?} index
* @param {?} self
* @return {?}
*/
(value, index, self) => self.indexOf(value) === index)).sort((/**
* @param {?} a
* @param {?} b
* @return {?}
*/
(a, b) => (a > b ? 1 : -1))).map((/**
* @param {?} res
* @return {?}
*/
res => { return { "text": res, "value": res }; }));
}));
}
/**
* @param {?} sort
* @return {?}
*/
sort(sort) {
this.sortName = sort.key;
this.sortValue = sort.value;
this.search();
}
/**
* @param {?} event
* @param {?} uuid
* @return {?}
*/
filter(event, uuid) {
this.listOfSearchValue = event;
this.searchKey = uuid;
this.search();
}
/**
* @return {?}
*/
search() {
/** @type {?} */
const filterFunc = (/**
* @param {?} item
* @return {?}
*/
item => this.listOfSearchValue.length ? this.listOfSearchValue.some((/**
* @param {?} name
* @return {?}
*/
name => item[this.searchKey].indexOf(name) !== -1)) : true);
/** @type {?} */
const data = this.fullData.filter((/**
* @param {?} item
* @return {?}
*/
item => filterFunc(item)));
if (this.sortName && this.sortValue) {
this.displayData = data.sort((/**
* @param {?} a
* @param {?} b
* @return {?}
*/
(a, b) => (this.sortValue === 'ascend') ? (a[this.sortName] > b[this.sortName] ? 1 : -1) : (b[this.sortName] > a[this.sortName] ? 1 : -1)));
}
else {
this.displayData = data;
}
}
/**
* @param {?} url
* @param {?} data
* @return {?}
*/
goTo(url, data) {
if (url) {
getInterpolation(url).forEach((/**
* @param {?} key
* @return {?}
*/
key => {
/** @type {?} */
let replacement = data[key] || "";
url = url.split("${" + key + "}").join(replacement);
}));
this.router.navigate([url], { relativeTo: this.route });
}
}
}
TableComponent.decorators = [
{ type: Component, args: [{
selector: 'aq-table',
template: "<nz-table #basicTable [nzData]=\"displayData\" class=\"table\" [nzPageSize]=\"noPerPage\">\n <thead (nzSortChange)=\"sort($event)\" nzSingleSort>\n <tr>\n <ng-template ngFor let-header [ngForOf]=\"headers\">\n <th *ngIf=\"!header.canSort && !header.canFilter\">{{ header?.label }}</th>\n <th *ngIf=\"!header.canSort && header.canFilter\" nzShowFilter [nzFilters]=\"filterList[header?.key] || []\"\n (nzFilterChange)=\"filter($event, header?.key)\">{{ header?.label }}</th>\n <th *ngIf=\"header.canSort && !header.canFilter\" [nzSortKey]=\"header?.key\" nzShowSort>{{ header?.label }}</th>\n <th *ngIf=\"header.canSort && header.canFilter\" [nzSortKey]=\"header?.key\" nzShowSort nzShowFilter\n [nzFilters]=\"filterList[header?.key] || []\" (nzFilterChange)=\"filter($event, header?.key)\">{{ header?.label }}\n </th>\n </ng-template>\n </tr>\n </thead>\n <tbody>\n <ng-template ngFor let-data [ngForOf]=\"basicTable.data\">\n <tr>\n <td *ngFor=\"let header of headers\">\n <a [ngClass]='{\"disableLink\": !header.routerLink }' (click)=\"goTo(header.routerLink, data)\">\n <ng-template [ngIf]=\"header.pipe == 'date'\">{{ data[header.key].toDate() | date : header.pipeParameter}}\n </ng-template>\n <ng-template [ngIf]=\"header.pipe == 'user'\">\n <ng-container *ngIf=\"data[header.key] | user : header.pipeParameter | async as user; else loading\">\n <ng-container *ngIf=\"user; else noItems\">{{ user }}</ng-container>\n <ng-template #noItems>{{data[header.key]}}</ng-template>\n </ng-container>\n <ng-template #loading><i nz-icon type=\"loading\" theme=\"outline\"></i></ng-template>\n </ng-template>\n <ng-template [ngIf]=\"!header.pipe\">{{ data[header.key]}}</ng-template>\n </a>\n </td>\n </tr>\n </ng-template>\n </tbody>\n</nz-table>",
styles: [".table{margin-top:20px}::ng-deep .table table{background-color:#fff}::ng-deep .ant-table-pagination.ant-pagination{margin-right:20px}::ng-deep .disableLink,::ng-deep .disableLink:active,::ng-deep .disableLink:focus,::ng-deep .disableLink:focus-within,::ng-deep .disableLink:hover,::ng-deep .disableLink:visited{color:rgba(0,0,0,.65);cursor:auto;text-decoration:none}"]
}] }
];
/** @nocollapse */
TableComponent.ctorParameters = () => [
{ type: Router },
{ type: ActivatedRoute }
];
TableComponent.propDecorators = {
data: [{ type: Input }],
headers: [{ type: Input }]
};
if (false) {
/** @type {?} */
TableComponent.prototype.headers;
/** @type {?} */
TableComponent.prototype.fullData;
/** @type {?} */
TableComponent.prototype.displayData;
/** @type {?} */
TableComponent.prototype.tableLoading;
/** @type {?} */
TableComponent.prototype.noPerPage;
/** @type {?} */
TableComponent.prototype.sortName;
/** @type {?} */
TableComponent.prototype.sortValue;
/** @type {?} */
TableComponent.prototype.listOfSearchValue;
/** @type {?} */
TableComponent.prototype.searchKey;
/** @type {?} */
TableComponent.prototype.filterList;
/**
* @type {?}
* @private
*/
TableComponent.prototype.router;
/**
* @type {?}
* @private
*/
TableComponent.prototype.route;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFibGUuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6Im5nOi8vbmd4LWZpcmViYXNlLWNtcy8iLCJzb3VyY2VzIjpbImxpYi9zaGFyZWQvdGFibGUvdGFibGUuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFVLEtBQUssRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUN6RCxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUNoRSxPQUFPLEVBQUUsTUFBTSxFQUFFLGNBQWMsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBT3pELE1BQU0sT0FBTyxjQUFjOzs7OztJQXNCekIsWUFDVSxNQUFjLEVBQ2QsS0FBcUI7UUFEckIsV0FBTSxHQUFOLE1BQU0sQ0FBUTtRQUNkLFVBQUssR0FBTCxLQUFLLENBQWdCO1FBaEJ0QixZQUFPLEdBQUcsRUFBRSxDQUFBO1FBQ3JCLGFBQVEsR0FBRyxFQUFFLENBQUE7UUFDYixnQkFBVyxHQUFHLEVBQUUsQ0FBQTtRQUNoQixpQkFBWSxHQUFHLElBQUksQ0FBQTtRQUNuQixjQUFTLEdBQUcsRUFBRSxDQUFBO1FBS2Qsc0JBQWlCLEdBQUcsRUFBRSxDQUFBO1FBRXRCLGVBQVUsR0FBRyxFQUFFLENBQUE7SUFNWCxDQUFDOzs7OztJQXZCTCxJQUFhLElBQUksQ0FBQyxLQUFVO1FBQzFCLElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFBO1FBQ3JCLElBQUksQ0FBQyxXQUFXLEdBQUcsS0FBSyxDQUFBO1FBQ3hCLElBQUksQ0FBQyxZQUFZLEdBQUcsS0FBSyxDQUFBO1FBQ3pCLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQTtJQUN0QixDQUFDOzs7O0lBb0JELFFBQVE7SUFDUixDQUFDOzs7OztJQUdELGFBQWE7O1lBQ1AsVUFBVSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTTs7OztRQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFD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RCxJQUFJLENBQUMsR0FBRyxFQUFFLElBQUk7UUFDWixJQUFJLEdBQUcsRUFBRTtZQUNQLGdCQUFnQixDQUFDLEdBQUcsQ0FBQyxDQUFDLE9BQU87Ozs7WUFBQyxHQUFHLENBQUMsRUFBRTs7b0JBQzlCLFdBQVcsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRTtnQkFDakMsR0FBRyxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsSUFBSSxHQUFDLEdBQUcsR0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUE7WUFDakQsQ0FBQyxFQUFDLENBQUE7WUFDRixJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUMsVUFBVSxFQUFFLElBQUksQ0FBQyxLQUFLLEVBQUMsQ0FBQyxDQUFBO1NBQ3REO0lBQ0gsQ0FBQzs7O1lBekVGLFNBQVMsU0FBQztnQkFDVCxRQUFRLEVBQUUsVUFBVTtnQkFDcEIsODhEQUFxQzs7YUFFdEM7Ozs7WUFOUSxNQUFNO1lBQUUsY0FBYzs7O21CQVM1QixLQUFLO3NCQU1MLEtBQUs7Ozs7SUFBTixpQ0FBcUI7O0lBQ3JCLGtDQUFhOztJQUNiLHFDQUFnQjs7SUFDaEIsc0NBQW1COztJQUNuQixtQ0FBYzs7SUFHZCxrQ0FBUTs7SUFDUixtQ0FBUzs7SUFDVCwyQ0FBc0I7O0lBQ3RCLG1DQUFTOztJQUNULG9DQUFlOzs7OztJQUliLGdDQUFzQjs7Ozs7SUFDdEIsK0JBQTZCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBPbkluaXQsIElucHV0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBnZXRJbnRlcnBvbGF0aW9uIH0gZnJvbSAnLi4vLi4vc2VydmljZS9oZWxwZXIuc2VydmljZSc7XG5pbXBvcnQgeyBSb3V0ZXIsIEFjdGl2YXRlZFJvdXRlIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnYXEtdGFibGUnLFxuICB0ZW1wbGF0ZVVybDogJy4vdGFibGUuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi90YWJsZS5jb21wb25lbnQuY3NzJ11cbn0pXG5leHBvcnQgY2xhc3MgVGFibGVDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQge1xuICBcbiAgQElucHV0KCkgc2V0IGRhdGEodmFsdWU6IGFueSkge1xuICAgIHRoaXMuZnVsbERhdGEgPSB2YWx1ZVxuICAgIHRoaXMuZGlzcGxheURhdGEgPSB2YWx1ZVxuICAgIHRoaXMudGFibGVMb2FkaW5nID0gZmFsc2VcbiAgICB0aGlzLmdldEZpbHRlckxpc3QoKVxuICB9XG4gIEBJbnB1dCgpIGhlYWRlcnMgPSBbXVxuICBmdWxsRGF0YSA9IFtdXG4gIGRpc3BsYXlEYXRhID0gW11cbiAgdGFibGVMb2FkaW5nID0gdHJ1ZVxuICBub1BlclBhZ2UgPSAxMFxuXG4gIC8vIHNvcnQgJiBmaWx0ZXJcbiAgc29ydE5hbWVcbiAgc29ydFZhbHVlXG4gIGxpc3RPZlNlYXJjaFZhbHVlID0gW11cbiAgc2VhcmNoS2V5XG4gIGZpbHRlckxpc3QgPSB7fVxuIFxuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgcm91dGVyOiBSb3V0ZXIsXG4gICAgcHJpdmF0ZSByb3V0ZTogQWN0aXZhdGVkUm91dGVcbiAgKSB7IH1cblxuICBuZ09uSW5pdCgpIHtcbiAgfVxuXG4gIC8qIEZpbHRlcmluZyAmIFNvcnRpbmcgKi9cbiAgZ2V0RmlsdGVyTGlzdCgpIHtcbiAgICBsZXQgZmlsdGVyS2V5cyA9IHRoaXMuaGVhZGVycy5maWx0ZXIocmVzID0+IHJlc1snY2FuRmlsdGVyJ10pLm1hcChyZXMgPT4gcmVzWydrZXknXSlcbiAgICBmaWx0ZXJLZXlzLmZvckVhY2goa2V5ID0+IHtcbiAgICAgIHRoaXMuZmlsdGVyTGlzdFtrZXldID0gdGhpcy5mdWxsRGF0YS5tYXAocmVzID0+IHJlc1trZXldKS5maWx0ZXIoKHZhbHVlLCBpbmRleCwgc2VsZikgPT4gc2VsZi5pbmRleE9mKHZhbHVlKSA9PT0gaW5kZXgpLnNvcnQoKGEsIGIpID0+IChhID4gYiA/IDEgOiAtMSkpLm1hcChyZXMgPT4ge3JldHVybiB7IFwidGV4dFwiOiByZXMsIFwidmFsdWVcIjogcmVzIH19KVxuICAgIH0pXG4gIH1cblxuICBzb3J0KHNvcnQ6IHsga2V5OiBzdHJpbmcsIHZhbHVlOiBzdHJpbmcgfSkge1xuICAgIHRoaXMuc29ydE5hbWUgPSBzb3J0LmtleTtcbiAgICB0aGlzLnNvcnRWYWx1ZSA9IHNvcnQudmFsdWU7XG4gICAgdGhpcy5zZWFyY2goKTtcbiAgfVxuXG4gIGZpbHRlcihldmVudCwgdXVpZCkge1xuICAgIHRoaXMubGlzdE9mU2VhcmNoVmFsdWUgPSBldmVudDtcbiAgICB0aGlzLnNlYXJjaEtleSA9IHV1aWQ7XG4gICAgdGhpcy5zZWFyY2goKTtcbiAgfVxuXG4gIHNlYXJjaCgpIHtcbiAgICBjb25zdCBmaWx0ZXJGdW5jID0gaXRlbSA9PiB0aGlzLmxpc3RPZlNlYXJjaFZhbHVlLmxlbmd0aCA/IHRoaXMubGlzdE9mU2VhcmNoVmFsdWUuc29tZShuYW1lID0+IGl0ZW1bdGhpcy5zZWFyY2hLZXldLmluZGV4T2YobmFtZSkgIT09IC0xKSA6IHRydWU7XG4gICAgY29uc3QgZGF0YSA9IHRoaXMuZnVsbERhdGEuZmlsdGVyKGl0ZW0gPT4gZmlsdGVyRnVuYyhpdGVtKSlcbiAgICBpZiAodGhpcy5zb3J0TmFtZSAmJiB0aGlzLnNvcnRWYWx1ZSkge1xuICAgICAgdGhpcy5kaXNwbGF5RGF0YSA9IGRhdGEuc29ydCgoYSwgYikgPT4gKHRoaXMuc29ydFZhbHVlID09PSAnYXNjZW5kJykgPyAoYVt0aGlzLnNvcnROYW1lXSA+IGJbdGhpcy5zb3J0TmFtZV0gPyAxIDogLTEpIDogKGJbdGhpcy5zb3J0TmFtZV0gPiBhW3RoaXMuc29ydE5hbWVdID8gMSA6IC0xKSlcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5kaXNwbGF5RGF0YSA9IGRhdGFcbiAgICB9XG4gIH1cblxuICBnb1RvKHVybCwgZGF0YSkge1xuICAgIGlmICh1cmwpIHtcbiAgICAgIGdldEludGVycG9sYXRpb24odXJsKS5mb3JFYWNoKGtleSA9PiB7XG4gICAgICAgIGxldCByZXBsYWNlbWVudCA9IGRhdGFba2V5XSB8fCBcIlwiXG4gICAgICAgIHVybCA9IHVybC5zcGxpdChcIiR7XCIra2V5K1wifVwiKS5qb2luKHJlcGxhY2VtZW50KVxuICAgICAgfSlcbiAgICAgIHRoaXMucm91dGVyLm5hdmlnYXRlKFt1cmxdLCB7cmVsYXRpdmVUbzogdGhpcy5yb3V0ZX0pXG4gICAgfVxuICB9XG4gIFxuXG59XG4iXX0=