mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-15 17:47:53 +00:00
update scene debug
This commit is contained in:
@ -94,7 +94,7 @@ class DeviceManagementPage extends StatelessWidget with HelperResponsiveLayout {
|
|||||||
return const RoutinesView();
|
return const RoutinesView();
|
||||||
}
|
}
|
||||||
if (state is ShowCreateRoutineState && state.showCreateRoutine) {
|
if (state is ShowCreateRoutineState && state.showCreateRoutine) {
|
||||||
return const CreateNewRoutineView();
|
return CreateNewRoutineView();
|
||||||
}
|
}
|
||||||
|
|
||||||
return BlocBuilder<DeviceManagementBloc, DeviceManagementState>(
|
return BlocBuilder<DeviceManagementBloc, DeviceManagementState>(
|
||||||
|
@ -13,6 +13,7 @@ import 'package:syncrow_web/pages/routiens/models/routine_model.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/navigation_service.dart';
|
||||||
import 'package:uuid/uuid.dart';
|
import 'package:uuid/uuid.dart';
|
||||||
|
|
||||||
part 'routine_event.dart';
|
part 'routine_event.dart';
|
||||||
@ -44,14 +45,15 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
on<FetchDevicesInRoutine>(_fetchDevices);
|
on<FetchDevicesInRoutine>(_fetchDevices);
|
||||||
on<UpdateScene>(_onUpdateScene);
|
on<UpdateScene>(_onUpdateScene);
|
||||||
on<UpdateAutomation>(_onUpdateAutomation);
|
on<UpdateAutomation>(_onUpdateAutomation);
|
||||||
|
on<SetAutomationActionExecutor>(_onSetAutomationActionExecutor);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onAddToIfContainer(AddToIfContainer event, Emitter<RoutineState> emit) {
|
void _onAddToIfContainer(AddToIfContainer event, Emitter<RoutineState> emit) {
|
||||||
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;
|
||||||
@ -60,18 +62,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;
|
||||||
@ -82,22 +87,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);
|
||||||
@ -107,13 +116,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));
|
||||||
@ -122,11 +133,13 @@ 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));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final scenes = await SceneApi.getScenesByUnitId(event.unitId, event.communityId);
|
final scenes =
|
||||||
|
await SceneApi.getScenesByUnitId(event.unitId, event.communityId);
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
scenes: scenes,
|
scenes: scenes,
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
@ -141,7 +154,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -169,14 +183,16 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,7 +206,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)) {
|
||||||
@ -257,7 +274,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']) {
|
||||||
emit(_resetState());
|
Navigator.of(NavigationService.navigatorKey.currentContext!).pop();
|
||||||
|
add(ResetRoutineState());
|
||||||
add(const LoadScenes(spaceId, communityId));
|
add(const LoadScenes(spaceId, communityId));
|
||||||
add(const LoadAutomation(spaceId));
|
add(const LoadAutomation(spaceId));
|
||||||
} else {
|
} else {
|
||||||
@ -274,7 +292,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(
|
||||||
@ -282,7 +301,21 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
));
|
));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (_isFirstActionDelay(state.thenItems)) {
|
||||||
|
emit(state.copyWith(
|
||||||
|
errorMessage: 'Cannot have delay as the first action',
|
||||||
|
isLoading: false,
|
||||||
|
));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_isLastActionDelay(state.thenItems)) {
|
||||||
|
emit(state.copyWith(
|
||||||
|
errorMessage: 'Cannot have delay as the last action',
|
||||||
|
isLoading: false,
|
||||||
|
));
|
||||||
|
return;
|
||||||
|
}
|
||||||
emit(state.copyWith(isLoading: true));
|
emit(state.copyWith(isLoading: true));
|
||||||
|
|
||||||
final conditions = state.ifItems.expand((item) {
|
final conditions = state.ifItems.expand((item) {
|
||||||
@ -358,7 +391,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']) {
|
||||||
emit(_resetState());
|
Navigator.of(NavigationService.navigatorKey.currentContext!).pop();
|
||||||
|
add(ResetRoutineState());
|
||||||
add(const LoadAutomation(spaceId));
|
add(const LoadAutomation(spaceId));
|
||||||
add(const LoadScenes(spaceId, communityId));
|
add(const LoadScenes(spaceId, communityId));
|
||||||
} else {
|
} else {
|
||||||
@ -375,17 +409,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);
|
||||||
@ -396,7 +434,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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -408,16 +447,21 @@ 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(routineName: event.name));
|
emit(state.copyWith(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,
|
||||||
@ -450,7 +494,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;
|
||||||
@ -486,8 +531,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),
|
||||||
};
|
};
|
||||||
@ -530,16 +578,26 @@ 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,
|
||||||
isTabToRun: event.isTabToRun,
|
isTabToRun: true,
|
||||||
isUpdate: true,
|
isUpdate: true,
|
||||||
sceneId: event.sceneId,
|
sceneId: event.sceneId,
|
||||||
|
routineName: null,
|
||||||
isAutomation: false,
|
isAutomation: false,
|
||||||
|
selectedFunctions: {},
|
||||||
ifItems: [],
|
ifItems: [],
|
||||||
thenItems: [],
|
thenItems: [],
|
||||||
|
errorMessage: null,
|
||||||
|
loadScenesErrorMessage: null,
|
||||||
|
loadAutomationErrorMessage: null,
|
||||||
|
searchText: '',
|
||||||
|
selectedIcon: null,
|
||||||
|
selectedAutomationOperator: 'or',
|
||||||
|
effectiveTime: null,
|
||||||
));
|
));
|
||||||
|
|
||||||
final sceneDetails = await SceneApi.getSceneDetails(event.sceneId);
|
final sceneDetails = await SceneApi.getSceneDetails(event.sceneId);
|
||||||
@ -549,20 +607,32 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
final Map<String, List<DeviceFunctionData>> updatedFunctions =
|
final Map<String, List<DeviceFunctionData>> updatedFunctions =
|
||||||
Map<String, List<DeviceFunctionData>>.from(state.selectedFunctions);
|
Map<String, List<DeviceFunctionData>>.from(state.selectedFunctions);
|
||||||
|
|
||||||
if (event.isTabToRun) {
|
final Map<String, Map<String, dynamic>> deviceCards = {};
|
||||||
thenItems = sceneDetails.actions.map((action) {
|
|
||||||
AllDevicesModel? matchingDevice;
|
|
||||||
for (var device in state.devices) {
|
|
||||||
if (device.uuid == action.entityId) {
|
|
||||||
matchingDevice = device;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final cardData = {
|
for (var action in sceneDetails.actions) {
|
||||||
|
AllDevicesModel? matchingDevice;
|
||||||
|
for (var device in state.devices) {
|
||||||
|
if (device.uuid == action.entityId) {
|
||||||
|
matchingDevice = device;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final deviceId = action.type == 'automation'
|
||||||
|
? '${action.entityId}_automation'
|
||||||
|
: action.actionExecutor == 'delay'
|
||||||
|
? '${action.entityId}_delay'
|
||||||
|
: action.entityId;
|
||||||
|
|
||||||
|
if (!deviceCards.containsKey(deviceId)) {
|
||||||
|
deviceCards[deviceId] = {
|
||||||
'entityId': action.entityId,
|
'entityId': action.entityId,
|
||||||
'uniqueCustomId': const Uuid().v4(),
|
'deviceId':
|
||||||
'deviceId': action.actionExecutor == 'delay' ? 'delay' : action.entityId,
|
action.actionExecutor == 'delay' ? 'delay' : action.entityId,
|
||||||
|
'uniqueCustomId':
|
||||||
|
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'
|
||||||
@ -570,75 +640,85 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
: (matchingDevice?.name ?? 'Device'),
|
: (matchingDevice?.name ?? 'Device'),
|
||||||
'productType': action.productType,
|
'productType': action.productType,
|
||||||
'functions': matchingDevice?.functions,
|
'functions': matchingDevice?.functions,
|
||||||
'imagePath': matchingDevice?.getDefaultIcon(action.productType),
|
'imagePath': action.type == 'automation'
|
||||||
'device': matchingDevice ?? null,
|
? Assets.automation
|
||||||
|
: action.actionExecutor == 'delay'
|
||||||
|
? Assets.delay
|
||||||
|
: matchingDevice?.getDefaultIcon(action.productType),
|
||||||
|
'device': matchingDevice,
|
||||||
'name': action.name,
|
'name': action.name,
|
||||||
'type': action.type,
|
'type': action.type,
|
||||||
};
|
};
|
||||||
if (action.type == 'automation') {
|
}
|
||||||
updatedFunctions[cardData['uniqueCustomId'].toString()] = [
|
|
||||||
DeviceFunctionData(
|
final cardData = deviceCards[deviceId]!;
|
||||||
entityId: action.entityId,
|
final uniqueCustomId = cardData['uniqueCustomId'].toString();
|
||||||
functionCode: 'rule',
|
|
||||||
value: action.actionExecutor,
|
if (action.type == 'automation') {
|
||||||
operationName: action.name ?? 'Automation',
|
if (!updatedFunctions.containsKey(uniqueCustomId)) {
|
||||||
),
|
updatedFunctions[uniqueCustomId] = [];
|
||||||
];
|
}
|
||||||
} else if (action.executorProperty != null && action.actionExecutor != 'delay') {
|
updatedFunctions[uniqueCustomId]!.add(
|
||||||
final functions = matchingDevice?.functions;
|
DeviceFunctionData(
|
||||||
final functionCode = action.executorProperty!.functionCode;
|
entityId: action.entityId,
|
||||||
for (var function in functions ?? []) {
|
functionCode: 'automation',
|
||||||
if (function.code == functionCode) {
|
value: action.actionExecutor,
|
||||||
updatedFunctions[cardData['uniqueCustomId'].toString()] = [
|
operationName: 'Automation',
|
||||||
DeviceFunctionData(
|
),
|
||||||
entityId: action.entityId,
|
);
|
||||||
functionCode: functionCode ?? '',
|
emit(state.copyWith(automationActionExecutor: action.actionExecutor));
|
||||||
value: action.executorProperty!.functionValue,
|
} else if (action.executorProperty != null &&
|
||||||
operationName: function.operationName,
|
action.actionExecutor != 'delay') {
|
||||||
),
|
if (!updatedFunctions.containsKey(uniqueCustomId)) {
|
||||||
];
|
updatedFunctions[uniqueCustomId] = [];
|
||||||
break;
|
}
|
||||||
}
|
final functions = matchingDevice?.functions;
|
||||||
|
final functionCode = action.executorProperty?.functionCode;
|
||||||
|
for (DeviceFunction function in functions ?? []) {
|
||||||
|
if (function.code == functionCode) {
|
||||||
|
updatedFunctions[uniqueCustomId]!.add(
|
||||||
|
DeviceFunctionData(
|
||||||
|
entityId: action.entityId,
|
||||||
|
functionCode: functionCode ?? '',
|
||||||
|
value: action.executorProperty?.functionValue,
|
||||||
|
operationName: function.operationName,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} else if (action.actionExecutor == 'delay') {
|
|
||||||
final delayFunction = DelayFunction(
|
|
||||||
deviceId: action.entityId,
|
|
||||||
deviceName: 'Delay',
|
|
||||||
);
|
|
||||||
updatedFunctions[cardData['uniqueCustomId'].toString()] = [
|
|
||||||
DeviceFunctionData(
|
|
||||||
entityId: action.entityId,
|
|
||||||
functionCode: 'delay',
|
|
||||||
value: action.executorProperty?.delaySeconds ?? 0,
|
|
||||||
operationName: delayFunction.operationName,
|
|
||||||
),
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
} else if (action.actionExecutor == 'delay') {
|
||||||
return cardData;
|
if (!updatedFunctions.containsKey(uniqueCustomId)) {
|
||||||
}).toList();
|
updatedFunctions[uniqueCustomId] = [];
|
||||||
|
|
||||||
ifItems = [
|
|
||||||
{
|
|
||||||
'entityId': 'tab_to_run',
|
|
||||||
'uniqueCustomId': const Uuid().v4(),
|
|
||||||
'deviceId': 'tab_to_run',
|
|
||||||
'title': 'Tab to run',
|
|
||||||
'productType': 'tab_to_run',
|
|
||||||
'imagePath': Assets.tabToRun,
|
|
||||||
}
|
}
|
||||||
];
|
final delayFunction = DelayFunction(
|
||||||
} else {
|
deviceId: action.entityId,
|
||||||
final result = _createCardData(
|
deviceName: 'Delay',
|
||||||
sceneDetails.actions,
|
);
|
||||||
sceneDetails.conditions,
|
updatedFunctions[uniqueCustomId]!.add(
|
||||||
updatedFunctions,
|
DeviceFunctionData(
|
||||||
false,
|
entityId: action.entityId,
|
||||||
);
|
functionCode: 'delay',
|
||||||
thenItems = result.$1;
|
value: action.executorProperty?.delaySeconds ?? 0,
|
||||||
ifItems = result.$2;
|
operationName: delayFunction.operationName,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
thenItems = deviceCards.values.toList();
|
||||||
|
|
||||||
|
ifItems = [
|
||||||
|
{
|
||||||
|
'entityId': 'tab_to_run',
|
||||||
|
'uniqueCustomId': const Uuid().v4(),
|
||||||
|
'deviceId': 'tab_to_run',
|
||||||
|
'title': 'Tab to run',
|
||||||
|
'productType': 'tab_to_run',
|
||||||
|
'imagePath': Assets.tabToRun,
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
routineName: sceneDetails.name,
|
routineName: sceneDetails.name,
|
||||||
@ -673,7 +753,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
thenItems: [],
|
thenItems: [],
|
||||||
));
|
));
|
||||||
|
|
||||||
final automationDetails = await SceneApi.getAutomationDetails(event.automationId);
|
final automationDetails =
|
||||||
|
await SceneApi.getAutomationDetails(event.automationId);
|
||||||
|
|
||||||
final List<Map<String, dynamic>> thenItems;
|
final List<Map<String, dynamic>> thenItems;
|
||||||
final List<Map<String, dynamic>> ifItems;
|
final List<Map<String, dynamic>> ifItems;
|
||||||
@ -692,13 +773,16 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
final cardData = {
|
final cardData = {
|
||||||
'entityId': condition.entityId,
|
'entityId': condition.entityId,
|
||||||
'uniqueCustomId': const Uuid().v4(),
|
'uniqueCustomId': const Uuid().v4(),
|
||||||
'deviceId': condition.expr.statusCode == 'delay' ? 'delay' : condition.entityId,
|
'deviceId': condition.expr.statusCode == 'delay'
|
||||||
|
? 'delay'
|
||||||
|
: condition.entityId,
|
||||||
'title': condition.expr.statusCode == 'delay'
|
'title': condition.expr.statusCode == 'delay'
|
||||||
? 'Delay'
|
? 'Delay'
|
||||||
: (matchingDevice?.name ?? 'Device'),
|
: (matchingDevice?.name ?? 'Device'),
|
||||||
'productType': condition.productType,
|
'productType': condition.productType,
|
||||||
'functions': matchingDevice?.functions ?? [],
|
'functions': matchingDevice?.functions ?? [],
|
||||||
'imagePath': matchingDevice?.getDefaultIcon(condition.productType) ?? '',
|
'imagePath':
|
||||||
|
matchingDevice?.getDefaultIcon(condition.productType) ?? '',
|
||||||
'device': matchingDevice,
|
'device': matchingDevice,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -735,15 +819,19 @@ 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,
|
||||||
'functions': matchingDevice.functions,
|
'functions': matchingDevice.functions,
|
||||||
'imagePath': matchingDevice.getDefaultIcon(action.productType),
|
'imagePath': matchingDevice.getDefaultIcon(action.productType),
|
||||||
'device': matchingDevice,
|
'device': matchingDevice,
|
||||||
};
|
};
|
||||||
|
|
||||||
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) {
|
||||||
@ -806,8 +894,9 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RoutineState _resetState() {
|
FutureOr<void> _onResetRoutineState(
|
||||||
return const RoutineState(
|
ResetRoutineState event, Emitter<RoutineState> emit) {
|
||||||
|
emit(state.copyWith(
|
||||||
ifItems: [],
|
ifItems: [],
|
||||||
thenItems: [],
|
thenItems: [],
|
||||||
selectedFunctions: {},
|
selectedFunctions: {},
|
||||||
@ -824,11 +913,7 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
selectedAutomationOperator: 'or',
|
selectedAutomationOperator: 'or',
|
||||||
effectiveTime: null,
|
effectiveTime: null,
|
||||||
routineName: null,
|
routineName: null,
|
||||||
);
|
));
|
||||||
}
|
|
||||||
|
|
||||||
FutureOr<void> _onResetRoutineState(ResetRoutineState event, Emitter<RoutineState> emit) {
|
|
||||||
emit(_resetState());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FutureOr<void> _deleteScene(DeleteScene event, Emitter<RoutineState> emit) {
|
FutureOr<void> _deleteScene(DeleteScene event, Emitter<RoutineState> emit) {
|
||||||
@ -842,7 +927,7 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
|
|
||||||
add(const LoadScenes(spaceId, communityId));
|
add(const LoadScenes(spaceId, communityId));
|
||||||
add(const LoadAutomation(spaceId));
|
add(const LoadAutomation(spaceId));
|
||||||
emit(_resetState());
|
add(ResetRoutineState());
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
@ -865,7 +950,8 @@ 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 devices = await DevicesManagementApi().fetchDevices();
|
||||||
@ -876,7 +962,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)) {
|
||||||
@ -884,6 +971,15 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
errorMessage: 'Cannot have delay as the first action',
|
errorMessage: 'Cannot have delay as the first action',
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
));
|
));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_isLastActionDelay(state.thenItems)) {
|
||||||
|
emit(state.copyWith(
|
||||||
|
errorMessage: 'Cannot have delay as the last action',
|
||||||
|
isLoading: false,
|
||||||
|
));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -933,10 +1029,13 @@ 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']) {
|
||||||
emit(_resetState());
|
Navigator.of(NavigationService.navigatorKey.currentContext!).pop();
|
||||||
|
add(ResetRoutineState());
|
||||||
add(const LoadScenes(spaceId, communityId));
|
add(const LoadScenes(spaceId, communityId));
|
||||||
|
add(const LoadAutomation(spaceId));
|
||||||
} else {
|
} else {
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
@ -951,7 +1050,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 {
|
||||||
if (_isFirstActionDelay(state.thenItems)) {
|
if (_isFirstActionDelay(state.thenItems)) {
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
errorMessage: 'Cannot have delay as the first action',
|
errorMessage: 'Cannot have delay as the first action',
|
||||||
@ -963,7 +1063,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
try {
|
try {
|
||||||
final conditions = state.ifItems
|
final conditions = state.ifItems
|
||||||
.map((item) {
|
.map((item) {
|
||||||
final functions = state.selectedFunctions[item['uniqueCustomId']] ?? [];
|
final functions =
|
||||||
|
state.selectedFunctions[item['uniqueCustomId']] ?? [];
|
||||||
if (functions.isEmpty) return null;
|
if (functions.isEmpty) return null;
|
||||||
|
|
||||||
final function = functions.first;
|
final function = functions.first;
|
||||||
@ -983,7 +1084,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
|
|
||||||
final actions = state.thenItems
|
final actions = state.thenItems
|
||||||
.map((item) {
|
.map((item) {
|
||||||
final functions = state.selectedFunctions[item['uniqueCustomId']] ?? [];
|
final functions =
|
||||||
|
state.selectedFunctions[item['uniqueCustomId']] ?? [];
|
||||||
if (functions.isEmpty) return null;
|
if (functions.isEmpty) return null;
|
||||||
|
|
||||||
final function = functions.first;
|
final function = functions.first;
|
||||||
@ -993,8 +1095,9 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
executorProperty: ExecutorProperty(
|
executorProperty: ExecutorProperty(
|
||||||
functionCode: function.functionCode,
|
functionCode: function.functionCode,
|
||||||
functionValue: function.value,
|
functionValue: function.value,
|
||||||
delaySeconds:
|
delaySeconds: function.functionCode == 'delay'
|
||||||
function.functionCode == 'delay' ? (function.value as num).toInt() : null,
|
? (function.value as num).toInt()
|
||||||
|
: null,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
@ -1005,12 +1108,14 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
spaceUuid: spaceId,
|
spaceUuid: spaceId,
|
||||||
automationName: state.routineName ?? '',
|
automationName: state.routineName ?? '',
|
||||||
decisionExpr: state.selectedAutomationOperator,
|
decisionExpr: state.selectedAutomationOperator,
|
||||||
effectiveTime: state.effectiveTime ?? EffectiveTime(start: '', end: '', loops: ''),
|
effectiveTime:
|
||||||
|
state.effectiveTime ?? EffectiveTime(start: '', end: '', loops: ''),
|
||||||
conditions: conditions,
|
conditions: conditions,
|
||||||
actions: actions,
|
actions: actions,
|
||||||
);
|
);
|
||||||
|
|
||||||
await SceneApi.updateAutomation(createAutomationModel, state.automationId ?? '');
|
await SceneApi.updateAutomation(
|
||||||
|
createAutomationModel, state.automationId ?? '');
|
||||||
|
|
||||||
add(const LoadAutomation(spaceId));
|
add(const LoadAutomation(spaceId));
|
||||||
emit(state.copyWith(isLoading: false));
|
emit(state.copyWith(isLoading: false));
|
||||||
@ -1021,4 +1126,10 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FutureOr<void> _onSetAutomationActionExecutor(
|
||||||
|
SetAutomationActionExecutor event, Emitter<RoutineState> emit) {
|
||||||
|
emit(state.copyWith(
|
||||||
|
automationActionExecutor: event.automationActionExecutor));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -181,6 +181,13 @@ class UpdateAutomation extends RoutineEvent {
|
|||||||
List<Object> get props => [];
|
List<Object> get props => [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class SetAutomationActionExecutor extends RoutineEvent {
|
||||||
|
final String automationActionExecutor;
|
||||||
|
const SetAutomationActionExecutor({required this.automationActionExecutor});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [automationActionExecutor];
|
||||||
|
}
|
||||||
|
|
||||||
class FetchDevicesInRoutine extends RoutineEvent {}
|
class FetchDevicesInRoutine extends RoutineEvent {}
|
||||||
|
|
||||||
class ResetRoutineState extends RoutineEvent {}
|
class ResetRoutineState extends RoutineEvent {}
|
||||||
|
@ -22,6 +22,7 @@ class RoutineState extends Equatable {
|
|||||||
final String? automationId;
|
final String? automationId;
|
||||||
final bool? isUpdate;
|
final bool? isUpdate;
|
||||||
final List<AllDevicesModel> devices;
|
final List<AllDevicesModel> devices;
|
||||||
|
final String? automationActionExecutor;
|
||||||
|
|
||||||
const RoutineState({
|
const RoutineState({
|
||||||
this.ifItems = const [],
|
this.ifItems = const [],
|
||||||
@ -45,6 +46,7 @@ class RoutineState extends Equatable {
|
|||||||
this.automationId,
|
this.automationId,
|
||||||
this.isUpdate,
|
this.isUpdate,
|
||||||
this.devices = const [],
|
this.devices = const [],
|
||||||
|
this.automationActionExecutor,
|
||||||
});
|
});
|
||||||
|
|
||||||
RoutineState copyWith({
|
RoutineState copyWith({
|
||||||
@ -68,6 +70,7 @@ class RoutineState extends Equatable {
|
|||||||
String? automationId,
|
String? automationId,
|
||||||
bool? isUpdate,
|
bool? isUpdate,
|
||||||
List<AllDevicesModel>? devices,
|
List<AllDevicesModel>? devices,
|
||||||
|
String? automationActionExecutor,
|
||||||
}) {
|
}) {
|
||||||
return RoutineState(
|
return RoutineState(
|
||||||
ifItems: ifItems ?? this.ifItems,
|
ifItems: ifItems ?? this.ifItems,
|
||||||
@ -93,6 +96,8 @@ class RoutineState extends Equatable {
|
|||||||
automationId: automationId ?? this.automationId,
|
automationId: automationId ?? this.automationId,
|
||||||
isUpdate: isUpdate ?? this.isUpdate,
|
isUpdate: isUpdate ?? this.isUpdate,
|
||||||
devices: devices ?? this.devices,
|
devices: devices ?? this.devices,
|
||||||
|
automationActionExecutor:
|
||||||
|
automationActionExecutor ?? this.automationActionExecutor,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,5 +123,6 @@ class RoutineState extends Equatable {
|
|||||||
automationId,
|
automationId,
|
||||||
isUpdate,
|
isUpdate,
|
||||||
devices,
|
devices,
|
||||||
|
automationActionExecutor,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -163,8 +163,6 @@ class SaveRoutineHelper {
|
|||||||
.add(const CreateSceneEvent());
|
.add(const CreateSceneEvent());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Navigator.pop(context, true);
|
|
||||||
},
|
},
|
||||||
isConfirmEnabled: true,
|
isConfirmEnabled: true,
|
||||||
),
|
),
|
||||||
|
@ -48,7 +48,8 @@ class RoutineDetailsModel {
|
|||||||
spaceUuid: spaceUuid,
|
spaceUuid: spaceUuid,
|
||||||
automationName: name,
|
automationName: name,
|
||||||
decisionExpr: decisionExpr,
|
decisionExpr: decisionExpr,
|
||||||
effectiveTime: effectiveTime ?? EffectiveTime(start: '', end: '', loops: ''),
|
effectiveTime:
|
||||||
|
effectiveTime ?? EffectiveTime(start: '', end: '', loops: ''),
|
||||||
conditions: conditions?.map((c) => c.toCondition()).toList() ?? [],
|
conditions: conditions?.map((c) => c.toCondition()).toList() ?? [],
|
||||||
actions: actions.map((a) => a.toAutomationAction()).toList(),
|
actions: actions.map((a) => a.toAutomationAction()).toList(),
|
||||||
);
|
);
|
||||||
@ -63,7 +64,8 @@ class RoutineDetailsModel {
|
|||||||
if (iconId != null) 'iconUuid': iconId,
|
if (iconId != null) 'iconUuid': iconId,
|
||||||
if (showInDevice != null) 'showInDevice': showInDevice,
|
if (showInDevice != null) 'showInDevice': showInDevice,
|
||||||
if (effectiveTime != null) 'effectiveTime': effectiveTime!.toMap(),
|
if (effectiveTime != null) 'effectiveTime': effectiveTime!.toMap(),
|
||||||
if (conditions != null) 'conditions': conditions!.map((x) => x.toMap()).toList(),
|
if (conditions != null)
|
||||||
|
'conditions': conditions!.map((x) => x.toMap()).toList(),
|
||||||
if (type != null) 'type': type,
|
if (type != null) 'type': type,
|
||||||
if (sceneId != null) 'sceneId': sceneId,
|
if (sceneId != null) 'sceneId': sceneId,
|
||||||
if (automationId != null) 'automationId': automationId,
|
if (automationId != null) 'automationId': automationId,
|
||||||
@ -80,10 +82,12 @@ class RoutineDetailsModel {
|
|||||||
),
|
),
|
||||||
iconId: map['iconUuid'],
|
iconId: map['iconUuid'],
|
||||||
showInDevice: map['showInDevice'],
|
showInDevice: map['showInDevice'],
|
||||||
effectiveTime:
|
effectiveTime: map['effectiveTime'] != null
|
||||||
map['effectiveTime'] != null ? EffectiveTime.fromMap(map['effectiveTime']) : null,
|
? EffectiveTime.fromMap(map['effectiveTime'])
|
||||||
|
: null,
|
||||||
conditions: map['conditions'] != null
|
conditions: map['conditions'] != null
|
||||||
? List<RoutineCondition>.from(map['conditions'].map((x) => RoutineCondition.fromMap(x)))
|
? List<RoutineCondition>.from(
|
||||||
|
map['conditions'].map((x) => RoutineCondition.fromMap(x)))
|
||||||
: null,
|
: null,
|
||||||
type: map['type'],
|
type: map['type'],
|
||||||
sceneId: map['sceneId'],
|
sceneId: map['sceneId'],
|
||||||
@ -136,7 +140,8 @@ class RoutineAction {
|
|||||||
'actionExecutor': actionExecutor,
|
'actionExecutor': actionExecutor,
|
||||||
if (type != null) 'type': type,
|
if (type != null) 'type': type,
|
||||||
if (name != null) 'name': name,
|
if (name != null) 'name': name,
|
||||||
if (executorProperty != null) 'executorProperty': executorProperty!.toMap(),
|
if (executorProperty != null)
|
||||||
|
'executorProperty': executorProperty!.toMap(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,7 +26,9 @@ class _RoutinesViewState extends State<RoutinesView> {
|
|||||||
return BlocBuilder<SwitchTabsBloc, SwitchTabsState>(
|
return BlocBuilder<SwitchTabsBloc, SwitchTabsState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
if (state is ShowCreateRoutineState && state.showCreateRoutine) {
|
if (state is ShowCreateRoutineState && state.showCreateRoutine) {
|
||||||
return const CreateNewRoutineView();
|
return const CreateNewRoutineView(
|
||||||
|
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
|
@ -7,7 +7,7 @@ import 'package:syncrow_web/pages/routiens/widgets/dialog_header.dart';
|
|||||||
import 'package:syncrow_web/pages/routiens/widgets/dialog_footer.dart';
|
import 'package:syncrow_web/pages/routiens/widgets/dialog_footer.dart';
|
||||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||||
|
|
||||||
class AutomationDialog extends StatefulWidget {
|
class AutomationDialog extends StatelessWidget {
|
||||||
final String automationName;
|
final String automationName;
|
||||||
final String automationId;
|
final String automationId;
|
||||||
final String uniqueCustomId;
|
final String uniqueCustomId;
|
||||||
@ -19,77 +19,86 @@ class AutomationDialog extends StatefulWidget {
|
|||||||
required this.uniqueCustomId,
|
required this.uniqueCustomId,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
|
||||||
_AutomationDialogState createState() => _AutomationDialogState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _AutomationDialogState extends State<AutomationDialog> {
|
|
||||||
bool _isEnabled = true;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Dialog(
|
return BlocBuilder<RoutineBloc, RoutineState>(
|
||||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
|
builder: (context, state) {
|
||||||
child: Container(
|
final isEnabled = state.automationActionExecutor == 'rule_enable';
|
||||||
width: 400,
|
|
||||||
padding: const EdgeInsets.all(16),
|
return Dialog(
|
||||||
child: Column(
|
shape:
|
||||||
mainAxisSize: MainAxisSize.min,
|
RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
|
||||||
children: [
|
child: Container(
|
||||||
DialogHeader(widget.automationName),
|
width: 400,
|
||||||
const SizedBox(height: 16),
|
padding: const EdgeInsets.all(16),
|
||||||
ListTile(
|
child: Column(
|
||||||
leading: SvgPicture.asset(Assets.acPower, width: 24, height: 24),
|
mainAxisSize: MainAxisSize.min,
|
||||||
title: const Text('Enable'),
|
children: [
|
||||||
trailing: Radio<bool>(
|
DialogHeader(automationName),
|
||||||
value: true,
|
const SizedBox(height: 16),
|
||||||
groupValue: _isEnabled,
|
ListTile(
|
||||||
onChanged: (bool? value) {
|
leading:
|
||||||
setState(() {
|
SvgPicture.asset(Assets.acPower, width: 24, height: 24),
|
||||||
_isEnabled = value!;
|
title: const Text('Enable'),
|
||||||
});
|
trailing: Radio<bool>(
|
||||||
},
|
value: true,
|
||||||
),
|
groupValue: isEnabled,
|
||||||
),
|
onChanged: (bool? value) {
|
||||||
ListTile(
|
if (value == true) {
|
||||||
leading:
|
context.read<RoutineBloc>().add(
|
||||||
SvgPicture.asset(Assets.acPowerOff, width: 24, height: 24),
|
const SetAutomationActionExecutor(
|
||||||
title: const Text('Disable'),
|
automationActionExecutor: 'rule_enable',
|
||||||
trailing: Radio<bool>(
|
),
|
||||||
value: false,
|
);
|
||||||
groupValue: _isEnabled,
|
}
|
||||||
onChanged: (bool? value) {
|
},
|
||||||
setState(() {
|
),
|
||||||
_isEnabled = value!;
|
),
|
||||||
});
|
ListTile(
|
||||||
},
|
leading: SvgPicture.asset(Assets.acPowerOff,
|
||||||
),
|
width: 24, height: 24),
|
||||||
),
|
title: const Text('Disable'),
|
||||||
const SizedBox(height: 16),
|
trailing: Radio<bool>(
|
||||||
DialogFooter(
|
value: false,
|
||||||
onConfirm: () {
|
groupValue: isEnabled,
|
||||||
context.read<RoutineBloc>().add(
|
onChanged: (bool? value) {
|
||||||
AddFunctionToRoutine(
|
if (value == false) {
|
||||||
[
|
context.read<RoutineBloc>().add(
|
||||||
DeviceFunctionData(
|
const SetAutomationActionExecutor(
|
||||||
entityId: widget.automationId,
|
automationActionExecutor: 'rule_disable',
|
||||||
functionCode: 'automation',
|
),
|
||||||
value: _isEnabled ? 'rule_enable' : 'rule_disable',
|
);
|
||||||
operationName: 'Automation',
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
DialogFooter(
|
||||||
|
onConfirm: () {
|
||||||
|
context.read<RoutineBloc>().add(
|
||||||
|
AddFunctionToRoutine(
|
||||||
|
[
|
||||||
|
DeviceFunctionData(
|
||||||
|
entityId: automationId,
|
||||||
|
functionCode: 'automation',
|
||||||
|
value: state.automationActionExecutor,
|
||||||
|
operationName: 'Automation',
|
||||||
|
),
|
||||||
|
],
|
||||||
|
uniqueCustomId,
|
||||||
),
|
),
|
||||||
],
|
);
|
||||||
widget.uniqueCustomId,
|
Navigator.of(context).pop(true);
|
||||||
),
|
},
|
||||||
);
|
onCancel: () => Navigator.of(context).pop(false),
|
||||||
Navigator.of(context).pop(true);
|
isConfirmEnabled: true,
|
||||||
},
|
dialogWidth: 400,
|
||||||
onCancel: () => Navigator.of(context).pop(false),
|
),
|
||||||
isConfirmEnabled: true,
|
],
|
||||||
dialogWidth: 400,
|
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
);
|
||||||
),
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,14 +10,41 @@ import 'package:syncrow_web/utils/color_manager.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';
|
import 'package:syncrow_web/utils/style.dart';
|
||||||
|
|
||||||
class RoutineSearchAndButtons extends StatelessWidget {
|
class RoutineSearchAndButtons extends StatefulWidget {
|
||||||
const RoutineSearchAndButtons({
|
const RoutineSearchAndButtons({
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<RoutineSearchAndButtons> createState() =>
|
||||||
|
_RoutineSearchAndButtonsState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _RoutineSearchAndButtonsState extends State<RoutineSearchAndButtons> {
|
||||||
|
late TextEditingController _nameController;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_nameController = TextEditingController();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_nameController.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocBuilder<RoutineBloc, RoutineState>(
|
return BlocConsumer<RoutineBloc, RoutineState>(
|
||||||
|
listenWhen: (previous, current) =>
|
||||||
|
previous.routineName != current.routineName,
|
||||||
|
listener: (context, state) {
|
||||||
|
if (state.routineName != _nameController.text) {
|
||||||
|
_nameController.text = state.routineName ?? '';
|
||||||
|
}
|
||||||
|
},
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
return LayoutBuilder(
|
return LayoutBuilder(
|
||||||
builder: (BuildContext context, BoxConstraints constraints) {
|
builder: (BuildContext context, BoxConstraints constraints) {
|
||||||
@ -35,26 +62,9 @@ class RoutineSearchAndButtons extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
ConstrainedBox(
|
ConstrainedBox(
|
||||||
constraints: BoxConstraints(
|
constraints: BoxConstraints(
|
||||||
maxWidth:
|
maxWidth: constraints.maxWidth > 700
|
||||||
constraints.maxWidth > 700 ? 450 : constraints.maxWidth - 32),
|
? 450
|
||||||
// child: StatefulTextField(
|
: constraints.maxWidth - 32),
|
||||||
// title: 'Routine Name',
|
|
||||||
// initialValue: state.routineName ?? '',
|
|
||||||
// height: 40,
|
|
||||||
// // controller: TextEditingController(),
|
|
||||||
// hintText: 'Please enter the name',
|
|
||||||
// boxDecoration: containerWhiteDecoration,
|
|
||||||
// elevation: 0,
|
|
||||||
// borderRadius: 15,
|
|
||||||
// isRequired: true,
|
|
||||||
// width: 450,
|
|
||||||
// onSubmitted: (value) {
|
|
||||||
// // context.read<RoutineBloc>().add(SetRoutineName(value));
|
|
||||||
// },
|
|
||||||
// onChanged: (value) {
|
|
||||||
// context.read<RoutineBloc>().add(SetRoutineName(value));
|
|
||||||
// },
|
|
||||||
// ),
|
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
@ -63,10 +73,13 @@ class RoutineSearchAndButtons extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
Text('* ',
|
Text('* ',
|
||||||
style: context.textTheme.bodyMedium!
|
style: context.textTheme.bodyMedium!
|
||||||
.copyWith(color: ColorsManager.red, fontSize: 13)),
|
.copyWith(
|
||||||
|
color: ColorsManager.red,
|
||||||
|
fontSize: 13)),
|
||||||
Text(
|
Text(
|
||||||
'Routine Name',
|
'Routine Name',
|
||||||
style: context.textTheme.bodyMedium!.copyWith(
|
style: context.textTheme.bodyMedium!
|
||||||
|
.copyWith(
|
||||||
fontSize: 13,
|
fontSize: 13,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: ColorsManager.blackColor,
|
color: ColorsManager.blackColor,
|
||||||
@ -80,18 +93,24 @@ class RoutineSearchAndButtons extends StatelessWidget {
|
|||||||
decoration: containerWhiteDecoration,
|
decoration: containerWhiteDecoration,
|
||||||
child: TextFormField(
|
child: TextFormField(
|
||||||
style: context.textTheme.bodyMedium!
|
style: context.textTheme.bodyMedium!
|
||||||
.copyWith(color: ColorsManager.blackColor),
|
.copyWith(
|
||||||
initialValue: state.routineName,
|
color: ColorsManager.blackColor),
|
||||||
|
controller: _nameController,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: 'Please enter the name',
|
hintText: 'Please enter the name',
|
||||||
hintStyle: context.textTheme.bodyMedium!
|
hintStyle: context.textTheme.bodyMedium!
|
||||||
.copyWith(fontSize: 12, color: ColorsManager.grayColor),
|
.copyWith(
|
||||||
|
fontSize: 12,
|
||||||
|
color: ColorsManager.grayColor),
|
||||||
contentPadding:
|
contentPadding:
|
||||||
const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
|
const EdgeInsets.symmetric(
|
||||||
|
horizontal: 12, vertical: 10),
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
),
|
),
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
context.read<RoutineBloc>().add(SetRoutineName(value));
|
context
|
||||||
|
.read<RoutineBloc>()
|
||||||
|
.add(SetRoutineName(value));
|
||||||
},
|
},
|
||||||
validator: (value) {
|
validator: (value) {
|
||||||
if (value == null || value.isEmpty) {
|
if (value == null || value.isEmpty) {
|
||||||
@ -111,15 +130,17 @@ class RoutineSearchAndButtons extends StatelessWidget {
|
|||||||
width: 200,
|
width: 200,
|
||||||
child: Center(
|
child: Center(
|
||||||
child: DefaultButton(
|
child: DefaultButton(
|
||||||
onPressed: state.isAutomation || state.isTabToRun
|
onPressed: state.isAutomation ||
|
||||||
|
state.isTabToRun
|
||||||
? () async {
|
? () async {
|
||||||
final result = await SettingHelper.showSettingDialog(
|
final result = await SettingHelper
|
||||||
|
.showSettingDialog(
|
||||||
context: context,
|
context: context,
|
||||||
|
iconId: state.selectedIcon,
|
||||||
);
|
);
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
context
|
context.read<RoutineBloc>().add(
|
||||||
.read<RoutineBloc>()
|
AddSelectedIcon(result));
|
||||||
.add(AddSelectedIcon(result));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
@ -175,10 +196,12 @@ class RoutineSearchAndButtons extends StatelessWidget {
|
|||||||
child: Center(
|
child: Center(
|
||||||
child: DefaultButton(
|
child: DefaultButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
if (state.routineName == null || state.routineName!.isEmpty) {
|
if (state.routineName == null ||
|
||||||
|
state.routineName!.isEmpty) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(
|
SnackBar(
|
||||||
content: const Text('Please enter the routine name'),
|
content: const Text(
|
||||||
|
'Please enter the routine name'),
|
||||||
duration: const Duration(seconds: 2),
|
duration: const Duration(seconds: 2),
|
||||||
backgroundColor: ColorsManager.red,
|
backgroundColor: ColorsManager.red,
|
||||||
action: SnackBarAction(
|
action: SnackBarAction(
|
||||||
@ -192,10 +215,12 @@ class RoutineSearchAndButtons extends StatelessWidget {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.ifItems.isEmpty || state.thenItems.isEmpty) {
|
if (state.ifItems.isEmpty ||
|
||||||
|
state.thenItems.isEmpty) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(
|
SnackBar(
|
||||||
content: const Text('Please add if and then condition'),
|
content: const Text(
|
||||||
|
'Please add if and then condition'),
|
||||||
duration: const Duration(seconds: 2),
|
duration: const Duration(seconds: 2),
|
||||||
backgroundColor: ColorsManager.red,
|
backgroundColor: ColorsManager.red,
|
||||||
action: SnackBarAction(
|
action: SnackBarAction(
|
||||||
@ -208,13 +233,15 @@ class RoutineSearchAndButtons extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final result =
|
final result = await SaveRoutineHelper
|
||||||
await SaveRoutineHelper.showSaveRoutineDialog(context);
|
.showSaveRoutineDialog(context);
|
||||||
if (result != null && result) {
|
if (result != null && result) {
|
||||||
BlocProvider.of<SwitchTabsBloc>(context).add(
|
BlocProvider.of<SwitchTabsBloc>(context)
|
||||||
|
.add(
|
||||||
const CreateNewRoutineViewEvent(false),
|
const CreateNewRoutineViewEvent(false),
|
||||||
);
|
);
|
||||||
BlocProvider.of<SwitchTabsBloc>(context).add(
|
BlocProvider.of<SwitchTabsBloc>(context)
|
||||||
|
.add(
|
||||||
const TriggerSwitchTabsEvent(true),
|
const TriggerSwitchTabsEvent(true),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -248,11 +275,15 @@ class RoutineSearchAndButtons extends StatelessWidget {
|
|||||||
child: DefaultButton(
|
child: DefaultButton(
|
||||||
onPressed: state.isAutomation || state.isTabToRun
|
onPressed: state.isAutomation || state.isTabToRun
|
||||||
? () async {
|
? () async {
|
||||||
final result = await SettingHelper.showSettingDialog(
|
final result =
|
||||||
|
await SettingHelper.showSettingDialog(
|
||||||
context: context,
|
context: context,
|
||||||
|
iconId: state.selectedIcon,
|
||||||
);
|
);
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
context.read<RoutineBloc>().add(AddSelectedIcon(result));
|
context
|
||||||
|
.read<RoutineBloc>()
|
||||||
|
.add(AddSelectedIcon(result));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
@ -302,10 +333,12 @@ class RoutineSearchAndButtons extends StatelessWidget {
|
|||||||
child: Center(
|
child: Center(
|
||||||
child: DefaultButton(
|
child: DefaultButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
if (state.routineName == null || state.routineName!.isEmpty) {
|
if (state.routineName == null ||
|
||||||
|
state.routineName!.isEmpty) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(
|
SnackBar(
|
||||||
content: const Text('Please enter the routine name'),
|
content: const Text(
|
||||||
|
'Please enter the routine name'),
|
||||||
duration: const Duration(seconds: 2),
|
duration: const Duration(seconds: 2),
|
||||||
backgroundColor: ColorsManager.red,
|
backgroundColor: ColorsManager.red,
|
||||||
action: SnackBarAction(
|
action: SnackBarAction(
|
||||||
@ -319,10 +352,12 @@ class RoutineSearchAndButtons extends StatelessWidget {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.ifItems.isEmpty || state.thenItems.isEmpty) {
|
if (state.ifItems.isEmpty ||
|
||||||
|
state.thenItems.isEmpty) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(
|
SnackBar(
|
||||||
content: const Text('Please add if and then condition'),
|
content: const Text(
|
||||||
|
'Please add if and then condition'),
|
||||||
duration: const Duration(seconds: 2),
|
duration: const Duration(seconds: 2),
|
||||||
backgroundColor: ColorsManager.red,
|
backgroundColor: ColorsManager.red,
|
||||||
action: SnackBarAction(
|
action: SnackBarAction(
|
||||||
@ -335,7 +370,9 @@ class RoutineSearchAndButtons extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final result = await SaveRoutineHelper.showSaveRoutineDialog(context);
|
final result =
|
||||||
|
await SaveRoutineHelper.showSaveRoutineDialog(
|
||||||
|
context);
|
||||||
if (result != null && result) {
|
if (result != null && result) {
|
||||||
BlocProvider.of<SwitchTabsBloc>(context).add(
|
BlocProvider.of<SwitchTabsBloc>(context).add(
|
||||||
const CreateNewRoutineViewEvent(false),
|
const CreateNewRoutineViewEvent(false),
|
||||||
|
@ -26,7 +26,9 @@ class ThenContainer extends StatelessWidget {
|
|||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
const Text('THEN', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
|
const Text('THEN',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 18, fontWeight: FontWeight.bold)),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
state.isLoading && state.isUpdate == true
|
state.isLoading && state.isUpdate == true
|
||||||
? const Center(
|
? const Center(
|
||||||
@ -39,12 +41,17 @@ class ThenContainer extends StatelessWidget {
|
|||||||
state.thenItems.length,
|
state.thenItems.length,
|
||||||
(index) => GestureDetector(
|
(index) => GestureDetector(
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
if (state.thenItems[index]['deviceId'] == 'delay') {
|
if (state.thenItems[index]
|
||||||
final result = await DelayHelper.showDelayPickerDialog(
|
['deviceId'] ==
|
||||||
context, state.thenItems[index]);
|
'delay') {
|
||||||
|
final result = await DelayHelper
|
||||||
|
.showDelayPickerDialog(context,
|
||||||
|
state.thenItems[index]);
|
||||||
|
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
context.read<RoutineBloc>().add(AddToThenContainer({
|
context
|
||||||
|
.read<RoutineBloc>()
|
||||||
|
.add(AddToThenContainer({
|
||||||
...state.thenItems[index],
|
...state.thenItems[index],
|
||||||
'imagePath': Assets.delay,
|
'imagePath': Assets.delay,
|
||||||
'title': 'Delay',
|
'title': 'Delay',
|
||||||
@ -53,57 +60,76 @@ class ThenContainer extends StatelessWidget {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.thenItems[index]['type'] == 'automation') {
|
if (state.thenItems[index]['type'] ==
|
||||||
|
'automation') {
|
||||||
final result = await showDialog<bool>(
|
final result = await showDialog<bool>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (BuildContext context) => AutomationDialog(
|
builder: (BuildContext context) =>
|
||||||
|
AutomationDialog(
|
||||||
automationName:
|
automationName:
|
||||||
state.thenItems[index]['name'] ?? 'Automation',
|
state.thenItems[index]
|
||||||
|
['name'] ??
|
||||||
|
'Automation',
|
||||||
automationId:
|
automationId:
|
||||||
state.thenItems[index]['deviceId'] ?? '',
|
state.thenItems[index]
|
||||||
uniqueCustomId: state.thenItems[index]
|
['deviceId'] ??
|
||||||
['uniqueCustomId'],
|
'',
|
||||||
|
uniqueCustomId:
|
||||||
|
state.thenItems[index]
|
||||||
|
['uniqueCustomId'],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
context.read<RoutineBloc>().add(AddToThenContainer({
|
context
|
||||||
|
.read<RoutineBloc>()
|
||||||
|
.add(AddToThenContainer({
|
||||||
...state.thenItems[index],
|
...state.thenItems[index],
|
||||||
'imagePath': Assets.automation,
|
'imagePath':
|
||||||
'title': state.thenItems[index]['name'],
|
Assets.automation,
|
||||||
|
'title': state
|
||||||
|
.thenItems[index]['name'],
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final result = await DeviceDialogHelper.showDeviceDialog(
|
final result = await DeviceDialogHelper
|
||||||
context, state.thenItems[index],
|
.showDeviceDialog(
|
||||||
removeComparetors: true);
|
context, state.thenItems[index],
|
||||||
|
removeComparetors: true);
|
||||||
|
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
context
|
context.read<RoutineBloc>().add(
|
||||||
.read<RoutineBloc>()
|
AddToThenContainer(
|
||||||
.add(AddToThenContainer(state.thenItems[index]));
|
state.thenItems[index]));
|
||||||
} else if (!['AC', '1G', '2G', '3G']
|
} else if (!['AC', '1G', '2G', '3G']
|
||||||
.contains(state.thenItems[index]['productType'])) {
|
.contains(state.thenItems[index]
|
||||||
context
|
['productType'])) {
|
||||||
.read<RoutineBloc>()
|
context.read<RoutineBloc>().add(
|
||||||
.add(AddToThenContainer(state.thenItems[index]));
|
AddToThenContainer(
|
||||||
|
state.thenItems[index]));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: DraggableCard(
|
child: DraggableCard(
|
||||||
imagePath: state.thenItems[index]['imagePath'] ?? '',
|
imagePath: state.thenItems[index]
|
||||||
title: state.thenItems[index]['title'] ?? '',
|
['imagePath'] ??
|
||||||
|
'',
|
||||||
|
title: state.thenItems[index]
|
||||||
|
['title'] ??
|
||||||
|
'',
|
||||||
deviceData: state.thenItems[index],
|
deviceData: state.thenItems[index],
|
||||||
padding:
|
padding: const EdgeInsets.symmetric(
|
||||||
const EdgeInsets.symmetric(horizontal: 4, vertical: 8),
|
horizontal: 4, vertical: 8),
|
||||||
isFromThen: true,
|
isFromThen: true,
|
||||||
isFromIf: false,
|
isFromIf: false,
|
||||||
onRemove: () {
|
onRemove: () {
|
||||||
context.read<RoutineBloc>().add(RemoveDragCard(
|
context.read<RoutineBloc>().add(
|
||||||
index: index,
|
RemoveDragCard(
|
||||||
isFromThen: true,
|
index: index,
|
||||||
key: state.thenItems[index]['uniqueCustomId']));
|
isFromThen: true,
|
||||||
|
key: state.thenItems[index]
|
||||||
|
['uniqueCustomId']));
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
))),
|
))),
|
||||||
@ -157,7 +183,8 @@ class ThenContainer extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mutableData['deviceId'] == 'delay') {
|
if (mutableData['deviceId'] == 'delay') {
|
||||||
final result = await DelayHelper.showDelayPickerDialog(context, mutableData);
|
final result =
|
||||||
|
await DelayHelper.showDelayPickerDialog(context, mutableData);
|
||||||
|
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
context.read<RoutineBloc>().add(AddToThenContainer({
|
context.read<RoutineBloc>().add(AddToThenContainer({
|
||||||
@ -169,11 +196,13 @@ class ThenContainer extends StatelessWidget {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final result = await DeviceDialogHelper.showDeviceDialog(context, mutableData,
|
final result = await DeviceDialogHelper.showDeviceDialog(
|
||||||
|
context, mutableData,
|
||||||
removeComparetors: true);
|
removeComparetors: true);
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
context.read<RoutineBloc>().add(AddToThenContainer(mutableData));
|
context.read<RoutineBloc>().add(AddToThenContainer(mutableData));
|
||||||
} else if (!['AC', '1G', '2G', '3G'].contains(mutableData['productType'])) {
|
} else if (!['AC', '1G', '2G', '3G']
|
||||||
|
.contains(mutableData['productType'])) {
|
||||||
context.read<RoutineBloc>().add(AddToThenContainer(mutableData));
|
context.read<RoutineBloc>().add(AddToThenContainer(mutableData));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -36,7 +36,6 @@ class SceneApi {
|
|||||||
static Future<Map<String, dynamic>> createAutomation(
|
static Future<Map<String, dynamic>> createAutomation(
|
||||||
CreateAutomationModel createAutomationModel) async {
|
CreateAutomationModel createAutomationModel) async {
|
||||||
try {
|
try {
|
||||||
debugPrint("automation body ${createAutomationModel.toMap()}");
|
|
||||||
final response = await _httpService.post(
|
final response = await _httpService.post(
|
||||||
path: ApiEndpoints.createAutomation,
|
path: ApiEndpoints.createAutomation,
|
||||||
body: createAutomationModel.toMap(),
|
body: createAutomationModel.toMap(),
|
||||||
|
Reference in New Issue
Block a user