SEPA Account - possibility to modify accepted countries

This commit is contained in:
xyzmaker123 2022-01-10 10:52:25 +01:00
parent ce76389402
commit b3bf1903be
No known key found for this signature in database
GPG key ID: 47689699B7B0AAFC
12 changed files with 110 additions and 143 deletions

View file

@ -247,4 +247,8 @@ public abstract class PaymentAccount implements PersistablePayload {
public String getMessageForAccountCreation() {
return null;
}
public void revertChanges() {
}
}

View file

@ -78,4 +78,9 @@ public final class SepaAccount extends CountryBasedPaymentAccount implements Ban
public void removeAcceptedCountry(String countryCode) {
((SepaAccountPayload) paymentAccountPayload).removeAcceptedCountry(countryCode);
}
@Override
public void revertChanges() {
((SepaAccountPayload) paymentAccountPayload).revertChanges();
}
}

View file

@ -78,4 +78,9 @@ public final class SepaInstantAccount extends CountryBasedPaymentAccount impleme
public void removeAcceptedCountry(String countryCode) {
((SepaInstantAccountPayload) paymentAccountPayload).removeAcceptedCountry(countryCode);
}
@Override
public void revertChanges() {
((SepaInstantAccountPayload) paymentAccountPayload).revertChanges();
}
}

View file

@ -54,6 +54,7 @@ public final class SepaAccountPayload extends CountryBasedPaymentAccountPayload
// Don't use a set here as we need a deterministic ordering, otherwise the contract hash does not match
private final List<String> acceptedCountryCodes;
private final List<String> persistedAcceptedCountryCodes = new ArrayList<>();
public SepaAccountPayload(String paymentMethod, String id, List<Country> acceptedCountries) {
super(paymentMethod, id);
@ -90,6 +91,7 @@ public final class SepaAccountPayload extends CountryBasedPaymentAccountPayload
this.bic = bic;
this.email = email;
this.acceptedCountryCodes = acceptedCountryCodes;
persistedAcceptedCountryCodes.addAll(acceptedCountryCodes);
}
@Override
@ -138,6 +140,11 @@ public final class SepaAccountPayload extends CountryBasedPaymentAccountPayload
acceptedCountryCodes.remove(countryCode);
}
public void revertChanges() {
acceptedCountryCodes.clear();
acceptedCountryCodes.addAll(persistedAcceptedCountryCodes);
}
@Override
public String getPaymentDetails() {
return Res.get(paymentMethodId) + " - " + Res.getWithCol("payment.account.owner") + " " + holderName + ", IBAN: " +

View file

@ -53,6 +53,7 @@ public final class SepaInstantAccountPayload extends CountryBasedPaymentAccountP
// Don't use a set here as we need a deterministic ordering, otherwise the contract hash does not match
private final List<String> acceptedCountryCodes;
private final List<String> persistedAcceptedCountryCodes = new ArrayList<>();
public SepaInstantAccountPayload(String paymentMethod, String id, List<Country> acceptedCountries) {
super(paymentMethod, id);
@ -87,6 +88,7 @@ public final class SepaInstantAccountPayload extends CountryBasedPaymentAccountP
this.iban = iban;
this.bic = bic;
this.acceptedCountryCodes = acceptedCountryCodes;
persistedAcceptedCountryCodes.addAll(acceptedCountryCodes);
}
@Override
@ -133,6 +135,11 @@ public final class SepaInstantAccountPayload extends CountryBasedPaymentAccountP
acceptedCountryCodes.remove(countryCode);
}
public void revertChanges() {
acceptedCountryCodes.clear();
acceptedCountryCodes.addAll(persistedAcceptedCountryCodes);
}
@Override
public String getPaymentDetails() {
return Res.get(paymentMethodId) + " - " + Res.getWithCol("payment.account.owner") + " " + holderName + ", IBAN: " +

View file

@ -1,5 +1,6 @@
package bisq.desktop.components.paymentmethods;
import bisq.desktop.components.AutoTooltipCheckBox;
import bisq.desktop.components.InputTextField;
import bisq.desktop.util.FormBuilder;
@ -22,13 +23,13 @@ import com.jfoenix.controls.JFXTextField;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ComboBox;
import javafx.scene.control.TextField;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.util.StringConverter;
import java.util.ArrayList;
import java.util.List;
import static bisq.desktop.util.FormBuilder.addTopLabelWithVBox;
@ -38,8 +39,6 @@ public abstract class GeneralSepaForm extends PaymentMethodForm {
static final String BIC = "BIC";
static final String IBAN = "IBAN";
final List<CheckBox> euroCountryCheckBoxes = new ArrayList<>();
final List<CheckBox> nonEuroCountryCheckBoxes = new ArrayList<>();
private TextField currencyTextField;
InputTextField ibanInputTextField;
@ -75,21 +74,34 @@ public abstract class GeneralSepaForm extends PaymentMethodForm {
Country selectedItem = countryComboBox.getSelectionModel().getSelectedItem();
paymentAccount.setCountry(selectedItem);
updateCountriesSelection(euroCountryCheckBoxes);
updateCountriesSelection(nonEuroCountryCheckBoxes);
updateFromInputs();
});
}
void addCountriesGrid(String title, List<CheckBox> checkBoxList,
List<Country> dataProvider) {
void addCountriesGrid(String title, List<Country> countries) {
FlowPane flowPane = FormBuilder.addTopLabelFlowPane(gridPane, ++gridRow, title, 0).second;
flowPane.setId("flow-pane-checkboxes-bg");
dataProvider.forEach(country ->
fillUpFlowPaneWithCountries(checkBoxList, flowPane, country));
updateCountriesSelection(checkBoxList);
countries.forEach(country -> {
CheckBox checkBox = new AutoTooltipCheckBox(country.code);
checkBox.setUserData(country.code);
checkBox.setSelected(isCountryAccepted(country.code));
checkBox.setMouseTransparent(false);
checkBox.setMinWidth(45);
checkBox.setMaxWidth(45);
checkBox.setTooltip(new Tooltip(country.name));
checkBox.setOnAction(event -> {
if (checkBox.isSelected()) {
addAcceptedCountry(country.code);
} else {
removeAcceptedCountry(country.code);
}
updateAllInputsValid();
});
flowPane.getChildren().add(checkBox);
});
}
ComboBox<Country> addCountrySelection() {
@ -126,6 +138,5 @@ public abstract class GeneralSepaForm extends PaymentMethodForm {
return countryComboBox;
}
abstract void updateCountriesSelection(List<CheckBox> checkBoxList);
abstract boolean isCountryAccepted(String countryCode);
}

View file

@ -312,27 +312,6 @@ public abstract class PaymentMethodForm {
flowPane.getChildren().add(checkBox);
}
void fillUpFlowPaneWithCountries(List<CheckBox> checkBoxList, FlowPane flowPane, Country country) {
final String countryCode = country.code;
CheckBox checkBox = new AutoTooltipCheckBox(countryCode);
checkBox.setUserData(countryCode);
checkBoxList.add(checkBox);
checkBox.setMouseTransparent(false);
checkBox.setMinWidth(45);
checkBox.setMaxWidth(45);
checkBox.setTooltip(new Tooltip(country.name));
checkBox.setOnAction(event -> {
if (checkBox.isSelected()) {
addAcceptedCountry(countryCode);
} else {
removeAcceptedCountry(countryCode);
}
updateAllInputsValid();
});
flowPane.getChildren().add(checkBox);
}
protected abstract void autoFillNameTextField();
public abstract void addFormForAddAccount();

View file

@ -27,7 +27,6 @@ import bisq.desktop.util.normalization.IBANNormalizer;
import bisq.core.account.witness.AccountAgeWitnessService;
import bisq.core.locale.Country;
import bisq.core.locale.CountryUtil;
import bisq.core.locale.CurrencyUtil;
import bisq.core.locale.Res;
import bisq.core.locale.TradeCurrency;
import bisq.core.payment.PaymentAccount;
@ -37,17 +36,12 @@ import bisq.core.payment.payload.SepaAccountPayload;
import bisq.core.util.coin.CoinFormatter;
import bisq.core.util.validation.InputValidator;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ComboBox;
import javafx.scene.control.TextField;
import javafx.scene.control.TextFormatter;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.GridPane;
import javafx.collections.FXCollections;
import java.util.List;
import static bisq.desktop.util.FormBuilder.addCompactTopLabelTextField;
import static bisq.desktop.util.FormBuilder.addCompactTopLabelTextFieldWithCopyIcon;
import static bisq.desktop.util.FormBuilder.addTopLabelTextField;
@ -116,8 +110,8 @@ public class SepaForm extends GeneralSepaForm {
setCountryComboBoxAction(countryComboBox, sepaAccount);
addEuroCountriesGrid();
addNonEuroCountriesGrid();
addCountriesGrid(Res.get("payment.accept.euro"), CountryUtil.getAllSepaEuroCountries());
addCountriesGrid(Res.get("payment.accept.nonEuro"), CountryUtil.getAllSepaNonEuroCountries());
addLimitations(false);
addAccountNameTextFieldWithAutoFillToggleButton();
@ -131,39 +125,6 @@ public class SepaForm extends GeneralSepaForm {
updateFromInputs();
}
private void addEuroCountriesGrid() {
addCountriesGrid(Res.get("payment.accept.euro"), euroCountryCheckBoxes,
CountryUtil.getAllSepaEuroCountries());
}
private void addNonEuroCountriesGrid() {
addCountriesGrid(Res.get("payment.accept.nonEuro"), nonEuroCountryCheckBoxes,
CountryUtil.getAllSepaNonEuroCountries());
}
@Override
void updateCountriesSelection(List<CheckBox> checkBoxList) {
checkBoxList.forEach(checkBox -> {
String countryCode = (String) checkBox.getUserData();
TradeCurrency selectedCurrency = sepaAccount.getSelectedTradeCurrency();
if (selectedCurrency == null) {
Country country = CountryUtil.getDefaultCountry();
if (CountryUtil.getAllSepaCountries().contains(country))
selectedCurrency = CurrencyUtil.getCurrencyByCountryCode(country.code);
}
boolean selected;
if (selectedCurrency != null) {
selected = true;
sepaAccount.addAcceptedCountry(countryCode);
} else {
selected = sepaAccount.getAcceptedCountryCodes().contains(countryCode);
}
checkBox.setSelected(selected);
});
}
@Override
public void updateAllInputsValid() {
allInputsValid.set(isAccountNameValid()
@ -189,19 +150,9 @@ public class SepaForm extends GeneralSepaForm {
TradeCurrency singleTradeCurrency = sepaAccount.getSingleTradeCurrency();
String nameAndCode = singleTradeCurrency != null ? singleTradeCurrency.getNameAndCode() : "null";
addCompactTopLabelTextField(gridPane, ++gridRow, Res.get("shared.currency"), nameAndCode);
String countries;
Tooltip tooltip = null;
if (CountryUtil.containsAllSepaEuroCountries(sepaAccount.getAcceptedCountryCodes())) {
countries = Res.get("shared.allEuroCountries");
} else {
countries = CountryUtil.getCodesString(sepaAccount.getAcceptedCountryCodes());
tooltip = new Tooltip(CountryUtil.getNamesByCodesString(sepaAccount.getAcceptedCountryCodes()));
}
TextField acceptedCountries = addCompactTopLabelTextField(gridPane, ++gridRow, Res.get("payment.accepted.countries"), countries).second;
if (tooltip != null) {
acceptedCountries.setMouseTransparent(false);
acceptedCountries.setTooltip(tooltip);
}
addCountriesGrid(Res.get("payment.accept.euro"), CountryUtil.getAllSepaEuroCountries());
addCountriesGrid(Res.get("payment.accept.nonEuro"), CountryUtil.getAllSepaNonEuroCountries());
addLimitations(true);
}
@ -214,4 +165,9 @@ public class SepaForm extends GeneralSepaForm {
void addAcceptedCountry(String countryCode) {
sepaAccount.addAcceptedCountry(countryCode);
}
@Override
boolean isCountryAccepted(String countryCode) {
return sepaAccount.getAcceptedCountryCodes().contains(countryCode);
}
}

View file

@ -27,7 +27,6 @@ import bisq.desktop.util.normalization.IBANNormalizer;
import bisq.core.account.witness.AccountAgeWitnessService;
import bisq.core.locale.Country;
import bisq.core.locale.CountryUtil;
import bisq.core.locale.CurrencyUtil;
import bisq.core.locale.Res;
import bisq.core.locale.TradeCurrency;
import bisq.core.payment.PaymentAccount;
@ -37,16 +36,12 @@ import bisq.core.payment.payload.SepaInstantAccountPayload;
import bisq.core.util.coin.CoinFormatter;
import bisq.core.util.validation.InputValidator;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ComboBox;
import javafx.scene.control.TextField;
import javafx.scene.control.TextFormatter;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.GridPane;
import javafx.collections.FXCollections;
import java.util.List;
import static bisq.desktop.util.FormBuilder.addCompactTopLabelTextField;
import static bisq.desktop.util.FormBuilder.addCompactTopLabelTextFieldWithCopyIcon;
@ -116,8 +111,8 @@ public class SepaInstantForm extends GeneralSepaForm {
setCountryComboBoxAction(countryComboBox, sepaInstantAccount);
addEuroCountriesGrid();
addNonEuroCountriesGrid();
addCountriesGrid(Res.get("payment.accept.euro"), CountryUtil.getAllSepaEuroCountries());
addCountriesGrid(Res.get("payment.accept.nonEuro"), CountryUtil.getAllSepaNonEuroCountries());
addLimitations(false);
addAccountNameTextFieldWithAutoFillToggleButton();
@ -131,38 +126,6 @@ public class SepaInstantForm extends GeneralSepaForm {
updateFromInputs();
}
private void addEuroCountriesGrid() {
addCountriesGrid(Res.get("payment.accept.euro"), euroCountryCheckBoxes,
CountryUtil.getAllSepaInstantEuroCountries());
}
private void addNonEuroCountriesGrid() {
addCountriesGrid(Res.get("payment.accept.nonEuro"), nonEuroCountryCheckBoxes,
CountryUtil.getAllSepaInstantNonEuroCountries());
}
@Override
void updateCountriesSelection(List<CheckBox> checkBoxList) {
checkBoxList.forEach(checkBox -> {
String countryCode = (String) checkBox.getUserData();
TradeCurrency selectedCurrency = sepaInstantAccount.getSelectedTradeCurrency();
if (selectedCurrency == null) {
Country country = CountryUtil.getDefaultCountry();
if (CountryUtil.getAllSepaInstantCountries().contains(country))
selectedCurrency = CurrencyUtil.getCurrencyByCountryCode(country.code);
}
boolean selected;
if (selectedCurrency != null) {
selected = true;
sepaInstantAccount.addAcceptedCountry(countryCode);
} else {
selected = sepaInstantAccount.getAcceptedCountryCodes().contains(countryCode);
}
checkBox.setSelected(selected);
});
}
@Override
public void updateAllInputsValid() {
allInputsValid.set(isAccountNameValid()
@ -188,19 +151,9 @@ public class SepaInstantForm extends GeneralSepaForm {
TradeCurrency singleTradeCurrency = sepaInstantAccount.getSingleTradeCurrency();
String nameAndCode = singleTradeCurrency != null ? singleTradeCurrency.getNameAndCode() : "null";
addCompactTopLabelTextField(gridPane, ++gridRow, Res.get("shared.currency"), nameAndCode);
String countries;
Tooltip tooltip = null;
if (CountryUtil.containsAllSepaInstantEuroCountries(sepaInstantAccount.getAcceptedCountryCodes())) {
countries = Res.get("shared.allEuroCountries");
} else {
countries = CountryUtil.getCodesString(sepaInstantAccount.getAcceptedCountryCodes());
tooltip = new Tooltip(CountryUtil.getNamesByCodesString(sepaInstantAccount.getAcceptedCountryCodes()));
}
TextField acceptedCountries = addCompactTopLabelTextField(gridPane, ++gridRow, Res.get("payment.accepted.countries"), countries).second;
if (tooltip != null) {
acceptedCountries.setMouseTransparent(false);
acceptedCountries.setTooltip(tooltip);
}
addCountriesGrid(Res.get("payment.accept.euro"), CountryUtil.getAllSepaEuroCountries());
addCountriesGrid(Res.get("payment.accept.nonEuro"), CountryUtil.getAllSepaNonEuroCountries());
addLimitations(true);
}
@ -213,4 +166,9 @@ public class SepaInstantForm extends GeneralSepaForm {
void addAcceptedCountry(String countryCode) {
sepaInstantAccount.addAcceptedCountry(countryCode);
}
@Override
boolean isCountryAccepted(String countryCode) {
return sepaInstantAccount.getAcceptedCountryCodes().contains(countryCode);
}
}

View file

@ -124,6 +124,10 @@ class FiatAccountsDataModel extends ActivatableDataModel {
accountAgeWitnessService.signAndPublishSameNameAccounts();
}
public void onUpdateAccount(PaymentAccount paymentAccount) {
user.requestPersistence();
}
public boolean onDeleteAccount(PaymentAccount paymentAccount) {
boolean usedInOpenOffers = openOfferManager.getObservableList().stream()
.anyMatch(openOffer -> openOffer.getOffer().getMakerPaymentAccountId().equals(paymentAccount.getId()));

View file

@ -386,6 +386,16 @@ public class FiatAccountsView extends PaymentAccountsView<GridPane, FiatAccounts
removeNewAccountForm();
}
private void onUpdateAccount(PaymentAccount paymentAccount) {
model.onUpdateAccount(paymentAccount);
removeSelectAccountForm();
}
private void onCancelSelectedAccount(PaymentAccount paymentAccount) {
paymentAccount.revertChanges();
removeSelectAccountForm();
}
protected boolean deleteAccountFromModel(PaymentAccount paymentAccount) {
return model.onDeleteAccount(paymentAccount);
}
@ -474,11 +484,19 @@ public class FiatAccountsView extends PaymentAccountsView<GridPane, FiatAccounts
if (paymentMethodForm != null) {
paymentMethodForm.addFormForDisplayAccount();
gridRow = paymentMethodForm.getGridRow();
Tuple2<Button, Button> tuple = add2ButtonsAfterGroup(root, ++gridRow, Res.get("shared.deleteAccount"), Res.get("shared.cancel"));
Button deleteAccountButton = tuple.first;
Tuple3<Button, Button, Button> tuple = add3ButtonsAfterGroup(
root,
++gridRow,
Res.get("shared.save"),
Res.get("shared.deleteAccount"),
Res.get("shared.cancel")
);
Button updateButton = tuple.first;
updateButton.setOnAction(event -> onUpdateAccount(paymentMethodForm.getPaymentAccount()));
Button deleteAccountButton = tuple.second;
deleteAccountButton.setOnAction(event -> onDeleteAccount(paymentMethodForm.getPaymentAccount()));
Button cancelButton = tuple.second;
cancelButton.setOnAction(event -> removeSelectAccountForm());
Button cancelButton = tuple.third;
cancelButton.setOnAction(event -> onCancelSelectedAccount(paymentMethodForm.getPaymentAccount()));
GridPane.setRowSpan(accountTitledGroupBg, paymentMethodForm.getRowSpan());
model.onSelectAccount(paymentAccount);
}
@ -638,5 +656,14 @@ public class FiatAccountsView extends PaymentAccountsView<GridPane, FiatAccounts
Utilities.copyToClipboard(accountAgeWitnessService.getSignInfoFromAccount(selectedAccount));
}
@Override
protected void deactivate() {
super.deactivate();
var selectedAccount = paymentAccountsListView.getSelectionModel().getSelectedItem();
if (selectedAccount != null) {
onCancelSelectedAccount(selectedAccount);
}
}
}

View file

@ -50,6 +50,10 @@ class FiatAccountsViewModel extends ActivatableWithDataModel<FiatAccountsDataMod
dataModel.onSaveNewAccount(paymentAccount);
}
public void onUpdateAccount(PaymentAccount paymentAccount) {
dataModel.onUpdateAccount(paymentAccount);
}
public boolean onDeleteAccount(PaymentAccount paymentAccount) {
return dataModel.onDeleteAccount(paymentAccount);
}