mirror of
https://github.com/dbeaver/cloudbeaver.git
synced 2026-09-24 16:04:36 +08:00
feat(plugin-data-viewer): readonly mode for spreadsheet
CB-186
This commit is contained in:
@@ -14,7 +14,7 @@ import {
|
||||
ObjectPropertyInfo
|
||||
} from '@cloudbeaver/core-sdk';
|
||||
|
||||
export type Connection = Pick<ConnectionInfo, 'id' | 'name' | 'description' | 'connected' | 'driverId' | 'features' | 'authModel' | 'authNeeded'> & { authProperties?: ObjectPropertyInfo[] }
|
||||
export type Connection = Pick<ConnectionInfo, 'id' | 'name' | 'description' | 'connected' | 'readOnly' | 'driverId' | 'features' | 'authModel' | 'authNeeded'> & { authProperties?: ObjectPropertyInfo[] }
|
||||
|
||||
@injectable()
|
||||
export class ConnectionInfoResource extends CachedMapResource<string, Connection> {
|
||||
|
||||
@@ -5,6 +5,8 @@ mutation closeConnection($id: ID!) {
|
||||
description
|
||||
driverId
|
||||
connected
|
||||
readOnly
|
||||
|
||||
features
|
||||
|
||||
authNeeded
|
||||
|
||||
@@ -5,6 +5,8 @@ query connectionState($id: ID!) {
|
||||
description
|
||||
driverId
|
||||
connected
|
||||
readOnly
|
||||
|
||||
features
|
||||
|
||||
authNeeded
|
||||
|
||||
@@ -5,6 +5,8 @@ mutation createConnection($config: ConnectionConfig!) {
|
||||
description
|
||||
driverId
|
||||
connected
|
||||
readOnly
|
||||
|
||||
features
|
||||
|
||||
authNeeded
|
||||
|
||||
@@ -5,6 +5,8 @@ mutation initConnection($id: ID!, $credentials: Object) {
|
||||
description
|
||||
driverId
|
||||
connected
|
||||
readOnly
|
||||
|
||||
features
|
||||
|
||||
authNeeded
|
||||
|
||||
@@ -5,6 +5,8 @@ mutation openConnection($config: ConnectionConfig!) {
|
||||
description
|
||||
driverId
|
||||
connected
|
||||
readOnly
|
||||
|
||||
features
|
||||
|
||||
authNeeded
|
||||
|
||||
@@ -5,6 +5,8 @@ query getTemplateConnections {
|
||||
description
|
||||
driverId
|
||||
connected
|
||||
readOnly
|
||||
|
||||
features
|
||||
|
||||
authNeeded
|
||||
|
||||
@@ -22,6 +22,7 @@ mutation getSqlExecuteTaskResults(
|
||||
name
|
||||
position
|
||||
precision
|
||||
readOnly
|
||||
scale
|
||||
typeName
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ mutation readDataFromContainer(
|
||||
name
|
||||
position
|
||||
precision
|
||||
readOnly
|
||||
scale
|
||||
typeName
|
||||
}
|
||||
|
||||
@@ -655,6 +655,7 @@ export type SqlResultColumn = {
|
||||
maxLength?: Maybe<Scalars['Int']>;
|
||||
scale?: Maybe<Scalars['Int']>;
|
||||
precision?: Maybe<Scalars['Int']>;
|
||||
readOnly: Scalars['Boolean'];
|
||||
};
|
||||
|
||||
export type SqlResultSet = {
|
||||
@@ -834,7 +835,7 @@ export type CloseConnectionMutationVariables = Exact<{
|
||||
id: Scalars['ID'];
|
||||
}>;
|
||||
|
||||
export type CloseConnectionMutation = { connection: Pick<ConnectionInfo, 'id' | 'name' | 'description' | 'driverId' | 'connected' | 'features' | 'authNeeded' | 'authModel'> };
|
||||
export type CloseConnectionMutation = { connection: Pick<ConnectionInfo, 'id' | 'name' | 'description' | 'driverId' | 'connected' | 'readOnly' | 'features' | 'authNeeded' | 'authModel'> };
|
||||
|
||||
export type ConnectionAuthPropertiesQueryVariables = Exact<{
|
||||
id: Scalars['ID'];
|
||||
@@ -846,13 +847,13 @@ export type ConnectionStateQueryVariables = Exact<{
|
||||
id: Scalars['ID'];
|
||||
}>;
|
||||
|
||||
export type ConnectionStateQuery = { connection: Pick<ConnectionInfo, 'id' | 'name' | 'description' | 'driverId' | 'connected' | 'features' | 'authNeeded' | 'authModel'> };
|
||||
export type ConnectionStateQuery = { connection: Pick<ConnectionInfo, 'id' | 'name' | 'description' | 'driverId' | 'connected' | 'readOnly' | 'features' | 'authNeeded' | 'authModel'> };
|
||||
|
||||
export type CreateConnectionMutationVariables = Exact<{
|
||||
config: ConnectionConfig;
|
||||
}>;
|
||||
|
||||
export type CreateConnectionMutation = { createConnection: Pick<ConnectionInfo, 'id' | 'name' | 'description' | 'driverId' | 'connected' | 'features' | 'authNeeded' | 'authModel'> };
|
||||
export type CreateConnectionMutation = { createConnection: Pick<ConnectionInfo, 'id' | 'name' | 'description' | 'driverId' | 'connected' | 'readOnly' | 'features' | 'authNeeded' | 'authModel'> };
|
||||
|
||||
export type DeleteConnectionMutationVariables = Exact<{
|
||||
id: Scalars['ID'];
|
||||
@@ -891,17 +892,17 @@ export type InitConnectionMutationVariables = Exact<{
|
||||
credentials?: Maybe<Scalars['Object']>;
|
||||
}>;
|
||||
|
||||
export type InitConnectionMutation = { connection: Pick<ConnectionInfo, 'id' | 'name' | 'description' | 'driverId' | 'connected' | 'features' | 'authNeeded' | 'authModel'> };
|
||||
export type InitConnectionMutation = { connection: Pick<ConnectionInfo, 'id' | 'name' | 'description' | 'driverId' | 'connected' | 'readOnly' | 'features' | 'authNeeded' | 'authModel'> };
|
||||
|
||||
export type OpenConnectionMutationVariables = Exact<{
|
||||
config: ConnectionConfig;
|
||||
}>;
|
||||
|
||||
export type OpenConnectionMutation = { connection: Pick<ConnectionInfo, 'id' | 'name' | 'description' | 'driverId' | 'connected' | 'features' | 'authNeeded' | 'authModel'> };
|
||||
export type OpenConnectionMutation = { connection: Pick<ConnectionInfo, 'id' | 'name' | 'description' | 'driverId' | 'connected' | 'readOnly' | 'features' | 'authNeeded' | 'authModel'> };
|
||||
|
||||
export type GetTemplateConnectionsQueryVariables = Exact<{ [key: string]: never }>;
|
||||
|
||||
export type GetTemplateConnectionsQuery = { connections: Array<Pick<ConnectionInfo, 'id' | 'name' | 'description' | 'driverId' | 'connected' | 'features' | 'authNeeded' | 'authModel'>> };
|
||||
export type GetTemplateConnectionsQuery = { connections: Array<Pick<ConnectionInfo, 'id' | 'name' | 'description' | 'driverId' | 'connected' | 'readOnly' | 'features' | 'authNeeded' | 'authModel'>> };
|
||||
|
||||
export type TestConnectionMutationVariables = Exact<{
|
||||
config: ConnectionConfig;
|
||||
@@ -984,7 +985,7 @@ export type GetSqlExecuteTaskResultsMutation = { result: (
|
||||
Pick<SqlQueryResults, 'updateRowCount' | 'sourceQuery' | 'title'>
|
||||
& { resultSet?: Maybe<(
|
||||
Pick<SqlResultSet, 'id' | 'rows'>
|
||||
& { columns?: Maybe<Array<Maybe<Pick<SqlResultColumn, 'dataKind' | 'entityName' | 'fullTypeName' | 'icon' | 'label' | 'maxLength' | 'name' | 'position' | 'precision' | 'scale' | 'typeName'>>>> }
|
||||
& { columns?: Maybe<Array<Maybe<Pick<SqlResultColumn, 'dataKind' | 'entityName' | 'fullTypeName' | 'icon' | 'label' | 'maxLength' | 'name' | 'position' | 'precision' | 'readOnly' | 'scale' | 'typeName'>>>> }
|
||||
)>; }
|
||||
)>; }
|
||||
); };
|
||||
@@ -1002,7 +1003,7 @@ export type ReadDataFromContainerMutation = { readDataFromContainer?: Maybe<(
|
||||
Pick<SqlQueryResults, 'updateRowCount' | 'sourceQuery' | 'title'>
|
||||
& { resultSet?: Maybe<(
|
||||
Pick<SqlResultSet, 'id' | 'rows'>
|
||||
& { columns?: Maybe<Array<Maybe<Pick<SqlResultColumn, 'dataKind' | 'entityName' | 'fullTypeName' | 'icon' | 'label' | 'maxLength' | 'name' | 'position' | 'precision' | 'scale' | 'typeName'>>>> }
|
||||
& { columns?: Maybe<Array<Maybe<Pick<SqlResultColumn, 'dataKind' | 'entityName' | 'fullTypeName' | 'icon' | 'label' | 'maxLength' | 'name' | 'position' | 'precision' | 'readOnly' | 'scale' | 'typeName'>>>> }
|
||||
)>; }
|
||||
)>; }
|
||||
)>; };
|
||||
@@ -1296,6 +1297,7 @@ export const CloseConnectionDocument = `
|
||||
description
|
||||
driverId
|
||||
connected
|
||||
readOnly
|
||||
features
|
||||
authNeeded
|
||||
authModel
|
||||
@@ -1327,6 +1329,7 @@ export const ConnectionStateDocument = `
|
||||
description
|
||||
driverId
|
||||
connected
|
||||
readOnly
|
||||
features
|
||||
authNeeded
|
||||
authModel
|
||||
@@ -1341,6 +1344,7 @@ export const CreateConnectionDocument = `
|
||||
description
|
||||
driverId
|
||||
connected
|
||||
readOnly
|
||||
features
|
||||
authNeeded
|
||||
authModel
|
||||
@@ -1422,6 +1426,7 @@ export const InitConnectionDocument = `
|
||||
description
|
||||
driverId
|
||||
connected
|
||||
readOnly
|
||||
features
|
||||
authNeeded
|
||||
authModel
|
||||
@@ -1436,6 +1441,7 @@ export const OpenConnectionDocument = `
|
||||
description
|
||||
driverId
|
||||
connected
|
||||
readOnly
|
||||
features
|
||||
authNeeded
|
||||
authModel
|
||||
@@ -1450,6 +1456,7 @@ export const GetTemplateConnectionsDocument = `
|
||||
description
|
||||
driverId
|
||||
connected
|
||||
readOnly
|
||||
features
|
||||
authNeeded
|
||||
authModel
|
||||
@@ -1593,6 +1600,7 @@ export const GetSqlExecuteTaskResultsDocument = `
|
||||
name
|
||||
position
|
||||
precision
|
||||
readOnly
|
||||
scale
|
||||
typeName
|
||||
}
|
||||
@@ -1623,6 +1631,7 @@ export const ReadDataFromContainerDocument = `
|
||||
name
|
||||
position
|
||||
precision
|
||||
readOnly
|
||||
scale
|
||||
typeName
|
||||
}
|
||||
|
||||
@@ -268,7 +268,7 @@ function mapDataToColumns(columns?: IAgGridCol[]): ColDef[] {
|
||||
type: v.dataKind,
|
||||
editable: (params: any) => {
|
||||
const context: AgGridContext = params.context;
|
||||
return !context.isReadonly();
|
||||
return !(context.isReadonly() || v.readOnly);
|
||||
},
|
||||
valueGetter: (params: ValueGetterParams) => {
|
||||
if (!params.data) {
|
||||
|
||||
@@ -103,7 +103,7 @@ export class DataViewerTabService {
|
||||
return;
|
||||
}
|
||||
|
||||
this.dataViewerTableService.create(
|
||||
await this.dataViewerTableService.create(
|
||||
tab.id,
|
||||
NodeManagerUtils.connectionNodeIdToConnectionId(nodeInfo.connectionId),
|
||||
tab.handlerState.objectId
|
||||
|
||||
@@ -6,17 +6,19 @@
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import { ConnectionInfoResource } from '@cloudbeaver/core-app';
|
||||
import { injectable } from '@cloudbeaver/core-di';
|
||||
import { GraphQLService } from '@cloudbeaver/core-sdk';
|
||||
|
||||
import { IExecutionContext } from './IExecutionContext';
|
||||
import { RowDiff } from './TableViewer/TableDataModel/EditedRow';
|
||||
import { IRequestDataResult, TableViewerModel } from './TableViewer/TableViewerModel';
|
||||
import { IRequestDataResult, TableViewerModel, AccessMode } from './TableViewer/TableViewerModel';
|
||||
import { TableViewerStorageService } from './TableViewer/TableViewerStorageService';
|
||||
|
||||
@injectable()
|
||||
export class DataViewerTableService {
|
||||
constructor(private tableViewerStorageService: TableViewerStorageService,
|
||||
private connectionInfoResource: ConnectionInfoResource,
|
||||
private graphQLService: GraphQLService) {
|
||||
}
|
||||
|
||||
@@ -28,16 +30,19 @@ export class DataViewerTableService {
|
||||
this.tableViewerStorageService.remove(tableId);
|
||||
}
|
||||
|
||||
create(
|
||||
async create(
|
||||
tabId: string,
|
||||
connectionId: string,
|
||||
containerNodePath?: string,
|
||||
): TableViewerModel {
|
||||
): Promise<TableViewerModel> {
|
||||
const connectionInfo = await this.connectionInfoResource.load(connectionId);
|
||||
|
||||
return this.tableViewerStorageService.create(
|
||||
{
|
||||
tableId: tabId,
|
||||
connectionId,
|
||||
containerNodePath,
|
||||
access: connectionInfo.readOnly ? AccessMode.Readonly : AccessMode.Default,
|
||||
requestDataAsync: this.requestDataAsync.bind(this),
|
||||
saveChanges: this.saveChanges.bind(this),
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ export type TableColumn = Pick<
|
||||
| 'name'
|
||||
| 'position'
|
||||
| 'precision'
|
||||
| 'readOnly'
|
||||
| 'scale'
|
||||
| 'typeName'
|
||||
>
|
||||
|
||||
@@ -52,6 +52,7 @@ export interface IAgGridCol {
|
||||
name?: string;
|
||||
position?: number;
|
||||
dataKind?: string;
|
||||
readOnly: boolean;
|
||||
}
|
||||
|
||||
export interface IRequestedData {
|
||||
|
||||
+6
-1
@@ -8,7 +8,7 @@
|
||||
|
||||
import { observable } from 'mobx';
|
||||
|
||||
import { ErrorDetailsDialog } from '@cloudbeaver/core-app';
|
||||
import { ErrorDetailsDialog, ConnectionInfoResource } from '@cloudbeaver/core-app';
|
||||
import { IDestructibleController, IInitializableController, injectable } from '@cloudbeaver/core-di';
|
||||
import { CommonDialogService } from '@cloudbeaver/core-dialogs';
|
||||
import { NotificationService } from '@cloudbeaver/core-events';
|
||||
@@ -20,6 +20,7 @@ import {
|
||||
RowDiff,
|
||||
TableViewerStorageService,
|
||||
TableViewerModel,
|
||||
AccessMode,
|
||||
} from '@cloudbeaver/plugin-data-viewer';
|
||||
|
||||
import { ISqlResultPanelParams } from '../../ISqlEditorTabState';
|
||||
@@ -47,6 +48,7 @@ implements IInitializableController, IDestructibleController {
|
||||
|
||||
constructor(private sqlResultService: SqlResultService,
|
||||
private tableViewerStorageService: TableViewerStorageService,
|
||||
private connectionInfoResource: ConnectionInfoResource,
|
||||
private commonDialogService: CommonDialogService,
|
||||
private notificationService: NotificationService) {
|
||||
}
|
||||
@@ -71,12 +73,15 @@ implements IInitializableController, IDestructibleController {
|
||||
const initialState = this.sqlResultService
|
||||
.sqlExecuteInfoToData(response, this.panelInit.indexInResultSet, fetchingSettings.fetchDefault);
|
||||
|
||||
const connectionInfo = await this.connectionInfoResource.load(panelInit.sqlQueryParams.connectionId);
|
||||
|
||||
const tableModel = this.tableViewerStorageService.create({
|
||||
tableId: this.getTableId(),
|
||||
connectionId: panelInit.sqlQueryParams.connectionId,
|
||||
executionContext: panelInit.sqlQueryParams,
|
||||
resultId: dataSet.resultSet.id,
|
||||
sourceName: panelInit.sqlQueryParams.query,
|
||||
access: connectionInfo.readOnly ? AccessMode.Readonly : AccessMode.Default,
|
||||
requestDataAsync: this.requestDataAsync.bind(this, panelInit.sqlExecutionState),
|
||||
noLoaderWhileRequestingDataAsync: true,
|
||||
saveChanges: this.saveChanges.bind(this),
|
||||
|
||||
Reference in New Issue
Block a user