mirror of
https://github.com/dbeaver/cloudbeaver.git
synced 2026-09-24 16:04:36 +08:00
CB-5181 Display User Notification Pop-up When Copy/Paste Functionality is Disabled by Administrator (#2730)
* CB-5181 adds copy event handler for data viewer (cells, value panel) * CB-5181 makes edit/copy settings independent from each other * CB-5181 adds disable copy case for read state JsonLine (pre) * CB-5181 changes message text for popup * CB-5181 changes message text for popup 2 * СB-5181 fixes rus locale for copy message --------- Co-authored-by: Evgenia Bezborodova <139753579+EvgeniaBzzz@users.noreply.github.com>
This commit is contained in:
co-authored by
Evgenia Bezborodova
parent
4078b6aa16
commit
4842cba903
@@ -22,7 +22,7 @@ export interface IReactCodeMirrorProps extends React.PropsWithChildren {
|
||||
getValue?: () => string;
|
||||
extensions?: Map<Compartment, Extension>;
|
||||
readonly?: boolean;
|
||||
disableCopy?: boolean;
|
||||
copyEventHandler?: (event: ClipboardEvent) => boolean;
|
||||
autoFocus?: boolean;
|
||||
onChange?: (value: string, update: ViewUpdate) => void;
|
||||
onCursorChange?: (selection: SelectionRange, update: ViewUpdate) => void;
|
||||
|
||||
@@ -31,7 +31,7 @@ export const ReactCodemirror = observer<IReactCodeMirrorProps, IEditorRef>(
|
||||
incomingValue,
|
||||
extensions = new Map<Compartment, Extension>(),
|
||||
readonly,
|
||||
disableCopy,
|
||||
copyEventHandler,
|
||||
autoFocus,
|
||||
onChange,
|
||||
onCursorChange,
|
||||
@@ -45,11 +45,9 @@ export const ReactCodemirror = observer<IReactCodeMirrorProps, IEditorRef>(
|
||||
const eventHandlers = useMemo(
|
||||
() =>
|
||||
EditorView.domEventHandlers({
|
||||
copy() {
|
||||
return disableCopy;
|
||||
},
|
||||
copy: copyEventHandler,
|
||||
}),
|
||||
[disableCopy],
|
||||
[copyEventHandler],
|
||||
);
|
||||
extensions = useCodemirrorExtensions(extensions, [readOnlyFacet, eventHandlers]);
|
||||
const [container, setContainer] = useState<HTMLDivElement | null>(null);
|
||||
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
IResultSetElementKey,
|
||||
ResultSetDataKeysUtils,
|
||||
ResultSetSelectAction,
|
||||
useDataViewerCopyHandler,
|
||||
} from '@cloudbeaver/plugin-data-viewer';
|
||||
|
||||
import type { IDataGridSelectionContext } from './DataGridSelection/DataGridSelectionContext';
|
||||
@@ -71,6 +72,7 @@ export function useGridSelectedCellsCopy(
|
||||
) {
|
||||
const dataViewerService = useService(DataViewerService);
|
||||
const props = useObjectRef({ tableData, selectionContext, resultSetSelectAction });
|
||||
const copyEventHandler = useDataViewerCopyHandler();
|
||||
|
||||
const onKeydownHandler = useCallback((event: React.KeyboardEvent) => {
|
||||
if ((event.ctrlKey || event.metaKey) && event.nativeEvent.code === EVENT_KEY_CODE.C) {
|
||||
@@ -98,6 +100,8 @@ export function useGridSelectedCellsCopy(
|
||||
copyToClipboard(value);
|
||||
}
|
||||
}
|
||||
|
||||
copyEventHandler(event);
|
||||
}
|
||||
}, []);
|
||||
|
||||
|
||||
@@ -14,11 +14,7 @@ import { DataViewerSettingsService } from './DataViewerSettingsService';
|
||||
@injectable()
|
||||
export class DataViewerService {
|
||||
get canCopyData() {
|
||||
if (this.sessionPermissionsResource.has(EAdminPermission.admin)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return !this.dataViewerSettingsService.disableCopyData;
|
||||
return this.sessionPermissionsResource.has(EAdminPermission.admin) || !this.dataViewerSettingsService.disableCopyData;
|
||||
}
|
||||
|
||||
constructor(
|
||||
|
||||
+3
-4
@@ -8,10 +8,9 @@
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
import { useService } from '@cloudbeaver/core-di';
|
||||
import { EditorLoader, useCodemirrorExtensions } from '@cloudbeaver/plugin-codemirror6';
|
||||
|
||||
import { DataViewerService } from '../../DataViewerService';
|
||||
import { useDataViewerCopyHandler } from '../../useDataViewerCopyHandler';
|
||||
import { getTypeExtension } from './getTypeExtension';
|
||||
|
||||
interface Props {
|
||||
@@ -27,7 +26,7 @@ export const TextValueEditor = observer<Props>(function TextValueEditor({ conten
|
||||
const typeExtension = useMemo(() => getTypeExtension(contentType!) ?? [], [contentType]);
|
||||
|
||||
const extensions = useCodemirrorExtensions(undefined, typeExtension);
|
||||
const dataViewerService = useService(DataViewerService);
|
||||
const copyEventHandler = useDataViewerCopyHandler();
|
||||
|
||||
return (
|
||||
<EditorLoader
|
||||
@@ -35,7 +34,7 @@ export const TextValueEditor = observer<Props>(function TextValueEditor({ conten
|
||||
lineWrapping={lineWrapping}
|
||||
readonly={readonly}
|
||||
extensions={extensions}
|
||||
disableCopy={!dataViewerService.canCopyData}
|
||||
copyEventHandler={copyEventHandler}
|
||||
onChange={onChange}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -85,5 +85,6 @@ export * from './ResultSetDataSource';
|
||||
export * from './DataPresentationService';
|
||||
export * from './DataViewerDataChangeConfirmationService';
|
||||
export * from './ValuePanelPresentation/BooleanValue/isBooleanValuePresentationAvailable';
|
||||
export * from './useDataViewerCopyHandler';
|
||||
export * from './DataViewerSettingsService';
|
||||
export * from './DATA_EDITOR_SETTINGS_GROUP';
|
||||
|
||||
@@ -34,6 +34,8 @@ export default [
|
||||
['data_viewer_script_preview_error_title', 'Kann das Skript nicht bekommen'],
|
||||
['data_viewer_total_count_tooltip', 'Totalzahl erhalten'],
|
||||
['data_viewer_model_not_loaded', 'Das Tabellenmodell ist nicht geladen'],
|
||||
['data_viewer_copy_not_allowed', 'An ability to copy data is disabled'],
|
||||
['data_viewer_copy_not_allowed_message', 'If this was unexpected, contact the administrator'],
|
||||
['settings_data_editor', 'Dateneditor'],
|
||||
['settings_data_editor_disable_edit_name', 'Bearbeiten deaktivieren'],
|
||||
['settings_data_editor_disable_edit_description', 'Deaktivieren Sie die Bearbeitung von Daten in Data Viewer für Nicht-Admin-Benutzer'],
|
||||
|
||||
@@ -57,6 +57,8 @@ export default [
|
||||
['data_viewer_total_count_canceled_message', 'Statement was cancelled due to user request'],
|
||||
['data_viewer_total_count_failed', 'Failed to get total count'],
|
||||
['data_viewer_model_not_loaded', 'Table model is not loaded'],
|
||||
['data_viewer_copy_not_allowed', 'An ability to copy data is disabled'],
|
||||
['data_viewer_copy_not_allowed_message', 'If this was unexpected, contact the administrator'],
|
||||
['settings_data_editor', 'Data Editor'],
|
||||
['settings_data_editor_disable_edit_name', 'Disable Edit'],
|
||||
['settings_data_editor_disable_edit_description', 'Disable editing of data in Data Viewer for non-admin users'],
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
export default [
|
||||
['plugin_data_viewer_data_viewer_settings_group', 'Affichage des données'],
|
||||
['table_header_sql_expression', 'Entrez une expression SQL pour filtrer les résultats, par exemple column_name=10'],
|
||||
['table_header_sql_expression_not_supported', 'Le filtrage des données n\'est pas supporté'],
|
||||
['table_header_sql_expression_not_supported', "Le filtrage des données n'est pas supporté"],
|
||||
['data_viewer_tab_title', 'Données'],
|
||||
['data_viewer_value_edit', 'Modifier'],
|
||||
['data_viewer_value_apply', 'Appliquer'],
|
||||
@@ -20,16 +20,16 @@ export default [
|
||||
['data_viewer_statistics_updated_rows', 'Lignes mises à jour :'],
|
||||
['data_viewer_action_refresh', 'Actualiser'],
|
||||
['data_viewer_action_auto_refresh', 'Actualisation automatique'],
|
||||
['data_viewer_action_auto_refresh_stop', 'Arrêter l\'actualisation automatique'],
|
||||
['data_viewer_action_auto_refresh_stop', "Arrêter l'actualisation automatique"],
|
||||
['data_viewer_action_edit_delete', 'Supprimer la sélection'],
|
||||
['data_viewer_action_edit_add', 'Ajouter'],
|
||||
['data_viewer_action_edit_add_copy', 'Dupliquer'],
|
||||
['data_viewer_action_edit_revert', 'Annuler la sélection'],
|
||||
['data_viewer_result_edited_title', 'Enregistrer les modifications'],
|
||||
['data_viewer_result_edited_message', 'Le jeu de résultats a été modifié. Voulez-vous enregistrer les modifications dans la base de données ?'],
|
||||
['data_viewer_data_save_error_title', 'Erreur lors de l\'enregistrement des modifications'],
|
||||
['data_viewer_auto_refresh_settings', 'Paramètres d\'actualisation automatique'],
|
||||
['data_viewer_auto_refresh_settings_stop_on_error', 'Arrêter en cas d\'erreur'],
|
||||
['data_viewer_data_save_error_title', "Erreur lors de l'enregistrement des modifications"],
|
||||
['data_viewer_auto_refresh_settings', "Paramètres d'actualisation automatique"],
|
||||
['data_viewer_auto_refresh_settings_stop_on_error', "Arrêter en cas d'erreur"],
|
||||
['data_viewer_presentation_value_title', 'Valeur'],
|
||||
['data_viewer_presentation_value_text_line_wrapping_wrap', 'Retour à la ligne'],
|
||||
['data_viewer_presentation_value_text_line_wrapping_no_wrap', 'Ne pas revenir à la ligne'],
|
||||
@@ -42,25 +42,30 @@ export default [
|
||||
['data_viewer_presentation_value_text_base64_title', 'Base64'],
|
||||
['data_viewer_presentation_value_image_title', 'Image'],
|
||||
['data_viewer_presentation_value_image_fit', 'Ajuster à la fenêtre'],
|
||||
['data_viewer_presentation_value_image_original_size', 'Taille d\'origine'],
|
||||
['data_viewer_presentation_value_boolean_placeholder', 'Impossible d\'afficher la valeur actuelle en tant que booléen'],
|
||||
['data_viewer_presentation_value_image_original_size', "Taille d'origine"],
|
||||
['data_viewer_presentation_value_boolean_placeholder', "Impossible d'afficher la valeur actuelle en tant que booléen"],
|
||||
['data_viewer_presentation_value_content_truncated_placeholder', 'La valeur a été tronquée en raison de la'],
|
||||
['data_viewer_presentation_value_content_download_error', 'Échec du téléchargement'],
|
||||
['data_viewer_presentation_value_content_paste_error', 'Impossible de charger le texte complet'],
|
||||
['data_viewer_script_preview', 'Script'],
|
||||
['data_viewer_script_preview_dialog_title', 'Aperçu des modifications'],
|
||||
['data_viewer_script_preview_error_title', 'Impossible d\'obtenir le script'],
|
||||
['data_viewer_script_preview_error_title', "Impossible d'obtenir le script"],
|
||||
['data_viewer_refresh_result_set', 'Actualiser le jeu de résultats'],
|
||||
['data_viewer_total_count_tooltip', 'Obtenir le compte total'],
|
||||
['data_viewer_total_count_canceled_title', 'Total annulé'],
|
||||
['data_viewer_total_count_canceled_message', 'La déclaration a été annulée à la demande de l\'utilisateur'],
|
||||
['data_viewer_total_count_failed', 'Échec de l\'obtention du compte total'],
|
||||
['data_viewer_model_not_loaded', 'Le modèle de la table n\'est pas chargé'],
|
||||
['data_viewer_total_count_canceled_message', "La déclaration a été annulée à la demande de l'utilisateur"],
|
||||
['data_viewer_total_count_failed', "Échec de l'obtention du compte total"],
|
||||
['data_viewer_model_not_loaded', "Le modèle de la table n'est pas chargé"],
|
||||
['data_viewer_copy_not_allowed', 'An ability to copy data is disabled'],
|
||||
['data_viewer_copy_not_allowed_message', 'If this was unexpected, contact the administrator'],
|
||||
['settings_data_editor', 'Éditeur de données'],
|
||||
['settings_data_editor_disable_edit_name', 'Désactiver l\'édition'],
|
||||
['settings_data_editor_disable_edit_description', 'Désactiver l\'édition des données dans le Data Viewer pour les utilisateurs non administrateurs'],
|
||||
['settings_data_editor_disable_edit_name', "Désactiver l'édition"],
|
||||
['settings_data_editor_disable_edit_description', "Désactiver l'édition des données dans le Data Viewer pour les utilisateurs non administrateurs"],
|
||||
['settings_data_editor_disable_data_copy_name', 'Désactiver la copie'],
|
||||
['settings_data_editor_disable_data_copy_description', 'Désactiver la copie des données dans le Data Viewer pour les utilisateurs non administrateurs'],
|
||||
[
|
||||
'settings_data_editor_disable_data_copy_description',
|
||||
'Désactiver la copie des données dans le Data Viewer pour les utilisateurs non administrateurs',
|
||||
],
|
||||
['settings_data_editor_fetch_min_name', 'Taille de récupération minimale'],
|
||||
['settings_data_editor_fetch_min_description', 'Nombre minimal de lignes à récupérer'],
|
||||
['settings_data_editor_fetch_max_name', 'Taille de récupération maximale'],
|
||||
|
||||
@@ -50,6 +50,8 @@ export default [
|
||||
['data_viewer_total_count_canceled_message', 'Statement was cancelled due to user request'],
|
||||
['data_viewer_total_count_failed', 'Failed to get total count'],
|
||||
['data_viewer_model_not_loaded', 'Table model is not loaded'],
|
||||
['data_viewer_copy_not_allowed', 'An ability to copy data is disabled'],
|
||||
['data_viewer_copy_not_allowed_message', 'If this was unexpected, contact the administrator'],
|
||||
['settings_data_editor', 'Data Editor'],
|
||||
['settings_data_editor_disable_edit_name', 'Disable Edit'],
|
||||
['settings_data_editor_disable_edit_description', 'Disable editing of data in Data Viewer for non-admin users'],
|
||||
|
||||
@@ -51,6 +51,8 @@ export default [
|
||||
['data_viewer_total_count_canceled_message', 'Запрос был отменен пользователем'],
|
||||
['data_viewer_total_count_failed', 'Не удалось получить количество записей'],
|
||||
['data_viewer_model_not_loaded', 'Не удалось загрузить модель таблицы'],
|
||||
['data_viewer_copy_not_allowed', 'Копирование отключено'],
|
||||
['data_viewer_copy_not_allowed_message', 'Если это не ожидаемо, обратитесь к администратору'],
|
||||
['settings_data_editor', 'Редактор данных'],
|
||||
['settings_data_editor_disable_edit_name', 'Отключить редактирование'],
|
||||
['settings_data_editor_disable_edit_description', 'Отключить редактирование данных для пользователей без прав администратора'],
|
||||
|
||||
@@ -57,6 +57,8 @@ export default [
|
||||
['data_viewer_total_count_canceled_title', 'Total count canceled'],
|
||||
['data_viewer_total_count_canceled_message', 'Statement was cancelled due to user request'],
|
||||
['data_viewer_model_not_loaded', 'Table model is not loaded'],
|
||||
['data_viewer_copy_not_allowed', 'An ability to copy data is disabled'],
|
||||
['data_viewer_copy_not_allowed_message', 'If this was unexpected, contact the administrator'],
|
||||
['settings_data_editor', 'Data Editor'],
|
||||
['settings_data_editor_disable_edit_name', 'Disable Edit'],
|
||||
['settings_data_editor_disable_edit_description', 'Disable editing of data in Data Viewer for non-admin users'],
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* CloudBeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020-2024 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 React from 'react';
|
||||
|
||||
import { useService } from '@cloudbeaver/core-di';
|
||||
import { NotificationService } from '@cloudbeaver/core-events';
|
||||
|
||||
import { DataViewerService } from './DataViewerService';
|
||||
|
||||
export function useDataViewerCopyHandler() {
|
||||
const notificationService = useService(NotificationService);
|
||||
const dataViewerService = useService(DataViewerService);
|
||||
|
||||
return function (event?: ClipboardEvent | React.KeyboardEvent | React.ClipboardEvent) {
|
||||
if (!dataViewerService.canCopyData) {
|
||||
event?.preventDefault();
|
||||
|
||||
notificationService.logError({
|
||||
title: 'data_viewer_copy_not_allowed',
|
||||
message: 'data_viewer_copy_not_allowed_message',
|
||||
});
|
||||
}
|
||||
|
||||
return !dataViewerService.canCopyData;
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user