2018-03-26 08:52:38 +08:00
import utils from '../services/utils.js' ;
import server from '../services/server.js' ;
2019-11-09 22:21:14 +08:00
import toastService from "../services/toast.js" ;
2020-01-21 05:35:52 +08:00
import appContext from "../services/app_context.js" ;
2018-03-26 08:52:38 +08:00
const $dialog = $ ( "#note-revisions-dialog" ) ;
const $list = $ ( "#note-revision-list" ) ;
2019-11-10 03:59:49 +08:00
const $listDropdown = $ ( "#note-revision-list-dropdown" ) ;
2018-03-26 08:52:38 +08:00
const $content = $ ( "#note-revision-content" ) ;
const $title = $ ( "#note-revision-title" ) ;
2019-11-09 15:53:13 +08:00
const $titleButtons = $ ( "#note-revision-title-buttons" ) ;
2019-11-09 22:21:14 +08:00
const $eraseAllRevisionsButton = $ ( "#note-revisions-erase-all-revisions-button" ) ;
2018-03-26 08:52:38 +08:00
2019-11-10 03:59:49 +08:00
$listDropdown . dropdown ( ) ;
$listDropdown . parent ( ) . on ( 'hide.bs.dropdown' , e => {
// prevent closing dropdown by clicking outside
if ( e . clickEvent ) {
e . preventDefault ( ) ;
}
} ) ;
2018-03-26 08:52:38 +08:00
let revisionItems = [ ] ;
2018-11-14 21:52:05 +08:00
let note ;
2019-11-10 03:59:49 +08:00
let noteRevisionId ;
2018-03-26 08:52:38 +08:00
2019-09-03 01:56:52 +08:00
export async function showCurrentNoteRevisions ( ) {
2020-02-08 04:08:55 +08:00
await showNoteRevisionsDialog ( appContext . tabManager . getActiveTabNoteId ( ) ) ;
2018-03-26 08:52:38 +08:00
}
2019-08-21 03:40:47 +08:00
export async function showNoteRevisionsDialog ( noteId , noteRevisionId ) {
2020-02-09 17:00:13 +08:00
utils . openDialog ( $dialog ) ;
2018-03-26 08:52:38 +08:00
2019-11-09 22:21:14 +08:00
await loadNoteRevisions ( noteId , noteRevisionId ) ;
}
2019-11-10 03:59:49 +08:00
async function loadNoteRevisions ( noteId , noteRevId ) {
2018-03-26 08:52:38 +08:00
$list . empty ( ) ;
$content . empty ( ) ;
2020-02-08 04:08:55 +08:00
note = appContext . tabManager . getActiveTabNote ( ) ;
2019-11-02 02:21:48 +08:00
revisionItems = await server . get ( ` notes/ ${ noteId } /revisions ` ) ;
2018-03-26 08:52:38 +08:00
for ( const item of revisionItems ) {
2019-11-10 03:59:49 +08:00
$list . append ( $ ( '<a class="dropdown-item" tabindex="0">' )
. text ( item . dateLastEdited . substr ( 0 , 16 ) + ` ( ${ item . contentLength } bytes) ` )
2020-05-01 06:01:53 +08:00
. attr ( 'data-note-revision-id' , item . noteRevisionId ) )
. attr ( 'title' , 'This revision was last edited on ' + item . dateLastEdited ) ;
2018-03-26 08:52:38 +08:00
}
2019-11-10 03:59:49 +08:00
$listDropdown . dropdown ( 'show' ) ;
noteRevisionId = noteRevId ;
2018-03-26 08:52:38 +08:00
if ( revisionItems . length > 0 ) {
if ( ! noteRevisionId ) {
2019-11-10 03:59:49 +08:00
noteRevisionId = revisionItems [ 0 ] . noteRevisionId ;
2018-03-26 08:52:38 +08:00
}
2019-11-09 22:21:14 +08:00
} else {
2018-03-26 08:52:38 +08:00
$title . text ( "No revisions for this note yet..." ) ;
2019-11-10 03:59:49 +08:00
noteRevisionId = null ;
2018-03-26 08:52:38 +08:00
}
}
2019-11-10 03:59:49 +08:00
$dialog . on ( 'shown.bs.modal' , ( ) => {
$list . find ( ` [data-note-revision-id=" ${ noteRevisionId } "] ` )
. trigger ( 'focus' ) ;
} ) ;
async function setContentPane ( ) {
const noteRevisionId = $list . find ( ".active" ) . attr ( 'data-note-revision-id' ) ;
2018-03-26 08:52:38 +08:00
2019-11-10 03:59:49 +08:00
const revisionItem = revisionItems . find ( r => r . noteRevisionId === noteRevisionId ) ;
2018-03-26 08:52:38 +08:00
2019-11-09 22:21:14 +08:00
$titleButtons . empty ( ) ;
$content . empty ( ) ;
2018-03-26 08:52:38 +08:00
$title . html ( revisionItem . title ) ;
2018-04-09 00:13:52 +08:00
2019-11-09 23:51:51 +08:00
const $eraseRevisionButton = $ ( '<button class="btn btn-sm" type="button">Delete this revision</button>' ) ;
2019-11-09 22:21:14 +08:00
$eraseRevisionButton . on ( 'click' , async ( ) => {
const confirmDialog = await import ( '../dialogs/confirm.js' ) ;
2019-11-09 23:51:51 +08:00
const text = 'Do you want to delete this revision? This action will delete revision title and content, but still preserve revision metadata.' ;
2019-11-09 22:21:14 +08:00
if ( await confirmDialog . confirm ( text ) ) {
await server . remove ( ` notes/ ${ revisionItem . noteId } /revisions/ ${ revisionItem . noteRevisionId } ` ) ;
loadNoteRevisions ( revisionItem . noteId ) ;
2019-11-09 23:51:51 +08:00
toastService . showMessage ( 'Note revision has been deleted.' ) ;
2019-11-09 22:21:14 +08:00
}
} ) ;
$titleButtons
. append ( $eraseRevisionButton )
. append ( ' ' ) ;
2019-11-09 15:53:13 +08:00
const $downloadButton = $ ( '<button class="btn btn-sm btn-primary" type="button">Download</button>' ) ;
$downloadButton . on ( 'click' , ( ) => {
2019-11-23 03:35:17 +08:00
const url = utils . getUrlForDownload ( ` api/notes/ ${ revisionItem . noteId } /revisions/ ${ revisionItem . noteRevisionId } /download ` ) ;
utils . download ( url ) ;
2019-11-09 15:53:13 +08:00
} ) ;
2019-11-09 22:21:14 +08:00
$titleButtons . append ( $downloadButton ) ;
2019-11-09 15:53:13 +08:00
2019-11-02 02:21:48 +08:00
const fullNoteRevision = await server . get ( ` notes/ ${ revisionItem . noteId } /revisions/ ${ revisionItem . noteRevisionId } ` ) ;
2019-11-09 20:01:05 +08:00
if ( revisionItem . type === 'text' ) {
2019-11-02 02:21:48 +08:00
$content . html ( fullNoteRevision . content ) ;
2018-04-09 00:13:52 +08:00
}
2019-11-09 20:01:05 +08:00
else if ( revisionItem . type === 'code' ) {
2019-11-02 02:21:48 +08:00
$content . html ( $ ( "<pre>" ) . text ( fullNoteRevision . content ) ) ;
2018-04-09 00:13:52 +08:00
}
2019-11-09 20:01:05 +08:00
else if ( revisionItem . type === 'image' ) {
2019-11-09 06:09:57 +08:00
$content . html ( $ ( "<img>" )
2019-11-09 15:53:13 +08:00
// reason why we put this inline as base64 is that we do not want to let user to copy this
// as a URL to be used in a note. Instead if they copy and paste it into a note, it will be a uploaded as a new note
2019-11-09 06:09:57 +08:00
. attr ( "src" , ` data: ${ note . mime } ;base64, ` + fullNoteRevision . content )
2019-11-10 03:59:49 +08:00
. css ( "max-width" , "100%" )
. css ( "max-height" , "100%" ) ) ;
2019-11-09 06:09:57 +08:00
}
2019-11-09 20:01:05 +08:00
else if ( revisionItem . type === 'file' ) {
const $table = $ ( "<table cellpadding='10'>" )
. append ( $ ( "<tr>" ) . append (
$ ( "<th>" ) . text ( "MIME: " ) ,
$ ( "<td>" ) . text ( revisionItem . mime )
) )
. append ( $ ( "<tr>" ) . append (
$ ( "<th>" ) . text ( "File size:" ) ,
$ ( "<td>" ) . text ( revisionItem . contentLength + " bytes" )
) ) ;
if ( fullNoteRevision . content ) {
$table . append ( $ ( "<tr>" ) . append (
$ ( "<th>" ) . text ( "Preview:" ) ,
$ ( "<td>" ) . append (
$ ( '<pre class="file-preview-content"></pre>' )
. text ( fullNoteRevision . content )
)
) ) ;
}
$content . html ( $table ) ;
2019-11-09 18:58:52 +08:00
}
2018-11-14 21:52:05 +08:00
else {
$content . text ( "Preview isn't available for this note type." ) ;
}
2019-11-10 03:59:49 +08:00
}
2019-11-09 22:21:14 +08:00
$eraseAllRevisionsButton . on ( 'click' , async ( ) => {
const confirmDialog = await import ( '../dialogs/confirm.js' ) ;
2019-11-09 23:51:51 +08:00
const text = 'Do you want to delete all revisions of this note? This action will erase revision title and content, but still preserve revision metadata.' ;
2019-11-09 22:21:14 +08:00
if ( await confirmDialog . confirm ( text ) ) {
await server . remove ( ` notes/ ${ note . noteId } /revisions ` ) ;
$dialog . modal ( 'hide' ) ;
2019-11-09 23:51:51 +08:00
toastService . showMessage ( 'Note revisions has been deleted.' ) ;
2019-11-09 22:21:14 +08:00
}
2019-11-10 03:59:49 +08:00
} ) ;
$list . on ( 'click' , '.dropdown-item' , e => {
e . preventDefault ( ) ;
return false ;
} ) ;
$list . on ( 'focus' , '.dropdown-item' , e => {
$list . find ( '.dropdown-item' ) . each ( ( i , el ) => {
$ ( el ) . toggleClass ( 'active' , el === e . target ) ;
} ) ;
setContentPane ( ) ;
2019-10-11 02:00:06 +08:00
} ) ;