mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-10 15:17:31 +00:00
Merge pull request #73 from SyncrowIOT/bugfix/edit-space
Bugfix/edit space
This commit is contained in:
@ -12,7 +12,6 @@ import 'package:syncrow_web/pages/spaces_management/all_spaces/model/product_mod
|
|||||||
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/selected_product_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/selected_product_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/assign_tag/views/assign_tag_dialog.dart';
|
import 'package:syncrow_web/pages/spaces_management/assign_tag/views/assign_tag_dialog.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/helper/tag_helper.dart';
|
import 'package:syncrow_web/pages/spaces_management/helper/tag_helper.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/tag_model/widgets/action_button_widget.dart';
|
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
|
||||||
class AddDeviceTypeWidget extends StatelessWidget {
|
class AddDeviceTypeWidget extends StatelessWidget {
|
||||||
@ -23,10 +22,12 @@ class AddDeviceTypeWidget extends StatelessWidget {
|
|||||||
final List<Tag>? spaceTags;
|
final List<Tag>? spaceTags;
|
||||||
final List<String>? allTags;
|
final List<String>? allTags;
|
||||||
final String spaceName;
|
final String spaceName;
|
||||||
|
final bool isCreate;
|
||||||
final Function(List<Tag>, List<SubspaceModel>?)? onSave;
|
final Function(List<Tag>, List<SubspaceModel>?)? onSave;
|
||||||
|
|
||||||
const AddDeviceTypeWidget(
|
const AddDeviceTypeWidget(
|
||||||
{super.key,
|
{super.key,
|
||||||
|
required this.isCreate,
|
||||||
this.products,
|
this.products,
|
||||||
this.initialSelectedProducts,
|
this.initialSelectedProducts,
|
||||||
this.onProductsSelected,
|
this.onProductsSelected,
|
||||||
@ -74,7 +75,9 @@ class AddDeviceTypeWidget extends StatelessWidget {
|
|||||||
padding:
|
padding:
|
||||||
const EdgeInsets.symmetric(horizontal: 20.0),
|
const EdgeInsets.symmetric(horizontal: 20.0),
|
||||||
child: ScrollableGridViewWidget(
|
child: ScrollableGridViewWidget(
|
||||||
|
initialProductCounts: state.selectedProducts,
|
||||||
products: products,
|
products: products,
|
||||||
|
isCreate: isCreate,
|
||||||
crossAxisCount: crossAxisCount),
|
crossAxisCount: crossAxisCount),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -131,10 +134,7 @@ class AddDeviceTypeWidget extends StatelessWidget {
|
|||||||
spaceName: spaceName,
|
spaceName: spaceName,
|
||||||
initialTags: initialTags,
|
initialTags: initialTags,
|
||||||
title: dialogTitle,
|
title: dialogTitle,
|
||||||
onSave: (tags, subspaces) {
|
onSave: onSave),
|
||||||
onSave!(tags, subspaces);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -148,29 +148,4 @@ class AddDeviceTypeWidget extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Tag> generateInitialTags({
|
|
||||||
List<Tag>? spaceTags,
|
|
||||||
List<SubspaceModel>? subspaces,
|
|
||||||
}) {
|
|
||||||
final List<Tag> initialTags = [];
|
|
||||||
|
|
||||||
if (spaceTags != null) {
|
|
||||||
initialTags.addAll(spaceTags);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (subspaces != null) {
|
|
||||||
for (var subspace in subspaces) {
|
|
||||||
if (subspace.tags != null) {
|
|
||||||
initialTags.addAll(
|
|
||||||
subspace.tags!.map(
|
|
||||||
(tag) => tag.copyWith(location: subspace.subspaceName),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return initialTags;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -13,12 +13,13 @@ import 'package:syncrow_web/utils/constants/assets.dart';
|
|||||||
class DeviceTypeTileWidget extends StatelessWidget {
|
class DeviceTypeTileWidget extends StatelessWidget {
|
||||||
final ProductModel product;
|
final ProductModel product;
|
||||||
final List<SelectedProduct> productCounts;
|
final List<SelectedProduct> productCounts;
|
||||||
|
final bool isCreate;
|
||||||
|
|
||||||
const DeviceTypeTileWidget({
|
const DeviceTypeTileWidget(
|
||||||
super.key,
|
{super.key,
|
||||||
required this.product,
|
required this.product,
|
||||||
required this.productCounts,
|
required this.productCounts,
|
||||||
});
|
required this.isCreate});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -48,7 +49,7 @@ class DeviceTypeTileWidget extends StatelessWidget {
|
|||||||
DeviceNameWidget(name: product.name),
|
DeviceNameWidget(name: product.name),
|
||||||
const SizedBox(height: 4),
|
const SizedBox(height: 4),
|
||||||
CounterWidget(
|
CounterWidget(
|
||||||
isCreate: false,
|
isCreate: isCreate,
|
||||||
initialCount: selectedProduct.count,
|
initialCount: selectedProduct.count,
|
||||||
onCountChanged: (newCount) {
|
onCountChanged: (newCount) {
|
||||||
context.read<AddDeviceTypeBloc>().add(
|
context.read<AddDeviceTypeBloc>().add(
|
||||||
|
@ -10,13 +10,14 @@ class ScrollableGridViewWidget extends StatelessWidget {
|
|||||||
final List<ProductModel>? products;
|
final List<ProductModel>? products;
|
||||||
final int crossAxisCount;
|
final int crossAxisCount;
|
||||||
final List<SelectedProduct>? initialProductCounts;
|
final List<SelectedProduct>? initialProductCounts;
|
||||||
|
final bool isCreate;
|
||||||
|
|
||||||
const ScrollableGridViewWidget({
|
const ScrollableGridViewWidget(
|
||||||
super.key,
|
{super.key,
|
||||||
required this.products,
|
required this.products,
|
||||||
required this.crossAxisCount,
|
required this.crossAxisCount,
|
||||||
this.initialProductCounts,
|
this.initialProductCounts,
|
||||||
});
|
required this.isCreate});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -46,6 +47,7 @@ class ScrollableGridViewWidget extends StatelessWidget {
|
|||||||
|
|
||||||
return DeviceTypeTileWidget(
|
return DeviceTypeTileWidget(
|
||||||
product: product,
|
product: product,
|
||||||
|
isCreate: isCreate,
|
||||||
productCounts: initialProductCount != null
|
productCounts: initialProductCount != null
|
||||||
? [...productCounts, initialProductCount]
|
? [...productCounts, initialProductCount]
|
||||||
: productCounts,
|
: productCounts,
|
||||||
|
@ -5,12 +5,15 @@ import 'package:syncrow_web/pages/spaces_management/all_spaces/model/product_mod
|
|||||||
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/all_spaces/bloc/space_management_event.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/bloc/space_management_event.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/all_spaces/bloc/space_management_state.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/bloc/space_management_state.dart';
|
||||||
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/subspace_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/tag.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/tag.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/tag_body_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/space_model/models/tag_body_model.dart';
|
||||||
|
import 'package:syncrow_web/pages/spaces_management/space_model/models/tag_update_model.dart';
|
||||||
import 'package:syncrow_web/services/product_api.dart';
|
import 'package:syncrow_web/services/product_api.dart';
|
||||||
import 'package:syncrow_web/services/space_mana_api.dart';
|
import 'package:syncrow_web/services/space_mana_api.dart';
|
||||||
import 'package:syncrow_web/services/space_model_mang_api.dart';
|
import 'package:syncrow_web/services/space_model_mang_api.dart';
|
||||||
|
import 'package:syncrow_web/utils/constants/action_enum.dart';
|
||||||
|
|
||||||
class SpaceManagementBloc
|
class SpaceManagementBloc
|
||||||
extends Bloc<SpaceManagementEvent, SpaceManagementState> {
|
extends Bloc<SpaceManagementEvent, SpaceManagementState> {
|
||||||
@ -341,7 +344,7 @@ class SpaceManagementBloc
|
|||||||
products: _cachedProducts ?? [],
|
products: _cachedProducts ?? [],
|
||||||
selectedCommunity: selectedCommunity,
|
selectedCommunity: selectedCommunity,
|
||||||
selectedSpace: selectedSpace,
|
selectedSpace: selectedSpace,
|
||||||
spaceModels: spaceModels ?? []));
|
spaceModels: spaceModels));
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(SpaceManagementError('Error updating state: $e'));
|
emit(SpaceManagementError('Error updating state: $e'));
|
||||||
@ -428,6 +431,76 @@ class SpaceManagementBloc
|
|||||||
for (var space in orderedSpaces) {
|
for (var space in orderedSpaces) {
|
||||||
try {
|
try {
|
||||||
if (space.uuid != null && space.uuid!.isNotEmpty) {
|
if (space.uuid != null && space.uuid!.isNotEmpty) {
|
||||||
|
List<TagModelUpdate> tagUpdates = [];
|
||||||
|
|
||||||
|
final prevSpace = await _api.getSpace(communityUuid, space.uuid!);
|
||||||
|
final List<UpdateSubspaceTemplateModel> subspaceUpdates = [];
|
||||||
|
final List<SubspaceModel>? prevSubspaces = prevSpace?.subspaces;
|
||||||
|
final List<SubspaceModel>? newSubspaces = space.subspaces;
|
||||||
|
|
||||||
|
tagUpdates = processTagUpdates(prevSpace?.tags, space.tags);
|
||||||
|
|
||||||
|
if (prevSubspaces != null || newSubspaces != null) {
|
||||||
|
if (prevSubspaces != null && newSubspaces != null) {
|
||||||
|
for (var prevSubspace in prevSubspaces) {
|
||||||
|
final existsInNew = newSubspaces
|
||||||
|
.any((subspace) => subspace.uuid == prevSubspace.uuid);
|
||||||
|
if (!existsInNew) {
|
||||||
|
subspaceUpdates.add(UpdateSubspaceTemplateModel(
|
||||||
|
action: Action.delete, uuid: prevSubspace.uuid));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (prevSubspaces != null && newSubspaces == null) {
|
||||||
|
for (var prevSubspace in prevSubspaces) {
|
||||||
|
subspaceUpdates.add(UpdateSubspaceTemplateModel(
|
||||||
|
action: Action.delete, uuid: prevSubspace.uuid));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newSubspaces != null) {
|
||||||
|
for (var newSubspace in newSubspaces) {
|
||||||
|
// Tag without UUID
|
||||||
|
if ((newSubspace.uuid == null || newSubspace.uuid!.isEmpty)) {
|
||||||
|
final List<TagModelUpdate> tagUpdates = [];
|
||||||
|
|
||||||
|
if (newSubspace.tags != null) {
|
||||||
|
for (var tag in newSubspace.tags!) {
|
||||||
|
tagUpdates.add(TagModelUpdate(
|
||||||
|
action: Action.add,
|
||||||
|
uuid: tag.uuid == '' ? null : tag.uuid,
|
||||||
|
tag: tag.tag,
|
||||||
|
productUuid: tag.product?.uuid));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
subspaceUpdates.add(UpdateSubspaceTemplateModel(
|
||||||
|
action: Action.add,
|
||||||
|
subspaceName: newSubspace.subspaceName,
|
||||||
|
tags: tagUpdates));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prevSubspaces != null && newSubspaces != null) {
|
||||||
|
final newSubspaceMap = {
|
||||||
|
for (var subspace in newSubspaces) subspace.uuid: subspace
|
||||||
|
};
|
||||||
|
|
||||||
|
for (var prevSubspace in prevSubspaces) {
|
||||||
|
final newSubspace = newSubspaceMap[prevSubspace.uuid];
|
||||||
|
|
||||||
|
if (newSubspace != null) {
|
||||||
|
final List<TagModelUpdate> tagSubspaceUpdates =
|
||||||
|
processTagUpdates(prevSubspace.tags, newSubspace.tags);
|
||||||
|
subspaceUpdates.add(UpdateSubspaceTemplateModel(
|
||||||
|
action: Action.update,
|
||||||
|
uuid: newSubspace.uuid,
|
||||||
|
subspaceName: newSubspace.subspaceName,
|
||||||
|
tags: tagSubspaceUpdates));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
final response = await _api.updateSpace(
|
final response = await _api.updateSpace(
|
||||||
communityId: communityUuid,
|
communityId: communityUuid,
|
||||||
spaceId: space.uuid!,
|
spaceId: space.uuid!,
|
||||||
@ -436,6 +509,8 @@ class SpaceManagementBloc
|
|||||||
isPrivate: space.isPrivate,
|
isPrivate: space.isPrivate,
|
||||||
position: space.position,
|
position: space.position,
|
||||||
icon: space.icon,
|
icon: space.icon,
|
||||||
|
subspaces: subspaceUpdates,
|
||||||
|
tags: tagUpdates,
|
||||||
direction: space.incomingConnection?.direction,
|
direction: space.incomingConnection?.direction,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
@ -535,4 +610,79 @@ class SpaceManagementBloc
|
|||||||
emit(SpaceManagementError('Error loading communities and spaces: $e'));
|
emit(SpaceManagementError('Error loading communities and spaces: $e'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<TagModelUpdate> processTagUpdates(
|
||||||
|
List<Tag>? prevTags,
|
||||||
|
List<Tag>? newTags,
|
||||||
|
) {
|
||||||
|
final List<TagModelUpdate> tagUpdates = [];
|
||||||
|
final processedTags = <String?>{};
|
||||||
|
|
||||||
|
if (prevTags == null && newTags != null) {
|
||||||
|
for (var newTag in newTags) {
|
||||||
|
tagUpdates.add(TagModelUpdate(
|
||||||
|
action: Action.add,
|
||||||
|
tag: newTag.tag,
|
||||||
|
uuid: newTag.uuid,
|
||||||
|
productUuid: newTag.product?.uuid,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
return tagUpdates;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newTags != null || prevTags != null) {
|
||||||
|
// Case 1: Tags deleted
|
||||||
|
if (prevTags != null && newTags != null) {
|
||||||
|
for (var prevTag in prevTags) {
|
||||||
|
final existsInNew =
|
||||||
|
newTags.any((newTag) => newTag.uuid == prevTag.uuid);
|
||||||
|
if (!existsInNew) {
|
||||||
|
tagUpdates
|
||||||
|
.add(TagModelUpdate(action: Action.delete, uuid: prevTag.uuid));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (prevTags != null && newTags == null) {
|
||||||
|
for (var prevTag in prevTags) {
|
||||||
|
tagUpdates
|
||||||
|
.add(TagModelUpdate(action: Action.delete, uuid: prevTag.uuid));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Case 2: Tags added
|
||||||
|
if (newTags != null) {
|
||||||
|
final prevTagUuids = prevTags?.map((t) => t.uuid).toSet() ?? {};
|
||||||
|
|
||||||
|
for (var newTag in newTags) {
|
||||||
|
// Tag without UUID
|
||||||
|
if ((newTag.uuid == null || !prevTagUuids.contains(newTag.uuid)) &&
|
||||||
|
!processedTags.contains(newTag.tag)) {
|
||||||
|
tagUpdates.add(TagModelUpdate(
|
||||||
|
action: Action.add,
|
||||||
|
tag: newTag.tag,
|
||||||
|
uuid: newTag.uuid == '' ? null : newTag.uuid,
|
||||||
|
productUuid: newTag.product?.uuid));
|
||||||
|
processedTags.add(newTag.tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Case 3: Tags updated
|
||||||
|
if (prevTags != null && newTags != null) {
|
||||||
|
final newTagMap = {for (var tag in newTags) tag.uuid: tag};
|
||||||
|
|
||||||
|
for (var prevTag in prevTags) {
|
||||||
|
final newTag = newTagMap[prevTag.uuid];
|
||||||
|
if (newTag != null) {
|
||||||
|
tagUpdates.add(TagModelUpdate(
|
||||||
|
action: Action.update,
|
||||||
|
uuid: newTag.uuid,
|
||||||
|
tag: newTag.tag,
|
||||||
|
));
|
||||||
|
} else {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tagUpdates;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,6 @@ class SpaceModel {
|
|||||||
final instance = SpaceModel(
|
final instance = SpaceModel(
|
||||||
internalId: internalId,
|
internalId: internalId,
|
||||||
uuid: json['uuid'] ?? '',
|
uuid: json['uuid'] ?? '',
|
||||||
spaceTuyaUuid: json['spaceTuyaUuid'],
|
|
||||||
name: json['spaceName'],
|
name: json['spaceName'],
|
||||||
isPrivate: json['isPrivate'] ?? false,
|
isPrivate: json['isPrivate'] ?? false,
|
||||||
invitationCode: json['invitationCode'],
|
invitationCode: json['invitationCode'],
|
||||||
|
@ -195,6 +195,7 @@ class _CommunityStructureAreaState extends State<CommunityStructureArea> {
|
|||||||
screenSize,
|
screenSize,
|
||||||
position:
|
position:
|
||||||
spaces[index].position + newPosition,
|
spaces[index].position + newPosition,
|
||||||
|
|
||||||
parentIndex: index,
|
parentIndex: index,
|
||||||
direction: direction,
|
direction: direction,
|
||||||
);
|
);
|
||||||
@ -294,6 +295,7 @@ class _CommunityStructureAreaState extends State<CommunityStructureArea> {
|
|||||||
return CreateSpaceDialog(
|
return CreateSpaceDialog(
|
||||||
products: widget.products,
|
products: widget.products,
|
||||||
spaceModels: widget.spaceModels,
|
spaceModels: widget.spaceModels,
|
||||||
|
allTags: _getAllTagValues(spaces),
|
||||||
parentSpace: parentIndex != null ? spaces[parentIndex] : null,
|
parentSpace: parentIndex != null ? spaces[parentIndex] : null,
|
||||||
onCreateSpace: (String name,
|
onCreateSpace: (String name,
|
||||||
String icon,
|
String icon,
|
||||||
@ -350,7 +352,10 @@ class _CommunityStructureAreaState extends State<CommunityStructureArea> {
|
|||||||
name: widget.selectedSpace!.name,
|
name: widget.selectedSpace!.name,
|
||||||
icon: widget.selectedSpace!.icon,
|
icon: widget.selectedSpace!.icon,
|
||||||
editSpace: widget.selectedSpace,
|
editSpace: widget.selectedSpace,
|
||||||
|
tags: widget.selectedSpace?.tags,
|
||||||
|
subspaces: widget.selectedSpace?.subspaces,
|
||||||
isEdit: true,
|
isEdit: true,
|
||||||
|
allTags: _getAllTagValues(spaces),
|
||||||
onCreateSpace: (String name,
|
onCreateSpace: (String name,
|
||||||
String icon,
|
String icon,
|
||||||
List<SelectedProduct> selectedProducts,
|
List<SelectedProduct> selectedProducts,
|
||||||
@ -742,4 +747,14 @@ class _CommunityStructureAreaState extends State<CommunityStructureArea> {
|
|||||||
duplicateRecursive(space, space.position, duplicatedParent);
|
duplicateRecursive(space, space.position, duplicatedParent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<String> _getAllTagValues(List<SpaceModel> spaces) {
|
||||||
|
final List<String> allTags = [];
|
||||||
|
for (final space in spaces) {
|
||||||
|
if (space.tags != null) {
|
||||||
|
allTags.addAll(space.listAllTagValues());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return allTags;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,7 @@ class CreateSpaceDialog extends StatefulWidget {
|
|||||||
final List<SpaceTemplateModel>? spaceModels;
|
final List<SpaceTemplateModel>? spaceModels;
|
||||||
final List<SubspaceModel>? subspaces;
|
final List<SubspaceModel>? subspaces;
|
||||||
final List<Tag>? tags;
|
final List<Tag>? tags;
|
||||||
|
final List<String>? allTags;
|
||||||
|
|
||||||
const CreateSpaceDialog(
|
const CreateSpaceDialog(
|
||||||
{super.key,
|
{super.key,
|
||||||
@ -49,6 +50,7 @@ class CreateSpaceDialog extends StatefulWidget {
|
|||||||
this.icon,
|
this.icon,
|
||||||
this.isEdit = false,
|
this.isEdit = false,
|
||||||
this.editSpace,
|
this.editSpace,
|
||||||
|
this.allTags,
|
||||||
this.selectedProducts = const [],
|
this.selectedProducts = const [],
|
||||||
this.spaceModels,
|
this.spaceModels,
|
||||||
this.subspaces,
|
this.subspaces,
|
||||||
@ -79,6 +81,8 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
|
|||||||
widget.selectedProducts.isNotEmpty ? widget.selectedProducts : [];
|
widget.selectedProducts.isNotEmpty ? widget.selectedProducts : [];
|
||||||
isOkButtonEnabled =
|
isOkButtonEnabled =
|
||||||
enteredName.isNotEmpty || nameController.text.isNotEmpty;
|
enteredName.isNotEmpty || nameController.text.isNotEmpty;
|
||||||
|
tags = widget.tags ?? [];
|
||||||
|
subspaces = widget.subspaces ?? [];
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -171,14 +175,13 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
style: const TextStyle(color: Colors.black),
|
style: Theme.of(context).textTheme.bodyMedium,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: 'Please enter the name',
|
hintText: 'Please enter the name',
|
||||||
hintStyle: const TextStyle(
|
hintStyle: Theme.of(context)
|
||||||
fontSize: 14,
|
.textTheme
|
||||||
color: ColorsManager.lightGrayColor,
|
.bodyMedium!
|
||||||
fontWeight: FontWeight.w400,
|
.copyWith(color: ColorsManager.lightGrayColor),
|
||||||
),
|
|
||||||
filled: true,
|
filled: true,
|
||||||
fillColor: ColorsManager.boxColor,
|
fillColor: ColorsManager.boxColor,
|
||||||
enabledBorder: OutlineInputBorder(
|
enabledBorder: OutlineInputBorder(
|
||||||
@ -237,7 +240,7 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
: Container(
|
: Container(
|
||||||
width: screenWidth * 0.35,
|
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(
|
||||||
@ -251,7 +254,10 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
|
|||||||
Chip(
|
Chip(
|
||||||
label: Text(
|
label: Text(
|
||||||
selectedSpaceModel?.modelName ?? '',
|
selectedSpaceModel?.modelName ?? '',
|
||||||
style: const TextStyle(
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.bodyMedium!
|
||||||
|
.copyWith(
|
||||||
color: ColorsManager.spaceColor),
|
color: ColorsManager.spaceColor),
|
||||||
),
|
),
|
||||||
backgroundColor: ColorsManager.whiteColors,
|
backgroundColor: ColorsManager.whiteColors,
|
||||||
@ -285,25 +291,25 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 25),
|
const SizedBox(height: 25),
|
||||||
const Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
const Expanded(
|
||||||
child: Divider(
|
child: Divider(
|
||||||
color: ColorsManager.neutralGray,
|
color: ColorsManager.neutralGray,
|
||||||
thickness: 1.0,
|
thickness: 1.0,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.symmetric(horizontal: 6.0),
|
padding: const EdgeInsets.symmetric(horizontal: 6.0),
|
||||||
child: Text(
|
child: Text(
|
||||||
'OR',
|
'OR',
|
||||||
style: TextStyle(
|
style: Theme.of(context)
|
||||||
color: Colors.black,
|
.textTheme
|
||||||
fontWeight: FontWeight.bold,
|
.bodyMedium
|
||||||
|
?.copyWith(fontWeight: FontWeight.bold),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
const Expanded(
|
||||||
Expanded(
|
|
||||||
child: Divider(
|
child: Divider(
|
||||||
color: ColorsManager.neutralGray,
|
color: ColorsManager.neutralGray,
|
||||||
thickness: 1.0,
|
thickness: 1.0,
|
||||||
@ -312,7 +318,7 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 25),
|
const SizedBox(height: 25),
|
||||||
subspaces == null
|
subspaces == null || subspaces!.isEmpty
|
||||||
? TextButton(
|
? TextButton(
|
||||||
style: TextButton.styleFrom(
|
style: TextButton.styleFrom(
|
||||||
padding: EdgeInsets.zero,
|
padding: EdgeInsets.zero,
|
||||||
@ -344,21 +350,29 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
|
|||||||
runSpacing: 8.0,
|
runSpacing: 8.0,
|
||||||
children: [
|
children: [
|
||||||
if (subspaces != null)
|
if (subspaces != null)
|
||||||
...subspaces!.map((subspace) =>
|
...subspaces!.map((subspace) {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment:
|
||||||
|
CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
SubspaceNameDisplayWidget(
|
SubspaceNameDisplayWidget(
|
||||||
validateName: (updatedName) {
|
|
||||||
return !subspaces!.any((s) =>
|
|
||||||
s != subspace &&
|
|
||||||
s.subspaceName == updatedName);
|
|
||||||
},
|
|
||||||
text: subspace.subspaceName,
|
text: subspace.subspaceName,
|
||||||
|
validateName: (updatedName) {
|
||||||
|
return subspaces!.any((s) =>
|
||||||
|
s != subspace &&
|
||||||
|
s.subspaceName ==
|
||||||
|
updatedName);
|
||||||
|
},
|
||||||
onNameChanged: (updatedName) {
|
onNameChanged: (updatedName) {
|
||||||
setState(() {
|
setState(() {
|
||||||
subspace.subspaceName =
|
subspace.subspaceName =
|
||||||
updatedName;
|
updatedName;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
)),
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}),
|
||||||
EditChip(
|
EditChip(
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
_showSubSpaceDialog(context, enteredName,
|
_showSubSpaceDialog(context, enteredName,
|
||||||
@ -408,9 +422,12 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
|
|||||||
),
|
),
|
||||||
label: Text(
|
label: Text(
|
||||||
'x${entry.value}', // Show count
|
'x${entry.value}', // Show count
|
||||||
style: const TextStyle(
|
style: Theme.of(context)
|
||||||
color: ColorsManager.spaceColor,
|
.textTheme
|
||||||
),
|
.bodySmall
|
||||||
|
?.copyWith(
|
||||||
|
color: ColorsManager
|
||||||
|
.spaceColor),
|
||||||
),
|
),
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
ColorsManager.whiteColors,
|
ColorsManager.whiteColors,
|
||||||
@ -425,14 +442,29 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
|
|||||||
),
|
),
|
||||||
|
|
||||||
EditChip(onTap: () async {
|
EditChip(onTap: () async {
|
||||||
_showTagCreateDialog(
|
final result = await showDialog(
|
||||||
context,
|
context: context,
|
||||||
enteredName,
|
builder: (context) => AssignTagDialog(
|
||||||
widget.isEdit,
|
products: widget.products,
|
||||||
widget.products,
|
subspaces: widget.subspaces,
|
||||||
subspaces,
|
addedProducts: TagHelper
|
||||||
|
.createInitialSelectedProductsForTags(
|
||||||
|
tags ?? [], subspaces),
|
||||||
|
title: 'Edit Device',
|
||||||
|
initialTags:
|
||||||
|
TagHelper.generateInitialForTags(
|
||||||
|
spaceTags: tags,
|
||||||
|
subspaces: subspaces),
|
||||||
|
spaceName: widget.name ?? '',
|
||||||
|
onSave:
|
||||||
|
(updatedTags, updatedSubspaces) {
|
||||||
|
setState(() {
|
||||||
|
tags = updatedTags;
|
||||||
|
subspaces = updatedSubspaces;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
);
|
);
|
||||||
// Edit action
|
|
||||||
})
|
})
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -547,6 +579,7 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
|
|||||||
setState(() {
|
setState(() {
|
||||||
selectedSpaceModel = selectedModel;
|
selectedSpaceModel = selectedModel;
|
||||||
subspaces = null;
|
subspaces = null;
|
||||||
|
tags = null;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -597,8 +630,26 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
|
|||||||
spaceName: name,
|
spaceName: name,
|
||||||
products: products,
|
products: products,
|
||||||
subspaces: subspaces,
|
subspaces: subspaces,
|
||||||
allTags: [],
|
allTags: widget.allTags,
|
||||||
onSave: (selectedSpaceTags, selectedSubspaces) {},
|
onSave: (selectedSpaceTags, selectedSubspaces) {
|
||||||
|
setState(() {
|
||||||
|
tags = selectedSpaceTags;
|
||||||
|
selectedSpaceModel = null;
|
||||||
|
|
||||||
|
if (selectedSubspaces != null) {
|
||||||
|
if (subspaces != null) {
|
||||||
|
for (final subspace in subspaces!) {
|
||||||
|
for (final selectedSubspace in selectedSubspaces) {
|
||||||
|
if (subspace.subspaceName ==
|
||||||
|
selectedSubspace.subspaceName) {
|
||||||
|
subspace.tags = selectedSubspace.tags;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -610,7 +661,8 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
|
|||||||
products: products,
|
products: products,
|
||||||
subspaces: subspaces,
|
subspaces: subspaces,
|
||||||
spaceTags: tags,
|
spaceTags: tags,
|
||||||
allTags: [],
|
isCreate: true,
|
||||||
|
allTags: widget.allTags,
|
||||||
initialSelectedProducts:
|
initialSelectedProducts:
|
||||||
TagHelper.createInitialSelectedProductsForTags(
|
TagHelper.createInitialSelectedProductsForTags(
|
||||||
tags, subspaces),
|
tags, subspaces),
|
||||||
|
@ -20,8 +20,7 @@ class SpaceWidget extends StatelessWidget {
|
|||||||
top: position.dy,
|
top: position.dy,
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
onTap: onTap,
|
onTap: onTap,
|
||||||
child:
|
child: Container(
|
||||||
Container(
|
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: ColorsManager.whiteColors,
|
color: ColorsManager.whiteColors,
|
||||||
@ -39,11 +38,10 @@ class SpaceWidget extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
const Icon(Icons.location_on, color: ColorsManager.spaceColor),
|
const Icon(Icons.location_on, color: ColorsManager.spaceColor),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
Text(name, style: const TextStyle(fontSize: 16)),
|
Text(name, style: Theme.of(context).textTheme.bodyMedium),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ import 'package:syncrow_web/pages/spaces_management/all_spaces/model/tag.dart';
|
|||||||
import 'package:syncrow_web/pages/spaces_management/assign_tag/bloc/assign_tag_bloc.dart';
|
import 'package:syncrow_web/pages/spaces_management/assign_tag/bloc/assign_tag_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/assign_tag/bloc/assign_tag_event.dart';
|
import 'package:syncrow_web/pages/spaces_management/assign_tag/bloc/assign_tag_event.dart';
|
||||||
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';
|
||||||
|
import 'package:syncrow_web/pages/spaces_management/helper/tag_helper.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
|
||||||
class AssignTagDialog extends StatelessWidget {
|
class AssignTagDialog extends StatelessWidget {
|
||||||
@ -40,8 +41,11 @@ class AssignTagDialog extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final List<String> locations =
|
final List<String> locations = (subspaces ?? [])
|
||||||
(subspaces ?? []).map((subspace) => subspace.subspaceName).toList();
|
.map((subspace) => subspace.subspaceName)
|
||||||
|
.toList()
|
||||||
|
..add('Main Space');
|
||||||
|
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (_) => AssignTagBloc()
|
create: (_) => AssignTagBloc()
|
||||||
..add(InitializeTags(
|
..add(InitializeTags(
|
||||||
@ -93,21 +97,22 @@ class AssignTagDialog extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
rows: state.tags.isEmpty
|
rows: state.tags.isEmpty
|
||||||
? [
|
? [
|
||||||
const DataRow(cells: [
|
DataRow(cells: [
|
||||||
DataCell(
|
DataCell(
|
||||||
Center(
|
Center(
|
||||||
child: Text(
|
child: Text('No Data Available',
|
||||||
'No Data Available',
|
style: Theme.of(context)
|
||||||
style: TextStyle(
|
.textTheme
|
||||||
fontSize: 14,
|
.bodyMedium
|
||||||
color: ColorsManager.lightGrayColor,
|
?.copyWith(
|
||||||
|
color: ColorsManager
|
||||||
|
.lightGrayColor,
|
||||||
|
)),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
const DataCell(SizedBox()),
|
||||||
),
|
const DataCell(SizedBox()),
|
||||||
DataCell(SizedBox()),
|
const DataCell(SizedBox()),
|
||||||
DataCell(SizedBox()),
|
|
||||||
DataCell(SizedBox()),
|
|
||||||
])
|
])
|
||||||
]
|
]
|
||||||
: List.generate(state.tags.length, (index) {
|
: List.generate(state.tags.length, (index) {
|
||||||
@ -209,10 +214,11 @@ class AssignTagDialog extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (state.errorMessage != null)
|
if (state.errorMessage != null)
|
||||||
Text(
|
Text(state.errorMessage!,
|
||||||
state.errorMessage!,
|
style: Theme.of(context)
|
||||||
style: const TextStyle(color: ColorsManager.warningRed),
|
.textTheme
|
||||||
),
|
.bodySmall
|
||||||
|
?.copyWith(color: ColorsManager.warningRed)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -235,16 +241,18 @@ class AssignTagDialog extends StatelessWidget {
|
|||||||
|
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
|
|
||||||
await showDialog<bool>(
|
await showDialog(
|
||||||
barrierDismissible: false,
|
|
||||||
context: context,
|
context: context,
|
||||||
builder: (dialogContext) => AddDeviceTypeWidget(
|
builder: (context) => AddDeviceTypeWidget(
|
||||||
products: products,
|
products: products,
|
||||||
subspaces: processedSubspaces,
|
subspaces: processedSubspaces,
|
||||||
initialSelectedProducts: addedProducts,
|
initialSelectedProducts: TagHelper
|
||||||
allTags: allTags,
|
.createInitialSelectedProductsForTags(
|
||||||
|
processedTags, processedSubspaces),
|
||||||
spaceName: spaceName,
|
spaceName: spaceName,
|
||||||
spaceTags: processedTags,
|
spaceTags: processedTags,
|
||||||
|
isCreate: false,
|
||||||
|
onSave: onSave,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -261,7 +269,6 @@ class AssignTagDialog extends StatelessWidget {
|
|||||||
foregroundColor: ColorsManager.whiteColors,
|
foregroundColor: ColorsManager.whiteColors,
|
||||||
onPressed: state.isSaveEnabled
|
onPressed: state.isSaveEnabled
|
||||||
? () async {
|
? () async {
|
||||||
Navigator.of(context).pop();
|
|
||||||
final updatedTags = List<Tag>.from(state.tags);
|
final updatedTags = List<Tag>.from(state.tags);
|
||||||
final result =
|
final result =
|
||||||
processTags(updatedTags, subspaces);
|
processTags(updatedTags, subspaces);
|
||||||
@ -270,8 +277,8 @@ class AssignTagDialog extends StatelessWidget {
|
|||||||
result['updatedTags'] as List<Tag>;
|
result['updatedTags'] as List<Tag>;
|
||||||
final processedSubspaces =
|
final processedSubspaces =
|
||||||
result['subspaces'] as List<SubspaceModel>;
|
result['subspaces'] as List<SubspaceModel>;
|
||||||
|
onSave?.call(processedTags, processedSubspaces);
|
||||||
onSave!(processedTags, processedSubspaces);
|
Navigator.of(context).pop();
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
child: const Text('Save'),
|
child: const Text('Save'),
|
||||||
@ -307,6 +314,14 @@ class AssignTagDialog extends StatelessWidget {
|
|||||||
final modifiedTags = List<Tag>.from(updatedTags);
|
final modifiedTags = List<Tag>.from(updatedTags);
|
||||||
final modifiedSubspaces = List<SubspaceModel>.from(subspaces ?? []);
|
final modifiedSubspaces = List<SubspaceModel>.from(subspaces ?? []);
|
||||||
|
|
||||||
|
if (subspaces != null) {
|
||||||
|
for (var subspace in subspaces) {
|
||||||
|
subspace.tags?.removeWhere(
|
||||||
|
(tag) => !modifiedTags
|
||||||
|
.any((updatedTag) => updatedTag.internalId == tag.internalId),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
for (var tag in modifiedTags.toList()) {
|
for (var tag in modifiedTags.toList()) {
|
||||||
if (modifiedSubspaces.isEmpty) continue;
|
if (modifiedSubspaces.isEmpty) continue;
|
||||||
|
|
||||||
|
@ -112,22 +112,22 @@ class AssignTagModelsDialog extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
rows: state.tags.isEmpty
|
rows: state.tags.isEmpty
|
||||||
? [
|
? [
|
||||||
const DataRow(cells: [
|
DataRow(cells: [
|
||||||
DataCell(
|
DataCell(
|
||||||
Center(
|
Center(
|
||||||
child: Text(
|
child: Text('No Devices Available',
|
||||||
'No Data Available',
|
style: Theme.of(context)
|
||||||
style: TextStyle(
|
.textTheme
|
||||||
fontSize: 14,
|
.bodyMedium
|
||||||
color:
|
?.copyWith(
|
||||||
ColorsManager.lightGrayColor,
|
color: ColorsManager
|
||||||
|
.lightGrayColor,
|
||||||
|
)),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
const DataCell(SizedBox()),
|
||||||
),
|
const DataCell(SizedBox()),
|
||||||
DataCell(SizedBox()),
|
const DataCell(SizedBox()),
|
||||||
DataCell(SizedBox()),
|
|
||||||
DataCell(SizedBox()),
|
|
||||||
])
|
])
|
||||||
]
|
]
|
||||||
: List.generate(state.tags.length, (index) {
|
: List.generate(state.tags.length, (index) {
|
||||||
@ -233,11 +233,11 @@ class AssignTagModelsDialog extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (state.errorMessage != null)
|
if (state.errorMessage != null)
|
||||||
Text(
|
Text(state.errorMessage!,
|
||||||
state.errorMessage!,
|
style: Theme.of(context)
|
||||||
style: const TextStyle(
|
.textTheme
|
||||||
color: ColorsManager.warningRed),
|
.bodySmall
|
||||||
),
|
?.copyWith(color: ColorsManager.warningRed)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -268,7 +268,7 @@ class AssignTagModelsDialog extends StatelessWidget {
|
|||||||
builder: (dialogContext) =>
|
builder: (dialogContext) =>
|
||||||
AddDeviceTypeModelWidget(
|
AddDeviceTypeModelWidget(
|
||||||
products: products,
|
products: products,
|
||||||
subspaces: subspaces,
|
subspaces: processedSubspaces,
|
||||||
isCreate: false,
|
isCreate: false,
|
||||||
initialSelectedProducts: TagHelper
|
initialSelectedProducts: TagHelper
|
||||||
.createInitialSelectedProducts(
|
.createInitialSelectedProducts(
|
||||||
|
@ -77,9 +77,7 @@ class CreateCommunityDialog extends StatelessWidget {
|
|||||||
.read<CommunityDialogBloc>()
|
.read<CommunityDialogBloc>()
|
||||||
.add(ValidateCommunityNameEvent(value));
|
.add(ValidateCommunityNameEvent(value));
|
||||||
},
|
},
|
||||||
style: const TextStyle(
|
style: Theme.of(context).textTheme.bodyMedium,
|
||||||
color: ColorsManager.blackColor,
|
|
||||||
),
|
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: 'Please enter the community name',
|
hintText: 'Please enter the community name',
|
||||||
filled: true,
|
filled: true,
|
||||||
|
@ -82,7 +82,6 @@ class SubSpaceBloc extends Bloc<SubSpaceEvent, SubSpaceState> {
|
|||||||
));
|
));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
on<UpdateSubSpace>((event, emit) {
|
on<UpdateSubSpace>((event, emit) {
|
||||||
final updatedSubSpaces = state.subSpaces.map((subSpace) {
|
final updatedSubSpaces = state.subSpaces.map((subSpace) {
|
||||||
if (subSpace.uuid == event.updatedSubSpace.uuid) {
|
if (subSpace.uuid == event.updatedSubSpace.uuid) {
|
||||||
|
@ -102,12 +102,13 @@ class CreateSubSpaceDialog extends StatelessWidget {
|
|||||||
duplicateIndices.indexOf(index) != 0;
|
duplicateIndices.indexOf(index) != 0;
|
||||||
|
|
||||||
return Chip(
|
return Chip(
|
||||||
label: Text(
|
label: Text(subSpace.subspaceName,
|
||||||
subSpace.subspaceName,
|
style: Theme.of(context)
|
||||||
style: const TextStyle(
|
.textTheme
|
||||||
color: ColorsManager.spaceColor,
|
.bodyMedium
|
||||||
),
|
?.copyWith(
|
||||||
),
|
color:
|
||||||
|
ColorsManager.spaceColor)),
|
||||||
backgroundColor: ColorsManager.whiteColors,
|
backgroundColor: ColorsManager.whiteColors,
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.circular(10),
|
borderRadius: BorderRadius.circular(10),
|
||||||
@ -149,9 +150,12 @@ class CreateSubSpaceDialog extends StatelessWidget {
|
|||||||
hintText: state.subSpaces.isEmpty
|
hintText: state.subSpaces.isEmpty
|
||||||
? 'Please enter the name'
|
? 'Please enter the name'
|
||||||
: null,
|
: null,
|
||||||
hintStyle: const TextStyle(
|
hintStyle: Theme.of(context)
|
||||||
color: ColorsManager.lightGrayColor),
|
.textTheme
|
||||||
),
|
.bodySmall
|
||||||
|
?.copyWith(
|
||||||
|
color: ColorsManager
|
||||||
|
.lightGrayColor)),
|
||||||
onSubmitted: (value) {
|
onSubmitted: (value) {
|
||||||
if (value.trim().isNotEmpty) {
|
if (value.trim().isNotEmpty) {
|
||||||
context.read<SubSpaceBloc>().add(
|
context.read<SubSpaceBloc>().add(
|
||||||
@ -161,9 +165,8 @@ class CreateSubSpaceDialog extends StatelessWidget {
|
|||||||
textController.clear();
|
textController.clear();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
style: const TextStyle(
|
style:
|
||||||
color: ColorsManager.blackColor),
|
Theme.of(context).textTheme.bodyMedium),
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -171,13 +174,13 @@ class CreateSubSpaceDialog extends StatelessWidget {
|
|||||||
if (state.errorMessage.isNotEmpty)
|
if (state.errorMessage.isNotEmpty)
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(top: 8.0),
|
padding: const EdgeInsets.only(top: 8.0),
|
||||||
child: Text(
|
child: Text(state.errorMessage,
|
||||||
state.errorMessage,
|
style: Theme.of(context)
|
||||||
style: const TextStyle(
|
.textTheme
|
||||||
|
.bodySmall
|
||||||
|
?.copyWith(
|
||||||
color: ColorsManager.warningRed,
|
color: ColorsManager.warningRed,
|
||||||
fontSize: 12,
|
)),
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
Row(
|
Row(
|
||||||
@ -193,7 +196,9 @@ class CreateSubSpaceDialog extends StatelessWidget {
|
|||||||
const SizedBox(width: 10),
|
const SizedBox(width: 10),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: DefaultButton(
|
child: DefaultButton(
|
||||||
onPressed: () async {
|
onPressed: (state.errorMessage.isNotEmpty)
|
||||||
|
? null
|
||||||
|
: () async {
|
||||||
final subSpaces = context
|
final subSpaces = context
|
||||||
.read<SubSpaceBloc>()
|
.read<SubSpaceBloc>()
|
||||||
.state
|
.state
|
||||||
@ -203,7 +208,9 @@ class CreateSubSpaceDialog extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
backgroundColor: ColorsManager.secondaryColor,
|
backgroundColor: ColorsManager.secondaryColor,
|
||||||
borderRadius: 10,
|
borderRadius: 10,
|
||||||
foregroundColor: ColorsManager.whiteColors,
|
foregroundColor: state.errorMessage.isNotEmpty
|
||||||
|
? ColorsManager.whiteColorsWithOpacity
|
||||||
|
: ColorsManager.whiteColors,
|
||||||
child: const Text('OK'),
|
child: const Text('OK'),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -94,12 +94,13 @@ class CreateSubSpaceModelDialog extends StatelessWidget {
|
|||||||
duplicateIndices.indexOf(index) != 0;
|
duplicateIndices.indexOf(index) != 0;
|
||||||
|
|
||||||
return Chip(
|
return Chip(
|
||||||
label: Text(
|
label: Text(subSpace.subspaceName,
|
||||||
subSpace.subspaceName,
|
style: Theme.of(context)
|
||||||
style: const TextStyle(
|
.textTheme
|
||||||
|
.bodySmall
|
||||||
|
?.copyWith(
|
||||||
color: ColorsManager.spaceColor,
|
color: ColorsManager.spaceColor,
|
||||||
),
|
)),
|
||||||
),
|
|
||||||
backgroundColor: ColorsManager.whiteColors,
|
backgroundColor: ColorsManager.whiteColors,
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.circular(10),
|
borderRadius: BorderRadius.circular(10),
|
||||||
@ -141,9 +142,12 @@ class CreateSubSpaceModelDialog extends StatelessWidget {
|
|||||||
hintText: state.subSpaces.isEmpty
|
hintText: state.subSpaces.isEmpty
|
||||||
? 'Please enter the name'
|
? 'Please enter the name'
|
||||||
: null,
|
: null,
|
||||||
hintStyle: const TextStyle(
|
hintStyle: Theme.of(context)
|
||||||
color: ColorsManager.lightGrayColor),
|
.textTheme
|
||||||
),
|
.bodySmall!
|
||||||
|
.copyWith(
|
||||||
|
color: ColorsManager
|
||||||
|
.lightGrayColor)),
|
||||||
onSubmitted: (value) {
|
onSubmitted: (value) {
|
||||||
if (value.trim().isNotEmpty) {
|
if (value.trim().isNotEmpty) {
|
||||||
context.read<SubSpaceModelBloc>().add(
|
context.read<SubSpaceModelBloc>().add(
|
||||||
@ -154,9 +158,11 @@ class CreateSubSpaceModelDialog extends StatelessWidget {
|
|||||||
textController.clear();
|
textController.clear();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
style: const TextStyle(
|
style: Theme.of(context)
|
||||||
color: ColorsManager.blackColor),
|
.textTheme
|
||||||
),
|
.bodyMedium
|
||||||
|
?.copyWith(
|
||||||
|
color: ColorsManager.blackColor)),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -164,13 +170,13 @@ class CreateSubSpaceModelDialog extends StatelessWidget {
|
|||||||
if (state.errorMessage.isNotEmpty)
|
if (state.errorMessage.isNotEmpty)
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(bottom: 16.0),
|
padding: const EdgeInsets.only(bottom: 16.0),
|
||||||
child: Text(
|
child: Text(state.errorMessage,
|
||||||
state.errorMessage,
|
style: Theme.of(context)
|
||||||
style: const TextStyle(
|
.textTheme
|
||||||
|
.bodySmall
|
||||||
|
?.copyWith(
|
||||||
color: ColorsManager.red,
|
color: ColorsManager.red,
|
||||||
fontSize: 12,
|
)),
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
Row(
|
Row(
|
||||||
|
@ -97,7 +97,10 @@ class SpaceModelPage extends StatelessWidget {
|
|||||||
return Center(
|
return Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
'Error: ${state.message}',
|
'Error: ${state.message}',
|
||||||
style: const TextStyle(color: ColorsManager.warningRed),
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.bodySmall
|
||||||
|
?.copyWith(color: ColorsManager.warningRed),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -109,14 +112,14 @@ class SpaceModelPage extends StatelessWidget {
|
|||||||
double _calculateChildAspectRatio(BuildContext context) {
|
double _calculateChildAspectRatio(BuildContext context) {
|
||||||
double screenWidth = MediaQuery.of(context).size.width;
|
double screenWidth = MediaQuery.of(context).size.width;
|
||||||
if (screenWidth > 1600) {
|
if (screenWidth > 1600) {
|
||||||
return 2;
|
return 1.5; // Decrease to make cards taller
|
||||||
}
|
}
|
||||||
if (screenWidth > 1200) {
|
if (screenWidth > 1200) {
|
||||||
return 3;
|
return 2.0;
|
||||||
} else if (screenWidth > 800) {
|
} else if (screenWidth > 800) {
|
||||||
return 3.5;
|
return 2.5;
|
||||||
} else {
|
} else {
|
||||||
return 4.0;
|
return 3.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,7 +167,8 @@ class CreateSpaceModelDialog extends StatelessWidget {
|
|||||||
onPressed: ((state.errorMessage != null &&
|
onPressed: ((state.errorMessage != null &&
|
||||||
state.errorMessage != '') ||
|
state.errorMessage != '') ||
|
||||||
!isNameValid)
|
!isNameValid)
|
||||||
? () {
|
? null
|
||||||
|
: () {
|
||||||
final updatedSpaceTemplate =
|
final updatedSpaceTemplate =
|
||||||
updatedSpaceModel.copyWith(
|
updatedSpaceModel.copyWith(
|
||||||
modelName:
|
modelName:
|
||||||
@ -240,8 +241,7 @@ class CreateSpaceModelDialog extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
: null,
|
|
||||||
backgroundColor: ColorsManager.secondaryColor,
|
backgroundColor: ColorsManager.secondaryColor,
|
||||||
borderRadius: 10,
|
borderRadius: 10,
|
||||||
foregroundColor: ((state.errorMessage != null &&
|
foregroundColor: ((state.errorMessage != null &&
|
||||||
|
@ -29,7 +29,7 @@ class DynamicRoomWidget extends StatelessWidget {
|
|||||||
final TextPainter textPainter = TextPainter(
|
final TextPainter textPainter = TextPainter(
|
||||||
text: TextSpan(
|
text: TextSpan(
|
||||||
text: subspace.subspaceName,
|
text: subspace.subspaceName,
|
||||||
style: const TextStyle(fontSize: 16),
|
style: Theme.of(context).textTheme.bodyMedium
|
||||||
),
|
),
|
||||||
textDirection: TextDirection.ltr,
|
textDirection: TextDirection.ltr,
|
||||||
)..layout();
|
)..layout();
|
||||||
|
@ -31,6 +31,9 @@ class SpaceModelCardWidget extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return LayoutBuilder(
|
||||||
|
builder: (context, constraints) {
|
||||||
|
bool showOnlyName = constraints.maxWidth < 250;
|
||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
@ -57,6 +60,7 @@ class SpaceModelCardWidget extends StatelessWidget {
|
|||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
),
|
),
|
||||||
|
if (!showOnlyName) ...[
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Row(
|
child: Row(
|
||||||
@ -80,7 +84,8 @@ class SpaceModelCardWidget extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (productTagCount.isNotEmpty && model.subspaceModels != null)
|
if (productTagCount.isNotEmpty &&
|
||||||
|
model.subspaceModels != null)
|
||||||
Container(
|
Container(
|
||||||
width: 1.0,
|
width: 1.0,
|
||||||
color: ColorsManager.softGray,
|
color: ColorsManager.softGray,
|
||||||
@ -105,8 +110,11 @@ class SpaceModelCardWidget extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
]
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -105,6 +105,7 @@ class _SubspaceModelCreateState extends State<SubspaceModelCreate> {
|
|||||||
isEdit: true,
|
isEdit: true,
|
||||||
dialogTitle: dialogTitle,
|
dialogTitle: dialogTitle,
|
||||||
existingSubSpaces: _subspaces,
|
existingSubSpaces: _subspaces,
|
||||||
|
|
||||||
onUpdate: (subspaceModels) {
|
onUpdate: (subspaceModels) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_subspaces = subspaceModels;
|
_subspaces = subspaceModels;
|
||||||
|
@ -4,7 +4,9 @@ import 'package:syncrow_web/pages/spaces_management/all_spaces/model/create_subs
|
|||||||
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_response_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_response_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/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/tag_body_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/space_model/models/tag_body_model.dart';
|
||||||
|
import 'package:syncrow_web/pages/spaces_management/space_model/models/tag_update_model.dart';
|
||||||
import 'package:syncrow_web/services/api/http_service.dart';
|
import 'package:syncrow_web/services/api/http_service.dart';
|
||||||
import 'package:syncrow_web/utils/constants/api_const.dart';
|
import 'package:syncrow_web/utils/constants/api_const.dart';
|
||||||
import 'package:syncrow_web/utils/constants/temp_const.dart';
|
import 'package:syncrow_web/utils/constants/temp_const.dart';
|
||||||
@ -154,7 +156,7 @@ class CommunitySpaceManagementApi {
|
|||||||
.replaceAll('{spaceId}', spaceId)
|
.replaceAll('{spaceId}', spaceId)
|
||||||
.replaceAll('{projectId}', TempConst.projectId),
|
.replaceAll('{projectId}', TempConst.projectId),
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
return SpaceModel.fromJson(json);
|
return SpaceModel.fromJson(json['data']);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
return response;
|
return response;
|
||||||
@ -210,7 +212,7 @@ class CommunitySpaceManagementApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<SpaceModel?> updateSpace({
|
Future<bool> updateSpace({
|
||||||
required String communityId,
|
required String communityId,
|
||||||
required spaceId,
|
required spaceId,
|
||||||
required String name,
|
required String name,
|
||||||
@ -219,6 +221,8 @@ class CommunitySpaceManagementApi {
|
|||||||
String? direction,
|
String? direction,
|
||||||
bool isPrivate = false,
|
bool isPrivate = false,
|
||||||
required Offset position,
|
required Offset position,
|
||||||
|
List<TagModelUpdate>? tags,
|
||||||
|
List<UpdateSubspaceTemplateModel>? subspaces,
|
||||||
}) async {
|
}) async {
|
||||||
try {
|
try {
|
||||||
final body = {
|
final body = {
|
||||||
@ -228,6 +232,8 @@ class CommunitySpaceManagementApi {
|
|||||||
'y': position.dy,
|
'y': position.dy,
|
||||||
'direction': direction,
|
'direction': direction,
|
||||||
'icon': icon,
|
'icon': icon,
|
||||||
|
'subspace': subspaces,
|
||||||
|
'tags': tags,
|
||||||
};
|
};
|
||||||
if (parentId != null) {
|
if (parentId != null) {
|
||||||
body['parentUuid'] = parentId;
|
body['parentUuid'] = parentId;
|
||||||
@ -240,13 +246,13 @@ class CommunitySpaceManagementApi {
|
|||||||
.replaceAll('{projectId}', TempConst.projectId),
|
.replaceAll('{projectId}', TempConst.projectId),
|
||||||
body: body,
|
body: body,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
return SpaceModel.fromJson(json['data']);
|
return json['success'] ?? false;
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
return response;
|
return response;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
debugPrint('Error creating space: $e');
|
debugPrint('Error updating space: $e');
|
||||||
return null;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user