mirror of
https://github.com/TandoorRecipes/recipes.git
synced 2025-12-24 02:39:20 -05:00
some fixes
This commit is contained in:
@@ -1184,6 +1184,7 @@ class ShoppingListRecipeSerializer(serializers.ModelSerializer):
|
||||
meal_plan_data = MealPlanSerializer(source='mealplan', read_only=True, required=False)
|
||||
servings = CustomDecimalField()
|
||||
created_by = UserSerializer(read_only=True)
|
||||
|
||||
def create(self, validated_data):
|
||||
validated_data['space'] = self.context['request'].space
|
||||
validated_data['created_by'] = self.context['request'].user
|
||||
@@ -1197,8 +1198,8 @@ class ShoppingListRecipeSerializer(serializers.ModelSerializer):
|
||||
|
||||
class Meta:
|
||||
model = ShoppingListRecipe
|
||||
fields = ('id', 'name', 'recipe', 'recipe_data', 'mealplan', 'meal_plan_data', 'servings','created_by',)
|
||||
read_only_fields = ('id','created_by',)
|
||||
fields = ('id', 'name', 'recipe', 'recipe_data', 'mealplan', 'meal_plan_data', 'servings', 'created_by',)
|
||||
read_only_fields = ('id', 'created_by',)
|
||||
|
||||
|
||||
class ShoppingListEntrySerializer(WritableNestedModelSerializer):
|
||||
@@ -1248,7 +1249,8 @@ class ShoppingListEntrySerializer(WritableNestedModelSerializer):
|
||||
if existing_slr := ShoppingListRecipe.objects.filter(mealplan_id=validated_data['mealplan_id'], space=self.context['request'].space).first():
|
||||
validated_data['list_recipe'] = existing_slr
|
||||
else:
|
||||
validated_data['list_recipe'] = ShoppingListRecipe.objects.create(mealplan_id=validated_data['mealplan_id'], space=self.context['request'].space, created_by=self.context['request'].user)
|
||||
validated_data['list_recipe'] = ShoppingListRecipe.objects.create(mealplan_id=validated_data['mealplan_id'], space=self.context['request'].space,
|
||||
created_by=self.context['request'].user)
|
||||
del validated_data['mealplan_id']
|
||||
|
||||
return super().create(validated_data)
|
||||
@@ -1464,6 +1466,9 @@ class AccessTokenSerializer(serializers.ModelSerializer):
|
||||
def get_token(self, obj):
|
||||
if (timezone.now() - obj.created).seconds < 15:
|
||||
return obj.token
|
||||
if obj.scope == 'bookmarklet':
|
||||
# bookmarklet only tokens are always returned because they have very limited access and are needed for the bookmarklet function to work
|
||||
return obj.token
|
||||
return f'tda_************_******_***********{obj.token[len(obj.token) - 4:]}'
|
||||
|
||||
class Meta:
|
||||
|
||||
@@ -88,7 +88,7 @@ urlpatterns = [
|
||||
path('settings-shopping/', views.shopping_settings, name='view_shopping_settings'), # TODO rename to search settings
|
||||
|
||||
path('abuse/<slug:token>', views.report_share_abuse, name='view_report_share_abuse'),
|
||||
path('api/import/', api.import_files, name='view_import'),
|
||||
|
||||
path('import-response/<int:pk>/', import_export.import_response, name='view_import_response'),
|
||||
path('export/', import_export.export_recipe, name='view_export'),
|
||||
path('export-response/<int:pk>/', import_export.export_response, name='view_export_response'),
|
||||
@@ -110,6 +110,7 @@ urlpatterns = [
|
||||
path('data/batch/edit', data.batch_edit, name='data_batch_edit'),
|
||||
path('data/batch/import', data.batch_import, name='data_batch_import'),
|
||||
path('data/sync/wait', data.sync_wait, name='data_sync_wait'),
|
||||
path('api/import/', api.AppImportView.as_view(), name='view_import'),
|
||||
path('data/import/url', data.import_url, name='data_import_url'),
|
||||
path('api/get_external_file_link/<int:recipe_id>/', api.get_external_file_link, name='api_get_external_file_link'),
|
||||
path('api/get_recipe_file/<int:recipe_id>/', api.get_recipe_file, name='api_get_recipe_file'),
|
||||
@@ -121,7 +122,6 @@ urlpatterns = [
|
||||
path('api/reset-food-inheritance/', api.reset_food_inheritance, name='api_reset_food_inheritance'),
|
||||
path('api/switch-active-space/<int:space_id>/', api.switch_active_space, name='api_switch_active_space'),
|
||||
path('api/download-file/<int:file_id>/', api.download_file, name='api_download_file'),
|
||||
path('api/image-to-recipe', api.ImageToRecipeView.as_view(), name='api_image_to_recipe'),
|
||||
path('telegram/setup/<int:pk>', telegram.setup_bot, name='telegram_setup'),
|
||||
path('telegram/remove/<int:pk>', telegram.remove_bot, name='telegram_remove'),
|
||||
path('telegram/hook/<slug:token>/', telegram.hook, name='telegram_hook'),
|
||||
@@ -175,4 +175,4 @@ urlpatterns += [
|
||||
re_path(r'^v3/.*', views.vue3, name='vue_3'),
|
||||
path('', views.index, name='index'),
|
||||
path('<path:resource>', views.index, name='tandoor_frontend'),
|
||||
]
|
||||
]
|
||||
|
||||
@@ -1895,6 +1895,37 @@ class ImageToRecipeView(APIView):
|
||||
return Response({'msg': serializer.errors})
|
||||
|
||||
|
||||
class AppImportView(APIView):
|
||||
parser_classes = [MultiPartParser]
|
||||
throttle_classes = [RecipeImportThrottle]
|
||||
permission_classes = [CustomIsUser & CustomTokenHasReadWriteScope]
|
||||
|
||||
@extend_schema(request=ImportImageSerializer(many=False), responses=RecipeFromSourceResponseSerializer(many=False))
|
||||
def post(self, request, *args, **kwargs):
|
||||
limit, msg = above_space_limit(request.space)
|
||||
if limit:
|
||||
return Response({'error': True, 'msg': _('File is above space limit')}, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
form = ImportForm(request.POST, request.FILES)
|
||||
if form.is_valid() and request.FILES != {}:
|
||||
try:
|
||||
integration = get_integration(request, form.cleaned_data['type'])
|
||||
|
||||
il = ImportLog.objects.create(type=form.cleaned_data['type'], created_by=request.user, space=request.space)
|
||||
files = []
|
||||
for f in request.FILES.getlist('files'):
|
||||
files.append({'file': io.BytesIO(f.read()), 'name': f.name})
|
||||
t = threading.Thread(target=integration.do_import, args=[files, il, form.cleaned_data['duplicates']])
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
|
||||
return Response({'import_id': il.pk}, status=status.HTTP_200_OK)
|
||||
except NotImplementedError:
|
||||
return Response({'error': True, 'msg': _('Importing is not implemented for this provider')},
|
||||
status=status.HTTP_400_BAD_REQUEST)
|
||||
else:
|
||||
return Response({'error': True, 'msg': form.errors}, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
@extend_schema(
|
||||
request=None,
|
||||
responses=None,
|
||||
|
||||
47
vue3/src/assets/bookmarklet_v3.js
Normal file
47
vue3/src/assets/bookmarklet_v3.js
Normal file
@@ -0,0 +1,47 @@
|
||||
(function(){
|
||||
|
||||
var v = "1.3.2";
|
||||
|
||||
if (window.jQuery === undefined || window.jQuery.fn.jquery < v) {
|
||||
var done = false;
|
||||
var script = document.createElement("script");
|
||||
script.src = "https://ajax.googleapis.com/ajax/libs/jquery/" + v + "/jquery.min.js";
|
||||
script.onload = script.onreadystatechange = function(){
|
||||
if (!done && (!this.readyState || this.readyState == "loaded" || this.readyState == "complete")) {
|
||||
done = true;
|
||||
initBookmarklet();
|
||||
}
|
||||
};
|
||||
document.getElementsByTagName("head")[0].appendChild(script);
|
||||
} else {
|
||||
initBookmarklet();
|
||||
}
|
||||
function initBookmarklet() {
|
||||
(window.bookmarkletTandoor = function() {
|
||||
let recipe = document.documentElement.outerHTML
|
||||
let windowName = "ImportRecipe"
|
||||
let url = localStorage.getItem('importURL')
|
||||
let redirect = localStorage.getItem('redirectURL')
|
||||
let token = localStorage.getItem('token')
|
||||
let params = { 'url': window.location.protocol + '//' + window.location.host + window.location.pathname, 'html' : recipe};
|
||||
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open('POST', url, true);
|
||||
xhr.setRequestHeader('Content-Type', 'application/json');
|
||||
xhr.setRequestHeader('Authorization', 'Bearer ' + token);
|
||||
|
||||
// listen for `onload` event
|
||||
xhr.onload = () => {
|
||||
// process response
|
||||
if (xhr.readyState == 4 && xhr.status == 201) {
|
||||
// parse JSON data
|
||||
window.open(redirect.concat('?bookmarklet_import=', JSON.parse(xhr.response).id) )
|
||||
} else {
|
||||
console.error('Error!');
|
||||
}
|
||||
};
|
||||
xhr.send(JSON.stringify(params));
|
||||
}
|
||||
)();
|
||||
}
|
||||
})();
|
||||
34
vue3/src/components/display/ImportLogViewer.vue
Normal file
34
vue3/src/components/display/ImportLogViewer.vue
Normal file
@@ -0,0 +1,34 @@
|
||||
<template>
|
||||
|
||||
<v-row v-if=" props.importLog.importedRecipes != undefined && props.importLog.totalRecipes != undefined">
|
||||
<v-col>
|
||||
<v-progress-linear :model-value="(props.importLog.importedRecipes/props.importLog.totalRecipes)*100" height="24" color="primary">
|
||||
{{ props.importLog.importedRecipes }} / {{ props.importLog.totalRecipes }}
|
||||
</v-progress-linear>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col>
|
||||
<v-textarea :model-value="importLog.msg"></v-textarea>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
||||
import {ImportLog} from "@/openapi";
|
||||
import {PropType} from "vue";
|
||||
|
||||
const props = defineProps({
|
||||
importLog: {type: {} as PropType<ImportLog>, required: true}
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -1,8 +1,8 @@
|
||||
import {useDjangoUrls} from "@/composables/useDjangoUrls";
|
||||
import {ref} from "vue";
|
||||
import {getCookie} from "@/utils/cookie";
|
||||
import {RecipeFromJSON, RecipeFromSourceFromJSON, RecipeFromSourceResponseFromJSON, RecipeImageFromJSON, UserFile, UserFileFromJSON} from "@/openapi";
|
||||
import {ErrorMessageType, PreparedMessage, useMessageStore} from "@/stores/MessageStore";
|
||||
import {RecipeFromSourceResponseFromJSON, RecipeImageFromJSON, UserFile, UserFileFromJSON} from "@/openapi";
|
||||
|
||||
|
||||
/**
|
||||
* function to upload files to the multipart endpoints accepting file uploads
|
||||
@@ -101,25 +101,27 @@ export function useFileApi() {
|
||||
|
||||
/**
|
||||
* uploads the given files to the app import endpoint
|
||||
* @param file array to import
|
||||
* @param files array to import
|
||||
* @param app app to import
|
||||
* @param includeDuplicates if recipes that were found as duplicates should be imported as well
|
||||
* @returns Promise resolving to the import ID of the app import
|
||||
*/
|
||||
function doAppImport(file: File, app: string, includeDuplicates: boolean) {
|
||||
function doAppImport(files: File[], app: string, includeDuplicates: boolean) {
|
||||
let formData = new FormData()
|
||||
formData.append('type', app);
|
||||
formData.append('duplicates', includeDuplicates ? 'true' : 'false')
|
||||
// files.forEach(file => {
|
||||
// formData.append('files', file)
|
||||
// })
|
||||
formData.append('files', file)
|
||||
files.forEach(file => {
|
||||
formData.append('files', file)
|
||||
})
|
||||
|
||||
return fetch(getDjangoUrl(`api/import/`), {
|
||||
method: 'POST',
|
||||
headers: {'X-CSRFToken': getCookie('csrftoken')},
|
||||
body: formData
|
||||
}).then(r => {
|
||||
console.log(r)
|
||||
return r.json().then(r => {
|
||||
return r.import_id
|
||||
})
|
||||
}).finally(() => {
|
||||
fileApiLoading.value = false
|
||||
})
|
||||
|
||||
@@ -32,6 +32,9 @@
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"Bookmarklet": "",
|
||||
"BookmarkletHelp1": "",
|
||||
"BookmarkletHelp2": "",
|
||||
"BookmarkletHelp3": "",
|
||||
"BookmarkletImportSubtitle": "",
|
||||
"Books": "",
|
||||
"Calories": "",
|
||||
@@ -143,6 +146,7 @@
|
||||
"IgnoredFood": "",
|
||||
"Image": "",
|
||||
"Import": "",
|
||||
"ImportIntoTandoor": "",
|
||||
"Import_Error": "",
|
||||
"Import_Not_Yet_Supported": "",
|
||||
"Import_Result_Info": "",
|
||||
|
||||
@@ -32,6 +32,9 @@
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"Bookmarklet": "Книжен пазар",
|
||||
"BookmarkletHelp1": "",
|
||||
"BookmarkletHelp2": "",
|
||||
"BookmarkletHelp3": "",
|
||||
"BookmarkletImportSubtitle": "",
|
||||
"Books": "Книги",
|
||||
"Calories": "Калории",
|
||||
@@ -140,6 +143,7 @@
|
||||
"IgnoredFood": "{food} е настроен да игнорира пазаруването.",
|
||||
"Image": "Изображение",
|
||||
"Import": "Импортиране",
|
||||
"ImportIntoTandoor": "",
|
||||
"Import_Error": "Възникна грешка по време на импортирането ви. Моля, разгънете подробностите в долната част на страницата, за да ги видите.",
|
||||
"Import_Not_Yet_Supported": "Импортирането все още не се поддържа",
|
||||
"Import_Result_Info": "Импортирани са {imported} от {total} рецепти",
|
||||
|
||||
@@ -39,6 +39,9 @@
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"Bookmarklet": "",
|
||||
"BookmarkletHelp1": "",
|
||||
"BookmarkletHelp2": "",
|
||||
"BookmarkletHelp3": "",
|
||||
"BookmarkletImportSubtitle": "",
|
||||
"Books": "",
|
||||
"Calculator": "",
|
||||
@@ -186,6 +189,7 @@
|
||||
"Image": "",
|
||||
"Import": "",
|
||||
"Import Recipe": "",
|
||||
"ImportIntoTandoor": "",
|
||||
"Import_Error": "",
|
||||
"Import_Not_Yet_Supported": "",
|
||||
"Import_Result_Info": "",
|
||||
|
||||
@@ -39,6 +39,9 @@
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"Bookmarklet": "Skript v záložce",
|
||||
"BookmarkletHelp1": "",
|
||||
"BookmarkletHelp2": "",
|
||||
"BookmarkletHelp3": "",
|
||||
"BookmarkletImportSubtitle": "",
|
||||
"Books": "Kuchařky",
|
||||
"Calculator": "Kalkulačka",
|
||||
@@ -186,6 +189,7 @@
|
||||
"Image": "Obrázek",
|
||||
"Import": "Import",
|
||||
"Import Recipe": "Importovat recept",
|
||||
"ImportIntoTandoor": "",
|
||||
"Import_Error": "Během importu došlo k chybě. Pro více informací rozbalte Detaily na konci stránky.",
|
||||
"Import_Not_Yet_Supported": "Import není zatím podporován",
|
||||
"Import_Result_Info": "{imported} z {total} receptů naimportováno",
|
||||
|
||||
@@ -39,6 +39,9 @@
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"Bookmarklet": "Bogmærke",
|
||||
"BookmarkletHelp1": "",
|
||||
"BookmarkletHelp2": "",
|
||||
"BookmarkletHelp3": "",
|
||||
"BookmarkletImportSubtitle": "",
|
||||
"Books": "Bøger",
|
||||
"Calories": "Kalorier",
|
||||
@@ -174,6 +177,7 @@
|
||||
"Image": "Billede",
|
||||
"Import": "Importer",
|
||||
"Import Recipe": "Importer opskrift",
|
||||
"ImportIntoTandoor": "",
|
||||
"Import_Error": "Der opstod en fejl under din importering. Udvid detaljerne i bunden af siden for at se fejlen.",
|
||||
"Import_Not_Yet_Supported": "Import endnu ikke understøttet",
|
||||
"Import_Result_Info": "{imported} af {total} opskrifter blev importeret",
|
||||
|
||||
@@ -41,6 +41,9 @@
|
||||
"BaseUnitHelp": "Optionale Standardeinheit zur automatischen Umrechnung",
|
||||
"Book": "Buch",
|
||||
"Bookmarklet": "Lesezeichen",
|
||||
"BookmarkletHelp1": "Schiebe den Knopf in deine Lesezeichenleiste",
|
||||
"BookmarkletHelp2": "Öffne die Seite von der importiert werden soll.",
|
||||
"BookmarkletHelp3": "Klicke auf das Lesezeichen um den Import durchzuführen",
|
||||
"BookmarkletImportSubtitle": "Verwende ein Bookmarklet um von nicht öffentlichen Seiten zu importieren.",
|
||||
"Books": "Kochbücher",
|
||||
"Calculator": "Rechner",
|
||||
@@ -189,6 +192,7 @@
|
||||
"Image": "Bild",
|
||||
"Import": "Importieren",
|
||||
"Import Recipe": "Rezept importieren",
|
||||
"ImportIntoTandoor": "In Tandoor importieren",
|
||||
"Import_Error": "Es ist ein Fehler beim Importieren aufgetreten. Bitte sieh dir die ausgeklappten Details unten auf der Seite an.",
|
||||
"Import_Not_Yet_Supported": "Importieren wird noch nicht unterstützt",
|
||||
"Import_Result_Info": "{imported} von insgesamt {total} Rezepten wurden importiert",
|
||||
|
||||
@@ -38,6 +38,9 @@
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"Bookmarklet": "Bookmarklet",
|
||||
"BookmarkletHelp1": "",
|
||||
"BookmarkletHelp2": "",
|
||||
"BookmarkletHelp3": "",
|
||||
"BookmarkletImportSubtitle": "",
|
||||
"Books": "Βιβλία",
|
||||
"Calories": "Θερμίδες",
|
||||
@@ -169,6 +172,7 @@
|
||||
"Image": "Εικόνα",
|
||||
"Import": "Εισαγωγή",
|
||||
"Import Recipe": "Εισαγωγή συνταγής",
|
||||
"ImportIntoTandoor": "",
|
||||
"Import_Error": "Συνέβη ένα σφάλμα κατά την εισαγωγή. Για να το δείτε, εμφανίστε τις λεπτομέρειες στο κάτω μέρος της σελίδας.",
|
||||
"Import_Not_Yet_Supported": "Η εισαγωγή δεν υποστηρίζεται ακόμη",
|
||||
"Import_Result_Info": "Έγινε εισαγωγή {imported} από τις {total} συνταγές",
|
||||
|
||||
@@ -39,6 +39,9 @@
|
||||
"BaseUnitHelp": "Standard unit for automatic unit conversion",
|
||||
"Book": "Book",
|
||||
"Bookmarklet": "Bookmarklet",
|
||||
"BookmarkletHelp1": "Drag the following button to your bookmarks bar",
|
||||
"BookmarkletHelp2": "Open the page you want to import from",
|
||||
"BookmarkletHelp3": "Click on the bookmark to perform the import.",
|
||||
"BookmarkletImportSubtitle": "Use a bookmarklet to import from non public pages.",
|
||||
"Books": "Books",
|
||||
"Calculator": "Calculator",
|
||||
@@ -187,6 +190,7 @@
|
||||
"Image": "Image",
|
||||
"Import": "Import",
|
||||
"Import Recipe": "Import Recipe",
|
||||
"ImportIntoTandoor": "Import into Tandoor",
|
||||
"Import_Error": "An Error occurred during your import. Please expand the Details at the bottom of the page to view it.",
|
||||
"Import_Not_Yet_Supported": "Import not yet supported",
|
||||
"Import_Result_Info": "{imported} of {total} recipes were imported",
|
||||
|
||||
@@ -39,6 +39,9 @@
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"Bookmarklet": "Marcadores",
|
||||
"BookmarkletHelp1": "",
|
||||
"BookmarkletHelp2": "",
|
||||
"BookmarkletHelp3": "",
|
||||
"BookmarkletImportSubtitle": "",
|
||||
"Books": "Libros",
|
||||
"Calculator": "Calculadora",
|
||||
@@ -187,6 +190,7 @@
|
||||
"Image": "Imagen",
|
||||
"Import": "Importar",
|
||||
"Import Recipe": "Importar Receta",
|
||||
"ImportIntoTandoor": "",
|
||||
"Import_Error": "Ocurrió un Error ocurrió durante la importación. Por favor, expanda los Detalles al final de la página para verlo.",
|
||||
"Import_Not_Yet_Supported": "Importación no soportada todavía",
|
||||
"Import_Result_Info": "{imported} de {total} recetas fueron importadas",
|
||||
|
||||
@@ -24,6 +24,9 @@
|
||||
"BaseUnit": "",
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"BookmarkletHelp1": "",
|
||||
"BookmarkletHelp2": "",
|
||||
"BookmarkletHelp3": "",
|
||||
"BookmarkletImportSubtitle": "",
|
||||
"Books": "Kirjat",
|
||||
"Calories": "Kalorit",
|
||||
@@ -110,6 +113,7 @@
|
||||
"Ignore_Shopping": "Ohita Ostokset",
|
||||
"Image": "Kuva",
|
||||
"Import": "Tuo",
|
||||
"ImportIntoTandoor": "",
|
||||
"Import_finished": "Tuonti valmistui",
|
||||
"Information": "Tiedot",
|
||||
"Ingredient": "",
|
||||
|
||||
@@ -40,6 +40,9 @@
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"Bookmarklet": "Signet",
|
||||
"BookmarkletHelp1": "",
|
||||
"BookmarkletHelp2": "",
|
||||
"BookmarkletHelp3": "",
|
||||
"BookmarkletImportSubtitle": "",
|
||||
"Books": "Livres",
|
||||
"Calculator": "Calculatrice",
|
||||
@@ -186,6 +189,7 @@
|
||||
"Image": "Image",
|
||||
"Import": "Importer",
|
||||
"Import Recipe": "Importer une recette",
|
||||
"ImportIntoTandoor": "",
|
||||
"Import_Error": "Une erreur est survenue pendant votre importation. Veuillez développer les détails au bas de la page pour la consulter.",
|
||||
"Import_Not_Yet_Supported": "Importation pas encore prise en charge",
|
||||
"Import_Result_Info": "{imported} sur {total} recettes ont été importées",
|
||||
|
||||
@@ -39,6 +39,9 @@
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"Bookmarklet": "סימניה",
|
||||
"BookmarkletHelp1": "",
|
||||
"BookmarkletHelp2": "",
|
||||
"BookmarkletHelp3": "",
|
||||
"BookmarkletImportSubtitle": "",
|
||||
"Books": "ספרים",
|
||||
"Calculator": "מחשבון",
|
||||
@@ -187,6 +190,7 @@
|
||||
"Image": "תמונה",
|
||||
"Import": "ייבוא",
|
||||
"Import Recipe": "ייבא מתכון",
|
||||
"ImportIntoTandoor": "",
|
||||
"Import_Error": "שגיאה בעת ייבוא. הרחב את הפירוט בסוף עמוד זה לראות מידע נוסף.",
|
||||
"Import_Not_Yet_Supported": "ייבוא לא נתמך עדיין",
|
||||
"Import_Result_Info": "{imported} מתוך {total} מתכונים יובאו",
|
||||
|
||||
@@ -39,6 +39,9 @@
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"Bookmarklet": "Könyvjelző",
|
||||
"BookmarkletHelp1": "",
|
||||
"BookmarkletHelp2": "",
|
||||
"BookmarkletHelp3": "",
|
||||
"BookmarkletImportSubtitle": "",
|
||||
"Books": "Könyvek",
|
||||
"Calories": "Kalóriák",
|
||||
@@ -170,6 +173,7 @@
|
||||
"Image": "Kép",
|
||||
"Import": "Import",
|
||||
"Import Recipe": "Recept importálása",
|
||||
"ImportIntoTandoor": "",
|
||||
"Import_Error": "Hiba történt az importálás során. Kérjük, a megtekintéshez bontsa ki az oldal alján található Részletek menüpontot.",
|
||||
"Import_Not_Yet_Supported": "",
|
||||
"Import_Result_Info": "{total}-ból/ből {imported} recept importálva",
|
||||
|
||||
@@ -21,6 +21,9 @@
|
||||
"BaseUnit": "",
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"BookmarkletHelp1": "",
|
||||
"BookmarkletHelp2": "",
|
||||
"BookmarkletHelp3": "",
|
||||
"BookmarkletImportSubtitle": "",
|
||||
"Books": "",
|
||||
"Calories": "",
|
||||
@@ -85,6 +88,7 @@
|
||||
"History": "",
|
||||
"HostedFreeVersion": "",
|
||||
"Import": "Ներմուծել",
|
||||
"ImportIntoTandoor": "",
|
||||
"Import_finished": "Ներմուծումն ավարտված է",
|
||||
"Information": "Տեղեկություն",
|
||||
"Ingredient": "",
|
||||
|
||||
@@ -34,6 +34,9 @@
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"Bookmarklet": "",
|
||||
"BookmarkletHelp1": "",
|
||||
"BookmarkletHelp2": "",
|
||||
"BookmarkletHelp3": "",
|
||||
"BookmarkletImportSubtitle": "",
|
||||
"Books": "Buku",
|
||||
"Calories": "Kalori",
|
||||
@@ -157,6 +160,7 @@
|
||||
"IgnoredFood": "",
|
||||
"Image": "Gambar",
|
||||
"Import": "Impor",
|
||||
"ImportIntoTandoor": "",
|
||||
"Import_Error": "",
|
||||
"Import_Not_Yet_Supported": "",
|
||||
"Import_Result_Info": "",
|
||||
|
||||
@@ -39,6 +39,9 @@
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"Bookmarklet": "",
|
||||
"BookmarkletHelp1": "",
|
||||
"BookmarkletHelp2": "",
|
||||
"BookmarkletHelp3": "",
|
||||
"BookmarkletImportSubtitle": "",
|
||||
"Books": "",
|
||||
"Calculator": "",
|
||||
@@ -186,6 +189,7 @@
|
||||
"Image": "",
|
||||
"Import": "",
|
||||
"Import Recipe": "",
|
||||
"ImportIntoTandoor": "",
|
||||
"Import_Error": "",
|
||||
"Import_Not_Yet_Supported": "",
|
||||
"Import_Result_Info": "",
|
||||
|
||||
@@ -38,6 +38,9 @@
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"Bookmarklet": "Segnalibro",
|
||||
"BookmarkletHelp1": "",
|
||||
"BookmarkletHelp2": "",
|
||||
"BookmarkletHelp3": "",
|
||||
"BookmarkletImportSubtitle": "",
|
||||
"Books": "Libri",
|
||||
"Calories": "Calorie",
|
||||
@@ -162,6 +165,7 @@
|
||||
"IgnoredFood": "{food} è impostato per ignorare la spesa.",
|
||||
"Image": "Immagine",
|
||||
"Import": "Importa",
|
||||
"ImportIntoTandoor": "",
|
||||
"Import_Error": "Si è verificato un errore durante l'importazione. Per avere maggiori informazioni, espandi la sezione dettagli in fondo alla pagina.",
|
||||
"Import_Not_Yet_Supported": "Importazione non ancora supportata",
|
||||
"Import_Result_Info": "{imported} di {total} ricette sono state importate",
|
||||
|
||||
@@ -39,6 +39,9 @@
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"Bookmarklet": "",
|
||||
"BookmarkletHelp1": "",
|
||||
"BookmarkletHelp2": "",
|
||||
"BookmarkletHelp3": "",
|
||||
"BookmarkletImportSubtitle": "",
|
||||
"Books": "",
|
||||
"Calories": "",
|
||||
@@ -172,6 +175,7 @@
|
||||
"Image": "",
|
||||
"Import": "",
|
||||
"Import Recipe": "",
|
||||
"ImportIntoTandoor": "",
|
||||
"Import_Error": "",
|
||||
"Import_Not_Yet_Supported": "",
|
||||
"Import_Result_Info": "",
|
||||
|
||||
@@ -38,6 +38,9 @@
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"Bookmarklet": "",
|
||||
"BookmarkletHelp1": "",
|
||||
"BookmarkletHelp2": "",
|
||||
"BookmarkletHelp3": "",
|
||||
"BookmarkletImportSubtitle": "",
|
||||
"Books": "Bøker",
|
||||
"Calories": "Kalorier",
|
||||
@@ -167,6 +170,7 @@
|
||||
"Image": "Bilde",
|
||||
"Import": "Importer",
|
||||
"Import Recipe": "Importer oppskrift",
|
||||
"ImportIntoTandoor": "",
|
||||
"Import_Error": "",
|
||||
"Import_Not_Yet_Supported": "",
|
||||
"Import_Result_Info": "",
|
||||
|
||||
@@ -40,6 +40,9 @@
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"Bookmarklet": "Bladwijzer",
|
||||
"BookmarkletHelp1": "",
|
||||
"BookmarkletHelp2": "",
|
||||
"BookmarkletHelp3": "",
|
||||
"BookmarkletImportSubtitle": "",
|
||||
"Books": "Boeken",
|
||||
"Calories": "Calorieën",
|
||||
@@ -171,6 +174,7 @@
|
||||
"Image": "Afbeelding",
|
||||
"Import": "Importeer",
|
||||
"Import Recipe": "Recept Importeren",
|
||||
"ImportIntoTandoor": "",
|
||||
"Import_Error": "Er is een fout opgetreden tijdens je import. Breid de details aan de onderzijde van de pagina uit om ze te bekijken.",
|
||||
"Import_Not_Yet_Supported": "Import nog niet ondersteund",
|
||||
"Import_Result_Info": "{imported} van {total} recepten zijn geïmporteerd",
|
||||
|
||||
@@ -40,6 +40,9 @@
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"Bookmarklet": "Skryptozakładka",
|
||||
"BookmarkletHelp1": "",
|
||||
"BookmarkletHelp2": "",
|
||||
"BookmarkletHelp3": "",
|
||||
"BookmarkletImportSubtitle": "",
|
||||
"Books": "Książki",
|
||||
"Calculator": "Kalkulator",
|
||||
@@ -188,6 +191,7 @@
|
||||
"Image": "Obraz",
|
||||
"Import": "Importuj",
|
||||
"Import Recipe": "Importuj przepis",
|
||||
"ImportIntoTandoor": "",
|
||||
"Import_Error": "Podczas importowania wystąpił błąd. Rozwiń Szczegóły na dole strony, aby go wyświetlić.",
|
||||
"Import_Not_Yet_Supported": "Importowanie jeszcze nie wspierane",
|
||||
"Import_Result_Info": "{imported} z {total} przepisów zostało zaimportowanych",
|
||||
|
||||
@@ -32,6 +32,9 @@
|
||||
"BaseUnit": "",
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"BookmarkletHelp1": "",
|
||||
"BookmarkletHelp2": "",
|
||||
"BookmarkletHelp3": "",
|
||||
"BookmarkletImportSubtitle": "",
|
||||
"Books": "Livros",
|
||||
"Calories": "Calorias",
|
||||
@@ -142,6 +145,7 @@
|
||||
"IgnoredFood": "{food} está definida para ignorar compras.",
|
||||
"Image": "Image",
|
||||
"Import": "Importar",
|
||||
"ImportIntoTandoor": "",
|
||||
"Import_finished": "Importação terminada",
|
||||
"Information": "Informação",
|
||||
"Ingredient": "",
|
||||
|
||||
@@ -38,6 +38,9 @@
|
||||
"BaseUnit": "",
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"BookmarkletHelp1": "",
|
||||
"BookmarkletHelp2": "",
|
||||
"BookmarkletHelp3": "",
|
||||
"BookmarkletImportSubtitle": "",
|
||||
"Books": "Livros",
|
||||
"Calculator": "Calculadora",
|
||||
@@ -182,6 +185,7 @@
|
||||
"Image": "Imagem",
|
||||
"Import": "Importar",
|
||||
"Import Recipe": "Importar Receita",
|
||||
"ImportIntoTandoor": "",
|
||||
"Import_Not_Yet_Supported": "Importação ainda não suportada",
|
||||
"Import_Result_Info": "{imported} de {total} receitas foram importadas",
|
||||
"Import_Supported": "Importação suportada",
|
||||
|
||||
@@ -38,6 +38,9 @@
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"Bookmarklet": "Marcaj",
|
||||
"BookmarkletHelp1": "",
|
||||
"BookmarkletHelp2": "",
|
||||
"BookmarkletHelp3": "",
|
||||
"BookmarkletImportSubtitle": "",
|
||||
"Books": "Cărți",
|
||||
"Calories": "Calorii",
|
||||
@@ -165,6 +168,7 @@
|
||||
"Image": "Imagine",
|
||||
"Import": "Importă",
|
||||
"Import Recipe": "Importă rețeta",
|
||||
"ImportIntoTandoor": "",
|
||||
"Import_Error": "A apărut o eroare în timpul importului. Vă rugăm să extindeți detaliile din partea de jos a paginii pentru a le vizualiza.",
|
||||
"Import_Not_Yet_Supported": "Importul încă nu este compatibil",
|
||||
"Import_Result_Info": "{imported} din {total} rețete au fost importate",
|
||||
|
||||
@@ -31,6 +31,9 @@
|
||||
"BaseUnit": "",
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"BookmarkletHelp1": "",
|
||||
"BookmarkletHelp2": "",
|
||||
"BookmarkletHelp3": "",
|
||||
"BookmarkletImportSubtitle": "",
|
||||
"Books": "Книги",
|
||||
"Calories": "Каллории",
|
||||
@@ -131,6 +134,7 @@
|
||||
"IgnoredFood": "{food} будет исключён из списка покупок.",
|
||||
"Image": "Изображение",
|
||||
"Import": "Импорт",
|
||||
"ImportIntoTandoor": "",
|
||||
"Import_Error": "Во время импорта произошла ошибка. Для просмотра разверните \"Подробности\" в нижней части страницы.",
|
||||
"Import_finished": "Импорт завершен",
|
||||
"Imported": "Импортировано",
|
||||
|
||||
@@ -30,6 +30,9 @@
|
||||
"BaseUnit": "",
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"BookmarkletHelp1": "",
|
||||
"BookmarkletHelp2": "",
|
||||
"BookmarkletHelp3": "",
|
||||
"BookmarkletImportSubtitle": "",
|
||||
"Books": "Knjige",
|
||||
"Calories": "Kalorije",
|
||||
@@ -130,6 +133,7 @@
|
||||
"Ignore_Shopping": "Prezri nakup",
|
||||
"Image": "Slika",
|
||||
"Import": "Uvozi",
|
||||
"ImportIntoTandoor": "",
|
||||
"Import_finished": "Uvoz je končan",
|
||||
"Information": "Informacija",
|
||||
"Ingredient": "",
|
||||
|
||||
@@ -40,6 +40,9 @@
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"Bookmarklet": "Bokmärke",
|
||||
"BookmarkletHelp1": "",
|
||||
"BookmarkletHelp2": "",
|
||||
"BookmarkletHelp3": "",
|
||||
"BookmarkletImportSubtitle": "",
|
||||
"Books": "Böcker",
|
||||
"Calculator": "Räknare",
|
||||
@@ -188,6 +191,7 @@
|
||||
"Image": "Bild",
|
||||
"Import": "Importera",
|
||||
"Import Recipe": "Importera recept",
|
||||
"ImportIntoTandoor": "",
|
||||
"Import_Error": "Ett fel uppstod under din import. Expandera informationen längst ner på sidan för att se den.",
|
||||
"Import_Not_Yet_Supported": "Import stöds inte ännu",
|
||||
"Import_Result_Info": "{imported} av totalt {total} recept blev importerat",
|
||||
|
||||
@@ -39,6 +39,9 @@
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"Bookmarklet": "Yer İmi",
|
||||
"BookmarkletHelp1": "",
|
||||
"BookmarkletHelp2": "",
|
||||
"BookmarkletHelp3": "",
|
||||
"BookmarkletImportSubtitle": "",
|
||||
"Books": "Kitaplar",
|
||||
"Calculator": "Hesap Makinesi",
|
||||
@@ -187,6 +190,7 @@
|
||||
"Image": "Resim",
|
||||
"Import": "İçeriye Aktar",
|
||||
"Import Recipe": "Tarif İçe Aktar",
|
||||
"ImportIntoTandoor": "",
|
||||
"Import_Error": "İçeri aktarma sırasında bir hata oluştu. Görüntülemek için lütfen sayfanın altındaki Ayrıntıları genişletin.",
|
||||
"Import_Not_Yet_Supported": "İçe aktarma henüz desteklenmiyor",
|
||||
"Import_Result_Info": "{total} tariften {imported} tanesi içe aktarıldı",
|
||||
|
||||
@@ -35,6 +35,9 @@
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"Bookmarklet": "",
|
||||
"BookmarkletHelp1": "",
|
||||
"BookmarkletHelp2": "",
|
||||
"BookmarkletHelp3": "",
|
||||
"BookmarkletImportSubtitle": "",
|
||||
"Books": "Книжки",
|
||||
"Calories": "Калорії",
|
||||
@@ -149,6 +152,7 @@
|
||||
"IgnoredFood": "{food} ігнорується в покупках.",
|
||||
"Image": "Зображення",
|
||||
"Import": "Імпорт",
|
||||
"ImportIntoTandoor": "",
|
||||
"Import_Error": "",
|
||||
"Import_Not_Yet_Supported": "",
|
||||
"Import_Result_Info": "",
|
||||
|
||||
@@ -39,6 +39,9 @@
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"Bookmarklet": "书签",
|
||||
"BookmarkletHelp1": "",
|
||||
"BookmarkletHelp2": "",
|
||||
"BookmarkletHelp3": "",
|
||||
"BookmarkletImportSubtitle": "",
|
||||
"Books": "书籍",
|
||||
"Calories": "卡路里",
|
||||
@@ -183,6 +186,7 @@
|
||||
"Image": "图片",
|
||||
"Import": "导入",
|
||||
"Import Recipe": "导入食谱",
|
||||
"ImportIntoTandoor": "",
|
||||
"Import_Error": "导入时发生错误。 请跳转至页面底部的详细信息进行查看。",
|
||||
"Import_Not_Yet_Supported": "导入尚未支持",
|
||||
"Import_Result_Info": "导入 {imported} 个,共 {total} 个食谱已导入",
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
"BaseUnit": "",
|
||||
"BaseUnitHelp": "",
|
||||
"Book": "",
|
||||
"BookmarkletHelp1": "",
|
||||
"BookmarkletHelp2": "",
|
||||
"BookmarkletHelp3": "",
|
||||
"BookmarkletImportSubtitle": "",
|
||||
"Books": "",
|
||||
"Calories": "",
|
||||
@@ -70,6 +73,7 @@
|
||||
"History": "",
|
||||
"HostedFreeVersion": "",
|
||||
"Import": "",
|
||||
"ImportIntoTandoor": "",
|
||||
"Import_finished": "匯入完成",
|
||||
"Information": "",
|
||||
"Ingredient": "",
|
||||
|
||||
@@ -33,6 +33,10 @@
|
||||
<v-stepper-item :title="$t('Import')" value="import_log" icon=" "></v-stepper-item>
|
||||
</template>
|
||||
|
||||
<template v-if="importType == 'bookmarklet'">
|
||||
<v-stepper-item :title="$t('Bookmarklet')" value="bookmarklet" icon=" "></v-stepper-item>
|
||||
</template>
|
||||
|
||||
</v-stepper-header>
|
||||
|
||||
<v-stepper-window>
|
||||
@@ -90,6 +94,7 @@
|
||||
<template #next>
|
||||
<v-btn @click="stepper = 'url'" v-if="['url','ai'].includes(importType)">{{ $t('Next') }}</v-btn>
|
||||
<v-btn @click="stepper = 'app'" v-if="importType == 'app'">{{ $t('Next') }}</v-btn>
|
||||
<v-btn @click="stepper = 'bookmarklet'" v-if="importType == 'bookmarklet'">{{ $t('Next') }}</v-btn>
|
||||
</template>
|
||||
</v-stepper-actions>
|
||||
</v-stepper-window-item>
|
||||
@@ -97,6 +102,7 @@
|
||||
<!-- ------------ -->
|
||||
<!-- ULR/AI Items -->
|
||||
<!-- ------------ -->
|
||||
|
||||
<v-stepper-window-item value="url">
|
||||
<v-text-field :label="$t('Website') + ' (https://...)'" v-model="importUrl" v-if="importType == 'url'" :loading="loading"></v-text-field>
|
||||
|
||||
@@ -107,7 +113,7 @@
|
||||
<v-btn @click="stepper = 'type'">{{ $t('Back') }}</v-btn>
|
||||
</template>
|
||||
<template #next>
|
||||
<v-btn @click="loadRecipeFromUrl()" v-if="importType == 'url'" :disabled="importUrl == ''" :loading="loading">{{ $t('Load') }}</v-btn>
|
||||
<v-btn @click="loadRecipeFromUrl({url: importUrl})" v-if="importType == 'url'" :disabled="importUrl == ''" :loading="loading">{{ $t('Load') }}</v-btn>
|
||||
<v-btn @click="uploadAndConvertImage()" v-if="importType == 'ai'" :disabled="image == null" :loading="loading">{{ $t('Load') }}</v-btn>
|
||||
</template>
|
||||
</v-stepper-actions>
|
||||
@@ -302,9 +308,11 @@
|
||||
</template>
|
||||
</v-stepper-actions>
|
||||
</v-stepper-window-item>
|
||||
<!-- ------------ -->
|
||||
|
||||
<!-- ---------------- -->
|
||||
<!-- App Import Items -->
|
||||
<!-- ------------ -->
|
||||
<!-- ---------------- -->
|
||||
|
||||
<v-stepper-window-item value="app">
|
||||
|
||||
<v-row>
|
||||
@@ -328,23 +336,55 @@
|
||||
</v-stepper-actions>
|
||||
</v-stepper-window-item>
|
||||
<v-stepper-window-item value="file">
|
||||
<v-file-upload v-model="appImportFile"></v-file-upload>
|
||||
<v-file-upload v-model="appImportFiles" multiple></v-file-upload>
|
||||
|
||||
<v-card variant="outlined" elevation="1" density="compact" :title="$t('Duplicate')" :subtitle="$t('import_duplicates')" class="mt-2">
|
||||
<template #prepend>
|
||||
<v-checkbox v-model="appImportDuplicates"></v-checkbox>
|
||||
</template>
|
||||
</v-card>
|
||||
|
||||
<v-stepper-actions>
|
||||
<template #prev>
|
||||
<v-btn @click="stepper = 'app'">{{ $t('Back') }}</v-btn>
|
||||
</template>
|
||||
<template #next>
|
||||
<v-btn @click="appImport()" :disabled="appImportFile == null" :loading="fileApiLoading">{{ $t('Import') }}</v-btn>
|
||||
<v-btn @click="appImport()" :disabled="appImportFiles.length == 0" :loading="fileApiLoading">{{ $t('Import') }}</v-btn>
|
||||
</template>
|
||||
</v-stepper-actions>
|
||||
</v-stepper-window-item>
|
||||
<v-stepper-window-item value="import_log">
|
||||
|
||||
<import-log-viewer :import-log="appImportLog" v-if="appImportLog"></import-log-viewer>
|
||||
|
||||
<v-stepper-actions>
|
||||
<template #prev>
|
||||
<v-btn @click="stepper = 'app'">{{ $t('Back') }}</v-btn>
|
||||
<v-btn @click="stepper = 'file'">{{ $t('Back') }}</v-btn>
|
||||
</template>
|
||||
<template #next>
|
||||
<v-btn :to="{name: 'SearchPage', query: {keywords: appImportLog.keyword.id}}" v-if="appImportLog && !appImportLog.running"
|
||||
:disabled="false">{{ $t('View_Recipes') }}
|
||||
</v-btn>
|
||||
</template>
|
||||
</v-stepper-actions>
|
||||
</v-stepper-window-item>
|
||||
|
||||
<!-- ------------ -->
|
||||
<!-- Bookmarklet -->
|
||||
<!-- ------------ -->
|
||||
<v-stepper-window-item value="bookmarklet">
|
||||
{{$t('BookmarkletImportSubtitle')}}
|
||||
|
||||
<ol>
|
||||
<li>1. {{$t('BookmarkletHelp1')}}</li>
|
||||
<li> <v-btn :href="bookmarkletContent" color="primary">{{$t('ImportIntoTandoor')}}</v-btn></li>
|
||||
<li>2. {{$t('BookmarkletHelp2')}}</li>
|
||||
<li>3. {{$t('BookmarkletHelp3')}}</li>
|
||||
</ol>
|
||||
|
||||
<v-stepper-actions>
|
||||
<template #prev>
|
||||
<v-btn @click="stepper = 'type'">{{ $t('Back') }}</v-btn>
|
||||
</template>
|
||||
<template #next>
|
||||
|
||||
@@ -354,13 +394,8 @@
|
||||
|
||||
|
||||
</v-stepper-window>
|
||||
|
||||
|
||||
</template>
|
||||
|
||||
</v-stepper>
|
||||
|
||||
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-container>
|
||||
@@ -368,14 +403,13 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
||||
import {nextTick, onMounted, ref} from "vue";
|
||||
import {ApiApi, Keyword, RecipeFromSourceResponse, type SourceImportIngredient, SourceImportKeyword, SourceImportStep} from "@/openapi";
|
||||
import {computed, onMounted, ref} from "vue";
|
||||
import {AccessToken, ApiApi, ImportLog, type RecipeFromSource, RecipeFromSourceResponse, type SourceImportIngredient, SourceImportKeyword, SourceImportStep} from "@/openapi";
|
||||
import {ErrorMessageType, MessageType, useMessageStore} from "@/stores/MessageStore";
|
||||
import {useRouter} from "vue-router";
|
||||
import {useUserPreferenceStore} from "@/stores/UserPreferenceStore";
|
||||
import {VueDraggable} from "vue-draggable-plus";
|
||||
import VClosableCardTitle from "@/components/dialogs/VClosableCardTitle.vue";
|
||||
import KeywordsBar from "@/components/display/KeywordsBar.vue";
|
||||
import {VNumberInput} from 'vuetify/labs/VNumberInput'
|
||||
import {useFileApi} from "@/composables/useFileApi";
|
||||
import ModelSelect from "@/components/inputs/ModelSelect.vue";
|
||||
@@ -383,11 +417,28 @@ import {useDisplay} from "vuetify";
|
||||
import {useUrlSearchParams} from "@vueuse/core";
|
||||
import {INTEGRATIONS} from "@/utils/integration_utils";
|
||||
import {VFileUpload} from 'vuetify/labs/VFileUpload'
|
||||
import ImportLogViewer from "@/components/display/ImportLogViewer.vue";
|
||||
import {DateTime} from "luxon";
|
||||
import {useDjangoUrls} from "@/composables/useDjangoUrls";
|
||||
import bookmarkletJs from '@/assets/bookmarklet_v3?url'
|
||||
|
||||
const params = useUrlSearchParams('history', {})
|
||||
const {mobile} = useDisplay()
|
||||
const router = useRouter()
|
||||
const {updateRecipeImage, convertImageToRecipe, doAppImport, fileApiLoading} = useFileApi()
|
||||
const {getDjangoUrl} = useDjangoUrls()
|
||||
|
||||
const bookmarkletContent = computed(() => {
|
||||
return 'javascript:(function(){' +
|
||||
'if(window.bookmarkletTandoor!==undefined){' +
|
||||
'bookmarkletTandoor();' +
|
||||
'} else {' +
|
||||
`localStorage.setItem("importURL", "${getDjangoUrl('/api/bookmarklet-import/')}");` +
|
||||
`localStorage.setItem("redirectURL", "${getDjangoUrl('/recipe/import/')}");` +
|
||||
`localStorage.setItem("token", "${bookmarkletToken.value}");` +
|
||||
`document.body.appendChild(document.createElement("script")).src="${bookmarkletJs}?r="+Math.floor(Math.random()*999999999)}` +
|
||||
`})()`
|
||||
})
|
||||
|
||||
const importType = ref<'url' | 'ai' | 'app' | 'bookmarklet' | 'source'>("url")
|
||||
const importApp = ref('DEFAULT')
|
||||
@@ -396,33 +447,43 @@ const dialog = ref(false)
|
||||
const loading = ref(false)
|
||||
const importUrl = ref("")
|
||||
|
||||
const appImportFile = ref<null | File>(null)
|
||||
const appImportFiles = ref<File[]>([])
|
||||
const appImportDuplicates = ref(false)
|
||||
const appImportLog = ref<null | ImportLog>(null)
|
||||
const image = ref<null | File>(null)
|
||||
|
||||
const bookmarkletToken = ref("")
|
||||
|
||||
const importResponse = ref({} as RecipeFromSourceResponse)
|
||||
const keywordSelect = ref<null | SourceImportKeyword>(null)
|
||||
const editingIngredient = ref({} as SourceImportIngredient)
|
||||
|
||||
onMounted(() => {
|
||||
loadOrCreateBookmarkletToken()
|
||||
|
||||
// handle manifest share intend passing url to import page
|
||||
if (params.url && typeof params.url === "string") {
|
||||
importUrl.value = params.url
|
||||
loadRecipeFromUrl()
|
||||
loadRecipeFromUrl({url: importUrl.value})
|
||||
}
|
||||
if (params.text && typeof params.text === "string") {
|
||||
importUrl.value = params.text
|
||||
loadRecipeFromUrl()
|
||||
loadRecipeFromUrl({url: importUrl.value})
|
||||
}
|
||||
|
||||
if (params.bookmarklet_import && typeof params.bookmarklet_import === "string" && !isNaN(parseInt(params.bookmarklet_import))) {
|
||||
importType.value = 'url'
|
||||
loadRecipeFromUrl({bookmarklet: parseInt(params.bookmarklet_import)})
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* call server to load recipe from a given URl
|
||||
*/
|
||||
function loadRecipeFromUrl() {
|
||||
function loadRecipeFromUrl(recipeFromSourceRequest: RecipeFromSource) {
|
||||
let api = new ApiApi()
|
||||
loading.value = true
|
||||
api.apiRecipeFromSourceCreate({recipeFromSource: {url: importUrl.value}}).then(r => {
|
||||
api.apiRecipeFromSourceCreate({recipeFromSource: recipeFromSourceRequest}).then(r => {
|
||||
importResponse.value = r
|
||||
|
||||
if (importResponse.value.duplicates && importResponse.value.duplicates.length > 0) {
|
||||
@@ -451,8 +512,24 @@ function uploadAndConvertImage() {
|
||||
}
|
||||
|
||||
function appImport() {
|
||||
doAppImport(appImportFile.value, importApp.value, true).then(r => {
|
||||
doAppImport(appImportFiles.value, importApp.value, appImportDuplicates.value).then(r => {
|
||||
stepper.value = 'import_log'
|
||||
recLoadImportLog(r)
|
||||
})
|
||||
}
|
||||
|
||||
function recLoadImportLog(importLogId: number) {
|
||||
let api = new ApiApi()
|
||||
|
||||
api.apiImportLogRetrieve({id: importLogId}).then(r => {
|
||||
appImportLog.value = r
|
||||
if (r.running) {
|
||||
setTimeout(() => {
|
||||
recLoadImportLog(importLogId)
|
||||
}, 1000)
|
||||
}
|
||||
}).catch(err => {
|
||||
useMessageStore().addError(ErrorMessageType.FETCH_ERROR, err)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -639,6 +716,27 @@ function addStep() {
|
||||
importResponse.value.recipe?.steps.push({} as SourceImportStep)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* load or create an AccessToken with the bookmarklet scope for use in the bookmarklet code
|
||||
*/
|
||||
function loadOrCreateBookmarkletToken() {
|
||||
let api = new ApiApi()
|
||||
api.apiAccessTokenList().then(r => {
|
||||
r.forEach(token => {
|
||||
if (token.scope == 'bookmarklet') {
|
||||
bookmarkletToken.value = token.token
|
||||
}
|
||||
})
|
||||
|
||||
if (bookmarkletToken.value == '') {
|
||||
api.apiAccessTokenCreate({accessToken: {scope: 'bookmarklet', expires: DateTime.now().plus({year: 100}).toJSDate()} as AccessToken}).then(r => {
|
||||
bookmarkletToken.value = r.token
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
Reference in New Issue
Block a user