mirror of
https://github.com/hcengineering/platform.git
synced 2024-11-26 04:23:58 +03:00
Update EditDoc layout (#2402)
Signed-off-by: Alexander Platov <sas_lord@mail.ru>
This commit is contained in:
parent
807a6f82b2
commit
a8a8f80d62
@ -225,7 +225,8 @@ export function createModel (builder: Builder): void {
|
|||||||
)
|
)
|
||||||
|
|
||||||
builder.mixin(contact.class.Member, core.class.Class, view.mixin.ObjectEditor, {
|
builder.mixin(contact.class.Member, core.class.Class, view.mixin.ObjectEditor, {
|
||||||
editor: contact.component.EditMember
|
editor: contact.component.EditMember,
|
||||||
|
pinned: true
|
||||||
})
|
})
|
||||||
|
|
||||||
builder.createDoc(
|
builder.createDoc(
|
||||||
@ -253,15 +254,18 @@ export function createModel (builder: Builder): void {
|
|||||||
)
|
)
|
||||||
|
|
||||||
builder.mixin(contact.class.Person, core.class.Class, view.mixin.ObjectEditor, {
|
builder.mixin(contact.class.Person, core.class.Class, view.mixin.ObjectEditor, {
|
||||||
editor: contact.component.EditPerson
|
editor: contact.component.EditPerson,
|
||||||
|
pinned: true
|
||||||
})
|
})
|
||||||
|
|
||||||
builder.mixin(contact.class.Employee, core.class.Class, view.mixin.ObjectEditor, {
|
builder.mixin(contact.class.Employee, core.class.Class, view.mixin.ObjectEditor, {
|
||||||
editor: contact.component.EditPerson
|
editor: contact.component.EditPerson,
|
||||||
|
pinned: true
|
||||||
})
|
})
|
||||||
|
|
||||||
builder.mixin(contact.class.Organization, core.class.Class, view.mixin.ObjectEditor, {
|
builder.mixin(contact.class.Organization, core.class.Class, view.mixin.ObjectEditor, {
|
||||||
editor: contact.component.EditOrganization
|
editor: contact.component.EditOrganization,
|
||||||
|
pinned: true
|
||||||
})
|
})
|
||||||
|
|
||||||
builder.mixin(contact.class.Organization, core.class.Class, view.mixin.AttributeEditor, {
|
builder.mixin(contact.class.Organization, core.class.Class, view.mixin.AttributeEditor, {
|
||||||
|
@ -136,6 +136,7 @@ export class TAttributePresenter extends TClass implements AttributePresenter {
|
|||||||
@Mixin(view.mixin.ObjectEditor, core.class.Class)
|
@Mixin(view.mixin.ObjectEditor, core.class.Class)
|
||||||
export class TObjectEditor extends TClass implements ObjectEditor {
|
export class TObjectEditor extends TClass implements ObjectEditor {
|
||||||
editor!: AnyComponent
|
editor!: AnyComponent
|
||||||
|
pinned?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
@Mixin(view.mixin.ObjectEditorHeader, core.class.Class)
|
@Mixin(view.mixin.ObjectEditorHeader, core.class.Class)
|
||||||
|
@ -87,7 +87,7 @@
|
|||||||
{#if $$slots.header}
|
{#if $$slots.header}
|
||||||
<div class="header-row between">
|
<div class="header-row between">
|
||||||
{#if $$slots.header}<slot name="header" />{/if}
|
{#if $$slots.header}<slot name="header" />{/if}
|
||||||
<div class="buttons-group xsmall-gap ml-4" style:align-self={'flex-end'}>
|
<div class="buttons-group xsmall-gap ml-4" style:align-self={'flex-start'}>
|
||||||
<slot name="tools" />
|
<slot name="tools" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -95,6 +95,9 @@
|
|||||||
{#if $$slots['custom-attributes'] && isCustomAttr}
|
{#if $$slots['custom-attributes'] && isCustomAttr}
|
||||||
{#if isSub}<div class="header-row"><slot name="custom-attributes" direction="row" /></div>{/if}
|
{#if isSub}<div class="header-row"><slot name="custom-attributes" direction="row" /></div>{/if}
|
||||||
{/if}
|
{/if}
|
||||||
|
{#if $$slots.subheader}
|
||||||
|
<slot name="subheader" />
|
||||||
|
{/if}
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
|
|
||||||
<svelte:fragment slot="aside">
|
<svelte:fragment slot="aside">
|
||||||
|
@ -368,6 +368,7 @@ input.search {
|
|||||||
.step-lr25 + .step-lr25 { margin-left: .25rem; }
|
.step-lr25 + .step-lr25 { margin-left: .25rem; }
|
||||||
.step-lr75 + .step-lr75 { margin-left: .75rem; }
|
.step-lr75 + .step-lr75 { margin-left: .75rem; }
|
||||||
.step-tb75 + .step-tb75 { margin-top: .75rem; }
|
.step-tb75 + .step-tb75 { margin-top: .75rem; }
|
||||||
|
.step-tb-6 + .step-tb-6 { margin-top: 1.5rem; }
|
||||||
|
|
||||||
.ml-0-5 { margin-left: .125rem; }
|
.ml-0-5 { margin-left: .125rem; }
|
||||||
.ml-1 { margin-left: .25rem; }
|
.ml-1 { margin-left: .25rem; }
|
||||||
@ -541,6 +542,7 @@ input.search {
|
|||||||
.max-h-50 { max-height: 12.5rem; }
|
.max-h-50 { max-height: 12.5rem; }
|
||||||
.max-h-60 { max-height: 15rem; }
|
.max-h-60 { max-height: 15rem; }
|
||||||
.max-h-125 { max-height: 31.25rem; }
|
.max-h-125 { max-height: 31.25rem; }
|
||||||
|
.max-h-30vh { max-height: 30vh; }
|
||||||
.clear-mins {
|
.clear-mins {
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
|
@ -161,7 +161,7 @@
|
|||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
padding: .5rem .75rem .75rem;
|
padding: .5rem .75rem .75rem;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-width: 700px;
|
min-width: 320px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.bottom-divider { border-bottom: 1px solid var(--divider-color); }
|
&.bottom-divider { border-bottom: 1px solid var(--divider-color); }
|
||||||
@ -179,7 +179,7 @@
|
|||||||
}
|
}
|
||||||
.popupPanel-body__mobile-content {
|
.popupPanel-body__mobile-content {
|
||||||
padding: .5rem;
|
padding: .5rem;
|
||||||
min-width: 700px;
|
min-width: 320px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__aside {
|
&__aside {
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Class, Doc, DocumentQuery, Ref, Space } from '@hcengineering/core'
|
import { Class, Doc, DocumentQuery, Ref, Space } from '@hcengineering/core'
|
||||||
import { Icon, Label, Spinner } from '@hcengineering/ui'
|
import { Icon, Label, Spinner, resizeObserver, Scroller } from '@hcengineering/ui'
|
||||||
import view from '@hcengineering/view'
|
import view from '@hcengineering/view'
|
||||||
import { Table } from '@hcengineering/view-resources'
|
import { Table } from '@hcengineering/view-resources'
|
||||||
import attachment from '../plugin'
|
import attachment from '../plugin'
|
||||||
@ -34,9 +34,10 @@
|
|||||||
let inputFile: HTMLInputElement
|
let inputFile: HTMLInputElement
|
||||||
let loading = 0
|
let loading = 0
|
||||||
let dragover = false
|
let dragover = false
|
||||||
|
let wSection: number
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="antiSection">
|
<div class="antiSection" use:resizeObserver={(element) => (wSection = element.clientWidth)}>
|
||||||
<div class="antiSection-header">
|
<div class="antiSection-header">
|
||||||
<div class="antiSection-header__icon">
|
<div class="antiSection-header__icon">
|
||||||
<Icon icon={IconAttachment} size={'small'} />
|
<Icon icon={IconAttachment} size={'small'} />
|
||||||
@ -70,6 +71,29 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</AttachmentDroppable>
|
</AttachmentDroppable>
|
||||||
|
{:else if wSection < 640}
|
||||||
|
<Scroller horizontal>
|
||||||
|
<Table
|
||||||
|
_class={attachment.class.Attachment}
|
||||||
|
config={[
|
||||||
|
'',
|
||||||
|
'description',
|
||||||
|
{
|
||||||
|
key: 'pinned',
|
||||||
|
presenter: view.component.BooleanTruePresenter,
|
||||||
|
label: attachment.string.Pinned,
|
||||||
|
sortingKey: 'pinned'
|
||||||
|
},
|
||||||
|
'lastModified'
|
||||||
|
]}
|
||||||
|
options={{ sort: { pinned: -1 } }}
|
||||||
|
query={{ ...query, attachedTo: objectId }}
|
||||||
|
loadingProps={{ length: attachments ?? 0 }}
|
||||||
|
on:content={(evt) => {
|
||||||
|
attachments = evt.detail.length
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Scroller>
|
||||||
{:else}
|
{:else}
|
||||||
<Table
|
<Table
|
||||||
_class={attachment.class.Attachment}
|
_class={attachment.class.Attachment}
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { Ref } from '@hcengineering/core'
|
import type { Ref } from '@hcengineering/core'
|
||||||
import type { Customer } from '@hcengineering/lead'
|
import type { Customer } from '@hcengineering/lead'
|
||||||
import { Button, IconAdd, Label, showPopup } from '@hcengineering/ui'
|
import { Button, IconAdd, Label, showPopup, resizeObserver, Scroller } from '@hcengineering/ui'
|
||||||
import { Table } from '@hcengineering/view-resources'
|
import { Table } from '@hcengineering/view-resources'
|
||||||
import lead from '../plugin'
|
import lead from '../plugin'
|
||||||
import CreateLead from './CreateLead.svelte'
|
import CreateLead from './CreateLead.svelte'
|
||||||
@ -27,9 +27,10 @@
|
|||||||
const createLead = (ev: MouseEvent): void => {
|
const createLead = (ev: MouseEvent): void => {
|
||||||
showPopup(CreateLead, { candidate: objectId, preserveCandidate: true }, ev.target as HTMLElement)
|
showPopup(CreateLead, { candidate: objectId, preserveCandidate: true }, ev.target as HTMLElement)
|
||||||
}
|
}
|
||||||
|
let wSection: number
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="antiSection">
|
<div class="antiSection" use:resizeObserver={(element) => (wSection = element.clientWidth)}>
|
||||||
<div class="antiSection-header">
|
<div class="antiSection-header">
|
||||||
<span class="antiSection-header__title">
|
<span class="antiSection-header__title">
|
||||||
<Label label={lead.string.Leads} />
|
<Label label={lead.string.Leads} />
|
||||||
@ -37,12 +38,23 @@
|
|||||||
<Button icon={IconAdd} kind={'transparent'} shape={'circle'} on:click={createLead} />
|
<Button icon={IconAdd} kind={'transparent'} shape={'circle'} on:click={createLead} />
|
||||||
</div>
|
</div>
|
||||||
{#if leads !== undefined && leads > 0}
|
{#if leads !== undefined && leads > 0}
|
||||||
<Table
|
{#if wSection < 640}
|
||||||
_class={lead.class.Lead}
|
<Scroller horizontal>
|
||||||
config={['', '$lookup.state', '$lookup.doneState']}
|
<Table
|
||||||
query={{ attachedTo: objectId }}
|
_class={lead.class.Lead}
|
||||||
{loadingProps}
|
config={['', '$lookup.state', '$lookup.doneState']}
|
||||||
/>
|
query={{ attachedTo: objectId }}
|
||||||
|
{loadingProps}
|
||||||
|
/>
|
||||||
|
</Scroller>
|
||||||
|
{:else}
|
||||||
|
<Table
|
||||||
|
_class={lead.class.Lead}
|
||||||
|
config={['', '$lookup.state', '$lookup.doneState']}
|
||||||
|
query={{ attachedTo: objectId }}
|
||||||
|
{loadingProps}
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
{:else}
|
{:else}
|
||||||
<div class="antiSection-empty solid flex-col-center mt-3">
|
<div class="antiSection-empty solid flex-col-center mt-3">
|
||||||
<span class="text-sm dark-color">
|
<span class="text-sm dark-color">
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { Doc, Ref } from '@hcengineering/core'
|
import type { Doc, Ref } from '@hcengineering/core'
|
||||||
import { Button, IconAdd, Label, showPopup, Icon } from '@hcengineering/ui'
|
import { Button, IconAdd, Label, showPopup, Icon, Scroller, resizeObserver } from '@hcengineering/ui'
|
||||||
import { BuildModelKey } from '@hcengineering/view'
|
import { BuildModelKey } from '@hcengineering/view'
|
||||||
import { Table } from '@hcengineering/view-resources'
|
import { Table } from '@hcengineering/view-resources'
|
||||||
import recruit from '../plugin'
|
import recruit from '../plugin'
|
||||||
@ -38,9 +38,10 @@
|
|||||||
'$lookup.state',
|
'$lookup.state',
|
||||||
'$lookup.doneState'
|
'$lookup.doneState'
|
||||||
]
|
]
|
||||||
|
let wSection: number
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="antiSection">
|
<div class="antiSection" use:resizeObserver={(element) => (wSection = element.clientWidth)}>
|
||||||
<div class="antiSection-header">
|
<div class="antiSection-header">
|
||||||
<div class="antiSection-header__icon">
|
<div class="antiSection-header__icon">
|
||||||
<Icon icon={IconApplication} size={'small'} />
|
<Icon icon={IconApplication} size={'small'} />
|
||||||
@ -51,12 +52,23 @@
|
|||||||
<Button id="appls.add" icon={IconAdd} kind={'transparent'} shape={'circle'} on:click={createApp} />
|
<Button id="appls.add" icon={IconAdd} kind={'transparent'} shape={'circle'} on:click={createApp} />
|
||||||
</div>
|
</div>
|
||||||
{#if applications > 0}
|
{#if applications > 0}
|
||||||
<Table
|
{#if wSection < 640}
|
||||||
_class={recruit.class.Applicant}
|
<Scroller horizontal>
|
||||||
{config}
|
<Table
|
||||||
query={{ attachedTo: objectId }}
|
_class={recruit.class.Applicant}
|
||||||
loadingProps={{ length: applications }}
|
{config}
|
||||||
/>
|
query={{ attachedTo: objectId }}
|
||||||
|
loadingProps={{ length: applications }}
|
||||||
|
/>
|
||||||
|
</Scroller>
|
||||||
|
{:else}
|
||||||
|
<Table
|
||||||
|
_class={recruit.class.Applicant}
|
||||||
|
{config}
|
||||||
|
query={{ attachedTo: objectId }}
|
||||||
|
loadingProps={{ length: applications }}
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
{:else}
|
{:else}
|
||||||
<div class="antiSection-empty solid flex-col-center mt-3">
|
<div class="antiSection-empty solid flex-col-center mt-3">
|
||||||
<div class="caption-color">
|
<div class="caption-color">
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
import { createEventDispatcher, onMount } from 'svelte'
|
import { createEventDispatcher, onMount } from 'svelte'
|
||||||
import { createQuery } from '@hcengineering/presentation'
|
import { createQuery } from '@hcengineering/presentation'
|
||||||
import type { Candidate, Applicant, Vacancy } from '@hcengineering/recruit'
|
import type { Candidate, Applicant, Vacancy } from '@hcengineering/recruit'
|
||||||
|
import { Scroller } from '@hcengineering/ui'
|
||||||
import CandidateCard from './CandidateCard.svelte'
|
import CandidateCard from './CandidateCard.svelte'
|
||||||
import VacancyCard from './VacancyCard.svelte'
|
import VacancyCard from './VacancyCard.svelte'
|
||||||
import ExpandRightDouble from './icons/ExpandRightDouble.svelte'
|
import ExpandRightDouble from './icons/ExpandRightDouble.svelte'
|
||||||
@ -51,11 +52,13 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if object !== undefined && candidate !== undefined}
|
{#if object !== undefined && candidate !== undefined}
|
||||||
<div class="flex-between">
|
<Scroller horizontal>
|
||||||
<div class="card"><CandidateCard {candidate} on:click /></div>
|
<div class="flex-between min-w-min">
|
||||||
<div class="arrows"><ExpandRightDouble /></div>
|
<div class="card"><CandidateCard {candidate} on:click /></div>
|
||||||
<div class="card"><VacancyCard {vacancy} /></div>
|
<div class="flex-center arrows"><ExpandRightDouble /></div>
|
||||||
</div>
|
<div class="card"><VacancyCard {vacancy} /></div>
|
||||||
|
</div>
|
||||||
|
</Scroller>
|
||||||
<div class="mt-6">
|
<div class="mt-6">
|
||||||
<Reviews objectId={candidate._id} reviews={candidate.reviews ?? 0} label={recruit.string.TalentReviews} />
|
<Reviews objectId={candidate._id} reviews={candidate.reviews ?? 0} label={recruit.string.TalentReviews} />
|
||||||
</div>
|
</div>
|
||||||
@ -63,11 +66,14 @@
|
|||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.card {
|
.card {
|
||||||
|
flex-shrink: 0;
|
||||||
align-self: stretch;
|
align-self: stretch;
|
||||||
width: calc(50% - 3rem);
|
width: calc(50% - 5rem);
|
||||||
|
min-width: max-content;
|
||||||
min-height: 16rem;
|
min-height: 16rem;
|
||||||
}
|
}
|
||||||
.arrows {
|
.arrows {
|
||||||
|
flex-shrink: 0;
|
||||||
width: 4rem;
|
width: 4rem;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -66,7 +66,7 @@
|
|||||||
icon={clazz.icon}
|
icon={clazz.icon}
|
||||||
title={object.name}
|
title={object.name}
|
||||||
subtitle={object.description}
|
subtitle={object.description}
|
||||||
isHeader={false}
|
isHeader={true}
|
||||||
isAside={true}
|
isAside={true}
|
||||||
{object}
|
{object}
|
||||||
on:close={() => {
|
on:close={() => {
|
||||||
@ -88,7 +88,7 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
|
|
||||||
<svelte:fragment slot="header">
|
<svelte:fragment slot="subheader">
|
||||||
<span class="fs-title flex-grow">
|
<span class="fs-title flex-grow">
|
||||||
<EditBox
|
<EditBox
|
||||||
bind:value={object.name}
|
bind:value={object.name}
|
||||||
@ -102,7 +102,7 @@
|
|||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
<svelte:fragment slot="tools">
|
<svelte:fragment slot="utils">
|
||||||
<div class="p-1">
|
<div class="p-1">
|
||||||
<Button icon={IconMoreH} kind={'transparent'} size={'medium'} on:click={showMenu} />
|
<Button icon={IconMoreH} kind={'transparent'} size={'medium'} on:click={showMenu} />
|
||||||
</div>
|
</div>
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
import core from '@hcengineering/core'
|
import core from '@hcengineering/core'
|
||||||
import { IntlString } from '@hcengineering/platform'
|
import { IntlString } from '@hcengineering/platform'
|
||||||
import calendar from '@hcengineering/calendar'
|
import calendar from '@hcengineering/calendar'
|
||||||
import { Button, IconAdd, Label, showPopup } from '@hcengineering/ui'
|
import { Button, IconAdd, Label, showPopup, resizeObserver, Scroller } from '@hcengineering/ui'
|
||||||
import { Table } from '@hcengineering/view-resources'
|
import { Table } from '@hcengineering/view-resources'
|
||||||
import recruit from '../../plugin'
|
import recruit from '../../plugin'
|
||||||
import FileDuo from '../icons/FileDuo.svelte'
|
import FileDuo from '../icons/FileDuo.svelte'
|
||||||
@ -30,9 +30,10 @@
|
|||||||
const createApp = (ev: MouseEvent): void => {
|
const createApp = (ev: MouseEvent): void => {
|
||||||
showPopup(CreateReview, { candidate: objectId, preserveCandidate: true }, ev.target as HTMLElement)
|
showPopup(CreateReview, { candidate: objectId, preserveCandidate: true }, ev.target as HTMLElement)
|
||||||
}
|
}
|
||||||
|
let wSection: number
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="antiSection">
|
<div class="antiSection" use:resizeObserver={(element) => (wSection = element.clientWidth)}>
|
||||||
<div class="antiSection-header">
|
<div class="antiSection-header">
|
||||||
<span class="antiSection-header__title">
|
<span class="antiSection-header__title">
|
||||||
<Label {label} />
|
<Label {label} />
|
||||||
@ -40,27 +41,58 @@
|
|||||||
<Button icon={IconAdd} kind={'transparent'} shape={'circle'} on:click={createApp} />
|
<Button icon={IconAdd} kind={'transparent'} shape={'circle'} on:click={createApp} />
|
||||||
</div>
|
</div>
|
||||||
{#if reviews > 0}
|
{#if reviews > 0}
|
||||||
<Table
|
{#if wSection < 640}
|
||||||
_class={recruit.class.Review}
|
<Scroller horizontal>
|
||||||
config={[
|
<Table
|
||||||
'',
|
_class={recruit.class.Review}
|
||||||
'verdict',
|
config={[
|
||||||
{
|
'',
|
||||||
key: '',
|
'verdict',
|
||||||
presenter: recruit.component.OpinionsPresenter,
|
{
|
||||||
label: recruit.string.Opinions,
|
key: '',
|
||||||
sortingKey: 'opinions'
|
presenter: recruit.component.OpinionsPresenter,
|
||||||
},
|
label: recruit.string.Opinions,
|
||||||
{ key: '', presenter: calendar.component.DateTimePresenter, label: calendar.string.Date, sortingKey: 'date' }
|
sortingKey: 'opinions'
|
||||||
]}
|
},
|
||||||
options={{
|
{
|
||||||
lookup: {
|
key: '',
|
||||||
space: core.class.Space
|
presenter: calendar.component.DateTimePresenter,
|
||||||
}
|
label: calendar.string.Date,
|
||||||
}}
|
sortingKey: 'date'
|
||||||
query={{ attachedTo: objectId }}
|
}
|
||||||
loadingProps={{ length: reviews }}
|
]}
|
||||||
/>
|
options={{
|
||||||
|
lookup: {
|
||||||
|
space: core.class.Space
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
query={{ attachedTo: objectId }}
|
||||||
|
loadingProps={{ length: reviews }}
|
||||||
|
/>
|
||||||
|
</Scroller>
|
||||||
|
{:else}
|
||||||
|
<Table
|
||||||
|
_class={recruit.class.Review}
|
||||||
|
config={[
|
||||||
|
'',
|
||||||
|
'verdict',
|
||||||
|
{
|
||||||
|
key: '',
|
||||||
|
presenter: recruit.component.OpinionsPresenter,
|
||||||
|
label: recruit.string.Opinions,
|
||||||
|
sortingKey: 'opinions'
|
||||||
|
},
|
||||||
|
{ key: '', presenter: calendar.component.DateTimePresenter, label: calendar.string.Date, sortingKey: 'date' }
|
||||||
|
]}
|
||||||
|
options={{
|
||||||
|
lookup: {
|
||||||
|
space: core.class.Space
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
query={{ attachedTo: objectId }}
|
||||||
|
loadingProps={{ length: reviews }}
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
{:else}
|
{:else}
|
||||||
<div class="antiSection-empty solid flex-col-center mt-3">
|
<div class="antiSection-empty solid flex-col-center mt-3">
|
||||||
<div class="caption-color">
|
<div class="caption-color">
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
import type { Ref, Space, Doc, Class } from '@hcengineering/core'
|
import type { Ref, Space, Doc, Class } from '@hcengineering/core'
|
||||||
import type { TodoItem } from '@hcengineering/task'
|
import type { TodoItem } from '@hcengineering/task'
|
||||||
import { createQuery } from '@hcengineering/presentation'
|
import { createQuery } from '@hcengineering/presentation'
|
||||||
import { Button, IconAdd, showPopup, Label } from '@hcengineering/ui'
|
import { Button, IconAdd, showPopup, Label, resizeObserver, Scroller } from '@hcengineering/ui'
|
||||||
import CreateTodo from './CreateTodo.svelte'
|
import CreateTodo from './CreateTodo.svelte'
|
||||||
import { Table } from '@hcengineering/view-resources'
|
import { Table } from '@hcengineering/view-resources'
|
||||||
|
|
||||||
@ -37,9 +37,10 @@
|
|||||||
const createApp = (ev: MouseEvent): void => {
|
const createApp = (ev: MouseEvent): void => {
|
||||||
showPopup(CreateTodo, { objectId, _class, space }, ev.target as HTMLElement)
|
showPopup(CreateTodo, { objectId, _class, space }, ev.target as HTMLElement)
|
||||||
}
|
}
|
||||||
|
let wSection: number
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="antiSection">
|
<div class="antiSection" use:resizeObserver={(element) => (wSection = element.clientWidth)}>
|
||||||
<div class="antiSection-header">
|
<div class="antiSection-header">
|
||||||
<span class="antiSection-header__title">
|
<span class="antiSection-header__title">
|
||||||
<Label label={plugin.string.Todos} />
|
<Label label={plugin.string.Todos} />
|
||||||
@ -47,20 +48,39 @@
|
|||||||
<Button icon={IconAdd} kind={'transparent'} shape={'circle'} on:click={createApp} />
|
<Button icon={IconAdd} kind={'transparent'} shape={'circle'} on:click={createApp} />
|
||||||
</div>
|
</div>
|
||||||
{#if todos.length > 0}
|
{#if todos.length > 0}
|
||||||
<Table
|
{#if wSection < 640}
|
||||||
_class={task.class.TodoItem}
|
<Scroller horizontal>
|
||||||
config={[
|
<Table
|
||||||
{ key: '', label: plugin.string.TodoName },
|
_class={task.class.TodoItem}
|
||||||
'dueTo',
|
config={[
|
||||||
{ key: 'done', presenter: plugin.component.TodoStatePresenter, label: plugin.string.TodoState }
|
{ key: '', label: plugin.string.TodoName },
|
||||||
]}
|
'dueTo',
|
||||||
options={{
|
{ key: 'done', presenter: plugin.component.TodoStatePresenter, label: plugin.string.TodoState }
|
||||||
sort: {
|
]}
|
||||||
rank: 1
|
options={{
|
||||||
}
|
sort: {
|
||||||
}}
|
rank: 1
|
||||||
query={{ attachedTo: objectId }}
|
}
|
||||||
/>
|
}}
|
||||||
|
query={{ attachedTo: objectId }}
|
||||||
|
/>
|
||||||
|
</Scroller>
|
||||||
|
{:else}
|
||||||
|
<Table
|
||||||
|
_class={task.class.TodoItem}
|
||||||
|
config={[
|
||||||
|
{ key: '', label: plugin.string.TodoName },
|
||||||
|
'dueTo',
|
||||||
|
{ key: 'done', presenter: plugin.component.TodoStatePresenter, label: plugin.string.TodoState }
|
||||||
|
]}
|
||||||
|
options={{
|
||||||
|
sort: {
|
||||||
|
rank: 1
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
query={{ attachedTo: objectId }}
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
{:else}
|
{:else}
|
||||||
<div class="antiSection-empty solid flex-col-center mt-3">
|
<div class="antiSection-empty solid flex-col-center mt-3">
|
||||||
<span class="text-sm over-underline" on:click={createApp}>
|
<span class="text-sm over-underline" on:click={createApp}>
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
import ActionContext from './ActionContext.svelte'
|
import ActionContext from './ActionContext.svelte'
|
||||||
import DocAttributeBar from './DocAttributeBar.svelte'
|
import DocAttributeBar from './DocAttributeBar.svelte'
|
||||||
import UpDownNavigator from './UpDownNavigator.svelte'
|
import UpDownNavigator from './UpDownNavigator.svelte'
|
||||||
|
import IconMixin from './icons/Mixin.svelte'
|
||||||
|
|
||||||
export let _id: Ref<Doc>
|
export let _id: Ref<Doc>
|
||||||
export let _class: Ref<Class<Doc>>
|
export let _class: Ref<Class<Doc>>
|
||||||
@ -131,14 +132,19 @@
|
|||||||
fieldEditors = editors.sort((a, b) => AttributeCategoryOrder[a.category] - AttributeCategoryOrder[b.category])
|
fieldEditors = editors.sort((a, b) => AttributeCategoryOrder[a.category] - AttributeCategoryOrder[b.category])
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getEditor (_class: Ref<Class<Doc>>): Promise<AnyComponent> {
|
interface MixinEditor {
|
||||||
|
editor: AnyComponent
|
||||||
|
pinned?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getEditor (_class: Ref<Class<Doc>>): Promise<MixinEditor> {
|
||||||
const clazz = hierarchy.getClass(_class)
|
const clazz = hierarchy.getClass(_class)
|
||||||
const editorMixin = hierarchy.as(clazz, view.mixin.ObjectEditor)
|
const editorMixin = hierarchy.as(clazz, view.mixin.ObjectEditor)
|
||||||
if (editorMixin?.editor == null && clazz.extends != null) return getEditor(clazz.extends)
|
if (editorMixin?.editor == null && clazz.extends != null) return getEditor(clazz.extends)
|
||||||
return editorMixin.editor
|
return { editor: editorMixin.editor, pinned: editorMixin?.pinned }
|
||||||
}
|
}
|
||||||
|
|
||||||
let mainEditor: AnyComponent | undefined
|
let mainEditor: MixinEditor | undefined
|
||||||
$: getEditorOrDefault(realObjectClass, showAllMixins)
|
$: getEditorOrDefault(realObjectClass, showAllMixins)
|
||||||
|
|
||||||
async function getEditorOrDefault (_class: Ref<Class<Doc>>, showAllMixins: boolean): Promise<void> {
|
async function getEditorOrDefault (_class: Ref<Class<Doc>>, showAllMixins: boolean): Promise<void> {
|
||||||
@ -252,7 +258,7 @@
|
|||||||
{icon}
|
{icon}
|
||||||
{title}
|
{title}
|
||||||
{object}
|
{object}
|
||||||
isHeader={false}
|
isHeader={mainEditor?.pinned ?? false}
|
||||||
isAside={true}
|
isAside={true}
|
||||||
bind:panelWidth
|
bind:panelWidth
|
||||||
bind:innerWidth
|
bind:innerWidth
|
||||||
@ -265,7 +271,7 @@
|
|||||||
<UpDownNavigator element={object} />
|
<UpDownNavigator element={object} />
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
|
|
||||||
<svelte:fragment slot="tools">
|
<svelte:fragment slot="utils">
|
||||||
<div class="p-1">
|
<div class="p-1">
|
||||||
<Button icon={IconMoreH} kind={'transparent'} size={'medium'} on:click={showMenu} />
|
<Button icon={IconMoreH} kind={'transparent'} size={'medium'} on:click={showMenu} />
|
||||||
</div>
|
</div>
|
||||||
@ -282,17 +288,7 @@
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<svelte:fragment slot="content">
|
<svelte:fragment slot="content">
|
||||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<IconMixin size={'small'} />
|
||||||
<rect x="2.66602" y="2.66663" width="10.6667" height="4.66667" rx="1" stroke="white" />
|
|
||||||
<path
|
|
||||||
d="M2.66602 11.3334C2.66602 10.3906 2.66602 9.91916 2.95891 9.62627C3.2518 9.33337 3.72321 9.33337 4.66602 9.33337H6.66602V11.3334C6.66602 12.2762 6.66602 12.7476 6.37312 13.0405C6.37312 13.0405 6.37312 13.0405 6.37312 13.0405C6.08023 13.3334 5.60882 13.3334 4.66602 13.3334V13.3334C3.72321 13.3334 3.2518 13.3334 2.95891 13.0405C2.95891 13.0405 2.95891 13.0405 2.95891 13.0405C2.66602 12.7476 2.66602 12.2762 2.66602 11.3334V11.3334Z"
|
|
||||||
stroke="white"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M9.33398 9.33337H11.334C12.2768 9.33337 12.7482 9.33337 13.0411 9.62627C13.334 9.91916 13.334 10.3906 13.334 11.3334V11.3334C13.334 12.2762 13.334 12.7476 13.0411 13.0405C12.7482 13.3334 12.2768 13.3334 11.334 13.3334V13.3334C10.3912 13.3334 9.91977 13.3334 9.62688 13.0405C9.33398 12.7476 9.33398 12.2762 9.33398 11.3334V9.33337Z"
|
|
||||||
stroke="white"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
@ -317,23 +313,45 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
|
|
||||||
{#if mainEditor}
|
<svelte:fragment slot="subheader">
|
||||||
<Component
|
{#if mainEditor && mainEditor.pinned}
|
||||||
is={mainEditor}
|
<div class="flex-col flex-grow step-tb-6">
|
||||||
props={{ object }}
|
<Component
|
||||||
on:open={(ev) => {
|
is={mainEditor.editor}
|
||||||
ignoreKeys = ev.detail.ignoreKeys
|
props={{ object }}
|
||||||
ignoreMixins = new Set(ev.detail.ignoreMixins)
|
on:open={(ev) => {
|
||||||
allowedCollections = ev.detail.allowedCollections ?? []
|
ignoreKeys = ev.detail.ignoreKeys
|
||||||
collectionArrays = ev.detail.collectionArrays ?? []
|
ignoreMixins = new Set(ev.detail.ignoreMixins)
|
||||||
getMixins(parentClass, object, showAllMixins)
|
allowedCollections = ev.detail.allowedCollections ?? []
|
||||||
updateKeys(showAllMixins)
|
collectionArrays = ev.detail.collectionArrays ?? []
|
||||||
}}
|
getMixins(parentClass, object, showAllMixins)
|
||||||
/>
|
updateKeys(showAllMixins)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</svelte:fragment>
|
||||||
|
|
||||||
|
{#if mainEditor && !mainEditor.pinned}
|
||||||
|
<div class="flex-col flex-grow flex-no-shrink step-tb-6">
|
||||||
|
<Component
|
||||||
|
is={mainEditor.editor}
|
||||||
|
props={{ object }}
|
||||||
|
on:open={(ev) => {
|
||||||
|
ignoreKeys = ev.detail.ignoreKeys
|
||||||
|
ignoreMixins = new Set(ev.detail.ignoreMixins)
|
||||||
|
allowedCollections = ev.detail.allowedCollections ?? []
|
||||||
|
collectionArrays = ev.detail.collectionArrays ?? []
|
||||||
|
getMixins(parentClass, object, showAllMixins)
|
||||||
|
updateKeys(showAllMixins)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#each fieldEditors as collection}
|
{#each fieldEditors as collection}
|
||||||
{#if collection.editor}
|
{#if collection.editor}
|
||||||
<div class="mt-6">
|
<div class="step-tb-6">
|
||||||
<Component
|
<Component
|
||||||
is={collection.editor}
|
is={collection.editor}
|
||||||
props={{
|
props={{
|
||||||
|
32
plugins/view-resources/src/components/icons/Mixin.svelte
Normal file
32
plugins/view-resources/src/components/icons/Mixin.svelte
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<!--
|
||||||
|
//
|
||||||
|
// 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">
|
||||||
|
export let size: 'small' | 'medium' | 'large'
|
||||||
|
const fill: string = 'currentColor'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svg class="svg-{size}" {fill} viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path
|
||||||
|
d="M12.3,7.8H3.7c-0.8,0-1.5-0.7-1.5-1.5V3.7c0-0.8,0.7-1.5,1.5-1.5h8.7c0.8,0,1.5,0.7,1.5,1.5v2.7C13.8,7.2,13.2,7.8,12.3,7.8z M3.7,3.2c-0.3,0-0.5,0.2-0.5,0.5v2.7c0,0.3,0.2,0.5,0.5,0.5h8.7c0.3,0,0.5-0.2,0.5-0.5V3.7c0-0.3-0.2-0.5-0.5-0.5H3.7z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M4.7,13.8c-1,0-1.6,0-2.1-0.4s-0.4-1-0.4-2.1s0-1.6,0.4-2.1s1-0.4,2.1-0.4h2.5v2.5c0,1,0,1.6-0.4,2.1S5.7,13.8,4.7,13.8z M4.7,9.8c-0.7,0-1.2,0-1.4,0.1s-0.1,0.6-0.1,1.4s0,1.2,0.1,1.4s0.6,0.1,1.4,0.1s1.2,0,1.4-0.1s0.1-0.6,0.1-1.4V9.8H4.7z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M11.3,13.8c-1,0-1.6,0-2.1-0.4s-0.4-1-0.4-2.1V8.8h2.5c1,0,1.6,0,2.1,0.4s0.4,1,0.4,2.1s0,1.6-0.4,2.1S12.4,13.8,11.3,13.8z M9.8,9.8v1.5c0,0.7,0,1.2,0.1,1.4s0.6,0.1,1.4,0.1s1.2,0,1.4-0.1s0.1-0.6,0.1-1.4s0-1.2-0.1-1.4s-0.6-0.1-1.4-0.1H9.8z"
|
||||||
|
/>
|
||||||
|
</svg>
|
@ -1,21 +1,22 @@
|
|||||||
<!--
|
<!--
|
||||||
// Copyright © 2020, 2021 Anticrm Platform Contributors.
|
//
|
||||||
// Copyright © 2021 Hardcore Engineering Inc.
|
// Copyright © 2022 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.
|
||||||
|
//
|
||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
export let size: 'small' | 'medium' | 'large'
|
export let size: 'small' | 'medium' | 'large'
|
||||||
const fill: string = 'var(--theme-caption-color)'
|
const fill: string = 'currentColor'
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svg class="svg-{size}" {fill} viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
|
<svg class="svg-{size}" {fill} viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
@ -133,6 +133,7 @@ export interface AttributePresenter extends Class<Doc> {
|
|||||||
*/
|
*/
|
||||||
export interface ObjectEditor extends Class<Doc> {
|
export interface ObjectEditor extends Class<Doc> {
|
||||||
editor: AnyComponent
|
editor: AnyComponent
|
||||||
|
pinned?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user