mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-10 15:17:31 +00:00
@ -18,13 +18,13 @@ class DeviceManagementPage extends StatelessWidget with HelperResponsiveLayout {
|
||||
Widget build(BuildContext context) {
|
||||
return MultiBlocProvider(
|
||||
providers: [
|
||||
BlocProvider(
|
||||
create: (context) => DeviceManagementBloc()..add(FetchDevices()),
|
||||
),
|
||||
BlocProvider(
|
||||
create: (context) =>
|
||||
SwitchTabsBloc()..add(const TriggerSwitchTabsEvent(false)),
|
||||
),
|
||||
BlocProvider(
|
||||
create: (context) => DeviceManagementBloc()..add(FetchDevices()),
|
||||
),
|
||||
],
|
||||
child: WebScaffold(
|
||||
appBarTitle: FittedBox(
|
||||
@ -101,12 +101,11 @@ class DeviceManagementPage extends StatelessWidget with HelperResponsiveLayout {
|
||||
builder: (context, deviceState) {
|
||||
if (deviceState is DeviceManagementLoading) {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
} else if (deviceState is DeviceManagementLoaded ||
|
||||
deviceState is DeviceManagementFiltered) {
|
||||
final devices = (deviceState as dynamic).devices ??
|
||||
(deviceState as DeviceManagementFiltered).filteredDevices;
|
||||
|
||||
return DeviceManagementBody(devices: devices);
|
||||
} else if (deviceState is DeviceManagementLoaded) {
|
||||
return DeviceManagementBody(devices: deviceState.devices);
|
||||
} else if (deviceState is DeviceManagementFiltered) {
|
||||
return DeviceManagementBody(
|
||||
devices: deviceState.filteredDevices);
|
||||
} else {
|
||||
return const Center(child: Text('Error fetching Devices'));
|
||||
}
|
||||
|
@ -18,14 +18,6 @@ class _DeviceSearchFiltersState extends State<DeviceSearchFilters>
|
||||
final TextEditingController unitNameController = TextEditingController();
|
||||
final TextEditingController productNameController = TextEditingController();
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
communityController.dispose();
|
||||
unitNameController.dispose();
|
||||
productNameController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return isExtraLargeScreenSize(context)
|
||||
|
@ -6,6 +6,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:syncrow_web/pages/routiens/models/create_scene_and_autoamtion/create_automation_model.dart';
|
||||
import 'package:syncrow_web/pages/routiens/models/create_scene_and_autoamtion/create_scene_model.dart';
|
||||
import 'package:syncrow_web/pages/routiens/models/device_functions.dart';
|
||||
import 'package:syncrow_web/pages/routiens/models/routine_details_model.dart';
|
||||
import 'package:syncrow_web/pages/routiens/models/routine_model.dart';
|
||||
import 'package:syncrow_web/services/routines_api.dart';
|
||||
|
||||
@ -13,6 +14,7 @@ part 'routine_event.dart';
|
||||
part 'routine_state.dart';
|
||||
|
||||
const spaceId = '25c96044-fadf-44bb-93c7-3c079e527ce6';
|
||||
const communityId = 'aff21a57-2f91-4e5c-b99b-0182c3ab65a9';
|
||||
|
||||
class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
||||
RoutineBloc() : super(const RoutineState()) {
|
||||
@ -30,6 +32,11 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
||||
on<CreateAutomationEvent>(_onCreateAutomation);
|
||||
on<SetRoutineName>(_onSetRoutineName);
|
||||
on<ResetRoutineState>(_onResetRoutineState);
|
||||
on<GetSceneDetails>(_onGetSceneDetails);
|
||||
on<GetAutomationDetails>(_onGetAutomationDetails);
|
||||
// on<InitializeRoutineState>(_onInitializeRoutineState);
|
||||
on<DeleteScene>(_deleteScene);
|
||||
on<DeleteAutomation>(_deleteAutomation);
|
||||
// on<RemoveFunction>(_onRemoveFunction);
|
||||
// on<ClearFunctions>(_onClearFunctions);
|
||||
}
|
||||
@ -38,8 +45,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
||||
final updatedIfItems = List<Map<String, dynamic>>.from(state.ifItems);
|
||||
|
||||
// Find the index of the item in teh current itemsList
|
||||
int index =
|
||||
updatedIfItems.indexWhere((map) => map['uniqueCustomId'] == event.item['uniqueCustomId']);
|
||||
int index = updatedIfItems.indexWhere(
|
||||
(map) => map['uniqueCustomId'] == event.item['uniqueCustomId']);
|
||||
// Replace the map if the index is valid
|
||||
if (index != -1) {
|
||||
updatedIfItems[index] = event.item;
|
||||
@ -48,18 +55,21 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
||||
}
|
||||
|
||||
if (event.isTabToRun) {
|
||||
emit(state.copyWith(ifItems: updatedIfItems, isTabToRun: true, isAutomation: false));
|
||||
emit(state.copyWith(
|
||||
ifItems: updatedIfItems, isTabToRun: true, isAutomation: false));
|
||||
} 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);
|
||||
|
||||
// Find the index of the item in teh current itemsList
|
||||
int index =
|
||||
currentItems.indexWhere((map) => map['uniqueCustomId'] == event.item['uniqueCustomId']);
|
||||
int index = currentItems.indexWhere(
|
||||
(map) => map['uniqueCustomId'] == event.item['uniqueCustomId']);
|
||||
// Replace the map if the index is valid
|
||||
if (index != -1) {
|
||||
currentItems[index] = event.item;
|
||||
@ -70,22 +80,26 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
||||
emit(state.copyWith(thenItems: currentItems));
|
||||
}
|
||||
|
||||
void _onAddFunctionsToRoutine(AddFunctionToRoutine event, Emitter<RoutineState> emit) {
|
||||
void _onAddFunctionsToRoutine(
|
||||
AddFunctionToRoutine event, Emitter<RoutineState> emit) {
|
||||
try {
|
||||
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>>.from(state.selectedFunctions);
|
||||
if (currentSelectedFunctions.containsKey(event.uniqueCustomId)) {
|
||||
List<DeviceFunctionData> currentFunctions =
|
||||
List<DeviceFunctionData>.from(currentSelectedFunctions[event.uniqueCustomId] ?? []);
|
||||
List<DeviceFunctionData>.from(
|
||||
currentSelectedFunctions[event.uniqueCustomId] ?? []);
|
||||
|
||||
List<String> functionCode = [];
|
||||
for (int i = 0; i < selectedFunction.length; i++) {
|
||||
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];
|
||||
if (!functionCode.contains(currentFunctions[j].functionCode)) {
|
||||
functionCode.add(currentFunctions[j].functionCode);
|
||||
@ -95,13 +109,15 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
||||
}
|
||||
|
||||
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)
|
||||
..addAll(selectedFunction);
|
||||
currentSelectedFunctions[event.uniqueCustomId] =
|
||||
List.from(currentFunctions)..addAll(selectedFunction);
|
||||
} else {
|
||||
currentSelectedFunctions[event.uniqueCustomId] = List.from(event.functions);
|
||||
currentSelectedFunctions[event.uniqueCustomId] =
|
||||
List.from(event.functions);
|
||||
}
|
||||
|
||||
emit(state.copyWith(selectedFunctions: currentSelectedFunctions));
|
||||
@ -110,11 +126,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));
|
||||
|
||||
try {
|
||||
final scenes = await SceneApi.getScenesByUnitId(event.unitId);
|
||||
final scenes =
|
||||
await SceneApi.getScenesByUnitId(event.unitId, event.communityId);
|
||||
emit(state.copyWith(
|
||||
scenes: scenes,
|
||||
isLoading: false,
|
||||
@ -129,7 +147,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));
|
||||
|
||||
try {
|
||||
@ -157,14 +176,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));
|
||||
await Future.delayed(const Duration(seconds: 1));
|
||||
emit(state.copyWith(isLoading: false, errorMessage: null));
|
||||
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));
|
||||
}
|
||||
|
||||
@ -173,7 +194,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
||||
return actions.first['deviceId'] == 'delay';
|
||||
}
|
||||
|
||||
Future<void> _onCreateScene(CreateSceneEvent event, Emitter<RoutineState> emit) async {
|
||||
Future<void> _onCreateScene(
|
||||
CreateSceneEvent event, Emitter<RoutineState> emit) async {
|
||||
try {
|
||||
// Check if first action is delay
|
||||
if (_isFirstActionDelay(state.thenItems)) {
|
||||
@ -233,7 +255,7 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
||||
final result = await SceneApi.createScene(createSceneModel);
|
||||
if (result['success']) {
|
||||
emit(_resetState());
|
||||
add(const LoadScenes(spaceId));
|
||||
add(const LoadScenes(spaceId, communityId));
|
||||
} else {
|
||||
emit(state.copyWith(
|
||||
isLoading: false,
|
||||
@ -248,7 +270,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 {
|
||||
if (state.routineName == null || state.routineName!.isEmpty) {
|
||||
emit(state.copyWith(
|
||||
@ -348,21 +371,34 @@ 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) {
|
||||
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);
|
||||
selectedFunctions.remove(event.key);
|
||||
emit(state.copyWith(thenItems: thenItems, selectedFunctions: selectedFunctions));
|
||||
emit(state.copyWith(
|
||||
thenItems: thenItems, selectedFunctions: selectedFunctions));
|
||||
} else {
|
||||
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);
|
||||
selectedFunctions.remove(event.key);
|
||||
emit(state.copyWith(ifItems: ifItems, selectedFunctions: selectedFunctions));
|
||||
if (ifItems.isEmpty && state.thenItems.isEmpty) {
|
||||
emit(state.copyWith(
|
||||
ifItems: ifItems,
|
||||
selectedFunctions: selectedFunctions,
|
||||
isAutomation: false,
|
||||
isTabToRun: false));
|
||||
} else {
|
||||
emit(state.copyWith(
|
||||
ifItems: ifItems, selectedFunctions: selectedFunctions));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -373,14 +409,134 @@ 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));
|
||||
}
|
||||
|
||||
FutureOr<void> _onSetRoutineName(SetRoutineName event, Emitter<RoutineState> emit) {
|
||||
FutureOr<void> _onSetRoutineName(
|
||||
SetRoutineName event, Emitter<RoutineState> emit) {
|
||||
emit(state.copyWith(routineName: event.name));
|
||||
}
|
||||
|
||||
Future<void> _onGetSceneDetails(
|
||||
GetSceneDetails event, Emitter<RoutineState> emit) async {
|
||||
try {
|
||||
emit(state.copyWith(
|
||||
isLoading: true,
|
||||
isTabToRun: event.isTabToRun,
|
||||
isUpdate: true,
|
||||
sceneId: event.sceneId,
|
||||
isAutomation: false));
|
||||
final sceneDetails = await SceneApi.getSceneDetails(event.sceneId);
|
||||
add(InitializeRoutineState(sceneDetails));
|
||||
} catch (e) {
|
||||
emit(state.copyWith(
|
||||
isLoading: false,
|
||||
errorMessage: 'Failed to load scene details',
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onGetAutomationDetails(
|
||||
GetAutomationDetails event, Emitter<RoutineState> emit) async {
|
||||
try {
|
||||
emit(state.copyWith(
|
||||
isLoading: true,
|
||||
isAutomation: event.isAutomation,
|
||||
automationId: event.automationId,
|
||||
isTabToRun: false,
|
||||
isUpdate: true,
|
||||
));
|
||||
final automationDetails =
|
||||
await SceneApi.getAutomationDetails(event.automationId);
|
||||
add(InitializeRoutineState(automationDetails));
|
||||
} catch (e) {
|
||||
emit(state.copyWith(
|
||||
isLoading: false,
|
||||
errorMessage: 'Failed to load automation details',
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// void _onInitializeRoutineState(
|
||||
// InitializeRoutineState event, Emitter<RoutineState> emit) {
|
||||
// final routineDetails = event.routineDetails;
|
||||
|
||||
// // Convert actions to draggable cards for the THEN container
|
||||
// final thenItems = routineDetails.actions.map((action) {
|
||||
// final Map<String, dynamic> cardData = {
|
||||
// 'entityId': action.entityId,
|
||||
// 'uniqueCustomId': const Uuid().v4(),
|
||||
// 'deviceId':
|
||||
// action.actionExecutor == 'delay' ? 'delay' : action.entityId,
|
||||
// 'title': action.actionExecutor == 'delay' ? 'Delay' : 'Device',
|
||||
// // fix this
|
||||
// 'imagePath':
|
||||
// action.actionExecutor == 'delay' ? Assets.delay : Assets.logo,
|
||||
// };
|
||||
|
||||
// // Add functions to selectedFunctions
|
||||
// if (action.executorProperty != null) {
|
||||
// final functions = <DeviceFunctionData>[
|
||||
// DeviceFunctionData(
|
||||
// entityId: action.entityId,
|
||||
// functionCode: action.executorProperty!.functionCode ?? '',
|
||||
// value: action.executorProperty!.functionValue,
|
||||
|
||||
// /// fix this
|
||||
// operationName: action.executorProperty?.functionCode ?? ''),
|
||||
// ];
|
||||
// state.selectedFunctions[cardData['uniqueCustomId']] = functions;
|
||||
// }
|
||||
|
||||
// return cardData;
|
||||
// }).toList();
|
||||
|
||||
// // Convert conditions to draggable cards for the IF container
|
||||
// final ifItems = routineDetails.conditions?.map((condition) {
|
||||
// final Map<String, dynamic> cardData = {
|
||||
// 'entityId': condition.entityId,
|
||||
// 'uniqueCustomId': const Uuid().v4(),
|
||||
// 'deviceId': condition.entityId,
|
||||
|
||||
// /// fix this
|
||||
// 'title': 'Device',
|
||||
|
||||
// /// fix this
|
||||
// 'imagePath': Assets.logo,
|
||||
// };
|
||||
|
||||
// // Add functions to selectedFunctions
|
||||
// final functions = <DeviceFunctionData>[
|
||||
// DeviceFunctionData(
|
||||
// entityId: condition.entityId,
|
||||
// functionCode: condition.expr.statusCode,
|
||||
// value: condition.expr.statusValue,
|
||||
// condition: condition.expr.comparator,
|
||||
// operationName: condition.expr.comparator,
|
||||
// ),
|
||||
// ];
|
||||
// state.selectedFunctions[cardData['uniqueCustomId']] = functions;
|
||||
|
||||
// return cardData;
|
||||
// }).toList() ??
|
||||
// [];
|
||||
|
||||
// emit(state.copyWith(
|
||||
// isLoading: false,
|
||||
// routineName: routineDetails.name,
|
||||
// selectedIcon: routineDetails.iconId,
|
||||
// selectedAutomationOperator: routineDetails.decisionExpr,
|
||||
// effectiveTime: routineDetails.effectiveTime,
|
||||
// isAutomation: routineDetails.conditions != null,
|
||||
// isTabToRun: routineDetails.conditions == null,
|
||||
// thenItems: thenItems,
|
||||
// ifItems: ifItems,
|
||||
// selectedFunctions: Map.from(state.selectedFunctions),
|
||||
// ));
|
||||
// }
|
||||
|
||||
RoutineState _resetState() {
|
||||
return const RoutineState(
|
||||
ifItems: [],
|
||||
@ -396,13 +552,44 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
||||
selectedIcon: null,
|
||||
isTabToRun: false,
|
||||
isAutomation: false,
|
||||
selectedAutomationOperator: 'AND',
|
||||
selectedAutomationOperator: 'or',
|
||||
effectiveTime: null,
|
||||
routineName: null,
|
||||
);
|
||||
}
|
||||
|
||||
FutureOr<void> _onResetRoutineState(ResetRoutineState event, Emitter<RoutineState> emit) {
|
||||
FutureOr<void> _onResetRoutineState(
|
||||
ResetRoutineState event, Emitter<RoutineState> emit) {
|
||||
emit(_resetState());
|
||||
}
|
||||
|
||||
FutureOr<void> _deleteScene(DeleteScene event, Emitter<RoutineState> emit) {
|
||||
try {
|
||||
// emit(state.copyWith(isLoading: true));
|
||||
SceneApi.deleteScene(unitUuid: spaceId, sceneId: event.sceneId);
|
||||
add(const LoadScenes(spaceId, communityId));
|
||||
//emit(_resetState());
|
||||
} catch (e) {
|
||||
emit(state.copyWith(
|
||||
isLoading: false,
|
||||
errorMessage: 'Failed to delete scene',
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
FutureOr<void> _deleteAutomation(
|
||||
DeleteAutomation event, Emitter<RoutineState> emit) {
|
||||
try {
|
||||
//emit(state.copyWith(isLoading: true));
|
||||
SceneApi.deleteAutomation(
|
||||
unitUuid: spaceId, automationId: event.automationId);
|
||||
add(const LoadAutomation(spaceId));
|
||||
// emit(_resetState());
|
||||
} catch (e) {
|
||||
emit(state.copyWith(
|
||||
isLoading: false,
|
||||
errorMessage: 'Failed to delete automation',
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,11 +28,12 @@ class AddToThenContainer extends RoutineEvent {
|
||||
|
||||
class LoadScenes extends RoutineEvent {
|
||||
final String unitId;
|
||||
final String communityId;
|
||||
|
||||
const LoadScenes(this.unitId);
|
||||
const LoadScenes(this.unitId, this.communityId);
|
||||
|
||||
@override
|
||||
List<Object> get props => [unitId];
|
||||
List<Object> get props => [unitId, communityId];
|
||||
}
|
||||
|
||||
class LoadAutomation extends RoutineEvent {
|
||||
@ -124,6 +125,55 @@ class SetRoutineName extends RoutineEvent {
|
||||
List<Object> get props => [name];
|
||||
}
|
||||
|
||||
class GetSceneDetails extends RoutineEvent {
|
||||
final String sceneId;
|
||||
final bool isUpdate;
|
||||
final bool isTabToRun;
|
||||
const GetSceneDetails({
|
||||
required this.sceneId,
|
||||
required this.isUpdate,
|
||||
required this.isTabToRun,
|
||||
});
|
||||
@override
|
||||
List<Object> get props => [sceneId];
|
||||
}
|
||||
|
||||
class GetAutomationDetails extends RoutineEvent {
|
||||
final String automationId;
|
||||
final bool isUpdate;
|
||||
final bool isAutomation;
|
||||
const GetAutomationDetails({
|
||||
required this.automationId,
|
||||
this.isUpdate = false,
|
||||
this.isAutomation = false,
|
||||
});
|
||||
@override
|
||||
List<Object> get props => [automationId];
|
||||
}
|
||||
|
||||
class InitializeRoutineState extends RoutineEvent {
|
||||
final RoutineDetailsModel routineDetails;
|
||||
const InitializeRoutineState(this.routineDetails);
|
||||
@override
|
||||
List<Object> get props => [routineDetails];
|
||||
}
|
||||
|
||||
class DeleteScene extends RoutineEvent {
|
||||
final String sceneId;
|
||||
final String unitUuid;
|
||||
const DeleteScene({required this.sceneId, required this.unitUuid});
|
||||
@override
|
||||
List<Object> get props => [sceneId];
|
||||
}
|
||||
|
||||
class DeleteAutomation extends RoutineEvent {
|
||||
final String automationId;
|
||||
final String unitUuid;
|
||||
const DeleteAutomation({required this.automationId, required this.unitUuid});
|
||||
@override
|
||||
List<Object> get props => [automationId];
|
||||
}
|
||||
|
||||
class ResetRoutineState extends RoutineEvent {}
|
||||
|
||||
class ClearFunctions extends RoutineEvent {}
|
||||
|
@ -18,6 +18,9 @@ class RoutineState extends Equatable {
|
||||
final bool isAutomation;
|
||||
final String selectedAutomationOperator;
|
||||
final EffectiveTime? effectiveTime;
|
||||
final String? sceneId;
|
||||
final String? automationId;
|
||||
final bool? isUpdate;
|
||||
|
||||
const RoutineState({
|
||||
this.ifItems = const [],
|
||||
@ -37,6 +40,9 @@ class RoutineState extends Equatable {
|
||||
this.isAutomation = false,
|
||||
this.selectedAutomationOperator = 'or',
|
||||
this.effectiveTime,
|
||||
this.sceneId,
|
||||
this.automationId,
|
||||
this.isUpdate,
|
||||
});
|
||||
|
||||
RoutineState copyWith({
|
||||
@ -56,6 +62,9 @@ class RoutineState extends Equatable {
|
||||
bool? isAutomation,
|
||||
String? selectedAutomationOperator,
|
||||
EffectiveTime? effectiveTime,
|
||||
String? sceneId,
|
||||
String? automationId,
|
||||
bool? isUpdate,
|
||||
}) {
|
||||
return RoutineState(
|
||||
ifItems: ifItems ?? this.ifItems,
|
||||
@ -77,6 +86,9 @@ class RoutineState extends Equatable {
|
||||
selectedAutomationOperator:
|
||||
selectedAutomationOperator ?? this.selectedAutomationOperator,
|
||||
effectiveTime: effectiveTime ?? this.effectiveTime,
|
||||
sceneId: sceneId ?? this.sceneId,
|
||||
automationId: automationId ?? this.automationId,
|
||||
isUpdate: isUpdate ?? this.isUpdate,
|
||||
);
|
||||
}
|
||||
|
||||
@ -97,6 +109,9 @@ class RoutineState extends Equatable {
|
||||
isTabToRun,
|
||||
isAutomation,
|
||||
selectedAutomationOperator,
|
||||
effectiveTime
|
||||
effectiveTime,
|
||||
sceneId,
|
||||
automationId,
|
||||
isUpdate
|
||||
];
|
||||
}
|
||||
|
@ -10,8 +10,9 @@ import 'package:syncrow_web/pages/routiens/models/device_functions.dart';
|
||||
class DeviceDialogHelper {
|
||||
static Future<Map<String, dynamic>?> showDeviceDialog(
|
||||
BuildContext context,
|
||||
Map<String, dynamic> data,
|
||||
) async {
|
||||
Map<String, dynamic> data, {
|
||||
required bool removeComparetors,
|
||||
}) async {
|
||||
final functions = data['functions'] as List<DeviceFunction>;
|
||||
|
||||
try {
|
||||
@ -20,6 +21,7 @@ class DeviceDialogHelper {
|
||||
data['productType'],
|
||||
data,
|
||||
functions,
|
||||
removeComparetors: removeComparetors,
|
||||
);
|
||||
|
||||
if (result != null) {
|
||||
@ -37,22 +39,37 @@ class DeviceDialogHelper {
|
||||
String productType,
|
||||
Map<String, dynamic> data,
|
||||
List<DeviceFunction> functions,
|
||||
) async {
|
||||
{required bool removeComparetors}) async {
|
||||
final routineBloc = context.read<RoutineBloc>();
|
||||
final deviceSelectedFunctions =
|
||||
routineBloc.state.selectedFunctions[data['uniqueCustomId']] ?? [];
|
||||
|
||||
switch (productType) {
|
||||
case 'AC':
|
||||
return ACHelper.showACFunctionsDialog(context, functions,
|
||||
data['device'], deviceSelectedFunctions, data['uniqueCustomId']);
|
||||
return ACHelper.showACFunctionsDialog(
|
||||
context,
|
||||
functions,
|
||||
data['device'],
|
||||
deviceSelectedFunctions,
|
||||
data['uniqueCustomId'],
|
||||
removeComparetors);
|
||||
|
||||
case '1G':
|
||||
return OneGangSwitchHelper.showSwitchFunctionsDialog(context, functions,
|
||||
data['device'], deviceSelectedFunctions, data['uniqueCustomId']);
|
||||
return OneGangSwitchHelper.showSwitchFunctionsDialog(
|
||||
context,
|
||||
functions,
|
||||
data['device'],
|
||||
deviceSelectedFunctions,
|
||||
data['uniqueCustomId'],
|
||||
removeComparetors);
|
||||
case '2G':
|
||||
return TwoGangSwitchHelper.showSwitchFunctionsDialog(context, functions,
|
||||
data['device'], deviceSelectedFunctions, data['uniqueCustomId']);
|
||||
return TwoGangSwitchHelper.showSwitchFunctionsDialog(
|
||||
context,
|
||||
functions,
|
||||
data['device'],
|
||||
deviceSelectedFunctions,
|
||||
data['uniqueCustomId'],
|
||||
removeComparetors);
|
||||
case '3G':
|
||||
return ThreeGangSwitchHelper.showSwitchFunctionsDialog(
|
||||
context,
|
||||
@ -60,7 +77,7 @@ class DeviceDialogHelper {
|
||||
data['device'],
|
||||
deviceSelectedFunctions,
|
||||
data['uniqueCustomId'],
|
||||
);
|
||||
removeComparetors);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
@ -8,8 +8,8 @@ import 'package:syncrow_web/utils/color_manager.dart';
|
||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||
|
||||
class SaveRoutineHelper {
|
||||
static Future<void> showSaveRoutineDialog(BuildContext context) async {
|
||||
return showDialog<void>(
|
||||
static Future<bool?> showSaveRoutineDialog(BuildContext context) async {
|
||||
return showDialog<bool?>(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return BlocBuilder<RoutineBloc, RoutineState>(
|
||||
@ -54,27 +54,23 @@ class SaveRoutineHelper {
|
||||
),
|
||||
if (state.isAutomation)
|
||||
...state.ifItems.map((item) {
|
||||
final functions = state.selectedFunctions[
|
||||
item['uniqueCustomId']] ??
|
||||
[];
|
||||
final functions =
|
||||
state.selectedFunctions[item['uniqueCustomId']] ?? [];
|
||||
return ListTile(
|
||||
leading: SvgPicture.asset(
|
||||
item['imagePath'],
|
||||
width: 22,
|
||||
height: 22,
|
||||
),
|
||||
title: Text(item['title'],
|
||||
style: const TextStyle(fontSize: 14)),
|
||||
title:
|
||||
Text(item['title'], style: const TextStyle(fontSize: 14)),
|
||||
subtitle: Wrap(
|
||||
children: functions
|
||||
.map((f) => Text(
|
||||
'${f.operationName}: ${f.value}, ',
|
||||
style: const TextStyle(
|
||||
color: ColorsManager
|
||||
.grayColor,
|
||||
fontSize: 8),
|
||||
overflow:
|
||||
TextOverflow.ellipsis,
|
||||
color: ColorsManager.grayColor, fontSize: 8),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
maxLines: 3,
|
||||
))
|
||||
.toList(),
|
||||
@ -99,25 +95,22 @@ class SaveRoutineHelper {
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
...state.thenItems.map((item) {
|
||||
final functions = state.selectedFunctions[
|
||||
item['uniqueCustomId']] ??
|
||||
[];
|
||||
final functions =
|
||||
state.selectedFunctions[item['uniqueCustomId']] ?? [];
|
||||
return ListTile(
|
||||
leading: SvgPicture.asset(
|
||||
item['imagePath'],
|
||||
width: 22,
|
||||
height: 22,
|
||||
),
|
||||
title: Text(item['title'],
|
||||
style: const TextStyle(fontSize: 14)),
|
||||
title:
|
||||
Text(item['title'], style: const TextStyle(fontSize: 14)),
|
||||
subtitle: Wrap(
|
||||
children: functions
|
||||
.map((f) => Text(
|
||||
'${f.operationName}: ${f.value}, ',
|
||||
style: const TextStyle(
|
||||
color:
|
||||
ColorsManager.grayColor,
|
||||
fontSize: 8),
|
||||
color: ColorsManager.grayColor, fontSize: 8),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
maxLines: 3,
|
||||
))
|
||||
@ -140,19 +133,15 @@ class SaveRoutineHelper {
|
||||
),
|
||||
),
|
||||
DialogFooter(
|
||||
onCancel: () => Navigator.pop(context),
|
||||
onCancel: () => Navigator.pop(context, false),
|
||||
onConfirm: () {
|
||||
if (state.isAutomation) {
|
||||
context
|
||||
.read<RoutineBloc>()
|
||||
.add(const CreateAutomationEvent());
|
||||
context.read<RoutineBloc>().add(const CreateAutomationEvent());
|
||||
} else {
|
||||
context
|
||||
.read<RoutineBloc>()
|
||||
.add(const CreateSceneEvent());
|
||||
context.read<RoutineBloc>().add(const CreateSceneEvent());
|
||||
}
|
||||
|
||||
Navigator.pop(context);
|
||||
Navigator.pop(context, true);
|
||||
},
|
||||
isConfirmEnabled: true,
|
||||
),
|
||||
|
@ -1,177 +1,5 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:syncrow_web/pages/routiens/models/create_scene_and_autoamtion/create_scene_model.dart';
|
||||
|
||||
// class CreateAutomationModel {
|
||||
// String unitUuid;
|
||||
// String automationName;
|
||||
// String decisionExpr;
|
||||
// EffectiveTime effectiveTime;
|
||||
// List<CreateCondition> conditions;
|
||||
// List<CreateSceneAction> actions;
|
||||
|
||||
// CreateAutomationModel({
|
||||
// required this.unitUuid,
|
||||
// required this.automationName,
|
||||
// required this.decisionExpr,
|
||||
// required this.effectiveTime,
|
||||
// required this.conditions,
|
||||
// required this.actions,
|
||||
// });
|
||||
|
||||
// CreateAutomationModel copyWith({
|
||||
// String? unitUuid,
|
||||
// String? automationName,
|
||||
// String? decisionExpr,
|
||||
// EffectiveTime? effectiveTime,
|
||||
// List<CreateCondition>? conditions,
|
||||
// List<CreateSceneAction>? actions,
|
||||
// }) {
|
||||
// return CreateAutomationModel(
|
||||
// unitUuid: unitUuid ?? this.unitUuid,
|
||||
// automationName: automationName ?? this.automationName,
|
||||
// decisionExpr: decisionExpr ?? this.decisionExpr,
|
||||
// effectiveTime: effectiveTime ?? this.effectiveTime,
|
||||
// conditions: conditions ?? this.conditions,
|
||||
// actions: actions ?? this.actions,
|
||||
// );
|
||||
// }
|
||||
|
||||
// Map<String, dynamic> toMap([String? automationId]) {
|
||||
// return {
|
||||
// if (automationId == null) 'spaceUuid': unitUuid,
|
||||
// 'automationName': automationName,
|
||||
// 'decisionExpr': decisionExpr,
|
||||
// 'effectiveTime': effectiveTime.toMap(),
|
||||
// 'conditions': conditions.map((x) => x.toMap()).toList(),
|
||||
// 'actions': actions.map((x) => x.toMap()).toList(),
|
||||
// };
|
||||
// }
|
||||
|
||||
// factory CreateAutomationModel.fromMap(Map<String, dynamic> map) {
|
||||
// return CreateAutomationModel(
|
||||
// unitUuid: map['spaceUuid'] ?? '',
|
||||
// automationName: map['automationName'] ?? '',
|
||||
// decisionExpr: map['decisionExpr'] ?? '',
|
||||
// effectiveTime: EffectiveTime.fromMap(map['effectiveTime']),
|
||||
// conditions: List<CreateCondition>.from(
|
||||
// map['conditions']?.map((x) => CreateCondition.fromMap(x))),
|
||||
// actions: List<CreateSceneAction>.from(
|
||||
// map['actions']?.map((x) => CreateSceneAction.fromMap(x))),
|
||||
// );
|
||||
// }
|
||||
|
||||
// String toJson([String? automationId]) => json.encode(toMap(automationId));
|
||||
|
||||
// factory CreateAutomationModel.fromJson(String source) =>
|
||||
// CreateAutomationModel.fromMap(json.decode(source));
|
||||
|
||||
// @override
|
||||
// String toString() {
|
||||
// return 'CreateAutomationModel(unitUuid: $unitUuid, automationName: $automationName, decisionExpr: $decisionExpr, effectiveTime: $effectiveTime, conditions: $conditions, actions: $actions)';
|
||||
// }
|
||||
// }
|
||||
|
||||
// class EffectiveTime {
|
||||
// String start;
|
||||
// String end;
|
||||
// String loops;
|
||||
|
||||
// EffectiveTime({
|
||||
// required this.start,
|
||||
// required this.end,
|
||||
// required this.loops,
|
||||
// });
|
||||
|
||||
// Map<String, dynamic> toMap() {
|
||||
// return {
|
||||
// 'start': start,
|
||||
// 'end': end,
|
||||
// 'loops': loops,
|
||||
// };
|
||||
// }
|
||||
|
||||
// factory EffectiveTime.fromMap(Map<String, dynamic> map) {
|
||||
// return EffectiveTime(
|
||||
// start: map['start'] ?? '',
|
||||
// end: map['end'] ?? '',
|
||||
// loops: map['loops'] ?? '',
|
||||
// );
|
||||
// }
|
||||
|
||||
// @override
|
||||
// String toString() => 'EffectiveTime(start: $start, end: $end, loops: $loops)';
|
||||
// }
|
||||
|
||||
// class CreateCondition {
|
||||
// int code;
|
||||
// String entityId;
|
||||
// String entityType;
|
||||
// ConditionExpr expr;
|
||||
|
||||
// CreateCondition({
|
||||
// required this.code,
|
||||
// required this.entityId,
|
||||
// required this.entityType,
|
||||
// required this.expr,
|
||||
// });
|
||||
|
||||
// Map<String, dynamic> toMap() {
|
||||
// return {
|
||||
// 'code': code,
|
||||
// 'entityId': entityId,
|
||||
// 'entityType': entityType,
|
||||
// 'expr': expr.toMap(),
|
||||
// };
|
||||
// }
|
||||
|
||||
// factory CreateCondition.fromMap(Map<String, dynamic> map) {
|
||||
// return CreateCondition(
|
||||
// code: map['code'] ?? 0,
|
||||
// entityId: map['entityId'] ?? '',
|
||||
// entityType: map['entityType'] ?? '',
|
||||
// expr: ConditionExpr.fromMap(map['expr']),
|
||||
// );
|
||||
// }
|
||||
|
||||
// @override
|
||||
// String toString() =>
|
||||
// 'CreateCondition(code: $code, entityId: $entityId, entityType: $entityType, expr: $expr)';
|
||||
// }
|
||||
|
||||
// class ConditionExpr {
|
||||
// String statusCode;
|
||||
// String comparator;
|
||||
// dynamic statusValue;
|
||||
|
||||
// ConditionExpr({
|
||||
// required this.statusCode,
|
||||
// required this.comparator,
|
||||
// required this.statusValue,
|
||||
// });
|
||||
|
||||
// Map<String, dynamic> toMap() {
|
||||
// return {
|
||||
// 'statusCode': statusCode,
|
||||
// 'comparator': comparator,
|
||||
// 'statusValue': statusValue,
|
||||
// };
|
||||
// }
|
||||
|
||||
// factory ConditionExpr.fromMap(Map<String, dynamic> map) {
|
||||
// return ConditionExpr(
|
||||
// statusCode: map['statusCode'] ?? '',
|
||||
// comparator: map['comparator'] ?? '',
|
||||
// statusValue: map['statusValue'],
|
||||
// );
|
||||
// }
|
||||
|
||||
// @override
|
||||
// String toString() =>
|
||||
// 'ConditionExpr(statusCode: $statusCode, comparator: $comparator, statusValue: $statusValue)';
|
||||
// }
|
||||
import 'dart:convert';
|
||||
|
||||
class CreateAutomationModel {
|
||||
String spaceUuid;
|
||||
String automationName;
|
||||
|
262
lib/pages/routiens/models/routine_details_model.dart
Normal file
262
lib/pages/routiens/models/routine_details_model.dart
Normal file
@ -0,0 +1,262 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:syncrow_web/pages/routiens/models/create_scene_and_autoamtion/create_automation_model.dart';
|
||||
import 'package:syncrow_web/pages/routiens/models/create_scene_and_autoamtion/create_scene_model.dart';
|
||||
|
||||
class RoutineDetailsModel {
|
||||
final String spaceUuid;
|
||||
final String name;
|
||||
final String decisionExpr;
|
||||
final List<RoutineAction> actions;
|
||||
final String? iconId;
|
||||
final bool? showInDevice;
|
||||
final EffectiveTime? effectiveTime;
|
||||
final List<RoutineCondition>? conditions;
|
||||
final String? type;
|
||||
|
||||
RoutineDetailsModel({
|
||||
required this.spaceUuid,
|
||||
required this.name,
|
||||
required this.decisionExpr,
|
||||
required this.actions,
|
||||
this.iconId,
|
||||
this.showInDevice,
|
||||
this.effectiveTime,
|
||||
this.conditions,
|
||||
this.type,
|
||||
});
|
||||
|
||||
// Convert to CreateSceneModel
|
||||
CreateSceneModel toCreateSceneModel() {
|
||||
return CreateSceneModel(
|
||||
spaceUuid: spaceUuid,
|
||||
iconId: iconId ?? '',
|
||||
showInDevice: showInDevice ?? false,
|
||||
sceneName: name,
|
||||
decisionExpr: decisionExpr,
|
||||
actions: actions.map((a) => a.toCreateSceneAction()).toList(),
|
||||
);
|
||||
}
|
||||
|
||||
// Convert to CreateAutomationModel
|
||||
CreateAutomationModel toCreateAutomationModel() {
|
||||
return CreateAutomationModel(
|
||||
spaceUuid: spaceUuid,
|
||||
automationName: name,
|
||||
decisionExpr: decisionExpr,
|
||||
effectiveTime:
|
||||
effectiveTime ?? EffectiveTime(start: '', end: '', loops: ''),
|
||||
conditions: conditions?.map((c) => c.toCondition()).toList() ?? [],
|
||||
actions: actions.map((a) => a.toAutomationAction()).toList(),
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
'spaceUuid': spaceUuid,
|
||||
'name': name,
|
||||
'decisionExpr': decisionExpr,
|
||||
'actions': actions.map((x) => x.toMap()).toList(),
|
||||
if (iconId != null) 'iconId': iconId,
|
||||
if (showInDevice != null) 'showInDevice': showInDevice,
|
||||
if (effectiveTime != null) 'effectiveTime': effectiveTime!.toMap(),
|
||||
if (conditions != null)
|
||||
'conditions': conditions!.map((x) => x.toMap()).toList(),
|
||||
if (type != null) 'type': type,
|
||||
};
|
||||
}
|
||||
|
||||
factory RoutineDetailsModel.fromMap(Map<String, dynamic> map) {
|
||||
return RoutineDetailsModel(
|
||||
spaceUuid: map['spaceUuid'] ?? '',
|
||||
name: map['name'] ?? '',
|
||||
decisionExpr: map['decisionExpr'] ?? '',
|
||||
actions: List<RoutineAction>.from(
|
||||
map['actions']?.map((x) => RoutineAction.fromMap(x)) ?? [],
|
||||
),
|
||||
iconId: map['iconId'],
|
||||
showInDevice: map['showInDevice'],
|
||||
effectiveTime: map['effectiveTime'] != null
|
||||
? EffectiveTime.fromMap(map['effectiveTime'])
|
||||
: null,
|
||||
conditions: map['conditions'] != null
|
||||
? List<RoutineCondition>.from(
|
||||
map['conditions'].map((x) => RoutineCondition.fromMap(x)))
|
||||
: null,
|
||||
type: map['type'],
|
||||
);
|
||||
}
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
factory RoutineDetailsModel.fromJson(String source) =>
|
||||
RoutineDetailsModel.fromMap(json.decode(source));
|
||||
}
|
||||
|
||||
class RoutineAction {
|
||||
final String entityId;
|
||||
final String actionExecutor;
|
||||
final RoutineExecutorProperty? executorProperty;
|
||||
|
||||
RoutineAction({
|
||||
required this.entityId,
|
||||
required this.actionExecutor,
|
||||
this.executorProperty,
|
||||
});
|
||||
|
||||
CreateSceneAction toCreateSceneAction() {
|
||||
return CreateSceneAction(
|
||||
entityId: entityId,
|
||||
actionExecutor: actionExecutor,
|
||||
executorProperty: executorProperty?.toCreateSceneExecutorProperty(),
|
||||
);
|
||||
}
|
||||
|
||||
AutomationAction toAutomationAction() {
|
||||
return AutomationAction(
|
||||
entityId: entityId,
|
||||
actionExecutor: actionExecutor,
|
||||
executorProperty: executorProperty?.toExecutorProperty(),
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
'entityId': entityId,
|
||||
'actionExecutor': actionExecutor,
|
||||
if (executorProperty != null)
|
||||
'executorProperty': executorProperty!.toMap(),
|
||||
};
|
||||
}
|
||||
|
||||
factory RoutineAction.fromMap(Map<String, dynamic> map) {
|
||||
return RoutineAction(
|
||||
entityId: map['entityId'] ?? '',
|
||||
actionExecutor: map['actionExecutor'] ?? '',
|
||||
executorProperty: map['executorProperty'] != null
|
||||
? RoutineExecutorProperty.fromMap(map['executorProperty'])
|
||||
: null,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class RoutineExecutorProperty {
|
||||
final String? functionCode;
|
||||
final dynamic functionValue;
|
||||
final int? delaySeconds;
|
||||
|
||||
RoutineExecutorProperty({
|
||||
this.functionCode,
|
||||
this.functionValue,
|
||||
this.delaySeconds,
|
||||
});
|
||||
|
||||
CreateSceneExecutorProperty toCreateSceneExecutorProperty() {
|
||||
return CreateSceneExecutorProperty(
|
||||
functionCode: functionCode ?? '',
|
||||
functionValue: functionValue,
|
||||
delaySeconds: delaySeconds ?? 0,
|
||||
);
|
||||
}
|
||||
|
||||
ExecutorProperty toExecutorProperty() {
|
||||
return ExecutorProperty(
|
||||
functionCode: functionCode,
|
||||
functionValue: functionValue,
|
||||
delaySeconds: delaySeconds,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
if (functionCode != null) 'functionCode': functionCode,
|
||||
if (functionValue != null) 'functionValue': functionValue,
|
||||
if (delaySeconds != null) 'delaySeconds': delaySeconds,
|
||||
};
|
||||
}
|
||||
|
||||
factory RoutineExecutorProperty.fromMap(Map<String, dynamic> map) {
|
||||
return RoutineExecutorProperty(
|
||||
functionCode: map['functionCode'],
|
||||
functionValue: map['functionValue'],
|
||||
delaySeconds: map['delaySeconds']?.toInt(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class RoutineCondition {
|
||||
final int code;
|
||||
final String entityId;
|
||||
final String entityType;
|
||||
final RoutineConditionExpr expr;
|
||||
|
||||
RoutineCondition({
|
||||
required this.code,
|
||||
required this.entityId,
|
||||
required this.entityType,
|
||||
required this.expr,
|
||||
});
|
||||
|
||||
Condition toCondition() {
|
||||
return Condition(
|
||||
code: code,
|
||||
entityId: entityId,
|
||||
entityType: entityType,
|
||||
expr: expr.toConditionExpr(),
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
'code': code,
|
||||
'entityId': entityId,
|
||||
'entityType': entityType,
|
||||
'expr': expr.toMap(),
|
||||
};
|
||||
}
|
||||
|
||||
factory RoutineCondition.fromMap(Map<String, dynamic> map) {
|
||||
return RoutineCondition(
|
||||
code: map['code']?.toInt() ?? 0,
|
||||
entityId: map['entityId'] ?? '',
|
||||
entityType: map['entityType'] ?? '',
|
||||
expr: RoutineConditionExpr.fromMap(map['expr']),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class RoutineConditionExpr {
|
||||
final String statusCode;
|
||||
final String comparator;
|
||||
final dynamic statusValue;
|
||||
|
||||
RoutineConditionExpr({
|
||||
required this.statusCode,
|
||||
required this.comparator,
|
||||
required this.statusValue,
|
||||
});
|
||||
|
||||
ConditionExpr toConditionExpr() {
|
||||
return ConditionExpr(
|
||||
statusCode: statusCode,
|
||||
comparator: comparator,
|
||||
statusValue: statusValue,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
'statusCode': statusCode,
|
||||
'comparator': comparator,
|
||||
'statusValue': statusValue,
|
||||
};
|
||||
}
|
||||
|
||||
factory RoutineConditionExpr.fromMap(Map<String, dynamic> map) {
|
||||
return RoutineConditionExpr(
|
||||
statusCode: map['statusCode'] ?? '',
|
||||
comparator: map['comparator'] ?? '',
|
||||
statusValue: map['statusValue'],
|
||||
);
|
||||
}
|
||||
}
|
@ -1,7 +1,10 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||
|
||||
class ScenesModel {
|
||||
final String id;
|
||||
final String? sceneTuyaId;
|
||||
final String name;
|
||||
final String status;
|
||||
final String type;
|
||||
@ -9,26 +12,43 @@ class ScenesModel {
|
||||
|
||||
ScenesModel({
|
||||
required this.id,
|
||||
this.sceneTuyaId,
|
||||
required this.name,
|
||||
required this.status,
|
||||
required this.type,
|
||||
this.icon,
|
||||
});
|
||||
|
||||
factory ScenesModel.fromRawJson(String str) =>
|
||||
ScenesModel.fromJson(json.decode(str));
|
||||
|
||||
String toRawJson() => json.encode(toJson());
|
||||
|
||||
Uint8List? get iconInBytes {
|
||||
if (icon == null || icon?.isEmpty == true) return null;
|
||||
try {
|
||||
return base64Decode(icon!);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
factory ScenesModel.fromJson(Map<String, dynamic> json,
|
||||
{bool? isAutomation}) =>
|
||||
ScenesModel(
|
||||
id: json["id"],
|
||||
{bool? isAutomation}) {
|
||||
return ScenesModel(
|
||||
id: json["id"] ?? json["uuid"] ?? '',
|
||||
sceneTuyaId: json["sceneTuyaId"] as String?,
|
||||
name: json["name"] ?? '',
|
||||
status: json["status"] ?? '',
|
||||
type: json["type"] ?? '',
|
||||
icon: (isAutomation ?? false)
|
||||
? Assets.automation
|
||||
: json["icon"] as String?,
|
||||
icon:
|
||||
isAutomation == true ? Assets.automation : (json["icon"] as String?),
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
"id": id,
|
||||
"sceneTuyaId": sceneTuyaId ?? '',
|
||||
"name": name,
|
||||
"status": status,
|
||||
"type": type,
|
||||
|
@ -6,8 +6,16 @@ import 'package:syncrow_web/pages/routiens/widgets/then_container.dart';
|
||||
import 'package:syncrow_web/utils/color_manager.dart';
|
||||
|
||||
class CreateNewRoutineView extends StatelessWidget {
|
||||
const CreateNewRoutineView({super.key});
|
||||
final bool isUpdate;
|
||||
final String? routineId;
|
||||
final bool isScene;
|
||||
|
||||
const CreateNewRoutineView({
|
||||
super.key,
|
||||
this.isUpdate = false,
|
||||
this.routineId,
|
||||
this.isScene = true,
|
||||
});
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
|
@ -1,7 +1,10 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/all_devices/bloc/switch_tabs/switch_tabs_bloc.dart';
|
||||
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart';
|
||||
import 'package:syncrow_web/pages/routiens/view/create_new_routine_view.dart';
|
||||
import 'package:syncrow_web/pages/routiens/widgets/main_routine_view/fetch_routine_scenes_automation.dart';
|
||||
import 'package:syncrow_web/pages/routiens/widgets/main_routine_view/routine_view_card.dart';
|
||||
import 'package:syncrow_web/utils/color_manager.dart';
|
||||
|
||||
class RoutinesView extends StatelessWidget {
|
||||
@ -23,49 +26,30 @@ class RoutinesView extends StatelessWidget {
|
||||
children: [
|
||||
Text(
|
||||
"Create New Routines",
|
||||
style: Theme.of(context).textTheme.titleMedium?.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
style: Theme.of(context).textTheme.titleLarge?.copyWith(
|
||||
color: ColorsManager.grayColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 200,
|
||||
width: 150,
|
||||
child: GestureDetector(
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
RoutineViewCard(
|
||||
onTap: () {
|
||||
BlocProvider.of<SwitchTabsBloc>(context).add(
|
||||
const CreateNewRoutineViewEvent(true),
|
||||
);
|
||||
context.read<RoutineBloc>().add(
|
||||
(ResetRoutineState()),
|
||||
);
|
||||
},
|
||||
child: Card(
|
||||
elevation: 3,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
icon: Icons.add,
|
||||
textString: '',
|
||||
),
|
||||
color: ColorsManager.whiteColors,
|
||||
child: Center(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: ColorsManager.graysColor,
|
||||
borderRadius: BorderRadius.circular(120),
|
||||
border: Border.all(
|
||||
color: ColorsManager.greyColor,
|
||||
width: 2.0,
|
||||
const SizedBox(
|
||||
height: 15,
|
||||
),
|
||||
),
|
||||
height: 70,
|
||||
width: 70,
|
||||
child: Icon(
|
||||
Icons.add,
|
||||
color: ColorsManager.dialogBlueTitle,
|
||||
size: 40,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
const Expanded(child: FetchRoutineScenesAutomation()),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
@ -1,3 +1,5 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
@ -81,7 +83,9 @@ class DraggableCard extends StatelessWidget {
|
||||
? SvgPicture.asset(
|
||||
imagePath,
|
||||
)
|
||||
: Image.network(imagePath),
|
||||
: Image.memory(
|
||||
base64Decode(imagePath),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Padding(
|
||||
|
@ -26,8 +26,10 @@ class IfContainer extends StatelessWidget {
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Text('IF', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
|
||||
if (state.isAutomation)
|
||||
const Text('IF',
|
||||
style: TextStyle(
|
||||
fontSize: 18, fontWeight: FontWeight.bold)),
|
||||
if (state.isAutomation && state.ifItems.isNotEmpty)
|
||||
AutomationOperatorSelector(
|
||||
selectedOperator: state.selectedAutomationOperator),
|
||||
],
|
||||
@ -53,33 +55,44 @@ class IfContainer extends StatelessWidget {
|
||||
(index) => GestureDetector(
|
||||
onTap: () async {
|
||||
if (!state.isTabToRun) {
|
||||
final result = await DeviceDialogHelper.showDeviceDialog(
|
||||
context, state.ifItems[index]);
|
||||
final result = await DeviceDialogHelper
|
||||
.showDeviceDialog(
|
||||
context, state.ifItems[index],
|
||||
removeComparetors: false);
|
||||
|
||||
if (result != null) {
|
||||
context
|
||||
.read<RoutineBloc>()
|
||||
.add(AddToIfContainer(state.ifItems[index], false));
|
||||
} else if (!['AC', '1G', '2G', '3G']
|
||||
.contains(state.ifItems[index]['productType'])) {
|
||||
context
|
||||
.read<RoutineBloc>()
|
||||
.add(AddToIfContainer(state.ifItems[index], false));
|
||||
context.read<RoutineBloc>().add(
|
||||
AddToIfContainer(
|
||||
state.ifItems[index], false));
|
||||
} else if (![
|
||||
'AC',
|
||||
'1G',
|
||||
'2G',
|
||||
'3G'
|
||||
].contains(
|
||||
state.ifItems[index]['productType'])) {
|
||||
context.read<RoutineBloc>().add(
|
||||
AddToIfContainer(
|
||||
state.ifItems[index], false));
|
||||
}
|
||||
}
|
||||
},
|
||||
child: DraggableCard(
|
||||
imagePath: state.ifItems[index]['imagePath'] ?? '',
|
||||
imagePath:
|
||||
state.ifItems[index]['imagePath'] ?? '',
|
||||
title: state.ifItems[index]['title'] ?? '',
|
||||
deviceData: state.ifItems[index],
|
||||
padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 8),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 4, vertical: 8),
|
||||
isFromThen: false,
|
||||
isFromIf: true,
|
||||
onRemove: () {
|
||||
context.read<RoutineBloc>().add(RemoveDragCard(
|
||||
context.read<RoutineBloc>().add(
|
||||
RemoveDragCard(
|
||||
index: index,
|
||||
isFromThen: false,
|
||||
key: state.ifItems[index]['uniqueCustomId']));
|
||||
key: state.ifItems[index]
|
||||
['uniqueCustomId']));
|
||||
},
|
||||
),
|
||||
)),
|
||||
@ -88,23 +101,35 @@ class IfContainer extends StatelessWidget {
|
||||
),
|
||||
);
|
||||
},
|
||||
onWillAccept: (data) => data != null,
|
||||
onAccept: (data) async {
|
||||
onAcceptWithDetails: (data) async {
|
||||
final uniqueCustomId = const Uuid().v4();
|
||||
|
||||
final mutableData = Map<String, dynamic>.from(data);
|
||||
final mutableData = Map<String, dynamic>.from(data.data);
|
||||
mutableData['uniqueCustomId'] = uniqueCustomId;
|
||||
|
||||
if (state.isAutomation && mutableData['deviceId'] == 'tab_to_run') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!state.isTabToRun) {
|
||||
if (mutableData['deviceId'] == 'tab_to_run') {
|
||||
context.read<RoutineBloc>().add(AddToIfContainer(mutableData, true));
|
||||
context
|
||||
.read<RoutineBloc>()
|
||||
.add(AddToIfContainer(mutableData, true));
|
||||
} else {
|
||||
final result = await DeviceDialogHelper.showDeviceDialog(context, mutableData);
|
||||
final result = await DeviceDialogHelper.showDeviceDialog(
|
||||
context, mutableData,
|
||||
removeComparetors: false);
|
||||
|
||||
if (result != null) {
|
||||
context.read<RoutineBloc>().add(AddToIfContainer(mutableData, false));
|
||||
} else if (!['AC', '1G', '2G', '3G'].contains(mutableData['productType'])) {
|
||||
context.read<RoutineBloc>().add(AddToIfContainer(mutableData, false));
|
||||
context
|
||||
.read<RoutineBloc>()
|
||||
.add(AddToIfContainer(mutableData, false));
|
||||
} else if (!['AC', '1G', '2G', '3G']
|
||||
.contains(mutableData['productType'])) {
|
||||
context
|
||||
.read<RoutineBloc>()
|
||||
.add(AddToIfContainer(mutableData, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -134,7 +159,7 @@ class AutomationOperatorSelector extends StatelessWidget {
|
||||
children: [
|
||||
TextButton(
|
||||
style: TextButton.styleFrom(
|
||||
backgroundColor: selectedOperator == 'or'
|
||||
backgroundColor: selectedOperator.toLowerCase() == 'or'
|
||||
? ColorsManager.dialogBlueTitle
|
||||
: ColorsManager.whiteColors,
|
||||
shape: RoundedRectangleBorder(
|
||||
@ -144,12 +169,15 @@ class AutomationOperatorSelector extends StatelessWidget {
|
||||
child: Text(
|
||||
'Any condition is met',
|
||||
style: context.textTheme.bodyMedium?.copyWith(
|
||||
color:
|
||||
selectedOperator == 'or' ? ColorsManager.whiteColors : ColorsManager.blackColor,
|
||||
color: selectedOperator.toLowerCase() == 'or'
|
||||
? ColorsManager.whiteColors
|
||||
: ColorsManager.blackColor,
|
||||
),
|
||||
),
|
||||
onPressed: () {
|
||||
context.read<RoutineBloc>().add(const ChangeAutomationOperator(operator: 'or'));
|
||||
context
|
||||
.read<RoutineBloc>()
|
||||
.add(const ChangeAutomationOperator(operator: 'or'));
|
||||
},
|
||||
),
|
||||
Container(
|
||||
@ -159,7 +187,7 @@ class AutomationOperatorSelector extends StatelessWidget {
|
||||
),
|
||||
TextButton(
|
||||
style: TextButton.styleFrom(
|
||||
backgroundColor: selectedOperator == 'and'
|
||||
backgroundColor: selectedOperator.toLowerCase() == 'and'
|
||||
? ColorsManager.dialogBlueTitle
|
||||
: ColorsManager.whiteColors,
|
||||
shape: RoundedRectangleBorder(
|
||||
@ -169,13 +197,15 @@ class AutomationOperatorSelector extends StatelessWidget {
|
||||
child: Text(
|
||||
'All condition is met',
|
||||
style: context.textTheme.bodyMedium?.copyWith(
|
||||
color: selectedOperator == 'and'
|
||||
color: selectedOperator.toLowerCase() == 'and'
|
||||
? ColorsManager.whiteColors
|
||||
: ColorsManager.blackColor,
|
||||
),
|
||||
),
|
||||
onPressed: () {
|
||||
context.read<RoutineBloc>().add(const ChangeAutomationOperator(operator: 'and'));
|
||||
context
|
||||
.read<RoutineBloc>()
|
||||
.add(const ChangeAutomationOperator(operator: 'and'));
|
||||
},
|
||||
),
|
||||
],
|
||||
|
@ -0,0 +1,196 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart';
|
||||
import 'package:syncrow_web/pages/routiens/widgets/main_routine_view/routine_view_card.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/helpers/responsice_layout_helper/responsive_layout_helper.dart';
|
||||
|
||||
class FetchRoutineScenesAutomation extends StatefulWidget {
|
||||
const FetchRoutineScenesAutomation({super.key});
|
||||
|
||||
@override
|
||||
State<FetchRoutineScenesAutomation> createState() =>
|
||||
_FetchRoutineScenesState();
|
||||
}
|
||||
|
||||
class _FetchRoutineScenesState extends State<FetchRoutineScenesAutomation>
|
||||
with HelperResponsiveLayout {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
context.read<RoutineBloc>()
|
||||
..add(const LoadScenes(spaceId, communityId))
|
||||
..add(const LoadAutomation(spaceId));
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<RoutineBloc, RoutineState>(
|
||||
builder: (context, state) {
|
||||
return state.isLoading
|
||||
? const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
)
|
||||
: SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
"Scenes (Tab to Run)",
|
||||
style: Theme.of(context).textTheme.titleLarge?.copyWith(
|
||||
color: ColorsManager.grayColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
if (state.scenes.isEmpty)
|
||||
Text(
|
||||
"No scenes found",
|
||||
style: context.textTheme.bodyMedium?.copyWith(
|
||||
color: ColorsManager.grayColor,
|
||||
),
|
||||
),
|
||||
if (state.scenes.isNotEmpty)
|
||||
ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
maxHeight: isSmallScreenSize(context) ? 160 : 170,
|
||||
),
|
||||
child: ListView.builder(
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemCount: state.scenes.length,
|
||||
itemBuilder: (context, index) => Padding(
|
||||
padding: EdgeInsets.only(
|
||||
right: isSmallScreenSize(context) ? 4.0 : 8.0,
|
||||
),
|
||||
child: Stack(
|
||||
children: [
|
||||
RoutineViewCard(
|
||||
onTap: () {},
|
||||
textString: state.scenes[index].name,
|
||||
icon: state.scenes[index].icon ??
|
||||
Assets.logoHorizontal,
|
||||
isFromScenes: true,
|
||||
iconInBytes:
|
||||
state.scenes[index].iconInBytes,
|
||||
),
|
||||
Positioned(
|
||||
top: 0,
|
||||
right: 0,
|
||||
child: InkWell(
|
||||
onTap: () => context
|
||||
.read<RoutineBloc>()
|
||||
.add(
|
||||
DeleteScene(
|
||||
sceneId: state.scenes[index].id,
|
||||
unitUuid: spaceId,
|
||||
),
|
||||
),
|
||||
child: Container(
|
||||
height: 20,
|
||||
width: 20,
|
||||
decoration: BoxDecoration(
|
||||
color: ColorsManager.whiteColors,
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(
|
||||
color: ColorsManager.grayColor,
|
||||
width: 2.0,
|
||||
),
|
||||
),
|
||||
child: const Center(
|
||||
child: Icon(Icons.delete,
|
||||
size: 15,
|
||||
color: ColorsManager.grayColor),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
Text(
|
||||
"Automations",
|
||||
style: Theme.of(context).textTheme.titleLarge?.copyWith(
|
||||
color: ColorsManager.grayColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
if (state.automations.isEmpty)
|
||||
Text(
|
||||
"No automations found",
|
||||
style: context.textTheme.bodyMedium?.copyWith(
|
||||
color: ColorsManager.grayColor,
|
||||
),
|
||||
),
|
||||
if (state.automations.isNotEmpty)
|
||||
ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
maxHeight: isSmallScreenSize(context) ? 160 : 170,
|
||||
),
|
||||
child: ListView.builder(
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemCount: state.automations.length,
|
||||
itemBuilder: (context, index) => Padding(
|
||||
padding: EdgeInsets.only(
|
||||
right: isSmallScreenSize(context) ? 4.0 : 8.0,
|
||||
),
|
||||
child: Stack(
|
||||
children: [
|
||||
RoutineViewCard(
|
||||
onTap: () {},
|
||||
textString: state.automations[index].name,
|
||||
icon: state.automations[index].icon ??
|
||||
Assets.automation,
|
||||
),
|
||||
Positioned(
|
||||
top: 0,
|
||||
right: 0,
|
||||
child: InkWell(
|
||||
onTap: () =>
|
||||
context.read<RoutineBloc>().add(
|
||||
DeleteAutomation(
|
||||
automationId: state
|
||||
.automations[index].id,
|
||||
unitUuid: spaceId,
|
||||
),
|
||||
),
|
||||
child: Container(
|
||||
height: 20,
|
||||
width: 20,
|
||||
decoration: BoxDecoration(
|
||||
color: ColorsManager.whiteColors,
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(
|
||||
color: ColorsManager.grayColor,
|
||||
width: 2.0,
|
||||
),
|
||||
),
|
||||
child: const Center(
|
||||
child: Icon(Icons.delete,
|
||||
size: 15,
|
||||
color: ColorsManager.grayColor),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,127 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_svg/flutter_svg.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/helpers/responsice_layout_helper/responsive_layout_helper.dart';
|
||||
|
||||
class RoutineViewCard extends StatelessWidget with HelperResponsiveLayout {
|
||||
const RoutineViewCard({
|
||||
super.key,
|
||||
required this.onTap,
|
||||
required this.icon,
|
||||
required this.textString,
|
||||
this.isFromScenes,
|
||||
this.iconInBytes,
|
||||
});
|
||||
|
||||
final Function() onTap;
|
||||
final dynamic icon;
|
||||
final String textString;
|
||||
final bool? isFromScenes;
|
||||
final Uint8List? iconInBytes;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final double cardWidth = isSmallScreenSize(context)
|
||||
? 120
|
||||
: isMediumScreenSize(context)
|
||||
? 135
|
||||
: 150;
|
||||
|
||||
final double cardHeight = isSmallScreenSize(context) ? 160 : 170;
|
||||
|
||||
final double iconSize = isSmallScreenSize(context)
|
||||
? 50
|
||||
: isMediumScreenSize(context)
|
||||
? 60
|
||||
: 70;
|
||||
|
||||
return ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
maxWidth: cardWidth,
|
||||
maxHeight: cardHeight,
|
||||
),
|
||||
child: Card(
|
||||
elevation: 3,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
color: ColorsManager.whiteColors,
|
||||
child: InkWell(
|
||||
onTap: onTap,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
Center(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: ColorsManager.graysColor,
|
||||
borderRadius: BorderRadius.circular(120),
|
||||
border: Border.all(
|
||||
color: ColorsManager.greyColor,
|
||||
width: 2.0,
|
||||
),
|
||||
),
|
||||
height: iconSize,
|
||||
width: iconSize,
|
||||
child: (isFromScenes ?? false)
|
||||
? (iconInBytes != null &&
|
||||
iconInBytes?.isNotEmpty == true)
|
||||
? Image.memory(
|
||||
iconInBytes!,
|
||||
height: iconSize,
|
||||
width: iconSize,
|
||||
fit: BoxFit.contain,
|
||||
errorBuilder: (context, error, stackTrace) =>
|
||||
Image.asset(
|
||||
Assets.logo,
|
||||
height: iconSize,
|
||||
width: iconSize,
|
||||
fit: BoxFit.contain,
|
||||
),
|
||||
)
|
||||
: Image.asset(
|
||||
Assets.logo,
|
||||
height: iconSize,
|
||||
width: iconSize,
|
||||
fit: BoxFit.contain,
|
||||
)
|
||||
: (icon is String && icon.endsWith('.svg'))
|
||||
? SvgPicture.asset(
|
||||
icon,
|
||||
fit: BoxFit.contain,
|
||||
)
|
||||
: Icon(
|
||||
icon,
|
||||
color: ColorsManager.dialogBlueTitle,
|
||||
size: isSmallScreenSize(context) ? 30 : 40,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 3),
|
||||
child: Text(
|
||||
textString,
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
maxLines: 2,
|
||||
style: context.textTheme.bodySmall?.copyWith(
|
||||
color: ColorsManager.blackColor,
|
||||
fontSize: isSmallScreenSize(context) ? 10 : 12,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -75,7 +75,11 @@ class PeriodOptions extends StatelessWidget {
|
||||
onTap: () {
|
||||
context.read<EffectPeriodBloc>().add(SetPeriod(value));
|
||||
},
|
||||
title: Text(EffectPeriodHelper.formatEnumValue(value)),
|
||||
title: Text(
|
||||
EffectPeriodHelper.formatEnumValue(value),
|
||||
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
||||
color: ColorsManager.blackColor, fontWeight: FontWeight.w400, fontSize: 12),
|
||||
),
|
||||
subtitle: Text(
|
||||
subtitle,
|
||||
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
||||
|
@ -19,6 +19,7 @@ class ACHelper {
|
||||
AllDevicesModel? device,
|
||||
List<DeviceFunctionData>? deviceSelectedFunctions,
|
||||
String uniqueCustomId,
|
||||
bool? removeComparetors,
|
||||
) async {
|
||||
List<ACFunction> acFunctions = functions.whereType<ACFunction>().toList();
|
||||
|
||||
@ -84,6 +85,7 @@ class ACHelper {
|
||||
acFunctions: acFunctions,
|
||||
device: device,
|
||||
operationName: selectedOperationName ?? '',
|
||||
removeComparators: removeComparetors,
|
||||
),
|
||||
),
|
||||
],
|
||||
@ -179,6 +181,7 @@ class ACHelper {
|
||||
required List<ACFunction> acFunctions,
|
||||
AllDevicesModel? device,
|
||||
required String operationName,
|
||||
bool? removeComparators,
|
||||
}) {
|
||||
if (selectedFunction == 'temp_set' || selectedFunction == 'temp_current') {
|
||||
final initialValue = selectedFunctionData?.value ?? 200;
|
||||
@ -190,6 +193,7 @@ class ACHelper {
|
||||
device: device,
|
||||
operationName: operationName,
|
||||
selectedFunctionData: selectedFunctionData,
|
||||
removeComparators: removeComparators,
|
||||
);
|
||||
}
|
||||
|
||||
@ -217,10 +221,12 @@ class ACHelper {
|
||||
AllDevicesModel? device,
|
||||
required String operationName,
|
||||
DeviceFunctionData? selectedFunctionData,
|
||||
bool? removeComparators,
|
||||
}) {
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
if (removeComparators != true)
|
||||
_buildConditionToggle(
|
||||
context,
|
||||
currentCondition,
|
||||
|
@ -1,8 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_web/pages/common/custom_table.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/all_devices/bloc/switch_tabs/switch_tabs_bloc.dart';
|
||||
import 'package:syncrow_web/pages/home/bloc/home_bloc.dart';
|
||||
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart';
|
||||
import 'package:syncrow_web/utils/color_manager.dart';
|
||||
import 'package:syncrow_web/utils/extension/build_context_x.dart';
|
||||
|
@ -20,6 +20,7 @@ class OneGangSwitchHelper {
|
||||
AllDevicesModel? device,
|
||||
List<DeviceFunctionData>? deviceSelectedFunctions,
|
||||
String uniqueCustomId,
|
||||
bool removeComparetors,
|
||||
) async {
|
||||
List<BaseSwitchFunction> acFunctions =
|
||||
functions.whereType<BaseSwitchFunction>().toList();
|
||||
@ -106,6 +107,7 @@ class OneGangSwitchHelper {
|
||||
acFunctions: acFunctions,
|
||||
device: device,
|
||||
operationName: selectedOperationName ?? '',
|
||||
removeComparetors: removeComparetors,
|
||||
),
|
||||
),
|
||||
],
|
||||
@ -162,6 +164,7 @@ class OneGangSwitchHelper {
|
||||
required List<BaseSwitchFunction> acFunctions,
|
||||
AllDevicesModel? device,
|
||||
required String operationName,
|
||||
required bool removeComparetors,
|
||||
}) {
|
||||
if (selectedFunction == 'countdown_1') {
|
||||
final initialValue = selectedFunctionData?.value ?? 200;
|
||||
@ -173,6 +176,7 @@ class OneGangSwitchHelper {
|
||||
device: device,
|
||||
operationName: operationName,
|
||||
selectedFunctionData: selectedFunctionData,
|
||||
removeComparetors: removeComparetors,
|
||||
);
|
||||
}
|
||||
|
||||
@ -199,10 +203,12 @@ class OneGangSwitchHelper {
|
||||
AllDevicesModel? device,
|
||||
required String operationName,
|
||||
DeviceFunctionData? selectedFunctionData,
|
||||
required bool removeComparetors,
|
||||
}) {
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
if (removeComparetors != true)
|
||||
_buildConditionToggle(
|
||||
context,
|
||||
currentCondition,
|
||||
|
@ -20,6 +20,7 @@ class ThreeGangSwitchHelper {
|
||||
AllDevicesModel? device,
|
||||
List<DeviceFunctionData>? deviceSelectedFunctions,
|
||||
String uniqueCustomId,
|
||||
bool removeComparetors,
|
||||
) async {
|
||||
List<BaseSwitchFunction> switchFunctions =
|
||||
functions.whereType<BaseSwitchFunction>().toList();
|
||||
@ -106,6 +107,7 @@ class ThreeGangSwitchHelper {
|
||||
switchFunctions: switchFunctions,
|
||||
device: device,
|
||||
operationName: selectedOperationName ?? '',
|
||||
removeComparetors: removeComparetors,
|
||||
),
|
||||
),
|
||||
],
|
||||
@ -162,6 +164,7 @@ class ThreeGangSwitchHelper {
|
||||
required List<BaseSwitchFunction> switchFunctions,
|
||||
AllDevicesModel? device,
|
||||
required String operationName,
|
||||
required bool removeComparetors,
|
||||
}) {
|
||||
if (selectedFunction == 'countdown_1' ||
|
||||
selectedFunction == 'countdown_2' ||
|
||||
@ -175,6 +178,7 @@ class ThreeGangSwitchHelper {
|
||||
device: device,
|
||||
operationName: operationName,
|
||||
selectedFunctionData: selectedFunctionData,
|
||||
removeComparetors: removeComparetors,
|
||||
);
|
||||
}
|
||||
|
||||
@ -201,10 +205,12 @@ class ThreeGangSwitchHelper {
|
||||
AllDevicesModel? device,
|
||||
required String operationName,
|
||||
DeviceFunctionData? selectedFunctionData,
|
||||
bool? removeComparetors,
|
||||
}) {
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
if (removeComparetors != true)
|
||||
_buildConditionToggle(
|
||||
context,
|
||||
currentCondition,
|
||||
|
@ -20,6 +20,7 @@ class TwoGangSwitchHelper {
|
||||
AllDevicesModel? device,
|
||||
List<DeviceFunctionData>? deviceSelectedFunctions,
|
||||
String uniqueCustomId,
|
||||
bool removeComparetors,
|
||||
) async {
|
||||
List<BaseSwitchFunction> switchFunctions =
|
||||
functions.whereType<BaseSwitchFunction>().toList();
|
||||
@ -106,6 +107,7 @@ class TwoGangSwitchHelper {
|
||||
switchFunctions: switchFunctions,
|
||||
device: device,
|
||||
operationName: selectedOperationName ?? '',
|
||||
removeComparetors: removeComparetors,
|
||||
),
|
||||
),
|
||||
],
|
||||
@ -162,6 +164,7 @@ class TwoGangSwitchHelper {
|
||||
required List<BaseSwitchFunction> switchFunctions,
|
||||
AllDevicesModel? device,
|
||||
required String operationName,
|
||||
required bool removeComparetors,
|
||||
}) {
|
||||
if (selectedFunction == 'countdown_1' ||
|
||||
selectedFunction == 'countdown_2') {
|
||||
@ -174,6 +177,7 @@ class TwoGangSwitchHelper {
|
||||
device: device,
|
||||
operationName: operationName,
|
||||
selectedFunctionData: selectedFunctionData,
|
||||
removeComparetors: removeComparetors,
|
||||
);
|
||||
}
|
||||
|
||||
@ -200,10 +204,12 @@ class TwoGangSwitchHelper {
|
||||
AllDevicesModel? device,
|
||||
required String operationName,
|
||||
DeviceFunctionData? selectedFunctionData,
|
||||
bool? removeComparetors,
|
||||
}) {
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
if (removeComparetors != true)
|
||||
_buildConditionToggle(
|
||||
context,
|
||||
currentCondition,
|
||||
|
@ -1,6 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_web/pages/common/buttons/default_button.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/all_devices/bloc/switch_tabs/switch_tabs_bloc.dart';
|
||||
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart';
|
||||
import 'package:syncrow_web/pages/routiens/helper/save_routine_helper.dart';
|
||||
import 'package:syncrow_web/pages/routiens/widgets/routine_dialogs/discard_dialog.dart';
|
||||
@ -173,7 +174,7 @@ class RoutineSearchAndButtons extends StatelessWidget {
|
||||
width: 200,
|
||||
child: Center(
|
||||
child: DefaultButton(
|
||||
onPressed: () {
|
||||
onPressed: () async {
|
||||
if (state.routineName == null || state.routineName!.isEmpty) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
@ -207,7 +208,16 @@ class RoutineSearchAndButtons extends StatelessWidget {
|
||||
);
|
||||
return;
|
||||
}
|
||||
SaveRoutineHelper.showSaveRoutineDialog(context);
|
||||
final result =
|
||||
await SaveRoutineHelper.showSaveRoutineDialog(context);
|
||||
if (result != null && result) {
|
||||
BlocProvider.of<SwitchTabsBloc>(context).add(
|
||||
const CreateNewRoutineViewEvent(false),
|
||||
);
|
||||
BlocProvider.of<SwitchTabsBloc>(context).add(
|
||||
const TriggerSwitchTabsEvent(true),
|
||||
);
|
||||
}
|
||||
},
|
||||
borderRadius: 15,
|
||||
elevation: 0,
|
||||
|
@ -18,7 +18,7 @@ class _ScenesAndAutomationsState extends State<ScenesAndAutomations> {
|
||||
void initState() {
|
||||
super.initState();
|
||||
context.read<RoutineBloc>()
|
||||
..add(const LoadScenes(spaceId))
|
||||
..add(const LoadScenes(spaceId, communityId))
|
||||
..add(const LoadAutomation(spaceId));
|
||||
}
|
||||
|
||||
@ -34,7 +34,9 @@ class _ScenesAndAutomationsState extends State<ScenesAndAutomations> {
|
||||
children: scenes.asMap().entries.map((entry) {
|
||||
final scene = entry.value;
|
||||
if (state.searchText != null && state.searchText!.isNotEmpty) {
|
||||
return scene.name.toLowerCase().contains(state.searchText!.toLowerCase())
|
||||
return scene.name
|
||||
.toLowerCase()
|
||||
.contains(state.searchText!.toLowerCase())
|
||||
? DraggableCard(
|
||||
imagePath: scene.icon ?? Assets.loginLogo,
|
||||
title: scene.name,
|
||||
|
@ -26,7 +26,9 @@ class ThenContainer extends StatelessWidget {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
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),
|
||||
Wrap(
|
||||
spacing: 8,
|
||||
@ -35,12 +37,16 @@ class ThenContainer extends StatelessWidget {
|
||||
state.thenItems.length,
|
||||
(index) => GestureDetector(
|
||||
onTap: () async {
|
||||
if (state.thenItems[index]['deviceId'] == 'delay') {
|
||||
final result = await DelayHelper.showDelayPickerDialog(
|
||||
if (state.thenItems[index]['deviceId'] ==
|
||||
'delay') {
|
||||
final result = await DelayHelper
|
||||
.showDelayPickerDialog(
|
||||
context, state.thenItems[index]);
|
||||
|
||||
if (result != null) {
|
||||
context.read<RoutineBloc>().add(AddToThenContainer({
|
||||
context
|
||||
.read<RoutineBloc>()
|
||||
.add(AddToThenContainer({
|
||||
...state.thenItems[index],
|
||||
'imagePath': Assets.delay,
|
||||
'title': 'Delay',
|
||||
@ -49,32 +55,41 @@ class ThenContainer extends StatelessWidget {
|
||||
return;
|
||||
}
|
||||
|
||||
final result = await DeviceDialogHelper.showDeviceDialog(
|
||||
context, state.thenItems[index]);
|
||||
final result = await DeviceDialogHelper
|
||||
.showDeviceDialog(
|
||||
context, state.thenItems[index],
|
||||
removeComparetors: true);
|
||||
|
||||
if (result != null) {
|
||||
context
|
||||
.read<RoutineBloc>()
|
||||
.add(AddToThenContainer(state.thenItems[index]));
|
||||
context.read<RoutineBloc>().add(
|
||||
AddToThenContainer(
|
||||
state.thenItems[index]));
|
||||
} else if (!['AC', '1G', '2G', '3G']
|
||||
.contains(state.thenItems[index]['productType'])) {
|
||||
context
|
||||
.read<RoutineBloc>()
|
||||
.add(AddToThenContainer(state.thenItems[index]));
|
||||
.contains(state.thenItems[index]
|
||||
['productType'])) {
|
||||
context.read<RoutineBloc>().add(
|
||||
AddToThenContainer(
|
||||
state.thenItems[index]));
|
||||
}
|
||||
},
|
||||
child: DraggableCard(
|
||||
imagePath: state.thenItems[index]['imagePath'] ?? '',
|
||||
title: state.thenItems[index]['title'] ?? '',
|
||||
imagePath: state.thenItems[index]
|
||||
['imagePath'] ??
|
||||
'',
|
||||
title:
|
||||
state.thenItems[index]['title'] ?? '',
|
||||
deviceData: state.thenItems[index],
|
||||
padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 8),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 4, vertical: 8),
|
||||
isFromThen: true,
|
||||
isFromIf: false,
|
||||
onRemove: () {
|
||||
context.read<RoutineBloc>().add(RemoveDragCard(
|
||||
context.read<RoutineBloc>().add(
|
||||
RemoveDragCard(
|
||||
index: index,
|
||||
isFromThen: true,
|
||||
key: state.thenItems[index]['uniqueCustomId']));
|
||||
key: state.thenItems[index]
|
||||
['uniqueCustomId']));
|
||||
},
|
||||
),
|
||||
))),
|
||||
@ -83,21 +98,6 @@ class ThenContainer extends StatelessWidget {
|
||||
),
|
||||
);
|
||||
},
|
||||
// onWillAcceptWithDetails: (data) {
|
||||
// if (data == null) return false;
|
||||
// return data.data;
|
||||
|
||||
// // if (state.isTabToRun) {
|
||||
// // return data.data['type'] == 'automation';
|
||||
// // }
|
||||
|
||||
// // if (state.isAutomation) {
|
||||
// // return data.data['type'] == 'scene' ||
|
||||
// // data.data['type'] == 'automation';
|
||||
// // }
|
||||
|
||||
// // return data.data['deviceId'] != null;
|
||||
// },
|
||||
onAcceptWithDetails: (data) async {
|
||||
final uniqueCustomId = const Uuid().v4();
|
||||
final mutableData = Map<String, dynamic>.from(data.data);
|
||||
@ -128,8 +128,23 @@ class ThenContainer extends StatelessWidget {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mutableData['type'] == 'tap_to_run' && state.isAutomation) {
|
||||
context.read<RoutineBloc>().add(AddToThenContainer({
|
||||
...mutableData,
|
||||
'imagePath': Assets.logo,
|
||||
'title': mutableData['name'],
|
||||
}));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (mutableData['type'] == 'tap_to_run' && !state.isAutomation) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mutableData['deviceId'] == 'delay') {
|
||||
final result = await DelayHelper.showDelayPickerDialog(context, mutableData);
|
||||
final result =
|
||||
await DelayHelper.showDelayPickerDialog(context, mutableData);
|
||||
|
||||
if (result != null) {
|
||||
context.read<RoutineBloc>().add(AddToThenContainer({
|
||||
@ -141,11 +156,13 @@ class ThenContainer extends StatelessWidget {
|
||||
return;
|
||||
}
|
||||
|
||||
final result = await DeviceDialogHelper.showDeviceDialog(context, mutableData);
|
||||
|
||||
final result = await DeviceDialogHelper.showDeviceDialog(
|
||||
context, mutableData,
|
||||
removeComparetors: true);
|
||||
if (result != null) {
|
||||
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));
|
||||
}
|
||||
},
|
||||
|
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:syncrow_web/pages/routiens/models/create_scene_and_autoamtion/create_automation_model.dart';
|
||||
import 'package:syncrow_web/pages/routiens/models/create_scene_and_autoamtion/create_scene_model.dart';
|
||||
import 'package:syncrow_web/pages/routiens/models/icon_model.dart';
|
||||
import 'package:syncrow_web/pages/routiens/models/routine_details_model.dart';
|
||||
import 'package:syncrow_web/pages/routiens/models/routine_model.dart';
|
||||
import 'package:syncrow_web/services/api/http_service.dart';
|
||||
import 'package:syncrow_web/utils/constants/api_const.dart';
|
||||
@ -67,17 +68,24 @@ class SceneApi {
|
||||
return response;
|
||||
}
|
||||
|
||||
//get scene by unit id
|
||||
//get scenes by community id and space id
|
||||
|
||||
static Future<List<ScenesModel>> getScenesByUnitId(String unitId) async {
|
||||
static Future<List<ScenesModel>> getScenesByUnitId(
|
||||
String unitId, String communityId,
|
||||
{showInDevice = false}) async {
|
||||
try {
|
||||
final response = await _httpService.get(
|
||||
path: ApiEndpoints.getSpaceScenes.replaceAll('{unitUuid}', unitId),
|
||||
path: ApiEndpoints.getUnitScenes
|
||||
.replaceAll('{spaceUuid}', unitId)
|
||||
.replaceAll('{communityUuid}', communityId),
|
||||
queryParameters: {'showInHomePage': showInDevice},
|
||||
showServerMessage: false,
|
||||
expectedResponseModel: (json) {
|
||||
final scenesJson = json['data'] as List;
|
||||
|
||||
List<ScenesModel> scenes = [];
|
||||
for (var scene in json) {
|
||||
scenes.add(ScenesModel.fromJson(scene));
|
||||
for (var scene in scenesJson) {
|
||||
scenes.add(ScenesModel.fromJson(scene, isAutomation: false));
|
||||
}
|
||||
return scenes;
|
||||
},
|
||||
@ -122,21 +130,21 @@ class SceneApi {
|
||||
// }
|
||||
// }
|
||||
|
||||
// //automation details
|
||||
// static Future<SceneDetailsModel> getAutomationDetails(
|
||||
// String automationId) async {
|
||||
// try {
|
||||
// final response = await _httpService.get(
|
||||
// path: ApiEndpoints.getAutomationDetails
|
||||
// .replaceAll('{automationId}', automationId),
|
||||
// showServerMessage: false,
|
||||
// expectedResponseModel: (json) => SceneDetailsModel.fromJson(json),
|
||||
// );
|
||||
// return response;
|
||||
// } catch (e) {
|
||||
// rethrow;
|
||||
// }
|
||||
// }
|
||||
//automation details
|
||||
static Future<RoutineDetailsModel> getAutomationDetails(
|
||||
String automationId) async {
|
||||
try {
|
||||
final response = await _httpService.get(
|
||||
path: ApiEndpoints.getAutomationDetails
|
||||
.replaceAll('{automationId}', automationId),
|
||||
showServerMessage: false,
|
||||
expectedResponseModel: (json) => RoutineDetailsModel.fromJson(json),
|
||||
);
|
||||
return response;
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
//
|
||||
// //updateAutomationStatus
|
||||
// static Future<bool> updateAutomationStatus(String automationId,
|
||||
@ -154,20 +162,19 @@ class SceneApi {
|
||||
// }
|
||||
// }
|
||||
|
||||
// //getScene
|
||||
//
|
||||
// static Future<SceneDetailsModel> getSceneDetails(String sceneId) async {
|
||||
// try {
|
||||
// final response = await _httpService.get(
|
||||
// path: ApiEndpoints.getScene.replaceAll('{sceneId}', sceneId),
|
||||
// showServerMessage: false,
|
||||
// expectedResponseModel: (json) => SceneDetailsModel.fromJson(json),
|
||||
// );
|
||||
// return response;
|
||||
// } catch (e) {
|
||||
// rethrow;
|
||||
// }
|
||||
// }
|
||||
//getScene
|
||||
static Future<RoutineDetailsModel> getSceneDetails(String sceneId) async {
|
||||
try {
|
||||
final response = await _httpService.get(
|
||||
path: ApiEndpoints.getScene.replaceAll('{sceneId}', sceneId),
|
||||
showServerMessage: false,
|
||||
expectedResponseModel: (json) => RoutineDetailsModel.fromJson(json),
|
||||
);
|
||||
return response;
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
//
|
||||
// //update Scene
|
||||
// static updateScene(CreateSceneModel createSceneModel, String sceneId) async {
|
||||
@ -205,38 +212,39 @@ class SceneApi {
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// //delete Scene
|
||||
//
|
||||
// static Future<bool> deleteScene(
|
||||
// {required String unitUuid, required String sceneId}) async {
|
||||
// try {
|
||||
// final response = await _httpService.delete(
|
||||
// path: ApiEndpoints.deleteScene
|
||||
// .replaceAll('{sceneId}', sceneId)
|
||||
// .replaceAll('{unitUuid}', unitUuid),
|
||||
// showServerMessage: false,
|
||||
// expectedResponseModel: (json) => json['statusCode'] == 200,
|
||||
// );
|
||||
// return response;
|
||||
// } catch (e) {
|
||||
// rethrow;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // delete automation
|
||||
// static Future<bool> deleteAutomation(
|
||||
// {required String unitUuid, required String automationId}) async {
|
||||
// try {
|
||||
// final response = await _httpService.delete(
|
||||
// path: ApiEndpoints.deleteAutomation
|
||||
// .replaceAll('{automationId}', automationId)
|
||||
// .replaceAll('{unitUuid}', unitUuid),
|
||||
// showServerMessage: false,
|
||||
// expectedResponseModel: (json) => json['statusCode'] == 200,
|
||||
// );
|
||||
// return response;
|
||||
// } catch (e) {
|
||||
// rethrow;
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
//delete Scene
|
||||
static Future<bool> deleteScene(
|
||||
{required String unitUuid, required String sceneId}) async {
|
||||
try {
|
||||
final response = await _httpService.delete(
|
||||
path: ApiEndpoints.deleteScene
|
||||
.replaceAll('{sceneId}', sceneId)
|
||||
.replaceAll('{unitUuid}', unitUuid),
|
||||
showServerMessage: false,
|
||||
expectedResponseModel: (json) => json['statusCode'] == 200,
|
||||
);
|
||||
return response;
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
// delete automation
|
||||
static Future<bool> deleteAutomation(
|
||||
{required String unitUuid, required String automationId}) async {
|
||||
try {
|
||||
final response = await _httpService.delete(
|
||||
path: ApiEndpoints.deleteAutomation
|
||||
.replaceAll('{automationId}', automationId)
|
||||
.replaceAll('{unitUuid}', unitUuid),
|
||||
showServerMessage: false,
|
||||
expectedResponseModel: (json) => json['statusCode'] == 200,
|
||||
);
|
||||
return response;
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -46,7 +46,6 @@ abstract class ApiEndpoints {
|
||||
'/schedule/{deviceUuid}/{scheduleUuid}';
|
||||
static const String updateScheduleByDeviceId =
|
||||
'/schedule/enable/{deviceUuid}';
|
||||
|
||||
static const String factoryReset = '/device/factory/reset/{deviceUuid}';
|
||||
static const String powerClamp =
|
||||
'/device/{powerClampUuid}/power-clamp/status';
|
||||
@ -55,4 +54,12 @@ abstract class ApiEndpoints {
|
||||
static const String getIconScene = '/scene/icon';
|
||||
static const String createScene = '/scene/tap-to-run';
|
||||
static const String createAutomation = '/automation';
|
||||
static const String getUnitScenes =
|
||||
'/communities/{communityUuid}/spaces/{spaceUuid}/scenes';
|
||||
static const String getAutomationDetails =
|
||||
'/automation/details/{automationId}';
|
||||
static const String getScene = '/scene/tap-to-run/{sceneId}';
|
||||
static const String deleteScene = '/scene/tap-to-run/{sceneId}';
|
||||
|
||||
static const String deleteAutomation = '/automation/{automationId}';
|
||||
}
|
||||
|
Reference in New Issue
Block a user