mirror of
https://github.com/hcengineering/platform.git
synced 2024-11-22 21:50:34 +03:00
Update EditStatuses, PDFViewer. Add full size for Panel. (#1797)
Signed-off-by: Alexander Platov <sas_lord@mail.ru>
This commit is contained in:
parent
8abadca450
commit
d277134032
@ -32,9 +32,18 @@
|
|||||||
export let isSub: boolean = true
|
export let isSub: boolean = true
|
||||||
export let isAside: boolean = true
|
export let isAside: boolean = true
|
||||||
export let isCustomAttr: boolean = true
|
export let isCustomAttr: boolean = true
|
||||||
|
export let isFullSize: boolean = false
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Panel bind:isAside isHeader={$$slots.header || isHeader} bind:panelWidth bind:innerWidth on:close>
|
<Panel
|
||||||
|
bind:isAside
|
||||||
|
bind:isFullSize
|
||||||
|
isHeader={$$slots.header || isHeader}
|
||||||
|
bind:panelWidth
|
||||||
|
bind:innerWidth
|
||||||
|
on:close
|
||||||
|
on:fullsize
|
||||||
|
>
|
||||||
<svelte:fragment slot="title">
|
<svelte:fragment slot="title">
|
||||||
<div class="popupPanel-title__content-container antiTitle">
|
<div class="popupPanel-title__content-container antiTitle">
|
||||||
{#if $$slots.navigator}
|
{#if $$slots.navigator}
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
"Cancel": "Отменить",
|
"Cancel": "Отменить",
|
||||||
"Ok": "Ок",
|
"Ok": "Ок",
|
||||||
"Save": "Сохранить",
|
"Save": "Сохранить",
|
||||||
"Download": "Загрузить",
|
"Download": "Скачать",
|
||||||
"Close": "Закрыть",
|
"Close": "Закрыть",
|
||||||
"NotSelected": "Не выбрано",
|
"NotSelected": "Не выбрано",
|
||||||
"Deselect": "Снять выделение",
|
"Deselect": "Снять выделение",
|
||||||
|
@ -13,43 +13,88 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Button, CircleButton, IconClose, ActionIcon } from '@anticrm/ui'
|
import { Button, Tooltip, Panel } from '@anticrm/ui'
|
||||||
|
import type { PopupOptions } from '@anticrm/ui'
|
||||||
import { createEventDispatcher } from 'svelte'
|
import { createEventDispatcher } from 'svelte'
|
||||||
import presentation from '..'
|
import presentation from '..'
|
||||||
import { getFileUrl } from '../utils'
|
import { getFileUrl } from '../utils'
|
||||||
import Avatar from './Avatar.svelte'
|
|
||||||
import MaximizeH from './icons/MaximizeH.svelte'
|
import MaximizeH from './icons/MaximizeH.svelte'
|
||||||
import MaximizeV from './icons/MaximizeV.svelte'
|
import MaximizeV from './icons/MaximizeV.svelte'
|
||||||
import MaximizeO from './icons/MaximizeO.svelte'
|
import MaximizeO from './icons/MaximizeO.svelte'
|
||||||
|
import Download from './icons/Download.svelte'
|
||||||
|
|
||||||
export let file: string
|
export let file: string
|
||||||
export let name: string
|
export let name: string
|
||||||
export let contentType: string | undefined
|
export let contentType: string | undefined
|
||||||
|
export let options: PopupOptions
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
let imgView: 'img-horizontal-fit' | 'img-vertical-fit' | 'img-original-fit' = 'img-horizontal-fit'
|
let imgView: 'img-horizontal-fit' | 'img-vertical-fit' | 'img-original-fit' = 'img-horizontal-fit'
|
||||||
|
|
||||||
|
function iconLabel (name: string): string {
|
||||||
|
const parts = name.split('.')
|
||||||
|
const ext = parts[parts.length - 1]
|
||||||
|
return ext.substring(0, 4).toUpperCase()
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div
|
<Panel
|
||||||
class="antiOverlay"
|
isHeader={false}
|
||||||
on:click={() => {
|
isAside={options && options.fullSize}
|
||||||
|
isFullSize
|
||||||
|
on:fullsize
|
||||||
|
on:close={() => {
|
||||||
dispatch('close')
|
dispatch('close')
|
||||||
}}
|
}}
|
||||||
/>
|
>
|
||||||
<div class="antiDialogs antiComponent pdfviewer-container">
|
<svelte:fragment slot="title">
|
||||||
<div class="ac-header short mirror">
|
<div class="antiTitle icon-wrapper">
|
||||||
<div class="ac-header__wrap-title">
|
<div class="wrapped-icon">
|
||||||
<div class="ac-header__icon"><Avatar size={'medium'} /></div>
|
<div class="flex-center icon">
|
||||||
<span class="ac-header__title">{name}</span>
|
{iconLabel(name)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<span class="wrapped-title">{name}</span>
|
||||||
</div>
|
</div>
|
||||||
<ActionIcon
|
</svelte:fragment>
|
||||||
icon={IconClose}
|
|
||||||
size={'medium'}
|
<svelte:fragment slot="utils">
|
||||||
action={(_) => {
|
{#if contentType && contentType.startsWith('image/')}
|
||||||
dispatch('close')
|
<Button
|
||||||
}}
|
icon={MaximizeH}
|
||||||
/>
|
kind={'transparent'}
|
||||||
</div>
|
shape={'circle'}
|
||||||
|
on:click={() => {
|
||||||
|
imgView = 'img-horizontal-fit'
|
||||||
|
}}
|
||||||
|
selected={imgView === 'img-horizontal-fit'}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
icon={MaximizeV}
|
||||||
|
kind={'transparent'}
|
||||||
|
shape={'circle'}
|
||||||
|
on:click={() => {
|
||||||
|
imgView = 'img-vertical-fit'
|
||||||
|
}}
|
||||||
|
selected={imgView === 'img-vertical-fit'}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
icon={MaximizeO}
|
||||||
|
kind={'transparent'}
|
||||||
|
shape={'circle'}
|
||||||
|
on:click={() => {
|
||||||
|
imgView = 'img-original-fit'
|
||||||
|
}}
|
||||||
|
selected={imgView === 'img-original-fit'}
|
||||||
|
/>
|
||||||
|
<div class="buttons-divider" />
|
||||||
|
{/if}
|
||||||
|
<a class="no-line" href={getFileUrl(file)} download={name}>
|
||||||
|
<Tooltip label={presentation.string.Download}>
|
||||||
|
<Button icon={Download} kind={'transparent'} shape={'circle'} />
|
||||||
|
</Tooltip>
|
||||||
|
</a>
|
||||||
|
</svelte:fragment>
|
||||||
|
|
||||||
{#if contentType && contentType.startsWith('image/')}
|
{#if contentType && contentType.startsWith('image/')}
|
||||||
<div class="pdfviewer-content">
|
<div class="pdfviewer-content">
|
||||||
@ -58,55 +103,26 @@
|
|||||||
{:else}
|
{:else}
|
||||||
<iframe class="pdfviewer-content" src={getFileUrl(file)} title="" />
|
<iframe class="pdfviewer-content" src={getFileUrl(file)} title="" />
|
||||||
{/if}
|
{/if}
|
||||||
|
</Panel>
|
||||||
<div class="pdfviewer-footer">
|
|
||||||
<div class="flex-row-reverse">
|
|
||||||
<a class="no-line ml-4" href={getFileUrl(file)} download={name}
|
|
||||||
><Button label={presentation.string.Download} kind={'primary'} /></a
|
|
||||||
>
|
|
||||||
<Button
|
|
||||||
label={presentation.string.Close}
|
|
||||||
on:click={() => {
|
|
||||||
dispatch('close')
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{#if contentType && contentType.startsWith('image/')}
|
|
||||||
<div class="img-nav">
|
|
||||||
<CircleButton
|
|
||||||
icon={MaximizeH}
|
|
||||||
on:click={() => {
|
|
||||||
imgView = 'img-horizontal-fit'
|
|
||||||
}}
|
|
||||||
selected={imgView === 'img-horizontal-fit'}
|
|
||||||
/>
|
|
||||||
<CircleButton
|
|
||||||
icon={MaximizeV}
|
|
||||||
on:click={() => {
|
|
||||||
imgView = 'img-vertical-fit'
|
|
||||||
}}
|
|
||||||
selected={imgView === 'img-vertical-fit'}
|
|
||||||
/>
|
|
||||||
<CircleButton
|
|
||||||
icon={MaximizeO}
|
|
||||||
on:click={() => {
|
|
||||||
imgView = 'img-original-fit'
|
|
||||||
}}
|
|
||||||
selected={imgView === 'img-original-fit'}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.pdfviewer-container {
|
.icon {
|
||||||
left: 40%;
|
position: relative;
|
||||||
|
flex-shrink: 0;
|
||||||
|
width: 2rem;
|
||||||
|
height: 2rem;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 0.625rem;
|
||||||
|
color: var(--white-color);
|
||||||
|
background-color: var(--primary-bg-color);
|
||||||
|
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.pdfviewer-content {
|
.pdfviewer-content {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
margin: 0 1.5rem;
|
margin: 1.5rem;
|
||||||
border-style: none;
|
border-style: none;
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
background-color: var(--theme-menu-color);
|
background-color: var(--theme-menu-color);
|
||||||
@ -124,14 +140,12 @@
|
|||||||
.img-vertical-fit {
|
.img-vertical-fit {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
.pdfviewer-footer {
|
.pdfviewer-header {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
flex-direction: row-reverse;
|
flex-direction: row-reverse;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 0 2.25rem;
|
|
||||||
height: 5.25rem;
|
|
||||||
}
|
}
|
||||||
.img-nav {
|
.img-nav {
|
||||||
display: grid;
|
display: grid;
|
||||||
|
28
packages/presentation/src/components/icons/Download.svelte
Normal file
28
packages/presentation/src/components/icons/Download.svelte
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<!--
|
||||||
|
// Copyright © 2020, 2021 Anticrm Platform Contributors.
|
||||||
|
// Copyright © 2021 Hardcore Engineering Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License. You may
|
||||||
|
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
//
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
-->
|
||||||
|
<script lang="ts">
|
||||||
|
export let size: 'small' | 'medium' | 'large'
|
||||||
|
const fill: string = 'currentColor'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svg class="svg-{size}" {fill} viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path
|
||||||
|
d="M12,8.8c-0.2,0-0.4-0.1-0.5-0.4c-0.2-0.5-0.6-1-1-1.3v1.6c0,0.1,0.1,0.1,0.1,0.2c0.2,0.5,0.7,1,1.4,1c0.8,0,1.5,0.7,1.5,1.5 s-0.7,1.5-1.5,1.5H8H4c-0.8,0-1.5-0.7-1.5-1.5S3.2,9.8,4,9.8c0.7,0,1.2-0.5,1.4-1c0-0.1,0.1-0.1,0.1-0.2V7.1c-0.4,0.4-0.8,0.8-1,1.3 C4.4,8.7,4.2,8.8,4,8.8c-1.4,0-2.5,1.1-2.5,2.5s1.1,2.5,2.5,2.5h4h4c1.4,0,2.5-1.1,2.5-2.5S13.4,8.8,12,8.8z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M7.5,3.2v5.5c0,0.3,0.2,0.5,0.5,0.5c0.3,0,0.5-0.2,0.5-0.5V3.2L10.3,5L11,4.3L8.4,1.6L8,1.3L7.6,1.6L8,2l0,0L7.6,1.6L5,4.3 L5.7,5L7.5,3.2z"
|
||||||
|
/>
|
||||||
|
</svg>
|
@ -356,6 +356,7 @@ input.search {
|
|||||||
.mb-3 { margin-bottom: .75rem; }
|
.mb-3 { margin-bottom: .75rem; }
|
||||||
.mb-4 { margin-bottom: 1rem; }
|
.mb-4 { margin-bottom: 1rem; }
|
||||||
.mb-6 { margin-bottom: 1.5rem; }
|
.mb-6 { margin-bottom: 1.5rem; }
|
||||||
|
.mb-10 { margin-bottom: 2.5rem; }
|
||||||
.mx-1 { margin: 0 .25rem; }
|
.mx-1 { margin: 0 .25rem; }
|
||||||
.mx-2 { margin: 0 .5rem; }
|
.mx-2 { margin: 0 .5rem; }
|
||||||
.mx-3 { margin: 0 .75rem; }
|
.mx-3 { margin: 0 .75rem; }
|
||||||
|
@ -432,8 +432,7 @@
|
|||||||
|
|
||||||
// THead background-color in Tooltip and Popups
|
// THead background-color in Tooltip and Popups
|
||||||
.popup-tooltip .antiTable .scroller-thead,
|
.popup-tooltip .antiTable .scroller-thead,
|
||||||
.popup .antiTable .scroller-thead,
|
.popup .antiTable .scroller-thead { background-color: var(--accent-bg-color); }
|
||||||
.antiDialogs .antiTable .scroller-thead { background-color: var(--accent-bg-color); }
|
|
||||||
|
|
||||||
// Hide row menu in Tooltip
|
// Hide row menu in Tooltip
|
||||||
.popup-tooltip .antiTable .antiTable-body__row:hover .antiTable-cells__firstCell .antiTable-cells__firstCell-menuRow { visibility: hidden; }
|
.popup-tooltip .antiTable .antiTable-body__row:hover .antiTable-cells__firstCell .antiTable-cells__firstCell-menuRow { visibility: hidden; }
|
||||||
|
@ -13,51 +13,6 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
/* Dialogs */
|
|
||||||
.antiDialogs {
|
|
||||||
overflow: hidden;
|
|
||||||
position: fixed;
|
|
||||||
top: 32px;
|
|
||||||
bottom: 1.25rem;
|
|
||||||
left: 50%;
|
|
||||||
right: 1rem;
|
|
||||||
|
|
||||||
height: calc(100% - 32px - 1.25rem);
|
|
||||||
background: var(--popup-bg-color);
|
|
||||||
border-radius: .5rem;
|
|
||||||
|
|
||||||
&.fullSize {
|
|
||||||
flex-direction: row;
|
|
||||||
left: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ac-header.divide { border-bottom: 1px solid var(--theme-card-divider); }
|
|
||||||
|
|
||||||
.ad-section-50 {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
flex-basis: 50%;
|
|
||||||
min-height: 0;
|
|
||||||
width: 50%;
|
|
||||||
|
|
||||||
&.divide { border-right: 1px solid var(--theme-card-divider); }
|
|
||||||
}
|
|
||||||
|
|
||||||
.ad-tools {
|
|
||||||
position: absolute;
|
|
||||||
display: flex;
|
|
||||||
top: 1.375rem;
|
|
||||||
right: 2rem;
|
|
||||||
}
|
|
||||||
.tool {
|
|
||||||
margin-left: 1rem;
|
|
||||||
color: var(--theme-content-accent-color);
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
&:hover { color: var(--theme-caption-color); }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Overlays */
|
/* Overlays */
|
||||||
.antiOverlay {
|
.antiOverlay {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
|
@ -212,3 +212,24 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Full size state
|
||||||
|
.panel-instance.fullsize .panel-container {
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
.panel-instance.fullsize .panel-container .popupPanel,
|
||||||
|
.popup.fullsize .popupPanel {
|
||||||
|
border-radius: 0;
|
||||||
|
box-shadow: none !important;
|
||||||
|
|
||||||
|
.popupPanel-title,
|
||||||
|
.popupPanel-body {
|
||||||
|
border-radius: 0;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
.popupPanel-title { border-bottom: 1px solid var(--divider-color); }
|
||||||
|
}
|
||||||
|
.panel-instance.fullsize,
|
||||||
|
.popup.fullsize {
|
||||||
|
transition-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19) !important;
|
||||||
|
}
|
||||||
|
@ -14,12 +14,13 @@
|
|||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { createEventDispatcher } from 'svelte'
|
import { createEventDispatcher } from 'svelte'
|
||||||
import { Button, IconClose, IconDetails } from '..'
|
import { Button, IconClose, IconDetails, IconExpand } from '..'
|
||||||
|
|
||||||
export let innerWidth: number = 0
|
export let innerWidth: number = 0
|
||||||
export let panelWidth: number = 0
|
export let panelWidth: number = 0
|
||||||
export let isHeader: boolean = true
|
export let isHeader: boolean = true
|
||||||
export let isAside: boolean = true
|
export let isAside: boolean = true
|
||||||
|
export let isFullSize: boolean = false
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
|
|
||||||
@ -30,8 +31,13 @@
|
|||||||
asideFloat = false
|
asideFloat = false
|
||||||
asideShown = false
|
asideShown = false
|
||||||
}
|
}
|
||||||
|
let docWidth: number
|
||||||
|
let fullSize: boolean = false
|
||||||
|
$: if (docWidth <= 900 && !fullSize) fullSize = true
|
||||||
|
$: if (docWidth > 900 && fullSize) fullSize = false
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<svelte:window bind:innerWidth={docWidth} />
|
||||||
<div class="popupPanel" bind:clientWidth={panelWidth}>
|
<div class="popupPanel" bind:clientWidth={panelWidth}>
|
||||||
<div class="popupPanel-title">
|
<div class="popupPanel-title">
|
||||||
<Button
|
<Button
|
||||||
@ -45,8 +51,8 @@
|
|||||||
<div class="popupPanel-title__content"><slot name="title" /></div>
|
<div class="popupPanel-title__content"><slot name="title" /></div>
|
||||||
<div class="buttons-group xsmall-gap">
|
<div class="buttons-group xsmall-gap">
|
||||||
<slot name="utils" />
|
<slot name="utils" />
|
||||||
|
{#if $$slots.utils}<div class="buttons-divider" />{/if}
|
||||||
{#if asideFloat && $$slots.aside && isAside}
|
{#if asideFloat && $$slots.aside && isAside}
|
||||||
{#if $$slots.utils}<div class="buttons-divider" />{/if}
|
|
||||||
<Button
|
<Button
|
||||||
icon={IconDetails}
|
icon={IconDetails}
|
||||||
kind={'transparent'}
|
kind={'transparent'}
|
||||||
@ -57,6 +63,19 @@
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
{#if isFullSize}
|
||||||
|
<Button
|
||||||
|
icon={IconExpand}
|
||||||
|
kind={'transparent'}
|
||||||
|
size={'medium'}
|
||||||
|
selected={fullSize}
|
||||||
|
disabled={docWidth <= 900}
|
||||||
|
on:click={() => {
|
||||||
|
fullSize = !fullSize
|
||||||
|
dispatch('fullsize')
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="popupPanel-body" class:asideShown>
|
<div class="popupPanel-body" class:asideShown>
|
||||||
|
@ -15,8 +15,9 @@
|
|||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { getResource } from '@anticrm/platform'
|
import { getResource } from '@anticrm/platform'
|
||||||
import { afterUpdate } from 'svelte'
|
import { afterUpdate, onMount } from 'svelte'
|
||||||
import { AnySvelteComponent, Spinner } from '..'
|
import { Spinner } from '..'
|
||||||
|
import type { AnySvelteComponent, PopupOptions } from '..'
|
||||||
import { closePanel, PanelProps, panelstore } from '../panelup'
|
import { closePanel, PanelProps, panelstore } from '../panelup'
|
||||||
import { fitPopupElement, popupstore } from '../popups'
|
import { fitPopupElement, popupstore } from '../popups'
|
||||||
|
|
||||||
@ -24,11 +25,25 @@
|
|||||||
|
|
||||||
let modalHTML: HTMLElement
|
let modalHTML: HTMLElement
|
||||||
let componentInstance: any
|
let componentInstance: any
|
||||||
|
let docWidth: number
|
||||||
|
let docSize: boolean = false
|
||||||
|
let fullSize: boolean = false
|
||||||
|
|
||||||
let options: {
|
let options: PopupOptions = {
|
||||||
show: boolean
|
props: {
|
||||||
direction: string
|
top: '',
|
||||||
} = { show: false, direction: 'bottom' }
|
bottom: '',
|
||||||
|
left: '',
|
||||||
|
right: '',
|
||||||
|
width: '',
|
||||||
|
height: '',
|
||||||
|
maxWidth: '',
|
||||||
|
maxHeight: '',
|
||||||
|
minWidth: ''
|
||||||
|
},
|
||||||
|
showOverlay: false,
|
||||||
|
direction: 'bottom'
|
||||||
|
}
|
||||||
|
|
||||||
let component: AnySvelteComponent
|
let component: AnySvelteComponent
|
||||||
|
|
||||||
@ -62,7 +77,17 @@
|
|||||||
|
|
||||||
const fitPopup = (props: PanelProps, contentPanel: HTMLElement): void => {
|
const fitPopup = (props: PanelProps, contentPanel: HTMLElement): void => {
|
||||||
if (modalHTML) {
|
if (modalHTML) {
|
||||||
options = fitPopupElement(modalHTML, props.element, contentPanel)
|
if ((fullSize || docSize) && (props.element === 'float' || props.element === 'content')) {
|
||||||
|
options = fitPopupElement(modalHTML, 'full')
|
||||||
|
options.props.width = '100vw'
|
||||||
|
options.props.maxHeight = 'max-content'
|
||||||
|
options.showOverlay = false
|
||||||
|
modalHTML.classList.add('fullsize')
|
||||||
|
} else {
|
||||||
|
options = fitPopupElement(modalHTML, props.element, contentPanel)
|
||||||
|
modalHTML.classList.remove('fullsize')
|
||||||
|
}
|
||||||
|
options.fullSize = fullSize
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,9 +107,16 @@
|
|||||||
export function fitPopupInstance (): void {
|
export function fitPopupInstance (): void {
|
||||||
if (props) fitPopup(props, contentPanel)
|
if (props) fitPopup(props, contentPanel)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
if (props) fitPopup(props, contentPanel)
|
||||||
|
})
|
||||||
|
$: if (docWidth <= 900 && !docSize) docSize = true
|
||||||
|
$: if (docWidth > 900 && docSize) docSize = false
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:window
|
<svelte:window
|
||||||
|
bind:innerWidth={docWidth}
|
||||||
on:resize={() => {
|
on:resize={() => {
|
||||||
if (props) fitPopup(props, contentPanel)
|
if (props) fitPopup(props, contentPanel)
|
||||||
}}
|
}}
|
||||||
@ -97,7 +129,20 @@
|
|||||||
<Spinner />
|
<Spinner />
|
||||||
{:else}
|
{:else}
|
||||||
<slot name="panel-header" />
|
<slot name="panel-header" />
|
||||||
<div class="panel-instance" class:bg={props.element === 'content'} bind:this={modalHTML}>
|
<div
|
||||||
|
class="panel-instance"
|
||||||
|
class:bg={props.element === 'content'}
|
||||||
|
bind:this={modalHTML}
|
||||||
|
style:top={options.props.top}
|
||||||
|
style:bottom={options.props.bottom}
|
||||||
|
style:left={options.props.left}
|
||||||
|
style:right={options.props.right}
|
||||||
|
style:width={options.props.width}
|
||||||
|
style:height={options.props.height}
|
||||||
|
style:max-width={options.props.maxWidth}
|
||||||
|
style:max-height={options.props.maxHeight}
|
||||||
|
style:min-width={options.props.minWidth}
|
||||||
|
>
|
||||||
<div class="panel-container" class:padding={props.element === 'content'}>
|
<div class="panel-container" class:padding={props.element === 'content'}>
|
||||||
<svelte:component
|
<svelte:component
|
||||||
this={component}
|
this={component}
|
||||||
@ -106,15 +151,19 @@
|
|||||||
_class={props._class}
|
_class={props._class}
|
||||||
rightSection={props.rightSection}
|
rightSection={props.rightSection}
|
||||||
position={props.element}
|
position={props.element}
|
||||||
|
bind:options
|
||||||
on:close={_close}
|
on:close={_close}
|
||||||
on:update={_update}
|
on:update={_update}
|
||||||
|
on:fullsize={() => {
|
||||||
|
fullSize = !fullSize
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{#if props.element !== 'content'}
|
{#if props.element !== 'content'}
|
||||||
<div
|
<div
|
||||||
class="modal-overlay"
|
class="modal-overlay"
|
||||||
class:show={options.show}
|
class:show={options.showOverlay}
|
||||||
on:click={() => escapeClose()}
|
on:click={() => escapeClose()}
|
||||||
on:keydown={() => {}}
|
on:keydown={() => {}}
|
||||||
on:keyup={() => {}}
|
on:keyup={() => {}}
|
||||||
@ -128,6 +177,10 @@
|
|||||||
z-index: 401;
|
z-index: 401;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
|
will-change: top, bottom, left, right;
|
||||||
|
transition-property: top, bottom, left, right, width, height;
|
||||||
|
transition-duration: 0.15s;
|
||||||
|
transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
|
||||||
|
|
||||||
&.bg {
|
&.bg {
|
||||||
background-color: var(--body-color);
|
background-color: var(--body-color);
|
||||||
@ -154,4 +207,7 @@
|
|||||||
background: rgba(0, 0, 0, 0.5);
|
background: rgba(0, 0, 0, 0.5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
:global(.panel-instance.fullsize) {
|
||||||
|
transition-timing-function: cubic-bezier(0.19, 1, 0.22, 1) !important;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -14,9 +14,9 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { afterUpdate } from 'svelte'
|
import { afterUpdate, onMount } from 'svelte'
|
||||||
import { fitPopupElement } from '../popups'
|
import { fitPopupElement } from '../popups'
|
||||||
import type { AnyComponent, AnySvelteComponent, PopupAlignment } from '../types'
|
import type { AnyComponent, AnySvelteComponent, PopupAlignment, PopupOptions } from '../types'
|
||||||
|
|
||||||
export let is: AnyComponent | AnySvelteComponent
|
export let is: AnyComponent | AnySvelteComponent
|
||||||
export let props: object
|
export let props: object
|
||||||
@ -29,12 +29,25 @@
|
|||||||
|
|
||||||
let modalHTML: HTMLElement
|
let modalHTML: HTMLElement
|
||||||
let componentInstance: any
|
let componentInstance: any
|
||||||
let height: number
|
let docWidth: number
|
||||||
|
let docSize: boolean = false
|
||||||
|
let fullSize: boolean = false
|
||||||
|
|
||||||
let options: {
|
let options: PopupOptions = {
|
||||||
show: boolean
|
props: {
|
||||||
direction: string
|
top: '',
|
||||||
} = { show: false, direction: 'bottom' }
|
bottom: '',
|
||||||
|
left: '',
|
||||||
|
right: '',
|
||||||
|
width: '',
|
||||||
|
height: '',
|
||||||
|
maxWidth: '',
|
||||||
|
maxHeight: '',
|
||||||
|
minWidth: ''
|
||||||
|
},
|
||||||
|
showOverlay: false,
|
||||||
|
direction: 'bottom'
|
||||||
|
}
|
||||||
|
|
||||||
function _update (result: any): void {
|
function _update (result: any): void {
|
||||||
if (onUpdate !== undefined) onUpdate(result)
|
if (onUpdate !== undefined) onUpdate(result)
|
||||||
@ -55,7 +68,14 @@
|
|||||||
|
|
||||||
const fitPopup = (): void => {
|
const fitPopup = (): void => {
|
||||||
if (modalHTML) {
|
if (modalHTML) {
|
||||||
options = fitPopupElement(modalHTML, element)
|
if ((fullSize || docSize) && (element === 'float' || element === 'content')) {
|
||||||
|
options = fitPopupElement(modalHTML, 'full')
|
||||||
|
modalHTML.classList.add('fullsize')
|
||||||
|
} else {
|
||||||
|
options = fitPopupElement(modalHTML, element)
|
||||||
|
modalHTML.classList.remove('fullsize')
|
||||||
|
}
|
||||||
|
options.fullSize = fullSize
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,27 +84,47 @@
|
|||||||
escapeClose()
|
escapeClose()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onMount(() => fitPopup())
|
||||||
|
$: if (docWidth <= 900 && !docSize) docSize = true
|
||||||
|
$: if (docWidth > 900 && docSize) docSize = false
|
||||||
|
|
||||||
afterUpdate(() => fitPopup())
|
afterUpdate(() => fitPopup())
|
||||||
$: if (height) fitPopup()
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:window on:resize={fitPopup} on:keydown={handleKeydown} />
|
<svelte:window on:resize={fitPopup} on:keydown={handleKeydown} bind:innerWidth={docWidth} />
|
||||||
|
|
||||||
<div class="popup" bind:this={modalHTML} bind:clientHeight={height} style={`z-index: ${zIndex + 1};`}>
|
<div
|
||||||
|
class="popup"
|
||||||
|
bind:this={modalHTML}
|
||||||
|
style={`z-index: ${zIndex + 1};`}
|
||||||
|
style:top={options.props.top}
|
||||||
|
style:bottom={options.props.bottom}
|
||||||
|
style:left={options.props.left}
|
||||||
|
style:right={options.props.right}
|
||||||
|
style:width={options.props.width}
|
||||||
|
style:height={options.props.height}
|
||||||
|
style:max-width={options.props.maxWidth}
|
||||||
|
style:max-height={options.props.maxHeight}
|
||||||
|
style:min-width={options.props.minWidth}
|
||||||
|
>
|
||||||
<svelte:component
|
<svelte:component
|
||||||
this={is}
|
this={is}
|
||||||
bind:this={componentInstance}
|
bind:this={componentInstance}
|
||||||
{...props}
|
{...props}
|
||||||
direction={options.direction}
|
bind:options
|
||||||
on:update={(ev) => {
|
on:update={(ev) => {
|
||||||
_update(ev.detail)
|
_update(ev.detail)
|
||||||
}}
|
}}
|
||||||
on:close={(ev) => _close(ev.detail)}
|
on:close={(ev) => _close(ev.detail)}
|
||||||
|
on:fullsize={() => {
|
||||||
|
fullSize = !fullSize
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="modal-overlay"
|
class="modal-overlay"
|
||||||
class:antiOverlay={options.show}
|
class:antiOverlay={options.showOverlay}
|
||||||
style={`z-index: ${zIndex};`}
|
style={`z-index: ${zIndex};`}
|
||||||
on:click={() => escapeClose()}
|
on:click={() => escapeClose()}
|
||||||
/>
|
/>
|
||||||
@ -97,6 +137,10 @@
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
max-height: calc(100vh - 2rem);
|
max-height: calc(100vh - 2rem);
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
|
will-change: top, bottom, left, right;
|
||||||
|
transition-property: top, bottom, left, right, width, height;
|
||||||
|
transition-duration: 0.15s;
|
||||||
|
transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
|
||||||
}
|
}
|
||||||
.modal-overlay {
|
.modal-overlay {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import type { AnySvelteComponent, AnyComponent, PopupAlignment, PopupPositionElement } from './types'
|
import type { AnySvelteComponent, AnyComponent, PopupAlignment, PopupPositionElement, PopupOptions } from './types'
|
||||||
import { getResource } from '@anticrm/platform'
|
import { getResource } from '@anticrm/platform'
|
||||||
import { writable } from 'svelte/store'
|
import { writable } from 'svelte/store'
|
||||||
|
|
||||||
@ -117,7 +117,7 @@ export function fitPopupPositionedElement (
|
|||||||
modalHTML: HTMLElement,
|
modalHTML: HTMLElement,
|
||||||
alignment: PopupPositionElement,
|
alignment: PopupPositionElement,
|
||||||
newProps: Record<string, string | number>
|
newProps: Record<string, string | number>
|
||||||
): { show: boolean, direction: string } {
|
): PopupOptions {
|
||||||
let direction: string = ''
|
let direction: string = ''
|
||||||
const rect = alignment.getBoundingClientRect()
|
const rect = alignment.getBoundingClientRect()
|
||||||
const rectPopup = modalHTML.getBoundingClientRect()
|
const rectPopup = modalHTML.getBoundingClientRect()
|
||||||
@ -159,17 +159,17 @@ export function fitPopupPositionedElement (
|
|||||||
direction += '|right'
|
direction += '|right'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return { show: false, direction }
|
return { props: newProps, showOverlay: false, direction }
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyStyle (values: Record<string, string | number>, modalHTML: HTMLElement): void {
|
// function applyStyle (values: Record<string, string | number>, modalHTML: HTMLElement): void {
|
||||||
for (const [k, v] of Object.entries(values)) {
|
// for (const [k, v] of Object.entries(values)) {
|
||||||
const old = (modalHTML.style as any)[k]
|
// const old = (modalHTML.style as any)[k]
|
||||||
if (old !== v) {
|
// if (old !== v) {
|
||||||
;(modalHTML.style as any)[k] = v
|
// ;(modalHTML.style as any)[k] = v
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
@ -182,7 +182,7 @@ export function fitPopupElement (
|
|||||||
modalHTML: HTMLElement,
|
modalHTML: HTMLElement,
|
||||||
element?: PopupAlignment,
|
element?: PopupAlignment,
|
||||||
contentPanel?: HTMLElement
|
contentPanel?: HTMLElement
|
||||||
): { show: boolean, direction: string } {
|
): PopupOptions {
|
||||||
let show = true
|
let show = true
|
||||||
const newProps: Record<string, string | number> = {}
|
const newProps: Record<string, string | number> = {}
|
||||||
if (element != null) {
|
if (element != null) {
|
||||||
@ -192,7 +192,7 @@ export function fitPopupElement (
|
|||||||
newProps.maxWidth = newProps.width = newProps.minWidth = ''
|
newProps.maxWidth = newProps.width = newProps.minWidth = ''
|
||||||
if (typeof element !== 'string') {
|
if (typeof element !== 'string') {
|
||||||
const result = fitPopupPositionedElement(modalHTML, element, newProps)
|
const result = fitPopupPositionedElement(modalHTML, element, newProps)
|
||||||
applyStyle(newProps, modalHTML)
|
// applyStyle(newProps, modalHTML)
|
||||||
return result
|
return result
|
||||||
} else if (element === 'right' && contentPanel !== undefined) {
|
} else if (element === 'right' && contentPanel !== undefined) {
|
||||||
const rect = contentPanel.getBoundingClientRect()
|
const rect = contentPanel.getBoundingClientRect()
|
||||||
@ -209,13 +209,20 @@ export function fitPopupElement (
|
|||||||
} else if (element === 'float') {
|
} else if (element === 'float') {
|
||||||
newProps.top = 'calc(var(--status-bar-height) + .25rem)'
|
newProps.top = 'calc(var(--status-bar-height) + .25rem)'
|
||||||
newProps.bottom = '.25rem'
|
newProps.bottom = '.25rem'
|
||||||
newProps.minWidth = '40rem'
|
newProps.left = '60%'
|
||||||
newProps.width = '40%'
|
|
||||||
newProps.right = '.25rem'
|
newProps.right = '.25rem'
|
||||||
show = true
|
show = true
|
||||||
} else if (element === 'account') {
|
} else if (element === 'account') {
|
||||||
newProps.bottom = '2.75rem'
|
newProps.bottom = '2.75rem'
|
||||||
newProps.left = '5rem'
|
newProps.left = '5rem'
|
||||||
|
} else if (element === 'full' && contentPanel === undefined) {
|
||||||
|
newProps.top = '0'
|
||||||
|
newProps.bottom = '0'
|
||||||
|
newProps.left = '0'
|
||||||
|
newProps.right = '0'
|
||||||
|
// newProps.width = '100vw'
|
||||||
|
newProps.height = '100vh'
|
||||||
|
show = false
|
||||||
} else if (element === 'full' && contentPanel !== undefined) {
|
} else if (element === 'full' && contentPanel !== undefined) {
|
||||||
const rect = contentPanel.getBoundingClientRect()
|
const rect = contentPanel.getBoundingClientRect()
|
||||||
newProps.top = `${rect.top + 1}px`
|
newProps.top = `${rect.top + 1}px`
|
||||||
@ -248,8 +255,8 @@ export function fitPopupElement (
|
|||||||
newProps.transform = 'translate(-50%, -50%)'
|
newProps.transform = 'translate(-50%, -50%)'
|
||||||
show = true
|
show = true
|
||||||
}
|
}
|
||||||
applyStyle(newProps, modalHTML)
|
// applyStyle(newProps, modalHTML)
|
||||||
return { show, direction: '' }
|
return { props: newProps, showOverlay: show, direction: '' }
|
||||||
}
|
}
|
||||||
|
|
||||||
export function eventToHTMLElement (evt: MouseEvent): HTMLElement {
|
export function eventToHTMLElement (evt: MouseEvent): HTMLElement {
|
||||||
|
@ -110,3 +110,10 @@ export interface DropdownIntlItem {
|
|||||||
id: string
|
id: string
|
||||||
label: IntlString
|
label: IntlString
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface PopupOptions {
|
||||||
|
props: Record<string, string | number>
|
||||||
|
showOverlay: boolean
|
||||||
|
direction: string
|
||||||
|
fullSize?: boolean
|
||||||
|
}
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
// This file is read by tools that parse documentation comments conforming to the TSDoc standard.
|
// This file is read by tools that parse documentation comments conforming to the TSDoc standard.
|
||||||
// It should be published with your NPM package. It should not be tracked by Git.
|
// It should be published with your NPM package. It should not be tracked by Git.
|
||||||
{
|
{
|
||||||
"tsdocVersion": "0.12",
|
"tsdocVersion": "0.12",
|
||||||
"toolPackages": [
|
"toolPackages": [
|
||||||
{
|
{
|
||||||
"packageName": "@microsoft/api-extractor",
|
"packageName": "@microsoft/api-extractor",
|
||||||
"packageVersion": "7.23.0"
|
"packageVersion": "7.23.0"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@
|
|||||||
|
|
||||||
function openAttachment () {
|
function openAttachment () {
|
||||||
closeTooltip()
|
closeTooltip()
|
||||||
showPopup(PDFViewer, { file: value.file, name: value.name, contentType: value.type }, 'right')
|
showPopup(PDFViewer, { file: value.file, name: value.name, contentType: value.type }, 'float')
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@
|
|||||||
class="flex-center icon"
|
class="flex-center icon"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
closeTooltip()
|
closeTooltip()
|
||||||
showPopup(PDFViewer, { file: value.file, name: value.name, contentType: value.type }, 'right')
|
showPopup(PDFViewer, { file: value.file, name: value.name, contentType: value.type }, 'float')
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{iconLabel(value.name)}
|
{iconLabel(value.name)}
|
||||||
@ -86,7 +86,7 @@
|
|||||||
class="name"
|
class="name"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
closeTooltip()
|
closeTooltip()
|
||||||
showPopup(PDFViewer, { file: value.file, name: value.name, contentType: value.type }, 'right')
|
showPopup(PDFViewer, { file: value.file, name: value.name, contentType: value.type }, 'float')
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{trimFilename(value.name)}
|
{trimFilename(value.name)}
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
class="content flex-center buttonContainer cursor-pointer"
|
class="content flex-center buttonContainer cursor-pointer"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
closeTooltip()
|
closeTooltip()
|
||||||
showPopup(PDFViewer, { file: value.file, name: value.name, contentType: value.type }, 'right')
|
showPopup(PDFViewer, { file: value.file, name: value.name, contentType: value.type }, 'float')
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<img src={getFileUrl(value.file)} alt={value.name} />
|
<img src={getFileUrl(value.file)} alt={value.name} />
|
||||||
|
@ -88,7 +88,7 @@
|
|||||||
const el: HTMLElement = ev.currentTarget as HTMLElement
|
const el: HTMLElement = ev.currentTarget as HTMLElement
|
||||||
el.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'center' })
|
el.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'center' })
|
||||||
if (item !== undefined) {
|
if (item !== undefined) {
|
||||||
showPopup(PDFViewer, { file: item.file, name: item.name, contentType: item.type }, 'right')
|
showPopup(PDFViewer, { file: item.file, name: item.name, contentType: item.type }, 'float')
|
||||||
} else {
|
} else {
|
||||||
inputFile.click()
|
inputFile.click()
|
||||||
}
|
}
|
||||||
|
@ -88,6 +88,8 @@
|
|||||||
{object}
|
{object}
|
||||||
isHeader={false}
|
isHeader={false}
|
||||||
isAside={true}
|
isAside={true}
|
||||||
|
isFullSize
|
||||||
|
on:fullsize
|
||||||
on:close={() => dispatch('close')}
|
on:close={() => dispatch('close')}
|
||||||
>
|
>
|
||||||
<svelte:fragment slot="navigator">
|
<svelte:fragment slot="navigator">
|
||||||
|
@ -45,7 +45,7 @@
|
|||||||
|
|
||||||
function handleClick () {
|
function handleClick () {
|
||||||
closeTooltip()
|
closeTooltip()
|
||||||
showPopup(PDFViewer, { file: value.file, name: value.name, contentType: value.type }, 'right')
|
showPopup(PDFViewer, { file: value.file, name: value.name, contentType: value.type }, 'float')
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -64,6 +64,8 @@
|
|||||||
<Panel
|
<Panel
|
||||||
isHeader={false}
|
isHeader={false}
|
||||||
isAside={_class === chunter.class.Channel}
|
isAside={_class === chunter.class.Channel}
|
||||||
|
isFullSize
|
||||||
|
on:fullsize
|
||||||
on:close={() => {
|
on:close={() => {
|
||||||
dispatch('close')
|
dispatch('close')
|
||||||
}}
|
}}
|
||||||
|
@ -28,13 +28,14 @@
|
|||||||
} from '@anticrm/ui'
|
} from '@anticrm/ui'
|
||||||
import IconCopy from './icons/Copy.svelte'
|
import IconCopy from './icons/Copy.svelte'
|
||||||
import { FocusHandler } from '@anticrm/ui'
|
import { FocusHandler } from '@anticrm/ui'
|
||||||
|
import type { PopupOptions } from '@anticrm/ui'
|
||||||
import plugin from '../plugin'
|
import plugin from '../plugin'
|
||||||
|
|
||||||
export let value: string = ''
|
export let value: string = ''
|
||||||
export let placeholder: IntlString
|
export let placeholder: IntlString
|
||||||
export let editable: boolean | undefined = undefined
|
export let editable: boolean | undefined = undefined
|
||||||
export let openable: boolean = false
|
export let openable: boolean = false
|
||||||
export let direction: string = 'bottom'
|
export let options: PopupOptions
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
let input: HTMLInputElement
|
let input: HTMLInputElement
|
||||||
@ -75,11 +76,12 @@
|
|||||||
input.addEventListener('focus', updateFocus, { once: true })
|
input.addEventListener('focus', updateFocus, { once: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let dir: string = 'bottom'
|
||||||
const vDir = (d: string): string => d.split('|')[0]
|
const vDir = (d: string): string => d.split('|')[0]
|
||||||
const fitEditor = (): void => {
|
const fitEditor = (): void => {
|
||||||
dir = vDir(direction)
|
if (options) dir = vDir(options.direction)
|
||||||
}
|
}
|
||||||
$: dir = vDir(direction)
|
$: if (options) dir = vDir(options.direction)
|
||||||
afterUpdate(() => {
|
afterUpdate(() => {
|
||||||
fitEditor()
|
fitEditor()
|
||||||
})
|
})
|
||||||
|
@ -76,6 +76,8 @@
|
|||||||
<Panel
|
<Panel
|
||||||
isHeader={true}
|
isHeader={true}
|
||||||
isAside={false}
|
isAside={false}
|
||||||
|
isFullSize
|
||||||
|
on:fullsize
|
||||||
on:close={() => {
|
on:close={() => {
|
||||||
dispatch('close')
|
dispatch('close')
|
||||||
}}
|
}}
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
"GotoLeadApplication": "Switch to Lead Application",
|
"GotoLeadApplication": "Switch to Lead Application",
|
||||||
"IssueDescriptionPlaceholder": "Add description...",
|
"IssueDescriptionPlaceholder": "Add description...",
|
||||||
"CreateCustomer": "Create Customer",
|
"CreateCustomer": "Create Customer",
|
||||||
"CreateCustomerLabel": "New Customer"
|
"CreateCustomerLabel": "New Customer",
|
||||||
|
"NoLeadsForDocument": "No leads for document"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -25,6 +25,7 @@
|
|||||||
"GotoLeadApplication": "Открыть приложение Сделки",
|
"GotoLeadApplication": "Открыть приложение Сделки",
|
||||||
"IssueDescriptionPlaceholder": "Добавить описание...",
|
"IssueDescriptionPlaceholder": "Добавить описание...",
|
||||||
"CreateCustomer": "Добавить Клиента",
|
"CreateCustomer": "Добавить Клиента",
|
||||||
"CreateCustomerLabel": "Новый Клиент"
|
"CreateCustomerLabel": "Новый Клиент",
|
||||||
|
"NoLeadsForDocument": "Нет потенциальных клиентов для документа"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -538,7 +538,7 @@
|
|||||||
focusIndex={103}
|
focusIndex={103}
|
||||||
icon={FileIcon}
|
icon={FileIcon}
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
showPopup(PDFViewer, { file: resume.uuid, name: resume.name }, 'right')
|
showPopup(PDFViewer, { file: resume.uuid, name: resume.name }, 'float')
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<svelte:fragment slot="content">
|
<svelte:fragment slot="content">
|
||||||
|
@ -58,6 +58,8 @@
|
|||||||
isHeader={false}
|
isHeader={false}
|
||||||
isAside={true}
|
isAside={true}
|
||||||
{object}
|
{object}
|
||||||
|
isFullSize
|
||||||
|
on:fullsize
|
||||||
on:close={() => {
|
on:close={() => {
|
||||||
dispatch('close')
|
dispatch('close')
|
||||||
}}
|
}}
|
||||||
|
@ -54,6 +54,8 @@
|
|||||||
isHeader={false}
|
isHeader={false}
|
||||||
isAside={true}
|
isAside={true}
|
||||||
{object}
|
{object}
|
||||||
|
isFullSize
|
||||||
|
on:fullsize
|
||||||
on:close={() => {
|
on:close={() => {
|
||||||
dispatch('close')
|
dispatch('close')
|
||||||
}}
|
}}
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
import type { DoneState, Kanban, SpaceWithStates, State } from '@anticrm/task'
|
import type { DoneState, Kanban, SpaceWithStates, State } from '@anticrm/task'
|
||||||
import task from '../../plugin'
|
import task from '../../plugin'
|
||||||
import KanbanEditor from '../kanban/KanbanEditor.svelte'
|
import KanbanEditor from '../kanban/KanbanEditor.svelte'
|
||||||
import { Icon, IconClose, Label, showPopup, ActionIcon, ScrollBox } from '@anticrm/ui'
|
import { Icon, Label, showPopup, Panel, Scroller } from '@anticrm/ui'
|
||||||
import { createEventDispatcher } from 'svelte'
|
import { createEventDispatcher } from 'svelte'
|
||||||
import workbench from '@anticrm/workbench'
|
import workbench from '@anticrm/workbench'
|
||||||
|
|
||||||
@ -91,39 +91,35 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div
|
<Panel
|
||||||
class="antiOverlay"
|
isHeader={false}
|
||||||
on:click={() => {
|
isAside={false}
|
||||||
|
isFullSize
|
||||||
|
on:fullsize
|
||||||
|
on:close={() => {
|
||||||
dispatch('close')
|
dispatch('close')
|
||||||
}}
|
}}
|
||||||
/>
|
>
|
||||||
<div class="antiDialogs antiComponent">
|
<svelte:fragment slot="title">
|
||||||
<div class="ac-header short mirror divide">
|
<div class="antiTitle icon-wrapper">
|
||||||
<div class="ac-header__wrap-description">
|
<div class="wrapped-icon">
|
||||||
<div class="ac-header__wrap-title">
|
<Icon icon={task.icon.ManageStatuses} size={'small'} />
|
||||||
<div class="ac-header__icon"><Icon icon={task.icon.ManageStatuses} size={'small'} /></div>
|
</div>
|
||||||
<span class="ac-header__title">
|
<div class="title-wrapper">
|
||||||
|
<span class="wrapped-title">
|
||||||
<Label label={task.string.ManageStatusesWithin} />
|
<Label label={task.string.ManageStatusesWithin} />
|
||||||
{#if spaceClassInstance}<Label label={spaceClassInstance?.label} />{:else}...{/if}
|
{#if spaceClassInstance}<Label label={spaceClassInstance?.label} />{:else}...{/if}
|
||||||
</span>
|
</span>
|
||||||
|
{#if spaceInstance?.name}<span class="wrapped-subtitle">{spaceInstance?.name}</span>{/if}
|
||||||
</div>
|
</div>
|
||||||
{#if spaceInstance?.name}<span class="ac-header__description">{spaceInstance?.name}</span>{/if}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="tool">
|
</svelte:fragment>
|
||||||
<ActionIcon
|
|
||||||
icon={IconClose}
|
<Scroller>
|
||||||
size={'small'}
|
<div class="popupPanel-body__main-content py-10 clear-mins">
|
||||||
action={() => {
|
|
||||||
dispatch('close')
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="p-10 flex-grow">
|
|
||||||
<ScrollBox vertical stretch>
|
|
||||||
{#if kanban !== undefined}
|
{#if kanban !== undefined}
|
||||||
<KanbanEditor {kanban} on:delete={(e) => deleteState(e.detail)} />
|
<KanbanEditor {kanban} on:delete={(e) => deleteState(e.detail)} />
|
||||||
{/if}
|
{/if}
|
||||||
</ScrollBox>
|
</div>
|
||||||
</div>
|
</Scroller>
|
||||||
</div>
|
</Panel>
|
||||||
|
@ -75,68 +75,66 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div>
|
<div class="flex-no-shrink flex-between trans-title uppercase">
|
||||||
<div class="flex-no-shrink flex-between trans-title uppercase">
|
<Label label={task.string.ActiveStates} />
|
||||||
<Label label={task.string.ActiveStates} />
|
<CircleButton
|
||||||
<CircleButton
|
icon={IconAdd}
|
||||||
icon={IconAdd}
|
size={'medium'}
|
||||||
size={'medium'}
|
on:click={() => {
|
||||||
on:click={() => {
|
onAdd(task.class.State)
|
||||||
onAdd(task.class.State)
|
}}
|
||||||
}}
|
/>
|
||||||
/>
|
</div>
|
||||||
</div>
|
<div class="mt-3">
|
||||||
<div class="mt-3">
|
{#each states as state, i}
|
||||||
{#each states as state, i}
|
{#if state}
|
||||||
{#if state}
|
<div
|
||||||
|
bind:this={elements[i]}
|
||||||
|
class="flex-between states"
|
||||||
|
draggable={true}
|
||||||
|
on:dragover|preventDefault={(ev) => {
|
||||||
|
dragover(ev, i)
|
||||||
|
}}
|
||||||
|
on:drop|preventDefault={() => {
|
||||||
|
onMove(i)
|
||||||
|
}}
|
||||||
|
on:dragstart={() => {
|
||||||
|
selected = i
|
||||||
|
dragState = states[i]._id
|
||||||
|
}}
|
||||||
|
on:dragend={() => {
|
||||||
|
selected = undefined
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div class="bar"><Circles /></div>
|
||||||
<div
|
<div
|
||||||
bind:this={elements[i]}
|
class="color"
|
||||||
class="flex-between states"
|
style="background-color: {getPlatformColor(state.color)}"
|
||||||
draggable={true}
|
on:click={() => {
|
||||||
on:dragover|preventDefault={(ev) => {
|
showPopup(ColorsPopup, {}, elements[i], onColorChange(state))
|
||||||
dragover(ev, i)
|
|
||||||
}}
|
}}
|
||||||
on:drop|preventDefault={() => {
|
/>
|
||||||
onMove(i)
|
<div class="flex-grow caption-color">
|
||||||
}}
|
<AttributeEditor maxWidth={'20rem'} _class={state._class} object={state} key="title" />
|
||||||
on:dragstart={() => {
|
|
||||||
selected = i
|
|
||||||
dragState = states[i]._id
|
|
||||||
}}
|
|
||||||
on:dragend={() => {
|
|
||||||
selected = undefined
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div class="bar"><Circles /></div>
|
|
||||||
<div
|
|
||||||
class="color"
|
|
||||||
style="background-color: {getPlatformColor(state.color)}"
|
|
||||||
on:click={() => {
|
|
||||||
showPopup(ColorsPopup, {}, elements[i], onColorChange(state))
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<div class="flex-grow caption-color">
|
|
||||||
<AttributeEditor maxWidth={'20rem'} _class={state._class} object={state} key="title" />
|
|
||||||
</div>
|
|
||||||
{#if states.length > 1}
|
|
||||||
<div
|
|
||||||
class="tool hover-trans"
|
|
||||||
on:click={(ev) => {
|
|
||||||
showPopup(
|
|
||||||
StatusesPopup,
|
|
||||||
{ onDelete: () => dispatch('delete', { state }) },
|
|
||||||
eventToHTMLElement(ev),
|
|
||||||
() => {}
|
|
||||||
)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<IconMoreH size={'medium'} />
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{#if states.length > 1}
|
||||||
{/each}
|
<div
|
||||||
</div>
|
class="tool hover-trans"
|
||||||
|
on:click={(ev) => {
|
||||||
|
showPopup(
|
||||||
|
StatusesPopup,
|
||||||
|
{ onDelete: () => dispatch('delete', { state }) },
|
||||||
|
eventToHTMLElement(ev),
|
||||||
|
() => {}
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<IconMoreH size={'medium'} />
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-9">
|
<div class="mt-9">
|
||||||
<div class="flex-no-shrink flex-between trans-title uppercase">
|
<div class="flex-no-shrink flex-between trans-title uppercase">
|
||||||
@ -189,7 +187,7 @@
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-4">
|
<div class="mt-4 mb-10">
|
||||||
{#each lostStates as state}
|
{#each lostStates as state}
|
||||||
{#if state}
|
{#if state}
|
||||||
<div class="states flex-row-center">
|
<div class="states flex-row-center">
|
||||||
@ -222,10 +220,10 @@
|
|||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.states {
|
.states {
|
||||||
padding: 0.5rem 1rem;
|
padding: 0.5rem 1rem;
|
||||||
color: var(--theme-caption-color);
|
color: var(--caption-color);
|
||||||
background-color: var(--theme-button-bg-enabled);
|
background-color: var(--button-bg-color);
|
||||||
border: 1px solid var(--theme-bg-accent-color);
|
border: 1px solid var(--button-border-color);
|
||||||
border-radius: 0.75rem;
|
border-radius: 0.5rem;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
|
||||||
.bar {
|
.bar {
|
||||||
|
@ -43,7 +43,7 @@ import AssignedTasks from './components/AssignedTasks.svelte'
|
|||||||
import task from './plugin'
|
import task from './plugin'
|
||||||
|
|
||||||
async function editStatuses (object: SpaceWithStates): Promise<void> {
|
async function editStatuses (object: SpaceWithStates): Promise<void> {
|
||||||
showPopup(EditStatuses, { _id: object._id, spaceClass: object._class }, 'right')
|
showPopup(EditStatuses, { _id: object._id, spaceClass: object._class }, 'float')
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function queryTask<D extends Task> (
|
export async function queryTask<D extends Task> (
|
||||||
|
@ -188,6 +188,8 @@
|
|||||||
<Panel
|
<Panel
|
||||||
isHeader={true}
|
isHeader={true}
|
||||||
isAside={false}
|
isAside={false}
|
||||||
|
isFullSize
|
||||||
|
on:fullsize
|
||||||
on:close={() => {
|
on:close={() => {
|
||||||
dispatch('close')
|
dispatch('close')
|
||||||
}}
|
}}
|
||||||
|
@ -139,6 +139,8 @@
|
|||||||
isSub={false}
|
isSub={false}
|
||||||
withoutActivity={isEditing}
|
withoutActivity={isEditing}
|
||||||
bind:innerWidth
|
bind:innerWidth
|
||||||
|
isFullSize
|
||||||
|
on:fullsize
|
||||||
on:close={() => dispatch('close')}
|
on:close={() => dispatch('close')}
|
||||||
>
|
>
|
||||||
<svelte:fragment slot="subtitle">
|
<svelte:fragment slot="subtitle">
|
||||||
|
@ -228,6 +228,8 @@
|
|||||||
isAside={true}
|
isAside={true}
|
||||||
bind:panelWidth
|
bind:panelWidth
|
||||||
bind:innerWidth
|
bind:innerWidth
|
||||||
|
isFullSize
|
||||||
|
on:fullsize
|
||||||
on:update={(ev) => _update(ev.detail)}
|
on:update={(ev) => _update(ev.detail)}
|
||||||
on:close={() => {
|
on:close={() => {
|
||||||
dispatch('close')
|
dispatch('close')
|
||||||
|
@ -55,6 +55,8 @@
|
|||||||
<Panel
|
<Panel
|
||||||
isHeader={false}
|
isHeader={false}
|
||||||
isAside={false}
|
isAside={false}
|
||||||
|
isFullSize
|
||||||
|
on:fullsize
|
||||||
on:close={() => {
|
on:close={() => {
|
||||||
dispatch('close')
|
dispatch('close')
|
||||||
}}
|
}}
|
||||||
|
Loading…
Reference in New Issue
Block a user