From 65ddacd444720cb85ad20fa8f3fd6045f9ab8220 Mon Sep 17 00:00:00 2001
From: Denis Bykhov <80476319+BykhovDenis@users.noreply.github.com>
Date: Sat, 19 Mar 2022 22:19:14 +0600
Subject: [PATCH] Open space editor with click on header (#1179)

Signed-off-by: Denis Bykhov <80476319+BykhovDenis@users.noreply.github.com>
---
 models/recruit/src/index.ts                   | 11 +++++++--
 .../src/components/Header.svelte              | 13 +++++++++-
 .../src/components/SpaceHeader.svelte         | 24 +++++++++++++++----
 .../src/components/SpaceView.svelte           |  2 +-
 .../src/components/navigator/SpacesNav.svelte | 18 ++++++++++----
 .../src/components/navigator/TreeItem.svelte  |  2 +-
 plugins/workbench/src/index.ts                |  1 -
 7 files changed, 56 insertions(+), 15 deletions(-)

diff --git a/models/recruit/src/index.ts b/models/recruit/src/index.ts
index 1c24d07647..ed3ccae000 100644
--- a/models/recruit/src/index.ts
+++ b/models/recruit/src/index.ts
@@ -147,8 +147,7 @@ export function createModel (builder: Builder): void {
             label: recruit.string.ReviewCategory,
             spaceClass: recruit.class.ReviewCategory,
             addSpaceLabel: recruit.string.CreateReviewCategory,
-            createComponent: recruit.component.CreateReviewCategory,
-            component: recruit.component.EditReviewCategory
+            createComponent: recruit.component.CreateReviewCategory
           }
         ],
         specials: [
@@ -295,6 +294,14 @@ export function createModel (builder: Builder): void {
     editor: recruit.component.EditApplication
   })
 
+  builder.mixin(recruit.class.Vacancy, core.class.Class, view.mixin.ObjectEditor, {
+    editor: recruit.component.EditVacancy
+  })
+
+  builder.mixin(recruit.class.ReviewCategory, core.class.Class, view.mixin.ObjectEditor, {
+    editor: recruit.component.EditReviewCategory
+  })
+
   builder.mixin(recruit.class.Applicant, core.class.Class, view.mixin.AttributePresenter, {
     presenter: recruit.component.ApplicationPresenter
   })
diff --git a/plugins/workbench-resources/src/components/Header.svelte b/plugins/workbench-resources/src/components/Header.svelte
index 2c41ffb5d2..638d195a7f 100644
--- a/plugins/workbench-resources/src/components/Header.svelte
+++ b/plugins/workbench-resources/src/components/Header.svelte
@@ -23,9 +23,20 @@
 </script>
 
 <div class="ac-header__wrap-description">
-  <div class="ac-header__wrap-title">
+  <div class="ac-header__wrap-title" on:click>
     {#if icon }<div class="ac-header__icon"><Icon {icon} size={'small'}/></div>{/if}
     <span class="ac-header__title">{label}</span>
   </div>
   {#if description }<span class="ac-header__description">{description}</span>{/if}
 </div>
+
+
+
+<style lang="scss">
+  .ac-header__wrap-title:hover {
+    cursor: pointer;
+    span {
+      text-decoration: underline;
+    }
+  }
+</style>
diff --git a/plugins/workbench-resources/src/components/SpaceHeader.svelte b/plugins/workbench-resources/src/components/SpaceHeader.svelte
index 3b2177f3ac..7f29480e78 100644
--- a/plugins/workbench-resources/src/components/SpaceHeader.svelte
+++ b/plugins/workbench-resources/src/components/SpaceHeader.svelte
@@ -14,19 +14,19 @@
 -->
 
 <script lang="ts">
-  import type { Ref,Space } from '@anticrm/core'
+  import type { Class, Doc, Ref,Space } from '@anticrm/core'
   import core, { WithLookup } from '@anticrm/core'
   import { IntlString } from '@anticrm/platform'
   import presentation, { createQuery, getClient } from '@anticrm/presentation'
-  import type { AnyComponent } from '@anticrm/ui'
+  import { AnyComponent, showPanel } from '@anticrm/ui'
   import { Button, Icon, SearchEdit, showPopup, Tooltip, IconAdd } from '@anticrm/ui'
-  import { Viewlet } from '@anticrm/view'
+  import view, { Viewlet } from '@anticrm/view'
   import { createEventDispatcher } from 'svelte'
+  import plugin from '../plugin'
   import { classIcon } from '../utils'
   import Header from './Header.svelte'
 
   export let spaceId: Ref<Space> | undefined
-  // export let _class: Ref<Class<Doc>> | undefined
   export let createItemDialog: AnyComponent | undefined
   export let createItemLabel: IntlString = presentation.string.Create
   export let search: string
@@ -34,6 +34,7 @@
   export let viewlets: WithLookup<Viewlet>[] = []
 
   const client = getClient()
+  const hierarchy = client.getHierarchy()
   const query = createQuery()
   let space: Space | undefined
   const dispatch = createEventDispatcher()
@@ -53,11 +54,24 @@
     search = ''
     dispatch('search', '')
   }
+
+  async function getEditor (_class: Ref<Class<Doc>>): Promise<AnyComponent | undefined> {
+    const clazz = hierarchy.getClass(_class)
+    const editorMixin = hierarchy.as(clazz, view.mixin.ObjectEditor)
+    if (editorMixin?.editor == null && clazz.extends != null) return getEditor(clazz.extends)
+    return editorMixin.editor
+  }
+
+  async function onSpaceEdit (): Promise<void> {
+    if (space === undefined) return
+    const editor = await getEditor(space._class)
+    showPanel(editor ?? plugin.component.SpacePanel, space._id, space._class, 'right')
+  }
 </script>
 
 <div class="ac-header full">
   {#if space}
-    <Header icon={classIcon(client, space._class)} label={space.name} description={space.description} />
+    <Header icon={classIcon(client, space._class)} label={space.name} description={space.description} on:click={onSpaceEdit} />
     {#if viewlets.length > 1}
       <div class="flex">
         {#each viewlets as viewlet, i}
diff --git a/plugins/workbench-resources/src/components/SpaceView.svelte b/plugins/workbench-resources/src/components/SpaceView.svelte
index cdee2ccb3d..cf4c8ee87f 100644
--- a/plugins/workbench-resources/src/components/SpaceView.svelte
+++ b/plugins/workbench-resources/src/components/SpaceView.svelte
@@ -54,7 +54,7 @@
   $: update(currentView?.class, currentSpace)
 </script>
 
-<SpaceHeader spaceId={space} {_class} {viewlets} {createItemDialog} {createItemLabel} bind:search={search} bind:viewlet={viewlet} />
+<SpaceHeader spaceId={space} {viewlets} {createItemDialog} {createItemLabel} bind:search={search} bind:viewlet={viewlet} />
 {#if _class && space}
   <SpaceContent {space} {_class} {search} {viewlet} />
 {/if}
diff --git a/plugins/workbench-resources/src/components/navigator/SpacesNav.svelte b/plugins/workbench-resources/src/components/navigator/SpacesNav.svelte
index c21e8efa8d..c1f975b5c7 100644
--- a/plugins/workbench-resources/src/components/navigator/SpacesNav.svelte
+++ b/plugins/workbench-resources/src/components/navigator/SpacesNav.svelte
@@ -13,11 +13,12 @@
 // limitations under the License.
 -->
 <script lang="ts">
-  import type { Doc, Ref, Space } from '@anticrm/core'
+  import type { Class,Doc,Ref,Space } from '@anticrm/core'
   import core from '@anticrm/core'
-  import { getResource, IntlString } from '@anticrm/platform'
+  import { getResource } from '@anticrm/platform'
   import { getClient } from '@anticrm/presentation'
-  import { Action, IconAdd, IconEdit, showPanel, showPopup } from '@anticrm/ui'
+  import { Action,AnyComponent,IconAdd,IconEdit,showPanel,showPopup } from '@anticrm/ui'
+  import view from '@anticrm/view'
   import { getActions as getContributedActions } from '@anticrm/view-resources'
   import { SpacesNavModel } from '@anticrm/workbench'
   import { createEventDispatcher } from 'svelte'
@@ -44,10 +45,19 @@
     label: plugin.string.Open,
     icon: IconEdit,
     action: async (_id: Ref<Doc>): Promise<void> => {
-      showPanel(model.component ?? plugin.component.SpacePanel, _id, model.spaceClass, 'right')
+      const editor = await getEditor(model.spaceClass)
+      showPanel(editor ?? plugin.component.SpacePanel, _id, model.spaceClass, 'right')
     }
   }
 
+  async function getEditor (_class: Ref<Class<Doc>>): Promise<AnyComponent | undefined> {
+    const hierarchy = client.getHierarchy()
+    const clazz = hierarchy.getClass(_class)
+    const editorMixin = hierarchy.as(clazz, view.mixin.ObjectEditor)
+    if (editorMixin?.editor == null && clazz.extends != null) return getEditor(clazz.extends)
+    return editorMixin.editor
+  }
+
   function selectSpace (id: Ref<Space>) {
     dispatch('space', id)
   }
diff --git a/plugins/workbench-resources/src/components/navigator/TreeItem.svelte b/plugins/workbench-resources/src/components/navigator/TreeItem.svelte
index 9009a57f1c..5eca00aa0d 100644
--- a/plugins/workbench-resources/src/components/navigator/TreeItem.svelte
+++ b/plugins/workbench-resources/src/components/navigator/TreeItem.svelte
@@ -21,7 +21,7 @@
   import { createEventDispatcher } from 'svelte'
 
   export let _id: Ref<Space>
-  export let icon: Asset
+  export let icon: Asset | undefined 
   export let title: string
   export let notifications = 0
   export let actions: () => Promise<Action[]> = async () => []
diff --git a/plugins/workbench/src/index.ts b/plugins/workbench/src/index.ts
index 312789359d..117d598c71 100644
--- a/plugins/workbench/src/index.ts
+++ b/plugins/workbench/src/index.ts
@@ -39,7 +39,6 @@ export interface SpacesNavModel {
   spaceClass: Ref<Class<Space>>
   addSpaceLabel: IntlString
   createComponent: AnyComponent
-  component?: AnyComponent
 }
 
 /**