mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-09 22:57:21 +00:00
fix selection from dynamic table
This commit is contained in:
@ -82,6 +82,7 @@ class AccessManagementPage extends StatelessWidget with HelperResponsiveLayout {
|
||||
const SizedBox(height: 20),
|
||||
Expanded(
|
||||
child: DynamicTable(
|
||||
uuidIndex: 0,
|
||||
isEmpty: filteredData.isEmpty,
|
||||
withCheckBox: false,
|
||||
size: MediaQuery.of(context).size,
|
||||
|
@ -14,6 +14,7 @@ class DynamicTable extends StatefulWidget {
|
||||
final void Function(bool?)? selectAll;
|
||||
final void Function(int, bool, dynamic)? onRowSelected;
|
||||
final List<String>? initialSelectedIds;
|
||||
final int uuidIndex;
|
||||
const DynamicTable({
|
||||
super.key,
|
||||
required this.headers,
|
||||
@ -26,6 +27,7 @@ class DynamicTable extends StatefulWidget {
|
||||
this.selectAll,
|
||||
this.onRowSelected,
|
||||
this.initialSelectedIds,
|
||||
required this.uuidIndex,
|
||||
});
|
||||
|
||||
@override
|
||||
@ -38,9 +40,24 @@ class _DynamicTableState extends State<DynamicTable> {
|
||||
@override
|
||||
void 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) {
|
||||
// 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 &&
|
||||
widget.initialSelectedIds!.contains(widget.data[index][1]);
|
||||
widget.initialSelectedIds!.contains(deviceUuid);
|
||||
});
|
||||
}
|
||||
|
||||
@ -71,8 +88,7 @@ class _DynamicTableState extends State<DynamicTable> {
|
||||
children: [
|
||||
if (widget.withCheckBox) _buildSelectAllCheckbox(),
|
||||
...widget.headers
|
||||
.map((header) => _buildTableHeaderCell(header))
|
||||
.toList(),
|
||||
.map((header) => _buildTableHeaderCell(header)),
|
||||
],
|
||||
),
|
||||
),
|
||||
@ -119,11 +135,9 @@ class _DynamicTableState extends State<DynamicTable> {
|
||||
if (widget.withCheckBox)
|
||||
_buildRowCheckbox(
|
||||
index, widget.size.height * 0.10),
|
||||
...row
|
||||
.map((cell) => _buildTableCell(
|
||||
cell.toString(),
|
||||
widget.size.height * 0.10))
|
||||
.toList(),
|
||||
...row.map((cell) => _buildTableCell(
|
||||
cell.toString(),
|
||||
widget.size.height * 0.10)),
|
||||
],
|
||||
);
|
||||
},
|
||||
|
@ -28,11 +28,12 @@ class DeviceManagementBloc
|
||||
emit(DeviceManagementLoading());
|
||||
try {
|
||||
final devices = await DevicesManagementApi().fetchDevices();
|
||||
_selectedDevices.clear();
|
||||
_devices = devices;
|
||||
_calculateDeviceCounts();
|
||||
emit(DeviceManagementLoaded(
|
||||
devices: devices,
|
||||
selectedIndex: _selectedIndex,
|
||||
selectedIndex: 0,
|
||||
onlineCount: _onlineCount,
|
||||
offlineCount: _offlineCount,
|
||||
lowBatteryCount: _lowBatteryCount,
|
||||
@ -64,6 +65,8 @@ class DeviceManagementBloc
|
||||
onlineCount: _onlineCount,
|
||||
offlineCount: _offlineCount,
|
||||
lowBatteryCount: _lowBatteryCount,
|
||||
selectedDevice:
|
||||
_selectedDevices.isNotEmpty ? _selectedDevices.first : null,
|
||||
));
|
||||
}
|
||||
}
|
||||
@ -76,8 +79,10 @@ class DeviceManagementBloc
|
||||
|
||||
void _onSelectDevice(
|
||||
SelectDevice event, Emitter<DeviceManagementState> emit) {
|
||||
if (_selectedDevices.contains(event.selectedDevice)) {
|
||||
_selectedDevices.remove(event.selectedDevice);
|
||||
final selectedUuid = event.selectedDevice.uuid;
|
||||
|
||||
if (_selectedDevices.any((device) => device.uuid == selectedUuid)) {
|
||||
_selectedDevices.removeWhere((device) => device.uuid == selectedUuid);
|
||||
} else {
|
||||
_selectedDevices.add(event.selectedDevice);
|
||||
}
|
||||
@ -130,6 +135,9 @@ class DeviceManagementBloc
|
||||
void _onSearchDevices(
|
||||
SearchDevices event, Emitter<DeviceManagementState> emit) {
|
||||
if (_devices.isNotEmpty) {
|
||||
_selectedDevices.clear();
|
||||
_selectedIndex = 0;
|
||||
|
||||
final filteredDevices = _devices.where((device) {
|
||||
final matchesCommunity = event.community == null ||
|
||||
event.community!.isEmpty ||
|
||||
@ -151,7 +159,6 @@ class DeviceManagementBloc
|
||||
false);
|
||||
return matchesCommunity && matchesUnit && matchesProductName;
|
||||
}).toList();
|
||||
_selectedDevices = [];
|
||||
emit(DeviceManagementFiltered(
|
||||
filteredDevices: filteredDevices,
|
||||
selectedIndex: 0,
|
||||
|
@ -42,6 +42,10 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
|
||||
offlineCount = state.offlineCount;
|
||||
lowBatteryCount = state.lowBatteryCount;
|
||||
isControlButtonEnabled = state.selectedDevice != null;
|
||||
} else if (state is DeviceManagementInitial) {
|
||||
devicesToShow = [];
|
||||
selectedIndex = 0;
|
||||
isControlButtonEnabled = false;
|
||||
}
|
||||
|
||||
final tabs = [
|
||||
@ -125,6 +129,7 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
|
||||
},
|
||||
withCheckBox: true,
|
||||
size: context.screenSize,
|
||||
uuidIndex: 2,
|
||||
headers: const [
|
||||
'Device Name',
|
||||
'Product Name',
|
||||
@ -153,10 +158,15 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
|
||||
(device.updateTime ?? 0) * 1000)),
|
||||
];
|
||||
}).toList(),
|
||||
initialSelectedIds: context
|
||||
.read<DeviceManagementBloc>()
|
||||
.selectedDevices
|
||||
.map((device) => device.uuid!)
|
||||
.toList(),
|
||||
isEmpty: devicesToShow.isEmpty,
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
);
|
||||
},
|
||||
|
@ -16,11 +16,11 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
|
||||
final BuchheimWalkerConfiguration builder = BuchheimWalkerConfiguration();
|
||||
List<Node> sourcesList = [];
|
||||
List<Node> destinationsList = [];
|
||||
static UserModel? user;
|
||||
UserModel? user;
|
||||
|
||||
HomeBloc() : super((HomeInitial())) {
|
||||
on<CreateNewNode>(_createNode);
|
||||
fetchUserInfo();
|
||||
on<FetchUserInfo>(_fetchUserInfo);
|
||||
}
|
||||
|
||||
void _createNode(CreateNewNode event, Emitter<HomeState> emit) async {
|
||||
@ -39,10 +39,12 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
|
||||
emit(HomeUpdateTree(graph: graph, builder: builder));
|
||||
}
|
||||
|
||||
static Future fetchUserInfo() async {
|
||||
Future _fetchUserInfo(FetchUserInfo event, Emitter<HomeState> emit) async {
|
||||
try {
|
||||
var uuid = await const FlutterSecureStorage().read(key: UserModel.userUuidKey);
|
||||
var uuid =
|
||||
await const FlutterSecureStorage().read(key: UserModel.userUuidKey);
|
||||
user = await HomeApi().fetchUserInfo(uuid);
|
||||
emit(HomeInitial());
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
|
@ -17,3 +17,7 @@ class CreateNewNode extends HomeEvent {
|
||||
@override
|
||||
List<Object> get props => [sourceNode, destinationNode];
|
||||
}
|
||||
|
||||
class FetchUserInfo extends HomeEvent {
|
||||
const FetchUserInfo();
|
||||
}
|
@ -1,11 +1,25 @@
|
||||
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_web.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});
|
||||
|
||||
@override
|
||||
State<HomePage> createState() => _HomePageState();
|
||||
}
|
||||
|
||||
class _HomePageState extends State<HomePage> with HelperResponsiveLayout {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
context.read<HomeBloc>().add(const FetchUserInfo());
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final isSmallScreen = isSmallScreenSize(context);
|
||||
|
@ -10,6 +10,7 @@ import 'package:syncrow_web/web_layout/web_scaffold.dart';
|
||||
|
||||
class HomeMobilePage extends StatelessWidget {
|
||||
HomeMobilePage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Size size = MediaQuery.of(context).size;
|
||||
@ -79,7 +80,7 @@ class HomeMobilePage extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
dynamic homeItems = [
|
||||
final dynamic homeItems = [
|
||||
{
|
||||
'title': 'Access',
|
||||
'icon': Assets.accessIcon,
|
||||
|
@ -184,6 +184,7 @@ class AddDeviceDialog extends StatelessWidget {
|
||||
},
|
||||
withCheckBox: true,
|
||||
size: size * 0.5,
|
||||
uuidIndex: 1,
|
||||
headers: const [
|
||||
'Device Name',
|
||||
'Device ID',
|
||||
|
@ -15,13 +15,14 @@ class WebAppBar extends StatelessWidget with HelperResponsiveLayout {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
bool isSmallScreen = isSmallScreenSize(context);
|
||||
|
||||
bool isHalfMediumScreen = isHafMediumScreenSize(context);
|
||||
return BlocBuilder<HomeBloc, HomeState>(builder: (context, state) {
|
||||
final user = context.read<HomeBloc>().user;
|
||||
return Container(
|
||||
height: isSmallScreen ? 130 : 100,
|
||||
height: (isSmallScreen || isHalfMediumScreen) ? 130 : 100,
|
||||
decoration: const BoxDecoration(color: ColorsManager.secondaryColor),
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: isSmallScreen
|
||||
child: isSmallScreen || isHalfMediumScreen
|
||||
? Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
@ -31,14 +32,11 @@ class WebAppBar extends StatelessWidget with HelperResponsiveLayout {
|
||||
child: title!,
|
||||
),
|
||||
if (centerBody != null)
|
||||
Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: centerBody,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: centerBody,
|
||||
),
|
||||
if (rightBody != null || HomeBloc.user != null)
|
||||
if (rightBody != null || user != null)
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
@ -61,9 +59,9 @@ class WebAppBar extends StatelessWidget with HelperResponsiveLayout {
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
if (HomeBloc.user != null)
|
||||
if (user != null)
|
||||
Text(
|
||||
'${HomeBloc.user!.firstName} ${HomeBloc.user!.lastName}',
|
||||
'${user.firstName} ${user.lastName}',
|
||||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
),
|
||||
],
|
||||
@ -78,14 +76,19 @@ class WebAppBar extends StatelessWidget with HelperResponsiveLayout {
|
||||
children: [
|
||||
Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: title!,
|
||||
),
|
||||
if (centerBody != null)
|
||||
Expanded(
|
||||
child: Center(
|
||||
child: centerBody,
|
||||
child: Expanded(
|
||||
child: Row(
|
||||
children: [
|
||||
title!,
|
||||
if (centerBody != null)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 80),
|
||||
child: centerBody!,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
@ -113,9 +116,9 @@ class WebAppBar extends StatelessWidget with HelperResponsiveLayout {
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
if (HomeBloc.user != null)
|
||||
if (user != null)
|
||||
Text(
|
||||
'${HomeBloc.user!.firstName} ${HomeBloc.user!.lastName}',
|
||||
'${user.firstName} ${user.lastName}',
|
||||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
),
|
||||
],
|
||||
|
Reference in New Issue
Block a user