diff --git a/src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/attachment-unit-form/attachment-unit-form.component.html b/src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/attachment-unit-form/attachment-unit-form.component.html
index 7c8434dc9023..f658308506ef 100644
--- a/src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/attachment-unit-form/attachment-unit-form.component.html
+++ b/src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/attachment-unit-form/attachment-unit-form.component.html
@@ -2,7 +2,7 @@
-
- @if (hasCancelButton()) {
-
diff --git a/src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/attachment-unit-form/attachment-unit-form.component.ts b/src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/attachment-unit-form/attachment-unit-form.component.ts
index 1bc42524d04b..92f071e8a537 100644
--- a/src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/attachment-unit-form/attachment-unit-form.component.ts
+++ b/src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/attachment-unit-form/attachment-unit-form.component.ts
@@ -6,7 +6,9 @@ import { ACCEPTED_FILE_EXTENSIONS_FILE_BROWSER, ALLOWED_FILE_EXTENSIONS_HUMAN_RE
import { CompetencyLectureUnitLink } from 'app/entities/competency.model';
import { MAX_FILE_SIZE } from 'app/shared/constants/input.constants';
import { toSignal } from '@angular/core/rxjs-interop';
+import { map, of } from 'rxjs';
import { FormDateTimePickerComponent } from 'app/shared/date-time-picker/date-time-picker.component';
+import { TranslateService } from '@ngx-translate/core';
export interface AttachmentUnitFormData {
formProperties: FormProperties;
@@ -50,7 +52,7 @@ export class AttachmentUnitFormComponent implements OnChanges {
datePickerComponent = viewChild(FormDateTimePickerComponent);
- // have to handle the file input as a special case at is not part of the reactive form
+ // have to handle the file input as a special case, as it is not part of the reactive form
@ViewChild('fileInput', { static: false })
fileInput: ElementRef;
file: File;
@@ -59,6 +61,7 @@ export class AttachmentUnitFormComponent implements OnChanges {
fileName = signal(undefined);
isFileTooBig = signal(false);
+ private readonly translateService = inject(TranslateService);
private readonly formBuilder = inject(FormBuilder);
form: FormGroup = this.formBuilder.group({
name: [undefined as string | undefined, [Validators.required, Validators.maxLength(255)]],
@@ -69,9 +72,9 @@ export class AttachmentUnitFormComponent implements OnChanges {
competencyLinks: [undefined as CompetencyLectureUnitLink[] | undefined],
});
private readonly statusChanges = toSignal(this.form.statusChanges ?? 'INVALID');
-
+ private readonly name = toSignal(this.nameControl?.valueChanges ?? of(''));
isFormValid = computed(() => {
- return (this.statusChanges() === 'VALID' || this.fileName()) && !this.isFileTooBig() && this.datePickerComponent()?.isValid();
+ return this.statusChanges() === 'VALID' && !this.isFileTooBig() && this.name() && this.fileName();
});
ngOnChanges(): void {
@@ -80,6 +83,8 @@ export class AttachmentUnitFormComponent implements OnChanges {
}
}
+ private readonly currentLanguage = toSignal(this.translateService.onLangChange.pipe(map((event) => event.lang)));
+
onFileChange(event: Event): void {
const input = event.target as HTMLInputElement;
if (!input.files?.length) {
@@ -88,7 +93,7 @@ export class AttachmentUnitFormComponent implements OnChanges {
this.file = input.files[0];
this.fileName.set(this.file.name);
// automatically set the name in case it is not yet specified
- if (this.form && (this.nameControl?.value == undefined || this.nameControl?.value == '')) {
+ if (this.form && !this.name()) {
this.form.patchValue({
// without extension
name: this.file.name.replace(/\.[^/.]+$/, ''),
@@ -97,6 +102,20 @@ export class AttachmentUnitFormComponent implements OnChanges {
this.isFileTooBig.set(this.file.size > MAX_FILE_SIZE);
}
+ tooltipText = computed(() => {
+ this.currentLanguage();
+ if (!this.fileName() && !this.name()) {
+ return this.translateService.instant('artemisApp.attachmentUnit.createAttachmentUnit.nameAndFileRequiredValidationError');
+ }
+ if (!this.fileName()) {
+ return this.translateService.instant('artemisApp.attachmentUnit.createAttachmentUnit.fileRequiredValidationError');
+ }
+ if (!this.name()) {
+ return this.translateService.instant('artemisApp.attachmentUnit.createAttachmentUnit.nameRequiredValidationError');
+ }
+ return undefined;
+ });
+
get nameControl() {
return this.form.get('name');
}
diff --git a/src/main/webapp/i18n/de/lectureUnit.json b/src/main/webapp/i18n/de/lectureUnit.json
index 2ed9397e04ff..4e8d8efa8002 100644
--- a/src/main/webapp/i18n/de/lectureUnit.json
+++ b/src/main/webapp/i18n/de/lectureUnit.json
@@ -173,6 +173,7 @@
"file": "Datei",
"version": "Version",
"fileRequiredValidationError": "Du musst eine Datei zum Uploaden auswählen.",
+ "nameAndFileRequiredValidationError": "Der Name ist ein Pflichtfeld. Du musst eine Datei zum Uploaden auswählen.",
"chooseFile": "Datei auswählen",
"fileTooBig": "Die Datei ist zu groß! Die maximale Dateigröße beträgt 20 MB.",
"fileLimitation": "(max. Größe 20 MB)",
diff --git a/src/main/webapp/i18n/en/lectureUnit.json b/src/main/webapp/i18n/en/lectureUnit.json
index d54a06f188b1..8513f82b8306 100644
--- a/src/main/webapp/i18n/en/lectureUnit.json
+++ b/src/main/webapp/i18n/en/lectureUnit.json
@@ -173,6 +173,7 @@
"file": "File",
"version": "Version",
"fileRequiredValidationError": "You must select a file to upload.",
+ "nameAndFileRequiredValidationError": "Name is required. You must select a file to upload.",
"chooseFile": "Choose File",
"fileTooBig": "File is too big! The maximum file size is 20 MB.",
"fileLimitation": "(max. size 20 MB)",