org.bklab.flow.dialog.timerange.TimeRangeDialog Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of fluent-vaadin-flow Show documentation
Show all versions of fluent-vaadin-flow Show documentation
Broderick Labs for fluent vaadin flow. Inherits common Vaadin components.
package org.bklab.flow.dialog.timerange;
import com.vaadin.flow.component.ClickEvent;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.datetimepicker.DateTimePicker;
import com.vaadin.flow.component.formlayout.FormLayout;
import com.vaadin.flow.component.icon.VaadinIcon;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.server.VaadinSession;
import dev.mett.vaadin.tooltip.Tooltips;
import org.apache.commons.collections4.map.UnmodifiableMap;
import org.bklab.flow.components.button.FluentButton;
import org.bklab.flow.dialog.ErrorDialog;
import org.bklab.flow.dialog.ModalDialog;
import org.bklab.flow.factory.*;
import org.bklab.flow.layout.ToolBar;
import org.bklab.flow.util.element.HasSaveListeners;
import org.bklab.flow.util.url.QueryParameterBuilder;
import org.bklab.flow.util.url.QueryParameterUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.*;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import static com.vaadin.flow.component.button.ButtonVariant.LUMO_PRIMARY;
public class TimeRangeDialog extends ModalDialog implements ITimeRangeSupplier, HasSaveListeners {
private static final Logger logger = LoggerFactory.getLogger(TimeRangeDialog.class);
private final DateTimePicker minDatetimePicker;
private final DateTimePicker maxDatetimePicker;
private final TextField statusField;
private final Map buttonMap = new LinkedHashMap<>();
private final Map timeRangeSupplierMap = new LinkedHashMap<>();
private final List> saveListeners = new ArrayList<>();
private ITimeRangeSupplier timeRangeSupplier;
private ITimeRangeSupplier globalTimeRangeSupplier;
private boolean memoryMode = true;
private int defaultMaxDurationDay = Integer.MAX_VALUE;
private Supplier globalMinDateTime = () -> LocalDateTime.MIN;
private Supplier globalMaxDateTime = () -> LocalDateTime.MAX;
private String defaultSelectName;
private ITimeRangeSupplier[] initTimeRangeSupplier;
{
this.minDatetimePicker = new DateTimePickerFactory().startTimePlaceholder().lumoSmall()
.widthFull().clearButtonVisible(false).step(Duration.ofMinutes(5)).get();
this.maxDatetimePicker = new DateTimePickerFactory().endTimePlaceholder().lumoSmall()
.widthFull().clearButtonVisible(false).step(Duration.ofMinutes(5)).get();
this.statusField = new TextFieldFactory().lumoSmall().width("12em").readOnly()
.suffixComponent(new ButtonFactory().clickListener(e -> {
if (!isOpened()) open();
}).icon(VaadinIcon.CLOCK).lumoIcon().lumoSmall().lumoTertiaryInline().get()).get();
}
public TimeRangeDialog() {
}
public TimeRangeDialog(ITimeRangeSupplier... initTimeRangeSupplier) {
initTimeRangeSupplier(initTimeRangeSupplier);
}
public TimeRangeDialog initTimeRangeSupplier(ITimeRangeSupplier... initTimeRangeSupplier) {
this.initTimeRangeSupplier = initTimeRangeSupplier;
return this;
}
public static ITimeRangeSupplier createTimeRangeSupplier(QueryParameterUtil util) {
long minDatetime = util.getLong("minDatetime");
long maxDatetime = util.getLong("maxDatetime");
return TimeRangeSupplier.appoint(
LocalDateTime.ofEpochSecond(minDatetime, 0, ZoneOffset.ofHours(8)),
LocalDateTime.ofEpochSecond(maxDatetime, 0, ZoneOffset.ofHours(8))
);
}
public static ITimeRangeSupplier createTimeRangeSupplier(int maxDuration, QueryParameterUtil util) {
long minDatetime = util.getLong("minDatetime");
long maxDatetime = util.getLong("maxDatetime");
if (maxDatetime > 0 && minDatetime <= 0 || maxDatetime - minDatetime > maxDuration)
minDatetime = maxDatetime - maxDuration;
if (minDatetime > 0 && maxDatetime <= 0 || maxDatetime > minDatetime + maxDuration)
maxDatetime = minDatetime + maxDuration;
return TimeRangeSupplier.appoint(
LocalDateTime.ofEpochSecond(minDatetime, 0, ZoneOffset.ofHours(8)),
LocalDateTime.ofEpochSecond(maxDatetime, 0, ZoneOffset.ofHours(8))
);
}
public int getDefaultMaxDurationDay() {
return defaultMaxDurationDay;
}
public TimeRangeDialog setDefaultMaxDurationDay(int defaultMaxDurationDay) {
this.defaultMaxDurationDay = defaultMaxDurationDay;
return this;
}
public Supplier getGlobalMinDateTime() {
return globalMinDateTime;
}
public TimeRangeDialog setGlobalMinDateTime(Supplier globalMinDateTime) {
this.globalMinDateTime = globalMinDateTime;
return this;
}
public Supplier getGlobalMaxDateTime() {
return globalMaxDateTime;
}
public TimeRangeDialog setGlobalMaxDateTime(Supplier globalMaxDateTime) {
this.globalMaxDateTime = globalMaxDateTime;
return this;
}
public TimeRangeDialog defaultInitTimeRangeSupplier() {
return this.initTimeRangeSupplier(
TimeRangeSupplier.lastMinutes(5),
TimeRangeSupplier.lastMinutes(15),
TimeRangeSupplier.lastMinutes(30),
TimeRangeSupplier.lastHours(1),
TimeRangeSupplier.lastHours(6),
TimeRangeSupplier.lastHours(12),
TimeRangeSupplier.lastDays(1),
TimeRangeSupplier.lastDays(3),
TimeRangeSupplier.lastDays(7),
TimeRangeSupplier.lastDays(15),
TimeRangeSupplier.lastDays(30)
);
}
public TimeRangeDialog globalTimeRangeSupplier(ITimeRangeSupplier globalTimeRangeSupplier) {
this.globalTimeRangeSupplier = globalTimeRangeSupplier;
return this;
}
public TimeRangeDialog globalTimeRangeSupplierToday() {
this.globalTimeRangeSupplier = new ITimeRangeSupplier() {
@Override
public String getName() {
return "今天";
}
@Override
public LocalDateTime getMin() {
return LocalDateTime.of(LocalDate.now(), LocalTime.MIN);
}
@Override
public LocalDateTime getMax() {
return LocalDateTime.of(LocalDate.now(), LocalTime.MAX);
}
};
return this;
}
public String getDefaultSelectName() {
return defaultSelectName;
}
public TimeRangeDialog setDefaultSelectName(String defaultSelectName) {
this.defaultSelectName = defaultSelectName;
return this;
}
public static String extend(QueryParameterUtil util, Map> map) {
ITimeRangeSupplier timeRangeSupplier = createTimeRangeSupplier(util);
if (map != null && !(map instanceof UnmodifiableMap)) {
map.put("minDatetime", timeRangeSupplier::getMin);
map.put("maxDatetime", timeRangeSupplier::getMax);
}
return timeRangeSupplier.getLabel();
}
public static void write(Map> parameterMap, QueryParameterBuilder builder) {
Optional.ofNullable(parameterMap.get("minDatetime")).map(Supplier::get)
.map(d -> ((LocalDateTime) d).toEpochSecond(ZoneOffset.ofHours(8)))
.ifPresent(s -> builder.add("minDatetime", s));
Optional.ofNullable(parameterMap.get("maxDatetime")).map(Supplier::get)
.map(d -> ((LocalDateTime) d).toEpochSecond(ZoneOffset.ofHours(8)))
.ifPresent(s -> builder.add("maxDatetime", s));
}
public ITimeRangeSupplier getDefaultGlobalTimeRangeSupplier() {
return new ITimeRangeSupplier() {
private LocalDateTime globalMin = null;
@Override
public String getName() {
return "全部时间";
}
@Override
public LocalDateTime getMin() {
if (globalMin == null) {
globalMin = globalMinDateTime.get();
}
return globalMin;
}
@Override
public LocalDateTime getMax() {
return globalMaxDateTime.get();
}
};
}
public TimeRangeDialog build() {
if (this.timeRangeSupplier == null) this.timeRangeSupplier = TimeRangeSupplier.lastDays(30);
if (this.globalTimeRangeSupplier == null) this.globalTimeRangeSupplier = getDefaultGlobalTimeRangeSupplier();
if (initTimeRangeSupplier == null) defaultInitTimeRangeSupplier();
minDatetimePicker.setMin(globalTimeRangeSupplier.getMin());
maxDatetimePicker.setMin(globalTimeRangeSupplier.getMin());
minDatetimePicker.setMax(globalTimeRangeSupplier.getMax());
maxDatetimePicker.setMax(globalTimeRangeSupplier.getMax());
minDatetimePicker.addValueChangeListener(e -> {
if (defaultMaxDurationDay == Integer.MAX_VALUE) return;
LocalDateTime minDateTime = e.getValue();
if (minDateTime == null) return;
LocalDateTime maxDateTime = minDateTime.plusDays(defaultMaxDurationDay);
maxDatetimePicker.getOptionalValue().ifPresent(value -> {
if (maxDateTime.isBefore(value)) {
maxDatetimePicker.setValue(maxDateTime);
}
});
});
maxDatetimePicker.addValueChangeListener(e -> {
if (defaultMaxDurationDay == Integer.MAX_VALUE) return;
LocalDateTime maxDateTime = e.getValue();
if (maxDateTime == null) return;
LocalDateTime minDateTime = maxDateTime.minusDays(defaultMaxDurationDay);
minDatetimePicker.getOptionalValue().ifPresent(value -> {
if (minDateTime.isAfter(value)) {
minDatetimePicker.setValue(minDateTime);
}
});
});
FormLayout appointForm = new FormLayoutFactory().visible(false).style("padding-top", "1em")
.formItem(minDatetimePicker, "开始时间:").formItem(maxDatetimePicker, "结束时间:")
.widthFull().componentFullWidth().formItemAlignEnd().formItemAlignVerticalCenter().get();
content(createTimeSelector(appointForm), appointForm);
Optional.ofNullable(defaultSelectName).ifPresent(value -> {
Optional.ofNullable(buttonMap.get(value)).ifPresent(Button::clickInClient);
Optional.ofNullable(timeRangeSupplierMap.get(value)).ifPresent(this::setTimeRangeSupplier);
});
AtomicReference lastSelectRangeSupplier = new AtomicReference<>(timeRangeSupplier);
addButton(FluentButton.cancelButton().asFactory().clickListener(event -> {
close();
ITimeRangeSupplier timeRangeSupplier = lastSelectRangeSupplier.get();
minDatetimePicker.setValue(timeRangeSupplier.getMin());
maxDatetimePicker.setValue(timeRangeSupplier.getMax());
selectButton(timeRangeSupplier.getName());
appointForm.setVisible("自定义".equals(timeRangeSupplier.getName()));
}).get());
addButton(new FluentButton(VaadinIcon.CHECK, "确定", this::processSave).primary());
title("选择时间").width("720px", "720px", "90vw").setMinHeight("350px");
addSaveListeners(e -> doMemory());
addSaveListeners(e -> lastSelectRangeSupplier.set(getTimeRangeSupplier()));
doRestore();
refreshStatusField();
return this;
}
public TimeRangeDialog write(QueryParameterBuilder builder) {
Function function = d -> d.toEpochSecond(ZoneOffset.ofHours(8));
builder.add("minDatetime", function.apply(getMin()));
builder.add("maxDatetime", function.apply(getMax()));
builder.add("time-range", URLEncoder.encode(getTimeRangeSupplier().getName(), StandardCharsets.UTF_8));
return this;
}
public TimeRangeDialog read(QueryParameterUtil util) {
if (util.decode("time-range") != null || (util.get("minDatetime") != null && util.get("maxDatetime") != null)) {
setValue(Optional.ofNullable(util.decode("time-range"))
.map(timeRange -> "自定义".equals(timeRange) ? null : timeRange)
.map(timeRangeSupplierMap::get).orElse(createTimeRangeSupplier(util)));
}
refreshStatusField();
return this;
}
public TimeRangeDialog setValue(ITimeRangeSupplier timeRangeSupplier) {
if (timeRangeSupplier == null) return this;
this.timeRangeSupplier = timeRangeSupplier;
refreshStatusField();
selectButton(timeRangeSupplier.getName());
return this;
}
public TimeRangeDialog setValue(String timeRangeSupplier) {
try {
timeRangeSupplier = URLDecoder.decode(timeRangeSupplier, StandardCharsets.UTF_8);
} catch (Exception ignore) {
}
return this.setValue(timeRangeSupplierMap.get(timeRangeSupplier));
}
private void selectButton(String name) {
buttonMap.values().forEach(a -> a.removeThemeVariants(LUMO_PRIMARY));
Optional.ofNullable(buttonMap.getOrDefault(name, buttonMap.get("自定义")))
.ifPresent(a -> a.addThemeVariants(LUMO_PRIMARY));
}
public TimeRangeDialog today() {
this.timeRangeSupplier = TimeRangeSupplier.appoint(
LocalDateTime.of(LocalDate.now(), LocalTime.MIN),
LocalDateTime.of(LocalDate.now(), LocalTime.MAX), "今天");
minDatetimePicker.setValue(timeRangeSupplier.getMin());
maxDatetimePicker.setValue(timeRangeSupplier.getMax());
refreshStatusField();
return this;
}
public TimeRangeDialog recentOneDay() {
Optional.ofNullable(buttonMap.get("最近一天")).ifPresent(Button::clickInClient);
return this;
}
public TimeRangeDialog init(QueryParameterUtil util) {
this.timeRangeSupplier = createTimeRangeSupplier(util);
refreshStatusField();
return this;
}
private void processSave(ClickEvent
© 2015 - 2025 Weber Informatics LLC | Privacy Policy