mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-11 07:38:05 +00:00
Merge pull request #69 from SyncrowIOT/bugfix/space-edit
Bugfix/space edit
This commit is contained in:
@ -48,6 +48,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,
|
||||||
initialCount: selectedProduct.count,
|
initialCount: selectedProduct.count,
|
||||||
onCountChanged: (newCount) {
|
onCountChanged: (newCount) {
|
||||||
context.read<AddDeviceTypeBloc>().add(
|
context.read<AddDeviceTypeBloc>().add(
|
||||||
|
@ -420,9 +420,10 @@ class SpaceManagementBloc
|
|||||||
await _api.deleteSpace(communityUuid, parent.uuid!);
|
await _api.deleteSpace(communityUuid, parent.uuid!);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
rethrow; // Decide whether to stop execution or continue
|
rethrow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
orderedSpaces.removeWhere((space) => parentsToDelete.contains(space));
|
||||||
|
|
||||||
for (var space in orderedSpaces) {
|
for (var space in orderedSpaces) {
|
||||||
try {
|
try {
|
||||||
|
@ -27,8 +27,7 @@ class SpaceManagementLoaded extends SpaceManagementState {
|
|||||||
required this.products,
|
required this.products,
|
||||||
this.selectedCommunity,
|
this.selectedCommunity,
|
||||||
this.selectedSpace,
|
this.selectedSpace,
|
||||||
this.spaceModels
|
this.spaceModels});
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class SpaceModelManagenetLoaded extends SpaceManagementState {
|
class SpaceModelManagenetLoaded extends SpaceManagementState {
|
||||||
@ -38,14 +37,10 @@ class SpaceModelManagenetLoaded extends SpaceManagementState {
|
|||||||
class BlankState extends SpaceManagementState {
|
class BlankState extends SpaceManagementState {
|
||||||
final List<CommunityModel> communities;
|
final List<CommunityModel> communities;
|
||||||
final List<ProductModel> products;
|
final List<ProductModel> products;
|
||||||
List<SpaceTemplateModel>? spaceModels;
|
List<SpaceTemplateModel>? spaceModels;
|
||||||
|
|
||||||
|
BlankState(
|
||||||
BlankState({
|
{required this.communities, required this.products, this.spaceModels});
|
||||||
required this.communities,
|
|
||||||
required this.products,
|
|
||||||
this.spaceModels
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class SpaceCreationSuccess extends SpaceManagementState {
|
class SpaceCreationSuccess extends SpaceManagementState {
|
||||||
@ -67,7 +62,7 @@ class SpaceManagementError extends SpaceManagementState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class SpaceModelLoaded extends SpaceManagementState {
|
class SpaceModelLoaded extends SpaceManagementState {
|
||||||
final List<SpaceTemplateModel> spaceModels;
|
List<SpaceTemplateModel> spaceModels;
|
||||||
final List<ProductModel> products;
|
final List<ProductModel> products;
|
||||||
final List<CommunityModel> communities;
|
final List<CommunityModel> communities;
|
||||||
|
|
||||||
|
@ -66,4 +66,25 @@ class ProductModel {
|
|||||||
String toString() {
|
String toString() {
|
||||||
return 'ProductModel(uuid: $uuid, catName: $catName, prodId: $prodId, prodType: $prodType, name: $name, icon: $icon)';
|
return 'ProductModel(uuid: $uuid, catName: $catName, prodId: $prodId, prodType: $prodType, name: $name, icon: $icon)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) =>
|
||||||
|
identical(this, other) ||
|
||||||
|
other is ProductModel &&
|
||||||
|
runtimeType == other.runtimeType &&
|
||||||
|
uuid == other.uuid &&
|
||||||
|
catName == other.catName &&
|
||||||
|
prodId == other.prodId &&
|
||||||
|
prodType == other.prodType &&
|
||||||
|
name == other.name &&
|
||||||
|
icon == other.icon;
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode =>
|
||||||
|
uuid.hashCode ^
|
||||||
|
catName.hashCode ^
|
||||||
|
prodId.hashCode ^
|
||||||
|
prodType.hashCode ^
|
||||||
|
name.hashCode ^
|
||||||
|
icon.hashCode;
|
||||||
}
|
}
|
||||||
|
@ -137,6 +137,7 @@ class _AddDeviceWidgetState extends State<AddDeviceWidget> {
|
|||||||
_buildDeviceName(product, size),
|
_buildDeviceName(product, size),
|
||||||
const SizedBox(height: 4),
|
const SizedBox(height: 4),
|
||||||
CounterWidget(
|
CounterWidget(
|
||||||
|
isCreate: false,
|
||||||
initialCount: selectedProduct.count,
|
initialCount: selectedProduct.count,
|
||||||
onCountChanged: (newCount) {
|
onCountChanged: (newCount) {
|
||||||
setState(() {
|
setState(() {
|
||||||
|
@ -177,7 +177,7 @@ class _CommunityStructureAreaState extends State<CommunityStructureArea> {
|
|||||||
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 &&
|
||||||
entry.value.status != SpaceStatus.parentDeleted)
|
entry.value.status != SpaceStatus.parentDeleted)
|
||||||
Positioned(
|
Positioned(
|
||||||
left: entry.value.position.dx,
|
left: entry.value.position.dx,
|
||||||
@ -301,7 +301,6 @@ class _CommunityStructureAreaState extends State<CommunityStructureArea> {
|
|||||||
List<Tag>? tags) {
|
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 ?? _getCenterPosition(screenSize);
|
position ?? _getCenterPosition(screenSize);
|
||||||
SpaceModel newSpace = SpaceModel(
|
SpaceModel newSpace = SpaceModel(
|
||||||
@ -385,10 +384,10 @@ class _CommunityStructureAreaState extends State<CommunityStructureArea> {
|
|||||||
|
|
||||||
void flatten(SpaceModel space) {
|
void flatten(SpaceModel space) {
|
||||||
if (space.status == SpaceStatus.deleted ||
|
if (space.status == SpaceStatus.deleted ||
|
||||||
space.status == SpaceStatus.parentDeleted) return;
|
space.status == SpaceStatus.parentDeleted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
result.add(space);
|
result.add(space);
|
||||||
|
|
||||||
for (var child in space.children) {
|
for (var child in space.children) {
|
||||||
flatten(child);
|
flatten(child);
|
||||||
}
|
}
|
||||||
@ -456,21 +455,15 @@ class _CommunityStructureAreaState extends State<CommunityStructureArea> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _onDelete() {
|
void _onDelete() {
|
||||||
if (widget.selectedCommunity != null &&
|
|
||||||
widget.selectedCommunity?.uuid != null &&
|
|
||||||
widget.selectedSpace == null) {
|
|
||||||
context.read<SpaceManagementBloc>().add(DeleteCommunityEvent(
|
|
||||||
communityUuid: widget.selectedCommunity!.uuid,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
if (widget.selectedSpace != null) {
|
if (widget.selectedSpace != null) {
|
||||||
setState(() {
|
setState(() {
|
||||||
for (var space in spaces) {
|
for (var space in spaces) {
|
||||||
if (space.uuid == widget.selectedSpace?.uuid) {
|
if (space.internalId == widget.selectedSpace?.internalId) {
|
||||||
space.status = SpaceStatus.deleted;
|
space.status = SpaceStatus.deleted;
|
||||||
_markChildrenAsDeleted(space);
|
_markChildrenAsDeleted(space);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_removeConnectionsForDeletedSpaces();
|
_removeConnectionsForDeletedSpaces();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -4,12 +4,14 @@ import 'package:syncrow_web/utils/color_manager.dart';
|
|||||||
class CounterWidget extends StatefulWidget {
|
class CounterWidget extends StatefulWidget {
|
||||||
final int initialCount;
|
final int initialCount;
|
||||||
final ValueChanged<int> onCountChanged;
|
final ValueChanged<int> onCountChanged;
|
||||||
|
final bool isCreate;
|
||||||
|
|
||||||
const CounterWidget({
|
const CounterWidget(
|
||||||
Key? key,
|
{Key? key,
|
||||||
this.initialCount = 0,
|
this.initialCount = 0,
|
||||||
required this.onCountChanged,
|
required this.onCountChanged,
|
||||||
}) : super(key: key);
|
required this.isCreate})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<CounterWidget> createState() => _CounterWidgetState();
|
State<CounterWidget> createState() => _CounterWidgetState();
|
||||||
@ -53,25 +55,26 @@ class _CounterWidgetState extends State<CounterWidget> {
|
|||||||
child: Row(
|
child: Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
_buildCounterButton(Icons.remove, _decrementCounter),
|
_buildCounterButton(Icons.remove, _decrementCounter,!widget.isCreate ),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
Text(
|
Text(
|
||||||
'$_counter',
|
'$_counter',
|
||||||
style: theme.textTheme.bodyLarge?.copyWith(color: ColorsManager.spaceColor),
|
style: theme.textTheme.bodyLarge
|
||||||
|
?.copyWith(color: ColorsManager.spaceColor),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
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(
|
return GestureDetector(
|
||||||
onTap: onPressed,
|
onTap: isDisabled? null: onPressed,
|
||||||
child: Icon(
|
child: Icon(
|
||||||
icon,
|
icon,
|
||||||
color: ColorsManager.spaceColor,
|
color: isDisabled? ColorsManager.spaceColor.withOpacity(0.3): ColorsManager.spaceColor,
|
||||||
size: 18,
|
size: 18,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -47,14 +47,13 @@ class AssignTagModelBloc
|
|||||||
}
|
}
|
||||||
|
|
||||||
emit(AssignTagModelLoaded(
|
emit(AssignTagModelLoaded(
|
||||||
tags: allTags,
|
tags: allTags,
|
||||||
isSaveEnabled: _validateTags(allTags),
|
isSaveEnabled: _validateTags(allTags),
|
||||||
));
|
errorMessage: ''));
|
||||||
});
|
});
|
||||||
|
|
||||||
on<UpdateTag>((event, emit) {
|
on<UpdateTag>((event, emit) {
|
||||||
final currentState = state;
|
final currentState = state;
|
||||||
|
|
||||||
if (currentState is AssignTagModelLoaded &&
|
if (currentState is AssignTagModelLoaded &&
|
||||||
currentState.tags.isNotEmpty) {
|
currentState.tags.isNotEmpty) {
|
||||||
final tags = List<TagModel>.from(currentState.tags);
|
final tags = List<TagModel>.from(currentState.tags);
|
||||||
@ -122,9 +121,7 @@ class AssignTagModelBloc
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool _validateTags(List<TagModel> tags) {
|
bool _validateTags(List<TagModel> tags) {
|
||||||
if (tags.isEmpty) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
final uniqueTags = tags.map((tag) => tag.tag?.trim() ?? '').toSet();
|
final uniqueTags = tags.map((tag) => tag.tag?.trim() ?? '').toSet();
|
||||||
final hasEmptyTag = tags.any((tag) => (tag.tag?.trim() ?? '').isEmpty);
|
final hasEmptyTag = tags.any((tag) => (tag.tag?.trim() ?? '').isEmpty);
|
||||||
final isValid = uniqueTags.length == tags.length && !hasEmptyTag;
|
final isValid = uniqueTags.length == tags.length && !hasEmptyTag;
|
||||||
@ -133,7 +130,11 @@ class AssignTagModelBloc
|
|||||||
|
|
||||||
String? _getValidationError(List<TagModel> tags) {
|
String? _getValidationError(List<TagModel> tags) {
|
||||||
final hasEmptyTag = tags.any((tag) => (tag.tag?.trim() ?? '').isEmpty);
|
final hasEmptyTag = tags.any((tag) => (tag.tag?.trim() ?? '').isEmpty);
|
||||||
if (hasEmptyTag) return 'Tags cannot be empty.';
|
if (hasEmptyTag) {
|
||||||
|
return 'Tags cannot be empty.';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for duplicate tags
|
||||||
final duplicateTags = tags
|
final duplicateTags = tags
|
||||||
.map((tag) => tag.tag?.trim() ?? '')
|
.map((tag) => tag.tag?.trim() ?? '')
|
||||||
.fold<Map<String, int>>({}, (map, tag) {
|
.fold<Map<String, int>>({}, (map, tag) {
|
||||||
|
@ -5,7 +5,7 @@ abstract class AssignTagModelState extends Equatable {
|
|||||||
const AssignTagModelState();
|
const AssignTagModelState();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [];
|
List<Object?> get props => [];
|
||||||
}
|
}
|
||||||
|
|
||||||
class AssignTagModelInitial extends AssignTagModelState {}
|
class AssignTagModelInitial extends AssignTagModelState {}
|
||||||
@ -15,7 +15,7 @@ class AssignTagModelLoading extends AssignTagModelState {}
|
|||||||
class AssignTagModelLoaded extends AssignTagModelState {
|
class AssignTagModelLoaded extends AssignTagModelState {
|
||||||
final List<TagModel> tags;
|
final List<TagModel> tags;
|
||||||
final bool isSaveEnabled;
|
final bool isSaveEnabled;
|
||||||
final String? errorMessage;
|
final String? errorMessage;
|
||||||
|
|
||||||
const AssignTagModelLoaded({
|
const AssignTagModelLoaded({
|
||||||
required this.tags,
|
required this.tags,
|
||||||
@ -24,7 +24,7 @@ class AssignTagModelLoaded extends AssignTagModelState {
|
|||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [tags, isSaveEnabled];
|
List<Object?> get props => [tags, isSaveEnabled, errorMessage];
|
||||||
}
|
}
|
||||||
|
|
||||||
class AssignTagModelError extends AssignTagModelState {
|
class AssignTagModelError extends AssignTagModelState {
|
||||||
@ -33,5 +33,5 @@ class AssignTagModelError extends AssignTagModelState {
|
|||||||
const AssignTagModelError(this.errorMessage);
|
const AssignTagModelError(this.errorMessage);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [errorMessage];
|
List<Object?> get props => [errorMessage];
|
||||||
}
|
}
|
||||||
|
@ -9,22 +9,26 @@ import 'package:syncrow_web/pages/spaces_management/all_spaces/model/selected_pr
|
|||||||
import 'package:syncrow_web/pages/spaces_management/assign_tag_models/bloc/assign_tag_model_bloc.dart';
|
import 'package:syncrow_web/pages/spaces_management/assign_tag_models/bloc/assign_tag_model_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/assign_tag_models/bloc/assign_tag_model_event.dart';
|
import 'package:syncrow_web/pages/spaces_management/assign_tag_models/bloc/assign_tag_model_event.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/assign_tag_models/bloc/assign_tag_model_state.dart';
|
import 'package:syncrow_web/pages/spaces_management/assign_tag_models/bloc/assign_tag_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/models/subspace_template_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/space_model/models/subspace_template_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/space_model/models/tag_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/space_model/models/tag_model.dart';
|
||||||
|
import 'package:syncrow_web/pages/spaces_management/space_model/widgets/dialog/create_space_model_dialog.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/tag_model/views/add_device_type_model_widget.dart';
|
import 'package:syncrow_web/pages/spaces_management/tag_model/views/add_device_type_model_widget.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
|
||||||
class AssignTagModelsDialog extends StatelessWidget {
|
class AssignTagModelsDialog extends StatelessWidget {
|
||||||
final List<ProductModel>? products;
|
final List<ProductModel>? products;
|
||||||
final List<SubspaceTemplateModel>? subspaces;
|
final List<SubspaceTemplateModel>? subspaces;
|
||||||
|
final SpaceTemplateModel? spaceModel;
|
||||||
|
|
||||||
final List<TagModel> initialTags;
|
final List<TagModel> initialTags;
|
||||||
final ValueChanged<List<TagModel>>? onTagsAssigned;
|
final ValueChanged<List<TagModel>>? onTagsAssigned;
|
||||||
final List<SelectedProduct> addedProducts;
|
final List<SelectedProduct> addedProducts;
|
||||||
final List<String>? allTags;
|
final List<String>? allTags;
|
||||||
final String spaceName;
|
final String spaceName;
|
||||||
final String title;
|
final String title;
|
||||||
final void Function(
|
final BuildContext? pageContext;
|
||||||
List<TagModel>? tags, List<SubspaceTemplateModel>? subspaces)? onUpdate;
|
final List<String>? otherSpaceModels;
|
||||||
|
|
||||||
const AssignTagModelsDialog(
|
const AssignTagModelsDialog(
|
||||||
{Key? key,
|
{Key? key,
|
||||||
@ -36,7 +40,9 @@ class AssignTagModelsDialog extends StatelessWidget {
|
|||||||
this.allTags,
|
this.allTags,
|
||||||
required this.spaceName,
|
required this.spaceName,
|
||||||
required this.title,
|
required this.title,
|
||||||
this.onUpdate})
|
this.pageContext,
|
||||||
|
this.otherSpaceModels,
|
||||||
|
this.spaceModel})
|
||||||
: super(key: key);
|
: super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -47,249 +53,202 @@ class AssignTagModelsDialog extends StatelessWidget {
|
|||||||
..add('Main Space');
|
..add('Main Space');
|
||||||
|
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (_) => AssignTagModelBloc()
|
create: (_) => AssignTagModelBloc()
|
||||||
..add(InitializeTagModels(
|
..add(InitializeTagModels(
|
||||||
initialTags: initialTags,
|
initialTags: initialTags,
|
||||||
addedProducts: addedProducts,
|
addedProducts: addedProducts,
|
||||||
)),
|
)),
|
||||||
child: BlocBuilder<AssignTagModelBloc, AssignTagModelState>(
|
child: BlocListener<AssignTagModelBloc, AssignTagModelState>(
|
||||||
builder: (context, state) {
|
listener: (context, state) {},
|
||||||
if (state is AssignTagModelLoaded) {
|
child: BlocBuilder<AssignTagModelBloc, AssignTagModelState>(
|
||||||
final controllers = List.generate(
|
builder: (context, state) {
|
||||||
state.tags.length,
|
if (state is AssignTagModelLoaded) {
|
||||||
(index) => TextEditingController(text: state.tags[index].tag),
|
final controllers = List.generate(
|
||||||
);
|
state.tags.length,
|
||||||
|
(index) => TextEditingController(text: state.tags[index].tag),
|
||||||
|
);
|
||||||
|
|
||||||
return AlertDialog(
|
return AlertDialog(
|
||||||
title: Text(title),
|
title: Text(title),
|
||||||
backgroundColor: ColorsManager.whiteColors,
|
backgroundColor: ColorsManager.whiteColors,
|
||||||
content: SingleChildScrollView(
|
content: SingleChildScrollView(
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
ClipRRect(
|
ClipRRect(
|
||||||
borderRadius: BorderRadius.circular(20),
|
|
||||||
child: DataTable(
|
|
||||||
headingRowColor: WidgetStateProperty.all(
|
|
||||||
ColorsManager.dataHeaderGrey),
|
|
||||||
border: TableBorder.all(
|
|
||||||
color: ColorsManager.dataHeaderGrey,
|
|
||||||
width: 1,
|
|
||||||
borderRadius: BorderRadius.circular(20),
|
borderRadius: BorderRadius.circular(20),
|
||||||
),
|
child: DataTable(
|
||||||
columns: [
|
headingRowColor: WidgetStateProperty.all(
|
||||||
DataColumn(
|
ColorsManager.dataHeaderGrey),
|
||||||
label: Text('#',
|
border: TableBorder.all(
|
||||||
style:
|
color: ColorsManager.dataHeaderGrey,
|
||||||
Theme.of(context).textTheme.bodyMedium)),
|
width: 1,
|
||||||
DataColumn(
|
borderRadius: BorderRadius.circular(20),
|
||||||
label: Text('Device',
|
),
|
||||||
style:
|
columns: [
|
||||||
Theme.of(context).textTheme.bodyMedium)),
|
DataColumn(
|
||||||
DataColumn(
|
label: Text('#',
|
||||||
numeric: false,
|
style: Theme.of(context)
|
||||||
headingRowAlignment: MainAxisAlignment.start,
|
.textTheme
|
||||||
label: Text('Tag',
|
.bodyMedium)),
|
||||||
style:
|
DataColumn(
|
||||||
Theme.of(context).textTheme.bodyMedium)),
|
label: Text('Device',
|
||||||
DataColumn(
|
style: Theme.of(context)
|
||||||
label: Text('Location',
|
.textTheme
|
||||||
style:
|
.bodyMedium)),
|
||||||
Theme.of(context).textTheme.bodyMedium)),
|
DataColumn(
|
||||||
],
|
numeric: false,
|
||||||
rows: state.tags.isEmpty
|
headingRowAlignment: MainAxisAlignment.start,
|
||||||
? [
|
label: Text('Tag',
|
||||||
const DataRow(cells: [
|
style: Theme.of(context)
|
||||||
DataCell(
|
.textTheme
|
||||||
Center(
|
.bodyMedium)),
|
||||||
child: Text(
|
DataColumn(
|
||||||
'No Data Available',
|
label: Text('Location',
|
||||||
style: TextStyle(
|
style: Theme.of(context)
|
||||||
fontSize: 14,
|
.textTheme
|
||||||
color: ColorsManager.lightGrayColor,
|
.bodyMedium)),
|
||||||
|
],
|
||||||
|
rows: state.tags.isEmpty
|
||||||
|
? [
|
||||||
|
const DataRow(cells: [
|
||||||
|
DataCell(
|
||||||
|
Center(
|
||||||
|
child: Text(
|
||||||
|
'No Data Available',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
color:
|
||||||
|
ColorsManager.lightGrayColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
DataCell(SizedBox()),
|
||||||
),
|
DataCell(SizedBox()),
|
||||||
DataCell(SizedBox()),
|
DataCell(SizedBox()),
|
||||||
DataCell(SizedBox()),
|
])
|
||||||
DataCell(SizedBox()),
|
]
|
||||||
])
|
: List.generate(state.tags.length, (index) {
|
||||||
]
|
final tag = state.tags[index];
|
||||||
: List.generate(state.tags.length, (index) {
|
final controller = controllers[index];
|
||||||
final tag = state.tags[index];
|
final availableTags = getAvailableTags(
|
||||||
final controller = controllers[index];
|
allTags ?? [], state.tags, tag);
|
||||||
final availableTags = getAvailableTags(
|
|
||||||
allTags ?? [], state.tags, tag);
|
|
||||||
|
|
||||||
return DataRow(
|
return DataRow(
|
||||||
cells: [
|
cells: [
|
||||||
DataCell(Text(index.toString())),
|
DataCell(Text((index + 1).toString())),
|
||||||
DataCell(
|
DataCell(
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment:
|
mainAxisAlignment:
|
||||||
MainAxisAlignment.spaceBetween,
|
MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Text(
|
child: Text(
|
||||||
tag.product?.name ?? 'Unknown',
|
tag.product?.name ?? 'Unknown',
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
)),
|
)),
|
||||||
const SizedBox(width: 10),
|
const SizedBox(width: 10),
|
||||||
|
Container(
|
||||||
|
width: 20.0,
|
||||||
|
height: 20.0,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
shape: BoxShape.circle,
|
||||||
|
border: Border.all(
|
||||||
|
color: ColorsManager
|
||||||
|
.lightGrayColor,
|
||||||
|
width: 1.0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: IconButton(
|
||||||
|
icon: const Icon(
|
||||||
|
Icons.close,
|
||||||
|
color: ColorsManager
|
||||||
|
.lightGreyColor,
|
||||||
|
size: 16,
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
context
|
||||||
|
.read<
|
||||||
|
AssignTagModelBloc>()
|
||||||
|
.add(DeleteTagModel(
|
||||||
|
tagToDelete: tag,
|
||||||
|
tags: state.tags));
|
||||||
|
},
|
||||||
|
tooltip: 'Delete Tag',
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
constraints:
|
||||||
|
const BoxConstraints(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
DataCell(
|
||||||
Container(
|
Container(
|
||||||
width: 20.0,
|
alignment: Alignment
|
||||||
height: 20.0,
|
.centerLeft, // Align cell content to the left
|
||||||
decoration: BoxDecoration(
|
child: SizedBox(
|
||||||
shape: BoxShape.circle,
|
width: double
|
||||||
border: Border.all(
|
.infinity, // Ensure full width for dropdown
|
||||||
color: ColorsManager
|
child: DialogTextfieldDropdown(
|
||||||
.lightGrayColor,
|
items: availableTags,
|
||||||
width: 1.0,
|
initialValue: tag.tag,
|
||||||
|
onSelected: (value) {
|
||||||
|
controller.text = value;
|
||||||
|
context
|
||||||
|
.read<
|
||||||
|
AssignTagModelBloc>()
|
||||||
|
.add(UpdateTag(
|
||||||
|
index: index,
|
||||||
|
tag: value,
|
||||||
|
));
|
||||||
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: IconButton(
|
|
||||||
icon: const Icon(
|
|
||||||
Icons.close,
|
|
||||||
color: ColorsManager
|
|
||||||
.lightGreyColor,
|
|
||||||
size: 16,
|
|
||||||
),
|
|
||||||
onPressed: () {
|
|
||||||
context
|
|
||||||
.read<AssignTagModelBloc>()
|
|
||||||
.add(DeleteTagModel(
|
|
||||||
tagToDelete: tag,
|
|
||||||
tags: state.tags));
|
|
||||||
},
|
|
||||||
tooltip: 'Delete Tag',
|
|
||||||
padding: EdgeInsets.zero,
|
|
||||||
constraints:
|
|
||||||
const BoxConstraints(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
DataCell(
|
|
||||||
Container(
|
|
||||||
alignment: Alignment
|
|
||||||
.centerLeft, // Align cell content to the left
|
|
||||||
child: SizedBox(
|
|
||||||
width: double
|
|
||||||
.infinity, // Ensure full width for dropdown
|
|
||||||
child: DialogTextfieldDropdown(
|
|
||||||
items: availableTags,
|
|
||||||
initialValue: tag.tag,
|
|
||||||
onSelected: (value) {
|
|
||||||
controller.text = value;
|
|
||||||
context
|
|
||||||
.read<AssignTagModelBloc>()
|
|
||||||
.add(UpdateTag(
|
|
||||||
index: index,
|
|
||||||
tag: value,
|
|
||||||
));
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
DataCell(
|
||||||
),
|
SizedBox(
|
||||||
DataCell(
|
width: double.infinity,
|
||||||
SizedBox(
|
child: DialogDropdown(
|
||||||
width: double.infinity,
|
items: locations,
|
||||||
child: DialogDropdown(
|
selectedValue:
|
||||||
items: locations,
|
tag.location ?? 'Main Space',
|
||||||
selectedValue:
|
onSelected: (value) {
|
||||||
tag.location ?? 'None',
|
context
|
||||||
onSelected: (value) {
|
.read<
|
||||||
context
|
AssignTagModelBloc>()
|
||||||
.read<AssignTagModelBloc>()
|
.add(UpdateLocation(
|
||||||
.add(UpdateLocation(
|
index: index,
|
||||||
index: index,
|
location: value,
|
||||||
location: value,
|
));
|
||||||
));
|
},
|
||||||
},
|
)),
|
||||||
)),
|
),
|
||||||
),
|
],
|
||||||
],
|
);
|
||||||
);
|
}),
|
||||||
}),
|
),
|
||||||
),
|
|
||||||
),
|
|
||||||
if (state.errorMessage != null)
|
|
||||||
Text(
|
|
||||||
state.errorMessage!,
|
|
||||||
style: const TextStyle(color: ColorsManager.warningRed),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
actions: [
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
|
||||||
children: [
|
|
||||||
const SizedBox(width: 10),
|
|
||||||
Expanded(
|
|
||||||
child: Builder(
|
|
||||||
builder: (buttonContext) => CancelButton(
|
|
||||||
label: 'Add New Device',
|
|
||||||
onPressed: () async {
|
|
||||||
for (var tag in state.tags) {
|
|
||||||
if (tag.location == null || subspaces == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
final previousTagSubspace =
|
|
||||||
checkTagExistInSubspace(tag, subspaces ?? []);
|
|
||||||
|
|
||||||
if (tag.location == 'Main Space') {
|
|
||||||
removeTagFromSubspace(tag, previousTagSubspace);
|
|
||||||
} else if (tag.location !=
|
|
||||||
previousTagSubspace?.subspaceName) {
|
|
||||||
removeTagFromSubspace(tag, previousTagSubspace);
|
|
||||||
moveToNewSubspace(tag, subspaces ?? []);
|
|
||||||
state.tags.removeWhere(
|
|
||||||
(t) => t.internalId == tag.internalId);
|
|
||||||
} else {
|
|
||||||
updateTagInSubspace(tag, previousTagSubspace);
|
|
||||||
state.tags.removeWhere(
|
|
||||||
(t) => t.internalId == tag.internalId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (context.mounted) {
|
|
||||||
await showDialog<bool>(
|
|
||||||
barrierDismissible: false,
|
|
||||||
context: context,
|
|
||||||
builder: (dialogContext) =>
|
|
||||||
AddDeviceTypeModelWidget(
|
|
||||||
products: products,
|
|
||||||
subspaces: subspaces,
|
|
||||||
isCreate: false,
|
|
||||||
initialSelectedProducts: addedProducts,
|
|
||||||
allTags: allTags,
|
|
||||||
spaceName: spaceName,
|
|
||||||
spaceTagModels: state.tags,
|
|
||||||
onUpdate: (tags, subspaces) {
|
|
||||||
onUpdate?.call(state.tags, subspaces);
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
if (state.errorMessage != null)
|
||||||
|
Text(
|
||||||
|
state.errorMessage!,
|
||||||
|
style: const TextStyle(
|
||||||
|
color: ColorsManager.warningRed),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(width: 10),
|
),
|
||||||
Expanded(
|
actions: [
|
||||||
child: DefaultButton(
|
Row(
|
||||||
borderRadius: 10,
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
backgroundColor: state.isSaveEnabled
|
children: [
|
||||||
? ColorsManager.secondaryColor
|
const SizedBox(width: 10),
|
||||||
: ColorsManager.grayColor,
|
Expanded(
|
||||||
foregroundColor: ColorsManager.whiteColors,
|
child: Builder(
|
||||||
onPressed: state.isSaveEnabled
|
builder: (buttonContext) => CancelButton(
|
||||||
? () async {
|
label: 'Add New Device',
|
||||||
Navigator.of(context).pop();
|
onPressed: () async {
|
||||||
|
|
||||||
for (var tag in state.tags) {
|
for (var tag in state.tags) {
|
||||||
if (tag.location == null ||
|
if (tag.location == null ||
|
||||||
subspaces == null) {
|
subspaces == null) {
|
||||||
@ -317,26 +276,113 @@ class AssignTagModelsDialog extends StatelessWidget {
|
|||||||
(t) => t.internalId == tag.internalId);
|
(t) => t.internalId == tag.internalId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (context.mounted) {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
|
||||||
onUpdate?.call(state.tags, subspaces);
|
await showDialog<bool>(
|
||||||
}
|
barrierDismissible: false,
|
||||||
: null,
|
context: context,
|
||||||
child: const Text('Save'),
|
builder: (dialogContext) =>
|
||||||
),
|
AddDeviceTypeModelWidget(
|
||||||
|
products: products,
|
||||||
|
subspaces: subspaces,
|
||||||
|
isCreate: false,
|
||||||
|
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)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 10),
|
||||||
|
Expanded(
|
||||||
|
child: DefaultButton(
|
||||||
|
borderRadius: 10,
|
||||||
|
backgroundColor: state.isSaveEnabled
|
||||||
|
? ColorsManager.secondaryColor
|
||||||
|
: ColorsManager.grayColor,
|
||||||
|
foregroundColor: ColorsManager.whiteColors,
|
||||||
|
onPressed: state.isSaveEnabled
|
||||||
|
? () async {
|
||||||
|
for (var tag in state.tags) {
|
||||||
|
if (tag.location == null ||
|
||||||
|
subspaces == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
final previousTagSubspace =
|
||||||
|
checkTagExistInSubspace(
|
||||||
|
tag, subspaces ?? []);
|
||||||
|
|
||||||
|
if (tag.location == 'Main Space') {
|
||||||
|
removeTagFromSubspace(
|
||||||
|
tag, previousTagSubspace);
|
||||||
|
} else if (tag.location !=
|
||||||
|
previousTagSubspace?.subspaceName) {
|
||||||
|
removeTagFromSubspace(
|
||||||
|
tag, previousTagSubspace);
|
||||||
|
moveToNewSubspace(tag, subspaces ?? []);
|
||||||
|
state.tags.removeWhere((t) =>
|
||||||
|
t.internalId == tag.internalId);
|
||||||
|
} else {
|
||||||
|
updateTagInSubspace(
|
||||||
|
tag, previousTagSubspace);
|
||||||
|
state.tags.removeWhere((t) =>
|
||||||
|
t.internalId == tag.internalId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Navigator.of(context)
|
||||||
|
.popUntil((route) => route.isFirst);
|
||||||
|
|
||||||
|
await showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext dialogContext) {
|
||||||
|
return CreateSpaceModelDialog(
|
||||||
|
products: products,
|
||||||
|
allTags: allTags,
|
||||||
|
pageContext: pageContext,
|
||||||
|
otherSpaceModels: otherSpaceModels,
|
||||||
|
spaceModel: SpaceTemplateModel(
|
||||||
|
modelName: spaceName,
|
||||||
|
tags: state.tags,
|
||||||
|
uuid: spaceModel?.uuid,
|
||||||
|
internalId:
|
||||||
|
spaceModel?.internalId,
|
||||||
|
subspaceModels: subspaces),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
child: const Text('Save'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 10),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(width: 10),
|
|
||||||
],
|
],
|
||||||
),
|
);
|
||||||
],
|
} else if (state is AssignTagModelLoading) {
|
||||||
);
|
return const Center(child: CircularProgressIndicator());
|
||||||
} else if (state is AssignTagModelLoading) {
|
} else {
|
||||||
return const Center(child: CircularProgressIndicator());
|
return const Center(child: Text('Something went wrong.'));
|
||||||
} else {
|
}
|
||||||
return const Center(child: Text('Something went wrong.'));
|
},
|
||||||
}
|
),
|
||||||
},
|
));
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> getAvailableTags(
|
List<String> getAvailableTags(
|
||||||
|
@ -186,8 +186,7 @@ class CreateSubSpaceModelDialog extends StatelessWidget {
|
|||||||
const SizedBox(width: 10),
|
const SizedBox(width: 10),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: DefaultButton(
|
child: DefaultButton(
|
||||||
onPressed: (state.subSpaces.isEmpty ||
|
onPressed: (state.errorMessage.isNotEmpty)
|
||||||
state.errorMessage.isNotEmpty)
|
|
||||||
? null
|
? null
|
||||||
: () async {
|
: () async {
|
||||||
final subSpaces = context
|
final subSpaces = context
|
||||||
@ -201,8 +200,7 @@ class CreateSubSpaceModelDialog extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
backgroundColor: ColorsManager.secondaryColor,
|
backgroundColor: ColorsManager.secondaryColor,
|
||||||
borderRadius: 10,
|
borderRadius: 10,
|
||||||
foregroundColor: state.subSpaces.isEmpty ||
|
foregroundColor: state.errorMessage.isNotEmpty
|
||||||
state.errorMessage.isNotEmpty
|
|
||||||
? ColorsManager.whiteColorsWithOpacity
|
? ColorsManager.whiteColorsWithOpacity
|
||||||
: ColorsManager.whiteColors,
|
: ColorsManager.whiteColors,
|
||||||
child: const Text('OK'),
|
child: const Text('OK'),
|
||||||
|
@ -37,7 +37,8 @@ class TagHelper {
|
|||||||
final Map<ProductModel, int> groupedTags = {};
|
final Map<ProductModel, int> groupedTags = {};
|
||||||
for (var tag in tags) {
|
for (var tag in tags) {
|
||||||
if (tag.product != null) {
|
if (tag.product != null) {
|
||||||
groupedTags[tag.product!] = (groupedTags[tag.product!] ?? 0) + 1;
|
final product = tag.product!;
|
||||||
|
groupedTags[product] = (groupedTags[product] ?? 0) + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return groupedTags;
|
return groupedTags;
|
||||||
|
@ -5,7 +5,9 @@ import 'package:syncrow_web/pages/spaces_management/space_model/models/create_sp
|
|||||||
import 'package:syncrow_web/pages/spaces_management/space_model/models/space_template_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/space_model/models/space_template_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/space_model/models/subspace_template_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/space_model/models/subspace_template_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/space_model/models/tag_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/space_model/models/tag_model.dart';
|
||||||
|
import 'package:syncrow_web/pages/spaces_management/space_model/models/tag_update_model.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 CreateSpaceModelBloc
|
class CreateSpaceModelBloc
|
||||||
extends Bloc<CreateSpaceModelEvent, CreateSpaceModelState> {
|
extends Bloc<CreateSpaceModelEvent, CreateSpaceModelState> {
|
||||||
@ -172,7 +174,12 @@ class CreateSpaceModelBloc
|
|||||||
on<UpdateSpaceTemplateName>((event, emit) {
|
on<UpdateSpaceTemplateName>((event, emit) {
|
||||||
final currentState = state;
|
final currentState = state;
|
||||||
if (currentState is CreateSpaceModelLoaded) {
|
if (currentState is CreateSpaceModelLoaded) {
|
||||||
if (event.name.trim().isEmpty) {
|
if (event.allModels.contains(event.name) == true) {
|
||||||
|
emit(CreateSpaceModelLoaded(
|
||||||
|
currentState.space,
|
||||||
|
errorMessage: "Duplicate Model name",
|
||||||
|
));
|
||||||
|
} else if (event.name.trim().isEmpty) {
|
||||||
emit(CreateSpaceModelLoaded(
|
emit(CreateSpaceModelLoaded(
|
||||||
currentState.space,
|
currentState.space,
|
||||||
errorMessage: "Model name cannot be empty",
|
errorMessage: "Model name cannot be empty",
|
||||||
@ -187,5 +194,160 @@ class CreateSpaceModelBloc
|
|||||||
emit(CreateSpaceModelError("Space template not initialized"));
|
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 = [];
|
||||||
|
final List<SubspaceTemplateModel>? prevSubspaces =
|
||||||
|
prevSpaceModel.subspaceModels;
|
||||||
|
final List<SubspaceTemplateModel>? newSubspaces =
|
||||||
|
newSpaceModel.subspaceModels;
|
||||||
|
|
||||||
|
tagUpdates = processTagUpdates(prevSpaceModel.tags, newSpaceModel.tags);
|
||||||
|
|
||||||
|
if (prevSubspaces != null || newSubspaces != null) {
|
||||||
|
if (prevSubspaces != null && newSubspaces != null) {
|
||||||
|
for (var prevSubspace in prevSubspaces!) {
|
||||||
|
final existsInNew = newSubspaces!
|
||||||
|
.any((newTag) => newTag.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,
|
||||||
|
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));
|
||||||
|
} else {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} 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) {
|
||||||
|
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 SpaceTemplateModel spaceTemplate;
|
||||||
final Function(SpaceTemplateModel)? onCreate;
|
final Function(SpaceTemplateModel)? onCreate;
|
||||||
|
|
||||||
|
|
||||||
const CreateSpaceTemplate({
|
const CreateSpaceTemplate({
|
||||||
required this.spaceTemplate,
|
required this.spaceTemplate,
|
||||||
this.onCreate,
|
this.onCreate,
|
||||||
@ -34,11 +33,12 @@ class CreateSpaceTemplate extends CreateSpaceModelEvent {
|
|||||||
|
|
||||||
class UpdateSpaceTemplateName extends CreateSpaceModelEvent {
|
class UpdateSpaceTemplateName extends CreateSpaceModelEvent {
|
||||||
final String name;
|
final String name;
|
||||||
|
final List<String> allModels;
|
||||||
|
|
||||||
UpdateSpaceTemplateName({required this.name});
|
UpdateSpaceTemplateName({required this.name, required this.allModels});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [name];
|
List<Object> get props => [name, allModels];
|
||||||
}
|
}
|
||||||
|
|
||||||
class AddSubspacesToSpaceTemplate extends CreateSpaceModelEvent {
|
class AddSubspacesToSpaceTemplate extends CreateSpaceModelEvent {
|
||||||
@ -53,9 +53,19 @@ class AddTagsToSpaceTemplate extends CreateSpaceModelEvent {
|
|||||||
AddTagsToSpaceTemplate(this.tags);
|
AddTagsToSpaceTemplate(this.tags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class ValidateSpaceTemplateName extends CreateSpaceModelEvent {
|
class ValidateSpaceTemplateName extends CreateSpaceModelEvent {
|
||||||
final String name;
|
final String name;
|
||||||
|
|
||||||
ValidateSpaceTemplateName({required this.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,
|
required List<SpaceTemplateModel> initialSpaceModels,
|
||||||
}) : super(SpaceModelLoaded(spaceModels: initialSpaceModels)) {
|
}) : super(SpaceModelLoaded(spaceModels: initialSpaceModels)) {
|
||||||
on<CreateSpaceModel>(_onCreateSpaceModel);
|
on<CreateSpaceModel>(_onCreateSpaceModel);
|
||||||
|
on<UpdateSpaceModel>(_onUpdateSpaceModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _onCreateSpaceModel(
|
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
|
@override
|
||||||
List<Object?> get props => [newSpaceModel];
|
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 {
|
class CreateSpaceTemplateBodyModel {
|
||||||
final String modelName;
|
final String? modelName;
|
||||||
final List<dynamic>? tags;
|
final List<dynamic>? tags;
|
||||||
final List<dynamic>? subspaceModels;
|
final List<dynamic>? subspaceModels;
|
||||||
|
|
||||||
CreateSpaceTemplateBodyModel({
|
CreateSpaceTemplateBodyModel({
|
||||||
required this.modelName,
|
this.modelName,
|
||||||
this.tags,
|
this.tags,
|
||||||
this.subspaceModels,
|
this.subspaceModels,
|
||||||
});
|
});
|
||||||
@ -47,4 +47,9 @@ class CreateSpaceTemplateBodyModel {
|
|||||||
'subspaceModels': subspaceModels,
|
'subspaceModels': subspaceModels,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return toJson().toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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/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/subspace_template_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/space_model/models/tag_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/space_model/models/tag_model.dart';
|
||||||
|
import 'package:syncrow_web/pages/spaces_management/space_model/models/tag_update_model.dart';
|
||||||
import 'package:syncrow_web/utils/constants/action_enum.dart';
|
import 'package:syncrow_web/utils/constants/action_enum.dart';
|
||||||
import 'package:uuid/uuid.dart';
|
import 'package:uuid/uuid.dart';
|
||||||
|
|
||||||
@ -70,14 +71,14 @@ class SpaceTemplateModel extends Equatable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class UpdateSubspaceTemplateModel {
|
class UpdateSubspaceTemplateModel {
|
||||||
final String uuid;
|
final String? uuid;
|
||||||
final Action action;
|
final Action action;
|
||||||
final String? subspaceName;
|
final String? subspaceName;
|
||||||
final List<UpdateTagModel>? tags;
|
final List<TagModelUpdate>? tags;
|
||||||
|
|
||||||
UpdateSubspaceTemplateModel({
|
UpdateSubspaceTemplateModel({
|
||||||
required this.action,
|
required this.action,
|
||||||
required this.uuid,
|
this.uuid,
|
||||||
this.subspaceName,
|
this.subspaceName,
|
||||||
this.tags,
|
this.tags,
|
||||||
});
|
});
|
||||||
@ -88,7 +89,7 @@ class UpdateSubspaceTemplateModel {
|
|||||||
uuid: json['uuid'] ?? '',
|
uuid: json['uuid'] ?? '',
|
||||||
subspaceName: json['subspaceName'] ?? '',
|
subspaceName: json['subspaceName'] ?? '',
|
||||||
tags: (json['tags'] as List)
|
tags: (json['tags'] as List)
|
||||||
.map((item) => UpdateTagModel.fromJson(item))
|
.map((item) => TagModelUpdate.fromJson(item))
|
||||||
.toList(),
|
.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 {
|
extension SpaceTemplateExtensions on SpaceTemplateModel {
|
||||||
List<String> listAllTagValues() {
|
List<String> listAllTagValues() {
|
||||||
final List<String> tagValues = [];
|
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,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -2,7 +2,6 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/product_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/product_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/space_model/bloc/space_model_bloc.dart';
|
import 'package:syncrow_web/pages/spaces_management/space_model/bloc/space_model_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/space_model/bloc/space_model_event.dart';
|
|
||||||
import 'package:syncrow_web/pages/spaces_management/space_model/bloc/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/models/space_template_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/space_model/widgets/add_space_model_widget.dart';
|
import 'package:syncrow_web/pages/spaces_management/space_model/widgets/add_space_model_widget.dart';
|
||||||
@ -24,6 +23,7 @@ class SpaceModelPage extends StatelessWidget {
|
|||||||
} else if (state is SpaceModelLoaded) {
|
} else if (state is SpaceModelLoaded) {
|
||||||
final spaceModels = state.spaceModels;
|
final spaceModels = state.spaceModels;
|
||||||
final allTagValues = _getAllTagValues(spaceModels);
|
final allTagValues = _getAllTagValues(spaceModels);
|
||||||
|
final allSpaceModelNames = _getAllSpaceModelName(spaceModels);
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: ColorsManager.whiteColors,
|
backgroundColor: ColorsManager.whiteColors,
|
||||||
@ -52,12 +52,8 @@ class SpaceModelPage extends StatelessWidget {
|
|||||||
return CreateSpaceModelDialog(
|
return CreateSpaceModelDialog(
|
||||||
products: products,
|
products: products,
|
||||||
allTags: allTagValues,
|
allTags: allTagValues,
|
||||||
onLoad: (newModel) {
|
pageContext: context,
|
||||||
context.read<SpaceModelBloc>().add(
|
otherSpaceModels: allSpaceModelNames,
|
||||||
CreateSpaceModel(
|
|
||||||
newSpaceModel: newModel),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@ -67,6 +63,8 @@ class SpaceModelPage extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
// Render existing space model
|
// Render existing space model
|
||||||
final model = spaceModels[index];
|
final model = spaceModels[index];
|
||||||
|
final otherModel = List<String>.from(allSpaceModelNames);
|
||||||
|
otherModel.remove(model.modelName);
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
showDialog(
|
showDialog(
|
||||||
@ -76,7 +74,8 @@ class SpaceModelPage extends StatelessWidget {
|
|||||||
products: products,
|
products: products,
|
||||||
allTags: allTagValues,
|
allTags: allTagValues,
|
||||||
spaceModel: model,
|
spaceModel: model,
|
||||||
onLoad: (newModel) {},
|
otherSpaceModels: otherModel,
|
||||||
|
pageContext: context,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@ -128,4 +127,12 @@ class SpaceModelPage extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
return allTags;
|
return allTags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<String> _getAllSpaceModelName(List<SpaceTemplateModel> spaceModels) {
|
||||||
|
final List<String> names = [];
|
||||||
|
for (final spaceModel in spaceModels) {
|
||||||
|
names.add(spaceModel.modelName);
|
||||||
|
}
|
||||||
|
return names;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,8 +6,11 @@ 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_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_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/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/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/widgets/tag_chips_display_widget.dart';
|
||||||
|
import 'package:syncrow_web/pages/spaces_management/space_model/bloc/space_model_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/spaces_management/space_model/bloc/space_model_event.dart';
|
||||||
|
|
||||||
import 'package:syncrow_web/pages/spaces_management/space_model/widgets/subspace_model_create_widget.dart';
|
import 'package:syncrow_web/pages/spaces_management/space_model/widgets/subspace_model_create_widget.dart';
|
||||||
import 'package:syncrow_web/services/space_model_mang_api.dart';
|
import 'package:syncrow_web/services/space_model_mang_api.dart';
|
||||||
@ -17,15 +20,17 @@ class CreateSpaceModelDialog extends StatelessWidget {
|
|||||||
final List<ProductModel>? products;
|
final List<ProductModel>? products;
|
||||||
final List<String>? allTags;
|
final List<String>? allTags;
|
||||||
final SpaceTemplateModel? spaceModel;
|
final SpaceTemplateModel? spaceModel;
|
||||||
final void Function(SpaceTemplateModel newModel)? onLoad;
|
final BuildContext? pageContext;
|
||||||
|
final List<String>? otherSpaceModels;
|
||||||
|
|
||||||
const CreateSpaceModelDialog({
|
const CreateSpaceModelDialog(
|
||||||
Key? key,
|
{Key? key,
|
||||||
this.products,
|
this.products,
|
||||||
this.allTags,
|
this.allTags,
|
||||||
this.spaceModel,
|
this.spaceModel,
|
||||||
this.onLoad,
|
this.pageContext,
|
||||||
}) : super(key: key);
|
this.otherSpaceModels})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -44,17 +49,19 @@ class CreateSpaceModelDialog extends StatelessWidget {
|
|||||||
child: BlocProvider(
|
child: BlocProvider(
|
||||||
create: (_) {
|
create: (_) {
|
||||||
final bloc = CreateSpaceModelBloc(_spaceModelApi);
|
final bloc = CreateSpaceModelBloc(_spaceModelApi);
|
||||||
if (spaceModel != null) {
|
if (spaceModel != null) {
|
||||||
bloc.add(UpdateSpaceTemplate(spaceModel!));
|
bloc.add(UpdateSpaceTemplate(spaceModel!));
|
||||||
} else {
|
} else {
|
||||||
bloc.add(UpdateSpaceTemplate(SpaceTemplateModel(
|
bloc.add(UpdateSpaceTemplate(SpaceTemplateModel(
|
||||||
modelName: '',
|
modelName: '',
|
||||||
subspaceModels: const [],
|
subspaceModels: const [],
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
spaceNameController.addListener(() {
|
spaceNameController.addListener(() {
|
||||||
bloc.add(UpdateSpaceTemplateName(name: spaceNameController.text));
|
bloc.add(UpdateSpaceTemplateName(
|
||||||
|
name: spaceNameController.text,
|
||||||
|
allModels: otherSpaceModels ?? []));
|
||||||
});
|
});
|
||||||
|
|
||||||
return bloc;
|
return bloc;
|
||||||
@ -86,9 +93,10 @@ class CreateSpaceModelDialog extends StatelessWidget {
|
|||||||
child: TextField(
|
child: TextField(
|
||||||
controller: spaceNameController,
|
controller: spaceNameController,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
context
|
context.read<CreateSpaceModelBloc>().add(
|
||||||
.read<CreateSpaceModelBloc>()
|
UpdateSpaceTemplateName(
|
||||||
.add(UpdateSpaceTemplateName(name: value));
|
name: value,
|
||||||
|
allModels: otherSpaceModels ?? []));
|
||||||
},
|
},
|
||||||
style: const TextStyle(color: ColorsManager.blackColor),
|
style: const TextStyle(color: ColorsManager.blackColor),
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
@ -128,21 +136,8 @@ class CreateSpaceModelDialog extends StatelessWidget {
|
|||||||
subspaces: subspaces,
|
subspaces: subspaces,
|
||||||
allTags: allTags,
|
allTags: allTags,
|
||||||
spaceNameController: spaceNameController,
|
spaceNameController: spaceNameController,
|
||||||
onLoad: (tags, subspaces) {
|
pageContext: pageContext,
|
||||||
if (context.read<CreateSpaceModelBloc>().state
|
otherSpaceModels: otherSpaceModels,
|
||||||
is CreateSpaceModelLoaded) {
|
|
||||||
if (subspaces != null) {
|
|
||||||
context
|
|
||||||
.read<CreateSpaceModelBloc>()
|
|
||||||
.add(AddSubspacesToSpaceTemplate(subspaces));
|
|
||||||
}
|
|
||||||
if (tags != null) {
|
|
||||||
context
|
|
||||||
.read<CreateSpaceModelBloc>()
|
|
||||||
.add(AddTagsToSpaceTemplate(tags));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
@ -166,17 +161,73 @@ class CreateSpaceModelDialog extends StatelessWidget {
|
|||||||
modelName:
|
modelName:
|
||||||
spaceNameController.text.trim(),
|
spaceNameController.text.trim(),
|
||||||
);
|
);
|
||||||
context.read<CreateSpaceModelBloc>().add(
|
if (updatedSpaceModel.uuid == null) {
|
||||||
CreateSpaceTemplate(
|
context
|
||||||
spaceTemplate:
|
.read<CreateSpaceModelBloc>()
|
||||||
updatedSpaceTemplate,
|
.add(
|
||||||
onCreate: (newModel) {
|
CreateSpaceTemplate(
|
||||||
onLoad!(newModel);
|
spaceTemplate:
|
||||||
Navigator.of(context)
|
updatedSpaceTemplate,
|
||||||
.pop(); // Close the dialog
|
onCreate: (newModel) {
|
||||||
},
|
if (pageContext != null) {
|
||||||
),
|
pageContext!
|
||||||
);
|
.read<SpaceModelBloc>()
|
||||||
|
.add(CreateSpaceModel(
|
||||||
|
newSpaceModel:
|
||||||
|
newModel));
|
||||||
|
}
|
||||||
|
Navigator.of(context)
|
||||||
|
.pop(); // Close the dialog
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} 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,
|
: null,
|
||||||
backgroundColor: ColorsManager.secondaryColor,
|
backgroundColor: ColorsManager.secondaryColor,
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.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 {
|
class SubspaceChipWidget extends StatelessWidget {
|
||||||
final String subspace;
|
final String subspace;
|
||||||
|
|
||||||
|
@ -46,23 +46,23 @@ class SubspaceModelCreate extends StatelessWidget {
|
|||||||
spacing: 8.0,
|
spacing: 8.0,
|
||||||
runSpacing: 8.0,
|
runSpacing: 8.0,
|
||||||
children: [
|
children: [
|
||||||
...subspaces.map(
|
...subspaces.map((subspace) => Container(
|
||||||
(subspace) => Chip(
|
padding: const EdgeInsets.symmetric(
|
||||||
label: Text(
|
horizontal: 8.0, vertical: 4.0),
|
||||||
subspace.subspaceName,
|
decoration: BoxDecoration(
|
||||||
style: const TextStyle(
|
color: ColorsManager.whiteColors,
|
||||||
color: ColorsManager.spaceColor), // Text color
|
borderRadius: BorderRadius.circular(10),
|
||||||
),
|
border: Border.all(
|
||||||
backgroundColor:
|
color: ColorsManager.transparentColor),
|
||||||
ColorsManager.whiteColors, // Chip background color
|
),
|
||||||
shape: RoundedRectangleBorder(
|
child: Text(
|
||||||
borderRadius:
|
subspace.subspaceName,
|
||||||
BorderRadius.circular(16), // Rounded chip
|
style: Theme.of(context)
|
||||||
side: const BorderSide(
|
.textTheme
|
||||||
color: ColorsManager.spaceColor), // Border color
|
.bodySmall
|
||||||
),
|
?.copyWith(color: ColorsManager.spaceColor),
|
||||||
),
|
),
|
||||||
),
|
)),
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
await _openDialog(context, 'Edit Sub-space');
|
await _openDialog(context, 'Edit Sub-space');
|
||||||
|
@ -5,7 +5,6 @@ import 'package:syncrow_web/pages/spaces_management/assign_tag_models/views/assi
|
|||||||
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/space_model/models/space_template_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/space_model/models/space_template_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/space_model/models/subspace_template_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/space_model/models/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/button_content_widget.dart';
|
import 'package:syncrow_web/pages/spaces_management/space_model/widgets/button_content_widget.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/tag_model/views/add_device_type_model_widget.dart';
|
import 'package:syncrow_web/pages/spaces_management/tag_model/views/add_device_type_model_widget.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
@ -17,8 +16,8 @@ class TagChipDisplay extends StatelessWidget {
|
|||||||
final List<SubspaceTemplateModel>? subspaces;
|
final List<SubspaceTemplateModel>? subspaces;
|
||||||
final List<String>? allTags;
|
final List<String>? allTags;
|
||||||
final TextEditingController spaceNameController;
|
final TextEditingController spaceNameController;
|
||||||
final void Function(
|
final BuildContext? pageContext;
|
||||||
List<TagModel>? tags, List<SubspaceTemplateModel>? subspaces)? onLoad;
|
final List<String>? otherSpaceModels;
|
||||||
|
|
||||||
const TagChipDisplay(BuildContext context,
|
const TagChipDisplay(BuildContext context,
|
||||||
{Key? key,
|
{Key? key,
|
||||||
@ -28,7 +27,8 @@ class TagChipDisplay extends StatelessWidget {
|
|||||||
required this.subspaces,
|
required this.subspaces,
|
||||||
required this.allTags,
|
required this.allTags,
|
||||||
required this.spaceNameController,
|
required this.spaceNameController,
|
||||||
this.onLoad})
|
this.pageContext,
|
||||||
|
this.otherSpaceModels})
|
||||||
: super(key: key);
|
: super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -91,24 +91,23 @@ class TagChipDisplay extends StatelessWidget {
|
|||||||
|
|
||||||
if (navigatorContext != null) {
|
if (navigatorContext != null) {
|
||||||
await showDialog<bool>(
|
await showDialog<bool>(
|
||||||
barrierDismissible: false,
|
barrierDismissible: false,
|
||||||
context: navigatorContext,
|
context: navigatorContext,
|
||||||
builder: (context) => AssignTagModelsDialog(
|
builder: (context) => AssignTagModelsDialog(
|
||||||
products: products,
|
products: products,
|
||||||
subspaces: subspaces,
|
|
||||||
allTags: allTags,
|
|
||||||
initialTags: TagHelper.generateInitialTags(
|
|
||||||
subspaces: subspaces,
|
subspaces: subspaces,
|
||||||
spaceTagModels: spaceModel?.tags ?? []),
|
pageContext: pageContext,
|
||||||
title: 'Edit Device',
|
allTags: allTags,
|
||||||
addedProducts:
|
spaceModel: spaceModel,
|
||||||
TagHelper.createInitialSelectedProducts(
|
initialTags: TagHelper.generateInitialTags(
|
||||||
spaceModel?.tags ?? [], subspaces),
|
subspaces: subspaces,
|
||||||
spaceName: spaceModel?.modelName ?? '',
|
spaceTagModels: spaceModel?.tags ?? []),
|
||||||
onUpdate: (tags, subspaces) {
|
title: 'Edit Device',
|
||||||
onLoad?.call(tags, subspaces);
|
addedProducts:
|
||||||
}),
|
TagHelper.createInitialSelectedProducts(
|
||||||
);
|
spaceModel?.tags ?? [], subspaces),
|
||||||
|
spaceName: spaceModel?.modelName ?? '',
|
||||||
|
));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: Chip(
|
child: Chip(
|
||||||
@ -129,6 +128,8 @@ class TagChipDisplay extends StatelessWidget {
|
|||||||
)
|
)
|
||||||
: TextButton(
|
: TextButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
|
||||||
await showDialog<bool>(
|
await showDialog<bool>(
|
||||||
barrierDismissible: false,
|
barrierDismissible: false,
|
||||||
context: context,
|
context: context,
|
||||||
@ -137,13 +138,9 @@ class TagChipDisplay extends StatelessWidget {
|
|||||||
subspaces: subspaces,
|
subspaces: subspaces,
|
||||||
allTags: allTags,
|
allTags: allTags,
|
||||||
spaceName: spaceNameController.text,
|
spaceName: spaceNameController.text,
|
||||||
|
pageContext: pageContext,
|
||||||
isCreate: true,
|
isCreate: true,
|
||||||
onUpdate: (tags, subspaces) {
|
spaceModel: spaceModel,
|
||||||
onLoad?.call(tags, subspaces);
|
|
||||||
},
|
|
||||||
onLoad: (tags, subspaces) {
|
|
||||||
onLoad?.call(tags, subspaces);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -5,8 +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/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/product_model.dart';
|
||||||
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/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/subspace_template_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/space_model/models/tag_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/space_model/models/tag_model.dart';
|
||||||
|
import 'package:syncrow_web/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_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_model_state.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/tag_model/bloc/add_device_type_model_event.dart';
|
import 'package:syncrow_web/pages/spaces_management/tag_model/bloc/add_device_type_model_event.dart';
|
||||||
@ -21,28 +23,25 @@ class AddDeviceTypeModelWidget extends StatelessWidget {
|
|||||||
final List<String>? allTags;
|
final List<String>? allTags;
|
||||||
final String spaceName;
|
final String spaceName;
|
||||||
final bool isCreate;
|
final bool isCreate;
|
||||||
final void Function(
|
final List<String>? otherSpaceModels;
|
||||||
List<TagModel>? tags, List<SubspaceTemplateModel>? subspaces)? onLoad;
|
final BuildContext? pageContext;
|
||||||
final void Function(
|
final SpaceTemplateModel? spaceModel;
|
||||||
List<TagModel>? tags, List<SubspaceTemplateModel>? subspaces)? onUpdate;
|
|
||||||
|
|
||||||
const AddDeviceTypeModelWidget({
|
const AddDeviceTypeModelWidget(
|
||||||
super.key,
|
{super.key,
|
||||||
this.products,
|
this.products,
|
||||||
this.initialSelectedProducts,
|
this.initialSelectedProducts,
|
||||||
this.subspaces,
|
this.subspaces,
|
||||||
this.allTags,
|
this.allTags,
|
||||||
this.spaceTagModels,
|
this.spaceTagModels,
|
||||||
required this.spaceName,
|
required this.spaceName,
|
||||||
required this.isCreate,
|
required this.isCreate,
|
||||||
this.onLoad,
|
this.pageContext,
|
||||||
this.onUpdate,
|
this.otherSpaceModels,
|
||||||
});
|
this.spaceModel});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|
||||||
|
|
||||||
final size = MediaQuery.of(context).size;
|
final size = MediaQuery.of(context).size;
|
||||||
final crossAxisCount = size.width > 1200
|
final crossAxisCount = size.width > 1200
|
||||||
? 8
|
? 8
|
||||||
@ -79,6 +78,7 @@ class AddDeviceTypeModelWidget extends StatelessWidget {
|
|||||||
padding:
|
padding:
|
||||||
const EdgeInsets.symmetric(horizontal: 20.0),
|
const EdgeInsets.symmetric(horizontal: 20.0),
|
||||||
child: ScrollableGridViewWidget(
|
child: ScrollableGridViewWidget(
|
||||||
|
isCreate: isCreate,
|
||||||
products: products,
|
products: products,
|
||||||
crossAxisCount: crossAxisCount,
|
crossAxisCount: crossAxisCount,
|
||||||
initialProductCounts: state.selectedProducts,
|
initialProductCounts: state.selectedProducts,
|
||||||
@ -102,6 +102,44 @@ class AddDeviceTypeModelWidget extends StatelessWidget {
|
|||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
if (isCreate) {
|
if (isCreate) {
|
||||||
Navigator.of(context).pop();
|
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,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -142,10 +180,10 @@ class AddDeviceTypeModelWidget extends StatelessWidget {
|
|||||||
allTags: allTags,
|
allTags: allTags,
|
||||||
spaceName: spaceName,
|
spaceName: spaceName,
|
||||||
initialTags: state.initialTag,
|
initialTags: state.initialTag,
|
||||||
|
otherSpaceModels: otherSpaceModels,
|
||||||
title: dialogTitle,
|
title: dialogTitle,
|
||||||
onUpdate: (tags, subspaces) {
|
spaceModel: spaceModel,
|
||||||
onUpdate?.call(tags, subspaces);
|
pageContext: pageContext,
|
||||||
},
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -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,6 +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: isCreate,
|
||||||
initialCount: selectedProduct.count,
|
initialCount: selectedProduct.count,
|
||||||
onCountChanged: (newCount) {
|
onCountChanged: (newCount) {
|
||||||
context.read<AddDeviceTypeModelBloc>().add(
|
context.read<AddDeviceTypeModelBloc>().add(
|
||||||
|
@ -10,12 +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
|
||||||
@ -30,7 +32,7 @@ class ScrollableGridViewWidget extends StatelessWidget {
|
|||||||
final productCounts = state is AddDeviceModelLoaded
|
final productCounts = state is AddDeviceModelLoaded
|
||||||
? state.selectedProducts
|
? state.selectedProducts
|
||||||
: <SelectedProduct>[];
|
: <SelectedProduct>[];
|
||||||
|
|
||||||
return GridView.builder(
|
return GridView.builder(
|
||||||
controller: scrollController,
|
controller: scrollController,
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
@ -47,6 +49,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,
|
||||||
|
@ -34,6 +34,20 @@ class SpaceModelManagementApi {
|
|||||||
return response;
|
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 {
|
Future<SpaceTemplateModel?> getSpaceModel(String spaceModelUuid) async {
|
||||||
final response = await HTTPService().get(
|
final response = await HTTPService().get(
|
||||||
path: ApiEndpoints.getSpaceModel
|
path: ApiEndpoints.getSpaceModel
|
||||||
|
@ -101,8 +101,11 @@ abstract class ApiEndpoints {
|
|||||||
//space model
|
//space model
|
||||||
static const String listSpaceModels = '/projects/{projectId}/space-models';
|
static const String listSpaceModels = '/projects/{projectId}/space-models';
|
||||||
static const String createSpaceModel = '/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 roleTypes = '/role/types';
|
||||||
static const String permission = '/permission/{roleUuid}';
|
static const String permission = '/permission/{roleUuid}';
|
||||||
static const String inviteUser = '/invite-user';
|
static const String inviteUser = '/invite-user';
|
||||||
|
Reference in New Issue
Block a user