reording and duplication of components

This commit is contained in:
Michael Shanks 2020-02-19 10:17:31 +00:00
parent e0c67a9ac5
commit d9ceee49a1
8 changed files with 170 additions and 22 deletions

View File

@ -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, () => {

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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}

View File

@ -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>

View File

@ -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}