diff --git a/plugins/contact-resources/src/components/EditOrganizationPanel.svelte b/plugins/contact-resources/src/components/EditOrganizationPanel.svelte
new file mode 100644
index 0000000000..aa4f555238
--- /dev/null
+++ b/plugins/contact-resources/src/components/EditOrganizationPanel.svelte
@@ -0,0 +1,163 @@
+
+
+{#if object}
+
{
+ dispatch('close')
+ }}
+ >
+
+
+ {object.name}
+
+
+
+
+ {#if dir === 'column'}
+
+ {/if}
+
+
+
+ {#if saved}
+
+ {/if}
+
+
+
+
+
+
+
+
+
{
+ saved = evt.detail
+ }}
+ />
+
+
+
+ {#each editors as editor}
+ {#if editor.editor}
+
+
+
+ {/if}
+ {/each}
+
+{/if}
diff --git a/plugins/contact-resources/src/components/OrganizationPresenter.svelte b/plugins/contact-resources/src/components/OrganizationPresenter.svelte
index c11b7d8588..4f73d37057 100644
--- a/plugins/contact-resources/src/components/OrganizationPresenter.svelte
+++ b/plugins/contact-resources/src/components/OrganizationPresenter.svelte
@@ -18,6 +18,8 @@
import { getEmbeddedLabel } from '@hcengineering/platform'
import { tooltip } from '@hcengineering/ui'
import { DocNavLink, ObjectMention } from '@hcengineering/view-resources'
+
+ import contact from '../plugin'
import Company from './icons/Company.svelte'
export let value: Organization
@@ -30,9 +32,15 @@
{#if value}
{#if inline}
-
+
{:else}
-
+
diff --git a/plugins/contact-resources/src/index.ts b/plugins/contact-resources/src/index.ts
index c98054c424..6ea8b8682e 100644
--- a/plugins/contact-resources/src/index.ts
+++ b/plugins/contact-resources/src/index.ts
@@ -103,6 +103,7 @@ import UsersList from './components/UsersList.svelte'
import SelectUsersPopup from './components/SelectUsersPopup.svelte'
import IconAddMember from './components/icons/AddMember.svelte'
import UserDetails from './components/UserDetails.svelte'
+import EditOrganizationPanel from './components/EditOrganizationPanel.svelte'
import contact from './plugin'
import {
@@ -332,7 +333,8 @@ export default async (): Promise
=> ({
PersonAccountFilterValuePresenter,
DeleteConfirmationPopup,
PersonAccountRefPresenter,
- PersonIcon
+ PersonIcon,
+ EditOrganizationPanel
},
completion: {
EmployeeQuery: async (
diff --git a/plugins/contact-resources/src/utils.ts b/plugins/contact-resources/src/utils.ts
index 035f10f5ae..ccdcbc931f 100644
--- a/plugins/contact-resources/src/utils.ts
+++ b/plugins/contact-resources/src/utils.ts
@@ -37,7 +37,8 @@ import {
type Timestamp,
type TxOperations,
getCurrentAccount,
- toIdMap
+ toIdMap,
+ type Class
} from '@hcengineering/core'
import notification, { type DocNotifyContext, type InboxNotification } from '@hcengineering/notification'
import { getEmbeddedLabel, getResource } from '@hcengineering/platform'
@@ -268,14 +269,18 @@ async function generateLocation (loc: Location, id: Ref): Promise>, view.mixin.ObjectPanel)
+ const component = objectPanel?.component ?? view.component.EditDoc
+
return {
loc: {
path: [appComponent, workspace],
- fragment: getPanelURI(view.component.EditDoc, doc._id, doc._class, 'content')
+ fragment: getPanelURI(component, doc._id, doc._class, 'content')
},
defaultLocation: {
path: [appComponent, workspace, contactId, special],
- fragment: getPanelURI(view.component.EditDoc, doc._id, doc._class, 'content')
+ fragment: getPanelURI(component, doc._id, doc._class, 'content')
}
}
}
diff --git a/plugins/contact/src/index.ts b/plugins/contact/src/index.ts
index a7cacde4f0..45d9ff817d 100644
--- a/plugins/contact/src/index.ts
+++ b/plugins/contact/src/index.ts
@@ -121,6 +121,7 @@ export interface Member extends AttachedDoc {
*/
export interface Organization extends Contact {
members: number
+ description?: string
}
/**
@@ -196,7 +197,8 @@ export const contactPlugin = plugin(contactId, {
SpaceMembers: '' as AnyComponent,
DeleteConfirmationPopup: '' as AnyComponent,
AccountArrayEditor: '' as AnyComponent,
- PersonIcon: '' as AnyComponent
+ PersonIcon: '' as AnyComponent,
+ EditOrganizationPanel: '' as AnyComponent
},
channelProvider: {
Email: '' as Ref,
diff --git a/plugins/recruit-resources/src/utils.ts b/plugins/recruit-resources/src/utils.ts
index fea89b4ad2..b9eac83661 100644
--- a/plugins/recruit-resources/src/utils.ts
+++ b/plugins/recruit-resources/src/utils.ts
@@ -72,7 +72,8 @@ async function generateIdLocation (loc: Location, shortLink: string): Promise>, view.mixin.ObjectPanel)
+ const objectPanel = hierarchy.classHierarchyMixin(Hierarchy.mixinOrClass(doc), view.mixin.ObjectPanel)
+
const component = objectPanel?.component ?? view.component.EditDoc
const special = _class === recruit.mixin.Candidate ? 'talents' : 'organizations'
const defaultPath = [appComponent, workspace, recruitId, special]
diff --git a/plugins/view-resources/src/components/EditDoc.svelte b/plugins/view-resources/src/components/EditDoc.svelte
index 0b3106abe2..4d0c02c22a 100644
--- a/plugins/view-resources/src/components/EditDoc.svelte
+++ b/plugins/view-resources/src/components/EditDoc.svelte
@@ -21,11 +21,9 @@
import {
ActionContext,
AttributeCategory,
- AttributeCategoryOrder,
AttributesBar,
KeyedAttribute,
createQuery,
- getAttributePresenterClass,
getClient,
hasResource
} from '@hcengineering/presentation'
@@ -33,8 +31,8 @@
import view from '@hcengineering/view'
import { createEventDispatcher, onDestroy } from 'svelte'
- import { DocNavLink, ParentsNavigator, getDocLabel, getDocMixins, showMenu } from '..'
- import { categorizeFields, getCollectionCounter, getFiltredKeys } from '../utils'
+ import { DocNavLink, ParentsNavigator, getDocLabel, getDocMixins, showMenu, getDocAttrsInfo } from '..'
+ import { getCollectionCounter } from '../utils'
import DocAttributeBar from './DocAttributeBar.svelte'
export let _id: Ref
@@ -96,8 +94,6 @@
let mixins: Array> = []
let showAllMixins = false
- $: mixins = getDocMixins(object, showAllMixins, ignoreMixins, realObjectClass)
-
const dispatch = createEventDispatcher()
let ignoreKeys: string[] = []
@@ -107,33 +103,14 @@
let inplaceAttributes: string[] = []
let ignoreMixins: Set[>> = new Set][>>()
+ $: mixins = getDocMixins(object, showAllMixins, ignoreMixins, realObjectClass)
+
async function updateKeys (): Promise {
- const keysMap = new Map(getFiltredKeys(hierarchy, realObjectClass, ignoreKeys).map((p) => [p.attr._id, p]))
- for (const m of mixins) {
- const mkeys = getFiltredKeys(hierarchy, m._id, ignoreKeys)
- for (const key of mkeys) {
- keysMap.set(key.attr._id, key)
- }
- }
- const filtredKeys = Array.from(keysMap.values())
- const { attributes, collections } = categorizeFields(hierarchy, filtredKeys, collectionArrays, allowedCollections)
+ const info = await getDocAttrsInfo(mixins, ignoreKeys, realObjectClass, allowedCollections, collectionArrays)
- keys = attributes.map((it) => it.key)
-
- const editors: Array<{ key: KeyedAttribute, editor: AnyComponent, category: AttributeCategory }> = []
- const newInplaceAttributes: string[] = []
-
- for (const k of collections) {
- if (allowedCollections.includes(k.key.key)) continue
- const editor = await getFieldEditor(k.key)
- if (editor === undefined) continue
- if (k.category === 'inplace') {
- newInplaceAttributes.push(k.key.key)
- }
- editors.push({ key: k.key, editor, category: k.category })
- }
- inplaceAttributes = newInplaceAttributes
- fieldEditors = editors.sort((a, b) => AttributeCategoryOrder[a.category] - AttributeCategoryOrder[b.category])
+ keys = info.keys
+ inplaceAttributes = info.inplaceAttributes
+ fieldEditors = info.editors
}
interface MixinEditor {
@@ -166,37 +143,18 @@
$: editorFooter = getEditorFooter(_class, object)
- $: getEditorOrDefault(realObjectClass, _id)
+ $: void getEditorOrDefault(realObjectClass, _id)
async function getEditorOrDefault (_class: Ref>, _id: Ref): Promise {
await updateKeys()
mainEditor = getEditor(_class)
}
- async function getFieldEditor (key: KeyedAttribute): Promise {
- const attrClass = getAttributePresenterClass(hierarchy, key.attr)
- const clazz = hierarchy.getClass(attrClass.attrClass)
- const mix = {
- array: view.mixin.ArrayEditor,
- collection: view.mixin.CollectionEditor,
- inplace: view.mixin.InlineAttributEditor,
- attribute: view.mixin.AttributeEditor,
- object: undefined
- }
- const mixinRef = mix[attrClass.category]
- if (mixinRef) {
- const editorMixin = hierarchy.as(clazz, mixinRef)
- return (editorMixin as any).editor
- } else {
- return undefined
- }
- }
-
let title: string | undefined = undefined
let rawTitle: string = ''
$: if (object !== undefined) {
- getDocLabel(pClient, object).then((t) => {
+ void getDocLabel(pClient, object).then((t) => {
if (t) {
rawTitle = t
}
@@ -216,7 +174,7 @@
let headerLoading = false
$: {
headerLoading = true
- getHeaderEditor(realObjectClass).then((r) => {
+ void getHeaderEditor(realObjectClass).then((r) => {
headerEditor = r
headerLoading = false
})
@@ -236,7 +194,7 @@
collectionArrays = ev.detail.collectionArrays ?? []
title = ev.detail.title
mixins = getDocMixins(object, showAllMixins, ignoreMixins, realObjectClass)
- updateKeys()
+ void updateKeys()
}
$: finalTitle = title ?? rawTitle
diff --git a/plugins/view-resources/src/utils.ts b/plugins/view-resources/src/utils.ts
index 708a518396..81c3da74d3 100644
--- a/plugins/view-resources/src/utils.ts
+++ b/plugins/view-resources/src/utils.ts
@@ -53,12 +53,14 @@ import { type Restrictions } from '@hcengineering/guest'
import type { Asset, IntlString } from '@hcengineering/platform'
import { getResource, translate } from '@hcengineering/platform'
import {
+ type AttributeCategory,
+ AttributeCategoryOrder,
getAttributePresenterClass,
getClient,
hasResource,
- isAdminUser,
- type AttributeCategory,
- type KeyedAttribute
+ type KeyedAttribute,
+ getFiltredKeys,
+ isAdminUser
} from '@hcengineering/presentation'
import {
ErrorPresenter,
@@ -1266,3 +1268,67 @@ export const restrictionStore = writable({
disableNavigation: false,
disableActions: false
})
+
+export async function getDocAttrsInfo (
+ mixins: Array>,
+ ignoreKeys: string[],
+ _class: Ref>,
+ allowedCollections: string[] = [],
+ collectionArrays: string[] = []
+): Promise<{
+ keys: KeyedAttribute[]
+ inplaceAttributes: string[]
+ editors: Array<{ key: KeyedAttribute, editor: AnyComponent, category: AttributeCategory }>
+ }> {
+ const client = getClient()
+ const hierarchy = client.getHierarchy()
+
+ const keysMap = new Map(getFiltredKeys(hierarchy, _class, ignoreKeys).map((p) => [p.attr._id, p]))
+ for (const m of mixins) {
+ const mkeys = getFiltredKeys(hierarchy, m._id, ignoreKeys)
+ for (const key of mkeys) {
+ keysMap.set(key.attr._id, key)
+ }
+ }
+ const filteredKeys = Array.from(keysMap.values())
+ const { attributes, collections } = categorizeFields(hierarchy, filteredKeys, collectionArrays, allowedCollections)
+
+ const keys = attributes.map((it) => it.key)
+ const editors: Array<{ key: KeyedAttribute, editor: AnyComponent, category: AttributeCategory }> = []
+ const inplaceAttributes: string[] = []
+
+ for (const k of collections) {
+ if (allowedCollections.includes(k.key.key)) continue
+ const editor = await getAttrEditor(k.key, hierarchy)
+ if (editor === undefined) continue
+ if (k.category === 'inplace') {
+ inplaceAttributes.push(k.key.key)
+ }
+ editors.push({ key: k.key, editor, category: k.category })
+ }
+
+ return {
+ keys,
+ inplaceAttributes,
+ editors: editors.sort((a, b) => AttributeCategoryOrder[a.category] - AttributeCategoryOrder[b.category])
+ }
+}
+
+async function getAttrEditor (key: KeyedAttribute, hierarchy: Hierarchy): Promise {
+ const attrClass = getAttributePresenterClass(hierarchy, key.attr)
+ const clazz = hierarchy.getClass(attrClass.attrClass)
+ const mix = {
+ array: view.mixin.ArrayEditor,
+ collection: view.mixin.CollectionEditor,
+ inplace: view.mixin.InlineAttributEditor,
+ attribute: view.mixin.AttributeEditor,
+ object: undefined as any
+ }
+ const mixinRef = mix[attrClass.category]
+ if (mixinRef !== undefined) {
+ const editorMixin = hierarchy.as(clazz, mixinRef)
+ return (editorMixin as any).editor
+ } else {
+ return undefined
+ }
+}
]