diff --git a/models/contact/src/index.ts b/models/contact/src/index.ts
index 1e6d23f4c7..7b85638526 100644
--- a/models/contact/src/index.ts
+++ b/models/contact/src/index.ts
@@ -286,7 +286,8 @@ export function createModel (builder: Builder): void {
         }
       ],
       configOptions: {
-        hiddenKeys: ['name']
+        hiddenKeys: ['name'],
+        sortable: true
       }
     },
     contact.viewlet.TableContact
diff --git a/models/inventory/src/index.ts b/models/inventory/src/index.ts
index 9cae385fa3..2889c0ead7 100644
--- a/models/inventory/src/index.ts
+++ b/models/inventory/src/index.ts
@@ -111,7 +111,10 @@ export function createModel (builder: Builder): void {
     {
       attachTo: inventory.class.Product,
       descriptor: view.viewlet.Table,
-      config: ['', 'attachedTo', 'modifiedOn']
+      config: ['', 'attachedTo', 'modifiedOn'],
+      configOptions: {
+        sortable: true
+      }
     },
     inventory.viewlet.TableProduct
   )
diff --git a/models/lead/src/index.ts b/models/lead/src/index.ts
index 8129f35b87..d451181794 100644
--- a/models/lead/src/index.ts
+++ b/models/lead/src/index.ts
@@ -209,7 +209,8 @@ export function createModel (builder: Builder): void {
         }
       ],
       configOptions: {
-        hiddenKeys: ['name']
+        hiddenKeys: ['name'],
+        sortable: true
       },
       options: {
         lookup: {
@@ -241,11 +242,6 @@ export function createModel (builder: Builder): void {
         'state',
         'doneState',
         'attachments',
-        {
-          key: '',
-          presenter: tracker.component.RelatedIssueSelector,
-          label: tracker.string.Relations
-        },
         'comments',
         'modifiedOn',
         {
@@ -253,6 +249,9 @@ export function createModel (builder: Builder): void {
           sortingKey: ['$lookup.attachedTo.$lookup.channels.lastMessage', '$lookup.attachedTo.channels']
         }
       ],
+      configOptions: {
+        sortable: true
+      },
       options: {
         lookup: {
           _id: {
@@ -292,6 +291,7 @@ export function createModel (builder: Builder): void {
       descriptor: view.viewlet.List,
       configOptions: {
         hiddenKeys: ['title'],
+        sortable: true,
         extraProps: {
           displayProps: {
             optional: true
diff --git a/models/recruit/src/index.ts b/models/recruit/src/index.ts
index 518b9df861..87ef2d7160 100644
--- a/models/recruit/src/index.ts
+++ b/models/recruit/src/index.ts
@@ -400,7 +400,8 @@ export function createModel (builder: Builder): void {
         }
       ],
       configOptions: {
-        hiddenKeys: ['name']
+        hiddenKeys: ['name'],
+        sortable: true
       },
       options: {
         lookup: {
@@ -420,6 +421,9 @@ export function createModel (builder: Builder): void {
       attachTo: recruit.class.Applicant,
       descriptor: view.viewlet.Table,
       config: ['', '$lookup.attachedTo', 'state', 'doneState', 'modifiedOn'],
+      configOptions: {
+        sortable: true
+      },
       variant: 'short'
     },
     recruit.viewlet.VacancyApplicationsShort
@@ -432,6 +436,9 @@ export function createModel (builder: Builder): void {
       attachTo: recruit.class.Applicant,
       descriptor: view.viewlet.Table,
       config: ['', '$lookup.space.name', '$lookup.space.$lookup.company', 'state', 'comments', 'doneState'],
+      configOptions: {
+        sortable: true
+      },
       variant: 'embedded'
     },
     recruit.viewlet.VacancyApplicationsEmbeddeed
@@ -460,7 +467,8 @@ export function createModel (builder: Builder): void {
         }
       ],
       configOptions: {
-        hiddenKeys: ['name', 'space', 'modifiedOn']
+        hiddenKeys: ['name', 'space', 'modifiedOn'],
+        sortable: true
       }
     },
     recruit.viewlet.TableVacancy
@@ -492,7 +500,8 @@ export function createModel (builder: Builder): void {
         }
       ],
       configOptions: {
-        hiddenKeys: ['name', 'space', 'modifiedOn']
+        hiddenKeys: ['name', 'space', 'modifiedOn'],
+        sortable: true
       }
     },
     recruit.viewlet.TableVacancyList
@@ -533,7 +542,8 @@ export function createModel (builder: Builder): void {
         }
       ],
       configOptions: {
-        hiddenKeys: ['name', 'attachedTo']
+        hiddenKeys: ['name', 'attachedTo'],
+        sortable: true
       },
       options: {
         lookup: {
@@ -588,7 +598,8 @@ export function createModel (builder: Builder): void {
         }
       },
       configOptions: {
-        hiddenKeys: ['name', 'attachedTo']
+        hiddenKeys: ['name', 'attachedTo'],
+        sortable: true
       },
       baseQuery: {
         doneState: null,
@@ -722,6 +733,7 @@ export function createModel (builder: Builder): void {
       },
       configOptions: {
         hiddenKeys: ['name', 'attachedTo'],
+        sortable: true,
         extraProps: {
           displayProps: {
             optional: true
diff --git a/models/tracker/src/index.ts b/models/tracker/src/index.ts
index f181497933..49b0b1348c 100644
--- a/models/tracker/src/index.ts
+++ b/models/tracker/src/index.ts
@@ -505,6 +505,7 @@ export function createModel (builder: Builder): void {
           'dueDate',
           'attachedTo'
         ],
+        sortable: true,
         extraProps: {
           displayProps: {
             optional: true
@@ -643,32 +644,51 @@ export function createModel (builder: Builder): void {
       descriptor: view.viewlet.List,
       viewOptions: subIssuesOptions,
       variant: 'subissue',
+      configOptions: {
+        sortable: true,
+        hiddenKeys: ['priority', 'number', 'status', 'title', 'dueDate', 'milestone', 'estimation'],
+        extraProps: {
+          displayProps: {
+            optional: true
+          }
+        }
+      },
       config: [
         {
           key: '',
+          label: tracker.string.Priority,
           presenter: tracker.component.PriorityEditor,
           props: { type: 'priority', kind: 'list', size: 'small' }
         },
         {
           key: '',
+          label: tracker.string.Issue,
           presenter: tracker.component.IssuePresenter,
           props: { type: 'issue' },
           displayProps: { fixed: 'left' }
         },
         {
           key: '',
+          label: tracker.string.Status,
           presenter: tracker.component.StatusEditor,
           props: { kind: 'list', size: 'small', justify: 'center' }
         },
-        { key: '', presenter: tracker.component.TitlePresenter, props: { shouldUseMargin: true, showParent: false } },
-        { key: '', presenter: tracker.component.SubIssuesSelector, props: {} },
         {
           key: '',
+          label: tracker.string.Title,
+          presenter: tracker.component.TitlePresenter,
+          props: { shouldUseMargin: true, showParent: false }
+        },
+        { key: '', label: tracker.string.SubIssues, presenter: tracker.component.SubIssuesSelector, props: {} },
+        {
+          key: '',
+          label: tracker.string.DueDate,
           presenter: tracker.component.DueDatePresenter,
           props: { kind: 'list' }
         },
         {
           key: '',
+          label: tracker.string.Milestone,
           presenter: tracker.component.MilestoneEditor,
           props: {
             kind: 'list',
@@ -683,6 +703,7 @@ export function createModel (builder: Builder): void {
         },
         {
           key: '',
+          label: tracker.string.Estimation,
           presenter: tracker.component.EstimationEditor,
           props: { kind: 'list', size: 'small' },
           displayProps: { optional: true }
@@ -720,7 +741,8 @@ export function createModel (builder: Builder): void {
       },
       configOptions: {
         hiddenKeys: ['milestone', 'estimation', 'component', 'title', 'description'],
-        extraProps: { displayProps: { optional: true } }
+        extraProps: { displayProps: { optional: true } },
+        sortable: true
       },
       config: [
         // { key: '', presenter: tracker.component.PriorityEditor, props: { kind: 'list', size: 'small' } },
@@ -1861,7 +1883,8 @@ export function createModel (builder: Builder): void {
       viewOptions: milestoneOptions,
       configOptions: {
         hiddenKeys: ['targetDate', 'label', 'description'],
-        extraProps: { displayProps: { optional: true } }
+        extraProps: { displayProps: { optional: true } },
+        sortable: true
       },
       config: [
         {
@@ -1941,7 +1964,8 @@ export function createModel (builder: Builder): void {
       viewOptions: componentListViewOptions,
       configOptions: {
         hiddenKeys: ['label', 'description'],
-        extraProps: { displayProps: { optional: true } }
+        extraProps: { displayProps: { optional: true } },
+        sortable: true
       },
       config: [
         {
diff --git a/plugins/tracker-resources/src/components/views/Views.svelte b/plugins/tracker-resources/src/components/views/Views.svelte
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/plugins/tracker-resources/src/index.ts b/plugins/tracker-resources/src/index.ts
index 929b53be2b..27583e70db 100644
--- a/plugins/tracker-resources/src/index.ts
+++ b/plugins/tracker-resources/src/index.ts
@@ -67,7 +67,6 @@ import SetParentIssueActionPopup from './components/SetParentIssueActionPopup.sv
 import MilestoneDatePresenter from './components/milestones/MilestoneDatePresenter.svelte'
 import EditMilestone from './components/milestones/EditMilestone.svelte'
 import CreateIssueTemplate from './components/templates/CreateIssueTemplate.svelte'
-import Views from './components/views/Views.svelte'
 import Statuses from './components/workflow/Statuses.svelte'
 
 import {
@@ -384,7 +383,6 @@ export default async (): Promise<Resources> => ({
     Inbox,
     MyIssues,
     Components,
-    Views,
     IssuePresenter,
     ComponentPresenter,
     ComponentTitlePresenter,
diff --git a/plugins/view-resources/src/components/ViewletSetting.svelte b/plugins/view-resources/src/components/ViewletSetting.svelte
index a6730f6648..24ed4e39fb 100644
--- a/plugins/view-resources/src/components/ViewletSetting.svelte
+++ b/plugins/view-resources/src/components/ViewletSetting.svelte
@@ -17,7 +17,7 @@
   import { Asset, IntlString } from '@hcengineering/platform'
   import preferencePlugin from '@hcengineering/preference'
   import { createQuery, getAttributePresenterClass, getClient, hasResource } from '@hcengineering/presentation'
-  import { Loading, ToggleWithLabel } from '@hcengineering/ui'
+  import { Button, Loading, ToggleWithLabel } from '@hcengineering/ui'
   import { BuildModelKey, Viewlet, ViewletPreference } from '@hcengineering/view'
   import { deepEqual } from 'fast-equals'
   import view from '../plugin'
@@ -36,8 +36,7 @@
       },
       (res) => {
         preference = res[0]
-        attributes = getConfig(viewlet, preference)
-        classes = groupByClasses(attributes)
+        items = getConfig(viewlet, preference)
         loading = false
       },
       { limit: 1 }
@@ -48,7 +47,7 @@
 
   const client = getClient()
   const hierarchy = client.getHierarchy()
-  let attributes: AttributeConfig[] = []
+  let items: AttributeConfig[] = []
   let loading = true
 
   interface AttributeConfig {
@@ -57,6 +56,7 @@
     value: string | BuildModelKey
     _class: Ref<Class<Doc>>
     icon: Asset | undefined
+    order?: number
   }
 
   function getObjectConfig (_class: Ref<Class<Doc>>, param: string): AttributeConfig {
@@ -201,10 +201,7 @@
   }
 
   async function save (): Promise<void> {
-    const config = Array.from(classes.values())
-      .flat()
-      .filter((p) => p.enabled)
-      .map((p) => p.value)
+    const config = items.filter((p) => p.enabled).map((p) => p.value)
     if (preference !== undefined) {
       await client.update(preference, {
         config
@@ -217,29 +214,51 @@
     }
   }
 
-  // function restoreDefault (): void {
-  //   attributes = getConfig(viewlet, undefined)
-  //   classes = groupByClasses(attributes)
-  // }
+  function restoreDefault (): void {
+    items = getConfig(viewlet, undefined)
+    save()
+  }
 
   function setStatus (result: AttributeConfig[], preference: ViewletPreference): AttributeConfig[] {
     for (const key of result) {
-      key.enabled = preference.config.findIndex((p) => deepEqual(p, key.value)) !== -1
+      const index = preference.config.findIndex((p) => deepEqual(p, key.value))
+      key.enabled = index !== -1
+      key.order = index !== -1 ? index : undefined
     }
+    result.sort((a, b) => {
+      if (a.order === undefined && b.order === undefined) return 0
+      if (a.order === undefined) return 1
+      if (b.order === undefined) return -1
+      return a.order - b.order
+    })
     return result
   }
 
-  function groupByClasses (attributes: AttributeConfig[]): Map<Ref<Class<Doc>>, AttributeConfig[]> {
-    const res = new Map()
-    for (const attribute of attributes) {
-      const arr = res.get(attribute._class) ?? []
-      arr.push(attribute)
-      res.set(attribute._class, arr)
-    }
-    return res
+  function dragEnd () {
+    selected = undefined
+    save()
   }
 
-  let classes: Map<Ref<Class<Doc>>, AttributeConfig[]> = new Map()
+  function dragOver (e: DragEvent, i: number) {
+    const s = selected as number
+    if (dragswap(e, i, s)) {
+      ;[items[i], items[s]] = [items[s], items[i]]
+      selected = i
+    }
+  }
+
+  const elements: HTMLElement[] = []
+
+  function dragswap (ev: MouseEvent, i: number, s: number): boolean {
+    if (i < s) {
+      return ev.offsetY < elements[i].offsetHeight / 2
+    } else if (i > s) {
+      return ev.offsetY > elements[i].offsetHeight / 2
+    }
+    return false
+  }
+
+  let selected: number | undefined
 </script>
 
 <div class="selectPopup p-2">
@@ -247,23 +266,29 @@
     {#if loading}
       <Loading />
     {:else}
-      {#each Array.from(classes.keys()) as _class, i}
-        {@const items = classes.get(_class) ?? []}
-        {#if i !== 0}
-          <div class="menu-separator" />
-        {/if}
-        {#each items as item}
-          <div class="item">
-            <ToggleWithLabel
-              on={item.enabled}
-              label={item.label}
-              on:change={(e) => {
-                item.enabled = e.detail
-                save()
-              }}
-            />
-          </div>
-        {/each}
+      <div class="flex-row-reverse">
+        <Button on:click={restoreDefault} label={view.string.RestoreDefaults} size={'x-small'} kind={'link'} noFocus />
+      </div>
+      {#each items as item, i}
+        <div
+          class="item"
+          bind:this={elements[i]}
+          draggable={viewlet.configOptions?.sortable}
+          on:dragstart={() => {
+            selected = i
+          }}
+          on:dragover|preventDefault={(e) => dragOver(e, i)}
+          on:dragend={dragEnd}
+        >
+          <ToggleWithLabel
+            on={item.enabled}
+            label={item.label}
+            on:change={(e) => {
+              item.enabled = e.detail
+              save()
+            }}
+          />
+        </div>
       {/each}
     {/if}
   </div>
diff --git a/plugins/view/src/index.ts b/plugins/view/src/index.ts
index 2a3cccaf49..3f15992e90 100644
--- a/plugins/view/src/index.ts
+++ b/plugins/view/src/index.ts
@@ -329,6 +329,7 @@ export interface ViewletConfigOptions {
   hiddenKeys?: string[]
   strict?: boolean
   extraProps?: Omit<BuildModelKey, 'key'>
+  sortable?: boolean
 }
 
 /**