UNPKG

ng2-json-editor

Version:

Angular2 component for editing large json documents

273 lines 17.6 kB
/* * This file is part of ng2-json-editor. * Copyright (C) 2016 CERN. * * ng2-json-editor is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * ng2-json-editor is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with ng2-json-editor; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. * In applying this license, CERN does not * waive the privileges and immunities granted to it by virtue of its status * as an Intergovernmental Organization or submit itself to any jurisdiction. */ var __extends = (this && this.__extends) || (function () { var extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); import { Component, Input, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; import { AbstractListFieldComponent } from '../abstract-list-field'; import { AppGlobalsService, JsonStoreService, DomUtilService, PathUtilService, ListPageChangerService, ProblemsService, EmptyValueService, } from '../shared/services'; var ComplexListFieldComponent = (function (_super) { __extends(ComplexListFieldComponent, _super); function ComplexListFieldComponent(appGlobalsService, problemsService, jsonStoreService, domUtilService, pathUtilService, changeDetectorRef, emptyValueService, listPageChangerService) { var _this = _super.call(this, appGlobalsService, problemsService, jsonStoreService, pathUtilService, changeDetectorRef) || this; _this.appGlobalsService = appGlobalsService; _this.problemsService = problemsService; _this.jsonStoreService = jsonStoreService; _this.domUtilService = domUtilService; _this.pathUtilService = pathUtilService; _this.changeDetectorRef = changeDetectorRef; _this.emptyValueService = emptyValueService; _this.listPageChangerService = listPageChangerService; _this.currentFound = 0; _this.currentPage = 1; _this._shouldDisplayOnlyEditFormItems = false; return _this; } ComplexListFieldComponent.prototype.ngOnInit = function () { var _this = this; _super.prototype.ngOnInit.call(this); this.navigator = this.schema.longListNavigatorConfig; this.paginatableItems = this.getPaginatableItems(); this.paginatedItems = this.getPaginatableItemsForPage(this.currentPage); if (this.navigator) { this.listPageChangerService .registerPaginatedList(this.pathString, this.navigator.itemsPerPage) .skipWhile(function (page) { return page === _this.currentPage; }) .takeUntil(this.isDestroyed) .subscribe(function (page) { return _this.onPageChange(page); }); } }; ComplexListFieldComponent.prototype.ngOnChanges = function (changes) { _super.prototype.ngOnChanges.call(this, changes); var valuesChange = changes['values']; if (valuesChange && !valuesChange.isFirstChange()) { var preSize = valuesChange.previousValue.size; var curSize = valuesChange.currentValue.size; if (curSize !== preSize) { if (this.navigator) { // check if element added in the end by comparing the last elements var elementAddedToEnd = valuesChange.previousValue.equals(valuesChange.currentValue.pop()); var lastPage = this.getPageForIndex(curSize - 1); // change the page if a new element is added in the end and it's not on the last page if (curSize > preSize && this.currentPage !== lastPage && elementAddedToEnd) { this.currentPage = lastPage; } } } this.paginatableItems = this.getPaginatableItems(); this.paginatedItems = this.getPaginatableItemsForPage(this.currentPage); } }; ComplexListFieldComponent.prototype.hasProblemOrPatch = function (index) { var itemPath = this.getPathStringForChild(index); return this.problemsService.hasProblem(itemPath) || this.jsonStoreService.hasPatchOrChildrenHavePatch(itemPath); }; Object.defineProperty(ComplexListFieldComponent.prototype, "headerItemTemplate", { get: function () { return this.appGlobalsService.templates[this.navigator.headerItemTemplateName]; }, enumerable: true, configurable: true }); ComplexListFieldComponent.prototype.onFindClick = function () { var _this = this; // clear for new search this.foundIndices = []; this.currentFound = 0; // search to look for the first match if (this.navigator.findSingle) { var foundIndex = this.values .findIndex(function (value) { return _this.navigator.findSingle(value, _this.findExpression); }); if (foundIndex > -1) { this.foundIndices.push(foundIndex); } } // search to look for all matches if (this.foundIndices.length === 0 && this.navigator.findMultiple) { this.values .forEach(function (value, index) { if (_this.navigator.findMultiple(value, _this.findExpression)) { _this.foundIndices.push(index); } }); } // navigate to first search result if found any if (this.foundIndices.length > 0) { this.navigateToItem(this.foundIndices[0]); this.shouldDisplayFoundNavigation = true; } else { this.shouldDisplayFoundNavigation = false; } }; ComplexListFieldComponent.prototype.onAddNewElementAtPosition = function (index) { var _this = this; var itemSchema = this.schema.items; var emptyValue = this.emptyValueService.generateEmptyValue(itemSchema); var values = this.jsonStoreService.getIn(this.path); var insertIndex; if (this.navigator) { insertIndex = index + (this.navigator.itemsPerPage * (this.currentPage - 1)); } else { insertIndex = index; } var insertPath = this.path.concat(insertIndex); this.jsonStoreService.addIn(insertPath, emptyValue); // focus on the new added element var insertPathString = this.pathUtilService.toPathString(insertPath); setTimeout(function () { _this.domUtilService.focusAndSelectFirstEditableChildById(insertPathString); }); }; ComplexListFieldComponent.prototype.onFindInputKeypress = function (key) { if (key === 'Enter') { this.onFindClick(); } }; ComplexListFieldComponent.prototype.onFoundNavigate = function (direction) { // No bound checks, since the buttons are disabled in these cases. this.currentFound += direction; this.navigateToItem(this.foundIndices[this.currentFound]); }; ComplexListFieldComponent.prototype.navigateToItem = function (index) { var _this = this; var item = this.paginatableItems.get(index); if (!item.editFormDisplayedByUser) { item.editFormDisplayedByUser = true; this.changeDetectorRef.markForCheck(); } var itemPath = this.path.concat(index); var itemId = this.pathUtilService.toPathString(itemPath); setTimeout(function () { return _this.domUtilService.focusAndSelectFirstEditableChildById(itemId); }); }; ComplexListFieldComponent.prototype.onPageChange = function (page) { this.currentPage = page; this.paginatedItems = this.getPaginatableItemsForPage(page); }; ComplexListFieldComponent.prototype.getPaginatableItemsForPage = function (page) { if (this.navigator) { var begin = (page - 1) * this.navigator.itemsPerPage; var end = (page * this.navigator.itemsPerPage); return this.paginatableItems.slice(begin, end); } else { return this.paginatableItems; } }; ComplexListFieldComponent.prototype.getPaginatableItems = function () { var _this = this; var viewTemplateConfig = this.schema.viewTemplateConfig; return this.values .map(function (value, index) { var paginatableItem = _this.paginatableItems ? _this.paginatableItems.get(index) : null; var isNewItem = paginatableItem == null; var editFormDisplayedByUser = isNewItem ? null : paginatableItem.editFormDisplayedByUser; var shouldDisplayEditForm = viewTemplateConfig ? viewTemplateConfig.showEditForm(value) : true; return { index: index, shouldDisplayEditForm: shouldDisplayEditForm, editFormDisplayedByUser: editFormDisplayedByUser }; }).filter(function (item) { if (_this.shouldDisplayOnlyEditFormItems) { return item.shouldDisplayEditForm; } else { return true; } }); }; ComplexListFieldComponent.prototype.getPageForIndex = function (index) { return Math.floor((index / this.navigator.itemsPerPage) + 1); }; Object.defineProperty(ComplexListFieldComponent.prototype, "customTemplate", { get: function () { return this.appGlobalsService.templates[this.schema.viewTemplateConfig.itemTemplateName]; }, enumerable: true, configurable: true }); Object.defineProperty(ComplexListFieldComponent.prototype, "shouldDisplayViewTemplate", { get: function () { return this.schema.viewTemplateConfig !== undefined; }, enumerable: true, configurable: true }); Object.defineProperty(ComplexListFieldComponent.prototype, "sortable", { get: function () { return this.schema.sortable && !this.shouldDisplayOnlyEditFormItems; }, enumerable: true, configurable: true }); ComplexListFieldComponent.prototype.shouldDisplayEditableFieldsForItem = function (item) { // override default display state that is based on viewTemplateConfig.showEditForm(item) with user action var shouldDisplayEditForm = item.editFormDisplayedByUser != null ? item.editFormDisplayedByUser : item.shouldDisplayEditForm; return shouldDisplayEditForm || this.hasProblemOrPatch(item.index); }; Object.defineProperty(ComplexListFieldComponent.prototype, "shouldDisplayOnlyEditFormItems", { get: function () { return this._shouldDisplayOnlyEditFormItems; }, set: function (value) { this.currentPage = 1; this._shouldDisplayOnlyEditFormItems = value; this.paginatableItems = this.getPaginatableItems(); this.paginatedItems = this.getPaginatableItemsForPage(this.currentPage); }, enumerable: true, configurable: true }); return ComplexListFieldComponent; }(AbstractListFieldComponent)); export { ComplexListFieldComponent }; ComplexListFieldComponent.decorators = [ { type: Component, args: [{ selector: 'complex-list-field', styles: [".complex-list-field-wrapper { margin: 10px 15px 15px 10px; padding: 5px; box-shadow: 0 0 3px 1px rgba(0, 0, 0, 0.25); } .top-bar-container { width: 100%; position: sticky; top: 46px; z-index: 1; display: flex; align-items: center; justify-content: space-between; padding: 0 15px; background-color: white; box-shadow: 0 0.5px 0 0 #ffffff inset, 0 1px 2px 0 #B3B3B3; } .item-count-label { position: relative; top: -19px; } .transparent { background: transparent; } .borderless { border: none; } .find-button { color: darkslategray; } .find-button .fa-search { opacity: 0.83; } .element-button-container { padding-top: 8px; } .element-button-container .text-right { padding: 0px; } label.btn { color: white !important; } .add-new-element { text-align: right; } "], template: "<div [id]=\"pathString\"> <!-- Top Bar: Navigator, ToEdit/All switch, custom header item etc. --> <div *ngIf=\"navigator || shouldDisplayViewTemplate\" class=\"top-bar-container\"> <div *ngIf=\"navigator\"> <div class=\"input-group input-group-sm\"> <span class=\"input-group-btn\"> <button type=\"button\" class=\"btn btn-default find-button\" (click)=\"onFindClick()\"> <i class=\"fa fa-search\" aria-hidden=\"true\"></i> </button> </span> <input type=\"search\" class=\"form-control\" [(ngModel)]=\"findExpression\" (keypress)=\"onFindInputKeypress($event.key)\" placeholder=\"Find\" /> <span class=\"input-group-btn\" *ngIf=\"shouldDisplayFoundNavigation\"> <button type=\"button\" class=\"btn btn-default\" [disabled]=\"currentFound <= 0\" (click)=\"onFoundNavigate(-1)\">❮</button> </span> <span class=\"input-group-btn\" *ngIf=\"shouldDisplayFoundNavigation\"> <button type=\"button\" class=\"btn btn-default\" [disabled]=\"currentFound >= foundIndices.length - 1\" (click)=\"onFoundNavigate(1)\">❯</button> </span> <span *ngIf=\"foundIndices\" [ngSwitch]=\"foundIndices.length\" class=\"input-group-addon transparent borderless\"> <span *ngSwitchCase=\"0\"> Nothing found </span> <span *ngSwitchDefault> {{currentFound + 1}} of {{foundIndices.length}} </span> </span> </div> </div> <div *ngIf=\"shouldDisplayViewTemplate\" class=\"btn-group\"> <label class=\"btn btn-switch\" [class.active]=\"!shouldDisplayOnlyEditFormItems\" (click)=\"shouldDisplayOnlyEditFormItems = false\">All</label> <label class=\"btn btn-switch\" [class.active]=\"shouldDisplayOnlyEditFormItems\" (click)=\"shouldDisplayOnlyEditFormItems = true\">To Edit</label> </div> <div *ngIf=\"headerItemTemplate\"> <ng-template [ngTemplateOutlet]=\"headerItemTemplate\"></ng-template> </div> <div *ngIf=\"navigator\"> <label class=\"item-count-label\"> {{paginatableItems.size}} {{path[path.length - 1]}} </label> <br> <pagination [totalItems]=\"paginatableItems.size\" [ngModel]=\"currentPage\" [maxSize]=\"navigator.maxVisiblePageCount\" [itemsPerPage]=\"navigator.itemsPerPage\" class=\"pagination-sm pagination-top\" [boundaryLinks]=\"true\" [rotate]=\"false\" [firstText]=\"'❮❮'\" [previousText]=\"'❮'\" [nextText]=\"'❯'\" [lastText]=\"'❯❯'\" (pageChanged)=\"onPageChange($event.page)\"></pagination> </div> </div> <div [ngClass]=\"redLeftBorderClass\"> <!-- Elements --> <div *ngFor=\"let item of paginatedItems; index as i; trackBy:trackByElement\"> <div class=\"complex-list-field-wrapper\"> <div class=\"add-new-element\"> <a href=\"javascript:void(0)\" (click)=\"onAddNewElementAtPosition(i)\"> Add new element here </a> </div> <span *ngIf=\"shouldDisplayViewTemplate && values.get(item.index).keySeq().size != 0\"> <ng-template [ngTemplateOutlet]=\"customTemplate\" [ngTemplateOutletContext]=\"{item: values.get(item.index)}\"></ng-template> <a href=\"javascript:void(0)\" (click)=\"item.editFormDisplayedByUser = !shouldDisplayEditableFieldsForItem(item)\"> {{shouldDisplayEditableFieldsForItem(item) ? 'Hide Fields' : 'Show Fields'}} </a> </span> <span *ngIf=\"shouldDisplayEditableFieldsForItem(item)\"> <object-field [value]=\"values.get(item.index)\" [schema]=\"schema.items\" [path]=\"getPathForChild(item.index)\" [isComplexListFieldItem]=\"true\"> </object-field> <div class=\"row element-button-container\"> <div class=\"col-md-12 text-right\"> <list-action-group (onMove)=\"moveElement(item.index, $event)\" (onDelete)=\"deleteElement(item.index, values.get(item.index))\" [canMove]=\"sortable\" [isDisabled]=\"disabled || hasPatchOrChildrenHavePatch()\"> </list-action-group> </div> </div> </span> </div> </div> <div class=\"text-right\" *ngIf=\"removeJsonPatch\"> <patch-actions [patch]=\"removeJsonPatch\"></patch-actions> </div> </div> <div *ngFor=\"let patch of addJsonPatches\" class=\"complex-list-field-wrapper\"> <add-or-replace-patch [patch]=\"patch\"></add-or-replace-patch> </div> <div *ngIf=\"replaceJsonPatches && replaceJsonPatches[0]\"> <add-or-replace-patch [patch]=\"replaceJsonPatches[0]\"></add-or-replace-patch> </div> </div> ", changeDetection: ChangeDetectionStrategy.OnPush },] }, ]; /** @nocollapse */ ComplexListFieldComponent.ctorParameters = function () { return [ { type: AppGlobalsService, }, { type: ProblemsService, }, { type: JsonStoreService, }, { type: DomUtilService, }, { type: PathUtilService, }, { type: ChangeDetectorRef, }, { type: EmptyValueService, }, { type: ListPageChangerService, }, ]; }; ComplexListFieldComponent.propDecorators = { 'values': [{ type: Input },], 'supportValues': [{ type: Input },], 'schema': [{ type: Input },], 'path': [{ type: Input },], }; //# sourceMappingURL=complex-list-field.component.js.map