Skip to content

Commit

Permalink
Merge pull request #3007 from axpoems/add-rep-to-profile-card
Browse files Browse the repository at this point in the history
Add reputation table to profile card
  • Loading branch information
axpoems authored Nov 17, 2024
2 parents e40bb8c + 7fc35b3 commit 340981b
Show file tree
Hide file tree
Showing 7 changed files with 313 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,16 @@
*
* 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
* 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
* 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/>.
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
*/

package bisq.desktop;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import bisq.desktop.main.content.components.ReportToModeratorWindow;
import bisq.desktop.main.content.user.profile_card.details.ProfileCardDetailsController;
import bisq.desktop.main.content.user.profile_card.overview.ProfileCardOverviewController;
import bisq.desktop.main.content.user.profile_card.reputation.ProfileCardReputationController;
import bisq.desktop.overlay.OverlayController;
import bisq.user.banned.BannedUserService;
import bisq.user.identity.UserIdentityService;
Expand Down Expand Up @@ -81,6 +82,7 @@ public InitData(UserProfile userProfile) {
protected final UserIdentityService userIdentityService;
private final ProfileCardOverviewController profileCardOverviewController;
private final ProfileCardDetailsController profileCardDetailsController;
private final ProfileCardReputationController profileCardReputationController;
private Optional<ChatChannel<? extends ChatMessage>> selectedChannel;
private Optional<Runnable> ignoreUserStateHandler, closeHandler;
private Subscription userProfilePin;
Expand All @@ -95,15 +97,17 @@ public ProfileCardController(ServiceProvider serviceProvider) {
userIdentityService = serviceProvider.getUserService().getUserIdentityService();
profileCardOverviewController = new ProfileCardOverviewController(serviceProvider);
profileCardDetailsController = new ProfileCardDetailsController(serviceProvider);
profileCardReputationController = new ProfileCardReputationController(serviceProvider);
view = new ProfileCardView(model, this);
}

@Override
public void onActivate() {
userProfilePin = EasyBind.subscribe(model.getUserProfile(), userProfile -> {
model.getReputationScore().set(reputationService.getReputationScore(userProfile));
profileCardDetailsController.updateUserProfileData(userProfile);
profileCardOverviewController.updateUserProfileData(userProfile);
profileCardDetailsController.updateUserProfileData(userProfile);
profileCardReputationController.updateUserProfileData(userProfile);
boolean isMyProfile = userIdentityService.isUserIdentityPresent(userProfile.getId());
model.getShouldShowReportButton().set(!isMyProfile && selectedChannel.isPresent());
model.getShouldShowUserActionsMenu().set(!isMyProfile);
Expand All @@ -120,8 +124,8 @@ protected Optional<? extends Controller> createController(NavigationTarget navig
return switch (navigationTarget) {
case PROFILE_CARD_OVERVIEW -> Optional.of(profileCardOverviewController);
case PROFILE_CARD_DETAILS -> Optional.of(profileCardDetailsController);
// case USER_DETAILS_OFFERS -> Optional.of();
// case USER_DETAILS_REPUTATION -> Optional.of();
// case PROFILE_CARD_OFFERS -> Optional.of();
case PROFILE_CARD_REPUTATION -> Optional.of(profileCardReputationController);
default -> Optional.empty();
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ public ProfileCardView(ProfileCardModel model, ProfileCardController controller)

addTab(Res.get("user.profileCard.tab.overview"), NavigationTarget.PROFILE_CARD_OVERVIEW);
addTab(Res.get("user.profileCard.tab.details"), NavigationTarget.PROFILE_CARD_DETAILS);
// addTab(Res.get("user.profileCard.tab.offers"), NavigationTarget.USER_CARD_OFFERS);
// addTab(Res.get("user.profileCard.tab.reputation"), NavigationTarget.USER_CARD_REPUTATION);
// addTab(Res.get("user.profileCard.tab.offers"), NavigationTarget.PROFILE_CARD_OFFERS);
addTab(Res.get("user.profileCard.tab.reputation"), NavigationTarget.PROFILE_CARD_REPUTATION);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* 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.desktop.main.content.user.profile_card.reputation;

import bisq.desktop.ServiceProvider;
import bisq.desktop.common.view.Controller;
import bisq.user.profile.UserProfile;
import bisq.user.reputation.AccountAgeService;
import bisq.user.reputation.BondedReputationService;
import bisq.user.reputation.ProfileAgeService;
import bisq.user.reputation.ProofOfBurnService;
import bisq.user.reputation.ReputationService;
import bisq.user.reputation.ReputationSource;
import bisq.user.reputation.SignedWitnessService;
import lombok.Getter;

import java.util.Optional;

public class ProfileCardReputationController implements Controller {
@Getter
private final ProfileCardReputationView view;
private final ProfileCardReputationModel model;
private final ReputationService reputationService;

public ProfileCardReputationController(ServiceProvider serviceProvider) {
model = new ProfileCardReputationModel();
view = new ProfileCardReputationView(model, this);
reputationService = serviceProvider.getUserService().getReputationService();
}

@Override
public void onActivate() {
}

@Override
public void onDeactivate() {
}

public void updateUserProfileData(UserProfile userProfile) {
model.getListItems().clear();

ProofOfBurnService proofOfBurnService = reputationService.getProofOfBurnService();
Optional.ofNullable(proofOfBurnService.getDataSetByHash().get(userProfile.getProofOfBurnKey()))
.ifPresent(dataSet -> model.getListItems().addAll(dataSet.stream()
.map(data -> new ProfileCardReputationView.ListItem(ReputationSource.BURNED_BSQ,
data.getBlockTime(),
proofOfBurnService.calculateScore(data),
data.getAmount()))
.toList()));

BondedReputationService bondedReputationService = reputationService.getBondedReputationService();
Optional.ofNullable(bondedReputationService.getDataSetByHash().get(userProfile.getBondedReputationKey()))
.ifPresent(dataSet -> model.getListItems().addAll(dataSet.stream()
.map(data -> new ProfileCardReputationView.ListItem(ReputationSource.BSQ_BOND,
data.getBlockTime(),
bondedReputationService.calculateScore(data),
Optional.of(data.getAmount()),
Optional.of(data.getLockTime())))
.toList()));

AccountAgeService accountAgeService = reputationService.getAccountAgeService();
Optional.ofNullable(accountAgeService.getDataSetByHash().get(userProfile.getAccountAgeKey()))
.ifPresent(dataSet -> model.getListItems().addAll(dataSet.stream()
.map(data -> new ProfileCardReputationView.ListItem(ReputationSource.BISQ1_ACCOUNT_AGE,
data.getDate(),
accountAgeService.calculateScore(data)))
.toList()));

SignedWitnessService signedWitnessService = reputationService.getSignedWitnessService();
Optional.ofNullable(signedWitnessService.getDataSetByHash().get(userProfile.getSignedWitnessKey()))
.ifPresent(dataSet -> model.getListItems().addAll(dataSet.stream()
.map(data -> new ProfileCardReputationView.ListItem(ReputationSource.BISQ1_SIGNED_ACCOUNT_AGE_WITNESS,
data.getWitnessSignDate(),
signedWitnessService.calculateScore(data)))
.toList()));

ProfileAgeService profileAgeService = reputationService.getProfileAgeService();
Optional.ofNullable(profileAgeService.getDataSetByHash().get(userProfile.getProfileAgeKey()))
.ifPresent(dataSet -> model.getListItems().addAll(dataSet.stream()
.map(data -> new ProfileCardReputationView.ListItem(ReputationSource.PROFILE_AGE,
data.getDate(),
profileAgeService.calculateScore(data)))
.toList()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* 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.desktop.main.content.user.profile_card.reputation;

import bisq.desktop.common.view.Model;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Getter
public class ProfileCardReputationModel implements Model {
private final ObservableList<ProfileCardReputationView.ListItem> listItems = FXCollections.observableArrayList();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
/*
* 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.desktop.main.content.user.profile_card.reputation;

import bisq.common.monetary.Coin;
import bisq.desktop.common.view.View;
import bisq.desktop.components.table.BisqTableColumn;
import bisq.desktop.components.table.BisqTableView;
import bisq.desktop.components.table.DateColumnUtil;
import bisq.desktop.components.table.DateTableItem;
import bisq.i18n.Res;
import bisq.presentation.formatters.AmountFormatter;
import bisq.presentation.formatters.DateFormatter;
import bisq.presentation.formatters.TimeFormatter;
import bisq.user.reputation.ReputationSource;
import javafx.geometry.Insets;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

import java.util.Comparator;
import java.util.Optional;

@Slf4j
public class ProfileCardReputationView extends View<VBox, ProfileCardReputationModel, ProfileCardReputationController> {
private final BisqTableView<ListItem> tableView;

public ProfileCardReputationView(ProfileCardReputationModel model,
ProfileCardReputationController controller) {
super(new VBox(), model, controller);

VBox vBox = new VBox();
vBox.setFillWidth(true);
vBox.getStyleClass().add("header");
tableView = new BisqTableView<>(model.getListItems());
tableView.getStyleClass().addAll("reputation-table", "rich-table-view");
tableView.allowVerticalScrollbar();
configTableView();
root.getChildren().addAll(vBox, tableView);
root.setPadding(new Insets(20, 0, 0, 0));
root.getStyleClass().add("reputation");
}

@Override
protected void onViewAttached() {
tableView.initialize();
}

@Override
protected void onViewDetached() {
tableView.dispose();
}

private void configTableView() {
BisqTableColumn<ListItem> dateColumn = DateColumnUtil.getDateColumn(tableView.getSortOrder());
dateColumn.setMinWidth(100);
tableView.getColumns().add(dateColumn);

tableView.getColumns().add(new BisqTableColumn.Builder<ListItem>()
.title(Res.get("reputation.details.table.columns.source"))
.left()
.comparator(Comparator.comparing(ListItem::getReputationSource))
.valueSupplier(ListItem::getSourceString)
.build());
tableView.getColumns().add(new BisqTableColumn.Builder<ListItem>()
.title(Res.get("reputation.details.table.columns.score"))
.comparator(Comparator.comparing(ListItem::getScore))
.valueSupplier(ListItem::getScoreString)
.build());
tableView.getColumns().add(new BisqTableColumn.Builder<ListItem>()
.title(Res.get("temporal.age"))
.comparator(Comparator.comparing(ListItem::getAge))
.valueSupplier(ListItem::getAgeString)
.build());
tableView.getColumns().add(new BisqTableColumn.Builder<ListItem>()
.title(Res.get("offer.amount"))
.comparator(Comparator.comparing(ListItem::getAmount))
.valueSupplier(ListItem::getAmountString)
.build());
tableView.getColumns().add(new BisqTableColumn.Builder<ListItem>()
.title(Res.get("reputation.details.table.columns.lockTime"))
.comparator(Comparator.comparing(ListItem::getLockTime))
.valueSupplier(ListItem::getLockTimeString)
.build());
}

@EqualsAndHashCode(onlyExplicitlyIncluded = true)
@Getter
static class ListItem implements DateTableItem {
@EqualsAndHashCode.Include
private final ReputationSource reputationSource;
@EqualsAndHashCode.Include
private final long date, score, amount, lockTime;

private final long age;
private final String dateString, timeString, sourceString, ageString, amountString, scoreString, lockTimeString;

public ListItem(ReputationSource reputationSource, long blockTime, long score) {
this(reputationSource, blockTime, score, Optional.empty(), Optional.empty());
}

public ListItem(ReputationSource reputationSource, long blockTime, long score, long amount) {
this(reputationSource, blockTime, score, Optional.of(amount), Optional.empty());
}

public ListItem(ReputationSource reputationSource,
long blockTime,
long score,
Optional<Long> optionalAmount,
Optional<Long> optionalLockTime) {
this.reputationSource = reputationSource;
this.date = blockTime;
this.score = score;
this.amount = optionalAmount.orElse(0L);
this.lockTime = optionalLockTime.orElse(0L);

dateString = DateFormatter.formatDate(blockTime);
timeString = DateFormatter.formatTime(blockTime);
age = TimeFormatter.getAgeInDays(blockTime);
ageString = TimeFormatter.formatAgeInDays(blockTime);
sourceString = reputationSource.getDisplayString();
amountString = optionalAmount.map(amount -> AmountFormatter.formatAmountWithCode(Coin.fromValue(amount, "BSQ"))).orElse("-");
scoreString = String.valueOf(score);
lockTimeString = optionalLockTime.map(String::valueOf).orElse("-");
}
}
}
27 changes: 27 additions & 0 deletions apps/desktop/desktop/src/main/resources/css/user.css
Original file line number Diff line number Diff line change
Expand Up @@ -143,3 +143,30 @@
.profile-card .bisq-common-bg {
-fx-padding: 35 !important;
}

.profile-card .reputation .header {
-fx-pref-height: 8;
-fx-background-color: -bisq-dark-grey-30;
-fx-background-radius: 8 8 0 0;
}

.profile-card .reputation .reputation-table.table-view {
-fx-pref-height: 300;
-fx-background-radius: 0 0 8 8;
-fx-background-insets: 0;
-fx-padding: 0;
-fx-border-width: 0;
}

.profile-card .reputation .reputation-table.table-view .table-cell .text {
-fx-font-size: 0.9em;
-fx-padding: 0;
}

.profile-card .reputation .reputation-table.table-view .column-header {
-fx-pref-height: 25;
}

.profile-card .reputation .reputation-table.table-view .table-row-cell {
-fx-border-width: 0;
}

0 comments on commit 340981b

Please sign in to comment.