Improve not in make proposal phase state

This commit is contained in:
Christoph Atteneder 2019-02-05 14:57:55 +01:00
parent 67b255562f
commit 20a1cf567f
No known key found for this signature in database
GPG Key ID: CD5DC1C529CDFD3B
4 changed files with 119 additions and 37 deletions

View File

@ -0,0 +1,43 @@
/*
* This file is part of Bisq.
*
* Bisq is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bisq is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.dao;
import bisq.core.dao.state.model.governance.DaoPhase;
import bisq.core.locale.Res;
import bisq.core.util.BSFormatter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
public class DaoUtil {
public static String getPhaseDuration(int height, DaoPhase.Phase phase, DaoFacade daoFacade, BSFormatter formatter) {
long start = daoFacade.getFirstBlockOfPhaseForDisplay(height, phase);
long end = daoFacade.getLastBlockOfPhaseForDisplay(height, phase);
long duration = daoFacade.getDurationForPhaseForDisplay(phase);
long now = new Date().getTime();
SimpleDateFormat dateFormatter = new SimpleDateFormat("dd MMM", Locale.getDefault());
SimpleDateFormat timeFormatter = new SimpleDateFormat("HH:mm", Locale.getDefault());
String startDateTime = formatter.formatDateTime(new Date(now + (start - height) * 10 * 60 * 1000L), dateFormatter, timeFormatter);
String endDateTime = formatter.formatDateTime(new Date(now + (end - height) * 10 * 60 * 1000L), dateFormatter, timeFormatter);
String durationTime = formatter.formatDurationAsWords(duration * 10 * 60 * 1000, false, false);
return Res.get("dao.cycle.phaseDuration", duration, durationTime, start, end, startDateTime, endDateTime);
}
}

View File

@ -1205,6 +1205,7 @@ dao.cycle.overview.headline=Voting cycle overview
dao.cycle.currentPhase=Current phase
dao.cycle.currentBlockHeight=Current block height
dao.cycle.proposal=Proposal phase
dao.cycle.proposal.next=Next proposal phase
dao.cycle.blindVote=Blind vote phase
dao.cycle.voteReveal=Vote reveal phase
dao.cycle.voteResult=Vote result
@ -1575,6 +1576,7 @@ dao.proposal.votes.header=Vote on all proposals
dao.proposal.votes.header.voted=My vote
dao.proposal.myVote.button=Vote on all proposals
dao.proposal.create.selectProposalType=Select proposal type
dao.proposal.create.phase.inactive=Please wait until the next proposal phase
dao.proposal.create.proposalType=Proposal type
dao.proposal.create.createNew=Make new proposal
dao.proposal.create.create.button=Make proposal

View File

@ -20,10 +20,10 @@ package bisq.desktop.main.dao.governance.dashboard;
import bisq.desktop.common.view.ActivatableView;
import bisq.desktop.common.view.FxmlView;
import bisq.desktop.main.dao.governance.PhasesView;
import bisq.desktop.util.FormBuilder;
import bisq.desktop.util.Layout;
import bisq.core.dao.DaoFacade;
import bisq.core.dao.DaoUtil;
import bisq.core.dao.governance.period.PeriodService;
import bisq.core.dao.state.DaoStateListener;
import bisq.core.dao.state.model.governance.DaoPhase;
@ -35,11 +35,6 @@ import javax.inject.Inject;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import static bisq.desktop.util.FormBuilder.addTitledGroupBg;
import static bisq.desktop.util.FormBuilder.addTopLabelReadOnlyTextField;
@ -76,11 +71,11 @@ public class GovernanceDashboardView extends ActivatableView<GridPane, Void> imp
addTitledGroupBg(root, ++gridRow, 6, Res.get("dao.cycle.overview.headline"), Layout.GROUP_DISTANCE);
currentBlockHeightTextField = addTopLabelReadOnlyTextField(root, gridRow, Res.get("dao.cycle.currentBlockHeight"),
Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
currentPhaseTextField = FormBuilder.addTopLabelReadOnlyTextField(root, ++gridRow, Res.get("dao.cycle.currentPhase")).second;
proposalTextField = FormBuilder.addTopLabelReadOnlyTextField(root, ++gridRow, Res.get("dao.cycle.proposal")).second;
blindVoteTextField = FormBuilder.addTopLabelReadOnlyTextField(root, ++gridRow, Res.get("dao.cycle.blindVote")).second;
voteRevealTextField = FormBuilder.addTopLabelReadOnlyTextField(root, ++gridRow, Res.get("dao.cycle.voteReveal")).second;
voteResultTextField = FormBuilder.addTopLabelReadOnlyTextField(root, ++gridRow, Res.get("dao.cycle.voteResult")).second;
currentPhaseTextField = addTopLabelReadOnlyTextField(root, ++gridRow, Res.get("dao.cycle.currentPhase")).second;
proposalTextField = addTopLabelReadOnlyTextField(root, ++gridRow, Res.get("dao.cycle.proposal")).second;
blindVoteTextField = addTopLabelReadOnlyTextField(root, ++gridRow, Res.get("dao.cycle.blindVote")).second;
voteRevealTextField = addTopLabelReadOnlyTextField(root, ++gridRow, Res.get("dao.cycle.voteReveal")).second;
voteResultTextField = addTopLabelReadOnlyTextField(root, ++gridRow, Res.get("dao.cycle.voteResult")).second;
}
@Override
@ -131,22 +126,9 @@ public class GovernanceDashboardView extends ActivatableView<GridPane, Void> imp
phase = periodService.getPhaseForHeight(height + 1);
}
currentPhaseTextField.setText(Res.get("dao.phase." + phase.name()));
proposalTextField.setText(getPhaseDuration(height, DaoPhase.Phase.PROPOSAL));
blindVoteTextField.setText(getPhaseDuration(height, DaoPhase.Phase.BLIND_VOTE));
voteRevealTextField.setText(getPhaseDuration(height, DaoPhase.Phase.VOTE_REVEAL));
voteResultTextField.setText(getPhaseDuration(height, DaoPhase.Phase.RESULT));
}
private String getPhaseDuration(int height, DaoPhase.Phase phase) {
long start = daoFacade.getFirstBlockOfPhaseForDisplay(height, phase);
long end = daoFacade.getLastBlockOfPhaseForDisplay(height, phase);
long duration = daoFacade.getDurationForPhaseForDisplay(phase);
long now = new Date().getTime();
SimpleDateFormat dateFormatter = new SimpleDateFormat("dd MMM", Locale.getDefault());
SimpleDateFormat timeFormatter = new SimpleDateFormat("HH:mm", Locale.getDefault());
String startDateTime = formatter.formatDateTime(new Date(now + (start - height) * 10 * 60 * 1000L), dateFormatter, timeFormatter);
String endDateTime = formatter.formatDateTime(new Date(now + (end - height) * 10 * 60 * 1000L), dateFormatter, timeFormatter);
String durationTime = formatter.formatDurationAsWords(duration * 10 * 60 * 1000, false, false);
return Res.get("dao.cycle.phaseDuration", duration, durationTime, start, end, startDateTime, endDateTime);
proposalTextField.setText(DaoUtil.getPhaseDuration(height, DaoPhase.Phase.PROPOSAL, daoFacade, formatter));
blindVoteTextField.setText(DaoUtil.getPhaseDuration(height, DaoPhase.Phase.BLIND_VOTE, daoFacade, formatter));
voteRevealTextField.setText(DaoUtil.getPhaseDuration(height, DaoPhase.Phase.VOTE_REVEAL, daoFacade, formatter));
voteResultTextField.setText(DaoUtil.getPhaseDuration(height, DaoPhase.Phase.RESULT, daoFacade, formatter));
}
}

View File

@ -21,16 +21,17 @@ import bisq.desktop.Navigation;
import bisq.desktop.common.view.ActivatableView;
import bisq.desktop.common.view.FxmlView;
import bisq.desktop.components.InputTextField;
import bisq.desktop.components.TitledGroupBg;
import bisq.desktop.main.dao.governance.PhasesView;
import bisq.desktop.main.dao.governance.ProposalDisplay;
import bisq.desktop.main.overlays.popups.Popup;
import bisq.desktop.util.FormBuilder;
import bisq.desktop.util.GUIUtil;
import bisq.desktop.util.Layout;
import bisq.core.btc.exceptions.InsufficientBsqException;
import bisq.core.btc.setup.WalletsSetup;
import bisq.core.dao.DaoFacade;
import bisq.core.dao.DaoUtil;
import bisq.core.dao.exceptions.ValidationException;
import bisq.core.dao.governance.bond.Bond;
import bisq.core.dao.governance.param.Param;
@ -51,6 +52,7 @@ import bisq.asset.Asset;
import bisq.network.p2p.P2PService;
import bisq.common.app.DevEnv;
import bisq.common.util.Tuple3;
import org.bitcoinj.core.Coin;
import org.bitcoinj.core.InsufficientMoneyException;
@ -60,8 +62,15 @@ import javax.inject.Inject;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.VBox;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ChangeListener;
import javafx.collections.FXCollections;
@ -76,7 +85,9 @@ import java.util.concurrent.atomic.AtomicBoolean;
import javax.annotation.Nullable;
import static bisq.desktop.util.FormBuilder.addButtonAfterGroup;
import static bisq.desktop.util.FormBuilder.addComboBox;
import static bisq.desktop.util.FormBuilder.addTitledGroupBg;
import static bisq.desktop.util.FormBuilder.addTopLabelReadOnlyTextField;
import static com.google.common.base.Preconditions.checkNotNull;
@FxmlView
@ -95,6 +106,13 @@ public class MakeProposalView extends ActivatableView<GridPane, Void> implements
private Button makeProposalButton;
private ComboBox<ProposalType> proposalTypeComboBox;
private ChangeListener<ProposalType> proposalTypeChangeListener;
private TextField nextProposalTextField;
private TitledGroupBg proposalTitledGroup;
private VBox nextProposalBox;
private BooleanProperty isProposalPhase = new SimpleBooleanProperty(false);
private StringProperty proposalGroupTitle = new SimpleStringProperty(Res.get("dao.proposal.create.phase.inactive"));
@Nullable
private ProposalType selectedProposalType;
private int gridRow;
@ -128,8 +146,13 @@ public class MakeProposalView extends ActivatableView<GridPane, Void> implements
public void initialize() {
gridRow = phasesView.addGroup(root, gridRow);
addTitledGroupBg(root, ++gridRow, 1, Res.get("dao.proposal.create.selectProposalType"), Layout.GROUP_DISTANCE);
proposalTypeComboBox = FormBuilder.addComboBox(root, gridRow,
proposalTitledGroup = addTitledGroupBg(root, ++gridRow, 2, proposalGroupTitle.get(), Layout.GROUP_DISTANCE);
final Tuple3<Label, TextField, VBox> nextProposalPhaseTuple = addTopLabelReadOnlyTextField(root, gridRow,
Res.get("dao.cycle.proposal.next"),
Layout.FIRST_ROW_AND_GROUP_DISTANCE);
nextProposalBox = nextProposalPhaseTuple.third;
nextProposalTextField = nextProposalPhaseTuple.second;
proposalTypeComboBox = addComboBox(root, gridRow,
Res.get("dao.proposal.create.proposalType"), Layout.FIRST_ROW_AND_GROUP_DISTANCE);
proposalTypeComboBox.setMaxWidth(300);
proposalTypeComboBox.setConverter(new StringConverter<>() {
@ -156,6 +179,8 @@ public class MakeProposalView extends ActivatableView<GridPane, Void> implements
@Override
protected void activate() {
addBindings();
phasesView.activate();
daoFacade.addBsqStateListener(this);
@ -169,6 +194,8 @@ public class MakeProposalView extends ActivatableView<GridPane, Void> implements
@Override
protected void deactivate() {
removeBindings();
phasesView.deactivate();
daoFacade.removeBsqStateListener(this);
@ -178,6 +205,25 @@ public class MakeProposalView extends ActivatableView<GridPane, Void> implements
makeProposalButton.setOnAction(null);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Bindings, Listeners
///////////////////////////////////////////////////////////////////////////////////////////
private void addBindings() {
proposalTypeComboBox.managedProperty().bind(isProposalPhase);
proposalTypeComboBox.visibleProperty().bind(isProposalPhase);
nextProposalBox.managedProperty().bind(isProposalPhase.not());
nextProposalBox.visibleProperty().bind(isProposalPhase.not());
proposalTitledGroup.textProperty().bind(proposalGroupTitle);
}
private void removeBindings() {
proposalTypeComboBox.managedProperty().unbind();
proposalTypeComboBox.visibleProperty().unbind();
nextProposalBox.managedProperty().unbind();
nextProposalBox.visibleProperty().unbind();
proposalTitledGroup.textProperty().unbind();
}
///////////////////////////////////////////////////////////////////////////////////////////
// DaoStateListener
@ -185,12 +231,18 @@ public class MakeProposalView extends ActivatableView<GridPane, Void> implements
@Override
public void onNewBlockHeight(int height) {
boolean isProposalPhase = daoFacade.isInPhaseButNotLastBlock(DaoPhase.Phase.PROPOSAL);
proposalTypeComboBox.setDisable(!isProposalPhase);
if (!isProposalPhase)
isProposalPhase.set(daoFacade.isInPhaseButNotLastBlock(DaoPhase.Phase.PROPOSAL));
if (isProposalPhase.get()) {
proposalGroupTitle.set(Res.get("dao.proposal.create.selectProposalType"));
} else {
proposalGroupTitle.set(Res.get("dao.proposal.create.phase.inactive"));
proposalTypeComboBox.getSelectionModel().clearSelection();
updateTimeUntilNextProposalPhase(height);
}
}
@Override
public void onParseBlockChainComplete() {
}
@ -200,6 +252,10 @@ public class MakeProposalView extends ActivatableView<GridPane, Void> implements
// Private
///////////////////////////////////////////////////////////////////////////////////////////
private void updateTimeUntilNextProposalPhase(int height) {
nextProposalTextField.setText(DaoUtil.getPhaseDuration(height, DaoPhase.Phase.PROPOSAL, daoFacade, btcFormatter));
}
private void publishMyProposal(ProposalType type) {
try {
ProposalWithTransaction proposalWithTransaction = getProposalWithTransaction(type);
@ -378,9 +434,8 @@ public class MakeProposalView extends ActivatableView<GridPane, Void> implements
}
});
proposalDisplay.getComboBoxes().stream()
.filter(Objects::nonNull).forEach(comboBox -> {
inputsValid.set(inputsValid.get() && comboBox.getSelectionModel().getSelectedItem() != null);
});
.filter(Objects::nonNull).forEach(comboBox -> inputsValid.set(inputsValid.get() &&
comboBox.getSelectionModel().getSelectedItem() != null));
InputTextField linkInputTextField = proposalDisplay.linkInputTextField;
inputsValid.set(inputsValid.get() &&