Skip to content
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ export class MotionRepositoryService extends BaseAgendaItemAndListOfSpeakersCont
const agendaTitle: AgendaListTitle = { title };

if (viewMotion.submitterNames && viewMotion.submitterNames.length) {
agendaTitle.subtitle = `${this.translate.instant(`by`)} ${viewMotion.submitterNames.join(`, `)}`;
agendaTitle.subtitle = `${this.translate.instant(`by`)} ${viewMotion.submitterNames.map(sub => (sub === undefined ? this.translate.instant(`Deleted user`) : sub)).join(`, `)}`;
}
return agendaTitle;
};
Expand Down
2 changes: 1 addition & 1 deletion client/src/app/gateways/repositories/motions/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export abstract class BaseMotionMeetingUserRepositoryService<
super(repositoryServiceCollector, constructor);
}

public getTitle = (model: V): string => model?.user?.getTitle() || this.translate.instant(`Unknown participant`);
public getTitle = (model: V): string => model?.user?.getTitle() || this.translate.instant(`Deleted user`);

public create(motion: Identifiable, ...meetingUsers: Identifiable[]): Action<Identifiable[]> {
const payload = meetingUsers.map(user => ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -292,20 +292,30 @@ export abstract class BaseFilterListService<V extends BaseViewModel> implements
if (viewModels && viewModels.length) {
let models: FilterModel[] = viewModels.filter(filterFn ?? ((): boolean => true));
if (mapFn) {
models = Object.values(models.map(mapFn).mapToObject(model => ({ [model.id]: model })));
models = Object.values(
models.map(mapFn).mapToObject(model => {
if (!model) {
// This is [undefined]: undefined
// That is only relevant for models which were deleted but should still be displayed
// That is (so far) only the case for a meeting user who was assigned as editor/speaker and is now deleted)
return { [model?.id]: undefined };
}
return { [model.id]: model };
})
);
}
filterProperties = models
.map((model: FilterModel) => ({
condition: model.id,
label: model.getTitle(),
isChild: !!model.parent,
condition: model?.id,
label: model?.getTitle() ?? `Deleted user`,
isChild: !!model?.parent,
isActive: (
filter.options.find(
f => (f as OsFilterOption)?.condition === model.id
f => (f as OsFilterOption)?.condition === model?.id
) as OsFilterOption
)?.isActive,
skipTranslate: true,
children: model.children?.length
skipTranslate: model?.getTitle() ? true : false,
children: model?.children?.length
? model.children.map((child: any) => ({
label: child.getTitle(),
condition: child.id
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,10 +163,10 @@ export class ParticipantSearchSelectorComponent extends BaseUiComponent implemen

public async createNewSelectedUser(name: string): Promise<void> {
const newUserObj = await this.userRepo.createFromString(name);
this.emitSelectedUser({ userId: newUserObj.id, user: newUserObj });
const user = await firstValueFrom(
this.userRepo.getViewModelObservable(newUserObj.id).pipe(filter(user => !!user))
);
this.emitSelectedUser({ userId: newUserObj.id, user });
this.snackBar.open(
this.translate
.instant(`A user with the username '%username%' and the first name '%first_name%' was created.`)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@
<span class="data-preview">
<os-comma-separated-listing [list]="data.motion[0].submitterNames">
<ng-template let-submitter>
{{ submitter }}
{{ getSubmitterOrDeletedUser(submitter) }}
</ng-template>
</os-comma-separated-listing>
</span>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Component, Inject, OnInit } from '@angular/core';
import { MatCheckboxChange } from '@angular/material/checkbox';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { TranslateService } from '@ngx-translate/core';
import { BehaviorSubject, Observable } from 'rxjs';
import { Id, Ids } from 'src/app/domain/definitions/key-types';
import { GetForwardingMeetingsPresenter, GetForwardingMeetingsPresenterMeeting } from 'src/app/gateways/presenter';
Expand Down Expand Up @@ -59,7 +60,8 @@ export class MotionForwardDialogComponent implements OnInit {
@Inject(MAT_DIALOG_DATA)
public data: { motion: ViewMotion[]; forwardingMeetings: GetForwardingMeetingsPresenter[] },
private dialogRef: MatDialogRef<MotionForwardDialogComponent, MotionForwardDialogReturnData>,
private activeMeeting: ActiveMeetingService
private activeMeeting: ActiveMeetingService,
private translate: TranslateService
) {}

public async ngOnInit(): Promise<void> {
Expand Down Expand Up @@ -134,4 +136,8 @@ export class MotionForwardDialogComponent implements OnInit {
const hasAmend: (element: ViewMotion) => boolean = element => element.amendments.length > 0;
return this.data.motion.some(hasAmend);
}

public getSubmitterOrDeletedUser(submitter: string): string {
return submitter ?? this.translate.instant(`Deleted user`);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ <h2>
@if (motion.submitterNames.length) {
<span>
<span>{{ 'by' | translate }}</span>
{{ motion.submitterNames }}
{{ getSubmitterListWithDeletedUsers(motion.submitterNames) }}
</span>
}
@if (showSequentialNumber) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,4 +159,8 @@ export class AmendmentListComponent extends BaseMeetingListViewComponent<ViewMot
public getChangedLinesFromAmendment(amendment: ViewMotion): string | null {
return amendment.getChangedLines();
}

public getSubmitterListWithDeletedUsers(submitters: string[]): string[] {
return submitters.map(sub => sub ?? this.translate.instant(`Deleted user`));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,9 @@
</mat-icon>
}
<i class="grey">&nbsp;- {{ change.amendment.state!.name }}</i>
<i class="grey">&nbsp;- {{ change.amendment.submitterNames }}</i>
<i class="grey">
&nbsp;- {{ getSubmitterListWithDeletedUsers(change.amendment.submitterNames) }}
</i>
</div>
}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -586,4 +586,8 @@ export class MotionDetailDiffComponent extends BaseMeetingComponent implements A
behavior: `smooth`
});
}

public getSubmitterListWithDeletedUsers(submitters: string[]): string[] {
return submitters.map(sub => sub ?? this.translate.instant(`Deleted user`));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ <h4>
<div>
@for (model of intermediateModels$ | async; track model.id) {
<mat-chip-listbox class="user">
<mat-basic-chip class="pre-wrap" disableRipple>{{ model.user?.getTitle() }}</mat-basic-chip>
@if (model.user) {
<mat-basic-chip class="pre-wrap" disableRipple>{{ model.user.getTitle() }}</mat-basic-chip>
} @else {
<mat-basic-chip class="pre-wrap" disableRipple>{{ 'Deleted user' | translate }}</mat-basic-chip>
}
</mat-chip-listbox>
}
@if (useAdditionalInput && additionalInputValue) {
Expand Down Expand Up @@ -51,7 +55,7 @@ <h4>
<div class="text-field-container">
<os-participant-search-selector
placeholder="{{ 'Select participant' | translate }}"
[nonSelectableUserIds]="editUserIds"
[nonSelectableUserIds]="nonSelectableUserIds"
(userSelected)="addUser($event)"
></os-participant-search-selector>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,14 @@ import { Action, ActionService } from 'src/app/gateways/actions';
import { KeyOfType } from 'src/app/infrastructure/utils/keyof-type';
import { BaseHasMeetingUserViewModel } from 'src/app/site/pages/meetings/base/base-has-meeting-user-view-model';
import { UserSelectionData } from 'src/app/site/pages/meetings/modules/participant-search-selector';
import { ViewMotion } from 'src/app/site/pages/meetings/pages/motions';
import { ViewMotion, ViewMotionSubmitter } from 'src/app/site/pages/meetings/pages/motions';
import { ParticipantControllerService } from 'src/app/site/pages/meetings/pages/participants/services/common/participant-controller.service/participant-controller.service';
import { ViewUser } from 'src/app/site/pages/meetings/view-models/view-user';
import { BaseUiComponent } from 'src/app/ui/base/base-ui-component';

import { ViewMotionEditor } from '../../../../../../modules/editors';
import { BaseMotionMeetingUserControllerService } from '../../../../../../modules/util';
import { ViewMotionWorkingGroupSpeaker } from '../../../../../../modules/working-group-speakers';
import { MotionControllerService } from '../../../../../../services/common/motion-controller.service';
import { MotionPermissionService } from '../../../../../../services/common/motion-permission.service/motion-permission.service';

Expand Down Expand Up @@ -92,7 +95,7 @@ export class MotionManageMotionMeetingUsersComponent<V extends BaseHasMeetingUse
* The current list of intermediate models.
*/
public readonly editSubject = new BehaviorSubject<MotionMeetingUser[]>([]);
public editUserIds: number[] = [];
public nonSelectableUserIds: number[] = [];

/**
* The observable from editSubject. Fixing this value is a performance boost, because
Expand Down Expand Up @@ -143,7 +146,7 @@ export class MotionManageMotionMeetingUsersComponent<V extends BaseHasMeetingUse
this.additionalInputControl = this.fb.control(``);
this.secondSelectorFormControl = this.fb.control(``);
this.subscriptions.push(
this.editSubject.subscribe(ids => (this.editUserIds = ids.map(model => model.user_id ?? model.id)))
this.editSubject.subscribe(ids => (this.nonSelectableUserIds = ids.map(model => model.user_id ?? model.id)))
);
this.subscriptions.push(
this.secondSelectorFormControl.valueChanges.subscribe(value => {
Expand Down Expand Up @@ -176,7 +179,19 @@ export class MotionManageMotionMeetingUsersComponent<V extends BaseHasMeetingUse
? val
: firstValueFrom(
this.motionController.getViewModelObservable(this.motion.id).pipe(
map(motion => this.getIntermediateModels(motion).find(model => model.user_id === val.id)),
map(motion =>
this.getIntermediateModels(motion).find(model => {
if (
val instanceof ViewMotionSubmitter ||
val instanceof ViewMotionEditor ||
val instanceof ViewMotionWorkingGroupSpeaker
) {
return model.id === val.id;
}
// else is (val instanceof ViewUser)
return model.user_id === val.id;
})
),
filter(model => !!model)
)
)
Expand Down Expand Up @@ -213,7 +228,7 @@ export class MotionManageMotionMeetingUsersComponent<V extends BaseHasMeetingUse
this.additionalInputControl.setValue(this.additionalInputValue);
}
this.editSubject.next(this.intermediateModels);
this._oldIds = new Set(this.intermediateModels.map(model => model.user_id));
this._oldIds = new Set(this.intermediateModels.map(model => model.id));
}

public async createNewIntermediateModel(username: string): Promise<void> {
Expand All @@ -233,9 +248,11 @@ export class MotionManageMotionMeetingUsersComponent<V extends BaseHasMeetingUse
*/
public onRemove(model: MotionMeetingUser): void {
if (model.user_id) {
this._removeUsersMap[model.user_id] = model.id;
this._removeUsersMap[model.id] = model.id;
} else if (this._addUsersSet.has(model.id)) {
this._addUsersSet.delete(model.id);
} else if (model.user_id === undefined) {
this._removeUsersMap[model.id] = model.id;
}
const value = this.editSubject.getValue();
this.editSubject.next(value.filter(user => user.fqid !== model.fqid));
Expand Down Expand Up @@ -271,10 +288,10 @@ export class MotionManageMotionMeetingUsersComponent<V extends BaseHasMeetingUse
const newRemoveMap: IdMap = {};
const sortMap = new Map(this.editSubject.value.map((model, index) => [this.getUserId(model), index]));
for (const model of models) {
if (this._removeUsersMap[model.user_id]) {
newRemoveMap[model.user_id] = model.id;
} else if (this._addUsersSet.has(model.user_id)) {
this._addUsersSet.delete(model.user_id);
if (this._removeUsersMap[model.id]) {
newRemoveMap[model.id] = model?.id;
} else if (this._addUsersSet.has(model.id)) {
this._addUsersSet.delete(model.id);
}
}
this.editSubject.next(
Expand Down Expand Up @@ -303,11 +320,20 @@ export class MotionManageMotionMeetingUsersComponent<V extends BaseHasMeetingUse
* Adds the user to the list, if they aren't already in there.
*/
private async addUserAsIntermediateModel(model: MotionMeetingUser): Promise<void> {
if (!model?.user_id) {
if (this._oldIds.has(model.id)) {
delete this._removeUsersMap[model.id];
let userNumber = model.id;
if (!model?.user_id || model instanceof ViewUser) {
if (model instanceof ViewUser) {
const user = this.getIntermediateModels(this.motion).find(user => {
return user.user_id === model.id;
});
if (user !== undefined) {
userNumber = user.id;
}
}
if (this._oldIds.has(userNumber)) {
delete this._removeUsersMap[userNumber];
} else {
this._addUsersSet.add(model.id);
this._addUsersSet.add(userNumber);
}
}
const models = this.editSubject.value;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ <h2>{{ 'Motions' | translate }}</h2>
@if (motion.submitterNames.length) {
<span>
<span>{{ 'by' | translate }}</span>
{{ motion.submitterNames }}
{{ getSubmitterListWithDeletedUsers(motion.submitterNames) }}
</span>
}
@if (showSequential) {
Expand Down Expand Up @@ -303,13 +303,12 @@ <h2>{{ 'Motions' | translate }}</h2>
{{ motion.title }}
</span>
</div>

<!-- Submitters -->
<div class="submitters-line ellipsis-overflow">
@if (motion.submitterNames.length) {
<span>
<span>{{ 'by' | translate }}</span>
{{ motion.submitterNames }}
{{ getSubmitterListWithDeletedUsers(motion.submitterNames) }}
</span>
}
@if (showSequential) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -378,4 +378,8 @@ export class MotionListComponent extends BaseMeetingListViewComponent<ViewMotion
queryParams: { motions: motions_ids }
});
}

public getSubmitterListWithDeletedUsers(submitters: string[]): string[] {
return submitters.map(sub => sub ?? this.translate.instant(`Deleted user`));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,9 @@ export class AmendmentListPdfService {
text: amendment.getChangedLines()
},
{
text: amendment.submitterNames.toString()
text: amendment.submitterNames
.map(sub => (sub === undefined ? this.translate.instant(`Deleted user`) : sub))
.toString()
},
{
// requires stack cause this can be an array
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,12 @@ export class MotionCsvExportService {
case `submitters`:
return {
label: `submitters`,
map: motion => motion.mapSubmittersWithAdditional(s => s.full_name).join(`, `)
map: motion =>
motion
.mapSubmittersWithAdditional(s =>
s ? s.full_name : this.translate.instant(`Deleted user`)
)
.join(`, `)
};
case `editors`:
return {
Expand Down Expand Up @@ -204,7 +209,12 @@ export class MotionCsvExportService {
{ label: `Called with`, map: (motion): string => (!motion.sort_parent_id ? `` : motion.numberOrTitle) },
{
label: `submitters`,
map: (motion): string => motion.mapSubmittersWithAdditional(s => s.short_name).join(`,`)
map: (motion): string =>
motion
.mapSubmittersWithAdditional(s =>
s ? s.short_name : this.translate.instant(`Deleted user`)
)
.join(`,`)
},
{ property: `title` },
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,11 @@ export class MotionPdfCatalogService {
pageReference: `${motion.id}`,
style
},
this.pdfService.createTocLineInline(motion.submitterNames.join(`, `)),
this.pdfService.createTocLineInline(
motion.submitterNames
.map(submitter => (!submitter ? this.translate.instant(`Deleted user`) : submitter))
.join(`, `)
),
this.pdfService.createTocLineInline(state, true)
);
}
Expand Down
Loading
Loading