Board: fix popup alignments (#1467)

Signed-off-by: Anna No <anna.no@xored.com>
This commit is contained in:
Anna No 2022-04-20 23:33:56 +07:00 committed by GitHub
parent fd717a9d59
commit b684014b42
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 82 additions and 53 deletions

View File

@ -117,7 +117,7 @@ export class TCardAction extends TDoc implements CardAction {
label!: IntlString label!: IntlString
position!: number position!: number
type!: string type!: string
handler?: Resource<(card: Card, client: Client) => void> handler?: Resource<(card: Card, client: Client, e?: Event) => void>
supported?: Resource<(card: Card, client: Client) => boolean> supported?: Resource<(card: Card, client: Client) => boolean>
} }

View File

@ -99,10 +99,10 @@
label={action.label} label={action.label}
kind={action.kind ?? 'no-border'} kind={action.kind ?? 'no-border'}
justify="left" justify="left"
on:click={async () => { on:click={async (e) => {
if (action.handler) { if (action.handler) {
const handler = await getResource(action.handler) const handler = await getResource(action.handler)
handler(value, client) handler(value, client, e)
} }
}} }}
/> />

View File

@ -2,12 +2,12 @@
import { createEventDispatcher } from 'svelte' import { createEventDispatcher } from 'svelte'
import { Label, Button, ActionIcon, IconClose, EditBox } from '@anticrm/ui' import { Label, Button, ActionIcon, IconClose, EditBox } from '@anticrm/ui'
import board from '../../plugin' import board from '../../plugin'
import { getClient } from '@anticrm/presentation'; import { getClient } from '@anticrm/presentation'
import { Attachment } from '@anticrm/attachment'; import { Attachment } from '@anticrm/attachment'
export let object: Attachment export let object: Attachment
let {name} = object let { name } = object
const client = getClient() const client = getClient()
const dispatch = createEventDispatcher() const dispatch = createEventDispatcher()
@ -19,8 +19,8 @@
<div class="flex-center flex-grow"> <div class="flex-center flex-grow">
<Label label={board.string.Edit}/> <Label label={board.string.Edit}/>
</div> </div>
<div class="close-icon"> <div class="close-icon mr-1">
<ActionIcon icon={IconClose} size={'small'} action={() => {dispatch("close")}} /> <ActionIcon icon={IconClose} size={'small'} action={() => { dispatch('close') }} />
</div> </div>
</div> </div>
<div class="ap-space bottom-divider"/> <div class="ap-space bottom-divider"/>
@ -36,7 +36,7 @@
kind={'primary'} kind={'primary'}
on:click={() => { on:click={() => {
if (!name) return if (!name) return
client.update(object, {name}) client.update(object, { name })
dispatch('close') dispatch('close')
}} }}
/> />

View File

@ -2,8 +2,8 @@
import { createEventDispatcher } from 'svelte' import { createEventDispatcher } from 'svelte'
import { Label, Button, ActionIcon, IconClose } from '@anticrm/ui' import { Label, Button, ActionIcon, IconClose } from '@anticrm/ui'
import board from '../../plugin' import board from '../../plugin'
import { getClient } from '@anticrm/presentation'; import { getClient } from '@anticrm/presentation'
import { Attachment } from '@anticrm/attachment'; import { Attachment } from '@anticrm/attachment'
export let object: Attachment export let object: Attachment
@ -17,8 +17,8 @@
<div class="flex-center flex-grow"> <div class="flex-center flex-grow">
<Label label={board.string.Delete} /> <Label label={board.string.Delete} />
</div> </div>
<div class="close-icon"> <div class="close-icon mr-1">
<ActionIcon icon={IconClose} size={'small'} action={() => {dispatch("close")}} /> <ActionIcon icon={IconClose} size={'small'} action={() => { dispatch('close') }} />
</div> </div>
</div> </div>
<div class="ap-space bottom-divider"/> <div class="ap-space bottom-divider"/>

View File

@ -12,21 +12,20 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
--> -->
<script lang="ts"> <script lang="ts">
import type { Attachment } from '@anticrm/attachment' import type { Attachment } from '@anticrm/attachment'
import { PDFViewer, getFileUrl } from '@anticrm/presentation' import { PDFViewer, getFileUrl } from '@anticrm/presentation'
import { Button, showPopup, TimeSince, closeTooltip } from '@anticrm/ui' import { Button, showPopup, TimeSince, closeTooltip } from '@anticrm/ui'
import board from '../../plugin' import board from '../../plugin'
import EditAttachment from '../popups/EditAttachment.svelte'; import { getPopupAlignment } from '../../utils/PopupUtils'
import RemoveAttachment from '../popups/RemoveAttachment.svelte'; import EditAttachment from '../popups/EditAttachment.svelte'
import RemoveAttachment from '../popups/RemoveAttachment.svelte'
export let value: Attachment export let value: Attachment
const maxLenght: number = 30 const maxLenght: number = 30
const trimFilename = (fname: string): string => (fname.length > maxLenght) const trimFilename = (fname: string): string =>
? fname.substr(0, (maxLenght - 1) / 2) + '...' + fname.substr(-(maxLenght - 1) / 2) fname.length > maxLenght ? fname.substr(0, (maxLenght - 1) / 2) + '...' + fname.substr(-(maxLenght - 1) / 2) : fname
: fname
function iconLabel (name: string): string { function iconLabel (name: string): string {
const parts = name.split('.') const parts = name.split('.')
@ -39,10 +38,11 @@
} }
const handleClick = openEmbedded(value.type) const handleClick = openEmbedded(value.type)
? () => { ? () => {
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 }, 'right')
} : undefined }
: undefined
</script> </script>
<div class="flex-row-center"> <div class="flex-row-center">
@ -51,14 +51,26 @@
<img src={getFileUrl(value.file)} alt={value.name} /> <img src={getFileUrl(value.file)} alt={value.name} />
</div> </div>
{:else} {:else}
<a class="no-line" href={getFileUrl(value.file)} download={value.name}><div class="flex-center icon">{iconLabel(value.name)}</div></a> <a class="no-line" href={getFileUrl(value.file)} download={value.name}><div class="flex-center icon">
{iconLabel(value.name)}
</div></a>
{/if} {/if}
<div class="flex-col-centre info"> <div class="flex-col-centre info">
<div class="fs-title">{trimFilename(value.name)}</div> <div class="fs-title">{trimFilename(value.name)}</div>
<div class="flex-row-center"> <div class="flex-row-center flex-gap-1">
<TimeSince value={value.lastModified}/> <TimeSince value={value.lastModified} />
<Button label={board.string.Edit} on:click={() => {showPopup(EditAttachment, {object: value})}} kind="transparent"/> <Button
<Button label={board.string.Delete} on:click={() => {showPopup(RemoveAttachment, {object: value})}} kind="transparent"/> label={board.string.Edit}
on:click={(e) => {
showPopup(EditAttachment, { object: value }, getPopupAlignment(e))
}}
kind="transparent" />
<Button
label={board.string.Delete}
on:click={(e) => {
showPopup(RemoveAttachment, { object: value }, getPopupAlignment(e))
}}
kind="transparent" />
</div> </div>
</div> </div>
</div> </div>
@ -73,8 +85,8 @@
font-size: 1rem; font-size: 1rem;
color: var(--primary-button-color); color: var(--primary-button-color);
background-color: var(--primary-button-enabled); background-color: var(--primary-button-enabled);
border: 1px solid rgba(0, 0, 0, .1); border: 1px solid rgba(0, 0, 0, 0.1);
border-radius: .5rem; border-radius: 0.5rem;
} }
.content { .content {
width: 8rem; width: 8rem;

View File

@ -20,6 +20,7 @@ import { Ref } from '@anticrm/core'
import contact, { Employee } from '@anticrm/contact' import contact, { Employee } from '@anticrm/contact'
import { showPopup } from '@anticrm/ui' import { showPopup } from '@anticrm/ui'
import { Card } from '@anticrm/board' import { Card } from '@anticrm/board'
import type { TxOperations as Client } from '@anticrm/core'
import { Resources } from '@anticrm/platform' import { Resources } from '@anticrm/platform'
import { TxOperations } from '@anticrm/core' import { TxOperations } from '@anticrm/core'
import CardPresenter from './components/CardPresenter.svelte' import CardPresenter from './components/CardPresenter.svelte'
@ -46,17 +47,18 @@ import {
unarchiveCard, unarchiveCard,
deleteCard deleteCard
} from './utils/CardUtils' } from './utils/CardUtils'
import { getPopupAlignment } from './utils/PopupUtils'
async function showMoveCardPopup (object: Card): Promise<void> { async function showMoveCardPopup (object: Card, client: Client, e?: Event): Promise<void> {
showPopup(MoveView, { object }) showPopup(MoveView, { object }, getPopupAlignment(e))
} }
async function showDatePickerPopup (object: Card): Promise<void> { async function showDatePickerPopup (object: Card, client: Client, e?: Event): Promise<void> {
showPopup(DateRangePicker, { object }) showPopup(DateRangePicker, { object }, getPopupAlignment(e))
} }
async function showCardLabelsPopup (object: Card): Promise<void> { async function showCardLabelsPopup (object: Card, client: Client, e?: Event): Promise<void> {
showPopup(CardLabelsPopup, { object }) showPopup(CardLabelsPopup, { object }, getPopupAlignment(e))
} }
async function showEditMembersPopup(object: Card, client: TxOperations): Promise<void> { async function showEditMembersPopup(object: Card, client: TxOperations): Promise<void> {

View File

@ -0,0 +1,15 @@
import { PopupAlignment } from '@anticrm/ui'
export function getPopupAlignment (e?: Event): PopupAlignment | undefined {
if (!e || !e.target) {
return undefined
}
const target = e.target as HTMLElement
if (target.getBoundingClientRect) {
return {
getBoundingClientRect: () => target.getBoundingClientRect()
}
}
return undefined
}

View File

@ -91,7 +91,7 @@ export interface CardAction extends Doc {
label: IntlString label: IntlString
position: number position: number
type: string type: string
handler?: Resource<(card: Card, client: Client) => void> handler?: Resource<(card: Card, client: Client, e?: Event) => void>
supported?: Resource<(card: Card, client: Client) => boolean> supported?: Resource<(card: Card, client: Client) => boolean>
} }
@ -148,22 +148,22 @@ const boards = plugin(boardId, {
Delete: '' as Ref<CardAction> Delete: '' as Ref<CardAction>
}, },
cardActionHandler: { cardActionHandler: {
Cover: '' as Resource<(card: Card, client: Client) => void>, Cover: '' as Resource<(card: Card, client: Client, e?: Event) => void>,
Join: '' as Resource<(card: Card, client: Client) => void>, Join: '' as Resource<(card: Card, client: Client, e?: Event) => void>,
Members: '' as Resource<(card: Card, client: Client) => void>, Members: '' as Resource<(card: Card, client: Client, e?: Event) => void>,
Labels: '' as Resource<(card: Card, client: Client) => void>, Labels: '' as Resource<(card: Card, client: Client, e?: Event) => void>,
Checklist: '' as Resource<(card: Card, client: Client) => void>, Checklist: '' as Resource<(card: Card, client: Client, e?: Event) => void>,
Dates: '' as Resource<(card: Card, client: Client) => void>, Dates: '' as Resource<(card: Card, client: Client, e?: Event) => void>,
Attachments: '' as Resource<(card: Card, client: Client) => void>, Attachments: '' as Resource<(card: Card, client: Client, e?: Event) => void>,
CustomFields: '' as Resource<(card: Card, client: Client) => void>, CustomFields: '' as Resource<(card: Card, client: Client, e?: Event) => void>,
AddButton: '' as Resource<(card: Card, client: Client) => void>, AddButton: '' as Resource<(card: Card, client: Client, e?: Event) => void>,
Move: '' as Resource<(card: Card, client: Client) => void>, Move: '' as Resource<(card: Card, client: Client, e?: Event) => void>,
Copy: '' as Resource<(card: Card, client: Client) => void>, Copy: '' as Resource<(card: Card, client: Client, e?: Event) => void>,
MakeTemplate: '' as Resource<(card: Card, client: Client) => void>, MakeTemplate: '' as Resource<(card: Card, client: Client, e?: Event) => void>,
Watch: '' as Resource<(card: Card, client: Client) => void>, Watch: '' as Resource<(card: Card, client: Client, e?: Event) => void>,
Archive: '' as Resource<(card: Card, client: Client) => void>, Archive: '' as Resource<(card: Card, client: Client, e?: Event) => void>,
SendToBoard: '' as Resource<(card: Card, client: Client) => void>, SendToBoard: '' as Resource<(card: Card, client: Client, e?: Event) => void>,
Delete: '' as Resource<(card: Card, client: Client) => void> Delete: '' as Resource<(card: Card, client: Client, e?: Event) => void>
}, },
cardActionSupportedHandler: { cardActionSupportedHandler: {
Join: '' as Resource<(card: Card, client: Client) => boolean>, Join: '' as Resource<(card: Card, client: Client) => boolean>,