feat: CB-1028 document editing

This commit is contained in:
Wroud
2021-06-09 18:12:31 +03:00
parent a5fd4fb6d0
commit 94af33ebae
9 changed files with 194 additions and 2 deletions
@@ -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];
}
}
@@ -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;
}
}
@@ -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;
}
@@ -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;
}
@@ -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';