All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.dominokit.domino.ui.datatable.plugins.HeaderBarPlugin Maven / Gradle / Ivy

There is a newer version: 2.0.3
Show newest version
/*
 * Copyright © 2019 Dominokit
 *
 * 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
 *
 *     http://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.
 */
package org.dominokit.domino.ui.datatable.plugins;

import static java.util.Objects.nonNull;
import static org.jboss.elemento.Elements.*;

import elemental2.dom.*;
import java.util.ArrayList;
import java.util.List;
import jsinterop.base.Js;
import org.dominokit.domino.ui.datatable.DataTable;
import org.dominokit.domino.ui.datatable.DataTableStyles;
import org.dominokit.domino.ui.datatable.DefaultColumnShowHideListener;
import org.dominokit.domino.ui.datatable.events.SearchClearedEvent;
import org.dominokit.domino.ui.datatable.events.TableEvent;
import org.dominokit.domino.ui.datatable.model.Category;
import org.dominokit.domino.ui.datatable.model.Filter;
import org.dominokit.domino.ui.datatable.model.SearchContext;
import org.dominokit.domino.ui.dropdown.DropDownMenu;
import org.dominokit.domino.ui.dropdown.DropDownPosition;
import org.dominokit.domino.ui.dropdown.DropdownAction;
import org.dominokit.domino.ui.forms.TextBox;
import org.dominokit.domino.ui.grid.Column;
import org.dominokit.domino.ui.grid.Row;
import org.dominokit.domino.ui.grid.flex.FlexItem;
import org.dominokit.domino.ui.grid.flex.FlexJustifyContent;
import org.dominokit.domino.ui.grid.flex.FlexLayout;
import org.dominokit.domino.ui.icons.Icon;
import org.dominokit.domino.ui.icons.Icons;
import org.dominokit.domino.ui.icons.MdiIcon;
import org.dominokit.domino.ui.style.Style;
import org.dominokit.domino.ui.style.Styles;
import org.dominokit.domino.ui.style.Unit;
import org.dominokit.domino.ui.utils.DominoElement;
import org.dominokit.domino.ui.utils.ElementUtil;
import org.dominokit.domino.ui.utils.TextNode;
import org.gwtproject.timer.client.Timer;
import org.jboss.elemento.EventType;

/**
 * This plugin attach an action bar to the table and adds {@link HeaderActionElement}(s) to it
 *
 * @param  the type of the data table records
 */
public class HeaderBarPlugin implements DataTablePlugin {

  private Column titleColumn = Column.span6();
  private Column actionsBarColumn = Column.span6();

  private HTMLHeadingElement title = Style.of(h(2)).setMarginBottom("0px").element();
  private FlexLayout actionsBar = FlexLayout.create().setJustifyContent(FlexJustifyContent.END);

  private HTMLDivElement element =
      DominoElement.of(div())
          .add(
              Row.create()
                  .appendChild(titleColumn.appendChild(title))
                  .appendChild(actionsBarColumn.appendChild(actionsBar))
                  .element())
          .css(DataTableStyles.HEADER)
          .style("padding-bottom: 5px;")
          .element();

  private final List> actionElements = new ArrayList<>();

  /**
   * creates an instance with a custom title
   *
   * @param title String title of the header bar
   */
  public HeaderBarPlugin(String title) {
    this(title, "");
  }

  /**
   * creates an instance with a custom and description
   *
   * @param title String title of the header bar
   * @param description String description of the header bar
   */
  public HeaderBarPlugin(String title, String description) {
    this.title.appendChild(DomGlobal.document.createTextNode(title));
    if (nonNull(description) && !description.isEmpty()) {
      this.title.appendChild(small().textContent(description).element());
    }

    Style.of(titleColumn).setMarginBottom("0px");
    Style.of(actionsBarColumn).setMarginBottom("0px");
  }

  /** {@inheritDoc} */
  @Override
  public void onBeforeAddTable(DataTable dataTable) {
    actionElements.forEach(
        actionElement ->
            actionsBar.appendChild(
                FlexItem.create()
                    .addCss(Styles.m_r_5)
                    .addCss(Styles.m_l_5)
                    .appendChild(actionElement.asElement(dataTable))
                    .element()));
    dataTable.element().appendChild(element);
  }

  /**
   * Adds a new header action to this header bar
   *
   * @param headerActionElement the {@link HeaderActionElement}
   * @return same plugin instance
   */
  public HeaderBarPlugin addActionElement(HeaderActionElement headerActionElement) {
    actionElements.add(headerActionElement);
    return this;
  }

  /**
   * a Predefined {@link HeaderActionElement} that condense/expand the data table rows
   *
   * @param  the type of the data table records
   */
  public static class CondenseTableAction implements HeaderActionElement {
    private String condenseToolTip = "Condense";
    private String expandToolTip = "Expand";

    /** {@inheritDoc} */
    @Override
    public Node asElement(DataTable dataTable) {
      Icon condenseIcon =
          Icons.ALL
              .line_weight()
              .clickable()
              .setTooltip(condenseToolTip)
              .setToggleIcon(Icons.ALL.format_line_spacing())
              .toggleOnClick(true)
              .apply(
                  icon ->
                      icon.addClickListener(
                          evt -> {
                            if (dataTable.isCondensed()) {
                              dataTable.show();
                              icon.setTooltip(condenseToolTip);
                            } else {
                              dataTable.condense();
                              icon.setTooltip(expandToolTip);
                            }
                          }));

      return a().add(condenseIcon).element();
    }

    /**
     * Changes the condense icon tooltip
     *
     * @param condenseToolTip String
     * @return same acton instance
     */
    public CondenseTableAction setCondenseToolTip(String condenseToolTip) {
      this.condenseToolTip = condenseToolTip;
      return this;
    }

    /**
     * Changes the expand icon tooltip
     *
     * @param expandToolTip String
     * @return same acton instance
     */
    public CondenseTableAction setExpandToolTip(String expandToolTip) {
      this.expandToolTip = expandToolTip;
      return this;
    }
  }

  /**
   * A predefined action to toggle stripes on data table rows
   *
   * @param  the type of the data table records
   */
  public static class StripesTableAction implements HeaderActionElement {

    private String noStripsToolTip = "No stripes";
    private String stripsToolTip = "Stripes";

    /** {@inheritDoc} */
    @Override
    public Node asElement(DataTable dataTable) {
      Icon stripesIcon =
          Icons.ALL
              .format_line_spacing()
              .clickable()
              .setToggleIcon(Icons.ALL.power_input())
              .setTooltip(noStripsToolTip)
              .toggleOnClick(true)
              .apply(
                  icon ->
                      icon.addClickListener(
                          evt -> {
                            if (dataTable.isStriped()) {
                              dataTable.noStripes();
                              icon.setTooltip(stripsToolTip);
                            } else {
                              dataTable.striped();
                              icon.setTooltip(noStripsToolTip);
                            }
                          }));

      return a().add(stripesIcon).element();
    }

    /**
     * Changes the no strips icon tooltip
     *
     * @param noStripsToolTip String
     * @return same acton instance
     */
    public StripesTableAction setNoStripsToolTip(String noStripsToolTip) {
      this.noStripsToolTip = noStripsToolTip;
      return this;
    }

    /**
     * Changes the strips icon tooltip
     *
     * @param stripsToolTip String
     * @return same acton instance
     */
    public StripesTableAction setStripsToolTip(String stripsToolTip) {
      this.stripsToolTip = stripsToolTip;
      return this;
    }
  }

  /**
   * A predefined action to toggle borders on data table rows
   *
   * @param  the type of the data table records
   */
  public static class BordersTableAction implements HeaderActionElement {

    private String borderedToolTip = "Bordered";
    private String noBprdersToolTip = "No borders";

    /** {@inheritDoc} */
    @Override
    public Node asElement(DataTable dataTable) {

      Icon bordersIcon =
          Icons.ALL
              .border_vertical()
              .clickable()
              .setToggleIcon(Icons.ALL.border_clear())
              .toggleOnClick(true)
              .setTooltip(borderedToolTip)
              .apply(
                  icon ->
                      icon.addClickListener(
                          evt -> {
                            if (dataTable.isBordered()) {
                              dataTable.noBorder();
                              icon.setTooltip(borderedToolTip);
                            } else {
                              dataTable.bordered();
                              icon.setTooltip(noBprdersToolTip);
                            }
                          }));

      return a().add(bordersIcon).element();
    }

    /**
     * Changes the borders icon tooltip
     *
     * @param borderedToolTip String
     * @return same acton instance
     */
    public BordersTableAction setBorderedToolTip(String borderedToolTip) {
      this.borderedToolTip = borderedToolTip;
      return this;
    }

    /**
     * Changes the no borders icon tooltip
     *
     * @param noBordersToolTip String
     * @return same acton instance
     */
    public BordersTableAction setNoBordersToolTip(String noBordersToolTip) {
      this.noBprdersToolTip = noBordersToolTip;
      return this;
    }
  }

  /**
   * A predefined action to toggle hover on data table rows
   *
   * @param  the type of the data table records
   */
  public static class HoverTableAction implements HeaderActionElement {

    private String hoverToolTip = "Hover";
    private String noHoverToolTip = "No Hover";

    /** {@inheritDoc} */
    @Override
    public Node asElement(DataTable dataTable) {

      Icon hoverIcon =
          Icons.ALL
              .blur_off()
              .clickable()
              .setToggleIcon(Icons.ALL.blur_on())
              .toggleOnClick(true)
              .setTooltip(noHoverToolTip)
              .apply(
                  icon ->
                      icon.addClickListener(
                          evt -> {
                            if (dataTable.isHoverable()) {
                              dataTable.noHover();
                              icon.setTooltip(hoverToolTip);
                            } else {
                              dataTable.hovered();
                              icon.setTooltip(noHoverToolTip);
                            }
                          }));

      return a().add(hoverIcon).element();
    }

    /**
     * Changes the hover icon tooltip
     *
     * @param hoverToolTip String
     * @return same acton instance
     */
    public HoverTableAction setHoverToolTip(String hoverToolTip) {
      this.hoverToolTip = hoverToolTip;
      return this;
    }

    /**
     * Changes the no hover icon tooltip
     *
     * @param noHoverToolTip String
     * @return same acton instance
     */
    public HoverTableAction setNoHoverToolTip(String noHoverToolTip) {
      this.noHoverToolTip = noHoverToolTip;
      return this;
    }
  }

  /**
   * A predefined action to clear data table search
   *
   * @param  the type of the data table records
   */
  public static class ClearSearch implements HeaderActionElement {

    private String clearFiltersToolTip = "Clear filters";

    /** {@inheritDoc} */
    @Override
    public Node asElement(DataTable dataTable) {

      MdiIcon clearFiltersIcon =
          Icons.MDI_ICONS
              .filter_remove_mdi()
              .setTooltip(clearFiltersToolTip)
              .size18()
              .clickable()
              .addClickListener(evt -> dataTable.getSearchContext().clear().fireSearchEvent());

      return a().add(clearFiltersIcon).element();
    }

    /**
     * Changes the clear filters icon tooltip
     *
     * @param clearFiltersToolTip String
     * @return same acton instance
     */
    public ClearSearch setClearFiltersToolTip(String clearFiltersToolTip) {
      this.clearFiltersToolTip = clearFiltersToolTip;
      return this;
    }
  }

  /**
   * A predefined action to add a search box the data table
   *
   * @param  the type of the data table records
   */
  public static class SearchTableAction implements HeaderActionElement {

    private String searchToolTip = "Search";
    private String clearSearchToolTip = "Clear search";

    private int autoSearchDelay = 200;
    private HTMLDivElement element = DominoElement.of(div()).css("search-new").element();
    private DataTable dataTable;
    private final TextBox textBox;
    private boolean autoSearch = true;
    private Timer autoSearchTimer;
    private EventListener autoSearchEventListener;
    private final Icon searchIcon;
    private final Icon clearIcon;

    /** creates a new instance */
    public SearchTableAction() {

      searchIcon =
          Icons.ALL
              .search()
              .addClickListener(
                  evt -> {
                    autoSearchTimer.cancel();
                    doSearch();
                  })
              .setTooltip(searchToolTip)
              .style()
              .setCursor("pointer")
              .get();

      clearIcon =
          Icons.ALL.clear().setTooltip(clearSearchToolTip).style().setCursor("pointer").get();

      textBox =
          TextBox.create()
              .setPlaceholder(searchToolTip)
              .addLeftAddOn(searchIcon)
              .addRightAddOn(clearIcon)
              .addCss("table-search-box")
              .setMarginBottom("0px")
              .setMaxWidth("300px")
              .addCss(Styles.pull_right);

      clearIcon.addClickListener(
          evt -> {
            textBox.clear();
            autoSearchTimer.cancel();
            doSearch();
          });

      element.appendChild(textBox.element());

      autoSearchTimer =
          new Timer() {
            @Override
            public void run() {
              doSearch();
            }
          };

      autoSearchEventListener =
          evt -> {
            autoSearchTimer.cancel();
            autoSearchTimer.schedule(autoSearchDelay);
          };

      setAutoSearch(true);
    }

    /** @return boolean, true if the auto search is enabled */
    public boolean isAutoSearch() {
      return autoSearch;
    }

    /**
     * Enable/Disable auto search when enabled the search will triggered while the user is typing
     * with a delay otherwise the search will only be triggered when the user click on search or
     * press Enter
     *
     * @param autoSearch boolean
     * @return same action instance
     */
    public SearchTableAction setAutoSearch(boolean autoSearch) {
      this.autoSearch = autoSearch;

      if (autoSearch) {
        textBox.addEventListener("input", autoSearchEventListener);
      } else {
        textBox.removeEventListener("input", autoSearchEventListener);
        autoSearchTimer.cancel();
      }

      textBox.addEventListener(
          EventType.keypress.getName(),
          evt -> {
            if (ElementUtil.isEnterKey(Js.uncheckedCast(evt))) {
              doSearch();
            }
          });

      return this;
    }

    /** @return int search delay in milliseconds */
    public int getAutoSearchDelay() {
      return autoSearchDelay;
    }

    /** @param autoSearchDelayInMillies int auto search delay in milliseconds */
    public void setAutoSearchDelay(int autoSearchDelayInMillies) {
      this.autoSearchDelay = autoSearchDelayInMillies;
    }

    private void doSearch() {
      SearchContext searchContext = dataTable.getSearchContext();
      Category search = Category.SEARCH;
      searchContext.removeByCategory(search);
      searchContext.add(Filter.create("*", textBox.getValue(), Category.SEARCH)).fireSearchEvent();
    }

    /** {@inheritDoc} */
    @Override
    public void handleEvent(TableEvent event) {
      if (SearchClearedEvent.SEARCH_EVENT_CLEARED.equals(event.getType())) {
        textBox.pauseChangeHandlers();
        textBox.clear();
        textBox.resumeChangeHandlers();
      }
    }

    /** {@inheritDoc} */
    @Override
    public Node asElement(DataTable dataTable) {
      this.dataTable = dataTable;
      dataTable.addTableEventListener(SearchClearedEvent.SEARCH_EVENT_CLEARED, this);
      return element;
    }

    /**
     * Set the search icon tooltip
     *
     * @param searchToolTip String
     * @return same action instance
     */
    public SearchTableAction setSearchToolTip(String searchToolTip) {
      this.searchToolTip = searchToolTip;
      searchIcon.setTooltip(searchToolTip);
      textBox.setPlaceholder(searchToolTip);
      return this;
    }

    /**
     * Set the clear search icon tooltip
     *
     * @param clearSearchToolTip String
     * @return same action instance
     */
    public SearchTableAction setClearSearchToolTip(String clearSearchToolTip) {
      this.clearSearchToolTip = clearSearchToolTip;
      clearIcon.setTooltip(clearSearchToolTip);
      return this;
    }
  }

  /**
   * A predefined action to add a drop down to the data table that allow selecting which columns be
   * shown/hidden
   *
   * @param  the type of the data table records
   */
  public static class ShowHideColumnsAction implements HeaderActionElement {
    /** {@inheritDoc} */
    @Override
    public Node asElement(DataTable dataTable) {
      Icon columnsIcon = Icons.ALL.view_column().clickable();

      DropDownMenu dropDownMenu = DropDownMenu.create(columnsIcon);
      dropDownMenu
          .setPosition(DropDownPosition.BOTTOM_LEFT)
          .apply(
              columnsMenu ->
                  dataTable
                      .getTableConfig()
                      .getColumns()
                      .forEach(
                          columnConfig -> {
                            Icon checkIcon = Icons.ALL.check();
                            columnConfig.addShowHideListener(
                                DefaultColumnShowHideListener.of(checkIcon.element(), true));
                            FlexLayout itemElement =
                                FlexLayout.create()
                                    .appendChild(
                                        FlexItem.create()
                                            .styler(style -> style.setWidth(Unit.px.of(24)))
                                            .appendChild(checkIcon))
                                    .appendChild(
                                        FlexItem.create()
                                            .appendChild(TextNode.of(columnConfig.getTitle())));

                            columnsMenu.addAction(
                                DropdownAction.create(columnConfig.getName(), itemElement.element())
                                    .setAutoClose(false)
                                    .addSelectionHandler(
                                        value ->
                                            columnConfig.toggleDisplay(columnConfig.isHidden())));
                          }));

      columnsIcon.addClickListener(
          evt -> {
            dropDownMenu.open();
            evt.stopPropagation();
          });
      return columnsIcon.element();
    }

    /** {@inheritDoc} */
    @Override
    public void handleEvent(TableEvent event) {}
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy