mirror of
https://github.com/dbeaver/cloudbeaver.git
synced 2026-10-29 19:19:39 +08:00
feat(plugin-data-viewer): CB-908 image value presentation
This commit is contained in:
+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 IResultSetContentValue {
|
||||
$type: 'content';
|
||||
binary?: string;
|
||||
text?: string;
|
||||
contentType?: string;
|
||||
contentLength?: number;
|
||||
}
|
||||
+15
@@ -12,6 +12,7 @@ import { DatabaseDataAction } from '../../DatabaseDataAction';
|
||||
import type { IDatabaseResultSet } from '../../IDatabaseResultSet';
|
||||
import { databaseDataAction } from '../DatabaseDataActionDecorator';
|
||||
import type { IDatabaseDataResultAction } from '../IDatabaseDataResultAction';
|
||||
import type { IResultSetContentValue } from './IResultSetContentValue';
|
||||
import type { IResultSetElementKey } from './IResultSetElementKey';
|
||||
|
||||
@databaseDataAction()
|
||||
@@ -27,6 +28,20 @@ export class ResultSetDataAction extends DatabaseDataAction<any, IDatabaseResult
|
||||
return this.result.data.rows?.[cell.row]?.[cell.column];
|
||||
}
|
||||
|
||||
getContent(cell: IResultSetElementKey): IResultSetContentValue | null {
|
||||
const value = this.getCellValue(cell);
|
||||
|
||||
if (
|
||||
value !== null
|
||||
&& typeof value === 'object'
|
||||
&& '$type' in value
|
||||
&& value.$type === 'content'
|
||||
) {
|
||||
return value;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
getColumn(columnIndex: number) {
|
||||
if (!this.result.data?.columns) {
|
||||
return undefined;
|
||||
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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 { observer } from 'mobx-react-lite';
|
||||
import styled, { css } from 'reshadow';
|
||||
|
||||
import type { TabContainerPanelComponent } from '@cloudbeaver/core-blocks';
|
||||
import { useStyles } from '@cloudbeaver/core-theming';
|
||||
import { getMIME } from '@cloudbeaver/core-utils';
|
||||
|
||||
import { ResultSetDataAction } from '../../DatabaseDataModel/Actions/ResultSet/ResultSetDataAction';
|
||||
import { ResultSetSelectAction } from '../../DatabaseDataModel/Actions/ResultSet/ResultSetSelectAction';
|
||||
import type { IDatabaseResultSet } from '../../DatabaseDataModel/IDatabaseResultSet';
|
||||
import type { IDataValuePanelProps } from '../../TableViewer/ValuePanel/DataValuePanelService';
|
||||
|
||||
const styles = css`
|
||||
img {
|
||||
margin: auto;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
}
|
||||
`;
|
||||
|
||||
export const ImageValuePresentation: TabContainerPanelComponent<IDataValuePanelProps<any, IDatabaseResultSet>> = observer(function ImageValuePresentation({
|
||||
model,
|
||||
resultIndex,
|
||||
}) {
|
||||
const selection = model.source.getAction(resultIndex, ResultSetSelectAction);
|
||||
|
||||
const selectedCells = selection.getSelectedElements();
|
||||
const focusCell = selection.getFocusedElement();
|
||||
|
||||
let src: string | undefined;
|
||||
|
||||
if (selectedCells.length > 0 || focusCell) {
|
||||
const firstSelectedCell = selectedCells[0] || focusCell;
|
||||
|
||||
const content = model.source
|
||||
.getAction(resultIndex, ResultSetDataAction)
|
||||
.getContent(firstSelectedCell);
|
||||
|
||||
if (content?.binary) {
|
||||
src = `data:${getMIME(content.binary)};base64,${content.binary}`;
|
||||
}
|
||||
}
|
||||
|
||||
return styled(useStyles(styles))(
|
||||
<img src={src} />
|
||||
);
|
||||
});
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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 { Bootstrap, injectable } from '@cloudbeaver/core-di';
|
||||
import { ResultDataFormat } from '@cloudbeaver/core-sdk';
|
||||
import { getMIME } from '@cloudbeaver/core-utils';
|
||||
|
||||
import type { IResultSetContentValue } from '../../DatabaseDataModel/Actions/ResultSet/IResultSetContentValue';
|
||||
import { ResultSetDataAction } from '../../DatabaseDataModel/Actions/ResultSet/ResultSetDataAction';
|
||||
import { ResultSetSelectAction } from '../../DatabaseDataModel/Actions/ResultSet/ResultSetSelectAction';
|
||||
import { DataValuePanelService } from '../../TableViewer/ValuePanel/DataValuePanelService';
|
||||
import { ImageValuePresentation } from './ImageValuePresentation';
|
||||
|
||||
@injectable()
|
||||
export class ImageValuePresentationBootstrap extends Bootstrap {
|
||||
constructor(private readonly dataValuePanelService: DataValuePanelService) {
|
||||
super();
|
||||
}
|
||||
|
||||
register(): void | Promise<void> {
|
||||
this.dataValuePanelService.add({
|
||||
key: 'image-presentation',
|
||||
options: { dataFormat: [ResultDataFormat.Resultset] },
|
||||
name: 'data_viewer_presentation_value_image_title',
|
||||
order: 1,
|
||||
panel: () => ImageValuePresentation,
|
||||
isHidden: (_, context) => {
|
||||
if (!context || !context.model.source.hasResult(context.resultIndex)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const selection = context.model.source.getAction(context.resultIndex, ResultSetSelectAction);
|
||||
const data = context.model.source.getAction(context.resultIndex, ResultSetDataAction);
|
||||
|
||||
const selectedCells = selection.getSelectedElements();
|
||||
const focusedElement = selection.getFocusedElement();
|
||||
|
||||
if (selectedCells.length > 0 || focusedElement) {
|
||||
const firstSelectedCell = selectedCells[0] || focusedElement;
|
||||
return !this.isImage(data.getContent(firstSelectedCell));
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
load(): void { }
|
||||
|
||||
private isImage(value: IResultSetContentValue | null) {
|
||||
if (value !== null && 'binary' in value) {
|
||||
return getMIME(value.binary || '') !== null;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ import { manifest } from './manifest';
|
||||
|
||||
export default manifest;
|
||||
|
||||
export * from './DatabaseDataModel/Actions/ResultSet/IResultSetContentValue';
|
||||
export * from './DatabaseDataModel/Actions/ResultSet/IResultSetElementKey';
|
||||
export * from './DatabaseDataModel/Actions/ResultSet/ResultSetFormatAction';
|
||||
export * from './DatabaseDataModel/Actions/ResultSet/ResultSetSelectAction';
|
||||
|
||||
@@ -6,4 +6,5 @@ export default [
|
||||
['data_viewer_statistics_updated_rows', 'Updated Rows:'],
|
||||
['data_viewer_presentation_value_title', 'Value'],
|
||||
['data_viewer_presentation_value_text_title', 'Text'],
|
||||
['data_viewer_presentation_value_image_title', 'Image'],
|
||||
];
|
||||
|
||||
@@ -3,4 +3,5 @@ export default [
|
||||
['data_viewer_nodata_message', 'Нет данных для отображения'],
|
||||
['data_viewer_presentation_value_title', 'Значение'],
|
||||
['data_viewer_presentation_value_text_title', 'Текст'],
|
||||
['data_viewer_presentation_value_image_title', 'Изображение'],
|
||||
];
|
||||
|
||||
@@ -18,6 +18,7 @@ import { TableHeaderService } from './TableViewer/TableHeader/TableHeaderService
|
||||
import { TableViewerStorageService } from './TableViewer/TableViewerStorageService';
|
||||
import { DataValuePanelBootstrap } from './TableViewer/ValuePanel/DataValuePanelBootstrap';
|
||||
import { DataValuePanelService } from './TableViewer/ValuePanel/DataValuePanelService';
|
||||
import { ImageValuePresentationBootstrap } from './ValuePanelPresentation/ImageValue/ImageValuePresentationBootstrap';
|
||||
import { TextValuePresentationBootstrap } from './ValuePanelPresentation/TextValue/TextValuePresentationBootstrap';
|
||||
|
||||
export const manifest: PluginManifest = {
|
||||
@@ -36,6 +37,7 @@ export const manifest: PluginManifest = {
|
||||
LocaleService,
|
||||
DataValuePanelService,
|
||||
TextValuePresentationBootstrap,
|
||||
ImageValuePresentationBootstrap,
|
||||
DataValuePanelBootstrap,
|
||||
],
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user