浏览代码

:sparkles: 数据仓库支持云端备份 https://github.com/siyuan-note/siyuan/issues/5336

Liang Ding 3 年之前
父节点
当前提交
44c0372a19

+ 4 - 2
app/appearance/langs/en_US.json

@@ -1,6 +1,8 @@
 {
-  "snapshotName": "Snapshot Name",
-  "snapshotNameTip": "Do not include symbols \\ / : * ? " ' < > |",
+  "snapshotMemo": "Snapshot Memo",
+  "snapshotMemoTip": "Please enter the snapshot memo",
+  "tagSnapshot": "Tag Snapshot",
+  "tagSnapshotTip": "Do not include symbols \\ / : * ? " ' < > |",
   "syncDataRepo": "⚗️ Use data repo sync mechanism",
   "syncDataRepoTip": "The data repo sync mechanism can better handle data conflicts, and the sync performance is also better",
   "dataRepo": "Data repo",

+ 5 - 3
app/appearance/langs/es_ES.json

@@ -1,6 +1,8 @@
 {
-  "snapshotName": "Nombre de la instantánea",
-  "snapshotNameTip": "No incluir símbolos \\ / : * ? " ' < > |",
+  "snapshotMemo": "Memo de Instantánea",
+  "snapshotMemoTip": "Ingrese la nota instantánea",
+  "tagSnapshot": "Instantánea de la etiqueta",
+  "tagSnapshotTip": "No incluir símbolos \\ / : * ? " ' < > |",
   "syncDataRepo": "⚗️ Usar mecanismo de sincronización de repositorio de datos",
   "syncDataRepoTip": "El mecanismo de sincronización del repositorio de datos puede manejar mejor los conflictos de datos y el rendimiento de la sincronización también es mejor",
   "dataRepo": "Repositorio de datos",
@@ -906,7 +908,7 @@
     "139": "Se está generando la instantánea de datos, se han procesado [%s] archivos de datos, quedan [%s]...",
     "140": "Fallo en la creación de la instantánea de datos: %s",
     "141": "Fallo en la reversión de la instantánea de datos",
-    "142": "El memo de la instantánea no puede estar vacío",
+    "142": "La entrada no puede estar vacía",
     "143": "Creando instantánea de datos...",
     "144": "Restableciendo repositorio de datos...",
     "145": "Restablecimiento del repositorio de datos completado",

+ 5 - 3
app/appearance/langs/fr_FR.json

@@ -1,6 +1,8 @@
 {
-  "snapshotName": "Nom de l'instantané",
-  "snapshotNameTip": "Ne pas inclure les symboles \\ / : * ? " ' < > |",
+  "snapshotMemo": "Mémo d'instantané",
+  "snapshotMemoTip": "Veuillez entrer le mémo instantané",
+  "tagSnapshot": "Instantané de balise",
+  "tagSnapshotTip": "Ne pas inclure les symboles \\ / : * ? " ' < > |",
   "syncDataRepo": "⚗️ Utiliser le mécanisme de synchronisation du référentiel de données",
   "syncDataRepoTip": "Le mécanisme de synchronisation du référentiel de données peut mieux gérer les conflits de données, et les performances de synchronisation sont également meilleures",
   "dataRepo": "Dépôt de données",
@@ -906,7 +908,7 @@
     "139": "L'instantané des données est en cours de génération, [%s] fichiers de données ont été traités, [%s] restants...",
     "140": "Échec de la création de l'instantané des données: %s",
     "141": "Échec de la restauration de l'instantané des données",
-    "142": "Le mémo d'instantané ne peut pas être vide",
+    "142": "L'entrée ne peut pas être vide",
     "143": "Création d'un instantané de données...",
     "144": "Réinitialisation du référentiel de données...",
     "145": "Réinitialisation du référentiel de données terminée",

+ 5 - 3
app/appearance/langs/zh_CHT.json

@@ -1,6 +1,8 @@
 {
-  "snapshotName": "快照名稱",
-  "snapshotNameTip": "請勿包含符號 \\ / : * ? " ' < > |",
+  "snapshotMemo": "快照備註",
+  "snapshotMemoTip": "請輸入快照備註",
+  "tagSnapshot": "標記快照",
+  "tagSnapshotTip": "請勿包含符號 \\ / : * ? " ' < > |",
   "syncDataRepo": "⚗️ 使用數據倉庫同步機制",
   "syncDataRepoTip": "數據倉庫同步機制能夠更好地處理數據衝突,同步性能也更好",
   "dataRepo": "數據倉庫",
@@ -905,7 +907,7 @@
     "139": "正在生成數據快照,已處理 [%s] 個數據文件,剩餘待處理 [%s]...",
     "140": "創建數據快照失敗:%s",
     "141": "回滾數據快照失敗",
-    "142": "快照備註不能為空",
+    "142": "輸入不能為空",
     "143": "正在創建數據快照...",
     "144": "正在重置數據倉庫...",
     "145": "數據倉庫重置完畢",

+ 5 - 3
app/appearance/langs/zh_CN.json

@@ -1,6 +1,8 @@
 {
-  "snapshotName": "快照名称",
-  "snapshotNameTip": "请勿包含符号 \\ / : * ? " ' < > |",
+  "snapshotMemo": "快照备注",
+  "snapshotMemoTip": "请输入快照备注",
+  "tagSnapshot": "标记快照",
+  "tagSnapshotTip": "请勿包含符号 \\ / : * ? " ' < > |",
   "syncDataRepo": "⚗️ 使用数据仓库同步机制(该特性正处于公测阶段)",
   "syncDataRepoTip": "数据仓库同步机制能够更好地处理数据冲突,同步性能也更好",
   "dataRepo": "数据仓库",
@@ -907,7 +909,7 @@
     "139": "正在生成数据快照,已处理 [%s] 个数据文件,剩余待处理 [%s]...",
     "140": "创建数据快照失败:%s",
     "141": "回滚数据快照失败",
-    "142": "快照备注不能为空",
+    "142": "输入不能为空",
     "143": "正在创建数据快照...",
     "144": "正在重置数据仓库...",
     "145": "数据仓库重置完毕",

+ 5 - 5
app/src/util/history.ts

@@ -379,9 +379,9 @@ export const openHistory = () => {
                 break;
             } else if (type === "genRepo") {
                 const genRepoDialog = new Dialog({
-                    title: window.siyuan.languages.snapshotName,
+                    title: window.siyuan.languages.snapshotMemo,
                     content: `<div class="b3-dialog__content">
-    <input class="b3-text-field fn__block" placeholder="${window.siyuan.languages.snapshotNameTip}"></input>
+    <textarea class="b3-text-field fn__block" placeholder="${window.siyuan.languages.snapshotMemoTip}"></textarea>
 </div>
 <div class="b3-dialog__action">
     <button class="b3-button b3-button--cancel">${window.siyuan.languages.cancel}</button><div class="fn__space"></div>
@@ -389,14 +389,14 @@ export const openHistory = () => {
 </div>`,
                     width: isMobile() ? "80vw" : "520px",
                 });
-                const inputElement = genRepoDialog.element.querySelector("input");
-                inputElement.focus();
+                const textareaElement = genRepoDialog.element.querySelector("textarea");
+                textareaElement.focus();
                 const btnsElement = genRepoDialog.element.querySelectorAll(".b3-button");
                 btnsElement[0].addEventListener("click", () => {
                     genRepoDialog.destroy();
                 });
                 btnsElement[1].addEventListener("click", () => {
-                    fetchPost("/api/repo/createSnapshot", {name: inputElement.value}, () => {
+                    fetchPost("/api/repo/createSnapshot", {memo: textareaElement.value}, () => {
                         renderRepo(repoElement, 1);
                     });
                     genRepoDialog.destroy();

+ 20 - 1
kernel/api/repo.go

@@ -75,8 +75,27 @@ func createSnapshot(c *gin.Context) {
 		return
 	}
 
+	memo := arg["memo"].(string)
+	if err := model.IndexRepo(memo); nil != err {
+		ret.Code = -1
+		ret.Msg = fmt.Sprintf(model.Conf.Language(140), err)
+		ret.Data = map[string]interface{}{"closeTimeout": 5000}
+		return
+	}
+}
+
+func tagSnapshot(c *gin.Context) {
+	ret := gulu.Ret.NewResult()
+	defer c.JSON(http.StatusOK, ret)
+
+	arg, ok := util.JsonArg(c, ret)
+	if !ok {
+		return
+	}
+
+	id := arg["id"].(string)
 	name := arg["name"].(string)
-	if err := model.CreateSnapshot(name); nil != err {
+	if err := model.TagSnapshot(id, name); nil != err {
 		ret.Code = -1
 		ret.Msg = fmt.Sprintf(model.Conf.Language(140), err)
 		ret.Data = map[string]interface{}{"closeTimeout": 5000}

+ 1 - 0
kernel/api/router.go

@@ -255,6 +255,7 @@ func ServeAPI(ginServer *gin.Engine) {
 	ginServer.Handle("POST", "/api/repo/resetRepo", model.CheckAuth, resetRepo)
 	ginServer.Handle("POST", "/api/repo/importRepoKey", model.CheckAuth, importRepoKey)
 	ginServer.Handle("POST", "/api/repo/createSnapshot", model.CheckAuth, createSnapshot)
+	ginServer.Handle("POST", "/api/repo/tagSnapshot", model.CheckAuth, tagSnapshot)
 	ginServer.Handle("POST", "/api/repo/checkoutRepo", model.CheckAuth, checkoutRepo)
 	ginServer.Handle("POST", "/api/repo/getRepoIndexLogs", model.CheckAuth, getRepoIndexLogs)
 

+ 5 - 29
kernel/model/repository.go

@@ -85,7 +85,7 @@ func ImportRepoKey(base64Key string) (err error) {
 	time.Sleep(1 * time.Second)
 	util.PushUpdateMsg(msgId, Conf.Language(138), 3000)
 	time.Sleep(1 * time.Second)
-	if initErr := indexRepo("[Init] Init data repo"); nil != initErr {
+	if initErr := IndexRepo("[Init] Init data repo"); nil != initErr {
 		util.PushUpdateMsg(msgId, fmt.Sprintf(Conf.Language(140), initErr), 7000)
 	}
 	return
@@ -145,7 +145,7 @@ func InitRepoKey() (err error) {
 	time.Sleep(1 * time.Second)
 	util.PushUpdateMsg(msgId, Conf.Language(138), 3000)
 	time.Sleep(1 * time.Second)
-	if initErr := indexRepo("[Init] Init data repo"); nil != initErr {
+	if initErr := IndexRepo("[Init] Init data repo"); nil != initErr {
 		util.PushUpdateMsg(msgId, fmt.Sprintf(Conf.Language(140), initErr), 7000)
 	}
 	return
@@ -194,7 +194,7 @@ func CheckoutRepo(id string) (err error) {
 	return
 }
 
-func CreateSnapshot(name string) (err error) {
+func TagSnapshot(id, name string) (err error) {
 	if 1 > len(Conf.Repo.Key) {
 		err = errors.New(Conf.Language(26))
 		return
@@ -216,19 +216,8 @@ func CreateSnapshot(name string) (err error) {
 		return
 	}
 
-	util.PushEndlessProgress(Conf.Language(143))
-	writingDataLock.Lock()
-	defer writingDataLock.Unlock()
-
-	start := time.Now()
-	latest, _ := repo.Latest()
-	WaitForWritingFiles()
-	filelock.ReleaseAllFileLocks()
-	index, err := repo.Index("[Snapshot] "+name, map[string]interface{}{
-		CtxPushMsg: CtxPushMsgToStatusBarAndProgress,
-	})
+	index, err := repo.GetIndex(id)
 	if nil != err {
-		util.PushStatusBar("Create data snapshot failed: " + err.Error())
 		return
 	}
 
@@ -237,23 +226,10 @@ func CreateSnapshot(name string) (err error) {
 		util.PushStatusBar(msg)
 		return
 	}
-
-	elapsed := time.Since(start)
-
-	if nil == latest || latest.ID != index.ID {
-		msg := fmt.Sprintf(Conf.Language(147), elapsed.Seconds())
-		util.PushStatusBar(msg)
-		util.PushMsg(msg, 5000)
-	} else {
-		msg := fmt.Sprintf(Conf.Language(148), elapsed.Seconds())
-		util.PushStatusBar(msg)
-		util.PushMsg(msg, 5000)
-	}
-	util.PushClearProgress()
 	return
 }
 
-func indexRepo(memo string) (err error) {
+func IndexRepo(memo string) (err error) {
 	if 1 > len(Conf.Repo.Key) {
 		err = errors.New(Conf.Language(26))
 		return