@mongoosejs/studio 0.0.95 → 0.0.97
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/frontend/public/app.js +55 -22
- package/frontend/public/tw.css +194 -35
- package/frontend/src/chat/chat-message/chat-message.html +3 -3
- package/frontend/src/chat/chat-message-script/chat-message-script.html +2 -2
- package/frontend/src/chat/chat-message-script/chat-message-script.js +1 -2
- package/frontend/src/chat/chat.html +27 -11
- package/frontend/src/chat/chat.js +19 -1
- package/frontend/src/index.js +11 -2
- package/frontend/src/navbar/navbar.css +0 -21
- package/frontend/src/navbar/navbar.html +111 -6
- package/frontend/src/navbar/navbar.js +16 -11
- package/frontend/src/routes.js +3 -1
- package/package.json +1 -1
package/frontend/public/app.js
CHANGED
|
@@ -324,12 +324,11 @@ module.exports = app => app.component('async-button', {
|
|
|
324
324
|
|
|
325
325
|
|
|
326
326
|
const api = __webpack_require__(/*! ../../api */ "./frontend/src/api.js");
|
|
327
|
-
const marked = (__webpack_require__(/*! marked */ "./node_modules/marked/lib/marked.cjs").marked);
|
|
328
327
|
const template = __webpack_require__(/*! ./chat-message-script.html */ "./frontend/src/chat/chat-message-script/chat-message-script.html");
|
|
329
328
|
const vanillatoasts = __webpack_require__(/*! vanillatoasts */ "./node_modules/vanillatoasts/vanillatoasts.js");
|
|
330
329
|
|
|
331
330
|
module.exports = app => app.component('chat-message-script', {
|
|
332
|
-
template
|
|
331
|
+
template,
|
|
333
332
|
props: ['message', 'script', 'language'],
|
|
334
333
|
data: () => ({ activeTab: 'code', showDetailModal: false }),
|
|
335
334
|
computed: {
|
|
@@ -469,7 +468,8 @@ module.exports = app => app.component('chat', {
|
|
|
469
468
|
newMessage: '',
|
|
470
469
|
chatThreadId: null,
|
|
471
470
|
chatThreads: [],
|
|
472
|
-
chatMessages: []
|
|
471
|
+
chatMessages: [],
|
|
472
|
+
hideSidebar: null
|
|
473
473
|
}),
|
|
474
474
|
methods: {
|
|
475
475
|
async sendMessage() {
|
|
@@ -500,6 +500,11 @@ module.exports = app => app.component('chat', {
|
|
|
500
500
|
this.chatMessages.push(chatMessages[1]);
|
|
501
501
|
|
|
502
502
|
this.newMessage = '';
|
|
503
|
+
this.$nextTick(() => {
|
|
504
|
+
if (this.$refs.messageInput) {
|
|
505
|
+
this.$refs.messageInput.style.height = 'auto';
|
|
506
|
+
}
|
|
507
|
+
});
|
|
503
508
|
|
|
504
509
|
this.$nextTick(() => {
|
|
505
510
|
if (this.$refs.messagesContainer) {
|
|
@@ -510,6 +515,18 @@ module.exports = app => app.component('chat', {
|
|
|
510
515
|
this.sendingMessage = false;
|
|
511
516
|
}
|
|
512
517
|
},
|
|
518
|
+
handleEnter(ev) {
|
|
519
|
+
if (!ev.shiftKey) {
|
|
520
|
+
this.sendMessage();
|
|
521
|
+
}
|
|
522
|
+
},
|
|
523
|
+
adjustTextareaHeight(ev) {
|
|
524
|
+
const textarea = ev.target;
|
|
525
|
+
textarea.style.height = 'auto';
|
|
526
|
+
const lineHeight = parseInt(window.getComputedStyle(textarea).lineHeight, 10);
|
|
527
|
+
const maxHeight = lineHeight * 5;
|
|
528
|
+
textarea.style.height = Math.min(textarea.scrollHeight, maxHeight) + 'px';
|
|
529
|
+
},
|
|
513
530
|
selectThread(threadId) {
|
|
514
531
|
this.$router.push('/chat/' + threadId);
|
|
515
532
|
},
|
|
@@ -1756,6 +1773,7 @@ if (typeof process === 'undefined') {
|
|
|
1756
1773
|
|
|
1757
1774
|
const api = __webpack_require__(/*! ./api */ "./frontend/src/api.js");
|
|
1758
1775
|
const mothership = __webpack_require__(/*! ./mothership */ "./frontend/src/mothership.js");
|
|
1776
|
+
const { routes } = __webpack_require__(/*! ./routes */ "./frontend/src/routes.js");
|
|
1759
1777
|
const vanillatoasts = __webpack_require__(/*! vanillatoasts */ "./node_modules/vanillatoasts/vanillatoasts.js");
|
|
1760
1778
|
|
|
1761
1779
|
const app = Vue.createApp({
|
|
@@ -1814,7 +1832,7 @@ app.component('app-component', {
|
|
|
1814
1832
|
window.state = this;
|
|
1815
1833
|
|
|
1816
1834
|
if (mothership.hasAPIKey) {
|
|
1817
|
-
const hash = window.location.hash.replace(
|
|
1835
|
+
const hash = window.location.hash.replace(/^#?\/?/, '') || '';
|
|
1818
1836
|
const hashQuery = hash.split('?')[1] || '';
|
|
1819
1837
|
const hashParams = new URLSearchParams(hashQuery);
|
|
1820
1838
|
if (hashParams.has('code')) {
|
|
@@ -1857,6 +1875,7 @@ app.component('app-component', {
|
|
|
1857
1875
|
const { nodeEnv } = await api.status();
|
|
1858
1876
|
this.nodeEnv = nodeEnv;
|
|
1859
1877
|
}
|
|
1878
|
+
|
|
1860
1879
|
this.status = 'loaded';
|
|
1861
1880
|
},
|
|
1862
1881
|
setup() {
|
|
@@ -1873,7 +1892,6 @@ app.component('app-component', {
|
|
|
1873
1892
|
}
|
|
1874
1893
|
});
|
|
1875
1894
|
|
|
1876
|
-
const { routes } = __webpack_require__(/*! ./routes */ "./frontend/src/routes.js");
|
|
1877
1895
|
const router = VueRouter.createRouter({
|
|
1878
1896
|
history: VueRouter.createWebHashHistory(),
|
|
1879
1897
|
routes: routes.map(route => ({
|
|
@@ -1883,6 +1901,14 @@ const router = VueRouter.createRouter({
|
|
|
1883
1901
|
}))
|
|
1884
1902
|
});
|
|
1885
1903
|
|
|
1904
|
+
router.beforeEach((to, from, next) => {
|
|
1905
|
+
if (to.name === 'root' && window.state.roles && window.state.roles[0] === 'dashboards') {
|
|
1906
|
+
return next({ name: 'dashboards' });
|
|
1907
|
+
} else {
|
|
1908
|
+
next();
|
|
1909
|
+
}
|
|
1910
|
+
});
|
|
1911
|
+
|
|
1886
1912
|
app.use(router);
|
|
1887
1913
|
|
|
1888
1914
|
app.mount('#content');
|
|
@@ -2693,13 +2719,21 @@ module.exports = app => app.component('navbar', {
|
|
|
2693
2719
|
inject: ['state'],
|
|
2694
2720
|
data: () => ({ showFlyout: false }),
|
|
2695
2721
|
mounted: function() {
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2722
|
+
const mobileMenuMask = document.querySelector('#mobile-menu-mask');
|
|
2723
|
+
const mobileMenu = document.querySelector('#mobile-menu');
|
|
2724
|
+
|
|
2725
|
+
document.querySelector('#open-mobile-menu').addEventListener('click', (event) => {
|
|
2726
|
+
event.stopPropagation();
|
|
2727
|
+
mobileMenuMask.style.display = 'block';
|
|
2728
|
+
mobileMenu.classList.remove('translate-x-full');
|
|
2729
|
+
mobileMenu.classList.add('translate-x-0');
|
|
2730
|
+
});
|
|
2731
|
+
|
|
2732
|
+
document.querySelector('body').addEventListener('click', () => {
|
|
2733
|
+
mobileMenuMask.style.display = 'none';
|
|
2734
|
+
mobileMenu.classList.remove('translate-x-0');
|
|
2735
|
+
mobileMenu.classList.add('translate-x-full');
|
|
2736
|
+
});
|
|
2703
2737
|
},
|
|
2704
2738
|
computed: {
|
|
2705
2739
|
dashboardView() {
|
|
@@ -2723,11 +2757,8 @@ module.exports = app => app.component('navbar', {
|
|
|
2723
2757
|
canViewTeam() {
|
|
2724
2758
|
return this.hasAccess(this.roles, 'team');
|
|
2725
2759
|
},
|
|
2726
|
-
allowedRoutes() {
|
|
2727
|
-
return routes.filter(route => this.hasAccess(this.roles, route.name));
|
|
2728
|
-
},
|
|
2729
2760
|
defaultRoute() {
|
|
2730
|
-
return this.
|
|
2761
|
+
return this.roles && this.roles[0] === 'dashboards' ? 'dashboards' : 'root';
|
|
2731
2762
|
}
|
|
2732
2763
|
},
|
|
2733
2764
|
methods: {
|
|
@@ -2788,10 +2819,12 @@ const roleAccess = {
|
|
|
2788
2819
|
dashboards: ['dashboards', 'dashboard']
|
|
2789
2820
|
};
|
|
2790
2821
|
|
|
2822
|
+
const allowedRoutesForLocalDev = ['document', 'root', 'chat'];
|
|
2823
|
+
|
|
2791
2824
|
// Helper function to check if a role has access to a route
|
|
2792
2825
|
function hasAccess(roles, routeName) {
|
|
2793
2826
|
// change to true for local development
|
|
2794
|
-
if (!roles) return
|
|
2827
|
+
if (!roles) return allowedRoutesForLocalDev.includes(routeName);
|
|
2795
2828
|
return roles.some(role => roleAccess[role]?.includes(routeName));
|
|
2796
2829
|
}
|
|
2797
2830
|
|
|
@@ -3881,7 +3914,7 @@ module.exports = "<button v-bind=\"attrsToBind\" :disabled=\"isDisabled\" @click
|
|
|
3881
3914
|
/***/ ((module) => {
|
|
3882
3915
|
|
|
3883
3916
|
"use strict";
|
|
3884
|
-
module.exports = "<div class=\"relative border rounded bg-gray-100 text-black text-sm overflow-hidden\">\n <div class=\"flex border-b pt-[1px] text-xs font-medium bg-gray-200\">\n <button\n class=\"px-3 py-1 border-r border-gray-300 hover:bg-green-300\"\n :class=\"{'bg-gray-300': activeTab === 'code', 'bg-green-300': activeTab === 'code'}\"\n @click=\"activeTab = 'code'\">\n Code\n </button>\n <button\n class=\"px-3 py-1 hover:bg-green-300\"\n :class=\"{'bg-green-300': activeTab === 'output'}\"\n @click=\"activeTab = 'output'\">\n Output\n </button>\n <div class=\"ml-auto mr-1 flex\">\n <button\n v-if=\"activeTab === 'output'\"\n class=\"px-2 py-1 mr-1 text-xs bg-gray-500 text-white border-none rounded cursor-pointer hover:bg-gray-600 transition-colors flex items-center\"\n @click=\"copyOutput\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" class=\"h-3 w-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M8 5H6a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2v-1M8 5a2 2 0 002 2h2a2 2 0 002-2M8 5a2 2 0 012-2h2a2 2 0 012 2m0 0h2a2 2 0 012 2v3m2 4H10m0 0l3-3m-3 3l3 3\" />\n </svg>\n </button>\n <button\n v-if=\"activeTab === 'output'\"\n class=\"px-2 py-1 mr-1 text-xs bg-blue-500 text-white border-none rounded cursor-pointer hover:bg-blue-600 transition-colors flex items-center\"\n @click=\"openDetailModal\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" class=\"h-3 w-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <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\" />\n </svg>\n </button>\n <async-button\n class=\"px-2 py-1 text-xs bg-green-500 text-white border-none rounded cursor-pointer hover:bg-green-600 transition-colors disabled:bg-gray-400\"\n @click=\"executeScript(message, script)\">\n Execute\n </async-button>\n </div>\n </div>\n\n <pre class=\"p-3 whitespace-pre-wrap max-h-[
|
|
3917
|
+
module.exports = "<div class=\"relative border rounded bg-gray-100 text-black text-sm overflow-hidden\">\n <div class=\"flex border-b pt-[1px] text-xs font-medium bg-gray-200\">\n <button\n class=\"px-3 py-1 border-r border-gray-300 hover:bg-green-300\"\n :class=\"{'bg-gray-300': activeTab === 'code', 'bg-green-300': activeTab === 'code'}\"\n @click=\"activeTab = 'code'\">\n Code\n </button>\n <button\n class=\"px-3 py-1 hover:bg-green-300\"\n :class=\"{'bg-green-300': activeTab === 'output'}\"\n @click=\"activeTab = 'output'\">\n Output\n </button>\n <div class=\"ml-auto mr-1 flex\">\n <button\n v-if=\"activeTab === 'output'\"\n class=\"px-2 py-1 mr-1 text-xs bg-gray-500 text-white border-none rounded cursor-pointer hover:bg-gray-600 transition-colors flex items-center\"\n @click=\"copyOutput\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" class=\"h-3 w-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M8 5H6a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2v-1M8 5a2 2 0 002 2h2a2 2 0 002-2M8 5a2 2 0 012-2h2a2 2 0 012 2m0 0h2a2 2 0 012 2v3m2 4H10m0 0l3-3m-3 3l3 3\" />\n </svg>\n </button>\n <button\n v-if=\"activeTab === 'output'\"\n class=\"px-2 py-1 mr-1 text-xs bg-blue-500 text-white border-none rounded cursor-pointer hover:bg-blue-600 transition-colors flex items-center\"\n @click=\"openDetailModal\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" class=\"h-3 w-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <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\" />\n </svg>\n </button>\n <async-button\n class=\"px-2 py-1 text-xs bg-green-500 text-white border-none rounded cursor-pointer hover:bg-green-600 transition-colors disabled:bg-gray-400\"\n @click=\"executeScript(message, script)\">\n Execute\n </async-button>\n </div>\n </div>\n\n <pre class=\"p-3 whitespace-pre-wrap max-h-[50vh] max-w-[calc(100vw-4rem)] lg:max-w-[calc(100vw-20rem)] overflow-y-auto\" v-show=\"activeTab === 'code'\"><code v-text=\"script\" ref=\"code\" :class=\"'language-' + language\"></code></pre>\n\n <div class=\"p-3 whitespace-pre-wrap max-h-[50vh] overflow-y-auto bg-white border-t max-w-[calc(100vw-4rem)] lg:max-w-[calc(100vw-20rem)] relative\" v-show=\"activeTab === 'output'\">\n <dashboard-chart v-if=\"message.executionResult?.output?.$chart\" :value=\"message.executionResult?.output\" />\n <pre v-else>{{ message.executionResult?.output || 'No output' }}</pre>\n </div>\n\n <modal ref=\"outputModal\" v-if=\"showDetailModal\" containerClass=\"!h-[90vh] !w-[90vw]\">\n <template #body>\n <div class=\"absolute font-mono right-1 top-1 cursor-pointer text-xl\" @click=\"showDetailModal = false;\">×</div>\n <div class=\"h-full overflow-auto\">\n <dashboard-chart v-if=\"message.executionResult?.output?.$chart\" :value=\"message.executionResult?.output\" />\n <pre v-else class=\"whitespace-pre-wrap\">{{ message.executionResult?.output || 'No output' }}</pre>\n </div>\n </template>\n </modal>\n</div>\n";
|
|
3885
3918
|
|
|
3886
3919
|
/***/ }),
|
|
3887
3920
|
|
|
@@ -3892,7 +3925,7 @@ module.exports = "<div class=\"relative border rounded bg-gray-100 text-black te
|
|
|
3892
3925
|
/***/ ((module) => {
|
|
3893
3926
|
|
|
3894
3927
|
"use strict";
|
|
3895
|
-
module.exports = "<div class=\"relative flex items-start
|
|
3928
|
+
module.exports = "<div class=\"relative flex items-start\" :class=\"{'justify-end': message.role === 'user'}\">\n <div\n class=\"min-w-0 max-w-[calc(100vw-4rem)] lg:max-w-[calc(100vw-20rem)]\"\n :class=\"{'text-right': message.role === 'user'}\">\n\n <div class=\"text-sm text-gray-900 md:p-3 rounded-md inline-block\" :class=\"styleForMessage\">\n <div v-for=\"part in contentSplitByScripts\">\n <div v-if=\"part.type === 'text'\" v-html=\"marked(part.content)\">\n </div>\n <div v-else-if=\"part.type === 'code'\">\n <chat-message-script :message=\"message\" :script=\"part.content\" :language=\"part.language\"></chat-message-script>\n </div>\n </div>\n </div>\n </div>\n</div>\n";
|
|
3896
3929
|
|
|
3897
3930
|
/***/ }),
|
|
3898
3931
|
|
|
@@ -3903,7 +3936,7 @@ module.exports = "<div class=\"relative flex items-start space-x-3\" :class=\"{'
|
|
|
3903
3936
|
/***/ ((module) => {
|
|
3904
3937
|
|
|
3905
3938
|
"use strict";
|
|
3906
|
-
module.exports = "<div class=\"flex\" style=\"height: calc(100vh - 55px)\">\n <!-- Sidebar: Chat Threads -->\n <aside class=\"
|
|
3939
|
+
module.exports = "<div class=\"flex\" style=\"height: calc(100vh - 55px)\">\n <div class=\"fixed top-[65px] cursor-pointer bg-gray-100 rounded-r-md z-10\" @click=\"hideSidebar = false\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" style=\"h-5 w-5\" viewBox=\"0 -960 960 960\" class=\"w-5\" fill=\"#5f6368\"><path d=\"M360-120v-720h80v720h-80Zm160-160v-400l200 200-200 200Z\"/></svg>\n </div>\n <!-- Sidebar: Chat Threads -->\n <aside class=\"bg-gray-50 border-r overflow-y-auto overflow-x-hidden h-full transition-all duration-300 ease-in-out z-20 w-0 lg:w-64 fixed lg:relative\" :class=\"hideSidebar === true ? '!w-0' : hideSidebar === false ? '!w-64' : ''\">\n <div class=\"flex items-center border-b border-gray-100 w-64 overflow-x-hidden\">\n <div class=\"p-4 font-bold text-lg\">Chat Threads</div>\n <button\n @click=\"hideSidebar = true\"\n class=\"ml-auto mr-2 p-2 rounded hover:bg-gray-200 focus:outline-none\"\n aria-label=\"Close sidebar\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" style=\"h-5 w-5\" viewBox=\"0 -960 960 960\" class=\"w-5\" fill=\"currentColor\"><path d=\"M660-320v-320L500-480l160 160ZM200-120q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h560q33 0 56.5 23.5T840-760v560q0 33-23.5 56.5T760-120H200Zm120-80v-560H200v560h120Zm80 0h360v-560H400v560Zm-80 0H200h120Z\"/></svg>\n </button>\n </div>\n <div class=\"p-4 w-64\">\n <async-button\n @click=\"createNewThread\"\n class=\"w-full bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700\"\n >\n Create New Thread\n </async-button>\n </div>\n <div v-if=\"status === 'loaded' && chatThreads.length === 0\" class=\"p-4 text-sm text-gray-700\">\n No threads yet\n </div>\n <ul v-if=\"status === 'loaded'\" class=\"w-64\">\n <li\n v-for=\"thread in chatThreads\"\n :key=\"thread._id\"\n @click=\"selectThread(thread._id)\"\n class=\"p-4 hover:bg-gray-200 cursor-pointer w-64\"\n :class=\"{ 'bg-gray-300': thread._id === chatThreadId }\"\n >\n {{ thread.title || 'Untitled Thread' }}\n </li>\n </ul>\n </aside>\n\n <!-- Main Chat Area -->\n <main class=\"flex-1 flex flex-col\">\n <div class=\"flex-1 overflow-y-auto p-6 space-y-4\" ref=\"messagesContainer\">\n <ul role=\"list\" class=\"space-y-4\">\n <div v-if=\"true\">\n <div class=\"flex items-center justify-center py-3 mb-4\">\n <div class=\"bg-gray-300 h-px flex-grow max-w-xs\"></div>\n <p class=\"mx-4 text-sm font-medium text-gray-500\">This is the beginning of the message thread</p>\n <div class=\"bg-gray-300 h-px flex-grow max-w-xs\"></div>\n </div>\n </div>\n <li v-for=\"message in chatMessages\" :key=\"message._id\">\n <chat-message :message=\"message\"></chat-message>\n </li>\n </ul>\n </div>\n\n\n <!-- Input Area -->\n <div class=\"border-t p-4\">\n <form @submit.prevent=\"sendMessage\" :disabled=\"sendingMessage\" class=\"flex gap-2 items-end justify-end\">\n <textarea\n v-model=\"newMessage\"\n placeholder=\"Ask something...\"\n class=\"flex-1 border rounded px-4 py-2 resize-none overflow-y-auto\"\n rows=\"1\"\n ref=\"messageInput\"\n @input=\"adjustTextareaHeight\"\n @keydown.enter.exact.prevent=\"handleEnter\"\n ></textarea>\n <button class=\"bg-blue-600 text-white px-4 h-[42px] rounded disabled:bg-gray-600\" :disabled=\"sendingMessage\">\n <svg v-if=\"sendingMessage\" style=\"height: 1em\" viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\">\n <g>\n <circle cx=\"12\" cy=\"12\" r=\"10\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" opacity=\"0.3\" />\n <path d=\"M12 2a10 10 0 0 1 10 10\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\">\n <animateTransform attributeName=\"transform\" type=\"rotate\" from=\"0 12 12\" to=\"360 12 12\" dur=\"1s\" repeatCount=\"indefinite\" />\n </path>\n </g>\n </svg>\n <span v-else>Send</span>\n </button>\n </form>\n </div>\n </main>\n</div>\n";
|
|
3907
3940
|
|
|
3908
3941
|
/***/ }),
|
|
3909
3942
|
|
|
@@ -4431,7 +4464,7 @@ module.exports = "<div class=\"models\">\n <div>\n <div class=\"flex grow fl
|
|
|
4431
4464
|
/***/ ((module) => {
|
|
4432
4465
|
|
|
4433
4466
|
"use strict";
|
|
4434
|
-
module.exports = ".
|
|
4467
|
+
module.exports = ".active {\n text-decoration: underline;\n}\n\n.navbar .nav-left {\n float: left;\n line-height: 54px;\n font-size: 20px;\n padding-left: 20px;\n}\n\n.navbar .nav-left a {\n color: #232323;\n}\n\n.navbar .nav-right {\n float: right;\n display: flex;\n flex-direction: row;\n justify-content: space-between;\n font-size: 16px;\n line-height: 54px;\n padding-right: 20px;\n}\n\n.navbar .nav-right .nav-item {\n flex-grow: 1;\n padding: 0px 12px;\n position: relative;\n z-index: 21000;\n}\n\n.navbar .nav-right .nav-item:hover {\n flex-grow: 1;\n padding: 0px 12px;\n border-bottom: 1px solid #E1B9A0;\n}\n\n.navbar .nav-right .nav-item.active {\n border-bottom: 1px solid #E1B9A0;\n}\n\n.navbar .nav-action {\n cursor: pointer;\n color: #E1B9A0;\n}\n\n.navbar .nav-action svg {\n height: 1em;\n vertical-align: middle;\n}\n\n.navbar .nav-right .nav-item .flyout {\n position: absolute;\n top: 55px;\n right: 0px;\n visibility: hidden;\n opacity: 0;\n transition: opacity .25s,visibility .25s,transform .25s;\n width: auto;\n box-shadow: 0 12px 32px rgba(0, 0, 0, .1), 0 2px 6px rgba(0, 0, 0, .08);\n background-color: #393944;\n padding-left: 0.5em;\n padding-right: 0.5em;\n z-index: 1000;\n min-width: 192px;\n font-size: 0.9em;\n}\n\n.navbar .nav-right .nav-item:hover .flyout a {\n color: #E1B9A0;\n margin-top: 0.25em;\n margin-bottom: 0.25em;\n}\n\n.navbar .nav-right .nav-item:hover .flyout a:hover {\n color: #E1B9A0;\n}\n\n.navbar .nav-right .nav-item:hover .flyout .nav-action {\n color: #E1B9A0;\n margin-top: 0.25em;\n margin-bottom: 0.25em;\n}\n\n.navbar .nav-right .nav-item:hover .flyout .nav-action:hover {\n color: #E1B9A0;\n}\n\n.navbar .nav-right .nav-item:hover .flyout {\n visibility: visible;\n opacity: 1;\n}\n\n#bar-1 {\n\ttransform: translateY(-4px);\n}\n#bar-3 {\n\ttransform: translateY(4px);\n}\n.menu {\n display: none;\n}\n.menu {\n\twidth: 35px;\n\theight: 30px;\n\tmargin: 18px 2px 0px 0px;\n\tcursor: pointer;\n float: right;\n}\n.bar {\n\theight: 5px;\n\twidth: 100%;\n\tbackground-color: #fff;\n\tdisplay: block;\n\tborder-radius: 5px;\n\ttransition: 0.4s ease;\n}\n.change-icon #bar-1 {\n transform: translateY(4px) rotateZ(-405deg);\n}\n.change-icon #bar-2 {\n opacity: 0;\n}\n.change-icon #bar-3 {\n transform: translateY(-6px) rotateZ(405deg);\n}\n\n@media (max-width: 767px) {\n .menu {\n display: block;\n }\n\n .change-icon ~ div.nav-right {\n left: 0;\n }\n\n .navbar .nav-right {\n\t\tposition: fixed;\n\t\ttop: 55px;\n\t\tleft: -130%;\n\t\tbackground: #111;\n\t\theight: 100vh;\n\t\twidth: 100%;\n\t\ttext-align: center;\n\t\tdisplay: block;\n\t\ttransition: all 0.3s ease;\n z-index: 10000;\n\t}\n}\n";
|
|
4435
4468
|
|
|
4436
4469
|
/***/ }),
|
|
4437
4470
|
|
|
@@ -4442,7 +4475,7 @@ module.exports = ".navbar {\n width: 100%;\n background-color: #eee;\n}\n\n.ac
|
|
|
4442
4475
|
/***/ ((module) => {
|
|
4443
4476
|
|
|
4444
4477
|
"use strict";
|
|
4445
|
-
module.exports = "<div class=\"navbar\">\n <div class=\"nav-left flex items-center gap-4 h-full\">\n <router-link :to=\"{ name: defaultRoute }\">\n <img src=\"images/logo.svg\" alt=\"Mongoose Studio Logo\" />\n </router-link>\n <div v-if=\"!!state.nodeEnv\" class=\"inline-flex items-center rounded-md px-2 py-1 text-sm font-medium text-gray-900\" :class=\"warnEnv ? 'bg-red-300' : 'bg-yellow-300'\">\n {{state.nodeEnv}}\n </div>\n </div>\n <div class=\"nav-right h-full\">\n <div class=\"sm:ml-6 sm:flex sm:space-x-8 h-full\">\n <a v-if=\"hasAccess(roles, 'root')\"\n href=\"#/\"\n class=\"inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium\"\n :class=\"documentView ? 'text-gray-900 border-ultramarine-500' : 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700'\">Documents</a>\n <a v-if=\"hasAccess(roles, 'dashboards')\"\n href=\"#/dashboards\"\n class=\"inline-flex items-center border-b-2 px-1 pt-1 text-sm font-medium\"\n :class=\"dashboardView ? 'text-gray-900 border-ultramarine-500' : 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700'\">Dashboards</a>\n <a v-if=\"hasAccess(roles, 'chat')\"\n href=\"#/chat\"\n class=\"inline-flex items-center border-b-2 px-1 pt-1 text-sm font-medium\"\n :class=\"chatView ? 'text-gray-900 border-ultramarine-500' : 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700'\">Chat</a>\n\n <div class=\"h-full flex items-center\" v-if=\"!user && hasAPIKey\">\n <button\n type=\"button\"\n @click=\"loginWithGithub\"\n class=\"rounded bg-ultramarine-600 px-2 py-2 text-sm font-semibold text-white shadow-sm hover:bg-ultramarine-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ultramarine-600\">\n Login\n </button>\n </div>\n <div v-if=\"user && hasAPIKey\" class=\"h-full flex items-center relative\" v-clickOutside=\"hideFlyout\">\n <div>\n <button type=\"button\" @click=\"showFlyout = !showFlyout\" class=\"relative flex rounded-full bg-gray-800 text-sm focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-gray-800\" id=\"user-menu-button\" aria-expanded=\"false\" aria-haspopup=\"true\">\n <span class=\"absolute -inset-1.5\"></span>\n <span class=\"sr-only\">Open user menu</span>\n <img class=\"size-8 rounded-full\" :src=\"user.picture\" alt=\"\">\n </button>\n </div>\n\n <div v-if=\"showFlyout\" class=\"absolute right-0 z-10 top-[90%] w-48 origin-top-right rounded-md bg-white py-1 shadow-lg ring-1 ring-black/5 focus:outline-none\" role=\"menu\" aria-orientation=\"vertical\" aria-labelledby=\"user-menu-button\" tabindex=\"-1\">\n <router-link to=\"/team\" v-if=\"hasAccess(roles, 'team')\" @click=\"showFlyout = false\" class=\"cursor-pointer block px-4 py-2 text-sm text-gray-700 hover:bg-ultramarine-200\" role=\"menuitem\" tabindex=\"-1\" id=\"user-menu-item-2\">Team</router-link>\n <span @click=\"logout\" class=\"cursor-pointer block px-4 py-2 text-sm text-gray-700 hover:bg-ultramarine-200\" role=\"menuitem\" tabindex=\"-1\" id=\"user-menu-item-2\">Sign out</span>\n </div>\n </div>\n\n </div>\n </div>\n <div style=\"clear: both\"></div>\n</div>\n";
|
|
4478
|
+
module.exports = "<div class=\"navbar w-full bg-gray-50 flex justify-between border-b border-gray-200 !h-[55px]\">\n <div class=\"flex items-center gap-4 h-full pl-4\">\n <router-link :to=\"{ name: defaultRoute }\">\n <img src=\"images/logo.svg\" class=\"h-[32px] mr-1\" alt=\"Mongoose Studio Logo\" />\n </router-link>\n <div v-if=\"!!state.nodeEnv\" title=\"NODE_ENV\" class=\"inline-flex items-center rounded-md px-2 py-1 text-sm font-medium text-gray-900\" :class=\"warnEnv ? 'bg-red-300' : 'bg-yellow-300'\">\n {{state.nodeEnv}}\n </div>\n </div>\n <div class=\"h-full pr-4 hidden md:block\">\n <div class=\"sm:ml-6 sm:flex sm:space-x-8 h-full\">\n <a v-if=\"hasAccess(roles, 'root')\"\n href=\"#/\"\n class=\"inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium\"\n :class=\"documentView ? 'text-gray-900 border-ultramarine-500' : 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700'\">Documents</a>\n <span v-else class=\"inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium text-gray-300 cursor-not-allowed\" aria-disabled=\"true\">\n Documents\n <svg class=\"h-4 w-4 ml-1\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z\" clip-rule=\"evenodd\" />\n </svg>\n </span>\n <a v-if=\"hasAccess(roles, 'dashboards')\"\n href=\"#/dashboards\"\n class=\"inline-flex items-center border-b-2 px-1 pt-1 text-sm font-medium\"\n :class=\"dashboardView ? 'text-gray-900 border-ultramarine-500' : 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700'\">Dashboards</a>\n <span v-else class=\"inline-flex items-center border-b-2 px-1 pt-1 text-sm font-medium text-gray-300 cursor-not-allowed\">\n Dashboards\n <svg class=\"h-4 w-4 ml-1\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z\" clip-rule=\"evenodd\" />\n </svg>\n </span>\n <a v-if=\"hasAccess(roles, 'chat')\"\n href=\"#/chat\"\n class=\"inline-flex items-center border-b-2 px-1 pt-1 text-sm font-medium\"\n :class=\"chatView ? 'text-gray-900 border-ultramarine-500' : 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700'\">Chat</a>\n <span v-else class=\"inline-flex items-center border-b-2 px-1 pt-1 text-sm font-medium text-gray-300 cursor-not-allowed\">\n Chat\n <svg class=\"h-4 w-4 ml-1\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z\" clip-rule=\"evenodd\" />\n </svg>\n </span>\n\n <div class=\"h-full flex items-center\" v-if=\"!user && hasAPIKey\">\n <button\n type=\"button\"\n @click=\"loginWithGithub\"\n class=\"rounded bg-ultramarine-600 px-2 py-2 text-sm font-semibold text-white shadow-sm hover:bg-ultramarine-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ultramarine-600\">\n Login\n </button>\n </div>\n <div v-if=\"user && hasAPIKey\" class=\"h-full flex items-center relative\" v-clickOutside=\"hideFlyout\">\n <div>\n <button type=\"button\" @click=\"showFlyout = !showFlyout\" class=\"relative flex rounded-full bg-gray-800 text-sm focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-gray-800\" id=\"user-menu-button\" aria-expanded=\"false\" aria-haspopup=\"true\">\n <span class=\"absolute -inset-1.5\"></span>\n <span class=\"sr-only\">Open user menu</span>\n <img class=\"size-8 rounded-full\" :src=\"user.picture\" alt=\"\">\n </button>\n </div>\n\n <div v-if=\"showFlyout\" class=\"absolute right-0 z-10 top-[90%] w-48 origin-top-right rounded-md bg-white py-1 shadow-lg ring-1 ring-black/5 focus:outline-none\" role=\"menu\" aria-orientation=\"vertical\" aria-labelledby=\"user-menu-button\" tabindex=\"-1\">\n <router-link to=\"/team\" v-if=\"hasAccess(roles, 'team')\" @click=\"showFlyout = false\" class=\"cursor-pointer block px-4 py-2 text-sm text-gray-700 hover:bg-ultramarine-200\" role=\"menuitem\" tabindex=\"-1\" id=\"user-menu-item-2\">Team</router-link>\n <span v-else class=\"block px-4 py-2 text-sm text-gray-300 cursor-not-allowed\" role=\"menuitem\" tabindex=\"-1\" id=\"user-menu-item-2\">\n Team\n <svg class=\"h-4 w-4 ml-1 inline\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z\" clip-rule=\"evenodd\" />\n </svg>\n </span>\n <span @click=\"logout\" class=\"cursor-pointer block px-4 py-2 text-sm text-gray-700 hover:bg-ultramarine-200\" role=\"menuitem\" tabindex=\"-1\" id=\"user-menu-item-2\">Sign out</span>\n </div>\n </div>\n\n </div>\n </div>\n <div class=\"md:hidden flex items-center\">\n <!-- Mobile menu toggle, controls the 'mobileMenuOpen' state. -->\n <button type=\"button\" id=\"open-mobile-menu\" class=\"-ml-2 rounded-md p-2 pr-4 text-gray-400\">\n <span class=\"sr-only\">Open menu</span>\n <svg class=\"h-6 w-6\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" aria-hidden=\"true\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5\" />\n </svg>\n </button>\n </div>\n\n <!-- Mobile menu mask -->\n <div id=\"mobile-menu-mask\" class=\"fixed inset-0 bg-black bg-opacity-40 z-40 hidden\"></div>\n <!-- Mobile menu drawer -->\n <div id=\"mobile-menu\" class=\"fixed inset-0 bg-white shadow-lg z-50 transform translate-x-full transition-transform duration-200 ease-in-out flex flex-col\">\n <div class=\"flex items-center justify-between px-4 !h-[55px] border-b border-gray-200\">\n <router-link :to=\"{ name: defaultRoute }\">\n <img src=\"images/logo.svg\" class=\"h-[32px]\" alt=\"Mongoose Studio Logo\" />\n </router-link>\n <button type=\"button\" id=\"close-mobile-menu\" class=\"text-gray-400 p-2 rounded-md\">\n <span class=\"sr-only\">Close menu</span>\n <svg class=\"h-6 w-6\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" aria-hidden=\"true\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n </div>\n <nav class=\"flex-1 px-4 py-4 space-y-2\">\n <a v-if=\"hasAccess(roles, 'root')\"\n href=\"#/\"\n class=\"block px-3 py-2 rounded-md text-base font-medium\"\n :class=\"documentView ? 'text-ultramarine-700 bg-ultramarine-100' : 'text-gray-700 hover:bg-gray-100'\">Documents</a>\n <span v-else class=\"block px-3 py-2 rounded-md text-base font-medium text-gray-300 cursor-not-allowed\">\n Documents\n <svg class=\"h-4 w-4 ml-1 inline\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z\" clip-rule=\"evenodd\" />\n </svg>\n </span>\n <a v-if=\"hasAccess(roles, 'dashboards')\"\n href=\"#/dashboards\"\n class=\"block px-3 py-2 rounded-md text-base font-medium\"\n :class=\"dashboardView ? 'text-ultramarine-700 bg-ultramarine-100' : 'text-gray-700 hover:bg-gray-100'\">Dashboards</a>\n <span v-else class=\"block px-3 py-2 rounded-md text-base font-medium text-gray-300 cursor-not-allowed\">\n Dashboards\n <svg class=\"h-4 w-4 ml-1 inline\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z\" clip-rule=\"evenodd\" />\n </svg>\n </span>\n <a v-if=\"hasAccess(roles, 'chat')\"\n href=\"#/chat\"\n class=\"block px-3 py-2 rounded-md text-base font-medium\"\n :class=\"chatView ? 'text-ultramarine-700 bg-ultramarine-100' : 'text-gray-700 hover:bg-gray-100'\">Chat</a>\n <span v-else class=\"block px-3 py-2 rounded-md text-base font-medium text-gray-300 cursor-not-allowed\">\n Chat\n <svg class=\"h-4 w-4 ml-1 inline\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z\" clip-rule=\"evenodd\" />\n </svg>\n </span>\n <div v-if=\"!user && hasAPIKey\" class=\"mt-4\">\n <button\n type=\"button\"\n @click=\"loginWithGithub\"\n class=\"w-full rounded bg-ultramarine-600 px-3 py-2 text-base font-semibold text-white shadow-sm hover:bg-ultramarine-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ultramarine-600\">\n Login\n </button>\n </div>\n <div v-if=\"user && hasAPIKey\" class=\"mt-4\">\n <div class=\"flex items-center gap-3 px-3 py-2 bg-gray-50 rounded-md\">\n <img class=\"size-8 rounded-full\" :src=\"user.picture\" alt=\"\">\n <span class=\"text-gray-900 font-medium\">{{ user.name }}</span>\n </div>\n <div class=\"mt-2 space-y-1\">\n <router-link to=\"/team\" v-if=\"hasAccess(roles, 'team')\" class=\"block px-3 py-2 rounded-md text-base text-gray-700 hover:bg-ultramarine-100\">Team</router-link>\n <span v-else class=\"block px-3 py-2 rounded-md text-base text-gray-300 cursor-not-allowed\">\n Team\n <svg class=\"h-4 w-4 ml-1 inline\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z\" clip-rule=\"evenodd\" />\n </svg>\n </span>\n <span @click=\"logout\" class=\"block px-3 py-2 rounded-md text-base text-gray-700 hover:bg-ultramarine-100 cursor-pointer\">Sign out</span>\n </div>\n </div>\n </nav>\n </div>\n</div>\n";
|
|
4446
4479
|
|
|
4447
4480
|
/***/ }),
|
|
4448
4481
|
|
package/frontend/public/tw.css
CHANGED
|
@@ -594,6 +594,10 @@ video {
|
|
|
594
594
|
pointer-events: none;
|
|
595
595
|
}
|
|
596
596
|
|
|
597
|
+
.fixed {
|
|
598
|
+
position: fixed;
|
|
599
|
+
}
|
|
600
|
+
|
|
597
601
|
.absolute {
|
|
598
602
|
position: absolute;
|
|
599
603
|
}
|
|
@@ -610,6 +614,10 @@ video {
|
|
|
610
614
|
inset: -0.375rem;
|
|
611
615
|
}
|
|
612
616
|
|
|
617
|
+
.inset-0 {
|
|
618
|
+
inset: 0px;
|
|
619
|
+
}
|
|
620
|
+
|
|
613
621
|
.right-0 {
|
|
614
622
|
right: 0px;
|
|
615
623
|
}
|
|
@@ -622,6 +630,10 @@ video {
|
|
|
622
630
|
top: 0.25rem;
|
|
623
631
|
}
|
|
624
632
|
|
|
633
|
+
.top-\[65px\] {
|
|
634
|
+
top: 65px;
|
|
635
|
+
}
|
|
636
|
+
|
|
625
637
|
.top-\[90\%\] {
|
|
626
638
|
top: 90%;
|
|
627
639
|
}
|
|
@@ -634,6 +646,18 @@ video {
|
|
|
634
646
|
z-index: 10;
|
|
635
647
|
}
|
|
636
648
|
|
|
649
|
+
.z-20 {
|
|
650
|
+
z-index: 20;
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
.z-40 {
|
|
654
|
+
z-index: 40;
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
.z-50 {
|
|
658
|
+
z-index: 50;
|
|
659
|
+
}
|
|
660
|
+
|
|
637
661
|
.col-start-1 {
|
|
638
662
|
grid-column-start: 1;
|
|
639
663
|
}
|
|
@@ -679,6 +703,10 @@ video {
|
|
|
679
703
|
margin-left: -0.125rem;
|
|
680
704
|
}
|
|
681
705
|
|
|
706
|
+
.-ml-2 {
|
|
707
|
+
margin-left: -0.5rem;
|
|
708
|
+
}
|
|
709
|
+
|
|
682
710
|
.-ml-px {
|
|
683
711
|
margin-left: -1px;
|
|
684
712
|
}
|
|
@@ -802,6 +830,10 @@ video {
|
|
|
802
830
|
height: 2rem;
|
|
803
831
|
}
|
|
804
832
|
|
|
833
|
+
.\!h-\[55px\] {
|
|
834
|
+
height: 55px !important;
|
|
835
|
+
}
|
|
836
|
+
|
|
805
837
|
.\!h-\[90vh\] {
|
|
806
838
|
height: 90vh !important;
|
|
807
839
|
}
|
|
@@ -826,6 +858,10 @@ video {
|
|
|
826
858
|
height: 1.25rem;
|
|
827
859
|
}
|
|
828
860
|
|
|
861
|
+
.h-6 {
|
|
862
|
+
height: 1.5rem;
|
|
863
|
+
}
|
|
864
|
+
|
|
829
865
|
.h-8 {
|
|
830
866
|
height: 2rem;
|
|
831
867
|
}
|
|
@@ -838,6 +874,10 @@ video {
|
|
|
838
874
|
height: 300px;
|
|
839
875
|
}
|
|
840
876
|
|
|
877
|
+
.h-\[32px\] {
|
|
878
|
+
height: 32px;
|
|
879
|
+
}
|
|
880
|
+
|
|
841
881
|
.h-\[42px\] {
|
|
842
882
|
height: 42px;
|
|
843
883
|
}
|
|
@@ -854,6 +894,14 @@ video {
|
|
|
854
894
|
height: 1px;
|
|
855
895
|
}
|
|
856
896
|
|
|
897
|
+
.h-10 {
|
|
898
|
+
height: 2.5rem;
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
.h-11 {
|
|
902
|
+
height: 2.75rem;
|
|
903
|
+
}
|
|
904
|
+
|
|
857
905
|
.max-h-\[30vh\] {
|
|
858
906
|
max-height: 30vh;
|
|
859
907
|
}
|
|
@@ -862,10 +910,22 @@ video {
|
|
|
862
910
|
max-height: 50vh;
|
|
863
911
|
}
|
|
864
912
|
|
|
913
|
+
.\!w-0 {
|
|
914
|
+
width: 0px !important;
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
.\!w-64 {
|
|
918
|
+
width: 16rem !important;
|
|
919
|
+
}
|
|
920
|
+
|
|
865
921
|
.\!w-\[90vw\] {
|
|
866
922
|
width: 90vw !important;
|
|
867
923
|
}
|
|
868
924
|
|
|
925
|
+
.w-0 {
|
|
926
|
+
width: 0px;
|
|
927
|
+
}
|
|
928
|
+
|
|
869
929
|
.w-16 {
|
|
870
930
|
width: 4rem;
|
|
871
931
|
}
|
|
@@ -886,6 +946,10 @@ video {
|
|
|
886
946
|
width: 1.25rem;
|
|
887
947
|
}
|
|
888
948
|
|
|
949
|
+
.w-6 {
|
|
950
|
+
width: 1.5rem;
|
|
951
|
+
}
|
|
952
|
+
|
|
889
953
|
.w-64 {
|
|
890
954
|
width: 16rem;
|
|
891
955
|
}
|
|
@@ -914,12 +978,8 @@ video {
|
|
|
914
978
|
max-width: 64rem;
|
|
915
979
|
}
|
|
916
980
|
|
|
917
|
-
.max-w-\[
|
|
918
|
-
max-width:
|
|
919
|
-
}
|
|
920
|
-
|
|
921
|
-
.max-w-\[calc\(100\%-6\.5rem\)\] {
|
|
922
|
-
max-width: calc(100% - 6.5rem);
|
|
981
|
+
.max-w-\[calc\(100vw-4rem\)\] {
|
|
982
|
+
max-width: calc(100vw - 4rem);
|
|
923
983
|
}
|
|
924
984
|
|
|
925
985
|
.max-w-xs {
|
|
@@ -962,6 +1022,16 @@ video {
|
|
|
962
1022
|
transform-origin: top right;
|
|
963
1023
|
}
|
|
964
1024
|
|
|
1025
|
+
.translate-x-0 {
|
|
1026
|
+
--tw-translate-x: 0px;
|
|
1027
|
+
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
.translate-x-full {
|
|
1031
|
+
--tw-translate-x: 100%;
|
|
1032
|
+
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
|
1033
|
+
}
|
|
1034
|
+
|
|
965
1035
|
.transform {
|
|
966
1036
|
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
|
967
1037
|
}
|
|
@@ -974,6 +1044,10 @@ video {
|
|
|
974
1044
|
cursor: pointer;
|
|
975
1045
|
}
|
|
976
1046
|
|
|
1047
|
+
.resize-none {
|
|
1048
|
+
resize: none;
|
|
1049
|
+
}
|
|
1050
|
+
|
|
977
1051
|
.list-disc {
|
|
978
1052
|
list-style-type: disc;
|
|
979
1053
|
}
|
|
@@ -1004,6 +1078,10 @@ video {
|
|
|
1004
1078
|
align-items: flex-start;
|
|
1005
1079
|
}
|
|
1006
1080
|
|
|
1081
|
+
.items-end {
|
|
1082
|
+
align-items: flex-end;
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1007
1085
|
.items-center {
|
|
1008
1086
|
align-items: center;
|
|
1009
1087
|
}
|
|
@@ -1080,6 +1158,12 @@ video {
|
|
|
1080
1158
|
margin-bottom: calc(0.25rem * var(--tw-space-y-reverse));
|
|
1081
1159
|
}
|
|
1082
1160
|
|
|
1161
|
+
.space-y-2 > :not([hidden]) ~ :not([hidden]) {
|
|
1162
|
+
--tw-space-y-reverse: 0;
|
|
1163
|
+
margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse)));
|
|
1164
|
+
margin-bottom: calc(0.5rem * var(--tw-space-y-reverse));
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1083
1167
|
.space-y-4 > :not([hidden]) ~ :not([hidden]) {
|
|
1084
1168
|
--tw-space-y-reverse: 0;
|
|
1085
1169
|
margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse)));
|
|
@@ -1135,6 +1219,10 @@ video {
|
|
|
1135
1219
|
overflow-y: auto;
|
|
1136
1220
|
}
|
|
1137
1221
|
|
|
1222
|
+
.overflow-x-hidden {
|
|
1223
|
+
overflow-x: hidden;
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1138
1226
|
.truncate {
|
|
1139
1227
|
overflow: hidden;
|
|
1140
1228
|
text-overflow: ellipsis;
|
|
@@ -1235,9 +1323,9 @@ video {
|
|
|
1235
1323
|
border-color: rgb(63 83 255 / var(--tw-border-opacity));
|
|
1236
1324
|
}
|
|
1237
1325
|
|
|
1238
|
-
.
|
|
1239
|
-
--tw-
|
|
1240
|
-
|
|
1326
|
+
.bg-black {
|
|
1327
|
+
--tw-bg-opacity: 1;
|
|
1328
|
+
background-color: rgb(0 0 0 / var(--tw-bg-opacity));
|
|
1241
1329
|
}
|
|
1242
1330
|
|
|
1243
1331
|
.bg-blue-200 {
|
|
@@ -1374,6 +1462,11 @@ video {
|
|
|
1374
1462
|
background-color: rgb(229 234 255 / var(--tw-bg-opacity));
|
|
1375
1463
|
}
|
|
1376
1464
|
|
|
1465
|
+
.bg-ultramarine-500 {
|
|
1466
|
+
--tw-bg-opacity: 1;
|
|
1467
|
+
background-color: rgb(63 83 255 / var(--tw-bg-opacity));
|
|
1468
|
+
}
|
|
1469
|
+
|
|
1377
1470
|
.bg-ultramarine-600 {
|
|
1378
1471
|
--tw-bg-opacity: 1;
|
|
1379
1472
|
background-color: rgb(24 35 255 / var(--tw-bg-opacity));
|
|
@@ -1399,9 +1492,8 @@ video {
|
|
|
1399
1492
|
background-color: rgb(253 224 71 / var(--tw-bg-opacity));
|
|
1400
1493
|
}
|
|
1401
1494
|
|
|
1402
|
-
.bg-
|
|
1403
|
-
--tw-bg-opacity:
|
|
1404
|
-
background-color: rgb(63 83 255 / var(--tw-bg-opacity));
|
|
1495
|
+
.bg-opacity-40 {
|
|
1496
|
+
--tw-bg-opacity: 0.4;
|
|
1405
1497
|
}
|
|
1406
1498
|
|
|
1407
1499
|
.p-1 {
|
|
@@ -1630,6 +1722,11 @@ video {
|
|
|
1630
1722
|
color: rgb(0 242 58 / var(--tw-text-opacity));
|
|
1631
1723
|
}
|
|
1632
1724
|
|
|
1725
|
+
.text-gray-300 {
|
|
1726
|
+
--tw-text-opacity: 1;
|
|
1727
|
+
color: rgb(209 213 219 / var(--tw-text-opacity));
|
|
1728
|
+
}
|
|
1729
|
+
|
|
1633
1730
|
.text-gray-400 {
|
|
1634
1731
|
--tw-text-opacity: 1;
|
|
1635
1732
|
color: rgb(156 163 175 / var(--tw-text-opacity));
|
|
@@ -1685,6 +1782,11 @@ video {
|
|
|
1685
1782
|
color: rgb(0 168 165 / var(--tw-text-opacity));
|
|
1686
1783
|
}
|
|
1687
1784
|
|
|
1785
|
+
.text-ultramarine-700 {
|
|
1786
|
+
--tw-text-opacity: 1;
|
|
1787
|
+
color: rgb(7 19 250 / var(--tw-text-opacity));
|
|
1788
|
+
}
|
|
1789
|
+
|
|
1688
1790
|
.text-valencia-500 {
|
|
1689
1791
|
--tw-text-opacity: 1;
|
|
1690
1792
|
color: rgb(220 73 73 / var(--tw-text-opacity));
|
|
@@ -1777,16 +1879,6 @@ video {
|
|
|
1777
1879
|
--tw-ring-color: rgb(22 163 74 / 0.2);
|
|
1778
1880
|
}
|
|
1779
1881
|
|
|
1780
|
-
.ring-yellow-800 {
|
|
1781
|
-
--tw-ring-opacity: 1;
|
|
1782
|
-
--tw-ring-color: rgb(133 77 14 / var(--tw-ring-opacity));
|
|
1783
|
-
}
|
|
1784
|
-
|
|
1785
|
-
.ring-yellow-300 {
|
|
1786
|
-
--tw-ring-opacity: 1;
|
|
1787
|
-
--tw-ring-color: rgb(253 224 71 / var(--tw-ring-opacity));
|
|
1788
|
-
}
|
|
1789
|
-
|
|
1790
1882
|
.filter {
|
|
1791
1883
|
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
|
|
1792
1884
|
}
|
|
@@ -1799,12 +1891,36 @@ video {
|
|
|
1799
1891
|
transition-duration: 150ms;
|
|
1800
1892
|
}
|
|
1801
1893
|
|
|
1894
|
+
.transition-all {
|
|
1895
|
+
transition-property: all;
|
|
1896
|
+
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
1897
|
+
transition-duration: 150ms;
|
|
1898
|
+
}
|
|
1899
|
+
|
|
1802
1900
|
.transition-colors {
|
|
1803
1901
|
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke;
|
|
1804
1902
|
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
1805
1903
|
transition-duration: 150ms;
|
|
1806
1904
|
}
|
|
1807
1905
|
|
|
1906
|
+
.transition-transform {
|
|
1907
|
+
transition-property: transform;
|
|
1908
|
+
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
1909
|
+
transition-duration: 150ms;
|
|
1910
|
+
}
|
|
1911
|
+
|
|
1912
|
+
.duration-200 {
|
|
1913
|
+
transition-duration: 200ms;
|
|
1914
|
+
}
|
|
1915
|
+
|
|
1916
|
+
.duration-300 {
|
|
1917
|
+
transition-duration: 300ms;
|
|
1918
|
+
}
|
|
1919
|
+
|
|
1920
|
+
.ease-in-out {
|
|
1921
|
+
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
1922
|
+
}
|
|
1923
|
+
|
|
1808
1924
|
.placeholder\:text-gray-400::-moz-placeholder {
|
|
1809
1925
|
--tw-text-opacity: 1;
|
|
1810
1926
|
color: rgb(156 163 175 / var(--tw-text-opacity));
|
|
@@ -1850,6 +1966,11 @@ video {
|
|
|
1850
1966
|
background-color: rgb(0 242 58 / var(--tw-bg-opacity));
|
|
1851
1967
|
}
|
|
1852
1968
|
|
|
1969
|
+
.hover\:bg-gray-100:hover {
|
|
1970
|
+
--tw-bg-opacity: 1;
|
|
1971
|
+
background-color: rgb(243 244 246 / var(--tw-bg-opacity));
|
|
1972
|
+
}
|
|
1973
|
+
|
|
1853
1974
|
.hover\:bg-gray-200:hover {
|
|
1854
1975
|
--tw-bg-opacity: 1;
|
|
1855
1976
|
background-color: rgb(229 231 235 / var(--tw-bg-opacity));
|
|
@@ -1930,6 +2051,11 @@ video {
|
|
|
1930
2051
|
background-color: rgb(63 83 255 / var(--tw-bg-opacity));
|
|
1931
2052
|
}
|
|
1932
2053
|
|
|
2054
|
+
.hover\:bg-ultramarine-600:hover {
|
|
2055
|
+
--tw-bg-opacity: 1;
|
|
2056
|
+
background-color: rgb(24 35 255 / var(--tw-bg-opacity));
|
|
2057
|
+
}
|
|
2058
|
+
|
|
1933
2059
|
.hover\:bg-valencia-400:hover {
|
|
1934
2060
|
--tw-bg-opacity: 1;
|
|
1935
2061
|
background-color: rgb(235 126 126 / var(--tw-bg-opacity));
|
|
@@ -1940,11 +2066,6 @@ video {
|
|
|
1940
2066
|
background-color: rgb(220 73 73 / var(--tw-bg-opacity));
|
|
1941
2067
|
}
|
|
1942
2068
|
|
|
1943
|
-
.hover\:bg-ultramarine-600:hover {
|
|
1944
|
-
--tw-bg-opacity: 1;
|
|
1945
|
-
background-color: rgb(24 35 255 / var(--tw-bg-opacity));
|
|
1946
|
-
}
|
|
1947
|
-
|
|
1948
2069
|
.hover\:text-gray-700:hover {
|
|
1949
2070
|
--tw-text-opacity: 1;
|
|
1950
2071
|
color: rgb(55 65 81 / var(--tw-text-opacity));
|
|
@@ -2075,6 +2196,10 @@ video {
|
|
|
2075
2196
|
outline-color: #d1d5db;
|
|
2076
2197
|
}
|
|
2077
2198
|
|
|
2199
|
+
.focus-visible\:outline-gray-500:focus-visible {
|
|
2200
|
+
outline-color: #6b7280;
|
|
2201
|
+
}
|
|
2202
|
+
|
|
2078
2203
|
.focus-visible\:outline-green-600:focus-visible {
|
|
2079
2204
|
outline-color: #16a34a;
|
|
2080
2205
|
}
|
|
@@ -2107,14 +2232,6 @@ video {
|
|
|
2107
2232
|
outline-color: #1823ff;
|
|
2108
2233
|
}
|
|
2109
2234
|
|
|
2110
|
-
.focus-visible\:outline-gray-600:focus-visible {
|
|
2111
|
-
outline-color: #4b5563;
|
|
2112
|
-
}
|
|
2113
|
-
|
|
2114
|
-
.focus-visible\:outline-gray-500:focus-visible {
|
|
2115
|
-
outline-color: #6b7280;
|
|
2116
|
-
}
|
|
2117
|
-
|
|
2118
2235
|
.disabled\:cursor-not-allowed:disabled {
|
|
2119
2236
|
cursor: not-allowed;
|
|
2120
2237
|
}
|
|
@@ -2228,12 +2345,54 @@ video {
|
|
|
2228
2345
|
}
|
|
2229
2346
|
}
|
|
2230
2347
|
|
|
2348
|
+
@media (min-width: 768px) {
|
|
2349
|
+
.md\:relative {
|
|
2350
|
+
position: relative;
|
|
2351
|
+
}
|
|
2352
|
+
|
|
2353
|
+
.md\:block {
|
|
2354
|
+
display: block;
|
|
2355
|
+
}
|
|
2356
|
+
|
|
2357
|
+
.md\:hidden {
|
|
2358
|
+
display: none;
|
|
2359
|
+
}
|
|
2360
|
+
|
|
2361
|
+
.md\:w-64 {
|
|
2362
|
+
width: 16rem;
|
|
2363
|
+
}
|
|
2364
|
+
|
|
2365
|
+
.md\:max-w-\[calc\(100vw-16rem\)\] {
|
|
2366
|
+
max-width: calc(100vw - 16rem);
|
|
2367
|
+
}
|
|
2368
|
+
|
|
2369
|
+
.md\:max-w-\[calc\(100vw-20rem\)\] {
|
|
2370
|
+
max-width: calc(100vw - 20rem);
|
|
2371
|
+
}
|
|
2372
|
+
|
|
2373
|
+
.md\:p-3 {
|
|
2374
|
+
padding: 0.75rem;
|
|
2375
|
+
}
|
|
2376
|
+
}
|
|
2377
|
+
|
|
2231
2378
|
@media (min-width: 1024px) {
|
|
2379
|
+
.lg\:relative {
|
|
2380
|
+
position: relative;
|
|
2381
|
+
}
|
|
2382
|
+
|
|
2232
2383
|
.lg\:-mx-8 {
|
|
2233
2384
|
margin-left: -2rem;
|
|
2234
2385
|
margin-right: -2rem;
|
|
2235
2386
|
}
|
|
2236
2387
|
|
|
2388
|
+
.lg\:w-64 {
|
|
2389
|
+
width: 16rem;
|
|
2390
|
+
}
|
|
2391
|
+
|
|
2392
|
+
.lg\:max-w-\[calc\(100vw-20rem\)\] {
|
|
2393
|
+
max-width: calc(100vw - 20rem);
|
|
2394
|
+
}
|
|
2395
|
+
|
|
2237
2396
|
.lg\:px-8 {
|
|
2238
2397
|
padding-left: 2rem;
|
|
2239
2398
|
padding-right: 2rem;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
<div class="relative flex items-start
|
|
1
|
+
<div class="relative flex items-start" :class="{'justify-end': message.role === 'user'}">
|
|
2
2
|
<div
|
|
3
|
-
class="min-w-0 max-w-[calc(
|
|
3
|
+
class="min-w-0 max-w-[calc(100vw-4rem)] lg:max-w-[calc(100vw-20rem)]"
|
|
4
4
|
:class="{'text-right': message.role === 'user'}">
|
|
5
5
|
|
|
6
|
-
<div class="text-sm text-gray-900 p-3 rounded-md inline-block" :class="styleForMessage">
|
|
6
|
+
<div class="text-sm text-gray-900 md:p-3 rounded-md inline-block" :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>
|
|
@@ -37,9 +37,9 @@
|
|
|
37
37
|
</div>
|
|
38
38
|
</div>
|
|
39
39
|
|
|
40
|
-
<pre class="p-3 whitespace-pre-wrap max-h-[
|
|
40
|
+
<pre class="p-3 whitespace-pre-wrap max-h-[50vh] max-w-[calc(100vw-4rem)] lg:max-w-[calc(100vw-20rem)] overflow-y-auto" v-show="activeTab === 'code'"><code v-text="script" ref="code" :class="'language-' + language"></code></pre>
|
|
41
41
|
|
|
42
|
-
<div class="p-3 whitespace-pre-wrap max-h-[
|
|
42
|
+
<div class="p-3 whitespace-pre-wrap max-h-[50vh] overflow-y-auto bg-white border-t max-w-[calc(100vw-4rem)] lg:max-w-[calc(100vw-20rem)] relative" v-show="activeTab === 'output'">
|
|
43
43
|
<dashboard-chart v-if="message.executionResult?.output?.$chart" :value="message.executionResult?.output" />
|
|
44
44
|
<pre v-else>{{ message.executionResult?.output || 'No output' }}</pre>
|
|
45
45
|
</div>
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const api = require('../../api');
|
|
4
|
-
const marked = require('marked').marked;
|
|
5
4
|
const template = require('./chat-message-script.html');
|
|
6
5
|
const vanillatoasts = require('vanillatoasts');
|
|
7
6
|
|
|
8
7
|
module.exports = app => app.component('chat-message-script', {
|
|
9
|
-
template
|
|
8
|
+
template,
|
|
10
9
|
props: ['message', 'script', 'language'],
|
|
11
10
|
data: () => ({ activeTab: 'code', showDetailModal: false }),
|
|
12
11
|
computed: {
|
|
@@ -1,8 +1,20 @@
|
|
|
1
1
|
<div class="flex" style="height: calc(100vh - 55px)">
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
<div class="fixed top-[65px] cursor-pointer bg-gray-100 rounded-r-md z-10" @click="hideSidebar = false">
|
|
3
|
+
<svg xmlns="http://www.w3.org/2000/svg" style="h-5 w-5" viewBox="0 -960 960 960" class="w-5" fill="#5f6368"><path d="M360-120v-720h80v720h-80Zm160-160v-400l200 200-200 200Z"/></svg>
|
|
4
|
+
</div>
|
|
5
|
+
<!-- Sidebar: Chat Threads -->
|
|
6
|
+
<aside class="bg-gray-50 border-r overflow-y-auto overflow-x-hidden h-full transition-all duration-300 ease-in-out z-20 w-0 lg:w-64 fixed lg:relative" :class="hideSidebar === true ? '!w-0' : hideSidebar === false ? '!w-64' : ''">
|
|
7
|
+
<div class="flex items-center border-b border-gray-100 w-64 overflow-x-hidden">
|
|
8
|
+
<div class="p-4 font-bold text-lg">Chat Threads</div>
|
|
9
|
+
<button
|
|
10
|
+
@click="hideSidebar = true"
|
|
11
|
+
class="ml-auto mr-2 p-2 rounded hover:bg-gray-200 focus:outline-none"
|
|
12
|
+
aria-label="Close sidebar"
|
|
13
|
+
>
|
|
14
|
+
<svg xmlns="http://www.w3.org/2000/svg" style="h-5 w-5" viewBox="0 -960 960 960" class="w-5" fill="currentColor"><path d="M660-320v-320L500-480l160 160ZM200-120q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h560q33 0 56.5 23.5T840-760v560q0 33-23.5 56.5T760-120H200Zm120-80v-560H200v560h120Zm80 0h360v-560H400v560Zm-80 0H200h120Z"/></svg>
|
|
15
|
+
</button>
|
|
16
|
+
</div>
|
|
17
|
+
<div class="p-4 w-64">
|
|
6
18
|
<async-button
|
|
7
19
|
@click="createNewThread"
|
|
8
20
|
class="w-full bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700"
|
|
@@ -13,12 +25,12 @@
|
|
|
13
25
|
<div v-if="status === 'loaded' && chatThreads.length === 0" class="p-4 text-sm text-gray-700">
|
|
14
26
|
No threads yet
|
|
15
27
|
</div>
|
|
16
|
-
<ul
|
|
28
|
+
<ul v-if="status === 'loaded'" class="w-64">
|
|
17
29
|
<li
|
|
18
30
|
v-for="thread in chatThreads"
|
|
19
31
|
:key="thread._id"
|
|
20
32
|
@click="selectThread(thread._id)"
|
|
21
|
-
class="p-4 hover:bg-gray-200 cursor-pointer"
|
|
33
|
+
class="p-4 hover:bg-gray-200 cursor-pointer w-64"
|
|
22
34
|
:class="{ 'bg-gray-300': thread._id === chatThreadId }"
|
|
23
35
|
>
|
|
24
36
|
{{ thread.title || 'Untitled Thread' }}
|
|
@@ -46,13 +58,17 @@
|
|
|
46
58
|
|
|
47
59
|
<!-- Input Area -->
|
|
48
60
|
<div class="border-t p-4">
|
|
49
|
-
<form @submit.prevent="sendMessage" :disabled="sendingMessage" class="flex gap-2">
|
|
50
|
-
<
|
|
61
|
+
<form @submit.prevent="sendMessage" :disabled="sendingMessage" class="flex gap-2 items-end justify-end">
|
|
62
|
+
<textarea
|
|
51
63
|
v-model="newMessage"
|
|
52
64
|
placeholder="Ask something..."
|
|
53
|
-
class="flex-1 border rounded px-4 py-2"
|
|
54
|
-
|
|
55
|
-
|
|
65
|
+
class="flex-1 border rounded px-4 py-2 resize-none overflow-y-auto"
|
|
66
|
+
rows="1"
|
|
67
|
+
ref="messageInput"
|
|
68
|
+
@input="adjustTextareaHeight"
|
|
69
|
+
@keydown.enter.exact.prevent="handleEnter"
|
|
70
|
+
></textarea>
|
|
71
|
+
<button class="bg-blue-600 text-white px-4 h-[42px] rounded disabled:bg-gray-600" :disabled="sendingMessage">
|
|
56
72
|
<svg v-if="sendingMessage" style="height: 1em" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
|
57
73
|
<g>
|
|
58
74
|
<circle cx="12" cy="12" r="10" fill="none" stroke="currentColor" stroke-width="2" opacity="0.3" />
|
|
@@ -12,7 +12,8 @@ module.exports = app => app.component('chat', {
|
|
|
12
12
|
newMessage: '',
|
|
13
13
|
chatThreadId: null,
|
|
14
14
|
chatThreads: [],
|
|
15
|
-
chatMessages: []
|
|
15
|
+
chatMessages: [],
|
|
16
|
+
hideSidebar: null
|
|
16
17
|
}),
|
|
17
18
|
methods: {
|
|
18
19
|
async sendMessage() {
|
|
@@ -43,6 +44,11 @@ module.exports = app => app.component('chat', {
|
|
|
43
44
|
this.chatMessages.push(chatMessages[1]);
|
|
44
45
|
|
|
45
46
|
this.newMessage = '';
|
|
47
|
+
this.$nextTick(() => {
|
|
48
|
+
if (this.$refs.messageInput) {
|
|
49
|
+
this.$refs.messageInput.style.height = 'auto';
|
|
50
|
+
}
|
|
51
|
+
});
|
|
46
52
|
|
|
47
53
|
this.$nextTick(() => {
|
|
48
54
|
if (this.$refs.messagesContainer) {
|
|
@@ -53,6 +59,18 @@ module.exports = app => app.component('chat', {
|
|
|
53
59
|
this.sendingMessage = false;
|
|
54
60
|
}
|
|
55
61
|
},
|
|
62
|
+
handleEnter(ev) {
|
|
63
|
+
if (!ev.shiftKey) {
|
|
64
|
+
this.sendMessage();
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
adjustTextareaHeight(ev) {
|
|
68
|
+
const textarea = ev.target;
|
|
69
|
+
textarea.style.height = 'auto';
|
|
70
|
+
const lineHeight = parseInt(window.getComputedStyle(textarea).lineHeight, 10);
|
|
71
|
+
const maxHeight = lineHeight * 5;
|
|
72
|
+
textarea.style.height = Math.min(textarea.scrollHeight, maxHeight) + 'px';
|
|
73
|
+
},
|
|
56
74
|
selectThread(threadId) {
|
|
57
75
|
this.$router.push('/chat/' + threadId);
|
|
58
76
|
},
|
package/frontend/src/index.js
CHANGED
|
@@ -6,6 +6,7 @@ if (typeof process === 'undefined') {
|
|
|
6
6
|
|
|
7
7
|
const api = require('./api');
|
|
8
8
|
const mothership = require('./mothership');
|
|
9
|
+
const { routes } = require('./routes');
|
|
9
10
|
const vanillatoasts = require('vanillatoasts');
|
|
10
11
|
|
|
11
12
|
const app = Vue.createApp({
|
|
@@ -67,7 +68,7 @@ app.component('app-component', {
|
|
|
67
68
|
window.state = this;
|
|
68
69
|
|
|
69
70
|
if (mothership.hasAPIKey) {
|
|
70
|
-
const hash = window.location.hash.replace(
|
|
71
|
+
const hash = window.location.hash.replace(/^#?\/?/, '') || '';
|
|
71
72
|
const hashQuery = hash.split('?')[1] || '';
|
|
72
73
|
const hashParams = new URLSearchParams(hashQuery);
|
|
73
74
|
if (hashParams.has('code')) {
|
|
@@ -110,6 +111,7 @@ app.component('app-component', {
|
|
|
110
111
|
const { nodeEnv } = await api.status();
|
|
111
112
|
this.nodeEnv = nodeEnv;
|
|
112
113
|
}
|
|
114
|
+
|
|
113
115
|
this.status = 'loaded';
|
|
114
116
|
},
|
|
115
117
|
setup() {
|
|
@@ -126,7 +128,6 @@ app.component('app-component', {
|
|
|
126
128
|
}
|
|
127
129
|
});
|
|
128
130
|
|
|
129
|
-
const { routes } = require('./routes');
|
|
130
131
|
const router = VueRouter.createRouter({
|
|
131
132
|
history: VueRouter.createWebHashHistory(),
|
|
132
133
|
routes: routes.map(route => ({
|
|
@@ -136,6 +137,14 @@ const router = VueRouter.createRouter({
|
|
|
136
137
|
}))
|
|
137
138
|
});
|
|
138
139
|
|
|
140
|
+
router.beforeEach((to, from, next) => {
|
|
141
|
+
if (to.name === 'root' && window.state.roles && window.state.roles[0] === 'dashboards') {
|
|
142
|
+
return next({ name: 'dashboards' });
|
|
143
|
+
} else {
|
|
144
|
+
next();
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
|
|
139
148
|
app.use(router);
|
|
140
149
|
|
|
141
150
|
app.mount('#content');
|
|
@@ -1,16 +1,7 @@
|
|
|
1
|
-
.navbar {
|
|
2
|
-
width: 100%;
|
|
3
|
-
background-color: #eee;
|
|
4
|
-
}
|
|
5
|
-
|
|
6
1
|
.active {
|
|
7
2
|
text-decoration: underline;
|
|
8
3
|
}
|
|
9
4
|
|
|
10
|
-
.spacing {
|
|
11
|
-
margin-right: 10px;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
5
|
.navbar .nav-left {
|
|
15
6
|
float: left;
|
|
16
7
|
line-height: 54px;
|
|
@@ -22,18 +13,6 @@
|
|
|
22
13
|
color: #232323;
|
|
23
14
|
}
|
|
24
15
|
|
|
25
|
-
.navbar {
|
|
26
|
-
border-bottom: 1px solid #ddd;
|
|
27
|
-
height: 55px;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
.navbar .nav-left img {
|
|
31
|
-
height: 32px;
|
|
32
|
-
vertical-align: middle;
|
|
33
|
-
margin-right: 0.5em;
|
|
34
|
-
margin-top: 8px;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
16
|
.navbar .nav-right {
|
|
38
17
|
float: right;
|
|
39
18
|
display: flex;
|
|
@@ -1,26 +1,44 @@
|
|
|
1
|
-
<div class="navbar">
|
|
2
|
-
<div class="
|
|
1
|
+
<div class="navbar w-full bg-gray-50 flex justify-between border-b border-gray-200 !h-[55px]">
|
|
2
|
+
<div class="flex items-center gap-4 h-full pl-4">
|
|
3
3
|
<router-link :to="{ name: defaultRoute }">
|
|
4
|
-
<img src="images/logo.svg" alt="Mongoose Studio Logo" />
|
|
4
|
+
<img src="images/logo.svg" class="h-[32px] mr-1" alt="Mongoose Studio Logo" />
|
|
5
5
|
</router-link>
|
|
6
|
-
<div v-if="!!state.nodeEnv" class="inline-flex items-center rounded-md px-2 py-1 text-sm font-medium text-gray-900" :class="warnEnv ? 'bg-red-300' : 'bg-yellow-300'">
|
|
6
|
+
<div v-if="!!state.nodeEnv" title="NODE_ENV" class="inline-flex items-center rounded-md px-2 py-1 text-sm font-medium text-gray-900" :class="warnEnv ? 'bg-red-300' : 'bg-yellow-300'">
|
|
7
7
|
{{state.nodeEnv}}
|
|
8
8
|
</div>
|
|
9
9
|
</div>
|
|
10
|
-
<div class="
|
|
10
|
+
<div class="h-full pr-4 hidden md:block">
|
|
11
11
|
<div class="sm:ml-6 sm:flex sm:space-x-8 h-full">
|
|
12
12
|
<a v-if="hasAccess(roles, 'root')"
|
|
13
13
|
href="#/"
|
|
14
14
|
class="inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium"
|
|
15
15
|
:class="documentView ? 'text-gray-900 border-ultramarine-500' : 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700'">Documents</a>
|
|
16
|
+
<span v-else class="inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium text-gray-300 cursor-not-allowed" aria-disabled="true">
|
|
17
|
+
Documents
|
|
18
|
+
<svg class="h-4 w-4 ml-1" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
|
19
|
+
<path fill-rule="evenodd" d="M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z" clip-rule="evenodd" />
|
|
20
|
+
</svg>
|
|
21
|
+
</span>
|
|
16
22
|
<a v-if="hasAccess(roles, 'dashboards')"
|
|
17
23
|
href="#/dashboards"
|
|
18
24
|
class="inline-flex items-center border-b-2 px-1 pt-1 text-sm font-medium"
|
|
19
25
|
:class="dashboardView ? 'text-gray-900 border-ultramarine-500' : 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700'">Dashboards</a>
|
|
26
|
+
<span v-else class="inline-flex items-center border-b-2 px-1 pt-1 text-sm font-medium text-gray-300 cursor-not-allowed">
|
|
27
|
+
Dashboards
|
|
28
|
+
<svg class="h-4 w-4 ml-1" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
|
29
|
+
<path fill-rule="evenodd" d="M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z" clip-rule="evenodd" />
|
|
30
|
+
</svg>
|
|
31
|
+
</span>
|
|
20
32
|
<a v-if="hasAccess(roles, 'chat')"
|
|
21
33
|
href="#/chat"
|
|
22
34
|
class="inline-flex items-center border-b-2 px-1 pt-1 text-sm font-medium"
|
|
23
35
|
:class="chatView ? 'text-gray-900 border-ultramarine-500' : 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700'">Chat</a>
|
|
36
|
+
<span v-else class="inline-flex items-center border-b-2 px-1 pt-1 text-sm font-medium text-gray-300 cursor-not-allowed">
|
|
37
|
+
Chat
|
|
38
|
+
<svg class="h-4 w-4 ml-1" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
|
39
|
+
<path fill-rule="evenodd" d="M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z" clip-rule="evenodd" />
|
|
40
|
+
</svg>
|
|
41
|
+
</span>
|
|
24
42
|
|
|
25
43
|
<div class="h-full flex items-center" v-if="!user && hasAPIKey">
|
|
26
44
|
<button
|
|
@@ -41,11 +59,98 @@
|
|
|
41
59
|
|
|
42
60
|
<div v-if="showFlyout" class="absolute right-0 z-10 top-[90%] w-48 origin-top-right rounded-md bg-white py-1 shadow-lg ring-1 ring-black/5 focus:outline-none" role="menu" aria-orientation="vertical" aria-labelledby="user-menu-button" tabindex="-1">
|
|
43
61
|
<router-link to="/team" v-if="hasAccess(roles, 'team')" @click="showFlyout = false" class="cursor-pointer block px-4 py-2 text-sm text-gray-700 hover:bg-ultramarine-200" role="menuitem" tabindex="-1" id="user-menu-item-2">Team</router-link>
|
|
62
|
+
<span v-else class="block px-4 py-2 text-sm text-gray-300 cursor-not-allowed" role="menuitem" tabindex="-1" id="user-menu-item-2">
|
|
63
|
+
Team
|
|
64
|
+
<svg class="h-4 w-4 ml-1 inline" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
|
65
|
+
<path fill-rule="evenodd" d="M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z" clip-rule="evenodd" />
|
|
66
|
+
</svg>
|
|
67
|
+
</span>
|
|
44
68
|
<span @click="logout" class="cursor-pointer block px-4 py-2 text-sm text-gray-700 hover:bg-ultramarine-200" role="menuitem" tabindex="-1" id="user-menu-item-2">Sign out</span>
|
|
45
69
|
</div>
|
|
46
70
|
</div>
|
|
47
71
|
|
|
48
72
|
</div>
|
|
49
73
|
</div>
|
|
50
|
-
<div
|
|
74
|
+
<div class="md:hidden flex items-center">
|
|
75
|
+
<!-- Mobile menu toggle, controls the 'mobileMenuOpen' state. -->
|
|
76
|
+
<button type="button" id="open-mobile-menu" class="-ml-2 rounded-md p-2 pr-4 text-gray-400">
|
|
77
|
+
<span class="sr-only">Open menu</span>
|
|
78
|
+
<svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true">
|
|
79
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" />
|
|
80
|
+
</svg>
|
|
81
|
+
</button>
|
|
82
|
+
</div>
|
|
83
|
+
|
|
84
|
+
<!-- Mobile menu mask -->
|
|
85
|
+
<div id="mobile-menu-mask" class="fixed inset-0 bg-black bg-opacity-40 z-40 hidden"></div>
|
|
86
|
+
<!-- Mobile menu drawer -->
|
|
87
|
+
<div id="mobile-menu" class="fixed inset-0 bg-white shadow-lg z-50 transform translate-x-full transition-transform duration-200 ease-in-out flex flex-col">
|
|
88
|
+
<div class="flex items-center justify-between px-4 !h-[55px] border-b border-gray-200">
|
|
89
|
+
<router-link :to="{ name: defaultRoute }">
|
|
90
|
+
<img src="images/logo.svg" class="h-[32px]" alt="Mongoose Studio Logo" />
|
|
91
|
+
</router-link>
|
|
92
|
+
<button type="button" id="close-mobile-menu" class="text-gray-400 p-2 rounded-md">
|
|
93
|
+
<span class="sr-only">Close menu</span>
|
|
94
|
+
<svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true">
|
|
95
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
|
|
96
|
+
</svg>
|
|
97
|
+
</button>
|
|
98
|
+
</div>
|
|
99
|
+
<nav class="flex-1 px-4 py-4 space-y-2">
|
|
100
|
+
<a v-if="hasAccess(roles, 'root')"
|
|
101
|
+
href="#/"
|
|
102
|
+
class="block px-3 py-2 rounded-md text-base font-medium"
|
|
103
|
+
:class="documentView ? 'text-ultramarine-700 bg-ultramarine-100' : 'text-gray-700 hover:bg-gray-100'">Documents</a>
|
|
104
|
+
<span v-else class="block px-3 py-2 rounded-md text-base font-medium text-gray-300 cursor-not-allowed">
|
|
105
|
+
Documents
|
|
106
|
+
<svg class="h-4 w-4 ml-1 inline" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
|
107
|
+
<path fill-rule="evenodd" d="M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z" clip-rule="evenodd" />
|
|
108
|
+
</svg>
|
|
109
|
+
</span>
|
|
110
|
+
<a v-if="hasAccess(roles, 'dashboards')"
|
|
111
|
+
href="#/dashboards"
|
|
112
|
+
class="block px-3 py-2 rounded-md text-base font-medium"
|
|
113
|
+
:class="dashboardView ? 'text-ultramarine-700 bg-ultramarine-100' : 'text-gray-700 hover:bg-gray-100'">Dashboards</a>
|
|
114
|
+
<span v-else class="block px-3 py-2 rounded-md text-base font-medium text-gray-300 cursor-not-allowed">
|
|
115
|
+
Dashboards
|
|
116
|
+
<svg class="h-4 w-4 ml-1 inline" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
|
117
|
+
<path fill-rule="evenodd" d="M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z" clip-rule="evenodd" />
|
|
118
|
+
</svg>
|
|
119
|
+
</span>
|
|
120
|
+
<a v-if="hasAccess(roles, 'chat')"
|
|
121
|
+
href="#/chat"
|
|
122
|
+
class="block px-3 py-2 rounded-md text-base font-medium"
|
|
123
|
+
:class="chatView ? 'text-ultramarine-700 bg-ultramarine-100' : 'text-gray-700 hover:bg-gray-100'">Chat</a>
|
|
124
|
+
<span v-else class="block px-3 py-2 rounded-md text-base font-medium text-gray-300 cursor-not-allowed">
|
|
125
|
+
Chat
|
|
126
|
+
<svg class="h-4 w-4 ml-1 inline" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
|
127
|
+
<path fill-rule="evenodd" d="M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z" clip-rule="evenodd" />
|
|
128
|
+
</svg>
|
|
129
|
+
</span>
|
|
130
|
+
<div v-if="!user && hasAPIKey" class="mt-4">
|
|
131
|
+
<button
|
|
132
|
+
type="button"
|
|
133
|
+
@click="loginWithGithub"
|
|
134
|
+
class="w-full rounded bg-ultramarine-600 px-3 py-2 text-base font-semibold text-white shadow-sm hover:bg-ultramarine-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ultramarine-600">
|
|
135
|
+
Login
|
|
136
|
+
</button>
|
|
137
|
+
</div>
|
|
138
|
+
<div v-if="user && hasAPIKey" class="mt-4">
|
|
139
|
+
<div class="flex items-center gap-3 px-3 py-2 bg-gray-50 rounded-md">
|
|
140
|
+
<img class="size-8 rounded-full" :src="user.picture" alt="">
|
|
141
|
+
<span class="text-gray-900 font-medium">{{ user.name }}</span>
|
|
142
|
+
</div>
|
|
143
|
+
<div class="mt-2 space-y-1">
|
|
144
|
+
<router-link to="/team" v-if="hasAccess(roles, 'team')" class="block px-3 py-2 rounded-md text-base text-gray-700 hover:bg-ultramarine-100">Team</router-link>
|
|
145
|
+
<span v-else class="block px-3 py-2 rounded-md text-base text-gray-300 cursor-not-allowed">
|
|
146
|
+
Team
|
|
147
|
+
<svg class="h-4 w-4 ml-1 inline" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
|
148
|
+
<path fill-rule="evenodd" d="M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z" clip-rule="evenodd" />
|
|
149
|
+
</svg>
|
|
150
|
+
</span>
|
|
151
|
+
<span @click="logout" class="block px-3 py-2 rounded-md text-base text-gray-700 hover:bg-ultramarine-100 cursor-pointer">Sign out</span>
|
|
152
|
+
</div>
|
|
153
|
+
</div>
|
|
154
|
+
</nav>
|
|
155
|
+
</div>
|
|
51
156
|
</div>
|
|
@@ -15,13 +15,21 @@ module.exports = app => app.component('navbar', {
|
|
|
15
15
|
inject: ['state'],
|
|
16
16
|
data: () => ({ showFlyout: false }),
|
|
17
17
|
mounted: function() {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
18
|
+
const mobileMenuMask = document.querySelector('#mobile-menu-mask');
|
|
19
|
+
const mobileMenu = document.querySelector('#mobile-menu');
|
|
20
|
+
|
|
21
|
+
document.querySelector('#open-mobile-menu').addEventListener('click', (event) => {
|
|
22
|
+
event.stopPropagation();
|
|
23
|
+
mobileMenuMask.style.display = 'block';
|
|
24
|
+
mobileMenu.classList.remove('translate-x-full');
|
|
25
|
+
mobileMenu.classList.add('translate-x-0');
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
document.querySelector('body').addEventListener('click', () => {
|
|
29
|
+
mobileMenuMask.style.display = 'none';
|
|
30
|
+
mobileMenu.classList.remove('translate-x-0');
|
|
31
|
+
mobileMenu.classList.add('translate-x-full');
|
|
32
|
+
});
|
|
25
33
|
},
|
|
26
34
|
computed: {
|
|
27
35
|
dashboardView() {
|
|
@@ -45,11 +53,8 @@ module.exports = app => app.component('navbar', {
|
|
|
45
53
|
canViewTeam() {
|
|
46
54
|
return this.hasAccess(this.roles, 'team');
|
|
47
55
|
},
|
|
48
|
-
allowedRoutes() {
|
|
49
|
-
return routes.filter(route => this.hasAccess(this.roles, route.name));
|
|
50
|
-
},
|
|
51
56
|
defaultRoute() {
|
|
52
|
-
return this.
|
|
57
|
+
return this.roles && this.roles[0] === 'dashboards' ? 'dashboards' : 'root';
|
|
53
58
|
}
|
|
54
59
|
},
|
|
55
60
|
methods: {
|
package/frontend/src/routes.js
CHANGED
|
@@ -9,10 +9,12 @@ const roleAccess = {
|
|
|
9
9
|
dashboards: ['dashboards', 'dashboard']
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
+
const allowedRoutesForLocalDev = ['document', 'root', 'chat'];
|
|
13
|
+
|
|
12
14
|
// Helper function to check if a role has access to a route
|
|
13
15
|
function hasAccess(roles, routeName) {
|
|
14
16
|
// change to true for local development
|
|
15
|
-
if (!roles) return
|
|
17
|
+
if (!roles) return allowedRoutesForLocalDev.includes(routeName);
|
|
16
18
|
return roles.some(role => roleAccess[role]?.includes(routeName));
|
|
17
19
|
}
|
|
18
20
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mongoosejs/studio",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.97",
|
|
4
4
|
"description": "A sleek, powerful MongoDB UI with built-in dashboarding and auth, seamlessly integrated with your Express, Vercel, or Netlify app.",
|
|
5
5
|
"homepage": "https://studio.mongoosejs.io/",
|
|
6
6
|
"repository": {
|