Skip to content

Commit

Permalink
feat(dmn-js-drd): implement search
Browse files Browse the repository at this point in the history
  • Loading branch information
barmac committed Oct 17, 2023
1 parent ba631f1 commit aa32eea
Show file tree
Hide file tree
Showing 10 changed files with 421 additions and 16 deletions.
11 changes: 7 additions & 4 deletions packages/dmn-js-drd/src/NavigatedViewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ import inherits from 'inherits-browser';

import Viewer from './Viewer';

import ZoomScroll from 'diagram-js/lib/navigation/zoomscroll';
import MoveCanvas from 'diagram-js/lib/navigation/movecanvas';
import TouchModule from 'diagram-js/lib/navigation/touch';

import DmnSearchModule from './features/search';

/**
* A viewer that includes mouse navigation facilities
Expand All @@ -14,14 +19,12 @@ export default function NavigatedViewer(options) {

inherits(NavigatedViewer, Viewer);

import ZoomScroll from 'diagram-js/lib/navigation/zoomscroll';
import MoveCanvas from 'diagram-js/lib/navigation/movecanvas';
import TouchModule from 'diagram-js/lib/navigation/touch';

NavigatedViewer.prototype._navigationModules = [
ZoomScroll,
MoveCanvas,
TouchModule
TouchModule,
DmnSearchModule
];

NavigatedViewer.prototype._modules = [].concat(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,15 @@ DrdEditorActions.prototype._registerDefaultActions = function(injector) {

// (1) retrieve optional components to integrate with

var canvas = injector.get('canvas', false);
var elementRegistry = injector.get('elementRegistry', false);
var selection = injector.get('selection', false);
var lassoTool = injector.get('lassoTool', false);
var handTool = injector.get('handTool', false);
var directEditing = injector.get('directEditing', false);
var distributeElements = injector.get('distributeElements', false);
var alignElements = injector.get('alignElements', false);
const canvas = injector.get('canvas', false),
elementRegistry = injector.get('elementRegistry', false),
selection = injector.get('selection', false),
lassoTool = injector.get('lassoTool', false),
handTool = injector.get('handTool', false),
directEditing = injector.get('directEditing', false),
distributeElements = injector.get('distributeElements', false),
alignElements = injector.get('alignElements', false),
searchPad = injector.get('searchPad', false);

// (2) check components and register actions

Expand Down Expand Up @@ -97,4 +98,10 @@ DrdEditorActions.prototype._registerDefaultActions = function(injector) {
}
});
}

if (selection && searchPad) {
this._registerAction('find', function() {
searchPad.toggle();
});
}
};
12 changes: 12 additions & 0 deletions packages/dmn-js-drd/src/features/keyboard/DrdKeyboardBindings.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,16 @@ DrdKeyboardBindings.prototype.registerBindings = function(keyboard, editorAction
}
});

// search labels
// CTRL + F
addListener('find', function(context) {

var event = context.keyEvent;

if (keyboard.isKey([ 'f', 'F' ], event) && keyboard.isCmd(event)) {
editorActions.trigger('find');

return true;
}
});
};
139 changes: 139 additions & 0 deletions packages/dmn-js-drd/src/features/search/DmnSearchProvider.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
import {
map,
filter,
sortBy
} from 'min-dash';

import {
getLabel
} from '../label-editing/LabelUtil';

/**
* @typedef {import('diagram-js/lib/core/Canvas').default} Canvas
* @typedef {import('diagram-js/lib/core/ElementRegistry').default} ElementRegistry
* @typedef {import('diagram-js/lib/features/search-pad/SearchPad').default} SearchPad
*
* @typedef {import('diagram-js/lib/features/search-pad/SearchPadProvider').default
* } SearchPadProvider
* @typedef {import('diagram-js/lib/features/search-pad/SearchPadProvider').SearchResult
* } SearchResult
*/

/**
* Provides ability to search for DMN elements.
*
* @implements {SearchPadProvider}
*
* @param {ElementRegistry} elementRegistry
* @param {SearchPad} searchPad
* @param {Canvas} canvas
*/
export default function DmnSearchProvider(elementRegistry, searchPad, canvas) {
this._elementRegistry = elementRegistry;
this._canvas = canvas;

searchPad.registerProvider(this);
}

DmnSearchProvider.$inject = [
'elementRegistry',
'searchPad',
'canvas'
];

/**
* @param {string} pattern
*
* @return {SearchResult[]}
*/
DmnSearchProvider.prototype.find = function(pattern) {
const rootElement = this._canvas.getRootElement();

let elements = this._elementRegistry.filter(function(element) {
if (element.labelTarget) {
return false;
}
return true;
});

// do not include root element
elements = filter(elements, function(element) {
return element !== rootElement;
});

elements = map(elements, function(element) {
return {
primaryTokens: matchAndSplit(getLabel(element), pattern),
secondaryTokens: matchAndSplit(element.id, pattern),
element: element
};
});

// exclude non-matched elements
elements = filter(elements, function(element) {
return hasMatched(element.primaryTokens) || hasMatched(element.secondaryTokens);
});

elements = sortBy(elements, function(element) {
return getLabel(element.element) + element.element.id;
});

return elements;
};

/**
* @param {Token[]} tokens
*
* @return {boolean}
*/
function hasMatched(tokens) {
const matched = filter(tokens, function(token) {
return !!token.matched;
});

return matched.length > 0;
}

/**
* @param {string} text
* @param {string} pattern
*
* @return {Token[]}
*/
function matchAndSplit(text, pattern) {
const tokens = [],
originalText = text;

if (!text) {
return tokens;
}

text = text.toLowerCase();
pattern = pattern.toLowerCase();

const i = text.indexOf(pattern);

if (i > -1) {
if (i !== 0) {
tokens.push({
normal: originalText.substr(0, i)
});
}

tokens.push({
matched: originalText.substr(i, pattern.length)
});

if (pattern.length + i < text.length) {
tokens.push({
normal: originalText.substr(pattern.length + i, text.length)
});
}
} else {
tokens.push({
normal: originalText
});
}

return tokens;
}
12 changes: 12 additions & 0 deletions packages/dmn-js-drd/src/features/search/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import SearchPadModule from 'diagram-js/lib/features/search-pad';

import DmnSearchProvider from './DmnSearchProvider';


export default {
__depends__: [
SearchPadModule
],
__init__: [ 'dmnSearch' ],
dmnSearch: [ 'type', DmnSearchProvider ]
};
3 changes: 2 additions & 1 deletion packages/dmn-js-drd/test/spec/ModelerSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,8 @@ describe('Modeler', function() {
'alignElements',
'lassoTool',
'handTool',
'directEditing'
'directEditing',
'find'
];

// when
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import handToolModule from 'diagram-js/lib/features/hand-tool';
import distributeElementsModule from 'src/features/distribute-elements';
import coreModule from 'src/core';
import lassoTool from 'diagram-js/lib/features/lasso-tool';
import searchModule from 'src/features/search';

var diagramXML = require('./DrdEditorActions.dmn');

Expand All @@ -27,7 +28,8 @@ describe('features/editor-actions', function() {
distributeElementsModule,
lassoToolModule,
handToolModule,
lassoTool
lassoTool,
searchModule
]
}));

Expand Down Expand Up @@ -116,4 +118,24 @@ describe('features/editor-actions', function() {

});


describe('lassoTool', function() {

it('should toggle', inject(function(editorActions, searchPad) {

// given
editorActions.trigger('find');

// assume
expect(searchPad.isOpen()).to.be.true;

// when
editorActions.trigger('find');

// then
expect(!!searchPad.isOpen()).to.be.false;
}));

});

});
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import lassoToolModule from 'diagram-js/lib/features/lasso-tool';
import handToolModule from 'diagram-js/lib/features/hand-tool';
import keyboardModule from 'src/features/keyboard';
import modelingModule from 'src/features/modeling';
import searchModule from 'src/features/search';

import {
createKeyEvent
Expand All @@ -34,7 +35,8 @@ describe('features - keyboard', function() {
handToolModule,
keyboardModule,
editorActionsModule,
modelingModule
modelingModule,
searchModule
]
}));

Expand All @@ -52,7 +54,8 @@ describe('features - keyboard', function() {
'selectElements',
'lassoTool',
'handTool',
'directEditing'
'directEditing',
'find'
];

// then
Expand Down Expand Up @@ -151,6 +154,25 @@ describe('features - keyboard', function() {

});


forEach([ 'f', 'F' ], function(key) {

it('should open search',
inject(function(keyboard, searchPad) {

// given
const e = createKeyEvent(key, { ctrlKey: true });

// when
keyboard._keyHandler(e);

// then
expect(searchPad.isOpen()).to.be.true;
})
);

});

});

});
Loading

0 comments on commit aa32eea

Please sign in to comment.