Skip to content

Commit

Permalink
Merge branch 'feat/proposal-template-models' of github.com:input-outp…
Browse files Browse the repository at this point in the history
…ut-hk/catalyst-voices into feat/proposal-template-models
  • Loading branch information
LynxLynxx committed Dec 23, 2024
2 parents 4d70b4a + 0106505 commit cfdd91d
Show file tree
Hide file tree
Showing 32 changed files with 1,069 additions and 270 deletions.
2 changes: 1 addition & 1 deletion catalyst-gateway/bin/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ repository.workspace = true
workspace = true

[dependencies]
cardano-chain-follower = { version = "0.0.5", git = "https://github.com/input-output-hk/catalyst-libs.git", tag = "cardano-chain-follower-v0.0.5" }
cardano-chain-follower = { version = "0.0.6", git = "https://github.com/input-output-hk/catalyst-libs.git", tag = "v0.0.10" }
c509-certificate = { version = "0.0.3", git = "https://github.com/input-output-hk/catalyst-libs.git", tag = "v0.0.3" }

pallas = { version = "0.30.1", git = "https://github.com/input-output-hk/catalyst-pallas.git", rev = "9b5183c8b90b90fe2cc319d986e933e9518957b3" }
Expand Down
3 changes: 3 additions & 0 deletions catalyst_voices/apps/voices/lib/app/view/app.dart
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ class _AppState extends State<App> {
BlocProvider<WorkspaceBloc>(
create: (context) => Dependencies.instance.get<WorkspaceBloc>(),
),
BlocProvider<ProposalBuilderBloc>(
create: (context) => Dependencies.instance.get<ProposalBuilderBloc>(),
),
];
}
}
5 changes: 5 additions & 0 deletions catalyst_voices/apps/voices/lib/dependency/dependencies.dart
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,11 @@ final class Dependencies extends DependencyProvider {
return WorkspaceBloc(
get<CampaignService>(),
);
})
..registerFactory<ProposalBuilderBloc>(() {
return ProposalBuilderBloc(
get<CampaignService>(),
);
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -467,8 +467,10 @@ class _EmptyProposals extends StatelessWidget {

@override
Widget build(BuildContext context) {
return EmptyState(
description: context.l10n.discoverySpaceEmptyProposals,
return Center(
child: EmptyState(
description: context.l10n.discoverySpaceEmptyProposals,
),
);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export 'proposal_builder_page.dart';
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import 'package:catalyst_voices/pages/workspace/workspace_rich_text_step.dart';
import 'package:catalyst_voices/pages/proposal_builder/proposal_builder_rich_text_step.dart';
import 'package:catalyst_voices/widgets/navigation/sections_list_view.dart';
import 'package:catalyst_voices/widgets/navigation/sections_list_view_builder.dart';
import 'package:catalyst_voices_view_models/catalyst_voices_view_models.dart';
import 'package:flutter/material.dart';
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';

class WorkspaceBody extends StatelessWidget {
class ProposalBuilderBody extends StatelessWidget {
final ItemScrollController itemScrollController;

const WorkspaceBody({
const ProposalBuilderBody({
super.key,
required this.itemScrollController,
});
Expand All @@ -23,7 +23,7 @@ class WorkspaceBody extends StatelessWidget {
stepBuilder: (context, step) {
switch (step) {
case RichTextStep():
return WorkspaceRichTextStep(step: step);
return ProposalBuilderRichTextStep(step: step);
}
},
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,19 @@ import 'package:catalyst_voices_localization/catalyst_voices_localization.dart';
import 'package:catalyst_voices_models/catalyst_voices_models.dart';
import 'package:flutter/material.dart';

class GuidanceView extends StatefulWidget {
class ProposalBuilderGuidanceView extends StatefulWidget {
final List<Guidance> guidances;
const GuidanceView(this.guidances, {super.key});

const ProposalBuilderGuidanceView(this.guidances, {super.key});

@override
State<GuidanceView> createState() => _GuidanceViewState();
State<ProposalBuilderGuidanceView> createState() {
return _ProposalBuilderGuidanceViewState();
}
}

class _GuidanceViewState extends State<GuidanceView> {
class _ProposalBuilderGuidanceViewState
extends State<ProposalBuilderGuidanceView> {
final List<Guidance> filteredGuidances = [];

GuidanceType? selectedType;
Expand All @@ -27,7 +31,7 @@ class _GuidanceViewState extends State<GuidanceView> {
}

@override
void didUpdateWidget(GuidanceView oldWidget) {
void didUpdateWidget(ProposalBuilderGuidanceView oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.guidances != widget.guidances) {
filteredGuidances
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import 'package:catalyst_voices/widgets/widgets.dart';
import 'package:catalyst_voices_localization/catalyst_voices_localization.dart';
import 'package:flutter/material.dart';

class WorkspaceNavigationPanel extends StatelessWidget {
const WorkspaceNavigationPanel({super.key});
class ProposalBuilderNavigationPanel extends StatelessWidget {
const ProposalBuilderNavigationPanel({super.key});

@override
Widget build(BuildContext context) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import 'dart:async';

import 'package:catalyst_voices/pages/proposal_builder/proposal_builder_body.dart';
import 'package:catalyst_voices/pages/proposal_builder/proposal_builder_navigation_panel.dart';
import 'package:catalyst_voices/pages/proposal_builder/proposal_builder_setup_panel.dart';
import 'package:catalyst_voices/widgets/containers/space_scaffold.dart';
import 'package:catalyst_voices/widgets/navigation/sections_controller.dart';
import 'package:catalyst_voices_blocs/catalyst_voices_blocs.dart';
import 'package:catalyst_voices_view_models/catalyst_voices_view_models.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';

class ProposalBuilderPage extends StatefulWidget {
final String proposalId;

const ProposalBuilderPage({
super.key,
required this.proposalId,
});

@override
State<ProposalBuilderPage> createState() => _ProposalBuilderPageState();
}

class _ProposalBuilderPageState extends State<ProposalBuilderPage> {
late final SectionsController _sectionsController;
late final ItemScrollController _bodyItemScrollController;

SectionStepId? _activeStepId;
StreamSubscription<List<Section>>? _sectionsSub;

@override
void initState() {
super.initState();

final bloc = context.read<ProposalBuilderBloc>();

_sectionsController = SectionsController();
_bodyItemScrollController = ItemScrollController();

_sectionsController
..addListener(_handleSectionsControllerChange)
..attachItemsScrollController(_bodyItemScrollController);

_sectionsSub = bloc.stream
.map((event) => event.sections)
.distinct(listEquals)
.listen(_updateSections);

bloc.add(LoadProposalEvent(id: widget.proposalId));
}

@override
void didUpdateWidget(covariant ProposalBuilderPage oldWidget) {
super.didUpdateWidget(oldWidget);

if (widget.proposalId != oldWidget.proposalId) {
final event = LoadProposalEvent(id: widget.proposalId);
context.read<ProposalBuilderBloc>().add(event);
}
}

@override
void dispose() {
unawaited(_sectionsSub?.cancel());
_sectionsSub = null;

_sectionsController.dispose();
super.dispose();
}

@override
Widget build(BuildContext context) {
return SectionsControllerScope(
controller: _sectionsController,
child: SpaceScaffold(
left: const ProposalBuilderNavigationPanel(),
body: ProposalBuilderBody(
itemScrollController: _bodyItemScrollController,
),
right: const ProposalBuilderSetupPanel(),
),
);
}

void _updateSections(List<Section> data) {
final state = _sectionsController.value;

final newState = state.sections.isEmpty
? SectionsControllerState.initial(sections: data)
: state.copyWith(sections: data);

_sectionsController.value = newState;
}

void _handleSectionsControllerChange() {
final activeStepId = _sectionsController.value.activeStepId;

if (_activeStepId != activeStepId) {
_activeStepId = activeStepId;

final event = ActiveStepChangedEvent(activeStepId);
context.read<ProposalBuilderBloc>().add(event);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,22 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_quill/flutter_quill.dart';

class WorkspaceRichTextStep extends StatefulWidget {
class ProposalBuilderRichTextStep extends StatefulWidget {
final RichTextStep step;

const WorkspaceRichTextStep({
const ProposalBuilderRichTextStep({
super.key,
required this.step,
});

@override
State<WorkspaceRichTextStep> createState() => _WorkspaceRichTextStepState();
State<ProposalBuilderRichTextStep> createState() {
return _ProposalBuilderRichTextStepState();
}
}

class _WorkspaceRichTextStepState extends State<WorkspaceRichTextStep> {
class _ProposalBuilderRichTextStepState
extends State<ProposalBuilderRichTextStep> {
late final VoicesRichTextController _controller;
late final VoicesRichTextEditModeController _editModeController;

Expand Down Expand Up @@ -84,7 +87,7 @@ class _WorkspaceRichTextStepState extends State<WorkspaceRichTextStep> {
data: markdownString.data.isNotEmpty ? markdownString : null,
);

context.read<WorkspaceBloc>().add(event);
context.read<ProposalBuilderBloc>().add(event);
}

bool _canEditDocument(Document document) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import 'package:catalyst_voices/pages/workspace/workspace_guidance_view.dart';
import 'package:catalyst_voices/pages/proposal_builder/proposal_builder_guidance_view.dart';
import 'package:catalyst_voices/widgets/cards/comment_card.dart';
import 'package:catalyst_voices/widgets/widgets.dart';
import 'package:catalyst_voices_blocs/catalyst_voices_blocs.dart';
Expand All @@ -7,8 +7,8 @@ import 'package:catalyst_voices_view_models/catalyst_voices_view_models.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

class WorkspaceSetupPanel extends StatelessWidget {
const WorkspaceSetupPanel({super.key});
class ProposalBuilderSetupPanel extends StatelessWidget {
const ProposalBuilderSetupPanel({super.key});

@override
Widget build(BuildContext context) {
Expand Down Expand Up @@ -46,15 +46,16 @@ class _GuidanceSelector extends StatelessWidget {

@override
Widget build(BuildContext context) {
return BlocSelector<WorkspaceBloc, WorkspaceState, WorkspaceGuidance>(
return BlocSelector<ProposalBuilderBloc, ProposalBuilderState,
ProposalGuidance>(
selector: (state) => state.guidance,
builder: (context, state) {
if (state.isNoneSelected) {
return Text(context.l10n.selectASection);
} else if (state.showEmptyState) {
return Text(context.l10n.noGuidanceForThisSection);
} else {
return GuidanceView(state.guidances);
return ProposalBuilderGuidanceView(state.guidances);
}
},
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import 'package:catalyst_voices/widgets/empty_state/empty_state.dart';
import 'package:catalyst_voices_blocs/catalyst_voices_blocs.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

class WorkspaceEmptyStateSelector extends StatelessWidget {
const WorkspaceEmptyStateSelector({super.key});

@override
Widget build(BuildContext context) {
return BlocSelector<WorkspaceBloc, WorkspaceState, bool>(
selector: (state) => state.showEmptyState,
builder: (context, state) {
return Offstage(
offstage: !state,
child: const _WorkspaceEmptyState(),
);
},
);
}
}

class _WorkspaceEmptyState extends StatelessWidget {
const _WorkspaceEmptyState();

@override
Widget build(BuildContext context) {
// TODO(damian-molinski): Strings and looks is not final
return const Center(
child: EmptyState(
title: 'No proposals found',
description: 'Created proposals will appear here',
),
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import 'package:catalyst_voices/widgets/widgets.dart';
import 'package:catalyst_voices_blocs/catalyst_voices_blocs.dart';
import 'package:catalyst_voices_localization/catalyst_voices_localization.dart';
import 'package:catalyst_voices_view_models/catalyst_voices_view_models.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

typedef _StateData = ({bool show, LocalizedException? error});

class WorkspaceErrorSelector extends StatelessWidget {
const WorkspaceErrorSelector({super.key});

@override
Widget build(BuildContext context) {
return BlocSelector<WorkspaceBloc, WorkspaceState, _StateData>(
selector: (state) => (show: state.showError, error: state.error),
builder: (context, state) {
final errorMessage = state.error?.message(context);

return Offstage(
offstage: !state.show,
child: _WorkspaceError(
message: errorMessage ?? context.l10n.somethingWentWrong,
),
);
},
);
}
}

class _WorkspaceError extends StatelessWidget {
final String message;

const _WorkspaceError({
required this.message,
});

@override
Widget build(BuildContext context) {
return Center(
child: VoicesErrorIndicator(
message: message,
onRetry: () {
const event = LoadProposalsEvent();
context.read<WorkspaceBloc>().add(event);
},
),
);
}
}
Loading

0 comments on commit cfdd91d

Please sign in to comment.