feat(multi load): multiple csv files
This commit is contained in:
		| @@ -7,7 +7,7 @@ | |||||||
|     <button |     <button | ||||||
|       (click)="fileUploadInput.click()" |       (click)="fileUploadInput.click()" | ||||||
|       class="btn btn-primary btn-sm" |       class="btn btn-primary btn-sm" | ||||||
|       [disabled]="selectedFile !== null" |       [disabled]="selectedFile !== null || submittingCsv" | ||||||
|     > |     > | ||||||
|       Browse file |       Browse file | ||||||
|     </button> |     </button> | ||||||
| @@ -17,7 +17,7 @@ | |||||||
|       id="file-upload" |       id="file-upload" | ||||||
|       type="file" |       type="file" | ||||||
|       (change)="onFileChange($event)" |       (change)="onFileChange($event)" | ||||||
|       appFileSelect |       multiple | ||||||
|     /> |     /> | ||||||
|   </div> |   </div> | ||||||
|  |  | ||||||
| @@ -91,7 +91,7 @@ | |||||||
|     </div> |     </div> | ||||||
|  |  | ||||||
|     <div |     <div | ||||||
|       *ngIf="selectedFile === null" |       *ngIf="selectedFile === null && !submittingCsv" | ||||||
|       class="no-table-selected pointer-events-none" |       class="no-table-selected pointer-events-none" | ||||||
|     > |     > | ||||||
|       <clr-icon |       <clr-icon | ||||||
| @@ -104,8 +104,8 @@ | |||||||
|       </p> |       </p> | ||||||
|     </div> |     </div> | ||||||
|  |  | ||||||
|     <ng-container *ngIf="selectedFile !== null"> |     <ng-container *ngIf="selectedFile !== null || submittingCsv"> | ||||||
|       <ng-container *ngIf="!parsedDatasets.length"> |       <ng-container *ngIf="!parsedDatasets.length && selectedFile !== null"> | ||||||
|         <div class="d-flex clr-justify-content-center mt-15"> |         <div class="d-flex clr-justify-content-center mt-15"> | ||||||
|           <div class="dataset-input-wrapper"> |           <div class="dataset-input-wrapper"> | ||||||
|             <p cds-text="secondary regular" class="mb-20"> |             <p cds-text="secondary regular" class="mb-20"> | ||||||
| @@ -148,9 +148,9 @@ | |||||||
|         </div> |         </div> | ||||||
|       </ng-container> |       </ng-container> | ||||||
|  |  | ||||||
|       <ng-container *ngIf="parsedDatasets.length"> |       <ng-container *ngIf="parsedDatasets.length && !submittedDatasets.length"> | ||||||
|         <div |         <div | ||||||
|           *ngIf="!activeParsedDataset && !activeSubmittedDataset" |           *ngIf="!activeParsedDataset" | ||||||
|           class="no-table-selected pointer-events-none" |           class="no-table-selected pointer-events-none" | ||||||
|         > |         > | ||||||
|           <clr-icon |           <clr-icon | ||||||
| @@ -159,12 +159,7 @@ | |||||||
|             class="is-info icon-dc-fill" |             class="is-info icon-dc-fill" | ||||||
|           ></clr-icon> |           ></clr-icon> | ||||||
|           <p class="text-center color-gray mt-10" cds-text="section"> |           <p class="text-center color-gray mt-10" cds-text="section"> | ||||||
|             Please select a dataset on the left to |             Please select a dataset on the left to review the data | ||||||
|             {{ |  | ||||||
|               !submittedDatasets.length |  | ||||||
|                 ? 'review data' |  | ||||||
|                 : 'review submitted results' |  | ||||||
|             }} |  | ||||||
|           </p> |           </p> | ||||||
|         </div> |         </div> | ||||||
|  |  | ||||||
| @@ -238,10 +233,26 @@ | |||||||
|         </ng-container> |         </ng-container> | ||||||
|       </ng-container> |       </ng-container> | ||||||
|  |  | ||||||
|  |       <ng-container *ngIf="submittedDatasets.length"> | ||||||
|  |         <div | ||||||
|  |           *ngIf="!activeSubmittedDataset" | ||||||
|  |           class="no-table-selected pointer-events-none" | ||||||
|  |         > | ||||||
|  |         <clr-icon | ||||||
|  |           shape="warning-standard" | ||||||
|  |           size="40" | ||||||
|  |           class="is-info icon-dc-fill" | ||||||
|  |         ></clr-icon> | ||||||
|  |         <p class="text-center color-gray mt-10" cds-text="section"> | ||||||
|  |           Please select a dataset on the left to review the submit results | ||||||
|  |         </p> | ||||||
|  |       </div> | ||||||
|  |       </ng-container> | ||||||
|  |  | ||||||
|       <ng-container *ngIf="activeSubmittedDataset"> |       <ng-container *ngIf="activeSubmittedDataset"> | ||||||
|         <div class="d-flex clr-justify-content-between p-10"> |         <div class="d-flex clr-justify-content-between p-10"> | ||||||
|           <div> |           <div> | ||||||
|             <p cds-text="secondary regular" class="mb-10"> |             <p *ngIf="activeSubmittedDataset.parseResult" cds-text="secondary regular" class="mb-10"> | ||||||
|               Found in range: |               Found in range: | ||||||
|               <strong |               <strong | ||||||
|                 >"{{ |                 >"{{ | ||||||
| @@ -274,6 +285,7 @@ | |||||||
|  |  | ||||||
|           <div> |           <div> | ||||||
|             <button |             <button | ||||||
|  |             *ngIf="!submittingCsv && activeSubmittedDataset.error" | ||||||
|             (click)="reSubmitTable(activeSubmittedDataset)" |             (click)="reSubmitTable(activeSubmittedDataset)" | ||||||
|             class="btn btn-primary mt-10" |             class="btn btn-primary mt-10" | ||||||
|             [clrLoading]="submitLoading" |             [clrLoading]="submitLoading" | ||||||
| @@ -360,3 +372,18 @@ | |||||||
|     </button> |     </button> | ||||||
|   </div> |   </div> | ||||||
| </clr-modal> | </clr-modal> | ||||||
|  |  | ||||||
|  | <clr-modal [(clrModalOpen)]="csvSubmitting" [clrModalClosable]="false"> | ||||||
|  |   <h3 class="modal-title"> | ||||||
|  |     Submitting {{ csvFiles.length }} CSV {{ csvFiles.length === 1 ? 'file' : 'files'}} | ||||||
|  |   </h3> | ||||||
|  |   <div class="modal-body"> | ||||||
|  |     <div class="text-center"> | ||||||
|  |       <clr-spinner clrMedium></clr-spinner> | ||||||
|  |     </div> | ||||||
|  |  | ||||||
|  |     <p cds-text="caption_clean" class="mt-10 text-center"> | ||||||
|  |       This will take few moments | ||||||
|  |     </p> | ||||||
|  |   </div> | ||||||
|  | </clr-modal> | ||||||
| @@ -28,6 +28,7 @@ import { EditorsStageDataSASResponse } from '../models/sas/editors-stagedata.mod | |||||||
| import { CellChange, ChangeSource } from 'handsontable/common' | import { CellChange, ChangeSource } from 'handsontable/common' | ||||||
| import { baseAfterGetColHeader } from '../shared/utils/hot.utils' | import { baseAfterGetColHeader } from '../shared/utils/hot.utils' | ||||||
| import { ColumnSettings } from 'handsontable/settings' | import { ColumnSettings } from 'handsontable/settings' | ||||||
|  | import { UploadFile } from '@sasjs/adapter' | ||||||
|  |  | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-multi-dataset', |   selector: 'app-multi-dataset', | ||||||
| @@ -44,6 +45,9 @@ export class MultiDatasetComponent implements OnInit { | |||||||
|   public hotTableMaxRows = |   public hotTableMaxRows = | ||||||
|     this.licenceState.value.viewer_rows_allowed || Infinity |     this.licenceState.value.viewer_rows_allowed || Infinity | ||||||
|  |  | ||||||
|  |   public csvFiles: UploadFile[] = [] | ||||||
|  |   public csvSubmitting: boolean = false | ||||||
|  |  | ||||||
|   public selectedFile: File | null = null |   public selectedFile: File | null = null | ||||||
|   public parsedDatasets: ParsedDataset[] = [] |   public parsedDatasets: ParsedDataset[] = [] | ||||||
|   public submittedDatasets: SubmittedDatasetResult[] = [] |   public submittedDatasets: SubmittedDatasetResult[] = [] | ||||||
| @@ -67,10 +71,7 @@ export class MultiDatasetComponent implements OnInit { | |||||||
|   public submitReasonMessage: string = '' |   public submitReasonMessage: string = '' | ||||||
|  |  | ||||||
|   public hotUserDatasets: Handsontable.GridSettings = { |   public hotUserDatasets: Handsontable.GridSettings = { | ||||||
|     colHeaders: [ |     colHeaders: ['Library', 'Table'], | ||||||
|       'Library', |  | ||||||
|       'Table' |  | ||||||
|     ], |  | ||||||
|     data: [ |     data: [ | ||||||
|       ['', ''], |       ['', ''], | ||||||
|       ['', ''], |       ['', ''], | ||||||
| @@ -122,6 +123,7 @@ export class MultiDatasetComponent implements OnInit { | |||||||
|     private helperService: HelperService, |     private helperService: HelperService, | ||||||
|     private sasStoreService: SasStoreService, |     private sasStoreService: SasStoreService, | ||||||
|     private spreadsheetService: SpreadsheetService, |     private spreadsheetService: SpreadsheetService, | ||||||
|  |     private sasService: SasService, | ||||||
|     private cdr: ChangeDetectorRef |     private cdr: ChangeDetectorRef | ||||||
|   ) { |   ) { | ||||||
|     this.hotRegisterer = new HotTableRegisterer() |     this.hotRegisterer = new HotTableRegisterer() | ||||||
| @@ -151,12 +153,14 @@ export class MultiDatasetComponent implements OnInit { | |||||||
|     const libs: string[] = Object.keys(this.libsAndTables) |     const libs: string[] = Object.keys(this.libsAndTables) | ||||||
|  |  | ||||||
|     if (this.hotUserDatasets?.columns) { |     if (this.hotUserDatasets?.columns) { | ||||||
|       (this.hotUserDatasets.columns as ColumnSettings[])[0].source = libs; |       ;(this.hotUserDatasets.columns as ColumnSettings[])[0].source = libs | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   onFileChange(event: any) { |   onFileChange(event: any) { | ||||||
|     if (!event?.target?.files[0]) { |     const files = event?.target?.files || [] | ||||||
|  |  | ||||||
|  |     if (files.length < 1) { | ||||||
|       this.eventService.showAbortModal( |       this.eventService.showAbortModal( | ||||||
|         null, |         null, | ||||||
|         'No file found.', |         'No file found.', | ||||||
| @@ -166,11 +170,35 @@ export class MultiDatasetComponent implements OnInit { | |||||||
|       return |       return | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     const file = event.target.files[0] |     let matchedExtension = '' | ||||||
|     const fileTitle = file.name |  | ||||||
|     const fileExtension = fileTitle.split('.').pop() |  | ||||||
|  |  | ||||||
|     if (!['xlsx', 'xlsm', 'xlm'].includes(fileExtension)) { |     for (let file of files) { | ||||||
|  |       const fileExtension = file.name.split('.').pop() | ||||||
|  |  | ||||||
|  |       if (!matchedExtension) { | ||||||
|  |         matchedExtension = fileExtension | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       if (matchedExtension !== fileExtension) { | ||||||
|  |         this.eventService.showInfoModal( | ||||||
|  |           'Mixed extensions error', | ||||||
|  |           'Please select files with same extension.' | ||||||
|  |         ) | ||||||
|  |         return | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       matchedExtension = fileExtension | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (['xlsx', 'xlsm', 'xlm'].includes(matchedExtension)) { | ||||||
|  |       // For EXCEL if multiple files, we only take one (the first one) | ||||||
|  |       this.selectedFile = event.target.files[0] | ||||||
|  |  | ||||||
|  |       this.initUserInputHot() | ||||||
|  |       this.onAutoDetectColumns() | ||||||
|  |     } else if (matchedExtension === 'csv') { | ||||||
|  |       this.onMultiCsvFiles(event.target.files) | ||||||
|  |     } else { | ||||||
|       this.eventService.showAbortModal( |       this.eventService.showAbortModal( | ||||||
|         null, |         null, | ||||||
|         'Only excel extensions are allowed. (xlsx)', |         'Only excel extensions are allowed. (xlsx)', | ||||||
| @@ -180,11 +208,37 @@ export class MultiDatasetComponent implements OnInit { | |||||||
|       return |       return | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     this.selectedFile = event.target.files[0] |  | ||||||
|     event.target.value = '' // Reset the upload input |     event.target.value = '' // Reset the upload input | ||||||
|  |   } | ||||||
|  |  | ||||||
|     this.initUserInputHot() |   async onMultiCsvFiles(files: File[]) { | ||||||
|     this.onAutoDetectColumns() |     for (let file of files) { | ||||||
|  |       const fileNameNoExtension = this.parseDatasetFromCsvName(file.name) | ||||||
|  |  | ||||||
|  |       if ( | ||||||
|  |         this.isValidDatasetFormat(fileNameNoExtension) && | ||||||
|  |         this.isValidDatasetReference(fileNameNoExtension) | ||||||
|  |       ) { | ||||||
|  |         this.csvFiles.push({ | ||||||
|  |           file: file, | ||||||
|  |           fileName: file.name | ||||||
|  |         }) | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (!this.csvFiles.length) { | ||||||
|  |       this.eventService.showInfoModal( | ||||||
|  |         'CSV Upload', | ||||||
|  |         'None of the attached CSV file names matched an actual dataset.' | ||||||
|  |       ) | ||||||
|  |       return | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     this.csvSubmitting = true | ||||||
|  |  | ||||||
|  |     await this.submitCsvFiles() | ||||||
|  |  | ||||||
|  |     this.csvSubmitting = false | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   onDiscardFile() { |   onDiscardFile() { | ||||||
| @@ -276,7 +330,10 @@ export class MultiDatasetComponent implements OnInit { | |||||||
|     if (this.tablesToSubmit.length) { |     if (this.tablesToSubmit.length) { | ||||||
|       this.showSubmitReasonModal = true |       this.showSubmitReasonModal = true | ||||||
|     } else { |     } else { | ||||||
|       this.eventService.showInfoModal('No tables to submit', 'Please include at least one table to proceed.') |       this.eventService.showInfoModal( | ||||||
|  |         'No tables to submit', | ||||||
|  |         'Please include at least one table to proceed.' | ||||||
|  |       ) | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -307,9 +364,13 @@ export class MultiDatasetComponent implements OnInit { | |||||||
|  |  | ||||||
|   initUserInputHot() { |   initUserInputHot() { | ||||||
|     setTimeout(() => { |     setTimeout(() => { | ||||||
|       this.hotInstanceUserDataset = this.hotRegisterer.getInstance('hotInstanceUserDataset') |       this.hotInstanceUserDataset = this.hotRegisterer.getInstance( | ||||||
|  |         'hotInstanceUserDataset' | ||||||
|  |       ) | ||||||
|  |  | ||||||
|       this.hotInstanceUserDataset.addHook('beforeChange', (changes: (CellChange | null)[], source: ChangeSource) => { |       this.hotInstanceUserDataset.addHook( | ||||||
|  |         'beforeChange', | ||||||
|  |         (changes: (CellChange | null)[], source: ChangeSource) => { | ||||||
|           if (changes) { |           if (changes) { | ||||||
|             for (let change of changes) { |             for (let change of changes) { | ||||||
|               if (change && change[3]) { |               if (change && change[3]) { | ||||||
| @@ -317,9 +378,12 @@ export class MultiDatasetComponent implements OnInit { | |||||||
|               } |               } | ||||||
|             } |             } | ||||||
|           } |           } | ||||||
|       }) |         } | ||||||
|  |       ) | ||||||
|  |  | ||||||
|       this.hotInstanceUserDataset.addHook('afterChange', async (changes: CellChange[] | null, source: ChangeSource) => { |       this.hotInstanceUserDataset.addHook( | ||||||
|  |         'afterChange', | ||||||
|  |         async (changes: CellChange[] | null, source: ChangeSource) => { | ||||||
|           if (changes) { |           if (changes) { | ||||||
|             if (source === 'edit') { |             if (source === 'edit') { | ||||||
|               await this.onUserInputDatasetsChange() |               await this.onUserInputDatasetsChange() | ||||||
| @@ -335,15 +399,24 @@ export class MultiDatasetComponent implements OnInit { | |||||||
|  |  | ||||||
|             this.hotInstanceUserDataset.render() |             this.hotInstanceUserDataset.render() | ||||||
|           } |           } | ||||||
|       }) |         } | ||||||
|  |       ) | ||||||
|  |  | ||||||
|       this.hotInstanceUserDataset.addHook('afterRemoveRow', async (index: number, amount: number, physicalRows: number[], source?: Handsontable.ChangeSource | undefined) => { |       this.hotInstanceUserDataset.addHook( | ||||||
|  |         'afterRemoveRow', | ||||||
|  |         async ( | ||||||
|  |           index: number, | ||||||
|  |           amount: number, | ||||||
|  |           physicalRows: number[], | ||||||
|  |           source?: Handsontable.ChangeSource | undefined | ||||||
|  |         ) => { | ||||||
|           await this.onUserInputDatasetsChange() |           await this.onUserInputDatasetsChange() | ||||||
|  |  | ||||||
|           for (let row of physicalRows) { |           for (let row of physicalRows) { | ||||||
|             this.markUnmatchedRows(row) |             this.markUnmatchedRows(row) | ||||||
|           } |           } | ||||||
|       }) |         } | ||||||
|  |       ) | ||||||
|     }) |     }) | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -367,17 +440,32 @@ export class MultiDatasetComponent implements OnInit { | |||||||
|  |  | ||||||
|     if (dataAtRow && dataAtRow[0] && dataAtRow[1]) { |     if (dataAtRow && dataAtRow[0] && dataAtRow[1]) { | ||||||
|       if (!this.matchedDatasets.includes(dataset)) { |       if (!this.matchedDatasets.includes(dataset)) { | ||||||
|         cellMetaAtRow.forEach(cellMeta => { |         cellMetaAtRow.forEach((cellMeta) => { | ||||||
|           this.hotInstanceUserDataset.setCellMeta(row, cellMeta.col, 'className', 'not-matched') |           this.hotInstanceUserDataset.setCellMeta( | ||||||
|  |             row, | ||||||
|  |             cellMeta.col, | ||||||
|  |             'className', | ||||||
|  |             'not-matched' | ||||||
|  |           ) | ||||||
|         }) |         }) | ||||||
|       } else { |       } else { | ||||||
|         cellMetaAtRow.forEach(cellMeta => { |         cellMetaAtRow.forEach((cellMeta) => { | ||||||
|           this.hotInstanceUserDataset.setCellMeta(row, cellMeta.col, 'className', '') |           this.hotInstanceUserDataset.setCellMeta( | ||||||
|  |             row, | ||||||
|  |             cellMeta.col, | ||||||
|  |             'className', | ||||||
|  |             '' | ||||||
|  |           ) | ||||||
|         }) |         }) | ||||||
|       } |       } | ||||||
|     } else { |     } else { | ||||||
|       cellMetaAtRow.forEach(cellMeta => { |       cellMetaAtRow.forEach((cellMeta) => { | ||||||
|         this.hotInstanceUserDataset.setCellMeta(row, cellMeta.col, 'className', '') |         this.hotInstanceUserDataset.setCellMeta( | ||||||
|  |           row, | ||||||
|  |           cellMeta.col, | ||||||
|  |           'className', | ||||||
|  |           '' | ||||||
|  |         ) | ||||||
|       }) |       }) | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| @@ -444,11 +532,8 @@ export class MultiDatasetComponent implements OnInit { | |||||||
|     // Set matched datasets to textarea, dataset per row |     // Set matched datasets to textarea, dataset per row | ||||||
|     this.userInputDatasets = this.matchedDatasets.join('\n') |     this.userInputDatasets = this.matchedDatasets.join('\n') | ||||||
|  |  | ||||||
|     const hotReadyData = this.matchedDatasets.map(matchedDs => { |     const hotReadyData = this.matchedDatasets.map((matchedDs) => { | ||||||
|       return [ |       return [matchedDs.split('.')[0], matchedDs.split('.')[1]] | ||||||
|         matchedDs.split('.')[0], |  | ||||||
|         matchedDs.split('.')[1] |  | ||||||
|       ] |  | ||||||
|     }) |     }) | ||||||
|  |  | ||||||
|     // Add empty rows to fill initial number of rows if data has less rows |     // Add empty rows to fill initial number of rows if data has less rows | ||||||
| @@ -493,7 +578,9 @@ export class MultiDatasetComponent implements OnInit { | |||||||
|   public get notFoundDatasets(): string[] { |   public get notFoundDatasets(): string[] { | ||||||
|     const userDatasets = this.getDatasetsFromHot() |     const userDatasets = this.getDatasetsFromHot() | ||||||
|  |  | ||||||
|     return userDatasets.filter(userDs => !this.matchedDatasets.includes(userDs.trim())).filter(userDs => userDs.length) |     return userDatasets | ||||||
|  |       .filter((userDs) => !this.matchedDatasets.includes(userDs.trim())) | ||||||
|  |       .filter((userDs) => userDs.length) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   public get isHotHidden(): boolean { |   public get isHotHidden(): boolean { | ||||||
| @@ -509,16 +596,60 @@ export class MultiDatasetComponent implements OnInit { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   public get tablesToSubmit(): ParsedDataset[] { |   public get tablesToSubmit(): ParsedDataset[] { | ||||||
|     return this.parsedDatasets.filter(dataset => dataset.datasource && dataset.parseResult && dataset.includeInSubmission) |     return this.parsedDatasets.filter( | ||||||
|  |       (dataset) => | ||||||
|  |         dataset.datasource && dataset.parseResult && dataset.includeInSubmission | ||||||
|  |     ) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   public downloadFile( |   public get submittingCsv(): boolean { | ||||||
|     response: any |     return this.csvFiles.length > 0 | ||||||
|   ) { |   } | ||||||
|  |  | ||||||
|  |   public downloadFile(response: any) { | ||||||
|     const filename = `stagedata-${this.activeSubmittedDataset?.libds}-log` |     const filename = `stagedata-${this.activeSubmittedDataset?.libds}-log` | ||||||
|     this.helperService.downloadTextFile(filename, JSON.stringify(response)) |     this.helperService.downloadTextFile(filename, JSON.stringify(response)) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Submits attached CSVs which are matched with existing datasets | ||||||
|  |    */ | ||||||
|  |   async submitCsvFiles() { | ||||||
|  |     let requestsResults: SubmittedDatasetResult[] = [] | ||||||
|  |  | ||||||
|  |     for (let file of this.csvFiles) { | ||||||
|  |       const libds = this.parseDatasetFromCsvName(file.fileName) | ||||||
|  |  | ||||||
|  |       let error | ||||||
|  |       let success | ||||||
|  |  | ||||||
|  |       await this.sasService | ||||||
|  |       .uploadFile('services/editors/loadfile', [file], { table: libds }) | ||||||
|  |       .then( | ||||||
|  |         (res: any) => { | ||||||
|  |           if (typeof res.sasjsAbort !== 'undefined') { | ||||||
|  |             error = res.sasjsAbort | ||||||
|  |           } else { | ||||||
|  |             success = res | ||||||
|  |           } | ||||||
|  |         }, | ||||||
|  |         (err: any) => { | ||||||
|  |           console.error('err', err) | ||||||
|  |  | ||||||
|  |           error = err | ||||||
|  |         } | ||||||
|  |       ) | ||||||
|  |  | ||||||
|  |       requestsResults.push({ | ||||||
|  |         success, | ||||||
|  |         error, | ||||||
|  |         libds: libds | ||||||
|  |       }) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     this.submittedDatasets = requestsResults | ||||||
|  |   } | ||||||
|  |  | ||||||
|   /** |   /** | ||||||
|    * Fetches the table for given datasets params LIBRARY.TABLE |    * Fetches the table for given datasets params LIBRARY.TABLE | ||||||
|    */ |    */ | ||||||
| @@ -557,7 +688,9 @@ export class MultiDatasetComponent implements OnInit { | |||||||
|  |  | ||||||
|     this.submitLoading = true |     this.submitLoading = true | ||||||
|  |  | ||||||
|     let requestsResults: SubmittedDatasetResult[] = explicitDatasets ? this.submittedDatasets : [] |     let requestsResults: SubmittedDatasetResult[] = explicitDatasets | ||||||
|  |       ? this.submittedDatasets | ||||||
|  |       : [] | ||||||
|  |  | ||||||
|     for (let table of this.parsedDatasets) { |     for (let table of this.parsedDatasets) { | ||||||
|       // Skip the table if no data inside |       // Skip the table if no data inside | ||||||
| @@ -629,7 +762,9 @@ export class MultiDatasetComponent implements OnInit { | |||||||
|         // If explicit datasets are set don't just push to th array |         // If explicit datasets are set don't just push to th array | ||||||
|         // instead replace if result already exist from before (this might be re-submit) |         // instead replace if result already exist from before (this might be re-submit) | ||||||
|         if (explicitDatasets) { |         if (explicitDatasets) { | ||||||
|           const existingResultIndex = requestsResults.findIndex(result => result.libds === table.libds) |           const existingResultIndex = requestsResults.findIndex( | ||||||
|  |             (result) => result.libds === table.libds | ||||||
|  |           ) | ||||||
|  |  | ||||||
|           if (existingResultIndex > -1) { |           if (existingResultIndex > -1) { | ||||||
|             requestsResults[existingResultIndex] = requestResult |             requestsResults[existingResultIndex] = requestResult | ||||||
| @@ -653,10 +788,18 @@ export class MultiDatasetComponent implements OnInit { | |||||||
|     await this.submitTables([activeSubmittedDataset.libds]) |     await this.submitTables([activeSubmittedDataset.libds]) | ||||||
|  |  | ||||||
|     // Activate new resubmitted table |     // Activate new resubmitted table | ||||||
|     const newSubmittedDataset = this.submittedDatasets.find(sd => sd.libds === activeSubmittedDataset.libds) |     const newSubmittedDataset = this.submittedDatasets.find( | ||||||
|  |       (sd) => sd.libds === activeSubmittedDataset.libds | ||||||
|  |     ) | ||||||
|     if (newSubmittedDataset) newSubmittedDataset.active = true |     if (newSubmittedDataset) newSubmittedDataset.active = true | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   private parseDatasetFromCsvName(fileName: string) { | ||||||
|  |     const fileNameArr = fileName.split('.') | ||||||
|  |     fileNameArr.pop() | ||||||
|  |     return fileNameArr.join('.') | ||||||
|  |   } | ||||||
|  |  | ||||||
|   /** |   /** | ||||||
|    * |    * | ||||||
|    * @returns list of strings containing datasets in the HOT user input |    * @returns list of strings containing datasets in the HOT user input | ||||||
| @@ -667,7 +810,9 @@ export class MultiDatasetComponent implements OnInit { | |||||||
|  |  | ||||||
|     const hotData = this.hotInstanceUserDataset.getData() |     const hotData = this.hotInstanceUserDataset.getData() | ||||||
|  |  | ||||||
|     return hotData.filter(row => row[0]?.length && row[1]?.length).map(row => row ? `${row[0]}.${row[1]}` : '') |     return hotData | ||||||
|  |       .filter((row) => row[0]?.length && row[1]?.length) | ||||||
|  |       .map((row) => (row ? `${row[0]}.${row[1]}` : '')) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   private parseExcelSheetNames(): Promise<string[]> { |   private parseExcelSheetNames(): Promise<string[]> { | ||||||
| @@ -718,9 +863,9 @@ export class MultiDatasetComponent implements OnInit { | |||||||
|    * |    * | ||||||
|    *  example: LIB123.TABLE_123 |    *  example: LIB123.TABLE_123 | ||||||
|    */ |    */ | ||||||
|   private isValidDatasetFormat(sheetName: string) { |   private isValidDatasetFormat(name: string) { | ||||||
|     const regex = /^\w{1,8}\.\w{1,32}$/gim |     const regex = /^\w{1,8}\.\w{1,32}$/gim | ||||||
|     const correctFormat = regex.test(sheetName) |     const correctFormat = regex.test(name) | ||||||
|  |  | ||||||
|     return correctFormat |     return correctFormat | ||||||
|   } |   } | ||||||
| @@ -867,6 +1012,6 @@ export interface SubmittedDatasetResult { | |||||||
|   libds: string |   libds: string | ||||||
|   success: EditorsStageDataSASResponse | undefined |   success: EditorsStageDataSASResponse | undefined | ||||||
|   error: any |   error: any | ||||||
|   parseResult: ParseResult |   parseResult?: ParseResult | ||||||
|   active?: boolean |   active?: boolean | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user