hotfix: enhance radio button and file upload components
- Improved the styling and functionality of the radio button component, including a new radio button style. - Added a loading spinner to the file upload component to indicate when large files are being processed. - Added the ability to sort files in the file upload component. - Fixed an issue where the radio button component was not correctly updating the model value. - Updated the dataset creation and edit forms to use the new radio button component. - Added a global declaration for the `sort_order` property on the `File` interface. - Updated the API to filter authors by first and last name. - Removed the import of `_checkbox-radio-switch.css` as the radio button styling is now handled within the component.
This commit is contained in:
parent
b93e46207f
commit
9823364670
11 changed files with 272 additions and 181 deletions
|
@ -17,6 +17,15 @@
|
|||
<p class="text-lg text-blue-700">Drop files to upload</p>
|
||||
</div>
|
||||
|
||||
<!-- Loading Spinner when processing big files -->
|
||||
<div v-if="isLoading" class="absolute inset-0 z-60 flex items-center justify-center bg-gray-500 bg-opacity-50">
|
||||
<svg class="animate-spin h-12 w-12 text-white" xmlns="http://www.w3.org/2000/svg" fill="none"
|
||||
viewBox="0 0 24 24">
|
||||
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
||||
<path class="opacity-75" fill="currentColor" d="M12 2a10 10 0 0110 10h-4a6 6 0 00-6-6V2z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<!-- scroll area -->
|
||||
<div class="h-full p-8 w-full h-full flex flex-col">
|
||||
<header class="flex items-center justify-center w-full">
|
||||
|
@ -32,9 +41,8 @@
|
|||
<p class="mb-2 text-sm text-gray-500 dark:text-gray-400">
|
||||
<span class="font-semibold">Click to upload</span> or drag and drop
|
||||
</p>
|
||||
<!-- <p class="text-xs text-gray-500 dark:text-gray-400">SVG, PNG, JPG or GIF (MAX. 800x400px)</p> -->
|
||||
</div>
|
||||
<input id="dropzone-file" type="file" class="hidden" @change="onChangeFile" multiple="true" />
|
||||
<input id="dropzone-file" type="file" class="hidden" @click="showSpinner" @change="onChangeFile" @cancel="cancelSpinner" multiple="true" />
|
||||
</label>
|
||||
</header>
|
||||
|
||||
|
@ -241,6 +249,8 @@ class FileUploadComponent extends Vue {
|
|||
|
||||
@Ref('overlay') overlay: HTMLDivElement;
|
||||
|
||||
|
||||
public isLoading: boolean = false;
|
||||
private counter: number = 0;
|
||||
// @Prop() files: Array<TestFile>;
|
||||
|
||||
|
@ -264,7 +274,7 @@ class FileUploadComponent extends Vue {
|
|||
set deletetFiles(values: Array<TethysFile>) {
|
||||
// this.modelValue = value;
|
||||
this.filesToDelete.length = 0;
|
||||
this.filesToDelete.push(...values);
|
||||
this.filesToDelete.push(...values);
|
||||
}
|
||||
|
||||
get items(): Array<TethysFile | File> {
|
||||
|
@ -342,10 +352,10 @@ class FileUploadComponent extends Vue {
|
|||
}
|
||||
|
||||
// reset counter and append file to gallery when file is dropped
|
||||
|
||||
public dropHandler(event: DragEvent): void {
|
||||
event.preventDefault();
|
||||
const dataTransfer = event.dataTransfer;
|
||||
// let bigFileFound = false;
|
||||
if (dataTransfer) {
|
||||
for (const file of event.dataTransfer?.files) {
|
||||
// let fileName = String(file.name.replace(/\.[^/.]+$/, ''));
|
||||
|
@ -353,28 +363,73 @@ class FileUploadComponent extends Vue {
|
|||
// if (file.type.match('image.*')) {
|
||||
// this.generateURL(file);
|
||||
// }
|
||||
// if (file.size > 62914560) { // 60 MB in bytes
|
||||
// bigFileFound = true;
|
||||
// }
|
||||
this._addFile(file);
|
||||
}
|
||||
this.overlay.classList.remove('draggedover');
|
||||
this.counter = 0;
|
||||
}
|
||||
// if (bigFileFound) {
|
||||
// this.isLoading = true;
|
||||
// // Assume file processing delay; adjust timeout as needed or rely on async processing completion.
|
||||
// setTimeout(() => {
|
||||
// this.isLoading = false;
|
||||
// }, 1500);
|
||||
// }
|
||||
}
|
||||
|
||||
public showSpinner() {
|
||||
// event.preventDefault();
|
||||
this.isLoading = true;
|
||||
}
|
||||
|
||||
public cancelSpinner() {
|
||||
// const target = event.target as HTMLInputElement;
|
||||
// // If no files were selected, remove spinner
|
||||
// if (!target.files || target.files.length === 0) {
|
||||
// this.isLoading = false;
|
||||
// }
|
||||
this.isLoading = false;
|
||||
}
|
||||
|
||||
public onChangeFile(event: Event) {
|
||||
event.preventDefault();
|
||||
let target = event.target as HTMLInputElement;
|
||||
// let uploadedFile = event.target.files[0];
|
||||
// let fileName = String(event.target.files[0].name.replace(/\.[^/.]+$/, ''));
|
||||
|
||||
for (const file of event.target.files) {
|
||||
// let fileName = String(event.target.files[0].name.replace(/\.[^/.]+$/, ''));
|
||||
// file.label = fileName;
|
||||
// if (file.type.match('image.*')) {
|
||||
// this.generateURL(file);
|
||||
// }
|
||||
this._addFile(file);
|
||||
if (target && target.files) {
|
||||
for (const file of event.target.files) {
|
||||
// let fileName = String(event.target.files[0].name.replace(/\.[^/.]+$/, ''));
|
||||
// file.label = fileName;
|
||||
// if (file.type.match('image.*')) {
|
||||
// this.generateURL(file);
|
||||
// }
|
||||
// Immediately set spinner if any file is large (over 100 MB)
|
||||
// for (const file of target.files) {
|
||||
// if (file.size > 62914560) { // 100 MB
|
||||
// bigFileFound = true;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// if (bigFileFound) {
|
||||
// this.isLoading = true;
|
||||
// }
|
||||
this._addFile(file);
|
||||
|
||||
}
|
||||
}
|
||||
// if (bigFileFound) {
|
||||
// this.isLoading = true;
|
||||
// setTimeout(() => {
|
||||
// this.isLoading = false;
|
||||
// }, 1500);
|
||||
// }
|
||||
// this.overlay.classList.remove('draggedover');
|
||||
this.counter = 0;
|
||||
this.isLoading = false;
|
||||
}
|
||||
|
||||
get errors(): IDictionary {
|
||||
|
@ -445,7 +500,7 @@ class FileUploadComponent extends Vue {
|
|||
let localUrl: string = '';
|
||||
if (file instanceof File) {
|
||||
localUrl = URL.createObjectURL(file as Blob);
|
||||
}
|
||||
}
|
||||
// else if (file.fileData) {
|
||||
// // const blob = new Blob([file.fileData]);
|
||||
// // localUrl = URL.createObjectURL(blob);
|
||||
|
@ -465,17 +520,6 @@ class FileUploadComponent extends Vue {
|
|||
return localUrl;
|
||||
}
|
||||
|
||||
// private async downloadFile(id: number): Promise<string> {
|
||||
// const response = await axios.get<Blob>(`/api/download/${id}`, {
|
||||
// responseType: 'blob',
|
||||
// });
|
||||
// const url = URL.createObjectURL(response.data);
|
||||
// setTimeout(() => {
|
||||
// URL.revokeObjectURL(url);
|
||||
// }, 1000);
|
||||
// return url;
|
||||
// }
|
||||
|
||||
public getFileSize(file: File) {
|
||||
if (file.size > 1024) {
|
||||
if (file.size > 1048576) {
|
||||
|
@ -488,17 +532,6 @@ class FileUploadComponent extends Vue {
|
|||
}
|
||||
}
|
||||
|
||||
// private _addFile(file) {
|
||||
// // const isImage = file.type.match('image.*');
|
||||
// // const objectURL = URL.createObjectURL(file);
|
||||
|
||||
// // this.files[objectURL] = file;
|
||||
// // let test: TethysFile = { upload: file, label: "dfdsfs", sorting: 0 };
|
||||
// // file.sorting = this.files.length;
|
||||
// file.sort_order = (this.items.length + 1),
|
||||
// this.files.push(file);
|
||||
// }
|
||||
|
||||
private _addFile(file: File) {
|
||||
// const reader = new FileReader();
|
||||
// reader.onload = (event) => {
|
||||
|
@ -530,14 +563,11 @@ class FileUploadComponent extends Vue {
|
|||
// this.items.push(test);
|
||||
this.items[this.items.length] = test;
|
||||
} else {
|
||||
file.sort_order = this.items.length + 1;
|
||||
this.items.push(file);
|
||||
}
|
||||
}
|
||||
|
||||
// use to check if a file is being dragged
|
||||
// private _hasFiles({ types = [] as Array<string> }) {
|
||||
// return types.indexOf('Files') > -1;
|
||||
// }
|
||||
private _hasFiles(dataTransfer: DataTransfer | null): boolean {
|
||||
return dataTransfer ? dataTransfer.items.length > 0 : false;
|
||||
}
|
||||
|
|
Loading…
Add table
editor.link_modal.header
Reference in a new issue