From f72351264a4fe44645ae0c3d3f421c49789a8083 Mon Sep 17 00:00:00 2001 From: Zied Dahmani Date: Tue, 1 Oct 2024 15:36:41 +0100 Subject: [PATCH 1/5] fix: retrieve unity and quorum --- .../base_proposal_model_extension.dart | 2 +- lib/core/extension/vote_tally_extension.dart | 30 +++++++++++++++++++ .../api/services/proposal_service.dart | 7 ++--- .../network/models/base_proposal_model.dart | 14 +++++++-- .../models/proposal_details_model.dart | 8 ++++- .../models/proposal_details_model.g.dart | 12 +++++--- lib/core/network/models/proposal_model.dart | 6 ++++ lib/core/network/models/proposal_model.g.dart | 12 +++++--- .../filter/components/hypha_filter_card.dart | 6 +++- 9 files changed, 80 insertions(+), 17 deletions(-) create mode 100644 lib/core/extension/vote_tally_extension.dart diff --git a/lib/core/extension/base_proposal_model_extension.dart b/lib/core/extension/base_proposal_model_extension.dart index de7248d6..bb9ec515 100644 --- a/lib/core/extension/base_proposal_model_extension.dart +++ b/lib/core/extension/base_proposal_model_extension.dart @@ -33,5 +33,5 @@ extension BaseProposalModelExtension on BaseProposalModel { bool isExpired() => expiration!.toLocal().isBefore(DateTime.now()); // TODO(saif): Replace hardcoded values (.2 and .8) with dynamic values fetched from the server. // These thresholds are relative to each DAO and should be retrieved from the DAO settings. - bool isPassing() => quorumToPercent() >= .2 && unityToPercent() >= .8; + bool isPassing() => (quorum ?? 0) >= (pastQuorum ?? 0) && (unity ?? 0) >= (pastUnity ?? 0); } diff --git a/lib/core/extension/vote_tally_extension.dart b/lib/core/extension/vote_tally_extension.dart new file mode 100644 index 00000000..d99fd2e7 --- /dev/null +++ b/lib/core/extension/vote_tally_extension.dart @@ -0,0 +1,30 @@ +extension VoteTallyExtension on Map { + Map calculateUnityAndQuorum() { + if (this['votetally'] != null && this['votetally'].isNotEmpty) { + double supply = 0; + final double abstain = _extractVotePower(this['votetally'][0]['abstain_votePower_a'] ?? '0.00'); + final double pass = _extractVotePower(this['votetally'][0]['pass_votePower_a'] ?? '0.00'); + final double fail = _extractVotePower(this['votetally'][0]['fail_votePower_a'] ?? '0.00'); + final double unity = (pass + fail > 0) ? pass / (pass + fail) : 0; + + if (this['details_ballotSupply_a'] != null) { + final List supplyParts = this['details_ballotSupply_a'].split(' '); + if (supplyParts.isNotEmpty) { + supply = double.parse(supplyParts[0]); + } + } + + final double quorum = supply > 0 ? (abstain + pass + fail) / supply : 0; + + this['unity'] = unity * 100; + this['quorum'] = quorum * 100; + } + + return this; + } + + double _extractVotePower(String votePower) { + final List parts = votePower.split(' '); + return parts.isNotEmpty ? double.parse(parts[0]) : 0.0; + } +} diff --git a/lib/core/network/api/services/proposal_service.dart b/lib/core/network/api/services/proposal_service.dart index 6a829e41..61fa3b1c 100644 --- a/lib/core/network/api/services/proposal_service.dart +++ b/lib/core/network/api/services/proposal_service.dart @@ -9,13 +9,12 @@ class ProposalService { const ProposalService(this._graphQLService); Future, HyphaError>> getActiveProposals(UserProfileData user, int daoId) async { - final String query = '{"query":"query ActiveProposals(\$docId: String!) { queryDao(filter: { docId: { eq: \$docId } }) { proposal { docId ... on Poll { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Budget { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Queststart { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Questcomplet { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Policy { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Circle { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Payout { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Assignment { details_timeShareX100_i details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Assignbadge { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Role { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Badge { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Suspend { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Edit { details_timeShareX100_i original { ... on Assignbadge { details_title_s } ... on Assignment { details_title_s } } details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Votable { vote { ... on Vote { vote_voter_n vote_vote_s } } } } } }","variables":{"docId":"$daoId"}}'; + final String query = '{"query":"query ActiveProposals(\$docId: String!) { queryDao(filter: { docId: { eq: \$docId } }) { proposal { docId ... on Poll { details_title_s details_ballotAlignment_i details_ballotSupply_a details_ballotQuorum_i ballot_expiration_t creator } ... on Budget { details_title_s details_ballotAlignment_i details_ballotSupply_a details_ballotQuorum_i ballot_expiration_t creator } ... on Queststart { details_title_s details_ballotAlignment_i details_ballotSupply_a details_ballotQuorum_i ballot_expiration_t creator } ... on Questcomplet { details_title_s details_ballotAlignment_i details_ballotSupply_a details_ballotQuorum_i ballot_expiration_t creator } ... on Policy { details_title_s details_ballotAlignment_i details_ballotSupply_a details_ballotQuorum_i ballot_expiration_t creator votetally { ... on VoteTally { pass_votePower_a fail_votePower_a abstain_votePower_a } } } ... on Circle { details_title_s details_ballotAlignment_i details_ballotSupply_a details_ballotQuorum_i ballot_expiration_t creator votetally { ... on VoteTally { pass_votePower_a fail_votePower_a abstain_votePower_a } } } ... on Payout { details_title_s details_ballotAlignment_i details_ballotSupply_a details_ballotQuorum_i ballot_expiration_t creator } ... on Assignment { details_timeShareX100_i details_title_s details_ballotAlignment_i details_ballotSupply_a details_ballotQuorum_i ballot_expiration_t creator } ... on Assignbadge { details_title_s details_ballotAlignment_i details_ballotSupply_a details_ballotQuorum_i ballot_expiration_t creator } ... on Role { details_title_s details_ballotAlignment_i details_ballotSupply_a details_ballotQuorum_i ballot_expiration_t creator } ... on Badge { details_title_s details_ballotAlignment_i details_ballotSupply_a details_ballotQuorum_i ballot_expiration_t creator } ... on Suspend { details_title_s details_ballotAlignment_i details_ballotSupply_a details_ballotQuorum_i ballot_expiration_t creator } ... on Edit { details_timeShareX100_i original { ... on Assignbadge { details_title_s } ... on Assignment { details_title_s } } details_ballotAlignment_i details_ballotSupply_a details_ballotQuorum_i ballot_expiration_t creator } ... on Votable { vote { ... on Vote { vote_voter_n vote_vote_s } } votetally { ... on VoteTally { pass_votePower_a fail_votePower_a abstain_votePower_a } } } } } }","variables":{"docId":"$daoId"}}'; return _graphQLService.graphQLQuery(network: user.network, query: query); } - Future, HyphaError>> getPastProposals(UserProfileData user, int daoId) async { - final String query = '{"query":"query PastProposals(\$docId: String!) { queryDao(filter: { docId: { eq: \$docId } }) { votable { docId ... on Poll { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Budget { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Queststart { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Questcomplet { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Policy { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Circle { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Payout { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Assignment { details_timeShareX100_i details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Assignbadge { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Role { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Badge { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Suspend { details_title_s details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Edit { details_timeShareX100_i original { ... on Assignbadge { details_title_s } ... on Assignment { details_title_s } } details_ballotAlignment_i details_ballotQuorum_i ballot_expiration_t creator } ... on Votable { vote { ... on Vote { vote_voter_n vote_vote_s } } } } } }","variables":{"docId":"$daoId"}}'; + final String query = '{"query":"query PastProposals(\$docId: String!) { queryDao(filter: { docId: { eq: \$docId } }) { votable { docId ... on Poll { details_title_s details_ballotAlignment_i details_ballotSupply_a details_ballotQuorum_i ballot_expiration_t creator votetally { ... on VoteTally { pass_votePower_a fail_votePower_a abstain_votePower_a } } } ... on Budget { details_title_s details_ballotAlignment_i details_ballotSupply_a details_ballotQuorum_i ballot_expiration_t creator votetally { ... on VoteTally { pass_votePower_a fail_votePower_a abstain_votePower_a } } } ... on Queststart { details_title_s details_ballotAlignment_i details_ballotSupply_a details_ballotQuorum_i ballot_expiration_t creator votetally { ... on VoteTally { pass_votePower_a fail_votePower_a abstain_votePower_a } } } ... on Questcomplet { details_title_s details_ballotAlignment_i details_ballotSupply_a details_ballotQuorum_i ballot_expiration_t creator votetally { ... on VoteTally { pass_votePower_a fail_votePower_a abstain_votePower_a } } } ... on Policy { details_title_s details_ballotAlignment_i details_ballotSupply_a details_ballotQuorum_i ballot_expiration_t creator votetally { ... on VoteTally { pass_votePower_a fail_votePower_a abstain_votePower_a } } } ... on Circle { details_title_s details_ballotAlignment_i details_ballotSupply_a details_ballotQuorum_i ballot_expiration_t creator votetally { ... on VoteTally { pass_votePower_a fail_votePower_a abstain_votePower_a } } } ... on Payout { details_title_s details_ballotAlignment_i details_ballotSupply_a details_ballotQuorum_i ballot_expiration_t creator votetally { ... on VoteTally { pass_votePower_a fail_votePower_a abstain_votePower_a } } } ... on Assignment { details_timeShareX100_i details_title_s details_ballotAlignment_i details_ballotSupply_a details_ballotQuorum_i ballot_expiration_t creator votetally { ... on VoteTally { pass_votePower_a fail_votePower_a abstain_votePower_a } } } ... on Assignbadge { details_title_s details_ballotAlignment_i details_ballotSupply_a details_ballotQuorum_i ballot_expiration_t creator votetally { ... on VoteTally { pass_votePower_a fail_votePower_a abstain_votePower_a } } } ... on Role { details_title_s details_ballotAlignment_i details_ballotSupply_a details_ballotQuorum_i ballot_expiration_t creator votetally { ... on VoteTally { pass_votePower_a fail_votePower_a abstain_votePower_a } } } ... on Badge { details_title_s details_ballotAlignment_i details_ballotSupply_a details_ballotQuorum_i ballot_expiration_t creator votetally { ... on VoteTally { pass_votePower_a fail_votePower_a abstain_votePower_a } } } ... on Edit { details_timeShareX100_i votetally { ... on VoteTally { pass_votePower_a fail_votePower_a abstain_votePower_a } } original { ... on Assignbadge { details_title_s } ... on Assignment { details_title_s } } details_ballotAlignment_i details_ballotSupply_a details_ballotQuorum_i ballot_expiration_t creator } ... on Votable { vote { ... on Vote { vote_voter_n vote_vote_s } } } } } }","variables":{"docId":"$daoId"}}'; return _graphQLService.graphQLQuery(network: user.network, query: query); } @@ -23,7 +22,7 @@ class ProposalService { Future, HyphaError>> getProposalDetails( String proposalId, UserProfileData user) async { final String query = - '{"query":"query proposalDetails(\$docId: String!) { getDocument(docId: \$docId) {__typename docId creator createdDate ... on Votable {pass: voteAggregate(filter: { vote_vote_s: { regexp: \\"/.*pass*./\\" } }) {count} fail: voteAggregate(filter: { vote_vote_s: { regexp: \\"/.*fail*./\\" } }) {count} vote { ... on Vote { vote_voter_n vote_vote_s } } } ... on Edit {details_title_s details_description_s details_periodCount_i details_deferredPercX100_i ballot_expiration_t dao {settings {settings_daoTitle_s settings_periodDurationSec_i}} details_ballotAlignment_i details_ballotQuorum_i} ... on Queststart {details_title_s details_description_s details_periodCount_i details_deferredPercX100_i start {details_startTime_t} ballot_expiration_t dao {settings {settings_daoTitle_s settings_periodDurationSec_i}} details_ballotAlignment_i details_ballotQuorum_i details_pegAmount_a details_voiceAmount_a details_rewardAmount_a} ... on Questcomple {details_title_s details_description_s ballot_expiration_t dao {settings {settings_daoTitle_s settings_periodDurationSec_i}} details_pegAmount_a details_voiceAmount_a details_rewardAmount_a} ... on Policy {details_title_s details_description_s details_periodCount_i details_deferredPercX100_i ballot_expiration_t dao {settings {settings_daoTitle_s settings_periodDurationSec_i}} details_ballotAlignment_i details_ballotQuorum_i details_pegAmount_a details_voiceAmount_a details_rewardAmount_a} ... on Payout {details_title_s details_description_s details_periodCount_i details_deferredPercX100_i start {details_startTime_t} ballot_expiration_t dao {settings {settings_daoTitle_s settings_periodDurationSec_i}} details_ballotAlignment_i details_ballotQuorum_i details_pegAmount_a details_voiceAmount_a details_rewardAmount_a} ... on Badge {details_title_s details_description_s details_periodCount_i ballot_expiration_t dao {settings {settings_daoTitle_s settings_periodDurationSec_i}} details_ballotAlignment_i details_ballotQuorum_i} ... on Poll {details_title_s details_description_s ballot_expiration_t dao {settings {settings_daoTitle_s settings_periodDurationSec_i}} details_ballotAlignment_i details_ballotQuorum_i} ... on Budget {details_title_s details_description_s details_deferredPercX100_i ballot_expiration_t dao {settings {settings_daoTitle_s settings_periodDurationSec_i}} details_ballotAlignment_i details_ballotQuorum_i details_pegAmount_a details_voiceAmount_a details_rewardAmount_a} ... on Assignment {details_title_s details_description_s details_periodCount_i details_deferredPercX100_i start {details_startTime_t} details_rewardSalaryPerPeriod_a details_voiceSalaryPerPeriod_a details_pegSalaryPerPeriod_a ballot_expiration_t dao {settings {settings_daoTitle_s settings_periodDurationSec_i}} details_timeShareX100_i details_ballotAlignment_i details_ballotQuorum_i} } }", "variables":{"docId":"$proposalId"}}'; + '{"query":"query proposalDetails(\$docId: String!) { getDocument(docId: \$docId) {__typename docId creator createdDate ... on Votable { votetally { ... on VoteTally { pass_votePower_a fail_votePower_a abstain_votePower_a } } pass: voteAggregate(filter: { vote_vote_s: { regexp: \\"/.*pass*./\\" } }) {count} fail: voteAggregate(filter: { vote_vote_s: { regexp: \\"/.*fail*./\\" } }) {count} vote { ... on Vote { vote_voter_n vote_vote_s } } } ... on Edit {details_title_s details_description_s details_periodCount_i details_deferredPercX100_i ballot_expiration_t dao {settings {settings_daoTitle_s settings_periodDurationSec_i}} details_ballotAlignment_i details_ballotQuorum_i details_ballotSupply_a } ... on Queststart {details_title_s details_description_s details_periodCount_i details_deferredPercX100_i start {details_startTime_t} ballot_expiration_t dao {settings {settings_daoTitle_s settings_periodDurationSec_i}} details_ballotAlignment_i details_ballotSupply_a details_ballotQuorum_i details_pegAmount_a details_voiceAmount_a details_rewardAmount_a} ... on Questcomple {details_title_s details_description_s ballot_expiration_t dao {settings {settings_daoTitle_s settings_periodDurationSec_i}} details_pegAmount_a details_voiceAmount_a details_rewardAmount_a} ... on Policy {details_title_s details_description_s details_periodCount_i details_deferredPercX100_i ballot_expiration_t dao {settings {settings_daoTitle_s settings_periodDurationSec_i}} details_ballotAlignment_i details_ballotSupply_a details_ballotQuorum_i details_pegAmount_a details_voiceAmount_a details_rewardAmount_a} ... on Payout {details_title_s details_description_s details_periodCount_i details_deferredPercX100_i start {details_startTime_t} ballot_expiration_t dao {settings {settings_daoTitle_s settings_periodDurationSec_i}} details_ballotAlignment_i details_ballotSupply_a details_ballotQuorum_i details_pegAmount_a details_voiceAmount_a details_rewardAmount_a} ... on Badge {details_title_s details_description_s details_periodCount_i ballot_expiration_t dao {settings {settings_daoTitle_s settings_periodDurationSec_i}} details_ballotAlignment_i details_ballotSupply_a details_ballotQuorum_i} ... on Poll {details_title_s details_description_s ballot_expiration_t dao {settings {settings_daoTitle_s settings_periodDurationSec_i}} details_ballotAlignment_i details_ballotSupply_a details_ballotQuorum_i} ... on Budget {details_title_s details_description_s details_deferredPercX100_i ballot_expiration_t dao {settings {settings_daoTitle_s settings_periodDurationSec_i}} details_ballotAlignment_i details_ballotSupply_a details_ballotQuorum_i details_pegAmount_a details_voiceAmount_a details_rewardAmount_a} ... on Assignment {details_title_s details_description_s details_periodCount_i details_deferredPercX100_i start {details_startTime_t} details_rewardSalaryPerPeriod_a details_voiceSalaryPerPeriod_a details_pegSalaryPerPeriod_a ballot_expiration_t dao {settings {settings_daoTitle_s settings_periodDurationSec_i}} details_timeShareX100_i details_ballotAlignment_i details_ballotSupply_a details_ballotQuorum_i} } }", "variables":{"docId":"$proposalId"}}'; return _graphQLService.graphQLQuery(network: user.network, query: query); } diff --git a/lib/core/network/models/base_proposal_model.dart b/lib/core/network/models/base_proposal_model.dart index 2dbb69f8..a95e6831 100644 --- a/lib/core/network/models/base_proposal_model.dart +++ b/lib/core/network/models/base_proposal_model.dart @@ -16,11 +16,18 @@ abstract class BaseProposalModel { @JsonKey(name: 'details_title_s') final String? title; + final double? unity; + + final double? quorum; + @JsonKey(name: 'details_ballotAlignment_i') - final int? unity; + final int? pastUnity; @JsonKey(name: 'details_ballotQuorum_i') - final int? quorum; + final int? pastQuorum; + + @JsonKey(name: 'details_ballotSupply_a') + final int? supply; @JsonKey(name: 'ballot_expiration_t') final DateTime? expiration; @@ -37,6 +44,9 @@ abstract class BaseProposalModel { this.title, this.unity, this.quorum, + this.pastUnity, + this.pastQuorum, + this.supply, this.expiration, this.creator, this.votes, diff --git a/lib/core/network/models/proposal_details_model.dart b/lib/core/network/models/proposal_details_model.dart index 1a708a85..f05744d6 100644 --- a/lib/core/network/models/proposal_details_model.dart +++ b/lib/core/network/models/proposal_details_model.dart @@ -1,4 +1,5 @@ -import 'package:hypha_wallet/core/extension/string_extension.dart'; // Add this import +import 'package:hypha_wallet/core/extension/string_extension.dart'; +import 'package:hypha_wallet/core/extension/vote_tally_extension.dart'; import 'package:hypha_wallet/core/network/models/base_proposal_model.dart'; import 'package:hypha_wallet/core/network/models/dao_data_model.dart'; import 'package:hypha_wallet/core/network/models/vote_model.dart'; @@ -78,6 +79,8 @@ class ProposalDetailsModel extends BaseProposalModel { super.title, super.unity, super.quorum, + super.pastUnity, + super.pastQuorum, super.expiration, super.creator, super.votes, @@ -116,6 +119,9 @@ class ProposalDetailsModel extends BaseProposalModel { } json['dao'] = null; json['creator'] = null; + + json.calculateUnityAndQuorum(); + return _$ProposalDetailsModelFromJson(json); } diff --git a/lib/core/network/models/proposal_details_model.g.dart b/lib/core/network/models/proposal_details_model.g.dart index a00287dc..fa1e06a8 100644 --- a/lib/core/network/models/proposal_details_model.g.dart +++ b/lib/core/network/models/proposal_details_model.g.dart @@ -17,8 +17,10 @@ ProposalDetailsModel _$ProposalDetailsModelFromJson( : DaoData.fromJson(json['dao'] as Map), commitment: (json['details_timeShareX100_i'] as num?)?.toInt(), title: json['details_title_s'] as String?, - unity: (json['details_ballotAlignment_i'] as num?)?.toInt(), - quorum: (json['details_ballotQuorum_i'] as num?)?.toInt(), + unity: (json['unity'] as num?)?.toDouble(), + quorum: (json['quorum'] as num?)?.toDouble(), + pastUnity: (json['details_ballotAlignment_i'] as num?)?.toInt(), + pastQuorum: (json['details_ballotQuorum_i'] as num?)?.toInt(), expiration: json['ballot_expiration_t'] == null ? null : DateTime.parse(json['ballot_expiration_t'] as String), @@ -52,8 +54,10 @@ Map _$ProposalDetailsModelToJson( 'dao': instance.dao, 'details_timeShareX100_i': instance.commitment, 'details_title_s': instance.title, - 'details_ballotAlignment_i': instance.unity, - 'details_ballotQuorum_i': instance.quorum, + 'unity': instance.unity, + 'quorum': instance.quorum, + 'details_ballotAlignment_i': instance.pastUnity, + 'details_ballotQuorum_i': instance.pastQuorum, 'ballot_expiration_t': instance.expiration?.toIso8601String(), 'creator': instance.creator, 'vote': instance.votes, diff --git a/lib/core/network/models/proposal_model.dart b/lib/core/network/models/proposal_model.dart index 5a4e9ee1..e6f09b12 100644 --- a/lib/core/network/models/proposal_model.dart +++ b/lib/core/network/models/proposal_model.dart @@ -1,4 +1,5 @@ import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:hypha_wallet/core/extension/vote_tally_extension.dart'; import 'package:hypha_wallet/core/network/models/base_proposal_model.dart'; import 'package:hypha_wallet/core/network/models/dao_data_model.dart'; import 'package:hypha_wallet/core/network/models/vote_model.dart'; @@ -15,6 +16,8 @@ class ProposalModel extends BaseProposalModel{ super.title, super.unity, super.quorum, + super.pastUnity, + super.pastQuorum, super.expiration, super.creator, super.votes, @@ -24,6 +27,9 @@ class ProposalModel extends BaseProposalModel{ if (json.containsKey('original')) { json['details_title_s'] = json['original'][0]['details_title_s']; } + + json.calculateUnityAndQuorum(); + return _$ProposalModelFromJson(json); } } diff --git a/lib/core/network/models/proposal_model.g.dart b/lib/core/network/models/proposal_model.g.dart index c93a2761..2b01a8d9 100644 --- a/lib/core/network/models/proposal_model.g.dart +++ b/lib/core/network/models/proposal_model.g.dart @@ -14,8 +14,10 @@ ProposalModel _$ProposalModelFromJson(Map json) => : DaoData.fromJson(json['dao'] as Map), commitment: (json['details_timeShareX100_i'] as num?)?.toInt(), title: json['details_title_s'] as String?, - unity: (json['details_ballotAlignment_i'] as num?)?.toInt(), - quorum: (json['details_ballotQuorum_i'] as num?)?.toInt(), + unity: (json['unity'] as num?)?.toDouble(), + quorum: (json['quorum'] as num?)?.toDouble(), + pastUnity: (json['details_ballotAlignment_i'] as num?)?.toInt(), + pastQuorum: (json['details_ballotQuorum_i'] as num?)?.toInt(), expiration: json['ballot_expiration_t'] == null ? null : DateTime.parse(json['ballot_expiration_t'] as String), @@ -33,8 +35,10 @@ Map _$ProposalModelToJson(ProposalModel instance) => 'dao': instance.dao, 'details_timeShareX100_i': instance.commitment, 'details_title_s': instance.title, - 'details_ballotAlignment_i': instance.unity, - 'details_ballotQuorum_i': instance.quorum, + 'unity': instance.unity, + 'quorum': instance.quorum, + 'details_ballotAlignment_i': instance.pastUnity, + 'details_ballotQuorum_i': instance.pastQuorum, 'ballot_expiration_t': instance.expiration?.toIso8601String(), 'creator': instance.creator, 'vote': instance.votes, diff --git a/lib/ui/proposals/filter/components/hypha_filter_card.dart b/lib/ui/proposals/filter/components/hypha_filter_card.dart index 372373ef..a614e590 100644 --- a/lib/ui/proposals/filter/components/hypha_filter_card.dart +++ b/lib/ui/proposals/filter/components/hypha_filter_card.dart @@ -19,7 +19,11 @@ class HyphaFilterCard extends StatelessWidget { // TODO(Saif): fix the card height (filter by status) return GestureDetector( onTap: () { - valueNotifier.value = valueNotifier.value == index ? null : index; + if (valueNotifier.value != index) { + valueNotifier.value = index; + } else if (subTitle != null) { + valueNotifier.value = null; + } }, child: HyphaCard( child: Padding( From 7c9efb32a4a1a0cd5bcfad462506960962ba74c8 Mon Sep 17 00:00:00 2001 From: Zied Dahmani Date: Tue, 1 Oct 2024 15:53:44 +0100 Subject: [PATCH 2/5] style: remove TODO --- lib/core/extension/base_proposal_model_extension.dart | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/core/extension/base_proposal_model_extension.dart b/lib/core/extension/base_proposal_model_extension.dart index bb9ec515..a8c6487c 100644 --- a/lib/core/extension/base_proposal_model_extension.dart +++ b/lib/core/extension/base_proposal_model_extension.dart @@ -31,7 +31,6 @@ extension BaseProposalModelExtension on BaseProposalModel { double unityToPercent() => unity==null?0:unity!*.01; double commitmentToPercent() => commitment == null ? 0 : commitment! * .01; bool isExpired() => expiration!.toLocal().isBefore(DateTime.now()); - // TODO(saif): Replace hardcoded values (.2 and .8) with dynamic values fetched from the server. - // These thresholds are relative to each DAO and should be retrieved from the DAO settings. + bool isPassing() => (quorum ?? 0) >= (pastQuorum ?? 0) && (unity ?? 0) >= (pastUnity ?? 0); } From 2b9616f7a535bc56c0c55c42bfff6aa0647e0036 Mon Sep 17 00:00:00 2001 From: Zied Dahmani Date: Thu, 3 Oct 2024 14:01:06 +0100 Subject: [PATCH 3/5] refactor: call quantityAsDouble --- lib/core/extension/vote_tally_extension.dart | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/lib/core/extension/vote_tally_extension.dart b/lib/core/extension/vote_tally_extension.dart index d99fd2e7..98b26478 100644 --- a/lib/core/extension/vote_tally_extension.dart +++ b/lib/core/extension/vote_tally_extension.dart @@ -2,9 +2,9 @@ extension VoteTallyExtension on Map { Map calculateUnityAndQuorum() { if (this['votetally'] != null && this['votetally'].isNotEmpty) { double supply = 0; - final double abstain = _extractVotePower(this['votetally'][0]['abstain_votePower_a'] ?? '0.00'); - final double pass = _extractVotePower(this['votetally'][0]['pass_votePower_a'] ?? '0.00'); - final double fail = _extractVotePower(this['votetally'][0]['fail_votePower_a'] ?? '0.00'); + final double abstain = this['votetally'][0]['abstain_votePower_a'].quantityAsDouble(); + final double pass = this['votetally'][0]['pass_votePower_a'].quantityAsDouble(); + final double fail = this['votetally'][0]['fail_votePower_a'].quantityAsDouble(); final double unity = (pass + fail > 0) ? pass / (pass + fail) : 0; if (this['details_ballotSupply_a'] != null) { @@ -22,9 +22,4 @@ extension VoteTallyExtension on Map { return this; } - - double _extractVotePower(String votePower) { - final List parts = votePower.split(' '); - return parts.isNotEmpty ? double.parse(parts[0]) : 0.0; - } } From 80193f08012c827766d28dba8f04d0bd5e17ad48 Mon Sep 17 00:00:00 2001 From: Zied Dahmani Date: Fri, 4 Oct 2024 08:39:15 +0100 Subject: [PATCH 4/5] refactor: call quantityAsDouble --- lib/core/extension/vote_tally_extension.dart | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/lib/core/extension/vote_tally_extension.dart b/lib/core/extension/vote_tally_extension.dart index 98b26478..7d76b474 100644 --- a/lib/core/extension/vote_tally_extension.dart +++ b/lib/core/extension/vote_tally_extension.dart @@ -1,19 +1,13 @@ extension VoteTallyExtension on Map { Map calculateUnityAndQuorum() { if (this['votetally'] != null && this['votetally'].isNotEmpty) { - double supply = 0; final double abstain = this['votetally'][0]['abstain_votePower_a'].quantityAsDouble(); final double pass = this['votetally'][0]['pass_votePower_a'].quantityAsDouble(); final double fail = this['votetally'][0]['fail_votePower_a'].quantityAsDouble(); - final double unity = (pass + fail > 0) ? pass / (pass + fail) : 0; - if (this['details_ballotSupply_a'] != null) { - final List supplyParts = this['details_ballotSupply_a'].split(' '); - if (supplyParts.isNotEmpty) { - supply = double.parse(supplyParts[0]); - } - } + final double unity = (pass + fail > 0) ? pass / (pass + fail) : 0; + final double supply = this['details_ballotSupply_a']?.quantityAsDouble() ?? 0; final double quorum = supply > 0 ? (abstain + pass + fail) / supply : 0; this['unity'] = unity * 100; From 94078095983762c930be6100fa735bc1d7948f7b Mon Sep 17 00:00:00 2001 From: Zied Dahmani Date: Tue, 8 Oct 2024 16:42:17 +0100 Subject: [PATCH 5/5] fix: quantityAsDouble call --- lib/core/extension/vote_tally_extension.dart | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/core/extension/vote_tally_extension.dart b/lib/core/extension/vote_tally_extension.dart index 7d76b474..a95636dc 100644 --- a/lib/core/extension/vote_tally_extension.dart +++ b/lib/core/extension/vote_tally_extension.dart @@ -1,13 +1,15 @@ +import 'package:hypha_wallet/core/extension/string_extension.dart'; + extension VoteTallyExtension on Map { Map calculateUnityAndQuorum() { if (this['votetally'] != null && this['votetally'].isNotEmpty) { - final double abstain = this['votetally'][0]['abstain_votePower_a'].quantityAsDouble(); - final double pass = this['votetally'][0]['pass_votePower_a'].quantityAsDouble(); - final double fail = this['votetally'][0]['fail_votePower_a'].quantityAsDouble(); + final double abstain = (this['votetally'][0]['abstain_votePower_a'] as String).quantityAsDouble; + final double pass = (this['votetally'][0]['pass_votePower_a'] as String).quantityAsDouble; + final double fail = (this['votetally'][0]['fail_votePower_a'] as String).quantityAsDouble; final double unity = (pass + fail > 0) ? pass / (pass + fail) : 0; - final double supply = this['details_ballotSupply_a']?.quantityAsDouble() ?? 0; + final double supply = (this['details_ballotSupply_a'] as String?)?.quantityAsDouble ?? 0; final double quorum = supply > 0 ? (abstain + pass + fail) / supply : 0; this['unity'] = unity * 100;