mirror of
https://github.com/hcengineering/platform.git
synced 2025-04-12 19:30:52 +00:00
Inbox as popup (#2957)
Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
This commit is contained in:
parent
3c0fdc9698
commit
981cbada6a
@ -15,7 +15,7 @@
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { ObjectSearchPopup, ObjectSearchResult } from '@hcengineering/presentation'
|
||||
import { showPopup, resizeObserver, deviceOptionsStore as deviceInfo } from '@hcengineering/ui'
|
||||
import { showPopup, resizeObserver, deviceOptionsStore as deviceInfo, PopupResult } from '@hcengineering/ui'
|
||||
import { onDestroy, onMount } from 'svelte'
|
||||
import DummyPopup from './DummyPopup.svelte'
|
||||
|
||||
@ -25,10 +25,10 @@
|
||||
export let close: () => void
|
||||
|
||||
let popup: HTMLDivElement
|
||||
let popupClose: () => void
|
||||
let dummyPopup: PopupResult
|
||||
|
||||
onMount(() => {
|
||||
popupClose = showPopup(
|
||||
dummyPopup = showPopup(
|
||||
DummyPopup,
|
||||
{},
|
||||
undefined,
|
||||
@ -39,7 +39,7 @@
|
||||
})
|
||||
|
||||
onDestroy(() => {
|
||||
popupClose()
|
||||
dummyPopup.close()
|
||||
})
|
||||
|
||||
function dispatchItem (item: ObjectSearchResult): void {
|
||||
|
@ -15,6 +15,8 @@
|
||||
<script lang="ts">
|
||||
import { popupstore as modal } from '../popups'
|
||||
import PopupInstance from './PopupInstance.svelte'
|
||||
|
||||
export let contentPanel: HTMLElement
|
||||
</script>
|
||||
|
||||
{#if $modal.length > 0}
|
||||
@ -31,6 +33,7 @@
|
||||
zIndex={(i + 1) * 500}
|
||||
top={$modal.length - 1 === i}
|
||||
close={popup.close}
|
||||
{contentPanel}
|
||||
overlay={popup.options.overlay}
|
||||
/>
|
||||
{/key}
|
||||
|
@ -27,6 +27,7 @@
|
||||
export let zIndex: number
|
||||
export let top: boolean
|
||||
export let close: () => void
|
||||
export let contentPanel: HTMLElement
|
||||
|
||||
let modalHTML: HTMLElement
|
||||
let componentInstance: any
|
||||
@ -67,13 +68,13 @@
|
||||
_close(undefined)
|
||||
}
|
||||
|
||||
const fitPopup = (modalHTML: HTMLElement, element: PopupAlignment | undefined): void => {
|
||||
const fitPopup = (modalHTML: HTMLElement, element: PopupAlignment | undefined, contentPanel: HTMLElement): void => {
|
||||
if ((fullSize || docSize) && (element === 'float' || element === 'centered')) {
|
||||
options = fitPopupElement(modalHTML, 'full')
|
||||
options = fitPopupElement(modalHTML, 'full', contentPanel)
|
||||
options.props.maxHeight = '100vh'
|
||||
if (!modalHTML.classList.contains('fullsize')) modalHTML.classList.add('fullsize')
|
||||
} else {
|
||||
options = fitPopupElement(modalHTML, element)
|
||||
options = fitPopupElement(modalHTML, element, contentPanel)
|
||||
if (modalHTML.classList.contains('fullsize')) modalHTML.classList.remove('fullsize')
|
||||
}
|
||||
options.fullSize = fullSize
|
||||
@ -103,7 +104,7 @@
|
||||
|
||||
$: if (modalHTML !== undefined && oldModalHTML !== modalHTML) {
|
||||
oldModalHTML = modalHTML
|
||||
fitPopup(modalHTML, element)
|
||||
fitPopup(modalHTML, element, contentPanel)
|
||||
showing = true
|
||||
modalHTML.addEventListener(
|
||||
'transitionend',
|
||||
@ -121,7 +122,7 @@
|
||||
<svelte:window
|
||||
on:resize={() => {
|
||||
if (modalHTML) {
|
||||
fitPopup(modalHTML, element)
|
||||
fitPopup(modalHTML, element, contentPanel)
|
||||
}
|
||||
}}
|
||||
on:keydown={handleKeydown}
|
||||
@ -155,10 +156,10 @@
|
||||
on:close={(ev) => _close(ev?.detail)}
|
||||
on:fullsize={() => {
|
||||
fullSize = !fullSize
|
||||
fitPopup(modalHTML, element)
|
||||
fitPopup(modalHTML, element, contentPanel)
|
||||
}}
|
||||
on:changeContent={() => {
|
||||
fitPopup(modalHTML, element)
|
||||
fitPopup(modalHTML, element, contentPanel)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
import { writable, derived } from 'svelte/store'
|
||||
import { Location as PlatformLocation } from './types'
|
||||
import { closePopup } from './popups'
|
||||
|
||||
export function locationToUrl (location: PlatformLocation): string {
|
||||
let result = '/'
|
||||
@ -110,6 +111,7 @@ window.addEventListener('popstate', () => {
|
||||
export const location = derived(locationWritable, (loc) => loc)
|
||||
|
||||
export function navigate (location: PlatformLocation, store = true): void {
|
||||
closePopup()
|
||||
const url = locationToUrl(location)
|
||||
if (locationToUrl(getCurrentLocation()) !== url) {
|
||||
if (store) {
|
||||
|
@ -12,7 +12,7 @@ import type {
|
||||
} from './types'
|
||||
import { ComponentType } from 'svelte'
|
||||
|
||||
interface CompAndProps {
|
||||
export interface CompAndProps {
|
||||
id: string
|
||||
is: AnySvelteComponent | ComponentType
|
||||
props: any
|
||||
@ -26,6 +26,11 @@ interface CompAndProps {
|
||||
}
|
||||
}
|
||||
|
||||
export interface PopupResult {
|
||||
id: string
|
||||
close: () => void
|
||||
}
|
||||
|
||||
export const popupstore = writable<CompAndProps[]>([])
|
||||
|
||||
function addPopup (props: CompAndProps): void {
|
||||
@ -45,7 +50,7 @@ export function showPopup (
|
||||
category: string
|
||||
overlay: boolean
|
||||
} = { category: 'popup', overlay: true }
|
||||
): () => void {
|
||||
): PopupResult {
|
||||
const id = `${popupId++}`
|
||||
const closePopupOp = (): void => {
|
||||
popupstore.update((popups) => {
|
||||
@ -66,7 +71,10 @@ export function showPopup (
|
||||
} else {
|
||||
addPopup({ id, is: component, props, element: _element, onClose, onUpdate, close: closePopupOp, options })
|
||||
}
|
||||
return closePopupOp
|
||||
return {
|
||||
id,
|
||||
close: closePopupOp
|
||||
}
|
||||
}
|
||||
|
||||
export function closePopup (category?: string): void {
|
||||
|
@ -71,21 +71,21 @@
|
||||
return new Promise<'single' | 'multiple' | 'close'>((resolve) => {
|
||||
const popupOpts = {
|
||||
onAddSingle: () => {
|
||||
closePopup()
|
||||
popup.close()
|
||||
resolve('single')
|
||||
},
|
||||
onAddMultiple: () => {
|
||||
closePopup()
|
||||
popup.close()
|
||||
resolve('multiple')
|
||||
},
|
||||
onClose: () => {
|
||||
closePopup()
|
||||
popup.close()
|
||||
resolve('close')
|
||||
},
|
||||
cardsNumber: splittedTitle.length
|
||||
}
|
||||
|
||||
const closePopup = showPopup(AddMultipleCardsPopup, popupOpts, anchorRef, () => resolve('close'))
|
||||
const popup = showPopup(AddMultipleCardsPopup, popupOpts, anchorRef, () => resolve('close'))
|
||||
}).then((value) => {
|
||||
if (value === 'single' || value === 'close') {
|
||||
return addCard(title.replace('\n', ' ')).then((res) => {
|
||||
|
@ -96,10 +96,12 @@
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{#if loading}
|
||||
<Loading />
|
||||
{:else if component && _id && _class}
|
||||
{#if component && _id && _class}
|
||||
<Component is={component} props={{ embedded: true, _id, _class }} />
|
||||
{:else}
|
||||
<div class="antiPanel-component filled w-full">
|
||||
<Loading />
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
|
@ -83,6 +83,10 @@
|
||||
_class,
|
||||
{ _id },
|
||||
async (result) => {
|
||||
if (saveTrigger !== undefined) {
|
||||
clearTimeout(saveTrigger)
|
||||
await save()
|
||||
}
|
||||
;[issue] = result
|
||||
title = issue.title
|
||||
description = issue.description
|
||||
@ -177,7 +181,7 @@
|
||||
{/if}
|
||||
<EditBox bind:value={title} placeholder={tracker.string.IssueTitlePlaceholder} kind="large-style" on:blur={save} />
|
||||
<div class="w-full mt-6">
|
||||
{#key _id}
|
||||
{#key issue._id}
|
||||
<AttachmentStyledBox
|
||||
bind:this={descriptionBox}
|
||||
useAttachmentPreview={true}
|
||||
|
@ -47,7 +47,6 @@
|
||||
}
|
||||
|
||||
let selectedId: Ref<FilteredView> | undefined = undefined
|
||||
let selectedFW: FilteredView[] | undefined = undefined
|
||||
async function load (fv: FilteredView): Promise<void> {
|
||||
if (fv.viewletId !== undefined && fv.viewletId !== null) {
|
||||
const viewlet = await client.findOne(view.class.Viewlet, { _id: fv.viewletId })
|
||||
@ -66,7 +65,7 @@
|
||||
}
|
||||
|
||||
const clearSelection = () => {
|
||||
selectedId = selectedFW = undefined
|
||||
selectedId = undefined
|
||||
dispatch('select', false)
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
import request, { RequestStatus } from '@hcengineering/request'
|
||||
import {
|
||||
AnyComponent,
|
||||
CompAndProps,
|
||||
Component,
|
||||
DatePickerPopup,
|
||||
Label,
|
||||
@ -33,6 +34,7 @@
|
||||
Popup,
|
||||
PopupAlignment,
|
||||
PopupPosAlignment,
|
||||
PopupResult,
|
||||
ResolvedLocation,
|
||||
TooltipInstance,
|
||||
areLocationsEqual,
|
||||
@ -43,6 +45,7 @@
|
||||
location,
|
||||
navigate,
|
||||
openPanel,
|
||||
popupstore,
|
||||
resizeObserver,
|
||||
showPopup
|
||||
} from '@hcengineering/ui'
|
||||
@ -500,7 +503,18 @@
|
||||
}
|
||||
}
|
||||
|
||||
let prevLoc: Location | undefined = undefined
|
||||
function checkInbox (popups: CompAndProps[]) {
|
||||
if (inboxPopup !== undefined) {
|
||||
const exists = popups.find((p) => p.id === inboxPopup?.id)
|
||||
if (!exists) {
|
||||
inboxPopup = undefined
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$: checkInbox($popupstore)
|
||||
|
||||
let inboxPopup: PopupResult | undefined = undefined
|
||||
</script>
|
||||
|
||||
{#if employee?.active === true}
|
||||
@ -568,17 +582,26 @@
|
||||
<AppItem
|
||||
icon={notification.icon.Notifications}
|
||||
label={notification.string.Inbox}
|
||||
selected={currentAppAlias === notificationId}
|
||||
selected={currentAppAlias === notificationId || inboxPopup !== undefined}
|
||||
on:click={(e) => {
|
||||
if (currentAppAlias === notificationId) {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
if (prevLoc !== undefined) {
|
||||
navigate(prevLoc)
|
||||
}
|
||||
if (e.metaKey || e.ctrlKey) return
|
||||
if (inboxPopup) {
|
||||
inboxPopup.close()
|
||||
} else {
|
||||
prevLoc = $location
|
||||
inboxPopup = showPopup(
|
||||
notification.component.Inbox,
|
||||
{ visibileNav: true },
|
||||
'content',
|
||||
undefined,
|
||||
undefined,
|
||||
{
|
||||
category: 'popup',
|
||||
overlay: false
|
||||
}
|
||||
)
|
||||
}
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
}}
|
||||
notify={hasNotification}
|
||||
/>
|
||||
@ -672,7 +695,7 @@
|
||||
<ActionContext context={{ mode: 'panel' }} />
|
||||
</svelte:fragment>
|
||||
</PanelInstance>
|
||||
<Popup>
|
||||
<Popup {contentPanel}>
|
||||
<svelte:fragment slot="popup-header">
|
||||
<ActionContext context={{ mode: 'popup' }} />
|
||||
</svelte:fragment>
|
||||
|
Loading…
Reference in New Issue
Block a user