mirror of
https://github.com/hcengineering/platform.git
synced 2025-04-18 06:13:52 +00:00
Update DatePicker. Add and update presenters. Fix Activity layout. (#1162)
Signed-off-by: Alexander Platov <sas_lord@mail.ru>
This commit is contained in:
parent
773022cfae
commit
92c9732b52
@ -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;
|
||||
|
@ -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: ''; }
|
||||
}
|
||||
|
@ -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}}",
|
||||
|
@ -1,6 +1,7 @@
|
||||
{
|
||||
"string": {
|
||||
"EditBoxPlaceholder": "Введите текст здесь",
|
||||
"Ok": "Ок",
|
||||
"Cancel": "Отменить",
|
||||
"Minutes": "{minutes, plural, =0 {меньше минуты назад} =1 {минуту назад} other {# минут назад}}",
|
||||
"Hours": "{hours, plural, =0 {меньше часа назад} =1 {час назад} other {# часов назад}}",
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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"> — </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}
|
||||
|
@ -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>
|
||||
|
@ -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"> — </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}
|
||||
|
24
packages/ui/src/components/DateTimePresenter.svelte
Normal file
24
packages/ui/src/components/DateTimePresenter.svelte
Normal 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 />
|
@ -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;
|
||||
|
@ -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'
|
||||
|
@ -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'
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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>
|
@ -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}
|
||||
|
@ -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}
|
||||
|
@ -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}
|
||||
|
@ -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}
|
||||
|
@ -74,7 +74,6 @@
|
||||
"ReviewShortLabel": "RVE",
|
||||
"StartDate": "Start date",
|
||||
"DueDate": "Due date",
|
||||
"Period": "Period",
|
||||
"ReviewCategoryTitle":"Category",
|
||||
"Verdict": "Verdict",
|
||||
"OpinionSave": "Save",
|
||||
|
@ -75,7 +75,6 @@
|
||||
"ReviewShortLabel": "RVE",
|
||||
"StartDate": "Дата начала",
|
||||
"DueDate": "Дата конца",
|
||||
"Period": "Период",
|
||||
"ReviewCategoryTitle":"Категория",
|
||||
"Verdict": "Вердикт",
|
||||
"OpinionSave": "Сохранить",
|
||||
|
@ -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}
|
||||
|
@ -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}
|
||||
|
@ -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>
|
||||
|
@ -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}
|
||||
|
@ -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,
|
||||
|
@ -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}
|
||||
|
Loading…
Reference in New Issue
Block a user