Thanks to visit codestin.com
Credit goes to github.com

Skip to content
This repository was archived by the owner on Aug 29, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 13 additions & 13 deletions app/components/Settings/ConnectButton/ConnectButton.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@ import React, {Component} from 'react';
import PropTypes from 'prop-types';
import {pathOr} from 'ramda';

/**
* The following is the Connect Button which triggers the connection
* @param {function} connect - Connect function
* @param {object} connectRequest - Connection Request
* @param {number || string} connectRequest.status -- 400 or loading
* @param {Error} connectRequest.error
* @param {object} saveConnectionsRequest - Saved Connection Request
* @param {number || string } saveConnectionsRequest.status -- 400 or loading
* @param {Error} saveConnectionsRequest.error
* @param {boolean} editMode - Enabled if Editting credentials
* @returns {ConnectButton}
*/
export default class ConnectButton extends Component {
/**
* Component props
* @type {object} props
* @property {function} props.connect - Connect function
* @property {object} props.connectRequest - Connection Request
* @property {(number|string)} props.connectRequest.status - 400 or loading
* @property {Error} props.connectRequest.error
* @property {object} props.saveConnectionsRequest - Saved Connection Request
* @property {(number|string)} props.saveConnectionsRequest.status - 400 or loading
* @property {Error} props.saveConnectionsRequest.error
* @property {boolean} props.editMode - Enabled if editing credentials
*/
static propTypes = {
connect: PropTypes.func,
connectRequest: PropTypes.object,
Expand Down Expand Up @@ -118,4 +118,4 @@ export default class ConnectButton extends Component {
</div>
);
}
}
}
8 changes: 5 additions & 3 deletions app/components/Settings/Preview/TableTree.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,13 @@ class TableTree extends Component {
getLabel(connectionObject) {
switch (connectionObject.dialect) {
case DIALECTS.SQLITE:
return BASENAME_RE.exec(connectionObject.storage)[0] || connectionObject.storage;
return BASENAME_RE.exec(connectionObject.storage)[0] || connectionObject.storage;
case DIALECTS.DATA_WORLD:
return getPathNames(connectionObject.url)[2];
return getPathNames(connectionObject.url)[2];
case DIALECTS.CSV:
return connectionObject.label || connectionObject.id || connectionObject.database;
default:
return connectionObject.database;
return connectionObject.database;
}
}

Expand Down
2 changes: 1 addition & 1 deletion app/components/Settings/Tabs/Tab.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export default class ConnectionTab extends Component {
} else if (dialect === DIALECTS.APACHE_SPARK) {
label = `Apache Spark (${connectionObject.host}:${connectionObject.port})`;
} else if (connectionObject.dialect === DIALECTS.CSV) {
label = `CSV (${connectionObject.database})`;
label = connectionObject.label || connectionObject.id || connectionObject.database;
} else if (connectionObject.dialect === DIALECTS.ELASTICSEARCH) {
label = `Elasticsearch (${connectionObject.host})`;
} else if (connectionObject.dialect === DIALECTS.SQLITE) {
Expand Down
12 changes: 12 additions & 0 deletions app/components/Settings/UserConnections/UserConnections.react.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import React, {Component} from 'react';
import PropTypes from 'prop-types';
import Filedrop from './filedrop.jsx';

import {contains} from 'ramda';

import {CONNECTION_CONFIG, SAMPLE_DBS} from '../../../constants/constants';
import {dynamicRequireElectron} from '../../../utils/utils';

Expand Down Expand Up @@ -151,6 +154,15 @@ export default class UserConnections extends Component {
</div>
</div>
);
} else if (setting.type === 'filedrop') {
input = (
<Filedrop
settings={setting}
connection={connectionObject}
updateConnection={updateConnection}
sampleCredentialsStyle={sampleCredentialsStyle}
/>
);
}

return (
Expand Down
172 changes: 172 additions & 0 deletions app/components/Settings/UserConnections/filedrop.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
import React, {Component} from 'react';
import PropTypes from 'prop-types';

import {SAMPLE_DBS} from '../../../constants/constants';

export default class Filedrop extends Component {
static propTypes = {
settings: PropTypes.object,
connection: PropTypes.object,
updateConnection: PropTypes.func,
sampleCredentialsStyle: PropTypes.object
}

/**
* Filedrop is an input component where users can type an URL or drop a file
*
* @param {object} props - Component properties
*
* @param {object} props.settings - FileDrop settings
* @param {string} props.settings.type - Set to 'filedrop'
* @param {string} props.settings.value - Target property in the connection object
* @param {string} props.settings.inputLabel - Label for input box
* @param {string} props.settings.dropLabel - Label for drop box
* @param {string} props.settings.placeholder - Placeholder for input box
*
* @param {object} props.connection - Connection object
* @param {string} props.connection.dialect - Connection dialect
* @param {string} props.connection.label - Connection label
*
* @param {function} props.updateConnection - Callback to update the connection object
*
* @param {object} props.sampleCredentialsStyle - To control the display of sample credentials
*/
constructor(props) {
super(props);

const {
settings,
connection
} = this.props;

const url = connection[settings.value];

/**
* @member {object} state - Component state
* @property {string} state.inputValue - Value typed into the input box
* @property {string} state.dropValue - Data URL dropped into the drop box
*/
this.state = (typeof url === 'string' && url.startsWith('data:')) ? {
inputValue: connection.label || url.slice(0, 64),
dropValue: url
} : {
inputValue: url || '',
dropValue: ''
};
}


render() {
const {
settings,
connection,
updateConnection,
sampleCredentialsStyle
} = this.props;

const {
inputValue,
dropValue,
drag
} = this.state;

const setState = this.setState.bind(this);

const {
value,
inputLabel,
dropLabel,
placeholder
} = settings;

const {dialect} = connection;

const sampleCredential = (SAMPLE_DBS[dialect]) ? SAMPLE_DBS[dialect][value] : null;

return (
<div
className={'inputContainer'}
onDragOver={onDragOver}
onDrop={onDrop}
>
<label className={'label'}>
{inputLabel}
</label>
<div className={'wrapInput'}>
<input
style={{backgroundColor: (drag || dropValue) ? 'lightcyan' : null}}
onChange={onChange}
onDragEnter={onDragEnter}
onDragLeave={onDragLeave}
value={inputValue}
placeholder={placeholder}
type={'text'}
/>
<small style={{clear: 'both', float: 'left', marginLeft: '20px'}}>
{dropLabel}
</small>
<div style={sampleCredentialsStyle}>
<code>
{sampleCredential}
</code>
</div>
</div>
</div>
);

function onChange(event) {
setState({
inputValue: event.target.value,
dropValue: ''
});
updateConnection({
[value]: event.target.value,
label: event.target.value
});
}

function onDragEnter(event) {
event.stopPropagation();
event.preventDefault();
setState({drag: true});
}

function onDragOver(event) {
event.stopPropagation();
event.preventDefault();
event.dataTransfer.dropEffect = 'copy';
}

function onDragLeave(event) {
event.stopPropagation();
event.preventDefault();
setState({drag: false});
}

function onDrop(event) {
event.stopPropagation();
event.preventDefault();

const files = event.dataTransfer.files;
if (!files || files.length !== 1) {
setState({drag: false});
return;
}

const file = files[0];
const reader = new FileReader();
reader.onload = () => {
setState({
drag: false,
dropValue: reader.result,
inputValue: file.name
});
updateConnection({
[value]: reader.result,
label: file.name
});
};
reader.readAsDataURL(file);
}
}
}
9 changes: 6 additions & 3 deletions app/constants/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,12 @@ const hadoopQLOptions = [
export const CONNECTION_CONFIG = {
[DIALECTS.APACHE_IMPALA]: hadoopQLOptions,
[DIALECTS.APACHE_SPARK]: hadoopQLOptions,
[DIALECTS.CSV]: [
{'label': 'URL to CSV File', 'value': 'database', 'type': 'text'}
],
[DIALECTS.CSV]: [{
'inputLabel': 'Type URL to a CSV file',
'dropLabel': '(or drop a CSV file here)',
'value': 'database',
'type': 'filedrop'
}],
[DIALECTS.IBM_DB2]: commonSqlOptions,
[DIALECTS.MYSQL]: commonSqlOptions,
[DIALECTS.MARIADB]: commonSqlOptions,
Expand Down
25 changes: 25 additions & 0 deletions backend/init.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import Logger from './logger';

import {
deleteAllConnections,
deleteBadConnections
} from './persistent/Connections.js';
import {getSetting} from './settings.js';

const setCSVStorageSize = require('./persistent/datastores/csv.js').setStorageSize;

export default function init() {
try {
deleteBadConnections();
} catch (error) {
Logger.log(`Failed to delete bad connections: ${error.message}`);
deleteAllConnections();
}

try {
setCSVStorageSize(getSetting('CSV_STORAGE_SIZE'));
} catch (error) {
Logger.log(`Failed to get setting CSV_STORAGE_SIZE: ${error.message}`);
setCSVStorageSize(0);
}
}
24 changes: 23 additions & 1 deletion backend/persistent/Connections.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {assoc, dissoc, findIndex} from 'ramda';
import uuid from 'uuid';
import YAML from 'yamljs';
import * as Datastores from './datastores/Datastores.js';
import {DIALECTS} from '../../app/constants/constants.js';

import {getSetting} from '../settings';

Expand Down Expand Up @@ -39,11 +40,32 @@ export function deleteConnectionById(id) {
const connections = getConnections();
const index = findIndex(connection => connection.id === id, connections);
if (index > -1) {
Datastores.disconnect(connections[index]);
connections.splice(index, 1);
fs.writeFileSync(getSetting('CONNECTIONS_PATH'), YAML.stringify(connections, 4));
}
}

export function deleteBadConnections() {
getConnections().forEach(connection => {
const {id, dialect} = connection;

const dialects = Object.getOwnPropertyNames(DIALECTS).map(k => DIALECTS[k]);

const isUnknownDialect = (dialects.indexOf(dialect) === -1);
if (isUnknownDialect) {
deleteConnectionById(id);
}
});
}

export function deleteAllConnections() {
if (!fs.existsSync(getSetting('STORAGE_PATH'))) {
createStoragePath();
}
fs.writeFileSync(getSetting('CONNECTIONS_PATH'), YAML.stringify([], 4));
}

export function getSanitizedConnections() {
const connections = getConnections();
return connections.map(cred => sanitize(cred));
Expand All @@ -60,7 +82,7 @@ export function saveConnection(connectionObject) {
return connectionId;
}

export function validateConnection (connectionObject) {
export function validateConnection(connectionObject) {
return Datastores.connect(connectionObject).then(() => {
return {};
}).catch(err => {
Expand Down
Loading