Browse Source

Added front end for comment editing and deletion

master
Thomas Withiam 3 years ago
parent
commit
0c60940723
  1. 68
      delete button.svg
  2. 76
      edit button.svg
  3. 16
      index.html
  4. 139
      main.css
  5. 104
      main.js

68
delete button.svg

@ -0,0 +1,68 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="24"
height="24"
viewBox="0 0 24 24"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="delete button.svg">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="22.4"
inkscape:cx="12.177983"
inkscape:cy="11.681217"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:window-width="1366"
inkscape:window-height="717"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1028.3622)">
<path
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 5 8 L 5 22 A 2 2 0 0 0 7 24 L 17 24 A 2 2 0 0 0 19 22 L 19 8 L 5 8 z "
transform="translate(0,1028.3622)"
id="path4136" />
<path
style="fill:#000000;fill-opacity:1;stroke:none;stroke-opacity:1"
d="M 9 2 A 1.0001 1.0001 0 0 0 8 3 L 8 5 L 4 5 L 4 7 L 20 7 L 20 5 L 16 5 L 16 3 A 1.0001 1.0001 0 0 0 15 2 L 9 2 z M 10 4 L 14 4 L 14 5 L 10 5 L 10 4 z "
transform="translate(0,1028.3622)"
id="rect4160" />
</g>
</svg>

76
edit button.svg

@ -0,0 +1,76 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="24"
height="24"
viewBox="0 0 24 24"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="edit button.svg">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="15.839192"
inkscape:cx="7.0605588"
inkscape:cy="7.8818064"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:window-width="1366"
inkscape:window-height="717"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1028.3622)">
<path
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 0,1052.3622 2,-6 4,4 z"
id="path4136"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 3.5,1044.8622 4,4 13.5,-13.5 -4,-4"
id="path4138"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 20,1028.3622 4,4 -2,2 -4,-4 z"
id="path4140"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
</g>
</svg>

16
index.html

@ -47,7 +47,7 @@
</div>
</div>
</div>
<input type="checkbox" id="commentModal">
<input type="checkbox" id="commentModal" class="modalControl">
<div>
<div class="modal">
<div class="right">
@ -72,6 +72,20 @@
</div>
</div>
</div>
<input type="checkbox" id="deleteConfirmationModal" class="modalControl">
<div>
<div class="modal">
<div class="right">
<label for="deleteConfirmationModal" class="close">X</label>
</div>
<p class="center">Are you sure you want to delete the folowing comment?</p>
<p class="center" id="deleteCommentText"></p>
<div class="center">
<button class="bestButton" onclick="confirmDelete();">Delete</button>
<label for="deleteConfirmationModal" class="bestButton">Cancel</label>
</div>
</div>
</div>
<a id="gitea-link" href="https://gitea.cslabs.clarkson.edu/pop1040/Wishlist">
<img src="gitea.svg" />
</a>

139
main.css

@ -11,18 +11,19 @@
left: 0px;
padding-top: 16px;
}
.ATF-container input{
.ATF-container input, .ATF-container p[contenteditable]{
border: none;
border-bottom: 1px solid rgb(156, 156, 156);
font-size: 20px;
color: rgb(119, 119, 119);
width: 500px;
padding: 1px;
margin: 0px;
}
.ATF-container input:focus{
.ATF-container input:focus, .ATF-container p[contenteditable]:focus{
outline: none; /* Because Chrome */
}
.ATF-container input ~ div{
.ATF-container input ~ div, .ATF-container p[contenteditable] ~ div{
display: block;
margin-top: -1px;
z-index: 1;
@ -30,7 +31,7 @@
transform: scaleX(0);
transition: transform 250ms ease-in-out;
}
.ATF-container input ~ span{
.ATF-container input ~ span, .ATF-container p[contenteditable] ~ span{
transition: all 200ms ease-in-out;
position: absolute;
/* top:16px;
@ -44,22 +45,53 @@
font-size: 20px;
pointer-events:none;
}
.ATF-container input:focus ~ span, .ATF-container input:valid ~ span{
.ATF-container p[contenteditable] ~ span{
transform: translate(0, 0) scale(0.7);
}
.ATF-container p[contenteditable]:empty ~ span{
transform: translate(0, 16px) scale(1);
}
.ATF-container input:focus ~ span, .ATF-container input:valid ~ span, .ATF-container p[contenteditable]:focus ~ span{
/* top: 0px; */
/* left: 1px; */
/* font-size: 14px; */
transform: translate(0, 0) scale(0.7);
}
.ATF-container input:invalid {
.ATF-container input:invalid, .ATF-container p[contenteditable]:invalid{
box-shadow: none;
}
.ATF-container input:focus ~ div{
.ATF-container input:focus ~ div, .ATF-container p[contenteditable]:focus ~ div{
transform: scaleX(1);
}
/* end of Awesome TextField CSS */
.EditableComment > p{
border: none;
border-bottom: 1px solid rgb(156, 156, 156);
font-size: 18px;
color: rgb(48, 48, 48);
width: 500px;
padding: 0px;
margin: 0px;
width: 100%;
}
.EditableComment > p:focus{
outline: none; /* Because Chrome */
}
.EditableComment > p ~ div{
display: block;
margin-top: -1px;
z-index: 1;
border-bottom: 2px solid rgb(149, 3, 168);
transform: scaleX(0);
transition: transform 250ms ease-in-out;
}
.EditableComment > p:focus ~ div{
transform: scaleX(1);
}
#gitea-link{
position: fixed;
position: absolute;
top: 0;
right: 0;
}
@ -79,10 +111,10 @@ body{
text-align: center;
padding: 10vh 0px 5vh;
}
#commentModal{
.modalControl{
display: none;
}
input#commentModal + div{
input.modalControl + div{
display: none;
position: fixed;
top: 0;
@ -93,7 +125,7 @@ input#commentModal + div{
align-items: center;
justify-content: center;
}
input#commentModal:checked + div{
input.modalControl:checked + div{
display: flex;
}
@ -134,14 +166,76 @@ input#commentModal:checked + div{
border-radius: 50%;
padding: 8px;
font-size: 24px;
cursor: pointer;
}
.close:hover{
background-color: rgb(223, 197, 235);
}
#commentsContent{
padding-top: 30px;
display: grid;
grid-template-columns: 200px auto 64px;
width: 60%;
}
/* @media only screen and (max-width: 800px){
#commentsContent{
width: calc(20% + 480px);
}
}
@media only screen and (max-width: 600px){
#commentsContent{
width: 100%;
}
} */
@media only screen and (max-width: 1000px){
#commentsContent{
width: 600px;
}
}
@media only screen and (max-width: 600px){
#commentsContent{
width: 100%;
}
}
.comment-username{
grid-column: 1 / span 1;
}
.comment-username > p{
background-color: rgb(24, 24, 24);
color: rgb(240, 240, 240);
padding: 12px;
margin: 16px 0px;
}
.comment-text{
grid-column: 2 / span 1;
border-top: 10px solid rgb(24, 24, 24);
padding: 12px;
margin: 16px 0px;
color: rgb(48, 48, 48);
font-size: 18px;
}
.comment-controls{
grid-column: 3 / span 1;
/* border-top: 10px solid rgb(24, 24, 24); */
padding: 20px 0px 20px 12px;
display: flex;
opacity: 0;
}
.comment-controls:hover, .comment-text:hover + .comment-controls, .comment-username:hover + * + .comment-controls{
opacity: 1;
}
.comment-controls.edit-controls{
opacity: 1;
display: flex;
flex-direction: column;
align-items: flex-start;
}
.comment{
.comment-controls.edit-controls > .bestButton{
margin: 2px;
font-size: 16px;
padding: 6px 12px;
}
/* .comment{
text-align: center;
display: flex;
justify-content: flex-start;
@ -151,10 +245,27 @@ input#commentModal:checked + div{
}
.comment > p:first-child{
width: 200px;
} */
.commentControl{
display: block;
border: none;
cursor: pointer;
width: 24px;
height: 24px;
padding: 12px;
margin: 2px;
background-attachment: fixed;
background-position: center;
}
#comments{
/* padding: 0 10%; */
.editIcon{
background: url('edit\ button.svg') no-repeat;
}
.deleteIcon{
background: url('delete\ button.svg') no-repeat;
}
/* #comments{ */
/* padding: 0 10%; */
/* } */
.comment-display{
display: flex;
flex-direction: column;

104
main.js

@ -17,6 +17,15 @@ function request(input, callback){
xhr.send(JSON.stringify(input));
console.log('sent');
}
function addEvent(to, type, fn){
if(document.addEventListener){
to.addEventListener(type, fn, false);
} else if(document.attachEvent){
to.attachEvent('on'+type, fn);
} else {
to['on'+type] = fn;
}
}
function search(user, text){
request({action:'searchComments',name:user,text:text}, (response)=>{
@ -25,13 +34,15 @@ function search(user, text){
comEl.innerHTML = '';
response.comments.forEach((com)=>{
comEl.insertAdjacentHTML('beforeend',
`<div class="comment" nodeID="${com.id}">
<p class="comment-username">
${com.name}
</p>
<p class="comment-text">
${com.text}
</p>
`<div class="comment-username" nodeID="${com.id}">
<p>${com.name}</p>
</div>
<p class="comment-text" nodeID="${com.id}">
${com.text}
</p>
<div class="comment-controls" nodeID="${com.id}">
<button class="commentControl editIcon" onclick="edit(${com.id});"></button>
<button class="commentControl deleteIcon" onclick="deleteComment(${com.id});"></button>
</div>`);
});
}else{
@ -40,12 +51,18 @@ function search(user, text){
});
}
window.onload = function(){
document.onkeypress = function(evt) {
addEvent(document, "keydown", function(evt) {
evt = evt || window.event;
if (evt.keyCode == 27) {
qSelectAll(document, 'body > input[type="checkbox"]:checked').forEach(el => el.checked = false); //escape out of any modal
let isEscape = false;
if ("key" in evt) {
isEscape = (evt.key === "Escape" || evt.key === "Esc");
} else {
isEscape = (evt.keyCode === 27);
}
if (isEscape) {
qSelectAll(document, 'input.modalControl[type="checkbox"]:checked').forEach(el => el.checked = false);
}
};
});
search(document.getElementById('search-comment-name').value, document.getElementById('search-comment-text').value);
}
function qSelectAll(el, str){
@ -62,4 +79,69 @@ function submitComment(name, comment){
console.log('uh-ho');
}
});
}
function edit(cID){
let t = document.querySelector('.comment-text[nodeID="' + cID + '"]');
let b = document.querySelector('.comment-controls[nodeID="' + cID + '"]');
if(t != null && b != null){
let text = t.textContent;
t.innerHTML =
`<div class="EditableComment">
<p id="edit-comment-${cID}" autocomplete="off" spellcheck="true" autocorrect="true" required="" contenteditable>${text}</p>
<div></div>
</div>`;
t.setAttribute('originalText',text);
b.innerHTML =
`<button class="bestButton" onclick="stopEdit(true, ${cID});">Save</button>
<button class="bestButton" onclick="stopEdit(false, ${cID});">Cancel</button>`;
b.classList = 'comment-controls edit-controls';
}else{
console.log('uh-ho');
}
}
function stopEdit(save, cID){
let t = document.querySelector('.comment-text[nodeID="' + cID + '"]');
let b = document.querySelector('.comment-controls[nodeID="' + cID + '"]');
if(t != null && b != null){
let newText = t.getAttribute('originalText');
if(save){
newText = t.querySelector('p').textContent;
}
t.textContent = newText;
b.innerHTML =
`<button class="commentControl editIcon" onclick="edit(${cID});"></button>
<button class="commentControl deleteIcon" onclick="deleteComment(${cID});"></button>`;
b.classList = 'comment-controls';
if(save){
request({action:'editComment', id:cID, newText:newText}, (response)=>{
if(response.success){
console.log('success');
}else{
console.log('uh-ho');
}
});
}
}
}
function deleteComment(cID){
let t = document.querySelector('.comment-text[nodeID="' + cID + '"]');
if(t != null){
document.getElementById('deleteConfirmationModal').checked = true;
document.getElementById('deleteCommentText').innerText = t.innerText;
window.selectedCommentForDeletion = cID;
}
}
function confirmDelete(){
if(window.selectedCommentForDeletion){
let cID = window.selectedCommentForDeletion;
let t = document.querySelector('.comment-text[nodeID="' + cID + '"]');
if(t != null){
request({action:'deleteComment', id:cID}, (response)=>{
if(response.success){
qSelectAll(document, `[nodeID="${cID}"]`).forEach(e=>e.parentElement.removeChild(e));
document.getElementById('deleteConfirmationModal').checked = false;
}
});
}
}
}
Loading…
Cancel
Save