Skip to content

Commit 47fc157

Browse files
authored
feat(cat-voices): opening proposal editor via links (#2551)
* feat: proposal editor links handle * feat: adding proposalRef into tryCatch bloc * feat: change name from action to unlock * fix: format
1 parent 7ccb985 commit 47fc157

File tree

5 files changed

+94
-1
lines changed

5 files changed

+94
-1
lines changed

catalyst_voices/apps/voices/lib/pages/proposal_builder/proposal_builder_page.dart

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import 'package:catalyst_voices/widgets/modals/comment/submit_comment_error_dial
1818
import 'package:catalyst_voices/widgets/modals/proposals/proposal_limit_reached_dialog.dart';
1919
import 'package:catalyst_voices/widgets/modals/proposals/publish_proposal_error_dialog.dart';
2020
import 'package:catalyst_voices/widgets/modals/proposals/submit_proposal_error_dialog.dart';
21+
import 'package:catalyst_voices/widgets/modals/proposals/unlock_edit_proposal.dart';
2122
import 'package:catalyst_voices/widgets/snackbar/voices_snackbar.dart';
2223
import 'package:catalyst_voices/widgets/snackbar/voices_snackbar_action.dart';
2324
import 'package:catalyst_voices/widgets/snackbar/voices_snackbar_type.dart';
@@ -164,6 +165,8 @@ class _ProposalBuilderPageState extends State<ProposalBuilderPage>
164165
unawaited(_showEmailNotVerifiedDialog());
165166
case MaxProposalsLimitReachedSignal():
166167
unawaited(_showProposalLimitReachedDialog(signal));
168+
case UnlockProposalSignal():
169+
unawaited(_showUnlockProposalDialog(signal));
167170
}
168171
}
169172

@@ -317,6 +320,28 @@ class _ProposalBuilderPageState extends State<ProposalBuilderPage>
317320
);
318321
}
319322

323+
Future<void> _showUnlockProposalDialog(
324+
UnlockProposalSignal signal, {
325+
ProposalBuilderBloc? bloc,
326+
}) async {
327+
bloc ??= context.read<ProposalBuilderBloc>();
328+
final unlock = await UnlockEditProposalDialog.show(
329+
context: context,
330+
title: signal.title,
331+
version: signal.version,
332+
) ??
333+
false;
334+
335+
if (unlock && mounted) {
336+
return bloc.add(const UnlockProposalBuilderEvent());
337+
}
338+
if (mounted) {
339+
Router.neglect(context, () {
340+
const WorkspaceRoute().replace(context);
341+
});
342+
}
343+
}
344+
320345
void _showValidationErrorSnackbar(ProposalBuilderValidationException error) {
321346
VoicesSnackBar.hideCurrent(context);
322347

catalyst_voices/packages/internal/catalyst_voices_blocs/lib/src/proposal_builder/proposal_builder_bloc.dart

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ final class ProposalBuilderBloc extends Bloc<ProposalBuilderEvent, ProposalBuild
6565
on<MaxProposalsLimitChangedEvent>(_updateMaxProposalsLimitReached);
6666
on<MaxProposalsLimitReachedEvent>(_onMaxProposalsLimitReached);
6767
on<UpdateUsernameEvent>(_onUpdateUsername);
68+
on<UnlockProposalBuilderEvent>(_unlockProposal);
6869

6970
final activeAccount = _userService.user.activeAccount;
7071

@@ -414,7 +415,8 @@ final class ProposalBuilderBloc extends Bloc<ProposalBuilderEvent, ProposalBuild
414415
LoadProposalEvent event,
415416
Emitter<ProposalBuilderState> emit,
416417
) async {
417-
final proposalRef = event.proposalId;
418+
final proposalRef = await _proposalService.getLatestProposalVersion(ref: event.proposalId);
419+
418420
if (state.metadata.documentRef == proposalRef) {
419421
_logger.info('Loading proposal: $proposalRef ignored, already loaded');
420422
return;
@@ -429,6 +431,15 @@ final class ProposalBuilderBloc extends Bloc<ProposalBuilderEvent, ProposalBuild
429431

430432
final proposal = Proposal.fromData(proposalData);
431433

434+
if (proposalData.publish.isPublished) {
435+
emitSignal(
436+
UnlockProposalSignal(
437+
title: proposal.title,
438+
version: proposal.versionCount,
439+
),
440+
);
441+
}
442+
432443
final versions = proposalData.versions.mapIndexed((index, version) {
433444
final versionRef = version.document.metadata.selfRef;
434445
final versionId = versionRef.version ?? versionRef.id;
@@ -914,6 +925,27 @@ final class ProposalBuilderBloc extends Bloc<ProposalBuilderEvent, ProposalBuild
914925
emitSignal(const SubmittedProposalBuilderSignal());
915926
}
916927

928+
Future<void> _unlockProposal(
929+
UnlockProposalBuilderEvent event,
930+
Emitter<ProposalBuilderState> emit,
931+
) async {
932+
try {
933+
final proposalRef = state.metadata.documentRef! as SignedDocumentRef;
934+
final categoryId = state.metadata.categoryId!;
935+
emit(state.copyWith(isChanging: true));
936+
await _proposalService.unlockProposal(
937+
proposalRef: proposalRef,
938+
categoryId: categoryId,
939+
);
940+
final stateMetadata = state.metadata.copyWith(publish: ProposalPublish.publishedDraft);
941+
_cache = _cache.copyWith(proposalMetadata: Optional(stateMetadata));
942+
emit(state.copyWith(metadata: stateMetadata, isChanging: false));
943+
} catch (e, stackTrace) {
944+
_logger.severe('Unlock proposal failed', e, stackTrace);
945+
emitError(LocalizedException.create(e));
946+
}
947+
}
948+
917949
Future<void> _updateCommentBuilder(
918950
UpdateCommentBuilderEvent event,
919951
Emitter<ProposalBuilderState> emit,

catalyst_voices/packages/internal/catalyst_voices_blocs/lib/src/proposal_builder/proposal_builder_event.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,13 @@ final class SubmitProposalEvent extends ProposalBuilderEvent {
140140
List<Object?> get props => [];
141141
}
142142

143+
final class UnlockProposalBuilderEvent extends ProposalBuilderEvent {
144+
const UnlockProposalBuilderEvent();
145+
146+
@override
147+
List<Object?> get props => [];
148+
}
149+
143150
final class UpdateCommentBuilderEvent extends ProposalBuilderEvent {
144151
final SignedDocumentRef ref;
145152
final bool show;

catalyst_voices/packages/internal/catalyst_voices_blocs/lib/src/proposal_builder/proposal_builder_signal.dart

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,16 @@ final class SubmittedProposalBuilderSignal extends ProposalBuilderSignal {
5959
@override
6060
List<Object?> get props => [];
6161
}
62+
63+
final class UnlockProposalSignal extends ProposalBuilderSignal {
64+
final String title;
65+
final int version;
66+
67+
const UnlockProposalSignal({
68+
required this.title,
69+
required this.version,
70+
});
71+
72+
@override
73+
List<Object?> get props => [title, version];
74+
}

catalyst_voices/packages/internal/catalyst_voices_services/lib/src/proposal/proposal_service.dart

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ abstract interface class ProposalService {
4949
/// Similar to [watchFavoritesProposalsIds] stops after first emit.
5050
Future<List<String>> getFavoritesProposalsIds();
5151

52+
Future<DocumentRef> getLatestProposalVersion({required DocumentRef ref});
53+
5254
Future<ProposalData> getProposal({
5355
required DocumentRef ref,
5456
});
@@ -224,6 +226,20 @@ final class ProposalServiceImpl implements ProposalService {
224226
.first;
225227
}
226228

229+
@override
230+
Future<DocumentRef> getLatestProposalVersion({
231+
required DocumentRef ref,
232+
}) async {
233+
final proposalVersions = await _documentRepository.getAllVersionsOfId(
234+
id: ref.id,
235+
);
236+
final refList = List<DocumentRef>.from(
237+
proposalVersions.map((e) => e.metadata.selfRef).toList(),
238+
)..sort();
239+
240+
return refList.last;
241+
}
242+
227243
@override
228244
Future<ProposalData> getProposal({
229245
required DocumentRef ref,

0 commit comments

Comments
 (0)