Update EditStatuses, PDFViewer. Add full size for Panel. (#1797)

Signed-off-by: Alexander Platov <sas_lord@mail.ru>
This commit is contained in:
Alexander Platov 2022-05-19 09:42:38 +03:00 committed by GitHub
parent 8abadca450
commit d277134032
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 446 additions and 270 deletions

View File

@ -32,9 +32,18 @@
export let isSub: boolean = true
export let isAside: boolean = true
export let isCustomAttr: boolean = true
export let isFullSize: boolean = false
</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">
<div class="popupPanel-title__content-container antiTitle">
{#if $$slots.navigator}

View File

@ -4,7 +4,7 @@
"Cancel": "Отменить",
"Ok": "Ок",
"Save": "Сохранить",
"Download": "Загрузить",
"Download": "Скачать",
"Close": "Закрыть",
"NotSelected": "Не выбрано",
"Deselect": "Снять выделение",

View File

@ -13,43 +13,88 @@
// limitations under the License.
-->
<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 presentation from '..'
import { getFileUrl } from '../utils'
import Avatar from './Avatar.svelte'
import MaximizeH from './icons/MaximizeH.svelte'
import MaximizeV from './icons/MaximizeV.svelte'
import MaximizeO from './icons/MaximizeO.svelte'
import Download from './icons/Download.svelte'
export let file: string
export let name: string
export let contentType: string | undefined
export let options: PopupOptions
const dispatch = createEventDispatcher()
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>
<div
class="antiOverlay"
on:click={() => {
<Panel
isHeader={false}
isAside={options && options.fullSize}
isFullSize
on:fullsize
on:close={() => {
dispatch('close')
}}
/>
<div class="antiDialogs antiComponent pdfviewer-container">
<div class="ac-header short mirror">
<div class="ac-header__wrap-title">
<div class="ac-header__icon"><Avatar size={'medium'} /></div>
<span class="ac-header__title">{name}</span>
>
<svelte:fragment slot="title">
<div class="antiTitle icon-wrapper">
<div class="wrapped-icon">
<div class="flex-center icon">
{iconLabel(name)}
</div>
</div>
<span class="wrapped-title">{name}</span>
</div>
<ActionIcon
icon={IconClose}
size={'medium'}
action={(_) => {
dispatch('close')
}}
/>
</div>
</svelte:fragment>
<svelte:fragment slot="utils">
{#if contentType && contentType.startsWith('image/')}
<Button
icon={MaximizeH}
kind={'transparent'}
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/')}
<div class="pdfviewer-content">
@ -58,55 +103,26 @@
{:else}
<iframe class="pdfviewer-content" src={getFileUrl(file)} title="" />
{/if}
<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>
</Panel>
<style lang="scss">
.pdfviewer-container {
left: 40%;
.icon {
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 {
flex-grow: 1;
overflow: auto;
margin: 0 1.5rem;
margin: 1.5rem;
border-style: none;
border-radius: 0.5rem;
background-color: var(--theme-menu-color);
@ -124,14 +140,12 @@
.img-vertical-fit {
height: 100%;
}
.pdfviewer-footer {
.pdfviewer-header {
flex-shrink: 0;
display: flex;
justify-content: space-between;
flex-direction: row-reverse;
align-items: center;
padding: 0 2.25rem;
height: 5.25rem;
}
.img-nav {
display: grid;

View 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>

View File

@ -356,6 +356,7 @@ input.search {
.mb-3 { margin-bottom: .75rem; }
.mb-4 { margin-bottom: 1rem; }
.mb-6 { margin-bottom: 1.5rem; }
.mb-10 { margin-bottom: 2.5rem; }
.mx-1 { margin: 0 .25rem; }
.mx-2 { margin: 0 .5rem; }
.mx-3 { margin: 0 .75rem; }

View File

@ -432,8 +432,7 @@
// THead background-color in Tooltip and Popups
.popup-tooltip .antiTable .scroller-thead,
.popup .antiTable .scroller-thead,
.antiDialogs .antiTable .scroller-thead { background-color: var(--accent-bg-color); }
.popup .antiTable .scroller-thead { background-color: var(--accent-bg-color); }
// Hide row menu in Tooltip
.popup-tooltip .antiTable .antiTable-body__row:hover .antiTable-cells__firstCell .antiTable-cells__firstCell-menuRow { visibility: hidden; }

View File

@ -13,51 +13,6 @@
// 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 */
.antiOverlay {
position: fixed;

View File

@ -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;
}

View File

@ -14,12 +14,13 @@
-->
<script lang="ts">
import { createEventDispatcher } from 'svelte'
import { Button, IconClose, IconDetails } from '..'
import { Button, IconClose, IconDetails, IconExpand } from '..'
export let innerWidth: number = 0
export let panelWidth: number = 0
export let isHeader: boolean = true
export let isAside: boolean = true
export let isFullSize: boolean = false
const dispatch = createEventDispatcher()
@ -30,8 +31,13 @@
asideFloat = false
asideShown = false
}
let docWidth: number
let fullSize: boolean = false
$: if (docWidth <= 900 && !fullSize) fullSize = true
$: if (docWidth > 900 && fullSize) fullSize = false
</script>
<svelte:window bind:innerWidth={docWidth} />
<div class="popupPanel" bind:clientWidth={panelWidth}>
<div class="popupPanel-title">
<Button
@ -45,8 +51,8 @@
<div class="popupPanel-title__content"><slot name="title" /></div>
<div class="buttons-group xsmall-gap">
<slot name="utils" />
{#if $$slots.utils}<div class="buttons-divider" />{/if}
{#if asideFloat && $$slots.aside && isAside}
{#if $$slots.utils}<div class="buttons-divider" />{/if}
<Button
icon={IconDetails}
kind={'transparent'}
@ -57,6 +63,19 @@
}}
/>
{/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 class="popupPanel-body" class:asideShown>

View File

@ -15,8 +15,9 @@
-->
<script lang="ts">
import { getResource } from '@anticrm/platform'
import { afterUpdate } from 'svelte'
import { AnySvelteComponent, Spinner } from '..'
import { afterUpdate, onMount } from 'svelte'
import { Spinner } from '..'
import type { AnySvelteComponent, PopupOptions } from '..'
import { closePanel, PanelProps, panelstore } from '../panelup'
import { fitPopupElement, popupstore } from '../popups'
@ -24,11 +25,25 @@
let modalHTML: HTMLElement
let componentInstance: any
let docWidth: number
let docSize: boolean = false
let fullSize: boolean = false
let options: {
show: boolean
direction: string
} = { show: false, direction: 'bottom' }
let options: PopupOptions = {
props: {
top: '',
bottom: '',
left: '',
right: '',
width: '',
height: '',
maxWidth: '',
maxHeight: '',
minWidth: ''
},
showOverlay: false,
direction: 'bottom'
}
let component: AnySvelteComponent
@ -62,7 +77,17 @@
const fitPopup = (props: PanelProps, contentPanel: HTMLElement): void => {
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 {
if (props) fitPopup(props, contentPanel)
}
onMount(() => {
if (props) fitPopup(props, contentPanel)
})
$: if (docWidth <= 900 && !docSize) docSize = true
$: if (docWidth > 900 && docSize) docSize = false
</script>
<svelte:window
bind:innerWidth={docWidth}
on:resize={() => {
if (props) fitPopup(props, contentPanel)
}}
@ -97,7 +129,20 @@
<Spinner />
{:else}
<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'}>
<svelte:component
this={component}
@ -106,15 +151,19 @@
_class={props._class}
rightSection={props.rightSection}
position={props.element}
bind:options
on:close={_close}
on:update={_update}
on:fullsize={() => {
fullSize = !fullSize
}}
/>
</div>
</div>
{#if props.element !== 'content'}
<div
class="modal-overlay"
class:show={options.show}
class:show={options.showOverlay}
on:click={() => escapeClose()}
on:keydown={() => {}}
on:keyup={() => {}}
@ -128,6 +177,10 @@
z-index: 401;
position: fixed;
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 {
background-color: var(--body-color);
@ -154,4 +207,7 @@
background: rgba(0, 0, 0, 0.5);
}
}
:global(.panel-instance.fullsize) {
transition-timing-function: cubic-bezier(0.19, 1, 0.22, 1) !important;
}
</style>

View File

@ -14,9 +14,9 @@
// limitations under the License.
-->
<script lang="ts">
import { afterUpdate } from 'svelte'
import { afterUpdate, onMount } from 'svelte'
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 props: object
@ -29,12 +29,25 @@
let modalHTML: HTMLElement
let componentInstance: any
let height: number
let docWidth: number
let docSize: boolean = false
let fullSize: boolean = false
let options: {
show: boolean
direction: string
} = { show: false, direction: 'bottom' }
let options: PopupOptions = {
props: {
top: '',
bottom: '',
left: '',
right: '',
width: '',
height: '',
maxWidth: '',
maxHeight: '',
minWidth: ''
},
showOverlay: false,
direction: 'bottom'
}
function _update (result: any): void {
if (onUpdate !== undefined) onUpdate(result)
@ -55,7 +68,14 @@
const fitPopup = (): void => {
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()
}
}
onMount(() => fitPopup())
$: if (docWidth <= 900 && !docSize) docSize = true
$: if (docWidth > 900 && docSize) docSize = false
afterUpdate(() => fitPopup())
$: if (height) fitPopup()
</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
this={is}
bind:this={componentInstance}
{...props}
direction={options.direction}
bind:options
on:update={(ev) => {
_update(ev.detail)
}}
on:close={(ev) => _close(ev.detail)}
on:fullsize={() => {
fullSize = !fullSize
}}
/>
</div>
<div
class="modal-overlay"
class:antiOverlay={options.show}
class:antiOverlay={options.showOverlay}
style={`z-index: ${zIndex};`}
on:click={() => escapeClose()}
/>
@ -97,6 +137,10 @@
justify-content: center;
max-height: calc(100vh - 2rem);
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 {
position: fixed;

View File

@ -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 { writable } from 'svelte/store'
@ -117,7 +117,7 @@ export function fitPopupPositionedElement (
modalHTML: HTMLElement,
alignment: PopupPositionElement,
newProps: Record<string, string | number>
): { show: boolean, direction: string } {
): PopupOptions {
let direction: string = ''
const rect = alignment.getBoundingClientRect()
const rectPopup = modalHTML.getBoundingClientRect()
@ -159,17 +159,17 @@ export function fitPopupPositionedElement (
direction += '|right'
}
}
return { show: false, direction }
return { props: newProps, showOverlay: false, direction }
}
function applyStyle (values: Record<string, string | number>, modalHTML: HTMLElement): void {
for (const [k, v] of Object.entries(values)) {
const old = (modalHTML.style as any)[k]
if (old !== v) {
;(modalHTML.style as any)[k] = v
}
}
}
// function applyStyle (values: Record<string, string | number>, modalHTML: HTMLElement): void {
// for (const [k, v] of Object.entries(values)) {
// const old = (modalHTML.style as any)[k]
// if (old !== v) {
// ;(modalHTML.style as any)[k] = v
// }
// }
// }
/**
* @public
@ -182,7 +182,7 @@ export function fitPopupElement (
modalHTML: HTMLElement,
element?: PopupAlignment,
contentPanel?: HTMLElement
): { show: boolean, direction: string } {
): PopupOptions {
let show = true
const newProps: Record<string, string | number> = {}
if (element != null) {
@ -192,7 +192,7 @@ export function fitPopupElement (
newProps.maxWidth = newProps.width = newProps.minWidth = ''
if (typeof element !== 'string') {
const result = fitPopupPositionedElement(modalHTML, element, newProps)
applyStyle(newProps, modalHTML)
// applyStyle(newProps, modalHTML)
return result
} else if (element === 'right' && contentPanel !== undefined) {
const rect = contentPanel.getBoundingClientRect()
@ -209,13 +209,20 @@ export function fitPopupElement (
} else if (element === 'float') {
newProps.top = 'calc(var(--status-bar-height) + .25rem)'
newProps.bottom = '.25rem'
newProps.minWidth = '40rem'
newProps.width = '40%'
newProps.left = '60%'
newProps.right = '.25rem'
show = true
} else if (element === 'account') {
newProps.bottom = '2.75rem'
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) {
const rect = contentPanel.getBoundingClientRect()
newProps.top = `${rect.top + 1}px`
@ -248,8 +255,8 @@ export function fitPopupElement (
newProps.transform = 'translate(-50%, -50%)'
show = true
}
applyStyle(newProps, modalHTML)
return { show, direction: '' }
// applyStyle(newProps, modalHTML)
return { props: newProps, showOverlay: show, direction: '' }
}
export function eventToHTMLElement (evt: MouseEvent): HTMLElement {

View File

@ -110,3 +110,10 @@ export interface DropdownIntlItem {
id: string
label: IntlString
}
export interface PopupOptions {
props: Record<string, string | number>
showOverlay: boolean
direction: string
fullSize?: boolean
}

View File

@ -42,7 +42,7 @@
function openAttachment () {
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>

View File

@ -46,7 +46,7 @@
class="flex-center icon"
on:click={() => {
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)}
@ -86,7 +86,7 @@
class="name"
on:click={() => {
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)}

View File

@ -33,7 +33,7 @@
class="content flex-center buttonContainer cursor-pointer"
on:click={() => {
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} />

View File

@ -88,7 +88,7 @@
const el: HTMLElement = ev.currentTarget as HTMLElement
el.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'center' })
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 {
inputFile.click()
}

View File

@ -88,6 +88,8 @@
{object}
isHeader={false}
isAside={true}
isFullSize
on:fullsize
on:close={() => dispatch('close')}
>
<svelte:fragment slot="navigator">

View File

@ -45,7 +45,7 @@
function handleClick () {
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>

View File

@ -64,6 +64,8 @@
<Panel
isHeader={false}
isAside={_class === chunter.class.Channel}
isFullSize
on:fullsize
on:close={() => {
dispatch('close')
}}

View File

@ -28,13 +28,14 @@
} from '@anticrm/ui'
import IconCopy from './icons/Copy.svelte'
import { FocusHandler } from '@anticrm/ui'
import type { PopupOptions } from '@anticrm/ui'
import plugin from '../plugin'
export let value: string = ''
export let placeholder: IntlString
export let editable: boolean | undefined = undefined
export let openable: boolean = false
export let direction: string = 'bottom'
export let options: PopupOptions
const dispatch = createEventDispatcher()
let input: HTMLInputElement
@ -75,11 +76,12 @@
input.addEventListener('focus', updateFocus, { once: true })
}
let dir: string = 'bottom'
const vDir = (d: string): string => d.split('|')[0]
const fitEditor = (): void => {
dir = vDir(direction)
if (options) dir = vDir(options.direction)
}
$: dir = vDir(direction)
$: if (options) dir = vDir(options.direction)
afterUpdate(() => {
fitEditor()
})

View File

@ -76,6 +76,8 @@
<Panel
isHeader={true}
isAside={false}
isFullSize
on:fullsize
on:close={() => {
dispatch('close')
}}

View File

@ -25,6 +25,7 @@
"GotoLeadApplication": "Switch to Lead Application",
"IssueDescriptionPlaceholder": "Add description...",
"CreateCustomer": "Create Customer",
"CreateCustomerLabel": "New Customer"
"CreateCustomerLabel": "New Customer",
"NoLeadsForDocument": "No leads for document"
}
}

View File

@ -25,6 +25,7 @@
"GotoLeadApplication": "Открыть приложение Сделки",
"IssueDescriptionPlaceholder": "Добавить описание...",
"CreateCustomer": "Добавить Клиента",
"CreateCustomerLabel": "Новый Клиент"
"CreateCustomerLabel": "Новый Клиент",
"NoLeadsForDocument": "Нет потенциальных клиентов для документа"
}
}

View File

@ -538,7 +538,7 @@
focusIndex={103}
icon={FileIcon}
on:click={() => {
showPopup(PDFViewer, { file: resume.uuid, name: resume.name }, 'right')
showPopup(PDFViewer, { file: resume.uuid, name: resume.name }, 'float')
}}
>
<svelte:fragment slot="content">

View File

@ -58,6 +58,8 @@
isHeader={false}
isAside={true}
{object}
isFullSize
on:fullsize
on:close={() => {
dispatch('close')
}}

View File

@ -54,6 +54,8 @@
isHeader={false}
isAside={true}
{object}
isFullSize
on:fullsize
on:close={() => {
dispatch('close')
}}

View File

@ -20,7 +20,7 @@
import type { DoneState, Kanban, SpaceWithStates, State } from '@anticrm/task'
import task from '../../plugin'
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 workbench from '@anticrm/workbench'
@ -91,39 +91,35 @@
}
</script>
<div
class="antiOverlay"
on:click={() => {
<Panel
isHeader={false}
isAside={false}
isFullSize
on:fullsize
on:close={() => {
dispatch('close')
}}
/>
<div class="antiDialogs antiComponent">
<div class="ac-header short mirror divide">
<div class="ac-header__wrap-description">
<div class="ac-header__wrap-title">
<div class="ac-header__icon"><Icon icon={task.icon.ManageStatuses} size={'small'} /></div>
<span class="ac-header__title">
>
<svelte:fragment slot="title">
<div class="antiTitle icon-wrapper">
<div class="wrapped-icon">
<Icon icon={task.icon.ManageStatuses} size={'small'} />
</div>
<div class="title-wrapper">
<span class="wrapped-title">
<Label label={task.string.ManageStatusesWithin} />
{#if spaceClassInstance}<Label label={spaceClassInstance?.label} />{:else}...{/if}
</span>
{#if spaceInstance?.name}<span class="wrapped-subtitle">{spaceInstance?.name}</span>{/if}
</div>
{#if spaceInstance?.name}<span class="ac-header__description">{spaceInstance?.name}</span>{/if}
</div>
<div class="tool">
<ActionIcon
icon={IconClose}
size={'small'}
action={() => {
dispatch('close')
}}
/>
</div>
</div>
<div class="p-10 flex-grow">
<ScrollBox vertical stretch>
</svelte:fragment>
<Scroller>
<div class="popupPanel-body__main-content py-10 clear-mins">
{#if kanban !== undefined}
<KanbanEditor {kanban} on:delete={(e) => deleteState(e.detail)} />
{/if}
</ScrollBox>
</div>
</div>
</div>
</Scroller>
</Panel>

View File

@ -75,68 +75,66 @@
}
</script>
<div>
<div class="flex-no-shrink flex-between trans-title uppercase">
<Label label={task.string.ActiveStates} />
<CircleButton
icon={IconAdd}
size={'medium'}
on:click={() => {
onAdd(task.class.State)
}}
/>
</div>
<div class="mt-3">
{#each states as state, i}
{#if state}
<div class="flex-no-shrink flex-between trans-title uppercase">
<Label label={task.string.ActiveStates} />
<CircleButton
icon={IconAdd}
size={'medium'}
on:click={() => {
onAdd(task.class.State)
}}
/>
</div>
<div class="mt-3">
{#each states as state, i}
{#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
bind:this={elements[i]}
class="flex-between states"
draggable={true}
on:dragover|preventDefault={(ev) => {
dragover(ev, i)
class="color"
style="background-color: {getPlatformColor(state.color)}"
on:click={() => {
showPopup(ColorsPopup, {}, elements[i], onColorChange(state))
}}
on:drop|preventDefault={() => {
onMove(i)
}}
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 class="flex-grow caption-color">
<AttributeEditor maxWidth={'20rem'} _class={state._class} object={state} key="title" />
</div>
{/if}
{/each}
</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>
{/if}
{/each}
</div>
<div class="mt-9">
<div class="flex-no-shrink flex-between trans-title uppercase">
@ -189,7 +187,7 @@
}}
/>
</div>
<div class="mt-4">
<div class="mt-4 mb-10">
{#each lostStates as state}
{#if state}
<div class="states flex-row-center">
@ -222,10 +220,10 @@
<style lang="scss">
.states {
padding: 0.5rem 1rem;
color: var(--theme-caption-color);
background-color: var(--theme-button-bg-enabled);
border: 1px solid var(--theme-bg-accent-color);
border-radius: 0.75rem;
color: var(--caption-color);
background-color: var(--button-bg-color);
border: 1px solid var(--button-border-color);
border-radius: 0.5rem;
user-select: none;
.bar {

View File

@ -43,7 +43,7 @@ import AssignedTasks from './components/AssignedTasks.svelte'
import task from './plugin'
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> (

View File

@ -188,6 +188,8 @@
<Panel
isHeader={true}
isAside={false}
isFullSize
on:fullsize
on:close={() => {
dispatch('close')
}}

View File

@ -139,6 +139,8 @@
isSub={false}
withoutActivity={isEditing}
bind:innerWidth
isFullSize
on:fullsize
on:close={() => dispatch('close')}
>
<svelte:fragment slot="subtitle">

View File

@ -228,6 +228,8 @@
isAside={true}
bind:panelWidth
bind:innerWidth
isFullSize
on:fullsize
on:update={(ev) => _update(ev.detail)}
on:close={() => {
dispatch('close')

View File

@ -55,6 +55,8 @@
<Panel
isHeader={false}
isAside={false}
isFullSize
on:fullsize
on:close={() => {
dispatch('close')
}}