switch from children / grandchilden to full space tree. Resolve error with data from visible chats also being counted in private chat analytics
This commit is contained in:
parent
9b6466c09c
commit
2b4ada3202
6 changed files with 69 additions and 88 deletions
|
|
@ -129,6 +129,15 @@ class AnalyticsController extends BaseController {
|
|||
return null;
|
||||
}
|
||||
|
||||
// Map of space ids to the last fetched hierarchy. Used when filtering
|
||||
// private chat analytics to determine which children are already visible
|
||||
// in the chat list
|
||||
final Map<String, List<String>> _lastFetchedHierarchies = {};
|
||||
void setLatestHierarchy(String spaceId, GetSpaceHierarchyResponse resp) {
|
||||
final List<String> roomIds = resp.rooms.map((room) => room.roomId).toList();
|
||||
_lastFetchedHierarchies[spaceId] = roomIds;
|
||||
}
|
||||
|
||||
//////////////////////////// MESSAGE SUMMARY ANALYTICS ////////////////////////////
|
||||
|
||||
Future<List<SummaryAnalyticsEvent>> mySummaryAnalytics() async {
|
||||
|
|
@ -188,10 +197,7 @@ class AnalyticsController extends BaseController {
|
|||
}
|
||||
}
|
||||
|
||||
// get a list of all the space's children, including sub-space children
|
||||
final resp = await space.client.getSpaceHierarchy(space.id);
|
||||
final List<String> spaceChildrenIds =
|
||||
resp.rooms.map((room) => room.roomId).toList();
|
||||
final List<String> spaceChildrenIds = space.allSpaceChildRoomIds;
|
||||
|
||||
// filter out the analyics events that don't belong to the space's children
|
||||
final List<SummaryAnalyticsEvent> allAnalyticsEvents = [];
|
||||
|
|
@ -288,22 +294,32 @@ class AnalyticsController extends BaseController {
|
|||
return filtered;
|
||||
}
|
||||
|
||||
List<SummaryAnalyticsEvent> filterPrivateChatAnalytics(
|
||||
Future<List<SummaryAnalyticsEvent>> filterPrivateChatAnalytics(
|
||||
List<SummaryAnalyticsEvent> unfiltered,
|
||||
Room? space,
|
||||
) {
|
||||
final List<String> directChatIds =
|
||||
space?.childrenAndGrandChildrenDirectChatIds ?? [];
|
||||
) async {
|
||||
if (space != null && !_lastFetchedHierarchies.containsKey(space.id)) {
|
||||
final resp = await _pangeaController.matrixState.client
|
||||
.getSpaceHierarchy(space.id);
|
||||
setLatestHierarchy(space.id, resp);
|
||||
}
|
||||
|
||||
final List<String> privateChatIds = space?.allSpaceChildRoomIds ?? [];
|
||||
final List<String> lastFetched = _lastFetchedHierarchies[space!.id] ?? [];
|
||||
for (final id in lastFetched) {
|
||||
privateChatIds.removeWhere((e) => e == id);
|
||||
}
|
||||
|
||||
List<SummaryAnalyticsEvent> filtered =
|
||||
List<SummaryAnalyticsEvent>.from(unfiltered);
|
||||
filtered = filtered.where((e) {
|
||||
return (e.content).messages.any(
|
||||
(u) => directChatIds.contains(u.chatId),
|
||||
(u) => privateChatIds.contains(u.chatId),
|
||||
);
|
||||
}).toList();
|
||||
filtered.forEachIndexed(
|
||||
(i, _) => (filtered[i].content).messages.removeWhere(
|
||||
(u) => !directChatIds.contains(u.chatId),
|
||||
(u) => !privateChatIds.contains(u.chatId),
|
||||
),
|
||||
);
|
||||
return filtered;
|
||||
|
|
@ -369,7 +385,10 @@ class AnalyticsController extends BaseController {
|
|||
if (defaultSelected.type == AnalyticsEntryType.student) {
|
||||
throw "private chat filtering not available for my analytics";
|
||||
}
|
||||
return filterPrivateChatAnalytics(unfilteredAnalytics, space);
|
||||
return await filterPrivateChatAnalytics(
|
||||
unfilteredAnalytics,
|
||||
space,
|
||||
);
|
||||
case AnalyticsEntryType.space:
|
||||
return filterSpaceAnalytics(unfilteredAnalytics, selected!.id);
|
||||
default:
|
||||
|
|
@ -573,10 +592,7 @@ class AnalyticsController extends BaseController {
|
|||
}
|
||||
}
|
||||
|
||||
final resp = await space.client.getSpaceHierarchy(space.id);
|
||||
final List<String> spaceChildrenIds =
|
||||
resp.rooms.map((room) => room.roomId).toList();
|
||||
|
||||
final List<String> spaceChildrenIds = space.allSpaceChildRoomIds;
|
||||
final List<ConstructAnalyticsEvent> allConstructs = [];
|
||||
for (final constructEvent in constructEvents) {
|
||||
final lemmaUses = constructEvent.content.uses;
|
||||
|
|
@ -622,8 +638,7 @@ class AnalyticsController extends BaseController {
|
|||
List<ConstructAnalyticsEvent> unfilteredConstructs,
|
||||
Room parentSpace,
|
||||
) {
|
||||
final List<String> directChatIds =
|
||||
parentSpace.childrenAndGrandChildrenDirectChatIds;
|
||||
final List<String> directChatIds = [];
|
||||
final List<ConstructAnalyticsEvent> filtered =
|
||||
List<ConstructAnalyticsEvent>.from(unfilteredConstructs);
|
||||
for (final construct in filtered) {
|
||||
|
|
|
|||
|
|
@ -5,11 +5,7 @@ extension GeneralInfoClientExtension on Client {
|
|||
final List<String> adminRoomIds = [];
|
||||
for (final Room adminSpace in (await _classesAndExchangesImTeaching)) {
|
||||
adminRoomIds.add(adminSpace.id);
|
||||
final children = adminSpace.childrenAndGrandChildren;
|
||||
final List<String> adminSpaceRooms = children
|
||||
.where((e) => e.roomId != null)
|
||||
.map((e) => e.roomId!)
|
||||
.toList();
|
||||
final List<String> adminSpaceRooms = adminSpace.allSpaceChildRoomIds;
|
||||
adminRoomIds.addAll(adminSpaceRooms);
|
||||
}
|
||||
return adminRoomIds;
|
||||
|
|
|
|||
|
|
@ -20,57 +20,6 @@ extension ChildrenAndParentsRoomExtension on Room {
|
|||
List<String> get _joinedChildrenRoomIds =>
|
||||
joinedChildren.map((child) => child.id).toList();
|
||||
|
||||
List<SpaceChild> get _childrenAndGrandChildren {
|
||||
if (!isSpace) return [];
|
||||
final List<SpaceChild> kids = [];
|
||||
for (final child in spaceChildren) {
|
||||
kids.add(child);
|
||||
if (child.roomId != null) {
|
||||
final Room? childRoom = client.getRoomById(child.roomId!);
|
||||
if (childRoom != null && childRoom.isSpace) {
|
||||
kids.addAll(childRoom.spaceChildren);
|
||||
}
|
||||
}
|
||||
}
|
||||
return kids.where((element) => element.roomId != null).toList();
|
||||
}
|
||||
|
||||
//this assumes that a user has been invited to all group chats in a space
|
||||
//it is a janky workaround for determining whether a spacechild is a direct chat
|
||||
//since the spaceChild object doesn't contain this info. this info is only accessible
|
||||
//when the user has joined or been invited to the room. direct chats included in
|
||||
//a space show up in spaceChildren but the user has not been invited to them.
|
||||
List<String> get _childrenAndGrandChildrenDirectChatIds {
|
||||
final List<String> nonDirectChatRoomIds = childrenAndGrandChildren
|
||||
.where((child) => child.roomId != null)
|
||||
.map((e) => client.getRoomById(e.roomId!))
|
||||
.where((r) => r != null && !r.isDirectChat)
|
||||
.map((e) => e!.id)
|
||||
.toList();
|
||||
|
||||
return childrenAndGrandChildren
|
||||
.where(
|
||||
(child) =>
|
||||
child.roomId != null &&
|
||||
!nonDirectChatRoomIds.contains(child.roomId),
|
||||
)
|
||||
.map((e) => e.roomId)
|
||||
.cast<String>()
|
||||
.toList();
|
||||
|
||||
// return childrenAndGrandChildren
|
||||
// .where((element) => element.roomId != null)
|
||||
// .where(
|
||||
// (child) {
|
||||
// final room = client.getRoomById(child.roomId!);
|
||||
// return room == null || room.isDirectChat;
|
||||
// },
|
||||
// )
|
||||
// .map((e) => e.roomId)
|
||||
// .cast<String>()
|
||||
// .toList();
|
||||
}
|
||||
|
||||
Future<List<Room>> _getChildRooms() async {
|
||||
final List<Room> children = [];
|
||||
for (final child in spaceChildren) {
|
||||
|
|
@ -145,4 +94,19 @@ extension ChildrenAndParentsRoomExtension on Room {
|
|||
),
|
||||
)
|
||||
.toList();
|
||||
|
||||
// gets all space children of a given space, down the
|
||||
// space tree.
|
||||
List<String> get _allSpaceChildRoomIds {
|
||||
final List<String> childIds = [];
|
||||
for (final child in spaceChildren) {
|
||||
if (child.roomId == null) continue;
|
||||
childIds.add(child.roomId!);
|
||||
final Room? room = client.getRoomById(child.roomId!);
|
||||
if (room != null && room.isSpace) {
|
||||
childIds.addAll(room._allSpaceChildRoomIds);
|
||||
}
|
||||
}
|
||||
return childIds;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ import 'package:future_loading_dialog/future_loading_dialog.dart';
|
|||
import 'package:html_unescape/html_unescape.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
import 'package:matrix/src/utils/markdown.dart';
|
||||
import 'package:matrix/src/utils/space_child.dart';
|
||||
import 'package:sentry_flutter/sentry_flutter.dart';
|
||||
|
||||
import '../../../config/app_config.dart';
|
||||
|
|
@ -98,11 +97,6 @@ extension PangeaRoom on Room {
|
|||
|
||||
List<String> get joinedChildrenRoomIds => _joinedChildrenRoomIds;
|
||||
|
||||
List<SpaceChild> get childrenAndGrandChildren => _childrenAndGrandChildren;
|
||||
|
||||
List<String> get childrenAndGrandChildrenDirectChatIds =>
|
||||
_childrenAndGrandChildrenDirectChatIds;
|
||||
|
||||
Future<List<Room>> getChildRooms() async => await _getChildRooms();
|
||||
|
||||
Future<void> joinSpaceChild(String roomID) async =>
|
||||
|
|
@ -115,6 +109,8 @@ extension PangeaRoom on Room {
|
|||
|
||||
List<Room> get pangeaSpaceParents => _pangeaSpaceParents;
|
||||
|
||||
List<String> get allSpaceChildRoomIds => _allSpaceChildRoomIds;
|
||||
|
||||
// class_and_exchange_settings
|
||||
|
||||
DateTime? get rulesUpdatedAt => _rulesUpdatedAt;
|
||||
|
|
|
|||
|
|
@ -94,15 +94,18 @@ class BaseAnalyticsController extends State<BaseAnalyticsPage> {
|
|||
}
|
||||
|
||||
Future<void> onRefresh() async {
|
||||
await showFutureLoadingDialog(
|
||||
context: context,
|
||||
future: () async {
|
||||
debugPrint("updating analytics");
|
||||
await pangeaController.myAnalytics.updateAnalytics();
|
||||
await setChartData(forceUpdate: true);
|
||||
refreshStream.add(true);
|
||||
},
|
||||
);
|
||||
// postframe callback to avoid calling this function during build
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||
await showFutureLoadingDialog(
|
||||
context: context,
|
||||
future: () async {
|
||||
debugPrint("updating analytics");
|
||||
await pangeaController.myAnalytics.updateAnalytics();
|
||||
await setChartData(forceUpdate: true);
|
||||
refreshStream.add(true);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Future<ChartAnalyticsModel> fetchChartData(
|
||||
|
|
|
|||
|
|
@ -70,6 +70,13 @@ class ClassAnalyticsV2Controller extends State<ClassAnalyticsPage> {
|
|||
final response = await Matrix.of(context).client.getSpaceHierarchy(
|
||||
classRoom!.id,
|
||||
);
|
||||
|
||||
// set the latest fetched full hierarchy in message analytics controller
|
||||
// we want to avoid calling this endpoint again and again, so whenever the
|
||||
// data is made available, set it in the controller
|
||||
MatrixState.pangeaController.analytics
|
||||
.setLatestHierarchy(_classRoom!.id, response);
|
||||
|
||||
students = classRoom!.students;
|
||||
chats = response.rooms
|
||||
.where(
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue