diff --git a/webapp/packages/plugin-data-viewer/src/DatabaseDataModel/Actions/Document/DocumentDataAction.ts b/webapp/packages/plugin-data-viewer/src/DatabaseDataModel/Actions/Document/DocumentDataAction.ts new file mode 100644 index 0000000000..e422e50315 --- /dev/null +++ b/webapp/packages/plugin-data-viewer/src/DatabaseDataModel/Actions/Document/DocumentDataAction.ts @@ -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 + implements IDatabaseDataResultAction { + 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]; + } +} diff --git a/webapp/packages/plugin-data-viewer/src/DatabaseDataModel/Actions/Document/DocumentEditAction.ts b/webapp/packages/plugin-data-viewer/src/DatabaseDataModel/Actions/Document/DocumentEditAction.ts new file mode 100644 index 0000000000..a3314ee149 --- /dev/null +++ b/webapp/packages/plugin-data-viewer/src/DatabaseDataModel/Actions/Document/DocumentEditAction.ts @@ -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 + implements IDatabaseDataEditAction { + static dataFormat = ResultDataFormat.Document; + + readonly editedElements: Map; + + constructor(source: IDatabaseDataSource, 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; + } +} diff --git a/webapp/packages/plugin-data-viewer/src/DatabaseDataModel/Actions/Document/IDatabaseDataDocument.ts b/webapp/packages/plugin-data-viewer/src/DatabaseDataModel/Actions/Document/IDatabaseDataDocument.ts new file mode 100644 index 0000000000..1ff6e93c22 --- /dev/null +++ b/webapp/packages/plugin-data-viewer/src/DatabaseDataModel/Actions/Document/IDatabaseDataDocument.ts @@ -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; + data: string; +} diff --git a/webapp/packages/plugin-data-viewer/src/DatabaseDataModel/Actions/Document/IDocumentElementKey.ts b/webapp/packages/plugin-data-viewer/src/DatabaseDataModel/Actions/Document/IDocumentElementKey.ts new file mode 100644 index 0000000000..39b72a04e5 --- /dev/null +++ b/webapp/packages/plugin-data-viewer/src/DatabaseDataModel/Actions/Document/IDocumentElementKey.ts @@ -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; +} diff --git a/webapp/packages/plugin-data-viewer/src/DatabaseDataModel/Actions/IDatabaseDataEditAction.ts b/webapp/packages/plugin-data-viewer/src/DatabaseDataModel/Actions/IDatabaseDataEditAction.ts new file mode 100644 index 0000000000..bcffc1f937 --- /dev/null +++ b/webapp/packages/plugin-data-viewer/src/DatabaseDataModel/Actions/IDatabaseDataEditAction.ts @@ -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 + extends IDatabaseDataAction { + isEdited: () => boolean; + isElementEdited: (key: TKey) => boolean; + set: (key: TKey, value: TValue) => void; + get: (key: TKey) => TValue | undefined; + revert: (key: TKey) => void; + clear: () => void; +} diff --git a/webapp/packages/plugin-data-viewer/src/DatabaseDataModel/DatabaseDataAction.ts b/webapp/packages/plugin-data-viewer/src/DatabaseDataModel/DatabaseDataAction.ts index 0ca5b12b1d..4bb89e46b0 100644 --- a/webapp/packages/plugin-data-viewer/src/DatabaseDataModel/DatabaseDataAction.ts +++ b/webapp/packages/plugin-data-viewer/src/DatabaseDataModel/DatabaseDataAction.ts @@ -12,9 +12,14 @@ import type { IDatabaseDataSource } from './IDatabaseDataSource'; export abstract class DatabaseDataAction implements IDatabaseDataAction { - readonly source: IDatabaseDataSource; result: TResult; + get resultIndex(): number { + return this.source.results.indexOf(this.result); + } + + readonly source: IDatabaseDataSource; + constructor(source: IDatabaseDataSource, result: TResult) { this.result = result; this.source = source; diff --git a/webapp/packages/plugin-data-viewer/src/DatabaseDataModel/IDatabaseDataAction.ts b/webapp/packages/plugin-data-viewer/src/DatabaseDataModel/IDatabaseDataAction.ts index 0c4acb9925..b2ee9acc21 100644 --- a/webapp/packages/plugin-data-viewer/src/DatabaseDataModel/IDatabaseDataAction.ts +++ b/webapp/packages/plugin-data-viewer/src/DatabaseDataModel/IDatabaseDataAction.ts @@ -23,6 +23,7 @@ export interface IDatabaseDataActionClass< export interface IDatabaseDataAction { readonly source: IDatabaseDataSource; result: TResult; + resultIndex: number; updateResult: (result: TResult) => void; getAction: >( action: IDatabaseDataActionClass diff --git a/webapp/packages/plugin-data-viewer/src/DatabaseDataModel/IDatabaseDataModel.ts b/webapp/packages/plugin-data-viewer/src/DatabaseDataModel/IDatabaseDataModel.ts index cd70fd8a88..471d2b9df2 100644 --- a/webapp/packages/plugin-data-viewer/src/DatabaseDataModel/IDatabaseDataModel.ts +++ b/webapp/packages/plugin-data-viewer/src/DatabaseDataModel/IDatabaseDataModel.ts @@ -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 { +export interface IDatabaseDataModel { readonly id: string; readonly source: IDatabaseDataSource; readonly requestInfo: IRequestInfo; diff --git a/webapp/packages/plugin-data-viewer/src/index.ts b/webapp/packages/plugin-data-viewer/src/index.ts index bf90b42247..10511895f0 100644 --- a/webapp/packages/plugin-data-viewer/src/index.ts +++ b/webapp/packages/plugin-data-viewer/src/index.ts @@ -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';