mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-18 02:21:13 +00:00
feat(editor): Show avatars for users currently working on the same workflow (#7763)
This PR introduces the following changes: - New Vue stores: `collaborationStore` and `pushConnectionStore` - Front-end push connection handling overhaul: Keep only a singe connection open and handle it from the new store - Add user avatars in the editor header when there are multiple users working on the same workflow - Sending a heartbeat event to back-end service periodically to confirm user is still active - Back-end overhauls (authored by @tomi): - Implementing a cleanup procedure that removes inactive users - Refactoring collaboration service current implementation --------- Co-authored-by: Tomi Turtiainen <10324676+tomi@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
99a9ea497a
commit
77bc8ecd4b
@@ -56,18 +56,20 @@
|
||||
<span v-else class="tags"></span>
|
||||
|
||||
<PushConnectionTracker class="actions">
|
||||
<span class="activator">
|
||||
<span :class="`activator ${$style.group}`">
|
||||
<WorkflowActivator :workflow-active="isWorkflowActive" :workflow-id="currentWorkflowId" />
|
||||
</span>
|
||||
<enterprise-edition :features="[EnterpriseEditionFeature.Sharing]">
|
||||
<n8n-button
|
||||
type="secondary"
|
||||
class="mr-2xs"
|
||||
@click="onShareButtonClick"
|
||||
data-test-id="workflow-share-button"
|
||||
>
|
||||
{{ $locale.baseText('workflowDetails.share') }}
|
||||
</n8n-button>
|
||||
<div :class="$style.group">
|
||||
<collaboration-pane />
|
||||
<n8n-button
|
||||
type="secondary"
|
||||
@click="onShareButtonClick"
|
||||
data-test-id="workflow-share-button"
|
||||
>
|
||||
{{ $locale.baseText('workflowDetails.share') }}
|
||||
</n8n-button>
|
||||
</div>
|
||||
<template #fallback>
|
||||
<n8n-tooltip>
|
||||
<n8n-button type="secondary" :class="['mr-2xs', $style.disabledShareButton]">
|
||||
@@ -94,28 +96,30 @@
|
||||
</n8n-tooltip>
|
||||
</template>
|
||||
</enterprise-edition>
|
||||
<SaveButton
|
||||
type="primary"
|
||||
:saved="!this.isDirty && !this.isNewWorkflow"
|
||||
:disabled="isWorkflowSaving || readOnly"
|
||||
data-test-id="workflow-save-button"
|
||||
@click="onSaveButtonClick"
|
||||
/>
|
||||
<router-link
|
||||
v-if="isWorkflowHistoryFeatureEnabled"
|
||||
:to="workflowHistoryRoute"
|
||||
:class="$style.workflowHistoryButton"
|
||||
>
|
||||
<n8n-icon-button
|
||||
:disabled="isWorkflowHistoryButtonDisabled"
|
||||
data-test-id="workflow-history-button"
|
||||
type="tertiary"
|
||||
icon="history"
|
||||
size="medium"
|
||||
text
|
||||
<div :class="$style.group">
|
||||
<SaveButton
|
||||
type="primary"
|
||||
:saved="!this.isDirty && !this.isNewWorkflow"
|
||||
:disabled="isWorkflowSaving || readOnly"
|
||||
data-test-id="workflow-save-button"
|
||||
@click="onSaveButtonClick"
|
||||
/>
|
||||
</router-link>
|
||||
<div :class="$style.workflowMenuContainer">
|
||||
<router-link
|
||||
v-if="isWorkflowHistoryFeatureEnabled"
|
||||
:to="workflowHistoryRoute"
|
||||
:class="$style.workflowHistoryButton"
|
||||
>
|
||||
<n8n-icon-button
|
||||
:disabled="isWorkflowHistoryButtonDisabled"
|
||||
data-test-id="workflow-history-button"
|
||||
type="tertiary"
|
||||
icon="history"
|
||||
size="medium"
|
||||
text
|
||||
/>
|
||||
</router-link>
|
||||
</div>
|
||||
<div :class="[$style.workflowMenuContainer, $style.group]">
|
||||
<input
|
||||
:class="$style.hiddenInput"
|
||||
type="file"
|
||||
@@ -159,6 +163,7 @@ import SaveButton from '@/components/SaveButton.vue';
|
||||
import TagsDropdown from '@/components/TagsDropdown.vue';
|
||||
import InlineTextEdit from '@/components/InlineTextEdit.vue';
|
||||
import BreakpointsObserver from '@/components/BreakpointsObserver.vue';
|
||||
import CollaborationPane from '@/components/MainHeader/CollaborationPane.vue';
|
||||
import type { IUser, IWorkflowDataUpdate, IWorkflowDb, IWorkflowToShare } from '@/Interface';
|
||||
|
||||
import { saveAs } from 'file-saver';
|
||||
@@ -201,6 +206,7 @@ export default defineComponent({
|
||||
TagsDropdown,
|
||||
InlineTextEdit,
|
||||
BreakpointsObserver,
|
||||
CollaborationPane,
|
||||
},
|
||||
props: {
|
||||
readOnly: {
|
||||
@@ -681,7 +687,6 @@ $--header-spacing: 20px;
|
||||
line-height: $--text-line-height;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-right: 30px;
|
||||
|
||||
> span {
|
||||
margin-right: 5px;
|
||||
@@ -717,14 +722,15 @@ $--header-spacing: 20px;
|
||||
.actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--spacing-m);
|
||||
}
|
||||
</style>
|
||||
|
||||
<style module lang="scss">
|
||||
.workflowMenuContainer {
|
||||
margin-left: var(--spacing-2xs);
|
||||
.group {
|
||||
display: flex;
|
||||
gap: var(--spacing-xs);
|
||||
}
|
||||
|
||||
.hiddenInput {
|
||||
display: none;
|
||||
}
|
||||
@@ -740,8 +746,6 @@ $--header-spacing: 20px;
|
||||
.workflowHistoryButton {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
margin-left: var(--spacing-m);
|
||||
margin-right: var(--spacing-4xs);
|
||||
color: var(--color-text-dark);
|
||||
border-radius: var(--border-radius-base);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user