mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-10 07:07:19 +00:00
fixed the edit flow for space model
This commit is contained in:
@ -48,6 +48,7 @@ class DeviceTypeTileWidget extends StatelessWidget {
|
||||
DeviceNameWidget(name: product.name),
|
||||
const SizedBox(height: 4),
|
||||
CounterWidget(
|
||||
isCreate: false,
|
||||
initialCount: selectedProduct.count,
|
||||
onCountChanged: (newCount) {
|
||||
context.read<AddDeviceTypeBloc>().add(
|
||||
|
@ -27,8 +27,7 @@ class SpaceManagementLoaded extends SpaceManagementState {
|
||||
required this.products,
|
||||
this.selectedCommunity,
|
||||
this.selectedSpace,
|
||||
this.spaceModels
|
||||
});
|
||||
this.spaceModels});
|
||||
}
|
||||
|
||||
class SpaceModelManagenetLoaded extends SpaceManagementState {
|
||||
@ -40,12 +39,8 @@ class BlankState extends SpaceManagementState {
|
||||
final List<ProductModel> products;
|
||||
List<SpaceTemplateModel>? spaceModels;
|
||||
|
||||
|
||||
BlankState({
|
||||
required this.communities,
|
||||
required this.products,
|
||||
this.spaceModels
|
||||
});
|
||||
BlankState(
|
||||
{required this.communities, required this.products, this.spaceModels});
|
||||
}
|
||||
|
||||
class SpaceCreationSuccess extends SpaceManagementState {
|
||||
@ -67,7 +62,7 @@ class SpaceManagementError extends SpaceManagementState {
|
||||
}
|
||||
|
||||
class SpaceModelLoaded extends SpaceManagementState {
|
||||
final List<SpaceTemplateModel> spaceModels;
|
||||
List<SpaceTemplateModel> spaceModels;
|
||||
final List<ProductModel> products;
|
||||
final List<CommunityModel> communities;
|
||||
|
||||
|
@ -137,6 +137,7 @@ class _AddDeviceWidgetState extends State<AddDeviceWidget> {
|
||||
_buildDeviceName(product, size),
|
||||
const SizedBox(height: 4),
|
||||
CounterWidget(
|
||||
isCreate: false,
|
||||
initialCount: selectedProduct.count,
|
||||
onCountChanged: (newCount) {
|
||||
setState(() {
|
||||
|
@ -4,12 +4,14 @@ import 'package:syncrow_web/utils/color_manager.dart';
|
||||
class CounterWidget extends StatefulWidget {
|
||||
final int initialCount;
|
||||
final ValueChanged<int> onCountChanged;
|
||||
final bool isCreate;
|
||||
|
||||
const CounterWidget({
|
||||
Key? key,
|
||||
const CounterWidget(
|
||||
{Key? key,
|
||||
this.initialCount = 0,
|
||||
required this.onCountChanged,
|
||||
}) : super(key: key);
|
||||
required this.isCreate})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
State<CounterWidget> createState() => _CounterWidgetState();
|
||||
@ -53,25 +55,26 @@ class _CounterWidgetState extends State<CounterWidget> {
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
_buildCounterButton(Icons.remove, _decrementCounter),
|
||||
_buildCounterButton(Icons.remove, _decrementCounter,!widget.isCreate ),
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
'$_counter',
|
||||
style: theme.textTheme.bodyLarge?.copyWith(color: ColorsManager.spaceColor),
|
||||
style: theme.textTheme.bodyLarge
|
||||
?.copyWith(color: ColorsManager.spaceColor),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
_buildCounterButton(Icons.add, _incrementCounter),
|
||||
_buildCounterButton(Icons.add, _incrementCounter, false),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildCounterButton(IconData icon, VoidCallback onPressed) {
|
||||
Widget _buildCounterButton(IconData icon, VoidCallback onPressed, bool isDisabled) {
|
||||
return GestureDetector(
|
||||
onTap: onPressed,
|
||||
onTap: isDisabled? null: onPressed,
|
||||
child: Icon(
|
||||
icon,
|
||||
color: ColorsManager.spaceColor,
|
||||
color: isDisabled? ColorsManager.spaceColor.withOpacity(0.3): ColorsManager.spaceColor,
|
||||
size: 18,
|
||||
),
|
||||
);
|
||||
|
@ -19,6 +19,8 @@ import 'package:syncrow_web/utils/color_manager.dart';
|
||||
class AssignTagModelsDialog extends StatelessWidget {
|
||||
final List<ProductModel>? products;
|
||||
final List<SubspaceTemplateModel>? subspaces;
|
||||
final SpaceTemplateModel? spaceModel;
|
||||
|
||||
final List<TagModel> initialTags;
|
||||
final ValueChanged<List<TagModel>>? onTagsAssigned;
|
||||
final List<SelectedProduct> addedProducts;
|
||||
@ -39,7 +41,8 @@ class AssignTagModelsDialog extends StatelessWidget {
|
||||
required this.spaceName,
|
||||
required this.title,
|
||||
this.pageContext,
|
||||
this.otherSpaceModels})
|
||||
this.otherSpaceModels,
|
||||
this.spaceModel})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
@ -210,7 +213,7 @@ class AssignTagModelsDialog extends StatelessWidget {
|
||||
child: DialogDropdown(
|
||||
items: locations,
|
||||
selectedValue:
|
||||
tag.location ?? 'None',
|
||||
tag.location ?? 'Main Space',
|
||||
onSelected: (value) {
|
||||
context
|
||||
.read<
|
||||
@ -284,13 +287,20 @@ class AssignTagModelsDialog extends StatelessWidget {
|
||||
products: products,
|
||||
subspaces: subspaces,
|
||||
isCreate: false,
|
||||
initialSelectedProducts: addedProducts,
|
||||
initialSelectedProducts:
|
||||
addedProducts,
|
||||
allTags: allTags,
|
||||
spaceName: spaceName,
|
||||
otherSpaceModels: otherSpaceModels,
|
||||
spaceTagModels: state.tags,
|
||||
pageContext: pageContext,
|
||||
),
|
||||
spaceModel: SpaceTemplateModel(
|
||||
modelName: spaceName,
|
||||
tags: state.tags,
|
||||
uuid: spaceModel?.uuid,
|
||||
internalId:
|
||||
spaceModel?.internalId,
|
||||
subspaceModels: subspaces)),
|
||||
);
|
||||
}
|
||||
},
|
||||
@ -348,6 +358,9 @@ class AssignTagModelsDialog extends StatelessWidget {
|
||||
spaceModel: SpaceTemplateModel(
|
||||
modelName: spaceName,
|
||||
tags: state.tags,
|
||||
uuid: spaceModel?.uuid,
|
||||
internalId:
|
||||
spaceModel?.internalId,
|
||||
subspaceModels: subspaces),
|
||||
);
|
||||
},
|
||||
|
@ -186,8 +186,7 @@ class CreateSubSpaceModelDialog extends StatelessWidget {
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: DefaultButton(
|
||||
onPressed: (state.subSpaces.isEmpty ||
|
||||
state.errorMessage.isNotEmpty)
|
||||
onPressed: (state.errorMessage.isNotEmpty)
|
||||
? null
|
||||
: () async {
|
||||
final subSpaces = context
|
||||
@ -201,8 +200,7 @@ class CreateSubSpaceModelDialog extends StatelessWidget {
|
||||
},
|
||||
backgroundColor: ColorsManager.secondaryColor,
|
||||
borderRadius: 10,
|
||||
foregroundColor: state.subSpaces.isEmpty ||
|
||||
state.errorMessage.isNotEmpty
|
||||
foregroundColor: state.errorMessage.isNotEmpty
|
||||
? ColorsManager.whiteColorsWithOpacity
|
||||
: ColorsManager.whiteColors,
|
||||
child: const Text('OK'),
|
||||
|
@ -37,7 +37,8 @@ class TagHelper {
|
||||
final Map<ProductModel, int> groupedTags = {};
|
||||
for (var tag in tags) {
|
||||
if (tag.product != null) {
|
||||
groupedTags[tag.product!] = (groupedTags[tag.product!] ?? 0) + 1;
|
||||
final product = tag.product!;
|
||||
groupedTags[product] = (groupedTags[product] ?? 0) + 1;
|
||||
}
|
||||
}
|
||||
return groupedTags;
|
||||
|
@ -1,12 +1,12 @@
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/space_model/bloc/create_space_model_event.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/space_model/bloc/create_space_model_state.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/space_model/models/create_space_template_body_model.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/space_model/models/space_template_model.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/space_model/models/tag_model.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/space_model/models/tag_update_model.dart';
|
||||
import 'package:syncrow_web/services/space_model_mang_api.dart';
|
||||
import 'package:syncrow_web/utils/constants/action_enum.dart';
|
||||
|
||||
class CreateSpaceModelBloc
|
||||
extends Bloc<CreateSpaceModelEvent, CreateSpaceModelState> {
|
||||
@ -193,5 +193,229 @@ class CreateSpaceModelBloc
|
||||
emit(CreateSpaceModelError("Space template not initialized"));
|
||||
}
|
||||
});
|
||||
|
||||
on<ModifySpaceTemplate>((event, emit) async {
|
||||
try {
|
||||
final prevSpaceModel = event.spaceTemplate;
|
||||
final newSpaceModel = event.updatedSpaceTemplate;
|
||||
String? spaceModelName;
|
||||
if (prevSpaceModel.modelName != newSpaceModel.modelName) {
|
||||
spaceModelName = newSpaceModel.modelName;
|
||||
}
|
||||
List<TagModelUpdate> tagUpdates = [];
|
||||
final List<UpdateSubspaceTemplateModel> subspaceUpdates = [];
|
||||
|
||||
tagUpdates = processTagUpdates(prevSpaceModel.tags, newSpaceModel.tags);
|
||||
|
||||
if (prevSpaceModel.subspaceModels != null) {
|
||||
for (var prevSubspace in prevSpaceModel.subspaceModels!) {
|
||||
if (newSpaceModel.subspaceModels == null) {
|
||||
subspaceUpdates.add(UpdateSubspaceTemplateModel(
|
||||
action: Action.delete,
|
||||
uuid: prevSubspace.uuid,
|
||||
));
|
||||
continue;
|
||||
}
|
||||
|
||||
final subspaceExistsInNew = newSpaceModel.subspaceModels!
|
||||
.any((newSubspace) => newSubspace.uuid == prevSubspace.uuid);
|
||||
if (!subspaceExistsInNew) {
|
||||
subspaceUpdates.add(UpdateSubspaceTemplateModel(
|
||||
action: Action.delete,
|
||||
uuid: prevSubspace.uuid,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (newSpaceModel.subspaceModels != null) {
|
||||
for (var newSubspaceModel in newSpaceModel.subspaceModels!) {
|
||||
if (newSubspaceModel.uuid == null ||
|
||||
newSubspaceModel.uuid!.isEmpty) {
|
||||
final List<TagModelUpdate> tagUpdatesInSubspace = [];
|
||||
|
||||
if (newSubspaceModel.tags != null) {
|
||||
for (var tag in newSubspaceModel.tags!) {
|
||||
tagUpdatesInSubspace.add(TagModelUpdate(
|
||||
action: Action.add,
|
||||
uuid: tag.uuid,
|
||||
tag: tag.tag,
|
||||
productUuid: tag.product?.uuid,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
subspaceUpdates.add(UpdateSubspaceTemplateModel(
|
||||
action: Action.add,
|
||||
subspaceName: newSubspaceModel.subspaceName,
|
||||
tags: tagUpdatesInSubspace,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (newSpaceModel.subspaceModels != null &&
|
||||
prevSpaceModel.subspaceModels != null) {
|
||||
final prevSubspaceMap = {
|
||||
for (var subspace in prevSpaceModel.subspaceModels!)
|
||||
subspace.uuid: subspace
|
||||
};
|
||||
|
||||
for (var newSubspace in newSpaceModel.subspaceModels!) {
|
||||
if (newSubspace.uuid != null &&
|
||||
prevSubspaceMap.containsKey(newSubspace.uuid)) {
|
||||
final prevSubspace = prevSubspaceMap[newSubspace.uuid]!;
|
||||
|
||||
// Check if modelName has changed
|
||||
if (newSubspace.subspaceName != prevSubspace.subspaceName) {
|
||||
subspaceUpdates.add(UpdateSubspaceTemplateModel(
|
||||
action: Action.update,
|
||||
uuid: newSubspace.uuid,
|
||||
subspaceName: newSubspace.subspaceName,
|
||||
));
|
||||
}
|
||||
|
||||
// Compare tags within the subspace
|
||||
final List<TagModelUpdate> tagUpdatesInSubspace = [];
|
||||
if (prevSubspace.tags != null && newSubspace.tags != null) {
|
||||
final prevTagMap = {
|
||||
for (var tag in prevSubspace.tags!) tag.uuid: tag
|
||||
};
|
||||
|
||||
// Check for deleted tags
|
||||
for (var prevTag in prevSubspace.tags!) {
|
||||
if (!newSubspace.tags!
|
||||
.any((newTag) => newTag.uuid == prevTag.uuid)) {
|
||||
tagUpdatesInSubspace.add(TagModelUpdate(
|
||||
action: Action.delete,
|
||||
uuid: prevTag.uuid,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// Check for added tags, including those without a UUID
|
||||
for (var newTag in newSubspace.tags!) {
|
||||
if (newTag.uuid == null || newTag.uuid!.isEmpty) {
|
||||
// Add new tag without UUID
|
||||
tagUpdatesInSubspace.add(TagModelUpdate(
|
||||
action: Action.add,
|
||||
uuid: null, // or generate a new UUID if required
|
||||
tag: newTag.tag,
|
||||
productUuid: newTag.product?.uuid,
|
||||
));
|
||||
} else if (!prevSubspace.tags!
|
||||
.any((prevTag) => prevTag.uuid == newTag.uuid)) {
|
||||
// Add new tag with UUID
|
||||
tagUpdatesInSubspace.add(TagModelUpdate(
|
||||
action: Action.add,
|
||||
uuid: newTag.uuid,
|
||||
tag: newTag.tag,
|
||||
productUuid: newTag.product?.uuid,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// Check for updated tags
|
||||
for (var prevTag in prevSubspace.tags!) {
|
||||
final newTag = newSubspace.tags!.cast<TagModel?>().firstWhere(
|
||||
(tag) => tag?.uuid == prevTag.uuid,
|
||||
orElse: () => null,
|
||||
);
|
||||
if (newTag != null && newTag.tag != prevTag.tag) {
|
||||
tagUpdatesInSubspace.add(TagModelUpdate(
|
||||
action: Action.update,
|
||||
uuid: newTag.uuid,
|
||||
tag: newTag.tag,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add the subspace with updated tags if necessary
|
||||
if (tagUpdatesInSubspace.isNotEmpty) {
|
||||
subspaceUpdates.add(UpdateSubspaceTemplateModel(
|
||||
action: Action.update,
|
||||
uuid: newSubspace.uuid,
|
||||
subspaceName: newSubspace.subspaceName,
|
||||
tags: tagUpdatesInSubspace,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final spaceModelBody = CreateSpaceTemplateBodyModel(
|
||||
modelName: spaceModelName,
|
||||
tags: tagUpdates,
|
||||
subspaceModels: subspaceUpdates);
|
||||
|
||||
final res = await _api.updateSpaceModel(
|
||||
spaceModelBody, prevSpaceModel.uuid ?? '');
|
||||
|
||||
if (res != null) {
|
||||
emit(CreateSpaceModelLoaded(newSpaceModel));
|
||||
if (event.onUpdate != null) {
|
||||
event.onUpdate!(event.updatedSpaceTemplate);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
emit(CreateSpaceModelError('Error creating space model'));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
List<TagModelUpdate> processTagUpdates(
|
||||
List<TagModel>? prevTags,
|
||||
List<TagModel>? newTags,
|
||||
) {
|
||||
final List<TagModelUpdate> tagUpdates = [];
|
||||
final processedTags = <String?>{};
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Case 2: Tags added
|
||||
if (newTags != null) {
|
||||
for (var newTag in newTags!) {
|
||||
// Tag without UUID
|
||||
if ((newTag.uuid == null || newTag.uuid!.isEmpty) &&
|
||||
!processedTags.contains(newTag.tag)) {
|
||||
tagUpdates.add(TagModelUpdate(
|
||||
action: Action.add,
|
||||
tag: newTag.tag,
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,6 @@ class CreateSpaceTemplate extends CreateSpaceModelEvent {
|
||||
final SpaceTemplateModel spaceTemplate;
|
||||
final Function(SpaceTemplateModel)? onCreate;
|
||||
|
||||
|
||||
const CreateSpaceTemplate({
|
||||
required this.spaceTemplate,
|
||||
this.onCreate,
|
||||
@ -54,9 +53,19 @@ class AddTagsToSpaceTemplate extends CreateSpaceModelEvent {
|
||||
AddTagsToSpaceTemplate(this.tags);
|
||||
}
|
||||
|
||||
|
||||
class ValidateSpaceTemplateName extends CreateSpaceModelEvent {
|
||||
final String name;
|
||||
|
||||
ValidateSpaceTemplateName({required this.name});
|
||||
}
|
||||
|
||||
class ModifySpaceTemplate extends CreateSpaceModelEvent {
|
||||
final SpaceTemplateModel spaceTemplate;
|
||||
final SpaceTemplateModel updatedSpaceTemplate;
|
||||
final Function(SpaceTemplateModel)? onUpdate;
|
||||
|
||||
ModifySpaceTemplate(
|
||||
{required this.spaceTemplate,
|
||||
required this.updatedSpaceTemplate,
|
||||
this.onUpdate});
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ class SpaceModelBloc extends Bloc<SpaceModelEvent, SpaceModelState> {
|
||||
required List<SpaceTemplateModel> initialSpaceModels,
|
||||
}) : super(SpaceModelLoaded(spaceModels: initialSpaceModels)) {
|
||||
on<CreateSpaceModel>(_onCreateSpaceModel);
|
||||
on<UpdateSpaceModel>(_onUpdateSpaceModel);
|
||||
}
|
||||
|
||||
Future<void> _onCreateSpaceModel(
|
||||
@ -33,4 +34,23 @@ class SpaceModelBloc extends Bloc<SpaceModelEvent, SpaceModelState> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onUpdateSpaceModel(
|
||||
UpdateSpaceModel event, Emitter<SpaceModelState> emit) async {
|
||||
final currentState = state;
|
||||
if (currentState is SpaceModelLoaded) {
|
||||
try {
|
||||
final newSpaceModel =
|
||||
await api.getSpaceModel(event.spaceModelUuid ?? '');
|
||||
if (newSpaceModel != null) {
|
||||
final updatedSpaceModels = currentState.spaceModels.map((model) {
|
||||
return model.uuid == event.spaceModelUuid ? newSpaceModel : model;
|
||||
}).toList();
|
||||
emit(SpaceModelLoaded(spaceModels: updatedSpaceModels));
|
||||
}
|
||||
} catch (e) {
|
||||
emit(SpaceModelError(message: e.toString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,3 +16,21 @@ class CreateSpaceModel extends SpaceModelEvent {
|
||||
@override
|
||||
List<Object?> get props => [newSpaceModel];
|
||||
}
|
||||
|
||||
class GetSpaceModel extends SpaceModelEvent {
|
||||
final String spaceModelUuid;
|
||||
|
||||
GetSpaceModel({required this.spaceModelUuid});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [spaceModelUuid];
|
||||
}
|
||||
|
||||
class UpdateSpaceModel extends SpaceModelEvent {
|
||||
final String spaceModelUuid;
|
||||
|
||||
UpdateSpaceModel({required this.spaceModelUuid});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [spaceModelUuid];
|
||||
}
|
||||
|
@ -30,12 +30,12 @@ class CreateSubspaceTemplateModel {
|
||||
}
|
||||
|
||||
class CreateSpaceTemplateBodyModel {
|
||||
final String modelName;
|
||||
final String? modelName;
|
||||
final List<dynamic>? tags;
|
||||
final List<dynamic>? subspaceModels;
|
||||
|
||||
CreateSpaceTemplateBodyModel({
|
||||
required this.modelName,
|
||||
this.modelName,
|
||||
this.tags,
|
||||
this.subspaceModels,
|
||||
});
|
||||
|
@ -2,6 +2,7 @@ import 'package:equatable/equatable.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/product_model.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/space_model/models/subspace_template_model.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/space_model/models/tag_model.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/space_model/models/tag_update_model.dart';
|
||||
import 'package:syncrow_web/utils/constants/action_enum.dart';
|
||||
import 'package:uuid/uuid.dart';
|
||||
|
||||
@ -70,14 +71,14 @@ class SpaceTemplateModel extends Equatable {
|
||||
}
|
||||
|
||||
class UpdateSubspaceTemplateModel {
|
||||
final String uuid;
|
||||
final String? uuid;
|
||||
final Action action;
|
||||
final String? subspaceName;
|
||||
final List<UpdateTagModel>? tags;
|
||||
final List<TagModelUpdate>? tags;
|
||||
|
||||
UpdateSubspaceTemplateModel({
|
||||
required this.action,
|
||||
required this.uuid,
|
||||
this.uuid,
|
||||
this.subspaceName,
|
||||
this.tags,
|
||||
});
|
||||
@ -88,7 +89,7 @@ class UpdateSubspaceTemplateModel {
|
||||
uuid: json['uuid'] ?? '',
|
||||
subspaceName: json['subspaceName'] ?? '',
|
||||
tags: (json['tags'] as List)
|
||||
.map((item) => UpdateTagModel.fromJson(item))
|
||||
.map((item) => TagModelUpdate.fromJson(item))
|
||||
.toList(),
|
||||
);
|
||||
}
|
||||
@ -103,44 +104,6 @@ class UpdateSubspaceTemplateModel {
|
||||
}
|
||||
}
|
||||
|
||||
class UpdateTagModel {
|
||||
final Action action;
|
||||
final String? uuid;
|
||||
final String tag;
|
||||
final bool disabled;
|
||||
final ProductModel? product;
|
||||
|
||||
UpdateTagModel({
|
||||
required this.action,
|
||||
this.uuid,
|
||||
required this.tag,
|
||||
required this.disabled,
|
||||
this.product,
|
||||
});
|
||||
|
||||
factory UpdateTagModel.fromJson(Map<String, dynamic> json) {
|
||||
return UpdateTagModel(
|
||||
action: ActionExtension.fromValue(json['action']),
|
||||
uuid: json['uuid'] ?? '',
|
||||
tag: json['tag'] ?? '',
|
||||
disabled: json['disabled'] ?? false,
|
||||
product: json['product'] != null
|
||||
? ProductModel.fromMap(json['product'])
|
||||
: null,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'action': action.value,
|
||||
'uuid': uuid,
|
||||
'tag': tag,
|
||||
'disabled': disabled,
|
||||
'product': product?.toMap(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
extension SpaceTemplateExtensions on SpaceTemplateModel {
|
||||
List<String> listAllTagValues() {
|
||||
final List<String> tagValues = [];
|
||||
|
@ -0,0 +1,34 @@
|
||||
import 'package:syncrow_web/utils/constants/action_enum.dart';
|
||||
|
||||
class TagModelUpdate {
|
||||
final Action action;
|
||||
final String? uuid;
|
||||
final String? tag;
|
||||
final String? productUuid;
|
||||
|
||||
TagModelUpdate({
|
||||
required this.action,
|
||||
this.uuid,
|
||||
this.tag,
|
||||
this.productUuid,
|
||||
});
|
||||
|
||||
factory TagModelUpdate.fromJson(Map<String, dynamic> json) {
|
||||
return TagModelUpdate(
|
||||
action: json['action'],
|
||||
uuid: json['uuid'],
|
||||
tag: json['tag'],
|
||||
productUuid: json['productUuid'],
|
||||
);
|
||||
}
|
||||
|
||||
// Method to convert an instance to JSON
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'action': action.value,
|
||||
'uuid': uuid, // Nullable field
|
||||
'tag': tag,
|
||||
'productUuid': productUuid,
|
||||
};
|
||||
}
|
||||
}
|
@ -65,7 +65,6 @@ class SpaceModelPage extends StatelessWidget {
|
||||
final model = spaceModels[index];
|
||||
final otherModel = List<String>.from(allSpaceModelNames);
|
||||
otherModel.remove(model.modelName);
|
||||
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
showDialog(
|
||||
@ -76,6 +75,7 @@ class SpaceModelPage extends StatelessWidget {
|
||||
allTags: allTagValues,
|
||||
spaceModel: model,
|
||||
otherSpaceModels: otherModel,
|
||||
pageContext: context,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
@ -6,6 +6,7 @@ import 'package:syncrow_web/pages/spaces_management/all_spaces/model/product_mod
|
||||
import 'package:syncrow_web/pages/spaces_management/space_model/bloc/create_space_model_bloc.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/space_model/bloc/create_space_model_event.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/space_model/bloc/create_space_model_state.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/space_model/bloc/space_model_state.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/space_model/models/space_template_model.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/space_model/widgets/tag_chips_display_widget.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/space_model/bloc/space_model_bloc.dart';
|
||||
@ -58,7 +59,9 @@ class CreateSpaceModelDialog extends StatelessWidget {
|
||||
}
|
||||
|
||||
spaceNameController.addListener(() {
|
||||
bloc.add(UpdateSpaceTemplateName(name: spaceNameController.text,allModels: otherSpaceModels ??[]));
|
||||
bloc.add(UpdateSpaceTemplateName(
|
||||
name: spaceNameController.text,
|
||||
allModels: otherSpaceModels ?? []));
|
||||
});
|
||||
|
||||
return bloc;
|
||||
@ -153,15 +156,12 @@ class CreateSpaceModelDialog extends StatelessWidget {
|
||||
onPressed: state.errorMessage == null ||
|
||||
isNameValid
|
||||
? () {
|
||||
if (updatedSpaceModel.uuid == null) {
|
||||
final updatedSpaceTemplate =
|
||||
updatedSpaceModel.copyWith(
|
||||
modelName:
|
||||
spaceNameController.text.trim(),
|
||||
);
|
||||
if (updatedSpaceTemplate.uuid !=
|
||||
null) {}
|
||||
|
||||
if (updatedSpaceModel.uuid == null) {
|
||||
context
|
||||
.read<CreateSpaceModelBloc>()
|
||||
.add(
|
||||
@ -181,6 +181,52 @@ class CreateSpaceModelDialog extends StatelessWidget {
|
||||
},
|
||||
),
|
||||
);
|
||||
} else {
|
||||
if (pageContext != null) {
|
||||
final currentState = pageContext!
|
||||
.read<SpaceModelBloc>()
|
||||
.state;
|
||||
if (currentState
|
||||
is SpaceModelLoaded) {
|
||||
final spaceModels =
|
||||
List<SpaceTemplateModel>.from(
|
||||
currentState.spaceModels);
|
||||
|
||||
final SpaceTemplateModel?
|
||||
currentSpaceModel = spaceModels
|
||||
.cast<SpaceTemplateModel?>()
|
||||
.firstWhere(
|
||||
(sm) =>
|
||||
sm?.uuid ==
|
||||
updatedSpaceModel
|
||||
.uuid,
|
||||
orElse: () => null,
|
||||
);
|
||||
if (currentSpaceModel != null) {
|
||||
context
|
||||
.read<CreateSpaceModelBloc>()
|
||||
.add(ModifySpaceTemplate(
|
||||
spaceTemplate:
|
||||
currentSpaceModel,
|
||||
updatedSpaceTemplate:
|
||||
updatedSpaceTemplate,
|
||||
onUpdate: (newModel) {
|
||||
if (pageContext !=
|
||||
null) {
|
||||
pageContext!
|
||||
.read<
|
||||
SpaceModelBloc>()
|
||||
.add(UpdateSpaceModel(
|
||||
spaceModelUuid:
|
||||
newModel.uuid ??
|
||||
''));
|
||||
}
|
||||
Navigator.of(context)
|
||||
.pop();
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
: null,
|
||||
|
@ -1,9 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:syncrow_web/utils/color_manager.dart';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:syncrow_web/utils/color_manager.dart';
|
||||
|
||||
class SubspaceChipWidget extends StatelessWidget {
|
||||
final String subspace;
|
||||
|
||||
|
@ -46,23 +46,23 @@ class SubspaceModelCreate extends StatelessWidget {
|
||||
spacing: 8.0,
|
||||
runSpacing: 8.0,
|
||||
children: [
|
||||
...subspaces.map(
|
||||
(subspace) => Chip(
|
||||
label: Text(
|
||||
...subspaces.map((subspace) => Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 8.0, vertical: 4.0),
|
||||
decoration: BoxDecoration(
|
||||
color: ColorsManager.whiteColors,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
border: Border.all(
|
||||
color: ColorsManager.transparentColor),
|
||||
),
|
||||
child: Text(
|
||||
subspace.subspaceName,
|
||||
style: const TextStyle(
|
||||
color: ColorsManager.spaceColor), // Text color
|
||||
),
|
||||
backgroundColor:
|
||||
ColorsManager.whiteColors, // Chip background color
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius:
|
||||
BorderRadius.circular(16), // Rounded chip
|
||||
side: const BorderSide(
|
||||
color: ColorsManager.spaceColor), // Border color
|
||||
),
|
||||
),
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodySmall
|
||||
?.copyWith(color: ColorsManager.spaceColor),
|
||||
),
|
||||
)),
|
||||
GestureDetector(
|
||||
onTap: () async {
|
||||
await _openDialog(context, 'Edit Sub-space');
|
||||
|
@ -98,6 +98,7 @@ class TagChipDisplay extends StatelessWidget {
|
||||
subspaces: subspaces,
|
||||
pageContext: pageContext,
|
||||
allTags: allTags,
|
||||
spaceModel: spaceModel,
|
||||
initialTags: TagHelper.generateInitialTags(
|
||||
subspaces: subspaces,
|
||||
spaceTagModels: spaceModel?.tags ?? []),
|
||||
@ -139,6 +140,7 @@ class TagChipDisplay extends StatelessWidget {
|
||||
spaceName: spaceNameController.text,
|
||||
pageContext: pageContext,
|
||||
isCreate: true,
|
||||
spaceModel: spaceModel,
|
||||
),
|
||||
);
|
||||
},
|
||||
|
@ -5,9 +5,10 @@ import 'package:syncrow_web/pages/common/buttons/default_button.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/assign_tag_models/views/assign_tag_models_dialog.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/product_model.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/selected_product_model.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/link_space_model/bloc/link_space_model_bloc.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/space_model/models/space_template_model.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/space_model/models/subspace_template_model.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/space_model/models/tag_model.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/space_model/widgets/dialog/create_space_model_dialog.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/tag_model/bloc/add_device_model_bloc.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/tag_model/bloc/add_device_model_state.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/tag_model/bloc/add_device_type_model_event.dart';
|
||||
@ -24,6 +25,7 @@ class AddDeviceTypeModelWidget extends StatelessWidget {
|
||||
final bool isCreate;
|
||||
final List<String>? otherSpaceModels;
|
||||
final BuildContext? pageContext;
|
||||
final SpaceTemplateModel? spaceModel;
|
||||
|
||||
const AddDeviceTypeModelWidget(
|
||||
{super.key,
|
||||
@ -35,7 +37,8 @@ class AddDeviceTypeModelWidget extends StatelessWidget {
|
||||
required this.spaceName,
|
||||
required this.isCreate,
|
||||
this.pageContext,
|
||||
this.otherSpaceModels});
|
||||
this.otherSpaceModels,
|
||||
this.spaceModel});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -75,6 +78,7 @@ class AddDeviceTypeModelWidget extends StatelessWidget {
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 20.0),
|
||||
child: ScrollableGridViewWidget(
|
||||
isCreate: isCreate,
|
||||
products: products,
|
||||
crossAxisCount: crossAxisCount,
|
||||
initialProductCounts: state.selectedProducts,
|
||||
@ -98,6 +102,44 @@ class AddDeviceTypeModelWidget extends StatelessWidget {
|
||||
onPressed: () async {
|
||||
if (isCreate) {
|
||||
Navigator.of(context).pop();
|
||||
await showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext dialogContext) {
|
||||
return CreateSpaceModelDialog(
|
||||
products: products,
|
||||
allTags: allTags,
|
||||
pageContext: pageContext,
|
||||
otherSpaceModels: otherSpaceModels,
|
||||
spaceModel: SpaceTemplateModel(
|
||||
modelName: spaceName,
|
||||
tags: spaceModel?.tags ?? [],
|
||||
uuid: spaceModel?.uuid,
|
||||
internalId: spaceModel?.internalId,
|
||||
subspaceModels: subspaces),
|
||||
);
|
||||
},
|
||||
);
|
||||
} else {
|
||||
final initialTags = generateInitialTags(
|
||||
spaceTagModels: spaceTagModels,
|
||||
subspaces: subspaces,
|
||||
);
|
||||
|
||||
Navigator.of(context).pop();
|
||||
await showDialog<bool>(
|
||||
context: context,
|
||||
builder: (context) => AssignTagModelsDialog(
|
||||
products: products,
|
||||
subspaces: subspaces,
|
||||
addedProducts: initialSelectedProducts ?? [],
|
||||
allTags: allTags,
|
||||
spaceName: spaceName,
|
||||
initialTags: initialTags,
|
||||
otherSpaceModels: otherSpaceModels,
|
||||
title: 'Edit Device',
|
||||
spaceModel: spaceModel,
|
||||
pageContext: pageContext,
|
||||
));
|
||||
}
|
||||
},
|
||||
),
|
||||
@ -140,6 +182,7 @@ class AddDeviceTypeModelWidget extends StatelessWidget {
|
||||
initialTags: state.initialTag,
|
||||
otherSpaceModels: otherSpaceModels,
|
||||
title: dialogTitle,
|
||||
spaceModel: spaceModel,
|
||||
pageContext: pageContext,
|
||||
),
|
||||
);
|
||||
|
@ -13,12 +13,13 @@ import 'package:syncrow_web/utils/constants/assets.dart';
|
||||
class DeviceTypeTileWidget extends StatelessWidget {
|
||||
final ProductModel product;
|
||||
final List<SelectedProduct> productCounts;
|
||||
final bool isCreate;
|
||||
|
||||
const DeviceTypeTileWidget({
|
||||
super.key,
|
||||
const DeviceTypeTileWidget(
|
||||
{super.key,
|
||||
required this.product,
|
||||
required this.productCounts,
|
||||
});
|
||||
required this.isCreate});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -48,6 +49,7 @@ class DeviceTypeTileWidget extends StatelessWidget {
|
||||
DeviceNameWidget(name: product.name),
|
||||
const SizedBox(height: 4),
|
||||
CounterWidget(
|
||||
isCreate: isCreate,
|
||||
initialCount: selectedProduct.count,
|
||||
onCountChanged: (newCount) {
|
||||
context.read<AddDeviceTypeModelBloc>().add(
|
||||
|
@ -10,12 +10,14 @@ class ScrollableGridViewWidget extends StatelessWidget {
|
||||
final List<ProductModel>? products;
|
||||
final int crossAxisCount;
|
||||
final List<SelectedProduct>? initialProductCounts;
|
||||
final bool isCreate;
|
||||
|
||||
const ScrollableGridViewWidget({
|
||||
super.key,
|
||||
required this.products,
|
||||
required this.crossAxisCount,
|
||||
this.initialProductCounts,
|
||||
required this.isCreate
|
||||
});
|
||||
|
||||
@override
|
||||
@ -47,6 +49,7 @@ class ScrollableGridViewWidget extends StatelessWidget {
|
||||
|
||||
return DeviceTypeTileWidget(
|
||||
product: product,
|
||||
isCreate: isCreate,
|
||||
productCounts: initialProductCount != null
|
||||
? [...productCounts, initialProductCount]
|
||||
: productCounts,
|
||||
|
@ -34,6 +34,20 @@ class SpaceModelManagementApi {
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
Future<String?> updateSpaceModel(
|
||||
CreateSpaceTemplateBodyModel spaceModel, String spaceModelUuid) async {
|
||||
final response = await HTTPService().put(
|
||||
path: ApiEndpoints.updateSpaceModel
|
||||
.replaceAll('{projectId}', TempConst.projectId).replaceAll('{spaceModelUuid}', spaceModelUuid),
|
||||
body: spaceModel.toJson(),
|
||||
expectedResponseModel: (json) {
|
||||
return json['message'];
|
||||
},
|
||||
);
|
||||
return response;
|
||||
}
|
||||
|
||||
Future<SpaceTemplateModel?> getSpaceModel(String spaceModelUuid) async {
|
||||
final response = await HTTPService().get(
|
||||
path: ApiEndpoints.getSpaceModel
|
||||
|
@ -101,7 +101,10 @@ abstract class ApiEndpoints {
|
||||
//space model
|
||||
static const String listSpaceModels = '/projects/{projectId}/space-models';
|
||||
static const String createSpaceModel = '/projects/{projectId}/space-models';
|
||||
static const String getSpaceModel = '/projects/{projectId}/space-models/{spaceModelUuid}';
|
||||
static const String getSpaceModel =
|
||||
'/projects/{projectId}/space-models/{spaceModelUuid}';
|
||||
static const String updateSpaceModel =
|
||||
'/projects/{projectId}/space-models/{spaceModelUuid}';
|
||||
|
||||
static const String roleTypes = '/role/types';
|
||||
static const String permission = '/permission/{roleUuid}';
|
||||
|
Reference in New Issue
Block a user