reording and duplication of components
This commit is contained in:
parent
e0c67a9ac5
commit
d9ceee49a1
|
@ -33,6 +33,7 @@ import { loadLibs, loadLibUrls } from "./loadComponentLibraries"
|
||||||
import { buildCodeForScreens } from "./buildCodeForScreens"
|
import { buildCodeForScreens } from "./buildCodeForScreens"
|
||||||
import { generate_screen_css } from "./generate_css"
|
import { generate_screen_css } from "./generate_css"
|
||||||
import { insertCodeMetadata } from "./insertCodeMetadata"
|
import { insertCodeMetadata } from "./insertCodeMetadata"
|
||||||
|
import { uuid } from "./uuid"
|
||||||
|
|
||||||
let appname = ""
|
let appname = ""
|
||||||
|
|
||||||
|
@ -107,6 +108,9 @@ export const getStore = () => {
|
||||||
store.setComponentCode = setComponentCode(store)
|
store.setComponentCode = setComponentCode(store)
|
||||||
store.setScreenType = setScreenType(store)
|
store.setScreenType = setScreenType(store)
|
||||||
store.deleteComponent = deleteComponent(store)
|
store.deleteComponent = deleteComponent(store)
|
||||||
|
store.moveUpComponent = moveUpComponent(store)
|
||||||
|
store.moveDownComponent = moveDownComponent(store)
|
||||||
|
store.copyComponent = copyComponent(store)
|
||||||
return store
|
return store
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -815,13 +819,7 @@ const setScreenType = store => type => {
|
||||||
|
|
||||||
const deleteComponent = store => component => {
|
const deleteComponent = store => component => {
|
||||||
store.update(s => {
|
store.update(s => {
|
||||||
let parent
|
const parent = getParent(s.currentPreviewItem.props, component)
|
||||||
walkProps(s.currentPreviewItem.props, (p, breakWalk) => {
|
|
||||||
if (p._children.includes(component)) {
|
|
||||||
parent = p
|
|
||||||
breakWalk()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
if (parent) {
|
if (parent) {
|
||||||
parent._children = parent._children.filter(c => c !== component)
|
parent._children = parent._children.filter(c => c !== component)
|
||||||
|
@ -835,6 +833,76 @@ const deleteComponent = store => component => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const moveUpComponent = store => component => {
|
||||||
|
store.update(s => {
|
||||||
|
const parent = getParent(s.currentPreviewItem.props, component)
|
||||||
|
|
||||||
|
if (parent) {
|
||||||
|
const currentIndex = parent._children.indexOf(component)
|
||||||
|
if (currentIndex === 0) return s
|
||||||
|
|
||||||
|
const newChildren = parent._children.filter(c => c !== component)
|
||||||
|
newChildren.splice(currentIndex - 1, 0, component)
|
||||||
|
parent._children = newChildren
|
||||||
|
}
|
||||||
|
s.currentComponentInfo = component
|
||||||
|
s.currentFrontEndType === "page"
|
||||||
|
? _savePage(s)
|
||||||
|
: _saveScreenApi(s.currentPreviewItem, s)
|
||||||
|
|
||||||
|
return s
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const moveDownComponent = store => component => {
|
||||||
|
store.update(s => {
|
||||||
|
const parent = getParent(s.currentPreviewItem.props, component)
|
||||||
|
|
||||||
|
if (parent) {
|
||||||
|
const currentIndex = parent._children.indexOf(component)
|
||||||
|
if (currentIndex === parent._children.length - 1) return s
|
||||||
|
|
||||||
|
const newChildren = parent._children.filter(c => c !== component)
|
||||||
|
newChildren.splice(currentIndex + 1, 0, component)
|
||||||
|
parent._children = newChildren
|
||||||
|
}
|
||||||
|
s.currentComponentInfo = component
|
||||||
|
s.currentFrontEndType === "page"
|
||||||
|
? _savePage(s)
|
||||||
|
: _saveScreenApi(s.currentPreviewItem, s)
|
||||||
|
|
||||||
|
return s
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const copyComponent = store => component => {
|
||||||
|
store.update(s => {
|
||||||
|
const parent = getParent(s.currentPreviewItem.props, component)
|
||||||
|
const copiedComponent = cloneDeep(component)
|
||||||
|
walkProps(copiedComponent, p => {
|
||||||
|
p._id = uuid()
|
||||||
|
})
|
||||||
|
parent._children = [...parent._children, copiedComponent]
|
||||||
|
s.curren
|
||||||
|
s.currentFrontEndType === "page"
|
||||||
|
? _savePage(s)
|
||||||
|
: _saveScreenApi(s.currentPreviewItem, s)
|
||||||
|
s.currentComponentInfo = copiedComponent
|
||||||
|
return s
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const getParent = (rootProps, child) => {
|
||||||
|
let parent
|
||||||
|
walkProps(rootProps, (p, breakWalk) => {
|
||||||
|
if (p._children.includes(child)) {
|
||||||
|
parent = p
|
||||||
|
breakWalk()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return parent
|
||||||
|
}
|
||||||
|
|
||||||
const walkProps = (props, action, cancelToken = null) => {
|
const walkProps = (props, action, cancelToken = null) => {
|
||||||
cancelToken = cancelToken || { cancelled: false }
|
cancelToken = cancelToken || { cancelled: false }
|
||||||
action(props, () => {
|
action(props, () => {
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-down"><polyline points="6 9 12 15 18 9"></polyline></svg>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
svg {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
After Width: | Height: | Size: 330 B |
|
@ -0,0 +1,8 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-up"><polyline points="18 15 12 9 6 15"></polyline></svg>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
svg {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
After Width: | Height: | Size: 329 B |
|
@ -0,0 +1,8 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-copy"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
svg {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
After Width: | Height: | Size: 412 B |
|
@ -8,3 +8,6 @@ export { default as CircleIndicator } from "./CircleIndicator.svelte"
|
||||||
export { default as PencilIcon } from "./Pencil.svelte"
|
export { default as PencilIcon } from "./Pencil.svelte"
|
||||||
export { default as EventsIcon } from "./Events.svelte"
|
export { default as EventsIcon } from "./Events.svelte"
|
||||||
export { default as XCircleIcon } from "./XCircle.svelte"
|
export { default as XCircleIcon } from "./XCircle.svelte"
|
||||||
|
export { default as ChevronUpIcon } from "./ChevronUp.svelte"
|
||||||
|
export { default as ChevronDownIcon } from "./ChevronDown.svelte"
|
||||||
|
export { default as CopyIcon } from "./Copy.svelte"
|
||||||
|
|
|
@ -74,7 +74,10 @@
|
||||||
components={screen.component.props._children}
|
components={screen.component.props._children}
|
||||||
currentComponent={$store.currentComponentInfo}
|
currentComponent={$store.currentComponentInfo}
|
||||||
onSelect={store.selectComponent}
|
onSelect={store.selectComponent}
|
||||||
onDeleteComponent={confirmDeleteComponent}/>
|
onDeleteComponent={confirmDeleteComponent}
|
||||||
|
onMoveUpComponent={store.moveUpComponent}
|
||||||
|
onMoveDownComponent={store.moveDownComponent}
|
||||||
|
onCopyComponent={store.copyComponent}/>
|
||||||
{/if}
|
{/if}
|
||||||
{/each}
|
{/each}
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
<script>
|
<script>
|
||||||
import { last } from "lodash/fp"
|
import { last } from "lodash/fp"
|
||||||
import { pipe } from "../common/core"
|
import { pipe } from "../common/core"
|
||||||
import { XCircleIcon } from "../common/Icons"
|
import { XCircleIcon, ChevronUpIcon, ChevronDownIcon, CopyIcon } from "../common/Icons"
|
||||||
|
|
||||||
export let components = []
|
export let components = []
|
||||||
export let currentComponent
|
export let currentComponent
|
||||||
export let onSelect = () => {}
|
export let onSelect = () => {}
|
||||||
export let level = 0
|
export let level = 0
|
||||||
export let onDeleteComponent
|
export let onDeleteComponent
|
||||||
|
export let onMoveUpComponent
|
||||||
|
export let onMoveDownComponent
|
||||||
|
export let onCopyComponent
|
||||||
|
|
||||||
|
|
||||||
const capitalise = s => s.substring(0, 1).toUpperCase() + s.substring(1)
|
const capitalise = s => s.substring(0, 1).toUpperCase() + s.substring(1)
|
||||||
|
@ -19,22 +22,43 @@
|
||||||
[get_name, capitalise]
|
[get_name, capitalise]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const moveDownComponent = component => {
|
||||||
|
const c = component
|
||||||
|
return () => {
|
||||||
|
return onMoveDownComponent(c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
{#each components as component}
|
{#each components as component, index (component._id)}
|
||||||
<li on:click|stopPropagation={() => onSelect(component)}>
|
<li on:click|stopPropagation={() => onSelect(component)}>
|
||||||
<span
|
<div
|
||||||
class="item"
|
class="item"
|
||||||
class:selected={currentComponent === component}
|
class:selected={currentComponent === component}
|
||||||
style="padding-left: {level * 20 + 67}px">
|
style="padding-left: {level * 20 + 67}px">
|
||||||
<span class="item-name">{get_capitalised_name(component._component)}</span>
|
<span class="item-name">{get_capitalised_name(component._component)}</span>
|
||||||
|
<div class="reorder-buttons">
|
||||||
|
{#if index > 0}
|
||||||
|
<button on:click|stopPropagation={() => onMoveUpComponent(component)}>
|
||||||
|
<ChevronUpIcon />
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
|
{#if index < (components.length - 1)}
|
||||||
|
<button on:click|stopPropagation={moveDownComponent(component)}>
|
||||||
|
<ChevronDownIcon />
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
<button on:click|stopPropagation={() => onCopyComponent(component)}>
|
||||||
|
<CopyIcon />
|
||||||
|
</button>
|
||||||
<button
|
<button
|
||||||
class="delete-component"
|
on:click|stopPropagation={() => onDeleteComponent(component)}>
|
||||||
on:click={() => onDeleteComponent(component)}>
|
|
||||||
<XCircleIcon />
|
<XCircleIcon />
|
||||||
</button>
|
</button>
|
||||||
</span>
|
</div>
|
||||||
|
|
||||||
{#if component._children}
|
{#if component._children}
|
||||||
<svelte:self
|
<svelte:self
|
||||||
|
@ -42,7 +66,10 @@
|
||||||
{currentComponent}
|
{currentComponent}
|
||||||
{onSelect}
|
{onSelect}
|
||||||
level={level + 1}
|
level={level + 1}
|
||||||
{onDeleteComponent} />
|
{onDeleteComponent}
|
||||||
|
{onMoveUpComponent}
|
||||||
|
{onMoveDownComponent}
|
||||||
|
{onCopyComponent} />
|
||||||
{/if}
|
{/if}
|
||||||
</li>
|
</li>
|
||||||
{/each}
|
{/each}
|
||||||
|
@ -54,11 +81,19 @@
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
li {
|
||||||
|
background: #fafafa;
|
||||||
|
}
|
||||||
|
|
||||||
.item {
|
.item {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
padding: 11px 5px 11px 67px;
|
padding: 0px 5px 0px 67px;
|
||||||
|
margin: auto 0px;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
|
height: 43px;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item > span {
|
.item > span {
|
||||||
|
@ -66,25 +101,25 @@
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item > button {
|
.item button {
|
||||||
display: none;
|
display: none;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
color: var(--slate)
|
color: var(--slate);
|
||||||
|
padding: 0px 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item:hover {
|
.item:hover {
|
||||||
|
|
||||||
background: #fafafa;
|
background: #fafafa;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.item:hover > button {
|
.item:hover button {
|
||||||
border-style: none;
|
border-style: none;
|
||||||
background: rgba(0,0,0,0);
|
background: rgba(0,0,0,0);
|
||||||
display: block;
|
display: block;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item:hover > button:hover {
|
.item:hover button:hover {
|
||||||
color: var(--button-text);
|
color: var(--button-text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,4 +127,16 @@
|
||||||
color: var(--button-text);
|
color: var(--button-text);
|
||||||
background: var(--background-button) !important;
|
background: var(--background-button) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.reorder-buttons {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reorder-buttons > button {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
height: 17px
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
confirmDeleteDialog.show()
|
confirmDeleteDialog.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
const lastPartOfName = c => c ? c.split("/") : ""
|
const lastPartOfName = c => c ? last(c.split("/")) : ""
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -67,6 +67,9 @@
|
||||||
currentComponent={$store.currentComponentInfo}
|
currentComponent={$store.currentComponentInfo}
|
||||||
onDeleteComponent={confirmDeleteComponent}
|
onDeleteComponent={confirmDeleteComponent}
|
||||||
onSelect={store.selectComponent}
|
onSelect={store.selectComponent}
|
||||||
|
onMoveUpComponent={store.moveUpComponent}
|
||||||
|
onMoveDownComponent={store.moveDownComponent}
|
||||||
|
onCopyComponent={store.copyComponent}
|
||||||
level={-2} />
|
level={-2} />
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue