Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,3 @@
bottom: 0;
right: 0;
}

.iconOrImage {
cursor: auto;
width: 10px;
position: absolute;
top: 50%;
transform: translateY(-50%);
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2025 DBeaver Corp and others
* Copyright (C) 2020-2026 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 { useContext } from 'react';

import { getComputed, IconOrImage, s, useS, useTranslate } from '@cloudbeaver/core-blocks';
import { s, useS, useTranslate } from '@cloudbeaver/core-blocks';

import { DataGridContext } from '../DataGridContext.js';
import { DataGridSelectionContext } from '../DataGridSelection/DataGridSelectionContext.js';
import { TableDataContext } from '../TableDataContext.js';
import style from './TableIndexColumnHeader.module.css';
import { TableStatusIndicator } from './TableStatusIndicator.js';

export const TableIndexColumnHeader = observer(function TableIndexColumnHeader() {
const dataGridContext = useContext(DataGridContext);
Expand All @@ -26,20 +27,14 @@ export const TableIndexColumnHeader = observer(function TableIndexColumnHeader()
throw new Error('Contexts required');
}

const readonly = getComputed(
() => dataGridContext.model.isReadonly(dataGridContext.resultIndex) || !dataGridContext.model.hasElementIdentifier(dataGridContext.resultIndex),
);

function handleClick(event: React.MouseEvent<HTMLDivElement>) {
function handleClick() {
selectionContext.selectTable();
dataGridContext.focus();
}

return (
<>
{readonly && (
<IconOrImage title={translate('data_grid_table_readonly_tooltip')} icon="/icons/lock.png" className={s(styles, { iconOrImage: true })} />
)}
<TableStatusIndicator readOnlyConnection={dataGridContext.model.isReadonly(dataGridContext.resultIndex)} />
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems like this prop not needed, component itself uses dataGridContext and can retrieve this information by itself

<div
role="button"
title={translate('data_grid_table_index_column_tooltip')}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2026 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 { SqlResultColumn } from '@cloudbeaver/core-sdk';
import { observer } from 'mobx-react-lite';
import { useContext } from 'react';
import { clsx } from '@dbeaver/ui-kit';

import { IconOrImage, useTranslate } from '@cloudbeaver/core-blocks';

import { DataGridContext } from '../DataGridContext.js';
import { TableDataContext } from '../TableDataContext.js';

interface Props {
readOnlyConnection: boolean;
}

const STATUS_COLOR = 'status';
const POSITIVE_COLOR = 'positive';
const INFO_COLOR = 'info';

export const TableStatusIndicator = observer<Props>(function TableStatusIndicator({ readOnlyConnection }) {
const dataGridContext = useContext(DataGridContext);
const tableDataContext = useContext(TableDataContext);
const translate = useTranslate();

if (!tableDataContext || !dataGridContext) {
return null;
}

const hasRowIdentifier = dataGridContext.model.hasElementIdentifier(dataGridContext.resultIndex);

const firstColumn = tableDataContext.columns[1];
const firstColumnData =
firstColumn?.key !== null && firstColumn?.key !== undefined
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
firstColumn?.key !== null && firstColumn?.key !== undefined
isNotNullDefined(firstColumn?.key)

? (tableDataContext.data.getColumn(firstColumn.key) as SqlResultColumn | undefined)
: undefined;
const readOnlyStatus = firstColumnData?.readOnlyStatus;

// TODO: Detect virtual keys when backend provides the information
const isVirtualKey = false;
const tooltipParts: string[] = [];

if (readOnlyConnection) {
tooltipParts.push(translate('data_grid_table_readonly_connection_tooltip'));
}

if (readOnlyStatus) {
if (!readOnlyConnection) {
tooltipParts.push(translate('data_grid_table_readonly_tooltip'));
}
tooltipParts.push(readOnlyStatus);
}

if (hasRowIdentifier) {
// TEMPORARY: Detect primary key by checking for required and not read-only columns
// TODO: Remove when backend provides the information
const pkColumn = tableDataContext.columns.find(col => {
const colData = col.key && (tableDataContext.data.getColumn(col.key) as SqlResultColumn | undefined);
return colData?.required && !colData?.readOnly;
})?.key;

if (pkColumn) {
tooltipParts.push(`Unique key: ${(tableDataContext.data.getColumn(pkColumn) as SqlResultColumn | undefined)?.name}`);
}
}
Comment on lines +48 to +70
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'm not sure that it's good idea to try to implement this logic on frontend, because it might be different from dbeaver or incomplete


const tooltip = tooltipParts.join('\n');

let themeColor = STATUS_COLOR;
if (hasRowIdentifier && !isVirtualKey) {
themeColor = POSITIVE_COLOR;
} else if (isVirtualKey) {
themeColor = INFO_COLOR;
}

return (
<div
title={tooltip}
className="tw:absolute tw:top-1/2 tw:left-1 tw:-translate-y-1/2 tw:z-1 tw:pointer-events-auto tw:flex tw:items-center tw:gap-1 tw:cursor-help"
>
{readOnlyConnection && <IconOrImage icon="/icons/lock.png" className="tw:w-2.5 tw:cursor-help" />}
<div
className={clsx(
'tw:w-3 tw:h-3 tw:rounded-full tw:shrink-0 tw:bg-transparent tw:border',
"tw:before:content-[''] tw:before:block tw:before:w-1.5 tw:before:h-1.5 tw:before:rounded-full tw:before:m-0.5",
`tw:border-(--theme-${themeColor}) tw:before:bg-(--theme-${themeColor})`,
)}
/>
Comment on lines +87 to +93
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we really need to always show this indicator? if table is normal table without restrictions and limitations, what the purpose of this indicator?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image To show the primary key of a table

</div>
);
});
2 changes: 2 additions & 0 deletions webapp/packages/plugin-data-spreadsheet-new/src/locales/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ export default [
['data_grid_table_context_menu_filter_dialog_title', 'Wert bearbeiten'],
['data_grid_table_index_column_tooltip', 'Wählen ganze Tabelle aus'],
['data_grid_table_readonly_tooltip', 'Schreibgeschützt'],
['data_grid_table_readonly_connection_tooltip', 'Schreibgeschützte Verbindung'],
['data_grid_table_no_key_found_tooltip', 'Kein eindeutiger Schlüssel gefunden. Datenänderung nicht möglich.'],
['plugin_data_spreadsheet_new_settings_disable', 'Tabellenpräsentation deaktivieren'],
['plugin_data_spreadsheet_new_settings_disable_description', 'Deaktivieren Sie die Tabellenpräsentation von Daten für alle Benutzer'],
['plugin_data_spreadsheet_new_settings_description_label', 'Show columns description'],
Expand Down
2 changes: 2 additions & 0 deletions webapp/packages/plugin-data-spreadsheet-new/src/locales/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ export default [
['data_grid_table_context_menu_save_value_error', 'Failed to save value'],
['data_grid_table_index_column_tooltip', 'Select whole table'],
['data_grid_table_readonly_tooltip', 'Read-only'],
['data_grid_table_readonly_connection_tooltip', 'Read-only connection'],
['data_grid_table_no_key_found_tooltip', 'No unique key was found. Data modification is not possible.'],
['plugin_data_spreadsheet_new_settings_disable', 'Disable Table presentation'],
['plugin_data_spreadsheet_new_settings_disable_description', 'Disable table presentation of data for all users'],
['plugin_data_spreadsheet_new_settings_description_label', 'Show columns description'],
Expand Down
2 changes: 2 additions & 0 deletions webapp/packages/plugin-data-spreadsheet-new/src/locales/fr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ export default [
['data_grid_table_context_menu_filter_clipboard_permission', 'Donner accès au presse-papiers'],
['data_grid_table_context_menu_save_value_error', 'Échec de la sauvegarde de la valeur'],
['data_grid_table_index_column_tooltip', 'Sélectionner toute la table'],
['data_grid_table_no_key_found_tooltip', "Aucune clé unique n'a été trouvée. La modification des données n'est pas possible."],
['data_grid_table_readonly_tooltip', 'Lecture seule'],
['data_grid_table_readonly_connection_tooltip', 'Connexion en lecture seule'],
['plugin_data_spreadsheet_new_settings_disable', 'Désactiver la présentation de la table'],
['plugin_data_spreadsheet_new_settings_description_label', 'Show columns description'],
['plugin_data_spreadsheet_new_settings_description_label_description', 'Description will be shown under the column names in the table header'],
Expand Down
11 changes: 8 additions & 3 deletions webapp/packages/plugin-data-spreadsheet-new/src/locales/it.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,12 @@ export default [
['data_grid_table_context_menu_save_value_error', 'Failed to save value'],
['data_grid_table_index_column_tooltip', 'Seleziona tutta la tabella'],
['data_grid_table_readonly_tooltip', 'In sola lettura'],
['plugin_data_spreadsheet_new_settings_disable', 'Disable Table presentation'],
['plugin_data_spreadsheet_new_settings_description_label', 'Show columns description'],
['plugin_data_spreadsheet_new_settings_description_label_description', 'Description will be shown under the column names in the table header'],
['data_grid_table_readonly_connection_tooltip', 'Connessione in sola lettura'],
['data_grid_table_no_key_found_tooltip', 'Nessuna chiave univoca è stata trovata. La modifica dei dati non è possibile.'],
['plugin_data_spreadsheet_new_settings_disable', 'Disabilita la presentazione della tabella'],
['plugin_data_spreadsheet_new_settings_description_label', 'Mostra la descrizione delle colonne'],
[
'plugin_data_spreadsheet_new_settings_description_label_description',
"La descrizione verrà mostrata sotto i nomi delle colonne nell'intestazione della tabella",
],
];
2 changes: 2 additions & 0 deletions webapp/packages/plugin-data-spreadsheet-new/src/locales/ru.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ export default [
['data_grid_table_context_menu_save_value_error', 'Не удалось сохранить значение'],
['data_grid_table_index_column_tooltip', 'Выбрать всю таблицу'],
['data_grid_table_readonly_tooltip', 'Доступно только для чтения'],
['data_grid_table_readonly_connection_tooltip', 'Подключение только для чтения'],
['data_grid_table_no_key_found_tooltip', 'Не найден уникальный ключ. Изменение данных невозможно.'],
['plugin_data_spreadsheet_new_settings_disable', 'Отключить табличное представление'],
['plugin_data_spreadsheet_new_settings_disable_description', 'Отключить табличное представление данных для всех пользователей'],
['plugin_data_spreadsheet_new_settings_description_label', 'Показать описание колонки'],
Expand Down
6 changes: 4 additions & 2 deletions webapp/packages/plugin-data-spreadsheet-new/src/locales/vi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@ export default [
['data_grid_table_context_menu_save_value_error', 'Không thể lưu giá trị'],
['data_grid_table_index_column_tooltip', 'Chọn toàn bộ bảng'],
['data_grid_table_readonly_tooltip', 'Chỉ đọc'],
['data_grid_table_readonly_connection_tooltip', 'Kết nối chỉ đọc'],
['data_grid_table_no_key_found_tooltip', 'Không tìm thấy khóa duy nhất. Không thể sửa đổi dữ liệu.'],
['plugin_data_spreadsheet_new_settings_disable', 'Tắt chế độ hiển thị dạng bảng'],
['plugin_data_spreadsheet_new_settings_disable_description', 'Tắt chế độ hiển thị dữ liệu dạng bảng cho tất cả người dùng'],
['plugin_data_spreadsheet_new_settings_description_label', 'Show columns description'],
['plugin_data_spreadsheet_new_settings_description_label_description', 'Description will be shown under the column names in the table header'],
['plugin_data_spreadsheet_new_settings_description_label', 'Hiển thị mô tả cột'],
['plugin_data_spreadsheet_new_settings_description_label_description', 'Mô tả sẽ được hiển thị dưới tên các cột trong tiêu đề bảng'],
];
6 changes: 4 additions & 2 deletions webapp/packages/plugin-data-spreadsheet-new/src/locales/zh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@ export default [
['data_grid_table_context_menu_filter_clipboard_permission', '授予访问剪贴板的权限'],
['data_grid_table_context_menu_save_value_error', '保存失败'],
['data_grid_table_index_column_tooltip', '选择整个表'],
['data_grid_table_no_key_found_tooltip', '未找到唯一键。无法修改数据。'],
['data_grid_table_readonly_tooltip', '只读'],
['data_grid_table_readonly_connection_tooltip', '只读连接'],
['plugin_data_spreadsheet_new_settings_disable', '禁用表显示'],
['plugin_data_spreadsheet_new_settings_description_label', 'Show columns description'],
['plugin_data_spreadsheet_new_settings_description_label_description', 'Description will be shown under the column names in the table header'],
['plugin_data_spreadsheet_new_settings_description_label', '显示列描述'],
['plugin_data_spreadsheet_new_settings_description_label_description', '描述将显示在表头的列名下方'],
];
Loading