diff --git a/frontend/angular-clarity-master/src/app/modules/main/BuilderComponents/file-uploader/file-uploader.component.html b/frontend/angular-clarity-master/src/app/modules/main/BuilderComponents/file-uploader/file-uploader.component.html new file mode 100644 index 0000000..6767fa5 --- /dev/null +++ b/frontend/angular-clarity-master/src/app/modules/main/BuilderComponents/file-uploader/file-uploader.component.html @@ -0,0 +1,57 @@ +
+ + + +
+ + Uploading... +
+ + +
+ +
+ + +
+ +
+ {{ value }} +
+ + +
+ +
+ + +
+ +
+ + +
+ + {{ value }} + +
+
+
+ diff --git a/frontend/angular-clarity-master/src/app/modules/main/BuilderComponents/file-uploader/file-uploader.component.scss b/frontend/angular-clarity-master/src/app/modules/main/BuilderComponents/file-uploader/file-uploader.component.scss new file mode 100644 index 0000000..a4bfbb6 --- /dev/null +++ b/frontend/angular-clarity-master/src/app/modules/main/BuilderComponents/file-uploader/file-uploader.component.scss @@ -0,0 +1,102 @@ +.file-uploader-container { + margin-bottom: 0.5rem; + + .clr-control-label { + display: block; + font-size: 0.65rem; + font-weight: 600; + margin-bottom: 0.25rem; + color: #444; + } + + .upload-input-row { + margin-top: 0.25rem; + + .upload-btn { + position: relative; + cursor: pointer; + display: inline-flex; + align-items: center; + gap: 0.35rem; + margin: 0; + + .hidden-file-input { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + opacity: 0; + cursor: pointer; + } + } + } + + .uploading-state { + display: flex; + align-items: center; + gap: 0.5rem; + padding: 0.35rem 0; + color: #555; + font-size: 0.75rem; + } + + .preview-container { + margin-top: 0.35rem; + padding: 0.4rem; + border: 1px solid #e0e0e0; + border-radius: 4px; + background-color: #fafafa; + + .image-preview img { + max-width: 100%; + max-height: 120px; + object-fit: cover; + border-radius: 3px; + margin-bottom: 0.3rem; + display: block; + } + + .audio-preview audio { + width: 100%; + height: 36px; + margin-bottom: 0.3rem; + } + + .video-preview video { + max-width: 100%; + max-height: 140px; + border-radius: 3px; + margin-bottom: 0.3rem; + display: block; + } + + .file-meta { + display: flex; + align-items: center; + gap: 0.35rem; + font-size: 0.75rem; + + .file-icon { + flex-shrink: 0; + } + + .file-name { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + flex-grow: 1; + color: #0072a3; + text-decoration: underline; + } + + .remove-btn { + margin: 0; + padding: 0 0.25rem; + min-width: auto; + color: #c92c2c; + } + } + } +} + diff --git a/frontend/angular-clarity-master/src/app/modules/main/BuilderComponents/file-uploader/file-uploader.component.ts b/frontend/angular-clarity-master/src/app/modules/main/BuilderComponents/file-uploader/file-uploader.component.ts new file mode 100644 index 0000000..dd96beb --- /dev/null +++ b/frontend/angular-clarity-master/src/app/modules/main/BuilderComponents/file-uploader/file-uploader.component.ts @@ -0,0 +1,122 @@ +import { Component, forwardRef, Input } from '@angular/core'; +import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; +import { HttpClient } from '@angular/common/http'; +import { ToastrService } from 'ngx-toastr'; +import { AppConfig } from 'src/app/app-config'; + +@Component({ + selector: 'app-file-uploader', + templateUrl: './file-uploader.component.html', + styleUrls: ['./file-uploader.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => FileUploaderComponent), + multi: true + } + ] +}) +export class FileUploaderComponent implements ControlValueAccessor { + @Input() label: string = 'Upload File'; + @Input() type: 'file' | 'image' | 'audio' | 'video' = 'file'; + @Input() ref: string = 'common'; + @Input() tableName: string = 'files'; + + value: string = ''; + uploading: boolean = false; + disabled: boolean = false; + + private onChange: (val: any) => void = () => {}; + private onTouched: () => void = () => {}; + + constructor( + private http: HttpClient, + private appConfig: AppConfig, + private toastr: ToastrService + ) {} + + get acceptTypes(): string { + switch (this.type) { + case 'image': + return 'image/*'; + case 'audio': + return 'audio/*'; + case 'video': + return 'video/*'; + default: + return '*/*'; + } + } + + get fileUrl(): string { + if (!this.value) { + return ''; + } + if (this.value.startsWith('http://') || this.value.startsWith('https://')) { + return this.value; + } + const base = this.appConfig?.baseApiPath || ''; + const cleanBase = base.endsWith('/') ? base : base + '/'; + return `${cleanBase}FileUpload/files/${this.value}`; + } + + writeValue(val: any): void { + this.value = val || ''; + } + + registerOnChange(fn: any): void { + this.onChange = fn; + } + + registerOnTouched(fn: any): void { + this.onTouched = fn; + } + + setDisabledState?(isDisabled: boolean): void { + this.disabled = isDisabled; + } + + onFileSelected(event: any): void { + const file = event.target.files && event.target.files[0]; + if (!file) { + return; + } + + this.uploading = true; + const formData = new FormData(); + formData.append('file', file); + + const base = this.appConfig?.baseApiPath || ''; + const cleanBase = base.endsWith('/') ? base : base + '/'; + const uploadUrl = `${cleanBase}FileUpload/Uploadeddocs/${this.ref}/${this.tableName}`; + + this.http.post(uploadUrl, formData).subscribe({ + next: (res) => { + this.uploading = false; + const filename = res?.uploadedfile_name || file.name; + this.value = filename; + this.onChange(this.value); + this.onTouched(); + this.toastr.success('File uploaded successfully'); + event.target.value = ''; + }, + error: (err) => { + this.uploading = false; + console.error('File upload failed', err); + this.toastr.error('File upload failed'); + event.target.value = ''; + } + }); + } + + removeFile(): void { + this.value = ''; + this.onChange(''); + this.onTouched(); + } + + onImgError(event: any): void { + console.warn('Image failed to load:', this.fileUrl); + } +} + diff --git a/frontend/angular-clarity-master/src/app/modules/main/main.module.ts b/frontend/angular-clarity-master/src/app/modules/main/main.module.ts index 714ccd6..cdd3bd2 100644 --- a/frontend/angular-clarity-master/src/app/modules/main/main.module.ts +++ b/frontend/angular-clarity-master/src/app/modules/main/main.module.ts @@ -106,6 +106,7 @@ import { MappingruleaddComponent } from './datamanagement/mappingrule/mappingrul import { MappingruleallComponent } from './datamanagement/mappingrule/mappingruleall/mappingruleall.component'; import { MappingruleeditComponent } from './datamanagement/mappingrule/mappingruleedit/mappingruleedit.component'; import { Stepper_workflowComponent } from './BuilderComponents/stepperworkflow/Stepper_workflow/Stepper_workflow.component'; +import { FileUploaderComponent } from './BuilderComponents/file-uploader/file-uploader.component'; import { Token_registeryComponent } from './fnd/Token_registery/Token_registery.component'; import { MyworkspaceComponent } from './admin/myworkspace/myworkspace.component'; import { DynamicformComponent } from './superadmin/dynamicform/dynamicform.component'; @@ -140,6 +141,7 @@ import { DynamicFormViewerComponent } from './superadmin/dynamicform/dynamic-for // buildercomponents + FileUploaderComponent, diff --git a/frontend/angular-clarity-master/src/environments/environment.prod.ts b/frontend/angular-clarity-master/src/environments/environment.prod.ts index f038c84..4dc13f2 100644 --- a/frontend/angular-clarity-master/src/environments/environment.prod.ts +++ b/frontend/angular-clarity-master/src/environments/environment.prod.ts @@ -9,9 +9,8 @@ export const environment = { // changeble url // port captchaSiteKey: '6LfrdSUpAAAAALkYDmnvdX3GLLCArgPWNHfXasjP', - - //Deployment configs - + + //Deployment configs };