mirror of
https://github.com/hcengineering/platform.git
synced 2025-05-03 13:53:42 +00:00
parent
29371e128e
commit
e4783e09f9
@ -62,8 +62,8 @@ export class TAttribute extends TDoc implements AnyAttribute {
|
|||||||
label!: IntlString
|
label!: IntlString
|
||||||
}
|
}
|
||||||
|
|
||||||
@Model(core.class.Type, core.class.Doc)
|
@Model(core.class.Type, core.class.Obj)
|
||||||
export class TType extends TDoc implements Type<any> {
|
export class TType extends TObj implements Type<any> {
|
||||||
label!: IntlString
|
label!: IntlString
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
import type { Account, Arr, Domain, Ref, Space, State } from '@anticrm/core'
|
import type { Account, Arr, Domain, Ref, Space, State } from '@anticrm/core'
|
||||||
import { DOMAIN_MODEL } from '@anticrm/core'
|
import { DOMAIN_MODEL } from '@anticrm/core'
|
||||||
import { Implements, Model, Prop, TypeBoolean, TypeState, TypeString } from '@anticrm/model'
|
import { Implements, Model, Prop, TypeBoolean, TypeRef, TypeString } from '@anticrm/model'
|
||||||
import type { IntlString } from '@anticrm/platform'
|
import type { IntlString } from '@anticrm/platform'
|
||||||
import core from './component'
|
import core from './component'
|
||||||
import { TDoc } from './core'
|
import { TDoc } from './core'
|
||||||
@ -53,7 +53,7 @@ export class TState extends TDoc implements State {
|
|||||||
|
|
||||||
@Implements(core.interface.DocWithState)
|
@Implements(core.interface.DocWithState)
|
||||||
export class TDocWithState extends TDoc {
|
export class TDocWithState extends TDoc {
|
||||||
@Prop(TypeState(), 'State' as IntlString)
|
@Prop(TypeRef(core.class.State), 'State' as IntlString)
|
||||||
state!: Ref<State>
|
state!: Ref<State>
|
||||||
|
|
||||||
@Prop(TypeString(), 'No.' as IntlString)
|
@Prop(TypeString(), 'No.' as IntlString)
|
||||||
|
@ -38,7 +38,6 @@
|
|||||||
"@anticrm/recruit-resources": "~0.6.0",
|
"@anticrm/recruit-resources": "~0.6.0",
|
||||||
"@anticrm/chunter": "~0.6.0",
|
"@anticrm/chunter": "~0.6.0",
|
||||||
"@anticrm/model-chunter": "~0.6.0",
|
"@anticrm/model-chunter": "~0.6.0",
|
||||||
"@anticrm/view": "~0.6.0",
|
"@anticrm/view": "~0.6.0"
|
||||||
"@anticrm/activity": "~0.6.0"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,10 +13,9 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
import activity from '@anticrm/activity'
|
|
||||||
import type { Employee } from '@anticrm/contact'
|
import type { Employee } from '@anticrm/contact'
|
||||||
import type { Doc, Domain, FindOptions, Ref, Timestamp } from '@anticrm/core'
|
import type { Doc, Domain, FindOptions, Ref, Timestamp } from '@anticrm/core'
|
||||||
import { Builder, Model, Prop, TypeBoolean, TypeDate, TypeString, UX } from '@anticrm/model'
|
import { Builder, Model, Prop, TypeBoolean, TypeDate, TypeRef, TypeString, UX } from '@anticrm/model'
|
||||||
import chunter from '@anticrm/model-chunter'
|
import chunter from '@anticrm/model-chunter'
|
||||||
import contact, { TPerson } from '@anticrm/model-contact'
|
import contact, { TPerson } from '@anticrm/model-contact'
|
||||||
import core, { TAttachedDoc, TDocWithState, TSpace, TSpaceWithStates } from '@anticrm/model-core'
|
import core, { TAttachedDoc, TDocWithState, TSpace, TSpaceWithStates } from '@anticrm/model-core'
|
||||||
@ -80,7 +79,7 @@ export class TCandidate extends TPerson implements Candidate {
|
|||||||
@UX('Application' as IntlString, recruit.icon.RecruitApplication, 'APP' as IntlString)
|
@UX('Application' as IntlString, recruit.icon.RecruitApplication, 'APP' as IntlString)
|
||||||
export class TApplicant extends TAttachedDoc implements Applicant {
|
export class TApplicant extends TAttachedDoc implements Applicant {
|
||||||
// We need to declare, to provide property with label
|
// We need to declare, to provide property with label
|
||||||
@Prop(TypeString(), 'Candidate' as IntlString)
|
@Prop(TypeRef(recruit.class.Candidate), 'Candidate' as IntlString)
|
||||||
declare attachedTo: Ref<Candidate>
|
declare attachedTo: Ref<Candidate>
|
||||||
|
|
||||||
@Prop(TypeString(), 'Attachments' as IntlString)
|
@Prop(TypeString(), 'Attachments' as IntlString)
|
||||||
@ -89,8 +88,8 @@ export class TApplicant extends TAttachedDoc implements Applicant {
|
|||||||
@Prop(TypeString(), 'Comments' as IntlString)
|
@Prop(TypeString(), 'Comments' as IntlString)
|
||||||
comments?: number
|
comments?: number
|
||||||
|
|
||||||
@Prop(TypeString(), 'Assigned recruiter' as IntlString)
|
@Prop(TypeRef(contact.class.Employee), 'Assigned recruiter' as IntlString)
|
||||||
employee!: Ref<Employee>
|
employee!: Ref<Employee> | null
|
||||||
|
|
||||||
// We need this two to make typescript happy.
|
// We need this two to make typescript happy.
|
||||||
declare state: TDocWithState['state']
|
declare state: TDocWithState['state']
|
||||||
@ -228,14 +227,6 @@ export function createModel (builder: Builder): void {
|
|||||||
attachedTo: recruit.class.Applicant,
|
attachedTo: recruit.class.Applicant,
|
||||||
sequence: 0
|
sequence: 0
|
||||||
})
|
})
|
||||||
|
|
||||||
builder.createDoc(activity.class.TxViewlet, core.space.Model, {
|
|
||||||
objectClass: recruit.class.Applicant,
|
|
||||||
icon: recruit.icon.RecruitApplication,
|
|
||||||
txClass: core.class.TxUpdateDoc,
|
|
||||||
component: recruit.activity.TxApplicantUpdate,
|
|
||||||
display: 'inline'
|
|
||||||
}, recruit.ids.TxApplicantUpdate)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export { default } from './plugin'
|
export { default } from './plugin'
|
||||||
|
@ -13,14 +13,13 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
import { mergeIds } from '@anticrm/platform'
|
import type { Doc, Ref, Space } from '@anticrm/core'
|
||||||
import type { IntlString, Resource } from '@anticrm/platform'
|
import type { IntlString, Resource } from '@anticrm/platform'
|
||||||
import type { Ref, Space, Doc } from '@anticrm/core'
|
import { mergeIds } from '@anticrm/platform'
|
||||||
import type { AnyComponent } from '@anticrm/ui'
|
|
||||||
import type { Action } from '@anticrm/view'
|
|
||||||
import { recruitId } from '@anticrm/recruit'
|
import { recruitId } from '@anticrm/recruit'
|
||||||
import recruit from '@anticrm/recruit-resources/src/plugin'
|
import recruit from '@anticrm/recruit-resources/src/plugin'
|
||||||
import { TxViewlet } from '@anticrm/activity'
|
import type { AnyComponent } from '@anticrm/ui'
|
||||||
|
import type { Action } from '@anticrm/view'
|
||||||
|
|
||||||
export default mergeIds(recruitId, recruit, {
|
export default mergeIds(recruitId, recruit, {
|
||||||
action: {
|
action: {
|
||||||
@ -48,11 +47,5 @@ export default mergeIds(recruitId, recruit, {
|
|||||||
},
|
},
|
||||||
space: {
|
space: {
|
||||||
CandidatesPublic: '' as Ref<Space>
|
CandidatesPublic: '' as Ref<Space>
|
||||||
},
|
|
||||||
ids: {
|
|
||||||
TxApplicantUpdate: '' as Ref<TxViewlet>
|
|
||||||
},
|
|
||||||
activity: {
|
|
||||||
TxApplicantUpdate: '' as AnyComponent
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
import type { Employee } from '@anticrm/contact'
|
import type { Employee } from '@anticrm/contact'
|
||||||
import contact from '@anticrm/contact'
|
import contact from '@anticrm/contact'
|
||||||
import type { Doc, DocWithState, Domain, FindOptions, Ref } from '@anticrm/core'
|
import type { Doc, DocWithState, Domain, FindOptions, Ref } from '@anticrm/core'
|
||||||
import { Builder, Model, Prop, TypeString, UX } from '@anticrm/model'
|
import { Builder, Model, Prop, TypeRef, TypeString, UX } from '@anticrm/model'
|
||||||
import chunter from '@anticrm/model-chunter'
|
import chunter from '@anticrm/model-chunter'
|
||||||
import core, { TDoc, TSpaceWithStates } from '@anticrm/model-core'
|
import core, { TDoc, TSpaceWithStates } from '@anticrm/model-core'
|
||||||
import view from '@anticrm/model-view'
|
import view from '@anticrm/model-view'
|
||||||
@ -42,8 +42,8 @@ export class TTask extends TDoc implements Task {
|
|||||||
@Prop(TypeString(), 'Description' as IntlString)
|
@Prop(TypeString(), 'Description' as IntlString)
|
||||||
description!: string
|
description!: string
|
||||||
|
|
||||||
@Prop(TypeString(), 'Assignee' as IntlString)
|
@Prop(TypeRef(contact.class.Employee), 'Assignee' as IntlString)
|
||||||
assignee!: Ref<Employee>
|
assignee!: Ref<Employee> | null
|
||||||
|
|
||||||
@Prop(TypeString(), 'Comments' as IntlString)
|
@Prop(TypeString(), 'Comments' as IntlString)
|
||||||
comments!: number
|
comments!: number
|
||||||
|
@ -84,7 +84,7 @@ export abstract class MemDb extends TxProcessor {
|
|||||||
const result: LookupData<T> = {}
|
const result: LookupData<T> = {}
|
||||||
for (const key in lookup) {
|
for (const key in lookup) {
|
||||||
const id = (doc as any)[key] as Ref<Doc>
|
const id = (doc as any)[key] as Ref<Doc>
|
||||||
if (id !== undefined) {
|
if (id != null) {
|
||||||
(result as any)[key] = this.getObject(id)
|
(result as any)[key] = this.getObject(id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -308,8 +308,8 @@ export function TypeDate (): Type<string> {
|
|||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
export function TypeState (): Type<string> {
|
export function TypeRef (_class: Ref<Class<Doc>>): Type<string> {
|
||||||
return { _class: core.class.State, label: 'TypeState' as IntlString }
|
return { _class: _class, label: 'TypeRef' as IntlString }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -15,12 +15,13 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { Ref, Class, Doc } from '@anticrm/core'
|
import type { AttachedDoc, AttachedDoc, Doc } from '@anticrm/core'
|
||||||
|
import core from '@anticrm/core'
|
||||||
import { getResource } from '@anticrm/platform'
|
import { getResource } from '@anticrm/platform'
|
||||||
import type { AnySvelteComponent } from '@anticrm/ui'
|
import type { AnySvelteComponent } from '@anticrm/ui'
|
||||||
import { CircleButton, Label } from '@anticrm/ui'
|
import { CircleButton, Label } from '@anticrm/ui'
|
||||||
import { getClient } from '../utils'
|
|
||||||
import view from '@anticrm/view'
|
import view from '@anticrm/view'
|
||||||
|
import { getClient } from '../utils'
|
||||||
|
|
||||||
// export let _class: Ref<Class<Doc>>
|
// export let _class: Ref<Class<Doc>>
|
||||||
export let key: string
|
export let key: string
|
||||||
@ -45,8 +46,13 @@
|
|||||||
editor = getResource(editorMixin.editor)
|
editor = getResource(editorMixin.editor)
|
||||||
}
|
}
|
||||||
|
|
||||||
function onChange(value: any) {
|
function onChange (value: any) {
|
||||||
client.updateDoc(_class, object.space, object._id, { [key]: value }, true).then(result => console.log('UPDATE RESULT', result))
|
if (client.getHierarchy().isDerived(object._class, core.class.AttachedDoc)) {
|
||||||
|
const adoc = object as AttachedDoc
|
||||||
|
client.updateCollection(_class, object.space, adoc._id, adoc.attachedTo, adoc.attachedToClass, adoc.collection, { [key]: value })
|
||||||
|
} else {
|
||||||
|
client.updateDoc(_class, object.space, object._id, { [key]: value }, true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -29,8 +29,11 @@
|
|||||||
export let _class: Ref<Class<Person>>
|
export let _class: Ref<Class<Person>>
|
||||||
export let title: IntlString
|
export let title: IntlString
|
||||||
export let caption: IntlString
|
export let caption: IntlString
|
||||||
export let value: Ref<Person>
|
export let value: Ref<Person> | null | undefined
|
||||||
export let show: boolean = false
|
export let show: boolean = false
|
||||||
|
export let allowDeselect = false
|
||||||
|
export let titleDeselect: IntlString | undefined = undefined
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
|
|
||||||
let selected: Person | undefined
|
let selected: Person | undefined
|
||||||
@ -40,11 +43,13 @@
|
|||||||
|
|
||||||
const client = getClient()
|
const client = getClient()
|
||||||
|
|
||||||
async function updateSelected(value: Ref<Person>) {
|
async function updateSelected (value: Ref<Person>) {
|
||||||
selected = await client.findOne(_class, { _id: value })
|
selected = await client.findOne(_class, { _id: value })
|
||||||
}
|
}
|
||||||
|
|
||||||
$: updateSelected(value)
|
$: if (value != null) {
|
||||||
|
updateSelected(value)
|
||||||
|
}
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
if (btn && show) {
|
if (btn && show) {
|
||||||
@ -59,10 +64,19 @@
|
|||||||
btn.focus()
|
btn.focus()
|
||||||
if (!opened) {
|
if (!opened) {
|
||||||
opened = true
|
opened = true
|
||||||
showPopup(UsersPopup, { _class, title, caption }, container, (result) => {
|
showPopup(UsersPopup, { _class, title, caption, allowDeselect, selected: value, titleDeselect }, container, (result) => {
|
||||||
if (result) {
|
if (result === undefined) {
|
||||||
|
// Value is not changed.
|
||||||
|
opened = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (result != null) {
|
||||||
value = result._id
|
value = result._id
|
||||||
dispatch('change', value)
|
dispatch('change', value)
|
||||||
|
} else {
|
||||||
|
value = null
|
||||||
|
selected = undefined
|
||||||
|
dispatch('change', null)
|
||||||
}
|
}
|
||||||
opened = false
|
opened = false
|
||||||
})
|
})
|
||||||
|
@ -22,17 +22,23 @@
|
|||||||
import type { Ref, Class } from '@anticrm/core'
|
import type { Ref, Class } from '@anticrm/core'
|
||||||
import type { Person } from '@anticrm/contact'
|
import type { Person } from '@anticrm/contact'
|
||||||
import { createQuery } from '../utils'
|
import { createQuery } from '../utils'
|
||||||
|
import { ActionIcon } from '@anticrm/ui'
|
||||||
|
import BlueCheck from './icons/BlueCheck.svelte'
|
||||||
|
|
||||||
export let _class: Ref<Class<Person>>
|
export let _class: Ref<Class<Person>>
|
||||||
export let title: IntlString
|
export let title: IntlString
|
||||||
export let caption: IntlString
|
export let caption: IntlString
|
||||||
|
export let selected: Ref<Person> | undefined
|
||||||
|
|
||||||
|
export let allowDeselect: boolean = false
|
||||||
|
export let titleDeselect: IntlString | undefined = undefined
|
||||||
|
|
||||||
let search: string = ''
|
let search: string = ''
|
||||||
let objects: Person[] = []
|
let objects: Person[] = []
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
const query = createQuery()
|
const query = createQuery()
|
||||||
$: query.query(_class, { name: { $like: '%'+search+'%' } }, result => { objects = result })
|
$: query.query(_class, { name: { $like: '%' + search + '%' } }, result => { objects = result })
|
||||||
afterUpdate(() => { dispatch('update', Date.now()) })
|
afterUpdate(() => { dispatch('update', Date.now()) })
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -46,7 +52,12 @@
|
|||||||
<div class="flex-col box">
|
<div class="flex-col box">
|
||||||
{#each objects as person}
|
{#each objects as person}
|
||||||
<button class="menu-item" on:click={() => { dispatch('close', person) }}>
|
<button class="menu-item" on:click={() => { dispatch('close', person) }}>
|
||||||
<UserInfo size={'medium'} value={person} />
|
<div class='flex-grow'>
|
||||||
|
<UserInfo size={'medium'} value={person} />
|
||||||
|
</div>
|
||||||
|
{#if allowDeselect && person._id === selected}
|
||||||
|
<ActionIcon direction={'top'} label={titleDeselect ?? 'Deselect'} icon={BlueCheck} action={() => { dispatch('close', null) }} size={'small'}/>
|
||||||
|
{/if}
|
||||||
</button>
|
</button>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
22
packages/presentation/src/components/icons/BlueCheck.svelte
Normal file
22
packages/presentation/src/components/icons/BlueCheck.svelte
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
export let size: 'small' | 'medium' | 'large'
|
||||||
|
const fill: string = 'currentColor'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svg class="svg-{size}" {fill} xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
|
||||||
|
<svg viewBox="0 0 24 24" {fill} xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g filter="url(#filter0_b_991_16450)">
|
||||||
|
<rect width="24" height="24" rx="12" fill="#4474F6"/>
|
||||||
|
</g>
|
||||||
|
<path d="M8.25 12L10.9989 15L15.75 9" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<defs>
|
||||||
|
<filter id="filter0_b_991_16450" x="-100" y="-100" width="224" height="224" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feGaussianBlur in="BackgroundImage" stdDeviation="50"/>
|
||||||
|
<feComposite in2="SourceAlpha" operator="in" result="effect1_backgroundBlur_991_16450"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="effect1_backgroundBlur_991_16450" result="shape"/>
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
</svg>
|
@ -129,8 +129,15 @@
|
|||||||
actions = result
|
actions = result
|
||||||
})
|
})
|
||||||
|
|
||||||
function getValue (utx: TxUpdateDoc<Doc>, key: string): any {
|
async function getValue (m: AttributeModel, utx: TxUpdateDoc<Doc>): Promise<any> {
|
||||||
return (utx.operations as any)[key]
|
const val = (utx.operations as any)[m.key]
|
||||||
|
console.log(m._class, m.key, val, typeof val)
|
||||||
|
|
||||||
|
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 showMenu = async (ev: MouseEvent): Promise<void> => {
|
||||||
showPopup(
|
showPopup(
|
||||||
@ -207,8 +214,14 @@
|
|||||||
{/if}
|
{/if}
|
||||||
{#if viewlet === undefined && model.length > 0 && tx.updateTx}
|
{#if viewlet === undefined && model.length > 0 && tx.updateTx}
|
||||||
{#each model as m}
|
{#each model as m}
|
||||||
<span>changed {m.label} to</span>
|
{#await getValue(m, tx.updateTx) then value}
|
||||||
<div class="strong"><svelte:component this={m.presenter} value={getValue(tx.updateTx, m.key)} /></div>
|
{#if value === null}
|
||||||
|
<span>unset {m.label}</span>
|
||||||
|
{:else}
|
||||||
|
<span>changed {m.label} to</span>
|
||||||
|
<div class="strong"><svelte:component this={m.presenter} {value} /></div>
|
||||||
|
{/if}
|
||||||
|
{/await}
|
||||||
{/each}
|
{/each}
|
||||||
{:else if viewlet && viewlet.display === 'inline' && viewlet.component}
|
{:else if viewlet && viewlet.display === 'inline' && viewlet.component}
|
||||||
<div>
|
<div>
|
||||||
|
@ -13,28 +13,43 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import contact from '@anticrm/contact'
|
||||||
import { AttributeBarEditor, getClient, UserBox } from '@anticrm/presentation'
|
import { AttributeBarEditor, getClient, UserBox } from '@anticrm/presentation'
|
||||||
import { Applicant } from '@anticrm/recruit'
|
import { Applicant } from '@anticrm/recruit'
|
||||||
import contact from '@anticrm/contact'
|
|
||||||
|
|
||||||
export let object: Applicant
|
export let object: Applicant
|
||||||
const client = getClient()
|
const client = getClient()
|
||||||
|
|
||||||
function change () {
|
function change() {
|
||||||
client.updateDoc(object._class, object.space, object._id, { employee: object.employee })
|
client.updateCollection(
|
||||||
|
object._class,
|
||||||
|
object.space,
|
||||||
|
object._id,
|
||||||
|
object.attachedTo,
|
||||||
|
object.attachedToClass,
|
||||||
|
object.collection,
|
||||||
|
{ employee: object.employee }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="flex-between header">
|
<div class="flex-between header">
|
||||||
<UserBox _class={contact.class.Employee} title='Assigned recruiter' caption='Recruiters' bind:value={object.employee} on:change={change} />
|
<UserBox
|
||||||
|
_class={contact.class.Employee}
|
||||||
|
title="Assigned recruiter"
|
||||||
|
caption="Recruiters"
|
||||||
|
bind:value={object.employee}
|
||||||
|
on:change={change}
|
||||||
|
allowDeselect
|
||||||
|
titleDeselect={'Unassign recruiter'}
|
||||||
|
/>
|
||||||
<AttributeBarEditor key={'state'} {object} showHeader={false} />
|
<AttributeBarEditor key={'state'} {object} showHeader={false} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.header {
|
.header {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 0 .5rem;
|
padding: 0 0.5rem;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { createEventDispatcher } from 'svelte'
|
import { createEventDispatcher } from 'svelte'
|
||||||
import type { Ref, Space, SpaceWithStates } from '@anticrm/core'
|
import type { Ref, Space, SpaceWithStates } from '@anticrm/core'
|
||||||
@ -33,7 +32,7 @@
|
|||||||
|
|
||||||
export let space: Ref<SpaceWithStates>
|
export let space: Ref<SpaceWithStates>
|
||||||
export let candidate: Ref<Candidate> // | null = null
|
export let candidate: Ref<Candidate> // | null = null
|
||||||
export let employee: Ref<Employee> // | null = null
|
export let employee: Ref<Employee> | null = null
|
||||||
|
|
||||||
export let preserveCandidate = false
|
export let preserveCandidate = false
|
||||||
|
|
||||||
@ -56,18 +55,31 @@
|
|||||||
if (sequence === undefined) {
|
if (sequence === undefined) {
|
||||||
throw new Error('sequence object not found')
|
throw new Error('sequence object not found')
|
||||||
}
|
}
|
||||||
const incResult = await client.updateDoc(view.class.Sequence, view.space.Sequence, sequence._id, {
|
const incResult = await client.updateDoc(
|
||||||
$inc: { sequence: 1 }
|
view.class.Sequence,
|
||||||
}, true)
|
view.space.Sequence,
|
||||||
const id = await client.addCollection(recruit.class.Applicant, _space, candidate, recruit.class.Candidate, 'applications', {
|
sequence._id,
|
||||||
state: state._id,
|
{
|
||||||
number: incResult.object.sequence,
|
$inc: { sequence: 1 }
|
||||||
employee: employee
|
},
|
||||||
})
|
true
|
||||||
|
)
|
||||||
|
const id = await client.addCollection(
|
||||||
|
recruit.class.Applicant,
|
||||||
|
_space,
|
||||||
|
candidate,
|
||||||
|
recruit.class.Candidate,
|
||||||
|
'applications',
|
||||||
|
{
|
||||||
|
state: state._id,
|
||||||
|
number: incResult.object.sequence,
|
||||||
|
employee: employee
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function validate (candidate: Ref<Candidate>, space: Ref<Space>) {
|
async function validate (candidate: Ref<Candidate>, space: Ref<Space>) {
|
||||||
if (candidate === undefined) {
|
if (candidate == null) {
|
||||||
status = new Status(Severity.INFO, recruit.status.CandidateRequired, {})
|
status = new Status(Severity.INFO, recruit.status.CandidateRequired, {})
|
||||||
} else {
|
} else {
|
||||||
if (space === undefined) {
|
if (space === undefined) {
|
||||||
@ -84,22 +96,32 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
$: validate(candidate, _space)
|
$: validate(candidate, _space)
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Card label={'Create Application'}
|
<Card
|
||||||
okAction={createApplication}
|
label={'Create Application'}
|
||||||
canSave={status.severity === Severity.OK}
|
okAction={createApplication}
|
||||||
spaceClass={recruit.class.Vacancy}
|
canSave={status.severity === Severity.OK}
|
||||||
spaceLabel={'Vacancy'}
|
spaceClass={recruit.class.Vacancy}
|
||||||
spacePlaceholder={'Select vacancy'}
|
spaceLabel={'Vacancy'}
|
||||||
bind:space={_space}
|
spacePlaceholder={'Select vacancy'}
|
||||||
on:close={() => { dispatch('close') }}>
|
bind:space={_space}
|
||||||
|
on:close={() => {
|
||||||
|
dispatch('close')
|
||||||
|
}}
|
||||||
|
>
|
||||||
<StatusControl slot="error" {status} />
|
<StatusControl slot="error" {status} />
|
||||||
<Grid column={1} rowGap={1.75}>
|
<Grid column={1} rowGap={1.75}>
|
||||||
{#if !preserveCandidate}
|
{#if !preserveCandidate}
|
||||||
<UserBox _class={recruit.class.Candidate} title='Candidate' caption='Candidates' bind:value={candidate} />
|
<UserBox _class={recruit.class.Candidate} title="Candidate" caption="Candidates" bind:value={candidate} />
|
||||||
{/if}
|
{/if}
|
||||||
<UserBox _class={contact.class.Employee} title='Assigned recruiter' caption='Recruiters' bind:value={employee} />
|
<UserBox
|
||||||
|
_class={contact.class.Employee}
|
||||||
|
title="Assigned recruiter"
|
||||||
|
caption="Recruiters"
|
||||||
|
bind:value={employee}
|
||||||
|
allowDeselect
|
||||||
|
titleDeselect={'Unassign recruiter'}
|
||||||
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Card>
|
</Card>
|
||||||
|
@ -1,48 +0,0 @@
|
|||||||
<!--
|
|
||||||
// Copyright © 2020, 2021 Anticrm Platform Contributors.
|
|
||||||
//
|
|
||||||
// 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 type { Class, State, TxUpdateDoc } from '@anticrm/core'
|
|
||||||
import core from '@anticrm/core'
|
|
||||||
import { getClient } from '@anticrm/presentation'
|
|
||||||
import type { Applicant } from '@anticrm/recruit'
|
|
||||||
import { Component } from '@anticrm/ui'
|
|
||||||
import view from '@anticrm/view'
|
|
||||||
|
|
||||||
export let tx: TxUpdateDoc<Applicant>
|
|
||||||
|
|
||||||
const client = getClient()
|
|
||||||
|
|
||||||
const stateClass = client.getModel().getObject(core.class.State) as Class<State>
|
|
||||||
const statePresenter = client.getHierarchy().as(stateClass, view.mixin.AttributePresenter)
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{#if tx.operations.state}
|
|
||||||
<div class="flex-row-center update-container">
|
|
||||||
<span>updated State to</span>
|
|
||||||
{#if statePresenter?.presenter}
|
|
||||||
{#await client.findOne(core.class.State, { _id: tx.operations.state }) then st}
|
|
||||||
{#if st}
|
|
||||||
<Component is={statePresenter.presenter} props={{ value: st }}/>
|
|
||||||
{/if}
|
|
||||||
{/await}
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
.update-container span { margin-right: .5rem; }
|
|
||||||
</style>
|
|
@ -25,7 +25,6 @@ import KanbanCard from './components/KanbanCard.svelte'
|
|||||||
import EditVacancy from './components/EditVacancy.svelte'
|
import EditVacancy from './components/EditVacancy.svelte'
|
||||||
import ApplicationPresenter from './components/ApplicationPresenter.svelte'
|
import ApplicationPresenter from './components/ApplicationPresenter.svelte'
|
||||||
import ApplicationsPresenter from './components/ApplicationsPresenter.svelte'
|
import ApplicationsPresenter from './components/ApplicationsPresenter.svelte'
|
||||||
import TxApplicantUpdate from './components/activity/TxApplicantUpdate.svelte'
|
|
||||||
|
|
||||||
import { showPopup } from '@anticrm/ui'
|
import { showPopup } from '@anticrm/ui'
|
||||||
import { Resources } from '@anticrm/platform'
|
import { Resources } from '@anticrm/platform'
|
||||||
@ -49,8 +48,5 @@ export default async (): Promise<Resources> => ({
|
|||||||
ApplicationPresenter,
|
ApplicationPresenter,
|
||||||
ApplicationsPresenter,
|
ApplicationsPresenter,
|
||||||
EditVacancy
|
EditVacancy
|
||||||
},
|
|
||||||
activity: {
|
|
||||||
TxApplicantUpdate
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -53,7 +53,7 @@ export interface Candidate extends Person {
|
|||||||
export interface Applicant extends DocWithState, AttachedDoc {
|
export interface Applicant extends DocWithState, AttachedDoc {
|
||||||
attachments?: number
|
attachments?: number
|
||||||
comments?: number
|
comments?: number
|
||||||
employee: Ref<Employee>
|
employee: Ref<Employee> | null
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
"UploadDropFilesHere": "Upload or drop files here",
|
"UploadDropFilesHere": "Upload or drop files here",
|
||||||
"NoAttachmentsForTask": "There are no attachments for this task.",
|
"NoAttachmentsForTask": "There are no attachments for this task.",
|
||||||
"AssigneeRequired": "Assignee is required",
|
"AssigneeRequired": "Assignee is required",
|
||||||
"More": "Options"
|
"More": "Options",
|
||||||
|
"TaskUnAssign": "Unassign"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -13,7 +13,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import contact, { Employee, EmployeeAccount } from '@anticrm/contact'
|
import contact, { Employee } from '@anticrm/contact'
|
||||||
import type { Data, Ref, Space } from '@anticrm/core'
|
import type { Data, Ref, Space } from '@anticrm/core'
|
||||||
import { generateId } from '@anticrm/core'
|
import { generateId } from '@anticrm/core'
|
||||||
import { OK, Status } from '@anticrm/platform'
|
import { OK, Status } from '@anticrm/platform'
|
||||||
@ -29,12 +29,12 @@
|
|||||||
let _space = space
|
let _space = space
|
||||||
const status: Status = OK
|
const status: Status = OK
|
||||||
|
|
||||||
let assignee: Ref<EmployeeAccount> // | null = null
|
let assignee: Ref<Employee> | null = null
|
||||||
|
|
||||||
const object: Data<Task> = {
|
const object: Data<Task> = {
|
||||||
name: '',
|
name: '',
|
||||||
description: '',
|
description: '',
|
||||||
assignee: undefined as unknown as Ref<Employee>,
|
assignee: null,
|
||||||
number: 0
|
number: 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,7 +79,7 @@
|
|||||||
<Card
|
<Card
|
||||||
label={task.string.CreateTask}
|
label={task.string.CreateTask}
|
||||||
okAction={createTask}
|
okAction={createTask}
|
||||||
canSave={object.name.length > 0 && assignee !== undefined}
|
canSave={object.name.length > 0}
|
||||||
spaceClass={task.class.Project}
|
spaceClass={task.class.Project}
|
||||||
spaceLabel={task.string.ProjectName}
|
spaceLabel={task.string.ProjectName}
|
||||||
spacePlaceholder={task.string.SelectProject}
|
spacePlaceholder={task.string.SelectProject}
|
||||||
@ -99,10 +99,12 @@
|
|||||||
focus
|
focus
|
||||||
/>
|
/>
|
||||||
<UserBox
|
<UserBox
|
||||||
_class={contact.class.EmployeeAccount}
|
_class={contact.class.Employee}
|
||||||
title="Assignee *"
|
title="Assignee *"
|
||||||
caption="Assign this task"
|
caption="Assign this task"
|
||||||
bind:value={assignee}
|
bind:value={assignee}
|
||||||
|
allowDeselect
|
||||||
|
titleDeselect={task.string.TaskUnAssign}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Card>
|
</Card>
|
||||||
|
@ -34,6 +34,8 @@
|
|||||||
caption="Assignee"
|
caption="Assignee"
|
||||||
bind:value={object.assignee}
|
bind:value={object.assignee}
|
||||||
on:change={change}
|
on:change={change}
|
||||||
|
allowDeselect
|
||||||
|
titleDeselect={task.string.TaskUnAssign}
|
||||||
/>
|
/>
|
||||||
<AttributeBarEditor key={'state'} {object} showHeader={false} />
|
<AttributeBarEditor key={'state'} {object} showHeader={false} />
|
||||||
</div>
|
</div>
|
||||||
|
@ -30,6 +30,7 @@ export default mergeIds(taskId, task, {
|
|||||||
SelectProject: '' as IntlString,
|
SelectProject: '' as IntlString,
|
||||||
TaskName: '' as IntlString,
|
TaskName: '' as IntlString,
|
||||||
TaskAssignee: '' as IntlString,
|
TaskAssignee: '' as IntlString,
|
||||||
|
TaskUnAssign: '' as IntlString,
|
||||||
TaskDescription: '' as IntlString,
|
TaskDescription: '' as IntlString,
|
||||||
NoAttachmentsForTask: '' as IntlString,
|
NoAttachmentsForTask: '' as IntlString,
|
||||||
UploadDropFilesHere: '' as IntlString,
|
UploadDropFilesHere: '' as IntlString,
|
||||||
|
@ -33,7 +33,7 @@ export interface Task extends Doc {
|
|||||||
|
|
||||||
name: string
|
name: string
|
||||||
description: string
|
description: string
|
||||||
assignee: Ref<Employee>
|
assignee: Ref<Employee> | null
|
||||||
|
|
||||||
comments?: number
|
comments?: number
|
||||||
attachments?: number
|
attachments?: number
|
||||||
|
@ -1,36 +1,35 @@
|
|||||||
//
|
//
|
||||||
// Copyright © 2020, 2021 Anticrm Platform Contributors.
|
// Copyright © 2020, 2021 Anticrm Platform Contributors.
|
||||||
// Copyright © 2021 Hardcore Engineering Inc.
|
// Copyright © 2021 Hardcore Engineering Inc.
|
||||||
//
|
//
|
||||||
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
// 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
|
// 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
|
// 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
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
//
|
//
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
import type { Class, Client, Doc, FindOptions, FindResult, Obj, Ref } from '@anticrm/core'
|
||||||
import type { IntlString } from '@anticrm/platform'
|
import type { IntlString } from '@anticrm/platform'
|
||||||
import { getResource } from '@anticrm/platform'
|
import { getResource } from '@anticrm/platform'
|
||||||
import type { Ref, Class, Obj, FindOptions, Doc, Client, FindResult } from '@anticrm/core'
|
import type { AnyComponent } from '@anticrm/ui'
|
||||||
import type { AnyComponent, AnySvelteComponent } from '@anticrm/ui'
|
|
||||||
import type { Action, ActionTarget, BuildModelOptions } from '@anticrm/view'
|
import type { Action, ActionTarget, BuildModelOptions } from '@anticrm/view'
|
||||||
|
|
||||||
import view, { AttributeModel } from '@anticrm/view'
|
import view, { AttributeModel } from '@anticrm/view'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
export async function getObjectPresenter(client: Client, _class: Ref<Class<Obj>>, preserveKey: string): Promise<AttributeModel> {
|
export async function getObjectPresenter (client: Client, _class: Ref<Class<Obj>>, preserveKey: string): Promise<AttributeModel> {
|
||||||
const clazz = client.getHierarchy().getClass(_class)
|
const clazz = client.getHierarchy().getClass(_class)
|
||||||
const presenterMixin = client.getHierarchy().as(clazz, view.mixin.AttributePresenter)
|
const presenterMixin = client.getHierarchy().as(clazz, view.mixin.AttributePresenter)
|
||||||
if (presenterMixin.presenter === undefined) {
|
if (presenterMixin.presenter === undefined) {
|
||||||
if (clazz.extends !== undefined) {
|
if (clazz.extends !== undefined) {
|
||||||
return getObjectPresenter(client, clazz.extends, preserveKey)
|
return await getObjectPresenter(client, clazz.extends, preserveKey)
|
||||||
} else {
|
} else {
|
||||||
throw new Error('object presenter not found for ' + preserveKey)
|
throw new Error('object presenter not found for ' + preserveKey)
|
||||||
}
|
}
|
||||||
@ -38,37 +37,48 @@ export async function getObjectPresenter(client: Client, _class: Ref<Class<Obj>>
|
|||||||
const presenter = await getResource(presenterMixin.presenter)
|
const presenter = await getResource(presenterMixin.presenter)
|
||||||
return {
|
return {
|
||||||
key: preserveKey,
|
key: preserveKey,
|
||||||
|
_class,
|
||||||
label: clazz.label,
|
label: clazz.label,
|
||||||
presenter
|
presenter
|
||||||
} as AttributeModel
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getAttributePresenter(client: Client, _class: Ref<Class<Obj>>, key: string, preserveKey: string) {
|
async function getAttributePresenter (client: Client, _class: Ref<Class<Obj>>, key: string, preserveKey: string): Promise<AttributeModel> {
|
||||||
const attribute = client.getHierarchy().getAttribute(_class, key)
|
const attribute = client.getHierarchy().getAttribute(_class, key)
|
||||||
const clazz = client.getHierarchy().getClass(attribute.type._class)
|
let attrClass = attribute.type._class
|
||||||
const presenterMixin = client.getHierarchy().as(clazz, view.mixin.AttributePresenter)
|
const clazz = client.getHierarchy().getClass(attrClass)
|
||||||
|
let presenterMixin = client.getHierarchy().as(clazz, view.mixin.AttributePresenter)
|
||||||
|
let parent = clazz.extends
|
||||||
|
while (presenterMixin.presenter === undefined && parent !== undefined) {
|
||||||
|
const pclazz = client.getHierarchy().getClass(parent)
|
||||||
|
attrClass = parent
|
||||||
|
presenterMixin = client.getHierarchy().as(pclazz, view.mixin.AttributePresenter)
|
||||||
|
parent = pclazz.extends
|
||||||
|
}
|
||||||
if (presenterMixin.presenter === undefined) {
|
if (presenterMixin.presenter === undefined) {
|
||||||
throw new Error('attribute presenter not found for ' + preserveKey)
|
throw new Error('attribute presenter not found for ' + preserveKey)
|
||||||
}
|
}
|
||||||
const presenter = await getResource(presenterMixin.presenter)
|
const presenter = await getResource(presenterMixin.presenter)
|
||||||
return {
|
return {
|
||||||
key: preserveKey,
|
key: preserveKey,
|
||||||
|
_class: attrClass,
|
||||||
label: attribute.label,
|
label: attribute.label,
|
||||||
presenter
|
presenter
|
||||||
} as AttributeModel
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getPresenter(client: Client, _class: Ref<Class<Obj>>, key: string, preserveKey: string, options?: FindOptions<Doc>): Promise<AttributeModel> {
|
async function getPresenter (client: Client, _class: Ref<Class<Obj>>, key: string, preserveKey: string, options?: FindOptions<Doc>): Promise<AttributeModel> {
|
||||||
if (typeof key === 'object') {
|
if (typeof key === 'object') {
|
||||||
const {presenter, label} = key
|
const { presenter, label } = key
|
||||||
return {
|
return {
|
||||||
key: '',
|
key: '',
|
||||||
|
_class,
|
||||||
label: label as IntlString,
|
label: label as IntlString,
|
||||||
presenter: await getResource(presenter as AnyComponent)
|
presenter: await getResource(presenter as AnyComponent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (key.length === 0) {
|
if (key.length === 0) {
|
||||||
return getObjectPresenter(client, _class, preserveKey)
|
return await getObjectPresenter(client, _class, preserveKey)
|
||||||
} else {
|
} else {
|
||||||
const split = key.split('.')
|
const split = key.split('.')
|
||||||
if (split[0] === '$lookup') {
|
if (split[0] === '$lookup') {
|
||||||
@ -80,36 +90,37 @@ async function getPresenter(client: Client, _class: Ref<Class<Obj>>, key: string
|
|||||||
const model = await getPresenter(client, lookupClass, lookupKey, preserveKey)
|
const model = await getPresenter(client, lookupClass, lookupKey, preserveKey)
|
||||||
if (lookupKey === '') {
|
if (lookupKey === '') {
|
||||||
const attribute = client.getHierarchy().getAttribute(_class, split[1])
|
const attribute = client.getHierarchy().getAttribute(_class, split[1])
|
||||||
model.label = attribute.label as IntlString
|
model.label = attribute.label
|
||||||
} else {
|
} else {
|
||||||
const attribute = client.getHierarchy().getAttribute(lookupClass, lookupKey)
|
const attribute = client.getHierarchy().getAttribute(lookupClass, lookupKey)
|
||||||
model.label = attribute.label as IntlString
|
model.label = attribute.label
|
||||||
}
|
}
|
||||||
return model
|
return model
|
||||||
}
|
}
|
||||||
return getAttributePresenter(client, _class, key, preserveKey)
|
return await getAttributePresenter(client, _class, key, preserveKey)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function buildModel(options: BuildModelOptions): Promise<AttributeModel[]> {
|
export async function buildModel (options: BuildModelOptions): Promise<AttributeModel[]> {
|
||||||
console.log('building table model for', options._class)
|
console.log('building table model for', options._class)
|
||||||
|
// eslint-disable-next-line array-callback-return
|
||||||
const model = options.keys.map(key => {
|
const model = options.keys.map(key => {
|
||||||
try {
|
try {
|
||||||
const result = getPresenter(options.client, options._class, key, key, options.options)
|
const result = getPresenter(options.client, options._class, key, key, options.options)
|
||||||
return result
|
return result
|
||||||
} catch(err: any) {
|
} catch (err: any) {
|
||||||
if (!(options.ignoreMissing ?? false)) {
|
if (!(options.ignoreMissing ?? false)) {
|
||||||
throw err
|
throw err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
console.log(model)
|
console.log(model)
|
||||||
return (await Promise.all(model)).filter(a => a !== undefined) as AttributeModel[]
|
return (await Promise.all(model)).filter(a => a !== undefined) as AttributeModel[]
|
||||||
}
|
}
|
||||||
|
|
||||||
function filterActions(client: Client, _class: Ref<Class<Obj>>, targets: ActionTarget[]): Ref<Action>[] {
|
function filterActions (client: Client, _class: Ref<Class<Obj>>, targets: ActionTarget[]): Array<Ref<Action>> {
|
||||||
const result: Ref<Action>[] = []
|
const result: Array<Ref<Action>> = []
|
||||||
for (const target of targets) {
|
for (const target of targets) {
|
||||||
if (client.getHierarchy().isDerived(_class, target.target)) {
|
if (client.getHierarchy().isDerived(_class, target.target)) {
|
||||||
result.push(target.action)
|
result.push(target.action)
|
||||||
}
|
}
|
||||||
@ -117,7 +128,7 @@ function filterActions(client: Client, _class: Ref<Class<Obj>>, targets: ActionT
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getActions(client: Client, _class: Ref<Class<Obj>>): Promise<FindResult<Action>> {
|
export async function getActions (client: Client, _class: Ref<Class<Obj>>): Promise<FindResult<Action>> {
|
||||||
const targets = await client.findAll(view.class.ActionTarget, {})
|
const targets = await client.findAll(view.class.ActionTarget, {})
|
||||||
return await client.findAll(view.class.Action, { _id: { $in: filterActions(client, _class, targets) }})
|
return await client.findAll(view.class.Action, { _id: { $in: filterActions(client, _class, targets) } })
|
||||||
}
|
}
|
||||||
|
@ -109,6 +109,7 @@ export const viewId = 'view' as Plugin
|
|||||||
export interface AttributeModel {
|
export interface AttributeModel {
|
||||||
key: string
|
key: string
|
||||||
label: IntlString
|
label: IntlString
|
||||||
|
_class: Ref<Class<Doc>>
|
||||||
presenter: AnySvelteComponent
|
presenter: AnySvelteComponent
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user