[MOBIL-382] chore: add Unsplash images and project cover APIs (#1496)

* fix: implemented mobile unsplash project covers

* fix: updated error handle

* fix: project covers
This commit is contained in:
guru_sainath
2024-10-15 14:47:32 +05:30
committed by GitHub
parent 6a1a085f3d
commit 406f4b4efd
5 changed files with 231 additions and 0 deletions

View File

@@ -0,0 +1,2 @@
from .unsplash import UnsplashImagesQuery
from .project_covers import ProjectCoversQuery

View File

@@ -0,0 +1,57 @@
# Third-Party Imports
import strawberry
# Python Standard Library Imports
import boto3
from django.conf import settings
# Strawberry Imports
from strawberry.types import Info
from strawberry.permission import PermissionExtension
# Module Imports
from plane.graphql.permissions.workspace import WorkspaceBasePermission
from plane.graphql.types.external import ProjectCovers
@strawberry.type
class ProjectCoversQuery:
@strawberry.field(
extensions=[
PermissionExtension(permissions=[WorkspaceBasePermission()])
]
)
async def project_covers(
self,
slug: str,
info: Info,
) -> ProjectCovers:
project_cover_files = []
if settings.USE_MINIO:
s3 = boto3.client(
"s3",
endpoint_url=settings.AWS_S3_ENDPOINT_URL,
aws_access_key_id=settings.AWS_ACCESS_KEY_ID,
aws_secret_access_key=settings.AWS_SECRET_ACCESS_KEY,
)
else:
s3 = boto3.client(
"s3",
aws_access_key_id=settings.AWS_ACCESS_KEY_ID,
aws_secret_access_key=settings.AWS_SECRET_ACCESS_KEY,
)
params = {
"Bucket": settings.AWS_STORAGE_BUCKET_NAME,
"Prefix": "static/project-cover/",
}
response = s3.list_objects_v2(**params)
if "Contents" in response:
for content in response["Contents"]:
if not content["Key"].endswith("/"):
project_cover_files.append(
f"https://{settings.AWS_STORAGE_BUCKET_NAME}.s3.{settings.AWS_REGION}.amazonaws.com/{content['Key']}"
)
return ProjectCovers(urls=project_cover_files)

View File

@@ -0,0 +1,129 @@
# Third-Party Imports
import strawberry
import requests
import os
# Python Standard Library Imports
from asgiref.sync import sync_to_async
# Strawberry Imports
from strawberry.types import Info
from strawberry.permission import PermissionExtension
# Django Imports
from typing import Optional
from django.conf import settings
# Module Imports
from plane.graphql.permissions.workspace import WorkspaceBasePermission
from plane.graphql.types.external import UnsplashImagesInfo, UnsplashImages
from plane.license.models import InstanceConfiguration
from plane.license.utils.encryption import decrypt_data
@sync_to_async
def get_instance_configuration():
return list(
InstanceConfiguration.objects.values("key", "value", "is_encrypted")
)
async def get_configuration_value(keys):
environment_list = []
if settings.SKIP_ENV_VAR:
# Get the configurations
instance_configuration = await get_instance_configuration()
for key in keys:
for item in instance_configuration:
if key.get("key") == item.get("key"):
if item.get("is_encrypted", False):
environment_list.append(
await sync_to_async(
decrypt_data(item.get("value"))
)
)
else:
environment_list.append(item.get("value"))
break
else:
environment_list.append(key.get("default"))
else:
# Get the configuration from os
for key in keys:
environment_list.append(
os.environ.get(key.get("key"), key.get("default"))
)
return tuple(environment_list)
@sync_to_async
def unsplash_request(url, headers):
return requests.get(url, headers=headers)
@strawberry.type
class UnsplashImagesQuery:
@strawberry.field(
extensions=[
PermissionExtension(permissions=[WorkspaceBasePermission()])
]
)
async def unsplash_images(
self,
slug: str,
info: Info,
page: Optional[int] = 1,
per_page: Optional[int] = 20,
query: Optional[str] = None,
) -> UnsplashImages:
(UNSPLASH_ACCESS_KEY,) = await get_configuration_value(
[
{
"key": "UNSPLASH_ACCESS_KEY",
"default": os.environ.get("UNSPLASH_ACCESS_KEY"),
}
]
)
# Check unsplash access key
if not UNSPLASH_ACCESS_KEY:
return UnsplashImages(total=None, total_pages=None, urls=[])
# construct the unsplash url and headers
unsplash_url = (
f"https://api.unsplash.com/search/photos/?client_id={UNSPLASH_ACCESS_KEY}&query={query}&page=${page}&per_page={per_page}"
if query
else f"https://api.unsplash.com/photos/?client_id={UNSPLASH_ACCESS_KEY}&page={page}&per_page={per_page}"
)
unsplash_headers = {"Content-Type": "application/json"}
# make a request to unsplash api
unsplash_response = await unsplash_request(
unsplash_url, unsplash_headers
)
unsplash_response_data = unsplash_response.json()
total = None
total_pages = None
if query is not None:
total = unsplash_response_data.get("total")
total_pages = unsplash_response_data.get("total_pages")
unsplash_response_data = unsplash_response_data.get("results")
unsplash_data = list()
for data in unsplash_response_data:
unsplash_data.append(
UnsplashImagesInfo(
raw=data.get("urls").get("raw"),
full=data.get("urls").get("full"),
regular=data.get("urls").get("regular"),
small=data.get("urls").get("small"),
thumb=data.get("urls").get("thumb"),
small_s3=data.get("urls").get("small_s3"),
)
)
return UnsplashImages(
total=total, total_pages=total_pages, urls=unsplash_data
)

View File

@@ -47,6 +47,7 @@ from .queries.issues import (
SubIssuesQuery,
)
from .queries.dashboard import userInformationQuery
from .queries.external import UnsplashImagesQuery, ProjectCoversQuery
# mutations
from .mutations.workspace import WorkspaceMutation, WorkspaceInviteMutation
@@ -127,6 +128,8 @@ class Query(
IssueRelationQuery,
IssuesSearchQuery,
userInformationQuery,
UnsplashImagesQuery,
ProjectCoversQuery,
):
pass

View File

@@ -0,0 +1,40 @@
# Python imports
from typing import Optional
# Strawberry imports
import strawberry
@strawberry.type
class ProjectCovers:
urls: list[str]
@strawberry.type
class UnsplashPaginatorInfo:
prev_cursor: Optional[int]
cursor: str
next_cursor: Optional[int]
prev_page_results: bool
next_page_results: bool
count: int
total_count: int
@strawberry.type
# unsplash images info
class UnsplashImagesInfo:
raw: str
full: str
regular: str
small: str
thumb: str
small_s3: str
@strawberry.type
# unsplash images
class UnsplashImages:
total: Optional[int]
total_pages: Optional[int]
urls: list[UnsplashImagesInfo]