From 42f902a7b6e8925e442e38e3c9b99d0f8e5e2cd6 Mon Sep 17 00:00:00 2001
From: Alexander Platov <sas_lord@mail.ru>
Date: Fri, 23 Jun 2023 13:51:56 +0300
Subject: [PATCH] UBER-504: correct display of optional presenters (#3452)

Signed-off-by: Alexander Platov <sas_lord@mail.ru>
---
 models/tracker/src/index.ts                   |   2 +-
 packages/theme/styles/components.scss         |  14 +--
 .../ui/src/components/EditWithIcon.svelte     |   2 +-
 .../src/components/list/ListItem.svelte       | 101 ++++++------------
 .../src/components/list/ListPresenter.svelte  |  62 +++++++++++
 5 files changed, 101 insertions(+), 80 deletions(-)
 create mode 100644 plugins/view-resources/src/components/list/ListPresenter.svelte

diff --git a/models/tracker/src/index.ts b/models/tracker/src/index.ts
index 41a9dcb2fa..6f491b14b5 100644
--- a/models/tracker/src/index.ts
+++ b/models/tracker/src/index.ts
@@ -477,6 +477,7 @@ export function createModel (builder: Builder): void {
         { key: 'comments', displayProps: { key: 'comments' } },
         { key: 'attachments', displayProps: { key: 'attachments' } },
         { key: '', label: tracker.string.SubIssues, presenter: tracker.component.SubIssuesSelector, props: {} },
+        { key: '', displayProps: { grow: true } },
         {
           key: 'labels',
           presenter: tags.component.LabelsPresenter,
@@ -524,7 +525,6 @@ export function createModel (builder: Builder): void {
           displayProps: { key: 'dueDate', optional: true, compression: true },
           props: { kind: 'list' }
         },
-        { key: '', displayProps: { grow: true } },
         {
           key: '',
           label: tracker.string.Estimation,
diff --git a/packages/theme/styles/components.scss b/packages/theme/styles/components.scss
index 2dd7d69a6d..895f01cdf2 100644
--- a/packages/theme/styles/components.scss
+++ b/packages/theme/styles/components.scss
@@ -916,15 +916,15 @@
 // Labels on the ListView
 .list-container .listitems-container,
 .list-container .listitems-container:hover,
-.list-container .button.list,
-.list-container .button.list:hover,
+.list-container .antiButton.list,
+.list-container .antiButton.list:hover,
 .list-container .datetime-button,
 .list-container .datetime-button:hover {
-  background-color: var(--theme-list-button-color);
-  .icon, .btn-icon {
-    margin-right: .5rem;
-    color: var(--theme-halfcontent-color) !important;
-  }
+  background-color: var(--theme-list-button-color) !important;
+
+  &:not(.only-icon) .btn-icon,
+  &:not(.only-icon) .icon { margin-right: .5rem !important; }
+  .icon, .btn-icon { color: var(--theme-halfcontent-color) !important; }
   .label {
     font-size: 0.8125rem !important;
     color: var(--theme-halfcontent-color) !important;
diff --git a/packages/ui/src/components/EditWithIcon.svelte b/packages/ui/src/components/EditWithIcon.svelte
index ed8b61d582..ee9856244d 100644
--- a/packages/ui/src/components/EditWithIcon.svelte
+++ b/packages/ui/src/components/EditWithIcon.svelte
@@ -72,7 +72,7 @@
 <style lang="scss">
   .editbox {
     padding: 0 0.25rem 0 0.5rem;
-    min-width: 10rem;
+    min-width: 8rem;
     color: var(--theme-caption-color);
     border-radius: 0.25rem;
 
diff --git a/plugins/view-resources/src/components/list/ListItem.svelte b/plugins/view-resources/src/components/list/ListItem.svelte
index f96fb254a2..fd08556306 100644
--- a/plugins/view-resources/src/components/list/ListItem.svelte
+++ b/plugins/view-resources/src/components/list/ListItem.svelte
@@ -13,16 +13,15 @@
 // limitations under the License.
 -->
 <script lang="ts">
-  import core, { AnyAttribute, Doc, getObjectValue } from '@hcengineering/core'
+  import { AnyAttribute, Doc, getObjectValue } from '@hcengineering/core'
   import notification from '@hcengineering/notification'
   import { getClient, updateAttribute } from '@hcengineering/presentation'
   import { CheckBox, Component, deviceOptionsStore as deviceInfo, IconCircles, tooltip } from '@hcengineering/ui'
   import { AttributeModel } from '@hcengineering/view'
   import { createEventDispatcher, onMount } from 'svelte'
-  import { FixedColumn } from '../..'
   import view from '../../plugin'
   import GrowPresenter from './GrowPresenter.svelte'
-  import DividerPresenter from './DividerPresenter.svelte'
+  import ListPresenter from './ListPresenter.svelte'
 
   export let docObject: Doc
   export let model: AttributeModel[]
@@ -65,14 +64,6 @@
     return (value: any) => onChange(value, docObject, attribute.key, attr)
   }
 
-  function joinProps (attribute: AttributeModel, object: Doc, props: Record<string, any>) {
-    const clearAttributeProps = attribute.props
-    if (attribute.attribute?.type._class === core.class.EnumOf) {
-      return { ...clearAttributeProps, type: attribute.attribute.type, ...props }
-    }
-    return { object, ...clearAttributeProps, ...props }
-  }
-
   let noCompressed: number
   $: if (model) {
     noCompressed = -1
@@ -129,63 +120,33 @@
       />
     </div>
   </div>
-  {#each model.filter((p) => !p.displayProps?.optional) as attributeModel, i}
+  {#each model.filter((p) => !(p.displayProps?.optional === true)) as attributeModel, i}
     {@const displayProps = attributeModel.displayProps}
     {#if !groupByKey || displayProps?.excludeByKey !== groupByKey}
-      {#if !(compactMode && displayProps?.compression)}
-        {#if displayProps?.grow}
-          <GrowPresenter />
-          {#each model.filter((p) => p.displayProps?.optional) as attributeModel, i}
-            {@const dp = attributeModel.displayProps}
-            {#if dp?.dividerBefore === true}
-              <DividerPresenter />
-            {/if}
-            {#if dp?.fixed}
-              <FixedColumn key={`list_item_${dp.key}`} justify={dp.fixed}>
-                <svelte:component
-                  this={attributeModel.presenter}
-                  value={getObjectValue(attributeModel.key, docObject)}
-                  kind={'list'}
-                  onChange={getOnChange(docObject, attributeModel)}
-                  {...joinProps(attributeModel, docObject, props)}
-                />
-              </FixedColumn>
-            {:else}
-              <svelte:component
-                this={attributeModel.presenter}
-                value={getObjectValue(attributeModel.key, docObject)}
-                onChange={getOnChange(docObject, attributeModel)}
-                kind={'list'}
-                compression={dp?.compression && i !== noCompressed}
-                {...joinProps(attributeModel, docObject, props)}
-              />
-            {/if}
-          {/each}
-        {:else}
-          {#if i !== 0 && displayProps?.dividerBefore === true}
-            <DividerPresenter />
-          {/if}
-          {#if displayProps?.fixed}
-            <FixedColumn key={`list_item_${displayProps.key}`} justify={displayProps.fixed}>
-              <svelte:component
-                this={attributeModel.presenter}
-                value={getObjectValue(attributeModel.key, docObject)}
-                kind={'list'}
-                onChange={getOnChange(docObject, attributeModel)}
-                {...joinProps(attributeModel, docObject, props)}
-              />
-            </FixedColumn>
-          {:else}
-            <svelte:component
-              this={attributeModel.presenter}
-              value={getObjectValue(attributeModel.key, docObject)}
-              onChange={getOnChange(docObject, attributeModel)}
-              kind={'list'}
-              compression={displayProps?.compression && i !== noCompressed}
-              {...joinProps(attributeModel, docObject, props)}
+      {#if displayProps?.grow}
+        <GrowPresenter />
+        {#if !compactMode}
+          {#each model.filter((p) => p.displayProps?.optional === true) as attrModel, j}
+            <ListPresenter
+              {docObject}
+              attributeModel={attrModel}
+              {props}
+              compression={j !== noCompressed}
+              value={getObjectValue(attrModel.key, docObject)}
+              onChange={getOnChange(docObject, attrModel)}
             />
-          {/if}
+          {/each}
         {/if}
+      {:else}
+        <ListPresenter
+          {docObject}
+          {attributeModel}
+          {props}
+          compression={i !== noCompressed}
+          value={getObjectValue(attributeModel.key, docObject)}
+          onChange={getOnChange(docObject, attributeModel)}
+          hideDivider={i === 0}
+        />
       {/if}
     {/if}
   {/each}
@@ -207,15 +168,13 @@
           {@const displayProps = attributeModel.displayProps}
           {@const value = getObjectValue(attributeModel.key, docObject)}
           {#if displayProps?.excludeByKey !== groupByKey && value !== undefined}
-            {#if j !== 0 && displayProps?.dividerBefore === true}
-              <DividerPresenter />
-            {/if}
-            <svelte:component
-              this={attributeModel.presenter}
+            <ListPresenter
+              {docObject}
+              {attributeModel}
+              {props}
               value={getObjectValue(attributeModel.key, docObject)}
               onChange={getOnChange(docObject, attributeModel)}
-              kind={'list'}
-              {...joinProps(attributeModel, docObject, props)}
+              hideDivider={j === 0}
             />
           {/if}
         {/each}
diff --git a/plugins/view-resources/src/components/list/ListPresenter.svelte b/plugins/view-resources/src/components/list/ListPresenter.svelte
new file mode 100644
index 0000000000..5dc25c8da0
--- /dev/null
+++ b/plugins/view-resources/src/components/list/ListPresenter.svelte
@@ -0,0 +1,62 @@
+<!--
+// Copyright © 2022 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 core, { Doc } from '@hcengineering/core'
+  import { AttributeModel } from '@hcengineering/view'
+  import { FixedColumn } from '../..'
+  import DividerPresenter from './DividerPresenter.svelte'
+
+  export let docObject: Doc
+  export let attributeModel: AttributeModel
+  export let onChange: ((value: any) => void) | undefined
+  export let value: any
+  export let props: Record<string, any>
+  export let compression: boolean = false
+  export let hideDivider: boolean = false
+
+  $: dp = attributeModel?.displayProps
+
+  function joinProps (attribute: AttributeModel, object: Doc, props: Record<string, any>) {
+    const clearAttributeProps = attribute.props
+    if (attribute.attribute?.type._class === core.class.EnumOf) {
+      return { ...clearAttributeProps, type: attribute.attribute.type, ...props }
+    }
+    return { object, ...clearAttributeProps, ...props }
+  }
+</script>
+
+{#if dp?.dividerBefore === true && !hideDivider}
+  <DividerPresenter />
+{/if}
+{#if dp?.fixed}
+  <FixedColumn key={`list_item_${dp.key}`} justify={dp.fixed}>
+    <svelte:component
+      this={attributeModel.presenter}
+      {value}
+      {onChange}
+      kind={'list'}
+      {...joinProps(attributeModel, docObject, props)}
+    />
+  </FixedColumn>
+{:else}
+  <svelte:component
+    this={attributeModel.presenter}
+    {value}
+    {onChange}
+    kind={'list'}
+    compression={dp?.compression && compression}
+    {...joinProps(attributeModel, docObject, props)}
+  />
+{/if}