2
0
mirror of https://github.com/frappe/books.git synced 2024-12-22 10:58:59 +00:00

Add remote database integration

Fixes #907

Add support for remote database connections when importing an existing database.

* **backend/database/manager.ts**
  - Add `connectToRemoteDatabase` method to support remote database connections.
  - Update `connectToDatabase` method to handle both local and remote database connections based on the provided configuration.
  - Add `_connectRemote` method to handle remote database connections.
* **backend/database/core.ts**
  - Add `connectToRemoteDatabase` method to support remote database connections.
* **README.md**
  - Add instructions for configuring and using the remote database connection feature.
* **src/pages/DatabaseConnections.vue**
  - Add a new user interface to configure remote database details.
  - Include fields for database type, authentication method, connection string, connection timeout, and request timeout.
  - Add buttons for testing the connection, saving, and canceling.
This commit is contained in:
M.F.M Fazrin 2024-08-13 21:01:08 +03:00
parent 13414c5a29
commit c54c834e1b
4 changed files with 157 additions and 0 deletions

View File

@ -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:

View File

@ -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();
}

View File

@ -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);
@ -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?.(

View File

@ -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>