Skip to content

Commit f065bae

Browse files
Add copyToClipboard button to Text View and Documentation View (#885)
* Add copyToClipboard button to Text View and Documentation View * update copy to clipboard button color and remove from documentation view * apply formatting changes --------- Co-authored-by: Felix Neubauer <[email protected]> Co-authored-by: Logende <[email protected]>
1 parent 5dc11e4 commit f065bae

10 files changed

Lines changed: 120 additions & 9 deletions

File tree

meta_configurator/src/components/panels/ai-prompts/AiPromptsPanel.vue

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ const props = defineProps<{
1515

1616
<template>
1717
<div class="panel-container">
18-
<PanelSettings panel-name="AI Prompts View" :panel-settings-path="['aiIntegration']">
18+
<PanelSettings
19+
panel-name="AI Prompts View"
20+
:panel-settings-path="['aiIntegration']"
21+
:sessionMode="props.sessionMode">
1922
<p>
2023
This panel allows you to manage AI prompts for the current document. You can define prompts
2124
for schema generation, data manipulation, and other AI-related tasks.

meta_configurator/src/components/panels/code-editor/CodeEditorPanel.vue

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
<template>
22
<div class="panel-container">
3-
<PanelSettings panel-name="Text View" :panel-settings-path="['codeEditor']">
3+
<PanelSettings
4+
panel-name="Text View"
5+
:panel-settings-path="['codeEditor']"
6+
:sessionMode="props.sessionMode">
47
<p>
58
This panel allows you to view and edit the raw JSON/YAML/XML data of the current document.
69
It is useful for advanced users who want to directly manipulate the data structure.

meta_configurator/src/components/panels/documentation/DocumentationPanel.vue

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,10 @@ onUnmounted(() => docsRef.value?.removeEventListener('click', onAnchorClick));
9595

9696
<template>
9797
<div class="panel-container">
98-
<PanelSettings panel-name="Documentation View" :panel-settings-path="['documentation']">
98+
<PanelSettings
99+
panel-name="Documentation View"
100+
:panel-settings-path="['documentation']"
101+
:sessionMode="props.sessionMode">
99102
<p>
100103
This panel provides documentation for the current schema. It is generated from the schema
101104
itself and includes details about properties, types, and descriptions.

meta_configurator/src/components/panels/gui-editor/GuiEditorPanel.vue

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@ const props = defineProps<{
1717
<template>
1818
<div class="panel-container">
1919
<div class="gui-panel">
20-
<PanelSettings panel-name="GUI View" :panel-settings-path="['guiEditor']">
20+
<PanelSettings
21+
panel-name="GUI View"
22+
:panel-settings-path="['guiEditor']"
23+
:sessionMode="props.sessionMode">
2124
<p>
2225
This panel allows you to view and edit the current document in a GUI format. You can
2326
navigate through the document tree, view properties, and modify data directly.

meta_configurator/src/components/panels/list-analysis/ListAnalysisPanel.vue

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,10 @@ function exportTableAsCsv() {
8383

8484
<template>
8585
<div class="panel-container">
86-
<PanelSettings panel-name="Table View" :panel-settings-path="['listAnalysis']">
86+
<PanelSettings
87+
panel-name="Table View"
88+
:panel-settings-path="['listAnalysis']"
89+
:sessionMode="props.sessionMode">
8790
<p>
8891
This panel allows you to analyze object arrays in the current document. Select an object
8992
array to view its contents in a table format.

meta_configurator/src/components/panels/schema-diagram/SchemaDiagramPanel.vue

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ const props = defineProps<{
99
</script>
1010

1111
<template>
12-
<PanelSettings panel-name="Diagram View" :panel-settings-path="['schemaDiagram']">
12+
<PanelSettings
13+
panel-name="Diagram View"
14+
:panel-settings-path="['schemaDiagram']"
15+
:sessionMode="props.sessionMode">
1316
<p>
1417
This panel provides a visual representation of the current schema as a diagram. You can
1518
explore the structure of the schema, view relationships between different elements, and

meta_configurator/src/components/panels/shared-components/PanelSettings.vue

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {computed} from 'vue';
77
import type {Path} from '@/utility/path';
88
import {SessionMode} from '@/store/sessionMode';
99
import Panel from 'primevue/panel';
10+
import Button from 'primevue/button';
1011
import PropertiesPanel from '@/components/panels/gui-editor/PropertiesPanel.vue';
1112
import {JsonSchemaWrapper} from '@/schema/jsonSchemaWrapper';
1213
import {getDataForMode, getSchemaForMode} from '@/data/useDataLink';
@@ -15,6 +16,7 @@ const props = defineProps<{
1516
panelName: string;
1617
settingsHeader?: string;
1718
panelSettingsPath: Path;
19+
sessionMode: SessionMode;
1820
}>();
1921
2022
const schema = getSchemaForMode(SessionMode.Settings);
@@ -36,6 +38,21 @@ function removeProperty(path: Path) {
3638
data.removeDataAt(path);
3739
}
3840
41+
const copyToClipboard = async () => {
42+
if (props.sessionMode === SessionMode.Settings) return;
43+
44+
try {
45+
const text = getDataForMode(props.sessionMode).unparsedData.value;
46+
await navigator.clipboard.writeText(text);
47+
} catch (err) {
48+
console.error('Failed to copy: ', err);
49+
}
50+
};
51+
52+
const containsText = computed(() => {
53+
return ['Text View'].includes(props.panelName);
54+
});
55+
3956
const settingsName = computed(() => {
4057
if (props.settingsHeader && props.settingsHeader !== '') {
4158
return props.settingsHeader;
@@ -52,8 +69,10 @@ const settingsName = computed(() => {
5269

5370
<template>
5471
<Panel :header="panelName" toggleable :collapsed="true">
72+
<template v-if="containsText" #icons>
73+
<Button icon="pi pi-clone" severity="secondary" @click="copyToClipboard" rounded text />
74+
</template>
5575
<slot></slot>
56-
5776
<div class="properties-panel-container">
5877
<PropertiesPanel
5978
v-if="currentSchema.jsonSchema"
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import {describe, it, expect, vi, beforeEach} from 'vitest';
2+
import {mount, flushPromises} from '@vue/test-utils';
3+
import {defineComponent} from 'vue';
4+
import PanelSettings from '../PanelSettings.vue';
5+
import {SessionMode} from '@/store/sessionMode';
6+
7+
vi.mock('@/data/useDataLink', async () => {
8+
const vue = await import('vue');
9+
const stubData = {
10+
setDataAt: vi.fn(),
11+
removeDataAt: vi.fn(),
12+
dataAt: vi.fn(),
13+
unparsedData: vue.ref('clipboard text'),
14+
};
15+
const stubSchema = {
16+
effectiveSchemaAtPath: vi.fn(() => ({
17+
schema: {
18+
jsonSchema: {},
19+
},
20+
})),
21+
};
22+
23+
return {
24+
getDataForMode: vi.fn(() => stubData),
25+
getSchemaForMode: vi.fn(() => stubSchema),
26+
};
27+
});
28+
29+
const PanelStub = defineComponent({
30+
template: '<div><slot name="icons" /><slot /></div>',
31+
});
32+
33+
const ButtonStub = defineComponent({
34+
template: '<button type="button" @click="$emit(\'click\')"></button>',
35+
});
36+
37+
const PropertiesPanelStub = defineComponent({
38+
template: '<div />',
39+
});
40+
41+
describe('PanelSettings', () => {
42+
beforeEach(() => {
43+
Object.assign(navigator, {
44+
clipboard: {
45+
writeText: vi.fn().mockResolvedValue(undefined),
46+
},
47+
});
48+
});
49+
50+
it('copies panel content to the clipboard when the copy button is clicked', async () => {
51+
const wrapper = mount(PanelSettings, {
52+
props: {
53+
panelName: 'Text View',
54+
panelSettingsPath: [],
55+
sessionMode: SessionMode.DataEditor,
56+
},
57+
global: {
58+
stubs: {
59+
Panel: PanelStub,
60+
Button: ButtonStub,
61+
PropertiesPanel: PropertiesPanelStub,
62+
},
63+
},
64+
});
65+
66+
await wrapper.get('button').trigger('click');
67+
await flushPromises();
68+
69+
const clipboard = navigator.clipboard as Clipboard;
70+
expect(clipboard.writeText).toHaveBeenCalledWith('clipboard text');
71+
});
72+
});

meta_configurator/src/components/toolbar/dialogs/data-export/DataExportDialog.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,8 @@ defineExpose({show: openDialog, close: hideDialog, activateSchemaMode, activateD
119119
<PanelSettings
120120
panel-name="API Key and AI Settings"
121121
settings-header="AI Settings"
122-
:panel-settings-path="['aiIntegration']">
122+
:panel-settings-path="['aiIntegration']"
123+
:sessionMode="SessionMode.DataEditor">
123124
<ApiKey />
124125
</PanelSettings>
125126
<ApiKeyWarning />

meta_configurator/src/components/toolbar/dialogs/data-mapping/DataMappingDialog.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,8 @@ defineExpose({show: openDialog, close: hideDialog});
209209
<PanelSettings
210210
panel-name="API Key and AI Settings"
211211
settings-header="AI Settings"
212-
:panel-settings-path="['aiIntegration']">
212+
:panel-settings-path="['aiIntegration']"
213+
:sessionMode="SessionMode.DataEditor">
213214
<ApiKey />
214215
</PanelSettings>
215216
<ApiKeyWarning />

0 commit comments

Comments
 (0)