diff --git a/client/src/app/site/modules/user-components/components/user-multiselect-actions/user-multiselect-actions.component.ts b/client/src/app/site/modules/user-components/components/user-multiselect-actions/user-multiselect-actions.component.ts index 4a02bfec14e..84a17ac9c37 100644 --- a/client/src/app/site/modules/user-components/components/user-multiselect-actions/user-multiselect-actions.component.ts +++ b/client/src/app/site/modules/user-components/components/user-multiselect-actions/user-multiselect-actions.component.ts @@ -8,6 +8,7 @@ import { TemplateRef, viewChild } from '@angular/core'; +import { MatMenuTrigger } from '@angular/material/menu'; import { BaseComponent } from '@app/site/base/base.component'; import { ActiveMeetingIdService } from '@app/site/pages/meetings/services/active-meeting-id.service'; import { ViewUser } from '@app/site/pages/meetings/view-models/view-user'; @@ -23,13 +24,10 @@ import { PromptService } from '@app/ui/modules/prompt-dialog'; standalone: false }) export class UserMultiselectActionsComponent extends BaseComponent { - public repo = inject(UserControllerService); - private operator = inject(OperatorService); - private promptService = inject(PromptService); - private activeMeetingIdService = inject(ActiveMeetingIdService); - public implicitContent = viewChild.required(TemplateRef); + public meetingMenu = viewChild(MatMenuTrigger); + public canManage = input(true); public canUpdate = input(true); public selectedUsers = input([]); @@ -43,6 +41,11 @@ export class UserMultiselectActionsComponent extends BaseComponent { private _selectedUsers: ViewUser[] = []; + public repo = inject(UserControllerService); + private operator = inject(OperatorService); + private promptService = inject(PromptService); + private activeMeetingIdService = inject(ActiveMeetingIdService); + public constructor() { super(); @@ -55,6 +58,7 @@ export class UserMultiselectActionsComponent extends BaseComponent { * Handler for bulk resetting passwords to the default ones. Needs multiSelect mode. */ public async resetPasswordsToDefaultSelected(): Promise { + this.meetingMenu().closeMenu(); const title = this.translate.instant(`Are you sure you want to reset all passwords to the default ones?`); if (!(await this.promptService.open(title))) { return; @@ -76,6 +80,7 @@ export class UserMultiselectActionsComponent extends BaseComponent { * Handler for bulk generating new passwords. Needs multiSelect mode. */ public async generateNewPasswordsPasswordsSelected(): Promise { + this.meetingMenu().closeMenu(); const title = this.translate.instant( `Are you sure you want to generate new passwords for all selected participants?` ); @@ -98,6 +103,7 @@ export class UserMultiselectActionsComponent extends BaseComponent { } public async sendInvitationEmailSelected(): Promise { + this.meetingMenu().closeMenu(); const title = this.translate.instant(`Are you sure you want to send emails to all selected participants?`); const content = this.selectedUsers().length + ` ` + this.translate.instant(`emails`); if (await this.promptService.open(title, content)) { diff --git a/client/src/app/site/pages/meetings/pages/participants/pages/participant-detail/components/participant-detail-edit/participant-detail-edit.component.ts b/client/src/app/site/pages/meetings/pages/participants/pages/participant-detail/components/participant-detail-edit/participant-detail-edit.component.ts index ca1342aaa9a..5059a9ffc15 100644 --- a/client/src/app/site/pages/meetings/pages/participants/pages/participant-detail/components/participant-detail-edit/participant-detail-edit.component.ts +++ b/client/src/app/site/pages/meetings/pages/participants/pages/participant-detail/components/participant-detail-edit/participant-detail-edit.component.ts @@ -1,5 +1,6 @@ -import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit, ViewChild } from '@angular/core'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, inject, OnInit, viewChild } from '@angular/core'; import { Validators } from '@angular/forms'; +import { MatMenuTrigger } from '@angular/material/menu'; import { ActivatedRoute } from '@angular/router'; import { Id } from '@app/domain/definitions/key-types'; import { CML, OML } from '@app/domain/definitions/organization-permission'; @@ -20,7 +21,6 @@ import { OperatorService } from '@app/site/services/operator.service'; import { UserService } from '@app/site/services/user.service'; import { PromptService } from '@app/ui/modules/prompt-dialog'; import { _ } from '@ngx-translate/core'; -import { TranslateService } from '@ngx-translate/core'; import { combineLatest, Observable } from 'rxjs'; import { GroupControllerService } from '../../../../modules'; @@ -40,8 +40,8 @@ import { ViewStructureLevel } from '../../../structure-levels/view-models'; standalone: false }) export class ParticipantDetailEditComponent extends BaseMeetingComponent implements OnInit { - @ViewChild(UserDetailViewComponent) - private userDetailView; + private userDetailView = viewChild(UserDetailViewComponent); + public meetingMenu = viewChild(MatMenuTrigger); public participantSubscriptionConfig = getParticipantMinimalSubscriptionConfig(this.activeMeetingId); public committeeSubscriptionConfig = getCommitteeListMinimalSubscriptionConfig(); @@ -185,21 +185,20 @@ export class ParticipantDetailEditComponent extends BaseMeetingComponent impleme private _isDefaultPasswordEditable = false; private _isUserEditable = false; - public constructor( - protected override translate: TranslateService, - private route: ActivatedRoute, - public repo: ParticipantControllerService, - public sortService: ParticipantListSortService, - public readonly committeeController: CommitteeControllerService, - public readonly committeeSortService: CommitteeSortService, - private operator: OperatorService, - private promptService: PromptService, - private groupRepo: GroupControllerService, - private structureLevelRepo: StructureLevelControllerService, - private userService: UserService, - private cd: ChangeDetectorRef, - private organizationSettingsService: OrganizationSettingsService - ) { + private route = inject(ActivatedRoute); + public repo = inject(ParticipantControllerService); + public sortService = inject(ParticipantListSortService); + public readonly committeeController = inject(CommitteeControllerService); + public readonly committeeSortService = inject(CommitteeSortService); + private operator = inject(OperatorService); + private promptService = inject(PromptService); + private groupRepo = inject(GroupControllerService); + private structureLevelRepo = inject(StructureLevelControllerService); + private userService = inject(UserService); + private cd = inject(ChangeDetectorRef); + private organizationSettingsService = inject(OrganizationSettingsService); + + public constructor() { super(); this.getUserByUrl(); @@ -299,11 +298,11 @@ export class ParticipantDetailEditComponent extends BaseMeetingComponent impleme public updateByValueChange(event: any): void { this.personalInfoFormValue = event; - if (this.userDetailView.personalInfoForm.get(`locked_out`).disabled !== this.lockoutCheckboxDisabled) { + if (this.userDetailView().personalInfoForm.get(`locked_out`).disabled !== this.lockoutCheckboxDisabled) { if (this.lockoutCheckboxDisabled) { - this.userDetailView.personalInfoForm.get(`locked_out`).disable(); + this.userDetailView().personalInfoForm.get(`locked_out`).disable(); } else { - this.userDetailView.personalInfoForm.get(`locked_out`).enable(); + this.userDetailView().personalInfoForm.get(`locked_out`).enable(); } } } @@ -322,8 +321,8 @@ export class ParticipantDetailEditComponent extends BaseMeetingComponent impleme : null, vote_delegations_from_ids: this.personalInfoFormValue.vote_delegations_from_ids ? this.personalInfoFormValue.vote_delegations_from_ids - .map(id => this.repo.getViewModel(id).getMeetingUser().id) - .filter(id => !!id) + .map((id: number) => this.repo.getViewModel(id).getMeetingUser().id) + .filter((id: number) => !!id) : [] }; if (payload.member_number === ``) { @@ -376,7 +375,7 @@ export class ParticipantDetailEditComponent extends BaseMeetingComponent impleme private checkForGroups(user: any): void { const defaultGroupId = this.activeMeetingService.meeting!.default_group_id; if (user?.group_ids.includes(defaultGroupId) && user?.group_ids.length > 1) { - user.group_ids = user.group_ids.filter(id => id !== defaultGroupId); + user.group_ids = user.group_ids.filter((id: number) => id !== defaultGroupId); } if (!user?.group_ids.length) { user.group_ids = [defaultGroupId]; diff --git a/client/src/app/site/pages/organization/pages/committees/modules/committee-meeting-preview/committee-meeting-preview.component.ts b/client/src/app/site/pages/organization/pages/committees/modules/committee-meeting-preview/committee-meeting-preview.component.ts index 981cb874628..3ed6a67e1ba 100644 --- a/client/src/app/site/pages/organization/pages/committees/modules/committee-meeting-preview/committee-meeting-preview.component.ts +++ b/client/src/app/site/pages/organization/pages/committees/modules/committee-meeting-preview/committee-meeting-preview.component.ts @@ -1,4 +1,5 @@ import { ChangeDetectionStrategy, Component, inject, Input, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core'; +import { MatDialog } from '@angular/material/dialog'; import { CML, OML } from '@app/domain/definitions/organization-permission'; import { MeetingControllerService } from '@app/site/pages/meetings/services/meeting-controller.service'; import { ViewMeeting } from '@app/site/pages/meetings/view-models/view-meeting'; @@ -82,6 +83,7 @@ export class CommitteeMeetingPreviewComponent implements OnDestroy, OnInit { private meetingService = inject(MeetingService); private promptService = inject(PromptService); private translate = inject(TranslateService); + private dialog = inject(MatDialog); /** * Get the subject diff --git a/client/src/app/site/pages/organization/pages/orga-meetings/pages/meeting-list/components/meeting-list/meeting-list.component.ts b/client/src/app/site/pages/organization/pages/orga-meetings/pages/meeting-list/components/meeting-list/meeting-list.component.ts index ed407c031a6..d0adc3855cb 100644 --- a/client/src/app/site/pages/organization/pages/orga-meetings/pages/meeting-list/components/meeting-list/meeting-list.component.ts +++ b/client/src/app/site/pages/organization/pages/orga-meetings/pages/meeting-list/components/meeting-list/meeting-list.component.ts @@ -1,4 +1,5 @@ -import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { ChangeDetectionStrategy, Component, inject, viewChild } from '@angular/core'; +import { MatMenuTrigger } from '@angular/material/menu'; import { OML } from '@app/domain/definitions/organization-permission'; import { BaseListViewComponent } from '@app/site/base/base-list-view.component'; import { MeetingControllerService } from '@app/site/pages/meetings/services/meeting-controller.service'; @@ -7,7 +8,6 @@ import { OperatorService } from '@app/site/services/operator.service'; import { ColumnRestriction } from '@app/ui/modules/list'; import { PromptService } from '@app/ui/modules/prompt-dialog/services/prompt.service'; import { _ } from '@ngx-translate/core'; -import { TranslateService } from '@ngx-translate/core'; import { MeetingCsvExportService } from '../../services/meeting-export.service'; import { MeetingListFilterService } from '../../services/meeting-list-filter/meeting-list-filter.service'; @@ -30,18 +30,19 @@ export class MeetingListComponent extends BaseListViewComponent { } ]; + public meetingMenu = viewChild(MatMenuTrigger); + public toRestrictFn = (restriction: ColumnRestriction): boolean => !this.operator.hasOrganizationPermissions(restriction.permission); - public constructor( - protected override translate: TranslateService, - public meetingController: MeetingControllerService, - public operator: OperatorService, - public filterService: MeetingListFilterService, - public sortService: MeetingListSortService, - private csvExport: MeetingCsvExportService, - private promptService: PromptService - ) { + public meetingController = inject(MeetingControllerService); + public operator = inject(OperatorService); + public filterService = inject(MeetingListFilterService); + public sortService = inject(MeetingListSortService); + private csvExport = inject(MeetingCsvExportService); + private promptService = inject(PromptService); + + public constructor() { super(); super.setTitle(`Meetings`); this.canMultiSelect = true; @@ -65,6 +66,7 @@ export class MeetingListComponent extends BaseListViewComponent { } public async doDelete(meeting?: ViewMeeting): Promise { + this.meetingMenu().closeMenu(); const toDelete = meeting ? [meeting] : this.selectedRows; const toTranslate = meeting ? _(`Are you sure you want to delete this meeting?`) diff --git a/client/src/app/ui/modules/prompt-dialog/services/prompt.service.ts b/client/src/app/ui/modules/prompt-dialog/services/prompt.service.ts index 77e6c7b7294..2c182082751 100644 --- a/client/src/app/ui/modules/prompt-dialog/services/prompt.service.ts +++ b/client/src/app/ui/modules/prompt-dialog/services/prompt.service.ts @@ -24,6 +24,9 @@ export class PromptService { decline?: string, deletion?: boolean ): Promise { + if (document.activeElement instanceof HTMLElement) { + document.activeElement.blur(); + } this.dialogRef = this.dialog.open(PromptDialogComponent, { width: `290px`, data: { title, content, confirm, decline, deletion }