From a028e83bb7419091c1b60d37c0d284632e77b14c Mon Sep 17 00:00:00 2001
From: Kristina <kristin.fefelova@gmail.com>
Date: Mon, 18 Mar 2024 13:51:26 +0400
Subject: [PATCH] Fix doc aside in chat (#5006)

Signed-off-by: Kristina Fefelova <kristin.fefelova@gmail.com>
---
 .../src/components/ChannelScrollView.svelte   | 15 ++--
 .../src/components/ChannelView.svelte         | 14 +---
 .../src/components/chat/ChannelAside.svelte   |  3 +-
 .../src/components/chat/DocAside.svelte       | 77 +++++++++++--------
 4 files changed, 61 insertions(+), 48 deletions(-)

diff --git a/plugins/chunter-resources/src/components/ChannelScrollView.svelte b/plugins/chunter-resources/src/components/ChannelScrollView.svelte
index 22647f1f68..8f01ca3a3a 100644
--- a/plugins/chunter-resources/src/components/ChannelScrollView.svelte
+++ b/plugins/chunter-resources/src/components/ChannelScrollView.svelte
@@ -364,10 +364,15 @@
     }
   }
 
-  $: void initializeScroll($isLoadingStore, separatorElement, $newTimestampStore)
+  $: newTimestamp = $newTimestampStore
+  $: separatorIndex =
+    newTimestamp !== undefined
+      ? displayMessages.findIndex((message) => (message.createdOn ?? 0) >= (newTimestamp ?? 0))
+      : -1
+  $: void initializeScroll($isLoadingStore, separatorElement, separatorIndex)
 
   let isInitialScrolling = true
-  async function initializeScroll (isLoading: boolean, separatorElement?: HTMLDivElement, newTimestamp?: Timestamp) {
+  async function initializeScroll (isLoading: boolean, separatorElement?: HTMLDivElement, separatorIndex?: number) {
     if (isLoading || isScrollInitialized) {
       return
     }
@@ -379,7 +384,7 @@
       await wait()
       scrollToMessage()
       isInitialScrolling = false
-    } else if (newTimestamp === undefined) {
+    } else if (separatorIndex === -1) {
       isScrollInitialized = true
       shouldWaitAndRead = true
       autoscroll = true
@@ -564,10 +569,10 @@
       {/if}
       <slot name="header" />
 
-      {#each displayMessages as message (message._id)}
+      {#each displayMessages as message, index (message._id)}
         {@const isSelected = message._id === selectedMessageId}
 
-        {#if message.createdOn === $newTimestampStore}
+        {#if separatorIndex === index}
           <ActivityMessagesSeparator bind:element={separatorElement} label={activity.string.New} />
         {/if}
 
diff --git a/plugins/chunter-resources/src/components/ChannelView.svelte b/plugins/chunter-resources/src/components/ChannelView.svelte
index 1f5b3dec96..2e2cffcc07 100644
--- a/plugins/chunter-resources/src/components/ChannelView.svelte
+++ b/plugins/chunter-resources/src/components/ChannelView.svelte
@@ -47,14 +47,10 @@
   $: withAside =
     !embedded && !isThreadOpened && !hierarchy.isDerived(context.attachedToClass, chunter.class.DirectMessage)
 
-  function toChannel (object?: Doc) {
+  function toChannel (object?: Doc): Channel | undefined {
     return object as Channel | undefined
   }
 
-  function toChannelRef (ref: Ref<Doc>) {
-    return ref as Ref<Channel>
-  }
-
   defineSeparators('aside', panelSeparators)
 </script>
 
@@ -87,13 +83,9 @@
         <Separator name="aside" float index={0} />
         <div class="antiPanel-wrap__content">
           {#if hierarchy.isDerived(context.attachedToClass, chunter.class.Channel)}
-            <ChannelAside
-              _id={toChannelRef(context.attachedTo)}
-              _class={context.attachedToClass}
-              object={toChannel(object)}
-            />
+            <ChannelAside _class={context.attachedToClass} object={toChannel(object)} />
           {:else}
-            <DocAside _id={context.attachedTo} _class={context.attachedToClass} {object} />
+            <DocAside _class={context.attachedToClass} {object} />
           {/if}
         </div>
       </div>
diff --git a/plugins/chunter-resources/src/components/chat/ChannelAside.svelte b/plugins/chunter-resources/src/components/chat/ChannelAside.svelte
index 941eae24e8..40fb0949a9 100644
--- a/plugins/chunter-resources/src/components/chat/ChannelAside.svelte
+++ b/plugins/chunter-resources/src/components/chat/ChannelAside.svelte
@@ -25,7 +25,6 @@
   import DocAside from './DocAside.svelte'
   import { joinChannel, leaveChannel } from '../../utils'
 
-  export let _id: Ref<ChunterSpace>
   export let _class: Ref<Class<ChunterSpace>>
   export let object: ChunterSpace | undefined
 
@@ -116,7 +115,7 @@
   }
 </script>
 
-<DocAside {_id} {_class} {object}>
+<DocAside {_class} {object}>
   {#if object && creatorPersonRef}
     <div class="popupPanel-body__aside-grid" style:margin-top="0">
       <span
diff --git a/plugins/chunter-resources/src/components/chat/DocAside.svelte b/plugins/chunter-resources/src/components/chat/DocAside.svelte
index fde7927751..ec7f6a64d4 100644
--- a/plugins/chunter-resources/src/components/chat/DocAside.svelte
+++ b/plugins/chunter-resources/src/components/chat/DocAside.svelte
@@ -14,13 +14,18 @@
 -->
 <script lang="ts">
   import { Class, Doc, Mixin, Ref } from '@hcengineering/core'
-  import { getClient } from '@hcengineering/presentation'
-  import { Label, Scroller } from '@hcengineering/ui'
-  import { DocAttributeBar, DocNavLink, getDocLinkTitle, getDocMixins } from '@hcengineering/view-resources'
+  import {
+    AttributeBarEditor,
+    getClient,
+    getFiltredKeys,
+    isCollectionAttr,
+    KeyedAttribute
+  } from '@hcengineering/presentation'
+  import { Scroller } from '@hcengineering/ui'
+  import { ClassAttributeBar, getDocMixins } from '@hcengineering/view-resources'
 
   import chunter from '../../plugin'
 
-  export let _id: Ref<Doc>
   export let _class: Ref<Class<Doc>>
   export let object: Doc | undefined
 
@@ -28,41 +33,53 @@
   const hierarchy = client.getHierarchy()
 
   let mixins: Array<Mixin<Doc>> = []
-  let objectLinkTitle: string | undefined = undefined
 
-  $: clazz = hierarchy.getClass(_class)
   $: objectChatPanel = hierarchy.classHierarchyMixin(_class, chunter.mixin.ObjectChatPanel)
 
   $: mixins = object ? getDocMixins(object) : []
 
-  $: getDocLinkTitle(client, _id, _class, object).then((res) => {
-    objectLinkTitle = res
-  })
+  function getMixinKeys (mixin: Ref<Mixin<Doc>>): KeyedAttribute[] {
+    if (object === undefined) return []
+
+    const mixinClass = hierarchy.getClass(mixin)
+    const filtredKeys = getFiltredKeys(
+      hierarchy,
+      mixin,
+      objectChatPanel?.ignoreKeys ?? [],
+      hierarchy.isMixin(mixinClass.extends as Ref<Class<Doc>>) ? mixinClass.extends : object._class
+    )
+    return filtredKeys.filter((key) => !isCollectionAttr(hierarchy, key))
+  }
 </script>
 
 <Scroller>
   {#if object}
-    <DocAttributeBar {object} {mixins} ignoreKeys={objectChatPanel?.ignoreKeys ?? []} showHeader={false} />
+    <ClassAttributeBar
+      _class={object._class}
+      {object}
+      ignoreKeys={objectChatPanel?.ignoreKeys ?? []}
+      showHeader={false}
+      readonly={false}
+      on:update
+    />
+    <div class="popupPanel-body__aside-grid">
+      {#each mixins as mixin}
+        {@const mixinKeys = getMixinKeys(mixin._id)}
+        {#if mixinKeys.length}
+          <div class="divider" />
+          {#each mixinKeys as key (typeof key === 'string' ? key : key.key)}
+            <AttributeBarEditor
+              {key}
+              _class={mixin._id}
+              readonly={false}
+              object={hierarchy.as(object, mixin._id)}
+              showHeader={true}
+              size={'medium'}
+            />
+          {/each}
+        {/if}
+      {/each}
+    </div>
   {/if}
   <slot />
 </Scroller>
-
-<style lang="scss">
-  .header {
-    display: flex;
-    flex-direction: column;
-    gap: 0.5rem;
-    flex-shrink: 0;
-    margin: 0.75rem;
-    padding: 0 0.75rem;
-    color: var(--theme-content-color);
-    margin-bottom: 0;
-  }
-
-  .identifier {
-    display: flex;
-    gap: 0.25rem;
-    color: var(--theme-halfcontent-color);
-    font-size: 0.75rem;
-  }
-</style>