preface
LogicFlow has received more attention than we expected since it became open source. When we first set out to do LogicFlow, we spent a lot of time talking about what kind of process visualization library to make. One option is to implement a library directly out of the box, based on existing businesses, that includes all of the usual functionality of the process editing library. But in the end, we did not choose to do so because of the background: different projects, in the appearance of the flow chart, the data format required in the background are quite different. Some projects use Activities, and some teams develop their own process engines. Therefore, we need to make a process visualization library that can support the smooth migration of each system, which needs to be flexible enough and meet the style of each system visually, and it is best that all the functions on the flow chart can be used as required.
Extension mechanism based on plug-in
Configuration or plug-in?
We have two ideas about how to implement LogicFlow as a flexible enough flow visualization inventory. One is configurability, which is configurability. This is the practice of many visualization libraries, the most typical of which is ECharts. As anyone who has used ECharts knows, it has rich configuration functions. It can configure almost any element on the graph to achieve the customized effect required by business developers.
But for us, configuration turned out to provide enough flexibility to keep it, and we needed to maintain too much UI-related logic internally. Take a node as an example:
In the case of configuration, the configuration passed in by the developer looks something like this:
{
type: 'rect'.icon: 'https://example-icon.com/settings.png'.text: '22\n33333',}Copy the code
We need to determine in our internal code whether the parameter passed has an icon, and if so, display the icon in the upper left corner. However, for processes that want to display text in the upper left corner, we may need to add another field, nodeText, to control this. What if we want to show an icon on the right? Want to display 3 columns of text inside?
In general, configuration, while business developer-friendly, can be achieved with sufficient documentation and internal compatibility of the library. However, we need to pay a lot of cost to achieve various effects, and it is possible to abandon support for some uncommon effects because of some other situations. In the long run, this configuration is not flexible enough for us.
Another solution is plug-in, which disperses the changing non-core functions into plug-ins to avoid coupling them with the core code and keep the core code simple and stable. In the plug-in scheme, we can achieve a support for setting the Icon node, as for other special requirements of the node, users can use their own custom mechanism to achieve. And by opening it up to the community, other developer customizations can be contributed to LogicFlow as a plug-in.
Plugins offer many benefits:
- Get more of the front-end community involved, and if there are problems with the code written in the plug-in part, it won’t affect the core code.
- Secondary extension development, such as the lF-BPMN plug-in we plan to implement later in the extension pack, which is compatible with the BPMN 2.0 specification process designer. You can also add a Venn graph drawing LF-VENn plug-in, to achieve the use of LogicFlow Venn graph drawing. Even in the future, we can implement a corresponding plug-in for each form of flowchart editing.
- Flexible customization functions, menus, toolbars, artboards, etc. are made into plug-ins, developers feel that they do not meet their business needs, they can not use these plug-ins and develop their own.
API soundness & stability
What is a plug-in? A plug-in is a program written again in accordance with the interface specification provided by the core program. Plug-in can not be separated from the core program exists alone, is an extension of the core program function. So personally, the most important point of plug-in is the API soundness and stability of the core program. If our API wasn’t perfect, community developers wouldn’t be able to develop plugins that fit their needs. If our API changes too much, it is very likely that previously developed plug-ins will become unusable after our version is upgraded, resulting in chaos for the entire LogicFlow community.
To keep the API robust and stable, we do the following:
- Strictly follow open source release specifications. Ensure that the impact of the release of LogicFlow on the surrounding ecology is controllable.
- Focus on forward compatibility when API changes are made.
- There are enough built-in plug-ins to verify the API’s soundness and stability.
Built-in plug-ins
If we only provide @LogicFlow /core, which represents the edit part of the diagram, then logicFlow is a half-finished product, which is not conducive to promotion or hands-on use. So we’re going to make LogicFlow non-core functions like menus, toolbars, etc.; Various characteristic morphological nodes; Some common processes and practical application scenarios are implemented in the way of plug-ins in the @LogicFlow/Extension package. One of them is the BPMN-JS plugin. Here I will briefly describe how LogicFlow uses the plugin mechanism to implement bPMN-JS compatible plug-ins.
- The first is the various nodes and wires in BPMN-JS, such as userTask, gateWay, sequenceFlow, etc. We use LogicFlow custom nodes and custom wiring mechanisms to encapsulate all the basic graphics required by BPMN-JS into BpmnElement plug-ins.
- By default, LogicFlow generates data in JSON consisting of nodes and edges, while BPMN-JS needs to generate data in XML that meets the BPMN 2.0 standard. Therefore, we provide a BpmnAdapter that converts BPMN XML into LogicFlow Data when the Data is entered into LogicFlow, and LogicFlow Data into BPMN XML when it is output.
- Finally, we use LogicFlow’s custom Component function to package the menus, sketchboards and shortcut tools needed in the process of flowchart drawing into Bpmn Component.
- Wrap the above three plug-ins together as Bpmn plug-ins.
LogicFlow itself is a simple flowchart editor with no business attributes. For better ease of use, we provide a BPMN-JS plug-in that allows projects using BPMN-JS to be quickly replaced. Once you have the Bpmn plug-in, load the Bpmn plug-in directly through LogicFlow, and the page behaves as BPMN-js.
import LogicFlow from '@logicflow/core';
import { Bpmn } from '@logicflow/extension';
LogicFlow.use(Bpmn);
Copy the code
LogicFlow scalability
As mentioned earlier, the extensibility of a plug-in depends on the extensibility of the API provided by the core application. LogicFlow is designed on most apis with the goal of supporting extensibility. The plugin we developed in @LogicFlow/Extension is also a way to validate our API. The figure below shows the overall thinking behind LogicFlow’s ability to support scalability.
Custom node
For ease of use, in terms of nodes, LogicFlow has built in base nodes and then implemented some special nodes in @LogicFlow/Extension. In practice, developers can customize nodes to meet their business requirements based on these basic nodes and special nodes.
- Base node: in
@logicflow/core
There is a BaseNode abstract class, which implements most of the logic required by the nodes in the flowchart, such as node drag, click and other events and line processing. There are also methods to obtain node appearance attributes, node basic attributes, node configuration customization attributes, which can be overridden by subclasses. - Built-in nodes: BaseNode is an abstract class. For ease of use, we have built some basic graphical nodes into LogicFlow. Examples are RectNode, CircleNode, DiamondNode, and PolygonNode.
- Extension nodes: To reduce access costs for developers, LogicFlow is expanding packages in addition to providing built-in nodes for development inheritance customization in the core package
@logicflow/extension
More nodes are provided in. For example, cylindernodes, recticonnodes with ICONS, etc. - Custom nodes: Developers can build their own projects based on any of the LogicFlow nodes (including
@logicflow/extension
), using inheritance to rewrite the corresponding method, to achieve their own business requirements of the node. Also, the developer’s own custom nodes can become plug-ins and open source to the community. In the future, we will increase the LogicFlow plugin market, and you will be free to choose the nodes you want for your project.
Custom node rules
At some point, we may need to control how the wires are connected, for example, node A cannot be the beginning of the wire, node B cannot be the end of the wire, node C must be followed by node A, and so on. LogicFlow provides the ability to customize node rules to fulfill this requirement.
LogicFlow has two public methods, getConnectedSourceRules and getConnectedTargetRules, which return the validation rule for the current node as the connection start and the connection target, respectively. When the panel is connected, it will determine whether all rules pass or not, and can only be connected if they pass.
class CnodeModel extends RectModel {
/* ignore other code*/
// Determine whether the next node of this node meets the custom requirements
getConnectedSourceRules(): ConnectRule[] {
const rules = super.getConnectedSourceRules();
const gateWayOnlyAsTarget = {
message: 'C can only be A next node '.validate: (source: BaseNode, target: BaseNode) = > {
let isValid = true;
if(target.type ! = ='a-node ') {
isValid = false;
}
returnisValid; }}; rules.push(gateWayOnlyAsTarget);return rules;
}
// Determine whether the previous node of this node meets the custom requirements
getConnectedTargetRules(){}}Copy the code
Custom Connections
The custom connection scheme is basically the same as the custom node. The basic connection realizes most of the logic of the line, and then realizes the special interaction processing of the line in the built-in connection. Finally, the developer carries out the custom development based on the built-in connection. Of course, since most graph editing lines are only lines, lines, and curves, developers usually change the style (color, dotted line) and name (Bpmn is called Bpmn :sequenceFlow).
Custom attributes
Generally speaking, for a node, we only need type, x, y, and text to complete all the visible information of a node in the graph. Type controls the type of the node, x and y control the position of the node, and text controls the text on the node. However, in actual use, we may need to put more attributes with business nature on the node, and then make corresponding processing based on these business attributes on the node display. For example, in a process, we need to highlight some nodes to indicate that they are in an abnormal state.
LogicFlow provides a properties field for developers to store their own business-related properties, which can then be processed based on these properties when customizing nodes.
lf.register('custom-process'.({TriangleNode,TriangleModel }) = > {
class CustomProcessNode extends TriangleNode {
static extendKey = 'CustomProcessNode';
getShapeStyle() {
const attributes = super.getShapeStyle();
const properties = super.getProperties();
// Check whether the customStatus attribute is error.
// If so, set the fill color of this node to red.
if (properties.customStatus === 'error') {
attributes.fill = 'red'
}
returnattributes; }}return {
view: CustomProcessNode,
model: PolygonNodeModel,
};
});
Copy the code
The above code defines a custom-process node. If the node type in the data is custom- Process and the customStatus in the node property is error, a red triangle is displayed on the flowchart.
Custom Components
In LogicFlow, in addition to SVG rendered graphics such as nodes and wires, there are components for controlling the graph editing process that LogicFlow implements through HTML (menus, control panels, etc.). LogicFlow opens up the ability to insert DOM on a graph, allowing developers to implement custom components based on this ability.
With the ability to freely plug in the DOM on a graph, you can do a lot of things, such as implementing a tool to freely adjust node colors and font sizes. The development of this tool just needs to follow our normal front-end development. Then, after listening for the user to select the node, insert the DOM next to the node.
The theme
We mentioned above that you can use custom nodes to customize the appearance of any node, but it would be too cumbersome to customize each node individually. LogicFlow provides theme functionality to unify the appearance base properties of all nodes. Let’s say we want all rectangles to have no borders.
lf.setTheme({
rect: {
strokeWidth: 0}})Copy the code
In addition to setting the appearance of nodes and wires, themes can also set the style of internal functions, such as text, alignment lines, and so on.
The last
From the above introduction, you should have a certain understanding of LogicFlow extension mechanism. LogicFlow itself is not a process design tool for a particular scenario, but rather a flowchart editing library. In most cases, extensibility means not being able to use it out of the box. To make LogicFlow a library out of the box, LogicFlow uses plug-ins to limit scenarios to actual business scenarios.
LogicFlow is still a very new open source project, the plugins are not rich enough, there are also some business scenarios are not considered, welcome everyone to send an issue on Github, we will take every issue seriously! LogicFlow is also looking for contributors, so if you’re interested, come and contribute!
Read more:
- LogicFlow github:github.com/didi/LogicF…
- Official document of LogicFlow: logic-flow.org/
- LogicFlow design principle overview: juejin.cn/post/693341…
- Add wechat to user group: logic-flow