Update DatePicker. Add and update presenters. Fix Activity layout. (#1162)

Signed-off-by: Alexander Platov <sas_lord@mail.ru>
This commit is contained in:
Alexander Platov 2022-03-18 07:58:10 +03:00 committed by GitHub
parent 773022cfae
commit 92c9732b52
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 312 additions and 158 deletions

View File

@ -199,7 +199,10 @@ p:last-child { margin-block-end: 0; }
line-clamp: 2;
user-select: none;
&.nowrap { white-space: nowrap; }
&.nowrap {
white-space: nowrap;
text-overflow: ellipsis;
}
}
.action {
visibility: hidden;

View File

@ -434,6 +434,7 @@
cursor: pointer;
.button {
flex-shrink: 0;
width: 2.25rem;
height: 2.25rem;
background-color: transparent;
@ -487,31 +488,6 @@
margin-left: .75rem;
min-height: 0;
}
.wrap {
position: relative;
display: flex;
align-items: center;
flex-wrap: nowrap;
min-width: 0;
&::after, &::before {
position: absolute;
width: 6px;
height: 6px;
background-color: var(--primary-button-enabled);
}
&::before {
top: -2px;
left: -4px;
clip-path: path('M0,6v-6h6v1h-5v5z');
}
&::after {
bottom: -2px;
right: -4px;
clip-path: path('M0,6h6v-6h-1v5h-5z');
}
&.wraped::before, &.wraped::after { content: ''; }
}
.divider {
margin: 0 .125rem;
@ -527,3 +503,32 @@
}
}
}
/* Wraps */
.antiWrapper {
position: relative;
display: flex;
align-items: center;
flex-wrap: nowrap;
min-width: 0;
&::after, &::before {
position: absolute;
width: 6px;
height: 6px;
background-color: var(--primary-button-enabled);
}
&::before {
top: -2px;
left: -4px;
clip-path: path('M0,6v-6h6v1h-5v5z');
}
&::after {
bottom: -2px;
right: -4px;
clip-path: path('M0,6h6v-6h-1v5h-5z');
}
&.wraped::before, &.wraped::after { content: ''; }
&.focusWI:focus-within::before, &.focusWI:focus-within::after { content: ''; }
&.focus:focus::before, &.focus:focus::after { content: ''; }
}

View File

@ -1,6 +1,7 @@
{
"string": {
"EditBoxPlaceholder": "placeholder",
"Ok": "Ok",
"Cancel": "Cancel",
"Minutes": "{minutes, plural, =0 {less than a minute ago} =1 {a minute ago} other {# minutes ago}}",
"Hours": "{hours, plural, =0 {less than an hour ago} =1 {an hour ago} other {# hours ago}}",

View File

@ -1,6 +1,7 @@
{
"string": {
"EditBoxPlaceholder": "Введите текст здесь",
"Ok": "Ок",
"Cancel": "Отменить",
"Minutes": "{minutes, plural, =0 {меньше минуты назад} =1 {минуту назад} other {# минут назад}}",
"Hours": "{hours, plural, =0 {меньше часа назад} =1 {час назад} other {# часов назад}}",

View File

@ -30,9 +30,10 @@
export let width: string | undefined = undefined
export let focus: boolean = false
let input: HTMLButtonElement
export let input: HTMLButtonElement | undefined = undefined
onMount(() => {
if (focus) {
if (focus && input) {
input.focus()
focus = false
}

View File

@ -22,40 +22,29 @@
export let title: IntlString
export let value: Date | null | undefined = null
export let range: Date | null | undefined = undefined
export let withTime: boolean = false
export let bigDay: boolean = false
export let show: boolean = false
const dispatch = createEventDispatcher()
let opened: boolean = false
let secondSelect: boolean = false
let container: HTMLElement
let btn: HTMLElement
const changeValue = (result: any): void => {
if (result !== undefined) {
value = result
dispatch('change', result)
}
}
onMount(() => {
if (btn && show) {
btn.click()
show = false
}
})
const splitRes = (result: any): void => {
if (result !== undefined) {
if (result[0] !== value) value = result[0]
if (result[1] !== range) range = result[1]
dispatch('change', [value, range])
}
}
const onClosePopup = (result: any): void => {
splitRes(result)
opened = false
secondSelect = false
}
const onUpdatePopup = (result: any): void => {
secondSelect = true
splitRes(result)
}
</script>
<div class="antiSelect"
@ -64,7 +53,10 @@
btn.focus()
if (!opened) {
opened = true
showPopup(DatePopup, { title, value, range }, container, onClosePopup, onUpdatePopup)
showPopup(DatePopup, { title, value, withTime }, container, (ev) => {
changeValue(ev)
opened = false
}, changeValue)
}
}}
>
@ -81,13 +73,7 @@
<div class="group">
<span class="label"><Label label={title} /></span>
{#if value !== undefined}
<div class="flex-row-center">
<DatePresenter {value} {bigDay} wraped={opened && !secondSelect} />
{#if range !== undefined}
<span class="divider max"> &mdash; </span>
<DatePresenter value={range} {bigDay} wraped={opened && secondSelect} />
{/if}
</div>
<DatePresenter {value} withTime={withTime} {bigDay} wraped={opened} />
{:else}
<span class="result not-selected"><Label label={ui.string.NotSelected} /></span>
{/if}

View File

@ -18,12 +18,12 @@
import Back from './icons/Back.svelte'
import Forward from './icons/Forward.svelte'
import { createEventDispatcher } from 'svelte'
import ui, { Label } from '..'
import ui, { Label, Button } from '..'
import type { TSelectDate, TCellStyle, ICell } from '../types'
export let title: IntlString
export let value: TSelectDate = null
export let range: TSelectDate = undefined
export let value: TSelectDate
export let withTime: boolean = false
const dispatch = createEventDispatcher()
@ -55,8 +55,12 @@
]
let monthYear: string
let days: Array<ICell> = []
let firstClick: boolean = true
let result: Array<TSelectDate> = [value, range]
let result: TSelectDate = value
let prevDiv: HTMLElement
let nextDiv: HTMLElement
let hourDiv: HTMLElement
let minDiv: HTMLElement
let okDiv: HTMLButtonElement
const daysInMonth = (date: Date): number => {
return 33 - new Date(date.getFullYear(), date.getMonth(), 33).getDate()
@ -69,12 +73,7 @@
return false
}
const getDateStyle = (date: Date): TCellStyle => {
if (value !== undefined && value !== null && compareDates(value, date)) return 'selected-start'
else if (value && value < date && range) {
if (range && compareDates(range, date)) return 'selected-end'
else if (date < range) return 'selected'
else return 'not-selected'
}
if (value !== undefined && value !== null && compareDates(value, date)) return 'selected'
return 'not-selected'
}
@ -94,14 +93,56 @@
$: monthYear = months[view.getMonth()] + ' ' + view.getFullYear()
$: if (value) renderCellStyles()
$: if (range) renderCellStyles()
const zeroLead = (n: number): string => {
if (n < 10) return '0' + n.toString()
return n.toString()
}
const keyPress = (ev: KeyboardEvent, isHour: boolean): void => {
if (ev.key >= '0' && ev.key <= '9') {
const keyNumber: number = parseInt(ev.key, 10)
let number: number = isHour ? view.getHours() : view.getMinutes()
let newNumber: number = ((isHour && number > 2) || (!isHour && number > 5))
? keyNumber
: number * 10 + keyNumber
if (isHour) {
if (newNumber > 23) newNumber = 23
view.setHours(newNumber)
} else {
if (newNumber > 59) newNumber = 59
view.setMinutes(newNumber)
}
view = view
value = view
if (isHour && newNumber > 9) minDiv.focus()
if (!isHour && newNumber > 9) okDiv.focus()
}
}
const keyDown = (ev: KeyboardEvent, isHour: boolean): void => {
if (ev.key === 'Backspace') {
console.log('BACKSPACE')
if (isHour) view.setHours(0)
else view.setMinutes(0)
view = view
value = view
}
}
const navKey = (ev: KeyboardEvent): void => {
if (ev.code === 'ArrowLeft') prevDiv.click()
if (ev.code === 'ArrowRight') nextDiv.click()
}
</script>
<svelte:window on:keydown={navKey} />
<div class="popup">
<div class="flex-col caption-color">
<div class="title"><Label label={title} /></div>
<div class="flex-between nav">
<button
bind:this={prevDiv}
class="focused-button arrow"
on:click|preventDefault={() => {
view.setMonth(view.getMonth() - 1)
@ -112,6 +153,7 @@
{monthYear}
</div>
<button
bind:this={nextDiv}
class="focused-button arrow"
on:click|preventDefault={() => {
view.setMonth(view.getMonth() + 1)
@ -136,26 +178,45 @@
data-today={day.today ? todayString : ''}
style="grid-column: {day.dayOfWeek}/{day.dayOfWeek + 1};"
on:click={() => {
if (firstClick) {
result[0] = new Date(view.getFullYear(), view.getMonth(), i + 1)
value = result[0]
firstClick = false
if (result[1] === undefined) dispatch('close', result)
else dispatch('update', result)
} else {
result[1] = new Date(view.getFullYear(), view.getMonth(), i + 1)
if (result[0] && result[1] && result[0].getTime() > result[1].getTime())
[result[0], result[1]] = [result[1], result[0]]
value = result[0]
range = result[1]
dispatch('close', result)
}
result = new Date(view.getFullYear(), view.getMonth(), i + 1, view.getHours(), view.getMinutes())
view = value = result
if (withTime) {
dispatch('update', result)
hourDiv.focus()
} else dispatch('close', result)
}}
>
{i + 1}
</div>
{/each}
</div>
{#if withTime}
<div class="calendar-divider" />
<div class="flex-row-center flex-reverse">
<div class="ml-2">
<Button bind:input={okDiv} label={ui.string.Ok} size={'small'} primary on:click={() => { dispatch('close', view) }} />
</div>
<div class="time-container">
<button
bind:this={hourDiv}
class="time-digit antiWrapper focus hours"
on:keypress={(ev) => { keyPress(ev, true) }}
on:keydown={(ev) => { keyDown(ev, true) }}
>
{zeroLead(view.getHours())}
</button>
<div class="time-divider">:</div>
<button
bind:this={minDiv}
class="time-digit antiWrapper focus minutes"
on:keypress={(ev) => { keyPress(ev, false) }}
on:keydown={(ev) => { keyDown(ev, false) }}
>
{zeroLead(view.getMinutes())}
</button>
</div>
</div>
{/if}
</div>
<style lang="scss">
@ -215,15 +276,9 @@
cursor: pointer;
&.selected {
background-color: var(--primary-button-disabled);
border-color: transparent;
color: var(--theme-content-accent-color);
&-start, &-end {
background-color: var(--primary-button-enabled);
border-color: var(--primary-button-focused-border);
color: var(--primary-button-color);
}
background-color: var(--primary-button-enabled);
border-color: var(--primary-button-focused-border);
color: var(--primary-button-color);
}
&.today {
position: relative;
@ -245,4 +300,36 @@
}
}
}
.calendar-divider {
flex-shrink: 0;
margin: .5rem 0;
height: 1px;
background-color: var(--theme-menu-divider);
}
.time-container {
display: flex;
justify-content: center;
align-items: center;
flex-grow: 1;
min-width: 0;
height: 100%;
border: 1px solid var(--theme-button-border-enabled);
border-radius: .75rem;
}
.time-digit, .time-divider {
font-weight: 500;
font-size: 1.25rem;
cursor: pointer;
}
.time-divider {
margin: 0 .5rem;
font-size: 1rem;
color: var(--theme-content-dark-color);
}
.time-digit {
padding: 0;
font-weight: 600;
color: var(--theme-caption-color);
}
</style>

View File

@ -19,13 +19,19 @@
export let value: TSelectDate
export let bigDay: boolean = false
export let wraped: boolean = false
export let withTime: boolean = false
const { currentLanguage } = getContext('lang')
let inter: boolean = (currentLanguage === 'ru') ?? false
const zeroLead = (n: number): string => {
if (n < 10) return '0' + n.toString()
return n.toString()
}
</script>
{#if value !== undefined}
<div class="wrap" class:wraped>
<div class="antiWrapper" class:wraped>
<span class="result" class:selected={value !== null} class:not-selected={value === null} class:highlight={inter && bigDay}>
{#if value === null}--{:else}{inter ? value.getDate() : value.getMonth() + 1}{/if}
</span>
@ -37,5 +43,15 @@
<span class="result" class:selected={value !== null} class:not-selected={value === null}>
{#if value === null}--{:else}{value.getFullYear()}{/if}
</span>
{#if withTime}
<span class="divider max"> &mdash; </span>
<span class="result" class:selected={value !== null} class:not-selected={value === null} class:highlight={!inter && bigDay}>
{#if value === null}--{:else}{zeroLead(value.getHours())}{/if}
</span>
<span class="divider">:</span>
<span class="result" class:selected={value !== null} class:not-selected={value === null}>
{#if value === null}--{:else}{zeroLead(value.getMinutes())}{/if}
</span>
{/if}
</div>
{/if}

View File

@ -0,0 +1,24 @@
<!--
// Copyright © 2020 Anticrm Platform Contributors.
//
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. You may
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
-->
<script lang="ts">
import type { TSelectDate } from '../types'
import DatePresenter from './DatePresenter.svelte'
export let value: TSelectDate
export let bigDay: boolean = false
export let wraped: boolean = false
</script>
<DatePresenter {value} {bigDay} {wraped} withTime />

View File

@ -75,7 +75,7 @@
<Icon {icon} size={'small'}/>
</div>
{/if}
<div class="wrap">
<div class="antiWrapper focusWI">
{#if format === 'password'}
<input bind:this={input} type='passsword' bind:value placeholder={phTraslate} {style} on:input={(ev) => ev.target && computeSize(ev.target)} on:change/>
{:else if format === 'number'}
@ -94,28 +94,6 @@
align-items: flex-start;
}
.wrap {
position: relative;
&::after, &::before {
position: absolute;
width: 6px;
height: 6px;
background-color: var(--primary-button-enabled);
}
&::before {
top: -2px;
left: -4px;
clip-path: path('M0,6v-6h6v1h-5v5z');
}
&::after {
bottom: -2px;
right: -4px;
clip-path: path('M0,6h6v-6h-1v5h-5z');
}
&:focus-within::before, &:focus-within::after { content: ''; }
}
.label {
margin-bottom: .25rem;
font-size: .75rem;

View File

@ -16,7 +16,7 @@
<script lang="ts">
import { IntlString, translate } from '@anticrm/platform'
import { translate } from '@anticrm/platform'
import { ticker } from '..'
import ui from '../plugin'
import Tooltip from './Tooltip.svelte'

View File

@ -47,6 +47,7 @@ export { default as Section } from './components/Section.svelte'
export { default as DatePicker } from './components/DatePicker.svelte'
export { default as DatePopup } from './components/DatePopup.svelte'
export { default as DatePresenter } from './components/DatePresenter.svelte'
export { default as DateTimePresenter } from './components/DateTimePresenter.svelte'
export { default as StylishEdit } from './components/StylishEdit.svelte'
export { default as Grid } from './components/Grid.svelte'
export { default as Row } from './components/Row.svelte'

View File

@ -26,6 +26,7 @@ export const uiId = 'ui' as Plugin
export default plugin(uiId, {
string: {
EditBoxPlaceholder: '' as IntlString,
Ok: '' as IntlString,
Cancel: '' as IntlString,
Minutes: '' as IntlString,
Hours: '' as IntlString,

View File

@ -88,7 +88,7 @@ export interface DropdownTextItem {
}
export type TSelectDate = Date | null | undefined
export type TCellStyle = 'not-selected' | 'selected' | 'selected-start' | 'selected-end'
export type TCellStyle = 'not-selected' | 'selected'
export interface ICell {
dayOfWeek: number
style: TCellStyle

View File

@ -20,23 +20,27 @@
<div class="flex-row-center flex-grow flex-wrap content">
{#each filterTx([tx, ...tx.txes], core.class.TxCreateDoc) as ctx, i}
{#if i === 0}
<div class="mr-1"><IconAdd size={'small'} /></div>
{/if}
{#if typeof viewlet?.component === 'string'}
<Component is={viewlet?.component} props={getProps(getDTxProps(ctx), edit)} on:close={onCancelEdit} />
{:else}
<svelte:component this={viewlet?.component} {...getProps(getDTxProps(ctx), edit)} on:close={onCancelEdit} />
<div class="mr-2"><IconAdd size={'small'} /></div>
{/if}
<div class="mr-2">
{#if typeof viewlet?.component === 'string'}
<Component is={viewlet?.component} props={getProps(getDTxProps(ctx), edit)} on:close={onCancelEdit} />
{:else}
<svelte:component this={viewlet?.component} {...getProps(getDTxProps(ctx), edit)} on:close={onCancelEdit} />
{/if}
</div>
{/each}
{#each filterTx([tx, ...tx.txes], core.class.TxRemoveDoc) as ctx, i}
{#if i === 0}
<div class="mr-1"><IconDelete size={'small'} /></div>
{/if}
{#if typeof viewlet?.component === 'string'}
<Component is={viewlet?.component} props={getProps(getDTxProps(ctx), edit)} on:close={onCancelEdit} />
{:else}
<svelte:component this={viewlet?.component} {...getProps(getDTxProps(ctx), edit)} on:close={onCancelEdit} />
<div class="mr-2"><IconDelete size={'small'} /></div>
{/if}
<div class="mr-2">
{#if typeof viewlet?.component === 'string'}
<Component is={viewlet?.component} props={getProps(getDTxProps(ctx), edit)} on:close={onCancelEdit} />
{:else}
<svelte:component this={viewlet?.component} {...getProps(getDTxProps(ctx), edit)} on:close={onCancelEdit} />
{/if}
</div>
{/each}
</div>
@ -46,6 +50,6 @@
color: var(--theme-caption-color);
background: var(--theme-bg-accent-color);
border: 1px solid var(--theme-bg-accent-color);
border-radius: 0.75rem;
border-radius: .75rem;
}
</style>

View File

@ -103,11 +103,13 @@
class="channels {length}"
class:one={displayItems?.length === 1}
class:reverse
class:small-gap={size === 'small'}
class:normal-gap={size !== 'small'}
>
{#each displayItems as item,i}
<div class='channel-item'>
<Tooltip component={ChannelsPopup} props={{ value: item }} label={undefined} anchor={divHTML}>
<CircleButton
<Tooltip component={ChannelsPopup} props={{ value: item }} label={undefined} anchor={divHTML}>
<CircleButton
icon={item.icon}
{size}
primary={item.integration || item.notification}
@ -131,9 +133,5 @@
&.reverse { grid-auto-flow: dense; }
&.small-gap { gap: .25rem; }
&.normal-gap { gap: .5rem; }
.channel-item {
margin: 0.125rem;
}
}
</style>

View File

@ -28,8 +28,13 @@
</script>
{#if value}
<div class="flex-presenter" class:inline-presenter={inline} on:click={onClick}>
<a
class="flex-presenter"
class:inline-presenter={inline}
href="#{encodeURIComponent([view.component.EditDoc, value._id, value._class].join('|'))}"
on:click={onClick}
>
<div class="icon"><Company size={'small'} /></div>
<span class="label">{value.name}</span>
</div>
</a>
{/if}

View File

@ -29,10 +29,15 @@
</script>
{#if value}
<div class="flex-presenter" class:inline-presenter={inline} on:click={onClick}>
<a
class="flex-presenter"
class:inline-presenter={inline}
href="#{encodeURIComponent([view.component.EditDoc, value._id, Hierarchy.mixinOrClass(value)].join('|'))}"
on:click={onClick}
>
<div class="icon">
<Avatar size={'x-small'} avatar={value.avatar} />
</div>
<span class="label">{formatName(value.name)}</span>
</div>
</a>
{/if}

View File

@ -29,8 +29,13 @@
</script>
{#if value}
<div class="flex-presenter" class:inline-presenter={inline} on:click={show}>
<a
class="flex-presenter"
class:inline-presenter={inline}
href="#{encodeURIComponent([view.component.EditDoc, value._id, value._class].join('|'))}"
on:click={show}
>
<div class="icon"><Icon icon={inventory.icon.Products} size={'small'} /></div>
<span class="label">{value.name}</span>
</div>
</a>
{/if}

View File

@ -20,14 +20,23 @@
import lead from '../plugin'
export let value: Lead
export let inline: boolean = false
function show () {
async function show () {
showPanel(view.component.EditDoc, value._id, value._class, 'full')
}
</script>
{#if value}
<div class="sm-tool-icon" on:click={show}>
<span class="icon"><Icon icon={lead.icon.Lead} size={'small'} /></span>{value.title}
</div>
<a
class="flex-presenter"
class:inline-presenter={inline}
href="#{encodeURIComponent([view.component.EditDoc, value._id, value._class].join('|'))}"
on:click={show}
>
<div class="icon">
<Icon icon={lead.icon.Lead} size={'small'} />
</div>
<span class="label">{value.title}</span>
</a>
{/if}

View File

@ -74,7 +74,6 @@
"ReviewShortLabel": "RVE",
"StartDate": "Start date",
"DueDate": "Due date",
"Period": "Period",
"ReviewCategoryTitle":"Category",
"Verdict": "Verdict",
"OpinionSave": "Save",

View File

@ -75,7 +75,6 @@
"ReviewShortLabel": "RVE",
"StartDate": "Дата начала",
"DueDate": "Дата конца",
"Period": "Период",
"ReviewCategoryTitle":"Категория",
"Verdict": "Вердикт",
"OpinionSave": "Сохранить",

View File

@ -33,10 +33,15 @@
</script>
{#if value && shortLabel}
<div class="flex-presenter" class:inline-presenter={inline} on:click={show}>
<a
class="flex-presenter"
class:inline-presenter={inline}
href="#{encodeURIComponent([view.component.EditDoc, value._id, value._class].join('|'))}"
on:click={show}
>
<div class="icon">
<Icon icon={recruit.icon.Application} size={'small'} />
</div>
<span class="label nowrap">{#if shortLabel}<Label label={shortLabel} />-{/if}{value.number}</span>
</div>
</a>
{/if}

View File

@ -28,10 +28,15 @@
</script>
{#if value}
<div class="flex-presenter" class:inline-presenter={inline} on:click={show}>
<a
class="flex-presenter"
class:inline-presenter={inline}
href="#{encodeURIComponent([recruit.component.EditVacancy, value._id, value._class].join('|'))}"
on:click={show}
>
<div class="icon">
<Icon icon={recruit.icon.Vacancy} size={'small'} />
</div>
<span class="label">{value.name}</span>
</div>
</a>
{/if}

View File

@ -155,6 +155,7 @@
allowDeselect
titleDeselect={recruit.string.UnAssignRecruiter}
/>
<DatePicker title={recruit.string.Period} bind:value={startDate} bind:range={dueDate} />
<DatePicker title={recruit.string.StartDate} bind:value={startDate} withTime />
<DatePicker title={recruit.string.DueDate} bind:value={dueDate} withTime />
</Grid>
</Card>

View File

@ -42,10 +42,15 @@
</script>
{#if value && shortLabel}
<div class="flex-presenter" class:inline-presenter={inline} on:click={show}>
<a
class="flex-presenter"
class:inline-presenter={inline}
href="#{encodeURIComponent([view.component.EditDoc, value._id, value._class].join('|'))}"
on:click={show}
>
<div class="icon">
<Icon icon={recruit.icon.Application} size={'small'} />
</div>
<span class="label nowrap">{shortLabel}-{value.number}</span>
</div>
</a>
{/if}

View File

@ -100,7 +100,6 @@ export default mergeIds(recruitId, recruit, {
ReviewShortLabel: '' as IntlString,
StartDate: '' as IntlString,
DueDate: '' as IntlString,
Period: '' as IntlString,
CandidateReviews: '' as IntlString,
Participants: '' as IntlString,
NoParticipants: '' as IntlString,

View File

@ -21,6 +21,7 @@
import task from '../plugin'
export let value: Issue
export let inline: boolean = false
const client = getClient()
const shortLabel = client.getHierarchy().getClass(value._class).shortLabel
@ -30,6 +31,16 @@
}
</script>
<div class="sm-tool-icon" on:click={show}>
<span class="icon"><Icon icon={task.icon.Task} size={'small'} /></span>{#if shortLabel}<Label label={shortLabel} />-{/if}{value.number}
</div>
{#if value && shortLabel}
<a
class="flex-presenter"
class:inline-presenter={inline}
href="#{encodeURIComponent([view.component.EditDoc, value._id, value._class].join('|'))}"
on:click={show}
>
<div class="icon">
<Icon icon={task.icon.Task} size={'small'} />
</div>
<span class="label nowrap">{#if shortLabel}<Label label={shortLabel} />-{/if}{value.number}</span>
</a>
{/if}