Skip to content

Commit 218c985

Browse files
authored
fix: handle new versions created by the proposal builder (#2179)
1 parent c004500 commit 218c985

File tree

3 files changed

+76
-30
lines changed

3 files changed

+76
-30
lines changed

catalyst_voices/apps/voices/lib/widgets/modals/proposals/create_new_proposal_dialog.dart

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import 'package:catalyst_voices/common/error_handler.dart';
12
import 'package:catalyst_voices/common/ext/build_context_ext.dart';
23
import 'package:catalyst_voices/routes/routes.dart';
34
import 'package:catalyst_voices/routes/routing/proposal_builder_route.dart';
@@ -120,7 +121,8 @@ class _CategorySelection extends StatelessWidget {
120121
}
121122
}
122123

123-
class _CreateNewProposalDialogState extends State<CreateNewProposalDialog> {
124+
class _CreateNewProposalDialogState extends State<CreateNewProposalDialog>
125+
with ErrorHandlerStateMixin<NewProposalCubit, CreateNewProposalDialog> {
124126
final FocusNode _categoryFocusNode = FocusNode();
125127

126128
@override
@@ -183,16 +185,16 @@ class _CreateNewProposalDialogState extends State<CreateNewProposalDialog> {
183185
Future<void> _onOpenInEditor() async {
184186
final cubit = context.read<NewProposalCubit>();
185187
final draftRef = await cubit.createDraft();
186-
if (mounted) {
188+
if (draftRef != null && mounted) {
187189
ProposalBuilderRoute.fromRef(ref: draftRef).go(context);
188190
}
189191
}
190192

191193
Future<void> _onSave() async {
192194
final cubit = context.read<NewProposalCubit>();
193-
await cubit.createDraft();
195+
final draftRef = await cubit.createDraft();
194196

195-
if (mounted) {
197+
if (draftRef != null && mounted) {
196198
Navigator.of(context).pop();
197199
}
198200
}

catalyst_voices/packages/internal/catalyst_voices_blocs/lib/src/proposal_builder/new_proposal/new_proposal_cubit.dart

Lines changed: 38 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
11
import 'dart:async';
22

3+
import 'package:catalyst_voices_blocs/src/common/bloc_error_emitter_mixin.dart';
34
import 'package:catalyst_voices_blocs/src/proposal_builder/new_proposal/new_proposal_state.dart';
45
import 'package:catalyst_voices_models/catalyst_voices_models.dart';
56
import 'package:catalyst_voices_services/catalyst_voices_services.dart';
7+
import 'package:catalyst_voices_shared/catalyst_voices_shared.dart';
68
import 'package:catalyst_voices_view_models/catalyst_voices_view_models.dart';
79
import 'package:flutter_bloc/flutter_bloc.dart';
810

9-
class NewProposalCubit extends Cubit<NewProposalState> {
11+
final _logger = Logger('NewProposalCubit');
12+
13+
class NewProposalCubit extends Cubit<NewProposalState>
14+
with BlocErrorEmitterMixin<NewProposalState> {
1015
final CampaignService _campaignService;
1116
final ProposalService _proposalService;
1217
final DocumentMapper _documentMapper;
@@ -23,36 +28,43 @@ class NewProposalCubit extends Cubit<NewProposalState> {
2328
unawaited(getCampaignCategories());
2429
}
2530

26-
Future<DraftRef> createDraft() async {
27-
final title = state.title.value;
28-
final categoryId = state.categoryId;
29-
30-
if (categoryId == null) {
31-
throw StateError('Cannot create draft, category not selected');
32-
}
31+
Future<DraftRef?> createDraft() async {
32+
try {
33+
final title = state.title.value;
34+
final categoryId = state.categoryId;
3335

34-
final category = await _campaignService.getCategory(categoryId);
35-
final templateRef = category.proposalTemplateRef;
36-
final template = await _proposalService.getProposalTemplate(
37-
ref: templateRef,
38-
);
36+
if (categoryId == null) {
37+
throw StateError('Cannot create draft, category not selected');
38+
}
3939

40-
final documentBuilder = DocumentBuilder.fromSchema(schema: template.schema)
41-
..addChange(
42-
DocumentValueChange(
43-
nodeId: ProposalDocument.titleNodeId,
44-
value: title,
45-
),
40+
final category = await _campaignService.getCategory(categoryId);
41+
final templateRef = category.proposalTemplateRef;
42+
final template = await _proposalService.getProposalTemplate(
43+
ref: templateRef,
4644
);
4745

48-
final document = documentBuilder.build();
49-
final documentContent = _documentMapper.toContent(document);
46+
final documentBuilder =
47+
DocumentBuilder.fromSchema(schema: template.schema)
48+
..addChange(
49+
DocumentValueChange(
50+
nodeId: ProposalDocument.titleNodeId,
51+
value: title,
52+
),
53+
);
5054

51-
return _proposalService.createDraftProposal(
52-
content: documentContent,
53-
template: templateRef,
54-
categoryId: categoryId,
55-
);
55+
final document = documentBuilder.build();
56+
final documentContent = _documentMapper.toContent(document);
57+
58+
return await _proposalService.createDraftProposal(
59+
content: documentContent,
60+
template: templateRef,
61+
categoryId: categoryId,
62+
);
63+
} catch (error, stackTrace) {
64+
_logger.severe('Create draft', error, stackTrace);
65+
emitError(LocalizedException.create(error));
66+
return null;
67+
}
5668
}
5769

5870
Future<void> getCampaignCategories() async {

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

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -654,19 +654,49 @@ final class ProposalBuilderBloc
654654
);
655655
}
656656

657+
List<DocumentVersion> _recreateDocumentVersionsWithNewRef(
658+
DocumentRef newRef,
659+
) {
660+
final current = state.metadata.versions;
661+
662+
return [
663+
...current.map(
664+
(e) => e.copyWith(
665+
isCurrent: false,
666+
isLatest: false,
667+
),
668+
),
669+
DocumentVersion(
670+
id: newRef.version!,
671+
number: current.length + 1,
672+
isCurrent: true,
673+
isLatest: true,
674+
),
675+
];
676+
}
677+
657678
Future<void> _saveDocumentLocally(
658679
Emitter<ProposalBuilderState> emit,
659680
Document document,
660681
) async {
682+
final currentRef = state.metadata.documentRef!;
661683
final updatedRef = await _upsertDraftProposal(
662684
_documentMapper.toContent(document),
663685
);
664686

687+
List<DocumentVersion>? updatedVersions;
688+
if (updatedRef != currentRef) {
689+
// if a new ref has been created we need to recreate
690+
// the version history to reflect it
691+
updatedVersions = _recreateDocumentVersionsWithNewRef(updatedRef);
692+
}
693+
665694
_updateMetadata(
666695
emit,
667696
documentRef: updatedRef,
668697
originalDocumentRef: state.metadata.originalDocumentRef ?? updatedRef,
669698
publish: ProposalPublish.localDraft,
699+
versions: updatedVersions,
670700
);
671701
}
672702

@@ -801,12 +831,14 @@ final class ProposalBuilderBloc
801831
DocumentRef? documentRef,
802832
DocumentRef? originalDocumentRef,
803833
ProposalPublish? publish,
834+
List<DocumentVersion>? versions,
804835
}) {
805836
final updatedMetadata = state.metadata.copyWith(
806837
documentRef: documentRef != null ? Optional(documentRef) : null,
807838
originalDocumentRef:
808839
originalDocumentRef != null ? Optional(originalDocumentRef) : null,
809840
publish: publish,
841+
versions: versions,
810842
);
811843

812844
final updatedState = state.copyWith(

0 commit comments

Comments
 (0)