UBER-795: replacing the Panel with a Dialog, fix circle button in Kanban. (#3659)

Signed-off-by: Alexander Platov <sas_lord@mail.ru>
This commit is contained in:
Alexander Platov 2023-09-05 18:16:27 +03:00 committed by GitHub
parent ced02f223d
commit b73e5340f7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 257 additions and 312 deletions

View File

@ -534,6 +534,7 @@ input.search {
.pl-8 { padding-left: 2rem; }
.pl-9 { padding-left: 2.25rem; }
.pl-10 { padding-left: 2.5rem; }
.pl-12 { padding-left: 3rem; }
.pr-1 { padding-right: .25rem; }
.pr-2 { padding-right: .5rem; }
.pr-3 { padding-right: .75rem; }
@ -580,6 +581,7 @@ input.search {
.step-lr75 + .step-lr75 { margin-left: .75rem; }
.step-tb25 + .step-tb25 { margin-top: .25rem; }
.step-tb375 + .step-tb375 { margin-top: .375rem; }
.step-tb5 + .step-tb5 { margin-top: .5rem; }
.step-tb75 + .step-tb75 { margin-top: .75rem; }
.step-tb-6 + .step-tb-6 { margin-top: 1.5rem; }
.step-tb-12 + .step-tb-12 { margin-top: 3rem; }
@ -686,6 +688,7 @@ input.search {
.min-h-8 { min-height: 2rem; }
.min-h-9 { min-height: 2.25rem; }
.min-h-11 { min-height: 2.75rem; }
.min-h-12 { min-height: 3rem; }
.min-h-30 { min-height: 7.5rem; }
.min-h-60 { min-height: 15rem; }
.max-w-2 { max-width: .5rem; }
@ -919,6 +922,7 @@ a.no-line {
}
.background-body-color { background-color: var(--theme-bg-color); }
.background-bg-accent-color { background-color: var(--theme-bg-accent-color); }
.background-accent-bg-color { background-color: var(--accent-bg-color); }
.background-highlight-select { background-color: var(--highlight-select); }
.background-highlight-red { background-color: var(--highlight-red); }

View File

@ -334,13 +334,13 @@
.wrapped-icon, &.wrapped-icon {
margin-right: .75rem;
color: var(--content-color);
color: var(--theme-content-color);
}
.wrapped-title, &.wrapped-title {
min-width: 0;
font-weight: 500;
font-size: 1rem;
color: var(--caption-color);
color: var(--theme-caption-color);
overflow: hidden;
text-overflow: ellipsis;
@ -349,7 +349,7 @@
.wrapped-subtitle, &.wrapped-subtitle {
min-width: 0;
font-size: 0.75rem;
color: var(--dark-color);
color: var(--theme-dark-color);
overflow: hidden;
visibility: visible;
@ -360,7 +360,7 @@
line-clamp: 2;
user-select: text;
b { color: var(--content-color); }
b { color: var(--theme-content-color); }
}
}

View File

@ -1098,7 +1098,7 @@
}
/* Kanban - global style */
.kanban-container .card-container .antiButton.link-bordered { padding: 0 .5rem; }
.kanban-container .card-container .antiButton.link-bordered { padding: 0 .5rem !important; }
.kanban-container .card-container .card-labels > *:not(.labels-container),
.kanban-container .card-container .card-labels.labels .labels-container > * {
margin: .25rem .25rem 0 0;

View File

@ -294,3 +294,59 @@
}
}
}
/* Dialog */
.antiDialog {
display: flex;
flex-direction: column;
height: 100%;
min-width: 25rem;
min-height: 0;
background-color: var(--theme-popup-color);
border-radius: .5rem;
&:not(.fullsize) {
max-width: calc(100vw - 2rem);
border: 1px solid var(--theme-popup-divider);
box-shadow: var(--theme-popup-shadow);
}
&.fullsize {
width: 100%;
height: 100%;
max-width: 100%;
max-height: 100%;
}
.header {
flex-shrink: 0;
padding: .25rem .5rem;
background-color: var(--theme-popup-header);
border-bottom: 1px solid var(--theme-popup-divider);
border-radius: .5rem .5rem 0 0;
.title {
flex-grow: 1;
font-size: 1rem;
color: var(--theme-caption-color);
}
}
.content {
display: flex;
flex-direction: column;
flex-grow: 1;
min-width: 0;
min-height: 0;
&.rounded { border-radius: 0 0 .5rem .5rem; }
}
.footer {
display: flex;
justify-content: space-between;
align-items: center;
flex-shrink: 0;
padding: .25rem .5rem;
border-top: 1px solid var(--theme-popup-divider);
border-radius: 0 0 .5rem .5rem;
}
}

View File

@ -20,6 +20,7 @@
export let label: IntlString | undefined = undefined
export let isFullSize: boolean = false
export let padding: string = '1rem'
const dispatch = createEventDispatcher()
@ -27,7 +28,7 @@
</script>
<form
class="dialog-container"
class="antiDialog"
class:fullsize={fullSize}
on:submit|preventDefault={() => {}}
use:resizeObserver={() => {
@ -37,10 +38,10 @@
<div class="flex-between header">
<div class="flex-row-center gap-1-5">
<Button icon={IconClose} kind={'ghost'} size={'medium'} on:click={() => dispatch('close')} />
<div class="title">
{#if label}<Label {label} />{/if}
{#if $$slots.title}<slot name="title" />{/if}
</div>
{#if label}
<span class="title"><Label {label} /></span>
{/if}
{#if $$slots.title}<slot name="title" />{/if}
</div>
<div class="flex-row-center gap-1-5">
{#if $$slots.utils}
@ -64,7 +65,7 @@
{/if}
</div>
</div>
<div class="content" class:rounded={!($$slots.footerLeft || $$slots.footerRight)}>
<div class="content" class:rounded={!($$slots.footerLeft || $$slots.footerRight)} style:padding>
<slot />
</div>
{#if $$slots.footerLeft || $$slots.footerRight}
@ -82,61 +83,3 @@
</div>
{/if}
</form>
<style lang="scss">
.dialog-container {
display: flex;
flex-direction: column;
min-width: 25rem;
max-width: calc(100vw - 2rem);
min-height: 0;
max-height: 80vh;
background-color: var(--theme-popup-color);
border-radius: 0.5rem;
&:not(.fullsize) {
border: 1px solid var(--theme-popup-divider);
box-shadow: var(--theme-popup-shadow);
}
&.fullsize {
width: 100%;
height: 100%;
max-width: 100%;
max-height: 100%;
}
.header {
flex-shrink: 0;
padding: 0.5rem;
background-color: var(--theme-popup-header);
border-bottom: 1px solid var(--theme-popup-divider);
border-radius: 0.5rem 0.5rem 0 0;
.title {
flex-grow: 1;
font-size: 1rem;
color: var(--theme-caption-color);
}
}
.content {
display: flex;
flex-direction: column;
padding: 1rem;
min-width: 0;
min-height: 0;
&.rounded {
border-radius: 0 0 0.5rem 0.5rem;
}
}
.footer {
display: flex;
justify-content: space-between;
align-items: center;
flex-shrink: 0;
padding: 0.25rem 0.5rem;
border-top: 1px solid var(--theme-popup-divider);
border-radius: 0 0 0.5rem 0.5rem;
}
}
</style>

View File

@ -94,61 +94,51 @@
}
</script>
<div class="popupPanel-body__main-header bottom-divider p-2">
<div class="flex-between">
{#if selectable}
<span><b>{selected.size}</b> <Label label={gmail.string.MessagesSelected} /></span>
<div class="flex">
<div>
<Button label={gmail.string.Cancel} size={'small'} on:click={clear} />
</div>
<div class="ml-3">
<Button
label={gmail.string.PublishSelected}
size={'small'}
kind={'accented'}
disabled={!selected.size}
on:click={share}
/>
</div>
</div>
{:else}
{#if enabled}
<Button
label={gmail.string.CreateMessage}
size={'small'}
kind={'accented'}
on:click={() => {
newMessage = true
}}
/>
{/if}
<div class="flex-between bottom-divider min-h-12 px-2">
{#if selectable}
<span class="pl-2"><b>{selected.size}</b> <Label label={gmail.string.MessagesSelected} /></span>
<div class="flex-row-center gap-3">
<Button label={gmail.string.Cancel} on:click={clear} />
<Button label={gmail.string.PublishSelected} kind={'accented'} disabled={!selected.size} on:click={share} />
</div>
{:else}
{#if enabled}
<Button
icon={IconShare}
kind={'ghost'}
showTooltip={{ label: gmail.string.ShareMessages }}
on:click={async () => {
selectable = !selectable
label={gmail.string.CreateMessage}
kind={'accented'}
on:click={() => {
newMessage = true
}}
/>
{/if}
</div>
</div>
<Scroller>
<div class="popupPanel-body__main-content py-4 clear-mins flex-no-shrink">
{#if messages && messages.length > 0}
<Messages
messages={convertMessages(object, channel, messages, $personAccountByIdStore, $employeeByIdStore)}
{selectable}
bind:selected
on:select
/>
<div class="clear-mins h-4 flex-no-shrink" />
{:else}
<div class="flex-col-center justify-center h-full">
<Icon icon={IconInbox} size={'full'} />
<div class="mt-4 fs-bold content-dark-color"><Label label={plugin.string.Incoming} /></div>
</div>
<div />
{/if}
<Button
icon={IconShare}
kind={'ghost'}
showTooltip={{ label: gmail.string.ShareMessages }}
on:click={async () => {
selectable = !selectable
}}
/>
{/if}
</div>
{#if messages && messages.length > 0}
<div class="antiVSpacer x2" />
<Scroller padding={'.5rem 1rem'}>
<Messages
messages={convertMessages(object, channel, messages, $personAccountByIdStore, $employeeByIdStore)}
{selectable}
bind:selected
on:select
/>
<div class="antiVSpacer x2" />
</Scroller>
<div class="antiVSpacer x2" />
{:else}
<div class="flex-col-center justify-center h-full">
<Icon icon={IconInbox} size={'full'} />
<div class="mt-4 fs-bold content-dark-color"><Label label={plugin.string.Incoming} /></div>
</div>
</Scroller>
{/if}

View File

@ -57,81 +57,56 @@
$: user = currentMessage.incoming ? currentMessage.receiver : currentMessage.sender
</script>
<div class="popupPanel-body__main-header bottom-divider">
<div class="flex-between p-2">
<div class="flex-row-center clear-mins">
<Button
icon={IconArrowLeft}
kind={'ghost'}
on:click={() => {
dispatch('close')
}}
/>
<div class="flex-grow flex-col clear-mins ml-2 mr-2">
<div class="overflow-label" use:tooltip={{ label: getEmbeddedLabel(currentMessage.subject) }}>
{currentMessage.subject}
</div>
<span class="content-color">
<Label label={currentMessage.incoming ? gmail.string.From : gmail.string.To} />
<b>{title}</b>
</span>
<div class="flex-between min-h-12 px-2">
<div class="flex-row-center clear-mins">
<Button
icon={IconArrowLeft}
kind={'ghost'}
on:click={() => {
dispatch('close')
}}
/>
<div class="flex-grow flex-col clear-mins ml-2 mr-2">
<div class="overflow-label" use:tooltip={{ label: getEmbeddedLabel(currentMessage.subject) }}>
{currentMessage.subject}
</div>
</div>
<div class="buttons-group small-gap">
<Button
label={hasError ? gmail.string.Resend : gmail.string.Reply}
size={'small'}
kind={'accented'}
on:click={() => {
if (hasError) {
resendMessage()
dispatch('close')
} else newMessage = true
}}
/>
<span class="content-color">
<Label label={currentMessage.incoming ? gmail.string.From : gmail.string.To} />
<b>{title}</b>
</span>
</div>
</div>
<Button
label={hasError ? gmail.string.Resend : gmail.string.Reply}
on:click={() => {
if (hasError) {
resendMessage()
dispatch('close')
} else newMessage = true
}}
/>
</div>
<Scroller>
<div class="popupPanel-body__main-content py-4 h-full">
<Label label={currentMessage.incoming ? gmail.string.To : gmail.string.From} />
{user}
{#if currentMessage.copy?.length}
<Label label={gmail.string.Copy} />: {currentMessage.copy.join(', ')}
{/if}
{#if attachments.length}
<div class="flex-row-center list mt-2">
{#each attachments as attachment}
<div class="item flex">
<AttachmentPresenter value={attachment} showPreview />
</div>
{/each}
</div>
{/if}
<div class="flex-col content clear-mins h-full">
<FullMessageContent content={currentMessage.content} />
</div>
<div class="flex-col justify-center bottom-divider min-h-8 pl-12 pt-2 pb-2 pr-2">
<div class="flex-row-center gap-2">
<Label label={currentMessage.incoming ? gmail.string.To : gmail.string.From} />&nbsp;
<b>{user}</b>
</div>
{#if currentMessage.copy?.length}
<Label label={gmail.string.Copy} />: {currentMessage.copy.join(', ')}
{/if}
</div>
{#if attachments.length}
<div class="flex-row-center background-bg-accent-color bottom-divider">
<Scroller padding={'.5rem'} gap={'gap-2'} horizontal contentDirection={'horizontal'} noFade={false}>
{#each attachments as attachment}
<AttachmentPresenter value={attachment} showPreview />
{/each}
</Scroller>
{#if attachments.length}<div class="antiHSpacer x2" />{/if}
</div>
{/if}
<Scroller padding={'1rem'}>
<FullMessageContent content={currentMessage.content} />
</Scroller>
<style lang="scss">
.list {
padding: 0.5rem;
color: var(--caption-color);
overflow-x: auto;
overflow-y: hidden;
background-color: var(--accent-bg-color);
border: 1px solid var(--divider-color);
border-radius: 0.25rem;
.item + .item {
padding-left: 1rem;
border-left: 1px solid var(--divider-color);
}
}
.content {
margin-top: 1rem;
background-color: var(--incoming-msg);
border-radius: 0.25rem;
}
</style>

View File

@ -23,7 +23,7 @@
import { createQuery, getClient } from '@hcengineering/presentation'
import setting, { Integration } from '@hcengineering/setting'
import templates, { TemplateDataProvider } from '@hcengineering/templates'
import { Button, Icon, Label, Panel, eventToHTMLElement, showPopup } from '@hcengineering/ui'
import { Button, Icon, Label, Dialog, eventToHTMLElement, showPopup } from '@hcengineering/ui'
import { createEventDispatcher, onDestroy } from 'svelte'
import gmail from '../plugin'
import { convertMessage } from '../utils'
@ -94,23 +94,21 @@
</script>
{#if channel && object}
<Panel
isHeader={true}
isAside={false}
<Dialog
isFullSize
{embedded}
padding={'0'}
on:fullsize
on:close={() => {
dispatch('close')
}}
>
<svelte:fragment slot="title">
<div class="antiTitle icon-wrapper">
<div class="wrapped-icon"><Icon icon={contact.icon.Email} size={'medium'} /></div>
<div class="antiTitle icon-wrapper ml-2">
<div class="wrapped-icon"><Icon icon={contact.icon.Email} size={'small'} /></div>
<div class="title-wrapper">
<span class="wrapped-title">Email</span>
<span class="wrapped-subtitle">
<b>{getName(client.getHierarchy(), object)}</b>
{getName(client.getHierarchy(), object)}
</span>
</div>
</div>
@ -121,13 +119,14 @@
<Button
label={gmail.string.Connect}
kind={'accented'}
size={'medium'}
on:click={(e) => {
showPopup(Connect, {}, eventToHTMLElement(e))
}}
/>
{:else}
<Label label={gmail.string.From} />
<IntegrationSelector bind:selected={selectedIntegration} {integrations} />
<span class="content-darker-color text-sm mr-1-5"><Label label={gmail.string.From} /></span>
<IntegrationSelector bind:selected={selectedIntegration} {integrations} size={'medium'} kind={'ghost'} />
{/if}
</svelte:fragment>
@ -138,5 +137,5 @@
{:else}
<Chats {object} {channel} bind:newMessage enabled={integrations.length > 0} on:select={selectHandler} />
{/if}
</Panel>
</Dialog>
{/if}

View File

@ -30,8 +30,9 @@
const dispatch = createEventDispatcher()
</script>
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div
class="flex-row-center clear-mins message-conatiner"
class="flex-row-center clear-mins message-conatiner step-tb5"
on:click|preventDefault={() => {
dispatch('select', message)
}}
@ -42,8 +43,8 @@
<Label label={gmail.string.From} />
<span class="content-color">{message.sender}</span>
</div>
<div class="content-dark-color flex">
<AttachmentsPresenter value={message.attachments} object={message} />
<div class="content-dark-color flex-row-center gap-3">
<AttachmentsPresenter value={message.attachments} object={message} size={'x-small'} />
<span class="content-color">{!isError ? getTime(message.sendOn) : getTime(message.modifiedOn)}</span>
</div>
</div>
@ -75,7 +76,6 @@
<style lang="scss">
.message-conatiner {
flex-shrink: 0;
margin: 0.25rem 0;
cursor: pointer;
}

View File

@ -92,6 +92,8 @@
}
function fileDrop (e: DragEvent) {
e.preventDefault()
e.stopPropagation()
const list = e.dataTransfer?.files
if (list === undefined || list.length === 0) return
for (let index = 0; index < list.length; index++) {
@ -167,94 +169,74 @@
style="display: none"
on:change={fileSelected}
/>
<div class="popupPanel-body__main-header bottom-divider p-2">
<div class="flex-between">
<div class="buttons-group">
<Button
icon={IconArrowLeft}
kind={'ghost'}
on:click={() => {
dispatch('close')
}}
/>
<div class="flex-grow flex-col">
<Label label={plugin.string.NewMessage} />
<span class="content-color"><b>{getName(client.getHierarchy(), object)} ({channel.value})</b></span>
</div>
</div>
<div class="buttons-group small-gap">
<Button
icon={IconAttachment}
kind={'ghost'}
on:click={() => {
inputFile.click()
}}
/>
<Button label={plugin.string.Send} size={'small'} kind={'accented'} on:click={sendMsg} />
<div class="flex-between bottom-divider min-h-12 px-2">
<div class="buttons-group">
<Button
icon={IconArrowLeft}
kind={'ghost'}
on:click={() => {
dispatch('close')
}}
/>
<div class="flex-grow flex-col">
<Label label={plugin.string.NewMessage} />
<span class="content-color"><b>{getName(client.getHierarchy(), object)} ({channel.value})</b></span>
</div>
</div>
<div class="buttons-group small-gap">
<Button
icon={IconAttachment}
kind={'ghost'}
on:click={() => {
inputFile.click()
}}
/>
<Button label={plugin.string.Send} kind={'accented'} on:click={sendMsg} />
</div>
</div>
<Scroller>
<div
class="popupPanel-body__main-content py-4 h-full"
on:dragover|preventDefault={() => {}}
on:dragleave={() => {}}
on:drop|preventDefault|stopPropagation={fileDrop}
>
<div class="mb-2">
<EditBox label={plugin.string.Subject} bind:value={obj.subject} placeholder={plugin.string.SubjectPlaceholder} />
</div>
<div>
<EditBox label={plugin.string.Copy} bind:value={copy} placeholder={plugin.string.CopyPlaceholder} />
</div>
{#if attachments.length}
<div class="flex-row-center list mt-2 scroll-divider-color">
{#each attachments as attachment}
<div class="item flex-row-center flex-no-shrink">
<AttachmentPresenter
value={attachment}
showPreview
removable
on:remove={(result) => {
if (result !== undefined) removeAttachment(attachment)
}}
/>
</div>
{/each}
</div>
{/if}
<div class="input mt-4 clear-mins">
<StyledTextEditor full bind:content={obj.content} maxHeight="panel" on:template={onTemplate} />
</div>
{#if attachments.length}
<div class="flex-row-center background-bg-accent-color bottom-divider">
<Scroller padding={'.5rem'} gap={'gap-2'} horizontal contentDirection={'horizontal'} noFade={false}>
{#each attachments as attachment}
<AttachmentPresenter
value={attachment}
showPreview
removable
on:remove={(result) => {
if (result !== undefined) removeAttachment(attachment)
}}
/>
{/each}
</Scroller>
{#if attachments.length}<div class="antiHSpacer x2" />{/if}
</div>
{/if}
<div class="antiVSpacer x2" />
<Scroller padding={'.5rem 1rem'} on:drop={fileDrop}>
<div class="mb-2">
<EditBox label={plugin.string.Subject} bind:value={obj.subject} placeholder={plugin.string.SubjectPlaceholder} />
</div>
<div>
<EditBox label={plugin.string.Copy} bind:value={copy} placeholder={plugin.string.CopyPlaceholder} />
</div>
<div class="input clear-mins">
<StyledTextEditor full bind:content={obj.content} maxHeight={'max'} on:template={onTemplate} />
</div>
</Scroller>
<div class="antiVSpacer x2" />
<style lang="scss">
.list {
padding: 0.5rem;
color: var(--caption-color);
overflow-x: auto;
overflow-y: hidden;
background-color: var(--accent-bg-color);
border: 1px solid var(--divider-color);
border-radius: 0.25rem;
.item + .item {
padding-left: 1rem;
border-left: 1px solid var(--divider-color);
}
}
.input {
overflow: auto;
margin-top: 1rem;
padding: 1rem;
background-color: var(--outcoming-msg);
color: #d6d6d6;
caret-color: var(--theme-caret-color);
min-height: 0;
margin-bottom: 2rem;
height: 100%;
min-height: 0;
color: #d6d6d6;
background-color: var(--theme-bg-color);
border-radius: 0.25rem;
caret-color: var(--theme-caret-color);
:global(.ProseMirror) {
min-height: 0;

View File

@ -30,7 +30,7 @@
Icon,
IconShare,
Label,
Panel,
Dialog,
Scroller,
eventToHTMLElement,
showPopup,
@ -215,10 +215,7 @@
</script>
{#if object !== undefined}
<Panel
isHeader={true}
isAside={false}
{embedded}
<Dialog
isFullSize
on:fullsize
on:close={() => {
@ -226,21 +223,19 @@
}}
>
<svelte:fragment slot="title">
<div class="antiTitle icon-wrapper">
<div class="wrapped-icon"><Icon icon={TelegramIcon} size={'medium'} /></div>
<div class="title-wrapper">
<div class="wrapped-title flex">
Telegram
{#each participants as participant}
<div
class="ml-2"
use:tooltip={{ label: getEmbeddedLabel(getContactName(client.getHierarchy(), participant)) }}
>
<Avatar size="x-small" avatar={participant.avatar} />
</div>
{/each}
</div>
<div class="antiTitle icon-wrapper ml-2">
<div class="wrapped-icon"><Icon icon={TelegramIcon} size={'small'} /></div>
<div class="title-wrapper mr-2">
<div class="wrapped-title flex-row-center">Telegram</div>
</div>
{#each participants as participant}
<div
class="ml-2"
use:tooltip={{ label: getEmbeddedLabel(getContactName(client.getHierarchy(), participant)) }}
>
<Avatar size="small" avatar={participant.avatar} />
</div>
{/each}
</div>
</svelte:fragment>
<svelte:fragment slot="utils">
@ -307,17 +302,18 @@
/>
{/if}
</div>
</Panel>
</Dialog>
{/if}
<style lang="scss">
.ref-input {
padding: 0.5rem 0 1.5rem;
padding-top: 0.5rem;
&.selectable {
padding: 1rem;
color: var(--caption-color);
border-top: 1px solid var(--divider-color);
margin-top: 0.5rem;
padding-top: 1rem;
color: var(--theme-caption-color);
border-top: 1px solid var(--theme-divider-color);
}
}
</style>

View File

@ -133,7 +133,7 @@
}
.message {
padding: 0.5rem 0.75rem;
max-width: 66%;
max-width: 90%;
width: fit-content;
background-color: var(--incoming-msg);
border-radius: 0.75rem 0.75rem 0.75rem 0.125rem;

View File

@ -27,8 +27,8 @@
<style lang="scss">
.container {
padding: 1rem;
background-color: var(--accent-bg-color);
border: 1px solid var(--divider-color);
border-radius: 0.75rem;
background-color: var(--theme-bg-accent-color);
border: 1px solid var(--theme-divider-color);
border-radius: 0.5rem;
}
</style>