mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
Implement chat panels
This commit is contained in:
parent
e61a8535aa
commit
e0da51be2e
|
@ -98,6 +98,9 @@ const updateGridWidth = async () => {
|
||||||
</keep-alive>
|
</keep-alive>
|
||||||
<component :is="Component" v-else />
|
<component :is="Component" v-else />
|
||||||
</router-view>
|
</router-view>
|
||||||
|
<div :class="$style.contentFooter">
|
||||||
|
<router-view name="footer" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div :id="APP_MODALS_ELEMENT_ID" :class="$style.modals">
|
<div :id="APP_MODALS_ELEMENT_ID" :class="$style.modals">
|
||||||
<Modals />
|
<Modals />
|
||||||
|
@ -145,11 +148,19 @@ const updateGridWidth = async () => {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
main {
|
main {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.contentFooter {
|
||||||
|
height: auto;
|
||||||
|
z-index: 1000000;
|
||||||
|
background: white;
|
||||||
|
border: 1px solid red;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
|
|
94
packages/editor-ui/src/components/CanvasChat/CanvasChat.vue
Normal file
94
packages/editor-ui/src/components/CanvasChat/CanvasChat.vue
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { useAssistantStore } from '@/stores/assistant.store';
|
||||||
|
import { useDebounce } from '@/composables/useDebounce';
|
||||||
|
import { useUsersStore } from '@/stores/users.store';
|
||||||
|
import { computed, ref } from 'vue';
|
||||||
|
import SlideTransition from '@/components/transitions/SlideTransition.vue';
|
||||||
|
import AskAssistantChat from 'n8n-design-system/components/AskAssistantChat/AskAssistantChat.vue';
|
||||||
|
import { useTelemetry } from '@/composables/useTelemetry';
|
||||||
|
|
||||||
|
const assistantStore = useAssistantStore();
|
||||||
|
const usersStore = useUsersStore();
|
||||||
|
const telemetry = useTelemetry();
|
||||||
|
|
||||||
|
const height = ref(0);
|
||||||
|
|
||||||
|
const chatWidth = ref(0);
|
||||||
|
const logsWidth = ref(0);
|
||||||
|
|
||||||
|
const rootStyles = computed(() => {
|
||||||
|
return {
|
||||||
|
'--chat-width': chatWidth.value + 'px',
|
||||||
|
'--logs-width': logsWidth.value + 'px',
|
||||||
|
'--panel-height': height.value + 'px',
|
||||||
|
};
|
||||||
|
});
|
||||||
|
function onResize(data) {
|
||||||
|
console.log('🚀 ~ onResize ~ direction:', data);
|
||||||
|
height.value = data.height;
|
||||||
|
// assistantStore.updateWindowWidth(data.width);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onResizeDebounced(data: { direction: string; x: number; width: number }) {
|
||||||
|
void useDebounce().callDebounced(onResize, { debounceTime: 10, trailing: true }, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onResizeHorizontal(
|
||||||
|
component: 'chat' | 'logs',
|
||||||
|
data: { direction: string; x: number; width: number },
|
||||||
|
) {
|
||||||
|
if (component === 'chat') {
|
||||||
|
chatWidth.value = data.width;
|
||||||
|
} else {
|
||||||
|
logsWidth.value = data.width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<n8n-resize-wrapper
|
||||||
|
v-show="true"
|
||||||
|
:supported-directions="['top']"
|
||||||
|
:class="$style.container"
|
||||||
|
:height="height"
|
||||||
|
data-test-id="ask-assistant-sidebar"
|
||||||
|
@resize="onResizeDebounced"
|
||||||
|
:style="rootStyles"
|
||||||
|
>
|
||||||
|
<div :class="$style.content">
|
||||||
|
<n8n-resize-wrapper
|
||||||
|
v-show="true"
|
||||||
|
:supported-directions="['right']"
|
||||||
|
:width="chatWidth"
|
||||||
|
:class="$style.chat"
|
||||||
|
@resize="(data) => onResizeHorizontal('chat', data)"
|
||||||
|
>
|
||||||
|
Chat
|
||||||
|
</n8n-resize-wrapper>
|
||||||
|
<div :class="$style.logs" @resize="(data) => onResizeHorizontal('logs', data)">Logs</div>
|
||||||
|
</div>
|
||||||
|
</n8n-resize-wrapper>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" module>
|
||||||
|
.container {
|
||||||
|
height: var(--panel-height);
|
||||||
|
min-height: 3rem;
|
||||||
|
flex-basis: content;
|
||||||
|
z-index: 300;
|
||||||
|
// transform: translateY(-18rem);
|
||||||
|
}
|
||||||
|
.content {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.chat {
|
||||||
|
width: var(--chat-width);
|
||||||
|
min-width: 5rem;
|
||||||
|
border-right: 2px solid var(--color-foreground-base);
|
||||||
|
}
|
||||||
|
.logs {
|
||||||
|
width: var(--logs-width);
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -24,6 +24,7 @@ const ErrorView = async () => await import('./views/ErrorView.vue');
|
||||||
const ForgotMyPasswordView = async () => await import('./views/ForgotMyPasswordView.vue');
|
const ForgotMyPasswordView = async () => await import('./views/ForgotMyPasswordView.vue');
|
||||||
const MainHeader = async () => await import('@/components/MainHeader/MainHeader.vue');
|
const MainHeader = async () => await import('@/components/MainHeader/MainHeader.vue');
|
||||||
const MainSidebar = async () => await import('@/components/MainSidebar.vue');
|
const MainSidebar = async () => await import('@/components/MainSidebar.vue');
|
||||||
|
const CanvasChat = async () => await import('@/components/CanvasChat/CanvasChat.vue');
|
||||||
const NodeView = async () => await import('@/views/NodeViewSwitcher.vue');
|
const NodeView = async () => await import('@/views/NodeViewSwitcher.vue');
|
||||||
const WorkflowExecutionsView = async () => await import('@/views/WorkflowExecutionsView.vue');
|
const WorkflowExecutionsView = async () => await import('@/views/WorkflowExecutionsView.vue');
|
||||||
const WorkflowExecutionsLandingPage = async () =>
|
const WorkflowExecutionsLandingPage = async () =>
|
||||||
|
@ -314,6 +315,7 @@ export const routes: RouteRecordRaw[] = [
|
||||||
default: NodeView,
|
default: NodeView,
|
||||||
header: MainHeader,
|
header: MainHeader,
|
||||||
sidebar: MainSidebar,
|
sidebar: MainSidebar,
|
||||||
|
footer: CanvasChat,
|
||||||
},
|
},
|
||||||
meta: {
|
meta: {
|
||||||
nodeView: true,
|
nodeView: true,
|
||||||
|
@ -346,6 +348,7 @@ export const routes: RouteRecordRaw[] = [
|
||||||
default: NodeView,
|
default: NodeView,
|
||||||
header: MainHeader,
|
header: MainHeader,
|
||||||
sidebar: MainSidebar,
|
sidebar: MainSidebar,
|
||||||
|
footer: CanvasChat,
|
||||||
},
|
},
|
||||||
meta: {
|
meta: {
|
||||||
nodeView: true,
|
nodeView: true,
|
||||||
|
|
Loading…
Reference in a new issue