diff --git a/package.json b/package.json index 87031c68..7cd52141 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "vscode-couchbase", "displayName": "Couchbase", "description": "", - "version": "1.0.0", + "version": "1.1.0", "engines": { "vscode": "^1.63.1" }, diff --git a/src/commands/tools/dataImport.ts b/src/commands/tools/dataImport.ts index 4298e0a1..1f569058 100644 --- a/src/commands/tools/dataImport.ts +++ b/src/commands/tools/dataImport.ts @@ -38,6 +38,11 @@ export class DataImport { readonly MONO_INCR_FLAG = "#MONO_INCR#"; readonly WORDS_WITH_PERCENT_SYMBOLS_REGEX = "%(\\w+)%"; + protected readonly possibleScopeFields: string[] = ["cbms", "scope", "cbs", "type", "category"]; + protected readonly possibleCollectionFields: string[] = ["cbmc", "collection", "cbc", "subtype", "subcategory"]; + protected readonly possibleKeyFields: string[] = ["cbmid", "id", "uuid", "name", "cbmk", "key", "cbk"]; + + protected fileFormat: string = ""; constructor() {} @@ -330,6 +335,44 @@ export class DataImport { return previewContent.join("\n"); } + // Functions to get default values for dynamic scopesAndCollections + protected async getSampleElementContentSplit(datasetFieldText: string): Promise { + let sampleElementContentSplit: string[] = []; + + if (this.JSON_FILE_FORMAT === this.fileFormat) { + const sampleElement = await this.sampleElementFromJsonArrayFile(datasetFieldText); + if (sampleElement) { + sampleElementContentSplit = sampleElement.split(','); + } else { + throw new Error("Failed to retrieve sample JSON element."); + } + } else if (this.CSV_FILE_FORMAT === this.fileFormat) { + const sampleElement = await this.sampleElementFromCsvFile(datasetFieldText, 1); + if(sampleElement){ + sampleElementContentSplit = sampleElement; + } + } else { + throw new Error(`Unsupported file format: ${this.fileFormat}`); + } + + logger.debug("sampleElementContentSplit: " + sampleElementContentSplit.join(', ')); + + return sampleElementContentSplit; + } + + protected async matchElements(jsonFieldsArr: string[], possibleFieldsArr: string[]): Promise{ + for(let x of jsonFieldsArr){ + for(let y of possibleFieldsArr){ + if(x.match(y)){ + return y; + } + } + } + return ""; + } + + + // Functions to detect validity of scopes and collections async sampleElementFromJsonArrayFile( @@ -574,8 +617,6 @@ export class DataImport { logger.error("format not detected"); errors.push("Please enter valid json file format only"); } - - // Check if given JSON File is correct } return errors; }; @@ -877,12 +918,16 @@ export class DataImport { ); if (validationError === "") { // NO Validation Error on Page 1, We can shift to next page + const elementSplit = await this.getSampleElementContentSplit(formData.dataset); + const defaultKeysValue = await this.matchElements(elementSplit, this.possibleKeyFields); + currentPanel.webview.html = getLoader("Data Import"); currentPanel.webview.html = getKeysAndAdvancedSettings( formData, - keysAndAdvancedSettingsData + keysAndAdvancedSettingsData, + defaultKeysValue ); } else { currentPanel.webview.postMessage({ @@ -922,13 +967,33 @@ export class DataImport { vscode.window .showOpenDialog(options) - .then((fileUri) => { + .then(async (fileUri) => { if (fileUri && fileUri[0]) { + const dataset = fileUri[0].fsPath; + + // understand first few documents, get fields and update default values + // Firstly validate the dataset + const errors = await this.validateDataset(dataset); + if(errors.length === 0){ + const elementSplit = await this.getSampleElementContentSplit(dataset); + const defaultScopeValue = await this.matchElements(elementSplit, this.possibleScopeFields); + const defaultCollectionValue = await this.matchElements(elementSplit, this.possibleCollectionFields); + currentPanel.webview.postMessage({ + command: "vscode-couchbase.tools.dataImport.defaultScopeAndCollectionDynamicField", + defaultScopeValue: `%${defaultScopeValue}%`, + defaultCollectionValue: `%${defaultCollectionValue}%` + }); + } else { + logger.error("error while reading dataset: \n " + errors.join("\n")); + } + currentPanel.webview.postMessage({ command: "vscode-couchbase.tools.dataImport.datasetFile", - dataset: fileUri[0].fsPath, + dataset: dataset, }); + + } }); break; diff --git a/src/tools/CBExport.ts b/src/tools/CBExport.ts index cffe19a0..43d76f79 100644 --- a/src/tools/CBExport.ts +++ b/src/tools/CBExport.ts @@ -72,7 +72,7 @@ export class CBExport { cmd.push("-u"); cmd.push(connection.username); cmd.push("-p"); - cmd.push(password); + cmd.push('"' + password + '"'); cmd.push("-b"); cmd.push(bucket); diff --git a/src/tools/CBImport.ts b/src/tools/CBImport.ts index 4295178f..5e7223fa 100644 --- a/src/tools/CBImport.ts +++ b/src/tools/CBImport.ts @@ -76,7 +76,7 @@ export class CBImport { cmd.push("-u"); cmd.push(connection.username); cmd.push("-p"); - cmd.push(password); + cmd.push('"' + password + '"'); cmd.push("-b"); cmd.push(importData.bucket); diff --git a/src/webViews/tools/dataImport/getDatasetAndCollection.webview.ts b/src/webViews/tools/dataImport/getDatasetAndCollection.webview.ts index 2ee6221f..cf6b123f 100644 --- a/src/webViews/tools/dataImport/getDatasetAndCollection.webview.ts +++ b/src/webViews/tools/dataImport/getDatasetAndCollection.webview.ts @@ -385,6 +385,12 @@ export const getDatasetAndCollection = async ( const error = message.error; document.getElementById("validation-error").innerHTML = message.error; break; + case "vscode-couchbase.tools.dataImport.defaultScopeAndCollectionDynamicField": + const defaultScopeValue = message.defaultScopeValue; + const defaultCollectionValue = message.defaultCollectionValue; + document.getElementById("scopesDynamicField").value = defaultScopeValue; + document.getElementById("collectionsDynamicField").value = defaultCollectionValue; + break; } }); diff --git a/src/webViews/tools/dataImport/getKeysAndAdvancedSettings.webview.ts b/src/webViews/tools/dataImport/getKeysAndAdvancedSettings.webview.ts index 3d549b9b..c226d865 100644 --- a/src/webViews/tools/dataImport/getKeysAndAdvancedSettings.webview.ts +++ b/src/webViews/tools/dataImport/getKeysAndAdvancedSettings.webview.ts @@ -1,6 +1,7 @@ export const getKeysAndAdvancedSettings = ( datasetAndCollectionData: any, - prefilledData: any + prefilledData: any, + defaultKeysValue?: string ): string => { return /*html*/ ` @@ -217,7 +218,7 @@ export const getKeysAndAdvancedSettings = ( - +
@@ -232,7 +233,7 @@ export const getKeysAndAdvancedSettings = ( - +
Note: If random UUID or #UUID# tag is used, the UUID values in the preview area might not match the actual UUID values generated during import.
@@ -332,6 +333,7 @@ export const getKeysAndAdvancedSettings = ( window.onload = async function() { let prefilledData = ${JSON.stringify(prefilledData)}; + let defaultKeysValue = "${defaultKeysValue}"; if(prefilledData){ // If prefilled data is undefined, go with defaults only setInitialValue('keyOptions', prefilledData.keyOptions); setInitialValue('keyFieldName', prefilledData.keyFieldName); @@ -345,6 +347,9 @@ export const getKeysAndAdvancedSettings = ( if(prefilledData.verboseLog){ document.getElementById('verboseLog').checked = true; } + } else if(defaultKeysValue && defaultKeysValue.length > 0){ // Only check for default values if there is not any prefilled Data + document.getElementById("keyFieldName").value = defaultKeysValue; + document.getElementById("customExpression").value = "%" + defaultKeysValue + "%"; } // After setting prefilled data, set it to undefined so that it doesn't interfere @@ -442,7 +447,7 @@ export const getKeysAndAdvancedSettings = ( switch (message.command) { case "vscode-couchbase.tools.dataImport.sendKeyPreview": let preview = message.preview; - if(preview === ""){ + if(preview.trim() === ""){ preview = "No Preview to Show!"; } document.getElementById("keyPreviewTextArea").innerHTML = preview;