From e9c70298a5c425b4e1c9833a78db9161d5c6089c Mon Sep 17 00:00:00 2001 From: Yagnik Hingrajiya <50392803+Yagnik56@users.noreply.github.com> Date: Wed, 10 Jul 2024 02:40:50 +0530 Subject: [PATCH] common import container (#1734) * common import container * added comment for example use * resolved review cmts --------- Co-authored-by: danoswaltCL <97542869+danoswaltCL@users.noreply.github.com> --- .../import-feature-flag-modal.component.html | 31 ++------ .../import-feature-flag-modal.component.scss | 46 +---------- .../import-feature-flag-modal.component.ts | 53 +++---------- .../common-import-container.component.html | 14 ++++ .../common-import-container.component.scss | 29 +++++++ .../common-import-container.component.ts | 79 +++++++++++++++++++ .../common-modal.component.spec.ts | 22 ------ .../common-modal/common-modal.component.ts | 1 - .../shared/services/common-dialog.service.ts | 2 +- types/src/Experiment/enums.ts | 5 ++ types/src/index.ts | 1 + 11 files changed, 151 insertions(+), 132 deletions(-) create mode 100644 frontend/projects/upgrade/src/app/shared-standalone-component-lib/components/common-import-container/common-import-container.component.html create mode 100644 frontend/projects/upgrade/src/app/shared-standalone-component-lib/components/common-import-container/common-import-container.component.scss create mode 100644 frontend/projects/upgrade/src/app/shared-standalone-component-lib/components/common-import-container/common-import-container.component.ts delete mode 100644 frontend/projects/upgrade/src/app/shared-standalone-component-lib/components/common-modal/common-modal.component.spec.ts diff --git a/frontend/projects/upgrade/src/app/features/dashboard/feature-flags/modals/import-feature-flag-modal/import-feature-flag-modal.component.html b/frontend/projects/upgrade/src/app/features/dashboard/feature-flags/modals/import-feature-flag-modal/import-feature-flag-modal.component.html index 259e49ebe8..6632f185b8 100644 --- a/frontend/projects/upgrade/src/app/features/dashboard/feature-flags/modals/import-feature-flag-modal/import-feature-flag-modal.component.html +++ b/frontend/projects/upgrade/src/app/features/dashboard/feature-flags/modals/import-feature-flag-modal/import-feature-flag-modal.component.html @@ -5,32 +5,17 @@ [primaryActionBtnLabel]="data.primaryActionBtnLabel" [primaryActionBtnColor]="data.primaryActionBtnColor" [primaryActionBtnDisabled]="isImportActionBtnDisabled | async" + (primaryActionBtnClicked)="importFiles()" >
-
-
- close -
-
- insert_drive_file -

{{ fileName }}

-
- - file_upload -

Drag & drop or

- - -
-
-

+ +

{{ 'feature-flags.import-feature-flag.message.text' | translate }} Learn More

diff --git a/frontend/projects/upgrade/src/app/features/dashboard/feature-flags/modals/import-feature-flag-modal/import-feature-flag-modal.component.scss b/frontend/projects/upgrade/src/app/features/dashboard/feature-flags/modals/import-feature-flag-modal/import-feature-flag-modal.component.scss index 8ee757f43a..0a13fbb9a7 100644 --- a/frontend/projects/upgrade/src/app/features/dashboard/feature-flags/modals/import-feature-flag-modal/import-feature-flag-modal.component.scss +++ b/frontend/projects/upgrade/src/app/features/dashboard/feature-flags/modals/import-feature-flag-modal/import-feature-flag-modal.component.scss @@ -7,52 +7,14 @@ height: 100%; color: grey; - mat-icon { - height: 70px; - width: 70px; - font-size: 70px; - color: grey; + .full-width { + width: 100%; } } -.input-container { - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - border: 1px dashed grey; - border-radius: 4px; - height: 206px; - width: 592px; - position: relative; - - button { - font-size: 14px; - } -} - -.input-container-header { - position: absolute; - top: 5px; - right: 5px; - - mat-icon { - height: 24px; - width: 24px; - font-size: 24px; - } -} - -.input-container-content { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; -} - -p { +.import-message { + margin-top: 5px; color: grey; - font-size: 12px; } a { diff --git a/frontend/projects/upgrade/src/app/features/dashboard/feature-flags/modals/import-feature-flag-modal/import-feature-flag-modal.component.ts b/frontend/projects/upgrade/src/app/features/dashboard/feature-flags/modals/import-feature-flag-modal/import-feature-flag-modal.component.ts index e9cb49b01a..fced0d1298 100644 --- a/frontend/projects/upgrade/src/app/features/dashboard/feature-flags/modals/import-feature-flag-modal/import-feature-flag-modal.component.ts +++ b/frontend/projects/upgrade/src/app/features/dashboard/feature-flags/modals/import-feature-flag-modal/import-feature-flag-modal.component.ts @@ -2,25 +2,22 @@ import { ChangeDetectionStrategy, Component, ElementRef, Inject, OnInit, ViewChi import { CommonModalComponent } from '../../../../../shared-standalone-component-lib/components'; import { MAT_DIALOG_DATA, MatDialog, MatDialogRef } from '@angular/material/dialog'; import { CommonModalConfig } from '../../../../../shared-standalone-component-lib/components/common-modal/common-modal-config'; -import { FeatureFlagsService } from '../../../../../core/feature-flags/feature-flags.service'; import { BehaviorSubject } from 'rxjs'; import { CommonModule } from '@angular/common'; import { SharedModule } from '../../../../../shared/shared.module'; +import { CommonImportContainerComponent } from '../../../../../shared-standalone-component-lib/components/common-import-container/common-import-container.component'; @Component({ selector: 'app-import-feature-flag-modal', standalone: true, - imports: [CommonModalComponent, CommonModule, SharedModule], + imports: [CommonModalComponent, CommonModule, SharedModule, CommonImportContainerComponent], templateUrl: './import-feature-flag-modal.component.html', styleUrls: ['./import-feature-flag-modal.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush, }) export class ImportFeatureFlagModalComponent { - @ViewChild('fileInput') fileInput: ElementRef; isImportActionBtnDisabled = new BehaviorSubject(true); - isDragOver = new BehaviorSubject(false); - fileName = new BehaviorSubject(null); constructor( @Inject(MAT_DIALOG_DATA) @@ -29,46 +26,12 @@ export class ImportFeatureFlagModalComponent { public dialogRef: MatDialogRef ) {} - onDragOver(event: DragEvent) { - event.preventDefault(); - event.stopPropagation(); - this.isDragOver.next(true); - } - - onDragLeave(event: DragEvent) { - event.preventDefault(); - event.stopPropagation(); - this.isDragOver.next(false); - } - - onDrop(event: DragEvent) { - event.preventDefault(); - event.stopPropagation(); - this.isDragOver.next(false); - - const files = event.dataTransfer?.files; - if (files && files.length > 0) { - this.processFile(files[0]); - } - } - - onFileSelected(event: Event) { - const input = event.target as HTMLInputElement; - if (input.files && input.files.length > 0) { - this.processFile(input.files[0]); - } - } - - processFile(file: File) { - if (file.type === 'application/json') { - this.fileName.next(file.name); + handleFilesSelected(files: File[]) { + if(files.length>0) { this.isImportActionBtnDisabled.next(false); - this.handleFileInput(file); - } else { - alert('Please upload a valid JSON file.'); - this.fileName.next(null); - this.isImportActionBtnDisabled.next(true); } + console.log('Selected files:', files); + //Send files to validation endpoint to receive data for table } handleFileInput(file: File) { @@ -80,6 +43,10 @@ export class ImportFeatureFlagModalComponent { reader.readAsText(file); } + importFiles() { + console.log('Import feature flags'); + } + closeModal() { this.dialogRef.close(); } diff --git a/frontend/projects/upgrade/src/app/shared-standalone-component-lib/components/common-import-container/common-import-container.component.html b/frontend/projects/upgrade/src/app/shared-standalone-component-lib/components/common-import-container/common-import-container.component.html new file mode 100644 index 0000000000..c23e8623c5 --- /dev/null +++ b/frontend/projects/upgrade/src/app/shared-standalone-component-lib/components/common-import-container/common-import-container.component.html @@ -0,0 +1,14 @@ +
+ file_upload +

Drag & drop or

+ + +
\ No newline at end of file diff --git a/frontend/projects/upgrade/src/app/shared-standalone-component-lib/components/common-import-container/common-import-container.component.scss b/frontend/projects/upgrade/src/app/shared-standalone-component-lib/components/common-import-container/common-import-container.component.scss new file mode 100644 index 0000000000..744ffe9850 --- /dev/null +++ b/frontend/projects/upgrade/src/app/shared-standalone-component-lib/components/common-import-container/common-import-container.component.scss @@ -0,0 +1,29 @@ +.input-container { + /* Add your styles here */ + height: 210px; + width: 592px; + border: 2px dashed #ccc; + padding: 20px; + text-align: center; + border-radius: 10px; + transition: background-color 0.3s; + + &.drag-over { + background-color: #f0f0f0; + } + + .drag-text { + margin-bottom: 0.7rem; + } + + mat-icon { + height: 70px; + width: 70px; + font-size: 70px; + color: grey; + } + + button { + font-size: 14px; + } +} \ No newline at end of file diff --git a/frontend/projects/upgrade/src/app/shared-standalone-component-lib/components/common-import-container/common-import-container.component.ts b/frontend/projects/upgrade/src/app/shared-standalone-component-lib/components/common-import-container/common-import-container.component.ts new file mode 100644 index 0000000000..250566b484 --- /dev/null +++ b/frontend/projects/upgrade/src/app/shared-standalone-component-lib/components/common-import-container/common-import-container.component.ts @@ -0,0 +1,79 @@ +import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { SharedModule } from '../../../shared/shared.module'; +import { CommonModalComponent } from '../common-modal/common-modal.component'; +import { BehaviorSubject } from 'rxjs'; +import { FILE_TYPE } from 'upgrade_types'; + +/** + * A reusable component for drag-and-drop file import functionality. + * This component allows users to drag and drop files or select them via a file input. + * It supports specifying a file type and emits the selected files to the parent component. + * + * The component accepts the following inputs: + * - `fileType`: A string representing the accepted file type (e.g., '.json'). Only files with this extension can be selected or dropped. + * - `buttonLabel`: A string representing the label text of the button. Defaults to 'Upload File'. + * + * The component emits the following outputs: + * - `filesSelected`: An event that emits the selected files as an array of `File` objects. + * + * Example usage: + * + * ``` + * + * ``` + */ +@Component({ + selector: 'app-common-import-container', + standalone: true, + imports: [CommonModalComponent, CommonModule, SharedModule], + templateUrl: './common-import-container.component.html', + styleUrls: ['./common-import-container.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class CommonImportContainerComponent { + @Input() fileType!: FILE_TYPE; + @Input() buttonLabel!: string; + @Output() filesSelected = new EventEmitter(); + + isDragOver = new BehaviorSubject(false); + + onDragOver(event: DragEvent) { + this.handleDragState(event, true); + } + + onDragLeave(event: DragEvent) { + this.handleDragState(event, false); + } + + onDrop(event: DragEvent) { + this.handleDragState(event, false); + this.handleFileSelection(event.dataTransfer?.files); + } + + private handleDragState(event: DragEvent, isOver: boolean) { + event.preventDefault(); + event.stopPropagation(); + this.isDragOver.next(isOver); + } + + onFileSelected(event: Event) { + const input = event.target as HTMLInputElement; + this.handleFileSelection(input.files); + } + + private handleFileSelection(files: FileList | null) { + if (files && files.length > 0) { + const validFiles = Array.from(files).filter(file => file.name.endsWith(this.fileType)); + if (validFiles.length > 0) { + this.filesSelected.emit(validFiles); + } else { + console.error('Invalid file types...'); + } + } + } +} \ No newline at end of file diff --git a/frontend/projects/upgrade/src/app/shared-standalone-component-lib/components/common-modal/common-modal.component.spec.ts b/frontend/projects/upgrade/src/app/shared-standalone-component-lib/components/common-modal/common-modal.component.spec.ts deleted file mode 100644 index 7323254d65..0000000000 --- a/frontend/projects/upgrade/src/app/shared-standalone-component-lib/components/common-modal/common-modal.component.spec.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { CommonModalComponent } from './common-modal.component'; - -xdescribe('CommonDialogComponent', () => { - let component: CommonModalComponent; - let fixture: ComponentFixture; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - imports: [CommonModalComponent], - }).compileComponents(); - - fixture = TestBed.createComponent(CommonModalComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/frontend/projects/upgrade/src/app/shared-standalone-component-lib/components/common-modal/common-modal.component.ts b/frontend/projects/upgrade/src/app/shared-standalone-component-lib/components/common-modal/common-modal.component.ts index 94e8feaac3..1fded529d5 100644 --- a/frontend/projects/upgrade/src/app/shared-standalone-component-lib/components/common-modal/common-modal.component.ts +++ b/frontend/projects/upgrade/src/app/shared-standalone-component-lib/components/common-modal/common-modal.component.ts @@ -7,7 +7,6 @@ import { MatButtonModule } from '@angular/material/button'; import { MatDialogActions, MatDialogClose, MatDialogContent, MatDialogTitle } from '@angular/material/dialog'; import { CommonModule, NgTemplateOutlet } from '@angular/common'; import { MatIcon } from '@angular/material/icon'; -import { Observable } from 'rxjs'; @Component({ selector: 'app-common-dialog', diff --git a/frontend/projects/upgrade/src/app/shared/services/common-dialog.service.ts b/frontend/projects/upgrade/src/app/shared/services/common-dialog.service.ts index 51ea502f5f..9d3b1ea15c 100644 --- a/frontend/projects/upgrade/src/app/shared/services/common-dialog.service.ts +++ b/frontend/projects/upgrade/src/app/shared/services/common-dialog.service.ts @@ -114,7 +114,7 @@ export class DialogService { const config: MatDialogConfig = { data: commonModalConfig, width: '670px', - height: '450px', + height: '460px', autoFocus: 'input', disableClose: true, }; diff --git a/types/src/Experiment/enums.ts b/types/src/Experiment/enums.ts index 2e026925b1..d666c63f4c 100644 --- a/types/src/Experiment/enums.ts +++ b/types/src/Experiment/enums.ts @@ -270,3 +270,8 @@ export enum FEATURE_FLAG_PARTICIPANT_LIST_KEY { INCLUDE = 'featureFlagSegmentInclusion', EXCLUDE = 'featureFlagSegmentExclusion', } + +export enum FILE_TYPE { + JSON = '.json', + CSV = '.csv', +} diff --git a/types/src/index.ts b/types/src/index.ts index 56f95714d2..2d92cf032e 100644 --- a/types/src/index.ts +++ b/types/src/index.ts @@ -34,6 +34,7 @@ export { FLAG_SEARCH_KEY, FEATURE_FLAG_STATUS, STATUS_INDICATOR_CHIP_TYPE, + FILE_TYPE, } from './Experiment/enums'; export { IEnrollmentCompleteCondition,