mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-10 15:17:31 +00:00
updated tag issue for subspace
This commit is contained in:
39
lib/common/edit_chip.dart
Normal file
39
lib/common/edit_chip.dart
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
|
||||||
|
class EditChip extends StatelessWidget {
|
||||||
|
final String label;
|
||||||
|
final VoidCallback onTap;
|
||||||
|
final Color labelColor;
|
||||||
|
final Color backgroundColor;
|
||||||
|
final Color borderColor;
|
||||||
|
final double borderRadius;
|
||||||
|
|
||||||
|
const EditChip({
|
||||||
|
Key? key,
|
||||||
|
this.label = 'Edit',
|
||||||
|
required this.onTap,
|
||||||
|
this.labelColor = ColorsManager.spaceColor,
|
||||||
|
this.backgroundColor = ColorsManager.whiteColors,
|
||||||
|
this.borderColor = ColorsManager.spaceColor,
|
||||||
|
this.borderRadius = 16.0,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: onTap,
|
||||||
|
child: Chip(
|
||||||
|
label: Text(
|
||||||
|
label,
|
||||||
|
style: TextStyle(color: labelColor),
|
||||||
|
),
|
||||||
|
backgroundColor: backgroundColor,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(borderRadius),
|
||||||
|
side: BorderSide(color: borderColor),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
26
lib/pages/spaces_management/all_spaces/model/base_tag.dart
Normal file
26
lib/pages/spaces_management/all_spaces/model/base_tag.dart
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/product_model.dart';
|
||||||
|
import 'package:uuid/uuid.dart';
|
||||||
|
|
||||||
|
abstract class BaseTag {
|
||||||
|
String? uuid;
|
||||||
|
String? tag;
|
||||||
|
final ProductModel? product;
|
||||||
|
String internalId;
|
||||||
|
String? location;
|
||||||
|
|
||||||
|
BaseTag({
|
||||||
|
this.uuid,
|
||||||
|
required this.tag,
|
||||||
|
this.product,
|
||||||
|
String? internalId,
|
||||||
|
this.location,
|
||||||
|
}) : internalId = internalId ?? const Uuid().v4();
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson();
|
||||||
|
BaseTag copyWith({
|
||||||
|
String? tag,
|
||||||
|
ProductModel? product,
|
||||||
|
String? location,
|
||||||
|
String? internalId,
|
||||||
|
});
|
||||||
|
}
|
@ -1,22 +1,23 @@
|
|||||||
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/base_tag.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/create_space_template_body_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/space_model/models/create_space_template_body_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/space_model/models/tag_body_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/space_model/models/tag_body_model.dart';
|
||||||
import 'package:uuid/uuid.dart';
|
import 'package:uuid/uuid.dart';
|
||||||
|
|
||||||
class Tag {
|
class Tag extends BaseTag {
|
||||||
String? uuid;
|
Tag({
|
||||||
String? tag;
|
String? uuid,
|
||||||
final ProductModel? product;
|
required String? tag,
|
||||||
String internalId;
|
ProductModel? product,
|
||||||
String? location;
|
String? internalId,
|
||||||
|
String? location,
|
||||||
Tag(
|
}) : super(
|
||||||
{this.uuid,
|
uuid: uuid,
|
||||||
required this.tag,
|
tag: tag,
|
||||||
this.product,
|
product: product,
|
||||||
String? internalId,
|
internalId: internalId,
|
||||||
this.location})
|
location: location,
|
||||||
: internalId = internalId ?? const Uuid().v4();
|
);
|
||||||
|
|
||||||
factory Tag.fromJson(Map<String, dynamic> json) {
|
factory Tag.fromJson(Map<String, dynamic> json) {
|
||||||
final String internalId = json['internalId'] ?? const Uuid().v4();
|
final String internalId = json['internalId'] ?? const Uuid().v4();
|
||||||
@ -31,15 +32,19 @@ class Tag {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
Tag copyWith({
|
Tag copyWith({
|
||||||
String? tag,
|
String? tag,
|
||||||
ProductModel? product,
|
ProductModel? product,
|
||||||
String? location,
|
String? location,
|
||||||
|
String? internalId,
|
||||||
}) {
|
}) {
|
||||||
return Tag(
|
return Tag(
|
||||||
|
uuid: uuid,
|
||||||
tag: tag ?? this.tag,
|
tag: tag ?? this.tag,
|
||||||
product: product ?? this.product,
|
product: product ?? this.product,
|
||||||
location: location ?? this.location,
|
location: location ?? this.location,
|
||||||
|
internalId: internalId ?? this.internalId,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,7 +65,7 @@ extension TagModelExtensions on Tag {
|
|||||||
..productUuid = product?.uuid;
|
..productUuid = product?.uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
CreateTagBodyModel toCreateTagBodyModel() {
|
CreateTagBodyModel toCreateTagBodyModel() {
|
||||||
return CreateTagBodyModel()
|
return CreateTagBodyModel()
|
||||||
..tag = tag ?? ''
|
..tag = tag ?? ''
|
||||||
..productUuid = product?.uuid;
|
..productUuid = product?.uuid;
|
||||||
|
@ -344,6 +344,7 @@ class _CommunityStructureAreaState extends State<CommunityStructureArea> {
|
|||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
return CreateSpaceDialog(
|
return CreateSpaceDialog(
|
||||||
products: widget.products,
|
products: widget.products,
|
||||||
|
spaceModels: widget.spaceModels,
|
||||||
name: space.name,
|
name: space.name,
|
||||||
icon: space.icon,
|
icon: space.icon,
|
||||||
editSpace: space,
|
editSpace: space,
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
import 'package:syncrow_web/common/edit_chip.dart';
|
||||||
import 'package:syncrow_web/pages/common/buttons/cancel_button.dart';
|
import 'package:syncrow_web/pages/common/buttons/cancel_button.dart';
|
||||||
import 'package:syncrow_web/pages/common/buttons/default_button.dart';
|
import 'package:syncrow_web/pages/common/buttons/default_button.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/add_device_type/views/add_device_type_widget.dart';
|
import 'package:syncrow_web/pages/spaces_management/add_device_type/views/add_device_type_widget.dart';
|
||||||
@ -10,15 +11,23 @@ import 'package:syncrow_web/pages/spaces_management/all_spaces/model/subspace_mo
|
|||||||
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/tag.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/tag.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/all_spaces/widgets/dialogs/icon_selection_dialog.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/widgets/dialogs/icon_selection_dialog.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/create_subspace/views/create_subspace_model_dialog.dart';
|
import 'package:syncrow_web/pages/spaces_management/create_subspace/views/create_subspace_model_dialog.dart';
|
||||||
|
import 'package:syncrow_web/pages/spaces_management/helper/tag_helper.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/link_space_model/view/link_space_model_dialog.dart';
|
import 'package:syncrow_web/pages/spaces_management/link_space_model/view/link_space_model_dialog.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/button_content_widget.dart';
|
||||||
|
import 'package:syncrow_web/pages/spaces_management/space_model/widgets/subspace_name_label_widget.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||||
import 'package:syncrow_web/utils/constants/space_icon_const.dart';
|
import 'package:syncrow_web/utils/constants/space_icon_const.dart';
|
||||||
|
|
||||||
class CreateSpaceDialog extends StatefulWidget {
|
class CreateSpaceDialog extends StatefulWidget {
|
||||||
final Function(String, String, List<SelectedProduct> selectedProducts,
|
final Function(
|
||||||
SpaceTemplateModel? spaceModel, List<SubspaceModel>? subspaces, List<Tag>? tags) onCreateSpace;
|
String,
|
||||||
|
String,
|
||||||
|
List<SelectedProduct> selectedProducts,
|
||||||
|
SpaceTemplateModel? spaceModel,
|
||||||
|
List<SubspaceModel>? subspaces,
|
||||||
|
List<Tag>? tags) onCreateSpace;
|
||||||
final List<ProductModel>? products;
|
final List<ProductModel>? products;
|
||||||
final String? name;
|
final String? name;
|
||||||
final String? icon;
|
final String? icon;
|
||||||
@ -211,42 +220,13 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
|
|||||||
),
|
),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
selectedSpaceModel == null
|
selectedSpaceModel == null
|
||||||
? DefaultButton(
|
? TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
_showLinkSpaceModelDialog(context);
|
_showLinkSpaceModelDialog(context);
|
||||||
},
|
},
|
||||||
backgroundColor: ColorsManager.textFieldGreyColor,
|
child: const ButtonContentWidget(
|
||||||
foregroundColor: Colors.black,
|
svgAssets: Assets.link,
|
||||||
borderColor: ColorsManager.neutralGray,
|
label: 'Link a space model',
|
||||||
borderRadius: 16.0,
|
|
||||||
padding: 10.0, // Reduced padding for smaller size
|
|
||||||
child: Align(
|
|
||||||
alignment: Alignment.centerLeft,
|
|
||||||
child: Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(left: 6.0),
|
|
||||||
child: SvgPicture.asset(
|
|
||||||
Assets.link,
|
|
||||||
width: screenWidth *
|
|
||||||
0.015, // Adjust icon size
|
|
||||||
height: screenWidth * 0.015,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(width: 3),
|
|
||||||
Flexible(
|
|
||||||
child: Text(
|
|
||||||
'Link a space model',
|
|
||||||
overflow: TextOverflow
|
|
||||||
.ellipsis, // Prevent overflow
|
|
||||||
style: Theme.of(context)
|
|
||||||
.textTheme
|
|
||||||
.bodyMedium,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: Container(
|
: Container(
|
||||||
@ -307,7 +287,7 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.symmetric(horizontal: 8.0),
|
padding: EdgeInsets.symmetric(horizontal: 6.0),
|
||||||
child: Text(
|
child: Text(
|
||||||
'OR',
|
'OR',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
@ -326,47 +306,21 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
|
|||||||
),
|
),
|
||||||
const SizedBox(height: 25),
|
const SizedBox(height: 25),
|
||||||
subspaces == null
|
subspaces == null
|
||||||
? DefaultButton(
|
? TextButton(
|
||||||
onPressed: () {
|
style: TextButton.styleFrom(
|
||||||
|
overlayColor: ColorsManager.transparentColor,
|
||||||
|
),
|
||||||
|
onPressed: () async {
|
||||||
_showSubSpaceDialog(context, enteredName, [],
|
_showSubSpaceDialog(context, enteredName, [],
|
||||||
false, widget.products, subspaces);
|
false, widget.products, subspaces);
|
||||||
},
|
},
|
||||||
backgroundColor: ColorsManager.textFieldGreyColor,
|
child: const ButtonContentWidget(
|
||||||
foregroundColor: Colors.black,
|
icon: Icons.add,
|
||||||
borderColor: ColorsManager.neutralGray,
|
label: 'Create Sub Space',
|
||||||
borderRadius: 16.0,
|
|
||||||
padding: 10.0, // Reduced padding for smaller size
|
|
||||||
child: Align(
|
|
||||||
alignment: Alignment.centerLeft,
|
|
||||||
child: Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(left: 6.0),
|
|
||||||
child: SvgPicture.asset(
|
|
||||||
Assets.addIcon,
|
|
||||||
width: screenWidth *
|
|
||||||
0.015, // Adjust icon size
|
|
||||||
height: screenWidth * 0.015,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(width: 3),
|
|
||||||
Flexible(
|
|
||||||
child: Text(
|
|
||||||
'Create sub space',
|
|
||||||
overflow: TextOverflow
|
|
||||||
.ellipsis, // Prevent overflow
|
|
||||||
style: Theme.of(context)
|
|
||||||
.textTheme
|
|
||||||
.bodyMedium,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: SizedBox(
|
: SizedBox(
|
||||||
width: screenWidth * 0.35,
|
width: screenWidth * 0.25,
|
||||||
child: Container(
|
child: Container(
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
@ -383,49 +337,15 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
|
|||||||
children: [
|
children: [
|
||||||
if (subspaces != null)
|
if (subspaces != null)
|
||||||
...subspaces!.map(
|
...subspaces!.map(
|
||||||
(subspace) => Chip(
|
(subspace) => SubspaceNameDisplayWidget(
|
||||||
label: Text(
|
text: subspace.subspaceName,
|
||||||
subspace.subspaceName,
|
)),
|
||||||
style: const TextStyle(
|
EditChip(
|
||||||
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
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
GestureDetector(
|
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
_showSubSpaceDialog(
|
_showSubSpaceDialog(context, enteredName,
|
||||||
context,
|
[], true, widget.products, subspaces);
|
||||||
enteredName,
|
|
||||||
[],
|
|
||||||
false,
|
|
||||||
widget.products,
|
|
||||||
subspaces);
|
|
||||||
},
|
},
|
||||||
child: Chip(
|
)
|
||||||
label: const Text(
|
|
||||||
'Edit',
|
|
||||||
style: TextStyle(
|
|
||||||
color: ColorsManager.spaceColor),
|
|
||||||
),
|
|
||||||
backgroundColor:
|
|
||||||
ColorsManager.whiteColors,
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.circular(16),
|
|
||||||
side: const BorderSide(
|
|
||||||
color: ColorsManager.spaceColor),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -452,7 +372,7 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
|
|||||||
runSpacing: 8.0,
|
runSpacing: 8.0,
|
||||||
children: [
|
children: [
|
||||||
// Combine tags from spaceModel and subspaces
|
// Combine tags from spaceModel and subspaces
|
||||||
..._groupTags([
|
...TagHelper.groupTags([
|
||||||
...?tags,
|
...?tags,
|
||||||
...?subspaces?.expand(
|
...?subspaces?.expand(
|
||||||
(subspace) => subspace.tags ?? [])
|
(subspace) => subspace.tags ?? [])
|
||||||
@ -484,70 +404,31 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
GestureDetector(
|
|
||||||
onTap: () async {
|
EditChip(onTap: () async {
|
||||||
_showTagCreateDialog(context, enteredName,
|
_showTagCreateDialog(
|
||||||
widget.products);
|
context,
|
||||||
// Edit action
|
enteredName,
|
||||||
},
|
widget.products,
|
||||||
child: Chip(
|
);
|
||||||
label: const Text(
|
// Edit action
|
||||||
'Edit',
|
})
|
||||||
style: TextStyle(
|
|
||||||
color: ColorsManager.spaceColor),
|
|
||||||
),
|
|
||||||
backgroundColor:
|
|
||||||
ColorsManager.whiteColors,
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.circular(16),
|
|
||||||
side: const BorderSide(
|
|
||||||
color: ColorsManager.spaceColor),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: DefaultButton(
|
: TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
_showTagCreateDialog(
|
_showTagCreateDialog(
|
||||||
context, enteredName, widget.products);
|
context, enteredName, widget.products);
|
||||||
},
|
},
|
||||||
backgroundColor: ColorsManager.textFieldGreyColor,
|
style: TextButton.styleFrom(
|
||||||
foregroundColor: Colors.black,
|
padding: EdgeInsets.zero,
|
||||||
borderColor: ColorsManager.neutralGray,
|
|
||||||
borderRadius: 16.0,
|
|
||||||
padding: 10.0, // Reduced padding for smaller size
|
|
||||||
child: Align(
|
|
||||||
alignment: Alignment.centerLeft,
|
|
||||||
child: Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(left: 6.0),
|
|
||||||
child: SvgPicture.asset(
|
|
||||||
Assets.addIcon,
|
|
||||||
width: screenWidth *
|
|
||||||
0.015, // Adjust icon size
|
|
||||||
height: screenWidth * 0.015,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(width: 3),
|
|
||||||
Flexible(
|
|
||||||
child: Text(
|
|
||||||
'Add devices',
|
|
||||||
overflow: TextOverflow
|
|
||||||
.ellipsis, // Prevent overflow
|
|
||||||
style: Theme.of(context)
|
|
||||||
.textTheme
|
|
||||||
.bodyMedium,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
)
|
child: const ButtonContentWidget(
|
||||||
|
icon: Icons.add,
|
||||||
|
label: 'Add Devices',
|
||||||
|
))
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -579,8 +460,13 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
|
|||||||
? enteredName
|
? enteredName
|
||||||
: (widget.name ?? '');
|
: (widget.name ?? '');
|
||||||
if (newName.isNotEmpty) {
|
if (newName.isNotEmpty) {
|
||||||
widget.onCreateSpace(newName, selectedIcon,
|
widget.onCreateSpace(
|
||||||
selectedProducts, selectedSpaceModel,subspaces,tags);
|
newName,
|
||||||
|
selectedIcon,
|
||||||
|
selectedProducts,
|
||||||
|
selectedSpaceModel,
|
||||||
|
subspaces,
|
||||||
|
tags);
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -655,7 +541,7 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
|
|||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
return CreateSubSpaceDialog(
|
return CreateSubSpaceDialog(
|
||||||
spaceName: name,
|
spaceName: name,
|
||||||
dialogTitle: 'Create Sub-space',
|
dialogTitle: isEdit ? 'Edit Sub-space' : 'Create Sub-space',
|
||||||
spaceTags: spaceTags,
|
spaceTags: spaceTags,
|
||||||
isEdit: isEdit,
|
isEdit: isEdit,
|
||||||
products: products,
|
products: products,
|
||||||
|
@ -29,6 +29,7 @@ class AssignTagModelsDialog extends StatelessWidget {
|
|||||||
final String title;
|
final String title;
|
||||||
final BuildContext? pageContext;
|
final BuildContext? pageContext;
|
||||||
final List<String>? otherSpaceModels;
|
final List<String>? otherSpaceModels;
|
||||||
|
final List<SpaceTemplateModel>? allSpaceModels;
|
||||||
|
|
||||||
const AssignTagModelsDialog(
|
const AssignTagModelsDialog(
|
||||||
{Key? key,
|
{Key? key,
|
||||||
@ -42,7 +43,8 @@ class AssignTagModelsDialog extends StatelessWidget {
|
|||||||
required this.title,
|
required this.title,
|
||||||
this.pageContext,
|
this.pageContext,
|
||||||
this.otherSpaceModels,
|
this.otherSpaceModels,
|
||||||
this.spaceModel})
|
this.spaceModel,
|
||||||
|
this.allSpaceModels})
|
||||||
: super(key: key);
|
: super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -212,8 +214,8 @@ class AssignTagModelsDialog extends StatelessWidget {
|
|||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
child: DialogDropdown(
|
child: DialogDropdown(
|
||||||
items: locations,
|
items: locations,
|
||||||
selectedValue:
|
selectedValue: tag.location ??
|
||||||
tag.location ?? 'Main Space',
|
'Main Space',
|
||||||
onSelected: (value) {
|
onSelected: (value) {
|
||||||
context
|
context
|
||||||
.read<
|
.read<
|
||||||
@ -250,8 +252,7 @@ class AssignTagModelsDialog extends StatelessWidget {
|
|||||||
label: 'Add New Device',
|
label: 'Add New Device',
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
for (var tag in state.tags) {
|
for (var tag in state.tags) {
|
||||||
if (tag.location == null ||
|
if (tag.location == null) {
|
||||||
subspaces == null) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -352,6 +353,7 @@ class AssignTagModelsDialog extends StatelessWidget {
|
|||||||
builder: (BuildContext dialogContext) {
|
builder: (BuildContext dialogContext) {
|
||||||
return CreateSpaceModelDialog(
|
return CreateSpaceModelDialog(
|
||||||
products: products,
|
products: products,
|
||||||
|
allSpaceModels: allSpaceModels,
|
||||||
allTags: allTags,
|
allTags: allTags,
|
||||||
pageContext: pageContext,
|
pageContext: pageContext,
|
||||||
otherSpaceModels: otherSpaceModels,
|
otherSpaceModels: otherSpaceModels,
|
||||||
|
@ -6,18 +6,23 @@ import 'subspace_event.dart';
|
|||||||
import 'subspace_state.dart';
|
import 'subspace_state.dart';
|
||||||
|
|
||||||
class SubSpaceBloc extends Bloc<SubSpaceEvent, SubSpaceState> {
|
class SubSpaceBloc extends Bloc<SubSpaceEvent, SubSpaceState> {
|
||||||
SubSpaceBloc() : super(SubSpaceState([], [], '')) {
|
SubSpaceBloc() : super(SubSpaceState([], [], '',{})) {
|
||||||
on<AddSubSpace>((event, emit) {
|
on<AddSubSpace>((event, emit) {
|
||||||
final existingNames =
|
final existingNames = state.subSpaces.map((e) => e.subspaceName).toSet();
|
||||||
state.subSpaces.map((e) => e.subspaceName).toSet();
|
|
||||||
|
|
||||||
if (existingNames.contains(event.subSpace.subspaceName.toLowerCase())) {
|
if (existingNames.contains(event.subSpace.subspaceName.toLowerCase())) {
|
||||||
|
final updatedDuplicates = Set<String>.from(state.duplicates)
|
||||||
|
..add(event.subSpace.subspaceName.toLowerCase());
|
||||||
|
final updatedSubSpaces = List<SubspaceModel>.from(state.subSpaces)
|
||||||
|
..add(event.subSpace);
|
||||||
emit(SubSpaceState(
|
emit(SubSpaceState(
|
||||||
state.subSpaces,
|
updatedSubSpaces,
|
||||||
state.updatedSubSpaceModels,
|
state.updatedSubSpaceModels,
|
||||||
'Subspace name already exists.',
|
'*Duplicated sub-space name',
|
||||||
|
updatedDuplicates,
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
|
// Add subspace if no duplicate exists
|
||||||
final updatedSubSpaces = List<SubspaceModel>.from(state.subSpaces)
|
final updatedSubSpaces = List<SubspaceModel>.from(state.subSpaces)
|
||||||
..add(event.subSpace);
|
..add(event.subSpace);
|
||||||
|
|
||||||
@ -25,6 +30,8 @@ class SubSpaceBloc extends Bloc<SubSpaceEvent, SubSpaceState> {
|
|||||||
updatedSubSpaces,
|
updatedSubSpaces,
|
||||||
state.updatedSubSpaceModels,
|
state.updatedSubSpaceModels,
|
||||||
'',
|
'',
|
||||||
|
state.duplicates,
|
||||||
|
// Clear error message
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -38,6 +45,16 @@ class SubSpaceBloc extends Bloc<SubSpaceEvent, SubSpaceState> {
|
|||||||
state.updatedSubSpaceModels,
|
state.updatedSubSpaceModels,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
final nameOccurrences = <String, int>{};
|
||||||
|
for (final subSpace in updatedSubSpaces) {
|
||||||
|
final lowerName = subSpace.subspaceName.toLowerCase();
|
||||||
|
nameOccurrences[lowerName] = (nameOccurrences[lowerName] ?? 0) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
final updatedDuplicates = nameOccurrences.entries
|
||||||
|
.where((entry) => entry.value > 1)
|
||||||
|
.map((entry) => entry.key)
|
||||||
|
.toSet();
|
||||||
if (event.subSpace.uuid?.isNotEmpty ?? false) {
|
if (event.subSpace.uuid?.isNotEmpty ?? false) {
|
||||||
updatedSubspaceModels.add(UpdateSubspaceModel(
|
updatedSubspaceModels.add(UpdateSubspaceModel(
|
||||||
action: Action.delete,
|
action: Action.delete,
|
||||||
@ -45,13 +62,36 @@ class SubSpaceBloc extends Bloc<SubSpaceEvent, SubSpaceState> {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
emit(SubSpaceState(
|
emit(SubSpaceState(updatedSubSpaces, updatedSubspaceModels, '',
|
||||||
updatedSubSpaces,
|
updatedDuplicates // Clear error message
|
||||||
updatedSubspaceModels,
|
));
|
||||||
'', // Clear error message
|
|
||||||
));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Handle UpdateSubSpace Event
|
// Handle UpdateSubSpace Event
|
||||||
|
|
||||||
|
on<UpdateSubSpace>((event, emit) {
|
||||||
|
final updatedSubSpaces = state.subSpaces.map((subSpace) {
|
||||||
|
if (subSpace.uuid == event.updatedSubSpace.uuid) {
|
||||||
|
return event.updatedSubSpace;
|
||||||
|
}
|
||||||
|
return subSpace;
|
||||||
|
}).toList();
|
||||||
|
|
||||||
|
final updatedSubspaceModels = List<UpdateSubspaceModel>.from(
|
||||||
|
state.updatedSubSpaceModels,
|
||||||
|
);
|
||||||
|
|
||||||
|
updatedSubspaceModels.add(UpdateSubspaceModel(
|
||||||
|
action: Action.update,
|
||||||
|
uuid: event.updatedSubSpace.uuid!,
|
||||||
|
));
|
||||||
|
|
||||||
|
emit(SubSpaceState(
|
||||||
|
updatedSubSpaces,
|
||||||
|
updatedSubspaceModels,
|
||||||
|
'',
|
||||||
|
state.duplicates,
|
||||||
|
));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,23 +4,26 @@ class SubSpaceState {
|
|||||||
final List<SubspaceModel> subSpaces;
|
final List<SubspaceModel> subSpaces;
|
||||||
final List<UpdateSubspaceModel> updatedSubSpaceModels;
|
final List<UpdateSubspaceModel> updatedSubSpaceModels;
|
||||||
final String errorMessage;
|
final String errorMessage;
|
||||||
|
final Set<String> duplicates;
|
||||||
|
|
||||||
SubSpaceState(
|
SubSpaceState(
|
||||||
this.subSpaces,
|
this.subSpaces,
|
||||||
this.updatedSubSpaceModels,
|
this.updatedSubSpaceModels,
|
||||||
this.errorMessage,
|
this.errorMessage,
|
||||||
|
this.duplicates,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
SubSpaceState copyWith({
|
SubSpaceState copyWith({
|
||||||
List<SubspaceModel>? subSpaces,
|
List<SubspaceModel>? subSpaces,
|
||||||
List<UpdateSubspaceModel>? updatedSubSpaceModels,
|
List<UpdateSubspaceModel>? updatedSubSpaceModels,
|
||||||
String? errorMessage,
|
String? errorMessage,
|
||||||
|
Set<String>? duplicates,
|
||||||
}) {
|
}) {
|
||||||
return SubSpaceState(
|
return SubSpaceState(
|
||||||
subSpaces ?? this.subSpaces,
|
subSpaces ?? this.subSpaces,
|
||||||
updatedSubSpaceModels ?? this.updatedSubSpaceModels,
|
updatedSubSpaceModels ?? this.updatedSubSpaceModels,
|
||||||
errorMessage ?? this.errorMessage,
|
errorMessage ?? this.errorMessage,
|
||||||
|
duplicates ?? this.duplicates,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,41 +81,64 @@ class CreateSubSpaceDialog extends StatelessWidget {
|
|||||||
spacing: 8.0,
|
spacing: 8.0,
|
||||||
runSpacing: 8.0,
|
runSpacing: 8.0,
|
||||||
children: [
|
children: [
|
||||||
...state.subSpaces.map(
|
...state.subSpaces.asMap().entries.map(
|
||||||
(subSpace) => Chip(
|
(entry) {
|
||||||
label: Text(
|
final index = entry.key;
|
||||||
subSpace.subspaceName,
|
final subSpace = entry.value;
|
||||||
style: const TextStyle(
|
|
||||||
color: ColorsManager.spaceColor),
|
final lowerName =
|
||||||
),
|
subSpace.subspaceName.toLowerCase();
|
||||||
backgroundColor: ColorsManager.whiteColors,
|
|
||||||
shape: RoundedRectangleBorder(
|
final duplicateIndices = state.subSpaces
|
||||||
borderRadius: BorderRadius.circular(8),
|
.asMap()
|
||||||
side: const BorderSide(
|
.entries
|
||||||
color: ColorsManager.transparentColor,
|
.where((e) =>
|
||||||
width: 0,
|
e.value.subspaceName.toLowerCase() ==
|
||||||
),
|
lowerName)
|
||||||
),
|
.map((e) => e.key)
|
||||||
deleteIcon: Container(
|
.toList();
|
||||||
width: 24,
|
final isDuplicate =
|
||||||
height: 24,
|
duplicateIndices.length > 1 &&
|
||||||
decoration: BoxDecoration(
|
duplicateIndices.indexOf(index) != 0;
|
||||||
shape: BoxShape.circle,
|
|
||||||
border: Border.all(
|
return Chip(
|
||||||
color: ColorsManager.lightGrayColor,
|
label: Text(
|
||||||
width: 1.5,
|
subSpace.subspaceName,
|
||||||
|
style: const TextStyle(
|
||||||
|
color: ColorsManager.spaceColor,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: const Icon(
|
backgroundColor: ColorsManager.whiteColors,
|
||||||
Icons.close,
|
shape: RoundedRectangleBorder(
|
||||||
size: 16,
|
borderRadius: BorderRadius.circular(10),
|
||||||
color: ColorsManager.lightGrayColor,
|
side: BorderSide(
|
||||||
|
color: isDuplicate
|
||||||
|
? ColorsManager.red
|
||||||
|
: ColorsManager.transparentColor,
|
||||||
|
width: 0,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
deleteIcon: Container(
|
||||||
onDeleted: () => context
|
width: 24,
|
||||||
.read<SubSpaceBloc>()
|
height: 24,
|
||||||
.add(RemoveSubSpace(subSpace)),
|
decoration: BoxDecoration(
|
||||||
),
|
shape: BoxShape.circle,
|
||||||
|
border: Border.all(
|
||||||
|
color: ColorsManager.lightGrayColor,
|
||||||
|
width: 1.5,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: const Icon(
|
||||||
|
Icons.close,
|
||||||
|
size: 16,
|
||||||
|
color: ColorsManager.lightGrayColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onDeleted: () => context
|
||||||
|
.read<SubSpaceBloc>()
|
||||||
|
.add(RemoveSubSpace(subSpace)),
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: 200,
|
width: 200,
|
||||||
@ -142,27 +165,29 @@ class CreateSubSpaceDialog extends StatelessWidget {
|
|||||||
color: ColorsManager.blackColor),
|
color: ColorsManager.blackColor),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (state.errorMessage.isNotEmpty)
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(top: 8.0),
|
|
||||||
child: Text(
|
|
||||||
state.errorMessage,
|
|
||||||
style: const TextStyle(
|
|
||||||
color: ColorsManager.warningRed,
|
|
||||||
fontSize: 12,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
if (state.errorMessage.isNotEmpty)
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 8.0),
|
||||||
|
child: Text(
|
||||||
|
state.errorMessage,
|
||||||
|
style: const TextStyle(
|
||||||
|
color: ColorsManager.warningRed,
|
||||||
|
fontSize: 12,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: CancelButton(
|
child: CancelButton(
|
||||||
label: 'Cancel',
|
label: 'Cancel',
|
||||||
onPressed: () async {},
|
onPressed: () async {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 10),
|
const SizedBox(width: 10),
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/base_tag.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/subspace_template_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/space_model/models/subspace_template_model.dart';
|
||||||
@ -33,7 +34,7 @@ class TagHelper {
|
|||||||
return initialTags;
|
return initialTags;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Map<ProductModel, int> groupTags(List<TagModel> tags) {
|
static Map<ProductModel, int> groupTags(List<BaseTag> tags) {
|
||||||
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) {
|
||||||
|
@ -301,7 +301,7 @@ class CreateSpaceModelBloc
|
|||||||
if (newTags != null || prevTags != null) {
|
if (newTags != null || prevTags != null) {
|
||||||
// Case 1: Tags deleted
|
// Case 1: Tags deleted
|
||||||
if (prevTags != null && newTags != null) {
|
if (prevTags != null && newTags != null) {
|
||||||
for (var prevTag in prevTags!) {
|
for (var prevTag in prevTags) {
|
||||||
final existsInNew =
|
final existsInNew =
|
||||||
newTags!.any((newTag) => newTag.uuid == prevTag.uuid);
|
newTags!.any((newTag) => newTag.uuid == prevTag.uuid);
|
||||||
if (!existsInNew) {
|
if (!existsInNew) {
|
||||||
|
@ -1,22 +1,22 @@
|
|||||||
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/base_tag.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/create_space_template_body_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/space_model/models/create_space_template_body_model.dart';
|
||||||
import 'package:uuid/uuid.dart';
|
import 'package:uuid/uuid.dart';
|
||||||
|
|
||||||
class TagModel {
|
class TagModel extends BaseTag {
|
||||||
String? uuid;
|
TagModel({
|
||||||
String? tag;
|
String? uuid,
|
||||||
final ProductModel? product;
|
required String? tag,
|
||||||
String internalId;
|
ProductModel? product,
|
||||||
String? location;
|
String? internalId,
|
||||||
|
String? location,
|
||||||
TagModel(
|
}) : super(
|
||||||
{this.uuid,
|
uuid: uuid,
|
||||||
required this.tag,
|
tag: tag,
|
||||||
this.product,
|
product: product,
|
||||||
String? internalId,
|
internalId: internalId,
|
||||||
this.location})
|
location: location,
|
||||||
: internalId = internalId ?? const Uuid().v4();
|
);
|
||||||
|
|
||||||
factory TagModel.fromJson(Map<String, dynamic> json) {
|
factory TagModel.fromJson(Map<String, dynamic> json) {
|
||||||
final String internalId = json['internalId'] ?? const Uuid().v4();
|
final String internalId = json['internalId'] ?? const Uuid().v4();
|
||||||
|
|
||||||
@ -30,16 +30,19 @@ class TagModel {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
TagModel copyWith(
|
TagModel copyWith(
|
||||||
{String? tag,
|
{String? tag,
|
||||||
ProductModel? product,
|
ProductModel? product,
|
||||||
|
String? uuid,
|
||||||
String? location,
|
String? location,
|
||||||
String? internalId}) {
|
String? internalId}) {
|
||||||
return TagModel(
|
return TagModel(
|
||||||
tag: tag ?? this.tag,
|
tag: tag ?? this.tag,
|
||||||
product: product ?? this.product,
|
product: product ?? this.product,
|
||||||
location: location ?? this.location,
|
location: location ?? this.location,
|
||||||
internalId: internalId ?? this.internalId,
|
internalId: internalId ?? this.internalId,
|
||||||
|
uuid:uuid?? this.uuid
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,7 +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);
|
final otherModel =
|
||||||
|
List<String>.from(allSpaceModelNames);
|
||||||
otherModel.remove(model.modelName);
|
otherModel.remove(model.modelName);
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
@ -76,6 +77,7 @@ class SpaceModelPage extends StatelessWidget {
|
|||||||
spaceModel: model,
|
spaceModel: model,
|
||||||
otherSpaceModels: otherModel,
|
otherSpaceModels: otherModel,
|
||||||
pageContext: context,
|
pageContext: context,
|
||||||
|
allSpaceModels: spaceModels,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_svg/svg.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
|
||||||
class ButtonContentWidget extends StatelessWidget {
|
class ButtonContentWidget extends StatelessWidget {
|
||||||
final IconData icon;
|
final IconData? icon;
|
||||||
final String label;
|
final String label;
|
||||||
|
final String? svgAssets;
|
||||||
|
|
||||||
const ButtonContentWidget({
|
const ButtonContentWidget(
|
||||||
Key? key,
|
{Key? key, this.icon, required this.label, this.svgAssets})
|
||||||
required this.icon,
|
: super(key: key);
|
||||||
required this.label,
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -30,10 +30,20 @@ class ButtonContentWidget extends StatelessWidget {
|
|||||||
padding: const EdgeInsets.symmetric(vertical: 10.0, horizontal: 16.0),
|
padding: const EdgeInsets.symmetric(vertical: 10.0, horizontal: 16.0),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Icon(
|
if (icon != null)
|
||||||
icon,
|
Icon(
|
||||||
color: ColorsManager.spaceColor,
|
icon,
|
||||||
),
|
color: ColorsManager.spaceColor,
|
||||||
|
),
|
||||||
|
if (svgAssets != null)
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 6.0),
|
||||||
|
child: SvgPicture.asset(
|
||||||
|
svgAssets!,
|
||||||
|
width: screenWidth * 0.015, // Adjust icon size
|
||||||
|
height: screenWidth * 0.015,
|
||||||
|
),
|
||||||
|
),
|
||||||
const SizedBox(width: 10),
|
const SizedBox(width: 10),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Text(
|
child: Text(
|
||||||
|
@ -22,6 +22,7 @@ class CreateSpaceModelDialog extends StatelessWidget {
|
|||||||
final SpaceTemplateModel? spaceModel;
|
final SpaceTemplateModel? spaceModel;
|
||||||
final BuildContext? pageContext;
|
final BuildContext? pageContext;
|
||||||
final List<String>? otherSpaceModels;
|
final List<String>? otherSpaceModels;
|
||||||
|
final List<SpaceTemplateModel>? allSpaceModels;
|
||||||
|
|
||||||
const CreateSpaceModelDialog(
|
const CreateSpaceModelDialog(
|
||||||
{Key? key,
|
{Key? key,
|
||||||
@ -29,7 +30,8 @@ class CreateSpaceModelDialog extends StatelessWidget {
|
|||||||
this.allTags,
|
this.allTags,
|
||||||
this.spaceModel,
|
this.spaceModel,
|
||||||
this.pageContext,
|
this.pageContext,
|
||||||
this.otherSpaceModels})
|
this.otherSpaceModels,
|
||||||
|
this.allSpaceModels})
|
||||||
: super(key: key);
|
: super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -138,6 +140,7 @@ class CreateSpaceModelDialog extends StatelessWidget {
|
|||||||
spaceNameController: spaceNameController,
|
spaceNameController: spaceNameController,
|
||||||
pageContext: pageContext,
|
pageContext: pageContext,
|
||||||
otherSpaceModels: otherSpaceModels,
|
otherSpaceModels: otherSpaceModels,
|
||||||
|
allSpaceModels: allSpaceModels,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
@ -147,7 +150,8 @@ class CreateSpaceModelDialog extends StatelessWidget {
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: CancelButton(
|
child: CancelButton(
|
||||||
label: 'Cancel',
|
label: 'Cancel',
|
||||||
onPressed: () => Navigator.of(context).pop(),
|
onPressed: (){
|
||||||
|
Navigator.of(context).pop();},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 10),
|
const SizedBox(width: 10),
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:syncrow_web/common/edit_chip.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/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/create_subspace_model/views/create_subspace_model_dialog.dart';
|
import 'package:syncrow_web/pages/spaces_management/create_subspace_model/views/create_subspace_model_dialog.dart';
|
||||||
|
import 'package:syncrow_web/pages/spaces_management/space_model/widgets/subspace_name_label_widget.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
|
||||||
class SubspaceModelCreate extends StatelessWidget {
|
class SubspaceModelCreate extends StatelessWidget {
|
||||||
@ -46,39 +48,13 @@ class SubspaceModelCreate extends StatelessWidget {
|
|||||||
spacing: 8.0,
|
spacing: 8.0,
|
||||||
runSpacing: 8.0,
|
runSpacing: 8.0,
|
||||||
children: [
|
children: [
|
||||||
...subspaces.map((subspace) => Container(
|
...subspaces.map((subspace) => SubspaceNameDisplayWidget(
|
||||||
padding: const EdgeInsets.symmetric(
|
text: subspace.subspaceName,
|
||||||
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: Theme.of(context)
|
|
||||||
.textTheme
|
|
||||||
.bodySmall
|
|
||||||
?.copyWith(color: ColorsManager.spaceColor),
|
|
||||||
),
|
|
||||||
)),
|
)),
|
||||||
GestureDetector(
|
EditChip(
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
await _openDialog(context, 'Edit Sub-space');
|
await _openDialog(context, 'Edit Sub-space');
|
||||||
},
|
},
|
||||||
child: Chip(
|
|
||||||
label: const Text(
|
|
||||||
'Edit',
|
|
||||||
style: TextStyle(color: ColorsManager.spaceColor),
|
|
||||||
),
|
|
||||||
backgroundColor: ColorsManager.whiteColors,
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.circular(16),
|
|
||||||
side:
|
|
||||||
const BorderSide(color: ColorsManager.spaceColor),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -0,0 +1,40 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class SubspaceNameDisplayWidget extends StatelessWidget {
|
||||||
|
final String text;
|
||||||
|
final TextStyle? textStyle;
|
||||||
|
final Color backgroundColor;
|
||||||
|
final Color borderColor;
|
||||||
|
final EdgeInsetsGeometry padding;
|
||||||
|
final BorderRadiusGeometry borderRadius;
|
||||||
|
|
||||||
|
const SubspaceNameDisplayWidget({
|
||||||
|
Key? key,
|
||||||
|
required this.text,
|
||||||
|
this.textStyle,
|
||||||
|
this.backgroundColor = Colors.white,
|
||||||
|
this.borderColor = Colors.transparent,
|
||||||
|
this.padding = const EdgeInsets.symmetric(horizontal: 8.0, vertical: 4.0),
|
||||||
|
this.borderRadius = const BorderRadius.all(Radius.circular(10)),
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
padding: padding,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: backgroundColor,
|
||||||
|
borderRadius: borderRadius,
|
||||||
|
border: Border.all(color: borderColor),
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
text,
|
||||||
|
style: textStyle ??
|
||||||
|
Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.bodySmall
|
||||||
|
?.copyWith(color: Colors.black),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
|
import 'package:syncrow_web/common/edit_chip.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/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/helper/tag_helper.dart';
|
import 'package:syncrow_web/pages/spaces_management/helper/tag_helper.dart';
|
||||||
@ -18,6 +19,7 @@ class TagChipDisplay extends StatelessWidget {
|
|||||||
final TextEditingController spaceNameController;
|
final TextEditingController spaceNameController;
|
||||||
final BuildContext? pageContext;
|
final BuildContext? pageContext;
|
||||||
final List<String>? otherSpaceModels;
|
final List<String>? otherSpaceModels;
|
||||||
|
final List<SpaceTemplateModel>? allSpaceModels;
|
||||||
|
|
||||||
const TagChipDisplay(BuildContext context,
|
const TagChipDisplay(BuildContext context,
|
||||||
{Key? key,
|
{Key? key,
|
||||||
@ -28,7 +30,8 @@ class TagChipDisplay extends StatelessWidget {
|
|||||||
required this.allTags,
|
required this.allTags,
|
||||||
required this.spaceNameController,
|
required this.spaceNameController,
|
||||||
this.pageContext,
|
this.pageContext,
|
||||||
this.otherSpaceModels})
|
this.otherSpaceModels,
|
||||||
|
this.allSpaceModels})
|
||||||
: super(key: key);
|
: super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -83,45 +86,31 @@ class TagChipDisplay extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
GestureDetector(
|
EditChip(onTap: () async {
|
||||||
onTap: () async {
|
// Use the Navigator's context for showDialog
|
||||||
// Use the Navigator's context for showDialog
|
Navigator.of(context).pop();
|
||||||
final navigatorContext =
|
|
||||||
Navigator.of(context).overlay?.context;
|
|
||||||
|
|
||||||
if (navigatorContext != null) {
|
await showDialog<bool>(
|
||||||
await showDialog<bool>(
|
barrierDismissible: false,
|
||||||
barrierDismissible: false,
|
context: context,
|
||||||
context: navigatorContext,
|
builder: (context) => AssignTagModelsDialog(
|
||||||
builder: (context) => AssignTagModelsDialog(
|
products: products,
|
||||||
products: products,
|
allSpaceModels: allSpaceModels,
|
||||||
|
subspaces: subspaces,
|
||||||
|
pageContext: pageContext,
|
||||||
|
allTags: allTags,
|
||||||
|
spaceModel: spaceModel,
|
||||||
|
otherSpaceModels: otherSpaceModels,
|
||||||
|
initialTags: TagHelper.generateInitialTags(
|
||||||
subspaces: subspaces,
|
subspaces: subspaces,
|
||||||
pageContext: pageContext,
|
spaceTagModels: spaceModel?.tags ?? []),
|
||||||
allTags: allTags,
|
title: 'Edit Device',
|
||||||
spaceModel: spaceModel,
|
addedProducts:
|
||||||
initialTags: TagHelper.generateInitialTags(
|
TagHelper.createInitialSelectedProducts(
|
||||||
subspaces: subspaces,
|
spaceModel?.tags ?? [], subspaces),
|
||||||
spaceTagModels: spaceModel?.tags ?? []),
|
spaceName: spaceModel?.modelName ?? '',
|
||||||
title: 'Edit Device',
|
));
|
||||||
addedProducts:
|
})
|
||||||
TagHelper.createInitialSelectedProducts(
|
|
||||||
spaceModel?.tags ?? [], subspaces),
|
|
||||||
spaceName: spaceModel?.modelName ?? '',
|
|
||||||
));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
child: Chip(
|
|
||||||
label: const Text(
|
|
||||||
'Edit',
|
|
||||||
style: TextStyle(color: ColorsManager.spaceColor),
|
|
||||||
),
|
|
||||||
backgroundColor: ColorsManager.whiteColors,
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.circular(16),
|
|
||||||
side: const BorderSide(color: ColorsManager.spaceColor),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -141,6 +130,7 @@ class TagChipDisplay extends StatelessWidget {
|
|||||||
pageContext: pageContext,
|
pageContext: pageContext,
|
||||||
isCreate: true,
|
isCreate: true,
|
||||||
spaceModel: spaceModel,
|
spaceModel: spaceModel,
|
||||||
|
otherSpaceModels: otherSpaceModels,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -26,6 +26,7 @@ class AddDeviceTypeModelWidget extends StatelessWidget {
|
|||||||
final List<String>? otherSpaceModels;
|
final List<String>? otherSpaceModels;
|
||||||
final BuildContext? pageContext;
|
final BuildContext? pageContext;
|
||||||
final SpaceTemplateModel? spaceModel;
|
final SpaceTemplateModel? spaceModel;
|
||||||
|
final List<SpaceTemplateModel>? allSpaceModels;
|
||||||
|
|
||||||
const AddDeviceTypeModelWidget(
|
const AddDeviceTypeModelWidget(
|
||||||
{super.key,
|
{super.key,
|
||||||
@ -38,7 +39,8 @@ class AddDeviceTypeModelWidget extends StatelessWidget {
|
|||||||
required this.isCreate,
|
required this.isCreate,
|
||||||
this.pageContext,
|
this.pageContext,
|
||||||
this.otherSpaceModels,
|
this.otherSpaceModels,
|
||||||
this.spaceModel});
|
this.spaceModel,
|
||||||
|
this.allSpaceModels});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -106,6 +108,7 @@ class AddDeviceTypeModelWidget extends StatelessWidget {
|
|||||||
context: context,
|
context: context,
|
||||||
builder: (BuildContext dialogContext) {
|
builder: (BuildContext dialogContext) {
|
||||||
return CreateSpaceModelDialog(
|
return CreateSpaceModelDialog(
|
||||||
|
allSpaceModels: allSpaceModels,
|
||||||
products: products,
|
products: products,
|
||||||
allTags: allTags,
|
allTags: allTags,
|
||||||
pageContext: pageContext,
|
pageContext: pageContext,
|
||||||
@ -175,11 +178,12 @@ class AddDeviceTypeModelWidget extends StatelessWidget {
|
|||||||
context: context,
|
context: context,
|
||||||
builder: (context) => AssignTagModelsDialog(
|
builder: (context) => AssignTagModelsDialog(
|
||||||
products: products,
|
products: products,
|
||||||
|
allSpaceModels: allSpaceModels,
|
||||||
subspaces: subspaces,
|
subspaces: subspaces,
|
||||||
addedProducts: state.selectedProducts,
|
addedProducts: state.selectedProducts,
|
||||||
allTags: allTags,
|
allTags: allTags,
|
||||||
spaceName: spaceName,
|
spaceName: spaceName,
|
||||||
initialTags: state.initialTag,
|
initialTags: initialTags,
|
||||||
otherSpaceModels: otherSpaceModels,
|
otherSpaceModels: otherSpaceModels,
|
||||||
title: dialogTitle,
|
title: dialogTitle,
|
||||||
spaceModel: spaceModel,
|
spaceModel: spaceModel,
|
||||||
@ -216,13 +220,15 @@ class AddDeviceTypeModelWidget extends StatelessWidget {
|
|||||||
if (subspace.tags != null) {
|
if (subspace.tags != null) {
|
||||||
initialTags.addAll(
|
initialTags.addAll(
|
||||||
subspace.tags!.map(
|
subspace.tags!.map(
|
||||||
(tag) => tag.copyWith(location: subspace.subspaceName),
|
(tag) => tag.copyWith(
|
||||||
|
location: subspace.subspaceName,
|
||||||
|
tag: tag.tag,
|
||||||
|
internalId: tag.internalId),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return initialTags;
|
return initialTags;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user