fix selection from dynamic table

This commit is contained in:
ashrafzarkanisala
2024-09-02 19:26:52 +03:00
parent 4cf9d4c2f2
commit 7bbae2d332
10 changed files with 96 additions and 39 deletions

View File

@ -82,6 +82,7 @@ class AccessManagementPage extends StatelessWidget with HelperResponsiveLayout {
const SizedBox(height: 20), const SizedBox(height: 20),
Expanded( Expanded(
child: DynamicTable( child: DynamicTable(
uuidIndex: 0,
isEmpty: filteredData.isEmpty, isEmpty: filteredData.isEmpty,
withCheckBox: false, withCheckBox: false,
size: MediaQuery.of(context).size, size: MediaQuery.of(context).size,

View File

@ -14,6 +14,7 @@ class DynamicTable extends StatefulWidget {
final void Function(bool?)? selectAll; final void Function(bool?)? selectAll;
final void Function(int, bool, dynamic)? onRowSelected; final void Function(int, bool, dynamic)? onRowSelected;
final List<String>? initialSelectedIds; final List<String>? initialSelectedIds;
final int uuidIndex;
const DynamicTable({ const DynamicTable({
super.key, super.key,
required this.headers, required this.headers,
@ -26,6 +27,7 @@ class DynamicTable extends StatefulWidget {
this.selectAll, this.selectAll,
this.onRowSelected, this.onRowSelected,
this.initialSelectedIds, this.initialSelectedIds,
required this.uuidIndex,
}); });
@override @override
@ -38,9 +40,24 @@ class _DynamicTableState extends State<DynamicTable> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_initializeSelection();
}
@override
void didUpdateWidget(DynamicTable oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.data != widget.data) {
_initializeSelection();
}
}
void _initializeSelection() {
_selected = List<bool>.generate(widget.data.length, (index) { _selected = List<bool>.generate(widget.data.length, (index) {
// Check if the initialSelectedIds contains the deviceUuid
// uuidIndex is the index of the column containing the deviceUuid
final deviceUuid = widget.data[index][widget.uuidIndex];
return widget.initialSelectedIds != null && return widget.initialSelectedIds != null &&
widget.initialSelectedIds!.contains(widget.data[index][1]); widget.initialSelectedIds!.contains(deviceUuid);
}); });
} }
@ -71,8 +88,7 @@ class _DynamicTableState extends State<DynamicTable> {
children: [ children: [
if (widget.withCheckBox) _buildSelectAllCheckbox(), if (widget.withCheckBox) _buildSelectAllCheckbox(),
...widget.headers ...widget.headers
.map((header) => _buildTableHeaderCell(header)) .map((header) => _buildTableHeaderCell(header)),
.toList(),
], ],
), ),
), ),
@ -119,11 +135,9 @@ class _DynamicTableState extends State<DynamicTable> {
if (widget.withCheckBox) if (widget.withCheckBox)
_buildRowCheckbox( _buildRowCheckbox(
index, widget.size.height * 0.10), index, widget.size.height * 0.10),
...row ...row.map((cell) => _buildTableCell(
.map((cell) => _buildTableCell( cell.toString(),
cell.toString(), widget.size.height * 0.10)),
widget.size.height * 0.10))
.toList(),
], ],
); );
}, },

View File

@ -28,11 +28,12 @@ class DeviceManagementBloc
emit(DeviceManagementLoading()); emit(DeviceManagementLoading());
try { try {
final devices = await DevicesManagementApi().fetchDevices(); final devices = await DevicesManagementApi().fetchDevices();
_selectedDevices.clear();
_devices = devices; _devices = devices;
_calculateDeviceCounts(); _calculateDeviceCounts();
emit(DeviceManagementLoaded( emit(DeviceManagementLoaded(
devices: devices, devices: devices,
selectedIndex: _selectedIndex, selectedIndex: 0,
onlineCount: _onlineCount, onlineCount: _onlineCount,
offlineCount: _offlineCount, offlineCount: _offlineCount,
lowBatteryCount: _lowBatteryCount, lowBatteryCount: _lowBatteryCount,
@ -64,6 +65,8 @@ class DeviceManagementBloc
onlineCount: _onlineCount, onlineCount: _onlineCount,
offlineCount: _offlineCount, offlineCount: _offlineCount,
lowBatteryCount: _lowBatteryCount, lowBatteryCount: _lowBatteryCount,
selectedDevice:
_selectedDevices.isNotEmpty ? _selectedDevices.first : null,
)); ));
} }
} }
@ -76,8 +79,10 @@ class DeviceManagementBloc
void _onSelectDevice( void _onSelectDevice(
SelectDevice event, Emitter<DeviceManagementState> emit) { SelectDevice event, Emitter<DeviceManagementState> emit) {
if (_selectedDevices.contains(event.selectedDevice)) { final selectedUuid = event.selectedDevice.uuid;
_selectedDevices.remove(event.selectedDevice);
if (_selectedDevices.any((device) => device.uuid == selectedUuid)) {
_selectedDevices.removeWhere((device) => device.uuid == selectedUuid);
} else { } else {
_selectedDevices.add(event.selectedDevice); _selectedDevices.add(event.selectedDevice);
} }
@ -130,6 +135,9 @@ class DeviceManagementBloc
void _onSearchDevices( void _onSearchDevices(
SearchDevices event, Emitter<DeviceManagementState> emit) { SearchDevices event, Emitter<DeviceManagementState> emit) {
if (_devices.isNotEmpty) { if (_devices.isNotEmpty) {
_selectedDevices.clear();
_selectedIndex = 0;
final filteredDevices = _devices.where((device) { final filteredDevices = _devices.where((device) {
final matchesCommunity = event.community == null || final matchesCommunity = event.community == null ||
event.community!.isEmpty || event.community!.isEmpty ||
@ -151,7 +159,6 @@ class DeviceManagementBloc
false); false);
return matchesCommunity && matchesUnit && matchesProductName; return matchesCommunity && matchesUnit && matchesProductName;
}).toList(); }).toList();
_selectedDevices = [];
emit(DeviceManagementFiltered( emit(DeviceManagementFiltered(
filteredDevices: filteredDevices, filteredDevices: filteredDevices,
selectedIndex: 0, selectedIndex: 0,

View File

@ -42,6 +42,10 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
offlineCount = state.offlineCount; offlineCount = state.offlineCount;
lowBatteryCount = state.lowBatteryCount; lowBatteryCount = state.lowBatteryCount;
isControlButtonEnabled = state.selectedDevice != null; isControlButtonEnabled = state.selectedDevice != null;
} else if (state is DeviceManagementInitial) {
devicesToShow = [];
selectedIndex = 0;
isControlButtonEnabled = false;
} }
final tabs = [ final tabs = [
@ -125,6 +129,7 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
}, },
withCheckBox: true, withCheckBox: true,
size: context.screenSize, size: context.screenSize,
uuidIndex: 2,
headers: const [ headers: const [
'Device Name', 'Device Name',
'Product Name', 'Product Name',
@ -153,10 +158,15 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
(device.updateTime ?? 0) * 1000)), (device.updateTime ?? 0) * 1000)),
]; ];
}).toList(), }).toList(),
initialSelectedIds: context
.read<DeviceManagementBloc>()
.selectedDevices
.map((device) => device.uuid!)
.toList(),
isEmpty: devicesToShow.isEmpty, isEmpty: devicesToShow.isEmpty,
), ),
), ),
), )
], ],
); );
}, },

View File

@ -16,11 +16,11 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
final BuchheimWalkerConfiguration builder = BuchheimWalkerConfiguration(); final BuchheimWalkerConfiguration builder = BuchheimWalkerConfiguration();
List<Node> sourcesList = []; List<Node> sourcesList = [];
List<Node> destinationsList = []; List<Node> destinationsList = [];
static UserModel? user; UserModel? user;
HomeBloc() : super((HomeInitial())) { HomeBloc() : super((HomeInitial())) {
on<CreateNewNode>(_createNode); on<CreateNewNode>(_createNode);
fetchUserInfo(); on<FetchUserInfo>(_fetchUserInfo);
} }
void _createNode(CreateNewNode event, Emitter<HomeState> emit) async { void _createNode(CreateNewNode event, Emitter<HomeState> emit) async {
@ -39,10 +39,12 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
emit(HomeUpdateTree(graph: graph, builder: builder)); emit(HomeUpdateTree(graph: graph, builder: builder));
} }
static Future fetchUserInfo() async { Future _fetchUserInfo(FetchUserInfo event, Emitter<HomeState> emit) async {
try { try {
var uuid = await const FlutterSecureStorage().read(key: UserModel.userUuidKey); var uuid =
await const FlutterSecureStorage().read(key: UserModel.userUuidKey);
user = await HomeApi().fetchUserInfo(uuid); user = await HomeApi().fetchUserInfo(uuid);
emit(HomeInitial());
} catch (e) { } catch (e) {
return; return;
} }

View File

@ -17,3 +17,7 @@ class CreateNewNode extends HomeEvent {
@override @override
List<Object> get props => [sourceNode, destinationNode]; List<Object> get props => [sourceNode, destinationNode];
} }
class FetchUserInfo extends HomeEvent {
const FetchUserInfo();
}

View File

@ -1,11 +1,25 @@
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/home/bloc/home_bloc.dart';
import 'package:syncrow_web/pages/home/bloc/home_event.dart';
import 'package:syncrow_web/pages/home/view/home_page_mobile.dart'; import 'package:syncrow_web/pages/home/view/home_page_mobile.dart';
import 'package:syncrow_web/pages/home/view/home_page_web.dart'; import 'package:syncrow_web/pages/home/view/home_page_web.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';
class HomePage extends StatelessWidget with HelperResponsiveLayout { class HomePage extends StatefulWidget {
const HomePage({super.key}); const HomePage({super.key});
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> with HelperResponsiveLayout {
@override
void initState() {
super.initState();
context.read<HomeBloc>().add(const FetchUserInfo());
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final isSmallScreen = isSmallScreenSize(context); final isSmallScreen = isSmallScreenSize(context);

View File

@ -10,6 +10,7 @@ import 'package:syncrow_web/web_layout/web_scaffold.dart';
class HomeMobilePage extends StatelessWidget { class HomeMobilePage extends StatelessWidget {
HomeMobilePage({super.key}); HomeMobilePage({super.key});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size; Size size = MediaQuery.of(context).size;
@ -79,7 +80,7 @@ class HomeMobilePage extends StatelessWidget {
); );
} }
dynamic homeItems = [ final dynamic homeItems = [
{ {
'title': 'Access', 'title': 'Access',
'icon': Assets.accessIcon, 'icon': Assets.accessIcon,

View File

@ -184,6 +184,7 @@ class AddDeviceDialog extends StatelessWidget {
}, },
withCheckBox: true, withCheckBox: true,
size: size * 0.5, size: size * 0.5,
uuidIndex: 1,
headers: const [ headers: const [
'Device Name', 'Device Name',
'Device ID', 'Device ID',

View File

@ -15,13 +15,14 @@ class WebAppBar extends StatelessWidget with HelperResponsiveLayout {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
bool isSmallScreen = isSmallScreenSize(context); bool isSmallScreen = isSmallScreenSize(context);
bool isHalfMediumScreen = isHafMediumScreenSize(context);
return BlocBuilder<HomeBloc, HomeState>(builder: (context, state) { return BlocBuilder<HomeBloc, HomeState>(builder: (context, state) {
final user = context.read<HomeBloc>().user;
return Container( return Container(
height: isSmallScreen ? 130 : 100, height: (isSmallScreen || isHalfMediumScreen) ? 130 : 100,
decoration: const BoxDecoration(color: ColorsManager.secondaryColor), decoration: const BoxDecoration(color: ColorsManager.secondaryColor),
padding: const EdgeInsets.all(10), padding: const EdgeInsets.all(10),
child: isSmallScreen child: isSmallScreen || isHalfMediumScreen
? Column( ? Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -31,14 +32,11 @@ class WebAppBar extends StatelessWidget with HelperResponsiveLayout {
child: title!, child: title!,
), ),
if (centerBody != null) if (centerBody != null)
Align( Padding(
alignment: Alignment.centerLeft, padding: const EdgeInsets.only(top: 8.0),
child: Padding( child: centerBody,
padding: const EdgeInsets.only(top: 8.0),
child: centerBody,
),
), ),
if (rightBody != null || HomeBloc.user != null) if (rightBody != null || user != null)
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
@ -61,9 +59,9 @@ class WebAppBar extends StatelessWidget with HelperResponsiveLayout {
const SizedBox( const SizedBox(
width: 10, width: 10,
), ),
if (HomeBloc.user != null) if (user != null)
Text( Text(
'${HomeBloc.user!.firstName} ${HomeBloc.user!.lastName}', '${user.firstName} ${user.lastName}',
style: Theme.of(context).textTheme.bodyLarge, style: Theme.of(context).textTheme.bodyLarge,
), ),
], ],
@ -78,14 +76,19 @@ class WebAppBar extends StatelessWidget with HelperResponsiveLayout {
children: [ children: [
Align( Align(
alignment: Alignment.centerLeft, alignment: Alignment.centerLeft,
child: title!, child: Expanded(
), child: Row(
if (centerBody != null) children: [
Expanded( title!,
child: Center( if (centerBody != null)
child: centerBody, Padding(
padding: const EdgeInsets.only(left: 80),
child: centerBody!,
),
],
), ),
), ),
),
Row( Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
@ -113,9 +116,9 @@ class WebAppBar extends StatelessWidget with HelperResponsiveLayout {
const SizedBox( const SizedBox(
width: 10, width: 10,
), ),
if (HomeBloc.user != null) if (user != null)
Text( Text(
'${HomeBloc.user!.firstName} ${HomeBloc.user!.lastName}', '${user.firstName} ${user.lastName}',
style: Theme.of(context).textTheme.bodyLarge, style: Theme.of(context).textTheme.bodyLarge,
), ),
], ],