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

org.dominokit.domino.ui.datatable.DataTable Maven / Gradle / Ivy

There is a newer version: 1.0.139
Show newest version
package org.dominokit.domino.ui.datatable;

import elemental2.dom.HTMLDivElement;
import elemental2.dom.HTMLTableElement;
import elemental2.dom.HTMLTableSectionElement;
import org.dominokit.domino.ui.datatable.events.OnBeforeDataChangeEvent;
import org.dominokit.domino.ui.datatable.events.TableDataUpdatedEvent;
import org.dominokit.domino.ui.datatable.events.TableEvent;
import org.dominokit.domino.ui.datatable.events.TableEventListener;
import org.dominokit.domino.ui.datatable.model.SearchContext;
import org.dominokit.domino.ui.datatable.store.DataStore;
import org.dominokit.domino.ui.utils.BaseDominoElement;
import org.dominokit.domino.ui.utils.DominoElement;
import org.dominokit.domino.ui.utils.HasSelectionSupport;

import java.util.*;
import java.util.stream.Collectors;

import static java.util.Objects.nonNull;
import static org.dominokit.domino.ui.datatable.DataTableStyles.*;
import static org.jboss.gwt.elemento.core.Elements.*;

public class DataTable extends BaseDominoElement> implements HasSelectionSupport> {

    public static final String ANY = "*";
    public static final String DATA_TABLE_ROW_FILTERED = "data-table-row-filtered";

    private final DataStore dataStore;
    private DominoElement root = DominoElement.of(div().css(TABLE_RESPONSIVE));
    private DominoElement tableElement = DominoElement.of(table().css(TABLE, TABLE_HOVER, TABLE_STRIPED));
    private TableConfig tableConfig;
    private DominoElement tbody = DominoElement.of(tbody());
    private DominoElement thead = DominoElement.of(thead());
    private List data = new ArrayList<>();
    private boolean selectable = true;
    private List> tableRows = new ArrayList<>();

    private List> selectionChangeListeners = new ArrayList<>();
    private boolean condensed = false;
    private boolean hoverable = true;
    private boolean striped = true;
    private boolean bordered = false;

    private Map> events = new HashMap<>();

    private final SearchContext searchContext = new SearchContext<>(this);

    public DataTable(TableConfig tableConfig, DataStore dataStore) {
        this.tableConfig = tableConfig;
        this.events.put(ANY, new ArrayList<>());
        this.dataStore = dataStore;
        this.addTableEventListner(ANY, dataStore);
        this.dataStore.onDataChanged(dataChangedEvent -> {
            fireTableEvent(new OnBeforeDataChangeEvent<>(this.data, dataChangedEvent.getTotalCount(), dataChangedEvent.isAppend()));
            if (dataChangedEvent.isAppend()) {
                appendData(dataChangedEvent.getNewData());
            } else {
                setData(dataChangedEvent.getNewData());
            }
            fireTableEvent(new TableDataUpdatedEvent<>(this.data, dataChangedEvent.getTotalCount()));
        });

        init();
    }

    private DataTable init() {
        tableConfig.getPlugins().forEach(plugin -> {
            DataTable.this.addTableEventListner("*", plugin);
            plugin.init(DataTable.this);
            plugin.onBeforeAddTable(DataTable.this);
        });
        tableConfig.onBeforeHeaders(this);
        tableConfig.drawHeaders(this, thead);
        tableConfig.onAfterHeaders(this);
        tableElement.appendChild(tbody);
        tableConfig.getPlugins().forEach(plugin -> plugin.onBodyAdded(DataTable.this));
        root.appendChild(tableElement);
        tableConfig.getPlugins().forEach(plugin -> plugin.onAfterAddTable(DataTable.this));
        if (!tableConfig.isLazyLoad()) {
            this.dataStore.load();
        }
        if (tableConfig.isFixed()) {
            root.style().add(TABLE_FIXED);
            tbody.style()
                    .add(TBODY_FIXED)
                    .setMaxHeight(tableConfig.getFixedBodyHeight());
        }
        super.init(this);
        return this;
    }

    public void load() {
        this.dataStore.load();
    }

    public void setData(List data) {
        this.data = data;
        tableRows.clear();
        tbody.clearElement();
        if (nonNull(data) && !data.isEmpty()) {
            addRows(data, 0);
        }

        tbody.element().scrollTop = 0.0;
    }

    public void appendData(List newData) {
        if (nonNull(this.data)) {
            addRows(newData, this.data.size());
            this.data.addAll(newData);
        } else {
            setData(newData);
        }
    }

    private void addRows(List data, int initialIndex) {
        tableConfig.getColumns()
                .forEach(ColumnConfig::clearShowHideListners);

        for (int index = 0; index < data.size(); index++) {
            TableRow tableRow = new TableRow<>(data.get(index), initialIndex + index, this);
            tableConfig.getPlugins().forEach(plugin -> plugin.onBeforeAddRow(DataTable.this, tableRow));
            tableConfig.drawRecord(DataTable.this, tableRow);
            tableRows.add(tableRow);
        }

        tableConfig.getPlugins().forEach(plugin -> plugin.onAllRowsAdded(DataTable.this));
    }

    public Collection getData() {
        return data;
    }

    @Override
    public DataTable show() {
        tableElement.style().remove(TABLE_CONDENSED);
        this.condensed = false;
        return this;
    }

    public DataTable condense() {
        show();
        tableElement.style().add(TABLE_CONDENSED);
        this.condensed = true;
        return this;
    }

    public DataTable noHover() {
        tableElement.style().remove(TABLE_HOVER);
        this.hoverable = false;
        return this;
    }

    public DataTable hovered() {
        noHover();
        tableElement.style().add(TABLE_HOVER);
        this.hoverable = true;
        return this;
    }

    public DataTable noBorder() {
        tableElement.style().remove(TABLE_BORDERED);
        this.bordered = false;
        return this;
    }

    public DataTable bordered() {
        noBorder();
        tableElement.style().add(TABLE_BORDERED);
        this.bordered = true;
        return this;
    }

    public DataTable noStripes() {
        tableElement.style().remove(TABLE_STRIPED);
        this.striped = false;
        return this;
    }

    public DataTable striped() {
        noStripes();
        tableElement.style().add(TABLE_STRIPED);
        this.striped = true;
        return this;
    }

    public DominoElement tableElement() {
        return tableElement;
    }

    public DominoElement bodyElement() {
        return tbody;
    }

    public DominoElement headerElement() {
        return thead;
    }

    public TableConfig getTableConfig() {
        return tableConfig;
    }

    public boolean isCondensed() {
        return condensed;
    }

    public boolean isHoverable() {
        return hoverable;
    }

    public boolean isStriped() {
        return striped;
    }

    public boolean isBordered() {
        return bordered;
    }

    public void filterRows(LocalRowFilter rowFilter) {
        tableRows.forEach(tableRow -> {
            if (rowFilter.filter(tableRow)) {
                tableRow.style().remove(TABLE_ROW_FILTERED);
                tableRow.removeFlag(DATA_TABLE_ROW_FILTERED);
                tableRow.fireUpdate();
            } else {
                tableRow.style().add(TABLE_ROW_FILTERED);
                tableRow.setFlag(DATA_TABLE_ROW_FILTERED, "true");
                tableRow.deselect();
                tableRow.fireUpdate();
            }
        });
    }

    public void clearRowFilters() {
        tableRows.stream().filter(tableRow -> nonNull(tableRow.getFlag(DATA_TABLE_ROW_FILTERED)))
                .forEach(tableRow -> {
                    tableRow.style().remove(TABLE_ROW_FILTERED);
                    tableRow.removeFlag(DATA_TABLE_ROW_FILTERED);
                    tableRow.fireUpdate();
                });
    }

    @Override
    public HTMLDivElement element() {
        return root.element();
    }

    @Override
    public List> getSelectedItems() {
        return tableRows.stream().filter(TableRow::isSelected).collect(Collectors.toList());
    }

    public List getSelectedRecords() {
        return getSelectedItems().stream().map(TableRow::getRecord).collect(Collectors.toList());
    }

    @Override
    public List> getItems() {
        return tableRows;
    }

    @Override
    public void onSelectionChange(TableRow source) {
        selectionChangeListeners.forEach(selectionChangeListener -> selectionChangeListener.onSelectionChanged(getSelectedItems(), getSelectedRecords()));
    }

    @Override
    public void selectAll() {
        selectAll((table, tableRow) -> true);
    }

    public void selectAll(SelectionCondition selectionCondition) {
        if (tableConfig.isMultiSelect() && !tableRows.isEmpty()) {
            for (TableRow tableRow : tableRows) {
                if (selectionCondition.isAllowSelection(this, tableRow)) {
                    tableRow.select();
                }
            }
            onSelectionChange(tableRows.get(0));
        }
    }

    @Override
    public void deselectAll() {
        deselectAll((table, tableRow) -> true);
    }

    public void deselectAll(SelectionCondition selectionCondition) {
        if (!tableRows.isEmpty()) {
            for (TableRow tableRow : tableRows) {
                if (tableRow.isSelected()) {
                    if (selectionCondition.isAllowSelection(this, tableRow)) {
                        tableRow.deselect();
                    }
                }
            }
            onSelectionChange(tableRows.get(0));
        }
    }

    @Override
    public boolean isSelectable() {
        return this.selectable;
    }

    public void addSelectionListener(SelectionChangeListener selectionChangeListener) {
        this.selectionChangeListeners.add(selectionChangeListener);
    }

    public void removeSelectionListener(SelectionChangeListener selectionChangeListener) {
        this.selectionChangeListeners.remove(selectionChangeListener);
    }

    public void addTableEventListner(String type, TableEventListener listener) {
        if (!events.containsKey(type)) {
            events.put(type, new ArrayList<>());
        }
        events.get(type).add(listener);
    }

    public void removeTableListener(String type, TableEventListener listener) {
        if (events.containsKey(type)) {
            events.get(type).remove(listener);
        }
    }

    public void fireTableEvent(TableEvent tableEvent) {
        if (events.containsKey(tableEvent.getType())) {
            events.get(tableEvent.getType()).forEach(listener -> listener.handleEvent(tableEvent));
        }

        events.get(ANY).forEach(listener -> listener.handleEvent(tableEvent));
    }

    public SearchContext getSearchContext() {
        return searchContext;
    }

    @FunctionalInterface
    public interface SelectionChangeListener {
        void onSelectionChanged(List> selectedTableRows, List selectedRecords);
    }

    public interface LocalRowFilter {
        boolean filter(TableRow tableRow);
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy