Automatic SQL updates

This commit is contained in:
Magnus Åhall 2023-06-18 22:05:10 +02:00
parent 1812873e33
commit 85a2d0683e
8 changed files with 331 additions and 24 deletions

View file

@ -8,9 +8,8 @@
margin-bottom: 32px;
width: 100%;
border: 0px;
border-bottom: 1px solid #fff;
border-bottom: 1px solid #444;
font-size: 18pt;
color: #fff;
background-color: #fff;
}
#login input:focus {
@ -20,11 +19,14 @@
max-width: 300px;
border: 1px solid #666;
background: #fff;
color: #fff;
color: #444;
padding: 16px 32px;
font-size: 0.8em;
font-size: 1em;
align-self: center;
}
#login button:hover {
background: #ddd;
}
#login .auth-failed {
margin-top: 32px;
color: #a00;

View file

@ -24,9 +24,48 @@ h1 {
display: grid;
color: #fff;
}
#menu-blackout {
display: none;
position: absolute;
left: 0px;
right: 0px;
top: 0px;
bottom: 0px;
z-index: 1024;
background: rgba(0, 0, 0, 0.35);
}
#menu-blackout.show {
display: initial;
}
#menu {
display: none;
position: absolute;
top: 24px;
right: 24px;
background: #fff;
color: #000;
border: 2px solid #000;
box-shadow: 5px 5px 8px 0px rgba(0, 0, 0, 0.5);
z-index: 1025;
}
#menu.show {
display: initial;
}
#menu .item {
padding: 16px;
border-bottom: 1px solid #aaa;
user-select: none;
-webkit-tap-highlight-color: transparent;
}
#menu .item:hover {
background: #ddd;
}
#menu .item:last-child {
border-bottom: none;
}
header {
display: grid;
grid-template-columns: 1fr min-content;
grid-template-columns: 1fr min-content min-content;
align-items: center;
background: #ecbf00;
padding: 0px;
@ -45,6 +84,13 @@ header .add {
padding-right: 16px;
cursor: pointer;
}
header .menu {
font-size: 1.25em;
padding-right: 16px;
cursor: pointer;
user-select: none;
-webkit-tap-highlight-color: transparent;
}
.crumbs {
display: flex;
flex-wrap: wrap;
@ -98,7 +144,7 @@ header .add {
}
.node-content {
justify-self: center;
padding: 0px 32px 32px 32px;
padding: 0px 32px;
white-space: pre-wrap;
font-size: 0.85em;
color: #333;
@ -107,9 +153,13 @@ header .add {
.node-content[contenteditable] {
outline: 0px solid transparent;
}
.node-content:empty {
background: #ddd;
height: 48px;
}
@media only screen and (max-width: 100ex) {
.node-content {
width: initial;
width: 100%;
justify-self: start;
}
}

View file

@ -6,6 +6,7 @@ const html = htm.bind(h)
export class NodeUI extends Component {
constructor() {//{{{
super()
this.menu = signal(false)
this.node = signal(null)
this.nodeContent = createRef()
window.addEventListener('popstate', evt=>{
@ -42,14 +43,26 @@ export class NodeUI extends Component {
modified = 'modified';
return html`
<div id="menu-blackout" class="${this.menu.value ? 'show' : ''}" onclick=${()=>this.menu.value = false}></div>
<div id="menu" class="${this.menu.value ? 'show' : ''}">
<div class="item" onclick=${()=>this.renameNode()}>Rename</div>
<div class="item" onclick=${()=>this.deleteNode()}>Delete</div>
</div>
<header class="${modified}" onclick=${()=>this.saveNode()}>
<div class="name">Notes</div>
<div class="add" onclick=${()=>this.createNode()}>+</div>
<div class="menu" onclick=${()=>this.showMenu()}></div>
</header>
<div class="crumbs">${crumbs}</crumbs>
${children.length > 0 ? html`<div class="child-nodes">${children}</div>` : html``}
<div class="node-name">${node.Name}</div>
<${NodeContent} key=${node.ID} content=${node.Content} ref=${this.nodeContent} />
${node.ID > 0 ? html`
<div class="node-name">${node.Name}</div>
<${NodeContent} key=${node.ID} content=${node.Content} ref=${this.nodeContent} />
` : html``}
`
}//}}}
componentDidMount() {//{{{
@ -61,6 +74,11 @@ export class NodeUI extends Component {
this.node.value = node
})
}//}}}
showMenu() {//{{{
this.menu.value = true
}//}}}
goToNode(nodeID, dontPush) {//{{{
if(this.props.app.nodeModified.value) {
if(!confirm("Changes not saved. Do you want to discard changes?"))
@ -89,7 +107,7 @@ export class NodeUI extends Component {
})
.catch(this.props.app.responseError)
}//}}}
saveNode() {
saveNode() {//{{{
let content = this.nodeContent.current.contentDiv.current.innerText
this.props.app.request('/node/update', {
NodeID: this.node.value.ID,
@ -99,7 +117,35 @@ export class NodeUI extends Component {
this.props.app.nodeModified.value = false
})
.catch(this.props.app.responseError)
}
}//}}}
renameNode() {//{{{
let name = prompt("New name")
if(!name)
return
this.props.app.request('/node/rename', {
Name: name.trim(),
NodeID: this.node.value.ID,
})
.then(_=>{
this.goToNode(this.node.value.ID)
this.menu.value = false
})
.catch(this.props.app.responseError)
}//}}}
deleteNode() {//{{{
if(!confirm("Do you want to delete this note and all sub-notes?"))
return
this.props.app.request('/node/delete', {
NodeID: this.node.value.ID,
})
.then(_=>{
this.goToNode(this.node.value.ParentID)
this.menu.value = false
})
.catch(this.props.app.responseError)
}//}}}
}
class NodeContent extends Component {

View file

@ -10,10 +10,9 @@
margin-bottom: 32px;
width: 100%;
border: 0px;
border-bottom: 1px solid #fff;
border-bottom: 1px solid #444;
font-size: 18pt;
color: #fff;
background-color: @background;
&:focus {
@ -25,10 +24,14 @@
max-width: 300px;
border: 1px solid #666;
background: @background;
color: #fff;
color: #444;
padding: 16px 32px;
font-size: 0.8em;
font-size: 1em;
align-self: center;
&:hover {
background: #ddd;
}
}
.auth-failed {

View file

@ -30,9 +30,55 @@ h1 {
color: #fff;
}
#menu-blackout {
display: none;
position: absolute;
left: 0px;
right: 0px;
top: 0px;
bottom: 0px;
z-index: 1024;
background: rgba(0, 0, 0, 0.35);
&.show {
display: initial;
}
}
#menu {
display: none;
position: absolute;
top: 24px;
right: 24px;
background: #fff;
color: #000;
border: 2px solid #000;
box-shadow: 5px 5px 8px 0px rgba(0,0,0,0.5);
z-index: 1025;
&.show {
display: initial;
}
.item {
padding: 16px;
border-bottom: 1px solid #aaa;
user-select: none;
-webkit-tap-highlight-color: transparent;
&:hover {
background: #ddd;
}
&:last-child {
border-bottom: none;
}
}
}
header {
display: grid;
grid-template-columns: 1fr min-content;
grid-template-columns: 1fr min-content min-content;
align-items: center;
background: @accent_1;
padding: 0px;
@ -53,6 +99,14 @@ header {
padding-right: 16px;
cursor: pointer;
}
.menu {
font-size: 1.25em;
padding-right: 16px;
cursor: pointer;
user-select: none;
-webkit-tap-highlight-color: transparent;
}
}
.crumbs {
@ -117,7 +171,7 @@ header {
.node-content {
justify-self: center;
padding: 0px 32px 32px 32px;
padding: 0px 32px;
white-space: pre-wrap;
font-size: 0.85em;
color: #333;
@ -126,11 +180,16 @@ header {
&[contenteditable] {
outline: 0px solid transparent;
}
&:empty {
background: #ddd;
height: 48px;
}
}
@media only screen and (max-width: 100ex) {
.node-content {
width: initial;
width: 100%;
justify-self: start;
}
}