Skip to content

Commit

Permalink
feat: Workspace (#795)
Browse files Browse the repository at this point in the history
* feat: Workspace - initial commit

* feat: Workspace - simplify WorkspaceProposalSegmentStep model

* feat: Workspace - fix conflicts after merge

* feat: Workspace - showSearch

* feat: Workspace - add richtext

* feat: Workspace - consistent styling

* feat: Workspace - add footer

* feat: Workspace - add shadow

* feat: Workspace - correct onSave

* feat: Workspace - sample rich text

* feat: Workspace - fix icons foreground

* feat: Workspace - extract sample_rich_text.dart

* feat: Workspace - add drawer

* feat: Workspace - add drawer, part 2

* feat: Workspace - style drawer

* feat: Workspace - IgnorePointer instead of ExcludeFocus

* feat: Workspace - Correct edit / cancel

* feat: Workspace - Fix flutter_quill version problem

* feat: Workspace - update shadow colors

* feat: Workspace - fix dark mode

* feat: Workspace - Damian's feedback

* feat: Workspace - Damian's feedback, part 2
  • Loading branch information
digitalheartxs authored Sep 13, 2024
1 parent 7f3a894 commit 6b53a99
Show file tree
Hide file tree
Showing 32 changed files with 951 additions and 244 deletions.
32 changes: 32 additions & 0 deletions catalyst_voices/lib/pages/spaces/my_private_proposals.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import 'package:catalyst_voices/widgets/widgets.dart';
import 'package:catalyst_voices_models/catalyst_voices_models.dart';
import 'package:flutter/material.dart';

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

@override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
SectionHeader(
leading: SizedBox(width: 12),
title: Text('My private proposals (3/5)'),
),
VoicesDrawerNavItem(
name: 'My first proposal',
status: ProposalStatus.draft,
),
VoicesDrawerNavItem(
name: 'My second proposal',
status: ProposalStatus.inProgress,
),
VoicesDrawerNavItem(
name: 'My third proposal',
status: ProposalStatus.inProgress,
),
],
);
}
}
14 changes: 13 additions & 1 deletion catalyst_voices/lib/pages/spaces/spaces_drawer.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:catalyst_voices/pages/spaces/individual_private_campaigns.dart';
import 'package:catalyst_voices/pages/spaces/my_private_proposals.dart';
import 'package:catalyst_voices/routes/routes.dart';
import 'package:catalyst_voices/widgets/widgets.dart';
import 'package:catalyst_voices_brands/catalyst_voices_brands.dart';
Expand All @@ -18,7 +19,7 @@ class SpacesDrawer extends StatelessWidget {
return VoicesDrawer(
children: [
_SpaceHeader(space),
if (space == Space.treasury) IndividualPrivateCampaigns(),
_space(),
],
bottom: VoicesDrawerSpaceChooser(
currentSpace: space,
Expand All @@ -30,6 +31,17 @@ class SpacesDrawer extends StatelessWidget {
);
}

Widget _space() {
switch (space) {
case Space.treasury:
return IndividualPrivateCampaigns();
case Space.workspace:
return MyPrivateProposals();
default:
return SizedBox();
}
}

void _goTo(
BuildContext context, {
required Space space,
Expand Down
6 changes: 3 additions & 3 deletions catalyst_voices/lib/pages/treasury/campaign_details.dart
Original file line number Diff line number Diff line change
Expand Up @@ -129,16 +129,16 @@ class _StepDetails extends StatelessWidget {

@override
Widget build(BuildContext context) {
return WorkspaceTileContainer(
return WorkspaceTextTileContainer(
name: name,
isSelected: isSelected,
headerActions: [
VoicesTextButton(
child: Text(context.l10n.treasuryStepEdit),
child: Text(context.l10n.stepEdit),
onTap: isEditable ? () {} : null,
),
],
content: Text(desc),
content: desc,
);
}
}
161 changes: 161 additions & 0 deletions catalyst_voices/lib/pages/workspace/proposal_details.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
import 'package:catalyst_voices/pages/workspace/proposal_segment_controller.dart';
import 'package:catalyst_voices/pages/workspace/workspace_proposal_navigation_ext.dart';
import 'package:catalyst_voices/widgets/rich_text/voices_rich_text.dart';
import 'package:catalyst_voices/widgets/widgets.dart';
import 'package:catalyst_voices_localization/catalyst_voices_localization.dart';
import 'package:catalyst_voices_models/catalyst_voices_models.dart';
import 'package:catalyst_voices_shared/catalyst_voices_shared.dart';
import 'package:flutter/material.dart';
import 'package:flutter_quill/flutter_quill.dart';

class ProposalDetails extends StatelessWidget {
final WorkspaceProposalNavigation navigation;

const ProposalDetails({
super.key,
required this.navigation,
});

@override
Widget build(BuildContext context) {
return ListView.builder(
padding: const EdgeInsets.only(top: 10),
itemCount: navigation.segments.length,
itemBuilder: (context, index) {
final segment = navigation.segments[index];

return _ListenableSegmentDetails(
key: ValueKey('ListenableSegment${segment.id}DetailsKey'),
segment: segment,
controller: ProposalControllerScope.of(
context,
id: segment.id,
),
);
},
);
}
}

class _ListenableSegmentDetails extends StatelessWidget {
final WorkspaceProposalSegment segment;
final VoicesNodeMenuController controller;

const _ListenableSegmentDetails({
super.key,
required this.segment,
required this.controller,
});

@override
Widget build(BuildContext context) {
return ValueListenableBuilder(
valueListenable: controller,
builder: (context, value, _) {
return _SegmentDetails(
key: ValueKey('Segment${segment.id}DetailsKey'),
name: segment.localizedName(context.l10n),
steps: segment.steps,
selected: controller.selected,
isExpanded: controller.isExpanded,
onChevronTap: () {
controller.isExpanded = !controller.isExpanded;
},
);
},
);
}
}

class _SegmentDetails extends StatelessWidget {
final String name;
final List<WorkspaceProposalSegmentStep> steps;
final int? selected;
final bool isExpanded;
final VoidCallback? onChevronTap;

const _SegmentDetails({
super.key,
required this.name,
required this.steps,
this.selected,
this.isExpanded = false,
this.onChevronTap,
});

@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
SegmentHeader(
leading: ChevronExpandButton(
onTap: onChevronTap,
isExpanded: isExpanded,
),
name: name,
isSelected: isExpanded,
),
if (isExpanded)
...steps.map(
(step) {
return _StepDetails(
key: ValueKey('WorkspaceStep${step.id}TileKey'),
id: step.id,
name: step.title,
desc: step.description,
doc: step.document,
isSelected: step.id == selected,
isEditable: step.isEditable,
);
},
),
SizedBox(height: 24),
].separatedBy(SizedBox(height: 12)).toList(),
);
}
}

class _StepDetails extends StatelessWidget {
const _StepDetails({
super.key,
required this.id,
required this.name,
this.desc,
this.doc,
this.isSelected = false,
this.isEditable = false,
});

final int id;
final String name;
final String? desc;
final Document? doc;
final bool isSelected;
final bool isEditable;

@override
Widget build(BuildContext context) {
return (desc != null)
? WorkspaceTextTileContainer(
name: name,
isSelected: isSelected,
headerActions: [
TextButton(
child: Text(
context.l10n.stepEdit,
style: Theme.of(context).textTheme.labelSmall,
),
onPressed: isEditable ? () {} : null,
),
],
content: desc!,
)
: WorkspaceTileContainer(
isSelected: isSelected,
content: VoicesRichText(
title: name,
document: doc,
),
);
}
}
72 changes: 72 additions & 0 deletions catalyst_voices/lib/pages/workspace/proposal_navigation_panel.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import 'package:catalyst_voices/pages/workspace/proposal_segment_controller.dart';
import 'package:catalyst_voices/pages/workspace/workspace_proposal_navigation_ext.dart';
import 'package:catalyst_voices/widgets/widgets.dart';
import 'package:catalyst_voices_localization/catalyst_voices_localization.dart';
import 'package:catalyst_voices_models/catalyst_voices_models.dart';
import 'package:flutter/material.dart';

class ProposalNavigationPanel extends StatelessWidget {
final WorkspaceProposalNavigation navigation;

const ProposalNavigationPanel({
required this.navigation,
});

@override
Widget build(BuildContext context) {
return SpaceSidePanel(
isLeft: true,
name: context.l10n.workspaceProposalNavigation,
onCollapseTap: () {},
tabs: [
if (navigation.segments.isNotEmpty)
SpaceSidePanelTab(
name: context.l10n.workspaceProposalNavigationSegments,
body: Column(
children: navigation.segments.map(
(segment) {
return _ProposalSegmentBody(
key: ValueKey('ProposalSegment${segment.id}Key'),
segment: segment,
controller: ProposalControllerScope.of(
context,
id: segment.id,
),
);
},
).toList(),
),
),
],
);
}
}

class _ProposalSegmentBody extends StatelessWidget {
final WorkspaceProposalSegment segment;
final VoicesNodeMenuController? controller;

const _ProposalSegmentBody({
super.key,
required this.segment,
this.controller,
});

@override
Widget build(BuildContext context) {
final l10n = context.l10n;

return VoicesNodeMenu(
name: segment.localizedName(l10n),
controller: controller,
items: segment.steps.map(
(step) {
return VoicesNodeMenuItem(
id: step.id,
label: step.title,
);
},
).toList(),
);
}
}
Loading

0 comments on commit 6b53a99

Please sign in to comment.