diff --git a/locales/de.json b/locales/de.json index 5d7c063d..6c0b1da0 100644 --- a/locales/de.json +++ b/locales/de.json @@ -826,7 +826,8 @@ "diffusion_model": "Diffusion Model" }, "contextMenu": { - "moveToOtherTypeFolder": "In {otherType}-Ordner verschieben" + "moveToOtherTypeFolder": "In {otherType}-Ordner verschieben", + "sendToWorkflow": "[TODO: Translate] Send to Workflow" } }, "embeddings": { @@ -1339,7 +1340,9 @@ "recipeReplaced": "Rezept im Workflow ersetzt", "recipeFailedToSend": "Fehler beim Senden des Rezepts an den Workflow", "noMatchingNodes": "Keine kompatiblen Knoten im aktuellen Workflow verfügbar", - "noTargetNodeSelected": "Kein Zielknoten ausgewählt" + "noTargetNodeSelected": "Kein Zielknoten ausgewählt", + "modelUpdated": "Modell im Workflow aktualisiert", + "modelFailed": "Fehler beim Aktualisieren des Modellknotens" }, "nodeSelector": { "recipe": "Rezept", diff --git a/locales/en.json b/locales/en.json index c2fc9c65..5cb4bde4 100644 --- a/locales/en.json +++ b/locales/en.json @@ -826,7 +826,8 @@ "diffusion_model": "Diffusion Model" }, "contextMenu": { - "moveToOtherTypeFolder": "Move to {otherType} Folder" + "moveToOtherTypeFolder": "Move to {otherType} Folder", + "sendToWorkflow": "Send to Workflow" } }, "embeddings": { @@ -1339,7 +1340,9 @@ "recipeReplaced": "Recipe replaced in workflow", "recipeFailedToSend": "Failed to send recipe to workflow", "noMatchingNodes": "No compatible nodes available in the current workflow", - "noTargetNodeSelected": "No target node selected" + "noTargetNodeSelected": "No target node selected", + "modelUpdated": "Model updated in workflow", + "modelFailed": "Failed to update model node" }, "nodeSelector": { "recipe": "Recipe", diff --git a/locales/es.json b/locales/es.json index 2c0224eb..f6129fa8 100644 --- a/locales/es.json +++ b/locales/es.json @@ -826,7 +826,8 @@ "diffusion_model": "Diffusion Model" }, "contextMenu": { - "moveToOtherTypeFolder": "Mover a la carpeta {otherType}" + "moveToOtherTypeFolder": "Mover a la carpeta {otherType}", + "sendToWorkflow": "[TODO: Translate] Send to Workflow" } }, "embeddings": { @@ -1339,7 +1340,9 @@ "recipeReplaced": "Receta reemplazada en el flujo de trabajo", "recipeFailedToSend": "Error al enviar receta al flujo de trabajo", "noMatchingNodes": "No hay nodos compatibles disponibles en el flujo de trabajo actual", - "noTargetNodeSelected": "No se ha seleccionado ningún nodo de destino" + "noTargetNodeSelected": "No se ha seleccionado ningún nodo de destino", + "modelUpdated": "Modelo actualizado en el flujo de trabajo", + "modelFailed": "Error al actualizar nodo de modelo" }, "nodeSelector": { "recipe": "Receta", diff --git a/locales/fr.json b/locales/fr.json index 8bccc171..dd9d7b83 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -826,7 +826,8 @@ "diffusion_model": "Diffusion Model" }, "contextMenu": { - "moveToOtherTypeFolder": "Déplacer vers le dossier {otherType}" + "moveToOtherTypeFolder": "Déplacer vers le dossier {otherType}", + "sendToWorkflow": "[TODO: Translate] Send to Workflow" } }, "embeddings": { @@ -1339,7 +1340,9 @@ "recipeReplaced": "Recipe remplacée dans le workflow", "recipeFailedToSend": "Échec de l'envoi de la recipe au workflow", "noMatchingNodes": "Aucun nœud compatible disponible dans le workflow actuel", - "noTargetNodeSelected": "Aucun nœud cible sélectionné" + "noTargetNodeSelected": "Aucun nœud cible sélectionné", + "modelUpdated": "Modèle mis à jour dans le workflow", + "modelFailed": "Échec de la mise à jour du nœud modèle" }, "nodeSelector": { "recipe": "Recipe", diff --git a/locales/he.json b/locales/he.json index da09c0c3..2622b12c 100644 --- a/locales/he.json +++ b/locales/he.json @@ -826,7 +826,8 @@ "diffusion_model": "Diffusion Model" }, "contextMenu": { - "moveToOtherTypeFolder": "העבר לתיקיית {otherType}" + "moveToOtherTypeFolder": "העבר לתיקיית {otherType}", + "sendToWorkflow": "[TODO: Translate] Send to Workflow" } }, "embeddings": { @@ -1339,7 +1340,9 @@ "recipeReplaced": "מתכון הוחלף ב-workflow", "recipeFailedToSend": "שליחת מתכון ל-workflow נכשלה", "noMatchingNodes": "אין צמתים תואמים זמינים ב-workflow הנוכחי", - "noTargetNodeSelected": "לא נבחר צומת יעד" + "noTargetNodeSelected": "לא נבחר צומת יעד", + "modelUpdated": "מודל עודכן ב-workflow", + "modelFailed": "עדכון צומת המודל נכשל" }, "nodeSelector": { "recipe": "מתכון", diff --git a/locales/ja.json b/locales/ja.json index 6c6b2e79..8e53be63 100644 --- a/locales/ja.json +++ b/locales/ja.json @@ -826,7 +826,8 @@ "diffusion_model": "Diffusion Model" }, "contextMenu": { - "moveToOtherTypeFolder": "{otherType} フォルダに移動" + "moveToOtherTypeFolder": "{otherType} フォルダに移動", + "sendToWorkflow": "[TODO: Translate] Send to Workflow" } }, "embeddings": { @@ -1339,7 +1340,9 @@ "recipeReplaced": "レシピがワークフローで置換されました", "recipeFailedToSend": "レシピをワークフローに送信できませんでした", "noMatchingNodes": "現在のワークフローには互換性のあるノードがありません", - "noTargetNodeSelected": "ターゲットノードが選択されていません" + "noTargetNodeSelected": "ターゲットノードが選択されていません", + "modelUpdated": "モデルがワークフローで更新されました", + "modelFailed": "モデルノードの更新に失敗しました" }, "nodeSelector": { "recipe": "レシピ", diff --git a/locales/ko.json b/locales/ko.json index 717700c7..0b868792 100644 --- a/locales/ko.json +++ b/locales/ko.json @@ -826,7 +826,8 @@ "diffusion_model": "Diffusion Model" }, "contextMenu": { - "moveToOtherTypeFolder": "{otherType} 폴더로 이동" + "moveToOtherTypeFolder": "{otherType} 폴더로 이동", + "sendToWorkflow": "[TODO: Translate] Send to Workflow" } }, "embeddings": { @@ -1339,7 +1340,9 @@ "recipeReplaced": "레시피가 워크플로에서 교체되었습니다", "recipeFailedToSend": "레시피를 워크플로로 전송하지 못했습니다", "noMatchingNodes": "현재 워크플로에서 호환되는 노드가 없습니다", - "noTargetNodeSelected": "대상 노드가 선택되지 않았습니다" + "noTargetNodeSelected": "대상 노드가 선택되지 않았습니다", + "modelUpdated": "모델이 워크플로에서 업데이트되었습니다", + "modelFailed": "모델 노드 업데이트 실패" }, "nodeSelector": { "recipe": "레시피", diff --git a/locales/ru.json b/locales/ru.json index 920489d4..fe37c07a 100644 --- a/locales/ru.json +++ b/locales/ru.json @@ -826,7 +826,8 @@ "diffusion_model": "Diffusion Model" }, "contextMenu": { - "moveToOtherTypeFolder": "Переместить в папку {otherType}" + "moveToOtherTypeFolder": "Переместить в папку {otherType}", + "sendToWorkflow": "[TODO: Translate] Send to Workflow" } }, "embeddings": { @@ -1339,7 +1340,9 @@ "recipeReplaced": "Рецепт заменён в workflow", "recipeFailedToSend": "Не удалось отправить рецепт в workflow", "noMatchingNodes": "В текущем workflow нет совместимых узлов", - "noTargetNodeSelected": "Целевой узел не выбран" + "noTargetNodeSelected": "Целевой узел не выбран", + "modelUpdated": "Модель обновлена в workflow", + "modelFailed": "Не удалось обновить узел модели" }, "nodeSelector": { "recipe": "Рецепт", diff --git a/locales/zh-CN.json b/locales/zh-CN.json index 6ccfe49e..ff008fbe 100644 --- a/locales/zh-CN.json +++ b/locales/zh-CN.json @@ -826,7 +826,8 @@ "diffusion_model": "Diffusion Model" }, "contextMenu": { - "moveToOtherTypeFolder": "移动到 {otherType} 文件夹" + "moveToOtherTypeFolder": "移动到 {otherType} 文件夹", + "sendToWorkflow": "[TODO: Translate] Send to Workflow" } }, "embeddings": { @@ -1339,7 +1340,9 @@ "recipeReplaced": "配方已替换到工作流", "recipeFailedToSend": "发送配方到工作流失败", "noMatchingNodes": "当前工作流中没有兼容的节点", - "noTargetNodeSelected": "未选择目标节点" + "noTargetNodeSelected": "未选择目标节点", + "modelUpdated": "模型已更新到工作流", + "modelFailed": "更新模型节点失败" }, "nodeSelector": { "recipe": "配方", diff --git a/locales/zh-TW.json b/locales/zh-TW.json index 9a7fe49f..b80b00c9 100644 --- a/locales/zh-TW.json +++ b/locales/zh-TW.json @@ -826,7 +826,8 @@ "diffusion_model": "Diffusion Model" }, "contextMenu": { - "moveToOtherTypeFolder": "移動到 {otherType} 資料夾" + "moveToOtherTypeFolder": "移動到 {otherType} 資料夾", + "sendToWorkflow": "[TODO: Translate] Send to Workflow" } }, "embeddings": { @@ -1339,7 +1340,9 @@ "recipeReplaced": "配方已取代於工作流", "recipeFailedToSend": "傳送配方到工作流失敗", "noMatchingNodes": "目前工作流程中沒有相容的節點", - "noTargetNodeSelected": "未選擇目標節點" + "noTargetNodeSelected": "未選擇目標節點", + "modelUpdated": "模型已更新到工作流", + "modelFailed": "更新模型節點失敗" }, "nodeSelector": { "recipe": "配方", diff --git a/static/js/components/ContextMenu/CheckpointContextMenu.js b/static/js/components/ContextMenu/CheckpointContextMenu.js index f2b05161..58b615b7 100644 --- a/static/js/components/ContextMenu/CheckpointContextMenu.js +++ b/static/js/components/ContextMenu/CheckpointContextMenu.js @@ -4,6 +4,8 @@ import { getModelApiClient, resetAndReload } from '../../api/modelApiFactory.js' import { showDeleteModal, showExcludeModal } from '../../utils/modalUtils.js'; import { moveManager } from '../../managers/MoveManager.js'; import { i18n } from '../../i18n/index.js'; +import { sendModelPathToWorkflow } from '../../utils/uiHelpers.js'; +import { MODEL_TYPES } from '../../api/apiConfig.js'; export class CheckpointContextMenu extends BaseContextMenu { constructor() { @@ -60,6 +62,10 @@ export class CheckpointContextMenu extends BaseContextMenu { this.currentCard.querySelector('.fa-copy').click(); } break; + case 'sendworkflow': + // Send checkpoint to workflow (always replace mode) + this.sendCheckpointToWorkflow(); + break; case 'refresh-metadata': // Refresh metadata from CivitAI apiClient.refreshSingleModelMetadata(this.currentCard.dataset.filepath); @@ -79,6 +85,52 @@ export class CheckpointContextMenu extends BaseContextMenu { break; } } + + async sendCheckpointToWorkflow() { + const modelPath = this.currentCard.dataset.filepath; + if (!modelPath) { + return; + } + + const subtype = (this.currentCard.dataset.sub_type || 'checkpoint').toLowerCase(); + const isDiffusionModel = subtype === 'diffusion_model'; + const widgetName = isDiffusionModel ? 'unet_name' : 'ckpt_name'; + const actionTypeText = i18n.t( + isDiffusionModel ? 'uiHelpers.nodeSelector.diffusionModel' : 'uiHelpers.nodeSelector.checkpoint', + {}, + isDiffusionModel ? 'Diffusion Model' : 'Checkpoint' + ); + const successMessage = i18n.t( + 'uiHelpers.workflow.modelUpdated', + {}, + 'Model updated in workflow' + ); + const failureMessage = i18n.t( + 'uiHelpers.workflow.modelFailed', + {}, + 'Failed to update model node' + ); + const missingNodesMessage = i18n.t( + 'uiHelpers.workflow.noMatchingNodes', + {}, + 'No compatible nodes available in the current workflow' + ); + const missingTargetMessage = i18n.t( + 'uiHelpers.workflow.noTargetNodeSelected', + {}, + 'No target node selected' + ); + + await sendModelPathToWorkflow(modelPath, { + widgetName, + collectionType: MODEL_TYPES.CHECKPOINT, + actionTypeText, + successMessage, + failureMessage, + missingNodesMessage, + missingTargetMessage, + }); + } } // Mix in shared methods diff --git a/static/js/components/RecipeModal.js b/static/js/components/RecipeModal.js index d0c94722..25bc1f58 100644 --- a/static/js/components/RecipeModal.js +++ b/static/js/components/RecipeModal.js @@ -1415,14 +1415,14 @@ class RecipeModal { isDiffusionModel ? 'Diffusion Model' : 'Checkpoint' ); const successMessage = translate( - isDiffusionModel ? 'uiHelpers.workflow.diffusionModelUpdated' : 'uiHelpers.workflow.checkpointUpdated', + 'uiHelpers.workflow.modelUpdated', {}, - isDiffusionModel ? 'Diffusion model updated in workflow' : 'Checkpoint updated in workflow' + 'Model updated in workflow' ); const failureMessage = translate( - isDiffusionModel ? 'uiHelpers.workflow.diffusionModelFailed' : 'uiHelpers.workflow.checkpointFailed', + 'uiHelpers.workflow.modelFailed', {}, - isDiffusionModel ? 'Failed to update diffusion model node' : 'Failed to update checkpoint node' + 'Failed to update model node' ); const missingNodesMessage = translate( 'uiHelpers.workflow.noMatchingNodes', diff --git a/static/js/components/shared/ModelCard.js b/static/js/components/shared/ModelCard.js index 89689907..717c5243 100644 --- a/static/js/components/shared/ModelCard.js +++ b/static/js/components/shared/ModelCard.js @@ -185,14 +185,14 @@ function handleSendToWorkflow(card, replaceMode, modelType) { isDiffusionModel ? 'Diffusion Model' : 'Checkpoint' ); const successMessage = translate( - isDiffusionModel ? 'uiHelpers.workflow.diffusionModelUpdated' : 'uiHelpers.workflow.checkpointUpdated', + 'uiHelpers.workflow.modelUpdated', {}, - isDiffusionModel ? 'Diffusion model updated in workflow' : 'Checkpoint updated in workflow' + 'Model updated in workflow' ); const failureMessage = translate( - isDiffusionModel ? 'uiHelpers.workflow.diffusionModelFailed' : 'uiHelpers.workflow.checkpointFailed', + 'uiHelpers.workflow.modelFailed', {}, - isDiffusionModel ? 'Failed to update diffusion model node' : 'Failed to update checkpoint node' + 'Failed to update model node' ); const missingNodesMessage = translate( 'uiHelpers.workflow.noMatchingNodes', diff --git a/static/js/components/shared/ModelModal.js b/static/js/components/shared/ModelModal.js index a4f252a6..5b1a92b7 100644 --- a/static/js/components/shared/ModelModal.js +++ b/static/js/components/shared/ModelModal.js @@ -1088,14 +1088,14 @@ async function handleSendToWorkflow(target, modelType) { isDiffusionModel ? 'Diffusion Model' : 'Checkpoint' ); const successMessage = translate( - isDiffusionModel ? 'uiHelpers.workflow.diffusionModelUpdated' : 'uiHelpers.workflow.checkpointUpdated', + 'uiHelpers.workflow.modelUpdated', {}, - isDiffusionModel ? 'Diffusion model updated in workflow' : 'Checkpoint updated in workflow' + 'Model updated in workflow' ); const failureMessage = translate( - isDiffusionModel ? 'uiHelpers.workflow.diffusionModelFailed' : 'uiHelpers.workflow.checkpointFailed', + 'uiHelpers.workflow.modelFailed', {}, - isDiffusionModel ? 'Failed to update diffusion model node' : 'Failed to update checkpoint node' + 'Failed to update model node' ); const missingNodesMessage = translate( 'uiHelpers.workflow.noMatchingNodes', diff --git a/templates/checkpoints.html b/templates/checkpoints.html index 26f7368e..5635761e 100644 --- a/templates/checkpoints.html +++ b/templates/checkpoints.html @@ -13,6 +13,7 @@
+