Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add remote database integration #926

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,23 @@ computer) check the _Building_ section at

So to build for linux you could use the `--linux` flag like so: `yarn build --linux`.

## Remote Database Connection

Frappe Books now supports connecting to a remote database when importing an existing database. Follow the steps below to configure and use the remote database connection feature:

1. Open Frappe Books and navigate to the "Database Connections" section.
2. Click on "New Database Connection" to add a new remote database connection.
3. Fill in the required details:
- **ID**: A unique identifier for the database connection.
- **Database type**: Select the database type (e.g., SQL Server).
- **Authentication method**: Choose the authentication method.
- **Connection String**: Enter the connection string for the remote database.
- **Connection timeout (ms)**: Specify the connection timeout in milliseconds (optional).
- **Request timeout (ms)**: Specify the request timeout in milliseconds (optional).
4. Click on "Test Connection" to verify the connection details.
5. If the connection is successful, click "Save" to save the remote database connection.
6. You can now use the remote database connection when importing an existing database.

## Contributions and Community

If you want to contribute to Frappe Books, please check our [Contribution Guidelines](https://github.com/frappe/books/blob/master/.github/CONTRIBUTING.md). There are many ways you can contribute even if you don't code:
Expand Down
8 changes: 8 additions & 0 deletions backend/database/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,14 @@ export default class DatabaseCore extends DatabaseBase {
await this.knex.raw('PRAGMA foreign_keys=ON');
}

async connectToRemoteDatabase(connectionString: string) {
this.knex = knex({
client: 'pg',
connection: connectionString,
});
await this.knex.raw('SELECT 1');
}

async close() {
await this.knex!.destroy();
}
Expand Down
19 changes: 19 additions & 0 deletions backend/database/manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,20 @@ export class DatabaseManager extends DatabaseDemuxBase {
}

async connectToDatabase(dbPath: string, countryCode?: string) {
if (dbPath.startsWith('http://') || dbPath.startsWith('https://')) {
return await this.connectToRemoteDatabase(dbPath, countryCode);
}
countryCode = await this._connect(dbPath, countryCode);
await this.#migrate();
return countryCode;
}

async connectToRemoteDatabase(dbPath: string, countryCode?: string) {
countryCode = await this._connectRemote(dbPath, countryCode);
await this.#migrate();
return countryCode;
}

async _connect(dbPath: string, countryCode?: string) {
countryCode ??= await DatabaseCore.getCountryCode(dbPath);
this.db = new DatabaseCore(dbPath);
Expand All @@ -50,6 +59,16 @@ export class DatabaseManager extends DatabaseDemuxBase {
return countryCode;
}

async _connectRemote(dbPath: string, countryCode?: string) {
countryCode ??= await DatabaseCore.getCountryCode(dbPath);
this.db = new DatabaseCore(dbPath);
await this.db.connectToRemoteDatabase(dbPath);
await this.setRawCustomFields();
const schemaMap = getSchemas(countryCode, this.rawCustomFields);
this.db.setSchemaMap(schemaMap);
return countryCode;
}

async setRawCustomFields() {
try {
this.rawCustomFields = (await this.db?.knex?.(
Expand Down
113 changes: 113 additions & 0 deletions src/pages/DatabaseConnections.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
<template>
<div class="database-connections">
<h1>{{ t`Database Connections` }}</h1>
<div class="new-connection">
<h2>{{ t`New Database Connection` }}</h2>
<form @submit.prevent="saveConnection">
<div class="form-group">
<label for="id">{{ t`ID` }}</label>
<input type="text" id="id" v-model="connection.id" required />
</div>
<div class="form-group">
<label for="databaseType">{{ t`Database type` }}</label>
<select id="databaseType" v-model="connection.databaseType" required>
<option value="SQL Server">{{ t`SQL Server` }}</option>
<!-- Add more database types as needed -->
</select>
</div>
<div class="form-group">
<label for="authenticationMethod">{{ t`Authentication method` }}</label>
<select id="authenticationMethod" v-model="connection.authenticationMethod" required>
<option value="">{{ t`Select authentication method` }}</option>
<!-- Add more authentication methods as needed -->
</select>
</div>
<div class="form-group">
<label for="connectionString">{{ t`Connection String` }}</label>
<input type="text" id="connectionString" v-model="connection.connectionString" required />
</div>
<div class="form-group">
<label for="connectionTimeout">{{ t`Connection timeout (ms)` }}</label>
<input type="number" id="connectionTimeout" v-model="connection.connectionTimeout" />
</div>
<div class="form-group">
<label for="requestTimeout">{{ t`Request timeout (ms)` }}</label>
<input type="number" id="requestTimeout" v-model="connection.requestTimeout" />
</div>
<div class="form-actions">
<button type="button" @click="testConnection">{{ t`Test Connection` }}</button>
<button type="button" @click="cancel">{{ t`Cancel` }}</button>
<button type="submit">{{ t`Save` }}</button>
</div>
</form>
</div>
</div>
</template>

<script lang="ts">
import { defineComponent } from 'vue';
import { t } from 'fyo';

export default defineComponent({
name: 'DatabaseConnections',
data() {
return {
connection: {
id: '',
databaseType: '',
authenticationMethod: '',
connectionString: '',
connectionTimeout: null,
requestTimeout: null,
},
};
},
methods: {
async testConnection() {
// Implement the logic to test the database connection
},
cancel() {
// Implement the logic to cancel the connection creation
},
async saveConnection() {
// Implement the logic to save the database connection
},
},
});
</script>

<style scoped>
.database-connections {
padding: 20px;
}

.new-connection {
margin-top: 20px;
}

.form-group {
margin-bottom: 15px;
}

.form-group label {
display: block;
margin-bottom: 5px;
}

.form-group input,
.form-group select {
width: 100%;
padding: 8px;
box-sizing: border-box;
}

.form-actions {
display: flex;
justify-content: space-between;
margin-top: 20px;
}

.form-actions button {
padding: 10px 20px;
}
</style>