[notes] replace all the javascript

This commit is contained in:
Shish 2024-01-05 02:03:41 +00:00
parent 48b3de3c6e
commit 05a981d935
11 changed files with 393 additions and 321 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 B

File diff suppressed because one or more lines are too long

View file

@ -1,2 +0,0 @@
/** imgnotes jQuery plugin v1.0.0 **/
p{font-family:"Times New Roman";font-size:14px}.ui-widget-content{font-family:"Times New Roman"}.ui-widget-content a{color:blue}.marker{position:absolute;width:27px;height:40px}.marker-text{position:absolute;top:10%;width:100%;margin:0 0 0 0;z-index:1;font-size:12px;font-weight:700;text-align:center;color:#fff}.pin{position:absolute;width:20px;height:30px}.pin-text{position:absolute;top:10%;width:100%;margin:0 0 0 0;font-size:14px;font-weight:700;text-align:center;color:#000}.tooltip{position:relative;display:inline-block}.tooltip .tooltiptext{visibility:visible;width:180px;background-color:#fff;color:#000;text-align:center;padding:5px 0;border-radius:6px;position:absolute;z-index:1;bottom:7px;left:50%;margin-left:-90px}.tooltip .tooltiptext::after{content:"";position:absolute;top:100%;left:50%;margin-left:-7px;border-width:7px;border-style:solid;border-color:#fff transparent transparent transparent}table.gridtable{font-family:verdana,arial,sans-serif;font-size:11px;color:#333;border-width:1px;border-color:#666;border-collapse:collapse}table.gridtable th{border-width:1px;padding:8px;border-style:solid;border-color:#666;background-color:#dedede}table.gridtable td{border-width:1px;padding:8px;border-style:solid;border-color:#666;background-color:#fff}

View file

@ -1,15 +0,0 @@
/**
* imgnotes jQuery plugin
* version 1.0
*
* Copyright (c) 2008 - Dr. Tarique Sani <tarique@sanisoft.com>
*
* Dual licensed under the MIT (MIT-LICENSE.txt)
* and GPL (GPL-LICENSE.txt) licenses.
*
* @URL http://www.sanisoft.com/blog/2008/05/26/img-notes-jquery-plugin/
* @Example example.html
*
**/
(function(e){function t(){e(".note").hover(function(){e(".note").show();e(this).next(".notep").show();e(this).next(".notep").css("z-index",1e4)},function(){e(".note").show();e(this).next(".notep").hide();e(this).next(".notep").css("z-index",0)})}function n(t){note_left=parseInt(imgOffset.left)+parseInt(t.x1);note_top=parseInt(imgOffset.top)+parseInt(t.y1);note_p_top=note_top+parseInt(t.height)+5;note_area_div=e("<div class='note'></div>").css({left:note_left+"px",top:note_top+"px",width:t.width+"px",height:t.height+"px"});note_text_div=e('<div class="notep" >'+t.note+"</div>").css({left:note_left+"px",top:note_p_top+"px"});e("body").append(note_area_div);e("body").append(note_text_div)}function r(t){if(true!==t){return}notes_icon_left=parseInt(imgOffset.left)+parseInt(imgWidth)-36;notes_icon_top=parseInt(imgOffset.top)+parseInt(imgHieght)-40;notes_icon_div=note_area_div=e("<div class='notesicon'></div>").css({left:notes_icon_left+"px",top:notes_icon_top+"px"});e("body").append(notes_icon_div);e(".notesicon").toggle(function(){e.fn.imgNotes.showAll()},function(){e.fn.imgNotes.hideAll()})}e.fn.imgNotes=function(i){if(undefined==s){var s}if(undefined!=i.notes){s=i.notes}if(i.url){e.ajaxSetup({async:false});e.getJSON(i.url,function(e){s=e})}image=this;imgOffset=e(image).offset();imgHieght=e(image).height();imgWidth=e(image).width();e(s).each(function(){n(this)});e(image).hover(function(){e(".note").show()},function(){e(".note").hide();e(".notep").hide()});t();r(i.isMobile);e(window).resize(function(){e(".note").remove();e(".notep").remove();e(".notesicon").remove();imgOffset=e(image).offset();imgHieght=e(image).height();imgWidth=e(image).width();e(s).each(function(){n(this)});t();r(i.isMobile)})};e.fn.imgNotes.showAll=function(){e(".note").show();e(".notep").show()};e.fn.imgNotes.hideAll=function(){e(".note").hide();e(".notep").hide()}})(jQuery);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 B

View file

@ -98,26 +98,49 @@ class Notes extends Extension
if (!$user->is_anonymous()) {
$this->revert_history($noteID, $reviewID);
}
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("note/updated"));
break;
case "add_note":
if (!$user->is_anonymous()) {
$this->add_new_note();
}
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/view/".$_POST["image_id"]));
break;
case "add_request":
if (!$user->is_anonymous()) {
$this->add_note_request();
}
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/view/".$_POST["image_id"]));
break;
case "nuke_requests":
if ($user->can(Permissions::NOTES_ADMIN)) {
$this->nuke_requests();
}
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/view/".$_POST["image_id"]));
break;
case "create_note":
$page->set_mode(PageMode::DATA);
if (!$user->is_anonymous()) {
$note_id = $this->add_new_note();
$page->set_data(json_encode([
'status' => 'success',
'note_id' => $note_id,
]));
}
break;
case "update_note":
$page->set_mode(PageMode::DATA);
if (!$user->is_anonymous()) {
$this->update_note();
$page->set_data(json_encode(['status' => 'success']));
}
break;
case "delete_note":
$page->set_mode(PageMode::DATA);
if ($user->can(Permissions::NOTES_ADMIN)) {
$this->delete_note();
$page->set_data(json_encode(['status' => 'success']));
}
break;
case "nuke_notes":
if ($user->can(Permissions::NOTES_ADMIN)) {
$this->nuke_notes();
@ -126,28 +149,7 @@ class Notes extends Extension
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/view/".$_POST["image_id"]));
break;
case "nuke_requests":
if ($user->can(Permissions::NOTES_ADMIN)) {
$this->nuke_requests();
}
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/view/".$_POST["image_id"]));
break;
case "edit_note":
if (!$user->is_anonymous()) {
$this->update_note();
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/view/" . $_POST["image_id"]));
}
break;
case "delete_note":
if ($user->can(Permissions::NOTES_ADMIN)) {
$this->delete_note();
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/view/".$_POST["image_id"]));
}
break;
default:
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("note/list"));
@ -243,32 +245,43 @@ class Notes extends Extension
/*
* HERE WE ADD A NOTE TO DATABASE
*/
private function add_new_note()
private function add_new_note(): int
{
global $database, $user;
$imageID = int_escape($_POST["image_id"]);
$user_id = $user->id;
$noteX1 = int_escape($_POST["note_x1"]);
$noteY1 = int_escape($_POST["note_y1"]);
$noteHeight = int_escape($_POST["note_height"]);
$noteWidth = int_escape($_POST["note_width"]);
$noteText = html_escape($_POST["note_text"]);
$note = json_decode(file_get_contents('php://input'), true);
$database->execute(
"
INSERT INTO notes (enable, image_id, user_id, user_ip, date, x1, y1, height, width, note)
VALUES (:enable, :image_id, :user_id, :user_ip, now(), :x1, :y1, :height, :width, :note)",
['enable' => 1, 'image_id' => $imageID, 'user_id' => $user_id, 'user_ip' => get_real_ip(), 'x1' => $noteX1, 'y1' => $noteY1, 'height' => $noteHeight, 'width' => $noteWidth, 'note' => $noteText]
[
'enable' => 1,
'image_id' => $note['image_id'],
'user_id' => $user->id,
'user_ip' => get_real_ip(),
'x1' => $note['x1'],
'y1' => $note['y1'],
'height' => $note['height'],
'width' => $note['width'],
'note' => $note['note'],
]
);
$noteID = $database->get_last_insert_id('notes_id_seq');
log_info("notes", "Note added {$noteID} by {$user->name}");
$database->execute("UPDATE images SET notes=(SELECT COUNT(*) FROM notes WHERE image_id=:id1) WHERE id=:id2", ['id1' => $imageID, 'id2' => $imageID]);
$database->execute("UPDATE images SET notes=(SELECT COUNT(*) FROM notes WHERE image_id=:id) WHERE id=:id", ['id' => $note['image_id']]);
$this->add_history(1, $noteID, $imageID, $noteX1, $noteY1, $noteHeight, $noteWidth, $noteText);
$this->add_history(
1, $noteID, $note['image_id'],
$note['x1'], $note['y1'],
$note['height'], $note['width'],
$note['note']
);
return $noteID;
}
private function add_note_request()
@ -294,15 +307,7 @@ class Notes extends Extension
{
global $database;
$note = [
"x1" => int_escape($_POST["note_x1"]),
"y1" => int_escape($_POST["note_y1"]),
"height" => int_escape($_POST["note_height"]),
"width" => int_escape($_POST["note_width"]),
"note" => $_POST["note_text"],
"image_id" => int_escape($_POST["image_id"]),
"id" => int_escape($_POST["note_id"])
];
$note = json_decode(file_get_contents('php://input'), true);
// validate parameters
if (empty($note['note'])) {
@ -312,29 +317,22 @@ class Notes extends Extension
$database->execute("
UPDATE notes
SET x1 = :x1, y1 = :y1, height = :height, width = :width, note = :note
WHERE image_id = :image_id AND id = :id", $note);
WHERE image_id = :image_id AND id = :note_id", $note);
$this->add_history(1, $note['id'], $note['image_id'], $note['x1'], $note['y1'], $note['height'], $note['width'], $note['note']);
$this->add_history(1, $note['note_id'], $note['image_id'], $note['x1'], $note['y1'], $note['height'], $note['width'], $note['note']);
}
private function delete_note()
{
global $user, $database;
$imageID = int_escape($_POST["image_id"]);
$noteID = int_escape($_POST["note_id"]);
// validate parameters
if (is_null($imageID) || !is_numeric($imageID) || is_null($noteID) || !is_numeric($noteID)) {
return;
}
$note = json_decode(file_get_contents('php://input'), true);
$database->execute("
UPDATE notes SET enable = :enable
WHERE image_id = :image_id AND id = :id
", ['enable' => 0, 'image_id' => $imageID, 'id' => $noteID]);
", ['enable' => 0, 'image_id' => $note["image_id"], 'id' => $note["note_id"]]);
log_info("notes", "Note deleted {$noteID} by {$user->name}");
log_info("notes", "Note deleted {$note["note_id"]} by {$user->name}");
}
private function nuke_notes()

View file

@ -1,81 +1,274 @@
/*jshint bitwise:true, curly:true, forin:false, noarg:true, noempty:true, nonew:true, undef:true, strict:false, browser:true, jquery:true */
let notesContainer = null;
let noteImage = document.getElementById('main_image');
let noteBeingEdited = null;
let dragStart = null;
document.addEventListener('DOMContentLoaded', () => {
if(window.notes) {
$('#main_image').load(function(){
$('#main_image').imgNotes({notes: window.notes});
if(noteImage.complete) {
renderNotes();
} else {
noteImage.addEventListener('load', () => {
renderNotes();
});
}
//Make sure notes are always shown
$('#main_image').off('mouseenter mouseleave');
let resizeObserver = new ResizeObserver(entries => {
renderNotes();
});
resizeObserver.observe(noteImage);
}
});
function renderNotes() {
// reset the DOM to empty
if(notesContainer) {
notesContainer.remove();
}
$('#cancelnote').click(function(){
$('#main_image').imgAreaSelect({ hide: true });
$('#noteform').hide();
// check the image we're adding notes on top of
let br = noteImage.getBoundingClientRect();
let scale = br.width / noteImage.getAttribute("data-width");
// render a container full of notes
notesContainer = document.createElement('div');
notesContainer.className = 'notes-container';
notesContainer.style.left = window.scrollX + br.left + 'px';
notesContainer.style.top = window.scrollY + br.top + 'px';
notesContainer.style.width = br.width + 'px';
notesContainer.style.height = br.height + 'px';
// render each note
window.notes.forEach(note => {
let noteDiv = document.createElement('div');
noteDiv.classList.add('note');
noteDiv.style.left = note.x1 * scale + 'px';
noteDiv.style.top = note.y1 * scale + 'px';
noteDiv.style.width = note.width * scale + 'px';
noteDiv.style.height = note.height * scale + 'px';
let text = document.createElement('div');
text.innerText = note.note;
noteDiv.addEventListener('click', (e) => {
noteBeingEdited = note.note_id;
renderNotes();
});
noteDiv.appendChild(text);
notesContainer.appendChild(noteDiv);
// if the current note is being edited, render the editor
if(note.note_id == noteBeingEdited) {
let editor = renderEditor(noteDiv, note);
notesContainer.appendChild(editor);
}
});
$('#EditCancelNote').click(function() {
$('#main_image').imgAreaSelect({ hide: true });
$('#noteEditForm').hide();
});
$('#addnote').click(function(){
$('#noteEditForm').hide();
$('#main_image').imgAreaSelect({ onSelectChange: showaddnote, x1: 120, y1: 90, x2: 280, y2: 210 });
return false;
});
$('.note').click(function() {
$('#noteform').hide();
var imgOffset = $('#main_image').offset();
var x1 = parseInt(this.style.left) - imgOffset.left;
var y1 = parseInt(this.style.top) - imgOffset.top;
var width = parseInt(this.style.width);
var height = parseInt(this.style.height);
var text = $(this).next('.notep').text().replace(/([^>]?)\\n{2}/g, '$1\\n');
var id = $(this).next('.notep').next('.noteID').text();
$('#main_image').imgAreaSelect({ onSelectChange: showeditnote, x1: x1, y1: y1, x2: x1 + width, y2: y1 + height });
setEditNoteData(x1, y1, width, height, text, id);
});
});
function showaddnote (img, area) {
var imgOffset = $(img).offset();
var form_left = parseInt(imgOffset.left) + parseInt(area.x1);
var form_top = parseInt(imgOffset.top) + parseInt(area.y1) + parseInt(area.height)+5;
$('#noteform').css({ left: form_left + 'px', top: form_top + 'px'});
$('#noteform').show();
$('#noteform').css('z-index', 10000);
$('#NoteX1').val(area.x1);
$('#NoteY1').val(area.y1);
$('#NoteHeight').val(area.height);
$('#NoteWidth').val(area.width);
noteImage.parentNode.appendChild(notesContainer);
}
function showeditnote (img, area) {
var imgOffset = $(img).offset();
var form_left = parseInt(imgOffset.left) + area.x1;
var form_top = parseInt(imgOffset.top) + area.y2;
/**
*
* @param {HTMLElement} noteDiv
* @param {*} note
* @returns
*/
function renderEditor(noteDiv, note) {
// check the image we're adding notes on top of
let br = noteImage.getBoundingClientRect();
let scale = br.width / noteImage.getAttribute("data-width");
$('#noteEditForm').css({ left: form_left + 'px', top: form_top + 'px'});
$('#noteEditForm').show();
$('#noteEditForm').css('z-index', 10000);
$('#EditNoteX1').val(area.x1);
$('#EditNoteY1').val(area.y1);
$('#EditNoteHeight').val(area.height);
$('#EditNoteWidth').val(area.width);
// set the note itself into drag & resize mode
// NOTE: to avoid re-rendering the whole DOM every time the mouse
// moves, we directly edit the style of the noteDiv, and then when
// the mouse is released, we update the note object and re-render
noteDiv.classList.add('editing');
noteDiv.addEventListener('mousedown', (e) => {
dragStart = {
x: e.pageX,
y: e.pageY,
mode: getArea(e.offsetX, e.offsetY, noteDiv.offsetWidth, noteDiv.offsetHeight),
};
noteDiv.classList.add("dragging");
});
noteDiv.addEventListener('mousemove', (e) => {
if(dragStart) {
if(dragStart.mode == "c") {
noteDiv.style.left = (note.x1 * scale) + (e.pageX - dragStart.x) + 'px';
noteDiv.style.top = (note.y1 * scale) + (e.pageY - dragStart.y) + 'px';
}
if(dragStart.mode.indexOf("n") >= 0) {
noteDiv.style.top = (note.y1 * scale) + (e.pageY - dragStart.y) + 'px';
noteDiv.style.height = (note.height * scale) - (e.pageY - dragStart.y) + 'px';
}
if(dragStart.mode.indexOf("s") >= 0) {
noteDiv.style.height = (note.height * scale) + (e.pageY - dragStart.y) + 'px';
}
if(dragStart.mode.indexOf("w") >= 0) {
noteDiv.style.left = (note.x1 * scale) + (e.pageX - dragStart.x) + 'px';
noteDiv.style.width = (note.width * scale) - (e.pageX - dragStart.x) + 'px';
}
if(dragStart.mode.indexOf("e") >= 0) {
noteDiv.style.width = (note.width * scale) + (e.pageX - dragStart.x) + 'px';
}
} else {
let area = getArea(e.offsetX, e.offsetY, noteDiv.offsetWidth, noteDiv.offsetHeight);
if(area == "c") {
noteDiv.style.cursor = 'move';
} else {
noteDiv.style.cursor = area + '-resize';
}
}
});
function _commit() {
noteDiv.classList.remove("dragging");
dragStart = null;
note.x1 = noteDiv.offsetLeft / scale;
note.y1 = noteDiv.offsetTop / scale;
note.width = noteDiv.offsetWidth / scale;
note.height = noteDiv.offsetHeight / scale;
renderNotes();
}
noteDiv.addEventListener('mouseup', _commit);
noteDiv.addEventListener('mouseleave', _commit);
// add textarea / save / cancel / delete buttons
let editor = document.createElement('div');
editor.classList.add('editor');
editor.style.left = note.x1 * scale + 'px';
editor.style.top = (note.y1 + note.height) * scale + 'px';
let textarea = document.createElement('textarea');
textarea.value = note.note;
textarea.addEventListener('input', () => {
note.note = textarea.value;
});
editor.appendChild(textarea);
let save = document.createElement('button');
save.innerText = 'Save';
save.addEventListener('click', () => {
if(note.note_id == null) {
fetch('/note/create_note', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(note)
}).then(response => {
if(response.ok) {
return response.json();
} else {
throw new Error('Failed to create note');
}
}).then(data => {
note.note_id = data.note_id;
renderNotes();
}).catch(error => {
alert(error);
});
} else {
fetch('/note/update_note', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(note)
}).then(response => {
if(!response.ok) {
throw new Error('Failed to update note');
}
}).catch(error => {
alert(error);
});
}
noteBeingEdited = null;
renderNotes();
});
editor.appendChild(save);
let cancel = document.createElement('button');
cancel.innerText = 'Cancel';
cancel.addEventListener('click', () => {
noteBeingEdited = null;
if(note.note_id == null) {
// delete the un-saved note
window.notes = window.notes.filter(n => n.note_id != null);
}
renderNotes();
});
editor.appendChild(cancel);
if(window.notes_admin && note.note_id != null) {
let deleteNote = document.createElement('button');
deleteNote.innerText = 'Delete';
deleteNote.addEventListener('click', () => {
// TODO: delete note from server
fetch('/note/delete_note', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(note)
}).then(response => {
if(!response.ok) {
throw new Error('Failed to delete note');
}
}).catch(error => {
alert(error);
});
noteBeingEdited = null;
window.notes = window.notes.filter(n => n.note_id != note.note_id);
renderNotes();
});
editor.appendChild(deleteNote);
}
return editor;
}
function setEditNoteData(x1, y1, width, height, text, id) {
$('#EditNoteX1').val(x1);
$('#EditNoteY1').val(y1);
$('#EditNoteHeight').val(height);
$('#EditNoteWidth').val(width);
$('#EditNoteNote').text(text);
$('#EditNoteID').val(id);
$('#DeleteNoteNoteID').val(id);
function addNewNote() {
if(window.notes.filter(note => note.note_id == null).length > 0) {
alert("Please save all notes before adding a new one.");
return;
}
window.notes.push(
{
x1: 10,
y1: 10,
width: 100,
height: 40,
note: "new note",
note_id: null,
image_id: window.notes_image_id,
}
);
noteBeingEdited = null;
renderNotes();
}
function getArea(x, y, width, height) {
let border = 10;
if(y < border) {
if(x < border) {
return "nw";
} else if(x > width - border) {
return "ne";
} else {
return "n";
}
} else if(y > height - border) {
if(x < border) {
return "sw";
} else if(x > width - border) {
return "se";
} else {
return "s";
}
} else if(x < border) {
return "w";
} else if(x > width - border) {
return "e";
} else {
return "c";
}
}

View file

@ -1,87 +1,57 @@
.note {
display: block;
.notes-container {
position: absolute;
border: 1px solid red;
}
.notes-container .note {
display: flex;
justify-content: center;
align-items: center;
color: black;
background-color: #FFE;
border: 1px dashed black;
overflow: hidden;
position: absolute;
z-index: 0;
filter:alpha(opacity=50);
-moz-opacity:0.5;
-khtml-opacity: 0.5;
opacity: 0.5;
z-index: 1;
}
.notep {
display: none;
color: #412a21;
background-color: #fffdef;
border: #412a21 1px solid;
font-size: 8pt;
margin-top: 0;
padding: 2px;
position: absolute;
width: 175px;
.notes-container .note.editing {
opacity: 1;
border: 1px dashed red;
z-index: 2;
}
#noteform, #noteEditForm {
display: none;
position: absolute;
width: 250px;
}
#noteform textarea, #noteEditForm textarea {
width: 100%;
}
/*
* imgAreaSelect default style
*/
.imgareaselect-border1 {
background: url(border-v.gif) repeat-y left top;
}
.imgareaselect-border2 {
background: url(border-h.gif) repeat-x left top;
}
.imgareaselect-border3 {
background: url(border-v.gif) repeat-y right top;
}
.imgareaselect-border4 {
background: url(border-h.gif) repeat-x left bottom;
}
.imgareaselect-border1, .imgareaselect-border2,
.imgareaselect-border3, .imgareaselect-border4 {
filter: alpha(opacity=50);
.notes-container .note.editing.dragging {
opacity: 0.5;
z-index: 2;
}
.notes-container .note:hover {
opacity: 1;
z-index: 3;
}
.imgareaselect-handle {
background-color: #fff;
border: solid 1px #000;
filter: alpha(opacity=50);
opacity: 0.5;
.notes-container .editor {
display: grid;
color: black;
background-color: #EFE;
border: 1px dashed blue;
position: absolute;
grid-template-columns: 1fr 1fr;
grid-template-areas:
"text text"
"save cancel"
"delete delete";
z-index: 4;
}
.imgareaselect-outer {
/*background-color: #000;*/
filter: alpha(opacity=50);
opacity: 0.5;
.notes-container .editor TEXTAREA {
grid-area: text;
// resize: none;
}
.imgareaselect-selection {
.notes-container .editor BUTTON[value="Save"] {
grid-area: save;
}
/* Makes sure the note block is hidden */
section#note_system {
height: 0;
.notes-container .editor BUTTON[value="Cancel"] {
grid-area: cancel;
}
section#note_system > .blockbody {
padding: 0;
border: 0;
.notes-container .editor BUTTON[value="Delete"] {
grid-area: delete;
}

View file

@ -4,41 +4,38 @@ declare(strict_types=1);
namespace Shimmie2;
use MicroHTML\HTMLElement;
use function MicroHTML\INPUT;
class NotesTheme extends Themelet
{
public function note_button(int $image_id): string
public function note_button(int $image_id): HTMLElement
{
return '
<!-- <a href="#" id="addnotelink" >Add a note</a> -->
<form action="" method="">
<input type="button" id="addnote" value="Add Note">
<input type="hidden" name="image_id" value="'.$image_id.'">
</form>
';
return SHM_SIMPLE_FORM("", INPUT(["type"=>"button", "value"=>"Add Note", "onclick"=>"addNewNote()"]));
}
public function request_button(int $image_id): string
public function request_button(int $image_id): HTMLElement
{
return make_form(make_link("note/add_request")) . '
<input id="noterequest" type="submit" value="Add Note Request">
<input type="hidden" name="image_id" value="'.$image_id.'">
</form>
';
return SHM_SIMPLE_FORM(
"note/add_request",
INPUT(["type"=>"hidden", "name"=>"image_id", "value"=>$image_id]),
INPUT(["type"=>"submit", "value"=>"Add Note Request"]),
);
}
public function nuke_notes_button(int $image_id): string
public function nuke_notes_button(int $image_id): HTMLElement
{
return make_form(make_link("note/nuke_notes")) . '
<input id="noterequest" type="submit" value="Nuke Notes" onclick="return confirm_action(\'Are you sure?\')">
<input type="hidden" name="image_id" value="'.$image_id.'">
</form>
';
return SHM_SIMPLE_FORM(
"note/nuke_notes",
INPUT(["type"=>"hidden", "name"=>"image_id", "value"=>$image_id]),
INPUT(["type"=>"submit", "value"=>"Nuke Notes", "onclick"=>"return confirm_action('Are you sure?')"]),
);
}
public function nuke_requests_button(int $image_id): string
public function nuke_requests_button(int $image_id): HTMLElement
{
return make_form(make_link("note/nuke_requests")) . '
<input id="noterequest" type="submit" value="Nuke Requests" onclick="return confirm_action()">
<input type="hidden" name="image_id" value="'.$image_id.'">
</form>
';
return SHM_SIMPLE_FORM(
"note/nuke_requests",
INPUT(["type"=>"hidden", "name"=>"image_id", "value"=>$image_id]),
INPUT(["type"=>"submit", "value"=>"Nuke Requests", "onclick"=>"return confirm_action('Are you sure?')"]),
);
}
public function search_notes_page(Page $page): void
@ -56,91 +53,23 @@ class NotesTheme extends Themelet
// check action POST on form
public function display_note_system(Page $page, int $image_id, array $recovered_notes, bool $adminOptions): void
{
$base_href = get_base_href();
$page->add_html_header("<script defer src='$base_href/ext/notes/lib/jquery.imgnotes-1.0.min.js' type='text/javascript'></script>");
$page->add_html_header("<script defer src='$base_href/ext/notes/lib/jquery.imgareaselect-1.0.0-rc1.min.js' type='text/javascript'></script>");
$page->add_html_header("<link rel='stylesheet' type='text/css' href='$base_href/ext/notes/lib/jquery.imgnotes-1.0.min.css' />");
$to_json = [];
foreach ($recovered_notes as $note) {
$parsedNote = $note["note"];
$parsedNote = str_replace("\n", "\\n", $parsedNote);
$parsedNote = str_replace("\r", "\\r", $parsedNote);
$to_json[] = [
'image_id' => $image_id,
'x1' => $note["x1"],
'y1' => $note["y1"],
'height' => $note["height"],
'width' => $note["width"],
'note' => $parsedNote,
'note' => $note["note"],
'note_id' => $note["id"],
];
}
$html = "<script type='text/javascript'>notes = ".json_encode($to_json)."</script>";
$html .= "
<div id='noteform'>
".make_form(make_link("note/add_note"))."
<input type='hidden' name='image_id' value='".$image_id."' />
<input name='note_x1' type='hidden' value='' id='NoteX1' />
<input name='note_y1' type='hidden' value='' id='NoteY1' />
<input name='note_height' type='hidden' value='' id='NoteHeight' />
<input name='note_width' type='hidden' value='' id='NoteWidth' />
<table>
<tr>
<td colspan='2'>
<textarea name='note_text' id='NoteNote' ></textarea>
</td>
</tr>
<tr>
<td><input type='submit' value='Add Note' /></td>
<td><input type='button' value='Cancel' id='cancelnote' /></td>
</tr>
</table>
</form>
</div>
<div id='noteEditForm'>
".make_form(make_link("note/edit_note"))."
<input type='hidden' name='image_id' value='".$image_id."' />
<input type='hidden' name='note_id' id='EditNoteID' value='' />
<input name='note_x1' type='hidden' value='' id='EditNoteX1' />
<input name='note_y1' type='hidden' value='' id='EditNoteY1' />
<input name='note_height' type='hidden' value='' id='EditNoteHeight' />
<input name='note_width' type='hidden' value='' id='EditNoteWidth' />
<table>
<tr>
<td colspan='2'>
<textarea name='note_text' id='EditNoteNote' ></textarea>
</td>
</tr>
<tr>
<td><input type='submit' value='Save Note' /></td>
<td><input type='button' value='Cancel' id='EditCancelNote' /></td>
</tr>
</table>
</form>";
if ($adminOptions) {
$html .= "
".make_form(make_link("note/delete_note"))."
<input type='hidden' name='image_id' value='".$image_id."' />
<input type='hidden' name='note_id' value='' id='DeleteNoteNoteID' />
<table>
<tr>
<td><input type='submit' value='Delete note' /></td>
</tr>
</table>
</form>
";
}
$html .= "</div>";
$page->add_block(new Block(null, $html, "main", 1, 'note_system'));
$page->add_html_header("<script type='text/javascript'>
window.notes = ".json_encode($to_json).";
window.notes_image_id = $image_id;
window.notes_admin = ".($adminOptions ? "true" : "false").";
</script>");
}

View file

@ -3,10 +3,11 @@
declare(strict_types=1);
namespace Shimmie2;
use MicroHTML\HTMLElement;
class ImageAdminBlockBuildingEvent extends Event
{
/** @var string[] */
/** @var HTMLElement[]|string[] */
public array $parts = [];
public Image $image;
public User $user;
@ -20,7 +21,7 @@ class ImageAdminBlockBuildingEvent extends Event
$this->context = $context;
}
public function add_part(string $html, int $position = 50)
public function add_part(HTMLElement|string $html, int $position = 50)
{
while (isset($this->parts[$position])) {
$position++;