@if (canLeaveConversation || canChangeChannelArchivalState || canDeleteChannel) {
diff --git a/src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-settings/conversation-settings.component.ts b/src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-settings/conversation-settings.component.ts
index 9a9b9b56bb6e..3b1268fafeb8 100644
--- a/src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-settings/conversation-settings.component.ts
+++ b/src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-settings/conversation-settings.component.ts
@@ -1,4 +1,4 @@
-import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core';
+import { Component, OnDestroy, OnInit, inject, input, output } from '@angular/core';
import { ChannelDTO, getAsChannelDTO, isChannelDTO } from 'app/entities/metis/conversation/channel.model';
import { ConversationDTO } from 'app/entities/metis/conversation/conversation.model';
import { Course } from 'app/entities/course.model';
@@ -24,20 +24,12 @@ import { catchError } from 'rxjs/operators';
export class ConversationSettingsComponent implements OnInit, OnDestroy {
private ngUnsubscribe = new Subject();
- @Input()
- activeConversation: ConversationDTO;
+ activeConversation = input();
+ course = input();
- @Input()
- course: Course;
-
- @Output()
- channelArchivalChange: EventEmitter = new EventEmitter();
-
- @Output()
- channelDeleted: EventEmitter = new EventEmitter();
-
- @Output()
- conversationLeave: EventEmitter = new EventEmitter();
+ channelArchivalChange = output();
+ channelDeleted = output();
+ conversationLeave = output();
private dialogErrorSource = new Subject();
dialogError$ = this.dialogErrorSource.asObservable();
@@ -49,34 +41,35 @@ export class ConversationSettingsComponent implements OnInit, OnDestroy {
canChangeChannelArchivalState: boolean;
canDeleteChannel: boolean;
- constructor(
- private modalService: NgbModal,
- private channelService: ChannelService,
- private groupChatService: GroupChatService,
- private alertService: AlertService,
- ) {}
+ private modalService = inject(NgbModal);
+ private channelService = inject(ChannelService);
+ private groupChatService = inject(GroupChatService);
+ private alertService = inject(AlertService);
ngOnInit(): void {
- this.canLeaveConversation = canLeaveConversation(this.activeConversation);
-
- this.conversationAsChannel = getAsChannelDTO(this.activeConversation);
+ const conversation = this.activeConversation();
+ if (!conversation) {
+ return;
+ }
+ this.canLeaveConversation = canLeaveConversation(conversation);
+ this.conversationAsChannel = getAsChannelDTO(conversation);
this.canChangeChannelArchivalState = this.conversationAsChannel ? canChangeChannelArchivalState(this.conversationAsChannel) : false;
- this.canDeleteChannel = this.conversationAsChannel ? canDeleteChannel(this.course, this.conversationAsChannel) : false;
+ this.canDeleteChannel = this.conversationAsChannel ? canDeleteChannel(this.course()!, this.conversationAsChannel) : false;
}
leaveConversation($event: MouseEvent) {
$event.stopPropagation();
- if (isGroupChatDTO(this.activeConversation)) {
+ if (isGroupChatDTO(this.activeConversation()!)) {
this.groupChatService
- .removeUsersFromGroupChat(this.course.id!, this.activeConversation.id!)
+ .removeUsersFromGroupChat(this.course()!.id!, this.activeConversation()?.id!)
.pipe(takeUntil(this.ngUnsubscribe))
.subscribe(() => {
this.conversationLeave.emit();
});
return;
- } else if (isChannelDTO(this.activeConversation)) {
+ } else if (isChannelDTO(this.activeConversation()!)) {
this.channelService
- .deregisterUsersFromChannel(this.course.id!, this.activeConversation.id!)
+ .deregisterUsersFromChannel(this.course()!.id!, this.activeConversation()?.id!)
.pipe(takeUntil(this.ngUnsubscribe))
.subscribe(() => {
this.conversationLeave.emit();
@@ -92,7 +85,7 @@ export class ConversationSettingsComponent implements OnInit, OnDestroy {
}
openArchivalModal(event: MouseEvent) {
- const channel = getAsChannelDTO(this.activeConversation);
+ const channel = getAsChannelDTO(this.activeConversation()!);
if (!channel) {
return;
}
@@ -121,7 +114,7 @@ export class ConversationSettingsComponent implements OnInit, OnDestroy {
takeUntil(this.ngUnsubscribe),
)
.subscribe(() => {
- this.channelService.archive(this.course.id!, channel.id!).subscribe({
+ this.channelService.archive(this.course()?.id!, channel.id!).subscribe({
next: () => {
this.channelArchivalChange.emit();
},
@@ -131,7 +124,7 @@ export class ConversationSettingsComponent implements OnInit, OnDestroy {
}
openUnArchivalModal(event: MouseEvent) {
- const channel = getAsChannelDTO(this.activeConversation);
+ const channel = getAsChannelDTO(this.activeConversation()!);
if (!channel) {
return;
}
@@ -161,7 +154,7 @@ export class ConversationSettingsComponent implements OnInit, OnDestroy {
)
.subscribe(() => {
this.channelService
- .unarchive(this.course.id!, channel.id!)
+ .unarchive(this.course()?.id!, channel.id!)
.pipe(takeUntil(this.ngUnsubscribe))
.subscribe({
next: () => {
@@ -173,12 +166,12 @@ export class ConversationSettingsComponent implements OnInit, OnDestroy {
}
deleteChannel() {
- const channel = getAsChannelDTO(this.activeConversation);
+ const channel = getAsChannelDTO(this.activeConversation()!);
if (!channel) {
return;
}
this.channelService
- .delete(this.course.id!, channel.id!)
+ .delete(this.course()?.id!, channel.id!)
.pipe(takeUntil(this.ngUnsubscribe))
.subscribe({
next: () => {
diff --git a/src/test/javascript/spec/component/overview/course-conversations/dialogs/conversation-detail-dialog/conversation-detail-dialog.component.spec.ts b/src/test/javascript/spec/component/overview/course-conversations/dialogs/conversation-detail-dialog/conversation-detail-dialog.component.spec.ts
index 07100e45f567..dc0c8f2325a3 100644
--- a/src/test/javascript/spec/component/overview/course-conversations/dialogs/conversation-detail-dialog/conversation-detail-dialog.component.spec.ts
+++ b/src/test/javascript/spec/component/overview/course-conversations/dialogs/conversation-detail-dialog/conversation-detail-dialog.component.spec.ts
@@ -25,7 +25,7 @@ class ConversationMembersStubComponent {
@Input()
course: Course;
@Input()
- public activeConversation: ConversationDTO;
+ public activeConversationInput: ConversationDTO;
@Output() changesPerformed = new EventEmitter();
}
diff --git a/src/test/javascript/spec/component/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-info/conversation-info.component.spec.ts b/src/test/javascript/spec/component/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-info/conversation-info.component.spec.ts
index b06aea67f4ef..6f8c5379103d 100644
--- a/src/test/javascript/spec/component/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-info/conversation-info.component.spec.ts
+++ b/src/test/javascript/spec/component/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-info/conversation-info.component.spec.ts
@@ -18,6 +18,7 @@ import { HttpResponse } from '@angular/common/http';
import { of } from 'rxjs';
import { GenericUpdateTextPropertyDialogComponent } from 'app/overview/course-conversations/dialogs/generic-update-text-property-dialog/generic-update-text-property-dialog.component';
import { defaultSecondLayerDialogOptions } from 'app/overview/course-conversations/other/conversation.util';
+import { input } from '@angular/core';
const examples: ConversationDTO[] = [generateOneToOneChatDTO({}), generateExampleGroupChatDTO({}), generateExampleChannelDTO({})];
@@ -48,9 +49,11 @@ examples.forEach((activeConversation) => {
canChangeChannelProperties.mockReturnValue(true);
canChangeGroupChatProperties.mockReturnValue(true);
fixture = TestBed.createComponent(ConversationInfoComponent);
- component = fixture.componentInstance;
- component.activeConversation = activeConversation;
- component.course = course;
+ TestBed.runInInjectionContext(() => {
+ component = fixture.componentInstance;
+ component.activeConversation = input(activeConversation);
+ component.course = input(course);
+ });
component.canChangeChannelProperties = canChangeChannelProperties;
component.canChangeGroupChatProperties = canChangeGroupChatProperties;
fixture.detectChanges();
diff --git a/src/test/javascript/spec/component/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-member-row/conversation-member-row.component.spec.ts b/src/test/javascript/spec/component/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-member-row/conversation-member-row.component.spec.ts
index 1e43c269b9bf..59d135ef102f 100644
--- a/src/test/javascript/spec/component/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-member-row/conversation-member-row.component.spec.ts
+++ b/src/test/javascript/spec/component/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-member-row/conversation-member-row.component.spec.ts
@@ -23,6 +23,7 @@ import { isGroupChatDTO } from 'app/entities/metis/conversation/group-chat.model
import { By } from '@angular/platform-browser';
import { NgbDropdownMocksModule } from '../../../../../../../../helpers/mocks/directive/ngbDropdownMocks.module';
import { ProfilePictureComponent } from 'app/shared/profile-picture/profile-picture.component';
+import { input, runInInjectionContext } from '@angular/core';
const memberTemplate = {
id: 1,
@@ -85,10 +86,12 @@ examples.forEach((activeConversation) => {
canRevokeChannelModeratorRole.mockReturnValue(true);
fixture = TestBed.createComponent(ConversationMemberRowComponent);
- component = fixture.componentInstance;
- component.activeConversation = activeConversation;
- component.course = course;
- component.conversationMember = conversationMember;
+ TestBed.runInInjectionContext(() => {
+ component = fixture.componentInstance;
+ component.activeConversation = input(activeConversation);
+ component.course = input(course);
+ component.conversationMember = input(conversationMember);
+ });
component.canRevokeChannelModeratorRole = canRevokeChannelModeratorRole;
component.canGrantChannelModeratorRole = canGrantChannelModeratorRole;
component.canRemoveUsersFromConversation = canRemoveUsersFromConversation;
@@ -156,7 +159,11 @@ examples.forEach((activeConversation) => {
it('should show grant moderator button if user is not yet moderator', fakeAsync(() => {
if (isChannelDTO(activeConversation)) {
- component.conversationMember.isChannelModerator = false;
+ runInInjectionContext(fixture.debugElement.injector, () => {
+ const conversationMember = component.conversationMember();
+ (conversationMember as ChannelDTO).isChannelModerator = false;
+ component.conversationMember = input(conversationMember as ConversationUserDTO);
+ });
fixture.detectChanges();
tick();
fixture.detectChanges();
diff --git a/src/test/javascript/spec/component/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-members.component.spec.ts b/src/test/javascript/spec/component/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-members.component.spec.ts
index 4e18e0a62496..d4f4e305d886 100644
--- a/src/test/javascript/spec/component/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-members.component.spec.ts
+++ b/src/test/javascript/spec/component/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-members.component.spec.ts
@@ -3,7 +3,7 @@ import { FaIconComponent } from '@fortawesome/angular-fontawesome';
import { ConversationMembersComponent } from 'app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-members.component';
import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe';
import { MockComponent, MockPipe, MockProvider } from 'ng-mocks';
-import { Component, EventEmitter, Input, Output } from '@angular/core';
+import { Component, EventEmitter, Input, Output, input, signal } from '@angular/core';
import { ConversationDTO } from 'app/entities/metis/conversation/conversation.model';
import { Course } from 'app/entities/course.model';
import { ConversationUserDTO } from 'app/entities/metis/conversation/conversation-user-dto.model';
@@ -75,9 +75,11 @@ examples.forEach((activeConversation) => {
canAddUsersToConversation.mockReturnValue(true);
fixture = TestBed.createComponent(ConversationMembersComponent);
- component = fixture.componentInstance;
- component.activeConversation = activeConversation;
- component.course = course;
+ TestBed.runInInjectionContext(() => {
+ component = fixture.componentInstance;
+ component.activeConversation = signal(activeConversation);
+ component.course = input(course);
+ });
component.canAddUsersToConversation = canAddUsersToConversation;
});
@@ -147,7 +149,7 @@ examples.forEach((activeConversation) => {
const modalService = TestBed.inject(NgbModal);
const mockModalRef = {
- componentInstance: { course: undefined, activeConversation: undefined, initialize: () => {} },
+ componentInstance: { course: component.course(), activeConversation: component.activeConversation(), initialize: () => {} },
result: Promise.resolve(),
};
const openDialogSpy = jest.spyOn(modalService, 'open').mockReturnValue(mockModalRef as unknown as NgbModalRef);
@@ -159,7 +161,7 @@ examples.forEach((activeConversation) => {
expect(openDialogSpy).toHaveBeenCalledOnce();
expect(openDialogSpy).toHaveBeenCalledWith(ConversationAddUsersDialogComponent, defaultSecondLayerDialogOptions);
expect(mockModalRef.componentInstance.course).toEqual(course);
- expect(mockModalRef.componentInstance.activeConversation).toEqual(activeConversation);
+ expect(mockModalRef.componentInstance.activeConversation?.id).toEqual(activeConversation.id);
});
}));
diff --git a/src/test/javascript/spec/component/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-settings/conversation-settings.component.spec.ts b/src/test/javascript/spec/component/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-settings/conversation-settings.component.spec.ts
index 3f4670775995..85057eddc05d 100644
--- a/src/test/javascript/spec/component/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-settings/conversation-settings.component.spec.ts
+++ b/src/test/javascript/spec/component/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-settings/conversation-settings.component.spec.ts
@@ -18,6 +18,7 @@ import { HttpResponse } from '@angular/common/http';
import { GenericConfirmationDialogComponent } from 'app/overview/course-conversations/dialogs/generic-confirmation-dialog/generic-confirmation-dialog.component';
import { defaultSecondLayerDialogOptions } from 'app/overview/course-conversations/other/conversation.util';
import * as ConversationPermissionUtils from 'app/shared/metis/conversations/conversation-permissions.utils';
+import { input, runInInjectionContext } from '@angular/core';
const examples: ConversationDTO[] = [generateExampleGroupChatDTO({}), generateExampleChannelDTO({})];
@@ -43,12 +44,19 @@ examples.forEach((activeConversation) => {
canDeleteChannel.mockReturnValue(true);
fixture = TestBed.createComponent(ConversationSettingsComponent);
component = fixture.componentInstance;
- component.course = course;
- component.activeConversation = activeConversation;
- component.ngOnInit();
+ TestBed.runInInjectionContext(() => {
+ component.course = input(course);
+ component.activeConversation = input(activeConversation);
+ component.ngOnInit();
+ });
fixture.detectChanges();
});
+ afterEach(() => {
+ // Reset injection context
+ TestBed.resetTestingModule();
+ });
+
it('should create', () => {
expect(component).toBeTruthy();
});
@@ -118,7 +126,11 @@ examples.forEach((activeConversation) => {
it('should open unarchive dialog when button is pressed', fakeAsync(() => {
if (isChannelDTO(activeConversation)) {
- (component.activeConversation as ChannelDTO).isArchived = true;
+ runInInjectionContext(fixture.debugElement.injector, () => {
+ const activeConversation = component.activeConversation();
+ (activeConversation as ChannelDTO).isArchived = true;
+ component.activeConversation = input(activeConversation as ConversationDTO);
+ });
fixture.detectChanges();
const channelService = TestBed.inject(ChannelService);
const unarchivespy = jest.spyOn(channelService, 'unarchive').mockReturnValue(of(new HttpResponse({ status: 200 }) as HttpResponse));