Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
22 changes: 17 additions & 5 deletions web-app/django/VIM/templates/instruments/create.html
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,23 @@ <h5>Image (Optional)</h5>
<div class="row">
<div class="col-md-6 mb-3">
<label for="image" class="form-label">Image File</label>
<input type="file"
class="form-control"
id="image"
name="image"
accept="image/jpeg,image/png,image/gif,image/webp" />
<div class="input-group">
<input type="file"
class="form-control"
id="image"
name="image"
accept="image/jpeg,image/png,image/gif,image/webp" />
<button type="button"
class="btn btn-outline-danger"
id="deleteImageBtn"
style="display: none"
tabindex="-1">
<i class="bi bi-trash"></i> Delete
</button>
</div>
<div class="form-text d-none" id="selectDifferentImageText">
To select a different image, click on “Choose File” again.
</div>
<div class="form-text">
Accepted formats: JPEG, PNG, GIF, WebP.
<br />
Expand Down
101 changes: 62 additions & 39 deletions web-app/frontend/src/instruments/helpers/CreateInstrumentManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,55 +57,78 @@ export class CreateInstrumentManager {
* Toggles image source field visibility based on image selection
*/
setupImageFieldToggle(): void {
const imageInput = document.getElementById('image') as HTMLInputElement;
const imageInput = document.getElementById(
'image',
) as HTMLInputElement | null;
const imageSourceContainer = document.getElementById(
'imageSourceContainer',
);
const imagePreview = document.getElementById(
'imagePreview',
) as HTMLImageElement;
) as HTMLImageElement | null;
const imagePreviewContainer = document.getElementById(
'imagePreviewContainer',
);
const deleteBtn = document.getElementById(
'deleteImageBtn',
) as HTMLButtonElement | null;
const selectDifferentText = document.getElementById(
'selectDifferentImageText',
);

if (imageInput && imageSourceContainer) {
imageInput.addEventListener('change', () => {
const files = imageInput.files;
if (files && files.length > 0) {
imageSourceContainer.classList.remove('d-none');
const sourceInput = imageSourceContainer.querySelector(
'input',
) as HTMLInputElement;
if (sourceInput) {
sourceInput.required = true;
}

// Show image preview
if (imagePreview && imagePreviewContainer) {
const reader = new FileReader();
reader.onload = (e) => {
imagePreview.src = e.target?.result as string;
imagePreviewContainer.classList.remove('d-none');
};
reader.readAsDataURL(files[0]);
}
} else {
imageSourceContainer.classList.add('d-none');
const sourceInput = imageSourceContainer.querySelector(
'input',
) as HTMLInputElement;
if (sourceInput) {
sourceInput.required = false;
sourceInput.value = '';
}

// Hide image preview
if (imagePreviewContainer) {
imagePreviewContainer.classList.add('d-none');
}
}
});
// Check for absence once
if (
!imageInput ||
!imageSourceContainer ||
!imagePreview ||
!imagePreviewContainer ||
!deleteBtn ||
!selectDifferentText
)
return;

const getSourceInput = () =>
imageSourceContainer.querySelector('input') as HTMLInputElement | null;

function resetImageInput() {
imageInput.value = '';
imagePreview.src = '';
imagePreviewContainer.classList.add('d-none');
deleteBtn.style.display = 'none';
selectDifferentText.classList.add('d-none');
imageSourceContainer.classList.add('d-none');
const sourceInput = getSourceInput();
if (sourceInput) {
sourceInput.required = false;
sourceInput.value = '';
}
}

imageInput.addEventListener('change', function () {
const file = imageInput.files && imageInput.files[0];
if (file) {
// Show and require source
imageSourceContainer.classList.remove('d-none');
const sourceInput = getSourceInput();
if (sourceInput) sourceInput.required = true;

// Preview and UI
const reader = new FileReader();
reader.onload = function (e) {
imagePreview.src = e.target?.result as string;
imagePreviewContainer.classList.remove('d-none');
};
reader.readAsDataURL(file);
deleteBtn.style.display = '';
selectDifferentText.classList.remove('d-none');
} else {
resetImageInput();
}
});

deleteBtn.addEventListener('click', function () {
resetImageInput();
});
}

/**
Expand Down
Loading