Skip to content

Commit

Permalink
Merge pull request #284 from hypha-dao/feat/implement-retrieve-active…
Browse files Browse the repository at this point in the history
…-proposals-logic

feat: implement logic to retrieve active proposals
  • Loading branch information
Zied-Dahmani authored Aug 23, 2024
2 parents 62a994e + 5b2c3c0 commit 4ff6e68
Show file tree
Hide file tree
Showing 18 changed files with 1,047 additions and 3 deletions.
7 changes: 6 additions & 1 deletion lib/core/di/bloc_module.dart
Original file line number Diff line number Diff line change
Expand Up @@ -133,4 +133,9 @@ void _registerBlocsModule() {
_getIt<SearchForMemberUseCase>(),
_getIt<AuthRepository>(),
));
}

_registerFactory(() => ProposalsBloc(
_getIt<GetProposalsUseCase>(),
_getIt<ErrorHandlerManager>(),
));
}
4 changes: 4 additions & 0 deletions lib/core/di/di_setup.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import 'package:hypha_wallet/core/network/api/services/graphql_service.dart';
import 'package:hypha_wallet/core/network/api/services/hypha_member_service.dart';
import 'package:hypha_wallet/core/network/api/services/invite_service.dart';
import 'package:hypha_wallet/core/network/api/services/pay_cpu_service.dart';
import 'package:hypha_wallet/core/network/api/services/proposal_service.dart';
import 'package:hypha_wallet/core/network/api/services/remote_config_service.dart';
import 'package:hypha_wallet/core/network/api/services/sign_transaction_callback_service.dart';
import 'package:hypha_wallet/core/network/api/services/token_repository.dart';
Expand All @@ -34,6 +35,7 @@ import 'package:hypha_wallet/core/network/models/user_profile_data.dart';
import 'package:hypha_wallet/core/network/networking_manager.dart';
import 'package:hypha_wallet/core/network/repository/auth_repository.dart';
import 'package:hypha_wallet/core/network/repository/profile_repository.dart';
import 'package:hypha_wallet/core/network/repository/proposal_repository.dart';
import 'package:hypha_wallet/core/network/repository/transaction_history_repository.dart';
import 'package:hypha_wallet/core/network/repository/user_account_repository.dart';
import 'package:hypha_wallet/core/shared_preferences/hypha_shared_prefs.dart';
Expand Down Expand Up @@ -70,6 +72,8 @@ import 'package:hypha_wallet/ui/profile/usecases/remove_avatar_use_case.dart';
import 'package:hypha_wallet/ui/profile/usecases/set_bio_use_case.dart';
import 'package:hypha_wallet/ui/profile/usecases/set_image_use_case.dart';
import 'package:hypha_wallet/ui/profile/usecases/set_name_use_case.dart';
import 'package:hypha_wallet/ui/proposals/list/interactor/proposals_bloc.dart';
import 'package:hypha_wallet/ui/proposals/list/usecases/get_proposals_use_case.dart';
import 'package:hypha_wallet/ui/search_user/interactor/search_user_bloc.dart';
import 'package:hypha_wallet/ui/search_user/usecases/search_for_user_use_case.dart';
import 'package:hypha_wallet/ui/settings/interactor/settings_bloc.dart';
Expand Down
4 changes: 3 additions & 1 deletion lib/core/di/repositories_module.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,6 @@ void _registerRepositoriesModule() {
_registerLazySingleton(() => UserAccountRepository(userService: _getIt<UserAccountService>(), memberService: _getIt<HyphaMemberService>()));

_registerLazySingleton(() => TransactionHistoryRepository(service: _getIt<TransactionHistoryService>()));
}

_registerLazySingleton(() => ProposalRepository(_getIt<ProposalService>()));
}
2 changes: 2 additions & 0 deletions lib/core/di/services_module.dart
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,6 @@ Future<void> _registerServicesModule() async {
_registerLazySingleton<PermissionService>(() => PermissionServiceImplementation());

_registerLazySingleton<ProfileService>(() => ProfileService(_getIt<RemoteConfigService>()));

_registerLazySingleton<ProposalService>(() => ProposalService(_getIt<GraphQLService>()));
}
4 changes: 3 additions & 1 deletion lib/core/di/usecases_module.dart
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,6 @@ void _registerUseCasesModule() {
));

_registerFactory(() => GetDaoNameUseCase(_getIt<DaoService>()));
}

_registerFactory(() => GetProposalsUseCase(_getIt<AuthRepository>(), _getIt<ProposalRepository>()));
}
16 changes: 16 additions & 0 deletions lib/core/network/api/services/proposal_service.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import 'package:hypha_wallet/core/error_handler/model/hypha_error.dart';
import 'package:hypha_wallet/core/network/api/services/graphql_service.dart';
import 'package:hypha_wallet/core/network/models/user_profile_data.dart';
import 'package:hypha_wallet/ui/architecture/result/result.dart';

class ProposalService {
final GraphQLService _graphQLService;

const ProposalService(this._graphQLService);

Future<Result<Map<String, dynamic>, HyphaError>> getProposals(UserProfileData user) async {
final String query = r'{"query":"query Proposals($first: Int, $offset: Int) { queryDao(first: $first, offset: $offset) { details_daoName_n proposal(first: $first, offset: $offset) { 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 } } } } }}"}';

return _graphQLService.graphQLQuery(network: user.network, query: query);
}
}
33 changes: 33 additions & 0 deletions lib/core/network/models/proposal_model.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import 'package:hypha_wallet/core/network/models/vote_model.dart';
import 'package:json_annotation/json_annotation.dart';

part 'proposal_model.g.dart';

@JsonSerializable()
class ProposalModel {
@JsonKey(name: 'docId')
final String id;
final String daoName;
@JsonKey(name: 'details_timeShareX100_i')
final int? commitment;
@JsonKey(name: 'details_title_s')
final String? title;
@JsonKey(name: 'details_ballotAlignment_i')
final int? unity;
@JsonKey(name: 'details_ballotQuorum_i')
final int? quorum;
@JsonKey(name: 'ballot_expiration_t')
final DateTime? expiration;
final String creator;
@JsonKey(name: 'vote')
final List<VoteModel>? votes;

ProposalModel({required this.id, required this.daoName, this.commitment, this.title, this.unity, this.quorum, this.expiration, required this.creator, this.votes});

factory ProposalModel.fromJson(Map<String, dynamic> json) {
if (json.containsKey('original')) {
json['details_title_s'] = json['original'][0]['details_title_s'];
}
return _$ProposalModelFromJson(json);
}
}
37 changes: 37 additions & 0 deletions lib/core/network/models/proposal_model.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 18 additions & 0 deletions lib/core/network/models/vote_model.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import 'package:json_annotation/json_annotation.dart';

part 'vote_model.g.dart';

enum VoteStatus { pass, abstain, fail }

@JsonSerializable()
class VoteModel {
@JsonKey(name: 'vote_voter_n')
final String voter;

@JsonKey(name: 'vote_vote_s')
final VoteStatus voteStatus;

VoteModel(this.voter, this.voteStatus);

factory VoteModel.fromJson(Map<String, dynamic> json) => _$VoteModelFromJson(json);
}
23 changes: 23 additions & 0 deletions lib/core/network/models/vote_model.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

44 changes: 44 additions & 0 deletions lib/core/network/repository/proposal_repository.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import 'package:hypha_wallet/core/error_handler/model/hypha_error.dart';
import 'package:hypha_wallet/core/logging/log_helper.dart';
import 'package:hypha_wallet/core/network/api/services/proposal_service.dart';
import 'package:hypha_wallet/core/network/models/proposal_model.dart';
import 'package:hypha_wallet/core/network/models/user_profile_data.dart';
import 'package:hypha_wallet/ui/architecture/result/result.dart';

class ProposalRepository {
final ProposalService _proposalService;

ProposalRepository(this._proposalService);

Future<Result<List<ProposalModel>, HyphaError>> getProposals(UserProfileData user) async {
final Result<Map<String, dynamic>, HyphaError> result = await _proposalService.getProposals(user);

if (result.isValue) {
if (result.asValue!.value['errors'] != null) {
LogHelper.e('GraphQL query failed',error: result.asValue!.value['errors']);
return Result.error(HyphaError.api('GraphQL query failed'));
}

try {
final Map<String, dynamic> response = result.valueOrCrash;
final List<dynamic> proposalsData = response['data']['queryDao'];
final List<ProposalModel> proposals = proposalsData.expand((dao) {
final String daoName = dao['details_daoName_n'];
final List<dynamic> proposals = dao['proposal'] as List<dynamic>;

return proposals.map((dynamic proposal) {
return ProposalModel.fromJson({...{'daoName': daoName}, ...proposal});
});
}).toList();

return Result.value(proposals);
} catch (e, stackTrace) {
LogHelper.e('Error parsing data into proposal model', error: e, stacktrace: stackTrace);
return Result.error(HyphaError.generic('Error parsing data into proposal model'));
}
} else {
LogHelper.e('GraphQL query failed', error: result.asError!.error);
return Result.error(result.asError!.error);
}
}
}
6 changes: 6 additions & 0 deletions lib/ui/proposals/list/interactor/page_command.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
part of 'proposals_bloc.dart';

@freezed
class PageCommand with _$PageCommand {
const factory PageCommand.navigateToProposalDetails(ProposalModel proposal) = _NavigateToProposalDetails;
}
37 changes: 37 additions & 0 deletions lib/ui/proposals/list/interactor/proposals_bloc.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:hypha_wallet/core/error_handler/error_handler_manager.dart';
import 'package:hypha_wallet/core/error_handler/model/hypha_error.dart';
import 'package:hypha_wallet/core/network/models/proposal_model.dart';
import 'package:hypha_wallet/ui/architecture/interactor/page_states.dart';
import 'package:hypha_wallet/ui/architecture/result/result.dart';
import 'package:hypha_wallet/ui/proposals/list/usecases/get_proposals_use_case.dart';

part 'page_command.dart';
part 'proposals_bloc.freezed.dart';
part 'proposals_event.dart';
part 'proposals_state.dart';

class ProposalsBloc extends Bloc<ProposalsEvent, ProposalsState> {
final GetProposalsUseCase _getProposalsUseCase;
final ErrorHandlerManager _errorHandlerManager;

ProposalsBloc(this._getProposalsUseCase, this._errorHandlerManager) : super(const ProposalsState()) {
on<_Initial>(_initial);
}

Future<void> _initial(_Initial event, Emitter<ProposalsState> emit) async {
if(!event.refresh) {
emit(state.copyWith(pageState: PageState.loading));
}

final Result<List<ProposalModel>, HyphaError> result = await _getProposalsUseCase.run();

if (result.isValue) {
emit(state.copyWith(pageState: PageState.success, proposals: result.valueOrCrash));
} else {
await _errorHandlerManager.handlerError(result.asError!.error);
emit(state.copyWith(pageState: PageState.failure));
}
}
}
Loading

0 comments on commit 4ff6e68

Please sign in to comment.