diff --git a/assets/icons/scenesPlayIcon.svg b/assets/icons/scenesPlayIcon.svg
new file mode 100644
index 00000000..6417b0e6
--- /dev/null
+++ b/assets/icons/scenesPlayIcon.svg
@@ -0,0 +1,17 @@
+
diff --git a/assets/icons/scenesPlayIconCheck.svg b/assets/icons/scenesPlayIconCheck.svg
new file mode 100644
index 00000000..9e81869a
--- /dev/null
+++ b/assets/icons/scenesPlayIconCheck.svg
@@ -0,0 +1,30 @@
+
diff --git a/assets/icons/spaseLocationIcon.svg b/assets/icons/spaseLocationIcon.svg
new file mode 100644
index 00000000..2c3f0ad9
--- /dev/null
+++ b/assets/icons/spaseLocationIcon.svg
@@ -0,0 +1,4 @@
+
diff --git a/lib/main.dart b/lib/main.dart
index f2f640e4..8eb6ce38 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -8,6 +8,7 @@ import 'package:syncrow_web/firebase_options_prod.dart';
import 'package:syncrow_web/pages/auth/bloc/auth_bloc.dart';
import 'package:syncrow_web/pages/home/bloc/home_bloc.dart';
import 'package:syncrow_web/pages/home/bloc/home_event.dart';
+import 'package:syncrow_web/pages/routines/bloc/create_routine_bloc/create_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';
@@ -33,7 +34,6 @@ Future main() async {
}
class MyApp extends StatelessWidget {
-
MyApp({super.key});
final GoRouter _router = GoRouter(
@@ -55,6 +55,9 @@ class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MultiBlocProvider(
providers: [
+ BlocProvider(
+ create: (context) => CreateRoutineBloc(),
+ ),
BlocProvider(
create: (context) => HomeBloc()..add(const FetchUserInfo())),
BlocProvider(
diff --git a/lib/main_dev.dart b/lib/main_dev.dart
index 9d00ebf7..a42d5d07 100644
--- a/lib/main_dev.dart
+++ b/lib/main_dev.dart
@@ -8,6 +8,7 @@ import 'package:syncrow_web/firebase_options_dev.dart';
import 'package:syncrow_web/pages/auth/bloc/auth_bloc.dart';
import 'package:syncrow_web/pages/home/bloc/home_bloc.dart';
import 'package:syncrow_web/pages/home/bloc/home_event.dart';
+import 'package:syncrow_web/pages/routines/bloc/create_routine_bloc/create_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';
@@ -55,6 +56,9 @@ class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MultiBlocProvider(
providers: [
+ BlocProvider(
+ create: (context) => CreateRoutineBloc(),
+ ),
BlocProvider(
create: (context) => HomeBloc()..add(const FetchUserInfo())),
BlocProvider(
diff --git a/lib/pages/device_managment/all_devices/bloc/device_mgmt_bloc/device_managment_bloc.dart b/lib/pages/device_managment/all_devices/bloc/device_mgmt_bloc/device_managment_bloc.dart
index 7ed3a377..05e82f1f 100644
--- a/lib/pages/device_managment/all_devices/bloc/device_mgmt_bloc/device_managment_bloc.dart
+++ b/lib/pages/device_managment/all_devices/bloc/device_mgmt_bloc/device_managment_bloc.dart
@@ -43,8 +43,7 @@ class DeviceManagementBloc
final projectUuid = await ProjectManager.getProjectUUID() ?? '';
if (spaceBloc.state.selectedCommunities.isEmpty) {
- devices = await DevicesManagementApi()
- .fetchDevices('', '', projectUuid );
+ devices = await DevicesManagementApi().fetchDevices('', '', projectUuid);
} else {
for (var community in spaceBloc.state.selectedCommunities) {
List spacesList =
diff --git a/lib/pages/device_managment/all_devices/models/factory_reset_model.dart b/lib/pages/device_managment/all_devices/models/factory_reset_model.dart
index aec14d16..56c6c90b 100644
--- a/lib/pages/device_managment/all_devices/models/factory_reset_model.dart
+++ b/lib/pages/device_managment/all_devices/models/factory_reset_model.dart
@@ -2,14 +2,17 @@ import 'package:flutter/foundation.dart';
class FactoryResetModel {
final List devicesUuid;
+ final String operationType;
FactoryResetModel({
required this.devicesUuid,
+ this.operationType = "RESET",
});
factory FactoryResetModel.fromJson(Map json) {
return FactoryResetModel(
devicesUuid: List.from(json['devicesUuid']),
+ operationType: "RESET",
);
}
diff --git a/lib/pages/device_managment/all_devices/view/device_managment_page.dart b/lib/pages/device_managment/all_devices/view/device_managment_page.dart
index 45af9751..f41b5a4a 100644
--- a/lib/pages/device_managment/all_devices/view/device_managment_page.dart
+++ b/lib/pages/device_managment/all_devices/view/device_managment_page.dart
@@ -3,6 +3,8 @@ import 'package:flutter_bloc/flutter_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/shared/navigate_home_grid_view.dart';
+import 'package:syncrow_web/pages/routines/bloc/create_routine_bloc/create_routine_bloc.dart';
+import 'package:syncrow_web/pages/routines/bloc/create_routine_bloc/create_routine_event.dart';
import 'package:syncrow_web/pages/routines/bloc/routine_bloc/routine_bloc.dart';
import 'package:syncrow_web/pages/routines/view/create_new_routine_view.dart';
import 'package:syncrow_web/pages/routines/view/routines_view.dart';
@@ -39,10 +41,15 @@ class DeviceManagementPage extends StatelessWidget with HelperResponsiveLayout {
backgroundColor: null,
),
onPressed: () {
+ BlocProvider.of(context)
+ .add(const ResetSelectedEvent());
+
context
.read()
.add(const TriggerSwitchTabsEvent(isRoutineTab: false));
- context.read().add(FetchDevices(context));
+ context
+ .read()
+ .add(FetchDevices(context));
},
child: Text(
'Devices',
@@ -60,6 +67,9 @@ class DeviceManagementPage extends StatelessWidget with HelperResponsiveLayout {
backgroundColor: null,
),
onPressed: () {
+ BlocProvider.of(context)
+ .add(const ResetSelectedEvent());
+
context
.read()
.add(const TriggerSwitchTabsEvent(isRoutineTab: true));
diff --git a/lib/pages/device_managment/all_devices/widgets/device_search_filters.dart b/lib/pages/device_managment/all_devices/widgets/device_search_filters.dart
index 650c0d21..1928768b 100644
--- a/lib/pages/device_managment/all_devices/widgets/device_search_filters.dart
+++ b/lib/pages/device_managment/all_devices/widgets/device_search_filters.dart
@@ -12,77 +12,95 @@ class DeviceSearchFilters extends StatefulWidget {
State createState() => _DeviceSearchFiltersState();
}
-class _DeviceSearchFiltersState extends State with HelperResponsiveLayout {
- final TextEditingController communityController = TextEditingController();
- final TextEditingController unitNameController = TextEditingController();
- final TextEditingController productNameController = TextEditingController();
+class _DeviceSearchFiltersState extends State
+ with HelperResponsiveLayout {
+ late final TextEditingController _unitNameController;
+ late final TextEditingController _productNameController;
+
+ @override
+ void initState() {
+ _unitNameController = TextEditingController();
+ _productNameController = TextEditingController();
+ super.initState();
+ }
+
+ @override
+ void dispose() {
+ _unitNameController.dispose();
+ _productNameController.dispose();
+ super.dispose();
+ }
+
+ List get _widgets => [
+ _buildSearchField(
+ "Space Name",
+ _unitNameController,
+ 200,
+ ),
+ _buildSearchField(
+ "Device Name / Product Name",
+ _productNameController,
+ 300,
+ ),
+ _buildSearchResetButtons(),
+ ];
@override
Widget build(BuildContext context) {
- return isExtraLargeScreenSize(context)
- ? Row(
- children: [
- _buildSearchField("Community", communityController, 200),
- const SizedBox(width: 20),
- _buildSearchField("Space Name", unitNameController, 200),
- const SizedBox(width: 20),
- _buildSearchField("Device Name / Product Name", productNameController, 300),
- const SizedBox(width: 20),
- _buildSearchResetButtons(),
- ],
- )
- : Wrap(
- spacing: 20,
- runSpacing: 10,
- children: [
- _buildSearchField(
- "Community",
- communityController,
- 200,
- ),
- _buildSearchField("Space Name", unitNameController, 200),
- _buildSearchField(
- "Device Name / Product Name",
- productNameController,
- 300,
- ),
- _buildSearchResetButtons(),
- ],
- );
+ if (isExtraLargeScreenSize(context)) {
+ return Row(
+ children: _widgets.map(
+ (e) {
+ return Padding(
+ padding: const EdgeInsets.symmetric(vertical: 10),
+ child: e,
+ );
+ },
+ ).toList(),
+ );
+ }
+
+ return Wrap(
+ spacing: 20,
+ runSpacing: 10,
+ children: _widgets,
+ );
}
- Widget _buildSearchField(String title, TextEditingController controller, double width) {
- return Container(
- child: StatefulTextField(
- title: title,
- width: width,
- elevation: 2,
- controller: controller,
- onSubmitted: () {
- context.read().add(SearchDevices(
- productName: productNameController.text,
- unitName: unitNameController.text,
- community: communityController.text,
- searchField: true));
- },
- onChanged: (p0) {},
- ),
+ Widget _buildSearchField(
+ String title,
+ TextEditingController controller,
+ double width,
+ ) {
+ return StatefulTextField(
+ title: title,
+ width: width,
+ elevation: 2,
+ controller: controller,
+ onSubmitted: () {
+ final searchDevicesEvent = SearchDevices(
+ productName: _productNameController.text,
+ unitName: _unitNameController.text,
+ searchField: true,
+ );
+ context.read().add(searchDevicesEvent);
+ },
+ onChanged: (p0) {},
);
}
Widget _buildSearchResetButtons() {
return SearchResetButtons(
- onSearch: () {
- context.read().add(SearchDevices(
- community: communityController.text,
- unitName: unitNameController.text,
- productName: productNameController.text,
- searchField: true));
- },
+ onSearch: () => context.read().add(
+ SearchDevices(
+ unitName: _unitNameController.text,
+ productName: _productNameController.text,
+ searchField: true,
+ ),
+ ),
onReset: () {
- communityController.clear();
- unitNameController.clear();
- productNameController.clear();
+ _unitNameController.clear();
+ _productNameController.clear();
context.read()
..add(ResetFilters())
..add(FetchDevices(context));
diff --git a/lib/pages/routines/bloc/automation_scene_trigger_bloc/automation_status_update.dart b/lib/pages/routines/bloc/automation_scene_trigger_bloc/automation_status_update.dart
new file mode 100644
index 00000000..c664c2c4
--- /dev/null
+++ b/lib/pages/routines/bloc/automation_scene_trigger_bloc/automation_status_update.dart
@@ -0,0 +1,39 @@
+
+import 'dart:convert';
+
+class AutomationStatusUpdate {
+ final String spaceUuid;
+ final bool isEnable;
+
+ AutomationStatusUpdate({
+ required this.spaceUuid,
+ required this.isEnable,
+ });
+
+ factory AutomationStatusUpdate.fromRawJson(String str) =>
+ AutomationStatusUpdate.fromJson(json.decode(str));
+
+ String toRawJson() => json.encode(toJson());
+
+ factory AutomationStatusUpdate.fromJson(Map json) =>
+ AutomationStatusUpdate(
+ spaceUuid: json["spaceUuid"],
+ isEnable: json["isEnable"],
+ );
+
+ Map toJson() => {
+ "spaceUuid": spaceUuid,
+ "isEnable": isEnable,
+ };
+
+ factory AutomationStatusUpdate.fromMap(Map map) =>
+ AutomationStatusUpdate(
+ spaceUuid: map["spaceUuid"],
+ isEnable: map["isEnable"],
+ );
+
+ Map toMap() => {
+ "spaceUuid": spaceUuid,
+ "isEnable": isEnable,
+ };
+}
diff --git a/lib/pages/routines/bloc/create_routine_bloc/create_routine_bloc.dart b/lib/pages/routines/bloc/create_routine_bloc/create_routine_bloc.dart
new file mode 100644
index 00000000..5a8e5590
--- /dev/null
+++ b/lib/pages/routines/bloc/create_routine_bloc/create_routine_bloc.dart
@@ -0,0 +1,51 @@
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:syncrow_web/pages/common/bloc/project_manager.dart';
+import 'package:syncrow_web/pages/routines/bloc/create_routine_bloc/create_routine_event.dart';
+import 'package:syncrow_web/pages/routines/bloc/create_routine_bloc/create_routine_state.dart';
+import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart';
+import 'package:syncrow_web/services/space_mana_api.dart';
+
+class CreateRoutineBloc extends Bloc {
+ CreateRoutineBloc() : super(const CreateRoutineInitial()) {
+ on(_fetchSpaceOnlyWithDevices);
+ on(saveSpaceIdCommunityId);
+ on(resetSelected);
+ }
+
+ String selectedSpaceId = '';
+ String selectedCommunityId = '';
+
+ List spacesOnlyWithDevices = [];
+
+ Future _fetchSpaceOnlyWithDevices(
+ SpaceOnlyWithDevicesEvent event, Emitter emit) async {
+ emit(const SpaceWithDeviceLoadingState());
+
+ try {
+ final projectUuid = await ProjectManager.getProjectUUID() ?? '';
+
+ spacesOnlyWithDevices = await CommunitySpaceManagementApi()
+ .getSpaceOnlyWithDevices(
+ communityId: event.communityID, projectId: projectUuid);
+
+ emit(SpaceWithDeviceLoadedState(spacesOnlyWithDevices));
+ } catch (e) {
+ emit(SpaceTreeErrorState('Error loading communities and spaces: $e'));
+ }
+ }
+
+ saveSpaceIdCommunityId(
+ SaveCommunityIdAndSpaceIdEvent event, Emitter emit) {
+ emit(const SpaceWithDeviceLoadingState());
+ selectedSpaceId = event.spaceID!;
+ selectedCommunityId = event.communityID!;
+ emit(const SelectedState());
+ }
+
+ resetSelected(ResetSelectedEvent event, Emitter emit) {
+ emit(const SpaceWithDeviceLoadingState());
+ selectedSpaceId = '';
+ selectedCommunityId = '';
+ emit(const ResetSelectedState());
+ }
+}
diff --git a/lib/pages/routines/bloc/create_routine_bloc/create_routine_event.dart b/lib/pages/routines/bloc/create_routine_bloc/create_routine_event.dart
new file mode 100644
index 00000000..24e620c0
--- /dev/null
+++ b/lib/pages/routines/bloc/create_routine_bloc/create_routine_event.dart
@@ -0,0 +1,43 @@
+import 'package:equatable/equatable.dart';
+import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart';
+
+abstract class CreateRoutineEvent extends Equatable {
+ const CreateRoutineEvent();
+
+ @override
+ List