mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-10 15:17:31 +00:00
matched community and space models with API.
This commit is contained in:
@ -2,12 +2,12 @@ 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/shared/navigate_home_grid_view.dart';
|
import 'package:syncrow_web/pages/device_managment/shared/navigate_home_grid_view.dart';
|
||||||
import 'package:syncrow_web/pages/space_management_v2/main_module/widgets/space_management_body.dart';
|
import 'package:syncrow_web/pages/space_management_v2/main_module/widgets/space_management_body.dart';
|
||||||
import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain/models/communities_pagination_model.dart';
|
import 'package:syncrow_web/pages/space_management_v2/modules/communities/data/services/debounced_communities_service.dart';
|
||||||
import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain/models/community_model.dart';
|
import 'package:syncrow_web/pages/space_management_v2/modules/communities/data/services/remote_communities_service.dart';
|
||||||
import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain/params/load_communities_param.dart';
|
import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain/params/load_communities_param.dart';
|
||||||
import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain/services/communities_service.dart';
|
|
||||||
import 'package:syncrow_web/pages/space_management_v2/modules/communities/presentation/bloc/communities_bloc.dart';
|
import 'package:syncrow_web/pages/space_management_v2/modules/communities/presentation/bloc/communities_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/space_management_v2/modules/communities/presentation/communities_tree_selection_bloc/communities_tree_selection_bloc.dart';
|
import 'package:syncrow_web/pages/space_management_v2/modules/communities/presentation/communities_tree_selection_bloc/communities_tree_selection_bloc.dart';
|
||||||
|
import 'package:syncrow_web/services/api/http_service.dart';
|
||||||
import 'package:syncrow_web/utils/theme/responsive_text_theme.dart';
|
import 'package:syncrow_web/utils/theme/responsive_text_theme.dart';
|
||||||
import 'package:syncrow_web/web_layout/web_scaffold.dart';
|
import 'package:syncrow_web/web_layout/web_scaffold.dart';
|
||||||
|
|
||||||
@ -20,7 +20,9 @@ class SpaceManagementPage extends StatelessWidget {
|
|||||||
providers: [
|
providers: [
|
||||||
BlocProvider(
|
BlocProvider(
|
||||||
create: (context) => CommunitiesBloc(
|
create: (context) => CommunitiesBloc(
|
||||||
communitiesService: _FakeCommunitiesService(),
|
communitiesService: DebouncedCommunitiesService(
|
||||||
|
RemoteCommunitiesService(HTTPService()),
|
||||||
|
),
|
||||||
)..add(const LoadCommunities(LoadCommunitiesParam())),
|
)..add(const LoadCommunities(LoadCommunitiesParam())),
|
||||||
),
|
),
|
||||||
BlocProvider(create: (context) => CommunitiesTreeSelectionBloc()),
|
BlocProvider(create: (context) => CommunitiesTreeSelectionBloc()),
|
||||||
@ -43,23 +45,3 @@ class SpaceManagementPage extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _FakeCommunitiesService extends CommunitiesService {
|
|
||||||
@override
|
|
||||||
Future<CommunitiesPaginationModel> getCommunity(LoadCommunitiesParam param) {
|
|
||||||
return Future.value(const CommunitiesPaginationModel(
|
|
||||||
communities: [
|
|
||||||
CommunityModel(
|
|
||||||
uuid: '1',
|
|
||||||
name: 'Community 1',
|
|
||||||
spaces: [],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
page: 1,
|
|
||||||
size: 10,
|
|
||||||
hasNext: false,
|
|
||||||
totalItems: 2,
|
|
||||||
totalPages: 1,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -4,57 +4,44 @@ import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain
|
|||||||
import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain/params/load_communities_param.dart';
|
import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain/params/load_communities_param.dart';
|
||||||
import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain/services/communities_service.dart';
|
import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain/services/communities_service.dart';
|
||||||
|
|
||||||
class DebouncedCommunitiesService implements CommunitiesService {
|
final class DebouncedCommunitiesService implements CommunitiesService {
|
||||||
DebouncedCommunitiesService({
|
DebouncedCommunitiesService(
|
||||||
required CommunitiesService communitiesService,
|
this._decoratee, {
|
||||||
this.debounceDuration = const Duration(milliseconds: 400),
|
this.debounceDuration = const Duration(milliseconds: 500),
|
||||||
}) : _communitiesService = communitiesService;
|
});
|
||||||
|
|
||||||
final CommunitiesService _communitiesService;
|
final CommunitiesService _decoratee;
|
||||||
final Duration debounceDuration;
|
final Duration debounceDuration;
|
||||||
|
|
||||||
Timer? _debounceTimer;
|
Timer? _debounceTimer;
|
||||||
String _lastSearchQuery = '';
|
Completer<CommunitiesPaginationModel>? _completer;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<CommunitiesPaginationModel> getCommunity(
|
Future<CommunitiesPaginationModel> getCommunity(
|
||||||
LoadCommunitiesParam param,
|
LoadCommunitiesParam param,
|
||||||
) async {
|
) async {
|
||||||
if (param.search.isNotEmpty) {
|
|
||||||
return _getDebouncedCommunity(param);
|
|
||||||
}
|
|
||||||
|
|
||||||
return _communitiesService.getCommunity(param);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<CommunitiesPaginationModel> _getDebouncedCommunity(
|
|
||||||
LoadCommunitiesParam param,
|
|
||||||
) async {
|
|
||||||
final completer = Completer<CommunitiesPaginationModel>();
|
|
||||||
|
|
||||||
_debounceTimer?.cancel();
|
_debounceTimer?.cancel();
|
||||||
|
|
||||||
_lastSearchQuery = param.search;
|
if (_completer != null && !_completer!.isCompleted) {
|
||||||
|
_completer!.completeError(Exception('Request cancelled by newer request'));
|
||||||
|
}
|
||||||
|
|
||||||
|
_completer = Completer<CommunitiesPaginationModel>();
|
||||||
|
final currentCompleter = _completer!;
|
||||||
|
|
||||||
_debounceTimer = Timer(debounceDuration, () async {
|
_debounceTimer = Timer(debounceDuration, () async {
|
||||||
try {
|
try {
|
||||||
if (_lastSearchQuery == param.search) {
|
final result = await _decoratee.getCommunity(param);
|
||||||
final result = await _communitiesService.getCommunity(param);
|
if (!currentCompleter.isCompleted) {
|
||||||
if (!completer.isCompleted) {
|
currentCompleter.complete(result);
|
||||||
completer.complete(result);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!completer.isCompleted) {
|
|
||||||
completer.complete(const CommunitiesPaginationModel.empty());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (!completer.isCompleted) {
|
if (!currentCompleter.isCompleted) {
|
||||||
completer.completeError(error);
|
currentCompleter.completeError(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return completer.future;
|
return currentCompleter.future;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,10 +15,9 @@ class RemoteCommunitiesService implements CommunitiesService {
|
|||||||
static const _defaultErrorMessage = 'Failed to load communities';
|
static const _defaultErrorMessage = 'Failed to load communities';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<CommunitiesPaginationModel> getCommunity(LoadCommunitiesParam param) async {
|
Future<CommunitiesPaginationModel> getCommunity(
|
||||||
final projectUuid = await ProjectManager.getProjectUUID();
|
LoadCommunitiesParam param,
|
||||||
if (projectUuid == null) throw APIException('Project UUID is not set');
|
) async {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final response = await _httpService.get(
|
final response = await _httpService.get(
|
||||||
path: await _makeUrl(),
|
path: await _makeUrl(),
|
||||||
@ -26,10 +25,12 @@ class RemoteCommunitiesService implements CommunitiesService {
|
|||||||
'page': param.page,
|
'page': param.page,
|
||||||
'size': param.size,
|
'size': param.size,
|
||||||
'includeSpaces': param.includeSpaces,
|
'includeSpaces': param.includeSpaces,
|
||||||
if (param.search.isNotEmpty) 'search': param.search,
|
if (param.search.isNotEmpty && param.search != 'null')
|
||||||
|
'search': param.search,
|
||||||
},
|
},
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
return CommunitiesPaginationModel.fromJson(json as Map<String, dynamic>);
|
final data = json as Map<String, dynamic>;
|
||||||
|
return CommunitiesPaginationModel.fromJson(data);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -48,6 +49,9 @@ class RemoteCommunitiesService implements CommunitiesService {
|
|||||||
Future<String> _makeUrl() async {
|
Future<String> _makeUrl() async {
|
||||||
final projectUuid = await ProjectManager.getProjectUUID();
|
final projectUuid = await ProjectManager.getProjectUUID();
|
||||||
if (projectUuid == null) throw APIException('Project UUID is required');
|
if (projectUuid == null) throw APIException('Project UUID is required');
|
||||||
return ApiEndpoints.getCommunityList.replaceAll('{projectId}', projectUuid);
|
return ApiEndpoints.getCommunityListv2.replaceAll(
|
||||||
|
'{projectId}',
|
||||||
|
projectUuid,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,8 +34,8 @@ class CommunitiesPaginationModel extends Equatable {
|
|||||||
page: json['page'] as int? ?? 1,
|
page: json['page'] as int? ?? 1,
|
||||||
size: json['size'] as int? ?? 25,
|
size: json['size'] as int? ?? 25,
|
||||||
hasNext: json['hasNext'] as bool? ?? false,
|
hasNext: json['hasNext'] as bool? ?? false,
|
||||||
totalItems: json['totalItems'] as int? ?? 0,
|
totalItems: json['totalItem'] as int? ?? 0,
|
||||||
totalPages: json['totalPages'] as int? ?? 0,
|
totalPages: json['totalPage'] as int? ?? 0,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,11 +4,19 @@ import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain
|
|||||||
class CommunityModel extends Equatable {
|
class CommunityModel extends Equatable {
|
||||||
final String uuid;
|
final String uuid;
|
||||||
final String name;
|
final String name;
|
||||||
|
final DateTime createdAt;
|
||||||
|
final DateTime updatedAt;
|
||||||
|
final String description;
|
||||||
|
final String externalId;
|
||||||
final List<SpaceModel> spaces;
|
final List<SpaceModel> spaces;
|
||||||
|
|
||||||
const CommunityModel({
|
const CommunityModel({
|
||||||
required this.uuid,
|
required this.uuid,
|
||||||
required this.name,
|
required this.name,
|
||||||
|
required this.createdAt,
|
||||||
|
required this.updatedAt,
|
||||||
|
required this.description,
|
||||||
|
required this.externalId,
|
||||||
required this.spaces,
|
required this.spaces,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -16,6 +24,10 @@ class CommunityModel extends Equatable {
|
|||||||
return CommunityModel(
|
return CommunityModel(
|
||||||
uuid: json['uuid'] as String,
|
uuid: json['uuid'] as String,
|
||||||
name: json['name'] as String,
|
name: json['name'] as String,
|
||||||
|
createdAt: DateTime.parse(json['createdAt'] as String),
|
||||||
|
updatedAt: DateTime.parse(json['updatedAt'] as String),
|
||||||
|
description: json['description'] as String,
|
||||||
|
externalId: json['externalId'] as String,
|
||||||
spaces: (json['spaces'] as List<dynamic>)
|
spaces: (json['spaces'] as List<dynamic>)
|
||||||
.map((e) => SpaceModel.fromJson(e as Map<String, dynamic>))
|
.map((e) => SpaceModel.fromJson(e as Map<String, dynamic>))
|
||||||
.toList(),
|
.toList(),
|
||||||
|
@ -1,43 +1,38 @@
|
|||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
|
|
||||||
enum SpaceStatus {
|
|
||||||
active,
|
|
||||||
deleted,
|
|
||||||
parentDeleted;
|
|
||||||
|
|
||||||
static SpaceStatus getValueFromString(String value) => switch (value) {
|
|
||||||
'active' => active,
|
|
||||||
'deleted' => deleted,
|
|
||||||
'parentDeleted' => parentDeleted,
|
|
||||||
_ => active,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
class SpaceModel extends Equatable {
|
class SpaceModel extends Equatable {
|
||||||
final String uuid;
|
final String uuid;
|
||||||
|
final DateTime createdAt;
|
||||||
|
final DateTime updatedAt;
|
||||||
final String spaceName;
|
final String spaceName;
|
||||||
final String icon;
|
final String icon;
|
||||||
final List<SpaceModel> children;
|
final List<SpaceModel> children;
|
||||||
final SpaceStatus status;
|
final SpaceModel? parent;
|
||||||
|
|
||||||
const SpaceModel({
|
const SpaceModel({
|
||||||
required this.uuid,
|
required this.uuid,
|
||||||
|
required this.createdAt,
|
||||||
|
required this.updatedAt,
|
||||||
required this.spaceName,
|
required this.spaceName,
|
||||||
required this.icon,
|
required this.icon,
|
||||||
required this.children,
|
required this.children,
|
||||||
required this.status,
|
required this.parent,
|
||||||
});
|
});
|
||||||
|
|
||||||
factory SpaceModel.fromJson(Map<String, dynamic> json) {
|
factory SpaceModel.fromJson(Map<String, dynamic> json) {
|
||||||
return SpaceModel(
|
return SpaceModel(
|
||||||
uuid: json['uuid'] as String,
|
uuid: json['uuid'] as String,
|
||||||
|
createdAt: DateTime.parse(json['createdAt'] as String),
|
||||||
|
updatedAt: DateTime.parse(json['updatedAt'] as String),
|
||||||
spaceName: json['spaceName'] as String,
|
spaceName: json['spaceName'] as String,
|
||||||
icon: json['icon'] as String,
|
icon: json['icon'] as String,
|
||||||
children: (json['children'] as List<dynamic>?)
|
children: (json['children'] as List<dynamic>?)
|
||||||
?.map((e) => SpaceModel.fromJson(e as Map<String, dynamic>))
|
?.map((e) => SpaceModel.fromJson(e as Map<String, dynamic>))
|
||||||
.toList() ??
|
.toList() ??
|
||||||
[],
|
[],
|
||||||
status: SpaceStatus.getValueFromString(json['status'] as String),
|
parent: json['parent'] != null
|
||||||
|
? SpaceModel.fromJson(json['parent'] as Map<String, dynamic>)
|
||||||
|
: null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,7 +146,6 @@ class _SpaceManagementCommunitiesTreeState
|
|||||||
|
|
||||||
Widget _buildCommunityTile(BuildContext context, CommunityModel community) {
|
Widget _buildCommunityTile(BuildContext context, CommunityModel community) {
|
||||||
final spaces = community.spaces
|
final spaces = community.spaces
|
||||||
.where((space) => space.status == SpaceStatus.active)
|
|
||||||
.map((space) => _buildSpaceTile(
|
.map((space) => _buildSpaceTile(
|
||||||
space: space,
|
space: space,
|
||||||
community: community,
|
community: community,
|
||||||
|
@ -46,6 +46,7 @@ abstract class ApiEndpoints {
|
|||||||
// Community Module
|
// Community Module
|
||||||
static const String createCommunity = '/projects/{projectId}/communities';
|
static const String createCommunity = '/projects/{projectId}/communities';
|
||||||
static const String getCommunityList = '/projects/{projectId}/communities';
|
static const String getCommunityList = '/projects/{projectId}/communities';
|
||||||
|
static const String getCommunityListv2 = '/projects/{projectId}/communities/v2';
|
||||||
static const String getCommunityById =
|
static const String getCommunityById =
|
||||||
'/projects/{projectId}/communities/{communityId}';
|
'/projects/{projectId}/communities/{communityId}';
|
||||||
static const String updateCommunity =
|
static const String updateCommunity =
|
||||||
|
Reference in New Issue
Block a user