mirror of https://github.com/Budibase/budibase.git
16 changed files with 221 additions and 97 deletions
@ -0,0 +1,78 @@ |
|||
<script> |
|||
import { peekStore, dataSourceStore, routeStore } from "../store" |
|||
import { Modal, ModalContent, Button, Divider, Layout } from "@budibase/bbui" |
|||
import { onDestroy } from "svelte" |
|||
|
|||
let iframe |
|||
let fullscreen = false |
|||
|
|||
const invalidateDataSource = event => { |
|||
const { dataSourceId } = event.detail |
|||
dataSourceStore.actions.invalidateDataSource(dataSourceId) |
|||
} |
|||
|
|||
const handleCancel = () => { |
|||
iframe.contentWindow.removeEventListener( |
|||
"invalidate-datasource", |
|||
invalidateDataSource |
|||
) |
|||
peekStore.actions.hidePeek() |
|||
fullscreen = false |
|||
} |
|||
|
|||
const navigate = () => { |
|||
if ($peekStore.external) { |
|||
window.location = $peekStore.href |
|||
} else { |
|||
routeStore.actions.navigate($peekStore.url) |
|||
} |
|||
peekStore.actions.hidePeek() |
|||
} |
|||
|
|||
$: { |
|||
if (iframe) { |
|||
iframe.contentWindow.addEventListener( |
|||
"invalidate-datasource", |
|||
invalidateDataSource |
|||
) |
|||
} |
|||
} |
|||
|
|||
onDestroy(() => { |
|||
if (iframe) { |
|||
iframe.contentWindow.removeEventListener( |
|||
"invalidate-datasource", |
|||
invalidateDataSource |
|||
) |
|||
} |
|||
}) |
|||
</script> |
|||
|
|||
{#if $peekStore.showPeek} |
|||
<Modal fixed on:cancel={handleCancel}> |
|||
<ModalContent |
|||
cancelText="Close" |
|||
showConfirmButton={false} |
|||
size="XL" |
|||
title="Screen Peek" |
|||
showDivider={false} |
|||
> |
|||
<iframe title="Peek" bind:this={iframe} src={$peekStore.href} /> |
|||
<div slot="footer"> |
|||
<Button cta on:click={navigate}>Full screen</Button> |
|||
</div> |
|||
</ModalContent> |
|||
</Modal> |
|||
{/if} |
|||
|
|||
<style> |
|||
iframe { |
|||
margin: 0 -40px; |
|||
border: none; |
|||
border-bottom: 1px solid var(--spectrum-global-color-gray-300); |
|||
border-top: 1px solid var(--spectrum-global-color-gray-300); |
|||
width: calc(100% + 80px); |
|||
height: 640px; |
|||
transition: width 1s ease, height 1s ease, top 1s ease, left 1s ease; |
|||
} |
|||
</style> |
|||
@ -1,56 +1,50 @@ |
|||
import { writable } from "svelte/store" |
|||
import { writable, get } from "svelte/store" |
|||
import { generate } from "shortid" |
|||
|
|||
const NOTIFICATION_TIMEOUT = 3000 |
|||
|
|||
const createNotificationStore = () => { |
|||
const timeoutIds = new Set() |
|||
const _notifications = writable([], () => { |
|||
let timeout |
|||
let block = false |
|||
|
|||
const store = writable(null, () => { |
|||
return () => { |
|||
// clear all the timers
|
|||
timeoutIds.forEach(timeoutId => { |
|||
clearTimeout(timeoutId) |
|||
}) |
|||
_notifications.set([]) |
|||
clearTimeout(timeout) |
|||
} |
|||
}) |
|||
let block = false |
|||
|
|||
const blockNotifications = (timeout = 1000) => { |
|||
block = true |
|||
setTimeout(() => (block = false), timeout) |
|||
} |
|||
|
|||
const send = (message, type = "default") => { |
|||
const send = (message, type = "info", icon) => { |
|||
if (block) { |
|||
return |
|||
} |
|||
let _id = id() |
|||
_notifications.update(state => { |
|||
return [...state, { id: _id, type, message }] |
|||
store.set({ |
|||
id: generate(), |
|||
type, |
|||
message, |
|||
icon, |
|||
delay: get(store) != null, |
|||
}) |
|||
const timeoutId = setTimeout(() => { |
|||
_notifications.update(state => { |
|||
return state.filter(({ id }) => id !== _id) |
|||
}) |
|||
clearTimeout(timeout) |
|||
timeout = setTimeout(() => { |
|||
store.set(null) |
|||
}, NOTIFICATION_TIMEOUT) |
|||
timeoutIds.add(timeoutId) |
|||
} |
|||
|
|||
const { subscribe } = _notifications |
|||
|
|||
return { |
|||
subscribe, |
|||
send, |
|||
danger: msg => send(msg, "danger"), |
|||
warning: msg => send(msg, "warning"), |
|||
info: msg => send(msg, "info"), |
|||
success: msg => send(msg, "success"), |
|||
blockNotifications, |
|||
subscribe: store.subscribe, |
|||
actions: { |
|||
info: msg => send(msg, "info", "Info"), |
|||
success: msg => send(msg, "success", "CheckmarkCircle"), |
|||
warning: msg => send(msg, "warning", "Alert"), |
|||
error: msg => send(msg, "error", "Alert"), |
|||
blockNotifications, |
|||
}, |
|||
} |
|||
} |
|||
|
|||
function id() { |
|||
return "_" + Math.random().toString(36).substr(2, 9) |
|||
} |
|||
|
|||
export const notificationStore = createNotificationStore() |
|||
|
|||
@ -0,0 +1,36 @@ |
|||
import { writable } from "svelte/store" |
|||
|
|||
const initialState = { |
|||
showPeek: false, |
|||
url: null, |
|||
href: null, |
|||
external: false, |
|||
} |
|||
|
|||
const createPeekStore = () => { |
|||
const store = writable(initialState) |
|||
|
|||
const showPeek = url => { |
|||
let href = url |
|||
let external = !url.startsWith("/") |
|||
if (!external) { |
|||
href = `${window.location.href.split("#")[0]}#${url}?peek=true` |
|||
} |
|||
store.set({ |
|||
showPeek: true, |
|||
url, |
|||
href, |
|||
external, |
|||
}) |
|||
} |
|||
const hidePeek = () => { |
|||
store.set(initialState) |
|||
} |
|||
|
|||
return { |
|||
subscribe: store.subscribe, |
|||
actions: { showPeek, hidePeek }, |
|||
} |
|||
} |
|||
|
|||
export const peekStore = createPeekStore() |
|||
Loading…
Reference in new issue