diff --git a/ajax/sessionController.php b/ajax/sessionController.php index 008f1a97..df2ba10d 100644 --- a/ajax/sessionController.php +++ b/ajax/sessionController.php @@ -22,6 +22,24 @@ class SessionController extends Controller{ self::join($uid, $file); } + public static function renameDocument($args){ + $fileId = intval(@$args['file_id']); + $name = @$_POST['name']; + $file = new File($fileId); + $l = new \OC_L10n('documents'); + + if (isset($name) && $file->getPermissions() & \OCP\PERMISSION_UPDATE) { + if ($file->renameTo($name)) { + // TODO: propagate to other clients + \OCP\JSON::success(); + return; + } + } + \OCP\JSON::error(array( + 'message' => $l->t('You don\'t have permission to rename this document') + )); + } + public static function joinAsUser($args){ $uid = self::preDispatch(); $fileId = intval(@$args['file_id']); diff --git a/appinfo/routes.php b/appinfo/routes.php index 6ea9b07f..8c4c2d53 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -73,6 +73,10 @@ $this->create('documents_session_joinasguest', 'ajax/session/joinasguest/{token} ->post() ->action('\OCA\Documents\SessionController', 'joinAsGuest') ; +$this->create('documents_session_renamedocument', 'ajax/session/renamedocument/{file_id}') + ->post() + ->action('\OCA\Documents\SessionController', 'renameDocument') +; $this->create('documents_session_save', 'ajax/session/save') ->post() diff --git a/css/style.css b/css/style.css index 5146f731..0be8fcd6 100755 --- a/css/style.css +++ b/css/style.css @@ -124,6 +124,13 @@ position: relative; /*margin-left:-50%;*/ } +#document-title>input { + height:9px; + margin: 0; + padding-top:4px; + width: 300px; +} + #odf-close{ float: right; } @@ -280,4 +287,9 @@ margin-top:-1px; .dojoTabular {border-collapse: collapse; border-spacing: 0; border: 1px solid #ccc; margin: 0 1.5em;} .dojoTabular th {text-align: center; font-weight: bold;} .dojoTabular thead,.dojoTabular tfoot {background-color: #efefef; border: 1px solid #ccc; border-width: 1px 0;} -.dojoTabular th,.dojoTabular td {padding: 0.25em 0.5em;} \ No newline at end of file +.dojoTabular th,.dojoTabular td {padding: 0.25em 0.5em;} + +/* raise notification z-index above the documents app */ +#odf-toolbar + #notification-container { + z-index: 501; +} diff --git a/js/documents.js b/js/documents.js index decb3ff4..f14e58f3 100644 --- a/js/documents.js +++ b/js/documents.js @@ -9,6 +9,7 @@ var documentsMain = { memberId : false, esId : false, ready :false, + fileName: null, UI : { /* Overlay HTML */ @@ -186,8 +187,10 @@ var documentsMain = { // fade out file list and show WebODF canvas $('#content').fadeOut('fast').promise().done(function() { + documentsMain.fileId = response.file_id; + documentsMain.fileName = documentsMain.getNameByFileid(response.file_id); documentsMain.UI.showEditor( - documentsMain.getNameByFileid(response.file_id), + documentsMain.fileName, response.permissions & OC.PERMISSION_SHARE && !documentsMain.isGuest ); var serverFactory = new ServerFactory(); @@ -281,7 +284,100 @@ var documentsMain = { }); $.post(OC.Router.generate('documents_user_invite'), {users: users}); }, - + + renameDocument: function(name) { + var url = OC.Router.generate('documents_session_renamedocument') + '/' + documentsMain.fileId; + $.post( + url, + { name : name }, + function(result) { + if (result && result.status === 'error') { + if (result.message){ + OC.Notification.show(result.message); + setTimeout(function() { + OC.Notification.hide(); + }, 10000); + } + return; + } + documentsMain.fileName = name; + $('title').text(documentsMain.UI.mainTitle + '| ' + name); + $('#document-title>div').text(name); + } + ); + }, + + // FIXME: copy/pasted from Files.isFileNameValid, needs refactor into core + isFileNameValid:function (name) { + if (name === '.') { + throw t('files', '\'.\' is an invalid file name.'); + } else if (name.length === 0) { + throw t('files', 'File name cannot be empty.'); + } + + // check for invalid characters + var invalid_characters = ['\\', '/', '<', '>', ':', '"', '|', '?', '*']; + for (var i = 0; i < invalid_characters.length; i++) { + if (name.indexOf(invalid_characters[i]) !== -1) { + throw t('files', "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed."); + } + } + return true; + }, + + onRenamePrompt: function() { + var name = documentsMain.fileName; + var lastPos = name.lastIndexOf('.'); + var extension = name.substr(lastPos + 1); + name = name.substr(0, lastPos); + var input = $('').val(name); + $('#document-title').append(input); + $('#document-title>div').hide(); + + input.on('blur', function(){ + var newName = input.val(); + if (!newName || newName === name) { + input.tipsy('hide'); + input.remove(); + $('#document-title>div').show(); + return; + } + else { + newName = newName + '.' + extension; + try { + input.tipsy('hide'); + input.removeClass('error'); + if (documentsMain.isFileNameValid(newName)) { + input.tipsy('hide'); + input.remove(); + $('#document-title>div').show(); + documentsMain.renameDocument(newName); + } + } + catch (error) { + input.attr('title', error); + input.tipsy({gravity: 'n', trigger: 'manual'}); + input.tipsy('show'); + input.addClass('error'); + } + } + }); + input.on('keyup', function(event){ + if (event.keyCode === 27) { + // cancel by putting in an empty value + $(this).val(''); + $(this).blur(); + event.preventDefault(); + } + if (event.keyCode === 13) { + $(this).blur(); + event.preventDefault(); + } + }); + input.focus(); + input.selectRange(0, name.length); + }, + onClose: function() { "use strict"; @@ -433,6 +529,7 @@ $(document).ready(function() { } }); + $(document.body).on('click', '#document-title>div', documentsMain.onRenamePrompt); $(document.body).on('click', '#odf-close', documentsMain.onClose); $(document.body).on('click', '#odf-invite', documentsMain.onInvite); $(document.body).on('click', '#odf-join', function(event){ diff --git a/lib/file.php b/lib/file.php index 84125bda..af6fc287 100644 --- a/lib/file.php +++ b/lib/file.php @@ -151,6 +151,17 @@ class File { return $permissions; } + /** + * Rename this file to the given name + * @param string $newName name to give (without path) + * @return boolean true if rename succeeded, false otherwise + */ + public function renameTo($newName) { + list($owner, $path) = $this->getOwnerViewAndPath(); + $newPath = dirname($path) . '/' . $newName; + return \OC\Files\Filesystem::rename($path, $newPath); + } + /** * * @return string owner of the current file item