mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-15 17:47:53 +00:00
Compare commits
46 Commits
connect_re
...
SP-1218
Author | SHA1 | Date | |
---|---|---|---|
60bf58d5fd | |||
8d072ee6bb | |||
de614d40a5 | |||
45f6599c40 | |||
ec502214f4 | |||
64adf516f6 | |||
ef777cfce9 | |||
6e90f81760 | |||
51cfa8d5ae | |||
4469efe465 | |||
c7c8e9a519 | |||
692b05a600 | |||
7607e5f80d | |||
b84513c09d | |||
41605bef6b | |||
fd24d6bd27 | |||
5ea29efaf5 | |||
70cb12236b | |||
9f75ce817e | |||
aa23daa0b4 | |||
61f0c3ad2b | |||
553c77d1e3 | |||
27fef7ddaa | |||
010176cc25 | |||
d08a1d1037 | |||
e634154fb3 | |||
c0f59aba61 | |||
7ee7681e09 | |||
57c5f4752c | |||
ad4f2ae382 | |||
eafb811d2e | |||
2d0dcc41df | |||
d89e3fac8e | |||
25acd67351 | |||
0c2a092f4d | |||
b968b5a6eb | |||
05edc7641a | |||
b8204f1015 | |||
d87fec796b | |||
b00b0c82dc | |||
0aa029a2fc | |||
dec3a25639 | |||
581dcf7016 | |||
e1609309cf | |||
da445e11aa | |||
55de7fab0f |
6
assets/icons/delete_space_model.svg
Normal file
6
assets/icons/delete_space_model.svg
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<svg width="16" height="18" viewBox="0 0 16 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M14.4 2.10938H11.7333V1.58203C11.7333 0.709699 11.0156 0 10.1333 0H5.86667C4.98443 0 4.26667 0.709699 4.26667 1.58203V2.10938H1.6C0.71776 2.10938 0 2.81907 0 3.69141C0 4.392 0.463111 4.9873 1.1024 5.19472L2.05369 16.5493C2.1222 17.3628 2.82258 18 3.64814 18H12.3519C13.1775 18 13.8778 17.3628 13.9464 16.5491L14.8976 5.19469C15.5369 4.9873 16 4.392 16 3.69141C16 2.81907 15.2822 2.10938 14.4 2.10938ZM5.33333 1.58203C5.33333 1.29125 5.57259 1.05469 5.86667 1.05469H10.1333C10.4274 1.05469 10.6667 1.29125 10.6667 1.58203V2.10938H5.33333V1.58203ZM12.8833 16.4618C12.8605 16.7329 12.6271 16.9453 12.3519 16.9453H3.64814C3.37298 16.9453 3.13952 16.7329 3.11673 16.462L2.17934 5.27344H13.8207L12.8833 16.4618ZM14.4 4.21875H1.6C1.30592 4.21875 1.06667 3.98218 1.06667 3.69141C1.06667 3.40063 1.30592 3.16406 1.6 3.16406H14.4C14.6941 3.16406 14.9333 3.40063 14.9333 3.69141C14.9333 3.98218 14.6941 4.21875 14.4 4.21875Z" fill="#999999"/>
|
||||||
|
<path d="M5.86561 15.3307L5.33228 6.82286C5.31404 6.53215 5.05957 6.31106 4.76698 6.32916C4.47297 6.3472 4.24943 6.59744 4.26764 6.88811L4.80097 15.396C4.8185 15.6756 5.05331 15.8907 5.33278 15.8907C5.64165 15.8907 5.88456 15.6335 5.86561 15.3307Z" fill="#999999"/>
|
||||||
|
<path d="M7.99989 6.32812C7.70534 6.32812 7.46655 6.56423 7.46655 6.85547V15.3633C7.46655 15.6545 7.70534 15.8906 7.99989 15.8906C8.29443 15.8906 8.53322 15.6545 8.53322 15.3633V6.85547C8.53322 6.56423 8.29443 6.32812 7.99989 6.32812Z" fill="#999999"/>
|
||||||
|
<path d="M11.233 6.32915C10.9396 6.31112 10.6859 6.53215 10.6677 6.82285L10.1343 15.3307C10.1162 15.6213 10.3397 15.8716 10.6337 15.8896C10.9278 15.9076 11.1808 15.6865 11.199 15.3959L11.7323 6.8881C11.7505 6.5974 11.527 6.34715 11.233 6.32915Z" fill="#999999"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.8 KiB |
@ -20,15 +20,22 @@ class DialogTextfieldDropdown extends StatefulWidget {
|
|||||||
|
|
||||||
class _DialogTextfieldDropdownState extends State<DialogTextfieldDropdown> {
|
class _DialogTextfieldDropdownState extends State<DialogTextfieldDropdown> {
|
||||||
bool _isOpen = false;
|
bool _isOpen = false;
|
||||||
late OverlayEntry _overlayEntry;
|
OverlayEntry? _overlayEntry;
|
||||||
final TextEditingController _controller = TextEditingController();
|
final TextEditingController _controller = TextEditingController();
|
||||||
late List<String> _filteredItems; // Filtered items list
|
final FocusNode _focusNode = FocusNode();
|
||||||
|
List<String> _filteredItems = [];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_controller.text = widget.initialValue ?? 'Select Tag';
|
_controller.text = widget.initialValue ?? '';
|
||||||
_filteredItems = List.from(widget.items); // Initialize filtered items
|
_filteredItems = List.from(widget.items);
|
||||||
|
|
||||||
|
_focusNode.addListener(() {
|
||||||
|
if (!_focusNode.hasFocus) {
|
||||||
|
_closeDropdown();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void _toggleDropdown() {
|
void _toggleDropdown() {
|
||||||
@ -41,13 +48,16 @@ class _DialogTextfieldDropdownState extends State<DialogTextfieldDropdown> {
|
|||||||
|
|
||||||
void _openDropdown() {
|
void _openDropdown() {
|
||||||
_overlayEntry = _createOverlayEntry();
|
_overlayEntry = _createOverlayEntry();
|
||||||
Overlay.of(context).insert(_overlayEntry);
|
Overlay.of(context).insert(_overlayEntry!);
|
||||||
_isOpen = true;
|
_isOpen = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _closeDropdown() {
|
void _closeDropdown() {
|
||||||
_overlayEntry.remove();
|
if (_isOpen && _overlayEntry != null) {
|
||||||
_isOpen = false;
|
_overlayEntry!.remove();
|
||||||
|
_overlayEntry = null;
|
||||||
|
_isOpen = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
OverlayEntry _createOverlayEntry() {
|
OverlayEntry _createOverlayEntry() {
|
||||||
@ -58,9 +68,7 @@ class _DialogTextfieldDropdownState extends State<DialogTextfieldDropdown> {
|
|||||||
return OverlayEntry(
|
return OverlayEntry(
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: () {
|
onTap: _closeDropdown,
|
||||||
_closeDropdown();
|
|
||||||
},
|
|
||||||
behavior: HitTestBehavior.translucent,
|
behavior: HitTestBehavior.translucent,
|
||||||
child: Stack(
|
child: Stack(
|
||||||
children: [
|
children: [
|
||||||
@ -72,40 +80,44 @@ class _DialogTextfieldDropdownState extends State<DialogTextfieldDropdown> {
|
|||||||
elevation: 4.0,
|
elevation: 4.0,
|
||||||
child: Container(
|
child: Container(
|
||||||
color: ColorsManager.whiteColors,
|
color: ColorsManager.whiteColors,
|
||||||
constraints: const BoxConstraints(
|
constraints: const BoxConstraints(maxHeight: 200.0),
|
||||||
maxHeight: 200.0,
|
child: StatefulBuilder(
|
||||||
),
|
builder: (context, setStateDropdown) {
|
||||||
child: ListView.builder(
|
return ListView.builder(
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
itemCount: _filteredItems.length,
|
itemCount: _filteredItems.length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final item = _filteredItems[index];
|
final item = _filteredItems[index];
|
||||||
return Container(
|
|
||||||
decoration: const BoxDecoration(
|
return Container(
|
||||||
border: Border(
|
decoration: const BoxDecoration(
|
||||||
bottom: BorderSide(
|
border: Border(
|
||||||
color: ColorsManager.lightGrayBorderColor,
|
bottom: BorderSide(
|
||||||
width: 1.0,
|
color: ColorsManager.lightGrayBorderColor,
|
||||||
|
width: 1.0,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
child: ListTile(
|
||||||
),
|
title: Text(item,
|
||||||
child: ListTile(
|
style: Theme.of(context)
|
||||||
title: Text(item,
|
.textTheme
|
||||||
style: Theme.of(context)
|
.bodyMedium
|
||||||
.textTheme
|
?.copyWith(
|
||||||
.bodyMedium
|
color: ColorsManager
|
||||||
?.copyWith(
|
.textPrimaryColor)),
|
||||||
color: ColorsManager.textPrimaryColor)),
|
onTap: () {
|
||||||
onTap: () {
|
_controller.text = item;
|
||||||
_controller.text = item;
|
widget.onSelected(item);
|
||||||
widget.onSelected(item);
|
setState(() {
|
||||||
setState(() {
|
_filteredItems
|
||||||
_filteredItems
|
.remove(item); // Remove selected item
|
||||||
.remove(item); // Remove selected item
|
});
|
||||||
});
|
_closeDropdown();
|
||||||
_closeDropdown();
|
},
|
||||||
},
|
),
|
||||||
),
|
);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -122,7 +134,8 @@ class _DialogTextfieldDropdownState extends State<DialogTextfieldDropdown> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: _toggleDropdown,
|
onTap: () => FocusScope.of(context).unfocus(),
|
||||||
|
behavior: HitTestBehavior.opaque,
|
||||||
child: Container(
|
child: Container(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 8.0),
|
padding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 8.0),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
@ -135,23 +148,26 @@ class _DialogTextfieldDropdownState extends State<DialogTextfieldDropdown> {
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: TextFormField(
|
child: TextFormField(
|
||||||
controller: _controller,
|
controller: _controller,
|
||||||
onChanged: (value) {
|
focusNode: _focusNode,
|
||||||
setState(() {
|
onFieldSubmitted: (value) {
|
||||||
_filteredItems = widget.items
|
|
||||||
.where((item) =>
|
|
||||||
item.toLowerCase().contains(value.toLowerCase()))
|
|
||||||
.toList(); // Filter items dynamically
|
|
||||||
});
|
|
||||||
widget.onSelected(value);
|
widget.onSelected(value);
|
||||||
|
_closeDropdown();
|
||||||
|
},
|
||||||
|
onTapOutside: (event) {
|
||||||
|
widget.onSelected(_controller.text);
|
||||||
|
_closeDropdown();
|
||||||
},
|
},
|
||||||
style: Theme.of(context).textTheme.bodyMedium,
|
style: Theme.of(context).textTheme.bodyMedium,
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
hintText: 'Enter or Select tag',
|
hintText: 'Enter or Select a tag',
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const Icon(Icons.arrow_drop_down),
|
GestureDetector(
|
||||||
|
onTap: _toggleDropdown,
|
||||||
|
child: const Icon(Icons.arrow_drop_down),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -56,24 +56,6 @@ class CustomExpansionTileState extends State<CustomExpansionTile> {
|
|||||||
children: [
|
children: [
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
// Checkbox with independent state management
|
|
||||||
Checkbox(
|
|
||||||
value: false,
|
|
||||||
onChanged: (bool? value) {
|
|
||||||
setState(() {});
|
|
||||||
},
|
|
||||||
side: WidgetStateBorderSide.resolveWith((states) {
|
|
||||||
return const BorderSide(color: ColorsManager.grayBorder);
|
|
||||||
}),
|
|
||||||
fillColor: WidgetStateProperty.resolveWith((states) {
|
|
||||||
if (states.contains(WidgetState.selected)) {
|
|
||||||
return ColorsManager.grayBorder;
|
|
||||||
} else {
|
|
||||||
return ColorsManager.checkBoxFillColor;
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
checkColor: ColorsManager.whiteColors,
|
|
||||||
),
|
|
||||||
// Expand/collapse icon, now wrapped in a GestureDetector for specific onTap
|
// Expand/collapse icon, now wrapped in a GestureDetector for specific onTap
|
||||||
if (widget.children != null && widget.children!.isNotEmpty)
|
if (widget.children != null && widget.children!.isNotEmpty)
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
@ -84,7 +66,9 @@ class CustomExpansionTileState extends State<CustomExpansionTile> {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
child: Icon(
|
child: Icon(
|
||||||
_isExpanded ? Icons.keyboard_arrow_down : Icons.keyboard_arrow_right,
|
_isExpanded
|
||||||
|
? Icons.keyboard_arrow_down
|
||||||
|
: Icons.keyboard_arrow_right,
|
||||||
color: ColorsManager.lightGrayColor,
|
color: ColorsManager.lightGrayColor,
|
||||||
size: 16.0, // Adjusted size for better alignment
|
size: 16.0, // Adjusted size for better alignment
|
||||||
),
|
),
|
||||||
@ -101,8 +85,10 @@ class CustomExpansionTileState extends State<CustomExpansionTile> {
|
|||||||
_capitalizeFirstLetter(widget.title),
|
_capitalizeFirstLetter(widget.title),
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: widget.isSelected
|
color: widget.isSelected
|
||||||
? ColorsManager.blackColor // Change color to black when selected
|
? ColorsManager
|
||||||
: ColorsManager.lightGrayColor, // Gray when not selected
|
.blackColor // Change color to black when selected
|
||||||
|
: ColorsManager
|
||||||
|
.lightGrayColor, // Gray when not selected
|
||||||
fontWeight: FontWeight.w400,
|
fontWeight: FontWeight.w400,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -111,7 +97,9 @@ class CustomExpansionTileState extends State<CustomExpansionTile> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
// The expanded section (children) that shows when the tile is expanded
|
// The expanded section (children) that shows when the tile is expanded
|
||||||
if (_isExpanded && widget.children != null && widget.children!.isNotEmpty)
|
if (_isExpanded &&
|
||||||
|
widget.children != null &&
|
||||||
|
widget.children!.isNotEmpty)
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(left: 48.0), // Indented children
|
padding: const EdgeInsets.only(left: 48.0), // Indented children
|
||||||
child: Column(
|
child: Column(
|
||||||
|
@ -3,18 +3,33 @@ import 'package:flutter_svg/svg.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';
|
||||||
|
|
||||||
class CustomSearchBar extends StatelessWidget {
|
class CustomSearchBar extends StatefulWidget {
|
||||||
final TextEditingController? controller;
|
final TextEditingController? controller;
|
||||||
final String hintText;
|
final String hintText;
|
||||||
|
final String? searchQuery;
|
||||||
final Function(String)? onSearchChanged; // Callback for search input changes
|
final Function(String)? onSearchChanged; // Callback for search input changes
|
||||||
|
|
||||||
const CustomSearchBar({
|
const CustomSearchBar({
|
||||||
super.key,
|
super.key,
|
||||||
this.controller,
|
this.controller,
|
||||||
|
this.searchQuery = '',
|
||||||
this.hintText = 'Search',
|
this.hintText = 'Search',
|
||||||
this.onSearchChanged,
|
this.onSearchChanged,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<CustomSearchBar> createState() => _CustomSearchBarState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _CustomSearchBarState extends State<CustomSearchBar> {
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
if (widget.controller != null) {
|
||||||
|
widget.controller!.dispose();
|
||||||
|
}
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return Container(
|
||||||
@ -36,16 +51,17 @@ class CustomSearchBar extends StatelessWidget {
|
|||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
),
|
),
|
||||||
child: TextField(
|
child: TextFormField(
|
||||||
controller: controller,
|
controller: widget.controller,
|
||||||
|
initialValue: widget.searchQuery,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
color: Colors.black,
|
color: Colors.black,
|
||||||
),
|
),
|
||||||
onChanged: onSearchChanged, // Call the callback on text change
|
onChanged: widget.onSearchChanged, // Call the callback on text change
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
filled: true,
|
filled: true,
|
||||||
fillColor: ColorsManager.textFieldGreyColor,
|
fillColor: ColorsManager.textFieldGreyColor,
|
||||||
hintText: hintText,
|
hintText: widget.hintText,
|
||||||
hintStyle: Theme.of(context).textTheme.bodyLarge!.copyWith(
|
hintStyle: Theme.of(context).textTheme.bodyLarge!.copyWith(
|
||||||
color: ColorsManager.lightGrayColor,
|
color: ColorsManager.lightGrayColor,
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
|
@ -1,25 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart';
|
|
||||||
|
|
||||||
class SpacesSideTree extends StatefulWidget {
|
|
||||||
final List<CommunityModel> communities;
|
|
||||||
final String? selectedSpaceUuid;
|
|
||||||
const SpacesSideTree({
|
|
||||||
super.key,
|
|
||||||
required this.communities,
|
|
||||||
this.selectedSpaceUuid,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
State<SpacesSideTree> createState() => _SpacesSideTreeState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _SpacesSideTreeState extends State<SpacesSideTree> {
|
|
||||||
String _searchQuery = '';
|
|
||||||
String? _selectedSpaceUuid;
|
|
||||||
String? _selectedId;
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return const Placeholder();
|
|
||||||
}
|
|
||||||
}
|
|
@ -16,6 +16,7 @@ import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_bloc.da
|
|||||||
import 'package:syncrow_web/services/locator.dart';
|
import 'package:syncrow_web/services/locator.dart';
|
||||||
import 'package:syncrow_web/utils/app_routes.dart';
|
import 'package:syncrow_web/utils/app_routes.dart';
|
||||||
import 'package:syncrow_web/utils/constants/routes_const.dart';
|
import 'package:syncrow_web/utils/constants/routes_const.dart';
|
||||||
|
import 'package:syncrow_web/utils/navigation_service.dart';
|
||||||
import 'package:syncrow_web/utils/theme/theme.dart';
|
import 'package:syncrow_web/utils/theme/theme.dart';
|
||||||
|
|
||||||
Future<void> main() async {
|
Future<void> main() async {
|
||||||
@ -33,9 +34,8 @@ Future<void> main() async {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class MyApp extends StatelessWidget {
|
class MyApp extends StatelessWidget {
|
||||||
MyApp({
|
|
||||||
super.key,
|
MyApp({super.key});
|
||||||
});
|
|
||||||
|
|
||||||
final GoRouter _router = GoRouter(
|
final GoRouter _router = GoRouter(
|
||||||
initialLocation: RoutesConst.auth,
|
initialLocation: RoutesConst.auth,
|
||||||
@ -78,6 +78,8 @@ class MyApp extends StatelessWidget {
|
|||||||
PointerDeviceKind.unknown,
|
PointerDeviceKind.unknown,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
key: NavigationService.navigatorKey,
|
||||||
|
// scaffoldMessengerKey: NavigationService.snackbarKey,
|
||||||
theme: myTheme,
|
theme: myTheme,
|
||||||
routerConfig: _router,
|
routerConfig: _router,
|
||||||
));
|
));
|
||||||
|
@ -3,6 +3,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
|||||||
import 'package:syncrow_web/pages/access_management/bloc/access_event.dart';
|
import 'package:syncrow_web/pages/access_management/bloc/access_event.dart';
|
||||||
import 'package:syncrow_web/pages/access_management/bloc/access_state.dart';
|
import 'package:syncrow_web/pages/access_management/bloc/access_state.dart';
|
||||||
import 'package:syncrow_web/pages/access_management/model/password_model.dart';
|
import 'package:syncrow_web/pages/access_management/model/password_model.dart';
|
||||||
|
import 'package:syncrow_web/pages/common/bloc/project_manager.dart';
|
||||||
import 'package:syncrow_web/pages/common/hour_picker_dialog.dart';
|
import 'package:syncrow_web/pages/common/hour_picker_dialog.dart';
|
||||||
import 'package:syncrow_web/services/access_mang_api.dart';
|
import 'package:syncrow_web/services/access_mang_api.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
@ -30,8 +31,9 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
|||||||
Future<void> _onFetchTableData(
|
Future<void> _onFetchTableData(
|
||||||
FetchTableData event, Emitter<AccessState> emit) async {
|
FetchTableData event, Emitter<AccessState> emit) async {
|
||||||
try {
|
try {
|
||||||
|
final projectUuid = await ProjectManager.getProjectUUID() ?? '';
|
||||||
emit(AccessLoaded());
|
emit(AccessLoaded());
|
||||||
data = await AccessMangApi().fetchVisitorPassword();
|
data = await AccessMangApi().fetchVisitorPassword(projectUuid);
|
||||||
filteredData = data;
|
filteredData = data;
|
||||||
updateTabsCount();
|
updateTabsCount();
|
||||||
emit(TableLoaded(data));
|
emit(TableLoaded(data));
|
||||||
@ -88,8 +90,8 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
|||||||
return Theme(
|
return Theme(
|
||||||
data: ThemeData.light().copyWith(
|
data: ThemeData.light().copyWith(
|
||||||
colorScheme: ColorScheme.light(
|
colorScheme: ColorScheme.light(
|
||||||
primary: ColorsManager.blackColor,
|
primary: ColorsManager.blackColor,
|
||||||
onPrimary: Colors.white,
|
onPrimary: Colors.white,
|
||||||
onSurface: ColorsManager.grayColor,
|
onSurface: ColorsManager.grayColor,
|
||||||
),
|
),
|
||||||
textButtonTheme: TextButtonThemeData(
|
textButtonTheme: TextButtonThemeData(
|
||||||
|
@ -3,6 +3,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
|||||||
import 'package:syncrow_web/pages/access_management/bloc/access_bloc.dart';
|
import 'package:syncrow_web/pages/access_management/bloc/access_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/access_management/bloc/access_event.dart';
|
import 'package:syncrow_web/pages/access_management/bloc/access_event.dart';
|
||||||
import 'package:syncrow_web/pages/access_management/bloc/access_state.dart';
|
import 'package:syncrow_web/pages/access_management/bloc/access_state.dart';
|
||||||
|
import 'package:syncrow_web/pages/common/bloc/project_manager.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/common/buttons/search_reset_buttons.dart';
|
import 'package:syncrow_web/pages/common/buttons/search_reset_buttons.dart';
|
||||||
import 'package:syncrow_web/pages/common/custom_table.dart';
|
import 'package:syncrow_web/pages/common/custom_table.dart';
|
||||||
|
@ -9,9 +9,13 @@ import 'package:syncrow_web/pages/auth/model/login_with_email_model.dart';
|
|||||||
import 'package:syncrow_web/pages/auth/model/region_model.dart';
|
import 'package:syncrow_web/pages/auth/model/region_model.dart';
|
||||||
import 'package:syncrow_web/pages/auth/model/token.dart';
|
import 'package:syncrow_web/pages/auth/model/token.dart';
|
||||||
import 'package:syncrow_web/pages/auth/model/user_model.dart';
|
import 'package:syncrow_web/pages/auth/model/user_model.dart';
|
||||||
|
import 'package:syncrow_web/pages/common/bloc/project_manager.dart';
|
||||||
|
import 'package:syncrow_web/pages/space_tree/bloc/space_tree_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/space_tree/bloc/space_tree_event.dart';
|
||||||
import 'package:syncrow_web/services/auth_api.dart';
|
import 'package:syncrow_web/services/auth_api.dart';
|
||||||
import 'package:syncrow_web/utils/constants/strings_manager.dart';
|
import 'package:syncrow_web/utils/constants/strings_manager.dart';
|
||||||
import 'package:syncrow_web/utils/helpers/shared_preferences_helper.dart';
|
import 'package:syncrow_web/utils/helpers/shared_preferences_helper.dart';
|
||||||
|
import 'package:syncrow_web/utils/navigation_service.dart';
|
||||||
import 'package:syncrow_web/utils/snack_bar.dart';
|
import 'package:syncrow_web/utils/snack_bar.dart';
|
||||||
|
|
||||||
class AuthBloc extends Bloc<AuthEvent, AuthState> {
|
class AuthBloc extends Bloc<AuthEvent, AuthState> {
|
||||||
@ -31,8 +35,7 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
|
|||||||
|
|
||||||
////////////////////////////// forget password //////////////////////////////////
|
////////////////////////////// forget password //////////////////////////////////
|
||||||
final TextEditingController forgetEmailController = TextEditingController();
|
final TextEditingController forgetEmailController = TextEditingController();
|
||||||
final TextEditingController forgetPasswordController =
|
final TextEditingController forgetPasswordController = TextEditingController();
|
||||||
TextEditingController();
|
|
||||||
final TextEditingController forgetOtp = TextEditingController();
|
final TextEditingController forgetOtp = TextEditingController();
|
||||||
final forgetFormKey = GlobalKey<FormState>();
|
final forgetFormKey = GlobalKey<FormState>();
|
||||||
final forgetEmailKey = GlobalKey<FormState>();
|
final forgetEmailKey = GlobalKey<FormState>();
|
||||||
@ -49,8 +52,7 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_remainingTime = 1;
|
_remainingTime = 1;
|
||||||
add(UpdateTimerEvent(
|
add(UpdateTimerEvent(remainingTime: _remainingTime, isButtonEnabled: false));
|
||||||
remainingTime: _remainingTime, isButtonEnabled: false));
|
|
||||||
try {
|
try {
|
||||||
forgetEmailValidate = '';
|
forgetEmailValidate = '';
|
||||||
_remainingTime = (await AuthenticationAPI.sendOtp(
|
_remainingTime = (await AuthenticationAPI.sendOtp(
|
||||||
@ -87,8 +89,7 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
|
|||||||
_timer?.cancel();
|
_timer?.cancel();
|
||||||
add(const UpdateTimerEvent(remainingTime: 0, isButtonEnabled: true));
|
add(const UpdateTimerEvent(remainingTime: 0, isButtonEnabled: true));
|
||||||
} else {
|
} else {
|
||||||
add(UpdateTimerEvent(
|
add(UpdateTimerEvent(remainingTime: _remainingTime, isButtonEnabled: false));
|
||||||
remainingTime: _remainingTime, isButtonEnabled: false));
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -98,8 +99,7 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
|
|||||||
emit(const TimerState(isButtonEnabled: true, remainingTime: 0));
|
emit(const TimerState(isButtonEnabled: true, remainingTime: 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> changePassword(
|
Future<void> changePassword(ChangePasswordEvent event, Emitter<AuthState> emit) async {
|
||||||
ChangePasswordEvent event, Emitter<AuthState> emit) async {
|
|
||||||
emit(LoadingForgetState());
|
emit(LoadingForgetState());
|
||||||
try {
|
try {
|
||||||
var response = await AuthenticationAPI.verifyOtp(
|
var response = await AuthenticationAPI.verifyOtp(
|
||||||
@ -115,8 +115,7 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
|
|||||||
}
|
}
|
||||||
} on DioException catch (e) {
|
} on DioException catch (e) {
|
||||||
final errorData = e.response!.data;
|
final errorData = e.response!.data;
|
||||||
String errorMessage =
|
String errorMessage = errorData['error']['message'] ?? 'something went wrong';
|
||||||
errorData['error']['message'] ?? 'something went wrong';
|
|
||||||
validate = errorMessage;
|
validate = errorMessage;
|
||||||
emit(AuthInitialState());
|
emit(AuthInitialState());
|
||||||
}
|
}
|
||||||
@ -130,9 +129,7 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _onUpdateTimer(UpdateTimerEvent event, Emitter<AuthState> emit) {
|
void _onUpdateTimer(UpdateTimerEvent event, Emitter<AuthState> emit) {
|
||||||
emit(TimerState(
|
emit(TimerState(isButtonEnabled: event.isButtonEnabled, remainingTime: event.remainingTime));
|
||||||
isButtonEnabled: event.isButtonEnabled,
|
|
||||||
remainingTime: event.remainingTime));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////// login /////////////////////////////////////
|
///////////////////////////////////// login /////////////////////////////////////
|
||||||
@ -180,18 +177,15 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (token.accessTokenIsNotEmpty) {
|
if (token.accessTokenIsNotEmpty) {
|
||||||
FlutterSecureStorage storage = const FlutterSecureStorage();
|
FlutterSecureStorage storage = const FlutterSecureStorage();
|
||||||
await storage.write(
|
await storage.write(key: Token.loginAccessTokenKey, value: token.accessToken);
|
||||||
key: Token.loginAccessTokenKey, value: token.accessToken);
|
|
||||||
const FlutterSecureStorage().write(
|
const FlutterSecureStorage().write(
|
||||||
key: UserModel.userUuidKey,
|
key: UserModel.userUuidKey,
|
||||||
value: Token.decodeToken(token.accessToken)['uuid'].toString());
|
value: Token.decodeToken(token.accessToken)['uuid'].toString());
|
||||||
user = UserModel.fromToken(token);
|
user = UserModel.fromToken(token);
|
||||||
loginEmailController.clear();
|
loginEmailController.clear();
|
||||||
loginPasswordController.clear();
|
loginPasswordController.clear();
|
||||||
debugPrint("token " + token.accessToken);
|
|
||||||
emit(LoginSuccess());
|
emit(LoginSuccess());
|
||||||
} else {
|
} else {
|
||||||
emit(const LoginFailure(error: 'Something went wrong'));
|
emit(const LoginFailure(error: 'Something went wrong'));
|
||||||
@ -342,14 +336,12 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
|
|||||||
static Future<String> getTokenAndValidate() async {
|
static Future<String> getTokenAndValidate() async {
|
||||||
try {
|
try {
|
||||||
const storage = FlutterSecureStorage();
|
const storage = FlutterSecureStorage();
|
||||||
final firstLaunch = await SharedPreferencesHelper.readBoolFromSP(
|
final firstLaunch =
|
||||||
StringsManager.firstLaunch) ??
|
await SharedPreferencesHelper.readBoolFromSP(StringsManager.firstLaunch) ?? true;
|
||||||
true;
|
|
||||||
if (firstLaunch) {
|
if (firstLaunch) {
|
||||||
storage.deleteAll();
|
storage.deleteAll();
|
||||||
}
|
}
|
||||||
await SharedPreferencesHelper.saveBoolToSP(
|
await SharedPreferencesHelper.saveBoolToSP(StringsManager.firstLaunch, false);
|
||||||
StringsManager.firstLaunch, false);
|
|
||||||
final value = await storage.read(key: Token.loginAccessTokenKey) ?? '';
|
final value = await storage.read(key: Token.loginAccessTokenKey) ?? '';
|
||||||
if (value.isEmpty) {
|
if (value.isEmpty) {
|
||||||
return 'Token not found';
|
return 'Token not found';
|
||||||
@ -402,9 +394,7 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
|
|||||||
final String formattedTime = [
|
final String formattedTime = [
|
||||||
if (days > 0) '${days}d', // Append 'd' for days
|
if (days > 0) '${days}d', // Append 'd' for days
|
||||||
if (days > 0 || hours > 0)
|
if (days > 0 || hours > 0)
|
||||||
hours
|
hours.toString().padLeft(2, '0'), // Show hours if there are days or hours
|
||||||
.toString()
|
|
||||||
.padLeft(2, '0'), // Show hours if there are days or hours
|
|
||||||
minutes.toString().padLeft(2, '0'),
|
minutes.toString().padLeft(2, '0'),
|
||||||
seconds.toString().padLeft(2, '0'),
|
seconds.toString().padLeft(2, '0'),
|
||||||
].join(':');
|
].join(':');
|
||||||
@ -442,8 +432,10 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
|
|||||||
emit(LoginInitial());
|
emit(LoginInitial());
|
||||||
}
|
}
|
||||||
|
|
||||||
static logout() {
|
static Future<void> logout(BuildContext context) async {
|
||||||
const storage = FlutterSecureStorage();
|
final storage = FlutterSecureStorage();
|
||||||
|
ProjectManager.clearProjectUUID();
|
||||||
|
context.read<SpaceTreeBloc>().add(ClearAllData());
|
||||||
storage.deleteAll();
|
storage.deleteAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
27
lib/pages/auth/model/project_model.dart
Normal file
27
lib/pages/auth/model/project_model.dart
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
class Project {
|
||||||
|
final String uuid;
|
||||||
|
final String name;
|
||||||
|
final String description;
|
||||||
|
|
||||||
|
const Project({
|
||||||
|
required this.uuid,
|
||||||
|
required this.name,
|
||||||
|
required this.description,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory Project.fromJson(Map<String, dynamic> json) {
|
||||||
|
return Project(
|
||||||
|
uuid: json['uuid'] as String,
|
||||||
|
name: json['name'] as String,
|
||||||
|
description: json['description'] as String,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return {
|
||||||
|
'uuid': uuid,
|
||||||
|
'name': name,
|
||||||
|
'description': description,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -1,3 +1,4 @@
|
|||||||
|
import 'package:syncrow_web/pages/auth/model/project_model.dart';
|
||||||
import 'package:syncrow_web/pages/auth/model/token.dart';
|
import 'package:syncrow_web/pages/auth/model/token.dart';
|
||||||
|
|
||||||
class UserModel {
|
class UserModel {
|
||||||
@ -13,6 +14,7 @@ class UserModel {
|
|||||||
final bool? hasAcceptedWebAgreement;
|
final bool? hasAcceptedWebAgreement;
|
||||||
final DateTime? webAgreementAcceptedAt;
|
final DateTime? webAgreementAcceptedAt;
|
||||||
final UserRole? role;
|
final UserRole? role;
|
||||||
|
final Project? project;
|
||||||
|
|
||||||
UserModel({
|
UserModel({
|
||||||
required this.uuid,
|
required this.uuid,
|
||||||
@ -26,6 +28,7 @@ class UserModel {
|
|||||||
required this.hasAcceptedWebAgreement,
|
required this.hasAcceptedWebAgreement,
|
||||||
required this.webAgreementAcceptedAt,
|
required this.webAgreementAcceptedAt,
|
||||||
required this.role,
|
required this.role,
|
||||||
|
required this.project,
|
||||||
});
|
});
|
||||||
|
|
||||||
factory UserModel.fromJson(Map<String, dynamic> json) {
|
factory UserModel.fromJson(Map<String, dynamic> json) {
|
||||||
@ -43,6 +46,8 @@ class UserModel {
|
|||||||
? DateTime.parse(json['webAgreementAcceptedAt'])
|
? DateTime.parse(json['webAgreementAcceptedAt'])
|
||||||
: null,
|
: null,
|
||||||
role: json['role'] != null ? UserRole.fromJson(json['role']) : null,
|
role: json['role'] != null ? UserRole.fromJson(json['role']) : null,
|
||||||
|
project:
|
||||||
|
json['project'] != null ? Project.fromJson(json['project']) : null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,6 +69,7 @@ class UserModel {
|
|||||||
phoneNumber: null,
|
phoneNumber: null,
|
||||||
isEmailVerified: null,
|
isEmailVerified: null,
|
||||||
isAgreementAccepted: null,
|
isAgreementAccepted: null,
|
||||||
|
project: null
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
19
lib/pages/common/bloc/project_manager.dart
Normal file
19
lib/pages/common/bloc/project_manager.dart
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import 'package:syncrow_web/utils/constants/strings_manager.dart';
|
||||||
|
import 'package:syncrow_web/utils/helpers/shared_preferences_helper.dart';
|
||||||
|
|
||||||
|
class ProjectManager {
|
||||||
|
static Future<String?> getProjectUUID() async {
|
||||||
|
final projectUuid = await SharedPreferencesHelper.readStringFromSP(
|
||||||
|
StringsManager.projectKey);
|
||||||
|
return projectUuid.isNotEmpty ? projectUuid : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<void> setProjectUUID(String newUUID) async {
|
||||||
|
await SharedPreferencesHelper.saveStringToSP(
|
||||||
|
StringsManager.projectKey, newUUID);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<void> clearProjectUUID() async {
|
||||||
|
await SharedPreferencesHelper.removeValueFromSP(StringsManager.projectKey);
|
||||||
|
}
|
||||||
|
}
|
@ -1,14 +1,19 @@
|
|||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/common/bloc/project_manager.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
|
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
|
||||||
import 'package:syncrow_web/pages/space_tree/bloc/space_tree_bloc.dart';
|
import 'package:syncrow_web/pages/space_tree/bloc/space_tree_bloc.dart';
|
||||||
import 'package:syncrow_web/services/devices_mang_api.dart';
|
import 'package:syncrow_web/services/devices_mang_api.dart';
|
||||||
|
import 'package:syncrow_web/utils/constants/strings_manager.dart';
|
||||||
|
import 'package:syncrow_web/utils/constants/temp_const.dart';
|
||||||
|
import 'package:syncrow_web/utils/helpers/shared_preferences_helper.dart';
|
||||||
|
|
||||||
part 'device_managment_event.dart';
|
part 'device_managment_event.dart';
|
||||||
part 'device_managment_state.dart';
|
part 'device_managment_state.dart';
|
||||||
|
|
||||||
class DeviceManagementBloc extends Bloc<DeviceManagementEvent, DeviceManagementState> {
|
class DeviceManagementBloc
|
||||||
|
extends Bloc<DeviceManagementEvent, DeviceManagementState> {
|
||||||
int _selectedIndex = 0;
|
int _selectedIndex = 0;
|
||||||
List<AllDevicesModel> _devices = [];
|
List<AllDevicesModel> _devices = [];
|
||||||
int _onlineCount = 0;
|
int _onlineCount = 0;
|
||||||
@ -31,19 +36,25 @@ class DeviceManagementBloc extends Bloc<DeviceManagementEvent, DeviceManagementS
|
|||||||
on<UpdateSelection>(_onUpdateSelection);
|
on<UpdateSelection>(_onUpdateSelection);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _onFetchDevices(FetchDevices event, Emitter<DeviceManagementState> emit) async {
|
Future<void> _onFetchDevices(
|
||||||
|
FetchDevices event, Emitter<DeviceManagementState> emit) async {
|
||||||
emit(DeviceManagementLoading());
|
emit(DeviceManagementLoading());
|
||||||
try {
|
try {
|
||||||
List<AllDevicesModel> devices = [];
|
List<AllDevicesModel> devices = [];
|
||||||
_devices.clear();
|
_devices.clear();
|
||||||
var spaceBloc = event.context.read<SpaceTreeBloc>();
|
var spaceBloc = event.context.read<SpaceTreeBloc>();
|
||||||
|
final projectUuid = await ProjectManager.getProjectUUID() ?? '';
|
||||||
|
|
||||||
if (spaceBloc.state.selectedCommunities.isEmpty) {
|
if (spaceBloc.state.selectedCommunities.isEmpty) {
|
||||||
devices = await DevicesManagementApi().fetchDevices('', '');
|
devices = await DevicesManagementApi()
|
||||||
|
.fetchDevices('', '', projectUuid );
|
||||||
} else {
|
} else {
|
||||||
for (var community in spaceBloc.state.selectedCommunities) {
|
for (var community in spaceBloc.state.selectedCommunities) {
|
||||||
List<String> spacesList = spaceBloc.state.selectedCommunityAndSpaces[community] ?? [];
|
List<String> spacesList =
|
||||||
|
spaceBloc.state.selectedCommunityAndSpaces[community] ?? [];
|
||||||
for (var space in spacesList) {
|
for (var space in spacesList) {
|
||||||
devices.addAll(await DevicesManagementApi().fetchDevices(community, space));
|
devices.addAll(await DevicesManagementApi().fetchDevices(
|
||||||
|
community, space, projectUuid));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -66,7 +77,8 @@ class DeviceManagementBloc extends Bloc<DeviceManagementEvent, DeviceManagementS
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onFilterDevices(FilterDevices event, Emitter<DeviceManagementState> emit) async {
|
void _onFilterDevices(
|
||||||
|
FilterDevices event, Emitter<DeviceManagementState> emit) async {
|
||||||
if (_devices.isNotEmpty) {
|
if (_devices.isNotEmpty) {
|
||||||
_filteredDevices = List.from(_devices.where((device) {
|
_filteredDevices = List.from(_devices.where((device) {
|
||||||
switch (event.filter) {
|
switch (event.filter) {
|
||||||
@ -97,7 +109,8 @@ class DeviceManagementBloc extends Bloc<DeviceManagementEvent, DeviceManagementS
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _onResetFilters(ResetFilters event, Emitter<DeviceManagementState> emit) async {
|
Future<void> _onResetFilters(
|
||||||
|
ResetFilters event, Emitter<DeviceManagementState> emit) async {
|
||||||
currentProductName = '';
|
currentProductName = '';
|
||||||
_selectedDevices.clear();
|
_selectedDevices.clear();
|
||||||
_filteredDevices = List.from(_devices);
|
_filteredDevices = List.from(_devices);
|
||||||
@ -113,7 +126,8 @@ class DeviceManagementBloc extends Bloc<DeviceManagementEvent, DeviceManagementS
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onResetSelectedDevices(ResetSelectedDevices event, Emitter<DeviceManagementState> emit) {
|
void _onResetSelectedDevices(
|
||||||
|
ResetSelectedDevices event, Emitter<DeviceManagementState> emit) {
|
||||||
_selectedDevices.clear();
|
_selectedDevices.clear();
|
||||||
|
|
||||||
if (state is DeviceManagementLoaded) {
|
if (state is DeviceManagementLoaded) {
|
||||||
@ -139,12 +153,14 @@ class DeviceManagementBloc extends Bloc<DeviceManagementEvent, DeviceManagementS
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onSelectedFilterChanged(SelectedFilterChanged event, Emitter<DeviceManagementState> emit) {
|
void _onSelectedFilterChanged(
|
||||||
|
SelectedFilterChanged event, Emitter<DeviceManagementState> emit) {
|
||||||
_selectedIndex = event.selectedIndex;
|
_selectedIndex = event.selectedIndex;
|
||||||
add(FilterDevices(_getFilterFromIndex(_selectedIndex)));
|
add(FilterDevices(_getFilterFromIndex(_selectedIndex)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onSelectDevice(SelectDevice event, Emitter<DeviceManagementState> emit) {
|
void _onSelectDevice(
|
||||||
|
SelectDevice event, Emitter<DeviceManagementState> emit) {
|
||||||
final selectedUuid = event.selectedDevice.uuid;
|
final selectedUuid = event.selectedDevice.uuid;
|
||||||
|
|
||||||
if (_selectedDevices.any((device) => device.uuid == selectedUuid)) {
|
if (_selectedDevices.any((device) => device.uuid == selectedUuid)) {
|
||||||
@ -155,7 +171,8 @@ class DeviceManagementBloc extends Bloc<DeviceManagementEvent, DeviceManagementS
|
|||||||
|
|
||||||
List<AllDevicesModel> clonedSelectedDevices = List.from(_selectedDevices);
|
List<AllDevicesModel> clonedSelectedDevices = List.from(_selectedDevices);
|
||||||
|
|
||||||
bool isControlButtonEnabled = _checkIfControlButtonEnabled(clonedSelectedDevices);
|
bool isControlButtonEnabled =
|
||||||
|
_checkIfControlButtonEnabled(clonedSelectedDevices);
|
||||||
|
|
||||||
if (state is DeviceManagementLoaded) {
|
if (state is DeviceManagementLoaded) {
|
||||||
emit(DeviceManagementLoaded(
|
emit(DeviceManagementLoaded(
|
||||||
@ -164,7 +181,8 @@ class DeviceManagementBloc extends Bloc<DeviceManagementEvent, DeviceManagementS
|
|||||||
onlineCount: _onlineCount,
|
onlineCount: _onlineCount,
|
||||||
offlineCount: _offlineCount,
|
offlineCount: _offlineCount,
|
||||||
lowBatteryCount: _lowBatteryCount,
|
lowBatteryCount: _lowBatteryCount,
|
||||||
selectedDevice: clonedSelectedDevices.isNotEmpty ? clonedSelectedDevices : null,
|
selectedDevice:
|
||||||
|
clonedSelectedDevices.isNotEmpty ? clonedSelectedDevices : null,
|
||||||
isControlButtonEnabled: isControlButtonEnabled,
|
isControlButtonEnabled: isControlButtonEnabled,
|
||||||
));
|
));
|
||||||
} else if (state is DeviceManagementFiltered) {
|
} else if (state is DeviceManagementFiltered) {
|
||||||
@ -174,13 +192,15 @@ class DeviceManagementBloc extends Bloc<DeviceManagementEvent, DeviceManagementS
|
|||||||
onlineCount: _onlineCount,
|
onlineCount: _onlineCount,
|
||||||
offlineCount: _offlineCount,
|
offlineCount: _offlineCount,
|
||||||
lowBatteryCount: _lowBatteryCount,
|
lowBatteryCount: _lowBatteryCount,
|
||||||
selectedDevice: clonedSelectedDevices.isNotEmpty ? clonedSelectedDevices : null,
|
selectedDevice:
|
||||||
|
clonedSelectedDevices.isNotEmpty ? clonedSelectedDevices : null,
|
||||||
isControlButtonEnabled: isControlButtonEnabled,
|
isControlButtonEnabled: isControlButtonEnabled,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onUpdateSelection(UpdateSelection event, Emitter<DeviceManagementState> emit) {
|
void _onUpdateSelection(
|
||||||
|
UpdateSelection event, Emitter<DeviceManagementState> emit) {
|
||||||
List<AllDevicesModel> selectedDevices = [];
|
List<AllDevicesModel> selectedDevices = [];
|
||||||
List<AllDevicesModel> devicesToSelectFrom = [];
|
List<AllDevicesModel> devicesToSelectFrom = [];
|
||||||
|
|
||||||
@ -223,7 +243,8 @@ class DeviceManagementBloc extends Bloc<DeviceManagementEvent, DeviceManagementS
|
|||||||
|
|
||||||
bool _checkIfControlButtonEnabled(List<AllDevicesModel> selectedDevices) {
|
bool _checkIfControlButtonEnabled(List<AllDevicesModel> selectedDevices) {
|
||||||
if (selectedDevices.length > 1) {
|
if (selectedDevices.length > 1) {
|
||||||
final productTypes = selectedDevices.map((device) => device.productType).toSet();
|
final productTypes =
|
||||||
|
selectedDevices.map((device) => device.productType).toSet();
|
||||||
return productTypes.length == 1;
|
return productTypes.length == 1;
|
||||||
} else if (selectedDevices.length == 1) {
|
} else if (selectedDevices.length == 1) {
|
||||||
return true;
|
return true;
|
||||||
@ -234,8 +255,10 @@ class DeviceManagementBloc extends Bloc<DeviceManagementEvent, DeviceManagementS
|
|||||||
void _calculateDeviceCounts() {
|
void _calculateDeviceCounts() {
|
||||||
_onlineCount = _devices.where((device) => device.online == true).length;
|
_onlineCount = _devices.where((device) => device.online == true).length;
|
||||||
_offlineCount = _devices.where((device) => device.online == false).length;
|
_offlineCount = _devices.where((device) => device.online == false).length;
|
||||||
_lowBatteryCount =
|
_lowBatteryCount = _devices
|
||||||
_devices.where((device) => device.batteryLevel != null && device.batteryLevel! < 20).length;
|
.where((device) =>
|
||||||
|
device.batteryLevel != null && device.batteryLevel! < 20)
|
||||||
|
.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
String _getFilterFromIndex(int index) {
|
String _getFilterFromIndex(int index) {
|
||||||
@ -251,7 +274,8 @@ class DeviceManagementBloc extends Bloc<DeviceManagementEvent, DeviceManagementS
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onSearchDevices(SearchDevices event, Emitter<DeviceManagementState> emit) {
|
void _onSearchDevices(
|
||||||
|
SearchDevices event, Emitter<DeviceManagementState> emit) {
|
||||||
if ((event.community == null || event.community!.isEmpty) &&
|
if ((event.community == null || event.community!.isEmpty) &&
|
||||||
(event.unitName == null || event.unitName!.isEmpty) &&
|
(event.unitName == null || event.unitName!.isEmpty) &&
|
||||||
(event.productName == null || event.productName!.isEmpty)) {
|
(event.productName == null || event.productName!.isEmpty)) {
|
||||||
@ -280,22 +304,33 @@ class DeviceManagementBloc extends Bloc<DeviceManagementEvent, DeviceManagementS
|
|||||||
final filteredDevices = devicesToSearch.where((device) {
|
final filteredDevices = devicesToSearch.where((device) {
|
||||||
final matchesCommunity = event.community == null ||
|
final matchesCommunity = event.community == null ||
|
||||||
event.community!.isEmpty ||
|
event.community!.isEmpty ||
|
||||||
(device.community?.name?.toLowerCase().contains(event.community!.toLowerCase()) ??
|
(device.community?.name
|
||||||
|
?.toLowerCase()
|
||||||
|
.contains(event.community!.toLowerCase()) ??
|
||||||
false);
|
false);
|
||||||
final matchesUnit = event.unitName == null ||
|
final matchesUnit = event.unitName == null ||
|
||||||
event.unitName!.isEmpty ||
|
event.unitName!.isEmpty ||
|
||||||
(device.spaces != null &&
|
(device.spaces != null &&
|
||||||
device.spaces!.isNotEmpty &&
|
device.spaces!.isNotEmpty &&
|
||||||
device.spaces![0].spaceName!.toLowerCase().contains(event.unitName!.toLowerCase()));
|
device.spaces![0].spaceName!
|
||||||
|
.toLowerCase()
|
||||||
|
.contains(event.unitName!.toLowerCase()));
|
||||||
final matchesProductName = event.productName == null ||
|
final matchesProductName = event.productName == null ||
|
||||||
event.productName!.isEmpty ||
|
event.productName!.isEmpty ||
|
||||||
(device.name?.toLowerCase().contains(event.productName!.toLowerCase()) ?? false);
|
(device.name
|
||||||
|
?.toLowerCase()
|
||||||
|
.contains(event.productName!.toLowerCase()) ??
|
||||||
|
false);
|
||||||
final matchesDeviceName = event.productName == null ||
|
final matchesDeviceName = event.productName == null ||
|
||||||
event.productName!.isEmpty ||
|
event.productName!.isEmpty ||
|
||||||
(device.categoryName?.toLowerCase().contains(event.productName!.toLowerCase()) ??
|
(device.categoryName
|
||||||
|
?.toLowerCase()
|
||||||
|
.contains(event.productName!.toLowerCase()) ??
|
||||||
false);
|
false);
|
||||||
|
|
||||||
return matchesCommunity && matchesUnit && (matchesProductName || matchesDeviceName);
|
return matchesCommunity &&
|
||||||
|
matchesUnit &&
|
||||||
|
(matchesProductName || matchesDeviceName);
|
||||||
}).toList();
|
}).toList();
|
||||||
|
|
||||||
emit(DeviceManagementFiltered(
|
emit(DeviceManagementFiltered(
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/common/bloc/project_manager.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/all_devices/bloc/device_mgmt_bloc/device_managment_bloc.dart';
|
import 'package:syncrow_web/pages/device_managment/all_devices/bloc/device_mgmt_bloc/device_managment_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/all_devices/widgets/device_managment_body.dart';
|
import 'package:syncrow_web/pages/device_managment/all_devices/widgets/device_managment_body.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/shared/navigate_home_grid_view.dart';
|
import 'package:syncrow_web/pages/device_managment/shared/navigate_home_grid_view.dart';
|
||||||
@ -42,6 +43,7 @@ class DeviceManagementPage extends StatelessWidget with HelperResponsiveLayout {
|
|||||||
context
|
context
|
||||||
.read<RoutineBloc>()
|
.read<RoutineBloc>()
|
||||||
.add(const TriggerSwitchTabsEvent(isRoutineTab: false));
|
.add(const TriggerSwitchTabsEvent(isRoutineTab: false));
|
||||||
|
context.read<DeviceManagementBloc>().add(FetchDevices(context));
|
||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
'Devices',
|
'Devices',
|
||||||
|
@ -2,16 +2,19 @@ import 'package:flutter/widgets.dart';
|
|||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
// import 'package:graphview/GraphView.dart';
|
|
||||||
import 'package:syncrow_web/pages/auth/model/user_model.dart';
|
import 'package:syncrow_web/pages/auth/model/user_model.dart';
|
||||||
|
import 'package:syncrow_web/pages/common/bloc/project_manager.dart';
|
||||||
import 'package:syncrow_web/pages/home/bloc/home_event.dart';
|
import 'package:syncrow_web/pages/home/bloc/home_event.dart';
|
||||||
import 'package:syncrow_web/pages/home/bloc/home_state.dart';
|
import 'package:syncrow_web/pages/home/bloc/home_state.dart';
|
||||||
import 'package:syncrow_web/pages/home/home_model/home_item_model.dart';
|
import 'package:syncrow_web/pages/home/home_model/home_item_model.dart';
|
||||||
import 'package:syncrow_web/pages/routines/bloc/routine_bloc/routine_bloc.dart';
|
import 'package:syncrow_web/pages/routines/bloc/routine_bloc/routine_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/space_tree/bloc/space_tree_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/space_tree/bloc/space_tree_event.dart';
|
||||||
import 'package:syncrow_web/services/home_api.dart';
|
import 'package:syncrow_web/services/home_api.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/routes_const.dart';
|
import 'package:syncrow_web/utils/constants/routes_const.dart';
|
||||||
|
import 'package:syncrow_web/utils/navigation_service.dart';
|
||||||
|
|
||||||
class HomeBloc extends Bloc<HomeEvent, HomeState> {
|
class HomeBloc extends Bloc<HomeEvent, HomeState> {
|
||||||
// final Graph graph = Graph()..isTree = true;
|
// final Graph graph = Graph()..isTree = true;
|
||||||
@ -48,9 +51,13 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
|
|||||||
|
|
||||||
Future _fetchUserInfo(FetchUserInfo event, Emitter<HomeState> emit) async {
|
Future _fetchUserInfo(FetchUserInfo event, Emitter<HomeState> emit) async {
|
||||||
try {
|
try {
|
||||||
var uuid =
|
var uuid = await const FlutterSecureStorage().read(key: UserModel.userUuidKey);
|
||||||
await const FlutterSecureStorage().read(key: UserModel.userUuidKey);
|
|
||||||
user = await HomeApi().fetchUserInfo(uuid);
|
user = await HomeApi().fetchUserInfo(uuid);
|
||||||
|
|
||||||
|
if (user != null && user!.project != null) {
|
||||||
|
await ProjectManager.setProjectUUID(user!.project!.uuid);
|
||||||
|
NavigationService.navigatorKey.currentContext!.read<SpaceTreeBloc>().add(InitialEvent());
|
||||||
|
}
|
||||||
add(FetchTermEvent());
|
add(FetchTermEvent());
|
||||||
add(FetchPolicyEvent());
|
add(FetchPolicyEvent());
|
||||||
|
|
||||||
@ -81,12 +88,10 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future _confirmUserAgreement(
|
Future _confirmUserAgreement(ConfirmUserAgreementEvent event, Emitter<HomeState> emit) async {
|
||||||
ConfirmUserAgreementEvent event, Emitter<HomeState> emit) async {
|
|
||||||
try {
|
try {
|
||||||
emit(LoadingHome());
|
emit(LoadingHome());
|
||||||
var uuid =
|
var uuid = await const FlutterSecureStorage().read(key: UserModel.userUuidKey);
|
||||||
await const FlutterSecureStorage().read(key: UserModel.userUuidKey);
|
|
||||||
policy = await HomeApi().confirmUserAgreements(uuid);
|
policy = await HomeApi().confirmUserAgreements(uuid);
|
||||||
emit(PolicyAgreement());
|
emit(PolicyAgreement());
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -110,6 +115,7 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
|
|||||||
icon: Assets.accessIcon,
|
icon: Assets.accessIcon,
|
||||||
active: true,
|
active: true,
|
||||||
onPress: (context) {
|
onPress: (context) {
|
||||||
|
context.read<SpaceTreeBloc>().add(ClearCachedData());
|
||||||
context.go(RoutesConst.accessManagementPage);
|
context.go(RoutesConst.accessManagementPage);
|
||||||
},
|
},
|
||||||
color: null,
|
color: null,
|
||||||
@ -119,6 +125,7 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
|
|||||||
icon: Assets.spaseManagementIcon,
|
icon: Assets.spaseManagementIcon,
|
||||||
active: true,
|
active: true,
|
||||||
onPress: (context) {
|
onPress: (context) {
|
||||||
|
context.read<SpaceTreeBloc>().add(ClearCachedData());
|
||||||
context.go(RoutesConst.spacesManagementPage);
|
context.go(RoutesConst.spacesManagementPage);
|
||||||
},
|
},
|
||||||
color: ColorsManager.primaryColor,
|
color: ColorsManager.primaryColor,
|
||||||
@ -128,6 +135,7 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
|
|||||||
icon: Assets.devicesIcon,
|
icon: Assets.devicesIcon,
|
||||||
active: true,
|
active: true,
|
||||||
onPress: (context) {
|
onPress: (context) {
|
||||||
|
context.read<SpaceTreeBloc>().add(ClearCachedData());
|
||||||
BlocProvider.of<RoutineBloc>(context)
|
BlocProvider.of<RoutineBloc>(context)
|
||||||
.add(const TriggerSwitchTabsEvent(isRoutineTab: false));
|
.add(const TriggerSwitchTabsEvent(isRoutineTab: false));
|
||||||
context.go(RoutesConst.deviceManagementPage);
|
context.go(RoutesConst.deviceManagementPage);
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_html/flutter_html.dart';
|
import 'package:flutter_html/flutter_html.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:syncrow_web/pages/auth/bloc/auth_bloc.dart';
|
import 'package:syncrow_web/pages/auth/bloc/auth_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/common/bloc/project_manager.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
import 'package:syncrow_web/utils/constants/routes_const.dart';
|
import 'package:syncrow_web/utils/constants/routes_const.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
@ -162,7 +164,7 @@ class _AgreementAndPrivacyDialogState extends State<AgreementAndPrivacyDialog> {
|
|||||||
children: [
|
children: [
|
||||||
InkWell(
|
InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
AuthBloc.logout();
|
AuthBloc.logout(context);
|
||||||
context.go(RoutesConst.auth);
|
context.go(RoutesConst.auth);
|
||||||
},
|
},
|
||||||
child: const Text("Cancel"),
|
child: const Text("Cancel"),
|
||||||
|
@ -219,6 +219,9 @@ class UserSpaceModel {
|
|||||||
final double x;
|
final double x;
|
||||||
final double y;
|
final double y;
|
||||||
final String icon;
|
final String icon;
|
||||||
|
final String communityUuid;
|
||||||
|
|
||||||
|
//communityUuid
|
||||||
|
|
||||||
UserSpaceModel({
|
UserSpaceModel({
|
||||||
required this.uuid,
|
required this.uuid,
|
||||||
@ -231,22 +234,23 @@ class UserSpaceModel {
|
|||||||
required this.x,
|
required this.x,
|
||||||
required this.y,
|
required this.y,
|
||||||
required this.icon,
|
required this.icon,
|
||||||
|
required this.communityUuid,
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Create a [UserSpaceModel] from JSON data
|
/// Create a [UserSpaceModel] from JSON data
|
||||||
factory UserSpaceModel.fromJson(Map<String, dynamic> json) {
|
factory UserSpaceModel.fromJson(Map<String, dynamic> json) {
|
||||||
return UserSpaceModel(
|
return UserSpaceModel(
|
||||||
uuid: json['uuid'] as String,
|
uuid: json['uuid'] as String,
|
||||||
createdAt: json['createdAt'] as String,
|
createdAt: json['createdAt'] as String,
|
||||||
updatedAt: json['updatedAt'] as String,
|
updatedAt: json['updatedAt'] as String,
|
||||||
spaceTuyaUuid: json['spaceTuyaUuid'] as String?,
|
spaceTuyaUuid: json['spaceTuyaUuid'] as String?,
|
||||||
spaceName: json['spaceName'] as String,
|
spaceName: json['spaceName'] as String,
|
||||||
invitationCode: json['invitationCode'] as String?,
|
invitationCode: json['invitationCode'] as String?,
|
||||||
disabled: json['disabled'] as bool,
|
disabled: json['disabled'] as bool,
|
||||||
x: (json['x'] as num).toDouble(),
|
x: (json['x'] as num).toDouble(),
|
||||||
y: (json['y'] as num).toDouble(),
|
y: (json['y'] as num).toDouble(),
|
||||||
icon: json['icon'] as String,
|
icon: json['icon'] as String,
|
||||||
);
|
communityUuid: json['communityUuid'] as String);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert the [UserSpaceModel] to JSON
|
/// Convert the [UserSpaceModel] to JSON
|
||||||
@ -262,6 +266,7 @@ class UserSpaceModel {
|
|||||||
'x': x,
|
'x': x,
|
||||||
'y': y,
|
'y': y,
|
||||||
'icon': icon,
|
'icon': icon,
|
||||||
|
'communityUuid': communityUuid
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import 'package:bloc/bloc.dart';
|
import 'package:bloc/bloc.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/common/bloc/project_manager.dart';
|
||||||
import 'package:syncrow_web/pages/common/custom_dialog.dart';
|
import 'package:syncrow_web/pages/common/custom_dialog.dart';
|
||||||
import 'package:syncrow_web/pages/roles_and_permission/model/edit_user_model.dart';
|
import 'package:syncrow_web/pages/roles_and_permission/model/edit_user_model.dart';
|
||||||
import 'package:syncrow_web/pages/roles_and_permission/model/role_type_model.dart';
|
import 'package:syncrow_web/pages/roles_and_permission/model/role_type_model.dart';
|
||||||
@ -7,11 +9,14 @@ import 'package:syncrow_web/pages/roles_and_permission/users_page/add_user_dialo
|
|||||||
import 'package:syncrow_web/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_status.dart';
|
import 'package:syncrow_web/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_status.dart';
|
||||||
import 'package:syncrow_web/pages/roles_and_permission/users_page/add_user_dialog/model/permission_option_model.dart';
|
import 'package:syncrow_web/pages/roles_and_permission/users_page/add_user_dialog/model/permission_option_model.dart';
|
||||||
import 'package:syncrow_web/pages/roles_and_permission/users_page/add_user_dialog/model/tree_node_model.dart';
|
import 'package:syncrow_web/pages/roles_and_permission/users_page/add_user_dialog/model/tree_node_model.dart';
|
||||||
|
import 'package:syncrow_web/pages/space_tree/bloc/space_tree_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/space_tree/bloc/space_tree_event.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart';
|
||||||
import 'package:syncrow_web/services/space_mana_api.dart';
|
import 'package:syncrow_web/services/space_mana_api.dart';
|
||||||
import 'package:syncrow_web/services/user_permission.dart';
|
import 'package:syncrow_web/services/user_permission.dart';
|
||||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||||
|
import 'package:syncrow_web/utils/navigation_service.dart';
|
||||||
|
|
||||||
class UsersBloc extends Bloc<UsersEvent, UsersState> {
|
class UsersBloc extends Bloc<UsersEvent, UsersState> {
|
||||||
UsersBloc() : super(UsersInitial()) {
|
UsersBloc() : super(UsersInitial()) {
|
||||||
@ -61,8 +66,10 @@ class UsersBloc extends Bloc<UsersEvent, UsersState> {
|
|||||||
void isCompleteSpacesFun(
|
void isCompleteSpacesFun(
|
||||||
CheckSpacesStepStatus event, Emitter<UsersState> emit) {
|
CheckSpacesStepStatus event, Emitter<UsersState> emit) {
|
||||||
emit(UsersLoadingState());
|
emit(UsersLoadingState());
|
||||||
List<String> selectedIds = getSelectedIds(updatedCommunities);
|
var spaceBloc =
|
||||||
isCompleteSpaces = selectedIds.isNotEmpty;
|
NavigationService.navigatorKey.currentContext!.read<SpaceTreeBloc>();
|
||||||
|
|
||||||
|
isCompleteSpaces = spaceBloc.state.selectedCommunities.isNotEmpty;
|
||||||
emit(ChangeStatusSteps());
|
emit(ChangeStatusSteps());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,7 +81,10 @@ class UsersBloc extends Bloc<UsersEvent, UsersState> {
|
|||||||
|
|
||||||
Future<List<SpaceModel>> _fetchSpacesForCommunity(
|
Future<List<SpaceModel>> _fetchSpacesForCommunity(
|
||||||
String communityUuid) async {
|
String communityUuid) async {
|
||||||
return await CommunitySpaceManagementApi().getSpaceHierarchy(communityUuid);
|
final projectUuid = await ProjectManager.getProjectUUID() ?? '';
|
||||||
|
|
||||||
|
return await CommunitySpaceManagementApi()
|
||||||
|
.getSpaceHierarchy(communityUuid, projectUuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<TreeNode> updatedCommunities = [];
|
List<TreeNode> updatedCommunities = [];
|
||||||
@ -84,8 +94,10 @@ class UsersBloc extends Bloc<UsersEvent, UsersState> {
|
|||||||
LoadCommunityAndSpacesEvent event, Emitter<UsersState> emit) async {
|
LoadCommunityAndSpacesEvent event, Emitter<UsersState> emit) async {
|
||||||
try {
|
try {
|
||||||
emit(UsersLoadingState());
|
emit(UsersLoadingState());
|
||||||
|
final projectUuid = await ProjectManager.getProjectUUID() ?? '';
|
||||||
|
|
||||||
List<CommunityModel> communities =
|
List<CommunityModel> communities =
|
||||||
await CommunitySpaceManagementApi().fetchCommunities();
|
await CommunitySpaceManagementApi().fetchCommunities(projectUuid);
|
||||||
communityIds = communities.map((community) => community.uuid).toList();
|
communityIds = communities.map((community) => community.uuid).toList();
|
||||||
updatedCommunities = await Future.wait(
|
updatedCommunities = await Future.wait(
|
||||||
communities.map((community) async {
|
communities.map((community) async {
|
||||||
@ -328,20 +340,24 @@ class UsersBloc extends Bloc<UsersEvent, UsersState> {
|
|||||||
|
|
||||||
void _sendInvitUser(SendInviteUsers event, Emitter<UsersState> emit) async {
|
void _sendInvitUser(SendInviteUsers event, Emitter<UsersState> emit) async {
|
||||||
try {
|
try {
|
||||||
|
final projectUuid = await ProjectManager.getProjectUUID() ?? '';
|
||||||
|
|
||||||
emit(UsersLoadingState());
|
emit(UsersLoadingState());
|
||||||
List<String> selectedIds = getSelectedIds(updatedCommunities)
|
// List<String> selectedIds =
|
||||||
.where((id) => !communityIds.contains(id))
|
// getSelectedIds(updatedCommunities).where((id) => !communityIds.contains(id)).toList();
|
||||||
.toList();
|
|
||||||
|
List<String> selectedSpacesId = getSelectedSpacesIds();
|
||||||
|
// List<String> selectedIds = getSelectedIds(updatedCommunities);
|
||||||
|
|
||||||
bool res = await UserPermissionApi().sendInviteUser(
|
bool res = await UserPermissionApi().sendInviteUser(
|
||||||
email: emailController.text,
|
email: emailController.text,
|
||||||
firstName: firstNameController.text,
|
firstName: firstNameController.text,
|
||||||
jobTitle: jobTitleController.text,
|
jobTitle: jobTitleController.text,
|
||||||
lastName: lastNameController.text,
|
lastName: lastNameController.text,
|
||||||
phoneNumber: phoneController.text,
|
phoneNumber: phoneController.text,
|
||||||
roleUuid: roleSelected,
|
roleUuid: roleSelected,
|
||||||
spaceUuids: selectedIds,
|
spaceUuids: selectedSpacesId,
|
||||||
);
|
projectUuid: projectUuid);
|
||||||
|
|
||||||
if (res) {
|
if (res) {
|
||||||
showCustomDialog(
|
showCustomDialog(
|
||||||
@ -370,22 +386,31 @@ class UsersBloc extends Bloc<UsersEvent, UsersState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<String> getSelectedSpacesIds() {
|
||||||
|
List<String> selectedSpacesId = [];
|
||||||
|
var spaceBloc =
|
||||||
|
NavigationService.navigatorKey.currentContext!.read<SpaceTreeBloc>();
|
||||||
|
for (var community in spaceBloc.state.selectedCommunities) {
|
||||||
|
selectedSpacesId
|
||||||
|
.addAll(spaceBloc.state.selectedCommunityAndSpaces[community] ?? []);
|
||||||
|
}
|
||||||
|
return selectedSpacesId;
|
||||||
|
}
|
||||||
|
|
||||||
_editInviteUser(EditInviteUsers event, Emitter<UsersState> emit) async {
|
_editInviteUser(EditInviteUsers event, Emitter<UsersState> emit) async {
|
||||||
try {
|
try {
|
||||||
emit(UsersLoadingState());
|
emit(UsersLoadingState());
|
||||||
List<String> selectedIds = getSelectedIds(updatedCommunities)
|
final projectUuid = await ProjectManager.getProjectUUID() ?? '';
|
||||||
.where((id) => !communityIds.contains(id))
|
|
||||||
.toList();
|
|
||||||
|
|
||||||
bool res = await UserPermissionApi().editInviteUser(
|
bool res = await UserPermissionApi().editInviteUser(
|
||||||
userId: event.userId,
|
userId: event.userId,
|
||||||
firstName: firstNameController.text,
|
firstName: firstNameController.text,
|
||||||
jobTitle: jobTitleController.text,
|
jobTitle: jobTitleController.text,
|
||||||
lastName: lastNameController.text,
|
lastName: lastNameController.text,
|
||||||
phoneNumber: phoneController.text,
|
phoneNumber: phoneController.text,
|
||||||
roleUuid: roleSelected,
|
roleUuid: roleSelected,
|
||||||
spaceUuids: selectedIds,
|
spaceUuids: getSelectedSpacesIds(),
|
||||||
);
|
projectUuid: projectUuid);
|
||||||
if (res == true) {
|
if (res == true) {
|
||||||
showCustomDialog(
|
showCustomDialog(
|
||||||
barrierDismissible: false,
|
barrierDismissible: false,
|
||||||
@ -490,8 +515,13 @@ class UsersBloc extends Bloc<UsersEvent, UsersState> {
|
|||||||
emit(UsersLoadingState());
|
emit(UsersLoadingState());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
var spaceBloc =
|
||||||
|
NavigationService.navigatorKey.currentContext!.read<SpaceTreeBloc>();
|
||||||
|
final projectUuid = await ProjectManager.getProjectUUID() ?? '';
|
||||||
|
|
||||||
if (event.uuid?.isNotEmpty ?? false) {
|
if (event.uuid?.isNotEmpty ?? false) {
|
||||||
final res = await UserPermissionApi().fetchUserById(event.uuid);
|
final res =
|
||||||
|
await UserPermissionApi().fetchUserById(event.uuid, projectUuid);
|
||||||
|
|
||||||
if (res != null) {
|
if (res != null) {
|
||||||
// Populate the text controllers
|
// Populate the text controllers
|
||||||
@ -501,13 +531,20 @@ class UsersBloc extends Bloc<UsersEvent, UsersState> {
|
|||||||
phoneController.text = res.phoneNumber ?? '';
|
phoneController.text = res.phoneNumber ?? '';
|
||||||
jobTitleController.text = res.jobTitle ?? '';
|
jobTitleController.text = res.jobTitle ?? '';
|
||||||
res.roleType;
|
res.roleType;
|
||||||
if (updatedCommunities.isNotEmpty) {
|
res.spaces.map((space) {
|
||||||
// Create a list of UUIDs to mark
|
selectedIds.add(space.uuid);
|
||||||
final uuidsToMark = res.spaces.map((space) => space.uuid).toList();
|
CommunityModel community = spaceBloc.state.communityList
|
||||||
// Print all IDs and mark nodes in updatedCommunities
|
.firstWhere((item) => item.uuid == space.communityUuid);
|
||||||
debugPrint('Printing and marking nodes in updatedCommunities:');
|
spaceBloc.add(OnSpaceSelected(community, space.uuid, []));
|
||||||
_printAndMarkNodes(updatedCommunities, uuidsToMark);
|
}).toList();
|
||||||
}
|
|
||||||
|
// if (updatedCommunities.isNotEmpty) {
|
||||||
|
// // Create a list of UUIDs to mark
|
||||||
|
// final uuidsToMark = res.spaces.map((space) => space.uuid).toList();
|
||||||
|
// // Print all IDs and mark nodes in updatedCommunities
|
||||||
|
// debugPrint('Printing and marking nodes in updatedCommunities:');
|
||||||
|
// _printAndMarkNodes(updatedCommunities, uuidsToMark);
|
||||||
|
// }
|
||||||
final roleId = roles
|
final roleId = roles
|
||||||
.firstWhere((element) =>
|
.firstWhere((element) =>
|
||||||
element.type ==
|
element.type ==
|
||||||
@ -600,4 +637,16 @@ class UsersBloc extends Bloc<UsersEvent, UsersState> {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> close() {
|
||||||
|
emailController.dispose();
|
||||||
|
firstNameController.dispose();
|
||||||
|
lastNameController.dispose();
|
||||||
|
emailController.dispose();
|
||||||
|
phoneController.dispose();
|
||||||
|
jobTitleController.dispose();
|
||||||
|
roleSearchController.dispose();
|
||||||
|
return super.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ class _AddNewUserDialogState extends State<AddNewUserDialog> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (BuildContext context) => UsersBloc()
|
create: (BuildContext context) => UsersBloc()
|
||||||
..add(const LoadCommunityAndSpacesEvent())
|
// ..add(const LoadCommunityAndSpacesEvent())
|
||||||
..add(const RoleEvent()),
|
..add(const RoleEvent()),
|
||||||
child: BlocConsumer<UsersBloc, UsersState>(
|
child: BlocConsumer<UsersBloc, UsersState>(
|
||||||
listener: (context, state) {},
|
listener: (context, state) {},
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
|
import 'package:syncrow_web/pages/common/bloc/project_manager.dart';
|
||||||
import 'package:syncrow_web/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_bloc.dart';
|
import 'package:syncrow_web/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_event.dart';
|
import 'package:syncrow_web/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_event.dart';
|
||||||
import 'package:syncrow_web/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_status.dart';
|
import 'package:syncrow_web/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_status.dart';
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
import 'package:syncrow_web/pages/common/bloc/project_manager.dart';
|
||||||
import 'package:syncrow_web/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_bloc.dart';
|
import 'package:syncrow_web/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_event.dart';
|
import 'package:syncrow_web/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_event.dart';
|
||||||
import 'package:syncrow_web/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_status.dart';
|
import 'package:syncrow_web/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_status.dart';
|
||||||
@ -25,13 +26,12 @@ class _EditUserDialogState extends State<EditUserDialog> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (BuildContext context) => UsersBloc()
|
create: (BuildContext context) => UsersBloc()
|
||||||
..add(const LoadCommunityAndSpacesEvent())
|
// ..add(const LoadCommunityAndSpacesEvent())
|
||||||
..add(const RoleEvent())
|
..add(const RoleEvent())
|
||||||
..add(GetUserByIdEvent(uuid: widget.userId)),
|
..add(GetUserByIdEvent(uuid: widget.userId)),
|
||||||
child: BlocConsumer<UsersBloc, UsersState>(listener: (context, state) {
|
child: BlocConsumer<UsersBloc, UsersState>(listener: (context, state) {
|
||||||
if (state is SpacesLoadedState) {
|
if (state is SpacesLoadedState) {
|
||||||
BlocProvider.of<UsersBloc>(context)
|
BlocProvider.of<UsersBloc>(context).add(GetUserByIdEvent(uuid: widget.userId));
|
||||||
.add(GetUserByIdEvent(uuid: widget.userId));
|
|
||||||
}
|
}
|
||||||
}, builder: (context, state) {
|
}, builder: (context, state) {
|
||||||
final _blocRole = BlocProvider.of<UsersBloc>(context);
|
final _blocRole = BlocProvider.of<UsersBloc>(context);
|
||||||
@ -39,8 +39,7 @@ class _EditUserDialogState extends State<EditUserDialog> {
|
|||||||
return Dialog(
|
return Dialog(
|
||||||
child: Container(
|
child: Container(
|
||||||
decoration: const BoxDecoration(
|
decoration: const BoxDecoration(
|
||||||
color: Colors.white,
|
color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(20))),
|
||||||
borderRadius: BorderRadius.all(Radius.circular(20))),
|
|
||||||
width: 900,
|
width: 900,
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
@ -69,8 +68,7 @@ class _EditUserDialogState extends State<EditUserDialog> {
|
|||||||
children: [
|
children: [
|
||||||
_buildStep1Indicator(1, "Basics", _blocRole),
|
_buildStep1Indicator(1, "Basics", _blocRole),
|
||||||
_buildStep2Indicator(2, "Spaces", _blocRole),
|
_buildStep2Indicator(2, "Spaces", _blocRole),
|
||||||
_buildStep3Indicator(
|
_buildStep3Indicator(3, "Role & Permissions", _blocRole),
|
||||||
3, "Role & Permissions", _blocRole),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -118,15 +116,13 @@ class _EditUserDialogState extends State<EditUserDialog> {
|
|||||||
if (currentStep < 3) {
|
if (currentStep < 3) {
|
||||||
currentStep++;
|
currentStep++;
|
||||||
if (currentStep == 2) {
|
if (currentStep == 2) {
|
||||||
_blocRole
|
_blocRole.add(CheckStepStatus(isEditUser: true));
|
||||||
.add(CheckStepStatus(isEditUser: true));
|
|
||||||
} else if (currentStep == 3) {
|
} else if (currentStep == 3) {
|
||||||
_blocRole.add(const CheckSpacesStepStatus());
|
_blocRole.add(const CheckSpacesStepStatus());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_blocRole.add(EditInviteUsers(
|
_blocRole
|
||||||
context: context,
|
.add(EditInviteUsers(context: context, userId: widget.userId!));
|
||||||
userId: widget.userId!));
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@ -135,8 +131,7 @@ class _EditUserDialogState extends State<EditUserDialog> {
|
|||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: (_blocRole.isCompleteSpaces == false ||
|
color: (_blocRole.isCompleteSpaces == false ||
|
||||||
_blocRole.isCompleteBasics == false ||
|
_blocRole.isCompleteBasics == false ||
|
||||||
_blocRole.isCompleteRolePermissions ==
|
_blocRole.isCompleteRolePermissions == false) &&
|
||||||
false) &&
|
|
||||||
currentStep == 3
|
currentStep == 3
|
||||||
? ColorsManager.grayColor
|
? ColorsManager.grayColor
|
||||||
: ColorsManager.secondaryColor),
|
: ColorsManager.secondaryColor),
|
||||||
@ -209,12 +204,8 @@ class _EditUserDialogState extends State<EditUserDialog> {
|
|||||||
label,
|
label,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
color: currentStep == step
|
color: currentStep == step ? ColorsManager.blackColor : ColorsManager.greyColor,
|
||||||
? ColorsManager.blackColor
|
fontWeight: currentStep == step ? FontWeight.bold : FontWeight.normal,
|
||||||
: ColorsManager.greyColor,
|
|
||||||
fontWeight: currentStep == step
|
|
||||||
? FontWeight.bold
|
|
||||||
: FontWeight.normal,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -272,12 +263,8 @@ class _EditUserDialogState extends State<EditUserDialog> {
|
|||||||
label,
|
label,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
color: currentStep == step
|
color: currentStep == step ? ColorsManager.blackColor : ColorsManager.greyColor,
|
||||||
? ColorsManager.blackColor
|
fontWeight: currentStep == step ? FontWeight.bold : FontWeight.normal,
|
||||||
: ColorsManager.greyColor,
|
|
||||||
fontWeight: currentStep == step
|
|
||||||
? FontWeight.bold
|
|
||||||
: FontWeight.normal,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -334,12 +321,8 @@ class _EditUserDialogState extends State<EditUserDialog> {
|
|||||||
label,
|
label,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
color: currentStep == step
|
color: currentStep == step ? ColorsManager.blackColor : ColorsManager.greyColor,
|
||||||
? ColorsManager.blackColor
|
fontWeight: currentStep == step ? FontWeight.bold : FontWeight.normal,
|
||||||
: ColorsManager.greyColor,
|
|
||||||
fontWeight: currentStep == step
|
|
||||||
? FontWeight.bold
|
|
||||||
: FontWeight.normal,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -1,14 +1,9 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
|
||||||
import 'package:syncrow_web/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_bloc.dart';
|
import 'package:syncrow_web/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_event.dart';
|
|
||||||
import 'package:syncrow_web/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_status.dart';
|
import 'package:syncrow_web/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_status.dart';
|
||||||
import 'package:syncrow_web/pages/roles_and_permission/users_page/add_user_dialog/view/build_tree_view.dart';
|
import 'package:syncrow_web/pages/space_tree/view/space_tree_view.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
|
||||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
|
||||||
import 'package:syncrow_web/utils/extension/build_context_x.dart';
|
import 'package:syncrow_web/utils/extension/build_context_x.dart';
|
||||||
import 'package:syncrow_web/utils/style.dart';
|
|
||||||
|
|
||||||
class SpacesAccessView extends StatelessWidget {
|
class SpacesAccessView extends StatelessWidget {
|
||||||
final String? userId;
|
final String? userId;
|
||||||
@ -27,10 +22,8 @@ class SpacesAccessView extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
'Spaces access',
|
'Spaces access',
|
||||||
style: context.textTheme.bodyLarge?.copyWith(
|
style: context.textTheme.bodyLarge
|
||||||
fontWeight: FontWeight.w700,
|
?.copyWith(fontWeight: FontWeight.w700, fontSize: 20, color: Colors.black),
|
||||||
fontSize: 20,
|
|
||||||
color: Colors.black),
|
|
||||||
),
|
),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 35,
|
height: 35,
|
||||||
@ -42,77 +35,78 @@ class SpacesAccessView extends StatelessWidget {
|
|||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 25,
|
height: 25,
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(child: SpaceTreeView(onSelect: () {}))
|
||||||
child: SizedBox(
|
// Expanded(
|
||||||
child: Column(
|
// child: SizedBox(
|
||||||
children: [
|
// child: Column(
|
||||||
Expanded(
|
// children: [
|
||||||
flex: 2,
|
// Expanded(
|
||||||
child: Container(
|
// flex: 2,
|
||||||
decoration: const BoxDecoration(
|
// child: Container(
|
||||||
color: ColorsManager.circleRolesBackground,
|
// decoration: const BoxDecoration(
|
||||||
borderRadius: BorderRadius.only(
|
// color: ColorsManager.circleRolesBackground,
|
||||||
topRight: Radius.circular(20),
|
// borderRadius: BorderRadius.only(
|
||||||
topLeft: Radius.circular(20)),
|
// topRight: Radius.circular(20),
|
||||||
),
|
// topLeft: Radius.circular(20)),
|
||||||
child: Padding(
|
// ),
|
||||||
padding: const EdgeInsets.all(8.0),
|
// child: Padding(
|
||||||
child: Row(
|
// padding: const EdgeInsets.all(8.0),
|
||||||
children: [
|
// child: Row(
|
||||||
Expanded(
|
// children: [
|
||||||
child: Container(
|
// Expanded(
|
||||||
decoration: BoxDecoration(
|
// child: Container(
|
||||||
borderRadius: const BorderRadius.all(
|
// decoration: BoxDecoration(
|
||||||
Radius.circular(20)),
|
// borderRadius: const BorderRadius.all(
|
||||||
border: Border.all(
|
// Radius.circular(20)),
|
||||||
color: ColorsManager.grayBorder)),
|
// border: Border.all(
|
||||||
child: TextFormField(
|
// color: ColorsManager.grayBorder)),
|
||||||
style:
|
// child: TextFormField(
|
||||||
const TextStyle(color: Colors.black),
|
// style:
|
||||||
// controller: _blocRole.firstNameController,
|
// const TextStyle(color: Colors.black),
|
||||||
onChanged: (value) {
|
// // controller: _blocRole.firstNameController,
|
||||||
_blocRole.add(SearchAnode(
|
// onChanged: (value) {
|
||||||
nodes: _blocRole.updatedCommunities,
|
// _blocRole.add(SearchAnode(
|
||||||
searchTerm: value));
|
// nodes: _blocRole.updatedCommunities,
|
||||||
},
|
// searchTerm: value));
|
||||||
decoration: textBoxDecoration(radios: 20)!
|
// },
|
||||||
.copyWith(
|
// decoration: textBoxDecoration(radios: 20)!
|
||||||
fillColor: Colors.white,
|
// .copyWith(
|
||||||
suffixIcon: Padding(
|
// fillColor: Colors.white,
|
||||||
padding:
|
// suffixIcon: Padding(
|
||||||
const EdgeInsets.only(right: 16),
|
// padding:
|
||||||
child: SvgPicture.asset(
|
// const EdgeInsets.only(right: 16),
|
||||||
Assets.textFieldSearch,
|
// child: SvgPicture.asset(
|
||||||
width: 24,
|
// Assets.textFieldSearch,
|
||||||
height: 24,
|
// width: 24,
|
||||||
),
|
// height: 24,
|
||||||
),
|
// ),
|
||||||
hintStyle: context.textTheme.bodyMedium
|
// ),
|
||||||
?.copyWith(
|
// hintStyle: context.textTheme.bodyMedium
|
||||||
fontWeight: FontWeight.w400,
|
// ?.copyWith(
|
||||||
fontSize: 12,
|
// fontWeight: FontWeight.w400,
|
||||||
color: ColorsManager.textGray),
|
// fontSize: 12,
|
||||||
),
|
// color: ColorsManager.textGray),
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
],
|
// ),
|
||||||
),
|
// ],
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
Expanded(
|
// ),
|
||||||
flex: 7,
|
// Expanded(
|
||||||
child: Container(
|
// flex: 7,
|
||||||
color: ColorsManager.circleRolesBackground,
|
// child: Container(
|
||||||
padding: const EdgeInsets.all(8.0),
|
// color: ColorsManager.circleRolesBackground,
|
||||||
child: Container(
|
// padding: const EdgeInsets.all(8.0),
|
||||||
color: ColorsManager.whiteColors,
|
// child: Container(
|
||||||
child: TreeView(userId: userId))))
|
// color: ColorsManager.whiteColors,
|
||||||
],
|
// child: TreeView(userId: userId))))
|
||||||
),
|
// ],
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
|
// ),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'package:bloc/bloc.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/common/bloc/project_manager.dart';
|
||||||
import 'package:syncrow_web/pages/roles_and_permission/model/roles_user_model.dart';
|
import 'package:syncrow_web/pages/roles_and_permission/model/roles_user_model.dart';
|
||||||
import 'package:syncrow_web/pages/roles_and_permission/users_page/users_table/bloc/user_table_event.dart';
|
import 'package:syncrow_web/pages/roles_and_permission/users_page/users_table/bloc/user_table_event.dart';
|
||||||
import 'package:syncrow_web/pages/roles_and_permission/users_page/users_table/bloc/user_table_state.dart';
|
import 'package:syncrow_web/pages/roles_and_permission/users_page/users_table/bloc/user_table_state.dart';
|
||||||
import 'package:syncrow_web/services/user_permission.dart';
|
import 'package:syncrow_web/services/user_permission.dart';
|
||||||
|
import 'package:syncrow_web/utils/constants/strings_manager.dart';
|
||||||
|
import 'package:syncrow_web/utils/helpers/shared_preferences_helper.dart';
|
||||||
|
|
||||||
class UserTableBloc extends Bloc<UserTableEvent, UserTableState> {
|
class UserTableBloc extends Bloc<UserTableEvent, UserTableState> {
|
||||||
UserTableBloc() : super(TableInitial()) {
|
UserTableBloc() : super(TableInitial()) {
|
||||||
@ -46,10 +49,12 @@ class UserTableBloc extends Bloc<UserTableEvent, UserTableState> {
|
|||||||
Future<void> _getUsers(GetUsers event, Emitter<UserTableState> emit) async {
|
Future<void> _getUsers(GetUsers event, Emitter<UserTableState> emit) async {
|
||||||
emit(UsersLoadingState());
|
emit(UsersLoadingState());
|
||||||
try {
|
try {
|
||||||
|
final projectUuid = await ProjectManager.getProjectUUID() ?? '';
|
||||||
|
|
||||||
roleTypes.clear();
|
roleTypes.clear();
|
||||||
jobTitle.clear();
|
jobTitle.clear();
|
||||||
createdBy.clear();
|
createdBy.clear();
|
||||||
users = await UserPermissionApi().fetchUsers();
|
users = await UserPermissionApi().fetchUsers(projectUuid);
|
||||||
users.sort((a, b) {
|
users.sort((a, b) {
|
||||||
final dateA = _parseDateTime(a.createdDate);
|
final dateA = _parseDateTime(a.createdDate);
|
||||||
final dateB = _parseDateTime(b.createdDate);
|
final dateB = _parseDateTime(b.createdDate);
|
||||||
@ -96,9 +101,11 @@ class UserTableBloc extends Bloc<UserTableEvent, UserTableState> {
|
|||||||
Future<void> _changeUserStatus(
|
Future<void> _changeUserStatus(
|
||||||
ChangeUserStatus event, Emitter<UserTableState> emit) async {
|
ChangeUserStatus event, Emitter<UserTableState> emit) async {
|
||||||
try {
|
try {
|
||||||
|
final projectUuid = await ProjectManager.getProjectUUID() ?? '';
|
||||||
|
|
||||||
emit(UsersLoadingState());
|
emit(UsersLoadingState());
|
||||||
bool res = await UserPermissionApi().changeUserStatusById(
|
bool res = await UserPermissionApi().changeUserStatusById(event.userId,
|
||||||
event.userId, event.newStatus == "disabled" ? false : true);
|
event.newStatus == "disabled" ? false : true, projectUuid);
|
||||||
if (res == true) {
|
if (res == true) {
|
||||||
add(const GetUsers());
|
add(const GetUsers());
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,8 @@ import 'package:syncrow_web/pages/roles_and_permission/users_page/users_table/vi
|
|||||||
import 'package:syncrow_web/pages/roles_and_permission/users_page/users_table/view/de_activate_filter.dart';
|
import 'package:syncrow_web/pages/roles_and_permission/users_page/users_table/view/de_activate_filter.dart';
|
||||||
import 'package:syncrow_web/pages/roles_and_permission/users_page/users_table/view/name_filter.dart';
|
import 'package:syncrow_web/pages/roles_and_permission/users_page/users_table/view/name_filter.dart';
|
||||||
import 'package:syncrow_web/pages/roles_and_permission/users_page/users_table/view/user_table.dart';
|
import 'package:syncrow_web/pages/roles_and_permission/users_page/users_table/view/user_table.dart';
|
||||||
|
import 'package:syncrow_web/pages/space_tree/bloc/space_tree_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/space_tree/bloc/space_tree_event.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/extension/build_context_x.dart';
|
import 'package:syncrow_web/utils/extension/build_context_x.dart';
|
||||||
@ -25,8 +27,7 @@ class UsersPage extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final TextEditingController searchController = TextEditingController();
|
final TextEditingController searchController = TextEditingController();
|
||||||
|
|
||||||
Widget actionButton(
|
Widget actionButton({bool isActive = false, required String title, Function()? onTap}) {
|
||||||
{bool isActive = false, required String title, Function()? onTap}) {
|
|
||||||
return InkWell(
|
return InkWell(
|
||||||
onTap: onTap,
|
onTap: onTap,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
@ -59,8 +60,7 @@ class UsersPage extends StatelessWidget {
|
|||||||
: ColorsManager.disabledPink.withOpacity(0.5),
|
: ColorsManager.disabledPink.withOpacity(0.5),
|
||||||
),
|
),
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding:
|
padding: const EdgeInsets.only(left: 10, right: 10, bottom: 5, top: 5),
|
||||||
const EdgeInsets.only(left: 10, right: 10, bottom: 5, top: 5),
|
|
||||||
child: Row(
|
child: Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
@ -84,15 +84,12 @@ class UsersPage extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget changeIconStatus(
|
Widget changeIconStatus(
|
||||||
{required String userId,
|
{required String userId, required String status, required Function()? onTap}) {
|
||||||
required String status,
|
|
||||||
required Function()? onTap}) {
|
|
||||||
return Center(
|
return Center(
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: onTap,
|
onTap: onTap,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding:
|
padding: const EdgeInsets.only(left: 5, right: 5, bottom: 5, top: 5),
|
||||||
const EdgeInsets.only(left: 5, right: 5, bottom: 5, top: 5),
|
|
||||||
child: SvgPicture.asset(
|
child: SvgPicture.asset(
|
||||||
status == "invited"
|
status == "invited"
|
||||||
? Assets.invitedIcon
|
? Assets.invitedIcon
|
||||||
@ -160,6 +157,7 @@ class UsersPage extends StatelessWidget {
|
|||||||
const SizedBox(width: 20),
|
const SizedBox(width: 20),
|
||||||
InkWell(
|
InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
|
context.read<SpaceTreeBloc>().add(ClearCachedData());
|
||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
barrierDismissible: false,
|
barrierDismissible: false,
|
||||||
@ -198,14 +196,10 @@ class UsersPage extends StatelessWidget {
|
|||||||
context: context,
|
context: context,
|
||||||
isSelected: _blocRole.currentSortOrder,
|
isSelected: _blocRole.currentSortOrder,
|
||||||
aToZTap: () {
|
aToZTap: () {
|
||||||
context
|
context.read<UserTableBloc>().add(const SortUsersByNameAsc());
|
||||||
.read<UserTableBloc>()
|
|
||||||
.add(const SortUsersByNameAsc());
|
|
||||||
},
|
},
|
||||||
zToaTap: () {
|
zToaTap: () {
|
||||||
context
|
context.read<UserTableBloc>().add(const SortUsersByNameDesc());
|
||||||
.read<UserTableBloc>()
|
|
||||||
.add(const SortUsersByNameDesc());
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -214,9 +208,8 @@ class UsersPage extends StatelessWidget {
|
|||||||
for (var item in _blocRole.jobTitle)
|
for (var item in _blocRole.jobTitle)
|
||||||
item: _blocRole.selectedJobTitles.contains(item),
|
item: _blocRole.selectedJobTitles.contains(item),
|
||||||
};
|
};
|
||||||
final RenderBox overlay = Overlay.of(context)
|
final RenderBox overlay =
|
||||||
.context
|
Overlay.of(context).context.findRenderObject() as RenderBox;
|
||||||
.findRenderObject() as RenderBox;
|
|
||||||
|
|
||||||
showPopUpFilterMenu(
|
showPopUpFilterMenu(
|
||||||
position: RelativeRect.fromLTRB(
|
position: RelativeRect.fromLTRB(
|
||||||
@ -256,9 +249,8 @@ class UsersPage extends StatelessWidget {
|
|||||||
for (var item in _blocRole.roleTypes)
|
for (var item in _blocRole.roleTypes)
|
||||||
item: _blocRole.selectedRoles.contains(item),
|
item: _blocRole.selectedRoles.contains(item),
|
||||||
};
|
};
|
||||||
final RenderBox overlay = Overlay.of(context)
|
final RenderBox overlay =
|
||||||
.context
|
Overlay.of(context).context.findRenderObject() as RenderBox;
|
||||||
.findRenderObject() as RenderBox;
|
|
||||||
showPopUpFilterMenu(
|
showPopUpFilterMenu(
|
||||||
position: RelativeRect.fromLTRB(
|
position: RelativeRect.fromLTRB(
|
||||||
overlay.size.width / 4,
|
overlay.size.width / 4,
|
||||||
@ -278,10 +270,9 @@ class UsersPage extends StatelessWidget {
|
|||||||
.map((entry) => entry.key)
|
.map((entry) => entry.key)
|
||||||
.toList();
|
.toList();
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
context.read<UserTableBloc>().add(
|
context.read<UserTableBloc>().add(FilterUsersByRoleEvent(
|
||||||
FilterUsersByRoleEvent(
|
selectedRoles: selectedItems,
|
||||||
selectedRoles: selectedItems,
|
sortOrder: _blocRole.currentSortRole));
|
||||||
sortOrder: _blocRole.currentSortRole));
|
|
||||||
},
|
},
|
||||||
onSortAtoZ: (v) {
|
onSortAtoZ: (v) {
|
||||||
_blocRole.currentSortRole = v;
|
_blocRole.currentSortRole = v;
|
||||||
@ -296,14 +287,10 @@ class UsersPage extends StatelessWidget {
|
|||||||
context: context,
|
context: context,
|
||||||
isSelected: _blocRole.currentSortOrder,
|
isSelected: _blocRole.currentSortOrder,
|
||||||
aToZTap: () {
|
aToZTap: () {
|
||||||
context
|
context.read<UserTableBloc>().add(const DateNewestToOldestEvent());
|
||||||
.read<UserTableBloc>()
|
|
||||||
.add(const DateNewestToOldestEvent());
|
|
||||||
},
|
},
|
||||||
zToaTap: () {
|
zToaTap: () {
|
||||||
context
|
context.read<UserTableBloc>().add(const DateOldestToNewestEvent());
|
||||||
.read<UserTableBloc>()
|
|
||||||
.add(const DateOldestToNewestEvent());
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -312,9 +299,8 @@ class UsersPage extends StatelessWidget {
|
|||||||
for (var item in _blocRole.createdBy)
|
for (var item in _blocRole.createdBy)
|
||||||
item: _blocRole.selectedCreatedBy.contains(item),
|
item: _blocRole.selectedCreatedBy.contains(item),
|
||||||
};
|
};
|
||||||
final RenderBox overlay = Overlay.of(context)
|
final RenderBox overlay =
|
||||||
.context
|
Overlay.of(context).context.findRenderObject() as RenderBox;
|
||||||
.findRenderObject() as RenderBox;
|
|
||||||
showPopUpFilterMenu(
|
showPopUpFilterMenu(
|
||||||
position: RelativeRect.fromLTRB(
|
position: RelativeRect.fromLTRB(
|
||||||
overlay.size.width / 1,
|
overlay.size.width / 1,
|
||||||
@ -352,9 +338,8 @@ class UsersPage extends StatelessWidget {
|
|||||||
item: _blocRole.selectedStatuses.contains(item),
|
item: _blocRole.selectedStatuses.contains(item),
|
||||||
};
|
};
|
||||||
|
|
||||||
final RenderBox overlay = Overlay.of(context)
|
final RenderBox overlay =
|
||||||
.context
|
Overlay.of(context).context.findRenderObject() as RenderBox;
|
||||||
.findRenderObject() as RenderBox;
|
|
||||||
showPopUpFilterMenu(
|
showPopUpFilterMenu(
|
||||||
position: RelativeRect.fromLTRB(
|
position: RelativeRect.fromLTRB(
|
||||||
overlay.size.width / 0,
|
overlay.size.width / 0,
|
||||||
@ -391,14 +376,10 @@ class UsersPage extends StatelessWidget {
|
|||||||
context: context,
|
context: context,
|
||||||
isSelected: _blocRole.currentSortOrderDate,
|
isSelected: _blocRole.currentSortOrderDate,
|
||||||
aToZTap: () {
|
aToZTap: () {
|
||||||
context
|
context.read<UserTableBloc>().add(const DateNewestToOldestEvent());
|
||||||
.read<UserTableBloc>()
|
|
||||||
.add(const DateNewestToOldestEvent());
|
|
||||||
},
|
},
|
||||||
zToaTap: () {
|
zToaTap: () {
|
||||||
context
|
context.read<UserTableBloc>().add(const DateOldestToNewestEvent());
|
||||||
.read<UserTableBloc>()
|
|
||||||
.add(const DateOldestToNewestEvent());
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -425,23 +406,17 @@ class UsersPage extends StatelessWidget {
|
|||||||
Text(user.createdTime ?? ''),
|
Text(user.createdTime ?? ''),
|
||||||
Text(user.invitedBy),
|
Text(user.invitedBy),
|
||||||
status(
|
status(
|
||||||
status: user.isEnabled == false
|
status: user.isEnabled == false ? 'disabled' : user.status,
|
||||||
? 'disabled'
|
|
||||||
: user.status,
|
|
||||||
),
|
),
|
||||||
changeIconStatus(
|
changeIconStatus(
|
||||||
status: user.isEnabled == false
|
status: user.isEnabled == false ? 'disabled' : user.status,
|
||||||
? 'disabled'
|
|
||||||
: user.status,
|
|
||||||
userId: user.uuid,
|
userId: user.uuid,
|
||||||
onTap: user.status != "invited"
|
onTap: user.status != "invited"
|
||||||
? () {
|
? () {
|
||||||
context.read<UserTableBloc>().add(
|
context.read<UserTableBloc>().add(ChangeUserStatus(
|
||||||
ChangeUserStatus(
|
userId: user.uuid,
|
||||||
userId: user.uuid,
|
newStatus:
|
||||||
newStatus: user.isEnabled == false
|
user.isEnabled == false ? 'disabled' : user.status));
|
||||||
? 'disabled'
|
|
||||||
: user.status));
|
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
),
|
),
|
||||||
@ -452,12 +427,12 @@ class UsersPage extends StatelessWidget {
|
|||||||
isActive: true,
|
isActive: true,
|
||||||
title: "Edit",
|
title: "Edit",
|
||||||
onTap: () {
|
onTap: () {
|
||||||
|
context.read<SpaceTreeBloc>().add(ClearCachedData());
|
||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
barrierDismissible: false,
|
barrierDismissible: false,
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
return EditUserDialog(
|
return EditUserDialog(userId: user.uuid);
|
||||||
userId: user.uuid);
|
|
||||||
},
|
},
|
||||||
).then((v) {
|
).then((v) {
|
||||||
if (v != null) {
|
if (v != null) {
|
||||||
@ -478,13 +453,10 @@ class UsersPage extends StatelessWidget {
|
|||||||
context: context,
|
context: context,
|
||||||
barrierDismissible: false,
|
barrierDismissible: false,
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
return DeleteUserDialog(
|
return DeleteUserDialog(onTapDelete: () async {
|
||||||
onTapDelete: () async {
|
|
||||||
try {
|
try {
|
||||||
_blocRole.add(DeleteUserEvent(
|
_blocRole.add(DeleteUserEvent(user.uuid, context));
|
||||||
user.uuid, context));
|
await Future.delayed(const Duration(seconds: 2));
|
||||||
await Future.delayed(
|
|
||||||
const Duration(seconds: 2));
|
|
||||||
return true;
|
return true;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return false;
|
return false;
|
||||||
@ -514,20 +486,14 @@ class UsersPage extends StatelessWidget {
|
|||||||
visiblePagesCount: 4,
|
visiblePagesCount: 4,
|
||||||
buttonRadius: 10,
|
buttonRadius: 10,
|
||||||
selectedButtonColor: ColorsManager.secondaryColor,
|
selectedButtonColor: ColorsManager.secondaryColor,
|
||||||
buttonUnSelectedBorderColor:
|
buttonUnSelectedBorderColor: ColorsManager.grayBorder,
|
||||||
ColorsManager.grayBorder,
|
lastPageIcon: const Icon(Icons.keyboard_double_arrow_right),
|
||||||
lastPageIcon:
|
firstPageIcon: const Icon(Icons.keyboard_double_arrow_left),
|
||||||
const Icon(Icons.keyboard_double_arrow_right),
|
totalPages:
|
||||||
firstPageIcon:
|
(_blocRole.totalUsersCount.length / _blocRole.itemsPerPage).ceil(),
|
||||||
const Icon(Icons.keyboard_double_arrow_left),
|
|
||||||
totalPages: (_blocRole.totalUsersCount.length /
|
|
||||||
_blocRole.itemsPerPage)
|
|
||||||
.ceil(),
|
|
||||||
currentPage: _blocRole.currentPage,
|
currentPage: _blocRole.currentPage,
|
||||||
onPageChanged: (int pageNumber) {
|
onPageChanged: (int pageNumber) {
|
||||||
context
|
context.read<UserTableBloc>().add(ChangePage(pageNumber));
|
||||||
.read<UserTableBloc>()
|
|
||||||
.add(ChangePage(pageNumber));
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/common/bloc/project_manager.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/shared/navigate_home_grid_view.dart';
|
import 'package:syncrow_web/pages/device_managment/shared/navigate_home_grid_view.dart';
|
||||||
import 'package:syncrow_web/pages/roles_and_permission/bloc/roles_permission_bloc.dart';
|
import 'package:syncrow_web/pages/roles_and_permission/bloc/roles_permission_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/roles_and_permission/bloc/roles_permission_state.dart';
|
import 'package:syncrow_web/pages/roles_and_permission/bloc/roles_permission_state.dart';
|
||||||
|
@ -3,6 +3,8 @@ import 'dart:async';
|
|||||||
import 'package:bloc/bloc.dart';
|
import 'package:bloc/bloc.dart';
|
||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:syncrow_web/pages/common/bloc/project_manager.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
|
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
|
||||||
import 'package:syncrow_web/pages/routines/models/create_scene_and_autoamtion/create_automation_model.dart';
|
import 'package:syncrow_web/pages/routines/models/create_scene_and_autoamtion/create_automation_model.dart';
|
||||||
import 'package:syncrow_web/pages/routines/models/create_scene_and_autoamtion/create_scene_model.dart';
|
import 'package:syncrow_web/pages/routines/models/create_scene_and_autoamtion/create_scene_model.dart';
|
||||||
@ -10,17 +12,22 @@ import 'package:syncrow_web/pages/routines/models/delay/delay_fucntions.dart';
|
|||||||
import 'package:syncrow_web/pages/routines/models/device_functions.dart';
|
import 'package:syncrow_web/pages/routines/models/device_functions.dart';
|
||||||
import 'package:syncrow_web/pages/routines/models/routine_details_model.dart';
|
import 'package:syncrow_web/pages/routines/models/routine_details_model.dart';
|
||||||
import 'package:syncrow_web/pages/routines/models/routine_model.dart';
|
import 'package:syncrow_web/pages/routines/models/routine_model.dart';
|
||||||
|
import 'package:syncrow_web/pages/space_tree/bloc/space_tree_bloc.dart';
|
||||||
import 'package:syncrow_web/services/devices_mang_api.dart';
|
import 'package:syncrow_web/services/devices_mang_api.dart';
|
||||||
import 'package:syncrow_web/services/routines_api.dart';
|
import 'package:syncrow_web/services/routines_api.dart';
|
||||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||||
|
import 'package:syncrow_web/utils/constants/strings_manager.dart';
|
||||||
|
import 'package:syncrow_web/utils/constants/temp_const.dart';
|
||||||
|
import 'package:syncrow_web/utils/helpers/shared_preferences_helper.dart';
|
||||||
|
import 'package:syncrow_web/utils/navigation_service.dart';
|
||||||
import 'package:syncrow_web/utils/snack_bar.dart';
|
import 'package:syncrow_web/utils/snack_bar.dart';
|
||||||
import 'package:uuid/uuid.dart';
|
import 'package:uuid/uuid.dart';
|
||||||
|
|
||||||
part 'routine_event.dart';
|
part 'routine_event.dart';
|
||||||
part 'routine_state.dart';
|
part 'routine_state.dart';
|
||||||
|
|
||||||
String spaceId = '25c96044-fadf-44bb-93c7-3c079e527ce6';
|
// String spaceId = '25c96044-fadf-44bb-93c7-3c079e527ce6';
|
||||||
String communityId = 'aff21a57-2f91-4e5c-b99b-0182c3ab65a9';
|
// String communityId = 'aff21a57-2f91-4e5c-b99b-0182c3ab65a9';
|
||||||
|
|
||||||
class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
||||||
RoutineBloc() : super(const RoutineState()) {
|
RoutineBloc() : super(const RoutineState()) {
|
||||||
@ -54,11 +61,12 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
TriggerSwitchTabsEvent event,
|
TriggerSwitchTabsEvent event,
|
||||||
Emitter<RoutineState> emit,
|
Emitter<RoutineState> emit,
|
||||||
) {
|
) {
|
||||||
emit(state.copyWith(routineTab: event.isRoutineTab, createRoutineView: false));
|
emit(state.copyWith(
|
||||||
|
routineTab: event.isRoutineTab, createRoutineView: false));
|
||||||
add(ResetRoutineState());
|
add(ResetRoutineState());
|
||||||
if (event.isRoutineTab) {
|
if (event.isRoutineTab) {
|
||||||
add(LoadScenes(spaceId, communityId));
|
add(const LoadScenes());
|
||||||
add(LoadAutomation(spaceId));
|
add(const LoadAutomation());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,8 +88,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
final updatedIfItems = List<Map<String, dynamic>>.from(state.ifItems);
|
final updatedIfItems = List<Map<String, dynamic>>.from(state.ifItems);
|
||||||
|
|
||||||
// Find the index of the item in teh current itemsList
|
// Find the index of the item in teh current itemsList
|
||||||
int index =
|
int index = updatedIfItems.indexWhere(
|
||||||
updatedIfItems.indexWhere((map) => map['uniqueCustomId'] == event.item['uniqueCustomId']);
|
(map) => map['uniqueCustomId'] == event.item['uniqueCustomId']);
|
||||||
// Replace the map if the index is valid
|
// Replace the map if the index is valid
|
||||||
if (index != -1) {
|
if (index != -1) {
|
||||||
updatedIfItems[index] = event.item;
|
updatedIfItems[index] = event.item;
|
||||||
@ -90,18 +98,21 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (event.isTabToRun) {
|
if (event.isTabToRun) {
|
||||||
emit(state.copyWith(ifItems: updatedIfItems, isTabToRun: true, isAutomation: false));
|
emit(state.copyWith(
|
||||||
|
ifItems: updatedIfItems, isTabToRun: true, isAutomation: false));
|
||||||
} else {
|
} else {
|
||||||
emit(state.copyWith(ifItems: updatedIfItems, isTabToRun: false, isAutomation: true));
|
emit(state.copyWith(
|
||||||
|
ifItems: updatedIfItems, isTabToRun: false, isAutomation: true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onAddToThenContainer(AddToThenContainer event, Emitter<RoutineState> emit) {
|
void _onAddToThenContainer(
|
||||||
|
AddToThenContainer event, Emitter<RoutineState> emit) {
|
||||||
final currentItems = List<Map<String, dynamic>>.from(state.thenItems);
|
final currentItems = List<Map<String, dynamic>>.from(state.thenItems);
|
||||||
|
|
||||||
// Find the index of the item in teh current itemsList
|
// Find the index of the item in teh current itemsList
|
||||||
int index =
|
int index = currentItems.indexWhere(
|
||||||
currentItems.indexWhere((map) => map['uniqueCustomId'] == event.item['uniqueCustomId']);
|
(map) => map['uniqueCustomId'] == event.item['uniqueCustomId']);
|
||||||
// Replace the map if the index is valid
|
// Replace the map if the index is valid
|
||||||
if (index != -1) {
|
if (index != -1) {
|
||||||
currentItems[index] = event.item;
|
currentItems[index] = event.item;
|
||||||
@ -112,22 +123,26 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
emit(state.copyWith(thenItems: currentItems));
|
emit(state.copyWith(thenItems: currentItems));
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onAddFunctionsToRoutine(AddFunctionToRoutine event, Emitter<RoutineState> emit) {
|
void _onAddFunctionsToRoutine(
|
||||||
|
AddFunctionToRoutine event, Emitter<RoutineState> emit) {
|
||||||
try {
|
try {
|
||||||
if (event.functions.isEmpty) return;
|
if (event.functions.isEmpty) return;
|
||||||
|
|
||||||
List<DeviceFunctionData> selectedFunction = List<DeviceFunctionData>.from(event.functions);
|
List<DeviceFunctionData> selectedFunction =
|
||||||
|
List<DeviceFunctionData>.from(event.functions);
|
||||||
|
|
||||||
Map<String, List<DeviceFunctionData>> currentSelectedFunctions =
|
Map<String, List<DeviceFunctionData>> currentSelectedFunctions =
|
||||||
Map<String, List<DeviceFunctionData>>.from(state.selectedFunctions);
|
Map<String, List<DeviceFunctionData>>.from(state.selectedFunctions);
|
||||||
if (currentSelectedFunctions.containsKey(event.uniqueCustomId)) {
|
if (currentSelectedFunctions.containsKey(event.uniqueCustomId)) {
|
||||||
List<DeviceFunctionData> currentFunctions =
|
List<DeviceFunctionData> currentFunctions =
|
||||||
List<DeviceFunctionData>.from(currentSelectedFunctions[event.uniqueCustomId] ?? []);
|
List<DeviceFunctionData>.from(
|
||||||
|
currentSelectedFunctions[event.uniqueCustomId] ?? []);
|
||||||
|
|
||||||
List<String> functionCode = [];
|
List<String> functionCode = [];
|
||||||
for (int i = 0; i < selectedFunction.length; i++) {
|
for (int i = 0; i < selectedFunction.length; i++) {
|
||||||
for (int j = 0; j < currentFunctions.length; j++) {
|
for (int j = 0; j < currentFunctions.length; j++) {
|
||||||
if (selectedFunction[i].functionCode == currentFunctions[j].functionCode) {
|
if (selectedFunction[i].functionCode ==
|
||||||
|
currentFunctions[j].functionCode) {
|
||||||
currentFunctions[j] = selectedFunction[i];
|
currentFunctions[j] = selectedFunction[i];
|
||||||
if (!functionCode.contains(currentFunctions[j].functionCode)) {
|
if (!functionCode.contains(currentFunctions[j].functionCode)) {
|
||||||
functionCode.add(currentFunctions[j].functionCode);
|
functionCode.add(currentFunctions[j].functionCode);
|
||||||
@ -137,13 +152,15 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < functionCode.length; i++) {
|
for (int i = 0; i < functionCode.length; i++) {
|
||||||
selectedFunction.removeWhere((code) => code.functionCode == functionCode[i]);
|
selectedFunction
|
||||||
|
.removeWhere((code) => code.functionCode == functionCode[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
currentSelectedFunctions[event.uniqueCustomId] = List.from(currentFunctions)
|
currentSelectedFunctions[event.uniqueCustomId] =
|
||||||
..addAll(selectedFunction);
|
List.from(currentFunctions)..addAll(selectedFunction);
|
||||||
} else {
|
} else {
|
||||||
currentSelectedFunctions[event.uniqueCustomId] = List.from(event.functions);
|
currentSelectedFunctions[event.uniqueCustomId] =
|
||||||
|
List.from(event.functions);
|
||||||
}
|
}
|
||||||
|
|
||||||
emit(state.copyWith(selectedFunctions: currentSelectedFunctions));
|
emit(state.copyWith(selectedFunctions: currentSelectedFunctions));
|
||||||
@ -152,18 +169,24 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _onLoadScenes(LoadScenes event, Emitter<RoutineState> emit) async {
|
Future<void> _onLoadScenes(
|
||||||
|
LoadScenes event, Emitter<RoutineState> emit) async {
|
||||||
emit(state.copyWith(isLoading: true, errorMessage: null));
|
emit(state.copyWith(isLoading: true, errorMessage: null));
|
||||||
|
List<ScenesModel> scenes = [];
|
||||||
try {
|
try {
|
||||||
spaceId = event.spaceId;
|
final projectUuid = await ProjectManager.getProjectUUID() ?? '';
|
||||||
communityId = event.communityId;
|
|
||||||
|
|
||||||
List<ScenesModel> scenes = [];
|
BuildContext context = NavigationService.navigatorKey.currentContext!;
|
||||||
|
var spaceBloc = context.read<SpaceTreeBloc>();
|
||||||
if (communityId.isNotEmpty && spaceId.isNotEmpty) {
|
for (var communityId in spaceBloc.state.selectedCommunities) {
|
||||||
scenes = await SceneApi.getScenes(event.spaceId, event.communityId);
|
List<String> spacesList =
|
||||||
|
spaceBloc.state.selectedCommunityAndSpaces[communityId] ?? [];
|
||||||
|
for (var spaceId in spacesList) {
|
||||||
|
scenes.addAll(
|
||||||
|
await SceneApi.getScenes(spaceId, communityId, projectUuid));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
scenes: scenes,
|
scenes: scenes,
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
@ -174,18 +197,24 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
loadScenesErrorMessage: 'Failed to load scenes',
|
loadScenesErrorMessage: 'Failed to load scenes',
|
||||||
errorMessage: '',
|
errorMessage: '',
|
||||||
loadAutomationErrorMessage: '',
|
loadAutomationErrorMessage: '',
|
||||||
scenes: []));
|
scenes: scenes));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _onLoadAutomation(LoadAutomation event, Emitter<RoutineState> emit) async {
|
Future<void> _onLoadAutomation(
|
||||||
|
LoadAutomation event, Emitter<RoutineState> emit) async {
|
||||||
emit(state.copyWith(isLoading: true, errorMessage: null));
|
emit(state.copyWith(isLoading: true, errorMessage: null));
|
||||||
|
List<ScenesModel> automations = [];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
spaceId = event.spaceId;
|
BuildContext context = NavigationService.navigatorKey.currentContext!;
|
||||||
List<ScenesModel> automations = [];
|
var spaceBloc = context.read<SpaceTreeBloc>();
|
||||||
if (spaceId.isNotEmpty) {
|
for (var communityId in spaceBloc.state.selectedCommunities) {
|
||||||
automations = await SceneApi.getAutomation(event.spaceId);
|
List<String> spacesList =
|
||||||
|
spaceBloc.state.selectedCommunityAndSpaces[communityId] ?? [];
|
||||||
|
for (var spaceId in spacesList) {
|
||||||
|
automations.addAll(await SceneApi.getAutomation(spaceId));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
automations: automations,
|
automations: automations,
|
||||||
@ -197,18 +226,20 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
loadAutomationErrorMessage: 'Failed to load automations',
|
loadAutomationErrorMessage: 'Failed to load automations',
|
||||||
errorMessage: '',
|
errorMessage: '',
|
||||||
loadScenesErrorMessage: '',
|
loadScenesErrorMessage: '',
|
||||||
automations: []));
|
automations: automations));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FutureOr<void> _onSearchRoutines(SearchRoutines event, Emitter<RoutineState> emit) async {
|
FutureOr<void> _onSearchRoutines(
|
||||||
|
SearchRoutines event, Emitter<RoutineState> emit) async {
|
||||||
emit(state.copyWith(isLoading: true, errorMessage: null));
|
emit(state.copyWith(isLoading: true, errorMessage: null));
|
||||||
await Future.delayed(const Duration(seconds: 1));
|
await Future.delayed(const Duration(seconds: 1));
|
||||||
emit(state.copyWith(isLoading: false, errorMessage: null));
|
emit(state.copyWith(isLoading: false, errorMessage: null));
|
||||||
emit(state.copyWith(searchText: event.query));
|
emit(state.copyWith(searchText: event.query));
|
||||||
}
|
}
|
||||||
|
|
||||||
FutureOr<void> _onAddSelectedIcon(AddSelectedIcon event, Emitter<RoutineState> emit) {
|
FutureOr<void> _onAddSelectedIcon(
|
||||||
|
AddSelectedIcon event, Emitter<RoutineState> emit) {
|
||||||
emit(state.copyWith(selectedIcon: event.icon));
|
emit(state.copyWith(selectedIcon: event.icon));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,7 +253,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
return actions.last['deviceId'] == 'delay';
|
return actions.last['deviceId'] == 'delay';
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _onCreateScene(CreateSceneEvent event, Emitter<RoutineState> emit) async {
|
Future<void> _onCreateScene(
|
||||||
|
CreateSceneEvent event, Emitter<RoutineState> emit) async {
|
||||||
try {
|
try {
|
||||||
// Check if first action is delay
|
// Check if first action is delay
|
||||||
// if (_isFirstActionDelay(state.thenItems)) {
|
// if (_isFirstActionDelay(state.thenItems)) {
|
||||||
@ -235,7 +267,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
|
|
||||||
if (_isLastActionDelay(state.thenItems)) {
|
if (_isLastActionDelay(state.thenItems)) {
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
errorMessage: 'A delay condition cannot be the only or the last action',
|
errorMessage:
|
||||||
|
'A delay condition cannot be the only or the last action',
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
));
|
));
|
||||||
return;
|
return;
|
||||||
@ -280,8 +313,11 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
});
|
});
|
||||||
}).toList();
|
}).toList();
|
||||||
|
|
||||||
|
BuildContext context = NavigationService.navigatorKey.currentContext!;
|
||||||
|
var spaceBloc = context.read<SpaceTreeBloc>();
|
||||||
|
|
||||||
final createSceneModel = CreateSceneModel(
|
final createSceneModel = CreateSceneModel(
|
||||||
spaceUuid: spaceId,
|
spaceUuid: spaceBloc.state.selectedSpaces[0],
|
||||||
iconId: state.selectedIcon ?? '',
|
iconId: state.selectedIcon ?? '',
|
||||||
showInDevice: true,
|
showInDevice: true,
|
||||||
sceneName: state.routineName ?? '',
|
sceneName: state.routineName ?? '',
|
||||||
@ -292,8 +328,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
final result = await SceneApi.createScene(createSceneModel);
|
final result = await SceneApi.createScene(createSceneModel);
|
||||||
if (result['success']) {
|
if (result['success']) {
|
||||||
add(ResetRoutineState());
|
add(ResetRoutineState());
|
||||||
add(LoadScenes(spaceId, communityId));
|
add(const LoadScenes());
|
||||||
add(LoadAutomation(spaceId));
|
add(const LoadAutomation());
|
||||||
} else {
|
} else {
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
@ -308,7 +344,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _onCreateAutomation(CreateAutomationEvent event, Emitter<RoutineState> emit) async {
|
Future<void> _onCreateAutomation(
|
||||||
|
CreateAutomationEvent event, Emitter<RoutineState> emit) async {
|
||||||
try {
|
try {
|
||||||
if (state.routineName == null || state.routineName!.isEmpty) {
|
if (state.routineName == null || state.routineName!.isEmpty) {
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
@ -329,7 +366,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
|
|
||||||
if (_isLastActionDelay(state.thenItems)) {
|
if (_isLastActionDelay(state.thenItems)) {
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
errorMessage: 'A delay condition cannot be the only or the last action',
|
errorMessage:
|
||||||
|
'A delay condition cannot be the only or the last action',
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
));
|
));
|
||||||
CustomSnackBar.redSnackBar('Cannot have delay as the last action');
|
CustomSnackBar.redSnackBar('Cannot have delay as the last action');
|
||||||
@ -404,9 +442,11 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
}).toList();
|
}).toList();
|
||||||
|
BuildContext context = NavigationService.navigatorKey.currentContext!;
|
||||||
|
var spaceBloc = context.read<SpaceTreeBloc>();
|
||||||
|
|
||||||
final createAutomationModel = CreateAutomationModel(
|
final createAutomationModel = CreateAutomationModel(
|
||||||
spaceUuid: spaceId,
|
spaceUuid: spaceBloc.state.selectedSpaces[0],
|
||||||
automationName: state.routineName ?? '',
|
automationName: state.routineName ?? '',
|
||||||
decisionExpr: state.selectedAutomationOperator,
|
decisionExpr: state.selectedAutomationOperator,
|
||||||
effectiveTime: EffectiveTime(
|
effectiveTime: EffectiveTime(
|
||||||
@ -421,8 +461,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
final result = await SceneApi.createAutomation(createAutomationModel);
|
final result = await SceneApi.createAutomation(createAutomationModel);
|
||||||
if (result['success']) {
|
if (result['success']) {
|
||||||
add(ResetRoutineState());
|
add(ResetRoutineState());
|
||||||
add(LoadAutomation(spaceId));
|
add(const LoadAutomation());
|
||||||
add(LoadScenes(spaceId, communityId));
|
add(const LoadScenes());
|
||||||
} else {
|
} else {
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
@ -439,17 +479,21 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FutureOr<void> _onRemoveDragCard(RemoveDragCard event, Emitter<RoutineState> emit) {
|
FutureOr<void> _onRemoveDragCard(
|
||||||
|
RemoveDragCard event, Emitter<RoutineState> emit) {
|
||||||
if (event.isFromThen) {
|
if (event.isFromThen) {
|
||||||
final thenItems = List<Map<String, dynamic>>.from(state.thenItems);
|
final thenItems = List<Map<String, dynamic>>.from(state.thenItems);
|
||||||
final selectedFunctions = Map<String, List<DeviceFunctionData>>.from(state.selectedFunctions);
|
final selectedFunctions =
|
||||||
|
Map<String, List<DeviceFunctionData>>.from(state.selectedFunctions);
|
||||||
|
|
||||||
thenItems.removeAt(event.index);
|
thenItems.removeAt(event.index);
|
||||||
selectedFunctions.remove(event.key);
|
selectedFunctions.remove(event.key);
|
||||||
emit(state.copyWith(thenItems: thenItems, selectedFunctions: selectedFunctions));
|
emit(state.copyWith(
|
||||||
|
thenItems: thenItems, selectedFunctions: selectedFunctions));
|
||||||
} else {
|
} else {
|
||||||
final ifItems = List<Map<String, dynamic>>.from(state.ifItems);
|
final ifItems = List<Map<String, dynamic>>.from(state.ifItems);
|
||||||
final selectedFunctions = Map<String, List<DeviceFunctionData>>.from(state.selectedFunctions);
|
final selectedFunctions =
|
||||||
|
Map<String, List<DeviceFunctionData>>.from(state.selectedFunctions);
|
||||||
|
|
||||||
ifItems.removeAt(event.index);
|
ifItems.removeAt(event.index);
|
||||||
selectedFunctions.remove(event.key);
|
selectedFunctions.remove(event.key);
|
||||||
@ -460,7 +504,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
isAutomation: false,
|
isAutomation: false,
|
||||||
isTabToRun: false));
|
isTabToRun: false));
|
||||||
} else {
|
} else {
|
||||||
emit(state.copyWith(ifItems: ifItems, selectedFunctions: selectedFunctions));
|
emit(state.copyWith(
|
||||||
|
ifItems: ifItems, selectedFunctions: selectedFunctions));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -472,18 +517,23 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
FutureOr<void> _onEffectiveTimeEvent(EffectiveTimePeriodEvent event, Emitter<RoutineState> emit) {
|
FutureOr<void> _onEffectiveTimeEvent(
|
||||||
|
EffectiveTimePeriodEvent event, Emitter<RoutineState> emit) {
|
||||||
emit(state.copyWith(effectiveTime: event.effectiveTime));
|
emit(state.copyWith(effectiveTime: event.effectiveTime));
|
||||||
}
|
}
|
||||||
|
|
||||||
FutureOr<void> _onSetRoutineName(SetRoutineName event, Emitter<RoutineState> emit) {
|
FutureOr<void> _onSetRoutineName(
|
||||||
|
SetRoutineName event, Emitter<RoutineState> emit) {
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
routineName: event.name,
|
routineName: event.name,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
(List<Map<String, dynamic>>, List<Map<String, dynamic>>, Map<String, List<DeviceFunctionData>>)
|
(
|
||||||
_createCardData(
|
List<Map<String, dynamic>>,
|
||||||
|
List<Map<String, dynamic>>,
|
||||||
|
Map<String, List<DeviceFunctionData>>
|
||||||
|
) _createCardData(
|
||||||
List<RoutineAction> actions,
|
List<RoutineAction> actions,
|
||||||
List<RoutineCondition>? conditions,
|
List<RoutineCondition>? conditions,
|
||||||
Map<String, List<DeviceFunctionData>> currentFunctions,
|
Map<String, List<DeviceFunctionData>> currentFunctions,
|
||||||
@ -516,7 +566,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
'deviceId': condition.entityId,
|
'deviceId': condition.entityId,
|
||||||
'title': matchingDevice.name ?? condition.entityId,
|
'title': matchingDevice.name ?? condition.entityId,
|
||||||
'productType': condition.entityType,
|
'productType': condition.entityType,
|
||||||
'imagePath': matchingDevice.getDefaultIcon(condition.entityType),
|
'imagePath':
|
||||||
|
matchingDevice.getDefaultIcon(condition.entityType),
|
||||||
};
|
};
|
||||||
|
|
||||||
final functions = matchingDevice.functions;
|
final functions = matchingDevice.functions;
|
||||||
@ -552,8 +603,11 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
final cardData = {
|
final cardData = {
|
||||||
'entityId': action.entityId,
|
'entityId': action.entityId,
|
||||||
'uniqueCustomId': const Uuid().v4(),
|
'uniqueCustomId': const Uuid().v4(),
|
||||||
'deviceId': action.actionExecutor == 'delay' ? 'delay' : action.entityId,
|
'deviceId':
|
||||||
'title': action.actionExecutor == 'delay' ? 'Delay' : (matchingDevice.name ?? 'Device'),
|
action.actionExecutor == 'delay' ? 'delay' : action.entityId,
|
||||||
|
'title': action.actionExecutor == 'delay'
|
||||||
|
? 'Delay'
|
||||||
|
: (matchingDevice.name ?? 'Device'),
|
||||||
'productType': action.productType,
|
'productType': action.productType,
|
||||||
'imagePath': matchingDevice.getDefaultIcon(action.productType),
|
'imagePath': matchingDevice.getDefaultIcon(action.productType),
|
||||||
};
|
};
|
||||||
@ -596,7 +650,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
return (thenItems, ifItems, currentFunctions);
|
return (thenItems, ifItems, currentFunctions);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _onGetSceneDetails(GetSceneDetails event, Emitter<RoutineState> emit) async {
|
Future<void> _onGetSceneDetails(
|
||||||
|
GetSceneDetails event, Emitter<RoutineState> emit) async {
|
||||||
try {
|
try {
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
isLoading: true,
|
isLoading: true,
|
||||||
@ -644,10 +699,12 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
if (!deviceCards.containsKey(deviceId)) {
|
if (!deviceCards.containsKey(deviceId)) {
|
||||||
deviceCards[deviceId] = {
|
deviceCards[deviceId] = {
|
||||||
'entityId': action.entityId,
|
'entityId': action.entityId,
|
||||||
'deviceId': action.actionExecutor == 'delay' ? 'delay' : action.entityId,
|
'deviceId':
|
||||||
'uniqueCustomId': action.type == 'automation' || action.actionExecutor == 'delay'
|
action.actionExecutor == 'delay' ? 'delay' : action.entityId,
|
||||||
? const Uuid().v4()
|
'uniqueCustomId':
|
||||||
: action.entityId,
|
action.type == 'automation' || action.actionExecutor == 'delay'
|
||||||
|
? const Uuid().v4()
|
||||||
|
: action.entityId,
|
||||||
'title': action.actionExecutor == 'delay'
|
'title': action.actionExecutor == 'delay'
|
||||||
? 'Delay'
|
? 'Delay'
|
||||||
: action.type == 'automation'
|
: action.type == 'automation'
|
||||||
@ -682,7 +739,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
// emit(state.copyWith(automationActionExecutor: action.actionExecutor));
|
// emit(state.copyWith(automationActionExecutor: action.actionExecutor));
|
||||||
} else if (action.executorProperty != null && action.actionExecutor != 'delay') {
|
} else if (action.executorProperty != null &&
|
||||||
|
action.actionExecutor != 'delay') {
|
||||||
if (!updatedFunctions.containsKey(uniqueCustomId)) {
|
if (!updatedFunctions.containsKey(uniqueCustomId)) {
|
||||||
updatedFunctions[uniqueCustomId] = [];
|
updatedFunctions[uniqueCustomId] = [];
|
||||||
}
|
}
|
||||||
@ -754,7 +812,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FutureOr<void> _onResetRoutineState(ResetRoutineState event, Emitter<RoutineState> emit) {
|
FutureOr<void> _onResetRoutineState(
|
||||||
|
ResetRoutineState event, Emitter<RoutineState> emit) {
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
ifItems: [],
|
ifItems: [],
|
||||||
thenItems: [],
|
thenItems: [],
|
||||||
@ -778,17 +837,24 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
createRoutineView: false));
|
createRoutineView: false));
|
||||||
}
|
}
|
||||||
|
|
||||||
FutureOr<void> _deleteScene(DeleteScene event, Emitter<RoutineState> emit) {
|
FutureOr<void> _deleteScene(
|
||||||
|
DeleteScene event, Emitter<RoutineState> emit) async {
|
||||||
try {
|
try {
|
||||||
emit(state.copyWith(isLoading: true));
|
emit(state.copyWith(isLoading: true));
|
||||||
|
BuildContext context = NavigationService.navigatorKey.currentContext!;
|
||||||
|
var spaceBloc = context.read<SpaceTreeBloc>();
|
||||||
if (state.isTabToRun) {
|
if (state.isTabToRun) {
|
||||||
SceneApi.deleteScene(unitUuid: spaceId, sceneId: state.sceneId ?? '');
|
await SceneApi.deleteScene(
|
||||||
|
unitUuid: spaceBloc.state.selectedSpaces[0],
|
||||||
|
sceneId: state.sceneId ?? '');
|
||||||
} else {
|
} else {
|
||||||
SceneApi.deleteAutomation(unitUuid: spaceId, automationId: state.automationId ?? '');
|
await SceneApi.deleteAutomation(
|
||||||
|
unitUuid: spaceBloc.state.selectedSpaces[0],
|
||||||
|
automationId: state.automationId ?? '');
|
||||||
}
|
}
|
||||||
|
|
||||||
add(LoadScenes(spaceId, communityId));
|
add(const LoadScenes());
|
||||||
add(LoadAutomation(spaceId));
|
add(const LoadAutomation());
|
||||||
add(ResetRoutineState());
|
add(ResetRoutineState());
|
||||||
emit(state.copyWith(isLoading: false, createRoutineView: false));
|
emit(state.copyWith(isLoading: false, createRoutineView: false));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -813,10 +879,24 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
FutureOr<void> _fetchDevices(FetchDevicesInRoutine event, Emitter<RoutineState> emit) async {
|
FutureOr<void> _fetchDevices(
|
||||||
|
FetchDevicesInRoutine event, Emitter<RoutineState> emit) async {
|
||||||
emit(state.copyWith(isLoading: true));
|
emit(state.copyWith(isLoading: true));
|
||||||
try {
|
try {
|
||||||
final devices = await DevicesManagementApi().fetchDevices('', '');
|
final projectUuid = await ProjectManager.getProjectUUID() ?? '';
|
||||||
|
|
||||||
|
List<AllDevicesModel> devices = [];
|
||||||
|
|
||||||
|
BuildContext context = NavigationService.navigatorKey.currentContext!;
|
||||||
|
var spaceBloc = context.read<SpaceTreeBloc>();
|
||||||
|
for (var communityId in spaceBloc.state.selectedCommunities) {
|
||||||
|
List<String> spacesList =
|
||||||
|
spaceBloc.state.selectedCommunityAndSpaces[communityId] ?? [];
|
||||||
|
for (var spaceId in spacesList) {
|
||||||
|
devices.addAll(await DevicesManagementApi()
|
||||||
|
.fetchDevices(communityId, spaceId, projectUuid));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
emit(state.copyWith(isLoading: false, devices: devices));
|
emit(state.copyWith(isLoading: false, devices: devices));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -824,7 +904,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FutureOr<void> _onUpdateScene(UpdateScene event, Emitter<RoutineState> emit) async {
|
FutureOr<void> _onUpdateScene(
|
||||||
|
UpdateScene event, Emitter<RoutineState> emit) async {
|
||||||
try {
|
try {
|
||||||
// Check if first action is delay
|
// Check if first action is delay
|
||||||
// if (_isFirstActionDelay(state.thenItems)) {
|
// if (_isFirstActionDelay(state.thenItems)) {
|
||||||
@ -838,7 +919,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
|
|
||||||
if (_isLastActionDelay(state.thenItems)) {
|
if (_isLastActionDelay(state.thenItems)) {
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
errorMessage: 'A delay condition cannot be the only or the last action',
|
errorMessage:
|
||||||
|
'A delay condition cannot be the only or the last action',
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
));
|
));
|
||||||
return;
|
return;
|
||||||
@ -891,11 +973,12 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
actions: actions,
|
actions: actions,
|
||||||
);
|
);
|
||||||
|
|
||||||
final result = await SceneApi.updateScene(createSceneModel, state.sceneId ?? '');
|
final result =
|
||||||
|
await SceneApi.updateScene(createSceneModel, state.sceneId ?? '');
|
||||||
if (result['success']) {
|
if (result['success']) {
|
||||||
add(ResetRoutineState());
|
add(ResetRoutineState());
|
||||||
add(LoadScenes(spaceId, communityId));
|
add(const LoadScenes());
|
||||||
add(LoadAutomation(spaceId));
|
add(const LoadAutomation());
|
||||||
} else {
|
} else {
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
@ -910,7 +993,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FutureOr<void> _onUpdateAutomation(UpdateAutomation event, Emitter<RoutineState> emit) async {
|
FutureOr<void> _onUpdateAutomation(
|
||||||
|
UpdateAutomation event, Emitter<RoutineState> emit) async {
|
||||||
try {
|
try {
|
||||||
if (state.routineName == null || state.routineName!.isEmpty) {
|
if (state.routineName == null || state.routineName!.isEmpty) {
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
@ -1005,8 +1089,11 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
});
|
});
|
||||||
}).toList();
|
}).toList();
|
||||||
|
|
||||||
|
BuildContext context = NavigationService.navigatorKey.currentContext!;
|
||||||
|
var spaceBloc = context.read<SpaceTreeBloc>();
|
||||||
|
|
||||||
final createAutomationModel = CreateAutomationModel(
|
final createAutomationModel = CreateAutomationModel(
|
||||||
spaceUuid: spaceId,
|
spaceUuid: spaceBloc.state.selectedSpaces[0],
|
||||||
automationName: state.routineName ?? '',
|
automationName: state.routineName ?? '',
|
||||||
decisionExpr: state.selectedAutomationOperator,
|
decisionExpr: state.selectedAutomationOperator,
|
||||||
effectiveTime: EffectiveTime(
|
effectiveTime: EffectiveTime(
|
||||||
@ -1018,13 +1105,13 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
actions: actions,
|
actions: actions,
|
||||||
);
|
);
|
||||||
|
|
||||||
final result =
|
final result = await SceneApi.updateAutomation(
|
||||||
await SceneApi.updateAutomation(createAutomationModel, state.automationId ?? '');
|
createAutomationModel, state.automationId ?? '');
|
||||||
|
|
||||||
if (result['success']) {
|
if (result['success']) {
|
||||||
add(ResetRoutineState());
|
add(ResetRoutineState());
|
||||||
add(LoadAutomation(spaceId));
|
add(LoadAutomation());
|
||||||
add(LoadScenes(spaceId, communityId));
|
add(LoadScenes());
|
||||||
} else {
|
} else {
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
@ -1052,7 +1139,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
thenItems: [],
|
thenItems: [],
|
||||||
));
|
));
|
||||||
|
|
||||||
final automationDetails = await SceneApi.getAutomationDetails(event.automationId);
|
final automationDetails =
|
||||||
|
await SceneApi.getAutomationDetails(event.automationId);
|
||||||
|
|
||||||
final Map<String, Map<String, dynamic>> deviceIfCards = {};
|
final Map<String, Map<String, dynamic>> deviceIfCards = {};
|
||||||
final Map<String, Map<String, dynamic>> deviceThenCards = {};
|
final Map<String, Map<String, dynamic>> deviceThenCards = {};
|
||||||
@ -1120,13 +1208,15 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
final deviceId =
|
final deviceId = action.actionExecutor == 'delay'
|
||||||
action.actionExecutor == 'delay' ? '${action.entityId}_delay' : action.entityId;
|
? '${action.entityId}_delay'
|
||||||
|
: action.entityId;
|
||||||
|
|
||||||
if (!deviceThenCards.containsKey(deviceId)) {
|
if (!deviceThenCards.containsKey(deviceId)) {
|
||||||
deviceThenCards[deviceId] = {
|
deviceThenCards[deviceId] = {
|
||||||
'entityId': action.entityId,
|
'entityId': action.entityId,
|
||||||
'deviceId': action.actionExecutor == 'delay' ? 'delay' : action.entityId,
|
'deviceId':
|
||||||
|
action.actionExecutor == 'delay' ? 'delay' : action.entityId,
|
||||||
'uniqueCustomId': const Uuid().v4(),
|
'uniqueCustomId': const Uuid().v4(),
|
||||||
'title': action.actionExecutor == 'delay'
|
'title': action.actionExecutor == 'delay'
|
||||||
? 'Delay'
|
? 'Delay'
|
||||||
@ -1157,7 +1247,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
updatedFunctions[uniqueCustomId] = [];
|
updatedFunctions[uniqueCustomId] = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action.executorProperty != null && action.actionExecutor != 'delay') {
|
if (action.executorProperty != null &&
|
||||||
|
action.actionExecutor != 'delay') {
|
||||||
final functions = matchingDevice.functions;
|
final functions = matchingDevice.functions;
|
||||||
final functionCode = action.executorProperty!.functionCode;
|
final functionCode = action.executorProperty!.functionCode;
|
||||||
for (var function in functions) {
|
for (var function in functions) {
|
||||||
@ -1199,10 +1290,14 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final ifItems = deviceIfCards.values.where((card) => card['type'] == 'condition').toList();
|
final ifItems = deviceIfCards.values
|
||||||
|
.where((card) => card['type'] == 'condition')
|
||||||
|
.toList();
|
||||||
final thenItems = deviceThenCards.values
|
final thenItems = deviceThenCards.values
|
||||||
.where((card) =>
|
.where((card) =>
|
||||||
card['type'] == 'action' || card['type'] == 'automation' || card['type'] == 'scene')
|
card['type'] == 'action' ||
|
||||||
|
card['type'] == 'automation' ||
|
||||||
|
card['type'] == 'scene')
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
|
@ -27,22 +27,24 @@ class AddToThenContainer extends RoutineEvent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class LoadScenes extends RoutineEvent {
|
class LoadScenes extends RoutineEvent {
|
||||||
final String spaceId;
|
// final String spaceId;
|
||||||
final String communityId;
|
// final String communityId;
|
||||||
|
// final BuildContext context;
|
||||||
|
|
||||||
const LoadScenes(this.spaceId, this.communityId);
|
const LoadScenes();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [spaceId, communityId];
|
List<Object> get props => [];
|
||||||
}
|
}
|
||||||
|
|
||||||
class LoadAutomation extends RoutineEvent {
|
class LoadAutomation extends RoutineEvent {
|
||||||
final String spaceId;
|
// final String spaceId;
|
||||||
|
// final BuildContext context;
|
||||||
|
|
||||||
const LoadAutomation(this.spaceId);
|
const LoadAutomation();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [spaceId];
|
List<Object> get props => [];
|
||||||
}
|
}
|
||||||
|
|
||||||
class AddFunctionToRoutine extends RoutineEvent {
|
class AddFunctionToRoutine extends RoutineEvent {
|
||||||
|
@ -7,7 +7,6 @@ import 'package:syncrow_web/pages/routines/widgets/main_routine_view/routine_vie
|
|||||||
import 'package:syncrow_web/pages/space_tree/bloc/space_tree_bloc.dart';
|
import 'package:syncrow_web/pages/space_tree/bloc/space_tree_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/space_tree/view/space_tree_view.dart';
|
import 'package:syncrow_web/pages/space_tree/view/space_tree_view.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
import 'package:syncrow_web/utils/snack_bar.dart';
|
|
||||||
|
|
||||||
class RoutinesView extends StatefulWidget {
|
class RoutinesView extends StatefulWidget {
|
||||||
const RoutinesView({super.key});
|
const RoutinesView({super.key});
|
||||||
@ -20,7 +19,7 @@ class _RoutinesViewState extends State<RoutinesView> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
context.read<RoutineBloc>().add(FetchDevicesInRoutine());
|
// context.read<RoutineBloc>().add(FetchDevicesInRoutine());
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -32,9 +31,12 @@ class _RoutinesViewState extends State<RoutinesView> {
|
|||||||
}
|
}
|
||||||
return Row(
|
return Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(child: SpaceTreeView(
|
||||||
child: SpaceTreeView(
|
onSelect: () {
|
||||||
onSelect: () {},
|
context.read<RoutineBloc>()
|
||||||
|
..add(const LoadScenes())
|
||||||
|
..add(const LoadAutomation());
|
||||||
|
},
|
||||||
)),
|
)),
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 4,
|
flex: 4,
|
||||||
@ -59,8 +61,8 @@ class _RoutinesViewState extends State<RoutinesView> {
|
|||||||
),
|
),
|
||||||
RoutineViewCard(
|
RoutineViewCard(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
if (context.read<SpaceTreeBloc>().selectedCommunityId.isNotEmpty &&
|
if (context.read<SpaceTreeBloc>().state.selectedCommunities.length == 1 &&
|
||||||
context.read<SpaceTreeBloc>().selectedSpaceId.isNotEmpty) {
|
context.read<SpaceTreeBloc>().state.selectedSpaces.length == 1) {
|
||||||
context.read<RoutineBloc>().add(
|
context.read<RoutineBloc>().add(
|
||||||
(ResetRoutineState()),
|
(ResetRoutineState()),
|
||||||
);
|
);
|
||||||
@ -68,7 +70,18 @@ class _RoutinesViewState extends State<RoutinesView> {
|
|||||||
const CreateNewRoutineViewEvent(createRoutineView: true),
|
const CreateNewRoutineViewEvent(createRoutineView: true),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
CustomSnackBar.redSnackBar('Please select a space');
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
SnackBar(
|
||||||
|
content: Text(
|
||||||
|
context.read<SpaceTreeBloc>().state.selectedSpaces.isEmpty
|
||||||
|
? 'Please select a space'
|
||||||
|
: 'Please select only one space to proceed'),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
// CustomSnackBar.redSnackBar(
|
||||||
|
// context.read<SpaceTreeBloc>().state.selectedSpaces.isEmpty
|
||||||
|
// ? 'Please select a space'
|
||||||
|
// : 'Please select only one space to proceed');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
icon: Icons.add,
|
icon: Icons.add,
|
||||||
|
@ -20,10 +20,6 @@ class _FetchRoutineScenesState extends State<FetchRoutineScenesAutomation>
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
context.read<RoutineBloc>()
|
|
||||||
..add(LoadScenes(context.read<SpaceTreeBloc>().selectedSpaceId,
|
|
||||||
context.read<SpaceTreeBloc>().selectedCommunityId))
|
|
||||||
..add(LoadAutomation(context.read<SpaceTreeBloc>().selectedSpaceId));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -4,9 +4,20 @@ import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_mo
|
|||||||
import 'package:syncrow_web/pages/routines/bloc/routine_bloc/routine_bloc.dart';
|
import 'package:syncrow_web/pages/routines/bloc/routine_bloc/routine_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/routines/widgets/dragable_card.dart';
|
import 'package:syncrow_web/pages/routines/widgets/dragable_card.dart';
|
||||||
|
|
||||||
class RoutineDevices extends StatelessWidget {
|
class RoutineDevices extends StatefulWidget {
|
||||||
const RoutineDevices({super.key});
|
const RoutineDevices({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<RoutineDevices> createState() => _RoutineDevicesState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _RoutineDevicesState extends State<RoutineDevices> {
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
context.read<RoutineBloc>().add(FetchDevicesInRoutine());
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocBuilder<RoutineBloc, RoutineState>(
|
return BlocBuilder<RoutineBloc, RoutineState>(
|
||||||
|
@ -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/routines/bloc/routine_bloc/routine_bloc.dart';
|
import 'package:syncrow_web/pages/routines/bloc/routine_bloc/routine_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/routines/widgets/dragable_card.dart';
|
import 'package:syncrow_web/pages/routines/widgets/dragable_card.dart';
|
||||||
import 'package:syncrow_web/pages/space_tree/bloc/space_tree_bloc.dart';
|
|
||||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||||
|
|
||||||
class ScenesAndAutomations extends StatefulWidget {
|
class ScenesAndAutomations extends StatefulWidget {
|
||||||
@ -19,9 +18,8 @@ class _ScenesAndAutomationsState extends State<ScenesAndAutomations> {
|
|||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
context.read<RoutineBloc>()
|
context.read<RoutineBloc>()
|
||||||
..add(LoadScenes(context.read<SpaceTreeBloc>().selectedSpaceId,
|
..add(const LoadScenes())
|
||||||
context.read<SpaceTreeBloc>().selectedCommunityId))
|
..add(const LoadAutomation());
|
||||||
..add(LoadAutomation(context.read<SpaceTreeBloc>().selectedSpaceId));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/common/bloc/project_manager.dart';
|
||||||
import 'package:syncrow_web/pages/space_tree/bloc/space_tree_event.dart';
|
import 'package:syncrow_web/pages/space_tree/bloc/space_tree_event.dart';
|
||||||
import 'package:syncrow_web/pages/space_tree/bloc/space_tree_state.dart';
|
import 'package:syncrow_web/pages/space_tree/bloc/space_tree_state.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart';
|
||||||
@ -6,9 +7,6 @@ import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model
|
|||||||
import 'package:syncrow_web/services/space_mana_api.dart';
|
import 'package:syncrow_web/services/space_mana_api.dart';
|
||||||
|
|
||||||
class SpaceTreeBloc extends Bloc<SpaceTreeEvent, SpaceTreeState> {
|
class SpaceTreeBloc extends Bloc<SpaceTreeEvent, SpaceTreeState> {
|
||||||
String selectedCommunityId = 'aff21a57-2f91-4e5c-b99b-0182c3ab65a9';
|
|
||||||
String selectedSpaceId = '25c96044-fadf-44bb-93c7-3c079e527ce6';
|
|
||||||
|
|
||||||
SpaceTreeBloc() : super(const SpaceTreeState()) {
|
SpaceTreeBloc() : super(const SpaceTreeState()) {
|
||||||
on<InitialEvent>(_fetchSpaces);
|
on<InitialEvent>(_fetchSpaces);
|
||||||
on<OnCommunityExpanded>(_onCommunityExpanded);
|
on<OnCommunityExpanded>(_onCommunityExpanded);
|
||||||
@ -16,17 +14,49 @@ class SpaceTreeBloc extends Bloc<SpaceTreeEvent, SpaceTreeState> {
|
|||||||
on<OnCommunitySelected>(_onCommunitySelected);
|
on<OnCommunitySelected>(_onCommunitySelected);
|
||||||
on<OnSpaceSelected>(_onSpaceSelected);
|
on<OnSpaceSelected>(_onSpaceSelected);
|
||||||
on<SearchQueryEvent>(_onSearch);
|
on<SearchQueryEvent>(_onSearch);
|
||||||
|
on<ClearAllData>(_clearAllData);
|
||||||
|
on<ClearCachedData>(_clearCachedData);
|
||||||
|
on<OnCommunityAdded>(_onCommunityAdded);
|
||||||
|
on<OnCommunityUpdated>(_onCommunityUpdate);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onCommunityUpdate(
|
||||||
|
OnCommunityUpdated event,
|
||||||
|
Emitter<SpaceTreeState> emit,
|
||||||
|
) async {
|
||||||
|
emit(SpaceTreeLoadingState());
|
||||||
|
|
||||||
|
try {
|
||||||
|
final updatedCommunity = event.updatedCommunity;
|
||||||
|
final updatedCommunities =
|
||||||
|
List<CommunityModel>.from(state.communityList);
|
||||||
|
|
||||||
|
final index = updatedCommunities
|
||||||
|
.indexWhere((community) => community.uuid == updatedCommunity.uuid);
|
||||||
|
|
||||||
|
if (index != -1) {
|
||||||
|
updatedCommunities[index] = updatedCommunity;
|
||||||
|
emit(state.copyWith(communitiesList: updatedCommunities));
|
||||||
|
} else {
|
||||||
|
emit(SpaceTreeErrorState('Community not found in the list.'));
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
emit(SpaceTreeErrorState('Error updating community: $e'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_fetchSpaces(InitialEvent event, Emitter<SpaceTreeState> emit) async {
|
_fetchSpaces(InitialEvent event, Emitter<SpaceTreeState> emit) async {
|
||||||
emit(SpaceTreeLoadingState());
|
emit(SpaceTreeLoadingState());
|
||||||
try {
|
try {
|
||||||
List<CommunityModel> communities = await CommunitySpaceManagementApi().fetchCommunities();
|
final projectUuid = await ProjectManager.getProjectUUID() ?? '';
|
||||||
|
|
||||||
|
List<CommunityModel> communities =
|
||||||
|
await CommunitySpaceManagementApi().fetchCommunities(projectUuid);
|
||||||
|
|
||||||
List<CommunityModel> updatedCommunities = await Future.wait(
|
List<CommunityModel> updatedCommunities = await Future.wait(
|
||||||
communities.map((community) async {
|
communities.map((community) async {
|
||||||
List<SpaceModel> spaces =
|
List<SpaceModel> spaces = await CommunitySpaceManagementApi()
|
||||||
await CommunitySpaceManagementApi().getSpaceHierarchy(community.uuid);
|
.getSpaceHierarchy(community.uuid, projectUuid);
|
||||||
|
|
||||||
return CommunityModel(
|
return CommunityModel(
|
||||||
uuid: community.uuid,
|
uuid: community.uuid,
|
||||||
@ -41,15 +71,27 @@ class SpaceTreeBloc extends Bloc<SpaceTreeEvent, SpaceTreeState> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
communitiesList: updatedCommunities, expandedCommunity: [], expandedSpaces: []));
|
communitiesList: updatedCommunities,
|
||||||
|
expandedCommunity: [],
|
||||||
|
expandedSpaces: []));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(SpaceTreeErrorState('Error loading communities and spaces: $e'));
|
emit(SpaceTreeErrorState('Error loading communities and spaces: $e'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_onCommunityExpanded(OnCommunityExpanded event, Emitter<SpaceTreeState> emit) async {
|
void _onCommunityAdded(
|
||||||
|
OnCommunityAdded event, Emitter<SpaceTreeState> emit) async {
|
||||||
|
final updatedCommunities = List<CommunityModel>.from(state.communityList);
|
||||||
|
updatedCommunities.add(event.newCommunity);
|
||||||
|
|
||||||
|
emit(state.copyWith(communitiesList: updatedCommunities));
|
||||||
|
}
|
||||||
|
|
||||||
|
_onCommunityExpanded(
|
||||||
|
OnCommunityExpanded event, Emitter<SpaceTreeState> emit) async {
|
||||||
try {
|
try {
|
||||||
List<String> updatedExpandedCommunityList = List.from(state.expandedCommunities);
|
List<String> updatedExpandedCommunityList =
|
||||||
|
List.from(state.expandedCommunities);
|
||||||
|
|
||||||
if (updatedExpandedCommunityList.contains(event.communityId)) {
|
if (updatedExpandedCommunityList.contains(event.communityId)) {
|
||||||
updatedExpandedCommunityList.remove(event.communityId);
|
updatedExpandedCommunityList.remove(event.communityId);
|
||||||
@ -81,13 +123,19 @@ class SpaceTreeBloc extends Bloc<SpaceTreeEvent, SpaceTreeState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_onCommunitySelected(OnCommunitySelected event, Emitter<SpaceTreeState> emit) async {
|
_onCommunitySelected(
|
||||||
|
OnCommunitySelected event, Emitter<SpaceTreeState> emit) async {
|
||||||
try {
|
try {
|
||||||
List<String> updatedSelectedCommunities =
|
List<String> updatedSelectedCommunities =
|
||||||
List.from(state.selectedCommunities.toSet().toList());
|
List.from(state.selectedCommunities.toSet().toList());
|
||||||
List<String> updatedSelectedSpaces = List.from(state.selectedSpaces.toSet().toList());
|
List<String> updatedSelectedSpaces =
|
||||||
List<String> updatedSoldChecks = List.from(state.soldCheck.toSet().toList());
|
List.from(state.selectedSpaces.toSet().toList());
|
||||||
Map<String, List<String>> communityAndSpaces = Map.from(state.selectedCommunityAndSpaces);
|
List<String> updatedSoldChecks =
|
||||||
|
List.from(state.soldCheck.toSet().toList());
|
||||||
|
Map<String, List<String>> communityAndSpaces =
|
||||||
|
Map.from(state.selectedCommunityAndSpaces);
|
||||||
|
List<String> selectedSpacesInCommunity =
|
||||||
|
communityAndSpaces[event.communityId] ?? [];
|
||||||
|
|
||||||
List<String> childrenIds = _getAllChildIds(event.children);
|
List<String> childrenIds = _getAllChildIds(event.children);
|
||||||
|
|
||||||
@ -95,14 +143,16 @@ class SpaceTreeBloc extends Bloc<SpaceTreeEvent, SpaceTreeState> {
|
|||||||
// Select the community and all its children
|
// Select the community and all its children
|
||||||
updatedSelectedCommunities.add(event.communityId);
|
updatedSelectedCommunities.add(event.communityId);
|
||||||
updatedSelectedSpaces.addAll(childrenIds);
|
updatedSelectedSpaces.addAll(childrenIds);
|
||||||
|
selectedSpacesInCommunity.addAll(childrenIds);
|
||||||
} else {
|
} else {
|
||||||
// Unselect the community and all its children
|
// Unselect the community and all its children
|
||||||
updatedSelectedCommunities.remove(event.communityId);
|
updatedSelectedCommunities.remove(event.communityId);
|
||||||
updatedSelectedSpaces.removeWhere(childrenIds.contains);
|
updatedSelectedSpaces.removeWhere(childrenIds.contains);
|
||||||
updatedSoldChecks.removeWhere(childrenIds.contains);
|
updatedSoldChecks.removeWhere(childrenIds.contains);
|
||||||
|
selectedSpacesInCommunity.removeWhere(childrenIds.contains);
|
||||||
}
|
}
|
||||||
|
|
||||||
communityAndSpaces[event.communityId] = updatedSelectedSpaces;
|
communityAndSpaces[event.communityId] = selectedSpacesInCommunity;
|
||||||
|
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
selectedCommunities: updatedSelectedCommunities,
|
selectedCommunities: updatedSelectedCommunities,
|
||||||
@ -118,9 +168,15 @@ class SpaceTreeBloc extends Bloc<SpaceTreeEvent, SpaceTreeState> {
|
|||||||
try {
|
try {
|
||||||
List<String> updatedSelectedCommunities =
|
List<String> updatedSelectedCommunities =
|
||||||
List.from(state.selectedCommunities.toSet().toList());
|
List.from(state.selectedCommunities.toSet().toList());
|
||||||
List<String> updatedSelectedSpaces = List.from(state.selectedSpaces.toSet().toList());
|
List<String> updatedSelectedSpaces =
|
||||||
List<String> updatedSoldChecks = List.from(state.soldCheck.toSet().toList());
|
List.from(state.selectedSpaces.toSet().toList());
|
||||||
Map<String, List<String>> communityAndSpaces = Map.from(state.selectedCommunityAndSpaces);
|
List<String> updatedSoldChecks =
|
||||||
|
List.from(state.soldCheck.toSet().toList());
|
||||||
|
Map<String, List<String>> communityAndSpaces =
|
||||||
|
Map.from(state.selectedCommunityAndSpaces);
|
||||||
|
|
||||||
|
List<String> selectedSpacesInCommunity =
|
||||||
|
communityAndSpaces[event.communityModel.uuid] ?? [];
|
||||||
|
|
||||||
List<String> childrenIds = _getAllChildIds(event.children);
|
List<String> childrenIds = _getAllChildIds(event.children);
|
||||||
bool isChildSelected = false;
|
bool isChildSelected = false;
|
||||||
@ -135,14 +191,19 @@ class SpaceTreeBloc extends Bloc<SpaceTreeEvent, SpaceTreeState> {
|
|||||||
!updatedSoldChecks.contains(event.spaceId)) {
|
!updatedSoldChecks.contains(event.spaceId)) {
|
||||||
// First click: Select the space and all its children
|
// First click: Select the space and all its children
|
||||||
updatedSelectedSpaces.add(event.spaceId);
|
updatedSelectedSpaces.add(event.spaceId);
|
||||||
updatedSelectedCommunities.add(event.communityId);
|
updatedSelectedCommunities.add(event.communityModel.uuid);
|
||||||
|
selectedSpacesInCommunity.add(event.spaceId);
|
||||||
|
|
||||||
if (childrenIds.isNotEmpty) {
|
if (childrenIds.isNotEmpty) {
|
||||||
updatedSelectedSpaces.addAll(childrenIds);
|
updatedSelectedSpaces.addAll(childrenIds);
|
||||||
|
selectedSpacesInCommunity.addAll(childrenIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> spaces = _getThePathToChild(event.communityId, event.spaceId);
|
List<String> spaces =
|
||||||
|
_getThePathToChild(event.communityModel.uuid, event.spaceId);
|
||||||
for (String space in spaces) {
|
for (String space in spaces) {
|
||||||
if (!updatedSelectedSpaces.contains(space) && !updatedSoldChecks.contains(space)) {
|
if (!updatedSelectedSpaces.contains(space) &&
|
||||||
|
!updatedSoldChecks.contains(space)) {
|
||||||
updatedSoldChecks.add(space);
|
updatedSoldChecks.add(space);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -150,31 +211,48 @@ class SpaceTreeBloc extends Bloc<SpaceTreeEvent, SpaceTreeState> {
|
|||||||
childrenIds.isNotEmpty &&
|
childrenIds.isNotEmpty &&
|
||||||
isChildSelected) {
|
isChildSelected) {
|
||||||
// Second click: Unselect space but keep children
|
// Second click: Unselect space but keep children
|
||||||
|
selectedSpacesInCommunity.remove(event.spaceId);
|
||||||
updatedSelectedSpaces.remove(event.spaceId);
|
updatedSelectedSpaces.remove(event.spaceId);
|
||||||
updatedSoldChecks.add(event.spaceId);
|
updatedSoldChecks.add(event.spaceId);
|
||||||
} else {
|
} else {
|
||||||
// Third click: Unselect space and all its children
|
// Third click: Unselect space and all its children
|
||||||
|
selectedSpacesInCommunity.remove(event.spaceId);
|
||||||
updatedSelectedSpaces.remove(event.spaceId);
|
updatedSelectedSpaces.remove(event.spaceId);
|
||||||
if (childrenIds.isNotEmpty) {
|
if (childrenIds.isNotEmpty) {
|
||||||
updatedSelectedSpaces.removeWhere(childrenIds.contains);
|
updatedSelectedSpaces.removeWhere(childrenIds.contains);
|
||||||
updatedSoldChecks.removeWhere(childrenIds.contains);
|
updatedSoldChecks.removeWhere(childrenIds.contains);
|
||||||
|
selectedSpacesInCommunity.removeWhere(childrenIds.contains);
|
||||||
}
|
}
|
||||||
updatedSoldChecks.remove(event.spaceId);
|
updatedSoldChecks.remove(event.spaceId);
|
||||||
|
|
||||||
List<String> parents = _getThePathToChild(event.communityId, event.spaceId);
|
List<String> parents =
|
||||||
if (!_parentSelected(parents, updatedSelectedSpaces)) {
|
_getThePathToChild(event.communityModel.uuid, event.spaceId)
|
||||||
|
.toSet()
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
if (updatedSelectedSpaces.isEmpty) {
|
||||||
updatedSoldChecks.removeWhere(parents.contains);
|
updatedSoldChecks.removeWhere(parents.contains);
|
||||||
}
|
updatedSelectedCommunities.remove(event.communityModel.uuid);
|
||||||
if (!_anySpacesSelectedInCommunity(
|
} else {
|
||||||
event.communityId, updatedSelectedSpaces, updatedSoldChecks)) {
|
// Check if any parent has selected children
|
||||||
updatedSelectedCommunities.remove(event.communityId);
|
for (String space in parents) {
|
||||||
|
if (!_noChildrenSelected(
|
||||||
|
event.communityModel, space, updatedSelectedSpaces, parents)) {
|
||||||
|
updatedSoldChecks.remove(space);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_anySpacesSelectedInCommunity(
|
||||||
|
event.communityModel, updatedSelectedSpaces, updatedSoldChecks)) {
|
||||||
|
updatedSelectedCommunities.remove(event.communityModel.uuid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
communityAndSpaces[event.communityId] = updatedSelectedSpaces;
|
communityAndSpaces[event.communityModel.uuid] = selectedSpacesInCommunity;
|
||||||
|
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
selectedCommunities: updatedSelectedCommunities,
|
selectedCommunities: updatedSelectedCommunities.toSet().toList(),
|
||||||
selectedSpaces: updatedSelectedSpaces,
|
selectedSpaces: updatedSelectedSpaces,
|
||||||
soldCheck: updatedSoldChecks,
|
soldCheck: updatedSoldChecks,
|
||||||
selectedCommunityAndSpaces: communityAndSpaces));
|
selectedCommunityAndSpaces: communityAndSpaces));
|
||||||
@ -184,12 +262,24 @@ class SpaceTreeBloc extends Bloc<SpaceTreeEvent, SpaceTreeState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_parentSelected(List<String> parents, List<String> selectedSpaces) {
|
_noChildrenSelected(CommunityModel community, String spaceId,
|
||||||
for (String space in parents) {
|
List<String> selectedSpaces, List<String> parents) {
|
||||||
if (selectedSpaces.contains(space)) {
|
if (selectedSpaces.contains(spaceId)) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<SpaceModel> children = _getAllChildSpaces(community.spaces);
|
||||||
|
for (var child in children) {
|
||||||
|
if (spaceId == child.uuid) {
|
||||||
|
List<String> ids = _getAllChildIds(child.children);
|
||||||
|
for (var id in ids) {
|
||||||
|
if (selectedSpaces.contains(id)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,16 +290,55 @@ class SpaceTreeBloc extends Bloc<SpaceTreeEvent, SpaceTreeState> {
|
|||||||
|
|
||||||
// Filter communities and expand only those that match the query
|
// Filter communities and expand only those that match the query
|
||||||
filteredCommunity = communities.where((community) {
|
filteredCommunity = communities.where((community) {
|
||||||
final containsQueryInCommunity =
|
final containsQueryInCommunity = community.name
|
||||||
community.name.toLowerCase().contains(event.searchQuery.toLowerCase());
|
.toLowerCase()
|
||||||
final containsQueryInSpaces =
|
.contains(event.searchQuery.toLowerCase());
|
||||||
community.spaces.any((space) => _containsQuery(space, event.searchQuery.toLowerCase()));
|
final containsQueryInSpaces = community.spaces.any(
|
||||||
|
(space) => _containsQuery(space, event.searchQuery.toLowerCase()));
|
||||||
|
|
||||||
return containsQueryInCommunity || containsQueryInSpaces;
|
return containsQueryInCommunity || containsQueryInSpaces;
|
||||||
}).toList();
|
}).toList();
|
||||||
|
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
filteredCommunity: filteredCommunity, isSearching: event.searchQuery.isNotEmpty));
|
filteredCommunity: filteredCommunity,
|
||||||
|
isSearching: event.searchQuery.isNotEmpty,
|
||||||
|
searchQuery: event.searchQuery));
|
||||||
|
} catch (e) {
|
||||||
|
emit(const SpaceTreeErrorState('Something went wrong'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_clearAllData(ClearAllData event, Emitter<SpaceTreeState> emit) async {
|
||||||
|
try {
|
||||||
|
emit(state.copyWith(
|
||||||
|
communitiesList: [],
|
||||||
|
filteredCommunity: [],
|
||||||
|
isSearching: false,
|
||||||
|
soldCheck: [],
|
||||||
|
selectedSpaces: [],
|
||||||
|
selectedCommunities: [],
|
||||||
|
selectedCommunityAndSpaces: {},
|
||||||
|
searchQuery: '',
|
||||||
|
expandedSpaces: [],
|
||||||
|
expandedCommunity: []));
|
||||||
|
} catch (e) {
|
||||||
|
emit(const SpaceTreeErrorState('Something went wrong'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_clearCachedData(ClearCachedData event, Emitter<SpaceTreeState> emit) async {
|
||||||
|
try {
|
||||||
|
emit(state.copyWith(
|
||||||
|
communitiesList: state.communityList,
|
||||||
|
filteredCommunity: [],
|
||||||
|
isSearching: false,
|
||||||
|
soldCheck: [],
|
||||||
|
selectedSpaces: [],
|
||||||
|
selectedCommunities: [],
|
||||||
|
selectedCommunityAndSpaces: {},
|
||||||
|
searchQuery: '',
|
||||||
|
expandedSpaces: [],
|
||||||
|
expandedCommunity: []));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(const SpaceTreeErrorState('Something went wrong'));
|
emit(const SpaceTreeErrorState('Something went wrong'));
|
||||||
}
|
}
|
||||||
@ -218,8 +347,8 @@ class SpaceTreeBloc extends Bloc<SpaceTreeEvent, SpaceTreeState> {
|
|||||||
// Helper function to determine if any space or its children match the search query
|
// Helper function to determine if any space or its children match the search query
|
||||||
bool _containsQuery(SpaceModel space, String query) {
|
bool _containsQuery(SpaceModel space, String query) {
|
||||||
final matchesSpace = space.name.toLowerCase().contains(query);
|
final matchesSpace = space.name.toLowerCase().contains(query);
|
||||||
final matchesChildren =
|
final matchesChildren = space.children.any((child) =>
|
||||||
space.children.any((child) => _containsQuery(child, query)); // Recursive check for children
|
_containsQuery(child, query)); // Recursive check for children
|
||||||
|
|
||||||
return matchesSpace || matchesChildren;
|
return matchesSpace || matchesChildren;
|
||||||
}
|
}
|
||||||
@ -230,21 +359,26 @@ class SpaceTreeBloc extends Bloc<SpaceTreeEvent, SpaceTreeState> {
|
|||||||
ids.add(child.uuid!);
|
ids.add(child.uuid!);
|
||||||
ids.addAll(_getAllChildIds(child.children));
|
ids.addAll(_getAllChildIds(child.children));
|
||||||
}
|
}
|
||||||
return ids;
|
return ids.toSet().toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _anySpacesSelectedInCommunity(
|
List<SpaceModel> _getAllChildSpaces(List<SpaceModel> spaces) {
|
||||||
String communityId, List<String> selectedSpaces, List<String> partialCheckedList) {
|
List<SpaceModel> children = [];
|
||||||
|
for (var child in spaces) {
|
||||||
|
children.add(child);
|
||||||
|
children.addAll(_getAllChildSpaces(child.children));
|
||||||
|
}
|
||||||
|
return children;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _anySpacesSelectedInCommunity(CommunityModel community,
|
||||||
|
List<String> selectedSpaces, List<String> partialCheckedList) {
|
||||||
bool result = false;
|
bool result = false;
|
||||||
for (var community in state.communityList) {
|
List<String> ids = _getAllChildIds(community.spaces);
|
||||||
if (community.uuid == communityId) {
|
for (var id in ids) {
|
||||||
List<String> ids = _getAllChildIds(community.spaces);
|
result = selectedSpaces.contains(id) || partialCheckedList.contains(id);
|
||||||
for (var id in ids) {
|
if (result) {
|
||||||
result = selectedSpaces.contains(id) || partialCheckedList.contains(id);
|
return result;
|
||||||
if (result) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@ -267,7 +401,8 @@ class SpaceTreeBloc extends Bloc<SpaceTreeEvent, SpaceTreeState> {
|
|||||||
return ids;
|
return ids;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> _getAllParentsIds(SpaceModel child, String spaceId, List<String> listIds) {
|
List<String> _getAllParentsIds(
|
||||||
|
SpaceModel child, String spaceId, List<String> listIds) {
|
||||||
List<String> ids = listIds;
|
List<String> ids = listIds;
|
||||||
|
|
||||||
ids.add(child.uuid ?? '');
|
ids.add(child.uuid ?? '');
|
||||||
@ -288,4 +423,9 @@ class SpaceTreeBloc extends Bloc<SpaceTreeEvent, SpaceTreeState> {
|
|||||||
ids.removeLast();
|
ids.removeLast();
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> close() async {
|
||||||
|
super.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart';
|
||||||
|
|
||||||
class SpaceTreeEvent extends Equatable {
|
class SpaceTreeEvent extends Equatable {
|
||||||
@ -49,14 +50,14 @@ class OnSpaceExpanded extends SpaceTreeEvent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class OnSpaceSelected extends SpaceTreeEvent {
|
class OnSpaceSelected extends SpaceTreeEvent {
|
||||||
final String communityId;
|
|
||||||
final String spaceId;
|
final String spaceId;
|
||||||
final List<SpaceModel> children;
|
final List<SpaceModel> children;
|
||||||
|
final CommunityModel communityModel;
|
||||||
|
|
||||||
const OnSpaceSelected(this.communityId, this.spaceId, this.children);
|
const OnSpaceSelected(this.communityModel, this.spaceId, this.children);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [communityId, spaceId, children];
|
List<Object> get props => [communityModel, spaceId, children];
|
||||||
}
|
}
|
||||||
|
|
||||||
class SearchQueryEvent extends SpaceTreeEvent {
|
class SearchQueryEvent extends SpaceTreeEvent {
|
||||||
@ -67,3 +68,24 @@ class SearchQueryEvent extends SpaceTreeEvent {
|
|||||||
@override
|
@override
|
||||||
List<Object> get props => [searchQuery];
|
List<Object> get props => [searchQuery];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class OnCommunityAdded extends SpaceTreeEvent {
|
||||||
|
final CommunityModel newCommunity;
|
||||||
|
const OnCommunityAdded(this.newCommunity);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [newCommunity];
|
||||||
|
}
|
||||||
|
|
||||||
|
class OnCommunityUpdated extends SpaceTreeEvent {
|
||||||
|
final CommunityModel updatedCommunity;
|
||||||
|
const OnCommunityUpdated(this.updatedCommunity);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [updatedCommunity];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class ClearAllData extends SpaceTreeEvent {}
|
||||||
|
|
||||||
|
class ClearCachedData extends SpaceTreeEvent {}
|
||||||
|
@ -11,6 +11,7 @@ class SpaceTreeState extends Equatable {
|
|||||||
final List<String> selectedSpaces;
|
final List<String> selectedSpaces;
|
||||||
final List<String> soldCheck;
|
final List<String> soldCheck;
|
||||||
final bool isSearching;
|
final bool isSearching;
|
||||||
|
final String searchQuery;
|
||||||
|
|
||||||
const SpaceTreeState(
|
const SpaceTreeState(
|
||||||
{this.communityList = const [],
|
{this.communityList = const [],
|
||||||
@ -21,7 +22,8 @@ class SpaceTreeState extends Equatable {
|
|||||||
this.selectedSpaces = const [],
|
this.selectedSpaces = const [],
|
||||||
this.soldCheck = const [],
|
this.soldCheck = const [],
|
||||||
this.isSearching = false,
|
this.isSearching = false,
|
||||||
this.selectedCommunityAndSpaces = const {}});
|
this.selectedCommunityAndSpaces = const {},
|
||||||
|
this.searchQuery = ''});
|
||||||
|
|
||||||
SpaceTreeState copyWith(
|
SpaceTreeState copyWith(
|
||||||
{List<CommunityModel>? communitiesList,
|
{List<CommunityModel>? communitiesList,
|
||||||
@ -32,7 +34,8 @@ class SpaceTreeState extends Equatable {
|
|||||||
List<String>? selectedSpaces,
|
List<String>? selectedSpaces,
|
||||||
List<String>? soldCheck,
|
List<String>? soldCheck,
|
||||||
bool? isSearching,
|
bool? isSearching,
|
||||||
Map<String, List<String>>? selectedCommunityAndSpaces}) {
|
Map<String, List<String>>? selectedCommunityAndSpaces,
|
||||||
|
String? searchQuery}) {
|
||||||
return SpaceTreeState(
|
return SpaceTreeState(
|
||||||
communityList: communitiesList ?? this.communityList,
|
communityList: communitiesList ?? this.communityList,
|
||||||
filteredCommunity: filteredCommunity ?? this.filteredCommunity,
|
filteredCommunity: filteredCommunity ?? this.filteredCommunity,
|
||||||
@ -42,7 +45,8 @@ class SpaceTreeState extends Equatable {
|
|||||||
selectedSpaces: selectedSpaces ?? this.selectedSpaces,
|
selectedSpaces: selectedSpaces ?? this.selectedSpaces,
|
||||||
soldCheck: soldCheck ?? this.soldCheck,
|
soldCheck: soldCheck ?? this.soldCheck,
|
||||||
isSearching: isSearching ?? this.isSearching,
|
isSearching: isSearching ?? this.isSearching,
|
||||||
selectedCommunityAndSpaces: selectedCommunityAndSpaces ?? this.selectedCommunityAndSpaces);
|
selectedCommunityAndSpaces: selectedCommunityAndSpaces ?? this.selectedCommunityAndSpaces,
|
||||||
|
searchQuery: searchQuery ?? this.searchQuery);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -55,7 +59,8 @@ class SpaceTreeState extends Equatable {
|
|||||||
selectedSpaces,
|
selectedSpaces,
|
||||||
soldCheck,
|
soldCheck,
|
||||||
isSearching,
|
isSearching,
|
||||||
selectedCommunityAndSpaces
|
selectedCommunityAndSpaces,
|
||||||
|
searchQuery
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,6 +39,7 @@ class _SpaceTreeViewState extends State<SpaceTreeView> {
|
|||||||
: Column(
|
: Column(
|
||||||
children: [
|
children: [
|
||||||
CustomSearchBar(
|
CustomSearchBar(
|
||||||
|
searchQuery: state.searchQuery,
|
||||||
onSearchChanged: (query) {
|
onSearchChanged: (query) {
|
||||||
context.read<SpaceTreeBloc>().add(SearchQueryEvent(query));
|
context.read<SpaceTreeBloc>().add(SearchQueryEvent(query));
|
||||||
},
|
},
|
||||||
@ -99,8 +100,8 @@ class _SpaceTreeViewState extends State<SpaceTreeView> {
|
|||||||
state.expandedSpaces.contains(space.uuid),
|
state.expandedSpaces.contains(space.uuid),
|
||||||
onItemSelected: () {
|
onItemSelected: () {
|
||||||
context.read<SpaceTreeBloc>().add(
|
context.read<SpaceTreeBloc>().add(
|
||||||
OnSpaceSelected(community.uuid,
|
OnSpaceSelected(community, space.uuid ?? '',
|
||||||
space.uuid ?? '', space.children));
|
space.children));
|
||||||
widget.onSelect();
|
widget.onSelect();
|
||||||
},
|
},
|
||||||
onExpansionChanged: () {
|
onExpansionChanged: () {
|
||||||
@ -113,7 +114,7 @@ class _SpaceTreeViewState extends State<SpaceTreeView> {
|
|||||||
state.soldCheck.contains(space.uuid),
|
state.soldCheck.contains(space.uuid),
|
||||||
isSoldCheck: state.soldCheck.contains(space.uuid),
|
isSoldCheck: state.soldCheck.contains(space.uuid),
|
||||||
children: _buildNestedSpaces(
|
children: _buildNestedSpaces(
|
||||||
context, state, space, community.uuid),
|
context, state, space, community),
|
||||||
);
|
);
|
||||||
}).toList(),
|
}).toList(),
|
||||||
),
|
),
|
||||||
@ -196,7 +197,7 @@ class _SpaceTreeViewState extends State<SpaceTreeView> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> _buildNestedSpaces(
|
List<Widget> _buildNestedSpaces(
|
||||||
BuildContext context, SpaceTreeState state, SpaceModel space, String communityId) {
|
BuildContext context, SpaceTreeState state, SpaceModel space, CommunityModel community) {
|
||||||
return space.children.map((child) {
|
return space.children.map((child) {
|
||||||
return CustomExpansionTileSpaceTree(
|
return CustomExpansionTileSpaceTree(
|
||||||
isSelected:
|
isSelected:
|
||||||
@ -207,13 +208,13 @@ class _SpaceTreeViewState extends State<SpaceTreeView> {
|
|||||||
onItemSelected: () {
|
onItemSelected: () {
|
||||||
context
|
context
|
||||||
.read<SpaceTreeBloc>()
|
.read<SpaceTreeBloc>()
|
||||||
.add(OnSpaceSelected(communityId, child.uuid ?? '', child.children));
|
.add(OnSpaceSelected(community, child.uuid ?? '', child.children));
|
||||||
widget.onSelect();
|
widget.onSelect();
|
||||||
},
|
},
|
||||||
onExpansionChanged: () {
|
onExpansionChanged: () {
|
||||||
context.read<SpaceTreeBloc>().add(OnSpaceExpanded(communityId, child.uuid ?? ''));
|
context.read<SpaceTreeBloc>().add(OnSpaceExpanded(community.uuid, child.uuid ?? ''));
|
||||||
},
|
},
|
||||||
children: _buildNestedSpaces(context, state, child, communityId),
|
children: _buildNestedSpaces(context, state, child, community),
|
||||||
);
|
);
|
||||||
}).toList();
|
}).toList();
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
|
import 'dart:async';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/common/bloc/project_manager.dart';
|
||||||
|
import 'package:syncrow_web/pages/space_tree/bloc/space_tree_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/space_tree/bloc/space_tree_event.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/create_subspace_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/create_subspace_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/product_model.dart';
|
||||||
@ -13,7 +17,7 @@ import 'package:syncrow_web/pages/spaces_management/space_model/models/tag_updat
|
|||||||
import 'package:syncrow_web/services/product_api.dart';
|
import 'package:syncrow_web/services/product_api.dart';
|
||||||
import 'package:syncrow_web/services/space_mana_api.dart';
|
import 'package:syncrow_web/services/space_mana_api.dart';
|
||||||
import 'package:syncrow_web/services/space_model_mang_api.dart';
|
import 'package:syncrow_web/services/space_model_mang_api.dart';
|
||||||
import 'package:syncrow_web/utils/constants/action_enum.dart';
|
import 'package:syncrow_web/utils/constants/action_enum.dart' as custom_action;
|
||||||
|
|
||||||
class SpaceManagementBloc
|
class SpaceManagementBloc
|
||||||
extends Bloc<SpaceManagementEvent, SpaceManagementState> {
|
extends Bloc<SpaceManagementEvent, SpaceManagementState> {
|
||||||
@ -22,11 +26,16 @@ class SpaceManagementBloc
|
|||||||
final SpaceModelManagementApi _spaceModelApi;
|
final SpaceModelManagementApi _spaceModelApi;
|
||||||
|
|
||||||
List<ProductModel>? _cachedProducts;
|
List<ProductModel>? _cachedProducts;
|
||||||
|
List<SpaceTemplateModel>? _cachedSpaceModels;
|
||||||
|
final SpaceTreeBloc _spaceTreeBloc;
|
||||||
|
|
||||||
SpaceManagementBloc(this._api, this._productApi, this._spaceModelApi)
|
SpaceManagementBloc(
|
||||||
: super(SpaceManagementInitial()) {
|
this._api,
|
||||||
|
this._productApi,
|
||||||
|
this._spaceModelApi,
|
||||||
|
this._spaceTreeBloc,
|
||||||
|
) : super(SpaceManagementInitial()) {
|
||||||
on<LoadCommunityAndSpacesEvent>(_onLoadCommunityAndSpaces);
|
on<LoadCommunityAndSpacesEvent>(_onLoadCommunityAndSpaces);
|
||||||
on<UpdateSpacePositionEvent>(_onUpdateSpacePosition);
|
|
||||||
on<CreateCommunityEvent>(_onCreateCommunity);
|
on<CreateCommunityEvent>(_onCreateCommunity);
|
||||||
on<SelectCommunityEvent>(_onSelectCommunity);
|
on<SelectCommunityEvent>(_onSelectCommunity);
|
||||||
on<DeleteCommunityEvent>(_onCommunityDelete);
|
on<DeleteCommunityEvent>(_onCommunityDelete);
|
||||||
@ -37,6 +46,88 @@ class SpaceManagementBloc
|
|||||||
on<NewCommunityEvent>(_onNewCommunity);
|
on<NewCommunityEvent>(_onNewCommunity);
|
||||||
on<BlankStateEvent>(_onBlankState);
|
on<BlankStateEvent>(_onBlankState);
|
||||||
on<SpaceModelLoadEvent>(_onLoadSpaceModel);
|
on<SpaceModelLoadEvent>(_onLoadSpaceModel);
|
||||||
|
on<UpdateSpaceModelCache>(_updateSpaceModelCache);
|
||||||
|
on<DeleteSpaceModelFromCache>(_deleteSpaceModelFromCache);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _updateSpaceModelCache(
|
||||||
|
UpdateSpaceModelCache event, Emitter<SpaceManagementState> emit) async {
|
||||||
|
if (_cachedSpaceModels != null) {
|
||||||
|
_cachedSpaceModels = _cachedSpaceModels!.map((model) {
|
||||||
|
return model.uuid == event.updatedModel.uuid
|
||||||
|
? event.updatedModel
|
||||||
|
: model;
|
||||||
|
}).toList();
|
||||||
|
} else {
|
||||||
|
_cachedSpaceModels = await fetchSpaceModels();
|
||||||
|
}
|
||||||
|
|
||||||
|
emit(SpaceModelLoaded(
|
||||||
|
communities: state is SpaceManagementLoaded
|
||||||
|
? (state as SpaceManagementLoaded).communities
|
||||||
|
: [],
|
||||||
|
products: _cachedProducts ?? [],
|
||||||
|
spaceModels: List.from(_cachedSpaceModels ?? []),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
void _deleteSpaceModelFromCache(DeleteSpaceModelFromCache event,
|
||||||
|
Emitter<SpaceManagementState> emit) async {
|
||||||
|
if (_cachedSpaceModels != null) {
|
||||||
|
_cachedSpaceModels = _cachedSpaceModels!
|
||||||
|
.where((model) => model.uuid != event.deletedUuid)
|
||||||
|
.toList();
|
||||||
|
} else {
|
||||||
|
_cachedSpaceModels = await fetchSpaceModels();
|
||||||
|
}
|
||||||
|
|
||||||
|
emit(SpaceModelLoaded(
|
||||||
|
communities: state is SpaceManagementLoaded
|
||||||
|
? (state as SpaceManagementLoaded).communities
|
||||||
|
: [],
|
||||||
|
products: _cachedProducts ?? [],
|
||||||
|
spaceModels: List.from(_cachedSpaceModels ?? []),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateCachedSpaceModels(List<SpaceTemplateModel> updatedModels) {
|
||||||
|
_cachedSpaceModels = List.from(updatedModels);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addToCachedSpaceModels(SpaceTemplateModel newModel) {
|
||||||
|
_cachedSpaceModels?.add(newModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<SpaceTemplateModel>> fetchSpaceModels() async {
|
||||||
|
try {
|
||||||
|
if (_cachedSpaceModels != null) {
|
||||||
|
return _cachedSpaceModels!;
|
||||||
|
}
|
||||||
|
|
||||||
|
final projectUuid = await ProjectManager.getProjectUUID() ?? '';
|
||||||
|
|
||||||
|
List<SpaceTemplateModel> allSpaceModels = [];
|
||||||
|
|
||||||
|
bool hasNext = true;
|
||||||
|
int page = 1;
|
||||||
|
|
||||||
|
while (hasNext) {
|
||||||
|
final spaceModels = await _spaceModelApi.listSpaceModels(
|
||||||
|
page: page, projectId: projectUuid);
|
||||||
|
if (spaceModels.isNotEmpty) {
|
||||||
|
allSpaceModels.addAll(spaceModels);
|
||||||
|
page++;
|
||||||
|
} else {
|
||||||
|
hasNext = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_cachedSpaceModels = allSpaceModels;
|
||||||
|
|
||||||
|
return allSpaceModels;
|
||||||
|
} catch (e) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onUpdateCommunity(
|
void _onUpdateCommunity(
|
||||||
@ -45,9 +136,11 @@ class SpaceManagementBloc
|
|||||||
) async {
|
) async {
|
||||||
final previousState = state;
|
final previousState = state;
|
||||||
try {
|
try {
|
||||||
|
final projectUuid = await ProjectManager.getProjectUUID() ?? '';
|
||||||
|
|
||||||
emit(SpaceManagementLoading());
|
emit(SpaceManagementLoading());
|
||||||
final success =
|
final success = await _api.updateCommunity(
|
||||||
await _api.updateCommunity(event.communityUuid, event.name);
|
event.communityUuid, event.name, projectUuid);
|
||||||
if (success) {
|
if (success) {
|
||||||
if (previousState is SpaceManagementLoaded) {
|
if (previousState is SpaceManagementLoaded) {
|
||||||
final updatedCommunities =
|
final updatedCommunities =
|
||||||
@ -55,11 +148,13 @@ class SpaceManagementBloc
|
|||||||
for (var community in updatedCommunities) {
|
for (var community in updatedCommunities) {
|
||||||
if (community.uuid == event.communityUuid) {
|
if (community.uuid == event.communityUuid) {
|
||||||
community.name = event.name;
|
community.name = event.name;
|
||||||
|
_spaceTreeBloc.add(OnCommunityAdded(community));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var prevSpaceModels = await fetchSpaceModels(previousState);
|
var prevSpaceModels = await fetchSpaceModels();
|
||||||
|
|
||||||
emit(SpaceManagementLoaded(
|
emit(SpaceManagementLoaded(
|
||||||
communities: updatedCommunities,
|
communities: updatedCommunities,
|
||||||
@ -76,42 +171,6 @@ class SpaceManagementBloc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<SpaceTemplateModel>> fetchSpaceModels(
|
|
||||||
SpaceManagementState previousState) async {
|
|
||||||
try {
|
|
||||||
List<SpaceTemplateModel> allSpaces = [];
|
|
||||||
List<SpaceTemplateModel> prevSpaceModels = [];
|
|
||||||
|
|
||||||
if (previousState is SpaceManagementLoaded ||
|
|
||||||
previousState is BlankState) {
|
|
||||||
prevSpaceModels = List<SpaceTemplateModel>.from(
|
|
||||||
(previousState as dynamic).spaceModels ?? [],
|
|
||||||
);
|
|
||||||
allSpaces.addAll(prevSpaceModels);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prevSpaceModels.isEmpty) {
|
|
||||||
bool hasNext = true;
|
|
||||||
int page = 1;
|
|
||||||
|
|
||||||
while (hasNext) {
|
|
||||||
final spaces = await _spaceModelApi.listSpaceModels(page: page);
|
|
||||||
if (spaces.isNotEmpty) {
|
|
||||||
allSpaces.addAll(spaces);
|
|
||||||
page++;
|
|
||||||
} else {
|
|
||||||
hasNext = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
prevSpaceModels = await _spaceModelApi.listSpaceModels(page: 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return allSpaces;
|
|
||||||
} catch (e) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void _onloadProducts() async {
|
void _onloadProducts() async {
|
||||||
if (_cachedProducts == null) {
|
if (_cachedProducts == null) {
|
||||||
final products = await _productApi.fetchProducts();
|
final products = await _productApi.fetchProducts();
|
||||||
@ -132,7 +191,9 @@ class SpaceManagementBloc
|
|||||||
|
|
||||||
Future<List<SpaceModel>> _fetchSpacesForCommunity(
|
Future<List<SpaceModel>> _fetchSpacesForCommunity(
|
||||||
String communityUuid) async {
|
String communityUuid) async {
|
||||||
return await _api.getSpaceHierarchy(communityUuid);
|
final projectUuid = await ProjectManager.getProjectUUID() ?? '';
|
||||||
|
|
||||||
|
return await _api.getSpaceHierarchy(communityUuid, projectUuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _onNewCommunity(
|
Future<void> _onNewCommunity(
|
||||||
@ -147,7 +208,7 @@ class SpaceManagementBloc
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var prevSpaceModels = await fetchSpaceModels(previousState);
|
var prevSpaceModels = await fetchSpaceModels();
|
||||||
|
|
||||||
emit(BlankState(
|
emit(BlankState(
|
||||||
communities: event.communities,
|
communities: event.communities,
|
||||||
@ -163,7 +224,11 @@ class SpaceManagementBloc
|
|||||||
BlankStateEvent event, Emitter<SpaceManagementState> emit) async {
|
BlankStateEvent event, Emitter<SpaceManagementState> emit) async {
|
||||||
try {
|
try {
|
||||||
final previousState = state;
|
final previousState = state;
|
||||||
var prevSpaceModels = await fetchSpaceModels(previousState);
|
final projectUuid = await ProjectManager.getProjectUUID() ?? '';
|
||||||
|
var spaceBloc = event.context.read<SpaceTreeBloc>();
|
||||||
|
List<CommunityModel> communities = await _waitForCommunityList(spaceBloc);
|
||||||
|
|
||||||
|
var prevSpaceModels = await fetchSpaceModels();
|
||||||
|
|
||||||
if (previousState is SpaceManagementLoaded ||
|
if (previousState is SpaceManagementLoaded ||
|
||||||
previousState is BlankState) {
|
previousState is BlankState) {
|
||||||
@ -176,25 +241,31 @@ class SpaceManagementBloc
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final communities = await _api.fetchCommunities();
|
if (communities.isEmpty) {
|
||||||
final updatedCommunities =
|
communities = await _api.fetchCommunities(projectUuid);
|
||||||
await Future.wait(communities.map((community) async {
|
|
||||||
final spaces = await _fetchSpacesForCommunity(community.uuid);
|
|
||||||
|
|
||||||
return CommunityModel(
|
List<CommunityModel> updatedCommunities = await Future.wait(
|
||||||
uuid: community.uuid,
|
communities.map((community) async {
|
||||||
createdAt: community.createdAt,
|
List<SpaceModel> spaces =
|
||||||
updatedAt: community.updatedAt,
|
await _fetchSpacesForCommunity(community.uuid);
|
||||||
name: community.name,
|
return CommunityModel(
|
||||||
description: community.description,
|
uuid: community.uuid,
|
||||||
spaces: spaces,
|
createdAt: community.createdAt,
|
||||||
region: community.region,
|
updatedAt: community.updatedAt,
|
||||||
|
name: community.name,
|
||||||
|
description: community.description,
|
||||||
|
spaces: spaces,
|
||||||
|
region: community.region,
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
);
|
);
|
||||||
}));
|
|
||||||
|
communities = updatedCommunities;
|
||||||
|
}
|
||||||
|
|
||||||
emit(BlankState(
|
emit(BlankState(
|
||||||
spaceModels: prevSpaceModels,
|
spaceModels: prevSpaceModels,
|
||||||
communities: updatedCommunities,
|
communities: communities,
|
||||||
products: _cachedProducts ?? [],
|
products: _cachedProducts ?? [],
|
||||||
));
|
));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -206,36 +277,39 @@ class SpaceManagementBloc
|
|||||||
LoadCommunityAndSpacesEvent event,
|
LoadCommunityAndSpacesEvent event,
|
||||||
Emitter<SpaceManagementState> emit,
|
Emitter<SpaceManagementState> emit,
|
||||||
) async {
|
) async {
|
||||||
var prevState = state;
|
var spaceBloc = event.context.read<SpaceTreeBloc>();
|
||||||
emit(SpaceManagementLoading());
|
_onloadProducts();
|
||||||
try {
|
|
||||||
_onloadProducts();
|
|
||||||
List<CommunityModel> communities = await _api.fetchCommunities();
|
|
||||||
|
|
||||||
List<CommunityModel> updatedCommunities = await Future.wait(
|
// Wait until `communityList` is loaded
|
||||||
communities.map((community) async {
|
List<CommunityModel> communities = await _waitForCommunityList(spaceBloc);
|
||||||
List<SpaceModel> spaces =
|
|
||||||
await _fetchSpacesForCommunity(community.uuid);
|
|
||||||
return CommunityModel(
|
|
||||||
uuid: community.uuid,
|
|
||||||
createdAt: community.createdAt,
|
|
||||||
updatedAt: community.updatedAt,
|
|
||||||
name: community.name,
|
|
||||||
description: community.description,
|
|
||||||
spaces: spaces, // New spaces list
|
|
||||||
region: community.region,
|
|
||||||
);
|
|
||||||
}).toList(),
|
|
||||||
);
|
|
||||||
|
|
||||||
final prevSpaceModels = await fetchSpaceModels(prevState);
|
// Fetch space models after communities are available
|
||||||
emit(SpaceManagementLoaded(
|
final prevSpaceModels = await fetchSpaceModels();
|
||||||
communities: updatedCommunities,
|
emit(SpaceManagementLoaded(
|
||||||
products: _cachedProducts ?? [],
|
communities: communities,
|
||||||
spaceModels: prevSpaceModels));
|
products: _cachedProducts ?? [],
|
||||||
} catch (e) {
|
spaceModels: prevSpaceModels,
|
||||||
emit(SpaceManagementError('Error loading communities and spaces: $e'));
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<CommunityModel>> _waitForCommunityList(
|
||||||
|
SpaceTreeBloc spaceBloc) async {
|
||||||
|
// Check if communityList is already populated
|
||||||
|
if (spaceBloc.state.communityList.isNotEmpty) {
|
||||||
|
return spaceBloc.state.communityList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final completer = Completer<List<CommunityModel>>();
|
||||||
|
final subscription = spaceBloc.stream.listen((state) {
|
||||||
|
if (state.communityList.isNotEmpty) {
|
||||||
|
completer.complete(state.communityList);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Return the list once available, then cancel the listener
|
||||||
|
final communities = await completer.future;
|
||||||
|
await subscription.cancel();
|
||||||
|
return communities;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onCommunityDelete(
|
void _onCommunityDelete(
|
||||||
@ -244,10 +318,12 @@ class SpaceManagementBloc
|
|||||||
) async {
|
) async {
|
||||||
try {
|
try {
|
||||||
emit(SpaceManagementLoading());
|
emit(SpaceManagementLoading());
|
||||||
|
final projectUuid = await ProjectManager.getProjectUUID() ?? '';
|
||||||
|
|
||||||
final success = await _api.deleteCommunity(event.communityUuid);
|
final success =
|
||||||
|
await _api.deleteCommunity(event.communityUuid, projectUuid);
|
||||||
if (success) {
|
if (success) {
|
||||||
add(LoadCommunityAndSpacesEvent());
|
// add(LoadCommunityAndSpacesEvent());
|
||||||
} else {
|
} else {
|
||||||
emit(const SpaceManagementError('Failed to delete the community.'));
|
emit(const SpaceManagementError('Failed to delete the community.'));
|
||||||
}
|
}
|
||||||
@ -257,11 +333,6 @@ class SpaceManagementBloc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onUpdateSpacePosition(
|
|
||||||
UpdateSpacePositionEvent event,
|
|
||||||
Emitter<SpaceManagementState> emit,
|
|
||||||
) {}
|
|
||||||
|
|
||||||
void _onCreateCommunity(
|
void _onCreateCommunity(
|
||||||
CreateCommunityEvent event,
|
CreateCommunityEvent event,
|
||||||
Emitter<SpaceManagementState> emit,
|
Emitter<SpaceManagementState> emit,
|
||||||
@ -270,9 +341,11 @@ class SpaceManagementBloc
|
|||||||
emit(SpaceManagementLoading());
|
emit(SpaceManagementLoading());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
CommunityModel? newCommunity =
|
final projectUuid = await ProjectManager.getProjectUUID() ?? '';
|
||||||
await _api.createCommunity(event.name, event.description);
|
|
||||||
var prevSpaceModels = await fetchSpaceModels(previousState);
|
CommunityModel? newCommunity = await _api.createCommunity(
|
||||||
|
event.name, event.description, projectUuid);
|
||||||
|
var prevSpaceModels = await fetchSpaceModels();
|
||||||
|
|
||||||
if (newCommunity != null) {
|
if (newCommunity != null) {
|
||||||
if (previousState is SpaceManagementLoaded ||
|
if (previousState is SpaceManagementLoaded ||
|
||||||
@ -281,6 +354,8 @@ class SpaceManagementBloc
|
|||||||
(previousState as dynamic).communities,
|
(previousState as dynamic).communities,
|
||||||
);
|
);
|
||||||
final updatedCommunities = prevCommunities..add(newCommunity);
|
final updatedCommunities = prevCommunities..add(newCommunity);
|
||||||
|
_spaceTreeBloc.add(OnCommunityAdded(newCommunity));
|
||||||
|
|
||||||
emit(SpaceManagementLoaded(
|
emit(SpaceManagementLoaded(
|
||||||
spaceModels: prevSpaceModels,
|
spaceModels: prevSpaceModels,
|
||||||
communities: updatedCommunities,
|
communities: updatedCommunities,
|
||||||
@ -375,8 +450,6 @@ class SpaceManagementBloc
|
|||||||
event.communityUuid,
|
event.communityUuid,
|
||||||
emit,
|
emit,
|
||||||
);
|
);
|
||||||
} else {
|
|
||||||
add(LoadCommunityAndSpacesEvent());
|
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(SpaceManagementError('Error saving spaces: $e'));
|
emit(SpaceManagementError('Error saving spaces: $e'));
|
||||||
@ -393,13 +466,15 @@ class SpaceManagementBloc
|
|||||||
String communityUuid,
|
String communityUuid,
|
||||||
Emitter<SpaceManagementState> emit,
|
Emitter<SpaceManagementState> emit,
|
||||||
) async {
|
) async {
|
||||||
var prevSpaceModels = await fetchSpaceModels(previousState);
|
var prevSpaceModels = await fetchSpaceModels();
|
||||||
|
|
||||||
final communities = List<CommunityModel>.from(previousState.communities);
|
final communities = List<CommunityModel>.from(previousState.communities);
|
||||||
|
|
||||||
for (var community in communities) {
|
for (var community in communities) {
|
||||||
if (community.uuid == communityUuid) {
|
if (community.uuid == communityUuid) {
|
||||||
community.spaces = allSpaces;
|
community.spaces = allSpaces;
|
||||||
|
_spaceTreeBloc.add(OnCommunityUpdated(community));
|
||||||
|
|
||||||
emit(SpaceManagementLoaded(
|
emit(SpaceManagementLoaded(
|
||||||
communities: communities,
|
communities: communities,
|
||||||
products: _cachedProducts ?? [],
|
products: _cachedProducts ?? [],
|
||||||
@ -414,6 +489,7 @@ class SpaceManagementBloc
|
|||||||
Future<List<SpaceModel>> saveSpacesHierarchically(
|
Future<List<SpaceModel>> saveSpacesHierarchically(
|
||||||
List<SpaceModel> spaces, String communityUuid) async {
|
List<SpaceModel> spaces, String communityUuid) async {
|
||||||
final orderedSpaces = flattenHierarchy(spaces);
|
final orderedSpaces = flattenHierarchy(spaces);
|
||||||
|
final projectUuid = await ProjectManager.getProjectUUID() ?? '';
|
||||||
|
|
||||||
final parentsToDelete = orderedSpaces.where((space) =>
|
final parentsToDelete = orderedSpaces.where((space) =>
|
||||||
space.status == SpaceStatus.deleted &&
|
space.status == SpaceStatus.deleted &&
|
||||||
@ -422,7 +498,7 @@ class SpaceManagementBloc
|
|||||||
for (var parent in parentsToDelete) {
|
for (var parent in parentsToDelete) {
|
||||||
try {
|
try {
|
||||||
if (parent.uuid != null) {
|
if (parent.uuid != null) {
|
||||||
await _api.deleteSpace(communityUuid, parent.uuid!);
|
await _api.deleteSpace(communityUuid, parent.uuid!, projectUuid);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
rethrow;
|
rethrow;
|
||||||
@ -435,7 +511,8 @@ class SpaceManagementBloc
|
|||||||
if (space.uuid != null && space.uuid!.isNotEmpty) {
|
if (space.uuid != null && space.uuid!.isNotEmpty) {
|
||||||
List<TagModelUpdate> tagUpdates = [];
|
List<TagModelUpdate> tagUpdates = [];
|
||||||
|
|
||||||
final prevSpace = await _api.getSpace(communityUuid, space.uuid!);
|
final prevSpace =
|
||||||
|
await _api.getSpace(communityUuid, space.uuid!, projectUuid);
|
||||||
final List<UpdateSubspaceTemplateModel> subspaceUpdates = [];
|
final List<UpdateSubspaceTemplateModel> subspaceUpdates = [];
|
||||||
final List<SubspaceModel>? prevSubspaces = prevSpace?.subspaces;
|
final List<SubspaceModel>? prevSubspaces = prevSpace?.subspaces;
|
||||||
final List<SubspaceModel>? newSubspaces = space.subspaces;
|
final List<SubspaceModel>? newSubspaces = space.subspaces;
|
||||||
@ -449,13 +526,15 @@ class SpaceManagementBloc
|
|||||||
.any((subspace) => subspace.uuid == prevSubspace.uuid);
|
.any((subspace) => subspace.uuid == prevSubspace.uuid);
|
||||||
if (!existsInNew) {
|
if (!existsInNew) {
|
||||||
subspaceUpdates.add(UpdateSubspaceTemplateModel(
|
subspaceUpdates.add(UpdateSubspaceTemplateModel(
|
||||||
action: Action.delete, uuid: prevSubspace.uuid));
|
action: custom_action.Action.delete,
|
||||||
|
uuid: prevSubspace.uuid));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (prevSubspaces != null && newSubspaces == null) {
|
} else if (prevSubspaces != null && newSubspaces == null) {
|
||||||
for (var prevSubspace in prevSubspaces) {
|
for (var prevSubspace in prevSubspaces) {
|
||||||
subspaceUpdates.add(UpdateSubspaceTemplateModel(
|
subspaceUpdates.add(UpdateSubspaceTemplateModel(
|
||||||
action: Action.delete, uuid: prevSubspace.uuid));
|
action: custom_action.Action.delete,
|
||||||
|
uuid: prevSubspace.uuid));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -468,14 +547,14 @@ class SpaceManagementBloc
|
|||||||
if (newSubspace.tags != null) {
|
if (newSubspace.tags != null) {
|
||||||
for (var tag in newSubspace.tags!) {
|
for (var tag in newSubspace.tags!) {
|
||||||
tagUpdates.add(TagModelUpdate(
|
tagUpdates.add(TagModelUpdate(
|
||||||
action: Action.add,
|
action: custom_action.Action.add,
|
||||||
uuid: tag.uuid == '' ? null : tag.uuid,
|
uuid: tag.uuid == '' ? null : tag.uuid,
|
||||||
tag: tag.tag,
|
tag: tag.tag,
|
||||||
productUuid: tag.product?.uuid));
|
productUuid: tag.product?.uuid));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
subspaceUpdates.add(UpdateSubspaceTemplateModel(
|
subspaceUpdates.add(UpdateSubspaceTemplateModel(
|
||||||
action: Action.add,
|
action: custom_action.Action.add,
|
||||||
subspaceName: newSubspace.subspaceName,
|
subspaceName: newSubspace.subspaceName,
|
||||||
tags: tagUpdates));
|
tags: tagUpdates));
|
||||||
}
|
}
|
||||||
@ -494,7 +573,7 @@ class SpaceManagementBloc
|
|||||||
final List<TagModelUpdate> tagSubspaceUpdates =
|
final List<TagModelUpdate> tagSubspaceUpdates =
|
||||||
processTagUpdates(prevSubspace.tags, newSubspace.tags);
|
processTagUpdates(prevSubspace.tags, newSubspace.tags);
|
||||||
subspaceUpdates.add(UpdateSubspaceTemplateModel(
|
subspaceUpdates.add(UpdateSubspaceTemplateModel(
|
||||||
action: Action.update,
|
action: custom_action.Action.update,
|
||||||
uuid: newSubspace.uuid,
|
uuid: newSubspace.uuid,
|
||||||
subspaceName: newSubspace.subspaceName,
|
subspaceName: newSubspace.subspaceName,
|
||||||
tags: tagSubspaceUpdates));
|
tags: tagSubspaceUpdates));
|
||||||
@ -504,17 +583,17 @@ class SpaceManagementBloc
|
|||||||
}
|
}
|
||||||
|
|
||||||
final response = await _api.updateSpace(
|
final response = await _api.updateSpace(
|
||||||
communityId: communityUuid,
|
communityId: communityUuid,
|
||||||
spaceId: space.uuid!,
|
spaceId: space.uuid!,
|
||||||
name: space.name,
|
name: space.name,
|
||||||
parentId: space.parent?.uuid,
|
parentId: space.parent?.uuid,
|
||||||
isPrivate: space.isPrivate,
|
isPrivate: space.isPrivate,
|
||||||
position: space.position,
|
position: space.position,
|
||||||
icon: space.icon,
|
icon: space.icon,
|
||||||
subspaces: subspaceUpdates,
|
subspaces: subspaceUpdates,
|
||||||
tags: tagUpdates,
|
tags: tagUpdates,
|
||||||
direction: space.incomingConnection?.direction,
|
direction: space.incomingConnection?.direction,
|
||||||
);
|
projectId: projectUuid);
|
||||||
} else {
|
} else {
|
||||||
// Call create if the space does not have a UUID
|
// Call create if the space does not have a UUID
|
||||||
final List<CreateTagBodyModel> tagBodyModels = space.tags != null
|
final List<CreateTagBodyModel> tagBodyModels = space.tags != null
|
||||||
@ -533,17 +612,17 @@ class SpaceManagementBloc
|
|||||||
[];
|
[];
|
||||||
|
|
||||||
final response = await _api.createSpace(
|
final response = await _api.createSpace(
|
||||||
communityId: communityUuid,
|
communityId: communityUuid,
|
||||||
name: space.name,
|
name: space.name,
|
||||||
parentId: space.parent?.uuid,
|
parentId: space.parent?.uuid,
|
||||||
isPrivate: space.isPrivate,
|
isPrivate: space.isPrivate,
|
||||||
position: space.position,
|
position: space.position,
|
||||||
icon: space.icon,
|
icon: space.icon,
|
||||||
direction: space.incomingConnection?.direction,
|
direction: space.incomingConnection?.direction,
|
||||||
spaceModelUuid: space.spaceModel?.uuid,
|
spaceModelUuid: space.spaceModel?.uuid,
|
||||||
tags: tagBodyModels,
|
tags: tagBodyModels,
|
||||||
subspaces: createSubspaceBodyModels,
|
subspaces: createSubspaceBodyModels,
|
||||||
);
|
projectId: projectUuid);
|
||||||
space.uuid = response?.uuid;
|
space.uuid = response?.uuid;
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -581,33 +660,42 @@ class SpaceManagementBloc
|
|||||||
void _onLoadSpaceModel(
|
void _onLoadSpaceModel(
|
||||||
SpaceModelLoadEvent event, Emitter<SpaceManagementState> emit) async {
|
SpaceModelLoadEvent event, Emitter<SpaceManagementState> emit) async {
|
||||||
emit(SpaceManagementLoading());
|
emit(SpaceManagementLoading());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var prevState = state;
|
var prevState = state;
|
||||||
|
final projectUuid = await ProjectManager.getProjectUUID() ?? '';
|
||||||
|
var spaceBloc = event.context.read<SpaceTreeBloc>();
|
||||||
|
List<CommunityModel> communities = spaceBloc.state.communityList;
|
||||||
|
|
||||||
List<CommunityModel> communities = await _api.fetchCommunities();
|
var prevSpaceModels = await fetchSpaceModels();
|
||||||
|
|
||||||
List<CommunityModel> updatedCommunities = await Future.wait(
|
if (communities.isEmpty) {
|
||||||
communities.map((community) async {
|
communities = await _api.fetchCommunities(projectUuid);
|
||||||
List<SpaceModel> spaces =
|
|
||||||
await _fetchSpacesForCommunity(community.uuid);
|
|
||||||
return CommunityModel(
|
|
||||||
uuid: community.uuid,
|
|
||||||
createdAt: community.createdAt,
|
|
||||||
updatedAt: community.updatedAt,
|
|
||||||
name: community.name,
|
|
||||||
description: community.description,
|
|
||||||
spaces: spaces, // New spaces list
|
|
||||||
region: community.region,
|
|
||||||
);
|
|
||||||
}).toList(),
|
|
||||||
);
|
|
||||||
|
|
||||||
var prevSpaceModels = await fetchSpaceModels(prevState);
|
List<CommunityModel> updatedCommunities = await Future.wait(
|
||||||
|
communities.map((community) async {
|
||||||
|
List<SpaceModel> spaces =
|
||||||
|
await _fetchSpacesForCommunity(community.uuid);
|
||||||
|
return CommunityModel(
|
||||||
|
uuid: community.uuid,
|
||||||
|
createdAt: community.createdAt,
|
||||||
|
updatedAt: community.updatedAt,
|
||||||
|
name: community.name,
|
||||||
|
description: community.description,
|
||||||
|
spaces: spaces,
|
||||||
|
region: community.region,
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
);
|
||||||
|
|
||||||
|
communities = updatedCommunities;
|
||||||
|
}
|
||||||
|
|
||||||
emit(SpaceModelLoaded(
|
emit(SpaceModelLoaded(
|
||||||
communities: updatedCommunities,
|
communities: communities,
|
||||||
products: _cachedProducts ?? [],
|
products: _cachedProducts ?? [],
|
||||||
spaceModels: prevSpaceModels));
|
spaceModels: prevSpaceModels,
|
||||||
|
));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(SpaceManagementError('Error loading communities and spaces: $e'));
|
emit(SpaceManagementError('Error loading communities and spaces: $e'));
|
||||||
}
|
}
|
||||||
@ -623,7 +711,7 @@ class SpaceManagementBloc
|
|||||||
if (prevTags == null && newTags != null) {
|
if (prevTags == null && newTags != null) {
|
||||||
for (var newTag in newTags) {
|
for (var newTag in newTags) {
|
||||||
tagUpdates.add(TagModelUpdate(
|
tagUpdates.add(TagModelUpdate(
|
||||||
action: Action.add,
|
action: custom_action.Action.add,
|
||||||
tag: newTag.tag,
|
tag: newTag.tag,
|
||||||
uuid: newTag.uuid,
|
uuid: newTag.uuid,
|
||||||
productUuid: newTag.product?.uuid,
|
productUuid: newTag.product?.uuid,
|
||||||
@ -639,14 +727,14 @@ class SpaceManagementBloc
|
|||||||
final existsInNew =
|
final existsInNew =
|
||||||
newTags.any((newTag) => newTag.uuid == prevTag.uuid);
|
newTags.any((newTag) => newTag.uuid == prevTag.uuid);
|
||||||
if (!existsInNew) {
|
if (!existsInNew) {
|
||||||
tagUpdates
|
tagUpdates.add(TagModelUpdate(
|
||||||
.add(TagModelUpdate(action: Action.delete, uuid: prevTag.uuid));
|
action: custom_action.Action.delete, uuid: prevTag.uuid));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (prevTags != null && newTags == null) {
|
} else if (prevTags != null && newTags == null) {
|
||||||
for (var prevTag in prevTags) {
|
for (var prevTag in prevTags) {
|
||||||
tagUpdates
|
tagUpdates.add(TagModelUpdate(
|
||||||
.add(TagModelUpdate(action: Action.delete, uuid: prevTag.uuid));
|
action: custom_action.Action.delete, uuid: prevTag.uuid));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -659,7 +747,7 @@ class SpaceManagementBloc
|
|||||||
if ((newTag.uuid == null || !prevTagUuids.contains(newTag.uuid)) &&
|
if ((newTag.uuid == null || !prevTagUuids.contains(newTag.uuid)) &&
|
||||||
!processedTags.contains(newTag.tag)) {
|
!processedTags.contains(newTag.tag)) {
|
||||||
tagUpdates.add(TagModelUpdate(
|
tagUpdates.add(TagModelUpdate(
|
||||||
action: Action.add,
|
action: custom_action.Action.add,
|
||||||
tag: newTag.tag,
|
tag: newTag.tag,
|
||||||
uuid: newTag.uuid == '' ? null : newTag.uuid,
|
uuid: newTag.uuid == '' ? null : newTag.uuid,
|
||||||
productUuid: newTag.product?.uuid));
|
productUuid: newTag.product?.uuid));
|
||||||
@ -676,7 +764,7 @@ class SpaceManagementBloc
|
|||||||
final newTag = newTagMap[prevTag.uuid];
|
final newTag = newTagMap[prevTag.uuid];
|
||||||
if (newTag != null) {
|
if (newTag != null) {
|
||||||
tagUpdates.add(TagModelUpdate(
|
tagUpdates.add(TagModelUpdate(
|
||||||
action: Action.update,
|
action: custom_action.Action.update,
|
||||||
uuid: newTag.uuid,
|
uuid: newTag.uuid,
|
||||||
tag: newTag.tag,
|
tag: newTag.tag,
|
||||||
));
|
));
|
||||||
|
@ -1,16 +1,23 @@
|
|||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart'; // Import for Offset
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart';
|
||||||
|
import 'package:syncrow_web/pages/spaces_management/space_model/models/space_template_model.dart'; // Import for Offset
|
||||||
|
|
||||||
abstract class SpaceManagementEvent extends Equatable {
|
abstract class SpaceManagementEvent extends Equatable {
|
||||||
const SpaceManagementEvent();
|
const SpaceManagementEvent();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [];
|
List<Object?> get props => [];
|
||||||
}
|
}
|
||||||
|
|
||||||
class LoadCommunityAndSpacesEvent extends SpaceManagementEvent {}
|
class LoadCommunityAndSpacesEvent extends SpaceManagementEvent {
|
||||||
|
final BuildContext context;
|
||||||
|
|
||||||
|
const LoadCommunityAndSpacesEvent(this.context);
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [context];
|
||||||
|
}
|
||||||
|
|
||||||
class DeleteCommunityEvent extends SpaceManagementEvent {
|
class DeleteCommunityEvent extends SpaceManagementEvent {
|
||||||
final String communityUuid;
|
final String communityUuid;
|
||||||
@ -74,14 +81,12 @@ class UpdateSpacePositionEvent extends SpaceManagementEvent {
|
|||||||
class CreateCommunityEvent extends SpaceManagementEvent {
|
class CreateCommunityEvent extends SpaceManagementEvent {
|
||||||
final String name;
|
final String name;
|
||||||
final String description;
|
final String description;
|
||||||
|
final BuildContext context;
|
||||||
|
|
||||||
const CreateCommunityEvent({
|
const CreateCommunityEvent(this.name, this.description, this.context);
|
||||||
required this.name,
|
|
||||||
required this.description,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [name, description];
|
List<Object?> get props => [name, description, context];
|
||||||
}
|
}
|
||||||
|
|
||||||
class UpdateCommunityEvent extends SpaceManagementEvent {
|
class UpdateCommunityEvent extends SpaceManagementEvent {
|
||||||
@ -141,7 +146,28 @@ class LoadSpaceHierarchyEvent extends SpaceManagementEvent {
|
|||||||
List<Object> get props => [communityId];
|
List<Object> get props => [communityId];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class BlankStateEvent extends SpaceManagementEvent {
|
||||||
|
final BuildContext context;
|
||||||
|
|
||||||
class BlankStateEvent extends SpaceManagementEvent {}
|
const BlankStateEvent(this.context);
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [context];
|
||||||
|
}
|
||||||
|
|
||||||
class SpaceModelLoadEvent extends SpaceManagementEvent {}
|
class SpaceModelLoadEvent extends SpaceManagementEvent {
|
||||||
|
final BuildContext context;
|
||||||
|
|
||||||
|
const SpaceModelLoadEvent(this.context);
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [context];
|
||||||
|
}
|
||||||
|
|
||||||
|
class UpdateSpaceModelCache extends SpaceManagementEvent {
|
||||||
|
final SpaceTemplateModel updatedModel;
|
||||||
|
UpdateSpaceModelCache(this.updatedModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
class DeleteSpaceModelFromCache extends SpaceManagementEvent {
|
||||||
|
final String deletedUuid;
|
||||||
|
DeleteSpaceModelFromCache(this.deletedUuid);
|
||||||
|
}
|
@ -30,10 +30,6 @@ class SpaceManagementLoaded extends SpaceManagementState {
|
|||||||
this.spaceModels});
|
this.spaceModels});
|
||||||
}
|
}
|
||||||
|
|
||||||
class SpaceModelManagenetLoaded extends SpaceManagementState {
|
|
||||||
SpaceModelManagenetLoaded();
|
|
||||||
}
|
|
||||||
|
|
||||||
class BlankState extends SpaceManagementState {
|
class BlankState extends SpaceManagementState {
|
||||||
final List<CommunityModel> communities;
|
final List<CommunityModel> communities;
|
||||||
final List<ProductModel> products;
|
final List<ProductModel> products;
|
||||||
@ -75,3 +71,4 @@ class SpaceModelLoaded extends SpaceManagementState {
|
|||||||
@override
|
@override
|
||||||
List<Object> get props => [communities, products, spaceModels];
|
List<Object> get props => [communities, products, spaceModels];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
|
import 'dart:developer';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/shared/navigate_home_grid_view.dart';
|
import 'package:syncrow_web/pages/device_managment/shared/navigate_home_grid_view.dart';
|
||||||
|
import 'package:syncrow_web/pages/space_tree/bloc/space_tree_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/structure_selector/bloc/center_body_bloc.dart';
|
import 'package:syncrow_web/pages/spaces_management/structure_selector/bloc/center_body_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/all_spaces/bloc/space_management_bloc.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/bloc/space_management_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/all_spaces/bloc/space_management_event.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/bloc/space_management_event.dart';
|
||||||
@ -29,11 +32,15 @@ class SpaceManagementPageState extends State<SpaceManagementPage> {
|
|||||||
return MultiBlocProvider(
|
return MultiBlocProvider(
|
||||||
providers: [
|
providers: [
|
||||||
BlocProvider(
|
BlocProvider(
|
||||||
create: (_) => SpaceManagementBloc(_api, _productApi, _spaceModelApi)
|
create: (context) => SpaceManagementBloc(
|
||||||
..add(LoadCommunityAndSpacesEvent()),
|
_api,
|
||||||
|
_productApi,
|
||||||
|
_spaceModelApi,
|
||||||
|
BlocProvider.of<SpaceTreeBloc>(context),
|
||||||
|
)..add(LoadCommunityAndSpacesEvent(this.context)),
|
||||||
),
|
),
|
||||||
BlocProvider(
|
BlocProvider(
|
||||||
create: (_) => CenterBodyBloc(),
|
create: (context) => CenterBodyBloc(),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
child: WebScaffold(
|
child: WebScaffold(
|
||||||
@ -57,6 +64,7 @@ class SpaceManagementPageState extends State<SpaceManagementPage> {
|
|||||||
shouldNavigateToSpaceModelPage: false,
|
shouldNavigateToSpaceModelPage: false,
|
||||||
);
|
);
|
||||||
} else if (state is SpaceManagementLoaded) {
|
} else if (state is SpaceManagementLoaded) {
|
||||||
|
|
||||||
return LoadedSpaceView(
|
return LoadedSpaceView(
|
||||||
communities: state.communities,
|
communities: state.communities,
|
||||||
selectedCommunity: state.selectedCommunity,
|
selectedCommunity: state.selectedCommunity,
|
||||||
|
@ -73,17 +73,14 @@ class _BlankCommunityWidgetState extends State<BlankCommunityWidget> {
|
|||||||
context: parentContext,
|
context: parentContext,
|
||||||
builder: (context) => CreateCommunityDialog(
|
builder: (context) => CreateCommunityDialog(
|
||||||
isEditMode: false,
|
isEditMode: false,
|
||||||
existingCommunityNames: widget.communities.map((community) => community.name).toList(),
|
existingCommunityNames:
|
||||||
|
widget.communities.map((community) => community.name).toList(),
|
||||||
onCreateCommunity: (String communityName, String description) {
|
onCreateCommunity: (String communityName, String description) {
|
||||||
parentContext.read<SpaceManagementBloc>().add(
|
parentContext.read<SpaceManagementBloc>().add(
|
||||||
CreateCommunityEvent(
|
CreateCommunityEvent(communityName, description, context),
|
||||||
name: communityName,
|
|
||||||
description: description,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -21,15 +21,17 @@ class CommunityTile extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return CustomExpansionTile(
|
return Padding(
|
||||||
title: title,
|
padding: const EdgeInsets.only(left: 16.0),
|
||||||
initiallyExpanded: isExpanded,
|
child: CustomExpansionTile(
|
||||||
isSelected: isSelected,
|
title: title,
|
||||||
onExpansionChanged: (bool expanded) {
|
initiallyExpanded: isExpanded,
|
||||||
onExpansionChanged(title, expanded);
|
isSelected: isSelected,
|
||||||
},
|
onExpansionChanged: (bool expanded) {
|
||||||
onItemSelected: onItemSelected,
|
onExpansionChanged(title, expanded);
|
||||||
children: children ?? [],
|
},
|
||||||
);
|
onItemSelected: onItemSelected,
|
||||||
|
children: children ?? [],
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/space_tree/view/space_tree_view.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_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/product_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart';
|
||||||
@ -39,6 +40,7 @@ class _LoadedSpaceViewState extends State<LoadedSpaceView> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
_spaceModels = List.from(widget.spaceModels ?? []);
|
_spaceModels = List.from(widget.spaceModels ?? []);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,6 +48,7 @@ class _LoadedSpaceViewState extends State<LoadedSpaceView> {
|
|||||||
@override
|
@override
|
||||||
void didUpdateWidget(covariant LoadedSpaceView oldWidget) {
|
void didUpdateWidget(covariant LoadedSpaceView oldWidget) {
|
||||||
super.didUpdateWidget(oldWidget);
|
super.didUpdateWidget(oldWidget);
|
||||||
|
|
||||||
if (widget.spaceModels != oldWidget.spaceModels) {
|
if (widget.spaceModels != oldWidget.spaceModels) {
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
@ -74,28 +77,36 @@ class _LoadedSpaceViewState extends State<LoadedSpaceView> {
|
|||||||
return Stack(
|
return Stack(
|
||||||
clipBehavior: Clip.none,
|
clipBehavior: Clip.none,
|
||||||
children: [
|
children: [
|
||||||
Row(
|
widget.shouldNavigateToSpaceModelPage
|
||||||
children: [
|
? _spaceModels.isNotEmpty
|
||||||
SidebarWidget(
|
? Row(
|
||||||
communities: widget.communities,
|
children: [
|
||||||
selectedSpaceUuid: widget.selectedSpace?.uuid ??
|
SizedBox(
|
||||||
widget.selectedCommunity?.uuid ??
|
width: 300, child: SpaceTreeView(onSelect: () {})),
|
||||||
'',
|
Expanded(
|
||||||
),
|
child: BlocProvider(
|
||||||
widget.shouldNavigateToSpaceModelPage
|
create: (context) => SpaceModelBloc(
|
||||||
? Expanded(
|
api: SpaceModelManagementApi(),
|
||||||
child: BlocProvider(
|
initialSpaceModels: _spaceModels,
|
||||||
create: (context) => SpaceModelBloc(
|
),
|
||||||
api: SpaceModelManagementApi(),
|
child: SpaceModelPage(
|
||||||
initialSpaceModels: _spaceModels,
|
products: widget.products,
|
||||||
|
onSpaceModelsUpdated: _onSpaceModelsUpdated,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
child: SpaceModelPage(
|
],
|
||||||
products: widget.products,
|
|
||||||
onSpaceModelsUpdated: _onSpaceModelsUpdated,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
: CommunityStructureArea(
|
: const Center(child: CircularProgressIndicator())
|
||||||
|
: Row(
|
||||||
|
children: [
|
||||||
|
SidebarWidget(
|
||||||
|
communities: widget.communities,
|
||||||
|
selectedSpaceUuid: widget.selectedSpace?.uuid ??
|
||||||
|
widget.selectedCommunity?.uuid ??
|
||||||
|
'',
|
||||||
|
),
|
||||||
|
CommunityStructureArea(
|
||||||
selectedCommunity: widget.selectedCommunity,
|
selectedCommunity: widget.selectedCommunity,
|
||||||
selectedSpace: widget.selectedSpace,
|
selectedSpace: widget.selectedSpace,
|
||||||
spaces: widget.selectedCommunity?.spaces ?? [],
|
spaces: widget.selectedCommunity?.spaces ?? [],
|
||||||
@ -103,8 +114,8 @@ class _LoadedSpaceViewState extends State<LoadedSpaceView> {
|
|||||||
communities: widget.communities,
|
communities: widget.communities,
|
||||||
spaceModels: _spaceModels,
|
spaceModels: _spaceModels,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const GradientCanvasBorderWidget(),
|
const GradientCanvasBorderWidget(),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/common/bloc/project_manager.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/models/create_space_template_body_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/space_model/models/create_space_template_body_model.dart';
|
||||||
@ -18,6 +19,8 @@ class CreateSpaceModelBloc
|
|||||||
CreateSpaceModelBloc(this._api) : super(CreateSpaceModelInitial()) {
|
CreateSpaceModelBloc(this._api) : super(CreateSpaceModelInitial()) {
|
||||||
on<CreateSpaceTemplate>((event, emit) async {
|
on<CreateSpaceTemplate>((event, emit) async {
|
||||||
try {
|
try {
|
||||||
|
final projectUuid = await ProjectManager.getProjectUUID() ?? '';
|
||||||
|
|
||||||
late SpaceTemplateModel spaceTemplate = event.spaceTemplate;
|
late SpaceTemplateModel spaceTemplate = event.spaceTemplate;
|
||||||
|
|
||||||
final tagBodyModels =
|
final tagBodyModels =
|
||||||
@ -40,7 +43,8 @@ class CreateSpaceModelBloc
|
|||||||
tags: tagBodyModels,
|
tags: tagBodyModels,
|
||||||
subspaceModels: subspaceTemplateBodyModels);
|
subspaceModels: subspaceTemplateBodyModels);
|
||||||
|
|
||||||
final newSpaceTemplate = await _api.createSpaceModel(spaceModelBody);
|
final newSpaceTemplate =
|
||||||
|
await _api.createSpaceModel(spaceModelBody, projectUuid);
|
||||||
spaceTemplate.uuid = newSpaceTemplate?.uuid ?? '';
|
spaceTemplate.uuid = newSpaceTemplate?.uuid ?? '';
|
||||||
|
|
||||||
if (newSpaceTemplate != null) {
|
if (newSpaceTemplate != null) {
|
||||||
@ -201,9 +205,11 @@ class CreateSpaceModelBloc
|
|||||||
|
|
||||||
on<ModifySpaceTemplate>((event, emit) async {
|
on<ModifySpaceTemplate>((event, emit) async {
|
||||||
try {
|
try {
|
||||||
|
final projectUuid = await ProjectManager.getProjectUUID() ?? '';
|
||||||
|
|
||||||
if (event.spaceTemplate.uuid != null) {
|
if (event.spaceTemplate.uuid != null) {
|
||||||
final prevSpaceModel =
|
final prevSpaceModel = await _api.getSpaceModel(
|
||||||
await _api.getSpaceModel(event.spaceTemplate.uuid ?? '');
|
event.spaceTemplate.uuid ?? '', projectUuid);
|
||||||
|
|
||||||
final newSpaceModel = event.updatedSpaceTemplate;
|
final newSpaceModel = event.updatedSpaceTemplate;
|
||||||
String? spaceModelName;
|
String? spaceModelName;
|
||||||
@ -287,7 +293,7 @@ class CreateSpaceModelBloc
|
|||||||
subspaceModels: subspaceUpdates);
|
subspaceModels: subspaceUpdates);
|
||||||
|
|
||||||
final res = await _api.updateSpaceModel(
|
final res = await _api.updateSpaceModel(
|
||||||
spaceModelBody, prevSpaceModel?.uuid ?? '');
|
spaceModelBody, prevSpaceModel?.uuid ?? '', projectUuid);
|
||||||
|
|
||||||
if (res != null) {
|
if (res != null) {
|
||||||
emit(CreateSpaceModelLoaded(newSpaceModel));
|
emit(CreateSpaceModelLoaded(newSpaceModel));
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
|
import 'dart:developer';
|
||||||
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/common/bloc/project_manager.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_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';
|
||||||
@ -11,17 +14,23 @@ class SpaceModelBloc extends Bloc<SpaceModelEvent, SpaceModelState> {
|
|||||||
required this.api,
|
required this.api,
|
||||||
required List<SpaceTemplateModel> initialSpaceModels,
|
required List<SpaceTemplateModel> initialSpaceModels,
|
||||||
}) : super(SpaceModelLoaded(spaceModels: initialSpaceModels)) {
|
}) : super(SpaceModelLoaded(spaceModels: initialSpaceModels)) {
|
||||||
|
log('Initial Space Models in: ${initialSpaceModels.map((e) => e.toJson()).toList()}');
|
||||||
|
|
||||||
on<CreateSpaceModel>(_onCreateSpaceModel);
|
on<CreateSpaceModel>(_onCreateSpaceModel);
|
||||||
on<UpdateSpaceModel>(_onUpdateSpaceModel);
|
on<UpdateSpaceModel>(_onUpdateSpaceModel);
|
||||||
|
on<DeleteSpaceModel>(_onDeleteSpaceModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _onCreateSpaceModel(
|
Future<void> _onCreateSpaceModel(
|
||||||
CreateSpaceModel event, Emitter<SpaceModelState> emit) async {
|
CreateSpaceModel event, Emitter<SpaceModelState> emit) async {
|
||||||
final currentState = state;
|
final currentState = state;
|
||||||
|
|
||||||
if (currentState is SpaceModelLoaded) {
|
if (currentState is SpaceModelLoaded) {
|
||||||
try {
|
try {
|
||||||
final newSpaceModel =
|
final projectUuid = await ProjectManager.getProjectUUID() ?? '';
|
||||||
await api.getSpaceModel(event.newSpaceModel.uuid ?? '');
|
|
||||||
|
final newSpaceModel = await api.getSpaceModel(
|
||||||
|
event.newSpaceModel.uuid ?? '', projectUuid);
|
||||||
|
|
||||||
if (newSpaceModel != null) {
|
if (newSpaceModel != null) {
|
||||||
final updatedSpaceModels =
|
final updatedSpaceModels =
|
||||||
@ -40,8 +49,10 @@ class SpaceModelBloc extends Bloc<SpaceModelEvent, SpaceModelState> {
|
|||||||
final currentState = state;
|
final currentState = state;
|
||||||
if (currentState is SpaceModelLoaded) {
|
if (currentState is SpaceModelLoaded) {
|
||||||
try {
|
try {
|
||||||
|
final projectUuid = await ProjectManager.getProjectUUID() ?? '';
|
||||||
|
|
||||||
final newSpaceModel =
|
final newSpaceModel =
|
||||||
await api.getSpaceModel(event.spaceModelUuid ?? '');
|
await api.getSpaceModel(event.spaceModelUuid, projectUuid);
|
||||||
if (newSpaceModel != null) {
|
if (newSpaceModel != null) {
|
||||||
final updatedSpaceModels = currentState.spaceModels.map((model) {
|
final updatedSpaceModels = currentState.spaceModels.map((model) {
|
||||||
return model.uuid == event.spaceModelUuid ? newSpaceModel : model;
|
return model.uuid == event.spaceModelUuid ? newSpaceModel : model;
|
||||||
@ -53,4 +64,28 @@ class SpaceModelBloc extends Bloc<SpaceModelEvent, SpaceModelState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _onDeleteSpaceModel(
|
||||||
|
DeleteSpaceModel event, Emitter<SpaceModelState> emit) async {
|
||||||
|
final currentState = state;
|
||||||
|
|
||||||
|
if (currentState is SpaceModelLoaded) {
|
||||||
|
try {
|
||||||
|
final projectUuid = await ProjectManager.getProjectUUID() ?? '';
|
||||||
|
|
||||||
|
final deletedSuccessfully =
|
||||||
|
await api.deleteSpaceModel(event.spaceModelUuid, projectUuid);
|
||||||
|
|
||||||
|
if (deletedSuccessfully) {
|
||||||
|
final updatedSpaceModels = currentState.spaceModels
|
||||||
|
.where((model) => model.uuid != event.spaceModelUuid)
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
emit(SpaceModelLoaded(spaceModels: updatedSpaceModels));
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
emit(SpaceModelError(message: e.toString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,3 +34,12 @@ class UpdateSpaceModel extends SpaceModelEvent {
|
|||||||
@override
|
@override
|
||||||
List<Object?> get props => [spaceModelUuid];
|
List<Object?> get props => [spaceModelUuid];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class DeleteSpaceModel extends SpaceModelEvent {
|
||||||
|
final String spaceModelUuid;
|
||||||
|
|
||||||
|
DeleteSpaceModel({required this.spaceModelUuid});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [spaceModelUuid];
|
||||||
|
}
|
||||||
|
@ -90,7 +90,11 @@ class SpaceModelPage extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
child: Container(
|
child: Container(
|
||||||
margin: const EdgeInsets.all(8.0),
|
margin: const EdgeInsets.all(8.0),
|
||||||
child: SpaceModelCardWidget(model: model),
|
child: SpaceModelCardWidget(
|
||||||
|
model: model,
|
||||||
|
pageContext: context,
|
||||||
|
topActionsDisabled: false,
|
||||||
|
),
|
||||||
));
|
));
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -2,6 +2,8 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.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/all_spaces/bloc/space_management_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/bloc/space_management_event.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/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';
|
||||||
@ -50,7 +52,9 @@ class CreateSpaceModelDialog extends StatelessWidget {
|
|||||||
width: screenWidth * 0.3,
|
width: screenWidth * 0.3,
|
||||||
child: BlocProvider(
|
child: BlocProvider(
|
||||||
create: (_) {
|
create: (_) {
|
||||||
final bloc = CreateSpaceModelBloc(_spaceModelApi);
|
final bloc = CreateSpaceModelBloc(
|
||||||
|
_spaceModelApi,
|
||||||
|
);
|
||||||
if (spaceModel != null) {
|
if (spaceModel != null) {
|
||||||
bloc.add(UpdateSpaceTemplate(spaceModel!, otherSpaceModels));
|
bloc.add(UpdateSpaceTemplate(spaceModel!, otherSpaceModels));
|
||||||
} else {
|
} else {
|
||||||
@ -194,6 +198,12 @@ class CreateSpaceModelDialog extends StatelessWidget {
|
|||||||
.add(CreateSpaceModel(
|
.add(CreateSpaceModel(
|
||||||
newSpaceModel:
|
newSpaceModel:
|
||||||
newModel));
|
newModel));
|
||||||
|
pageContext!
|
||||||
|
.read<
|
||||||
|
SpaceManagementBloc>()
|
||||||
|
.add(
|
||||||
|
UpdateSpaceModelCache(
|
||||||
|
newModel));
|
||||||
}
|
}
|
||||||
Navigator.of(context)
|
Navigator.of(context)
|
||||||
.pop(); // Close the dialog
|
.pop(); // Close the dialog
|
||||||
@ -239,6 +249,11 @@ class CreateSpaceModelDialog extends StatelessWidget {
|
|||||||
spaceModelUuid:
|
spaceModelUuid:
|
||||||
newModel.uuid ??
|
newModel.uuid ??
|
||||||
''));
|
''));
|
||||||
|
pageContext!
|
||||||
|
.read<
|
||||||
|
SpaceManagementBloc>()
|
||||||
|
.add(UpdateSpaceModelCache(
|
||||||
|
newModel));
|
||||||
}
|
}
|
||||||
Navigator.of(context)
|
Navigator.of(context)
|
||||||
.pop();
|
.pop();
|
||||||
|
@ -0,0 +1,85 @@
|
|||||||
|
import 'package:flutter/material.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/utils/color_manager.dart';
|
||||||
|
|
||||||
|
class DeleteSpaceModelDialog extends StatelessWidget {
|
||||||
|
final VoidCallback onConfirmDelete;
|
||||||
|
|
||||||
|
const DeleteSpaceModelDialog({Key? key, required this.onConfirmDelete})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final screenWidth = MediaQuery.of(context).size.width;
|
||||||
|
|
||||||
|
return AlertDialog(
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(20),
|
||||||
|
),
|
||||||
|
backgroundColor: ColorsManager.whiteColors,
|
||||||
|
title: Center(
|
||||||
|
child: Text(
|
||||||
|
"Delete Space Model",
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.headlineLarge
|
||||||
|
?.copyWith(color: ColorsManager.blackColor),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
content: SizedBox(
|
||||||
|
width: screenWidth * 0.4,
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"Are you sure you want to delete?",
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: Theme.of(context).textTheme.headlineSmall,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 15),
|
||||||
|
Text(
|
||||||
|
"The existing sub-spaces, devices, and routines will remain associated with the spaces, but the connection will be removed.",
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.bodyMedium
|
||||||
|
?.copyWith(color: ColorsManager.lightGrayColor),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
width: 200,
|
||||||
|
child: CancelButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop(); // Close dialog
|
||||||
|
},
|
||||||
|
label: "Cancel",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 10),
|
||||||
|
SizedBox(
|
||||||
|
width: 200,
|
||||||
|
child: DefaultButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop(); // Close dialog
|
||||||
|
onConfirmDelete(); // Execute delete action
|
||||||
|
},
|
||||||
|
backgroundColor: ColorsManager.semiTransparentRed,
|
||||||
|
borderRadius: 10,
|
||||||
|
foregroundColor: ColorsManager.whiteColors,
|
||||||
|
child: const Text('Delete'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,13 +1,30 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
|
import 'package:flutter_svg/svg.dart';
|
||||||
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/bloc/space_management_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/bloc/space_management_event.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/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/dialog/delete_space_model_dialog.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/space_model/widgets/dynamic_product_widget.dart';
|
import 'package:syncrow_web/pages/spaces_management/space_model/widgets/dynamic_product_widget.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/space_model/widgets/dynamic_room_widget.dart';
|
import 'package:syncrow_web/pages/spaces_management/space_model/widgets/dynamic_room_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';
|
||||||
|
|
||||||
class SpaceModelCardWidget extends StatelessWidget {
|
class SpaceModelCardWidget extends StatelessWidget {
|
||||||
final SpaceTemplateModel model;
|
final SpaceTemplateModel model;
|
||||||
|
final BuildContext? pageContext;
|
||||||
|
final bool topActionsDisabled;
|
||||||
|
|
||||||
const SpaceModelCardWidget({Key? key, required this.model}) : super(key: key);
|
const SpaceModelCardWidget({
|
||||||
|
Key? key,
|
||||||
|
required this.model,
|
||||||
|
this.pageContext,
|
||||||
|
this.topActionsDisabled = true,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -34,7 +51,7 @@ class SpaceModelCardWidget extends StatelessWidget {
|
|||||||
return LayoutBuilder(
|
return LayoutBuilder(
|
||||||
builder: (context, constraints) {
|
builder: (context, constraints) {
|
||||||
bool showOnlyName = constraints.maxWidth < 250;
|
bool showOnlyName = constraints.maxWidth < 250;
|
||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
@ -51,14 +68,50 @@ class SpaceModelCardWidget extends StatelessWidget {
|
|||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Row(
|
||||||
model.modelName,
|
children: [
|
||||||
style: Theme.of(context).textTheme.headlineMedium?.copyWith(
|
Expanded(
|
||||||
color: Colors.black,
|
child: Text(
|
||||||
fontWeight: FontWeight.bold,
|
model.modelName,
|
||||||
|
style:
|
||||||
|
Theme.of(context).textTheme.headlineMedium?.copyWith(
|
||||||
|
color: Colors.black,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
),
|
),
|
||||||
maxLines: 1,
|
),
|
||||||
overflow: TextOverflow.ellipsis,
|
if (!topActionsDisabled)
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () => _showDeleteDialog(context),
|
||||||
|
child: Container(
|
||||||
|
width: 36, // Adjust size as needed
|
||||||
|
height: 36,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
shape: BoxShape.circle,
|
||||||
|
color: Colors.white,
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.black.withOpacity(0.1),
|
||||||
|
spreadRadius: 2,
|
||||||
|
blurRadius: 5,
|
||||||
|
offset: const Offset(0, 2),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: Center(
|
||||||
|
child: SvgPicture.asset(
|
||||||
|
Assets.deleteSpaceModel, // Your actual SVG path
|
||||||
|
width: 20,
|
||||||
|
height: 20,
|
||||||
|
colorFilter: const ColorFilter.mode(
|
||||||
|
Colors.grey, BlendMode.srcIn),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
if (!showOnlyName) ...[
|
if (!showOnlyName) ...[
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
@ -117,4 +170,26 @@ class SpaceModelCardWidget extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _showDeleteDialog(BuildContext context) {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
barrierDismissible: true,
|
||||||
|
builder: (BuildContext dialogContext) {
|
||||||
|
return DeleteSpaceModelDialog(
|
||||||
|
onConfirmDelete: () {
|
||||||
|
if (pageContext != null) {
|
||||||
|
pageContext!.read<SpaceModelBloc>().add(
|
||||||
|
DeleteSpaceModel(spaceModelUuid: model.uuid ?? ''),
|
||||||
|
);
|
||||||
|
|
||||||
|
pageContext!.read<SpaceManagementBloc>().add(
|
||||||
|
DeleteSpaceModelFromCache(model.uuid ?? ''),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,11 +15,11 @@ class CenterBodyWidget extends StatelessWidget {
|
|||||||
context.read<CenterBodyBloc>().add(CommunityStructureSelectedEvent());
|
context.read<CenterBodyBloc>().add(CommunityStructureSelectedEvent());
|
||||||
}
|
}
|
||||||
if (state is CommunityStructureState) {
|
if (state is CommunityStructureState) {
|
||||||
context.read<SpaceManagementBloc>().add(BlankStateEvent());
|
context.read<SpaceManagementBloc>().add(BlankStateEvent(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state is SpaceModelState) {
|
if (state is SpaceModelState) {
|
||||||
context.read<SpaceManagementBloc>().add(SpaceModelLoadEvent());
|
context.read<SpaceManagementBloc>().add(SpaceModelLoadEvent(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
|
@ -3,6 +3,7 @@ import 'package:dio/dio.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
|
import 'package:syncrow_web/pages/common/bloc/project_manager.dart';
|
||||||
import 'package:syncrow_web/pages/common/custom_dialog.dart';
|
import 'package:syncrow_web/pages/common/custom_dialog.dart';
|
||||||
import 'package:syncrow_web/pages/common/hour_picker_dialog.dart';
|
import 'package:syncrow_web/pages/common/hour_picker_dialog.dart';
|
||||||
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_event.dart';
|
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_event.dart';
|
||||||
@ -13,9 +14,14 @@ import 'package:syncrow_web/pages/visitor_password/model/schedule_model.dart';
|
|||||||
import 'package:syncrow_web/services/access_mang_api.dart';
|
import 'package:syncrow_web/services/access_mang_api.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/strings_manager.dart';
|
||||||
|
import 'package:syncrow_web/utils/constants/temp_const.dart';
|
||||||
|
import 'package:syncrow_web/utils/helpers/shared_preferences_helper.dart';
|
||||||
import 'package:syncrow_web/utils/snack_bar.dart';
|
import 'package:syncrow_web/utils/snack_bar.dart';
|
||||||
|
|
||||||
class VisitorPasswordBloc extends Bloc<VisitorPasswordEvent, VisitorPasswordState> {
|
class VisitorPasswordBloc
|
||||||
|
extends Bloc<VisitorPasswordEvent, VisitorPasswordState> {
|
||||||
|
|
||||||
VisitorPasswordBloc() : super(VisitorPasswordInitial()) {
|
VisitorPasswordBloc() : super(VisitorPasswordInitial()) {
|
||||||
on<SelectUsageFrequency>(selectUsageFrequency);
|
on<SelectUsageFrequency>(selectUsageFrequency);
|
||||||
on<FetchDevice>(_onFetchDevice);
|
on<FetchDevice>(_onFetchDevice);
|
||||||
@ -38,7 +44,8 @@ class VisitorPasswordBloc extends Bloc<VisitorPasswordEvent, VisitorPasswordStat
|
|||||||
final TextEditingController deviceNameController = TextEditingController();
|
final TextEditingController deviceNameController = TextEditingController();
|
||||||
final TextEditingController deviceIdController = TextEditingController();
|
final TextEditingController deviceIdController = TextEditingController();
|
||||||
final TextEditingController unitNameController = TextEditingController();
|
final TextEditingController unitNameController = TextEditingController();
|
||||||
final TextEditingController virtualAddressController = TextEditingController();
|
final TextEditingController virtualAddressController =
|
||||||
|
TextEditingController();
|
||||||
List<String> selectedDevices = [];
|
List<String> selectedDevices = [];
|
||||||
|
|
||||||
List<DeviceModel> data = [];
|
List<DeviceModel> data = [];
|
||||||
@ -64,12 +71,14 @@ class VisitorPasswordBloc extends Bloc<VisitorPasswordEvent, VisitorPasswordStat
|
|||||||
String startTimeAccess = 'Start Time';
|
String startTimeAccess = 'Start Time';
|
||||||
String endTimeAccess = 'End Time';
|
String endTimeAccess = 'End Time';
|
||||||
PasswordStatus? passwordStatus;
|
PasswordStatus? passwordStatus;
|
||||||
selectAccessType(SelectPasswordType event, Emitter<VisitorPasswordState> emit) {
|
selectAccessType(
|
||||||
|
SelectPasswordType event, Emitter<VisitorPasswordState> emit) {
|
||||||
accessTypeSelected = event.type;
|
accessTypeSelected = event.type;
|
||||||
emit(PasswordTypeSelected(event.type));
|
emit(PasswordTypeSelected(event.type));
|
||||||
}
|
}
|
||||||
|
|
||||||
selectUsageFrequency(SelectUsageFrequency event, Emitter<VisitorPasswordState> emit) {
|
selectUsageFrequency(
|
||||||
|
SelectUsageFrequency event, Emitter<VisitorPasswordState> emit) {
|
||||||
usageFrequencySelected = event.usageType;
|
usageFrequencySelected = event.usageType;
|
||||||
emit(UsageFrequencySelected(event.usageType));
|
emit(UsageFrequencySelected(event.usageType));
|
||||||
}
|
}
|
||||||
@ -116,10 +125,12 @@ class VisitorPasswordBloc extends Bloc<VisitorPasswordEvent, VisitorPasswordStat
|
|||||||
timePicked.minute,
|
timePicked.minute,
|
||||||
);
|
);
|
||||||
|
|
||||||
final selectedTimestamp = selectedDateTime.millisecondsSinceEpoch ~/ 1000;
|
final selectedTimestamp =
|
||||||
|
selectedDateTime.millisecondsSinceEpoch ~/ 1000;
|
||||||
|
|
||||||
if (event.isStart) {
|
if (event.isStart) {
|
||||||
if (expirationTimeTimeStamp != null && selectedTimestamp > expirationTimeTimeStamp!) {
|
if (expirationTimeTimeStamp != null &&
|
||||||
|
selectedTimestamp > expirationTimeTimeStamp!) {
|
||||||
CustomSnackBar.displaySnackBar(
|
CustomSnackBar.displaySnackBar(
|
||||||
'Effective Time cannot be later than Expiration Time.',
|
'Effective Time cannot be later than Expiration Time.',
|
||||||
);
|
);
|
||||||
@ -128,7 +139,8 @@ class VisitorPasswordBloc extends Bloc<VisitorPasswordEvent, VisitorPasswordStat
|
|||||||
effectiveTimeTimeStamp = selectedTimestamp;
|
effectiveTimeTimeStamp = selectedTimestamp;
|
||||||
startTimeAccess = selectedDateTime.toString().split('.').first;
|
startTimeAccess = selectedDateTime.toString().split('.').first;
|
||||||
} else {
|
} else {
|
||||||
if (effectiveTimeTimeStamp != null && selectedTimestamp < effectiveTimeTimeStamp!) {
|
if (effectiveTimeTimeStamp != null &&
|
||||||
|
selectedTimestamp < effectiveTimeTimeStamp!) {
|
||||||
CustomSnackBar.displaySnackBar(
|
CustomSnackBar.displaySnackBar(
|
||||||
'Expiration Time cannot be earlier than Effective Time.',
|
'Expiration Time cannot be earlier than Effective Time.',
|
||||||
);
|
);
|
||||||
@ -143,7 +155,8 @@ class VisitorPasswordBloc extends Bloc<VisitorPasswordEvent, VisitorPasswordStat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool toggleRepeat(ToggleRepeatEvent event, Emitter<VisitorPasswordState> emit) {
|
bool toggleRepeat(
|
||||||
|
ToggleRepeatEvent event, Emitter<VisitorPasswordState> emit) {
|
||||||
emit(LoadingInitialState());
|
emit(LoadingInitialState());
|
||||||
repeat = !repeat;
|
repeat = !repeat;
|
||||||
emit(IsRepeatState(repeat: repeat));
|
emit(IsRepeatState(repeat: repeat));
|
||||||
@ -175,10 +188,13 @@ class VisitorPasswordBloc extends Bloc<VisitorPasswordEvent, VisitorPasswordStat
|
|||||||
emit(ChangeTimeState());
|
emit(ChangeTimeState());
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _onFetchDevice(FetchDevice event, Emitter<VisitorPasswordState> emit) async {
|
Future<void> _onFetchDevice(
|
||||||
|
FetchDevice event, Emitter<VisitorPasswordState> emit) async {
|
||||||
try {
|
try {
|
||||||
emit(DeviceLoaded());
|
emit(DeviceLoaded());
|
||||||
data = await AccessMangApi().fetchDevices();
|
final projectUuid = await ProjectManager.getProjectUUID() ?? '';
|
||||||
|
|
||||||
|
data = await AccessMangApi().fetchDevices(projectUuid);
|
||||||
emit(TableLoaded(data));
|
emit(TableLoaded(data));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(FailedState(e.toString()));
|
emit(FailedState(e.toString()));
|
||||||
@ -186,8 +202,8 @@ class VisitorPasswordBloc extends Bloc<VisitorPasswordEvent, VisitorPasswordStat
|
|||||||
}
|
}
|
||||||
|
|
||||||
//online password
|
//online password
|
||||||
Future<void> postOnlineOneTimePassword(
|
Future<void> postOnlineOneTimePassword(OnlineOneTimePasswordEvent event,
|
||||||
OnlineOneTimePasswordEvent event, Emitter<VisitorPasswordState> emit) async {
|
Emitter<VisitorPasswordState> emit) async {
|
||||||
try {
|
try {
|
||||||
emit(LoadingInitialState());
|
emit(LoadingInitialState());
|
||||||
generate7DigitNumber();
|
generate7DigitNumber();
|
||||||
@ -211,7 +227,8 @@ class VisitorPasswordBloc extends Bloc<VisitorPasswordEvent, VisitorPasswordStat
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> postOnlineMultipleTimePassword(
|
Future<void> postOnlineMultipleTimePassword(
|
||||||
OnlineMultipleTimePasswordEvent event, Emitter<VisitorPasswordState> emit) async {
|
OnlineMultipleTimePasswordEvent event,
|
||||||
|
Emitter<VisitorPasswordState> emit) async {
|
||||||
try {
|
try {
|
||||||
emit(LoadingInitialState());
|
emit(LoadingInitialState());
|
||||||
|
|
||||||
@ -221,7 +238,8 @@ class VisitorPasswordBloc extends Bloc<VisitorPasswordEvent, VisitorPasswordStat
|
|||||||
if (repeat)
|
if (repeat)
|
||||||
Schedule(
|
Schedule(
|
||||||
effectiveTime: getTimeFromDateTimeString(effectiveTime),
|
effectiveTime: getTimeFromDateTimeString(effectiveTime),
|
||||||
invalidTime: getTimeFromDateTimeString(expirationTime).toString(),
|
invalidTime:
|
||||||
|
getTimeFromDateTimeString(expirationTime).toString(),
|
||||||
workingDay: selectedDays,
|
workingDay: selectedDays,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -244,13 +262,15 @@ class VisitorPasswordBloc extends Bloc<VisitorPasswordEvent, VisitorPasswordStat
|
|||||||
}
|
}
|
||||||
|
|
||||||
//offline password
|
//offline password
|
||||||
Future<void> postOfflineOneTimePassword(
|
Future<void> postOfflineOneTimePassword(OfflineOneTimePasswordEvent event,
|
||||||
OfflineOneTimePasswordEvent event, Emitter<VisitorPasswordState> emit) async {
|
Emitter<VisitorPasswordState> emit) async {
|
||||||
try {
|
try {
|
||||||
emit(LoadingInitialState());
|
emit(LoadingInitialState());
|
||||||
await generate7DigitNumber();
|
await generate7DigitNumber();
|
||||||
var res = await AccessMangApi().postOffLineOneTime(
|
var res = await AccessMangApi().postOffLineOneTime(
|
||||||
email: event.email, devicesUuid: selectedDevices, passwordName: event.passwordName);
|
email: event.email,
|
||||||
|
devicesUuid: selectedDevices,
|
||||||
|
passwordName: event.passwordName);
|
||||||
if (res['statusCode'] == 201) {
|
if (res['statusCode'] == 201) {
|
||||||
passwordStatus = PasswordStatus.fromJson(res['data']);
|
passwordStatus = PasswordStatus.fromJson(res['data']);
|
||||||
emit(SuccessState());
|
emit(SuccessState());
|
||||||
@ -264,7 +284,8 @@ class VisitorPasswordBloc extends Bloc<VisitorPasswordEvent, VisitorPasswordStat
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> postOfflineMultipleTimePassword(
|
Future<void> postOfflineMultipleTimePassword(
|
||||||
OfflineMultipleTimePasswordEvent event, Emitter<VisitorPasswordState> emit) async {
|
OfflineMultipleTimePasswordEvent event,
|
||||||
|
Emitter<VisitorPasswordState> emit) async {
|
||||||
try {
|
try {
|
||||||
emit(LoadingInitialState());
|
emit(LoadingInitialState());
|
||||||
await generate7DigitNumber();
|
await generate7DigitNumber();
|
||||||
@ -287,7 +308,8 @@ class VisitorPasswordBloc extends Bloc<VisitorPasswordEvent, VisitorPasswordStat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void selectDevice(SelectDeviceEvent event, Emitter<VisitorPasswordState> emit) {
|
void selectDevice(
|
||||||
|
SelectDeviceEvent event, Emitter<VisitorPasswordState> emit) {
|
||||||
if (selectedDeviceIds.contains(event.deviceId)) {
|
if (selectedDeviceIds.contains(event.deviceId)) {
|
||||||
selectedDeviceIds.remove(event.deviceId);
|
selectedDeviceIds.remove(event.deviceId);
|
||||||
} else {
|
} else {
|
||||||
@ -329,7 +351,8 @@ class VisitorPasswordBloc extends Bloc<VisitorPasswordEvent, VisitorPasswordStat
|
|||||||
add(UpdateFilteredDevicesEvent(filteredData));
|
add(UpdateFilteredDevicesEvent(filteredData));
|
||||||
}
|
}
|
||||||
|
|
||||||
Stream<VisitorPasswordState> mapEventToState(VisitorPasswordEvent event) async* {
|
Stream<VisitorPasswordState> mapEventToState(
|
||||||
|
VisitorPasswordEvent event) async* {
|
||||||
if (event is FetchDevice) {
|
if (event is FetchDevice) {
|
||||||
} else if (event is UpdateFilteredDevicesEvent) {
|
} else if (event is UpdateFilteredDevicesEvent) {
|
||||||
yield TableLoaded(event.filteredData);
|
yield TableLoaded(event.filteredData);
|
||||||
@ -378,16 +401,20 @@ class VisitorPasswordBloc extends Bloc<VisitorPasswordEvent, VisitorPasswordStat
|
|||||||
).millisecondsSinceEpoch ~/
|
).millisecondsSinceEpoch ~/
|
||||||
1000; // Divide by 1000 to remove milliseconds
|
1000; // Divide by 1000 to remove milliseconds
|
||||||
if (event.isEffective) {
|
if (event.isEffective) {
|
||||||
if (expirationTimeTimeStamp != null && selectedTimestamp > expirationTimeTimeStamp!) {
|
if (expirationTimeTimeStamp != null &&
|
||||||
accessPeriodValidate = "Effective Time cannot be later than Expiration Time.";
|
selectedTimestamp > expirationTimeTimeStamp!) {
|
||||||
|
accessPeriodValidate =
|
||||||
|
"Effective Time cannot be later than Expiration Time.";
|
||||||
} else {
|
} else {
|
||||||
accessPeriodValidate = '';
|
accessPeriodValidate = '';
|
||||||
effectiveTime = selectedDateTime.toString().split('.').first;
|
effectiveTime = selectedDateTime.toString().split('.').first;
|
||||||
effectiveTimeTimeStamp = selectedTimestamp;
|
effectiveTimeTimeStamp = selectedTimestamp;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (effectiveTimeTimeStamp != null && selectedTimestamp < effectiveTimeTimeStamp!) {
|
if (effectiveTimeTimeStamp != null &&
|
||||||
accessPeriodValidate = 'Expiration Time cannot be earlier than Effective Time.';
|
selectedTimestamp < effectiveTimeTimeStamp!) {
|
||||||
|
accessPeriodValidate =
|
||||||
|
'Expiration Time cannot be earlier than Effective Time.';
|
||||||
} else {
|
} else {
|
||||||
accessPeriodValidate = '';
|
accessPeriodValidate = '';
|
||||||
expirationTime = selectedDateTime.toString().split('.').first;
|
expirationTime = selectedDateTime.toString().split('.').first;
|
||||||
|
@ -23,6 +23,7 @@ class DeviceModel {
|
|||||||
dynamic timeZone;
|
dynamic timeZone;
|
||||||
dynamic updateTime;
|
dynamic updateTime;
|
||||||
dynamic uuid;
|
dynamic uuid;
|
||||||
|
dynamic spaceName;
|
||||||
|
|
||||||
DeviceModel({
|
DeviceModel({
|
||||||
required this.productUuid,
|
required this.productUuid,
|
||||||
@ -45,6 +46,7 @@ class DeviceModel {
|
|||||||
required this.timeZone,
|
required this.timeZone,
|
||||||
required this.updateTime,
|
required this.updateTime,
|
||||||
required this.uuid,
|
required this.uuid,
|
||||||
|
required this.spaceName,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Deserialize from JSON
|
// Deserialize from JSON
|
||||||
@ -53,7 +55,8 @@ class DeviceModel {
|
|||||||
DeviceType type = devicesTypesMap[json['productType']] ?? DeviceType.Other;
|
DeviceType type = devicesTypesMap[json['productType']] ?? DeviceType.Other;
|
||||||
if (type == DeviceType.LightBulb) {
|
if (type == DeviceType.LightBulb) {
|
||||||
tempIcon = Assets.lightBulb;
|
tempIcon = Assets.lightBulb;
|
||||||
} else if (type == DeviceType.CeilingSensor || type == DeviceType.WallSensor) {
|
} else if (type == DeviceType.CeilingSensor ||
|
||||||
|
type == DeviceType.WallSensor) {
|
||||||
tempIcon = Assets.sensors;
|
tempIcon = Assets.sensors;
|
||||||
} else if (type == DeviceType.AC) {
|
} else if (type == DeviceType.AC) {
|
||||||
tempIcon = Assets.ac;
|
tempIcon = Assets.ac;
|
||||||
@ -102,6 +105,7 @@ class DeviceModel {
|
|||||||
timeZone: json['timeZone'],
|
timeZone: json['timeZone'],
|
||||||
updateTime: json['updateTime'],
|
updateTime: json['updateTime'],
|
||||||
uuid: json['uuid'],
|
uuid: json['uuid'],
|
||||||
|
spaceName: json['spaceName'],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,6 +132,7 @@ class DeviceModel {
|
|||||||
'timeZone': timeZone,
|
'timeZone': timeZone,
|
||||||
'updateTime': updateTime,
|
'updateTime': updateTime,
|
||||||
'uuid': uuid,
|
'uuid': uuid,
|
||||||
|
'spaceName': spaceName
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
import 'package:syncrow_web/pages/common/access_device_table.dart';
|
import 'package:syncrow_web/pages/common/access_device_table.dart';
|
||||||
|
import 'package:syncrow_web/pages/common/bloc/project_manager.dart';
|
||||||
import 'package:syncrow_web/pages/common/text_field/custom_web_textfield.dart';
|
import 'package:syncrow_web/pages/common/text_field/custom_web_textfield.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/visitor_password/bloc/visitor_password_bloc.dart';
|
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_bloc.dart';
|
||||||
@ -19,7 +20,8 @@ class AddDeviceDialog extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
Size size = MediaQuery.of(context).size;
|
Size size = MediaQuery.of(context).size;
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (context) => VisitorPasswordBloc()..add(FetchDevice()),
|
create: (context) =>
|
||||||
|
VisitorPasswordBloc()..add(FetchDevice()),
|
||||||
child: BlocBuilder<VisitorPasswordBloc, VisitorPasswordState>(
|
child: BlocBuilder<VisitorPasswordBloc, VisitorPasswordState>(
|
||||||
builder: (BuildContext context, VisitorPasswordState state) {
|
builder: (BuildContext context, VisitorPasswordState state) {
|
||||||
final visitorBloc = BlocProvider.of<VisitorPasswordBloc>(context);
|
final visitorBloc = BlocProvider.of<VisitorPasswordBloc>(context);
|
||||||
@ -35,10 +37,10 @@ class AddDeviceDialog extends StatelessWidget {
|
|||||||
backgroundColor: Colors.white,
|
backgroundColor: Colors.white,
|
||||||
title: Text(
|
title: Text(
|
||||||
'Add Accessible Device',
|
'Add Accessible Device',
|
||||||
style: Theme.of(context)
|
style: Theme.of(context).textTheme.headlineLarge!.copyWith(
|
||||||
.textTheme
|
fontWeight: FontWeight.w400,
|
||||||
.headlineLarge!
|
fontSize: 24,
|
||||||
.copyWith(fontWeight: FontWeight.w400, fontSize: 24, color: Colors.black),
|
color: Colors.black),
|
||||||
),
|
),
|
||||||
content: SizedBox(
|
content: SizedBox(
|
||||||
height: MediaQuery.of(context).size.height / 1.7,
|
height: MediaQuery.of(context).size.height / 1.7,
|
||||||
@ -68,10 +70,13 @@ class AddDeviceDialog extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
'Only online accessible devices can be added',
|
'Only online accessible devices can be added',
|
||||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
style: Theme.of(context)
|
||||||
fontWeight: FontWeight.w400,
|
.textTheme
|
||||||
fontSize: 12,
|
.bodySmall!
|
||||||
color: ColorsManager.grayColor),
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
fontSize: 12,
|
||||||
|
color: ColorsManager.grayColor),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)),
|
)),
|
||||||
@ -152,7 +157,8 @@ class AddDeviceDialog extends StatelessWidget {
|
|||||||
visitorBloc.deviceNameController.clear();
|
visitorBloc.deviceNameController.clear();
|
||||||
visitorBloc.deviceIdController.clear();
|
visitorBloc.deviceIdController.clear();
|
||||||
visitorBloc.unitNameController.clear();
|
visitorBloc.unitNameController.clear();
|
||||||
visitorBloc.add(FetchDevice()); // Reset to original list
|
visitorBloc.add(
|
||||||
|
FetchDevice()); // Reset to original list
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -172,7 +178,8 @@ class AddDeviceDialog extends StatelessWidget {
|
|||||||
selectAll: (p0) {
|
selectAll: (p0) {
|
||||||
visitorBloc.selectedDeviceIds.clear();
|
visitorBloc.selectedDeviceIds.clear();
|
||||||
for (var item in state.data) {
|
for (var item in state.data) {
|
||||||
visitorBloc.add(SelectDeviceEvent(item.uuid));
|
visitorBloc
|
||||||
|
.add(SelectDeviceEvent(item.uuid));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onRowSelected: (index, isSelected, row) {
|
onRowSelected: (index, isSelected, row) {
|
||||||
@ -193,7 +200,7 @@ class AddDeviceDialog extends StatelessWidget {
|
|||||||
item.name.toString(),
|
item.name.toString(),
|
||||||
item.uuid.toString(),
|
item.uuid.toString(),
|
||||||
item.productType.toString(),
|
item.productType.toString(),
|
||||||
'',
|
item.spaceName.toString(),
|
||||||
item.online.value.toString(),
|
item.online.value.toString(),
|
||||||
];
|
];
|
||||||
}).toList(),
|
}).toList(),
|
||||||
|
@ -2,6 +2,7 @@ import 'package:flutter/cupertino.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
|
import 'package:syncrow_web/pages/common/bloc/project_manager.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/common/date_time_widget.dart';
|
import 'package:syncrow_web/pages/common/date_time_widget.dart';
|
||||||
import 'package:syncrow_web/pages/common/text_field/custom_web_textfield.dart';
|
import 'package:syncrow_web/pages/common/text_field/custom_web_textfield.dart';
|
||||||
|
@ -6,10 +6,10 @@ import 'package:syncrow_web/services/api/http_service.dart';
|
|||||||
import 'package:syncrow_web/utils/constants/api_const.dart';
|
import 'package:syncrow_web/utils/constants/api_const.dart';
|
||||||
|
|
||||||
class AccessMangApi {
|
class AccessMangApi {
|
||||||
Future<List<PasswordModel>> fetchVisitorPassword() async {
|
Future<List<PasswordModel>> fetchVisitorPassword(String projectId) async {
|
||||||
try {
|
try {
|
||||||
final response = await HTTPService().get(
|
final response = await HTTPService().get(
|
||||||
path: ApiEndpoints.visitorPassword,
|
path: ApiEndpoints.visitorPassword.replaceAll('{projectId}', projectId),
|
||||||
showServerMessage: true,
|
showServerMessage: true,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
List<dynamic> jsonData = json;
|
List<dynamic> jsonData = json;
|
||||||
@ -25,10 +25,10 @@ class AccessMangApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future fetchDevices() async {
|
Future fetchDevices(String projectId) async {
|
||||||
try {
|
try {
|
||||||
final response = await HTTPService().get(
|
final response = await HTTPService().get(
|
||||||
path: ApiEndpoints.getDevices,
|
path: ApiEndpoints.getDevices.replaceAll('{projectId}', projectId),
|
||||||
showServerMessage: true,
|
showServerMessage: true,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
List<dynamic> jsonData = json;
|
List<dynamic> jsonData = json;
|
||||||
@ -86,7 +86,8 @@ class AccessMangApi {
|
|||||||
"invalidTime": invalidTime,
|
"invalidTime": invalidTime,
|
||||||
};
|
};
|
||||||
if (scheduleList != null) {
|
if (scheduleList != null) {
|
||||||
body["scheduleList"] = scheduleList.map((schedule) => schedule.toJson()).toList();
|
body["scheduleList"] =
|
||||||
|
scheduleList.map((schedule) => schedule.toJson()).toList();
|
||||||
}
|
}
|
||||||
final response = await HTTPService().post(
|
final response = await HTTPService().post(
|
||||||
path: ApiEndpoints.sendOnlineMultipleTime,
|
path: ApiEndpoints.sendOnlineMultipleTime,
|
||||||
@ -105,7 +106,11 @@ class AccessMangApi {
|
|||||||
{String? email, String? passwordName, List<String>? devicesUuid}) async {
|
{String? email, String? passwordName, List<String>? devicesUuid}) async {
|
||||||
final response = await HTTPService().post(
|
final response = await HTTPService().post(
|
||||||
path: ApiEndpoints.sendOffLineOneTime,
|
path: ApiEndpoints.sendOffLineOneTime,
|
||||||
body: jsonEncode({"email": email, "passwordName": passwordName, "devicesUuid": devicesUuid}),
|
body: jsonEncode({
|
||||||
|
"email": email,
|
||||||
|
"passwordName": passwordName,
|
||||||
|
"devicesUuid": devicesUuid
|
||||||
|
}),
|
||||||
showServerMessage: true,
|
showServerMessage: true,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
return json;
|
return json;
|
||||||
|
@ -12,15 +12,15 @@ import 'package:syncrow_web/utils/constants/api_const.dart';
|
|||||||
import 'package:syncrow_web/utils/constants/temp_const.dart';
|
import 'package:syncrow_web/utils/constants/temp_const.dart';
|
||||||
|
|
||||||
class DevicesManagementApi {
|
class DevicesManagementApi {
|
||||||
Future<List<AllDevicesModel>> fetchDevices(String communityId, String spaceId) async {
|
Future<List<AllDevicesModel>> fetchDevices(String communityId, String spaceId, String projectId) async {
|
||||||
try {
|
try {
|
||||||
final response = await HTTPService().get(
|
final response = await HTTPService().get(
|
||||||
path: communityId.isNotEmpty && spaceId.isNotEmpty
|
path: communityId.isNotEmpty && spaceId.isNotEmpty
|
||||||
? ApiEndpoints.getSpaceDevices
|
? ApiEndpoints.getSpaceDevices
|
||||||
.replaceAll('{spaceUuid}', spaceId)
|
.replaceAll('{spaceUuid}', spaceId)
|
||||||
.replaceAll('{communityUuid}', communityId)
|
.replaceAll('{communityUuid}', communityId)
|
||||||
.replaceAll('{projectId}', TempConst.projectId)
|
.replaceAll('{projectId}', projectId)
|
||||||
: ApiEndpoints.getAllDevices,
|
: ApiEndpoints.getAllDevices.replaceAll('{projectId}', projectId),
|
||||||
showServerMessage: true,
|
showServerMessage: true,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
List<dynamic> jsonData =
|
List<dynamic> jsonData =
|
||||||
|
@ -12,7 +12,8 @@ class SceneApi {
|
|||||||
static final HTTPService _httpService = HTTPService();
|
static final HTTPService _httpService = HTTPService();
|
||||||
|
|
||||||
// //create scene
|
// //create scene
|
||||||
static Future<Map<String, dynamic>> createScene(CreateSceneModel createSceneModel) async {
|
static Future<Map<String, dynamic>> createScene(
|
||||||
|
CreateSceneModel createSceneModel) async {
|
||||||
try {
|
try {
|
||||||
debugPrint('create scene model: ${createSceneModel.toMap()}');
|
debugPrint('create scene model: ${createSceneModel.toMap()}');
|
||||||
final response = await _httpService.post(
|
final response = await _httpService.post(
|
||||||
@ -69,14 +70,15 @@ class SceneApi {
|
|||||||
|
|
||||||
//get scenes by community id and space id
|
//get scenes by community id and space id
|
||||||
|
|
||||||
static Future<List<ScenesModel>> getScenes(String spaceId, String communityId,
|
static Future<List<ScenesModel>> getScenes(
|
||||||
|
String spaceId, String communityId, String projectId,
|
||||||
{showInDevice = false}) async {
|
{showInDevice = false}) async {
|
||||||
try {
|
try {
|
||||||
final response = await _httpService.get(
|
final response = await _httpService.get(
|
||||||
path: ApiEndpoints.getUnitScenes
|
path: ApiEndpoints.getUnitScenes
|
||||||
.replaceAll('{spaceUuid}', spaceId)
|
.replaceAll('{spaceUuid}', spaceId)
|
||||||
.replaceAll('{communityUuid}', communityId)
|
.replaceAll('{communityUuid}', communityId)
|
||||||
.replaceAll('{projectId}', TempConst.projectId),
|
.replaceAll('{projectId}', projectId),
|
||||||
queryParameters: {'showInHomePage': showInDevice},
|
queryParameters: {'showInHomePage': showInDevice},
|
||||||
showServerMessage: false,
|
showServerMessage: false,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
@ -100,7 +102,8 @@ class SceneApi {
|
|||||||
static Future<List<ScenesModel>> getAutomation(String spaceId) async {
|
static Future<List<ScenesModel>> getAutomation(String spaceId) async {
|
||||||
try {
|
try {
|
||||||
final response = await _httpService.get(
|
final response = await _httpService.get(
|
||||||
path: ApiEndpoints.getSpaceAutomation.replaceAll('{spaceUuid}', spaceId),
|
path:
|
||||||
|
ApiEndpoints.getSpaceAutomation.replaceAll('{spaceUuid}', spaceId),
|
||||||
showServerMessage: false,
|
showServerMessage: false,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
List<ScenesModel> scenes = [];
|
List<ScenesModel> scenes = [];
|
||||||
@ -130,10 +133,12 @@ class SceneApi {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
//automation details
|
//automation details
|
||||||
static Future<RoutineDetailsModel> getAutomationDetails(String automationId) async {
|
static Future<RoutineDetailsModel> getAutomationDetails(
|
||||||
|
String automationId) async {
|
||||||
try {
|
try {
|
||||||
final response = await _httpService.get(
|
final response = await _httpService.get(
|
||||||
path: ApiEndpoints.getAutomationDetails.replaceAll('{automationId}', automationId),
|
path: ApiEndpoints.getAutomationDetails
|
||||||
|
.replaceAll('{automationId}', automationId),
|
||||||
showServerMessage: false,
|
showServerMessage: false,
|
||||||
expectedResponseModel: (json) => RoutineDetailsModel.fromMap(json),
|
expectedResponseModel: (json) => RoutineDetailsModel.fromMap(json),
|
||||||
);
|
);
|
||||||
@ -148,7 +153,8 @@ class SceneApi {
|
|||||||
try {
|
try {
|
||||||
final response = await _httpService.put(
|
final response = await _httpService.put(
|
||||||
path: ApiEndpoints.updateScene.replaceAll('{sceneId}', sceneId),
|
path: ApiEndpoints.updateScene.replaceAll('{sceneId}', sceneId),
|
||||||
body: createSceneModel.toJson(sceneId.isNotEmpty == true ? sceneId : null),
|
body: createSceneModel
|
||||||
|
.toJson(sceneId.isNotEmpty == true ? sceneId : null),
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
return json;
|
return json;
|
||||||
},
|
},
|
||||||
@ -160,11 +166,14 @@ class SceneApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//update automation
|
//update automation
|
||||||
static updateAutomation(CreateAutomationModel createAutomationModel, String automationId) async {
|
static updateAutomation(
|
||||||
|
CreateAutomationModel createAutomationModel, String automationId) async {
|
||||||
try {
|
try {
|
||||||
final response = await _httpService.put(
|
final response = await _httpService.put(
|
||||||
path: ApiEndpoints.updateAutomation.replaceAll('{automationId}', automationId),
|
path: ApiEndpoints.updateAutomation
|
||||||
body: createAutomationModel.toJson(automationId.isNotEmpty == true ? automationId : null),
|
.replaceAll('{automationId}', automationId),
|
||||||
|
body: createAutomationModel
|
||||||
|
.toJson(automationId.isNotEmpty == true ? automationId : null),
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
return json;
|
return json;
|
||||||
},
|
},
|
||||||
@ -181,7 +190,8 @@ class SceneApi {
|
|||||||
final response = await _httpService.get(
|
final response = await _httpService.get(
|
||||||
path: ApiEndpoints.getScene.replaceAll('{sceneId}', sceneId),
|
path: ApiEndpoints.getScene.replaceAll('{sceneId}', sceneId),
|
||||||
showServerMessage: false,
|
showServerMessage: false,
|
||||||
expectedResponseModel: (json) => RoutineDetailsModel.fromMap(json['data']),
|
expectedResponseModel: (json) =>
|
||||||
|
RoutineDetailsModel.fromMap(json['data']),
|
||||||
);
|
);
|
||||||
return response;
|
return response;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -190,7 +200,8 @@ class SceneApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//delete Scene
|
//delete Scene
|
||||||
static Future<bool> deleteScene({required String unitUuid, required String sceneId}) async {
|
static Future<bool> deleteScene(
|
||||||
|
{required String unitUuid, required String sceneId}) async {
|
||||||
try {
|
try {
|
||||||
final response = await _httpService.delete(
|
final response = await _httpService.delete(
|
||||||
path: ApiEndpoints.deleteScene
|
path: ApiEndpoints.deleteScene
|
||||||
|
@ -13,7 +13,8 @@ import 'package:syncrow_web/utils/constants/temp_const.dart';
|
|||||||
|
|
||||||
class CommunitySpaceManagementApi {
|
class CommunitySpaceManagementApi {
|
||||||
// Community Management APIs
|
// Community Management APIs
|
||||||
Future<List<CommunityModel>> fetchCommunities({int page = 1}) async {
|
Future<List<CommunityModel>> fetchCommunities(String projectId,
|
||||||
|
{int page = 1}) async {
|
||||||
try {
|
try {
|
||||||
List<CommunityModel> allCommunities = [];
|
List<CommunityModel> allCommunities = [];
|
||||||
bool hasNext = true;
|
bool hasNext = true;
|
||||||
@ -21,7 +22,7 @@ class CommunitySpaceManagementApi {
|
|||||||
while (hasNext) {
|
while (hasNext) {
|
||||||
await HTTPService().get(
|
await HTTPService().get(
|
||||||
path: ApiEndpoints.getCommunityList
|
path: ApiEndpoints.getCommunityList
|
||||||
.replaceAll('{projectId}', TempConst.projectId),
|
.replaceAll('{projectId}', projectId),
|
||||||
queryParameters: {'page': page},
|
queryParameters: {'page': page},
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
try {
|
try {
|
||||||
@ -65,11 +66,10 @@ class CommunitySpaceManagementApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<CommunityModel?> createCommunity(
|
Future<CommunityModel?> createCommunity(
|
||||||
String name, String description) async {
|
String name, String description, String projectId) async {
|
||||||
try {
|
try {
|
||||||
final response = await HTTPService().post(
|
final response = await HTTPService().post(
|
||||||
path: ApiEndpoints.createCommunity
|
path: ApiEndpoints.createCommunity.replaceAll('{projectId}', projectId),
|
||||||
.replaceAll('{projectId}', TempConst.projectId),
|
|
||||||
body: {
|
body: {
|
||||||
'name': name,
|
'name': name,
|
||||||
'description': description,
|
'description': description,
|
||||||
@ -85,12 +85,13 @@ class CommunitySpaceManagementApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> updateCommunity(String communityId, String name) async {
|
Future<bool> updateCommunity(
|
||||||
|
String communityId, String name, String projectId) async {
|
||||||
try {
|
try {
|
||||||
final response = await HTTPService().put(
|
final response = await HTTPService().put(
|
||||||
path: ApiEndpoints.updateCommunity
|
path: ApiEndpoints.updateCommunity
|
||||||
.replaceAll('{communityId}', communityId)
|
.replaceAll('{communityId}', communityId)
|
||||||
.replaceAll('{projectId}', TempConst.projectId),
|
.replaceAll('{projectId}', projectId),
|
||||||
body: {
|
body: {
|
||||||
'name': name,
|
'name': name,
|
||||||
},
|
},
|
||||||
@ -105,12 +106,12 @@ class CommunitySpaceManagementApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> deleteCommunity(String communityId) async {
|
Future<bool> deleteCommunity(String communityId, String projectId) async {
|
||||||
try {
|
try {
|
||||||
final response = await HTTPService().delete(
|
final response = await HTTPService().delete(
|
||||||
path: ApiEndpoints.deleteCommunity
|
path: ApiEndpoints.deleteCommunity
|
||||||
.replaceAll('{communityId}', communityId)
|
.replaceAll('{communityId}', communityId)
|
||||||
.replaceAll('{projectId}', TempConst.projectId),
|
.replaceAll('{projectId}', projectId),
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
return json['success'] ?? false;
|
return json['success'] ?? false;
|
||||||
},
|
},
|
||||||
@ -122,12 +123,13 @@ class CommunitySpaceManagementApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<SpacesResponse> fetchSpaces(String communityId) async {
|
Future<SpacesResponse> fetchSpaces(
|
||||||
|
String communityId, String projectId) async {
|
||||||
try {
|
try {
|
||||||
final response = await HTTPService().get(
|
final response = await HTTPService().get(
|
||||||
path: ApiEndpoints.listSpaces
|
path: ApiEndpoints.listSpaces
|
||||||
.replaceAll('{communityId}', communityId)
|
.replaceAll('{communityId}', communityId)
|
||||||
.replaceAll('{projectId}', TempConst.projectId),
|
.replaceAll('{projectId}', projectId),
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
return SpacesResponse.fromJson(json);
|
return SpacesResponse.fromJson(json);
|
||||||
},
|
},
|
||||||
@ -148,13 +150,14 @@ class CommunitySpaceManagementApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<SpaceModel?> getSpace(String communityId, String spaceId) async {
|
Future<SpaceModel?> getSpace(
|
||||||
|
String communityId, String spaceId, String projectId) async {
|
||||||
try {
|
try {
|
||||||
final response = await HTTPService().get(
|
final response = await HTTPService().get(
|
||||||
path: ApiEndpoints.getSpace
|
path: ApiEndpoints.getSpace
|
||||||
.replaceAll('{communityId}', communityId)
|
.replaceAll('{communityId}', communityId)
|
||||||
.replaceAll('{spaceId}', spaceId)
|
.replaceAll('{spaceId}', spaceId)
|
||||||
.replaceAll('{projectId}', TempConst.projectId),
|
.replaceAll('{projectId}', projectId),
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
return SpaceModel.fromJson(json['data']);
|
return SpaceModel.fromJson(json['data']);
|
||||||
},
|
},
|
||||||
@ -176,7 +179,8 @@ class CommunitySpaceManagementApi {
|
|||||||
String? spaceModelUuid,
|
String? spaceModelUuid,
|
||||||
String? icon,
|
String? icon,
|
||||||
List<CreateTagBodyModel>? tags,
|
List<CreateTagBodyModel>? tags,
|
||||||
List<CreateSubspaceModel>? subspaces}) async {
|
List<CreateSubspaceModel>? subspaces,
|
||||||
|
required String projectId}) async {
|
||||||
try {
|
try {
|
||||||
final body = {
|
final body = {
|
||||||
'spaceName': name,
|
'spaceName': name,
|
||||||
@ -199,7 +203,7 @@ class CommunitySpaceManagementApi {
|
|||||||
final response = await HTTPService().post(
|
final response = await HTTPService().post(
|
||||||
path: ApiEndpoints.createSpace
|
path: ApiEndpoints.createSpace
|
||||||
.replaceAll('{communityId}', communityId)
|
.replaceAll('{communityId}', communityId)
|
||||||
.replaceAll('{projectId}', TempConst.projectId),
|
.replaceAll('{projectId}', projectId),
|
||||||
body: body,
|
body: body,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
return SpaceModel.fromJson(json['data']);
|
return SpaceModel.fromJson(json['data']);
|
||||||
@ -212,18 +216,18 @@ class CommunitySpaceManagementApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> updateSpace({
|
Future<bool> updateSpace(
|
||||||
required String communityId,
|
{required String communityId,
|
||||||
required spaceId,
|
required spaceId,
|
||||||
required String name,
|
required String name,
|
||||||
String? parentId,
|
String? parentId,
|
||||||
String? icon,
|
String? icon,
|
||||||
String? direction,
|
String? direction,
|
||||||
bool isPrivate = false,
|
bool isPrivate = false,
|
||||||
required Offset position,
|
required Offset position,
|
||||||
List<TagModelUpdate>? tags,
|
List<TagModelUpdate>? tags,
|
||||||
List<UpdateSubspaceTemplateModel>? subspaces,
|
List<UpdateSubspaceTemplateModel>? subspaces,
|
||||||
}) async {
|
required String projectId}) async {
|
||||||
try {
|
try {
|
||||||
final body = {
|
final body = {
|
||||||
'spaceName': name,
|
'spaceName': name,
|
||||||
@ -243,7 +247,7 @@ class CommunitySpaceManagementApi {
|
|||||||
path: ApiEndpoints.updateSpace
|
path: ApiEndpoints.updateSpace
|
||||||
.replaceAll('{communityId}', communityId)
|
.replaceAll('{communityId}', communityId)
|
||||||
.replaceAll('{spaceId}', spaceId)
|
.replaceAll('{spaceId}', spaceId)
|
||||||
.replaceAll('{projectId}', TempConst.projectId),
|
.replaceAll('{projectId}', projectId),
|
||||||
body: body,
|
body: body,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
return json['success'] ?? false;
|
return json['success'] ?? false;
|
||||||
@ -256,13 +260,14 @@ class CommunitySpaceManagementApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> deleteSpace(String communityId, String spaceId) async {
|
Future<bool> deleteSpace(
|
||||||
|
String communityId, String spaceId, String projectId) async {
|
||||||
try {
|
try {
|
||||||
final response = await HTTPService().delete(
|
final response = await HTTPService().delete(
|
||||||
path: ApiEndpoints.deleteSpace
|
path: ApiEndpoints.deleteSpace
|
||||||
.replaceAll('{communityId}', communityId)
|
.replaceAll('{communityId}', communityId)
|
||||||
.replaceAll('{spaceId}', spaceId)
|
.replaceAll('{spaceId}', spaceId)
|
||||||
.replaceAll('{projectId}', TempConst.projectId),
|
.replaceAll('{projectId}', projectId),
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
return json['success'] ?? false;
|
return json['success'] ?? false;
|
||||||
},
|
},
|
||||||
@ -274,12 +279,13 @@ class CommunitySpaceManagementApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<SpaceModel>> getSpaceHierarchy(String communityId) async {
|
Future<List<SpaceModel>> getSpaceHierarchy(
|
||||||
|
String communityId, String projectId) async {
|
||||||
try {
|
try {
|
||||||
final response = await HTTPService().get(
|
final response = await HTTPService().get(
|
||||||
path: ApiEndpoints.getSpaceHierarchy
|
path: ApiEndpoints.getSpaceHierarchy
|
||||||
.replaceAll('{communityId}', communityId)
|
.replaceAll('{communityId}', communityId)
|
||||||
.replaceAll('{projectId}', TempConst.projectId),
|
.replaceAll('{projectId}', projectId),
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
final spaceModels = (json['data'] as List)
|
final spaceModels = (json['data'] as List)
|
||||||
.map((spaceJson) => SpaceModel.fromJson(spaceJson))
|
.map((spaceJson) => SpaceModel.fromJson(spaceJson))
|
||||||
|
@ -5,10 +5,10 @@ import 'package:syncrow_web/utils/constants/api_const.dart';
|
|||||||
import 'package:syncrow_web/utils/constants/temp_const.dart';
|
import 'package:syncrow_web/utils/constants/temp_const.dart';
|
||||||
|
|
||||||
class SpaceModelManagementApi {
|
class SpaceModelManagementApi {
|
||||||
Future<List<SpaceTemplateModel>> listSpaceModels({int page = 1}) async {
|
Future<List<SpaceTemplateModel>> listSpaceModels(
|
||||||
|
{required String projectId, int page = 1}) async {
|
||||||
final response = await HTTPService().get(
|
final response = await HTTPService().get(
|
||||||
path: ApiEndpoints.listSpaceModels
|
path: ApiEndpoints.listSpaceModels.replaceAll('{projectId}', projectId),
|
||||||
.replaceAll('{projectId}', TempConst.projectId),
|
|
||||||
queryParameters: {'page': page},
|
queryParameters: {'page': page},
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
List<dynamic> jsonData = json['data'];
|
List<dynamic> jsonData = json['data'];
|
||||||
@ -21,10 +21,9 @@ class SpaceModelManagementApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<SpaceTemplateModel?> createSpaceModel(
|
Future<SpaceTemplateModel?> createSpaceModel(
|
||||||
CreateSpaceTemplateBodyModel spaceModel) async {
|
CreateSpaceTemplateBodyModel spaceModel, String projectId) async {
|
||||||
final response = await HTTPService().post(
|
final response = await HTTPService().post(
|
||||||
path: ApiEndpoints.createSpaceModel
|
path: ApiEndpoints.createSpaceModel.replaceAll('{projectId}', projectId),
|
||||||
.replaceAll('{projectId}', TempConst.projectId),
|
|
||||||
showServerMessage: true,
|
showServerMessage: true,
|
||||||
body: spaceModel.toJson(),
|
body: spaceModel.toJson(),
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
@ -34,12 +33,12 @@ class SpaceModelManagementApi {
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<String?> updateSpaceModel(CreateSpaceTemplateBodyModel spaceModel,
|
||||||
Future<String?> updateSpaceModel(
|
String spaceModelUuid, String projectId) async {
|
||||||
CreateSpaceTemplateBodyModel spaceModel, String spaceModelUuid) async {
|
|
||||||
final response = await HTTPService().put(
|
final response = await HTTPService().put(
|
||||||
path: ApiEndpoints.updateSpaceModel
|
path: ApiEndpoints.updateSpaceModel
|
||||||
.replaceAll('{projectId}', TempConst.projectId).replaceAll('{spaceModelUuid}', spaceModelUuid),
|
.replaceAll('{projectId}', projectId)
|
||||||
|
.replaceAll('{spaceModelUuid}', spaceModelUuid),
|
||||||
body: spaceModel.toJson(),
|
body: spaceModel.toJson(),
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
return json['message'];
|
return json['message'];
|
||||||
@ -48,10 +47,11 @@ class SpaceModelManagementApi {
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<SpaceTemplateModel?> getSpaceModel(String spaceModelUuid) async {
|
Future<SpaceTemplateModel?> getSpaceModel(
|
||||||
|
String spaceModelUuid, String projectId) async {
|
||||||
final response = await HTTPService().get(
|
final response = await HTTPService().get(
|
||||||
path: ApiEndpoints.getSpaceModel
|
path: ApiEndpoints.getSpaceModel
|
||||||
.replaceAll('{projectId}', TempConst.projectId)
|
.replaceAll('{projectId}', projectId)
|
||||||
.replaceAll('{spaceModelUuid}', spaceModelUuid),
|
.replaceAll('{spaceModelUuid}', spaceModelUuid),
|
||||||
showServerMessage: true,
|
showServerMessage: true,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
@ -60,4 +60,17 @@ class SpaceModelManagementApi {
|
|||||||
);
|
);
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<bool> deleteSpaceModel(String spaceModelUuid, String projectId) async {
|
||||||
|
final response = await HTTPService().delete(
|
||||||
|
path: ApiEndpoints.getSpaceModel
|
||||||
|
.replaceAll('{projectId}', projectId)
|
||||||
|
.replaceAll('{spaceModelUuid}', spaceModelUuid),
|
||||||
|
showServerMessage: true,
|
||||||
|
expectedResponseModel: (json) {
|
||||||
|
return json['success'] ?? false;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,10 +11,10 @@ import 'package:syncrow_web/utils/constants/api_const.dart';
|
|||||||
class UserPermissionApi {
|
class UserPermissionApi {
|
||||||
static final HTTPService _httpService = HTTPService();
|
static final HTTPService _httpService = HTTPService();
|
||||||
|
|
||||||
Future<List<RolesUserModel>> fetchUsers() async {
|
Future<List<RolesUserModel>> fetchUsers(String projectId) async {
|
||||||
try {
|
try {
|
||||||
final response = await _httpService.get(
|
final response = await _httpService.get(
|
||||||
path: ApiEndpoints.getUsers,
|
path: ApiEndpoints.getUsers.replaceAll('{projectId}', projectId),
|
||||||
showServerMessage: true,
|
showServerMessage: true,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
debugPrint('fetchUsers Response: $json');
|
debugPrint('fetchUsers Response: $json');
|
||||||
@ -34,8 +34,9 @@ class UserPermissionApi {
|
|||||||
path: ApiEndpoints.roleTypes,
|
path: ApiEndpoints.roleTypes,
|
||||||
showServerMessage: true,
|
showServerMessage: true,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
final List<RoleTypeModel> fetchedRoles =
|
final List<RoleTypeModel> fetchedRoles = (json['data'] as List)
|
||||||
(json['data'] as List).map((item) => RoleTypeModel.fromJson(item)).toList();
|
.map((item) => RoleTypeModel.fromJson(item))
|
||||||
|
.toList();
|
||||||
return fetchedRoles;
|
return fetchedRoles;
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@ -47,7 +48,9 @@ class UserPermissionApi {
|
|||||||
path: ApiEndpoints.permission.replaceAll("roleUuid", roleUuid),
|
path: ApiEndpoints.permission.replaceAll("roleUuid", roleUuid),
|
||||||
showServerMessage: true,
|
showServerMessage: true,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
return (json as List).map((data) => PermissionOption.fromJson(data)).toList();
|
return (json as List)
|
||||||
|
.map((data) => PermissionOption.fromJson(data))
|
||||||
|
.toList();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
return response ?? [];
|
return response ?? [];
|
||||||
@ -61,6 +64,7 @@ class UserPermissionApi {
|
|||||||
String? phoneNumber,
|
String? phoneNumber,
|
||||||
String? roleUuid,
|
String? roleUuid,
|
||||||
List<String>? spaceUuids,
|
List<String>? spaceUuids,
|
||||||
|
required String projectUuid,
|
||||||
}) async {
|
}) async {
|
||||||
try {
|
try {
|
||||||
final body = <String, dynamic>{
|
final body = <String, dynamic>{
|
||||||
@ -70,7 +74,7 @@ class UserPermissionApi {
|
|||||||
"jobTitle": jobTitle != '' ? jobTitle : null,
|
"jobTitle": jobTitle != '' ? jobTitle : null,
|
||||||
"phoneNumber": phoneNumber != '' ? phoneNumber : null,
|
"phoneNumber": phoneNumber != '' ? phoneNumber : null,
|
||||||
"roleUuid": roleUuid,
|
"roleUuid": roleUuid,
|
||||||
"projectUuid": "0e62577c-06fa-41b9-8a92-99a21fbaf51c",
|
"projectUuid": projectUuid,
|
||||||
"spaceUuids": spaceUuids,
|
"spaceUuids": spaceUuids,
|
||||||
};
|
};
|
||||||
final response = await _httpService.post(
|
final response = await _httpService.post(
|
||||||
@ -121,9 +125,11 @@ class UserPermissionApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<EditUserModel?> fetchUserById(userUuid) async {
|
Future<EditUserModel?> fetchUserById(userUuid, String projectId) async {
|
||||||
final response = await _httpService.get(
|
final response = await _httpService.get(
|
||||||
path: ApiEndpoints.getUserById.replaceAll("{userUuid}", userUuid),
|
path: ApiEndpoints.getUserById
|
||||||
|
.replaceAll("{userUuid}", userUuid)
|
||||||
|
.replaceAll("{projectId}", projectId),
|
||||||
showServerMessage: true,
|
showServerMessage: true,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
EditUserModel res = EditUserModel.fromJson(json['data']);
|
EditUserModel res = EditUserModel.fromJson(json['data']);
|
||||||
@ -141,6 +147,7 @@ class UserPermissionApi {
|
|||||||
String? phoneNumber,
|
String? phoneNumber,
|
||||||
String? roleUuid,
|
String? roleUuid,
|
||||||
List<String>? spaceUuids,
|
List<String>? spaceUuids,
|
||||||
|
required String projectUuid,
|
||||||
}) async {
|
}) async {
|
||||||
try {
|
try {
|
||||||
final body = <String, dynamic>{
|
final body = <String, dynamic>{
|
||||||
@ -149,7 +156,7 @@ class UserPermissionApi {
|
|||||||
"jobTitle": jobTitle != '' ? jobTitle : " ",
|
"jobTitle": jobTitle != '' ? jobTitle : " ",
|
||||||
"phoneNumber": phoneNumber != '' ? phoneNumber : " ",
|
"phoneNumber": phoneNumber != '' ? phoneNumber : " ",
|
||||||
"roleUuid": roleUuid,
|
"roleUuid": roleUuid,
|
||||||
"projectUuid": "0e62577c-06fa-41b9-8a92-99a21fbaf51c",
|
"projectUuid": projectUuid,
|
||||||
"spaceUuids": spaceUuids,
|
"spaceUuids": spaceUuids,
|
||||||
};
|
};
|
||||||
final response = await _httpService.put(
|
final response = await _httpService.put(
|
||||||
@ -186,15 +193,16 @@ class UserPermissionApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> changeUserStatusById(userUuid, status) async {
|
Future<bool> changeUserStatusById(userUuid, status, String projectUuid) async {
|
||||||
try {
|
try {
|
||||||
Map<String, dynamic> bodya = {
|
Map<String, dynamic> bodya = {
|
||||||
"disable": status,
|
"disable": status,
|
||||||
"projectUuid": "0e62577c-06fa-41b9-8a92-99a21fbaf51c"
|
"projectUuid": projectUuid
|
||||||
};
|
};
|
||||||
|
|
||||||
final response = await _httpService.put(
|
final response = await _httpService.put(
|
||||||
path: ApiEndpoints.changeUserStatus.replaceAll("{invitedUserUuid}", userUuid),
|
path: ApiEndpoints.changeUserStatus
|
||||||
|
.replaceAll("{invitedUserUuid}", userUuid),
|
||||||
body: bodya,
|
body: bodya,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
return json['success'];
|
return json['success'];
|
||||||
|
@ -71,4 +71,5 @@ abstract class ColorsManager {
|
|||||||
static const Color lightGrayBorderColor = Color(0xB2D5D5D5);
|
static const Color lightGrayBorderColor = Color(0xB2D5D5D5);
|
||||||
//background: #F8F8F8;
|
//background: #F8F8F8;
|
||||||
static const Color vividBlue = Color(0xFF023DFE);
|
static const Color vividBlue = Color(0xFF023DFE);
|
||||||
|
static const Color semiTransparentRed = Color(0x99FF0000);
|
||||||
}
|
}
|
||||||
|
@ -9,8 +9,8 @@ abstract class ApiEndpoints {
|
|||||||
static const String sendOtp = '/authentication/user/send-otp';
|
static const String sendOtp = '/authentication/user/send-otp';
|
||||||
static const String verifyOtp = '/authentication/user/verify-otp';
|
static const String verifyOtp = '/authentication/user/verify-otp';
|
||||||
static const String getRegion = '/region';
|
static const String getRegion = '/region';
|
||||||
static const String visitorPassword = '/visitor-password';
|
static const String visitorPassword = '/projects/{projectId}/visitor-password';
|
||||||
static const String getDevices = '/visitor-password/devices';
|
static const String getDevices = '/projects/{projectId}/visitor-password/devices';
|
||||||
|
|
||||||
static const String sendOnlineOneTime = '/visitor-password/temporary-password/online/one-time';
|
static const String sendOnlineOneTime = '/visitor-password/temporary-password/online/one-time';
|
||||||
static const String sendOnlineMultipleTime =
|
static const String sendOnlineMultipleTime =
|
||||||
@ -25,7 +25,7 @@ abstract class ApiEndpoints {
|
|||||||
|
|
||||||
////// Devices Management ////////////////
|
////// Devices Management ////////////////
|
||||||
|
|
||||||
static const String getAllDevices = '/device';
|
static const String getAllDevices = '/projects/{projectId}/devices';
|
||||||
static const String getSpaceDevices =
|
static const String getSpaceDevices =
|
||||||
'/projects/{projectId}/communities/{communityUuid}/spaces/{spaceUuid}/devices';
|
'/projects/{projectId}/communities/{communityUuid}/spaces/{spaceUuid}/devices';
|
||||||
static const String getDeviceStatus = '/device/{uuid}/functions/status';
|
static const String getDeviceStatus = '/device/{uuid}/functions/status';
|
||||||
@ -95,8 +95,8 @@ abstract class ApiEndpoints {
|
|||||||
static const String inviteUser = '/invite-user';
|
static const String inviteUser = '/invite-user';
|
||||||
|
|
||||||
static const String checkEmail = '/invite-user/check-email';
|
static const String checkEmail = '/invite-user/check-email';
|
||||||
static const String getUsers = '/projects/${projectUuid}/user';
|
static const String getUsers = '/projects/{projectId}/user';
|
||||||
static const String getUserById = '/projects/${projectUuid}/user/{userUuid}';
|
static const String getUserById = '/projects/{projectId}/user/{userUuid}';
|
||||||
static const String editUser = '/invite-user/{inviteUserUuid}';
|
static const String editUser = '/invite-user/{inviteUserUuid}';
|
||||||
static const String deleteUser = '/invite-user/{inviteUserUuid}';
|
static const String deleteUser = '/invite-user/{inviteUserUuid}';
|
||||||
static const String changeUserStatus = '/invite-user/{invitedUserUuid}/disable';
|
static const String changeUserStatus = '/invite-user/{invitedUserUuid}/disable';
|
||||||
|
@ -258,6 +258,7 @@ class Assets {
|
|||||||
static const String doorSensor = 'assets/icons/door_sensor.svg';
|
static const String doorSensor = 'assets/icons/door_sensor.svg';
|
||||||
|
|
||||||
static const String delete = 'assets/icons/delete.svg';
|
static const String delete = 'assets/icons/delete.svg';
|
||||||
|
static const String deleteSpaceModel = 'assets/icons/delete_space_model.svg';
|
||||||
static const String edit = 'assets/icons/edit.svg';
|
static const String edit = 'assets/icons/edit.svg';
|
||||||
static const String editSpace = 'assets/icons/edit_space.svg';
|
static const String editSpace = 'assets/icons/edit_space.svg';
|
||||||
//assets/icons/routine/tab_to_run.svg
|
//assets/icons/routine/tab_to_run.svg
|
||||||
|
@ -40,4 +40,5 @@ class StringsManager {
|
|||||||
static const String firstLaunch = "firstLaunch";
|
static const String firstLaunch = "firstLaunch";
|
||||||
static const String deleteScene = 'Delete Scene';
|
static const String deleteScene = 'Delete Scene';
|
||||||
static const String deleteAutomation = 'Delete Automation';
|
static const String deleteAutomation = 'Delete Automation';
|
||||||
|
static const String projectKey = 'selected_project_uuid';
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:syncrow_web/pages/auth/bloc/auth_bloc.dart';
|
import 'package:syncrow_web/pages/auth/bloc/auth_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/auth/model/user_model.dart';
|
import 'package:syncrow_web/pages/auth/model/user_model.dart';
|
||||||
|
import 'package:syncrow_web/pages/common/bloc/project_manager.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/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';
|
||||||
@ -218,7 +220,7 @@ class _UserDropdownMenuState extends State<UserDropdownMenu> {
|
|||||||
),
|
),
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
AuthBloc.logout();
|
AuthBloc.logout(context);
|
||||||
context.go(RoutesConst.auth);
|
context.go(RoutesConst.auth);
|
||||||
},
|
},
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
|
Reference in New Issue
Block a user