fixed duplicate tag issue

This commit is contained in:
hannathkadher
2025-01-21 15:21:25 +04:00
parent 0e912207e5
commit 81e9e58627
5 changed files with 283 additions and 261 deletions

View File

@ -49,12 +49,11 @@ class AssignTagModelBloc
emit(AssignTagModelLoaded( emit(AssignTagModelLoaded(
tags: allTags, tags: allTags,
isSaveEnabled: _validateTags(allTags), isSaveEnabled: _validateTags(allTags),
)); errorMessage: ''));
}); });
on<UpdateTag>((event, emit) { on<UpdateTag>((event, emit) {
final currentState = state; final currentState = state;
if (currentState is AssignTagModelLoaded && if (currentState is AssignTagModelLoaded &&
currentState.tags.isNotEmpty) { currentState.tags.isNotEmpty) {
final tags = List<TagModel>.from(currentState.tags); final tags = List<TagModel>.from(currentState.tags);
@ -122,9 +121,7 @@ class AssignTagModelBloc
} }
bool _validateTags(List<TagModel> tags) { bool _validateTags(List<TagModel> tags) {
if (tags.isEmpty) {
return false;
}
final uniqueTags = tags.map((tag) => tag.tag?.trim() ?? '').toSet(); final uniqueTags = tags.map((tag) => tag.tag?.trim() ?? '').toSet();
final hasEmptyTag = tags.any((tag) => (tag.tag?.trim() ?? '').isEmpty); final hasEmptyTag = tags.any((tag) => (tag.tag?.trim() ?? '').isEmpty);
final isValid = uniqueTags.length == tags.length && !hasEmptyTag; final isValid = uniqueTags.length == tags.length && !hasEmptyTag;
@ -133,7 +130,11 @@ class AssignTagModelBloc
String? _getValidationError(List<TagModel> tags) { String? _getValidationError(List<TagModel> tags) {
final hasEmptyTag = tags.any((tag) => (tag.tag?.trim() ?? '').isEmpty); final hasEmptyTag = tags.any((tag) => (tag.tag?.trim() ?? '').isEmpty);
if (hasEmptyTag) return 'Tags cannot be empty.'; if (hasEmptyTag) {
return 'Tags cannot be empty.';
}
// Check for duplicate tags
final duplicateTags = tags final duplicateTags = tags
.map((tag) => tag.tag?.trim() ?? '') .map((tag) => tag.tag?.trim() ?? '')
.fold<Map<String, int>>({}, (map, tag) { .fold<Map<String, int>>({}, (map, tag) {

View File

@ -5,7 +5,7 @@ abstract class AssignTagModelState extends Equatable {
const AssignTagModelState(); const AssignTagModelState();
@override @override
List<Object> get props => []; List<Object?> get props => [];
} }
class AssignTagModelInitial extends AssignTagModelState {} class AssignTagModelInitial extends AssignTagModelState {}
@ -24,7 +24,7 @@ class AssignTagModelLoaded extends AssignTagModelState {
}); });
@override @override
List<Object> get props => [tags, isSaveEnabled]; List<Object?> get props => [tags, isSaveEnabled, errorMessage];
} }
class AssignTagModelError extends AssignTagModelState { class AssignTagModelError extends AssignTagModelState {
@ -33,5 +33,5 @@ class AssignTagModelError extends AssignTagModelState {
const AssignTagModelError(this.errorMessage); const AssignTagModelError(this.errorMessage);
@override @override
List<Object> get props => [errorMessage]; List<Object?> get props => [errorMessage];
} }

View File

@ -52,6 +52,8 @@ class AssignTagModelsDialog extends StatelessWidget {
initialTags: initialTags, initialTags: initialTags,
addedProducts: addedProducts, addedProducts: addedProducts,
)), )),
child: BlocListener<AssignTagModelBloc, AssignTagModelState>(
listener: (context, state) {},
child: BlocBuilder<AssignTagModelBloc, AssignTagModelState>( child: BlocBuilder<AssignTagModelBloc, AssignTagModelState>(
builder: (context, state) { builder: (context, state) {
if (state is AssignTagModelLoaded) { if (state is AssignTagModelLoaded) {
@ -79,22 +81,26 @@ class AssignTagModelsDialog extends StatelessWidget {
columns: [ columns: [
DataColumn( DataColumn(
label: Text('#', label: Text('#',
style: style: Theme.of(context)
Theme.of(context).textTheme.bodyMedium)), .textTheme
.bodyMedium)),
DataColumn( DataColumn(
label: Text('Device', label: Text('Device',
style: style: Theme.of(context)
Theme.of(context).textTheme.bodyMedium)), .textTheme
.bodyMedium)),
DataColumn( DataColumn(
numeric: false, numeric: false,
headingRowAlignment: MainAxisAlignment.start, headingRowAlignment: MainAxisAlignment.start,
label: Text('Tag', label: Text('Tag',
style: style: Theme.of(context)
Theme.of(context).textTheme.bodyMedium)), .textTheme
.bodyMedium)),
DataColumn( DataColumn(
label: Text('Location', label: Text('Location',
style: style: Theme.of(context)
Theme.of(context).textTheme.bodyMedium)), .textTheme
.bodyMedium)),
], ],
rows: state.tags.isEmpty rows: state.tags.isEmpty
? [ ? [
@ -105,7 +111,8 @@ class AssignTagModelsDialog extends StatelessWidget {
'No Data Available', 'No Data Available',
style: TextStyle( style: TextStyle(
fontSize: 14, fontSize: 14,
color: ColorsManager.lightGrayColor, color:
ColorsManager.lightGrayColor,
), ),
), ),
), ),
@ -155,7 +162,8 @@ class AssignTagModelsDialog extends StatelessWidget {
), ),
onPressed: () { onPressed: () {
context context
.read<AssignTagModelBloc>() .read<
AssignTagModelBloc>()
.add(DeleteTagModel( .add(DeleteTagModel(
tagToDelete: tag, tagToDelete: tag,
tags: state.tags)); tags: state.tags));
@ -182,7 +190,8 @@ class AssignTagModelsDialog extends StatelessWidget {
onSelected: (value) { onSelected: (value) {
controller.text = value; controller.text = value;
context context
.read<AssignTagModelBloc>() .read<
AssignTagModelBloc>()
.add(UpdateTag( .add(UpdateTag(
index: index, index: index,
tag: value, tag: value,
@ -201,7 +210,8 @@ class AssignTagModelsDialog extends StatelessWidget {
tag.location ?? 'None', tag.location ?? 'None',
onSelected: (value) { onSelected: (value) {
context context
.read<AssignTagModelBloc>() .read<
AssignTagModelBloc>()
.add(UpdateLocation( .add(UpdateLocation(
index: index, index: index,
location: value, location: value,
@ -217,7 +227,8 @@ class AssignTagModelsDialog extends StatelessWidget {
if (state.errorMessage != null) if (state.errorMessage != null)
Text( Text(
state.errorMessage!, state.errorMessage!,
style: const TextStyle(color: ColorsManager.warningRed), style: const TextStyle(
color: ColorsManager.warningRed),
), ),
], ],
), ),
@ -233,23 +244,28 @@ class AssignTagModelsDialog extends StatelessWidget {
label: 'Add New Device', label: 'Add New Device',
onPressed: () async { onPressed: () async {
for (var tag in state.tags) { for (var tag in state.tags) {
if (tag.location == null || subspaces == null) { if (tag.location == null ||
subspaces == null) {
continue; continue;
} }
final previousTagSubspace = final previousTagSubspace =
checkTagExistInSubspace(tag, subspaces ?? []); checkTagExistInSubspace(
tag, subspaces ?? []);
if (tag.location == 'Main Space') { if (tag.location == 'Main Space') {
removeTagFromSubspace(tag, previousTagSubspace); removeTagFromSubspace(
tag, previousTagSubspace);
} else if (tag.location != } else if (tag.location !=
previousTagSubspace?.subspaceName) { previousTagSubspace?.subspaceName) {
removeTagFromSubspace(tag, previousTagSubspace); removeTagFromSubspace(
tag, previousTagSubspace);
moveToNewSubspace(tag, subspaces ?? []); moveToNewSubspace(tag, subspaces ?? []);
state.tags.removeWhere( state.tags.removeWhere(
(t) => t.internalId == tag.internalId); (t) => t.internalId == tag.internalId);
} else { } else {
updateTagInSubspace(tag, previousTagSubspace); updateTagInSubspace(
tag, previousTagSubspace);
state.tags.removeWhere( state.tags.removeWhere(
(t) => t.internalId == tag.internalId); (t) => t.internalId == tag.internalId);
} }
@ -308,13 +324,13 @@ class AssignTagModelsDialog extends StatelessWidget {
removeTagFromSubspace( removeTagFromSubspace(
tag, previousTagSubspace); tag, previousTagSubspace);
moveToNewSubspace(tag, subspaces ?? []); moveToNewSubspace(tag, subspaces ?? []);
state.tags.removeWhere( state.tags.removeWhere((t) =>
(t) => t.internalId == tag.internalId); t.internalId == tag.internalId);
} else { } else {
updateTagInSubspace( updateTagInSubspace(
tag, previousTagSubspace); tag, previousTagSubspace);
state.tags.removeWhere( state.tags.removeWhere((t) =>
(t) => t.internalId == tag.internalId); t.internalId == tag.internalId);
} }
} }
@ -336,7 +352,7 @@ class AssignTagModelsDialog extends StatelessWidget {
} }
}, },
), ),
); ));
} }
List<String> getAvailableTags( List<String> getAvailableTags(

View File

@ -3,7 +3,6 @@ import 'package:syncrow_web/pages/spaces_management/space_model/bloc/create_spac
import 'package:syncrow_web/pages/spaces_management/space_model/bloc/create_space_model_state.dart'; import 'package:syncrow_web/pages/spaces_management/space_model/bloc/create_space_model_state.dart';
import 'package:syncrow_web/pages/spaces_management/space_model/models/create_space_template_body_model.dart'; import 'package:syncrow_web/pages/spaces_management/space_model/models/create_space_template_body_model.dart';
import 'package:syncrow_web/pages/spaces_management/space_model/models/space_template_model.dart'; import 'package:syncrow_web/pages/spaces_management/space_model/models/space_template_model.dart';
import 'package:syncrow_web/pages/spaces_management/space_model/models/subspace_template_model.dart';
import 'package:syncrow_web/pages/spaces_management/space_model/models/tag_model.dart'; import 'package:syncrow_web/pages/spaces_management/space_model/models/tag_model.dart';
import 'package:syncrow_web/services/space_model_mang_api.dart'; import 'package:syncrow_web/services/space_model_mang_api.dart';
@ -53,6 +52,8 @@ class CreateSpaceModelBloc
} }
}); });
on<LoadSpaceTemplate>((event, emit) { on<LoadSpaceTemplate>((event, emit) {
emit(CreateSpaceModelLoading()); emit(CreateSpaceModelLoading());
Future.delayed(const Duration(seconds: 1), () { Future.delayed(const Duration(seconds: 1), () {

View File

@ -166,6 +166,10 @@ class CreateSpaceModelDialog extends StatelessWidget {
modelName: modelName:
spaceNameController.text.trim(), spaceNameController.text.trim(),
); );
if(updatedSpaceTemplate.uuid != null){
}
context.read<CreateSpaceModelBloc>().add( context.read<CreateSpaceModelBloc>().add(
CreateSpaceTemplate( CreateSpaceTemplate(
spaceTemplate: spaceTemplate: