diff --git a/models/setting/src/index.ts b/models/setting/src/index.ts
index 606f6b56d0..62356f0a82 100644
--- a/models/setting/src/index.ts
+++ b/models/setting/src/index.ts
@@ -302,6 +302,10 @@ export function createModel (builder: Builder): void {
     editor: setting.component.EnumTypeEditor
   })
 
+  builder.mixin(core.class.ArrOf, core.class.Class, view.mixin.ObjectEditor, {
+    editor: setting.component.ArrayEditor
+  })
+
   builder.mixin(core.class.Class, core.class.Class, view.mixin.IgnoreActions, {
     actions: [view.action.Delete]
   })
diff --git a/models/setting/src/plugin.ts b/models/setting/src/plugin.ts
index 44945b2373..987572a17b 100644
--- a/models/setting/src/plugin.ts
+++ b/models/setting/src/plugin.ts
@@ -40,7 +40,8 @@ export default mergeIds(settingId, setting, {
     RefEditor: '' as AnyComponent,
     EnumTypeEditor: '' as AnyComponent,
     Owners: '' as AnyComponent,
-    CreateMixin: '' as AnyComponent
+    CreateMixin: '' as AnyComponent,
+    ArrayEditor: '' as AnyComponent
   },
   category: {
     Settings: '' as Ref<ActionCategory>
diff --git a/models/view/src/index.ts b/models/view/src/index.ts
index 5778485794..eec97f03ff 100644
--- a/models/view/src/index.ts
+++ b/models/view/src/index.ts
@@ -383,6 +383,9 @@ export function createModel (builder: Builder): void {
   builder.mixin(core.class.Class, core.class.Class, view.mixin.ObjectPresenter, {
     presenter: view.component.ClassPresenter
   })
+  builder.mixin(core.class.EnumOf, core.class.Class, view.mixin.ArrayEditor, {
+    inlineEditor: view.component.EnumArrayEditor
+  })
 
   classPresenter(builder, core.class.TypeRelatedDocument, view.component.ObjectPresenter)
 
diff --git a/models/view/src/plugin.ts b/models/view/src/plugin.ts
index afc7f13e10..ebcc6fc221 100644
--- a/models/view/src/plugin.ts
+++ b/models/view/src/plugin.ts
@@ -60,6 +60,7 @@ export default mergeIds(viewId, view, {
     ClassPresenter: '' as AnyComponent,
     ClassRefPresenter: '' as AnyComponent,
     EnumEditor: '' as AnyComponent,
+    EnumArrayEditor: '' as AnyComponent,
     HTMLEditor: '' as AnyComponent,
     MarkupEditor: '' as AnyComponent,
     MarkupEditorPopup: '' as AnyComponent,
diff --git a/packages/ui/src/components/DropdownLabels.svelte b/packages/ui/src/components/DropdownLabels.svelte
index 976e7a4dd2..aaffcf6055 100644
--- a/packages/ui/src/components/DropdownLabels.svelte
+++ b/packages/ui/src/components/DropdownLabels.svelte
@@ -27,7 +27,8 @@
   export let label: IntlString
   export let placeholder: IntlString | undefined = ui.string.SearchDots
   export let items: DropdownTextItem[]
-  export let selected: DropdownTextItem['id'] | undefined = undefined
+  export let multiselect = false
+  export let selected: DropdownTextItem['id'] | DropdownTextItem['id'][] | undefined = multiselect ? [] : undefined
 
   export let kind: ButtonKind = 'no-border'
   export let size: ButtonSize = 'small'
@@ -41,13 +42,10 @@
 
   let container: HTMLElement
   let opened: boolean = false
-  let isDisabled = false
-  $: isDisabled = items.length === 0
 
-  let selectedItem = items.find((x) => x.id === selected)
-  $: selectedItem = items.find((x) => x.id === selected)
+  $: selectedItem = multiselect ? items.filter((p) => selected?.includes(p.id)) : items.find((x) => x.id === selected)
   $: if (autoSelect && selected === undefined && items[0] !== undefined) {
-    selected = items[0].id
+    selected = multiselect ? [items[0].id] : items[0].id
   }
 
   const dispatch = createEventDispatcher()
@@ -66,19 +64,42 @@
     on:click={() => {
       if (!opened) {
         opened = true
-        showPopup(DropdownLabelsPopup, { placeholder, items, selected }, container, (result) => {
-          if (result) {
-            selected = result
-            dispatch('selected', result)
+        showPopup(
+          DropdownLabelsPopup,
+          { placeholder, items, multiselect, selected },
+          container,
+          (result) => {
+            if (result) {
+              selected = result
+              dispatch('selected', result)
+            }
+            opened = false
+            mgr?.setFocusPos(focusIndex)
+          },
+          (result) => {
+            if (result) {
+              selected = result
+              dispatch('selected', result)
+            }
           }
-          opened = false
-          mgr?.setFocusPos(focusIndex)
-        })
+        )
       }
     }}
   >
     <span slot="content" class="overflow-label disabled" class:content-color={selectedItem === undefined}>
-      {#if selectedItem}{selectedItem.label}{:else}<Label label={label ?? ui.string.NotSelected} />{/if}
+      {#if Array.isArray(selectedItem)}
+        {#if selectedItem.length > 0}
+          {#each selectedItem as seleceted, i}
+            <span class:ml-1={i !== 0}>{seleceted.label}</span>
+          {/each}
+        {:else}
+          <Label label={label ?? ui.string.NotSelected} />
+        {/if}
+      {:else if selectedItem}
+        {selectedItem.label}
+      {:else}
+        <Label label={label ?? ui.string.NotSelected} />
+      {/if}
     </span>
   </Button>
 </div>
diff --git a/packages/ui/src/components/DropdownLabelsPopup.svelte b/packages/ui/src/components/DropdownLabelsPopup.svelte
index 7a1cd2068a..24f63a2007 100644
--- a/packages/ui/src/components/DropdownLabelsPopup.svelte
+++ b/packages/ui/src/components/DropdownLabelsPopup.svelte
@@ -24,7 +24,8 @@
 
   export let placeholder: IntlString = plugin.string.SearchDots
   export let items: DropdownTextItem[]
-  export let selected: DropdownTextItem['id'] | undefined = undefined
+  export let selected: DropdownTextItem['id'] | DropdownTextItem['id'][] | undefined = undefined
+  export let multiselect: boolean = false
 
   let search: string = ''
   let phTraslate: string = ''
@@ -45,8 +46,18 @@
 
   async function handleSelection (evt: Event | undefined, selection: number): Promise<void> {
     const item = objects[selection]
-
-    dispatch('close', item.id)
+    if (multiselect && Array.isArray(selected)) {
+      const index = selected.indexOf(item.id)
+      if (index !== -1) {
+        selected.splice(index, 1)
+        selected = selected
+      } else {
+        selected = selected === undefined ? [item.id] : [...selected, item.id]
+      }
+      dispatch('update', selected)
+    } else {
+      dispatch('close', item.id)
+    }
   }
 
   function onKeydown (key: KeyboardEvent): void {
@@ -71,6 +82,17 @@
       dispatch('close')
     }
   }
+
+  function isSelected (
+    selected: DropdownTextItem['id'] | DropdownTextItem['id'][] | undefined,
+    item: DropdownTextItem
+  ): boolean {
+    if (Array.isArray(selected)) {
+      return selected.includes(item.id)
+    } else {
+      return item.id === selected
+    }
+  }
 </script>
 
 <div
@@ -99,11 +121,22 @@
           <button
             class="menu-item flex-between w-full"
             on:click={() => {
-              dispatch('close', item.id)
+              if (multiselect && Array.isArray(selected)) {
+                const index = selected.indexOf(item.id)
+                if (index !== -1) {
+                  selected.splice(index, 1)
+                  selected = selected
+                } else {
+                  selected = selected === undefined ? [item.id] : [...selected, item.id]
+                }
+                dispatch('update', selected)
+              } else {
+                dispatch('close', item.id)
+              }
             }}
           >
             <div class="flex-grow caption-color lines-limit-2">{item.label}</div>
-            {#if item.id === selected}
+            {#if isSelected(selected, item)}
               <div class="check-right"><CheckBox checked primary /></div>
             {/if}
           </button>
diff --git a/plugins/setting-resources/src/components/typeEditors/ArrayEditor.svelte b/plugins/setting-resources/src/components/typeEditors/ArrayEditor.svelte
new file mode 100644
index 0000000000..c70f869223
--- /dev/null
+++ b/plugins/setting-resources/src/components/typeEditors/ArrayEditor.svelte
@@ -0,0 +1,89 @@
+<!--
+// 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, { ArrOf, Class, Doc, Ref, Type } from '@hcengineering/core'
+  import { ArrOf as createArrOf } from '@hcengineering/model'
+  import { getClient } from '@hcengineering/presentation'
+  import { AnyComponent, Component, DropdownLabelsIntl, Label } from '@hcengineering/ui'
+  import view from '@hcengineering/view'
+  import { createEventDispatcher } from 'svelte'
+  import setting from '../../plugin'
+
+  export let type: ArrOf<Doc> | undefined
+  export let editable: boolean = true
+
+  const dispatch = createEventDispatcher()
+  const client = getClient()
+  const hierarchy = client.getHierarchy()
+
+  const descendants = hierarchy.getDescendants(core.class.Type)
+
+  const types: Class<Type<Doc>>[] = descendants
+    .map((p) => hierarchy.getClass(p))
+    .filter((p) => {
+      return (
+        hierarchy.hasMixin(p, view.mixin.ArrayEditor) &&
+        hierarchy.hasMixin(p, view.mixin.ObjectEditor) &&
+        p.label !== undefined
+      )
+    })
+
+  let refClass: Ref<Doc> | undefined = type !== undefined ? hierarchy.getClass(type.of._class)._id : undefined
+
+  $: selected = types.find((p) => p._id === refClass)
+
+  const handleChange = (e: any) => {
+    const type = e.detail?.type
+    const res = { type: createArrOf(type) }
+    dispatch('change', res)
+  }
+
+  function getComponent (selected: Class<Type<Doc>>): AnyComponent {
+    const editor = hierarchy.as(selected, view.mixin.ObjectEditor)
+    return editor.editor
+  }
+</script>
+
+<div class="flex-col">
+  <div class="flex-row-center flex-grow">
+    <Label label={setting.string.Type} />
+    <div class="ml-4">
+      {#if editable}
+        <DropdownLabelsIntl
+          label={core.string.Class}
+          items={types.map((p) => {
+            return { id: p._id, label: p.label }
+          })}
+          width="8rem"
+          bind:selected={refClass}
+        />
+      {:else if selected}
+        <Label label={selected.label} />
+      {/if}
+    </div>
+  </div>
+  {#if selected}
+    <div class="flex mt-4">
+      <Component
+        is={getComponent(selected)}
+        props={{
+          type: type?.of,
+          editable
+        }}
+        on:change={handleChange}
+      />
+    </div>
+  {/if}
+</div>
diff --git a/plugins/setting-resources/src/index.ts b/plugins/setting-resources/src/index.ts
index d1ab450c60..52b660542f 100644
--- a/plugins/setting-resources/src/index.ts
+++ b/plugins/setting-resources/src/index.ts
@@ -38,6 +38,7 @@ import DateTypeEditor from './components/typeEditors/DateTypeEditor.svelte'
 import EnumTypeEditor from './components/typeEditors/EnumTypeEditor.svelte'
 import HyperlinkTypeEditor from './components/typeEditors/HyperlinkTypeEditor.svelte'
 import NumberTypeEditor from './components/typeEditors/NumberTypeEditor.svelte'
+import ArrayEditor from './components/typeEditors/ArrayEditor.svelte'
 import RefEditor from './components/typeEditors/RefEditor.svelte'
 import StringTypeEditor from './components/typeEditors/StringTypeEditor.svelte'
 import WorkspaceSettings from './components/WorkspaceSettings.svelte'
@@ -90,6 +91,7 @@ export default async (): Promise<Resources> => ({
     RefEditor,
     DateTypeEditor,
     EnumTypeEditor,
+    ArrayEditor,
     EditEnum,
     EnumSetting,
     Owners,
diff --git a/plugins/view-resources/src/components/EnumArrayEditor.svelte b/plugins/view-resources/src/components/EnumArrayEditor.svelte
new file mode 100644
index 0000000000..0b75afc9c5
--- /dev/null
+++ b/plugins/view-resources/src/components/EnumArrayEditor.svelte
@@ -0,0 +1,59 @@
+<!--
+// 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, { ArrOf, EnumOf } from '@hcengineering/core'
+  import type { IntlString } from '@hcengineering/platform'
+  import { createQuery } from '@hcengineering/presentation'
+  import { DropdownLabels, DropdownTextItem } from '@hcengineering/ui'
+
+  export let label: IntlString
+  export let value: string[] = []
+  export let type: ArrOf<string>
+  export let onChange: (value: string[]) => void
+
+  let items: DropdownTextItem[] = []
+
+  const query = createQuery()
+
+  query.query(
+    core.class.Enum,
+    {
+      _id: (type.of as EnumOf).of
+    },
+    (res) => {
+      items =
+        res[0]?.enumValues?.map((p) => {
+          return { id: p, label: p }
+        }) ?? []
+    },
+    { limit: 1 }
+  )
+</script>
+
+<DropdownLabels
+  selected={value ?? []}
+  {items}
+  {label}
+  useFlexGrow={true}
+  justify={'left'}
+  size={'large'}
+  kind={'link'}
+  width={'100%'}
+  multiselect
+  autoSelect={false}
+  on:selected={(e) => {
+    onChange(e.detail)
+  }}
+/>
diff --git a/plugins/view-resources/src/components/StringPresenter.svelte b/plugins/view-resources/src/components/StringPresenter.svelte
index 3dcc732f90..dbc7c002ba 100644
--- a/plugins/view-resources/src/components/StringPresenter.svelte
+++ b/plugins/view-resources/src/components/StringPresenter.svelte
@@ -14,7 +14,15 @@
 // limitations under the License.
 -->
 <script lang="ts">
-  export let value: string
+  export let value: string | string[]
 </script>
 
-<span class="lines-limit-2 select-text">{value}</span>
+<span class="lines-limit-2 select-text">
+  {#if Array.isArray(value)}
+    {#each value as str, i}
+      <span class:ml-1={i !== 0}>{str}</span>
+    {/each}
+  {:else}
+    {value}
+  {/if}
+</span>
diff --git a/plugins/view-resources/src/index.ts b/plugins/view-resources/src/index.ts
index a16de02b8b..40ca2d25e7 100644
--- a/plugins/view-resources/src/index.ts
+++ b/plugins/view-resources/src/index.ts
@@ -63,6 +63,7 @@ import UpDownNavigator from './components/UpDownNavigator.svelte'
 import ValueSelector from './components/ValueSelector.svelte'
 import ViewletSettingButton from './components/ViewletSettingButton.svelte'
 import SpaceRefPresenter from './components/SpaceRefPresenter.svelte'
+import EnumArrayEditor from './components/EnumArrayEditor.svelte'
 
 import {
   afterResult,
@@ -174,7 +175,8 @@ export default async (): Promise<Resources> => ({
     ListView,
     GrowPresenter,
     IndexedDocumentPreview,
-    SpaceRefPresenter
+    SpaceRefPresenter,
+    EnumArrayEditor
   },
   popup: {
     PositionElementAlignment