mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-10 15:17:31 +00:00
add_user_dialog
This commit is contained in:
@ -7,7 +7,6 @@ import 'package:syncrow_web/pages/roles_and_permission/users_page/model/tree_nod
|
|||||||
import 'package:syncrow_web/pages/spaces_management/model/community_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/model/community_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/model/space_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/model/space_model.dart';
|
||||||
import 'package:syncrow_web/services/space_mana_api.dart';
|
import 'package:syncrow_web/services/space_mana_api.dart';
|
||||||
|
|
||||||
class UsersBloc extends Bloc<UsersEvent, UsersState> {
|
class UsersBloc extends Bloc<UsersEvent, UsersState> {
|
||||||
UsersBloc() : super(UsersInitial()) {
|
UsersBloc() : super(UsersInitial()) {
|
||||||
on<GetUsers>(_getUsers);
|
on<GetUsers>(_getUsers);
|
||||||
@ -15,6 +14,7 @@ class UsersBloc extends Bloc<UsersEvent, UsersState> {
|
|||||||
on<CheckStepStatus>(isCompleteBasicsFun);
|
on<CheckStepStatus>(isCompleteBasicsFun);
|
||||||
on<LoadCommunityAndSpacesEvent>(_onLoadCommunityAndSpaces);
|
on<LoadCommunityAndSpacesEvent>(_onLoadCommunityAndSpaces);
|
||||||
on<SearchAnode>(searchTreeNode);
|
on<SearchAnode>(searchTreeNode);
|
||||||
|
on<CheckSpacesStepStatus>(isCompleteSpacesFun);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<RolesUserModel> users = [];
|
List<RolesUserModel> users = [];
|
||||||
@ -62,7 +62,6 @@ class UsersBloc extends Bloc<UsersEvent, UsersState> {
|
|||||||
|
|
||||||
void _changeUserStatus(ChangeUserStatus event, Emitter<UsersState> emit) {
|
void _changeUserStatus(ChangeUserStatus event, Emitter<UsersState> emit) {
|
||||||
try {
|
try {
|
||||||
// Update the user's status
|
|
||||||
users = users.map((user) {
|
users = users.map((user) {
|
||||||
if (user.id == event.userId) {
|
if (user.id == event.userId) {
|
||||||
return RolesUserModel(
|
return RolesUserModel(
|
||||||
@ -111,21 +110,27 @@ class UsersBloc extends Bloc<UsersEvent, UsersState> {
|
|||||||
return isCompleteBasics;
|
return isCompleteBasics;
|
||||||
}
|
}
|
||||||
|
|
||||||
isCompleteSpacesFun(CheckStepStatus event, Emitter<UsersState> emit) {
|
void isCompleteSpacesFun(
|
||||||
|
CheckSpacesStepStatus event, Emitter<UsersState> emit) {
|
||||||
emit(UsersLoadingState());
|
emit(UsersLoadingState());
|
||||||
isCompleteSpaces = false;
|
|
||||||
|
try {
|
||||||
|
List<String> selectedIds =
|
||||||
|
getSelectedIds(updatedCommunities);
|
||||||
|
isCompleteSpaces = selectedIds.isNotEmpty;
|
||||||
|
} catch (e) {
|
||||||
|
emit(ErrorState('Error while retrieving selected IDs: $e'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
emit(ChangeStatusSteps());
|
emit(ChangeStatusSteps());
|
||||||
print('isCompleteBasics==$isCompleteSpaces');
|
|
||||||
return isCompleteSpaces;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool checkRolePermissions() {
|
bool checkRolePermissions() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool checkSpaces() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<List<SpaceModel>> _fetchSpacesForCommunity(
|
Future<List<SpaceModel>> _fetchSpacesForCommunity(
|
||||||
String communityUuid) async {
|
String communityUuid) async {
|
||||||
@ -134,83 +139,60 @@ class UsersBloc extends Bloc<UsersEvent, UsersState> {
|
|||||||
|
|
||||||
List<TreeNode> updatedCommunities = [];
|
List<TreeNode> updatedCommunities = [];
|
||||||
List<TreeNode> spacesNodes = [];
|
List<TreeNode> spacesNodes = [];
|
||||||
|
|
||||||
_onLoadCommunityAndSpaces(
|
_onLoadCommunityAndSpaces(
|
||||||
LoadCommunityAndSpacesEvent event,
|
LoadCommunityAndSpacesEvent event, Emitter<UsersState> emit) async {
|
||||||
Emitter<UsersState> emit,
|
|
||||||
) async {
|
|
||||||
emit(UsersLoadingState()); // Emit loading state
|
|
||||||
try {
|
try {
|
||||||
// Fetch the list of communities
|
emit(UsersLoadingState());
|
||||||
List<CommunityModel> communities =
|
List<CommunityModel> communities =
|
||||||
await CommunitySpaceManagementApi().fetchCommunities();
|
await CommunitySpaceManagementApi().fetchCommunities();
|
||||||
|
|
||||||
// Fetch spaces and create TreeNodes for each community
|
|
||||||
updatedCommunities = await Future.wait(
|
updatedCommunities = await Future.wait(
|
||||||
communities.map((community) async {
|
communities.map((community) async {
|
||||||
// Fetch spaces for the current community
|
|
||||||
List<SpaceModel> spaces =
|
List<SpaceModel> spaces =
|
||||||
await _fetchSpacesForCommunity(community.uuid);
|
await _fetchSpacesForCommunity(community.uuid);
|
||||||
|
|
||||||
// Recursively build the tree structure
|
|
||||||
spacesNodes = _buildTreeNodes(spaces);
|
spacesNodes = _buildTreeNodes(spaces);
|
||||||
|
|
||||||
// Return a TreeNode for the community, with spaces as its children
|
|
||||||
return TreeNode(
|
return TreeNode(
|
||||||
uuid: community.uuid,
|
uuid: community.uuid,
|
||||||
title: community.name,
|
title: community.name,
|
||||||
children: spacesNodes,
|
children: spacesNodes,
|
||||||
isChecked: false, // Initial state; can be updated later
|
isChecked: false,
|
||||||
isHighlighted: false,
|
isHighlighted: false,
|
||||||
isExpanded: true, // Default to expanded for better UX
|
isExpanded: true,
|
||||||
);
|
);
|
||||||
}).toList(),
|
}).toList(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Emit the final state with the structured tree
|
|
||||||
emit(ChangeStatusSteps());
|
emit(ChangeStatusSteps());
|
||||||
|
return updatedCommunities;
|
||||||
return updatedCommunities; // Return the structured data if needed
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Emit error state in case of failure
|
|
||||||
emit(ErrorState('Error loading communities and spaces: $e'));
|
emit(ErrorState('Error loading communities and spaces: $e'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper function to recursively build tree nodes
|
|
||||||
List<TreeNode> _buildTreeNodes(List<SpaceModel> spaces) {
|
List<TreeNode> _buildTreeNodes(List<SpaceModel> spaces) {
|
||||||
return spaces.map((space) {
|
return spaces.map((space) {
|
||||||
// If the space has children, recursively build nodes for them
|
|
||||||
List<TreeNode> childNodes =
|
List<TreeNode> childNodes =
|
||||||
space.children != null ? _buildTreeNodes(space.children!) : [];
|
space.children != null ? _buildTreeNodes(space.children) : [];
|
||||||
|
|
||||||
// Create a TreeNode for the current space
|
|
||||||
return TreeNode(
|
return TreeNode(
|
||||||
uuid: space.uuid!,
|
uuid: space.uuid!,
|
||||||
title: space.name,
|
title: space.name,
|
||||||
isChecked: false,
|
isChecked: false,
|
||||||
isHighlighted: false,
|
isHighlighted: false,
|
||||||
isExpanded: childNodes.isNotEmpty, // Expand if there are children
|
isExpanded: childNodes.isNotEmpty,
|
||||||
children: childNodes,
|
children: childNodes,
|
||||||
);
|
);
|
||||||
}).toList();
|
}).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
void searchTreeNode(SearchAnode event, Emitter<UsersState> emit) {
|
void searchTreeNode(SearchAnode event, Emitter<UsersState> emit) {
|
||||||
emit(UsersLoadingState()); // Emit loading state
|
emit(UsersLoadingState());
|
||||||
|
|
||||||
// Clear all highlights if the search term is empty
|
|
||||||
if (event.searchTerm!.isEmpty) {
|
if (event.searchTerm!.isEmpty) {
|
||||||
_clearHighlights(updatedCommunities);
|
_clearHighlights(updatedCommunities);
|
||||||
} else {
|
} else {
|
||||||
// Perform the search and update the highlights
|
|
||||||
_searchAndHighlightNodes(updatedCommunities, event.searchTerm!);
|
_searchAndHighlightNodes(updatedCommunities, event.searchTerm!);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Emit the updated state after processing all nodes
|
|
||||||
emit(ChangeStatusSteps());
|
emit(ChangeStatusSteps());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper function to clear all highlights in the tree
|
|
||||||
void _clearHighlights(List<TreeNode> nodes) {
|
void _clearHighlights(List<TreeNode> nodes) {
|
||||||
for (var node in nodes) {
|
for (var node in nodes) {
|
||||||
node.isHighlighted = false;
|
node.isHighlighted = false;
|
||||||
@ -220,25 +202,32 @@ class UsersBloc extends Bloc<UsersEvent, UsersState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper function to search and highlight nodes recursively
|
|
||||||
bool _searchAndHighlightNodes(List<TreeNode> nodes, String searchTerm) {
|
bool _searchAndHighlightNodes(List<TreeNode> nodes, String searchTerm) {
|
||||||
bool anyMatch = false;
|
bool anyMatch = false;
|
||||||
|
|
||||||
for (var node in nodes) {
|
for (var node in nodes) {
|
||||||
// Check if this node matches the search term
|
|
||||||
bool isMatch =
|
bool isMatch =
|
||||||
node.title.toLowerCase().contains(searchTerm.toLowerCase());
|
node.title.toLowerCase().contains(searchTerm.toLowerCase());
|
||||||
|
|
||||||
// Recursively check children for matches
|
|
||||||
bool childMatch = _searchAndHighlightNodes(node.children, searchTerm);
|
bool childMatch = _searchAndHighlightNodes(node.children, searchTerm);
|
||||||
|
|
||||||
// Highlight this node if it matches or any of its children match
|
|
||||||
node.isHighlighted = isMatch || childMatch;
|
node.isHighlighted = isMatch || childMatch;
|
||||||
|
|
||||||
// Update if any matches were found in this branch
|
|
||||||
anyMatch = anyMatch || node.isHighlighted;
|
anyMatch = anyMatch || node.isHighlighted;
|
||||||
}
|
}
|
||||||
|
|
||||||
return anyMatch;
|
return anyMatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<String> selectedIds = [];
|
||||||
|
List<String> getSelectedIds(List<TreeNode> nodes) {
|
||||||
|
List<String> selectedIds = [];
|
||||||
|
for (var node in nodes) {
|
||||||
|
if (node.isChecked) {
|
||||||
|
selectedIds.add(node.uuid);
|
||||||
|
}
|
||||||
|
if (node.children.isNotEmpty) {
|
||||||
|
selectedIds.addAll(getSelectedIds(node.children));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return selectedIds;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,11 @@ class GetUsers extends UsersEvent {
|
|||||||
@override
|
@override
|
||||||
List<Object?> get props => [];
|
List<Object?> get props => [];
|
||||||
}
|
}
|
||||||
|
class CheckSpacesStepStatus extends UsersEvent {
|
||||||
|
const CheckSpacesStepStatus();
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [];
|
||||||
|
}
|
||||||
|
|
||||||
class LoadCommunityAndSpacesEvent extends UsersEvent {
|
class LoadCommunityAndSpacesEvent extends UsersEvent {
|
||||||
const LoadCommunityAndSpacesEvent();
|
const LoadCommunityAndSpacesEvent();
|
||||||
@ -49,3 +54,9 @@ class SearchAnode extends UsersEvent {
|
|||||||
@override
|
@override
|
||||||
List<Object?> get props => [nodes, searchTerm];
|
List<Object?> get props => [nodes, searchTerm];
|
||||||
}
|
}
|
||||||
|
class SelecteId extends UsersEvent {
|
||||||
|
List<TreeNode>? nodes;
|
||||||
|
SelecteId({this.nodes,});
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [nodes];
|
||||||
|
}
|
||||||
|
@ -23,7 +23,8 @@ class _AddNewUserDialogState extends State<AddNewUserDialog> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (BuildContext context) => UsersBloc()..add(LoadCommunityAndSpacesEvent()),
|
create: (BuildContext context) =>
|
||||||
|
UsersBloc()..add(LoadCommunityAndSpacesEvent()),
|
||||||
child: BlocConsumer<UsersBloc, UsersState>(
|
child: BlocConsumer<UsersBloc, UsersState>(
|
||||||
listener: (context, state) {},
|
listener: (context, state) {},
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
@ -121,11 +122,11 @@ class _AddNewUserDialogState extends State<AddNewUserDialog> {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _getFormContent() {
|
Widget _getFormContent() {
|
||||||
@ -162,7 +163,9 @@ class _AddNewUserDialogState extends State<AddNewUserDialog> {
|
|||||||
? Assets.currentProcessIcon
|
? Assets.currentProcessIcon
|
||||||
: bloc.isCompleteSpaces == false
|
: bloc.isCompleteSpaces == false
|
||||||
? Assets.wrongProcessIcon
|
? Assets.wrongProcessIcon
|
||||||
: Assets.uncomplete_ProcessIcon,
|
: bloc.isCompleteSpaces == true
|
||||||
|
? Assets.completeProcessIcon
|
||||||
|
: Assets.uncomplete_ProcessIcon,
|
||||||
width: 25,
|
width: 25,
|
||||||
height: 25,
|
height: 25,
|
||||||
),
|
),
|
||||||
@ -263,6 +266,7 @@ class _AddNewUserDialogState extends State<AddNewUserDialog> {
|
|||||||
onTap: () {
|
onTap: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
currentStep = step;
|
currentStep = step;
|
||||||
|
bloc.add(const CheckSpacesStepStatus());
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
child: Column(
|
child: Column(
|
||||||
|
@ -125,6 +125,7 @@ class SpacesAccessView extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ignore: must_be_immutable
|
// ignore: must_be_immutable
|
||||||
|
|
||||||
class TreeView extends StatefulWidget {
|
class TreeView extends StatefulWidget {
|
||||||
UsersBloc? bloc;
|
UsersBloc? bloc;
|
||||||
TreeView({super.key, this.bloc});
|
TreeView({super.key, this.bloc});
|
||||||
@ -155,6 +156,8 @@ class _TreeViewState extends State<TreeView> {
|
|||||||
node.isChecked = !node.isChecked;
|
node.isChecked = !node.isChecked;
|
||||||
_updateChildrenCheckStatus(node, node.isChecked);
|
_updateChildrenCheckStatus(node, node.isChecked);
|
||||||
_updateParentCheckStatus(node);
|
_updateParentCheckStatus(node);
|
||||||
|
// widget.bloc!.add(
|
||||||
|
// SelecteId(nodes: widget.bloc!.updatedCommunities));
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
child: Image.asset(
|
child: Image.asset(
|
||||||
@ -210,7 +213,6 @@ class _TreeViewState extends State<TreeView> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine the appropriate image based on the check state
|
|
||||||
String _getCheckBoxImage(TreeNode node) {
|
String _getCheckBoxImage(TreeNode node) {
|
||||||
if (node.children.isEmpty) {
|
if (node.children.isEmpty) {
|
||||||
return node.isChecked ? Assets.CheckBoxChecked : Assets.emptyBox;
|
return node.isChecked ? Assets.CheckBoxChecked : Assets.emptyBox;
|
||||||
@ -224,7 +226,6 @@ class _TreeViewState extends State<TreeView> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper to determine if all children are checked
|
|
||||||
bool _areAllChildrenChecked(TreeNode node) {
|
bool _areAllChildrenChecked(TreeNode node) {
|
||||||
return node.children.isNotEmpty &&
|
return node.children.isNotEmpty &&
|
||||||
node.children.every((child) =>
|
node.children.every((child) =>
|
||||||
@ -232,7 +233,6 @@ class _TreeViewState extends State<TreeView> {
|
|||||||
(child.children.isEmpty || _areAllChildrenChecked(child)));
|
(child.children.isEmpty || _areAllChildrenChecked(child)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper to determine if some children are checked
|
|
||||||
bool _areSomeChildrenChecked(TreeNode node) {
|
bool _areSomeChildrenChecked(TreeNode node) {
|
||||||
return node.children.isNotEmpty &&
|
return node.children.isNotEmpty &&
|
||||||
node.children.any((child) =>
|
node.children.any((child) =>
|
||||||
@ -240,7 +240,6 @@ class _TreeViewState extends State<TreeView> {
|
|||||||
(child.children.isNotEmpty && _areSomeChildrenChecked(child)));
|
(child.children.isNotEmpty && _areSomeChildrenChecked(child)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the checkbox state for all children
|
|
||||||
void _updateChildrenCheckStatus(TreeNode node, bool isChecked) {
|
void _updateChildrenCheckStatus(TreeNode node, bool isChecked) {
|
||||||
for (var child in node.children) {
|
for (var child in node.children) {
|
||||||
child.isChecked = isChecked;
|
child.isChecked = isChecked;
|
||||||
@ -248,18 +247,16 @@ class _TreeViewState extends State<TreeView> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the checkbox state for parent nodes
|
|
||||||
void _updateParentCheckStatus(TreeNode node) {
|
void _updateParentCheckStatus(TreeNode node) {
|
||||||
TreeNode? parent = _findParent(widget.bloc!.updatedCommunities, node);
|
TreeNode? parent = _findParent(widget.bloc!.updatedCommunities, node);
|
||||||
if (parent != null) {
|
if (parent != null) {
|
||||||
setState(() {
|
setState(() {
|
||||||
parent.isChecked = _areAllChildrenChecked(parent);
|
parent.isChecked = _areAllChildrenChecked(parent);
|
||||||
_updateParentCheckStatus(parent); // Recursively update ancestors
|
_updateParentCheckStatus(parent);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper to find a node's parent
|
|
||||||
TreeNode? _findParent(List<TreeNode> nodes, TreeNode target) {
|
TreeNode? _findParent(List<TreeNode> nodes, TreeNode target) {
|
||||||
for (var node in nodes) {
|
for (var node in nodes) {
|
||||||
if (node.children.contains(target)) {
|
if (node.children.contains(target)) {
|
||||||
|
Reference in New Issue
Block a user