@mongoosejs/studio 0.2.13 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/backend/actions/ChatMessage/executeScript.js +5 -1
- package/backend/actions/ChatThread/createChatMessage.js +4 -1
- package/backend/actions/ChatThread/streamChatMessage.js +4 -2
- package/backend/actions/Dashboard/updateDashboard.js +2 -2
- package/backend/actions/Task/getTaskOverview.js +102 -0
- package/backend/actions/Task/getTasks.js +85 -45
- package/backend/actions/Task/index.js +1 -0
- package/eslint.config.js +4 -1
- package/frontend/public/app.js +25025 -762
- package/frontend/public/dark-theme.css +365 -0
- package/frontend/public/images/mongoose-studio.svg +4 -0
- package/frontend/public/index.html +21 -1
- package/frontend/public/style.css +5 -7
- package/frontend/public/theme-variables.css +294 -0
- package/frontend/public/tw.css +348 -213
- package/frontend/src/_util/dateRange.js +82 -0
- package/frontend/src/ace-editor/ace-editor.html +4 -0
- package/frontend/src/ace-editor/ace-editor.js +95 -0
- package/frontend/src/aceEditor.js +69 -0
- package/frontend/src/api.js +6 -0
- package/frontend/src/chat/chat-message/chat-message.html +1 -1
- package/frontend/src/chat/chat-message/chat-message.js +1 -1
- package/frontend/src/chat/chat-message-script/chat-message-script.html +54 -42
- package/frontend/src/chat/chat-message-script/chat-message-script.js +6 -55
- package/frontend/src/chat/chat.html +68 -39
- package/frontend/src/chat/chat.js +26 -2
- package/frontend/src/clone-document/clone-document.html +7 -2
- package/frontend/src/clone-document/clone-document.js +1 -8
- package/frontend/src/create-dashboard/create-dashboard.html +11 -6
- package/frontend/src/create-dashboard/create-dashboard.js +0 -7
- package/frontend/src/create-document/create-document.html +15 -9
- package/frontend/src/create-document/create-document.js +5 -12
- package/frontend/src/dashboard/dashboard.html +14 -12
- package/frontend/src/dashboard/dashboard.js +21 -4
- package/frontend/src/dashboard/edit-dashboard/edit-dashboard.html +13 -7
- package/frontend/src/dashboard/edit-dashboard/edit-dashboard.js +16 -23
- package/frontend/src/dashboard-result/dashboard-chart/dashboard-chart.html +19 -17
- package/frontend/src/dashboard-result/dashboard-chart/dashboard-chart.js +97 -2
- package/frontend/src/dashboard-result/dashboard-map/dashboard-map.js +27 -3
- package/frontend/src/dashboard-result/dashboard-result.html +3 -3
- package/frontend/src/dashboard-result/dashboard-result.js +3 -0
- package/frontend/src/dashboard-result/dashboard-table/dashboard-table.html +34 -0
- package/frontend/src/dashboard-result/dashboard-table/dashboard-table.js +37 -0
- package/frontend/src/dashboards/dashboards.html +101 -109
- package/frontend/src/dashboards/dashboards.js +25 -1
- package/frontend/src/detail-default/detail-default.html +2 -2
- package/frontend/src/detail-default/detail-default.js +24 -3
- package/frontend/src/document/confirm-changes/confirm-changes.html +1 -1
- package/frontend/src/document/confirm-delete/confirm-delete.html +1 -1
- package/frontend/src/document/document.css +1 -1
- package/frontend/src/document/document.html +28 -28
- package/frontend/src/document/execute-script/execute-script.html +20 -21
- package/frontend/src/document/execute-script/execute-script.js +1 -43
- package/frontend/src/document-details/document-details.css +4 -9
- package/frontend/src/document-details/document-details.html +34 -33
- package/frontend/src/document-details/document-details.js +2 -53
- package/frontend/src/document-details/document-property/document-property.html +12 -12
- package/frontend/src/edit-array/edit-array.html +7 -6
- package/frontend/src/edit-array/edit-array.js +10 -50
- package/frontend/src/edit-boolean/edit-boolean.html +12 -12
- package/frontend/src/edit-date/edit-date.html +2 -2
- package/frontend/src/edit-default/edit-default.html +1 -1
- package/frontend/src/edit-string/edit-string.html +3 -3
- package/frontend/src/edit-subdocument/edit-subdocument.html +5 -3
- package/frontend/src/edit-subdocument/edit-subdocument.js +1 -15
- package/frontend/src/export-query-results/export-query-results.html +3 -3
- package/frontend/src/json-node/json-node.html +3 -3
- package/frontend/src/list-json/json-node.html +1 -1
- package/frontend/src/models/document-search/document-search.html +3 -3
- package/frontend/src/models/model-switcher/model-switcher.html +53 -0
- package/frontend/src/models/model-switcher/model-switcher.js +123 -0
- package/frontend/src/models/models.css +3 -10
- package/frontend/src/models/models.html +146 -80
- package/frontend/src/models/models.js +116 -7
- package/frontend/src/navbar/navbar.html +157 -97
- package/frontend/src/navbar/navbar.js +31 -12
- package/frontend/src/routes.js +1 -1
- package/frontend/src/splash/splash.html +5 -5
- package/frontend/src/task-by-name/task-by-name.html +77 -7
- package/frontend/src/task-by-name/task-by-name.js +84 -9
- package/frontend/src/task-single/task-single.html +29 -29
- package/frontend/src/task-single/task-single.js +10 -10
- package/frontend/src/tasks/task-details/task-details.html +43 -43
- package/frontend/src/tasks/task-details/task-details.js +9 -3
- package/frontend/src/tasks/tasks.html +36 -35
- package/frontend/src/tasks/tasks.js +27 -143
- package/frontend/src/team/new-invitation/new-invitation.html +8 -8
- package/frontend/src/team/team.html +27 -27
- package/frontend/src/update-document/update-document.html +7 -2
- package/frontend/src/update-document/update-document.js +2 -11
- package/package.json +3 -1
- package/tailwind.config.js +75 -11
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const DATE_FILTERS = [
|
|
4
|
+
{ value: 'last_hour', label: 'Last Hour' },
|
|
5
|
+
{ value: 'today', label: 'Today' },
|
|
6
|
+
{ value: 'yesterday', label: 'Yesterday' },
|
|
7
|
+
{ value: 'thisWeek', label: 'This Week' },
|
|
8
|
+
{ value: 'lastWeek', label: 'Last Week' },
|
|
9
|
+
{ value: 'thisMonth', label: 'This Month' },
|
|
10
|
+
{ value: 'lastMonth', label: 'Last Month' }
|
|
11
|
+
];
|
|
12
|
+
|
|
13
|
+
const DATE_FILTER_VALUES = DATE_FILTERS.map(f => f.value);
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Returns { start, end } Date objects for a given range key (e.g. 'last_hour', 'today').
|
|
17
|
+
* Month ranges use UTC boundaries.
|
|
18
|
+
* @param {string} selectedRange - One of DATE_FILTER_VALUES
|
|
19
|
+
* @returns {{ start: Date, end: Date }}
|
|
20
|
+
*/
|
|
21
|
+
function getDateRangeForRange(selectedRange) {
|
|
22
|
+
const now = new Date();
|
|
23
|
+
let start, end;
|
|
24
|
+
switch (selectedRange) {
|
|
25
|
+
case 'last_hour':
|
|
26
|
+
start = new Date();
|
|
27
|
+
start.setHours(start.getHours() - 1);
|
|
28
|
+
end = new Date();
|
|
29
|
+
break;
|
|
30
|
+
case 'today':
|
|
31
|
+
start = new Date();
|
|
32
|
+
start.setHours(0, 0, 0, 0);
|
|
33
|
+
end = new Date();
|
|
34
|
+
end.setHours(23, 59, 59, 999);
|
|
35
|
+
break;
|
|
36
|
+
case 'yesterday':
|
|
37
|
+
start = new Date(now);
|
|
38
|
+
start.setDate(start.getDate() - 1);
|
|
39
|
+
start.setHours(0, 0, 0, 0);
|
|
40
|
+
end = new Date(start);
|
|
41
|
+
end.setHours(23, 59, 59, 999);
|
|
42
|
+
break;
|
|
43
|
+
case 'thisWeek':
|
|
44
|
+
start = new Date(now.getTime() - (7 * 86400000));
|
|
45
|
+
start.setHours(0, 0, 0, 0);
|
|
46
|
+
end = new Date();
|
|
47
|
+
end.setHours(23, 59, 59, 999);
|
|
48
|
+
break;
|
|
49
|
+
case 'lastWeek':
|
|
50
|
+
start = new Date(now.getTime() - (14 * 86400000));
|
|
51
|
+
start.setHours(0, 0, 0, 0);
|
|
52
|
+
end = new Date(now.getTime() - (7 * 86400000));
|
|
53
|
+
end.setHours(23, 59, 59, 999);
|
|
54
|
+
break;
|
|
55
|
+
case 'thisMonth': {
|
|
56
|
+
const y = now.getUTCFullYear();
|
|
57
|
+
const m = now.getUTCMonth();
|
|
58
|
+
start = new Date(Date.UTC(y, m, 1, 0, 0, 0, 0));
|
|
59
|
+
end = new Date(Date.UTC(y, m + 1, 0, 23, 59, 59, 999));
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
case 'lastMonth': {
|
|
63
|
+
const y = now.getUTCFullYear();
|
|
64
|
+
const m = now.getUTCMonth();
|
|
65
|
+
start = new Date(Date.UTC(y, m - 1, 1, 0, 0, 0, 0));
|
|
66
|
+
end = new Date(Date.UTC(y, m, 0, 23, 59, 59, 999));
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
default:
|
|
70
|
+
start = new Date();
|
|
71
|
+
start.setHours(start.getHours() - 1);
|
|
72
|
+
end = new Date();
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
return { start, end };
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
module.exports = {
|
|
79
|
+
DATE_FILTERS,
|
|
80
|
+
DATE_FILTER_VALUES,
|
|
81
|
+
getDateRangeForRange
|
|
82
|
+
};
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const template = require('./ace-editor.html');
|
|
4
|
+
const { createAceEditor, destroyAceEditor } = require('../aceEditor');
|
|
5
|
+
|
|
6
|
+
module.exports = app => app.component('ace-editor', {
|
|
7
|
+
template,
|
|
8
|
+
props: {
|
|
9
|
+
modelValue: {
|
|
10
|
+
type: String,
|
|
11
|
+
default: ''
|
|
12
|
+
},
|
|
13
|
+
// Support :value for explicit binding
|
|
14
|
+
value: {
|
|
15
|
+
type: String,
|
|
16
|
+
default: ''
|
|
17
|
+
},
|
|
18
|
+
mode: {
|
|
19
|
+
type: String,
|
|
20
|
+
default: 'javascript',
|
|
21
|
+
validator: (v) => ['javascript', 'json'].includes(v)
|
|
22
|
+
},
|
|
23
|
+
lineNumbers: {
|
|
24
|
+
type: Boolean,
|
|
25
|
+
default: true
|
|
26
|
+
},
|
|
27
|
+
readOnly: {
|
|
28
|
+
type: Boolean,
|
|
29
|
+
default: false
|
|
30
|
+
},
|
|
31
|
+
wrap: {
|
|
32
|
+
type: Boolean,
|
|
33
|
+
default: false
|
|
34
|
+
},
|
|
35
|
+
minLines: { type: Number, default: null },
|
|
36
|
+
maxLines: { type: Number, default: null }
|
|
37
|
+
},
|
|
38
|
+
emits: ['input', 'update:modelValue'],
|
|
39
|
+
data() {
|
|
40
|
+
return { editor: null };
|
|
41
|
+
},
|
|
42
|
+
mounted() {
|
|
43
|
+
this.$nextTick(() => {
|
|
44
|
+
const container = this.$refs.container;
|
|
45
|
+
if (!container) return;
|
|
46
|
+
this.editor = createAceEditor(container, {
|
|
47
|
+
value: this.modelValue !== '' ? this.modelValue : this.value,
|
|
48
|
+
mode: this.mode,
|
|
49
|
+
lineNumbers: this.lineNumbers,
|
|
50
|
+
readOnly: this.readOnly,
|
|
51
|
+
wrap: this.wrap,
|
|
52
|
+
minLines: this.minLines,
|
|
53
|
+
maxLines: this.maxLines
|
|
54
|
+
});
|
|
55
|
+
this.editor.session.on('change', () => {
|
|
56
|
+
const val = this.editor.getValue();
|
|
57
|
+
this.$emit('input', val);
|
|
58
|
+
this.$emit('update:modelValue', val);
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
},
|
|
62
|
+
beforeDestroy() {
|
|
63
|
+
if (this.editor) {
|
|
64
|
+
destroyAceEditor(this.editor);
|
|
65
|
+
this.editor = null;
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
watch: {
|
|
69
|
+
modelValue(newVal) {
|
|
70
|
+
const val = newVal ?? '';
|
|
71
|
+
if (this.editor && this.editor.getValue() !== val) {
|
|
72
|
+
this.editor.setValue(val, -1);
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
value(newVal) {
|
|
76
|
+
const val = newVal ?? '';
|
|
77
|
+
if (this.editor && this.editor.getValue() !== val) {
|
|
78
|
+
this.editor.setValue(val, -1);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
methods: {
|
|
83
|
+
getValue() {
|
|
84
|
+
if (this.editor) {
|
|
85
|
+
return this.editor.getValue();
|
|
86
|
+
}
|
|
87
|
+
return this.modelValue !== '' ? this.modelValue : this.value;
|
|
88
|
+
},
|
|
89
|
+
setValue(val) {
|
|
90
|
+
if (this.editor) {
|
|
91
|
+
this.editor.setValue(val ?? '', -1);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
});
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const ace = require('ace-builds');
|
|
4
|
+
require('ace-builds/src-noconflict/mode-javascript');
|
|
5
|
+
require('ace-builds/src-noconflict/mode-json');
|
|
6
|
+
require('ace-builds/src-noconflict/theme-chrome');
|
|
7
|
+
require('ace-builds/src-noconflict/theme-one_dark');
|
|
8
|
+
|
|
9
|
+
const LIGHT_THEME = 'ace/theme/chrome';
|
|
10
|
+
const DARK_THEME = 'ace/theme/one_dark';
|
|
11
|
+
|
|
12
|
+
function isDarkMode() {
|
|
13
|
+
return typeof document !== 'undefined' && document.documentElement.classList.contains('dark');
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Create an Ace editor on a container element (div). The container must have
|
|
18
|
+
* explicit dimensions (e.g. height/min-height and width).
|
|
19
|
+
* @param {HTMLElement} container - A div element to attach the editor to
|
|
20
|
+
* @param {Object} options - { value: string, mode: 'javascript'|'json', lineNumbers: boolean, ... }
|
|
21
|
+
* @returns {ace.Ace.Editor} The Ace editor instance
|
|
22
|
+
*/
|
|
23
|
+
function createAceEditor(container, options = {}) {
|
|
24
|
+
const {
|
|
25
|
+
value = '',
|
|
26
|
+
mode = 'javascript',
|
|
27
|
+
lineNumbers = true,
|
|
28
|
+
minLines,
|
|
29
|
+
maxLines,
|
|
30
|
+
readOnly = false,
|
|
31
|
+
wrap = false
|
|
32
|
+
} = options;
|
|
33
|
+
|
|
34
|
+
const editor = ace.edit(container);
|
|
35
|
+
editor.setTheme(isDarkMode() ? DARK_THEME : LIGHT_THEME);
|
|
36
|
+
editor.session.setMode(mode === 'json' ? 'ace/mode/json' : 'ace/mode/javascript');
|
|
37
|
+
editor.setValue(value, -1);
|
|
38
|
+
editor.setOptions({
|
|
39
|
+
showLineNumbers: lineNumbers,
|
|
40
|
+
readOnly,
|
|
41
|
+
wrap
|
|
42
|
+
});
|
|
43
|
+
if (minLines != null) editor.setOption('minLines', minLines);
|
|
44
|
+
if (maxLines != null) editor.setOption('maxLines', maxLines);
|
|
45
|
+
|
|
46
|
+
// Listen for theme toggles
|
|
47
|
+
const onThemeChanged = (e) => {
|
|
48
|
+
editor.setTheme(e.detail?.dark ? DARK_THEME : LIGHT_THEME);
|
|
49
|
+
};
|
|
50
|
+
document.documentElement.addEventListener('studio-theme-changed', onThemeChanged);
|
|
51
|
+
editor._studioThemeHandler = onThemeChanged;
|
|
52
|
+
|
|
53
|
+
return editor;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Destroy an Ace editor and release resources.
|
|
58
|
+
* @param {ace.Ace.Editor|null} editor - The editor instance from createAceEditor
|
|
59
|
+
*/
|
|
60
|
+
function destroyAceEditor(editor) {
|
|
61
|
+
if (editor) {
|
|
62
|
+
if (editor._studioThemeHandler) {
|
|
63
|
+
document.documentElement.removeEventListener('studio-theme-changed', editor._studioThemeHandler);
|
|
64
|
+
}
|
|
65
|
+
editor.destroy();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
module.exports = { createAceEditor, destroyAceEditor };
|
package/frontend/src/api.js
CHANGED
|
@@ -185,6 +185,9 @@ if (window.MONGOOSE_STUDIO_CONFIG.isLambda) {
|
|
|
185
185
|
getTasks: function getTasks(params) {
|
|
186
186
|
return client.post('', { action: 'Task.getTasks', ...params }).then(res => res.data);
|
|
187
187
|
},
|
|
188
|
+
getTaskOverview: function getTaskOverview(params) {
|
|
189
|
+
return client.post('', { action: 'Task.getTaskOverview', ...params }).then(res => res.data);
|
|
190
|
+
},
|
|
188
191
|
rescheduleTask: function rescheduleTask(params) {
|
|
189
192
|
return client.post('', { action: 'Task.rescheduleTask', ...params }).then(res => res.data);
|
|
190
193
|
},
|
|
@@ -519,6 +522,9 @@ if (window.MONGOOSE_STUDIO_CONFIG.isLambda) {
|
|
|
519
522
|
getTasks: function getTasks(params) {
|
|
520
523
|
return client.post('/Task/getTasks', params).then(res => res.data);
|
|
521
524
|
},
|
|
525
|
+
getTaskOverview: function getTaskOverview(params) {
|
|
526
|
+
return client.post('/Task/getTaskOverview', params).then(res => res.data);
|
|
527
|
+
},
|
|
522
528
|
rescheduleTask: function rescheduleTask(params) {
|
|
523
529
|
return client.post('/Task/rescheduleTask', params).then(res => res.data);
|
|
524
530
|
},
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
class="min-w-0 max-w-[calc(100vw-3rem)] lg:max-w-[calc(100vw-15rem)]"
|
|
4
4
|
:class="{'text-right': message.role === 'user'}">
|
|
5
5
|
|
|
6
|
-
<div class="text-sm text-
|
|
6
|
+
<div class="text-sm text-content rounded-md inline-block relative" :class="styleForMessage">
|
|
7
7
|
<div v-for="part in contentSplitByScripts">
|
|
8
8
|
<div v-if="part.type === 'text'" v-html="marked(part.content)">
|
|
9
9
|
</div>
|
|
@@ -9,7 +9,7 @@ module.exports = app => app.component('chat-message', {
|
|
|
9
9
|
props: ['message', 'targetDashboardId'],
|
|
10
10
|
computed: {
|
|
11
11
|
styleForMessage() {
|
|
12
|
-
return this.message.role === 'user' ? 'p-3 bg-
|
|
12
|
+
return this.message.role === 'user' ? 'p-3 bg-muted' : 'py-3 pr-3';
|
|
13
13
|
},
|
|
14
14
|
contentSplitByScripts() {
|
|
15
15
|
const content = this.message.content;
|
|
@@ -1,39 +1,39 @@
|
|
|
1
|
-
<div class="relative border rounded bg-
|
|
2
|
-
<div class="flex border-b py-1 pl-1 text-xs font-medium bg-
|
|
1
|
+
<div class="chat-message-script relative border rounded bg-surface my-1 text-content text-sm overflow-hidden">
|
|
2
|
+
<div class="flex border-b py-1 pl-1 text-xs font-medium bg-surface">
|
|
3
3
|
<button
|
|
4
|
-
class="px-4 py-1 border-r border-
|
|
4
|
+
class="px-4 py-1 border-r border-edge-strong text-content-secondary font-semibold transition-colors duration-200 focus:outline-none"
|
|
5
5
|
:class="[
|
|
6
6
|
'rounded-l-md',
|
|
7
7
|
activeTab === 'code'
|
|
8
8
|
? 'bg-gray-700 text-white shadow'
|
|
9
|
-
: 'bg-
|
|
9
|
+
: 'bg-muted hover:bg-muted text-gray-600'
|
|
10
10
|
]"
|
|
11
11
|
@click="activeTab = 'code'">
|
|
12
12
|
Code
|
|
13
13
|
</button>
|
|
14
14
|
<button
|
|
15
|
-
class="px-4 py-1 text-
|
|
15
|
+
class="px-4 py-1 text-content-secondary font-semibold transition-colors duration-200 focus:outline-none"
|
|
16
16
|
:class="[
|
|
17
17
|
'rounded-r-md',
|
|
18
18
|
activeTab === 'output'
|
|
19
19
|
? 'bg-gray-700 text-white shadow'
|
|
20
|
-
: 'bg-
|
|
20
|
+
: 'bg-muted hover:bg-muted text-gray-600'
|
|
21
21
|
]"
|
|
22
22
|
@click="activeTab = 'output'">
|
|
23
23
|
Output
|
|
24
24
|
</button>
|
|
25
|
-
<div class="ml-auto mr-1 flex">
|
|
25
|
+
<div class="ml-auto mr-1 flex items-center">
|
|
26
26
|
<button
|
|
27
27
|
v-if="activeTab === 'output'"
|
|
28
|
-
class="px-2 py-1 mr-1 text-xs bg-
|
|
28
|
+
class="px-2 py-1 mr-1 text-xs bg-gray-700 text-white border-none rounded cursor-pointer hover:bg-primary-hover transition-colors flex items-center"
|
|
29
29
|
@click="openDetailModal">
|
|
30
|
-
<svg xmlns="http://www.w3.org/2000/svg"
|
|
30
|
+
<svg xmlns="http://www.w3.org/2000/svg" style="height: 1.2em;" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
31
31
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 8V4m0 0h4M4 4l5 5m11-1V4m0 0h-4m4 0l-5 5M4 16v4m0 0h4m-4 0l5-5m11 1v4m0 0h-4m4 0l-5-5" />
|
|
32
32
|
</svg>
|
|
33
33
|
</button>
|
|
34
34
|
<button
|
|
35
35
|
v-if="activeTab === 'code' && !isEditing"
|
|
36
|
-
class="px-2 py-1 mr-1 text-xs bg-
|
|
36
|
+
class="px-2 py-1 mr-1 text-xs bg-page0 text-white border-none rounded cursor-pointer hover:bg-gray-600 transition-colors flex items-center"
|
|
37
37
|
@click.stop="startEditing">
|
|
38
38
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-3 w-3" viewBox="0 0 20 20" fill="currentColor">
|
|
39
39
|
<path d="M13.586 3.586a2 2 0 112.828 2.828l-.793.793-2.828-2.828.793-.793zM4 13.5V16h2.5l7.086-7.086-2.828-2.828L4 13.5z" />
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
</button>
|
|
42
42
|
<async-button
|
|
43
43
|
v-if="!isEditing"
|
|
44
|
-
class="px-2 py-1 text-xs bg-
|
|
44
|
+
class="px-2 py-1 text-xs bg-primary hover:bg-primary-hover text-primary-text border-none rounded cursor-pointer transition-colors disabled:bg-gray-400"
|
|
45
45
|
@click="executeScript">
|
|
46
46
|
Run
|
|
47
47
|
</async-button>
|
|
@@ -55,25 +55,25 @@
|
|
|
55
55
|
</button>
|
|
56
56
|
<div
|
|
57
57
|
v-if="showDropdown"
|
|
58
|
-
class="absolute right-0 z-10 mt-1 w-64 origin-top-right rounded-md bg-
|
|
58
|
+
class="absolute right-0 z-10 mt-1 w-64 origin-top-right rounded-md bg-surface py-1 shadow-lg ring-1 ring-black/5">
|
|
59
59
|
<button
|
|
60
|
-
class="block w-full text-left px-4 py-2 text-xs text-
|
|
60
|
+
class="block w-full text-left px-4 py-2 text-xs text-content-secondary hover:bg-muted"
|
|
61
61
|
@click="openCreateDashboardModal(); showDropdown = false">
|
|
62
62
|
Create Dashboard
|
|
63
63
|
</button>
|
|
64
64
|
<button
|
|
65
|
-
class="block w-full text-left px-4 py-2 text-xs text-
|
|
65
|
+
class="block w-full text-left px-4 py-2 text-xs text-content-secondary hover:bg-muted"
|
|
66
66
|
@click="copyOutput(); showDropdown = false">
|
|
67
67
|
Copy Output As Text
|
|
68
68
|
</button>
|
|
69
69
|
<button
|
|
70
70
|
v-if="canOverwriteDashboard"
|
|
71
|
-
class="block w-full text-left px-4 py-2 text-xs text-
|
|
71
|
+
class="block w-full text-left px-4 py-2 text-xs text-content-secondary hover:bg-muted"
|
|
72
72
|
@click="openOverwriteDashboardConfirmation(); showDropdown = false">
|
|
73
73
|
Overwrite Dashboard
|
|
74
74
|
</button>
|
|
75
75
|
<button
|
|
76
|
-
class="block w-full text-left px-4 py-2 text-xs text-
|
|
76
|
+
class="block w-full text-left px-4 py-2 text-xs text-content-secondary hover:bg-muted"
|
|
77
77
|
@click="$emit('copyMessage'); showDropdown = false">
|
|
78
78
|
Copy Full Message
|
|
79
79
|
</button>
|
|
@@ -83,9 +83,14 @@
|
|
|
83
83
|
</div>
|
|
84
84
|
|
|
85
85
|
<div class="p-0 max-h-[50vh] max-w-[calc(100vw-4rem)] lg:max-w-[calc(100vw-20rem)] overflow-y-auto" v-show="activeTab === 'code'">
|
|
86
|
-
<div v-if="isEditing" class="flex flex-col space-y-2">
|
|
87
|
-
<div class="border border-
|
|
88
|
-
<
|
|
86
|
+
<div v-if="isEditing" class="flex flex-col space-y-2 chat-script-editor-wrap">
|
|
87
|
+
<div class="border border-edge">
|
|
88
|
+
<ace-editor
|
|
89
|
+
v-model="editedScript"
|
|
90
|
+
mode="javascript"
|
|
91
|
+
:line-numbers="true"
|
|
92
|
+
class="w-full h-[45vh] min-h-[200px]"
|
|
93
|
+
/>
|
|
89
94
|
</div>
|
|
90
95
|
<div class="flex justify-end gap-2 pb-2">
|
|
91
96
|
<button
|
|
@@ -100,17 +105,19 @@
|
|
|
100
105
|
</async-button>
|
|
101
106
|
</div>
|
|
102
107
|
</div>
|
|
103
|
-
<pre v-else class="whitespace-pre-wrap !my-0
|
|
108
|
+
<pre v-else class="whitespace-pre-wrap !my-0 bg-muted"><code v-text="script" ref="code" :class="'language-' + language"></code></pre>
|
|
104
109
|
</div>
|
|
105
110
|
|
|
106
|
-
<div class="p-3 whitespace-pre-wrap max-h-[50vh] overflow-y-auto bg-
|
|
107
|
-
<dashboard-
|
|
108
|
-
|
|
109
|
-
|
|
111
|
+
<div class="p-3 whitespace-pre-wrap max-h-[50vh] overflow-y-auto bg-surface border-t max-w-[calc(100vw-4rem)] lg:max-w-[calc(100vw-20rem)] relative" v-show="activeTab === 'output'">
|
|
112
|
+
<dashboard-result
|
|
113
|
+
v-if="message.executionResult?.output != null"
|
|
114
|
+
:result="message.executionResult.output">
|
|
115
|
+
</dashboard-result>
|
|
116
|
+
<pre v-else>No output</pre>
|
|
110
117
|
|
|
111
|
-
<div v-if="message.executionResult?.logs?.length" class="mt-3 pt-3 border-t border-
|
|
118
|
+
<div v-if="message.executionResult?.logs?.length" class="mt-3 pt-3 border-t border-edge">
|
|
112
119
|
<div class="text-xs font-semibold text-gray-600 uppercase tracking-wide">Console</div>
|
|
113
|
-
<pre class="mt-1 bg-
|
|
120
|
+
<pre class="mt-1 bg-muted text-content p-3 rounded whitespace-pre-wrap overflow-x-auto max-h-[280px]">{{ message.executionResult.logs }}</pre>
|
|
114
121
|
</div>
|
|
115
122
|
</div>
|
|
116
123
|
|
|
@@ -118,12 +125,12 @@
|
|
|
118
125
|
<template #body>
|
|
119
126
|
<div class="absolute font-mono right-1 top-1 cursor-pointer text-xl" @click="showDetailModal = false;">×</div>
|
|
120
127
|
<div class="h-full overflow-auto">
|
|
121
|
-
<dashboard-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
:
|
|
125
|
-
|
|
126
|
-
<pre v-else class="whitespace-pre-wrap">
|
|
128
|
+
<dashboard-result
|
|
129
|
+
v-if="message.executionResult?.output != null"
|
|
130
|
+
:result="message.executionResult.output"
|
|
131
|
+
:fullscreen="true">
|
|
132
|
+
</dashboard-result>
|
|
133
|
+
<pre v-else class="whitespace-pre-wrap">No output</pre>
|
|
127
134
|
</div>
|
|
128
135
|
</template>
|
|
129
136
|
</modal>
|
|
@@ -131,19 +138,24 @@
|
|
|
131
138
|
<template #body>
|
|
132
139
|
<div class="modal-exit" @click="showCreateDashboardModal = false">×</div>
|
|
133
140
|
<div>
|
|
134
|
-
<div class="mt-4 text-
|
|
141
|
+
<div class="mt-4 text-content font-semibold">Create Dashboard</div>
|
|
135
142
|
<div class="mt-4">
|
|
136
|
-
<label class="block text-sm font-medium leading-6 text-
|
|
143
|
+
<label class="block text-sm font-medium leading-6 text-content">Title</label>
|
|
137
144
|
<div class="mt-2">
|
|
138
145
|
<div class="w-full flex rounded-md shadow-sm ring-1 ring-inset ring-gray-300 focus-within:ring-2 focus-within:ring-inset focus-within:ring-teal-600">
|
|
139
|
-
<input type="text" v-model="newDashboardTitle" class="outline-none block flex-1 border-0 bg-transparent py-1.5 pl-1 text-
|
|
146
|
+
<input type="text" v-model="newDashboardTitle" class="outline-none block flex-1 border-0 bg-transparent py-1.5 pl-1 text-content placeholder:text-gray-400 focus:ring-0 sm:text-sm sm:leading-6" placeholder="My Dashboard">
|
|
140
147
|
</div>
|
|
141
148
|
</div>
|
|
142
149
|
</div>
|
|
143
150
|
<div class="my-4">
|
|
144
|
-
<label class="block text-sm font-medium leading-6 text-
|
|
145
|
-
<div class="border border-
|
|
146
|
-
<
|
|
151
|
+
<label class="block text-sm font-medium leading-6 text-content">Code</label>
|
|
152
|
+
<div class="border border-edge">
|
|
153
|
+
<ace-editor
|
|
154
|
+
v-model="dashboardCode"
|
|
155
|
+
mode="javascript"
|
|
156
|
+
:line-numbers="true"
|
|
157
|
+
class="h-[300px] w-full"
|
|
158
|
+
/>
|
|
147
159
|
</div>
|
|
148
160
|
</div>
|
|
149
161
|
<async-button
|
|
@@ -173,14 +185,14 @@
|
|
|
173
185
|
<template #body>
|
|
174
186
|
<div class="modal-exit" @click="showOverwriteDashboardConfirmationModal = false">×</div>
|
|
175
187
|
<div>
|
|
176
|
-
<div class="mt-4 text-
|
|
177
|
-
<p class="mt-2 text-sm text-
|
|
188
|
+
<div class="mt-4 text-content font-semibold">Overwrite Dashboard</div>
|
|
189
|
+
<p class="mt-2 text-sm text-content-secondary">
|
|
178
190
|
This will replace the linked dashboard's code with the script below.
|
|
179
191
|
</p>
|
|
180
192
|
<p class="mt-1 text-xs text-gray-600 break-all" v-if="targetDashboardId">
|
|
181
193
|
Dashboard ID: {{ targetDashboardId }}
|
|
182
194
|
</p>
|
|
183
|
-
<div class="my-4 border border-
|
|
195
|
+
<div class="my-4 border border-edge bg-page rounded">
|
|
184
196
|
<pre class="p-2 h-[300px] overflow-auto whitespace-pre-wrap text-xs">{{ overwriteDashboardCode }}</pre>
|
|
185
197
|
</div>
|
|
186
198
|
<div class="flex items-center gap-2">
|
|
@@ -190,7 +202,7 @@
|
|
|
190
202
|
Confirm Overwrite
|
|
191
203
|
</async-button>
|
|
192
204
|
<button
|
|
193
|
-
class="px-2.5 py-1.5 rounded-md text-sm font-semibold text-
|
|
205
|
+
class="px-2.5 py-1.5 rounded-md text-sm font-semibold text-content-secondary bg-gray-200 hover:bg-gray-300"
|
|
194
206
|
@click="showOverwriteDashboardConfirmationModal = false">
|
|
195
207
|
Cancel
|
|
196
208
|
</button>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* global
|
|
1
|
+
/* global Prism */
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
4
|
const api = require('../../api');
|
|
@@ -18,9 +18,7 @@ module.exports = app => app.component('chat-message-script', {
|
|
|
18
18
|
newDashboardTitle: '',
|
|
19
19
|
dashboardCode: '',
|
|
20
20
|
createError: null,
|
|
21
|
-
dashboardEditor: null,
|
|
22
21
|
isEditing: false,
|
|
23
|
-
codeEditor: null,
|
|
24
22
|
editedScript: null,
|
|
25
23
|
overwriteDashboardCode: '',
|
|
26
24
|
overwriteError: null
|
|
@@ -28,7 +26,7 @@ module.exports = app => app.component('chat-message-script', {
|
|
|
28
26
|
},
|
|
29
27
|
computed: {
|
|
30
28
|
styleForMessage() {
|
|
31
|
-
return this.message.role === 'user' ? 'bg-
|
|
29
|
+
return this.message.role === 'user' ? 'bg-muted' : '';
|
|
32
30
|
},
|
|
33
31
|
canOverwriteDashboard() {
|
|
34
32
|
return !!this.targetDashboardId;
|
|
@@ -36,10 +34,7 @@ module.exports = app => app.component('chat-message-script', {
|
|
|
36
34
|
},
|
|
37
35
|
methods: {
|
|
38
36
|
async executeScript() {
|
|
39
|
-
|
|
40
|
-
if (this.isEditing) {
|
|
41
|
-
scriptToRun = this.codeEditor ? this.codeEditor.getValue() : this.editedScript;
|
|
42
|
-
}
|
|
37
|
+
const scriptToRun = this.isEditing ? this.editedScript : this.script;
|
|
43
38
|
this.editedScript = scriptToRun;
|
|
44
39
|
const { chatMessage } = await api.ChatMessage.executeScript({
|
|
45
40
|
chatMessageId: this.message._id,
|
|
@@ -66,25 +61,12 @@ module.exports = app => app.component('chat-message-script', {
|
|
|
66
61
|
this.dashboardCode = this.script;
|
|
67
62
|
this.createError = null;
|
|
68
63
|
this.showCreateDashboardModal = true;
|
|
69
|
-
this.$nextTick(() => {
|
|
70
|
-
if (this.dashboardEditor) {
|
|
71
|
-
this.dashboardEditor.toTextArea();
|
|
72
|
-
}
|
|
73
|
-
this.$refs.dashboardCodeEditor.value = this.dashboardCode;
|
|
74
|
-
this.dashboardEditor = CodeMirror.fromTextArea(this.$refs.dashboardCodeEditor, {
|
|
75
|
-
mode: 'javascript',
|
|
76
|
-
lineNumbers: true
|
|
77
|
-
});
|
|
78
|
-
this.dashboardEditor.on('change', () => {
|
|
79
|
-
this.dashboardCode = this.dashboardEditor.getValue();
|
|
80
|
-
});
|
|
81
|
-
});
|
|
82
64
|
},
|
|
83
65
|
openOverwriteDashboardConfirmation() {
|
|
84
66
|
if (!this.canOverwriteDashboard) {
|
|
85
67
|
return;
|
|
86
68
|
}
|
|
87
|
-
this.overwriteDashboardCode = this.
|
|
69
|
+
this.overwriteDashboardCode = this.isEditing ? this.editedScript : this.script;
|
|
88
70
|
this.overwriteError = null;
|
|
89
71
|
this.showOverwriteDashboardConfirmationModal = true;
|
|
90
72
|
},
|
|
@@ -94,39 +76,16 @@ module.exports = app => app.component('chat-message-script', {
|
|
|
94
76
|
startEditing() {
|
|
95
77
|
this.isEditing = true;
|
|
96
78
|
this.editedScript = this.script;
|
|
97
|
-
this.$nextTick(() => {
|
|
98
|
-
if (!this.$refs.scriptEditor) {
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
this.$refs.scriptEditor.value = this.editedScript;
|
|
102
|
-
if (typeof CodeMirror === 'undefined') {
|
|
103
|
-
return;
|
|
104
|
-
}
|
|
105
|
-
this.destroyCodeMirror();
|
|
106
|
-
this.codeEditor = CodeMirror.fromTextArea(this.$refs.scriptEditor, {
|
|
107
|
-
mode: 'javascript',
|
|
108
|
-
lineNumbers: true,
|
|
109
|
-
smartIndent: false
|
|
110
|
-
});
|
|
111
|
-
});
|
|
112
79
|
},
|
|
113
80
|
cancelEditing() {
|
|
114
81
|
this.isEditing = false;
|
|
115
|
-
this.destroyCodeMirror();
|
|
116
82
|
this.editedScript = this.script;
|
|
117
83
|
this.highlightCode();
|
|
118
84
|
},
|
|
119
85
|
finishEditing() {
|
|
120
86
|
this.isEditing = false;
|
|
121
|
-
this.destroyCodeMirror();
|
|
122
87
|
this.highlightCode();
|
|
123
88
|
},
|
|
124
|
-
destroyCodeMirror() {
|
|
125
|
-
if (this.codeEditor) {
|
|
126
|
-
this.codeEditor.toTextArea();
|
|
127
|
-
this.codeEditor = null;
|
|
128
|
-
}
|
|
129
|
-
},
|
|
130
89
|
handleScriptInput(event) {
|
|
131
90
|
this.editedScript = event?.target?.value || '';
|
|
132
91
|
},
|
|
@@ -144,9 +103,8 @@ module.exports = app => app.component('chat-message-script', {
|
|
|
144
103
|
}
|
|
145
104
|
},
|
|
146
105
|
async createDashboardFromScript() {
|
|
147
|
-
this.dashboardCode = this.dashboardEditor.getValue();
|
|
148
106
|
const { dashboard } = await api.Dashboard.createDashboard({
|
|
149
|
-
code: this.dashboardCode,
|
|
107
|
+
code: this.dashboardCode || '',
|
|
150
108
|
title: this.newDashboardTitle
|
|
151
109
|
}).catch(err => {
|
|
152
110
|
if (err.response?.data?.message) {
|
|
@@ -167,7 +125,7 @@ module.exports = app => app.component('chat-message-script', {
|
|
|
167
125
|
return;
|
|
168
126
|
}
|
|
169
127
|
|
|
170
|
-
this.overwriteDashboardCode = this.
|
|
128
|
+
this.overwriteDashboardCode = this.isEditing ? this.editedScript : this.script;
|
|
171
129
|
|
|
172
130
|
const params = {
|
|
173
131
|
dashboardId: this.targetDashboardId,
|
|
@@ -209,12 +167,6 @@ module.exports = app => app.component('chat-message-script', {
|
|
|
209
167
|
}
|
|
210
168
|
},
|
|
211
169
|
watch: {
|
|
212
|
-
showCreateDashboardModal(val) {
|
|
213
|
-
if (!val && this.dashboardEditor) {
|
|
214
|
-
this.dashboardEditor.toTextArea();
|
|
215
|
-
this.dashboardEditor = null;
|
|
216
|
-
}
|
|
217
|
-
},
|
|
218
170
|
script(newScript) {
|
|
219
171
|
if (!this.isEditing) {
|
|
220
172
|
this.editedScript = newScript;
|
|
@@ -232,7 +184,6 @@ module.exports = app => app.component('chat-message-script', {
|
|
|
232
184
|
}
|
|
233
185
|
},
|
|
234
186
|
unmounted() {
|
|
235
|
-
this.destroyCodeMirror();
|
|
236
187
|
document.body.removeEventListener('click', this.handleBodyClick);
|
|
237
188
|
}
|
|
238
189
|
});
|