Skip to content

Commit b85822d

Browse files
Elblinatorbastianjoel
authored andcommitted
Fix non meeting members from being part of meeting (OpenSlides#5692)
1 parent cdb4771 commit b85822d

File tree

13 files changed

+96
-20
lines changed

13 files changed

+96
-20
lines changed

client/src/app/gateways/repositories/motions/motion-repository.service/motion-repository.service.ts

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,12 @@ export class MotionRepositoryService extends BaseAgendaItemAndListOfSpeakersCont
187187

188188
public createTextBased(
189189
partialMotion: Partial<
190-
Motion & { workflow_id: Id; attachment_mediafile_ids?: Id[]; supporter_meeting_user_ids?: Id[] }
190+
Motion & {
191+
workflow_id: Id;
192+
attachment_mediafile_ids?: Id[];
193+
supporter_meeting_user_ids?: Id[];
194+
submitter_meeting_user_ids: Id[];
195+
}
191196
>
192197
): Action<CreateResponse> {
193198
const payload = {
@@ -196,7 +201,7 @@ export class MotionRepositoryService extends BaseAgendaItemAndListOfSpeakersCont
196201
title: partialMotion.title,
197202
text: partialMotion.text,
198203
origin_id: partialMotion.origin_id,
199-
submitter_ids: partialMotion.submitter_ids,
204+
submitter_meeting_user_ids: partialMotion.submitter_meeting_user_ids,
200205
workflow_id: partialMotion.workflow_id,
201206
category_id: partialMotion.category_id,
202207
attachment_mediafile_ids: partialMotion.attachment_mediafile_ids,
@@ -212,15 +217,20 @@ export class MotionRepositoryService extends BaseAgendaItemAndListOfSpeakersCont
212217

213218
public createParagraphBased(
214219
partialMotion: Partial<
215-
Motion & { workflow_id: Id; attachment_mediafile_ids?: Id[]; supporter_meeting_user_ids?: Id[] }
220+
Motion & {
221+
workflow_id: Id;
222+
attachment_mediafile_ids?: Id[];
223+
supporter_meeting_user_ids?: Id[];
224+
submitter_meeting_user_ids: Id[];
225+
}
216226
>
217227
): Action<CreateResponse> {
218228
const payload = {
219229
meeting_id: this.activeMeetingIdService.meetingId,
220230
lead_motion_id: partialMotion.lead_motion_id,
221231
title: partialMotion.title,
222232
origin_id: partialMotion.origin_id,
223-
submitter_ids: partialMotion.submitter_ids === null ? [] : partialMotion.submitter_ids,
233+
submitter_meeting_user_ids: partialMotion.submitter_meeting_user_ids,
224234
workflow_id: partialMotion.workflow_id,
225235
category_id: partialMotion.category_id,
226236
attachment_mediafile_ids:
@@ -320,7 +330,7 @@ export class MotionRepositoryService extends BaseAgendaItemAndListOfSpeakersCont
320330
title: partialMotion.title,
321331
text: partialMotion.text,
322332
origin_id: partialMotion.origin_id,
323-
submitter_ids: partialMotion.submitter_ids,
333+
submitter_meeting_user_ids: partialMotion.submitter_meeting_user_ids,
324334
additional_submitter: partialMotion.additional_submitter,
325335
workflow_id: partialMotion.workflow_id,
326336
category_id: partialMotion.category_id,

client/src/app/site/modules/global-headbar/components/account-button/account-button.component.html

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,11 @@
8181
<mat-icon class="menu-icon">done</mat-icon>
8282
<span class="menu-text">{{ 'Present' | translate }}</span>
8383
</div>
84+
} @else if (!isinMeeting) {
85+
<div mat-menu-item>
86+
<mat-icon class="menu-icon">clear</mat-icon>
87+
<span class="menu-text">{{ 'Not part of meeting' | translate }}</span>
88+
</div>
8489
} @else {
8590
<div mat-menu-item>
8691
<mat-icon class="menu-icon">clear</mat-icon>

client/src/app/site/modules/global-headbar/components/account-button/account-button.component.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,16 @@ export class AccountButtonComponent extends BaseUiComponent implements OnInit {
4444

4545
private _langTriggerSubscription: Subscription;
4646

47+
public get isinMeeting(): boolean {
48+
return this.hasActiveMeeting && this.operator.isInMeeting(this.activeMeetingId) && !this.operator.isAnonymous;
49+
}
50+
4751
public get isPresent(): boolean {
48-
return this.hasActiveMeeting && this.operator.isInMeeting(this.activeMeetingId) && !this.operator.isAnonymous
49-
? this.user.isPresentInMeeting()
50-
: false;
52+
return this.isinMeeting && this.user.isPresentInMeeting();
5153
}
5254

5355
public get isAllowedSelfSetPresent(): boolean {
54-
return this._isAllowedSelfSetPresent && this.operator.isInMeeting(this.activeMeetingId);
56+
return this.isinMeeting && this._isAllowedSelfSetPresent;
5557
}
5658

5759
public get hasActiveMeeting(): boolean {

client/src/app/site/pages/meetings/modules/poll/components/base-poll-vote/base-poll-vote.component.html

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
@if (poll && isReady) {
22
<!-- own voting -->
3-
@if (isUserPresent) {
3+
@if (!isUserInMeeting) {
4+
<div class="text-center">
5+
{{ 'You are not part of the meeting' | translate }}
6+
</div>
7+
} @else if (isUserPresent) {
48
<ng-container [ngTemplateOutlet]="votingArea" />
59
} @else {
610
<div class="text-center">

client/src/app/site/pages/meetings/modules/poll/components/base-poll-vote/base-poll-vote.component.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,10 @@ export abstract class BasePollVoteComponent<C extends PollContentObject = any> e
7575
return this.user?.isPresentInMeeting();
7676
}
7777

78+
public get isUserInMeeting(): boolean {
79+
return this.user?.isInActiveMeeting;
80+
}
81+
7882
public get isMobile(): boolean {
7983
return this.viewport.isMobile;
8084
}

client/src/app/site/pages/meetings/pages/assignments/pages/assignment-detail/components/assignment-detail/assignment-detail.component.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Component, OnDestroy } from '@angular/core';
22
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
3+
import { MatSnackBar } from '@angular/material/snack-bar';
34
import { TranslateService } from '@ngx-translate/core';
45
import { BehaviorSubject, Subscription } from 'rxjs';
56
import { Id } from 'src/app/domain/definitions/key-types';
@@ -162,7 +163,8 @@ export class AssignmentDetailComponent extends BaseMeetingComponent implements O
162163
private pollDialog: AssignmentPollDialogService,
163164
private assignmentPollService: AssignmentPollService,
164165
private pollController: PollControllerService,
165-
private userRepo: UserControllerService
166+
private userRepo: UserControllerService,
167+
private snackBar: MatSnackBar
166168
) {
167169
super();
168170
this.assignmentForm = formBuilder.group({
@@ -355,7 +357,12 @@ export class AssignmentDetailComponent extends BaseMeetingComponent implements O
355357
* Adds the operator to list of candidates
356358
*/
357359
public async addSelf(): Promise<void> {
358-
await this.addCandidate({ userId: this.operator.operatorId! });
360+
if (!this.operator.isInMeeting(this.activeMeetingIdService.meetingId)) {
361+
const infoMessage = this.translate.instant(`Action not possible. You have to be part of the meeting.`);
362+
this.snackBar.open(infoMessage, this.translate.instant(`Ok`));
363+
} else {
364+
await this.addCandidate({ userId: this.operator.operatorId! });
365+
}
359366
}
360367

361368
/**

client/src/app/site/pages/meetings/pages/chat/pages/chat-group-list/components/chat-group-detail-message-form/chat-group-detail-message-form.component.html

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
<mat-form-field appearance="outline" class="chat-form-field full-width" (keydown)="onKeyDown($event)">
1+
<mat-form-field
2+
appearance="outline"
3+
class="chat-form-field full-width"
4+
[color]="isPartOfMeeting() ? 'accent' : 'warn'"
5+
(keydown)="onKeyDown($event)"
6+
>
27
@if (currentMessage) {
38
<div class="chat-form-field-prefix flex-vertical-center" matPrefix>
49
<span>{{ 'Edit' | translate }}</span>
@@ -25,14 +30,21 @@
2530
</mat-hint>
2631
}
2732
<button
28-
color="accent"
2933
mat-icon-button
3034
matSuffix
3135
matTooltip=" {{ 'Send' | translate }}"
3236
type="button"
37+
[color]="isPartOfMeeting() ? 'accent' : 'warn'"
3338
[disabled]="!isMessageFormValid"
3439
(click)="sendChatMessage()"
3540
>
3641
<mat-icon>send</mat-icon>
3742
</button>
43+
@if (!isPartOfMeeting()) {
44+
<mat-hint>
45+
<span class="warn">
46+
{{ 'You have to be part of the meeting to write messages.' | translate }}
47+
</span>
48+
</mat-hint>
49+
}
3850
</mat-form-field>

client/src/app/site/pages/meetings/pages/chat/pages/chat-group-list/components/chat-group-detail-message-form/chat-group-detail-message-form.component.ts

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
import { Component, EventEmitter, Input, Output } from '@angular/core';
22
import { UntypedFormBuilder, UntypedFormControl, Validators } from '@angular/forms';
3+
import { MatSnackBar } from '@angular/material/snack-bar';
4+
import { TranslateService } from '@ngx-translate/core';
35
import { CHAT_MESSAGE_MAX_LENGTH } from 'src/app/gateways/repositories/chat/chat-message-repository.service';
46
import { KeyCode } from 'src/app/infrastructure/utils/key-code';
57
import { ViewChatMessage } from 'src/app/site/pages/meetings/pages/chat';
8+
import { ActiveMeetingIdService } from 'src/app/site/pages/meetings/services/active-meeting-id.service';
9+
import { OperatorService } from 'src/app/site/services/operator.service';
610

711
@Component({
812
selector: `os-chat-group-detail-message-form`,
@@ -37,7 +41,13 @@ export class ChatGroupDetailMessageFormComponent {
3741

3842
private _currentMessage: ViewChatMessage | null = null;
3943

40-
public constructor(fb: UntypedFormBuilder) {
44+
public constructor(
45+
fb: UntypedFormBuilder,
46+
private operator: OperatorService,
47+
private activeMeetingIdService: ActiveMeetingIdService,
48+
private translate: TranslateService,
49+
private snackBar: MatSnackBar
50+
) {
4151
this.messageForm = fb.control(``, [Validators.maxLength(CHAT_MESSAGE_MAX_LENGTH)]);
4252
}
4353

@@ -49,9 +59,14 @@ export class ChatGroupDetailMessageFormComponent {
4959
}
5060

5161
public sendChatMessage(): void {
52-
const content = this.messageForm.value?.trim() as string;
53-
this.messageSent.emit(content);
54-
this.resetMessageForm();
62+
if (!this.isPartOfMeeting()) {
63+
const infoMessage = this.translate.instant(`Action not possible. You have to be part of the meeting.`);
64+
this.snackBar.open(infoMessage, this.translate.instant(`Ok`));
65+
} else {
66+
const content = this.messageForm.value?.trim() as string;
67+
this.messageSent.emit(content);
68+
this.resetMessageForm();
69+
}
5570
}
5671

5772
public cancelEditingChatMessage(): void {
@@ -63,4 +78,8 @@ export class ChatGroupDetailMessageFormComponent {
6378
this.currentMessage = null;
6479
this.messageForm.markAsPristine();
6580
}
81+
82+
public isPartOfMeeting(): boolean {
83+
return this.operator.isInMeeting(this.activeMeetingIdService.meetingId);
84+
}
6685
}

client/src/app/site/pages/meetings/pages/motions/pages/motion-detail/pages/motion-form/components/amendment-create-wizard/amendment-create-wizard.component.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,13 +179,17 @@ export class AmendmentCreateWizardComponent extends BaseMeetingComponent impleme
179179
amendmentParagraphs[paraNo] = this.contentForm.value[`text_` + paraNo];
180180
}
181181
});
182+
const submitterMeetingUserId = this.operator.isInMeeting(this.activeMeetingId)
183+
? [this.operator.user.getMeetingUser(this.activeMeetingId)?.id]
184+
: [];
182185
const motionCreate = {
183186
...this.contentForm.value,
184187
title: this.translate.instant(`Amendment to`) + ` ` + this.motion.getNumberOrTitle(),
185188
parent_id: this.motion.id,
186189
category_id: this.operator.hasPerms(Permission.motionCanManage) ? this.motion.category_id : undefined,
187190
lead_motion_id: this.motion.id,
188191
amendment_paragraphs: amendmentParagraphs,
192+
submitter_meeting_user_ids: submitterMeetingUserId,
189193
workflow_id: this.meetingSettingsService.instant(`motions_default_amendment_workflow_id`)
190194
};
191195

client/src/app/site/pages/meetings/pages/motions/pages/motion-detail/pages/motion-form/components/motion-form/motion-form.component.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,11 @@ export class MotionFormComponent extends BaseMeetingComponent implements OnInit
251251
}
252252

253253
if (this.newMotion) {
254+
if (update.submitter_ids.length === 0 && this.operator.isInMeeting(this.activeMeetingId)) {
255+
update.submitter_meeting_user_ids = [this.operator.user.getMeetingUser(this.activeMeetingId).id];
256+
} else {
257+
update.submitter_meeting_user_ids = update.submitter_ids;
258+
}
254259
for (const key in update) {
255260
if (update[key] === null || update[key].length === 0) {
256261
delete update[key];
@@ -323,7 +328,7 @@ export class MotionFormComponent extends BaseMeetingComponent implements OnInit
323328

324329
public async createNewSubmitter(username: string): Promise<void> {
325330
const newUserObj = await this.createNewUser(username);
326-
this.addNewUserToFormCtrl(newUserObj, `submitter_ids`);
331+
this.addNewUserToFormCtrl(newUserObj, `submitter_meeting_user_ids`);
327332
}
328333

329334
public async createNewSupporter(username: string): Promise<void> {

0 commit comments

Comments
 (0)