mirror of
https://github.com/hcengineering/platform.git
synced 2024-12-22 19:11:33 +03:00
TSK-857: Create company button (#2762)
Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
parent
8e3a6989cd
commit
34b8a6cdd2
@ -0,0 +1,30 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { Class, Data, Doc, Ref } from '@hcengineering/core'
|
||||||
|
import { InlineAttributeBarEditor } from '..'
|
||||||
|
import { KeyedAttribute } from '../attributes'
|
||||||
|
import { getClient, getFiltredKeys, isCollectionAttr } from '../utils'
|
||||||
|
|
||||||
|
export let object: Doc | Data<Doc>
|
||||||
|
export let _class: Ref<Class<Doc>>
|
||||||
|
export let toClass: Ref<Class<Doc>> | undefined = undefined
|
||||||
|
export let ignoreKeys: string[] = []
|
||||||
|
export let extraKeys: string[] = []
|
||||||
|
export let extraProps: Record<string, any> = {}
|
||||||
|
|
||||||
|
let keys: KeyedAttribute[]
|
||||||
|
|
||||||
|
const client = getClient()
|
||||||
|
|
||||||
|
function updateKeys (_class: Ref<Class<Doc>>, ignoreKeys: string[], to: Ref<Class<Doc>> | undefined): void {
|
||||||
|
const filtredKeys = getFiltredKeys(client.getHierarchy(), _class, ignoreKeys, to)
|
||||||
|
keys = filtredKeys.filter(
|
||||||
|
(key) => (extraKeys.includes(key.key) || !isCollectionAttr(client.getHierarchy(), key)) && !key.attr.readonly
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
$: updateKeys(_class, ignoreKeys, toClass)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#each keys as key (typeof key === 'string' ? key : key.key)}
|
||||||
|
<InlineAttributeBarEditor {key} {_class} {object} readonly={false} draft={true} on:update {extraProps} />
|
||||||
|
{/each}
|
@ -0,0 +1,79 @@
|
|||||||
|
<!--
|
||||||
|
// Copyright © 2020, 2021 Anticrm Platform Contributors.
|
||||||
|
// Copyright © 2021 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 type { Class, Doc, Ref } from '@hcengineering/core'
|
||||||
|
import { AnySvelteComponent } from '@hcengineering/ui'
|
||||||
|
import { createEventDispatcher } from 'svelte'
|
||||||
|
import { getAttribute, KeyedAttribute, updateAttribute } from '../attributes'
|
||||||
|
import { getAttributeEditor, getClient } from '../utils'
|
||||||
|
|
||||||
|
export let key: KeyedAttribute | string
|
||||||
|
export let object: Doc | Record<string, any>
|
||||||
|
export let _class: Ref<Class<Doc>>
|
||||||
|
export let maxWidth: string | undefined = undefined
|
||||||
|
export let focus: boolean = false
|
||||||
|
export let readonly = false
|
||||||
|
export let draft = false
|
||||||
|
export let extraProps: Record<string, any> = {}
|
||||||
|
|
||||||
|
const client = getClient()
|
||||||
|
const hierarchy = client.getHierarchy()
|
||||||
|
const dispatch = createEventDispatcher()
|
||||||
|
|
||||||
|
let editor: Promise<void | AnySvelteComponent> | undefined
|
||||||
|
|
||||||
|
function onChange (value: any) {
|
||||||
|
const doc = object as Doc
|
||||||
|
if (draft) {
|
||||||
|
;(doc as any)[attributeKey] = value
|
||||||
|
dispatch('update', { key, value })
|
||||||
|
} else {
|
||||||
|
updateAttribute(client, doc, _class, { key: attributeKey, attr: attribute }, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$: attribute = typeof key === 'string' ? hierarchy.getAttribute(_class, key) : key.attr
|
||||||
|
$: attributeKey = typeof key === 'string' ? key : key.key
|
||||||
|
$: editor = getAttributeEditor(client, _class, key)
|
||||||
|
$: isReadonly = (attribute.readonly ?? false) || readonly
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if editor}
|
||||||
|
{#await editor then instance}
|
||||||
|
{#if instance}
|
||||||
|
<div class="flex min-w-0">
|
||||||
|
<svelte:component
|
||||||
|
this={instance}
|
||||||
|
{...extraProps}
|
||||||
|
readonly={isReadonly}
|
||||||
|
label={attribute?.label}
|
||||||
|
placeholder={attribute?.label}
|
||||||
|
kind={'link'}
|
||||||
|
size={'large'}
|
||||||
|
width={'100%'}
|
||||||
|
justify={'left'}
|
||||||
|
type={attribute?.type}
|
||||||
|
{maxWidth}
|
||||||
|
value={getAttribute(client, object, { key: attributeKey, attr: attribute })}
|
||||||
|
space={object.space}
|
||||||
|
{onChange}
|
||||||
|
{focus}
|
||||||
|
{object}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
{/await}
|
||||||
|
{/if}
|
@ -47,6 +47,7 @@
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
font-weight: inherit;
|
||||||
|
|
||||||
&.inline {
|
&.inline {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
|
@ -19,6 +19,8 @@ import { presentationId } from './plugin'
|
|||||||
export * from './attributes'
|
export * from './attributes'
|
||||||
export { default as AttributeBarEditor } from './components/AttributeBarEditor.svelte'
|
export { default as AttributeBarEditor } from './components/AttributeBarEditor.svelte'
|
||||||
export { default as AttributeEditor } from './components/AttributeEditor.svelte'
|
export { default as AttributeEditor } from './components/AttributeEditor.svelte'
|
||||||
|
export { default as InlineAttributeBarEditor } from './components/InlineAttributeBarEditor.svelte'
|
||||||
|
export { default as InlineAttributeBar } from './components/InlineAttributeBar.svelte'
|
||||||
export { default as AttributesBar } from './components/AttributesBar.svelte'
|
export { default as AttributesBar } from './components/AttributesBar.svelte'
|
||||||
export { default as Avatar } from './components/Avatar.svelte'
|
export { default as Avatar } from './components/Avatar.svelte'
|
||||||
export { default as AssigneeBox } from './components/AssigneeBox.svelte'
|
export { default as AssigneeBox } from './components/AssigneeBox.svelte'
|
||||||
|
@ -402,3 +402,33 @@ export async function getAttributeEditor (
|
|||||||
console.error(getAttributeEditorNotFoundError(_class, key, ex))
|
console.error(getAttributeEditorNotFoundError(_class, key, ex))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function filterKeys (hierarchy: Hierarchy, keys: KeyedAttribute[], ignoreKeys: string[]): KeyedAttribute[] {
|
||||||
|
const docKeys: Set<string> = new Set<string>(hierarchy.getAllAttributes(core.class.AttachedDoc).keys())
|
||||||
|
keys = keys.filter((k) => !docKeys.has(k.key))
|
||||||
|
keys = keys.filter((k) => !ignoreKeys.includes(k.key))
|
||||||
|
return keys
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export function getFiltredKeys (
|
||||||
|
hierarchy: Hierarchy,
|
||||||
|
objectClass: Ref<Class<Doc>>,
|
||||||
|
ignoreKeys: string[],
|
||||||
|
to?: Ref<Class<Doc>>
|
||||||
|
): KeyedAttribute[] {
|
||||||
|
const keys = [...hierarchy.getAllAttributes(objectClass, to).entries()]
|
||||||
|
.filter(([, value]) => value.hidden !== true)
|
||||||
|
.map(([key, attr]) => ({ key, attr }))
|
||||||
|
|
||||||
|
return filterKeys(hierarchy, keys, ignoreKeys)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export function isCollectionAttr (hierarchy: Hierarchy, key: KeyedAttribute): boolean {
|
||||||
|
return hierarchy.isDerived(key.attr.type._class, core.class.Collection)
|
||||||
|
}
|
||||||
|
@ -14,8 +14,8 @@
|
|||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Channel, findContacts, Organization } from '@hcengineering/contact'
|
import { Channel, findContacts, Organization } from '@hcengineering/contact'
|
||||||
import { AttachedData, generateId, WithLookup } from '@hcengineering/core'
|
import { AttachedData, generateId, Ref, TxOperations, WithLookup } from '@hcengineering/core'
|
||||||
import { Card, getClient } from '@hcengineering/presentation'
|
import { Card, getClient, InlineAttributeBar } from '@hcengineering/presentation'
|
||||||
import { Button, createFocusManager, EditBox, FocusHandler, IconInfo, Label } from '@hcengineering/ui'
|
import { Button, createFocusManager, EditBox, FocusHandler, IconInfo, Label } from '@hcengineering/ui'
|
||||||
import { createEventDispatcher } from 'svelte'
|
import { createEventDispatcher } from 'svelte'
|
||||||
import contact from '../plugin'
|
import contact from '../plugin'
|
||||||
@ -23,11 +23,13 @@
|
|||||||
import Company from './icons/Company.svelte'
|
import Company from './icons/Company.svelte'
|
||||||
import OrganizationPresenter from './OrganizationPresenter.svelte'
|
import OrganizationPresenter from './OrganizationPresenter.svelte'
|
||||||
|
|
||||||
|
export let onCreate: ((orgId: Ref<Organization>, client: TxOperations) => Promise<void>) | undefined = undefined
|
||||||
|
|
||||||
export function canClose (): boolean {
|
export function canClose (): boolean {
|
||||||
return object.name === ''
|
return object.name === ''
|
||||||
}
|
}
|
||||||
|
|
||||||
const id = generateId()
|
const id: Ref<Organization> = generateId()
|
||||||
|
|
||||||
const object: Organization = {
|
const object: Organization = {
|
||||||
name: ''
|
name: ''
|
||||||
@ -51,6 +53,9 @@
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
if (onCreate !== undefined) {
|
||||||
|
await onCreate?.(id, client)
|
||||||
|
}
|
||||||
|
|
||||||
dispatch('close', id)
|
dispatch('close', id)
|
||||||
}
|
}
|
||||||
@ -90,12 +95,22 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<svelte:fragment slot="pool">
|
<svelte:fragment slot="pool">
|
||||||
|
<div class="flex-row-center flex-wrap">
|
||||||
<ChannelsDropdown
|
<ChannelsDropdown
|
||||||
bind:value={channels}
|
bind:value={channels}
|
||||||
focusIndex={10}
|
focusIndex={10}
|
||||||
editable
|
editable
|
||||||
highlighted={matchedChannels.map((it) => it.provider)}
|
highlighted={matchedChannels.map((it) => it.provider)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<InlineAttributeBar
|
||||||
|
_class={contact.class.Organization}
|
||||||
|
{object}
|
||||||
|
toClass={contact.class.Contact}
|
||||||
|
on:update
|
||||||
|
extraProps={{ showNavigate: false }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
<svelte:fragment slot="footer">
|
<svelte:fragment slot="footer">
|
||||||
{#if matches.length > 0}
|
{#if matches.length > 0}
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
export let justify: 'left' | 'center' = 'center'
|
export let justify: 'left' | 'center' = 'center'
|
||||||
export let width: string | undefined = undefined
|
export let width: string | undefined = undefined
|
||||||
export let readonly = false
|
export let readonly = false
|
||||||
|
export let showNavigate = true
|
||||||
|
|
||||||
$: _class = type?.to ?? contact.class.Employee
|
$: _class = type?.to ?? contact.class.Employee
|
||||||
|
|
||||||
@ -50,4 +51,5 @@
|
|||||||
titleDeselect={contact.string.Cancel}
|
titleDeselect={contact.string.Cancel}
|
||||||
bind:value
|
bind:value
|
||||||
on:change={(e) => onChange(e.detail)}
|
on:change={(e) => onChange(e.detail)}
|
||||||
|
{showNavigate}
|
||||||
/>
|
/>
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
export let size: ButtonSize = 'small'
|
export let size: ButtonSize = 'small'
|
||||||
export let justify: 'left' | 'center' = 'left'
|
export let justify: 'left' | 'center' = 'left'
|
||||||
export let width: string | undefined = 'min-content'
|
export let width: string | undefined = 'min-content'
|
||||||
|
export let showNavigate = true
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<UserBox
|
<UserBox
|
||||||
@ -43,4 +44,5 @@
|
|||||||
on:change={(evt) => {
|
on:change={(evt) => {
|
||||||
onChange(evt.detail)
|
onChange(evt.detail)
|
||||||
}}
|
}}
|
||||||
|
{showNavigate}
|
||||||
/>
|
/>
|
||||||
|
@ -57,6 +57,7 @@ import PersonEditor from './components/PersonEditor.svelte'
|
|||||||
import PersonPresenter from './components/PersonPresenter.svelte'
|
import PersonPresenter from './components/PersonPresenter.svelte'
|
||||||
import PersonRefPresenter from './components/PersonRefPresenter.svelte'
|
import PersonRefPresenter from './components/PersonRefPresenter.svelte'
|
||||||
import SocialEditor from './components/SocialEditor.svelte'
|
import SocialEditor from './components/SocialEditor.svelte'
|
||||||
|
import ExpandRightDouble from './components/icons/ExpandRightDouble.svelte'
|
||||||
import contact from './plugin'
|
import contact from './plugin'
|
||||||
import {
|
import {
|
||||||
employeeSort,
|
employeeSort,
|
||||||
@ -86,7 +87,9 @@ export {
|
|||||||
EditPerson,
|
EditPerson,
|
||||||
EmployeeRefPresenter,
|
EmployeeRefPresenter,
|
||||||
AccountArrayEditor,
|
AccountArrayEditor,
|
||||||
AccountBox
|
AccountBox,
|
||||||
|
CreateOrganization,
|
||||||
|
ExpandRightDouble
|
||||||
}
|
}
|
||||||
|
|
||||||
const toObjectSearchResult = (e: WithLookup<Contact>): ObjectSearchResult => ({
|
const toObjectSearchResult = (e: WithLookup<Contact>): ObjectSearchResult => ({
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Employee } from '@hcengineering/contact'
|
import { Employee } from '@hcengineering/contact'
|
||||||
import { Ref } from '@hcengineering/core'
|
import { Ref } from '@hcengineering/core'
|
||||||
import { Card, getClient, SpaceSelector, EmployeeBox } from '@hcengineering/presentation'
|
import { Card, EmployeeBox, getClient, SpaceSelector } from '@hcengineering/presentation'
|
||||||
import { Button, createFocusManager, EditBox, FocusHandler } from '@hcengineering/ui'
|
import { Button, createFocusManager, EditBox, FocusHandler } from '@hcengineering/ui'
|
||||||
import { createEventDispatcher } from 'svelte'
|
import { createEventDispatcher } from 'svelte'
|
||||||
import hr from '../plugin'
|
import hr from '../plugin'
|
||||||
@ -82,6 +82,7 @@
|
|||||||
placeholder={hr.string.TeamLead}
|
placeholder={hr.string.TeamLead}
|
||||||
bind:value={lead}
|
bind:value={lead}
|
||||||
allowDeselect
|
allowDeselect
|
||||||
|
showNavigate={false}
|
||||||
titleDeselect={hr.string.UnAssignLead}
|
titleDeselect={hr.string.UnAssignLead}
|
||||||
/>
|
/>
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
import { OK, Status } from '@hcengineering/platform'
|
import { OK, Status } from '@hcengineering/platform'
|
||||||
import { Card, createQuery, EmployeeBox, getClient, SpaceSelector, UserBox } from '@hcengineering/presentation'
|
import { Card, createQuery, EmployeeBox, getClient, SpaceSelector, UserBox } from '@hcengineering/presentation'
|
||||||
import task, { calcRank } from '@hcengineering/task'
|
import task, { calcRank } from '@hcengineering/task'
|
||||||
import { createFocusManager, EditBox, FocusHandler, Label, Status as StatusControl, Button } from '@hcengineering/ui'
|
import { Button, createFocusManager, EditBox, FocusHandler, Label, Status as StatusControl } from '@hcengineering/ui'
|
||||||
import { createEventDispatcher } from 'svelte'
|
import { createEventDispatcher } from 'svelte'
|
||||||
import lead from '../plugin'
|
import lead from '../plugin'
|
||||||
|
|
||||||
@ -152,6 +152,7 @@
|
|||||||
label={lead.string.Assignee}
|
label={lead.string.Assignee}
|
||||||
bind:value={assignee}
|
bind:value={assignee}
|
||||||
allowDeselect
|
allowDeselect
|
||||||
|
showNavigate={false}
|
||||||
titleDeselect={lead.string.UnAssign}
|
titleDeselect={lead.string.UnAssign}
|
||||||
/>
|
/>
|
||||||
{#if !preserveCustomer}
|
{#if !preserveCustomer}
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
"CreateVacancy": "Create Vacancy",
|
"CreateVacancy": "Create Vacancy",
|
||||||
"Vacancy": "Vacancy",
|
"Vacancy": "Vacancy",
|
||||||
"VacancyCreateLabel": "Vacancy",
|
"VacancyCreateLabel": "Vacancy",
|
||||||
|
"CompanyCreateLabel": "Company",
|
||||||
"VacancyPlaceholder": "Software Engineer",
|
"VacancyPlaceholder": "Software Engineer",
|
||||||
"CreateAnApplication": "New Application",
|
"CreateAnApplication": "New Application",
|
||||||
"NoApplicationsForTalent": "There are no applications for this talent.",
|
"NoApplicationsForTalent": "There are no applications for this talent.",
|
||||||
@ -103,7 +104,10 @@
|
|||||||
"PerformMatch": "Match",
|
"PerformMatch": "Match",
|
||||||
"MoveApplication": "Move to another vacancy",
|
"MoveApplication": "Move to another vacancy",
|
||||||
"SearchVacancy": "Search vacancy...",
|
"SearchVacancy": "Search vacancy...",
|
||||||
"Organizations": "Companies"
|
"Organizations": "Companies",
|
||||||
|
|
||||||
|
"TemplateReplace": "You you replace selected template?",
|
||||||
|
"TemplateReplaceConfirm": "All field changes will be override by template values"
|
||||||
},
|
},
|
||||||
"status": {
|
"status": {
|
||||||
"TalentRequired": "Please select talent",
|
"TalentRequired": "Please select talent",
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
"CreateVacancy": "Создать вакансию",
|
"CreateVacancy": "Создать вакансию",
|
||||||
"Vacancy": "Вакансия",
|
"Vacancy": "Вакансия",
|
||||||
"VacancyCreateLabel": "Вакансию",
|
"VacancyCreateLabel": "Вакансию",
|
||||||
|
"CompanyCreateLabel": "Компания",
|
||||||
"VacancyPlaceholder": "Разработчик",
|
"VacancyPlaceholder": "Разработчик",
|
||||||
"CreateAnApplication": "Новый Кандидат",
|
"CreateAnApplication": "Новый Кандидат",
|
||||||
"NoApplicationsForTalent": "Нет кандидатов для данного таланта.",
|
"NoApplicationsForTalent": "Нет кандидатов для данного таланта.",
|
||||||
@ -105,7 +106,9 @@
|
|||||||
"PerformMatch": "Сопоставить",
|
"PerformMatch": "Сопоставить",
|
||||||
"MoveApplication": "Поменять Вакансию",
|
"MoveApplication": "Поменять Вакансию",
|
||||||
"SearchVacancy": "Найти вакансию...",
|
"SearchVacancy": "Найти вакансию...",
|
||||||
"Organizations": "Компании"
|
"Organizations": "Компании",
|
||||||
|
"TemplateReplace": "Вы хотите заменить выбранный шаблон?",
|
||||||
|
"TemplateReplaceConfirm": "Все внесенные изменения в будут заменены значениями из шаблоном"
|
||||||
},
|
},
|
||||||
"status": {
|
"status": {
|
||||||
"TalentRequired": "Пожалуйста выберите таланта",
|
"TalentRequired": "Пожалуйста выберите таланта",
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
import chunter from '@hcengineering/chunter'
|
import chunter from '@hcengineering/chunter'
|
||||||
import type { Contact, Employee, Person } from '@hcengineering/contact'
|
import type { Contact, Employee, Person } from '@hcengineering/contact'
|
||||||
import contact from '@hcengineering/contact'
|
import contact from '@hcengineering/contact'
|
||||||
import ExpandRightDouble from '@hcengineering/contact-resources/src/components/icons/ExpandRightDouble.svelte'
|
import { ExpandRightDouble } from '@hcengineering/contact-resources'
|
||||||
import {
|
import {
|
||||||
Account,
|
Account,
|
||||||
Class,
|
Class,
|
||||||
@ -36,6 +36,7 @@
|
|||||||
createQuery,
|
createQuery,
|
||||||
EmployeeBox,
|
EmployeeBox,
|
||||||
getClient,
|
getClient,
|
||||||
|
InlineAttributeBar,
|
||||||
SpaceSelect,
|
SpaceSelect,
|
||||||
UserBox
|
UserBox
|
||||||
} from '@hcengineering/presentation'
|
} from '@hcengineering/presentation'
|
||||||
@ -140,6 +141,7 @@
|
|||||||
recruit.mixin.Candidate,
|
recruit.mixin.Candidate,
|
||||||
'applications',
|
'applications',
|
||||||
{
|
{
|
||||||
|
...doc,
|
||||||
state: state._id,
|
state: state._id,
|
||||||
doneState: null,
|
doneState: null,
|
||||||
number: (incResult as any).object.sequence,
|
number: (incResult as any).object.sequence,
|
||||||
@ -284,6 +286,8 @@
|
|||||||
let btn: HTMLButtonElement
|
let btn: HTMLButtonElement
|
||||||
|
|
||||||
let descriptionBox: AttachmentStyledBox
|
let descriptionBox: AttachmentStyledBox
|
||||||
|
|
||||||
|
const assignAttr = getClient().getHierarchy().getAttribute(recruit.class.Applicant, 'assignee')
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<FocusHandler {manager} />
|
<FocusHandler {manager} />
|
||||||
@ -378,10 +382,11 @@
|
|||||||
{#key doc}
|
{#key doc}
|
||||||
<EmployeeBox
|
<EmployeeBox
|
||||||
focusIndex={2}
|
focusIndex={2}
|
||||||
label={recruit.string.AssignRecruiter}
|
label={assignAttr.label}
|
||||||
placeholder={recruit.string.Recruiters}
|
placeholder={assignAttr.label}
|
||||||
bind:value={doc.assignee}
|
bind:value={doc.assignee}
|
||||||
allowDeselect
|
allowDeselect
|
||||||
|
showNavigate={false}
|
||||||
titleDeselect={recruit.string.UnAssignRecruiter}
|
titleDeselect={recruit.string.UnAssignRecruiter}
|
||||||
/>
|
/>
|
||||||
{#if states.length > 0}
|
{#if states.length > 0}
|
||||||
@ -416,6 +421,16 @@
|
|||||||
</div>
|
</div>
|
||||||
</Button>
|
</Button>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
{#if vacancy}
|
||||||
|
<InlineAttributeBar
|
||||||
|
_class={recruit.class.Applicant}
|
||||||
|
object={doc}
|
||||||
|
toClass={task.class.Task}
|
||||||
|
ignoreKeys={['assignee']}
|
||||||
|
extraProps={{ showNavigate: false }}
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
{/key}
|
{/key}
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
</Card>
|
</Card>
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
EditableAvatar,
|
EditableAvatar,
|
||||||
getClient,
|
getClient,
|
||||||
getUserDraft,
|
getUserDraft,
|
||||||
|
InlineAttributeBar,
|
||||||
KeyedAttribute,
|
KeyedAttribute,
|
||||||
MessageBox,
|
MessageBox,
|
||||||
PDFViewer,
|
PDFViewer,
|
||||||
@ -257,9 +258,22 @@
|
|||||||
remote: object.remote
|
remote: object.remote
|
||||||
}
|
}
|
||||||
|
|
||||||
const id = await client.createDoc(contact.class.Person, contact.space.Contacts, candidate, candidateId)
|
// Store all extra values.
|
||||||
await client.createMixin(
|
for (const [k, v] of Object.entries(object)) {
|
||||||
id as Ref<Person>,
|
if (v != null && k !== 'createOn' && k !== 'avatar') {
|
||||||
|
if (client.getHierarchy().getAttribute(recruit.mixin.Candidate, k).attributeOf === recruit.mixin.Candidate) {
|
||||||
|
;(candidateData as any)[k] = v
|
||||||
|
} else {
|
||||||
|
;(candidate as any)[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const applyOps = client.apply(candidateId)
|
||||||
|
|
||||||
|
await applyOps.createDoc(contact.class.Person, contact.space.Contacts, candidate, candidateId)
|
||||||
|
await applyOps.createMixin(
|
||||||
|
candidateId as Ref<Person>,
|
||||||
contact.class.Person,
|
contact.class.Person,
|
||||||
contact.space.Contacts,
|
contact.space.Contacts,
|
||||||
recruit.mixin.Candidate,
|
recruit.mixin.Candidate,
|
||||||
@ -267,10 +281,10 @@
|
|||||||
)
|
)
|
||||||
|
|
||||||
if (resume.uuid !== undefined) {
|
if (resume.uuid !== undefined) {
|
||||||
client.addCollection(
|
applyOps.addCollection(
|
||||||
attachment.class.Attachment,
|
attachment.class.Attachment,
|
||||||
contact.space.Contacts,
|
contact.space.Contacts,
|
||||||
id,
|
candidateId,
|
||||||
contact.class.Person,
|
contact.class.Person,
|
||||||
'attachments',
|
'attachments',
|
||||||
{
|
{
|
||||||
@ -283,7 +297,7 @@
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
for (const channel of channels) {
|
for (const channel of channels) {
|
||||||
await client.addCollection(
|
await applyOps.addCollection(
|
||||||
contact.class.Channel,
|
contact.class.Channel,
|
||||||
contact.space.Contacts,
|
contact.space.Contacts,
|
||||||
candidateId,
|
candidateId,
|
||||||
@ -312,7 +326,7 @@
|
|||||||
category: findTagCategory(skill.title, categories)
|
category: findTagCategory(skill.title, categories)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
await client.addCollection(skill._class, skill.space, candidateId, recruit.mixin.Candidate, 'skills', {
|
await applyOps.addCollection(skill._class, skill.space, candidateId, recruit.mixin.Candidate, 'skills', {
|
||||||
title: skill.title,
|
title: skill.title,
|
||||||
color: skill.color,
|
color: skill.color,
|
||||||
tag: skill.tag,
|
tag: skill.tag,
|
||||||
@ -320,8 +334,10 @@
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await applyOps.commit()
|
||||||
|
|
||||||
if (!createMore) {
|
if (!createMore) {
|
||||||
dispatch('close', id)
|
dispatch('close', candidateId)
|
||||||
}
|
}
|
||||||
resetObject()
|
resetObject()
|
||||||
saveDraft()
|
saveDraft()
|
||||||
@ -706,6 +722,15 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
<div class="flex flex-grow flex-wrap">
|
||||||
|
<InlineAttributeBar
|
||||||
|
_class={recruit.mixin.Candidate}
|
||||||
|
{object}
|
||||||
|
toClass={contact.class.Contact}
|
||||||
|
ignoreKeys={['onsite', 'remote']}
|
||||||
|
extraProps={{ showNavigate: false }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
|
|
||||||
<svelte:fragment slot="footer">
|
<svelte:fragment slot="footer">
|
||||||
|
@ -0,0 +1,34 @@
|
|||||||
|
<!--
|
||||||
|
// 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 contact, { Organization } from '@hcengineering/contact'
|
||||||
|
import { CreateOrganization } from '@hcengineering/contact-resources'
|
||||||
|
import { Ref, TxOperations } from '@hcengineering/core'
|
||||||
|
import recruit from '../plugin'
|
||||||
|
|
||||||
|
let createOrg: CreateOrganization
|
||||||
|
|
||||||
|
export function canClose (): boolean {
|
||||||
|
return createOrg.canClose()
|
||||||
|
}
|
||||||
|
|
||||||
|
async function onCreate (org: Ref<Organization>, client: TxOperations): Promise<void> {
|
||||||
|
await client.createMixin(org, contact.class.Organization, contact.space.Contacts, recruit.mixin.VacancyList, {
|
||||||
|
vacancies: 0
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<CreateOrganization bind:this={createOrg} {onCreate} on:close />
|
@ -15,8 +15,8 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { AttachmentStyledBox } from '@hcengineering/attachment-resources'
|
import { AttachmentStyledBox } from '@hcengineering/attachment-resources'
|
||||||
import contact, { Organization } from '@hcengineering/contact'
|
import contact, { Organization } from '@hcengineering/contact'
|
||||||
import core, { FindResult, generateId, getCurrentAccount, Ref, SortingOrder } from '@hcengineering/core'
|
import core, { Data, FindResult, generateId, getCurrentAccount, Ref, SortingOrder } from '@hcengineering/core'
|
||||||
import { Card, createQuery, getClient, UserBox } from '@hcengineering/presentation'
|
import { Card, createQuery, getClient, InlineAttributeBar, MessageBox, UserBox } from '@hcengineering/presentation'
|
||||||
import { Vacancy as VacancyClass } from '@hcengineering/recruit'
|
import { Vacancy as VacancyClass } from '@hcengineering/recruit'
|
||||||
import tags from '@hcengineering/tags'
|
import tags from '@hcengineering/tags'
|
||||||
import task, { createKanban, KanbanTemplate } from '@hcengineering/task'
|
import task, { createKanban, KanbanTemplate } from '@hcengineering/task'
|
||||||
@ -28,7 +28,15 @@
|
|||||||
IssueTemplateData,
|
IssueTemplateData,
|
||||||
Project
|
Project
|
||||||
} from '@hcengineering/tracker'
|
} from '@hcengineering/tracker'
|
||||||
import { Button, Component, createFocusManager, EditBox, FocusHandler, IconAttachment } from '@hcengineering/ui'
|
import {
|
||||||
|
Button,
|
||||||
|
Component,
|
||||||
|
createFocusManager,
|
||||||
|
EditBox,
|
||||||
|
FocusHandler,
|
||||||
|
IconAttachment,
|
||||||
|
showPopup
|
||||||
|
} from '@hcengineering/ui'
|
||||||
import { createEventDispatcher } from 'svelte'
|
import { createEventDispatcher } from 'svelte'
|
||||||
import recruit from '../plugin'
|
import recruit from '../plugin'
|
||||||
import Company from './icons/Company.svelte'
|
import Company from './icons/Company.svelte'
|
||||||
@ -42,11 +50,25 @@
|
|||||||
let objectId: Ref<VacancyClass> = generateId()
|
let objectId: Ref<VacancyClass> = generateId()
|
||||||
let issueTemplates: FindResult<IssueTemplate>
|
let issueTemplates: FindResult<IssueTemplate>
|
||||||
|
|
||||||
let fullDescription: string = template?.description ?? ''
|
let fullDescription: string = ''
|
||||||
|
|
||||||
export let company: Ref<Organization> | undefined
|
export let company: Ref<Organization> | undefined
|
||||||
export let preserveCompany: boolean = false
|
export let preserveCompany: boolean = false
|
||||||
|
|
||||||
|
let vacancyData: Data<VacancyClass> = {
|
||||||
|
archived: false,
|
||||||
|
description: '',
|
||||||
|
members: [],
|
||||||
|
name: '',
|
||||||
|
number: 0,
|
||||||
|
private: false,
|
||||||
|
attachments: 0,
|
||||||
|
comments: 0,
|
||||||
|
company: '' as Ref<Organization>,
|
||||||
|
fullDescription: '',
|
||||||
|
location: ''
|
||||||
|
}
|
||||||
|
|
||||||
export function canClose (): boolean {
|
export function canClose (): boolean {
|
||||||
return name === '' && templateId !== undefined
|
return name === '' && templateId !== undefined
|
||||||
}
|
}
|
||||||
@ -56,11 +78,9 @@
|
|||||||
const client = getClient()
|
const client = getClient()
|
||||||
const templateQ = createQuery()
|
const templateQ = createQuery()
|
||||||
$: templateQ.query(task.class.KanbanTemplate, { _id: templateId }, (result) => {
|
$: templateQ.query(task.class.KanbanTemplate, { _id: templateId }, (result) => {
|
||||||
template = result[0]
|
const { _class, _id, description, ...templateData } = result[0]
|
||||||
if (!changed || descriptionBox?.isEmptyContent()) {
|
vacancyData = { ...(templateData as unknown as Data<VacancyClass>), fullDescription: description }
|
||||||
changed = false
|
fullDescription = description ?? ''
|
||||||
fullDescription = template?.description ?? fullDescription
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const issueTemplatesQ = createQuery()
|
const issueTemplatesQ = createQuery()
|
||||||
@ -142,7 +162,7 @@
|
|||||||
recruit.class.Vacancy,
|
recruit.class.Vacancy,
|
||||||
core.space.Space,
|
core.space.Space,
|
||||||
{
|
{
|
||||||
...template,
|
...vacancyData,
|
||||||
name,
|
name,
|
||||||
description: template?.shortDescription ?? '',
|
description: template?.shortDescription ?? '',
|
||||||
fullDescription,
|
fullDescription,
|
||||||
@ -174,6 +194,27 @@
|
|||||||
const manager = createFocusManager()
|
const manager = createFocusManager()
|
||||||
|
|
||||||
let descriptionBox: AttachmentStyledBox
|
let descriptionBox: AttachmentStyledBox
|
||||||
|
|
||||||
|
function handleTemplateChange (evt: CustomEvent<Ref<KanbanTemplate>>): void {
|
||||||
|
if (templateId == null) {
|
||||||
|
templateId = evt.detail
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Template is already specified, ask to replace.
|
||||||
|
showPopup(
|
||||||
|
MessageBox,
|
||||||
|
{
|
||||||
|
label: recruit.string.TemplateReplace,
|
||||||
|
message: recruit.string.TemplateReplaceConfirm
|
||||||
|
},
|
||||||
|
'top',
|
||||||
|
(result?: boolean) => {
|
||||||
|
if (result === true) {
|
||||||
|
templateId = evt.detail ?? undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<FocusHandler {manager} />
|
<FocusHandler {manager} />
|
||||||
@ -199,7 +240,7 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{#key template?.description}
|
{#key vacancyData?.fullDescription}
|
||||||
<AttachmentStyledBox
|
<AttachmentStyledBox
|
||||||
bind:this={descriptionBox}
|
bind:this={descriptionBox}
|
||||||
{objectId}
|
{objectId}
|
||||||
@ -241,9 +282,17 @@
|
|||||||
template: templateId,
|
template: templateId,
|
||||||
focusIndex: 4
|
focusIndex: 4
|
||||||
}}
|
}}
|
||||||
on:change={(evt) => {
|
on:change={handleTemplateChange}
|
||||||
templateId = evt.detail
|
/>
|
||||||
}}
|
</svelte:fragment>
|
||||||
|
|
||||||
|
<svelte:fragment slot="pool">
|
||||||
|
<InlineAttributeBar
|
||||||
|
_class={recruit.class.Vacancy}
|
||||||
|
object={vacancyData}
|
||||||
|
toClass={core.class.Space}
|
||||||
|
ignoreKeys={['fullDescription', 'company']}
|
||||||
|
extraProps={{ showNavigate: false }}
|
||||||
/>
|
/>
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
<svelte:fragment slot="footer">
|
<svelte:fragment slot="footer">
|
||||||
|
@ -32,13 +32,13 @@
|
|||||||
FilterBar,
|
FilterBar,
|
||||||
FilterButton,
|
FilterButton,
|
||||||
getViewOptions,
|
getViewOptions,
|
||||||
viewOptionStore,
|
|
||||||
setActiveViewletId,
|
setActiveViewletId,
|
||||||
TableBrowser,
|
TableBrowser,
|
||||||
ViewletSettingButton
|
ViewletSettingButton,
|
||||||
|
viewOptionStore
|
||||||
} from '@hcengineering/view-resources'
|
} from '@hcengineering/view-resources'
|
||||||
import recruit from '../plugin'
|
import recruit from '../plugin'
|
||||||
import CreateVacancy from './CreateVacancy.svelte'
|
import CreateOrganization from './CreateOrganization.svelte'
|
||||||
import VacancyListApplicationsPopup from './organizations/VacancyListApplicationsPopup.svelte'
|
import VacancyListApplicationsPopup from './organizations/VacancyListApplicationsPopup.svelte'
|
||||||
import VacancyListCountPresenter from './organizations/VacancyListCountPresenter.svelte'
|
import VacancyListCountPresenter from './organizations/VacancyListCountPresenter.svelte'
|
||||||
import VacancyPopup from './organizations/VacancyPopup.svelte'
|
import VacancyPopup from './organizations/VacancyPopup.svelte'
|
||||||
@ -123,7 +123,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function showCreateDialog () {
|
function showCreateDialog () {
|
||||||
showPopup(CreateVacancy, { space: recruit.space.CandidatesPublic }, 'top')
|
showPopup(CreateOrganization, { space: recruit.space.CandidatesPublic }, 'top')
|
||||||
}
|
}
|
||||||
const applicationSorting = (a: Doc, b: Doc) =>
|
const applicationSorting = (a: Doc, b: Doc) =>
|
||||||
(applications?.get(b._id as Ref<Organization>)?.count ?? 0) -
|
(applications?.get(b._id as Ref<Organization>)?.count ?? 0) -
|
||||||
@ -252,7 +252,7 @@
|
|||||||
<div class="ac-header-full" class:secondRow={twoRows}>
|
<div class="ac-header-full" class:secondRow={twoRows}>
|
||||||
<Button
|
<Button
|
||||||
icon={IconAdd}
|
icon={IconAdd}
|
||||||
label={recruit.string.VacancyCreateLabel}
|
label={recruit.string.CompanyCreateLabel}
|
||||||
size={'small'}
|
size={'small'}
|
||||||
kind={'primary'}
|
kind={'primary'}
|
||||||
on:click={showCreateDialog}
|
on:click={showCreateDialog}
|
||||||
@ -277,8 +277,7 @@
|
|||||||
config={createConfig(descr, preference)}
|
config={createConfig(descr, preference)}
|
||||||
options={descr.options}
|
options={descr.options}
|
||||||
query={{
|
query={{
|
||||||
...resultQuery,
|
...resultQuery
|
||||||
_id: { $in: Array.from(vacancies.keys()) }
|
|
||||||
}}
|
}}
|
||||||
showNotification
|
showNotification
|
||||||
/>
|
/>
|
||||||
|
@ -44,6 +44,7 @@ export default mergeIds(recruitId, recruit, {
|
|||||||
ApplicationCreateLabel: '' as IntlString,
|
ApplicationCreateLabel: '' as IntlString,
|
||||||
Vacancy: '' as IntlString,
|
Vacancy: '' as IntlString,
|
||||||
VacancyCreateLabel: '' as IntlString,
|
VacancyCreateLabel: '' as IntlString,
|
||||||
|
CompanyCreateLabel: '' as IntlString,
|
||||||
SelectVacancy: '' as IntlString,
|
SelectVacancy: '' as IntlString,
|
||||||
Talent: '' as IntlString,
|
Talent: '' as IntlString,
|
||||||
TalentCreateLabel: '' as IntlString,
|
TalentCreateLabel: '' as IntlString,
|
||||||
@ -118,7 +119,10 @@ export default mergeIds(recruitId, recruit, {
|
|||||||
Match: '' as IntlString,
|
Match: '' as IntlString,
|
||||||
PerformMatch: '' as IntlString,
|
PerformMatch: '' as IntlString,
|
||||||
MoveApplication: '' as IntlString,
|
MoveApplication: '' as IntlString,
|
||||||
Application: '' as IntlString
|
Application: '' as IntlString,
|
||||||
|
|
||||||
|
TemplateReplace: '' as IntlString,
|
||||||
|
TemplateReplaceConfirm: '' as IntlString
|
||||||
},
|
},
|
||||||
space: {
|
space: {
|
||||||
CandidatesPublic: '' as Ref<Space>
|
CandidatesPublic: '' as Ref<Space>
|
||||||
|
@ -266,13 +266,13 @@
|
|||||||
"AddedAsBlocked": "Marked as blocked",
|
"AddedAsBlocked": "Marked as blocked",
|
||||||
"AddedAsBlocking": "Marked as blocking",
|
"AddedAsBlocking": "Marked as blocking",
|
||||||
|
|
||||||
"IssueTemplate": "Pattern",
|
"IssueTemplate": "Template",
|
||||||
"IssueTemplates": "Patterns",
|
"IssueTemplates": "Templates",
|
||||||
"NewProcess": "New Pattern",
|
"NewProcess": "New Template",
|
||||||
"SaveProcess": "Save Pattern",
|
"SaveProcess": "Save Template",
|
||||||
"NoIssueTemplate": "No Pattern",
|
"NoIssueTemplate": "No Template",
|
||||||
"TemplateReplace": "You you replace applied pattern?",
|
"TemplateReplace": "You you replace selected template?",
|
||||||
"TemplateReplaceConfirm": "All changes to task values will be override by template.",
|
"TemplateReplaceConfirm": "All field changes will be override by template values",
|
||||||
|
|
||||||
"CurrentWorkDay": "Current Working Day",
|
"CurrentWorkDay": "Current Working Day",
|
||||||
"PreviousWorkDay": "Previous Working Day",
|
"PreviousWorkDay": "Previous Working Day",
|
||||||
|
@ -272,7 +272,7 @@
|
|||||||
"SaveProcess": "Сохранить шаблон",
|
"SaveProcess": "Сохранить шаблон",
|
||||||
"NoIssueTemplate": "Шаблон не задан",
|
"NoIssueTemplate": "Шаблон не задан",
|
||||||
"TemplateReplace": "Вы хотите заменить выбранный шаблон?",
|
"TemplateReplace": "Вы хотите заменить выбранный шаблон?",
|
||||||
"TemplateReplaceConfirm": "Все внесенные изменения в задачу будут заменены шаблоном",
|
"TemplateReplaceConfirm": "Все внесенные изменения в будут заменены значениями из шаблоном",
|
||||||
|
|
||||||
"CurrentWorkDay": "Текущий Рабочий День",
|
"CurrentWorkDay": "Текущий Рабочий День",
|
||||||
"PreviousWorkDay": "Предыдущий Рабочий День",
|
"PreviousWorkDay": "Предыдущий Рабочий День",
|
||||||
|
@ -151,7 +151,9 @@
|
|||||||
kind={'large-style'}
|
kind={'large-style'}
|
||||||
focus
|
focus
|
||||||
on:input={() => {
|
on:input={() => {
|
||||||
|
if (isNew) {
|
||||||
identifier = name.toLocaleUpperCase().replaceAll(' ', '_').substring(0, 5)
|
identifier = name.toLocaleUpperCase().replaceAll(' ', '_').substring(0, 5)
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<EditBox
|
<EditBox
|
||||||
@ -221,6 +223,7 @@
|
|||||||
kind="link-bordered"
|
kind="link-bordered"
|
||||||
bind:value={defaultAssignee}
|
bind:value={defaultAssignee}
|
||||||
titleDeselect={tracker.string.Unassigned}
|
titleDeselect={tracker.string.Unassigned}
|
||||||
|
showNavigate={false}
|
||||||
showTooltip={{ label: tracker.string.DefaultAssignee }}
|
showTooltip={{ label: tracker.string.DefaultAssignee }}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -14,18 +14,19 @@
|
|||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { TypeDate } from '@hcengineering/core'
|
import { TypeDate } from '@hcengineering/core'
|
||||||
// import { IntlString } from '@hcengineering/platform'
|
import { IntlString } from '@hcengineering/platform'
|
||||||
import { DateRangePresenter } from '@hcengineering/ui'
|
import { DateRangePresenter } from '@hcengineering/ui'
|
||||||
|
|
||||||
export let value: number | null | undefined
|
export let value: number | null | undefined
|
||||||
export let type: TypeDate | undefined
|
export let type: TypeDate | undefined
|
||||||
// export let label: IntlString
|
export let label: IntlString | undefined = undefined
|
||||||
export let onChange: (value: any) => void
|
export let onChange: (value: any) => void
|
||||||
export let kind: 'no-border' | 'link' = 'no-border'
|
export let kind: 'no-border' | 'link' = 'no-border'
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<DateRangePresenter
|
<DateRangePresenter
|
||||||
{value}
|
{value}
|
||||||
|
labelNull={label}
|
||||||
mode={type?.mode}
|
mode={type?.mode}
|
||||||
noShift={!type?.withShift}
|
noShift={!type?.withShift}
|
||||||
editable
|
editable
|
||||||
|
@ -49,6 +49,8 @@ import { writable } from 'svelte/store'
|
|||||||
import plugin from './plugin'
|
import plugin from './plugin'
|
||||||
import { noCategory } from './viewOptions'
|
import { noCategory } from './viewOptions'
|
||||||
|
|
||||||
|
export { getFiltredKeys, isCollectionAttr } from '@hcengineering/presentation'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define some properties to be used to show component until data is properly loaded.
|
* Define some properties to be used to show component until data is properly loaded.
|
||||||
*/
|
*/
|
||||||
@ -442,26 +444,6 @@ export function getCollectionCounter (hierarchy: Hierarchy, object: Doc, key: Ke
|
|||||||
return (object as any)[key.key] ?? 0
|
return (object as any)[key.key] ?? 0
|
||||||
}
|
}
|
||||||
|
|
||||||
function filterKeys (hierarchy: Hierarchy, keys: KeyedAttribute[], ignoreKeys: string[]): KeyedAttribute[] {
|
|
||||||
const docKeys: Set<string> = new Set<string>(hierarchy.getAllAttributes(core.class.AttachedDoc).keys())
|
|
||||||
keys = keys.filter((k) => !docKeys.has(k.key))
|
|
||||||
keys = keys.filter((k) => !ignoreKeys.includes(k.key))
|
|
||||||
return keys
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getFiltredKeys (
|
|
||||||
hierarchy: Hierarchy,
|
|
||||||
objectClass: Ref<Class<Doc>>,
|
|
||||||
ignoreKeys: string[],
|
|
||||||
to?: Ref<Class<Doc>>
|
|
||||||
): KeyedAttribute[] {
|
|
||||||
const keys = [...hierarchy.getAllAttributes(objectClass, to).entries()]
|
|
||||||
.filter(([, value]) => value.hidden !== true)
|
|
||||||
.map(([key, attr]) => ({ key, attr }))
|
|
||||||
|
|
||||||
return filterKeys(hierarchy, keys, ignoreKeys)
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface CategoryKey {
|
export interface CategoryKey {
|
||||||
key: KeyedAttribute
|
key: KeyedAttribute
|
||||||
category: AttributeCategory
|
category: AttributeCategory
|
||||||
@ -505,10 +487,6 @@ export function categorizeFields (
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isCollectionAttr (hierarchy: Hierarchy, key: KeyedAttribute): boolean {
|
|
||||||
return hierarchy.isDerived(key.attr.type._class, core.class.Collection)
|
|
||||||
}
|
|
||||||
|
|
||||||
function makeViewletKey (loc?: Location): string {
|
function makeViewletKey (loc?: Location): string {
|
||||||
loc = loc ?? getCurrentLocation()
|
loc = loc ?? getCurrentLocation()
|
||||||
loc.fragment = undefined
|
loc.fragment = undefined
|
||||||
|
Loading…
Reference in New Issue
Block a user