Skip to content

Commit

Permalink
added form validation
Browse files Browse the repository at this point in the history
  • Loading branch information
lokesh-couchbase committed Oct 11, 2023
1 parent f170642 commit 42cf402
Show file tree
Hide file tree
Showing 3 changed files with 183 additions and 102 deletions.
264 changes: 170 additions & 94 deletions src/pages/Tools/DataExport/dataExport.ts
Original file line number Diff line number Diff line change
@@ -1,117 +1,193 @@
import { CBExport } from "../../../tools/CBExport";
import { CBTools, Type as CBToolsType } from "../../../util/DependencyDownloaderUtils/CBTool";
import * as vscode from 'vscode';
import {
CBTools,
Type as CBToolsType,
} from "../../../util/DependencyDownloaderUtils/CBTool";
import * as vscode from "vscode";
import { getActiveConnection } from "../../../util/connections";
import { Memory } from "../../../util/util";
import { Constants } from "../../../util/constants";
import { logger } from "../../../logger/logger";
import * as path from 'path';
import * as path from "path";
import { getLoader } from "../../../webViews/loader.webview";
import { dataExportWebview } from "../../../webViews/tools/dataExport.webview";
import { IConnection } from "../../../types/IConnection";

const getScopes = async (bucketId: string, connection: IConnection) => {
let scopes = await connection.cluster
?.bucket(bucketId)
.collections()
.getAllScopes();
return scopes;
};

const validateFormData = (formData: any): string => {
const errors = [];

if (!formData.bucket) {
errors.push("Please select a bucket");
} else {
if (formData.scopes.length === 0) {
errors.push("Select one or more scopes");
} else {
if (
!formData.scopes.includes("Select All") &&
formData.collections.length === 0
) {
errors.push("Select one or more collections");
}
}
}

if (!formData.documentsKeyField.trim()) {
errors.push("Please specify the document's key field name");
}

if (!formData.scopeFieldName.trim()) {
errors.push("Please specify the scope field name");
}

if (!formData.collectionFieldName.trim()) {
errors.push("Please specify the collection field name");
}

if (!formData.fileDestination.trim()) {
errors.push("Please inform the file destination folder");
}

const getScopes = async(bucketId: string, connection: IConnection) => {
let scopes = await connection.cluster?.bucket(bucketId).collections().getAllScopes();
return scopes;
if (errors.length > 0) {
return errors.join("<br>");
}

return "";
};

export interface IDataExportWebviewState {
webviewPanel: vscode.WebviewPanel
webviewPanel: vscode.WebviewPanel;
}

export const dataExport = async () => {
const connection = getActiveConnection();
if (!connection) {
return;
}
if (!CBTools.getTool(CBToolsType.CB_EXPORT).isAvailable()) {
vscode.window.showErrorMessage("CB Export is still loading, Please try again later");
return;
}

const dataExportWebviewDetails = Memory.state.get<IDataExportWebviewState>(Constants.DATA_EXPORT_WEBVIEW);
if (dataExportWebviewDetails) {
// data export webview already exists, Closing existing and creating new
try {
dataExportWebviewDetails.webviewPanel.dispose();
} catch (e) {
logger.error("Error while disposing data export webview: " + e);
}
Memory.state.update(Constants.DATA_EXPORT_WEBVIEW, null);
}

const currentPanel = vscode.window.createWebviewPanel(
"dataExport",
"Data Export",
vscode.ViewColumn.One,
{
enableScripts: true,
enableForms: true,
}
);
Memory.state.update(Constants.DATA_EXPORT_WEBVIEW, {
webviewPanel: currentPanel
});
currentPanel.iconPath = vscode.Uri.file(
path.join(__filename, "..", "..", "images", "cb-logo-icon.svg")
const connection = getActiveConnection();
if (!connection) {
return;
}
if (!CBTools.getTool(CBToolsType.CB_EXPORT).isAvailable()) {
vscode.window.showErrorMessage(
"CB Export is still loading, Please try again later"
);
currentPanel.webview.html = getLoader("Data Export");
return;
}

// Get all buckets
let buckets = await connection.cluster?.buckets().getAllBuckets();
if(buckets === undefined) {
vscode.window.showErrorMessage("Buckets not found");
return;
}
let bucketNameArr: string[] = [];
for(let bucket of buckets){
bucketNameArr.push(bucket.name);
}

const dataExportWebviewDetails = Memory.state.get<IDataExportWebviewState>(
Constants.DATA_EXPORT_WEBVIEW
);
if (dataExportWebviewDetails) {
// data export webview already exists, Closing existing and creating new
try {
currentPanel.webview.html = await dataExportWebview(bucketNameArr);
currentPanel.webview.onDidReceiveMessage(async (message)=>{
switch(message.command) {
// ADD cases here :)
case 'vscode-couchbase.tools.dataExport.runExport':
let formData = message.data;
CBExport.export(formData.bucket, formData.scopes, formData.collections, formData.fileDestination, formData.documentsKeyField, formData.scopeFieldName, formData.collectionFieldName, formData.format, '4', false);
break;
case 'vscode-couchbase.tools.dataExport.getScopes':
let scopes = await getScopes(message.bucketId, connection);
if(scopes === undefined){
vscode.window.showErrorMessage("Scopes are undefined");
break;
}

currentPanel.webview.postMessage({command: 'vscode-couchbase.tools.dataExport.scopesInfo', scopes: scopes});
break;
case 'vscode-couchbase.tools.dataExport.getFolder':
const options: vscode.OpenDialogOptions = {
canSelectMany: false,
openLabel: 'Choose Destination Folder',
canSelectFiles: false,
canSelectFolders: true
};

vscode.window.showOpenDialog(options).then(fileUri => {
if (fileUri && fileUri[0]) {
currentPanel.webview.postMessage({command: 'vscode-couchbase.tools.dataExport.folderInfo', folder: fileUri[0].fsPath});
}
});
break;
}
});
dataExportWebviewDetails.webviewPanel.dispose();
} catch (e) {
logger.error("Error while disposing data export webview: " + e);
}
Memory.state.update(Constants.DATA_EXPORT_WEBVIEW, null);
}

} catch (err) {
logger.error(`Failed to open data export webview`);
logger.debug(err);
vscode.window.showErrorMessage("Failed to open data export webview: "+ err);
const currentPanel = vscode.window.createWebviewPanel(
"dataExport",
"Data Export",
vscode.ViewColumn.One,
{
enableScripts: true,
enableForms: true,
}
);
Memory.state.update(Constants.DATA_EXPORT_WEBVIEW, {
webviewPanel: currentPanel,
});
currentPanel.iconPath = vscode.Uri.file(
path.join(__filename, "..", "..", "images", "cb-logo-icon.svg")
);
currentPanel.webview.html = getLoader("Data Export");

// Get all buckets
let buckets = await connection.cluster?.buckets().getAllBuckets();
if (buckets === undefined) {
vscode.window.showErrorMessage("Buckets not found");
return;
}
let bucketNameArr: string[] = [];
for (let bucket of buckets) {
bucketNameArr.push(bucket.name);
}

try {
currentPanel.webview.html = await dataExportWebview(bucketNameArr);
currentPanel.webview.onDidReceiveMessage(async (message) => {
switch (message.command) {
// ADD cases here :)
case "vscode-couchbase.tools.dataExport.runExport":
let formData = message.data;
let validationError = validateFormData(formData);
if (validationError === "") {
// There is no error
CBExport.export(
formData.bucket,
formData.scopes,
formData.collections,
formData.fileDestination,
formData.documentsKeyField,
formData.scopeFieldName,
formData.collectionFieldName,
formData.format,
"4",
false
);
} else {
currentPanel.webview.postMessage({
command: "vscode-couchbase.tools.dataExport.formValidationError",
error: validationError,
});
}
break;
case "vscode-couchbase.tools.dataExport.getScopes":
let scopes = await getScopes(message.bucketId, connection);
if (scopes === undefined) {
vscode.window.showErrorMessage("Scopes are undefined");
break;
}

currentPanel.onDidDispose(() => {
Memory.state.update(Constants.DATA_EXPORT_WEBVIEW, null);
});
};
currentPanel.webview.postMessage({
command: "vscode-couchbase.tools.dataExport.scopesInfo",
scopes: scopes,
});
break;
case "vscode-couchbase.tools.dataExport.getFolder":
const options: vscode.OpenDialogOptions = {
canSelectMany: false,
openLabel: "Choose Destination Folder",
canSelectFiles: false,
canSelectFolders: true,
};

vscode.window.showOpenDialog(options).then((fileUri) => {
if (fileUri && fileUri[0]) {
currentPanel.webview.postMessage({
command: "vscode-couchbase.tools.dataExport.folderInfo",
folder: fileUri[0].fsPath,
});
}
});
break;
}
});
} catch (err) {
logger.error(`Failed to open data export webview`);
logger.debug(err);
vscode.window.showErrorMessage(
"Failed to open data export webview: " + err
);
}

currentPanel.onDidDispose(() => {
Memory.state.update(Constants.DATA_EXPORT_WEBVIEW, null);
});
};
4 changes: 2 additions & 2 deletions src/tools/CBExport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ export class CBExport {

if (!allScopes) {
for (const col of cols) {
if (col.includes(" ")) {
scp.push(col.split(" ")[3]);
if (col.includes(" ")) { // All XXX (XXX represents scopeName)
scp.push(col.split(" ")[1]);
}
}

Expand Down
17 changes: 11 additions & 6 deletions src/webViews/tools/dataExport.webview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,17 +164,19 @@ export const dataExportWebview = async (buckets: string[]): Promise<string> => {
<input type="text" id="selectedFolder" name="selectedFolder" readonly>
</div>
<br>
<div class="validation-error" id="validation-error"></div>
<input type="submit" value="Submit" onclick="submitForm(event)">
</form>
</body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.13/js/select2.min.js"></script>
<script >
<script>
const vscode = acquireVsCodeApi();
let scopesSpecData = [];
function onBucketClick(bucketId) {
document.getElementById('scopes').setAttribute('disabled',"");
document.getElementById('collections').setAttribute('disabled',"");
vscode.postMessage({
command: 'vscode-couchbase.tools.dataExport.getScopes',
Expand All @@ -194,13 +196,13 @@ export const dataExportWebview = async (buckets: string[]): Promise<string> => {
for(let i=0;i<allScopeCnt;i++){
if(allScopes[i].selected === true){
if(i===0){
selectedScopes.push("all-scopes");
selectedScopes.push("All Scopes");
} else{
selectedScopes.push(scopesSpecData[i-1]); // scopeSpecData is i-1 for eliminating all scopes
}
}
}
if(selectedScopes.includes("all-scopes")){
if(selectedScopes.includes("All Scopes")){
// No Collections Required
document.getElementById('collections').setAttribute('disabled',"");
Expand All @@ -210,7 +212,7 @@ export const dataExportWebview = async (buckets: string[]): Promise<string> => {
selectedScopes.map((scopeDetails)=>{
// All Collections of the scope
const selectAllOption = document.createElement('option');
selectAllOption.value = 'all-collections-'+scopeDetails.name;
selectAllOption.value = 'All '+scopeDetails.name;
selectAllOption.text = 'Select all collections of scope: '+scopeDetails.name;
collectionsDropdown.appendChild(selectAllOption);
Expand Down Expand Up @@ -244,7 +246,7 @@ export const dataExportWebview = async (buckets: string[]): Promise<string> => {
// Clear existing options in the scope dropdown
scopeDropdown.innerHTML = '';
const selectAllOption = document.createElement('option');
selectAllOption.value = 'all-scopes';
selectAllOption.value = 'All Scopes';
selectAllOption.text = 'Select All';
scopeDropdown.appendChild(selectAllOption);
Expand All @@ -259,8 +261,11 @@ export const dataExportWebview = async (buckets: string[]): Promise<string> => {
break;
case 'vscode-couchbase.tools.dataExport.folderInfo':
let folder = message.folder;
console.log(folder);
document.getElementById("selectedFolder").setAttribute("value", folder);
case 'vscode-couchbase.tools.dataExport.formValidationError':
let error = message.error;
document.getElementById("validation-error").innerHTML = message.error;
}
});
Expand Down

0 comments on commit 42cf402

Please sign in to comment.