added support for external recipes to new frontend

This commit is contained in:
vabene1111
2025-06-04 20:35:35 +02:00
parent cd707d20a1
commit 63069dd716
56 changed files with 1428 additions and 75 deletions

View File

@@ -1094,6 +1094,19 @@ class RecipeImport(models.Model, PermissionModelMixin):
def __str__(self):
return self.name
def convert_to_recipe(self, user):
recipe = Recipe(
name=self.name,
file_path=self.file_path,
storage=self.storage,
file_uid=self.file_uid,
created_by=user,
space=self.space
)
recipe.save()
self.delete()
return recipe
class RecipeBook(ExportModelOperationsMixin('book'), models.Model, PermissionModelMixin):
name = models.CharField(max_length=128)

View File

@@ -31,7 +31,7 @@ class Dropbox(Provider):
except ValueError:
log_entry = SyncLog(status='ERROR', msg=str(r), sync=monitor)
log_entry.save()
return r
return log_entry
import_count = 0
# TODO check if has_more is set and import that as well
@@ -59,7 +59,7 @@ class Dropbox(Provider):
monitor.last_checked = datetime.now()
monitor.save()
return True
return log_entry
@staticmethod
def create_share_link(recipe):

View File

@@ -42,7 +42,7 @@ class Local(Provider):
monitor.last_checked = datetime.now()
monitor.save()
return True
return log_entry
@staticmethod
def get_file(recipe):

View File

@@ -66,7 +66,7 @@ class Nextcloud(Provider):
monitor.last_checked = datetime.now()
monitor.save()
return True
return log_entry
@staticmethod
def create_share_link(recipe):

View File

@@ -447,27 +447,6 @@ class UserPreferenceSerializer(WritableNestedModelSerializer):
read_only_fields = ('user',)
class StorageSerializer(SpacedModelSerializer):
def create(self, validated_data):
validated_data['created_by'] = self.context['request'].user
return super().create(validated_data)
class Meta:
model = Storage
fields = (
'id', 'name', 'method', 'username', 'password',
'token', 'created_by'
)
read_only_fields = ('created_by',)
extra_kwargs = {
'password': {'write_only': True},
'token': {'write_only': True},
}
class ConnectorConfigConfigSerializer(SpacedModelSerializer):
def create(self, validated_data):
@@ -489,7 +468,38 @@ class ConnectorConfigConfigSerializer(SpacedModelSerializer):
}
class SyncSerializer(SpacedModelSerializer):
class StorageSerializer(WritableNestedModelSerializer, SpacedModelSerializer):
def create(self, validated_data):
validated_data['created_by'] = self.context['request'].user
return super().create(validated_data)
class Meta:
model = Storage
fields = (
'id', 'name', 'method', 'username', 'password',
'token', 'url', 'path', 'created_by'
)
read_only_fields = ( 'id', 'created_by',)
extra_kwargs = {
'password': {'write_only': True},
'token': {'write_only': True},
}
class RecipeImportSerializer(WritableNestedModelSerializer, SpacedModelSerializer):
storage = StorageSerializer()
class Meta:
model = RecipeImport
fields = ('id', 'storage', 'name', 'file_uid', 'file_path', 'created_at')
class SyncSerializer(WritableNestedModelSerializer, SpacedModelSerializer):
storage = StorageSerializer()
class Meta:
model = Sync
fields = (
@@ -499,6 +509,8 @@ class SyncSerializer(SpacedModelSerializer):
class SyncLogSerializer(SpacedModelSerializer):
sync = SyncSerializer(read_only=True)
class Meta:
model = SyncLog
fields = ('id', 'sync', 'status', 'msg', 'created_at')
@@ -1710,6 +1722,7 @@ class ExportRequestSerializer(serializers.Serializer):
recipes = RecipeFlatSerializer(many=True, default=[])
custom_filter = CustomFilterSerializer(many=False, default=None, allow_null=True)
class ImportOpenDataSerializer(serializers.Serializer):
selected_version = serializers.CharField()
selected_datatypes = serializers.ListField(child=serializers.CharField())

View File

@@ -56,6 +56,7 @@ router.register(r'supermarket-category', api.SupermarketCategoryViewSet)
router.register(r'supermarket-category-relation', api.SupermarketCategoryRelationViewSet)
router.register(r'sync', api.SyncViewSet)
router.register(r'sync-log', api.SyncLogViewSet)
router.register(r'recipe-import', api.RecipeImportViewSet)
router.register(r'unit', api.UnitViewSet)
router.register(r'user-file', api.UserFileViewSet)
router.register(r'user', api.UserViewSet)

View File

@@ -85,7 +85,7 @@ from cookbook.models import (Automation, BookmarkletImport, ConnectorConfig, Coo
RecipeBookEntry, ShareLink, ShoppingListEntry,
ShoppingListRecipe, Space, Step, Storage, Supermarket, SupermarketCategory,
SupermarketCategoryRelation, Sync, SyncLog, Unit, UnitConversion,
UserFile, UserPreference, UserSpace, ViewLog
UserFile, UserPreference, UserSpace, ViewLog, RecipeImport
)
from cookbook.provider.dropbox import Dropbox
from cookbook.provider.local import Local
@@ -109,7 +109,8 @@ from cookbook.serializer import (AccessTokenSerializer, AutomationSerializer, Au
UnitConversionSerializer, UnitSerializer, UserFileSerializer, UserPreferenceSerializer,
UserSerializer, UserSpaceSerializer, ViewLogSerializer,
LocalizationSerializer, ServerSettingsSerializer, RecipeFromSourceResponseSerializer, ShoppingListEntryBulkCreateSerializer, FdcQuerySerializer,
AiImportSerializer, ImportOpenDataSerializer, ImportOpenDataMetaDataSerializer, ImportOpenDataResponseSerializer, ExportRequestSerializer
AiImportSerializer, ImportOpenDataSerializer, ImportOpenDataMetaDataSerializer, ImportOpenDataResponseSerializer, ExportRequestSerializer,
RecipeImportSerializer
)
from cookbook.version_info import TANDOOR_VERSION
from cookbook.views.import_export import get_integration
@@ -585,17 +586,7 @@ class StorageViewSet(LoggingMixin, viewsets.ModelViewSet):
queryset = Storage.objects
serializer_class = StorageSerializer
permission_classes = [CustomIsAdmin & CustomTokenHasReadWriteScope]
pagination_disabled = True
def get_queryset(self):
return self.queryset.filter(space=self.request.space)
class ConnectorConfigConfigViewSet(LoggingMixin, viewsets.ModelViewSet):
queryset = ConnectorConfig.objects
serializer_class = ConnectorConfigConfigSerializer
permission_classes = [CustomIsAdmin & CustomTokenHasReadWriteScope]
pagination_disabled = True
pagination_class = DefaultPagination
def get_queryset(self):
return self.queryset.filter(space=self.request.space)
@@ -610,6 +601,21 @@ class SyncViewSet(LoggingMixin, viewsets.ModelViewSet):
def get_queryset(self):
return self.queryset.filter(space=self.request.space)
@extend_schema(responses=SyncLogSerializer(many=False))
@decorators.action(detail=True, pagination_class=None, methods=['POST'], )
def perform_update(self, request, pk):
sync = get_object_or_404(Sync, pk=pk)
sync_log = None
if sync.storage.method == Storage.DROPBOX:
sync_log = Dropbox.import_all(sync)
if sync.storage.method == Storage.NEXTCLOUD:
sync_log = Nextcloud.import_all(sync)
if sync.storage.method == Storage.LOCAL:
sync_log = Local.import_all(sync)
return Response(SyncLogSerializer(sync_log, many=False, context={'request': self.request}).data)
class SyncLogViewSet(LoggingMixin, viewsets.ReadOnlyModelViewSet):
queryset = SyncLog.objects
@@ -621,6 +627,42 @@ class SyncLogViewSet(LoggingMixin, viewsets.ReadOnlyModelViewSet):
return self.queryset.filter(sync__space=self.request.space)
class RecipeImportViewSet(LoggingMixin, viewsets.ModelViewSet):
queryset = RecipeImport.objects
serializer_class = RecipeImportSerializer
permission_classes = [CustomIsAdmin & CustomTokenHasReadWriteScope]
pagination_class = DefaultPagination
def get_queryset(self):
return self.queryset.filter(space=self.request.space)
@extend_schema(responses=RecipeSerializer(many=False))
@decorators.action(detail=True, pagination_class=None, methods=['POST'], )
def import_recipe(self, request, pk):
new_recipe = get_object_or_404(RecipeImport, pk=pk, space=request.space)
recipe = new_recipe.convert_to_recipe(request.user)
return Response(RecipeSerializer(recipe, many=False, context={'request': self.request}).data)
@decorators.action(detail=False, pagination_class=None, methods=['POST'], )
def import_all(self, request):
imports = RecipeImport.objects.filter(space=request.space).all()
for new_recipe in imports:
new_recipe.convert_to_recipe(request.user)
return Response({'msg': 'ok'}, status=status.HTTP_200_OK)
class ConnectorConfigConfigViewSet(LoggingMixin, viewsets.ModelViewSet):
queryset = ConnectorConfig.objects
serializer_class = ConnectorConfigConfigSerializer
permission_classes = [CustomIsAdmin & CustomTokenHasReadWriteScope]
pagination_disabled = True
def get_queryset(self):
return self.queryset.filter(space=self.request.space)
class SupermarketViewSet(LoggingMixin, StandardFilterModelViewSet):
queryset = Supermarket.objects
serializer_class = SupermarketSerializer
@@ -1984,6 +2026,7 @@ class AppExportView(APIView):
return Response({'error': True, 'msg': serializer.errors}, status=status.HTTP_400_BAD_REQUEST)
class FdcSearchView(APIView):
permission_classes = [CustomIsUser & CustomTokenHasReadWriteScope]