#6, initial continuous adding of items
This commit is contained in:
parent
2c16d7af60
commit
9d45d87ef3
@ -13,6 +13,11 @@ html {
|
|||||||
*:after {
|
*:after {
|
||||||
box-sizing: inherit;
|
box-sizing: inherit;
|
||||||
}
|
}
|
||||||
|
*,
|
||||||
|
*:focus,
|
||||||
|
*:hover {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
[onClick] {
|
[onClick] {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
@ -413,6 +418,7 @@ header .menu {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
#checklist .checklist-item {
|
#checklist .checklist-item {
|
||||||
|
transform: translate(0, 0);
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(3, min-content);
|
grid-template-columns: repeat(3, min-content);
|
||||||
grid-gap: 0 8px;
|
grid-gap: 0 8px;
|
||||||
@ -778,6 +784,24 @@ header .menu {
|
|||||||
#schedule-events .header {
|
#schedule-events .header {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
#input-text {
|
||||||
|
border: 1px solid #000 !important;
|
||||||
|
padding: 16px;
|
||||||
|
width: 300px;
|
||||||
|
}
|
||||||
|
#input-text .label {
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
#input-text input[type=text] {
|
||||||
|
width: 100%;
|
||||||
|
padding: 4px;
|
||||||
|
}
|
||||||
|
#input-text .buttons {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 64px 64px;
|
||||||
|
grid-gap: 8px;
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
@media only screen and (max-width: 932px) {
|
@media only screen and (max-width: 932px) {
|
||||||
#app.node {
|
#app.node {
|
||||||
grid-template-areas: "header" "crumbs" "child-nodes" "name" "content" "checklist" "schedule" "files" "blank";
|
grid-template-areas: "header" "crumbs" "child-nodes" "name" "content" "checklist" "schedule" "files" "blank";
|
||||||
|
@ -110,10 +110,11 @@ export class Checklist extends Component {
|
|||||||
this.groupElements = {}
|
this.groupElements = {}
|
||||||
this.state = {
|
this.state = {
|
||||||
confirmDeletion: true,
|
confirmDeletion: true,
|
||||||
|
continueAddingItems: true,
|
||||||
}
|
}
|
||||||
window._checklist = this
|
window._checklist = this
|
||||||
}//}}}
|
}//}}}
|
||||||
render({ ui, groups }, { confirmDeletion }) {//{{{
|
render({ ui, groups }, { confirmDeletion, continueAddingItems }) {//{{{
|
||||||
this.groupElements = {}
|
this.groupElements = {}
|
||||||
if (groups.length == 0 && !ui.node.value.ShowChecklist.value)
|
if (groups.length == 0 && !ui.node.value.ShowChecklist.value)
|
||||||
return
|
return
|
||||||
@ -136,6 +137,10 @@ export class Checklist extends Component {
|
|||||||
<input type="checkbox" id="confirm-checklist-delete" checked=${confirmDeletion} onchange=${() => this.setState({ confirmDeletion: !confirmDeletion })} />
|
<input type="checkbox" id="confirm-checklist-delete" checked=${confirmDeletion} onchange=${() => this.setState({ confirmDeletion: !confirmDeletion })} />
|
||||||
<label for="confirm-checklist-delete">Confirm checklist deletion</label>
|
<label for="confirm-checklist-delete">Confirm checklist deletion</label>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<input type="checkbox" id="continue-adding-items" checked=${continueAddingItems} onchange=${() => this.setState({ continueAddingItems: !continueAddingItems })} />
|
||||||
|
<label for="continue-adding-items">Continue adding items</label>
|
||||||
|
</div>
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,10 +199,62 @@ export class Checklist extends Component {
|
|||||||
}//}}}
|
}//}}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class InputElement extends Component {
|
||||||
|
render({ placeholder, label }) {//{{{
|
||||||
|
return html`
|
||||||
|
<dialog id="input-text">
|
||||||
|
<div class="container">
|
||||||
|
<div class="label">${label}</div>
|
||||||
|
<input id="input-text-el" type="text" placeholder=${placeholder} />
|
||||||
|
<div class="buttons">
|
||||||
|
<div></div>
|
||||||
|
<button onclick=${()=>this.cancel()}>Cancel</button>
|
||||||
|
<button onclick=${()=>this.ok()}>OK</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</dialog>
|
||||||
|
`
|
||||||
|
}//}}}
|
||||||
|
componentDidMount() {//{{{
|
||||||
|
const dlg = document.getElementById('input-text')
|
||||||
|
const input = document.getElementById('input-text-el')
|
||||||
|
dlg.showModal()
|
||||||
|
dlg.addEventListener("keydown", evt => this.keyhandler(evt))
|
||||||
|
input.addEventListener("keydown", evt => this.keyhandler(evt))
|
||||||
|
input.focus()
|
||||||
|
}//}}}
|
||||||
|
ok() {//{{{
|
||||||
|
const input = document.getElementById('input-text-el')
|
||||||
|
this.props.callback(true, input.value)
|
||||||
|
}//}}}
|
||||||
|
cancel() {//{{{
|
||||||
|
this.props.callback(false)
|
||||||
|
}//}}}
|
||||||
|
keyhandler(evt) {//{{{
|
||||||
|
let handled = true
|
||||||
|
switch (evt.key) {
|
||||||
|
case 'Enter':
|
||||||
|
this.ok()
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'Escape':
|
||||||
|
this.cancel()
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
handled = false
|
||||||
|
}
|
||||||
|
if (handled) {
|
||||||
|
evt.stopPropagation()
|
||||||
|
evt.preventDefault()
|
||||||
|
}
|
||||||
|
}//}}}
|
||||||
|
}
|
||||||
|
|
||||||
class ChecklistGroupElement extends Component {
|
class ChecklistGroupElement extends Component {
|
||||||
constructor() {//{{{
|
constructor() {//{{{
|
||||||
super()
|
super()
|
||||||
this.label = createRef()
|
this.label = createRef()
|
||||||
|
this.addingItem = signal(false)
|
||||||
}//}}}
|
}//}}}
|
||||||
render({ ui, group }) {//{{{
|
render({ ui, group }) {//{{{
|
||||||
let items = ({ ui, group }) =>
|
let items = ({ ui, group }) =>
|
||||||
@ -206,30 +263,42 @@ class ChecklistGroupElement extends Component {
|
|||||||
.map(item => html`<${ChecklistItemElement} key="item-${item.ID}" ui=${ui} group=${this} item=${item} />`)
|
.map(item => html`<${ChecklistItemElement} key="item-${item.ID}" ui=${ui} group=${this} item=${item} />`)
|
||||||
|
|
||||||
let label = () => html`<div class="label" style="cursor: pointer" ref=${this.label} onclick=${() => this.editLabel()}>${group.Label}</div>`
|
let label = () => html`<div class="label" style="cursor: pointer" ref=${this.label} onclick=${() => this.editLabel()}>${group.Label}</div>`
|
||||||
|
let addItem = () => {
|
||||||
|
if (this.addingItem.value)
|
||||||
|
return html`<${InputElement} label="New item" callback=${(ok, val) => this.addItem(ok, val)} />`
|
||||||
|
}
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
|
<${addItem} />
|
||||||
<div class="checklist-group-container">
|
<div class="checklist-group-container">
|
||||||
<div class="checklist-group ${ui.edit.value ? 'edit' : ''}">
|
<div class="checklist-group ${ui.edit.value ? 'edit' : ''}">
|
||||||
<div class="reorder" style="cursor: grab">☰</div>
|
<div class="reorder" style="cursor: grab">☰</div>
|
||||||
<img src="/images/${_VERSION}/trashcan.svg" onclick=${() => this.delete()} />
|
<img src="/images/${_VERSION}/trashcan.svg" onclick=${() => this.delete()} />
|
||||||
<${label} />
|
<${label} />
|
||||||
<img src="/images/${_VERSION}/add-gray.svg" onclick=${() => this.addItem()} />
|
<img src="/images/${_VERSION}/add-gray.svg" onclick=${() => this.addingItem.value = true} />
|
||||||
</div>
|
</div>
|
||||||
<${items} ui=${ui} group=${group} />
|
<${items} ui=${ui} group=${group} />
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
}//}}}
|
}//}}}
|
||||||
addItem() {//{{{
|
addItem(ok, label) {//{{{
|
||||||
let label = prompt("Create a new item")
|
if (!ok) {
|
||||||
if (label === null)
|
this.addingItem.value = false
|
||||||
return
|
return
|
||||||
|
}
|
||||||
|
|
||||||
label = label.trim()
|
label = label.trim()
|
||||||
if (label == '')
|
if (label == '') {
|
||||||
|
this.addingItem.value = false
|
||||||
return
|
return
|
||||||
|
}
|
||||||
|
|
||||||
this.props.group.addItem(label, () => {
|
this.props.group.addItem(label, () => {
|
||||||
this.forceUpdate()
|
this.forceUpdate()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if (!this.props.ui.state.continueAddingItems)
|
||||||
|
this.addingItem.value = false
|
||||||
}//}}}
|
}//}}}
|
||||||
editLabel() {//{{{
|
editLabel() {//{{{
|
||||||
let label = prompt('Edit label', this.props.group.Label)
|
let label = prompt('Edit label', this.props.group.Label)
|
||||||
@ -299,7 +368,7 @@ class ChecklistItemElement extends Component {
|
|||||||
`
|
`
|
||||||
}//}}}
|
}//}}}
|
||||||
componentDidMount() {//{{{
|
componentDidMount() {//{{{
|
||||||
this.base.addEventListener('dragstart', () => this.dragStart())
|
this.base.addEventListener('dragstart', evt => this.dragStart(evt))
|
||||||
this.base.addEventListener('dragend', () => this.dragEnd())
|
this.base.addEventListener('dragend', () => this.dragEnd())
|
||||||
this.base.addEventListener('dragenter', evt => this.dragEnter(evt))
|
this.base.addEventListener('dragenter', evt => this.dragEnter(evt))
|
||||||
}//}}}
|
}//}}}
|
||||||
@ -353,10 +422,13 @@ class ChecklistItemElement extends Component {
|
|||||||
setDragTarget(state) {//{{{
|
setDragTarget(state) {//{{{
|
||||||
this.setState({ dragTarget: state })
|
this.setState({ dragTarget: state })
|
||||||
}//}}}
|
}//}}}
|
||||||
dragStart() {//{{{
|
dragStart(evt) {//{{{
|
||||||
// Shouldn't be needed, but in case the previous drag was bungled up, we reset.
|
// Shouldn't be needed, but in case the previous drag was bungled up, we reset.
|
||||||
this.props.ui.dragReset()
|
this.props.ui.dragReset()
|
||||||
this.props.ui.dragItemSource = this
|
this.props.ui.dragItemSource = this
|
||||||
|
|
||||||
|
const img = new Image();
|
||||||
|
evt.dataTransfer.setDragImage(img, 10, 10);
|
||||||
}//}}}
|
}//}}}
|
||||||
dragEnter(evt) {//{{{
|
dragEnter(evt) {//{{{
|
||||||
evt.preventDefault()
|
evt.preventDefault()
|
||||||
@ -393,7 +465,7 @@ class ChecklistItemElement extends Component {
|
|||||||
this.props.ui.groupElements[fromGroup.ID].current.forceUpdate()
|
this.props.ui.groupElements[fromGroup.ID].current.forceUpdate()
|
||||||
this.props.ui.groupElements[toGroup.ID].current.forceUpdate()
|
this.props.ui.groupElements[toGroup.ID].current.forceUpdate()
|
||||||
|
|
||||||
from.move(to, ()=>console.log('ok'))
|
from.move(to, () => {})
|
||||||
}//}}}
|
}//}}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,10 @@ html {
|
|||||||
box-sizing: inherit;
|
box-sizing: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*,*:focus,*:hover{
|
||||||
|
outline:none;
|
||||||
|
}
|
||||||
|
|
||||||
[onClick] {
|
[onClick] {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
@ -476,6 +480,7 @@ header {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.checklist-item {
|
.checklist-item {
|
||||||
|
transform: translate(0, 0);
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(3, min-content);
|
grid-template-columns: repeat(3, min-content);
|
||||||
grid-gap: 0 8px;
|
grid-gap: 0 8px;
|
||||||
@ -905,6 +910,28 @@ header {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#input-text {
|
||||||
|
border: 1px solid #000 !important;
|
||||||
|
padding: 16px;
|
||||||
|
width: 300px;
|
||||||
|
|
||||||
|
.label {
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type=text] {
|
||||||
|
width: 100%;
|
||||||
|
padding: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttons {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 64px 64px;
|
||||||
|
grid-gap: 8px;
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@media only screen and (max-width: 932px) {
|
@media only screen and (max-width: 932px) {
|
||||||
#app.node {
|
#app.node {
|
||||||
.layout-crumbs();
|
.layout-crumbs();
|
||||||
|
Loading…
Reference in New Issue
Block a user