Added move document feature

pull/2/head
NGPixel 9 years ago
parent f0916dcfe6
commit 492bb9efa6

@ -23,8 +23,8 @@
- [x] Create Entry - [x] Create Entry
- [x] Edit Entry - [x] Edit Entry
- [x] Git Management - [x] Git Management
- [ ] History Management
- [ ] Markdown Editor - [ ] Markdown Editor
- [x] Move Entry
- [x] Navigation - [x] Navigation
- [x] Parsing / Tree / Metadata - [x] Parsing / Tree / Metadata
- [x] Search - [x] Search

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -0,0 +1,29 @@
//-> Create New Document
let suggestedCreatePath = currentBasePath + '/new-page';
$('.btn-create-prompt').on('click', (ev) => {
$('#txt-create-prompt').val(suggestedCreatePath);
$('#modal-create-prompt').toggleClass('is-active');
setInputSelection($('#txt-create-prompt').get(0), currentBasePath.length + 1, suggestedCreatePath.length);
$('#txt-create-prompt').removeClass('is-danger').next().addClass('is-hidden');
});
$('#txt-create-prompt').on('keypress', (ev) => {
if(ev.which === 13) {
$('.btn-create-go').trigger('click');
}
});
$('.btn-create-go').on('click', (ev) => {
let newDocPath = makeSafePath($('#txt-create-prompt').val());
if(_.isEmpty(newDocPath)) {
$('#txt-create-prompt').addClass('is-danger').next().removeClass('is-hidden');
} else {
$('#txt-create-prompt').parent().addClass('is-loading');
window.location.assign('/create/' + newDocPath);
}
});

@ -0,0 +1,49 @@
//-> Move Existing Document
if(currentBasePath !== '') {
$('.btn-move-prompt').removeClass('is-hidden');
}
let moveInitialDocument = _.lastIndexOf(currentBasePath, '/') + 1;
$('.btn-move-prompt').on('click', (ev) => {
$('#txt-move-prompt').val(currentBasePath);
$('#modal-move-prompt').toggleClass('is-active');
setInputSelection($('#txt-move-prompt').get(0), moveInitialDocument, currentBasePath.length);
$('#txt-move-prompt').removeClass('is-danger').next().addClass('is-hidden');
});
$('#txt-move-prompt').on('keypress', (ev) => {
if(ev.which === 13) {
$('.btn-move-go').trigger('click');
}
});
$('.btn-move-go').on('click', (ev) => {
let newDocPath = makeSafePath($('#txt-move-prompt').val());
if(_.isEmpty(newDocPath) || newDocPath === currentBasePath || newDocPath === 'home') {
$('#txt-move-prompt').addClass('is-danger').next().removeClass('is-hidden');
} else {
$('#txt-move-prompt').parent().addClass('is-loading');
$.ajax(window.location.href, {
data: {
move: newDocPath
},
dataType: 'json',
method: 'PUT'
}).then((rData, rStatus, rXHR) => {
if(rData.ok) {
window.location.assign('/' + newDocPath);
} else {
alerts.pushError('Something went wrong', rData.error);
}
}, (rXHR, rStatus, err) => {
alerts.pushError('Something went wrong', 'Save operation failed.');
});
}
});

@ -7,4 +7,9 @@ if($('#page-type-source').length) {
scEditor.setReadOnly(true); scEditor.setReadOnly(true);
scEditor.renderer.updateFull(); scEditor.renderer.updateFull();
let currentBasePath = ($('#page-type-source').data('entrypath') !== 'home') ? $('#page-type-source').data('entrypath') : '';
//=include ../modals/create.js
//=include ../modals/move.js
} }

@ -1,34 +1,9 @@
if($('#page-type-view').length) { if($('#page-type-view').length) {
let currentBasePath = ($('#page-type-view').data('entrypath') !== 'home') ? $('#page-type-view').data('entrypath') + '/' : ''; let currentBasePath = ($('#page-type-view').data('entrypath') !== 'home') ? $('#page-type-view').data('entrypath') : '';
let suggestedCreatePath = currentBasePath + 'new-page';
//-> Create New Document //=include ../modals/create.js
//=include ../modals/move.js
$('.btn-create-prompt').on('click', (ev) => {
$('#txt-create-prompt').val(suggestedCreatePath);
$('#modal-create-prompt').toggleClass('is-active');
setInputSelection($('#txt-create-prompt').get(0), currentBasePath.length, suggestedCreatePath.length);
$('#txt-create-prompt').removeClass('is-danger').next().addClass('is-hidden');
});
$('#txt-create-prompt').on('keypress', (ev) => {
if(ev.which === 13) {
$('.btn-create-go').trigger('click');
}
});
$('.btn-create-go').on('click', (ev) => {
let newDocPath = makeSafePath($('#txt-create-prompt').val());
if(_.isEmpty(newDocPath)) {
$('#txt-create-prompt').addClass('is-danger').next().removeClass('is-hidden');
} else {
$('#txt-create-prompt').parent().addClass('is-loading');
window.location.assign('/create/' + newDocPath);
}
});
} }

@ -127,6 +127,10 @@ p code {
background-color: $red; background-color: $red;
} }
&.is-info {
background-color: $purple;
}
} }
.card-header-title { .card-header-title {

@ -174,4 +174,33 @@ router.get('/*', (req, res, next) => {
}); });
/**
* Move document
*/
router.put('/*', (req, res, next) => {
let safePath = entries.parsePath(req.path);
if(_.isEmpty(req.body.move)) {
return res.json({
ok: false,
error: 'Invalid document action call.'
});
}
let safeNewPath = entries.parsePath(req.body.move);
entries.move(safePath, safeNewPath).then(() => {
res.json({
ok: true
});
}).catch((err) => {
res.json({
ok: false,
error: err.message
});
});
});
module.exports = router; module.exports = router;

@ -376,7 +376,24 @@ module.exports = {
}, },
/**
* Move a document
*
* @param {String} entryPath The current entry path
* @param {String} newEntryPath The new entry path
* @return {Promise} Promise of the operation
*/
move(entryPath, newEntryPath) {
let self = this;
return git.moveDocument(entryPath, newEntryPath).then(() => {
return git.commitDocument(newEntryPath).then(() => {
return self.updateCache(newEntryPath);
});
});
},
/** /**
* Generate a starter page content based on the entry path * Generate a starter page content based on the entry path

@ -200,6 +200,30 @@ module.exports = {
}); });
}); });
},
/**
* Move a document.
*
* @param {String} entryPath The current entry path
* @param {String} newEntryPath The new entry path
* @return {Promise<Boolean>} Resolve on success
*/
moveDocument(entryPath, newEntryPath) {
let self = this;
let gitFilePath = entryPath + '.md';
let gitNewFilePath = newEntryPath + '.md';
return self._git.exec('mv', [gitFilePath, gitNewFilePath]).then((cProc) => {
let out = cProc.stdout.toString();
if(_.includes(out, 'fatal')) {
let errorMsg = _.capitalize(_.head(_.split(_.replace(out, 'fatal: ', ''), ',')));
throw new Error(errorMsg);
}
return true;
})
} }
}; };

@ -19,19 +19,6 @@
.nav-right.nav-menu .nav-right.nav-menu
block rootNavRight block rootNavRight
i.nav-item#notifload i.nav-item#notifload
a.nav-item(href='/history/' + pageData.meta.path)
| History
a.nav-item(href='/source/' + pageData.meta.path)
| Source
span.nav-item
a.button(href='/edit/' + pageData.meta.path)
span.icon
i.fa.fa-edit
span Edit
a.button.is-primary.btn-create-prompt
span.icon
i.fa.fa-plus
span Create
.box.searchresults.animated(v-show='searchactive', transition='slide', v-cloak, style={'display':'none'}) .box.searchresults.animated(v-show='searchactive', transition='slide', v-cloak, style={'display':'none'})
.menu .menu

@ -0,0 +1,18 @@
.modal#modal-move-prompt
.modal-background
.modal-container
.modal-content
.card.is-fullwidth
header.card-header.is-info
p.card-header-title Move document
.card-content
.content
label.label Enter the new document path:
p.control
input.input(type='text', placeholder='page-name')#txt-move-prompt
span.help.is-danger.is-hidden This document path is invalid or not allowed!
span Note that moving or renaming documents can lead to broken links. Make sure to edit any page that links to this document afterwards!
footer.card-footer
a.card-footer-item.btn-move-prompt Discard
a.card-footer-item.btn-move-go Move

@ -5,10 +5,6 @@ block rootNavCenter
block rootNavRight block rootNavRight
i.nav-item#notifload i.nav-item#notifload
a.nav-item(href='/history/' + pageData.meta.path, target='_blank')
| History
a.nav-item(href='/source/' + pageData.meta.path, target='_blank')
| Source
span.nav-item span.nav-item
a.button.is-warning.btn-edit-discard a.button.is-warning.btn-edit-discard
span.icon span.icon
@ -25,3 +21,4 @@ block content
textarea#mk-editor= pageData.markdown textarea#mk-editor= pageData.markdown
include ../modals/edit.pug include ../modals/edit.pug
include ../modals/move.pug

@ -1,9 +1,29 @@
extends ../layout.pug extends ../layout.pug
block rootNavCenter
h2.nav-item= pageData.meta.title
block rootNavRight
i.nav-item#notifload
a.nav-item.btn-move-prompt.is-hidden
| Move
a.nav-item(href='/' + pageData.meta.path)
| Normal View
span.nav-item
a.button(href='/edit/' + pageData.meta.path)
span.icon
i.fa.fa-edit
span Edit
a.button.is-primary.btn-create-prompt
span.icon
i.fa.fa-plus
span Create
block content block content
#page-type-source(data-entrypath=pageData.meta.path) #page-type-source(data-entrypath=pageData.meta.path)
.ace-container .ace-container
#source-display= pageData.markdown #source-display= pageData.markdown
include ../modals/create include ../modals/create.pug
include ../modals/move.pug

@ -10,8 +10,8 @@ mixin tocMenu(ti)
block rootNavRight block rootNavRight
i.nav-item#notifload i.nav-item#notifload
a.nav-item(href='/history/' + pageData.meta.path) a.nav-item.btn-move-prompt.is-hidden
| History | Move
a.nav-item(href='/source/' + pageData.meta.path) a.nav-item(href='/source/' + pageData.meta.path)
| Source | Source
span.nav-item span.nav-item
@ -62,3 +62,4 @@ block content
!= pageData.html != pageData.html
include ../modals/create.pug include ../modals/create.pug
include ../modals/move.pug

Loading…
Cancel
Save