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
JavaScript
/**
* @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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