Coder Social home page Coder Social logo

cuba-platform / rich-search-addon Goto Github PK

View Code? Open in Web Editor NEW
2.0 6.0 2.0 1.29 MB

Global Search CUBA Platform application component that will provide user ability to search many types of objects in one search field.

License: Apache License 2.0

Java 57.46% CSS 0.14% XSLT 42.41%
cuba-platform cuba-component search apache2

rich-search-addon's Introduction

license Build Status

Rich Search

Overview

The add-on is designed to search for various types of objects using a single field. This out-of-the-box solution enables searching by application menu items.

You can configure your application to search for entities including related ones as well as entity attributes.

Key features:

  • A single field for searching.
  • Customizable search strategy.

Component image example

See sample application using this add-on.

Installation

The add-on can be added to your project in one of the ways described below. Installation from the Marketplace is the simplest way. The last version of the add-on compatible with the used version of the platform will be installed. Also, you can install the add-on by coordinates choosing the required version of the add-on from the table.

In case you want to install the add-on by manual editing or by building from sources see the complete add-ons installation guide in CUBA Platform documentation.

From the Marketplace

  1. Open your application in CUBA Studio. Check the latest version of CUBA Studio on the CUBA Platform site.
  2. Go to CUBA -> Marketplace in the main menu.

marketplace

  1. Find the Rich Search add-on there.

addons

  1. Click Install and apply the changes. The add-on corresponding to the used platform version will be installed.

By coordinates

  1. Open your application in CUBA Studio. Check the latest version of CUBA Studio on the CUBA Platform site.
  2. Go to CUBA -> Marketplace in the main menu.
  3. Click the icon in the upper-right corner.

by-coordinates

  1. Paste the add-on coordinates in the corresponding field as follows:

com.haulmont.addon.search:search-global:<add-on version>

where <add-on version> is compatible with the used version of the CUBA platform.

Platform Version Add-on Version
7.2.X 1.6.0
7.1.X 1.5.0
7.0.X 1.4.0
6.10.X 1.3.0
6.9.X 1.2.0
6.8.X 1.0.3
  1. Click Install and apply the changes. The add-on will be installed to your project.

Quick Start

  1. Override the main screen via the Studio interface.
  2. Add the following code to ext-mainwindow.xml:

For horizontal menu layout

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<window xmlns="http://schemas.haulmont.com/cuba/window.xsd"
        class="com.company.rs.web.screens.ExtAppMainWindow"
        extends="/com/haulmont/cuba/web/app/mainwindow/mainwindow.xml"
        messagesPack="com.company.rs.web.screens"
        xmlns:ext="http://schemas.haulmont.com/cuba/window-ext.xsd"
        xmlns:search="http://schemas.haulmont.com/cuba/search.xsd">
    <dialogMode height="600"
                width="800"/>
    <layout>
        <hbox id="titleBar">
            <search:richSearch id="search"
                               align="MIDDLE_LEFT"
                               ext:index="3"
                               inputPrompt="msg://search"
                               suggestionsLimit="200">
                <search:strategyBean name="search_MainMenuSearchStrategy"/>
            </search:richSearch>
        </hbox>
    </layout>
</window>

For vertical menu layout

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<window xmlns="http://schemas.haulmont.com/cuba/window.xsd"
        extends="/com/haulmont/cuba/web/app/main/main-screen.xml"
        messagesPack="com.haulmont.demo.richsearch.web.screens"
        xmlns:ext="http://schemas.haulmont.com/cuba/window-ext.xsd"
        xmlns:search="http://schemas.haulmont.com/cuba/search.xsd">
    <dialogMode height="600"
                width="800"/>
    <layout>
        <hbox id="horizontalWrap">
            <vbox id="sideMenuPanel">
                <vbox ext:index="4" margin="true">
                    <search:richSearch id="search"
                                       align="MIDDLE_LEFT"
                                       width="100%"
                                       inputPrompt="msg://search"
                                       suggestionsLimit="200">
                        <search:strategyBean name="search_SideMenuSearchStrategy"/>                        
                    </search:richSearch>
                </vbox>
            </vbox>
        </hbox>
    </layout>
</window>

Data Model

Search Field

Search Field provides one or several search strategies that are called for each search query.

Search Strategy

Search Strategy defines which objects should be returned as a result of the current search request.

SearchEntry

SearchEntry is an interface designed to work with search result objects. Each SearchEntry has an id, caption and the name of a search strategy that it belongs to specified.

DefaultSearchEntry

DefaultSearchEntry defines the default implementation of SearchEntry.

SearchContext

SearchContext provides the context dependent data for the search mechanism, e.g. a user session, additional params.

HeaderEntry

HeaderEntry implements a header for grouping strategy results.

Usage

Let us consider an example of how the component can be of use. Start by searching for a system user. The component finds the required user and opens User Editor.

The system performs search by login. In order to configure the component, use the following code:

LoadContext<User> lc = LoadContext.create(User.class);
lc.setQueryString("select u from sec$User u where u.loginLowerCase like concat('%',:loginLowerCase,'%')")
        .setParameter("loginLowerCase", query.toLowerCase());

The sections below present several options to define search strategies.

Using A Spring Bean As Search Strategy

Spring bean:

@Component("search_UsersSearchStrategy")
public class UsersSearchStrategy implements SearchStrategy {
    @Override
    public List<SearchEntry> load(SearchContext context, String query) {
        LoadContext<User> lc = LoadContext.create(User.class);
        lc.setQueryString("select u from sec$User u where u.loginLowerCase like concat('%',:loginLowerCase,'%')")
                .setParameter("loginLowerCase", query.toLowerCase());

        return dataManager.loadList(lc).stream()
                .map(user -> new DefaultSearchEntry(user.getId().toString(), user.getCaption(), name()))
                .collect(Collectors.toList());
    }

    @Override
    public void invoke(SearchContext context, SearchEntry value) {
        LoadContext<User> lc = LoadContext.create(User.class)
                .setId(UuidProvider.fromString(value.getId()));
        User user = dataManager.load(lc);
        AppUI.getCurrent().getTopLevelWindow().openEditor(user, WindowManager.OpenType.NEW_TAB);
    }


    @Override
    public String name() {
        return "usersSearchStrategy";
    }
}

XML screen config:

<window
    class="com.company.test.web.screens.TestWindow"
    xmlns:search="http://schemas.haulmont.com/cuba/search.xsd">
    ...
    <layout>
        ...
        <search:richSearch id="search" inputPrompt="msg://search">
            <search:strategyBean name="search_UsersSearchStrategy" />
        </search:richSearch>
        ...
    </layout>
    ...
</window>

Localization

Add the following entry to the main message pack as it is given below:

searchStrategy.{strategyName} = Strategy name

Example:

searchStrategy.usersSearchStrategy = Users

Using Controller Methods

XML screen config:

<window
    class="com.company.test.web.screens.MyWindowController"
    xmlns:search="http://schemas.haulmont.com/cuba/search.xsd">
    ...
    <layout>
        ...
        <search:richSearch id="search" inputPrompt="msg://search">
            <search:strategy name="usersSearchStrategy" searchMethod="search" invokeMethod="invoke" />
        </search:richSearch>
        ...
    </layout>
    ...
</window>

Screen controller:

public class MyWindowController extends AbstractWindow {

    @Inject
    protected DataManager dataManager;

    public List<SearchEntry> search(SearchContext context, String query) {
        LoadContext<User> lc = LoadContext.create(User.class);
        lc.setQueryString("select u from sec$User u where u.loginLowerCase like concat('%',:loginLowerCase,'%')")
                .setParameter("loginLowerCase", query.toLowerCase());

        return dataManager.loadList(lc).stream()
                .map(user -> new DefaultSearchEntry(user.getId().toString(), user.getCaption(), "usersSearchStrategy"))
                .collect(Collectors.toList());
    }

    public void invoke(SearchContext context, SearchEntry searchEntry) {
        LoadContext<User> lc = LoadContext.create(User.class)
                .setId(UuidProvider.fromString(searchEntry.getId()));
        User user = dataManager.load(lc);
        AppUI.getCurrent().getTopLevelWindow().openEditor(user, WindowManager.OpenType.NEW_TAB);
    }
}

Using Programmatic Strategy

Screen controller:

public class MyWindowController extends AbstractWindow {

    @Inject
    protected DataManager dataManager;

    @Inject
    protected RichSearch search;

    @Override
    public void init(Map<String, Object> params) {
        super.init(params);

        search.addStrategy("usersSearchStrategy", query -> {
            LoadContext<User> lc = LoadContext.create(User.class);
            lc.setQueryString("select u from sec$User u where u.loginLowerCase like concat('%',:loginLowerCase,'%')")
                    .setParameter("loginLowerCase", query.toLowerCase());

            return dataManager.loadList(lc).stream()
                    .map(user -> new DefaultSearchEntry(user.getId().toString(), user.getCaption(), "usersSearchStrategy"))
                    .collect(Collectors.toList());
        }, searchEntry -> {
            LoadContext<User> lc = LoadContext.create(User.class)
                    .setId(UuidProvider.fromString(searchEntry.getId()));
            User user = dataManager.load(lc);
            AppUI.getCurrent().getTopLevelWindow().openEditor(user, WindowManager.OpenType.NEW_TAB);
        });
    }
}

The result is:

User search example

Known issues

  1. The available amount of input should be accounted for each strategy separately (no task, to be discussed).
  2. It is required to add an XML declaration for specific strategy parameters (no task, to be discussed).
  3. It is required to add keyboard shortcuts for the component and its settings (no task, to be discussed).

rich-search-addon's People

Contributors

nikitashchienko avatar zharenov avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

Forkers

knstvk douit

rich-search-addon's Issues

There is no search field in demo

Environment

  • Platform version: 7.1.0
  • Addon version: 1.5-SNAPSHOT
  1. Run demo
  2. Login

Expected result: there is a search field
Actual result: there is NO search field

11144444444

Upgrade add-on to CUBA 7.1 platform version.

Upgrade add-on to CUBA 7.1 platform version.
Snapshot add-on version should be updated to 1.5.
Current releases/cuba_7.0 branch should be merged from the master. Create this branch if it does not exist.

Improve README

  • Explain what the component can do out-of-the-box and what with additional programming

  • Explain what are main components and how they interact: search field, SearchStrategy, SearchContext, etc.

  • In "Main Screen Configuration" (which can probably be renamed to "Quick Start"), remove all unneeded from the XML descriptor and keep only the meaningful part like this:

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <window xmlns="http://schemas.haulmont.com/cuba/window.xsd"
            class="com.company.testrichsearch.web.screens.ExtAppMainWindow"
            extends="/com/haulmont/cuba/web/app/mainwindow/mainwindow.xml"
            messagesPack="com.company.testrichsearch.web.screens"
            xmlns:ext="http://schemas.haulmont.com/cuba/window-ext.xsd"
            xmlns:search="http://schemas.haulmont.com/cuba/search.xsd">
        <layout>
            <hbox id="titleBar">
                <hbox id="mainButtonsBox"
                    ext:index="2"
                    spacing="true">
                    <search:richSearch id="search"
                                    align="MIDDLE_LEFT"
                                    inputPrompt="Search..."
                                    suggestionsLimit="200">
                        <search:strategyBean name="search_MainMenuSearchStrategy"/>
                    </search:richSearch>
                </hbox>
            </hbox>
        </layout>
    </window>
    
  • "Usage" section is too concise and confusing:

    • "Using Declarative XML Strategy" - confusing. It's actually a way to define a strategy as a Spring bean.
    • "Configuration of references for frame methods" - confusing. It's a way to use controller methods instead of implementing the strategy interface.
  • Fix typos: "If a custom theme is used in your project, aff the following stypes"

Empty HSQL db init - scripts

Environment

  • Platform version: 7.2.0.beta2

  • Studio 13

  • Minimal reproducible example

  1. Using new Studio create a project. Use HSQLDB
  2. Using Marketplace add the rich text search
  3. CreateDb, and launch the application from Studio
  4. restart the application from Studio
  • Actual behavior
    On every application restart Studio shows the following dialog.

image

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.