From 4355f1a2a1ea20d107c204d6b1b3f758b329b716 Mon Sep 17 00:00:00 2001 From: Bastian Rihm Date: Wed, 17 Apr 2024 15:20:17 +0200 Subject: [PATCH 1/6] Improve meeting user relation handling --- .../users/user-repository.service.ts | 16 ++++- .../pages/agenda/agenda.subscription.ts | 36 +----------- .../assignments/assignments.subscription.ts | 21 +------ .../pages/autopilot/autopilot.subscription.ts | 7 --- .../pages/motions/motions.subscription.ts | 58 ++----------------- .../participants/participants.subscription.ts | 8 +-- 6 files changed, 24 insertions(+), 122 deletions(-) diff --git a/client/src/app/gateways/repositories/users/user-repository.service.ts b/client/src/app/gateways/repositories/users/user-repository.service.ts index 5b8444dd94..4429b4df43 100644 --- a/client/src/app/gateways/repositories/users/user-repository.service.ts +++ b/client/src/app/gateways/repositories/users/user-repository.service.ts @@ -341,11 +341,21 @@ export class UserRepositoryService extends BaseRepository { const meetingUserIdMap = new Map(); const getMeetingUserId = (meetingId: Id) => { if (!meetingUserIdMap.has(meetingId)) { - for (const meetingUser of this.relationManager.handleRelation( + const meetingUsers = this.relationManager.handleRelation( viewModel.getModel(), this.relationsByKey[`meeting_users`] - )) { - meetingUserIdMap.set(meetingUser.meeting_id, meetingUser.id); + ); + + if (meetingUsers?.length) { + for (const meetingUser of meetingUsers) { + meetingUserIdMap.set(meetingUser.meeting_id, meetingUser.id); + } + } else { + for (const meetingUser of this.meetingUserRepo.getViewModelList()) { + if (meetingUser.user_id === model.id) { + meetingUserIdMap.set(meetingUser.meeting_id, meetingUser.id); + } + } } } diff --git a/client/src/app/site/pages/meetings/pages/agenda/agenda.subscription.ts b/client/src/app/site/pages/meetings/pages/agenda/agenda.subscription.ts index 1b03dc0009..d6e7914935 100644 --- a/client/src/app/site/pages/meetings/pages/agenda/agenda.subscription.ts +++ b/client/src/app/site/pages/meetings/pages/agenda/agenda.subscription.ts @@ -1,5 +1,5 @@ import { Id } from 'src/app/domain/definitions/key-types'; -import { FULL_FIELDSET, MEETING_ROUTING_FIELDS, mergeSubscriptionFollow } from 'src/app/domain/fieldsets/misc'; +import { FULL_FIELDSET, MEETING_ROUTING_FIELDS } from 'src/app/domain/fieldsets/misc'; import { MeetingUserFieldsets, UserFieldsets } from 'src/app/domain/fieldsets/user'; import { SubscriptionConfigGenerator } from 'src/app/domain/interfaces/subscription-config'; import { ViewMeeting } from 'src/app/site/pages/meetings/view-models/view-meeting'; @@ -23,21 +23,7 @@ export const agendaItemFollow: FollowList = [ idField: `speaker_ids`, fieldset: FULL_FIELDSET, follow: [ - mergeSubscriptionFollow( - { - idField: `meeting_user_id`, - follow: [ - mergeSubscriptionFollow( - { idField: `user_id`, ...UserFieldsets.FullNameSubscription }, - { - idField: `user_id`, - fieldset: [`meeting_user_ids`] - } - ) - ] - }, - { idField: `meeting_user_id`, ...MeetingUserFieldsets.FullNameSubscription } - ), + { idField: `meeting_user_id`, ...MeetingUserFieldsets.FullNameSubscription }, { idField: `point_of_order_category_id`, fieldset: FULL_FIELDSET @@ -72,23 +58,7 @@ export const getAgendaListSubscriptionConfig: SubscriptionConfigGenerator = (id: { idField: `submitter_ids`, fieldset: FULL_FIELDSET, - follow: [ - mergeSubscriptionFollow( - { - idField: `meeting_user_id`, - follow: [ - mergeSubscriptionFollow( - { idField: `user_id`, ...UserFieldsets.FullNameSubscription }, - { - idField: `user_id`, - fieldset: [`meeting_user_ids`] - } - ) - ] - }, - { idField: `meeting_user_id`, ...MeetingUserFieldsets.FullNameSubscription } - ) - ] + follow: [{ idField: `meeting_user_id`, ...MeetingUserFieldsets.FullNameSubscription }] } ] } diff --git a/client/src/app/site/pages/meetings/pages/assignments/assignments.subscription.ts b/client/src/app/site/pages/meetings/pages/assignments/assignments.subscription.ts index 867b587be1..ba69e5432f 100644 --- a/client/src/app/site/pages/meetings/pages/assignments/assignments.subscription.ts +++ b/client/src/app/site/pages/meetings/pages/assignments/assignments.subscription.ts @@ -1,6 +1,5 @@ import { Id } from 'src/app/domain/definitions/key-types'; -import { mergeSubscriptionFollow } from 'src/app/domain/fieldsets/misc'; -import { MeetingUserFieldsets, UserFieldsets } from 'src/app/domain/fieldsets/user'; +import { MeetingUserFieldsets } from 'src/app/domain/fieldsets/user'; import { SubscriptionConfigGenerator } from 'src/app/domain/interfaces/subscription-config'; import { ViewMeeting } from 'src/app/site/pages/meetings/view-models/view-meeting'; @@ -24,23 +23,7 @@ export const getAssignmentSubscriptionConfig: SubscriptionConfigGenerator = (id: }, { idField: `assignment_candidate_ids`, - follow: [ - mergeSubscriptionFollow( - { - idField: `meeting_user_id`, - follow: [ - mergeSubscriptionFollow( - { idField: `user_id`, ...UserFieldsets.FullNameSubscription }, - { - idField: `user_id`, - fieldset: [`meeting_user_ids`] - } - ) - ] - }, - { idField: `meeting_user_id`, ...MeetingUserFieldsets.FullNameSubscription } - ) - ] + follow: [{ idField: `meeting_user_id`, ...MeetingUserFieldsets.FullNameSubscription }] } ] }, diff --git a/client/src/app/site/pages/meetings/pages/autopilot/autopilot.subscription.ts b/client/src/app/site/pages/meetings/pages/autopilot/autopilot.subscription.ts index 61875bedb6..09bb857856 100644 --- a/client/src/app/site/pages/meetings/pages/autopilot/autopilot.subscription.ts +++ b/client/src/app/site/pages/meetings/pages/autopilot/autopilot.subscription.ts @@ -61,13 +61,6 @@ export const getAutopilotContentSubscriptionConfig = (id: Id): SubscriptionConfi { idField: `meeting_user_id`, follow: [ - mergeSubscriptionFollow( - { idField: `user_id`, ...UserFieldsets.FullNameSubscription }, - { - idField: `user_id`, - fieldset: [`meeting_user_ids`] - } - ), { idField: `structure_level_ids`, fieldset: [`name`, `color`] diff --git a/client/src/app/site/pages/meetings/pages/motions/motions.subscription.ts b/client/src/app/site/pages/meetings/pages/motions/motions.subscription.ts index 910c1d4c6d..da79017e59 100644 --- a/client/src/app/site/pages/meetings/pages/motions/motions.subscription.ts +++ b/client/src/app/site/pages/meetings/pages/motions/motions.subscription.ts @@ -1,6 +1,6 @@ import { Id } from 'src/app/domain/definitions/key-types'; -import { FULL_FIELDSET, mergeSubscriptionFollow } from 'src/app/domain/fieldsets/misc'; -import { MeetingUserFieldsets, UserFieldsets } from 'src/app/domain/fieldsets/user'; +import { FULL_FIELDSET } from 'src/app/domain/fieldsets/misc'; +import { MeetingUserFieldsets } from 'src/app/domain/fieldsets/user'; import { SubscriptionConfigGenerator } from 'src/app/domain/interfaces/subscription-config'; import { ViewMeeting } from 'src/app/site/pages/meetings/view-models/view-meeting'; @@ -72,65 +72,17 @@ export const getMotionListSubscriptionConfig: SubscriptionConfigGenerator = (id: { idField: `submitter_ids`, fieldset: FULL_FIELDSET, - follow: [ - mergeSubscriptionFollow( - { - idField: `meeting_user_id`, - follow: [ - mergeSubscriptionFollow( - { idField: `user_id`, ...UserFieldsets.FullNameSubscription }, - { - idField: `user_id`, - fieldset: [`meeting_user_ids`] - } - ) - ] - }, - { idField: `meeting_user_id`, ...MeetingUserFieldsets.FullNameSubscription } - ) - ] + follow: [{ idField: `meeting_user_id`, ...MeetingUserFieldsets.FullNameSubscription }] }, { idField: `editor_ids`, fieldset: FULL_FIELDSET, - follow: [ - mergeSubscriptionFollow( - { - idField: `meeting_user_id`, - follow: [ - mergeSubscriptionFollow( - { idField: `user_id`, ...UserFieldsets.FullNameSubscription }, - { - idField: `user_id`, - fieldset: [`meeting_user_ids`] - } - ) - ] - }, - { idField: `meeting_user_id`, ...MeetingUserFieldsets.FullNameSubscription } - ) - ] + follow: [{ idField: `meeting_user_id`, ...MeetingUserFieldsets.FullNameSubscription }] }, { idField: `working_group_speaker_ids`, fieldset: FULL_FIELDSET, - follow: [ - mergeSubscriptionFollow( - { - idField: `meeting_user_id`, - follow: [ - mergeSubscriptionFollow( - { idField: `user_id`, ...UserFieldsets.FullNameSubscription }, - { - idField: `user_id`, - fieldset: [`meeting_user_ids`] - } - ) - ] - }, - { idField: `meeting_user_id`, ...MeetingUserFieldsets.FullNameSubscription } - ) - ] + follow: [{ idField: `meeting_user_id`, ...MeetingUserFieldsets.FullNameSubscription }] } ] } diff --git a/client/src/app/site/pages/meetings/pages/participants/participants.subscription.ts b/client/src/app/site/pages/meetings/pages/participants/participants.subscription.ts index 510fbbe773..7643dc05c0 100644 --- a/client/src/app/site/pages/meetings/pages/participants/participants.subscription.ts +++ b/client/src/app/site/pages/meetings/pages/participants/participants.subscription.ts @@ -138,13 +138,7 @@ export const getSpeakersListSubscriptionConfig: SubscriptionConfigGenerator = (i idField: `speaker_ids`, fieldset: FULL_FIELDSET, follow: [ - mergeSubscriptionFollow( - { - idField: `meeting_user_id`, - follow: [{ idField: `user_id`, ...UserFieldsets.FullNameSubscription }] - }, - { idField: `meeting_user_id`, ...MeetingUserFieldsets.FullNameSubscription } - ), + { idField: `meeting_user_id`, ...MeetingUserFieldsets.FullNameSubscription }, { idField: `structure_level_list_of_speakers_id`, fieldset: [], From 95a0135c8816e1dcaacac2b18cc7b56909728e61 Mon Sep 17 00:00:00 2001 From: Bastian Rihm Date: Wed, 17 Apr 2024 15:25:48 +0200 Subject: [PATCH 2/6] Remove meeting_user_ids subscription --- .../meetings/pages/participants/participants.subscription.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/src/app/site/pages/meetings/pages/participants/participants.subscription.ts b/client/src/app/site/pages/meetings/pages/participants/participants.subscription.ts index 7643dc05c0..09ed3c3272 100644 --- a/client/src/app/site/pages/meetings/pages/participants/participants.subscription.ts +++ b/client/src/app/site/pages/meetings/pages/participants/participants.subscription.ts @@ -32,13 +32,12 @@ export const getParticipantVoteInfoSubscriptionConfig: SubscriptionConfigGenerat `is_physical_person`, `is_active`, `meeting_ids`, - `meeting_user_ids`, `is_present_in_meeting_ids` ] }, { idField: `vote_delegated_to_id`, - follow: [{ idField: `user_id`, fieldset: [`is_present_in_meeting_ids`, `meeting_user_ids`] }], + follow: [{ idField: `user_id`, fieldset: [`is_present_in_meeting_ids`] }], fieldset: [`meeting_id`] } ] From e719323ed6a21cf6f60d5ff6cf2cbfb1ce802af6 Mon Sep 17 00:00:00 2001 From: Bastian Rihm Date: Wed, 17 Apr 2024 15:41:24 +0200 Subject: [PATCH 3/6] Linter fixes --- .../pages/meetings/pages/autopilot/autopilot.subscription.ts | 2 +- .../meetings/pages/participants/participants.subscription.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/src/app/site/pages/meetings/pages/autopilot/autopilot.subscription.ts b/client/src/app/site/pages/meetings/pages/autopilot/autopilot.subscription.ts index 09bb857856..985b33fb6e 100644 --- a/client/src/app/site/pages/meetings/pages/autopilot/autopilot.subscription.ts +++ b/client/src/app/site/pages/meetings/pages/autopilot/autopilot.subscription.ts @@ -1,6 +1,6 @@ import { Id } from 'src/app/domain/definitions/key-types'; import { FULL_FIELDSET, MEETING_ROUTING_FIELDS, mergeSubscriptionFollow } from 'src/app/domain/fieldsets/misc'; -import { MeetingUserFieldsets, UserFieldsets } from 'src/app/domain/fieldsets/user'; +import { MeetingUserFieldsets } from 'src/app/domain/fieldsets/user'; import { SubscriptionConfig, SubscriptionConfigGenerator } from 'src/app/domain/interfaces/subscription-config'; import { ViewMeeting } from 'src/app/site/pages/meetings/view-models/view-meeting'; diff --git a/client/src/app/site/pages/meetings/pages/participants/participants.subscription.ts b/client/src/app/site/pages/meetings/pages/participants/participants.subscription.ts index 09ed3c3272..5187a92018 100644 --- a/client/src/app/site/pages/meetings/pages/participants/participants.subscription.ts +++ b/client/src/app/site/pages/meetings/pages/participants/participants.subscription.ts @@ -1,6 +1,6 @@ import { Id } from 'src/app/domain/definitions/key-types'; -import { FULL_FIELDSET, MEETING_ROUTING_FIELDS, mergeSubscriptionFollow } from 'src/app/domain/fieldsets/misc'; -import { MeetingUserFieldsets, UserFieldsets } from 'src/app/domain/fieldsets/user'; +import { FULL_FIELDSET, MEETING_ROUTING_FIELDS } from 'src/app/domain/fieldsets/misc'; +import { MeetingUserFieldsets } from 'src/app/domain/fieldsets/user'; import { SubscriptionConfigGenerator } from 'src/app/domain/interfaces/subscription-config'; import { ViewMeeting } from 'src/app/site/pages/meetings/view-models/view-meeting'; import { DEFAULT_FIELDSET } from 'src/app/site/services/model-request-builder'; From b657d06c59dc04fc399f2fb3d6fc3701f3ed26a1 Mon Sep 17 00:00:00 2001 From: Bastian Rihm Date: Fri, 19 Apr 2024 12:19:23 +0200 Subject: [PATCH 4/6] Improve subscription categorization --- client/src/app/worker/sw-autoupdate.ts | 33 +++++++++++++++++--------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/client/src/app/worker/sw-autoupdate.ts b/client/src/app/worker/sw-autoupdate.ts index 64524b6a54..0bd5eb9521 100644 --- a/client/src/app/worker/sw-autoupdate.ts +++ b/client/src/app/worker/sw-autoupdate.ts @@ -19,6 +19,7 @@ const subscriptionQueues: { [key: string]: AutoupdateSubscription[] } = { required: [], requiredMeeting: [], sequentialnumbermapping: [], + detail: [], other: [] }; const openTimeouts = { @@ -77,7 +78,7 @@ function openConnection( function getRequestCategory( description: string, _request: unknown - ): 'required' | 'requiredMeeting' | 'other' | 'sequentialnumbermapping' { + ): 'required' | 'requiredMeeting' | 'other' | 'sequentialnumbermapping' | null { const required = [`theme_list:subscription`, `operator:subscription`, `organization:subscription`]; if (required.indexOf(description) !== -1) { return `required`; @@ -92,6 +93,12 @@ function openConnection( return `sequentialnumbermapping`; } + // Subscriptions ending with a number nomally are used for detail subscriptions + // and should not be bundled + if (!isNaN(+description.substring(description.length - 13, description.length - 14))) { + return null; + } + return `other`; } @@ -123,16 +130,20 @@ function openConnection( const category = getRequestCategory(description, request); const subscription = new AutoupdateSubscription(streamId, queryParams, requestHash, request, description, [ctx]); - subscriptionQueues[category].push(subscription); - - clearTimeout(openTimeouts[category]); - openTimeouts[category] = setTimeout(() => { - const queue = subscriptionQueues[category]; - subscriptionQueues[category] = []; - openTimeouts[category] = undefined; - - autoupdatePool.openNewStream(queue, queryParams); - }, 5); + if (category) { + subscriptionQueues[category].push(subscription); + + clearTimeout(openTimeouts[category]); + openTimeouts[category] = setTimeout(() => { + const queue = subscriptionQueues[category]; + subscriptionQueues[category] = []; + openTimeouts[category] = undefined; + + autoupdatePool.openNewStream(queue, queryParams); + }, 5); + } else { + autoupdatePool.openNewStream([subscription], queryParams); + } } function closeConnection(ctx: MessagePort, params: AutoupdateCloseStreamParams): void { From 12e1e3808413c3c4df735cef1983dc63592f6a62 Mon Sep 17 00:00:00 2001 From: Bastian Rihm Date: Fri, 19 Apr 2024 12:20:02 +0200 Subject: [PATCH 5/6] Return if meeting user id found --- .../app/gateways/repositories/users/user-repository.service.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/client/src/app/gateways/repositories/users/user-repository.service.ts b/client/src/app/gateways/repositories/users/user-repository.service.ts index 4429b4df43..6aec725f71 100644 --- a/client/src/app/gateways/repositories/users/user-repository.service.ts +++ b/client/src/app/gateways/repositories/users/user-repository.service.ts @@ -354,6 +354,7 @@ export class UserRepositoryService extends BaseRepository { for (const meetingUser of this.meetingUserRepo.getViewModelList()) { if (meetingUser.user_id === model.id) { meetingUserIdMap.set(meetingUser.meeting_id, meetingUser.id); + return meetingUser.id; } } } From ef68a0ef5dcba47fd625f0438ebd200fd40b07a5 Mon Sep 17 00:00:00 2001 From: Bastian Rihm Date: Tue, 23 Apr 2024 13:22:05 +0200 Subject: [PATCH 6/6] Handle meeting user user id mapping in meeting user repo --- .../meeting-user-repository.service.ts | 39 +++++++++++++++++ .../users/user-repository.service.ts | 42 +++++-------------- 2 files changed, 50 insertions(+), 31 deletions(-) diff --git a/client/src/app/gateways/repositories/meeting_user/meeting-user-repository.service.ts b/client/src/app/gateways/repositories/meeting_user/meeting-user-repository.service.ts index a4b1f290c0..4498ec3608 100644 --- a/client/src/app/gateways/repositories/meeting_user/meeting-user-repository.service.ts +++ b/client/src/app/gateways/repositories/meeting_user/meeting-user-repository.service.ts @@ -1,4 +1,5 @@ import { Injectable } from '@angular/core'; +import { Id } from 'src/app/domain/definitions/key-types'; import { MeetingUser } from 'src/app/domain/models/meeting-users/meeting-user'; import { toDecimal } from 'src/app/infrastructure/utils'; import { ViewMeetingUser } from 'src/app/site/pages/meetings/view-models/view-meeting-user'; @@ -17,6 +18,8 @@ export type MeetingUserPatchFn = export class MeetingUserRepositoryService extends BaseMeetingRelatedRepository { public override readonly resetOnMeetingChange = false; + private meetingUserIdMap: Map> = new Map(); + public constructor(repositoryServiceCollector: RepositoryMeetingServiceCollectorService) { super(repositoryServiceCollector, MeetingUser); } @@ -66,4 +69,40 @@ export class MeetingUserRepositoryService extends BaseMeetingRelatedRepository viewUser.user?.getTitle() ?? `Unknown`; public getVerboseName = (plural = false): string => this.translate.instant(plural ? `Participants` : `Participant`); + + public getMeetingUserId(userId: Id, meetingId: Id): Id | null { + if (this.meetingUserIdMap.has(userId) && this.meetingUserIdMap.get(userId).has(meetingId)) { + return this.meetingUserIdMap.get(userId).get(meetingId); + } + + return null; + } + + public override deleteModels(ids: Id[]): void { + ids.forEach(id => { + const user = this.viewModelStore[id]; + if (user && user.user_id && user.meeting_id) { + const meetingUserId = this.meetingUserIdMap.get(user.user_id)?.get(user.meeting_id); + if (meetingUserId === user.id) { + this.meetingUserIdMap.get(user.user_id).delete(user.meeting_id); + } + } + }); + super.deleteModels(ids); + } + + protected override clearViewModelStore(): void { + super.clearViewModelStore(); + this.meetingUserIdMap = new Map(); + } + + protected override onCreateViewModel(meetingUser: ViewMeetingUser): void { + if (meetingUser.user_id && meetingUser.meeting_id) { + if (!this.meetingUserIdMap.has(meetingUser.user_id)) { + this.meetingUserIdMap.set(meetingUser.user_id, new Map()); + } + + this.meetingUserIdMap.get(meetingUser.user_id).set(meetingUser.meeting_id, meetingUser.id); + } + } } diff --git a/client/src/app/gateways/repositories/users/user-repository.service.ts b/client/src/app/gateways/repositories/users/user-repository.service.ts index 6aec725f71..d056099961 100644 --- a/client/src/app/gateways/repositories/users/user-repository.service.ts +++ b/client/src/app/gateways/repositories/users/user-repository.service.ts @@ -338,37 +338,17 @@ export class UserRepositoryService extends BaseRepository { protected override createViewModel(model: User): ViewUser { const viewModel = super.createViewModel(model); - const meetingUserIdMap = new Map(); - const getMeetingUserId = (meetingId: Id) => { - if (!meetingUserIdMap.has(meetingId)) { - const meetingUsers = this.relationManager.handleRelation( - viewModel.getModel(), - this.relationsByKey[`meeting_users`] - ); - - if (meetingUsers?.length) { - for (const meetingUser of meetingUsers) { - meetingUserIdMap.set(meetingUser.meeting_id, meetingUser.id); - } - } else { - for (const meetingUser of this.meetingUserRepo.getViewModelList()) { - if (meetingUser.user_id === model.id) { - meetingUserIdMap.set(meetingUser.meeting_id, meetingUser.id); - return meetingUser.id; - } - } - } - } - - return meetingUserIdMap.get(meetingId); - }; - - viewModel.getName = () => this.getName(viewModel); - viewModel.getShortName = () => this.getShortName(viewModel); - viewModel.getFullName = (structureLevel?: ViewStructureLevel) => this.getFullName(viewModel, structureLevel); - viewModel.getMeetingUser = (meetingId: Id) => this.getMeetingUser(getMeetingUserId, meetingId); - viewModel.getLevelAndNumber = () => this.getLevelAndNumber(viewModel); - viewModel.getEnsuredActiveMeetingId = () => this.activeMeetingIdService.meetingId; + viewModel.getName = (): string => this.getName(viewModel); + viewModel.getShortName = (): string => this.getShortName(viewModel); + viewModel.getFullName = (structureLevel?: ViewStructureLevel): string => + this.getFullName(viewModel, structureLevel); + viewModel.getMeetingUser = (meetingId: Id): ViewMeetingUser => + this.getMeetingUser( + (meetingId: Id): Id => this.meetingUserRepo.getMeetingUserId(model.id, meetingId), + meetingId + ); + viewModel.getLevelAndNumber = (): string => this.getLevelAndNumber(viewModel); + viewModel.getEnsuredActiveMeetingId = (): Id => this.activeMeetingIdService.meetingId; return viewModel; }