Compare commits

...
Author SHA1 Message Date
Abdullah Alassaf 132cafcaa2 Enhanced the side tree design 2025-02-05 11:52:44 +03:00
Abdullah Alassaf 572520eed5 Fixed issues 2025-02-04 01:54:18 +03:00
Abdullah Alassaf 506531e16a Fetch devices based on selection 2025-02-03 11:15:36 +03:00
11 changed files with 260 additions and 137 deletions
@@ -1,6 +1,8 @@
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart'; import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
import 'package:syncrow_web/pages/space_tree/bloc/space_tree_bloc.dart';
import 'package:syncrow_web/services/devices_mang_api.dart'; import 'package:syncrow_web/services/devices_mang_api.dart';
part 'device_managment_event.dart'; part 'device_managment_event.dart';
@@ -32,7 +34,20 @@ class DeviceManagementBloc extends Bloc<DeviceManagementEvent, DeviceManagementS
Future<void> _onFetchDevices(FetchDevices event, Emitter<DeviceManagementState> emit) async { Future<void> _onFetchDevices(FetchDevices event, Emitter<DeviceManagementState> emit) async {
emit(DeviceManagementLoading()); emit(DeviceManagementLoading());
try { try {
final devices = await DevicesManagementApi().fetchDevices(event.communityId, event.spaceId); List<AllDevicesModel> devices = [];
_devices.clear();
var spaceBloc = event.context.read<SpaceTreeBloc>();
if (spaceBloc.state.selectedCommunities.isEmpty) {
devices = await DevicesManagementApi().fetchDevices('', '');
} else {
for (var community in spaceBloc.state.selectedCommunities) {
List<String> spacesList = spaceBloc.state.selectedCommunityAndSpaces[community] ?? [];
for (var space in spacesList) {
devices.addAll(await DevicesManagementApi().fetchDevices(community, space));
}
}
}
_selectedDevices.clear(); _selectedDevices.clear();
_devices = devices; _devices = devices;
_filteredDevices = devices; _filteredDevices = devices;
@@ -8,12 +8,13 @@ abstract class DeviceManagementEvent extends Equatable {
} }
class FetchDevices extends DeviceManagementEvent { class FetchDevices extends DeviceManagementEvent {
final String communityId; // final Map<String, List<String>> selectedCommunitiesSpaces;
final String spaceId; // final String spaceId;
final BuildContext context;
const FetchDevices(this.communityId, this.spaceId); const FetchDevices(this.context);
@override @override
List<Object?> get props => [communityId, spaceId]; List<Object?> get props => [context];
} }
class FilterDevices extends DeviceManagementEvent { class FilterDevices extends DeviceManagementEvent {
@@ -19,7 +19,7 @@ class DeviceManagementPage extends StatelessWidget with HelperResponsiveLayout {
return MultiBlocProvider( return MultiBlocProvider(
providers: [ providers: [
BlocProvider( BlocProvider(
create: (context) => DeviceManagementBloc()..add(const FetchDevices('', '')), create: (context) => DeviceManagementBloc()..add(FetchDevices(context)),
), ),
], ],
child: WebScaffold( child: WebScaffold(
@@ -8,6 +8,7 @@ import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_mo
import 'package:syncrow_web/pages/device_managment/all_devices/widgets/device_search_filters.dart'; import 'package:syncrow_web/pages/device_managment/all_devices/widgets/device_search_filters.dart';
import 'package:syncrow_web/pages/device_managment/shared/device_batch_control_dialog.dart'; import 'package:syncrow_web/pages/device_managment/shared/device_batch_control_dialog.dart';
import 'package:syncrow_web/pages/device_managment/shared/device_control_dialog.dart'; import 'package:syncrow_web/pages/device_managment/shared/device_control_dialog.dart';
import 'package:syncrow_web/pages/space_tree/bloc/space_tree_bloc.dart';
import 'package:syncrow_web/pages/space_tree/view/space_tree_view.dart'; import 'package:syncrow_web/pages/space_tree/view/space_tree_view.dart';
import 'package:syncrow_web/utils/format_date_time.dart'; import 'package:syncrow_web/utils/format_date_time.dart';
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart'; import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
@@ -62,14 +63,13 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
return Row( return Row(
children: [ children: [
const Expanded( Expanded(child: SpaceTreeView(
child: SpaceTreeView( onSelect: () {
// onSelectAction: (String communityId, String spaceId) { context.read<DeviceManagementBloc>().add(FetchDevices(context));
// context.read<DeviceManagementBloc>().add(FetchDevices(communityId, spaceId)); },
// }, )),
)),
Expanded( Expanded(
flex: 3, flex: 4,
child: state is DeviceManagementLoading child: state is DeviceManagementLoading
? const Center(child: CircularProgressIndicator()) ? const Center(child: CircularProgressIndicator())
: Column( : Column(
@@ -85,7 +85,7 @@ class _DeviceSearchFiltersState extends State<DeviceSearchFilters> with HelperRe
productNameController.clear(); productNameController.clear();
context.read<DeviceManagementBloc>() context.read<DeviceManagementBloc>()
..add(ResetFilters()) ..add(ResetFilters())
..add(const FetchDevices('', '')); ..add(FetchDevices(context));
}, },
); );
} }
@@ -816,7 +816,7 @@ 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(communityId, spaceId); final devices = await DevicesManagementApi().fetchDevices('', '');
emit(state.copyWith(isLoading: false, devices: devices)); emit(state.copyWith(isLoading: false, devices: devices));
} catch (e) { } catch (e) {
+48 -55
View File
@@ -32,63 +32,56 @@ class _RoutinesViewState extends State<RoutinesView> {
} }
return Row( return Row(
children: [ children: [
const Expanded(
child:
// SideSpacesView(
// onSelectAction: (String communityId, String spaceId) {
// // context.read<RoutineBloc>()
// // ..add(LoadScenes(spaceId, communityId))
// // ..add(LoadAutomation(spaceId));
// },
// )
SpaceTreeView()),
Expanded( Expanded(
flex: 3, child: SpaceTreeView(
child: Padding( onSelect: () {},
padding: const EdgeInsets.all(16), )),
child: Row( Expanded(
children: [ flex: 4,
Column( child: ListView(children: [
mainAxisSize: MainAxisSize.min, Container(
crossAxisAlignment: CrossAxisAlignment.start, padding: const EdgeInsets.all(16),
mainAxisAlignment: MainAxisAlignment.start, height: MediaQuery.sizeOf(context).height,
children: [ child: Column(
Text( mainAxisSize: MainAxisSize.min,
"Create New Routines", crossAxisAlignment: CrossAxisAlignment.start,
style: Theme.of(context).textTheme.titleLarge?.copyWith( mainAxisAlignment: MainAxisAlignment.start,
color: ColorsManager.grayColor, children: [
fontWeight: FontWeight.bold, Text(
), "Create New Routines",
), style: Theme.of(context).textTheme.titleLarge?.copyWith(
const SizedBox( color: ColorsManager.grayColor,
height: 10, fontWeight: FontWeight.bold,
), ),
RoutineViewCard( ),
onTap: () { const SizedBox(
if (context.read<SpaceTreeBloc>().selectedCommunityId.isNotEmpty && height: 10,
context.read<SpaceTreeBloc>().selectedSpaceId.isNotEmpty) { ),
context.read<RoutineBloc>().add( RoutineViewCard(
(ResetRoutineState()), onTap: () {
); if (context.read<SpaceTreeBloc>().selectedCommunityId.isNotEmpty &&
BlocProvider.of<RoutineBloc>(context).add( context.read<SpaceTreeBloc>().selectedSpaceId.isNotEmpty) {
const CreateNewRoutineViewEvent(createRoutineView: true), context.read<RoutineBloc>().add(
); (ResetRoutineState()),
} else { );
CustomSnackBar.redSnackBar('Please select a space'); BlocProvider.of<RoutineBloc>(context).add(
} const CreateNewRoutineViewEvent(createRoutineView: true),
}, );
icon: Icons.add, } else {
textString: '', CustomSnackBar.redSnackBar('Please select a space');
), }
const SizedBox( },
height: 15, icon: Icons.add,
), textString: '',
const Expanded(child: FetchRoutineScenesAutomation()), ),
], const SizedBox(
), height: 15,
], ),
const Expanded(child: FetchRoutineScenesAutomation()),
],
),
), ),
), ]),
), ),
], ],
); );
+12 -4
View File
@@ -6,8 +6,8 @@ import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model
import 'package:syncrow_web/services/space_mana_api.dart'; import 'package:syncrow_web/services/space_mana_api.dart';
class SpaceTreeBloc extends Bloc<SpaceTreeEvent, SpaceTreeState> { class SpaceTreeBloc extends Bloc<SpaceTreeEvent, SpaceTreeState> {
String selectedCommunityId = ''; String selectedCommunityId = 'aff21a57-2f91-4e5c-b99b-0182c3ab65a9';
String selectedSpaceId = ''; String selectedSpaceId = '25c96044-fadf-44bb-93c7-3c079e527ce6';
SpaceTreeBloc() : super(const SpaceTreeState()) { SpaceTreeBloc() : super(const SpaceTreeState()) {
on<InitialEvent>(_fetchSpaces); on<InitialEvent>(_fetchSpaces);
@@ -87,6 +87,7 @@ class SpaceTreeBloc extends Bloc<SpaceTreeEvent, SpaceTreeState> {
List.from(state.selectedCommunities.toSet().toList()); List.from(state.selectedCommunities.toSet().toList());
List<String> updatedSelectedSpaces = List.from(state.selectedSpaces.toSet().toList()); List<String> updatedSelectedSpaces = List.from(state.selectedSpaces.toSet().toList());
List<String> updatedSoldChecks = List.from(state.soldCheck.toSet().toList()); List<String> updatedSoldChecks = List.from(state.soldCheck.toSet().toList());
Map<String, List<String>> communityAndSpaces = Map.from(state.selectedCommunityAndSpaces);
List<String> childrenIds = _getAllChildIds(event.children); List<String> childrenIds = _getAllChildIds(event.children);
@@ -101,10 +102,13 @@ class SpaceTreeBloc extends Bloc<SpaceTreeEvent, SpaceTreeState> {
updatedSoldChecks.removeWhere(childrenIds.contains); updatedSoldChecks.removeWhere(childrenIds.contains);
} }
communityAndSpaces[event.communityId] = updatedSelectedSpaces;
emit(state.copyWith( emit(state.copyWith(
selectedCommunities: updatedSelectedCommunities, selectedCommunities: updatedSelectedCommunities,
selectedSpaces: updatedSelectedSpaces, selectedSpaces: updatedSelectedSpaces,
soldCheck: updatedSoldChecks)); soldCheck: updatedSoldChecks,
selectedCommunityAndSpaces: communityAndSpaces));
} catch (e) { } catch (e) {
emit(const SpaceTreeErrorState('Something went wrong')); emit(const SpaceTreeErrorState('Something went wrong'));
} }
@@ -116,6 +120,7 @@ class SpaceTreeBloc extends Bloc<SpaceTreeEvent, SpaceTreeState> {
List.from(state.selectedCommunities.toSet().toList()); List.from(state.selectedCommunities.toSet().toList());
List<String> updatedSelectedSpaces = List.from(state.selectedSpaces.toSet().toList()); List<String> updatedSelectedSpaces = List.from(state.selectedSpaces.toSet().toList());
List<String> updatedSoldChecks = List.from(state.soldCheck.toSet().toList()); List<String> updatedSoldChecks = List.from(state.soldCheck.toSet().toList());
Map<String, List<String>> communityAndSpaces = Map.from(state.selectedCommunityAndSpaces);
List<String> childrenIds = _getAllChildIds(event.children); List<String> childrenIds = _getAllChildIds(event.children);
bool isChildSelected = false; bool isChildSelected = false;
@@ -166,10 +171,13 @@ class SpaceTreeBloc extends Bloc<SpaceTreeEvent, SpaceTreeState> {
} }
} }
communityAndSpaces[event.communityId] = updatedSelectedSpaces;
emit(state.copyWith( emit(state.copyWith(
selectedCommunities: updatedSelectedCommunities, selectedCommunities: updatedSelectedCommunities,
selectedSpaces: updatedSelectedSpaces, selectedSpaces: updatedSelectedSpaces,
soldCheck: updatedSoldChecks)); soldCheck: updatedSoldChecks,
selectedCommunityAndSpaces: communityAndSpaces));
emit(state.copyWith(selectedSpaces: updatedSelectedSpaces)); emit(state.copyWith(selectedSpaces: updatedSelectedSpaces));
} catch (e) { } catch (e) {
emit(const SpaceTreeErrorState('Something went wrong')); emit(const SpaceTreeErrorState('Something went wrong'));
@@ -2,6 +2,7 @@ import 'package:equatable/equatable.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart'; import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart';
class SpaceTreeState extends Equatable { class SpaceTreeState extends Equatable {
final Map<String, List<String>> selectedCommunityAndSpaces;
final List<CommunityModel> communityList; final List<CommunityModel> communityList;
final List<CommunityModel> filteredCommunity; final List<CommunityModel> filteredCommunity;
final List<String> expandedCommunities; final List<String> expandedCommunities;
@@ -19,7 +20,8 @@ class SpaceTreeState extends Equatable {
this.selectedCommunities = const [], this.selectedCommunities = const [],
this.selectedSpaces = const [], this.selectedSpaces = const [],
this.soldCheck = const [], this.soldCheck = const [],
this.isSearching = false}); this.isSearching = false,
this.selectedCommunityAndSpaces = const {}});
SpaceTreeState copyWith( SpaceTreeState copyWith(
{List<CommunityModel>? communitiesList, {List<CommunityModel>? communitiesList,
@@ -29,7 +31,8 @@ class SpaceTreeState extends Equatable {
List<String>? selectedCommunities, List<String>? selectedCommunities,
List<String>? selectedSpaces, List<String>? selectedSpaces,
List<String>? soldCheck, List<String>? soldCheck,
bool? isSearching}) { bool? isSearching,
Map<String, List<String>>? selectedCommunityAndSpaces}) {
return SpaceTreeState( return SpaceTreeState(
communityList: communitiesList ?? this.communityList, communityList: communitiesList ?? this.communityList,
filteredCommunity: filteredCommunity ?? this.filteredCommunity, filteredCommunity: filteredCommunity ?? this.filteredCommunity,
@@ -38,7 +41,8 @@ class SpaceTreeState extends Equatable {
selectedCommunities: selectedCommunities ?? this.selectedCommunities, selectedCommunities: selectedCommunities ?? this.selectedCommunities,
selectedSpaces: selectedSpaces ?? this.selectedSpaces, selectedSpaces: selectedSpaces ?? this.selectedSpaces,
soldCheck: soldCheck ?? this.soldCheck, soldCheck: soldCheck ?? this.soldCheck,
isSearching: isSearching ?? this.isSearching); isSearching: isSearching ?? this.isSearching,
selectedCommunityAndSpaces: selectedCommunityAndSpaces ?? this.selectedCommunityAndSpaces);
} }
@override @override
@@ -50,7 +54,8 @@ class SpaceTreeState extends Equatable {
selectedCommunities, selectedCommunities,
selectedSpaces, selectedSpaces,
soldCheck, soldCheck,
isSearching isSearching,
selectedCommunityAndSpaces
]; ];
} }
+158 -58
View File
@@ -10,8 +10,22 @@ import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model
import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/style.dart'; import 'package:syncrow_web/utils/style.dart';
class SpaceTreeView extends StatelessWidget { class SpaceTreeView extends StatefulWidget {
const SpaceTreeView({super.key}); final Function onSelect;
const SpaceTreeView({required this.onSelect, super.key});
@override
State<SpaceTreeView> createState() => _SpaceTreeViewState();
}
class _SpaceTreeViewState extends State<SpaceTreeView> {
final ScrollController _scrollController = ScrollController();
@override
void dispose() {
_scrollController.dispose();
super.dispose();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@@ -20,7 +34,6 @@ class SpaceTreeView extends StatelessWidget {
return Container( return Container(
height: MediaQuery.sizeOf(context).height, height: MediaQuery.sizeOf(context).height,
decoration: subSectionContainerDecoration, decoration: subSectionContainerDecoration,
// padding: const EdgeInsets.all(16.0),
child: state is SpaceTreeLoadingState child: state is SpaceTreeLoadingState
? const Center(child: CircularProgressIndicator()) ? const Center(child: CircularProgressIndicator())
: Column( : Column(
@@ -32,64 +45,150 @@ class SpaceTreeView extends StatelessWidget {
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
Expanded( Expanded(
child: Padding( child: ListView(
padding: const EdgeInsets.all(8.0), shrinkWrap: true,
child: list.isEmpty scrollDirection: Axis.horizontal,
? Center( children: [
child: Text( Container(
'No results found', width: MediaQuery.sizeOf(context).width * 0.5,
style: Theme.of(context).textTheme.bodySmall!.copyWith( padding: const EdgeInsets.all(8.0),
color: ColorsManager.lightGrayColor, // Gray when not selected child: list.isEmpty
fontWeight: FontWeight.w400, ? Center(
child: Text(
'No results found',
style: Theme.of(context).textTheme.bodySmall!.copyWith(
color: ColorsManager.lightGrayColor,
fontWeight: FontWeight.w400,
),
),
)
: Scrollbar(
scrollbarOrientation: ScrollbarOrientation.left,
thumbVisibility: true,
controller: _scrollController,
child: Padding(
padding: const EdgeInsets.only(left: 16),
child: ListView(
controller: _scrollController,
shrinkWrap: true,
children: list
.map(
(community) => CustomExpansionTileSpaceTree(
title: community.name,
isSelected: state.selectedCommunities
.contains(community.uuid),
isSoldCheck: state.selectedCommunities
.contains(community.uuid),
onExpansionChanged: () {
context
.read<SpaceTreeBloc>()
.add(OnCommunityExpanded(community.uuid));
},
isExpanded: state.expandedCommunities
.contains(community.uuid),
onItemSelected: () {
context.read<SpaceTreeBloc>().add(
OnCommunitySelected(
community.uuid, community.spaces));
widget.onSelect();
},
children: community.spaces.map((space) {
return CustomExpansionTileSpaceTree(
title: space.name,
isExpanded:
state.expandedSpaces.contains(space.uuid),
onItemSelected: () {
context.read<SpaceTreeBloc>().add(
OnSpaceSelected(community.uuid,
space.uuid ?? '', space.children));
widget.onSelect();
},
onExpansionChanged: () {
context.read<SpaceTreeBloc>().add(
OnSpaceExpanded(
community.uuid, space.uuid ?? ''));
},
isSelected:
state.selectedSpaces.contains(space.uuid) ||
state.soldCheck.contains(space.uuid),
isSoldCheck: state.soldCheck.contains(space.uuid),
children: _buildNestedSpaces(
context, state, space, community.uuid),
);
}).toList(),
),
)
.toList(),
), ),
), ),
) ),
: ListView( ),
shrinkWrap: true, ],
children: list
.map(
(community) => CustomExpansionTileSpaceTree(
title: community.name,
isSelected:
state.selectedCommunities.contains(community.uuid),
isSoldCheck:
state.selectedCommunities.contains(community.uuid),
onExpansionChanged: () {
context
.read<SpaceTreeBloc>()
.add(OnCommunityExpanded(community.uuid));
},
isExpanded:
state.expandedCommunities.contains(community.uuid),
onItemSelected: () {
context.read<SpaceTreeBloc>().add(
OnCommunitySelected(community.uuid, community.spaces));
},
children: community.spaces.map((space) {
return CustomExpansionTileSpaceTree(
title: space.name,
isExpanded: state.expandedSpaces.contains(space.uuid),
onItemSelected: () {
context.read<SpaceTreeBloc>().add(OnSpaceSelected(
community.uuid, space.uuid ?? '', space.children));
},
onExpansionChanged: () {
context.read<SpaceTreeBloc>().add(
OnSpaceExpanded(community.uuid, space.uuid ?? ''));
},
isSelected: state.selectedSpaces.contains(space.uuid) ||
state.soldCheck.contains(space.uuid),
isSoldCheck: state.soldCheck.contains(space.uuid),
children: _buildNestedSpaces(
context, state, space, community.uuid),
);
}).toList(),
),
)
.toList(),
),
), ),
), ),
// Expanded(
// child: Padding(
// padding: const EdgeInsets.all(8.0),
// child: list.isEmpty
// ? Center(
// child: Text(
// 'No results found',
// style: Theme.of(context).textTheme.bodySmall!.copyWith(
// color: ColorsManager.lightGrayColor, // Gray when not selected
// fontWeight: FontWeight.w400,
// ),
// ),
// )
// : ListView(
// shrinkWrap: true,
// children: list
// .map(
// (community) => CustomExpansionTileSpaceTree(
// title: community.name,
// isSelected:
// state.selectedCommunities.contains(community.uuid),
// isSoldCheck:
// state.selectedCommunities.contains(community.uuid),
// onExpansionChanged: () {
// context
// .read<SpaceTreeBloc>()
// .add(OnCommunityExpanded(community.uuid));
// },
// isExpanded:
// state.expandedCommunities.contains(community.uuid),
// onItemSelected: () {
// context.read<SpaceTreeBloc>().add(
// OnCommunitySelected(community.uuid, community.spaces));
// onSelect();
// },
// children: community.spaces.map((space) {
// return CustomExpansionTileSpaceTree(
// title: space.name,
// isExpanded: state.expandedSpaces.contains(space.uuid),
// onItemSelected: () {
// context.read<SpaceTreeBloc>().add(OnSpaceSelected(
// community.uuid, space.uuid ?? '', space.children));
// onSelect();
// },
// onExpansionChanged: () {
// context.read<SpaceTreeBloc>().add(
// OnSpaceExpanded(community.uuid, space.uuid ?? ''));
// },
// isSelected: state.selectedSpaces.contains(space.uuid) ||
// state.soldCheck.contains(space.uuid),
// isSoldCheck: state.soldCheck.contains(space.uuid),
// children: _buildNestedSpaces(
// context, state, space, community.uuid),
// );
// }).toList(),
// ),
// )
// .toList(),
// ),
// ),
// ),
], ],
), ),
); );
@@ -109,6 +208,7 @@ class SpaceTreeView extends StatelessWidget {
context context
.read<SpaceTreeBloc>() .read<SpaceTreeBloc>()
.add(OnSpaceSelected(communityId, child.uuid ?? '', child.children)); .add(OnSpaceSelected(communityId, child.uuid ?? '', child.children));
widget.onSelect();
}, },
onExpansionChanged: () { onExpansionChanged: () {
context.read<SpaceTreeBloc>().add(OnSpaceExpanded(communityId, child.uuid ?? '')); context.read<SpaceTreeBloc>().add(OnSpaceExpanded(communityId, child.uuid ?? ''));
+2 -1
View File
@@ -23,7 +23,8 @@ class DevicesManagementApi {
: ApiEndpoints.getAllDevices, : ApiEndpoints.getAllDevices,
showServerMessage: true, showServerMessage: true,
expectedResponseModel: (json) { expectedResponseModel: (json) {
List<dynamic> jsonData = json; List<dynamic> jsonData =
communityId.isNotEmpty && spaceId.isNotEmpty ? json['data'] : json;
List<AllDevicesModel> devicesList = jsonData.map((jsonItem) { List<AllDevicesModel> devicesList = jsonData.map((jsonItem) {
return AllDevicesModel.fromJson(jsonItem); return AllDevicesModel.fromJson(jsonItem);
}).toList(); }).toList();