diff --git a/locales/de.json b/locales/de.json index d4fb6e55..42591ed4 100644 --- a/locales/de.json +++ b/locales/de.json @@ -692,6 +692,7 @@ "copyAll": "Alle Syntax kopieren", "refreshAll": "Alle Metadaten aktualisieren", "repairMetadata": "Metadaten der Auswahl reparieren", + "reimportMetadata": "Metadaten der Auswahl neu importieren", "checkUpdates": "Auswahl auf Updates prüfen", "moveAll": "Alle in Ordner verschieben", "autoOrganize": "Automatisch organisieren", @@ -739,6 +740,7 @@ "setContentRating": "Inhaltsbewertung festlegen", "moveToFolder": "In Ordner verschieben", "repairMetadata": "Metadaten reparieren", + "reimportMetadata": "Aus Quelle neu importieren", "excludeModel": "Modell ausschließen", "restoreModel": "Modell wiederherstellen", "deleteModel": "Modell löschen", @@ -866,6 +868,13 @@ "skipped": "Rezept bereits in der neuesten Version, keine Reparatur erforderlich", "failed": "Rezept-Reparatur fehlgeschlagen: {message}", "missingId": "Rezept kann nicht repariert werden: Fehlende Rezept-ID" + }, + "reimport": { + "starting": "Rezept wird aus Quelle neu importiert...", + "success": "Rezept erfolgreich neu importiert", + "noSourceUrl": "Rezept hat keine Quell-URL, Neuimport nicht möglich", + "failed": "Neuimport des Rezepts fehlgeschlagen: {message}", + "missingId": "Neuimport nicht möglich: Rezept-ID fehlt" } }, "batchImport": { @@ -1717,6 +1726,10 @@ "repairBulkComplete": "Reparatur abgeschlossen: {repaired} repariert, {skipped} übersprungen (von {total})", "repairBulkSkipped": "Keine Reparatur für die {total} ausgewählten Rezepte erforderlich", "repairBulkFailed": "Reparatur der ausgewählten Rezepte fehlgeschlagen: {message}", + "reimporting": "Rezept wird aus Quelle neu importiert...", + "reimportSuccess": "Rezept erfolgreich neu importiert", + "reimportBulkComplete": "Neuimport abgeschlossen: {completed} importiert, {failed} fehlgeschlagen (von {total})", + "reimportBulkFailed": "Neuimport einiger Rezepte fehlgeschlagen", "noMissingLorasInSelection": "Keine fehlenden LoRAs in ausgewählten Rezepten gefunden", "noLoraRootConfigured": "Kein LoRA-Stammverzeichnis konfiguriert. Bitte legen Sie ein Standard-LoRA-Stammverzeichnis in den Einstellungen fest." }, diff --git a/locales/en.json b/locales/en.json index 73b9ca37..e91dc45a 100644 --- a/locales/en.json +++ b/locales/en.json @@ -692,6 +692,7 @@ "copyAll": "Copy Selected Syntax", "refreshAll": "Refresh Selected Metadata", "repairMetadata": "Repair Metadata for Selected", + "reimportMetadata": "Re-import Metadata for Selected", "checkUpdates": "Check Updates for Selected", "moveAll": "Move Selected to Folder", "autoOrganize": "Auto-Organize Selected", @@ -739,6 +740,7 @@ "setContentRating": "Set Content Rating", "moveToFolder": "Move to Folder", "repairMetadata": "Repair metadata", + "reimportMetadata": "Re-import from Source", "excludeModel": "Exclude Model", "restoreModel": "Restore Model", "deleteModel": "Delete Model", @@ -866,6 +868,13 @@ "skipped": "Recipe already at latest version, no repair needed", "failed": "Failed to repair recipe: {message}", "missingId": "Cannot repair recipe: Missing recipe ID" + }, + "reimport": { + "starting": "Re-importing recipe from source...", + "success": "Recipe re-imported successfully", + "noSourceUrl": "Recipe has no source URL, cannot re-import", + "failed": "Failed to re-import recipe: {message}", + "missingId": "Cannot re-import recipe: Missing recipe ID" } }, "batchImport": { @@ -1717,6 +1726,10 @@ "repairBulkComplete": "Repair complete: {repaired} repaired, {skipped} skipped (of {total})", "repairBulkSkipped": "No repair needed for any of the {total} selected recipes", "repairBulkFailed": "Failed to repair selected recipes: {message}", + "reimporting": "Re-importing recipe from source...", + "reimportSuccess": "Recipe re-imported successfully", + "reimportBulkComplete": "Re-import complete: {completed} re-imported, {failed} failed (of {total})", + "reimportBulkFailed": "Failed to re-import some recipes", "noMissingLorasInSelection": "No missing LoRAs found in selected recipes", "noLoraRootConfigured": "No LoRA root directory configured. Please set a default LoRA root in settings." }, diff --git a/locales/es.json b/locales/es.json index fa91a7e3..14725a09 100644 --- a/locales/es.json +++ b/locales/es.json @@ -692,6 +692,7 @@ "copyAll": "Copiar toda la sintaxis", "refreshAll": "Actualizar todos los metadatos", "repairMetadata": "Reparar metadatos de la selección", + "reimportMetadata": "Reimportar metadatos de la selección", "checkUpdates": "Comprobar actualizaciones para la selección", "moveAll": "Mover todos a carpeta", "autoOrganize": "Auto-organizar seleccionados", @@ -739,6 +740,7 @@ "setContentRating": "Establecer clasificación de contenido", "moveToFolder": "Mover a carpeta", "repairMetadata": "Reparar metadatos", + "reimportMetadata": "Reimportar desde origen", "excludeModel": "Excluir modelo", "restoreModel": "Restaurar modelo", "deleteModel": "Eliminar modelo", @@ -866,6 +868,13 @@ "skipped": "La receta ya está en la última versión, no se necesita reparación", "failed": "Error al reparar la receta: {message}", "missingId": "No se puede reparar la receta: falta el ID de la receta" + }, + "reimport": { + "starting": "Reimportando receta desde origen...", + "success": "Receta reimportada exitosamente", + "noSourceUrl": "La receta no tiene URL de origen, no se puede reimportar", + "failed": "Error al reimportar la receta: {message}", + "missingId": "No se puede reimportar la receta: falta el ID" } }, "batchImport": { @@ -1717,6 +1726,10 @@ "repairBulkComplete": "Reparación completa: {repaired} reparadas, {skipped} omitidas (de {total})", "repairBulkSkipped": "No se necesita reparación para ninguna de las {total} recetas seleccionadas", "repairBulkFailed": "Error al reparar las recetas seleccionadas: {message}", + "reimporting": "Reimportando receta desde origen...", + "reimportSuccess": "Receta reimportada exitosamente", + "reimportBulkComplete": "Reimportación completa: {completed} reimportadas, {failed} fallidas (de {total})", + "reimportBulkFailed": "Error al reimportar algunas recetas", "noMissingLorasInSelection": "No se encontraron LoRAs faltantes en las recetas seleccionadas", "noLoraRootConfigured": "No se ha configurado el directorio raíz de LoRA. Por favor, establezca un directorio raíz de LoRA predeterminado en la configuración." }, diff --git a/locales/fr.json b/locales/fr.json index 85f23153..6a20acf8 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -692,6 +692,7 @@ "copyAll": "Copier toute la syntaxe", "refreshAll": "Actualiser toutes les métadonnées", "repairMetadata": "Réparer les métadonnées de la sélection", + "reimportMetadata": "Ré-importer les métadonnées de la sélection", "checkUpdates": "Vérifier les mises à jour pour la sélection", "moveAll": "Déplacer tout vers un dossier", "autoOrganize": "Auto-organiser la sélection", @@ -739,6 +740,7 @@ "setContentRating": "Définir la classification du contenu", "moveToFolder": "Déplacer vers un dossier", "repairMetadata": "Réparer les métadonnées", + "reimportMetadata": "Ré-importer depuis la source", "excludeModel": "Exclure le modèle", "restoreModel": "Restaurer le modèle", "deleteModel": "Supprimer le modèle", @@ -866,6 +868,13 @@ "skipped": "Recette déjà à la version la plus récente, aucune réparation nécessaire", "failed": "Échec de la réparation de la recette : {message}", "missingId": "Impossible de réparer la recette : ID de recette manquant" + }, + "reimport": { + "starting": "Ré-import de la recette depuis la source...", + "success": "Recette ré-importée avec succès", + "noSourceUrl": "La recette n'a pas d'URL source, ré-import impossible", + "failed": "Échec du ré-import de la recette : {message}", + "missingId": "Impossible de ré-importer la recette : ID de recette manquant" } }, "batchImport": { @@ -1717,6 +1726,10 @@ "repairBulkComplete": "Réparation terminée : {repaired} réparée(s), {skipped} ignorée(s) (sur {total})", "repairBulkSkipped": "Aucune réparation nécessaire parmi les {total} recettes sélectionnées", "repairBulkFailed": "Échec de la réparation des recettes sélectionnées : {message}", + "reimporting": "Ré-import de la recette depuis la source...", + "reimportSuccess": "Recette ré-importée avec succès", + "reimportBulkComplete": "Ré-import terminé : {completed} ré-importé(s), {failed} échec(s) (sur {total})", + "reimportBulkFailed": "Échec du ré-import de certaines recettes", "noMissingLorasInSelection": "Aucun LoRA manquant trouvé dans les recettes sélectionnées", "noLoraRootConfigured": "Aucun répertoire racine LoRA configuré. Veuillez définir un répertoire racine LoRA par défaut dans les paramètres." }, diff --git a/locales/he.json b/locales/he.json index 1aa6a5b2..7564815e 100644 --- a/locales/he.json +++ b/locales/he.json @@ -692,6 +692,7 @@ "copyAll": "העתק את כל התחבירים", "refreshAll": "רענן את כל המטא-דאטה", "repairMetadata": "תקן מטא-דאטה עבור הנבחרים", + "reimportMetadata": "ייבא מחדש מטא-דאטה עבור הנבחרים", "checkUpdates": "בדוק עדכונים לבחירה", "moveAll": "העבר הכל לתיקייה", "autoOrganize": "ארגן אוטומטית נבחרים", @@ -739,6 +740,7 @@ "setContentRating": "הגדר דירוג תוכן", "moveToFolder": "העבר לתיקייה", "repairMetadata": "תיקון מטא-דאטה", + "reimportMetadata": "ייבא מחדש ממקור", "excludeModel": "החרג מודל", "restoreModel": "שחזור מודל", "deleteModel": "מחק מודל", @@ -866,6 +868,13 @@ "skipped": "המתכון כבר בגרסה העדכנית ביותר, אין צורך בתיקון", "failed": "תיקון המתכון נכשל: {message}", "missingId": "לא ניתן לתקן את המתכון: חסר מזהה מתכון" + }, + "reimport": { + "starting": "מייבא מתכון מחדש מהמקור...", + "success": "המתכון יובא מחדש בהצלחה", + "noSourceUrl": "למתכון אין כתובת מקור, לא ניתן לייבא מחדש", + "failed": "ייבוא המתכון מחדש נכשל: {message}", + "missingId": "לא ניתן לייבא מחדש: חסר מזהה מתכון" } }, "batchImport": { @@ -1717,6 +1726,10 @@ "repairBulkComplete": "התיקון הושלם: {repaired} תוקנו, {skipped} דולגו (מתוך {total})", "repairBulkSkipped": "אין צורך בתיקון עבור {total} המתכונים הנבחרים", "repairBulkFailed": "תיקון המתכונים הנבחרים נכשל: {message}", + "reimporting": "מייבא מתכון מחדש מהמקור...", + "reimportSuccess": "המתכון יובא מחדש בהצלחה", + "reimportBulkComplete": "ייבוא מחדש הושלם: {completed} יובאו, {failed} נכשלו (מתוך {total})", + "reimportBulkFailed": "ייבוא מחדש של חלק מהמתכונים נכשל", "noMissingLorasInSelection": "לא נמצאו LoRAs חסרים במתכונים שנבחרו", "noLoraRootConfigured": "תיקיית השורש של LoRA לא מוגדרת. אנא הגדר תיקיית שורש LoRA ברירת מחדל בהגדרות." }, diff --git a/locales/ja.json b/locales/ja.json index 2921a099..e3a91115 100644 --- a/locales/ja.json +++ b/locales/ja.json @@ -692,6 +692,7 @@ "copyAll": "すべての構文をコピー", "refreshAll": "すべてのメタデータを更新", "repairMetadata": "選択したレシピのメタデータを修復", + "reimportMetadata": "選択したレシピを再インポート", "checkUpdates": "選択項目の更新を確認", "moveAll": "すべてをフォルダに移動", "autoOrganize": "自動整理を実行", @@ -739,6 +740,7 @@ "setContentRating": "コンテンツレーティングを設定", "moveToFolder": "フォルダに移動", "repairMetadata": "メタデータを修復", + "reimportMetadata": "ソースから再インポート", "excludeModel": "モデルを除外", "restoreModel": "モデルを復元", "deleteModel": "モデルを削除", @@ -866,6 +868,13 @@ "skipped": "レシピはすでに最新バージョンです。修復は不要です", "failed": "レシピの修復に失敗しました: {message}", "missingId": "レシピを修復できません: レシピIDがありません" + }, + "reimport": { + "starting": "ソースからレシピを再インポート中...", + "success": "レシピの再インポートが完了しました", + "noSourceUrl": "レシピにソースURLがありません。再インポートできません", + "failed": "レシピの再インポートに失敗しました: {message}", + "missingId": "レシピを再インポートできません: レシピIDがありません" } }, "batchImport": { @@ -1717,6 +1726,10 @@ "repairBulkComplete": "修復完了:{repaired} 件修復、{skipped} 件スキップ(合計 {total} 件)", "repairBulkSkipped": "選択した {total} 件のレシピは修復不要です", "repairBulkFailed": "選択したレシピの修復に失敗しました:{message}", + "reimporting": "ソースからレシピを再インポート中...", + "reimportSuccess": "レシピの再インポートが完了しました", + "reimportBulkComplete": "再インポート完了:{completed} 件成功、{failed} 件失敗(合計 {total} 件)", + "reimportBulkFailed": "一部のレシピの再インポートに失敗しました", "noMissingLorasInSelection": "選択したレシピに不足している LoRA が見つかりませんでした", "noLoraRootConfigured": "LoRA ルートディレクトリが設定されていません。設定でデフォルトの LoRA ルートを設定してください。" }, diff --git a/locales/ko.json b/locales/ko.json index b1075bb2..735f8ef0 100644 --- a/locales/ko.json +++ b/locales/ko.json @@ -692,6 +692,7 @@ "copyAll": "모든 문법 복사", "refreshAll": "모든 메타데이터 새로고침", "repairMetadata": "선택한 레시피 메타데이터 복구", + "reimportMetadata": "선택한 레시피 다시 가져오기", "checkUpdates": "선택 항목 업데이트 확인", "moveAll": "모두 폴더로 이동", "autoOrganize": "자동 정리 선택", @@ -739,6 +740,7 @@ "setContentRating": "콘텐츠 등급 설정", "moveToFolder": "폴더로 이동", "repairMetadata": "메타데이터 복구", + "reimportMetadata": "소스에서 다시 가져오기", "excludeModel": "모델 제외", "restoreModel": "모델 복원", "deleteModel": "모델 삭제", @@ -866,6 +868,13 @@ "skipped": "레시피가 이미 최신 버전입니다. 복구가 필요하지 않습니다", "failed": "레시피 복구 실패: {message}", "missingId": "레시피를 복구할 수 없음: 레시피 ID 누락" + }, + "reimport": { + "starting": "소스에서 레시피를 다시 가져오는 중...", + "success": "레시피를 다시 가져왔습니다", + "noSourceUrl": "레시피에 소스 URL이 없어 다시 가져올 수 없습니다", + "failed": "레시피 다시 가져오기 실패: {message}", + "missingId": "레시피를 다시 가져올 수 없음: 레시피 ID 누락" } }, "batchImport": { @@ -1717,6 +1726,10 @@ "repairBulkComplete": "복구 완료: {repaired}개 복구, {skipped}개 건너뜀 (총 {total}개)", "repairBulkSkipped": "선택한 {total}개 레시피는 복구가 필요하지 않습니다", "repairBulkFailed": "선택한 레시피 복구 실패: {message}", + "reimporting": "소스에서 레시피를 다시 가져오는 중...", + "reimportSuccess": "레시피를 다시 가져왔습니다", + "reimportBulkComplete": "다시 가져오기 완료: {completed}개 성공, {failed}개 실패 (총 {total}개)", + "reimportBulkFailed": "일부 레시피를 다시 가져오지 못했습니다", "noMissingLorasInSelection": "선택한 레시피에서 누락된 LoRA를 찾을 수 없습니다", "noLoraRootConfigured": "LoRA 루트 디렉토리가 구성되지 않았습니다. 설정에서 기본 LoRA 루트를 설정하세요." }, diff --git a/locales/ru.json b/locales/ru.json index 0ad7b528..3ad5cac1 100644 --- a/locales/ru.json +++ b/locales/ru.json @@ -692,6 +692,7 @@ "copyAll": "Копировать весь синтаксис", "refreshAll": "Обновить все метаданные", "repairMetadata": "Восстановить метаданные для выбранных", + "reimportMetadata": "Переимпортировать метаданные для выбранных", "checkUpdates": "Проверить обновления для выбранных", "moveAll": "Переместить все в папку", "autoOrganize": "Автоматически организовать выбранные", @@ -739,6 +740,7 @@ "setContentRating": "Установить рейтинг контента", "moveToFolder": "Переместить в папку", "repairMetadata": "Восстановить метаданные", + "reimportMetadata": "Переимпортировать из источника", "excludeModel": "Исключить модель", "restoreModel": "Восстановить модель", "deleteModel": "Удалить модель", @@ -866,6 +868,13 @@ "skipped": "Рецепт уже последней версии, восстановление не требуется", "failed": "Не удалось восстановить рецепт: {message}", "missingId": "Не удалось восстановить рецепт: отсутствует ID рецепта" + }, + "reimport": { + "starting": "Переимпорт рецепта из источника...", + "success": "Рецепт успешно переимпортирован", + "noSourceUrl": "У рецепта нет URL источника, переимпорт невозможен", + "failed": "Не удалось переимпортировать рецепт: {message}", + "missingId": "Невозможно переимпортировать рецепт: отсутствует ID" } }, "batchImport": { @@ -1717,6 +1726,10 @@ "repairBulkComplete": "Восстановление завершено: {repaired} восстановлено, {skipped} пропущено (из {total})", "repairBulkSkipped": "Ни один из {total} выбранных рецептов не требует восстановления", "repairBulkFailed": "Не удалось восстановить выбранные рецепты: {message}", + "reimporting": "Переимпорт рецепта из источника...", + "reimportSuccess": "Рецепт успешно переимпортирован", + "reimportBulkComplete": "Переимпорт завершён: {completed} переимпортировано, {failed} ошибок (из {total})", + "reimportBulkFailed": "Не удалось переимпортировать некоторые рецепты", "noMissingLorasInSelection": "В выбранных рецептах не найдены отсутствующие LoRAs", "noLoraRootConfigured": "Корневой каталог LoRA не настроен. Пожалуйста, установите корневой каталог LoRA по умолчанию в настройках." }, diff --git a/locales/zh-CN.json b/locales/zh-CN.json index c8b0f514..897c7607 100644 --- a/locales/zh-CN.json +++ b/locales/zh-CN.json @@ -692,6 +692,7 @@ "copyAll": "复制所选中语法", "refreshAll": "刷新所选中元数据", "repairMetadata": "修复所选中元数据", + "reimportMetadata": "重新导入所选配方元数据", "checkUpdates": "检查所选更新", "moveAll": "移动所选中到文件夹", "autoOrganize": "自动整理所选模型", @@ -739,6 +740,7 @@ "setContentRating": "设置内容评级", "moveToFolder": "移动到文件夹", "repairMetadata": "修复元数据", + "reimportMetadata": "从源重新导入", "excludeModel": "排除模型", "restoreModel": "恢复模型", "deleteModel": "删除模型", @@ -866,6 +868,13 @@ "skipped": "配方已是最新版本,无需修复", "failed": "修复配方失败:{message}", "missingId": "无法修复配方:缺少配方 ID" + }, + "reimport": { + "starting": "正在从源重新导入配方...", + "success": "配方已从源重新导入成功", + "noSourceUrl": "配方没有源URL,无法重新导入", + "failed": "重新导入配方失败:{message}", + "missingId": "无法重新导入配方:缺少配方ID" } }, "batchImport": { @@ -1717,6 +1726,10 @@ "repairBulkComplete": "修复完成:{repaired} 个已修复,{skipped} 个已跳过(共 {total} 个)", "repairBulkSkipped": "所选 {total} 个配方无需修复", "repairBulkFailed": "修复所选配方失败:{message}", + "reimporting": "正在从源重新导入配方...", + "reimportSuccess": "配方已从源重新导入成功", + "reimportBulkComplete": "重新导入完成:{completed} 个已导入,{failed} 个失败(共 {total} 个)", + "reimportBulkFailed": "重新导入某些配方失败", "noMissingLorasInSelection": "在选定的配方中未找到缺失的 LoRAs", "noLoraRootConfigured": "未配置 LoRA 根目录。请在设置中设置默认的 LoRA 根目录。" }, diff --git a/locales/zh-TW.json b/locales/zh-TW.json index fc089e15..b4a155e3 100644 --- a/locales/zh-TW.json +++ b/locales/zh-TW.json @@ -692,6 +692,7 @@ "copyAll": "複製全部語法", "refreshAll": "刷新全部 metadata", "repairMetadata": "修復所選中元數據", + "reimportMetadata": "重新匯入所選配方元數據", "checkUpdates": "檢查所選更新", "moveAll": "全部移動到資料夾", "autoOrganize": "自動整理所選模型", @@ -739,6 +740,7 @@ "setContentRating": "設定內容分級", "moveToFolder": "移動到資料夾", "repairMetadata": "修復元數據", + "reimportMetadata": "從來源重新匯入", "excludeModel": "排除模型", "restoreModel": "還原模型", "deleteModel": "刪除模型", @@ -866,6 +868,13 @@ "skipped": "配方已是最新版本,無需修復", "failed": "修復配方失敗:{message}", "missingId": "無法修復配方:缺少配方 ID" + }, + "reimport": { + "starting": "正在從來源重新匯入配方...", + "success": "配方已從來源重新匯入成功", + "noSourceUrl": "配方沒有來源URL,無法重新匯入", + "failed": "重新匯入配方失敗:{message}", + "missingId": "無法重新匯入配方:缺少配方ID" } }, "batchImport": { @@ -1717,6 +1726,10 @@ "repairBulkComplete": "修復完成:{repaired} 個已修復,{skipped} 個已跳過(共 {total} 個)", "repairBulkSkipped": "所選 {total} 個配方無需修復", "repairBulkFailed": "修復所選配方失敗:{message}", + "reimporting": "正在從來源重新匯入配方...", + "reimportSuccess": "配方已從來源重新匯入成功", + "reimportBulkComplete": "重新匯入完成:{completed} 個已匯入,{failed} 個失敗(共 {total} 個)", + "reimportBulkFailed": "重新匯入某些配方失敗", "noMissingLorasInSelection": "在選取的食譜中未找到缺失的 LoRAs", "noLoraRootConfigured": "未配置 LoRA 根目錄。請在設定中設定預設的 LoRA 根目錄。" }, diff --git a/static/js/components/ContextMenu/BulkContextMenu.js b/static/js/components/ContextMenu/BulkContextMenu.js index b076a2b3..6be0c42b 100644 --- a/static/js/components/ContextMenu/BulkContextMenu.js +++ b/static/js/components/ContextMenu/BulkContextMenu.js @@ -42,10 +42,14 @@ export class BulkContextMenu extends BaseContextMenu { const deleteAllItem = this.menu.querySelector('[data-action="delete-all"]'); const downloadMissingLorasItem = this.menu.querySelector('[data-action="download-missing-loras"]'); const repairMetadataItem = this.menu.querySelector('[data-action="repair-metadata"]'); + const reimportMetadataItem = this.menu.querySelector('[data-action="reimport-metadata"]'); if (repairMetadataItem) { repairMetadataItem.style.display = config.repairMetadata ? 'flex' : 'none'; } + if (reimportMetadataItem) { + reimportMetadataItem.style.display = config.reimportMetadata ? 'flex' : 'none'; + } if (sendToWorkflowAppendItem) { sendToWorkflowAppendItem.style.display = config.sendToWorkflow ? 'flex' : 'none'; @@ -264,6 +268,9 @@ export class BulkContextMenu extends BaseContextMenu { case 'repair-metadata': bulkManager.repairSelectedRecipes(); break; + case 'reimport-metadata': + bulkManager.reimportSelectedRecipes(); + break; case 'set-favorite': { const allFavorited = this.countFavoritedInSelection() === state.selectedModels.size; bulkManager.setBulkFavorites(!allFavorited); diff --git a/static/js/components/ContextMenu/RecipeContextMenu.js b/static/js/components/ContextMenu/RecipeContextMenu.js index bcd42548..79832587 100644 --- a/static/js/components/ContextMenu/RecipeContextMenu.js +++ b/static/js/components/ContextMenu/RecipeContextMenu.js @@ -97,6 +97,9 @@ export class RecipeContextMenu extends BaseContextMenu { // Repair recipe metadata this.repairRecipe(recipeId); break; + case 'reimport': + this.reimportRecipe(recipeId); + break; } } @@ -325,6 +328,35 @@ export class RecipeContextMenu extends BaseContextMenu { showToast('recipes.contextMenu.repair.failed', { message: error.message }, 'error'); } } + + async reimportRecipe(recipeId) { + if (!recipeId) { + showToast('recipes.contextMenu.reimport.missingId', {}, 'error'); + return; + } + + state.loadingManager.showSimpleLoading('Re-importing recipe from source...'); + + try { + const response = await fetch(`/api/lm/recipe/${recipeId}/reimport`, { + method: 'POST' + }); + const result = await response.json(); + + if (result.success) { + state.loadingManager.hide(); + showToast('toast.recipes.reimportSuccess', {}, 'success'); + const { resetAndReload } = await import('../../api/recipeApi.js'); + resetAndReload(false, { preserveScroll: true }); + } else { + throw new Error(result.error || 'Re-import failed'); + } + } catch (error) { + console.error('Error reimporting recipe:', error); + state.loadingManager.hide(); + showToast('recipes.contextMenu.reimport.failed', { message: error.message }, 'error'); + } + } } // Mix in shared methods from ModelContextMenuMixin diff --git a/static/js/managers/BulkManager.js b/static/js/managers/BulkManager.js index 488f7a4e..0e9434ee 100644 --- a/static/js/managers/BulkManager.js +++ b/static/js/managers/BulkManager.js @@ -86,7 +86,8 @@ export class BulkManager { skipMetadataRefresh: false, setFavorite: true, unfavorite: true, - repairMetadata: true + repairMetadata: true, + reimportMetadata: true } }; @@ -657,6 +658,87 @@ export class BulkManager { } } + async reimportSelectedRecipes() { + if (state.selectedModels.size === 0) { + showToast('toast.recipes.noRecipesSelected', {}, 'warning'); + return; + } + + if (state.currentPageType !== 'recipes') { + showToast('This operation is only available for recipes', {}, 'warning'); + return; + } + + const filePaths = Array.from(state.selectedModels); + const total = filePaths.length; + let completed = 0; + let failed = 0; + + const recipeMap = new Map(); + if (state.virtualScroller?.items) { + for (const item of state.virtualScroller.items) { + if (item.file_path && item.id) { + recipeMap.set(item.file_path, item); + } + } + } + + const progressUI = state.loadingManager.showEnhancedProgress( + `Re-importing recipe 1/${total}...` + ); + + try { + for (let i = 0; i < filePaths.length; i++) { + const filePath = filePaths[i]; + const recipeItem = recipeMap.get(filePath); + const recipeId = recipeItem?.id; + const recipeName = recipeItem?.title || recipeId || 'Unknown'; + + progressUI.updateProgress( + Math.floor((i / total) * 100), + recipeName, + `Re-importing recipe ${Math.min(i + 1, total)}/${total}...` + ); + + if (!recipeId) { + failed++; + continue; + } + + try { + const response = await fetch( + `/api/lm/recipe/${recipeId}/reimport`, + { method: 'POST' } + ); + const result = await response.json(); + if (result.success) { + completed++; + } else { + failed++; + } + } catch { + failed++; + } + } + if (completed > 0) { + await progressUI.complete( + `Re-import complete: ${completed} re-imported, ${failed} failed` + ); + } else { + state.loadingManager.hide(); + showToast('toast.recipes.reimportBulkFailed', {}, 'error'); + } + + const { resetAndReload: recipeResetAndReload } = await import('../api/recipeApi.js'); + recipeResetAndReload(false, { preserveScroll: true }); + this.clearSelection(); + } catch (error) { + console.error('[reimportSelectedRecipes] outer catch:', error); + state.loadingManager.hide(); + showToast('toast.recipes.reimportBulkFailed', {}, 'error'); + } + } + async repairSelectedRecipes() { if (state.selectedModels.size === 0) { showToast('toast.recipes.noRecipesSelected', {}, 'warning'); diff --git a/templates/components/context_menu.html b/templates/components/context_menu.html index d7b4a652..3e4c7c86 100644 --- a/templates/components/context_menu.html +++ b/templates/components/context_menu.html @@ -83,6 +83,9 @@
{{ t('loras.bulkOperations.repairMetadata') }}
+
+ {{ t('loras.bulkOperations.reimportMetadata') }} +
{{ t('loras.bulkOperations.skipMetadataRefresh') }}
diff --git a/templates/recipes.html b/templates/recipes.html index 587a61fa..ebcb94f2 100644 --- a/templates/recipes.html +++ b/templates/recipes.html @@ -35,6 +35,9 @@
{{ t('loras.contextMenu.repairMetadata') }}
+
+ {{ t('loras.contextMenu.reimportMetadata') }} +
{{ t('loras.contextMenu.moveToFolder') }}