mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-10 07:07:19 +00:00
add tags
This commit is contained in:
@ -24,6 +24,8 @@ class AddDeviceTypeWidget extends StatelessWidget {
|
|||||||
final String spaceName;
|
final String spaceName;
|
||||||
final bool isCreate;
|
final bool isCreate;
|
||||||
final Function(List<Tag>, List<SubspaceModel>?)? onSave;
|
final Function(List<Tag>, List<SubspaceModel>?)? onSave;
|
||||||
|
final List<Tag> projectTags;
|
||||||
|
|
||||||
|
|
||||||
const AddDeviceTypeWidget(
|
const AddDeviceTypeWidget(
|
||||||
{super.key,
|
{super.key,
|
||||||
@ -35,7 +37,8 @@ class AddDeviceTypeWidget extends StatelessWidget {
|
|||||||
this.allTags,
|
this.allTags,
|
||||||
this.spaceTags,
|
this.spaceTags,
|
||||||
this.onSave,
|
this.onSave,
|
||||||
required this.spaceName});
|
required this.spaceName,
|
||||||
|
required this.projectTags});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -134,7 +137,8 @@ class AddDeviceTypeWidget extends StatelessWidget {
|
|||||||
spaceName: spaceName,
|
spaceName: spaceName,
|
||||||
initialTags: initialTags,
|
initialTags: initialTags,
|
||||||
title: dialogTitle,
|
title: dialogTitle,
|
||||||
onSave: onSave),
|
onSave: onSave,
|
||||||
|
projectTags: projectTags),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -296,11 +296,10 @@ class SpaceManagementBloc extends Bloc<SpaceManagementEvent, SpaceManagementStat
|
|||||||
// Fetch space models after communities are available
|
// Fetch space models after communities are available
|
||||||
final prevSpaceModels = await fetchSpaceModels();
|
final prevSpaceModels = await fetchSpaceModels();
|
||||||
emit(SpaceManagementLoaded(
|
emit(SpaceManagementLoaded(
|
||||||
communities: communities,
|
communities: communities,
|
||||||
products: _cachedProducts ?? [],
|
products: _cachedProducts ?? [],
|
||||||
spaceModels: prevSpaceModels,
|
spaceModels: prevSpaceModels,
|
||||||
allTags: _cachedTags ?? []
|
allTags: _cachedTags ?? []));
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<CommunityModel>> _waitForCommunityList(SpaceTreeBloc spaceBloc) async {
|
Future<List<CommunityModel>> _waitForCommunityList(SpaceTreeBloc spaceBloc) async {
|
||||||
@ -365,13 +364,13 @@ class SpaceManagementBloc extends Bloc<SpaceManagementEvent, SpaceManagementStat
|
|||||||
_spaceTreeBloc.add(OnCommunityAdded(newCommunity));
|
_spaceTreeBloc.add(OnCommunityAdded(newCommunity));
|
||||||
|
|
||||||
emit(SpaceManagementLoaded(
|
emit(SpaceManagementLoaded(
|
||||||
spaceModels: prevSpaceModels,
|
spaceModels: prevSpaceModels,
|
||||||
communities: updatedCommunities,
|
communities: updatedCommunities,
|
||||||
products: _cachedProducts ?? [],
|
products: _cachedProducts ?? [],
|
||||||
selectedCommunity: newCommunity,
|
selectedCommunity: newCommunity,
|
||||||
selectedSpace: null,
|
selectedSpace: null,
|
||||||
allTags: _cachedTags ?? [],
|
allTags: _cachedTags ?? [],
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
emit(const SpaceManagementError('Error creating community'));
|
emit(const SpaceManagementError('Error creating community'));
|
||||||
@ -492,7 +491,7 @@ class SpaceManagementBloc extends Bloc<SpaceManagementEvent, SpaceManagementStat
|
|||||||
selectedCommunity: community,
|
selectedCommunity: community,
|
||||||
selectedSpace: null,
|
selectedSpace: null,
|
||||||
spaceModels: prevSpaceModels,
|
spaceModels: prevSpaceModels,
|
||||||
allTags: _cachedTags ??[]));
|
allTags: _cachedTags ?? []));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -557,7 +556,7 @@ class SpaceManagementBloc extends Bloc<SpaceManagementEvent, SpaceManagementStat
|
|||||||
for (var tag in newSubspace.tags!) {
|
for (var tag in newSubspace.tags!) {
|
||||||
tagUpdates.add(TagModelUpdate(
|
tagUpdates.add(TagModelUpdate(
|
||||||
action: custom_action.Action.add,
|
action: custom_action.Action.add,
|
||||||
uuid: tag.uuid == '' ? null : tag.uuid,
|
newTagUuid: tag.uuid == '' ? null : tag.uuid,
|
||||||
tag: tag.tag,
|
tag: tag.tag,
|
||||||
productUuid: tag.product?.uuid));
|
productUuid: tag.product?.uuid));
|
||||||
}
|
}
|
||||||
@ -695,11 +694,10 @@ class SpaceManagementBloc extends Bloc<SpaceManagementEvent, SpaceManagementStat
|
|||||||
}
|
}
|
||||||
|
|
||||||
emit(SpaceModelLoaded(
|
emit(SpaceModelLoaded(
|
||||||
communities: communities,
|
communities: communities,
|
||||||
products: _cachedProducts ?? [],
|
products: _cachedProducts ?? [],
|
||||||
spaceModels: prevSpaceModels,
|
spaceModels: prevSpaceModels,
|
||||||
allTags: _cachedTags ?? []
|
allTags: _cachedTags ?? []));
|
||||||
));
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(SpaceManagementError('Error loading communities and spaces: $e'));
|
emit(SpaceManagementError('Error loading communities and spaces: $e'));
|
||||||
}
|
}
|
||||||
@ -717,7 +715,7 @@ class SpaceManagementBloc extends Bloc<SpaceManagementEvent, SpaceManagementStat
|
|||||||
tagUpdates.add(TagModelUpdate(
|
tagUpdates.add(TagModelUpdate(
|
||||||
action: custom_action.Action.add,
|
action: custom_action.Action.add,
|
||||||
tag: newTag.tag,
|
tag: newTag.tag,
|
||||||
uuid: newTag.uuid,
|
newTagUuid: newTag.uuid,
|
||||||
productUuid: newTag.product?.uuid,
|
productUuid: newTag.product?.uuid,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@ -750,7 +748,7 @@ class SpaceManagementBloc extends Bloc<SpaceManagementEvent, SpaceManagementStat
|
|||||||
tagUpdates.add(TagModelUpdate(
|
tagUpdates.add(TagModelUpdate(
|
||||||
action: custom_action.Action.add,
|
action: custom_action.Action.add,
|
||||||
tag: newTag.tag,
|
tag: newTag.tag,
|
||||||
uuid: newTag.uuid == '' ? null : newTag.uuid,
|
newTagUuid: newTag.uuid == '' ? null : newTag.uuid,
|
||||||
productUuid: newTag.product?.uuid));
|
productUuid: newTag.product?.uuid));
|
||||||
processedTags.add(newTag.tag);
|
processedTags.add(newTag.tag);
|
||||||
}
|
}
|
||||||
@ -767,6 +765,7 @@ class SpaceManagementBloc extends Bloc<SpaceManagementEvent, SpaceManagementStat
|
|||||||
tagUpdates.add(TagModelUpdate(
|
tagUpdates.add(TagModelUpdate(
|
||||||
action: custom_action.Action.update,
|
action: custom_action.Action.update,
|
||||||
uuid: newTag.uuid,
|
uuid: newTag.uuid,
|
||||||
|
newTagUuid: newTag.uuid,
|
||||||
tag: newTag.tag,
|
tag: newTag.tag,
|
||||||
));
|
));
|
||||||
} else {}
|
} else {}
|
||||||
|
@ -36,16 +36,17 @@ class CommunityStructureArea extends StatefulWidget {
|
|||||||
final List<CommunityModel> communities;
|
final List<CommunityModel> communities;
|
||||||
final List<SpaceModel> spaces;
|
final List<SpaceModel> spaces;
|
||||||
final List<SpaceTemplateModel>? spaceModels;
|
final List<SpaceTemplateModel>? spaceModels;
|
||||||
|
final List<Tag> projectTags;
|
||||||
|
|
||||||
CommunityStructureArea({
|
CommunityStructureArea(
|
||||||
this.selectedCommunity,
|
{this.selectedCommunity,
|
||||||
this.selectedSpace,
|
this.selectedSpace,
|
||||||
required this.communities,
|
required this.communities,
|
||||||
this.products,
|
this.products,
|
||||||
required this.spaces,
|
required this.spaces,
|
||||||
this.onSpaceSelected,
|
this.onSpaceSelected,
|
||||||
this.spaceModels,
|
this.spaceModels,
|
||||||
});
|
required this.projectTags});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_CommunityStructureAreaState createState() => _CommunityStructureAreaState();
|
_CommunityStructureAreaState createState() => _CommunityStructureAreaState();
|
||||||
@ -64,8 +65,7 @@ class _CommunityStructureAreaState extends State<CommunityStructureArea> {
|
|||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
spaces = widget.spaces.isNotEmpty ? flattenSpaces(widget.spaces) : [];
|
spaces = widget.spaces.isNotEmpty ? flattenSpaces(widget.spaces) : [];
|
||||||
connections =
|
connections = widget.spaces.isNotEmpty ? createConnections(widget.spaces) : [];
|
||||||
widget.spaces.isNotEmpty ? createConnections(widget.spaces) : [];
|
|
||||||
_adjustCanvasSizeForSpaces();
|
_adjustCanvasSizeForSpaces();
|
||||||
_nameController = TextEditingController(
|
_nameController = TextEditingController(
|
||||||
text: widget.selectedCommunity?.name ?? '',
|
text: widget.selectedCommunity?.name ?? '',
|
||||||
@ -92,14 +92,12 @@ class _CommunityStructureAreaState extends State<CommunityStructureArea> {
|
|||||||
if (oldWidget.spaces != widget.spaces) {
|
if (oldWidget.spaces != widget.spaces) {
|
||||||
setState(() {
|
setState(() {
|
||||||
spaces = widget.spaces.isNotEmpty ? flattenSpaces(widget.spaces) : [];
|
spaces = widget.spaces.isNotEmpty ? flattenSpaces(widget.spaces) : [];
|
||||||
connections =
|
connections = widget.spaces.isNotEmpty ? createConnections(widget.spaces) : [];
|
||||||
widget.spaces.isNotEmpty ? createConnections(widget.spaces) : [];
|
|
||||||
_adjustCanvasSizeForSpaces();
|
_adjustCanvasSizeForSpaces();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (widget.selectedSpace != oldWidget.selectedSpace &&
|
if (widget.selectedSpace != oldWidget.selectedSpace && widget.selectedSpace != null) {
|
||||||
widget.selectedSpace != null) {
|
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
_moveToSpace(widget.selectedSpace!);
|
_moveToSpace(widget.selectedSpace!);
|
||||||
});
|
});
|
||||||
@ -182,8 +180,7 @@ class _CommunityStructureAreaState extends State<CommunityStructureArea> {
|
|||||||
connection, widget.selectedSpace)
|
connection, widget.selectedSpace)
|
||||||
? 1.0
|
? 1.0
|
||||||
: 0.3, // Adjust opacity
|
: 0.3, // Adjust opacity
|
||||||
child: CustomPaint(
|
child: CustomPaint(painter: CurvedLinePainter([connection])),
|
||||||
painter: CurvedLinePainter([connection])),
|
|
||||||
),
|
),
|
||||||
for (var entry in spaces.asMap().entries)
|
for (var entry in spaces.asMap().entries)
|
||||||
if (entry.value.status != SpaceStatus.deleted &&
|
if (entry.value.status != SpaceStatus.deleted &&
|
||||||
@ -193,15 +190,12 @@ class _CommunityStructureAreaState extends State<CommunityStructureArea> {
|
|||||||
top: entry.value.position.dy,
|
top: entry.value.position.dy,
|
||||||
child: SpaceCardWidget(
|
child: SpaceCardWidget(
|
||||||
index: entry.key,
|
index: entry.key,
|
||||||
onButtonTap: (int index, Offset newPosition,
|
onButtonTap: (int index, Offset newPosition, String direction) {
|
||||||
String direction) {
|
_showCreateSpaceDialog(screenSize,
|
||||||
_showCreateSpaceDialog(
|
position: spaces[index].position + newPosition,
|
||||||
screenSize,
|
parentIndex: index,
|
||||||
position:
|
direction: direction,
|
||||||
spaces[index].position + newPosition,
|
projectTags: widget.projectTags);
|
||||||
parentIndex: index,
|
|
||||||
direction: direction,
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
position: entry.value.position,
|
position: entry.value.position,
|
||||||
isHovered: entry.value.isHovered,
|
isHovered: entry.value.isHovered,
|
||||||
@ -211,9 +205,8 @@ class _CommunityStructureAreaState extends State<CommunityStructureArea> {
|
|||||||
_updateNodePosition(entry.value, newPosition);
|
_updateNodePosition(entry.value, newPosition);
|
||||||
},
|
},
|
||||||
buildSpaceContainer: (int index) {
|
buildSpaceContainer: (int index) {
|
||||||
final bool isHighlighted =
|
final bool isHighlighted = SpaceHelper.isHighlightedSpace(
|
||||||
SpaceHelper.isHighlightedSpace(
|
spaces[index], widget.selectedSpace);
|
||||||
spaces[index], widget.selectedSpace);
|
|
||||||
|
|
||||||
return Opacity(
|
return Opacity(
|
||||||
opacity: isHighlighted ? 1.0 : 0.3,
|
opacity: isHighlighted ? 1.0 : 0.3,
|
||||||
@ -238,7 +231,8 @@ class _CommunityStructureAreaState extends State<CommunityStructureArea> {
|
|||||||
onTap: () {
|
onTap: () {
|
||||||
_showCreateSpaceDialog(screenSize,
|
_showCreateSpaceDialog(screenSize,
|
||||||
canvasHeight: canvasHeight,
|
canvasHeight: canvasHeight,
|
||||||
canvasWidth: canvasWidth);
|
canvasWidth: canvasWidth,
|
||||||
|
projectTags: widget.projectTags);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -292,26 +286,22 @@ class _CommunityStructureAreaState extends State<CommunityStructureArea> {
|
|||||||
int? parentIndex,
|
int? parentIndex,
|
||||||
String? direction,
|
String? direction,
|
||||||
double? canvasWidth,
|
double? canvasWidth,
|
||||||
double? canvasHeight}) {
|
double? canvasHeight,
|
||||||
|
required List<Tag> projectTags}) {
|
||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
return CreateSpaceDialog(
|
return CreateSpaceDialog(
|
||||||
products: widget.products,
|
products: widget.products,
|
||||||
spaceModels: widget.spaceModels,
|
spaceModels: widget.spaceModels,
|
||||||
allTags:
|
allTags: TagHelper.getAllTagValues(widget.communities, widget.spaceModels),
|
||||||
TagHelper.getAllTagValues(widget.communities, widget.spaceModels),
|
|
||||||
parentSpace: parentIndex != null ? spaces[parentIndex] : null,
|
parentSpace: parentIndex != null ? spaces[parentIndex] : null,
|
||||||
onCreateSpace: (String name,
|
projectTags: projectTags,
|
||||||
String icon,
|
onCreateSpace: (String name, String icon, List<SelectedProduct> selectedProducts,
|
||||||
List<SelectedProduct> selectedProducts,
|
SpaceTemplateModel? spaceModel, List<SubspaceModel>? subspaces, List<Tag>? tags) {
|
||||||
SpaceTemplateModel? spaceModel,
|
|
||||||
List<SubspaceModel>? subspaces,
|
|
||||||
List<Tag>? tags) {
|
|
||||||
setState(() {
|
setState(() {
|
||||||
// Set the first space in the center or use passed position
|
// Set the first space in the center or use passed position
|
||||||
Offset centerPosition =
|
Offset centerPosition = position ?? ConnectionHelper.getCenterPosition(screenSize);
|
||||||
position ?? ConnectionHelper.getCenterPosition(screenSize);
|
|
||||||
SpaceModel newSpace = SpaceModel(
|
SpaceModel newSpace = SpaceModel(
|
||||||
name: name,
|
name: name,
|
||||||
icon: icon,
|
icon: icon,
|
||||||
@ -356,21 +346,17 @@ class _CommunityStructureAreaState extends State<CommunityStructureArea> {
|
|||||||
spaceModels: widget.spaceModels,
|
spaceModels: widget.spaceModels,
|
||||||
name: widget.selectedSpace!.name,
|
name: widget.selectedSpace!.name,
|
||||||
icon: widget.selectedSpace!.icon,
|
icon: widget.selectedSpace!.icon,
|
||||||
parentSpace: SpaceHelper.findSpaceByInternalId(
|
projectTags: widget.projectTags,
|
||||||
widget.selectedSpace?.parent?.internalId, spaces),
|
parentSpace:
|
||||||
|
SpaceHelper.findSpaceByInternalId(widget.selectedSpace?.parent?.internalId, spaces),
|
||||||
editSpace: widget.selectedSpace,
|
editSpace: widget.selectedSpace,
|
||||||
currentSpaceModel: widget.selectedSpace?.spaceModel,
|
currentSpaceModel: widget.selectedSpace?.spaceModel,
|
||||||
tags: widget.selectedSpace?.tags,
|
tags: widget.selectedSpace?.tags,
|
||||||
subspaces: widget.selectedSpace?.subspaces,
|
subspaces: widget.selectedSpace?.subspaces,
|
||||||
isEdit: true,
|
isEdit: true,
|
||||||
allTags: TagHelper.getAllTagValues(
|
allTags: TagHelper.getAllTagValues(widget.communities, widget.spaceModels),
|
||||||
widget.communities, widget.spaceModels),
|
onCreateSpace: (String name, String icon, List<SelectedProduct> selectedProducts,
|
||||||
onCreateSpace: (String name,
|
SpaceTemplateModel? spaceModel, List<SubspaceModel>? subspaces, List<Tag>? tags) {
|
||||||
String icon,
|
|
||||||
List<SelectedProduct> selectedProducts,
|
|
||||||
SpaceTemplateModel? spaceModel,
|
|
||||||
List<SubspaceModel>? subspaces,
|
|
||||||
List<Tag>? tags) {
|
|
||||||
setState(() {
|
setState(() {
|
||||||
// Update the space's properties
|
// Update the space's properties
|
||||||
widget.selectedSpace!.name = name;
|
widget.selectedSpace!.name = name;
|
||||||
@ -380,8 +366,7 @@ class _CommunityStructureAreaState extends State<CommunityStructureArea> {
|
|||||||
widget.selectedSpace!.tags = tags;
|
widget.selectedSpace!.tags = tags;
|
||||||
|
|
||||||
if (widget.selectedSpace!.status != SpaceStatus.newSpace) {
|
if (widget.selectedSpace!.status != SpaceStatus.newSpace) {
|
||||||
widget.selectedSpace!.status =
|
widget.selectedSpace!.status = SpaceStatus.modified; // Mark as modified
|
||||||
SpaceStatus.modified; // Mark as modified
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var space in spaces) {
|
for (var space in spaces) {
|
||||||
@ -411,8 +396,7 @@ class _CommunityStructureAreaState extends State<CommunityStructureArea> {
|
|||||||
List<SpaceModel> result = [];
|
List<SpaceModel> result = [];
|
||||||
|
|
||||||
void flatten(SpaceModel space) {
|
void flatten(SpaceModel space) {
|
||||||
if (space.status == SpaceStatus.deleted ||
|
if (space.status == SpaceStatus.deleted || space.status == SpaceStatus.parentDeleted) {
|
||||||
space.status == SpaceStatus.parentDeleted) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
result.add(space);
|
result.add(space);
|
||||||
@ -527,16 +511,13 @@ class _CommunityStructureAreaState extends State<CommunityStructureArea> {
|
|||||||
|
|
||||||
void _selectSpace(BuildContext context, SpaceModel space) {
|
void _selectSpace(BuildContext context, SpaceModel space) {
|
||||||
context.read<SpaceManagementBloc>().add(
|
context.read<SpaceManagementBloc>().add(
|
||||||
SelectSpaceEvent(
|
SelectSpaceEvent(selectedCommunity: widget.selectedCommunity, selectedSpace: space),
|
||||||
selectedCommunity: widget.selectedCommunity,
|
|
||||||
selectedSpace: space),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _deselectSpace(BuildContext context) {
|
void _deselectSpace(BuildContext context) {
|
||||||
context.read<SpaceManagementBloc>().add(
|
context.read<SpaceManagementBloc>().add(
|
||||||
SelectSpaceEvent(
|
SelectSpaceEvent(selectedCommunity: widget.selectedCommunity, selectedSpace: null),
|
||||||
selectedCommunity: widget.selectedCommunity, selectedSpace: null),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -625,19 +606,16 @@ class _CommunityStructureAreaState extends State<CommunityStructureArea> {
|
|||||||
const double horizontalGap = 200.0;
|
const double horizontalGap = 200.0;
|
||||||
const double verticalGap = 100.0;
|
const double verticalGap = 100.0;
|
||||||
|
|
||||||
SpaceModel duplicateRecursive(SpaceModel original, Offset parentPosition,
|
SpaceModel duplicateRecursive(
|
||||||
SpaceModel? duplicatedParent) {
|
SpaceModel original, Offset parentPosition, SpaceModel? duplicatedParent) {
|
||||||
Offset newPosition =
|
Offset newPosition = Offset(parentPosition.dx + horizontalGap, original.position.dy);
|
||||||
Offset(parentPosition.dx + horizontalGap, original.position.dy);
|
|
||||||
|
|
||||||
while (spaces.any((s) =>
|
while (spaces.any((s) =>
|
||||||
(s.position - newPosition).distance < horizontalGap &&
|
(s.position - newPosition).distance < horizontalGap && s.status != SpaceStatus.deleted)) {
|
||||||
s.status != SpaceStatus.deleted)) {
|
|
||||||
newPosition += Offset(horizontalGap, 0);
|
newPosition += Offset(horizontalGap, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
final duplicatedName =
|
final duplicatedName = SpaceHelper.generateUniqueSpaceName(original.name, spaces);
|
||||||
SpaceHelper.generateUniqueSpaceName(original.name, spaces);
|
|
||||||
|
|
||||||
final List<SubspaceModel>? duplicatedSubspaces;
|
final List<SubspaceModel>? duplicatedSubspaces;
|
||||||
final List<Tag>? duplicatedTags;
|
final List<Tag>? duplicatedTags;
|
||||||
@ -681,8 +659,7 @@ class _CommunityStructureAreaState extends State<CommunityStructureArea> {
|
|||||||
|
|
||||||
if (original.parent != null && duplicatedParent == null) {
|
if (original.parent != null && duplicatedParent == null) {
|
||||||
final originalParent = original.parent!;
|
final originalParent = original.parent!;
|
||||||
final duplicatedParent =
|
final duplicatedParent = originalToDuplicate[originalParent] ?? originalParent;
|
||||||
originalToDuplicate[originalParent] ?? originalParent;
|
|
||||||
|
|
||||||
final parentConnection = Connection(
|
final parentConnection = Connection(
|
||||||
startSpace: duplicatedParent,
|
startSpace: duplicatedParent,
|
||||||
@ -698,8 +675,7 @@ class _CommunityStructureAreaState extends State<CommunityStructureArea> {
|
|||||||
|
|
||||||
final childrenWithDownDirection = original.children
|
final childrenWithDownDirection = original.children
|
||||||
.where((child) =>
|
.where((child) =>
|
||||||
child.incomingConnection?.direction == "down" &&
|
child.incomingConnection?.direction == "down" && child.status != SpaceStatus.deleted)
|
||||||
child.status != SpaceStatus.deleted)
|
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
Offset childStartPosition = childrenWithDownDirection.length == 1
|
Offset childStartPosition = childrenWithDownDirection.length == 1
|
||||||
@ -707,8 +683,7 @@ class _CommunityStructureAreaState extends State<CommunityStructureArea> {
|
|||||||
: newPosition + Offset(0, verticalGap);
|
: newPosition + Offset(0, verticalGap);
|
||||||
|
|
||||||
for (final child in original.children) {
|
for (final child in original.children) {
|
||||||
final isDownDirection =
|
final isDownDirection = child.incomingConnection?.direction == "down" ?? false;
|
||||||
child.incomingConnection?.direction == "down" ?? false;
|
|
||||||
|
|
||||||
if (isDownDirection && childrenWithDownDirection.length == 1) {
|
if (isDownDirection && childrenWithDownDirection.length == 1) {
|
||||||
childStartPosition = duplicated.position + Offset(0, verticalGap);
|
childStartPosition = duplicated.position + Offset(0, verticalGap);
|
||||||
@ -716,8 +691,7 @@ class _CommunityStructureAreaState extends State<CommunityStructureArea> {
|
|||||||
childStartPosition = duplicated.position + Offset(horizontalGap, 0);
|
childStartPosition = duplicated.position + Offset(horizontalGap, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
final duplicatedChild =
|
final duplicatedChild = duplicateRecursive(child, childStartPosition, duplicated);
|
||||||
duplicateRecursive(child, childStartPosition, duplicated);
|
|
||||||
duplicated.children.add(duplicatedChild);
|
duplicated.children.add(duplicatedChild);
|
||||||
childStartPosition += Offset(0, verticalGap);
|
childStartPosition += Offset(0, verticalGap);
|
||||||
}
|
}
|
||||||
@ -728,8 +702,7 @@ class _CommunityStructureAreaState extends State<CommunityStructureArea> {
|
|||||||
if (space.parent == null) {
|
if (space.parent == null) {
|
||||||
duplicateRecursive(space, space.position, null);
|
duplicateRecursive(space, space.position, null);
|
||||||
} else {
|
} else {
|
||||||
final duplicatedParent =
|
final duplicatedParent = originalToDuplicate[space.parent!] ?? space.parent!;
|
||||||
originalToDuplicate[space.parent!] ?? space.parent!;
|
|
||||||
duplicateRecursive(space, space.position, duplicatedParent);
|
duplicateRecursive(space, space.position, duplicatedParent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,7 @@ class CreateSpaceDialog extends StatefulWidget {
|
|||||||
final List<Tag>? tags;
|
final List<Tag>? tags;
|
||||||
final List<String>? allTags;
|
final List<String>? allTags;
|
||||||
final SpaceTemplateModel? currentSpaceModel;
|
final SpaceTemplateModel? currentSpaceModel;
|
||||||
|
final List<Tag> projectTags;
|
||||||
|
|
||||||
const CreateSpaceDialog(
|
const CreateSpaceDialog(
|
||||||
{super.key,
|
{super.key,
|
||||||
@ -57,7 +58,8 @@ class CreateSpaceDialog extends StatefulWidget {
|
|||||||
this.spaceModels,
|
this.spaceModels,
|
||||||
this.subspaces,
|
this.subspaces,
|
||||||
this.tags,
|
this.tags,
|
||||||
this.currentSpaceModel});
|
this.currentSpaceModel,
|
||||||
|
required this.projectTags});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
CreateSpaceDialogState createState() => CreateSpaceDialogState();
|
CreateSpaceDialogState createState() => CreateSpaceDialogState();
|
||||||
@ -80,10 +82,8 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
|
|||||||
super.initState();
|
super.initState();
|
||||||
selectedIcon = widget.icon ?? Assets.location;
|
selectedIcon = widget.icon ?? Assets.location;
|
||||||
nameController = TextEditingController(text: widget.name ?? '');
|
nameController = TextEditingController(text: widget.name ?? '');
|
||||||
selectedProducts =
|
selectedProducts = widget.selectedProducts.isNotEmpty ? widget.selectedProducts : [];
|
||||||
widget.selectedProducts.isNotEmpty ? widget.selectedProducts : [];
|
isOkButtonEnabled = enteredName.isNotEmpty || nameController.text.isNotEmpty;
|
||||||
isOkButtonEnabled =
|
|
||||||
enteredName.isNotEmpty || nameController.text.isNotEmpty;
|
|
||||||
if (widget.currentSpaceModel != null) {
|
if (widget.currentSpaceModel != null) {
|
||||||
subspaces = [];
|
subspaces = [];
|
||||||
tags = [];
|
tags = [];
|
||||||
@ -96,15 +96,13 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
bool isSpaceModelDisabled = (tags != null && tags!.isNotEmpty ||
|
bool isSpaceModelDisabled =
|
||||||
subspaces != null && subspaces!.isNotEmpty);
|
(tags != null && tags!.isNotEmpty || subspaces != null && subspaces!.isNotEmpty);
|
||||||
bool isTagsAndSubspaceModelDisabled = (selectedSpaceModel != null);
|
bool isTagsAndSubspaceModelDisabled = (selectedSpaceModel != null);
|
||||||
|
|
||||||
final screenWidth = MediaQuery.of(context).size.width;
|
final screenWidth = MediaQuery.of(context).size.width;
|
||||||
return AlertDialog(
|
return AlertDialog(
|
||||||
title: widget.isEdit
|
title: widget.isEdit ? const Text('Edit Space') : const Text('Create New Space'),
|
||||||
? const Text('Edit Space')
|
|
||||||
: const Text('Create New Space'),
|
|
||||||
backgroundColor: ColorsManager.whiteColors,
|
backgroundColor: ColorsManager.whiteColors,
|
||||||
content: SizedBox(
|
content: SizedBox(
|
||||||
width: screenWidth * 0.5,
|
width: screenWidth * 0.5,
|
||||||
@ -178,7 +176,8 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
|
|||||||
isNameFieldInvalid = value.isEmpty;
|
isNameFieldInvalid = value.isEmpty;
|
||||||
|
|
||||||
if (!isNameFieldInvalid) {
|
if (!isNameFieldInvalid) {
|
||||||
if (SpaceHelper.isNameConflict(value, widget.parentSpace, widget.editSpace)) {
|
if (SpaceHelper.isNameConflict(
|
||||||
|
value, widget.parentSpace, widget.editSpace)) {
|
||||||
isNameFieldExist = true;
|
isNameFieldExist = true;
|
||||||
isOkButtonEnabled = false;
|
isOkButtonEnabled = false;
|
||||||
} else {
|
} else {
|
||||||
@ -245,9 +244,7 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
|
|||||||
padding: EdgeInsets.zero,
|
padding: EdgeInsets.zero,
|
||||||
),
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
isSpaceModelDisabled
|
isSpaceModelDisabled ? null : _showLinkSpaceModelDialog(context);
|
||||||
? null
|
|
||||||
: _showLinkSpaceModelDialog(context);
|
|
||||||
},
|
},
|
||||||
child: ButtonContentWidget(
|
child: ButtonContentWidget(
|
||||||
svgAssets: Assets.link,
|
svgAssets: Assets.link,
|
||||||
@ -257,8 +254,7 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
|
|||||||
)
|
)
|
||||||
: Container(
|
: Container(
|
||||||
width: screenWidth * 0.25,
|
width: screenWidth * 0.25,
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: const EdgeInsets.symmetric(vertical: 10.0, horizontal: 16.0),
|
||||||
vertical: 10.0, horizontal: 16.0),
|
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: ColorsManager.boxColor,
|
color: ColorsManager.boxColor,
|
||||||
borderRadius: BorderRadius.circular(10),
|
borderRadius: BorderRadius.circular(10),
|
||||||
@ -273,8 +269,7 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
|
|||||||
style: Theme.of(context)
|
style: Theme.of(context)
|
||||||
.textTheme
|
.textTheme
|
||||||
.bodyMedium!
|
.bodyMedium!
|
||||||
.copyWith(
|
.copyWith(color: ColorsManager.spaceColor),
|
||||||
color: ColorsManager.spaceColor),
|
|
||||||
),
|
),
|
||||||
backgroundColor: ColorsManager.whiteColors,
|
backgroundColor: ColorsManager.whiteColors,
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
@ -343,8 +338,8 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
|
|||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
isTagsAndSubspaceModelDisabled
|
isTagsAndSubspaceModelDisabled
|
||||||
? null
|
? null
|
||||||
: _showSubSpaceDialog(context, enteredName,
|
: _showSubSpaceDialog(
|
||||||
[], false, widget.products, subspaces);
|
context, enteredName, [], false, widget.products, subspaces);
|
||||||
},
|
},
|
||||||
child: ButtonContentWidget(
|
child: ButtonContentWidget(
|
||||||
icon: Icons.add,
|
icon: Icons.add,
|
||||||
@ -371,22 +366,16 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
|
|||||||
if (subspaces != null)
|
if (subspaces != null)
|
||||||
...subspaces!.map((subspace) {
|
...subspaces!.map((subspace) {
|
||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment:
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
CrossAxisAlignment.start,
|
|
||||||
children: [
|
children: [
|
||||||
SubspaceNameDisplayWidget(
|
SubspaceNameDisplayWidget(
|
||||||
text: subspace.subspaceName,
|
text: subspace.subspaceName,
|
||||||
validateName: (updatedName) {
|
validateName: (updatedName) {
|
||||||
bool nameExists =
|
bool nameExists = subspaces!.any((s) {
|
||||||
subspaces!.any((s) {
|
bool isSameId = s.internalId == subspace.internalId;
|
||||||
bool isSameId = s.internalId ==
|
bool isSameName =
|
||||||
subspace.internalId;
|
s.subspaceName.trim().toLowerCase() ==
|
||||||
bool isSameName = s.subspaceName
|
updatedName.trim().toLowerCase();
|
||||||
.trim()
|
|
||||||
.toLowerCase() ==
|
|
||||||
updatedName
|
|
||||||
.trim()
|
|
||||||
.toLowerCase();
|
|
||||||
|
|
||||||
return !isSameId && isSameName;
|
return !isSameId && isSameName;
|
||||||
});
|
});
|
||||||
@ -395,8 +384,7 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
|
|||||||
},
|
},
|
||||||
onNameChanged: (updatedName) {
|
onNameChanged: (updatedName) {
|
||||||
setState(() {
|
setState(() {
|
||||||
subspace.subspaceName =
|
subspace.subspaceName = updatedName;
|
||||||
updatedName;
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -405,8 +393,8 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
|
|||||||
}),
|
}),
|
||||||
EditChip(
|
EditChip(
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
_showSubSpaceDialog(context, enteredName,
|
_showSubSpaceDialog(context, enteredName, [], true,
|
||||||
[], true, widget.products, subspaces);
|
widget.products, subspaces);
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
@ -415,9 +403,7 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
|
|||||||
),
|
),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
(tags?.isNotEmpty == true ||
|
(tags?.isNotEmpty == true ||
|
||||||
subspaces?.any((subspace) =>
|
subspaces?.any((subspace) => subspace.tags?.isNotEmpty == true) == true)
|
||||||
subspace.tags?.isNotEmpty == true) ==
|
|
||||||
true)
|
|
||||||
? SizedBox(
|
? SizedBox(
|
||||||
width: screenWidth * 0.25,
|
width: screenWidth * 0.25,
|
||||||
child: Container(
|
child: Container(
|
||||||
@ -437,16 +423,14 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
|
|||||||
// Combine tags from spaceModel and subspaces
|
// Combine tags from spaceModel and subspaces
|
||||||
...TagHelper.groupTags([
|
...TagHelper.groupTags([
|
||||||
...?tags,
|
...?tags,
|
||||||
...?subspaces?.expand(
|
...?subspaces?.expand((subspace) => subspace.tags ?? [])
|
||||||
(subspace) => subspace.tags ?? [])
|
|
||||||
]).entries.map(
|
]).entries.map(
|
||||||
(entry) => Chip(
|
(entry) => Chip(
|
||||||
avatar: SizedBox(
|
avatar: SizedBox(
|
||||||
width: 24,
|
width: 24,
|
||||||
height: 24,
|
height: 24,
|
||||||
child: SvgPicture.asset(
|
child: SvgPicture.asset(
|
||||||
entry.key.icon ??
|
entry.key.icon ?? 'assets/icons/gateway.svg',
|
||||||
'assets/icons/gateway.svg',
|
|
||||||
fit: BoxFit.contain,
|
fit: BoxFit.contain,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -455,15 +439,11 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
|
|||||||
style: Theme.of(context)
|
style: Theme.of(context)
|
||||||
.textTheme
|
.textTheme
|
||||||
.bodySmall
|
.bodySmall
|
||||||
?.copyWith(
|
?.copyWith(color: ColorsManager.spaceColor),
|
||||||
color: ColorsManager
|
|
||||||
.spaceColor),
|
|
||||||
),
|
),
|
||||||
backgroundColor:
|
backgroundColor: ColorsManager.whiteColors,
|
||||||
ColorsManager.whiteColors,
|
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius:
|
borderRadius: BorderRadius.circular(16),
|
||||||
BorderRadius.circular(16),
|
|
||||||
side: const BorderSide(
|
side: const BorderSide(
|
||||||
color: ColorsManager.spaceColor,
|
color: ColorsManager.spaceColor,
|
||||||
),
|
),
|
||||||
@ -472,23 +452,21 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
|
|||||||
),
|
),
|
||||||
|
|
||||||
EditChip(onTap: () async {
|
EditChip(onTap: () async {
|
||||||
final result = await showDialog(
|
await showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => AssignTagDialog(
|
builder: (context) => AssignTagDialog(
|
||||||
products: widget.products,
|
products: widget.products,
|
||||||
subspaces: subspaces,
|
subspaces: subspaces,
|
||||||
allTags: widget.allTags,
|
allTags: widget.allTags,
|
||||||
addedProducts: TagHelper
|
addedProducts:
|
||||||
.createInitialSelectedProductsForTags(
|
TagHelper.createInitialSelectedProductsForTags(
|
||||||
tags ?? [], subspaces),
|
tags ?? [], subspaces),
|
||||||
title: 'Edit Device',
|
title: 'Edit Device',
|
||||||
initialTags:
|
initialTags: TagHelper.generateInitialForTags(
|
||||||
TagHelper.generateInitialForTags(
|
spaceTags: tags, subspaces: subspaces),
|
||||||
spaceTags: tags,
|
|
||||||
subspaces: subspaces),
|
|
||||||
spaceName: widget.name ?? '',
|
spaceName: widget.name ?? '',
|
||||||
onSave:
|
projectTags: widget.projectTags,
|
||||||
(updatedTags, updatedSubspaces) {
|
onSave: (updatedTags, updatedSubspaces) {
|
||||||
setState(() {
|
setState(() {
|
||||||
tags = updatedTags;
|
tags = updatedTags;
|
||||||
subspaces = updatedSubspaces;
|
subspaces = updatedSubspaces;
|
||||||
@ -547,25 +525,17 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
|
|||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
String newName = enteredName.isNotEmpty
|
String newName = enteredName.isNotEmpty ? enteredName : (widget.name ?? '');
|
||||||
? enteredName
|
|
||||||
: (widget.name ?? '');
|
|
||||||
if (newName.isNotEmpty) {
|
if (newName.isNotEmpty) {
|
||||||
widget.onCreateSpace(
|
widget.onCreateSpace(newName, selectedIcon, selectedProducts,
|
||||||
newName,
|
selectedSpaceModel, subspaces, tags);
|
||||||
selectedIcon,
|
|
||||||
selectedProducts,
|
|
||||||
selectedSpaceModel,
|
|
||||||
subspaces,
|
|
||||||
tags);
|
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
borderRadius: 10,
|
borderRadius: 10,
|
||||||
backgroundColor: isOkButtonEnabled
|
backgroundColor:
|
||||||
? ColorsManager.secondaryColor
|
isOkButtonEnabled ? ColorsManager.secondaryColor : ColorsManager.grayColor,
|
||||||
: ColorsManager.grayColor,
|
|
||||||
foregroundColor: ColorsManager.whiteColors,
|
foregroundColor: ColorsManager.whiteColors,
|
||||||
child: const Text('OK'),
|
child: const Text('OK'),
|
||||||
),
|
),
|
||||||
@ -592,7 +562,6 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void _showLinkSpaceModelDialog(BuildContext context) {
|
void _showLinkSpaceModelDialog(BuildContext context) {
|
||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
@ -613,13 +582,8 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _showSubSpaceDialog(
|
void _showSubSpaceDialog(BuildContext context, String name, final List<Tag>? spaceTags,
|
||||||
BuildContext context,
|
bool isEdit, List<ProductModel>? products, final List<SubspaceModel>? existingSubSpaces) {
|
||||||
String name,
|
|
||||||
final List<Tag>? spaceTags,
|
|
||||||
bool isEdit,
|
|
||||||
List<ProductModel>? products,
|
|
||||||
final List<SubspaceModel>? existingSubSpaces) {
|
|
||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
@ -634,12 +598,10 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
|
|||||||
final List<Tag> tagsToAppendToSpace = [];
|
final List<Tag> tagsToAppendToSpace = [];
|
||||||
|
|
||||||
if (slectedSubspaces != null) {
|
if (slectedSubspaces != null) {
|
||||||
final updatedIds =
|
final updatedIds = slectedSubspaces.map((s) => s.internalId).toSet();
|
||||||
slectedSubspaces.map((s) => s.internalId).toSet();
|
|
||||||
if (existingSubSpaces != null) {
|
if (existingSubSpaces != null) {
|
||||||
final deletedSubspaces = existingSubSpaces
|
final deletedSubspaces =
|
||||||
.where((s) => !updatedIds.contains(s.internalId))
|
existingSubSpaces.where((s) => !updatedIds.contains(s.internalId)).toList();
|
||||||
.toList();
|
|
||||||
for (var s in deletedSubspaces) {
|
for (var s in deletedSubspaces) {
|
||||||
if (s.tags != null) {
|
if (s.tags != null) {
|
||||||
tagsToAppendToSpace.addAll(s.tags!);
|
tagsToAppendToSpace.addAll(s.tags!);
|
||||||
@ -659,20 +621,20 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _showTagCreateDialog(BuildContext context, String name, bool isEdit,
|
void _showTagCreateDialog(
|
||||||
List<ProductModel>? products) {
|
BuildContext context, String name, bool isEdit, List<ProductModel>? products) {
|
||||||
isEdit
|
isEdit
|
||||||
? showDialog(
|
? showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
return AssignTagDialog(
|
return AssignTagDialog(
|
||||||
title: 'Edit Device',
|
title: 'Edit Device',
|
||||||
addedProducts: TagHelper.createInitialSelectedProductsForTags(
|
addedProducts: TagHelper.createInitialSelectedProductsForTags(tags, subspaces),
|
||||||
tags, subspaces),
|
|
||||||
spaceName: name,
|
spaceName: name,
|
||||||
products: products,
|
products: products,
|
||||||
subspaces: subspaces,
|
subspaces: subspaces,
|
||||||
allTags: widget.allTags,
|
allTags: widget.allTags,
|
||||||
|
projectTags: widget.projectTags,
|
||||||
onSave: (selectedSpaceTags, selectedSubspaces) {
|
onSave: (selectedSpaceTags, selectedSubspaces) {
|
||||||
setState(() {
|
setState(() {
|
||||||
tags = selectedSpaceTags;
|
tags = selectedSpaceTags;
|
||||||
@ -682,8 +644,7 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
|
|||||||
if (subspaces != null) {
|
if (subspaces != null) {
|
||||||
for (final subspace in subspaces!) {
|
for (final subspace in subspaces!) {
|
||||||
for (final selectedSubspace in selectedSubspaces) {
|
for (final selectedSubspace in selectedSubspaces) {
|
||||||
if (subspace.subspaceName ==
|
if (subspace.subspaceName == selectedSubspace.subspaceName) {
|
||||||
selectedSubspace.subspaceName) {
|
|
||||||
subspace.tags = selectedSubspace.tags;
|
subspace.tags = selectedSubspace.tags;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -705,9 +666,9 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
|
|||||||
spaceTags: tags,
|
spaceTags: tags,
|
||||||
isCreate: true,
|
isCreate: true,
|
||||||
allTags: widget.allTags,
|
allTags: widget.allTags,
|
||||||
|
projectTags: widget.projectTags,
|
||||||
initialSelectedProducts:
|
initialSelectedProducts:
|
||||||
TagHelper.createInitialSelectedProductsForTags(
|
TagHelper.createInitialSelectedProductsForTags(tags, subspaces),
|
||||||
tags, subspaces),
|
|
||||||
onSave: (selectedSpaceTags, selectedSubspaces) {
|
onSave: (selectedSpaceTags, selectedSubspaces) {
|
||||||
setState(() {
|
setState(() {
|
||||||
tags = selectedSpaceTags;
|
tags = selectedSpaceTags;
|
||||||
@ -717,8 +678,7 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
|
|||||||
if (subspaces != null) {
|
if (subspaces != null) {
|
||||||
for (final subspace in subspaces!) {
|
for (final subspace in subspaces!) {
|
||||||
for (final selectedSubspace in selectedSubspaces) {
|
for (final selectedSubspace in selectedSubspaces) {
|
||||||
if (subspace.subspaceName ==
|
if (subspace.subspaceName == selectedSubspace.subspaceName) {
|
||||||
selectedSubspace.subspaceName) {
|
|
||||||
subspace.tags = selectedSubspace.tags;
|
subspace.tags = selectedSubspace.tags;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -114,6 +114,7 @@ class _LoadedSpaceViewState extends State<LoadedSpaceView> {
|
|||||||
products: widget.products,
|
products: widget.products,
|
||||||
communities: widget.communities,
|
communities: widget.communities,
|
||||||
spaceModels: _spaceModels,
|
spaceModels: _spaceModels,
|
||||||
|
projectTags: widget.projectTags,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -4,17 +4,16 @@ import 'package:syncrow_web/pages/spaces_management/assign_tag/bloc/assign_tag_e
|
|||||||
import 'package:syncrow_web/pages/spaces_management/assign_tag/bloc/assign_tag_state.dart';
|
import 'package:syncrow_web/pages/spaces_management/assign_tag/bloc/assign_tag_state.dart';
|
||||||
|
|
||||||
class AssignTagBloc extends Bloc<AssignTagEvent, AssignTagState> {
|
class AssignTagBloc extends Bloc<AssignTagEvent, AssignTagState> {
|
||||||
final List<String> allTags;
|
final List<Tag> projectTags;
|
||||||
|
|
||||||
AssignTagBloc(this.allTags) : super(AssignTagInitial()) {
|
AssignTagBloc(this.projectTags) : super(AssignTagInitial()) {
|
||||||
on<InitializeTags>((event, emit) {
|
on<InitializeTags>((event, emit) {
|
||||||
final initialTags = event.initialTags ?? [];
|
final initialTags = event.initialTags ?? [];
|
||||||
|
|
||||||
final existingTagCounts = <String, int>{};
|
final existingTagCounts = <String, int>{};
|
||||||
for (var tag in initialTags) {
|
for (var tag in initialTags) {
|
||||||
if (tag.product != null) {
|
if (tag.product != null) {
|
||||||
existingTagCounts[tag.product!.uuid] =
|
existingTagCounts[tag.product!.uuid] = (existingTagCounts[tag.product!.uuid] ?? 0) + 1;
|
||||||
(existingTagCounts[tag.product!.uuid] ?? 0) + 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23,17 +22,14 @@ class AssignTagBloc extends Bloc<AssignTagEvent, AssignTagState> {
|
|||||||
for (var selectedProduct in event.addedProducts) {
|
for (var selectedProduct in event.addedProducts) {
|
||||||
final existingCount = existingTagCounts[selectedProduct.productId] ?? 0;
|
final existingCount = existingTagCounts[selectedProduct.productId] ?? 0;
|
||||||
|
|
||||||
if (selectedProduct.count == 0 ||
|
if (selectedProduct.count == 0 || selectedProduct.count <= existingCount) {
|
||||||
selectedProduct.count <= existingCount) {
|
tags.addAll(initialTags.where((tag) => tag.product?.uuid == selectedProduct.productId));
|
||||||
tags.addAll(initialTags
|
|
||||||
.where((tag) => tag.product?.uuid == selectedProduct.productId));
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
final missingCount = selectedProduct.count - existingCount;
|
final missingCount = selectedProduct.count - existingCount;
|
||||||
|
|
||||||
tags.addAll(initialTags
|
tags.addAll(initialTags.where((tag) => tag.product?.uuid == selectedProduct.productId));
|
||||||
.where((tag) => tag.product?.uuid == selectedProduct.productId));
|
|
||||||
|
|
||||||
if (missingCount > 0) {
|
if (missingCount > 0) {
|
||||||
tags.addAll(List.generate(
|
tags.addAll(List.generate(
|
||||||
@ -47,11 +43,11 @@ class AssignTagBloc extends Bloc<AssignTagEvent, AssignTagState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final updatedTags = _calculateAvailableTags(allTags, tags);
|
final updatedTags = _calculateAvailableTags(projectTags, tags);
|
||||||
|
|
||||||
emit(AssignTagLoaded(
|
emit(AssignTagLoaded(
|
||||||
tags: tags,
|
tags: tags,
|
||||||
updatedTags: updatedTags,
|
updatedTags: updatedTags,
|
||||||
isSaveEnabled: _validateTags(tags),
|
isSaveEnabled: _validateTags(tags),
|
||||||
errorMessage: '',
|
errorMessage: '',
|
||||||
));
|
));
|
||||||
@ -62,9 +58,16 @@ class AssignTagBloc extends Bloc<AssignTagEvent, AssignTagState> {
|
|||||||
|
|
||||||
if (currentState is AssignTagLoaded && currentState.tags.isNotEmpty) {
|
if (currentState is AssignTagLoaded && currentState.tags.isNotEmpty) {
|
||||||
final tags = List<Tag>.from(currentState.tags);
|
final tags = List<Tag>.from(currentState.tags);
|
||||||
tags[event.index] = tags[event.index].copyWith(tag: event.tag);
|
if (event.index < 0 || event.index >= tags.length) return;
|
||||||
|
|
||||||
final updatedTags = _calculateAvailableTags(allTags, tags);
|
tags[event.index] = tags[event.index].copyWith(
|
||||||
|
tag: event.tag.tag,
|
||||||
|
uuid: event.tag.uuid,
|
||||||
|
product: event.tag.product,
|
||||||
|
internalId: event.tag.internalId,
|
||||||
|
location: event.tag.location,
|
||||||
|
);
|
||||||
|
final updatedTags = _calculateAvailableTags(projectTags, tags);
|
||||||
|
|
||||||
emit(AssignTagLoaded(
|
emit(AssignTagLoaded(
|
||||||
tags: tags,
|
tags: tags,
|
||||||
@ -82,10 +85,9 @@ class AssignTagBloc extends Bloc<AssignTagEvent, AssignTagState> {
|
|||||||
final tags = List<Tag>.from(currentState.tags);
|
final tags = List<Tag>.from(currentState.tags);
|
||||||
|
|
||||||
// Update the location
|
// Update the location
|
||||||
tags[event.index] =
|
tags[event.index] = tags[event.index].copyWith(location: event.location);
|
||||||
tags[event.index].copyWith(location: event.location);
|
|
||||||
|
|
||||||
final updatedTags = _calculateAvailableTags(allTags, tags);
|
final updatedTags = _calculateAvailableTags(projectTags, tags);
|
||||||
|
|
||||||
emit(AssignTagLoaded(
|
emit(AssignTagLoaded(
|
||||||
tags: tags,
|
tags: tags,
|
||||||
@ -104,7 +106,7 @@ class AssignTagBloc extends Bloc<AssignTagEvent, AssignTagState> {
|
|||||||
|
|
||||||
emit(AssignTagLoaded(
|
emit(AssignTagLoaded(
|
||||||
tags: tags,
|
tags: tags,
|
||||||
updatedTags: _calculateAvailableTags(allTags, tags),
|
updatedTags: _calculateAvailableTags(projectTags, tags),
|
||||||
isSaveEnabled: _validateTags(tags),
|
isSaveEnabled: _validateTags(tags),
|
||||||
errorMessage: _getValidationError(tags),
|
errorMessage: _getValidationError(tags),
|
||||||
));
|
));
|
||||||
@ -115,11 +117,10 @@ class AssignTagBloc extends Bloc<AssignTagEvent, AssignTagState> {
|
|||||||
final currentState = state;
|
final currentState = state;
|
||||||
|
|
||||||
if (currentState is AssignTagLoaded && currentState.tags.isNotEmpty) {
|
if (currentState is AssignTagLoaded && currentState.tags.isNotEmpty) {
|
||||||
final tags = List<Tag>.from(currentState.tags)
|
final tags = List<Tag>.from(currentState.tags)..remove(event.tagToDelete);
|
||||||
..remove(event.tagToDelete);
|
|
||||||
|
|
||||||
// Recalculate available tags
|
// Recalculate available tags
|
||||||
final updatedTags = _calculateAvailableTags(allTags, tags);
|
final updatedTags = _calculateAvailableTags(projectTags, tags);
|
||||||
|
|
||||||
emit(AssignTagLoaded(
|
emit(AssignTagLoaded(
|
||||||
tags: tags,
|
tags: tags,
|
||||||
@ -140,10 +141,8 @@ class AssignTagBloc extends Bloc<AssignTagEvent, AssignTagState> {
|
|||||||
|
|
||||||
// Get validation error for duplicate tags
|
// Get validation error for duplicate tags
|
||||||
String? _getValidationError(List<Tag> tags) {
|
String? _getValidationError(List<Tag> tags) {
|
||||||
final nonEmptyTags = tags
|
final nonEmptyTags =
|
||||||
.map((tag) => tag.tag?.trim() ?? '')
|
tags.map((tag) => tag.tag?.trim() ?? '').where((tag) => tag.isNotEmpty).toList();
|
||||||
.where((tag) => tag.isNotEmpty)
|
|
||||||
.toList();
|
|
||||||
|
|
||||||
final duplicateTags = nonEmptyTags
|
final duplicateTags = nonEmptyTags
|
||||||
.fold<Map<String, int>>({}, (map, tag) {
|
.fold<Map<String, int>>({}, (map, tag) {
|
||||||
@ -162,14 +161,16 @@ class AssignTagBloc extends Bloc<AssignTagEvent, AssignTagState> {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> _calculateAvailableTags(List<String> allTags, List<Tag> tags) {
|
List<Tag> _calculateAvailableTags(List<Tag> allTags, List<Tag> selectedTags) {
|
||||||
final selectedTags = tags
|
final selectedTagSet = selectedTags
|
||||||
.where((tag) => (tag.tag?.trim().isNotEmpty ?? false))
|
.where((tag) => (tag.tag?.trim().isNotEmpty ?? false))
|
||||||
.map((tag) => tag.tag!.trim())
|
.map((tag) => tag.tag!.trim())
|
||||||
.toSet();
|
.toSet();
|
||||||
|
|
||||||
final availableTags =
|
final availableTags = allTags
|
||||||
allTags.where((tag) => !selectedTags.contains(tag.trim())).toList();
|
.where((tag) => tag.tag != null && !selectedTagSet.contains(tag.tag!.trim()))
|
||||||
|
.toList();
|
||||||
|
|
||||||
return availableTags;
|
return availableTags;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ class InitializeTags extends AssignTagEvent {
|
|||||||
|
|
||||||
class UpdateTagEvent extends AssignTagEvent {
|
class UpdateTagEvent extends AssignTagEvent {
|
||||||
final int index;
|
final int index;
|
||||||
final String tag;
|
final Tag tag;
|
||||||
|
|
||||||
const UpdateTagEvent({required this.index, required this.tag});
|
const UpdateTagEvent({required this.index, required this.tag});
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ abstract class AssignTagState extends Equatable {
|
|||||||
const AssignTagState();
|
const AssignTagState();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [];
|
List<Object?> get props => [];
|
||||||
}
|
}
|
||||||
|
|
||||||
class AssignTagInitial extends AssignTagState {}
|
class AssignTagInitial extends AssignTagState {}
|
||||||
@ -14,7 +14,7 @@ class AssignTagLoading extends AssignTagState {}
|
|||||||
|
|
||||||
class AssignTagLoaded extends AssignTagState {
|
class AssignTagLoaded extends AssignTagState {
|
||||||
final List<Tag> tags;
|
final List<Tag> tags;
|
||||||
final List<String> updatedTags;
|
final List<Tag> updatedTags;
|
||||||
|
|
||||||
final bool isSaveEnabled;
|
final bool isSaveEnabled;
|
||||||
final String? errorMessage;
|
final String? errorMessage;
|
||||||
@ -27,8 +27,7 @@ class AssignTagLoaded extends AssignTagState {
|
|||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props =>
|
List<Object?> get props => [tags, updatedTags, isSaveEnabled, errorMessage ?? ''];
|
||||||
[tags, updatedTags, isSaveEnabled, errorMessage ?? ''];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class AssignTagError extends AssignTagState {
|
class AssignTagError extends AssignTagState {
|
||||||
@ -37,5 +36,5 @@ class AssignTagError extends AssignTagState {
|
|||||||
const AssignTagError(this.errorMessage);
|
const AssignTagError(this.errorMessage);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [errorMessage];
|
List<Object?> get props => [errorMessage];
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:syncrow_web/common/dialog_dropdown.dart';
|
import 'package:syncrow_web/common/dialog_dropdown.dart';
|
||||||
import 'package:syncrow_web/common/dialog_textfield_dropdown.dart';
|
import 'package:syncrow_web/common/tag_dialog_textfield_dropdown.dart';
|
||||||
import 'package:syncrow_web/pages/common/buttons/cancel_button.dart';
|
import 'package:syncrow_web/pages/common/buttons/cancel_button.dart';
|
||||||
import 'package:syncrow_web/pages/common/buttons/default_button.dart';
|
import 'package:syncrow_web/pages/common/buttons/default_button.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/add_device_type/views/add_device_type_widget.dart';
|
import 'package:syncrow_web/pages/spaces_management/add_device_type/views/add_device_type_widget.dart';
|
||||||
@ -26,6 +26,7 @@ class AssignTagDialog extends StatelessWidget {
|
|||||||
final String spaceName;
|
final String spaceName;
|
||||||
final String title;
|
final String title;
|
||||||
final Function(List<Tag>, List<SubspaceModel>?)? onSave;
|
final Function(List<Tag>, List<SubspaceModel>?)? onSave;
|
||||||
|
final List<Tag> projectTags;
|
||||||
|
|
||||||
const AssignTagDialog(
|
const AssignTagDialog(
|
||||||
{Key? key,
|
{Key? key,
|
||||||
@ -37,18 +38,17 @@ class AssignTagDialog extends StatelessWidget {
|
|||||||
this.allTags,
|
this.allTags,
|
||||||
required this.spaceName,
|
required this.spaceName,
|
||||||
required this.title,
|
required this.title,
|
||||||
this.onSave})
|
this.onSave,
|
||||||
|
required this.projectTags})
|
||||||
: super(key: key);
|
: super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final List<String> locations = (subspaces ?? [])
|
final List<String> locations =
|
||||||
.map((subspace) => subspace.subspaceName)
|
(subspaces ?? []).map((subspace) => subspace.subspaceName).toList()..add('Main Space');
|
||||||
.toList()
|
|
||||||
..add('Main Space');
|
|
||||||
|
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (_) => AssignTagBloc(allTags ?? [])
|
create: (_) => AssignTagBloc(projectTags)
|
||||||
..add(InitializeTags(
|
..add(InitializeTags(
|
||||||
initialTags: initialTags,
|
initialTags: initialTags,
|
||||||
addedProducts: addedProducts,
|
addedProducts: addedProducts,
|
||||||
@ -70,8 +70,7 @@ class AssignTagDialog extends StatelessWidget {
|
|||||||
ClipRRect(
|
ClipRRect(
|
||||||
borderRadius: BorderRadius.circular(20),
|
borderRadius: BorderRadius.circular(20),
|
||||||
child: DataTable(
|
child: DataTable(
|
||||||
headingRowColor: WidgetStateProperty.all(
|
headingRowColor: WidgetStateProperty.all(ColorsManager.dataHeaderGrey),
|
||||||
ColorsManager.dataHeaderGrey),
|
|
||||||
key: ValueKey(state.tags.length),
|
key: ValueKey(state.tags.length),
|
||||||
border: TableBorder.all(
|
border: TableBorder.all(
|
||||||
color: ColorsManager.dataHeaderGrey,
|
color: ColorsManager.dataHeaderGrey,
|
||||||
@ -80,22 +79,15 @@ class AssignTagDialog extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
columns: [
|
columns: [
|
||||||
DataColumn(
|
DataColumn(
|
||||||
label: Text('#',
|
label: Text('#', style: Theme.of(context).textTheme.bodyMedium)),
|
||||||
style:
|
|
||||||
Theme.of(context).textTheme.bodyMedium)),
|
|
||||||
DataColumn(
|
DataColumn(
|
||||||
label: Text('Device',
|
label: Text('Device', style: Theme.of(context).textTheme.bodyMedium)),
|
||||||
style:
|
|
||||||
Theme.of(context).textTheme.bodyMedium)),
|
|
||||||
DataColumn(
|
DataColumn(
|
||||||
numeric: false,
|
numeric: false,
|
||||||
label: Text('Tag',
|
label: Text('Tag', style: Theme.of(context).textTheme.bodyMedium)),
|
||||||
style:
|
|
||||||
Theme.of(context).textTheme.bodyMedium)),
|
|
||||||
DataColumn(
|
DataColumn(
|
||||||
label: Text('Location',
|
label:
|
||||||
style:
|
Text('Location', style: Theme.of(context).textTheme.bodyMedium)),
|
||||||
Theme.of(context).textTheme.bodyMedium)),
|
|
||||||
],
|
],
|
||||||
rows: state.tags.isEmpty
|
rows: state.tags.isEmpty
|
||||||
? [
|
? [
|
||||||
@ -103,12 +95,8 @@ class AssignTagDialog extends StatelessWidget {
|
|||||||
DataCell(
|
DataCell(
|
||||||
Center(
|
Center(
|
||||||
child: Text('No Data Available',
|
child: Text('No Data Available',
|
||||||
style: Theme.of(context)
|
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||||
.textTheme
|
color: ColorsManager.lightGrayColor,
|
||||||
.bodyMedium
|
|
||||||
?.copyWith(
|
|
||||||
color: ColorsManager
|
|
||||||
.lightGrayColor,
|
|
||||||
)),
|
)),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -126,8 +114,7 @@ class AssignTagDialog extends StatelessWidget {
|
|||||||
DataCell(Text((index + 1).toString())),
|
DataCell(Text((index + 1).toString())),
|
||||||
DataCell(
|
DataCell(
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment:
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Text(
|
child: Text(
|
||||||
@ -141,31 +128,25 @@ class AssignTagDialog extends StatelessWidget {
|
|||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
border: Border.all(
|
border: Border.all(
|
||||||
color: ColorsManager
|
color: ColorsManager.lightGrayColor,
|
||||||
.lightGrayColor,
|
|
||||||
width: 1.0,
|
width: 1.0,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: IconButton(
|
child: IconButton(
|
||||||
icon: const Icon(
|
icon: const Icon(
|
||||||
Icons.close,
|
Icons.close,
|
||||||
color: ColorsManager
|
color: ColorsManager.lightGreyColor,
|
||||||
.lightGreyColor,
|
|
||||||
size: 16,
|
size: 16,
|
||||||
),
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
context
|
context.read<AssignTagBloc>().add(
|
||||||
.read<AssignTagBloc>()
|
DeleteTag(tagToDelete: tag, tags: state.tags));
|
||||||
.add(DeleteTag(
|
|
||||||
tagToDelete: tag,
|
|
||||||
tags: state.tags));
|
|
||||||
|
|
||||||
controllers.removeAt(index);
|
controllers.removeAt(index);
|
||||||
},
|
},
|
||||||
tooltip: 'Delete Tag',
|
tooltip: 'Delete Tag',
|
||||||
padding: EdgeInsets.zero,
|
padding: EdgeInsets.zero,
|
||||||
constraints:
|
constraints: const BoxConstraints(),
|
||||||
const BoxConstraints(),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -173,23 +154,20 @@ class AssignTagDialog extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
DataCell(
|
DataCell(
|
||||||
Container(
|
Container(
|
||||||
alignment: Alignment
|
alignment:
|
||||||
.centerLeft, // Align cell content to the left
|
Alignment.centerLeft, // Align cell content to the left
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
width: double
|
width: double.infinity,
|
||||||
.infinity, // Ensure full width for dropdown
|
child: TagDialogTextfieldDropdown(
|
||||||
child: DialogTextfieldDropdown(
|
key: ValueKey('dropdown_${const Uuid().v4()}_$index'),
|
||||||
key: ValueKey(
|
|
||||||
'dropdown_${Uuid().v4()}_${index}'),
|
|
||||||
items: state.updatedTags,
|
items: state.updatedTags,
|
||||||
initialValue: tag.tag,
|
product: tag.product?.uuid ?? 'Unknown',
|
||||||
|
initialValue: tag,
|
||||||
onSelected: (value) {
|
onSelected: (value) {
|
||||||
controller.text = value;
|
controller.text = value.tag ?? '';
|
||||||
context
|
context.read<AssignTagBloc>().add(UpdateTagEvent(
|
||||||
.read<AssignTagBloc>()
|
|
||||||
.add(UpdateTagEvent(
|
|
||||||
index: index,
|
index: index,
|
||||||
tag: value.trim(),
|
tag: value,
|
||||||
));
|
));
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -201,12 +179,9 @@ class AssignTagDialog extends StatelessWidget {
|
|||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
child: DialogDropdown(
|
child: DialogDropdown(
|
||||||
items: locations,
|
items: locations,
|
||||||
selectedValue:
|
selectedValue: tag.location ?? 'Main Space',
|
||||||
tag.location ?? 'Main Space',
|
|
||||||
onSelected: (value) {
|
onSelected: (value) {
|
||||||
context
|
context.read<AssignTagBloc>().add(UpdateLocation(
|
||||||
.read<AssignTagBloc>()
|
|
||||||
.add(UpdateLocation(
|
|
||||||
index: index,
|
index: index,
|
||||||
location: value,
|
location: value,
|
||||||
));
|
));
|
||||||
@ -238,13 +213,11 @@ class AssignTagDialog extends StatelessWidget {
|
|||||||
label: 'Add New Device',
|
label: 'Add New Device',
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
final updatedTags = List<Tag>.from(state.tags);
|
final updatedTags = List<Tag>.from(state.tags);
|
||||||
final result =
|
final result = TagHelper.processTags(updatedTags, subspaces);
|
||||||
TagHelper.processTags(updatedTags, subspaces);
|
|
||||||
|
|
||||||
final processedTags =
|
final processedTags = result['updatedTags'] as List<Tag>;
|
||||||
result['updatedTags'] as List<Tag>;
|
final processedSubspaces =
|
||||||
final processedSubspaces = List<SubspaceModel>.from(
|
List<SubspaceModel>.from(result['subspaces'] as List<dynamic>);
|
||||||
result['subspaces'] as List<dynamic>);
|
|
||||||
|
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
|
|
||||||
@ -253,8 +226,9 @@ class AssignTagDialog extends StatelessWidget {
|
|||||||
builder: (context) => AddDeviceTypeWidget(
|
builder: (context) => AddDeviceTypeWidget(
|
||||||
products: products,
|
products: products,
|
||||||
subspaces: processedSubspaces,
|
subspaces: processedSubspaces,
|
||||||
initialSelectedProducts: TagHelper
|
projectTags: projectTags,
|
||||||
.createInitialSelectedProductsForTags(
|
initialSelectedProducts:
|
||||||
|
TagHelper.createInitialSelectedProductsForTags(
|
||||||
processedTags, processedSubspaces),
|
processedTags, processedSubspaces),
|
||||||
spaceName: spaceName,
|
spaceName: spaceName,
|
||||||
spaceTags: processedTags,
|
spaceTags: processedTags,
|
||||||
@ -278,14 +252,11 @@ class AssignTagDialog extends StatelessWidget {
|
|||||||
onPressed: state.isSaveEnabled
|
onPressed: state.isSaveEnabled
|
||||||
? () async {
|
? () async {
|
||||||
final updatedTags = List<Tag>.from(state.tags);
|
final updatedTags = List<Tag>.from(state.tags);
|
||||||
final result = TagHelper.processTags(
|
final result = TagHelper.processTags(updatedTags, subspaces);
|
||||||
updatedTags, subspaces);
|
|
||||||
|
|
||||||
final processedTags =
|
final processedTags = result['updatedTags'] as List<Tag>;
|
||||||
result['updatedTags'] as List<Tag>;
|
|
||||||
final processedSubspaces =
|
final processedSubspaces =
|
||||||
List<SubspaceModel>.from(
|
List<SubspaceModel>.from(result['subspaces'] as List<dynamic>);
|
||||||
result['subspaces'] as List<dynamic>);
|
|
||||||
onSave?.call(processedTags, processedSubspaces);
|
onSave?.call(processedTags, processedSubspaces);
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ class AssignTagModelBloc extends Bloc<AssignTagModelEvent, AssignTagModelState>
|
|||||||
|
|
||||||
AssignTagModelBloc(this.projectTags) : super(AssignTagModelInitial()) {
|
AssignTagModelBloc(this.projectTags) : super(AssignTagModelInitial()) {
|
||||||
on<InitializeTagModels>((event, emit) {
|
on<InitializeTagModels>((event, emit) {
|
||||||
final initialTags = event.initialTags ?? [];
|
final initialTags = event.initialTags;
|
||||||
|
|
||||||
final existingTagCounts = <String, int>{};
|
final existingTagCounts = <String, int>{};
|
||||||
for (var tag in initialTags) {
|
for (var tag in initialTags) {
|
||||||
@ -67,7 +67,7 @@ class AssignTagModelBloc extends Bloc<AssignTagModelEvent, AssignTagModelState>
|
|||||||
location: event.tag.location,
|
location: event.tag.location,
|
||||||
);
|
);
|
||||||
|
|
||||||
final updatedTags = _calculateAvailableTags(projectTags ?? [], tags);
|
final updatedTags = _calculateAvailableTags(projectTags, tags);
|
||||||
|
|
||||||
emit(AssignTagModelLoaded(
|
emit(AssignTagModelLoaded(
|
||||||
tags: tags,
|
tags: tags,
|
||||||
@ -83,12 +83,9 @@ class AssignTagModelBloc extends Bloc<AssignTagModelEvent, AssignTagModelState>
|
|||||||
|
|
||||||
if (currentState is AssignTagModelLoaded && currentState.tags.isNotEmpty) {
|
if (currentState is AssignTagModelLoaded && currentState.tags.isNotEmpty) {
|
||||||
final tags = List<Tag>.from(currentState.tags);
|
final tags = List<Tag>.from(currentState.tags);
|
||||||
for (var t in tags) {
|
|
||||||
}
|
|
||||||
// Use copyWith for immutability
|
// Use copyWith for immutability
|
||||||
tags[event.index] = tags[event.index].copyWith(location: event.location);
|
tags[event.index] = tags[event.index].copyWith(location: event.location);
|
||||||
|
|
||||||
|
|
||||||
final updatedTags = _calculateAvailableTags(projectTags, tags);
|
final updatedTags = _calculateAvailableTags(projectTags, tags);
|
||||||
|
|
||||||
emit(AssignTagModelLoaded(
|
emit(AssignTagModelLoaded(
|
||||||
|
@ -171,8 +171,7 @@ class AssignTagModelsDialog extends StatelessWidget {
|
|||||||
alignment: Alignment
|
alignment: Alignment
|
||||||
.centerLeft, // Align cell content to the left
|
.centerLeft, // Align cell content to the left
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
width:
|
width: double.infinity,
|
||||||
double.infinity, // Ensure full width for dropdown
|
|
||||||
child: TagDialogTextfieldDropdown(
|
child: TagDialogTextfieldDropdown(
|
||||||
key: ValueKey(
|
key: ValueKey(
|
||||||
'dropdown_${const Uuid().v4()}_$index'),
|
'dropdown_${const Uuid().v4()}_$index'),
|
||||||
|
Reference in New Issue
Block a user