UNPKG

ngx-diagrams

Version:

This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 7.2.0.

719 lines 76.4 kB
/** * @fileoverview added by tsickle * Generated from: lib/containers/diagram/diagram.component.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ import * as tslib_1 from "tslib"; import { Component, Input, Renderer2, Output, EventEmitter, ViewChild, ViewContainerRef, ElementRef, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; import { DiagramModel } from '../../models/diagram.model'; import { NodeModel } from '../../models/node.model'; import { BehaviorSubject, combineLatest, ReplaySubject } from 'rxjs'; import { filter, takeUntil } from 'rxjs/operators'; import { MoveCanvasAction, SelectingAction, LinkCreatedAction } from '../../actions'; import { MoveItemsAction } from '../../actions/move-items.action'; import { PointModel } from '../../models/point.model'; import { PortModel } from '../../models/port.model'; import { some } from 'lodash'; var NgxDiagramComponent = /** @class */ (function () { function NgxDiagramComponent(renderer, cdRef) { var _this = this; this.renderer = renderer; this.cdRef = cdRef; this.allowCanvasZoon = true; this.allowCanvasTranslation = true; this.inverseZoom = true; this.allowLooseLinks = true; this.actionStartedFiring = new EventEmitter(); this.actionStillFiring = new EventEmitter(); this.actionStoppedFiring = new EventEmitter(); this.action$ = new BehaviorSubject(null); this.destroyed$ = new ReplaySubject(1); this.mouseUpListener = (/** * @return {?} */ function () { }); this.mouseMoveListener = (/** * @return {?} */ function () { }); this.onMouseUp = (/** * @param {?} event * @return {?} */ function (event) { /** @type {?} */ var diagramEngine = _this.diagramModel.getDiagramEngine(); /** @type {?} */ var action = _this.action$.getValue(); // are we going to connect a link to something? if (action instanceof MoveItemsAction) { /** @type {?} */ var element_1 = _this.getMouseElement(event); action.selectionModels.forEach((/** * @param {?} model * @return {?} */ function (model) { // only care about points connecting to things if (!(model.model instanceof PointModel)) { return; } if (element_1 && element_1.model instanceof PortModel && !diagramEngine.isModelLocked(element_1.model)) { /** @type {?} */ var link = model.model.getLink(); if (link.getTargetPort() !== null) { // if this was a valid link already and we are adding a node in the middle, create 2 links from the original if (link.getTargetPort() !== element_1.model && link.getSourcePort() !== element_1.model) { /** @type {?} */ var targetPort = link.getTargetPort(); /** @type {?} */ var newLink = link.clone({}); newLink.setSourcePort(element_1.model); newLink.setTargetPort(targetPort); link.setTargetPort(element_1.model); targetPort.removeLink(link); newLink.removePointsBefore(newLink.getPoints()[link.getPointIndex(model.model)]); link.removePointsAfter(model.model); diagramEngine.getDiagramModel().addLink(newLink); // if we are connecting to the same target or source, destroy tweener points } else if (link.getTargetPort() === element_1.model) { link.removePointsAfter(model.model); } else if (link.getSourcePort() === element_1.model) { link.removePointsBefore(model.model); } } else { link.setTargetPort(element_1.model); /** @type {?} */ var targetPort = link.getTargetPort(); /** @type {?} */ var srcPort = link.getSourcePort(); if (targetPort.id !== srcPort.id) { // link is valid, fire the event _this.startFiringAction(new LinkCreatedAction(event.clientX, event.clientY, link)); } } } })); // check for / destroy any loose links in any models which have been moved if (!_this.allowLooseLinks) { action.selectionModels.forEach((/** * @param {?} model * @return {?} */ function (model) { // only care about points connecting to things if (!(model.model instanceof PointModel)) { return; } /** @type {?} */ var selectedPoint = model.model; /** @type {?} */ var link = selectedPoint.getLink(); if (link.getSourcePort() === null || link.getTargetPort() === null) { link.destroy(); } })); } // destroy any invalid links action.selectionModels.forEach((/** * @param {?} model * @return {?} */ function (model) { // only care about points connecting to things if (!(model.model instanceof PointModel)) { return; } /** @type {?} */ var link = model.model.getLink(); /** @type {?} */ var sourcePort = link.getSourcePort(); /** @type {?} */ var targetPort = link.getTargetPort(); if (sourcePort !== null && targetPort !== null) { if (!sourcePort.canLinkToPort(targetPort)) { // link not allowed link.destroy(); } else if (some(Object.values(targetPort.getLinks()), (/** * @param {?} l * @return {?} */ function (l) { return l !== link && (l.getSourcePort() === sourcePort || l.getTargetPort() === sourcePort); }))) { // link is a duplicate link.destroy(); } } })); _this.stopFiringAction(); } else { _this.stopFiringAction(); } _this.mouseUpListener(); _this.mouseMoveListener(); _this.action$.next(null); }); this.onMouseMove = (/** * @param {?} event * @return {?} */ function (event) { /** @type {?} */ var action = _this.action$.getValue(); if (action === null || action === undefined) { return; } if (action instanceof SelectingAction) { /** @type {?} */ var relative = _this.diagramModel.getDiagramEngine().getRelativePoint(event.clientX, event.clientY); Object.values(_this.diagramModel.getNodes()).forEach((/** * @param {?} node * @return {?} */ function (node) { if (((/** @type {?} */ (action))).containsElement(node.getCoords(), _this.diagramModel)) { node.setSelected(); } else { node.setSelected(false); } })); Object.values(_this.diagramModel.getLinks()).forEach((/** * @param {?} link * @return {?} */ function (link) { /** @type {?} */ var allSelected = true; link.getPoints().forEach((/** * @param {?} point * @return {?} */ function (point) { if (((/** @type {?} */ (action))).containsElement(point.getCoords(), _this.diagramModel)) { point.setSelected(); } else { point.setSelected(false); allSelected = false; } })); if (allSelected) { link.setSelected(); } })); action.mouseX2 = relative.x; action.mouseY2 = relative.y; _this.fireAction(); _this.action$.next(action); return; } else if (action instanceof MoveItemsAction) { /** @type {?} */ var coords_1 = { x: event.clientX - action.mouseX, y: event.clientY - action.mouseY }; /** @type {?} */ var amountZoom_1 = _this.diagramModel.getZoomLevel() / 100; action.selectionModels.forEach((/** * @param {?} model * @return {?} */ function (model) { // in this case we need to also work out the relative grid position if (model.model instanceof NodeModel || (model.model instanceof PointModel && !model.model.isConnectedToPort())) { /** @type {?} */ var newCoords = { x: model.initialX + coords_1.x / amountZoom_1, y: model.initialY + coords_1.y / amountZoom_1 }; model.model.setCoords(_this.diagramModel.getGridPosition(newCoords)); if (model.model instanceof NodeModel) { // update port coordinates as well Object.values(model.model.getPorts()).forEach((/** * @param {?} port * @return {?} */ function (port) { /** @type {?} */ var portCoords = _this.diagramModel.getDiagramEngine().getPortCoords(port); port.updateCoords(portCoords); })); } } else if (model.model instanceof PointModel) { // we want points that are connected to ports, to not necessarily snap to grid // this stuff needs to be pixel perfect, dont touch it /** @type {?} */ var newCoords = _this.diagramModel.getGridPosition({ x: coords_1.x / amountZoom_1, y: coords_1.y / amountZoom_1 }); model.model.setCoords({ x: model.initialX + newCoords.x, y: model.initialY + newCoords.y }); } })); _this.fireAction(); } else if (action instanceof MoveCanvasAction) { if (_this.allowCanvasTranslation) { _this.diagramModel.setOffset(action.initialOffsetX + (event.clientX - action.mouseX), action.initialOffsetY + (event.clientY - action.mouseY)); _this.fireAction(); } } }); } // TODO: handle destruction of container, resseting all observables to avoid memory leaks! // TODO: handle destruction of container, resseting all observables to avoid memory leaks! /** * @return {?} */ NgxDiagramComponent.prototype.ngOnInit = // TODO: handle destruction of container, resseting all observables to avoid memory leaks! /** * @return {?} */ function () { var _this = this; if (this.diagramModel) { this.diagramModel.getDiagramEngine().setCanvas(this.canvas.nativeElement); this.nodes$ = this.diagramModel.selectNodes(); this.links$ = this.diagramModel.selectLinks(); this.nodesRendered$ = new BehaviorSubject(false); this.nodes$.pipe(takeUntil(this.destroyed$)).subscribe((/** * @param {?} nodes * @return {?} */ function (nodes) { _this.nodesRendered$.next(false); Object.values(nodes).forEach((/** * @param {?} node * @return {?} */ function (node) { if (!node.getPainted()) { _this.diagramModel.getDiagramEngine().generateWidgetForNode(node, _this.nodesLayer); node.setPainted(); _this.cdRef.detectChanges(); } })); _this.nodesRendered$.next(true); })); } }; /** * @return {?} */ NgxDiagramComponent.prototype.ngOnDestroy = /** * @return {?} */ function () { this.destroyed$.next(true); this.destroyed$.complete(); }; /** * @return {?} */ NgxDiagramComponent.prototype.ngAfterViewInit = /** * @return {?} */ function () { var _this = this; combineLatest([this.nodesRendered$, this.links$]) .pipe(takeUntil(this.destroyed$), filter((/** * @param {?} __0 * @return {?} */ function (_a) { var _b = tslib_1.__read(_a, 2), nodesRendered = _b[0], _ = _b[1]; return !!nodesRendered; }))) .subscribe((/** * @param {?} __0 * @return {?} */ function (_a) { var _b = tslib_1.__read(_a, 2), _ = _b[0], links = _b[1]; Object.values(links).forEach((/** * @param {?} link * @return {?} */ function (link) { if (!link.getPainted()) { if (link.getSourcePort() !== null) { /** @type {?} */ var portCenter = _this.diagramModel.getDiagramEngine().getPortCenter(link.getSourcePort()); link.getPoints()[0].setCoords(portCenter); /** @type {?} */ var portCoords = _this.diagramModel.getDiagramEngine().getPortCoords(link.getSourcePort()); link.getSourcePort().updateCoords(portCoords); } if (link.getTargetPort() !== null) { /** @type {?} */ var portCenter = _this.diagramModel.getDiagramEngine().getPortCenter(link.getTargetPort()); link.getPoints()[link.getPoints().length - 1].setCoords(portCenter); /** @type {?} */ var portCoords = _this.diagramModel.getDiagramEngine().getPortCoords(link.getTargetPort()); link.getTargetPort().updateCoords(portCoords); } _this.diagramModel.getDiagramEngine().generateWidgetForLink(link, _this.linksLayer); link.setPainted(); _this.cdRef.detectChanges(); } })); })); }; /** * fire the action registered and notify subscribers */ /** * fire the action registered and notify subscribers * @return {?} */ NgxDiagramComponent.prototype.fireAction = /** * fire the action registered and notify subscribers * @return {?} */ function () { if (this.action$.value) { this.actionStillFiring.emit(this.action$.value); } }; /** * Unregister the action, post firing and notify subscribers */ /** * Unregister the action, post firing and notify subscribers * @param {?=} shouldSkipEvent * @return {?} */ NgxDiagramComponent.prototype.stopFiringAction = /** * Unregister the action, post firing and notify subscribers * @param {?=} shouldSkipEvent * @return {?} */ function (shouldSkipEvent) { if (!shouldSkipEvent) { this.actionStoppedFiring.emit(this.action$.value); } this.action$.next(null); }; /** * Register the new action, pre firing and notify subscribers */ /** * Register the new action, pre firing and notify subscribers * @param {?} action * @return {?} */ NgxDiagramComponent.prototype.startFiringAction = /** * Register the new action, pre firing and notify subscribers * @param {?} action * @return {?} */ function (action) { this.action$.next(action); this.actionStartedFiring.emit(action); }; /** * @return {?} */ NgxDiagramComponent.prototype.selectAction = /** * @return {?} */ function () { return this.action$; }; /** * @return {?} */ NgxDiagramComponent.prototype.shouldDrawSelectionBox = /** * @return {?} */ function () { /** @type {?} */ var action = this.action$.getValue(); if (action instanceof SelectingAction) { action.getBoxDimensions(); return true; } return false; }; /** * @param {?} event * @return {?} */ NgxDiagramComponent.prototype.getMouseElement = /** * @param {?} event * @return {?} */ function (event) { /** @type {?} */ var target = (/** @type {?} */ (event.target)); // is it a port? /** @type {?} */ var element = target.closest('[data-portid]'); if (element) { // get the relevant node and return the port. /** @type {?} */ var nodeEl = target.closest('[data-nodeid]'); return { model: this.diagramModel.getNode(nodeEl.getAttribute('data-nodeid')).getPort(element.getAttribute('data-portid')), element: element }; } // look for a point element = target.closest('[data-pointid]'); if (element) { return { model: this.diagramModel.getLink(element.getAttribute('data-linkid')).getPointModel(element.getAttribute('data-pointid')), element: element }; } // look for a link element = target.closest('[data-linkid]'); if (element) { return { model: this.diagramModel.getLink(element.getAttribute('data-linkid')), element: element }; } // a node maybe element = target.closest('[data-nodeid]'); if (element) { return { model: this.diagramModel.getNode(element.getAttribute('data-nodeid')), element: element }; } // just the canvas return null; }; /** * @param {?} event * @return {?} */ NgxDiagramComponent.prototype.onMouseDown = /** * @param {?} event * @return {?} */ function (event) { if (event.button === 3) { return; } /** @type {?} */ var selectedModel = this.getMouseElement(event); // canvas selected if (selectedModel === null) { // multiple selection if (event.shiftKey) { // initiate multiple selection selector /** @type {?} */ var relative = this.diagramModel.getDiagramEngine().getRelativePoint(event.clientX, event.clientY); this.startFiringAction(new SelectingAction(relative.x, relative.y)); } else { // drag canvas action this.diagramModel.clearSelection(); this.startFiringAction(new MoveCanvasAction(event.clientX, event.clientY, this.diagramModel)); } } else if (selectedModel.model instanceof PortModel) { // its a port element, we want to drag a link if (!this.diagramModel.getDiagramEngine().isModelLocked(selectedModel.model)) { /** @type {?} */ var relative = this.diagramModel.getDiagramEngine().getRelativeMousePoint(event); /** @type {?} */ var sourcePort = selectedModel.model; /** @type {?} */ var link = sourcePort.createLinkModel(); link.setSourcePort(sourcePort); if (link) { link.removeMiddlePoints(); if (link.getSourcePort() !== sourcePort) { link.setSourcePort(sourcePort); } link.setTargetPort(null); link.getFirstPoint().setCoords(relative); link.getLastPoint().setCoords(relative); this.diagramModel.clearSelection(); link.getLastPoint().setSelected(); this.diagramModel.addLink(link); this.startFiringAction(new MoveItemsAction(event.clientX, event.clientY, this.diagramModel.getDiagramEngine())); } } else { this.diagramModel.clearSelection(); } } else { // its some other element, probably want to move it if (!event.shiftKey && !selectedModel.model.getSelected()) { this.diagramModel.clearSelection(); } selectedModel.model.setSelected(); this.startFiringAction(new MoveItemsAction(event.clientX, event.clientY, this.diagramModel.getDiagramEngine())); } // create mouseMove and mouseUp listeners this.mouseMoveListener = this.renderer.listen(document, 'mousemove', this.onMouseMove); this.mouseUpListener = this.renderer.listen(document, 'mouseup', this.onMouseUp); }; /** * @param {?} event * @return {?} */ NgxDiagramComponent.prototype.onMouseWheel = /** * @param {?} event * @return {?} */ function (event) { if (this.allowCanvasZoon) { event.preventDefault(); event.stopPropagation(); /** @type {?} */ var currentZoomLevel = this.diagramModel.getZoomLevel(); /** @type {?} */ var oldZoomFactor = currentZoomLevel / 100; /** @type {?} */ var scrollDelta = this.inverseZoom ? -event.deltaY : event.deltaY; // check if it is pinch gesture if (event.ctrlKey && scrollDelta % 1 !== 0) { /* Chrome and Firefox sends wheel event with deltaY that have fractional part, also `ctrlKey` prop of the event is true though ctrl isn't pressed */ scrollDelta /= 3; } else { scrollDelta /= 60; } if (currentZoomLevel + scrollDelta > 10) { this.diagramModel.setZoomLevel(currentZoomLevel + scrollDelta); } /** @type {?} */ var zoomFactor = this.diagramModel.getZoomLevel() / 100; /** @type {?} */ var boundingRect = ((/** @type {?} */ (event.currentTarget))).getBoundingClientRect(); /** @type {?} */ var clientWidth = boundingRect.width; /** @type {?} */ var clientHeight = boundingRect.height; // compute difference between rect before and after scroll /** @type {?} */ var widthDiff = clientWidth * zoomFactor - clientWidth * oldZoomFactor; /** @type {?} */ var heightDiff = clientHeight * zoomFactor - clientHeight * oldZoomFactor; // compute mouse coords relative to canvas /** @type {?} */ var clientX = event.clientX - boundingRect.left; /** @type {?} */ var clientY = event.clientY - boundingRect.top; // compute width and height increment factor /** @type {?} */ var xFactor = (clientX - this.diagramModel.getOffsetX()) / oldZoomFactor / clientWidth; /** @type {?} */ var yFactor = (clientY - this.diagramModel.getOffsetY()) / oldZoomFactor / clientHeight; this.diagramModel.setOffset(this.diagramModel.getOffsetX() - widthDiff * xFactor, this.diagramModel.getOffsetY() - heightDiff * yFactor); } }; NgxDiagramComponent.decorators = [ { type: Component, args: [{ selector: 'ngdx-diagram', template: "<div class=\"ngdx-diagram\" #canvas (mousedown)=\"onMouseDown($event)\" (wheel)=\"onMouseWheel($event)\">\n\t<!-- Nodes Layer -->\n\t<div\n\t\tclass=\"ngdx-nodes-layer\"\n\t\t[ngStyle]=\"{\n\t\t\ttransform:\n\t\t\t\t'translate(' +\n\t\t\t\t(diagramModel.selectOffsetX() | async) +\n\t\t\t\t'px, ' +\n\t\t\t\t(diagramModel.selectOffsetY() | async) +\n\t\t\t\t'px) scale(' +\n\t\t\t\t(diagramModel.selectZoomLevel() | async) / 100.0 +\n\t\t\t\t')'\n\t\t}\"\n\t>\n\t\t<ng-template #nodesLayer></ng-template>\n\t</div>\n\n\t<!-- Links Layer -->\n\t<div\n\t\tclass=\"ngdx-links-layer\"\n\t\t[ngStyle]=\"{\n\t\t\ttransform:\n\t\t\t\t'translate(' +\n\t\t\t\t(diagramModel.selectOffsetX() | async) +\n\t\t\t\t'px, ' +\n\t\t\t\t(diagramModel.selectOffsetY() | async) +\n\t\t\t\t'px) scale(' +\n\t\t\t\t(diagramModel.selectZoomLevel() | async) / 100.0 +\n\t\t\t\t')'\n\t\t}\"\n\t>\n\t\t<ng-template #linksLayer></ng-template>\n\t</div>\n\n\t<!-- Selection Box -->\n\t<div\n\t\t*ngIf=\"shouldDrawSelectionBox() && selectAction() | async as action\"\n\t\tclass=\"selector\"\n\t\t[ngStyle]=\"{\n\t\t\ttop: action.dimensions.top + 'px',\n\t\t\tleft: action.dimensions.left + 'px',\n\t\t\twidth: action.dimensions.width + 'px',\n\t\t\theight: action.dimensions.height + 'px'\n\t\t}\"\n\t></div>\n</div>\n", changeDetection: ChangeDetectionStrategy.OnPush, styles: [".ngdx-diagram{position:relative;flex-grow:1;display:flex;cursor:move;overflow:hidden}.ngdx-diagram .selector{position:absolute;background-color:rgba(0,192,255,.2);border:2px solid #00c0ff}.ngdx-diagram .ngdx-nodes-layer{position:absolute;height:100%;width:100%;transform-origin:0 0;overflow:visible!important;pointer-events:none;z-index:150;top:0;bottom:0;left:0;right:0}.ngdx-diagram .ngdx-links-layer{position:absolute;height:100%;width:100%;transform-origin:0 0;overflow:visible!important;pointer-events:none;z-index:100;top:0;bottom:0;left:0;right:0}"] }] } ]; /** @nocollapse */ NgxDiagramComponent.ctorParameters = function () { return [ { type: Renderer2 }, { type: ChangeDetectorRef } ]; }; NgxDiagramComponent.propDecorators = { diagramModel: [{ type: Input, args: ['model',] }], allowCanvasZoon: [{ type: Input }], allowCanvasTranslation: [{ type: Input }], inverseZoom: [{ type: Input }], allowLooseLinks: [{ type: Input }], actionStartedFiring: [{ type: Output }], actionStillFiring: [{ type: Output }], actionStoppedFiring: [{ type: Output }], nodesLayer: [{ type: ViewChild, args: ['nodesLayer', { read: ViewContainerRef, static: true },] }], linksLayer: [{ type: ViewChild, args: ['linksLayer', { read: ViewContainerRef, static: true },] }], canvas: [{ type: ViewChild, args: ['canvas', { read: ElementRef, static: true },] }] }; return NgxDiagramComponent; }()); export { NgxDiagramComponent }; if (false) { /** @type {?} */ NgxDiagramComponent.prototype.diagramModel; /** @type {?} */ NgxDiagramComponent.prototype.allowCanvasZoon; /** @type {?} */ NgxDiagramComponent.prototype.allowCanvasTranslation; /** @type {?} */ NgxDiagramComponent.prototype.inverseZoom; /** @type {?} */ NgxDiagramComponent.prototype.allowLooseLinks; /** @type {?} */ NgxDiagramComponent.prototype.actionStartedFiring; /** @type {?} */ NgxDiagramComponent.prototype.actionStillFiring; /** @type {?} */ NgxDiagramComponent.prototype.actionStoppedFiring; /** @type {?} */ NgxDiagramComponent.prototype.nodesLayer; /** @type {?} */ NgxDiagramComponent.prototype.linksLayer; /** @type {?} */ NgxDiagramComponent.prototype.canvas; /** * @type {?} * @private */ NgxDiagramComponent.prototype.nodes$; /** * @type {?} * @private */ NgxDiagramComponent.prototype.links$; /** * @type {?} * @private */ NgxDiagramComponent.prototype.action$; /** * @type {?} * @private */ NgxDiagramComponent.prototype.nodesRendered$; /** * @type {?} * @private */ NgxDiagramComponent.prototype.destroyed$; /** * @type {?} * @private */ NgxDiagramComponent.prototype.mouseUpListener; /** * @type {?} * @private */ NgxDiagramComponent.prototype.mouseMoveListener; /** @type {?} */ NgxDiagramComponent.prototype.onMouseUp; /** @type {?} */ NgxDiagramComponent.prototype.onMouseMove; /** * @type {?} * @private */ NgxDiagramComponent.prototype.renderer; /** * @type {?} * @private */ NgxDiagramComponent.prototype.cdRef; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGlhZ3JhbS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9uZ3gtZGlhZ3JhbXMvIiwic291cmNlcyI6WyJsaWIvY29udGFpbmVycy9kaWFncmFtL2RpYWdyYW0uY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLE9BQU8sRUFDTixTQUFTLEVBRVQsS0FBSyxFQUNMLFNBQVMsRUFDVCxNQUFNLEVBQ04sWUFBWSxFQUNaLFNBQVMsRUFDVCxnQkFBZ0IsRUFDaEIsVUFBVSxFQUVWLHVCQUF1QixFQUN2QixpQkFBaUIsRUFFakIsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQzFELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUVwRCxPQUFPLEVBQUUsZUFBZSxFQUFjLGFBQWEsRUFBRSxhQUFhLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDakYsT0FBTyxFQUFFLE1BQU0sRUFBRSxTQUFTLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUNuRCxPQUFPLEVBQWMsZ0JBQWdCLEVBQUUsZUFBZSxFQUFFLGlCQUFpQixFQUFFLE1BQU0sZUFBZSxDQUFDO0FBRWpHLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUNsRSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFFdEQsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ3BELE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxRQUFRLENBQUM7QUFFOUI7SUErQkMsNkJBQW9CLFFBQW1CLEVBQVUsS0FBd0I7UUFBekUsaUJBQTZFO1FBQXpELGFBQVEsR0FBUixRQUFRLENBQVc7UUFBVSxVQUFLLEdBQUwsS0FBSyxDQUFtQjtRQXRCaEUsb0JBQWUsR0FBRyxJQUFJLENBQUM7UUFDdkIsMkJBQXNCLEdBQUcsSUFBSSxDQUFDO1FBQzlC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