Added move document feature
This commit is contained in:
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
29
client/js/modals/create.js
Normal file
29
client/js/modals/create.js
Normal file
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
49
client/js/modals/move.js
Normal file
49
client/js/modals/move.js
Normal file
@ -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
|
||||||
|
18
views/modals/move.pug
Normal file
18
views/modals/move.pug
Normal file
@ -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
|
||||||
@ -24,4 +20,5 @@ block content
|
|||||||
#page-type-edit(data-entrypath=pageData.meta.path)
|
#page-type-edit(data-entrypath=pageData.meta.path)
|
||||||
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…
Reference in New Issue
Block a user