mirror of
https://github.com/dbeaver/cloudbeaver.git
synced 2026-09-24 16:04:36 +08:00
feat: CB-1028 document editing
This commit is contained in:
+29
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* CloudBeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020-2021 DBeaver Corp and others
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import { ResultDataFormat } from '@cloudbeaver/core-sdk';
|
||||
|
||||
import { DatabaseDataAction } from '../../DatabaseDataAction';
|
||||
import type { IDatabaseResultSet } from '../../IDatabaseResultSet';
|
||||
import { databaseDataAction } from '../DatabaseDataActionDecorator';
|
||||
import type { IDatabaseDataResultAction } from '../IDatabaseDataResultAction';
|
||||
import type { IDatabaseDataDocument } from './IDatabaseDataDocument';
|
||||
|
||||
@databaseDataAction()
|
||||
export class DocumentDataAction extends DatabaseDataAction<any, IDatabaseResultSet>
|
||||
implements IDatabaseDataResultAction<IDatabaseResultSet> {
|
||||
static dataFormat = ResultDataFormat.Document;
|
||||
|
||||
get count(): number {
|
||||
return this.result.data?.rows?.length || 0;
|
||||
}
|
||||
|
||||
get(index: number): IDatabaseDataDocument | undefined {
|
||||
return this.result.data?.rows?.[index]?.[0];
|
||||
}
|
||||
}
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* CloudBeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020-2021 DBeaver Corp and others
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import { makeObservable, observable } from 'mobx';
|
||||
|
||||
import { ResultDataFormat } from '@cloudbeaver/core-sdk';
|
||||
|
||||
import { DatabaseDataAction } from '../../DatabaseDataAction';
|
||||
import type { IDatabaseDataSource } from '../../IDatabaseDataSource';
|
||||
import type { IDatabaseResultSet } from '../../IDatabaseResultSet';
|
||||
import { databaseDataAction } from '../DatabaseDataActionDecorator';
|
||||
import type { IDatabaseDataEditAction } from '../IDatabaseDataEditAction';
|
||||
import { DocumentDataAction } from './DocumentDataAction';
|
||||
import type { IDatabaseDataDocument } from './IDatabaseDataDocument';
|
||||
import type { IDocumentElementKey } from './IDocumentElementKey';
|
||||
|
||||
@databaseDataAction()
|
||||
export class DocumentEditAction extends DatabaseDataAction<any, IDatabaseResultSet>
|
||||
implements IDatabaseDataEditAction<IDocumentElementKey, IDatabaseDataDocument, IDatabaseResultSet> {
|
||||
static dataFormat = ResultDataFormat.Document;
|
||||
|
||||
readonly editedElements: Map<number, IDatabaseDataDocument>;
|
||||
|
||||
constructor(source: IDatabaseDataSource<any, IDatabaseResultSet>, result: IDatabaseResultSet) {
|
||||
super(source, result);
|
||||
this.editedElements = new Map();
|
||||
|
||||
makeObservable(this, {
|
||||
editedElements: observable,
|
||||
});
|
||||
}
|
||||
|
||||
isEdited(): boolean {
|
||||
return this.editedElements.size > 0;
|
||||
}
|
||||
|
||||
isElementEdited(key: IDocumentElementKey): boolean {
|
||||
const value = this.getAction(DocumentDataAction).get(key.index);
|
||||
|
||||
return !this.compare(value, this.get(key));
|
||||
}
|
||||
|
||||
set(key: IDocumentElementKey, value: IDatabaseDataDocument): void {
|
||||
this.editedElements.set(key.index, value);
|
||||
|
||||
// TODO: remove
|
||||
this.source
|
||||
.getEditor(this.resultIndex)
|
||||
.setCell(key.index, 0, value);
|
||||
|
||||
this.removeUnchanged(key);
|
||||
}
|
||||
|
||||
setData(key: IDocumentElementKey, value: string): void {
|
||||
const edited = this.editedElements.get(key.index);
|
||||
|
||||
if (edited) {
|
||||
edited.data = value;
|
||||
this.removeUnchanged(key);
|
||||
return;
|
||||
}
|
||||
|
||||
const sourceValue = this.getAction(DocumentDataAction)
|
||||
.get(key.index);
|
||||
|
||||
if (!sourceValue) {
|
||||
throw new Error('Source value not found');
|
||||
}
|
||||
|
||||
this.set(key, {
|
||||
...sourceValue,
|
||||
data: value,
|
||||
});
|
||||
}
|
||||
|
||||
get(key: IDocumentElementKey): IDatabaseDataDocument | undefined {
|
||||
return this.editedElements.get(key.index);
|
||||
}
|
||||
|
||||
revert(key: IDocumentElementKey): void {
|
||||
this.editedElements.delete(key.index);
|
||||
|
||||
// TODO: remove
|
||||
this.source
|
||||
.getEditor(this.resultIndex)
|
||||
.revert(key.index);
|
||||
}
|
||||
|
||||
clear(): void {
|
||||
this.editedElements.clear();
|
||||
}
|
||||
|
||||
private removeUnchanged(key: IDocumentElementKey) {
|
||||
if (!this.isElementEdited(key)) {
|
||||
this.revert(key);
|
||||
}
|
||||
}
|
||||
|
||||
private compare(documentA: IDatabaseDataDocument | undefined, documentB: IDatabaseDataDocument | undefined) {
|
||||
return documentA?.data === documentB?.data;
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* CloudBeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020-2021 DBeaver Corp and others
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
export interface IDatabaseDataDocument {
|
||||
$type: 'document';
|
||||
id: string;
|
||||
contentType: string;
|
||||
properties: Record<string, any>;
|
||||
data: string;
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* CloudBeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020-2021 DBeaver Corp and others
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
export interface IDocumentElementKey {
|
||||
readonly index: number;
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* CloudBeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020-2021 DBeaver Corp and others
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import type { IDatabaseDataAction } from '../IDatabaseDataAction';
|
||||
import type { IDatabaseDataResult } from '../IDatabaseDataResult';
|
||||
|
||||
export interface IDatabaseDataEditAction<TKey, TValue, TResult extends IDatabaseDataResult>
|
||||
extends IDatabaseDataAction<any, TResult> {
|
||||
isEdited: () => boolean;
|
||||
isElementEdited: (key: TKey) => boolean;
|
||||
set: (key: TKey, value: TValue) => void;
|
||||
get: (key: TKey) => TValue | undefined;
|
||||
revert: (key: TKey) => void;
|
||||
clear: () => void;
|
||||
}
|
||||
@@ -12,9 +12,14 @@ import type { IDatabaseDataSource } from './IDatabaseDataSource';
|
||||
|
||||
export abstract class DatabaseDataAction<TOptions, TResult extends IDatabaseDataResult>
|
||||
implements IDatabaseDataAction<TOptions, TResult> {
|
||||
readonly source: IDatabaseDataSource<TOptions, TResult>;
|
||||
result: TResult;
|
||||
|
||||
get resultIndex(): number {
|
||||
return this.source.results.indexOf(this.result);
|
||||
}
|
||||
|
||||
readonly source: IDatabaseDataSource<TOptions, TResult>;
|
||||
|
||||
constructor(source: IDatabaseDataSource<TOptions, TResult>, result: TResult) {
|
||||
this.result = result;
|
||||
this.source = source;
|
||||
|
||||
@@ -23,6 +23,7 @@ export interface IDatabaseDataActionClass<
|
||||
export interface IDatabaseDataAction<TOptions, TResult extends IDatabaseDataResult> {
|
||||
readonly source: IDatabaseDataSource<TOptions, TResult>;
|
||||
result: TResult;
|
||||
resultIndex: number;
|
||||
updateResult: (result: TResult) => void;
|
||||
getAction: <T extends IDatabaseDataAction<TOptions, TResult>>(
|
||||
action: IDatabaseDataActionClass<TOptions, TResult, T>
|
||||
|
||||
@@ -11,7 +11,7 @@ import type { ResultDataFormat } from '@cloudbeaver/core-sdk';
|
||||
import type { IDatabaseDataResult } from './IDatabaseDataResult';
|
||||
import type { DatabaseDataAccessMode, IDatabaseDataSource, IRequestInfo } from './IDatabaseDataSource';
|
||||
|
||||
export interface IDatabaseDataModel<TOptions, TResult extends IDatabaseDataResult = IDatabaseDataResult> {
|
||||
export interface IDatabaseDataModel<TOptions = any, TResult extends IDatabaseDataResult = IDatabaseDataResult> {
|
||||
readonly id: string;
|
||||
readonly source: IDatabaseDataSource<TOptions, TResult>;
|
||||
readonly requestInfo: IRequestInfo;
|
||||
|
||||
@@ -2,6 +2,10 @@ import { manifest } from './manifest';
|
||||
|
||||
export default manifest;
|
||||
|
||||
export * from './DatabaseDataModel/Actions/Document/DocumentDataAction';
|
||||
export * from './DatabaseDataModel/Actions/Document/DocumentEditAction';
|
||||
export * from './DatabaseDataModel/Actions/Document/IDatabaseDataDocument';
|
||||
export * from './DatabaseDataModel/Actions/Document/IDocumentElementKey';
|
||||
export * from './DatabaseDataModel/Actions/ResultSet/IResultSetContentValue';
|
||||
export * from './DatabaseDataModel/Actions/ResultSet/IResultSetElementKey';
|
||||
export * from './DatabaseDataModel/Actions/ResultSet/ResultSetFormatAction';
|
||||
|
||||
Reference in New Issue
Block a user