diff --git a/client/src/components/ui/goBack.tsx b/client/src/components/ui/goBack.tsx new file mode 100644 index 00000000..4273aad5 --- /dev/null +++ b/client/src/components/ui/goBack.tsx @@ -0,0 +1,34 @@ +import Link from "next/link"; + +const ButtonGallery = () => { + return ( + + + + ); +}; + +export default ButtonGallery; diff --git a/client/src/components/ui/imageFrame.tsx b/client/src/components/ui/imageFrame.tsx new file mode 100644 index 00000000..6d66335c --- /dev/null +++ b/client/src/components/ui/imageFrame.tsx @@ -0,0 +1,30 @@ +import Image from "next/image"; +import React from "react"; + +interface CardProps { + imageSrc?: string; + imageAlt?: string; + children?: React.ReactNode; +} + +const Card = ({ imageSrc, imageAlt = "Artwork", children }: CardProps) => { + return ( +
+
+ {imageSrc ? ( + {imageAlt} + ) : ( + children || No Image + )} +
+
+ ); +}; + +export default Card; diff --git a/client/src/hooks/useArtworkData.ts b/client/src/hooks/useArtworkData.ts new file mode 100644 index 00000000..44d0136c --- /dev/null +++ b/client/src/hooks/useArtworkData.ts @@ -0,0 +1,49 @@ +import { Art } from "@/types/art"; + +export const generateMockArtworks = (count: number): Art[] => { + const artworks: Art[] = []; + for (let i = 1; i <= count; i++) { + artworks.push({ + id: i, + name: `Artwork ${i}`, + description: "Mock artwork description", + //source_game: "Mock Game", + path_to_media: "", + active: true, + contributors: [], + //created_at: new Date().toISOString(), + }); + } + return artworks; +}; + +export const generateMockArtwork = (id: string): Art => { + return { + id: Number(id), + name: "Mock Artwork Title", + description: + "Lorem ipsum dolor sit amet. Non numquam dicta nam autem dicta 33 error molestias et repellat consequatur eum iste expedita est dolorem libero et quas provident!", + //source_game: "Mock Game", + path_to_media: "", + active: true, + //created_at: new Date().toISOString(), + contributors: [ + { + id: 1, + art_id: Number(id), + member_name: "Contributor 1", + role: "user1", + discord_url: "https://discord.com", + instagram_url: "", + }, + { + id: 2, + art_id: Number(id), + member_name: "Contributor 2", + role: "user2", + discord_url: "", + instagram_url: "https://instagram.com", + }, + ], + }; +}; diff --git a/client/src/pages/artwork/[id].tsx b/client/src/pages/artwork/[id].tsx index 95adacb5..ac8ecc3a 100644 --- a/client/src/pages/artwork/[id].tsx +++ b/client/src/pages/artwork/[id].tsx @@ -1,8 +1,9 @@ import { GetServerSideProps } from "next"; import Image from "next/image"; -import Link from "next/link"; import { JSX } from "react"; +import ButtonGallery from "@/components/ui/goBack"; +import { generateMockArtwork } from "@/hooks/useArtworkData"; import api from "@/lib/api"; import { Art } from "@/types/art"; @@ -102,13 +103,13 @@ export default function ArtworkPage({ artwork }: ArtworkPageProps) {
- < Gallery +
- Artwork image + {artwork.path_to_media ? ( + Artwork image + ) : ( + // in case fail to load image or no image in db yet +
+
+ + + +
+
+ )}
= async ( context, ) => { const { id } = context.params as { id: string }; - const artResponse = await api.get(`game-dev/arts/${id}`); - const artwork = artResponse.data; - return { props: { artwork } }; + try { + const artResponse = await api.get(`game-dev/arts/${id}`); + const artwork = artResponse.data; + return { props: { artwork } }; + } catch { + // Return mock data when API fails or DB is empty + const mockArtwork = generateMockArtwork(id); + return { props: { artwork: mockArtwork } }; + } }; diff --git a/client/src/pages/artwork/index.tsx b/client/src/pages/artwork/index.tsx index 8a3586f5..e34fbddf 100644 --- a/client/src/pages/artwork/index.tsx +++ b/client/src/pages/artwork/index.tsx @@ -1,13 +1,15 @@ import { GetServerSideProps } from "next"; -import Image from "next/image"; import Link from "next/link"; +import { Button } from "@/components/ui/button"; +import Card from "@/components/ui/imageFrame"; +import { generateMockArtworks } from "@/hooks/useArtworkData"; import api from "@/lib/api"; import { Art } from "@/types/art"; import { PageResult } from "@/types/page-response"; interface ArtworksPageProps { - pages: PageResult; + artworks: PageResult; } const PLACEHOLDER_ICON = ( @@ -31,29 +33,22 @@ function renderArtworkCard(artwork: Art) { return ( -
-
- Artwork image -
-
+ {!artwork.path_to_media && PLACEHOLDER_ICON} + ); } -export default function ArtworksPage({ pages }: ArtworksPageProps) { +export default function ArtworksPage({ artworks }: ArtworksPageProps) { return (
-
-
- More about us → -
-
+ More about us → +
- {pages.results.map((artwork) => renderArtworkCard(artwork))} + {artworks.results.map((artwork) => renderArtworkCard(artwork))}
= async () => { - const res = await api.get>("game-dev/arts"); - const pages = res.data; - return { props: { pages } }; + try { + const res = await api.get>("game-dev/arts"); + return { props: { artworks: res.data } }; + } catch { + // return { + // props: { + // artworks: { + // count: 0, + // next: null as unknown as string, + // previous: null as unknown as string, + // results: [] as Art[], + // }, + // }, + // }; ==> use when successfully populate db + const mockArtworks = generateMockArtworks(12); + return { + props: { + artworks: { + count: mockArtworks.length, + next: "", + previous: "", + results: mockArtworks, + }, + }, + }; + } }; diff --git a/client/src/styles/globals.css b/client/src/styles/globals.css index 53eb51bc..43a74218 100644 --- a/client/src/styles/globals.css +++ b/client/src/styles/globals.css @@ -34,11 +34,11 @@ --radius: 0.5rem; - --dark-2: #090A19; - --neutral-1: #1B1F4C; - --light-1: #FFFFFF; - --light-2: #CED1FE; - --light-3: #9CA4FD; + --dark-2: #090a19; + --neutral-1: #1b1f4c; + --light-1: #ffffff; + --light-2: #ced1fe; + --light-3: #9ca4fd; } } @@ -68,4 +68,4 @@ } .border-light-2 { border-color: var(--light-2); -} \ No newline at end of file +} diff --git a/server/api/settings.py b/server/api/settings.py index 4664e69a..46902758 100644 --- a/server/api/settings.py +++ b/server/api/settings.py @@ -158,4 +158,4 @@ REST_FRAMEWORK = { 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', 'PAGE_SIZE': 100, -} \ No newline at end of file +} diff --git a/server/api/urls.py b/server/api/urls.py index c6a16187..073e0e7d 100644 --- a/server/api/urls.py +++ b/server/api/urls.py @@ -21,5 +21,5 @@ urlpatterns = [ path("admin/", admin.site.urls), path("api/healthcheck/", include("api.healthcheck.urls")), - path("api/game-dev/", include("game_dev.urls")), -] \ No newline at end of file + path("api/game-dev/", include("game_dev.urls")), +] diff --git a/server/game_dev/admin.py b/server/game_dev/admin.py index 2cfeab2e..b148cace 100644 --- a/server/game_dev/admin.py +++ b/server/game_dev/admin.py @@ -2,23 +2,8 @@ from .models import Member, Art, ArtContributor -@admin.register(Member) -class MemberAdmin(admin.ModelAdmin): - list_display = ['name', 'active', 'pronouns'] - list_filter = ['active'] - search_fields = ['name'] +admin.site.register(Member) +admin.site.register(Art) -@admin.register(Art) -class ArtAdmin(admin.ModelAdmin): - list_display = ['name', 'active'] - list_filter = ['active'] - search_fields = ['name'] - - -@admin.register(ArtContributor) -class ArtContributorAdmin(admin.ModelAdmin): - list_display = ['art', 'member', 'role'] - list_filter = ['role'] - search_fields = ['member__name', 'art__name'] - autocomplete_fields = ['art', 'member'] \ No newline at end of file +admin.site.register(ArtContributor) diff --git a/server/game_dev/models.py b/server/game_dev/models.py index ea132d6b..0735d3f3 100644 --- a/server/game_dev/models.py +++ b/server/game_dev/models.py @@ -22,14 +22,16 @@ class Art(models.Model): def __str__(self): return str(self.name) + class ArtContributor(models.Model): art = models.ForeignKey('Art', on_delete=models.CASCADE, related_name='contributors') member = models.ForeignKey('Member', on_delete=models.CASCADE, related_name='art_contributions') role = models.CharField(max_length=100) + class Meta: unique_together = ('art', 'member') verbose_name = 'Art Contributor' verbose_name_plural = 'Art Contributors' - + def __str__(self): return f"{self.member.name} - {self.art.name} ({self.role})" diff --git a/server/game_dev/serializers.py b/server/game_dev/serializers.py index 48901998..ae3a0d67 100644 --- a/server/game_dev/serializers.py +++ b/server/game_dev/serializers.py @@ -4,17 +4,20 @@ class ArtContributorSerializer(serializers.ModelSerializer): member_name = serializers.CharField(source='member.name', read_only=True) - + class Meta: model = ArtContributor fields = ['id', 'art', 'member', 'member_name', 'role'] + class ArtSerializer(serializers.ModelSerializer): - contributors = ArtContributorSerializer(many = True, read_only = True) + contributors = ArtContributorSerializer(many=True, read_only=True) + class Meta: model = Art fields = ['id', 'name', 'description', 'path_to_media', 'active', 'contributors'] + class MemberSerializer(serializers.ModelSerializer): class Meta: model = Member diff --git a/server/game_dev/urls.py b/server/game_dev/urls.py index b6f94c27..7fb8d68d 100644 --- a/server/game_dev/urls.py +++ b/server/game_dev/urls.py @@ -9,4 +9,4 @@ urlpatterns = [ path('', include(router.urls)), -] \ No newline at end of file +] diff --git a/server/game_dev/views.py b/server/game_dev/views.py index 86d0f0ad..78790797 100644 --- a/server/game_dev/views.py +++ b/server/game_dev/views.py @@ -8,12 +8,14 @@ class ArtContributorViewSet(viewsets.ModelViewSet): queryset = ArtContributor.objects.all() serializer_class = ArtContributorSerializer filter_backends = [DjangoFilterBackend] - filterset_fields=['art'] + filterset_fields = ['art'] + class ArtViewSet(viewsets.ModelViewSet): queryset = Art.objects.all() serializer_class = ArtSerializer + class MemberViewSet(viewsets.ModelViewSet): queryset = Member.objects.all() - serializer_class = MemberSerializer \ No newline at end of file + serializer_class = MemberSerializer diff --git a/server/poetry.lock b/server/poetry.lock index c6b7d5ff..bb17707c 100644 --- a/server/poetry.lock +++ b/server/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.2.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.4 and should not be changed by hand. [[package]] name = "asgiref" @@ -6,7 +6,6 @@ version = "3.8.1" description = "ASGI specs, helper code, and adapters" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "asgiref-3.8.1-py3-none-any.whl", hash = "sha256:3e1e3ecc849832fe52ccf2cb6686b7a55f82bb1d6aee72a58826471390335e47"}, {file = "asgiref-3.8.1.tar.gz", hash = "sha256:c343bd80a0bec947a9860adb4c432ffa7db769836c64238fc34bdc3fec84d590"}, @@ -21,7 +20,6 @@ version = "2.15.8" description = "An abstract syntax tree for Python with inference support." optional = false python-versions = ">=3.7.2" -groups = ["dev"] files = [ {file = "astroid-2.15.8-py3-none-any.whl", hash = "sha256:1aa149fc5c6589e3d0ece885b4491acd80af4f087baafa3fb5203b113e68cd3c"}, {file = "astroid-2.15.8.tar.gz", hash = "sha256:6c107453dffee9055899705de3c9ead36e74119cee151e5a9aaf7f0b0e020a6a"}, @@ -37,8 +35,6 @@ version = "0.4.6" description = "Cross-platform colored terminal text." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -groups = ["dev"] -markers = "sys_platform == \"win32\"" files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, @@ -46,18 +42,17 @@ files = [ [[package]] name = "django" -version = "5.1.14" +version = "5.2.9" description = "A high-level Python web framework that encourages rapid development and clean, pragmatic design." optional = false python-versions = ">=3.10" -groups = ["main"] files = [ - {file = "django-5.1.14-py3-none-any.whl", hash = "sha256:2a4b9c20404fd1bf50aaaa5542a19d860594cba1354f688f642feb271b91df27"}, - {file = "django-5.1.14.tar.gz", hash = "sha256:b98409fb31fdd6e8c3a6ba2eef3415cc5c0020057b43b21ba7af6eff5f014831"}, + {file = "django-5.2.9-py3-none-any.whl", hash = "sha256:3a4ea88a70370557ab1930b332fd2887a9f48654261cdffda663fef5976bb00a"}, + {file = "django-5.2.9.tar.gz", hash = "sha256:16b5ccfc5e8c27e6c0561af551d2ea32852d7352c67d452ae3e76b4f6b2ca495"}, ] [package.dependencies] -asgiref = ">=3.8.1,<4" +asgiref = ">=3.8.1" sqlparse = ">=0.3.1" tzdata = {version = "*", markers = "sys_platform == \"win32\""} @@ -71,7 +66,6 @@ version = "4.4.0" description = "django-cors-headers is a Django application for handling the server headers required for Cross-Origin Resource Sharing (CORS)." optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "django_cors_headers-4.4.0-py3-none-any.whl", hash = "sha256:5c6e3b7fe870876a1efdfeb4f433782c3524078fa0dc9e0195f6706ce7a242f6"}, {file = "django_cors_headers-4.4.0.tar.gz", hash = "sha256:92cf4633e22af67a230a1456cb1b7a02bb213d6536d2dcb2a4a24092ea9cebc2"}, @@ -87,7 +81,6 @@ version = "3.2.3" description = "Extensions for Django" optional = false python-versions = ">=3.6" -groups = ["main"] files = [ {file = "django-extensions-3.2.3.tar.gz", hash = "sha256:44d27919d04e23b3f40231c4ab7af4e61ce832ef46d610cc650d53e68328410a"}, {file = "django_extensions-3.2.3-py3-none-any.whl", hash = "sha256:9600b7562f79a92cbf1fde6403c04fee314608fefbb595502e34383ae8203401"}, @@ -96,13 +89,29 @@ files = [ [package.dependencies] Django = ">=3.2" +[[package]] +name = "django-filter" +version = "25.2" +description = "Django-filter is a reusable Django application for allowing users to filter querysets dynamically." +optional = false +python-versions = ">=3.10" +files = [ + {file = "django_filter-25.2-py3-none-any.whl", hash = "sha256:9c0f8609057309bba611062fe1b720b4a873652541192d232dd28970383633e3"}, + {file = "django_filter-25.2.tar.gz", hash = "sha256:760e984a931f4468d096f5541787efb8998c61217b73006163bf2f9523fe8f23"}, +] + +[package.dependencies] +Django = ">=5.2" + +[package.extras] +drf = ["djangorestframework"] + [[package]] name = "djangorestframework" version = "3.15.2" description = "Web APIs for Django, made easy." optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "djangorestframework-3.15.2-py3-none-any.whl", hash = "sha256:2b8871b062ba1aefc2de01f773875441a961fefbf79f5eed1e32b2f096944b20"}, {file = "djangorestframework-3.15.2.tar.gz", hash = "sha256:36fe88cd2d6c6bec23dca9804bab2ba5517a8bb9d8f47ebc68981b56840107ad"}, @@ -117,7 +126,6 @@ version = "6.1.0" description = "the modular source code checker: pep8 pyflakes and co" optional = false python-versions = ">=3.8.1" -groups = ["dev"] files = [ {file = "flake8-6.1.0-py2.py3-none-any.whl", hash = "sha256:ffdfce58ea94c6580c77888a86506937f9a1a227dfcd15f245d694ae20a6b6e5"}, {file = "flake8-6.1.0.tar.gz", hash = "sha256:d5b3857f07c030bdb5bf41c7f53799571d75c4491748a3adcd47de929e34cd23"}, @@ -134,7 +142,6 @@ version = "1.4" description = "Plugin to catch bad style specific to Django Projects." optional = false python-versions = ">=3.7.2,<4.0.0" -groups = ["dev"] files = [ {file = "flake8_django-1.4.tar.gz", hash = "sha256:4debba883084191568e3187416d1d6bdd4abd826da988f197a3c36572e9f30de"}, ] @@ -149,7 +156,6 @@ version = "1.5.1" description = "Let your Python tests travel through time" optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "freezegun-1.5.1-py3-none-any.whl", hash = "sha256:bf111d7138a8abe55ab48a71755673dbaa4ab87f4cff5634a4442dfec34c15f1"}, {file = "freezegun-1.5.1.tar.gz", hash = "sha256:b29dedfcda6d5e8e083ce71b2b542753ad48cfec44037b3fc79702e2980a89e9"}, @@ -164,7 +170,6 @@ version = "23.0.0" description = "WSGI HTTP Server for UNIX" optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "gunicorn-23.0.0-py3-none-any.whl", hash = "sha256:ec400d38950de4dfd418cff8328b2c8faed0edb0d517d3394e457c317908ca4d"}, {file = "gunicorn-23.0.0.tar.gz", hash = "sha256:f014447a0101dc57e294f6c18ca6b40227a4c90e9bdb586042628030cba004ec"}, @@ -186,7 +191,6 @@ version = "2.0.0" description = "brain-dead simple config-ini parsing" optional = false python-versions = ">=3.7" -groups = ["dev"] files = [ {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, @@ -198,7 +202,6 @@ version = "1.10.0" description = "A fast and thorough lazy object proxy." optional = false python-versions = ">=3.8" -groups = ["dev"] files = [ {file = "lazy-object-proxy-1.10.0.tar.gz", hash = "sha256:78247b6d45f43a52ef35c25b5581459e85117225408a4128a3daf8bf9648ac69"}, {file = "lazy_object_proxy-1.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:855e068b0358ab916454464a884779c7ffa312b8925c6f7401e952dcf3b89977"}, @@ -245,7 +248,6 @@ version = "0.7.0" description = "McCabe checker, plugin for flake8" optional = false python-versions = ">=3.6" -groups = ["dev"] files = [ {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, @@ -257,7 +259,6 @@ version = "24.1" description = "Core utilities for Python packages" optional = false python-versions = ">=3.8" -groups = ["main", "dev"] files = [ {file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"}, {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"}, @@ -269,7 +270,6 @@ version = "11.3.0" description = "Python Imaging Library (Fork)" optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "pillow-11.3.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:1b9c17fd4ace828b3003dfd1e30bff24863e0eb59b535e8f80194d9cc7ecf860"}, {file = "pillow-11.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:65dc69160114cdd0ca0f35cb434633c75e8e7fad4cf855177a05bf38678f73ad"}, @@ -385,7 +385,7 @@ fpx = ["olefile"] mic = ["olefile"] test-arrow = ["pyarrow"] tests = ["check-manifest", "coverage (>=7.4.2)", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "trove-classifiers (>=2024.10.12)"] -typing = ["typing-extensions ; python_version < \"3.10\""] +typing = ["typing-extensions"] xmp = ["defusedxml"] [[package]] @@ -394,7 +394,6 @@ version = "1.5.0" description = "plugin and hook calling mechanisms for python" optional = false python-versions = ">=3.8" -groups = ["dev"] files = [ {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, @@ -410,7 +409,6 @@ version = "2.11.1" description = "Python style guide checker" optional = false python-versions = ">=3.8" -groups = ["dev"] files = [ {file = "pycodestyle-2.11.1-py2.py3-none-any.whl", hash = "sha256:44fe31000b2d866f2e41841b18528a505fbd7fef9017b04eff4e2648a0fadc67"}, {file = "pycodestyle-2.11.1.tar.gz", hash = "sha256:41ba0e7afc9752dfb53ced5489e89f8186be00e599e712660695b7a75ff2663f"}, @@ -422,7 +420,6 @@ version = "3.1.0" description = "passive checker of Python programs" optional = false python-versions = ">=3.8" -groups = ["dev"] files = [ {file = "pyflakes-3.1.0-py2.py3-none-any.whl", hash = "sha256:4132f6d49cb4dae6819e5379898f2b8cce3c5f23994194c24b77d5da2e36f774"}, {file = "pyflakes-3.1.0.tar.gz", hash = "sha256:a0aae034c444db0071aa077972ba4768d40c830d9539fd45bf4cd3f8f6992efc"}, @@ -434,7 +431,6 @@ version = "8.3.2" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.8" -groups = ["dev"] files = [ {file = "pytest-8.3.2-py3-none-any.whl", hash = "sha256:4ba08f9ae7dcf84ded419494d229b48d0903ea6407b030eaec46df5e6a73bba5"}, {file = "pytest-8.3.2.tar.gz", hash = "sha256:c132345d12ce551242c87269de812483f5bcc87cdbb4722e48487ba194f9fdce"}, @@ -455,7 +451,6 @@ version = "2.9.0.post0" description = "Extensions to the standard Python datetime module" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -groups = ["main"] files = [ {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, @@ -470,7 +465,6 @@ version = "1.0.1" description = "Read key-value pairs from a .env file and set them as environment variables" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca"}, {file = "python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a"}, @@ -485,7 +479,6 @@ version = "1.16.0" description = "Python 2 and 3 compatibility utilities" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" -groups = ["main"] files = [ {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, @@ -497,7 +490,6 @@ version = "0.5.1" description = "A non-validating SQL parser." optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "sqlparse-0.5.1-py3-none-any.whl", hash = "sha256:773dcbf9a5ab44a090f3441e2180efe2560220203dc2f8c0b0fa141e18b505e4"}, {file = "sqlparse-0.5.1.tar.gz", hash = "sha256:bb6b4df465655ef332548e24f08e205afc81b9ab86cb1c45657a7ff173a3a00e"}, @@ -513,8 +505,6 @@ version = "2024.1" description = "Provider of IANA time zone data" optional = false python-versions = ">=2" -groups = ["main"] -markers = "sys_platform == \"win32\"" files = [ {file = "tzdata-2024.1-py2.py3-none-any.whl", hash = "sha256:9068bc196136463f5245e51efda838afa15aaeca9903f49050dfa2679db4d252"}, {file = "tzdata-2024.1.tar.gz", hash = "sha256:2674120f8d891909751c38abcdfd386ac0a5a1127954fbc332af6b5ceae07efd"}, @@ -526,7 +516,6 @@ version = "1.16.0" description = "Module for decorators, wrappers and monkey patching." optional = false python-versions = ">=3.6" -groups = ["dev"] files = [ {file = "wrapt-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ffa565331890b90056c01db69c0fe634a776f8019c143a5ae265f9c6bc4bd6d4"}, {file = "wrapt-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e4fdb9275308292e880dcbeb12546df7f3e0f96c6b41197e0cf37d2826359020"}, @@ -601,6 +590,6 @@ files = [ ] [metadata] -lock-version = "2.1" +lock-version = "2.0" python-versions = "^3.12" -content-hash = "f804c2f3998772b91e34ad214e5fcafe900bec97675f73046d3bcc79aba0f7db" +content-hash = "c5308f28a61ca954f8c322f9d9c4ae9412b82c10eb7a262c8ee438554aeed16f" diff --git a/server/pyproject.toml b/server/pyproject.toml index 5ec547cb..dd0e67ee 100644 --- a/server/pyproject.toml +++ b/server/pyproject.toml @@ -16,6 +16,7 @@ gunicorn = "^23.0.0" python-dotenv = "^1.0.1" django-extensions = "^3.2.3" pillow = "^11.3.0" +django-filter = "^25.2" [tool.poetry.group.dev.dependencies]