mirror of
https://github.com/hcengineering/platform.git
synced 2024-12-23 03:22:19 +03:00
Selection/Navigation fixes (#1500)
Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
parent
a45fecaf69
commit
0188f2dcc3
@ -26,7 +26,7 @@ import attachment from '@anticrm/model-attachment'
|
||||
import chunter from '@anticrm/model-chunter'
|
||||
import core, { TAccount, TAttachedDoc, TDoc, TSpace } from '@anticrm/model-core'
|
||||
import presentation from '@anticrm/model-presentation'
|
||||
import view from '@anticrm/model-view'
|
||||
import view, { actionTarget } from '@anticrm/model-view'
|
||||
import workbench from '@anticrm/model-workbench'
|
||||
import type { Asset, IntlString } from '@anticrm/platform'
|
||||
import contact from './plugin'
|
||||
@ -265,6 +265,8 @@ export function createModel (builder: Builder): void {
|
||||
label: contact.string.SearchOrganization,
|
||||
query: contact.completion.OrganizationQuery
|
||||
}, contact.completion.OrganizationCategory)
|
||||
|
||||
actionTarget(builder, view.action.Open, contact.class.Contact, { mode: ['browser', 'context'] })
|
||||
}
|
||||
|
||||
export { contactOperation } from './migration'
|
||||
|
@ -457,6 +457,9 @@ export function createModel (builder: Builder): void {
|
||||
actions: [view.action.Delete]
|
||||
})
|
||||
createReviewModel(builder)
|
||||
|
||||
actionTarget(builder, view.action.Open, recruit.class.Vacancy, { mode: ['browser', 'context'] })
|
||||
actionTarget(builder, view.action.Open, recruit.class.Applicant, { mode: ['browser', 'context'] })
|
||||
}
|
||||
|
||||
export { recruitOperation } from './migration'
|
||||
|
@ -17,6 +17,7 @@ import { IntlString, mergeIds } from '@anticrm/platform'
|
||||
import { TagCategory, tagsId } from '@anticrm/tags'
|
||||
import tags from '@anticrm/tags-resources/src/plugin'
|
||||
import type { AnyComponent } from '@anticrm/ui'
|
||||
import { ViewAction } from '@anticrm/model-view'
|
||||
|
||||
export default mergeIds(tagsId, tags, {
|
||||
// Without it, CLI version is failed with some svelte dependency exception.
|
||||
@ -44,5 +45,8 @@ export default mergeIds(tagsId, tags, {
|
||||
},
|
||||
category: {
|
||||
Category: '' as Ref<TagCategory>
|
||||
},
|
||||
actionImpl: {
|
||||
Open: '' as ViewAction
|
||||
}
|
||||
})
|
||||
|
@ -33,12 +33,11 @@ import {
|
||||
import attachment from '@anticrm/model-attachment'
|
||||
import chunter from '@anticrm/model-chunter'
|
||||
import core, { DOMAIN_SPACE, TAttachedDoc, TDoc, TSpace } from '@anticrm/model-core'
|
||||
import workbench from '@anticrm/model-workbench'
|
||||
import { Asset, IntlString } from '@anticrm/platform'
|
||||
import { Document, Issue, IssuePriority, IssueStatus, IssueStatusCategory, Team } from '@anticrm/tracker'
|
||||
import tracker from './plugin'
|
||||
|
||||
import workbench from '@anticrm/model-workbench'
|
||||
|
||||
export { trackerOperation } from './migration'
|
||||
export { default } from './plugin'
|
||||
|
||||
|
@ -37,12 +37,14 @@ import type {
|
||||
TextPresenter,
|
||||
ViewAction,
|
||||
ViewContext,
|
||||
ViewContextType,
|
||||
Viewlet,
|
||||
ViewletDescriptor
|
||||
} from '@anticrm/view'
|
||||
import view from './plugin'
|
||||
|
||||
export { viewOperation } from './migration'
|
||||
export { ViewAction }
|
||||
|
||||
export function createAction (
|
||||
builder: Builder,
|
||||
@ -73,12 +75,22 @@ export function actionTarget (
|
||||
builder: Builder,
|
||||
action: Ref<Action>,
|
||||
target: Ref<Class<Doc>>,
|
||||
context: ViewContext
|
||||
options: {
|
||||
mode: ViewContextType | ViewContextType[]
|
||||
application?: Ref<Doc>
|
||||
group?: string
|
||||
override?: ViewAction
|
||||
}
|
||||
): void {
|
||||
builder.createDoc(view.class.ActionTarget, core.space.Model, {
|
||||
target,
|
||||
action,
|
||||
context
|
||||
context: {
|
||||
mode: options.mode,
|
||||
application: options.application,
|
||||
group: options.group
|
||||
},
|
||||
override: options.override
|
||||
})
|
||||
}
|
||||
|
||||
@ -290,8 +302,14 @@ export function createModel (builder: Builder): void {
|
||||
})
|
||||
actionTarget(builder, view.action.ShowPreview, core.class.Doc, { mode: 'browser' })
|
||||
|
||||
createAction(builder, view.action.Edit, view.string.Edit, view.actionImpl.Edit, { keyBinding: ['Enter'], singleInput: true })
|
||||
actionTarget(builder, view.action.Edit, core.class.Doc, { mode: ['browser', 'context'] })
|
||||
createAction(builder, view.action.Open, view.string.Open, view.actionImpl.Open, {
|
||||
icon: view.icon.Open,
|
||||
keyBinding: ['Enter'],
|
||||
singleInput: true
|
||||
})
|
||||
|
||||
// Should be contributed via individual plugins.
|
||||
// actionTarget(builder, view.action.Open, core.class.Doc, { mode: ['browser', 'context'] })
|
||||
}
|
||||
|
||||
export default view
|
||||
|
@ -37,7 +37,7 @@ export default mergeIds(viewId, view, {
|
||||
ShowActions: '' as Ref<Action>,
|
||||
|
||||
// Edit document
|
||||
Edit: '' as Ref<Action>
|
||||
Open: '' as Ref<Action>
|
||||
},
|
||||
actionImpl: {
|
||||
Delete: '' as ViewAction,
|
||||
@ -56,7 +56,7 @@ export default mergeIds(viewId, view, {
|
||||
ShowPreview: '' as ViewAction,
|
||||
ShowActions: '' as ViewAction,
|
||||
|
||||
Edit: '' as ViewAction
|
||||
Open: '' as ViewAction
|
||||
},
|
||||
component: {
|
||||
StringEditor: '' as AnyComponent,
|
||||
@ -90,6 +90,6 @@ export default mergeIds(viewId, view, {
|
||||
SelectDown: '' as IntlString,
|
||||
ShowPreview: '' as IntlString,
|
||||
ShowActions: '' as IntlString,
|
||||
Edit: '' as IntlString
|
||||
Open: '' as IntlString
|
||||
}
|
||||
})
|
||||
|
@ -186,7 +186,26 @@
|
||||
stateRefs[statePos].scrollIntoView({ behavior: 'auto', block: 'nearest' })
|
||||
}
|
||||
|
||||
export function selectStatePosition (pos: number, direction: 'up' | 'down' | 'left' | 'right'): void {
|
||||
export function select (offset: 1 | -1 | 0, of?: Doc, dir?: 'vertical' | 'horizontal'): void {
|
||||
let pos = (((of !== undefined) ? objects.findIndex(it => it._id === of._id) : selection) ?? -1)
|
||||
if (pos === -1) {
|
||||
for (const st of states) {
|
||||
const stateObjs = getStateObjects(objects, st)
|
||||
if (stateObjs.length > 0) {
|
||||
pos = objects.findIndex(it => it._id === stateObjs[0].it._id)
|
||||
console.log('SELECT', '#1', pos)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pos < 0) {
|
||||
pos = 0
|
||||
}
|
||||
if (pos >= objects.length) {
|
||||
pos = objects.length - 1
|
||||
}
|
||||
|
||||
const obj = objects[pos]
|
||||
if (obj === undefined) {
|
||||
return
|
||||
@ -201,16 +220,13 @@
|
||||
if (statePos === undefined) {
|
||||
return
|
||||
}
|
||||
switch (direction) {
|
||||
case 'up':
|
||||
|
||||
if (offset === -1) {
|
||||
if (dir === undefined || dir === 'vertical') {
|
||||
scrollInto(objState)
|
||||
dispatch('obj-focus', (stateObjs[statePos - 1] ?? stateObjs[0]).it)
|
||||
break
|
||||
case 'down':
|
||||
scrollInto(objState)
|
||||
dispatch('obj-focus', (stateObjs[statePos + 1] ?? stateObjs[stateObjs.length - 1]).it)
|
||||
break
|
||||
case 'left':
|
||||
return
|
||||
} else {
|
||||
while (objState > 0) {
|
||||
objState--
|
||||
const nstateObjs = getStateObjects(objects, states[objState])
|
||||
@ -220,8 +236,14 @@
|
||||
break
|
||||
}
|
||||
}
|
||||
break
|
||||
case 'right':
|
||||
}
|
||||
}
|
||||
if (offset === 1) {
|
||||
if (dir === undefined || dir === 'vertical') {
|
||||
scrollInto(objState)
|
||||
dispatch('obj-focus', (stateObjs[statePos + 1] ?? stateObjs[stateObjs.length - 1]).it)
|
||||
return
|
||||
} else {
|
||||
while (objState < states.length - 1) {
|
||||
objState++
|
||||
const nstateObjs = getStateObjects(objects, states[objState])
|
||||
@ -231,7 +253,11 @@
|
||||
break
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
if (offset === 0) {
|
||||
scrollInto(objState)
|
||||
dispatch('obj-focus', obj)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,7 +76,6 @@
|
||||
placeholder={attribute?.label}
|
||||
{maxWidth}
|
||||
value={getAttribute(client, object, { key: attributeKey, attr: attribute })}
|
||||
attributeType={attribute.type}
|
||||
space={object.space}
|
||||
{onChange}
|
||||
{focus}
|
||||
@ -95,7 +94,6 @@
|
||||
placeholder={attribute?.label}
|
||||
{maxWidth}
|
||||
value={getAttribute(client, object, { key: attributeKey, attr: attribute })}
|
||||
attributeType={attribute.type}
|
||||
space={object.space}
|
||||
{onChange}
|
||||
{focus}
|
||||
@ -107,7 +105,6 @@
|
||||
this={instance}
|
||||
{maxWidth}
|
||||
value={getAttribute(client, object, { key: attributeKey, attr: attribute })}
|
||||
attributeType={attribute.type}
|
||||
space={object.space}
|
||||
{onChange}
|
||||
{focus}
|
||||
|
@ -33,10 +33,8 @@
|
||||
export let labelProps: any | undefined = undefined
|
||||
export let okAction: () => void
|
||||
export let canSave: boolean = false
|
||||
export let size: 'small'| 'medium' = 'small'
|
||||
export let createMore: boolean | undefined = undefined
|
||||
export let okLabel: IntlString = presentation.string.Create
|
||||
export let cancelLabel: IntlString = presentation.string.Cancel
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
</script>
|
||||
|
@ -31,7 +31,6 @@
|
||||
export let label: IntlString
|
||||
export let placeholder: IntlString = presentation.string.Search
|
||||
export let value: Ref<Contact> | null | undefined
|
||||
export let show: boolean = false
|
||||
export let allowDeselect = false
|
||||
export let titleDeselect: IntlString | undefined = undefined
|
||||
export let readonly = false
|
||||
|
@ -16,7 +16,7 @@
|
||||
import type { IntlString } from '@anticrm/platform'
|
||||
import { translate } from '@anticrm/platform'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import { Icon, Label, getPlatformColor } from '..'
|
||||
import { getPlatformColor } from '..'
|
||||
|
||||
export let placeholder: IntlString | undefined = undefined
|
||||
export let placeholderParam: any | undefined = undefined
|
||||
|
@ -23,7 +23,7 @@
|
||||
export let ctx: any = undefined
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
let btns: HTMLButtonElement[] = []
|
||||
const btns: HTMLButtonElement[] = []
|
||||
|
||||
const keyDown = (ev: KeyboardEvent, n: number): void => {
|
||||
if (ev.key === 'ArrowDown') {
|
||||
|
@ -16,7 +16,6 @@
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import TimeShiftPresenter from './TimeShiftPresenter.svelte'
|
||||
|
||||
export let value: number
|
||||
export let direction: 'before' | 'after'
|
||||
export let minutes: number[] = [5, 15, 30]
|
||||
export let hours: number[] = [1, 2, 4]
|
||||
|
@ -52,7 +52,7 @@
|
||||
{#if $$slots.cell}
|
||||
<slot name="header" date={day(weekMonday, 0)} days={displayedDaysCount} />
|
||||
{/if}
|
||||
{#each [...Array(displayedHours).keys()] as hourOfDay, row}
|
||||
{#each [...Array(displayedHours).keys()] as hourOfDay}
|
||||
<tr class="antiTable-body__row">
|
||||
<td style="width: 50px;" class="calendar-td">
|
||||
<div class="antiTable-cells__firstCell">
|
||||
@ -63,7 +63,7 @@
|
||||
<td
|
||||
class="antiTable-body__border calendar-td cell"
|
||||
style={`height: ${cellHeight};`}
|
||||
on:click={(evt) => {
|
||||
on:click={() => {
|
||||
onSelect(day(weekMonday, dayIndex))
|
||||
}}
|
||||
>
|
||||
@ -82,15 +82,6 @@
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
.selected {
|
||||
// border-radius: 3px;
|
||||
background-color: var(--primary-button-enabled);
|
||||
// border-color: var(--primary-button-focused-border);
|
||||
color: var(--primary-button-color);
|
||||
border-radius: 0.5rem;
|
||||
height: calc(100% - 5px);
|
||||
width: calc(100% - 5px);
|
||||
}
|
||||
.cell {
|
||||
width: 8rem;
|
||||
overflow: hidden;
|
||||
|
@ -119,7 +119,7 @@ export function fitPopupPositionedElement (modalHTML: HTMLElement, alignment: Po
|
||||
modalHTML.style.left = modalHTML.style.right = modalHTML.style.top = modalHTML.style.bottom = ''
|
||||
modalHTML.style.maxHeight = modalHTML.style.height = ''
|
||||
modalHTML.style.maxWidth = modalHTML.style.width = ''
|
||||
if (alignment.position) {
|
||||
if (alignment.position !== undefined) {
|
||||
if (alignment.position.v === 'top') {
|
||||
modalHTML.style.top = `${rect.top}px`
|
||||
} else if (alignment.position.v === 'bottom') {
|
||||
@ -171,6 +171,7 @@ export function fitPopupElement (modalHTML: HTMLElement, element?: PopupAlignmen
|
||||
modalHTML.style.top = `calc(${rect.top}px + 0.5rem)`
|
||||
modalHTML.style.bottom = '0.75rem'
|
||||
modalHTML.style.right = '0.75rem'
|
||||
modalHTML.style.maxWidth = '50%'
|
||||
show = true
|
||||
} else if (element === 'top') {
|
||||
modalHTML.style.top = '15vh'
|
||||
|
@ -42,7 +42,7 @@ export interface AnySvelteComponentWithProps {
|
||||
export interface Action {
|
||||
label: IntlString
|
||||
icon: Asset | AnySvelteComponent
|
||||
action: (props: any, ev?: Event) => Promise<void>
|
||||
action: (props: any, ev: Event) => Promise<void>
|
||||
}
|
||||
|
||||
export interface IPopupItem {
|
||||
|
@ -127,10 +127,6 @@
|
||||
.ref-input {
|
||||
flex-shrink: 0;
|
||||
padding: 1.5rem 2.5rem;
|
||||
|
||||
&.fill {
|
||||
background-color: var(--body-color);
|
||||
}
|
||||
}
|
||||
.p-activity {
|
||||
padding: 1.5rem 2.5rem 2.5rem;
|
||||
|
@ -19,16 +19,7 @@
|
||||
import core, { AnyAttribute, Doc, getCurrentAccount, Ref } from '@anticrm/core'
|
||||
import { Asset, getResource } from '@anticrm/platform'
|
||||
import { getClient } from '@anticrm/presentation'
|
||||
import {
|
||||
Component,
|
||||
Icon, IconEdit,
|
||||
IconMoreH,
|
||||
Label,
|
||||
Menu,
|
||||
ShowMore,
|
||||
showPopup,
|
||||
TimeSince
|
||||
} from '@anticrm/ui'
|
||||
import { Component, Icon, IconEdit, IconMoreH, Label, Menu, ShowMore, showPopup, TimeSince } from '@anticrm/ui'
|
||||
import type { AttributeModel } from '@anticrm/view'
|
||||
import { getActions } from '@anticrm/view-resources'
|
||||
import { ActivityKey, DisplayTx } from '../activity'
|
||||
@ -60,7 +51,7 @@
|
||||
|
||||
const client = getClient()
|
||||
|
||||
function getProps (props: any, edit: boolean): any {
|
||||
function getProps(props: any, edit: boolean): any {
|
||||
return { ...props, edit }
|
||||
}
|
||||
|
||||
@ -96,7 +87,7 @@
|
||||
...actions.map((a) => ({
|
||||
label: a.label,
|
||||
icon: a.icon,
|
||||
action: async (evt: Event) => {
|
||||
action: async (ctx:any, evt: Event) => {
|
||||
const impl = await getResource(a.action)
|
||||
await impl(tx.doc as Doc, evt)
|
||||
}
|
||||
@ -110,7 +101,7 @@
|
||||
edit = false
|
||||
props = getProps(props, edit)
|
||||
}
|
||||
function isMessageType (attr?: AnyAttribute): boolean {
|
||||
function isMessageType(attr?: AnyAttribute): boolean {
|
||||
return attr?.type._class === core.class.TypeMarkup
|
||||
}
|
||||
|
||||
@ -181,11 +172,11 @@
|
||||
{/if}
|
||||
{#if isMessageType(m.attribute)}
|
||||
<div class="strong message emphasized">
|
||||
<svelte:component this={m.presenter} {value} attributeType={m.attribute?.type} />
|
||||
<svelte:component this={m.presenter} {value} />
|
||||
</div>
|
||||
{:else}
|
||||
<div class="strong">
|
||||
<svelte:component this={m.presenter} {value} attributeType={m.attribute?.type} />
|
||||
<svelte:component this={m.presenter} {value} />
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
@ -206,11 +197,11 @@
|
||||
</span>
|
||||
{#if isMessageType(m.attribute)}
|
||||
<div class="strong message emphasized">
|
||||
<svelte:component this={m.presenter} {value} attributeType={m.attribute?.type} />
|
||||
<svelte:component this={m.presenter} {value} />
|
||||
</div>
|
||||
{:else}
|
||||
<div class="strong">
|
||||
<svelte:component this={m.presenter} {value} attributeType={m.attribute?.type} />
|
||||
<svelte:component this={m.presenter} {value} />
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
@ -223,12 +214,10 @@
|
||||
<TxViewTx {tx} {onCancelEdit} {edit} {viewlet}/>
|
||||
</div>
|
||||
</ShowMore>
|
||||
{:else}
|
||||
{#if typeof viewlet.component === 'string'}
|
||||
<Component is={viewlet.component} {props} on:close={onCancelEdit} />
|
||||
{:else}
|
||||
<svelte:component this={viewlet.component} {...props} on:close={onCancelEdit} />
|
||||
{/if}
|
||||
{:else if typeof viewlet.component === 'string'}
|
||||
<Component is={viewlet.component} {props} on:close={onCancelEdit} />
|
||||
{:else}
|
||||
<svelte:component this={viewlet.component} {...props} on:close={onCancelEdit} />
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
@ -242,14 +231,12 @@
|
||||
<ShowMore ignore={edit}>
|
||||
{#if tx.collectionAttribute !== undefined && (tx.txDocIds?.size ?? 0) > 1}
|
||||
<div class="flex-row-center flex-grow flex-wrap">
|
||||
<TxViewTx {tx} {onCancelEdit} {edit} {viewlet}/>
|
||||
<TxViewTx {tx} {onCancelEdit} {edit} {viewlet} />
|
||||
</div>
|
||||
{:else if typeof viewlet.component === 'string'}
|
||||
<Component is={viewlet.component} {props} on:close={onCancelEdit} />
|
||||
{:else}
|
||||
{#if typeof viewlet.component === 'string'}
|
||||
<Component is={viewlet.component} {props} on:close={onCancelEdit} />
|
||||
{:else}
|
||||
<svelte:component this={viewlet.component} {...props} on:close={onCancelEdit} />
|
||||
{/if}
|
||||
<svelte:component this={viewlet.component} {...props} on:close={onCancelEdit} />
|
||||
{/if}
|
||||
</ShowMore>
|
||||
</div>
|
||||
|
@ -12,8 +12,12 @@
|
||||
function filterTx (dtx: DisplayTx[], _class: Ref<Class<Doc>>): DisplayTx[] {
|
||||
return dtx.filter((it) => it.tx._class === _class)
|
||||
}
|
||||
function getProps (props: any, edit: boolean): any {
|
||||
return { ...props, edit }
|
||||
function getProps (ctx: DisplayTx, edit: boolean): any {
|
||||
if (viewlet?.pseudo) {
|
||||
return { value: ctx.doc }
|
||||
}
|
||||
const dprops = getDTxProps(ctx)
|
||||
return { ...dprops, edit }
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -24,9 +28,9 @@
|
||||
{/if}
|
||||
<div class="mr-2">
|
||||
{#if typeof viewlet?.component === 'string'}
|
||||
<Component is={viewlet?.component} props={getProps(getDTxProps(ctx), edit)} on:close={onCancelEdit} />
|
||||
<Component is={viewlet?.component} props={getProps(ctx, edit)} on:close={onCancelEdit} />
|
||||
{:else}
|
||||
<svelte:component this={viewlet?.component} {...getProps(getDTxProps(ctx), edit)} on:close={onCancelEdit} />
|
||||
<svelte:component this={viewlet?.component} {...getProps(ctx, edit)} on:close={onCancelEdit} />
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
@ -36,9 +40,9 @@
|
||||
{/if}
|
||||
<div class="mr-2">
|
||||
{#if typeof viewlet?.component === 'string'}
|
||||
<Component is={viewlet?.component} props={getProps(getDTxProps(ctx), edit)} on:close={onCancelEdit} />
|
||||
<Component is={viewlet?.component} props={getProps(ctx, edit)} on:close={onCancelEdit} />
|
||||
{:else}
|
||||
<svelte:component this={viewlet?.component} {...getProps(getDTxProps(ctx), edit)} on:close={onCancelEdit} />
|
||||
<svelte:component this={viewlet?.component} {...getProps(ctx, edit)} on:close={onCancelEdit} />
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
|
@ -10,6 +10,7 @@ import activity from '../plugin'
|
||||
export type TxDisplayViewlet =
|
||||
| (Pick<TxViewlet, 'icon' | 'label' | 'display' | 'editable' | 'hideOnRemove' | 'labelComponent' | 'labelParams'> & {
|
||||
component?: AnyComponent | AnySvelteComponent
|
||||
pseudo: boolean
|
||||
})
|
||||
| undefined
|
||||
|
||||
@ -41,13 +42,14 @@ async function createPseudoViewlet (
|
||||
icon: docClass.icon ?? activity.icon.Activity,
|
||||
label: label,
|
||||
labelParams: { _class: trLabel, collection: dtx.collectionAttribute?.label !== undefined ? await translate(dtx.collectionAttribute?.label, {}) : '' },
|
||||
component: presenter.presenter
|
||||
component: presenter.presenter,
|
||||
pseudo: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function getDTxProps (dtx: DisplayTx): any {
|
||||
return { tx: dtx.tx, value: dtx.doc, dtx }
|
||||
return { tx: dtx.tx, value: dtx.doc }
|
||||
}
|
||||
|
||||
function getViewlet (viewlets: Map<ActivityKey, TxViewlet>, dtx: DisplayTx): TxDisplayViewlet | undefined {
|
||||
@ -57,7 +59,10 @@ function getViewlet (viewlets: Map<ActivityKey, TxViewlet>, dtx: DisplayTx): TxD
|
||||
} else {
|
||||
key = activityKey(dtx.tx.objectClass, dtx.tx._class)
|
||||
}
|
||||
return viewlets.get(key)
|
||||
const vl = viewlets.get(key)
|
||||
if (vl !== undefined) {
|
||||
return { ...vl, pseudo: false }
|
||||
}
|
||||
}
|
||||
|
||||
export async function updateViewlet (
|
||||
@ -73,12 +78,14 @@ export async function updateViewlet (
|
||||
}> {
|
||||
let viewlet = getViewlet(viewlets, dtx)
|
||||
|
||||
const props = getDTxProps(dtx)
|
||||
let props = getDTxProps(dtx)
|
||||
let model: AttributeModel[] = []
|
||||
let modelIcon: Asset | undefined
|
||||
|
||||
if (viewlet === undefined) {
|
||||
;({ viewlet, model } = await checkInlineViewlets(dtx, viewlet, client, model))
|
||||
// Only value is necessary for inline viewlets
|
||||
props = { value: dtx.doc }
|
||||
if (model !== undefined) {
|
||||
// Check for State attribute
|
||||
for (const a of model) {
|
||||
|
@ -30,7 +30,6 @@
|
||||
import DatePresenter from './presenters/DatePresenter.svelte'
|
||||
|
||||
export let object: WithLookup<Card>
|
||||
export let dragged: boolean
|
||||
|
||||
let loadingAttachment = 0
|
||||
let dragoverAttachment = false
|
||||
|
@ -21,7 +21,7 @@
|
||||
import type { Kanban, SpaceWithStates, State } from '@anticrm/task'
|
||||
import task, { calcRank } from '@anticrm/task'
|
||||
import { showPopup } from '@anticrm/ui'
|
||||
import { ActionContext, focusStore, ListSelectionProvider, Menu, selectionStore } from '@anticrm/view-resources'
|
||||
import { ActionContext, focusStore, ListSelectionProvider, Menu, SelectDirection, selectionStore } from '@anticrm/view-resources'
|
||||
import { onMount } from 'svelte'
|
||||
import AddCard from './add-card/AddCard.svelte'
|
||||
import KanbanCard from './KanbanCard.svelte'
|
||||
@ -74,21 +74,8 @@
|
||||
|
||||
let kanbanUI: KanbanUI
|
||||
const listProvider = new ListSelectionProvider(
|
||||
(pos, dir) => {
|
||||
if (dir === 'vertical') {
|
||||
// Select next
|
||||
kanbanUI.selectStatePosition(pos, 'down')
|
||||
} else {
|
||||
kanbanUI.selectStatePosition(pos, 'right')
|
||||
}
|
||||
},
|
||||
(pos, dir) => {
|
||||
// Select prev
|
||||
if (dir === 'vertical') {
|
||||
kanbanUI.selectStatePosition(pos, 'up')
|
||||
} else {
|
||||
kanbanUI.selectStatePosition(pos, 'left')
|
||||
}
|
||||
(offset: 1 | -1 | 0, of?: Doc, dir?: SelectDirection) => {
|
||||
kanbanUI.select(offset, of, dir)
|
||||
}
|
||||
)
|
||||
onMount(() => {
|
||||
@ -133,8 +120,8 @@
|
||||
on:contextmenu={(evt) => showMenu(evt.detail.evt, evt.detail.objects)}
|
||||
selection={listProvider.current($focusStore)}
|
||||
>
|
||||
<svelte:fragment slot="card" let:object let:dragged>
|
||||
<KanbanCard object={castObject(object)} {dragged} />
|
||||
<svelte:fragment slot="card" let:object>
|
||||
<KanbanCard object={castObject(object)} />
|
||||
</svelte:fragment>
|
||||
|
||||
<svelte:fragment slot="additionalPanel">
|
||||
|
@ -1,7 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { Card, CardLabel } from '@anticrm/board'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
|
||||
import CardLabelsEditor from './CardLabelsEditor.svelte'
|
||||
import CardLabelsPicker from './CardLabelsPicker.svelte'
|
||||
|
||||
@ -12,15 +10,11 @@
|
||||
object?: CardLabel
|
||||
} = {}
|
||||
let search: string | undefined = undefined
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
function setEditMode (isEdit: boolean, object?: CardLabel) {
|
||||
editMode = { isEdit, object }
|
||||
}
|
||||
|
||||
function close () {
|
||||
dispatch('close')
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if editMode.isEdit}
|
||||
|
@ -25,7 +25,7 @@
|
||||
|
||||
const maxLenght: number = 30
|
||||
const trimFilename = (fname: string): string =>
|
||||
fname.length > maxLenght ? fname.substr(0, (maxLenght - 1) / 2) + '...' + fname.substr(-(maxLenght - 1) / 2) : fname
|
||||
fname.length > maxLenght ? fname.substring(0, (maxLenght - 1) / 2) + '...' + fname.substring(-(maxLenght - 1) / 2) : fname
|
||||
|
||||
function iconLabel (name: string): string {
|
||||
const parts = name.split('.')
|
||||
|
@ -108,7 +108,7 @@
|
||||
...actions.map((a) => ({
|
||||
label: a.label,
|
||||
icon: a.icon,
|
||||
action: async (evt: MouseEvent) => {
|
||||
action: async (ctx:any, evt: MouseEvent) => {
|
||||
const impl = await getResource(a.action)
|
||||
await impl(message, evt)
|
||||
}
|
||||
|
@ -26,7 +26,6 @@
|
||||
import notification from '@anticrm/notification'
|
||||
|
||||
export let object: WithLookup<Lead>
|
||||
export let dragged: boolean
|
||||
|
||||
function showMenu (ev?: Event): void {
|
||||
showPopup(ContextMenu, { object }, (ev as MouseEvent).target as HTMLElement)
|
||||
|
@ -26,7 +26,6 @@
|
||||
export let items: TagReference[] = []
|
||||
export let targetClass: Ref<Class<Doc>>
|
||||
export let key: KeyedAttribute
|
||||
export let elements: Map<Ref<TagElement>, TagElement>
|
||||
export let newElements: TagElement[] = []
|
||||
export let countLabel: IntlString
|
||||
|
||||
|
@ -11,20 +11,20 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Doc, TxOperations } from '@anticrm/core'
|
||||
import { Resources } from '@anticrm/platform'
|
||||
import { TagElement } from '@anticrm/tags'
|
||||
import { eventToHTMLElement, showPopup } from '@anticrm/ui'
|
||||
import TagsCategoryBar from './components/CategoryBar.svelte'
|
||||
import CategoryPresenter from './components/CategoryPresenter.svelte'
|
||||
import EditTagElement from './components/EditTagElement.svelte'
|
||||
import TagElementPresenter from './components/TagElementPresenter.svelte'
|
||||
import TagReferencePresenter from './components/TagReferencePresenter.svelte'
|
||||
import Tags from './components/Tags.svelte'
|
||||
import TagsPresenter from './components/TagsPresenter.svelte'
|
||||
import TagsItemPresenter from './components/TagsItemPresenter.svelte'
|
||||
import TagsView from './components/TagsView.svelte'
|
||||
import TagsEditor from './components/TagsEditor.svelte'
|
||||
import TagsDropdownEditor from './components/TagsDropdownEditor.svelte'
|
||||
import CategoryPresenter from './components/CategoryPresenter.svelte'
|
||||
import tags from './plugin'
|
||||
import TagsCategoryBar from './components/CategoryBar.svelte'
|
||||
import TagsEditor from './components/TagsEditor.svelte'
|
||||
import TagsItemPresenter from './components/TagsItemPresenter.svelte'
|
||||
import TagsPresenter from './components/TagsPresenter.svelte'
|
||||
import TagsView from './components/TagsView.svelte'
|
||||
|
||||
export default async (): Promise<Resources> => ({
|
||||
component: {
|
||||
@ -38,5 +38,10 @@ export default async (): Promise<Resources> => ({
|
||||
TagsItemPresenter,
|
||||
CategoryPresenter,
|
||||
TagsCategoryBar
|
||||
},
|
||||
actionImpl: {
|
||||
Open: (value: TagElement, evt: MouseEvent) => {
|
||||
showPopup(EditTagElement, { value, keyTitle: '' }, eventToHTMLElement(evt))
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -21,7 +21,7 @@
|
||||
import type { Kanban, SpaceWithStates, State, Task } from '@anticrm/task'
|
||||
import task from '@anticrm/task'
|
||||
import { showPopup } from '@anticrm/ui'
|
||||
import { ActionContext, focusStore, ListSelectionProvider, selectionStore } from '@anticrm/view-resources'
|
||||
import { ActionContext, focusStore, ListSelectionProvider, SelectDirection, selectionStore } from '@anticrm/view-resources'
|
||||
import Menu from '@anticrm/view-resources/src/components/Menu.svelte'
|
||||
import { onMount } from 'svelte'
|
||||
import KanbanDragDone from './KanbanDragDone.svelte'
|
||||
@ -66,22 +66,10 @@
|
||||
/* eslint-disable no-undef */
|
||||
|
||||
let kanbanUI: KanbanUI
|
||||
let objects: Doc[] = []
|
||||
const listProvider = new ListSelectionProvider(
|
||||
(pos, dir) => {
|
||||
if (dir === 'vertical') {
|
||||
// Select next
|
||||
kanbanUI.selectStatePosition(pos, 'down')
|
||||
} else {
|
||||
kanbanUI.selectStatePosition(pos, 'right')
|
||||
}
|
||||
},
|
||||
(pos, dir) => {
|
||||
// Select prev
|
||||
if (dir === 'vertical') {
|
||||
kanbanUI.selectStatePosition(pos, 'up')
|
||||
} else {
|
||||
kanbanUI.selectStatePosition(pos, 'left')
|
||||
}
|
||||
(offset: 1 | -1 | 0, of?: Doc, dir?: SelectDirection) => {
|
||||
kanbanUI.select(offset, of, dir)
|
||||
}
|
||||
)
|
||||
onMount(() => {
|
||||
@ -96,7 +84,6 @@
|
||||
// selection = undefined
|
||||
})
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
{#await cardPresenter then presenter}
|
||||
@ -118,6 +105,7 @@
|
||||
rankFieldName={'rank'}
|
||||
on:content={(evt) => {
|
||||
listProvider.update(evt.detail)
|
||||
objects = evt.detail
|
||||
}}
|
||||
on:obj-focus={(evt) => {
|
||||
listProvider.updateFocus(evt.detail)
|
||||
|
@ -19,7 +19,7 @@
|
||||
import { createQuery } from '@anticrm/presentation'
|
||||
import { Issue, Team } from '@anticrm/tracker'
|
||||
import { Button, eventToHTMLElement, Icon, IconAdd, showPopup, Tooltip } from '@anticrm/ui'
|
||||
import { focusStore, ListSelectionProvider, selectionStore } from '@anticrm/view-resources'
|
||||
import { focusStore, ListSelectionProvider, SelectDirection, selectionStore } from '@anticrm/view-resources'
|
||||
import ActionContext from '@anticrm/view-resources/src/components/ActionContext.svelte'
|
||||
import Menu from '@anticrm/view-resources/src/components/Menu.svelte'
|
||||
import { onMount } from 'svelte'
|
||||
@ -70,21 +70,8 @@ import PriorityPresenter from './PriorityPresenter.svelte'
|
||||
|
||||
let kanbanUI: Kanban
|
||||
const listProvider = new ListSelectionProvider(
|
||||
(pos, dir) => {
|
||||
if (dir === 'vertical') {
|
||||
// Select next
|
||||
kanbanUI.selectStatePosition(pos, 'down')
|
||||
} else {
|
||||
kanbanUI.selectStatePosition(pos, 'right')
|
||||
}
|
||||
},
|
||||
(pos, dir) => {
|
||||
// Select prev
|
||||
if (dir === 'vertical') {
|
||||
kanbanUI.selectStatePosition(pos, 'up')
|
||||
} else {
|
||||
kanbanUI.selectStatePosition(pos, 'left')
|
||||
}
|
||||
(offset: 1 | -1 | 0, of?: Doc, dir?: SelectDirection) => {
|
||||
kanbanUI.select(offset, of, dir)
|
||||
}
|
||||
)
|
||||
onMount(() => {
|
||||
|
@ -41,4 +41,9 @@
|
||||
<path d="M13.3,8.3c-0.1,2.8-2.5,5.1-5.4,5.1C5,13.4,2.6,11,2.6,8c0-2.9,2.3-5.2,5.1-5.4c0.1-0.4,0.2-0.7,0.4-1c0,0-0.1,0-0.1,0 C4.4,1.7,1.6,4.5,1.6,8c0,3.5,2.9,6.4,6.4,6.4s6.4-2.9,6.4-6.4c0,0,0-0.1,0-0.1C14,8.1,13.7,8.2,13.3,8.3z"/>
|
||||
<ellipse cx="12.1" cy="3.9" rx="2.5" ry="2.5"/>
|
||||
</symbol>
|
||||
<symbol id='open' viewBox="0 0 16 16">
|
||||
<path d="M14,13.1H9.2c-0.3,0-0.5,0.2-0.5,0.5s0.2,0.5,0.5,0.5H14c0.3,0,0.5-0.2,0.5-0.5S14.3,13.1,14,13.1z"/>
|
||||
<path d="M11.4,7.1C11.4,7.1,11.4,7.1,11.4,7.1c1.2-1.6,1.3-1.6,1.3-1.6C12.9,5,13,4.5,12.9,4c-0.1-0.5-0.4-0.9-0.8-1.2 c0,0-1.1-0.9-1.1-0.9c-0.8-0.7-2.1-0.6-2.8,0.3c0,0,0,0,0,0l-6.3,7.9c-0.3,0.4-0.4,0.9-0.3,1.4l0.5,2.3c0.1,0.2,0.3,0.4,0.5,0.4 c0,0,0,0,0,0l2.4,0c0.5,0,1-0.2,1.3-0.6C8.9,10.2,10.5,8.2,11.4,7.1C11.4,7.1,11.4,7.1,11.4,7.1z M8.9,2.8c0.3-0.4,1-0.5,1.4-0.1 c0,0,1.2,0.9,1.2,0.9c0.2,0.1,0.4,0.3,0.4,0.6c0.1,0.2,0,0.5-0.1,0.7c0,0-0.4,0.5-0.9,1.2L8.1,3.9L8.9,2.8z M5.5,12.9 C5.4,13,5.2,13.1,5,13.1l-2,0l-0.5-1.9c0-0.2,0-0.4,0.1-0.5l4.8-6l2.8,2.2C8.9,8.6,6.8,11.2,5.5,12.9z"/>
|
||||
</symbol>
|
||||
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 4.2 KiB |
@ -12,6 +12,7 @@
|
||||
"Table": "Table",
|
||||
"Role": "Role",
|
||||
"DeleteObject": "Delete object",
|
||||
"DeleteObjectConfirm": "Do you want to delete this {count, plural, =1 {object} other {# objects}}?"
|
||||
"DeleteObjectConfirm": "Do you want to delete this {count, plural, =1 {object} other {# objects}}?",
|
||||
"Open": "Open"
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,7 @@
|
||||
"Table": "Таблица",
|
||||
"Role": "Роль",
|
||||
"DeleteObject": "Удалить объект",
|
||||
"DeleteObjectConfirm": "Вы действительно хотите удалить {count, plural, =1 {этот обьект} other {эти # обьекта}}?"
|
||||
"DeleteObjectConfirm": "Вы действительно хотите удалить {count, plural, =1 {этот обьект} other {эти # обьекта}}?",
|
||||
"Open": "Открыть"
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,8 @@ loadMetadata(view.icon, {
|
||||
Move: `${icons}#move`,
|
||||
MoreH: `${icons}#more-h`,
|
||||
Archive: `${icons}#archive`,
|
||||
Statuses: `${icons}#statuses`
|
||||
Statuses: `${icons}#statuses`,
|
||||
Open: `${icons}#open`
|
||||
})
|
||||
|
||||
addStringsLoader(viewId, async (lang: string) => await import(`../lang/${lang}.json`))
|
||||
|
@ -36,29 +36,10 @@ focusStore.subscribe((it) => {
|
||||
$focusStore = it
|
||||
})
|
||||
|
||||
function selPrev (doc: Doc | undefined, evt: Event, dir: SelectDirection): void {
|
||||
selectPrevItem(dir)
|
||||
evt.preventDefault()
|
||||
}
|
||||
export function selectPrevItem (dir: SelectDirection): void {
|
||||
if ($focusStore.provider?.prev !== undefined) {
|
||||
$focusStore.provider?.prev(dir)
|
||||
previewDocument.update(old => {
|
||||
if (old !== undefined) {
|
||||
return $focusStore.focus
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function selNext (doc: Doc|undefined, evt: Event, dir: SelectDirection): void {
|
||||
selectNextItem(dir)
|
||||
evt.preventDefault()
|
||||
}
|
||||
|
||||
export function selectNextItem (dir: SelectDirection): void {
|
||||
if ($focusStore.provider?.next !== undefined) {
|
||||
$focusStore.provider?.next(dir)
|
||||
export function select (evt: Event|undefined, offset: 1 | -1 | 0, of?: Doc, direction?: SelectDirection): void {
|
||||
if ($focusStore.provider?.select !== undefined) {
|
||||
$focusStore.provider?.select(offset, of, direction)
|
||||
evt?.preventDefault()
|
||||
previewDocument.update(old => {
|
||||
if (old !== undefined) {
|
||||
return $focusStore.focus
|
||||
@ -93,10 +74,10 @@ function SelectItemAll (doc: Doc | undefined, evt: Event): void {
|
||||
evt.preventDefault()
|
||||
}
|
||||
|
||||
const MoveUp = (doc: Doc | undefined, evt: Event): void => selPrev(doc, evt, 'vertical')
|
||||
const MoveDown = (doc: Doc | undefined, evt: Event): void => selNext(doc, evt, 'vertical')
|
||||
const MoveLeft = (doc: Doc | undefined, evt: Event): void => selPrev(doc, evt, 'horizontal')
|
||||
const MoveRight = (doc: Doc | undefined, evt: Event): void => selNext(doc, evt, 'horizontal')
|
||||
const MoveUp = (doc: Doc | undefined, evt: Event): void => select(evt, -1, doc, 'vertical')
|
||||
const MoveDown = (doc: Doc | undefined, evt: Event): void => select(evt, 1, doc, 'vertical')
|
||||
const MoveLeft = (doc: Doc | undefined, evt: Event): void => select(evt, -1, doc, 'horizontal')
|
||||
const MoveRight = (doc: Doc | undefined, evt: Event): void => select(evt, 1, doc, 'horizontal')
|
||||
|
||||
function ShowActions (doc: Doc | Doc[] | undefined, evt: Event): void {
|
||||
evt.preventDefault()
|
||||
@ -112,7 +93,7 @@ function ShowPreview (doc: Doc | undefined, evt: Event): void {
|
||||
evt.preventDefault()
|
||||
}
|
||||
|
||||
function Edit (doc: Doc, evt: Event): void {
|
||||
function Open (doc: Doc, evt: Event): void {
|
||||
evt.preventDefault()
|
||||
showPanel(view.component.EditDoc, doc._id, Hierarchy.mixinOrClass(doc), 'content')
|
||||
}
|
||||
@ -132,5 +113,5 @@ export const actionImpl = {
|
||||
SelectItemAll,
|
||||
ShowActions,
|
||||
ShowPreview,
|
||||
Edit
|
||||
Open
|
||||
}
|
||||
|
@ -22,7 +22,6 @@
|
||||
export let value: number | null | undefined
|
||||
// export let label: IntlString
|
||||
export let onChange: (value: any) => void
|
||||
// export let attributeType: TypeDate | undefined
|
||||
</script>
|
||||
|
||||
<DateRangePresenter {value} withTime editable on:change={(res) => { if (res.detail !== undefined) onChange(res.detail) }} />
|
||||
|
@ -19,7 +19,6 @@
|
||||
import { DateRangePresenter } from '@anticrm/ui'
|
||||
|
||||
export let value: number | null | undefined
|
||||
// export let attributeType: TypeDate | undefined
|
||||
</script>
|
||||
|
||||
<DateRangePresenter {value} />
|
||||
|
@ -26,14 +26,12 @@
|
||||
getClient,
|
||||
KeyedAttribute
|
||||
} from '@anticrm/presentation'
|
||||
import { AnyComponent, Button, Component, IconDownOutline, IconUpOutline, Label, PopupAlignment, showPanel } from '@anticrm/ui'
|
||||
import { AnyComponent, Component, Label, PopupAlignment } from '@anticrm/ui'
|
||||
import view from '@anticrm/view'
|
||||
import { createEventDispatcher, onDestroy } from 'svelte'
|
||||
import ActionContext from './ActionContext.svelte'
|
||||
import { getCollectionCounter, getMixinStyle } from '../utils'
|
||||
import { selectNextItem, selectPrevItem } from '../actionImpl'
|
||||
import { tick } from 'svelte'
|
||||
import { focusStore } from '../selection'
|
||||
import ActionContext from './ActionContext.svelte'
|
||||
import UpDownNavigator from './UpDownNavigator.svelte'
|
||||
|
||||
export let _id: Ref<Doc>
|
||||
export let _class: Ref<Class<Doc>>
|
||||
@ -241,17 +239,6 @@
|
||||
headerLoading = false
|
||||
})
|
||||
}
|
||||
async function next (pn: boolean): Promise<void> {
|
||||
if (pn) {
|
||||
selectNextItem('vertical')
|
||||
} else {
|
||||
selectPrevItem('vertical')
|
||||
}
|
||||
await tick()
|
||||
if ($focusStore.focus !== undefined) {
|
||||
showPanel(view.component.EditDoc, $focusStore.focus._id, $focusStore.focus._class, 'content')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<ActionContext context={{
|
||||
mode: 'editor'
|
||||
@ -270,8 +257,7 @@
|
||||
}}
|
||||
>
|
||||
<svelte:fragment slot="navigate-actions">
|
||||
<Button icon={IconDownOutline} kind={'secondary'} size={'medium'} on:click={() => next(true)}/>
|
||||
<Button icon={IconUpOutline} kind={'secondary'} size={'medium'} on:click={() => next(false)}/>
|
||||
<UpDownNavigator element={object}/>
|
||||
</svelte:fragment>
|
||||
<div class="w-full" slot="subtitle">
|
||||
{#if !headerLoading}
|
||||
|
@ -38,7 +38,7 @@
|
||||
actions = result.map(a => ({
|
||||
label: a.label,
|
||||
icon: a.icon as Asset,
|
||||
action: async (evt: Event) => { invokeAction(evt, a.action) }
|
||||
action: async (props:any, evt: Event) => { invokeAction(evt, a.action) }
|
||||
}))
|
||||
loaded = 1
|
||||
})
|
||||
|
@ -14,7 +14,7 @@
|
||||
-->
|
||||
|
||||
<script lang="ts">
|
||||
import type { Class, Doc, Ref, Type } from '@anticrm/core'
|
||||
import type { Class, Doc, Ref } from '@anticrm/core'
|
||||
import { createQuery, getClient } from '@anticrm/presentation'
|
||||
import { AttributeModel } from '@anticrm/view'
|
||||
import { getObjectPresenter } from '../utils'
|
||||
@ -22,7 +22,6 @@
|
||||
export let objectId: Ref<Doc>
|
||||
export let _class: Ref<Class<Doc>>
|
||||
export let value: Doc | undefined
|
||||
export let attributeType: Type<any>
|
||||
export let props: Record<string, any> = {}
|
||||
|
||||
const client = getClient()
|
||||
@ -45,5 +44,5 @@
|
||||
</script>
|
||||
|
||||
{#if presenter}
|
||||
<svelte:component this={presenter.presenter} value={doc} {attributeType} {...props} inline />
|
||||
<svelte:component this={presenter.presenter} value={doc} {...props} inline />
|
||||
{/if}
|
||||
|
@ -16,9 +16,6 @@
|
||||
|
||||
<script lang="ts">
|
||||
export let value: string
|
||||
|
||||
// eslint-disable-next-line
|
||||
// export let attributeType: Type<any>
|
||||
</script>
|
||||
|
||||
<span class="lines-limit-2">{value}</span>
|
||||
|
@ -21,7 +21,7 @@
|
||||
import { CheckBox, Component, IconDown, IconUp, Label, Loading, showPopup, Spinner } from '@anticrm/ui'
|
||||
import { BuildModelKey } from '@anticrm/view'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import { selectionStore } from '../selection'
|
||||
import { SelectDirection } from '../selection'
|
||||
import { buildModel, LoadingProps } from '../utils'
|
||||
import Menu from './Menu.svelte'
|
||||
|
||||
@ -132,14 +132,20 @@
|
||||
dispatch('row-focus', object)
|
||||
}
|
||||
|
||||
export function scrollSelection (pos: number): void {
|
||||
if (pos !== -1) {
|
||||
const r = refs[pos]
|
||||
if (r !== undefined) {
|
||||
selection = pos
|
||||
onRow(objects[pos])
|
||||
r?.scrollIntoView({ behavior: 'auto', block: 'nearest' })
|
||||
}
|
||||
export function select (offset: 1 | -1 | 0, of?: Doc, dir?: SelectDirection): void {
|
||||
let pos = (((of !== undefined) ? objects.findIndex(it => it._id === of._id) : selection) ?? -1)
|
||||
pos += offset
|
||||
if (pos < 0) {
|
||||
pos = 0
|
||||
}
|
||||
if (pos >= objects.length) {
|
||||
pos = objects.length - 1
|
||||
}
|
||||
const r = refs[pos]
|
||||
selection = pos
|
||||
onRow(objects[pos])
|
||||
if (r !== undefined) {
|
||||
r?.scrollIntoView({ behavior: 'auto', block: 'nearest' })
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -15,9 +15,9 @@
|
||||
<script lang="ts">
|
||||
import type { Class, Doc, DocumentQuery, FindOptions, Ref } from '@anticrm/core'
|
||||
import { BuildModelKey } from '@anticrm/view'
|
||||
import { onMount } from 'svelte'
|
||||
import { onMount } from 'svelte'
|
||||
import { ActionContext } from '..'
|
||||
import { focusStore, ListSelectionProvider, selectionStore } from '../selection'
|
||||
import { focusStore, ListSelectionProvider, SelectDirection, selectionStore } from '../selection'
|
||||
import { LoadingProps } from '../utils'
|
||||
import Table from './Table.svelte'
|
||||
|
||||
@ -33,16 +33,10 @@ import { onMount } from 'svelte'
|
||||
|
||||
let table: Table
|
||||
const listProvider = new ListSelectionProvider(
|
||||
(pos, dir) => {
|
||||
(offset: 1 | -1 | 0, of?: Doc, dir?: SelectDirection) => {
|
||||
if (dir === 'vertical') {
|
||||
// Select next
|
||||
table.scrollSelection(pos + 1)
|
||||
}
|
||||
},
|
||||
(pos, dir) => {
|
||||
// Select prev
|
||||
if (dir === 'vertical') {
|
||||
table.scrollSelection(pos - 1)
|
||||
table.select(offset, of, dir)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
23
plugins/view-resources/src/components/UpDownNavigator.svelte
Normal file
23
plugins/view-resources/src/components/UpDownNavigator.svelte
Normal file
@ -0,0 +1,23 @@
|
||||
<script lang="ts">
|
||||
import { Doc } from '@anticrm/core'
|
||||
import { Button, IconDownOutline, IconUpOutline, panelstore, showPanel } from '@anticrm/ui'
|
||||
import { tick } from 'svelte'
|
||||
import { select } from '../actionImpl'
|
||||
import { focusStore } from '../selection'
|
||||
|
||||
export let element: Doc
|
||||
|
||||
async function next (evt: Event, pn: boolean): Promise<void> {
|
||||
select(evt, pn ? 1 : -1, element, 'vertical')
|
||||
await tick()
|
||||
if ($focusStore.focus !== undefined && $panelstore.panel !== undefined) {
|
||||
showPanel($panelstore.panel.component, $focusStore.focus._id, $focusStore.focus._class, $panelstore.panel?.element ?? 'content', $panelstore.panel.rightSection)
|
||||
}
|
||||
}
|
||||
|
||||
$: select(undefined, 0, element, 'vertical')
|
||||
|
||||
</script>
|
||||
|
||||
<Button icon={IconDownOutline} kind={'secondary'} size={'medium'} on:click={(evt) => next(evt, true)}/>
|
||||
<Button icon={IconUpOutline} kind={'secondary'} size={'medium'} on:click={(evt) => next(evt, false)}/>
|
@ -9,12 +9,13 @@ import { writable } from 'svelte/store'
|
||||
export type SelectDirection = 'vertical' | 'horizontal'
|
||||
|
||||
export interface SelectionFocusProvider {
|
||||
// -1 - previous
|
||||
// 0 - selec of as current
|
||||
// 1 - next
|
||||
// * If vertical, next will return item under.
|
||||
// * If horizontal, next will return item on right.
|
||||
next?: (direction?: SelectDirection) => void
|
||||
// * If vertical, next will return item amove.
|
||||
// * If horizontal, next will return item on left.
|
||||
prev?: (vertical?: SelectDirection) => void
|
||||
// of - document offset from we requesting.
|
||||
select?: (offset: 1 | -1 | 0, of?: Doc, direction?: SelectDirection) => void
|
||||
|
||||
// Update documents content
|
||||
update: (docs: Doc[]) => void
|
||||
@ -89,8 +90,7 @@ export class ListSelectionProvider implements SelectionFocusProvider {
|
||||
_docs: Doc[] = []
|
||||
_current?: FocusSelection
|
||||
constructor (
|
||||
private readonly selectNext: (cur: number, direction?: SelectDirection) => void,
|
||||
private readonly selectPrev: (cur: number, direction?: SelectDirection) => void
|
||||
private readonly delegate: (offset: 1 | -1 | 0, of?: Doc, direction?: SelectDirection) => void
|
||||
) {
|
||||
const unsubscribe = focusStore.subscribe((doc) => {
|
||||
this._current = doc
|
||||
@ -101,29 +101,21 @@ export class ListSelectionProvider implements SelectionFocusProvider {
|
||||
})
|
||||
}
|
||||
|
||||
next (direction?: SelectDirection): void {
|
||||
this.selectNext(this.current(this._current) ?? 0, direction)
|
||||
}
|
||||
|
||||
prev (direction?: SelectDirection): void {
|
||||
this.selectPrev(this.current(this._current) ?? this._docs.length - 1, direction)
|
||||
select (offset: 1 | -1 | 0, of?: Doc, direction?: SelectDirection): void {
|
||||
this.delegate(offset, of, direction)
|
||||
}
|
||||
|
||||
update (docs: Doc[]): void {
|
||||
this._docs = docs
|
||||
|
||||
if (this._docs.length > 0) {
|
||||
if (this._current === undefined) {
|
||||
updateFocus({
|
||||
focus: this._docs[0],
|
||||
provider: this
|
||||
})
|
||||
if (this._current?.focus === undefined) {
|
||||
this.delegate(0, undefined, 'vertical')
|
||||
} else {
|
||||
// Check if we don't have object, we need to select first one.
|
||||
if (this._docs.findIndex((it) => it._id === this._current?.focus?._id) === -1) {
|
||||
updateFocus({ focus: this._docs[0], provider: this })
|
||||
}
|
||||
this.delegate(0, this._current?.focus, 'vertical')
|
||||
}
|
||||
updateFocus({ focus: this._current?.focus, provider: this })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -105,7 +105,7 @@ async function getAttributePresenter (
|
||||
_class: attrClass,
|
||||
label: preserveKey.label ?? attribute.label,
|
||||
presenter,
|
||||
props: { attributeType: attribute.type },
|
||||
props: { },
|
||||
icon: presenterMixin.icon,
|
||||
attribute
|
||||
}
|
||||
|
@ -280,7 +280,8 @@ const view = plugin(viewId, {
|
||||
MoreH: '' as Asset,
|
||||
Move: '' as Asset,
|
||||
Archive: '' as Asset,
|
||||
Statuses: '' as Asset
|
||||
Statuses: '' as Asset,
|
||||
Open: '' as Asset
|
||||
}
|
||||
})
|
||||
export default view
|
||||
|
@ -49,7 +49,7 @@
|
||||
</span>
|
||||
{#each actions as action}
|
||||
<div class="an-element__tool">
|
||||
<ActionIcon label={action.label} icon={action.icon} size={'small'} action={action.action} />
|
||||
<ActionIcon label={action.label} icon={action.icon} size={'small'} action={(evt) => action.action({}, evt)} />
|
||||
</div>
|
||||
{/each}
|
||||
{#if notifications > 0}
|
||||
|
Loading…
Reference in New Issue
Block a user