mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-10 07:07:19 +00:00
Sp 1711 fe implement blank state (#288)
<!-- Thanks for contributing! Provide a description of your changes below and a general summary in the title Please look at the following checklist to ensure that your PR can be accepted quickly: --> ## Jira Ticket [SP-1711](https://syncrow.atlassian.net/browse/SP-1711) [SP-1712](https://syncrow.atlassian.net/browse/SP-1712) ## Description 1. Shows tooltip on space cell. 2. navigates to space when a new space is selected 3. Fixed a thrown Exception because of an Expanded widget 4. Adjusted connections between spaces to select from and to nodes. 5. Created a `SpaceDetailsDialog` and a helper class to show it, because a space can be created through different widgets, and this was done to unify the logic and remove code duplication. ## Type of Change <!--- Put an `x` in all the boxes that apply: --> - [x] ✨ New feature (non-breaking change which adds functionality) - [x] 🛠️ Bug fix (non-breaking change which fixes an issue) - [ ] ❌ Breaking change (fix or feature that would cause existing functionality to change) - [ ] 🧹 Code refactor - [ ] ✅ Build configuration change - [ ] 📝 Documentation - [ ] 🗑️ Chore [SP-1711]: https://syncrow.atlassian.net/browse/SP-1711?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ [SP-1712]: https://syncrow.atlassian.net/browse/SP-1712?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
This commit is contained in:
@ -7,21 +7,22 @@ class SpacesConnectionsArrowPainter extends CustomPainter {
|
|||||||
final Map<String, Offset> positions;
|
final Map<String, Offset> positions;
|
||||||
final double cardWidth = 150.0;
|
final double cardWidth = 150.0;
|
||||||
final double cardHeight = 90.0;
|
final double cardHeight = 90.0;
|
||||||
final String? selectedSpaceUuid;
|
final Set<String> highlightedUuids;
|
||||||
|
|
||||||
SpacesConnectionsArrowPainter({
|
SpacesConnectionsArrowPainter({
|
||||||
required this.connections,
|
required this.connections,
|
||||||
required this.positions,
|
required this.positions,
|
||||||
this.selectedSpaceUuid,
|
required this.highlightedUuids,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void paint(Canvas canvas, Size size) {
|
void paint(Canvas canvas, Size size) {
|
||||||
for (final connection in connections) {
|
for (final connection in connections) {
|
||||||
final isSelected = connection.to == selectedSpaceUuid;
|
final isSelected = highlightedUuids.contains(connection.from) ||
|
||||||
|
highlightedUuids.contains(connection.to);
|
||||||
final paint = Paint()
|
final paint = Paint()
|
||||||
..color = isSelected
|
..color = isSelected
|
||||||
? ColorsManager.primaryColor
|
? ColorsManager.blackColor
|
||||||
: ColorsManager.blackColor.withValues(alpha: 0.5)
|
: ColorsManager.blackColor.withValues(alpha: 0.5)
|
||||||
..strokeWidth = 2.0
|
..strokeWidth = 2.0
|
||||||
..style = PaintingStyle.stroke;
|
..style = PaintingStyle.stroke;
|
||||||
@ -36,7 +37,7 @@ class SpacesConnectionsArrowPainter extends CustomPainter {
|
|||||||
|
|
||||||
final path = Path()..moveTo(startPoint.dx, startPoint.dy);
|
final path = Path()..moveTo(startPoint.dx, startPoint.dy);
|
||||||
|
|
||||||
final controlPoint1 = Offset(startPoint.dx, startPoint.dy + 60);
|
final controlPoint1 = Offset(startPoint.dx, startPoint.dy + 20);
|
||||||
final controlPoint2 = Offset(endPoint.dx, endPoint.dy - 60);
|
final controlPoint2 = Offset(endPoint.dx, endPoint.dy - 60);
|
||||||
|
|
||||||
path.cubicTo(controlPoint1.dx, controlPoint1.dy, controlPoint2.dx,
|
path.cubicTo(controlPoint1.dx, controlPoint1.dy, controlPoint2.dx,
|
||||||
@ -46,7 +47,7 @@ class SpacesConnectionsArrowPainter extends CustomPainter {
|
|||||||
|
|
||||||
final circlePaint = Paint()
|
final circlePaint = Paint()
|
||||||
..color = isSelected
|
..color = isSelected
|
||||||
? ColorsManager.primaryColor
|
? ColorsManager.blackColor
|
||||||
: ColorsManager.blackColor.withValues(alpha: 0.5)
|
: ColorsManager.blackColor.withValues(alpha: 0.5)
|
||||||
..style = PaintingStyle.fill
|
..style = PaintingStyle.fill
|
||||||
..blendMode = BlendMode.srcIn;
|
..blendMode = BlendMode.srcIn;
|
||||||
|
@ -1,21 +1,26 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/space_management_v2/main_module/models/space_connection_model.dart';
|
import 'package:syncrow_web/pages/space_management_v2/main_module/models/space_connection_model.dart';
|
||||||
import 'package:syncrow_web/pages/space_management_v2/main_module/painters/spaces_connections_arrow_painter.dart';
|
import 'package:syncrow_web/pages/space_management_v2/main_module/painters/spaces_connections_arrow_painter.dart';
|
||||||
import 'package:syncrow_web/pages/space_management_v2/main_module/widgets/space_card_widget.dart';
|
import 'package:syncrow_web/pages/space_management_v2/main_module/widgets/space_card_widget.dart';
|
||||||
import 'package:syncrow_web/pages/space_management_v2/main_module/widgets/space_cell.dart';
|
import 'package:syncrow_web/pages/space_management_v2/main_module/widgets/space_cell.dart';
|
||||||
import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain/models/community_model.dart';
|
import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain/models/community_model.dart';
|
||||||
import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain/models/space_model.dart';
|
import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain/models/space_model.dart';
|
||||||
|
import 'package:syncrow_web/pages/space_management_v2/modules/communities/presentation/communities_tree_selection_bloc/communities_tree_selection_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/space_management_v2/modules/space_details/presentation/helpers/space_details_dialog_helper.dart';
|
||||||
|
|
||||||
class CommunityStructureCanvas extends StatefulWidget {
|
class CommunityStructureCanvas extends StatefulWidget {
|
||||||
const CommunityStructureCanvas({
|
const CommunityStructureCanvas({
|
||||||
required this.community,
|
required this.community,
|
||||||
|
required this.selectedSpace,
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
|
|
||||||
final CommunityModel community;
|
final CommunityModel community;
|
||||||
|
final SpaceModel? selectedSpace;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<CommunityStructureCanvas> createState() =>_CommunityStructureCanvasState();
|
State<CommunityStructureCanvas> createState() => _CommunityStructureCanvasState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _CommunityStructureCanvasState extends State<CommunityStructureCanvas>
|
class _CommunityStructureCanvasState extends State<CommunityStructureCanvas>
|
||||||
@ -25,19 +30,30 @@ class _CommunityStructureCanvasState extends State<CommunityStructureCanvas>
|
|||||||
final double _cardHeight = 90.0;
|
final double _cardHeight = 90.0;
|
||||||
final double _horizontalSpacing = 150.0;
|
final double _horizontalSpacing = 150.0;
|
||||||
final double _verticalSpacing = 120.0;
|
final double _verticalSpacing = 120.0;
|
||||||
String? _selectedSpaceUuid;
|
|
||||||
|
|
||||||
late TransformationController _transformationController;
|
late TransformationController _transformationController;
|
||||||
late AnimationController _animationController;
|
late AnimationController _animationController;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
|
||||||
_transformationController = TransformationController();
|
_transformationController = TransformationController();
|
||||||
_animationController = AnimationController(
|
_animationController = AnimationController(
|
||||||
vsync: this,
|
vsync: this,
|
||||||
duration: const Duration(milliseconds: 100),
|
duration: const Duration(milliseconds: 150),
|
||||||
);
|
);
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didUpdateWidget(covariant CommunityStructureCanvas oldWidget) {
|
||||||
|
super.didUpdateWidget(oldWidget);
|
||||||
|
if (widget.selectedSpace?.uuid != oldWidget.selectedSpace?.uuid) {
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
if (mounted) {
|
||||||
|
_animateToSpace(widget.selectedSpace);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -47,6 +63,15 @@ class _CommunityStructureCanvasState extends State<CommunityStructureCanvas>
|
|||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Set<String> _getAllDescendantUuids(SpaceModel space) {
|
||||||
|
final uuids = <String>{};
|
||||||
|
for (final child in space.children) {
|
||||||
|
uuids.add(child.uuid);
|
||||||
|
uuids.addAll(_getAllDescendantUuids(child));
|
||||||
|
}
|
||||||
|
return uuids;
|
||||||
|
}
|
||||||
|
|
||||||
void _runAnimation(Matrix4 target) {
|
void _runAnimation(Matrix4 target) {
|
||||||
final animation = Matrix4Tween(
|
final animation = Matrix4Tween(
|
||||||
begin: _transformationController.value,
|
begin: _transformationController.value,
|
||||||
@ -63,15 +88,16 @@ class _CommunityStructureCanvasState extends State<CommunityStructureCanvas>
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onSpaceTapped(String spaceUuid) {
|
void _animateToSpace(SpaceModel? space) {
|
||||||
setState(() {
|
if (space == null) {
|
||||||
_selectedSpaceUuid = spaceUuid;
|
_runAnimation(Matrix4.identity());
|
||||||
});
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
final position = _positions[spaceUuid];
|
final position = _positions[space.uuid];
|
||||||
if (position == null) return;
|
if (position == null) return;
|
||||||
|
|
||||||
const scale = 2.0;
|
const scale = 1.5;
|
||||||
final viewSize = context.size;
|
final viewSize = context.size;
|
||||||
if (viewSize == null) return;
|
if (viewSize == null) return;
|
||||||
|
|
||||||
@ -86,11 +112,19 @@ class _CommunityStructureCanvasState extends State<CommunityStructureCanvas>
|
|||||||
_runAnimation(matrix);
|
_runAnimation(matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _onSpaceTapped(SpaceModel? space) {
|
||||||
|
context.read<CommunitiesTreeSelectionBloc>().add(
|
||||||
|
SelectSpaceEvent(community: widget.community, space: space),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
void _resetSelectionAndZoom() {
|
void _resetSelectionAndZoom() {
|
||||||
setState(() {
|
context.read<CommunitiesTreeSelectionBloc>().add(
|
||||||
_selectedSpaceUuid = null;
|
SelectSpaceEvent(
|
||||||
});
|
community: widget.community,
|
||||||
_runAnimation(Matrix4.identity());
|
space: null,
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _calculateLayout(
|
void _calculateLayout(
|
||||||
@ -150,16 +184,23 @@ class _CommunityStructureCanvasState extends State<CommunityStructureCanvas>
|
|||||||
|
|
||||||
_calculateLayout(community.spaces, 0, {});
|
_calculateLayout(community.spaces, 0, {});
|
||||||
|
|
||||||
|
final selectedSpace = widget.selectedSpace;
|
||||||
|
final highlightedUuids = <String>{};
|
||||||
|
if (selectedSpace != null) {
|
||||||
|
highlightedUuids.add(selectedSpace.uuid);
|
||||||
|
highlightedUuids.addAll(_getAllDescendantUuids(selectedSpace));
|
||||||
|
}
|
||||||
|
|
||||||
final widgets = <Widget>[];
|
final widgets = <Widget>[];
|
||||||
final connections = <SpaceConnectionModel>[];
|
final connections = <SpaceConnectionModel>[];
|
||||||
_generateWidgets(community.spaces, widgets, connections);
|
_generateWidgets(community.spaces, widgets, connections, highlightedUuids);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
CustomPaint(
|
CustomPaint(
|
||||||
painter: SpacesConnectionsArrowPainter(
|
painter: SpacesConnectionsArrowPainter(
|
||||||
connections: connections,
|
connections: connections,
|
||||||
positions: _positions,
|
positions: _positions,
|
||||||
selectedSpaceUuid: _selectedSpaceUuid,
|
highlightedUuids: highlightedUuids,
|
||||||
),
|
),
|
||||||
child: Stack(alignment: AlignmentDirectional.center, children: widgets),
|
child: Stack(alignment: AlignmentDirectional.center, children: widgets),
|
||||||
),
|
),
|
||||||
@ -170,11 +211,15 @@ class _CommunityStructureCanvasState extends State<CommunityStructureCanvas>
|
|||||||
List<SpaceModel> spaces,
|
List<SpaceModel> spaces,
|
||||||
List<Widget> widgets,
|
List<Widget> widgets,
|
||||||
List<SpaceConnectionModel> connections,
|
List<SpaceConnectionModel> connections,
|
||||||
|
Set<String> highlightedUuids,
|
||||||
) {
|
) {
|
||||||
for (final space in spaces) {
|
for (final space in spaces) {
|
||||||
final position = _positions[space.uuid];
|
final position = _positions[space.uuid];
|
||||||
if (position == null) continue;
|
if (position == null) continue;
|
||||||
|
|
||||||
|
final isHighlighted = highlightedUuids.contains(space.uuid);
|
||||||
|
final hasNoSelectedSpace = widget.selectedSpace == null;
|
||||||
|
|
||||||
widgets.add(
|
widgets.add(
|
||||||
Positioned(
|
Positioned(
|
||||||
left: position.dx,
|
left: position.dx,
|
||||||
@ -182,32 +227,31 @@ class _CommunityStructureCanvasState extends State<CommunityStructureCanvas>
|
|||||||
width: _cardWidth,
|
width: _cardWidth,
|
||||||
height: _cardHeight,
|
height: _cardHeight,
|
||||||
child: SpaceCardWidget(
|
child: SpaceCardWidget(
|
||||||
index: spaces.indexOf(space),
|
buildSpaceContainer: () {
|
||||||
onPositionChanged: (newPosition) {},
|
|
||||||
buildSpaceContainer: (index) {
|
|
||||||
return Opacity(
|
return Opacity(
|
||||||
opacity: 1.0,
|
opacity: hasNoSelectedSpace || isHighlighted ? 1.0 : 0.5,
|
||||||
child: SpaceCell(
|
child: Tooltip(
|
||||||
index: index,
|
message: space.spaceName,
|
||||||
onTap: () => _onSpaceTapped(space.uuid),
|
preferBelow: false,
|
||||||
icon: space.icon,
|
child: SpaceCell(
|
||||||
name: space.spaceName,
|
onTap: () => _onSpaceTapped(space),
|
||||||
|
icon: space.icon,
|
||||||
|
name: space.spaceName,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
screenSize: MediaQuery.sizeOf(context),
|
onTap: () => SpaceDetailsDialogHelper.showCreate(context),
|
||||||
position: position,
|
|
||||||
isHovered: false,
|
|
||||||
onHoverChanged: (int index, bool isHovered) {},
|
|
||||||
onButtonTap: (int index, Offset newPosition) {},
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
for (final child in space.children) {
|
for (final child in space.children) {
|
||||||
connections.add(SpaceConnectionModel(from: space.uuid, to: child.uuid));
|
connections.add(
|
||||||
|
SpaceConnectionModel(from: space.uuid, to: child.uuid),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
_generateWidgets(space.children, widgets, connections);
|
_generateWidgets(space.children, widgets, connections, highlightedUuids);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -218,7 +262,7 @@ class _CommunityStructureCanvasState extends State<CommunityStructureCanvas>
|
|||||||
transformationController: _transformationController,
|
transformationController: _transformationController,
|
||||||
boundaryMargin: EdgeInsets.symmetric(
|
boundaryMargin: EdgeInsets.symmetric(
|
||||||
horizontal: MediaQuery.sizeOf(context).width * 0.3,
|
horizontal: MediaQuery.sizeOf(context).width * 0.3,
|
||||||
vertical: MediaQuery.sizeOf(context).height * 0.2,
|
vertical: MediaQuery.sizeOf(context).height * 0.3,
|
||||||
),
|
),
|
||||||
minScale: 0.5,
|
minScale: 0.5,
|
||||||
maxScale: 3.0,
|
maxScale: 3.0,
|
||||||
@ -226,8 +270,8 @@ class _CommunityStructureCanvasState extends State<CommunityStructureCanvas>
|
|||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
onTap: _resetSelectionAndZoom,
|
onTap: _resetSelectionAndZoom,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
width: MediaQuery.sizeOf(context).width * 2,
|
width: MediaQuery.sizeOf(context).width * 5,
|
||||||
height: MediaQuery.sizeOf(context).height * 2,
|
height: MediaQuery.sizeOf(context).height * 5,
|
||||||
child: Stack(children: treeWidgets),
|
child: Stack(children: treeWidgets),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:syncrow_web/pages/space_management_v2/modules/space_details/presentation/helpers/space_details_dialog_helper.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
|
||||||
class CreateSpaceButton extends StatelessWidget {
|
class CreateSpaceButton extends StatelessWidget {
|
||||||
@ -7,7 +8,7 @@ class CreateSpaceButton extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: () {},
|
onTap: () => SpaceDetailsDialogHelper.showCreate(context),
|
||||||
child: Container(
|
child: Container(
|
||||||
height: 60,
|
height: 60,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
|
@ -2,15 +2,11 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
|
||||||
class PlusButtonWidget extends StatelessWidget {
|
class PlusButtonWidget extends StatelessWidget {
|
||||||
final int index;
|
|
||||||
final String direction;
|
|
||||||
final Offset offset;
|
final Offset offset;
|
||||||
final void Function(int index, Offset newPosition) onButtonTap;
|
final void Function() onButtonTap;
|
||||||
|
|
||||||
const PlusButtonWidget({
|
const PlusButtonWidget({
|
||||||
super.key,
|
super.key,
|
||||||
required this.index,
|
|
||||||
required this.direction,
|
|
||||||
required this.offset,
|
required this.offset,
|
||||||
required this.onButtonTap,
|
required this.onButtonTap,
|
||||||
});
|
});
|
||||||
@ -18,13 +14,7 @@ class PlusButtonWidget extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: () {
|
onTap: onButtonTap,
|
||||||
if (direction == 'down') {
|
|
||||||
onButtonTap(index, const Offset(0, 150));
|
|
||||||
} else {
|
|
||||||
onButtonTap(index, const Offset(150, 0));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
child: Container(
|
child: Container(
|
||||||
width: 30,
|
width: 30,
|
||||||
height: 30,
|
height: 30,
|
||||||
|
@ -1,60 +1,39 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:syncrow_web/pages/space_management_v2/main_module/widgets/plus_button_widget.dart';
|
import 'package:syncrow_web/pages/space_management_v2/main_module/widgets/plus_button_widget.dart';
|
||||||
|
|
||||||
class SpaceCardWidget extends StatelessWidget {
|
class SpaceCardWidget extends StatefulWidget {
|
||||||
final int index;
|
final void Function() onTap;
|
||||||
final Size screenSize;
|
final Widget Function() buildSpaceContainer;
|
||||||
final Offset position;
|
|
||||||
final bool isHovered;
|
|
||||||
final void Function(int index, bool isHovered) onHoverChanged;
|
|
||||||
final void Function(int index, Offset newPosition) onButtonTap;
|
|
||||||
final Widget Function(int index) buildSpaceContainer;
|
|
||||||
final ValueChanged<Offset> onPositionChanged;
|
|
||||||
|
|
||||||
const SpaceCardWidget({
|
const SpaceCardWidget({
|
||||||
super.key,
|
required this.onTap,
|
||||||
required this.index,
|
|
||||||
required this.onPositionChanged,
|
|
||||||
required this.screenSize,
|
|
||||||
required this.position,
|
|
||||||
required this.isHovered,
|
|
||||||
required this.onHoverChanged,
|
|
||||||
required this.onButtonTap,
|
|
||||||
required this.buildSpaceContainer,
|
required this.buildSpaceContainer,
|
||||||
|
super.key,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<SpaceCardWidget> createState() => _SpaceCardWidgetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _SpaceCardWidgetState extends State<SpaceCardWidget> {
|
||||||
|
bool isHovered = false;
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return MouseRegion(
|
return MouseRegion(
|
||||||
onEnter: (_) => onHoverChanged(index, true),
|
onEnter: (_) => setState(() => isHovered = true),
|
||||||
onExit: (_) => onHoverChanged(index, false),
|
onExit: (_) => setState(() => isHovered = false),
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
width: 150,
|
|
||||||
height: 90,
|
|
||||||
child: Stack(
|
child: Stack(
|
||||||
clipBehavior: Clip.none,
|
clipBehavior: Clip.none,
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
children: [
|
children: [
|
||||||
buildSpaceContainer(index),
|
widget.buildSpaceContainer(),
|
||||||
|
|
||||||
if (isHovered)
|
if (isHovered)
|
||||||
Positioned(
|
Positioned(
|
||||||
bottom: 0,
|
bottom: 0,
|
||||||
child: PlusButtonWidget(
|
child: PlusButtonWidget(
|
||||||
index: index,
|
|
||||||
direction: 'down',
|
|
||||||
offset: Offset.zero,
|
offset: Offset.zero,
|
||||||
onButtonTap: onButtonTap,
|
onButtonTap: widget.onTap,
|
||||||
),
|
|
||||||
),
|
|
||||||
if (isHovered)
|
|
||||||
Positioned(
|
|
||||||
right: -15,
|
|
||||||
child: PlusButtonWidget(
|
|
||||||
index: index,
|
|
||||||
direction: 'right',
|
|
||||||
offset: Offset.zero,
|
|
||||||
onButtonTap: onButtonTap,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -1,29 +1,23 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
import 'package:syncrow_web/utils/extension/build_context_x.dart';
|
||||||
|
|
||||||
class SpaceCell extends StatelessWidget {
|
class SpaceCell extends StatelessWidget {
|
||||||
final int index;
|
|
||||||
final String icon;
|
final String icon;
|
||||||
final String name;
|
final String name;
|
||||||
final VoidCallback? onDoubleTap;
|
|
||||||
final VoidCallback? onTap;
|
final VoidCallback? onTap;
|
||||||
|
|
||||||
const SpaceCell({
|
const SpaceCell({
|
||||||
super.key,
|
super.key,
|
||||||
required this.index,
|
|
||||||
required this.icon,
|
required this.icon,
|
||||||
required this.name,
|
required this.name,
|
||||||
this.onTap,
|
required this.onTap,
|
||||||
this.onDoubleTap,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final theme = Theme.of(context);
|
|
||||||
|
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onDoubleTap: onDoubleTap,
|
|
||||||
onTap: onTap,
|
onTap: onTap,
|
||||||
child: Container(
|
child: Container(
|
||||||
width: 150,
|
width: 150,
|
||||||
@ -36,7 +30,7 @@ class SpaceCell extends StatelessWidget {
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: Text(
|
child: Text(
|
||||||
name,
|
name,
|
||||||
style: theme.textTheme.bodyLarge?.copyWith(
|
style: context.textTheme.bodyLarge?.copyWith(
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
color: ColorsManager.blackColor,
|
color: ColorsManager.blackColor,
|
||||||
),
|
),
|
||||||
@ -63,7 +57,10 @@ class SpaceCell extends StatelessWidget {
|
|||||||
child: Center(
|
child: Center(
|
||||||
child: SvgPicture.asset(
|
child: SvgPicture.asset(
|
||||||
icon,
|
icon,
|
||||||
color: ColorsManager.whiteColors,
|
colorFilter: const ColorFilter.mode(
|
||||||
|
ColorsManager.whiteColors,
|
||||||
|
BlendMode.srcIn,
|
||||||
|
),
|
||||||
width: 24,
|
width: 24,
|
||||||
height: 24,
|
height: 24,
|
||||||
),
|
),
|
||||||
|
@ -9,14 +9,19 @@ class SpaceManagementCommunityStructure extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final selectedCommunity =
|
final selectionBloc = context.watch<CommunitiesTreeSelectionBloc>().state;
|
||||||
context.watch<CommunitiesTreeSelectionBloc>().state.selectedCommunity!;
|
final selectedCommunity = selectionBloc.selectedCommunity;
|
||||||
|
final selectedSpace = selectionBloc.selectedSpace;
|
||||||
const spacer = Spacer(flex: 10);
|
const spacer = Spacer(flex: 10);
|
||||||
return Visibility(
|
return Visibility(
|
||||||
visible: selectedCommunity.spaces.isNotEmpty,
|
visible: selectedCommunity!.spaces.isNotEmpty,
|
||||||
replacement: const Row(
|
replacement: const Row(
|
||||||
children: [spacer, Expanded(child: CreateSpaceButton()), spacer]),
|
children: [spacer, Expanded(child: CreateSpaceButton()), spacer],
|
||||||
child: CommunityStructureCanvas(community: selectedCommunity),
|
),
|
||||||
|
child: CommunityStructureCanvas(
|
||||||
|
community: selectedCommunity,
|
||||||
|
selectedSpace: selectedSpace,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,26 +7,24 @@ class SpaceManagementTemplatesView extends StatelessWidget {
|
|||||||
const SpaceManagementTemplatesView({super.key});
|
const SpaceManagementTemplatesView({super.key});
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Expanded(
|
return ColoredBox(
|
||||||
child: ColoredBox(
|
color: ColorsManager.whiteColors,
|
||||||
color: ColorsManager.whiteColors,
|
child: GridView.builder(
|
||||||
child: GridView.builder(
|
padding: const EdgeInsets.symmetric(horizontal: 40, vertical: 20),
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 40, vertical: 20),
|
gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
|
||||||
gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
|
maxCrossAxisExtent: 400,
|
||||||
maxCrossAxisExtent: 400,
|
mainAxisSpacing: 10,
|
||||||
mainAxisSpacing: 10,
|
crossAxisSpacing: 10,
|
||||||
crossAxisSpacing: 10,
|
childAspectRatio: 2.0,
|
||||||
childAspectRatio: 2.0,
|
|
||||||
),
|
|
||||||
itemCount: _gridItems(context).length,
|
|
||||||
itemBuilder: (context, index) {
|
|
||||||
final model = _gridItems(context)[index];
|
|
||||||
return CommunityTemplateCell(
|
|
||||||
onTap: model.onTap,
|
|
||||||
title: model.title,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
|
itemCount: _gridItems(context).length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final model = _gridItems(context)[index];
|
||||||
|
return CommunityTemplateCell(
|
||||||
|
onTap: model.onTap,
|
||||||
|
title: model.title,
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ final class SelectCommunityEvent extends CommunitiesTreeSelectionEvent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final class SelectSpaceEvent extends CommunitiesTreeSelectionEvent {
|
final class SelectSpaceEvent extends CommunitiesTreeSelectionEvent {
|
||||||
final SpaceModel space;
|
final SpaceModel? space;
|
||||||
final CommunityModel community;
|
final CommunityModel community;
|
||||||
|
|
||||||
const SelectSpaceEvent({required this.space, required this.community});
|
const SelectSpaceEvent({required this.space, required this.community});
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:syncrow_web/pages/space_management_v2/modules/space_details/presentation/widgets/space_details_dialog.dart';
|
||||||
|
|
||||||
|
abstract final class SpaceDetailsDialogHelper {
|
||||||
|
static void showCreate(BuildContext context) {
|
||||||
|
showDialog<void>(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => const SpaceDetailsDialog(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class SpaceDetailsDialog extends StatelessWidget {
|
||||||
|
const SpaceDetailsDialog({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return const Dialog(
|
||||||
|
child: Text('Create Space'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user