update dis
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,4 +1,3 @@
|
||||
dist/
|
||||
node_modules/
|
||||
out-tsc/
|
||||
debug.log
|
||||
|
||||
202
dist/LICENSE
vendored
Normal file
202
dist/LICENSE
vendored
Normal file
@@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
https://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
33
dist/README.md
vendored
Normal file
33
dist/README.md
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
# Spring Flo
|
||||
|
||||
[](https://travis-ci.org/spring-projects/spring-flo) [](https://david-dm.org/spring-projects/spring-flo)
|
||||
|
||||
Spring Flo is a JavaScript library that offers a basic embeddable HTML5 visual builder for pipelines and simple graphs. This library is used as the basis of the stream builder in Spring Cloud Data Flow.
|
||||
|
||||
[](https://cloud.spring.io/spring-cloud-dataflow/)
|
||||
|
||||
Here is a [youtube video](https://www.youtube.com/watch?v=78CgV46OstI) of Spring Flo in action.
|
||||
|
||||
## Consuming Spring Flo
|
||||
|
||||
Refer to the [wiki](https://github.com/spring-projects/spring-flo/wiki) for more information on how to embed it in an application.
|
||||
|
||||
## Build
|
||||
|
||||
Spring Flo is built using NPM commands. Simplest way to build is via `npm run build` to build the project and run the tests (Prerequisite for th build is `npm install` executed before the build command is). Build results are produced under the __dist__ folder.
|
||||
|
||||
## Getting Help
|
||||
|
||||
If you have any questions, issues, feedback or feature request please [raise an issue](https://github.com/spring-projects/spring-flo/issues).
|
||||
|
||||
## Samples
|
||||
|
||||
A small self contained sample usage of Spring Flo is available in the [demo](https://github.com/spring-projects/spring-flo/tree/master/src/demo) sub folder. Execute `npm start` to run the sample. The [Spring Cloud Data Flow UI](https://github.com/spring-cloud/spring-cloud-dataflow-ui) at github shows a larger scale usage of Spring Flo.
|
||||
|
||||
## Contributing
|
||||
|
||||
Pull requests are welcome, but before accepting them we will need you to sign the [Contributors Agreement](https://support.springsource.com/spring_committer_signup).
|
||||
|
||||
## License
|
||||
|
||||
Spring Flo is Open Source software released under the [Apache 2.0 license](https://www.apache.org/licenses/LICENSE-2.0.html).
|
||||
3351
dist/bundles/spring-flo.umd.js
vendored
Normal file
3351
dist/bundles/spring-flo.umd.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
dist/bundles/spring-flo.umd.min.js
vendored
Normal file
1
dist/bundles/spring-flo.umd.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
249
dist/esm2015/code-editor/code-editor.component.js
vendored
Normal file
249
dist/esm2015/code-editor/code-editor.component.js
vendored
Normal file
File diff suppressed because one or more lines are too long
161
dist/esm2015/directives/resizer.js
vendored
Normal file
161
dist/esm2015/directives/resizer.js
vendored
Normal file
@@ -0,0 +1,161 @@
|
||||
import * as tslib_1 from "tslib";
|
||||
import { Directive, Input, Output, EventEmitter, Inject, ElementRef } from '@angular/core';
|
||||
import { DOCUMENT } from '@angular/platform-browser';
|
||||
import { fromEvent } from 'rxjs';
|
||||
import { sampleTime } from 'rxjs/operators';
|
||||
import { CompositeDisposable, Disposable } from 'ts-disposables';
|
||||
import * as _$ from 'jquery';
|
||||
const $ = _$;
|
||||
let ResizerDirective = class ResizerDirective {
|
||||
constructor(element, document) {
|
||||
this.element = element;
|
||||
this.document = document;
|
||||
this.dragInProgress = false;
|
||||
this.vertical = true;
|
||||
this._subscriptions = new CompositeDisposable();
|
||||
this.sizeChange = new EventEmitter();
|
||||
this.mouseMoveHandler = (e) => {
|
||||
if (this.dragInProgress) {
|
||||
this.mousemove(e);
|
||||
}
|
||||
};
|
||||
}
|
||||
set splitSize(splitSize) {
|
||||
if (this.maxSplitSize && splitSize > this.maxSplitSize) {
|
||||
splitSize = this.maxSplitSize;
|
||||
}
|
||||
if (this.vertical) {
|
||||
// Handle vertical resizer
|
||||
$(this.element.nativeElement).css({
|
||||
left: splitSize + 'px'
|
||||
});
|
||||
$(this.first).css({
|
||||
width: splitSize + 'px'
|
||||
});
|
||||
$(this.second).css({
|
||||
left: (splitSize + this._size) + 'px'
|
||||
});
|
||||
}
|
||||
else {
|
||||
// Handle horizontal resizer
|
||||
$(this.element.nativeElement).css({
|
||||
bottom: splitSize + 'px'
|
||||
});
|
||||
$(this.first).css({
|
||||
bottom: (splitSize + this._size) + 'px'
|
||||
});
|
||||
$(this.second).css({
|
||||
height: splitSize + 'px'
|
||||
});
|
||||
}
|
||||
this._splitSize = splitSize;
|
||||
// Update the local field
|
||||
this.sizeChange.emit(splitSize);
|
||||
}
|
||||
set resizerWidth(width) {
|
||||
this._size = width;
|
||||
this.vertical = true;
|
||||
}
|
||||
set resizerHeight(height) {
|
||||
this._size = height;
|
||||
this.vertical = false;
|
||||
}
|
||||
set resizerLeft(first) {
|
||||
this.first = first;
|
||||
}
|
||||
set resizerTop(first) {
|
||||
this.first = first;
|
||||
}
|
||||
set resizerRight(second) {
|
||||
this.second = second;
|
||||
}
|
||||
set resizerBottom(second) {
|
||||
this.second = second;
|
||||
}
|
||||
startDrag() {
|
||||
this.dragInProgress = true;
|
||||
}
|
||||
mousemove(event) {
|
||||
let size;
|
||||
if (this.vertical) { // Handle vertical resizer. Calculate new size relative to palette container DOM node
|
||||
size = event.pageX - $(this.first).offset().left;
|
||||
}
|
||||
else {
|
||||
// Handle horizontal resizer Calculate new size relative to palette container DOM node
|
||||
size = window.innerHeight - event.pageY - $(this.second).offset().top;
|
||||
}
|
||||
this.splitSize = size;
|
||||
}
|
||||
ngOnInit() {
|
||||
// Need to set left and right elements width and fire events on init when DOM is built
|
||||
this.splitSize = this._splitSize;
|
||||
let subscription1 = fromEvent($(this.document).get(0), 'mousemove')
|
||||
.pipe(sampleTime(300))
|
||||
.subscribe(this.mouseMoveHandler);
|
||||
this._subscriptions.add(Disposable.create(() => subscription1.unsubscribe()));
|
||||
let subscription2 = fromEvent($(this.document).get(0), 'mouseup')
|
||||
.subscribe(e => {
|
||||
if (this.dragInProgress) {
|
||||
this.mousemove(e);
|
||||
this.dragInProgress = false;
|
||||
}
|
||||
});
|
||||
this._subscriptions.add(Disposable.create(() => subscription2.unsubscribe()));
|
||||
}
|
||||
ngOnDestroy() {
|
||||
this._subscriptions.dispose();
|
||||
}
|
||||
};
|
||||
tslib_1.__decorate([
|
||||
Input(),
|
||||
tslib_1.__metadata("design:type", Number)
|
||||
], ResizerDirective.prototype, "maxSplitSize", void 0);
|
||||
tslib_1.__decorate([
|
||||
Output(),
|
||||
tslib_1.__metadata("design:type", Object)
|
||||
], ResizerDirective.prototype, "sizeChange", void 0);
|
||||
tslib_1.__decorate([
|
||||
Input(),
|
||||
tslib_1.__metadata("design:type", Number),
|
||||
tslib_1.__metadata("design:paramtypes", [Number])
|
||||
], ResizerDirective.prototype, "splitSize", null);
|
||||
tslib_1.__decorate([
|
||||
Input(),
|
||||
tslib_1.__metadata("design:type", Number),
|
||||
tslib_1.__metadata("design:paramtypes", [Number])
|
||||
], ResizerDirective.prototype, "resizerWidth", null);
|
||||
tslib_1.__decorate([
|
||||
Input(),
|
||||
tslib_1.__metadata("design:type", Number),
|
||||
tslib_1.__metadata("design:paramtypes", [Number])
|
||||
], ResizerDirective.prototype, "resizerHeight", null);
|
||||
tslib_1.__decorate([
|
||||
Input(),
|
||||
tslib_1.__metadata("design:type", String),
|
||||
tslib_1.__metadata("design:paramtypes", [String])
|
||||
], ResizerDirective.prototype, "resizerLeft", null);
|
||||
tslib_1.__decorate([
|
||||
Input(),
|
||||
tslib_1.__metadata("design:type", String),
|
||||
tslib_1.__metadata("design:paramtypes", [String])
|
||||
], ResizerDirective.prototype, "resizerTop", null);
|
||||
tslib_1.__decorate([
|
||||
Input(),
|
||||
tslib_1.__metadata("design:type", String),
|
||||
tslib_1.__metadata("design:paramtypes", [String])
|
||||
], ResizerDirective.prototype, "resizerRight", null);
|
||||
tslib_1.__decorate([
|
||||
Input(),
|
||||
tslib_1.__metadata("design:type", String),
|
||||
tslib_1.__metadata("design:paramtypes", [String])
|
||||
], ResizerDirective.prototype, "resizerBottom", null);
|
||||
ResizerDirective = tslib_1.__decorate([
|
||||
Directive({
|
||||
selector: '[resizer]',
|
||||
host: { '(mousedown)': 'startDrag()' }
|
||||
}),
|
||||
tslib_1.__param(1, Inject(DOCUMENT)),
|
||||
tslib_1.__metadata("design:paramtypes", [ElementRef, Object])
|
||||
], ResizerDirective);
|
||||
export { ResizerDirective };
|
||||
//# sourceMappingURL=resizer.js.map
|
||||
168
dist/esm2015/dsl-editor/dsl-editor.component.js
vendored
Normal file
168
dist/esm2015/dsl-editor/dsl-editor.component.js
vendored
Normal file
File diff suppressed because one or more lines are too long
108
dist/esm2015/editor/editor-utils.js
vendored
Normal file
108
dist/esm2015/editor/editor-utils.js
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
import { Flo } from '../shared/flo-common';
|
||||
import * as _ from 'lodash';
|
||||
const joint = Flo.joint;
|
||||
import * as _$ from 'jquery';
|
||||
const $ = _$;
|
||||
export class Utils {
|
||||
static fanRoute(graph, cell) {
|
||||
if (cell instanceof joint.dia.Element) {
|
||||
const links = graph.getConnectedLinks(cell);
|
||||
const groupsOfOverlappingLinks = _.groupBy(links, (link) => {
|
||||
// the key of the group is the model id of the link's source or target, but not our cell id.
|
||||
const sourceId = link.get('source').id;
|
||||
const targetId = link.get('target').id;
|
||||
return cell.id !== sourceId ? sourceId : targetId;
|
||||
});
|
||||
_.each(groupsOfOverlappingLinks, (group, key) => {
|
||||
// If the member of the group has both source and target model adjust vertices.
|
||||
let toRoute = {};
|
||||
if (key !== undefined) {
|
||||
group.forEach((link) => {
|
||||
if (link.get('source').id === cell.get('id') && link.get('target').id) {
|
||||
toRoute[link.get('target').id] = link;
|
||||
}
|
||||
else if (link.get('target').id === cell.get('id') && link.get('source').id) {
|
||||
toRoute[link.get('source').id] = link;
|
||||
}
|
||||
});
|
||||
Object.keys(toRoute).forEach(k => {
|
||||
Utils.fanRoute(graph, toRoute[k]);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (cell instanceof joint.dia.Link) {
|
||||
// The cell is a link. Let's find its source and target models.
|
||||
let srcId = cell.get('source').id || cell.previous('source').id;
|
||||
let trgId = cell.get('target').id || cell.previous('target').id;
|
||||
// If one of the ends is not a model, the link has no siblings.
|
||||
if (!srcId || !trgId) {
|
||||
return;
|
||||
}
|
||||
const siblings = graph.getLinks().filter((sibling) => {
|
||||
const _srcId = sibling.get('source').id;
|
||||
const _trgId = sibling.get('target').id;
|
||||
const vertices = sibling.get('vertices');
|
||||
const fanRouted = !vertices || vertices.length === 0 || sibling.get('fanRouted');
|
||||
return ((_srcId === srcId && _trgId === trgId) || (_srcId === trgId && _trgId === srcId)) && fanRouted;
|
||||
});
|
||||
switch (siblings.length) {
|
||||
case 0:
|
||||
// The link was removed and had no siblings.
|
||||
break;
|
||||
case 1:
|
||||
// There is only one link between the source and target. No vertices needed.
|
||||
let vertices = cell.get('vertices');
|
||||
if (vertices && vertices.length && cell.get('fanRouted')) {
|
||||
cell.unset('vertices');
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// There is more than one siblings. We need to create vertices.
|
||||
// First of all we'll find the middle point of the link.
|
||||
let source = graph.getCell(srcId);
|
||||
let target = graph.getCell(trgId);
|
||||
if (!source || !target) {
|
||||
// When clearing the graph it may happen that some nodes are gone and some are left
|
||||
return;
|
||||
}
|
||||
let srcCenter = source.getBBox().center();
|
||||
let trgCenter = target.getBBox().center();
|
||||
let midPoint = joint.g.line(srcCenter, trgCenter).midpoint();
|
||||
// Then find the angle it forms.
|
||||
let theta = srcCenter.theta(trgCenter);
|
||||
// This is the maximum distance between links
|
||||
let gap = 20;
|
||||
siblings.forEach((sibling, index) => {
|
||||
// We want the offset values to be calculated as follows 0, 20, 20, 40, 40, 60, 60 ..
|
||||
let offset = gap * Math.ceil(index / 2);
|
||||
// Now we need the vertices to be placed at points which are 'offset' pixels distant
|
||||
// from the first link and forms a perpendicular angle to it. And as index goes up
|
||||
// alternate left and right.
|
||||
//
|
||||
// ^ odd indexes
|
||||
// |
|
||||
// |----> index 0 line (straight line between a source center and a target center.
|
||||
// |
|
||||
// v even indexes
|
||||
let sign = index % 2 ? 1 : -1;
|
||||
let angle = joint.g.toRad(theta + sign * 90);
|
||||
// We found the vertex.
|
||||
let vertex = joint.g.point.fromPolar(offset, angle, midPoint);
|
||||
sibling.set('fanRouted', true);
|
||||
sibling.set('vertices', [{ x: vertex.x, y: vertex.y }], { 'fanRouted': true });
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
static isCustomPaperEvent(args) {
|
||||
return args.length === 5 &&
|
||||
_.isString(args[0]) &&
|
||||
(args[0].indexOf('link:') === 0 || args[0].indexOf('element:') === 0) &&
|
||||
args[1] instanceof $.Event &&
|
||||
args[2] instanceof joint.dia.CellView &&
|
||||
_.isNumber(args[3]) &&
|
||||
_.isNumber(args[4]);
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=editor-utils.js.map
|
||||
1778
dist/esm2015/editor/editor.component.js
vendored
Normal file
1778
dist/esm2015/editor/editor.component.js
vendored
Normal file
File diff suppressed because one or more lines are too long
12
dist/esm2015/index.js
vendored
Normal file
12
dist/esm2015/index.js
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
export { FloModule } from './module';
|
||||
export { Palette } from './palette/palette.component';
|
||||
export { EditorComponent } from './editor/editor.component';
|
||||
export { DslEditorComponent } from './dsl-editor/dsl-editor.component';
|
||||
export { CodeEditorComponent } from './code-editor/code-editor.component';
|
||||
export { PropertiesGroupComponent } from './properties/properties.group.component';
|
||||
export { DynamicFormPropertyComponent } from './properties/df.property.component';
|
||||
export { ResizerDirective } from './directives/resizer';
|
||||
export * from './shared/flo-common';
|
||||
export * from './shared/flo-properties';
|
||||
export * from './shared/shapes';
|
||||
//# sourceMappingURL=index.js.map
|
||||
39
dist/esm2015/module.js
vendored
Normal file
39
dist/esm2015/module.js
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
import * as tslib_1 from "tslib";
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Palette } from './palette/palette.component';
|
||||
import { EditorComponent } from './editor/editor.component';
|
||||
import { ResizerDirective } from './directives/resizer';
|
||||
import { DslEditorComponent } from './dsl-editor/dsl-editor.component';
|
||||
import { CodeEditorComponent } from './code-editor/code-editor.component';
|
||||
import { PropertiesGroupComponent } from './properties/properties.group.component';
|
||||
import { DynamicFormPropertyComponent } from './properties/df.property.component';
|
||||
let FloModule = class FloModule {
|
||||
};
|
||||
FloModule = tslib_1.__decorate([
|
||||
NgModule({
|
||||
imports: [
|
||||
FormsModule,
|
||||
CommonModule,
|
||||
ReactiveFormsModule
|
||||
],
|
||||
declarations: [
|
||||
Palette,
|
||||
EditorComponent,
|
||||
ResizerDirective,
|
||||
DslEditorComponent,
|
||||
CodeEditorComponent,
|
||||
PropertiesGroupComponent,
|
||||
DynamicFormPropertyComponent
|
||||
],
|
||||
exports: [
|
||||
EditorComponent,
|
||||
DslEditorComponent,
|
||||
DynamicFormPropertyComponent,
|
||||
PropertiesGroupComponent
|
||||
]
|
||||
})
|
||||
], FloModule);
|
||||
export { FloModule };
|
||||
//# sourceMappingURL=module.js.map
|
||||
511
dist/esm2015/palette/palette.component.js
vendored
Normal file
511
dist/esm2015/palette/palette.component.js
vendored
Normal file
@@ -0,0 +1,511 @@
|
||||
import * as tslib_1 from "tslib";
|
||||
import { Component, ElementRef, Input, Output, EventEmitter, Inject, ViewEncapsulation } from '@angular/core';
|
||||
import { Subject } from 'rxjs';
|
||||
import { debounceTime } from 'rxjs/operators';
|
||||
import { dia } from 'jointjs';
|
||||
import { Flo } from '../shared/flo-common';
|
||||
import { Shapes, Constants } from '../shared/shapes';
|
||||
import { DOCUMENT } from '@angular/platform-browser';
|
||||
import * as _$ from 'jquery';
|
||||
const joint = Flo.joint;
|
||||
const $ = _$;
|
||||
const DEBOUNCE_TIME = 300;
|
||||
joint.shapes.flo.PaletteGroupHeader = joint.shapes.basic.Generic.extend({
|
||||
// The path is the open/close arrow, defaults to vertical (open)
|
||||
markup: '<g class="scalable"><rect/></g><text/><g class="rotatable"><path d="m 10 10 l 5 8.7 l 5 -8.7 z"/></g>',
|
||||
defaults: joint.util.deepSupplement({
|
||||
type: 'palette.groupheader',
|
||||
size: { width: 170, height: 30 },
|
||||
position: { x: 0, y: 0 },
|
||||
attrs: {
|
||||
'rect': { fill: '#34302d', 'stroke-width': 1, stroke: '#6db33f', 'follow-scale': true, width: 80, height: 40 },
|
||||
'text': {
|
||||
text: '',
|
||||
fill: '#eeeeee',
|
||||
'ref-x': 0.5,
|
||||
'ref-y': 7,
|
||||
'x-alignment': 'middle',
|
||||
'font-size': 18 /*, 'font-weight': 'bold', 'font-variant': 'small-caps', 'text-transform': 'capitalize'*/
|
||||
},
|
||||
'path': { fill: 'white', 'stroke-width': 2, stroke: 'white' /*,transform:'rotate(90,15,15)'*/ }
|
||||
},
|
||||
// custom properties
|
||||
isOpen: true
|
||||
}, joint.shapes.basic.Generic.prototype.defaults)
|
||||
});
|
||||
let Palette = class Palette {
|
||||
constructor(element, document) {
|
||||
this.element = element;
|
||||
this.document = document;
|
||||
this._metamodelListener = {
|
||||
metadataError: (data) => { },
|
||||
metadataAboutToChange: () => { },
|
||||
metadataChanged: () => this.rebuildPalette()
|
||||
};
|
||||
this.initialized = false;
|
||||
this._filterText = '';
|
||||
this.filterTextModel = new Subject();
|
||||
this.paletteEntryPadding = { width: 12, height: 12 };
|
||||
this.onPaletteEntryDrop = new EventEmitter();
|
||||
this.paletteReady = new EventEmitter();
|
||||
this.paletteFocus = new EventEmitter();
|
||||
this.mouseMoveHanlder = (e) => this.handleDrag(e);
|
||||
this.mouseUpHanlder = (e) => this.handleMouseUp(e);
|
||||
this.paletteGraph = new joint.dia.Graph();
|
||||
this.paletteGraph.set('type', Constants.PALETTE_CONTEXT);
|
||||
this._filterText = '';
|
||||
this.closedGroups = new Set();
|
||||
}
|
||||
set paletteSize(size) {
|
||||
console.debug('Palette Size: ' + size);
|
||||
if (this._paletteSize !== size) {
|
||||
this._paletteSize = size;
|
||||
this.rebuildPalette();
|
||||
}
|
||||
}
|
||||
onFocus() {
|
||||
this.paletteFocus.emit();
|
||||
}
|
||||
ngOnInit() {
|
||||
let element = $('#palette-paper', this.element.nativeElement);
|
||||
// Create the paper for the palette using the specified element view
|
||||
this.palette = new joint.dia.Paper({
|
||||
el: element,
|
||||
gridSize: 1,
|
||||
model: this.paletteGraph,
|
||||
height: $(this.element.nativeElement.parentNode).height(),
|
||||
width: $(this.element.nativeElement.parentNode).width(),
|
||||
elementView: this.getPaletteView(this.renderer && this.renderer.getNodeView ? this.renderer.getNodeView() : joint.dia.ElementView),
|
||||
interactive: false
|
||||
});
|
||||
this.palette.on('cell:pointerup', (cellview, evt) => {
|
||||
if (this.viewBeingDragged) {
|
||||
this.trigger({
|
||||
type: Flo.DnDEventType.DROP,
|
||||
view: this.viewBeingDragged,
|
||||
event: evt
|
||||
});
|
||||
this.viewBeingDragged = undefined;
|
||||
}
|
||||
this.clickedElement = undefined;
|
||||
$('#palette-floater').remove();
|
||||
if (this.floaterpaper) {
|
||||
this.floaterpaper.remove();
|
||||
}
|
||||
});
|
||||
// Toggle the header open/closed on a click
|
||||
this.palette.on('cell:pointerclick', (cellview, event) => {
|
||||
// TODO [design][palette] should the user need to click on the arrow rather than anywhere on the header?
|
||||
// Click position within the element would be: evt.offsetX, evt.offsetY
|
||||
const cell = cellview.model;
|
||||
if (cell.attributes.header) {
|
||||
// Toggle the header open/closed
|
||||
if (cell.get('isOpen')) {
|
||||
this.rotateClosed(cell);
|
||||
}
|
||||
else {
|
||||
this.rotateOpen(cell);
|
||||
}
|
||||
}
|
||||
// TODO [palette] ensure other mouse handling events do nothing for headers
|
||||
// TODO [palette] move 'metadata' field to the right place (not inside attrs I think)
|
||||
});
|
||||
$(this.document).on('mouseup', this.mouseUpHanlder);
|
||||
if (this.metamodel) {
|
||||
this.metamodel.load().then(data => {
|
||||
this.buildPalette(data);
|
||||
// Add listener to metamodel
|
||||
if (this.metamodel && this.metamodel.subscribe) {
|
||||
this.metamodel.subscribe(this._metamodelListener);
|
||||
}
|
||||
// Add debounced listener to filter text changes
|
||||
this.filterTextModel
|
||||
.pipe(debounceTime(DEBOUNCE_TIME))
|
||||
.subscribe((value) => this.rebuildPalette());
|
||||
this.initialized = true;
|
||||
});
|
||||
}
|
||||
else {
|
||||
console.error('No Metamodel service specified for palette!');
|
||||
}
|
||||
this._paletteSize = this._paletteSize || $(this.element.nativeElement.parentNode).width();
|
||||
}
|
||||
ngOnDestroy() {
|
||||
if (this.metamodel && this.metamodel.unsubscribe) {
|
||||
this.metamodel.unsubscribe(this._metamodelListener);
|
||||
}
|
||||
$(this.document).off('mouseup', this.mouseUpHanlder);
|
||||
this.palette.remove();
|
||||
}
|
||||
ngOnChanges(changes) {
|
||||
// if (changes.hasOwnProperty('paletteSize') || changes.hasOwnProperty('filterText')) {
|
||||
// this.metamodel.load().then(metamodel => this.buildPalette(metamodel));
|
||||
// }
|
||||
}
|
||||
createPaletteGroup(title, isOpen) {
|
||||
let newGroupHeader = new joint.shapes.flo.PaletteGroupHeader({ attrs: { text: { text: title } } });
|
||||
newGroupHeader.set('header', title);
|
||||
if (!isOpen) {
|
||||
newGroupHeader.attr({ 'path': { 'transform': 'rotate(-90,15,13)' } });
|
||||
newGroupHeader.set('isOpen', false);
|
||||
}
|
||||
this.paletteGraph.addCell(newGroupHeader);
|
||||
return newGroupHeader;
|
||||
}
|
||||
createPaletteEntry(title, metadata) {
|
||||
return Shapes.Factory.createNode({
|
||||
renderer: this.renderer,
|
||||
paper: this.palette,
|
||||
metadata: metadata
|
||||
});
|
||||
}
|
||||
buildPalette(metamodel) {
|
||||
let startTime = new Date().getTime();
|
||||
this.paletteReady.emit(false);
|
||||
this.paletteGraph.clear();
|
||||
let filterText = this.filterText;
|
||||
if (filterText) {
|
||||
filterText = filterText.toLowerCase();
|
||||
}
|
||||
let paletteNodes = [];
|
||||
let groupAdded = new Set();
|
||||
let parentWidth = this._paletteSize;
|
||||
console.debug(`Parent Width: ${parentWidth}`);
|
||||
// The field closedGroups tells us which should not be shown
|
||||
// Work out the list of active groups/nodes based on the filter text
|
||||
this.metamodel.groups().forEach(group => {
|
||||
if (metamodel && metamodel.has(group)) {
|
||||
Array.from(metamodel.get(group).keys()).sort().forEach(name => {
|
||||
let node = metamodel.get(group).get(name);
|
||||
if (node) {
|
||||
let nodeActive = !(node.metadata && node.metadata.noPaletteEntry);
|
||||
if (nodeActive && filterText) {
|
||||
nodeActive = false;
|
||||
if (name.toLowerCase().indexOf(filterText) !== -1) {
|
||||
nodeActive = true;
|
||||
}
|
||||
else if (group.toLowerCase().indexOf(filterText) !== -1) {
|
||||
nodeActive = true;
|
||||
}
|
||||
// else if (node.description && node.description.toLowerCase().indexOf(filterText) !== -1) {
|
||||
// nodeActive = true;
|
||||
// }
|
||||
// else if (node.properties) {
|
||||
// Object.keys(node.properties).sort().forEach(function(propertyName) {
|
||||
// if (propertyName.toLowerCase().indexOf(filterText) !== -1 ||
|
||||
// (node.properties[propertyName].description &&
|
||||
// node.properties[propertyName].description.toLowerCase().indexOf(filterText) !== -1)) {
|
||||
// nodeActive=true;
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
}
|
||||
if (nodeActive) {
|
||||
if (!groupAdded.has(group)) {
|
||||
let header = this.createPaletteGroup(group, !this.closedGroups.has(group));
|
||||
header.set('size', { width: parentWidth, height: 30 });
|
||||
paletteNodes.push(header);
|
||||
groupAdded.add(group);
|
||||
}
|
||||
if (!this.closedGroups.has(group)) {
|
||||
paletteNodes.push(this.createPaletteEntry(name, node));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
let cellWidth = 0, cellHeight = 0;
|
||||
// Determine the size of the palette entry cell (width and height)
|
||||
paletteNodes.forEach(pnode => {
|
||||
if (pnode.attr('metadata/name')) {
|
||||
let dimension = {
|
||||
width: pnode.get('size').width,
|
||||
height: pnode.get('size').height
|
||||
};
|
||||
if (cellWidth < dimension.width) {
|
||||
cellWidth = dimension.width;
|
||||
}
|
||||
if (cellHeight < dimension.height) {
|
||||
cellHeight = dimension.height;
|
||||
}
|
||||
}
|
||||
});
|
||||
// Adjust the palette entry cell size with paddings.
|
||||
cellWidth += 2 * this.paletteEntryPadding.width;
|
||||
cellHeight += 2 * this.paletteEntryPadding.height;
|
||||
// Align palette entries row to be at the center
|
||||
let startX = parentWidth >= cellWidth ? (parentWidth - Math.floor(parentWidth / cellWidth) * cellWidth) / 2 : 0;
|
||||
let xpos = startX;
|
||||
let ypos = 0;
|
||||
let prevNode;
|
||||
// Layout palette entry nodes
|
||||
paletteNodes.forEach(pnode => {
|
||||
let dimension = {
|
||||
width: pnode.get('size').width,
|
||||
height: pnode.get('size').height
|
||||
};
|
||||
if (pnode.get('header')) { //attributes.attrs.header) {
|
||||
// Palette entry header
|
||||
xpos = startX;
|
||||
pnode.set('position', { x: 0, y: ypos });
|
||||
ypos += dimension.height + 5;
|
||||
}
|
||||
else {
|
||||
// Palette entry element
|
||||
if (xpos + cellWidth > parentWidth) {
|
||||
// Not enough real estate to place entry in a row - reset x position and leave the y pos which is next line
|
||||
xpos = startX;
|
||||
pnode.set('position', { x: xpos + (cellWidth - dimension.width) / 2, y: ypos + (cellHeight - dimension.height) / 2 });
|
||||
}
|
||||
else {
|
||||
// Enough real estate to place entry in a row - adjust y position
|
||||
if (prevNode && prevNode.attr('metadata/name')) {
|
||||
ypos -= cellHeight;
|
||||
}
|
||||
pnode.set('position', { x: xpos + (cellWidth - dimension.width) / 2, y: ypos + (cellHeight - dimension.height) / 2 });
|
||||
}
|
||||
// increment x position and y position (can be reorganized)
|
||||
xpos += cellWidth;
|
||||
ypos += cellHeight;
|
||||
}
|
||||
prevNode = pnode;
|
||||
});
|
||||
this.palette.setDimensions(parentWidth, ypos);
|
||||
this.paletteReady.emit(true);
|
||||
console.debug('buildPalette took ' + (new Date().getTime() - startTime) + 'ms');
|
||||
}
|
||||
rebuildPalette() {
|
||||
if (this.initialized && this.metamodel) {
|
||||
this.metamodel.load().then(metamodel => this.buildPalette(metamodel));
|
||||
}
|
||||
}
|
||||
set filterText(text) {
|
||||
if (this._filterText !== text) {
|
||||
this._filterText = text;
|
||||
this.filterTextModel.next(text);
|
||||
}
|
||||
}
|
||||
get filterText() {
|
||||
return this._filterText;
|
||||
}
|
||||
getPaletteView(view) {
|
||||
let self = this;
|
||||
return view.extend({
|
||||
pointerdown: function ( /*evt, x, y*/) {
|
||||
// Remove the tooltip
|
||||
// $('.node-tooltip').remove();
|
||||
// TODO move metadata to the right place (not inside attrs I think)
|
||||
self.clickedElement = this.model;
|
||||
if (self.clickedElement && self.clickedElement.attr('metadata')) {
|
||||
$(self.document).on('mousemove', self.mouseMoveHanlder);
|
||||
}
|
||||
},
|
||||
pointermove: function ( /*evt, x, y*/) {
|
||||
// Nothing to prevent move within the palette canvas
|
||||
},
|
||||
});
|
||||
}
|
||||
handleMouseUp(event) {
|
||||
$(this.document).off('mousemove', this.mouseMoveHanlder);
|
||||
}
|
||||
trigger(event) {
|
||||
this.onPaletteEntryDrop.emit(event);
|
||||
}
|
||||
handleDrag(event) {
|
||||
// TODO offsetX/Y not on firefox
|
||||
// console.debug("tracking move: x="+event.pageX+",y="+event.pageY);
|
||||
// console.debug('Element = ' + (this.clickedElement ? this.clickedElement.attr('metadata/name'): 'null'));
|
||||
if (this.clickedElement && this.clickedElement.attr('metadata')) {
|
||||
if (!this.viewBeingDragged) {
|
||||
let dataOfClickedElement = this.clickedElement.attr('metadata');
|
||||
// custom div if not already built.
|
||||
$('<div>', {
|
||||
id: 'palette-floater'
|
||||
}).appendTo($('body'));
|
||||
let floatergraph = new joint.dia.Graph();
|
||||
floatergraph.set('type', Constants.FEEDBACK_CONTEXT);
|
||||
const parent = $('#palette-floater');
|
||||
this.floaterpaper = new joint.dia.Paper({
|
||||
el: $('#palette-floater'),
|
||||
elementView: this.renderer && this.renderer.getNodeView ? this.renderer.getNodeView() : joint.dia.ElementView,
|
||||
gridSize: 10,
|
||||
model: floatergraph,
|
||||
height: parent.height(),
|
||||
width: parent.width(),
|
||||
validateMagnet: () => false,
|
||||
validateConnection: () => false
|
||||
});
|
||||
// TODO float thing needs to be bigger otherwise icon label is missing
|
||||
// Initiative drag and drop - create draggable element
|
||||
let floaternode = Shapes.Factory.createNode({
|
||||
'renderer': this.renderer,
|
||||
'paper': this.floaterpaper,
|
||||
'graph': floatergraph,
|
||||
'metadata': dataOfClickedElement
|
||||
});
|
||||
// Only node view expected
|
||||
let box = this.floaterpaper.findViewByModel(floaternode).getBBox();
|
||||
let size = floaternode.get('size');
|
||||
// Account for node real size including ports
|
||||
floaternode.translate(box.width - size.width, box.height - size.height);
|
||||
this.viewBeingDragged = this.floaterpaper.findViewByModel(floaternode);
|
||||
$('#palette-floater').offset({ left: event.pageX + 5, top: event.pageY + 5 });
|
||||
}
|
||||
else {
|
||||
$('#palette-floater').offset({ left: event.pageX + 5, top: event.pageY + 5 });
|
||||
this.trigger({
|
||||
type: Flo.DnDEventType.DRAG,
|
||||
view: this.viewBeingDragged,
|
||||
event: event
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Modify the rotation of the arrow in the header from horizontal(closed) to vertical(open)
|
||||
*/
|
||||
rotateOpen(element) {
|
||||
setTimeout(() => this.doRotateOpen(element, 90));
|
||||
}
|
||||
doRotateOpen(element, angle) {
|
||||
angle -= 10;
|
||||
element.attr({ 'path': { 'transform': 'rotate(-' + angle + ',15,13)' } });
|
||||
if (angle <= 0) {
|
||||
element.set('isOpen', true);
|
||||
this.closedGroups.delete(element.get('header'));
|
||||
this.rebuildPalette();
|
||||
}
|
||||
else {
|
||||
setTimeout(() => this.doRotateOpen(element, angle), 10);
|
||||
}
|
||||
}
|
||||
doRotateClose(element, angle) {
|
||||
angle += 10;
|
||||
element.attr({ 'path': { 'transform': 'rotate(-' + angle + ',15,13)' } });
|
||||
if (angle >= 90) {
|
||||
element.set('isOpen', false);
|
||||
this.closedGroups.add(element.get('header'));
|
||||
this.rebuildPalette();
|
||||
}
|
||||
else {
|
||||
setTimeout(() => this.doRotateClose(element, angle), 10);
|
||||
}
|
||||
}
|
||||
// TODO better name for this function as this does the animation *and* updates the palette
|
||||
/*
|
||||
* Modify the rotation of the arrow in the header from vertical(open) to horizontal(closed)
|
||||
*/
|
||||
rotateClosed(element) {
|
||||
setTimeout(() => this.doRotateClose(element, 0));
|
||||
}
|
||||
};
|
||||
tslib_1.__decorate([
|
||||
Input(),
|
||||
tslib_1.__metadata("design:type", Object)
|
||||
], Palette.prototype, "metamodel", void 0);
|
||||
tslib_1.__decorate([
|
||||
Input(),
|
||||
tslib_1.__metadata("design:type", Object)
|
||||
], Palette.prototype, "renderer", void 0);
|
||||
tslib_1.__decorate([
|
||||
Input(),
|
||||
tslib_1.__metadata("design:type", Object)
|
||||
], Palette.prototype, "paletteEntryPadding", void 0);
|
||||
tslib_1.__decorate([
|
||||
Output(),
|
||||
tslib_1.__metadata("design:type", Object)
|
||||
], Palette.prototype, "onPaletteEntryDrop", void 0);
|
||||
tslib_1.__decorate([
|
||||
Output(),
|
||||
tslib_1.__metadata("design:type", Object)
|
||||
], Palette.prototype, "paletteReady", void 0);
|
||||
tslib_1.__decorate([
|
||||
Output(),
|
||||
tslib_1.__metadata("design:type", Object)
|
||||
], Palette.prototype, "paletteFocus", void 0);
|
||||
tslib_1.__decorate([
|
||||
Input(),
|
||||
tslib_1.__metadata("design:type", Number),
|
||||
tslib_1.__metadata("design:paramtypes", [Number])
|
||||
], Palette.prototype, "paletteSize", null);
|
||||
Palette = tslib_1.__decorate([
|
||||
Component({
|
||||
selector: 'flo-palette',
|
||||
template: `
|
||||
<div id="palette-filter" class="palette-filter">
|
||||
<input type="text" id="palette-filter-textfield" class="palette-filter-textfield" [(ngModel)]="filterText" (focus)="onFocus()"/>
|
||||
</div>
|
||||
<div id="palette-paper-container" style="height:calc(100% - 46px); width:100%;">
|
||||
<div id="palette-paper" class="palette-paper" style="overflow:hidden;"></div>
|
||||
</div>
|
||||
`,
|
||||
styles: [`
|
||||
/* Joint JS paper for drawing palette -> canvas DnD visual feedback START */
|
||||
|
||||
#palette-floater {
|
||||
/* TODO size relative to paper that goes on it? */
|
||||
opacity: 0.75;
|
||||
width:170px;
|
||||
height:60px;
|
||||
background-color: transparent;
|
||||
/*
|
||||
background-color: #6db33f;
|
||||
*/
|
||||
float:left;
|
||||
position: absolute;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-o-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
#palette-floater.joint-paper > svg {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
#palette-paper-container {
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
background-color: white;
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Joint JS paper for drawing palette -> canvas DnD visual feedback END */
|
||||
|
||||
/* Palette START */
|
||||
|
||||
.palette-filter {
|
||||
border: 3px solid #6db33f;
|
||||
}
|
||||
|
||||
.palette-filter-textfield {
|
||||
width: 100%;
|
||||
font-size:24px;
|
||||
/* border: 3px solid #6db33f;
|
||||
*/ font-family: "Varela Round",sans-serif;
|
||||
/* padding: 2px; */
|
||||
}
|
||||
|
||||
.palette-paper {
|
||||
background-color: #eeeeee;
|
||||
/*
|
||||
border-right: 7px solid;
|
||||
*/
|
||||
border-color: #6db33f;
|
||||
/* width: 170px;
|
||||
height:100%;
|
||||
float: left;
|
||||
*/
|
||||
}
|
||||
|
||||
/* Palette END */
|
||||
`],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
}),
|
||||
tslib_1.__param(1, Inject(DOCUMENT)),
|
||||
tslib_1.__metadata("design:paramtypes", [ElementRef, Object])
|
||||
], Palette);
|
||||
export { Palette };
|
||||
//# sourceMappingURL=palette.component.js.map
|
||||
82
dist/esm2015/properties/df.property.component.js
vendored
Normal file
82
dist/esm2015/properties/df.property.component.js
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
import * as tslib_1 from "tslib";
|
||||
import { Component, Input, ViewEncapsulation } from '@angular/core';
|
||||
import { FormGroup } from '@angular/forms';
|
||||
import { Properties } from '../shared/flo-properties';
|
||||
let DynamicFormPropertyComponent = class DynamicFormPropertyComponent {
|
||||
constructor() { }
|
||||
get types() {
|
||||
return Properties.InputType;
|
||||
}
|
||||
get control() {
|
||||
return this.form.controls[this.model.id];
|
||||
}
|
||||
get errorData() {
|
||||
return (this.model.validation && this.model.validation.errorData ? this.model.validation.errorData : [])
|
||||
.filter(e => this.control.errors && this.control.errors[e.id]);
|
||||
}
|
||||
};
|
||||
tslib_1.__decorate([
|
||||
Input(),
|
||||
tslib_1.__metadata("design:type", Object)
|
||||
], DynamicFormPropertyComponent.prototype, "model", void 0);
|
||||
tslib_1.__decorate([
|
||||
Input(),
|
||||
tslib_1.__metadata("design:type", FormGroup)
|
||||
], DynamicFormPropertyComponent.prototype, "form", void 0);
|
||||
DynamicFormPropertyComponent = tslib_1.__decorate([
|
||||
Component({
|
||||
selector: 'df-property',
|
||||
template: `
|
||||
<tr [formGroup]="form" class="df-property-row" [ngClass]="{'invalid-property-value': control.invalid}">
|
||||
|
||||
<td class="df-property-label-cell">
|
||||
<label [attr.for]="model.id" class="df-form-label">{{model.name}}</label>
|
||||
</td>
|
||||
|
||||
<td class="df-property-control-cell">
|
||||
<div [ngSwitch]="model.type" class="df-property-container">
|
||||
|
||||
<label *ngSwitchCase="types.CHECKBOX" class="df-property-control">
|
||||
<input type="checkbox" [id]="model.id" [(ngModel)]="model.value" [formControlName]="model.id">
|
||||
{{model.value ? 'True' : 'False' }}
|
||||
</label>
|
||||
|
||||
<input *ngSwitchCase="types.NUMBER" class="df-property-control" type="number" [id]="model.id"
|
||||
[formControlName]="model.id" [placeholder]="model.defaultValue || ''" [(ngModel)]="model.value">
|
||||
|
||||
<input *ngSwitchCase="types.PASSWORD" class="df-property-control" type="password" [id]="model.id"
|
||||
[formControlName]="model.id" [placeholder]="model.defaultValue || ''" [(ngModel)]="model.value">
|
||||
|
||||
<input *ngSwitchCase="types.EMAIL" class="df-property-control" type="password" [id]="model.id"
|
||||
[formControlName]="model.id" [placeholder]="model.defaultValue || ''" [(ngModel)]="model.value">
|
||||
|
||||
<input *ngSwitchCase="types.URL" class="df-property-control" type="url" [id]="model.id"
|
||||
[formControlName]="model.id" [placeholder]="model.defaultValue || ''" [(ngModel)]="model.value">
|
||||
|
||||
<select *ngSwitchCase="types.SELECT" class="df-property-control" [id]="model.id"
|
||||
[formControlName]="model.id" [(ngModel)]="model.value">
|
||||
<option *ngFor="let o of model['options']" [ngValue]="o.value">{{o.name}}</option>
|
||||
</select>
|
||||
|
||||
<code-editor *ngSwitchCase="types.CODE" class="df-property-control" [id]="model.id"
|
||||
[formControlName]="model.id" [language]="model['language']" [(ngModel)]="model.value" line-numbers="true"
|
||||
scrollbar-style="simple" [placeholder]="model.defaultValue || 'Enter code snippet...'" overview-ruler="true">
|
||||
</code-editor>
|
||||
|
||||
<input *ngSwitchDefault class="df-property-control" type="text" [id]="model.id" [formControlName]="model.id"
|
||||
[placeholder]="model.defaultValue || ''" [(ngModel)]="model.value">
|
||||
</div>
|
||||
<div class="help-block">
|
||||
<div>{{model.description}}</div>
|
||||
<div *ngFor="let e of errorData" class="validation-error-block">{{e.message}}</div>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
`,
|
||||
encapsulation: ViewEncapsulation.None
|
||||
}),
|
||||
tslib_1.__metadata("design:paramtypes", [])
|
||||
], DynamicFormPropertyComponent);
|
||||
export { DynamicFormPropertyComponent };
|
||||
//# sourceMappingURL=df.property.component.js.map
|
||||
50
dist/esm2015/properties/properties.group.component.js
vendored
Normal file
50
dist/esm2015/properties/properties.group.component.js
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
import * as tslib_1 from "tslib";
|
||||
import { Component, Input, ViewEncapsulation } from '@angular/core';
|
||||
import { FormGroup, FormControl } from '@angular/forms';
|
||||
import { Properties } from '../shared/flo-properties';
|
||||
let PropertiesGroupComponent = class PropertiesGroupComponent {
|
||||
ngOnInit() {
|
||||
if (this.propertiesGroupModel.isLoading) {
|
||||
let subscription = this.propertiesGroupModel.loadedSubject.subscribe(loaded => {
|
||||
if (loaded) {
|
||||
subscription.unsubscribe();
|
||||
this.createGroupControls();
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.createGroupControls();
|
||||
}
|
||||
}
|
||||
createGroupControls() {
|
||||
this.propertiesGroupModel.getControlsModels().forEach(c => {
|
||||
if (c.validation) {
|
||||
this.form.addControl(c.id, new FormControl(c.value || '', c.validation.validator, c.validation.asyncValidator));
|
||||
}
|
||||
else {
|
||||
this.form.addControl(c.id, new FormControl(c.value || ''));
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
tslib_1.__decorate([
|
||||
Input(),
|
||||
tslib_1.__metadata("design:type", Properties.PropertiesGroupModel)
|
||||
], PropertiesGroupComponent.prototype, "propertiesGroupModel", void 0);
|
||||
tslib_1.__decorate([
|
||||
Input(),
|
||||
tslib_1.__metadata("design:type", FormGroup)
|
||||
], PropertiesGroupComponent.prototype, "form", void 0);
|
||||
PropertiesGroupComponent = tslib_1.__decorate([
|
||||
Component({
|
||||
selector: 'properties-group',
|
||||
template: `
|
||||
<div *ngIf="propertiesGroupModel && !propertiesGroupModel.isLoading" class="properties-group-container" [formGroup]="form">
|
||||
<df-property *ngFor="let model of propertiesGroupModel.getControlsModels()" [model]="model" [form]="form" class="property-row"></df-property>
|
||||
</div>
|
||||
`,
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
], PropertiesGroupComponent);
|
||||
export { PropertiesGroupComponent };
|
||||
//# sourceMappingURL=properties.group.component.js.map
|
||||
57
dist/esm2015/shared/flo-common.js
vendored
Normal file
57
dist/esm2015/shared/flo-common.js
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
import * as _joint from 'jointjs';
|
||||
import * as _$ from 'jquery';
|
||||
const $ = _$;
|
||||
export var Flo;
|
||||
(function (Flo) {
|
||||
Flo.joint = _joint;
|
||||
let DnDEventType;
|
||||
(function (DnDEventType) {
|
||||
DnDEventType[DnDEventType["DRAG"] = 0] = "DRAG";
|
||||
DnDEventType[DnDEventType["DROP"] = 1] = "DROP";
|
||||
})(DnDEventType = Flo.DnDEventType || (Flo.DnDEventType = {}));
|
||||
let Severity;
|
||||
(function (Severity) {
|
||||
Severity[Severity["Error"] = 0] = "Error";
|
||||
Severity[Severity["Warning"] = 1] = "Warning";
|
||||
})(Severity = Flo.Severity || (Flo.Severity = {}));
|
||||
function findMagnetByClass(view, className) {
|
||||
if (className && className.startsWith('.')) {
|
||||
className = className.substr(1);
|
||||
}
|
||||
const element = view.$('[magnet]').toArray().find((magnet) => magnet.getAttribute('class').split(/\s+/).indexOf(className) >= 0);
|
||||
if (element) {
|
||||
return view.findMagnet($(element));
|
||||
}
|
||||
}
|
||||
Flo.findMagnetByClass = findMagnetByClass;
|
||||
function findMagnetByPort(view, port) {
|
||||
const element = view.$('[magnet]').toArray().find((magnet) => magnet.getAttribute('port') === port);
|
||||
if (element) {
|
||||
return view.findMagnet($(element));
|
||||
}
|
||||
}
|
||||
Flo.findMagnetByPort = findMagnetByPort;
|
||||
/**
|
||||
* Return the metadata for a particular palette entry in a particular group.
|
||||
* @param name - name of the palette entry
|
||||
* @param group - group in which the palette entry should exist (e.g. sinks)
|
||||
* @return
|
||||
*/
|
||||
function getMetadata(metamodel, name, group) {
|
||||
const groupObj = metamodel && group ? metamodel.get(group) : undefined;
|
||||
if (name && groupObj && groupObj.get(name)) {
|
||||
return metamodel.get(group).get(name);
|
||||
}
|
||||
else {
|
||||
return {
|
||||
name: name,
|
||||
group: group,
|
||||
unresolved: true,
|
||||
get: (property) => new Promise(resolve => resolve()),
|
||||
properties: () => Promise.resolve(new Map())
|
||||
};
|
||||
}
|
||||
}
|
||||
Flo.getMetadata = getMetadata;
|
||||
})(Flo || (Flo = {}));
|
||||
//# sourceMappingURL=flo-common.js.map
|
||||
273
dist/esm2015/shared/flo-properties.js
vendored
Normal file
273
dist/esm2015/shared/flo-properties.js
vendored
Normal file
@@ -0,0 +1,273 @@
|
||||
import { Subject, Observable } from 'rxjs';
|
||||
import { debounceTime, mergeMap } from 'rxjs/operators';
|
||||
export var Properties;
|
||||
(function (Properties) {
|
||||
let InputType;
|
||||
(function (InputType) {
|
||||
InputType[InputType["TEXT"] = 0] = "TEXT";
|
||||
InputType[InputType["NUMBER"] = 1] = "NUMBER";
|
||||
InputType[InputType["SELECT"] = 2] = "SELECT";
|
||||
InputType[InputType["CHECKBOX"] = 3] = "CHECKBOX";
|
||||
InputType[InputType["PASSWORD"] = 4] = "PASSWORD";
|
||||
InputType[InputType["EMAIL"] = 5] = "EMAIL";
|
||||
InputType[InputType["URL"] = 6] = "URL";
|
||||
InputType[InputType["CODE"] = 7] = "CODE";
|
||||
})(InputType = Properties.InputType || (Properties.InputType = {}));
|
||||
class GenericControlModel {
|
||||
constructor(_property, type, validation) {
|
||||
this._property = _property;
|
||||
this.type = type;
|
||||
this.validation = validation;
|
||||
}
|
||||
get id() {
|
||||
return this.property.id;
|
||||
}
|
||||
get name() {
|
||||
return this.property.name;
|
||||
}
|
||||
get description() {
|
||||
return this.property.description;
|
||||
}
|
||||
get defaultValue() {
|
||||
return this.property.defaultValue;
|
||||
}
|
||||
get value() {
|
||||
return this.getValue();
|
||||
}
|
||||
set value(value) {
|
||||
this.setValue(value);
|
||||
}
|
||||
get property() {
|
||||
return this._property;
|
||||
}
|
||||
setValue(value) {
|
||||
this.property.value = value;
|
||||
}
|
||||
getValue() {
|
||||
return this.property.value;
|
||||
}
|
||||
}
|
||||
Properties.GenericControlModel = GenericControlModel;
|
||||
class CheckBoxControlModel extends GenericControlModel {
|
||||
constructor(_property, validation) {
|
||||
super(_property, InputType.CHECKBOX, validation);
|
||||
}
|
||||
getValue() {
|
||||
const res = super.getValue();
|
||||
const type = typeof res;
|
||||
switch (type) {
|
||||
case 'boolean':
|
||||
return res;
|
||||
case 'string':
|
||||
switch (res.trim().toLowerCase()) {
|
||||
case 'true':
|
||||
case '1':
|
||||
return true;
|
||||
case 'false':
|
||||
case '0':
|
||||
return false;
|
||||
default:
|
||||
return this.property.defaultValue;
|
||||
}
|
||||
case 'number':
|
||||
const num = res;
|
||||
if (num === 0) {
|
||||
return false;
|
||||
}
|
||||
else if (num === 1) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return this.property.defaultValue;
|
||||
}
|
||||
}
|
||||
return this.property.defaultValue;
|
||||
}
|
||||
}
|
||||
Properties.CheckBoxControlModel = CheckBoxControlModel;
|
||||
class AbstractCodeControlModel extends GenericControlModel {
|
||||
constructor(_property, encode, decode, validation) {
|
||||
super(_property, InputType.CODE, validation);
|
||||
this.encode = encode;
|
||||
this.decode = decode;
|
||||
}
|
||||
set value(value) {
|
||||
if (value && this.encode) {
|
||||
super.setValue(this.encode(value));
|
||||
}
|
||||
else {
|
||||
super.setValue(value);
|
||||
}
|
||||
}
|
||||
get value() {
|
||||
let dsl = super.getValue();
|
||||
if (dsl && this.decode) {
|
||||
return this.decode(dsl);
|
||||
}
|
||||
else {
|
||||
return dsl;
|
||||
}
|
||||
}
|
||||
}
|
||||
Properties.AbstractCodeControlModel = AbstractCodeControlModel;
|
||||
class GenericCodeControlModel extends AbstractCodeControlModel {
|
||||
constructor(_property, language, encode, decode, validation) {
|
||||
super(_property, encode, decode, validation);
|
||||
this.language = language;
|
||||
}
|
||||
}
|
||||
Properties.GenericCodeControlModel = GenericCodeControlModel;
|
||||
class CodeControlModelWithDynamicLanguageProperty extends AbstractCodeControlModel {
|
||||
constructor(_property, _languagePropertyName, _groupModel, encode, decode, validation) {
|
||||
super(_property, encode, decode, validation);
|
||||
this._languagePropertyName = _languagePropertyName;
|
||||
this._groupModel = _groupModel;
|
||||
}
|
||||
get language() {
|
||||
const value = this.languageControlModel.value;
|
||||
return value ? value : this.languageControlModel.defaultValue;
|
||||
}
|
||||
get languageControlModel() {
|
||||
if (!this._langControlModel) {
|
||||
// Cast to Properties.ControlModel<any> from Properties.ControlModel<any> | undefined
|
||||
// Should not be undefined!
|
||||
this._langControlModel = this._groupModel.getControlsModels().find(c => c.id === this._languagePropertyName);
|
||||
}
|
||||
return this._langControlModel;
|
||||
}
|
||||
}
|
||||
Properties.CodeControlModelWithDynamicLanguageProperty = CodeControlModelWithDynamicLanguageProperty;
|
||||
class GenericListControlModel extends GenericControlModel {
|
||||
constructor(property, validation) {
|
||||
super(property, InputType.TEXT, validation);
|
||||
}
|
||||
get value() {
|
||||
return this.property.value ? this.property.value.join(', ') : '';
|
||||
}
|
||||
set value(value) {
|
||||
this.property.value = value && value.trim() ? value.split(/\s*,\s*/) : undefined;
|
||||
}
|
||||
}
|
||||
Properties.GenericListControlModel = GenericListControlModel;
|
||||
class SelectControlModel extends GenericControlModel {
|
||||
constructor(_property, type, options) {
|
||||
super(_property, type);
|
||||
this.options = options;
|
||||
if (_property.defaultValue === undefined) {
|
||||
options.unshift({
|
||||
name: 'SELECT',
|
||||
value: _property.defaultValue
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
Properties.SelectControlModel = SelectControlModel;
|
||||
class DefaultCellPropertiesSource {
|
||||
constructor(cell) {
|
||||
this.cell = cell;
|
||||
}
|
||||
getProperties() {
|
||||
let metadata = this.cell.attr('metadata');
|
||||
return Promise.resolve(metadata.properties().then(propsMetadata => Array.from(propsMetadata.values()).map(m => this.createProperty(m))));
|
||||
}
|
||||
createProperty(metadata) {
|
||||
return {
|
||||
id: metadata.id,
|
||||
name: metadata.name,
|
||||
type: metadata.type,
|
||||
defaultValue: metadata.defaultValue,
|
||||
attr: `props/${metadata.name}`,
|
||||
value: this.cell.attr(`props/${metadata.name}`),
|
||||
description: metadata.description,
|
||||
valueOptions: metadata.options
|
||||
};
|
||||
}
|
||||
applyChanges(properties) {
|
||||
this.cell.trigger('batch:start', { batchName: 'update properties' });
|
||||
properties.forEach(property => {
|
||||
if ((typeof property.value === 'boolean' && !property.defaultValue && !property.value) ||
|
||||
(property.value === property.defaultValue || property.value === '' || property.value === undefined || property.value === null)) {
|
||||
let currentValue = this.cell.attr(property.attr);
|
||||
if (currentValue !== undefined && currentValue !== null) {
|
||||
// Remove attr doesn't fire appropriate event. Set default value first as a workaround to schedule DSL resync
|
||||
this.cell.attr(property.attr, property.defaultValue === undefined ? null : property.defaultValue);
|
||||
this.cell.removeAttr(property.attr);
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.cell.attr(property.attr, property.value);
|
||||
}
|
||||
});
|
||||
this.cell.trigger('batch:stop', { batchName: 'update properties' });
|
||||
}
|
||||
}
|
||||
Properties.DefaultCellPropertiesSource = DefaultCellPropertiesSource;
|
||||
class PropertiesGroupModel {
|
||||
constructor(propertiesSource) {
|
||||
this.loading = true;
|
||||
this.propertiesSource = propertiesSource;
|
||||
}
|
||||
load() {
|
||||
this.loading = true;
|
||||
this._loadedSubject = new Subject();
|
||||
this.propertiesSource.getProperties().then(properties => {
|
||||
this.controlModels = properties.map(p => this.createControlModel(p));
|
||||
this.loading = false;
|
||||
this._loadedSubject.next(true);
|
||||
this._loadedSubject.complete();
|
||||
});
|
||||
}
|
||||
get isLoading() {
|
||||
return this.loading;
|
||||
}
|
||||
get loadedSubject() {
|
||||
return this._loadedSubject;
|
||||
}
|
||||
getControlsModels() {
|
||||
return this.controlModels;
|
||||
}
|
||||
createControlModel(property) {
|
||||
return new GenericControlModel(property, InputType.TEXT);
|
||||
}
|
||||
applyChanges() {
|
||||
if (this.loading) {
|
||||
return;
|
||||
}
|
||||
let properties = this.controlModels.map(cm => cm.property);
|
||||
this.propertiesSource.applyChanges(properties);
|
||||
}
|
||||
}
|
||||
Properties.PropertiesGroupModel = PropertiesGroupModel;
|
||||
let Validators;
|
||||
(function (Validators) {
|
||||
function uniqueResource(service, debounce) {
|
||||
return (control) => {
|
||||
return new Observable(obs => {
|
||||
if (control.valueChanges && control.value) {
|
||||
control.valueChanges
|
||||
.pipe(debounceTime(debounce), mergeMap(value => service(value)))
|
||||
.subscribe(() => {
|
||||
obs.next({ uniqueResource: true });
|
||||
obs.complete();
|
||||
}, () => {
|
||||
obs.next(undefined);
|
||||
obs.complete();
|
||||
});
|
||||
}
|
||||
else {
|
||||
obs.next(undefined);
|
||||
obs.complete();
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
Validators.uniqueResource = uniqueResource;
|
||||
function noneOf(excluded) {
|
||||
return (control) => {
|
||||
return excluded.find(e => e === control.value) ? { 'noneOf': { value: control.value } } : {};
|
||||
};
|
||||
}
|
||||
Validators.noneOf = noneOf;
|
||||
})(Validators = Properties.Validators || (Properties.Validators = {}));
|
||||
})(Properties || (Properties = {}));
|
||||
//# sourceMappingURL=flo-properties.js.map
|
||||
494
dist/esm2015/shared/shapes.js
vendored
Normal file
494
dist/esm2015/shared/shapes.js
vendored
Normal file
@@ -0,0 +1,494 @@
|
||||
import { Flo } from './flo-common';
|
||||
import * as _ from 'lodash';
|
||||
import * as _$ from 'jquery';
|
||||
const joint = Flo.joint;
|
||||
const $ = _$;
|
||||
const isChrome = /Chrome/.test(navigator.userAgent) && /Google Inc/.test(navigator.vendor);
|
||||
const isFF = navigator.userAgent.indexOf('Firefox') > 0;
|
||||
const IMAGE_W = 120;
|
||||
const IMAGE_H = 35;
|
||||
const ERROR_MARKER_SIZE = { width: 16, height: 16 };
|
||||
const HANDLE_SIZE = { width: 10, height: 10 };
|
||||
joint.shapes.flo = {};
|
||||
joint.shapes.flo.NODE_TYPE = 'sinspctr.IntNode';
|
||||
joint.shapes.flo.LINK_TYPE = 'sinspctr.Link';
|
||||
joint.shapes.flo.DECORATION_TYPE = 'decoration';
|
||||
joint.shapes.flo.HANDLE_TYPE = 'handle';
|
||||
const HANDLE_ICON_MAP = new Map();
|
||||
const REMOVE = 'remove';
|
||||
HANDLE_ICON_MAP.set(REMOVE, 'icons/delete.svg');
|
||||
const DECORATION_ICON_MAP = new Map();
|
||||
const ERROR = 'error';
|
||||
DECORATION_ICON_MAP.set(ERROR, 'icons/error.svg');
|
||||
joint.util.cloneDeep = (obj) => {
|
||||
return _.cloneDeepWith(obj, (o) => {
|
||||
if (_.isObject(o) && !_.isPlainObject(o)) {
|
||||
return o;
|
||||
}
|
||||
});
|
||||
};
|
||||
joint.util.filter.redscale = (args) => {
|
||||
let amount = Number.isFinite(args.amount) ? args.amount : 1;
|
||||
return _.template('<filter><feColorMatrix type="matrix" values="${a} ${b} ${c} 0 ${d} ${e} ${f} ${g} 0 0 ${h} ${i} ${k} 0 0 0 0 0 1 0"/></filter>', {
|
||||
a: 1 - 0.96 * amount,
|
||||
b: 0.95 * amount,
|
||||
c: 0.01 * amount,
|
||||
d: 0.3 * amount,
|
||||
e: 0.2 * amount,
|
||||
f: 1 - 0.9 * amount,
|
||||
g: 0.7 * amount,
|
||||
h: 0.05 * amount,
|
||||
i: 0.05 * amount,
|
||||
k: 1 - 0.1 * amount
|
||||
});
|
||||
};
|
||||
joint.util.filter.orangescale = (args) => {
|
||||
let amount = Number.isFinite(args.amount) ? args.amount : 1;
|
||||
return _.template('<filter><feColorMatrix type="matrix" values="${a} ${b} ${c} 0 ${d} ${e} ${f} ${g} 0 ${h} ${i} ${k} ${l} 0 0 0 0 0 1 0"/></filter>', {
|
||||
a: 1.0 + 0.5 * amount,
|
||||
b: 1.4 * amount,
|
||||
c: 0.2 * amount,
|
||||
d: 0.3 * amount,
|
||||
e: 0.3 * amount,
|
||||
f: 1 + 0.05 * amount,
|
||||
g: 0.2 * amount,
|
||||
h: 0.15 * amount,
|
||||
i: 0.3 * amount,
|
||||
k: 0.3 * amount,
|
||||
l: 1 - 0.6 * amount
|
||||
});
|
||||
};
|
||||
joint.shapes.flo.Node = joint.shapes.basic.Generic.extend({
|
||||
markup: '<g class="shape"><image class="image" /></g>' +
|
||||
'<rect class="border-white"/>' +
|
||||
'<rect class="border"/>' +
|
||||
'<rect class="box"/>' +
|
||||
'<text class="label"/>' +
|
||||
'<text class="label2"></text>' +
|
||||
'<rect class="input-port" />' +
|
||||
'<rect class="output-port"/>' +
|
||||
'<rect class="output-port-cover"/>',
|
||||
defaults: joint.util.deepSupplement({
|
||||
type: joint.shapes.flo.NODE_TYPE,
|
||||
position: { x: 0, y: 0 },
|
||||
size: { width: IMAGE_W, height: IMAGE_H },
|
||||
attrs: {
|
||||
'.': { magnet: false },
|
||||
// rounded edges around image
|
||||
'.border': {
|
||||
width: IMAGE_W,
|
||||
height: IMAGE_H,
|
||||
rx: 3,
|
||||
ry: 3,
|
||||
'fill-opacity': 0,
|
||||
stroke: '#eeeeee',
|
||||
'stroke-width': 0
|
||||
},
|
||||
'.box': {
|
||||
width: IMAGE_W,
|
||||
height: IMAGE_H,
|
||||
rx: 3,
|
||||
ry: 3,
|
||||
//'fill-opacity': 0, // see through
|
||||
stroke: '#6db33f',
|
||||
fill: '#eeeeee',
|
||||
'stroke-width': 1
|
||||
},
|
||||
'.input-port': {
|
||||
port: 'input',
|
||||
height: 8, width: 8,
|
||||
magnet: true,
|
||||
fill: '#eeeeee',
|
||||
transform: 'translate(' + -4 + ',' + ((IMAGE_H / 2) - 4) + ')',
|
||||
stroke: '#34302d',
|
||||
'stroke-width': 1
|
||||
},
|
||||
'.output-port': {
|
||||
port: 'output',
|
||||
height: 8, width: 8,
|
||||
magnet: true,
|
||||
fill: '#eeeeee',
|
||||
transform: 'translate(' + (IMAGE_W - 4) + ',' + ((IMAGE_H / 2) - 4) + ')',
|
||||
stroke: '#34302d',
|
||||
'stroke-width': 1
|
||||
},
|
||||
'.label': {
|
||||
'text-anchor': 'middle',
|
||||
'ref-x': 0.5,
|
||||
// 'ref-y': -12, // jointjs specific: relative position to ref'd element
|
||||
'ref-y': 0.3,
|
||||
ref: '.border',
|
||||
fill: 'black',
|
||||
'font-size': 14
|
||||
},
|
||||
'.label2': {
|
||||
'text': '\u21d2',
|
||||
'text-anchor': 'middle',
|
||||
'ref-x': 0.15,
|
||||
'ref-y': 0.2,
|
||||
ref: '.border',
|
||||
// transform: 'translate(' + (IMAGE_W/2) + ',' + (IMAGE_H/2) + ')',
|
||||
fill: 'black',
|
||||
'font-size': 24
|
||||
},
|
||||
'.shape': {},
|
||||
'.image': {
|
||||
width: IMAGE_W,
|
||||
height: IMAGE_H
|
||||
}
|
||||
}
|
||||
}, joint.shapes.basic.Generic.prototype.defaults)
|
||||
});
|
||||
joint.shapes.flo.Link = joint.dia.Link.extend({
|
||||
defaults: joint.util.deepSupplement({
|
||||
type: joint.shapes.flo.LINK_TYPE,
|
||||
attrs: {
|
||||
'.connection': { stroke: '#34302d', 'stroke-width': 2 },
|
||||
// Lots of alternatives that have been played with:
|
||||
// '.smoooth': true
|
||||
// '.marker-source': { stroke: '#9B59B6', fill: '#9B59B6', d: 'M24.316,5.318,9.833,13.682,9.833,5.5,5.5,5.5,5.5,25.5,9.833,25.5,9.833,17.318,24.316,25.682z' },
|
||||
// '.marker-target': { stroke: '#F39C12', fill: '#F39C12', d: 'M14.615,4.928c0.487-0.986,1.284-0.986,1.771,0l2.249,4.554c0.486,0.986,1.775,1.923,2.864,2.081l5.024,0.73c1.089,0.158,1.335,0.916,0.547,1.684l-3.636,3.544c-0.788,0.769-1.28,2.283-1.095,3.368l0.859,5.004c0.186,1.085-0.459,1.553-1.433,1.041l-4.495-2.363c-0.974-0.512-2.567-0.512-3.541,0l-4.495,2.363c-0.974,0.512-1.618,0.044-1.432-1.041l0.858-5.004c0.186-1.085-0.307-2.6-1.094-3.368L3.93,13.977c-0.788-0.768-0.542-1.525,0.547-1.684l5.026-0.73c1.088-0.158,2.377-1.095,2.864-2.081L14.615,4.928z' },
|
||||
// '.connection': { 'stroke':'black'},
|
||||
// '.': { filter: { name: 'dropShadow', args: { dx: 1, dy: 1, blur: 2 } } },
|
||||
// '.connection': { 'stroke-width': 10, 'stroke-linecap': 'round' },
|
||||
// This means: moveto 10 0, lineto 0 5, lineto, 10 10 closepath(z)
|
||||
// '.marker-target': { d: 'M 5 0 L 0 7 L 5 14 z', stroke: '#34302d','stroke-width': 1},
|
||||
// '.marker-target': { d: 'M 14 2 L 9,2 L9,0 L 0,7 L 9,14 L 9,12 L 14,12 z', 'stroke-width': 1, fill: '#34302d', stroke: '#34302d'},
|
||||
// '.marker-source': {d: 'M 5 0 L 5,10 L 0,10 L 0,0 z', 'stroke-width': 0, fill: '#34302d', stroke: '#34302d'},
|
||||
// '.marker-target': { stroke: '#E74C3C', fill: '#E74C3C', d: 'M 10 0 L 0 5 L 10 10 z' },
|
||||
'.marker-arrowheads': { display: 'none' },
|
||||
'.tool-options': { display: 'none' }
|
||||
},
|
||||
}, joint.dia.Link.prototype.defaults)
|
||||
});
|
||||
joint.shapes.flo.LinkView = joint.dia.LinkView.extend({
|
||||
options: joint.util.deepSupplement({}, joint.dia.LinkView.prototype.options),
|
||||
_beforeArrowheadMove: function () {
|
||||
if (this.model.get('source').id) {
|
||||
this._oldSource = this.model.get('source');
|
||||
}
|
||||
if (this.model.get('target').id) {
|
||||
this._oldTarget = this.model.get('target');
|
||||
}
|
||||
joint.dia.LinkView.prototype._beforeArrowheadMove.apply(this, arguments);
|
||||
},
|
||||
_afterArrowheadMove: function () {
|
||||
joint.dia.LinkView.prototype._afterArrowheadMove.apply(this, arguments);
|
||||
if (!this.model.get('source').id) {
|
||||
if (this._oldSource) {
|
||||
this.model.set('source', this._oldSource);
|
||||
}
|
||||
else {
|
||||
this.model.remove();
|
||||
}
|
||||
}
|
||||
if (!this.model.get('target').id) {
|
||||
if (this._oldTarget) {
|
||||
this.model.set('target', this._oldTarget);
|
||||
}
|
||||
else {
|
||||
this.model.remove();
|
||||
}
|
||||
}
|
||||
delete this._oldSource;
|
||||
delete this._oldTarget;
|
||||
}
|
||||
});
|
||||
// TODO: must do cleanup for the `mainElementView'
|
||||
joint.shapes.flo.ElementView = joint.dia.ElementView.extend({
|
||||
// canShowTooltip: true,
|
||||
beingDragged: false,
|
||||
// _tempZorder: 0,
|
||||
_tempOpacity: 1.0,
|
||||
_hovering: false,
|
||||
dragLinkStart: function (evt, magnet, x, y) {
|
||||
this.model.startBatch('add-link');
|
||||
const linkView = this.addLinkFromMagnet(magnet, x, y);
|
||||
// backwards compatiblity events
|
||||
joint.dia.CellView.prototype.pointerdown.apply(linkView, [evt, x, y]);
|
||||
linkView.notify('link:pointerdown', evt, x, y);
|
||||
/*** START MAIN DIFF ***/
|
||||
const sourceOrTarget = $(magnet).attr('port') === 'input' ? 'source' : 'target';
|
||||
linkView.eventData(evt, linkView.startArrowheadMove(sourceOrTarget, { whenNotAllowed: 'remove' }));
|
||||
/*** END MAIN DIFF ***/
|
||||
this.eventData(evt, { linkView: linkView });
|
||||
},
|
||||
addLinkFromMagnet: function (magnet, x, y) {
|
||||
const paper = this.paper;
|
||||
const graph = paper.model;
|
||||
const link = paper.getDefaultLink(this, magnet);
|
||||
let sourceEnd, targetEnd;
|
||||
/*** START MAIN DIFF ***/
|
||||
if ($(magnet).attr('port') === 'input') {
|
||||
sourceEnd = { x: x, y: y };
|
||||
targetEnd = this.getLinkEnd(magnet, x, y, link, 'target');
|
||||
}
|
||||
else {
|
||||
sourceEnd = this.getLinkEnd(magnet, x, y, link, 'source');
|
||||
targetEnd = { x: x, y: y };
|
||||
}
|
||||
/*** END MAIN DIFF ***/
|
||||
link.set({
|
||||
source: sourceEnd,
|
||||
target: targetEnd
|
||||
}).addTo(graph, {
|
||||
async: false,
|
||||
ui: true
|
||||
});
|
||||
return link.findView(paper);
|
||||
},
|
||||
// pointerdown: function(evt: any, x: number, y: number) {
|
||||
// // this.canShowTooltip = false;
|
||||
// // this.hideTooltip();
|
||||
// this.beingDragged = false;
|
||||
// this._tempOpacity = this.model.attr('./opacity');
|
||||
//
|
||||
// this.model.trigger('batch:start');
|
||||
//
|
||||
// if ( // target is a valid magnet start linking
|
||||
// evt.target.getAttribute('magnet') &&
|
||||
// this.paper.options.validateMagnet.call(this.paper, this, evt.target)
|
||||
// ) {
|
||||
// let link = this.paper.getDefaultLink(this, evt.target);
|
||||
// if ($(evt.target).attr('port') === 'input') {
|
||||
// link.set({
|
||||
// source: { x: x, y: y },
|
||||
// target: {
|
||||
// id: this.model.id,
|
||||
// selector: this.getSelector(evt.target),
|
||||
// port: evt.target.getAttribute('port')
|
||||
// }
|
||||
// });
|
||||
// } else {
|
||||
// link.set({
|
||||
// source: {
|
||||
// id: this.model.id,
|
||||
// selector: this.getSelector(evt.target),
|
||||
// port: evt.target.getAttribute('port')
|
||||
// },
|
||||
// target: { x: x, y: y }
|
||||
// });
|
||||
// }
|
||||
// this.paper.model.addCell(link);
|
||||
// this._linkView = this.paper.findViewByModel(link);
|
||||
// if ($(evt.target).attr('port') === 'input') {
|
||||
// this._linkView.startArrowheadMove('source');
|
||||
// } else {
|
||||
// this._linkView.startArrowheadMove('target');
|
||||
// }
|
||||
// this.paper.__creatingLinkFromPort = true;
|
||||
// } else {
|
||||
// this._dx = x;
|
||||
// this._dy = y;
|
||||
// joint.dia.CellView.prototype.pointerdown.apply(this, arguments);
|
||||
// }
|
||||
// },
|
||||
drag: function (evt, x, y) {
|
||||
let interactive = _.isFunction(this.options.interactive) ? this.options.interactive(this, 'pointermove') :
|
||||
this.options.interactive;
|
||||
if (interactive !== false) {
|
||||
this.paper.trigger('dragging-node-over-canvas', { type: Flo.DnDEventType.DRAG, view: this, event: evt });
|
||||
}
|
||||
joint.dia.ElementView.prototype.drag.apply(this, arguments);
|
||||
},
|
||||
dragEnd: function (evt, x, y) {
|
||||
this.paper.trigger('dragging-node-over-canvas', { type: Flo.DnDEventType.DROP, view: this, event: evt });
|
||||
joint.dia.ElementView.prototype.dragEnd.apply(this, arguments);
|
||||
},
|
||||
});
|
||||
joint.shapes.flo.ErrorDecoration = joint.shapes.basic.Generic.extend({
|
||||
markup: '<g class="rotatable"><g class="scalable"><image/></g></g>',
|
||||
defaults: joint.util.deepSupplement({
|
||||
type: joint.shapes.flo.DECORATION_TYPE,
|
||||
size: ERROR_MARKER_SIZE,
|
||||
attrs: {
|
||||
'image': ERROR_MARKER_SIZE
|
||||
}
|
||||
}, joint.shapes.basic.Generic.prototype.defaults)
|
||||
});
|
||||
export var Constants;
|
||||
(function (Constants) {
|
||||
Constants.REMOVE_HANDLE_TYPE = REMOVE;
|
||||
Constants.PROPERTIES_HANDLE_TYPE = 'properties';
|
||||
Constants.ERROR_DECORATION_KIND = ERROR;
|
||||
Constants.PALETTE_CONTEXT = 'palette';
|
||||
Constants.CANVAS_CONTEXT = 'canvas';
|
||||
Constants.FEEDBACK_CONTEXT = 'feedback';
|
||||
})(Constants || (Constants = {}));
|
||||
export var Shapes;
|
||||
(function (Shapes) {
|
||||
class Factory {
|
||||
/**
|
||||
* Create a JointJS node that embeds extra metadata (properties).
|
||||
*/
|
||||
static createNode(params) {
|
||||
let renderer = params.renderer;
|
||||
let paper = params.paper;
|
||||
let metadata = params.metadata;
|
||||
let position = params.position;
|
||||
let props = params.props;
|
||||
let graph = params.graph || (params.paper ? params.paper.model : undefined);
|
||||
let node;
|
||||
if (!position) {
|
||||
position = { x: 0, y: 0 };
|
||||
}
|
||||
if (renderer && _.isFunction(renderer.createNode)) {
|
||||
node = renderer.createNode(metadata, props);
|
||||
}
|
||||
else {
|
||||
node = new joint.shapes.flo.Node();
|
||||
if (metadata) {
|
||||
node.attr('.label/text', metadata.name);
|
||||
}
|
||||
}
|
||||
node.set('type', joint.shapes.flo.NODE_TYPE);
|
||||
if (position) {
|
||||
node.set('position', position);
|
||||
}
|
||||
if (props) {
|
||||
Array.from(props.keys()).forEach(key => node.attr(`props/${key}`, props.get(key)));
|
||||
}
|
||||
node.attr('metadata', metadata);
|
||||
if (graph) {
|
||||
graph.addCell(node);
|
||||
}
|
||||
if (renderer && _.isFunction(renderer.initializeNewNode)) {
|
||||
let descriptor = {
|
||||
paper: paper,
|
||||
graph: graph
|
||||
};
|
||||
renderer.initializeNewNode(node, descriptor);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
static createLink(params) {
|
||||
let renderer = params.renderer;
|
||||
let paper = params.paper;
|
||||
let metadata = params.metadata;
|
||||
let source = params.source;
|
||||
let target = params.target;
|
||||
let props = params.props;
|
||||
let graph = params.graph || (params.paper ? params.paper.model : undefined);
|
||||
let link;
|
||||
if (renderer && _.isFunction(renderer.createLink)) {
|
||||
link = renderer.createLink(source, target, metadata, props);
|
||||
}
|
||||
else {
|
||||
link = new joint.shapes.flo.Link();
|
||||
}
|
||||
if (source) {
|
||||
link.set('source', source);
|
||||
}
|
||||
if (target) {
|
||||
link.set('target', target);
|
||||
}
|
||||
link.set('type', joint.shapes.flo.LINK_TYPE);
|
||||
if (metadata) {
|
||||
link.attr('metadata', metadata);
|
||||
}
|
||||
if (props) {
|
||||
Array.from(props.keys()).forEach(key => link.attr(`props/${key}`, props.get(key)));
|
||||
}
|
||||
if (graph) {
|
||||
graph.addCell(link);
|
||||
}
|
||||
if (renderer && _.isFunction(renderer.initializeNewLink)) {
|
||||
let descriptor = {
|
||||
paper: paper,
|
||||
graph: graph
|
||||
};
|
||||
renderer.initializeNewLink(link, descriptor);
|
||||
}
|
||||
// prevent creation of link breaks
|
||||
link.attr('.marker-vertices/display', 'none');
|
||||
return link;
|
||||
}
|
||||
static createDecoration(params) {
|
||||
let renderer = params.renderer;
|
||||
let paper = params.paper;
|
||||
let parent = params.parent;
|
||||
let kind = params.kind;
|
||||
let messages = params.messages;
|
||||
let location = params.position;
|
||||
let graph = params.graph || (params.paper ? params.paper.model : undefined);
|
||||
if (!location) {
|
||||
location = { x: 0, y: 0 };
|
||||
}
|
||||
let decoration;
|
||||
if (renderer && _.isFunction(renderer.createDecoration)) {
|
||||
decoration = renderer.createDecoration(kind, parent);
|
||||
}
|
||||
else {
|
||||
decoration = new joint.shapes.flo.ErrorDecoration({
|
||||
attrs: {
|
||||
image: { 'xlink:href': DECORATION_ICON_MAP.get(kind) },
|
||||
}
|
||||
});
|
||||
}
|
||||
decoration.set('type', joint.shapes.flo.DECORATION_TYPE);
|
||||
decoration.set('position', location);
|
||||
if ((isChrome || isFF) && parent && typeof parent.get('z') === 'number') {
|
||||
decoration.set('z', parent.get('z') + 1);
|
||||
}
|
||||
decoration.attr('./kind', kind);
|
||||
decoration.attr('messages', messages);
|
||||
if (graph) {
|
||||
graph.addCell(decoration);
|
||||
}
|
||||
parent.embed(decoration);
|
||||
if (renderer && _.isFunction(renderer.initializeNewDecoration)) {
|
||||
let descriptor = {
|
||||
paper: paper,
|
||||
graph: graph
|
||||
};
|
||||
renderer.initializeNewDecoration(decoration, descriptor);
|
||||
}
|
||||
return decoration;
|
||||
}
|
||||
static createHandle(params) {
|
||||
let renderer = params.renderer;
|
||||
let paper = params.paper;
|
||||
let parent = params.parent;
|
||||
let kind = params.kind;
|
||||
let location = params.position;
|
||||
let graph = params.graph || (params.paper ? params.paper.model : undefined);
|
||||
let handle;
|
||||
if (!location) {
|
||||
location = { x: 0, y: 0 };
|
||||
}
|
||||
if (renderer && _.isFunction(renderer.createHandle)) {
|
||||
handle = renderer.createHandle(kind, parent);
|
||||
}
|
||||
else {
|
||||
handle = new joint.shapes.flo.ErrorDecoration({
|
||||
size: HANDLE_SIZE,
|
||||
attrs: {
|
||||
'image': {
|
||||
'xlink:href': HANDLE_ICON_MAP.get(kind)
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
handle.set('type', joint.shapes.flo.HANDLE_TYPE);
|
||||
handle.set('position', location);
|
||||
if ((isChrome || isFF) && parent && typeof parent.get('z') === 'number') {
|
||||
handle.set('z', parent.get('z') + 1);
|
||||
}
|
||||
handle.attr('./kind', kind);
|
||||
if (graph) {
|
||||
graph.addCell(handle);
|
||||
}
|
||||
parent.embed(handle);
|
||||
if (renderer && _.isFunction(renderer.initializeNewHandle)) {
|
||||
let descriptor = {
|
||||
paper: paper,
|
||||
graph: graph
|
||||
};
|
||||
renderer.initializeNewHandle(handle, descriptor);
|
||||
}
|
||||
return handle;
|
||||
}
|
||||
}
|
||||
Shapes.Factory = Factory;
|
||||
})(Shapes || (Shapes = {}));
|
||||
//# sourceMappingURL=shapes.js.map
|
||||
5
dist/esm2015/spring-flo.js
vendored
Normal file
5
dist/esm2015/spring-flo.js
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* Generated bundle index. Do not edit.
|
||||
*/
|
||||
export * from './index';
|
||||
//# sourceMappingURL=spring-flo.js.map
|
||||
1
dist/esm2015/spring-flo.metadata.json
vendored
Normal file
1
dist/esm2015/spring-flo.metadata.json
vendored
Normal file
File diff suppressed because one or more lines are too long
237
dist/esm5/code-editor/code-editor.component.js
vendored
Normal file
237
dist/esm5/code-editor/code-editor.component.js
vendored
Normal file
File diff suppressed because one or more lines are too long
192
dist/esm5/directives/resizer.js
vendored
Normal file
192
dist/esm5/directives/resizer.js
vendored
Normal file
@@ -0,0 +1,192 @@
|
||||
import * as tslib_1 from "tslib";
|
||||
import { Directive, Input, Output, EventEmitter, Inject, ElementRef } from '@angular/core';
|
||||
import { DOCUMENT } from '@angular/platform-browser';
|
||||
import { fromEvent } from 'rxjs';
|
||||
import { sampleTime } from 'rxjs/operators';
|
||||
import { CompositeDisposable, Disposable } from 'ts-disposables';
|
||||
import * as _$ from 'jquery';
|
||||
var $ = _$;
|
||||
var ResizerDirective = /** @class */ (function () {
|
||||
function ResizerDirective(element, document) {
|
||||
var _this = this;
|
||||
this.element = element;
|
||||
this.document = document;
|
||||
this.dragInProgress = false;
|
||||
this.vertical = true;
|
||||
this._subscriptions = new CompositeDisposable();
|
||||
this.sizeChange = new EventEmitter();
|
||||
this.mouseMoveHandler = function (e) {
|
||||
if (_this.dragInProgress) {
|
||||
_this.mousemove(e);
|
||||
}
|
||||
};
|
||||
}
|
||||
Object.defineProperty(ResizerDirective.prototype, "splitSize", {
|
||||
set: function (splitSize) {
|
||||
if (this.maxSplitSize && splitSize > this.maxSplitSize) {
|
||||
splitSize = this.maxSplitSize;
|
||||
}
|
||||
if (this.vertical) {
|
||||
// Handle vertical resizer
|
||||
$(this.element.nativeElement).css({
|
||||
left: splitSize + 'px'
|
||||
});
|
||||
$(this.first).css({
|
||||
width: splitSize + 'px'
|
||||
});
|
||||
$(this.second).css({
|
||||
left: (splitSize + this._size) + 'px'
|
||||
});
|
||||
}
|
||||
else {
|
||||
// Handle horizontal resizer
|
||||
$(this.element.nativeElement).css({
|
||||
bottom: splitSize + 'px'
|
||||
});
|
||||
$(this.first).css({
|
||||
bottom: (splitSize + this._size) + 'px'
|
||||
});
|
||||
$(this.second).css({
|
||||
height: splitSize + 'px'
|
||||
});
|
||||
}
|
||||
this._splitSize = splitSize;
|
||||
// Update the local field
|
||||
this.sizeChange.emit(splitSize);
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(ResizerDirective.prototype, "resizerWidth", {
|
||||
set: function (width) {
|
||||
this._size = width;
|
||||
this.vertical = true;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(ResizerDirective.prototype, "resizerHeight", {
|
||||
set: function (height) {
|
||||
this._size = height;
|
||||
this.vertical = false;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(ResizerDirective.prototype, "resizerLeft", {
|
||||
set: function (first) {
|
||||
this.first = first;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(ResizerDirective.prototype, "resizerTop", {
|
||||
set: function (first) {
|
||||
this.first = first;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(ResizerDirective.prototype, "resizerRight", {
|
||||
set: function (second) {
|
||||
this.second = second;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(ResizerDirective.prototype, "resizerBottom", {
|
||||
set: function (second) {
|
||||
this.second = second;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
ResizerDirective.prototype.startDrag = function () {
|
||||
this.dragInProgress = true;
|
||||
};
|
||||
ResizerDirective.prototype.mousemove = function (event) {
|
||||
var size;
|
||||
if (this.vertical) { // Handle vertical resizer. Calculate new size relative to palette container DOM node
|
||||
size = event.pageX - $(this.first).offset().left;
|
||||
}
|
||||
else {
|
||||
// Handle horizontal resizer Calculate new size relative to palette container DOM node
|
||||
size = window.innerHeight - event.pageY - $(this.second).offset().top;
|
||||
}
|
||||
this.splitSize = size;
|
||||
};
|
||||
ResizerDirective.prototype.ngOnInit = function () {
|
||||
// Need to set left and right elements width and fire events on init when DOM is built
|
||||
var _this = this;
|
||||
this.splitSize = this._splitSize;
|
||||
var subscription1 = fromEvent($(this.document).get(0), 'mousemove')
|
||||
.pipe(sampleTime(300))
|
||||
.subscribe(this.mouseMoveHandler);
|
||||
this._subscriptions.add(Disposable.create(function () { return subscription1.unsubscribe(); }));
|
||||
var subscription2 = fromEvent($(this.document).get(0), 'mouseup')
|
||||
.subscribe(function (e) {
|
||||
if (_this.dragInProgress) {
|
||||
_this.mousemove(e);
|
||||
_this.dragInProgress = false;
|
||||
}
|
||||
});
|
||||
this._subscriptions.add(Disposable.create(function () { return subscription2.unsubscribe(); }));
|
||||
};
|
||||
ResizerDirective.prototype.ngOnDestroy = function () {
|
||||
this._subscriptions.dispose();
|
||||
};
|
||||
tslib_1.__decorate([
|
||||
Input(),
|
||||
tslib_1.__metadata("design:type", Number)
|
||||
], ResizerDirective.prototype, "maxSplitSize", void 0);
|
||||
tslib_1.__decorate([
|
||||
Output(),
|
||||
tslib_1.__metadata("design:type", Object)
|
||||
], ResizerDirective.prototype, "sizeChange", void 0);
|
||||
tslib_1.__decorate([
|
||||
Input(),
|
||||
tslib_1.__metadata("design:type", Number),
|
||||
tslib_1.__metadata("design:paramtypes", [Number])
|
||||
], ResizerDirective.prototype, "splitSize", null);
|
||||
tslib_1.__decorate([
|
||||
Input(),
|
||||
tslib_1.__metadata("design:type", Number),
|
||||
tslib_1.__metadata("design:paramtypes", [Number])
|
||||
], ResizerDirective.prototype, "resizerWidth", null);
|
||||
tslib_1.__decorate([
|
||||
Input(),
|
||||
tslib_1.__metadata("design:type", Number),
|
||||
tslib_1.__metadata("design:paramtypes", [Number])
|
||||
], ResizerDirective.prototype, "resizerHeight", null);
|
||||
tslib_1.__decorate([
|
||||
Input(),
|
||||
tslib_1.__metadata("design:type", String),
|
||||
tslib_1.__metadata("design:paramtypes", [String])
|
||||
], ResizerDirective.prototype, "resizerLeft", null);
|
||||
tslib_1.__decorate([
|
||||
Input(),
|
||||
tslib_1.__metadata("design:type", String),
|
||||
tslib_1.__metadata("design:paramtypes", [String])
|
||||
], ResizerDirective.prototype, "resizerTop", null);
|
||||
tslib_1.__decorate([
|
||||
Input(),
|
||||
tslib_1.__metadata("design:type", String),
|
||||
tslib_1.__metadata("design:paramtypes", [String])
|
||||
], ResizerDirective.prototype, "resizerRight", null);
|
||||
tslib_1.__decorate([
|
||||
Input(),
|
||||
tslib_1.__metadata("design:type", String),
|
||||
tslib_1.__metadata("design:paramtypes", [String])
|
||||
], ResizerDirective.prototype, "resizerBottom", null);
|
||||
ResizerDirective = tslib_1.__decorate([
|
||||
Directive({
|
||||
selector: '[resizer]',
|
||||
host: { '(mousedown)': 'startDrag()' }
|
||||
}),
|
||||
tslib_1.__param(1, Inject(DOCUMENT)),
|
||||
tslib_1.__metadata("design:paramtypes", [ElementRef, Object])
|
||||
], ResizerDirective);
|
||||
return ResizerDirective;
|
||||
}());
|
||||
export { ResizerDirective };
|
||||
//# sourceMappingURL=resizer.js.map
|
||||
158
dist/esm5/dsl-editor/dsl-editor.component.js
vendored
Normal file
158
dist/esm5/dsl-editor/dsl-editor.component.js
vendored
Normal file
File diff suppressed because one or more lines are too long
112
dist/esm5/editor/editor-utils.js
vendored
Normal file
112
dist/esm5/editor/editor-utils.js
vendored
Normal file
@@ -0,0 +1,112 @@
|
||||
import { Flo } from '../shared/flo-common';
|
||||
import * as _ from 'lodash';
|
||||
var joint = Flo.joint;
|
||||
import * as _$ from 'jquery';
|
||||
var $ = _$;
|
||||
var Utils = /** @class */ (function () {
|
||||
function Utils() {
|
||||
}
|
||||
Utils.fanRoute = function (graph, cell) {
|
||||
if (cell instanceof joint.dia.Element) {
|
||||
var links = graph.getConnectedLinks(cell);
|
||||
var groupsOfOverlappingLinks = _.groupBy(links, function (link) {
|
||||
// the key of the group is the model id of the link's source or target, but not our cell id.
|
||||
var sourceId = link.get('source').id;
|
||||
var targetId = link.get('target').id;
|
||||
return cell.id !== sourceId ? sourceId : targetId;
|
||||
});
|
||||
_.each(groupsOfOverlappingLinks, function (group, key) {
|
||||
// If the member of the group has both source and target model adjust vertices.
|
||||
var toRoute = {};
|
||||
if (key !== undefined) {
|
||||
group.forEach(function (link) {
|
||||
if (link.get('source').id === cell.get('id') && link.get('target').id) {
|
||||
toRoute[link.get('target').id] = link;
|
||||
}
|
||||
else if (link.get('target').id === cell.get('id') && link.get('source').id) {
|
||||
toRoute[link.get('source').id] = link;
|
||||
}
|
||||
});
|
||||
Object.keys(toRoute).forEach(function (k) {
|
||||
Utils.fanRoute(graph, toRoute[k]);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (cell instanceof joint.dia.Link) {
|
||||
// The cell is a link. Let's find its source and target models.
|
||||
var srcId_1 = cell.get('source').id || cell.previous('source').id;
|
||||
var trgId_1 = cell.get('target').id || cell.previous('target').id;
|
||||
// If one of the ends is not a model, the link has no siblings.
|
||||
if (!srcId_1 || !trgId_1) {
|
||||
return;
|
||||
}
|
||||
var siblings = graph.getLinks().filter(function (sibling) {
|
||||
var _srcId = sibling.get('source').id;
|
||||
var _trgId = sibling.get('target').id;
|
||||
var vertices = sibling.get('vertices');
|
||||
var fanRouted = !vertices || vertices.length === 0 || sibling.get('fanRouted');
|
||||
return ((_srcId === srcId_1 && _trgId === trgId_1) || (_srcId === trgId_1 && _trgId === srcId_1)) && fanRouted;
|
||||
});
|
||||
switch (siblings.length) {
|
||||
case 0:
|
||||
// The link was removed and had no siblings.
|
||||
break;
|
||||
case 1:
|
||||
// There is only one link between the source and target. No vertices needed.
|
||||
var vertices = cell.get('vertices');
|
||||
if (vertices && vertices.length && cell.get('fanRouted')) {
|
||||
cell.unset('vertices');
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// There is more than one siblings. We need to create vertices.
|
||||
// First of all we'll find the middle point of the link.
|
||||
var source = graph.getCell(srcId_1);
|
||||
var target = graph.getCell(trgId_1);
|
||||
if (!source || !target) {
|
||||
// When clearing the graph it may happen that some nodes are gone and some are left
|
||||
return;
|
||||
}
|
||||
var srcCenter = source.getBBox().center();
|
||||
var trgCenter = target.getBBox().center();
|
||||
var midPoint_1 = joint.g.line(srcCenter, trgCenter).midpoint();
|
||||
// Then find the angle it forms.
|
||||
var theta_1 = srcCenter.theta(trgCenter);
|
||||
// This is the maximum distance between links
|
||||
var gap_1 = 20;
|
||||
siblings.forEach(function (sibling, index) {
|
||||
// We want the offset values to be calculated as follows 0, 20, 20, 40, 40, 60, 60 ..
|
||||
var offset = gap_1 * Math.ceil(index / 2);
|
||||
// Now we need the vertices to be placed at points which are 'offset' pixels distant
|
||||
// from the first link and forms a perpendicular angle to it. And as index goes up
|
||||
// alternate left and right.
|
||||
//
|
||||
// ^ odd indexes
|
||||
// |
|
||||
// |----> index 0 line (straight line between a source center and a target center.
|
||||
// |
|
||||
// v even indexes
|
||||
var sign = index % 2 ? 1 : -1;
|
||||
var angle = joint.g.toRad(theta_1 + sign * 90);
|
||||
// We found the vertex.
|
||||
var vertex = joint.g.point.fromPolar(offset, angle, midPoint_1);
|
||||
sibling.set('fanRouted', true);
|
||||
sibling.set('vertices', [{ x: vertex.x, y: vertex.y }], { 'fanRouted': true });
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
Utils.isCustomPaperEvent = function (args) {
|
||||
return args.length === 5 &&
|
||||
_.isString(args[0]) &&
|
||||
(args[0].indexOf('link:') === 0 || args[0].indexOf('element:') === 0) &&
|
||||
args[1] instanceof $.Event &&
|
||||
args[2] instanceof joint.dia.CellView &&
|
||||
_.isNumber(args[3]) &&
|
||||
_.isNumber(args[4]);
|
||||
};
|
||||
return Utils;
|
||||
}());
|
||||
export { Utils };
|
||||
//# sourceMappingURL=editor-utils.js.map
|
||||
1195
dist/esm5/editor/editor.component.js
vendored
Normal file
1195
dist/esm5/editor/editor.component.js
vendored
Normal file
File diff suppressed because one or more lines are too long
12
dist/esm5/index.js
vendored
Normal file
12
dist/esm5/index.js
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
export { FloModule } from './module';
|
||||
export { Palette } from './palette/palette.component';
|
||||
export { EditorComponent } from './editor/editor.component';
|
||||
export { DslEditorComponent } from './dsl-editor/dsl-editor.component';
|
||||
export { CodeEditorComponent } from './code-editor/code-editor.component';
|
||||
export { PropertiesGroupComponent } from './properties/properties.group.component';
|
||||
export { DynamicFormPropertyComponent } from './properties/df.property.component';
|
||||
export { ResizerDirective } from './directives/resizer';
|
||||
export * from './shared/flo-common';
|
||||
export * from './shared/flo-properties';
|
||||
export * from './shared/shapes';
|
||||
//# sourceMappingURL=index.js.map
|
||||
42
dist/esm5/module.js
vendored
Normal file
42
dist/esm5/module.js
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
import * as tslib_1 from "tslib";
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Palette } from './palette/palette.component';
|
||||
import { EditorComponent } from './editor/editor.component';
|
||||
import { ResizerDirective } from './directives/resizer';
|
||||
import { DslEditorComponent } from './dsl-editor/dsl-editor.component';
|
||||
import { CodeEditorComponent } from './code-editor/code-editor.component';
|
||||
import { PropertiesGroupComponent } from './properties/properties.group.component';
|
||||
import { DynamicFormPropertyComponent } from './properties/df.property.component';
|
||||
var FloModule = /** @class */ (function () {
|
||||
function FloModule() {
|
||||
}
|
||||
FloModule = tslib_1.__decorate([
|
||||
NgModule({
|
||||
imports: [
|
||||
FormsModule,
|
||||
CommonModule,
|
||||
ReactiveFormsModule
|
||||
],
|
||||
declarations: [
|
||||
Palette,
|
||||
EditorComponent,
|
||||
ResizerDirective,
|
||||
DslEditorComponent,
|
||||
CodeEditorComponent,
|
||||
PropertiesGroupComponent,
|
||||
DynamicFormPropertyComponent
|
||||
],
|
||||
exports: [
|
||||
EditorComponent,
|
||||
DslEditorComponent,
|
||||
DynamicFormPropertyComponent,
|
||||
PropertiesGroupComponent
|
||||
]
|
||||
})
|
||||
], FloModule);
|
||||
return FloModule;
|
||||
}());
|
||||
export { FloModule };
|
||||
//# sourceMappingURL=module.js.map
|
||||
460
dist/esm5/palette/palette.component.js
vendored
Normal file
460
dist/esm5/palette/palette.component.js
vendored
Normal file
@@ -0,0 +1,460 @@
|
||||
import * as tslib_1 from "tslib";
|
||||
import { Component, ElementRef, Input, Output, EventEmitter, Inject, ViewEncapsulation } from '@angular/core';
|
||||
import { Subject } from 'rxjs';
|
||||
import { debounceTime } from 'rxjs/operators';
|
||||
import { dia } from 'jointjs';
|
||||
import { Flo } from '../shared/flo-common';
|
||||
import { Shapes, Constants } from '../shared/shapes';
|
||||
import { DOCUMENT } from '@angular/platform-browser';
|
||||
import * as _$ from 'jquery';
|
||||
var joint = Flo.joint;
|
||||
var $ = _$;
|
||||
var DEBOUNCE_TIME = 300;
|
||||
joint.shapes.flo.PaletteGroupHeader = joint.shapes.basic.Generic.extend({
|
||||
// The path is the open/close arrow, defaults to vertical (open)
|
||||
markup: '<g class="scalable"><rect/></g><text/><g class="rotatable"><path d="m 10 10 l 5 8.7 l 5 -8.7 z"/></g>',
|
||||
defaults: joint.util.deepSupplement({
|
||||
type: 'palette.groupheader',
|
||||
size: { width: 170, height: 30 },
|
||||
position: { x: 0, y: 0 },
|
||||
attrs: {
|
||||
'rect': { fill: '#34302d', 'stroke-width': 1, stroke: '#6db33f', 'follow-scale': true, width: 80, height: 40 },
|
||||
'text': {
|
||||
text: '',
|
||||
fill: '#eeeeee',
|
||||
'ref-x': 0.5,
|
||||
'ref-y': 7,
|
||||
'x-alignment': 'middle',
|
||||
'font-size': 18 /*, 'font-weight': 'bold', 'font-variant': 'small-caps', 'text-transform': 'capitalize'*/
|
||||
},
|
||||
'path': { fill: 'white', 'stroke-width': 2, stroke: 'white' /*,transform:'rotate(90,15,15)'*/ }
|
||||
},
|
||||
// custom properties
|
||||
isOpen: true
|
||||
}, joint.shapes.basic.Generic.prototype.defaults)
|
||||
});
|
||||
var Palette = /** @class */ (function () {
|
||||
function Palette(element, document) {
|
||||
var _this = this;
|
||||
this.element = element;
|
||||
this.document = document;
|
||||
this._metamodelListener = {
|
||||
metadataError: function (data) { },
|
||||
metadataAboutToChange: function () { },
|
||||
metadataChanged: function () { return _this.rebuildPalette(); }
|
||||
};
|
||||
this.initialized = false;
|
||||
this._filterText = '';
|
||||
this.filterTextModel = new Subject();
|
||||
this.paletteEntryPadding = { width: 12, height: 12 };
|
||||
this.onPaletteEntryDrop = new EventEmitter();
|
||||
this.paletteReady = new EventEmitter();
|
||||
this.paletteFocus = new EventEmitter();
|
||||
this.mouseMoveHanlder = function (e) { return _this.handleDrag(e); };
|
||||
this.mouseUpHanlder = function (e) { return _this.handleMouseUp(e); };
|
||||
this.paletteGraph = new joint.dia.Graph();
|
||||
this.paletteGraph.set('type', Constants.PALETTE_CONTEXT);
|
||||
this._filterText = '';
|
||||
this.closedGroups = new Set();
|
||||
}
|
||||
Object.defineProperty(Palette.prototype, "paletteSize", {
|
||||
set: function (size) {
|
||||
console.debug('Palette Size: ' + size);
|
||||
if (this._paletteSize !== size) {
|
||||
this._paletteSize = size;
|
||||
this.rebuildPalette();
|
||||
}
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Palette.prototype.onFocus = function () {
|
||||
this.paletteFocus.emit();
|
||||
};
|
||||
Palette.prototype.ngOnInit = function () {
|
||||
var _this = this;
|
||||
var element = $('#palette-paper', this.element.nativeElement);
|
||||
// Create the paper for the palette using the specified element view
|
||||
this.palette = new joint.dia.Paper({
|
||||
el: element,
|
||||
gridSize: 1,
|
||||
model: this.paletteGraph,
|
||||
height: $(this.element.nativeElement.parentNode).height(),
|
||||
width: $(this.element.nativeElement.parentNode).width(),
|
||||
elementView: this.getPaletteView(this.renderer && this.renderer.getNodeView ? this.renderer.getNodeView() : joint.dia.ElementView),
|
||||
interactive: false
|
||||
});
|
||||
this.palette.on('cell:pointerup', function (cellview, evt) {
|
||||
if (_this.viewBeingDragged) {
|
||||
_this.trigger({
|
||||
type: Flo.DnDEventType.DROP,
|
||||
view: _this.viewBeingDragged,
|
||||
event: evt
|
||||
});
|
||||
_this.viewBeingDragged = undefined;
|
||||
}
|
||||
_this.clickedElement = undefined;
|
||||
$('#palette-floater').remove();
|
||||
if (_this.floaterpaper) {
|
||||
_this.floaterpaper.remove();
|
||||
}
|
||||
});
|
||||
// Toggle the header open/closed on a click
|
||||
this.palette.on('cell:pointerclick', function (cellview, event) {
|
||||
// TODO [design][palette] should the user need to click on the arrow rather than anywhere on the header?
|
||||
// Click position within the element would be: evt.offsetX, evt.offsetY
|
||||
var cell = cellview.model;
|
||||
if (cell.attributes.header) {
|
||||
// Toggle the header open/closed
|
||||
if (cell.get('isOpen')) {
|
||||
_this.rotateClosed(cell);
|
||||
}
|
||||
else {
|
||||
_this.rotateOpen(cell);
|
||||
}
|
||||
}
|
||||
// TODO [palette] ensure other mouse handling events do nothing for headers
|
||||
// TODO [palette] move 'metadata' field to the right place (not inside attrs I think)
|
||||
});
|
||||
$(this.document).on('mouseup', this.mouseUpHanlder);
|
||||
if (this.metamodel) {
|
||||
this.metamodel.load().then(function (data) {
|
||||
_this.buildPalette(data);
|
||||
// Add listener to metamodel
|
||||
if (_this.metamodel && _this.metamodel.subscribe) {
|
||||
_this.metamodel.subscribe(_this._metamodelListener);
|
||||
}
|
||||
// Add debounced listener to filter text changes
|
||||
_this.filterTextModel
|
||||
.pipe(debounceTime(DEBOUNCE_TIME))
|
||||
.subscribe(function (value) { return _this.rebuildPalette(); });
|
||||
_this.initialized = true;
|
||||
});
|
||||
}
|
||||
else {
|
||||
console.error('No Metamodel service specified for palette!');
|
||||
}
|
||||
this._paletteSize = this._paletteSize || $(this.element.nativeElement.parentNode).width();
|
||||
};
|
||||
Palette.prototype.ngOnDestroy = function () {
|
||||
if (this.metamodel && this.metamodel.unsubscribe) {
|
||||
this.metamodel.unsubscribe(this._metamodelListener);
|
||||
}
|
||||
$(this.document).off('mouseup', this.mouseUpHanlder);
|
||||
this.palette.remove();
|
||||
};
|
||||
Palette.prototype.ngOnChanges = function (changes) {
|
||||
// if (changes.hasOwnProperty('paletteSize') || changes.hasOwnProperty('filterText')) {
|
||||
// this.metamodel.load().then(metamodel => this.buildPalette(metamodel));
|
||||
// }
|
||||
};
|
||||
Palette.prototype.createPaletteGroup = function (title, isOpen) {
|
||||
var newGroupHeader = new joint.shapes.flo.PaletteGroupHeader({ attrs: { text: { text: title } } });
|
||||
newGroupHeader.set('header', title);
|
||||
if (!isOpen) {
|
||||
newGroupHeader.attr({ 'path': { 'transform': 'rotate(-90,15,13)' } });
|
||||
newGroupHeader.set('isOpen', false);
|
||||
}
|
||||
this.paletteGraph.addCell(newGroupHeader);
|
||||
return newGroupHeader;
|
||||
};
|
||||
Palette.prototype.createPaletteEntry = function (title, metadata) {
|
||||
return Shapes.Factory.createNode({
|
||||
renderer: this.renderer,
|
||||
paper: this.palette,
|
||||
metadata: metadata
|
||||
});
|
||||
};
|
||||
Palette.prototype.buildPalette = function (metamodel) {
|
||||
var _this = this;
|
||||
var startTime = new Date().getTime();
|
||||
this.paletteReady.emit(false);
|
||||
this.paletteGraph.clear();
|
||||
var filterText = this.filterText;
|
||||
if (filterText) {
|
||||
filterText = filterText.toLowerCase();
|
||||
}
|
||||
var paletteNodes = [];
|
||||
var groupAdded = new Set();
|
||||
var parentWidth = this._paletteSize;
|
||||
console.debug("Parent Width: " + parentWidth);
|
||||
// The field closedGroups tells us which should not be shown
|
||||
// Work out the list of active groups/nodes based on the filter text
|
||||
this.metamodel.groups().forEach(function (group) {
|
||||
if (metamodel && metamodel.has(group)) {
|
||||
Array.from(metamodel.get(group).keys()).sort().forEach(function (name) {
|
||||
var node = metamodel.get(group).get(name);
|
||||
if (node) {
|
||||
var nodeActive = !(node.metadata && node.metadata.noPaletteEntry);
|
||||
if (nodeActive && filterText) {
|
||||
nodeActive = false;
|
||||
if (name.toLowerCase().indexOf(filterText) !== -1) {
|
||||
nodeActive = true;
|
||||
}
|
||||
else if (group.toLowerCase().indexOf(filterText) !== -1) {
|
||||
nodeActive = true;
|
||||
}
|
||||
// else if (node.description && node.description.toLowerCase().indexOf(filterText) !== -1) {
|
||||
// nodeActive = true;
|
||||
// }
|
||||
// else if (node.properties) {
|
||||
// Object.keys(node.properties).sort().forEach(function(propertyName) {
|
||||
// if (propertyName.toLowerCase().indexOf(filterText) !== -1 ||
|
||||
// (node.properties[propertyName].description &&
|
||||
// node.properties[propertyName].description.toLowerCase().indexOf(filterText) !== -1)) {
|
||||
// nodeActive=true;
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
}
|
||||
if (nodeActive) {
|
||||
if (!groupAdded.has(group)) {
|
||||
var header = _this.createPaletteGroup(group, !_this.closedGroups.has(group));
|
||||
header.set('size', { width: parentWidth, height: 30 });
|
||||
paletteNodes.push(header);
|
||||
groupAdded.add(group);
|
||||
}
|
||||
if (!_this.closedGroups.has(group)) {
|
||||
paletteNodes.push(_this.createPaletteEntry(name, node));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
var cellWidth = 0, cellHeight = 0;
|
||||
// Determine the size of the palette entry cell (width and height)
|
||||
paletteNodes.forEach(function (pnode) {
|
||||
if (pnode.attr('metadata/name')) {
|
||||
var dimension = {
|
||||
width: pnode.get('size').width,
|
||||
height: pnode.get('size').height
|
||||
};
|
||||
if (cellWidth < dimension.width) {
|
||||
cellWidth = dimension.width;
|
||||
}
|
||||
if (cellHeight < dimension.height) {
|
||||
cellHeight = dimension.height;
|
||||
}
|
||||
}
|
||||
});
|
||||
// Adjust the palette entry cell size with paddings.
|
||||
cellWidth += 2 * this.paletteEntryPadding.width;
|
||||
cellHeight += 2 * this.paletteEntryPadding.height;
|
||||
// Align palette entries row to be at the center
|
||||
var startX = parentWidth >= cellWidth ? (parentWidth - Math.floor(parentWidth / cellWidth) * cellWidth) / 2 : 0;
|
||||
var xpos = startX;
|
||||
var ypos = 0;
|
||||
var prevNode;
|
||||
// Layout palette entry nodes
|
||||
paletteNodes.forEach(function (pnode) {
|
||||
var dimension = {
|
||||
width: pnode.get('size').width,
|
||||
height: pnode.get('size').height
|
||||
};
|
||||
if (pnode.get('header')) { //attributes.attrs.header) {
|
||||
// Palette entry header
|
||||
xpos = startX;
|
||||
pnode.set('position', { x: 0, y: ypos });
|
||||
ypos += dimension.height + 5;
|
||||
}
|
||||
else {
|
||||
// Palette entry element
|
||||
if (xpos + cellWidth > parentWidth) {
|
||||
// Not enough real estate to place entry in a row - reset x position and leave the y pos which is next line
|
||||
xpos = startX;
|
||||
pnode.set('position', { x: xpos + (cellWidth - dimension.width) / 2, y: ypos + (cellHeight - dimension.height) / 2 });
|
||||
}
|
||||
else {
|
||||
// Enough real estate to place entry in a row - adjust y position
|
||||
if (prevNode && prevNode.attr('metadata/name')) {
|
||||
ypos -= cellHeight;
|
||||
}
|
||||
pnode.set('position', { x: xpos + (cellWidth - dimension.width) / 2, y: ypos + (cellHeight - dimension.height) / 2 });
|
||||
}
|
||||
// increment x position and y position (can be reorganized)
|
||||
xpos += cellWidth;
|
||||
ypos += cellHeight;
|
||||
}
|
||||
prevNode = pnode;
|
||||
});
|
||||
this.palette.setDimensions(parentWidth, ypos);
|
||||
this.paletteReady.emit(true);
|
||||
console.debug('buildPalette took ' + (new Date().getTime() - startTime) + 'ms');
|
||||
};
|
||||
Palette.prototype.rebuildPalette = function () {
|
||||
var _this = this;
|
||||
if (this.initialized && this.metamodel) {
|
||||
this.metamodel.load().then(function (metamodel) { return _this.buildPalette(metamodel); });
|
||||
}
|
||||
};
|
||||
Object.defineProperty(Palette.prototype, "filterText", {
|
||||
get: function () {
|
||||
return this._filterText;
|
||||
},
|
||||
set: function (text) {
|
||||
if (this._filterText !== text) {
|
||||
this._filterText = text;
|
||||
this.filterTextModel.next(text);
|
||||
}
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Palette.prototype.getPaletteView = function (view) {
|
||||
var self = this;
|
||||
return view.extend({
|
||||
pointerdown: function ( /*evt, x, y*/) {
|
||||
// Remove the tooltip
|
||||
// $('.node-tooltip').remove();
|
||||
// TODO move metadata to the right place (not inside attrs I think)
|
||||
self.clickedElement = this.model;
|
||||
if (self.clickedElement && self.clickedElement.attr('metadata')) {
|
||||
$(self.document).on('mousemove', self.mouseMoveHanlder);
|
||||
}
|
||||
},
|
||||
pointermove: function ( /*evt, x, y*/) {
|
||||
// Nothing to prevent move within the palette canvas
|
||||
},
|
||||
});
|
||||
};
|
||||
Palette.prototype.handleMouseUp = function (event) {
|
||||
$(this.document).off('mousemove', this.mouseMoveHanlder);
|
||||
};
|
||||
Palette.prototype.trigger = function (event) {
|
||||
this.onPaletteEntryDrop.emit(event);
|
||||
};
|
||||
Palette.prototype.handleDrag = function (event) {
|
||||
// TODO offsetX/Y not on firefox
|
||||
// console.debug("tracking move: x="+event.pageX+",y="+event.pageY);
|
||||
// console.debug('Element = ' + (this.clickedElement ? this.clickedElement.attr('metadata/name'): 'null'));
|
||||
if (this.clickedElement && this.clickedElement.attr('metadata')) {
|
||||
if (!this.viewBeingDragged) {
|
||||
var dataOfClickedElement = this.clickedElement.attr('metadata');
|
||||
// custom div if not already built.
|
||||
$('<div>', {
|
||||
id: 'palette-floater'
|
||||
}).appendTo($('body'));
|
||||
var floatergraph = new joint.dia.Graph();
|
||||
floatergraph.set('type', Constants.FEEDBACK_CONTEXT);
|
||||
var parent_1 = $('#palette-floater');
|
||||
this.floaterpaper = new joint.dia.Paper({
|
||||
el: $('#palette-floater'),
|
||||
elementView: this.renderer && this.renderer.getNodeView ? this.renderer.getNodeView() : joint.dia.ElementView,
|
||||
gridSize: 10,
|
||||
model: floatergraph,
|
||||
height: parent_1.height(),
|
||||
width: parent_1.width(),
|
||||
validateMagnet: function () { return false; },
|
||||
validateConnection: function () { return false; }
|
||||
});
|
||||
// TODO float thing needs to be bigger otherwise icon label is missing
|
||||
// Initiative drag and drop - create draggable element
|
||||
var floaternode = Shapes.Factory.createNode({
|
||||
'renderer': this.renderer,
|
||||
'paper': this.floaterpaper,
|
||||
'graph': floatergraph,
|
||||
'metadata': dataOfClickedElement
|
||||
});
|
||||
// Only node view expected
|
||||
var box = this.floaterpaper.findViewByModel(floaternode).getBBox();
|
||||
var size = floaternode.get('size');
|
||||
// Account for node real size including ports
|
||||
floaternode.translate(box.width - size.width, box.height - size.height);
|
||||
this.viewBeingDragged = this.floaterpaper.findViewByModel(floaternode);
|
||||
$('#palette-floater').offset({ left: event.pageX + 5, top: event.pageY + 5 });
|
||||
}
|
||||
else {
|
||||
$('#palette-floater').offset({ left: event.pageX + 5, top: event.pageY + 5 });
|
||||
this.trigger({
|
||||
type: Flo.DnDEventType.DRAG,
|
||||
view: this.viewBeingDragged,
|
||||
event: event
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
/*
|
||||
* Modify the rotation of the arrow in the header from horizontal(closed) to vertical(open)
|
||||
*/
|
||||
Palette.prototype.rotateOpen = function (element) {
|
||||
var _this = this;
|
||||
setTimeout(function () { return _this.doRotateOpen(element, 90); });
|
||||
};
|
||||
Palette.prototype.doRotateOpen = function (element, angle) {
|
||||
var _this = this;
|
||||
angle -= 10;
|
||||
element.attr({ 'path': { 'transform': 'rotate(-' + angle + ',15,13)' } });
|
||||
if (angle <= 0) {
|
||||
element.set('isOpen', true);
|
||||
this.closedGroups.delete(element.get('header'));
|
||||
this.rebuildPalette();
|
||||
}
|
||||
else {
|
||||
setTimeout(function () { return _this.doRotateOpen(element, angle); }, 10);
|
||||
}
|
||||
};
|
||||
Palette.prototype.doRotateClose = function (element, angle) {
|
||||
var _this = this;
|
||||
angle += 10;
|
||||
element.attr({ 'path': { 'transform': 'rotate(-' + angle + ',15,13)' } });
|
||||
if (angle >= 90) {
|
||||
element.set('isOpen', false);
|
||||
this.closedGroups.add(element.get('header'));
|
||||
this.rebuildPalette();
|
||||
}
|
||||
else {
|
||||
setTimeout(function () { return _this.doRotateClose(element, angle); }, 10);
|
||||
}
|
||||
};
|
||||
// TODO better name for this function as this does the animation *and* updates the palette
|
||||
/*
|
||||
* Modify the rotation of the arrow in the header from vertical(open) to horizontal(closed)
|
||||
*/
|
||||
Palette.prototype.rotateClosed = function (element) {
|
||||
var _this = this;
|
||||
setTimeout(function () { return _this.doRotateClose(element, 0); });
|
||||
};
|
||||
tslib_1.__decorate([
|
||||
Input(),
|
||||
tslib_1.__metadata("design:type", Object)
|
||||
], Palette.prototype, "metamodel", void 0);
|
||||
tslib_1.__decorate([
|
||||
Input(),
|
||||
tslib_1.__metadata("design:type", Object)
|
||||
], Palette.prototype, "renderer", void 0);
|
||||
tslib_1.__decorate([
|
||||
Input(),
|
||||
tslib_1.__metadata("design:type", Object)
|
||||
], Palette.prototype, "paletteEntryPadding", void 0);
|
||||
tslib_1.__decorate([
|
||||
Output(),
|
||||
tslib_1.__metadata("design:type", Object)
|
||||
], Palette.prototype, "onPaletteEntryDrop", void 0);
|
||||
tslib_1.__decorate([
|
||||
Output(),
|
||||
tslib_1.__metadata("design:type", Object)
|
||||
], Palette.prototype, "paletteReady", void 0);
|
||||
tslib_1.__decorate([
|
||||
Output(),
|
||||
tslib_1.__metadata("design:type", Object)
|
||||
], Palette.prototype, "paletteFocus", void 0);
|
||||
tslib_1.__decorate([
|
||||
Input(),
|
||||
tslib_1.__metadata("design:type", Number),
|
||||
tslib_1.__metadata("design:paramtypes", [Number])
|
||||
], Palette.prototype, "paletteSize", null);
|
||||
Palette = tslib_1.__decorate([
|
||||
Component({
|
||||
selector: 'flo-palette',
|
||||
template: "\n <div id=\"palette-filter\" class=\"palette-filter\">\n <input type=\"text\" id=\"palette-filter-textfield\" class=\"palette-filter-textfield\" [(ngModel)]=\"filterText\" (focus)=\"onFocus()\"/>\n </div>\n <div id=\"palette-paper-container\" style=\"height:calc(100% - 46px); width:100%;\">\n <div id=\"palette-paper\" class=\"palette-paper\" style=\"overflow:hidden;\"></div>\n </div>\n ",
|
||||
styles: ["\n /* Joint JS paper for drawing palette -> canvas DnD visual feedback START */\n\n #palette-floater {\n /* TODO size relative to paper that goes on it? */\n opacity: 0.75;\n width:170px;\n height:60px;\n background-color: transparent;\n /*\n background-color: #6db33f;\n */\n float:left;\n position: absolute;\n -webkit-user-select: none;\n -khtml-user-select: none;\n -moz-user-select: none;\n -o-user-select: none;\n user-select: none;\n }\n\n #palette-floater.joint-paper > svg {\n background-color: transparent;\n }\n\n #palette-paper-container {\n overflow-y: auto;\n overflow-x: hidden;\n background-color: white;\n color: white;\n }\n\n /* Joint JS paper for drawing palette -> canvas DnD visual feedback END */\n\n /* Palette START */\n\n .palette-filter {\n border: 3px solid #6db33f;\n }\n\n .palette-filter-textfield {\n width: 100%;\n font-size:24px;\n /* border: 3px solid #6db33f;\n */\tfont-family: \"Varela Round\",sans-serif;\n /* \tpadding: 2px; */\n }\n\n .palette-paper {\n background-color: #eeeeee;\n /*\n border-right: 7px solid;\n */\n border-color: #6db33f;\n /* \twidth: 170px;\n height:100%;\n float: left;\n */\n }\n\n /* Palette END */\n "],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
}),
|
||||
tslib_1.__param(1, Inject(DOCUMENT)),
|
||||
tslib_1.__metadata("design:paramtypes", [ElementRef, Object])
|
||||
], Palette);
|
||||
return Palette;
|
||||
}());
|
||||
export { Palette };
|
||||
//# sourceMappingURL=palette.component.js.map
|
||||
50
dist/esm5/properties/df.property.component.js
vendored
Normal file
50
dist/esm5/properties/df.property.component.js
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
import * as tslib_1 from "tslib";
|
||||
import { Component, Input, ViewEncapsulation } from '@angular/core';
|
||||
import { FormGroup } from '@angular/forms';
|
||||
import { Properties } from '../shared/flo-properties';
|
||||
var DynamicFormPropertyComponent = /** @class */ (function () {
|
||||
function DynamicFormPropertyComponent() {
|
||||
}
|
||||
Object.defineProperty(DynamicFormPropertyComponent.prototype, "types", {
|
||||
get: function () {
|
||||
return Properties.InputType;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(DynamicFormPropertyComponent.prototype, "control", {
|
||||
get: function () {
|
||||
return this.form.controls[this.model.id];
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(DynamicFormPropertyComponent.prototype, "errorData", {
|
||||
get: function () {
|
||||
var _this = this;
|
||||
return (this.model.validation && this.model.validation.errorData ? this.model.validation.errorData : [])
|
||||
.filter(function (e) { return _this.control.errors && _this.control.errors[e.id]; });
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
tslib_1.__decorate([
|
||||
Input(),
|
||||
tslib_1.__metadata("design:type", Object)
|
||||
], DynamicFormPropertyComponent.prototype, "model", void 0);
|
||||
tslib_1.__decorate([
|
||||
Input(),
|
||||
tslib_1.__metadata("design:type", FormGroup)
|
||||
], DynamicFormPropertyComponent.prototype, "form", void 0);
|
||||
DynamicFormPropertyComponent = tslib_1.__decorate([
|
||||
Component({
|
||||
selector: 'df-property',
|
||||
template: "\n <tr [formGroup]=\"form\" class=\"df-property-row\" [ngClass]=\"{'invalid-property-value': control.invalid}\">\n\n <td class=\"df-property-label-cell\">\n <label [attr.for]=\"model.id\" class=\"df-form-label\">{{model.name}}</label>\n </td>\n\n <td class=\"df-property-control-cell\">\n <div [ngSwitch]=\"model.type\" class=\"df-property-container\">\n\n <label *ngSwitchCase=\"types.CHECKBOX\" class=\"df-property-control\">\n <input type=\"checkbox\" [id]=\"model.id\" [(ngModel)]=\"model.value\" [formControlName]=\"model.id\">\n {{model.value ? 'True' : 'False' }}\n </label>\n\n <input *ngSwitchCase=\"types.NUMBER\" class=\"df-property-control\" type=\"number\" [id]=\"model.id\"\n [formControlName]=\"model.id\" [placeholder]=\"model.defaultValue || ''\" [(ngModel)]=\"model.value\">\n\n <input *ngSwitchCase=\"types.PASSWORD\" class=\"df-property-control\" type=\"password\" [id]=\"model.id\"\n [formControlName]=\"model.id\" [placeholder]=\"model.defaultValue || ''\" [(ngModel)]=\"model.value\">\n\n <input *ngSwitchCase=\"types.EMAIL\" class=\"df-property-control\" type=\"password\" [id]=\"model.id\"\n [formControlName]=\"model.id\" [placeholder]=\"model.defaultValue || ''\" [(ngModel)]=\"model.value\">\n\n <input *ngSwitchCase=\"types.URL\" class=\"df-property-control\" type=\"url\" [id]=\"model.id\"\n [formControlName]=\"model.id\" [placeholder]=\"model.defaultValue || ''\" [(ngModel)]=\"model.value\">\n\n <select *ngSwitchCase=\"types.SELECT\" class=\"df-property-control\" [id]=\"model.id\"\n [formControlName]=\"model.id\" [(ngModel)]=\"model.value\">\n <option *ngFor=\"let o of model['options']\" [ngValue]=\"o.value\">{{o.name}}</option>\n </select>\n\n <code-editor *ngSwitchCase=\"types.CODE\" class=\"df-property-control\" [id]=\"model.id\"\n [formControlName]=\"model.id\" [language]=\"model['language']\" [(ngModel)]=\"model.value\" line-numbers=\"true\"\n scrollbar-style=\"simple\" [placeholder]=\"model.defaultValue || 'Enter code snippet...'\" overview-ruler=\"true\">\n </code-editor>\n\n <input *ngSwitchDefault class=\"df-property-control\" type=\"text\" [id]=\"model.id\" [formControlName]=\"model.id\"\n [placeholder]=\"model.defaultValue || ''\" [(ngModel)]=\"model.value\">\n </div>\n <div class=\"help-block\">\n <div>{{model.description}}</div>\n <div *ngFor=\"let e of errorData\" class=\"validation-error-block\">{{e.message}}</div>\n </div>\n </td>\n\n </tr>\n ",
|
||||
encapsulation: ViewEncapsulation.None
|
||||
}),
|
||||
tslib_1.__metadata("design:paramtypes", [])
|
||||
], DynamicFormPropertyComponent);
|
||||
return DynamicFormPropertyComponent;
|
||||
}());
|
||||
export { DynamicFormPropertyComponent };
|
||||
//# sourceMappingURL=df.property.component.js.map
|
||||
51
dist/esm5/properties/properties.group.component.js
vendored
Normal file
51
dist/esm5/properties/properties.group.component.js
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
import * as tslib_1 from "tslib";
|
||||
import { Component, Input, ViewEncapsulation } from '@angular/core';
|
||||
import { FormGroup, FormControl } from '@angular/forms';
|
||||
import { Properties } from '../shared/flo-properties';
|
||||
var PropertiesGroupComponent = /** @class */ (function () {
|
||||
function PropertiesGroupComponent() {
|
||||
}
|
||||
PropertiesGroupComponent.prototype.ngOnInit = function () {
|
||||
var _this = this;
|
||||
if (this.propertiesGroupModel.isLoading) {
|
||||
var subscription_1 = this.propertiesGroupModel.loadedSubject.subscribe(function (loaded) {
|
||||
if (loaded) {
|
||||
subscription_1.unsubscribe();
|
||||
_this.createGroupControls();
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.createGroupControls();
|
||||
}
|
||||
};
|
||||
PropertiesGroupComponent.prototype.createGroupControls = function () {
|
||||
var _this = this;
|
||||
this.propertiesGroupModel.getControlsModels().forEach(function (c) {
|
||||
if (c.validation) {
|
||||
_this.form.addControl(c.id, new FormControl(c.value || '', c.validation.validator, c.validation.asyncValidator));
|
||||
}
|
||||
else {
|
||||
_this.form.addControl(c.id, new FormControl(c.value || ''));
|
||||
}
|
||||
});
|
||||
};
|
||||
tslib_1.__decorate([
|
||||
Input(),
|
||||
tslib_1.__metadata("design:type", Properties.PropertiesGroupModel)
|
||||
], PropertiesGroupComponent.prototype, "propertiesGroupModel", void 0);
|
||||
tslib_1.__decorate([
|
||||
Input(),
|
||||
tslib_1.__metadata("design:type", FormGroup)
|
||||
], PropertiesGroupComponent.prototype, "form", void 0);
|
||||
PropertiesGroupComponent = tslib_1.__decorate([
|
||||
Component({
|
||||
selector: 'properties-group',
|
||||
template: "\n <div *ngIf=\"propertiesGroupModel && !propertiesGroupModel.isLoading\" class=\"properties-group-container\" [formGroup]=\"form\">\n <df-property *ngFor=\"let model of propertiesGroupModel.getControlsModels()\" [model]=\"model\" [form]=\"form\" class=\"property-row\"></df-property>\n </div>\n ",
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
], PropertiesGroupComponent);
|
||||
return PropertiesGroupComponent;
|
||||
}());
|
||||
export { PropertiesGroupComponent };
|
||||
//# sourceMappingURL=properties.group.component.js.map
|
||||
57
dist/esm5/shared/flo-common.js
vendored
Normal file
57
dist/esm5/shared/flo-common.js
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
import * as _joint from 'jointjs';
|
||||
import * as _$ from 'jquery';
|
||||
var $ = _$;
|
||||
export var Flo;
|
||||
(function (Flo) {
|
||||
Flo.joint = _joint;
|
||||
var DnDEventType;
|
||||
(function (DnDEventType) {
|
||||
DnDEventType[DnDEventType["DRAG"] = 0] = "DRAG";
|
||||
DnDEventType[DnDEventType["DROP"] = 1] = "DROP";
|
||||
})(DnDEventType = Flo.DnDEventType || (Flo.DnDEventType = {}));
|
||||
var Severity;
|
||||
(function (Severity) {
|
||||
Severity[Severity["Error"] = 0] = "Error";
|
||||
Severity[Severity["Warning"] = 1] = "Warning";
|
||||
})(Severity = Flo.Severity || (Flo.Severity = {}));
|
||||
function findMagnetByClass(view, className) {
|
||||
if (className && className.startsWith('.')) {
|
||||
className = className.substr(1);
|
||||
}
|
||||
var element = view.$('[magnet]').toArray().find(function (magnet) { return magnet.getAttribute('class').split(/\s+/).indexOf(className) >= 0; });
|
||||
if (element) {
|
||||
return view.findMagnet($(element));
|
||||
}
|
||||
}
|
||||
Flo.findMagnetByClass = findMagnetByClass;
|
||||
function findMagnetByPort(view, port) {
|
||||
var element = view.$('[magnet]').toArray().find(function (magnet) { return magnet.getAttribute('port') === port; });
|
||||
if (element) {
|
||||
return view.findMagnet($(element));
|
||||
}
|
||||
}
|
||||
Flo.findMagnetByPort = findMagnetByPort;
|
||||
/**
|
||||
* Return the metadata for a particular palette entry in a particular group.
|
||||
* @param name - name of the palette entry
|
||||
* @param group - group in which the palette entry should exist (e.g. sinks)
|
||||
* @return
|
||||
*/
|
||||
function getMetadata(metamodel, name, group) {
|
||||
var groupObj = metamodel && group ? metamodel.get(group) : undefined;
|
||||
if (name && groupObj && groupObj.get(name)) {
|
||||
return metamodel.get(group).get(name);
|
||||
}
|
||||
else {
|
||||
return {
|
||||
name: name,
|
||||
group: group,
|
||||
unresolved: true,
|
||||
get: function (property) { return new Promise(function (resolve) { return resolve(); }); },
|
||||
properties: function () { return Promise.resolve(new Map()); }
|
||||
};
|
||||
}
|
||||
}
|
||||
Flo.getMetadata = getMetadata;
|
||||
})(Flo || (Flo = {}));
|
||||
//# sourceMappingURL=flo-common.js.map
|
||||
345
dist/esm5/shared/flo-properties.js
vendored
Normal file
345
dist/esm5/shared/flo-properties.js
vendored
Normal file
@@ -0,0 +1,345 @@
|
||||
import * as tslib_1 from "tslib";
|
||||
import { Subject, Observable } from 'rxjs';
|
||||
import { debounceTime, mergeMap } from 'rxjs/operators';
|
||||
export var Properties;
|
||||
(function (Properties) {
|
||||
var InputType;
|
||||
(function (InputType) {
|
||||
InputType[InputType["TEXT"] = 0] = "TEXT";
|
||||
InputType[InputType["NUMBER"] = 1] = "NUMBER";
|
||||
InputType[InputType["SELECT"] = 2] = "SELECT";
|
||||
InputType[InputType["CHECKBOX"] = 3] = "CHECKBOX";
|
||||
InputType[InputType["PASSWORD"] = 4] = "PASSWORD";
|
||||
InputType[InputType["EMAIL"] = 5] = "EMAIL";
|
||||
InputType[InputType["URL"] = 6] = "URL";
|
||||
InputType[InputType["CODE"] = 7] = "CODE";
|
||||
})(InputType = Properties.InputType || (Properties.InputType = {}));
|
||||
var GenericControlModel = /** @class */ (function () {
|
||||
function GenericControlModel(_property, type, validation) {
|
||||
this._property = _property;
|
||||
this.type = type;
|
||||
this.validation = validation;
|
||||
}
|
||||
Object.defineProperty(GenericControlModel.prototype, "id", {
|
||||
get: function () {
|
||||
return this.property.id;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(GenericControlModel.prototype, "name", {
|
||||
get: function () {
|
||||
return this.property.name;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(GenericControlModel.prototype, "description", {
|
||||
get: function () {
|
||||
return this.property.description;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(GenericControlModel.prototype, "defaultValue", {
|
||||
get: function () {
|
||||
return this.property.defaultValue;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(GenericControlModel.prototype, "value", {
|
||||
get: function () {
|
||||
return this.getValue();
|
||||
},
|
||||
set: function (value) {
|
||||
this.setValue(value);
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(GenericControlModel.prototype, "property", {
|
||||
get: function () {
|
||||
return this._property;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
GenericControlModel.prototype.setValue = function (value) {
|
||||
this.property.value = value;
|
||||
};
|
||||
GenericControlModel.prototype.getValue = function () {
|
||||
return this.property.value;
|
||||
};
|
||||
return GenericControlModel;
|
||||
}());
|
||||
Properties.GenericControlModel = GenericControlModel;
|
||||
var CheckBoxControlModel = /** @class */ (function (_super) {
|
||||
tslib_1.__extends(CheckBoxControlModel, _super);
|
||||
function CheckBoxControlModel(_property, validation) {
|
||||
return _super.call(this, _property, InputType.CHECKBOX, validation) || this;
|
||||
}
|
||||
CheckBoxControlModel.prototype.getValue = function () {
|
||||
var res = _super.prototype.getValue.call(this);
|
||||
var type = typeof res;
|
||||
switch (type) {
|
||||
case 'boolean':
|
||||
return res;
|
||||
case 'string':
|
||||
switch (res.trim().toLowerCase()) {
|
||||
case 'true':
|
||||
case '1':
|
||||
return true;
|
||||
case 'false':
|
||||
case '0':
|
||||
return false;
|
||||
default:
|
||||
return this.property.defaultValue;
|
||||
}
|
||||
case 'number':
|
||||
var num = res;
|
||||
if (num === 0) {
|
||||
return false;
|
||||
}
|
||||
else if (num === 1) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return this.property.defaultValue;
|
||||
}
|
||||
}
|
||||
return this.property.defaultValue;
|
||||
};
|
||||
return CheckBoxControlModel;
|
||||
}(GenericControlModel));
|
||||
Properties.CheckBoxControlModel = CheckBoxControlModel;
|
||||
var AbstractCodeControlModel = /** @class */ (function (_super) {
|
||||
tslib_1.__extends(AbstractCodeControlModel, _super);
|
||||
function AbstractCodeControlModel(_property, encode, decode, validation) {
|
||||
var _this = _super.call(this, _property, InputType.CODE, validation) || this;
|
||||
_this.encode = encode;
|
||||
_this.decode = decode;
|
||||
return _this;
|
||||
}
|
||||
Object.defineProperty(AbstractCodeControlModel.prototype, "value", {
|
||||
get: function () {
|
||||
var dsl = _super.prototype.getValue.call(this);
|
||||
if (dsl && this.decode) {
|
||||
return this.decode(dsl);
|
||||
}
|
||||
else {
|
||||
return dsl;
|
||||
}
|
||||
},
|
||||
set: function (value) {
|
||||
if (value && this.encode) {
|
||||
_super.prototype.setValue.call(this, this.encode(value));
|
||||
}
|
||||
else {
|
||||
_super.prototype.setValue.call(this, value);
|
||||
}
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
return AbstractCodeControlModel;
|
||||
}(GenericControlModel));
|
||||
Properties.AbstractCodeControlModel = AbstractCodeControlModel;
|
||||
var GenericCodeControlModel = /** @class */ (function (_super) {
|
||||
tslib_1.__extends(GenericCodeControlModel, _super);
|
||||
function GenericCodeControlModel(_property, language, encode, decode, validation) {
|
||||
var _this = _super.call(this, _property, encode, decode, validation) || this;
|
||||
_this.language = language;
|
||||
return _this;
|
||||
}
|
||||
return GenericCodeControlModel;
|
||||
}(AbstractCodeControlModel));
|
||||
Properties.GenericCodeControlModel = GenericCodeControlModel;
|
||||
var CodeControlModelWithDynamicLanguageProperty = /** @class */ (function (_super) {
|
||||
tslib_1.__extends(CodeControlModelWithDynamicLanguageProperty, _super);
|
||||
function CodeControlModelWithDynamicLanguageProperty(_property, _languagePropertyName, _groupModel, encode, decode, validation) {
|
||||
var _this = _super.call(this, _property, encode, decode, validation) || this;
|
||||
_this._languagePropertyName = _languagePropertyName;
|
||||
_this._groupModel = _groupModel;
|
||||
return _this;
|
||||
}
|
||||
Object.defineProperty(CodeControlModelWithDynamicLanguageProperty.prototype, "language", {
|
||||
get: function () {
|
||||
var value = this.languageControlModel.value;
|
||||
return value ? value : this.languageControlModel.defaultValue;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(CodeControlModelWithDynamicLanguageProperty.prototype, "languageControlModel", {
|
||||
get: function () {
|
||||
var _this = this;
|
||||
if (!this._langControlModel) {
|
||||
// Cast to Properties.ControlModel<any> from Properties.ControlModel<any> | undefined
|
||||
// Should not be undefined!
|
||||
this._langControlModel = this._groupModel.getControlsModels().find(function (c) { return c.id === _this._languagePropertyName; });
|
||||
}
|
||||
return this._langControlModel;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
return CodeControlModelWithDynamicLanguageProperty;
|
||||
}(AbstractCodeControlModel));
|
||||
Properties.CodeControlModelWithDynamicLanguageProperty = CodeControlModelWithDynamicLanguageProperty;
|
||||
var GenericListControlModel = /** @class */ (function (_super) {
|
||||
tslib_1.__extends(GenericListControlModel, _super);
|
||||
function GenericListControlModel(property, validation) {
|
||||
return _super.call(this, property, InputType.TEXT, validation) || this;
|
||||
}
|
||||
Object.defineProperty(GenericListControlModel.prototype, "value", {
|
||||
get: function () {
|
||||
return this.property.value ? this.property.value.join(', ') : '';
|
||||
},
|
||||
set: function (value) {
|
||||
this.property.value = value && value.trim() ? value.split(/\s*,\s*/) : undefined;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
return GenericListControlModel;
|
||||
}(GenericControlModel));
|
||||
Properties.GenericListControlModel = GenericListControlModel;
|
||||
var SelectControlModel = /** @class */ (function (_super) {
|
||||
tslib_1.__extends(SelectControlModel, _super);
|
||||
function SelectControlModel(_property, type, options) {
|
||||
var _this = _super.call(this, _property, type) || this;
|
||||
_this.options = options;
|
||||
if (_property.defaultValue === undefined) {
|
||||
options.unshift({
|
||||
name: 'SELECT',
|
||||
value: _property.defaultValue
|
||||
});
|
||||
}
|
||||
return _this;
|
||||
}
|
||||
return SelectControlModel;
|
||||
}(GenericControlModel));
|
||||
Properties.SelectControlModel = SelectControlModel;
|
||||
var DefaultCellPropertiesSource = /** @class */ (function () {
|
||||
function DefaultCellPropertiesSource(cell) {
|
||||
this.cell = cell;
|
||||
}
|
||||
DefaultCellPropertiesSource.prototype.getProperties = function () {
|
||||
var _this = this;
|
||||
var metadata = this.cell.attr('metadata');
|
||||
return Promise.resolve(metadata.properties().then(function (propsMetadata) { return Array.from(propsMetadata.values()).map(function (m) { return _this.createProperty(m); }); }));
|
||||
};
|
||||
DefaultCellPropertiesSource.prototype.createProperty = function (metadata) {
|
||||
return {
|
||||
id: metadata.id,
|
||||
name: metadata.name,
|
||||
type: metadata.type,
|
||||
defaultValue: metadata.defaultValue,
|
||||
attr: "props/" + metadata.name,
|
||||
value: this.cell.attr("props/" + metadata.name),
|
||||
description: metadata.description,
|
||||
valueOptions: metadata.options
|
||||
};
|
||||
};
|
||||
DefaultCellPropertiesSource.prototype.applyChanges = function (properties) {
|
||||
var _this = this;
|
||||
this.cell.trigger('batch:start', { batchName: 'update properties' });
|
||||
properties.forEach(function (property) {
|
||||
if ((typeof property.value === 'boolean' && !property.defaultValue && !property.value) ||
|
||||
(property.value === property.defaultValue || property.value === '' || property.value === undefined || property.value === null)) {
|
||||
var currentValue = _this.cell.attr(property.attr);
|
||||
if (currentValue !== undefined && currentValue !== null) {
|
||||
// Remove attr doesn't fire appropriate event. Set default value first as a workaround to schedule DSL resync
|
||||
_this.cell.attr(property.attr, property.defaultValue === undefined ? null : property.defaultValue);
|
||||
_this.cell.removeAttr(property.attr);
|
||||
}
|
||||
}
|
||||
else {
|
||||
_this.cell.attr(property.attr, property.value);
|
||||
}
|
||||
});
|
||||
this.cell.trigger('batch:stop', { batchName: 'update properties' });
|
||||
};
|
||||
return DefaultCellPropertiesSource;
|
||||
}());
|
||||
Properties.DefaultCellPropertiesSource = DefaultCellPropertiesSource;
|
||||
var PropertiesGroupModel = /** @class */ (function () {
|
||||
function PropertiesGroupModel(propertiesSource) {
|
||||
this.loading = true;
|
||||
this.propertiesSource = propertiesSource;
|
||||
}
|
||||
PropertiesGroupModel.prototype.load = function () {
|
||||
var _this = this;
|
||||
this.loading = true;
|
||||
this._loadedSubject = new Subject();
|
||||
this.propertiesSource.getProperties().then(function (properties) {
|
||||
_this.controlModels = properties.map(function (p) { return _this.createControlModel(p); });
|
||||
_this.loading = false;
|
||||
_this._loadedSubject.next(true);
|
||||
_this._loadedSubject.complete();
|
||||
});
|
||||
};
|
||||
Object.defineProperty(PropertiesGroupModel.prototype, "isLoading", {
|
||||
get: function () {
|
||||
return this.loading;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(PropertiesGroupModel.prototype, "loadedSubject", {
|
||||
get: function () {
|
||||
return this._loadedSubject;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
PropertiesGroupModel.prototype.getControlsModels = function () {
|
||||
return this.controlModels;
|
||||
};
|
||||
PropertiesGroupModel.prototype.createControlModel = function (property) {
|
||||
return new GenericControlModel(property, InputType.TEXT);
|
||||
};
|
||||
PropertiesGroupModel.prototype.applyChanges = function () {
|
||||
if (this.loading) {
|
||||
return;
|
||||
}
|
||||
var properties = this.controlModels.map(function (cm) { return cm.property; });
|
||||
this.propertiesSource.applyChanges(properties);
|
||||
};
|
||||
return PropertiesGroupModel;
|
||||
}());
|
||||
Properties.PropertiesGroupModel = PropertiesGroupModel;
|
||||
var Validators;
|
||||
(function (Validators) {
|
||||
function uniqueResource(service, debounce) {
|
||||
return function (control) {
|
||||
return new Observable(function (obs) {
|
||||
if (control.valueChanges && control.value) {
|
||||
control.valueChanges
|
||||
.pipe(debounceTime(debounce), mergeMap(function (value) { return service(value); }))
|
||||
.subscribe(function () {
|
||||
obs.next({ uniqueResource: true });
|
||||
obs.complete();
|
||||
}, function () {
|
||||
obs.next(undefined);
|
||||
obs.complete();
|
||||
});
|
||||
}
|
||||
else {
|
||||
obs.next(undefined);
|
||||
obs.complete();
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
Validators.uniqueResource = uniqueResource;
|
||||
function noneOf(excluded) {
|
||||
return function (control) {
|
||||
return excluded.find(function (e) { return e === control.value; }) ? { 'noneOf': { value: control.value } } : {};
|
||||
};
|
||||
}
|
||||
Validators.noneOf = noneOf;
|
||||
})(Validators = Properties.Validators || (Properties.Validators = {}));
|
||||
})(Properties || (Properties = {}));
|
||||
//# sourceMappingURL=flo-properties.js.map
|
||||
497
dist/esm5/shared/shapes.js
vendored
Normal file
497
dist/esm5/shared/shapes.js
vendored
Normal file
@@ -0,0 +1,497 @@
|
||||
import { Flo } from './flo-common';
|
||||
import * as _ from 'lodash';
|
||||
import * as _$ from 'jquery';
|
||||
var joint = Flo.joint;
|
||||
var $ = _$;
|
||||
var isChrome = /Chrome/.test(navigator.userAgent) && /Google Inc/.test(navigator.vendor);
|
||||
var isFF = navigator.userAgent.indexOf('Firefox') > 0;
|
||||
var IMAGE_W = 120;
|
||||
var IMAGE_H = 35;
|
||||
var ERROR_MARKER_SIZE = { width: 16, height: 16 };
|
||||
var HANDLE_SIZE = { width: 10, height: 10 };
|
||||
joint.shapes.flo = {};
|
||||
joint.shapes.flo.NODE_TYPE = 'sinspctr.IntNode';
|
||||
joint.shapes.flo.LINK_TYPE = 'sinspctr.Link';
|
||||
joint.shapes.flo.DECORATION_TYPE = 'decoration';
|
||||
joint.shapes.flo.HANDLE_TYPE = 'handle';
|
||||
var HANDLE_ICON_MAP = new Map();
|
||||
var REMOVE = 'remove';
|
||||
HANDLE_ICON_MAP.set(REMOVE, 'icons/delete.svg');
|
||||
var DECORATION_ICON_MAP = new Map();
|
||||
var ERROR = 'error';
|
||||
DECORATION_ICON_MAP.set(ERROR, 'icons/error.svg');
|
||||
joint.util.cloneDeep = function (obj) {
|
||||
return _.cloneDeepWith(obj, function (o) {
|
||||
if (_.isObject(o) && !_.isPlainObject(o)) {
|
||||
return o;
|
||||
}
|
||||
});
|
||||
};
|
||||
joint.util.filter.redscale = function (args) {
|
||||
var amount = Number.isFinite(args.amount) ? args.amount : 1;
|
||||
return _.template('<filter><feColorMatrix type="matrix" values="${a} ${b} ${c} 0 ${d} ${e} ${f} ${g} 0 0 ${h} ${i} ${k} 0 0 0 0 0 1 0"/></filter>', {
|
||||
a: 1 - 0.96 * amount,
|
||||
b: 0.95 * amount,
|
||||
c: 0.01 * amount,
|
||||
d: 0.3 * amount,
|
||||
e: 0.2 * amount,
|
||||
f: 1 - 0.9 * amount,
|
||||
g: 0.7 * amount,
|
||||
h: 0.05 * amount,
|
||||
i: 0.05 * amount,
|
||||
k: 1 - 0.1 * amount
|
||||
});
|
||||
};
|
||||
joint.util.filter.orangescale = function (args) {
|
||||
var amount = Number.isFinite(args.amount) ? args.amount : 1;
|
||||
return _.template('<filter><feColorMatrix type="matrix" values="${a} ${b} ${c} 0 ${d} ${e} ${f} ${g} 0 ${h} ${i} ${k} ${l} 0 0 0 0 0 1 0"/></filter>', {
|
||||
a: 1.0 + 0.5 * amount,
|
||||
b: 1.4 * amount,
|
||||
c: 0.2 * amount,
|
||||
d: 0.3 * amount,
|
||||
e: 0.3 * amount,
|
||||
f: 1 + 0.05 * amount,
|
||||
g: 0.2 * amount,
|
||||
h: 0.15 * amount,
|
||||
i: 0.3 * amount,
|
||||
k: 0.3 * amount,
|
||||
l: 1 - 0.6 * amount
|
||||
});
|
||||
};
|
||||
joint.shapes.flo.Node = joint.shapes.basic.Generic.extend({
|
||||
markup: '<g class="shape"><image class="image" /></g>' +
|
||||
'<rect class="border-white"/>' +
|
||||
'<rect class="border"/>' +
|
||||
'<rect class="box"/>' +
|
||||
'<text class="label"/>' +
|
||||
'<text class="label2"></text>' +
|
||||
'<rect class="input-port" />' +
|
||||
'<rect class="output-port"/>' +
|
||||
'<rect class="output-port-cover"/>',
|
||||
defaults: joint.util.deepSupplement({
|
||||
type: joint.shapes.flo.NODE_TYPE,
|
||||
position: { x: 0, y: 0 },
|
||||
size: { width: IMAGE_W, height: IMAGE_H },
|
||||
attrs: {
|
||||
'.': { magnet: false },
|
||||
// rounded edges around image
|
||||
'.border': {
|
||||
width: IMAGE_W,
|
||||
height: IMAGE_H,
|
||||
rx: 3,
|
||||
ry: 3,
|
||||
'fill-opacity': 0,
|
||||
stroke: '#eeeeee',
|
||||
'stroke-width': 0
|
||||
},
|
||||
'.box': {
|
||||
width: IMAGE_W,
|
||||
height: IMAGE_H,
|
||||
rx: 3,
|
||||
ry: 3,
|
||||
//'fill-opacity': 0, // see through
|
||||
stroke: '#6db33f',
|
||||
fill: '#eeeeee',
|
||||
'stroke-width': 1
|
||||
},
|
||||
'.input-port': {
|
||||
port: 'input',
|
||||
height: 8, width: 8,
|
||||
magnet: true,
|
||||
fill: '#eeeeee',
|
||||
transform: 'translate(' + -4 + ',' + ((IMAGE_H / 2) - 4) + ')',
|
||||
stroke: '#34302d',
|
||||
'stroke-width': 1
|
||||
},
|
||||
'.output-port': {
|
||||
port: 'output',
|
||||
height: 8, width: 8,
|
||||
magnet: true,
|
||||
fill: '#eeeeee',
|
||||
transform: 'translate(' + (IMAGE_W - 4) + ',' + ((IMAGE_H / 2) - 4) + ')',
|
||||
stroke: '#34302d',
|
||||
'stroke-width': 1
|
||||
},
|
||||
'.label': {
|
||||
'text-anchor': 'middle',
|
||||
'ref-x': 0.5,
|
||||
// 'ref-y': -12, // jointjs specific: relative position to ref'd element
|
||||
'ref-y': 0.3,
|
||||
ref: '.border',
|
||||
fill: 'black',
|
||||
'font-size': 14
|
||||
},
|
||||
'.label2': {
|
||||
'text': '\u21d2',
|
||||
'text-anchor': 'middle',
|
||||
'ref-x': 0.15,
|
||||
'ref-y': 0.2,
|
||||
ref: '.border',
|
||||
// transform: 'translate(' + (IMAGE_W/2) + ',' + (IMAGE_H/2) + ')',
|
||||
fill: 'black',
|
||||
'font-size': 24
|
||||
},
|
||||
'.shape': {},
|
||||
'.image': {
|
||||
width: IMAGE_W,
|
||||
height: IMAGE_H
|
||||
}
|
||||
}
|
||||
}, joint.shapes.basic.Generic.prototype.defaults)
|
||||
});
|
||||
joint.shapes.flo.Link = joint.dia.Link.extend({
|
||||
defaults: joint.util.deepSupplement({
|
||||
type: joint.shapes.flo.LINK_TYPE,
|
||||
attrs: {
|
||||
'.connection': { stroke: '#34302d', 'stroke-width': 2 },
|
||||
// Lots of alternatives that have been played with:
|
||||
// '.smoooth': true
|
||||
// '.marker-source': { stroke: '#9B59B6', fill: '#9B59B6', d: 'M24.316,5.318,9.833,13.682,9.833,5.5,5.5,5.5,5.5,25.5,9.833,25.5,9.833,17.318,24.316,25.682z' },
|
||||
// '.marker-target': { stroke: '#F39C12', fill: '#F39C12', d: 'M14.615,4.928c0.487-0.986,1.284-0.986,1.771,0l2.249,4.554c0.486,0.986,1.775,1.923,2.864,2.081l5.024,0.73c1.089,0.158,1.335,0.916,0.547,1.684l-3.636,3.544c-0.788,0.769-1.28,2.283-1.095,3.368l0.859,5.004c0.186,1.085-0.459,1.553-1.433,1.041l-4.495-2.363c-0.974-0.512-2.567-0.512-3.541,0l-4.495,2.363c-0.974,0.512-1.618,0.044-1.432-1.041l0.858-5.004c0.186-1.085-0.307-2.6-1.094-3.368L3.93,13.977c-0.788-0.768-0.542-1.525,0.547-1.684l5.026-0.73c1.088-0.158,2.377-1.095,2.864-2.081L14.615,4.928z' },
|
||||
// '.connection': { 'stroke':'black'},
|
||||
// '.': { filter: { name: 'dropShadow', args: { dx: 1, dy: 1, blur: 2 } } },
|
||||
// '.connection': { 'stroke-width': 10, 'stroke-linecap': 'round' },
|
||||
// This means: moveto 10 0, lineto 0 5, lineto, 10 10 closepath(z)
|
||||
// '.marker-target': { d: 'M 5 0 L 0 7 L 5 14 z', stroke: '#34302d','stroke-width': 1},
|
||||
// '.marker-target': { d: 'M 14 2 L 9,2 L9,0 L 0,7 L 9,14 L 9,12 L 14,12 z', 'stroke-width': 1, fill: '#34302d', stroke: '#34302d'},
|
||||
// '.marker-source': {d: 'M 5 0 L 5,10 L 0,10 L 0,0 z', 'stroke-width': 0, fill: '#34302d', stroke: '#34302d'},
|
||||
// '.marker-target': { stroke: '#E74C3C', fill: '#E74C3C', d: 'M 10 0 L 0 5 L 10 10 z' },
|
||||
'.marker-arrowheads': { display: 'none' },
|
||||
'.tool-options': { display: 'none' }
|
||||
},
|
||||
}, joint.dia.Link.prototype.defaults)
|
||||
});
|
||||
joint.shapes.flo.LinkView = joint.dia.LinkView.extend({
|
||||
options: joint.util.deepSupplement({}, joint.dia.LinkView.prototype.options),
|
||||
_beforeArrowheadMove: function () {
|
||||
if (this.model.get('source').id) {
|
||||
this._oldSource = this.model.get('source');
|
||||
}
|
||||
if (this.model.get('target').id) {
|
||||
this._oldTarget = this.model.get('target');
|
||||
}
|
||||
joint.dia.LinkView.prototype._beforeArrowheadMove.apply(this, arguments);
|
||||
},
|
||||
_afterArrowheadMove: function () {
|
||||
joint.dia.LinkView.prototype._afterArrowheadMove.apply(this, arguments);
|
||||
if (!this.model.get('source').id) {
|
||||
if (this._oldSource) {
|
||||
this.model.set('source', this._oldSource);
|
||||
}
|
||||
else {
|
||||
this.model.remove();
|
||||
}
|
||||
}
|
||||
if (!this.model.get('target').id) {
|
||||
if (this._oldTarget) {
|
||||
this.model.set('target', this._oldTarget);
|
||||
}
|
||||
else {
|
||||
this.model.remove();
|
||||
}
|
||||
}
|
||||
delete this._oldSource;
|
||||
delete this._oldTarget;
|
||||
}
|
||||
});
|
||||
// TODO: must do cleanup for the `mainElementView'
|
||||
joint.shapes.flo.ElementView = joint.dia.ElementView.extend({
|
||||
// canShowTooltip: true,
|
||||
beingDragged: false,
|
||||
// _tempZorder: 0,
|
||||
_tempOpacity: 1.0,
|
||||
_hovering: false,
|
||||
dragLinkStart: function (evt, magnet, x, y) {
|
||||
this.model.startBatch('add-link');
|
||||
var linkView = this.addLinkFromMagnet(magnet, x, y);
|
||||
// backwards compatiblity events
|
||||
joint.dia.CellView.prototype.pointerdown.apply(linkView, [evt, x, y]);
|
||||
linkView.notify('link:pointerdown', evt, x, y);
|
||||
/*** START MAIN DIFF ***/
|
||||
var sourceOrTarget = $(magnet).attr('port') === 'input' ? 'source' : 'target';
|
||||
linkView.eventData(evt, linkView.startArrowheadMove(sourceOrTarget, { whenNotAllowed: 'remove' }));
|
||||
/*** END MAIN DIFF ***/
|
||||
this.eventData(evt, { linkView: linkView });
|
||||
},
|
||||
addLinkFromMagnet: function (magnet, x, y) {
|
||||
var paper = this.paper;
|
||||
var graph = paper.model;
|
||||
var link = paper.getDefaultLink(this, magnet);
|
||||
var sourceEnd, targetEnd;
|
||||
/*** START MAIN DIFF ***/
|
||||
if ($(magnet).attr('port') === 'input') {
|
||||
sourceEnd = { x: x, y: y };
|
||||
targetEnd = this.getLinkEnd(magnet, x, y, link, 'target');
|
||||
}
|
||||
else {
|
||||
sourceEnd = this.getLinkEnd(magnet, x, y, link, 'source');
|
||||
targetEnd = { x: x, y: y };
|
||||
}
|
||||
/*** END MAIN DIFF ***/
|
||||
link.set({
|
||||
source: sourceEnd,
|
||||
target: targetEnd
|
||||
}).addTo(graph, {
|
||||
async: false,
|
||||
ui: true
|
||||
});
|
||||
return link.findView(paper);
|
||||
},
|
||||
// pointerdown: function(evt: any, x: number, y: number) {
|
||||
// // this.canShowTooltip = false;
|
||||
// // this.hideTooltip();
|
||||
// this.beingDragged = false;
|
||||
// this._tempOpacity = this.model.attr('./opacity');
|
||||
//
|
||||
// this.model.trigger('batch:start');
|
||||
//
|
||||
// if ( // target is a valid magnet start linking
|
||||
// evt.target.getAttribute('magnet') &&
|
||||
// this.paper.options.validateMagnet.call(this.paper, this, evt.target)
|
||||
// ) {
|
||||
// let link = this.paper.getDefaultLink(this, evt.target);
|
||||
// if ($(evt.target).attr('port') === 'input') {
|
||||
// link.set({
|
||||
// source: { x: x, y: y },
|
||||
// target: {
|
||||
// id: this.model.id,
|
||||
// selector: this.getSelector(evt.target),
|
||||
// port: evt.target.getAttribute('port')
|
||||
// }
|
||||
// });
|
||||
// } else {
|
||||
// link.set({
|
||||
// source: {
|
||||
// id: this.model.id,
|
||||
// selector: this.getSelector(evt.target),
|
||||
// port: evt.target.getAttribute('port')
|
||||
// },
|
||||
// target: { x: x, y: y }
|
||||
// });
|
||||
// }
|
||||
// this.paper.model.addCell(link);
|
||||
// this._linkView = this.paper.findViewByModel(link);
|
||||
// if ($(evt.target).attr('port') === 'input') {
|
||||
// this._linkView.startArrowheadMove('source');
|
||||
// } else {
|
||||
// this._linkView.startArrowheadMove('target');
|
||||
// }
|
||||
// this.paper.__creatingLinkFromPort = true;
|
||||
// } else {
|
||||
// this._dx = x;
|
||||
// this._dy = y;
|
||||
// joint.dia.CellView.prototype.pointerdown.apply(this, arguments);
|
||||
// }
|
||||
// },
|
||||
drag: function (evt, x, y) {
|
||||
var interactive = _.isFunction(this.options.interactive) ? this.options.interactive(this, 'pointermove') :
|
||||
this.options.interactive;
|
||||
if (interactive !== false) {
|
||||
this.paper.trigger('dragging-node-over-canvas', { type: Flo.DnDEventType.DRAG, view: this, event: evt });
|
||||
}
|
||||
joint.dia.ElementView.prototype.drag.apply(this, arguments);
|
||||
},
|
||||
dragEnd: function (evt, x, y) {
|
||||
this.paper.trigger('dragging-node-over-canvas', { type: Flo.DnDEventType.DROP, view: this, event: evt });
|
||||
joint.dia.ElementView.prototype.dragEnd.apply(this, arguments);
|
||||
},
|
||||
});
|
||||
joint.shapes.flo.ErrorDecoration = joint.shapes.basic.Generic.extend({
|
||||
markup: '<g class="rotatable"><g class="scalable"><image/></g></g>',
|
||||
defaults: joint.util.deepSupplement({
|
||||
type: joint.shapes.flo.DECORATION_TYPE,
|
||||
size: ERROR_MARKER_SIZE,
|
||||
attrs: {
|
||||
'image': ERROR_MARKER_SIZE
|
||||
}
|
||||
}, joint.shapes.basic.Generic.prototype.defaults)
|
||||
});
|
||||
export var Constants;
|
||||
(function (Constants) {
|
||||
Constants.REMOVE_HANDLE_TYPE = REMOVE;
|
||||
Constants.PROPERTIES_HANDLE_TYPE = 'properties';
|
||||
Constants.ERROR_DECORATION_KIND = ERROR;
|
||||
Constants.PALETTE_CONTEXT = 'palette';
|
||||
Constants.CANVAS_CONTEXT = 'canvas';
|
||||
Constants.FEEDBACK_CONTEXT = 'feedback';
|
||||
})(Constants || (Constants = {}));
|
||||
export var Shapes;
|
||||
(function (Shapes) {
|
||||
var Factory = /** @class */ (function () {
|
||||
function Factory() {
|
||||
}
|
||||
/**
|
||||
* Create a JointJS node that embeds extra metadata (properties).
|
||||
*/
|
||||
Factory.createNode = function (params) {
|
||||
var renderer = params.renderer;
|
||||
var paper = params.paper;
|
||||
var metadata = params.metadata;
|
||||
var position = params.position;
|
||||
var props = params.props;
|
||||
var graph = params.graph || (params.paper ? params.paper.model : undefined);
|
||||
var node;
|
||||
if (!position) {
|
||||
position = { x: 0, y: 0 };
|
||||
}
|
||||
if (renderer && _.isFunction(renderer.createNode)) {
|
||||
node = renderer.createNode(metadata, props);
|
||||
}
|
||||
else {
|
||||
node = new joint.shapes.flo.Node();
|
||||
if (metadata) {
|
||||
node.attr('.label/text', metadata.name);
|
||||
}
|
||||
}
|
||||
node.set('type', joint.shapes.flo.NODE_TYPE);
|
||||
if (position) {
|
||||
node.set('position', position);
|
||||
}
|
||||
if (props) {
|
||||
Array.from(props.keys()).forEach(function (key) { return node.attr("props/" + key, props.get(key)); });
|
||||
}
|
||||
node.attr('metadata', metadata);
|
||||
if (graph) {
|
||||
graph.addCell(node);
|
||||
}
|
||||
if (renderer && _.isFunction(renderer.initializeNewNode)) {
|
||||
var descriptor = {
|
||||
paper: paper,
|
||||
graph: graph
|
||||
};
|
||||
renderer.initializeNewNode(node, descriptor);
|
||||
}
|
||||
return node;
|
||||
};
|
||||
Factory.createLink = function (params) {
|
||||
var renderer = params.renderer;
|
||||
var paper = params.paper;
|
||||
var metadata = params.metadata;
|
||||
var source = params.source;
|
||||
var target = params.target;
|
||||
var props = params.props;
|
||||
var graph = params.graph || (params.paper ? params.paper.model : undefined);
|
||||
var link;
|
||||
if (renderer && _.isFunction(renderer.createLink)) {
|
||||
link = renderer.createLink(source, target, metadata, props);
|
||||
}
|
||||
else {
|
||||
link = new joint.shapes.flo.Link();
|
||||
}
|
||||
if (source) {
|
||||
link.set('source', source);
|
||||
}
|
||||
if (target) {
|
||||
link.set('target', target);
|
||||
}
|
||||
link.set('type', joint.shapes.flo.LINK_TYPE);
|
||||
if (metadata) {
|
||||
link.attr('metadata', metadata);
|
||||
}
|
||||
if (props) {
|
||||
Array.from(props.keys()).forEach(function (key) { return link.attr("props/" + key, props.get(key)); });
|
||||
}
|
||||
if (graph) {
|
||||
graph.addCell(link);
|
||||
}
|
||||
if (renderer && _.isFunction(renderer.initializeNewLink)) {
|
||||
var descriptor = {
|
||||
paper: paper,
|
||||
graph: graph
|
||||
};
|
||||
renderer.initializeNewLink(link, descriptor);
|
||||
}
|
||||
// prevent creation of link breaks
|
||||
link.attr('.marker-vertices/display', 'none');
|
||||
return link;
|
||||
};
|
||||
Factory.createDecoration = function (params) {
|
||||
var renderer = params.renderer;
|
||||
var paper = params.paper;
|
||||
var parent = params.parent;
|
||||
var kind = params.kind;
|
||||
var messages = params.messages;
|
||||
var location = params.position;
|
||||
var graph = params.graph || (params.paper ? params.paper.model : undefined);
|
||||
if (!location) {
|
||||
location = { x: 0, y: 0 };
|
||||
}
|
||||
var decoration;
|
||||
if (renderer && _.isFunction(renderer.createDecoration)) {
|
||||
decoration = renderer.createDecoration(kind, parent);
|
||||
}
|
||||
else {
|
||||
decoration = new joint.shapes.flo.ErrorDecoration({
|
||||
attrs: {
|
||||
image: { 'xlink:href': DECORATION_ICON_MAP.get(kind) },
|
||||
}
|
||||
});
|
||||
}
|
||||
decoration.set('type', joint.shapes.flo.DECORATION_TYPE);
|
||||
decoration.set('position', location);
|
||||
if ((isChrome || isFF) && parent && typeof parent.get('z') === 'number') {
|
||||
decoration.set('z', parent.get('z') + 1);
|
||||
}
|
||||
decoration.attr('./kind', kind);
|
||||
decoration.attr('messages', messages);
|
||||
if (graph) {
|
||||
graph.addCell(decoration);
|
||||
}
|
||||
parent.embed(decoration);
|
||||
if (renderer && _.isFunction(renderer.initializeNewDecoration)) {
|
||||
var descriptor = {
|
||||
paper: paper,
|
||||
graph: graph
|
||||
};
|
||||
renderer.initializeNewDecoration(decoration, descriptor);
|
||||
}
|
||||
return decoration;
|
||||
};
|
||||
Factory.createHandle = function (params) {
|
||||
var renderer = params.renderer;
|
||||
var paper = params.paper;
|
||||
var parent = params.parent;
|
||||
var kind = params.kind;
|
||||
var location = params.position;
|
||||
var graph = params.graph || (params.paper ? params.paper.model : undefined);
|
||||
var handle;
|
||||
if (!location) {
|
||||
location = { x: 0, y: 0 };
|
||||
}
|
||||
if (renderer && _.isFunction(renderer.createHandle)) {
|
||||
handle = renderer.createHandle(kind, parent);
|
||||
}
|
||||
else {
|
||||
handle = new joint.shapes.flo.ErrorDecoration({
|
||||
size: HANDLE_SIZE,
|
||||
attrs: {
|
||||
'image': {
|
||||
'xlink:href': HANDLE_ICON_MAP.get(kind)
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
handle.set('type', joint.shapes.flo.HANDLE_TYPE);
|
||||
handle.set('position', location);
|
||||
if ((isChrome || isFF) && parent && typeof parent.get('z') === 'number') {
|
||||
handle.set('z', parent.get('z') + 1);
|
||||
}
|
||||
handle.attr('./kind', kind);
|
||||
if (graph) {
|
||||
graph.addCell(handle);
|
||||
}
|
||||
parent.embed(handle);
|
||||
if (renderer && _.isFunction(renderer.initializeNewHandle)) {
|
||||
var descriptor = {
|
||||
paper: paper,
|
||||
graph: graph
|
||||
};
|
||||
renderer.initializeNewHandle(handle, descriptor);
|
||||
}
|
||||
return handle;
|
||||
};
|
||||
return Factory;
|
||||
}());
|
||||
Shapes.Factory = Factory;
|
||||
})(Shapes || (Shapes = {}));
|
||||
//# sourceMappingURL=shapes.js.map
|
||||
5
dist/esm5/spring-flo.js
vendored
Normal file
5
dist/esm5/spring-flo.js
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* Generated bundle index. Do not edit.
|
||||
*/
|
||||
export * from './index';
|
||||
//# sourceMappingURL=spring-flo.js.map
|
||||
3902
dist/fesm2015/spring-flo.js
vendored
Normal file
3902
dist/fesm2015/spring-flo.js
vendored
Normal file
File diff suppressed because one or more lines are too long
3326
dist/fesm5/spring-flo.js
vendored
Normal file
3326
dist/fesm5/spring-flo.js
vendored
Normal file
File diff suppressed because one or more lines are too long
109
dist/package.json
vendored
Normal file
109
dist/package.json
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
{
|
||||
"name": "spring-flo",
|
||||
"version": "0.8.9",
|
||||
"description": "Library for quickly building text DSL visualization diagram editor",
|
||||
"main": "./bundles/spring-flo.umd.js",
|
||||
"module": "./fesm5/spring-flo.js",
|
||||
"es2015": "./fesm2015/spring-flo.js",
|
||||
"esm5": "./esm5/spring-flo.js",
|
||||
"esm2015": "./esm2015/spring-flo.js",
|
||||
"fesm5": "./fesm5/spring-flo.js",
|
||||
"fesm2015": "./fesm2015/spring-flo.js",
|
||||
"typings": "./out-tsc/spring-flo.d.ts",
|
||||
"author": "",
|
||||
"license": "Apache-2.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/spring-projects/spring-flo.git"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6.9.0",
|
||||
"npm": ">= 3.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"clean": "rimraf out-tsc dist/*",
|
||||
"prebuild": "npm run clean",
|
||||
"build": "node build.js",
|
||||
"build-demo": "tsc -p src/demo/",
|
||||
"build-demo:watch": "tsc -p src/demo/ -w",
|
||||
"serve": "lite-server -c=bs-config.json",
|
||||
"prestart": "npm run build-demo",
|
||||
"start": "concurrently \"npm run build-demo:watch\" \"npm run serve\"",
|
||||
"build-test": "tsc -p src/lib/tsconfig.spec.json",
|
||||
"build-test:watch": "tsc -p src/lib/tsconfig.spec.json -w",
|
||||
"pretest": "npm run build-test",
|
||||
"test": "concurrently \"npm run build-test:watch\" \"karma start karma.conf.js\"",
|
||||
"pretest:once": "npm run build-test",
|
||||
"test:once": "karma start karma.conf.js --single-run",
|
||||
"preintegration": "npm run build && cd integration && npm run clean && npm install",
|
||||
"integration": "npm run integration:aot && npm run integration:jit",
|
||||
"integration:jit": "cd integration && npm run e2e",
|
||||
"integration:aot": "cd integration && npm run e2e:aot",
|
||||
"lint": "tslint ./src/**/*.ts -t verbose",
|
||||
"release": "standard-version"
|
||||
},
|
||||
"dependencies": {
|
||||
"codemirror-minified": "5.44.0",
|
||||
"jointjs": "2.2.1",
|
||||
"ts-disposables": "2.2.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular/core": ">=6.0.0 <8.0.0",
|
||||
"@angular/forms": ">=6.0.0 < 8.0.0",
|
||||
"@angular/platform-browser": ">=6.0.0 <8.0.0",
|
||||
"rxjs": ">=6.0.0 <7.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular/animations": "7.2.10",
|
||||
"@angular/common": "7.2.10",
|
||||
"@angular/compiler": "7.2.10",
|
||||
"@angular/compiler-cli": "7.2.10",
|
||||
"@angular/core": "7.2.10",
|
||||
"@angular/forms": "7.2.10",
|
||||
"@angular/platform-browser": "7.2.10",
|
||||
"@angular/platform-browser-dynamic": "7.2.10",
|
||||
"@angular/platform-server": "7.2.10",
|
||||
"@types/backbone": "1.3.42",
|
||||
"@types/codemirror": "0.0.64",
|
||||
"@types/jasmine": "2.5.36",
|
||||
"@types/jquery": "3.3.4",
|
||||
"@types/lodash": "4.14.123",
|
||||
"@types/node": "6.0.46",
|
||||
"camelcase": "4.0.0",
|
||||
"chalk": "2.4.1",
|
||||
"codemirror-minified": "5.44.0",
|
||||
"concurrently": "4.0.1",
|
||||
"core-js": "2.6.5",
|
||||
"glob": "7.1.1",
|
||||
"gulp": "3.9.1",
|
||||
"gulp-inline-ng2-template": "5.0.1",
|
||||
"jasmine-core": "2.5.2",
|
||||
"jointjs": "2.2.1",
|
||||
"jquery": "3.1.1",
|
||||
"jshint": "2.10.2",
|
||||
"karma": "1.5.0",
|
||||
"karma-chrome-launcher": "2.0.0",
|
||||
"karma-cli": "1.0.1",
|
||||
"karma-html-reporter": "0.2.7",
|
||||
"karma-jasmine": "1.1.0",
|
||||
"karma-jasmine-html-reporter": "0.2.2",
|
||||
"lite-server": "2.4.0",
|
||||
"ngx-bootstrap": "2.0.5",
|
||||
"node-sass": "4.9.0",
|
||||
"rimraf": "2.6.1",
|
||||
"rollup": "0.62.0",
|
||||
"rollup-plugin-commonjs": "9.1.3",
|
||||
"rollup-plugin-node-resolve": "3.3.0",
|
||||
"rollup-plugin-sourcemaps": "0.4.2",
|
||||
"rxjs": "6.3.3",
|
||||
"shelljs": "0.8.1",
|
||||
"standard-version": "4.0.0",
|
||||
"systemjs": "0.21.4",
|
||||
"ts-disposables": "2.2.3",
|
||||
"tslint": "5.12.1",
|
||||
"typescript": "3.1.4",
|
||||
"uglify-js": "3.3.23",
|
||||
"zone.js": "0.8.29",
|
||||
"rxjs-compat": "^6.4.0"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user