forked from tsai/budibase
11 changed files with 391 additions and 814 deletions
@ -1,95 +1,85 @@ |
|||
<script> |
|||
import { store } from "../builderStore" |
|||
import { map, join } from "lodash/fp" |
|||
import { pipe } from "../common/core" |
|||
import { store } from "../builderStore"; |
|||
import { map, join } from "lodash/fp"; |
|||
import { pipe } from "../common/core"; |
|||
import { buildPropsHierarchy } from "./pagesParsing/buildPropsHierarchy"; |
|||
|
|||
let iframe |
|||
let iframe; |
|||
|
|||
function transform_component(comp) { |
|||
const props = comp.props || comp |
|||
if (props && props._children && props._children.length) { |
|||
props._children = props._children.map(transform_component) |
|||
} |
|||
|
|||
return props |
|||
} |
|||
|
|||
$: iframe && |
|||
console.log( |
|||
iframe.contentDocument.head.insertAdjacentHTML( |
|||
"beforeend", |
|||
`<\style></style>` |
|||
) |
|||
) |
|||
$: hasComponent = !!$store.currentPreviewItem |
|||
$: styles = hasComponent ? $store.currentPreviewItem._css : "" |
|||
|
|||
$: stylesheetLinks = pipe( |
|||
$store.pages.stylesheets, |
|||
[map(s => `<link rel="stylesheet" href="${s}"/>`), join("\n")] |
|||
) |
|||
$: iframe && console.log(iframe.contentDocument.head.insertAdjacentHTML('beforeend', '<style></style>')) |
|||
$: hasComponent = !!$store.currentFrontEndItem; |
|||
$: styles = hasComponent ? $store.currentFrontEndItem._css : ''; |
|||
|
|||
$: frontendDefinition = { |
|||
componentLibraries: $store.loadLibraryUrls(), |
|||
page: $store.currentPreviewItem, |
|||
screens: [], |
|||
appRootPath: "", |
|||
} |
|||
|
|||
$: backendDefinition = { |
|||
hierarchy: $store.hierarchy, |
|||
} |
|||
$: stylesheetLinks = pipe($store.pages.stylesheets, [ |
|||
map(s => `<link rel="stylesheet" href="${s}"/>`), |
|||
join("\n") |
|||
]); |
|||
|
|||
$: appDefinition = { |
|||
componentLibraries: $store.loadLibraryUrls(), |
|||
props: buildPropsHierarchy( |
|||
$store.components, |
|||
$store.screens, |
|||
$store.currentFrontEndItem), |
|||
hierarchy: $store.hierarchy, |
|||
appRootPath: "" |
|||
}; |
|||
|
|||
</script> |
|||
|
|||
|
|||
<div class="component-container"> |
|||
{#if hasComponent && $store.currentPreviewItem} |
|||
<iframe |
|||
style="height: 100%; width: 100%" |
|||
title="componentPreview" |
|||
bind:this={iframe} |
|||
srcdoc={`<html> |
|||
<head> |
|||
${stylesheetLinks} |
|||
<style> |
|||
${styles || ''} |
|||
body, html { |
|||
height: 100%!important; |
|||
} |
|||
<\/style> |
|||
<\script> |
|||
window["##BUDIBASE_FRONTEND_DEFINITION##"] = ${JSON.stringify(frontendDefinition)}; |
|||
window["##BUDIBASE_BACKEND_DEFINITION##"] = ${JSON.stringify(backendDefinition)}; |
|||
window["##BUDIBASE_FRONTEND_FUNCTIONS##"] = ${$store.currentScreenFunctions}; |
|||
{#if hasComponent} |
|||
<iframe style="height: 100%; width: 100%" |
|||
title="componentPreview" |
|||
bind:this={iframe} |
|||
srcdoc={ |
|||
`<html> |
|||
|
|||
<head> |
|||
${stylesheetLinks} |
|||
<script> |
|||
window["##BUDIBASE_APPDEFINITION##"] = ${JSON.stringify(appDefinition)}; |
|||
window["##BUDIBASE_UIFUNCTIONS"] = ${$store.currentScreenFunctions}; |
|||
|
|||
import('/_builder/budibase-client.esm.mjs') |
|||
.then(module => { |
|||
module.loadBudibase({ window, localStorage }); |
|||
}) |
|||
<\/script> |
|||
</head> |
|||
<body> |
|||
</body> |
|||
</html>`} /> |
|||
{/if} |
|||
</script> |
|||
<style> |
|||
|
|||
body { |
|||
box-sizing: border-box; |
|||
padding: 20px; |
|||
} |
|||
${styles} |
|||
</style> |
|||
</head> |
|||
<body> |
|||
</body> |
|||
</html>`}> |
|||
</iframe> |
|||
{/if} |
|||
</div> |
|||
|
|||
|
|||
<style> |
|||
.component-container { |
|||
grid-row-start: middle; |
|||
grid-column-start: middle; |
|||
position: relative; |
|||
overflow: hidden; |
|||
padding-top: 56.25%; |
|||
margin: auto; |
|||
} |
|||
.component-container { |
|||
grid-row-start: middle; |
|||
grid-column-start: middle; |
|||
position: relative; |
|||
overflow: hidden; |
|||
padding-top: 56.25%; |
|||
margin: auto; |
|||
} |
|||
|
|||
.component-container iframe { |
|||
border: 0; |
|||
height: 100%; |
|||
left: 0; |
|||
position: absolute; |
|||
top: 0; |
|||
width: 100%; |
|||
} |
|||
</style> |
|||
.component-container iframe { |
|||
border: 0; |
|||
height: 100%; |
|||
left: 0; |
|||
position: absolute; |
|||
top: 0; |
|||
width: 100%; |
|||
} |
|||
</style> |
|||
@ -0,0 +1,188 @@ |
|||
<script> |
|||
import { ArrowDownIcon } from "../common/Icons/"; |
|||
import { store } from "../builderStore"; |
|||
import { isBinding, getBinding, setBinding } from "../common/binding"; |
|||
|
|||
export let value = ""; |
|||
export let onChanged = () => {}; |
|||
export let type = ""; |
|||
|
|||
let isOpen = false; |
|||
let stateBindings = []; |
|||
|
|||
let isBound = false; |
|||
let bindingPath = ""; |
|||
let bindingFallbackValue = ""; |
|||
let bindingSource = "store"; |
|||
let isExpanded = false; |
|||
let forceIsBound = false; |
|||
let canOnlyBind = false; |
|||
|
|||
$: { |
|||
canOnlyBind = type === "state"; |
|||
if (!forceIsBound && canOnlyBind) forceIsBound = true; |
|||
|
|||
isBound = forceIsBound || isBinding(value); |
|||
|
|||
if (isBound) { |
|||
const binding = getBinding(value); |
|||
bindingPath = binding.path; |
|||
bindingFallbackValue = binding.fallback; |
|||
bindingSource = binding.source || "store"; |
|||
} else { |
|||
bindingPath = ""; |
|||
bindingFallbackValue = ""; |
|||
bindingSource = "store"; |
|||
} |
|||
} |
|||
|
|||
const clearBinding = () => { |
|||
forceIsBound = false; |
|||
onChanged(""); |
|||
}; |
|||
|
|||
const bind = (path, fallback, source) => { |
|||
if (!path) { |
|||
clearBinding(""); |
|||
return; |
|||
} |
|||
const binding = setBinding({ path, fallback, source }); |
|||
onChanged(binding); |
|||
}; |
|||
|
|||
const setBindingPath = value => { |
|||
forceIsBound = canOnlyBind; |
|||
bind(value, bindingFallbackValue, bindingSource); |
|||
}; |
|||
|
|||
const setBindingFallback = value => bind(bindingPath, value, bindingSource); |
|||
|
|||
const setBindingSource = value => |
|||
bind(bindingPath, bindingFallbackValue, value); |
|||
|
|||
$: { |
|||
console.log({ |
|||
bindingFallbackValue, |
|||
bindingPath, |
|||
value |
|||
}); |
|||
|
|||
const currentScreen = $store.screens.find( |
|||
({ name }) => name === $store.currentFrontEndItem.name |
|||
); |
|||
stateBindings = currentScreen ? currentScreen.stateOrigins : []; |
|||
} |
|||
</script> |
|||
|
|||
<div class="cascader"> |
|||
<div class="input-box"> |
|||
<input |
|||
class="uk-input uk-form-small" |
|||
value={bindingFallbackValue} |
|||
on:change={e => { |
|||
setBindingFallback(e.target.value) |
|||
}}/> |
|||
<button on:click={() => (isOpen = !isOpen)}> |
|||
<span |
|||
class="icon" |
|||
style={` |
|||
transform: rotate(${isOpen ? 0 : 90}deg); |
|||
color: ${bindingPath ? 'rgba(0, 85, 255, 0.8)' : 'inherit'} |
|||
`}> |
|||
<ArrowDownIcon size={36} /> |
|||
</span> |
|||
</button> |
|||
</div> |
|||
{#if isOpen} |
|||
<ul class="options"> |
|||
{#each Object.keys(stateBindings) as stateBinding} |
|||
<li |
|||
style={`font-weight: ${stateBinding === bindingPath ? 'bold' : 'initial'}`} |
|||
on:click={() => { |
|||
setBindingPath(stateBinding === bindingPath ? null : stateBinding); |
|||
}}> |
|||
{stateBinding} |
|||
</li> |
|||
{/each} |
|||
</ul> |
|||
{/if} |
|||
</div> |
|||
|
|||
<style> |
|||
button { |
|||
cursor: pointer; |
|||
outline: none; |
|||
border: none; |
|||
border-radius: 5px; |
|||
background: rgba(249, 249, 249, 1); |
|||
|
|||
width: 30px; |
|||
height: 30px; |
|||
padding-bottom: 10px; |
|||
|
|||
display: flex; |
|||
justify-content: center; |
|||
align-items: center; |
|||
|
|||
font-size: 1.6rem; |
|||
font-weight: 700; |
|||
color: rgba(22, 48, 87, 1); |
|||
} |
|||
|
|||
.cascader { |
|||
position: relative; |
|||
width: 100%; |
|||
} |
|||
|
|||
.input-box { |
|||
display: flex; |
|||
align-items: center; |
|||
} |
|||
|
|||
.options { |
|||
width: 172px; |
|||
margin: 0; |
|||
position: absolute; |
|||
top: 35px; |
|||
padding: 10px; |
|||
z-index: 1; |
|||
background: rgba(249, 249, 249, 1); |
|||
min-height: 50px; |
|||
border-radius: 2px; |
|||
} |
|||
|
|||
li { |
|||
list-style-type: none; |
|||
transition: 0.2s all; |
|||
} |
|||
|
|||
li:hover { |
|||
cursor: pointer; |
|||
font-weight: 600; |
|||
} |
|||
|
|||
input { |
|||
margin-right: 5px; |
|||
border: 1px solid #dbdbdb; |
|||
border-radius: 2px; |
|||
opacity: 0.5; |
|||
height: 40px; |
|||
/* display: block; |
|||
font-size: 14px; |
|||
font-family: sans-serif; |
|||
font-weight: 500; |
|||
color: #163057; |
|||
line-height: 1.3; |
|||
padding: 1em 2.6em 0.9em 1.4em; |
|||
/* width: 100%; */ |
|||
/* max-width: 100%; |
|||
box-sizing: border-box; |
|||
margin: 0; |
|||
-moz-appearance: none; |
|||
-webkit-appearance: none; |
|||
appearance: none; |
|||
background: #fff; |
|||
border: 1px solid #ccc; |
|||
height: 50px; */ |
|||
} |
|||
</style> |
|||
File diff suppressed because it is too large
File diff suppressed because one or more lines are too long
Loading…
Reference in new issue