mirror of
https://github.com/hcengineering/platform.git
synced 2025-04-15 21:03:30 +00:00
Removed full-size panel mode. Integrate views for channels provider. (#1575)
Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
parent
64cbfdb7e8
commit
bde8549e5d
@ -14,43 +14,30 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import activity from '@anticrm/activity'
|
||||
import calendar from '@anticrm/calendar'
|
||||
import type { Doc } from '@anticrm/core'
|
||||
import notification from '@anticrm/notification'
|
||||
import type { Asset } from '@anticrm/platform'
|
||||
import { Button, AnyComponent, AnySvelteComponent, Component, IconExpand, Panel, Scroller } from '@anticrm/ui'
|
||||
import { PopupAlignment } from '@anticrm/ui'
|
||||
import { AnyComponent, AnySvelteComponent, Component, Panel } from '@anticrm/ui'
|
||||
|
||||
export let title: string | undefined = undefined
|
||||
export let subtitle: string | undefined = undefined
|
||||
export let icon: Asset | AnySvelteComponent | undefined = undefined
|
||||
export let fullSize: boolean = true
|
||||
export let showHeader: boolean = true
|
||||
export let rightSection: AnyComponent | undefined = undefined
|
||||
export let object: Doc
|
||||
export let position: PopupAlignment | undefined = undefined
|
||||
export let panelWidth: number = 0
|
||||
export let innerWidth: number = 0
|
||||
export let isSubtitle: boolean = false
|
||||
export let isProperties: boolean = false
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
$: allowFullSize = panelWidth > 1200 && (position === 'full' || position === 'content')
|
||||
$: isFullSize = allowFullSize && fullSize
|
||||
|
||||
const resizePanel = () => {
|
||||
isFullSize = !isFullSize
|
||||
}
|
||||
</script>
|
||||
|
||||
<Panel
|
||||
{title}
|
||||
{subtitle}
|
||||
{icon}
|
||||
rightSection={isFullSize}
|
||||
rightSection={rightSection !== undefined}
|
||||
{showHeader}
|
||||
bind:panelWidth
|
||||
bind:innerWidth
|
||||
@ -69,31 +56,12 @@
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="commands">
|
||||
<div class="buttons-group xsmall-gap">
|
||||
<slot name="actions" />
|
||||
<Component is={calendar.component.DocReminder} props={{ value: object, title }} />
|
||||
<Component is={notification.component.LastViewEditor} props={{ value: object }} />
|
||||
</div>
|
||||
<slot name="actions" />
|
||||
</svelte:fragment>
|
||||
|
||||
<svelte:fragment slot="rightSection">
|
||||
{#if isFullSize}
|
||||
<div class="ad-section-50">
|
||||
<Component is={rightSection ?? activity.component.Activity} props={{ object, fullSize: isFullSize }} />
|
||||
</div>
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="actions">
|
||||
{#if allowFullSize}
|
||||
<Button icon={IconExpand} size={'medium'} kind={'transparent'} on:click={resizePanel} />
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
{#if isFullSize}
|
||||
<Scroller correctPadding={40}>
|
||||
<div class="p-10 clear-mins"><slot /></div>
|
||||
</Scroller>
|
||||
{:else}
|
||||
<Component is={activity.component.Activity} props={{ object, fullSize: isFullSize }}>
|
||||
<Component is={rightSection ?? activity.component.Activity} props={{ object, integrate: true }}>
|
||||
<slot />
|
||||
</Component>
|
||||
{/if}
|
||||
</Panel>
|
||||
|
@ -61,6 +61,9 @@
|
||||
--accent-bg-color: #27282b;
|
||||
--accent-shadow: rgb(0 0 0 / 10%) 0px 2px 4px;
|
||||
|
||||
--highlight-select: #8a8f9810;
|
||||
--highlight-hover: #8a8f9820;
|
||||
|
||||
--dark-color: #62666d;
|
||||
--content-color: #8a8f98;
|
||||
--accent-color: #d7d8db;
|
||||
@ -198,6 +201,9 @@
|
||||
--accent-bg-color: #f8f9fb; // HZ
|
||||
--accent-shadow: rgb(0 0 0 / 10%) 0px 2px 4px; // Dark
|
||||
|
||||
--highlight-select: #3c414910;
|
||||
--highlight-hover: #3c414920;
|
||||
|
||||
--dark-color: #90959d;
|
||||
--content-color: #3c4149;
|
||||
--accent-color: #282a30;
|
||||
|
@ -343,6 +343,7 @@ p:last-child { margin-block-end: 0; }
|
||||
.mx-1 { margin: 0 .25rem; }
|
||||
.mx-2 { margin: 0 .5rem; }
|
||||
.mx-3 { margin: 0 .75rem; }
|
||||
.mx-10 { margin: 0 2.5rem; }
|
||||
.mx-auto { margin: 0 auto; }
|
||||
.my-4 { margin: 1rem 0; }
|
||||
|
||||
@ -593,6 +594,7 @@ a.no-line {
|
||||
/* Backgrounds & Colors */
|
||||
.background-body-color { background-color: var(--body-color); }
|
||||
.background-accent-bg-color { background-color: var(--accent-bg-color); }
|
||||
.background-highlight-select { background-color: var(--highlight-select); }
|
||||
|
||||
.background-theme-content-accent { background-color: var(--theme-content-accent-color); }
|
||||
.background-theme-bg-color { background-color: var(--theme-bg-color); }
|
||||
@ -624,3 +626,4 @@ a.no-line {
|
||||
.border-button-enabled { border: 1px solid var(--theme-button-border-enabled); }
|
||||
|
||||
.bottom-divider { border-bottom: 1px solid var(--divider-color); }
|
||||
.bottom-highlight-select { border-bottom: 1px solid var(--highlight-select); }
|
||||
|
@ -26,6 +26,7 @@
|
||||
min-width: var(--app-panel-width);
|
||||
width: var(--app-panel-width);
|
||||
height: 100%;
|
||||
background-color: var(--board-bg-color);
|
||||
}
|
||||
.antiPanel-navigator,
|
||||
.antiPanel-component {
|
||||
@ -53,7 +54,10 @@
|
||||
z-index: 450;
|
||||
}
|
||||
}
|
||||
.antiPanel-component:not(.aside) { flex-grow: 1; }
|
||||
.antiPanel-component:not(.aside) {
|
||||
flex-grow: 1;
|
||||
background-color: var(--board-bg-color);
|
||||
}
|
||||
.antiPanel-component.aside {
|
||||
min-width: 30rem;
|
||||
width: 30rem;
|
||||
|
@ -49,74 +49,74 @@
|
||||
&.divide {
|
||||
border-bottom: 1px solid var(--divider-color);
|
||||
}
|
||||
}
|
||||
|
||||
.ac-header__wrap-description,
|
||||
.ac-header__wrap-title {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
min-width: 0;
|
||||
cursor: default;
|
||||
}
|
||||
.ac-header__wrap-description {
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
}
|
||||
.ac-header__wrap-title {
|
||||
align-items: center;
|
||||
}
|
||||
.ac-header__wrap-description,
|
||||
.ac-header__wrap-title {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
min-width: 0;
|
||||
cursor: default;
|
||||
}
|
||||
.ac-header__wrap-description {
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
}
|
||||
.ac-header__wrap-title {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.ac-header__icon {
|
||||
margin-right: 0.5rem;
|
||||
color: var(--theme-content-color);
|
||||
}
|
||||
.ac-header__title {
|
||||
min-width: 0;
|
||||
font-weight: 500;
|
||||
font-size: 1rem;
|
||||
.ac-header__icon {
|
||||
margin-right: 0.5rem;
|
||||
color: var(--theme-content-color);
|
||||
}
|
||||
.ac-header__title {
|
||||
min-width: 0;
|
||||
font-weight: 500;
|
||||
font-size: 1rem;
|
||||
color: var(--theme-caption-color);
|
||||
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
user-select: none;
|
||||
}
|
||||
.ac-header__description {
|
||||
min-width: 0;
|
||||
font-size: 0.75rem;
|
||||
color: var(--theme-content-dark-color);
|
||||
|
||||
overflow: hidden;
|
||||
visibility: visible;
|
||||
display: -webkit-box;
|
||||
/* autoprefixer: ignore next */
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
line-clamp: 2;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.ac-header__icon-button {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
color: var(--theme-content-trans-color);
|
||||
background-color: transparent;
|
||||
border-radius: .25rem;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: var(--theme-caption-color);
|
||||
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
user-select: none;
|
||||
}
|
||||
.ac-header__description {
|
||||
min-width: 0;
|
||||
font-size: 0.75rem;
|
||||
color: var(--theme-content-dark-color);
|
||||
|
||||
overflow: hidden;
|
||||
visibility: visible;
|
||||
display: -webkit-box;
|
||||
/* autoprefixer: ignore next */
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
line-clamp: 2;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.ac-header__icon-button {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
color: var(--theme-content-trans-color);
|
||||
background-color: transparent;
|
||||
border-radius: .25rem;
|
||||
cursor: pointer;
|
||||
|
||||
&.selected {
|
||||
color: var(--theme-content-accent-color);
|
||||
background-color: var(--menu-bg-select);
|
||||
cursor: default;
|
||||
&:hover {
|
||||
color: var(--theme-caption-color);
|
||||
}
|
||||
&.selected {
|
||||
color: var(--theme-content-accent-color);
|
||||
background-color: var(--menu-bg-select);
|
||||
cursor: default;
|
||||
&:hover {
|
||||
color: var(--theme-caption-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -412,8 +412,8 @@
|
||||
}
|
||||
|
||||
&.highlightRows .antiTable-body__row {
|
||||
&.checking { background-color: var(--theme-table-bg-hover); }
|
||||
&.selected { background-color: var(--menu-bg-select); }
|
||||
&.checking { background-color: var(--highlight-select); } // --theme-table-bg-hover
|
||||
&.selected { background-color: var(--highlight-hover); } // --menu-bg-select
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -129,7 +129,11 @@
|
||||
transition: color .15s;
|
||||
pointer-events: none;
|
||||
}
|
||||
&.highlight { box-shadow: inset 0 0 0 1px var(--primary-bg-color); }
|
||||
&.highlight {
|
||||
box-shadow: inset 0 0 1px 1px var(--primary-bg-color);
|
||||
|
||||
&:hover { box-shadow: inset 0 0 1px 1px var(--primary-bg-hover); }
|
||||
}
|
||||
&:hover {
|
||||
color: var(--accent-color);
|
||||
transition-duration: 0;
|
||||
|
@ -64,7 +64,7 @@
|
||||
{#if subtitle}<span class="ac-header__description">{subtitle}</span>{/if}
|
||||
</div>
|
||||
</div>
|
||||
<div class="buttons-group xsmall-gap mr-4">
|
||||
<div class="buttons-group xsmall-gap">
|
||||
<slot name="commands" />
|
||||
<slot name="actions" />
|
||||
</div>
|
||||
@ -148,17 +148,18 @@
|
||||
flex-shrink: 0;
|
||||
min-width: 20rem;
|
||||
width: 20rem;
|
||||
border-left: 1px solid var(--divider-color);
|
||||
// background-color: var(--board-card-bg-color);
|
||||
|
||||
&::before {
|
||||
position: absolute;
|
||||
content: '';
|
||||
top: 1.5rem;
|
||||
bottom: 1.5rem;
|
||||
left: 0;
|
||||
width: 1px;
|
||||
background-color: var(--divider-color);
|
||||
}
|
||||
// &::before {
|
||||
// position: absolute;
|
||||
// content: '';
|
||||
// top: 1.5rem;
|
||||
// bottom: 1.5rem;
|
||||
// left: 0;
|
||||
// width: 1px;
|
||||
// background-color: var(--divider-color);
|
||||
// }
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -119,7 +119,7 @@
|
||||
position: fixed;
|
||||
background-color: transparent;
|
||||
|
||||
&.bg { background-color: var(--body-color); }
|
||||
&.bg { background-color: var(--board-bg-color); }
|
||||
.panel-container {
|
||||
padding: .5rem;
|
||||
width: 100%;
|
||||
|
@ -19,6 +19,7 @@
|
||||
export let padding: boolean = false
|
||||
export let autoscroll: boolean = false
|
||||
export let correctPadding: number = 0
|
||||
export let bottomStart: boolean = false
|
||||
|
||||
let mask: 'top' | 'bottom' | 'both' | 'none' = 'bottom'
|
||||
|
||||
@ -38,6 +39,7 @@
|
||||
let visibleEl: number | undefined = undefined
|
||||
let belowContent: number | undefined = undefined
|
||||
let scrolling: boolean = false
|
||||
let firstScroll: boolean = autoscroll
|
||||
|
||||
const checkBack = (): void => {
|
||||
if (divBox) {
|
||||
@ -149,6 +151,7 @@
|
||||
divBar.style.top = procTop * (divScroll.clientHeight - 4) + 2 + 'px'
|
||||
if (mask === 'none') divBar.style.visibility = 'hidden'
|
||||
else divBar.style.visibility = 'visible'
|
||||
if (divScroll.clientHeight >= divScroll.scrollHeight) divBar.style.visibility = 'hidden'
|
||||
}
|
||||
}
|
||||
|
||||
@ -205,8 +208,12 @@
|
||||
|
||||
let observer = new IntersectionObserver(() => checkFade(), { root: null, threshold: .1 })
|
||||
|
||||
$: if (autoscroll && belowContent && belowContent <= 5) scrolling = true
|
||||
$: if (scrolling && belowContent && belowContent > 5)
|
||||
$: if (firstScroll && divScroll && divScroll.clientHeight !== divScroll.scrollHeight) {
|
||||
divScroll.scrollTop = divScroll.scrollHeight - divScroll.clientHeight
|
||||
firstScroll = false
|
||||
}
|
||||
$: if (autoscroll && belowContent && belowContent <= 50) scrolling = true
|
||||
$: if (scrolling && belowContent && belowContent > 50)
|
||||
divScroll.scrollTop = divScroll.scrollHeight - divScroll.clientHeight
|
||||
|
||||
onMount(() => {
|
||||
@ -223,6 +230,7 @@
|
||||
if (divScroll && divBox) {
|
||||
const tempEl = divBox.querySelector('*') as HTMLElement
|
||||
if (tempEl) observer.observe(tempEl)
|
||||
if (scrolling) divScroll.scrollTop = divScroll.scrollHeight - divScroll.clientHeight
|
||||
checkFade()
|
||||
clearTHead()
|
||||
findTHeaders()
|
||||
@ -239,7 +247,7 @@
|
||||
</script>
|
||||
|
||||
<svelte:window on:resize={_resize} />
|
||||
<div class="scroller-container">
|
||||
<div class="scroller-container" class:bottomStart>
|
||||
<div
|
||||
bind:this={divScroll}
|
||||
bind:clientWidth={divWidth}
|
||||
@ -290,6 +298,14 @@
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
}
|
||||
.scroller-container.bottomStart {
|
||||
justify-content: flex-end;
|
||||
.scroll {
|
||||
flex-grow: 0;
|
||||
height: min-content;
|
||||
.box { height: min-content; }
|
||||
}
|
||||
}
|
||||
|
||||
.track {
|
||||
visibility: hidden;
|
||||
|
@ -23,7 +23,7 @@
|
||||
import TxView from './TxView.svelte'
|
||||
|
||||
export let object: Doc
|
||||
export let fullSize: boolean = false
|
||||
export let integrate: boolean = false
|
||||
export let showCommenInput: boolean = true
|
||||
export let transparent: boolean = false
|
||||
|
||||
@ -55,7 +55,7 @@
|
||||
|
||||
</script>
|
||||
|
||||
{#if fullSize || transparent}
|
||||
{#if !integrate || transparent}
|
||||
{#if transparent !== undefined && !transparent}
|
||||
<div class="ac-header short mirror-tool highlight">
|
||||
<div class="ac-header__wrap-title">
|
||||
@ -86,11 +86,11 @@
|
||||
{/if}
|
||||
</div>
|
||||
{:else}
|
||||
<Scroller autoscroll>
|
||||
<div class="p-10">
|
||||
<Scroller>
|
||||
<div class="p-10 bottom-highlight-select">
|
||||
<slot />
|
||||
</div>
|
||||
<div class="ac-header short mirror-tool">
|
||||
<div class="ac-header short mirror-tool mt-2">
|
||||
<div class="ac-header__wrap-title">
|
||||
<div class="flex-center icon"><IconActivity size={'small'} /></div>
|
||||
<span class="ac-header__title"><Label label={activity.string.Activity} /></span>
|
||||
|
@ -16,22 +16,19 @@
|
||||
<script lang="ts">
|
||||
import type { Card } from '@anticrm/board'
|
||||
import { Class, Ref } from '@anticrm/core'
|
||||
import { Panel } from '@anticrm/panel'
|
||||
import { getResource } from '@anticrm/platform'
|
||||
import { createQuery, getClient } from '@anticrm/presentation'
|
||||
import type { State } from '@anticrm/task'
|
||||
import task from '@anticrm/task'
|
||||
import { StyledTextBox } from '@anticrm/text-editor'
|
||||
import type { AnyComponent } from '@anticrm/ui'
|
||||
import { EditBox, Icon, Label, Scroller } from '@anticrm/ui'
|
||||
import { Panel } from '@anticrm/panel'
|
||||
import { createEventDispatcher, onMount } from 'svelte'
|
||||
import { EditBox, Icon, Label } from '@anticrm/ui'
|
||||
import { UpDownNavigator } from '@anticrm/view-resources'
|
||||
|
||||
import { createEventDispatcher, onMount } from 'svelte'
|
||||
import board from '../plugin'
|
||||
import { getCardActions } from '../utils/CardActionUtils'
|
||||
import { updateCard } from '../utils/CardUtils'
|
||||
import CardActions from './editor/CardActions.svelte'
|
||||
import CardActivity from './editor/CardActivity.svelte'
|
||||
import CardAttachments from './editor/CardAttachments.svelte'
|
||||
import CardDetails from './editor/CardDetails.svelte'
|
||||
|
||||
@ -76,8 +73,6 @@
|
||||
dispatch('open', { ignoreKeys: ['comments', 'number', 'title'] })
|
||||
})
|
||||
|
||||
let fullSize: boolean = false
|
||||
let rightSection: AnyComponent | undefined = undefined
|
||||
</script>
|
||||
|
||||
{#if object !== undefined}
|
||||
@ -85,9 +80,6 @@
|
||||
icon={board.icon.Card}
|
||||
title={object?.title}
|
||||
{object}
|
||||
{rightSection}
|
||||
{fullSize}
|
||||
position={'content'}
|
||||
on:close={() => dispatch('close')}
|
||||
>
|
||||
<svelte:fragment slot="navigate-actions">
|
||||
|
@ -1,11 +1,11 @@
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import { Ref, Space } from '@anticrm/core'
|
||||
import { Label, ActionIcon, IconClose, Button, EditBox } from '@anticrm/ui'
|
||||
import { ActionIcon, Button, IconClose, Label } from '@anticrm/ui'
|
||||
import TextArea from '@anticrm/ui/src/components/TextArea.svelte'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import board from '../../plugin'
|
||||
import CardsArchive from '../CardArchive.svelte'
|
||||
import ListArchive from '../ListArchive.svelte'
|
||||
import TextArea from '@anticrm/ui/src/components/TextArea.svelte'
|
||||
|
||||
export let space: Ref<Space>
|
||||
const dispatch = createEventDispatcher()
|
||||
|
@ -234,6 +234,7 @@
|
||||
window.removeEventListener('click', listener)
|
||||
})
|
||||
</script>
|
||||
|
||||
<div
|
||||
bind:this={div}
|
||||
class="{displayItems.length === 0 ? 'clear-mins' : 'buttons-group'} {kind === 'no-border' ? 'xsmall-gap' : 'xxsmall-gap'}"
|
||||
|
@ -105,6 +105,21 @@
|
||||
}
|
||||
Promise.all(promises)
|
||||
}
|
||||
|
||||
function click (ev: any) {
|
||||
if (ev.detail.presenter !== undefined && Array.isArray(channels)) {
|
||||
const channel = channels[0]
|
||||
if (channel !== undefined) {
|
||||
showPanel(
|
||||
view.component.EditDoc,
|
||||
channel.attachedTo,
|
||||
channel.attachedToClass,
|
||||
'content',
|
||||
ev.detail.presenter
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<ChannelsDropdown
|
||||
@ -118,4 +133,5 @@
|
||||
on:change={(e) => {
|
||||
if (editable) save(e.detail)
|
||||
}}
|
||||
on:click={click}
|
||||
/>
|
||||
|
@ -36,7 +36,7 @@
|
||||
view.component.EditDoc,
|
||||
channel.attachedTo,
|
||||
channel.attachedToClass,
|
||||
'full',
|
||||
'content',
|
||||
ev.detail.presenter
|
||||
)
|
||||
}
|
||||
|
@ -15,13 +15,13 @@
|
||||
-->
|
||||
<script lang="ts">
|
||||
import attachment from '@anticrm/attachment'
|
||||
import { combineName,getFirstName,getLastName,Person } from '@anticrm/contact'
|
||||
import { getCurrentAccount,Ref,Space } from '@anticrm/core'
|
||||
import { combineName, getFirstName, getLastName, Person } from '@anticrm/contact'
|
||||
import { getCurrentAccount, Ref, Space } from '@anticrm/core'
|
||||
import { getResource } from '@anticrm/platform'
|
||||
import { AttributeEditor,Avatar,createQuery,EditableAvatar,getClient } from '@anticrm/presentation'
|
||||
import setting,{ IntegrationType } from '@anticrm/setting'
|
||||
import { CircleButton,EditBox,IconActivity,Label } from '@anticrm/ui'
|
||||
import { afterUpdate,createEventDispatcher,onMount } from 'svelte'
|
||||
import { AttributeEditor, Avatar, createQuery, EditableAvatar, getClient } from '@anticrm/presentation'
|
||||
import setting, { IntegrationType } from '@anticrm/setting'
|
||||
import { CircleButton, EditBox, IconActivity, Label } from '@anticrm/ui'
|
||||
import { afterUpdate, createEventDispatcher, onMount } from 'svelte'
|
||||
import contact from '../plugin'
|
||||
import ChannelsEditor from './ChannelsEditor.svelte'
|
||||
|
||||
|
@ -102,7 +102,7 @@
|
||||
}}>
|
||||
{#if search !== ''}<div class="icon"><Icon icon={IconClose} size={'inline'} /></div>{/if}
|
||||
</div>
|
||||
<Button kind={'transparent'} size={'small'} icon={show ? IconView : IconViewHide} on:click={() => show = !show} />
|
||||
<Button kind={'transparent'} size={'small'} icon={show ? IconView : IconViewHide} on:click={() => { show = !show }} />
|
||||
{#if !hideAdd}<Button kind={'transparent'} size={'small'} icon={IconAdd} on:click={createTagElement} />{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -22,7 +22,7 @@
|
||||
import { createQuery, getClient } from '@anticrm/presentation'
|
||||
import setting, { Integration } from '@anticrm/setting'
|
||||
import type { NewTelegramMessage, SharedTelegramMessage, TelegramMessage } from '@anticrm/telegram'
|
||||
import { ActionIcon, Button, eventToHTMLElement, IconShare, ScrollBox, showPopup } from '@anticrm/ui'
|
||||
import { Button, eventToHTMLElement, IconShare, Tooltip, Scroller, showPopup } from '@anticrm/ui'
|
||||
import telegram from '../plugin'
|
||||
import Connect from './Connect.svelte'
|
||||
import TelegramIcon from './icons/Telegram.svelte'
|
||||
@ -171,7 +171,7 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="ac-header short mirror-tool divide">
|
||||
<div class="telegram-header">
|
||||
<div class="ac-header__wrap-title">
|
||||
<div class="flex-center icon"><TelegramIcon size={'small'} /></div>
|
||||
<div class="ac-header__wrap-description">
|
||||
@ -179,22 +179,23 @@
|
||||
<span class="ac-header__description">You and {formatName(object.name)}</span>
|
||||
</div>
|
||||
</div>
|
||||
<ActionIcon
|
||||
icon={IconShare}
|
||||
size={'medium'}
|
||||
label={telegram.string.Share}
|
||||
direction={'bottom'}
|
||||
action={async () => {
|
||||
selectable = !selectable
|
||||
}}
|
||||
/>
|
||||
<Tooltip label={telegram.string.Share}>
|
||||
<Button
|
||||
icon={IconShare}
|
||||
kind={'transparent'}
|
||||
size={'medium'}
|
||||
on:click={async () => {
|
||||
selectable = !selectable
|
||||
}}
|
||||
/>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<div class="h-full right-content">
|
||||
<ScrollBox vertical stretch autoscrollable>
|
||||
<div class="telegram-content" class:selectable>
|
||||
<Scroller bottomStart autoscroll>
|
||||
{#if messages && accounts}
|
||||
<Messages messages={convertMessages(messages, accounts)} {selectable} bind:selected />
|
||||
{/if}
|
||||
</ScrollBox>
|
||||
</Scroller>
|
||||
</div>
|
||||
|
||||
<div class="ref-input" class:selectable>
|
||||
@ -203,12 +204,12 @@
|
||||
<span>{selected.size} messages selected</span>
|
||||
<div class="flex">
|
||||
<div>
|
||||
<Button label={telegram.string.Cancel} size={'small'} on:click={clear} />
|
||||
<Button label={telegram.string.Cancel} size={'medium'} on:click={clear} />
|
||||
</div>
|
||||
<div class="ml-3">
|
||||
<Button
|
||||
label={telegram.string.PublishSelected}
|
||||
size={'small'}
|
||||
size={'medium'}
|
||||
kind={'primary'}
|
||||
disabled={!selected.size}
|
||||
on:click={share}
|
||||
@ -247,12 +248,23 @@
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.telegram-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
flex-wrap: nowrap;
|
||||
margin: 0 2.5rem;
|
||||
padding: 0;
|
||||
height: 4rem;
|
||||
min-height: 4rem;
|
||||
border-bottom: 1px solid var(--divider-color);
|
||||
}
|
||||
.icon {
|
||||
margin-right: 1rem;
|
||||
width: 2.25rem;
|
||||
height: 2.25rem;
|
||||
color: var(--primary-button-color);
|
||||
background-color: var(--primary-button-enabled);
|
||||
color: var(--white-color);
|
||||
background-color: var(--primary-bg-color);
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
@ -260,14 +272,18 @@
|
||||
padding: 0 2.5rem 1.5rem;
|
||||
|
||||
&.selectable {
|
||||
padding: 0.75rem 1.25rem 0.75rem 2.5rem;
|
||||
padding: 1rem 2.5rem;
|
||||
color: var(--theme-caption-color);
|
||||
background-color: var(--accent-bg-color);
|
||||
border-top: 1px solid var(--theme-card-divider);
|
||||
}
|
||||
}
|
||||
|
||||
.right-content {
|
||||
flex-grow: 1;
|
||||
padding: 1.5rem 1rem;
|
||||
.telegram-content {
|
||||
padding-bottom: 1.5rem;
|
||||
min-height: 0;
|
||||
height: 100%;
|
||||
|
||||
&.selectable { padding-bottom: 0; }
|
||||
}
|
||||
</style>
|
||||
|
@ -38,11 +38,12 @@
|
||||
<style lang="scss">
|
||||
.datetime-container {
|
||||
justify-self: center;
|
||||
margin: 0.3rem 0;
|
||||
margin: 0.3rem auto;
|
||||
padding: 0.25rem 0.75rem;
|
||||
width: fit-content;
|
||||
color: var(--theme-content-accent-color);
|
||||
background-color: var(--theme-menu-divider);
|
||||
border-radius: 1.25rem;
|
||||
user-select: text;
|
||||
}
|
||||
</style>
|
||||
|
@ -33,13 +33,17 @@
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="flex-between"
|
||||
class="message-row"
|
||||
class:selectable
|
||||
class:selected-row={selected}
|
||||
on:click={() => {
|
||||
dispatch('select', message)
|
||||
}}
|
||||
>
|
||||
<div class="flex-grow ml-6 flex" class:mr-6={!selectable} class:justify-end={!message.incoming}>
|
||||
<div class="check-box">
|
||||
{#if selectable}<CheckBox circle primary bind:checked={selected} />{/if}
|
||||
</div>
|
||||
<div class="message-container" class:out={!message.incoming}>
|
||||
<div class="message" class:outcoming={!message.incoming} class:selected>
|
||||
{#if showName}
|
||||
<div class="name" style="color: {getPlatformColorForText(message.sender)}">{formatName(message.sender)}</div>
|
||||
@ -55,22 +59,61 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{#if selectable}
|
||||
<div class="ml-4 mr-1"><CheckBox circle primary bind:checked={selected} /></div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.message-row {
|
||||
display: flex;
|
||||
justify-content: stretch;
|
||||
align-items: center;
|
||||
|
||||
&.selectable {
|
||||
cursor: pointer;
|
||||
|
||||
&:hover { background-color: var(--highlight-hover); }
|
||||
&.selected-row {
|
||||
background-color: var(--highlight-select);
|
||||
|
||||
&:hover { background-color: var(--highlight-hover); }
|
||||
}
|
||||
.message { cursor: pointer; }
|
||||
.selected {
|
||||
background-color: var(--primary-bg-color);
|
||||
|
||||
&:hover { background-color: var(--primary-bg-hover); }
|
||||
}
|
||||
}
|
||||
}
|
||||
.check-box {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
width: 2.5rem;
|
||||
min-width: 2.5rem;
|
||||
pointer-events: none;
|
||||
}
|
||||
.message-container {
|
||||
display: flex;
|
||||
justify-content: stretch;
|
||||
align-items: center;
|
||||
flex-grow: 1;
|
||||
margin-right: 2.5rem;
|
||||
padding: .25rem 0;
|
||||
|
||||
&.out { justify-content: flex-end; }
|
||||
}
|
||||
.message {
|
||||
padding: 0.5rem 0.75rem;
|
||||
padding: .5rem .75rem;
|
||||
max-width: 66%;
|
||||
width: fit-content;
|
||||
background-color: var(--theme-incoming-msg);
|
||||
border-radius: 0.75rem;
|
||||
border-radius: .75rem .75rem .75rem .25rem;
|
||||
overflow-wrap: anywhere;
|
||||
user-select: text;
|
||||
cursor: default;
|
||||
|
||||
&.outcoming {
|
||||
background-color: var(--theme-outcoming-msg);
|
||||
border-radius: .75rem .75rem .25rem .75rem;
|
||||
}
|
||||
.time {
|
||||
align-self: flex-end;
|
||||
@ -81,12 +124,4 @@
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
.selectable {
|
||||
margin: 0 0.25rem 0 0;
|
||||
cursor: pointer;
|
||||
.selected {
|
||||
background-color: var(--primary-button-enabled);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -15,7 +15,6 @@
|
||||
-->
|
||||
<script lang="ts">
|
||||
import type { SharedTelegramMessage } from '@anticrm/telegram'
|
||||
import { Grid } from '@anticrm/ui'
|
||||
import Message from './Message.svelte'
|
||||
import { Ref } from '@anticrm/core'
|
||||
import DateView from './Date.svelte'
|
||||
@ -49,21 +48,19 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<Grid column={1} rowGap={0.3}>
|
||||
{#if messages}
|
||||
{#each messages as message, i (message._id)}
|
||||
{#if isNewDate(messages, i)}
|
||||
<DateView {message} />
|
||||
{/if}
|
||||
<Message
|
||||
{message}
|
||||
{selectable}
|
||||
selected={selected.has(message._id)}
|
||||
showName={needName(messages, i)}
|
||||
on:select={() => {
|
||||
select(message._id)
|
||||
}}
|
||||
/>
|
||||
{/each}
|
||||
{/if}
|
||||
</Grid>
|
||||
{#if messages}
|
||||
{#each messages as message, i (message._id)}
|
||||
{#if isNewDate(messages, i)}
|
||||
<DateView {message} />
|
||||
{/if}
|
||||
<Message
|
||||
{message}
|
||||
{selectable}
|
||||
selected={selected.has(message._id)}
|
||||
showName={needName(messages, i)}
|
||||
on:select={() => {
|
||||
select(message._id)
|
||||
}}
|
||||
/>
|
||||
{/each}
|
||||
{/if}
|
||||
|
@ -19,7 +19,7 @@
|
||||
import CreateIssue from './CreateIssue.svelte'
|
||||
export let currentSpace: Ref<Space>
|
||||
|
||||
async function newIssue (target: EventTarget | null): Promise<void> {
|
||||
async function newIssue (): Promise<void> {
|
||||
showPopup(CreateIssue, { space: currentSpace }, 'top')
|
||||
}
|
||||
</script>
|
||||
@ -31,7 +31,7 @@
|
||||
label={tracker.string.NewIssue}
|
||||
justify={'left'}
|
||||
width={'100%'}
|
||||
on:click={() => newIssue(null)}
|
||||
on:click={() => newIssue()}
|
||||
/>
|
||||
</div>
|
||||
<Button icon={tracker.icon.Magnifier} on:click={async () => {}} />
|
||||
|
@ -25,9 +25,9 @@
|
||||
import { onMount } from 'svelte'
|
||||
import tracker from '../../plugin'
|
||||
import CreateIssue from '../CreateIssue.svelte'
|
||||
import AssigneePresenter from './AssigneePresenter.svelte'
|
||||
import AssigneePresenter from './AssigneePresenter.svelte'
|
||||
import IssuePresenter from './IssuePresenter.svelte'
|
||||
import PriorityPresenter from './PriorityPresenter.svelte'
|
||||
import PriorityPresenter from './PriorityPresenter.svelte'
|
||||
|
||||
export let currentSpace: Ref<Team>
|
||||
export let baseMenuClass: Ref<Class<Doc>> | undefined = undefined
|
||||
|
@ -15,27 +15,22 @@
|
||||
<script lang="ts">
|
||||
import contact from '@anticrm/contact'
|
||||
import { Class, Ref, SortingOrder, WithLookup } from '@anticrm/core'
|
||||
// import Card from '../Card.svelte'
|
||||
import { Panel } from '@anticrm/panel'
|
||||
import { createQuery, getClient, UserBox } from '@anticrm/presentation'
|
||||
import { StyledTextBox } from '@anticrm/text-editor'
|
||||
import type { Issue, IssueStatus, Team } from '@anticrm/tracker'
|
||||
import {
|
||||
AnyComponent,
|
||||
Button,
|
||||
EditBox,
|
||||
IconDownOutline,
|
||||
IconUpOutline,
|
||||
Label,
|
||||
Scroller,
|
||||
IconMoreH,
|
||||
IconEdit
|
||||
IconDownOutline, IconEdit, IconMoreH, IconUpOutline,
|
||||
Label
|
||||
} from '@anticrm/ui'
|
||||
import { createEventDispatcher, onMount } from 'svelte'
|
||||
import tracker from '../../plugin'
|
||||
// import Card from '../Card.svelte'
|
||||
import { Panel } from '@anticrm/panel'
|
||||
import IssuePresenter from './IssuePresenter.svelte'
|
||||
import StatusPresenter from './StatusPresenter.svelte'
|
||||
import PriorityPresenter from './PriorityPresenter.svelte'
|
||||
import StatusPresenter from './StatusPresenter.svelte'
|
||||
|
||||
export let _id: Ref<Issue>
|
||||
export let _class: Ref<Class<Issue>>
|
||||
@ -48,7 +43,6 @@
|
||||
let issue: Issue | undefined
|
||||
let currentTeam: Team | undefined
|
||||
let issueStatuses: WithLookup<IssueStatus>[] | undefined
|
||||
const fullSize: boolean = false
|
||||
let innerWidth: number
|
||||
|
||||
$: _id &&
|
||||
@ -96,10 +90,8 @@
|
||||
{#if issue !== undefined}
|
||||
<Panel
|
||||
object={issue}
|
||||
{fullSize}
|
||||
showHeader={false}
|
||||
isSubtitle={true}
|
||||
position={'content'}
|
||||
bind:innerWidth
|
||||
on:close={() => {
|
||||
dispatch('close')
|
||||
@ -267,14 +259,5 @@
|
||||
border-bottom: 1px solid var(--divider-color);
|
||||
margin: 0.75rem 1.5rem 1.25rem 0;
|
||||
}
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
border-left: 1px solid var(--divider-color);
|
||||
top: 1.125rem;
|
||||
bottom: 1.125rem;
|
||||
width: 0px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -13,27 +13,20 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { Class, Doc, FindOptions, Ref, getObjectValue, WithLookup } from '@anticrm/core'
|
||||
import contact, { Employee } from '@anticrm/contact'
|
||||
import { Class, Doc, FindOptions, getObjectValue, Ref, WithLookup } from '@anticrm/core'
|
||||
import { getClient } from '@anticrm/presentation'
|
||||
import { Issue, IssueStatus, Team } from '@anticrm/tracker'
|
||||
import {
|
||||
CheckBox,
|
||||
showPopup,
|
||||
Spinner,
|
||||
IconMoreV,
|
||||
Tooltip,
|
||||
Component,
|
||||
Button,
|
||||
IconAdd,
|
||||
eventToHTMLElement
|
||||
Button, CheckBox, Component, eventToHTMLElement, IconAdd, IconMoreV, showPopup,
|
||||
Spinner, Tooltip
|
||||
} from '@anticrm/ui'
|
||||
import { BuildModelKey } from '@anticrm/view'
|
||||
import { buildModel, LoadingProps, Menu, SelectDirection } from '@anticrm/view-resources'
|
||||
import { buildModel, LoadingProps, Menu } from '@anticrm/view-resources'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import CreateIssue from '../CreateIssue.svelte'
|
||||
import tracker from '../../plugin'
|
||||
import { IssuesGroupByKeys, issuesGroupPresenterMap, IssuesOrderByKeys, issuesSortOrderMap } from '../../utils'
|
||||
import CreateIssue from '../CreateIssue.svelte'
|
||||
|
||||
export let _class: Ref<Class<Doc>>
|
||||
export let currentSpace: Ref<Team> | undefined = undefined
|
||||
@ -97,7 +90,7 @@
|
||||
dispatch('row-focus', object)
|
||||
}
|
||||
|
||||
export const onElementSelected = (offset: 1 | -1 | 0, docObject?: Doc, dir?: SelectDirection) => {
|
||||
export const onElementSelected = (offset: 1 | -1 | 0, docObject?: Doc) => {
|
||||
let position =
|
||||
(docObject !== undefined ? combinedGroupedIssues.findIndex((x) => x._id === docObject?._id) : selectedRowIndex) ??
|
||||
-1
|
||||
|
@ -43,7 +43,7 @@
|
||||
|
||||
const listProvider = new ListSelectionProvider((offset: 1 | -1 | 0, of?: Doc, dir?: SelectDirection) => {
|
||||
if (dir === 'vertical') {
|
||||
issuesList.onElementSelected(offset, of, dir)
|
||||
issuesList.onElementSelected(offset, of)
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -29,11 +29,11 @@
|
||||
startDate: SortingOrder.Ascending
|
||||
},
|
||||
lookup: {
|
||||
lead: contact.class.Employee,
|
||||
lead: contact.class.Employee
|
||||
}
|
||||
}
|
||||
|
||||
async function showCreateDialog (ev: Event) {
|
||||
async function showCreateDialog () {
|
||||
showPopup(NewProject, { space, targetElement: null }, null)
|
||||
}
|
||||
</script>
|
||||
|
@ -39,6 +39,7 @@
|
||||
"@anticrm/ui": "~0.6.0",
|
||||
"@anticrm/task": "~0.6.0",
|
||||
"@anticrm/notification": "~0.6.0",
|
||||
"@anticrm/presentation": "~0.6.2"
|
||||
"@anticrm/presentation": "~0.6.2",
|
||||
"@anticrm/setting": "~0.6.1"
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@
|
||||
}
|
||||
})
|
||||
|
||||
let lastKey: KeyboardEvent | undefined
|
||||
// let lastKey: KeyboardEvent | undefined
|
||||
|
||||
async function updateActions (
|
||||
context: ViewContext,
|
||||
@ -68,7 +68,7 @@
|
||||
console.log('no keyboard because', targetTagName, evt.target)
|
||||
return
|
||||
}
|
||||
lastKey = evt
|
||||
// lastKey = evt
|
||||
for (const a of actions) {
|
||||
// TODO: Handle multiple keys here
|
||||
if (a.keyBinding?.find((it) => matchKey(evt, it)) !== undefined) {
|
||||
|
@ -14,11 +14,11 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import contact, { formatName } from '@anticrm/contact'
|
||||
import core, { Class, ClassifierKind, Doc, Hierarchy, Mixin, Obj, Ref } from '@anticrm/core'
|
||||
import contact, { ChannelProvider, formatName } from '@anticrm/contact'
|
||||
import core, { Class, ClassifierKind, Doc, getCurrentAccount, Hierarchy, Mixin, Obj, Ref, Space } from '@anticrm/core'
|
||||
import notification from '@anticrm/notification'
|
||||
import { Panel } from '@anticrm/panel'
|
||||
import { Asset, getResource, translate } from '@anticrm/platform'
|
||||
import { Asset, getResource, IntlString, translate } from '@anticrm/platform'
|
||||
import {
|
||||
AttributesBar,
|
||||
createQuery,
|
||||
@ -26,24 +26,25 @@
|
||||
getClient,
|
||||
KeyedAttribute
|
||||
} from '@anticrm/presentation'
|
||||
import { AnyComponent, Component, Label, PopupAlignment } from '@anticrm/ui'
|
||||
import setting, { IntegrationType } from '@anticrm/setting'
|
||||
import { AnyComponent, Button, Component, IconActivity } from '@anticrm/ui'
|
||||
import Tooltip from '@anticrm/ui/src/components/Tooltip.svelte'
|
||||
import view from '@anticrm/view'
|
||||
import { createEventDispatcher, onDestroy } from 'svelte'
|
||||
import { getCollectionCounter, getMixinStyle } from '../utils'
|
||||
import { getCollectionCounter } from '../utils'
|
||||
import ActionContext from './ActionContext.svelte'
|
||||
import UpDownNavigator from './UpDownNavigator.svelte'
|
||||
|
||||
export let _id: Ref<Doc>
|
||||
export let _class: Ref<Class<Doc>>
|
||||
export let rightSection: AnyComponent | undefined = undefined
|
||||
export let position: PopupAlignment | undefined = undefined
|
||||
// export let position: PopupAlignment | undefined = undefined
|
||||
|
||||
let lastId: Ref<Doc> = _id
|
||||
let lastClass: Ref<Class<Doc>> = _class
|
||||
let object: Doc
|
||||
let objectClass: Class<Doc>
|
||||
let parentClass: Ref<Class<Doc>>
|
||||
let fullSize: boolean = true
|
||||
|
||||
const client = getClient()
|
||||
const hierarchy = client.getHierarchy()
|
||||
@ -79,7 +80,7 @@
|
||||
let prevSelected = selectedClass
|
||||
|
||||
let keys: KeyedAttribute[] = []
|
||||
let collectionEditors: {key: KeyedAttribute, editor: AnyComponent} [] = []
|
||||
let collectionEditors: { key: KeyedAttribute; editor: AnyComponent }[] = []
|
||||
|
||||
let mixins: Mixin<Doc>[] = []
|
||||
|
||||
@ -118,15 +119,11 @@
|
||||
let ignoreMixins: Set<Ref<Mixin<Doc>>> = new Set<Ref<Mixin<Doc>>>()
|
||||
|
||||
async function updateKeys (): Promise<void> {
|
||||
const filtredKeys = getFiltredKeys(
|
||||
selectedClass ?? object._class,
|
||||
ignoreKeys,
|
||||
selectedClass !== objectClass._id ? objectClass._id : undefined
|
||||
)
|
||||
const filtredKeys = getFiltredKeys(selectedClass ?? object._class, ignoreKeys)
|
||||
keys = collectionsFilter(filtredKeys, false)
|
||||
|
||||
const collectionKeys = collectionsFilter(filtredKeys, true)
|
||||
const editors: {key: KeyedAttribute, editor: AnyComponent}[] = []
|
||||
const editors: { key: KeyedAttribute; editor: AnyComponent }[] = []
|
||||
for (const k of collectionKeys) {
|
||||
const editor = await getCollectionEditor(k)
|
||||
editors.push({ key: k, editor })
|
||||
@ -245,20 +242,64 @@
|
||||
}
|
||||
let panelWidth: number = 0
|
||||
let innerWidth: number = 0
|
||||
|
||||
const accountId = getCurrentAccount()._id
|
||||
let channelProviders: ChannelProvider[] | undefined
|
||||
let currentProviders: ChannelProvider[] | undefined
|
||||
let integrations: Set<Ref<IntegrationType>> = new Set<Ref<IntegrationType>>()
|
||||
let displayedIntegrations:
|
||||
| {
|
||||
icon: Asset | undefined
|
||||
label: IntlString
|
||||
presenter: AnyComponent | undefined
|
||||
value: string
|
||||
}[]
|
||||
| undefined = []
|
||||
|
||||
client.findAll(contact.class.ChannelProvider, {}).then((res) => {
|
||||
channelProviders = res
|
||||
})
|
||||
const settingsQuery = createQuery()
|
||||
$: settingsQuery.query(
|
||||
setting.class.Integration,
|
||||
{ space: accountId as string as Ref<Space>, disabled: false },
|
||||
(res) => {
|
||||
integrations = new Set(res.map((p) => p.type))
|
||||
}
|
||||
)
|
||||
const channelsQuery = createQuery()
|
||||
$: _id &&
|
||||
integrations &&
|
||||
channelProviders &&
|
||||
channelsQuery.query(contact.class.Channel, { attachedTo: _id }, (res) => {
|
||||
const channels = res
|
||||
currentProviders = channelProviders?.filter((provider) =>
|
||||
provider.integrationType ? integrations.has(provider.integrationType as Ref<IntegrationType>) : false
|
||||
)
|
||||
displayedIntegrations = []
|
||||
currentProviders?.forEach((provider) => {
|
||||
displayedIntegrations?.push({
|
||||
icon: provider.icon,
|
||||
label: provider.label,
|
||||
presenter: provider.presenter,
|
||||
value: channels.filter((ch) => ch.provider === provider._id)[0].value
|
||||
})
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
<ActionContext context={{
|
||||
mode: 'editor'
|
||||
}}/>
|
||||
<ActionContext
|
||||
context={{
|
||||
mode: 'editor'
|
||||
}}
|
||||
/>
|
||||
|
||||
{#if object !== undefined && title !== undefined}
|
||||
<Panel
|
||||
{icon}
|
||||
{title}
|
||||
{rightSection}
|
||||
{fullSize}
|
||||
{object}
|
||||
{position}
|
||||
bind:panelWidth
|
||||
bind:innerWidth
|
||||
on:update={(ev) => _update(ev.detail)}
|
||||
@ -267,7 +308,7 @@
|
||||
}}
|
||||
>
|
||||
<svelte:fragment slot="navigate-actions">
|
||||
<UpDownNavigator element={object}/>
|
||||
<UpDownNavigator element={object} />
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="subtitle">
|
||||
{#if !headerLoading}
|
||||
@ -289,6 +330,33 @@
|
||||
</div>
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="actions">
|
||||
{#if displayedIntegrations && displayedIntegrations.length > 0}
|
||||
<div class="actions-divider" />
|
||||
{#each displayedIntegrations as pr}
|
||||
<Tooltip label={pr.label}>
|
||||
<Button
|
||||
icon={pr.icon}
|
||||
size={'medium'}
|
||||
kind={'transparent'}
|
||||
highlight={rightSection === pr.presenter}
|
||||
on:click={() => {
|
||||
if (rightSection !== pr.presenter) rightSection = pr.presenter
|
||||
}}
|
||||
/>
|
||||
</Tooltip>
|
||||
{/each}
|
||||
<Button
|
||||
icon={IconActivity}
|
||||
size={'medium'}
|
||||
kind={'transparent'}
|
||||
highlight={!rightSection}
|
||||
on:click={() => {
|
||||
if (rightSection) rightSection = undefined
|
||||
}}
|
||||
/>
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
<div class="main-editor">
|
||||
{#if mainEditor}
|
||||
<Component
|
||||
@ -301,36 +369,11 @@
|
||||
getMixins()
|
||||
}}
|
||||
on:click={(ev) => {
|
||||
fullSize = true
|
||||
rightSection = ev.detail.presenter
|
||||
}}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
{#if mixins.length > 0}
|
||||
<div class="mixin-container">
|
||||
<div
|
||||
class="mixin-selector"
|
||||
style={getMixinStyle(objectClass._id, selectedClass === objectClass._id)}
|
||||
on:click={() => {
|
||||
selectedClass = objectClass._id
|
||||
}}
|
||||
>
|
||||
<Label label={objectClass.label} />
|
||||
</div>
|
||||
{#each mixins as mixin}
|
||||
<div
|
||||
class="mixin-selector"
|
||||
style={getMixinStyle(mixin._id, selectedClass === mixin._id)}
|
||||
on:click={() => {
|
||||
selectedClass = mixin._id
|
||||
}}
|
||||
>
|
||||
<Label label={mixin.label} />
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
{#each collectionEditors as collection}
|
||||
{#if collection.editor}
|
||||
<div class="mt-14">
|
||||
@ -345,7 +388,7 @@
|
||||
[collection.key.key]: getCollectionCounter(hierarchy, object, collection.key)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{/each}
|
||||
</Panel>
|
||||
@ -357,26 +400,12 @@
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
}
|
||||
.mixin-container {
|
||||
margin-top: 2rem;
|
||||
display: flex;
|
||||
.mixin-selector {
|
||||
margin-left: 0.5rem;
|
||||
cursor: pointer;
|
||||
height: 1.5rem;
|
||||
min-width: 5.25rem;
|
||||
|
||||
border-radius: 0.5rem;
|
||||
|
||||
font-weight: 500;
|
||||
font-size: 0.625rem;
|
||||
|
||||
text-transform: uppercase;
|
||||
color: var(--theme-caption-color);
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.actions-divider {
|
||||
margin: 0 0.25rem;
|
||||
min-width: 1px;
|
||||
width: 1px;
|
||||
height: 1.5rem;
|
||||
background-color: var(--divider-color);
|
||||
}
|
||||
</style>
|
||||
|
@ -38,7 +38,7 @@
|
||||
actions = result.map(a => ({
|
||||
label: a.label,
|
||||
icon: a.icon as Asset,
|
||||
action: async (props:any, evt: Event) => { invokeAction(evt, a.action) }
|
||||
action: async (_:any, evt: Event) => { invokeAction(evt, a.action) }
|
||||
}))
|
||||
loaded = 1
|
||||
})
|
||||
|
@ -21,7 +21,6 @@
|
||||
import { CheckBox, Component, IconDown, IconUp, Label, Loading, showPopup, Spinner } from '@anticrm/ui'
|
||||
import { BuildModelKey } from '@anticrm/view'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import { SelectDirection } from '../selection'
|
||||
import { buildModel, LoadingProps } from '../utils'
|
||||
import Menu from './Menu.svelte'
|
||||
|
||||
@ -128,7 +127,7 @@
|
||||
dispatch('row-focus', object)
|
||||
}
|
||||
|
||||
export function select (offset: 1 | -1 | 0, of?: Doc, dir?: SelectDirection): void {
|
||||
export function select (offset: 1 | -1 | 0, of?: Doc): void {
|
||||
let pos = (((of !== undefined) ? objects.findIndex(it => it._id === of._id) : selection) ?? -1)
|
||||
pos += offset
|
||||
if (pos < 0) {
|
||||
|
@ -36,7 +36,7 @@
|
||||
(offset: 1 | -1 | 0, of?: Doc, dir?: SelectDirection) => {
|
||||
if (dir === 'vertical') {
|
||||
// Select next
|
||||
table.select(offset, of, dir)
|
||||
table.select(offset, of)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
@ -303,7 +303,10 @@
|
||||
if (window.innerWidth < 1100 && !navFloat) {
|
||||
visibileNav = false
|
||||
navFloat = true
|
||||
} else if (window.innerWidth >= 1100 && navFloat) navFloat = false
|
||||
} else if (window.innerWidth >= 1100 && navFloat) {
|
||||
navFloat = false
|
||||
visibileNav = true
|
||||
}
|
||||
}
|
||||
const checkOnHide = (): void => {
|
||||
if (visibileNav && navFloat) visibileNav = false
|
||||
|
@ -53,7 +53,7 @@ test.describe('recruit tests', () => {
|
||||
|
||||
await page.click('text=Candidates')
|
||||
await page.click('text=Andrey P.')
|
||||
await page.locator('.mixin-selector').locator('text="Candidate"').click()
|
||||
// await page.locator('.mixin-selector').locator('text="Candidate"').click()
|
||||
|
||||
// Click on Add button
|
||||
await page.click('.applications-container .flex-row-center .flex-center')
|
||||
|
Loading…
Reference in New Issue
Block a user