mirror of https://github.com/Budibase/budibase.git
9 changed files with 451 additions and 10 deletions
|
After Width: | Height: | Size: 260 B |
|
After Width: | Height: | Size: 395 B |
|
After Width: | Height: | Size: 326 B |
@ -0,0 +1,3 @@ |
|||
export { default as LayoutIcon } from './Layout.svelte'; |
|||
export { default as PaintIcon } from './Paint.svelte'; |
|||
export { default as TerminalIcon } from './Terminal.svelte'; |
|||
@ -0,0 +1,127 @@ |
|||
<script> |
|||
let snippets = []; |
|||
let current_snippet = 0; |
|||
let snippet_text = '' |
|||
let id = 0; |
|||
|
|||
function save_snippet() { |
|||
if (!snippet_text) return; |
|||
|
|||
const index = snippets.findIndex(({ id }) => current_snippet === id); |
|||
|
|||
if (index > -1) { |
|||
snippets[index].snippet = snippet_text; |
|||
} else { |
|||
snippets = snippets.concat({ snippet: snippet_text , id: id }); |
|||
} |
|||
snippet_text = ''; |
|||
current_snippet = ++id; |
|||
} |
|||
|
|||
function edit_snippet(id) { |
|||
const { snippet, id: _id } = snippets.find(({ id:_id }) => _id === id); |
|||
current_snippet = id |
|||
snippet_text = snippet; |
|||
} |
|||
</script> |
|||
|
|||
<h3>Code</h3> |
|||
|
|||
<p>Use the code box below to add snippets of javascript to enhance your webapp</p> |
|||
|
|||
<div class="editor"> |
|||
<textarea bind:value={snippet_text} /> |
|||
<button on:click={save_snippet}>Save</button> |
|||
</div> |
|||
|
|||
<div class="snippets"> |
|||
<h3>Snippets added</h3> |
|||
{#each snippets as { id, snippet } } |
|||
<div class="snippet"> |
|||
<pre>{snippet}</pre> |
|||
<button on:click={() => edit_snippet(id)}>Edit</button> |
|||
</div> |
|||
{/each} |
|||
</div> |
|||
|
|||
<style> |
|||
h3 { |
|||
text-transform: uppercase; |
|||
font-size: 10px; |
|||
font-weight: 700; |
|||
color: #8997ab; |
|||
margin-bottom: 10px; |
|||
} |
|||
|
|||
p { |
|||
font-size: 12px; |
|||
color: #333; |
|||
margin-top: 0; |
|||
} |
|||
|
|||
.editor { |
|||
position: relative; |
|||
} |
|||
|
|||
.editor textarea { |
|||
width: 100%; |
|||
outline: none; |
|||
height: 150px; |
|||
border: none; |
|||
background: #173157; |
|||
border-radius: 5px; |
|||
box-sizing: border-box; |
|||
white-space: pre; |
|||
color: #eee; |
|||
padding: 10px; |
|||
font-family: monospace; |
|||
resize: none; |
|||
overflow-y: scroll; |
|||
} |
|||
|
|||
button { |
|||
position: absolute; |
|||
box-shadow: 0 0 black; |
|||
color: #eee; |
|||
right: 5px; |
|||
bottom: 10px; |
|||
background: none; |
|||
border: none; |
|||
text-transform: uppercase; |
|||
font-size: 9px; |
|||
font-weight: 600; |
|||
outline: none; |
|||
cursor: pointer; |
|||
} |
|||
|
|||
.snippets { |
|||
margin-top: 20px; |
|||
} |
|||
|
|||
.snippet { |
|||
position: relative; |
|||
margin-top: 5px; |
|||
} |
|||
|
|||
.snippet pre { |
|||
width: 100%; |
|||
outline: none; |
|||
max-height: 150px; |
|||
border: none; |
|||
background: #f9f9f9; |
|||
border-radius: 5px; |
|||
box-sizing: border-box; |
|||
white-space: pre; |
|||
color: #333; |
|||
padding: 10px; |
|||
font-family: monospace; |
|||
resize: none; |
|||
overflow-y: scroll; |
|||
margin: 10px; |
|||
} |
|||
|
|||
.snippet button { |
|||
color: #ccc; |
|||
} |
|||
|
|||
</style> |
|||
@ -0,0 +1,265 @@ |
|||
<script> |
|||
|
|||
import PropsView from "./PropsView.svelte"; |
|||
import { store } from "../builderStore"; |
|||
import { isRootComponent } from "./pagesParsing/searchComponents"; |
|||
import IconButton from "../common/IconButton.svelte"; |
|||
import Textbox from "../common/Textbox.svelte"; |
|||
// import UIkit from "uikit"; |
|||
import { pipe } from "../common/core"; |
|||
import { |
|||
getScreenInfo |
|||
} from "./pagesParsing/createProps"; |
|||
// import Button from "../common/Button.svelte"; |
|||
// import ButtonGroup from "../common/ButtonGroup.svelte"; |
|||
import { LayoutIcon, PaintIcon, TerminalIcon } from '../common/Icons/'; |
|||
import CodeEditor from './CodeEditor.svelte'; |
|||
|
|||
import { |
|||
cloneDeep, |
|||
join, |
|||
split, |
|||
map, |
|||
keys, |
|||
isUndefined, |
|||
last |
|||
} from "lodash/fp"; |
|||
import { assign } from "lodash"; |
|||
|
|||
let component; |
|||
let name = ""; |
|||
let description = ""; |
|||
let tagsString = ""; |
|||
let nameInvalid = ""; |
|||
let componentInfo; |
|||
let modalElement |
|||
let propsValidationErrors = []; |
|||
let originalName=""; |
|||
let components; |
|||
let ignoreStore = false; |
|||
|
|||
$: shortName = last(name.split("/")); |
|||
|
|||
store.subscribe(s => { |
|||
if(ignoreStore) return; |
|||
component = s.currentFrontEndItem; |
|||
if(!component) return; |
|||
originalName = component.name; |
|||
name = component.name; |
|||
description = component.description; |
|||
tagsString = join(", ")(component.tags); |
|||
componentInfo = s.currentComponentInfo; |
|||
components = s.components; |
|||
}); |
|||
|
|||
// const save = () => { |
|||
|
|||
// ignoreStore = true; |
|||
// if(!validate()) { |
|||
// ignoreStore = false; |
|||
// return; |
|||
// } |
|||
|
|||
// component.name = originalName || name; |
|||
// component.description = description; |
|||
// component.tags = pipe(tagsString, [ |
|||
// split(","), |
|||
// map(s => s.trim()) |
|||
// ]); |
|||
|
|||
// store.saveScreen(component); |
|||
|
|||
// ignoreStore = false; |
|||
// // now do the rename |
|||
// if(name !== originalName) { |
|||
// store.renameScreen(originalName, name); |
|||
// } |
|||
// } |
|||
|
|||
// const deleteComponent = () => { |
|||
// showDialog(); |
|||
// } |
|||
|
|||
// const confirmDeleteComponent = () => { |
|||
// store.deleteScreen(component.name); |
|||
// hideDialog(); |
|||
// } |
|||
|
|||
const onPropsValidate = result => { |
|||
propsValidationErrors = result; |
|||
} |
|||
|
|||
const updateComponent = doChange => { |
|||
const newComponent = cloneDeep(component); |
|||
doChange(newComponent); |
|||
component = newComponent; |
|||
componentInfo = getScreenInfo(components, newComponent); |
|||
} |
|||
|
|||
const onPropsChanged = newProps => { |
|||
updateComponent(newComponent => |
|||
assign(newComponent.props, newProps)); |
|||
|
|||
} |
|||
|
|||
const validate = () => { |
|||
const fieldInvalid = (field, err) => |
|||
errors[field] = err; |
|||
const fieldValid = field => |
|||
errors[field] && delete errors[field]; |
|||
|
|||
if(!name) nameInvalid = "component name i not supplied"; |
|||
else nameInvalid = ""; |
|||
|
|||
return (!nameInvalid && propsValidationErrors.length === 0); |
|||
} |
|||
|
|||
// const hideDialog = () => { |
|||
// UIkit.modal(modalElement).hide(); |
|||
// } |
|||
|
|||
// const showDialog = () => { |
|||
// UIkit.modal(modalElement).show(); |
|||
// } |
|||
|
|||
let current_view = 'props'; |
|||
|
|||
|
|||
|
|||
</script> |
|||
|
|||
<div class="root"> |
|||
|
|||
<!-- <div class="title"> |
|||
<div>{shortName}</div> |
|||
<div> |
|||
<IconButton icon="save" |
|||
on:click={save} |
|||
color="var(--secondary100)" |
|||
hoverColor="var(--primary100)"/> |
|||
<IconButton icon="trash" |
|||
on:click={deleteComponent} |
|||
color="var(--secondary100)" |
|||
hoverColor="var(--primary100)"/> |
|||
</div> |
|||
</div> --> |
|||
|
|||
<ul> |
|||
<li> |
|||
<button class:selected={current_view === 'props'} on:click={() => current_view = 'props'}> |
|||
<PaintIcon /> |
|||
</button> |
|||
</li> |
|||
<li> |
|||
<button class:selected={current_view === 'layout'} on:click={() => current_view = 'layout'}> |
|||
<LayoutIcon /> |
|||
</button> |
|||
</li> |
|||
<li> |
|||
<button class:selected={current_view === 'code'} on:click={() => current_view = 'code'}> |
|||
<TerminalIcon /> |
|||
</button> |
|||
</li> |
|||
</ul> |
|||
|
|||
<div class="component-props-container"> |
|||
|
|||
{#if current_view === 'props'} |
|||
<PropsView onValidate={onPropsValidate} |
|||
{componentInfo} |
|||
{onPropsChanged} /> |
|||
{:else if current_view === 'layout'} |
|||
<p>Layout</p> |
|||
{:else} |
|||
<CodeEditor /> |
|||
{/if} |
|||
|
|||
</div> |
|||
|
|||
</div> |
|||
|
|||
|
|||
<!-- <div bind:this={modalElement} uk-modal> |
|||
<div class="uk-modal-dialog"> |
|||
|
|||
<div class="uk-modal-header"> |
|||
Delete {name} ? |
|||
</div> |
|||
|
|||
<div class="uk-modal-body"> |
|||
Are you sure you want to delete this component ? |
|||
</div> |
|||
|
|||
<div class="uk-modal-footer"> |
|||
<ButtonGroup> |
|||
<Button grouped |
|||
on:click={confirmDeleteComponent}> |
|||
OK |
|||
</Button> |
|||
<Button grouped |
|||
on:click={hideDialog} |
|||
color="secondary" > |
|||
Cancel |
|||
</Button> |
|||
</ButtonGroup> |
|||
</div> |
|||
|
|||
</div> |
|||
|
|||
</div> --> |
|||
|
|||
<style> |
|||
|
|||
.root { |
|||
height: 100%; |
|||
display: flex; |
|||
flex-direction: column; |
|||
|
|||
} |
|||
|
|||
.title > div:nth-child(1) { |
|||
grid-column-start: name; |
|||
color: var(--secondary100); |
|||
} |
|||
|
|||
.title > div:nth-child(2) { |
|||
grid-column-start: actions; |
|||
} |
|||
|
|||
.component-props-container { |
|||
margin-top: 10px; |
|||
flex: 1 1 auto; |
|||
overflow-y: auto; |
|||
} |
|||
|
|||
ul { |
|||
list-style: none; |
|||
display: flex; |
|||
padding: 0; |
|||
} |
|||
|
|||
li { |
|||
margin-right: 20px; |
|||
background: none; |
|||
border-radius: 5px; |
|||
width: 45px; |
|||
height: 45px; |
|||
} |
|||
|
|||
li button { |
|||
width: 100%; |
|||
height: 100%; |
|||
background: none; |
|||
border: none; |
|||
border-radius: 5px; |
|||
padding: 12px; |
|||
outline: none; |
|||
cursor: pointer; |
|||
} |
|||
|
|||
.selected { |
|||
color: var(--button-text); |
|||
background: var(--background-button)!important; |
|||
} |
|||
|
|||
</style> |
|||
Loading…
Reference in new issue