From 3a78cca9161b186641ae8428cc84e622a8092d1e Mon Sep 17 00:00:00 2001 From: life Date: Fri, 13 Mar 2015 11:00:40 +0800 Subject: [PATCH] =?UTF-8?q?send=20notebook=20changes,=20=E5=85=88=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E7=88=B6,=20=E5=86=8D=E6=B7=BB=E5=8A=A0=E5=AD=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- node_modules/api.js | 2 +- node_modules/db.js | 2 +- node_modules/notebook.js | 100 +++++++++++++++++++++++++++------------ node_modules/sync.js | 24 ++++++---- public/js/i18n/msg.en.js | 2 +- test.js | 46 +++++++++++++++--- 6 files changed, 129 insertions(+), 47 deletions(-) diff --git a/node_modules/api.js b/node_modules/api.js index 1e332ac4..e65a7c25 100644 --- a/node_modules/api.js +++ b/node_modules/api.js @@ -502,7 +502,7 @@ var Api = { Content: note.Content, IsMarkdown: note.IsMarkdown, Tags: note.Tags, - IsBlog: note.IsBlog, + IsBlog: false, // TODO 这里永远设为非blog note.IsBlog, Files: note.Files, FileDatas: note.FileDatas, } diff --git a/node_modules/db.js b/node_modules/db.js index aee71c1e..fb7f3152 100644 --- a/node_modules/db.js +++ b/node_modules/db.js @@ -10,7 +10,7 @@ console.error(dbPath); // test if(dbPath.length < 6) { - // var dbPath = '/Users/life/Library/Application Support/Leanote' + '/nedb'; + var dbPath = '/Users/life/Library/Application Support/Leanote' + '/nedb'; } // console.log(dbPath); diff --git a/node_modules/notebook.js b/node_modules/notebook.js index ce4316c7..aca1f493 100644 --- a/node_modules/notebook.js +++ b/node_modules/notebook.js @@ -65,40 +65,48 @@ var Notebook = { }); }, + // 建立关联 + _mapNotebooks: function(notebooks) { + var me = this; + // log(notebooks); + // 整理成层级关系, 并排序 + // 1. 建立map + var notebooksMap = {}; + for(var i in notebooks) { + var notebook = notebooks[i]; + notebook.Subs = []; + notebooksMap[notebook.NotebookId] = notebook; + } + // 2. 追加到父下 + var isolatedNotebooks = []; // 独立的, 没有父的, 第一级 + for(var notebookId in notebooksMap) { + var notebook = notebooksMap[notebookId]; + var parentNotebookId = notebook.ParentNotebookId; + if(parentNotebookId && notebooksMap[parentNotebookId]) { + notebooksMap[parentNotebookId].Subs.push(notebook); + } else { + isolatedNotebooks.push(notebook); + } + } + // 3. 排序 + sortNotebooks(isolatedNotebooks); + // log(notebooks); + // log(notebooksMap['1'].Subs); + return isolatedNotebooks; + }, + // 得到用户下所有的notebook // 排序好之后返回 - getNotebooks: function(callback) { + getNotebooks: function(callback) { + var me = this; var userId = User.getCurActiveUserId(); NB.find({UserId: userId, $or: [{LocalIsDelete : { $exists : false }}, {LocalIsDelete: false}] }, function(err, notebooks) { if(err) { log(err); return callback && callback(false); } - // log(notebooks); - // 整理成层级关系, 并排序 - // 1. 建立map - var notebooksMap = {}; - for(var i in notebooks) { - var notebook = notebooks[i]; - notebook.Subs = []; - notebooksMap[notebook.NotebookId] = notebook; - } - // 2. 追加到父下 - var isolatedNotebooks = []; // 独立的, 没有父的, 第一级 - for(var notebookId in notebooksMap) { - var notebook = notebooksMap[notebookId]; - var parentNotebookId = notebook.ParentNotebookId; - if(parentNotebookId && notebooksMap[parentNotebookId]) { - notebooksMap[parentNotebookId].Subs.push(notebook); - } else { - isolatedNotebooks.push(notebook); - } - } - // 3. 排序 - sortNotebooks(isolatedNotebooks); - // log(notebooks); - // log(notebooksMap['1'].Subs); - callback && callback(isolatedNotebooks); + + callback && callback(me._mapNotebooks(notebooks)); }); }, @@ -127,7 +135,10 @@ var Notebook = { }, updateNotebookTitle: function(notebookId, title, callback) { - NB.update({NotebookId: notebookId}, {$set: {Title: title, IsDirty: true, UpdatedTime: new Date()}}, function(err, n) { + NB.update({NotebookId: notebookId}, + {$set: + {Title: title, IsDirty: true, UpdatedTime: new Date()} + }, function(err, n) { callback(true); }); }, @@ -153,7 +164,11 @@ var Notebook = { for(var i = 0; i < siblingNotebookIds.length; ++i) { var siblingNotebookId = siblingNotebookIds[i]; console.log('siblingNotebookId: ' + siblingNotebookId); - NB.update({NotebookId: siblingNotebookId}, {$set: {ParentNotebookId: parentNotebookId, Seq: i, IsDirty: true, UpdatedTime: new Date()}}); + NB.update({NotebookId: siblingNotebookId}, + {$set: + {ParentNotebookId: parentNotebookId, Seq: i, IsDirty: true, UpdatedTime: new Date()} + } + ); } }); }, @@ -346,14 +361,41 @@ var Notebook = { }); }, + // 深度优先一个列表 + // 为了send changes时避免先send child + _deepTraversal: [], + _visited: {}, // 可以不要 + deep: function(T) { + var me = this; + if(!T || !T.Subs || T.Subs.length == 0) { + return; + } + for(var i = 0; i < T.Subs.length; ++i) { + var node = T.Subs[i]; + if(!me._visited[node.NotebookId]) { // 可以不要这个判断 + me._visited[node.NotebookId] = true; + me._deepTraversal.push(T.Subs[i]); + // 递归 + me.deep(T.Subs[i]); + } + } + }, + // 获得用户修改的笔记本 getDirtyNotebooks: function(callback) { + var me = this; NB.find({UserId: User.getCurActiveUserId(), IsDirty: true}, function(err, notebooks) { if(err) { log(err); return callback && callback(false); } else { - callback(notebooks); + var mapNotebooks = me._mapNotebooks(notebooks); + // 深度优先一个序列 + me._deepTraversal = []; + me._visited = {}; + me.deep({Subs: mapNotebooks}); + // 返回之 + callback(me._deepTraversal); } }); }, diff --git a/node_modules/sync.js b/node_modules/sync.js index 603b960f..554cac84 100644 --- a/node_modules/sync.js +++ b/node_modules/sync.js @@ -670,22 +670,28 @@ var Sync = { // 可能服务器上已删除, 此时应该要作为添加而不是更新 me._syncInfo.notebook.changeNeedAdds.push(notebook); } + + // me.checkNeedIncSyncAgain(newNotebook.Usn); + return cb(); } else { // 更新 // TODO 后端updateNotebook只要传Usn回来即可 - Notebook.updateNotebookForceForSendChange(notebook.NotebookId, newNotebook); - - if(notebook.LocalIsNew) { + Notebook.updateNotebookForceForSendChange(notebook.NotebookId, newNotebook, function() { + if(notebook.LocalIsNew) { // 没用 me._syncInfo.notebook.changeAdds.push(newNotebook); - } else { - // 没用 - me._syncInfo.notebook.updates.push(newNotebook); - } + } else { + // 没用 + me._syncInfo.notebook.updates.push(newNotebook); + } + + // 这里才cb(), 因为先添加父, 再添加子 + me.checkNeedIncSyncAgain(newNotebook.Usn); + cb(); + }); } - me.checkNeedIncSyncAgain(newNotebook.Usn); - cb(); + }); }, function() { callback && callback(); diff --git a/public/js/i18n/msg.en.js b/public/js/i18n/msg.en.js index 9b23b3fb..93dce17d 100644 --- a/public/js/i18n/msg.en.js +++ b/public/js/i18n/msg.en.js @@ -1,4 +1,4 @@ -var MSG = {"3th":"Third-party accounts","aboutLeanote":"About leanote","aboutMe":"About me","accountSetting":"Account","addChildNotebook":"Add child notebook","addNotebook":"Add notebook","addShare":"Add Friend","all":"Newest","app":"leanote","attachments ":" Attachments","basicInfo":"Basic","blog":"Blog","blogInfo":"You can public your knowledge and leanote is your blog!","blogSet":"Set blog","blue":"blue","cancel":"Cancel","cancelPublic":"Cancel public","canntNewNoteTips":"Sorry, cannot new note in here, please choose a notebook at first.","checkEmai":"Check email","checkEmail":"Check email","clearSearch":"Clear Search","clickAddTag":"Click to add Tag","clickToChangePermission":"Click to change permission","clickToCopy":"Click to copy","close":"Close","confirmBackup":"Are you sure to restore from this version? We will backup the current note.","confirmPassword":"Password not matched","cooperation":"Cooperation","cooperationInfo":"Collaborate with friends to improve your knowledge.","copy":"Copy","copyFailed":"Copy failed","copySuccess":"Copy success","copyToMyNotebook":"Copy to my notebook","create":"Create","createAccount":"Create account","createAccountFailed":"Account create failed","createAccountSuccess":"Account create success","curUser":"Email","currentEmail":"Your current email is: \u003ccode\u003e%s\u003c/code\u003e ","datetime":"Datetime","default":"Default","defaultShare":"Default sharing","defaulthhare":"Default","delete":"Delete","deleteAllShared":"Delete shared user","deleteSharedNotebook":"Delete shared notebook","demoRegister":"\u003ca href=\"/register\"\u003eSign up\u003c/a\u003e","discussion":"Discussion","donate ":" Donate","download":"Download","editorTips":"Tips","editorTipsInfo":"\u003ch4\u003e1. Short cuts\u003c/h4\u003ectrl+shift+c Toggle code \u003cbr /\u003e ctrl+shift+i Insert/edit image \u003ch4\u003e2. shift+enter Get out of current block\u003c/h4\u003e eg. \u003cimg src=\"/images/outofcode.png\" style=\"width: 90px\"/\u003e in this situation you can use shift+enter to get out of current code block.","email":"Email","emailBodyRequired":"Email body is required","emailInSending":"In sending to ","emailOrOthers":"Email or other contact way","emailSendFailed":"Email send failed","errorEmail":"Please input the right email","errorPassword":"The passowd's length is at least 6 and be sure as complex as possible","findPassword":"Find password","findPasswordSendEmailOver":"We have already send the find password link to your email, please check out your email","findPasswordTimeout":"time out","fold":"Fold","forgetPassword ":" Forget password?","fork github":"Fork leanote on Github","friendEmail":"Friend email","friendNotExits":"Your friend hasn't %s's account, invite register link: %s","green":"green","hadAcount ":" Already have an account?","hasAcount ":" Do not have an account?","hi":"Hi","historiesNum":"We have saved at most \u003cb\u003e10\u003c/b\u003e latest histories with each note","history":"Histories","home":"Home","howToInstallLeanote":"How to install leanote","ing":"processing","inputEmail":"Email is required","inputFriendEmail":"Friend email is required","inputNewPassword":"The new password is required","inputPassword":"Password is required","inputPassword2":"Please input the new password again","inputUsername":"input username","inviteEmailBody":"Hi,I am %s, %s is awesome, come on!","knowledge":"Knowledge","knowledgeInfo":"Use leanote as a note, manage your knowledge in leanote.","leanoteBlog":"Blog","leftHidden":"Hidden slide bar","leftShow":"Show slide bar","login":"Sign in","loginSuccess":"login success","logining":"Sign in","logout":"Logout","minLength":"The length is at least %s","moto":"your own cloud note!","moto2":"Knowledge, Sharing, Cooperation, Blog... all in leanote","moto3":"Brief But Not Simple","move":"Move","myBlog":"Blog","myNote":"My note","myNotebook":"My notebook","myTag":"My tag","nav":"Note nav","new":"New","newMarkdown":"New markdown note","newMarkdownNote":"New Markdown Note","newNote":"New note","newPassword":"New password","noHistories":"No histories","noNoteNewNoteTips":"The notebook is empty, why not...","noSpecialChars":"username cannot contains special chars","normalMode":"Normal Mode","notFound":"This page cann't found.","notGoodPassword":"Tt's not a good password, the length is at least 6","notebook":"Notebook","oldPassword":"Old password","or":"or","password":"Password","password2":"Confirm your password","passwordTips":"The length is at least 6","permission":"Permission","publicAsBlog":"Public as blog","reFindPassword":"find password again","readOnly":"Read only","red":"red","register":"Sign up","registerSuccessAndRdirectToNote":"Register success, redirecting...","rename":"Rename","resendVerifiedEmail":"Resend verification email","restoreFromThisVersion":"Restore from this version","save":"Save","saveSuccess":"Save success","saving":"Saving","search":"Search","send":"Send","sendInviteEmailToYourFriend":"Send invite email to your friend","sendSuccess":"success","sendVerifiedEmail":"Send verification email","setAvatar":"Avatar","setUsername":"Set username","setUsernameTips":"Your current email is: \u003ccode\u003e%s\u003c/code\u003e. You can set a unique username. \u003cbr /\u003eUsername' length is at least 4 and cannot contains special characters.","share":"Share","shareInfo":"Share your knowledge to your friends in leanote.","shareToFriends":"Share to friends","simple":"Simple","submit":"submit","suggestions":"Suggestions","suggestionsInfo":"help us to improve our service.","tag":"Tag","themeSetting":"Theme","thirdCreateAcountTips":"You are using the 3th account to login %(app)s, you can create a %(app)s account too. \u003cbr /\u003eAfter you create %(app)s account, you can use the account and the 3th account to login %(app)s.","trash":"Trash","try":"Try it","unTitled":"UnTitled","unVerified":"Unverfied","unfold":"Unfold","update":"Update","updateEmail":"Update email","updateEmailTips":"You must verify the email after you update the email. The verified email will be your new account.","updatePassword":"Update password","updatePasswordSuccess":"Update password success","updatePasswordSuccessRedirectToLogin":"update password success and redirect to login page...","updateUsernameSuccess":"Update username success","uploadImage":"Upload image","use ":" Use","usernameIsExisted":"Username is already exists","usernameOrEmail":"Username or email","usernameSetting":"Update username","verified":"Verified","verifiedEmaiHasSent":"The verification email has been sent, please check your email.","verifiedNow":"Verify now","welcomeUseLeanote":"Welcome!","writable":"Writable","writingMode":"Writing Mode","wrongEmail":"Wrong email","wrongPassword":"Wrong password","wrongUsernameOrPassword":"Wrong username or password","yellow":"yellow","yourContact":"Your contact","yourSuggestions":"Suggestions"}; +var MSG = {"3th":"Third-party accounts","aboutLeanote":"About leanote","aboutMe":"About me","accountSetting":"Account","addChildNotebook":"Add child notebook","addNotebook":"Add notebook","addShare":"Add Friend","all":"Newest","app":"leanote","attachments ":" Attachments","basicInfo":"Basic","blog":"Blog","blogInfo":"You can public your knowledge and leanote is your blog!","blogSet":"Set blog","blue":"blue","cancel":"Cancel","cancelPublic":"Cancel public","canntNewNoteTips":"Sorry, cannot new note in here, please choose a notebook at first.","checkEmai":"Check email","checkEmail":"Check email","clearSearch":"Clear Search","clickAddTag":"Click to add Tag","clickToChangePermission":"Click to change permission","clickToCopy":"Click to copy","close":"Close","confirmBackup":"Are you sure to restore from this version? We will backup the current note.","confirmPassword":"Password not matched","cooperation":"Cooperation","cooperationInfo":"Collaborate with friends to improve your knowledge.","copy":"Copy to","copyFailed":"Copy failed","copySuccess":"Copy success","copyToMyNotebook":"Copy to my notebook","create":"Create","createAccount":"Create account","createAccountFailed":"Account create failed","createAccountSuccess":"Account create success","curUser":"Email","currentEmail":"Your current email is: \u003ccode\u003e%s\u003c/code\u003e ","datetime":"Datetime","default":"Default","defaultShare":"Default sharing","defaulthhare":"Default","delete":"Delete","deleteAllShared":"Delete shared user","deleteSharedNotebook":"Delete shared notebook","demoRegister":"\u003ca href=\"/register\"\u003eSign up\u003c/a\u003e","discussion":"Discussion","donate ":" Donate","download":"Download","editorTips":"Tips","editorTipsInfo":"\u003ch4\u003e1. Short cuts\u003c/h4\u003ectrl+shift+c Toggle code \u003cbr /\u003e ctrl+shift+i Insert/edit image \u003ch4\u003e2. shift+enter Get out of current block\u003c/h4\u003e eg. \u003cimg src=\"/images/outofcode.png\" style=\"width: 90px\"/\u003e in this situation you can use shift+enter to get out of current code block.","email":"Email","emailBodyRequired":"Email body is required","emailInSending":"In sending to ","emailOrOthers":"Email or other contact way","emailSendFailed":"Email send failed","errorEmail":"Please input the right email","errorPassword":"The passowd's length is at least 6 and be sure as complex as possible","findPassword":"Find password","findPasswordSendEmailOver":"We have already send the find password link to your email, please check out your email","findPasswordTimeout":"time out","fold":"Fold","forgetPassword ":" Forget password?","fork github":"Fork leanote on Github","friendEmail":"Friend email","friendNotExits":"Your friend hasn't %s's account, invite register link: %s","green":"green","hadAcount ":" Already have an account?","hasAcount ":" Do not have an account?","hi":"Hi","historiesNum":"We have saved at most \u003cb\u003e10\u003c/b\u003e latest histories with each note","history":"Histories","home":"Home","howToInstallLeanote":"How to install leanote","ing":"processing","inputEmail":"Email is required","inputFriendEmail":"Friend email is required","inputNewPassword":"The new password is required","inputPassword":"Password is required","inputPassword2":"Please input the new password again","inputUsername":"input username","inviteEmailBody":"Hi,I am %s, %s is awesome, come on!","knowledge":"Knowledge","knowledgeInfo":"Use leanote as a note, manage your knowledge in leanote.","leanoteBlog":"Blog","leftHidden":"Hidden slide bar","leftShow":"Show slide bar","login":"Sign in","loginSuccess":"login success","logining":"Sign in","logout":"Logout","minLength":"The length is at least %s","moto":"your own cloud note!","moto2":"Knowledge, Sharing, Cooperation, Blog... all in leanote","moto3":"Brief But Not Simple","move":"Move to","myBlog":"Blog","myNote":"My note","myNotebook":"My notebook","myTag":"My tag","nav":"Note nav","new":"New","newMarkdown":"New markdown note","newMarkdownNote":"New Markdown Note","newNote":"New note","newPassword":"New password","noHistories":"No histories","noNoteNewNoteTips":"The notebook is empty, why not...","noSpecialChars":"username cannot contains special chars","normalMode":"Normal Mode","notFound":"This page cann't found.","notGoodPassword":"Tt's not a good password, the length is at least 6","notebook":"Notebook","oldPassword":"Old password","or":"or","password":"Password","password2":"Confirm your password","passwordTips":"The length is at least 6","permission":"Permission","publicAsBlog":"Public as blog","reFindPassword":"find password again","readOnly":"Read only","red":"red","register":"Sign up","registerSuccessAndRdirectToNote":"Register success, redirecting...","rename":"Rename","resendVerifiedEmail":"Resend verification email","restoreFromThisVersion":"Restore from this version","save":"Save","saveSuccess":"Save success","saving":"Saving","search":"Search","send":"Send","sendInviteEmailToYourFriend":"Send invite email to your friend","sendSuccess":"success","sendVerifiedEmail":"Send verification email","setAvatar":"Avatar","setUsername":"Set username","setUsernameTips":"Your current email is: \u003ccode\u003e%s\u003c/code\u003e. You can set a unique username. \u003cbr /\u003eUsername' length is at least 4 and cannot contains special characters.","share":"Share","shareInfo":"Share your knowledge to your friends in leanote.","shareToFriends":"Share to friends","simple":"Simple","submit":"submit","suggestions":"Suggestions","suggestionsInfo":"help us to improve our service.","tag":"Tag","themeSetting":"Theme","thirdCreateAcountTips":"You are using the 3th account to login %(app)s, you can create a %(app)s account too. \u003cbr /\u003eAfter you create %(app)s account, you can use the account and the 3th account to login %(app)s.","trash":"Trash","try":"Try it","unTitled":"UnTitled","unVerified":"Unverfied","unfold":"Unfold","update":"Update","updateEmail":"Update email","updateEmailTips":"You must verify the email after you update the email. The verified email will be your new account.","updatePassword":"Update password","updatePasswordSuccess":"Update password success","updatePasswordSuccessRedirectToLogin":"update password success and redirect to login page...","updateUsernameSuccess":"Update username success","uploadImage":"Upload image","use ":" Use","usernameIsExisted":"Username is already exists","usernameOrEmail":"Username or email","usernameSetting":"Update username","verified":"Verified","verifiedEmaiHasSent":"The verification email has been sent, please check your email.","verifiedNow":"Verify now","welcomeUseLeanote":"Welcome!","writable":"Writable","writingMode":"Writing Mode","wrongEmail":"Wrong email","wrongPassword":"Wrong password","wrongUsernameOrPassword":"Wrong username or password","yellow":"yellow","yourContact":"Your contact","yourSuggestions":"Suggestions"}; function getMsg(key, data) { var msg = MSG[key] if(msg) { diff --git a/test.js b/test.js index 1577fb1b..b3c51e16 100755 --- a/test.js +++ b/test.js @@ -21,14 +21,14 @@ Api.addNotebook({ // Api.uploadImage(); User.userId = '54bdc65599c37b0da9000002'; User.userId = '54d7620d99c37b030600002c'; -User.userId = '54f6e72899c37b6e20000044'; +User.userId = '545b26ad38f4116d08000029'; // 54d7624205fcd105da00005 // var reg = new RegExp(Evt.localUrl + '/api/file/getImage', 'g'); // content = content.replace(reg, Evt.leanoteUrl + '/api/file/getImage'); -Api.auth('leanote@leanote.com', 'myleanotelife121'); +// Api.auth('leanote@leanote.com', 'myleanotelife121'); User.init(function() { @@ -37,15 +37,19 @@ User.init(function() { console.log(note); }); */ + + Notebook.getDirtyNotebooks(function(notebooks) { + console.log(notebooks); + }) // Note.getNoteByServerNoteId('54f1a1f899c37b4faf000001', function(note) { // console.log(note); // }); - Note.getNotes('', function(ret) { - console.log(ret); - }); + // Note.getNotes('', function(ret) { + // console.log(ret); + // }); }); @@ -115,4 +119,34 @@ while(s = reg.exec(a)) { } */ -console.log(Common.goNowToDate('2014-01-06T18:29:48.802+08:00')); \ No newline at end of file +// console.log(Common.goNowToDate('2014-01-06T18:29:48.802+08:00')); + +var A = { + _deepTraversal: [], + _visited: {}, + deep: function(T) { + var me = this; + if(!T || !T.Subs || T.Subs.length == 0) { + return; + } + for(var i = 0; i < T.Subs.length; ++i) { + var node = T.Subs[i]; + if(!me._visited[node.NotebookId]) { + me._visited[node.NotebookId] = true; + me._deepTraversal.push(T.Subs[i]); + me.deep(T.Subs[i]); + } + } + }, + + init: function() { + var nodes = [ + {NotebookId: 1, Subs: [{NotebookId: 2, Subs: [{NotebookId: 9}]}, {NotebookId: 3, Subs: [{NotebookId: 4}, {NotebookId: 5}]}]}, + {NotebookId: 6}, + {NotebookId: 7} + ] + this.deep({Subs: nodes}); + console.log(this._deepTraversal); + } +}; +// A.init(); \ No newline at end of file