mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-10 07:07:19 +00:00
377 lines
13 KiB
Dart
377 lines
13 KiB
Dart
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
import 'package:syncrow_web/pages/common/bloc/project_manager.dart';
|
|
import 'package:syncrow_web/pages/space_tree/bloc/space_tree_event.dart';
|
|
import 'package:syncrow_web/pages/space_tree/bloc/space_tree_state.dart';
|
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart';
|
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart';
|
|
import 'package:syncrow_web/services/space_mana_api.dart';
|
|
|
|
class SpaceTreeBloc extends Bloc<SpaceTreeEvent, SpaceTreeState> {
|
|
SpaceTreeBloc() : super(const SpaceTreeState()) {
|
|
on<InitialEvent>(_fetchSpaces);
|
|
on<OnCommunityExpanded>(_onCommunityExpanded);
|
|
on<OnSpaceExpanded>(_onSpaceExpanded);
|
|
on<OnCommunitySelected>(_onCommunitySelected);
|
|
on<OnSpaceSelected>(_onSpaceSelected);
|
|
on<SearchQueryEvent>(_onSearch);
|
|
on<ClearAllData>(_clearAllData);
|
|
on<ClearCachedData>(_clearCachedData);
|
|
}
|
|
|
|
_fetchSpaces(InitialEvent event, Emitter<SpaceTreeState> emit) async {
|
|
emit(SpaceTreeLoadingState());
|
|
try {
|
|
final projectUuid = await ProjectManager.getProjectUUID() ?? '';
|
|
|
|
List<CommunityModel> communities =
|
|
await CommunitySpaceManagementApi().fetchCommunities(projectUuid);
|
|
|
|
List<CommunityModel> updatedCommunities = await Future.wait(
|
|
communities.map((community) async {
|
|
List<SpaceModel> spaces =
|
|
await CommunitySpaceManagementApi().getSpaceHierarchy(community.uuid, projectUuid);
|
|
|
|
return CommunityModel(
|
|
uuid: community.uuid,
|
|
createdAt: community.createdAt,
|
|
updatedAt: community.updatedAt,
|
|
name: community.name,
|
|
description: community.description,
|
|
spaces: spaces,
|
|
region: community.region,
|
|
);
|
|
}).toList(),
|
|
);
|
|
|
|
emit(state.copyWith(
|
|
communitiesList: updatedCommunities, expandedCommunity: [], expandedSpaces: []));
|
|
} catch (e) {
|
|
emit(SpaceTreeErrorState('Error loading communities and spaces: $e'));
|
|
}
|
|
}
|
|
|
|
_onCommunityExpanded(OnCommunityExpanded event, Emitter<SpaceTreeState> emit) async {
|
|
try {
|
|
List<String> updatedExpandedCommunityList = List.from(state.expandedCommunities);
|
|
|
|
if (updatedExpandedCommunityList.contains(event.communityId)) {
|
|
updatedExpandedCommunityList.remove(event.communityId);
|
|
} else {
|
|
updatedExpandedCommunityList.add(event.communityId);
|
|
}
|
|
|
|
emit(state.copyWith(
|
|
expandedCommunity: updatedExpandedCommunityList,
|
|
));
|
|
} catch (e) {
|
|
emit(const SpaceTreeErrorState('Something went wrong'));
|
|
}
|
|
}
|
|
|
|
_onSpaceExpanded(OnSpaceExpanded event, Emitter<SpaceTreeState> emit) async {
|
|
try {
|
|
List<String> updatedExpandedSpacesList = List.from(state.expandedSpaces);
|
|
|
|
if (updatedExpandedSpacesList.contains(event.spaceId)) {
|
|
updatedExpandedSpacesList.remove(event.spaceId);
|
|
} else {
|
|
updatedExpandedSpacesList.add(event.spaceId);
|
|
}
|
|
|
|
emit(state.copyWith(expandedSpaces: updatedExpandedSpacesList));
|
|
} catch (e) {
|
|
emit(const SpaceTreeErrorState('Something went wrong'));
|
|
}
|
|
}
|
|
|
|
_onCommunitySelected(OnCommunitySelected event, Emitter<SpaceTreeState> emit) async {
|
|
try {
|
|
List<String> updatedSelectedCommunities =
|
|
List.from(state.selectedCommunities.toSet().toList());
|
|
List<String> updatedSelectedSpaces = List.from(state.selectedSpaces.toSet().toList());
|
|
List<String> updatedSoldChecks = List.from(state.soldCheck.toSet().toList());
|
|
Map<String, List<String>> communityAndSpaces = Map.from(state.selectedCommunityAndSpaces);
|
|
List<String> selectedSpacesInCommunity = communityAndSpaces[event.communityId] ?? [];
|
|
|
|
List<String> childrenIds = _getAllChildIds(event.children);
|
|
|
|
if (!updatedSelectedCommunities.contains(event.communityId)) {
|
|
// Select the community and all its children
|
|
updatedSelectedCommunities.add(event.communityId);
|
|
updatedSelectedSpaces.addAll(childrenIds);
|
|
selectedSpacesInCommunity.addAll(childrenIds);
|
|
} else {
|
|
// Unselect the community and all its children
|
|
updatedSelectedCommunities.remove(event.communityId);
|
|
updatedSelectedSpaces.removeWhere(childrenIds.contains);
|
|
updatedSoldChecks.removeWhere(childrenIds.contains);
|
|
selectedSpacesInCommunity.removeWhere(childrenIds.contains);
|
|
}
|
|
|
|
communityAndSpaces[event.communityId] = selectedSpacesInCommunity;
|
|
|
|
emit(state.copyWith(
|
|
selectedCommunities: updatedSelectedCommunities,
|
|
selectedSpaces: updatedSelectedSpaces,
|
|
soldCheck: updatedSoldChecks,
|
|
selectedCommunityAndSpaces: communityAndSpaces));
|
|
} catch (e) {
|
|
emit(const SpaceTreeErrorState('Something went wrong'));
|
|
}
|
|
}
|
|
|
|
_onSpaceSelected(OnSpaceSelected event, Emitter<SpaceTreeState> emit) async {
|
|
try {
|
|
List<String> updatedSelectedCommunities =
|
|
List.from(state.selectedCommunities.toSet().toList());
|
|
List<String> updatedSelectedSpaces = List.from(state.selectedSpaces.toSet().toList());
|
|
List<String> updatedSoldChecks = List.from(state.soldCheck.toSet().toList());
|
|
Map<String, List<String>> communityAndSpaces = Map.from(state.selectedCommunityAndSpaces);
|
|
|
|
List<String> selectedSpacesInCommunity = communityAndSpaces[event.communityModel.uuid] ?? [];
|
|
|
|
List<String> childrenIds = _getAllChildIds(event.children);
|
|
bool isChildSelected = false;
|
|
|
|
for (String id in childrenIds) {
|
|
if (updatedSelectedSpaces.contains(id)) {
|
|
isChildSelected = true;
|
|
}
|
|
}
|
|
|
|
if (!updatedSelectedSpaces.contains(event.spaceId) &&
|
|
!updatedSoldChecks.contains(event.spaceId)) {
|
|
// First click: Select the space and all its children
|
|
updatedSelectedSpaces.add(event.spaceId);
|
|
updatedSelectedCommunities.add(event.communityModel.uuid);
|
|
selectedSpacesInCommunity.add(event.spaceId);
|
|
|
|
if (childrenIds.isNotEmpty) {
|
|
updatedSelectedSpaces.addAll(childrenIds);
|
|
selectedSpacesInCommunity.addAll(childrenIds);
|
|
}
|
|
|
|
List<String> spaces = _getThePathToChild(event.communityModel.uuid, event.spaceId);
|
|
for (String space in spaces) {
|
|
if (!updatedSelectedSpaces.contains(space) && !updatedSoldChecks.contains(space)) {
|
|
updatedSoldChecks.add(space);
|
|
}
|
|
}
|
|
} else if (!updatedSoldChecks.contains(event.spaceId) &&
|
|
childrenIds.isNotEmpty &&
|
|
isChildSelected) {
|
|
// Second click: Unselect space but keep children
|
|
selectedSpacesInCommunity.remove(event.spaceId);
|
|
updatedSelectedSpaces.remove(event.spaceId);
|
|
updatedSoldChecks.add(event.spaceId);
|
|
} else {
|
|
// Third click: Unselect space and all its children
|
|
selectedSpacesInCommunity.remove(event.spaceId);
|
|
updatedSelectedSpaces.remove(event.spaceId);
|
|
if (childrenIds.isNotEmpty) {
|
|
updatedSelectedSpaces.removeWhere(childrenIds.contains);
|
|
updatedSoldChecks.removeWhere(childrenIds.contains);
|
|
selectedSpacesInCommunity.removeWhere(childrenIds.contains);
|
|
}
|
|
updatedSoldChecks.remove(event.spaceId);
|
|
|
|
List<String> parents =
|
|
_getThePathToChild(event.communityModel.uuid, event.spaceId).toSet().toList();
|
|
|
|
if (updatedSelectedSpaces.isEmpty) {
|
|
updatedSoldChecks.removeWhere(parents.contains);
|
|
updatedSelectedCommunities.remove(event.communityModel.uuid);
|
|
} else {
|
|
// Check if any parent has selected children
|
|
for (String space in parents) {
|
|
if (!_noChildrenSelected(event.communityModel, space, updatedSelectedSpaces, parents)) {
|
|
updatedSoldChecks.remove(space);
|
|
}
|
|
}
|
|
|
|
if (!_anySpacesSelectedInCommunity(
|
|
event.communityModel, updatedSelectedSpaces, updatedSoldChecks)) {
|
|
updatedSelectedCommunities.remove(event.communityModel.uuid);
|
|
}
|
|
}
|
|
}
|
|
|
|
communityAndSpaces[event.communityModel.uuid] = selectedSpacesInCommunity;
|
|
|
|
emit(state.copyWith(
|
|
selectedCommunities: updatedSelectedCommunities.toSet().toList(),
|
|
selectedSpaces: updatedSelectedSpaces,
|
|
soldCheck: updatedSoldChecks,
|
|
selectedCommunityAndSpaces: communityAndSpaces));
|
|
emit(state.copyWith(selectedSpaces: updatedSelectedSpaces));
|
|
} catch (e) {
|
|
emit(const SpaceTreeErrorState('Something went wrong'));
|
|
}
|
|
}
|
|
|
|
_noChildrenSelected(
|
|
CommunityModel community, String spaceId, List<String> selectedSpaces, List<String> parents) {
|
|
if (selectedSpaces.contains(spaceId)) {
|
|
return true;
|
|
}
|
|
|
|
List<SpaceModel> children = _getAllChildSpaces(community.spaces);
|
|
for (var child in children) {
|
|
if (spaceId == child.uuid) {
|
|
List<String> ids = _getAllChildIds(child.children);
|
|
for (var id in ids) {
|
|
if (selectedSpaces.contains(id)) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
_onSearch(SearchQueryEvent event, Emitter<SpaceTreeState> emit) async {
|
|
try {
|
|
List<CommunityModel> communities = List.from(state.communityList);
|
|
List<CommunityModel> filteredCommunity = [];
|
|
|
|
// Filter communities and expand only those that match the query
|
|
filteredCommunity = communities.where((community) {
|
|
final containsQueryInCommunity =
|
|
community.name.toLowerCase().contains(event.searchQuery.toLowerCase());
|
|
final containsQueryInSpaces =
|
|
community.spaces.any((space) => _containsQuery(space, event.searchQuery.toLowerCase()));
|
|
|
|
return containsQueryInCommunity || containsQueryInSpaces;
|
|
}).toList();
|
|
|
|
emit(state.copyWith(
|
|
filteredCommunity: filteredCommunity,
|
|
isSearching: event.searchQuery.isNotEmpty,
|
|
searchQuery: event.searchQuery));
|
|
} catch (e) {
|
|
emit(const SpaceTreeErrorState('Something went wrong'));
|
|
}
|
|
}
|
|
|
|
_clearAllData(ClearAllData event, Emitter<SpaceTreeState> emit) async {
|
|
try {
|
|
emit(state.copyWith(
|
|
communitiesList: [],
|
|
filteredCommunity: [],
|
|
isSearching: false,
|
|
soldCheck: [],
|
|
selectedSpaces: [],
|
|
selectedCommunities: [],
|
|
selectedCommunityAndSpaces: {},
|
|
searchQuery: '',
|
|
expandedSpaces: [],
|
|
expandedCommunity: []));
|
|
} catch (e) {
|
|
emit(const SpaceTreeErrorState('Something went wrong'));
|
|
}
|
|
}
|
|
|
|
_clearCachedData(ClearCachedData event, Emitter<SpaceTreeState> emit) async {
|
|
try {
|
|
emit(state.copyWith(
|
|
communitiesList: state.communityList,
|
|
filteredCommunity: [],
|
|
isSearching: false,
|
|
soldCheck: [],
|
|
selectedSpaces: [],
|
|
selectedCommunities: [],
|
|
selectedCommunityAndSpaces: {},
|
|
searchQuery: '',
|
|
expandedSpaces: [],
|
|
expandedCommunity: []));
|
|
} catch (e) {
|
|
emit(const SpaceTreeErrorState('Something went wrong'));
|
|
}
|
|
}
|
|
|
|
// Helper function to determine if any space or its children match the search query
|
|
bool _containsQuery(SpaceModel space, String query) {
|
|
final matchesSpace = space.name.toLowerCase().contains(query);
|
|
final matchesChildren =
|
|
space.children.any((child) => _containsQuery(child, query)); // Recursive check for children
|
|
|
|
return matchesSpace || matchesChildren;
|
|
}
|
|
|
|
List<String> _getAllChildIds(List<SpaceModel> spaces) {
|
|
List<String> ids = [];
|
|
for (var child in spaces) {
|
|
ids.add(child.uuid!);
|
|
ids.addAll(_getAllChildIds(child.children));
|
|
}
|
|
return ids.toSet().toList();
|
|
}
|
|
|
|
List<SpaceModel> _getAllChildSpaces(List<SpaceModel> spaces) {
|
|
List<SpaceModel> children = [];
|
|
for (var child in spaces) {
|
|
children.add(child);
|
|
children.addAll(_getAllChildSpaces(child.children));
|
|
}
|
|
return children;
|
|
}
|
|
|
|
bool _anySpacesSelectedInCommunity(
|
|
CommunityModel community, List<String> selectedSpaces, List<String> partialCheckedList) {
|
|
bool result = false;
|
|
List<String> ids = _getAllChildIds(community.spaces);
|
|
for (var id in ids) {
|
|
result = selectedSpaces.contains(id) || partialCheckedList.contains(id);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
List<String> _getThePathToChild(String communityId, String selectedSpaceId) {
|
|
List<String> ids = [];
|
|
for (var community in state.communityList) {
|
|
if (community.uuid == communityId) {
|
|
for (var space in community.spaces) {
|
|
List<String> list = [];
|
|
list.add(space.uuid!);
|
|
ids = _getAllParentsIds(space, selectedSpaceId, List.from(list));
|
|
if (ids.isNotEmpty) {
|
|
return ids;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return ids;
|
|
}
|
|
|
|
List<String> _getAllParentsIds(SpaceModel child, String spaceId, List<String> listIds) {
|
|
List<String> ids = listIds;
|
|
|
|
ids.add(child.uuid ?? '');
|
|
|
|
if (child.uuid == spaceId) {
|
|
return ids;
|
|
}
|
|
|
|
if (child.children.isNotEmpty) {
|
|
for (var space in child.children) {
|
|
var result = _getAllParentsIds(space, spaceId, List.from(ids));
|
|
if (result.isNotEmpty) {
|
|
return result;
|
|
}
|
|
}
|
|
}
|
|
|
|
ids.removeLast();
|
|
return [];
|
|
}
|
|
|
|
@override
|
|
Future<void> close() async {
|
|
super.close();
|
|
}
|
|
}
|