diff --git a/models/task/src/index.ts b/models/task/src/index.ts
index a2a8515b3f..fa25f1a24f 100644
--- a/models/task/src/index.ts
+++ b/models/task/src/index.ts
@@ -54,7 +54,7 @@ export const DOMAIN_TASK = 'task' as Domain
 export const DOMAIN_STATE = 'state' as Domain
 export const DOMAIN_KANBAN = 'kanban' as Domain
 @Model(task.class.State, core.class.Doc, DOMAIN_STATE, [task.interface.DocWithRank])
-@UX('State' as IntlString, undefined, undefined, 'rank')
+@UX('State' as IntlString, task.icon.TaskState, undefined, 'rank')
 export class TState extends TDoc implements State {
   @Prop(TypeString(), 'Title' as IntlString)
   title!: string
@@ -65,7 +65,7 @@ export class TState extends TDoc implements State {
 }
 
 @Model(task.class.DoneState, core.class.Doc, DOMAIN_STATE, [task.interface.DocWithRank])
-@UX('Done' as IntlString, undefined, undefined, 'title')
+@UX('Done' as IntlString, task.icon.TaskState, undefined, 'title')
 export class TDoneState extends TDoc implements DoneState {
   @Prop(TypeString(), 'Title' as IntlString)
   title!: string
diff --git a/plugins/activity-assets/assets/icons.svg b/plugins/activity-assets/assets/icons.svg
index 22075d5191..647f5be9a2 100644
--- a/plugins/activity-assets/assets/icons.svg
+++ b/plugins/activity-assets/assets/icons.svg
@@ -1,5 +1,5 @@
 <svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
-  <symbol id="activity" viewBox="0 0 20 20" width='20' height='20' fill="none">
+  <symbol id="activity" viewBox="0 0 20 20" width='16' height='16' fill="none">
     <path d="M6.03772 12.3181L8.532 9.07628L11.3772 11.3112L13.818 8.16095" stroke="white" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" fill='none'/>
     <ellipse cx="16.6632" cy="3.50027" rx="1.60183" ry="1.60183" stroke="white" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
     <path d="M12.4372 2.6001H6.38078C3.87125 2.6001 2.31519 4.37737 2.31519 6.8869V13.6222C2.31519 16.1318 3.84074 17.9014 6.38078 17.9014H13.5509C16.0604 17.9014 17.6165 16.1318 17.6165 13.6222V7.75647" stroke="white" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
diff --git a/plugins/activity-resources/src/components/TxView.svelte b/plugins/activity-resources/src/components/TxView.svelte
index f1b1220590..cca472e3a9 100644
--- a/plugins/activity-resources/src/components/TxView.svelte
+++ b/plugins/activity-resources/src/components/TxView.svelte
@@ -18,34 +18,26 @@
   import type { TxViewlet } from '@anticrm/activity'
   import activity from '@anticrm/activity'
   import contact, { EmployeeAccount, formatName } from '@anticrm/contact'
-  import core, { Class, Doc, Ref, TxCUD, TxUpdateDoc } from '@anticrm/core'
-  import { getResource, IntlString } from '@anticrm/platform'
+  import { Doc, Ref } from '@anticrm/core'
+  import { Asset, getResource } from '@anticrm/platform'
   import { getClient } from '@anticrm/presentation'
   import {
-    AnyComponent,
-    AnySvelteComponent,
     Component,
     Icon,
     IconEdit,
     IconMoreH,
     Label,
-    Menu,
-    showPopup,
-    TimeSince,
-    ShowMore
+    Menu, ShowMore, showPopup,
+    TimeSince
   } from '@anticrm/ui'
   import type { AttributeModel } from '@anticrm/view'
-  import { buildModel, getActions, getObjectPresenter } from '@anticrm/view-resources'
-  import { activityKey, ActivityKey, DisplayTx } from '../activity'
+  import { getActions } from '@anticrm/view-resources'
+  import { ActivityKey, DisplayTx } from '../activity'
+  import { getValue, TxDisplayViewlet, updateViewlet } from './utils'
 
   export let tx: DisplayTx
   export let viewlets: Map<ActivityKey, TxViewlet>
 
-  type TxDisplayViewlet =
-    | (Pick<TxViewlet, 'icon' | 'label' | 'display' | 'editable' | 'hideOnRemove'> & {
-        component?: AnyComponent | AnySvelteComponent
-      })
-    | undefined
 
   let ptx: DisplayTx | undefined
 
@@ -53,6 +45,7 @@
   let props: any
   let employee: EmployeeAccount | undefined
   let model: AttributeModel[] = []
+  let modelIcon: Asset | undefined = undefined
 
   let edit = false
 
@@ -66,43 +59,12 @@
 
   const client = getClient()
 
-  async function createPseudoViewlet (dtx: DisplayTx, label: string): Promise<TxDisplayViewlet> {
-    const doc = dtx.doc
-    if (doc === undefined) {
-      return
-    }
-    const docClass: Class<Doc> = client.getModel().getObject(doc._class)
-
-    const presenter = await getObjectPresenter(client, doc._class, { key: 'doc-presenter' })
-    if (presenter !== undefined) {
-      return {
-        display: 'inline',
-        icon: docClass.icon ?? activity.icon.Activity,
-        label: (`${label} ` + docClass.label) as IntlString,
-        component: presenter.presenter
-      }
-    }
-  }
-
-  async function updateViewlet (dtx: DisplayTx): Promise<{ viewlet: TxDisplayViewlet; id: Ref<TxCUD<Doc>> }> {
-    const key = activityKey(dtx.tx.objectClass, dtx.tx._class)
-    let viewlet: TxDisplayViewlet = viewlets.get(key)
-
-    props = { tx: dtx.tx, value: dtx.doc, edit }
-
-    if (viewlet === undefined && dtx.tx._class === core.class.TxCreateDoc) {
-      // Check if we have a class presenter we could have a pseudo viewlet based on class presenter.
-      viewlet = await createPseudoViewlet(dtx, 'created')
-    }
-    if (viewlet === undefined && dtx.tx._class === core.class.TxRemoveDoc) {
-      viewlet = await createPseudoViewlet(dtx, 'deleted')
-    }
-    return { viewlet, id: dtx.tx._id }
-  }
-
-  $: updateViewlet(tx).then((result) => {
+  $: updateViewlet(client, viewlets, tx).then((result) => {
     if (result.id === tx.tx._id) {
       viewlet = result.viewlet
+      model = result.model
+      modelIcon = result.modelIcon
+      props = { ...result.props, edit }
     }
   })
 
@@ -112,47 +74,7 @@
       employee = account
     })
 
-  $: if (tx.updateTx !== undefined) {
-    const _class = tx.updateTx.objectClass
-    const ops = {
-      client,
-      _class,
-      keys: Object.keys(tx.updateTx.operations).filter((id) => !id.startsWith('$')),
-      ignoreMissing: true
-    }
-    const hiddenAttrs = new Set([...client.getHierarchy().getAllAttributes(_class).entries()]
-      .filter(([, attr]) => attr.hidden === true)
-      .map(([k]) => k))
 
-    buildModel(ops).then((m) => {
-      model = m.filter((x) => !hiddenAttrs.has(x.key))
-    })
-  } else if (tx.mixinTx !== undefined) {
-    const _class = tx.mixinTx.mixin
-    const ops = {
-      client,
-      _class,
-      keys: Object.keys(tx.mixinTx.attributes).filter((id) => !id.startsWith('$')),
-      ignoreMissing: true
-    }
-    const hiddenAttrs = new Set([...client.getHierarchy().getAllAttributes(_class).entries()]
-      .filter(([, attr]) => attr.hidden === true)
-      .map(([k]) => k))
-
-    buildModel(ops).then((m) => {
-      model = m.filter((x) => !hiddenAttrs.has(x.key))
-    })
-  }
-
-  async function getValue (m: AttributeModel, utx: any): Promise<any> {
-    const val = (utx as any)[m.key]
-
-    if (client.getHierarchy().isDerived(m._class, core.class.Doc) && typeof val === 'string') {
-      // We have an reference, we need to find a real object to pass for presenter
-      return await client.findOne(m._class, { _id: val as Ref<Doc> })
-    }
-    return val
-  }
   const showMenu = async (ev: MouseEvent): Promise<void> => {
     const actions = await getActions(client, tx.doc as Doc)
     showPopup(
@@ -192,7 +114,11 @@
       {#if viewlet}
         <Icon icon={viewlet.icon} size="small" />
       {:else}
-        <Icon icon={activity.icon.Activity} size="small" />
+        {#if viewlet === undefined && model.length > 0}
+          <Icon icon={modelIcon !== undefined ? modelIcon : IconEdit} size="small" />
+        {:else}
+          <Icon icon={activity.icon.Activity} size="small" />
+        {/if}
       {/if}
     </div>
 
@@ -226,7 +152,7 @@
           {/if}
           {#if viewlet === undefined && model.length > 0 && tx.updateTx}
             {#each model as m}
-              {#await getValue(m, tx.updateTx.operations) then value}
+              {#await getValue(client, m, tx.updateTx.operations) then value}
                   {#if value === null}
                     <span>unset <Label label={m.label} /></span>
                   {:else}
@@ -237,7 +163,7 @@
             {/each}
           {:else if viewlet === undefined && model.length > 0 && tx.mixinTx}
             {#each model as m}
-              {#await getValue(m, tx.mixinTx.attributes) then value}
+              {#await getValue(client, m, tx.mixinTx.attributes) then value}
                   {#if value === null}
                     <span>unset <Label label={m.label} /></span>
                   {:else}
@@ -247,13 +173,11 @@
                 {/await}
             {/each}
           {:else if viewlet && viewlet.display === 'inline' && viewlet.component}
-            <div>
-              {#if typeof viewlet.component === 'string'}
-                <Component is={viewlet.component} {props} on:close={onCancelEdit} />
-              {:else}
-                <svelte:component this={viewlet.component} {...props} on:close={onCancelEdit} />
-              {/if}
-            </div>
+            {#if typeof viewlet.component === 'string'}
+              <Component is={viewlet.component} {props} on:close={onCancelEdit} />
+            {:else}
+              <svelte:component this={viewlet.component} {...props} on:close={onCancelEdit} />
+            {/if}
           {/if}
         </div>
         <div class="time"><TimeSince value={tx.tx.modifiedOn} /></div>    
diff --git a/plugins/activity-resources/src/components/utils.ts b/plugins/activity-resources/src/components/utils.ts
new file mode 100644
index 0000000000..250d2154f3
--- /dev/null
+++ b/plugins/activity-resources/src/components/utils.ts
@@ -0,0 +1,135 @@
+import type { TxViewlet } from '@anticrm/activity'
+import activity from '@anticrm/activity'
+import core, { Class, Client, Doc, Ref, TxCUD, TxOperations } from '@anticrm/core'
+import { Asset, IntlString } from '@anticrm/platform'
+import { AnyComponent, AnySvelteComponent } from '@anticrm/ui'
+import { AttributeModel } from '@anticrm/view'
+import { buildModel, getObjectPresenter } from '@anticrm/view-resources'
+import { ActivityKey, activityKey, DisplayTx } from '../activity'
+
+export type TxDisplayViewlet =
+  | (Pick<TxViewlet, 'icon' | 'label' | 'display' | 'editable' | 'hideOnRemove'> & {
+    component?: AnyComponent | AnySvelteComponent
+  })
+  | undefined
+
+async function createPseudoViewlet (
+  client: Client & TxOperations,
+  dtx: DisplayTx,
+  label: string
+): Promise<TxDisplayViewlet> {
+  const doc = dtx.doc
+  if (doc === undefined) {
+    return
+  }
+  const docClass: Class<Doc> = client.getModel().getObject(doc._class)
+
+  const presenter = await getObjectPresenter(client, doc._class, { key: 'doc-presenter' })
+  if (presenter !== undefined) {
+    return {
+      display: 'inline',
+      icon: docClass.icon ?? activity.icon.Activity,
+      label: (`${label} ` + docClass.label) as IntlString,
+      component: presenter.presenter
+    }
+  }
+}
+
+export async function updateViewlet (
+  client: Client & TxOperations,
+  viewlets: Map<ActivityKey, TxViewlet>,
+  dtx: DisplayTx
+): Promise<{
+    viewlet: TxDisplayViewlet
+    id: Ref<TxCUD<Doc>>
+    model: AttributeModel[]
+    props: any
+    modelIcon: Asset | undefined
+  }> {
+  const key = activityKey(dtx.tx.objectClass, dtx.tx._class)
+  let viewlet: TxDisplayViewlet = viewlets.get(key)
+
+  const props = { tx: dtx.tx, value: dtx.doc, dtx }
+  let model: AttributeModel[] = []
+  let modelIcon: Asset | undefined
+
+  if (viewlet === undefined) {
+    ;({ viewlet, model } = await checkInlineViewlets(dtx, viewlet, client, model))
+    if (model !== undefined) {
+      // Check for State attribute
+      for (const a of model) {
+        if (a.icon !== undefined) {
+          modelIcon = a.icon
+          break
+        }
+      }
+    }
+  }
+  return { viewlet, id: dtx.tx._id, model, props, modelIcon }
+}
+
+async function checkInlineViewlets (
+  dtx: DisplayTx,
+  viewlet: TxDisplayViewlet,
+  client: Client & TxOperations,
+  model: AttributeModel[]
+): Promise<{ viewlet: TxDisplayViewlet, model: AttributeModel[] }> {
+  if (dtx.tx._class === core.class.TxCreateDoc) {
+    // Check if we have a class presenter we could have a pseudo viewlet based on class presenter.
+    viewlet = await createPseudoViewlet(client, dtx, 'created')
+  }
+  if (dtx.tx._class === core.class.TxRemoveDoc) {
+    viewlet = await createPseudoViewlet(client, dtx, 'deleted')
+  }
+  if (dtx.tx._class === core.class.TxUpdateDoc) {
+    model = await createUpdateModel(dtx, client, model)
+  }
+  return { viewlet, model }
+}
+
+async function createUpdateModel (
+  dtx: DisplayTx,
+  client: Client & TxOperations,
+  model: AttributeModel[]
+): Promise<AttributeModel[]> {
+  if (dtx.updateTx !== undefined) {
+    const _class = dtx.updateTx.objectClass
+    const ops = {
+      client,
+      _class,
+      keys: Object.keys(dtx.updateTx.operations).filter((id) => !id.startsWith('$')),
+      ignoreMissing: true
+    }
+    const hiddenAttrs = getHiddenAttrs(client, _class)
+    model = (await buildModel(ops)).filter((x) => !hiddenAttrs.has(x.key))
+  } else if (dtx.mixinTx !== undefined) {
+    const _class = dtx.mixinTx.mixin
+    const ops = {
+      client,
+      _class,
+      keys: Object.keys(dtx.mixinTx.attributes).filter((id) => !id.startsWith('$')),
+      ignoreMissing: true
+    }
+    const hiddenAttrs = getHiddenAttrs(client, _class)
+    model = (await buildModel(ops)).filter((x) => !hiddenAttrs.has(x.key))
+  }
+  return model
+}
+
+function getHiddenAttrs (client: Client & TxOperations, _class: Ref<Class<Doc>>): Set<string> {
+  return new Set(
+    [...client.getHierarchy().getAllAttributes(_class).entries()]
+      .filter(([, attr]) => attr.hidden === true)
+      .map(([k]) => k)
+  )
+}
+
+export async function getValue (client: Client & TxOperations, m: AttributeModel, utx: any): Promise<any> {
+  const val = utx[m.key]
+
+  if (client.getHierarchy().isDerived(m._class, core.class.Doc) && typeof val === 'string') {
+    // We have an reference, we need to find a real object to pass for presenter
+    return await client.findOne(m._class, { _id: val as Ref<Doc> })
+  }
+  return val
+}
diff --git a/plugins/task-assets/assets/icons.svg b/plugins/task-assets/assets/icons.svg
index 48d2c7308f..bb89076f86 100644
--- a/plugins/task-assets/assets/icons.svg
+++ b/plugins/task-assets/assets/icons.svg
@@ -19,4 +19,8 @@
     <path d="M13.3,8.3c-0.1,2.8-2.5,5.1-5.4,5.1C5,13.4,2.6,11,2.6,8c0-2.9,2.3-5.2,5.1-5.4c0.1-0.4,0.2-0.7,0.4-1c0,0-0.1,0-0.1,0 C4.4,1.7,1.6,4.5,1.6,8c0,3.5,2.9,6.4,6.4,6.4s6.4-2.9,6.4-6.4c0,0,0-0.1,0-0.1C14,8.1,13.7,8.2,13.3,8.3z"/>
     <ellipse cx="12.1" cy="3.9" rx="2.5" ry="2.5"/>
   </symbol>
+  <symbol id="task-state" viewBox="0 0 16 16">
+    <path d="M13.3,8.3c-0.1,2.8-2.5,5.1-5.4,5.1C5,13.4,2.6,11,2.6,8c0-2.9,2.3-5.2,5.1-5.4c0.1-0.4,0.2-0.7,0.4-1c0,0-0.1,0-0.1,0 C4.4,1.7,1.6,4.5,1.6,8c0,3.5,2.9,6.4,6.4,6.4s6.4-2.9,6.4-6.4c0,0,0-0.1,0-0.1C14,8.1,13.7,8.2,13.3,8.3z"/>
+    <ellipse cx="12.1" cy="3.9" rx="2.5" ry="2.5"/>
+  </symbol>
 </svg>
diff --git a/plugins/task-assets/src/index.ts b/plugins/task-assets/src/index.ts
index 36e9231e03..b18b8aea69 100644
--- a/plugins/task-assets/src/index.ts
+++ b/plugins/task-assets/src/index.ts
@@ -22,7 +22,8 @@ loadMetadata(task.icon, {
   Kanban: `${icons}#kanban`,
   TodoCheck: `${icons}#todo-check`,
   TodoUnCheck: `${icons}#todo-uncheck`,
-  ManageStatuses: `${icons}#manage-statuses`
+  ManageStatuses: `${icons}#manage-statuses`,
+  TaskState: `${icons}#task-state`
 })
 
 addStringsLoader(taskId, async (lang: string) => await import(`../lang/${lang}.json`))
diff --git a/plugins/task/src/index.ts b/plugins/task/src/index.ts
index b82e99e808..4fc9991b3b 100644
--- a/plugins/task/src/index.ts
+++ b/plugins/task/src/index.ts
@@ -212,7 +212,8 @@ const task = plugin(taskId, {
     Kanban: '' as Asset,
     TodoCheck: '' as Asset,
     TodoUnCheck: '' as Asset,
-    ManageStatuses: '' as Asset
+    ManageStatuses: '' as Asset,
+    TaskState: '' as Asset
   },
   global: {
     // Global task root, if not attached to some other object.
diff --git a/plugins/view-resources/src/utils.ts b/plugins/view-resources/src/utils.ts
index 1b4689694e..918a921506 100644
--- a/plugins/view-resources/src/utils.ts
+++ b/plugins/view-resources/src/utils.ts
@@ -79,7 +79,8 @@ async function getAttributePresenter (client: Client, _class: Ref<Class<Obj>>, k
     sortingKey,
     _class: attrClass,
     label: preserveKey.label ?? attribute.label,
-    presenter
+    presenter,
+    icon: presenterMixin.icon
   }
 }
 
@@ -141,7 +142,6 @@ export async function buildModel (options: BuildModelOptions): Promise<Attribute
       return errorPresenter
     }
   })
-  console.log(model)
   return (await Promise.all(model)).filter(a => a !== undefined) as AttributeModel[]
 }
 
diff --git a/plugins/view/src/index.ts b/plugins/view/src/index.ts
index 79fe0458e3..2f7e5e1f06 100644
--- a/plugins/view/src/index.ts
+++ b/plugins/view/src/index.ts
@@ -108,6 +108,8 @@ export interface AttributeModel {
   // Extra properties for component
   props?: Record<string, any>
   sortingKey: string
+  // Extra icon if applicable
+  icon?: Asset
 }
 
 /**