UBERF-6068 Show collaborators in collaborative editors (#5335)

Signed-off-by: Alexander Onnikov <Alexander.Onnikov@xored.com>
This commit is contained in:
Alexander Onnikov
2024-04-15 18:11:47 +07:00
committed by GitHub
parent 07ff2a9d3c
commit 2220d7e19e
24 changed files with 296 additions and 69 deletions
@@ -14,13 +14,14 @@
-->
<script lang="ts">
import attachment, { Attachment } from '@hcengineering/attachment'
import contact from '@hcengineering/contact'
import { Account, Doc, Ref, generateId } from '@hcengineering/core'
import { IntlString, setPlatformStatus, unknownError } from '@hcengineering/platform'
import { IntlString, getResource, setPlatformStatus, unknownError } from '@hcengineering/platform'
import { KeyedAttribute, createQuery, getClient } from '@hcengineering/presentation'
import textEditor, { AttachIcon, CollaborativeAttributeBox, RefAction } from '@hcengineering/text-editor'
import { navigate } from '@hcengineering/ui'
import { AnySvelteComponent, navigate } from '@hcengineering/ui'
import view from '@hcengineering/view'
import { getObjectLinkFragment } from '@hcengineering/view-resources'
import { getCollaborationUser, getObjectLinkFragment } from '@hcengineering/view-resources'
import AttachmentsGrid from './AttachmentsGrid.svelte'
import { uploadFile } from '../utils'
import { defaultRefActions, getModelRefActions } from '@hcengineering/text-editor/src/components/editor/actions'
@@ -38,6 +39,12 @@
const client = getClient()
const user = getCollaborationUser()
let userComponent: AnySvelteComponent | undefined
void getResource(contact.component.CollaborationUserAvatar).then((component) => {
userComponent = component
})
let editor: CollaborativeAttributeBox
let refActions: RefAction[] = []
@@ -235,6 +242,8 @@
bind:this={editor}
{object}
{key}
{user}
{userComponent}
{focusIndex}
{placeholder}
{boundary}
+2 -1
View File
@@ -54,6 +54,7 @@
"@hcengineering/attachment": "^0.6.9",
"@hcengineering/login": "^0.6.8",
"@hcengineering/templates": "^0.6.7",
"@hcengineering/image-cropper": "^0.6.0"
"@hcengineering/image-cropper": "^0.6.0",
"@hcengineering/text-editor": "^0.6.0"
}
}
@@ -50,6 +50,7 @@
timer = null
update = undefined
}
// eslint-disable-next-line @typescript-eslint/no-misused-promises
timer = setTimeout(() => update?.(), 500)
}
@@ -0,0 +1,43 @@
<!--
//
// Copyright © 2024 Hardcore Engineering Inc.
//
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. You may
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
//
-->
<script lang="ts">
import { Employee, PersonAccount } from '@hcengineering/contact'
import { Ref } from '@hcengineering/core'
import { CollaborationUser } from '@hcengineering/text-editor'
import { IconSize } from '@hcengineering/ui'
import { employeeByIdStore, personAccountByIdStore, personByIdStore } from '../utils'
import Avatar from './Avatar.svelte'
export let user: CollaborationUser
export let lastUpdate: number
export let size: IconSize = 'x-small'
let avatar: Avatar | undefined
$: lastUpdate !== 0 && avatar?.pulse()
$: personAccount = $personAccountByIdStore.get(user.id as Ref<PersonAccount>)
$: person =
personAccount?.person !== undefined
? $employeeByIdStore.get(personAccount.person as Ref<Employee>) ?? $personByIdStore.get(personAccount.person)
: undefined
</script>
{#if person}
<Avatar bind:this={avatar} {size} avatar={person.avatar} name={person.name} borderColor={user.color} />
{/if}
+2
View File
@@ -57,6 +57,7 @@ import ContactsTabs from './components/ContactsTabs.svelte'
import CreateEmployee from './components/CreateEmployee.svelte'
import CreateOrganization from './components/CreateOrganization.svelte'
import CreatePerson from './components/CreatePerson.svelte'
import CollaborationUserAvatar from './components/CollaborationUserAvatar.svelte'
import DeleteConfirmationPopup from './components/DeleteConfirmationPopup.svelte'
import EditEmployee from './components/EditEmployee.svelte'
import EditMember from './components/EditMember.svelte'
@@ -303,6 +304,7 @@ export default async (): Promise<Resources> => ({
OrganizationPresenter,
ChannelsPresenter,
CreatePerson,
CollaborationUserAvatar,
CreateOrganization,
EditPerson,
EditEmployee,
+2 -1
View File
@@ -198,7 +198,8 @@ export const contactPlugin = plugin(contactId, {
DeleteConfirmationPopup: '' as AnyComponent,
AccountArrayEditor: '' as AnyComponent,
PersonIcon: '' as AnyComponent,
EditOrganizationPanel: '' as AnyComponent
EditOrganizationPanel: '' as AnyComponent,
CollaborationUserAvatar: '' as AnyComponent
},
channelProvider: {
Email: '' as Ref<ChannelProvider>,
@@ -15,8 +15,9 @@
//
-->
<script lang="ts">
import { Extensions, FocusPosition } from '@tiptap/core'
import contact from '@hcengineering/contact'
import { Document } from '@hcengineering/document'
import { getResource } from '@hcengineering/platform'
import {
CollaboratorEditor,
HeadingsExtension,
@@ -25,6 +26,9 @@
TodoItemExtension,
TodoListExtension
} from '@hcengineering/text-editor'
import { AnySvelteComponent } from '@hcengineering/ui'
import { getCollaborationUser } from '@hcengineering/view-resources'
import { Extensions, FocusPosition } from '@tiptap/core'
import { createEventDispatcher } from 'svelte'
import ToDoItemNodeView from './node-view/ToDoItemNodeView.svelte'
@@ -38,6 +42,12 @@
export let overflow: 'auto' | 'none' = 'none'
export let editorAttributes: Record<string, string> = {}
const user = getCollaborationUser()
let userComponent: AnySvelteComponent | undefined
void getResource(contact.component.CollaborationUserAvatar).then((component) => {
userComponent = component
})
let collabEditor: CollaboratorEditor
export function focus (position?: FocusPosition): void {
@@ -83,6 +93,8 @@
objectClass={object._class}
objectId={object._id}
objectAttr="content"
{user}
{userComponent}
{focusIndex}
{readonly}
{attachFile}
@@ -13,17 +13,26 @@
// limitations under the License.
-->
<script lang="ts">
import contact from '@hcengineering/contact'
import { Doc } from '@hcengineering/core'
import { getResource } from '@hcengineering/platform'
import { KeyedAttribute } from '@hcengineering/presentation'
import { CollaborativeAttributeSectionBox } from '@hcengineering/text-editor'
import { AnySvelteComponent } from '@hcengineering/ui'
import { getCollaborationUser } from '../utils'
export let object: Doc
export let key: KeyedAttribute
const user = getCollaborationUser()
let userComponent: AnySvelteComponent | undefined
void getResource(contact.component.CollaborationUserAvatar).then((component) => {
userComponent = component
})
</script>
{#key object._id}
{#key key.key}
<CollaborativeAttributeSectionBox {object} {key} label={key.attr.label} />
<CollaborativeAttributeSectionBox {object} {key} {user} {userComponent} label={key.attr.label} />
{/key}
{/key}
@@ -13,15 +13,24 @@
// limitations under the License.
-->
<script lang="ts">
import contact from '@hcengineering/contact'
import { Doc } from '@hcengineering/core'
import { getResource } from '@hcengineering/platform'
import { KeyedAttribute } from '@hcengineering/presentation'
import { CollaborativeAttributeSectionBox } from '@hcengineering/text-editor'
import { AnySvelteComponent } from '@hcengineering/ui'
import { getCollaborationUser } from '../utils'
export let object: Doc
export let key: KeyedAttribute
const user = getCollaborationUser()
let userComponent: AnySvelteComponent | undefined
void getResource(contact.component.CollaborationUserAvatar).then((component) => {
userComponent = component
})
</script>
{#key object._id}
<CollaborativeAttributeSectionBox {object} {key} label={key.attr.label} />
<CollaborativeAttributeSectionBox {object} {key} {user} {userComponent} label={key.attr.label} />
{/key}
+15 -1
View File
@@ -1,6 +1,6 @@
//
// Copyright © 2020, 2021 Anticrm Platform Contributors.
// Copyright © 2021 Hardcore Engineering Inc.
// Copyright © 2021, 2024 Hardcore Engineering Inc.
//
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. You may
@@ -65,8 +65,10 @@ import {
isAdminUser,
createQuery
} from '@hcengineering/presentation'
import { type CollaborationUser } from '@hcengineering/text-editor'
import {
ErrorPresenter,
getColorNumberByText,
getCurrentResolvedLocation,
getPanelURI,
getPlatformColorForText,
@@ -1402,3 +1404,15 @@ permissionsQuery.query(core.class.Space, {}, (res) => {
whitelist: whitelistedSpaces
})
})
export function getCollaborationUser (): CollaborationUser {
const me = getCurrentAccount() as PersonAccount
const color = getColorNumberByText(me.email)
return {
id: me._id,
name: me.email,
email: me.email,
color
}
}