client/posts: add copying notes to clipboard
Saves some frustration when losing changes due to editing conflict
This commit is contained in:
parent
674d6c35d7
commit
87735110aa
|
@ -66,6 +66,12 @@
|
|||
<a href class='add'>Add a note</a>
|
||||
<%= ctx.makeTextarea({disabled: true, text: 'Content (supports Markdown)', rows: '8'}) %>
|
||||
<a href class='delete inactive'>Delete selected note</a>
|
||||
<% if (ctx.hasClipboard) { %>
|
||||
<br/>
|
||||
<a href class='copy'>Export notes to clipboard</a>
|
||||
<br/>
|
||||
<a href class='paste'>Import notes from clipboard</a>
|
||||
<% } %>
|
||||
</section>
|
||||
<% } %>
|
||||
|
||||
|
|
|
@ -5,6 +5,8 @@ const config = require('../config.js');
|
|||
const events = require('../events.js');
|
||||
const misc = require('../util/misc.js');
|
||||
const views = require('../util/views.js');
|
||||
const Note = require('../models/note.js');
|
||||
const Point = require('../models/point.js');
|
||||
const TagInputControl = require('./tag_input_control.js');
|
||||
const ExpanderControl = require('../controls/expander_control.js');
|
||||
const FileDropperControl = require('../controls/file_dropper_control.js');
|
||||
|
@ -25,6 +27,7 @@ class PostEditSidebarControl extends events.EventTarget {
|
|||
views.replaceContent(this._hostNode, template({
|
||||
post: this._post,
|
||||
enableSafety: config.enableSafety,
|
||||
hasClipboard: document.queryCommandSupported('copy'),
|
||||
canEditPostSafety: api.hasPrivilege('posts:edit:safety'),
|
||||
canEditPostSource: api.hasPrivilege('posts:edit:source'),
|
||||
canEditPostTags: api.hasPrivilege('posts:edit:tags'),
|
||||
|
@ -107,6 +110,16 @@ class PostEditSidebarControl extends events.EventTarget {
|
|||
'click', e => this._evtAddNoteClick(e));
|
||||
}
|
||||
|
||||
if (this._copyNotesLinkNode) {
|
||||
this._copyNotesLinkNode.addEventListener(
|
||||
'click', e => this._evtCopyNotesClick(e));
|
||||
}
|
||||
|
||||
if (this._pasteNotesLinkNode) {
|
||||
this._pasteNotesLinkNode.addEventListener(
|
||||
'click', e => this._evtPasteNotesClick(e));
|
||||
}
|
||||
|
||||
if (this._deleteNoteLinkNode) {
|
||||
this._deleteNoteLinkNode.addEventListener(
|
||||
'click', e => this._evtDeleteNoteClick(e));
|
||||
|
@ -252,6 +265,50 @@ class PostEditSidebarControl extends events.EventTarget {
|
|||
this._postNotesOverlayControl.switchToDrawing();
|
||||
}
|
||||
|
||||
_evtCopyNotesClick(e) {
|
||||
e.preventDefault();
|
||||
let textarea = document.createElement('textarea');
|
||||
textarea.style.position = 'fixed';
|
||||
textarea.style.opacity = '0';
|
||||
textarea.value = JSON.stringify([...this._post.notes].map(note => ({
|
||||
polygon: [...note.polygon].map(
|
||||
point => [point.x, point.y]),
|
||||
text: note.text,
|
||||
})));
|
||||
document.body.appendChild(textarea);
|
||||
textarea.select();
|
||||
|
||||
let success = false;
|
||||
try {
|
||||
success = document.execCommand('copy');
|
||||
} catch (err) {
|
||||
}
|
||||
textarea.blur();
|
||||
document.body.removeChild(textarea);
|
||||
alert(success
|
||||
? 'Notes copied to clipboard.'
|
||||
: 'Failed to copy the text to clipboard. Sorry.');
|
||||
}
|
||||
|
||||
_evtPasteNotesClick(e) {
|
||||
e.preventDefault();
|
||||
const text = window.prompt(
|
||||
'Please enter the exported notes snapshot:');
|
||||
if (!text) {
|
||||
return;
|
||||
}
|
||||
const notesObj = JSON.parse(text);
|
||||
this._post.notes.clear();
|
||||
for (let noteObj of notesObj) {
|
||||
let note = new Note();
|
||||
for (let pointObj of noteObj.polygon) {
|
||||
note.polygon.add(new Point(pointObj[0], pointObj[1]));
|
||||
}
|
||||
note.text = noteObj.text;
|
||||
this._post.notes.add(note);
|
||||
}
|
||||
}
|
||||
|
||||
_evtDeleteNoteClick(e) {
|
||||
e.preventDefault();
|
||||
if (e.target.classList.contains('inactive')) {
|
||||
|
@ -350,6 +407,14 @@ class PostEditSidebarControl extends events.EventTarget {
|
|||
return this._formNode.querySelector('.notes .add');
|
||||
}
|
||||
|
||||
get _copyNotesLinkNode() {
|
||||
return this._formNode.querySelector('.notes .copy');
|
||||
}
|
||||
|
||||
get _pasteNotesLinkNode() {
|
||||
return this._formNode.querySelector('.notes .paste');
|
||||
}
|
||||
|
||||
get _deleteNoteLinkNode() {
|
||||
return this._formNode.querySelector('.notes .delete');
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue